From 8e377d0d570b750146d3b8feb7d2fd956cf66555 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 8 Nov 2016 22:23:57 +0100 Subject: [PATCH 0001/1892] updated some docs to mention cairocffi and that it is preferred over pycairo --- igraph/drawing/__init__.py | 17 ++++++++++------- setup.py | 8 +++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/igraph/drawing/__init__.py b/igraph/drawing/__init__.py index 17f9b9b5c..1345cd5ad 100644 --- a/igraph/drawing/__init__.py +++ b/igraph/drawing/__init__.py @@ -1,15 +1,18 @@ """ Drawing and plotting routines for IGraph. -Plotting is dependent on the C{pycairo} library which provides Python bindings -to the popular U{Cairo library}. This means that -if you don't have U{pycairo} installed, -you won't be able to use the plotting capabilities. However, you can still use -L{Graph.write_svg} to save the graph to an SVG file and view it from +Plotting is dependent on the C{pycairo} or C{cairocffi} libraries that provide +Python bindings to the popular U{Cairo library}. +This means that if you don't have U{pycairo} +or U{cairocffi} installed, you won't be able +to use the plotting capabilities. However, you can still use L{Graph.write_svg} +to save the graph to an SVG file and view it from U{Mozilla Firefox} (free) or edit it in U{Inkscape} (free), U{Skencil} -(formerly known as Sketch, also free) or Adobe Illustrator (not free, therefore -I'm not linking to it :)). +(formerly known as Sketch, also free) or Adobe Illustrator. + +Whenever the documentation refers to the C{pycairo} library, you can safely +replace it with C{cairocffi} as the two are API-compatible. """ from __future__ import with_statement diff --git a/setup.py b/setup.py index eba742649..698e3391f 100644 --- a/setup.py +++ b/setup.py @@ -861,9 +861,11 @@ def use_educated_guess(self): Graph plotting functionality is provided by the Cairo library, so make sure you install the Python bindings of Cairo if you want to generate -publication-quality graph plots. - -See the `Cairo homepage `_ for details. +publication-quality graph plots. You can try either `pycairo +`_ or `cairocffi `_, +``cairocffi`` is recommended, in particular if you are on Python 3.x because +there were bug reports affecting igraph graph plots in Jupyter notebooks +when using ``pycairo`` (but not with ``cairocffi``). From release 0.5, the C core of the igraph library is **not** included in the Python distribution - you must compile and install the C core From d4c7978cff867631d32d2955ec37b7087294ea5c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 9 Nov 2016 11:55:35 +0100 Subject: [PATCH 0002/1892] fixed Graph.is_{minimal_}separator() tests --- igraph/test/separators.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/igraph/test/separators.py b/igraph/test/separators.py index 62094f2b4..caabc54c0 100644 --- a/igraph/test/separators.py +++ b/igraph/test/separators.py @@ -20,8 +20,9 @@ def testIsSeparator(self): g = Graph.Lattice([8, 4], circular=True) self.assertFalse(g.is_separator([3, 11, 19, 27])) self.assertFalse(g.is_separator([29, 20, 11, 2])) + self.assertFalse(g.is_separator(range(32))) - self.assertRaises(InternalError, g.is_separator, range(32)) + self.assertRaises(InternalError, g.is_separator, range(33)) def testIsMinimalSeparator(self): g = Graph.Lattice([8, 4], circular=False) @@ -29,8 +30,9 @@ def testIsMinimalSeparator(self): self.assertFalse(g.is_minimal_separator([3, 11, 19, 27, 28])) self.assertFalse(g.is_minimal_separator([16, 25, 17])) self.assertTrue(g.is_minimal_separator([16, 25])) + self.assertFalse(g.is_minimal_separator(range(32))) - self.assertRaises(InternalError, g.is_minimal_separator, range(32)) + self.assertRaises(InternalError, g.is_minimal_separator, range(33)) def testAllMinimalSTSeparators(self): g = Graph.Famous("petersen") @@ -61,7 +63,7 @@ def suite(): def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + if __name__ == "__main__": test() From db0e2f17c6368eba34b1c2c39c7a2a95f05ec6f9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Dec 2016 16:36:19 +0100 Subject: [PATCH 0003/1892] fixed memory leak in Graph.maxflow(), closes #104 --- src/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphobject.c b/src/graphobject.c index 64de23751..72584fefd 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -9877,7 +9877,7 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, if (partition_o == NULL) return NULL; - return Py_BuildValue("dOOO", (double)result, flow_o, cut_o, partition_o); + return Py_BuildValue("dNNN", (double)result, flow_o, cut_o, partition_o); } /********************************************************************** From 2740169866f8fbe627f73cdd870eb90f43ec5ef8 Mon Sep 17 00:00:00 2001 From: Sandeep Murthy Date: Mon, 23 Jan 2017 02:23:28 +0000 Subject: [PATCH 0004/1892] Added .gitattributes to ensure correct language tagging of repo (as Python) --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..c7158f857 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.c linguist-language=Python From 2917c0b23799229f5bcac40d65ebe114e214abf7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 23 Jan 2017 09:17:45 +0100 Subject: [PATCH 0005/1892] temporarily ignoring Nexus-related doctests until we decide what will happen to nexus.igraph.org --- test/doctests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/doctests.py b/test/doctests.py index 031a19655..f260ab7b6 100755 --- a/test/doctests.py +++ b/test/doctests.py @@ -11,7 +11,7 @@ def run_doctests(): import igraph num_failed = 0 modules = [igraph, igraph.clustering, igraph.cut, igraph.datatypes, - igraph.drawing.utils, igraph.formula, igraph.remote.nexus, + igraph.drawing.utils, igraph.formula, igraph.statistics, igraph.utils] for module in modules: num_failed += doctest.testmod(module)[0] From ccde3b3b353f11cc960a228215e8059a37d42418 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Feb 2017 10:42:40 +0100 Subject: [PATCH 0006/1892] fixed handling of font size in Graph.write_svg(); closes #114 --- igraph/__init__.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index c21911c91..566204560 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -2132,8 +2132,22 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ # flash up an unneccesary Tk window in some cases import tkFont import Tkinter as tk - # This allows us to dynamically size the width of the nodes - font = tkFont.Font(root=tk.Tk(), font=("Sans", font_size, tkFont.NORMAL)) + + # This allows us to dynamically size the width of the nodes. + # Unfortunately this works only with font sizes specified in pixels. + if font_size.endswith("px"): + font_size_in_pixels = int(font_size[:-2]) + else: + try: + font_size_in_pixels = int(font_size) + except: + raise ValueError("font sizes must be specified in pixels " + "when any of the nodes has shape=3 (i.e. " + "node size determined by text size)") + tk_window = tk.Tk() + font = tkFont.Font(root=tk_window, font=("Sans", font_size_in_pixels, tkFont.NORMAL)) + else: + tk_window = None for vidx in range(self.vcount()): print >> f, ' '.\ @@ -2161,7 +2175,7 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ print >> f, ' '.\ format(vertex_width / 2., vertex_height / 2., vertex_width, vertex_height, vidx, colors[vidx]) - print >> f, ' '.format(vertex_size / 2.,vidx, font_size) + print >> f, ' '.format(vertex_size / 2.,vidx, font_size) print >> f, '{2}'.format(vertex_size / 2.,vidx, str(labels[vidx])) print >> f, ' ' @@ -2171,6 +2185,8 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ if our_file: f.close() + if tk_window: + tk_window.destroy() @classmethod From ffa712b438be38325ce5fd6e1010bb54bf4b8f2c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Feb 2017 11:50:21 +0100 Subject: [PATCH 0007/1892] GephiGraphStreamer is now encoding-aware, fixes issue on Python 3.x; closes #115 --- igraph/remote/gephi.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/igraph/remote/gephi.py b/igraph/remote/gephi.py index 61a7617cd..adb362a60 100644 --- a/igraph/remote/gephi.py +++ b/igraph/remote/gephi.py @@ -35,15 +35,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ class GephiConnection(object): """Object that represents a connection to a Gephi master server.""" - - def __init__(self, url=None, host="127.0.0.1", port=8080, workspace=0): + + def __init__(self, url=None, host="127.0.0.1", port=8080, workspace=1): """Constructs a connection to a Gephi master server. The connection object can be constructed either by specifying the `url` @@ -81,7 +81,7 @@ def close(self): def flush(self): """Flushes all the pending operations to the Gephi master server in a single request.""" - data = "".join(self._pending_operations) + data = b"".join(self._pending_operations) self._pending_operations = [] conn = urllib2.urlopen(self._update_url, data=data) return conn.read() @@ -198,7 +198,7 @@ def get_delete_edge_event(self, identifier): class GephiGraphStreamer(object): """Class that produces JSON event objects that stream an igraph graph to Gephi using the Gephi Graph Streaming API. - + The Gephi graph streaming format is a simple JSON-based format that can be used to post mutations to a graph (i.e. node and edge additions, removals and updates) to a remote component. For instance, one can open up Gephi (http://www.gephi.org}), @@ -261,7 +261,7 @@ def post(self, graph, destination, encoder=None): """Posts the given graph to the destination of the streamer using the given JSON encoder. When `encoder` is ``None``, it falls back to the default JSON encoder of the streamer in the `encoder` property. - + `destination` must be a file-like object or an instance of `GephiConnection`. """ encoder = encoder or self.encoder @@ -273,7 +273,7 @@ def send_event(self, event, destination, encoder=None, flush=True): """Sends a single JSON event to the given destination using the given JSON encoder. When `encoder` is ``None``, it falls back to the default JSON encoder of the streamer in the `encoder` property. - + `destination` must be a file-like object or an instance of `GephiConnection`. The method flushes the destination after sending the event. If you want to @@ -281,8 +281,8 @@ def send_event(self, event, destination, encoder=None, flush=True): ``False``. """ encoder = encoder or self.encoder - destination.write(encoder.encode(event)) - destination.write("\r\n") + destination.write(encoder.encode(event).encode("utf-8")) + destination.write(b"\r\n") if flush: destination.flush() From d18b2a91fc4ab9ad73a0b2eb594e7f334788ce74 Mon Sep 17 00:00:00 2001 From: Hong Xu Date: Thu, 16 Mar 2017 23:58:57 -0700 Subject: [PATCH 0008/1892] Add commas after "i.e." in description lines. In this way, epydoc will not truncate words after "i.e." from the function summary line. --- igraph/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index 566204560..a98d4380b 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -686,7 +686,7 @@ def gomory_hu_tree(self, capacity=None, flow="flow"): def is_named(self): """is_named() - Returns whether the graph is named, i.e. whether it has a "name" + Returns whether the graph is named, i.e., whether it has a "name" vertex attribute. """ return "name" in self.vertex_attributes() @@ -694,7 +694,7 @@ def is_named(self): def is_weighted(self): """is_weighted() - Returns whether the graph is weighted, i.e. whether it has a "weight" + Returns whether the graph is weighted, i.e., whether it has a "weight" edge attribute. """ return "weight" in self.edge_attributes() From 55170745e34f224df88e7a519c9e81bcdda7242c Mon Sep 17 00:00:00 2001 From: ntamas Date: Wed, 21 Jun 2017 14:18:14 +0200 Subject: [PATCH 0009/1892] fixed handling of Unicode literals in igraphmodule_i_attribute_add_{vertices,edges}, closes #128 --- igraph/test/__init__.py | 5 +++-- igraph/test/unicode.py | 27 +++++++++++++++++++++++++++ src/attributes.c | 38 ++++++++++++++++++++++++++++++++------ 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 igraph/test/unicode.py diff --git a/igraph/test/__init__.py b/igraph/test/__init__.py index 5b8272132..9ab48e8da 100644 --- a/igraph/test/__init__.py +++ b/igraph/test/__init__.py @@ -4,7 +4,7 @@ spectral, attributes, cliques, decomposition, operators, generators, \ isomorphism, colortests, vertexseq, edgeseq, iterators, bipartite, \ conversion, rng, separators, indexing, atlas, matching, homepage, \ - walks + walks, unicode def suite(): @@ -34,7 +34,8 @@ def suite(): atlas.suite(), matching.suite(), homepage.suite(), - walks.suite() + walks.suite(), + unicode.suite() ]) diff --git a/igraph/test/unicode.py b/igraph/test/unicode.py new file mode 100644 index 000000000..e8c2eb0cb --- /dev/null +++ b/igraph/test/unicode.py @@ -0,0 +1,27 @@ +from __future__ import unicode_literals + +import unittest +from igraph import Graph + +class UnicodeTests(unittest.TestCase): + def testBug128(self): + y = [1, 4, 9] + g = Graph(n=len(y), directed=True, vertex_attrs={'y': y}) + self.assertEquals(3, g.vcount()) + g.add_vertices(1) + # Bug #128 would prevent us from reaching the next statement + # because an exception would have been thrown here + self.assertEquals(4, g.vcount()) + + +def suite(): + generator_suite = unittest.makeSuite(UnicodeTests) + return unittest.TestSuite([generator_suite]) + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + +if __name__ == "__main__": + test() + diff --git a/src/attributes.c b/src/attributes.c index aca566de6..570a54632 100644 --- a/src/attributes.c +++ b/src/attributes.c @@ -107,6 +107,36 @@ void igraphmodule_index_vertex_names(igraph_t *graph, igraph_bool_t force) { igraphmodule_i_attribute_struct_index_vertex_names(ATTR_STRUCT(graph), force); } +int igraphmodule_PyObject_matches_attribute_record(PyObject* object, igraph_attribute_record_t* record) { + int result; + + if (record == 0) { + return 0; + } + + if (PyString_Check(object)) { + return PyString_IsEqualToASCIIString(object, record->name); + } + +#ifndef IGRAPH_PYTHON3 + /* On Python 2.x, we need to handle Unicode strings as well because + * the user might use 'from __future__ import unicode_literals', which + * would turn some igraph attribute names into Unicode strings */ + if (PyUnicode_Check(object)) { + PyObject* ascii = PyUnicode_AsASCIIString(object); + if (ascii == 0) { + return 0; + } + + result = PyString_IsEqualToASCIIString(ascii, record->name); + Py_DECREF(ascii); + return result; + } +#endif + + return 0; +} + int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_integer_t* vid) { igraphmodule_i_attribute_struct* attrs = ATTR_STRUCT(graph); PyObject* o_vid = NULL; @@ -421,8 +451,6 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, i IGRAPH_ERROR("vertex attribute hash type mismatch", IGRAPH_EINVAL); while (PyDict_Next(dict, &pos, &key, &value)) { - if (!PyString_Check(key)) - IGRAPH_ERROR("vertex attribute hash key is not a string", IGRAPH_EINVAL); if (!PyList_Check(value)) IGRAPH_ERROR("vertex attribute hash member is not a list", IGRAPH_EINVAL); /* Check if we have specific values for the given attribute */ @@ -431,7 +459,7 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, i j=igraph_vector_ptr_size(attr); for (i=0; iname)) { + if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { added_attrs[i]=1; break; } @@ -603,8 +631,6 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect if (!PyDict_Check(dict)) IGRAPH_ERROR("edge attribute hash type mismatch", IGRAPH_EINVAL); while (PyDict_Next(dict, &pos, &key, &value)) { - if (!PyString_Check(key)) - IGRAPH_ERROR("edge attribute hash key is not a string", IGRAPH_EINVAL); if (!PyList_Check(value)) IGRAPH_ERROR("edge attribute hash member is not a list", IGRAPH_EINVAL); @@ -614,7 +640,7 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect j=igraph_vector_ptr_size(attr); for (i=0; iname)) { + if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { added_attrs[i]=1; break; } From 93d6b6c9bb80cba6e498672a44b9e335000e9a52 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 21 Jun 2017 15:19:01 +0200 Subject: [PATCH 0010/1892] renamed unicode.py to unicode_issues.py so it does not confuse 2to3 --- igraph/test/__init__.py | 4 ++-- igraph/test/{unicode.py => unicode_issues.py} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename igraph/test/{unicode.py => unicode_issues.py} (100%) diff --git a/igraph/test/__init__.py b/igraph/test/__init__.py index 9ab48e8da..75e44872b 100644 --- a/igraph/test/__init__.py +++ b/igraph/test/__init__.py @@ -4,7 +4,7 @@ spectral, attributes, cliques, decomposition, operators, generators, \ isomorphism, colortests, vertexseq, edgeseq, iterators, bipartite, \ conversion, rng, separators, indexing, atlas, matching, homepage, \ - walks, unicode + walks, unicode_issues def suite(): @@ -35,7 +35,7 @@ def suite(): matching.suite(), homepage.suite(), walks.suite(), - unicode.suite() + unicode_issues.suite() ]) diff --git a/igraph/test/unicode.py b/igraph/test/unicode_issues.py similarity index 100% rename from igraph/test/unicode.py rename to igraph/test/unicode_issues.py From f62a8e85e963f9e8ac4972c69f4781325446b837 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 9 Aug 2017 15:43:39 +0200 Subject: [PATCH 0011/1892] clarified the documentation of Graph.strength(), fixes igraph/igraph#1022 --- src/graphobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphobject.c b/src/graphobject.c index 72584fefd..8c0b99c4a 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -11763,7 +11763,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " them).\n" "@param loops: whether self-loops should be counted.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" - " even an edge attribute name.\n" + " even an edge attribute name. ``None`` means to treat the graph as\n" + " unweighted, falling back to ordinary degree calculations.\n" }, /* interface to igraph_is_loop */ From 787169d3d1eb5e51290c5dc1ae7959ec77735c0e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Sep 2017 12:55:41 +0200 Subject: [PATCH 0012/1892] fixed invalid exception handling in igraphmodule_PyObject_to_vector_t, closes #137 --- src/convert.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/convert.c b/src/convert.c index 762eb75d4..69c66b7cc 100644 --- a/src/convert.c +++ b/src/convert.c @@ -881,6 +881,7 @@ int igraphmodule_PyObject_to_vector_t(PyObject *list, igraph_vector_t *v, igraph Py_DECREF(it); } else { /* list is not iterable; maybe it's a single number? */ + PyErr_Clear(); if (igraphmodule_PyObject_to_integer_t(list, &number)) { PyErr_SetString(PyExc_TypeError, "sequence or iterable expected"); igraph_vector_destroy(v); From 7533e577e1398b287ea31e2a632224d87df8a726 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Sep 2017 13:04:58 +0200 Subject: [PATCH 0013/1892] fixed another manifestation of the bug in the previous commit --- src/convert.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/convert.c b/src/convert.c index 69c66b7cc..775084e1c 100644 --- a/src/convert.c +++ b/src/convert.c @@ -978,6 +978,7 @@ int igraphmodule_PyObject_float_to_vector_t(PyObject *list, igraph_vector_t *v) Py_DECREF(it); } else { /* list is not iterable; maybe it's a single number? */ + PyErr_Clear(); if (igraphmodule_PyObject_to_real_t(list, &number)) { PyErr_SetString(PyExc_TypeError, "sequence or iterable expected"); igraph_vector_destroy(v); @@ -2649,7 +2650,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, iterator = PyObject_GetIter(o); if (iterator == NULL) { - PyErr_SetString(PyExc_TypeError, "conversion to edge sequene failed"); + PyErr_SetString(PyExc_TypeError, "conversion to edge sequence failed"); return 1; } From 754026c73049141b08aff2f60a0c058cda30c7fa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Oct 2017 11:06:44 +0200 Subject: [PATCH 0014/1892] minor documentation fixes --- igraph/__init__.py | 2 +- src/graphobject.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index a98d4380b..31a268e66 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -1389,7 +1389,7 @@ def layout(self, layout=None, *args, **kwds): (see L{Graph.layout_circle}) - C{dh}, C{davidson_harel}: Davidson-Harel layout (see - L{Graph.davidson_harel}) + L{Graph.layout_davidson_harel}) - C{drl}: DrL layout for large graphs (see L{Graph.layout_drl}) diff --git a/src/graphobject.c b/src/graphobject.c index 8c0b99c4a..4ac91953b 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -13115,7 +13115,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "For each vertex specified by I{vertices}, returns the\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" - "than I{mindist] steps are excluded.\n\n" + "than I{mindist} steps are excluded.\n\n" "@param vertices: a single vertex ID or a list of vertex IDs, or\n" " C{None} meaning all the vertices in the graph.\n" "@param order: the order of the neighborhood, i.e. the maximum number of\n" @@ -13143,7 +13143,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "For each vertex specified by I{vertices}, returns the number of\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" - "than I{mindist] steps are excluded.\n\n" + "than I{mindist} steps are excluded.\n\n" "@param vertices: a single vertex ID or a list of vertex IDs, or\n" " C{None} meaning all the vertices in the graph.\n" "@param order: the order of the neighborhood, i.e. the maximum number of\n" From cca9eeb47bf899b5cc0a2425c38cbf0db1fb1308 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Oct 2017 11:08:18 +0200 Subject: [PATCH 0015/1892] further documentation fixes, related to #137 --- doc/source/tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 25068918c..bd1fbd28b 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -719,8 +719,8 @@ layout algorithm (see the table above). All the remaining positional and keyword are passed intact to the chosen layout method. For instance, the following two calls are completely equivalent: ->>> layout = g.layout_reingold_tilford(root=2) ->>> layout = g.layout("rt", 2) +>>> layout = g.layout_reingold_tilford(root=[2]) +>>> layout = g.layout("rt", [2]) Layout methods return a :class:`Layout` object which behaves mostly like a list of lists. Each list entry in a :class:`Layout` object corresponds to a vertex in the original graph From 3e6a7fabc9fcfe57bd42d719107caed398c5e29e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Nov 2017 10:31:45 +0100 Subject: [PATCH 0016/1892] don't use modularity-based cluster count selection for Graph.community_edge_betweenness() when the graph is weighted, closes igraph/igraph#1040 --- igraph/__init__.py | 8 ++++++-- src/graphobject.c | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index 31a268e66..efaf1f930 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -1229,7 +1229,10 @@ def community_edge_betweenness(self, clusters=None, directed=True, @param clusters: the number of clusters we would like to see. This practically defines the "level" where we "cut" the dendrogram to get the membership vector of the vertices. If C{None}, the dendrogram - is cut at the level which maximizes the modularity. + is cut at the level which maximizes the modularity when the graph is + unweighted; otherwise the dendrogram is cut at at a single cluster + (because cluster count selection based on modularities does not make + sense for this method if not all the weights are equal). @param directed: whether the directionality of the edges should be taken into account or not. @param weights: name of an edge attribute or a list containing @@ -1238,7 +1241,8 @@ def community_edge_betweenness(self, clusters=None, directed=True, modularity or at the desired number of clusters. """ merges, qs = GraphBase.community_edge_betweenness(self, directed, weights) - qs.reverse() + if qs is not None: + qs.reverse() if clusters is None: if qs: clusters = qs.index(max(qs))+1 diff --git a/src/graphobject.c b/src/graphobject.c index 4ac91953b..67e84d423 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -11009,7 +11009,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject /* edge_betweenness = */ 0, /* merges = */ &merges, /* bridges = */ 0, - /* modularity = */ &q, + /* modularity = */ weights ? 0 : &q, /* membership = */ 0, PyObject_IsTrue(directed), weights)) { @@ -11026,11 +11026,18 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject igraph_vector_destroy(weights); free(weights); } - qs=igraphmodule_vector_t_to_PyList(&q, IGRAPHMODULE_TYPE_FLOAT); - igraph_vector_destroy(&q); - if (!qs) { - igraph_matrix_destroy(&merges); - return NULL; + if (weights == 0) { + /* Calculate modularity vector only in the unweighted case as we don't + * calculate modularities for the weighted case */ + qs=igraphmodule_vector_t_to_PyList(&q, IGRAPHMODULE_TYPE_FLOAT); + igraph_vector_destroy(&q); + if (!qs) { + igraph_matrix_destroy(&merges); + return NULL; + } + } else { + qs = Py_None; + Py_INCREF(qs); } ms=igraphmodule_matrix_t_to_PyList(&merges, IGRAPHMODULE_TYPE_INT); From 0bb128f21a3771349ff0246e28fe651a274bccb0 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 14 Nov 2017 21:29:44 +0330 Subject: [PATCH 0017/1892] Isolate graph drawing result to avoid id collision This change which is suggested by @takluyver forces jupyter to isolate graphs inside a notebook so we won't have collision of similar ids can be available on cairo renderer. --- igraph/drawing/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/igraph/drawing/__init__.py b/igraph/drawing/__init__.py index 1345cd5ad..774972cd4 100644 --- a/igraph/drawing/__init__.py +++ b/igraph/drawing/__init__.py @@ -356,9 +356,11 @@ def _repr_svg_(self): # Return the raw SVG representation result = io.getvalue() if hasattr(result, "encode"): - return result.encode("utf-8") # for Python 2.x + result = result.encode("utf-8") # for Python 2.x else: - return result.decode("utf-8") # for Python 3.x + result = result.decode("utf-8") # for Python 3.x + + return result, {'isolated': True} # put it inside an iframe @property def bounding_box(self): From bbf71de4893b58c06dace86fab2c3530032d4f89 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Wed, 15 Nov 2017 13:34:07 +0330 Subject: [PATCH 0018/1892] Improve _is_running_in_ipython logic, fixes #149 For some reasons it seems the current code is not able to detect ipython when ran from ipywidgets interactive widgets, lets change it to what @takluyver from jupyter team is suggested below: https://github.com/jupyter/jupyter/issues/299#issuecomment-344540261 --- igraph/utils.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/igraph/utils.py b/igraph/utils.py index 8316f0800..861732f1d 100644 --- a/igraph/utils.py +++ b/igraph/utils.py @@ -39,11 +39,9 @@ def _is_running_in_ipython(): """Internal function that determines whether igraph is running inside IPython or not.""" try: - # get_ipython is injected into the Python builtins by IPython so - # this should succeed in IPython but throw a NameError otherwise - get_ipython - return True - except NameError: + from IPython import get_ipython + return get_ipython() is not None + except ImportError: return False From f5a1b3c08277ae6ecb068f714fd3d8fc0b89f993 Mon Sep 17 00:00:00 2001 From: Jay Smith Date: Thu, 28 Dec 2017 14:53:36 -0500 Subject: [PATCH 0019/1892] Adding igraphmodule_Graph_dominator and tests --- igraph/test/structural.py | 51 +++++++++++++++++++++++++++++++++++- src/graphobject.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/igraph/test/structural.py b/igraph/test/structural.py index 500fd9d27..1ddfae51c 100644 --- a/igraph/test/structural.py +++ b/igraph/test/structural.py @@ -1,5 +1,6 @@ from __future__ import division +import math import unittest from igraph import * @@ -516,6 +517,52 @@ def testPathLengthHist(self): h = g.path_length_hist(False) self.assertTrue(h.unconnected == 20) +class DominatorTests(unittest.TestCase): + def compareDomTrees(self, alist, blist): + ''' + Required due to NaN use for isolated nodes + ''' + if len(alist) != len(blist): + return False + for i, (a, b) in enumerate(zip(alist, blist)): + if math.isnan(a) and math.isnan(b): + continue + elif a == b: + continue + else: + return False + return True + + def testDominators(self): + # examples taken from igraph's examples/simple/dominator_tree.out + + # initial + g = Graph(13, [(0,1), (0,7), (0,10), (1,2), (1,5), (2,3), (3,4), (4,3), + (4,0), (5,3), (5,6), (6,3), (7,8), (7,10), (7,11), (8,9), (9,4), + (9,8), (10,11), (11,12), (12,9) ], directed=True) + s = [-1, 0, 1, 0, 0, 1, 5, 0, 0, 0, 0, 0, 11 ] + r = g.dominator(0) + self.assertTrue(self.compareDomTrees(s, r)) + + # flipped edges + g = Graph(13, [(1,0), (2,0), (3,0), (4,1), (1,2), (4,2), (5,2), (6,3), + (7,3), (12,4), (8,5), (9,6), (9,7), (10,7), (5,8), (11,8), + (11,9), (9,10), (9,11), (0,11), (8,12)], directed=True) + s = [-1, 0, 0, 0, 0, 0, 3, 3, 0, 0, 7, 0, 4] + r = g.dominator(0, mode=IN) + self.assertTrue(self.compareDomTrees(s, r)) + + # disconnected components + g = Graph(20, [(0,1), (0,2), (0,3), (1,4), (2,1), (2,4), (2,8), (3,9), + (3,10), (4,15), (8,11), (9,12), (10,12), (10,13), (11,8), + (11,14), (12,14), (13,12), (14,12), (14,0), (15,11)], + directed=True) + s = [-1, 0, 0, 0, 0, float("nan"), float("nan"), float("nan"), 0, 3, 3, 0, + 0, 10, 0, 4, float("nan"), float("nan"), float("nan"), float("nan")] + r = g.dominator(0, mode=OUT) + self.assertTrue(self.compareDomTrees(s, r)) + + def suite(): simple_suite = unittest.makeSuite(SimplePropertiesTests) degree_suite = unittest.makeSuite(DegreeTests) @@ -525,6 +572,7 @@ def suite(): neighborhood_suite = unittest.makeSuite(NeighborhoodTests) path_suite = unittest.makeSuite(PathTests) misc_suite = unittest.makeSuite(MiscTests) + dominator_suite = unittest.makeSuite(DominatorTests) return unittest.TestSuite([simple_suite, degree_suite, local_transitivity_suite, @@ -532,7 +580,8 @@ def suite(): centrality_suite, neighborhood_suite, path_suite, - misc_suite]) + misc_suite, + dominator_suite]) def test(): runner = unittest.TextTestRunner() diff --git a/src/graphobject.c b/src/graphobject.c index 67e84d423..7897c39af 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -9759,6 +9759,48 @@ PyObject *igraphmodule_Graph_unfold_tree(igraphmodule_GraphObject * self, return Py_BuildValue("NN", result_o, mapping_o); } +/********************************************************************** + * Dominator * + **********************************************************************/ + +/** \ingroup python_interface_graph + * \brief Calculates the dominator tree for the graph + */ +PyObject *igraphmodule_Graph_dominator(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + static char *kwlist[] = { "vid", "mode", NULL }; + PyObject *list = Py_None; + PyObject *mode_o = Py_None; + long int root = -1; + igraph_vector_t dom; + igraph_neimode_t mode = IGRAPH_OUT; + int res ; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O", kwlist, &root, &mode_o)) { + return NULL; + } + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { + return NULL; + } + if (mode == IGRAPH_ALL) { + mode = IGRAPH_OUT; + } + + if (igraph_vector_init(&dom, 0)) { + return NULL; + } + res = igraph_dominator_tree(&self->g, root, &dom, NULL, NULL, mode); + if(res) { + igraph_vector_destroy(&dom); + return NULL; + } + list = igraphmodule_vector_t_to_PyList(&dom, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(&dom); + return list; +} + /********************************************************************** * Maximum flows * **********************************************************************/ @@ -14905,6 +14947,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param graphs: the list of graphs to be united with\n" " the current one.\n"}, + /**********************/ + /* DOMINATORS */ + /**********************/ + {"dominator", (PyCFunction) igraphmodule_Graph_dominator, + METH_VARARGS | METH_KEYWORDS, + "dominator(vid, mode=)\n\n" + "Returns the dominator tree from the given root node" + "@param vid: the root vertex ID\n" + "@param mode: either L{IN} or L{OUT}\n" + "@return: a list containing the dominator tree for the current graph." + }, + /*****************/ /* MAXIMUM FLOWS */ /*****************/ From 47dff4aeaf0bd9e9b8a17660b8d1389fdd9eb0e0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 31 Dec 2017 10:21:26 +0100 Subject: [PATCH 0020/1892] fixed failing edge betweenness community detection test case --- igraph/test/decomposition.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/igraph/test/decomposition.py b/igraph/test/decomposition.py index 2aea82755..ec052c219 100644 --- a/igraph/test/decomposition.py +++ b/igraph/test/decomposition.py @@ -195,7 +195,12 @@ def testEdgeBetweenness(self): # Full graph with weights g.es["weight"] = 1 g[0,1] = g[1,2] = g[2,0] = g[3,4] = 10 - cl = g.community_edge_betweenness(weights="weight").as_clustering() + + # We need to specify the desired cluster count explicitly; this is + # because edge betweenness-based detection does not play well with + # modularity-based cluster count selection (the edge weights have + # different semantics) so we need to give igraph a hint + cl = g.community_edge_betweenness(weights="weight").as_clustering(n=2) self.assertMembershipsEqual(cl, [0,0,0,1,1]) self.assertAlmostEqual(cl.q, 0.2750, places=3) From f323aa389fad2e003f2b7beb52dd2b2eda00a955 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 31 Dec 2017 14:51:26 +0100 Subject: [PATCH 0021/1892] bump tested Python versions to 3.5 and 3.6; trying to fix pypy test issues --- .travis.yml | 2 ++ tox.ini | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 67da26e79..f8bfc7117 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,8 @@ language: python python: - "2.7" - "3.4" + - "3.5" + - "3.6" - "pypy" - "pypy3" diff --git a/tox.ini b/tox.ini index a6fa0e3e2..485d1820a 100644 --- a/tox.ini +++ b/tox.ini @@ -4,11 +4,10 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py34, pypy, pypy3 +envlist = py27, py34, py35, py36, pypy, pypy3 [testenv] commands = - python test/doctests.py python test/unittests.py deps = setenv = From 2f3960b78cf601f7d72f717ff97c7ac9ece33c9d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 2 Jan 2018 15:38:50 +0100 Subject: [PATCH 0022/1892] fixed crashing test cases on PyPy --- src/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphobject.c b/src/graphobject.c index 7897c39af..7bad43b8b 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -176,7 +176,7 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) igraph_destroy(&self->g); - if (PyCallable_Check(self->destructor)) { + if (self->destructor != NULL && PyCallable_Check(self->destructor)) { r = PyObject_CallObject(self->destructor, NULL); if (r) { Py_DECREF(r); From 9fcfd3a83586f40ba4a07c5730d4708682f14138 Mon Sep 17 00:00:00 2001 From: Yong-Yeol Ahn Date: Sat, 10 Feb 2018 11:55:13 -0500 Subject: [PATCH 0023/1892] make print statements python3 compatible Adding the parentheses in print statements to make code examples compatible with python3. --- doc/source/tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index bd1fbd28b..e8b2ac79c 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -37,7 +37,7 @@ namespace-qualification. E.g., to check which |igraph| version you are using, yo following: >>> import igraph ->>> print igraph.__version__ +>>> print(igraph.__version__) 0.6 Another way to make use of |igraph| is to import all its objects and methods into the main @@ -155,7 +155,7 @@ Let us go on with our graph ``g`` and add some more vertices and edges to it: >>> g.add_edges((2,0)) >>> g.add_vertices(3) >>> g.add_edges([(2,3),(3,4),(4,5),(5,3)]) ->>> print g +>>> print(g) IGRAPH U---- 6 7 -- + edges: 0--1 1--2 0--2 2--3 3--4 4--5 3--5 @@ -337,7 +337,7 @@ can assign attributes to the whole graph. Not too surprisingly, :class:`Graph` o themselves can also behave as dictionaries: >>> g["date"] = "2009-01-10" ->>> print g["date"] +>>> print(g["date"]) 2009-01-10 Finally, it should be mentioned that attributes can be deleted by the Python keyword From 26ac299639cb817a8b0c7f5e576960d0be147bbc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 20 Feb 2018 00:55:55 +0100 Subject: [PATCH 0024/1892] ignoring Pipfile; I use pipenv internally but as there are no deps, there's no point in adding it --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index bf7d4382f..479f60207 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ igraph/*.so .python-version .tox docker/wheelhouse +Pipfile + From 651fb00f5a56e3eec60c9d2d65d5c298f2f50f58 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 23 Feb 2018 16:56:35 +0100 Subject: [PATCH 0025/1892] removed two compilation warnings for Python 3.x --- src/attributes.c | 2 ++ src/convert.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/attributes.c b/src/attributes.c index 570a54632..6639e1a50 100644 --- a/src/attributes.c +++ b/src/attributes.c @@ -108,7 +108,9 @@ void igraphmodule_index_vertex_names(igraph_t *graph, igraph_bool_t force) { } int igraphmodule_PyObject_matches_attribute_record(PyObject* object, igraph_attribute_record_t* record) { +#ifndef IGRAPH_PYTHON3 int result; +#endif if (record == 0) { return 0; diff --git a/src/convert.c b/src/convert.c index 775084e1c..59d989701 100644 --- a/src/convert.c +++ b/src/convert.c @@ -2848,7 +2848,7 @@ int igraphmodule_i_PyObject_pair_to_attribute_combination_record_t( return 1; if (result->type == IGRAPH_ATTRIBUTE_COMBINE_FUNCTION) { - result->func = value; + result->func = (void*) value; } else { result->func = 0; } From f7f612cb2cc812a6e68fd254f5d63cf8f4a3b273 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 23 Feb 2018 17:10:07 +0100 Subject: [PATCH 0026/1892] fixed invalid error handling in file-related functions in Python 3.x; closes #95 --- igraph/test/foreign.py | 8 ++++++++ src/filehandle.c | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/igraph/test/foreign.py b/igraph/test/foreign.py index 520c885fa..7afb02ae8 100644 --- a/igraph/test/foreign.py +++ b/igraph/test/foreign.py @@ -173,6 +173,14 @@ def testLGL(self): self.assertTrue("name" in g.vertex_attributes() and \ "weight" not in g.edge_attributes()) + # This is not an LGL file; we are testing error handling here + with temporary_file(u"""\ + 1 2 + 1 3 + """) as tmpfname: + with self.assertRaises(InternalError): + Graph.Read_Lgl(tmpfname) + def testLGLWithIOModule(self): with temporary_file(u"""\ # eggs diff --git a/src/filehandle.c b/src/filehandle.c index 8282f76e9..22dce1426 100644 --- a/src/filehandle.c +++ b/src/filehandle.c @@ -319,6 +319,8 @@ int igraphmodule_filehandle_init(igraphmodule_filehandle_t* handle, * \brief Destroys the file handle object. */ void igraphmodule_filehandle_destroy(igraphmodule_filehandle_t* handle) { + PyObject *exc_type = 0, *exc_value = 0, *exc_traceback = 0; + if (handle->fp != 0) { fflush(handle->fp); } @@ -326,12 +328,17 @@ void igraphmodule_filehandle_destroy(igraphmodule_filehandle_t* handle) { handle->fp = 0; if (handle->object != 0) { + /* PyFile_Close might mess up the stored exception, so let's + * store the current exception state and restore it */ + PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); if (handle->need_close) { if (PyFile_Close(handle->object)) { PyErr_WriteUnraisable(Py_None); } } Py_DECREF(handle->object); + PyErr_Restore(exc_type, exc_value, exc_traceback); + exc_type = exc_value = exc_traceback = 0; handle->object = 0; } From 29e74333e0df50e614bdd904dbaf8eea7a974256 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 23 Feb 2018 18:21:50 +0100 Subject: [PATCH 0027/1892] removed closeness centrality warnings from test cases --- igraph/test/structural.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/igraph/test/structural.py b/igraph/test/structural.py index 1ddfae51c..d5176e245 100644 --- a/igraph/test/structural.py +++ b/igraph/test/structural.py @@ -2,6 +2,7 @@ import math import unittest +import warnings from igraph import * from igraph.compat import isnan @@ -261,7 +262,9 @@ def testClosenessCentrality(self): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) g = Graph.Star(5) - cl = g.closeness(cutoff=1) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + cl = g.closeness(cutoff=1) cl2 = [1., 0.25, 0.25, 0.25, 0.25] for idx in xrange(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -275,7 +278,9 @@ def testClosenessCentrality(self): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) g = Graph.Star(5) - cl = g.closeness(cutoff=1, weights=weights) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + cl = g.closeness(cutoff=1, weights=weights) cl2 = [1., 0.25, 0.25, 0.25, 0.25] for idx in xrange(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) From bb933e79445e6763025d2126d5c292b966be5a0e Mon Sep 17 00:00:00 2001 From: Philipp A Date: Tue, 27 Feb 2018 10:31:10 +0100 Subject: [PATCH 0028/1892] Allow passing environment variables to ./configure --- setup.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 698e3391f..1ed96b7d9 100644 --- a/setup.py +++ b/setup.py @@ -488,8 +488,8 @@ def _progress_hook(count, block_size, total_size): os.rename("ltmain.sh.new", "ltmain.sh") print("Configuring igraph...") - retcode = subprocess.call("CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --disable-tls --disable-gmp", - shell=True) + retcode = subprocess.call(["./configure", "--disable-tls", "--disable-gmp"], + env=self.enhanced_env(CFLAGS='-fPIC', CXXFLAGS='-fPIC')) if retcode: return False @@ -525,6 +525,14 @@ def _progress_hook(count, block_size, total_size): return True + @staticmethod + def enhanced_env(**kwargs): + env = os.environ.copy() + for k, v in kwargs.items(): + prev = os.environ.get(k) + env[k] = "{0} {1}".format(prev, v) if prev else v + return env + def find_first_version(self): """Finds the first version of igraph that exists in the nightly build repo from the version numbers provided in ``self.versions_to_try``.""" From e8b38c5a3bb27d443de4e3572415a077dfb9efca Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 9 Mar 2018 00:09:59 +0100 Subject: [PATCH 0029/1892] trying to fix a segfault during unit tests on certain platforms --- igraph/test/atlas.py | 6 ++++++ src/filehandle.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/igraph/test/atlas.py b/igraph/test/atlas.py index 28410b0f1..6e3b084b8 100644 --- a/igraph/test/atlas.py +++ b/igraph/test/atlas.py @@ -29,6 +29,10 @@ def testEigenvectorCentrality(self): try: for idx, g in enumerate(self.__class__.graphs): + if idx in self.__class__.skip_graphs: + # Skip this graph; it causes lots of problems and I don't know why + continue + try: ec, eval = g.evcent(return_eigenvalue=True) except Exception, ex: @@ -92,10 +96,12 @@ def testAuthorityScore(self): class GraphAtlasTests(TestBase): graphs = [Graph.Atlas(i) for i in xrange(1253)] + skip_graphs = set([136]) class IsoclassTests(TestBase): graphs = [Graph.Isoclass(3, i, directed=True) for i in xrange(16)] + \ [Graph.Isoclass(4, i, directed=True) for i in xrange(218)] + skip_graphs = set([]) def suite(): atlas_suite = unittest.makeSuite(GraphAtlasTests) diff --git a/src/filehandle.c b/src/filehandle.c index 22dce1426..f085d6f0b 100644 --- a/src/filehandle.c +++ b/src/filehandle.c @@ -39,6 +39,7 @@ static int igraphmodule_i_filehandle_init_cpython_2(igraphmodule_filehandle_t* h return 1; } + handle->object = 0; handle->need_close = 0; if (PyBaseString_Check(object)) { @@ -98,7 +99,6 @@ static int igraphmodule_i_filehandle_init_cpython_2(igraphmodule_filehandle_t* h if (fileno > 0) { fp = fdopen(fileno, mode); - handle->need_close = 1; } else { PyErr_SetString(PyExc_ValueError, "fileno() method returned invalid " "file descriptor"); @@ -129,6 +129,7 @@ static int igraphmodule_i_filehandle_init_cpython_3(igraphmodule_filehandle_t* h } handle->need_close = 0; + handle->object = 0; if (PyBaseString_Check(object)) { /* We have received a string; we need to open the file denoted by this @@ -187,6 +188,7 @@ static int igraphmodule_i_filehandle_init_pypy_2(igraphmodule_filehandle_t* hand } handle->need_close = 0; + handle->object = 0; if (PyBaseString_Check(object)) { /* We have received a string; we need to open the file denoted by this @@ -323,6 +325,9 @@ void igraphmodule_filehandle_destroy(igraphmodule_filehandle_t* handle) { if (handle->fp != 0) { fflush(handle->fp); + if (handle->need_close && !handle->object) { + fclose(handle->fp); + } } handle->fp = 0; From f158b05903d592a176a0138ff9b6d055a02e72f5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 9 Mar 2018 00:23:37 +0100 Subject: [PATCH 0030/1892] verbose tox test case reporting; removed a warning --- src/graphobject.c | 1 - tox.ini | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/graphobject.c b/src/graphobject.c index 7bad43b8b..7959338e0 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -7627,7 +7627,6 @@ PyObject *igraphmodule_Graph_Read_Lgl(PyTypeObject * type, PyObject * args, PyDict_GetItemString(kwds, "directed") == NULL) { if (PyErr_Occurred()) return NULL; - PY_IGRAPH_WARN("Graph.Read_Lgl creates directed networks by default from igraph 0.6. To get rid of this warning, specify directed=... explicitly. This warning will be removed from igraph 0.7."); } if (igraphmodule_filehandle_init(&fobj, fname, "r")) diff --git a/tox.ini b/tox.ini index 485d1820a..338c9b93e 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ envlist = py27, py34, py35, py36, pypy, pypy3 [testenv] commands = - python test/unittests.py + python test/unittests.py -v deps = setenv = TESTING_IN_TOX=1 From 82ac75e25a472972f630763985a4b6c786aa6f3e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 10 Mar 2018 00:31:11 +0100 Subject: [PATCH 0031/1892] fix ignored graphs in eigenvector centrality tests --- igraph/test/atlas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/igraph/test/atlas.py b/igraph/test/atlas.py index 6e3b084b8..f0946391f 100644 --- a/igraph/test/atlas.py +++ b/igraph/test/atlas.py @@ -96,12 +96,12 @@ def testAuthorityScore(self): class GraphAtlasTests(TestBase): graphs = [Graph.Atlas(i) for i in xrange(1253)] - skip_graphs = set([136]) + skip_graphs = set([]) class IsoclassTests(TestBase): graphs = [Graph.Isoclass(3, i, directed=True) for i in xrange(16)] + \ [Graph.Isoclass(4, i, directed=True) for i in xrange(218)] - skip_graphs = set([]) + skip_graphs = set([136]) def suite(): atlas_suite = unittest.makeSuite(GraphAtlasTests) From 6391810c0695b28c357f2c564ccca01dd1b6cc78 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 20 Apr 2018 21:31:03 +0200 Subject: [PATCH 0032/1892] added a regression test for igraph:igraph/#1078 --- igraph/test/structural.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/igraph/test/structural.py b/igraph/test/structural.py index d5176e245..a3affd184 100644 --- a/igraph/test/structural.py +++ b/igraph/test/structural.py @@ -285,6 +285,24 @@ def testClosenessCentrality(self): for idx in xrange(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) + # Test for igraph/igraph:#1078 + g = Graph([ + (0, 1), (0, 2), (0, 5), (0, 6), (0, 9), (1, 6), (1, 8), + (2, 4), (2, 6), (2, 7), (2, 8), (3, 6), (4, 8), + (5, 6), (5, 9), (6, 7), (6, 8), (7, 8), (7, 9), (8, 9) + ]) + weights = [0.69452, 0.329886, 0.131649, 0.503269, 0.472738, + 0.370933, 0.23857, 0.0354043, 0.189015, 0.355118, 0.768335, + 0.893289, 0.891709, 0.494896, 0.924684, 0.432001, 0.858159, + 0.246798, 0.881304, 0.64685] + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + cl = g.closeness(weights=weights) + expected_cl = [1.63318, 1.52014, 2.03724, 0.760158, 1.91449, + 1.43224, 1.91761, 1.60198, 1.3891, 1.12829] + for obs, exp in zip(cl, expected_cl): + self.assertAlmostEqual(obs, exp, places=4) + def testPageRank(self): g = Graph.Star(11) cent = g.pagerank() From 82f25e1925ca09cae039b0a97565d8da3b6fe677 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 28 May 2018 21:35:39 +0200 Subject: [PATCH 0033/1892] mark_groups=... now supports VertexClustering and VertexColor, closes #51 --- igraph/__init__.py | 9 +++++++-- igraph/clustering.py | 8 ++------ igraph/drawing/graph.py | 13 +++++++++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index efaf1f930..c902d34a0 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -3135,8 +3135,13 @@ def __plot__(self, context, bbox, palette, *args, **kwds): colors. - A list containing pairs or an iterable yielding pairs, where - the first element of each pair is a list of vertex indices and - the second element is a color. + the first element of each pair is a list of vertex indices and + the second element is a color. + + - A L{VertexClustering} or L{VertexCover} instance. The vertex + groups in the clustering or cover will be highlighted such that + the i-th group will be colored by the i-th color from the + current palette. In place of lists of vertex indices, you may also use L{VertexSeq} instances. diff --git a/igraph/clustering.py b/igraph/clustering.py index 7919aa84d..18660df93 100644 --- a/igraph/clustering.py +++ b/igraph/clustering.py @@ -496,9 +496,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: - kwds["mark_groups"] = ( - (group, color) for color, group in enumerate(self) - ) + kwds["mark_groups"] = self else: kwds["mark_groups"] = _handle_mark_groups_arg_for_clustering( kwds["mark_groups"], self) @@ -1327,7 +1325,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: - kwds["mark_groups"] = enumerate(self) + kwds["mark_groups"] = self else: kwds["mark_groups"] = _handle_mark_groups_arg_for_clustering( kwds["mark_groups"], self) @@ -1657,5 +1655,3 @@ def split_join_distance(comm1, comm2, remove_none=False): import igraph._igraph vec1, vec2 = _prepare_community_comparison(comm1, comm2, remove_none) return igraph._igraph._split_join_distance(vec1, vec2) - - diff --git a/igraph/drawing/graph.py b/igraph/drawing/graph.py index a532d104f..c24f09ffd 100644 --- a/igraph/drawing/graph.py +++ b/igraph/drawing/graph.py @@ -267,10 +267,20 @@ def draw(self, graph, palette, *args, **kwds): if "mark_groups" in kwds: mark_groups = kwds["mark_groups"] + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + # Figure out what to do with mark_groups in order to be able to # iterate over it and get memberlist-color pairs if isinstance(mark_groups, dict): + # Dictionary mapping vertex indices or tuples of vertex + # indices to colors group_iter = mark_groups.iteritems() + elif isinstance(mark_groups, (VertexClustering, VertexCover)): + # Vertex clustering + group_iter = ( + (group, color) for color, group in enumerate(mark_groups) + ) elif hasattr(mark_groups, "__iter__"): # Lists, tuples, iterators etc group_iter = iter(mark_groups) @@ -447,7 +457,7 @@ def draw(self, graph, palette, *args, **kwds): else: # Specified edge order edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) - + # Draw the edge labels for edge, visual_edge in edge_coord_iter: if visual_edge.label is None: @@ -916,4 +926,3 @@ def draw(self, graph, *args, **kwds): will be used to encode the JSON objects. """ self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) - From 9e82d6d58f1d8dd6fa277dbb1839dcb554ec97d5 Mon Sep 17 00:00:00 2001 From: Gao Fangshu Date: Wed, 30 May 2018 00:05:54 +0800 Subject: [PATCH 0034/1892] Correct a typo Correct a typo --- doc/source/tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index e8b2ac79c..40ff2987a 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -134,7 +134,7 @@ to your graph: :meth:`~Graph.add_edges` is clever enough to figure out what you want to do in most of the cases: if you supply a single pair of integers, it will automatically assume that you want to add a single edge. However, if you try to add edges to vertices with invalid IDs (i.e., -you try to add an edge to vertex 5 when you only have three edges), you will get an +you try to add an edge to vertex 5 when you only have three vertices), you will get an exception: >>> g.add_edges((5, 0)) From 41331a57953fa3b995ce11c8a90acec7c6720350 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 5 Jun 2018 17:34:11 +0200 Subject: [PATCH 0035/1892] clarify that a single isolated vertex is not a biconnected component --- src/graphobject.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/graphobject.c b/src/graphobject.c index 7959338e0..f232b7712 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -12644,6 +12644,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "biconnected_components(return_articulation_points=True)\n\n" "Calculates the biconnected components of the graph.\n\n" + "Components containing a single vertex only are not considered as being\n" + "biconnected.\n\n" "@param return_articulation_points: whether to return the articulation\n" " points as well\n" "@return: a list of lists containing edge indices making up spanning trees\n" From 86a6ad8c438f2b8caf2d9af9dc686057bdd6c2d4 Mon Sep 17 00:00:00 2001 From: deeenes Date: Wed, 13 Jun 2018 15:54:38 +0200 Subject: [PATCH 0036/1892] ConfigParser instead of deprecated SafeConfigParser; +2 Linux image viewers --- igraph/configuration.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/igraph/configuration.py b/igraph/configuration.py index c14cd0e55..0cde7e858 100644 --- a/igraph/configuration.py +++ b/igraph/configuration.py @@ -28,7 +28,7 @@ 02110-1301 USA """ -from ConfigParser import SafeConfigParser +from ConfigParser import ConfigParser import platform import os.path @@ -42,7 +42,8 @@ def get_platform_image_viewer(): elif plat == "Linux": # Linux has a whole lot of choices, try to find one choices = ["eog", "gthumb", "gqview", "kuickshow", "xnview", "display", - "gpicview", "gwenview", "qiv", "gimv", "ristretto"] + "gpicview", "gwenview", "qiv", "gimv", "ristretto", + "geeqie", "eom"] paths = ["/usr/bin", "/bin"] for path in paths: for choice in choices: @@ -225,15 +226,15 @@ def setfloat(obj, section, key, value): _types = { "boolean": { - "getter": SafeConfigParser.getboolean, + "getter": ConfigParser.getboolean, "setter": Types.setboolean }, "int": { - "getter": SafeConfigParser.getint, + "getter": ConfigParser.getint, "setter": Types.setint }, "float": { - "getter": SafeConfigParser.getfloat, + "getter": ConfigParser.getfloat, "setter": Types.setfloat } } @@ -285,7 +286,7 @@ def __init__(self, filename=None): @param filename: file or file pointer to be read. Can be omitted. """ - self._config = SafeConfigParser() + self._config = ConfigParser() self._filename = None # Create default sections @@ -460,3 +461,4 @@ def init(): @return: the L{Configuration} object loaded or created.""" return Configuration.instance() + From a9be781ae15637211219756dbc9deb75eb9f332e Mon Sep 17 00:00:00 2001 From: deeenes Date: Wed, 13 Jun 2018 22:26:41 +0200 Subject: [PATCH 0037/1892] Python 2/3 compatibility of ConfigParser import --- igraph/configuration.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/igraph/configuration.py b/igraph/configuration.py index 0cde7e858..0183aff50 100644 --- a/igraph/configuration.py +++ b/igraph/configuration.py @@ -28,7 +28,12 @@ 02110-1301 USA """ -from ConfigParser import ConfigParser +import sys +if sys.version_info < (3, ): + from ConfigParser import SafeConfigParser as ConfigParser +else: + from configparser import ConfigParser + import platform import os.path From bdd742ccd2c9e5adb7e4cd404a84390d51923ae8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jul 2018 17:09:52 +0200 Subject: [PATCH 0038/1892] add contribution guidelines and issue template --- .github/CONTRIBUTING.md | 7 +++++++ .github/ISSUE_TEMPLATE.md | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..75005ccfc --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,7 @@ +Reporting issues +================ + +We use the issue tracker for tracking bugs and feature requests _only_. +If you do not have a bug or feature request but you only need help with using +igraph, send your question to the igraph-help mailing list instead at +igraph-help@nongnu.org. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..24c3b711c --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,4 @@ +Make sure that these boxes are checked before submitting your issue -- thank you! + +- [ ] This issue is for the Python interface of igraph. +- [ ] This issue is a bug report or a feature request, not a support question. From ae3a6a6c8e0e2f834fa9830afeda04244becf091 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 2 Jul 2018 20:30:36 +0200 Subject: [PATCH 0039/1892] updated the documentation of copy(), mentioned copy.deepcopy(), fixes #74 --- src/graphobject.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/graphobject.c b/src/graphobject.c index f232b7712..39c3f8be1 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -283,7 +283,7 @@ PyObject *igraphmodule_Graph_str(igraphmodule_GraphObject * self) } /** \ingroup python_interface_copy - * \brief Creates an exact deep copy of the graph + * \brief Creates a copy of the graph * \return the copy of the graph */ PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject * self) @@ -12713,7 +12713,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the component index for every node in the graph.\n"}, {"copy", (PyCFunction) igraphmodule_Graph_copy, METH_NOARGS, - "copy()\n\n" "Creates an exact deep copy of the graph."}, + "copy()\n\n" + "Creates a copy of the graph.\n\n" + "Attributes are copied by reference; in other words, if you use\n" + "mutable Python objects as attribute values, these objects will still\n" + "be shared between the old and new graph. You can use `deepcopy()`\n" + "from the `copy` module if you need a truly deep copy of the graph.\n" + }, {"decompose", (PyCFunction) igraphmodule_Graph_decompose, METH_VARARGS | METH_KEYWORDS, "decompose(mode=STRONG, maxcompno=None, minelements=1)\n\n" From 161f39f221d7b0b32908b288169487726489b72c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 25 Aug 2018 00:40:57 +0200 Subject: [PATCH 0040/1892] make sure that Graph.__new__ and Graph.__init__ is called properly when using a class constructor of a Graph subclass, fixes #97 --- igraph/__init__.py | 14 +- igraph/test/basic.py | 33 ++++- src/graphobject.c | 312 ++++++++++++++++++++++++++----------------- src/graphobject.h | 12 +- 4 files changed, 237 insertions(+), 134 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index c902d34a0..7f8a886be 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -162,10 +162,15 @@ def __init__(self, *args, **kwds): dictionary value must be an iterable with exactly M{m} items where M{m} is the number of edges. """ + # Pop the special __ptr keyword argument + ptr = kwds.pop("__ptr", None) + # Set up default values for the parameters. This should match the order # in *args - kwd_order = ["n", "edges", "directed", "graph_attrs", "vertex_attrs", \ - "edge_attrs"] + kwd_order = ( + "n", "edges", "directed", "graph_attrs", "vertex_attrs", + "edge_attrs" + ) params = [0, [], False, {}, {}, {}] # Is there any keyword argument in kwds that we don't know? If so, @@ -204,7 +209,10 @@ def __init__(self, *args, **kwds): edges = [] # Initialize the graph - GraphBase.__init__(self, nverts, edges, directed) + if ptr: + GraphBase.__init__(self, __ptr=ptr) + else: + GraphBase.__init__(self, nverts, edges, directed) # Set the graph attributes for key, value in graph_attrs.iteritems(): diff --git a/igraph/test/basic.py b/igraph/test/basic.py index 804ff02b6..feb3dec21 100644 --- a/igraph/test/basic.py +++ b/igraph/test/basic.py @@ -502,14 +502,44 @@ def testIsGraphicalSequence(self): self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 4])) +class InheritedGraph(Graph): + def __init__(self, *args, **kwds): + super(InheritedGraph, self).__init__(*args, **kwds) + self.init_called = True + + def __new__(cls, *args, **kwds): + result = Graph.__new__(cls, *args, **kwds) + result.new_called = True + return result + + +class InheritanceTests(unittest.TestCase): + def testInitCalledProperly(self): + g = InheritedGraph() + self.assertTrue(getattr(g, "init_called", False)) + + def testNewCalledProperly(self): + g = InheritedGraph() + self.assertTrue(getattr(g, "new_called", False)) + + def testInitCalledProperlyWithClassMethod(self): + g = InheritedGraph.Tree(3, 2) + self.assertTrue(getattr(g, "init_called", False)) + + def testNewCalledProperlyWithClassMethod(self): + g = InheritedGraph.Tree(3, 2) + self.assertTrue(getattr(g, "new_called", False)) + + def suite(): basic_suite = unittest.makeSuite(BasicTests) datatype_suite = unittest.makeSuite(DatatypeTests) graph_dict_list_suite = unittest.makeSuite(GraphDictListTests) graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) + inheritance_suite = unittest.makeSuite(InheritanceTests) return unittest.TestSuite([basic_suite, datatype_suite, graph_dict_list_suite, - graph_tuple_list_suite, degree_sequence_suite]) + graph_tuple_list_suite, degree_sequence_suite, inheritance_suite]) def test(): runner = unittest.TextTestRunner() @@ -517,4 +547,3 @@ def test(): if __name__ == "__main__": test() - diff --git a/src/graphobject.c b/src/graphobject.c index 39c3f8be1..873eb6a01 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -1,21 +1,21 @@ /* vim:set ts=4 sw=2 sts=2 et: */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -38,21 +38,16 @@ PyTypeObject igraphmodule_GraphType; -#define CREATE_GRAPH(py_graph, c_graph) { \ - py_graph = (igraphmodule_GraphObject *) Py_TYPE(self)->tp_alloc(Py_TYPE(self), 0); \ - if (py_graph != NULL) { \ - igraphmodule_Graph_init_internal(py_graph); \ - py_graph->g = (c_graph); \ - } \ - RC_ALLOC("Graph", py_graph); \ -} #define CREATE_GRAPH_FROM_TYPE(py_graph, c_graph, py_type) { \ - py_graph = (igraphmodule_GraphObject *) py_type->tp_alloc(py_type, 0); \ - if (py_graph != NULL) { \ - igraphmodule_Graph_init_internal(py_graph); \ - py_graph->g = (c_graph); \ - } \ - RC_ALLOC("Graph", py_graph); \ + py_graph = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( \ + py_type, &c_graph \ + ); \ +} + +#define CREATE_GRAPH(py_graph, c_graph) { \ + py_graph = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( \ + Py_TYPE(self), &c_graph \ + ); \ } /********************************************************************** @@ -66,13 +61,14 @@ PyTypeObject igraphmodule_GraphType; * \ingroup python_interface_internal * \brief Initializes the internal structures in an \c igraph.Graph object's * C representation. - * + * * This function must be called whenever we create a new Graph object with * \c tp_alloc */ void igraphmodule_Graph_init_internal(igraphmodule_GraphObject * self) { if (!self) return; + self->destructor = NULL; self->weakreflist = NULL; } @@ -80,21 +76,21 @@ void igraphmodule_Graph_init_internal(igraphmodule_GraphObject * self) /** * \ingroup python_interface_graph * \brief Creates a new igraph object in Python - * + * * This function is called whenever a new \c igraph.Graph object is created in * Python. An optional \c n parameter can be passed from Python, * representing the number of vertices in the graph. If it is omitted, * the default value is 0. - * + * * Example call from Python: \verbatim g = igraph.Graph(5); \endverbatim * * In fact, the parameters are processed by \c igraphmodule_Graph_init - * + * * \return the new \c igraph.Graph object or NULL if an error occurred. - * + * * \sa igraphmodule_Graph_init * \sa igraph_empty */ @@ -106,10 +102,6 @@ PyObject *igraphmodule_Graph_new(PyTypeObject * type, PyObject * args, self = (igraphmodule_GraphObject *) type->tp_alloc(type, 0); RC_ALLOC("Graph", self); - /* don't need it, the constructor will do it */ - /*if (self != NULL) { - igraph_empty(&self->g, 1, 0); - } */ igraphmodule_Graph_init_internal(self); return (PyObject *) self; @@ -134,7 +126,7 @@ int igraphmodule_Graph_clear(igraphmodule_GraphObject * self) /** * \ingroup python_interface_graph * \brief Support for cyclic garbage collection in Python - * + * * This is necessary because the \c igraph.Graph object contains several * other \c PyObject pointers and they might point back to itself. */ @@ -193,31 +185,51 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) /** * \ingroup python_interface_graph * \brief Initializes a new \c igraph object in Python - * + * * This function is called whenever a new \c igraph.Graph object is initialized in * Python (note that initializing is not equal to creating: an object might * be created but not initialized when it is being recovered from a serialized * state). - * + * * Throws \c AssertionError in Python if \c vcount is less than or equal to zero. * \return the new \c igraph.Graph object or NULL if an error occurred. - * + * * \sa igraphmodule_Graph_new * \sa igraph_empty * \sa igraph_create */ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "n", "edges", "directed", NULL }; + static char *kwlist[] = { "n", "edges", "directed", "__ptr", NULL }; long int n = 0; - PyObject *edges = NULL, *dir = Py_False; + PyObject *edges = NULL, *dir = Py_False, *ptr_o = 0; + void* ptr = 0; igraph_vector_t edges_vector; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO!O", kwlist, - &n, &PyList_Type, &edges, &dir)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO!OO!", kwlist, + &n, &PyList_Type, &edges, &dir, + &PyCapsule_Type, &ptr_o)) return -1; - if (edges && PyList_Check(edges)) { + /* Safety check: if ptr is not null, it means that we have been explicitly + * given a pointer to an igraph_t for which we must take ownership. + * This means that n should be zero and edges should not be specified */ + if (ptr_o && (n != 0 || edges != NULL)) { + PyErr_SetString(PyExc_ValueError, "neither n nor edges should be given " + "in the call to Graph.__init__() when the graph is " + "pre-initialized with a C pointer"); + return -1; + } + + if (ptr_o) { + /* We must take ownership of an igraph graph */ + ptr = PyCapsule_GetPointer(ptr_o, "__igraph_t"); + if (ptr == 0) { + PyErr_SetString(PyExc_ValueError, "pointer should not be null"); + } else { + self->g = *(igraph_t*)ptr; + } + } else if (edges && PyList_Check(edges)) { /* Caller specified an edge list, so we use igraph_create */ /* We have to convert the Python list to a igraph_vector_t */ if (igraphmodule_PyObject_to_edgelist(edges, &edges_vector, 0)) { @@ -233,9 +245,9 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, } igraph_vector_destroy(&edges_vector); - } - else { - /* No edge list was specified, let's use igraph_empty */ + } else { + /* No edge list was specified, and no previously initialized graph object + * was fed into our object, so let's use igraph_empty */ if (igraph_empty(&self->g, (igraph_integer_t) n, PyObject_IsTrue(dir))) { igraphmodule_handle_igraph_error(); return -1; @@ -245,6 +257,64 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, return 0; } +/** \ingroup python_interface_graph + * \brief Creates an \c igraph.Graph subtype from an existing \c igraph_t + * + * The newly created instance (which will be a subtype of )\c igraph.Graph) + * will take ownership of the given \c igraph_t. This function is not + * accessible from Python. + */ +PyObject* igraphmodule_Graph_subclass_from_igraph_t( + PyTypeObject* type, igraph_t *graph +) { + PyObject* result; + PyObject* capsule; + PyObject* args; + PyObject* kwds; + + if (!PyType_IsSubtype(type, &igraphmodule_GraphType)) { + PyErr_SetString(PyExc_TypeError, "igraph.GraphBase expected"); + return 0; + } + + capsule = PyCapsule_New(graph, "__igraph_t", 0); + if (capsule == 0) { + return 0; + } + + args = PyTuple_New(0); + if (args == 0) { + Py_DECREF(capsule); + return 0; + } + + kwds = PyDict_New(); + if (kwds == 0) { + Py_DECREF(args); + Py_DECREF(capsule); + return 0; + } + + if (PyDict_SetItemString(kwds, "__ptr", capsule)) { + Py_DECREF(kwds); + Py_DECREF(args); + Py_DECREF(capsule); + return 0; + } + + /* kwds now holds a reference to the capsule so we can release it */ + Py_DECREF(capsule); + + /* Call the type */ + result = PyObject_Call((PyObject*) type, args, kwds); + + /* Release args and kwds */ + Py_DECREF(args); + Py_DECREF(kwds); + + return result; +} + /** \ingroup python_interface_graph * \brief Creates an \c igraph.Graph object from an existing \c igraph_t * @@ -254,20 +324,17 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, * See \c api.h for more details. */ PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph) { - igraphmodule_GraphObject* result; - PyTypeObject* type = &igraphmodule_GraphType; - - CREATE_GRAPH_FROM_TYPE(result, *graph, type); - - return (PyObject*)result; + return igraphmodule_Graph_subclass_from_igraph_t( + &igraphmodule_GraphType, graph + ); } /** \ingroup python_interface_graph * \brief Formats an \c igraph.Graph object in a human-readable format. - * + * * This function is rather simple now, it returns the number of vertices * and edges in a string. - * + * * \return the formatted textual representation as a \c PyObject */ PyObject *igraphmodule_Graph_str(igraphmodule_GraphObject * self) @@ -486,7 +553,7 @@ PyObject *igraphmodule_Graph_add_vertices(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Removes vertices from an \c igraph.Graph * \return the modified \c igraph.Graph object - * + * * \todo Need more error checking on vertex IDs. (igraph fails when an * invalid vertex ID is given) * \sa igraph_delete_vertices @@ -512,7 +579,7 @@ PyObject *igraphmodule_Graph_delete_vertices(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Adds edges to an \c igraph.Graph * \return the extended \c igraph.Graph object - * + * * \todo Need more error checking on vertex IDs. (igraph fails when an * invalid vertex ID is given) * \sa igraph_add_edges @@ -543,7 +610,7 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Deletes edges from an \c igraph.Graph * \return the extended \c igraph.Graph object - * + * * \todo Need more error checking on vertex IDs. (igraph fails when an * invalid vertex ID is given) * \sa igraph_delete_edges @@ -557,7 +624,7 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &list)) return NULL; - + if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { /* something bad happened during conversion, return immediately */ return NULL; @@ -856,7 +923,7 @@ PyObject *igraphmodule_Graph_maxdegree(igraphmodule_GraphObject * self, } /** \ingroup python_interface_graph - * \brief Checks whether an edge is a loop edge + * \brief Checks whether an edge is a loop edge * \return a boolean or a list of booleans * \sa igraph_is_loop */ @@ -904,7 +971,7 @@ PyObject *igraphmodule_Graph_is_loop(igraphmodule_GraphObject *self, } /** \ingroup python_interface_graph - * \brief Checks whether an edge is a multiple edge + * \brief Checks whether an edge is a multiple edge * \return a boolean or a list of booleans * \sa igraph_is_multiple */ @@ -952,7 +1019,7 @@ PyObject *igraphmodule_Graph_is_multiple(igraphmodule_GraphObject *self, } /** \ingroup python_interface_graph - * \brief Checks whether an edge is mutual + * \brief Checks whether an edge is mutual * \return a boolean or a list of booleans * \sa igraph_is_mutual */ @@ -1018,7 +1085,7 @@ PyObject *igraphmodule_Graph_has_multiple(igraphmodule_GraphObject *self) { } /** \ingroup python_interface_graph - * \brief Checks the multiplicity of the edges + * \brief Checks the multiplicity of the edges * \return the edge multiplicities as a Python list * \sa igraph_count_multiple */ @@ -1069,7 +1136,7 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, * second argument may be passed as well, meaning the type of neighbors to * be returned (\c OUT for successors, \c IN for predecessors or \c ALL * for both of them). This argument is ignored for undirected graphs. - * + * * \return the neighbor list as a Python list object * \sa igraph_neighbors */ @@ -1120,7 +1187,7 @@ PyObject *igraphmodule_Graph_neighbors(igraphmodule_GraphObject * self, * A second argument may be passed as well, meaning the type of neighbors to * be returned (\c OUT for successors, \c IN for predecessors or \c ALL * for both of them). This argument is ignored for undirected graphs. - * + * * \return the adjacency list as a Python list object * \sa igraph_incident */ @@ -1194,7 +1261,7 @@ PyObject *igraphmodule_Graph_reciprocity(igraphmodule_GraphObject * self, * This method accepts a single vertex ID as a parameter, and returns the * successors of the given vertex in the form of an integer list. It * is equivalent to calling \c igraph.Graph.neighbors with \c type=OUT - * + * * \return the successor list as a Python list object * \sa igraph_neighbors */ @@ -1231,7 +1298,7 @@ PyObject *igraphmodule_Graph_successors(igraphmodule_GraphObject * self, * This method accepts a single vertex ID as a parameter, and returns the * predecessors of the given vertex in the form of an integer list. It * is equivalent to calling \c igraph.Graph.neighbors with \c type=IN - * + * * \return the predecessor list as a Python list object * \sa igraph_neighbors */ @@ -1417,7 +1484,7 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, * in unconnected graphs: it is \c True if the longest geodesic * within a component should be returned and \c False if the number of * vertices should be returned. They both have a default value of \c False. - * + * * \return the diameter as a Python integer * \sa igraph_diameter */ @@ -1586,7 +1653,7 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, /** * \ingroup python_interface_graph - * \brief Calculates the convergence degree of the edges in a graph + * \brief Calculates the convergence degree of the edges in a graph */ PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) { igraph_vector_t result; @@ -1606,7 +1673,7 @@ PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) /** * \ingroup python_interface_graph - * \brief Calculates the sizes of the convergence fields in a graph + * \brief Calculates the sizes of the convergence fields in a graph */ PyObject *igraphmodule_Graph_convergence_field_size(igraphmodule_GraphObject *self) { igraph_vector_t ins, outs; @@ -1709,7 +1776,7 @@ PyObject *igraphmodule_Graph_knn(igraphmodule_GraphObject *self, /** \ingroup python_interface_graph * \brief Calculates the radius of an \c igraph.Graph - * + * * \return the radius as a Python integer * \sa igraph_radius */ @@ -1809,7 +1876,7 @@ PyObject *igraphmodule_Graph_Atlas(PyTypeObject * type, PyObject * args) * This is intended to be a class method in Python, so the first argument * is the type object and not the Python igraph object (because we have * to allocate that in this method). - * + * * \return a reference to the newly generated Python igraph object * \sa igraph_barabasi_game */ @@ -1924,7 +1991,7 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, igraph_vector_destroy(&edges); igraph_vector_bool_destroy(&types); - + CREATE_GRAPH_FROM_TYPE(self, g, type); return (PyObject *) self; @@ -1959,7 +2026,7 @@ PyObject *igraphmodule_Graph_De_Bruijn(PyTypeObject *type, PyObject *args, * This is intended to be a class method in Python, so the first argument * is the type object and not the Python igraph object (because we have * to allocate that in this method). - * + * * \return a reference to the newly generated Python igraph object * \sa igraph_degree_sequence_game */ @@ -2457,7 +2524,7 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, * This is intended to be a class method in Python, so the first argument * is the type object and not the Python igraph object (because we have * to allocate that in this method). - * + * * \return a reference to the newly generated Python igraph object * \sa igraph_isoclass_create */ @@ -2869,7 +2936,7 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, if (igraph_bipartite_game(&g, &vertex_types, t, (igraph_integer_t) n1, (igraph_integer_t) n2, - (igraph_real_t) p, (igraph_integer_t) m, + (igraph_real_t) p, (igraph_integer_t) m, PyObject_IsTrue(directed_o), neimode)) { igraph_vector_bool_destroy(&vertex_types); igraphmodule_handle_igraph_error(); @@ -3479,7 +3546,7 @@ PyObject *igraphmodule_Graph_authority_score( if (weights) { igraph_vector_destroy(weights); free(weights); } - res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); + res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); if (res_o == NULL) return igraphmodule_handle_igraph_error(); @@ -3702,7 +3769,7 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se igraph_vector_destroy(&points); return Py_BuildValue("NN", result, result2); /* references stolen */ } - + return result; } @@ -4391,8 +4458,8 @@ PyObject *igraphmodule_Graph_eigenvector_centrality( } if (weights) { igraph_vector_destroy(weights); free(weights); } - - res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); + + res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); if (res_o == NULL) return igraphmodule_handle_igraph_error(); @@ -4488,7 +4555,7 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; @@ -4749,7 +4816,7 @@ PyObject *igraphmodule_Graph_hub_score( if (weights) { igraph_vector_destroy(weights); free(weights); } - res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); + res_o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); if (res_o == NULL) return igraphmodule_handle_igraph_error(); @@ -5039,14 +5106,14 @@ PyObject *igraphmodule_Graph_path_length_hist(igraphmodule_GraphObject *self, igraph_vector_destroy(&res); return igraphmodule_handle_igraph_error(); } - + result=igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&res); return Py_BuildValue("Nd", result, (double)unconn); } /** \ingroup python_interface_graph - * \brief Permutes the vertices of the graph + * \brief Permutes the vertices of the graph * \return the new graph as a new igraph object * \sa igraph_permute_vertices */ @@ -5404,7 +5471,7 @@ PyObject *igraphmodule_Graph_similarity_inverse_log_weighted( return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) return NULL; + if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) return NULL; if (igraph_matrix_init(&res, 0, 0)) { igraph_vs_destroy(&vs); @@ -5754,7 +5821,7 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_init(&result, 0)) + if (igraph_vector_init(&result, 0)) return igraphmodule_handle_igraph_error(); if (!PyObject_IsTrue(warnings_o)) { @@ -5817,7 +5884,7 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, } if (!IGRAPH_FINITE(res)) return Py_BuildValue("d", (double)res); - + result = (long)res; return Py_BuildValue("l", result); } @@ -5936,7 +6003,7 @@ igraph_bool_t igraphmodule_i_Graph_motifs_randesu_callback(const igraph_t *graph } /** \ingroup python_interface_graph - * \brief Counts the motifs of the graph sorted by isomorphism classes + * \brief Counts the motifs of the graph sorted by isomorphism classes * \return the number of motifs found for each isomorphism class * \sa igraph_motifs_randesu */ @@ -7285,7 +7352,7 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, igraph_matrix_destroy(&matrix); return NULL; } - + if (types) { igraph_vector_bool_destroy(types); free(types); } matrix_o = igraphmodule_matrix_t_to_PyList(&matrix, IGRAPHMODULE_TYPE_INT); @@ -7328,7 +7395,7 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, return NULL; } - if (igraph_laplacian(&self->g, &m, /*sparseres=*/ 0, + if (igraph_laplacian(&self->g, &m, /*sparseres=*/ 0, PyObject_IsTrue(normalized), weights)) { igraphmodule_handle_igraph_error(); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -7672,7 +7739,7 @@ PyObject *igraphmodule_Graph_Read_Pajek(PyTypeObject * type, PyObject * args, igraphmodule_filehandle_destroy(&fobj); return NULL; } - + igraphmodule_filehandle_destroy(&fobj); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -7739,10 +7806,10 @@ PyObject *igraphmodule_Graph_Read_GraphDB(PyTypeObject * type, igraphmodule_filehandle_destroy(&fobj); return NULL; } - + igraphmodule_filehandle_destroy(&fobj); CREATE_GRAPH_FROM_TYPE(self, g, type); - + return (PyObject *) self; } @@ -7774,10 +7841,10 @@ PyObject *igraphmodule_Graph_Read_GraphML(PyTypeObject * type, igraphmodule_filehandle_destroy(&fobj); return NULL; } - + igraphmodule_filehandle_destroy(&fobj); CREATE_GRAPH_FROM_TYPE(self, g, type); - + return (PyObject *) self; } @@ -8551,7 +8618,7 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, } /** \ingroup python_interface_graph - * \brief Counts the number of isomorphisms of two given graphs + * \brief Counts the number of isomorphisms of two given graphs * * The actual code is almost the same as igraphmodule_Graph_count_subisomorphisms. * Make sure you correct bugs in both interfaces if applicable! @@ -8643,7 +8710,7 @@ PyObject *igraphmodule_Graph_count_isomorphisms_vf2(igraphmodule_GraphObject *se } /** \ingroup python_interface_graph - * \brief Returns all isomorphisms of two given graphs + * \brief Returns all isomorphisms of two given graphs * * The actual code is almost the same as igraphmodule_Graph_get_subisomorphisms. * Make sure you correct bugs in both interfaces if applicable! @@ -8891,7 +8958,7 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, } /** \ingroup python_interface_graph - * \brief Counts the number of subisomorphisms of two given graphs + * \brief Counts the number of subisomorphisms of two given graphs * * The actual code is almost the same as igraphmodule_Graph_count_isomorphisms. * Make sure you correct bugs in both interfaces if applicable! @@ -8980,7 +9047,7 @@ PyObject *igraphmodule_Graph_count_subisomorphisms_vf2(igraphmodule_GraphObject } /** \ingroup python_interface_graph - * \brief Returns all subisomorphisms of two given graphs + * \brief Returns all subisomorphisms of two given graphs * * The actual code is almost the same as igraphmodule_Graph_get_isomorphisms. * Make sure you correct bugs in both interfaces if applicable! @@ -9217,7 +9284,7 @@ Py_ssize_t igraphmodule_Graph_attribute_count(igraphmodule_GraphObject * self) /** \ingroup python_interface_graph * \brief Handles the subscript operator on the graph. - * + * * When the subscript is a string, returns the corresponding value of the * given attribute in the graph. When the subscript is a tuple of length * 2, retrieves the adjacency matrix representation of the graph between @@ -9233,7 +9300,7 @@ PyObject *igraphmodule_Graph_mp_subscript(igraphmodule_GraphObject * self, PyObject *ri = PyTuple_GET_ITEM(s, 0); PyObject *ci = PyTuple_GET_ITEM(s, 1); PyObject *attr; - + if (PyTuple_Size(s) == 2) { attr = 0; } else if (PyTuple_Size(s) == 3) { @@ -9262,7 +9329,7 @@ PyObject *igraphmodule_Graph_mp_subscript(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Handles the subscript assignment operator on the graph. - * + * * If k is a string, sets the value of the corresponding attribute of the graph. * If k is a tuple of length 2, sets part of the adjacency matrix. * @@ -9276,7 +9343,7 @@ int igraphmodule_Graph_mp_assign_subscript(igraphmodule_GraphObject * self, if (PyTuple_Check(k) && PyTuple_Size(k) >= 2) { /* Adjacency matrix representation */ PyObject *ri, *ci, *attr; - + if (v == NULL) { PyErr_SetString(PyExc_NotImplementedError, "cannot delete parts " "of the adjacency matrix of a graph"); @@ -9444,7 +9511,7 @@ PyObject *igraphmodule_Graph_union(igraphmodule_GraphObject * self, } o = (igraphmodule_GraphObject *) other; - if (igraph_union(&g, &self->g, &o->g, /*edge_map1=*/ 0, + if (igraph_union(&g, &self->g, &o->g, /*edge_map1=*/ 0, /*edge_map2=*/ 0)) { igraphmodule_handle_igraph_error(); return NULL; @@ -9507,7 +9574,7 @@ PyObject *igraphmodule_Graph_intersection(igraphmodule_GraphObject * self, } o = (igraphmodule_GraphObject *) other; - if (igraph_intersection(&g, &self->g, &o->g, /*edge_map1=*/ 0, + if (igraph_intersection(&g, &self->g, &o->g, /*edge_map1=*/ 0, /*edge_map2=*/ 0)) { igraphmodule_handle_igraph_error(); return NULL; @@ -9611,7 +9678,7 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, } o = (igraphmodule_GraphObject *) other; - if (igraph_compose(&g, &self->g, &o->g, /*edge_map1=*/ 0, + if (igraph_compose(&g, &self->g, &o->g, /*edge_map1=*/ 0, /*edge_map2=*/ 0)) { igraphmodule_handle_igraph_error(); return NULL; @@ -9647,7 +9714,7 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_init(&vids, igraph_vcount(&self->g))) + if (igraph_vector_init(&vids, igraph_vcount(&self->g))) return igraphmodule_handle_igraph_error(); if (igraph_vector_init(&layers, igraph_vcount(&self->g))) { igraph_vector_destroy(&vids); @@ -9830,7 +9897,7 @@ PyObject *igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); - if (igraph_maxflow_value(&self->g, &result, v1, v2, &capacity_vector, + if (igraph_maxflow_value(&self->g, &result, v1, v2, &capacity_vector, &stats)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); @@ -9897,7 +9964,7 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, flow_o = igraphmodule_vector_t_to_PyList(&flow, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&flow); - + if (flow_o == NULL) { igraph_vector_destroy(&cut); igraph_vector_destroy(&partition); @@ -9906,7 +9973,7 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, cut_o = igraphmodule_vector_t_to_PyList(&cut, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&cut); - + if (cut_o == NULL) { igraph_vector_destroy(&partition); return NULL; @@ -9914,7 +9981,7 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, partition_o = igraphmodule_vector_t_to_PyList(&partition, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&partition); - + if (partition_o == NULL) return NULL; @@ -10176,7 +10243,7 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, retval = igraph_st_mincut(&self->g, &value, &cut, &partition, &partition2, source, target, &capacity_vector); } - + if (retval) { igraph_vector_destroy(&cut); igraph_vector_destroy(&partition); @@ -10530,7 +10597,7 @@ PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, } parents_o = igraphmodule_vector_t_to_PyList(&parents, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&parents); + igraph_vector_destroy(&parents); if (parents_o == NULL) { Py_DECREF(blocks_o); @@ -11228,12 +11295,12 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, PyObject *e_weights = Py_None, *v_weights = Py_None; unsigned int nb_trials = 10; igraph_vector_t *e_ws = 0, *v_ws = 0; - + igraph_vector_t membership; PyObject *res = Py_False; igraph_real_t codelength; - - + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOI", kwlist, &e_weights, &v_weights, &nb_trials)) { return NULL; @@ -11248,7 +11315,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, igraph_vector_destroy(&membership); return NULL; } - + if (igraphmodule_attrib_to_vector_t(v_weights, self, &v_ws, ATTRIBUTE_TYPE_VERTEX)){ igraph_vector_destroy(&membership); if (e_ws) { @@ -11257,8 +11324,8 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, } return NULL; } - - if (igraph_community_infomap(/*in */ &self->g, + + if (igraph_community_infomap(/*in */ &self->g, /*e_weight=*/ e_ws, /*v_weight=*/ v_ws, /*nb_trials=*/nb_trials, /*out*/ &membership, &codelength)) { @@ -11274,23 +11341,23 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, } return NULL; } - + if (e_ws) { igraph_vector_destroy(e_ws); free(e_ws); } - + if (v_ws) { igraph_vector_destroy(v_ws); free(v_ws); } - + res = igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&membership); - + if (!res) return NULL; - + return Py_BuildValue("Nd", res, (double)codelength); } @@ -12078,7 +12145,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "from vertex M{v} to vertex M{w} if the string of M{v} can be transformed into\n" "the string of M{w} by removing its first letter and appending a letter to it.\n" "\n" - "Please note that the graph will have M{m^n} vertices and even more edges,\n" + "Please note that the graph will have M{m^n} vertices and even more edges,\n" "so probably you don't want to supply too big numbers for M{m} and M{n}.\n\n" "@param m: the size of the alphabet\n" "@param n: the length of the strings\n" @@ -12129,7 +12196,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Forest_Fire(n, fw_prob, bw_factor=0.0, ambs=1, directed=False)\n\n" "Generates a graph based on the forest fire model\n\n" - "The forest fire model is a growin graph model. In every time step, a new\n" + "The forest fire model is a growing graph model. In every time step, a new\n" "vertex is added to the graph. The new vertex chooses an ambassador (or\n" "more than one if M{ambs>1}) and starts a simulated forest fire at its\n" "ambassador(s). The fire spreads through the edges. The spreading probability\n" @@ -12326,12 +12393,12 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "the number of vertices in the graph, a list of shifts giving\n" "additional edges to a cycle backbone and another integer giving how\n" "many times the shifts should be performed. See\n" - "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" + "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" "@param n: the number of vertices\n" "@param shifts: the shifts in a list or tuple\n" "@param repeats: the number of repeats\n" }, - + // interface to igraph_ring {"Ring", (PyCFunction) igraphmodule_Graph_Ring, METH_VARARGS | METH_CLASS | METH_KEYWORDS, @@ -14885,7 +14952,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " contains a subgraph that is isomorphic to the given template, C{False}\n" " otherwise. If the mapping is calculated, the result is a tuple, the first\n" " element being the above mentioned boolean, and the second element being\n" - " the mapping from the target to the original graph.\n"}, + " the mapping from the target to the original graph.\n"}, {"get_subisomorphisms_lad", (PyCFunction) igraphmodule_Graph_get_subisomorphisms_lad, METH_VARARGS | METH_KEYWORDS, @@ -15755,4 +15822,3 @@ PyTypeObject igraphmodule_GraphType = { }; #undef CREATE_GRAPH - diff --git a/src/graphobject.h b/src/graphobject.h index 5b0fa4bee..618a8d1de 100644 --- a/src/graphobject.h +++ b/src/graphobject.h @@ -1,21 +1,21 @@ /* -*- mode: C -*- */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -34,7 +34,7 @@ extern PyTypeObject igraphmodule_GraphType; * \ingroup python_interface * \brief A structure containing all the fields required to access an igraph from Python */ -typedef struct +typedef struct { PyObject_HEAD // The graph object From 06e12fa536426e310964c4f5c287dc84616b183d Mon Sep 17 00:00:00 2001 From: FredInChina Date: Sat, 15 Sep 2018 22:35:29 +0800 Subject: [PATCH 0041/1892] remove redundant definition of TextAlignment --- igraph/drawing/text.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/igraph/drawing/text.py b/igraph/drawing/text.py index 73104884d..bff01c897 100644 --- a/igraph/drawing/text.py +++ b/igraph/drawing/text.py @@ -25,14 +25,6 @@ class TextAlignment(object): ##################################################################### -class TextAlignment(object): - """Text alignment constants.""" - - LEFT, CENTER, RIGHT = "left", "center", "right" - TOP, BOTTOM = "top", "bottom" - -##################################################################### - class TextDrawer(AbstractCairoDrawer): """Class that draws text on a Cairo context. From 22bc9aec626d95fc57d8acf4bacda3ccfc9f5e54 Mon Sep 17 00:00:00 2001 From: Grzegorz Chilczuk Date: Tue, 25 Sep 2018 00:05:49 +0200 Subject: [PATCH 0042/1892] add linux installation instructions --- README.md | 10 ++++++++++ doc/source/install.rst | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/README.md b/README.md index 904654a0d..be1bbc146 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,16 @@ $ sudo python setup.py install ``` See details in [Installing Python Modules](https://docs.python.org/2/install/). +### Installation with pip +Install dependencies +``` +$ sudo apt install build-essential python-dev libxml2 libxml2-de zlib1g-dev +``` +and then +``` +$ pip install python-igraph +``` + ## Compiling the development version If you have downloaded the source code from Github and not PyPI, chances are diff --git a/doc/source/install.rst b/doc/source/install.rst index e511312ec..5d6e458e7 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -107,6 +107,10 @@ Having done that, you can launch Python again and check if it worked: |igraph| on Debian GNU/Linux ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Make sure you have dependencie installed: +``$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev`` +and then install with pip / pip3 +``$ pip install python-igraph`` |igraph| on RedHat Linux ^^^^^^^^^^^^^^^^^^^^^^^^ From 146bf17593714a007c741c9dbef90ec4b251235a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Tue, 25 Sep 2018 09:11:47 +0200 Subject: [PATCH 0043/1892] minor doc fixes --- doc/source/install.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 5d6e458e7..a3fff76ce 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -107,10 +107,14 @@ Having done that, you can launch Python again and check if it worked: |igraph| on Debian GNU/Linux ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Make sure you have dependencie installed: -``$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev`` + +Make sure you have all the required dependencies installed: + + $ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev + and then install with pip / pip3 -``$ pip install python-igraph`` + + $ pip install python-igraph |igraph| on RedHat Linux ^^^^^^^^^^^^^^^^^^^^^^^^ From 1b5632ef2b1ef61e56bff7804d1daada1311fb23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Mon, 1 Oct 2018 09:44:48 +0200 Subject: [PATCH 0044/1892] fix dependency list in README --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index be1bbc146..8364a62fd 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,18 @@ igraph. You can learn more about python-igraph [on our website](http://igraph.org/python/). - ## Installation + ``` $ sudo python setup.py install ``` See details in [Installing Python Modules](https://docs.python.org/2/install/). -### Installation with pip +### Installation with pip on Debian / Ubuntu and derivatives + Install dependencies ``` -$ sudo apt install build-essential python-dev libxml2 libxml2-de zlib1g-dev +$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev ``` and then ``` From 5db17cd6dc6c87a657f87ca203a55c8a6857dbe4 Mon Sep 17 00:00:00 2001 From: frederik-h Date: Tue, 2 Oct 2018 19:17:36 +0200 Subject: [PATCH 0045/1892] Fix Makefile A variable substitution in the Makefile was missing parentheses which stopped the variable from being substituted correctly. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index acd7f1b49..5ee2b2c09 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TAG = igraph/manylinux build-wheel: - docker build -f docker/manylinux.docker -t $TAG . + docker build -f docker/manylinux.docker -t $(TAG) . copy-wheel: rm -rf docker/wheelhouse From a76038e2e94b4a50bb8628cd9f21036efd5d1e14 Mon Sep 17 00:00:00 2001 From: frederik-h Date: Sat, 6 Oct 2018 20:16:09 +0200 Subject: [PATCH 0046/1892] Add support for coloring to BLISS functions Although the functions for computing canonical permuations and testing isomorphism using BLISS in igraph's C core support colorings, this support is not exposed in the python library. This commit adds support for colorings to the corresponding functions of the python library. --- igraph/test/isomorphism.py | 24 +++++++++++++++++++ src/graphobject.c | 49 +++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/igraph/test/isomorphism.py b/igraph/test/isomorphism.py index 7bcde77ba..4a5044a97 100644 --- a/igraph/test/isomorphism.py +++ b/igraph/test/isomorphism.py @@ -43,6 +43,19 @@ def testIsomorphic(self): g2.vs["color"] = [0,0,1,1,0,1,1,0] self.assertTrue(not g1.isomorphic_vf2(g2, "color", "color")) + # Test bliss with colors + self.assertTrue(g1.isomorphic_bliss(g2, + color1=[0,0,0,0,0,0,0,0], + color2=[0,0,0,0,0,0,0,0])) + + self.assertTrue(g1.isomorphic_bliss(g2, + color1=[1,0,2,0,0,0,0,0], + color2=[1,0,2,0,0,0,0,0])) + + self.assertTrue(g1.isomorphic_bliss(g2, + color1=[0,1,0,1,0,1,0,1], + color2=[0,0,1,1,0,0,1,1])) + # Test VF2 with vertex and edge colors self.assertTrue(g1.isomorphic_vf2(g2, color1=[0,1,0,1,0,1,0,1], @@ -232,6 +245,17 @@ def testCanonicalPermutation(self): self.assertTrue(g3.vcount() == g4.vcount()) self.assertTrue(sorted(g3.get_edgelist()) == sorted(g4.get_edgelist())) + # Simple case with coloring + cp = g1.canonical_permutation(color = [0, 0, 1, 1]) + g3 = g1.permute_vertices(cp) + + cp = g2.canonical_permutation(color = [0, 0, 1, 1]) + g4 = g2.permute_vertices(cp) + + self.assertTrue(g3.vcount() == g4.vcount()) + self.assertTrue(sorted(g3.get_edgelist()) == sorted(g4.get_edgelist())) + + # More complicated one: small GRG, random permutation g = Graph.GRG(10, 0.5) perm = range(10) diff --git a/src/graphobject.c b/src/graphobject.c index 873eb6a01..3e2db726a 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -8196,13 +8196,15 @@ PyObject *igraphmodule_Graph_write_leda(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_canonical_permutation( igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = { "sh", NULL }; + static char *kwlist[] = { "sh", "color", NULL }; PyObject *sh_o = Py_None; + PyObject *color_o = Py_None; PyObject *list; igraph_bliss_sh_t sh = IGRAPH_BLISS_FM; igraph_vector_t labeling; + igraph_vector_int_t *color = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sh_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) return NULL; if (igraphmodule_PyObject_to_bliss_sh_t(sh_o, &sh)) @@ -8213,14 +8215,23 @@ PyObject *igraphmodule_Graph_canonical_permutation( return NULL; } - if (igraph_canonical_permutation(&self->g, 0, &labeling, sh, 0)) { + if (igraphmodule_attrib_to_vector_int_t(color_o, self, &color, + ATTRIBUTE_TYPE_VERTEX)) return NULL; + + int retval = igraph_canonical_permutation(&self->g, color, &labeling, sh, 0); + + if (color) { igraph_vector_int_destroy(color); free(color); } + + if (retval) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&labeling); return NULL; } list = igraphmodule_vector_t_to_PyList(&labeling, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(&labeling); + return list; } @@ -8311,16 +8322,19 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, igraph_bool_t result = 0; PyObject *o=Py_None, *return1=Py_False, *return2=Py_False; PyObject *sho1=Py_None, *sho2=Py_None; + PyObject *color1_o=Py_None, *color2_o=Py_None; igraphmodule_GraphObject *other; igraph_vector_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_bliss_sh_t sh1=IGRAPH_BLISS_FM, sh2=IGRAPH_BLISS_FM; + igraph_vector_int_t *color1=0, *color2=0; + static char *kwlist[] = { "other", "return_mapping_12", - "return_mapping_21", "sh1", "sh2", NULL }; + "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; /* TODO: convert igraph_bliss_info_t when needed */ if (!PyArg_ParseTupleAndKeywords - (args, kwds, "|O!OOOO", kwlist, &igraphmodule_GraphType, &o, - &return1, &return2, &sho1, &sho2)) + (args, kwds, "|O!OOOOOO", kwlist, &igraphmodule_GraphType, &o, + &return1, &return2, &sho1, &sho2, &color1_o, &color2_o)) return NULL; if (igraphmodule_PyObject_to_bliss_sh_t(sho1, &sh1)) return NULL; sh2 = sh1; @@ -8330,6 +8344,12 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, "be equal to sh1"); } sh2 = sh1; + + if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, + ATTRIBUTE_TYPE_VERTEX)) return NULL; + if (igraphmodule_attrib_to_vector_int_t(color2_o, self, &color2, + ATTRIBUTE_TYPE_VERTEX)) return NULL; + if (o == Py_None) other = self; else other = (igraphmodule_GraphObject *) o; if (PyObject_IsTrue(return1)) { @@ -8341,8 +8361,14 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, map21 = &mapping_21; } - if (igraph_isomorphic_bliss(&self->g, &other->g, 0, 0, &result, map12, map21, - sh1, 0, 0)) { + + int retval = igraph_isomorphic_bliss(&self->g, &other->g, color1, color2, + &result, map12, map21, sh1, 0, 0); + + if (color1) { igraph_vector_int_destroy(color1); free(color1); } + if (color2) { igraph_vector_int_destroy(color2); free(color2); } + + if (retval) { igraphmodule_handle_igraph_error(); return NULL; } @@ -14610,6 +14636,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " non-singleton cell\n\n" " - C{\"fsm\"}: smallest maximally non-trivially connected\n" " non-singleton cell\n\n" + "@param color: optional vector storing a coloring of the vertices\n " + "with respect to which the isomorphism is computed." + "If C{None}, all vertices have the same color.\n" "@return: a permutation vector containing vertex IDs. Vertex 0 in the original\n" " graph will be mapped to an ID contained in the first element of this\n" " vector; vertex 1 will be mapped to the second and so on.\n" @@ -14650,6 +14679,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" "about the BLISS algorithm.\n\n" "@param other: the other graph with which we want to compare the graph.\n" + "@param color1: optional vector storing the coloring of the vertices of\n" + " the first graph. If C{None}, all vertices have the same color.\n" + "@param color2: optional vector storing the coloring of the vertices of\n" + " the second graph. If C{None}, all vertices have the same color.\n" "@param return_mapping_12: if C{True}, calculates the mapping which maps\n" " the vertices of the first graph to the second.\n" "@param return_mapping_21: if C{True}, calculates the mapping which maps\n" From bddbacc3905eca1dc6a20509aa2d42dd5cf5e59e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Nov 2018 12:33:09 +0100 Subject: [PATCH 0047/1892] bytes objects can now be used as vertex names in Python 3.x, closes #196 --- igraph/test/attributes.py | 21 +++++++++++++++++++++ src/py2compat.h | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/igraph/test/attributes.py b/igraph/test/attributes.py index 799869c57..29bd839bf 100644 --- a/igraph/test/attributes.py +++ b/igraph/test/attributes.py @@ -75,6 +75,27 @@ def testVertexNameIndexing(self): del g.vs["name"] self.assertRaises(ValueError, g.degree, [u"bar", u"thud", 0]) + def testVertexNameIndexingBytes(self): + g = Graph.Famous("bull") + g.vs["name"] = [b"foo", b"bar", b"baz", b"fred", b"thud"] + self.assertTrue(g.degree(b"bar") == 3) + self.assertTrue(g.degree([b"bar", b"fred", 0]) == [3, 1, 2]) + g.vs[2]["name"] = b"quack" + self.assertRaises(ValueError, g.degree, b"baz") + self.assertTrue(g.degree(b"quack") == 3) + self.assertRaises(ValueError, g.degree, u"quack") + self.assertRaises(ValueError, g.degree, [u"bar", u"thud", 0]) + del g.vs["name"] + self.assertRaises(ValueError, g.degree, [b"bar", b"thud", 0]) + + def testVertexNameIndexingBug196(self): + g = Graph() + a, b = b'a', b'b' + g.add_vertices([a, b]) + g.add_edges([(a, b)]) + self.assertEqual(g.ecount(), 1) + self.assertTrue(g.are_connected(a, b)) + def testInvalidAttributeNames(self): g = Graph.Famous("bull") for attr_name in [None, 2.654, unittest, str]: diff --git a/src/py2compat.h b/src/py2compat.h index 6d8a5bfb0..d2a5f8a53 100644 --- a/src/py2compat.h +++ b/src/py2compat.h @@ -40,7 +40,7 @@ int PyFile_Close(PyObject* fileObj); /* Python 3.x-specific part follows here */ #define IGRAPH_PYTHON3 -#define PyBaseString_Check(o) PyUnicode_Check(o) +#define PyBaseString_Check(o) PyUnicode_Check(o) || PyBytes_Check(o) PyObject* PyFile_FromObject(PyObject* filename, const char* mode); From 804e489a3b6f37ee159f983a4f4071aba02a2712 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Nov 2018 14:53:27 +0100 Subject: [PATCH 0048/1892] removed two unneeded lines from bytes-typed name attribute handling test --- igraph/test/attributes.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/igraph/test/attributes.py b/igraph/test/attributes.py index 29bd839bf..abc15e7ae 100644 --- a/igraph/test/attributes.py +++ b/igraph/test/attributes.py @@ -83,8 +83,6 @@ def testVertexNameIndexingBytes(self): g.vs[2]["name"] = b"quack" self.assertRaises(ValueError, g.degree, b"baz") self.assertTrue(g.degree(b"quack") == 3) - self.assertRaises(ValueError, g.degree, u"quack") - self.assertRaises(ValueError, g.degree, [u"bar", u"thud", 0]) del g.vs["name"] self.assertRaises(ValueError, g.degree, [b"bar", b"thud", 0]) From 3fec1d71f6d3160dc5416eec9e5ef677e6f9cd00 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 14 Nov 2018 10:41:48 +0100 Subject: [PATCH 0049/1892] skip another graph in graph atlas tests --- igraph/test/atlas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igraph/test/atlas.py b/igraph/test/atlas.py index f0946391f..5580ac53b 100644 --- a/igraph/test/atlas.py +++ b/igraph/test/atlas.py @@ -96,7 +96,7 @@ def testAuthorityScore(self): class GraphAtlasTests(TestBase): graphs = [Graph.Atlas(i) for i in xrange(1253)] - skip_graphs = set([]) + skip_graphs = set([180]) class IsoclassTests(TestBase): graphs = [Graph.Isoclass(3, i, directed=True) for i in xrange(16)] + \ From 4507d9aefd2e939fa515815a87b63c905031de9e Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Sat, 8 Dec 2018 16:28:48 +0100 Subject: [PATCH 0050/1892] Avoid DeprecationWarning when importing SafeConfigParser Closes #202 --- igraph/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igraph/configuration.py b/igraph/configuration.py index 0183aff50..b5eb31762 100644 --- a/igraph/configuration.py +++ b/igraph/configuration.py @@ -29,7 +29,7 @@ """ import sys -if sys.version_info < (3, ): +if sys.version_info < (3, 2): from ConfigParser import SafeConfigParser as ConfigParser else: from configparser import ConfigParser From b570c4c9053cc9f7f7edf58b056fc74739826092 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 26 Dec 2018 14:08:00 +0100 Subject: [PATCH 0051/1892] fix a warning when trying to plot a tuple --- igraph/drawing/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igraph/drawing/__init__.py b/igraph/drawing/__init__.py index 774972cd4..d39109786 100644 --- a/igraph/drawing/__init__.py +++ b/igraph/drawing/__init__.py @@ -263,7 +263,7 @@ def redraw(self, context=None): palette = getattr(obj, "_default_palette", self._palette) plotter = getattr(obj, "__plot__", None) if plotter is None: - warn("%s does not support plotting" % obj) + warn("%s does not support plotting" % (obj, )) else: if opacity < 1.0: ctx.push_group() From 3ff3cc9d518adbf8314df800f27cb78187af761b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 11 Mar 2019 11:09:39 +0100 Subject: [PATCH 0052/1892] fix linter warnings in test/basic.py --- igraph/test/basic.py | 328 +++++++++++++++++++++++++++---------------- 1 file changed, 204 insertions(+), 124 deletions(-) diff --git a/igraph/test/basic.py b/igraph/test/basic.py index feb3dec21..0fe0e8044 100644 --- a/igraph/test/basic.py +++ b/igraph/test/basic.py @@ -1,33 +1,53 @@ import unittest -from igraph import * + +from igraph import ( + ALL, Graph, IN, InternalError, is_degree_sequence, + is_graphical_degree_sequence, Matrix +) class BasicTests(unittest.TestCase): def testGraphCreation(self): g = Graph() self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 0 and g.ecount() == 0 and g.is_directed() == False) - - g=Graph(3, [(0,1), (1,2), (2,0)]) - self.assertTrue(g.vcount() == 3 and g.ecount() == 3 and g.is_directed() == False and g.is_simple() == True) - g=Graph(2, [(0,1), (1,2), (2,3)], True) - self.assertTrue(g.vcount() == 4 and g.ecount() == 3 and g.is_directed() == True and g.is_simple()) - g=Graph([(0,1), (1,2), (2,1)]) - self.assertTrue(g.vcount() == 3 and g.ecount() == 3 and g.is_directed() == False and g.is_simple() == False) - g=Graph([(0,1), (0,0), (1,2)]) - self.assertTrue(g.vcount() == 3 and g.ecount() == 3 and g.is_directed() == False and g.is_simple() == False) - - g=Graph(8, None) + self.assertTrue( + g.vcount() == 0 and g.ecount() == 0 and not g.is_directed() + ) + + g = Graph(3, [(0, 1), (1, 2), (2, 0)]) + self.assertTrue( + g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and + g.is_simple() + ) + + g = Graph(2, [(0, 1), (1, 2), (2, 3)], True) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and + g.is_simple() + ) + + g = Graph([(0, 1), (1, 2), (2, 1)]) + self.assertTrue( + g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and + not g.is_simple() + ) + g = Graph([(0, 1), (0, 0), (1, 2)]) + self.assertTrue( + g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and + not g.is_simple() + ) + + g = Graph(8, None) self.assertEqual(8, g.vcount()) self.assertEqual(0, g.ecount()) self.assertFalse(g.is_directed()) - g=Graph(edges=None) + g = Graph(edges=None) self.assertEqual(0, g.vcount()) self.assertEqual(0, g.ecount()) self.assertFalse(g.is_directed()) - self.assertRaises(TypeError, Graph, edgelist=[(1,2)]) + self.assertRaises(TypeError, Graph, edgelist=[(1, 2)]) def testAddVertex(self): g = Graph() @@ -58,7 +78,9 @@ def testAddVertex(self): vertex = g.add_vertex(name="frob", spam="cheese", ham=42) self.assertTrue(g.vcount() == 5 and g.ecount() == 0) self.assertEquals(4, vertex.index) - self.assertEqual(sorted(g.vertex_attributes()), ["ham", "name", "spam"]) + self.assertEqual( + sorted(g.vertex_attributes()), ["ham", "name", "spam"] + ) self.assertEqual(g.vs["spam"], [None]*4 + ["cheese"]) self.assertEqual(g.vs["ham"], [None]*4 + [42]) @@ -74,7 +96,7 @@ def testAddVertices(self): self.assertEqual(g.vs[2:]["name"], ["spam", "bacon", "eggs"]) def testDeleteVertices(self): - g = Graph([(0,1), (1,2), (2,3), (0,2), (3,4), (4,5)]) + g = Graph([(0, 1), (1, 2), (2, 3), (0, 2), (3, 4), (4, 5)]) self.assertEqual(6, g.vcount()) self.assertEqual(6, g.ecount()) @@ -84,7 +106,7 @@ def testDeleteVertices(self): self.assertEqual(4, g.ecount()) # Delete multiple vertices - g.delete_vertices([1,3]) + g.delete_vertices([1, 3]) self.assertEqual(3, g.vcount()) self.assertEqual(1, g.ecount()) @@ -143,7 +165,9 @@ def testAddEdges(self): g.add_edges([("spam", "eggs"), ("spam", "ham")]) self.assertEqual(g.vcount(), 4) - self.assertEqual(g.get_edgelist(), [(0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3)]) + self.assertEqual(g.get_edgelist(), [ + (0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3) + ]) def testDeleteEdges(self): g = Graph.Famous("petersen") @@ -159,8 +183,10 @@ def testDeleteEdges(self): self.assertEqual(el, g.get_edgelist()) # Deleting multiple edges - g.delete_edges([2,5,7]) - el[7:8] = []; el[5:6] = []; el[2:3] = [] + g.delete_edges([2, 5, 7]) + el[7:8] = [] + el[5:6] = [] + el[2:3] = [] self.assertEqual(11, g.ecount()) self.assertEqual(el, g.get_edgelist()) @@ -177,21 +203,23 @@ def testDeleteEdges(self): self.assertEqual(el, g.get_edgelist()) # Deleting edges by IDs - g.delete_edges([(2,7), (5,8)]) - el[4:5] = []; el[1:2] = [] + g.delete_edges([(2, 7), (5, 8)]) + el[4:5] = [] + el[1:2] = [] self.assertEqual(5, g.ecount()) self.assertEqual(el, g.get_edgelist()) # Deleting edges by names g.delete_edges([("D", "I"), ("G", "I")]) - el[3:4] = []; el[1:2] = [] + el[3:4] = [] + el[1:2] = [] self.assertEqual(3, g.ecount()) self.assertEqual(el, g.get_edgelist()) # Deleting nonexistent edges - self.assertRaises(ValueError, g.delete_edges, [(0,2)]) + self.assertRaises(ValueError, g.delete_edges, [(0, 2)]) self.assertRaises(ValueError, g.delete_edges, [("A", "C")]) - self.assertRaises(ValueError, g.delete_edges, [(0,15)]) + self.assertRaises(ValueError, g.delete_edges, [(0, 15)]) def testGraphGetEid(self): g = Graph.Famous("petersen") @@ -207,75 +235,79 @@ def testGraphGetEid(self): def testGraphGetEids(self): g = Graph.Famous("petersen") - eids = g.get_eids(pairs=[(0,1), (0,5), (1, 6), (4, 9), (8, 6)]) + eids = g.get_eids(pairs=[(0, 1), (0, 5), (1, 6), (4, 9), (8, 6)]) self.assertTrue(eids == [0, 2, 4, 9, 12]) eids = g.get_eids(path=[0, 1, 2, 3, 4]) self.assertTrue(eids == [0, 3, 5, 7]) - eids = g.get_eids(pairs=[(7,9), (9,6)], path = [7, 9, 6]) + eids = g.get_eids(pairs=[(7, 9), (9, 6)], path=[7, 9, 6]) self.assertTrue(eids == [14, 13, 14, 13]) - self.assertRaises(InternalError, g.get_eids, pairs=[(0,1), (0,2)]) + self.assertRaises(InternalError, g.get_eids, pairs=[(0, 1), (0, 2)]) def testAdjacency(self): - g=Graph(4, [(0,1), (1,2), (2,0), (2,3)], directed=True) + g = Graph(4, [(0, 1), (1, 2), (2, 0), (2, 3)], directed=True) self.assertTrue(g.neighbors(2) == [0, 1, 3]) self.assertTrue(g.predecessors(2) == [1]) self.assertTrue(g.successors(2) == [0, 3]) - self.assertTrue(g.get_adjlist() == [[1], [2], [0,3], []]) + self.assertTrue(g.get_adjlist() == [[1], [2], [0, 3], []]) self.assertTrue(g.get_adjlist(IN) == [[2], [0], [1], [2]]) - self.assertTrue(g.get_adjlist(ALL) == [[1,2], [0,2], [0,1,3], [2]]) + self.assertTrue(g.get_adjlist(ALL) == [[1, 2], [0, 2], [0, 1, 3], [2]]) def testEdgeIncidency(self): - g=Graph(4, [(0,1), (1,2), (2,0), (2,3)], directed=True) + g = Graph(4, [(0, 1), (1, 2), (2, 0), (2, 3)], directed=True) self.assertTrue(g.incident(2) == [2, 3]) self.assertTrue(g.incident(2, IN) == [1]) self.assertTrue(g.incident(2, ALL) == [2, 3, 1]) - self.assertTrue(g.get_inclist() == [[0], [1], [2,3], []]) + self.assertTrue(g.get_inclist() == [[0], [1], [2, 3], []]) self.assertTrue(g.get_inclist(IN) == [[2], [0], [1], [3]]) - self.assertTrue(g.get_inclist(ALL) == [[0,2], [1,0], [2,3,1], [3]]) - + self.assertTrue(g.get_inclist(ALL) == [[0, 2], [1, 0], [2, 3, 1], [3]]) def testMultiplesLoops(self): - g=Graph.Tree(7, 2) + g = Graph.Tree(7, 2) # has_multiple self.assertFalse(g.has_multiple()) g.add_vertices(1) - g.add_edges([(0,1), (7,7), (6,6), (6,6), (6,6)]) + g.add_edges([(0, 1), (7, 7), (6, 6), (6, 6), (6, 6)]) # is_loop - self.assertTrue(g.is_loop() == [False, False, False, False, \ - False, False, False, True, True, True, True]) + self.assertTrue(g.is_loop() == [ + False, False, False, False, False, False, False, + True, True, True, True + ]) self.assertTrue(g.is_loop(g.ecount()-2)) - self.assertTrue(g.is_loop(range(6,8)) == [False, True]) + self.assertTrue(g.is_loop(range(6, 8)) == [False, True]) # is_multiple - self.assertTrue(g.is_multiple() == [False, False, False, False, \ - False, False, True, False, False, True, True]) + self.assertTrue(g.is_multiple() == [ + False, False, False, False, False, False, True, + False, False, True, True + ]) # has_multiple self.assertTrue(g.has_multiple()) # count_multiple - self.assertTrue(g.count_multiple() == [2, 1, 1, 1, 1, 1, 2, 1, 3, 3, 3]) + self.assertTrue( + g.count_multiple() == [2, 1, 1, 1, 1, 1, 2, 1, 3, 3, 3] + ) self.assertTrue(g.count_multiple(g.ecount()-1) == 3) - self.assertTrue(g.count_multiple(range(2,5)) == [1, 1, 1]) + self.assertTrue(g.count_multiple(range(2, 5)) == [1, 1, 1]) # check if a mutual directed edge pair is reported as multiple - g=Graph(2, [(0,1), (1,0)], directed=True) + g = Graph(2, [(0, 1), (1, 0)], directed=True) self.assertTrue(g.is_multiple() == [False, False]) - def testPickling(self): import pickle - g=Graph([(0,1), (1,2)]) - g["data"]="abcdef" - g.vs["data"]=[3,4,5] - g.es["data"]=["A", "B"] + g = Graph([(0, 1), (1, 2)]) + g["data"] = "abcdef" + g.vs["data"] = [3, 4, 5] + g.es["data"] = ["A", "B"] g.custom_data = None - pickled=pickle.dumps(g) + pickled = pickle.dumps(g) - g2=pickle.loads(pickled) + g2 = pickle.loads(pickled) self.assertTrue(g["data"] == g2["data"]) self.assertTrue(g.vs["data"] == g2.vs["data"]) self.assertTrue(g.es["data"] == g2.es["data"]) @@ -285,7 +317,7 @@ def testPickling(self): self.assertTrue(g2.custom_data == g.custom_data) def testHashing(self): - g = Graph([(0,1), (1,2)]) + g = Graph([(0, 1), (1, 2)]) self.assertRaises(TypeError, hash, g) def testIteration(self): @@ -295,65 +327,71 @@ def testIteration(self): class DatatypeTests(unittest.TestCase): def testMatrix(self): - m = Matrix([[1,2,3], [4,5], [6,7,8]]) + m = Matrix([[1, 2, 3], [4, 5], [6, 7, 8]]) self.assertTrue(m.shape == (3, 3)) # Reading data - self.assertTrue(m.data == [[1,2,3], [4,5,0], [6,7,8]]) - self.assertTrue(m[1,1] == 5) - self.assertTrue(m[0] == [1,2,3]) - self.assertTrue(m[0,:] == [1,2,3]) - self.assertTrue(m[:,0] == [1,4,6]) - self.assertTrue(m[2,0:2] == [6,7]) - self.assertTrue(m[:,:].data == [[1,2,3], [4,5,0], [6,7,8]]) - self.assertTrue(m[:,1:3].data == [[2,3], [5,0], [7,8]]) + self.assertTrue(m.data == [[1, 2, 3], [4, 5, 0], [6, 7, 8]]) + self.assertTrue(m[1, 1] == 5) + self.assertTrue(m[0] == [1, 2, 3]) + self.assertTrue(m[0, :] == [1, 2, 3]) + self.assertTrue(m[:, 0] == [1, 4, 6]) + self.assertTrue(m[2, 0:2] == [6, 7]) + self.assertTrue(m[:, :].data == [[1, 2, 3], [4, 5, 0], [6, 7, 8]]) + self.assertTrue(m[:, 1:3].data == [[2, 3], [5, 0], [7, 8]]) # Writing data - m[1,1] = 10 - self.assertTrue(m[1,1] == 10) - m[1] = (6,5,4) - self.assertTrue(m[1] == [6,5,4]) - m[1:3] = [[4,5,6], (7,8,9)] - self.assertTrue(m[1:3].data == [[4,5,6], [7,8,9]]) + m[1, 1] = 10 + self.assertTrue(m[1, 1] == 10) + m[1] = (6, 5, 4) + self.assertTrue(m[1] == [6, 5, 4]) + m[1:3] = [[4, 5, 6], (7, 8, 9)] + self.assertTrue(m[1:3].data == [[4, 5, 6], [7, 8, 9]]) # Minimums and maximums self.assertTrue(m.min() == 1) self.assertTrue(m.max() == 9) - self.assertTrue(m.min(0) == [1,2,3]) - self.assertTrue(m.max(0) == [7,8,9]) - self.assertTrue(m.min(1) == [1,4,7]) - self.assertTrue(m.max(1) == [3,6,9]) + self.assertTrue(m.min(0) == [1, 2, 3]) + self.assertTrue(m.max(0) == [7, 8, 9]) + self.assertTrue(m.min(1) == [1, 4, 7]) + self.assertTrue(m.max(1) == [3, 6, 9]) # Special constructors - m=Matrix.Fill(2, (3,3)) - self.assertTrue(m.min() == 2 and m.max() == 2 and m.shape == (3,3)) - m=Matrix.Zero(5, 4) - self.assertTrue(m.min() == 0 and m.max() == 0 and m.shape == (5,4)) - m=Matrix.Identity(3) - self.assertTrue(m.data == [[1,0,0], [0,1,0], [0,0,1]]) - m=Matrix.Identity(3, 2) - self.assertTrue(m.data == [[1,0], [0,1], [0,0]]) + m = Matrix.Fill(2, (3, 3)) + self.assertTrue(m.min() == 2 and m.max() == 2 and m.shape == (3, 3)) + m = Matrix.Zero(5, 4) + self.assertTrue(m.min() == 0 and m.max() == 0 and m.shape == (5, 4)) + m = Matrix.Identity(3) + self.assertTrue(m.data == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + m = Matrix.Identity(3, 2) + self.assertTrue(m.data == [[1, 0], [0, 1], [0, 0]]) # Conversion to string - m=Matrix.Identity(3) + m = Matrix.Identity(3) self.assertTrue(str(m) == "[[1, 0, 0]\n [0, 1, 0]\n [0, 0, 1]]") self.assertTrue(repr(m) == "Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])") class GraphDictListTests(unittest.TestCase): def setUp(self): - self.vertices = [ \ - {"name": "Alice", "age": 48, "gender": "F"}, - {"name": "Bob", "age": 33, "gender": "M"}, - {"name": "Cecil", "age": 45, "gender": "F"}, - {"name": "David", "age": 34, "gender": "M"} + self.vertices = [ + {"name": "Alice", "age": 48, "gender": "F"}, + {"name": "Bob", "age": 33, "gender": "M"}, + {"name": "Cecil", "age": 45, "gender": "F"}, + {"name": "David", "age": 34, "gender": "M"} ] - self.edges = [ \ - {"source": "Alice", "target": "Bob", "friendship": 4, "advice": 4}, - {"source": "Cecil", "target": "Bob", "friendship": 5, "advice": 5}, - {"source": "Cecil", "target": "Alice", "friendship": 5, "advice": 5}, - {"source": "David", "target": "Alice", "friendship": 2, "advice": 4}, - {"source": "David", "target": "Bob", "friendship": 1, "advice": 2} + self.edges = [ + {"source": "Alice", "target": "Bob", "friendship": 4, "advice": 4}, + {"source": "Cecil", "target": "Bob", "friendship": 5, "advice": 5}, + { + "source": "Cecil", "target": "Alice", + "friendship": 5, "advice": 5 + }, + { + "source": "David", "target": "Alice", + "friendship": 2, "advice": 4 + }, + {"source": "David", "target": "Bob", "friendship": 1, "advice": 2} ] def testGraphFromDictList(self): @@ -365,7 +403,9 @@ def testGraphFromDictList(self): def testGraphFromDictIterator(self): g = Graph.DictList(iter(self.vertices), iter(self.edges)) self.checkIfOK(g, "name") - g = Graph.DictList(iter(self.vertices), iter(self.edges), iterative=True) + g = Graph.DictList( + iter(self.vertices), iter(self.edges), iterative=True + ) self.checkIfOK(g, "name") def testGraphFromDictIteratorNoVertices(self): @@ -377,27 +417,39 @@ def testGraphFromDictIteratorNoVertices(self): def testGraphFromDictListExtraVertexName(self): del self.vertices[2:] # No data for "Cecil" and "David" g = Graph.DictList(self.vertices, self.edges) - self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and g.is_directed() == False) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() + ) self.assertTrue(g.vs["name"] == ["Alice", "Bob", "Cecil", "David"]) self.assertTrue(g.vs["age"] == [48, 33, None, None]) self.assertTrue(g.vs["gender"] == ["F", "M", None, None]) self.assertTrue(g.es["friendship"] == [4, 5, 5, 2, 1]) self.assertTrue(g.es["advice"] == [4, 5, 5, 4, 2]) - self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) + self.assertTrue(g.get_edgelist() == [ + (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) + ]) def testGraphFromDictListAlternativeName(self): for vdata in self.vertices: vdata["name_alternative"] = vdata["name"] del vdata["name"] - g = Graph.DictList(self.vertices, self.edges, vertex_name_attr="name_alternative") + g = Graph.DictList( + self.vertices, self.edges, vertex_name_attr="name_alternative" + ) self.checkIfOK(g, "name_alternative") - g = Graph.DictList(self.vertices, self.edges, vertex_name_attr="name_alternative", \ - iterative=True) + g = Graph.DictList( + self.vertices, self.edges, vertex_name_attr="name_alternative", + iterative=True + ) self.checkIfOK(g, "name_alternative") def checkIfOK(self, g, name_attr, check_vertex_attrs=True): - self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and g.is_directed() == False) - self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() + ) + self.assertTrue(g.get_edgelist() == [ + (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) + ]) self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) if check_vertex_attrs: self.assertTrue(g.vs["age"] == [48, 33, 45, 34]) @@ -408,12 +460,12 @@ def checkIfOK(self, g, name_attr, check_vertex_attrs=True): class GraphTupleListTests(unittest.TestCase): def setUp(self): - self.edges = [ \ - ("Alice", "Bob", 4, 4), - ("Cecil", "Bob", 5, 5), - ("Cecil", "Alice", 5, 5), - ("David", "Alice", 2, 4), - ("David", "Bob", 1, 2) + self.edges = [ + ("Alice", "Bob", 4, 4), + ("Cecil", "Bob", 5, 5), + ("Cecil", "Alice", 5, 5), + ("David", "Alice", 2, 4), + ("David", "Bob", 1, 2) ] def testGraphFromTupleList(self): @@ -439,16 +491,24 @@ def testGraphFromTupleListWithWeights(self): self.checkIfOK(g, "name", ("friendship", )) g = Graph.TupleList(self.edges, weights=False) self.checkIfOK(g, "name", ()) - self.assertRaises(ValueError, Graph.TupleList, - [self.edges], weights=True, edge_attrs="friendship") + self.assertRaises( + ValueError, Graph.TupleList, [self.edges], weights=True, + edge_attrs="friendship" + ) def testNoneForMissingAttributes(self): - g = Graph.TupleList(self.edges, edge_attrs=("friendship", "advice", "spam")) + g = Graph.TupleList( + self.edges, edge_attrs=("friendship", "advice", "spam") + ) self.checkIfOK(g, "name", ("friendship", "advice", "spam")) def checkIfOK(self, g, name_attr, edge_attrs): - self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and g.is_directed() == False) - self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() + ) + self.assertTrue(g.get_edgelist() == [ + (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) + ]) self.assertTrue(g.attributes() == []) self.assertTrue(g.vertex_attributes() == [name_attr]) self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) @@ -477,10 +537,14 @@ def testIsDegreeSequence(self): self.assertFalse(is_degree_sequence([2, 1, -2])) self.assertFalse(is_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None)) + self.assertTrue(is_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None + )) self.assertFalse(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], - [4, 3, 2, 3, 4, 4, 2, 2, 4, 2])) + self.assertTrue(is_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], + [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + )) def testIsGraphicalSequence(self): self.assertTrue(is_graphical_degree_sequence([])) @@ -491,14 +555,26 @@ def testIsGraphicalSequence(self): self.assertFalse(is_graphical_degree_sequence([1], [1])) self.assertFalse(is_graphical_degree_sequence([2])) self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1])) - self.assertTrue(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, 2])) + self.assertTrue(is_graphical_degree_sequence( + [2, 1, 1, 1], [1, 1, 1, 2] + )) self.assertFalse(is_graphical_degree_sequence([2, 1, -2])) - self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) - self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None)) - self.assertFalse(is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], - [4, 3, 2, 3, 4, 4, 2, 2, 4, 2])) + self.assertFalse(is_graphical_degree_sequence( + [2, 1, 1, 1], [1, 1, 1, -2] + )) + self.assertTrue(is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3] + )) + self.assertTrue(is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None + )) + self.assertFalse(is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] + )) + self.assertTrue(is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], + [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + )) self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 4])) @@ -538,12 +614,16 @@ def suite(): graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) - return unittest.TestSuite([basic_suite, datatype_suite, graph_dict_list_suite, - graph_tuple_list_suite, degree_sequence_suite, inheritance_suite]) + return unittest.TestSuite([ + basic_suite, datatype_suite, graph_dict_list_suite, + graph_tuple_list_suite, degree_sequence_suite, inheritance_suite + ]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() From 8e8017bd615197d98604676b8f31f85d554a7232 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 11 Mar 2019 11:10:23 +0100 Subject: [PATCH 0053/1892] allow creation of Graph with an edge list that is not a list (but an iterable) --- igraph/test/basic.py | 3 ++- src/graphobject.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/igraph/test/basic.py b/igraph/test/basic.py index 0fe0e8044..66b69b842 100644 --- a/igraph/test/basic.py +++ b/igraph/test/basic.py @@ -31,7 +31,8 @@ def testGraphCreation(self): g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and not g.is_simple() ) - g = Graph([(0, 1), (0, 0), (1, 2)]) + + g = Graph(((0, 1), (0, 0), (1, 2))) self.assertTrue( g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and not g.is_simple() diff --git a/src/graphobject.c b/src/graphobject.c index 3e2db726a..1739bab45 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -206,8 +206,8 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, void* ptr = 0; igraph_vector_t edges_vector; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO!OO!", kwlist, - &n, &PyList_Type, &edges, &dir, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOOO!", kwlist, + &n, &edges, &dir, &PyCapsule_Type, &ptr_o)) return -1; @@ -229,7 +229,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, } else { self->g = *(igraph_t*)ptr; } - } else if (edges && PyList_Check(edges)) { + } else if (edges) { /* Caller specified an edge list, so we use igraph_create */ /* We have to convert the Python list to a igraph_vector_t */ if (igraphmodule_PyObject_to_edgelist(edges, &edges_vector, 0)) { @@ -8361,13 +8361,13 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, map21 = &mapping_21; } - + int retval = igraph_isomorphic_bliss(&self->g, &other->g, color1, color2, &result, map12, map21, sh1, 0, 0); if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } - + if (retval) { igraphmodule_handle_igraph_error(); return NULL; From fd01a22f92fba5837844f3bfb42fe35742c8e353 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 11 Mar 2019 11:18:21 +0100 Subject: [PATCH 0054/1892] igraphmodule_PyObject_to_edgelist(): prepare for cases when we are providing a view only --- src/convert.c | 160 ++++++++++++++++++++++++---------------------- src/convert.h | 19 +++--- src/graphobject.c | 83 +++++++++++++++++------- 3 files changed, 157 insertions(+), 105 deletions(-) diff --git a/src/convert.c b/src/convert.c index 59d989701..2521bb59c 100644 --- a/src/convert.c +++ b/src/convert.c @@ -1,21 +1,21 @@ /* vim:set ts=2 sw=2 sts=2 et: */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -111,7 +111,7 @@ int igraphmodule_PyObject_to_enum(PyObject *o, int *result) { char *s, *s2; int i, best, best_result, best_unique; - + if (o == 0 || o == Py_None) return 0; if (PyInt_Check(o)) @@ -768,7 +768,7 @@ int igraphmodule_PyObject_to_real_t(PyObject *object, igraph_real_t *v) { * don't worry, the typedef is local to this function. */ typedef PyObject PyFloatObject; #endif /* PYPY_VERSION */ - + if (object == NULL) { } else if (PyLong_Check(object)) { double d = PyLong_AsDouble(object); @@ -802,7 +802,7 @@ int igraphmodule_PyObject_to_real_t(PyObject *object, igraph_real_t *v) { * \brief Converts a Python object to an igraph \c igraph_vector_t * The incoming \c igraph_vector_t should be uninitialized. Raises suitable * Python exceptions when needed. - * + * * \param list the Python list to be converted * \param v the \c igraph_vector_t containing the result * \param need_non_negative if true, checks whether all elements are non-negative @@ -864,7 +864,7 @@ int igraphmodule_PyObject_to_vector_t(PyObject *list, igraph_vector_t *v, igraph } Py_DECREF(item); - + if (!ok) { igraph_vector_destroy(v); Py_DECREF(it); @@ -905,7 +905,7 @@ int igraphmodule_PyObject_to_vector_t(PyObject *list, igraph_vector_t *v, igraph * \brief Converts a Python list of floats to an igraph \c igraph_vector_t * The incoming \c igraph_vector_t should be uninitialized. Raises suitable * Python exceptions when needed. - * + * * \param list the Python list to be converted * \param v the \c igraph_vector_t containing the result * \return 0 if everything was OK, 1 otherwise @@ -961,7 +961,7 @@ int igraphmodule_PyObject_float_to_vector_t(PyObject *list, igraph_vector_t *v) } Py_DECREF(item); - + if (!ok) { igraph_vector_destroy(v); Py_DECREF(it); @@ -1039,7 +1039,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v Py_DECREF(item2); } } - + if (ok == 0) { igraph_vector_int_destroy(v); Py_DECREF(item); @@ -1151,7 +1151,7 @@ int igraphmodule_PyObject_to_vector_long_t(PyObject *list, igraph_vector_long_t Py_DECREF(item2); } } - + if (ok == 0) { igraph_vector_long_destroy(v); Py_DECREF(item); @@ -1218,7 +1218,7 @@ int igraphmodule_PyObject_to_vector_long_t(PyObject *list, igraph_vector_long_t * \brief Converts a Python list of objects to an igraph \c igraph_vector_bool_t * The incoming \c igraph_vector_bool_t should be uninitialized. Raises suitable * Python exceptions when needed. - * + * * \param list the Python list to be converted * \param v the \c igraph_vector_bool_t containing the result * \return 0 if everything was OK, 1 otherwise @@ -1281,7 +1281,7 @@ int igraphmodule_PyObject_to_vector_bool_t(PyObject *list, /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_bool_t to a Python boolean list - * + * * \param v the \c igraph_vector_bool_t containing the vector to be converted * \return the Python boolean list as a \c PyObject*, or \c NULL if an * error occurred @@ -1289,7 +1289,7 @@ int igraphmodule_PyObject_to_vector_bool_t(PyObject *list, PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v) { PyObject *list, *item; Py_ssize_t n, i; - + n=igraph_vector_bool_size(v); if (n<0) return igraphmodule_handle_igraph_error(); @@ -1307,7 +1307,7 @@ PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v) { /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_t to a Python integer list - * + * * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer list as a \c PyObject*, or \c NULL if an error occurred */ @@ -1315,7 +1315,7 @@ PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, igraphmodule_conv_t type) { PyObject *list, *item; Py_ssize_t n, i; - + n=igraph_vector_size(v); if (n<0) return igraphmodule_handle_igraph_error(); @@ -1345,14 +1345,14 @@ PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_int_t to a Python integer list - * + * * \param v the \c igraph_vector_int_t containing the vector to be converted * \return the Python integer list as a \c PyObject*, or \c NULL if an error occurred */ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { PyObject *list, *item; Py_ssize_t n, i; - + n = igraph_vector_int_size(v); if (n<0) return igraphmodule_handle_igraph_error(); @@ -1373,14 +1373,14 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_long_t to a Python integer list - * + * * \param v the \c igraph_vector_long_t containing the vector to be converted * \return the Python integer list as a \c PyObject*, or \c NULL if an error occurred */ PyObject* igraphmodule_vector_long_t_to_PyList(const igraph_vector_long_t *v) { PyObject *list, *item; Py_ssize_t n, i; - + n = igraph_vector_long_size(v); if (n<0) return igraphmodule_handle_igraph_error(); @@ -1401,17 +1401,17 @@ PyObject* igraphmodule_vector_long_t_to_PyList(const igraph_vector_long_t *v) { /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_t to a Python integer tuple - * + * * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer tuple as a \c PyObject*, or \c NULL if an error occurred */ PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v) { PyObject* tuple; Py_ssize_t n, i; - + n=igraph_vector_size(v); if (n<0) return igraphmodule_handle_igraph_error(); - + tuple=PyTuple_New(n); for (i=0; i>=1; list=PyList_New(n); - + /* populate the list with data */ for (i=0, j=0; inc) nc=n; } - + igraph_matrix_init(m, nr, nc); for (i=0; ig); Py_DECREF(t); - } - + } + return 0; } /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a single vertex ID - * + * * \param o the Python object * \param vid the vertex ID will be stored here * \param graph the graph that will be used to interpret vertex names @@ -2370,7 +2381,7 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a vertex selector - * + * * \param o the Python object * \param vs the \c igraph_vs_t which will contain the result * \param graph an \c igraph_t object which will be used to interpret vertex @@ -2490,7 +2501,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, if (return_single) *return_single = 0; - + return 0; } @@ -2508,7 +2519,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a single edge ID - * + * * \param o the Python object * \param eid the edge ID will be stored here * \param graph the graph that will be used to interpret vertex names and @@ -2564,7 +2575,7 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g return 1; } else if (graph != 0 && PyTuple_Check(o)) { PyObject *o1, *o2; - + o1 = PyTuple_GetItem(o, 0); if (!o1) return 1; @@ -2603,7 +2614,7 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as an edge selector - * + * * \param o the Python object * \param vs the \c igraph_es_t which will contain the result * \param graph an \c igraph_t object which will be used to interpret vertex @@ -2674,7 +2685,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, IGRAPH_FINALLY_CLEAN(1); return 1; } - + if (igraph_vector_size(&vector) > 0) { igraph_es_vector_copy(es, &vector); } else { @@ -2686,7 +2697,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, if (return_single) *return_single = 0; - + return 0; } @@ -2706,7 +2717,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a numeric attribute value list - * + * * \param o the Python object * \param v the \c igraph_vector_t which will contain the result * \param g a \c igraphmodule_GraphObject object or \c NULL - used when the @@ -2728,7 +2739,7 @@ int igraphmodule_PyObject_to_attribute_values(PyObject *o, long i, n; if (o==NULL) return 1; - + if (o == Py_None) { if (type == ATTRHASH_IDX_VERTEX) n=igraph_vcount(&g->g); else if (type == ATTRHASH_IDX_EDGE) n=igraph_ecount(&g->g); @@ -2905,7 +2916,7 @@ int igraphmodule_i_PyObject_pair_to_attribute_combination_record_t( * \param object the Python object to be converted * \param result the result is returned here. It must be an uninitialized * \c igraph_attribute_combination_t object, it will be initialized accordingly. - * It is the responsibility of the caller to + * It is the responsibility of the caller to * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_attribute_combination_t(PyObject* object, @@ -2967,4 +2978,3 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, return igraphmodule_PyObject_to_enum(o, pagerank_algo_tt, (int*)result); } - diff --git a/src/convert.h b/src/convert.h index f163b17b6..635ddb6a0 100644 --- a/src/convert.h +++ b/src/convert.h @@ -1,21 +1,21 @@ /* -*- mode: C -*- */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -56,7 +56,7 @@ int igraphmodule_PyObject_to_barabasi_algorithm_t(PyObject *o, igraph_barabasi_algorithm_t *result); int igraphmodule_PyObject_to_bliss_sh_t(PyObject *o, igraph_bliss_sh_t *result); int igraphmodule_PyObject_to_community_comparison_t(PyObject *obj, - igraph_community_comparison_t *result); + igraph_community_comparison_t *result); 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); @@ -90,7 +90,10 @@ int igraphmodule_PyObject_to_vector_bool_t(PyObject *list, igraph_vector_bool_t int igraphmodule_PyObject_to_vector_ptr_t(PyObject *list, igraph_vector_ptr_t *v, igraph_bool_t need_non_negative); -int igraphmodule_PyObject_to_edgelist(PyObject *list, igraph_vector_t *v, igraph_t *graph); +int igraphmodule_PyObject_to_edgelist( + PyObject *list, igraph_vector_t *v, igraph_t *graph, + igraph_bool_t *list_is_owned +); int igraphmodule_PyList_to_matrix_t(PyObject *o, igraph_matrix_t *m); PyObject* igraphmodule_strvector_t_to_PyList(igraph_strvector_t *v); @@ -110,7 +113,7 @@ int igraphmodule_PyObject_to_attribute_values(PyObject *o, int type, igraph_real_t def); int igraphmodule_PyObject_to_drl_options_t(PyObject *obj, - igraph_layout_drl_options_t *options); + igraph_layout_drl_options_t *options); int igraphmodule_PyObject_to_attribute_combination_t(PyObject* object, igraph_attribute_combination_t *type); int igraphmodule_PyObject_to_eigen_algorithm_t(PyObject *object, diff --git a/src/graphobject.c b/src/graphobject.c index 1739bab45..eeeaee426 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -205,6 +205,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, PyObject *edges = NULL, *dir = Py_False, *ptr_o = 0; void* ptr = 0; igraph_vector_t edges_vector; + igraph_bool_t edges_vector_owned = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOOO!", kwlist, &n, &edges, &dir, @@ -232,7 +233,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, } else if (edges) { /* Caller specified an edge list, so we use igraph_create */ /* We have to convert the Python list to a igraph_vector_t */ - if (igraphmodule_PyObject_to_edgelist(edges, &edges_vector, 0)) { + if (igraphmodule_PyObject_to_edgelist(edges, &edges_vector, 0, &edges_vector_owned)) { igraphmodule_handle_igraph_error(); return -1; } @@ -240,11 +241,15 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, if (igraph_create (&self->g, &edges_vector, (igraph_integer_t) n, PyObject_IsTrue(dir))) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&edges_vector); + if (edges_vector_owned) { + igraph_vector_destroy(&edges_vector); + } return -1; } - igraph_vector_destroy(&edges_vector); + if (edges_vector_owned) { + igraph_vector_destroy(&edges_vector); + } } else { /* No edge list was specified, and no previously initialized graph object * was fed into our object, so let's use igraph_empty */ @@ -589,21 +594,27 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, { PyObject *list; igraph_vector_t v; + igraph_bool_t v_owned = 0; if (!PyArg_ParseTuple(args, "O", &list)) return NULL; - if (igraphmodule_PyObject_to_edgelist(list, &v, &self->g)) + if (igraphmodule_PyObject_to_edgelist(list, &v, &self->g, &v_owned)) return NULL; /* do the hard work :) */ if (igraph_add_edges(&self->g, &v, 0)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + if (v_owned) { + igraph_vector_destroy(&v); + } return NULL; } - igraph_vector_destroy(&v); + if (v_owned) { + igraph_vector_destroy(&v); + } + Py_RETURN_NONE; } @@ -1433,6 +1444,7 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, PyObject *error = Py_True; PyObject *result = NULL; igraph_vector_t pairs, path, res; + igraph_bool_t pairs_owned = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pairs_o, &path_o, &directed, @@ -1443,7 +1455,7 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); if (pairs_o != Py_None) { - if (igraphmodule_PyObject_to_edgelist(pairs_o, &pairs, &self->g)) { + if (igraphmodule_PyObject_to_edgelist(pairs_o, &pairs, &self->g, &pairs_owned)) { igraph_vector_destroy(&res); return NULL; } @@ -1452,7 +1464,9 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, if (path_o != Py_None) { if (igraphmodule_PyObject_to_vector_t(path_o, &path, 1)) { igraph_vector_destroy(&res); - if (pairs_o != Py_None) igraph_vector_destroy(&pairs); + if (pairs_owned) { + igraph_vector_destroy(&pairs); + } return NULL; } } @@ -1462,14 +1476,22 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, path_o == Py_None ? 0 : &path, PyObject_IsTrue(directed), PyObject_IsTrue(error))) { - if (pairs_o != Py_None) igraph_vector_destroy(&pairs); - if (path_o != Py_None) igraph_vector_destroy(&path); + if (pairs_owned) { + igraph_vector_destroy(&pairs); + } + if (path_o != Py_None) { + igraph_vector_destroy(&path); + } igraph_vector_destroy(&res); return igraphmodule_handle_igraph_error(); } - if (pairs_o != Py_None) igraph_vector_destroy(&pairs); - if (path_o != Py_None) igraph_vector_destroy(&path); + if (pairs_owned) { + igraph_vector_destroy(&pairs); + } + if (path_o != Py_None) { + igraph_vector_destroy(&path); + } result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&res); @@ -1966,6 +1988,7 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, igraph_t g; igraph_vector_bool_t types; igraph_vector_t edges; + igraph_bool_t edges_owned = 0; PyObject *types_o, *edges_o, *directed = Py_False; static char *kwlist[] = { "types", "edges", "directed", NULL }; @@ -1977,19 +2000,23 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, if (igraphmodule_PyObject_to_vector_bool_t(types_o, &types)) return NULL; - if (igraphmodule_PyObject_to_edgelist(edges_o, &edges, 0)) { + if (igraphmodule_PyObject_to_edgelist(edges_o, &edges, 0, &edges_owned)) { igraph_vector_bool_destroy(&types); return NULL; } if (igraph_create_bipartite(&g, &types, &edges, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } igraph_vector_bool_destroy(&types); return NULL; } - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } igraph_vector_bool_destroy(&types); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -5344,8 +5371,9 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, /* Case #2: vertex pairs or edges, returning list */ igraph_vector_t edges; igraph_vector_t res; + igraph_bool_t edges_owned; - if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0)) + if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0, &edges_owned)) return NULL; if (igraph_vector_init(&res, igraph_vector_size(&edges) / 2)) { @@ -5357,12 +5385,16 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, if (igraph_similarity_jaccard_pairs(&self->g, &res, &edges, mode, PyObject_IsTrue(loops))) { igraph_vector_destroy(&res); - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } igraphmodule_handle_igraph_error(); return NULL; } - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); @@ -5425,12 +5457,15 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, /* Case #2: vertex pairs or edges, returning list */ igraph_vector_t edges; igraph_vector_t res; + igraph_bool_t edges_owned; - if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0)) + if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0, &edges_owned)) return NULL; if (igraph_vector_init(&res, igraph_vector_size(&edges) / 2)) { - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } igraphmodule_handle_igraph_error(); return NULL; } @@ -5438,12 +5473,16 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, if (igraph_similarity_dice_pairs(&self->g, &res, &edges, mode, PyObject_IsTrue(loops))) { igraph_vector_destroy(&res); - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } igraphmodule_handle_igraph_error(); return NULL; } - igraph_vector_destroy(&edges); + if (edges_owned) { + igraph_vector_destroy(&edges); + } list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); From fdbf118233d7d690bf91bc799d5e84aaf428ddbf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 11 Mar 2019 12:18:35 +0100 Subject: [PATCH 0055/1892] added support for creating a Graph straight from a NumPy array without copying --- igraph/__init__.py | 19 ++++++++----- igraph/test/basic.py | 38 ++++++++++++++++++++++++++ igraph/utils.py | 63 ++++++++++++++++++++++++++++++++++++-------- src/convert.c | 40 ++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 17 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index 7f8a886be..c7f59ecfe 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -56,7 +56,6 @@ from collections import defaultdict from itertools import izip from shutil import copyfileobj -from tempfile import mkstemp from warnings import warn def deprecated(message): @@ -182,12 +181,11 @@ def __init__(self, *args, **kwds): self.__class__.__name__, unknown_kwds.pop() )) - # If the first argument is a list, assume that the number of vertices - # were omitted + # If the first argument is a list or any other iterable, assume that + # the number of vertices were omitted args = list(args) - if len(args) > 0: - if isinstance(args[0], list) or isinstance(args[0], tuple): - args.insert(0, params[0]) + if len(args) > 0 and hasattr(args[0], "__iter__"): + args.insert(0, params[0]) # Override default parameters from args params[:len(args)] = args @@ -208,6 +206,15 @@ def __init__(self, *args, **kwds): if edges is None: edges = [] + # When 'edges' is a NumPy array or matrix, convert it into a memoryview + # as the lower-level C API works with memoryviews only + try: + from numpy import ndarray, matrix + if isinstance(edges, (ndarray, matrix)): + edges = numpy_to_contiguous_memoryview(edges) + except ImportError: + pass + # Initialize the graph if ptr: GraphBase.__init__(self, __ptr=ptr) diff --git a/igraph/test/basic.py b/igraph/test/basic.py index 66b69b842..ee4d233fd 100644 --- a/igraph/test/basic.py +++ b/igraph/test/basic.py @@ -5,6 +5,11 @@ is_graphical_degree_sequence, Matrix ) +try: + import numpy as np +except ImportError: + np = None + class BasicTests(unittest.TestCase): def testGraphCreation(self): @@ -50,6 +55,39 @@ def testGraphCreation(self): self.assertRaises(TypeError, Graph, edgelist=[(1, 2)]) + @unittest.skipIf(np is None, "test case depends on NumPy") + def testGraphCreationWithNumPy(self): + # NumPy array with integers + arr = np.array([(0, 1), (1, 2), (2, 3)]) + g = Graph(arr, directed=True) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and + g.is_simple() + ) + + # Sliced NumPy array -- the sliced array is non-contiguous but we + # automatically make it so + arr = np.array([(0, 1), (10, 11), (1, 2), (11, 12), (2, 3), (12, 13)]) + g = Graph(arr[::2, :], directed=True) + self.assertTrue( + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and + g.is_simple() + ) + + # 1D NumPy array -- should raise a TypeError because we need a 2D array + arr = np.array([0, 1, 1, 2, 2, 3]) + self.assertRaises(TypeError, Graph, arr) + + # 3D NumPy array -- should raise a TypeError because we need a 2D array + arr = np.array( + [([0, 1], [10, 11]), ([1, 2], [11, 12]), ([2, 3], [12, 13])] + ) + self.assertRaises(TypeError, Graph, arr) + + # NumPy array with strings -- should be a casting error + arr = np.array([("a", "b"), ("c", "d"), ("e", "f")]) + self.assertRaises(ValueError, Graph, arr) + def testAddVertex(self): g = Graph() diff --git a/igraph/utils.py b/igraph/utils.py index 861732f1d..414c963a9 100644 --- a/igraph/utils.py +++ b/igraph/utils.py @@ -7,13 +7,18 @@ from contextlib import contextmanager from collections import MutableMapping +from ctypes import c_double, sizeof from itertools import chain import os import tempfile -__all__ = ["dbl_epsilon", "multidict", "named_temporary_file", "rescale", \ - "safemin", "safemax"] +__all__ = ( + "dbl_epsilon", "multidict", "named_temporary_file", + "numpy_to_contiguous_memoryview", "rescale", + "safemin", "safemax" +) + __docformat__ = "restructuredtext en" __license__ = u"""\ Copyright (C) 2006-2012 Tamás Nepusz @@ -35,6 +40,7 @@ 02110-1301 USA """ + def _is_running_in_ipython(): """Internal function that determines whether igraph is running inside IPython or not.""" @@ -60,8 +66,30 @@ def named_temporary_file(*args, **kwds): finally: os.unlink(tmpfile) -def rescale(values, out_range = (0., 1.), in_range = None, clamp = False, - scale = None): + +def numpy_to_contiguous_memoryview(obj): + """Converts a NumPy array or matrix into a contiguous memoryview object + that is suitable to be forwarded to the Graph constructor. + + This is used internally to allow us to use a NumPy array or matrix + directly when constructing a Graph. + """ + # Deferred import to prevent a hard dependency on NumPy + from numpy import float32, float64, require + + size = sizeof(c_double) + if size == 8: + dtype = float64 + elif size == 4: + dtype = float32 + else: + raise TypeError("size of C double (%d bytes) is not supported" % size) + + return memoryview(require(obj, dtype=dtype, requirements="AC")) + + +def rescale(values, out_range=(0., 1.), in_range=None, clamp=False, + scale=None): """Rescales a list of numbers into a given range. `out_range` gives the range of the output values; by default, the minimum @@ -128,7 +156,10 @@ def rescale(values, out_range = (0., 1.), in_range = None, clamp = False, else: return result -def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False): + +def str_to_orientation( + value, reversed_horizontal=False, reversed_vertical=False +): """Tries to interpret a string as an orientation value. The following basic values are understood: ``left-right``, ``bottom-top``, @@ -151,9 +182,11 @@ def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False if the string cannot be interpreted as an orientation. """ - aliases = {"left-right": "lr", "right-left": "rl", "top-bottom": "tb", - "bottom-top": "bt", "top-down": "tb", "bottom-up": "bt", - "top-bottom": "tb", "bottom-top": "bt", "td": "tb", "bu": "bt"} + aliases = { + "left-right": "lr", "right-left": "rl", "top-bottom": "tb", + "bottom-top": "bt", "top-down": "tb", "bottom-up": "bt", + "top-bottom": "tb", "bottom-top": "bt", "td": "tb", "bu": "bt" + } dir = ["lr", "rl"][reversed_horizontal] aliases.update(horizontal=dir, horiz=dir, h=dir) @@ -206,6 +239,7 @@ def consecutive_pairs(iterable, circular=False): except UnboundLocalError: yield first, first + class multidict(MutableMapping): """A dictionary-like object that is customized to deal with multiple values for the same key. @@ -219,15 +253,18 @@ class multidict(MutableMapping): def __init__(self, *args, **kwds): self._dict = {} if len(args) > 1: - raise ValueError("%r expected at most 1 argument, got %d" % \ - (self.__class__.__name__, len(args))) + raise ValueError( + "%r expected at most 1 argument, got %d" % + (self.__class__.__name__, len(args)) + ) if args: args = args[0] self.update(args) self.update(kwds) def __contains__(self, key): - """Returns whether there are any items associated to the given `key`.""" + """Returns whether there are any items associated to the given + `key`.""" try: return len(self._dict[key]) > 0 except KeyError: @@ -333,6 +370,7 @@ def update(self, arg, **kwds): for key, value in kwds.iteritems(): self.add(key, value) + def safemax(iterable, default=0): """Safer variant of ``max()`` that returns a default value if the iterable is empty. @@ -354,6 +392,7 @@ def safemax(iterable, default=0): else: return max(chain([first], it)) + def safemin(iterable, default=0): """Safer variant of ``min()`` that returns a default value if the iterable is empty. @@ -375,6 +414,7 @@ def safemin(iterable, default=0): else: return min(chain([first], it)) + def dbl_epsilon(): """Approximates the machine epsilon value for doubles.""" epsilon = 1.0 @@ -382,4 +422,5 @@ def dbl_epsilon(): epsilon /= 2 return epsilon + dbl_epsilon = dbl_epsilon() diff --git a/src/convert.c b/src/convert.c index 2521bb59c..947ba6789 100644 --- a/src/convert.c +++ b/src/convert.c @@ -1483,6 +1483,7 @@ int igraphmodule_PyObject_to_edgelist( igraph_bool_t* list_is_owned ) { PyObject *item, *i1, *i2, *it; + Py_buffer *buffer; int ok; igraph_integer_t idx1=0, idx2=0; @@ -1493,6 +1494,45 @@ int igraphmodule_PyObject_to_edgelist( return 1; } + /* We also accept a memoryview, although we don't advertise that in the + * public API yet as the exact layout of the memory area has to match the + * way items are laid out in an igraph_vector_t, and that's an implementation + * detail that we don't want to commit ourselves to */ + if (PyMemoryView_Check(list)) { + buffer = PyMemoryView_GET_BUFFER(list); + + if (buffer->itemsize != sizeof(igraph_real_t)) { + PyErr_SetString( + PyExc_TypeError, "item size of buffer must match the size of igraph_real_t" + ); + return 1; + } + + if (buffer->ndim != 2) { + PyErr_SetString(PyExc_TypeError, "edge list buffers must be two-dimensional"); + return 1; + } + + if (buffer->shape[1] != 2) { + PyErr_SetString(PyExc_TypeError, "edge list buffers must have two columns"); + return 1; + } + + if (buffer->strides[0] != 2 * buffer->itemsize || + buffer->strides[1] != buffer->itemsize) { + PyErr_SetString(PyExc_TypeError, "edge list buffers must be contiguous"); + return 1; + } + + igraph_vector_view(v, buffer->buf, buffer->len / buffer->itemsize); + + if (list_is_owned) { + *list_is_owned = 0; + } + + return 0; + } + it = PyObject_GetIter(list); if (!it) return 1; From 1a74749ac7d320cfcdf6ee4fd7646c98189746e3 Mon Sep 17 00:00:00 2001 From: Martino Mensio Date: Mon, 13 May 2019 16:11:04 +0100 Subject: [PATCH 0056/1892] tutorial fix: the graph is empty at the beginning --- doc/source/tutorial.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 40ff2987a..3054662e6 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -110,9 +110,9 @@ user-friendly output, we can try to print the graph using Python's >>> print(g) IGRAPH U--- 0 0 -- -TODO: explain it +This summary consists of `IGRAPH`, followed by a four-character long code, the number of vertices, the number of edges, two dashes (`--`) and the name of the graph (i.e. the contents of the `name` attribute, if any) -This is not too exciting so far; a graph with a single vertex and no edges is not really useful +This is not too exciting so far; a graph with no vertices and no edges is not really useful for us. Let's add some vertices first! >>> g.add_vertices(3) @@ -560,7 +560,7 @@ There are also a few special structural properties for selecting edges: originating from Claire (who has vertex index 2): >>> g.es.select(_source=2) - + - Using ``_target`` or ``_to`` filters based on the target vertices. This is different from ``_source`` and ``_from`` if the graph is directed. @@ -1047,4 +1047,3 @@ list`_ - maybe there is someone out there who can help you out immediately. .. _API documentation: http://igraph.org/python/doc/igraph-module.html .. _Graph class: http://igraph.org/python/doc/igraph.Graph-class.html .. _igraph mailing list: http://lists.nongnu.org/mailman/listinfo/igraph-help - From 90dc14b5b0da6139c1ceccaff64fff6671456a17 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Fri, 7 Jun 2019 22:44:25 -0500 Subject: [PATCH 0057/1892] Fixed typo in setup.py error message --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1ed96b7d9..830668035 100644 --- a/setup.py +++ b/setup.py @@ -811,7 +811,7 @@ def use_educated_guess(self): print("WARNING: we were not able to detect where igraph is installed on") print("your machine (if it is installed at all). We will use the fallback") - print("library and include pathss hardcoded in setup.py and hope that the") + print("library and include paths hardcoded in setup.py and hope that the") print("C core of igraph is installed there.") print("") print("If the compilation fails and you are sure that igraph is installed") From ad1b806609ac176487475afa1b8c8d828fb8bca2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Jun 2019 14:07:16 +0200 Subject: [PATCH 0058/1892] remove reference to unimplemented function igraphmodule_Graph_community_leading_eigenvector_naive, fixes #227 --- src/graphobject.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graphobject.h b/src/graphobject.h index 618a8d1de..0dcfd7ac4 100644 --- a/src/graphobject.h +++ b/src/graphobject.h @@ -216,7 +216,6 @@ PyObject* igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject* self PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_community_label_propagation(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_leading_eigenvector_naive(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject *igraphmodule_Graph_community_optimal_modularity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); From 665802171b18a28427bf2d6f74ae9e3bcd7b0948 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jun 2019 10:17:14 +0200 Subject: [PATCH 0059/1892] added Python 3.7 for CI tests, removed Python 3.4 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 338c9b93e..a1b97e058 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py34, py35, py36, pypy, pypy3 +envlist = py27, py35, py36, py37, pypy, pypy3 [testenv] commands = From f34ed668ab12f3bf34e5c6ca25a508e1a1fe1ef5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jun 2019 10:28:46 +0200 Subject: [PATCH 0060/1892] added Python 3.7 for CI tests, removed Python 3.4; really :) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f8bfc7117..e15de2fc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: python python: - "2.7" - - "3.4" - "3.5" - "3.6" + - "3.7" - "pypy" - "pypy3" From f011a8bdb63bda634bffb066ef299ad4204bef02 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jun 2019 10:37:56 +0200 Subject: [PATCH 0061/1892] Travis needs Ubuntu Xenial to test Python 3.7 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e15de2fc9..bab4c3581 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +dist: xenial language: python python: From f9c4b51d37e8cec8ee076ce24aecba7753c78812 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jun 2019 10:54:53 +0200 Subject: [PATCH 0062/1892] trying to obtain more debug info for failing Travis test --- igraph/formula.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igraph/formula.py b/igraph/formula.py index ac4fb994c..9dcab911e 100644 --- a/igraph/formula.py +++ b/igraph/formula.py @@ -86,7 +86,7 @@ def generate_edges(formula): # End markers are fine pass else: - msg = "invalid token found in edge specification: %s" % formula + msg = "invalid token found in edge specification: %s; token_type=%r; tok=%r" % (formula, token_type, tok) raise SyntaxError(msg) else: # We are parsing an edge operator From 516a2ecf12edc538af770ebc5e38d4bef15d8004 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jun 2019 12:59:53 +0200 Subject: [PATCH 0063/1892] trying to fix graph formula parsing for Python 3.5 and 3.6 --- igraph/formula.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/igraph/formula.py b/igraph/formula.py index 9dcab911e..75eb33506 100644 --- a/igraph/formula.py +++ b/igraph/formula.py @@ -82,6 +82,9 @@ def generate_edges(formula): elif tok == ":" and token_type == token.OP: # Separating semicolon between vertex names, we just go on continue + elif token_type == token.NEWLINE: + # Newlines are fine + pass elif token_type == token.ENDMARKER: # End markers are fine pass From 83a218e5603d03f3c3fa2903f6a604b729e8ee34 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Jun 2019 13:38:34 +0200 Subject: [PATCH 0064/1892] replaced sprintf() with snprintf() in error and warning handlers --- src/error.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/error.c b/src/error.c index 3f677b282..bb99960b8 100644 --- a/src/error.c +++ b/src/error.c @@ -58,7 +58,7 @@ PyObject* igraphmodule_handle_igraph_error() void igraphmodule_igraph_warning_hook(const char *reason, const char *file, int line, int igraph_errno) { char buf[4096]; - sprintf(buf, "%s at %s:%i", reason, file, line); + snprintf(buf, sizeof(buf), "%s at %s:%i", reason, file, line); PyErr_Warn(PyExc_RuntimeWarning, buf); } @@ -77,7 +77,7 @@ void igraphmodule_igraph_error_hook(const char *reason, const char *file, if (igraph_errno == IGRAPH_ENOMEM) exc = PyExc_MemoryError; - sprintf(buf, "Error at %s:%i: %s, %s", file, line, reason, + snprintf(buf, sizeof(buf), "Error at %s:%i: %s, %s", file, line, reason, igraph_strerror(igraph_errno)); IGRAPH_FINALLY_FREE(); From 5db51d9d7bcd55e8707ad935ce4a000ec09c8747 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 Jun 2019 16:28:20 +0200 Subject: [PATCH 0065/1892] replaced urlretrieve() with urlopen() in setup script, fixes #206 --- setup.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/setup.py b/setup.py index 830668035..1b7f70c4c 100644 --- a/setup.py +++ b/setup.py @@ -193,7 +193,9 @@ def execute(self): import tarfile import tempfile +from contextlib import closing from select import select +from shutil import copyfileobj try: from urllib import urlretrieve @@ -380,11 +382,9 @@ class IgraphCCoreBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet.""" - def __init__(self, versions_to_try, remote_url=None, - show_progress_bar=True, tmproot=None): + def __init__(self, versions_to_try, remote_url=None, tmproot=None): self.versions_to_try = versions_to_try self.remote_url = remote_url - self.show_progress_bar = show_progress_bar self.tmproot = tmproot self._tmpdir = None @@ -432,12 +432,10 @@ def _progress_hook(count, block_size, total_size): local_file_full_path = os.path.join(self.tmpdir, local_file) # Download the C core - if self.show_progress_bar: - urlretrieve(remote_url, local_file_full_path, reporthook=_progress_hook) - print("") - else: - print("Downloading %s... " % local_file) - urlretrieve(remote_url, local_file_full_path) + print("Downloading %s... " % local_file) + in_stream = urlopen(remote_url) + with open(local_file_full_path, "wb") as out_file: + copyfileobj(in_stream, out_file) # Extract it in the temporary directory print("Extracting %s..." % local_file) @@ -566,7 +564,6 @@ def __init__(self): self.extra_compile_args = [] self.extra_link_args = [] self.extra_objects = [] - self.show_progress_bar = True self.static_extension = False self.download_igraph_if_needed = True self.use_pkgconfig = True @@ -701,8 +698,7 @@ def download_and_compile_igraph(self): print("We will also try: %s" % ", ".join(self.c_core_versions[1:])) print("") - igraph_builder = IgraphCCoreBuilder(self.c_core_versions, self.c_core_url, - show_progress_bar=self.show_progress_bar) + igraph_builder = IgraphCCoreBuilder(self.c_core_versions, self.c_core_url) if not igraph_builder.run(): print("Could not download and compile the C core of igraph.") print("") @@ -747,9 +743,6 @@ def process_args_from_command_line(self): elif option == "--no-pkg-config": opts_to_remove.append(idx) self.use_pkgconfig = False - elif option == "--no-progress-bar": - opts_to_remove.append(idx) - self.show_progress_bar = False elif option == "--no-wait": opts_to_remove.append(idx) self.wait = False From b44f51517491b6ddef5e55bd6e49c91accd37232 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 2 Aug 2019 18:21:10 +0200 Subject: [PATCH 0066/1892] added Graph.to_prufer(), fixes #233 --- src/graphobject.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/graphobject.c b/src/graphobject.c index eeeaee426..cc7ec747e 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -1826,6 +1826,32 @@ PyObject *igraphmodule_Graph_radius(igraphmodule_GraphObject * self, return PyFloat_FromDouble((double)radius); } +/** \ingroup python_interface_graph + * \brief Converts a tree graph into a Prufer sequence + * \return the Prufer sequence as a Python object + * \sa igraph_to_prufer + */ +PyObject *igraphmodule_Graph_to_prufer(igraphmodule_GraphObject * self) +{ + igraph_vector_int_t result; + PyObject *list; + + if (igraph_vector_int_init(&result, 0)) { + return NULL; + } + + if (igraph_to_prufer(&self->g, &result)) { + igraphmodule_handle_igraph_error(); + igraph_vector_int_destroy(&result); + return NULL; + } + + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); + + return list; +} + /********************************************************************** * Deterministic and non-deterministic graph generators * **********************************************************************/ @@ -13620,6 +13646,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " successors. If L{IN}, all vertices come before their ancestors.\n" "@return: a possible topological ordering as a list"}, + /* interface to to_prufer */ + {"to_prufer", + (PyCFunction) igraphmodule_Graph_to_prufer, + METH_NOARGS, + "to_prufer()\n\n" + "Converts a tree graph into a Prufer sequence.\n\n" + "@return: the Prufer sequence as a list" + }, + // interface to igraph_transitivity_undirected {"transitivity_undirected", (PyCFunction) igraphmodule_Graph_transitivity_undirected, From be3ff2d2a1f7cb75cccfe885b99cc8935d5811b2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 13 Aug 2019 09:44:08 +0200 Subject: [PATCH 0067/1892] quick fix for API breakage in igraph_avg_nearest_neighbor_degree(), refs #236 --- src/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphobject.c b/src/graphobject.c index cc7ec747e..7797bd69d 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -1761,7 +1761,7 @@ PyObject *igraphmodule_Graph_knn(igraphmodule_GraphObject *self, return NULL; } - if (igraph_avg_nearest_neighbor_degree(&self->g, vids, &knn, &knnk, weights)) { + if (igraph_avg_nearest_neighbor_degree(&self->g, vids, IGRAPH_ALL, IGRAPH_ALL, &knn, &knnk, weights)) { igraphmodule_handle_igraph_error(); igraph_vs_destroy(&vids); igraph_vector_destroy(&knn); From 2c0e8ab028196c0fa6ad75d58cbd8181e27aa526 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 13 Aug 2019 22:11:32 +0200 Subject: [PATCH 0068/1892] setup.py: changed build folder of igraph to vendor/build/igraph This folder is used when igraph is downloaded and compiled during the invocation of setup.py. The whole thing might be deprecated in the future, but currently my focus is to switch to git submodules and the first step is to clean up the root folder a bit. As a side effect, the entire setup.py was reformatted with Black. --- setup.py | 313 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 201 insertions(+), 112 deletions(-) diff --git a/setup.py b/setup.py index 1b7f70c4c..a9f90752a 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ ########################################################################### # Global version number. Keep the format of the next line intact. -VERSION = '0.7.1.post6' +VERSION = "0.7.1.post6" # Check Python's version info and exit early if it is too old if sys.version_info < (2, 5): @@ -30,6 +30,7 @@ ## Here be ugly workarounds. These must be run before setuptools ## is imported. + class Workaround(object): """Base class for platform-specific workarounds and hacks that are needed to get the Python interface compile with as little user @@ -58,15 +59,19 @@ def _extend_compiler_customization(self, func): and ``setuptools.command.build_ext.customize_compiler`` with new, user-defined code at the end.""" from distutils import sysconfig + old_func = sysconfig.customize_compiler + def replaced(*args, **kwds): old_func(*args, **kwds) return func(*args, **kwds) + self._replace_compiler_customization_distutils(replaced) self._replace_compiler_customization_setuptools(replaced) def _replace_compiler_customization_distutils(self, new_func): from distutils import ccompiler, sysconfig + sysconfig.customize_compiler = new_func ccompiler.customize_compiler = new_func @@ -104,6 +109,7 @@ class OSXAnacondaPythonIconvWorkaround(Workaround): def required(self): from distutils.spawn import find_executable + if not sys.platform.startswith("darwin"): return False if "Anaconda" not in sys.version: @@ -132,14 +138,22 @@ def fix_install_name(self, cfg): for outputfile in cfg.get_outputs(): lines, retcode = get_output(["otool", "-L", outputfile]) if retcode: - raise OSError("otool -L %s failed with error code: %s" % (outputfile, retcode)) + raise OSError( + "otool -L %s failed with error code: %s" % (outputfile, retcode) + ) for line in lines.split("\n"): if "libxml2" in line: libname = line.strip().split(" ")[0] - subprocess.call(["install_name_tool", "-change", - libname, "@rpath/" + os.path.basename(libname), - outputfile]) + subprocess.call( + [ + "install_name_tool", + "-change", + libname, + "@rpath/" + os.path.basename(libname), + outputfile, + ] + ) class ContinuousIntegrationSetup(Workaround): @@ -164,11 +178,13 @@ def execute(self): self.executed.append(workaround) -workarounds = WorkaroundSet([ - OSXClangAndSystemPythonWorkaround, - OSXAnacondaPythonIconvWorkaround, - ContinuousIntegrationSetup -]) +workarounds = WorkaroundSet( + [ + OSXClangAndSystemPythonWorkaround, + OSXAnacondaPythonIconvWorkaround, + ContinuousIntegrationSetup, + ] +) workarounds.execute() ########################################################################### @@ -176,9 +192,11 @@ def execute(self): try: from setuptools import setup from setuptools.command.build_ext import build_ext + build_py = None except ImportError: from distutils.core import setup + try: from distutils.command.build_py import build_py_2to3 as build_py except ImportError: @@ -210,35 +228,40 @@ def execute(self): ########################################################################### -LIBIGRAPH_FALLBACK_INCLUDE_DIRS = ['/usr/include/igraph', '/usr/local/include/igraph'] -LIBIGRAPH_FALLBACK_LIBRARIES = ['igraph'] +LIBIGRAPH_FALLBACK_INCLUDE_DIRS = ["/usr/include/igraph", "/usr/local/include/igraph"] +LIBIGRAPH_FALLBACK_LIBRARIES = ["igraph"] LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [] ########################################################################### + def cleanup_tmpdir(dirname): """Removes the given temporary directory if it exists.""" if dirname is not None and os.path.exists(dirname): shutil.rmtree(dirname) + def create_dir_unless_exists(*args): """Creates a directory unless it exists already.""" path = os.path.join(*args) if not os.path.isdir(path): os.makedirs(path) + def ensure_dir_does_not_exist(*args): """Ensures that the given directory does not exist.""" path = os.path.join(*args) if os.path.isdir(path): shutil.rmtree(path) + def exclude_from_list(items, items_to_exclude): """Excludes certain items from a list, keeping the original order of the remaining items.""" itemset = set(items_to_exclude) return [item for item in items if item not in itemset] + def find_static_library(library_name, library_path): """Given the raw name of a library in `library_name`, tries to find a static library with this name in the given `library_path`. `library_path` @@ -247,8 +270,14 @@ def find_static_library(library_name, library_path): variants = ["lib{0}.a", "{0}.a", "{0}.lib", "lib{0}.lib"] if is_unix_like(): - extra_libdirs = ["/usr/local/lib64", "/usr/local/lib", - "/usr/lib64", "/usr/lib", "/lib64", "/lib"] + extra_libdirs = [ + "/usr/local/lib64", + "/usr/local/lib", + "/usr/lib64", + "/usr/lib", + "/lib64", + "/lib", + ] else: extra_libdirs = [] @@ -262,6 +291,7 @@ def find_static_library(library_name, library_path): if os.path.isfile(full_path): return full_path + def find_temporary_directory(): """Finds a suitable temporary directory where the installer can download the C core of igraph if needed and returns its full path.""" @@ -277,12 +307,14 @@ def find_temporary_directory(): result = os.path.join(os.path.dirname(script_file), "tmp") return os.path.abspath(result) + def first(iterable): """Returns the first element from the given iterable.""" for item in iterable: return item raise ValueError("iterable is empty") + def get_output(args, encoding="utf-8"): """Returns the output of a command returning a single line of output.""" PIPE = subprocess.PIPE @@ -299,6 +331,7 @@ def get_output(args, encoding="utf-8"): stderr = str(stderr, encoding=encoding) return stdout, returncode + def get_output_single_line(args, encoding="utf-8"): """Returns the output of a command returning a single line of output, stripped from any trailing newlines.""" @@ -309,27 +342,35 @@ def get_output_single_line(args, encoding="utf-8"): line = None return line, returncode + def http_url_exists(url): """Returns whether the given HTTP URL 'exists' in the sense that it is returning an HTTP error code or not. A URL is considered to exist if it does not return an HTTP error code.""" + class HEADRequest(Request): def get_method(self): return "HEAD" + try: response = urlopen(HEADRequest(url)) return True except URLError: return False + def is_unix_like(platform=None): """Returns whether the given platform is a Unix-like platform with the usual Unix filesystem. When the parameter is omitted, it defaults to ``sys.platform`` """ platform = platform or sys.platform platform = platform.lower() - return platform.startswith("linux") or platform.startswith("darwin") or \ - platform.startswith("cygwin") + return ( + platform.startswith("linux") + or platform.startswith("darwin") + or platform.startswith("cygwin") + ) + def preprocess_fallback_config(): """Preprocesses the fallback include and library paths depending on the @@ -338,23 +379,35 @@ def preprocess_fallback_config(): global LIBIGRAPH_FALLBACK_LIBRARY_DIRS global LIBIGRAPH_FALLBACK_LIBRARIES - if os.name == 'nt' and distutils.ccompiler.get_default_compiler() == 'msvc': + if os.name == "nt" and distutils.ccompiler.get_default_compiler() == "msvc": # if this setup is run in the source checkout *and* the igraph msvc was build, # this code adds the right library and include dir - all_msvc_dirs = glob.glob(os.path.join('..', '..', 'igraph-*-msvc')) + all_msvc_dirs = glob.glob(os.path.join("..", "..", "igraph-*-msvc")) if len(all_msvc_dirs) > 0: if len(all_msvc_dirs) > 1: - print("More than one MSVC build directory (..\\..\\igraph-*-msvc) found!") - print("It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n") + print( + "More than one MSVC build directory (..\\..\\igraph-*-msvc) found!" + ) + print( + "It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n" + ) msvc_builddir = all_msvc_dirs[-1] if not os.path.exists(os.path.join(msvc_builddir, "Release")): - print("There is no 'Release' dir in the MSVC build directory\n(%s)" % msvc_builddir) + print( + "There is no 'Release' dir in the MSVC build directory\n(%s)" + % msvc_builddir + ) print("Please build the MSVC build first!\n") else: print("Using MSVC build dir as a fallback: %s\n\n" % msvc_builddir) - LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [os.path.join(msvc_builddir, "include")] - LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [os.path.join(msvc_builddir, "Release")] + LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [ + os.path.join(msvc_builddir, "include") + ] + LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [ + os.path.join(msvc_builddir, "Release") + ] + def version_variants(version): """Given an igraph version number, returns a list of possible version @@ -376,8 +429,10 @@ def version_variants(version): return result + ########################################################################### + class IgraphCCoreBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet.""" @@ -409,15 +464,19 @@ def _progress_hook(count, block_size, total_size): else: percentage = count * block_size * 100.0 / total_size percentage = min(percentage, 100.0) - sys.stdout.write("\rDownloading %s... %.2f%%" % (local_file, percentage)) + sys.stdout.write( + "\rDownloading %s... %.2f%%" % (local_file, percentage) + ) sys.stdout.flush() # Determine the remote URL if needed if self.remote_url is None: self.version, remote_url = self.find_first_version() if not self.version: - print("Version %s of the C core of igraph is not found among the " - "nightly builds." % self.versions_to_try[0]) + print( + "Version %s of the C core of igraph is not found among the " + "nightly builds." % self.versions_to_try[0] + ) print("Use the --c-core-version switch to try a different version.") print("") return False @@ -458,8 +517,10 @@ def _progress_hook(count, block_size, total_size): break if not self.builddir: - print("Downloaded tarball did not contain a directory whose name " - "started with igraph; giving up build.") + print( + "Downloaded tarball did not contain a directory whose name " + "started with igraph; giving up build." + ) return False # Try to compile @@ -481,13 +542,17 @@ def _progress_hook(count, block_size, total_size): with open("ltmain.sh.new", "w") as outfp: for line in infp: if line.endswith("cd $darwin_orig_dir\n"): - line = line.replace("cd $darwin_orig_dir\n", "cd \"$darwin_orig_dir\"\n") + line = line.replace( + "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' + ) outfp.write(line) os.rename("ltmain.sh.new", "ltmain.sh") print("Configuring igraph...") - retcode = subprocess.call(["./configure", "--disable-tls", "--disable-gmp"], - env=self.enhanced_env(CFLAGS='-fPIC', CXXFLAGS='-fPIC')) + retcode = subprocess.call( + ["./configure", "--disable-tls", "--disable-gmp"], + env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), + ) if retcode: return False @@ -500,7 +565,9 @@ def _progress_hook(count, block_size, total_size): for line in open(os.path.join(self.builddir, "igraph.pc")): if line.startswith("Libs: ") or line.startswith("Libs.private: "): words = line.strip().split() - libraries.extend(word[2:] for word in words if word.startswith("-l")) + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) if not libraries: # Educated guess @@ -509,17 +576,20 @@ def _progress_hook(count, block_size, total_size): finally: os.chdir(cwd) - # Compilation succeeded; copy everything into igraphcore - create_dir_unless_exists("igraphcore") - ensure_dir_does_not_exist("igraphcore", "include") - ensure_dir_does_not_exist("igraphcore", "lib") - shutil.copytree(os.path.join(self.builddir, "include"), - os.path.join("igraphcore", "include")) - shutil.copytree(os.path.join(self.builddir, "src", ".libs"), - os.path.join("igraphcore", "lib")) - f = open(os.path.join("igraphcore", "build.cfg"), "w") - f.write(repr(libraries)) - f.close() + # Compilation succeeded; copy everything into vendor/build/igraph + create_dir_unless_exists("vendor", "build", "igraph") + ensure_dir_does_not_exist("vendor", "build", "igraph", "include") + ensure_dir_does_not_exist("vendor", "build", "igraph", "lib") + shutil.copytree( + os.path.join(self.builddir, "include"), + os.path.join("vendor", "build", "igraph", "include"), + ) + shutil.copytree( + os.path.join(self.builddir, "src", ".libs"), + os.path.join("vendor", "build", "igraph", "lib"), + ) + with open(os.path.join("vendor", "build", "igraph", "build.cfg"), "w") as f: + f.write(repr(libraries)) return True @@ -581,7 +651,7 @@ def has_pkgconfig(self): if self._has_pkgconfig is None: if self.use_pkgconfig: line, exit_code = get_output_single_line(["pkg-config", "igraph"]) - self._has_pkgconfig = (exit_code == 0) + self._has_pkgconfig = exit_code == 0 else: self._has_pkgconfig = False return self._has_pkgconfig @@ -598,6 +668,7 @@ def build_ext(self): from distutils.sysconfig import get_python_inc buildcfg = self + class custom_build_ext(build_ext): def run(self): # Bail out if we don't have the Python include files @@ -613,9 +684,9 @@ def run(self): detected = False # Check whether we have already compiled igraph in a previous run. - # If so, it should be found in igraphcore/include and - # igraphcore/lib - if os.path.exists("igraphcore"): + # If so, it should be found in vendor/build/igraph/include and + # vendor/build/igraph/lib + if os.path.exists(os.path.join("vendor", "build", "igraph")): buildcfg.use_built_igraph() detected = True @@ -643,8 +714,11 @@ def run(self): # Prints basic build information buildcfg.print_build_info() - ext = first(extension for extension in self.extensions - if extension.name == "igraph._igraph") + ext = first( + extension + for extension in self.extensions + if extension.name == "igraph._igraph" + ) buildcfg.configure(ext) # Run any pre-build hooks @@ -662,8 +736,12 @@ def run(self): def configure(self, ext): """Configures the given Extension object using this build configuration.""" - ext.include_dirs = exclude_from_list(self.include_dirs, self.excluded_include_dirs) - ext.library_dirs = exclude_from_list(self.library_dirs, self.excluded_library_dirs) + ext.include_dirs = exclude_from_list( + self.include_dirs, self.excluded_include_dirs + ) + ext.library_dirs = exclude_from_list( + self.library_dirs, self.excluded_library_dirs + ) ext.runtime_library_dirs = self.runtime_library_dirs ext.libraries = self.libraries ext.extra_compile_args = self.extra_compile_args @@ -749,22 +827,22 @@ def process_args_from_command_line(self): elif option.startswith("--c-core-version"): opts_to_remove.append(idx) if option == "--c-core-version": - value = sys.argv[idx+1] - opts_to_remove.append(idx+1) + value = sys.argv[idx + 1] + opts_to_remove.append(idx + 1) else: value = option.split("=", 1)[1] self.c_core_versions = [value] elif option.startswith("--c-core-url"): opts_to_remove.append(idx) if option == "--c-core-url": - value = sys.argv[idx+1] - opts_to_remove.append(idx+1) + value = sys.argv[idx + 1] + opts_to_remove.append(idx + 1) else: value = option.split("=", 1)[1] self.c_core_url = value for idx in reversed(opts_to_remove): - sys.argv[idx:(idx+1)] = [] + sys.argv[idx : (idx + 1)] = [] def replace_static_libraries(self, exclusions=None): """Replaces references to libraries with full paths to their static @@ -782,13 +860,13 @@ def replace_static_libraries(self, exclusions=None): self.extra_objects.append(static_lib) def use_built_igraph(self): - """Assumes that igraph is built already in ``igraphcore`` and sets up + """Assumes that igraph is built already in ``vendor/build/igraph`` and sets up the include and library paths and the library names accordingly.""" - buildcfg.include_dirs = [os.path.join("igraphcore", "include")] - buildcfg.library_dirs = [os.path.join("igraphcore", "lib")] + buildcfg.include_dirs = [os.path.join("vendor", "build", "igraph", "include")] + buildcfg.library_dirs = [os.path.join("vendor", "build", "igraph", "lib")] buildcfg.static_extension = True - buildcfg_file = os.path.join("igraphcore", "build.cfg") + buildcfg_file = os.path.join("vendor", "build", "igraph", "build.cfg") if os.path.exists(buildcfg_file): buildcfg.libraries = eval(open(buildcfg_file).read()) @@ -822,8 +900,10 @@ def use_educated_guess(self): else: plural = "" - sys.stdout.write("\rContinuing in %2d second%s; press Enter to continue " - "immediately. " % (seconds_remaining, plural)) + sys.stdout.write( + "\rContinuing in %2d second%s; press Enter to continue " + "immediately. " % (seconds_remaining, plural) + ) sys.stdout.flush() rlist, _, _ = select([sys.stdin], [], [], 1) @@ -832,7 +912,7 @@ def use_educated_guess(self): break seconds_remaining -= 1 - sys.stdout.write("\r" + " "*65 + "\r") + sys.stdout.write("\r" + " " * 65 + "\r") self.libraries = LIBIGRAPH_FALLBACK_LIBRARIES[:] if self.static_extension: @@ -840,6 +920,7 @@ def use_educated_guess(self): self.include_dirs = LIBIGRAPH_FALLBACK_INCLUDE_DIRS[:] self.library_dirs = LIBIGRAPH_FALLBACK_LIBRARY_DIRS[:] + ########################################################################### # Process command line options @@ -849,13 +930,13 @@ def use_educated_guess(self): workaround.update_buildcfg(buildcfg) # Define the extension -sources=glob.glob(os.path.join('src', '*.c')) -igraph_extension = Extension('igraph._igraph', sources) - # library_dirs=library_dirs, - # libraries=libraries, - # include_dirs=include_dirs, - # extra_objects=extra_objects, - # extra_link_args=extra_link_args +sources = glob.glob(os.path.join("src", "*.c")) +igraph_extension = Extension("igraph._igraph", sources) +# library_dirs=library_dirs, +# libraries=libraries, +# include_dirs=include_dirs, +# extra_objects=extra_objects, +# extra_link_args=extra_link_args description = """Python interface to the igraph high performance graph library, primarily aimed at complex network research and analysis. @@ -882,55 +963,63 @@ def use_educated_guess(self): Many thanks to the maintainers of this page! """ -headers = ['src/igraphmodule_api.h'] if not IS_PYPY else [] +headers = ["src/igraphmodule_api.h"] if not IS_PYPY else [] options = dict( - name = 'python-igraph', - version = VERSION, - url = 'http://pypi.python.org/pypi/python-igraph', - - description = 'High performance graph data structures and algorithms', - long_description = description, - license = 'GNU General Public License (GPL)', - - author = 'Tamas Nepusz', - author_email = 'tamas@cs.rhul.ac.uk', - - ext_modules = [igraph_extension], - package_dir = {'igraph': 'igraph'}, - packages = ['igraph', 'igraph.test', 'igraph.app', 'igraph.drawing', - 'igraph.remote', 'igraph.vendor'], - scripts = ['scripts/igraph'], - test_suite = "igraph.test.suite", - - headers = headers, - - platforms = 'ALL', - keywords = ['graph', 'network', 'mathematics', 'math', 'graph theory', 'discrete mathematics'], - classifiers = [ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'Operating System :: OS Independent', - 'Programming Language :: C', - 'Programming Language :: Python', - 'Topic :: Scientific/Engineering', - 'Topic :: Scientific/Engineering :: Information Analysis', - 'Topic :: Scientific/Engineering :: Mathematics', - 'Topic :: Scientific/Engineering :: Physics', - 'Topic :: Scientific/Engineering :: Bio-Informatics', - 'Topic :: Software Development :: Libraries :: Python Modules' + name="python-igraph", + version=VERSION, + url="http://pypi.python.org/pypi/python-igraph", + description="High performance graph data structures and algorithms", + long_description=description, + license="GNU General Public License (GPL)", + author="Tamas Nepusz", + author_email="tamas@cs.rhul.ac.uk", + ext_modules=[igraph_extension], + package_dir={"igraph": "igraph"}, + packages=[ + "igraph", + "igraph.test", + "igraph.app", + "igraph.drawing", + "igraph.remote", + "igraph.vendor", ], - - cmdclass = { - "build_ext": buildcfg.build_ext - } + scripts=["scripts/igraph"], + test_suite="igraph.test.suite", + headers=headers, + platforms="ALL", + keywords=[ + "graph", + "network", + "mathematics", + "math", + "graph theory", + "discrete mathematics", + ], + classifiers=[ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: C", + "Programming Language :: Python", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Scientific/Engineering :: Physics", + "Topic :: Scientific/Engineering :: Bio-Informatics", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + cmdclass={"build_ext": buildcfg.build_ext}, ) if "macosx" in get_platform() and "bdist_mpkg" in sys.argv: # OS X specific stuff to build the .mpkg installer - options["data_files"] = [ \ - ('/usr/local/lib', [os.path.join('..', 'igraph', 'fatbuild', 'libigraph.0.dylib')]) + options["data_files"] = [ + ( + "/usr/local/lib", + [os.path.join("..", "igraph", "fatbuild", "libigraph.0.dylib")], + ) ] if sys.version_info > (3, 0): From c31ea071341a8085ad618fe5dea66743598197a3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 13 Aug 2019 22:18:44 +0200 Subject: [PATCH 0069/1892] cleaned up flake8 warnings in setup.py --- setup.py | 15 ++++++--------- tox.ini | 5 +++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index a9f90752a..a0a4af13e 100644 --- a/setup.py +++ b/setup.py @@ -27,8 +27,8 @@ IS_PYPY = platform.python_implementation() == "PyPy" ########################################################################### -## Here be ugly workarounds. These must be run before setuptools -## is imported. +# Here be ugly workarounds. These must be run before setuptools +# is imported. class Workaround(object): @@ -191,7 +191,6 @@ def execute(self): try: from setuptools import setup - from setuptools.command.build_ext import build_ext build_py = None except ImportError: @@ -211,16 +210,14 @@ def execute(self): import tarfile import tempfile -from contextlib import closing from select import select from shutil import copyfileobj try: - from urllib import urlretrieve from urllib2 import Request, urlopen, URLError -except: +except ImportError: # Maybe Python 3? - from urllib.request import Request, urlopen, urlretrieve + from urllib.request import Request, urlopen from urllib.error import URLError from distutils.core import Extension @@ -353,7 +350,7 @@ def get_method(self): return "HEAD" try: - response = urlopen(HEADRequest(url)) + urlopen(HEADRequest(url)) return True except URLError: return False @@ -503,7 +500,7 @@ def _progress_hook(count, block_size, total_size): elif local_file.lower().endswith(".tar.bz2"): archive = tarfile.open(local_file_full_path, "r:bz2") else: - print("Cannot extract unknown archive format: %s." % ext) + print("Cannot extract unknown archive format: %s." % local_file) print("") return False archive.extractall(self.tmpdir) diff --git a/tox.ini b/tox.ini index a1b97e058..c78a9043d 100644 --- a/tox.ini +++ b/tox.ini @@ -12,3 +12,8 @@ commands = deps = setenv = TESTING_IN_TOX=1 + +[flake8] +max-line-length = 80 +select = C,E,F,W,B,B950 +ignore = W503,E501,E402,E203 From 52be19a552f9fef6faa4aba4bd4a3eb54ca5d458 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 14 Aug 2019 00:01:40 +0200 Subject: [PATCH 0070/1892] adjusted build folder to use git submodules --- .gitmodules | 3 + setup.py | 163 ++++++++++++++++++++++++++----------------- vendor/source/igraph | 1 + 3 files changed, 104 insertions(+), 63 deletions(-) create mode 100644 .gitmodules create mode 160000 vendor/source/igraph diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..bb3f72ea4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/source/igraph"] + path = vendor/source/igraph + url = https://github.com/igraph/igraph diff --git a/setup.py b/setup.py index a0a4af13e..b5390b985 100644 --- a/setup.py +++ b/setup.py @@ -434,7 +434,7 @@ class IgraphCCoreBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet.""" - def __init__(self, versions_to_try, remote_url=None, tmproot=None): + def __init__(self, versions_to_try=(), remote_url=None, tmproot=None): self.versions_to_try = versions_to_try self.remote_url = remote_url self.tmproot = tmproot @@ -452,6 +452,62 @@ def tmpdir(self): atexit.register(cleanup_tmpdir, self._tmpdir) return self._tmpdir + def compile_in(self, folder): + """Compiles igraph from its source code in the given folder.""" + cwd = os.getcwd() + try: + os.chdir(folder) + + # Run the bootstrap script if we have downloaded a tarball from + # Github + if os.path.isfile("bootstrap.sh") and not os.path.isfile("configure"): + print("Bootstrapping igraph...") + retcode = subprocess.call("sh bootstrap.sh", shell=True) + if retcode: + return False + + # Patch ltmain.sh so it does not freak out on OS X when the build + # directory contains spaces + with open("ltmain.sh") as infp: + with open("ltmain.sh.new", "w") as outfp: + for line in infp: + if line.endswith("cd $darwin_orig_dir\n"): + line = line.replace( + "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' + ) + outfp.write(line) + os.rename("ltmain.sh.new", "ltmain.sh") + + print("Configuring igraph...") + retcode = subprocess.call( + ["./configure", "--disable-tls", "--disable-gmp"], + env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), + ) + if retcode: + return False + + print("Building igraph...") + retcode = subprocess.call("make", shell=True) + if retcode: + return False + + libraries = [] + for line in open("igraph.pc"): + if line.startswith("Libs: ") or line.startswith("Libs.private: "): + words = line.strip().split() + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) + + if not libraries: + # Educated guess + libraries = ["igraph"] + + return libraries + + finally: + os.chdir(cwd) + def download_and_compile(self): """Downloads and compiles the C core of igraph.""" @@ -521,71 +577,22 @@ def _progress_hook(count, block_size, total_size): return False # Try to compile - cwd = os.getcwd() - try: - os.chdir(self.builddir) - - # Run the bootstrap script if we have downloaded a tarball from - # Github - if os.path.isfile("bootstrap.sh") and not os.path.isfile("configure"): - print("Bootstrapping igraph...") - retcode = subprocess.call("sh bootstrap.sh", shell=True) - if retcode: - return False - - # Patch ltmain.sh so it does not freak out on OS X when the build - # directory contains spaces - with open("ltmain.sh") as infp: - with open("ltmain.sh.new", "w") as outfp: - for line in infp: - if line.endswith("cd $darwin_orig_dir\n"): - line = line.replace( - "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' - ) - outfp.write(line) - os.rename("ltmain.sh.new", "ltmain.sh") - - print("Configuring igraph...") - retcode = subprocess.call( - ["./configure", "--disable-tls", "--disable-gmp"], - env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), - ) - if retcode: - return False - - print("Building igraph...") - retcode = subprocess.call("make", shell=True) - if retcode: - return False - - libraries = [] - for line in open(os.path.join(self.builddir, "igraph.pc")): - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) - - if not libraries: - # Educated guess - libraries = ["igraph"] - - finally: - os.chdir(cwd) + libraries = self.compile_in(self.builddir) # Compilation succeeded; copy everything into vendor/build/igraph - create_dir_unless_exists("vendor", "build", "igraph") - ensure_dir_does_not_exist("vendor", "build", "igraph", "include") - ensure_dir_does_not_exist("vendor", "build", "igraph", "lib") - shutil.copytree( - os.path.join(self.builddir, "include"), - os.path.join("vendor", "build", "igraph", "include"), - ) - shutil.copytree( - os.path.join(self.builddir, "src", ".libs"), - os.path.join("vendor", "build", "igraph", "lib"), + self.copy_build_artifacts_from( + self.builddir, + to=os.path.join("vendor", "build", "igraph"), + libraries=libraries, ) - with open(os.path.join("vendor", "build", "igraph", "build.cfg"), "w") as f: + + def copy_build_artifacts_from(self, source, to, libraries): + create_dir_unless_exists(to) + ensure_dir_does_not_exist(to, "include") + ensure_dir_does_not_exist(to, "lib") + shutil.copytree(os.path.join(source, "include"), os.path.join(to, "include")) + shutil.copytree(os.path.join(source, "src", ".libs"), os.path.join(to, "lib")) + with open(os.path.join(to, "build.cfg"), "w") as f: f.write(repr(libraries)) return True @@ -687,6 +694,17 @@ def run(self): buildcfg.use_built_igraph() detected = True + # If igraph is provided as a git submodule, use that + if not detected: + if os.path.isfile( + os.path.join("vendor", "source", "igraph", "configure.ac") + ): + detected = buildcfg.compile_igraph_from_vendor_source() + if detected: + buildcfg.use_built_igraph() + else: + sys.exit(1) + # Download and compile igraph if the user did not disable it and # we do not know the libraries from pkg-config yet if not detected: @@ -731,6 +749,25 @@ def run(self): return custom_build_ext + def compile_igraph_from_vendor_source(self): + """Compiles igraph from the vendored source code inside `vendor/igraph/source`. + This folder typically comes from a git submodule. + """ + path = os.path.join("vendor", "source", "igraph") + print("We are going to compile the C core of igraph from %s" % path) + print("") + + igraph_builder = IgraphCCoreBuilder() + libraries = igraph_builder.compile_in(path) + if not libraries or not igraph_builder.copy_build_artifacts_from( + path, to=os.path.join("vendor", "build", "igraph"), libraries=libraries + ): + print("Could not compile the C core of igraph.") + print("") + return False + else: + return True + def configure(self, ext): """Configures the given Extension object using this build configuration.""" ext.include_dirs = exclude_from_list( diff --git a/vendor/source/igraph b/vendor/source/igraph new file mode 160000 index 000000000..01bb64212 --- /dev/null +++ b/vendor/source/igraph @@ -0,0 +1 @@ +Subproject commit 01bb64212a518e607f37181cc8d18029dcc8f677 From 8cf3d2650cb989912d0c8b57d1cc5f15896e65ee Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 11:29:00 -0700 Subject: [PATCH 0071/1892] Contributing section of README --- README.md | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8364a62fd..a3ca11180 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,52 @@ bleeding edge version, you need to instruct the setup script to download the latest development version of the C core as well: ``` -$ sudo python setup.py develop --c-core-url https://github.com/igraph/igraph/archive/master.tar.gz +$ sudo python setup.py develop --no-pkg-config --c-core-url https://github.com/igraph/igraph/archive/master.tar.gz ``` +## Contributing + +Contributions to `python-igraph` are welcome! + +If you want to add a feature, fix a bug, or suggest an improvement, open an +issue on this repository and we'll try to answer. If you have a piece of code +that you would like to see included in the main tree, open a PR on this repo. + +To start developing `python-igraph`, you need a bleeding edge version of +both `python-igraph` and its core C library, `igraph`. Moreover, you probably +do not want either of those to install both locally so they don't interfere +with any systemwide installations. Follow the steps below (these are +for UNIX, Windows users should change the system commands a little). + +First, clone this repo (e.g. via https) and enter the folder: +```bash +git clone https://github.com/igraph/python-igraph.git +cd python-igraph +``` +Second, build both `igraph` and `python-igraph` at the same time: +```bash +python setup.py build --c-core-url https://github.com/igraph/igraph/archive/master.tar.gz --no-pkg-config +``` +**NOTE**: Building requires `autotools`, a C compiler, and a few more dependencies. + +This command creates a subfolder within `build` which you can insert into your +`PYTHONPATH` to import. You need to move out of the main folder to import +because there is a subfolder called `igraph` too. For instance on Linux: +```bash +cd .. +PYTHONPATH=$(pwd)/python-igraph/build/lib.linux-x86_64-3.7:$PYTHONPATH python +>>> import igraph +>>> g = igraph.Graph.Full(10) +... +``` +You can now play with your changes and see the results. Every time you +make changes to the `python-graph` code, you need to rebuild by calling +the second step above. After the first build, your `igraph` C core library +is compiled already so rebuilding is much faster. + ## Notes +### Pypy This version of python-igraph is compatible with [PyPy](http://pypy.org/) and is regularly tested on [PyPy](http://pypy.org/) with ``tox``. However, the PyPy version falls behind the CPython version in terms of performance; for From d0d03ebc81f4185f8b910e29d700e65746225f36 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 11:35:11 -0700 Subject: [PATCH 0072/1892] Delete some bla bla --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index a3ca11180..e53ee8412 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,7 @@ If you want to add a feature, fix a bug, or suggest an improvement, open an issue on this repository and we'll try to answer. If you have a piece of code that you would like to see included in the main tree, open a PR on this repo. -To start developing `python-igraph`, you need a bleeding edge version of -both `python-igraph` and its core C library, `igraph`. Moreover, you probably -do not want either of those to install both locally so they don't interfere -with any systemwide installations. Follow the steps below (these are +To start developing `python-igraph`, follow the steps below (these are for UNIX, Windows users should change the system commands a little). First, clone this repo (e.g. via https) and enter the folder: From 6637adc4cb6ae24cada54b3f204d88a9d186dd54 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 14:05:25 -0700 Subject: [PATCH 0073/1892] Add argument to get_all_simple_paths because of C API change --- igraph/__init__.py | 4 +++- src/graphobject.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index c7f59ecfe..bcae845cf 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -622,7 +622,7 @@ def get_adjedgelist(self, *args, **kwds): "please use Graph.get_inclist() instead") return self.get_inclist(*args, **kwds) - def get_all_simple_paths(self, v, to=None, mode=OUT): + def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): """get_all_simple_paths(v, to=None, mode=OUT) Calculates all the simple paths from a given node to some other nodes @@ -640,6 +640,8 @@ def get_all_simple_paths(self, v, to=None, mode=OUT): paths. This can be a single vertex ID, a list of vertex IDs, a single vertex name, a list of vertex names or a L{VertexSeq} object. C{None} means all the vertices. + @param cutoff: maximum length of path that is considered. If negative, + paths of all lengths are considered. @param mode: the directionality of the paths. L{IN} means to calculate incoming paths, L{OUT} means to calculate outgoing paths, L{ALL} means to calculate both ones. diff --git a/src/graphobject.c b/src/graphobject.c index 7797bd69d..d3e7c3387 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -4798,15 +4798,19 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * igraph_neimode_t mode = IGRAPH_OUT; igraph_integer_t from; igraph_vs_t to; - PyObject *list, *from_o, *mode_o=Py_None, *to_o=Py_None; + igraph_integer_t cutoff; + PyObject *list, *from_o, *mode_o=Py_None, *to_o=Py_None, *cutoff_o=Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &from_o, - &to_o, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &from_o, + &to_o, &cutoff_o, &mode_o)) return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_vid(cutoff_o, &cutoff, &self->g)) + return NULL; + if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) return NULL; @@ -4819,7 +4823,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * return NULL; } - if (igraph_get_all_simple_paths(&self->g, &res, from, to, mode)) { + if (igraph_get_all_simple_paths(&self->g, &res, from, to, cutoff, mode)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&res); igraph_vs_destroy(&to); From 3fe2e58e404f70c6e9b15427cb2f025484a16811 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 14:05:25 -0700 Subject: [PATCH 0074/1892] Add argument to get_all_simple_paths because of C API change --- igraph/__init__.py | 4 +++- src/graphobject.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index c7f59ecfe..bcae845cf 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -622,7 +622,7 @@ def get_adjedgelist(self, *args, **kwds): "please use Graph.get_inclist() instead") return self.get_inclist(*args, **kwds) - def get_all_simple_paths(self, v, to=None, mode=OUT): + def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): """get_all_simple_paths(v, to=None, mode=OUT) Calculates all the simple paths from a given node to some other nodes @@ -640,6 +640,8 @@ def get_all_simple_paths(self, v, to=None, mode=OUT): paths. This can be a single vertex ID, a list of vertex IDs, a single vertex name, a list of vertex names or a L{VertexSeq} object. C{None} means all the vertices. + @param cutoff: maximum length of path that is considered. If negative, + paths of all lengths are considered. @param mode: the directionality of the paths. L{IN} means to calculate incoming paths, L{OUT} means to calculate outgoing paths, L{ALL} means to calculate both ones. diff --git a/src/graphobject.c b/src/graphobject.c index 7797bd69d..d3e7c3387 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -4798,15 +4798,19 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * igraph_neimode_t mode = IGRAPH_OUT; igraph_integer_t from; igraph_vs_t to; - PyObject *list, *from_o, *mode_o=Py_None, *to_o=Py_None; + igraph_integer_t cutoff; + PyObject *list, *from_o, *mode_o=Py_None, *to_o=Py_None, *cutoff_o=Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &from_o, - &to_o, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &from_o, + &to_o, &cutoff_o, &mode_o)) return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_vid(cutoff_o, &cutoff, &self->g)) + return NULL; + if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) return NULL; @@ -4819,7 +4823,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * return NULL; } - if (igraph_get_all_simple_paths(&self->g, &res, from, to, mode)) { + if (igraph_get_all_simple_paths(&self->g, &res, from, to, cutoff, mode)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&res); igraph_vs_destroy(&to); From 9184d82468aff23e5b2c0824e564f4e368c84bd3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 14:42:10 -0700 Subject: [PATCH 0075/1892] Missing arg in simple_paths interface --- src/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphobject.c b/src/graphobject.c index d3e7c3387..458668457 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -4793,7 +4793,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "v", "to", "mode", NULL }; + static char *kwlist[] = { "v", "to", "cutoff", "mode", NULL }; igraph_vector_int_t res; igraph_neimode_t mode = IGRAPH_OUT; igraph_integer_t from; From 79cae54d4ff360e31f78792abb481bc4c122047c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Aug 2019 15:16:57 -0700 Subject: [PATCH 0076/1892] Tests pass locally now --- igraph/__init__.py | 2 +- src/graphobject.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/igraph/__init__.py b/igraph/__init__.py index bcae845cf..96d11ffad 100644 --- a/igraph/__init__.py +++ b/igraph/__init__.py @@ -649,7 +649,7 @@ def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): reachable node in the graph in a list. Note that in case of mode=L{IN}, the vertices in a path are returned in reversed order! """ - paths = self._get_all_simple_paths(v, to, mode) + paths = self._get_all_simple_paths(v, to, cutoff, mode) prev = 0 result = [] for index, item in enumerate(paths): diff --git a/src/graphobject.c b/src/graphobject.c index 458668457..964df00aa 100644 --- a/src/graphobject.c +++ b/src/graphobject.c @@ -4808,7 +4808,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraphmodule_PyObject_to_vid(cutoff_o, &cutoff, &self->g)) + if (PyInt_AsInt(cutoff_o, &cutoff)) return NULL; if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) @@ -13178,7 +13178,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"_get_all_simple_paths", (PyCFunction) igraphmodule_Graph_get_all_simple_paths, METH_VARARGS | METH_KEYWORDS, - "_get_all_simple_paths(v, to=None, mode=OUT)\n\n" + "_get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT)\n\n" "Internal function, undocumented.\n\n" "@see: Graph.get_all_simple_paths()\n\n" }, From 92b1be1e3d0621048a3b30f8c207f663f0134fe1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Aug 2019 14:45:31 +0200 Subject: [PATCH 0077/1892] vendored igraph submodule should take precedence over pkg-config --- setup.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index b5390b985..d3636a3f1 100644 --- a/setup.py +++ b/setup.py @@ -681,12 +681,6 @@ def run(self): print("You will need the Python headers to compile this extension.") sys.exit(1) - # Print a warning if pkg-config is not available or does not know about igraph - if buildcfg.use_pkgconfig: - detected = buildcfg.detect_from_pkgconfig() - else: - detected = False - # Check whether we have already compiled igraph in a previous run. # If so, it should be found in vendor/build/igraph/include and # vendor/build/igraph/lib @@ -705,6 +699,13 @@ def run(self): else: sys.exit(1) + # Try detecting with pkg-config if we haven't found the submodule + if not detected: + if buildcfg.use_pkgconfig: + detected = buildcfg.detect_from_pkgconfig() + else: + detected = False + # Download and compile igraph if the user did not disable it and # we do not know the libraries from pkg-config yet if not detected: From 15a065cea0713ccb241552260b3f293592b0c146 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Aug 2019 14:47:54 +0200 Subject: [PATCH 0078/1892] fix to previous commit --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index d3636a3f1..5d288d4de 100644 --- a/setup.py +++ b/setup.py @@ -687,6 +687,8 @@ def run(self): if os.path.exists(os.path.join("vendor", "build", "igraph")): buildcfg.use_built_igraph() detected = True + else: + detected = False # If igraph is provided as a git submodule, use that if not detected: From ea844f07c109240865d8398c8fc6ea4030340be4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Aug 2019 15:03:46 +0200 Subject: [PATCH 0079/1892] updated igraph submodule to head --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 01bb64212..370ba7d62 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 01bb64212a518e607f37181cc8d18029dcc8f677 +Subproject commit 370ba7d62405dda854de313839f170d785a26455 From d3f3258e8bd34f4d20aabfe5942f8e0413513c9c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Aug 2019 15:17:43 +0200 Subject: [PATCH 0080/1892] update test case now that the C core checks for bipartiteness --- igraph/test/matching.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igraph/test/matching.py b/igraph/test/matching.py index 3ac4a7eff..f84763e43 100644 --- a/igraph/test/matching.py +++ b/igraph/test/matching.py @@ -61,7 +61,7 @@ def testBipartiteMatchingErrors(self): types=[0,1,0]) # Graph not bipartite - self.assertRaises(ValueError, g.maximum_bipartite_matching, + self.assertRaises(InternalError, g.maximum_bipartite_matching, types=[0,1,1,1]) From ae3da1b256a48d5cbbe8e73fa6f4e0d33a39b4f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 11 Sep 2019 19:00:41 +0200 Subject: [PATCH 0081/1892] bumped igraph to latest revision --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 370ba7d62..141cc0d84 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 370ba7d62405dda854de313839f170d785a26455 +Subproject commit 141cc0d8435b71ee15771ca0ebef1640e9332762 From 00096515c807bff1f0acdab93809b012ed1d021d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 6 Oct 2019 21:56:04 +0200 Subject: [PATCH 0082/1892] fixed a bug in multi-line parsing in Graph.Formula(), closes #249 --- igraph/formula.py | 7 ++++--- igraph/test/generators.py | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/igraph/formula.py b/igraph/formula.py index 75eb33506..540febca7 100644 --- a/igraph/formula.py +++ b/igraph/formula.py @@ -11,6 +11,7 @@ from cStringIO import StringIO from igraph.datatypes import UniqueIdGenerator +import re import tokenize import token @@ -205,9 +206,9 @@ def construct_graph_from_formula(cls, formula = None, attr = "name", vertex_ids, edges, directed = UniqueIdGenerator(), [], False # Loop over each part in the formula - for part in formula.split(","): - # Drop newlines from the part - part = part.strip().replace("\n", "").replace("\t", "") + for part in re.compile(r"[,\n]").split(formula): + # Strip leading and trailing whitespace in the part + part = part.strip() # Parse the first vertex specification from the formula for start_names, end_names, arrowheads in generate_edges(part): start_ids = [vertex_ids[name] for name in start_names] diff --git a/igraph/test/generators.py b/igraph/test/generators.py index 9d282745f..61ad2b041 100644 --- a/igraph/test/generators.py +++ b/igraph/test/generators.py @@ -66,7 +66,9 @@ def testFormula(self): ('"+" -- "-", "*" -- "/", "%%" -- "%/%"', ["+", "-", "*", "/", "%%", "%/%"], [(0,1),(2,3),(4,5)] - ) + ), + ("A-B-C\nC-D", ["A", "B", "C", "D"], [(0,1),(1,2),(2,3)]), + ("A-B-C\n C-D", ["A", "B", "C", "D"], [(0,1),(1,2),(2,3)]) ] for formula, names, edges in tests: g = Graph.Formula(formula) From 16c4f260ca8cfe051214e452f31adfcfec9a96b5 Mon Sep 17 00:00:00 2001 From: Scott Gigante Date: Fri, 11 Oct 2019 22:29:29 -0400 Subject: [PATCH 0083/1892] Import MutableMapping from collections.abc where possible --- igraph/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/igraph/utils.py b/igraph/utils.py index 414c963a9..ea88a81d9 100644 --- a/igraph/utils.py +++ b/igraph/utils.py @@ -6,7 +6,10 @@ """ from contextlib import contextmanager -from collections import MutableMapping +try: + from collections.abc import MutableMapping +except ImportError: + from collections import MutableMapping from ctypes import c_double, sizeof from itertools import chain From fe50e41083198c40299f5718dc06bf813d8822e8 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 23 Oct 2019 23:12:26 +0100 Subject: [PATCH 0084/1892] expose SKIP_H_INSTALL --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 5d288d4de..d1bdee273 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ # Check whether we are compiling for PyPy. Headers will not be installed # for PyPy. -IS_PYPY = platform.python_implementation() == "PyPy" +SKIP_H_INSTALL = (platform.python_implementation() == "PyPy") or ("SKIP_H_INSTALL" in os.environ) ########################################################################### # Here be ugly workarounds. These must be run before setuptools @@ -1000,7 +1000,7 @@ def use_educated_guess(self): Many thanks to the maintainers of this page! """ -headers = ["src/igraphmodule_api.h"] if not IS_PYPY else [] +headers = ["src/igraphmodule_api.h"] if not SKIP_H_INSTALL else [] options = dict( name="python-igraph", From 2a9dce8eb0c622505cf02b971f8e43bf625ec4f5 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 23 Oct 2019 23:20:31 +0100 Subject: [PATCH 0085/1892] add missing yacc (via bison) dep --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e53ee8412..709643da6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ See details in [Installing Python Modules](https://docs.python.org/2/install/). Install dependencies ``` -$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev +$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev bison ``` and then ``` From 7fe0d94e2f18c380ecb2d2f65790dd0ca875e7c4 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Wed, 23 Oct 2019 23:31:18 +0100 Subject: [PATCH 0086/1892] add missing flex dependency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 709643da6..c9340b93c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ See details in [Installing Python Modules](https://docs.python.org/2/install/). Install dependencies ``` -$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev bison +$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev bison flex ``` and then ``` From 25a0522286c3119bedc4eb80314290c1355610a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Thu, 24 Oct 2019 14:33:59 +0200 Subject: [PATCH 0087/1892] Replaced SKIP_H_INSTALL with SKIP_HEADER_INSTALL ...for sake of readability :) --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index d1bdee273..3e1d33428 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ # Check whether we are compiling for PyPy. Headers will not be installed # for PyPy. -SKIP_H_INSTALL = (platform.python_implementation() == "PyPy") or ("SKIP_H_INSTALL" in os.environ) +SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ("SKIP_HEADER_INSTALL" in os.environ) ########################################################################### # Here be ugly workarounds. These must be run before setuptools @@ -1000,7 +1000,7 @@ def use_educated_guess(self): Many thanks to the maintainers of this page! """ -headers = ["src/igraphmodule_api.h"] if not SKIP_H_INSTALL else [] +headers = ["src/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] options = dict( name="python-igraph", From c44f590845830789a8ea079f96cf20d6f81c210b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Dec 2019 10:04:30 +0100 Subject: [PATCH 0088/1892] updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 141cc0d84..ed3350b16 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 141cc0d8435b71ee15771ca0ebef1640e9332762 +Subproject commit ed3350b166ccdfbfe0e839218b26a99a07553481 From bcde1926500f3de805e496902a0f2d9b1f95d007 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Dec 2019 10:30:32 +0100 Subject: [PATCH 0089/1892] fix an operator precedence bug in PyBaseString_Check() when using Python 3 --- src/py2compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py2compat.h b/src/py2compat.h index d2a5f8a53..8ab6dd56f 100644 --- a/src/py2compat.h +++ b/src/py2compat.h @@ -40,7 +40,7 @@ int PyFile_Close(PyObject* fileObj); /* Python 3.x-specific part follows here */ #define IGRAPH_PYTHON3 -#define PyBaseString_Check(o) PyUnicode_Check(o) || PyBytes_Check(o) +#define PyBaseString_Check(o) (PyUnicode_Check(o) || PyBytes_Check(o)) PyObject* PyFile_FromObject(PyObject* filename, const char* mode); From 70957c5e21e70fe5dde263148a7a988d23b652bc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Dec 2019 10:55:58 +0100 Subject: [PATCH 0090/1892] when building with a vendored igraph, use dynamic linkage by default (static won't work on Alpine Linux) --- setup.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 3e1d33428..f73dc8fd8 100644 --- a/setup.py +++ b/setup.py @@ -685,7 +685,7 @@ def run(self): # If so, it should be found in vendor/build/igraph/include and # vendor/build/igraph/lib if os.path.exists(os.path.join("vendor", "build", "igraph")): - buildcfg.use_built_igraph() + buildcfg.use_vendored_igraph() detected = True else: detected = False @@ -697,7 +697,7 @@ def run(self): ): detected = buildcfg.compile_igraph_from_vendor_source() if detected: - buildcfg.use_built_igraph() + buildcfg.use_vendored_igraph() else: sys.exit(1) @@ -714,7 +714,7 @@ def run(self): if buildcfg.download_igraph_if_needed and is_unix_like(): detected = buildcfg.download_and_compile_igraph() if detected: - buildcfg.use_built_igraph() + buildcfg.use_vendored_igraph() else: sys.exit(1) @@ -727,7 +727,10 @@ def run(self): # on Sabayon Linux where libm.a is probably not compiled with # -fPIC if buildcfg.static_extension: - buildcfg.replace_static_libraries(exclusions=["m"]) + if buildcfg.static_extension == "only_igraph": + buildcfg.replace_static_libraries(only=["igraph"]) + else: + buildcfg.replace_static_libraries(exclusions=["m"]) # Prints basic build information buildcfg.print_build_info() @@ -823,7 +826,9 @@ def download_and_compile_igraph(self): def print_build_info(self): """Prints the include and library path being used for debugging purposes.""" - if self.static_extension: + if self.static_extension == "only_igraph": + build_type = "dynamic extension with vendored igraph source" + elif self.static_extension: build_type = "static extension" else: build_type = "dynamic extension" @@ -881,7 +886,7 @@ def process_args_from_command_line(self): for idx in reversed(opts_to_remove): sys.argv[idx : (idx + 1)] = [] - def replace_static_libraries(self, exclusions=None): + def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" if "stdc++" not in self.libraries: @@ -891,17 +896,21 @@ def replace_static_libraries(self, exclusions=None): exclusions = [] for library_name in set(self.libraries) - set(exclusions): + if only is not None and library_name not in only: + continue + static_lib = find_static_library(library_name, self.library_dirs) if static_lib: self.libraries.remove(library_name) self.extra_objects.append(static_lib) - def use_built_igraph(self): + def use_vendored_igraph(self): """Assumes that igraph is built already in ``vendor/build/igraph`` and sets up the include and library paths and the library names accordingly.""" buildcfg.include_dirs = [os.path.join("vendor", "build", "igraph", "include")] buildcfg.library_dirs = [os.path.join("vendor", "build", "igraph", "lib")] - buildcfg.static_extension = True + if not buildcfg.static_extension: + buildcfg.static_extension = "only_igraph" buildcfg_file = os.path.join("vendor", "build", "igraph", "build.cfg") if os.path.exists(buildcfg_file): From 92ac72fec2bb5d772ce761f0ad6ad9e3526756df Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 18 Dec 2019 11:50:55 +0100 Subject: [PATCH 0091/1892] updated minimal Dockerfile to use Alpine Linux --- docker/minimal/Dockerfile | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/docker/minimal/Dockerfile b/docker/minimal/Dockerfile index 332147d30..7a598ebb4 100644 --- a/docker/minimal/Dockerfile +++ b/docker/minimal/Dockerfile @@ -1,7 +1,25 @@ -FROM ubuntu:latest +FROM alpine:latest AS builder MAINTAINER Tamas Nepusz LABEL Description="Simple Docker image that contains a pre-compiled version of igraph's Python interface" -RUN apt-get -y update && apt-get -y install build-essential libxml2-dev zlib1g-dev python-dev python-pip pkg-config libffi-dev libcairo-dev -RUN pip install python-igraph -RUN pip install cairocffi -CMD /usr/local/bin/igraph + +RUN apk add --no-cache --update \ + make gcc g++ libstdc++ git python3-dev libxslt-dev libxml2-dev libc-dev \ + libffi-dev zlib-dev py-pip libxml2 zlib libtool autoconf automake \ + flex bison \ + && rm -rf /var/cache/apk/* + +RUN pip3 install git+https://github.com/igraph/python-igraph +RUN pip3 install cairocffi + +FROM alpine:latest + +RUN apk add --no-cache --update \ + python3 libstdc++ libxml2 libxslt zlib cairo \ + && rm -rf /var/cache/apk/* + +COPY --from=builder /usr/lib/python3.7/site-packages/cairocffi /usr/lib/python3.7/site-packages/cairocffi +COPY --from=builder /usr/lib/python3.7/site-packages/igraph /usr/lib/python3.7/site-packages/igraph +COPY --from=builder /usr/bin/igraph /usr/bin + +CMD /usr/bin/igraph + From 71f2c4ce6226230970a58a603948697cc67507a3 Mon Sep 17 00:00:00 2001 From: vtraag Date: Fri, 20 Dec 2019 17:03:36 +0100 Subject: [PATCH 0092/1892] Reindex clusterings that were used for testing to fall within the proper range. --- igraph/test/decomposition.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/igraph/test/decomposition.py b/igraph/test/decomposition.py index ec052c219..e43404eda 100644 --- a/igraph/test/decomposition.py +++ b/igraph/test/decomposition.py @@ -368,11 +368,11 @@ def testCohesiveBlockingErrors(self): class ComparisonTests(unittest.TestCase): def setUp(self): self.clusterings = [ - ([1, 1, 1, 2, 2, 2], [2, 2, 2, 1, 1, 1]), - ([1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 3, 3]), - ([1, 1, 1, 1, 1, 1], [1, 2, 3, 5, 6, 7]), - ([1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3], - [3, 1, 2, 1, 3, 1, 3, 1, 2, 1, 4, 2]) + ([0, 0, 0, 1, 1, 1], [1, 1, 1, 0, 0, 0]), + ([0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 2, 2]), + ([0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5]), + ([0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2], + [2, 0, 1, 0, 2, 0, 2, 0, 1, 0, 3, 1]) ] def _testMethod(self, method, expected): From 0d09c2aa3266c0df3583a3c66c58734a851f7373 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Dec 2019 10:18:51 +0100 Subject: [PATCH 0093/1892] trying to set up cibuildwheel for Travis --- .travis.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index bab4c3581..bc68c24a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -dist: xenial +dist: bionic language: python python: @@ -16,15 +16,29 @@ addons: - flex - bison +jobs: + include: + - services: docker + - os: osx + language: shell + - os: windows + language: shell + before_install: + - choco install python --version 3.8.0 + - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" + +env: + global: + - TWINE_USERNAME=ntamas + install: - - pip install tox-travis + - python -m pip install tox-travis twine cibuildwheel==1.1.0 script: - tox + - python -m cibuildwheel --output-dir wheelhouse notifications: email: on_success: change on_failure: always - -sudo: false \ No newline at end of file From 710d7952221a7d893ce9fdfcc768cbf8c19b21d8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Dec 2019 11:06:56 +0100 Subject: [PATCH 0094/1892] installing dependencies for cibuildwheel in Docker --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index bc68c24a6..c6ca39e75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ jobs: env: global: + - CIBW_BEFORE_BUILD="yum install -y libxml2-devel flex bison" - TWINE_USERNAME=ntamas install: From cf79c38d163d34af9d9909dbbe44428cfddfc1c1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 10:23:08 +0100 Subject: [PATCH 0095/1892] bumped igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index ed3350b16..9ff13a12e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit ed3350b166ccdfbfe0e839218b26a99a07553481 +Subproject commit 9ff13a12e5560004da9f8abd8d21b499a8587556 From aebca7ca180a469bec42592ad4d7a692d9cee5cd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 10:43:34 +0100 Subject: [PATCH 0096/1892] ignore .venv/ when using Pipenv --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 479f60207..75366fadb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ igraph/*.so *.egg-info/ .python-version .tox +.venv/ docker/wheelhouse Pipfile From 71f6a6fb01166a01cf855457acd7f33983066ec3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 10:43:50 +0100 Subject: [PATCH 0097/1892] cleanup setup script: remove unused parts as we now vendor igraph's source --- setup.py | 417 +------------------------------------------------------ 1 file changed, 5 insertions(+), 412 deletions(-) diff --git a/setup.py b/setup.py index f73dc8fd8..f9f1d0a79 100644 --- a/setup.py +++ b/setup.py @@ -10,182 +10,15 @@ VERSION = "0.7.1.post6" # Check Python's version info and exit early if it is too old -if sys.version_info < (2, 5): - print("This module requires Python >= 2.5") +if sys.version_info < (2, 7): + print("This module requires Python >= 2.7") sys.exit(0) -# Check whether we are running inside tox -- if so, we will use a non-logging -# URL to download the C core of igraph to avoid inflating download counts -TESTING_IN_TOX = "TESTING_IN_TOX" in os.environ - -# Check whether we are running in a CI environment like Travis -- if so, -# we will download the master tarball of igraph when needed -TESTING_IN_CI = "CONTINUOUS_INTEGRATION" in os.environ - # Check whether we are compiling for PyPy. Headers will not be installed # for PyPy. -SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ("SKIP_HEADER_INSTALL" in os.environ) - -########################################################################### -# Here be ugly workarounds. These must be run before setuptools -# is imported. - - -class Workaround(object): - """Base class for platform-specific workarounds and hacks that are - needed to get the Python interface compile with as little user - intervention as possible.""" - - def required(self): - """Returns ``True`` if the workaround is required on the platform - of the user and ``False`` otherwise.""" - raise NotImplementedError - - def hack(self): - """Installs the workaround. This method will get called if and only - if the ``required()`` method returns ``True``. - """ - pass - - def update_buildcfg(self, cfg): - """Allows the workaround to update the build configuration of the - igraph extension. This method will get called if and only if the - ``required()`` method returns ``True``. - """ - pass - - def _extend_compiler_customization(self, func): - """Helper function that extends ``distutils.sysconfig.customize_compiler`` - and ``setuptools.command.build_ext.customize_compiler`` with new, - user-defined code at the end.""" - from distutils import sysconfig - - old_func = sysconfig.customize_compiler - - def replaced(*args, **kwds): - old_func(*args, **kwds) - return func(*args, **kwds) - - self._replace_compiler_customization_distutils(replaced) - self._replace_compiler_customization_setuptools(replaced) - - def _replace_compiler_customization_distutils(self, new_func): - from distutils import ccompiler, sysconfig - - sysconfig.customize_compiler = new_func - ccompiler.customize_compiler = new_func - - def _replace_compiler_customization_setuptools(self, new_func): - if "setuptools.command.build_ext" in sys.modules: - sys.modules["setuptools.command.build_ext"].customize_compiler = new_func - - -class OSXClangAndSystemPythonWorkaround(Workaround): - """Removes ``-mno-fused-madd`` from the arguments used to compile - Python extensions if the user is running OS X.""" - - @staticmethod - def remove_compiler_args(compiler): - while "-mno-fused-madd" in compiler.compiler: - compiler.compiler.remove("-mno-fused-madd") - while "-mno-fused-madd" in compiler.compiler_so: - compiler.compiler_so.remove("-mno-fused-madd") - while "-mno-fused-madd" in compiler.linker_so: - compiler.linker_so.remove("-mno-fused-madd") - - def required(self): - return sys.platform.startswith("darwin") - - def hack(self): - self._extend_compiler_customization(self.remove_compiler_args) - - -class OSXAnacondaPythonIconvWorkaround(Workaround): - """Anaconda Python contains a file named libxml2.la which refers to - /usr/lib/libiconv.la -- but such a file does not exist in OS X. This - hack ensures that we link to libxml2 from OS X itself and not from - Anaconda Python (after all, this is what would have happened if the - C core of igraph was compiled independently).""" - - def required(self): - from distutils.spawn import find_executable - - if not sys.platform.startswith("darwin"): - return False - if "Anaconda" not in sys.version: - return False - self.xml2_config_path = find_executable("xml2-config") - if not self.xml2_config_path: - return False - xml2_config_path_abs = os.path.abspath(self.xml2_config_path) - return xml2_config_path_abs.startswith(os.path.abspath(sys.prefix)) - - def hack(self): - path = os.environ["PATH"].split(os.pathsep) - dir_to_remove = os.path.dirname(self.xml2_config_path) - if dir_to_remove in path: - path.remove(dir_to_remove) - os.environ["PATH"] = os.pathsep.join(path) - - def update_buildcfg(self, cfg): - anaconda_libdir = os.path.join(sys.prefix, "lib") - cfg.extra_link_args.append("-Wl,-rpath,%s" % anaconda_libdir) - cfg.post_build_hooks.append(self.fix_install_name) - - def fix_install_name(self, cfg): - """Fixes the install name of the libxml2 library in _igraph.so - to ensure that it loads libxml2 from Anaconda Python.""" - for outputfile in cfg.get_outputs(): - lines, retcode = get_output(["otool", "-L", outputfile]) - if retcode: - raise OSError( - "otool -L %s failed with error code: %s" % (outputfile, retcode) - ) - - for line in lines.split("\n"): - if "libxml2" in line: - libname = line.strip().split(" ")[0] - subprocess.call( - [ - "install_name_tool", - "-change", - libname, - "@rpath/" + os.path.basename(libname), - outputfile, - ] - ) - - -class ContinuousIntegrationSetup(Workaround): - """Prepares the build configuration for a CI environment like Travis.""" - - def required(self): - return TESTING_IN_CI - - def update_buildcfg(self, cfg): - cfg.c_core_url = "https://github.com/igraph/igraph/archive/master.tar.gz" - - -class WorkaroundSet(object): - def __init__(self, workaround_classes): - self.each = [cls() for cls in workaround_classes] - self.executed = [] - - def execute(self): - for workaround in self.each: - if workaround.required(): - workaround.hack() - self.executed.append(workaround) - - -workarounds = WorkaroundSet( - [ - OSXClangAndSystemPythonWorkaround, - OSXAnacondaPythonIconvWorkaround, - ContinuousIntegrationSetup, - ] +SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ( + "SKIP_HEADER_INSTALL" in os.environ ) -workarounds.execute() ########################################################################### @@ -201,27 +34,15 @@ def execute(self): except ImportError: from distutils.command.build_py import build_py -import atexit import distutils.ccompiler import glob import shutil import subprocess import sys -import tarfile -import tempfile from select import select -from shutil import copyfileobj - -try: - from urllib2 import Request, urlopen, URLError -except ImportError: - # Maybe Python 3? - from urllib.request import Request, urlopen - from urllib.error import URLError from distutils.core import Extension -from distutils.util import get_platform ########################################################################### @@ -232,12 +53,6 @@ def execute(self): ########################################################################### -def cleanup_tmpdir(dirname): - """Removes the given temporary directory if it exists.""" - if dirname is not None and os.path.exists(dirname): - shutil.rmtree(dirname) - - def create_dir_unless_exists(*args): """Creates a directory unless it exists already.""" path = os.path.join(*args) @@ -289,22 +104,6 @@ def find_static_library(library_name, library_path): return full_path -def find_temporary_directory(): - """Finds a suitable temporary directory where the installer can download the - C core of igraph if needed and returns its full path.""" - script_file = sys.modules[__name__].__file__ - if not script_file.endswith("setup.py"): - # We are probably running within an easy_install sandbox. Luckily this - # provides a temporary directory for us so we can use that - result = tempfile.gettempdir() - else: - # Use a temporary directory next to setup.py. We cannot blindly use - # the default (given by tempfile.tempdir) because it might be on a - # RAM disk that has not enough space - result = os.path.join(os.path.dirname(script_file), "tmp") - return os.path.abspath(result) - - def first(iterable): """Returns the first element from the given iterable.""" for item in iterable: @@ -340,22 +139,6 @@ def get_output_single_line(args, encoding="utf-8"): return line, returncode -def http_url_exists(url): - """Returns whether the given HTTP URL 'exists' in the sense that it is returning - an HTTP error code or not. A URL is considered to exist if it does not return - an HTTP error code.""" - - class HEADRequest(Request): - def get_method(self): - return "HEAD" - - try: - urlopen(HEADRequest(url)) - return True - except URLError: - return False - - def is_unix_like(platform=None): """Returns whether the given platform is a Unix-like platform with the usual Unix filesystem. When the parameter is omitted, it defaults to ``sys.platform`` @@ -434,24 +217,6 @@ class IgraphCCoreBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet.""" - def __init__(self, versions_to_try=(), remote_url=None, tmproot=None): - self.versions_to_try = versions_to_try - self.remote_url = remote_url - self.tmproot = tmproot - self._tmpdir = None - - if self.tmproot is None: - self.tmproot = find_temporary_directory() - - @property - def tmpdir(self): - """The temporary directory in which igraph is downloaded and extracted.""" - if self._tmpdir is None: - create_dir_unless_exists(self.tmproot) - self._tmpdir = tempfile.mkdtemp(prefix="igraph.", dir=self.tmproot) - atexit.register(cleanup_tmpdir, self._tmpdir) - return self._tmpdir - def compile_in(self, folder): """Compiles igraph from its source code in the given folder.""" cwd = os.getcwd() @@ -508,84 +273,6 @@ def compile_in(self, folder): finally: os.chdir(cwd) - def download_and_compile(self): - """Downloads and compiles the C core of igraph.""" - - def _progress_hook(count, block_size, total_size): - if total_size < 0: - sys.stdout.write("\rDownloading %s... please wait." % local_file) - else: - percentage = count * block_size * 100.0 / total_size - percentage = min(percentage, 100.0) - sys.stdout.write( - "\rDownloading %s... %.2f%%" % (local_file, percentage) - ) - sys.stdout.flush() - - # Determine the remote URL if needed - if self.remote_url is None: - self.version, remote_url = self.find_first_version() - if not self.version: - print( - "Version %s of the C core of igraph is not found among the " - "nightly builds." % self.versions_to_try[0] - ) - print("Use the --c-core-version switch to try a different version.") - print("") - return False - local_file = "igraph-%s.tar.gz" % self.version - else: - remote_url = self.remote_url - _, _, local_file = remote_url.rpartition("/") - - print("Using temporary directory: %s" % self.tmpdir) - - # Now determine the full path where the C core will be downloaded - local_file_full_path = os.path.join(self.tmpdir, local_file) - - # Download the C core - print("Downloading %s... " % local_file) - in_stream = urlopen(remote_url) - with open(local_file_full_path, "wb") as out_file: - copyfileobj(in_stream, out_file) - - # Extract it in the temporary directory - print("Extracting %s..." % local_file) - if local_file.lower().endswith(".tar.gz"): - archive = tarfile.open(local_file_full_path, "r:gz") - elif local_file.lower().endswith(".tar.bz2"): - archive = tarfile.open(local_file_full_path, "r:bz2") - else: - print("Cannot extract unknown archive format: %s." % local_file) - print("") - return False - archive.extractall(self.tmpdir) - - # Determine the name of the build directory - self.builddir = None - for name in os.listdir(self.tmpdir): - full_path = os.path.join(self.tmpdir, name) - if name.startswith("igraph") and os.path.isdir(full_path): - self.builddir = full_path - break - - if not self.builddir: - print( - "Downloaded tarball did not contain a directory whose name " - "started with igraph; giving up build." - ) - return False - - # Try to compile - libraries = self.compile_in(self.builddir) - - # Compilation succeeded; copy everything into vendor/build/igraph - self.copy_build_artifacts_from( - self.builddir, - to=os.path.join("vendor", "build", "igraph"), - libraries=libraries, - ) - def copy_build_artifacts_from(self, source, to, libraries): create_dir_unless_exists(to) ensure_dir_does_not_exist(to, "include") @@ -605,32 +292,9 @@ def enhanced_env(**kwargs): env[k] = "{0} {1}".format(prev, v) if prev else v return env - def find_first_version(self): - """Finds the first version of igraph that exists in the nightly build - repo from the version numbers provided in ``self.versions_to_try``.""" - for version in self.versions_to_try: - remote_url = self.get_download_url(version=version) - if http_url_exists(remote_url): - return version, remote_url - return None, None - - def get_download_url(self, version): - if TESTING_IN_TOX: - # Make sure that tox unit tests are not counted as real - # igraph downloads - return "http://igraph.org/nightly/steal/c/igraph-%s.tar.gz" % version - else: - return "http://igraph.org/nightly/get/c/igraph-%s.tar.gz" % version - - def run(self): - return self.download_and_compile() - class BuildConfiguration(object): def __init__(self): - global VERSION - self.c_core_versions = version_variants(VERSION) - self.c_core_url = None self.include_dirs = [] self.library_dirs = [] self.runtime_library_dirs = [] @@ -639,7 +303,6 @@ def __init__(self): self.extra_link_args = [] self.extra_objects = [] self.static_extension = False - self.download_igraph_if_needed = True self.use_pkgconfig = True self._has_pkgconfig = None self.excluded_include_dirs = [] @@ -708,16 +371,6 @@ def run(self): else: detected = False - # Download and compile igraph if the user did not disable it and - # we do not know the libraries from pkg-config yet - if not detected: - if buildcfg.download_igraph_if_needed and is_unix_like(): - detected = buildcfg.download_and_compile_igraph() - if detected: - buildcfg.use_vendored_igraph() - else: - sys.exit(1) - # Fall back to an educated guess if everything else failed if not detected: buildcfg.use_educated_guess() @@ -808,22 +461,6 @@ def detect_from_pkgconfig(self): self.include_dirs = [opt[2:] for opt in opts if opt.startswith("-I")] return True - def download_and_compile_igraph(self): - """Downloads and compiles the C core of igraph.""" - print("We will now try to download and compile the C core from scratch.") - print("Version number of the C core: %s" % self.c_core_versions[0]) - if len(self.c_core_versions) > 1: - print("We will also try: %s" % ", ".join(self.c_core_versions[1:])) - print("") - - igraph_builder = IgraphCCoreBuilder(self.c_core_versions, self.c_core_url) - if not igraph_builder.run(): - print("Could not download and compile the C core of igraph.") - print("") - return False - else: - return True - def print_build_info(self): """Prints the include and library path being used for debugging purposes.""" if self.static_extension == "only_igraph": @@ -857,31 +494,12 @@ def process_args_from_command_line(self): if option == "--static": opts_to_remove.append(idx) self.static_extension = True - elif option == "--no-download": - opts_to_remove.append(idx) - self.download_igraph_if_needed = False elif option == "--no-pkg-config": opts_to_remove.append(idx) self.use_pkgconfig = False elif option == "--no-wait": opts_to_remove.append(idx) self.wait = False - elif option.startswith("--c-core-version"): - opts_to_remove.append(idx) - if option == "--c-core-version": - value = sys.argv[idx + 1] - opts_to_remove.append(idx + 1) - else: - value = option.split("=", 1)[1] - self.c_core_versions = [value] - elif option.startswith("--c-core-url"): - opts_to_remove.append(idx) - if option == "--c-core-url": - value = sys.argv[idx + 1] - opts_to_remove.append(idx + 1) - else: - value = option.split("=", 1)[1] - self.c_core_url = value for idx in reversed(opts_to_remove): sys.argv[idx : (idx + 1)] = [] @@ -972,17 +590,10 @@ def use_educated_guess(self): # Process command line options buildcfg = BuildConfiguration() buildcfg.process_args_from_command_line() -for workaround in workarounds.executed: - workaround.update_buildcfg(buildcfg) # Define the extension sources = glob.glob(os.path.join("src", "*.c")) igraph_extension = Extension("igraph._igraph", sources) -# library_dirs=library_dirs, -# libraries=libraries, -# include_dirs=include_dirs, -# extra_objects=extra_objects, -# extra_link_args=extra_link_args description = """Python interface to the igraph high performance graph library, primarily aimed at complex network research and analysis. @@ -995,15 +606,6 @@ def use_educated_guess(self): there were bug reports affecting igraph graph plots in Jupyter notebooks when using ``pycairo`` (but not with ``cairocffi``). -From release 0.5, the C core of the igraph library is **not** included -in the Python distribution - you must compile and install the C core -separately. Windows installers already contain a compiled igraph DLL, -so they should work out of the box. Linux users should refer to the -`igraph homepage `_ for -compilation instructions (but check your distribution first, maybe -there are pre-compiled packages available). OS X users may -benefit from the disk images in the Python Package Index. - Unofficial installers for 64-bit Windows machines and/or different Python versions can also be found `here `_. Many thanks to the maintainers of this page! @@ -1019,7 +621,7 @@ def use_educated_guess(self): long_description=description, license="GNU General Public License (GPL)", author="Tamas Nepusz", - author_email="tamas@cs.rhul.ac.uk", + author_email="ntamas@gmail.com", ext_modules=[igraph_extension], package_dir={"igraph": "igraph"}, packages=[ @@ -1059,15 +661,6 @@ def use_educated_guess(self): cmdclass={"build_ext": buildcfg.build_ext}, ) -if "macosx" in get_platform() and "bdist_mpkg" in sys.argv: - # OS X specific stuff to build the .mpkg installer - options["data_files"] = [ - ( - "/usr/local/lib", - [os.path.join("..", "igraph", "fatbuild", "libigraph.0.dylib")], - ) - ] - if sys.version_info > (3, 0): if build_py is None: options["use_2to3"] = True From bf56ad5734cf811f04634e67e179a81a478ec3bd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 10:50:36 +0100 Subject: [PATCH 0098/1892] remove unused scripts/release-osx.sh --- scripts/release-osx.sh | 136 ----------------------------------------- 1 file changed, 136 deletions(-) delete mode 100755 scripts/release-osx.sh diff --git a/scripts/release-osx.sh b/scripts/release-osx.sh deleted file mode 100755 index 65efecd75..000000000 --- a/scripts/release-osx.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash -# Creates the OS X installer package and puts it in a disk image - -FATLIB=../igraph/fatbuild/libigraph.dylib -PYTHON_VERSIONS="2.6 2.7" - -function check_universal { - if [ `file $1 | grep -c "binary with 2 architectures"` -lt 1 ]; then - echo "$1 is not a universal binary" - exit 2 - fi -} - -function get_dependent_libraries { - local LIBS=`otool -L $1 | awk 'NR >= 2 { print }' | cut -f 2 | cut -d ' ' -f 1` - echo "$LIBS" -} - -function check_library_paths { - local LIB - for LIB in $2; do - DIR=`dirname $LIB` - if [ x$DIR != x/usr/lib -a x$DIR != x/usr/local/lib ]; then - echo "$1 links to disallowed library: $LIB" - exit 3 - fi - done -} - -function check_mandatory_library_linkage { - local LIB - for LIB in $2; do - if [ x$LIB = x$3 ]; then - return - fi - done - echo "$1 does not link to required library: $3" - exit 4 -} - -function check_universal { - if [ `file $1 | grep -c "binary with 2 architectures"` -lt 1 ]; then - echo "$1 is not a universal binary" - exit 2 - fi -} - -function get_dependent_libraries { - local LIBS=`otool -L $1 | awk 'NR >= 2 { print }' | cut -f 2 | cut -d ' ' -f 1` - echo "$LIBS" -} - -function check_library_paths { - local LIB - for LIB in $2; do - DIR=`dirname $LIB` - if [ x$DIR != x/usr/lib -a x$DIR != x/usr/local/lib ]; then - echo "$1 links to disallowed library: $LIB" - exit 3 - fi - done -} - -function check_mandatory_library_linkage { - local LIB - for LIB in $2; do - if [ x$LIB = x$3 ]; then - return - fi - done - echo "$1 does not link to required library: $3" - exit 4 -} - -# Check whether we are running the script on Mac OS X -which hdiutil >/dev/null || ( echo "This script must be run on OS X"; exit 1 ) - -# Find the directory with setup.py -CWD=`pwd` -while [ ! -f setup.py ]; do cd ..; done - -# Extract the version number from setup.py -VERSION=`cat setup.py | grep "VERSION =" | cut -d '=' -f 2 | tr -d "' "` -VERSION_UNDERSCORE=`echo ${VERSION} | tr '-' '_'` - -# Ensure that the igraph library we are linking to is a fat binary -if [ ! -f ${FATLIB} ]; then - pushd ../igraph && tools/fatbuild.sh && popd - if [ ! -f ${FATLIB} ]; then - echo "Failed to build fat igraph library: ${FATLIB}" - exit 1 - fi -fi - -# Ensure that we are really linking to a fat binary and that it refers -# to libxml2 and libz -check_universal ${FATLIB} -LIBS=$(get_dependent_libraries ${FATLIB}) -check_library_paths ${FATLIB} "${LIBS}" -check_mandatory_library_linkage ${FATLIB} "${LIBS}" /usr/lib/libxml2.2.dylib -# check_mandatory_library_linkage ${FATLIB} "${LIBS}" /usr/lib/libz.1.dylib - -# Clean up the previous build directory -rm -rf build/ igraphcore/ - -# Set up ARCHFLAGS to ensure that we build a multi-arch Python extension -export ARCHFLAGS="-arch i386 -arch x86_64" - -# For each Python version, build the .mpkg and the .dmg -for PYVER in $PYTHON_VERSIONS; do - PYTHON=/usr/bin/python$PYVER - $PYTHON setup.py build_ext --no-download --no-wait --no-pkg-config -I ../igraph/include:../igraph/fatbuild/x86/include -L `dirname $FATLIB` || exit 3 - $PYTHON setup.py bdist_mpkg --no-download --no-wait --no-pkg-config || exit 4 - - # Ensure that the built library is really universal - LIB=build/lib.macosx-*-${PYVER}/igraph/_igraph.so - check_universal ${LIB} - DEPS=$(get_dependent_libraries ${LIB}) - check_library_paths ${LIB} "${DEPS}" - check_mandatory_library_linkage ${LIB} "${DEPS}" /usr/local/lib/libigraph.0.dylib - - for MACVER in 10.5 10.6 10.7 10.8 10.9; do - MPKG="dist/python_igraph-${VERSION_UNDERSCORE}-py${PYVER}-macosx${MACVER}.mpkg" - if [ -f $MPKG ]; then - break - fi - done - - DMG=dist/`basename $MPKG .mpkg`.dmg - rm -f ${DMG} - echo "hdiutil create -volname 'python-igraph ${VERSION}' -layout NONE -srcfolder $MPKG $DMG" - hdiutil create -volname "python-igraph ${VERSION}" -layout NONE -srcfolder $MPKG $DMG - rm -rf ${MPKG} -done - -cd $CWD From 4d0c99e3e9372307edccd77845fc7bf41a622169 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 10:51:35 +0100 Subject: [PATCH 0099/1892] remove unused pylint.rc --- pylint.rc | 310 ------------------------------------------------------ 1 file changed, 310 deletions(-) delete mode 100644 pylint.rc diff --git a/pylint.rc b/pylint.rc deleted file mode 100644 index 4c50648f0..000000000 --- a/pylint.rc +++ /dev/null @@ -1,310 +0,0 @@ -# lint Python modules using external checkers. -# -# This is the main checker controlling the other ones and the reports -# generation. It is itself both a raw checker and an astng checker in order -# to: -# * handle message activation / deactivation at the module level -# * handle some basic but necessary stats'data (number of classes, methods...) -# -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add to the black list. It should be a base name, not a -# path. You may set this option multiple times. -ignore=.bzr - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable only checker(s) with the given id(s). This option conflicts with the -# disable-checker option -#enable-checker= - -# Enable all checker(s) except those with the given id(s). This option -# conflicts with the enable-checker option -#disable-checker= - -# Enable all messages in the listed categories (IRCWEF). -#enable-msg-cat= - -# Disable all messages in the listed categories (IRCWEF). -disable-msg-cat=I - -# Enable the message(s) with the given id(s). -#enable-msg= - -# Disable the message(s) with the given id(s). -disable-msg=W0704 - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Include message's id in output -include-ids=yes - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (R0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (R0004). -comment=no - -# Enable the report(s) with the given id(s). -#enable-report= - -# Disable the report(s) with the given id(s). -#disable-report= - - -# checks for : -# * doc strings -# * modules / classes / functions / methods / arguments / variables name -# * number of arguments, local variables, branches, returns and statements in -# functions, methods -# * required module attributes -# * dangerous default values as arguments -# * redefinition of function / method / class -# * uses of the global statement -# -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,l,m,n,x,y,v,e,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - - -# try to find bugs in the code using type inference -# -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. -generated-members=REQUEST,acl_users,aq_parent - - -# checks for -# * unused variables / imports -# * undefined variables -# * redefinition of variable from builtins or from an outer scope -# * use of variable before assignment -# -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching names used for dummy variables (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -# checks for : -# * methods without self as first argument -# * overridden methods signature -# * access only to existent members via self -# * attributes not defined in the __init__ method -# * supported interfaces implementation -# * unreachable code -# -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - - -# checks for sign of poor/misdesign: -# * number of methods, attributes, local variables... -# * size, complexity of functions, methods -# -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -# checks for -# * external modules dependencies -# * relative / wildcard imports -# * cyclic imports -# * uses of deprecated modules -# -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report R0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report R0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report R0402 must -# not be disabled) -int-import-graph= - - -# checks for : -# * unauthorized constructions -# * strict indentation -# * line length -# * use of <> instead of != -# -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -# checks for: -# * warning notes in the code like FIXME, XXX -# * PEP 263: source code with non ascii character but no encoding declaration -# -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -# checks for similarities and duplicated code. This computation may be -# memory / CPU intensive, so you should disable it if you experiments some -# problems. -# -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes From dfe9308ada349649ac28b66e6b847f52cdf9df59 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 11:18:16 +0100 Subject: [PATCH 0100/1892] remove old distutils stuff from setup.py --- setup.py | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/setup.py b/setup.py index f9f1d0a79..9825d3e3a 100644 --- a/setup.py +++ b/setup.py @@ -22,17 +22,7 @@ ########################################################################### -try: - from setuptools import setup - - build_py = None -except ImportError: - from distutils.core import setup - - try: - from distutils.command.build_py import build_py_2to3 as build_py - except ImportError: - from distutils.command.build_py import build_py +from setuptools import setup, Extension import distutils.ccompiler import glob @@ -42,8 +32,6 @@ from select import select -from distutils.core import Extension - ########################################################################### LIBIGRAPH_FALLBACK_INCLUDE_DIRS = ["/usr/include/igraph", "/usr/local/include/igraph"] @@ -326,12 +314,10 @@ def has_pkgconfig(self): @property def build_ext(self): """Returns a class that can be used as a replacement for the - ``build_ext`` command in ``distutils`` and that will download and - compile the C core of igraph if needed.""" - try: - from setuptools.command.build_ext import build_ext - except ImportError: - from distutils.command.build_ext import build_ext + ``build_ext`` command in ``setuptools`` and that will compile the C core + of igraph before compiling the Python extension. + """ + from setuptools.command.build_ext import build_ext from distutils.sysconfig import get_python_inc buildcfg = self @@ -662,9 +648,6 @@ def use_educated_guess(self): ) if sys.version_info > (3, 0): - if build_py is None: - options["use_2to3"] = True - else: - options["cmdclass"]["build_py"] = build_py + options["use_2to3"] = True setup(**options) From 0bcc8f566230b53e8ff4479a79fb445535f9a272 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 13:34:44 +0100 Subject: [PATCH 0101/1892] setup.py: don't pollute vendor/source/igraph while building igraph, use vendor/build/igraph for that --- setup.py | 95 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/setup.py b/setup.py index 9825d3e3a..ff8547e37 100644 --- a/setup.py +++ b/setup.py @@ -205,11 +205,22 @@ class IgraphCCoreBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet.""" - def compile_in(self, folder): - """Compiles igraph from its source code in the given folder.""" + def compile_in(self, build_folder, source_folder=None): + """Compiles igraph from its source code in the given folder. + + source_folder is the name of the folder that contains igraph's source + files. If it is `None`, it is assumed that it is the same as the + build folder. + """ + if source_folder is None: + source_folder = build_folder + + source_folder = os.path.abspath(source_folder) + build_folder = os.path.abspath(build_folder) + cwd = os.getcwd() try: - os.chdir(folder) + os.chdir(source_folder) # Run the bootstrap script if we have downloaded a tarball from # Github @@ -231,9 +242,16 @@ def compile_in(self, folder): outfp.write(line) os.rename("ltmain.sh.new", "ltmain.sh") + create_dir_unless_exists(build_folder) + os.chdir(build_folder) + print("Configuring igraph...") retcode = subprocess.call( - ["./configure", "--disable-tls", "--disable-gmp"], + [ + os.path.join(source_folder, "configure"), + "--disable-tls", + "--disable-gmp", + ], env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), ) if retcode: @@ -261,13 +279,25 @@ def compile_in(self, folder): finally: os.chdir(cwd) - def copy_build_artifacts_from(self, source, to, libraries): - create_dir_unless_exists(to) - ensure_dir_does_not_exist(to, "include") - ensure_dir_does_not_exist(to, "lib") - shutil.copytree(os.path.join(source, "include"), os.path.join(to, "include")) - shutil.copytree(os.path.join(source, "src", ".libs"), os.path.join(to, "lib")) - with open(os.path.join(to, "build.cfg"), "w") as f: + def copy_build_artifacts( + self, source_folder, build_folder, install_folder, libraries + ): + create_dir_unless_exists(install_folder) + + ensure_dir_does_not_exist(install_folder, "include") + ensure_dir_does_not_exist(install_folder, "lib") + + shutil.copytree( + os.path.join(source_folder, "include"), + os.path.join(install_folder, "include"), + ) + create_dir_unless_exists(install_folder, "lib") + + for fname in glob.glob(os.path.join(build_folder, "include", "*.h")): + shutil.copy(fname, os.path.join(install_folder, "include")) + for fname in glob.glob(os.path.join(build_folder, "src", ".libs", "libigraph.*")): + shutil.copy(fname, os.path.join(install_folder, "lib")) + with open(os.path.join(install_folder, "build.cfg"), "w") as f: f.write(repr(libraries)) return True @@ -295,8 +325,6 @@ def __init__(self): self._has_pkgconfig = None self.excluded_include_dirs = [] self.excluded_library_dirs = [] - self.pre_build_hooks = [] - self.post_build_hooks = [] self.wait = True @property @@ -331,9 +359,9 @@ def run(self): sys.exit(1) # Check whether we have already compiled igraph in a previous run. - # If so, it should be found in vendor/build/igraph/include and - # vendor/build/igraph/lib - if os.path.exists(os.path.join("vendor", "build", "igraph")): + # If so, it should be found in vendor/install/igraph/include and + # vendor/install/igraph/lib + if os.path.exists(os.path.join("vendor", "install", "igraph")): buildcfg.use_vendored_igraph() detected = True else: @@ -381,31 +409,32 @@ def run(self): ) buildcfg.configure(ext) - # Run any pre-build hooks - for hook in buildcfg.pre_build_hooks: - hook(self) - # Run the original build_ext command build_ext.run(self) - # Run any post-build hooks - for hook in buildcfg.post_build_hooks: - hook(self) - return custom_build_ext def compile_igraph_from_vendor_source(self): """Compiles igraph from the vendored source code inside `vendor/igraph/source`. This folder typically comes from a git submodule. """ - path = os.path.join("vendor", "source", "igraph") - print("We are going to compile the C core of igraph from %s" % path) + source_folder = os.path.join("vendor", "source", "igraph") + build_folder = os.path.join("vendor", "build", "igraph") + install_folder = os.path.join("vendor", "install", "igraph") + + print("We are going to compile the C core of igraph.") + print(" Source folder: %s" % source_folder) + print(" Build folder: %s" % build_folder) + print(" Install folder: %s" % install_folder) print("") igraph_builder = IgraphCCoreBuilder() - libraries = igraph_builder.compile_in(path) - if not libraries or not igraph_builder.copy_build_artifacts_from( - path, to=os.path.join("vendor", "build", "igraph"), libraries=libraries + libraries = igraph_builder.compile_in(build_folder, source_folder=source_folder) + if not libraries or not igraph_builder.copy_build_artifacts( + source_folder=source_folder, + build_folder=build_folder, + install_folder=install_folder, + libraries=libraries, ): print("Could not compile the C core of igraph.") print("") @@ -509,14 +538,14 @@ def replace_static_libraries(self, only=None, exclusions=None): self.extra_objects.append(static_lib) def use_vendored_igraph(self): - """Assumes that igraph is built already in ``vendor/build/igraph`` and sets up + """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up the include and library paths and the library names accordingly.""" - buildcfg.include_dirs = [os.path.join("vendor", "build", "igraph", "include")] - buildcfg.library_dirs = [os.path.join("vendor", "build", "igraph", "lib")] + buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include")] + buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" - buildcfg_file = os.path.join("vendor", "build", "igraph", "build.cfg") + buildcfg_file = os.path.join("vendor", "install", "igraph", "build.cfg") if os.path.exists(buildcfg_file): buildcfg.libraries = eval(open(buildcfg_file).read()) From fa8ee9ff879a7e525df1a393a22a2c4db96ee8b7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 13:35:10 +0100 Subject: [PATCH 0102/1892] make manylinux wheel builds work again --- .dockerignore | 12 ++++++++++++ .gitignore | 3 +++ MANIFEST.in | 2 ++ docker/manylinux.docker | 11 ++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index 55ffc8b8f..4bd21acf4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,15 @@ +# ignore git's own files +.git + # ignore build commands so we don't trigger unnecessary rebuilds during iteration docker/* Makefile + +# ignore build and dist folders for python +build/* +dist/* + +# also ignore build folder for vendored stuff +vendor/build/* +vendor/install/* + diff --git a/.gitignore b/.gitignore index 75366fadb..f98dc2da8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,8 @@ igraph/*.so .tox .venv/ docker/wheelhouse +vendor/build/ +vendor/install/ Pipfile +Pipfile.lock diff --git a/MANIFEST.in b/MANIFEST.in index cfccd9149..084185f38 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,3 +6,5 @@ include scripts/mkdoc.sh include scripts/epydoc-patched include scripts/epydoc.cfg include test/*.py +graft vendor/source/igraph + diff --git a/docker/manylinux.docker b/docker/manylinux.docker index ff070a312..77d8ce18e 100644 --- a/docker/manylinux.docker +++ b/docker/manylinux.docker @@ -1,17 +1,22 @@ # manylinux.docker -- dockerfile for generating manylinux wheel -FROM quay.io/pypa/manylinux1_x86_64 +FROM quay.io/pypa/manylinux2010_x86_64 MAINTAINER awinter.public@gmail.com RUN echo "multilib_policy=best" >> /etc/yum.conf -RUN yum install -y zlib-devel libxml2-devel +RUN yum install -y flex bison zlib-devel libxml2-devel # kill static libxml2 as per http://lists.gnu.org/archive/html/igraph-help/2014-05/msg00045.html -RUN mv /usr/lib64/libxml2.a /usr/lib64/libxml2.a.org +# RUN mv /usr/lib64/libxml2.a /usr/lib64/libxml2.a.org COPY ./ /python-igraph/ RUN mkdir /wheelhouse WORKDIR /python-igraph +# Do not create bytecode files -- this will make setup.py try to compile the C +# extension first, without compiling the C core. This should be fixed in +# setup.py later, though. +ENV PYTHONDONTWRITEBYTECODE=1 + RUN /bin/bash -c "for PYBIN in /opt/python/*/bin; do \ echo \$PYBIN; \ \$PYBIN/pip wheel . -w /wheelhouse; \ From 146908c70ca4b827af09a8ef3ac4f4abe4279959 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 14:27:49 +0100 Subject: [PATCH 0103/1892] Removed cibuildwheel from Travis; takes too much time --- .travis.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6ca39e75..b08dd1d47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ python: - "3.5" - "3.6" - "3.7" + - "3.8" - "pypy" - "pypy3" @@ -16,28 +17,15 @@ addons: - flex - bison -jobs: - include: - - services: docker - - os: osx - language: shell - - os: windows - language: shell - before_install: - - choco install python --version 3.8.0 - - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" - env: global: - - CIBW_BEFORE_BUILD="yum install -y libxml2-devel flex bison" - TWINE_USERNAME=ntamas install: - - python -m pip install tox-travis twine cibuildwheel==1.1.0 + - python -m pip install tox-travis script: - tox - - python -m cibuildwheel --output-dir wheelhouse notifications: email: From e2b379c012a808bc09931f6316dde241f8724e27 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 14:47:30 +0100 Subject: [PATCH 0104/1892] Travis: drop support for PyPy, keep PyPy3 only; try building on OSX and Windows --- .travis.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b08dd1d47..63e86000d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ python: - "3.6" - "3.7" - "3.8" - - "pypy" - "pypy3" addons: @@ -17,9 +16,16 @@ addons: - flex - bison -env: - global: - - TWINE_USERNAME=ntamas +jobs: + include: + - services: docker + - os: osx + language: shell + - os: windows + language: shell + before_install: + - choco install python --version 3.8.0 + - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" install: - python -m pip install tox-travis From 48172ab26c40164d5cca70ed171b007774109fec Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 21:29:35 +0100 Subject: [PATCH 0105/1892] giving it another go with cibuildwheel --- .travis.yml | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 63e86000d..1bce82a49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,20 +18,36 @@ addons: jobs: include: - - services: docker - - os: osx + - stage: test + services: docker + install: + - python -m pip install tox-travis + script: + - tox + - stage: wheels + services: docker language: shell - - os: windows + install: + - python -m pip install cibuildwheel==1.1.0 + script: + - python -m cibuildwheel --output-dir wheelhouse + - stage: wheels + os: osx + language: shell + install: + - python -m pip install cibuildwheel==1.1.0 + script: + - python -m cibuildwheel --output-dir wheelhouse + - stage: wheels + os: windows language: shell before_install: - choco install python --version 3.8.0 - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" - -install: - - python -m pip install tox-travis - -script: - - tox + install: + - python -m pip install cibuildwheel==1.1.0 + script: + - python -m cibuildwheel --output-dir wheelhouse notifications: email: From 5f0e3c3351480d42ded9b248150a6ff7baae3069 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 21:41:15 +0100 Subject: [PATCH 0106/1892] giving it another go with cibuildwheel, chapter 2 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1bce82a49..76feb1227 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,13 @@ addons: - flex - bison +install: + - python -m pip install tox-travis + jobs: include: - stage: test services: docker - install: - - python -m pip install tox-travis script: - tox - stage: wheels From d86e533ba54b2402e3786f333147f297b330beaa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Jan 2020 22:02:55 +0100 Subject: [PATCH 0107/1892] giving it another go with cibuildwheel, chapter 3 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76feb1227..baa43f14c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,13 @@ addons: install: - python -m pip install tox-travis +script: + - tox + jobs: include: - stage: test services: docker - script: - - tox - stage: wheels services: docker language: shell From b29a193092b9a0cf69f9da7d63af3d4c7730c414 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 17:11:21 +0100 Subject: [PATCH 0108/1892] Travis: use sudo for the cibuildwheel part on Linux --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index baa43f14c..2870d6bc8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ jobs: - stage: wheels services: docker language: shell + sudo: true install: - python -m pip install cibuildwheel==1.1.0 script: From 4b835efc5ac86f4fad7caa81f5361deb1bfbf37e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 18:13:06 +0100 Subject: [PATCH 0109/1892] another attempt at sudoing in Travis --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2870d6bc8..bcc827284 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,9 +29,8 @@ jobs: - stage: wheels services: docker language: shell - sudo: true install: - - python -m pip install cibuildwheel==1.1.0 + - sudo python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse - stage: wheels From 57ad5c5e6dbdf7a9e84693c429fa4c51a1240a4f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 18:44:12 +0100 Subject: [PATCH 0110/1892] install flex and gfortran in cibuildwheel step --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index bcc827284..c3c08fc43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ jobs: services: docker language: shell install: + - sudo apt install gfortran flex bison - sudo python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse From 00862b0c3e09a6323cc201efb48718e2804ae3ce Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 22:03:47 +0100 Subject: [PATCH 0111/1892] install flex and gfortran in cibuildwheel Docker image, not outside --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c3c08fc43..20490942f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,8 +29,9 @@ jobs: - stage: wheels services: docker language: shell + env: + - CIBW_BEFORE_BUILD=apt install -y flex bison gfortran install: - - sudo apt install gfortran flex bison - sudo python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse From 230070f4d4467ef44046c8365d18518a5e0bea43 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 22:59:59 +0100 Subject: [PATCH 0112/1892] Travis: we need yum inside the cibuildwheel container, not apt --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20490942f..76c63bca1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: services: docker language: shell env: - - CIBW_BEFORE_BUILD=apt install -y flex bison gfortran + - CIBW_BEFORE_BUILD=yum install -y flex bison install: - sudo python -m pip install cibuildwheel==1.1.0 script: From a5fccb6571078c72884928244dfb6a151590fcf1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 23:28:24 +0100 Subject: [PATCH 0113/1892] Travis: quote environment variables properly --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 76c63bca1..ce288e233 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: services: docker language: shell env: - - CIBW_BEFORE_BUILD=yum install -y flex bison + - CIBW_BEFORE_BUILD="yum install -y flex bison" install: - sudo python -m pip install cibuildwheel==1.1.0 script: From 7d6acd04e0d93da62d47c428b89125c269e08036 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jan 2020 23:53:50 +0100 Subject: [PATCH 0114/1892] Travis: also install libxml2-devel and libz-devel in CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ce288e233..5eb9e3d22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: services: docker language: shell env: - - CIBW_BEFORE_BUILD="yum install -y flex bison" + - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel" install: - sudo python -m pip install cibuildwheel==1.1.0 script: From 8b50d487054e090f4ac6264e76d753dce8d20eb0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Jan 2020 01:49:08 +0100 Subject: [PATCH 0115/1892] Travis: increase verbosity of pip wheel step to figure out why it takes so long --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5eb9e3d22..f074aff33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel" + - CIBW_BUILD_VERBOSITY=1 install: - sudo python -m pip install cibuildwheel==1.1.0 script: From 7fbb79a27cf453cf0af1d0f3ff4c36a4ebf3b61b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Jan 2020 23:22:30 +0100 Subject: [PATCH 0116/1892] added custom setup.py command to build the C core only, hopefully useful in Travis CI --- .travis.yml | 2 +- setup.py | 94 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index f074aff33..893c9a7e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: services: docker language: shell env: - - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel" + - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_BUILD_VERBOSITY=1 install: - sudo python -m pip install cibuildwheel==1.1.0 diff --git a/setup.py b/setup.py index ff8547e37..4a67ddada 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ ########################################################################### -from setuptools import setup, Extension +from setuptools import setup, Command, Extension import distutils.ccompiler import glob @@ -295,7 +295,9 @@ def copy_build_artifacts( for fname in glob.glob(os.path.join(build_folder, "include", "*.h")): shutil.copy(fname, os.path.join(install_folder, "include")) - for fname in glob.glob(os.path.join(build_folder, "src", ".libs", "libigraph.*")): + for fname in glob.glob( + os.path.join(build_folder, "src", ".libs", "libigraph.*") + ): shutil.copy(fname, os.path.join(install_folder, "lib")) with open(os.path.join(install_folder, "build.cfg"), "w") as f: f.write(repr(libraries)) @@ -339,6 +341,35 @@ def has_pkgconfig(self): self._has_pkgconfig = False return self._has_pkgconfig + @property + def build_c_core(self): + """Returns a class representing a custom setup.py command that builds + the C core of igraph. + + This is used in CI environments where we want to build the C core of + igraph once and then build the Python interface for various Python + versions without having to recompile the C core all the time. + + If is also used as a custom building block of `build_ext`. + """ + + buildcfg = self + + class build_c_core(Command): + description = "Compile the C core of igraph only" + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + buildcfg.c_core_built = buildcfg.compile_igraph_from_vendor_source() + + return build_c_core + @property def build_ext(self): """Returns a class that can be used as a replacement for the @@ -361,33 +392,16 @@ def run(self): # Check whether we have already compiled igraph in a previous run. # If so, it should be found in vendor/install/igraph/include and # vendor/install/igraph/lib - if os.path.exists(os.path.join("vendor", "install", "igraph")): - buildcfg.use_vendored_igraph() - detected = True - else: - detected = False - - # If igraph is provided as a git submodule, use that - if not detected: - if os.path.isfile( - os.path.join("vendor", "source", "igraph", "configure.ac") - ): - detected = buildcfg.compile_igraph_from_vendor_source() - if detected: - buildcfg.use_vendored_igraph() - else: - sys.exit(1) - - # Try detecting with pkg-config if we haven't found the submodule - if not detected: - if buildcfg.use_pkgconfig: - detected = buildcfg.detect_from_pkgconfig() - else: - detected = False + self.run_command("build_c_core") + if not buildcfg.c_core_built: + # Try detecting with pkg-config if we haven't found the submodule + detected = ( + buildcfg.use_pkgconfig and buildcfg.detect_from_pkgconfig() + ) - # Fall back to an educated guess if everything else failed - if not detected: - buildcfg.use_educated_guess() + # Fall back to an educated guess if everything else failed + if not detected: + buildcfg.use_educated_guess() # Replaces library names with full paths to static libraries # where possible. libm.a is excluded because it caused problems @@ -418,11 +432,22 @@ def compile_igraph_from_vendor_source(self): """Compiles igraph from the vendored source code inside `vendor/igraph/source`. This folder typically comes from a git submodule. """ + if os.path.exists(os.path.join("vendor", "install", "igraph")): + # Vendored igraph already compiled and installed, just use it + self.use_vendored_igraph() + return True + + if not os.path.isfile( + os.path.join("vendor", "source", "igraph", "configure.ac") + ): + # No git submodule present with vendored source + return False + source_folder = os.path.join("vendor", "source", "igraph") build_folder = os.path.join("vendor", "build", "igraph") install_folder = os.path.join("vendor", "install", "igraph") - print("We are going to compile the C core of igraph.") + print("We are going to build the C core of igraph.") print(" Source folder: %s" % source_folder) print(" Build folder: %s" % build_folder) print(" Install folder: %s" % install_folder) @@ -438,9 +463,9 @@ def compile_igraph_from_vendor_source(self): ): print("Could not compile the C core of igraph.") print("") - return False - else: - return True + sys.exit(1) + + self.use_vendored_igraph() def configure(self, ext): """Configures the given Extension object using this build configuration.""" @@ -673,7 +698,10 @@ def use_educated_guess(self): "Topic :: Scientific/Engineering :: Bio-Informatics", "Topic :: Software Development :: Libraries :: Python Modules", ], - cmdclass={"build_ext": buildcfg.build_ext}, + cmdclass={ + "build_c_core": buildcfg.build_c_core, # used by CI + "build_ext": buildcfg.build_ext, + }, ) if sys.version_info > (3, 0): From 08bca7c4cea8b1f1298a6451a1a375ba61fb85ea Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Jan 2020 23:59:49 +0100 Subject: [PATCH 0117/1892] Travis: okay, Linux works, now try to make it work for macOS as well --- .travis.yml | 3 ++- setup.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 893c9a7e4..610617b4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,6 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - - CIBW_BUILD_VERBOSITY=1 install: - sudo python -m pip install cibuildwheel==1.1.0 script: @@ -39,6 +38,8 @@ jobs: - stage: wheels os: osx language: shell + env: + - CIBW_BEFORE_BUILD="python setup.py build_c_core" install: - python -m pip install cibuildwheel==1.1.0 script: diff --git a/setup.py b/setup.py index 4a67ddada..33d6cca30 100644 --- a/setup.py +++ b/setup.py @@ -466,6 +466,7 @@ def compile_igraph_from_vendor_source(self): sys.exit(1) self.use_vendored_igraph() + return True def configure(self, ext): """Configures the given Extension object using this build configuration.""" From 87de92444aea5715f5242d410e48cec203e2070f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Jan 2020 21:17:10 +0100 Subject: [PATCH 0118/1892] Travis: run unit tests on the built wheels to see if they work --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 610617b4f..7fb4b3a67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + - CIBW_TEST_COMMAND="python setup.py test" install: - sudo python -m pip install cibuildwheel==1.1.0 script: @@ -40,6 +41,7 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="python setup.py build_c_core" + - CIBW_TEST_COMMAND="python setup.py test" install: - python -m pip install cibuildwheel==1.1.0 script: From 30703b8cc1fb222a868db28e4eb4ef909e19f0e5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Jan 2020 21:43:18 +0100 Subject: [PATCH 0119/1892] remove Windows build from Travis, trying it on Appveyor instead --- .travis.yml | 10 ---------- appveyor.yml | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 appveyor.yml diff --git a/.travis.yml b/.travis.yml index 7fb4b3a67..d5cffd9e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,16 +46,6 @@ jobs: - python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse - - stage: wheels - os: windows - language: shell - before_install: - - choco install python --version 3.8.0 - - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" - install: - - python -m pip install cibuildwheel==1.1.0 - script: - - python -m cibuildwheel --output-dir wheelhouse notifications: email: diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..3a4381216 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,11 @@ +image: + - Visual Studio 2015 + +build_script: + - cmd: pip install cibuildwheel==1.1.0 + - cmd: cibuildwheel --output-dir wheelhouse + +artifacts: + - path: "wheelhouse\\*.whl" + name: Wheels + From 3ac4fbf62ad68bde3bb64483ef774eb11518d05f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:36:22 +0100 Subject: [PATCH 0120/1892] reorganized codebase a bit, tests are now in tests/ --- MANIFEST.in | 4 +- igraph/test/__init__.py | 55 ------------ {test => scripts}/doctests.py | 0 setup.py | 8 +- src/{ => _igraph}/arpackobject.c | 0 src/{ => _igraph}/arpackobject.h | 0 src/{ => _igraph}/attributes.c | 0 src/{ => _igraph}/attributes.h | 0 src/{ => _igraph}/bfsiter.c | 0 src/{ => _igraph}/bfsiter.h | 0 src/{ => _igraph}/common.c | 0 src/{ => _igraph}/common.h | 0 src/{ => _igraph}/convert.c | 0 src/{ => _igraph}/convert.h | 0 src/{ => _igraph}/edgeobject.c | 0 src/{ => _igraph}/edgeobject.h | 0 src/{ => _igraph}/edgeseqobject.c | 0 src/{ => _igraph}/edgeseqobject.h | 0 src/{ => _igraph}/error.c | 0 src/{ => _igraph}/error.h | 0 src/{ => _igraph}/filehandle.c | 0 src/{ => _igraph}/filehandle.h | 0 src/{ => _igraph}/graphobject.c | 0 src/{ => _igraph}/graphobject.h | 0 src/{ => _igraph}/igraphmodule.c | 0 src/{ => _igraph}/igraphmodule_api.h | 0 src/{ => _igraph}/indexing.c | 0 src/{ => _igraph}/indexing.h | 0 src/{ => _igraph}/platform.h | 0 src/{ => _igraph}/py2compat.c | 0 src/{ => _igraph}/py2compat.h | 0 src/{ => _igraph}/pyhelpers.c | 0 src/{ => _igraph}/pyhelpers.h | 0 src/{ => _igraph}/random.c | 0 src/{ => _igraph}/random.h | 0 src/{ => _igraph}/vertexobject.c | 0 src/{ => _igraph}/vertexobject.h | 0 src/{ => _igraph}/vertexseqobject.c | 0 src/{ => _igraph}/vertexseqobject.h | 0 {igraph => src/igraph}/__init__.py | 0 {igraph => src/igraph}/app/__init__.py | 0 {igraph => src/igraph}/app/shell.py | 0 {igraph => src/igraph}/clustering.py | 0 {igraph => src/igraph}/compat.py | 0 {igraph => src/igraph}/configuration.py | 0 {igraph => src/igraph}/cut.py | 0 {igraph => src/igraph}/datatypes.py | 0 {igraph => src/igraph}/drawing/__init__.py | 0 {igraph => src/igraph}/drawing/baseclasses.py | 0 {igraph => src/igraph}/drawing/colors.py | 0 {igraph => src/igraph}/drawing/coord.py | 0 {igraph => src/igraph}/drawing/edge.py | 0 {igraph => src/igraph}/drawing/graph.py | 0 {igraph => src/igraph}/drawing/metamagic.py | 0 {igraph => src/igraph}/drawing/shapes.py | 0 {igraph => src/igraph}/drawing/text.py | 0 {igraph => src/igraph}/drawing/utils.py | 0 {igraph => src/igraph}/drawing/vertex.py | 0 {igraph => src/igraph}/formula.py | 0 {igraph => src/igraph}/layout.py | 0 {igraph => src/igraph}/matching.py | 0 {igraph => src/igraph}/remote/__init__.py | 0 {igraph => src/igraph}/remote/gephi.py | 0 {igraph => src/igraph}/remote/nexus.py | 0 {igraph => src/igraph}/statistics.py | 0 {igraph => src/igraph}/summary.py | 0 {igraph => src/igraph}/utils.py | 0 {igraph => src/igraph}/vendor/__init__.py | 0 {igraph => src/igraph}/vendor/texttable.py | 0 test.sh | 59 ------------- test/cytoscape_test.py | 86 ------------------- test/unittests.py | 22 ----- tests/__init__.py | 0 igraph/test/atlas.py => tests/test_atlas.py | 19 ++-- .../attributes.py => tests/test_attributes.py | 18 ++-- igraph/test/basic.py => tests/test_basic.py | 12 +-- .../bipartite.py => tests/test_bipartite.py | 2 +- .../test/cliques.py => tests/test_cliques.py | 48 +++++------ .../colortests.py => tests/test_colortests.py | 6 +- .../conversion.py => tests/test_conversion.py | 0 .../test_decomposition.py | 18 ++-- .../test/edgeseq.py => tests/test_edgeseq.py | 24 +++--- igraph/test/flow.py => tests/test_flow.py | 8 +- .../test/foreign.py => tests/test_foreign.py | 3 +- igraph/test/games.py => tests/test_games.py | 0 .../generators.py => tests/test_generators.py | 4 +- .../homepage.py => tests/test_homepage.py | 0 .../indexing.py => tests/test_indexing.py | 6 +- .../test_isomorphism.py | 2 +- .../iterators.py => tests/test_iterators.py | 0 .../test/layouts.py => tests/test_layouts.py | 16 ++-- .../matching.py => tests/test_matching.py | 0 .../operators.py => tests/test_operators.py | 4 +- igraph/test/rng.py => tests/test_rng.py | 0 .../separators.py => tests/test_separators.py | 0 .../spectral.py => tests/test_spectral.py | 0 .../structural.py => tests/test_structural.py | 20 ++--- .../test_unicode_issues.py | 4 +- .../vertexseq.py => tests/test_vertexseq.py | 32 +++---- igraph/test/walks.py => tests/test_walks.py | 8 +- {igraph/test => tests}/utils.py | 2 +- tox.ini | 3 +- 102 files changed, 140 insertions(+), 353 deletions(-) delete mode 100644 igraph/test/__init__.py rename {test => scripts}/doctests.py (100%) rename src/{ => _igraph}/arpackobject.c (100%) rename src/{ => _igraph}/arpackobject.h (100%) rename src/{ => _igraph}/attributes.c (100%) rename src/{ => _igraph}/attributes.h (100%) rename src/{ => _igraph}/bfsiter.c (100%) rename src/{ => _igraph}/bfsiter.h (100%) rename src/{ => _igraph}/common.c (100%) rename src/{ => _igraph}/common.h (100%) rename src/{ => _igraph}/convert.c (100%) rename src/{ => _igraph}/convert.h (100%) rename src/{ => _igraph}/edgeobject.c (100%) rename src/{ => _igraph}/edgeobject.h (100%) rename src/{ => _igraph}/edgeseqobject.c (100%) rename src/{ => _igraph}/edgeseqobject.h (100%) rename src/{ => _igraph}/error.c (100%) rename src/{ => _igraph}/error.h (100%) rename src/{ => _igraph}/filehandle.c (100%) rename src/{ => _igraph}/filehandle.h (100%) rename src/{ => _igraph}/graphobject.c (100%) rename src/{ => _igraph}/graphobject.h (100%) rename src/{ => _igraph}/igraphmodule.c (100%) rename src/{ => _igraph}/igraphmodule_api.h (100%) rename src/{ => _igraph}/indexing.c (100%) rename src/{ => _igraph}/indexing.h (100%) rename src/{ => _igraph}/platform.h (100%) rename src/{ => _igraph}/py2compat.c (100%) rename src/{ => _igraph}/py2compat.h (100%) rename src/{ => _igraph}/pyhelpers.c (100%) rename src/{ => _igraph}/pyhelpers.h (100%) rename src/{ => _igraph}/random.c (100%) rename src/{ => _igraph}/random.h (100%) rename src/{ => _igraph}/vertexobject.c (100%) rename src/{ => _igraph}/vertexobject.h (100%) rename src/{ => _igraph}/vertexseqobject.c (100%) rename src/{ => _igraph}/vertexseqobject.h (100%) rename {igraph => src/igraph}/__init__.py (100%) rename {igraph => src/igraph}/app/__init__.py (100%) rename {igraph => src/igraph}/app/shell.py (100%) rename {igraph => src/igraph}/clustering.py (100%) rename {igraph => src/igraph}/compat.py (100%) rename {igraph => src/igraph}/configuration.py (100%) rename {igraph => src/igraph}/cut.py (100%) rename {igraph => src/igraph}/datatypes.py (100%) rename {igraph => src/igraph}/drawing/__init__.py (100%) rename {igraph => src/igraph}/drawing/baseclasses.py (100%) rename {igraph => src/igraph}/drawing/colors.py (100%) rename {igraph => src/igraph}/drawing/coord.py (100%) rename {igraph => src/igraph}/drawing/edge.py (100%) rename {igraph => src/igraph}/drawing/graph.py (100%) rename {igraph => src/igraph}/drawing/metamagic.py (100%) rename {igraph => src/igraph}/drawing/shapes.py (100%) rename {igraph => src/igraph}/drawing/text.py (100%) rename {igraph => src/igraph}/drawing/utils.py (100%) rename {igraph => src/igraph}/drawing/vertex.py (100%) rename {igraph => src/igraph}/formula.py (100%) rename {igraph => src/igraph}/layout.py (100%) rename {igraph => src/igraph}/matching.py (100%) rename {igraph => src/igraph}/remote/__init__.py (100%) rename {igraph => src/igraph}/remote/gephi.py (100%) rename {igraph => src/igraph}/remote/nexus.py (100%) rename {igraph => src/igraph}/statistics.py (100%) rename {igraph => src/igraph}/summary.py (100%) rename {igraph => src/igraph}/utils.py (100%) rename {igraph => src/igraph}/vendor/__init__.py (100%) rename {igraph => src/igraph}/vendor/texttable.py (100%) delete mode 100755 test.sh delete mode 100755 test/cytoscape_test.py delete mode 100755 test/unittests.py create mode 100644 tests/__init__.py rename igraph/test/atlas.py => tests/test_atlas.py (90%) rename igraph/test/attributes.py => tests/test_attributes.py (95%) rename igraph/test/basic.py => tests/test_basic.py (98%) rename igraph/test/bipartite.py => tests/test_bipartite.py (98%) rename igraph/test/cliques.py => tests/test_cliques.py (86%) rename igraph/test/colortests.py => tests/test_colortests.py (97%) rename igraph/test/conversion.py => tests/test_conversion.py (100%) rename igraph/test/decomposition.py => tests/test_decomposition.py (96%) rename igraph/test/edgeseq.py => tests/test_edgeseq.py (95%) rename igraph/test/flow.py => tests/test_flow.py (97%) rename igraph/test/foreign.py => tests/test_foreign.py (99%) rename igraph/test/games.py => tests/test_games.py (100%) rename igraph/test/generators.py => tests/test_generators.py (97%) rename igraph/test/homepage.py => tests/test_homepage.py (100%) rename igraph/test/indexing.py => tests/test_indexing.py (93%) rename igraph/test/isomorphism.py => tests/test_isomorphism.py (99%) rename igraph/test/iterators.py => tests/test_iterators.py (100%) rename igraph/test/layouts.py => tests/test_layouts.py (95%) rename igraph/test/matching.py => tests/test_matching.py (100%) rename igraph/test/operators.py => tests/test_operators.py (99%) rename igraph/test/rng.py => tests/test_rng.py (100%) rename igraph/test/separators.py => tests/test_separators.py (100%) rename igraph/test/spectral.py => tests/test_spectral.py (100%) rename igraph/test/structural.py => tests/test_structural.py (97%) rename igraph/test/unicode_issues.py => tests/test_unicode_issues.py (88%) rename igraph/test/vertexseq.py => tests/test_vertexseq.py (95%) rename igraph/test/walks.py => tests/test_walks.py (94%) rename {igraph/test => tests}/utils.py (97%) diff --git a/MANIFEST.in b/MANIFEST.in index 084185f38..9f8faf472 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,10 +1,10 @@ include setup.cfg -include src/*.h +include src/_igraph/*.h include MANIFEST.in include COPYING include scripts/mkdoc.sh include scripts/epydoc-patched include scripts/epydoc.cfg -include test/*.py +include tests/*.py graft vendor/source/igraph diff --git a/igraph/test/__init__.py b/igraph/test/__init__.py deleted file mode 100644 index 75e44872b..000000000 --- a/igraph/test/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -import sys -import unittest -from igraph.test import basic, layouts, games, foreign, structural, flow, \ - spectral, attributes, cliques, decomposition, operators, generators, \ - isomorphism, colortests, vertexseq, edgeseq, iterators, bipartite, \ - conversion, rng, separators, indexing, atlas, matching, homepage, \ - walks, unicode_issues - - -def suite(): - return unittest.TestSuite([ - basic.suite(), - layouts.suite(), - generators.suite(), - games.suite(), - foreign.suite(), - structural.suite(), - flow.suite(), - spectral.suite(), - attributes.suite(), - vertexseq.suite(), - edgeseq.suite(), - cliques.suite(), - decomposition.suite(), - conversion.suite(), - operators.suite(), - isomorphism.suite(), - iterators.suite(), - bipartite.suite(), - colortests.suite(), - rng.suite(), - separators.suite(), - indexing.suite(), - atlas.suite(), - matching.suite(), - homepage.suite(), - walks.suite(), - unicode_issues.suite() - ]) - - -def run_tests(verbosity=1): - runner = unittest.TextTestRunner(verbosity=verbosity).run - result = runner(suite()) - return result.wasSuccessful() - - -# Make nosetest skip run_tests -run_tests.__test__ = False - -if __name__ == "__main__": - if run_tests(verbosity=255): - sys.exit(0) - else: - sys.exit(1) diff --git a/test/doctests.py b/scripts/doctests.py similarity index 100% rename from test/doctests.py rename to scripts/doctests.py diff --git a/setup.py b/setup.py index 33d6cca30..65d07f013 100644 --- a/setup.py +++ b/setup.py @@ -633,7 +633,7 @@ def use_educated_guess(self): buildcfg.process_args_from_command_line() # Define the extension -sources = glob.glob(os.path.join("src", "*.c")) +sources = glob.glob(os.path.join("src", "_igraph", "*.c")) igraph_extension = Extension("igraph._igraph", sources) description = """Python interface to the igraph high performance graph @@ -652,7 +652,7 @@ def use_educated_guess(self): Many thanks to the maintainers of this page! """ -headers = ["src/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] +headers = ["src/_igraph/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] options = dict( name="python-igraph", @@ -664,17 +664,15 @@ def use_educated_guess(self): author="Tamas Nepusz", author_email="ntamas@gmail.com", ext_modules=[igraph_extension], - package_dir={"igraph": "igraph"}, + package_dir={"igraph": "src/igraph"}, packages=[ "igraph", - "igraph.test", "igraph.app", "igraph.drawing", "igraph.remote", "igraph.vendor", ], scripts=["scripts/igraph"], - test_suite="igraph.test.suite", headers=headers, platforms="ALL", keywords=[ diff --git a/src/arpackobject.c b/src/_igraph/arpackobject.c similarity index 100% rename from src/arpackobject.c rename to src/_igraph/arpackobject.c diff --git a/src/arpackobject.h b/src/_igraph/arpackobject.h similarity index 100% rename from src/arpackobject.h rename to src/_igraph/arpackobject.h diff --git a/src/attributes.c b/src/_igraph/attributes.c similarity index 100% rename from src/attributes.c rename to src/_igraph/attributes.c diff --git a/src/attributes.h b/src/_igraph/attributes.h similarity index 100% rename from src/attributes.h rename to src/_igraph/attributes.h diff --git a/src/bfsiter.c b/src/_igraph/bfsiter.c similarity index 100% rename from src/bfsiter.c rename to src/_igraph/bfsiter.c diff --git a/src/bfsiter.h b/src/_igraph/bfsiter.h similarity index 100% rename from src/bfsiter.h rename to src/_igraph/bfsiter.h diff --git a/src/common.c b/src/_igraph/common.c similarity index 100% rename from src/common.c rename to src/_igraph/common.c diff --git a/src/common.h b/src/_igraph/common.h similarity index 100% rename from src/common.h rename to src/_igraph/common.h diff --git a/src/convert.c b/src/_igraph/convert.c similarity index 100% rename from src/convert.c rename to src/_igraph/convert.c diff --git a/src/convert.h b/src/_igraph/convert.h similarity index 100% rename from src/convert.h rename to src/_igraph/convert.h diff --git a/src/edgeobject.c b/src/_igraph/edgeobject.c similarity index 100% rename from src/edgeobject.c rename to src/_igraph/edgeobject.c diff --git a/src/edgeobject.h b/src/_igraph/edgeobject.h similarity index 100% rename from src/edgeobject.h rename to src/_igraph/edgeobject.h diff --git a/src/edgeseqobject.c b/src/_igraph/edgeseqobject.c similarity index 100% rename from src/edgeseqobject.c rename to src/_igraph/edgeseqobject.c diff --git a/src/edgeseqobject.h b/src/_igraph/edgeseqobject.h similarity index 100% rename from src/edgeseqobject.h rename to src/_igraph/edgeseqobject.h diff --git a/src/error.c b/src/_igraph/error.c similarity index 100% rename from src/error.c rename to src/_igraph/error.c diff --git a/src/error.h b/src/_igraph/error.h similarity index 100% rename from src/error.h rename to src/_igraph/error.h diff --git a/src/filehandle.c b/src/_igraph/filehandle.c similarity index 100% rename from src/filehandle.c rename to src/_igraph/filehandle.c diff --git a/src/filehandle.h b/src/_igraph/filehandle.h similarity index 100% rename from src/filehandle.h rename to src/_igraph/filehandle.h diff --git a/src/graphobject.c b/src/_igraph/graphobject.c similarity index 100% rename from src/graphobject.c rename to src/_igraph/graphobject.c diff --git a/src/graphobject.h b/src/_igraph/graphobject.h similarity index 100% rename from src/graphobject.h rename to src/_igraph/graphobject.h diff --git a/src/igraphmodule.c b/src/_igraph/igraphmodule.c similarity index 100% rename from src/igraphmodule.c rename to src/_igraph/igraphmodule.c diff --git a/src/igraphmodule_api.h b/src/_igraph/igraphmodule_api.h similarity index 100% rename from src/igraphmodule_api.h rename to src/_igraph/igraphmodule_api.h diff --git a/src/indexing.c b/src/_igraph/indexing.c similarity index 100% rename from src/indexing.c rename to src/_igraph/indexing.c diff --git a/src/indexing.h b/src/_igraph/indexing.h similarity index 100% rename from src/indexing.h rename to src/_igraph/indexing.h diff --git a/src/platform.h b/src/_igraph/platform.h similarity index 100% rename from src/platform.h rename to src/_igraph/platform.h diff --git a/src/py2compat.c b/src/_igraph/py2compat.c similarity index 100% rename from src/py2compat.c rename to src/_igraph/py2compat.c diff --git a/src/py2compat.h b/src/_igraph/py2compat.h similarity index 100% rename from src/py2compat.h rename to src/_igraph/py2compat.h diff --git a/src/pyhelpers.c b/src/_igraph/pyhelpers.c similarity index 100% rename from src/pyhelpers.c rename to src/_igraph/pyhelpers.c diff --git a/src/pyhelpers.h b/src/_igraph/pyhelpers.h similarity index 100% rename from src/pyhelpers.h rename to src/_igraph/pyhelpers.h diff --git a/src/random.c b/src/_igraph/random.c similarity index 100% rename from src/random.c rename to src/_igraph/random.c diff --git a/src/random.h b/src/_igraph/random.h similarity index 100% rename from src/random.h rename to src/_igraph/random.h diff --git a/src/vertexobject.c b/src/_igraph/vertexobject.c similarity index 100% rename from src/vertexobject.c rename to src/_igraph/vertexobject.c diff --git a/src/vertexobject.h b/src/_igraph/vertexobject.h similarity index 100% rename from src/vertexobject.h rename to src/_igraph/vertexobject.h diff --git a/src/vertexseqobject.c b/src/_igraph/vertexseqobject.c similarity index 100% rename from src/vertexseqobject.c rename to src/_igraph/vertexseqobject.c diff --git a/src/vertexseqobject.h b/src/_igraph/vertexseqobject.h similarity index 100% rename from src/vertexseqobject.h rename to src/_igraph/vertexseqobject.h diff --git a/igraph/__init__.py b/src/igraph/__init__.py similarity index 100% rename from igraph/__init__.py rename to src/igraph/__init__.py diff --git a/igraph/app/__init__.py b/src/igraph/app/__init__.py similarity index 100% rename from igraph/app/__init__.py rename to src/igraph/app/__init__.py diff --git a/igraph/app/shell.py b/src/igraph/app/shell.py similarity index 100% rename from igraph/app/shell.py rename to src/igraph/app/shell.py diff --git a/igraph/clustering.py b/src/igraph/clustering.py similarity index 100% rename from igraph/clustering.py rename to src/igraph/clustering.py diff --git a/igraph/compat.py b/src/igraph/compat.py similarity index 100% rename from igraph/compat.py rename to src/igraph/compat.py diff --git a/igraph/configuration.py b/src/igraph/configuration.py similarity index 100% rename from igraph/configuration.py rename to src/igraph/configuration.py diff --git a/igraph/cut.py b/src/igraph/cut.py similarity index 100% rename from igraph/cut.py rename to src/igraph/cut.py diff --git a/igraph/datatypes.py b/src/igraph/datatypes.py similarity index 100% rename from igraph/datatypes.py rename to src/igraph/datatypes.py diff --git a/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py similarity index 100% rename from igraph/drawing/__init__.py rename to src/igraph/drawing/__init__.py diff --git a/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py similarity index 100% rename from igraph/drawing/baseclasses.py rename to src/igraph/drawing/baseclasses.py diff --git a/igraph/drawing/colors.py b/src/igraph/drawing/colors.py similarity index 100% rename from igraph/drawing/colors.py rename to src/igraph/drawing/colors.py diff --git a/igraph/drawing/coord.py b/src/igraph/drawing/coord.py similarity index 100% rename from igraph/drawing/coord.py rename to src/igraph/drawing/coord.py diff --git a/igraph/drawing/edge.py b/src/igraph/drawing/edge.py similarity index 100% rename from igraph/drawing/edge.py rename to src/igraph/drawing/edge.py diff --git a/igraph/drawing/graph.py b/src/igraph/drawing/graph.py similarity index 100% rename from igraph/drawing/graph.py rename to src/igraph/drawing/graph.py diff --git a/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py similarity index 100% rename from igraph/drawing/metamagic.py rename to src/igraph/drawing/metamagic.py diff --git a/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py similarity index 100% rename from igraph/drawing/shapes.py rename to src/igraph/drawing/shapes.py diff --git a/igraph/drawing/text.py b/src/igraph/drawing/text.py similarity index 100% rename from igraph/drawing/text.py rename to src/igraph/drawing/text.py diff --git a/igraph/drawing/utils.py b/src/igraph/drawing/utils.py similarity index 100% rename from igraph/drawing/utils.py rename to src/igraph/drawing/utils.py diff --git a/igraph/drawing/vertex.py b/src/igraph/drawing/vertex.py similarity index 100% rename from igraph/drawing/vertex.py rename to src/igraph/drawing/vertex.py diff --git a/igraph/formula.py b/src/igraph/formula.py similarity index 100% rename from igraph/formula.py rename to src/igraph/formula.py diff --git a/igraph/layout.py b/src/igraph/layout.py similarity index 100% rename from igraph/layout.py rename to src/igraph/layout.py diff --git a/igraph/matching.py b/src/igraph/matching.py similarity index 100% rename from igraph/matching.py rename to src/igraph/matching.py diff --git a/igraph/remote/__init__.py b/src/igraph/remote/__init__.py similarity index 100% rename from igraph/remote/__init__.py rename to src/igraph/remote/__init__.py diff --git a/igraph/remote/gephi.py b/src/igraph/remote/gephi.py similarity index 100% rename from igraph/remote/gephi.py rename to src/igraph/remote/gephi.py diff --git a/igraph/remote/nexus.py b/src/igraph/remote/nexus.py similarity index 100% rename from igraph/remote/nexus.py rename to src/igraph/remote/nexus.py diff --git a/igraph/statistics.py b/src/igraph/statistics.py similarity index 100% rename from igraph/statistics.py rename to src/igraph/statistics.py diff --git a/igraph/summary.py b/src/igraph/summary.py similarity index 100% rename from igraph/summary.py rename to src/igraph/summary.py diff --git a/igraph/utils.py b/src/igraph/utils.py similarity index 100% rename from igraph/utils.py rename to src/igraph/utils.py diff --git a/igraph/vendor/__init__.py b/src/igraph/vendor/__init__.py similarity index 100% rename from igraph/vendor/__init__.py rename to src/igraph/vendor/__init__.py diff --git a/igraph/vendor/texttable.py b/src/igraph/vendor/texttable.py similarity index 100% rename from igraph/vendor/texttable.py rename to src/igraph/vendor/texttable.py diff --git a/test.sh b/test.sh deleted file mode 100755 index f6249f4bb..000000000 --- a/test.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -if [ x$1 == x-d -a -x /usr/bin/valgrind ]; then - # Checking memory leaks with Valgrind - echo "Valgrind memory leak debugging enabled" - FNAME=/tmp/igraph_${RANDOM}.supp - cat /usr/lib/valgrind/python.supp >$FNAME - cat $0|awk 'BEGIN { ok=0 } /[S]UPPRESSIONS/ { first=1 } { if (first) { ok=1; first=0; } else if (ok) { print; } }' >>$FNAME - PRE="valgrind --tool=memcheck --leak-check=yes --trace-children=yes --suppressions=$FNAME" - shift -else - PRE="" -fi -DYLD_LIBRARY_PATH=src/.libs LD_LIBRARY_PATH=src/.libs $PRE python $1 interfaces/python/setup.py test -if [ x$FNAME != x ]; then rm -f $FNAME; fi - -exit 0 -################## SUPPRESSIONS for Valgrind ######################## -{ - - Memcheck:Cond - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so -} -{ - - Memcheck:Cond - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/tls/i686/cmov/libc-2.3.5.so - obj:/lib/ld-2.3.5.so - fun:_dl_open - obj:/lib/tls/i686/cmov/libdl-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/tls/i686/cmov/libdl-2.3.5.so - fun:dlopen - fun:_PyImport_GetDynLoadFunc - fun:_PyImport_LoadDynamicModule -} -{ - - Memcheck:Cond - obj:/lib/ld-2.3.5.so - obj:/lib/tls/i686/cmov/libc-2.3.5.so - obj:/lib/ld-2.3.5.so - fun:_dl_open - obj:/lib/tls/i686/cmov/libdl-2.3.5.so - obj:/lib/ld-2.3.5.so - obj:/lib/tls/i686/cmov/libdl-2.3.5.so - fun:dlopen - fun:_PyImport_GetDynLoadFunc - fun:_PyImport_LoadDynamicModule - obj:/usr/bin/python2.4 - obj:/usr/bin/python2.4 -} - diff --git a/test/cytoscape_test.py b/test/cytoscape_test.py deleted file mode 100755 index 111ab1cba..000000000 --- a/test/cytoscape_test.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -"""Simple script that tests CytoscapeGraphDrawer. - -This script is kept separate from the unit tests as it is very -hard to test for the correctness of CytoscapeGraphDrawer without -a working instance of Cytoscape. - -Prerequisites for running this test: - - 1. Start Cytoscape - 2. Activate the Cytoscape RPC plugin, listening at port 9000 - -""" - -from igraph import Graph -from igraph.drawing.graph import CytoscapeGraphDrawer - -def test(): - g = Graph.GRG(100, 0.2) - - ### Adding network attributes - g["name"] = "Network name" - g["version"] = 5 - g["obsolete"] = False - g["density"] = g.density() - - ### Adding vertex attributes - # String attribute - g.vs["name"] = ["Node %d" % (i+1) for i in xrange(g.vcount())] - # Integer attribute - g.vs["degree"] = g.degree() - # Float attribute - g.vs["pagerank"] = g.pagerank() - # Boolean attribute - g.vs["even"] = [i % 2 for i in xrange(g.vcount())] - # Mixed attribute - g.vs["mixed"] = ["abc", 123, None, 1.0] * ((g.vcount()+3) / 4) - # Special attribute with Hungarian accents - g.vs[0]["name"] = u"árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP" - - ### Adding edge attributes - # String attribute - g.es["name"] = ["Edge %d -- %d" % edge.tuple for edge in g.es] - # Integer attribute - g.es["multiplicity"] = g.count_multiple() - # Float attribute - g.es["betweenness"] = g.edge_betweenness() - # Boolean attribute - g.es["even"] = [i % 2 for i in xrange(g.ecount())] - # Mixed attribute - g.es["mixed"] = [u"yay", 123, None, 0.7] * ((g.ecount()+3) / 4) - - # Sending graph - drawer = CytoscapeGraphDrawer() - drawer.draw(g, layout="fr") - - # Fetching graph - g2 = drawer.fetch() - del g2.vs["hiddenLabel"] - del g2.es["interaction"] - - # Check isomorphism - result = g2.isomorphic(g) - if not result: - raise ValueError("g2 not isomorphic to g") - - # Check the graph attributes - if set(g.attributes()) != set(g2.attributes()): - raise ValueError("Graph attribute name set mismatch") - for attr_name in g.attributes(): - if g[attr_name] != g2[attr_name]: - raise ValueError("Graph attribute mismatch for %r" % attr_name) - - # Check the vertex attribute names - if set(g.vertex_attributes()) != set(g2.vertex_attributes()): - raise ValueError("Vertex attribute name set mismatch") - - # Check the edge attribute names - if set(g.edge_attributes()) != set(g2.edge_attributes()): - raise ValueError("Edge attribute name set mismatch") - - -if __name__ == "__main__": - test() - diff --git a/test/unittests.py b/test/unittests.py deleted file mode 100755 index eb0f993ba..000000000 --- a/test/unittests.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -""" -Simple script that runs the unit tests of igraph. -""" - -import sys - - -def run_unittests(): - from igraph.test import run_tests - if "-v" in sys.argv: - verbosity = 2 - else: - verbosity = 1 - return run_tests(verbosity=verbosity) - - -if __name__ == "__main__": - if run_unittests(): - sys.exit(0) - else: - sys.exit(1) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/igraph/test/atlas.py b/tests/test_atlas.py similarity index 90% rename from igraph/test/atlas.py rename to tests/test_atlas.py index 5580ac53b..438c2a04a 100644 --- a/igraph/test/atlas.py +++ b/tests/test_atlas.py @@ -4,12 +4,13 @@ import unittest from igraph import * -class TestBase(unittest.TestCase): + +class AtlasTestBase(object): def testPageRank(self): for idx, g in enumerate(self.__class__.graphs): try: pr = g.pagerank() - except Exception, ex: + except Exception as ex: self.assertTrue(False, msg="PageRank calculation threw exception for graph #%d: %s" % (idx, ex)) raise @@ -35,7 +36,7 @@ def testEigenvectorCentrality(self): try: ec, eval = g.evcent(return_eigenvalue=True) - except Exception, ex: + except Exception as ex: self.assertTrue(False, msg="Eigenvector centrality threw exception for graph #%d: %s" % (idx, ex)) raise @@ -62,7 +63,7 @@ def testEigenvectorCentrality(self): msg="Minimum eigenvector centrality is less than 0 for graph #%d" % idx) ec2 = [sum(ec[u.index] for u in v.predecessors()) for v in g.vs] - for i in xrange(n): + for i in range(n): self.assertAlmostEqual(ec[i] * eval, ec2[i], places=7, \ msg="Eigenvector centrality in graph #%d seems to be invalid "\ "for vertex %d" % (idx, i)) @@ -94,13 +95,13 @@ def testAuthorityScore(self): self.assertTrue(min(sc) >= 0, \ msg="Minimum authority score is less than 0 for graph #%d" % idx) -class GraphAtlasTests(TestBase): - graphs = [Graph.Atlas(i) for i in xrange(1253)] +class GraphAtlasTests(unittest.TestCase, AtlasTestBase): + graphs = [Graph.Atlas(i) for i in range(1253)] skip_graphs = set([180]) -class IsoclassTests(TestBase): - graphs = [Graph.Isoclass(3, i, directed=True) for i in xrange(16)] + \ - [Graph.Isoclass(4, i, directed=True) for i in xrange(218)] +class IsoclassTests(unittest.TestCase, AtlasTestBase): + graphs = [Graph.Isoclass(3, i, directed=True) for i in range(16)] + \ + [Graph.Isoclass(4, i, directed=True) for i in range(218)] skip_graphs = set([136]) def suite(): diff --git a/igraph/test/attributes.py b/tests/test_attributes.py similarity index 95% rename from igraph/test/attributes.py rename to tests/test_attributes.py index abc15e7ae..65eda85c9 100644 --- a/igraph/test/attributes.py +++ b/tests/test_attributes.py @@ -42,10 +42,10 @@ def testEdgeAttributes(self): def testMassVertexAttributeAssignment(self): g = Graph.Full(5) - g.vs.set_attribute_values("name", range(5)) - self.assertTrue(g.vs.get_attribute_values("name") == range(5)) - g.vs["name"] = range(5,10) - self.assertTrue(g.vs["name"] == range(5,10)) + g.vs.set_attribute_values("name", list(range(5))) + self.assertTrue(g.vs.get_attribute_values("name") == list(range(5))) + g.vs["name"] = list(range(5,10)) + self.assertTrue(g.vs["name"] == list(range(5,10))) g.vs["name2"] = (1,2,3,4,6) self.assertTrue(g.vs["name2"] == [1,2,3,4,6]) g.vs.set_attribute_values("name", [2]) @@ -53,10 +53,10 @@ def testMassVertexAttributeAssignment(self): def testMassEdgeAttributeAssignment(self): g = Graph.Full(5) - g.es.set_attribute_values("name", range(10)) - self.assertTrue(g.es.get_attribute_values("name") == range(10)) - g.es["name"] = range(10,20) - self.assertTrue(g.es["name"] == range(10,20)) + g.es.set_attribute_values("name", list(range(10))) + self.assertTrue(g.es.get_attribute_values("name") == list(range(10))) + g.es["name"] = list(range(10,20)) + self.assertTrue(g.es["name"] == list(range(10,20))) g.es["name2"] = (1,2,3,4,6,1,2,3,4,6) self.assertTrue(g.es["name2"] == [1,2,3,4,6,1,2,3,4,6]) g.es.set_attribute_values("name", [2]) @@ -129,7 +129,7 @@ def testCombinationRandom(self): g = self.g g.simplify(combine_edges="random") del g.es["weight2"] - for i in xrange(100): + for i in range(100): self.assertTrue(g.es[0]["weight"] in (1, 2)) self.assertTrue(g.es[1]["weight"] == 3) self.assertTrue(g.es[2]["weight"] in (4, 5, 6)) diff --git a/igraph/test/basic.py b/tests/test_basic.py similarity index 98% rename from igraph/test/basic.py rename to tests/test_basic.py index ee4d233fd..88c7deea4 100644 --- a/igraph/test/basic.py +++ b/tests/test_basic.py @@ -93,30 +93,30 @@ def testAddVertex(self): vertex = g.add_vertex() self.assertTrue(g.vcount() == 1 and g.ecount() == 0) - self.assertEquals(0, vertex.index) + self.assertEqual(0, vertex.index) self.assertFalse("name" in g.vertex_attributes()) vertex = g.add_vertex("foo") self.assertTrue(g.vcount() == 2 and g.ecount() == 0) - self.assertEquals(1, vertex.index) + self.assertEqual(1, vertex.index) self.assertTrue("name" in g.vertex_attributes()) self.assertEqual(g.vs["name"], [None, "foo"]) vertex = g.add_vertex(3) self.assertTrue(g.vcount() == 3 and g.ecount() == 0) - self.assertEquals(2, vertex.index) + self.assertEqual(2, vertex.index) self.assertTrue("name" in g.vertex_attributes()) self.assertEqual(g.vs["name"], [None, "foo", 3]) vertex = g.add_vertex(name="bar") self.assertTrue(g.vcount() == 4 and g.ecount() == 0) - self.assertEquals(3, vertex.index) + self.assertEqual(3, vertex.index) self.assertTrue("name" in g.vertex_attributes()) self.assertEqual(g.vs["name"], [None, "foo", 3, "bar"]) vertex = g.add_vertex(name="frob", spam="cheese", ham=42) self.assertTrue(g.vcount() == 5 and g.ecount() == 0) - self.assertEquals(4, vertex.index) + self.assertEqual(4, vertex.index) self.assertEqual( sorted(g.vertex_attributes()), ["ham", "name", "spam"] ) @@ -264,7 +264,7 @@ def testGraphGetEid(self): g = Graph.Famous("petersen") g.vs["name"] = list("ABCDEFGHIJ") edges_to_ids = dict((v, k) for k, v in enumerate(g.get_edgelist())) - for (source, target), edge_id in edges_to_ids.iteritems(): + for (source, target), edge_id in edges_to_ids.items(): source_name, target_name = g.vs[(source, target)]["name"] self.assertEqual(edge_id, g.get_eid(source, target)) self.assertEqual(edge_id, g.get_eid(source_name, target_name)) diff --git a/igraph/test/bipartite.py b/tests/test_bipartite.py similarity index 98% rename from igraph/test/bipartite.py rename to tests/test_bipartite.py index 0eaa7862c..7ce1e0901 100644 --- a/igraph/test/bipartite.py +++ b/tests/test_bipartite.py @@ -11,7 +11,7 @@ def testCreateBipartite(self): def testFullBipartite(self): g = Graph.Full_Bipartite(10, 5) self.assertTrue(g.vcount() == 15 and g.ecount() == 50 and g.is_directed() == False) - expected = sorted([(i, j) for i in xrange(10) for j in xrange(10, 15)]) + expected = sorted([(i, j) for i in range(10) for j in range(10, 15)]) self.assertTrue(sorted(g.get_edgelist()) == expected) self.assertTrue(g.vs["type"] == [False]*10 + [True]*5) diff --git a/igraph/test/cliques.py b/tests/test_cliques.py similarity index 86% rename from igraph/test/cliques.py rename to tests/test_cliques.py index eabd2e746..1cb2de48e 100644 --- a/igraph/test/cliques.py +++ b/tests/test_cliques.py @@ -1,7 +1,10 @@ +from __future__ import print_function + import unittest + from igraph import * -from igraph.test.foreign import temporary_file -from igraph.test.utils import is_pypy, skipIf + +from .utils import is_pypy, skipIf, temporary_file class CliqueTests(unittest.TestCase): @@ -22,7 +25,7 @@ def testCliques(self): [1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 4, 5], [2, 3, 4], [2, 4, 5], [1, 2, 3, 4], [1, 2, 4, 5]]} - for (lo, hi), exp in tests.iteritems(): + for (lo, hi), exp in tests.items(): self.assertEqual(sorted(exp), sorted(map(sorted, self.g.cliques(lo, hi)))) def testLargestCliques(self): @@ -73,7 +76,7 @@ def testIndependentVertexSets(self): (-1, -1): [(0,), (1,), (2,), (3,), (4,), (0, 3), (0, 4), (1, 2), (2, 3), (2, 4), (3, 4), (0, 3, 4), (2, 3, 4)]} - for (lo, hi), exp in tests.iteritems(): + for (lo, hi), exp in tests.items(): self.assertEqual(exp, self.g1.independent_vertex_sets(lo, hi)) def testLargestIndependentVertexSets(self): @@ -147,11 +150,11 @@ def run(self): self.testGRG() def printIntro(self): - print "n = number of vertices" - print "#cliques = number of maximal cliques found" - print "t1 = time required to determine the clique number" - print "t2 = time required to determine and save all maximal cliques" - print + print("n = number of vertices") + print("#cliques = number of maximal cliques found") + print("t1 = time required to determine the clique number") + print("t2 = time required to determine and save all maximal cliques") + print() def timeit(self, g): start = self.time() @@ -170,43 +173,40 @@ def testRandom(self): 1000:[0.1, 0.2], 10000: [0.001, 0.003, 0.005, 0.01, 0.02]} - print - print "Erdos-Renyi random graphs" - print " n p #cliques t1 t2" + print() + print("Erdos-Renyi random graphs") + print(" n p #cliques t1 t2") for n in sorted(np.keys()): for p in np[n]: g = Graph.Erdos_Renyi(n, p) result = self.timeit(g) - print "%8d %8.3f %8d %8.4fs %8.4fs" % \ - tuple([n, p] + list(result)) + print("%8d %8.3f %8d %8.4fs %8.4fs" % tuple([n, p] + list(result))) def testMoonMoser(self): ns = [15, 27, 33] - print - print "Moon-Moser graphs" - print " n exp_clqs #cliques t1 t2" + print() + print("Moon-Moser graphs") + print(" n exp_clqs #cliques t1 t2") for n in ns: n3 = n/3 types = range(n3) * 3 el = [(i, j) for i in range(n) for j in range(i+1,n) if types[i] != types[j]] g = Graph(n, el) result = self.timeit(g) - print "%8d %8d %8d %8.4fs %8.4fs" % \ - tuple([n, (3**(n/3))] + list(result)) + print("%8d %8d %8d %8.4fs %8.4fs" % tuple([n, (3**(n/3))] + list(result))) def testGRG(self): ns = [100, 1000, 5000, 10000, 25000, 50000] - print - print "Geometric random graphs" - print " n d #cliques t1 t2" + print() + print("Geometric random graphs") + print(" n d #cliques t1 t2") for n in ns: d = 2. / (n ** 0.5) g = Graph.GRG(n, d) result = self.timeit(g) - print "%8d %8.3f %8d %8.4fs %8.4fs" % \ - tuple([n, d] + list(result)) + print("%8d %8.3f %8d %8.4fs %8.4fs" % tuple([n, d] + list(result))) def suite(): diff --git a/igraph/test/colortests.py b/tests/test_colortests.py similarity index 97% rename from igraph/test/colortests.py rename to tests/test_colortests.py index 960687c4f..df7332ef1 100644 --- a/igraph/test/colortests.py +++ b/tests/test_colortests.py @@ -1,6 +1,10 @@ import unittest -from itertools import izip +try: + from itertools import izip +except ImportError: + izip = zip # Python 3.x + from igraph import * class ColorTests(unittest.TestCase): diff --git a/igraph/test/conversion.py b/tests/test_conversion.py similarity index 100% rename from igraph/test/conversion.py rename to tests/test_conversion.py diff --git a/igraph/test/decomposition.py b/tests/test_decomposition.py similarity index 96% rename from igraph/test/decomposition.py rename to tests/test_decomposition.py index e43404eda..90b8341b9 100644 --- a/igraph/test/decomposition.py +++ b/tests/test_decomposition.py @@ -222,8 +222,8 @@ def testInfomap(self): self.assertMembershipsEqual(cl, [1,1,1,1,2,2,2,1,0,1,2,1,1,1,0,0,2,1,0,1,0,1] + [0]*12) # Smoke testing with vertex and edge weights - v_weights = [random.randint(1, 5) for _ in xrange(g.vcount())] - e_weights = [random.randint(1, 5) for _ in xrange(g.ecount())] + v_weights = [random.randint(1, 5) for _ in range(g.vcount())] + e_weights = [random.randint(1, 5) for _ in range(g.ecount())] cl = g.community_infomap(edge_weights=e_weights) cl = g.community_infomap(vertex_weights=v_weights) cl = g.community_infomap(edge_weights=e_weights, vertex_weights=v_weights) @@ -269,7 +269,7 @@ def testOptimalModularity(self): self.assertMembershipsEqual(cl, [0, 0, 1, 0, 1]) self.assertAlmostEqual(cl.q, 0.08, places=7) - ws = [i % 5 for i in xrange(g.ecount())] + ws = [i % 5 for i in range(g.ecount())] cl = g.community_optimal_modularity(weights=ws) self.assertAlmostEqual(cl.q, g.modularity(cl.membership, weights=ws), places=7) @@ -282,7 +282,7 @@ def testOptimalModularity(self): 2, 2, 3, 2, 2]) self.assertAlmostEqual(cl.q, 0.4197896, places=7) - ws = [2+(i % 3) for i in xrange(g.ecount())] + ws = [2+(i % 3) for i in range(g.ecount())] cl = g.community_optimal_modularity(weights=ws) self.assertAlmostEqual(cl.q, g.modularity(cl.membership, weights=ws), places=7) @@ -297,7 +297,7 @@ def testSpinglass(self): # Spinglass community detection is a bit unstable, so run it three times ok = False - for i in xrange(3): + for i in range(3): cl = g.community_spinglass() if self.reindexMembership(cl) == [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2]: ok = True @@ -332,8 +332,8 @@ def testCohesiveBlocks1(self): cbs = g.cohesive_blocks() self.genericTests(cbs) self.assertEqual(sorted(list(cbs)), - [range(0, 5), range(18), [0, 1, 2, 3, 4, 6, 7, 8, 9, 10], - range(6, 10), range(12, 16), range(12, 17)]) + [list(range(0, 5)), list(range(18)), [0, 1, 2, 3, 4, 6, 7, 8, 9, 10], + list(range(6, 10)), list(range(12, 16)), list(range(12, 17))]) self.assertEqual(cbs.cohesions(), [1, 2, 2, 4, 3, 3]) self.assertEqual(cbs.max_cohesions(), [4, 4, 4, 4, 4, 1, 3, 3, 3, 3, 2, 1, 3, 3, 3, 3, 2, 1]) @@ -350,8 +350,8 @@ def testCohesiveBlocks2(self): cbs = g.cohesive_blocks() self.genericTests(cbs) - expected_blocks = [range(7), range(23), range(7)+range(16, 23), - range(6, 16), [6, 7, 10, 13]] + expected_blocks = [list(range(7)), list(range(23)), list(range(7))+list(range(16, 23)), + list(range(6, 16)), [6, 7, 10, 13]] observed_blocks = sorted(sorted(int(x)-1 for x in g.vs[bl]["name"]) for bl in cbs) self.assertEqual(expected_blocks, observed_blocks) self.assertTrue(cbs.cohesions() == [1, 2, 2, 5, 3]) diff --git a/igraph/test/edgeseq.py b/tests/test_edgeseq.py similarity index 95% rename from igraph/test/edgeseq.py rename to tests/test_edgeseq.py index 2b31e50bf..d15af3002 100644 --- a/igraph/test/edgeseq.py +++ b/tests/test_edgeseq.py @@ -1,8 +1,10 @@ # vim:ts=4 sw=4 sts=4: import unittest + from igraph import * -from igraph.test.utils import is_pypy, skipIf + +from .utils import is_pypy, skipIf try: import numpy as np @@ -16,13 +18,13 @@ def setUp(self): def testHash(self): data = {} n = self.g.ecount() - for i in xrange(n): + for i in range(n): code1 = hash(self.g.es[i]) code2 = hash(self.g.es[i]) self.assertEqual(code1, code2) data[self.g.es[i]] = i - for i in xrange(n): + for i in range(n): self.assertEqual(i, data[self.g.es[i]]) def testRichCompare(self): @@ -132,7 +134,7 @@ def testCreation(self): def testIndexing(self): n = self.g.ecount() - for i in xrange(n): + for i in range(n): self.assertEqual(i, self.g.es[i].index) self.assertEqual(n-i-1, self.g.es[-i-1].index) self.assertRaises(IndexError, self.g.es.__getitem__, n) @@ -142,7 +144,7 @@ def testIndexing(self): @skipIf(np is None, "test case depends on NumPy") def testNumPyIndexing(self): n = self.g.ecount() - for i in xrange(n): + for i in range(n): arr = np.array([i]) self.assertEqual(i, self.g.es[arr[0]].index) @@ -159,11 +161,11 @@ def testPartialAttributeAssignment(self): only_even = self.g.es.select(lambda e: (e.index % 2 == 0)) only_even["test"] = [0]*len(only_even) - expected = [[0,i][i % 2] for i in xrange(self.g.ecount())] + expected = [[0,i][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test"] == expected) only_even["test2"] = range(23) - expected = [[i//2, None][i % 2] for i in xrange(self.g.ecount())] + expected = [[i//2, None][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test2"] == expected) def testSequenceReusing(self): @@ -187,7 +189,7 @@ def testSequenceReusing(self): def testAllSequence(self): self.assertTrue(len(self.g.es) == 45) - self.assertTrue(self.g.es["test"] == range(45)) + self.assertTrue(self.g.es["test"] == list(range(45))) def testEmptySequence(self): empty_es = self.g.es.select(None) @@ -209,7 +211,7 @@ def testCallableFilteringSelect(self): only_even = self.g.es.select(lambda e: (e.index % 2 == 0)) self.assertTrue(len(only_even) == 23) self.assertRaises(KeyError, only_even.__getitem__, "nonexistent") - self.assertTrue(only_even["test"] == [i*2 for i in xrange(23)]) + self.assertTrue(only_even["test"] == [i*2 for i in range(23)]) def testChainedCallableFilteringSelect(self): only_div_six = self.g.es.select(lambda e: (e.index % 2 == 0), @@ -238,7 +240,7 @@ def testIntegerFilteringSelect(self): self.assertTrue(subset["test"] == [2,3,4,2]) def testIterableFilteringSelect(self): - subset = self.g.es.select(xrange(5,8)) + subset = self.g.es.select(range(5,8)) self.assertTrue(len(subset) == 3) self.assertTrue(subset["test"] == [5,6,7]) @@ -253,7 +255,7 @@ def testSliceFilteringSelect(self): def testKeywordFilteringSelect(self): g = Graph.Barabasi(1000, 2) g.es["betweenness"] = g.edge_betweenness() - g.es["parity"] = [i % 2 for i in xrange(g.ecount())] + g.es["parity"] = [i % 2 for i in range(g.ecount())] self.assertTrue(len(g.es(betweenness_gt=10)) < 2000) self.assertTrue(len(g.es(betweenness_gt=10, parity=0)) < 2000) diff --git a/igraph/test/flow.py b/tests/test_flow.py similarity index 97% rename from igraph/test/flow.py rename to tests/test_flow.py index 4fa0c2cec..b420c8995 100644 --- a/igraph/test/flow.py +++ b/tests/test_flow.py @@ -61,9 +61,9 @@ def constructSimpleGraph(self, directed=False): return g def constructLadderGraph(self, directed=False): - el = zip(range(0, 5), range(1, 6)) - el += zip(range(6, 11), range(7, 12)) - el += zip(range(0, 6), range(6, 12)) + el = list(zip(range(0, 5), range(1, 6))) + el += list(zip(range(6, 11), range(7, 12))) + el += list(zip(range(0, 6), range(6, 12))) g = Graph(el, directed=directed) return g @@ -206,7 +206,7 @@ def testDirected(self): def testRandomGRG(self): g = Graph.GRG(25, 0.4) self.validate_gomory_hu_tree(g, g.gomory_hu_tree()) - g.es["capacity"] = [randint(0, 10) for _ in xrange(g.ecount())] + g.es["capacity"] = [randint(0, 10) for _ in range(g.ecount())] self.validate_gomory_hu_tree(g, g.gomory_hu_tree("capacity")) def validate_gomory_hu_tree(self, g, t): diff --git a/igraph/test/foreign.py b/tests/test_foreign.py similarity index 99% rename from igraph/test/foreign.py rename to tests/test_foreign.py index 7afb02ae8..5c4ff1d30 100644 --- a/igraph/test/foreign.py +++ b/tests/test_foreign.py @@ -5,7 +5,8 @@ import warnings from igraph import * -from igraph.test.utils import temporary_file + +from .utils import temporary_file class ForeignTests(unittest.TestCase): diff --git a/igraph/test/games.py b/tests/test_games.py similarity index 100% rename from igraph/test/games.py rename to tests/test_games.py diff --git a/igraph/test/generators.py b/tests/test_generators.py similarity index 97% rename from igraph/test/generators.py rename to tests/test_generators.py index 61ad2b041..ddb64222e 100644 --- a/igraph/test/generators.py +++ b/tests/test_generators.py @@ -86,13 +86,13 @@ def testFullCitation(self): el=g.get_edgelist() el.sort() self.assertTrue(not g.is_directed()) - self.assertTrue(el == [(x, y) for x in xrange(19) for y in xrange(x+1, 20)]) + self.assertTrue(el == [(x, y) for x in range(19) for y in range(x+1, 20)]) g=Graph.Full_Citation(20, True) el=g.get_edgelist() el.sort() self.assertTrue(g.is_directed()) - self.assertTrue(el == [(x, y) for x in xrange(1, 20) for y in xrange(x)]) + self.assertTrue(el == [(x, y) for x in range(1, 20) for y in range(x)]) self.assertRaises(InternalError, Graph.Full_Citation, -2) diff --git a/igraph/test/homepage.py b/tests/test_homepage.py similarity index 100% rename from igraph/test/homepage.py rename to tests/test_homepage.py diff --git a/igraph/test/indexing.py b/tests/test_indexing.py similarity index 93% rename from igraph/test/indexing.py rename to tests/test_indexing.py index aefa83cea..301afbc56 100644 --- a/igraph/test/indexing.py +++ b/tests/test_indexing.py @@ -8,7 +8,7 @@ def testSingleEdgeRetrieval(self): for v1, v2 in g.get_edgelist(): self.assertEqual(g[v1, v2], 1) self.assertEqual(g[v2, v1], 1) - for v1 in xrange(g.vcount()): + for v1 in range(g.vcount()): for v2 in set(range(g.vcount())) - set(g.neighbors(v1)): self.assertEqual(g[v1, v2], 0) self.assertEqual(g[v2, v1], 0) @@ -22,7 +22,7 @@ def testSingleEdgeRetrievalWeights(self): for idx, (v1, v2) in enumerate(g.get_edgelist()): self.assertEqual(g[v1, v2], idx) self.assertEqual(g[v2, v1], idx) - for v1 in xrange(g.vcount()): + for v1 in range(g.vcount()): for v2 in set(range(g.vcount())) - set(g.neighbors(v1)): self.assertEqual(g[v1, v2], 0) self.assertEqual(g[v2, v1], 0) @@ -33,7 +33,7 @@ def testSingleEdgeRetrievalAttrName(self): for idx, (v1, v2) in enumerate(g.get_edgelist()): self.assertEqual(g[v1, v2, "value"], idx+20) self.assertEqual(g[v2, v1, "value"], idx+20) - for v1 in xrange(g.vcount()): + for v1 in range(g.vcount()): for v2 in set(range(g.vcount())) - set(g.neighbors(v1)): self.assertEqual(g[v1, v2, "value"], 0) self.assertEqual(g[v2, v1, "value"], 0) diff --git a/igraph/test/isomorphism.py b/tests/test_isomorphism.py similarity index 99% rename from igraph/test/isomorphism.py rename to tests/test_isomorphism.py index 4a5044a97..9b8fa7437 100644 --- a/igraph/test/isomorphism.py +++ b/tests/test_isomorphism.py @@ -258,7 +258,7 @@ def testCanonicalPermutation(self): # More complicated one: small GRG, random permutation g = Graph.GRG(10, 0.5) - perm = range(10) + perm = list(range(10)) shuffle(perm) g2 = g.permute_vertices(perm) g3 = g.permute_vertices(g.canonical_permutation()) diff --git a/igraph/test/iterators.py b/tests/test_iterators.py similarity index 100% rename from igraph/test/iterators.py rename to tests/test_iterators.py diff --git a/igraph/test/layouts.py b/tests/test_layouts.py similarity index 95% rename from igraph/test/layouts.py rename to tests/test_layouts.py index bcb7ae828..af4c3181c 100644 --- a/igraph/test/layouts.py +++ b/tests/test_layouts.py @@ -118,7 +118,7 @@ def testToPolar(self): layout = Layout([(0, 0), (-1, 1), (0, 1), (1, 1)]) layout.to_radial(min_angle=180, max_angle=0, max_radius=2) exp = [[0., 0.], [-2., 0.], [0., 2.], [2, 0.]] - for idx in xrange(4): + for idx in range(4): self.assertAlmostEqual(layout.coords[idx][0], exp[idx][0], places=3) self.assertAlmostEqual(layout.coords[idx][1], exp[idx][1], places=3) @@ -162,12 +162,12 @@ def layout_test(graph, test_with_dims=(2, 3)): del g["layout"] lo = layout_test(g, test_with_dims=(2,)) self.assertEqual([tuple(item) for item in lo], - zip(range(20), range(20, 40))) + list(zip(range(20), range(20, 40)))) g.vs["z"] = range(40, 60) lo = layout_test(g) self.assertEqual([tuple(item) for item in lo], - zip(range(20), range(20, 40), range(40, 60))) + list(zip(range(20), range(20, 40), range(40, 60)))) def testCircle(self): def test_is_proper_circular_layout(graph, layout): @@ -188,8 +188,8 @@ def test_is_proper_circular_layout(graph, layout): ordered_layout = g.layout("circle", order=order) test_is_proper_circular_layout(g, g.layout("circle")) for v, w in enumerate(order): - self.assertAlmostEquals(layout[v][0], ordered_layout[w][0]) - self.assertAlmostEquals(layout[v][1], ordered_layout[w][1]) + self.assertAlmostEqual(layout[v][0], ordered_layout[w][0]) + self.assertAlmostEqual(layout[v][1], ordered_layout[w][1]) def testDavidsonHarel(self): # Quick smoke testing only @@ -205,11 +205,11 @@ def testFruchtermanReingold(self): lo = g.layout("fr", miny=range(100)) self.assertTrue(isinstance(lo, Layout)) - self.assertTrue(all(lo[i][1] >= i for i in xrange(100))) + self.assertTrue(all(lo[i][1] >= i for i in range(100))) lo = g.layout("fr", miny=range(100), maxy=range(100)) self.assertTrue(isinstance(lo, Layout)) - self.assertTrue(all(lo[i][1] == i for i in xrange(100))) + self.assertTrue(all(lo[i][1] == i for i in range(100))) lo = g.layout("fr", miny=[2]*100, maxy=[3]*100, minx=[4]*100, maxx=[6]*100) self.assertTrue(isinstance(lo, Layout)) @@ -224,7 +224,7 @@ def testFruchtermanReingoldGrid(self): for grid_opt in ["grid", "nogrid", "auto", True, False]: lo = g.layout("fr", miny=range(100), grid=grid_opt) self.assertTrue(isinstance(lo, Layout)) - self.assertTrue(all(lo[i][1] >= i for i in xrange(100))) + self.assertTrue(all(lo[i][1] >= i for i in range(100))) def testKamadaKawai(self): g = Graph.Barabasi(100) diff --git a/igraph/test/matching.py b/tests/test_matching.py similarity index 100% rename from igraph/test/matching.py rename to tests/test_matching.py diff --git a/igraph/test/operators.py b/tests/test_operators.py similarity index 99% rename from igraph/test/operators.py rename to tests/test_operators.py index 78ce419cd..f539389f2 100644 --- a/igraph/test/operators.py +++ b/tests/test_operators.py @@ -1,6 +1,8 @@ import unittest + from igraph import * -from igraph.test.utils import skipIf + +from .utils import skipIf try: import numpy as np diff --git a/igraph/test/rng.py b/tests/test_rng.py similarity index 100% rename from igraph/test/rng.py rename to tests/test_rng.py diff --git a/igraph/test/separators.py b/tests/test_separators.py similarity index 100% rename from igraph/test/separators.py rename to tests/test_separators.py diff --git a/igraph/test/spectral.py b/tests/test_spectral.py similarity index 100% rename from igraph/test/spectral.py rename to tests/test_spectral.py diff --git a/igraph/test/structural.py b/tests/test_structural.py similarity index 97% rename from igraph/test/structural.py rename to tests/test_structural.py index a3affd184..22e6aedb1 100644 --- a/igraph/test/structural.py +++ b/tests/test_structural.py @@ -215,9 +215,9 @@ class BiconnectedComponentTests(unittest.TestCase): def testBiconnectedComponents(self): s = self.g1.biconnected_components() - self.assertTrue(len(s) == 1 and s[0]==range(10)) + self.assertTrue(len(s) == 1 and s[0]==list(range(10))) s, ap = self.g1.biconnected_components(True) - self.assertTrue(len(s) == 1 and s[0]==range(10)) + self.assertTrue(len(s) == 1 and s[0]==list(range(10))) s = self.g3.biconnected_components() self.assertTrue(len(s) == 2 and s[0]==[2,4,5] and s[1]==[0,1,2,3]) @@ -258,7 +258,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness() cl2 = [1., 0.57142, 0.57142, 0.57142, 0.57142] - for idx in xrange(g.vcount()): + for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) g = Graph.Star(5) @@ -266,7 +266,7 @@ def testClosenessCentrality(self): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1) cl2 = [1., 0.25, 0.25, 0.25, 0.25] - for idx in xrange(g.vcount()): + for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) weights = [1] * 4 @@ -274,7 +274,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness(weights=weights) cl2 = [1., 0.57142, 0.57142, 0.57142, 0.57142] - for idx in xrange(g.vcount()): + for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) g = Graph.Star(5) @@ -282,7 +282,7 @@ def testClosenessCentrality(self): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1, weights=weights) cl2 = [1., 0.25, 0.25, 0.25, 0.25] - for idx in xrange(g.vcount()): + for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) # Test for igraph/igraph:#1078 @@ -354,14 +354,14 @@ def testCoreness(self): class NeighborhoodTests(unittest.TestCase): def testNeighborhood(self): g = Graph.Ring(10, circular=False) - self.assertTrue(map(sorted, g.neighborhood()) == \ + self.assertTrue(list(map(sorted, g.neighborhood())) == \ [[0,1], [0,1,2], [1,2,3], [2,3,4], [3,4,5], [4,5,6], \ [5,6,7], [6,7,8], [7,8,9], [8,9]]) - self.assertTrue(map(sorted, g.neighborhood(order=3)) == \ + self.assertTrue(list(map(sorted, g.neighborhood(order=3))) == \ [[0,1,2,3], [0,1,2,3,4], [0,1,2,3,4,5], [0,1,2,3,4,5,6], \ [1,2,3,4,5,6,7], [2,3,4,5,6,7,8], [3,4,5,6,7,8,9], \ [4,5,6,7,8,9], [5,6,7,8,9], [6,7,8,9]]) - self.assertTrue(map(sorted, g.neighborhood(order=3, mindist=2)) == \ + self.assertTrue(list(map(sorted, g.neighborhood(order=3, mindist=2))) == \ [[2,3], [3,4], [0,4,5], [0,1,5,6], \ [1,2,6,7], [2,3,7,8], [3,4,8,9], \ [4,5,9], [5,6], [6,7]]) @@ -528,7 +528,7 @@ def testGetAllSimplePaths(self): def testPathLengthHist(self): g = Graph.Tree(15, 2) h = g.path_length_hist() - self.assertTrue(h.unconnected == 0L) + self.assertTrue(h.unconnected == 0) self.assertTrue([(int(l),x) for l,_,x in h.bins()] == \ [(1,14),(2,19),(3,20),(4,20),(5,16),(6,16)]) g = Graph.Full(5)+Graph.Full(4) diff --git a/igraph/test/unicode_issues.py b/tests/test_unicode_issues.py similarity index 88% rename from igraph/test/unicode_issues.py rename to tests/test_unicode_issues.py index e8c2eb0cb..3dccdc48b 100644 --- a/igraph/test/unicode_issues.py +++ b/tests/test_unicode_issues.py @@ -7,11 +7,11 @@ class UnicodeTests(unittest.TestCase): def testBug128(self): y = [1, 4, 9] g = Graph(n=len(y), directed=True, vertex_attrs={'y': y}) - self.assertEquals(3, g.vcount()) + self.assertEqual(3, g.vcount()) g.add_vertices(1) # Bug #128 would prevent us from reaching the next statement # because an exception would have been thrown here - self.assertEquals(4, g.vcount()) + self.assertEqual(4, g.vcount()) def suite(): diff --git a/igraph/test/vertexseq.py b/tests/test_vertexseq.py similarity index 95% rename from igraph/test/vertexseq.py rename to tests/test_vertexseq.py index 4830fd8e6..80ea27749 100644 --- a/igraph/test/vertexseq.py +++ b/tests/test_vertexseq.py @@ -1,8 +1,10 @@ # vim:ts=4 sw=4 sts=4: import unittest + from igraph import * -from igraph.test.utils import is_pypy, skipIf + +from .utils import is_pypy, skipIf try: import numpy as np @@ -16,19 +18,19 @@ def setUp(self): def testHash(self): data = {} n = self.g.vcount() - for i in xrange(n): + for i in range(n): code1 = hash(self.g.vs[i]) code2 = hash(self.g.vs[i]) self.assertEqual(code1, code2) data[self.g.vs[i]] = i - for i in xrange(n): + for i in range(n): self.assertEqual(i, data[self.g.vs[i]]) def testRichCompare(self): g2 = Graph.Full(10) - for i in xrange(self.g.vcount()): - for j in xrange(self.g.vcount()): + for i in range(self.g.vcount()): + for j in range(self.g.vcount()): self.assertEqual(i == j, self.g.vs[i] == self.g.vs[j]) self.assertEqual(i != j, self.g.vs[i] != self.g.vs[j]) self.assertEqual(i < j, self.g.vs[i] < self.g.vs[j]) @@ -76,15 +78,15 @@ def testIncident(self): "out": "out_edges" } - for i in xrange(g.vcount()): + for i in range(g.vcount()): vertex = g.vs[i] for mode, method_name in method_table.items(): method = getattr(vertex, method_name) - self.assertEquals( + self.assertEqual( g.incident(i, mode=mode), [edge.index for edge in vertex.incident(mode=mode)] ) - self.assertEquals( + self.assertEqual( g.incident(i, mode=mode), [edge.index for edge in method()] ) @@ -93,10 +95,10 @@ def testNeighbors(self): g = Graph.Famous("petersen") g.to_directed() - for i in xrange(g.vcount()): + for i in range(g.vcount()): vertex = g.vs[i] for mode in "all in out".split(): - self.assertEquals( + self.assertEqual( g.neighbors(i, mode=mode), [edge.index for edge in vertex.neighbors(mode=mode)] ) @@ -169,7 +171,7 @@ def testCreation(self): def testIndexing(self): n = self.g.vcount() - for i in xrange(n): + for i in range(n): self.assertEqual(i, self.g.vs[i].index) self.assertEqual(n-i-1, self.g.vs[-i-1].index) self.assertRaises(IndexError, self.g.vs.__getitem__, n) @@ -179,7 +181,7 @@ def testIndexing(self): @skipIf(np is None, "test case depends on NumPy") def testNumPyIndexing(self): n = self.g.vcount() - for i in xrange(self.g.vcount()): + for i in range(self.g.vcount()): arr = np.array([i]) self.assertEqual(i, self.g.vs[arr[0]].index) arr = np.array([-i-1]) @@ -219,7 +221,7 @@ def testSequenceReusing(self): def testAllSequence(self): self.assertTrue(len(self.g.vs) == 10) - self.assertTrue(self.g.vs["test"] == range(10)) + self.assertTrue(self.g.vs["test"] == list(range(10))) def testEmptySequence(self): empty_vs = self.g.vs.select(None) @@ -276,7 +278,7 @@ def testStringFilteringFind(self): self.assertRaises(ValueError, self.g.vs.find, "NoSuchName") def testIterableFilteringSelect(self): - subset = self.g.vs.select(xrange(5,8)) + subset = self.g.vs.select(range(5,8)) self.assertTrue(len(subset) == 3) self.assertTrue(subset["test"] == [5,6,7]) @@ -291,7 +293,7 @@ def testSliceFilteringSelect(self): def testKeywordFilteringSelect(self): g = Graph.Barabasi(10000) g.vs["degree"] = g.degree() - g.vs["parity"] = [i % 2 for i in xrange(g.vcount())] + g.vs["parity"] = [i % 2 for i in range(g.vcount())] l = len(g.vs(degree_gt=30)) self.assertTrue(l < 1000) self.assertTrue(len(g.vs(degree_gt=30, parity=0)) <= 500) diff --git a/igraph/test/walks.py b/tests/test_walks.py similarity index 94% rename from igraph/test/walks.py rename to tests/test_walks.py index 5f41ef1a3..8386bdecd 100644 --- a/igraph/test/walks.py +++ b/tests/test_walks.py @@ -15,7 +15,7 @@ def validate_walk(self, g, walk, start, length, mode="out"): def testRandomWalkUndirected(self): g = Graph.GRG(100, 0.2) - for i in xrange(100): + for i in range(100): start = random.randint(0, g.vcount()-1) length = random.randint(0, 10) walk = g.random_walk(start, length) @@ -24,7 +24,7 @@ def testRandomWalkUndirected(self): def testRandomWalkDirectedOut(self): g = Graph.Tree(121, 3, mode="out") mode = "out" - for i in xrange(100): + for i in range(100): start = 0 length = random.randint(0, 4) walk = g.random_walk(start, length, mode) @@ -33,7 +33,7 @@ def testRandomWalkDirectedOut(self): def testRandomWalkDirectedIn(self): g = Graph.Tree(121, 3, mode="out") mode = "in" - for i in xrange(100): + for i in range(100): start = random.randint(40, g.vcount()-1) length = random.randint(0, 4) walk = g.random_walk(start, length, mode) @@ -42,7 +42,7 @@ def testRandomWalkDirectedIn(self): def testRandomWalkDirectedAll(self): g = Graph.Tree(121, 3, mode="out") mode = "all" - for i in xrange(100): + for i in range(100): start = random.randint(0, g.vcount()-1) length = random.randint(0, 10) walk = g.random_walk(start, length, mode) diff --git a/igraph/test/utils.py b/tests/utils.py similarity index 97% rename from igraph/test/utils.py rename to tests/utils.py index 1a01d78ca..c4fab472f 100644 --- a/igraph/test/utils.py +++ b/tests/utils.py @@ -59,7 +59,7 @@ def temporary_file(content=None, mode=None): tmpf = open(tmpfname, mode) if content is not None: - if isinstance(content, unicode): + if hasattr(content, "encode"): tmpf.write(dedent(content).encode("utf8")) else: tmpf.write(content) diff --git a/tox.ini b/tox.ini index c78a9043d..42c0c0436 100644 --- a/tox.ini +++ b/tox.ini @@ -7,8 +7,7 @@ envlist = py27, py35, py36, py37, pypy, pypy3 [testenv] -commands = - python test/unittests.py -v +commands = python -m unittest deps = setenv = TESTING_IN_TOX=1 From 4ba0aebb857a3137a0a14a83cbad8d1b95375251 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:37:15 +0100 Subject: [PATCH 0121/1892] Travis: trying to run unittests in cibuildwheel, chapter 2 --- .travis.yml | 4 +-- README.md | 86 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index d5cffd9e0..f5a020bcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - - CIBW_TEST_COMMAND="python setup.py test" + - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - sudo python -m pip install cibuildwheel==1.1.0 script: @@ -41,7 +41,7 @@ jobs: language: shell env: - CIBW_BEFORE_BUILD="python setup.py build_c_core" - - CIBW_TEST_COMMAND="python setup.py test" + - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - python -m pip install cibuildwheel==1.1.0 script: diff --git a/README.md b/README.md index c9340b93c..eae63bc6e 100644 --- a/README.md +++ b/README.md @@ -13,34 +13,62 @@ igraph. You can learn more about python-igraph [on our website](http://igraph.org/python/). -## Installation +## Installation from PyPI + +We aim to provide wheels on PyPI for most of the stock Python versions; +typically the three most recent minor releases from Python 3.x. Therefore, +running the following command should work without having to compile anything +during installation: ``` -$ sudo python setup.py install +$ pip install python-igraph ``` -See details in [Installing Python Modules](https://docs.python.org/2/install/). -### Installation with pip on Debian / Ubuntu and derivatives +See details in [Installing Python Modules](https://docs.python.org/3/installing/). + +### Installation from source with pip on Debian / Ubuntu and derivatives + +If you need to compile python-igraph from source for some reason, you need to +install some dependencies first: -Install dependencies ``` $ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev bison flex ``` -and then + +and then run + ``` $ pip install python-igraph ``` +This should compile the C core of igraph as well as the Python extension +automatically. + ## Compiling the development version If you have downloaded the source code from Github and not PyPI, chances are -that you have the latest development version, which might not be compatible -with the latest release of the C core of igraph. Therefore, to install the -bleeding edge version, you need to instruct the setup script to download the -latest development version of the C core as well: +that you have the latest development version, which contains a matching version +of the C core of igraph as a git submodule. Therefore, to install the bleeding +edge version, you need to instruct git to check out the submodules first: + +``` +git submodule update --init +``` + +Then, running the setup script should work if you have a C compiler and the +necessary build dependencies (see the previous section): + +``` +$ sudo python setup.py build +``` + +## Running unit tests + +Unit tests can be executed from the project directory with `tox` or with the +built-in unittest module: ``` -$ sudo python setup.py develop --no-pkg-config --c-core-url https://github.com/igraph/igraph/archive/master.tar.gz +$ python -m unittest ``` ## Contributing @@ -52,37 +80,40 @@ issue on this repository and we'll try to answer. If you have a piece of code that you would like to see included in the main tree, open a PR on this repo. To start developing `python-igraph`, follow the steps below (these are -for UNIX, Windows users should change the system commands a little). +for Linux, Windows users should change the system commands a little). First, clone this repo (e.g. via https) and enter the folder: + ```bash git clone https://github.com/igraph/python-igraph.git cd python-igraph ``` -Second, build both `igraph` and `python-igraph` at the same time: + +Second, check out the necessary git submodules: + ```bash -python setup.py build --c-core-url https://github.com/igraph/igraph/archive/master.tar.gz --no-pkg-config +git submodule update --init ``` -**NOTE**: Building requires `autotools`, a C compiler, and a few more dependencies. -This command creates a subfolder within `build` which you can insert into your -`PYTHONPATH` to import. You need to move out of the main folder to import -because there is a subfolder called `igraph` too. For instance on Linux: +and install igraph in development mode so your changes in the Python source +code are picked up automatically by Python: + ```bash -cd .. -PYTHONPATH=$(pwd)/python-igraph/build/lib.linux-x86_64-3.7:$PYTHONPATH python ->>> import igraph ->>> g = igraph.Graph.Full(10) -... +python setup.py develop ``` -You can now play with your changes and see the results. Every time you -make changes to the `python-graph` code, you need to rebuild by calling -the second step above. After the first build, your `igraph` C core library -is compiled already so rebuilding is much faster. + +**NOTE**: Building requires `autotools`, a C compiler, and a few more dependencies. + +Changes that you make to the Python code do not need any extra action. However, +if you adjust the source code of the C extension, you need to rebuild it by running +`python setup.py develop` again. However, compilation of igraph's C core is +cached in ``vendor/build`` and ``vendor/install`` so subsequent builds are much +faster than the first one as the C core does not need to be recompiled. ## Notes ### Pypy + This version of python-igraph is compatible with [PyPy](http://pypy.org/) and is regularly tested on [PyPy](http://pypy.org/) with ``tox``. However, the PyPy version falls behind the CPython version in terms of performance; for @@ -97,3 +128,4 @@ There are also some subtle differences between the CPython and PyPy versions: - ``GraphBase`` is hashable and iterable in PyPy but not in CPython. Since ``GraphBase`` is internal anyway, this is likely to stay this way. + From ec42ef78c026779552c1e1ff27e2cb65de14882c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:42:38 +0100 Subject: [PATCH 0122/1892] don't wait 10 seconds on Windows when using an educated guess for building igraph --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 65d07f013..2f87992b0 100644 --- a/setup.py +++ b/setup.py @@ -327,7 +327,7 @@ def __init__(self): self._has_pkgconfig = None self.excluded_include_dirs = [] self.excluded_library_dirs = [] - self.wait = True + self.wait = platform.system() != "Windows" @property def has_pkgconfig(self): From 2a2c1810647eadfe4a8e345d87db9248014d7b69 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:45:09 +0100 Subject: [PATCH 0123/1892] adding a message in setup.py when it cannot find the vendored C source --- setup.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 2f87992b0..8cdfecba3 100644 --- a/setup.py +++ b/setup.py @@ -437,10 +437,12 @@ def compile_igraph_from_vendor_source(self): self.use_vendored_igraph() return True - if not os.path.isfile( - os.path.join("vendor", "source", "igraph", "configure.ac") - ): + vendor_source_path = os.path.join("vendor", "source", "igraph") + if not os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): # No git submodule present with vendored source + print("Cannot find vendored igraph source in vendor/source/igraph") + print("Assuming that igraph's C core is already installed") + print("") return False source_folder = os.path.join("vendor", "source", "igraph") From 6b8f1075ddbe09d6da32b0e67366906aa31607da Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:48:42 +0100 Subject: [PATCH 0124/1892] Appveyor: install git submodules --- appveyor.yml | 1 + setup.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3a4381216..208ee43eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,7 @@ image: - Visual Studio 2015 build_script: + - cmd: git submodule update --init - cmd: pip install cibuildwheel==1.1.0 - cmd: cibuildwheel --output-dir wheelhouse diff --git a/setup.py b/setup.py index 8cdfecba3..5cbcc2391 100644 --- a/setup.py +++ b/setup.py @@ -440,8 +440,7 @@ def compile_igraph_from_vendor_source(self): vendor_source_path = os.path.join("vendor", "source", "igraph") if not os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): # No git submodule present with vendored source - print("Cannot find vendored igraph source in vendor/source/igraph") - print("Assuming that igraph's C core is already installed") + print("Cannot find vendored igraph source in " + vendor_source_path) print("") return False From 34f964b59a8090664da0fb0d1a031c0f3cbb82c2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:52:01 +0100 Subject: [PATCH 0125/1892] Appveyor: install stuff required for compiling the C core --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 208ee43eb..339b8767e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,10 @@ image: - Visual Studio 2015 build_script: + - C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S libxml2-devel zip" - cmd: git submodule update --init - cmd: pip install cibuildwheel==1.1.0 - cmd: cibuildwheel --output-dir wheelhouse From fb9f638980f83a3fcfb2e191afce290a08862f8d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 09:54:13 +0100 Subject: [PATCH 0126/1892] Appveyor: we also need libtool --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 339b8767e..85e6880ad 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ image: build_script: - C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S libxml2-devel zip" - cmd: git submodule update --init - cmd: pip install cibuildwheel==1.1.0 From c208fba9c5c7ba76f49d38a8d469ba48b995a879 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:00:30 +0100 Subject: [PATCH 0127/1892] Appveyor: add MSYS2 to path --- appveyor.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 85e6880ad..4d65978a9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,20 @@ image: - Visual Studio 2015 -build_script: +install: - C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S libxml2-devel zip" - - cmd: git submodule update --init - - cmd: pip install cibuildwheel==1.1.0 - - cmd: cibuildwheel --output-dir wheelhouse + - pip install cibuildwheel==1.1.0 + +before_build: + - git submodule update --init --recursive + +build_script: + - set PATH=C:\msys64\usr\bin;%PATH% + - set MSYSTEM=MINGW64 + - cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" From 8a8597ed39c1c13f4739a5af98fef8bdd54d9dad Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:13:39 +0100 Subject: [PATCH 0128/1892] Appveyor: use bash to execute cibuildwheel; might avoid problems in igraph's bootstrap.sh with /dev/null --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 4d65978a9..ede6f057f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ before_build: build_script: - set PATH=C:\msys64\usr\bin;%PATH% - set MSYSTEM=MINGW64 - - cibuildwheel --output-dir wheelhouse + - C:\msys64\usr\bin\bash -lc "cibuildwheel --output-dir wheelhouse" artifacts: - path: "wheelhouse\\*.whl" From 7fa3609c9c17825b4f62c6fa0ebd874314e9defb Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:17:26 +0100 Subject: [PATCH 0129/1892] Appveyor: change to project dir before invoking cibuildwheel --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ede6f057f..e7c8f8944 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ before_build: build_script: - set PATH=C:\msys64\usr\bin;%PATH% - set MSYSTEM=MINGW64 - - C:\msys64\usr\bin\bash -lc "cibuildwheel --output-dir wheelhouse" + - C:\msys64\usr\bin\bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" artifacts: - path: "wheelhouse\\*.whl" From ee7e033445beec7bd2af2ed2173b1b6e55d8dbf0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:27:57 +0100 Subject: [PATCH 0130/1892] use shutil.move() instead of os.rename() because the latter does not work on Windows if the target file exists --- appveyor.yml | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e7c8f8944..9b3fb18c1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ image: install: - C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool" - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S libxml2-devel zip" - pip install cibuildwheel==1.1.0 @@ -14,7 +14,7 @@ before_build: build_script: - set PATH=C:\msys64\usr\bin;%PATH% - set MSYSTEM=MINGW64 - - C:\msys64\usr\bin\bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" + - cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" diff --git a/setup.py b/setup.py index 5cbcc2391..c628de622 100644 --- a/setup.py +++ b/setup.py @@ -240,7 +240,7 @@ def compile_in(self, build_folder, source_folder=None): "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' ) outfp.write(line) - os.rename("ltmain.sh.new", "ltmain.sh") + shutil.move("ltmain.sh.new", "ltmain.sh") create_dir_unless_exists(build_folder) os.chdir(build_folder) From 572d05f8a4deade0e1c10b4c2f10f948b7f29c7a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:39:18 +0100 Subject: [PATCH 0131/1892] Appveyor: run igraph's configure script through sh --- setup.py | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/setup.py b/setup.py index c628de622..ef56d59b6 100644 --- a/setup.py +++ b/setup.py @@ -177,25 +177,8 @@ def preprocess_fallback_config(): ] -def version_variants(version): - """Given an igraph version number, returns a list of possible version - number variants to try when looking for a suitable nightly build of the - C core to download from igraph.org.""" - - result = [version] - - # Strip any release tags - version, _, _ = version.partition(".post") - result.append(version) - - # Add trailing ".0" as needed to ensure that we have at least - # major.minor.patch - parts = version.split(".") - while len(parts) < 3: - parts.append("0") - result.append(".".join(parts)) - - return result +def shellquote(s): + return "'" + s.replace("'", "'\\''") + "'" ########################################################################### @@ -247,12 +230,9 @@ def compile_in(self, build_folder, source_folder=None): print("Configuring igraph...") retcode = subprocess.call( - [ - os.path.join(source_folder, "configure"), - "--disable-tls", - "--disable-gmp", - ], + "sh {0} --disable-tls --disable-gmp".format(shellquote(os.path.join(source_folder, "configure"))), env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), + shell=True ) if retcode: return False From 6fef4136fcf8386c5f4206acac2b48638a2a724a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:44:36 +0100 Subject: [PATCH 0132/1892] Appveyor: try to run configure script through bash again --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 9b3fb18c1..f52c3b258 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ before_build: build_script: - set PATH=C:\msys64\usr\bin;%PATH% - set MSYSTEM=MINGW64 - - cibuildwheel --output-dir wheelhouse + - C:\msys64\usr\bin\bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" artifacts: - path: "wheelhouse\\*.whl" From 82dbd920300a04fb1f44b79247db3c47d99ebbd8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 10:49:32 +0100 Subject: [PATCH 0133/1892] Appveyor: setting up aclocal path --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f52c3b258..726b496e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ before_build: build_script: - set PATH=C:\msys64\usr\bin;%PATH% - set MSYSTEM=MINGW64 - - C:\msys64\usr\bin\bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" + - C:\msys64\usr\bin\bash -lc "export ACLOCAL_PATH=/c/msys64/usr/share/aclocal && cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" artifacts: - path: "wheelhouse\\*.whl" From 7ab36d928cc75c93363b149b0d8bd5e6bb37a9c3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 11:03:01 +0100 Subject: [PATCH 0134/1892] Appveyor: config tweaks --- appveyor.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 726b496e4..10e0e1246 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,20 +1,26 @@ image: - Visual Studio 2015 +environment: + PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% + MSYSTEM: MINGW64 + TARGET_ARCH: "x64" + +platform: + - x64 + install: - - C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S libxml2-devel zip" + - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" + - bash -lc "pacman --noconfirm -Sy" + - bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool" + - bash -lc "pacman --noconfirm -S libxml2-devel zip" - pip install cibuildwheel==1.1.0 before_build: - git submodule update --init --recursive build_script: - - set PATH=C:\msys64\usr\bin;%PATH% - - set MSYSTEM=MINGW64 - - C:\msys64\usr\bin\bash -lc "export ACLOCAL_PATH=/c/msys64/usr/share/aclocal && cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" + - bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" artifacts: - path: "wheelhouse\\*.whl" From 6f079b97f2e7850ceb2720da3922a8fe509a5887 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 11:11:48 +0100 Subject: [PATCH 0135/1892] Appveyor: don't try cibuildwheel in a login shell --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 10e0e1246..548316fbb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,7 +20,7 @@ before_build: - git submodule update --init --recursive build_script: - - bash -lc "cd /c/projects/python-igraph && cibuildwheel --output-dir wheelhouse" + - bash cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" From f8ee57aadd69ea170804aeae7dd1553c529e3ce6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 11:23:37 +0100 Subject: [PATCH 0136/1892] Appveyor: invoke cibuildwheel directly, not via bash --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 548316fbb..6ac70592f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,7 +20,7 @@ before_build: - git submodule update --init --recursive build_script: - - bash cibuildwheel --output-dir wheelhouse + - cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" From cbaac38e80c1a02335357e78f1e882d00e3653d6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 11:32:54 +0100 Subject: [PATCH 0137/1892] Appveyor: proper quoting to make MSYS happy --- setup.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ef56d59b6..ad0bf7255 100644 --- a/setup.py +++ b/setup.py @@ -177,7 +177,15 @@ def preprocess_fallback_config(): ] -def shellquote(s): +def quote_path_for_shell(s): + # On MinGW / MSYS, we need to use forward slash style and remove unsafe + # characters in order not to trip up the configure script + if "MSYSTEM" in os.environ: + s = s.replace("\\", "/") + if s[1:3] == ":/": + s = s[0] + s[2:] + + # Now the proper quoting return "'" + s.replace("'", "'\\''") + "'" @@ -230,7 +238,7 @@ def compile_in(self, build_folder, source_folder=None): print("Configuring igraph...") retcode = subprocess.call( - "sh {0} --disable-tls --disable-gmp".format(shellquote(os.path.join(source_folder, "configure"))), + "sh {0} --disable-tls --disable-gmp".format(quote_path_for_shell(os.path.join(source_folder, "configure"))), env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), shell=True ) From 825e0f5502ef87840622761f596a9bc7a4d27803 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 11:35:42 +0100 Subject: [PATCH 0138/1892] Appveyor: fix quoting --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ad0bf7255..dc1258a0a 100644 --- a/setup.py +++ b/setup.py @@ -183,7 +183,7 @@ def quote_path_for_shell(s): if "MSYSTEM" in os.environ: s = s.replace("\\", "/") if s[1:3] == ":/": - s = s[0] + s[2:] + s = "/" + s[0] + s[2:] # Now the proper quoting return "'" + s.replace("'", "'\\''") + "'" From 86c5c021958783bbcedcac8f8299ddefdbd032e1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 12:04:23 +0100 Subject: [PATCH 0139/1892] fix some MSVC compilation errors --- src/_igraph/graphobject.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 964df00aa..96c75d10e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8272,6 +8272,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( igraph_bliss_sh_t sh = IGRAPH_BLISS_FM; igraph_vector_t labeling; igraph_vector_int_t *color = 0; + int retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) return NULL; @@ -8287,7 +8288,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( if (igraphmodule_attrib_to_vector_int_t(color_o, self, &color, ATTRIBUTE_TYPE_VERTEX)) return NULL; - int retval = igraph_canonical_permutation(&self->g, color, &labeling, sh, 0); + retval = igraph_canonical_permutation(&self->g, color, &labeling, sh, 0); if (color) { igraph_vector_int_destroy(color); free(color); } @@ -8396,7 +8397,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, igraph_vector_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_bliss_sh_t sh1=IGRAPH_BLISS_FM, sh2=IGRAPH_BLISS_FM; igraph_vector_int_t *color1=0, *color2=0; - + int retval; static char *kwlist[] = { "other", "return_mapping_12", "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; @@ -8430,8 +8431,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, map21 = &mapping_21; } - - int retval = igraph_isomorphic_bliss(&self->g, &other->g, color1, color2, + retval = igraph_isomorphic_bliss(&self->g, &other->g, color1, color2, &result, map12, map21, sh1, 0, 0); if (color1) { igraph_vector_int_destroy(color1); free(color1); } From 60194fbb7ff3dbd05c140493e116673834318fc2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Jan 2020 12:27:23 +0100 Subject: [PATCH 0140/1892] remove vendored texttable, use the most recent version from PyPI --- .gitignore | 1 + requirements.txt | 1 + setup.py | 1 + src/igraph/summary.py | 5 +- src/igraph/vendor/__init__.py | 40 --- src/igraph/vendor/texttable.py | 586 --------------------------------- 6 files changed, 5 insertions(+), 629 deletions(-) create mode 100644 requirements.txt delete mode 100644 src/igraph/vendor/__init__.py delete mode 100644 src/igraph/vendor/texttable.py diff --git a/.gitignore b/.gitignore index f98dc2da8..2a22ad337 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ doc/api/ igraph/*.so *.egg-info/ .python-version +.eggs/ .tox .venv/ docker/wheelhouse diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d6e1198b1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +-e . diff --git a/setup.py b/setup.py index dc1258a0a..6c77aaf8e 100644 --- a/setup.py +++ b/setup.py @@ -662,6 +662,7 @@ def use_educated_guess(self): "igraph.vendor", ], scripts=["scripts/igraph"], + install_requires=["texttable>=1.6.2"], headers=headers, platforms="ALL", keywords=[ diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 60dbdf0f0..ba065bdef 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -9,6 +9,7 @@ from igraph.statistics import median from itertools import islice from math import ceil +from texttable import Texttable from textwrap import TextWrapper __all__ = ["GraphSummary"] @@ -33,8 +34,6 @@ 02110-1301 USA """ -texttable = vendor_import("texttable") - class FakeWrapper(object): """Object whose interface is compatible with C{textwrap.TextWrapper} but does no wrapping.""" @@ -321,7 +320,7 @@ def _infer_column_alignment(self, vertex_attrs=None, edge_attrs=None): def _new_table(self, headers=None): """Constructs a new table to pretty-print vertex and edge attributes""" - table = texttable.Texttable(max_width=0) + table = Texttable(max_width=0) table.set_deco(0) if headers is not None: table.header(headers) diff --git a/src/igraph/vendor/__init__.py b/src/igraph/vendor/__init__.py deleted file mode 100644 index 915ca8ab1..000000000 --- a/src/igraph/vendor/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -This package contains third party libraries that igraph depends on and that -are small enough to be distributed with igraph itself. - -The primary entry point of this module is ``vendor_import``, a function that -first tries to import a particular library using the standard Python mechanism -and falls back to the version of the library provided within ``igraph.vendor`` -if the standard Python import fails. - -The libraries contained within igraph are as follows: - - - `texttable`, a library to print ASCII tables, by Gerome Fournier. - See . -""" - -__license__ = "GPL" - -__all__ = ["vendor_import"] -__docformat__ = "restructuredtext en" - -def vendor_import(module_name): - """Tries to import a module name ``module_name`` using the standard Python - `import` statement and return the imported module. If the import fails, - tries to import a module of the same name from within ``igraph.vendor`` - and return that module instead. - """ - - parts = module_name.split(".") - - try: - result = __import__(module_name, level=0) - except ImportError: - result = __import__("igraph.vendor.%s" % module_name, level=0) - parts[0:0] = ["igraph", "vendor"] - - parts.pop(0) - while parts: - result = getattr(result, parts.pop(0)) - - return result diff --git a/src/igraph/vendor/texttable.py b/src/igraph/vendor/texttable.py deleted file mode 100644 index 086ff43c3..000000000 --- a/src/igraph/vendor/texttable.py +++ /dev/null @@ -1,586 +0,0 @@ -#!/usr/bin/env python -# -# texttable - module for creating simple ASCII tables -# Copyright (C) 2003-2011 Gerome Fournier -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -"""module for creating simple ASCII tables - - -Example: - - table = Texttable() - table.set_cols_align(["l", "r", "c"]) - table.set_cols_valign(["t", "m", "b"]) - table.add_rows([ ["Name", "Age", "Nickname"], - ["Mr\\nXavier\\nHuon", 32, "Xav'"], - ["Mr\\nBaptiste\\nClement", 1, "Baby"] ]) - print table.draw() + "\\n" - - table = Texttable() - table.set_deco(Texttable.HEADER) - table.set_cols_dtype(['t', # text - 'f', # float (decimal) - 'e', # float (exponent) - 'i', # integer - 'a']) # automatic - table.set_cols_align(["l", "r", "r", "r", "l"]) - table.add_rows([["text", "float", "exp", "int", "auto"], - ["abcd", "67", 654, 89, 128.001], - ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023], - ["lmn", 5e-78, 5e-78, 89.4, .000000000000128], - ["opqrstu", .023, 5e+78, 92., 12800000000000000000000]]) - print table.draw() - -Result: - - +----------+-----+----------+ - | Name | Age | Nickname | - +==========+=====+==========+ - | Mr | | | - | Xavier | 32 | | - | Huon | | Xav' | - +----------+-----+----------+ - | Mr | | | - | Baptiste | 1 | | - | Clement | | Baby | - +----------+-----+----------+ - - text float exp int auto - =========================================== - abcd 67.000 6.540e+02 89 128.001 - efgh 67.543 6.540e-01 90 1.280e+22 - ijkl 0.000 5.000e-78 89 0.000 - mnop 0.023 5.000e+78 92 1.280e+22 -""" - -__all__ = ["Texttable", "ArraySizeError"] - -__author__ = 'Gerome Fournier ' -__license__ = 'GPL' -__version__ = '0.8.1' -__credits__ = """\ -Jeff Kowalczyk: - - textwrap improved import - - comment concerning header output - -Anonymous: - - add_rows method, for adding rows in one go - -Sergey Simonenko: - - redefined len() function to deal with non-ASCII characters - -Roger Lew: - - columns datatype specifications - -Brian Peterson: - - better handling of unicode errors -""" - -import sys -import string - -try: - if sys.version >= '2.3': - import textwrap - elif sys.version >= '2.2': - from optparse import textwrap - else: - from optik import textwrap -except ImportError: - sys.stderr.write("Can't import textwrap module!\n") - raise - -def len(iterable): - """Redefining len here so it will be able to work with non-ASCII characters - """ - if not isinstance(iterable, str): - return iterable.__len__() - - try: - return len(unicode(iterable, 'utf')) - except: - return iterable.__len__() - -class ArraySizeError(Exception): - """Exception raised when specified rows don't fit the required size - """ - - def __init__(self, msg): - self.msg = msg - Exception.__init__(self, msg, '') - - def __str__(self): - return self.msg - -class Texttable: - - BORDER = 1 - HEADER = 1 << 1 - HLINES = 1 << 2 - VLINES = 1 << 3 - - def __init__(self, max_width=80): - """Constructor - - - max_width is an integer, specifying the maximum width of the table - - if set to 0, size is unlimited, therefore cells won't be wrapped - """ - - if max_width <= 0: - max_width = False - self._max_width = max_width - self._precision = 3 - - self._deco = Texttable.VLINES | Texttable.HLINES | Texttable.BORDER | \ - Texttable.HEADER - self.set_chars(['-', '|', '+', '=']) - self.reset() - - def reset(self): - """Reset the instance - - - reset rows and header - """ - - self._hline_string = None - self._row_size = None - self._header = [] - self._rows = [] - - def set_chars(self, array): - """Set the characters used to draw lines between rows and columns - - - the array should contain 4 fields: - - [horizontal, vertical, corner, header] - - - default is set to: - - ['-', '|', '+', '='] - """ - - if len(array) != 4: - raise ArraySizeError, "array should contain 4 characters" - array = [ x[:1] for x in [ str(s) for s in array ] ] - (self._char_horiz, self._char_vert, - self._char_corner, self._char_header) = array - - def set_deco(self, deco): - """Set the table decoration - - - 'deco' can be a combinaison of: - - Texttable.BORDER: Border around the table - Texttable.HEADER: Horizontal line below the header - Texttable.HLINES: Horizontal lines between rows - Texttable.VLINES: Vertical lines between columns - - All of them are enabled by default - - - example: - - Texttable.BORDER | Texttable.HEADER - """ - - self._deco = deco - - def set_cols_align(self, array): - """Set the desired columns alignment - - - the elements of the array should be either "l", "c" or "r": - - * "l": column flushed left - * "c": column centered - * "r": column flushed right - """ - - self._check_row_size(array) - self._align = array - - def set_cols_valign(self, array): - """Set the desired columns vertical alignment - - - the elements of the array should be either "t", "m" or "b": - - * "t": column aligned on the top of the cell - * "m": column aligned on the middle of the cell - * "b": column aligned on the bottom of the cell - """ - - self._check_row_size(array) - self._valign = array - - def set_cols_dtype(self, array): - """Set the desired columns datatype for the cols. - - - the elements of the array should be either "a", "t", "f", "e" or "i": - - * "a": automatic (try to use the most appropriate datatype) - * "t": treat as text - * "f": treat as float in decimal format - * "e": treat as float in exponential format - * "i": treat as int - - - by default, automatic datatyping is used for each column - """ - - self._check_row_size(array) - self._dtype = array - - def set_cols_width(self, array): - """Set the desired columns width - - - the elements of the array should be integers, specifying the - width of each column. For example: - - [10, 20, 5] - """ - - self._check_row_size(array) - try: - array = map(int, array) - if reduce(min, array) <= 0: - raise ValueError - except ValueError: - sys.stderr.write("Wrong argument in column width specification\n") - raise - self._width = array - - def set_precision(self, width): - """Set the desired precision for float/exponential formats - - - width must be an integer >= 0 - - - default value is set to 3 - """ - - if not type(width) is int or width < 0: - raise ValueError('width must be an integer greater then 0') - self._precision = width - - def header(self, array): - """Specify the header of the table - """ - - self._check_row_size(array) - self._header = map(str, array) - - def add_row(self, array): - """Add a row in the rows stack - - - cells can contain newlines and tabs - """ - - self._check_row_size(array) - - if not hasattr(self, "_dtype"): - self._dtype = ["a"] * self._row_size - - cells = [] - for i,x in enumerate(array): - cells.append(self._str(i,x)) - self._rows.append(cells) - - def add_rows(self, rows, header=True): - """Add several rows in the rows stack - - - The 'rows' argument can be either an iterator returning arrays, - or a by-dimensional array - - 'header' specifies if the first row should be used as the header - of the table - """ - - # nb: don't use 'iter' on by-dimensional arrays, to get a - # usable code for python 2.1 - if header: - if hasattr(rows, '__iter__') and hasattr(rows, 'next'): - self.header(rows.next()) - else: - self.header(rows[0]) - rows = rows[1:] - for row in rows: - self.add_row(row) - - def draw(self): - """Draw the table - - - the table is returned as a whole string - """ - - if not self._header and not self._rows: - return - self._compute_cols_width() - self._check_align() - out = "" - if self._has_border(): - out += self._hline() - if self._header: - out += self._draw_line(self._header, isheader=True) - if self._has_header(): - out += self._hline_header() - length = 0 - for row in self._rows: - length += 1 - out += self._draw_line(row) - if self._has_hlines() and length < len(self._rows): - out += self._hline() - if self._has_border(): - out += self._hline() - return out[:-1] - - def _str(self, i, x): - """Handles string formatting of cell data - - i - index of the cell datatype in self._dtype - x - cell data to format - """ - try: - f = float(x) - except: - return str(x) - - n = self._precision - dtype = self._dtype[i] - - if dtype == 'i': - return str(int(round(f))) - elif dtype == 'f': - return '%.*f' % (n, f) - elif dtype == 'e': - return '%.*e' % (n, f) - elif dtype == 't': - return str(x) - else: - if f - round(f) == 0: - if abs(f) > 1e8: - return '%.*e' % (n, f) - else: - return str(int(round(f))) - else: - if abs(f) > 1e8: - return '%.*e' % (n, f) - else: - return '%.*f' % (n, f) - - def _check_row_size(self, array): - """Check that the specified array fits the previous rows size - """ - - if not self._row_size: - self._row_size = len(array) - elif self._row_size != len(array): - raise ArraySizeError, "array should contain %d elements" \ - % self._row_size - - def _has_vlines(self): - """Return a boolean, if vlines are required or not - """ - - return self._deco & Texttable.VLINES > 0 - - def _has_hlines(self): - """Return a boolean, if hlines are required or not - """ - - return self._deco & Texttable.HLINES > 0 - - def _has_border(self): - """Return a boolean, if border is required or not - """ - - return self._deco & Texttable.BORDER > 0 - - def _has_header(self): - """Return a boolean, if header line is required or not - """ - - return self._deco & Texttable.HEADER > 0 - - def _hline_header(self): - """Print header's horizontal line - """ - - return self._build_hline(True) - - def _hline(self): - """Print an horizontal line - """ - - if not self._hline_string: - self._hline_string = self._build_hline() - return self._hline_string - - def _build_hline(self, is_header=False): - """Return a string used to separated rows or separate header from - rows - """ - horiz = self._char_horiz - if (is_header): - horiz = self._char_header - # compute cell separator - s = "%s%s%s" % (horiz, [horiz, self._char_corner][self._has_vlines()], - horiz) - # build the line - l = string.join([horiz * n for n in self._width], s) - # add border if needed - if self._has_border(): - l = "%s%s%s%s%s\n" % (self._char_corner, horiz, l, horiz, - self._char_corner) - else: - l += "\n" - return l - - def _len_cell(self, cell): - """Return the width of the cell - - Special characters are taken into account to return the width of the - cell, such like newlines and tabs - """ - - cell_lines = cell.split('\n') - maxi = 0 - for line in cell_lines: - length = 0 - parts = line.split('\t') - for part, i in zip(parts, range(1, len(parts) + 1)): - length = length + len(part) - if i < len(parts): - length = (length/8 + 1) * 8 - maxi = max(maxi, length) - return maxi - - def _compute_cols_width(self): - """Return an array with the width of each column - - If a specific width has been specified, exit. If the total of the - columns width exceed the table desired width, another width will be - computed to fit, and cells will be wrapped. - """ - - if hasattr(self, "_width"): - return - maxi = [] - if self._header: - maxi = [ self._len_cell(x) for x in self._header ] - for row in self._rows: - for cell,i in zip(row, range(len(row))): - try: - maxi[i] = max(maxi[i], self._len_cell(cell)) - except (TypeError, IndexError): - maxi.append(self._len_cell(cell)) - items = len(maxi) - length = reduce(lambda x,y: x+y, maxi) - if self._max_width and length + items * 3 + 1 > self._max_width: - maxi = [(self._max_width - items * 3 -1) / items \ - for n in range(items)] - self._width = maxi - - def _check_align(self): - """Check if alignment has been specified, set default one if not - """ - - if not hasattr(self, "_align"): - self._align = ["l"] * self._row_size - if not hasattr(self, "_valign"): - self._valign = ["t"] * self._row_size - - def _draw_line(self, line, isheader=False): - """Draw a line - - Loop over a single cell length, over all the cells - """ - - line = self._splitit(line, isheader) - space = " " - out = "" - for i in range(len(line[0])): - if self._has_border(): - out += "%s " % self._char_vert - length = 0 - for cell, width, align in zip(line, self._width, self._align): - length += 1 - cell_line = cell[i] - fill = width - len(cell_line) - if isheader: - align = "c" - if align == "r": - out += "%s " % (fill * space + cell_line) - elif align == "c": - out += "%s " % (fill/2 * space + cell_line \ - + (fill/2 + fill%2) * space) - else: - out += "%s " % (cell_line + fill * space) - if length < len(line): - out += "%s " % [space, self._char_vert][self._has_vlines()] - out += "%s\n" % ['', self._char_vert][self._has_border()] - return out - - def _splitit(self, line, isheader): - """Split each element of line to fit the column width - - Each element is turned into a list, result of the wrapping of the - string to the desired width - """ - - line_wrapped = [] - for cell, width in zip(line, self._width): - array = [] - for c in cell.split('\n'): - try: - c = unicode(c, 'utf') - except UnicodeDecodeError, strerror: - sys.stderr.write("UnicodeDecodeError exception for string '%s': %s\n" % (c, strerror)) - c = unicode(c, 'utf', 'replace') - array.extend(textwrap.wrap(c, width)) - line_wrapped.append(array) - max_cell_lines = reduce(max, map(len, line_wrapped)) - for cell, valign in zip(line_wrapped, self._valign): - if isheader: - valign = "t" - if valign == "m": - missing = max_cell_lines - len(cell) - cell[:0] = [""] * (missing / 2) - cell.extend([""] * (missing / 2 + missing % 2)) - elif valign == "b": - cell[:0] = [""] * (max_cell_lines - len(cell)) - else: - cell.extend([""] * (max_cell_lines - len(cell))) - return line_wrapped - -if __name__ == '__main__': - table = Texttable() - table.set_cols_align(["l", "r", "c"]) - table.set_cols_valign(["t", "m", "b"]) - table.add_rows([ ["Name", "Age", "Nickname"], - ["Mr\nXavier\nHuon", 32, "Xav'"], - ["Mr\nBaptiste\nClement", 1, "Baby"] ]) - print table.draw() + "\n" - - table = Texttable() - table.set_deco(Texttable.HEADER) - table.set_cols_dtype(['t', # text - 'f', # float (decimal) - 'e', # float (exponent) - 'i', # integer - 'a']) # automatic - table.set_cols_align(["l", "r", "r", "r", "l"]) - table.add_rows([["text", "float", "exp", "int", "auto"], - ["abcd", "67", 654, 89, 128.001], - ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023], - ["lmn", 5e-78, 5e-78, 89.4, .000000000000128], - ["opqrstu", .023, 5e+78, 92., 12800000000000000000000]]) - print table.draw() From e731f7f66093d403ac31d7b512c1a3fe7bd35ca8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Jan 2020 14:25:50 +0100 Subject: [PATCH 0141/1892] Appveyor: allow extra library path to find libxml2 --- appveyor.yml | 4 +++- setup.py | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6ac70592f..760f1b405 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,9 +5,10 @@ environment: PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% MSYSTEM: MINGW64 TARGET_ARCH: "x64" + IGRAPH_EXTRA_LIBRARY_PATH: C:\msys64\mingw64\lib platform: - - x64 + - x64 install: - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" @@ -18,6 +19,7 @@ install: before_build: - git submodule update --init --recursive + - python setup.py build_c_core build_script: - cibuildwheel --output-dir wheelhouse diff --git a/setup.py b/setup.py index 6c77aaf8e..5db49a077 100644 --- a/setup.py +++ b/setup.py @@ -391,6 +391,13 @@ def run(self): if not detected: buildcfg.use_educated_guess() + # Add any extra library paths if needed; this is needed for the + # Appveyor CI build + if "IGRAPH_EXTRA_LIBRARY_PATH" in os.environ: + buildcfg.library_dirs = list( + os.environ["IGRAPH_EXTRA_LIBRARY_PATH"].split(os.pathsep) + ) + buildcfg.library_dirs + # Replaces library names with full paths to static libraries # where possible. libm.a is excluded because it caused problems # on Sabayon Linux where libm.a is probably not compiled with From cad29c4ba91e382990bbe49dddafce55353b05ca Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Jan 2020 14:29:51 +0100 Subject: [PATCH 0142/1892] Appveyor: use CIBW_BEFORE_BUILD --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 760f1b405..40a32a7c0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,7 @@ environment: PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% MSYSTEM: MINGW64 TARGET_ARCH: "x64" + CIBW_BEFORE_BUILD: python setup.py build_c_core IGRAPH_EXTRA_LIBRARY_PATH: C:\msys64\mingw64\lib platform: @@ -19,7 +20,6 @@ install: before_build: - git submodule update --init --recursive - - python setup.py build_c_core build_script: - cibuildwheel --output-dir wheelhouse From 8ee04da8837b90c00f455fc84d55411363ca7d44 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Jan 2020 14:34:08 +0100 Subject: [PATCH 0143/1892] igraph.vendor package is no more --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 5db49a077..32cb0174a 100644 --- a/setup.py +++ b/setup.py @@ -665,8 +665,7 @@ def use_educated_guess(self): "igraph", "igraph.app", "igraph.drawing", - "igraph.remote", - "igraph.vendor", + "igraph.remote" ], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], From 6786e05a39f5cc9d0740af34ec9b3f08bdf97ec3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Jan 2020 15:58:32 +0100 Subject: [PATCH 0144/1892] removed unused import --- src/igraph/summary.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/igraph/summary.py b/src/igraph/summary.py index ba065bdef..69ef3eb36 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -5,7 +5,6 @@ @undocumented: _get_wrapper_for_width, FakeWrapper """ -from igraph.vendor import vendor_import from igraph.statistics import median from itertools import islice from math import ceil From 926e6ad8d898ebe5e027e5503e1b33ed804dc104 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Jan 2020 22:11:53 +0100 Subject: [PATCH 0145/1892] Appveyor: okay, try building python-igraph without GraphML support first, this is easier --- appveyor.yml | 2 +- setup.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 40a32a7c0..e33d93d1e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: MSYSTEM: MINGW64 TARGET_ARCH: "x64" CIBW_BEFORE_BUILD: python setup.py build_c_core - IGRAPH_EXTRA_LIBRARY_PATH: C:\msys64\mingw64\lib + IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" platform: - x64 diff --git a/setup.py b/setup.py index 32cb0174a..3a7473c5b 100644 --- a/setup.py +++ b/setup.py @@ -237,8 +237,14 @@ def compile_in(self, build_folder, source_folder=None): os.chdir(build_folder) print("Configuring igraph...") + configure_args = ["--disable-tls", "--disable-gmp"] + if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: + configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) retcode = subprocess.call( - "sh {0} --disable-tls --disable-gmp".format(quote_path_for_shell(os.path.join(source_folder, "configure"))), + "sh {0} {1}".format( + quote_path_for_shell(os.path.join(source_folder, "configure")), + " ".join(configure_args) + ), env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), shell=True ) From 1214df81e1dbd6f7fe7076ce9d84b2e75e5d0e54 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 16 Jan 2020 22:48:07 +0100 Subject: [PATCH 0146/1892] fixing scripts/mkdoc.sh for new directory structure --- scripts/mkdoc.sh | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 7b58af6d4..ccbbd6bbf 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -24,20 +24,11 @@ fi PWD=`pwd` -SYNC=0 -if [ x$1 = x--sync ]; then - SYNC=1 - shift -fi -if [ x$1 != x ]; then - cd $1 || exit 1 -fi - -echo "Checking symlinked _igraph.so in ${ROOT_FOLDER}/igraph..." -if [ ! -e ${ROOT_FOLDER}/igraph/_igraph.so -o ! -L ${ROOT_FOLDER}/igraph/_igraph.so ]; then - rm -f ${ROOT_FOLDER}/igraph/_igraph.so - cd ${ROOT_FOLDER}/igraph - ln -s ../build/lib*/igraph/_igraph.so . +echo "Checking symlinked _igraph.so in ${ROOT_FOLDER}/src/igraph..." +if [ ! -e ${ROOT_FOLDER}/src/igraph/_igraph.so -o ! -L ${ROOT_FOLDER}/src/igraph/_igraph.so ]; then + rm -f ${ROOT_FOLDER}/src/igraph/_igraph.so + cd ${ROOT_FOLDER}/src/igraph + ln -s ../../build/lib*/igraph/_igraph.so . cd ${ROOT_FOLDER} fi @@ -45,21 +36,14 @@ echo "Removing existing documentation..." rm -rf html echo "Generating HTML documentation..." -${EPYDOC} --html -v -o ${DOC_API_FOLDER}/html --config ${CONFIG} +PYTHONPATH=src ${EPYDOC} --html -v -o ${DOC_API_FOLDER}/html --config ${CONFIG} PDF=0 which latex >/dev/null && PDF=1 if [ $PDF -eq 1 ]; then echo "Generating PDF documentation..." -${EPYDOC} --pdf -v -o ${DOC_API_FOLDER}/pdf --config ${CONFIG} -fi - -if [ $SYNC -eq 1 ]; then - echo "Syncing documentation to web" - cp ${DOC_API_FOLDER}/pdf/igraph.pdf ${DOC_API_FOLDER}/html - rsync --delete -avz ${DOC_API_FOLDER}/html/ csardi@igraph.org:2222:www/doc/python/ - rm ${DOC_API_FOLDER}/html/igraph.pdf + PYTHONPATH=src ${EPYDOC} --pdf -v -o ${DOC_API_FOLDER}/pdf --config ${CONFIG} fi cd "$PWD" From 00213eeed1c387984d6796a2b37eca8eff5dc298 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 11:16:10 +0100 Subject: [PATCH 0147/1892] modifying setup.py so it is using the MSVC build of igraph on Windows --- setup.py | 122 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/setup.py b/setup.py index 3a7473c5b..a1cb09996 100644 --- a/setup.py +++ b/setup.py @@ -140,6 +140,35 @@ def is_unix_like(platform=None): ) +def find_msvc_source_folder(folder = ".", requires_built=False): + """Finds the folder that contains the MSVC-specific source of igraph if there + is any. Returns `None` if no such folder is found. Prints a warning if the + choice is ambiguous. + """ + all_msvc_dirs = glob.glob(os.path.join(folder, "igraph-*-msvc")) + if len(all_msvc_dirs) > 0: + if len(all_msvc_dirs) > 1: + print( + "More than one MSVC build directory (..\\..\\igraph-*-msvc) found!" + ) + print( + "It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n" + ) + + msvc_builddir = all_msvc_dirs[-1] + if requires_built and not os.path.exists(os.path.join(msvc_builddir, "Release")): + print( + "There is no 'Release' dir in the MSVC build directory\n(%s)" + % msvc_builddir + ) + print("Please build the MSVC build first!\n") + return None + + return msvc_builddir + else: + return None + + def preprocess_fallback_config(): """Preprocesses the fallback include and library paths depending on the platform.""" @@ -147,34 +176,25 @@ def preprocess_fallback_config(): global LIBIGRAPH_FALLBACK_LIBRARY_DIRS global LIBIGRAPH_FALLBACK_LIBRARIES - if os.name == "nt" and distutils.ccompiler.get_default_compiler() == "msvc": + if platform.system() == "Windows" and distutils.ccompiler.get_default_compiler() == "msvc": # if this setup is run in the source checkout *and* the igraph msvc was build, # this code adds the right library and include dir - all_msvc_dirs = glob.glob(os.path.join("..", "..", "igraph-*-msvc")) - if len(all_msvc_dirs) > 0: - if len(all_msvc_dirs) > 1: - print( - "More than one MSVC build directory (..\\..\\igraph-*-msvc) found!" - ) - print( - "It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n" - ) + msvc_builddir = find_msvc_source_folder(os.path.join("..", ".."), requires_built=True) + + if msvc_builddir is not None: + print("Using MSVC build dir: %s\n\n" % msvc_builddir) + LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [ + os.path.join(msvc_builddir, "include") + ] + LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [ + os.path.join(msvc_builddir, "Release") + ] + return True + else: + return False - msvc_builddir = all_msvc_dirs[-1] - if not os.path.exists(os.path.join(msvc_builddir, "Release")): - print( - "There is no 'Release' dir in the MSVC build directory\n(%s)" - % msvc_builddir - ) - print("Please build the MSVC build first!\n") - else: - print("Using MSVC build dir as a fallback: %s\n\n" % msvc_builddir) - LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [ - os.path.join(msvc_builddir, "include") - ] - LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [ - os.path.join(msvc_builddir, "Release") - ] + else: + return True def quote_path_for_shell(s): @@ -221,8 +241,8 @@ def compile_in(self, build_folder, source_folder=None): if retcode: return False - # Patch ltmain.sh so it does not freak out on OS X when the build - # directory contains spaces + # Patch ltmain.sh so it does not freak out when the build directory + # contains spaces with open("ltmain.sh") as infp: with open("ltmain.sh.new", "w") as outfp: for line in infp: @@ -237,7 +257,7 @@ def compile_in(self, build_folder, source_folder=None): os.chdir(build_folder) print("Configuring igraph...") - configure_args = ["--disable-tls", "--disable-gmp"] + configure_args = ["--disable-tls"] if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) retcode = subprocess.call( @@ -251,22 +271,46 @@ def compile_in(self, build_folder, source_folder=None): if retcode: return False + building_on_windows = platform.system() == "Windows" + + if building_on_windows: + print("Creating Microsoft Visual Studio project...") + retcode = subprocess.call("make msvc", shell=True) + if retcode: + return False + print("Building igraph...") - retcode = subprocess.call("make", shell=True) + if building_on_windows: + msvc_source = find_msvc_source_folder() + if not msvc_source: + return False + + os.chdir(msvc_source) + retcode = subprocess.call("devenv /upgrade igraph.vcproj") + if retcode: + return False + + retcode = subprocess.call("msbuild.exe igraph.vcxproj") + else: + retcode = subprocess.call("make", shell=True) + if retcode: return False - libraries = [] - for line in open("igraph.pc"): - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) - - if not libraries: - # Educated guess + if building_on_windows: libraries = ["igraph"] + else: + libraries = [] + for line in open("igraph.pc"): + if line.startswith("Libs: ") or line.startswith("Libs.private: "): + words = line.strip().split() + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) + + if not libraries: + # Educated guess + libraries = ["igraph"] return libraries From ba4d3634e8aed6a11fde3f9b448b685f477039bc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 11:28:47 +0100 Subject: [PATCH 0148/1892] Appveyor: try without devenv upgrade --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index a1cb09996..ffab3b315 100644 --- a/setup.py +++ b/setup.py @@ -286,11 +286,11 @@ def compile_in(self, build_folder, source_folder=None): return False os.chdir(msvc_source) - retcode = subprocess.call("devenv /upgrade igraph.vcproj") - if retcode: - return False + # retcode = subprocess.call("devenv /upgrade igraph.vcproj") + # if retcode: + # return False - retcode = subprocess.call("msbuild.exe igraph.vcxproj") + retcode = subprocess.call("msbuild.exe igraph.vcxproj /p:configuration=Release") else: retcode = subprocess.call("make", shell=True) From 45065a464aa7f08bf92ddfaf988b072bfa145181 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 11:36:40 +0100 Subject: [PATCH 0149/1892] Appveyor: okay, it looks like devenv is needed --- setup.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ffab3b315..527a27f09 100644 --- a/setup.py +++ b/setup.py @@ -285,10 +285,13 @@ def compile_in(self, build_folder, source_folder=None): if not msvc_source: return False + from distutils.spawn import find_executable + print(repr(find_executable("devenv"))) + print(repr("\n".join(os.environ["PATH"].split(os.pathsep)))) os.chdir(msvc_source) - # retcode = subprocess.call("devenv /upgrade igraph.vcproj") - # if retcode: - # return False + retcode = subprocess.call("devenv /upgrade igraph.vcproj") + if retcode: + return False retcode = subprocess.call("msbuild.exe igraph.vcxproj /p:configuration=Release") else: From f52046901cdf0c863d8bf03a901badd5aae86da0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 11:45:46 +0100 Subject: [PATCH 0150/1892] Appveyor: specify full path of devenv --- appveyor.yml | 1 + setup.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e33d93d1e..3bc6f1121 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,7 @@ environment: TARGET_ARCH: "x64" CIBW_BEFORE_BUILD: python setup.py build_c_core IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" + DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe platform: - x64 diff --git a/setup.py b/setup.py index 527a27f09..ab9f0f726 100644 --- a/setup.py +++ b/setup.py @@ -286,10 +286,10 @@ def compile_in(self, build_folder, source_folder=None): return False from distutils.spawn import find_executable - print(repr(find_executable("devenv"))) - print(repr("\n".join(os.environ["PATH"].split(os.pathsep)))) + devenv = os.environ.get("DEVENV_EXECUTABLE", "devenv") + print(devenv) os.chdir(msvc_source) - retcode = subprocess.call("devenv /upgrade igraph.vcproj") + retcode = subprocess.call(quote_path_for_shell(devenv) + " /upgrade igraph.vcproj") if retcode: return False From 50ad082b53a289cb702a0bba3fd6e5513d6953b7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 11:55:19 +0100 Subject: [PATCH 0151/1892] Appveyor: trying to figure out why devenv.exe is missing --- setup.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index ab9f0f726..048f91167 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +usr/bin/env python import os import platform @@ -286,10 +286,15 @@ def compile_in(self, build_folder, source_folder=None): return False from distutils.spawn import find_executable - devenv = os.environ.get("DEVENV_EXECUTABLE", "devenv") - print(devenv) + devenv = os.environ.get("DEVENV_EXECUTABLE") os.chdir(msvc_source) - retcode = subprocess.call(quote_path_for_shell(devenv) + " /upgrade igraph.vcproj") + if devenv is None: + retcode = subprocess.call("devenv /upgrade igraph.vcproj", shell=True) + else: + print("=====") + subprocess.call("dir " + quote_path_for_shell(os.path.dirname(devenv)), shell=True) + print("=====") + retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) if retcode: return False From e0d5d3560a145f8cc73bec6ed829fbed6911bdfe Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 12:08:48 +0100 Subject: [PATCH 0152/1892] fixed the sheband that I accidentally removed from setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 048f91167..e406448e8 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -usr/bin/env python +#usr/bin/env python import os import platform From 61ec2544c924afc079a3b1fa0dac5f381cb10bbf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 12:22:28 +0100 Subject: [PATCH 0153/1892] Appveyor: fix copying of build artifacts for Windows build --- setup.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index e406448e8..922730b6c 100644 --- a/setup.py +++ b/setup.py @@ -285,15 +285,11 @@ def compile_in(self, build_folder, source_folder=None): if not msvc_source: return False - from distutils.spawn import find_executable devenv = os.environ.get("DEVENV_EXECUTABLE") os.chdir(msvc_source) if devenv is None: retcode = subprocess.call("devenv /upgrade igraph.vcproj", shell=True) else: - print("=====") - subprocess.call("dir " + quote_path_for_shell(os.path.dirname(devenv)), shell=True) - print("=====") retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) if retcode: return False @@ -328,6 +324,8 @@ def compile_in(self, build_folder, source_folder=None): def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries ): + building_on_windows = platform.system() == "Windows" + create_dir_unless_exists(install_folder) ensure_dir_does_not_exist(install_folder, "include") @@ -341,10 +339,19 @@ def copy_build_artifacts( for fname in glob.glob(os.path.join(build_folder, "include", "*.h")): shutil.copy(fname, os.path.join(install_folder, "include")) - for fname in glob.glob( - os.path.join(build_folder, "src", ".libs", "libigraph.*") - ): - shutil.copy(fname, os.path.join(install_folder, "lib")) + + if building_on_windows: + for fname in glob.glob( + os.path.join(source_folder, "Release", "*.lib") + ): + print("Copying to lib folder:", fname) + shutil.copy(fname, os.path.join(install_folder, "lib")) + else: + for fname in glob.glob( + os.path.join(build_folder, "src", ".libs", "libigraph.*") + ): + shutil.copy(fname, os.path.join(install_folder, "lib")) + with open(os.path.join(install_folder, "build.cfg"), "w") as f: f.write(repr(libraries)) From 8a09f194c74f16592b6b552a8cbaef727f7d75db Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 12:45:22 +0100 Subject: [PATCH 0154/1892] Appveyor: fix copying of build artifacts for Windows build, second try --- setup.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 922730b6c..7c719b678 100644 --- a/setup.py +++ b/setup.py @@ -341,11 +341,17 @@ def copy_build_artifacts( shutil.copy(fname, os.path.join(install_folder, "include")) if building_on_windows: - for fname in glob.glob( - os.path.join(source_folder, "Release", "*.lib") - ): - print("Copying to lib folder:", fname) - shutil.copy(fname, os.path.join(install_folder, "lib")) + msvc_builddir = find_msvc_source_folder(build_folder, requires_built=True) + if msvc_builddir is not None: + print("Using MSVC build dir: %s\n\n" % msvc_builddir) + for fname in glob.glob( + os.path.join(msvc_builddir, "Release", "*.lib") + ): + print("Copying to lib folder:", fname) + shutil.copy(fname, os.path.join(install_folder, "lib")) + else: + print("Cannot find MSVC build dir in %s\n\n" % build_folder) + return False else: for fname in glob.glob( os.path.join(build_folder, "src", ".libs", "libigraph.*") From 4fe12c20f8a90c3d13a44b2cbe9db712ed8e3abd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 12:58:43 +0100 Subject: [PATCH 0155/1892] don't link to stdc++ on Windows --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7c719b678..48cb44d2c 100644 --- a/setup.py +++ b/setup.py @@ -615,7 +615,9 @@ def process_args_from_command_line(self): def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" - if "stdc++" not in self.libraries: + building_on_windows = platform.system() == "Windows" + + if not building_on_windows and "stdc++" not in self.libraries: self.libraries.append("stdc++") if exclusions is None: From 3b0ba9a9feb61b06248fd06d109162a43726da65 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 13:10:54 +0100 Subject: [PATCH 0156/1892] Appveyor: skip 32-bit builds for now --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 3bc6f1121..1cf15798c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ environment: MSYSTEM: MINGW64 TARGET_ARCH: "x64" CIBW_BEFORE_BUILD: python setup.py build_c_core + CIBW_SKIP: "*-win32" IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe From 06c6fcf67e1fa8fa3c058b3248022a47f76c310e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 13:46:14 +0100 Subject: [PATCH 0157/1892] Appveyor: switching to newer image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1cf15798c..62f6b24db 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ image: - - Visual Studio 2015 + - Visual Studio 2017 environment: PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% From 2c4595147e2c35f0d84e60e99e7ea268c10ddf69 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 14:03:30 +0100 Subject: [PATCH 0158/1892] Appveyor: setting up environment properly for a 64-bit build --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 62f6b24db..0a04e010d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ environment: CIBW_BEFORE_BUILD: python setup.py build_c_core CIBW_SKIP: "*-win32" IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" - DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe + # DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe platform: - x64 @@ -24,6 +24,7 @@ before_build: - git submodule update --init --recursive build_script: + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" - cibuildwheel --output-dir wheelhouse artifacts: From 64592cd16a93fe825bb7ca60cab62886e6ab2be0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 14:49:21 +0100 Subject: [PATCH 0159/1892] Appveyor: trying to avoid __declspec misery on Windows --- setup.py | 8 ++++++++ vendor/source/igraph | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 48cb44d2c..9ca0407bc 100644 --- a/setup.py +++ b/setup.py @@ -380,6 +380,7 @@ def __init__(self): self.libraries = [] self.extra_compile_args = [] self.extra_link_args = [] + self.define_macros = [] self.extra_objects = [] self.static_extension = False self.use_pkgconfig = True @@ -482,6 +483,8 @@ def run(self): # Prints basic build information buildcfg.print_build_info() + # Find the igraph extension and configure it with the settings + # of this build configuration ext = first( extension for extension in self.extensions @@ -548,6 +551,7 @@ def configure(self, ext): ext.extra_compile_args = self.extra_compile_args ext.extra_link_args = self.extra_link_args ext.extra_objects = self.extra_objects + ext.define_macros = self.define_macros def detect_from_pkgconfig(self): """Detects the igraph include directory, library directory and the @@ -635,10 +639,14 @@ def replace_static_libraries(self, only=None, exclusions=None): def use_vendored_igraph(self): """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up the include and library paths and the library names accordingly.""" + building_on_windows = platform.system() == "Windows" + buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include")] buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" + if building_on_windows: + buildcfg.define_macros.append(("IGRAPH_NO_IMPORTS", "1")) buildcfg_file = os.path.join("vendor", "install", "igraph", "build.cfg") if os.path.exists(buildcfg_file): diff --git a/vendor/source/igraph b/vendor/source/igraph index 9ff13a12e..4fa0b4ef6 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 9ff13a12e5560004da9f8abd8d21b499a8587556 +Subproject commit 4fa0b4ef65f7ccde3a253e6ea7f3d0cdecb3ba2f From 392a7de35c863a0fa727d8d65fda1fdcb4d107f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 15:46:15 +0100 Subject: [PATCH 0160/1892] Appveyor: run unit tests as part of the build --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 0a04e010d..a68dc19bd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ environment: MSYSTEM: MINGW64 TARGET_ARCH: "x64" CIBW_BEFORE_BUILD: python setup.py build_c_core + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" CIBW_SKIP: "*-win32" IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" # DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe From fc984174aebf059e0c6f60fc3fb3532efce0425b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jan 2020 17:08:40 +0100 Subject: [PATCH 0161/1892] fix a test case on Windows / Python 3.6 --- setup.py | 1 - src/igraph/__init__.py | 13 +++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 9ca0407bc..aeed76ff8 100644 --- a/setup.py +++ b/setup.py @@ -347,7 +347,6 @@ def copy_build_artifacts( for fname in glob.glob( os.path.join(msvc_builddir, "Release", "*.lib") ): - print("Copying to lib folder:", fname) shutil.copy(fname, os.path.join(install_folder, "lib")) else: print("Cannot find MSVC build dir in %s\n\n" % build_folder) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 96d11ffad..f6e27f029 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1886,10 +1886,7 @@ def Read_Pickle(klass, fname=None): """Reads a graph from Python pickled format @param fname: the name of the file, a stream to read from, or - a string containing the pickled data. The string is assumed to - hold pickled data if it is longer than 40 characters and - contains a substring that's peculiar to pickled versions - of an C{igraph} Graph object. + a string containing the pickled data. @return: the created graph object. """ import cPickle as pickle @@ -1900,6 +1897,14 @@ def Read_Pickle(klass, fname=None): fp = None try: fp = open(fname, "rb") + except UnicodeDecodeError: + try: + # We are on Python 3.6 or above and we are passing a pickled + # stream that cannot be decoded as Unicode. Try unpickling + # directly. + result = pickle.loads(fname) + except TypeError: + raise IOError('Cannot load file. If fname is a file name, that filename may be incorrect.') except IOError: try: # No file with the given name, try unpickling directly. From 17d1dae4eaff7b890bffb7ab5b69b871a8f7bc61 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 22 Jan 2020 20:42:30 +0100 Subject: [PATCH 0162/1892] updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 4fa0b4ef6..48d100a0a 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 4fa0b4ef65f7ccde3a253e6ea7f3d0cdecb3ba2f +Subproject commit 48d100a0a92ea74dd7fa90c33c96b435f054de65 From c4f56635d9a5503317f71754b261c33d05d5f457 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 22 Jan 2020 20:42:53 +0100 Subject: [PATCH 0163/1892] renamed IGRAPH_NO_IMPORTS to IGRAPH_STATIC in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index aeed76ff8..3641621da 100644 --- a/setup.py +++ b/setup.py @@ -645,7 +645,7 @@ def use_vendored_igraph(self): if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" if building_on_windows: - buildcfg.define_macros.append(("IGRAPH_NO_IMPORTS", "1")) + buildcfg.define_macros.append(("IGRAPH_STATIC", "1")) buildcfg_file = os.path.join("vendor", "install", "igraph", "build.cfg") if os.path.exists(buildcfg_file): From 946de6dee8c1305bfd4eabbfd8a7058dcfb5c32f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 29 Jan 2020 14:00:01 +0100 Subject: [PATCH 0164/1892] pinning igraph source tree at 0.8.0 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 48d100a0a..8183bca22 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 48d100a0a92ea74dd7fa90c33c96b435f054de65 +Subproject commit 8183bca22070654136c58189681ce4319be96cf2 From e311e45b8c500ace9289e2554c80d80f46fff42d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Jan 2020 10:50:51 +0100 Subject: [PATCH 0165/1892] removed references to Nexus as it is not working any more --- src/igraph/__init__.py | 1 - src/igraph/configuration.py | 14 - src/igraph/remote/nexus.py | 576 ------------------------------------ 3 files changed, 591 deletions(-) delete mode 100644 src/igraph/remote/nexus.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index f6e27f029..7fad8bb29 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -42,7 +42,6 @@ from igraph.formula import * from igraph.layout import * from igraph.matching import * -from igraph.remote.nexus import * from igraph.statistics import * from igraph.summary import * from igraph.utils import * diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index b5eb31762..df33886f3 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -151,16 +151,6 @@ class Configuration(object): vertices automatically if they don't fit within the vertex. Default: C{False}. - Remote repository settings - -------------------------- - - These settings specify how igraph should access remote graph repositories. - Currently only the Nexus repository is supported. All these settings are - stored in section C{remote}. - - - B{nexus.url}: the root URL of the Nexus repository. Default: - C{http://nexus.igraph.org}. - Shell settings -------------- @@ -273,10 +263,6 @@ def setfloat(obj, section, key, value): "type": "boolean" }, - "remote.nexus.url": { - "default": "http://nexus.igraph.org" - }, - "shell.ipython.inlining.Plot": { "default": True, "type": "boolean" diff --git a/src/igraph/remote/nexus.py b/src/igraph/remote/nexus.py deleted file mode 100644 index 266f16a72..000000000 --- a/src/igraph/remote/nexus.py +++ /dev/null @@ -1,576 +0,0 @@ -# vim:ts=4:sw=4:sts=4:et -# -*- coding: utf-8 -*- -"""Interface to the Nexus online graph repository. - -The classes in this file facilitate access to the Nexus online graph -repository at U{http://nexus.igraph.org}. - -The main entry point of this package is the C{Nexus} variable, which is -an instance of L{NexusConnection}. Use L{NexusConnection.get} to get a particular -network from Nexus, L{NexusConnection.list} to list networks having a given set of -tags, L{NexusConnection.search} to search in the dataset descriptions, or -L{NexusConnection.info} to show the info sheet of a dataset.""" - -from __future__ import print_function - -from gzip import GzipFile -from itertools import izip -from textwrap import TextWrapper -from urllib import urlencode -from urlparse import urlparse, urlunparse - -from igraph.compat import property, BytesIO -from igraph.configuration import Configuration -from igraph.utils import multidict - -import re -import urllib2 - -__all__ = ["Nexus", "NexusConnection"] - -__license__ = u"""\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - - -class NexusConnection(object): - ur"""Connection to a remote Nexus server. - - In most cases, you will not have to instantiate this object, just use - the global L{Nexus} variable which is an instance of L{NexusConnection} - and connects to the Nexus repository at U{http://nexus.igraph.org}. - - Example: - - >>> from igraph import summary - >>> karate = Nexus.get("karate") - >>> summary(karate) - IGRAPH UNW- 34 78 -- Zachary's karate club network - + attr: Author (g), Citation (g), name (g), Faction (v), id (v), name (v), weight (e) - - @undocumented: _get_response, _parse_dataset_id, _parse_text_response, - _ensure_uncompressed""" - - def __init__(self, nexus_url=None): - """Constructs a connection to a remote Nexus server. - - @param nexus_url: the root URL of the remote server. Leave it at its - default value (C{None}) unless you have set up your own Nexus server - and you want to connect to that. C{None} fetches the URL from - igraph's configuration file or uses the default URL if no URL - is specified in the configuration file. - """ - self.debug = False - self.url = nexus_url - self._opener = urllib2.build_opener() - - def get(self, id): - """Retrieves the dataset with the given ID from Nexus. - - Dataset IDs are formatted as follows: the name of a dataset on its own - means that a single network should be returned if the dataset contains - a single network, or multiple networks should be returned if the dataset - contains multiple networks. When the name is followed by a dot and a - network ID, only a single network will be returned: the one that has the - given network ID. When the name is followed by a dot and a star, a - dictionary mapping network IDs to networks will be returned even if the - original dataset contains a single network only. - - E.g., getting C{"karate"} would return a single network since the - Zachary karate club dataset contains one network only. Getting - C{"karate.*"} on the other hand would return a dictionary with one - entry that contains the Zachary karate club network. - - @param id: the ID of the dataset to retrieve. - @return: an instance of L{Graph} (if a single graph has to be returned) - or a dictionary mapping network IDs to instances of L{Graph}. - """ - from igraph import load - - dataset_id, network_id = self._parse_dataset_id(id) - - params = dict(format="Python-igraph", id=dataset_id) - response = self._get_response("/api/dataset", params, compressed=True) - result = load(response, format="pickle") - - if network_id is None: - # If result contains a single network only, return that network. - # Otherwise return the whole dictionary - if not isinstance(result, dict): - return result - if len(result) == 1: - return result[result.keys()[0]] - return result - - if network_id == "*": - # Return a dict no matter what - if not isinstance(result, dict): - result = dict(dataset_id=result) - return result - - return result[network_id] - - def info(self, id): - """Retrieves informations about the dataset with the given numeric - or string ID from Nexus. - - @param id: the numeric or string ID of the dataset to retrieve. - @return: an instance of L{NexusDatasetInfo}. - """ - params = dict(format="text", id=id) - response = self._get_response("/api/dataset_info", params) - return NexusDatasetInfo.FromMultiDict(self._parse_text_response(response)) - - def list(self, tags=None, operator="or", order="date"): - """Retrieves a list of datasets matching a set of tags from Nexus. - - @param tags: the tags the returned datasets should have. C{None} - retrieves all the datasets, a single string retrieves datasets - having that given tag. Multiple tags may also be specified as - a list, tuple or any other iterable. - @param operator: when multiple tags are given, this argument - specifies whether the retrieved datasets should match all - the tags (C{"and"}) or any of them (C{"or"}). - @param order: the order of entries; it must be one of C{"date"}, - C{"name"} or C{"popularity"}. - @return: a L{NexusDatasetInfoList} object, which basically acts like a - list and yields L{NexusDatasetInfo} objects. The list is populated - lazily; i.e. the requests will be fired only when needed. - """ - params = dict(format="text", order=order) - if tags is not None: - if not hasattr(tags, "__iter__") or isinstance(tags, basestring): - params["tag"] = str(tags) - else: - params["tag"] = "|".join(str(tag) for tag in tags) - params["operator"] = operator - - return NexusDatasetInfoList(self, "/api/dataset_info", params) - - def search(self, query, order="date"): - """Retrieves a list of datasets matching a query string from Nexus. - - @param query: the query string. Searches are case insensitive and - Nexus searches for complete words only. The special word OR - can be used to find datasets that contain any of the given words - (instead of all of them). Exact phrases must be enclosed in - quotes in the search string. See the Nexus webpage for more - information at U{http://nexus.igraph.org/web/docs#searching}. - @param order: the order of entries; it must be one of C{"date"}, - C{"name"} or C{"popularity"}. - @return: a L{NexusDatasetInfoList} object, which basically acts like a - list and yields L{NexusDatasetInfo} objects. The list is populated - lazily; i.e. the requests will be fired only when needed. - """ - params = dict(q=query, order=order, format="text") - return NexusDatasetInfoList(self, "/api/search", params) - - @staticmethod - def _ensure_uncompressed(response): - """Expects an HTTP response object, checks its Content-Encoding header, - decompresses the data and returns an in-memory buffer holding the - uncompressed data.""" - compressed = response.headers.get("Content-Encoding") == "gzip" - if not compressed: - content_disp = response.headers.get("Content-Disposition", "") - compressed = bool(re.match(r'attachment; *filename=.*\.gz\"?$', - content_disp)) - if compressed: - return GzipFile(fileobj=BytesIO(response.read()), mode="rb") - else: - return response - - def _get_response(self, path, params={}, compressed=False): - """Sends a request to Nexus at the given path with the given parameters - and returns a file-like object for the response. `compressed` denotes - whether we accept compressed responses.""" - if self.url is None: - url = Configuration.instance()["remote.nexus.url"] - else: - url = self.url - url = "%s%s?%s" % (url, path, urlencode(params)) - request = urllib2.Request(url) - if compressed: - request.add_header("Accept-Encoding", "gzip") - if self.debug: - print("[debug] Sending request: %s" % url) - response = self._opener.open(request) - return self._ensure_uncompressed(response) - - @staticmethod - def _parse_dataset_id(id): - """Parses a dataset ID used in the `get` request. - - Returns the dataset ID and the network ID (the latter being C{None} - if the original ID did not contain a network ID ). - """ - dataset_id, _, network_id = str(id).partition(".") - if not network_id: - network_id = None - return dataset_id, network_id - - @staticmethod - def _parse_text_response(response): - """Parses a plain text formatted response from Nexus. - - Plain text formatted responses consist of key-value pairs, separated - by C{":"}. Values may span multiple lines; in this case, the key is - omitted after the first line and the extra lines start with - whitespace. - - The response is assumed to be in UTF-8 encoding. - - Examples: - - >>> d = Nexus._parse_text_response("Id: 17\\nName: foo") - >>> for key, value in sorted(d.items()): - ... print("{0}={1}".format(key, value)) - ... - Id=17 - Name=foo - >>> d = Nexus._parse_text_response("Id: 42\\nName: foo\\n .\\n bar") - >>> for key, value in sorted(d.items()): - ... print("{0}={1}".format(key, value)) - ... - Id=42 - Name=foo - - bar - """ - if hasattr(response, "decode"): - response = response.decode("utf-8") - - if isinstance(response, basestring): - response = response.split("\n") - - result = multidict() - key, value = None, [] - for line in response: - if hasattr(line, "decode"): - line = line.decode("utf-8") - - line = line.rstrip() - if not line: - continue - if key is not None and line[0] in ' \t': - # Line continuation - line = line.lstrip() - if line == '.': - line = '' - value.append(line) - else: - # Key-value pair - if key is not None: - result.add(key, "\n".join(value)) - key, value = line.split(":", 1) - value = [value.strip()] - - if key is not None: - result.add(key, "\n".join(value)) - - return result - - @property - def url(self): - """Returns the root URL of the Nexus repository the connection is - communicating with.""" - return self._url - - @url.setter - def url(self, value): - """Sets the root URL of the Nexus repository the connection is - communicating with.""" - if value is None: - self._url = None - else: - value = str(value) - parts = urlparse(value, "http", False) - self._url = urlunparse(parts) - if self._url and self._url[-1] == "/": - self._url = self._url[:-1] - - -class NexusDatasetInfo(object): - """Information about a dataset in the Nexus repository. - - @undocumented: _update_from_multidict, vertices_edges""" - - def __init__(self, id=None, sid=None, name=None, networks=None, - vertices=None, edges=None, tags=None, attributes=None, - rest=None): - self._conn = None - self.id = id - self.sid = sid - self.name = name - self.vertices = vertices - self.edges = edges - self.tags = tags - self.attributes = attributes - if networks is None: - self.networks = [] - elif not isinstance(networks, (str, unicode)): - self.networks = list(networks) - else: - self.networks = [networks] - if rest: - self.rest = multidict(rest) - else: - self.rest = None - - @property - def vertices_edges(self): - if self.vertices is None or self.edges is None: - return "" - elif isinstance(self.vertices, (list, tuple)) and isinstance(self.edges, (list, tuple)): - return " ".join("%s/%s" % pair for pair in izip(self.vertices, self.edges)) - else: - return "%s/%s" % (self.vertices, self.edges) - - @vertices_edges.setter - def vertices_edges(self, value): - if value is None: - self.vertices, self.edges = None, None - return - - value = value.strip().split(" ") - if len(value) == 0: - self.vertices, self.edges = None, None - elif len(value) == 1: - self.vertices, self.edges = map(int, value[0].split("/")) - else: - self.vertices = [] - self.edges = [] - for ve in value: - v, e = ve.split("/", 1) - self.vertices.append(int(v)) - self.edges.append(int(e)) - - def __repr__(self): - params = "(id=%(id)r, sid=%(sid)r, name=%(name)r, networks=%(networks)r, "\ - "vertices=%(vertices)r, edges=%(edges)r, tags=%(tags)r, "\ - "attributes=%(attributes)r, rest=%(rest)r)" % self.__dict__ - return "%s%s" % (self.__class__.__name__, params) - - def __str__(self): - if self.networks and len(self.networks) > 1: - lines = ["Nexus dataset '%s' (#%s) with %d networks" % - (self.sid, self.id, len(self.networks))] - else: - lines = ["Nexus dataset '%(sid)s' (#%(id)s)" % self.__dict__] - - lines.append("vertices/edges: %s" % self.vertices_edges) - - if self.name: - lines.append("name: %s" % self.name) - if self.tags: - lines.append("tags: %s" % "; ".join(self.tags)) - - if self.rest: - wrapper = TextWrapper(width=76, subsequent_indent=' ') - - keys = sorted(self.rest.iterkeys()) - if "attribute" in self.rest: - keys.remove("attribute") - keys.append("attribute") - - for key in keys: - for value in self.rest.getlist(key): - if not isinstance(value, basestring): - value = str(value) - paragraphs = value.splitlines() - wrapper.initial_indent = "%s: " % key - for paragraph in paragraphs: - ls = wrapper.wrap(paragraph) - if ls: - lines.extend(wrapper.wrap(paragraph)) - else: - lines.append(" .") - wrapper.initial_indent = " " - - return "\n".join(lines) - - def _update_from_multidict(self, params): - """Updates the dataset object from a multidict representation of - key-value pairs, similar to the ones provided by the Nexus API in - plain text response.""" - self.id = params.get("id") - self.sid = params.get("sid") - self.name = params.get("name") - self.vertices = params.get("vertices") - self.edges = params.get("edges") - self.tags = params.get("tags") - - networks = params.get("networks") - if networks: - self.networks = networks.split() - - keys_to_ignore = set("id sid name vertices edges tags networks".split()) - - if self.vertices is None and self.edges is None: - # Try "vertices/edges" - self.vertices_edges = params.get("vertices/edges") - keys_to_ignore.add("vertices/edges") - - if self.rest is None: - self.rest = multidict() - for k in set(params.iterkeys()) - keys_to_ignore: - for v in params.getlist(k): - self.rest.add(k, v) - - if self.id: - self.id = int(self.id) - if self.vertices and not isinstance(self.vertices, (list, tuple)): - self.vertices = int(self.vertices) - if self.edges and not isinstance(self.edges, (list, tuple)): - self.edges = int(self.edges) - if self.tags is not None: - self.tags = self.tags.split(";") - - @classmethod - def FromMultiDict(cls, dict): - """Constructs a Nexus dataset object from a multidict representation - of key-value pairs, similar to the ones provided by the Nexus API in - plain text response.""" - result = cls() - result._update_from_multidict(dict) - return result - - def download(self, network_id=None): - """Retrieves the actual dataset from Nexus. - - @param network_id: if the dataset contains multiple networks, the ID - of the network to be retrieved. C{None} returns a single network if - the dataset contains a single network, or a dictionary of networks - if the dataset contains more than one network. C{"*"} retrieves - a dictionary even if the dataset contains a single network only. - - @return: a L{Graph} instance or a dictionary mapping network names to - L{Graph} instances. - """ - if self.id is None: - raise ValueError("dataset ID is empty") - conn = self._conn or Nexus - if network_id is None: - return conn.get(self.id) - return conn.get("%s.%s" % (self.id, network_id)) - - get = download - - -class NexusDatasetInfoList(object): - """A read-only list-like object that can be used to retrieve the items - from a Nexus search result. - """ - - def __init__(self, connection, method, params): - """Constructs a Nexus dataset list that will use the given connection - and the given parameters to retrieve the search results. - - @param connection: a Nexus connection object - @param method: the URL of the Nexus API method to call - @param params: the parameters to pass in the GET requests, in the - form of a Python dictionary. - """ - self._conn = connection - self._method = str(method) - self._params = params - self._length = None - self._datasets = [] - self._blocksize = 10 - - def _fetch_results(self, index): - """Fetches the results from Nexus such that the result item with the - given index will be available (unless the result list is shorter than - the given index of course).""" - # Calculate the start offset - page = index // self._blocksize - offset = page * self._blocksize - self._params["offset"] = offset - self._params["limit"] = self._blocksize - - # Ensure that self._datasets has the necessary length - diff = (page+1) * self._blocksize - len(self._datasets) - if diff > 0: - self._datasets.extend([None] * diff) - - response = self._conn._get_response(self._method, self._params) - if hasattr(response, "decode"): - response = response.decode("utf-8") - - current_dataset = None - for line in response: - key, value = line.strip().split(": ", 1) - key = key.lower() - - if key == "totalsize": - # Total number of items in the search result - self._length = int(value) - elif key == "id": - # Starting a new dataset - if current_dataset: - self._datasets[offset] = current_dataset - offset += 1 - current_dataset = NexusDatasetInfo(id=int(value)) - current_dataset._conn = self._conn - elif key == "sid": - current_dataset.sid = value - elif key == "name": - current_dataset.name = value - elif key == "vertices": - current_dataset.vertices = int(value) - elif key == "edges": - current_dataset.edges = int(value) - elif key == "vertices/edges": - current_dataset.vertices_edges = value - elif key == "tags": - current_dataset.tags = value.split(";") - - if current_dataset: - self._datasets[offset] = current_dataset - - def __getitem__(self, index): - if len(self._datasets) <= index: - self._fetch_results(index) - elif self._datasets[index] is None: - self._fetch_results(index) - return self._datasets[index] - - def __iter__(self): - for i in xrange(len(self)): - yield self[i] - - def __len__(self): - """Returns the number of result items.""" - if self._length is None: - self._fetch_results(0) - return self._length - - def __str__(self): - """Converts the Nexus result list into a nice human-readable format.""" - max_index_length = len(str(len(self))) + 2 - indent = "\n" + " " * (max_index_length+1) - - result = [] - for index, item in enumerate(self): - formatted_item = ("[%d]" % index).rjust(max_index_length) + " " + \ - str(item).replace("\n", indent) - result.append(formatted_item) - return "\n".join(result) - -Nexus = NexusConnection() \ No newline at end of file From a2cfd061003023e6d1891c65c3db642112bca05b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Jan 2020 11:28:30 +0100 Subject: [PATCH 0166/1892] fixed usage of select.select() in setup.py on Windows, closes #59 --- setup.py | 60 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/setup.py b/setup.py index 3641621da..da9660833 100644 --- a/setup.py +++ b/setup.py @@ -209,6 +209,44 @@ def quote_path_for_shell(s): return "'" + s.replace("'", "'\\''") + "'" +def wait_for_keypress(seconds): + """Wait for a keypress or until the given number of seconds have passed, + whichever happens first. + """ + is_windows = platform.system() == "windows" + + while seconds > 0: + if seconds > 1: + plural = "s" + else: + plural = "" + + sys.stdout.write( + "\rContinuing in %2d second%s; press Enter to continue " + "immediately. " % (seconds, plural) + ) + sys.stdout.flush() + + if is_windows: + from msvcrt import kbhit + + for i in range(10): + if kbhit(): + seconds = 0 + break + sleep(0.1) + else: + rlist, _, _ = select([sys.stdin], [], [], 1) + if rlist: + sys.stdin.readline() + seconds = 0 + break + + seconds -= 1 + + sys.stdout.write("\r" + " " * 65 + "\r") + + ########################################################################### @@ -674,26 +712,8 @@ def use_educated_guess(self): print("- LIBIGRAPH_FALLBACK_LIBRARY_DIRS") print("") - seconds_remaining = 10 if self.wait else 0 - while seconds_remaining > 0: - if seconds_remaining > 1: - plural = "s" - else: - plural = "" - - sys.stdout.write( - "\rContinuing in %2d second%s; press Enter to continue " - "immediately. " % (seconds_remaining, plural) - ) - sys.stdout.flush() - - rlist, _, _ = select([sys.stdin], [], [], 1) - if rlist: - sys.stdin.readline() - break - - seconds_remaining -= 1 - sys.stdout.write("\r" + " " * 65 + "\r") + if self.wait: + wait_for_keypress(seconds=10) self.libraries = LIBIGRAPH_FALLBACK_LIBRARIES[:] if self.static_extension: From 2898e4ca9c66d426a9a0efaa17f2f1f372609878 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Jan 2020 11:34:35 +0100 Subject: [PATCH 0167/1892] fixed handling of integers-as-names in VertexSeq.find(), closes #73 --- src/igraph/__init__.py | 9 ++++++--- tests/test_vertexseq.py | 11 +++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 7fad8bb29..e93f2885b 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3469,8 +3469,11 @@ def find(self, *args, **kwds): >>> g.vs.find(_degree=0) #doctest:+SKIP """ - # Shortcut: if "name" is in kwds and there are no positional arguments, - # we try that first because that attribute is indexed + # Shortcut: if "name" is in kwds, there are no positional arguments, + # and the specified name is a string, we try that first because that + # attribute is indexed. Note that we cannot do this if name is an + # integer, because it would then translate to g.vs.select(name), which + # searches by _index_ if the argument is an integer if not args: if "name" in kwds: name = kwds.pop("name") @@ -3479,7 +3482,7 @@ def find(self, *args, **kwds): else: name = None - if name is not None: + if name is not None and isinstance(name, (str, unicode)): args = [name] if args: diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 80ea27749..89831fd5b 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -323,6 +323,17 @@ def testGraphMethodProxying(self): for v, d in zip(vs, vs.degree()): self.assertEqual(v.degree(), d) + def testBug73(self): + # This is a regression test for igraph/python-igraph#73 + g = Graph() + g.add_vertices(2) + g.vs[0]["name"] = 1 + g.vs[1]["name"] = "h" + + self.assertEqual(1, g.vs.find("h").index) + self.assertEqual(1, g.vs.find(1).index) + self.assertEqual(0, g.vs.find(name=1).index) + def suite(): vertex_suite = unittest.makeSuite(VertexTests) From e4c8e589f1ff77d24e0bfb2b939ffc8577917090 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Jan 2020 12:18:02 +0100 Subject: [PATCH 0168/1892] allow setting width and height separately for vertices, refs #39 --- src/igraph/drawing/vertex.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/vertex.py b/src/igraph/drawing/vertex.py index ff500995c..a84ba53e4 100644 --- a/src/igraph/drawing/vertex.py +++ b/src/igraph/drawing/vertex.py @@ -82,14 +82,18 @@ class VisualVertexBuilder(AttributeCollectorBase): label_size = 14.0 position = dict(func=self.layout.__getitem__) shape = ("circle", ShapeDrawerDirectory.resolve_default) - size = 20.0 + size = 20.0 + width = None + height = None return VisualVertexBuilder def draw(self, visual_vertex, vertex, coords): context = self.context - visual_vertex.shape.draw_path(context, \ - coords[0], coords[1], visual_vertex.size) + width = visual_vertex.width if visual_vertex.width is not None else visual_vertex.size + height = visual_vertex.height if visual_vertex.height is not None else visual_vertex.size + + visual_vertex.shape.draw_path(context, coords[0], coords[1], width, height) context.set_source_rgba(*visual_vertex.color) context.fill_preserve() context.set_source_rgba(*visual_vertex.frame_color) From da2be97d1ea56318061b30b62fbf0ea26cac44a1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Jan 2020 12:23:32 +0100 Subject: [PATCH 0169/1892] added stale bot (same settings as igraph/igraph) --- .github/stale.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..58e48a20f --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,24 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 14 + +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + - todo + - wishlist + +# Label to use when marking an issue as stale +staleLabel: stale + +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed in 14 days if no further activity occurs. + Thank you for your contributions. + +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 16dd372a04efbb818addeae8e77725330a1ac19f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jan 2020 09:41:23 +0100 Subject: [PATCH 0170/1892] added option to force setup.py to use pkg-config only, refs #245 --- README.md | 37 +++++++++++++++++++++++++++++++++++++ setup.py | 31 +++++++++++++++++-------------- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index eae63bc6e..40c263a5e 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,43 @@ $ pip install python-igraph This should compile the C core of igraph as well as the Python extension automatically. +### Linking to an existing igraph installation + +The source code of the Python package includes the source code of the matching +igraph version that the Python interface should compile against. However, if +you want to link the Python interface to a custom installation of the C core +that has already been compiled and installed on your system, you can ask +`setup.py` to use the pre-compiled version. This option requires that your +custom installation of igraph is discoverable with `pkg-config`. First, check +whether `pkg-config` can tell you the required compiler and linker flags for +igraph: + +``` +$ pkg-config --cflags --libs igraph +``` + +If `pkg-config` responds with a set of compiler and linker flags and not an +error message, you are probably okay. You can then proceed with the +installation using pip: + +``` +$ pip install python-igraph --install-option="--use-pkg-config" +``` + +Alternatively, if you have already downloaded and extracted the source code +of igraph, you can run `setup.py` directly: + +``` +$ python setup.py build --use-pkg-config +``` + +This option is primarily intended for package maintainers in Linux +distributions so they can ensure that the packaged Python interface links to +the packaged igraph library instead of bringing its own copy. + +It is also useful on macOS if you want to link to the igraph library installed +from Homebrew. + ## Compiling the development version If you have downloaded the source code from Github and not PyPI, chances are diff --git a/setup.py b/setup.py index da9660833..1f82686c0 100644 --- a/setup.py +++ b/setup.py @@ -420,7 +420,7 @@ def __init__(self): self.define_macros = [] self.extra_objects = [] self.static_extension = False - self.use_pkgconfig = True + self.use_pkgconfig = False self._has_pkgconfig = None self.excluded_include_dirs = [] self.excluded_library_dirs = [] @@ -486,19 +486,20 @@ def run(self): print("You will need the Python headers to compile this extension.") sys.exit(1) - # Check whether we have already compiled igraph in a previous run. - # If so, it should be found in vendor/install/igraph/include and - # vendor/install/igraph/lib - self.run_command("build_c_core") - if not buildcfg.c_core_built: - # Try detecting with pkg-config if we haven't found the submodule - detected = ( - buildcfg.use_pkgconfig and buildcfg.detect_from_pkgconfig() - ) - - # Fall back to an educated guess if everything else failed + # Check whether the user asked us to discover a pre-built igraph + # with pkg-config + if buildcfg.use_pkgconfig: + detected = buildcfg.detect_from_pkgconfig() if not detected: - buildcfg.use_educated_guess() + print("Cannot find the C core of igraph on this system using pkg-config.") + sys.exit(1) + else: + # Build the C core from the vendored igraph source + self.run_command("build_c_core") + if not buildcfg.c_core_built: + # Fall back to an educated guess if everything else failed + if not detected: + buildcfg.use_educated_guess() # Add any extra library paths if needed; this is needed for the # Appveyor CI build @@ -594,7 +595,6 @@ def detect_from_pkgconfig(self): """Detects the igraph include directory, library directory and the list of libraries to link to using ``pkg-config``.""" if not buildcfg.has_pkgconfig: - print("Cannot find the C core of igraph on this system using pkg-config.") return False cmd = ["pkg-config", "igraph", "--cflags", "--libs"] @@ -649,6 +649,9 @@ def process_args_from_command_line(self): elif option == "--no-wait": opts_to_remove.append(idx) self.wait = False + elif option == "--use-pkg-config": + opts_to_remove.append(idx) + self.use_pkgconfig = True for idx in reversed(opts_to_remove): sys.argv[idx : (idx + 1)] = [] From c69319e4df57b5b06ad6a5ae7029b38456a9ed83 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jan 2020 10:07:37 +0100 Subject: [PATCH 0171/1892] cleaning up the tarball generated with setup.py sdist a bit --- MANIFEST.in | 7 +++++++ setup.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 9f8faf472..561b3cf89 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,5 +6,12 @@ include scripts/mkdoc.sh include scripts/epydoc-patched include scripts/epydoc.cfg include tests/*.py + graft vendor/source/igraph +prune vendor/source/igraph/doc/abstracts +prune vendor/source/igraph/doc/papers +prune vendor/source/igraph/doc/presentations +prune vendor/source/igraph/tools/virtual +prune vendor/source/optional/simpleraytracer +prune vendor/source/tools/virtual diff --git a/setup.py b/setup.py index 1f82686c0..eec0c3077 100644 --- a/setup.py +++ b/setup.py @@ -535,6 +535,38 @@ def run(self): return custom_build_ext + @property + def sdist(self): + """Returns a class that can be used as a replacement for the + ``sdist`` command in ``setuptools`` and that will clean up + ``vendor/source/igraph`` before running the original ``sdist`` + command. + """ + from setuptools.command.sdist import sdist + from distutils.sysconfig import get_python_inc + + buildcfg = self + + class custom_sdist(sdist): + def run(self): + # Clean up vendor/source/igraph with git + cwd = os.getcwd() + try: + os.chdir(os.path.join("vendor", "source", "igraph")) + if os.path.exists(".git"): + retcode = subprocess.call("git clean -dfx", shell=True) + if retcode: + print("Failed to clean vendor/source/igraph with git") + print("") + return False + finally: + os.chdir(cwd) + + # Run the original sdist command + sdist.run(self) + + return custom_sdist + def compile_igraph_from_vendor_source(self): """Compiles igraph from the vendored source code inside `vendor/igraph/source`. This folder typically comes from a git submodule. @@ -799,6 +831,7 @@ def use_educated_guess(self): cmdclass={ "build_c_core": buildcfg.build_c_core, # used by CI "build_ext": buildcfg.build_ext, + "sdist": buildcfg.sdist }, ) From a45a40dfc2e304918fe7793ddf68bea4f6422a76 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jan 2020 10:10:04 +0100 Subject: [PATCH 0172/1892] more cleanup in sdist --- MANIFEST.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 561b3cf89..d1a691ec5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,6 +11,9 @@ graft vendor/source/igraph prune vendor/source/igraph/doc/abstracts prune vendor/source/igraph/doc/papers prune vendor/source/igraph/doc/presentations +prune vendor/source/igraph/interfaces +prune vendor/source/igraph/msvc +prune vendor/source/igraph/nexus prune vendor/source/igraph/tools/virtual prune vendor/source/optional/simpleraytracer prune vendor/source/tools/virtual From d3e798d316377a9c25aff66d45639b550f176351 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jan 2020 10:11:28 +0100 Subject: [PATCH 0173/1892] even more cleanup in sdist --- MANIFEST.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index d1a691ec5..23313f559 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -15,6 +15,6 @@ prune vendor/source/igraph/interfaces prune vendor/source/igraph/msvc prune vendor/source/igraph/nexus prune vendor/source/igraph/tools/virtual -prune vendor/source/optional/simpleraytracer -prune vendor/source/tools/virtual +prune vendor/source/igraph/optional/simpleraytracer +prune vendor/source/igraph/tools/virtual From dad94d8a105c4d6b9c2568b90bd72fc02807ad7f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jan 2020 12:30:39 +0100 Subject: [PATCH 0174/1892] removed Debian packaging --- debian/changelog | 20 ------------- debian/compat | 1 - debian/control | 48 -------------------------------- debian/copyright | 29 ------------------- debian/python-igraph-doc.install | 1 - debian/python-igraph.install | 3 -- debian/python3-igraph.install | 2 -- debian/rules | 44 ----------------------------- debian/source/format | 1 - 9 files changed, 149 deletions(-) delete mode 100644 debian/changelog delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/python-igraph-doc.install delete mode 100644 debian/python-igraph.install delete mode 100644 debian/python3-igraph.install delete mode 100755 debian/rules delete mode 100644 debian/source/format diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index b9ac4b75a..000000000 --- a/debian/changelog +++ /dev/null @@ -1,20 +0,0 @@ -python-igraph (0.6-3) unstable; urgency=low - - * Added python-docutils to build dependencies. - * Removed PDF documentation from python-igraph-doc. - * Not running unittests during build because some stochastic test - cases fail on i386. - - -- Tamas Nepusz Wed, 27 Jun 2012 22:33:00 +0200 - -python-igraph (0.6-2) unstable; urgency=low - - * Added pkg-config to build dependencies. - - -- Tamas Nepusz Wed, 27 Jun 2012 22:21:00 +0200 - -python-igraph (0.6-1) unstable; urgency=low - - * Initial Release. - - -- Tamas Nepusz Tue, 26 Jun 2012 19:17:00 +0200 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7f8f011eb..000000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/debian/control b/debian/control deleted file mode 100644 index d194b2ced..000000000 --- a/debian/control +++ /dev/null @@ -1,48 +0,0 @@ -Source: python-igraph -Section: python -Priority: optional -Maintainer: Tamas Nepusz -Build-Depends: debhelper (>= 7.0.50~), python-all-dev (>= 2.6.6-3~), - python3-all-dev (>= 3.2), libxml2-dev, libigraph0-dev (>= 0.6~), python-epydoc, - python-setuptools, python3-setuptools, pkg-config, python-docutils -Standards-Version: 3.9.4 -X-Python-Version: >= 2.5 -X-Python3-Version: >= 3.2 -Homepage: http://igraph.org - -Package: python-igraph -Architecture: any -Depends: ${shlibs:Depends}, ${python:Depends}, ${misc:Depends}, libigraph0 (>= 0.6~) -Suggests: python-igraph-doc, python-cairo -Provides: ${python:Provides} -Description: Python interface for the igraph library (Python 2) - igraph is a library for creating and manipulating graphs. - It is intended to be as powerful (ie. fast) as possible to enable the - analysis of large graphs. - . - This package contains the Python 2 interface of igraph. - -Package: python3-igraph -Architecture: any -Depends: ${shlibs:Depends}, ${python3:Depends}, ${misc:Depends}, libigraph0 (>= 0.6~) -Suggests: python-igraph-doc, python3-cairo -Provides: ${python3:Provides} -Description: Python interface for the igraph library (Python 3) - igraph is a library for creating and manipulating graphs. - It is intended to be as powerful (ie. fast) as possible to enable the - analysis of large graphs. - . - This package contains the Python 3 interface of igraph. - -Package: python-igraph-doc -Architecture: all -Section: doc -Depends: ${misc:Depends} -Suggests: python-igraph, python-doc -Description: Documentation of the Python interface of the igraph library - igraph is a library for creating and manipulating graphs. - It is intended to be as powerful (ie. fast) as possible to enable the - analysis of large graphs. - . - This package contains the API documentation of the Python interface of - the igraph library. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 62814f0fb..000000000 --- a/debian/copyright +++ /dev/null @@ -1,29 +0,0 @@ -This package was debianized by Tamas Nepusz on Tue, 26 Jun 2012 19:17:00 +0200. - -It was downloaded from http://pypi.python.org/packages/source/p/python-igraph/python-igraph-0.6.tar.gz - -Upstream Authors: Gabor Csardi, Tamas Nepusz - -Copyright: - -Copyright (C) 2005-2012 Gabor Csardi, Tamas Nepusz - -License: - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License with -the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; -if not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301 USA - -On Debian systems, the complete text of the GNU General Public -License, version 2, can be found in /usr/share/common-licenses/GPL-2. diff --git a/debian/python-igraph-doc.install b/debian/python-igraph-doc.install deleted file mode 100644 index c96544278..000000000 --- a/debian/python-igraph-doc.install +++ /dev/null @@ -1 +0,0 @@ -doc/api/html/* /usr/share/doc/python-igraph-doc \ No newline at end of file diff --git a/debian/python-igraph.install b/debian/python-igraph.install deleted file mode 100644 index 7dbca8f2a..000000000 --- a/debian/python-igraph.install +++ /dev/null @@ -1,3 +0,0 @@ -/usr/lib/python2*/*-packages/igraph/ -/usr/include/python2*/python-igraph/ -/usr/bin/igraph \ No newline at end of file diff --git a/debian/python3-igraph.install b/debian/python3-igraph.install deleted file mode 100644 index bb348a82f..000000000 --- a/debian/python3-igraph.install +++ /dev/null @@ -1,2 +0,0 @@ -/usr/lib/python3*/*-packages/igraph/ -/usr/include/python3*/python-igraph/ \ No newline at end of file diff --git a/debian/rules b/debian/rules deleted file mode 100755 index c52f42684..000000000 --- a/debian/rules +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -# export DH_VERBOSE=1 - -PYTHON2=$(shell pyversions -vr) -PYTHON3=$(shell py3versions -vr) - -%: - dh $@ --with python2,python3 - -# Disabled for the time being -# ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) -# test-python%: -# python$* setup.py test -vv -# -# override_dh_auto_test: $(PYTHON2:%=test-python%) $(PYTHON3:%=test-python%) -# endif - -build-python%: - python$* setup.py build - -override_dh_auto_build: $(PYTHON3:%=build-python%) - dh_auto_build - chmod a+x scripts/epydoc-patched - scripts/mkdoc.sh $(CURDIR)/build/lib.linux-*2.7 - -install-python%: - python$* setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb - -override_dh_auto_install: $(PYTHON3:%=install-python%) - dh_auto_install - -override_dh_auto_clean: - dh_auto_clean - rm -rf build - rm -rf *.egg-info - diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8d8..000000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) From a480ef35dcebf1286eb9f2ede4e1b3d789d24049 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 2 Feb 2020 11:25:50 +0100 Subject: [PATCH 0175/1892] trying to add support for 32-bit builds in Appveyor --- appveyor.yml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a68dc19bd..f472c2304 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,14 +2,21 @@ image: - Visual Studio 2017 environment: - PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% - MSYSTEM: MINGW64 - TARGET_ARCH: "x64" - CIBW_BEFORE_BUILD: python setup.py build_c_core - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "*-win32" - IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" - # DEVENV_EXECUTABLE: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe + global: + CIBW_BEFORE_BUILD: python setup.py build_c_core + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" + + matrix: + - CIBW_BUILD: "*-win_amd64" + MSYSTEM: MINGW64 + PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% + TARGET_ARCH: "x64" + + - CIBW_BUILD: "*-win32" + MSYSTEM: MINGW32 + PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% + TARGET_ARCH: "x86" platform: - x64 From 1e552710d42bbc054a71fb0eaf72937b7102ed84 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Feb 2020 11:25:04 +0100 Subject: [PATCH 0176/1892] skip Python 2.7 32-bit build on Windows temporarily - it seems like something is not installed in Appveyor --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index f472c2304..d0c9885fb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,7 @@ environment: TARGET_ARCH: "x64" - CIBW_BUILD: "*-win32" + CIBW_SKIP: "cp27-*" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" From ec6f417cbf1809eb5bde1111073819b434414249 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Feb 2020 13:55:26 +0100 Subject: [PATCH 0177/1892] Appveyor: load vcvars32.bat when compiling for 32-bit --- appveyor.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d0c9885fb..fe604e9f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,17 +8,17 @@ environment: IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" matrix: - - CIBW_BUILD: "*-win_amd64" - MSYSTEM: MINGW64 - PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% - TARGET_ARCH: "x64" - - CIBW_BUILD: "*-win32" CIBW_SKIP: "cp27-*" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" + - CIBW_BUILD: "*-win_amd64" + MSYSTEM: MINGW64 + PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% + TARGET_ARCH: "x64" + platform: - x64 @@ -32,9 +32,19 @@ install: before_build: - git submodule update --init --recursive -build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" - - cibuildwheel --output-dir wheelhouse +for: + - matrix: + only: + - MSYSTEM: MINGW32 + build_script: + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" + - cibuildwheel --output-dir wheelhouse + - matrix: + only: + - MSYSTEM: MINGW64 + build_script: + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + - cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" From 9c59f1fed3df5aa40a244c9cc10177b1320fd399 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Feb 2020 14:05:42 +0100 Subject: [PATCH 0178/1892] Appveyor: fix indentation in config --- appveyor.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fe604e9f6..223f03d0c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,15 +36,15 @@ for: - matrix: only: - MSYSTEM: MINGW32 - build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" - - cibuildwheel --output-dir wheelhouse + build_script: + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" + - cibuildwheel --output-dir wheelhouse - matrix: only: - MSYSTEM: MINGW64 - build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" - - cibuildwheel --output-dir wheelhouse + build_script: + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + - cibuildwheel --output-dir wheelhouse artifacts: - path: "wheelhouse\\*.whl" From 5d2fcd851bbe9b22744efe805da40d45a7e31c72 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 08:56:16 +0100 Subject: [PATCH 0179/1892] Appveyor: trying to compile with libxml2 now --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 223f03d0c..65deb3354 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,8 +25,7 @@ platform: install: - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - bash -lc "pacman --noconfirm -Sy" - - bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool" - - bash -lc "pacman --noconfirm -S libxml2-devel zip" + - bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - pip install cibuildwheel==1.1.0 before_build: From a132cda9f9357b404e2a133cf93c47495d9ee893 Mon Sep 17 00:00:00 2001 From: Sviatoslav Date: Thu, 30 Jan 2020 23:30:31 +0300 Subject: [PATCH 0180/1892] re-add sparse adjacency func --- src/igraph/__init__.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e93f2885b..ad858261f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -592,6 +592,36 @@ def get_adjacency(self, type=GET_ADJACENCY_BOTH, attribute=None, \ return Matrix(data) + def get_adjacency_sparse(self, attribute=None): + """Returns the adjacency matrix of a graph as scipy csr matrix. + @param attribute: if C{None}, returns the ordinary adjacency + matrix. When the name of a valid edge attribute is given + here, the matrix returned will contain the default value + at the places where there is no edge or the value of the + given attribute where there is an edge. + @return: the adjacency matrix as a L{scipy.sparse.csr_matrix}.""" + try: + from scipy.sparse import csr_matrix + except ImportError: + raise ImportError('You should install scipy package in order to use this function') + + edges = self.get_edgelist() + if attribute is None: + weights = np.ones(len(edges)) + else: + if attribute not in self.es.attribute_names(): + raise ValueError("Attribute does not exist") + + weights = self.es[attribute] + + N = self.vcount() + sparse_matrix = csr_matrix((weights, zip(*edges)), shape=(N, N)) + + if not self.is_directed(): + sparse_matrix = sparse_matrix + sparse_matrix.T + di = np.diag_indices(len(edges)) + sparse_matrix[di] /= 2 + return sparse_matrix def get_adjlist(self, mode=OUT): """get_adjlist(mode=OUT) From 39b8abc289b75a6810fbd974182bda2fc50bf862 Mon Sep 17 00:00:00 2001 From: Sviatoslav Date: Fri, 31 Jan 2020 22:37:29 +0300 Subject: [PATCH 0181/1892] add adjacency_sparse with inner import --- src/igraph/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index ad858261f..ddcf246ea 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -607,7 +607,7 @@ def get_adjacency_sparse(self, attribute=None): edges = self.get_edgelist() if attribute is None: - weights = np.ones(len(edges)) + weights = [1] * len(edges) else: if attribute not in self.es.attribute_names(): raise ValueError("Attribute does not exist") From b4f3a612b49564a00353edc59123bebbda9a137a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 10:02:26 +0100 Subject: [PATCH 0182/1892] raise an exception when using unhashable vertex names --- src/_igraph/attributes.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 6639e1a50..fd9431834 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -79,7 +79,22 @@ int igraphmodule_i_attribute_struct_index_vertex_names( value = PyInt_FromLong(n); /* we do own a reference to value */ if (value == 0) return 1; - PyDict_SetItem(attrs->vertex_name_index, key, value); + + if (PyDict_SetItem(attrs->vertex_name_index, key, value)) { + /* probably unhashable vertex name. If the error is a TypeError, convert + * it to a more readable error message */ + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_Format( + PyExc_RuntimeError, + "error while indexing vertex names; did you accidentally try to " + "use a non-hashable object as a vertex name earlier? " + "Check the name of vertex %R (%R)", value, key + ); + } + + return 1; + } + /* PyDict_SetItem did an INCREF for both the key and a value, therefore we * have to drop our reference on value */ Py_DECREF(value); From 99530e959cf30e8492920228dad3af4920873db8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 10:07:46 +0100 Subject: [PATCH 0183/1892] added a test case to unhashable vertex names --- tests/test_attributes.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 65eda85c9..45984a737 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -86,6 +86,24 @@ def testVertexNameIndexingBytes(self): del g.vs["name"] self.assertRaises(ValueError, g.degree, [b"bar", b"thud", 0]) + def testUnhashableVertexNames(self): + g = Graph.Famous("bull") + g.vs["name"] = [str(x) for x in range(4)] + + value = "this is not hashable".split() + g.vs[2]["name"] = value + + # Trigger an indexing by doing a lookup by name + try: + g.vs.find("3") + err = None + except Exception as ex: + err = ex + + # Check the exception + self.assertTrue(isinstance(err, RuntimeError)) + self.assertTrue(repr(value) in str(err)) + def testVertexNameIndexingBug196(self): g = Graph() a, b = b'a', b'b' From 1b6881b60e706d069001eb3f7fa4cc67d569ae5e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 10:10:54 +0100 Subject: [PATCH 0184/1892] Graph.es.select() with _source and _target now works properly for undirected graphs, fixes #30 --- src/igraph/__init__.py | 65 ++++++++++++++++++++++++++++++------- tests/test_edgeseq.py | 74 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 14 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index ddcf246ea..ec69625aa 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3647,13 +3647,13 @@ def select(self, *args, **kwds): "notin": lambda a, b: a not in b } for keyword, value in kwds.iteritems(): if "_" not in keyword or keyword.rindex("_") == 0: - keyword = keyword+"_eq" + keyword = keyword + "_eq" attr, _, op = keyword.rpartition("_") try: func = operators[op] except KeyError: # No such operator, assume that it's part of the attribute name - attr, func = keyword, operators["eq"] + attr, op, func = keyword, "eq", operators["eq"] if attr[0] == '_': # Method call, not an attribute @@ -3855,9 +3855,15 @@ def select(self, *args, **kwds): properties of the edges, e.g., their centrality. The rules are as follows: - 1. C{_source} or {_from} means the source vertex of an edge. + 1. C{_source} or {_from} means the source vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). - 2. C{_target} or {_to} means the target vertex of an edge. + 2. C{_target} or {_to} means the target vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). 3. C{_within} ignores the operator and checks whether both endpoints of the edge lie within a specified set. @@ -3867,7 +3873,10 @@ def select(self, *args, **kwds): endpoint lies within another specified set. The two sets must be given as a tuple. - 5. Otherwise, the rest of the name is interpreted as a method of the + 5. C{_incident} ignores the operator and checks whether the edge is + incident on a specific vertex or a set of vertices. + + 6. Otherwise, the rest of the name is interpreted as a method of the L{Graph} object. This method is called with the edge sequence as its first argument (all others left at default values) and edges are filtered according to the value returned by the method. @@ -3911,6 +3920,7 @@ def select(self, *args, **kwds): @return: the new, filtered edge sequence""" es = _igraph.EdgeSeq.select(self, *args) + is_directed = self.graph.is_directed() def _ensure_set(value): if isinstance(value, VertexSeq): @@ -3930,25 +3940,55 @@ def _ensure_set(value): "notin": lambda a, b: a not in b } for keyword, value in kwds.iteritems(): if "_" not in keyword or keyword.rindex("_") == 0: - keyword = keyword+"_eq" + keyword = keyword + "_eq" pos = keyword.rindex("_") attr, op = keyword[0:pos], keyword[pos+1:] try: func = operators[op] except KeyError: # No such operator, assume that it's part of the attribute name - attr = "%s_%s" % (attr,op) - func = operators["eq"] + attr, op, func = keyword, "eq", operators["eq"] if attr[0] == '_': - if attr == "_source" or attr == "_from": + if attr in ("_source", "_from", "_target", "_to") and not is_directed: + if op not in ("eq", "in"): + raise RuntimeError("unsupported for undirected graphs") + + # translate to _incident to avoid confusion + attr = "_incident" + if func == operators["eq"]: + if hasattr(value, "__iter__") and not isinstance(value, (str, unicode)): + value = set(value) + else: + value = set([value]) + + if attr in ("_source", "_from"): values = [e.source for e in es] if op == "in" or op == "notin": value = _ensure_set(value) - elif attr == "_target" or attr == "_to": + + elif attr in ("_target", "_to"): values = [e.target for e in es] if op == "in" or op == "notin": value = _ensure_set(value) + + elif attr == "_incident": + func = None # ignoring function, filtering here + value = _ensure_set(value) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in value: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those that are in the current edge sequence + filtered_idxs = [i for i, e in enumerate(es) if e.index in candidates] + else: + # We are done, the filtered indexes are in the candidates set + filtered_idxs = sorted(candidates) + elif attr == "_within": func = None # ignoring function, filtering here value = _ensure_set(value) @@ -3968,6 +4008,7 @@ def _ensure_set(value): # exactly once in increasing order of edge IDs filtered_idxs = [i for i in candidates if es[i].source in value and es[i].target in value] + elif attr == "_between": if len(value) != 2: raise ValueError("_between selector requires two vertex ID lists") @@ -3994,6 +4035,7 @@ def _ensure_set(value): filtered_idxs = [i for i in candidates if (es[i].source in set1 and es[i].target in set2) or (es[i].target in set1 and es[i].source in set2)] + else: # Method call, not an attribute values = getattr(es.graph, attr[1:])(es) @@ -4003,8 +4045,7 @@ def _ensure_set(value): # If we have a function to apply on the values, do that; otherwise # we assume that filtered_idxs has already been calculated. if func is not None: - filtered_idxs=[i for i, v in enumerate(values) \ - if func(v, value)] + filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] es = es.select(filtered_idxs) diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index d15af3002..6a448b735 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -11,6 +11,7 @@ except ImportError: np = None + class EdgeTests(unittest.TestCase): def setUp(self): self.g = Graph.Full(10) @@ -119,6 +120,10 @@ def testProxyMethods(self): class EdgeSeqTests(unittest.TestCase): + def assert_edges_unique_in(self, es): + pairs = sorted(e.tuple for e in es) + self.assertEqual(pairs, sorted(set(pairs))) + def setUp(self): self.g = Graph.Full(10) self.g.es["test"] = range(45) @@ -260,8 +265,8 @@ def testKeywordFilteringSelect(self): self.assertTrue(len(g.es(betweenness_gt=10, parity=0)) < 2000) def testSourceTargetFiltering(self): - g = Graph.Barabasi(1000, 2) - es1 = set(e.source for e in g.es.select(_target_in = [2,4])) + g = Graph.Barabasi(1000, 2, directed=True) + es1 = set(e.source for e in g.es.select(_target_in = [2, 4])) es2 = set(v1 for v1, v2 in g.get_edgelist() if v2 in [2, 4]) self.assertTrue(es1 == es2) @@ -276,10 +281,12 @@ def testWithinFiltering(self): for es in [es1, es2]: self.assertTrue(len(es) == 12) self.assertTrue(all(e.source in vs and e.target in vs for e in es)) + self.assert_edges_unique_in(es) es_filtered = es.select(_within = vs2) self.assertTrue(len(es_filtered) == 4) self.assertTrue(all(e.source in vs2 and e.target in vs2 for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) def testBetweenFiltering(self): g = Graph.Lattice([10, 10]) @@ -292,6 +299,69 @@ def testBetweenFiltering(self): self.assertTrue(len(es) == 3) self.assertTrue(all((e.source in vs1 and e.target in vs2) or \ (e.target in vs1 and e.source in vs2) for e in es)) + self.assert_edges_unique_in(es) + + def testIncidentFiltering(self): + g = Graph.Lattice([10, 10], circular=False) + vs = (0, 1, 10, 11) + vs2 = (11, 0, 24) + vs3 = sorted(set(vs).intersection(set(vs2))) + + es = g.es.select(_incident = vs) + self.assertEqual(8, len(es)) + self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) + self.assert_edges_unique_in(es) + + es_filtered = es.select(_incident = vs2) + self.assertEqual(6, len(es_filtered)) + self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) + + def testIncidentFilteringByNames(self): + g = Graph.Lattice([10, 10], circular=False) + vs = (0, 1, 10, 11) + g.vs[vs]["name"] = ["A", "B", "C", "D"] + + vs2 = (11, 0, 24) + g.vs[24]["name"] = "X" + + vs3 = sorted(set(vs).intersection(set(vs2))) + + es = g.es.select(_incident = ("A", "B", "C", "D")) + self.assertEqual(8, len(es)) + self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) + self.assert_edges_unique_in(es) + + es_filtered = es.select(_incident = ("D", "A", "X")) + self.assertEqual(6, len(es_filtered)) + self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) + + es_filtered = es_filtered.select(_from="A") + self.assertEqual(2, len(es_filtered)) + self.assertTrue(all((e.source == 0 or e.target == 0) for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) + + def testSourceAndTargetFilteringForUndirectedGraphs(self): + g = Graph.Lattice([10, 10], circular=False) + vs = (0, 1, 10, 11) + vs2 = (11, 0, 24) + vs3 = sorted(set(vs).intersection(set(vs2))) + + es = g.es.select(_from = vs) + self.assertEqual(8, len(es)) + self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) + self.assert_edges_unique_in(es) + + es_filtered = es.select(_to_in = vs2) + self.assertEqual(6, len(es_filtered)) + self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) + + es_filtered = es_filtered.select(_from_eq = 0) + self.assertEqual(2, len(es_filtered)) + self.assertTrue(all((e.source == 0 or e.target == 0) for e in es_filtered)) + self.assert_edges_unique_in(es_filtered) def testIndexOutOfBoundsSelect(self): g = Graph.Full(3) From 22860edb190133305e6a70aed4893efd43ee9794 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 10:31:11 +0100 Subject: [PATCH 0185/1892] added optimized code path for the common case of selecting edges based on source / target vertices in EdgeSeq, refs #270 --- src/igraph/__init__.py | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index ec69625aa..49168d7b5 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3918,7 +3918,8 @@ def select(self, *args, **kwds): >>> g.es["bs"] = g.edge_betweenness() >>> edges = g.es.select(bs_gt=10, bs_lt=30) - @return: the new, filtered edge sequence""" + @return: the new, filtered edge sequence + """ es = _igraph.EdgeSeq.select(self, *args) is_directed = self.graph.is_directed() @@ -3938,6 +3939,13 @@ def _ensure_set(value): "ne": operator.ne, \ "in": lambda a, b: a in b, \ "notin": lambda a, b: a not in b } + + # TODO(ntamas): some keyword arguments should be prioritized over + # others; for instance, we have optimized code paths for _source and + # _target in directed and undirected graphs if es.is_all() is True; + # these should be executed first. This matters only if there are + # multiple keyword arguments and es.is_all() is True. + for keyword, value in kwds.iteritems(): if "_" not in keyword or keyword.rindex("_") == 0: keyword = keyword + "_eq" @@ -3963,14 +3971,28 @@ def _ensure_set(value): value = set([value]) if attr in ("_source", "_from"): - values = [e.source for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="out")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.source for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) elif attr in ("_target", "_to"): - values = [e.target for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="in")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.target for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) elif attr == "_incident": func = None # ignoring function, filtering here From 2f242b68ef4f3ac3d3bd7c9cfc9b69c4c196d45a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 11:03:15 +0100 Subject: [PATCH 0186/1892] decouple version number of python-igraph from the version number of the C core --- setup.py | 7 ++++++- src/_igraph/igraphmodule.c | 2 +- src/igraph/__init__.py | 2 +- src/igraph/version.py | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 src/igraph/version.py diff --git a/setup.py b/setup.py index eec0c3077..ee27255b6 100644 --- a/setup.py +++ b/setup.py @@ -759,6 +759,11 @@ def use_educated_guess(self): ########################################################################### +# Import version number from version.py so we only need to change it in +# one place when a new release is created +__version__ = None +exec(open("src/igraph/version.py").read()) + # Process command line options buildcfg = BuildConfiguration() buildcfg.process_args_from_command_line() @@ -787,7 +792,7 @@ def use_educated_guess(self): options = dict( name="python-igraph", - version=VERSION, + version=__version__, url="http://pypi.python.org/pypi/python-igraph", description="High performance graph data structures and algorithms", long_description=description, diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index c4384d13e..05a0d16ec 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -844,7 +844,7 @@ extern PyObject* igraphmodule_arpack_options_default; { const char* version; igraph_version(&version, 0, 0, 0); - PyModule_AddStringConstant(m, "__version__", version); + PyModule_AddStringConstant(m, "__igraph_version__", version); } PyModule_AddStringConstant(m, "__build_date__", __DATE__); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 49168d7b5..4bd91e8e2 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -32,7 +32,6 @@ # pylint: disable-msg=W0401 # W0401: wildcard import from igraph._igraph import * -from igraph._igraph import __version__, __build_date__ from igraph.clustering import * from igraph.cut import * from igraph.configuration import Configuration @@ -45,6 +44,7 @@ from igraph.statistics import * from igraph.summary import * from igraph.utils import * +from igraph.version import __version__, __version_info__ import os import math diff --git a/src/igraph/version.py b/src/igraph/version.py new file mode 100644 index 000000000..4b41f137f --- /dev/null +++ b/src/igraph/version.py @@ -0,0 +1,2 @@ +__version_info__ = (0, 8, 0) +__version__ = ".".join("{0}".format(x) for x in __version_info__) From 37ddc95427d465dea8860e8d05aa7f7ba99b5330 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 11:15:32 +0100 Subject: [PATCH 0187/1892] Travis: trying to set up wheel deployment to Github Releases --- .travis.yml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5a020bcf..4b7bf6c92 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,14 +7,14 @@ python: - "3.6" - "3.7" - "3.8" - - "pypy3" + - pypy3 addons: apt: packages: - - gfortran - - flex - - bison + - gfortran + - flex + - bison install: - python -m pip install tox-travis @@ -51,3 +51,20 @@ notifications: email: on_success: change on_failure: always + +before_deploy: + - git config --local user.name "ntamas" + - git config --local user.email "ntamas@gmail.com" + - export TRAVIS_TAG=${TRAVIS_TAG:-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)} + - git tag $TRAVIS_TAG + +deploy: + provider: releases + api_key: + secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= + file: wheelhouse/*.whl + file_glob: true + draft: true + skip_cleanup: true + on: + repo: igraph/python-igraph From 89fdb2755e8fb3a0b26f4f486b33021b6b85c18f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 12:31:21 +0100 Subject: [PATCH 0188/1892] Travis: moved deployment to the wheels build phase --- .travis.yml | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4b7bf6c92..112827e95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,25 +46,23 @@ jobs: - python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse + before_deploy: + - git config --local user.name "ntamas" + - git config --local user.email "ntamas@gmail.com" + - export TRAVIS_TAG=0.8.0 + - git tag $TRAVIS_TAG + deploy: + provider: releases + api_key: + secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= + file: wheelhouse/*.whl + file_glob: true + draft: true + skip_cleanup: true + on: + repo: igraph/python-igraph notifications: email: on_success: change on_failure: always - -before_deploy: - - git config --local user.name "ntamas" - - git config --local user.email "ntamas@gmail.com" - - export TRAVIS_TAG=${TRAVIS_TAG:-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)} - - git tag $TRAVIS_TAG - -deploy: - provider: releases - api_key: - secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= - file: wheelhouse/*.whl - file_glob: true - draft: true - skip_cleanup: true - on: - repo: igraph/python-igraph From a909493a86962ba2d5e624f8c19f2cc8dffef237 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Feb 2020 13:15:13 +0100 Subject: [PATCH 0189/1892] Travis: switched to deployment v2 --- .travis.yml | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 112827e95..b88c95788 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ jobs: include: - stage: test services: docker + - stage: wheels services: docker language: shell @@ -36,32 +37,37 @@ jobs: - sudo python -m pip install cibuildwheel==1.1.0 script: - python -m cibuildwheel --output-dir wheelhouse - - stage: wheels - os: osx - language: shell - env: - - CIBW_BEFORE_BUILD="python setup.py build_c_core" - - CIBW_TEST_COMMAND="cd {project} && python -m unittest" - install: - - python -m pip install cibuildwheel==1.1.0 - script: - - python -m cibuildwheel --output-dir wheelhouse - before_deploy: + before_deploy: &before_deploy_releases - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - export TRAVIS_TAG=0.8.0 - git tag $TRAVIS_TAG - deploy: + deploy: &deploy_releases provider: releases - api_key: + token: secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= file: wheelhouse/*.whl file_glob: true draft: true - skip_cleanup: true + edge: true + overwrite: true + cleanup: false on: repo: igraph/python-igraph + - stage: wheels + os: osx + language: shell + env: + - CIBW_BEFORE_BUILD="python setup.py build_c_core" + - CIBW_TEST_COMMAND="cd {project} && python -m unittest" + install: + - python -m pip install cibuildwheel==1.1.0 + script: + - python -m cibuildwheel --output-dir wheelhouse + before_deploy: *before_deploy_releases + deploy: *deploy_releases + notifications: email: on_success: change From b58ea21aec5fe72b10120de960b4d3e795a48f36 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 19:35:00 +0100 Subject: [PATCH 0190/1892] fixed typos in tutorial, closes #276 --- doc/source/tutorial.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 3054662e6..7038ad846 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -140,7 +140,7 @@ exception: >>> g.add_edges((5, 0)) Traceback (most recent call last): File "", line 6, in -igraph.core.InternalError: Error at ../../src/type_indexededgelist.c:245: cannot add edges, invalid vertex id +TypeError: iterable must return pairs of integers or strings Most |igraph| functions will raise an :exc:`igraph.core.InternalError` if something goes wrong. The message corresponding to the exception gives you a @@ -152,9 +152,9 @@ but it is invaluable for |igraph| developers if you think you found an error in Let us go on with our graph ``g`` and add some more vertices and edges to it: ->>> g.add_edges((2,0)) +>>> g.add_edges([(2, 0)]) >>> g.add_vertices(3) ->>> g.add_edges([(2,3),(3,4),(4,5),(5,3)]) +>>> g.add_edges([(2, 3), (3, 4), (4, 5), (5, 3)]) >>> print(g) IGRAPH U---- 6 7 -- + edges: @@ -176,7 +176,7 @@ vertices at its two endpoints, you can use :meth:`~Graph.get_eid` to get the edge ID. Remember, all these are *methods* of the :class:`Graph` class and you must call them on the appropriate :class:`Graph` instance! ->>> g.get_eid(2,3) +>>> g.get_eid(2, 3) 3 >>> g.delete_edges(3) >>> summary(g) From e4bd79b922dbe0ee12c380226a0f613a246b6761 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 21:49:08 +0100 Subject: [PATCH 0191/1892] fixed styling of tutorial for the new homepage --- .../bootstrap-3.0.0/css/bootstrap.min.css | 2 - .../bootstrap-3.0.0/js/bootstrap.min.js | 2 - doc/source/_static/bootstrap-sphinx.js | 160 ------------------ doc/source/_templates/layout.html | 101 +++++++---- doc/source/conf.py | 19 ++- 5 files changed, 76 insertions(+), 208 deletions(-) delete mode 100644 doc/source/_static/bootstrap-3.0.0/css/bootstrap.min.css delete mode 100644 doc/source/_static/bootstrap-3.0.0/js/bootstrap.min.js delete mode 100644 doc/source/_static/bootstrap-sphinx.js diff --git a/doc/source/_static/bootstrap-3.0.0/css/bootstrap.min.css b/doc/source/_static/bootstrap-3.0.0/css/bootstrap.min.css deleted file mode 100644 index dd89b1155..000000000 --- a/doc/source/_static/bootstrap-3.0.0/css/bootstrap.min.css +++ /dev/null @@ -1,2 +0,0 @@ -/* disable the Bootstrap CSS shipped with sphinx_bootstrap_theme in order - * to use our own from http://igraph.org */ diff --git a/doc/source/_static/bootstrap-3.0.0/js/bootstrap.min.js b/doc/source/_static/bootstrap-3.0.0/js/bootstrap.min.js deleted file mode 100644 index bb1cac443..000000000 --- a/doc/source/_static/bootstrap-3.0.0/js/bootstrap.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* disable bootstrap.min.js coming from sphinx_bootstrap_theme in order to - * use our own from http://igraph.org */ diff --git a/doc/source/_static/bootstrap-sphinx.js b/doc/source/_static/bootstrap-sphinx.js deleted file mode 100644 index 30e5586d6..000000000 --- a/doc/source/_static/bootstrap-sphinx.js +++ /dev/null @@ -1,160 +0,0 @@ -(function ($) { - /** - * Patch TOC list. - * - * Will mutate the underlying span to have a correct ul for nav. - * - * @param $span: Span containing nested UL's to mutate. - * @param minLevel: Starting level for nested lists. (1: global, 2: local). - */ - var patchToc = function ($ul, minLevel) { - var findA, - patchTables, - $localLi; - - // Find all a "internal" tags, traversing recursively. - findA = function ($elem, level) { - level = level || 0; - var $items = $elem.find("> li > a.internal, > ul, > li > ul"); - - // Iterate everything in order. - $items.each(function (index, item) { - var $item = $(item), - tag = item.tagName.toLowerCase(), - $childrenLi = $item.children('li'), - $parentLi = $($item.parent('li'), $item.parent().parent('li')); - - // Add dropdowns if more children and above minimum level. - if (tag === 'ul' && level >= minLevel && $childrenLi.length > 0) { - $parentLi - .addClass('dropdown-submenu') - .children('a').first().attr('tabindex', -1); - - $item.addClass('dropdown-menu'); - } - - findA($item, level + 1); - }); - }; - - findA($ul); - }; - - /** - * Patch all tables to remove ``docutils`` class and add Bootstrap base - * ``table`` class. - */ - patchTables = function () { - $("table.docutils") - .removeClass("docutils") - .addClass("table") - .attr("border", 0); - }; - - $(window).load(function () { - /* - * Scroll the window to avoid the topnav bar - * https://github.com/twitter/bootstrap/issues/1768 - */ - if ($("#navbar.navbar-fixed-top").length > 0) { - var navHeight = $("#navbar").height(), - shiftWindow = function() { scrollBy(0, -navHeight - 10); }; - - if (location.hash) { - setTimeout(shiftWindow, 1); - } - - window.addEventListener("hashchange", shiftWindow); - } - }); - - $(document).ready(function () { - // Add styling, structure to TOC's. - $(".dropdown-menu").each(function () { - $(this).find("ul").each(function (index, item){ - var $item = $(item); - $item.addClass('unstyled'); - }); - }); - - // Global TOC. - if ($("ul.globaltoc li").length) { - patchToc($("ul.globaltoc"), 1); - } else { - // Remove Global TOC. - $(".globaltoc-container").remove(); - } - - // Local TOC. - $(".bs-sidenav ul").addClass("nav nav-list"); - $(".bs-sidenav > ul > li > a").addClass("nav-header"); - - // back to top - setTimeout(function () { - var $sideBar = $('.bs-sidenav'); - if (!$sideBar || !$sideBar.length) - return; - - $sideBar.affix({ - offset: { - top: function () { - var offsetTop = $sideBar.offset().top; - var sideBarMargin = parseInt($sideBar.children(0).css('margin-top'), 10); - var navOuterHeight = $('#navbar').height(); - - return (this.top = offsetTop - navOuterHeight - sideBarMargin); - } - , bottom: function () { - // add 25 because the footer height doesn't seem to be enough - return (this.bottom = $('.footer').outerHeight(true) + 25); - } - } - }); - }, 100); - - // Local TOC. - patchToc($("ul.localtoc"), 2); - - // Mutate sub-lists (for bs-2.3.0). - $(".dropdown-menu ul").not(".dropdown-menu").each(function () { - var $ul = $(this), - $parent = $ul.parent(), - tag = $parent[0].tagName.toLowerCase(), - $kids = $ul.children().detach(); - - // Replace list with items if submenu header. - if (tag === "ul") { - $ul.replaceWith($kids); - } else if (tag === "li") { - // Insert into previous list. - $parent.after($kids); - $ul.remove(); - } - }); - - // Add divider in page TOC. - $localLi = $("ul.localtoc li"); - if ($localLi.length > 2) { - $localLi.first().after('
  • '); - } - - // Enable dropdown. - // $('.dropdown-toggle').dropdown(); - - // Patch tables. - patchTables(); - - // Add Note, Warning styles. (BS v2,3 compatible). - $('div.note').addClass('alert alert-info'); - $('div.warning').addClass('alert alert-danger alert-error'); - - // Inline code styles to Bootstrap style. - $('tt.docutils.literal').not(".xref").each(function (i, e) { - // ignore references - if (!$(e).parent().hasClass("reference")) { - $(e).replaceWith(function () { - return $("").text($(this).text()); - }); - }}); - }); -}($jqTheme || window.jQuery)); diff --git a/doc/source/_templates/layout.html b/doc/source/_templates/layout.html index d89ffba57..2f79322a1 100644 --- a/doc/source/_templates/layout.html +++ b/doc/source/_templates/layout.html @@ -20,52 +20,83 @@ {%- endblock %} - -extrafoot: - - + --- -{# Sidebar: Rework into our Bootstrap nav section. #} +{% set css_files = css_files + [ + '_static/bootstrap-4.3.1-dist/css/bootstrap.min.css', + '_static/sphinxbootstrap4.css' +] %} + +{% set script_files = script_files + [ + '_static/bootstrap-4.3.1-dist/js/bootstrap.min.js', + '_static/sphinxbootstrap4.js' + ] +%} + +{%- macro sphinxsidebar() %} +
    + {%- block sidebarlogo %}{%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "globaltoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- endif %} +
    +{%- endmacro %} + {% macro navBar() %} {% include "navbar.html" %} {% endmacro %} -{# Update the content width and offset #} -{% set bs_content_width_real = "9" %} -{% set bs_content_offset = "1" %} +{% macro breadcrumb() %} +{% include "breadcrumb.html" %} +{% endmacro %} + +{%- block relbar1 %}{% endblock %} +{%- block relbar2 %}{% endblock %} + +{%- block header %}{%- endblock %} -{# Tweak the main documentation area #} {%- block content %} -
    -
    -
    - {{ navBar() }} -
    -
    -
    -
    -
    - {% block body %}{% endblock %} +
    + {%- block breadcrumb1 %}{{breadcrumb()}}{% endblock %} +
    +
    + {%- block document %} +
    +

    + {{ title }} + +

    + {{ toc }} + {% block body %} {% endblock %}
    + {%- endblock %} +
    +
    -
    - {%- endblock %} -{# Modified basic/layout.html #} +{%- block footer %} +{%- endblock %} -{%- block doctype -%}{%- endblock %} -{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} -{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} -{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and - (sidebars != []) %} -{%- set url_root = pathto('', 1) %} -{# XXX necessary? #} -{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} -{%- if not embedded and docstitle %} - {%- set titlesuffix = " — "|safe + docstitle|e %} -{%- else %} - {%- set titlesuffix = "" %} -{%- endif %} diff --git a/doc/source/conf.py b/doc/source/conf.py index c8182b7c4..38dd8e61a 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -11,8 +11,10 @@ # All configuration values have a default; values that are commented out # serve to show the default. +from datetime import datetime + import sys, os -import sphinx_bootstrap_theme +import sphinxbootstrap4theme # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -42,16 +44,16 @@ # General information about the project. project = u'python-igraph' -copyright = u'2010-2013, Tamás Nepusz, Gábor Csárdi' +copyright = u'2010-{0}, Tamás Nepusz, Gábor Csárdi'.format(datetime.now().year) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.7' +version = '0.8.0' # The full version, including alpha/beta/rc tags. -release = '0.7' +release = '0.8.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -92,19 +94,18 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'bootstrap' +html_theme = 'sphinxbootstrap4theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { - "navbar_fixed_top": "false", - "navbar_class": "navbar navbar-inverse", - "bootstrap_version": "3" + "navbar_style": "full", + "navbar_color_class": "dark" } # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() +html_theme_path = [sphinxbootstrap4theme.get_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". From d7f2dfcd38286e0be7328982fbd77d53ac966269 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 21:50:33 +0100 Subject: [PATCH 0192/1892] extensions to the previous commit [ci skip] --- doc/source/_static/other.css | 20 +++++ doc/source/_templates/breadcrumb.html | 48 ++++++++++++ doc/source/_templates/globaltoc.html | 5 ++ doc/source/_templates/layout.html | 101 +++++++++----------------- 4 files changed, 108 insertions(+), 66 deletions(-) create mode 100644 doc/source/_static/other.css create mode 100644 doc/source/_templates/breadcrumb.html create mode 100644 doc/source/_templates/globaltoc.html diff --git a/doc/source/_static/other.css b/doc/source/_static/other.css new file mode 100644 index 000000000..e95a78da4 --- /dev/null +++ b/doc/source/_static/other.css @@ -0,0 +1,20 @@ +.highlight { + border-radius: 8px; +} + +.highlight pre { + padding: 8px; +} + +.navigation-header { + text-align: center; +} + +.bs-docs-section h1 { + display: none; +} + +.bs-docs-section h1.real { + display: block; +} + diff --git a/doc/source/_templates/breadcrumb.html b/doc/source/_templates/breadcrumb.html new file mode 100644 index 000000000..a1d22f0be --- /dev/null +++ b/doc/source/_templates/breadcrumb.html @@ -0,0 +1,48 @@ +{%- if 0 %} +
    + +
    +{%- endif %} + + + diff --git a/doc/source/_templates/globaltoc.html b/doc/source/_templates/globaltoc.html new file mode 100644 index 000000000..e4b606d52 --- /dev/null +++ b/doc/source/_templates/globaltoc.html @@ -0,0 +1,5 @@ +{% block menu %} + +{% endblock %} diff --git a/doc/source/_templates/layout.html b/doc/source/_templates/layout.html index 2f79322a1..d89ffba57 100644 --- a/doc/source/_templates/layout.html +++ b/doc/source/_templates/layout.html @@ -20,83 +20,52 @@ {%- endblock %} - + +extrafoot: + + --- -{% set css_files = css_files + [ - '_static/bootstrap-4.3.1-dist/css/bootstrap.min.css', - '_static/sphinxbootstrap4.css' -] %} - -{% set script_files = script_files + [ - '_static/bootstrap-4.3.1-dist/js/bootstrap.min.js', - '_static/sphinxbootstrap4.js' - ] -%} - -{%- macro sphinxsidebar() %} -
    - {%- block sidebarlogo %}{%- endblock %} - {%- if sidebars != None %} - {#- new style sidebar: explicitly include/exclude templates #} - {%- for sidebartemplate in sidebars %} - {%- include sidebartemplate %} - {%- endfor %} - {%- else %} - {#- old style sidebars: using blocks -- should be deprecated #} - {%- block sidebartoc %} - {%- include "globaltoc.html" %} - {%- endblock %} - {%- block sidebarrel %} - {%- include "relations.html" %} - {%- endblock %} - {%- if customsidebar %} - {%- include customsidebar %} - {%- endif %} - {%- block sidebarsearch %} - {%- include "searchbox.html" %} - {%- endblock %} - {%- block sidebarsourcelink %} - {%- include "sourcelink.html" %} - {%- endblock %} - {%- endif %} -
    -{%- endmacro %} - +{# Sidebar: Rework into our Bootstrap nav section. #} {% macro navBar() %} {% include "navbar.html" %} {% endmacro %} -{% macro breadcrumb() %} -{% include "breadcrumb.html" %} -{% endmacro %} - -{%- block relbar1 %}{% endblock %} -{%- block relbar2 %}{% endblock %} - -{%- block header %}{%- endblock %} +{# Update the content width and offset #} +{% set bs_content_width_real = "9" %} +{% set bs_content_offset = "1" %} +{# Tweak the main documentation area #} {%- block content %} -
    - {%- block breadcrumb1 %}{{breadcrumb()}}{% endblock %} -
    -
    - {%- block document %} -
    -

    - {{ title }} - -

    - {{ toc }} - {% block body %} {% endblock %} -
    - {%- endblock %} +
    +
    +
    + {{ navBar() }}
    -
    +
    +
    +
    +
    + {% block body %}{% endblock %} +
    -{%- endblock %} +
    -{%- block footer %} {%- endblock %} +{# Modified basic/layout.html #} + +{%- block doctype -%}{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} From 2c7fd7d86217daffb13f16cf6557ab70f17b6623 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 22:10:21 +0100 Subject: [PATCH 0193/1892] extensions to the previous commit [ci skip] --- doc/source/_templates/layout.html | 101 +++++++++++++++++++----------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/doc/source/_templates/layout.html b/doc/source/_templates/layout.html index d89ffba57..2f79322a1 100644 --- a/doc/source/_templates/layout.html +++ b/doc/source/_templates/layout.html @@ -20,52 +20,83 @@ {%- endblock %} - -extrafoot: - - + --- -{# Sidebar: Rework into our Bootstrap nav section. #} +{% set css_files = css_files + [ + '_static/bootstrap-4.3.1-dist/css/bootstrap.min.css', + '_static/sphinxbootstrap4.css' +] %} + +{% set script_files = script_files + [ + '_static/bootstrap-4.3.1-dist/js/bootstrap.min.js', + '_static/sphinxbootstrap4.js' + ] +%} + +{%- macro sphinxsidebar() %} +
    + {%- block sidebarlogo %}{%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "globaltoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- endif %} +
    +{%- endmacro %} + {% macro navBar() %} {% include "navbar.html" %} {% endmacro %} -{# Update the content width and offset #} -{% set bs_content_width_real = "9" %} -{% set bs_content_offset = "1" %} +{% macro breadcrumb() %} +{% include "breadcrumb.html" %} +{% endmacro %} + +{%- block relbar1 %}{% endblock %} +{%- block relbar2 %}{% endblock %} + +{%- block header %}{%- endblock %} -{# Tweak the main documentation area #} {%- block content %} -
    -
    -
    - {{ navBar() }} -
    -
    -
    -
    -
    - {% block body %}{% endblock %} +
    + {%- block breadcrumb1 %}{{breadcrumb()}}{% endblock %} +
    +
    + {%- block document %} +
    +

    + {{ title }} + +

    + {{ toc }} + {% block body %} {% endblock %}
    + {%- endblock %} +
    +
    -
    - {%- endblock %} -{# Modified basic/layout.html #} +{%- block footer %} +{%- endblock %} -{%- block doctype -%}{%- endblock %} -{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} -{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} -{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and - (sidebars != []) %} -{%- set url_root = pathto('', 1) %} -{# XXX necessary? #} -{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} -{%- if not embedded and docstitle %} - {%- set titlesuffix = " — "|safe + docstitle|e %} -{%- else %} - {%- set titlesuffix = "" %} -{%- endif %} From b38b5dc4ac42df0db1c5b5e56a0e29175f4fa40f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 22:28:33 +0100 Subject: [PATCH 0194/1892] removed mention of mailing list from tutorial --- doc/source/tutorial.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 7038ad846..63f75a580 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -1041,9 +1041,10 @@ long-term plans are to extend this tutorial into a proper manual-style documentation to |igraph| in the next chapters. In the meanwhile, check out the full `API documentation`_ which should provide information about almost every |igraph| class, function or method. A good starting point is the documentation -of the `Graph class`_. Should you get stuck, drop a mail to the `igraph mailing -list`_ - maybe there is someone out there who can help you out immediately. +of the `Graph class`_. Should you get stuck, try asking in our +`Discourse group`_ first - maybe there is someone out there who can help you +out immediately. -.. _API documentation: http://igraph.org/python/doc/igraph-module.html -.. _Graph class: http://igraph.org/python/doc/igraph.Graph-class.html -.. _igraph mailing list: http://lists.nongnu.org/mailman/listinfo/igraph-help +.. _API documentation: https://igraph.org/python/doc/igraph-module.html +.. _Graph class: https://igraph.org/python/doc/igraph.Graph-class.html +.. _Discourse group: https://igraph.discourse.group From 7a0554fc3dda6217ed34306b88c151fb80428bb7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Feb 2020 22:35:20 +0100 Subject: [PATCH 0195/1892] Travis: don't draft releases unless the commit is tagged --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b88c95788..a05502118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,8 @@ jobs: before_deploy: &before_deploy_releases - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - - export TRAVIS_TAG=0.8.0 - - git tag $TRAVIS_TAG + # - export TRAVIS_TAG=0.8.0 + # - git tag $TRAVIS_TAG deploy: &deploy_releases provider: releases token: @@ -54,12 +54,13 @@ jobs: cleanup: false on: repo: igraph/python-igraph + tags: true - stage: wheels os: osx language: shell env: - - CIBW_BEFORE_BUILD="python setup.py build_c_core" + - CIBW_BEFORE_BUILD="python setup.py sdist && python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - python -m pip install cibuildwheel==1.1.0 From 07fdef5876d521b949c8e2f0ef5b1a3d25c32911 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Wed, 5 Feb 2020 23:41:35 +0100 Subject: [PATCH 0196/1892] Implementation of Leiden algorithm (#273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Leiden algorithm in Graph interface. * Added leiden algorithm also to public interface of graph object. * Changed the way to normalize the resolution parameter. * Now also creating node_weights internally when normalizing resolution. * Made minor corrections, added test. * Changed constant to string, made test deterministic. * Graph.community_leiden(): make objective_function argument case insensitive Co-authored-by: Tamás Nepusz --- src/_igraph/graphobject.c | 157 ++++++++++++++++++++++++++++++++++++ src/_igraph/graphobject.h | 1 + src/igraph/__init__.py | 50 ++++++++++++ tests/test_decomposition.py | 38 +++++++++ 4 files changed, 246 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 96c75d10e..bb3edd5ab 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11745,6 +11745,135 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, return res; } +/** + * Leiden community detection method of Traag, Waltman & van Eck + */ +PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, + PyObject *args, PyObject *kwds) { + + static char *kwlist[] = {"edge_weights", "node_weights", "resolution_parameter", + "normalize_resolution", "beta", "initial_membership", "n_iterations", NULL}; + + PyObject *edge_weights_o = Py_None; + PyObject *node_weights_o = Py_None; + PyObject *initial_membership_o = Py_None; + PyObject *res; + + int error = 0, i; + long int n_iterations = 2; + double resolution_parameter = 1.0; + double beta = 0.01; + igraph_vector_t *edge_weights = NULL, *node_weights = NULL, *membership; + igraph_bool_t start = 1; + igraph_bool_t normalize_resolution = 0; + igraph_integer_t nb_clusters = 0; + igraph_real_t quality = 0.0, prev_quality = -IGRAPH_INFINITY; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdidOl", kwlist, + &edge_weights_o, &node_weights_o, &resolution_parameter, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) + return NULL; + + /* Get edge weights */ + if (igraphmodule_attrib_to_vector_t(edge_weights_o, self, &edge_weights, + ATTRIBUTE_TYPE_EDGE)) { + igraphmodule_handle_igraph_error(); + error = -1; + } + + /* Get node weights */ + if (!error && igraphmodule_attrib_to_vector_t(node_weights_o, self, &node_weights, + ATTRIBUTE_TYPE_VERTEX)) { + igraphmodule_handle_igraph_error(); + error = -1; + } + + /* Get initial membership */ + if (!error && igraphmodule_attrib_to_vector_t(initial_membership_o, self, &membership, + ATTRIBUTE_TYPE_VERTEX)) { + igraphmodule_handle_igraph_error(); + error = -1; + } + + if (!error && membership == 0) { + start = 0; + membership = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); + if (membership==0) { + PyErr_NoMemory(); + error = -1; + } else { + igraph_vector_init(membership, 0); + } + } + + if (normalize_resolution) + { + /* If we need to normalize the resolution parameter, + * we will need to have node weights. */ + if (node_weights == 0) + { + node_weights = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); + if (node_weights==0) { + PyErr_NoMemory(); + error = -1; + } else { + igraph_vector_init(node_weights, 0); + if (igraph_strength(&self->g, node_weights, igraph_vss_all(), IGRAPH_ALL, 0, edge_weights)) { + igraphmodule_handle_igraph_error(); + error = -1; + } + } + } + resolution_parameter /= igraph_vector_sum(node_weights); + } + + /* Run actual Leiden algorithm for several iterations. */ + if (!error) { + if (n_iterations > 0) { + for (i = 0; !error && i < n_iterations; i++) { + error = igraph_community_leiden(&self->g, + edge_weights, node_weights, + resolution_parameter, beta, + start, membership, + &nb_clusters, &quality); + start = 1; + } + } else { + while (!error && prev_quality < quality) { + error = igraph_community_leiden(&self->g, + edge_weights, node_weights, + resolution_parameter, beta, + start, membership, + &nb_clusters, &quality); + start = 1; + prev_quality = quality; + } + } + } + + if (edge_weights != 0) { + igraph_vector_destroy(edge_weights); + free(edge_weights); + } + if (node_weights != 0) { + igraph_vector_destroy(node_weights); + free(node_weights); + } + + if (!error) { + res = igraphmodule_vector_t_to_PyList(membership, IGRAPHMODULE_TYPE_INT); + } + + if (membership != 0) { + igraph_vector_destroy(membership); + free(membership); + } + + if (!error) + { return res; } + else + { return NULL; } +} + /********************************************************************** * Random walks * **********************************************************************/ @@ -15699,6 +15828,34 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " original implementation is used.\n" "@return: the community membership vector.\n" }, + {"community_leiden", + (PyCFunction) igraphmodule_Graph_community_leiden, + METH_VARARGS | METH_KEYWORDS, + "community_leiden(edge_weights=None, node_weights=None, \n" + " resolution_parameter=1.0, normalize_resolution=False, beta=0.01, \n" + " initial_membership=None, n_iterations=2)\n\n" + " Finds the community structure of the graph using the\n" + " Leiden algorithm of Traag, van Eck & Waltman \n\n" + " @param edge_weights: edge weights to be used. Can be a sequence or\n" + " iterable or even an edge attribute name.\n" + " @param node_weights: the node weights used in the Leiden algorithm.\n" + " @param resolution_parameter: the resolution parameter to use.\n" + " Higher resolutions lead to more smaller communities, while \n" + " lower resolutions lead to fewer larger communities.\n" + " @param normalize_resolution: if set to true, the resolution parameter\n" + " will be divided by the sum of the node weights. If this is not\n" + " supplied, it will default to the node degree, or weighted degree\n" + " in case edge_weights are supplied.\n" + " @param node_weights: the node weights used in the Leiden algorithm.\n" + " @param beta: parameter affecting the randomness in the Leiden \n" + " algorithm. This affects only the refinement step of the algorithm.\n" + " @param initial_membership: if provided, the Leiden algorithm\n" + " will try to improve this provided membership. If no argument is\n" + " provided, the aglorithm simply starts from the singleton partition.\n" + " @param n_iterations: the number of iterations to iterate the Leiden\n" + " algorithm. Each iteration may improve the partition further.\n" + " @return: the community membership vector.\n" + }, {"community_walktrap", (PyCFunction) igraphmodule_Graph_community_walktrap, METH_VARARGS | METH_KEYWORDS, diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 0dcfd7ac4..5c87becd6 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -221,6 +221,7 @@ PyObject *igraphmodule_Graph_community_optimal_modularity(igraphmodule_GraphObje PyObject* igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_modularity(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); +PyObject* igraphmodule_Graph_leiden(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 4bd91e8e2..418d5e60b 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1420,6 +1420,56 @@ def k_core(self, *args): if return_single: return result[0] return result + def community_leiden(self, objective_function="CPM", weights=None, + resolution_parameter=1.0, beta=0.01, initial_membership=None, + n_iterations=2, node_weights=None): + """community_leiden(objective_function=CPM, weights=None, + resolution_parameter=1.0, beta=0.01, initial_membership=None, + n_iterations=2, node_weights=None) + + Finds the community structure of the graph using the + Leiden algorithm of Traag, van Eck & Waltman. + + @keyword objective_function: whether to use the Constant Potts + Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. + @keyword weights: edge weights to be used. Can be a sequence or + iterable or even an edge attribute name. + @keyword resolution_parameter: the resolution parameter to use. + Higher resolutions lead to more smaller communities, while + lower resolutions lead to fewer larger communities. + @keyword beta: parameter affecting the randomness in the Leiden + algorithm. This affects only the refinement step of the algorithm. + @keyword initial_membership: if provided, the Leiden algorithm + will try to improve this provided membership. If no argument is + provided, the aglorithm simply starts from the singleton partition. + @keyword n_iterations: the number of iterations to iterate the Leiden + algorithm. Each iteration may improve the partition further. + @keyword node_weights: the node weights used in the Leiden algorithm. + If this is not provided, it will be automatically determined on the + basis of whether you want to use CPM or modularity. If you do provide + this, please make sure that you understand what you are doing. + @return: an appropriate L{VertexClustering} object. + + @newfield ref: Reference + @ref: Traag, V. A., Waltman, L., & van Eck, N. J. (2019). From Louvain + to Leiden: guaranteeing well-connected communities. Scientific + reports, 9(1), 5233. doi: 10.1038/s41598-019-41695-z + """ + if objective_function.lower() not in ("cpm", "modularity"): + raise ValueError("objective_function must be \"CPM\" or \"modularity\".") + + membership = GraphBase.community_leiden(self, + edge_weights=weights, node_weights=node_weights, + resolution_parameter=resolution_parameter, + normalize_resolution=(objective_function == "modularity"), + beta=beta, initial_membership=initial_membership, n_iterations=n_iterations) + + if weights is not None: + modularity_params=dict(weights=weights) + else: + modularity_params={} + return VertexClustering(self, membership, + modularity_params=modularity_params) def layout(self, layout=None, *args, **kwds): """Returns the layout of the graph according to a layout algorithm. diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 90b8341b9..1f48c2f09 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -312,6 +312,44 @@ def testWalktrap(self): cl = g.community_walktrap(steps=3).as_clustering() self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2]) + def testLeiden(self): + + # Example from paper (Fig. C.1) + high_weight = 3.0 + low_weight = 3.0/2.0 + edges = [(0, 1, high_weight), + (2, 3, high_weight), + (4, 2, high_weight), + (3, 4, high_weight), + (5, 6, high_weight), + (7, 5, high_weight), + (6, 7, high_weight), + (0, 2, low_weight), + (0, 3, low_weight), + (0, 4, low_weight), + (1, 5, low_weight), + (1, 6, low_weight), + (1, 7, low_weight)] + G = Graph.TupleList(edges, weights=True) + + import random + random.seed(0) + set_random_number_generator(random) + # We don't find the optimal partition if we are greedy + cl = G.community_leiden("CPM", resolution_parameter=1, weights='weight', + beta=0, n_iterations=-1) + self.assertMembershipsEqual(cl, [0, 0, 1, 1, 1, 2, 2, 2]) + + random.seed(0) + set_random_number_generator(random) + # We can find the optimal partition if we allow for non-decreasing moves + # (The randomness is only present in the refinement, which is why we + # start from all nodes in the same community: this should then be + # refined). + cl = G.community_leiden("CPM", resolution_parameter=1, weights='weight', + beta=5, n_iterations=-1, + initial_membership=[0]*G.vcount()) + self.assertMembershipsEqual(cl, [0, 1, 0, 0, 0, 1, 1, 1]) class CohesiveBlocksTests(unittest.TestCase): def genericTests(self, cbs): From 7a4571cd8076d49b3cd0a79f0b509104a187e097 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 6 Feb 2020 12:05:43 +0100 Subject: [PATCH 0197/1892] Travis: moved creation of source dist to the Linux job --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a05502118..2f59dab76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ jobs: install: - sudo python -m pip install cibuildwheel==1.1.0 script: + - python setup.py sdist - python -m cibuildwheel --output-dir wheelhouse before_deploy: &before_deploy_releases - git config --local user.name "ntamas" @@ -60,7 +61,7 @@ jobs: os: osx language: shell env: - - CIBW_BEFORE_BUILD="python setup.py sdist && python setup.py build_c_core" + - CIBW_BEFORE_BUILD="python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - python -m pip install cibuildwheel==1.1.0 From 35add97ef7e9d2c3a779b8de89634edb9d46a40f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 7 Feb 2020 16:06:16 +0100 Subject: [PATCH 0198/1892] Travis: trying to ensure that the source distribution is also published with a release --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f59dab76..78ae070d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,13 +41,15 @@ jobs: before_deploy: &before_deploy_releases - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - # - export TRAVIS_TAG=0.8.0 - # - git tag $TRAVIS_TAG + - export TRAVIS_TAG=0.8.0 + - git tag $TRAVIS_TAG deploy: &deploy_releases provider: releases token: secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= - file: wheelhouse/*.whl + file: + - wheelhouse/*.whl + - dist/python-igraph-${TRAVIS_TAG}.tar.gz file_glob: true draft: true edge: true From 78abcc99bb8d6a8a1c600807dd7604c867700b25 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 7 Feb 2020 18:12:07 +0100 Subject: [PATCH 0199/1892] Travis: temporarily turn off tagged requirement --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 78ae070d2..7cafb44dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ jobs: cleanup: false on: repo: igraph/python-igraph - tags: true - stage: wheels os: osx From 743bd2748e691aa644527bff4f45bf8cca8989c6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 8 Feb 2020 00:59:11 +0100 Subject: [PATCH 0200/1892] reverted Travis settings; preparing for 0.8.0 release --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7cafb44dc..cf3a43bd0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,8 +41,8 @@ jobs: before_deploy: &before_deploy_releases - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - - export TRAVIS_TAG=0.8.0 - - git tag $TRAVIS_TAG + # - export TRAVIS_TAG=0.8.0 + # - git tag $TRAVIS_TAG deploy: &deploy_releases provider: releases token: @@ -57,6 +57,7 @@ jobs: cleanup: false on: repo: igraph/python-igraph + tags: true - stage: wheels os: osx From 7d344d4a2e4b3d590e4fa9f7d849af7a5e236b1b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 8 Feb 2020 09:32:11 +0100 Subject: [PATCH 0201/1892] removed unused VERSION constant from setup.py --- setup.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.py b/setup.py index ee27255b6..a5f16b500 100644 --- a/setup.py +++ b/setup.py @@ -6,9 +6,6 @@ ########################################################################### -# Global version number. Keep the format of the next line intact. -VERSION = "0.7.1.post6" - # Check Python's version info and exit early if it is too old if sys.version_info < (2, 7): print("This module requires Python >= 2.7") From 9adcf876baa17fedad1017239925a056839d6626 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Feb 2020 20:44:28 +0100 Subject: [PATCH 0202/1892] update homepage [ci skip] --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a5f16b500..983fe74cf 100644 --- a/setup.py +++ b/setup.py @@ -790,7 +790,7 @@ def use_educated_guess(self): options = dict( name="python-igraph", version=__version__, - url="http://pypi.python.org/pypi/python-igraph", + url="https://igraph.org/python", description="High performance graph data structures and algorithms", long_description=description, license="GNU General Public License (GPL)", From 69291f4ee687bbd02dc51f189339db195a45809d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Feb 2020 20:45:25 +0100 Subject: [PATCH 0203/1892] removed reference to Christoph Gohlke's page (thanks a lot!) because we build our own wheels now [ci skip] --- setup.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/setup.py b/setup.py index 983fe74cf..5e6f87882 100644 --- a/setup.py +++ b/setup.py @@ -779,10 +779,6 @@ def use_educated_guess(self): ``cairocffi`` is recommended, in particular if you are on Python 3.x because there were bug reports affecting igraph graph plots in Jupyter notebooks when using ``pycairo`` (but not with ``cairocffi``). - -Unofficial installers for 64-bit Windows machines and/or different Python -versions can also be found `here `_. -Many thanks to the maintainers of this page! """ headers = ["src/_igraph/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] From f2f88ac93d2e46c208ffcb09c5863ccc5d4e8548 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Feb 2020 14:01:23 +0100 Subject: [PATCH 0204/1892] make sure that vendor/igraph/source/msvc/ is in the source tarball, closes #280 --- MANIFEST.in | 1 - 1 file changed, 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 23313f559..2278efcb5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -12,7 +12,6 @@ prune vendor/source/igraph/doc/abstracts prune vendor/source/igraph/doc/papers prune vendor/source/igraph/doc/presentations prune vendor/source/igraph/interfaces -prune vendor/source/igraph/msvc prune vendor/source/igraph/nexus prune vendor/source/igraph/tools/virtual prune vendor/source/igraph/optional/simpleraytracer From 318bda1b1384489f33fec995c8c5d726a4912080 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 2 Mar 2020 11:23:33 +0100 Subject: [PATCH 0205/1892] added 'plotting' extra in setup.py --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index 5e6f87882..29482e21d 100644 --- a/setup.py +++ b/setup.py @@ -802,6 +802,9 @@ def use_educated_guess(self): ], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], + extras_require={ + "plotting": ["pycairo>=1.18.0"] + }, headers=headers, platforms="ALL", keywords=[ From eb903e33676a1f667c892a736b6fcd7f8a41af06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Thu, 5 Mar 2020 07:59:51 +0100 Subject: [PATCH 0206/1892] Sparse adjacency fix (#285) * Fix get_sparse_adjacency * Add scipy dependency for sparse conversion test * Try tox for dependencies instread of travis * Make tox deps multiline * Skip scipy test if scipy isn't installed * Update test skipping message * Don't install scipy for pypy builds --- src/igraph/__init__.py | 11 +++++------ tests/test_conversion.py | 24 ++++++++++++++++++++++++ tox.ini | 2 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 418d5e60b..f8db38ef8 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -601,9 +601,10 @@ def get_adjacency_sparse(self, attribute=None): given attribute where there is an edge. @return: the adjacency matrix as a L{scipy.sparse.csr_matrix}.""" try: - from scipy.sparse import csr_matrix + from scipy import sparse except ImportError: raise ImportError('You should install scipy package in order to use this function') + import numpy as np edges = self.get_edgelist() if attribute is None: @@ -615,13 +616,11 @@ def get_adjacency_sparse(self, attribute=None): weights = self.es[attribute] N = self.vcount() - sparse_matrix = csr_matrix((weights, zip(*edges)), shape=(N, N)) + mtx = sparse.csr_matrix((weights, zip(*edges)), shape=(N, N)) if not self.is_directed(): - sparse_matrix = sparse_matrix + sparse_matrix.T - di = np.diag_indices(len(edges)) - sparse_matrix[di] /= 2 - return sparse_matrix + mtx = mtx + sparse.triu(mtx, 1).T + sparse.tril(mtx, -1).T + return mtx def get_adjlist(self, mode=OUT): """get_adjlist(mode=OUT) diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 1a4601d00..8a00cbe09 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -86,6 +86,30 @@ def testGetAdjacency(self): [0, 0, 0, 0, 0, 0] ])) + def testGetSparseAdjacency(self): + try: + from scipy import sparse + import numpy as np + except ImportError: + self.skipTest("Scipy and numpy are dependencies of this test.") + + # Undirected case + g = Graph.Tree(6, 3) + g.es["weight"] = range(5) + self.assertTrue(np.all( + (g.get_adjacency_sparse() == np.array(g.get_adjacency().data)) + )) + self.assertTrue(np.all( + (g.get_adjacency_sparse(attribute="weight") == np.array(g.get_adjacency(attribute="weight").data)) + )) + + # Directed case + g = Graph.Tree(6, 3, "tree_out") + g.add_edges([(0,1), (1,0)]) + self.assertTrue(np.all( + g.get_adjacency_sparse() == np.array(g.get_adjacency().data) + )) + def suite(): direction_suite = unittest.makeSuite(DirectedUndirectedTests) diff --git a/tox.ini b/tox.ini index 42c0c0436..37d5c3e86 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,8 @@ envlist = py27, py35, py36, py37, pypy, pypy3 [testenv] commands = python -m unittest deps = + scipy; platform_python_implementation != "PyPy" + numpy; platform_python_implementation != "PyPy" setenv = TESTING_IN_TOX=1 From 554c7d9534c2669c7ff48f13041a4bc1c5f86edd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 9 Mar 2020 15:04:15 +0100 Subject: [PATCH 0207/1892] bumed to head revision of igraph/igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 8183bca22..5b3f8e0aa 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 8183bca22070654136c58189681ce4319be96cf2 +Subproject commit 5b3f8e0aa183edf8391b381028f976bbcb359e84 From d32e46cba2c4656c6e669da7419fa22a307a82b9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 12 Mar 2020 13:10:01 +0100 Subject: [PATCH 0208/1892] bumed vendor/source/igraph to head revision --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 5b3f8e0aa..48b1c706b 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 5b3f8e0aa183edf8391b381028f976bbcb359e84 +Subproject commit 48b1c706b4364c40678a3e01fde1766380dcfabd From 0e32e1f0879f435ccc0b264f7bad0706fbffb91b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 24 Mar 2020 16:00:07 +0100 Subject: [PATCH 0209/1892] fix indexing with numpy.int64, closes #288 --- src/_igraph/edgeseqobject.c | 47 ++++++------ src/_igraph/vertexseqobject.c | 41 ++++++----- tests/test_edgeseq.py | 130 +++++++++++++++++++--------------- tests/test_vertexseq.py | 122 +++++++++++++++++-------------- 4 files changed, 186 insertions(+), 154 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index deeaef86f..ee202203e 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -1,23 +1,23 @@ /* -*- mode: C -*- */ /* vim: set ts=2 sts=2 sw=2 et: */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -49,7 +49,7 @@ PyTypeObject igraphmodule_EdgeSeqType; PyObject* igraphmodule_EdgeSeq_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) { igraphmodule_EdgeSeqObject* o; - + o=(igraphmodule_EdgeSeqObject*)PyType_GenericNew(subtype, args, kwds); if (o == NULL) return NULL; @@ -58,7 +58,7 @@ PyObject* igraphmodule_EdgeSeq_new(PyTypeObject *subtype, o->weakreflist=0; RC_ALLOC("EdgeSeq", o); - + return (PyObject*)o; } @@ -73,7 +73,7 @@ igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { copy=(igraphmodule_EdgeSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0); if (copy == NULL) return NULL; - + if (igraph_es_type(&o->es) == IGRAPH_ES_VECTOR) { igraph_vector_t v; if (igraph_vector_copy(&v, o->es.data.vecptr)) { @@ -191,7 +191,7 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, Py_ssize_t i) { igraph_t *g; igraph_integer_t idx = -1; - + if (!self->gref) return NULL; g=&GET_GRAPH(self); switch (igraph_es_type(&self->es)) { @@ -358,7 +358,7 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject igraphmodule_GraphObject *gr; igraph_vector_t es; long i, j, n, no_of_edges; - + gr = self->gref; dict = ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE]; @@ -407,7 +407,7 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject if (PyList_SetItem(list, i, item)) { Py_DECREF(item); return -1; - } /* PyList_SetItem stole a reference to the item automatically */ + } /* PyList_SetItem stole a reference to the item automatically */ } } else if (values != 0) { /* We don't have attributes with the given name yet. Create an entry @@ -434,7 +434,7 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject if (igraph_vector_init(&es, 0)) { igraphmodule_handle_igraph_error(); return -1; - } + } if (igraph_es_as_vector(&gr->g, self->es, &es)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&es); @@ -459,7 +459,7 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject Py_DECREF(item); igraph_vector_destroy(&es); return -1; - } /* PyList_SetItem stole a reference to the item automatically */ + } /* PyList_SetItem stole a reference to the item automatically */ } igraph_vector_destroy(&es); } else if (values != 0) { @@ -559,6 +559,7 @@ PyObject* igraphmodule_EdgeSeq_find(igraphmodule_EdgeSeqObject *self, PyObject * PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject *args) { igraphmodule_EdgeSeqObject *result; igraphmodule_GraphObject *gr; + igraph_integer_t igraph_idx; long i, j, n, m; gr=self->gref; @@ -682,7 +683,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject /* Iterators and everything that was not handled directly */ PyObject *iter, *item2; igraph_vector_t v, v2; - + /* Allocate stuff */ if (igraph_vector_init(&v, 0)) { igraphmodule_handle_igraph_error(); @@ -743,10 +744,12 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } /* Do the iteration */ while ((item2=PyIter_Next(iter)) != 0) { - if (PyInt_Check(item2)) { - long idx = PyInt_AsLong(item2); + if (igraphmodule_PyObject_to_integer_t(item2, &igraph_idx)) { + /* We simply ignore elements that we don't know */ Py_DECREF(item2); - if (idx >= m || idx < 0) { + } else { + Py_DECREF(item2); + if (igraph_idx >= m || igraph_idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); Py_DECREF(result); Py_DECREF(iter); @@ -754,7 +757,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject igraph_vector_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); @@ -762,9 +765,6 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject igraph_vector_destroy(&v2); return NULL; } - } else { - /* We simply ignore elements that we don't know */ - Py_DECREF(item2); } } /* Deallocate stuff */ @@ -877,7 +877,7 @@ PyObject* igraphmodule_EdgeSeq_get_graph(igraphmodule_EdgeSeqObject* self, /** * \ingroup python_interface_edgeseq - * Returns the indices of the edges in this edge sequence + * Returns the indices of the edges in this edge sequence */ PyObject* igraphmodule_EdgeSeq_get_indices(igraphmodule_EdgeSeqObject* self, void* closure) { @@ -888,7 +888,7 @@ PyObject* igraphmodule_EdgeSeq_get_indices(igraphmodule_EdgeSeqObject* self, if (igraph_vector_init(&es, 0)) { igraphmodule_handle_igraph_error(); return 0; - } + } if (igraph_es_as_vector(&gr->g, self->es, &es)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&es); @@ -968,4 +968,3 @@ PyTypeObject igraphmodule_EdgeSeqType = 0, /* tp_subclasses */ 0, /* tp_weakreflist */ }; - diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 9af0f139f..533366e37 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -1,23 +1,23 @@ /* -*- mode: C -*- */ /* vim: set ts=2 sts=2 sw=2 et: */ -/* +/* IGraph library. Copyright (C) 2006-2012 Tamas Nepusz - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -73,7 +73,7 @@ igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) { copy=(igraphmodule_VertexSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0); if (copy == NULL) return NULL; - + if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) { igraph_vector_t v; if (igraph_vector_copy(&v, o->vs.data.vecptr)) { @@ -258,7 +258,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje PyErr_SetString(PyExc_KeyError, "Attribute does not exist"); return NULL; } else if (PyErr_Occurred()) return NULL; - + switch (igraph_vs_type(&self->vs)) { case IGRAPH_VS_NONE: n = 0; @@ -269,7 +269,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje n = PyList_Size(values); result = PyList_New(n); if (!result) return 0; - + for (i=0; ig, self->vs, &vs)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&vs); @@ -453,7 +453,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb Py_DECREF(item); igraph_vector_destroy(&vs); return -1; - } /* PyList_SetItem stole a reference to the item automatically */ + } /* PyList_SetItem stole a reference to the item automatically */ } igraph_vector_destroy(&vs); } else if (values != 0) { @@ -586,6 +586,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject *args) { igraphmodule_VertexSeqObject *result; igraphmodule_GraphObject *gr; + igraph_integer_t igraph_idx; long i, j, n, m; gr=self->gref; @@ -776,10 +777,12 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } /* Do the iteration */ while ((item2=PyIter_Next(iter)) != 0) { - if (PyInt_Check(item2)) { - long idx = PyInt_AsLong(item2); + if (igraphmodule_PyObject_to_integer_t(item2, &igraph_idx)) { + /* We simply ignore elements that we don't know */ + Py_DECREF(item2); + } else { Py_DECREF(item2); - if (idx >= m || idx < 0) { + if (igraph_idx >= m || igraph_idx < 0) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); Py_DECREF(result); Py_DECREF(iter); @@ -787,7 +790,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, igraph_vector_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); @@ -795,9 +798,6 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, igraph_vector_destroy(&v2); return NULL; } - } else { - /* We simply ignore elements that we don't know */ - Py_DECREF(item2); } } /* Deallocate stuff */ @@ -845,7 +845,7 @@ PyObject* igraphmodule_VertexSeq_get_graph(igraphmodule_VertexSeqObject* self, /** * \ingroup python_interface_vertexseq - * Returns the indices of the vertices in this vertex sequence + * Returns the indices of the vertices in this vertex sequence */ PyObject* igraphmodule_VertexSeq_get_indices(igraphmodule_VertexSeqObject* self, void* closure) { @@ -856,7 +856,7 @@ PyObject* igraphmodule_VertexSeq_get_indices(igraphmodule_VertexSeqObject* self, if (igraph_vector_init(&vs, 0)) { igraphmodule_handle_igraph_error(); return 0; - } + } if (igraph_vs_as_vector(&gr->g, self->vs, &vs)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&vs); @@ -1041,4 +1041,3 @@ PyTypeObject igraphmodule_VertexSeqType = 0, /* tp_subclasses */ 0, /* tp_weakreflist */ }; - diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index 6a448b735..d5235882d 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -29,20 +29,20 @@ def testHash(self): self.assertEqual(i, data[self.g.es[i]]) def testRichCompare(self): - idxs = [2,5,9,13,42] + idxs = [2, 5, 9, 13, 42] g2 = Graph.Full(10) for i in idxs: for j in idxs: self.assertEqual(i == j, self.g.es[i] == self.g.es[j]) self.assertEqual(i != j, self.g.es[i] != self.g.es[j]) - self.assertEqual(i < j, self.g.es[i] < self.g.es[j]) - self.assertEqual(i > j, self.g.es[i] > self.g.es[j]) + self.assertEqual(i < j, self.g.es[i] < self.g.es[j]) + self.assertEqual(i > j, self.g.es[i] > self.g.es[j]) self.assertEqual(i <= j, self.g.es[i] <= self.g.es[j]) self.assertEqual(i >= j, self.g.es[i] >= self.g.es[j]) self.assertFalse(self.g.es[i] == g2.es[j]) self.assertFalse(self.g.es[i] != g2.es[j]) - self.assertFalse(self.g.es[i] < g2.es[j]) - self.assertFalse(self.g.es[i] > g2.es[j]) + self.assertFalse(self.g.es[i] < g2.es[j]) + self.assertFalse(self.g.es[i] > g2.es[j]) self.assertFalse(self.g.es[i] <= g2.es[j]) self.assertFalse(self.g.es[i] >= g2.es[j]) @@ -69,7 +69,7 @@ def testUpdateAttributes(self): self.assertEqual(e.attributes(), dict(a=3, b=44, c=55, d=6)) def testPhantomEdge(self): - e = self.g.es[self.g.ecount()-1] + e = self.g.es[self.g.ecount() - 1] e.delete() # v is now a phantom edge; try to freak igraph out now :) @@ -95,8 +95,7 @@ def testProxyMethods(self): ignore = set(ignore.split()) # Methods not listed here are expected to return an int or a float - return_types = { - } + return_types = {} for name in Edge.__dict__: if name in ignore: @@ -109,16 +108,19 @@ def testProxyMethods(self): continue result = func() - self.assertEqual(getattr(g, name)(e.index), result, - msg=("Edge.%s proxy method misbehaved" % name)) + self.assertEqual( + getattr(g, name)(e.index), + result, + msg=("Edge.%s proxy method misbehaved" % name), + ) return_type = return_types.get(name, (int, float)) - self.assertTrue(isinstance(result, return_type), - msg=("Edge.%s proxy method did not return %s" % (name, return_type)) + self.assertTrue( + isinstance(result, return_type), + msg=("Edge.%s proxy method did not return %s" % (name, return_type)), ) - class EdgeSeqTests(unittest.TestCase): def assert_edges_unique_in(self, es): pairs = sorted(e.tuple for e in es) @@ -131,8 +133,8 @@ def setUp(self): def testCreation(self): self.assertTrue(len(EdgeSeq(self.g)) == 45) self.assertTrue(len(EdgeSeq(self.g, 2)) == 1) - self.assertTrue(len(EdgeSeq(self.g, [1,2,3])) == 3) - self.assertTrue(EdgeSeq(self.g, [1,2,3]).indices == [1,2,3]) + self.assertTrue(len(EdgeSeq(self.g, [1, 2, 3])) == 3) + self.assertTrue(EdgeSeq(self.g, [1, 2, 3]).indices == [1, 2, 3]) self.assertRaises(ValueError, EdgeSeq, self.g, 112) self.assertRaises(ValueError, EdgeSeq, self.g, [112]) self.assertTrue(self.g.es.graph == self.g) @@ -141,9 +143,9 @@ def testIndexing(self): n = self.g.ecount() for i in range(n): self.assertEqual(i, self.g.es[i].index) - self.assertEqual(n-i-1, self.g.es[-i-1].index) + self.assertEqual(n - i - 1, self.g.es[-i - 1].index) self.assertRaises(IndexError, self.g.es.__getitem__, n) - self.assertRaises(IndexError, self.g.es.__getitem__, -n-1) + self.assertRaises(IndexError, self.g.es.__getitem__, -n - 1) self.assertRaises(TypeError, self.g.es.__getitem__, 1.5) @skipIf(np is None, "test case depends on NumPy") @@ -156,28 +158,34 @@ def testNumPyIndexing(self): arr = np.array([n]) self.assertRaises(IndexError, self.g.es.__getitem__, arr[0]) - arr = np.array([-n-1]) + arr = np.array([-n - 1]) self.assertRaises(IndexError, self.g.es.__getitem__, arr[0]) arr = np.array([1.5]) self.assertRaises(TypeError, self.g.es.__getitem__, arr[0]) + ind = [1, 3, 5, 8, 3, 2] + arr = np.array(ind) + self.assertEqual(ind, [edge.index for edge in self.g.es[arr.tolist()]]) + self.assertEqual(ind, [edge.index for edge in self.g.es[list(arr)]]) + def testPartialAttributeAssignment(self): only_even = self.g.es.select(lambda e: (e.index % 2 == 0)) - only_even["test"] = [0]*len(only_even) - expected = [[0,i][i % 2] for i in range(self.g.ecount())] + only_even["test"] = [0] * len(only_even) + expected = [[0, i][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test"] == expected) only_even["test2"] = range(23) - expected = [[i//2, None][i % 2] for i in range(self.g.ecount())] + expected = [[i // 2, None][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test2"] == expected) def testSequenceReusing(self): - if "test" in self.g.edge_attributes(): del self.g.es["test"] + if "test" in self.g.edge_attributes(): + del self.g.es["test"] self.g.es["test"] = ["A", "B", "C"] - self.assertTrue(self.g.es["test"] == ["A", "B", "C"]*15) + self.assertTrue(self.g.es["test"] == ["A", "B", "C"] * 15) self.g.es["test"] = "ABC" self.assertTrue(self.g.es["test"] == ["ABC"] * 45) @@ -216,46 +224,48 @@ def testCallableFilteringSelect(self): only_even = self.g.es.select(lambda e: (e.index % 2 == 0)) self.assertTrue(len(only_even) == 23) self.assertRaises(KeyError, only_even.__getitem__, "nonexistent") - self.assertTrue(only_even["test"] == [i*2 for i in range(23)]) + self.assertTrue(only_even["test"] == [i * 2 for i in range(23)]) def testChainedCallableFilteringSelect(self): - only_div_six = self.g.es.select(lambda e: (e.index % 2 == 0), - lambda e: (e.index % 3 == 0)) + only_div_six = self.g.es.select( + lambda e: (e.index % 2 == 0), lambda e: (e.index % 3 == 0) + ) self.assertTrue(len(only_div_six) == 8) self.assertTrue(only_div_six["test"] == [0, 6, 12, 18, 24, 30, 36, 42]) - only_div_six = self.g.es.select(lambda e: (e.index % 2 == 0)).select(\ - lambda e: (e.index % 3 == 0)) + only_div_six = self.g.es.select(lambda e: (e.index % 2 == 0)).select( + lambda e: (e.index % 3 == 0) + ) self.assertTrue(len(only_div_six) == 8) self.assertTrue(only_div_six["test"] == [0, 6, 12, 18, 24, 30, 36, 42]) def testIntegerFilteringFind(self): self.assertEqual(self.g.es.find(3).index, 3) - self.assertEqual(self.g.es.select(2,3,4,2).find(3).index, 2) + self.assertEqual(self.g.es.select(2, 3, 4, 2).find(3).index, 2) self.assertRaises(IndexError, self.g.es.find, 178) def testIntegerFilteringSelect(self): - subset = self.g.es.select(2,3,4,2) + subset = self.g.es.select(2, 3, 4, 2) self.assertTrue(len(subset) == 4) - self.assertTrue(subset["test"] == [2,3,4,2]) + self.assertTrue(subset["test"] == [2, 3, 4, 2]) self.assertRaises(TypeError, self.g.es.select, 2, 3, 4, 2, None) - subset = self.g.es[2,3,4,2] + subset = self.g.es[2, 3, 4, 2] self.assertTrue(len(subset) == 4) - self.assertTrue(subset["test"] == [2,3,4,2]) + self.assertTrue(subset["test"] == [2, 3, 4, 2]) def testIterableFilteringSelect(self): - subset = self.g.es.select(range(5,8)) + subset = self.g.es.select(range(5, 8)) self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [5,6,7]) + self.assertTrue(subset["test"] == [5, 6, 7]) def testSliceFilteringSelect(self): subset = self.g.es.select(slice(5, 8)) self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [5,6,7]) + self.assertTrue(subset["test"] == [5, 6, 7]) subset = self.g.es[40:56:2] self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [40,42,44]) + self.assertTrue(subset["test"] == [40, 42, 44]) def testKeywordFilteringSelect(self): g = Graph.Barabasi(1000, 2) @@ -266,7 +276,7 @@ def testKeywordFilteringSelect(self): def testSourceTargetFiltering(self): g = Graph.Barabasi(1000, 2, directed=True) - es1 = set(e.source for e in g.es.select(_target_in = [2, 4])) + es1 = set(e.source for e in g.es.select(_target_in=[2, 4])) es2 = set(v1 for v1, v2 in g.get_edgelist() if v2 in [2, 4]) self.assertTrue(es1 == es2) @@ -275,30 +285,37 @@ def testWithinFiltering(self): vs = [0, 1, 2, 10, 11, 12, 20, 21, 22] vs2 = (0, 1, 10, 11) - es1 = g.es.select(_within = vs) - es2 = g.es.select(_within = VertexSeq(g, vs)) + es1 = g.es.select(_within=vs) + es2 = g.es.select(_within=VertexSeq(g, vs)) for es in [es1, es2]: self.assertTrue(len(es) == 12) self.assertTrue(all(e.source in vs and e.target in vs for e in es)) self.assert_edges_unique_in(es) - es_filtered = es.select(_within = vs2) + es_filtered = es.select(_within=vs2) self.assertTrue(len(es_filtered) == 4) - self.assertTrue(all(e.source in vs2 and e.target in vs2 for e in es_filtered)) + self.assertTrue( + all(e.source in vs2 and e.target in vs2 for e in es_filtered) + ) self.assert_edges_unique_in(es_filtered) def testBetweenFiltering(self): g = Graph.Lattice([10, 10]) vs1, vs2 = [10, 11, 12], [20, 21, 22] - es1 = g.es.select(_between = (vs1, vs2)) - es2 = g.es.select(_between = (VertexSeq(g, vs1), VertexSeq(g, vs2))) + es1 = g.es.select(_between=(vs1, vs2)) + es2 = g.es.select(_between=(VertexSeq(g, vs1), VertexSeq(g, vs2))) for es in [es1, es2]: self.assertTrue(len(es) == 3) - self.assertTrue(all((e.source in vs1 and e.target in vs2) or \ - (e.target in vs1 and e.source in vs2) for e in es)) + self.assertTrue( + all( + (e.source in vs1 and e.target in vs2) + or (e.target in vs1 and e.source in vs2) + for e in es + ) + ) self.assert_edges_unique_in(es) def testIncidentFiltering(self): @@ -307,12 +324,12 @@ def testIncidentFiltering(self): vs2 = (11, 0, 24) vs3 = sorted(set(vs).intersection(set(vs2))) - es = g.es.select(_incident = vs) + es = g.es.select(_incident=vs) self.assertEqual(8, len(es)) self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) self.assert_edges_unique_in(es) - es_filtered = es.select(_incident = vs2) + es_filtered = es.select(_incident=vs2) self.assertEqual(6, len(es_filtered)) self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) self.assert_edges_unique_in(es_filtered) @@ -327,12 +344,12 @@ def testIncidentFilteringByNames(self): vs3 = sorted(set(vs).intersection(set(vs2))) - es = g.es.select(_incident = ("A", "B", "C", "D")) + es = g.es.select(_incident=("A", "B", "C", "D")) self.assertEqual(8, len(es)) self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) self.assert_edges_unique_in(es) - es_filtered = es.select(_incident = ("D", "A", "X")) + es_filtered = es.select(_incident=("D", "A", "X")) self.assertEqual(6, len(es_filtered)) self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) self.assert_edges_unique_in(es_filtered) @@ -348,17 +365,17 @@ def testSourceAndTargetFilteringForUndirectedGraphs(self): vs2 = (11, 0, 24) vs3 = sorted(set(vs).intersection(set(vs2))) - es = g.es.select(_from = vs) + es = g.es.select(_from=vs) self.assertEqual(8, len(es)) self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) self.assert_edges_unique_in(es) - es_filtered = es.select(_to_in = vs2) + es_filtered = es.select(_to_in=vs2) self.assertEqual(6, len(es_filtered)) self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) self.assert_edges_unique_in(es_filtered) - es_filtered = es_filtered.select(_from_eq = 0) + es_filtered = es_filtered.select(_from_eq=0) self.assertEqual(2, len(es_filtered)) self.assertTrue(all((e.source == 0 or e.target == 0) for e in es_filtered)) self.assert_edges_unique_in(es_filtered) @@ -394,8 +411,8 @@ def testGraphMethodProxying(self): def testIsAll(self): g = Graph.Full(5) self.assertTrue(g.es.is_all()) - self.assertFalse(g.es.select(1,2,3).is_all()) - self.assertFalse(g.es.select(_within=[1,2,3]).is_all()) + self.assertFalse(g.es.select(1, 2, 3).is_all()) + self.assertFalse(g.es.select(_within=[1, 2, 3]).is_all()) def suite(): @@ -403,10 +420,11 @@ def suite(): es_suite = unittest.makeSuite(EdgeSeqTests) return unittest.TestSuite([edge_suite, es_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 89831fd5b..2d085413c 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -11,6 +11,7 @@ except ImportError: np = None + class VertexTests(unittest.TestCase): def setUp(self): self.g = Graph.Full(10) @@ -33,14 +34,14 @@ def testRichCompare(self): for j in range(self.g.vcount()): self.assertEqual(i == j, self.g.vs[i] == self.g.vs[j]) self.assertEqual(i != j, self.g.vs[i] != self.g.vs[j]) - self.assertEqual(i < j, self.g.vs[i] < self.g.vs[j]) - self.assertEqual(i > j, self.g.vs[i] > self.g.vs[j]) + self.assertEqual(i < j, self.g.vs[i] < self.g.vs[j]) + self.assertEqual(i > j, self.g.vs[i] > self.g.vs[j]) self.assertEqual(i <= j, self.g.vs[i] <= self.g.vs[j]) self.assertEqual(i >= j, self.g.vs[i] >= self.g.vs[j]) self.assertFalse(self.g.vs[i] == g2.vs[j]) self.assertFalse(self.g.vs[i] != g2.vs[j]) - self.assertFalse(self.g.vs[i] < g2.vs[j]) - self.assertFalse(self.g.vs[i] > g2.vs[j]) + self.assertFalse(self.g.vs[i] < g2.vs[j]) + self.assertFalse(self.g.vs[i] > g2.vs[j]) self.assertFalse(self.g.vs[i] <= g2.vs[j]) self.assertFalse(self.g.vs[i] >= g2.vs[j]) self.assertFalse(self.g.es[i] == self.g.vs[j]) @@ -72,11 +73,7 @@ def testIncident(self): g = Graph.Famous("petersen") g.to_directed() - method_table = { - "all": "all_edges", - "in": "in_edges", - "out": "out_edges" - } + method_table = {"all": "all_edges", "in": "in_edges", "out": "out_edges"} for i in range(g.vcount()): vertex = g.vs[i] @@ -84,11 +81,10 @@ def testIncident(self): method = getattr(vertex, method_name) self.assertEqual( g.incident(i, mode=mode), - [edge.index for edge in vertex.incident(mode=mode)] + [edge.index for edge in vertex.incident(mode=mode)], ) self.assertEqual( - g.incident(i, mode=mode), - [edge.index for edge in method()] + g.incident(i, mode=mode), [edge.index for edge in method()] ) def testNeighbors(self): @@ -100,7 +96,7 @@ def testNeighbors(self): for mode in "all in out".split(): self.assertEqual( g.neighbors(i, mode=mode), - [edge.index for edge in vertex.neighbors(mode=mode)] + [edge.index for edge in vertex.neighbors(mode=mode)], ) @skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") @@ -124,15 +120,14 @@ def testProxyMethods(self): # - pagerank() and personalized_pagerank() are ignored because of numerical # inaccuracies # - delete() is ignored because it mutates the graph - ignore = "neighbors predecessors successors pagerank personalized_pagerank"\ - " delete incident all_edges in_edges out_edges" + ignore = ( + "neighbors predecessors successors pagerank personalized_pagerank" + " delete incident all_edges in_edges out_edges" + ) ignore = set(ignore.split()) # Methods not listed here are expected to return an int or a float - return_types = { - "get_shortest_paths": list, - "shortest_paths": list - } + return_types = {"get_shortest_paths": list, "shortest_paths": list} for name in Vertex.__dict__: if name in ignore: @@ -145,12 +140,16 @@ def testProxyMethods(self): continue result = func() - self.assertEqual(getattr(g, name)(v.index), result, - msg=("Vertex.%s proxy method misbehaved" % name)) + self.assertEqual( + getattr(g, name)(v.index), + result, + msg=("Vertex.%s proxy method misbehaved" % name), + ) return_type = return_types.get(name, (int, float)) - self.assertTrue(isinstance(result, return_type), - msg=("Vertex.%s proxy method did not return %s" % (name, return_type)) + self.assertTrue( + isinstance(result, return_type), + msg=("Vertex.%s proxy method did not return %s" % (name, return_type)), ) @@ -163,8 +162,8 @@ def setUp(self): def testCreation(self): self.assertTrue(len(VertexSeq(self.g)) == 10) self.assertTrue(len(VertexSeq(self.g, 2)) == 1) - self.assertTrue(len(VertexSeq(self.g, [1,2,3])) == 3) - self.assertTrue(VertexSeq(self.g, [1,2,3]).indices == [1,2,3]) + self.assertTrue(len(VertexSeq(self.g, [1, 2, 3])) == 3) + self.assertTrue(VertexSeq(self.g, [1, 2, 3]).indices == [1, 2, 3]) self.assertRaises(ValueError, VertexSeq, self.g, 12) self.assertRaises(ValueError, VertexSeq, self.g, [12]) self.assertTrue(self.g.vs.graph == self.g) @@ -173,9 +172,9 @@ def testIndexing(self): n = self.g.vcount() for i in range(n): self.assertEqual(i, self.g.vs[i].index) - self.assertEqual(n-i-1, self.g.vs[-i-1].index) + self.assertEqual(n - i - 1, self.g.vs[-i - 1].index) self.assertRaises(IndexError, self.g.vs.__getitem__, n) - self.assertRaises(IndexError, self.g.vs.__getitem__, -n-1) + self.assertRaises(IndexError, self.g.vs.__getitem__, -n - 1) self.assertRaises(TypeError, self.g.vs.__getitem__, 1.5) @skipIf(np is None, "test case depends on NumPy") @@ -184,40 +183,54 @@ def testNumPyIndexing(self): for i in range(self.g.vcount()): arr = np.array([i]) self.assertEqual(i, self.g.vs[arr[0]].index) - arr = np.array([-i-1]) - self.assertEqual(n-i-1, self.g.vs[arr[0]].index) + arr = np.array([-i - 1]) + self.assertEqual(n - i - 1, self.g.vs[arr[0]].index) arr = np.array([n]) self.assertRaises(IndexError, self.g.vs.__getitem__, arr[0]) - arr = np.array([-n-1]) + arr = np.array([-n - 1]) self.assertRaises(IndexError, self.g.vs.__getitem__, arr[0]) arr = np.array([1.5]) self.assertRaises(TypeError, self.g.vs.__getitem__, arr[0]) + ind = [1, 3, 5, 8, 3, 2] + arr = np.array(ind) + self.assertEqual(ind, [vertex.index for vertex in self.g.vs[arr.tolist()]]) + self.assertEqual(ind, [vertex.index for vertex in self.g.vs[list(arr)]]) + def testPartialAttributeAssignment(self): only_even = self.g.vs.select(lambda v: (v.index % 2 == 0)) - only_even["test"] = [0]*len(only_even) - self.assertTrue(self.g.vs["test"] == [0,1,0,3,0,5,0,7,0,9]) + only_even["test"] = [0] * len(only_even) + self.assertTrue(self.g.vs["test"] == [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]) only_even["test2"] = range(5) - self.assertTrue(self.g.vs["test2"] == [0,None,1,None,2,None,3,None,4,None]) + self.assertTrue( + self.g.vs["test2"] == [0, None, 1, None, 2, None, 3, None, 4, None] + ) def testSequenceReusing(self): if "test" in self.g.vertex_attributes(): del self.g.vs["test"] self.g.vs["test"] = ["A", "B", "C"] - self.assertTrue(self.g.vs["test"] == ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A"]) + self.assertTrue( + self.g.vs["test"] == ["A", "B", "C", "A", "B", "C", "A", "B", "C", "A"] + ) self.g.vs["test"] = "ABC" self.assertTrue(self.g.vs["test"] == ["ABC"] * 10) only_even = self.g.vs.select(lambda v: (v.index % 2 == 0)) only_even["test"] = ["D", "E"] - self.assertTrue(self.g.vs["test"] == ["D", "ABC", "E", "ABC", "D", "ABC", "E", "ABC", "D", "ABC"]) + self.assertTrue( + self.g.vs["test"] + == ["D", "ABC", "E", "ABC", "D", "ABC", "E", "ABC", "D", "ABC"] + ) del self.g.vs["test"] only_even["test"] = ["D", "E"] - self.assertTrue(self.g.vs["test"] == ["D", None, "E", None, "D", None, "E", None, "D", None]) + self.assertTrue( + self.g.vs["test"] == ["D", None, "E", None, "D", None, "E", None, "D", None] + ) def testAllSequence(self): self.assertTrue(len(self.g.vs) == 10) @@ -246,49 +259,51 @@ def testCallableFilteringSelect(self): self.assertTrue(only_even["test"] == [0, 2, 4, 6, 8]) def testChainedCallableFilteringSelect(self): - only_div_six = self.g.vs.select(lambda v: (v.index % 2 == 0), - lambda v: (v.index % 3 == 0)) + only_div_six = self.g.vs.select( + lambda v: (v.index % 2 == 0), lambda v: (v.index % 3 == 0) + ) self.assertTrue(len(only_div_six) == 2) self.assertTrue(only_div_six["test"] == [0, 6]) - only_div_six = self.g.vs.select(lambda v: (v.index % 2 == 0)).select(\ - lambda v: (v.index % 3 == 0)) + only_div_six = self.g.vs.select(lambda v: (v.index % 2 == 0)).select( + lambda v: (v.index % 3 == 0) + ) self.assertTrue(len(only_div_six) == 2) self.assertTrue(only_div_six["test"] == [0, 6]) def testIntegerFilteringFind(self): self.assertEqual(self.g.vs.find(3).index, 3) - self.assertEqual(self.g.vs.select(2,3,4,2).find(3).index, 2) + self.assertEqual(self.g.vs.select(2, 3, 4, 2).find(3).index, 2) self.assertRaises(IndexError, self.g.vs.find, 17) def testIntegerFilteringSelect(self): - subset = self.g.vs.select(2,3,4,2) + subset = self.g.vs.select(2, 3, 4, 2) self.assertEqual(len(subset), 4) - self.assertEqual(subset["test"], [2,3,4,2]) + self.assertEqual(subset["test"], [2, 3, 4, 2]) self.assertRaises(TypeError, self.g.vs.select, 2, 3, 4, 2, None) - subset = self.g.vs[2,3,4,2] + subset = self.g.vs[2, 3, 4, 2] self.assertTrue(len(subset) == 4) - self.assertTrue(subset["test"] == [2,3,4,2]) + self.assertTrue(subset["test"] == [2, 3, 4, 2]) def testStringFilteringFind(self): self.assertEqual(self.g.vs.find("D").index, 3) - self.assertEqual(self.g.vs.select(2,3,4,2).find("C").index, 2) - self.assertRaises(ValueError, self.g.vs.select(2,3,4,2).find, "F") + self.assertEqual(self.g.vs.select(2, 3, 4, 2).find("C").index, 2) + self.assertRaises(ValueError, self.g.vs.select(2, 3, 4, 2).find, "F") self.assertRaises(ValueError, self.g.vs.find, "NoSuchName") def testIterableFilteringSelect(self): - subset = self.g.vs.select(range(5,8)) + subset = self.g.vs.select(range(5, 8)) self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [5,6,7]) + self.assertTrue(subset["test"] == [5, 6, 7]) def testSliceFilteringSelect(self): subset = self.g.vs.select(slice(5, 8)) self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [5,6,7]) + self.assertTrue(subset["test"] == [5, 6, 7]) subset = self.g.vs[5:16:2] self.assertTrue(len(subset) == 3) - self.assertTrue(subset["test"] == [5,7,9]) + self.assertTrue(subset["test"] == [5, 7, 9]) def testKeywordFilteringSelect(self): g = Graph.Barabasi(10000) @@ -317,7 +332,7 @@ def testIndexOutOfBoundsSelect(self): def testGraphMethodProxying(self): g = Graph.Barabasi(100) - vs = g.vs(1,3,5,7,9) + vs = g.vs(1, 3, 5, 7, 9) self.assertEqual(vs.degree(), g.degree(vs)) self.assertEqual(g.degree(vs), g.degree(vs.indices)) for v, d in zip(vs, vs.degree()): @@ -340,10 +355,11 @@ def suite(): vs_suite = unittest.makeSuite(VertexSeqTests) return unittest.TestSuite([vertex_suite, vs_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - From 4190b95b05e36ab747f3241d566f0e9b48843594 Mon Sep 17 00:00:00 2001 From: John Boy Date: Wed, 1 Apr 2020 12:21:25 +0000 Subject: [PATCH 0210/1892] Bring tutorial and documentation up to date. (#279) * Update references and links to general Python tutorials. * Simplify introduction to installation documentation. * Restructure and update installation instructions. Co-authored-by: John Boy --- doc/source/install.rst | 224 ++++++++++++++++++---------------------- doc/source/tutorial.rst | 20 ++-- 2 files changed, 109 insertions(+), 135 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index a3fff76ce..97c002cfb 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -8,160 +8,136 @@ Installing |igraph| =================== -This chapter describes how to install the C core of |igraph| and its Python bindings -on various operating systems. +This chapter describes how to install the C core of |igraph| and its Python bindings on +Windows, macOS, and GNU/Linux. Which |igraph| is right for you? ================================ -|igraph| is primarily a library written in C. It is *not* a standalone program, nor it is -a Python package that you can just drop on your Python path to start using it. Therefore, -if you would like to exploit |igraph|'s functionality in Python, you must install -a few packages. Do not worry, though, there are precompiled packages for the major operating -systems, so you will not have to compile |igraph| from source unless you use an esoteric -operating system or you have specific requirements (i.e., adding a custom patch to |igraph|'s -C core). Precompiled packages are often called *binary packages*, while the raw source code -is usually referred to as the *source package*. - -In general, you should almost always opt for the binary package unless a binary package is not -available for your platform or you have some local modifications that you want to incorporate -into |igraph|'s source. `Installation from a binary package`_ tells you how to install |igraph| -from a precompiled binary package on various platforms. `Compiling igraph from source`_ tells -you how to compile |igraph| from the source package. +|igraph| is primarily a library written in C. It is *not* a standalone program, nor it is a +pure Python package that you can just drop in your Python path. Therefore, if you would like +to use |igraph|'s functionality in Python, you must install a few packages. Do not worry, +though, there are precompiled packages for the major operating systems. Precompiled packages +are often called *binary packages*, while the raw source code is usually referred to as the +*source package*. + +In general, you should almost always opt for the binary package unless a binary package is +not available for your platform or you have some local modifications that you want to +incorporate into |igraph|'s source. `Installation from a binary package`_ tells you how to +install |igraph| from a precompiled binary package on various platforms. `Compiling igraph +from source`_ tells you how to compile |igraph| from the source package. Installation from a binary package ================================== -|igraph| on Windows -------------------- +Installing |igraph| from the Python Package Index +------------------------------------------------- + +To ensure getting the latest binary release of |igraph|'s Python interface, it is recommended +that you install it from the `Python Package Index +`_ (PyPI), which has installers for Windows, Linux, +and macOS. Currently there are binary packages for Python 2.7, and Python 3.5 through 3.8, but +note that support for Python 2.7 will be discontinued with the version 0.9.0 release of +|igraph|'s Python interface. + +Many users like to install packages into a project-specific `virtual environment +`_. +A variation of the following commands should work on most platforms: + + $ python -m venv ENV + $ source ENV/bin/activate + $ pip install python-igraph -There is a Windows installer for |igraph|'s Python interface on the -`Python Package Index `_. -Download the one that is suitable for your Python version (currently -there are binary packages for Python 2.6, Python 2.7 and Python 3.2, -though it might change in the future). To test the installed package, launch -your favourite Python IDE and type the following: +To test the installed package, launch Python within the virtual environment and run the +following: >>> import igraph.test >>> igraph.test.run_tests() -The above commands run the bundled test cases to ensure that everything -is fine with your |igraph| installation. - -Graph plotting in |igraph| on Windows -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Graph plotting in |igraph| is implemented using a third-party package -called `Cairo `_. If you want to create -publication-quality plots in |igraph| on Windows, you must also install -Cairo and its Python bindings. The Cairo project does not provide -pre-compiled binaries for Windows, but Christoph Gohlke maintains a site -containing unofficial Windows binaries for several Python extension packages, -including Cairo itself. Therefore, the easiest way to install Cairo on Windows -along with its Python bindings is simply to download it from -`Christoph's site `_. Make -sure you use an installer that is suitable for your Windows platform (32-bit or -64-bit) and the version of Python you are using. - -In case you use a version of Python for which the above site does not provide -an installer, you can install it from an alternative source in a slightly more -complicated way by following the steps below: - -1. Get the latest PyCairo for Windows installer from - http://ftp.gnome.org/pub/gnome/binaries/win32/pycairo/1.8. Make sure you - grab the one that matches your Python version. At the time of writing, - the above folder contained installers for Python 2.6 and 2.7 only. You may - also try and go one level up, then down then 1.4 subfolder -- these are - older versions, but they work with Python 2.5 and Python 2.6 as well. - -2. Install PyCairo using the installer. The installer extracts the necessary - files into ``Lib\site-packages\cairo`` within the folder where Python is - installed. Unfortunately there are some extra DLLs which are required to - make Cairo work, so we have to get these as well. - -3. Head to http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ and get - the binary versions of Cairo (``cairo_1.8.10-3_win32.zip`` at the time of - writing), Fontconfig (``fontconfig_2.8.0-2_win32.zip``), Freetype - (``freetype_2.4.4-1_win32.zip``), Expat (``expat_2.0.1-1_win32.zip``), - ``libpng`` (``libpng_1.4.3-1_win32.zip``) and ``zlib`` - (``zlib_1.2.5-2_win32.zip``). Version numbers may vary, so be - adaptive! Each ZIP file will contain a ``bin`` subfolder with a DLL file in - it. Put the following DLLs in ``Lib\site-packages\cairo`` within your Python - installation: - - - ``freetype6.dll`` (from ``freetype_2.4.4-1_win32.zip``) - - ``libcairo-2.dll`` (from ``cairo_1.8.10-3_win32.zip``) - - ``libexpat-1.dll`` (from ``expat_2.0.1-1_win32.zip``) - - ``libfontconfig-1.dll`` (from ``fontconfig_2.8.0-2_win32.zip``) - - ``libpng14-14.dll`` (from ``libpng_1.4.3-1_win32.zip``) - - ``zlib1.dll`` (from ``zlib_1.2.5-2_win32.zip``). - -Having done that, you can launch Python again and check if it worked: - - >>> from igraph import * - >>> g = Graph.Famous("petersen") - >>> plot(g) +The above commands run the bundled test cases to ensure that everything is fine with your +|igraph| installation. -|igraph| on Linux ------------------ +Installing |igraph| via Conda +----------------------------- -|igraph| on Debian GNU/Linux -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Users of the `Anaconda Python distribution `_ or the +`conda package manager `_ may opt to install |igraph|'s Python interface +using conda. That can be achieved by running the following command: -Make sure you have all the required dependencies installed: + $ conda install -c conda-forge python-graph - $ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev +To test the installed package, launch Python and run the following: -and then install with pip / pip3 + >>> import igraph.test + >>> igraph.test.run_tests() - $ pip install python-igraph +The above commands run the bundled test cases to ensure that everything is fine with your +|igraph| installation. -|igraph| on RedHat Linux -^^^^^^^^^^^^^^^^^^^^^^^^ +|igraph| on Windows +------------------- -|igraph| on other Linux distributions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +There is a Windows installer for |igraph|'s Python interface on the `Python Package Index +`_ (see `Installing igraph from the Python Package +Index`_). -|igraph| on Mac OS X --------------------- +TODO: Check if Windows still requires special steps to get PyCairo running. -There is a Mac OS X installer for |igraph|'s Python interface on the -`Python Package Index `_ -which works for Intel-based Macs running OS X Lion. The default -Python version in Leopard is Python 2.7, so the package is compiled -for this specific version. PowerPC users should compile the package -themselves (see `Compiling igraph from source`_). To test the -installed package, launch your favourite Python IDE or the default -command line interpreter and type the following: +Graph plotting in |igraph| is implemented using a third-party package called `Cairo +`_. If you want to create publication-quality plots in |igraph| +on Windows, you must also install Cairo and its Python bindings. The Cairo project does not +provide pre-compiled binaries for Windows, but Christoph Gohlke maintains a site containing +unofficial Windows binaries for several Python extension packages, including Cairo. +Therefore, the easiest way to install Cairo on Windows along with its Python bindings is +simply to download it from `Christoph's site +`_. Make sure you use an installer that is +suitable for your Windows platform (32-bit or 64-bit) and the version of Python you are using. - >>> import igraph.test - >>> igraph.test.run_tests() +After running the installer, you can launch Python again and check if it worked: + + >>> import igraph as ig + >>> g = ig.Graph.Famous("petersen") + >>> ig.plot(g) + +If PyCairo was successfully installed, this will display a Petersen graph. + +|igraph| on macOS +----------------- + +The Mac installer for |igraph|'s Python interface on the `Python Package Index +`_ works for Intel-based Macs only. PowerPC +users should compile the package themselves (see `Compiling igraph from source`_). -The above commands run the bundled test cases to ensure that everything -is fine with your |igraph| installation. +TODO: Check if PyCairo on Mac still requires using Brew -Graph plotting in |igraph| on Mac OS X -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Graph plotting in |igraph| is implemented using a third-party package called `Cairo +`_. If you want to create publication-quality plots in |igraph| +on macOS, you must also install Cairo and its Python bindings. The Cairo project does not +provide pre-compiled binaries for macOS, but the `Homebrew package manager +`, so you can use it to install Cairo. After installing Homebrew itself, you +can run: -Graph plotting in |igraph| is implemented using a third-party package -called `Cairo `_. If you want to create -publication-quality plots in |igraph| on Mac OS X, you must also install -Cairo and its Python bindings. The Cairo project does not provide -pre-compiled binaries for Mac OS X, but `MacPorts `_ -and `Fink `_ does, so you can use them to -install Cairo. The `Cairo homepage `_ gives -you some installation instructions. However, this is only one half of the -job, you will also need the Python bindings of Cairo from the -`PyCairo homepage `_. At the moment -there are no precompiled PyCairo packages for Mac OS X either. + $ brew install cairo + +After installing Cairo, launch Python and check if it worked: + + >>> import igraph as ig + >>> g = ig.Graph.Famous("petersen") + >>> ig.plot(g) + +If Cairo was successfully installed, this will display a Petersen graph. + +|igraph| on Linux +----------------- -TODO: detailed compilation instructions for PyCairo +|igraph|'s Python interface and its dependencies have been packaged for most popular Linux +distributions, including Arch Linux, Debian, Fedora, GNU Guix, NixOS, and Ubuntu. Because +distribution packages are often outdated, you may choose to install |igraph| from the `Python +Package Index `_ instead to get a more recent +release (see `Installing igraph from the Python Package Index`_). -|igraph| on other operating systems ------------------------------------ Compiling |igraph| from source ============================== -Summary -======= +TODO diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 63f75a580..f95f4d7da 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -6,17 +6,15 @@ Tutorial ======== -This chapter contains a short overview of |igraph|'s capabilities. It is highly recommended -to read it at least once if you are new to |igraph|. I assume that you have already installed -|igraph|; if you did not, see :ref:`installing-igraph` first. Familiarity with the Python -language is also assumed; if this is the first time you are trying to use Python, there are -many good Python tutorials on the Internet to get you started. Mark Pilgrim's -`Dive Into Python `_ is one that I personally suggest. -If this is the first time you ever try to use a programming language, -`A Byte of Python `_ is even better. If -you already have a stable programming background in other languages and you just want a -quick overview of Python, `Learn Python in 10 minutes -`_ is probably your best bet. +This chapter contains a short overview of |igraph|'s capabilities. It is highly recommended to read +it at least once if you are new to |igraph|. I assume that you have already installed |igraph|; if +you did not, see :ref:`installing-igraph` first. Familiarity with the Python language is also +assumed; if this is the first time you are trying to use Python, there are many good Python +tutorials on the Internet to get you started. If this is the first time you ever try to use a +programming language, `A Byte of Python `_ is a good place to +start out. If you already have a stable programming background in other languages and you just want +a quick overview of Python, `Learn Python in 10 minutes `_ +is probably your best bet. Starting |igraph| From 6d52cb8a7579bdb1dad57821160f5824bc08e8c1 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Mon, 6 Apr 2020 22:33:29 +0200 Subject: [PATCH 0211/1892] Fix possible crash in Leiden algorithm (#289) --- src/_igraph/graphobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index bb3edd5ab..f341714b9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11763,7 +11763,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, long int n_iterations = 2; double resolution_parameter = 1.0; double beta = 0.01; - igraph_vector_t *edge_weights = NULL, *node_weights = NULL, *membership; + igraph_vector_t *edge_weights = NULL, *node_weights = NULL, *membership = NULL; igraph_bool_t start = 1; igraph_bool_t normalize_resolution = 0; igraph_integer_t nb_clusters = 0; @@ -11859,7 +11859,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, free(node_weights); } - if (!error) { + if (!error && membership != 0) { res = igraphmodule_vector_t_to_PyList(membership, IGRAPHMODULE_TYPE_INT); } From a7752c1a6cb23999b3b0b2fadde10bd4b6edfaab Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 27 Apr 2020 16:02:19 +0200 Subject: [PATCH 0212/1892] bumped version to 0.8.1 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 38dd8e61a..7f52d887a 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.8.0' +version = '0.8.1' # The full version, including alpha/beta/rc tags. -release = '0.8.0' +release = '0.8.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 4b41f137f..b5c61ee08 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 8, 0) +__version_info__ = (0, 8, 1) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 6a82d8ace7dfbcfe4d51b1d5826bf9fd92d2949e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 27 Apr 2020 18:05:39 +0200 Subject: [PATCH 0213/1892] make sure that the tests are actually executed in tox with Python 2.7 --- setup.py | 3 +++ src/_igraph/attributes.c | 7 +++++-- tests/test_attributes.py | 4 +++- tests/test_foreign.py | 2 +- tests/utils.py | 4 ++-- tox.ini | 3 +++ 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 29482e21d..98465b559 100644 --- a/setup.py +++ b/setup.py @@ -836,6 +836,9 @@ def use_educated_guess(self): }, ) +if sys.version_info <= (2, 7): + options["requires"] = options.pop("install_requires") + if sys.version_info > (3, 0): options["use_2to3"] = True diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index fd9431834..db746334c 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -87,8 +87,11 @@ int igraphmodule_i_attribute_struct_index_vertex_names( PyErr_Format( PyExc_RuntimeError, "error while indexing vertex names; did you accidentally try to " - "use a non-hashable object as a vertex name earlier? " - "Check the name of vertex %R (%R)", value, key + "use a non-hashable object as a vertex name earlier?" +#ifdef IGRAPH_PYTHON3 + /* %R is not supported in Python 2.x */ + " Check the name of vertex %R (%R)", value, key +#endif ); } diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 45984a737..4d81ee18f 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -1,4 +1,5 @@ # vim:ts=4 sw=4 sts=4: +import sys import unittest from igraph import * @@ -102,7 +103,8 @@ def testUnhashableVertexNames(self): # Check the exception self.assertTrue(isinstance(err, RuntimeError)) - self.assertTrue(repr(value) in str(err)) + if sys.version_info >= (3, 4): + self.assertTrue(repr(value) in str(err)) def testVertexNameIndexingBug196(self): g = Graph() diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 5c4ff1d30..ff30ec2af 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -226,7 +226,7 @@ def testPickle(self): pickle = bytes(pickle) else: pickle = "".join(map(chr, pickle)) - with temporary_file(pickle, "wb") as tmpfname: + with temporary_file(pickle, "wb", binary=True) as tmpfname: g = Graph.Read_Pickle(pickle) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and diff --git a/tests/utils.py b/tests/utils.py index c4fab472f..82b951a54 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -47,7 +47,7 @@ def skipIf(condition, reason): @contextmanager -def temporary_file(content=None, mode=None): +def temporary_file(content=None, mode=None, binary=False): tmpf, tmpfname = tempfile.mkstemp() os.close(tmpf) @@ -59,7 +59,7 @@ def temporary_file(content=None, mode=None): tmpf = open(tmpfname, mode) if content is not None: - if hasattr(content, "encode"): + if hasattr(content, "encode") and not binary: tmpf.write(dedent(content).encode("utf8")) else: tmpf.write(content) diff --git a/tox.ini b/tox.ini index 37d5c3e86..d2c11f3e3 100644 --- a/tox.ini +++ b/tox.ini @@ -14,6 +14,9 @@ deps = setenv = TESTING_IN_TOX=1 +[testenv:py27] +commands = python -m unittest discover + [flake8] max-line-length = 80 select = C,E,F,W,B,B950 From c796a105d2fbeb331c46e8cc2390e04716416fb5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Apr 2020 11:38:44 +0200 Subject: [PATCH 0214/1892] update embedded igraph to dev version to fix compilation problems on MSVC --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 48b1c706b..578579185 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 48b1c706b4364c40678a3e01fde1766380dcfabd +Subproject commit 5785791853de2f9653161e5f5f035256f76dddb0 From 4b2bfbe8459c976c73e722aeb7ec78f52b1e12d7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Apr 2020 13:10:19 +0200 Subject: [PATCH 0215/1892] try again with further tweaks --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 578579185..0afacadd8 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 5785791853de2f9653161e5f5f035256f76dddb0 +Subproject commit 0afacadd854aefc3db9758a7a46863b4d851aacd From dee73ba0a5141047453718e4c9b1e75f08a2244f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Apr 2020 14:34:34 +0200 Subject: [PATCH 0216/1892] bumped version to 0.8.2 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 7f52d887a..5b83e8332 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.8.1' +version = '0.8.2' # The full version, including alpha/beta/rc tags. -release = '0.8.1' +release = '0.8.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index b5c61ee08..b523d76db 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 8, 1) +__version_info__ = (0, 8, 2) __version__ = ".".join("{0}".format(x) for x in __version_info__) From ad6e83f972a36ec82536c0b6db29b6913452429a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 30 Apr 2020 22:32:14 +0200 Subject: [PATCH 0217/1892] don't leak full absolute paths in warning messages, refs #293 --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 98465b559..58d3df338 100644 --- a/setup.py +++ b/setup.py @@ -263,6 +263,8 @@ def compile_in(self, build_folder, source_folder=None): source_folder = os.path.abspath(source_folder) build_folder = os.path.abspath(build_folder) + + build_to_source_folder = os.path.relpath(source_folder, build_folder) cwd = os.getcwd() try: @@ -297,7 +299,7 @@ def compile_in(self, build_folder, source_folder=None): configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) retcode = subprocess.call( "sh {0} {1}".format( - quote_path_for_shell(os.path.join(source_folder, "configure")), + quote_path_for_shell(os.path.join(build_to_source_folder, "configure")), " ".join(configure_args) ), env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), From b6b8d6d6d2f707055f8f8f37a159ec6a8b8376d6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 7 May 2020 21:35:42 +0200 Subject: [PATCH 0218/1892] fix typo in installation instructions, closes #26 --- doc/source/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 97c002cfb..45c26fbd9 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -64,7 +64,7 @@ Users of the `Anaconda Python distribution `_ may opt to install |igraph|'s Python interface using conda. That can be achieved by running the following command: - $ conda install -c conda-forge python-graph + $ conda install -c conda-forge python-igraph To test the installed package, launch Python and run the following: From b94ff802ece20f00107c4d17dcb0d72578e2b349 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 May 2020 12:47:15 +0200 Subject: [PATCH 0219/1892] trying to install zstd in Appveyor to support installing .tar.zst packages --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 65deb3354..a602baa12 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,6 +25,7 @@ platform: install: - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - bash -lc "pacman --noconfirm -Sy" + - bash -lc "pacman --noconfirm -S zstd" - bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - pip install cibuildwheel==1.1.0 From 9a826d6fc463ee7c74332dba510826431ae6ea4b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Jun 2020 12:24:57 +0200 Subject: [PATCH 0220/1892] fix an issue with 'detected' being referenced befure it is defined; closes #299 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 58d3df338..0515be342 100644 --- a/setup.py +++ b/setup.py @@ -487,6 +487,7 @@ def run(self): # Check whether the user asked us to discover a pre-built igraph # with pkg-config + detected = False if buildcfg.use_pkgconfig: detected = buildcfg.detect_from_pkgconfig() if not detected: From 5f71ad9716dda3470e6667b559ca0495de64e700 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Jun 2020 13:10:09 +0200 Subject: [PATCH 0221/1892] added supported Python versions to setup.py --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index 0515be342..24806c863 100644 --- a/setup.py +++ b/setup.py @@ -825,6 +825,11 @@ def use_educated_guess(self): "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics", From 0bf67030de0de11bcc4ba44807847fc631588fd4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Jun 2020 13:14:11 +0200 Subject: [PATCH 0222/1892] clarified supported Python versions, closes #300 --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40c263a5e..05e01b552 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ [![](https://travis-ci.org/igraph/python-igraph.svg?branch=master)](https://travis-ci.org/igraph/python-igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-2.7%20%7C%203.5%20%7C%203.6%20%7C%203.7%20%7C%203.8-blue)](https://pypi.python.org/pypi/python-igraph) +[![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) Python interface for the igraph library --------------------------------------- @@ -149,7 +151,23 @@ faster than the first one as the C core does not need to be recompiled. ## Notes -### Pypy +### Supported Python versions + +We aim to keep up with the development cycle of Python and support all official +Python versions that have not reached their end of life yet. Currently this +means that we support Python 3.5 to 3.8, inclusive. Please refer to [this +page](https://devguide.python.org/#branchstatus) for the status of Python +branches and let us know if you encounter problems with `python-igraph` on any +of the non-EOL Python versions. + +Continuous integration tests are regularly executed on all non-EOL Python +branches. + +As for Python 2.x, the latest branch of `python-igraph` that supports Python 2 +is the 0.8.x series. Python 2 support will be dropped with the release of +`python-igraph` 0.9. + +### PyPy This version of python-igraph is compatible with [PyPy](http://pypy.org/) and is regularly tested on [PyPy](http://pypy.org/) with ``tox``. However, the From 6318ee311cb230797e96419b0c96a3aa587e7ddb Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Jun 2020 13:15:56 +0200 Subject: [PATCH 0223/1892] updated Travis badge to match the style of the other badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05e01b552..f8b13693b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![](https://travis-ci.org/igraph/python-igraph.svg?branch=master)](https://travis-ci.org/igraph/python-igraph) +[![Travis CI](https://img.shields.io/travis/igraph/python-igraph)](https://travis-ci.org/igraph/python-igraph) [![PyPI pyversions](https://img.shields.io/badge/python-2.7%20%7C%203.5%20%7C%203.6%20%7C%203.7%20%7C%203.8-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) From 6bbae1fbee2eb240215e57d9e2ae7964574a0360 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 11 Jun 2020 14:09:38 +0200 Subject: [PATCH 0224/1892] updated vendored igraph to incorporate some recent bugfixes --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 0afacadd8..20ad88e75 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 0afacadd854aefc3db9758a7a46863b4d851aacd +Subproject commit 20ad88e759205e73d79f612663153ba97c56a866 From 8ff48a813b86f684b2eb1ca56552d643d6df4417 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Sat, 27 Jun 2020 14:44:06 +0200 Subject: [PATCH 0225/1892] Clarified and corrected negative number of iterations in Leiden algorithm (#304) --- src/_igraph/graphobject.c | 10 +++++----- src/igraph/__init__.py | 19 +++++++++++-------- vendor/source/igraph | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f341714b9..dac3b4740 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11753,7 +11753,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, static char *kwlist[] = {"edge_weights", "node_weights", "resolution_parameter", "normalize_resolution", "beta", "initial_membership", "n_iterations", NULL}; - + PyObject *edge_weights_o = Py_None; PyObject *node_weights_o = Py_None; PyObject *initial_membership_o = Py_None; @@ -11823,12 +11823,12 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } } } - resolution_parameter /= igraph_vector_sum(node_weights); + resolution_parameter /= igraph_vector_sum(node_weights); } /* Run actual Leiden algorithm for several iterations. */ if (!error) { - if (n_iterations > 0) { + if (n_iterations >= 0) { for (i = 0; !error && i < n_iterations; i++) { error = igraph_community_leiden(&self->g, edge_weights, node_weights, @@ -11839,13 +11839,13 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } } else { while (!error && prev_quality < quality) { + prev_quality = quality; error = igraph_community_leiden(&self->g, edge_weights, node_weights, resolution_parameter, beta, start, membership, &nb_clusters, &quality); start = 1; - prev_quality = quality; } } } @@ -15855,7 +15855,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " @param n_iterations: the number of iterations to iterate the Leiden\n" " algorithm. Each iteration may improve the partition further.\n" " @return: the community membership vector.\n" - }, + }, {"community_walktrap", (PyCFunction) igraphmodule_Graph_community_walktrap, METH_VARARGS | METH_KEYWORDS, diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index f8db38ef8..a07c4473d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1422,27 +1422,30 @@ def k_core(self, *args): def community_leiden(self, objective_function="CPM", weights=None, resolution_parameter=1.0, beta=0.01, initial_membership=None, n_iterations=2, node_weights=None): - """community_leiden(objective_function=CPM, weights=None, + """community_leiden(objective_function=CPM, weights=None, resolution_parameter=1.0, beta=0.01, initial_membership=None, n_iterations=2, node_weights=None) Finds the community structure of the graph using the Leiden algorithm of Traag, van Eck & Waltman. - @keyword objective_function: whether to use the Constant Potts + @keyword objective_function: whether to use the Constant Potts Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. @keyword weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. @keyword resolution_parameter: the resolution parameter to use. - Higher resolutions lead to more smaller communities, while + Higher resolutions lead to more smaller communities, while lower resolutions lead to fewer larger communities. - @keyword beta: parameter affecting the randomness in the Leiden + @keyword beta: parameter affecting the randomness in the Leiden algorithm. This affects only the refinement step of the algorithm. @keyword initial_membership: if provided, the Leiden algorithm will try to improve this provided membership. If no argument is provided, the aglorithm simply starts from the singleton partition. @keyword n_iterations: the number of iterations to iterate the Leiden - algorithm. Each iteration may improve the partition further. + algorithm. Each iteration may improve the partition further. Using + a negative number of iterations will run until a stable iteration is + encountered (i.e. the quality was not increased during that + iteration). @keyword node_weights: the node weights used in the Leiden algorithm. If this is not provided, it will be automatically determined on the basis of whether you want to use CPM or modularity. If you do provide @@ -1451,14 +1454,14 @@ def community_leiden(self, objective_function="CPM", weights=None, @newfield ref: Reference @ref: Traag, V. A., Waltman, L., & van Eck, N. J. (2019). From Louvain - to Leiden: guaranteeing well-connected communities. Scientific + to Leiden: guaranteeing well-connected communities. Scientific reports, 9(1), 5233. doi: 10.1038/s41598-019-41695-z """ if objective_function.lower() not in ("cpm", "modularity"): raise ValueError("objective_function must be \"CPM\" or \"modularity\".") membership = GraphBase.community_leiden(self, - edge_weights=weights, node_weights=node_weights, + edge_weights=weights, node_weights=node_weights, resolution_parameter=resolution_parameter, normalize_resolution=(objective_function == "modularity"), beta=beta, initial_membership=initial_membership, n_iterations=n_iterations) @@ -3992,7 +3995,7 @@ def _ensure_set(value): # TODO(ntamas): some keyword arguments should be prioritized over # others; for instance, we have optimized code paths for _source and # _target in directed and undirected graphs if es.is_all() is True; - # these should be executed first. This matters only if there are + # these should be executed first. This matters only if there are # multiple keyword arguments and es.is_all() is True. for keyword, value in kwds.iteritems(): diff --git a/vendor/source/igraph b/vendor/source/igraph index 20ad88e75..48b1c706b 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 20ad88e759205e73d79f612663153ba97c56a866 +Subproject commit 48b1c706b4364c40678a3e01fde1766380dcfabd From 22df25dabd171c8e4c7286cfa21ef924f3894bc3 Mon Sep 17 00:00:00 2001 From: Puneetha Pai <21996583+PuneethaPai@users.noreply.github.com> Date: Mon, 29 Jun 2020 18:03:42 +0530 Subject: [PATCH 0226/1892] Weighted incidence (#303) --- src/igraph/__init__.py | 25 +++++++++++++ tests/test_bipartite.py | 80 ++++++++++++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a07c4473d..1991105d6 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2817,12 +2817,37 @@ def Incidence(klass, *args, **kwds): what the value is. If C{True}, non-zero entries are rounded up to the nearest integer and this will be the number of multiple edges created. + @param weighted: defines whether to create a weighted graph from the + incidence matrix. If it is c{None} then an unweighted graph is created + and the multiple argument is used to determine the edges of the graph. + If it is a string then for every non-zero matrix entry, an edge is created + and the value of the entry is added as an edge attribute named by the + weighted argument. If it is C{True} then a weighted graph is created and + the name of the edge attribute will be ‘weight’. + + @raise ValueError: if the weighted and multiple are passed together. @return: the graph with a binary vertex attribute named C{"type"} that stores the vertex classes. """ + weighted = kwds.pop("weighted", False) + is_weighted = True if weighted or weighted == "" else False + multiple = kwds.get("multiple", False) + if is_weighted and multiple: + raise ValueError("arguments weighted and multiple can not co-exist") result, types = klass._Incidence(*args, **kwds) result.vs["type"] = types + if is_weighted: + weight_attr = "weight" if weighted == True else weighted + mat = args[0] + _, rows, columns = result.get_incidence() + num_vertices_of_first_kind = len(rows) + for edge in result.es: + source, target = edge.tuple + if source in rows: + edge[weight_attr] = mat[source][target - num_vertices_of_first_kind] + else: + edge[weight_attr] = mat[target][source - num_vertices_of_first_kind] return result def bipartite_projection(self, types="type", multiplicity=True, probe1=-1, diff --git a/tests/test_bipartite.py b/tests/test_bipartite.py index 7ce1e0901..74a57a002 100644 --- a/tests/test_bipartite.py +++ b/tests/test_bipartite.py @@ -34,24 +34,80 @@ def testFullBipartite(self): def testIncidence(self): g = Graph.Incidence([[0, 1, 1], [1, 2, 0]]) - self.assertTrue(g.vcount() == 5 and g.ecount() == 4 and g.is_directed() == False) - self.assertTrue(g.vs["type"] == [False]*2 + [True]*3) - self.assertTrue(sorted(g.get_edgelist()) == [(0,3),(0,4),(1,2),(1,3)]) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3)]) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True) - self.assertTrue(g.vcount() == 5 and g.ecount() == 5 and g.is_directed() == False) - self.assertTrue(g.vs["type"] == [False]*2 + [True]*3) - self.assertTrue(sorted(g.get_edgelist()) == [(0,3),(0,4),(1,2),(1,3),(1,3)]) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 5, not g.is_directed()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3),(1,3)]) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True) - self.assertTrue(g.vcount() == 5 and g.ecount() == 4 and g.is_directed() == True) - self.assertTrue(g.vs["type"] == [False]*2 + [True]*3) - self.assertTrue(sorted(g.get_edgelist()) == [(0,3),(0,4),(1,2),(1,3)]) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3)]) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="in") - self.assertTrue(g.vcount() == 5 and g.ecount() == 4 and g.is_directed() == True) - self.assertTrue(g.vs["type"] == [False]*2 + [True]*3) - self.assertTrue(sorted(g.get_edgelist()) == [(2,1),(3,0),(3,1),(4,0)]) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(sorted(g.get_edgelist()), [(2,1),(3,0),(3,1),(4,0)]) + + # Create a weighted Graph + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted=True) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + + # Graph is not weighted when weighted=`str` + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="some_attr_name") + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), not g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es["some_attr_name"], [1, 1, 1, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + + # Graph is not weighted when weighted="" + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="") + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), not g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es[""], [1, 1, 1, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + + # Should work when directed=True and mode=out with weighted + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, weighted=True) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + + # Should work when directed=True and mode=in with weighted + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="in", weighted=True) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(2, 1), (3, 0), (3, 1), (4, 0)]) + + # Should work when directed=True and mode=all with weighted + g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="all", weighted=True) + self.assertTrue(all((g.vcount() == 5, g.ecount() == 8, g.is_directed(), g.is_weighted()))) + self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertListEqual(g.es["weight"], [1, 1, 1, 1, 1, 1, 2, 2]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (3, 1), (4, 0)]) + + def testIncidenceError(self): + msg = "arguments weighted and multiple can not co-exist" + with self.assertRaises(ValueError) as e: + Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted=True) + self.assertIn(msg, e.exception.args) + + with self.assertRaises(ValueError) as e: + Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="string") + self.assertIn(msg, e.exception.args) + + with self.assertRaises(ValueError) as e: + Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="") + self.assertIn(msg, e.exception.args) def testGetIncidence(self): mat = [[0, 1, 1], [1, 1, 0]] From c94925d1cfa1a1d910f6ab65a5966f05f7578069 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 14 Jul 2020 14:44:00 +0200 Subject: [PATCH 0227/1892] update vendored igraph to 0.8.2 to fix MSVC compilation error --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 48b1c706b..4986fba9e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 48b1c706b4364c40678a3e01fde1766380dcfabd +Subproject commit 4986fba9e43740acf2f02d081aea8dd221e2372c From afe2230bd7a0c2606ddab582e0804e2542404b48 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 14 Jul 2020 23:03:17 +1000 Subject: [PATCH 0228/1892] Conversion of objects to/from other libraries (#242) --- src/igraph/__init__.py | 176 ++++++++++++++ src/igraph/test/foreign.py | 480 +++++++++++++++++++++++++++++++++++++ tox.ini | 1 + 3 files changed, 657 insertions(+) create mode 100644 src/igraph/test/foreign.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 1991105d6..56938a1f1 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1742,6 +1742,182 @@ def maximum_bipartite_matching(self, types="type", weights=None, eps=None): ############################################# # Auxiliary I/O functions + def to_networkx(self): + """Converts the graph to networkx format""" + import networkx as nx + + # Graph: decide on directness and mutliplicity + if any(self.is_multiple()): + if self.is_directed(): + klass = nx.MultiDiGraph + else: + klass = nx.MultiGraph + else: + if self.is_directed(): + klass = nx.DiGraph + else: + klass = nx.Graph + + # Graph attributes + kw = {x: self[x] for x in self.attributes()} + g = klass(**kw) + + # Nodes and node attributes + for i, v in enumerate(self.vs): + g.add_node(i, **v.attributes()) + + # Edges and edge attributes + for edge in self.es: + g.add_edge(edge.source, edge.target, **edge.attributes()) + + return g + + @classmethod + def from_networkx(klass, g): + """Converts the graph from networkx + + Vertex names will be converted to "_nx_name" attribute and the vertices + will get new ids from 0 up (as standard in igraph). + + @param g: networkx Graph or DiGraph + """ + import networkx as nx + + # Graph attributes + gattr = dict(g.graph) + + # Nodes + vnames = list(g.nodes) + vattr = {'_nx_name': vnames} + vcount = len(vnames) + vd = {v: i for i, v in enumerate(vnames)} + + # NOTE: we do not need a special class for multigraphs, it is taken + # care for at the edge level rather than at the graph level. + graph = klass( + n=vcount, + directed=g.is_directed(), + graph_attrs=gattr, + vertex_attrs=vattr) + + # Node attributes + for v, datum in g.nodes.data(): + for key, val in datum.items(): + graph.vs[vd[v]][key] = val + + # Edges and edge attributes + # NOTE: we need to do both together to deal well with multigraphs + # Each e might have a length of 2 (graphs) or 3 (multigraphs, the + # third element is the "color" of the edge) + for e, (_, _, datum) in zip(g.edges, g.edges.data()): + eid = graph.add_edge(vd[e[0]], vd[e[1]]) + for key, val in datum.items(): + eid[key] = val + + return graph + + def to_graph_tool( + self, + graph_attributes=None, + vertex_attributes=None, + edge_attributes=None): + """Converts the graph to graph-tool + + @param graph_attributes: dictionary of graph attributes to transfer. + Keys are attributes from the graph, values are data types (see + below). C{None} means no graph attributes are transferred. + @param vertex_attributes: dictionary of vertex attributes to transfer. + Keys are attributes from the vertices, values are data types (see + below). C{None} means no vertex attributes are transferred. + @param edge_attributes: dictionary of edge attributes to transfer. + Keys are attributes from the edges, values are data types (see + below). C{None} means no vertex attributes are transferred. + + Data types: graph-tool only accepts specific data types. See the + following web page for a list: + + https://graph-tool.skewed.de/static/doc/quickstart.html + + NOTE: because of the restricted data types in graph-tool, vertex and + edge attributes require to be type-consistent across all vertices or + edges. If you set the property for only some vertices/edges, the other + will be tagged as None in python-igraph, so they can only be converted + to graph-tool with the type 'object' and any other conversion will + fail. + """ + import graph_tool as gt + + # Graph + g = gt.Graph(directed=self.is_directed()) + + # Nodes + vc = self.vcount() + g.add_vertex(vc) + + # Graph attributes + if graph_attributes is not None: + for x, dtype in graph_attributes.items(): + # Strange syntax for setting internal properties + gprop = g.new_graph_property(str(dtype)) + g.graph_properties[x] = gprop + g.graph_properties[x] = self[x] + + # Vertex attributes + if vertex_attributes is not None: + for x, dtype in vertex_attributes.items(): + # Create a new vertex property + g.vertex_properties[x] = g.new_vertex_property(str(dtype)) + # Fill the values from the igraph.Graph + for i in range(vc): + g.vertex_properties[x][g.vertex(i)] = self.vs[i][x] + + # Edges and edge attributes + if edge_attributes is not None: + for x, dtype in edge_attributes.items(): + g.edge_properties[x] = g.new_edge_property(str(dtype)) + for edge in self.es: + e = g.add_edge(edge.source, edge.target) + if edge_attributes is not None: + for x, dtype in edge_attributes.items(): + prop = edge.attributes().get(x, None) + g.edge_properties[x][e] = prop + + return g + + @classmethod + def from_graph_tool(klass, g): + """Converts the graph from graph-tool + + @param g: graph-tool Graph + """ + # Graph attributes + gattr = dict(g.graph_properties) + + # Nodes + vcount = g.num_vertices() + + # Graph + graph = klass( + n=vcount, + directed=g.is_directed(), + graph_attrs=gattr) + + # Node attributes + for key, val in g.vertex_properties.items(): + prop = val.get_array() + for i in range(vcount): + graph.vs[i][key] = prop[i] + + # Edges + # NOTE: the order the edges are put in is necessary to set the + # attributes later on + for e in g.edges(): + edge = graph.add_edge(int(e.source()), int(e.target())) + for key, val in g.edge_properties.items(): + edge[key] = val[e] + + return graph + def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds): """Writes the adjacency matrix of the graph to the given file diff --git a/src/igraph/test/foreign.py b/src/igraph/test/foreign.py new file mode 100644 index 000000000..af8c1c950 --- /dev/null +++ b/src/igraph/test/foreign.py @@ -0,0 +1,480 @@ +from __future__ import with_statement + +import io +import unittest +import warnings + +from igraph import * +from igraph.test.utils import temporary_file + + +try: + import networkx as nx +except ImportError: + nx = None + + +try: + import graph_tool as gt +except ImportError: + gt = None + + +class ForeignTests(unittest.TestCase): + def testDIMACS(self): + with temporary_file(u"""\ + c + c This is a simple example file to demonstrate the + c DIMACS input file format for minimum-cost flow problems. + c + c problem line : + p max 4 5 + c + c node descriptor lines : + n 1 s + n 4 t + c + c arc descriptor lines : + a 1 2 4 + a 1 3 2 + a 2 3 2 + a 2 4 3 + a 3 4 5 + """) as tmpfname: + graph = Graph.Read_DIMACS(tmpfname, False) + self.assertTrue(isinstance(graph, Graph)) + self.assertTrue(graph.vcount() == 4 and graph.ecount() == 5) + self.assertTrue(graph["source"] == 0 and graph["target"] == 3) + self.assertTrue(graph.es["capacity"] == [4,2,2,3,5]) + graph.write_dimacs(tmpfname) + + + def testDL(self): + with temporary_file(u"""\ + dl n=5 + format = fullmatrix + labels embedded + data: + larry david lin pat russ + Larry 0 1 1 1 0 + david 1 0 0 0 1 + Lin 1 0 0 1 0 + Pat 1 0 1 0 1 + russ 0 1 0 1 0 + """) as tmpfname: + g = Graph.Read_DL(tmpfname) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 5 and g.ecount() == 12) + self.assertTrue(g.is_directed()) + self.assertTrue(sorted(g.get_edgelist()) == \ + [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ + (3,2),(3,4),(4,1),(4,3)]) + + with temporary_file(u"""\ + dl n=5 + format = fullmatrix + labels: + barry,david + lin,pat + russ + data: + 0 1 1 1 0 + 1 0 0 0 1 + 1 0 0 1 0 + 1 0 1 0 1 + 0 1 0 1 0 + """) as tmpfname: + g = Graph.Read_DL(tmpfname) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 5 and g.ecount() == 12) + self.assertTrue(g.is_directed()) + self.assertTrue(sorted(g.get_edgelist()) == \ + [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ + (3,2),(3,4),(4,1),(4,3)]) + + with temporary_file(u"""\ + DL n=5 + format = edgelist1 + labels: + george, sally, jim, billy, jane + labels embedded: + data: + george sally 2 + george jim 3 + sally jim 4 + billy george 5 + jane jim 6 + """) as tmpfname: + g = Graph.Read_DL(tmpfname, False) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 5 and g.ecount() == 5) + self.assertTrue(not g.is_directed()) + self.assertTrue(sorted(g.get_edgelist()) == \ + [(0,1),(0,2),(0,3),(1,2),(2,4)]) + + def _testNCOLOrLGL(self, func, fname, can_be_reopened=True): + g = func(fname, names=False, weights=False, \ + directed=False) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 4 and g.ecount() == 5) + self.assertTrue(not g.is_directed()) + self.assertTrue(sorted(g.get_edgelist()) == \ + [(0,1),(0,2),(1,1),(1,3),(2,3)]) + self.assertTrue("name" not in g.vertex_attributes() and \ + "weight" not in g.edge_attributes()) + if not can_be_reopened: + return + + g = func(fname, names=False, \ + directed=False) + self.assertTrue("name" not in g.vertex_attributes() and \ + "weight" in g.edge_attributes()) + self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) + + g = func(fname, directed=False) + self.assertTrue("name" in g.vertex_attributes() and \ + "weight" in g.edge_attributes()) + self.assertTrue(g.vs["name"] == ["eggs", "spam", "ham", "bacon"]) + self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) + + def testNCOL(self): + with temporary_file(u"""\ + eggs spam 1 + ham eggs 2 + ham bacon + bacon spam 3 + spam spam""") as tmpfname: + self._testNCOLOrLGL(func=Graph.Read_Ncol, fname=tmpfname) + + with temporary_file(u"""\ + eggs spam + ham eggs + ham bacon + bacon spam + spam spam""") as tmpfname: + g = Graph.Read_Ncol(tmpfname) + self.assertTrue("name" in g.vertex_attributes() and \ + "weight" not in g.edge_attributes()) + + def testLGL(self): + with temporary_file(u"""\ + # eggs + spam 1 + # ham + eggs 2 + bacon + # bacon + spam 3 + # spam + spam""") as tmpfname: + self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=tmpfname) + + with temporary_file(u"""\ + # eggs + spam + # ham + eggs + bacon + # bacon + spam + # spam + spam""") as tmpfname: + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + g = Graph.Read_Lgl(tmpfname) + self.assertTrue("name" in g.vertex_attributes() and \ + "weight" not in g.edge_attributes()) + + # This is not an LGL file; we are testing error handling here + with temporary_file(u"""\ + 1 2 + 1 3 + """) as tmpfname: + with self.assertRaises(InternalError): + Graph.Read_Lgl(tmpfname) + + def testLGLWithIOModule(self): + with temporary_file(u"""\ + # eggs + spam 1 + # ham + eggs 2 + bacon + # bacon + spam 3 + # spam + spam""") as tmpfname: + with io.open(tmpfname, "r") as fp: + self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=fp, + can_be_reopened=False) + + def testAdjacency(self): + with temporary_file(u"""\ + # Test comment line + 0 1 1 0 0 0 + 1 0 1 0 0 0 + 1 1 0 0 0 0 + 0 0 0 0 2 2 + 0 0 0 2 0 2 + 0 0 0 2 2 0 + """) as tmpfname: + g = Graph.Read_Adjacency(tmpfname) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 6 and g.ecount() == 18 and + g.is_directed() and "weight" not in g.edge_attributes()) + g = Graph.Read_Adjacency(tmpfname, attribute="weight") + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 6 and g.ecount() == 12 and + g.is_directed() and g.es["weight"] == [1,1,1,1,1,1,2,2,2,2,2,2]) + + g.write_adjacency(tmpfname) + + def testPickle(self): + pickle = [128, 2, 99, 105, 103, 114, 97, 112, 104, 10, 71, 114, 97, 112, + 104, 10, 113, 1, 40, 75, 3, 93, 113, 2, 75, 1, 75, 2, 134, 113, 3, 97, + 137, 125, 125, 125, 116, 82, 113, 4, 125, 98, 46] + if sys.version_info > (3, 0): + pickle = bytes(pickle) + else: + pickle = "".join(map(chr, pickle)) + with temporary_file(pickle, "wb") as tmpfname: + g = Graph.Read_Pickle(pickle) + self.assertTrue(isinstance(g, Graph)) + self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and + not g.is_directed()) + g.write_pickle(tmpfname) + + @unittest.skipIf(nx is None, "test case depends on networkx") + def testGraphNetworkx(self): + # Undirected + g = Graph.Ring(10) + g['gattr'] = 'graph_attribute' + g.vs['vattr'] = list(range(g.vcount())) + g.es['eattr'] = list(range(len(g.es))) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertFalse(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual( + sorted(['vattr', '_nx_name']), + sorted(g2.vertex_attributes())) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + if an == 'vattr': + continue + self.assertEqual( + vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + for edge in g.es: + eid = g2.get_eid(edge.source, edge.target) + edge2 = g2.es[eid] + for an in edge.attribute_names(): + self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) + + # Directed + g = Graph.Ring(10, directed=True) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertTrue(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(nx is None, "test case depends on networkx") + def testMultigraphNetworkx(self): + # Undirected + g = Graph.Ring(10) + g.add_edge(0, 1) + g['gattr'] = 'graph_attribute' + g.vs['vattr'] = list(range(g.vcount())) + g.es['eattr'] = list(range(len(g.es))) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertFalse(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual( + sorted(['vattr', '_nx_name']), + sorted(g2.vertex_attributes())) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + # Testing parallel edges is a bit more tricky + edge2_found = set() + for edge in g.es: + # Go through all parallel edges between these two vertices + for edge2 in g2.es: + if edge2 in edge2_found: + continue + if edge.source != edge2.source: + continue + if edge.target != edge2.target: + continue + # Check all attributes between these two + for an in edge.attribute_names(): + if edge.attributes()[an] != edge2.attributes()[an]: + break + else: + # Correspondence found + edge2_found.add(edge2) + break + + else: + self.assertTrue(False) + + # Directed + g = Graph.Ring(10, directed=True) + g.add_edge(0, 1) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertTrue(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(gt is None, "test case depends on graph-tool") + def testGraphGraphTool(self): + # Undirected + g = Graph.Ring(10) + g['gattr'] = 'graph_attribute' + g.vs['vattr'] = list(range(g.vcount())) + g.es['eattr'] = list(range(len(g.es))) + + # Go to graph-tool and back + g_gt = g.to_graph_tool( + graph_attributes={'gattr': 'object'}, + vertex_attributes={'vattr': 'int'}, + edge_attributes={'eattr': 'int'}) + g2 = Graph.from_graph_tool(g_gt) + + self.assertFalse(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + self.assertEqual( + vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + for edge in g.es: + eid = g2.get_eid(edge.source, edge.target) + edge2 = g2.es[eid] + for an in edge.attribute_names(): + self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) + + # Directed + g = Graph.Ring(10, directed=True) + + # Go to graph-tool and back + g_gt = g.to_graph_tool() + + g2 = Graph.from_graph_tool(g_gt) + + self.assertTrue(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(gt is None, "test case depends on graph-tool") + def testMultigraphGraphTool(self): + # Undirected + g = Graph.Ring(10) + g.add_edge(0, 1) + g['gattr'] = 'graph_attribute' + g.vs['vattr'] = list(range(g.vcount())) + g.es['eattr'] = list(range(len(g.es))) + + # Go to graph-tool and back + g_gt = g.to_graph_tool( + graph_attributes={'gattr': 'object'}, + vertex_attributes={'vattr': 'int'}, + edge_attributes={'eattr': 'int'}) + g2 = Graph.from_graph_tool(g_gt) + + self.assertFalse(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + self.assertEqual( + vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + # Testing parallel edges is a bit more tricky + edge2_found = set() + for edge in g.es: + # Go through all parallel edges between these two vertices + for edge2 in g2.es: + if edge2 in edge2_found: + continue + if edge.source != edge2.source: + continue + if edge.target != edge2.target: + continue + # Check all attributes between these two + for an in edge.attribute_names(): + if edge.attributes()[an] != edge2.attributes()[an]: + break + else: + # Correspondence found + edge2_found.add(edge2) + break + + else: + self.assertTrue(False) + + # Directed + g = Graph.Ring(10, directed=True) + g.add_edge(0, 1) + + # Go to graph-tool and back + g_gt = g.to_graph_tool() + g2 = Graph.from_graph_tool(g_gt) + + self.assertTrue(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + +def suite(): + foreign_suite = unittest.makeSuite(ForeignTests) + return unittest.TestSuite([foreign_suite]) + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + +if __name__ == "__main__": + test() + diff --git a/tox.ini b/tox.ini index d2c11f3e3..4806db4af 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,7 @@ commands = python -m unittest deps = scipy; platform_python_implementation != "PyPy" numpy; platform_python_implementation != "PyPy" + networkx setenv = TESTING_IN_TOX=1 From 0ab5d0bb2bca4ea1468b7871b7d014a9a4587236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20K=C3=B6pcke?= Date: Tue, 14 Jul 2020 17:14:31 +0200 Subject: [PATCH 0229/1892] setup.py: Support MinGW Windows build (#297) --- setup.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 24806c863..75f644cc2 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ import shutil import subprocess import sys +import sysconfig from select import select @@ -38,6 +39,11 @@ ########################################################################### +def building_on_windows_msvc(): + """Returns True when using the non-MingW CPython interpreter on Windows""" + return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" + + def create_dir_unless_exists(*args): """Creates a directory unless it exists already.""" path = os.path.join(*args) @@ -308,7 +314,7 @@ def compile_in(self, build_folder, source_folder=None): if retcode: return False - building_on_windows = platform.system() == "Windows" + building_on_windows = building_on_windows_msvc() if building_on_windows: print("Creating Microsoft Visual Studio project...") @@ -361,7 +367,7 @@ def compile_in(self, build_folder, source_folder=None): def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries ): - building_on_windows = platform.system() == "Windows" + building_on_windows = building_on_windows_msvc() create_dir_unless_exists(install_folder) @@ -691,7 +697,7 @@ def process_args_from_command_line(self): def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" - building_on_windows = platform.system() == "Windows" + building_on_windows = building_on_windows_msvc() if not building_on_windows and "stdc++" not in self.libraries: self.libraries.append("stdc++") @@ -711,7 +717,7 @@ def replace_static_libraries(self, only=None, exclusions=None): def use_vendored_igraph(self): """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up the include and library paths and the library names accordingly.""" - building_on_windows = platform.system() == "Windows" + building_on_windows = building_on_windows_msvc() buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include")] buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] From 9ad245de5a3fa38bd31fc004c69bf1664a1b6740 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 14 Jul 2020 17:15:13 +0200 Subject: [PATCH 0230/1892] typo fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 75f644cc2..8aa98e59d 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ def building_on_windows_msvc(): - """Returns True when using the non-MingW CPython interpreter on Windows""" + """Returns True when using the non-MinGW CPython interpreter on Windows""" return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" From feb9d4b6ed832d9a1023e942b51b7d775cbbcbb6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 26 Jul 2020 11:21:04 +0200 Subject: [PATCH 0231/1892] document that canonical_permutation() supports colors, refs #311 --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index dac3b4740..43bb56614 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14825,7 +14825,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"canonical_permutation", (PyCFunction) igraphmodule_Graph_canonical_permutation, METH_VARARGS | METH_KEYWORDS, - "canonical_permutation(sh=\"fm\")\n\n" + "canonical_permutation(sh=\"fm\", color=None)\n\n" "Calculates the canonical permutation of a graph using the BLISS isomorphism\n" "algorithm.\n\n" "Passing the permutation returned here to L{Graph.permute_vertices()} will\n" From 3e4fa50433a311910fd32bb721316d7f2f85b3d1 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 27 Jul 2020 18:08:17 +1000 Subject: [PATCH 0232/1892] Loading graph from one or two dataframes (#309) Co-authored-by: Tamas Nepusz --- src/igraph/__init__.py | 79 ++++++++++++++++++++++++++++++++++++++++ tests/test_generators.py | 34 ++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 56938a1f1..876fa143f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3026,6 +3026,85 @@ def Incidence(klass, *args, **kwds): edge[weight_attr] = mat[target][source - num_vertices_of_first_kind] return result + @classmethod + def DataFrame(klass, edges, directed=True, vertices=None): + """DataFrame(directed=True, vertices=None) + + Generates a graph from one or two dataframes. + + @param edges: pandas DataFrame containing edges and metadata + @param directed: bool setting whether the graph is directed + @param vertices: None (default) or pandas DataFrame containing vertex + metadata. The first column must contain the unique ids of the + vertices and will be set as attribute 'name'. All other columns + will be added as vertex attributes by column name. + + @return: the graph + """ + import numpy as np + import pandas as pd + + if edges.shape[1] < 2: + raise ValueError("the data frame should contain at least two columns") + + # Handle if some elements are 'NA' + if edges.iloc[:, :2].isna().values.any(): + warn("In 'edges' NA elements were replaced with string \"NA\"") + edges = edges.copy() + edges.iloc[:, :2].fillna('NA', inplace=True) + + if (vertices is not None) and vertices.iloc[:, 0].isna().values.any(): + warn("In the first column of 'vertices' NA elements were replaced "+ + "with string \"NA\"") + vertices = vertices.copy() + vertices.iloc[:, 0].fillna('NA', inplace=True) + + names = np.unique(edges.values[:, :2]) + + if vertices is not None: + names_edges = names + if vertices.shape[1] < 1: + raise ValueError('vertices has no columns') + + names = vertices.iloc[:, 0].astype(str) + + if names.duplicated().any(): + raise ValueError('Vertex names must be unique') + + if len(np.setdiff1d(names_edges, names.values)): + raise ValueError( + 'Some vertices in the edge DataFrame are missing from vertices DataFrame') + + names = names.values + + # create graph + g = Graph(n=len(names), directed=directed) + + # vertex attributes + if vertices is not None: + cols = vertices.columns + for v, (_, attr) in zip(g.vs, vertices.iterrows()): + v['name'] = attr[cols[0]] + if len(cols) > 1: + for an in cols[1:]: + v[an] = attr[an] + + # create edge list + names_idx = pd.Series(index=names, data=np.arange(len(names))) + e0 = names_idx[edges.values[:, 0]] + e1 = names_idx[edges.values[:, 1]] + + # add the edges + g.add_edges(zip(e0, e1)) + + # edge attributes + if edges.shape[1] > 2: + for e, (_, attr) in zip(g.es, edges.iloc[:, 2:]): + for an, av in attr.items(): + e[an] = av + + return g + def bipartite_projection(self, types="type", multiplicity=True, probe1=-1, which="both"): """Projects a bipartite graph into two one-mode graphs. Edge directions diff --git a/tests/test_generators.py b/tests/test_generators.py index ddb64222e..a8e20d403 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -1,6 +1,14 @@ import unittest from igraph import * +try: + import numpy as np + import pandas as pd +except ImportError: + np = None + pd = None + + class GeneratorTests(unittest.TestCase): def testStar(self): g=Graph.Star(5, "in") @@ -164,7 +172,31 @@ def testWeightedAdjacency(self): self.assertTrue(el == [(0,1), (0,2), (1,0), (3,1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) - + @unittest.skipIf((np is None) or (pd is None), "test case depends on NumPy/Pandas") + def testDataFrame(self): + edges = pd.DataFrame( + [['C', 'A', 0.4], ['A', 'B', 0.1]], + columns=[0, 1, 'weight']) + + g = Graph.DataFrame(edges, directed=False) + self.assertTrue(g.es["weight"] == [0.1, 0.4]) + + vertices = pd.DataFrame( + [['A', 'blue'], ['B', 'yellow'], ['C', 'blue']], + columns=[0, 'color']) + + g = Graph.DataFrame(edges, directed=True, vertices=vertices) + self.assertTrue(g.vs['name'] == ['A', 'B', 'C']) + self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) + self.assertTrue(g.es["weight"] == [0.4, 0.1]) + + vertices.iloc[0, 0] = np.nan + g = Graph.DataFrame(edges, directed=True, vertices=vertices) + self.assertTrue(g.vs['name'] == ['NA', 'B', 'C']) + self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) + self.assertTrue(g.es["weight"] == [0.4, 0.1]) + + def suite(): generator_suite = unittest.makeSuite(GeneratorTests) return unittest.TestSuite([generator_suite]) From 316fa6b3b42e348561b8b199338422841aceeb3c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 27 Jul 2020 18:13:10 +1000 Subject: [PATCH 0233/1892] Documenting graph generation (#308) --- doc/source/generation.rst | 165 +++++++++++++++++++++++++++++++++++++- src/_igraph/graphobject.c | 16 ++-- tests/test_isomorphism.py | 2 +- 3 files changed, 173 insertions(+), 10 deletions(-) diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 475b50e56..3c42c39e4 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -1,5 +1,168 @@ Graph generation ================ -.. note:: TODO. This is a placeholder section; it is not written yet. +The first step of most |igraph| applications is to generate a graph. This section will explain a number of ways to do that. Read the `API documentation`_ for details on each function and class. +The :class:`Graph` class is the main object used to generate graphs: + +>>> from igraph import Graph + +From nodes and edges +++++++++++++++++++++ +Nodes are always numbered from 0 upwards. To create a generic graph with a specified number of nodes (e.g. 10) and a list of edges between them, you can use the generic constructor: + +>>> g = Graph(n=10, edges=[[0, 1], [2, 3]]) + +If not specified, the graph is undirected. To make a directed graph: + +>>> g = Graph(n=10, edges=[[0, 1], [2, 3]], directed=True) + +To specify edge weights (or any other vertex/edge attributes), use dictionaries: + +>>> g = Graph(n=4, edges=[[0, 1], [2, 3]], +>>> edge_attrs={'weight': [0.1, 0.2]}, +>>> vertex_attrs={'color': ['b', 'g', 'g', 'y']}) + +Variations on this constructor is :meth:`Graph.DictList`, which constructs a graph from a list-of-dictionaries representation, and :meth:`Graph.TupleList`, which constructs a graph from a list-of-tuples representation. + +To create a bipartite graph from a list of types and a list of edges, use :meth:`Graph.Bipartite`. + +From matrices ++++++++++++++ +To create a graph from an adjecency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`: + +>>> g = Graph.Adjacency([[0, 1, 1], [0, 0, 0], [0, 0, 1]]) + +This graph is directed and has edges `[0, 1]`, `[0, 2]` and `[2, 2]` (a loop). + +To create a bipartite graph from an incidence matrix, use :meth:`Graph.Incidence`: + +>>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) + +From file ++++++++++ +To load a graph from a preexisting file in any of the supported formats, use :meth:`Graph.Load`. For instance: + +>>> g = Graph.Load('myfile.gml', format='gml') + +If you don't specify a format, |igraph| will try to figure it out or, if that fails, it will complain. + +From external libraries ++++++++++++++++++++++++ +|igraph| can read from and write to `networkx`_ and `graph-tool`_ graph formats: + +>>> g = Graph.from_networkx(nwx) + +and + +>>> g = Graph.from_graph_tool(gt) + +From pandas DataFrame(s) +++++++++++++++++++++++++ +A common practice is to store edges in a `pandas.DataFrame`, where the two first columns are the source and target vertex ids, +and any additional column indicates edge attributes. You can generate a graph via :meth:`Graph.DataFrame`: + +>>> g = Graph.DataFrame(edges, directed=False) + +It is possible to set vertex attributes at the same time via a separate DataFrame. The first column is assumed to contain all +vertex ids (including any vertices without edges) and any additional columns are vertex attributes: + +>>> g = Graph.DataFrame(edges, directed=False, vertices=vertices) + +From a formula +++++++++++++++ +To create a graph from a string formula, use :meth:`Graph.Formula`, e.g.: + +>>> g = Graph.Formula('D-A:B:F:G, A-C-F-A, B-E-G-B, A-B, F-G, H-F:G, H-I-J') + +.. note:: This particular formula also assigns the 'name' attribute to vertices. + +Full graphs ++++++++++++ +To create a full graph, use :meth:`Graph.Full`: + +>>> g = Graph.Full(n=3) + +where `n` is the number of nodes. You can specify directedness and whether self loops are allowed: + +>>> g = Graph.Full(n=3, directed=True, loops=True) + +A similar method, :meth:`Graph.Full_Bipartite`, generates a full bipartite graph. Finally, the metho :meth:`Graph.Full_Citation` created the full citation graph, in which each vertex `i` has a directed edge to all vertices strictly smaller than `i`. + +Tree and star ++++++++++++++ +:meth:`Graph.Tree` can be used to generate regular trees, in which almost each vertex has the same number of children: + +>>> g = Graph.Tree(n=7, n_children=2) + +creates a tree with seven vertices - of which four are leaves. The root (0) has two children (1 and 2), each of which has two children (the four leaves). Regular trees can be directed or undirected (default). + +The method :meth:`Graph.Star` creates a star graph, which is a subtype of a tree. + +Lattice ++++++++ +:meth:`Graph.Lattice` creates a regular lattice of the chosen size. For instance: + +>>> g = Graph.Lattice(dim=[3, 3], circular=False) + +creates a 3x3 grid in two dimensions (9 vertices total). `circular` is used to connect each edge of the lattice back onto the other side, a process also known as "periodic boundary condition" that is sometimes helpful to smoothen out edge effects. + +The one dimensional case (path graph or ring) is important enough to deserve its own constructor :meth:`Graph.Ring`, which can be circular or not: + +>>> g = Graph.Ring(n=4, circular=False) + +Graph atlas ++++++++++++ +The book ‘An Atlas of Graphs’ by Roland C. Read and Robin J. Wilson contains all undirected graphs with up to seven vertices, numbered from 0 up to 1252. You can create any graph from this list by index with :meth:`Graph.Atlas`, e.g.: + +>>> g = Graph.Atlas(44) + +The graphs are listed: + + - in increasing order of number of nodes; + - for a fixed number of nodes, in increasing order of the number of edges; + - for fixed numbers of nodes and edges, in increasing order of the degree sequence, for example 111223 < 112222; + - for fixed degree sequence, in increasing number of automorphisms. + + +Famous graphs ++++++++++++++ +A curated list of famous graphs, which are often used in the literature for benchmarking and other purposes, is available on the `igraph C core manual `_. You can generate any graph in that list by name, e.g.: + +>>> g = Graph.Famous('Zachary') + +will teach you some about martial arts. + + +Random graphs ++++++++++++++ +Stochastic graphs can be created according to several different models or games: + + - Barabasi-Albert model: :meth:`Graph.Barabasi` + - Erdos-Renyi: :meth:`Graph.Erdos_Renyi` + - Watts-Strogatz :meth:`Graph.Watts_Strogatz` + - stochastic block model :meth:`Graph.SBM` + - forest fire game :meth:`Graph.Forest_Fire` + - random geometric graph :meth:`Graph.GRG` + - growing :meth:`Graph.Growing_Random` + - establishment game :meth:`Graph.Establishment` + - preference, the non-growing variant of establishment :meth:`Graph.Preference` + - asymmetric preference :meth:`Graph.Asymmetric_Prefernce` + - recent degree :meth:`Graph.Recent_Degree` + - k-regular (each node has degree K) :meth:`Graph.K_Regular` + - non-growing graph with edge probabilities proportional to node fitnesses :meth:`Graph.Static_Fitness` + - non-growing graph with prescribed power-law degree distribution(s) :meth:`Graph.Static_Power_Law` + - random graph with a given degree sequence :meth:`Graph.Degree_Sequence` + - bipartite :meth:`Graph.Random_Bipartite` + + +Other graphs +++++++++++++ +Finally, there are some ways of generating graphs that are not covered by the previous sections: + + - Kautz graphs :meth:`Graph.Kautz` + - De Bruijn graphs :meth:`Graph.De_Bruijn` + - Lederberg-Coxeter-Frucht graphs :meth:`Graph.LCF` + - graphs with a specified isomorphism class :meth:`Graph.Isoclass` + +.. _API documentation: https://igraph.org/python/doc/igraph-module.html diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 43bb56614..89ae5ba56 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2573,7 +2573,7 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, } /** \ingroup python_interface_graph - * \brief Generates a graph with a given isomorphy class + * \brief Generates a graph with a given isomorphism class * This is intended to be a class method in Python, so the first argument * is the type object and not the Python igraph object (because we have * to allocate that in this method). @@ -8306,7 +8306,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( } /** \ingroup python_interface_graph - * \brief Calculates the isomorphy class of a graph or its subgraph + * \brief Calculates the isomorphism class of a graph or its subgraph * \sa igraph_isoclass, igraph_isoclass_subgraph */ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, @@ -12738,9 +12738,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"Isoclass", (PyCFunction) igraphmodule_Graph_Isoclass, METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Isoclass(n, class, directed=False)\n\n" - "Generates a graph with a given isomorphy class.\n\n" + "Generates a graph with a given isomorphism class.\n\n" "@param n: the number of vertices in the graph (3 or 4)\n" - "@param class: the isomorphy class\n" + "@param class: the isomorphism class\n" "@param directed: whether the graph should be directed.\n"}, /* interface to igraph_watts_strogatz_game */ @@ -14037,7 +14037,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " motifs.\n" "@param callback: C{None} or a callable that will be called for every motif\n" " found in the graph. The callable must accept three parameters: the graph\n" - " itself, the list of vertices in the motif and the isomorphy class of the\n" + " itself, the list of vertices in the motif and the isomorphism class of the\n" " motif (see L{Graph.isoclass()}). The search will stop when the callback\n" " returns an object with a non-zero truth value or raises an exception.\n" "@return: the list of motifs if I{callback} is C{None}, or C{None} otherwise\n" @@ -14853,13 +14853,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"isoclass", (PyCFunction) igraphmodule_Graph_isoclass, METH_VARARGS | METH_KEYWORDS, "isoclass(vertices)\n\n" - "Returns the isomorphy class of the graph or its subgraph.\n\n" + "Returns the isomorphism class of the graph or its subgraph.\n\n" "Isomorphy class calculations are implemented only for graphs with\n" "3 or 4 vertices.\n\n" "@param vertices: a list of vertices if we want to calculate the\n" - " isomorphy class for only a subset of vertices. C{None} means to\n" + " isomorphism class for only a subset of vertices. C{None} means to\n" " use the full graph.\n" - "@return: the isomorphy class of the (sub)graph\n\n"}, + "@return: the isomorphism class of the (sub)graph\n\n"}, {"isomorphic", (PyCFunction) igraphmodule_Graph_isomorphic, METH_VARARGS | METH_KEYWORDS, "isomorphic(other)\n\n" diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index 9b8fa7437..b8e6c0256 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -22,7 +22,7 @@ def testIsomorphic(self): (5, 1), (5, 4), (5, 6), \ (7, 3), (7, 6), (7, 4)]) - # Test the isomorphy of g1 and g2 + # Test the isomorphism of g1 and g2 self.assertTrue(g1.isomorphic(g2)) self.assertTrue(g2.isomorphic_vf2(g1, return_mapping_21=True) \ == (True, None, [0, 2, 5, 7, 1, 3, 4, 6])) From 5adcf61b75a483903c0a363bd52449b666b4e345 Mon Sep 17 00:00:00 2001 From: Christopher Falter Date: Tue, 28 Jul 2020 10:00:07 -0400 Subject: [PATCH 0234/1892] Update tutorial.rst to stop using deprecated syntax for Graph.degree (#313) --- doc/source/tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index f95f4d7da..935029af9 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -369,7 +369,7 @@ the vertex) and :dfn:`out-degree` (the number of edges originating from the vert [3, 1, 4, 3, 2, 3, 2] If the graph was directed, we would have been able to calculate the in- and out-degrees -separately using ``g.degree(type="in")`` and ``g.degree(type="out")``. You can +separately using ``g.degree(mode="in")`` and ``g.degree(mode="out")``. You can also pass a single vertex ID or a list of vertex IDs to :meth:`~Graph.degree` if you want to calculate the degrees for only a subset of vertices: From 743ce690f7fcea94df72765190f623f348f7fad0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 31 Jul 2020 21:58:13 +1000 Subject: [PATCH 0235/1892] Add vertices/edges with attributes (#319) --- src/igraph/__init__.py | 43 +++++++++++++++++++++++++++++++++++------- tests/test_basic.py | 18 ++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 876fa143f..5f999b6a8 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -258,7 +258,7 @@ def add_edge(self, source, target, **kwds): edge[key] = value return edge - def add_edges(self, es): + def add_edges(self, es, attributes=None): """add_edges(es) Adds some edges to the graph. @@ -266,8 +266,17 @@ def add_edges(self, es): @param es: the list of edges to be added. Every edge is represented with a tuple containing the vertex IDs or names of the two endpoints. Vertices are enumerated from zero. + @params attributes: dict of sequences, all of length equal to the + number of edges to be added, containing the attributes of the new + edges. """ - return GraphBase.add_edges(self, es) + eid = self.ecount() + res = GraphBase.add_edges(self, es) + n = self.ecount() - eid + if (attributes is not None) and (n > 0): + for key, val in attributes.items(): + self.es[eid:][key] = val + return res def add_vertex(self, name=None, **kwds): """add_vertex(name=None, **kwds) @@ -291,7 +300,7 @@ def add_vertex(self, name=None, **kwds): vertex["name"] = name return vertex - def add_vertices(self, n): + def add_vertices(self, n, attributes=None): """add_vertices(n) Adds some vertices to the graph. @@ -300,13 +309,24 @@ def add_vertices(self, n): vertex to be added, or a sequence of strings, each corresponding to the name of a vertex to be added. Names will be assigned to the C{name} vertex attribute. + @params attributes: dict of sequences, all of length equal to the + number of vertices to be added, containing the attributes of the new + vertices. If n is a string (so a single vertex is added), then the + values of this dict are the attributes themselves, but if n=1 then + they have to be lists of length 1. + + Note that if n is a sequence of strings, indicating the names of the + new vertices, and attributes has a key 'name', the two conflict. In + that case the attribute will be applied. """ if isinstance(n, basestring): # Adding a single vertex with a name m = self.vcount() result = GraphBase.add_vertices(self, 1) self.vs[m]["name"] = n - return result + if attributes is not None: + for key, val in attributes.items(): + self.vs[m][key] = val elif hasattr(n, "__iter__"): m = self.vcount() if not hasattr(n, "__len__"): @@ -314,9 +334,18 @@ def add_vertices(self, n): else: names = n result = GraphBase.add_vertices(self, len(names)) - self.vs[m:]["name"] = names - return result - return GraphBase.add_vertices(self, n) + if len(names) > 0: + self.vs[m:]["name"] = names + if attributes is not None: + for key, val in attributes.items(): + self.vs[m:][key] = val + else: + result = GraphBase.add_vertices(self, n) + if (attributes is not None) and (n > 0): + m = self.vcount() - n + for key, val in attributes.items(): + self.vs[m:][key] = val + return result def adjacent(self, *args, **kwds): """adjacent(vertex, mode=OUT) diff --git a/tests/test_basic.py b/tests/test_basic.py index 88c7deea4..6deebd4d7 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -120,20 +120,26 @@ def testAddVertex(self): self.assertEqual( sorted(g.vertex_attributes()), ["ham", "name", "spam"] ) - self.assertEqual(g.vs["spam"], [None]*4 + ["cheese"]) - self.assertEqual(g.vs["ham"], [None]*4 + [42]) + self.assertEqual(g.vs["spam"], [None] * 4 + ["cheese"]) + self.assertEqual(g.vs["ham"], [None] * 4 + [42]) def testAddVertices(self): g = Graph() g.add_vertices(2) self.assertTrue(g.vcount() == 2 and g.ecount() == 0) + g.add_vertices("spam") self.assertTrue(g.vcount() == 3 and g.ecount() == 0) self.assertEqual(g.vs[2]["name"], "spam") + g.add_vertices(["bacon", "eggs"]) self.assertTrue(g.vcount() == 5 and g.ecount() == 0) self.assertEqual(g.vs[2:]["name"], ["spam", "bacon", "eggs"]) + g.add_vertices(2, attributes={'color': ['k', 'b']}) + self.assertEqual(g.vs[2:]["name"], ["spam", "bacon", "eggs", None, None]) + self.assertEqual(g.vs[5:]["color"], ["k", "b"]) + def testDeleteVertices(self): g = Graph([(0, 1), (1, 2), (2, 3), (0, 2), (3, 4), (4, 5)]) self.assertEqual(6, g.vcount()) @@ -208,6 +214,14 @@ def testAddEdges(self): (0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3) ]) + g.add_edges([(0, 0), (1, 1)], attributes={'color': ['k', 'b']}) + self.assertEqual(g.get_edgelist(), [ + (0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3), (0, 0), (1, 1), + ]) + self.assertEqual( + g.es['color'], + [None, None, None, None, None, None, 'k', 'b']) + def testDeleteEdges(self): g = Graph.Famous("petersen") g.vs["name"] = list("ABCDEFGHIJ") From 319aa82ceff0f62ebdb1eeac7355e842e8dbdf7f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 31 Jul 2020 14:15:21 +0200 Subject: [PATCH 0236/1892] add Python 3.8 to tox virtualenvs --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4806db4af..e47224111 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py35, py36, py37, pypy, pypy3 +envlist = py27, py35, py36, py37, py38, pypy, pypy3 [testenv] commands = python -m unittest From 52678603271fcb3151abc57fca388c585689b596 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 4 Aug 2020 04:14:30 +1000 Subject: [PATCH 0237/1892] DFS and DFS iterator (#315) --- src/_igraph/dfsiter.c | 295 +++++++++++++++++++++++++++++++++++++ src/_igraph/dfsiter.h | 53 +++++++ src/_igraph/graphobject.c | 29 ++++ src/_igraph/igraphmodule.c | 4 + src/igraph/__init__.py | 44 ++++++ tests/test_iterators.py | 42 +++++- 6 files changed, 459 insertions(+), 8 deletions(-) create mode 100644 src/_igraph/dfsiter.c create mode 100644 src/_igraph/dfsiter.h diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c new file mode 100644 index 000000000..d7d8105af --- /dev/null +++ b/src/_igraph/dfsiter.c @@ -0,0 +1,295 @@ +/* -*- mode: C -*- */ +/* + IGraph library. + Copyright (C) 2020 The igraph development team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#include "dfsiter.h" +#include "common.h" +#include "error.h" +#include "py2compat.h" +#include "vertexobject.h" + +/** + * \ingroup python_interface + * \defgroup python_interface_dfsiter DFS iterator object + */ + +PyTypeObject igraphmodule_DFSIterType; + +/** + * \ingroup python_interface_dfsiter + * \brief Allocate a new DFS iterator object for a given graph and a given root + * \param g the graph object being referenced + * \param vid the root vertex index + * \param advanced whether the iterator should be advanced (returning distance and parent as well) + * \return the allocated PyObject + */ +PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_neimode_t mode, igraph_bool_t advanced) { + igraphmodule_DFSIterObject* o; + long int no_of_nodes, r; + + o=PyObject_GC_New(igraphmodule_DFSIterObject, &igraphmodule_DFSIterType); + Py_INCREF(g); + o->gref=g; + o->graph=&g->g; + + if (!PyInt_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { + PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); + return NULL; + } + + no_of_nodes=igraph_vcount(&g->g); + o->visited=(char*)calloc(no_of_nodes, sizeof(char)); + if (o->visited == 0) { + PyErr_SetString(PyExc_MemoryError, "out of memory"); + return NULL; + } + + if (igraph_stack_init(&o->stack, 100)) { + PyErr_SetString(PyExc_MemoryError, "out of memory"); + return NULL; + } + if (igraph_vector_init(&o->neis, 0)) { + PyErr_SetString(PyExc_MemoryError, "out of memory"); + igraph_stack_destroy(&o->stack); + return NULL; + } + + if (PyInt_Check(root)) { + r=PyInt_AsLong(root); + } else { + r = ((igraphmodule_VertexObject*)root)->idx; + } + /* push the root onto the stack */ + if (igraph_stack_push(&o->stack, r) || + igraph_stack_push(&o->stack, 0) || + igraph_stack_push(&o->stack, -1)) { + igraph_stack_destroy(&o->stack); + igraph_vector_destroy(&o->neis); + PyErr_SetString(PyExc_MemoryError, "out of memory"); + return NULL; + } + o->visited[r] = 1; + + if (!igraph_is_directed(&g->g)) mode=IGRAPH_ALL; + o->mode=mode; + o->advanced=advanced; + + PyObject_GC_Track(o); + + RC_ALLOC("DFSIter", o); + + return (PyObject*)o; +} + +/** + * \ingroup python_interface_dfsiter + * \brief Support for cyclic garbage collection in Python + * + * This is necessary because the \c igraph.DFSIter object contains several + * other \c PyObject pointers and they might point back to itself. + */ +int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, + visitproc visit, void *arg) { + int vret; + + RC_TRAVERSE("DFSIter", self); + + if (self->gref) { + vret=visit((PyObject*)self->gref, arg); + if (vret != 0) return vret; + } + + return 0; +} + +/** + * \ingroup python_interface_dfsiter + * \brief Clears the iterator's subobject (before deallocation) + */ +int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { + PyObject *tmp; + + PyObject_GC_UnTrack(self); + + tmp=(PyObject*)self->gref; + self->gref = NULL; + Py_XDECREF(tmp); + + igraph_stack_destroy(&self->stack); + igraph_vector_destroy(&self->neis); + free(self->visited); + self->visited = 0; + + return 0; +} + +/** + * \ingroup python_interface_dfsiter + * \brief Deallocates a Python representation of a given DFS iterator object + */ +void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { + igraphmodule_DFSIter_clear(self); + + RC_DEALLOC("DFSIter", self); + + PyObject_GC_Del(self); +} + +PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { + Py_INCREF(self); + return (PyObject*)self; +} + +PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { + /* the design is to return the top of the stack and then proceed until + * we have found an unvisited neighbor and push that on top */ + igraph_integer_t parent_out, dist_out, vid_out; + igraph_bool_t any = 0; + + /* nothing on the stack, end of iterator */ + if(igraph_stack_empty(&self->stack)) { + return NULL; + } + + /* peek at the top element on the stack + * because we save three things, pop 3 in inverse order and push them back */ + parent_out = (igraph_integer_t)igraph_stack_pop(&self->stack); + dist_out = (igraph_integer_t)igraph_stack_pop(&self->stack); + vid_out = (igraph_integer_t)igraph_stack_pop(&self->stack); + igraph_stack_push(&self->stack, (long int) vid_out); + igraph_stack_push(&self->stack, (long int) dist_out); + igraph_stack_push(&self->stack, (long int) parent_out); + + /* look for neighbors until you found one or until you have exausted the graph */ + while (!any && !igraph_stack_empty(&self->stack)) { + igraph_integer_t parent = (igraph_integer_t)igraph_stack_pop(&self->stack); + igraph_integer_t dist = (igraph_integer_t)igraph_stack_pop(&self->stack); + igraph_integer_t vid = (igraph_integer_t)igraph_stack_pop(&self->stack); + igraph_stack_push(&self->stack, (long int) vid); + igraph_stack_push(&self->stack, (long int) dist); + igraph_stack_push(&self->stack, (long int) parent); + long int i; + /* the values above are returned at at this stage. However, we must + * prepare for the next iteration by putting the next unvisited + * neighbor onto the stack */ + if (igraph_neighbors(self->graph, &self->neis, vid, self->mode)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + for (i=0; ineis); i++) { + igraph_integer_t neighbor = (igraph_integer_t)VECTOR(self->neis)[i]; + /* new neighbor, push the next item onto the stack */ + if (self->visited[neighbor] == 0) { + any = 1; + self->visited[neighbor]=1; + if (igraph_stack_push(&self->stack, neighbor) || + igraph_stack_push(&self->stack, dist+1) || + igraph_stack_push(&self->stack, vid)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + break; + } + } + /* no new neighbors, end of subtree */ + if (!any) { + igraph_stack_pop(&self->stack); + igraph_stack_pop(&self->stack); + igraph_stack_pop(&self->stack); + } + } + + /* no matter what the stack situation is: that is a worry for the next cycle + * now just return the top of the stack as it was at the function entry */ + PyObject *vertexobj = igraphmodule_Vertex_New(self->gref, vid_out); + if (self->advanced) { + PyObject *parentobj; + if (!vertexobj) + return NULL; + if (parent_out >= 0) { + parentobj = igraphmodule_Vertex_New(self->gref, parent_out); + if (!parentobj) + return NULL; + } else { + Py_INCREF(Py_None); + parentobj=Py_None; + } + return Py_BuildValue("NlN", vertexobj, (long int)dist_out, parentobj); + } else { + return vertexobj; + } +} + +/** + * \ingroup python_interface_dfsiter + * Method table for the \c igraph.DFSIter object + */ +PyMethodDef igraphmodule_DFSIter_methods[] = { + {NULL} +}; + +/** \ingroup python_interface_dfsiter + * Python type object referencing the methods Python calls when it performs various operations on + * a DFS iterator of a graph + */ +PyTypeObject igraphmodule_DFSIterType = +{ + PyVarObject_HEAD_INIT(0, 0) + "igraph.DFSIter", // tp_name + sizeof(igraphmodule_DFSIterObject), // tp_basicsize + 0, // tp_itemsize + (destructor)igraphmodule_DFSIter_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, /* tp_compare (2.x) / tp_reserved (3.x) */ + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, // tp_flags + "igraph DFS iterator object", // tp_doc + (traverseproc) igraphmodule_DFSIter_traverse, /* tp_traverse */ + (inquiry) igraphmodule_DFSIter_clear, /* tp_clear */ + 0, // tp_richcompare + 0, // tp_weaklistoffset + (getiterfunc)igraphmodule_DFSIter_iter, /* tp_iter */ + (iternextfunc)igraphmodule_DFSIter_iternext, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ +}; + diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h new file mode 100644 index 000000000..0a094c592 --- /dev/null +++ b/src/_igraph/dfsiter.h @@ -0,0 +1,53 @@ +/* -*- mode: C -*- */ +/* + IGraph library. + Copyright (C) 2020 The igraph development team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#ifndef PYTHON_DFSITER_H +#define PYTHON_DFSITER_H + +#include +#include "graphobject.h" + +/** + * \ingroup python_interface_dfsiter + * \brief A structure representing a DFS iterator of a graph + */ +typedef struct +{ + PyObject_HEAD + igraphmodule_GraphObject* gref; + igraph_stack_t stack; + igraph_vector_t neis; + igraph_t *graph; + char *visited; + igraph_neimode_t mode; + igraph_bool_t advanced; +} igraphmodule_DFSIterObject; + +PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *o, igraph_neimode_t mode, igraph_bool_t advanced); +int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, + visitproc visit, void *arg); +int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self); +void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self); + +extern PyTypeObject igraphmodule_DFSIterType; + +#endif diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 89ae5ba56..bb1789bd7 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -23,6 +23,7 @@ #include "attributes.h" #include "arpackobject.h" #include "bfsiter.h" +#include "dfsiter.h" #include "common.h" #include "convert.h" #include "edgeseqobject.h" @@ -9920,6 +9921,23 @@ PyObject *igraphmodule_Graph_unfold_tree(igraphmodule_GraphObject * self, return Py_BuildValue("NN", result_o, mapping_o); } +/** \ingroup python_interface_graph + * \brief Constructs a depth first search (DFS) iterator of the graph + */ +PyObject *igraphmodule_Graph_dfsiter(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + char *kwlist[] = { "vid", "mode", "advanced", NULL }; + PyObject *root, *adv = Py_False, *mode_o = Py_None; + igraph_neimode_t mode = IGRAPH_OUT; + + if (!PyArg_ParseTupleAndKeywords + (args, kwds, "O|OO", kwlist, &root, &mode_o, &adv)) + return NULL; + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + return igraphmodule_DFSIter_new(self, root, mode, PyObject_IsTrue(adv)); +} + /********************************************************************** * Dominator * **********************************************************************/ @@ -14517,6 +14535,17 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returns the distance of the vertex from the root and the\n" " parent of the vertex in the BFS tree as well.\n" "@return: the BFS iterator as an L{igraph.BFSIter} object.\n"}, + {"dfsiter", (PyCFunction) igraphmodule_Graph_dfsiter, + METH_VARARGS | METH_KEYWORDS, + "dfsiter(vid, mode=OUT, advanced=False)\n\n" + "Constructs a depth first search (DFS) iterator of the graph.\n\n" + "@param vid: the root vertex ID\n" + "@param mode: either L{IN} or L{OUT} or L{ALL}.\n" + "@param advanced: if C{False}, the iterator returns the next\n" + " vertex in DFS order in every step. If C{True}, the iterator\n" + " returns the distance of the vertex from the root and the\n" + " parent of the vertex in the DFS tree as well.\n" + "@return: the DFS iterator as an L{igraph.DFSIter} object.\n"}, ///////////////// // CONVERSIONS // diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 05a0d16ec..fcd79063e 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -26,6 +26,7 @@ #include "arpackobject.h" #include "attributes.h" #include "bfsiter.h" +#include "dfsiter.h" #include "common.h" #include "convert.h" #include "edgeobject.h" @@ -764,6 +765,8 @@ extern PyObject* igraphmodule_arpack_options_default; INITERROR; if (PyType_Ready(&igraphmodule_BFSIterType) < 0) INITERROR; + if (PyType_Ready(&igraphmodule_DFSIterType) < 0) + INITERROR; if (PyType_Ready(&igraphmodule_ARPACKOptionsType) < 0) INITERROR; @@ -783,6 +786,7 @@ extern PyObject* igraphmodule_arpack_options_default; /* Add the types to the core module */ PyModule_AddObject(m, "GraphBase", (PyObject*)&igraphmodule_GraphType); PyModule_AddObject(m, "BFSIter", (PyObject*)&igraphmodule_BFSIterType); + PyModule_AddObject(m, "DFSIter", (PyObject*)&igraphmodule_DFSIterType); PyModule_AddObject(m, "ARPACKOptions", (PyObject*)&igraphmodule_ARPACKOptionsType); PyModule_AddObject(m, "Edge", (PyObject*)&igraphmodule_EdgeType); PyModule_AddObject(m, "EdgeSeq", (PyObject*)&igraphmodule_EdgeSeqType); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 5f999b6a8..96814300f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3240,6 +3240,50 @@ def get_incidence(self, types="type", *args, **kwds): """ return super(Graph, self).get_incidence(types, *args, **kwds) + ########################### + # DFS (C version will come soon) + def dfs(self, vid, mode=OUT): + """Conducts a depth first search (DFS) on the graph. + + @param vid: the root vertex ID + @param mode: either L{IN} or L{OUT} or L{ALL}, ignored + for undirected graphs. + @return: a tuple with the following items: + - The vertex IDs visited (in order) + - The parent of every vertex in the DFS + """ + nv = self.vcount() + added = [False for v in range(nv)] + stack = [] + + # prepare output + vids = [] + parents = [] + + # ok start from vid + stack.append(vid) + vids.append(vid) + parents.append(vid) + added[vid] = True + + # go down the rabbit hole + while stack: + vid = stack[-1] + neighbors = self.neighbors(vid, mode=mode) + for neighbor in neighbors: + if not added[neighbor]: + # Add hanging subtree neighbor + stack.append(neighbor) + vids.append(neighbor) + parents.append(vid) + added[neighbor] = True + break + else: + # No neighbor found, end of subtree + stack.pop() + + return (vids, parents) + ########################### # ctypes support diff --git a/tests/test_iterators.py b/tests/test_iterators.py index a229e4383..7bd6d81bf 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -3,13 +3,40 @@ class IteratorTests(unittest.TestCase): def testBFS(self): - g=Graph.Tree(10, 2) - vs=[v.index for v in g.bfsiter(0)] + g = Graph.Tree(10, 2) + vs, layers, ps = g.bfs(0) self.assertEqual(vs, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - vs=[(v.index,dist,parent) for v,dist,parent in g.bfsiter(0, advanced=True)] - vs=[(v,d,p.index) for v,d,p in vs if p != None] - self.assertEqual(vs, [(1,1,0), (2,1,0), (3,2,1), (4,2,1), \ - (5,2,2), (6,2,2), (7,3,3), (8,3,3), (9,3,4)]) + self.assertEqual(ps, [0, 0, 0, 1, 1, 2, 2, 3, 3, 4]) + + def testBFSIter(self): + g = Graph.Tree(10, 2) + vs = [v.index for v in g.bfsiter(0)] + self.assertEqual(vs, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + vs = [(v.index, d, p) for v, d, p in g.bfsiter(0, advanced=True)] + vs = [(v, d, p.index) for v, d, p in vs if p is not None] + self.assertEqual( + vs, + [(1, 1, 0), (2, 1, 0), (3, 2, 1), + (4, 2, 1), (5, 2, 2), (6, 2, 2), + (7, 3, 3), (8, 3, 3), (9, 3, 4)]) + + def testDFS(self): + g = Graph.Tree(10, 2) + vs, ps = g.dfs(0) + self.assertEqual(vs, [0, 1, 3, 7, 8, 4, 9, 2, 5, 6]) + self.assertEqual(ps, [0, 0, 1, 3, 3, 1, 4, 0, 2, 2]) + + def testDFSIter(self): + g = Graph.Tree(10, 2) + vs = [v.index for v in g.dfsiter(0)] + self.assertEqual(vs, [0, 1, 3, 7, 8, 4, 9, 2, 5, 6]) + vs = [(v.index, d, p) for v, d, p in g.dfsiter(0, advanced=True)] + vs = [(v, d, p.index) for v, d, p in vs if p is not None] + self.assertEqual( + vs, + [(1, 1, 0), (3, 2, 1), (7, 3, 3), + (8, 3, 3), (4, 2, 1), (9, 3, 4), + (2, 1, 0), (5, 2, 2), (6, 2, 2)]) def suite(): @@ -19,7 +46,6 @@ def suite(): def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + if __name__ == "__main__": test() - From 5f7530a944a9354d39a61e091b26104d9af603c7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 4 Aug 2020 04:21:17 +1000 Subject: [PATCH 0238/1892] Docs on graph analysis (#314) --- doc/source/analysis.rst | 427 +++++++++++++++++++++++++++++++++++++- doc/source/generation.rst | 4 + src/_igraph/graphobject.c | 2 +- 3 files changed, 431 insertions(+), 2 deletions(-) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 8b0ff457f..a4ab5ec74 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -1,5 +1,430 @@ Graph analysis ============== +|igraph| enables analysis of graphs/networks from simple operations such as adding and removing nodes to complex theoretical constructs such as community detection. Read the `API documentation`_ for details on each function and class. -.. note:: TODO. This is a placeholder section; it is not written yet. +The context for the following examples will be to import |igraph| (commonly as `ig`), have the :class:`Graph` class and to have one or more graphs available: +>>> import igraph as ig +>>> from igraph import Graph +>>> g = Graph(edges=[[0, 1], [2, 3]]) + +To get a summary representation of the graph, use :meth:`Graph.summary`. For instance + +>>> g.summary(verbosity=1) + +will provide a fairly detailed description. + +To copy a graph, use :meth:`Graph.copy`. This is a "shallow" copy: any mutable objects in the attributes are not copied (they would refer to the same instance). +If you want to copy a graph including all its attributes, use Python's `deepcopy` module. + +Vertices and edges ++++++++++++++++++++++++++++ +Vertices are numbered 0 to `n-1`, where n is the number of vertices in the graph. These are called the "vertex ids". +To count vertices, use :meth:`Graph.vcount`: + +>>> n = g.vcount() + +Edges also have ids from 0 to `m-1` and are counted by :meth:`Graph.ecount`: + +>>> m = g.ecount() + +To get a sequence of vertices, use their ids and :attr:`Graph.vs`: + +>>> for v in g.vs: +>>> print(v) + +Similarly for edges, use :attr:`Graph.es`: + +>>> for e in g.es: +>>> print(e) + +You can index and slice vertices and edges similar to a list: + +>>> g.vs[:4] +>>> g.vs[0, 2, 4] +>>> g.es[3] + +.. note:: The `vs` and `es` attributes are special sequences with their own useful methods. See `API documentation`_ for a full list. + +If you prefer a vanilla edge list, you can use :meth:`Graph.get_edge_list`. + +Incidence +++++++++++++++++++++++++++++++ +To get the vertices at the two ends of an edge, use :attr:`Edge.source` and :attr:`Edge.target`: + +>>> e = g.es[0] +>>> v1, v2 = e.source, e.target + +Vice versa, to get the edge if from the source and target vertices, you can use :meth:`Graph.get_eid` or, for multiple pairs of source/targets, +:meth:`Graph.get_eids`. The boolean version, asking whether two vertices are directly connected, is :meth:`Graph.are_connected`. + +To get the edges incident on a vertex, you can use :meth:`Vertex.incident`, :meth:`Vertex.out_edges` and +:meth:`Vertex.in_edges`. The three are equivalent on undirected graphs but not directed ones, of course: + +>>> v = g.vs[0] +>>> edges = v.incident() + +The :meth:`Graph.incident` function fulfills the same purpose with a slightly different syntax based on vertex ids: + +>>> edges = g.incident(0) + +To get the full adjacency/incidence list representation of the graph, use :meth:`Graph.get_adjlist`, :meth:`Graph.g.get_inclist()` or, for a bipartite graph, :meth:`Graph.get_incidence`. + +Neighborhood ++++++++++++++ +To compute the neighbors, successors, and predecessors, the methods :meth:`Graph.neighbors`, :meth:`Graph.successors` and +:meth:`Graph.predecessors` are available. The three give the same answer in undirected graphs and have a similar dual syntax: + +>>> neis = g.vs[0].neighbors() +>>> neis = g.neighbors(0) + +To get the list of vertices within a certain distance from one or more initial vertices, you can use :meth:`Graph.neighborhood`: + +>>> g.neighborhood([0, 1], order=2) + +and to find the neighborhood size, there is :meth:`Graph.neighborhood_size`. + +Degrees ++++++++ +To compute the degree, in-degree, or out-degree of a node, use :meth:`Vertex.degree`, :meth:`Vertex.indegree`, and :meth:`Vertex.outdegree`: + +>>> deg = g.vs[0].degree() +>>> deg = g.degree(0) + +To compute the max degree in a list of vertices, use :meth:`Graph.maxdegree`. + +:meth:`Graph.knn` computes the average degree of the neighbors. + +Adding and removing vertices and edges +++++++++++++++++++++++++++++++++++++++ + +To add nodes to a graph, use :meth:`Graph.add_vertex` and :meth:`Graph.add_vertices`: + +>>> g.add_vertex() +>>> g.add_vertices(5) + +This changes the graph `g` in place. You can specify the name of the vertices if you wish. + +To remove nodes, use :meth:`Graph.delete_vertices`: + +>>> g.delete_vertices([1, 2]) + +Again, you can specify the names or the actual :class:`Vertex` objects instead. + +To add edges, use :meth:`Graph.add_edge` and :meth:`Graph.add_edges`: + +>>> g.add_edge(0, 2) +>>> g.add_edges([(0, 2), (1, 3)]) + +To remove edges, use :meth:`Graph.delete_edges`: + +>>> g.delete_edges([0, 5]) # remove by edge id + +You can also remove edges between source and target nodes. + +To contract vertices, use :meth:`Graph.contract_vertices`. Edges between contracted vertices will become loops. + +Graph operators ++++++++++++++++++ +It is possible to compute the union, intersection, difference, and other set operations (operators) between graphs. + +To compute the union of the graphs (nodes/edges in either are kept): + +>>> gu = ig.union([g, g2, g3]) + +Similarly for the intersection (nodes/edges present in all are kept): + +>>> gu = ig.intersection([g, g2, g3]) + +These two operations preserve attributes and can be performed with a few variations. The most important one is that vertices can be matched across the graphs by id (number) or by name. + +These and other operations are also available as methods of the :class:`Graph` class: + +>>> g.union(g2) +>>> g.intersection(g2) +>>> g.disjoint_union(g2) +>>> g.difference(g2) +>>> g.complementer() # complement graph, same nodes but missing edges + +and even as numerical operators: + +>>> g |= g2 +>>> g_intersection = g and g2 + +Topological sorting ++++++++++++++++++++ +To sort a graph topologically, use :meth:`Graph.topological_sorting`: + +>>> g = ig.Graph.Tree(10, 2, mode=ig.TREE_OUT) +>>> g.topological_sorting() + +Graph traversal ++++++++++++++++++++++ +A common operation is traversing the graph. |igraph| currently exposes breadth-first search (BFS) via :meth:`Graph.bfs` and :meth:`Graph.bfsiter`: + +>>> [vertices, layers, parents] = g.bfs() +>>> it = g.bfsiter() # Lazy version + +Depth-first search has a similar infrastructure via :meth:`Graph.dfs` and :meth:`Graph.dfsiter`: + +>>> [vertices, parents] = g.dfs() +>>> it = g.dfsiter() # Lazy version + +To perform a random walk from a certain vertex, use :meth:`Graph.random_walk`: + +>>> vids = g.random_walk(0, 3) + +Pathfinding and cuts +++++++++++++++++++++ +Several pathfinding algorithms are available: + +- :meth:`Graph.shortest_paths` or :meth:`Graph.get_shortest_paths` +- :meth:`Graph.get_all_shortest_paths` +- :meth:`Graph.get_all_simple_paths` +- :meth:`Graph.spanning_tree` finds a minimum spanning tree + +As well as functions related to cuts and paths: + +- :meth:`Graph.mincut` calculates the minimum cut between the source and target vertices +- :meth:`Graph.st_mincut` - as previous one, but returns a simpler data structure +- :meth:`Graph.mincut_value` - as previous one, but returns only the value +- :meth:`Graph.all_st_cuts` +- :meth:`Graph.all_st_mincuts` +- :meth:`Graph.edge_connectivity` or :meth:`Graph.edge_disjoint_paths` or :meth:`Graph.adhesion` +- :meth:`Graph.vertex_connectivity` or :meth:`Graph.cohesion` + +See also the section on flow. + +Global properties ++++++++++++++++++++++ +A number of global graph measures are available. + +Basic: + +- :meth:`Graph.diameter` or :meth:`Graph.get_diameter` +- :meth:`Graph.girth` +- :meth:`Graph.radius` +- :meth:`Graph.average_path_length` + +Distributions: + +- :meth:`Graph.degree_distribution` +- :meth:`Graph.path_length_hist` + +Connectedness: + +- :meth:`Graph.all_minimal_st_separators` +- :meth:`Graph.minimum_size_separators` +- :meth:`Graph.cut_vertices` or :meth:`Graph.articulation_points` + +Cliques and motifs: + +- :meth:`Graph.clique_number` (aka :meth:`Graph.omega`) +- :meth:`Graph.cliques` +- :meth:`Graph.maximal_cliques` +- :meth:`Graph.largest_cliques` +- :meth:`Graph.motifs_randesu` and :meth:`Graph.motifs_randesu_estimate` +- :meth:`Graph.motifs_randesu_no` counts the number of motifs + +Directed acyclic graphs: + +- :meth:`Graph.is_dag` +- :meth:`Graph.feedback_arc_set` +- :meth:`Graph.topological_sorting` + +Optimality: + +- :meth:`Graph.farthest_points` +- :meth:`Graph.modularity` +- :meth:`Graph.maximal_cliques` +- :meth:`Graph.largest_cliques` +- :meth:`Graph.independence_number` (aka :meth:`Graph.alpha`) +- :meth:`Graph.maximal_independent_vertex_sets` +- :meth:`Graph.largest_independent_vertex_sets` +- :meth:`Graph.mincut` +- :meth:`Graph.mincut_value` +- :meth:`Graph.feedback_arc_set` +- :meth:`Graph.maximum_bipartite_matching` (bipartite graphs) + +Other complex measures are: + +- :meth:`Graph.assortativity` +- :meth:`Graph.assortativity_degree` +- :meth:`Graph.assortativity_nominal` +- :meth:`Graph.density` +- :meth:`Graph.transitivity_undirected` +- :meth:`Graph.transitivity_avglocal_undirected` +- :meth:`Graph.dyad_census` +- :meth:`Graph.triad_census` +- :meth:`Graph.reciprocity` (directed graphs) +- :meth:`Graph.isoclass` (only 3 or 4 vertices) +- :meth:`Graph.biconnected_components` aka :meth:`Graph.blocks` + +Boolean properties: + +- :meth:`Graph.is_bipartite` +- :meth:`Graph.is_connected` +- :meth:`Graph.is_dag` +- :meth:`Graph.is_directed` +- :meth:`Graph.is_named` +- :meth:`Graph.is_simple` +- :meth:`Graph.is_weighted` +- :meth:`Graph.has_multiple` + +Vertex properties ++++++++++++++++++++ +A spectrum of vertex-level properties can be computed. Similarity measures include: + +- :meth:`Graph.similarity_dice` +- :meth:`Graph.similarity_jaccard` +- :meth:`Graph.similarity_inverse_log_weighted` +- :meth:`Graph.diversity` + +Structural: + +- :meth:`Graph.authority_score` +- :meth:`Graph.hub_score` +- :meth:`Graph.betweenness` +- :meth:`Graph.bibcoupling` +- :meth:`Graph.closeness` +- :meth:`Graph.constraint` +- :meth:`Graph.cocitation` +- :meth:`Graph.coreness` (aka :meth:`Graph.shell_index`) +- :meth:`Graph.eccentricity` +- :meth:`Graph.eigenvector_centrality` +- :meth:`Graph.pagerank` +- :meth:`Graph.personalized_pagerank` +- :meth:`Graph.strength` +- :meth:`Graph.transitivity_local_undirected` + +Connectedness: + +- :meth:`Graph.subcomponent` +- :meth:`Graph.is_separator` +- :meth:`Graph.is_minimal_separator` + +Edge properties ++++++++++++++++ +As for vertices, edge properties are implemented. Basic properties include: + +- :meth:`Graph.is_loop` +- :meth:`Graph.is_multiple` +- :meth:`Graph.is_mutual` +- :meth:`Graph.count_multiple` + +and more complex ones: + +- :meth:`Graph.edge_betweenness` + +Matrix representations ++++++++++++++++++++++++ +Matrix-related functionality includes: + +- :meth:`Graph.get_adjacency` +- :meth:`Graph.get_adjacency_sparse` (sparse CSR matrix version) +- :meth:`Graph.laplacian` + +Clustering +++++++++++ +|igraph| includes several approaches to unsupervised graph clustering and community detection: + +- :meth:`Graph.components` (aka :meth:`Graph.clusters`): the connected components +- :meth:`Graph.cohesive_blocks` +- :meth:`Graph.community_edge_betweenness` +- :meth:`Graph.community_fastgreedy` +- :meth:`Graph.community_infomap` +- :meth:`Graph.community_label_propagation` +- :meth:`Graph.community_leading_eigenvector` +- :meth:`Graph.community_leading_eigenvector_naive` +- :meth:`Graph.community_leiden` +- :meth:`Graph.community_multilevel` (a version of Louvain) +- :meth:`Graph.community_optimal_modularity` (exact solution, < 100 vertices) +- :meth:`Graph.community_spinglass` +- :meth:`Graph.community_walktrap` + +Simplification, permutations and rewiring ++++++++++++++++++++++++++++++++++++++++++ +To check is a graph is simple, you can use :meth:`Graph.is_simple`. + +>>> g.is_simple() + +To simplify a graph (remove multiedges and loops), use :meth:`Graph.simplify`: + +>>> g_simple = g.simplify() + +To return a directed/undirected copy of the graph, use :meth:`Graph.as_directed` and :meth:`Graph.as_undirected`, respectively. + +To permute the order of vertices, you can use :meth:`Graph.permute_vertices`: + +>>> g = ig.Tree(6, 2) +>>> g_perm = g.permute_vertices([1, 0, 2, 3, 4, 5]) + +The canonical permutation can be obtained via :meth:`Graph.canonical_permutation`, which can then be directly passed to the function above. + +To rewire the graph at random, there are: + +- :meth:`Graph.rewire` - preserves the degree distribution +- :meth:`Graph.rewire_edges` - fixed rewiring probability for each endpoint + +Line graph +++++++++++ +To compute the line graph of a graph `g`, which represents the connectedness of the *edges* of g, you can use :meth:`Graph.linegraph`: + +>>> g = Graph(n=4, edges=[[0, 1], [0, 2]]) +>>> gl = g.linegraph() + +In this case, the line graph has two vertices, representing the two edges of the original graph, and one edge, representing the point where +those two original edges touch. + +Composition and subgraphs +++++++++++++++++++++++++++ +The function :meth:`Graph.decompose` decomposes the graph into subgraphs. Vice versa, the function :meth:`Graph.compose` returns the composition of two graphs. + +To compute the subgraph spannes by some vertices/edges, use :meth:`Graph.subgraph` (aka :meth:`Graph.induced_subgraph`) and :meth:`Graph.subgraph_edges`: + +>>> g_sub = g.subgraph([0, 1]) +>>> g_sub = g.subgraph_edges([0]) + +To compute the minimum spanning tree, use :meth:`Graph.spanning_tree`. + +To compute graph k-cores, the method :meth:`Graph.k_core` is available. + +The dominator tree from a given node can be obtained with :meth:`Graph.dominator`. + +Bipartite graphs can be decomposed using :meth:`Graph.bipartite_projection`. The size of the projections can be computed using :meth:`Graph.bipartite_projection_size`. + +Morphisms +++++++++++++++++++ +|igraph| enables comparisons between graphs: + +- :meth:`Graph.isomorphic` +- :meth:`Graph.isomorphic_vf2` +- :meth:`Graph.subisomorphic_vf2` +- :meth:`Graph.subisomorphic_lad` +- :meth:`Graph.get_isomorphisms_vf2` +- :meth:`Graph.get_subisomorphisms_vf2` +- :meth:`Graph.get_subisomorphisms_lad` +- :meth:`Graph.get_automorphisms_vf2` +- :meth:`Graph.count_isomorphisms_vf2` +- :meth:`Graph.count_subisomorphisms_vf2` +- :meth:`Graph.count_automorphisms_vf2` + +Flow +++++ +Flow is a characteristic of directed graphs. The following functions are available: + +- :meth:`Graph.maxflow` between two nodes +- :meth:`Graph.maxflow_value` - similar to the previous one, but only the value is returned +- :meth:`Graph.gomory_hu_tree` + +Flow and cuts are closely related, therefore you might find the following functions useful as well: + +- :meth:`Graph.mincut` calculates the minimum cut between the source and target vertices +- :meth:`Graph.st_mincut` - as previous one, but returns a simpler data structure +- :meth:`Graph.mincut_value` - as previous one, but returns only the value +- :meth:`Graph.all_st_cuts` +- :meth:`Graph.all_st_mincuts` +- :meth:`Graph.edge_connectivity` or :meth:`Graph.edge_disjoint_paths` or :meth:`Graph.adhesion` +- :meth:`Graph.vertex_connectivity` or :meth:`Graph.cohesion` + +.. _API documentation: https://igraph.org/python/doc/igraph-module.html diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 3c42c39e4..a3f5b952e 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -7,6 +7,10 @@ The :class:`Graph` class is the main object used to generate graphs: >>> from igraph import Graph +To copy a graph, use :meth:`Graph.copy`: + +>>> g_new = g.copy() + From nodes and edges ++++++++++++++++++++ Nodes are always numbered from 0 upwards. To create a generic graph with a specified number of nodes (e.g. 10) and a list of edges between them, you can use the generic constructor: diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index bb1789bd7..3709fc569 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13096,7 +13096,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " the algorithm assumes that there might be some loops in the graph\n" " and calculates the density accordingly. If C{False}, the algorithm\n" " assumes that there can't be any loops.\n" - "@return: the reciprocity of the graph."}, + "@return: the density of the graph."}, /* interfaces to igraph_diameter */ {"diameter", (PyCFunction) igraphmodule_Graph_diameter, From 2d28d2f72f4efc6f5baef61ab599a520c5fbadc0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Aug 2020 13:45:55 +0200 Subject: [PATCH 0239/1892] trying to fix AppVeyor --- appveyor.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a602baa12..7e3ea6a77 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,10 +23,16 @@ platform: - x64 install: + # update msys2 keyring first + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + + # update msys2 - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - bash -lc "pacman --noconfirm -Sy" - - bash -lc "pacman --noconfirm -S zstd" - - bash -lc "pacman --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" + - bash -lc "pacman --needed --noconfirm -S zstd" + - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - pip install cibuildwheel==1.1.0 before_build: From 2fa27a958f8509ce686a34e62aca6a2ca7dba011 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Aug 2020 13:46:50 +0200 Subject: [PATCH 0240/1892] ignore VSCode files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a22ad337..06705accc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ igraph/*.so .eggs/ .tox .venv/ +.vscode/ docker/wheelhouse vendor/build/ vendor/install/ From 5e4a5e2bc10b4ae9d7a9ede6343f55d7e8cdb82a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Aug 2020 13:47:24 +0200 Subject: [PATCH 0241/1892] DFS: query neighbors only once for each vertex, don't query when backtracking --- src/igraph/__init__.py | 12 ++++++------ tests/test_iterators.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 96814300f..248754144 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3261,23 +3261,23 @@ def dfs(self, vid, mode=OUT): parents = [] # ok start from vid - stack.append(vid) + stack.append((vid, self.neighbors(vid, mode=mode))) vids.append(vid) parents.append(vid) added[vid] = True # go down the rabbit hole while stack: - vid = stack[-1] - neighbors = self.neighbors(vid, mode=mode) - for neighbor in neighbors: + vid, neighbors = stack[-1] + if neighbors: + # Get next neighbor to visit + neighbor = neighbors.pop() if not added[neighbor]: # Add hanging subtree neighbor - stack.append(neighbor) + stack.append((neighbor, self.neighbors(neighbor, mode=mode))) vids.append(neighbor) parents.append(vid) added[neighbor] = True - break else: # No neighbor found, end of subtree stack.pop() diff --git a/tests/test_iterators.py b/tests/test_iterators.py index 7bd6d81bf..b8777d275 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -23,8 +23,8 @@ def testBFSIter(self): def testDFS(self): g = Graph.Tree(10, 2) vs, ps = g.dfs(0) - self.assertEqual(vs, [0, 1, 3, 7, 8, 4, 9, 2, 5, 6]) - self.assertEqual(ps, [0, 0, 1, 3, 3, 1, 4, 0, 2, 2]) + self.assertEqual(vs, [0, 2, 6, 5, 1, 4, 9, 3, 8, 7]) + self.assertEqual(ps, [0, 0, 2, 2, 0, 1, 4, 1, 3, 3]) def testDFSIter(self): g = Graph.Tree(10, 2) From ab6d22bc9a53022329c684a9d7890d5edec98a10 Mon Sep 17 00:00:00 2001 From: Yisu Remy Wang Date: Mon, 10 Aug 2020 12:50:06 -0700 Subject: [PATCH 0242/1892] Clarify Read_EdgeList behavior (#323) --- src/_igraph/graphobject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3709fc569..7585b4c3b 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14658,7 +14658,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS | METH_CLASS, "Read_Edgelist(f, directed=True)\n\n" "Reads an edge list from a file and creates a graph based on it.\n\n" - "Please note that the vertex indices are zero-based.\n\n" + "Please note that the vertex indices are zero-based. A vertex of zero\n" + "degree will be created for every integer that is in range but does not\n" + "appear in the edgelist.\n\n" "@param f: the name of the file or a Python file handle\n" "@param directed: whether the generated graph should be directed.\n"}, /* interface to igraph_read_graph_graphdb */ From 7c1ed6dfce8604105cf2e606f28b49277b29e7b4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Aug 2020 00:05:38 +0200 Subject: [PATCH 0243/1892] clarified VertexClustering.giant() documentation, fixes #324 --- src/igraph/clustering.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 18660df93..8f519ddb1 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -422,13 +422,16 @@ def subgraphs(self): def giant(self): - """Returns the giant community of the clustered graph. + """Returns the largest cluster of the clustered graph. - The giant component a community for which no larger community exists. - @note: there can be multiple giant communities, this method will return - the copy of an arbitrary one if there are multiple giant communities. + The largest cluster is a cluster for which no larger cluster exists in + the clustering. It may also be known as the I{giant community} if the + clustering represents the result of a community detection function. - @return: a copy of the giant community. + @note: there can be multiple largest clusters, this method will return + the copy of an arbitrary one if there are multiple largest clusters. + + @return: a copy of the largest cluster. @precondition: the vertex set of the graph hasn't been modified since the moment the clustering was constructed. """ From 4e30ad1ce5864fbe15245bb44f275faef6ed646c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Aug 2020 00:05:55 +0200 Subject: [PATCH 0244/1892] Python virtualenvs are typically called 'venv' or '.venv' so we use that in the docs --- doc/source/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 45c26fbd9..6f067f093 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -44,8 +44,8 @@ Many users like to install packages into a project-specific `virtual environment `_. A variation of the following commands should work on most platforms: - $ python -m venv ENV - $ source ENV/bin/activate + $ python -m venv venv + $ source venv/bin/activate $ pip install python-igraph To test the installed package, launch Python within the virtual environment and run the From 2b5cf8a96b37e0080fede75f2294c5975e9b588f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 24 Aug 2020 19:10:19 +0200 Subject: [PATCH 0245/1892] fix incorrect handling of loop edges in graph difference --- tests/test_operators.py | 16 ++++++++++++++++ vendor/source/igraph | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/test_operators.py b/tests/test_operators.py index f539389f2..23b279140 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -22,6 +22,22 @@ def testIntersection(self): def testUnion(self): g = Graph.Tree(7, 2) | Graph.Lattice([7]) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) + self.assertTrue(sorted(g.get_edgelist()) == [ + (0, 1), (0, 2), (0, 6), (1, 2), (1, 3), (1, 4), (2, 3), (2, 5), + (2, 6), (3, 4), (4, 5), (5, 6) + ]) + + def testDifference(self): + g = Graph.Tree(7, 2) - Graph.Lattice([7]) + self.assertTrue(g.vcount() == 7 and g.ecount() == 5) + self.assertTrue(sorted(g.get_edgelist()) == [(0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]) + + def testDifferenceWithSelfLoop(self): + # https://github.com/igraph/igraph/issues/597# + g = Graph.Ring(10) + [(0, 0)] + g -= Graph.Ring(5) + self.assertTrue(g.vcount() == 10 and g.ecount() == 7) + self.assertTrue(sorted(g.get_edgelist()) == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]) def testInPlaceAddition(self): g = Graph.Full(3) diff --git a/vendor/source/igraph b/vendor/source/igraph index 4986fba9e..878de1310 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 4986fba9e43740acf2f02d081aea8dd221e2372c +Subproject commit 878de131016b23dc3b66d24e598c41325715b21f From bd3e5cbb4a0bfd9524beae399eb1d1c76a6f7216 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 2 Sep 2020 13:09:18 +0200 Subject: [PATCH 0246/1892] allow keyword arguments for Graph.complementer() --- src/_igraph/graphobject.c | 7 ++++--- src/_igraph/graphobject.h | 2 +- tests/test_operators.py | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 7585b4c3b..24cba807c 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -9717,13 +9717,14 @@ PyObject *igraphmodule_Graph_difference(igraphmodule_GraphObject * self, * \brief Creates the complementer of a graph */ PyObject *igraphmodule_Graph_complementer(igraphmodule_GraphObject * self, - PyObject * args) + PyObject * args, PyObject * kwds) { + static char *kwlist[] = { "loops", NULL }; igraphmodule_GraphObject *result; PyObject *o = Py_True; igraph_t g; - if (!PyArg_ParseTuple(args, "|O", &o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &o)) return NULL; if (igraph_complementer(&g, &self->g, PyObject_IsTrue(o))) { igraphmodule_handle_igraph_error(); @@ -15264,7 +15265,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // OPERATORS // /////////////// {"complementer", (PyCFunction) igraphmodule_Graph_complementer, - METH_VARARGS, + METH_VARARGS | METH_KEYWORDS, "complementer(loops=False)\n\n" "Returns the complementer of the graph\n\n" "@param loops: whether to include loop edges in the complementer.\n" diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 5c87becd6..3a00e0236 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -186,7 +186,7 @@ PyObject* igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject* self); PyObject* igraphmodule_Graph_get_vertices(igraphmodule_GraphObject* self, void* closure); PyObject* igraphmodule_Graph_get_edges(igraphmodule_GraphObject* self, void* closure); -PyObject* igraphmodule_Graph_complementer(igraphmodule_GraphObject* self, PyObject* args); +PyObject* igraphmodule_Graph_complementer(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); PyObject* igraphmodule_Graph_complementer_op(igraphmodule_GraphObject* self); PyObject* igraphmodule_Graph_compose(igraphmodule_GraphObject* self, PyObject* other); PyObject* igraphmodule_Graph_difference(igraphmodule_GraphObject* self, PyObject* other); diff --git a/tests/test_operators.py b/tests/test_operators.py index 23b279140..7ea92ec00 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -10,6 +10,24 @@ np = None class OperatorTests(unittest.TestCase): + def testComplementer(self): + g = Graph.Full(3) + g2 = g.complementer() + self.assertTrue(g2.vcount() == 3 and g2.ecount() == 3) + self.assertTrue(sorted(g2.get_edgelist()) == [(0, 0), (1, 1), (2, 2)]) + + g = Graph.Full(3) + Graph.Full(2) + g2 = g.complementer(False) + self.assertTrue(sorted(g2.get_edgelist()) == [ + (0, 3), (0, 4), (1, 3), (1, 4), (2, 3), (2, 4) + ]) + + g2 = g.complementer(loops=True) + self.assertTrue(sorted(g2.get_edgelist()) == [ + (0, 0), (0, 3), (0, 4), (1, 1), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), + (3, 3), (4, 4) + ]) + def testMultiplication(self): g = Graph.Full(3)*3 self.assertTrue(g.vcount() == 9 and g.ecount() == 9 From 88f2b3274403b68672a0ea316d23c39c4b5f3f5a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 2 Sep 2020 13:10:11 +0200 Subject: [PATCH 0247/1892] added Pandas to tox test environment because one of the unittests needs Pandas --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index e47224111..ffd3a411d 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ deps = scipy; platform_python_implementation != "PyPy" numpy; platform_python_implementation != "PyPy" networkx + pandas setenv = TESTING_IN_TOX=1 From 1b469ceff7105f16f618daba137f5c606fed03b3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 11 Sep 2020 10:41:12 +0200 Subject: [PATCH 0248/1892] added Graph.bridges(), closes #328 --- src/_igraph/graphobject.c | 35 +++++++++++++++++++++++++++++++++++ tests/test_structural.py | 8 ++++++++ 2 files changed, 43 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 24cba807c..8bed60901 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3970,6 +3970,32 @@ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject return Py_BuildValue("llll", (long)vcount1, (long)ecount1, (long)vcount2, (long)ecount2); } +/** \ingroup python_interface_graph + * \brief Calculates the bridges of a graph. + * \return the list of bridges in a PyObject + * \sa igraph_bridges + */ +PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { + igraph_vector_t res; + PyObject *o; + if (igraph_vector_init(&res, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_bridges(&self->g, &res)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&res); + return NULL; + } + + igraph_vector_sort(&res); + o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(&res); + + return o; +} + /** \ingroup python_interface_graph * \brief Calculates the closeness centrality of some vertices in a graph. * \return the closeness centralities as a list (or a single float) @@ -12977,6 +13003,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Internal function, undocumented.\n\n" "@see: Graph.bipartite_projection_size()\n"}, + /* interface to igraph_bridges */ + {"bridges", (PyCFunction)igraphmodule_Graph_bridges, + METH_NOARGS, + "bridges()\n\n" + "Returns the list of bridges in the graph.\n\n" + "An edge is a bridge if its removal increases the number of (weakly) connected\n" + "components in the graph.\n" + }, + /* interface to igraph_closeness */ {"closeness", (PyCFunction) igraphmodule_Graph_closeness, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/test_structural.py b/tests/test_structural.py index 22e6aedb1..2f192ce4c 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -375,6 +375,14 @@ def testNeighborhoodSize(self): class MiscTests(unittest.TestCase): + def testBridges(self): + g = Graph(5, [(0, 1), (1, 2), (2, 0), (0, 3), (3, 4)]) + self.assertTrue(g.bridges() == [3, 4]) + g = Graph(7, [(0, 1), (1, 2), (2, 0), (1, 6), (1, 3), (1, 4), (3, 5), (4, 5)]) + self.assertTrue(g.bridges() == [3]) + g = Graph(3, [(0, 1), (1, 2), (2, 3)]) + self.assertTrue(g.bridges() == [0, 1, 2]) + def testConstraint(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) self.assertTrue(isinstance(g.constraint(), list)) # TODO check more From 0da6bb668cc1e6dc976525d9e92da6a1d647e84d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 11 Sep 2020 12:49:31 +0200 Subject: [PATCH 0249/1892] exclude Pandas and NetworkX installation from pypy test run to prevent a timeout on the CI server --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index ffd3a411d..84fac76bb 100644 --- a/tox.ini +++ b/tox.ini @@ -11,8 +11,8 @@ commands = python -m unittest deps = scipy; platform_python_implementation != "PyPy" numpy; platform_python_implementation != "PyPy" - networkx - pandas + networkx; platform_python_implementation != "PyPy" + pandas; platform_python_implementation != "PyPy" setenv = TESTING_IN_TOX=1 From b7690ecf7b2632d48c5939f89890db0068b337eb Mon Sep 17 00:00:00 2001 From: deeenes Date: Mon, 14 Sep 2020 08:57:34 +0200 Subject: [PATCH 0250/1892] GraphSummary: vertex names can be not only str but something else that can be cast to str (#329) --- src/igraph/summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 69ef3eb36..143b597b0 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -152,7 +152,7 @@ def _construct_edgelist_adjlist(self): if self._graph.is_named(): names = self._graph.vs["name"] - maxlen = max(len(name) for name in names) + maxlen = max(len(str(name)) for name in names) format_str = "%%%ds %s %%s" % (maxlen, self._arrow) for v1, name in enumerate(names): neis = self._graph.successors(v1) From 1c9cf10aa6291d7d65ade5cf2a434e5a245b2a37 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 23 Sep 2020 19:54:21 +1000 Subject: [PATCH 0251/1892] Union/intersection of graphs with vertex names (#310) --- src/_igraph/convert.c | 35 +++ src/_igraph/convert.h | 2 + src/_igraph/graphobject.c | 213 +--------------- src/_igraph/graphobject.h | 3 +- src/_igraph/igraphmodule.c | 15 +- src/_igraph/operators.c | 316 ++++++++++++++++++++++++ src/_igraph/operators.h | 32 +++ src/igraph/__init__.py | 73 +++++- src/igraph/operators.py | 482 +++++++++++++++++++++++++++++++++++++ tests/test_generators.py | 8 +- tests/test_operators.py | 94 +++++++- 11 files changed, 1041 insertions(+), 232 deletions(-) create mode 100644 src/_igraph/operators.c create mode 100644 src/_igraph/operators.h create mode 100644 src/igraph/operators.py diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 947ba6789..1dcb2ec1f 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2345,6 +2345,41 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(PyObject *it, return 0; } +/** + * \ingroup python_interface_conversion + * \brief Appends the contents of a Python iterator returning graphs to + * an \c igraph_vectorptr_t, and also stores the class of the first graph + * + * The incoming \c igraph_vector_ptr_t should be INITIALIZED. + * Raises suitable Python exceptions when needed. + * + * \param it the Python iterator + * \param v the \c igraph_vector_ptr_t which will contain the result + * \return 0 if everything was OK, 1 otherwise + */ +int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, + igraph_vector_ptr_t *v, + PyTypeObject **g_type) { + PyObject *t; + int first = 1; + + while ((t=PyIter_Next(it))) { + if (!PyObject_TypeCheck(t, &igraphmodule_GraphType)) { + PyErr_SetString(PyExc_TypeError, "iterable argument must contain graphs"); + Py_DECREF(t); + return 1; + } + if (first) { + *g_type = Py_TYPE(t); + first = 0; + } + igraph_vector_ptr_push_back(v, &((igraphmodule_GraphObject*)t)->g); + Py_DECREF(t); + } + + return 0; +} + /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a single vertex ID diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 635ddb6a0..5385c1293 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -100,6 +100,8 @@ PyObject* igraphmodule_strvector_t_to_PyList(igraph_strvector_t *v); int igraphmodule_PyList_to_strvector_t(PyObject* v, igraph_strvector_t *result); int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(PyObject *it, igraph_vector_ptr_t *v); +int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, + igraph_vector_ptr_t *v, PyTypeObject **g_type); int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph); int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, igraph_t *graph, igraph_bool_t *return_single, diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8bed60901..d39a35702 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -268,7 +268,8 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, * * The newly created instance (which will be a subtype of )\c igraph.Graph) * will take ownership of the given \c igraph_t. This function is not - * accessible from Python. + * accessible from Python, however it is in the header file for other C API + * functions to use. */ PyObject* igraphmodule_Graph_subclass_from_igraph_t( PyTypeObject* type, igraph_t *graph @@ -9522,195 +9523,10 @@ PyObject *igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject * self) } /********************************************************************** - * Graph operations (union, intersection etc) * + * Graph operations * + * Disjoint union, union and intersection are in operators.c * **********************************************************************/ -/** \ingroup python_interface_graph - * \brief Creates the disjoint union of two graphs (operator version) - */ -PyObject *igraphmodule_Graph_disjoint_union(igraphmodule_GraphObject * self, - PyObject * other) -{ - PyObject *it; - igraphmodule_GraphObject *o, *result; - igraph_t g; - - /* Did we receive an iterable? */ - it = PyObject_GetIter(other); - if (it) { - /* Get all elements, store the graphs in an igraph_vector_ptr */ - igraph_vector_ptr_t gs; - if (igraph_vector_ptr_init(&gs, 0)) { - Py_DECREF(it); - return igraphmodule_handle_igraph_error(); - } - if (igraph_vector_ptr_push_back(&gs, &self->g)) { - Py_DECREF(it); - igraph_vector_ptr_destroy(&gs); - return igraphmodule_handle_igraph_error(); - } - if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(it, &gs)) { - igraph_vector_ptr_destroy(&gs); - Py_DECREF(it); - return NULL; - } - Py_DECREF(it); - - /* Create disjoint union */ - if (igraph_disjoint_union_many(&g, &gs)) { - igraph_vector_ptr_destroy(&gs); - return igraphmodule_handle_igraph_error(); - } - - igraph_vector_ptr_destroy(&gs); - } else { - PyErr_Clear(); - if (!PyObject_TypeCheck(other, &igraphmodule_GraphType)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - o = (igraphmodule_GraphObject *) other; - - if (igraph_disjoint_union(&g, &self->g, &o->g)) { - igraphmodule_handle_igraph_error(); - return NULL; - } - } - - /* this is correct as long as attributes are not copied by the - * operator. if they are copied, the initialization should not empty - * the attribute hashes */ - CREATE_GRAPH(result, g); - - return (PyObject *) result; -} - -/** \ingroup python_interface_graph - * \brief Creates the union of two graphs (operator version) - */ -PyObject *igraphmodule_Graph_union(igraphmodule_GraphObject * self, - PyObject * other) -{ - PyObject *it; - igraphmodule_GraphObject *o, *result; - igraph_t g; - - /* Did we receive an iterable? */ - it = PyObject_GetIter(other); - if (it) { - /* Get all elements, store the graphs in an igraph_vector_ptr */ - igraph_vector_ptr_t gs; - if (igraph_vector_ptr_init(&gs, 0)) { - Py_DECREF(it); - return igraphmodule_handle_igraph_error(); - } - if (igraph_vector_ptr_push_back(&gs, &self->g)) { - Py_DECREF(it); - igraph_vector_ptr_destroy(&gs); - return igraphmodule_handle_igraph_error(); - } - if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(it, &gs)) { - Py_DECREF(it); - igraph_vector_ptr_destroy(&gs); - return NULL; - } - Py_DECREF(it); - - /* Create union */ - if (igraph_union_many(&g, &gs, /*edgemaps=*/ 0)) { - igraph_vector_ptr_destroy(&gs); - igraphmodule_handle_igraph_error(); - return NULL; - } - - igraph_vector_ptr_destroy(&gs); - } - else { - PyErr_Clear(); - if (!PyObject_TypeCheck(other, &igraphmodule_GraphType)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - o = (igraphmodule_GraphObject *) other; - - if (igraph_union(&g, &self->g, &o->g, /*edge_map1=*/ 0, - /*edge_map2=*/ 0)) { - igraphmodule_handle_igraph_error(); - return NULL; - } - } - - /* this is correct as long as attributes are not copied by the - * operator. if they are copied, the initialization should not empty - * the attribute hashes */ - CREATE_GRAPH(result, g); - - return (PyObject *) result; -} - -/** \ingroup python_interface_graph - * \brief Creates the intersection of two graphs (operator version) - */ -PyObject *igraphmodule_Graph_intersection(igraphmodule_GraphObject * self, - PyObject * other) -{ - PyObject *it; - igraphmodule_GraphObject *o, *result; - igraph_t g; - - /* Did we receive an iterable? */ - it = PyObject_GetIter(other); - if (it) { - /* Get all elements, store the graphs in an igraph_vector_ptr */ - igraph_vector_ptr_t gs; - if (igraph_vector_ptr_init(&gs, 0)) { - Py_DECREF(it); - return igraphmodule_handle_igraph_error(); - } - if (igraph_vector_ptr_push_back(&gs, &self->g)) { - Py_DECREF(it); - igraph_vector_ptr_destroy(&gs); - return igraphmodule_handle_igraph_error(); - } - if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(it, &gs)) { - Py_DECREF(it); - igraph_vector_ptr_destroy(&gs); - return NULL; - } - Py_DECREF(it); - - /* Create union */ - if (igraph_intersection_many(&g, &gs, /*edgemaps=*/ 0)) { - igraph_vector_ptr_destroy(&gs); - igraphmodule_handle_igraph_error(); - return NULL; - } - - igraph_vector_ptr_destroy(&gs); - } - else { - PyErr_Clear(); - if (!PyObject_TypeCheck(other, &igraphmodule_GraphType)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - o = (igraphmodule_GraphObject *) other; - - if (igraph_intersection(&g, &self->g, &o->g, /*edge_map1=*/ 0, - /*edge_map2=*/ 0)) { - igraphmodule_handle_igraph_error(); - return NULL; - } - } - - /* this is correct as long as attributes are not copied by the - * operator. if they are copied, the initialization should not empty - * the attribute hashes */ - CREATE_GRAPH(result, g); - - return (PyObject *) result; -} - /** \ingroup python_interface_graph * \brief Creates the difference of two graphs (operator version) */ @@ -15310,23 +15126,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"difference", (PyCFunction) igraphmodule_Graph_difference, METH_O, "difference(other)\n\nSubtracts the given graph from the original"}, - {"disjoint_union", (PyCFunction) igraphmodule_Graph_disjoint_union, - METH_O, - "disjoint_union(graphs)\n\n" - "Creates the disjoint union of two (or more) graphs.\n\n" - "@param graphs: the list of graphs to be united with the current one.\n"}, - {"intersection", (PyCFunction) igraphmodule_Graph_intersection, - METH_O, - "intersection(graphs)\n\n" - "Creates the intersection of two (or more) graphs.\n\n" - "@param graphs: the list of graphs to be intersected with\n" - " the current one.\n"}, - {"union", (PyCFunction) igraphmodule_Graph_union, - METH_O, - "union(graphs)\n\n" - "Creates the union of two (or more) graphs.\n\n" - "@param graphs: the list of graphs to be united with\n" - " the current one.\n"}, /**********************/ /* DOMINATORS */ @@ -16064,9 +15863,9 @@ PyNumberMethods igraphmodule_Graph_as_number = { (unaryfunc) igraphmodule_Graph_complementer_op, /*nb_invert */ 0, /*nb_lshift */ 0, /*nb_rshift */ - (binaryfunc) igraphmodule_Graph_intersection, /*nb_and */ + 0, /*nb_and */ 0, /*nb_xor */ - (binaryfunc) igraphmodule_Graph_union, /*nb_or */ + 0, /*nb_or */ #ifndef IGRAPH_PYTHON3 0, /*nb_coerce */ #endif diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 3a00e0236..618dbb97b 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -55,6 +55,7 @@ int igraphmodule_Graph_clear(igraphmodule_GraphObject *self); int igraphmodule_Graph_traverse(igraphmodule_GraphObject *self, visitproc visit, void *arg); void igraphmodule_Graph_dealloc(igraphmodule_GraphObject* self); int igraphmodule_Graph_init(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); +PyObject* igraphmodule_Graph_subclass_from_igraph_t(PyTypeObject* type, igraph_t *graph); PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph); PyObject* igraphmodule_Graph_str(igraphmodule_GraphObject *self); @@ -191,8 +192,6 @@ PyObject* igraphmodule_Graph_complementer_op(igraphmodule_GraphObject* self); PyObject* igraphmodule_Graph_compose(igraphmodule_GraphObject* self, PyObject* other); PyObject* igraphmodule_Graph_difference(igraphmodule_GraphObject* self, PyObject* other); PyObject* igraphmodule_Graph_disjoint_union(igraphmodule_GraphObject* self, PyObject* other); -PyObject* igraphmodule_Graph_intersection(igraphmodule_GraphObject* self, PyObject* other); -PyObject* igraphmodule_Graph_union(igraphmodule_GraphObject* self, PyObject* other); PyObject* igraphmodule_Graph_bfs(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); PyObject* igraphmodule_Graph_bfsiter(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index fcd79063e..5e671486a 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -37,6 +37,7 @@ #include "random.h" #include "vertexobject.h" #include "vertexseqobject.h" +#include "operators.h" #define IGRAPH_MODULE #include "igraphmodule_api.h" @@ -651,6 +652,18 @@ static PyMethodDef igraphmodule_methods[] = METH_VARARGS | METH_KEYWORDS, "_split_join_distance(comm1, comm2)" }, + {"_disjoint_union", (PyCFunction)igraphmodule__disjoint_union, + METH_VARARGS | METH_KEYWORDS, + "_disjoint_union(graphs)" + }, + {"_union", (PyCFunction)igraphmodule__union, + METH_VARARGS | METH_KEYWORDS, + "_union(graphs, edgemaps)" + }, + {"_intersection", (PyCFunction)igraphmodule__intersection, + METH_VARARGS | METH_KEYWORDS, + "_intersection(graphs, edgemaps)" + }, {NULL, NULL, 0, NULL} }; @@ -658,7 +671,7 @@ static PyMethodDef igraphmodule_methods[] = "Low-level Python interface for the igraph library. " \ "Should not be used directly.\n\n" \ "@undocumented: community_to_membership, _compare_communities, _power_law_fit, " \ - "_split_join_distance" + "_split_join_distance, _union, _intersection, _disjoint_union" /** * Module definition table (only for Python 3.x) diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c new file mode 100644 index 000000000..3de9d4c15 --- /dev/null +++ b/src/_igraph/operators.c @@ -0,0 +1,316 @@ +/* vim:set ts=4 sw=2 sts=2 et: */ +/* + IGraph library. + Copyright (C) 2006-2012 Tamas Nepusz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#include "common.h" +#include "convert.h" +#include "error.h" +#include "graphobject.h" + + +/** \ingroup python_interface_graph + * \brief Creates the disjoint union of two or more graphs + */ +PyObject *igraphmodule__disjoint_union(PyObject *self, + PyObject *args, PyObject *kwds) +{ + static char* kwlist[] = { "graphs", NULL }; + PyObject *it, *graphs; + long int no_of_graphs; + igraph_vector_ptr_t gs; + igraphmodule_GraphObject *o; + PyObject *result; + PyTypeObject *result_type; + igraph_t g; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, + &graphs)) + return NULL; + + /* Needs to be an iterable */ + it = PyObject_GetIter(graphs); + if (!it) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + + /* Get all elements, store the graphs in an igraph_vector_ptr */ + if (igraph_vector_ptr_init(&gs, 0)) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(it, &gs, &result_type)) { + Py_DECREF(it); + igraph_vector_ptr_destroy(&gs); + return NULL; + } + Py_DECREF(it); + no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + + /* Create disjoint union */ + if (igraph_disjoint_union_many(&g, &gs)) { + igraph_vector_ptr_destroy(&gs); + igraphmodule_handle_igraph_error(); + return NULL; + } + + igraph_vector_ptr_destroy(&gs); + + /* this is correct as long as attributes are not copied by the + * operator. if they are copied, the initialization should not empty + * the attribute hashes */ + if (no_of_graphs > 0) { + result = igraphmodule_Graph_subclass_from_igraph_t( + result_type, + &g); + } + else { + result = igraphmodule_Graph_from_igraph_t(&g); + } + + return result; +} + + +/** \ingroup python_interface_graph + * \brief Creates the union of two or more graphs + */ +PyObject *igraphmodule__union(PyObject *self, + PyObject *args, PyObject *kwds) +{ + static char* kwlist[] = { "graphs", "edgemaps", NULL }; + PyObject *it, *em_list, *graphs, *with_edgemaps_o; + int with_edgemaps = 0; + long int no_of_graphs; + igraph_vector_ptr_t gs; + igraphmodule_GraphObject *o; + PyObject *result; + PyTypeObject *result_type; + igraph_t g; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, + &graphs, &with_edgemaps_o)) + return NULL; + + if (PyObject_IsTrue(with_edgemaps_o)) + with_edgemaps = 1; + + /* Needs to be an iterable */ + it = PyObject_GetIter(graphs); + if (!it) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + + /* Get all elements, store the graphs in an igraph_vector_ptr */ + if (igraph_vector_ptr_init(&gs, 0)) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(it, &gs, &result_type)) { + Py_DECREF(it); + igraph_vector_ptr_destroy(&gs); + return NULL; + } + Py_DECREF(it); + no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + + if (with_edgemaps) { + /* prepare edgemaps */ + igraph_vector_ptr_t edgemaps; + if (igraph_vector_ptr_init(&edgemaps, 0)) { + return igraphmodule_handle_igraph_error(); + } + + /* Create union */ + if (igraph_union_many(&g, &gs, &edgemaps)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + igraphmodule_handle_igraph_error(); + return NULL; + } + + /* extract edgemaps */ + long int i; + em_list = PyList_New((Py_ssize_t) no_of_graphs); + for (i = 0; i < no_of_graphs; i++) { + long int j; + long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); + igraph_vector_t *map = VECTOR(edgemaps)[i]; + PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); + for (j = 0; j < no_of_edges; j++) { + PyObject *dest = PyLong_FromLong(VECTOR(*map)[j]); + PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); + } + PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); + } + igraph_vector_ptr_destroy(&edgemaps); + } + else { + /* Create union */ + if (igraph_union_many(&g, &gs, /* edgemaps */ 0)) { + igraph_vector_ptr_destroy(&gs); + igraphmodule_handle_igraph_error(); + return NULL; + } + } + + igraph_vector_ptr_destroy(&gs); + + /* this is correct as long as attributes are not copied by the + * operator. if they are copied, the initialization should not empty + * the attribute hashes */ + if (no_of_graphs > 0) { + o = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( + result_type, + &g); + } + else { + o = (igraphmodule_GraphObject*) igraphmodule_Graph_from_igraph_t(&g); + } + + if (with_edgemaps) { + /* wrap in a dictionary */ + result = PyDict_New(); + PyDict_SetItemString(result, "graph", (PyObject *) o); + Py_DECREF(o); + PyDict_SetItemString(result, "edgemaps", em_list); + } + else { + result = (PyObject *) o; + } + + return result; +} + +/** \ingroup python_interface_graph + * \brief Creates the intersection of two or more graphs + */ +PyObject *igraphmodule__intersection(PyObject *self, + PyObject *args, PyObject *kwds) +{ + static char* kwlist[] = { "graphs", "edgemaps", NULL }; + PyObject *it, *em_list, *graphs, *with_edgemaps_o; + int with_edgemaps = 0; + long int no_of_graphs; + igraph_vector_ptr_t gs; + igraphmodule_GraphObject *o; + PyObject *result; + PyTypeObject *result_type; + igraph_t g; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, + &graphs, &with_edgemaps_o)) + return NULL; + + if (PyObject_IsTrue(with_edgemaps_o)) + with_edgemaps = 1; + + /* Needs to be an iterable */ + it = PyObject_GetIter(graphs); + if (!it) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + + /* Get all elements, store the graphs in an igraph_vector_ptr */ + if (igraph_vector_ptr_init(&gs, 0)) { + Py_DECREF(it); + return igraphmodule_handle_igraph_error(); + } + if (igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(it, &gs, &result_type)) { + Py_DECREF(it); + igraph_vector_ptr_destroy(&gs); + return NULL; + } + Py_DECREF(it); + no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + + if (with_edgemaps) { + /* prepare edgemaps */ + igraph_vector_ptr_t edgemaps; + if (igraph_vector_ptr_init(&edgemaps, 0)) { + return igraphmodule_handle_igraph_error(); + } + + /* Create intersection */ + if (igraph_intersection_many(&g, &gs, &edgemaps)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + igraphmodule_handle_igraph_error(); + return NULL; + } + + long int i; + em_list = PyList_New((Py_ssize_t) no_of_graphs); + for (i = 0; i < no_of_graphs; i++) { + long int j; + long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); + igraph_vector_t *map = VECTOR(edgemaps)[i]; + PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); + for (j = 0; j < no_of_edges; j++) { + PyObject *dest = PyLong_FromLong(VECTOR(*map)[j]); + PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); + } + PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); + } + igraph_vector_ptr_destroy(&edgemaps); + + } + else { + /* Create intersection */ + if (igraph_intersection_many(&g, &gs, /* edgemaps */ 0)) { + igraph_vector_ptr_destroy(&gs); + igraphmodule_handle_igraph_error(); + return NULL; + } + } + + igraph_vector_ptr_destroy(&gs); + + /* this is correct as long as attributes are not copied by the + * operator. if they are copied, the initialization should not empty + * the attribute hashes */ + if (no_of_graphs > 0) { + o = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( + result_type, + &g); + } + else { + o = (igraphmodule_GraphObject*) igraphmodule_Graph_from_igraph_t(&g); + } + + if (with_edgemaps) { + /* wrap in a dictionary */ + result = PyDict_New(); + PyDict_SetItemString(result, "graph", (PyObject *) o); + Py_DECREF(o); + PyDict_SetItemString(result, "edgemaps", em_list); + Py_DECREF(em_list); + } + else { + result = (PyObject *) o; + } + + return result; +} + + diff --git a/src/_igraph/operators.h b/src/_igraph/operators.h new file mode 100644 index 000000000..3823a55ae --- /dev/null +++ b/src/_igraph/operators.h @@ -0,0 +1,32 @@ +/* -*- mode: C -*- */ +/* + IGraph library. + Copyright (C) 2006-2012 Tamas Nepusz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#ifndef PYTHON_OPERATORS_H +#define PYTHON_OPERATORS_H + +#include + +PyObject* igraphmodule__disjoint_union(PyObject* self, PyObject* args, PyObject* kwds); +PyObject* igraphmodule__union(PyObject* self, PyObject* args, PyObject* kwds); +PyObject* igraphmodule__intersection(PyObject* self, PyObject* args, PyObject* kwds); + +#endif diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 248754144..e61d97a40 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -41,6 +41,7 @@ from igraph.formula import * from igraph.layout import * from igraph.matching import * +from igraph.operators import * from igraph.statistics import * from igraph.summary import * from igraph.utils import * @@ -3088,23 +3089,26 @@ def DataFrame(klass, edges, directed=True, vertices=None): vertices = vertices.copy() vertices.iloc[:, 0].fillna('NA', inplace=True) - names = np.unique(edges.values[:, :2]) + names_edges = np.unique(edges.values[:, :2]) - if vertices is not None: - names_edges = names + if vertices is None: + names = names_edges + else: if vertices.shape[1] < 1: raise ValueError('vertices has no columns') - names = vertices.iloc[:, 0].astype(str) + names_vertices = vertices.iloc[:, 0].astype(str) - if names.duplicated().any(): + if names_vertices.duplicated().any(): raise ValueError('Vertex names must be unique') - if len(np.setdiff1d(names_edges, names.values)): + names_vertices = names_vertices.values + + if len(np.setdiff1d(names_edges, names_vertices)): raise ValueError( 'Some vertices in the edge DataFrame are missing from vertices DataFrame') - names = names.values + names = names_vertices # create graph g = Graph(n=len(names), directed=directed) @@ -3128,9 +3132,9 @@ def DataFrame(klass, edges, directed=True, vertices=None): # edge attributes if edges.shape[1] > 2: - for e, (_, attr) in zip(g.es, edges.iloc[:, 2:]): - for an, av in attr.items(): - e[an] = av + for e, (_, attr) in zip(g.es, edges.iloc[:, 2:].iterrows()): + for a_name, a_value in attr.items(): + e[a_name] = a_value return g @@ -3379,7 +3383,7 @@ def __isub__(self, other): elif isinstance(other, tuple) and len(other) == 2: self.delete_edges([other]) elif isinstance(other, list): - if len(other)>0: + if len(other) > 0: if isinstance(other[0], tuple): self.delete_edges(other) elif isinstance(other[0], (int, long, basestring)): @@ -3418,7 +3422,7 @@ def __sub__(self, other): elif isinstance(other, tuple) and len(other) == 2: result.delete_edges([other]) elif isinstance(other, list): - if len(other)>0: + if len(other) > 0: if isinstance(other[0], tuple): result.delete_edges(other) elif isinstance(other[0], (int, long, basestring)): @@ -3454,7 +3458,7 @@ def __mul__(self, other): elif other == 1: return self elif other > 1: - return self.disjoint_union([self]*(other-1)) + return self.disjoint_union([self] * (other - 1)) else: return NotImplemented @@ -3752,6 +3756,49 @@ def summary(self, verbosity=0, width=None, *args, **kwds): """ return str(GraphSummary(self, verbosity, width, *args, **kwds)) + def disjoint_union(self, other): + '''disjoint_union(self, other) + + Creates the disjoint union of two (or more) graphs. + + @param graphs: graph or list of graphs to be united with + the current one. + @return: the disjoint union graph + ''' + if isinstance(other, GraphBase): + other = [other] + return disjoint_union([self] + other) + + def union(self, other, byname='auto'): + '''union(self, other) + + Creates the union of two (or more) graphs. + + @param graphs: graph or list of graphs to be united with + the current one. + @param byname: whether to use vertex names instead of ids. See + L{igraph.union} for details. + @return: the union graph + ''' + if isinstance(other, GraphBase): + other = [other] + return union([self] + other, byname=byname) + + def intersection(self, other, byname='auto'): + '''intersection(self, other) + + Creates the intersection of two (or more) graphs. + + @param other: graph or list of graphs to be intersected with + the current one. + @param byname: whether to use vertex names instead of ids. See + L{igraph.intersection} for details. + @return: the intersection graph + ''' + if isinstance(other, GraphBase): + other = [other] + return intersection([self] + other, byname=byname) + _format_mapping = { "ncol": ("Read_Ncol", "write_ncol"), "lgl": ("Read_Lgl", "write_lgl"), diff --git a/src/igraph/operators.py b/src/igraph/operators.py new file mode 100644 index 000000000..947cd0809 --- /dev/null +++ b/src/igraph/operators.py @@ -0,0 +1,482 @@ +# vim:ts=4:sw=4:sts=4:et +# -*- coding: utf-8 -*- +""" +IGraph library. + +@undocumented: deprecated, _graphmethod, _add_proxy_methods, _layout_method_wrapper, + _3d_version_for +""" + +from __future__ import with_statement + +__license__ = u""" +Copyright (C) 2006-2012 Tamás Nepusz +Pázmány Péter sétány 1/a, 1117 Budapest, Hungary + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA +""" + +# pylint: disable-msg=W0401 +# W0401: wildcard import +from igraph._igraph import * +from igraph._igraph import _union, _intersection, _disjoint_union + +from collections import defaultdict, Counter +from warnings import warn + + +def disjoint_union(graphs): + """Graph disjoint union. + + The disjoint union of two or more graphs is created. + + This function keeps the attributes of all graphs. All graph, vertex and + edge attributes are copied to the result. If an attribute is present in + multiple graphs and would result a name clash, then this attribute is + renamed by adding suffixes: _1, _2, etc. + + An error is generated if some input graphs are directed and others are + undirected. + + @param graph: list of graphs. A lazy sequence is not acceptable. + @return: the disjoint union graph + """ + if any(not isinstance(g, GraphBase) for g in graphs): + raise TypeError('Not all elements are graphs') + + ngr = len(graphs) + # Trivial cases + if ngr == 0: + return None + if ngr == 1: + return graphs[0].copy() + # Now there are at least two graphs + + graph_union = _disjoint_union(graphs) + + # Graph attributes + # NOTE: a_first_graph tracks which graph has the 1st occurrence of an + # attribute, while a_conflict track attributes with naming conflicts + a_first_graph = {} + a_conflict = set() + for ig, g in enumerate(graphs, 1): + # NOTE: a_name is the name of the attribute, a_value its value + for a_name in g.attributes(): + a_value = g[a_name] + # No conflicts + if a_name not in graph_union.attributes(): + a_first_graph[a_name] = ig + graph_union[a_name] = a_value + continue + if graph_union[a_name] == a_value: + continue + if a_name not in a_conflict: + # New conflict + a_conflict.add(a_name) + igf = a_first_graph[a_name] + graph_union['{:}_{:}'.format(a_name, igf)] = \ + graph_union.pop(a_name) + graph_union['{:}_{:}'.format(a_name, ig)] = a_value + + # Vertex attributes + i = 0 + for g in graphs: + nv = g.vcount() + for attr in g.vertex_attributes(): + graph_union.vs[i: i + nv][attr] = g.vs[attr] + i += nv + + # Edge attributes + i = 0 + for g in graphs: + ne = g.ecount() + for attr in g.edge_attributes(): + graph_union.es[i: i + ne][attr] = g.es[attr] + i += ne + + return graph_union + + +def union(graphs, byname='auto'): + """Graph union. + + The union of two or more graphs is created. The graphs may have identical + or overlapping vertex sets. Edges which are included in at least one graph + will be part of the new graph. + + This function keeps the attributes of all graphs. All graph, vertex and + edge attributes are copied to the result. If an attribute is present in + multiple graphs and would result a name clash, then this attribute is + renamed by adding suffixes: _1, _2, etc. + + The 'name' vertex attribute is treated specially if the operation is + performed based on symbolic vertex names. In this case 'name' must be + present in all graphs, and it is not renamed in the result graph. + + An error is generated if some input graphs are directed and others are + undirected. + + @param graph: list of graphs. A lazy sequence is not acceptable. + @param byname: bool or 'auto' specifying the function behaviour with + respect to names vertices (i.e. vertices with the 'name' attribute). If + False, ignore vertex names. If True, merge vertices based on names. If + 'auto', use True if all graphs have named vertices and False otherwise + (in the latter case, a warning is generated too). + @return: the union graph + """ + + if any(not isinstance(g, GraphBase) for g in graphs): + raise TypeError('Not all elements are graphs') + + if byname not in (True, False, 'auto'): + raise ValueError('"byname" should be a bool or "auto"') + + ngr = len(graphs) + n_named = sum(g.is_named() for g in graphs) + if byname == 'auto': + byname = n_named == ngr + if n_named not in (0, ngr): + warn("Some, but not all graphs are named, not using vertex names") + elif byname and (n_named != ngr): + raise AttributeError("Some graphs are not named") + # Now we know that byname is only used is all graphs are named + + # Trivial cases + if ngr == 0: + return None + if ngr == 1: + return graphs[0].copy() + # Now there are at least two graphs + + if byname: + allnames = [g.vs['name'] for g in graphs] + uninames = list(set.union(*(set(vns) for vns in allnames))) + permutation_map = {x: i for i, x in enumerate(uninames)} + nve = len(uninames) + newgraphs = [] + for g, vertex_names in zip(graphs, allnames): + # Make a copy + ng = g.copy() + + # Add the missing vertices + v_missing = list(set(uninames) - set(vertex_names)) + ng.add_vertices(v_missing) + + # Reorder vertices to match uninames + # vertex k -> p[k] + permutation = [permutation_map[x] for x in ng.vs['name']] + ng = ng.permute_vertices(permutation) + + newgraphs.append(ng) + else: + newgraphs = graphs + + # If any graph has any edge attributes, we need edgemaps + edgemaps = any(len(g.edge_attributes()) for g in graphs) + res = _union(newgraphs, edgemaps) + if edgemaps: + graph_union = res['graph'] + edgemaps = res['edgemaps'] + else: + graph_union = res + + # Graph attributes + a_first_graph = {} + a_conflict = set() + for ig, g in enumerate(newgraphs, 1): + # NOTE: a_name is the name of the attribute, a_value its value + for a_name in g.attributes(): + a_value = g[a_name] + # No conflicts + if a_name not in graph_union.attributes(): + a_first_graph[a_name] = ig + graph_union[a_name] = a_value + continue + if graph_union[a_name] == a_value: + continue + if a_name not in a_conflict: + # New conflict + a_conflict.add(a_name) + igf = a_first_graph[a_name] + graph_union['{:}_{:}'.format(a_name, igf)] = \ + graph_union.pop(a_name) + graph_union['{:}_{:}'.format(a_name, ig)] = a_value + + # Vertex attributes + if byname: + graph_union.vs['name'] = uninames + attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(['name']) + nve = graph_union.vcount() + for a_name in attrs: + # Check for conflicts at at least one vertex + conflict = False + vals = [None for i in range(nve)] + for g in newgraphs: + if a_name in g.vertex_attributes(): + for i, a_value in enumerate(g.vs[a_name]): + if a_value is None: + continue + if vals[i] is None: + vals[i] = a_value + continue + if vals[i] != a_value: + conflict = True + break + if conflict: + break + + if not conflict: + graph_union.vs[a_name] = vals + continue + + # There is a conflict, name after the graph number + for ig, g in enumerate(newgraphs, 1): + if a_name in g.vertex_attributes(): + graph_union.vs['{:}_{:}'.format(a_name, ig)] = g.vs[a_name] + + # Edge attributes + if edgemaps: + attrs = set.union(*(set(g.edge_attributes()) for g in newgraphs)) + ne = graph_union.ecount() + for a_name in attrs: + # Check for conflicts at at least one edge + conflict = False + vals = [None for i in range(ne)] + for g, emap in zip(newgraphs, edgemaps): + if a_name not in g.edge_attributes(): + continue + for iu, a_value in zip(emap, g.es[a_name]): + if a_value is None: + continue + if vals[iu] is None: + vals[iu] = a_value + continue + if vals[iu] != a_value: + print(g, g.vs['name'], emap, a_value, iu, vals[iu]) + conflict = True + break + if conflict: + break + + if not conflict: + graph_union.es[a_name] = vals + continue + + # There is a conflict, name after the graph number + for ig, (g, emap) in enumerate(zip(newgraphs, edgemaps), 1): + if a_name not in g.edge_attributes(): + continue + # Pass through map + vals = [None for i in range(ne)] + for iu, a_value in zip(emap, g.es[a_name]): + vals[iu] = a_value + graph_union.es['{:}_{:}'.format(a_name, ig)] = vals + + return graph_union + + +def intersection(graphs, byname='auto', keep_all_vertices=True): + """Graph intersection. + + The intersection of two or more graphs is created. The graphs may have + identical or overlapping vertex sets. Edges which are included in all + graphs will be part of the new graph. + + This function keeps the attributes of all graphs. All graph, vertex and + edge attributes are copied to the result. If an attribute is present in + multiple graphs and would result a name clash, then this attribute is + renamed by adding suffixes: _1, _2, etc. + + The 'name' vertex attribute is treated specially if the operation is + performed based on symbolic vertex names. In this case 'name' must be + present in all graphs, and it is not renamed in the result graph. + + An error is generated if some input graphs are directed and others are + undirected. + + @param graph: list of graphs. A lazy sequence is not acceptable. + @param byname: bool or 'auto' specifying the function behaviour with + respect to names vertices (i.e. vertices with the 'name' attribute). If + False, ignore vertex names. If True, merge vertices based on names. If + 'auto', use True if all graphs have named vertices and False otherwise + (in the latter case, a warning is generated too). + @keep_all_vertices: bool specifying if vertices that are not present in all + graphs should be kept in the intersection. + @return: the intersection graph + """ + + if any(not isinstance(g, GraphBase) for g in graphs): + raise TypeError('Not all elements are graphs') + + if byname not in (True, False, 'auto'): + raise ValueError('"byname" should be a bool or "auto"') + + ngr = len(graphs) + n_named = sum(g.is_named() for g in graphs) + if byname == 'auto': + byname = n_named == ngr + if n_named not in (0, ngr): + warn("Some, but not all graphs are named, not using vertex names") + elif byname and (n_named != ngr): + raise AttributeError("Some graphs are not named") + # Now we know that byname is only used is all graphs are named + + # Trivial cases + if ngr == 0: + return None + if ngr == 1: + return graphs[0].copy() + # Now there are at least two graphs + + if byname: + allnames = [g.vs['name'] for g in graphs] + + if keep_all_vertices: + uninames = list(set.union(*(set(vns) for vns in allnames))) + else: + uninames = list(set.intersection(*(set(vns) for vns in allnames))) + permutation_map = {x: i for i, x in enumerate(uninames)} + + nv = len(uninames) + newgraphs = [] + for g, vertex_names in zip(graphs, allnames): + # Make a copy + ng = g.copy() + + if keep_all_vertices: + # Add the missing vertices + v_missing = list(set(uninames) - set(vertex_names)) + ng.add_vertices(v_missing) + else: + # Delete the private vertices + v_private = list(set(vertex_names) - set(uninames)) + ng.delete_vertices(v_private) + + # Reorder vertices to match uninames + # vertex k -> p[k] + permutation = [permutation_map[x] for x in ng.vs['name']] + ng = ng.permute_vertices(permutation) + + newgraphs.append(ng) + else: + newgraphs = graphs + + # If any graph has any edge attributes, we need edgemaps + edgemaps = any(len(g.edge_attributes()) for g in graphs) + res = _intersection(newgraphs, edgemaps) + if edgemaps: + graph_intsec = res['graph'] + edgemaps = res['edgemaps'] + else: + graph_intsec = res + + # Graph attributes + a_first_graph = {} + a_conflict = set() + for ig, g in enumerate(newgraphs, 1): + # NOTE: a_name is the name of the attribute, a_value its value + for a_name in g.attributes(): + a_value = g[a_name] + # No conflicts + if a_name not in graph_intsec.attributes(): + a_first_graph[a_name] = ig + graph_intsec[a_name] = a_value + continue + if graph_intsec[a_name] == a_value: + continue + if a_name not in a_conflict: + # New conflict + a_conflict.add(a_name) + igf = a_first_graph[a_name] + graph_intsec['{:}_{:}'.format(a_name, igf)] = \ + graph_intsec.pop(a_name) + graph_intsec['{:}_{:}'.format(a_name, ig)] = a_value + + # Vertex attributes + if byname: + graph_intsec.vs['name'] = uninames + attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(['name']) + nv = graph_intsec.vcount() + for a_name in attrs: + # Check for conflicts at at least one vertex + conflict = False + vals = [None for i in range(nv)] + for g in newgraphs: + if a_name not in g.vertex_attributes(): + continue + for i, a_value in enumerate(g.vs[a_name]): + if a_value is None: + continue + if vals[i] is None: + vals[i] = a_value + continue + if vals[i] != a_value: + conflict = True + break + if conflict: + break + + if not conflict: + graph_intsec.vs[a_name] = vals + continue + + # There is a conflict, name after the graph number + for ig, g in enumerate(newgraphs, 1): + if a_name in g.vertex_attributes(): + graph_intsec.vs['{:}_{:}'.format(a_name, ig)] = g.vs[a_name] + + # Edge attributes + if edgemaps: + attrs = set.union(*(set(g.edge_attributes()) for g in newgraphs)) + ne = graph_intsec.ecount() + for a_name in attrs: + # Check for conflicts at at least one edge + conflict = False + vals = [None for i in range(ne)] + for g, emap in zip(newgraphs, edgemaps): + if a_name not in g.edge_attributes(): + continue + for iu, a_value in zip(emap, g.es[a_name]): + if iu == -1: + continue + if a_value is None: + continue + if vals[iu] is None: + vals[iu] = a_value + continue + if vals[iu] != a_value: + conflict = True + break + if conflict: + break + + if not conflict: + graph_intsec.es[a_name] = vals + continue + + # There is a conflict, name after the graph number + for ig, (g, emap) in enumerate(zip(newgraphs, edgemaps), 1): + if a_name not in g.edge_attributes(): + continue + # Pass through map + vals = [None for i in range(ne)] + for iu, a_value in zip(emap, g.es[a_name]): + if iu == -1: + continue + vals[iu] = a_value + graph_intsec.es['{:}_{:}'.format(a_name, ig)] = vals + + return graph_intsec diff --git a/tests/test_generators.py b/tests/test_generators.py index a8e20d403..5dad1405d 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -179,7 +179,7 @@ def testDataFrame(self): columns=[0, 1, 'weight']) g = Graph.DataFrame(edges, directed=False) - self.assertTrue(g.es["weight"] == [0.1, 0.4]) + self.assertTrue(g.es["weight"] == [0.4, 0.1]) vertices = pd.DataFrame( [['A', 'blue'], ['B', 'yellow'], ['C', 'blue']], @@ -190,12 +190,6 @@ def testDataFrame(self): self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) self.assertTrue(g.es["weight"] == [0.4, 0.1]) - vertices.iloc[0, 0] = np.nan - g = Graph.DataFrame(edges, directed=True, vertices=vertices) - self.assertTrue(g.vs['name'] == ['NA', 'B', 'C']) - self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) - self.assertTrue(g.es["weight"] == [0.4, 0.1]) - def suite(): generator_suite = unittest.makeSuite(GeneratorTests) diff --git a/tests/test_operators.py b/tests/test_operators.py index 7ea92ec00..064d4215d 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -29,14 +29,30 @@ def testComplementer(self): ]) def testMultiplication(self): - g = Graph.Full(3)*3 + g = Graph.Full(3) * 3 self.assertTrue(g.vcount() == 9 and g.ecount() == 9 - and g.clusters().membership == [0,0,0,1,1,1,2,2,2]) + and g.clusters().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2]) def testIntersection(self): g = Graph.Tree(7, 2) & Graph.Lattice([7]) self.assertTrue(g.get_edgelist() == [(0, 1)]) + def testIntersectionMethod(self): + g = Graph.Tree(7, 2).intersection(Graph.Lattice([7])) + self.assertTrue(g.get_edgelist() == [(0, 1)]) + + def testDisjointUnion(self): + g1 = Graph.Tree(7, 2) + g2 = Graph.Lattice([7]) + + # Method + g = g1.disjoint_union(g2) + self.assertTrue(g.vcount() == 14 and g.ecount() == 13) + + # Module function + g = disjoint_union([g1, g2]) + self.assertTrue(g.vcount() == 14 and g.ecount() == 13) + def testUnion(self): g = Graph.Tree(7, 2) | Graph.Lattice([7]) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) @@ -57,6 +73,80 @@ def testDifferenceWithSelfLoop(self): self.assertTrue(g.vcount() == 10 and g.ecount() == 7) self.assertTrue(sorted(g.get_edgelist()) == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]) + def testUnionMethod(self): + g = Graph.Tree(7, 2).union(Graph.Lattice([7])) + self.assertTrue(g.vcount() == 7 and g.ecount() == 12) + + def testIntersectionMany(self): + gs = [Graph.Tree(7, 2), Graph.Lattice([7])] + g = intersection(gs) + self.assertTrue(g.get_edgelist() == [(0, 1)]) + + def testIntersectionManyAttributes(self): + gs = [Graph.Tree(7, 2), Graph.Lattice([7])] + gs[0]['attr'] = 'graph1' + gs[0].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] + gs[1].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] + gs[0].vs[0]['attr'] = 'set' + gs[1].vs[5]['attr'] = 'set_too' + g = intersection(gs) + names = g.vs['name'] + self.assertTrue(g['attr'] == 'graph1') + self.assertTrue(g.vs[names.index('one')]['attr'] == 'set') + self.assertTrue(g.vs[names.index('six')]['attr'] == 'set_too') + self.assertTrue(g.ecount() == 1) + self.assertTrue( + set(g.get_edgelist()[0]) == set([names.index('one'), names.index('two')]), + ) + + def testIntersectionManyEdgemap(self): + gs = [ + Graph.Formula('A-B'), + Graph.Formula('A-B,C-D'), + ] + gs[0].es[0]['attr'] = 'set' + gs[1].es[1]['attr'] = 'set_too' + g = intersection(gs) + self.assertTrue(g.es['attr'] == ['set']) + + def testUnionMany(self): + gs = [Graph.Tree(7, 2), Graph.Lattice([7]), Graph.Lattice([7])] + g = union(gs) + self.assertTrue(g.vcount() == 7 and g.ecount() == 12) + + def testUnionManyAttributes(self): + gs = [ + Graph.Formula('A-B'), + Graph.Formula('A-B,C-D'), + ] + gs[0]['attr'] = 'graph1' + gs[0].vs['attr'] = ['set', 'set_too'] + gs[0].vs['attr2'] = ['set', 'set_too'] + gs[1].vs[0]['attr'] = 'set' + gs[1].vs[0]['attr2'] = 'conflict' + g = union(gs) + names = g.vs['name'] + self.assertTrue(g['attr'] == 'graph1') + self.assertTrue(g.vs[names.index('A')]['attr'] == 'set') + self.assertTrue(g.vs[names.index('B')]['attr'] == 'set_too') + self.assertTrue(g.ecount() == 2) + self.assertTrue(sorted(g.vertex_attributes()) == ['attr', 'attr2_1', 'attr2_2', 'name']) + + def testUnionManyEdgemap(self): + gs = [ + Graph.Formula('A-B'), + Graph.Formula('C-D, A-B'), + ] + gs[0].es[0]['attr'] = 'set' + gs[1].es[0]['attr'] = 'set_too' + g = union(gs) + for e in g.es: + vnames = [g.vs[e.source]['name'], g.vs[e.target]['name']] + if set(vnames) == set(['A', 'B']): + self.assertTrue(e['attr'] == 'set') + else: + self.assertTrue(e['attr'] == 'set_too') + def testInPlaceAddition(self): g = Graph.Full(3) orig = g From 38fbd84ff389e42cb540b7b88b08cf7468c2b0df Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 23 Sep 2020 12:17:27 +0200 Subject: [PATCH 0252/1892] union, intersection and disjoint_union operators now throw ValueError when given no graphs --- src/igraph/operators.py | 6 +- tests/test_operators.py | 128 +++++++++++++++++++++++++++------------- 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 947cd0809..469486dc0 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -60,7 +60,7 @@ def disjoint_union(graphs): ngr = len(graphs) # Trivial cases if ngr == 0: - return None + raise ValueError("disjoint_union() needs at least one graph") if ngr == 1: return graphs[0].copy() # Now there are at least two graphs @@ -156,7 +156,7 @@ def union(graphs, byname='auto'): # Trivial cases if ngr == 0: - return None + raise ValueError("union() needs at least one graph") if ngr == 1: return graphs[0].copy() # Now there are at least two graphs @@ -336,7 +336,7 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): # Trivial cases if ngr == 0: - return None + raise ValueError("intersection() needs at least one graph") if ngr == 1: return graphs[0].copy() # Now there are at least two graphs diff --git a/tests/test_operators.py b/tests/test_operators.py index 064d4215d..5261d4386 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -33,6 +33,18 @@ def testMultiplication(self): self.assertTrue(g.vcount() == 9 and g.ecount() == 9 and g.clusters().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2]) + def testDifference(self): + g = Graph.Tree(7, 2) - Graph.Lattice([7]) + self.assertTrue(g.vcount() == 7 and g.ecount() == 5) + self.assertTrue(sorted(g.get_edgelist()) == [(0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]) + + def testDifferenceWithSelfLoop(self): + # https://github.com/igraph/igraph/issues/597# + g = Graph.Ring(10) + [(0, 0)] + g -= Graph.Ring(5) + self.assertTrue(g.vcount() == 10 and g.ecount() == 7) + self.assertTrue(sorted(g.get_edgelist()) == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]) + def testIntersection(self): g = Graph.Tree(7, 2) & Graph.Lattice([7]) self.assertTrue(g.get_edgelist() == [(0, 1)]) @@ -41,6 +53,17 @@ def testIntersectionMethod(self): g = Graph.Tree(7, 2).intersection(Graph.Lattice([7])) self.assertTrue(g.get_edgelist() == [(0, 1)]) + def testIntersectionNoGraphs(self): + self.assertRaises(ValueError, intersection, []) + + def testIntersectionSingle(self): + g1 = Graph.Tree(7, 2) + g = intersection([g1]) + self.assertTrue(g != g1) + self.assertTrue(g.vcount() == g1.vcount() and g.ecount() == g1.ecount()) + self.assertTrue(g.is_directed() == g1.is_directed()) + self.assertTrue(g.get_edgelist() == g1.get_edgelist()) + def testDisjointUnion(self): g1 = Graph.Tree(7, 2) g2 = Graph.Lattice([7]) @@ -53,6 +76,17 @@ def testDisjointUnion(self): g = disjoint_union([g1, g2]) self.assertTrue(g.vcount() == 14 and g.ecount() == 13) + def testDisjointUnionNoGraphs(self): + self.assertRaises(ValueError, disjoint_union, []) + + def testDisjointUnionSingle(self): + g1 = Graph.Tree(7, 2) + g = disjoint_union([g1]) + self.assertTrue(g != g1) + self.assertTrue(g.vcount() == g1.vcount() and g.ecount() == g1.ecount()) + self.assertTrue(g.is_directed() == g1.is_directed()) + self.assertTrue(g.get_edgelist() == g1.get_edgelist()) + def testUnion(self): g = Graph.Tree(7, 2) | Graph.Lattice([7]) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) @@ -61,53 +95,20 @@ def testUnion(self): (2, 6), (3, 4), (4, 5), (5, 6) ]) - def testDifference(self): - g = Graph.Tree(7, 2) - Graph.Lattice([7]) - self.assertTrue(g.vcount() == 7 and g.ecount() == 5) - self.assertTrue(sorted(g.get_edgelist()) == [(0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]) - - def testDifferenceWithSelfLoop(self): - # https://github.com/igraph/igraph/issues/597# - g = Graph.Ring(10) + [(0, 0)] - g -= Graph.Ring(5) - self.assertTrue(g.vcount() == 10 and g.ecount() == 7) - self.assertTrue(sorted(g.get_edgelist()) == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]) - def testUnionMethod(self): g = Graph.Tree(7, 2).union(Graph.Lattice([7])) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) - def testIntersectionMany(self): - gs = [Graph.Tree(7, 2), Graph.Lattice([7])] - g = intersection(gs) - self.assertTrue(g.get_edgelist() == [(0, 1)]) - - def testIntersectionManyAttributes(self): - gs = [Graph.Tree(7, 2), Graph.Lattice([7])] - gs[0]['attr'] = 'graph1' - gs[0].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] - gs[1].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] - gs[0].vs[0]['attr'] = 'set' - gs[1].vs[5]['attr'] = 'set_too' - g = intersection(gs) - names = g.vs['name'] - self.assertTrue(g['attr'] == 'graph1') - self.assertTrue(g.vs[names.index('one')]['attr'] == 'set') - self.assertTrue(g.vs[names.index('six')]['attr'] == 'set_too') - self.assertTrue(g.ecount() == 1) - self.assertTrue( - set(g.get_edgelist()[0]) == set([names.index('one'), names.index('two')]), - ) + def testUnionNoGraphs(self): + self.assertRaises(ValueError, union, []) - def testIntersectionManyEdgemap(self): - gs = [ - Graph.Formula('A-B'), - Graph.Formula('A-B,C-D'), - ] - gs[0].es[0]['attr'] = 'set' - gs[1].es[1]['attr'] = 'set_too' - g = intersection(gs) - self.assertTrue(g.es['attr'] == ['set']) + def testUnionSingle(self): + g1 = Graph.Tree(7, 2) + g = union([g1]) + self.assertTrue(g != g1) + self.assertTrue(g.vcount() == g1.vcount() and g.ecount() == g1.ecount()) + self.assertTrue(g.is_directed() == g1.is_directed()) + self.assertTrue(g.get_edgelist() == g1.get_edgelist()) def testUnionMany(self): gs = [Graph.Tree(7, 2), Graph.Lattice([7]), Graph.Lattice([7])] @@ -147,6 +148,49 @@ def testUnionManyEdgemap(self): else: self.assertTrue(e['attr'] == 'set_too') + def testIntersectionNoGraphs(self): + self.assertRaises(ValueError, intersection, []) + + def testIntersectionSingle(self): + g1 = Graph.Tree(7, 2) + g = intersection([g1]) + self.assertTrue(g != g1) + self.assertTrue(g.vcount() == g1.vcount() and g.ecount() == g1.ecount()) + self.assertTrue(g.is_directed() == g1.is_directed()) + self.assertTrue(g.get_edgelist() == g1.get_edgelist()) + + def testIntersectionMany(self): + gs = [Graph.Tree(7, 2), Graph.Lattice([7])] + g = intersection(gs) + self.assertTrue(g.get_edgelist() == [(0, 1)]) + + def testIntersectionManyAttributes(self): + gs = [Graph.Tree(7, 2), Graph.Lattice([7])] + gs[0]['attr'] = 'graph1' + gs[0].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] + gs[1].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] + gs[0].vs[0]['attr'] = 'set' + gs[1].vs[5]['attr'] = 'set_too' + g = intersection(gs) + names = g.vs['name'] + self.assertTrue(g['attr'] == 'graph1') + self.assertTrue(g.vs[names.index('one')]['attr'] == 'set') + self.assertTrue(g.vs[names.index('six')]['attr'] == 'set_too') + self.assertTrue(g.ecount() == 1) + self.assertTrue( + set(g.get_edgelist()[0]) == set([names.index('one'), names.index('two')]), + ) + + def testIntersectionManyEdgemap(self): + gs = [ + Graph.Formula('A-B'), + Graph.Formula('A-B,C-D'), + ] + gs[0].es[0]['attr'] = 'set' + gs[1].es[1]['attr'] = 'set_too' + g = intersection(gs) + self.assertTrue(g.es['attr'] == ['set']) + def testInPlaceAddition(self): g = Graph.Full(3) orig = g From a44e0e525261ff88981552fba89ab69a4fb68d98 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 23 Sep 2020 20:37:36 +1000 Subject: [PATCH 0253/1892] Clear function and improve delete vertices and edges (#320) --- src/_igraph/graphobject.c | 34 ++++++++++++++++++++++++++++------ src/igraph/__init__.py | 37 +++++++++++++++++++++++++------------ tests/test_basic.py | 19 +++++++++++++++++++ 3 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d39a35702..80b4afb12 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -567,10 +567,21 @@ PyObject *igraphmodule_Graph_add_vertices(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_delete_vertices(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *list; + PyObject *list = 0; igraph_vs_t vs; - if (!PyArg_ParseTuple(args, "O", &list)) return NULL; + if (!PyArg_ParseTuple(args, "|O", &list)) return NULL; + + /* no arguments means delete all. */ + + /*Py_None also means all for now, but it is deprecated */ + if (list == Py_None) { + PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " + "deprecated since igraph 0.8.3, please use " + "Graph.delete_vertices() instead"); + } + + /* this already converts no arguments and Py_None to all vertices */ if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, 0, 0)) return NULL; if (igraph_delete_vertices(&self->g, vs)) { @@ -631,13 +642,23 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *list; + PyObject *list = 0; igraph_es_t es; static char *kwlist[] = { "edges", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &list)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &list)) return NULL; + /* no arguments means delete all. */ + + /*Py_None also means all for now, but it is deprecated */ + if (list == Py_None) { + PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " + "deprecated since igraph 0.8.3, please use " + "Graph.delete_vertices() instead"); + } + + /* this already converts no arguments and Py_None to all vertices */ if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { /* something bad happened during conversion, return immediately */ return NULL; @@ -11910,7 +11931,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "delete_vertices(vs)\n\n" "Deletes vertices and all its edges from the graph.\n\n" "@param vs: a single vertex ID or the list of vertex IDs\n" - " to be deleted.\n"}, + " to be deleted. No argument deletes all vertices.\n"}, /* interface to igraph_add_edges */ {"add_edges", (PyCFunction) igraphmodule_Graph_add_edges, @@ -11929,7 +11950,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "All vertices will be kept, even if they lose all their edges.\n" "Nonexistent edges will be silently ignored.\n\n" "@param es: the list of edges to be removed. Edges are identifed by\n" - " edge IDs. L{EdgeSeq} objects are also accepted here.\n"}, + " edge IDs. L{EdgeSeq} objects are also accepted here. No argument\n" + " deletes all edges.\n"}, /* interface to igraph_degree */ {"degree", (PyCFunction) igraphmodule_Graph_degree, diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e61d97a40..364ae550d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -383,30 +383,32 @@ def delete_edges(self, *args, **kwds): """Deletes some edges from the graph. The set of edges to be deleted is determined by the positional and - keyword arguments. If any keyword argument is present, or the - first positional argument is callable, an edge - sequence is derived by calling L{EdgeSeq.select} with the same - positional and keyword arguments. Edges in the derived edge sequence - will be removed. Otherwise the first positional argument is considered - as follows: - - - C{None} - deletes all edges + keyword arguments. If the function is called without any arguments, + all edges are deleted. If any keyword argument is present, or the + first positional argument is callable, an edge sequence is derived by + calling L{EdgeSeq.select} with the same positional and keyword + arguments. Edges in the derived edge sequence will be removed. + Otherwise the first positional argument is considered as follows: + + - C{None} - deletes all edges (deprecated since 0.8.3) - a single integer - deletes the edge with the given ID - a list of integers - deletes the edges denoted by the given IDs - a list of 2-tuples - deletes the edges denoted by the given source-target vertex pairs. When multiple edges are present between a given source-target vertex pair, only one is removed. + + @deprecated: L{Graph.delete_edges(None)} has been replaced by + L{Graph.delete_edges()} - with no arguments - since igraph 0.8.3. """ if len(args) == 0 and len(kwds) == 0: - raise ValueError("expected at least one argument") - if len(kwds)>0 or (hasattr(args[0], "__call__") and \ - not isinstance(args[0], EdgeSeq)): + return GraphBase.delete_edges(self) + + if len(kwds) > 0 or (callable(args[0]) and not isinstance(args[0], EdgeSeq)): edge_seq = self.es(*args, **kwds) else: edge_seq = args[0] return GraphBase.delete_edges(self, edge_seq) - def indegree(self, *args, **kwds): """Returns the in-degrees in a list. @@ -492,6 +494,17 @@ def biconnected_components(self, return_articulation_points=False): return clustering blocks = biconnected_components + def clear(self): + """clear() + + Clears the graph, deleting all vertices, edges, and attributes. + + @see: L{Graph.delete_vertices} and L{Graph.delete_edges}. + """ + self.delete_vertices() + for attr in self.attributes(): + del self[attr] + def cohesive_blocks(self): """cohesive_blocks() diff --git a/tests/test_basic.py b/tests/test_basic.py index 6deebd4d7..5368db09e 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -178,6 +178,10 @@ def testDeleteVertices(self): self.assertRaises(ValueError, g.delete_vertices, "no-such-vertex") self.assertRaises(InternalError, g.delete_vertices, 2) + # Delete all vertices + g.delete_vertices() + self.assertEqual(0, g.vcount()) + def testAddEdge(self): g = Graph() g.add_vertices(["spam", "bacon", "eggs", "ham"]) @@ -274,6 +278,21 @@ def testDeleteEdges(self): self.assertRaises(ValueError, g.delete_edges, [("A", "C")]) self.assertRaises(ValueError, g.delete_edges, [(0, 15)]) + # Delete all edges + g.delete_edges() + self.assertEqual(0, g.ecount()) + + def testClear(self): + g = Graph.Famous("petersen") + g["name"] = list("petersen") + + # Clearing the graph + g.clear() + + self.assertEqual(0, g.vcount()) + self.assertEqual(0, g.ecount()) + self.assertEqual([], g.attributes()) + def testGraphGetEid(self): g = Graph.Famous("petersen") g.vs["name"] = list("ABCDEFGHIJ") From 6c13eadf5841a0f72f8d3a843a77ad13d0a4f310 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 25 Sep 2020 17:52:53 +0200 Subject: [PATCH 0254/1892] removed unused variable [ci skip] --- src/_igraph/operators.c | 1 - vendor/source/igraph | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 3de9d4c15..7f82f2b35 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -36,7 +36,6 @@ PyObject *igraphmodule__disjoint_union(PyObject *self, PyObject *it, *graphs; long int no_of_graphs; igraph_vector_ptr_t gs; - igraphmodule_GraphObject *o; PyObject *result; PyTypeObject *result_type; igraph_t g; diff --git a/vendor/source/igraph b/vendor/source/igraph index 878de1310..21b37c4b7 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 878de131016b23dc3b66d24e598c41325715b21f +Subproject commit 21b37c4b786ae77736aca8f8dfa4017418b9d486 From 10c2579e6b3fa579950ed08037cbd88d4351103c Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Sat, 26 Sep 2020 10:12:07 +0200 Subject: [PATCH 0255/1892] community_leiden: corrected unitialized variable. (#332) --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 80b4afb12..765f7c3be 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11639,7 +11639,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, PyObject *edge_weights_o = Py_None; PyObject *node_weights_o = Py_None; PyObject *initial_membership_o = Py_None; - PyObject *res; + PyObject *res = Py_None; int error = 0, i; long int n_iterations = 2; From 0c8b85880f1af6f32e0ae139a7ceca256164ae1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Sat, 26 Sep 2020 13:29:32 +0200 Subject: [PATCH 0256/1892] Docs: fix broken link in tutorial --- doc/source/tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 935029af9..b3ffe7752 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -65,7 +65,7 @@ The command-line startup script imports all of |igraph|'s methods and objects in namespace, so it is practically equivalent to ``from igraph import *``. The difference between the two approaches (apart from saving some typing) is that the command-line script checks whether you have any of Python's more advanced shells installed and uses that instead of the -standard Python shell. Currently the module looks for `IPython `_ and +standard Python shell. Currently the module looks for `IPython `_ and IDLE (the Tcl/Tk-based graphical shell supplied with Python). If neither IPython nor IDLE is installed, the startup script launches the default Python shell. You can also modify the order in which these shells are searched by tweaking |igraph|'s configuration file From 679943e2c415dcfa2067535b1b2b3363334ff06e Mon Sep 17 00:00:00 2001 From: kmankinen <22212710+kmankinen@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:12:09 +0300 Subject: [PATCH 0257/1892] Adjacency list example to tutorial (#334) Co-authored-by: Katja Mankinen --- doc/source/tutorial.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index b3ffe7752..76acd1919 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -229,7 +229,7 @@ Let's do the same with a stochastic generator! IGRAPH U---- 100 516 -- + attr: x (v), y (v) -TODO: discuss what the ``+ attr`` line means. +where ``+ attr`` shows names of the attributes for vertices (v) and edges (e). :meth:`Graph.GRG` generates a geometric random graph: *n* points are chosen randomly and uniformly inside the unit square and pairs of points closer to each other than a predefined @@ -637,7 +637,14 @@ you look them up by names, the other one will be available only by its index. Treating a graph as an adjacency matrix ======================================= -TODO +Adjacency matrix is another way to form a graph. In adjacency matrix, rows and columns are labeled by graph vertices: the elements of the matrix indicate whether the vertices *i* and *j* have a common edge (*i, j*). +The adjacency matrix for the example graph is + +>>> g.get_adjacency() +Matrix([[0, 1, 1, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 1, 1, 1, 0], [0, 0, 1, 0, 1, 0, 1], [0, 0, 1, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 0, 1, 0]]) + +For example, Claire (``[1, 0, 0, 1, 1, 1, 0]``) is directly connected to Alice (who has vertex index 0), Dennis (index 3), +Esther (index 4), and Frank (index 5), but not to Bob (index 1) nor George (index 6). Layouts and plotting ==================== From a5815f4eeddbb3c026a47bd3bde71e12e092b623 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Oct 2020 16:27:17 +0200 Subject: [PATCH 0258/1892] bumped vendor/source/igraph to fix a bug in the RT layout --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 21b37c4b7..137b56963 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 21b37c4b786ae77736aca8f8dfa4017418b9d486 +Subproject commit 137b569634432c96f6ee3d4f88e09cbaa1b3da58 From 9b0bdfae08d25bf4918a7172d02268247c123afe Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 2 Oct 2020 10:20:01 +0200 Subject: [PATCH 0259/1892] updated documentation for eigenvector centrality and the C core itself --- src/_igraph/graphobject.c | 15 +++++++++++++++ vendor/source/igraph | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 765f7c3be..8102a059d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13107,6 +13107,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "eigenvector_centrality(directed=True, scale=True, weights=None, return_eigenvalue=False, arpack_options=None)\n\n" "Calculates the eigenvector centralities of the vertices in a graph.\n\n" + "Eigenvector centrality is a measure of the importance of a node in a\n" + "network. It assigns relative scores to all nodes in the network based\n" + "on the principle that connections from high-scoring nodes contribute\n" + "more to the score of the node in question than equal connections from\n" + "low-scoring nodes. In practice, the centralities are determined by calculating\n" + "eigenvector corresponding to the largest positive eigenvalue of the\n" + "adjacency matrix. In the undirected case, this function considers\n" + "the diagonal entries of the adjacency matrix to be twice the number of\n" + "self-loops on the corresponding vertex.\n\n" + "In the directed case, the left eigenvector of the adjacency matrix is\n" + "calculated. In other words, the centrality of a vertex is proportional\n" + "to the sum of centralities of vertices pointing to it.\n\n" + "Eigenvector centrality is meaningful only for connected graphs.\n" + "Graphs that are not connected should be decomposed into connected\n" + "components, and the eigenvector centrality calculated for each separately.\n\n" "@param directed: whether to consider edge directions in a directed\n" " graph. Ignored for undirected graphs.\n" "@param scale: whether to normalize the centralities so the largest\n" diff --git a/vendor/source/igraph b/vendor/source/igraph index 137b56963..3ed99a2e9 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 137b569634432c96f6ee3d4f88e09cbaa1b3da58 +Subproject commit 3ed99a2e9c9005258aadead548750cadcc2221f1 From bad92f64db77fc56cb738fd7a5bca2f1c7a5406c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 2 Oct 2020 14:03:11 +0200 Subject: [PATCH 0260/1892] updated igraph subrepo to 0.8.3 [ci skip] --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 3ed99a2e9..cafe1e4d4 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 3ed99a2e9c9005258aadead548750cadcc2221f1 +Subproject commit cafe1e4d447dded9f640fd4f14b7973bef045d62 From b2face64cda748dd6806bed617359bf641c87407 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Oct 2020 21:16:23 +0200 Subject: [PATCH 0261/1892] speed up biconnected_components() postprocessing, fixes #281 --- src/igraph/__init__.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 364ae550d..43696c7ed 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -481,11 +481,14 @@ def biconnected_components(self, return_articulation_points=False): trees = GraphBase.biconnected_components(self, False) clusters = [] - for tree in trees: - cluster = set() - for edge in self.es[tree]: - cluster.update(edge.tuple) - clusters.append(sorted(cluster)) + if trees: + edgelist = self.get_edgelist() + for tree in trees: + cluster = set() + for edge_id in tree: + cluster.update(edgelist[edge_id]) + clusters.append(sorted(cluster)) + clustering = VertexCover(self, clusters) if return_articulation_points: From 532f034500809d3f5c5f076027a4132a70fbb558 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Oct 2020 21:24:19 +0200 Subject: [PATCH 0262/1892] Appveyor: switch to an MSYS2 mirror because repo.msys2.org is down at the moment [ci skip] --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7e3ea6a77..b6e8f8d73 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,8 +24,8 @@ platform: install: # update msys2 keyring first - - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" - - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - bash -lc "curl -O https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - bash -lc "curl -O https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" - bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" # update msys2 @@ -33,7 +33,7 @@ install: - bash -lc "pacman --noconfirm -Sy" - bash -lc "pacman --needed --noconfirm -S zstd" - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - - pip install cibuildwheel==1.1.0 + - pip install cibuildwheel==1.6.1 before_build: - git submodule update --init --recursive From e241981762d141b4b2661a71ad6e691dc5ccba6e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Oct 2020 21:24:39 +0200 Subject: [PATCH 0263/1892] drop Python 3.5, add Python 3.9 to follow Python's branch status --- .travis.yml | 6 +++--- README.md | 4 ++-- tox.ini | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf3a43bd0..3293b1cd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,10 @@ language: python python: - "2.7" - - "3.5" - "3.6" - "3.7" - "3.8" + - "3.9" - pypy3 addons: @@ -34,7 +34,7 @@ jobs: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - - sudo python -m pip install cibuildwheel==1.1.0 + - sudo python -m pip install cibuildwheel==1.6.1 script: - python setup.py sdist - python -m cibuildwheel --output-dir wheelhouse @@ -66,7 +66,7 @@ jobs: - CIBW_BEFORE_BUILD="python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - - python -m pip install cibuildwheel==1.1.0 + - python -m pip install cibuildwheel==1.6.1 script: - python -m cibuildwheel --output-dir wheelhouse before_deploy: *before_deploy_releases diff --git a/README.md b/README.md index f8b13693b..a084ce5e4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Travis CI](https://img.shields.io/travis/igraph/python-igraph)](https://travis-ci.org/igraph/python-igraph) -[![PyPI pyversions](https://img.shields.io/badge/python-2.7%20%7C%203.5%20%7C%203.6%20%7C%203.7%20%7C%203.8-blue)](https://pypi.python.org/pypi/python-igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-2.7%20%7C%203.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) Python interface for the igraph library @@ -155,7 +155,7 @@ faster than the first one as the C core does not need to be recompiled. We aim to keep up with the development cycle of Python and support all official Python versions that have not reached their end of life yet. Currently this -means that we support Python 3.5 to 3.8, inclusive. Please refer to [this +means that we support Python 3.6 to 3.9, inclusive. Please refer to [this page](https://devguide.python.org/#branchstatus) for the status of Python branches and let us know if you encounter problems with `python-igraph` on any of the non-EOL Python versions. diff --git a/tox.ini b/tox.ini index 84fac76bb..d6f330ab3 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py35, py36, py37, py38, pypy, pypy3 +envlist = py27, py36, py37, py38, py39, pypy, pypy3 [testenv] commands = python -m unittest From 656d8d7cb9f08bbe5f0b0b819073a3a2391c70f1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Oct 2020 21:32:46 +0200 Subject: [PATCH 0264/1892] Appveyor: revert to cibuildwheel 1.1.0 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b6e8f8d73..233d7fa61 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ install: - bash -lc "pacman --noconfirm -Sy" - bash -lc "pacman --needed --noconfirm -S zstd" - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - - pip install cibuildwheel==1.6.1 + - pip install cibuildwheel==1.1.0 before_build: - git submodule update --init --recursive From 6263c44418e91fa2028e9a5287feecc69e716a7b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Oct 2020 22:31:53 +0200 Subject: [PATCH 0265/1892] Travis: Python 3.9 is still referred to as 3.9-dev --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3293b1cd4..ca2f1f73c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ python: - "3.6" - "3.7" - "3.8" - - "3.9" + - "3.9-dev" - pypy3 addons: From 50a8846597698cd5c7ce4f0cba0835485a695919 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 09:46:33 +0200 Subject: [PATCH 0266/1892] Travis: don't install NumPy / SciPy on py39 because there are no wheels yet --- tox.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tox.ini b/tox.ini index d6f330ab3..b660866ff 100644 --- a/tox.ini +++ b/tox.ini @@ -19,6 +19,11 @@ setenv = [testenv:py27] commands = python -m unittest discover +[testenv:py39] +deps = + networkx + pandas + [flake8] max-line-length = 80 select = C,E,F,W,B,B950 From ed8b329b950b54b7403f28cbf21252c94eb7e06e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 09:49:22 +0200 Subject: [PATCH 0267/1892] Appveyor: it looks like cibuildwheel 1.6.1 requires Python 3 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 233d7fa61..867d6d70f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,7 @@ install: - bash -lc "pacman --noconfirm -Sy" - bash -lc "pacman --needed --noconfirm -S zstd" - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - - pip install cibuildwheel==1.1.0 + - pip3 install cibuildwheel==1.6.1 before_build: - git submodule update --init --recursive From 034fa38a633383e1ac630e8a8d35a1179f7c92ea Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 10:51:11 +0200 Subject: [PATCH 0268/1892] Appveyor: force using Python 3 --- appveyor.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 867d6d70f..b80edf18c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ environment: CIBW_BEFORE_BUILD: python setup.py build_c_core CIBW_TEST_COMMAND: "cd {project} && python -m unittest" IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" + PYTHON: "C:\\Python37" matrix: - CIBW_BUILD: "*-win32" @@ -33,7 +34,14 @@ install: - bash -lc "pacman --noconfirm -Sy" - bash -lc "pacman --needed --noconfirm -S zstd" - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - - pip3 install cibuildwheel==1.6.1 + + # prepare Python + - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + - "python --version" + - "python -m pip install --upgrade pip" + + # install cibuildwheel + - pip install cibuildwheel==1.6.1 before_build: - git submodule update --init --recursive From aa7f8194c7ee128b699a8278ce6d62cc01f25747 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 12:15:16 +0200 Subject: [PATCH 0269/1892] Appveyor: don't build for Python 3.5, we dropped supporting it --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b80edf18c..6464920c1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,12 +10,13 @@ environment: matrix: - CIBW_BUILD: "*-win32" - CIBW_SKIP: "cp27-*" + CIBW_SKIP: "cp27-* cp35-*" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" - CIBW_BUILD: "*-win_amd64" + CIBW_SKIP: "cp27-* cp35-*" MSYSTEM: MINGW64 PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x64" From 55f69be8c78fc9cb8a8c80f061a634056c5a8847 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 12:16:56 +0200 Subject: [PATCH 0270/1892] Travis: don't install pandas either for py39 --- tox.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index b660866ff..055ea15f8 100644 --- a/tox.ini +++ b/tox.ini @@ -20,9 +20,10 @@ setenv = commands = python -m unittest discover [testenv:py39] +# py39 support is still sparse; most of the optional dependencies have no +# wheels for Python 3.9 yet so we install only those where they do deps = networkx - pandas [flake8] max-line-length = 80 From df696700444af9180d361fdb7f9cf1b2f615b173 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 14:50:32 +0200 Subject: [PATCH 0271/1892] Travis: trying to use Python 3 as well for cibuildwheel --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca2f1f73c..0525cceb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,10 +34,10 @@ jobs: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - - sudo python -m pip install cibuildwheel==1.6.1 + - sudo python3 -m pip install cibuildwheel==1.6.1 script: - python setup.py sdist - - python -m cibuildwheel --output-dir wheelhouse + - python3 -m cibuildwheel --output-dir wheelhouse before_deploy: &before_deploy_releases - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" @@ -61,14 +61,15 @@ jobs: - stage: wheels os: osx + osx_image: xcode11.2 language: shell env: - CIBW_BEFORE_BUILD="python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: - - python -m pip install cibuildwheel==1.6.1 + - python3 -m pip install cibuildwheel==1.6.1 script: - - python -m cibuildwheel --output-dir wheelhouse + - python3 -m cibuildwheel --output-dir wheelhouse before_deploy: *before_deploy_releases deploy: *deploy_releases From b6595e46189f0af5d1fc085ff2b3edd2e802dbb5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 16:15:38 +0200 Subject: [PATCH 0272/1892] Travis: install pip for Python 3 in the image --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0525cceb8..000da9860 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ jobs: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" install: + - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - sudo python3 -m pip install cibuildwheel==1.6.1 script: - python setup.py sdist From fccab29c1742bc73d7b684121bb6ee5e48d04663 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Oct 2020 17:29:44 +0200 Subject: [PATCH 0273/1892] Travis: make setup.py sdist quieter so we don't hit the log limits --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 000da9860..e9486e7c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ jobs: - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - sudo python3 -m pip install cibuildwheel==1.6.1 script: - - python setup.py sdist + - python setup.py -q sdist - python3 -m cibuildwheel --output-dir wheelhouse before_deploy: &before_deploy_releases - git config --local user.name "ntamas" From b17676fb1267223a5ebbb740bdaf781d7602e466 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 07:35:39 +0200 Subject: [PATCH 0274/1892] Appveyor: repo.msys2.org works again --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6464920c1..a1cfd8375 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,8 +26,8 @@ platform: install: # update msys2 keyring first - - bash -lc "curl -O https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" - - bash -lc "curl -O https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" - bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" # update msys2 From 81e0ff9b2138555b690e04fce59218fe49387907 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 07:45:22 +0200 Subject: [PATCH 0275/1892] enable silent rules during igraph compilation to make Travis output shorter --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8aa98e59d..511590b2f 100644 --- a/setup.py +++ b/setup.py @@ -300,7 +300,7 @@ def compile_in(self, build_folder, source_folder=None): os.chdir(build_folder) print("Configuring igraph...") - configure_args = ["--disable-tls"] + configure_args = ["--disable-tls", "--enable-silent-rules"] if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) retcode = subprocess.call( From 84d0505c7c1537ea54b1003c73493d6577387a69 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 12:13:28 +0200 Subject: [PATCH 0276/1892] bumped version to 0.8.3 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 5b83e8332..3a1483d4e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.8.2' +version = '0.8.3' # The full version, including alpha/beta/rc tags. -release = '0.8.2' +release = '0.8.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index b523d76db..aea240828 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 8, 2) +__version_info__ = (0, 8, 3) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 6f95052e809c92b0b0e2e374e202ed0ffa6fb5fa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 15:20:44 +0200 Subject: [PATCH 0277/1892] igraph.operators module: declare explicitly what is being exported --- src/igraph/operators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 469486dc0..6d19075cc 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -37,6 +37,8 @@ from collections import defaultdict, Counter from warnings import warn +__all__ = ("disjoint_union", "union", "intersection") + def disjoint_union(graphs): """Graph disjoint union. From de7b34f04c2405bd89063764cfa2c47ef52289a4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 15:45:34 +0200 Subject: [PATCH 0278/1892] don't use a wildcard import in igraph.operators --- src/igraph/operators.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 6d19075cc..da5efe31f 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -29,10 +29,7 @@ 02110-1301 USA """ -# pylint: disable-msg=W0401 -# W0401: wildcard import -from igraph._igraph import * -from igraph._igraph import _union, _intersection, _disjoint_union +from igraph._igraph import GraphBase, _union, _intersection, _disjoint_union from collections import defaultdict, Counter from warnings import warn From c3379d26e550abc71d176c53e475b10b960f9fd6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 16:19:52 +0200 Subject: [PATCH 0279/1892] igraph.operators: fix documentation header for Epydoc --- src/igraph/operators.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index da5efe31f..a9aee0014 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -1,14 +1,11 @@ # vim:ts=4:sw=4:sts=4:et # -*- coding: utf-8 -*- -""" -IGraph library. - -@undocumented: deprecated, _graphmethod, _add_proxy_methods, _layout_method_wrapper, - _3d_version_for -""" +"""Implementation of union, disjoint union and intersection operators.""" from __future__ import with_statement +__all__ = ("disjoint_union", "union", "intersection") +__docformat__ = "restructuredtext en" __license__ = u""" Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -34,8 +31,6 @@ from collections import defaultdict, Counter from warnings import warn -__all__ = ("disjoint_union", "union", "intersection") - def disjoint_union(graphs): """Graph disjoint union. From ab408676c15d38047d2768599c7ccfe027893385 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 16:44:11 +0200 Subject: [PATCH 0280/1892] added missing global.rst include in several doc chapters --- doc/source/analysis.rst | 2 ++ doc/source/generation.rst | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index a4ab5ec74..8c15b4b83 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -1,3 +1,5 @@ +.. include:: include/global.rst + Graph analysis ============== |igraph| enables analysis of graphs/networks from simple operations such as adding and removing nodes to complex theoretical constructs such as community detection. Read the `API documentation`_ for details on each function and class. diff --git a/doc/source/generation.rst b/doc/source/generation.rst index a3f5b952e..991e43dfd 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -1,3 +1,5 @@ +.. include:: include/global.rst + Graph generation ================ From 64e1fecb1f881c0676cdc9177bc073bdc904acd7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 17:29:24 +0200 Subject: [PATCH 0281/1892] fixed several Epydoc warnings --- src/_igraph/graphobject.c | 2 +- src/igraph/__init__.py | 72 +++++++++++++++++++-------------------- src/igraph/operators.py | 4 +-- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8102a059d..1cc937635 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14800,7 +14800,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"isomorphic_bliss", (PyCFunction) igraphmodule_Graph_isomorphic_bliss, METH_VARARGS | METH_KEYWORDS, "isomorphic_bliss(other, return_mapping_12=False, return_mapping_21=False,\n" - " sh1=\"fm\", sh2=None)\n\n" + " sh1=\"fm\", sh2=None, color1=None, color2=None)\n\n" "Checks whether the graph is isomorphic to another graph, using the\n" "BLISS isomorphism algorithm.\n\n" "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 43696c7ed..8646d6d3c 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -267,7 +267,7 @@ def add_edges(self, es, attributes=None): @param es: the list of edges to be added. Every edge is represented with a tuple containing the vertex IDs or names of the two endpoints. Vertices are enumerated from zero. - @params attributes: dict of sequences, all of length equal to the + @param attributes: dict of sequences, all of length equal to the number of edges to be added, containing the attributes of the new edges. """ @@ -302,23 +302,23 @@ def add_vertex(self, name=None, **kwds): return vertex def add_vertices(self, n, attributes=None): - """add_vertices(n) + """add_vertices(n, attributes=None) Adds some vertices to the graph. + Note that if C{n} is a sequence of strings, indicating the names of the + new vertices, and attributes has a key C{name}, the two conflict. In + that case the attribute will be applied. + @param n: the number of vertices to be added, or the name of a single vertex to be added, or a sequence of strings, each corresponding to the name of a vertex to be added. Names will be assigned to the C{name} vertex attribute. - @params attributes: dict of sequences, all of length equal to the + @param attributes: dict of sequences, all of length equal to the number of vertices to be added, containing the attributes of the new vertices. If n is a string (so a single vertex is added), then the values of this dict are the attributes themselves, but if n=1 then they have to be lists of length 1. - - Note that if n is a sequence of strings, indicating the names of the - new vertices, and attributes has a key 'name', the two conflict. In - that case the attribute will be applied. """ if isinstance(n, basestring): # Adding a single vertex with a name @@ -639,13 +639,15 @@ def get_adjacency(self, type=GET_ADJACENCY_BOTH, attribute=None, \ return Matrix(data) def get_adjacency_sparse(self, attribute=None): - """Returns the adjacency matrix of a graph as scipy csr matrix. + """Returns the adjacency matrix of a graph as a SciPy CSR matrix. + @param attribute: if C{None}, returns the ordinary adjacency matrix. When the name of a valid edge attribute is given here, the matrix returned will contain the default value at the places where there is no edge or the value of the given attribute where there is an edge. - @return: the adjacency matrix as a L{scipy.sparse.csr_matrix}.""" + @return: the adjacency matrix as a C{scipy.sparse.csr_matrix}. + """ try: from scipy import sparse except ImportError: @@ -697,7 +699,7 @@ def get_adjedgelist(self, *args, **kwds): return self.get_inclist(*args, **kwds) def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): - """get_all_simple_paths(v, to=None, mode=OUT) + """get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT) Calculates all the simple paths from a given node to some other nodes (or all of them) in a graph. @@ -1869,27 +1871,27 @@ def to_graph_tool( edge_attributes=None): """Converts the graph to graph-tool - @param graph_attributes: dictionary of graph attributes to transfer. - Keys are attributes from the graph, values are data types (see - below). C{None} means no graph attributes are transferred. - @param vertex_attributes: dictionary of vertex attributes to transfer. - Keys are attributes from the vertices, values are data types (see - below). C{None} means no vertex attributes are transferred. - @param edge_attributes: dictionary of edge attributes to transfer. - Keys are attributes from the edges, values are data types (see - below). C{None} means no vertex attributes are transferred. - Data types: graph-tool only accepts specific data types. See the following web page for a list: https://graph-tool.skewed.de/static/doc/quickstart.html - NOTE: because of the restricted data types in graph-tool, vertex and + Note: because of the restricted data types in graph-tool, vertex and edge attributes require to be type-consistent across all vertices or edges. If you set the property for only some vertices/edges, the other will be tagged as None in python-igraph, so they can only be converted to graph-tool with the type 'object' and any other conversion will fail. + + @param graph_attributes: dictionary of graph attributes to transfer. + Keys are attributes from the graph, values are data types (see + below). C{None} means no graph attributes are transferred. + @param vertex_attributes: dictionary of vertex attributes to transfer. + Keys are attributes from the vertices, values are data types (see + below). C{None} means no vertex attributes are transferred. + @param edge_attributes: dictionary of edge attributes to transfer. + Keys are attributes from the edges, values are data types (see + below). C{None} means no vertex attributes are transferred. """ import graph_tool as gt @@ -3018,7 +3020,7 @@ def GRG(klass, n, radius, torus=False): @classmethod def Incidence(klass, *args, **kwds): - """Incidence(matrix, directed=False, mode=ALL, multiple=False) + """Incidence(matrix, directed=False, mode=ALL, multiple=False, weighted=None) Creates a bipartite graph from an incidence matrix. @@ -3074,7 +3076,7 @@ def Incidence(klass, *args, **kwds): @classmethod def DataFrame(klass, edges, directed=True, vertices=None): - """DataFrame(directed=True, vertices=None) + """DataFrame(edges, directed=True, vertices=None) Generates a graph from one or two dataframes. @@ -3773,44 +3775,42 @@ def summary(self, verbosity=0, width=None, *args, **kwds): return str(GraphSummary(self, verbosity, width, *args, **kwds)) def disjoint_union(self, other): - '''disjoint_union(self, other) + """disjoint_union(self, other) Creates the disjoint union of two (or more) graphs. - @param graphs: graph or list of graphs to be united with - the current one. + @param other: graph or list of graphs to be united with the current one. @return: the disjoint union graph - ''' + """ if isinstance(other, GraphBase): other = [other] return disjoint_union([self] + other) def union(self, other, byname='auto'): - '''union(self, other) + """union(self, other, byname="auto") Creates the union of two (or more) graphs. - @param graphs: graph or list of graphs to be united with - the current one. + @param other: graph or list of graphs to be united with the current one. @param byname: whether to use vertex names instead of ids. See - L{igraph.union} for details. + L{igraph.union} for details. @return: the union graph - ''' + """ if isinstance(other, GraphBase): other = [other] return union([self] + other, byname=byname) def intersection(self, other, byname='auto'): - '''intersection(self, other) + """intersection(self, other, byname="auto") Creates the intersection of two (or more) graphs. @param other: graph or list of graphs to be intersected with - the current one. + the current one. @param byname: whether to use vertex names instead of ids. See - L{igraph.intersection} for details. + L{igraph.intersection} for details. @return: the intersection graph - ''' + """ if isinstance(other, GraphBase): other = [other] return intersection([self] + other, byname=byname) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index a9aee0014..00f8e0c13 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -307,8 +307,8 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): False, ignore vertex names. If True, merge vertices based on names. If 'auto', use True if all graphs have named vertices and False otherwise (in the latter case, a warning is generated too). - @keep_all_vertices: bool specifying if vertices that are not present in all - graphs should be kept in the intersection. + @param keep_all_vertices: bool specifying if vertices that are not present + in all graphs should be kept in the intersection. @return: the intersection graph """ From ea43a546b3463d1874af0ad907bbc55a200d7acf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 17:29:34 +0200 Subject: [PATCH 0282/1892] Travis: skip generating wheels for Python 3.5 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e9486e7c0..d4b4da247 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ jobs: env: - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND="cd {project} && python -m unittest" + - CIBW_SKIP="cp35-*" install: - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - sudo python3 -m pip install cibuildwheel==1.6.1 From a3b48ac4e1a55dfe218c68038031ebcddec9a19b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Oct 2020 20:07:57 +0200 Subject: [PATCH 0283/1892] fix three more warnings in the documentation generation --- doc/source/generation.rst | 2 +- src/igraph/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 991e43dfd..2e689dd36 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -55,7 +55,7 @@ If you don't specify a format, |igraph| will try to figure it out or, if that fa From external libraries +++++++++++++++++++++++ -|igraph| can read from and write to `networkx`_ and `graph-tool`_ graph formats: +|igraph| can read from and write to `networkx` and `graph-tool` graph formats: >>> g = Graph.from_networkx(nwx) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 8646d6d3c..20e9e9cbd 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -260,7 +260,7 @@ def add_edge(self, source, target, **kwds): return edge def add_edges(self, es, attributes=None): - """add_edges(es) + """add_edges(es, attributes=None) Adds some edges to the graph. From 64eab5458ae7662707df43721e6d9d23b4f1ad18 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Oct 2020 18:14:12 +0100 Subject: [PATCH 0284/1892] chore: reformatted setup.py with black [skip ci] --- setup.py | 93 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/setup.py b/setup.py index 511590b2f..c20468ccc 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -#usr/bin/env python +#!usr/bin/env python import os import platform @@ -29,6 +29,7 @@ import sysconfig from select import select +from time import sleep ########################################################################### @@ -143,7 +144,7 @@ def is_unix_like(platform=None): ) -def find_msvc_source_folder(folder = ".", requires_built=False): +def find_msvc_source_folder(folder=".", requires_built=False): """Finds the folder that contains the MSVC-specific source of igraph if there is any. Returns `None` if no such folder is found. Prints a warning if the choice is ambiguous. @@ -151,15 +152,15 @@ def find_msvc_source_folder(folder = ".", requires_built=False): all_msvc_dirs = glob.glob(os.path.join(folder, "igraph-*-msvc")) if len(all_msvc_dirs) > 0: if len(all_msvc_dirs) > 1: - print( - "More than one MSVC build directory (..\\..\\igraph-*-msvc) found!" - ) + print("More than one MSVC build directory (..\\..\\igraph-*-msvc) found!") print( "It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n" ) msvc_builddir = all_msvc_dirs[-1] - if requires_built and not os.path.exists(os.path.join(msvc_builddir, "Release")): + if requires_built and not os.path.exists( + os.path.join(msvc_builddir, "Release") + ): print( "There is no 'Release' dir in the MSVC build directory\n(%s)" % msvc_builddir @@ -179,19 +180,20 @@ def preprocess_fallback_config(): global LIBIGRAPH_FALLBACK_LIBRARY_DIRS global LIBIGRAPH_FALLBACK_LIBRARIES - if platform.system() == "Windows" and distutils.ccompiler.get_default_compiler() == "msvc": + if ( + platform.system() == "Windows" + and distutils.ccompiler.get_default_compiler() == "msvc" + ): # if this setup is run in the source checkout *and* the igraph msvc was build, # this code adds the right library and include dir - msvc_builddir = find_msvc_source_folder(os.path.join("..", ".."), requires_built=True) + msvc_builddir = find_msvc_source_folder( + os.path.join("..", ".."), requires_built=True + ) if msvc_builddir is not None: print("Using MSVC build dir: %s\n\n" % msvc_builddir) - LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [ - os.path.join(msvc_builddir, "include") - ] - LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [ - os.path.join(msvc_builddir, "Release") - ] + LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [os.path.join(msvc_builddir, "include")] + LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [os.path.join(msvc_builddir, "Release")] return True else: return False @@ -269,7 +271,7 @@ def compile_in(self, build_folder, source_folder=None): source_folder = os.path.abspath(source_folder) build_folder = os.path.abspath(build_folder) - + build_to_source_folder = os.path.relpath(source_folder, build_folder) cwd = os.getcwd() @@ -302,20 +304,24 @@ def compile_in(self, build_folder, source_folder=None): print("Configuring igraph...") configure_args = ["--disable-tls", "--enable-silent-rules"] if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: - configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) + configure_args.extend( + os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ") + ) retcode = subprocess.call( "sh {0} {1}".format( - quote_path_for_shell(os.path.join(build_to_source_folder, "configure")), - " ".join(configure_args) + quote_path_for_shell( + os.path.join(build_to_source_folder, "configure") + ), + " ".join(configure_args), ), env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), - shell=True + shell=True, ) if retcode: return False building_on_windows = building_on_windows_msvc() - + if building_on_windows: print("Creating Microsoft Visual Studio project...") retcode = subprocess.call("make msvc", shell=True) @@ -331,13 +337,17 @@ def compile_in(self, build_folder, source_folder=None): devenv = os.environ.get("DEVENV_EXECUTABLE") os.chdir(msvc_source) if devenv is None: - retcode = subprocess.call("devenv /upgrade igraph.vcproj", shell=True) + retcode = subprocess.call( + "devenv /upgrade igraph.vcproj", shell=True + ) else: retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) if retcode: return False - retcode = subprocess.call("msbuild.exe igraph.vcxproj /p:configuration=Release") + retcode = subprocess.call( + "msbuild.exe igraph.vcxproj /p:configuration=Release" + ) else: retcode = subprocess.call("make", shell=True) @@ -368,7 +378,7 @@ def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries ): building_on_windows = building_on_windows_msvc() - + create_dir_unless_exists(install_folder) ensure_dir_does_not_exist(install_folder, "include") @@ -387,9 +397,7 @@ def copy_build_artifacts( msvc_builddir = find_msvc_source_folder(build_folder, requires_built=True) if msvc_builddir is not None: print("Using MSVC build dir: %s\n\n" % msvc_builddir) - for fname in glob.glob( - os.path.join(msvc_builddir, "Release", "*.lib") - ): + for fname in glob.glob(os.path.join(msvc_builddir, "Release", "*.lib")): shutil.copy(fname, os.path.join(install_folder, "lib")) else: print("Cannot find MSVC build dir in %s\n\n" % build_folder) @@ -497,7 +505,9 @@ def run(self): if buildcfg.use_pkgconfig: detected = buildcfg.detect_from_pkgconfig() if not detected: - print("Cannot find the C core of igraph on this system using pkg-config.") + print( + "Cannot find the C core of igraph on this system using pkg-config." + ) sys.exit(1) else: # Build the C core from the vendored igraph source @@ -510,10 +520,11 @@ def run(self): # Add any extra library paths if needed; this is needed for the # Appveyor CI build if "IGRAPH_EXTRA_LIBRARY_PATH" in os.environ: - buildcfg.library_dirs = list( - os.environ["IGRAPH_EXTRA_LIBRARY_PATH"].split(os.pathsep) - ) + buildcfg.library_dirs - + buildcfg.library_dirs = ( + list(os.environ["IGRAPH_EXTRA_LIBRARY_PATH"].split(os.pathsep)) + + buildcfg.library_dirs + ) + # Replaces library names with full paths to static libraries # where possible. libm.a is excluded because it caused problems # on Sabayon Linux where libm.a is probably not compiled with @@ -549,9 +560,6 @@ def sdist(self): command. """ from setuptools.command.sdist import sdist - from distutils.sysconfig import get_python_inc - - buildcfg = self class custom_sdist(sdist): def run(self): @@ -698,7 +706,7 @@ def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" building_on_windows = building_on_windows_msvc() - + if not building_on_windows and "stdc++" not in self.libraries: self.libraries.append("stdc++") @@ -718,7 +726,7 @@ def use_vendored_igraph(self): """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up the include and library paths and the library names accordingly.""" building_on_windows = building_on_windows_msvc() - + buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include")] buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] if not buildcfg.static_extension: @@ -803,17 +811,10 @@ def use_educated_guess(self): author_email="ntamas@gmail.com", ext_modules=[igraph_extension], package_dir={"igraph": "src/igraph"}, - packages=[ - "igraph", - "igraph.app", - "igraph.drawing", - "igraph.remote" - ], + packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], - extras_require={ - "plotting": ["pycairo>=1.18.0"] - }, + extras_require={"plotting": ["pycairo>=1.18.0"]}, headers=headers, platforms="ALL", keywords=[ @@ -846,7 +847,7 @@ def use_educated_guess(self): cmdclass={ "build_c_core": buildcfg.build_c_core, # used by CI "build_ext": buildcfg.build_ext, - "sdist": buildcfg.sdist + "sdist": buildcfg.sdist, }, ) From d2c2efc270bf61daadc7aca9719ea8bcdb581ca8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Oct 2020 18:22:59 +0100 Subject: [PATCH 0285/1892] feat: added empty stub for soon-to-be-added CMake builder for igraph 0.9 [skip ci] --- setup.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index c20468ccc..5d18b9ba1 100644 --- a/setup.py +++ b/setup.py @@ -255,9 +255,11 @@ def wait_for_keypress(seconds): ########################################################################### -class IgraphCCoreBuilder(object): +class IgraphCCoreAutotoolsBuilder(object): """Class responsible for downloading and building the C core of igraph - if it is not installed yet.""" + if it is not installed yet, assuming that the C core uses `configure.ac` + and its friends. This used to be the case before igraph 0.9. + """ def compile_in(self, build_folder, source_folder=None): """Compiles igraph from its source code in the given folder. @@ -422,6 +424,27 @@ def enhanced_env(**kwargs): return env +########################################################################### + + +class IgraphCCoreCMakeBuilder(object): + """Class responsible for downloading and building the C core of igraph + if it is not installed yet, assuming that the C core uses CMake as the + build tool. This is the case from igraph 0.9. + """ + + def compile_in(self, build_folder, source_folder=None): + raise NotImplementedError + + def copy_build_artifacts( + self, source_folder, build_folder, install_folder, libraries + ): + raise NotImplementedError + + +########################################################################### + + class BuildConfiguration(object): def __init__(self): self.include_dirs = [] @@ -591,7 +614,11 @@ def compile_igraph_from_vendor_source(self): return True vendor_source_path = os.path.join("vendor", "source", "igraph") - if not os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): + if os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): + igraph_builder = IgraphCCoreAutotoolsBuilder() + elif os.path.isfile(os.path.join(vendor_source_path, "CMakeLists.txt")): + igraph_builder = IgraphCCoreCMakeBuilder() + else: # No git submodule present with vendored source print("Cannot find vendored igraph source in " + vendor_source_path) print("") @@ -607,7 +634,6 @@ def compile_igraph_from_vendor_source(self): print(" Install folder: %s" % install_folder) print("") - igraph_builder = IgraphCCoreBuilder() libraries = igraph_builder.compile_in(build_folder, source_folder=source_folder) if not libraries or not igraph_builder.copy_build_artifacts( source_folder=source_folder, From 19d48e47e2accf82f681c7c5db93b0556c7dd652 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 2 Nov 2020 22:14:09 +0100 Subject: [PATCH 0286/1892] CMake builder now builds the C core; work in progress --- setup.py | 257 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 156 insertions(+), 101 deletions(-) diff --git a/setup.py b/setup.py index 5d18b9ba1..ded7fc943 100644 --- a/setup.py +++ b/setup.py @@ -66,6 +66,20 @@ def exclude_from_list(items, items_to_exclude): return [item for item in items if item not in itemset] +def find_executable(name): + """Finds an executable with the given name on the system PATH and returns + its full path. + """ + try: + from shutil import which + + return which(name) # Python 3.3 and above + except ImportError: + import distutils.spawn + + return distutils.spawn.find_executable(name) # Earlier than Python 3.3 + + def find_static_library(library_name, library_path): """Given the raw name of a library in `library_name`, tries to find a static library with this name in the given `library_path`. `library_path` @@ -261,120 +275,106 @@ class IgraphCCoreAutotoolsBuilder(object): and its friends. This used to be the case before igraph 0.9. """ - def compile_in(self, build_folder, source_folder=None): + def compile_in(self, source_folder, build_folder, install_folder): """Compiles igraph from its source code in the given folder. source_folder is the name of the folder that contains igraph's source - files. If it is `None`, it is assumed that it is the same as the - build folder. - """ - if source_folder is None: - source_folder = build_folder - - source_folder = os.path.abspath(source_folder) - build_folder = os.path.abspath(build_folder) + files. build_folder is the name of the folder where the build should + be executed. Both must be absolute paths. + Returns: + False if the build failed or the list of libraries to link to when + linking the Python interface to igraph + """ build_to_source_folder = os.path.relpath(source_folder, build_folder) - cwd = os.getcwd() - try: - os.chdir(source_folder) - - # Run the bootstrap script if we have downloaded a tarball from - # Github - if os.path.isfile("bootstrap.sh") and not os.path.isfile("configure"): - print("Bootstrapping igraph...") - retcode = subprocess.call("sh bootstrap.sh", shell=True) - if retcode: - return False - - # Patch ltmain.sh so it does not freak out when the build directory - # contains spaces - with open("ltmain.sh") as infp: - with open("ltmain.sh.new", "w") as outfp: - for line in infp: - if line.endswith("cd $darwin_orig_dir\n"): - line = line.replace( - "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' - ) - outfp.write(line) - shutil.move("ltmain.sh.new", "ltmain.sh") - - create_dir_unless_exists(build_folder) - os.chdir(build_folder) - - print("Configuring igraph...") - configure_args = ["--disable-tls", "--enable-silent-rules"] - if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: - configure_args.extend( - os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ") - ) - retcode = subprocess.call( - "sh {0} {1}".format( - quote_path_for_shell( - os.path.join(build_to_source_folder, "configure") - ), - " ".join(configure_args), - ), - env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), - shell=True, - ) + os.chdir(source_folder) + + # Run the bootstrap script if we have downloaded a tarball from + # Github + if os.path.isfile("bootstrap.sh") and not os.path.isfile("configure"): + print("Bootstrapping igraph...") + retcode = subprocess.call("sh bootstrap.sh", shell=True) if retcode: return False - building_on_windows = building_on_windows_msvc() + # Patch ltmain.sh so it does not freak out when the build directory + # contains spaces + with open("ltmain.sh") as infp: + with open("ltmain.sh.new", "w") as outfp: + for line in infp: + if line.endswith("cd $darwin_orig_dir\n"): + line = line.replace( + "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' + ) + outfp.write(line) + shutil.move("ltmain.sh.new", "ltmain.sh") + + os.chdir(build_folder) + + print("Configuring igraph...") + configure_args = ["--disable-tls", "--enable-silent-rules"] + if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: + configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) + retcode = subprocess.call( + "sh {0} {1}".format( + quote_path_for_shell(os.path.join(build_to_source_folder, "configure")), + " ".join(configure_args), + ), + env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), + shell=True, + ) + if retcode: + return False + + building_on_windows = building_on_windows_msvc() - if building_on_windows: - print("Creating Microsoft Visual Studio project...") - retcode = subprocess.call("make msvc", shell=True) - if retcode: - return False + if building_on_windows: + print("Creating Microsoft Visual Studio project...") + retcode = subprocess.call("make msvc", shell=True) + if retcode: + return False - print("Building igraph...") - if building_on_windows: - msvc_source = find_msvc_source_folder() - if not msvc_source: - return False - - devenv = os.environ.get("DEVENV_EXECUTABLE") - os.chdir(msvc_source) - if devenv is None: - retcode = subprocess.call( - "devenv /upgrade igraph.vcproj", shell=True - ) - else: - retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) - if retcode: - return False + print("Building igraph...") + if building_on_windows: + msvc_source = find_msvc_source_folder() + if not msvc_source: + return False - retcode = subprocess.call( - "msbuild.exe igraph.vcxproj /p:configuration=Release" - ) + devenv = os.environ.get("DEVENV_EXECUTABLE") + os.chdir(msvc_source) + if devenv is None: + retcode = subprocess.call("devenv /upgrade igraph.vcproj", shell=True) else: - retcode = subprocess.call("make", shell=True) - + retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) if retcode: return False - if building_on_windows: - libraries = ["igraph"] - else: - libraries = [] - for line in open("igraph.pc"): - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) + retcode = subprocess.call( + "msbuild.exe igraph.vcxproj /p:configuration=Release" + ) + else: + retcode = subprocess.call("make", shell=True) - if not libraries: - # Educated guess - libraries = ["igraph"] + if retcode: + return False - return libraries + if building_on_windows: + libraries = ["igraph"] + else: + libraries = [] + for line in open("igraph.pc"): + if line.startswith("Libs: ") or line.startswith("Libs.private: "): + words = line.strip().split() + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) - finally: - os.chdir(cwd) + if not libraries: + # Educated guess + libraries = ["igraph"] + + return libraries def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries @@ -431,10 +431,50 @@ class IgraphCCoreCMakeBuilder(object): """Class responsible for downloading and building the C core of igraph if it is not installed yet, assuming that the C core uses CMake as the build tool. This is the case from igraph 0.9. + + Returns: + False if the build failed or the list of libraries to link to when + linking the Python interface to igraph """ - def compile_in(self, build_folder, source_folder=None): - raise NotImplementedError + def compile_in(self, source_folder, build_folder, install_folder): + """Compiles igraph from its source code in the given folder. + + source_folder is the name of the folder that contains igraph's source + files. build_folder is the name of the folder where the build should + be executed. Both must be absolute paths. + """ + cmake = find_executable("cmake") + if not cmake: + print( + "igraph uses CMake as the build system. You need to install CMake " + "before compiling igraph." + ) + return False + + build_to_source_folder = os.path.relpath(source_folder, build_folder) + os.chdir(build_folder) + + print("Configuring build...") + args = [cmake, build_to_source_folder] + for deps in "ARPACK BLAS CXSPARSE GLPK LAPACK".split(): + args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") + + retcode = subprocess.call(args) + if retcode: + return False + + print("Running build...") + retcode = subprocess.call( + [cmake, "--build", ".", "--parallel", "--config", "Release"] + ) + if retcode: + return False + + print("Installing build...") + retcode = subprocess.call([cmake, "--install", ".", "--prefix", install_folder]) + if retcode: + return False def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries @@ -614,10 +654,10 @@ def compile_igraph_from_vendor_source(self): return True vendor_source_path = os.path.join("vendor", "source", "igraph") - if os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): - igraph_builder = IgraphCCoreAutotoolsBuilder() - elif os.path.isfile(os.path.join(vendor_source_path, "CMakeLists.txt")): + if os.path.isfile(os.path.join(vendor_source_path, "CMakeLists.txt")): igraph_builder = IgraphCCoreCMakeBuilder() + elif os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): + igraph_builder = IgraphCCoreAutotoolsBuilder() else: # No git submodule present with vendored source print("Cannot find vendored igraph source in " + vendor_source_path) @@ -634,7 +674,22 @@ def compile_igraph_from_vendor_source(self): print(" Install folder: %s" % install_folder) print("") - libraries = igraph_builder.compile_in(build_folder, source_folder=source_folder) + source_folder = os.path.abspath(source_folder) + build_folder = os.path.abspath(build_folder) + install_folder = os.path.abspath(install_folder) + + create_dir_unless_exists(build_folder) + + cwd = os.getcwd() + try: + libraries = igraph_builder.compile_in( + source_folder=source_folder, + build_folder=build_folder, + install_folder=install_folder, + ) + finally: + os.chdir(cwd) + if not libraries or not igraph_builder.copy_build_artifacts( source_folder=source_folder, build_folder=build_folder, From 1979af57f31b8b4589e105d6e50ac2f9ca383b4f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 5 Nov 2020 08:36:20 +0100 Subject: [PATCH 0287/1892] fix two compiler warnings [ci skip] --- src/_igraph/operators.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 7f82f2b35..e748e7a39 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -96,7 +96,7 @@ PyObject *igraphmodule__union(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "graphs", "edgemaps", NULL }; - PyObject *it, *em_list, *graphs, *with_edgemaps_o; + PyObject *it, *em_list = 0, *graphs, *with_edgemaps_o; int with_edgemaps = 0; long int no_of_graphs; igraph_vector_ptr_t gs; @@ -207,7 +207,7 @@ PyObject *igraphmodule__intersection(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "graphs", "edgemaps", NULL }; - PyObject *it, *em_list, *graphs, *with_edgemaps_o; + PyObject *it, *em_list = 0, *graphs, *with_edgemaps_o; int with_edgemaps = 0; long int no_of_graphs; igraph_vector_ptr_t gs; From 6e5f803382b0ff7729dc63556245de12f3dea785 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 5 Nov 2020 19:15:58 +0100 Subject: [PATCH 0288/1892] updated issue templates [skip ci] --- .github/ISSUE_TEMPLATE/bug_report.md | 25 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 4 ++++ .github/ISSUE_TEMPLATE/feature_request.md | 22 ++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..678cf49c2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug report +about: Report a problem in the Python interface of igraph +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To reproduce** +Steps or minimal example code to reproduce the problem. + +If you are confident that the issue is not in the Python interface but in the +C core of igraph, please add it to the main [igraph repo](https://github.com/igraph/igraph) +instead. + +If you are unsure, feel free to add your issue here - we will transfer it to +the main [igraph repo](https://github.com/igraph/igraph) if the root cause is +in the C core of igraph. + +**Version information** +Which version of `python-igraph` are you using and where did you obtain it? diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..60b5562d1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: igraph support + url: https://igraph.discourse.group/ + about: Ask and answer questions about igraph diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..31afa92c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest an idea for python-igraph +title: '' +labels: '' +assignees: '' + +--- + +**What is the feature or improvement you would like to see?** +A concise description of the requested feature. If the feature request is about +an algorithm, consider adding your request in the main [igraph +repo](https://github.com/igraph/igraph) instead - in most cases the Python +interface simply provides access to the functionality of the igraph library, so +new algorithms should be added there in general. + +**Use cases for the feature** +Explain when and for what purpose the feature would be useful. + +**References** +List any relevant references (papers or books describing relevant algorithms). + From d372c8e986651604d1cd6b2fd56c951dd32228ed Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 3 Dec 2020 23:13:53 +1100 Subject: [PATCH 0289/1892] Bugfix Graph.DataFrame vertex names (#348) --- src/igraph/__init__.py | 80 ++++++++++++++++++++++++++++------------ tests/test_generators.py | 23 +++++++++++- 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 20e9e9cbd..eb200c1ad 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3075,19 +3075,32 @@ def Incidence(klass, *args, **kwds): return result @classmethod - def DataFrame(klass, edges, directed=True, vertices=None): + def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): """DataFrame(edges, directed=True, vertices=None) Generates a graph from one or two dataframes. - @param edges: pandas DataFrame containing edges and metadata + @param edges: pandas DataFrame containing edges and metadata. The first + two columns of this DataFrame contain the source and target vertices + for each edge. These indicate the vertex *names* rather than ids + unless `use_vids` is True and these are nonnegative integers. @param directed: bool setting whether the graph is directed @param vertices: None (default) or pandas DataFrame containing vertex metadata. The first column must contain the unique ids of the - vertices and will be set as attribute 'name'. All other columns - will be added as vertex attributes by column name. + vertices and will be set as attribute 'name'. Although vertex names + are usually strings, they can be any hashable object. All other + columns will be added as vertex attributes by column name. + @use_vids: whether to interpret the first two columns of the `edges` + argument as vertex ids (0-based integers) instead of vertex names. + If this argument is set to True and the first two columns of `edges` + are not integers, an error is thrown. @return: the graph + + Vertex names in either the `edges` or `vertices` arguments that are set + to NaN (not a number) will be set to the string "NA". That might lead + to unexpected behaviour: fill your NaNs with values before calling this + function to mitigate. """ import numpy as np import pandas as pd @@ -3095,11 +3108,21 @@ def DataFrame(klass, edges, directed=True, vertices=None): if edges.shape[1] < 2: raise ValueError("the data frame should contain at least two columns") - # Handle if some elements are 'NA' - if edges.iloc[:, :2].isna().values.any(): - warn("In 'edges' NA elements were replaced with string \"NA\"") - edges = edges.copy() - edges.iloc[:, :2].fillna('NA', inplace=True) + if use_vids: + if str(edges.dtypes[0]).startswith('int') and \ + str(edges.dtypes[1]).startswith('int'): + names_edges = None + else: + raise TypeError('vertex ids must be 0-based integers') + + else: + # Handle if some elements are 'NA' + if edges.iloc[:, :2].isna().values.any(): + warn("In 'edges' NA elements were replaced with string \"NA\"") + edges = edges.copy() + edges.iloc[:, :2].fillna('NA', inplace=True) + + names_edges = np.unique(edges.values[:, :2]) if (vertices is not None) and vertices.iloc[:, 0].isna().values.any(): warn("In the first column of 'vertices' NA elements were replaced "+ @@ -3107,43 +3130,54 @@ def DataFrame(klass, edges, directed=True, vertices=None): vertices = vertices.copy() vertices.iloc[:, 0].fillna('NA', inplace=True) - names_edges = np.unique(edges.values[:, :2]) - if vertices is None: names = names_edges else: if vertices.shape[1] < 1: raise ValueError('vertices has no columns') - names_vertices = vertices.iloc[:, 0].astype(str) + names_vertices = vertices.iloc[:, 0] if names_vertices.duplicated().any(): raise ValueError('Vertex names must be unique') names_vertices = names_vertices.values - if len(np.setdiff1d(names_edges, names_vertices)): + if (names_edges is not None) and \ + len(np.setdiff1d(names_edges, names_vertices)): raise ValueError( - 'Some vertices in the edge DataFrame are missing from vertices DataFrame') + 'Some vertices in the edge DataFrame are missing from '+ + 'vertices DataFrame') names = names_vertices # create graph - g = Graph(n=len(names), directed=directed) + if names is not None: + nv = len(names) + else: + nv = edges.iloc[:, :2].values.max() + 1 + g = Graph(n=nv, directed=directed) + + # vertex names + if names is not None: + for v, name in zip(g.vs, names): + v['name'] = name # vertex attributes - if vertices is not None: + if (vertices is not None) and (vertices.shape[1] > 1): cols = vertices.columns for v, (_, attr) in zip(g.vs, vertices.iterrows()): - v['name'] = attr[cols[0]] - if len(cols) > 1: - for an in cols[1:]: - v[an] = attr[an] + for an in cols[1:]: + v[an] = attr[an] # create edge list - names_idx = pd.Series(index=names, data=np.arange(len(names))) - e0 = names_idx[edges.values[:, 0]] - e1 = names_idx[edges.values[:, 1]] + if names is not None: + names_idx = pd.Series(index=names, data=np.arange(len(names))) + e0 = names_idx[edges.values[:, 0]] + e1 = names_idx[edges.values[:, 1]] + else: + e0 = edges.values[:, 0] + e1 = edges.values[:, 1] # add the edges g.add_edges(zip(e0, e1)) diff --git a/tests/test_generators.py b/tests/test_generators.py index 5dad1405d..e29e3a079 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -177,19 +177,38 @@ def testDataFrame(self): edges = pd.DataFrame( [['C', 'A', 0.4], ['A', 'B', 0.1]], columns=[0, 1, 'weight']) - g = Graph.DataFrame(edges, directed=False) self.assertTrue(g.es["weight"] == [0.4, 0.1]) vertices = pd.DataFrame( [['A', 'blue'], ['B', 'yellow'], ['C', 'blue']], columns=[0, 'color']) - g = Graph.DataFrame(edges, directed=True, vertices=vertices) self.assertTrue(g.vs['name'] == ['A', 'B', 'C']) self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) self.assertTrue(g.es["weight"] == [0.4, 0.1]) + # Issue #347 + edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) + vertices = pd.DataFrame({ + 'node': [1, 2, 3, 4, 5, 6], + 'label': ['1', '2', '3', '4', '5', '6']})[['node', 'label']] + g = Graph.DataFrame( + edges, + directed=True, + vertices=vertices, + ) + self.assertTrue(g.vs['name'] == [1, 2, 3, 4, 5, 6]) + self.assertTrue(g.vs['label'] == ['1', '2', '3', '4', '5', '6']) + + # Vertex ids + edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) + g = Graph.DataFrame(edges) + self.assertTrue(g.vcount() == 6) + + edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) + g = Graph.DataFrame(edges, use_vids=True) + self.assertTrue(g.vcount() == 7) def suite(): generator_suite = unittest.makeSuite(GeneratorTests) From 6f0f4903c27edd5b25c695f2dc5bd17364d86c97 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 5 Dec 2020 01:40:14 +1100 Subject: [PATCH 0290/1892] Prototype for matplotlib graph drawing (#341) --- src/igraph/drawing/__init__.py | 16 ++- src/igraph/drawing/edge.py | 3 - src/igraph/drawing/graph.py | 248 ++++++++++++++++++++++++++++++++- src/igraph/drawing/utils.py | 25 +++- 4 files changed, 279 insertions(+), 13 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index d39109786..83b38c4e9 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -27,8 +27,8 @@ from igraph.compat import property, BytesIO from igraph.configuration import Configuration from igraph.drawing.colors import Palette, palettes -from igraph.drawing.graph import DefaultGraphDrawer -from igraph.drawing.utils import BoundingBox, Point, Rectangle, find_cairo +from igraph.drawing.graph import DefaultGraphDrawer, MatplotlibGraphDrawer +from igraph.drawing.utils import BoundingBox, Point, Rectangle, find_cairo, find_matplotlib from igraph.utils import _is_running_in_ipython, named_temporary_file __all__ = ["BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot"] @@ -36,6 +36,7 @@ __license__ = "GPL" cairo = find_cairo() +matplotlib, plt = find_matplotlib() ##################################################################### @@ -50,7 +51,7 @@ class Plot(object): since C{pycairo} takes care of the actual drawing. Everything that's supported by C{pycairo} should be supported by this class as well. - Current Cairo surfaces that I'm aware of are: + Current Cairo surfaces include: - C{cairo.GlitzSurface} -- OpenGL accelerated surface for the X11 Window System. @@ -385,8 +386,10 @@ def width(self): is drawn""" return self.bbox.width + ##################################################################### + def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): """Plots the given object to the given target. @@ -449,6 +452,11 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @see: Graph.__plot__ """ + if hasattr(plt, 'Axes') and isinstance(target, plt.Axes): + result = MatplotlibGraphDrawer(ax=target) + result.draw(obj, *args, **kwds) + return + if not isinstance(bbox, BoundingBox): bbox = BoundingBox(bbox) @@ -482,7 +490,7 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): # so just show or save the result if target is None: result.show() - elif isinstance(target, basestring): + elif isinstance(target, str): result.save() # Also return the plot itself diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 077e1fc15..64e5ffc22 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -234,7 +234,6 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): return bezier_cubic(x0,y0, x1,y1, x2,y2, x3,y3, t1) - # Draw the edge ctx.set_source_rgba(*edge.color) ctx.set_line_width(edge.width) @@ -313,7 +312,6 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): # Draw the edge ctx.stroke() - # Draw the arrow head ctx.move_to(x2, y2) ctx.line_to(*aux_points[0]) @@ -322,7 +320,6 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): ctx.fill() - class TaperedEdgeDrawer(AbstractEdgeDrawer): """Edge drawer implementation that draws undirected edges as straight lines and directed edges as tapered lines that are diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index c24f09ffd..0491c851e 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -15,7 +15,7 @@ from collections import defaultdict from itertools import izip -from math import atan2, cos, pi, sin, tan +from math import atan2, cos, pi, sin, tan, sqrt from warnings import warn from igraph._igraph import convex_hull, VertexSeq @@ -576,7 +576,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): # Add the vertices n = graph.vcount() new_vertex = display.new_vertex - vertex_ids = [new_vertex() for _ in xrange(n)] + vertex_ids = [new_vertex() for _ in range(n)] # Add the edges new_edge = display.new_edge @@ -674,10 +674,10 @@ def draw(self, graph, name="Network from igraph", create_view=True, # Create the nodes if "node_ids" in kwds: node_ids = kwds["node_ids"] - if isinstance(node_ids, basestring): + if isinstance(node_ids, str): node_ids = graph.vs[node_ids] else: - node_ids = xrange(graph.vcount()) + node_ids = range(graph.vcount()) node_ids = [str(identifier) for identifier in node_ids] cy.createNodes(network_id, node_ids) @@ -926,3 +926,243 @@ def draw(self, graph, *args, **kwds): will be used to encode the JSON objects. """ self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) + +##################################################################### + +class MatplotlibGraphDrawer(AbstractGraphDrawer): + """Graph drawer that uses a pyplot.Axes as context""" + + _shape_dict = { + 'rectangle': 's', + 'circle': 'o', + 'hidden': 'none', + 'triangle-up': '^', + 'triangle-down': 'v', + } + + + + def __init__(self, ax): + """Constructs the graph drawer and associates it with the mpl axes""" + self.ax = ax + + def draw(self, graph, *args, **kwds): + import matplotlib.markers as mmarkers + from matplotlib.path import Path + from matplotlib.patches import FancyArrowPatch + from matplotlib.patches import ArrowStyle + + def shrink_vertex(ax, aux, vcoord, vsize_squared): + '''Shrink edge by vertex size''' + aux_display, vcoord_display = ax.transData.transform([aux, vcoord]) + d = sqrt(((aux_display - vcoord_display)**2).sum()) + fr = sqrt(vsize_squared) / d + end_display = vcoord_display + fr * (aux_display - vcoord_display) + end = ax.transData.inverted().transform(end_display) + return end + + def callback_factory(ax, vcoord, vsizes, arrows): + def callback_edge_offset(event): + for arrow, src, tgt in arrows: + v1, v2 = vcoord[src], vcoord[tgt] + # This covers both cases (curved and straight) + aux1, aux2 = arrow._path_original.vertices[[1, -2]] + start = shrink_vertex(ax, aux1, v1, vsizes[src]) + end = shrink_vertex(ax, aux2, v2, vsizes[tgt]) + arrow._path_original.vertices[0] = start + arrow._path_original.vertices[-1] = end + + return callback_edge_offset + + ax = self.ax + + # FIXME: deal with unnamed *args + + # Get layout + layout = kwds.get('layout', graph.layout()) + if isinstance(layout, str): + layout = graph.layout(layout) + + # Vertex coordinates + vcoord = layout.coords + + # Vertex properties + vsizes = kwds.get('vertex_size', None) + # NOTE: ax.scatter uses the *square* of diameter + if vsizes is not None: + vsizes **= 2 + if isinstance(vsizes, float) or isinstance(vsizes, int): + vsizes = [vsizes] * len(vcoord) + c = kwds.get('vertex_color', 'black') + alpha = kwds.get('alpha', 1.0) + label = kwds.get('vertex_label', None) + label_size = kwds.get('vertex_label_size', None) + vzorder = kwds.get('vertex_order', 2) + # mpl shapes use slightly different names from Cairo + shapes = kwds.get('vertex_shape', None) + if shapes is not None: + if isinstance(shapes, str): + shapes = self._shape_dict.get(shapes, shapes) + elif isinstance(shapes, mmarkers.MarkerStyle): + pass + + # Scatter vertices + # NOTE: matplotlib does not support a list of shapes yet + x, y = list(zip(*vcoord)) + ax.scatter(x, y, s=vsizes, c=c, marker=shapes, zorder=vzorder, alpha=alpha) + + # Vertex labels + if label is not None: + for i, lab in enumerate(label): + xi, yi = x[i], y[i] + ax.text(xi, yi, lab, fontsize=label_size) + + dx = (max(x) - min(x)) + dy = (max(y) - min(y)) + ax.set_xlim(min(x) - 0.05 * dx, max(x) + 0.05 * dx) + ax.set_ylim(min(y) - 0.05 * dy, max(y) + 0.05 * dy) + + # Edge properties + ne = graph.ecount() + ec = kwds.get('edge_color', 'black') + edge_width = kwds.get('edge_width', 1) + arrow_width = kwds.get('edge_arrow_width', 2) + arrow_length = kwds.get('edge_arrow_size', 4) + ealpha = kwds.get('edge_alpha', 1.0) + ezorder = kwds.get('edge_order', 1.0) + try: + ezorder = float(ezorder) + ezorder = [ezorder] * ne + except TypeError: + pass + + # Decide whether we need to calculate the curvature of edges + # automatically -- and calculate them if needed. + autocurve = kwds.get("autocurve", None) + if autocurve or (autocurve is None and \ + "edge_curved" not in kwds and "curved" not in graph.edge_attributes() \ + and graph.ecount() < 10000): + from igraph import autocurve + default = kwds.get("edge_curved", 0) + if default is True: + default = 0.5 + default = float(default) + kwds["edge_curved"] = autocurve(graph, attribute=None, default=default) + + # Arrow style for directed and undirected graphs + if graph.is_directed(): + arrowstyle = ArrowStyle( + '-|>', head_length=arrow_length, head_width=arrow_width, + ) + else: + arrowstyle = '-' + + # Edge coordinates and curvature + nloops = [0 for x in range(ne)] + has_curved = 'curved' in graph.es.attributes() + arrows = [] + for ie, edge in enumerate(graph.es): + src, tgt = edge.source, edge.target + x1, y1 = vcoord[src] + x2, y2 = vcoord[tgt] + + # Loops require special treatment + if src == tgt: + # Find all non-loop edges + nloopstot = 0 + angles = [] + for tgtn in graph.neighbors(src): + if tgtn == src: + nloopstot += 1 + continue + xn, yn = vcoord[tgtn] + angles.append(180. / pi * atan2(yn - y1, xn - x1) % 360) + # with .neighbors(mode=ALL), which is default, loops are double + # counted + nloopstot //= 2 + angles = sorted(set(angles)) + + # Only loops or one non-loop + if len(angles) < 2: + ashift = angles[0] if angles else 270 + if nloopstot == 1: + # Only one self loop, use a quadrant only + angles = [(ashift + 135) % 360, (ashift + 225) % 360] + else: + nshift = 360. / nloopstot + angles = [(ashift + nshift * nloops[src]) % 360, + (ashift + nshift * (nloops[src] + 1)) % 360] + nloops[src] += 1 + else: + angles.append(angles[0] + 360) + idiff = 0 + diff = 0 + for i in range(len(angles) - 1): + diffi = abs(angles[i + 1] - angles[i]) + if diffi > diff: + idiff = i + diff = diffi + angles = angles[idiff: idiff + 2] + ashift = angles[0] + nshift = (angles[1] - angles[0]) / nloopstot + angles = [(ashift + nshift * nloops[src]), + (ashift + nshift * (nloops[src] + 1))] + nloops[src] += 1 + + # this is not great, but alright + angspan = angles[1] - angles[0] + if angspan < 180: + angmid1 = angles[0] + 0.1 * angspan + angmid2 = angles[1] - 0.1 * angspan + else: + angmid1 = angles[0] + 0.5 * (angspan - 180) + 45 + angmid2 = angles[1] - 0.5 * (angspan - 180) - 45 + aux1 = (x1 + 0.2 * dx * cos(pi / 180 * angmid1), + y1 + 0.2 * dy * sin(pi / 180 * angmid1)) + aux2 = (x1 + 0.2 * dx * cos(pi / 180 * angmid2), + y1 + 0.2 * dy * sin(pi / 180 * angmid2)) + start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) + end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) + + path = Path( + [start, aux1, aux2, end], + # Cubic bezier by mpl + codes=[1, 4, 4, 4]) + + else: + curved = edge['curved'] if has_curved else False + if curved: + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), \ + (2 * y1 + y2) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), \ + (y1 + 2 * y2) / 3.0 + edge.curved * 0.5 * (x2 - x1) + start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) + end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) + + path = Path( + [start, aux1, aux2, end], + # Cubic bezier by mpl + codes=[1, 4, 4, 4]) + else: + start = shrink_vertex(ax, (x2, y2), (x1, y1), vsizes[src]) + end = shrink_vertex(ax, (x1, y1), (x2, y2), vsizes[tgt]) + + path = Path([start, end], codes=[1, 2]) + + arrow = FancyArrowPatch( + path=path, + arrowstyle=arrowstyle, + lw=edge_width, + color=ec, + alpha=ealpha, + zorder=ezorder[ie]) + ax.add_artist(arrow) + + # Store arrows and their sources and targets for autoscaling + arrows.append((arrow, src, tgt)) + + # Autoscaling during zoom, figure resize, reset axis limits + callback = callback_factory(ax, vcoord, vsizes, arrows) + ax.get_figure().canvas.mpl_connect('resize_event', callback) + ax.callbacks.connect('xlim_changed', callback) + ax.callbacks.connect('ylim_changed', callback) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 47f601687..205b55044 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -393,11 +393,11 @@ class FakeModule(object): """Fake module that raises an exception for everything""" def __getattr__(self, _): - raise TypeError("plotting not available") + raise AttributeError("plotting not available") def __call__(self, _): raise TypeError("plotting not available") def __setattr__(self, key, value): - raise TypeError("plotting not available") + raise AttributeError("plotting not available") ##################################################################### @@ -418,6 +418,27 @@ def find_cairo(): ##################################################################### +def find_matplotlib(): + """Tries to import the ``cairo`` Python module if it is installed, + also trying ``cairocffi`` (a drop-in replacement of ``cairo``). + Returns a fake module if everything fails. + """ + try: + import matplotlib as mpl + has_mpl = True + except ImportError: + mpl = FakeModule() + has_mpl = False + + if has_mpl: + import matplotlib.pyplot as plt + else: + plt = FakeModule() + + return mpl, plt + +##################################################################### + class Point(tuple): """Class representing a point on the 2D plane.""" __slots__ = () From 06f8bb9705234e7a0053c6057bb522302e897276 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 5 Dec 2020 01:41:16 +1100 Subject: [PATCH 0291/1892] Documentation on graph visualization (#340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Nepusz --- doc/source/visualisation.rst | 189 ++++++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 1 deletion(-) diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index 53b9d0bcb..7f12491d2 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -1,4 +1,191 @@ +.. include:: include/global.rst + +======================= Visualisation of graphs ======================= +|igraph| includes functionality to visualize graphs. There are two main components: graph layouts and graph plotting. + +In the following examples, we will assume |igraph| is imported as `ig` and a +:class:`Graph` object has been previously created, e.g.: + +>>> import igraph as ig +>>> g = ig.Graph(edges=[[0, 1], [2, 3]]) + +Read the `API documentation`_ for details on each function and class. The `tutorial`_ contains examples to get started. + +Graph layouts +============= +A graph *layout* is a low-dimensional (usually: 2 dimensional) representation of a graph. Different layouts for the same +graph can be computed and typically preserve or highlight distinct properties of the graph itself. Some layouts only make +sense for specific kinds of graphs, such as trees. + +|igraph| offers several graph layouts. The general function to compute a graph layout is :meth:`Graph.layout`: + +>>> layout = g.layout(layout='auto') + +See below for a list of supported layouts. The resulting object is an instance of `igraph.layout.Layout` and has some +useful properties: + +- :attr:`Layout.coords`: the coordinates of the vertices in the layout (each row is a vertex) +- :attr:`Layout.dim`: the number of dimensions of the embedding (usually 2) + +and methods: + +- :meth:`Layout.boundaries` the rectangle with the extreme coordinates of the layout +- :meth:`Layout.bounding_box` the boundary, but as an `igraph.drawing.utils.BoundingBox` (see below) +- :meth:`Layout.centroid` the coordinates of the centroid of the graph layout + +Indexing and slicing can be performed and returns the coordinates of the requested vertices: + +>>> coords_subgraph = layout[:2] # Coordinates of the first two vertices + +.. note:: The returned object is a list of lists with the coordinates, not an `igraph.layout.Layout` + object. You can wrap the result into such an object easily: + + >>> layout_subgraph = ig.Layout(coords=layout[:2]) + +It is possible to perform linear transformations to the layout: + +- :meth:`Layout.translate` +- :meth:`Layout.center` +- :meth:`Layout.scale` +- :meth:`Layout.fit_into` +- :meth:`Layout.rotate` +- :meth:`Layout.mirror` + +as well as a generic nonlinear transformation via: + +- :meth:`Layout.transform` + +The following regular layouts are supported: + +- `Graph.layout_star`: star layout +- `Graph.layout_circle`: circular/spherical layout +- `Graph.layout_grid`: regular grid layout in 2D +- `Graph.layout_grid_3d`: regular grid layout in 3D +- `Graph.layout_random`: random layout (2D and 3D) + +The following algorithms produce nice layouts for general graphs: + +- `Graph.layout_davidson_harel`: Davidson-Harel layout, based on simulated annealing optimization including edge crossings +- `Graph.layout_drl`: DrL layout for large graphs (2D and 3D), a scalable force-directed layout +- `Graph.layout_fruchterman_reingold`: Fruchterman-Reingold layout (2D and 3D), a "spring-electric" layout based on classical physics +- `Graph.layout_graphopt`: the graphopt algorithm, another force-directed layout +- `Graph.layout_kamada_kawai`: Kamada-Kawai layout (2D and 3D), a "spring" layout based on classical physics +- `Graph.layout_lgl`: Large Graph Layout +- `Graph.layout_mds`: multidimensional scaling layout + +The following algorithms are useful for *trees* (and for Sugiyama *directed acyclic graphs* or *DAGs*): + +- `Graph.layout_reingold_tilford`: Reingold-Tilford layout +- `Graph.layout_reingold_tilford_circular`: circular Reingold-Tilford layout +- `Graph.layout_sugiyama`: Sugiyama layout, a hierarchical layout + +For *bipartite graphs*, there is a dedicated function: + +- `Graph.layout_bipartite`: bipartite layout + +More might be added in the future, based on request. + +Graph plotting +============== +Once the layout of a graph has been computed, |igraph| can assist with the plotting itself. Plotting happens within a single +function, `igraph.plot`. + +Plotting with the default image viewer +++++++++++++++++++++++++++++++++++++++ +A naked call to `igraph.plot` generates a temporary file and opens it with the default image viewer: + +>>> ig.plot(g) + +(see below if you are using this in a `Jupyter`_ notebook). This uses the `Cairo`_ library behind the scenes. + +Saving a plot to a file ++++++++++++++++++++++++ +A call to `igraph.plot` with a `target` argument stores the graph image in the specified file and does *not* +open it automatically. Based on the filename extension, any of the following output formats can be chosen: +PNG, PDF, SVG and PostScript: + +>>> ig.plot(g, target='myfile.pdf') + +.. note:: PNG is a raster image format while PDF, SVG, and Postscript are vector image formats. Choose one of the last three + formats if you are planning on refining the image with a vector image editor such as Inkscape or Illustrator. + +Plotting graphs within Matplotlib figures ++++++++++++++++++++++++++++++++++++++++++ +If the target argument is a `matplotlib`_ axes, the graph will be plotted inside that axes: + +>>> import matplotlib.pyplot as plt +>>> fig, ax = plt.subplots() +>>> ig.plot(g, target=ax) + +You can then further manipulate the axes and figure however you like via the `ax` and `fig` variables (or whatever you +called them). This variant does not use `Cairo`_ directly and might be lacking some features that are available in the +`Cairo`_ backend: please open an issue on Github to request specific features. + +Plotting graphs in Jupyter notebooks +++++++++++++++++++++++++++++++++++++ +|igraph| supports inline plots within a `Jupyter`_ notebook via both the `Cairo`_ and `matplotlib`_ backend. If you are +calling `igraph.plot` from a notebook cell without a `matplotlib`_ axes, the image will be shown inline in the corresponding +output cell. Use the `bbox` argument to scale the image while preserving the size of the vertices, text, and other artists. +For instance, to get a compact plot: + +>>> ig.plot(g, bbox=(0, 0, 100, 100)) + +These inline plots can be either in PNG or SVG format. There is currently an open bug that makes SVG fail if more than one graph +per notebook is plotted: we are working on a fix for that. In the meanwhile, you can use PNG representation. + +If you want to use the `matplotlib`_ engine in a Jupyter notebook, you can use the recipe above. First create an axes, then +tell `igraph.plot` about it via the `target` argument: + +>>> import matplotlib.pyplot as plt +>>> fig, ax = plt.subplots() +>>> ig.plot(g, target=ax) + +Exporting to other graph formats +++++++++++++++++++++++++++++++++++ +If igraph is missing a certain plotting feature and you cannot wait for us to include it, you can always export your graph +to a number of formats and use an external graph plotting tool. We support both conversion to file (e.g. DOT format used by +`graphviz`_) and to popular graph libraries such as `networkx`_ and `graph-tool`_: + +>>> dot = g.write('/myfolder/myfile.dot') +>>> n = g.to_networkx() +>>> gt = g.to_graph_tool() + +You do not need to have any libraries installed if you export to file, but you do need them to convert directly to external +Python objects (`networkx`_, `graph-tool`_). + +Plotting options +==================== +You can add an argument `layout` to the `plot` function to specify a precomputed layout, e.g.: + +>>> layout = g.layout("kamada_kawai") +>>> ig.plot(g, layout=layout) + +It is also possible to use the name of the layout algorithm directly: + +>>> ig.plot(g, layout="kamada_kawai") + +If the layout is left unspecified, igraph uses the dedicated `layout_auto()` function, which chooses between one of several +possible layouts based on the number of vertices and edges. + +You can also specify vertex and edge color, size, and labels - and more - via additional arguments, e.g.: + +>>> ig.plot(g, +>>> vertex_size=20, +>>> vertex_color=['blue', 'red', 'green', 'yellow'], +>>> vertex_label=['first', 'second', 'third', 'fourth'], +>>> edge_width=[1, 4], +>>> edge_color=['black', 'grey'], +>>> ) + +See the `tutorial`_ for examples and a full list of options. -.. note:: TODO. This is a placeholder section; it is not written yet. +.. _API documentation: https://igraph.org/python/doc/igraph-module.html +.. _matplotlib: https://matplotlib.org +.. _Jupyter: https://jupyter.org/ +.. _tutorial: https://igraph.org/python/doc/tutorial/tutorial.html#layouts-and-plotting +.. _Cairo: https://www.cairographics.org +.. _graphviz: http://www.graphviz.org +.. _networkx: https://networkx.org/ +.. _graph-tool: https://graph-tool.skewed.de/ From 90e56251af00b30540fd06951a7423de249b8fd0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 6 Dec 2020 17:40:42 +1100 Subject: [PATCH 0292/1892] Bugfix #349 for in recent matplotlib drawing PR --- src/igraph/drawing/graph.py | 43 +++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 0491c851e..f713d2b67 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -947,10 +947,13 @@ def __init__(self, ax): self.ax = ax def draw(self, graph, *args, **kwds): + # NOTE: matplotlib has numpy as a dependency, so we can use it in here + import matplotlib as mpl import matplotlib.markers as mmarkers from matplotlib.path import Path from matplotlib.patches import FancyArrowPatch from matplotlib.patches import ArrowStyle + import numpy as np def shrink_vertex(ax, aux, vcoord, vsize_squared): '''Shrink edge by vertex size''' @@ -987,19 +990,38 @@ def callback_edge_offset(event): vcoord = layout.coords # Vertex properties - vsizes = kwds.get('vertex_size', None) - # NOTE: ax.scatter uses the *square* of diameter - if vsizes is not None: - vsizes **= 2 - if isinstance(vsizes, float) or isinstance(vsizes, int): - vsizes = [vsizes] * len(vcoord) - c = kwds.get('vertex_color', 'black') + nv = graph.vcount() + + # Vertex size + vsizes = kwds.get('vertex_size', 5) + # Enforce numpy array for sizes, because (1) we need the square and (2) + # they are needed to calculate autoshrinking of edges + if np.isscalar(vsizes): + vsizes = np.repeat(vsizes, nv) + else: + vsizes = np.asarray(vsizes) + # ax.scatter uses the *square* of diameter + vsizes **= 2 + + # Vertex color + c = kwds.get('vertex_color', 'steelblue') + + # Vertex opacity alpha = kwds.get('alpha', 1.0) + + # Vertex labels label = kwds.get('vertex_label', None) - label_size = kwds.get('vertex_label_size', None) + + # Vertex label size + label_size = kwds.get('vertex_label_size', mpl.rcParams['font.size']) + + # Vertex zorder vzorder = kwds.get('vertex_order', 2) - # mpl shapes use slightly different names from Cairo - shapes = kwds.get('vertex_shape', None) + + # Vertex shapes + # mpl shapes use slightly different names from Cairo, but we want the + # API to feel consistent, so we use a conversion dictionary + shapes = kwds.get('vertex_shape', 'o') if shapes is not None: if isinstance(shapes, str): shapes = self._shape_dict.get(shapes, shapes) @@ -1007,7 +1029,6 @@ def callback_edge_offset(event): pass # Scatter vertices - # NOTE: matplotlib does not support a list of shapes yet x, y = list(zip(*vcoord)) ax.scatter(x, y, s=vsizes, c=c, marker=shapes, zorder=vzorder, alpha=alpha) From 12e1654fb6701941e61889a63f6c54b78aa41aab Mon Sep 17 00:00:00 2001 From: MapleCCC Date: Sun, 6 Dec 2020 20:27:46 +0800 Subject: [PATCH 0293/1892] Fix outdated link and typo (#352) * Fix typo in tutorial * Fix outdated link to "A Byte of Python" in tutorial --- doc/source/tutorial.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 76acd1919..16ac2c6be 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -11,7 +11,7 @@ it at least once if you are new to |igraph|. I assume that you have already inst you did not, see :ref:`installing-igraph` first. Familiarity with the Python language is also assumed; if this is the first time you are trying to use Python, there are many good Python tutorials on the Internet to get you started. If this is the first time you ever try to use a -programming language, `A Byte of Python `_ is a good place to +programming language, `A Byte of Python `_ is a good place to start out. If you already have a stable programming background in other languages and you just want a quick overview of Python, `Learn Python in 10 minutes `_ is probably your best bet. @@ -40,7 +40,7 @@ following: Another way to make use of |igraph| is to import all its objects and methods into the main Python namespace (so you do not have to type the namespace-qualification every time). -This is fine as long as none of your own objects and methods do not conflict with the ones +This is fine as long as your own objects and methods do not conflict with the ones provided by |igraph|: >>> from igraph import * @@ -665,7 +665,7 @@ the screen or to a PDF, PNG or SVG file using the `Cairo library Date: Fri, 11 Dec 2020 18:37:36 +1030 Subject: [PATCH 0294/1892] Install from source instructions (#351) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Nepusz --- doc/source/install.rst | 121 ++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 19 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 6f067f093..b5aeb1599 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -40,6 +40,11 @@ and macOS. Currently there are binary packages for Python 2.7, and Python 3.5 th note that support for Python 2.7 will be discontinued with the version 0.9.0 release of |igraph|'s Python interface. +To install |python-igraph| globally, use the following command (you probably need +administrator/root priviledges): + + $ pip install python-igraph + Many users like to install packages into a project-specific `virtual environment `_. A variation of the following commands should work on most platforms: @@ -48,14 +53,20 @@ A variation of the following commands should work on most platforms: $ source venv/bin/activate $ pip install python-igraph -To test the installed package, launch Python within the virtual environment and run the -following: +Alternatively, if you do not want to activate the virtualenv, you can call the `pip` executable +in it directly: - >>> import igraph.test - >>> igraph.test.run_tests() + $ python -m venv venv + $ venv/bin/pip install python-igraph -The above commands run the bundled test cases to ensure that everything is fine with your -|igraph| installation. +The unit tests of `python-igraph` are implemented with the standard `unittest` module so you can +run them like this from your virtualenv: + + $ python -m unittest discover + +As usual, you can also do this without activating the virtualenv: + + $ venv/bin/python -m unittest discover Installing |igraph| via Conda ----------------------------- @@ -77,7 +88,7 @@ The above commands run the bundled test cases to ensure that everything is fine |igraph| on Windows ------------------- -There is a Windows installer for |igraph|'s Python interface on the `Python Package Index +Precompiled Windows wheels for |igraph|'s Python interface are available on the `Python Package Index `_ (see `Installing igraph from the Python Package Index`_). @@ -104,11 +115,9 @@ If PyCairo was successfully installed, this will display a Petersen graph. |igraph| on macOS ----------------- -The Mac installer for |igraph|'s Python interface on the `Python Package Index -`_ works for Intel-based Macs only. PowerPC -users should compile the package themselves (see `Compiling igraph from source`_). - -TODO: Check if PyCairo on Mac still requires using Brew +Precompiled macOS wheels for |igraph|'s Python interface are available on the `Python Package Index +`_ (see `Installing igraph from the Python Package +Index`_). Graph plotting in |igraph| is implemented using a third-party package called `Cairo `_. If you want to create publication-quality plots in |igraph| @@ -131,13 +140,87 @@ If Cairo was successfully installed, this will display a Petersen graph. ----------------- |igraph|'s Python interface and its dependencies have been packaged for most popular Linux -distributions, including Arch Linux, Debian, Fedora, GNU Guix, NixOS, and Ubuntu. Because -distribution packages are often outdated, you may choose to install |igraph| from the `Python -Package Index `_ instead to get a more recent -release (see `Installing igraph from the Python Package Index`_). +distributions, including Arch Linux, Debian, Fedora, GNU Guix, NixOS, and Ubuntu. +|python-igraph| and its underlying |igraph| C core are usually in two different packages, but +your package manager should take care of that dependency for you. + +.. note:: Distribution packages can be outdated: if you find that's the case for you, you may + choose to install |igraph| from the `Python Package Index `_ + instead to get a more recent release (see `Installing igraph from the Python Package Index`_). + +Compiling |python-igraph| from source +===================================== + +|python-igraph| binds itself into the main |igraph| library using some glue code written in C, so you'll need +both a C compiler and the library itself. Source tarballs of |python-igraph| obtained from PyPI already +contain a matching version of the C core of |igraph|. + +There are two common scenarios to compile |python-igraph| from source: + +1. Your would like to use the latest development version from Github, usually to try out some recently + added features + +2. The PyPI repository does not include precompiled binaries for your system. This can happen if your operating + system is not covered by our continuous development. + +Both will be covered in the next sections. + +Compiling using pip +------------------- +If you want the development version of |python-igraph|, call: + + $ pip install git+https://github.com/igraph/python-igraph + +`pip` is smart enough to download the sources from Github, initialize the submodule for the |igraph| C core, +compile it, and then compile |python-igraph| against it and install it. As above, a virtual environment is +a commonly used sandbox to test experimental packages. + +If you want the latest release from PyPI but prefer to (or have to) install from source, call: + + $ pip install --no-binary ':all:' python-igraph + +.. note:: If there is no binary for your system anyway, you can just try without the `--no-binary` option and + obtain the same result. + +Compiling step by step +---------------------- +This section should be rarely used in practice but explains how to compile and install |python-igraph| step +by step without `pip`. + +First, obtain the bleeding-edge source code from Github: + + $ git clone https://github.com/igraph/python-igraph.git + +or download a recent release from `PyPI ` or from the +`Github releases page `. Decompress the archive if +needed. + +Second, go into the folder: + + $ cd python-igraph + +(it might have a slightly different name depending on the release). + +Third, if you cloned the source from Github, initialize the `git` submodule for the |igraph| C core: + + $ git submodule update --init + +.. note:: If you prefer to compile and link |python-igraph| against an existing |igraph| C core, for instance + the one you installed with your package manager, you can skip the `git` submodule initialization step. If you + downloaded a tarball, you also need to remove the `vendor/source/igraph` folder because the setup script + will look for the vendored |igraph| copy first. However, a particular version of |python-igraph| is guaranteed + to work only with the version of the C core that is bundled with it (or with the revision that the `git` + submodule points to). + +Fourth, call the standard Python `setup.py` script, e.g. for compiling: + + $ python setup.py build +(press Enter when prompted). That will compile the |python-igraph| package in a subfolder called +`build/lib.`, e.g. `build/lib.linux-x86_64-3.8`. You can add +that folder to your `PYTHONPATH` if you want to import directly from it, or you can call the `setup.py` +script to install it from there: -Compiling |igraph| from source -============================== + $ python setup.py install -TODO +.. note:: The `setup.py` script takes a number of options to customize the install location. From 1ef2215c4c40183eb810b28ba08cdc5690655d67 Mon Sep 17 00:00:00 2001 From: Thierry Thomas Date: Sat, 2 Jan 2021 10:30:26 +0000 Subject: [PATCH 0295/1892] Adding an image viewer for FreeBSD (#354) --- src/igraph/configuration.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index df33886f3..4a50ce4ea 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -56,6 +56,18 @@ def get_platform_image_viewer(): if os.path.isfile(full_path): return full_path return "" + elif plat == "FreeBSD": + # FreeBSD also has a whole lot of choices, try to find one + choices = ["eog", "gthumb", "geeqie", "display", + "gpicview", "gwenview", "qiv", "gimv", "ristretto", + "geeqie", "eom"] + paths = ["%%LOCALBASE%%/bin"] + for path in paths: + for choice in choices: + full_path = os.path.join(path, choice) + if os.path.isfile(full_path): + return full_path + return "" elif plat == "Windows" or plat == "Microsoft": # Thanks to Dale Hunscher # Use the built-in Windows image viewer, if available return "start" From 0a3b81e14660d2a79f5695ed0ac056a18396de8d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Jan 2021 12:54:35 +0100 Subject: [PATCH 0296/1892] ci: try Appveyor without zstd --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a1cfd8375..782978be6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,7 +33,6 @@ install: # update msys2 - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - bash -lc "pacman --noconfirm -Sy" - - bash -lc "pacman --needed --noconfirm -S zstd" - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" # prepare Python From d206314ed20819ff1a6396f0e3896b517b4f8361 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Jan 2021 12:57:41 +0100 Subject: [PATCH 0297/1892] ci: try a newer Appveyor image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 782978be6..69a63209e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ image: - - Visual Studio 2017 + - Visual Studio 2019 environment: global: From ebcc444c10c22db627b21b809ef15a4888d5dc94 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Jan 2021 13:37:00 +0100 Subject: [PATCH 0298/1892] ci: adjust VS path in appveyor.yml for new image --- appveyor.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 69a63209e..4e3ee3605 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,11 +25,6 @@ platform: - x64 install: - # update msys2 keyring first - - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" - - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" - - bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" - # update msys2 - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - bash -lc "pacman --noconfirm -Sy" @@ -51,13 +46,13 @@ for: only: - MSYSTEM: MINGW32 build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" + - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" - cibuildwheel --output-dir wheelhouse - matrix: only: - MSYSTEM: MINGW64 build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - cibuildwheel --output-dir wheelhouse artifacts: From d353fa03f456dde825fd89eea8a1d8c01f18cb8e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 15 Jan 2021 21:03:24 +1100 Subject: [PATCH 0299/1892] Abandon Python 2 and lint black --- setup.py | 11 +- src/igraph/__init__.py | 1169 +++++---- src/igraph/app/shell.py | 144 +- src/igraph/clustering.py | 246 +- src/igraph/compat.py | 75 - src/igraph/configuration.py | 98 +- src/igraph/cut.py | 52 +- src/igraph/datatypes.py | 186 +- src/igraph/drawing/__init__.py | 73 +- src/igraph/drawing/baseclasses.py | 28 +- src/igraph/drawing/colors.py | 3902 +++++++++++------------------ src/igraph/drawing/coord.py | 15 +- src/igraph/drawing/edge.py | 269 +- src/igraph/drawing/graph.py | 392 +-- src/igraph/drawing/metamagic.py | 65 +- src/igraph/drawing/shapes.py | 136 +- src/igraph/drawing/text.py | 40 +- src/igraph/drawing/utils.py | 127 +- src/igraph/drawing/vertex.py | 32 +- src/igraph/formula.py | 40 +- src/igraph/layout.py | 124 +- src/igraph/matching.py | 25 +- src/igraph/operators.py | 75 +- src/igraph/remote/gephi.py | 23 +- src/igraph/statistics.py | 199 +- src/igraph/summary.py | 98 +- src/igraph/test/foreign.py | 288 ++- src/igraph/utils.py | 56 +- tests/test_structural.py | 2 +- tox.ini | 5 +- 30 files changed, 3796 insertions(+), 4199 deletions(-) delete mode 100644 src/igraph/compat.py diff --git a/setup.py b/setup.py index ded7fc943..f92ddda81 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,8 @@ ########################################################################### # Check Python's version info and exit early if it is too old -if sys.version_info < (2, 7): - print("This module requires Python >= 2.7") +if sys.version_info < (3, 5): + print("This module requires Python >= 3.5") sys.exit(0) # Check whether we are compiling for PyPy. Headers will not be installed @@ -913,7 +913,6 @@ def use_educated_guess(self): "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", @@ -932,10 +931,4 @@ def use_educated_guess(self): }, ) -if sys.version_info <= (2, 7): - options["requires"] = options.pop("install_requires") - -if sys.version_info > (3, 0): - options["use_2to3"] = True - setup(**options) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index eb200c1ad..c87bfa415 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -7,9 +7,8 @@ _3d_version_for """ -from __future__ import with_statement -__license__ = u""" +__license__ = """ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -54,15 +53,17 @@ import operator from collections import defaultdict -from itertools import izip + from shutil import copyfileobj from warnings import warn + def deprecated(message): """Prints a warning message related to the deprecation of some igraph feature.""" warn(message, DeprecationWarning, stacklevel=3) + # pylint: disable-msg=E1101 class Graph(GraphBase): """Generic graph. @@ -167,8 +168,12 @@ def __init__(self, *args, **kwds): # Set up default values for the parameters. This should match the order # in *args kwd_order = ( - "n", "edges", "directed", "graph_attrs", "vertex_attrs", - "edge_attrs" + "n", + "edges", + "directed", + "graph_attrs", + "vertex_attrs", + "edge_attrs", ) params = [0, [], False, {}, {}, {}] @@ -177,9 +182,11 @@ def __init__(self, *args, **kwds): unknown_kwds = set(kwds.keys()) unknown_kwds.difference_update(kwd_order) if unknown_kwds: - raise TypeError("{0}.__init__ got an unexpected keyword argument {1!r}".format( - self.__class__.__name__, unknown_kwds.pop() - )) + raise TypeError( + "{0}.__init__ got an unexpected keyword argument {1!r}".format( + self.__class__.__name__, unknown_kwds.pop() + ) + ) # If the first argument is a list or any other iterable, assume that # the number of vertices were omitted @@ -188,7 +195,7 @@ def __init__(self, *args, **kwds): args.insert(0, params[0]) # Override default parameters from args - params[:len(args)] = args + params[: len(args)] = args # Override default parameters from keywords for idx, k in enumerate(kwd_order): @@ -210,6 +217,7 @@ def __init__(self, *args, **kwds): # as the lower-level C API works with memoryviews only try: from numpy import ndarray, matrix + if isinstance(edges, (ndarray, matrix)): edges = numpy_to_contiguous_memoryview(edges) except ImportError: @@ -222,18 +230,18 @@ def __init__(self, *args, **kwds): GraphBase.__init__(self, nverts, edges, directed) # Set the graph attributes - for key, value in graph_attrs.iteritems(): - if isinstance(key, (int, long)): + for key, value in graph_attrs.items(): + if isinstance(key, int): key = str(key) self[key] = value # Set the vertex attributes - for key, value in vertex_attrs.iteritems(): - if isinstance(key, (int, long)): + for key, value in vertex_attrs.items(): + if isinstance(key, int): key = str(key) self.vs[key] = value # Set the edge attributes - for key, value in edge_attrs.iteritems(): - if isinstance(key, (int, long)): + for key, value in edge_attrs.items(): + if isinstance(key, int): key = str(key) self.es[key] = value @@ -255,7 +263,7 @@ def add_edge(self, source, target, **kwds): eid = self.ecount() self.add_edges([(source, target)]) edge = self.es[eid] - for key, value in kwds.iteritems(): + for key, value in kwds.items(): edge[key] = value return edge @@ -275,7 +283,7 @@ def add_edges(self, es, attributes=None): res = GraphBase.add_edges(self, es) n = self.ecount() - eid if (attributes is not None) and (n > 0): - for key, val in attributes.items(): + for key, val in list(attributes.items()): self.es[eid:][key] = val return res @@ -295,7 +303,7 @@ def add_vertex(self, name=None, **kwds): vid = self.vcount() self.add_vertices(1) vertex = self.vs[vid] - for key, value in kwds.iteritems(): + for key, value in kwds.items(): vertex[key] = value if name is not None: vertex["name"] = name @@ -320,13 +328,13 @@ def add_vertices(self, n, attributes=None): values of this dict are the attributes themselves, but if n=1 then they have to be lists of length 1. """ - if isinstance(n, basestring): + if isinstance(n, str): # Adding a single vertex with a name m = self.vcount() result = GraphBase.add_vertices(self, 1) self.vs[m]["name"] = n if attributes is not None: - for key, val in attributes.items(): + for key, val in list(attributes.items()): self.vs[m][key] = val elif hasattr(n, "__iter__"): m = self.vcount() @@ -338,13 +346,13 @@ def add_vertices(self, n, attributes=None): if len(names) > 0: self.vs[m:]["name"] = names if attributes is not None: - for key, val in attributes.items(): + for key, val in list(attributes.items()): self.vs[m:][key] = val else: result = GraphBase.add_vertices(self, n) if (attributes is not None) and (n > 0): m = self.vcount() - n - for key, val in attributes.items(): + for key, val in list(attributes.items()): self.vs[m:][key] = val return result @@ -355,8 +363,10 @@ def adjacent(self, *args, **kwds): @deprecated: replaced by L{Graph.incident()} since igraph 0.6 """ - deprecated("Graph.adjacent() is deprecated since igraph 0.6, please use " - "Graph.incident() instead") + deprecated( + "Graph.adjacent() is deprecated since igraph 0.6, please use " + "Graph.incident() instead" + ) return self.incident(*args, **kwds) def as_directed(self, *args, **kwds): @@ -414,7 +424,7 @@ def indegree(self, *args, **kwds): See L{degree} for possible arguments. """ - kwds['mode'] = IN + kwds["mode"] = IN return self.degree(*args, **kwds) def outdegree(self, *args, **kwds): @@ -422,7 +432,7 @@ def outdegree(self, *args, **kwds): See L{degree} for possible arguments. """ - kwds['mode'] = OUT + kwds["mode"] = OUT return self.degree(*args, **kwds) def all_st_cuts(self, source, target): @@ -441,8 +451,10 @@ def all_st_cuts(self, source, target): @ref: JS Provan and DR Shier: A paradigm for listing (s,t)-cuts in graphs. Algorithmica 15, 351--372, 1996. """ - return [Cut(self, cut=cut, partition=part) - for cut, part in izip(*GraphBase.all_st_cuts(self, source, target))] + return [ + Cut(self, cut=cut, partition=part) + for cut, part in zip(*GraphBase.all_st_cuts(self, source, target)) + ] def all_st_mincuts(self, source, target, capacity=None): """\ @@ -463,8 +475,9 @@ def all_st_mincuts(self, source, target, capacity=None): graphs. Algorithmica 15, 351--372, 1996. """ value, cuts, parts = GraphBase.all_st_mincuts(self, source, target, capacity) - return [Cut(self, value, cut=cut, partition=part) - for cut, part in izip(cuts, parts)] + return [ + Cut(self, value, cut=cut, partition=part) for cut, part in zip(cuts, parts) + ] def biconnected_components(self, return_articulation_points=False): """\ @@ -495,6 +508,7 @@ def biconnected_components(self, return_articulation_points=False): return clustering, aps else: return clustering + blocks = biconnected_components def clear(self): @@ -538,9 +552,10 @@ def clusters(self, mode=STRONG): clusters being sought. Optional, defaults to C{STRONG}. @return: a L{VertexClustering} object""" return VertexClustering(self, GraphBase.clusters(self, mode)) + components = clusters - def degree_distribution(self, bin_width = 1, *args, **kwds): + def degree_distribution(self, bin_width=1, *args, **kwds): """degree_distribution(bin_width=1, ...) Calculates the degree distribution of the graph. @@ -573,8 +588,9 @@ def dyad_census(self, *args, **kwds): """ return DyadCensus(GraphBase.dyad_census(self, *args, **kwds)) - def get_adjacency(self, type=GET_ADJACENCY_BOTH, attribute=None, \ - default=0, eids=False): + def get_adjacency( + self, type=GET_ADJACENCY_BOTH, attribute=None, default=0, eids=False + ): """Returns the adjacency matrix of a graph. @param type: either C{GET_ADJACENCY_LOWER} (uses the lower @@ -599,8 +615,11 @@ def get_adjacency(self, type=GET_ADJACENCY_BOTH, attribute=None, \ in the matrix for each vertex pair. @return: the adjacency matrix as a L{Matrix}. """ - if type != GET_ADJACENCY_LOWER and type != GET_ADJACENCY_UPPER and \ - type != GET_ADJACENCY_BOTH: + if ( + type != GET_ADJACENCY_LOWER + and type != GET_ADJACENCY_UPPER + and type != GET_ADJACENCY_BOTH + ): # Maybe it was called with the first argument as the attribute name type, attribute = attribute, type if type is None: @@ -617,7 +636,7 @@ def get_adjacency(self, type=GET_ADJACENCY_BOTH, attribute=None, \ if attribute not in self.es.attribute_names(): raise ValueError("Attribute does not exist") - data = [[default] * self.vcount() for _ in xrange(self.vcount())] + data = [[default] * self.vcount() for _ in range(self.vcount())] if self.is_directed(): for edge in self.es: @@ -651,7 +670,9 @@ def get_adjacency_sparse(self, attribute=None): try: from scipy import sparse except ImportError: - raise ImportError('You should install scipy package in order to use this function') + raise ImportError( + "You should install scipy package in order to use this function" + ) import numpy as np edges = self.get_edgelist() @@ -664,7 +685,7 @@ def get_adjacency_sparse(self, attribute=None): weights = self.es[attribute] N = self.vcount() - mtx = sparse.csr_matrix((weights, zip(*edges)), shape=(N, N)) + mtx = sparse.csr_matrix((weights, list(zip(*edges))), shape=(N, N)) if not self.is_directed(): mtx = mtx + sparse.triu(mtx, 1).T + sparse.tril(mtx, -1).T @@ -684,7 +705,7 @@ def get_adjlist(self, mode=OUT): the predecessors and the successors will be returned. Ignored for undirected graphs. """ - return [self.neighbors(idx, mode) for idx in xrange(self.vcount())] + return [self.neighbors(idx, mode) for idx in range(self.vcount())] def get_adjedgelist(self, *args, **kwds): """get_adjedgelist(mode=OUT) @@ -694,8 +715,10 @@ def get_adjedgelist(self, *args, **kwds): @deprecated: replaced by L{Graph.get_inclist()} since igraph 0.6 @see: Graph.get_inclist() """ - deprecated("Graph.get_adjedgelist() is deprecated since igraph 0.6, " - "please use Graph.get_inclist() instead") + deprecated( + "Graph.get_adjedgelist() is deprecated since igraph 0.6, " + "please use Graph.get_inclist() instead" + ) return self.get_inclist(*args, **kwds) def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): @@ -731,7 +754,7 @@ def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): for index, item in enumerate(paths): if item < 0: result.append(paths[prev:index]) - prev = index+1 + prev = index + 1 return result def get_inclist(self, mode=OUT): @@ -749,7 +772,7 @@ def get_inclist(self, mode=OUT): the predecessors and the successors will be returned. Ignored for undirected graphs. """ - return [self.incident(idx, mode) for idx in xrange(self.vcount())] + return [self.incident(idx, mode) for idx in range(self.vcount())] def gomory_hu_tree(self, capacity=None, flow="flow"): """gomory_hu_tree(capacity=None, flow="flow") @@ -917,13 +940,21 @@ def path_length_hist(self, directed=True): data, unconn = GraphBase.path_length_hist(self, directed) hist = Histogram(bin_width=1) for i, length in enumerate(data): - hist.add(i+1, length) - hist.unconnected = long(unconn) + hist.add(i + 1, length) + hist.unconnected = int(unconn) return hist - def pagerank(self, vertices=None, directed=True, damping=0.85, - weights=None, arpack_options=None, implementation="prpack", - niter=1000, eps=0.001): + def pagerank( + self, + vertices=None, + directed=True, + damping=0.85, + weights=None, + arpack_options=None, + implementation="prpack", + niter=1000, + eps=0.001, + ): """Calculates the Google PageRank values of a graph. @param vertices: the indices of the vertices being queried. @@ -957,9 +988,18 @@ def pagerank(self, vertices=None, directed=True, damping=0.85, vertices.""" if arpack_options is None: arpack_options = _igraph.arpack_options - return self.personalized_pagerank(vertices, directed, damping, None,\ - None, weights, arpack_options, \ - implementation, niter, eps) + return self.personalized_pagerank( + vertices, + directed, + damping, + None, + None, + weights, + arpack_options, + implementation, + niter, + eps, + ) def spanning_tree(self, weights=None, return_tree=True): """Calculates a minimum spanning tree for a graph. @@ -1037,8 +1077,9 @@ def triad_census(self, *args, **kwds): return TriadCensus(GraphBase.triad_census(self, *args, **kwds)) # Automorphisms - def count_automorphisms_vf2(self, color=None, edge_color=None, - node_compat_fn=None, edge_compat_fn=None): + def count_automorphisms_vf2( + self, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None + ): """Returns the number of automorphisms of the graph. This function simply calls C{count_isomorphisms_vf2} with the graph @@ -1048,12 +1089,19 @@ def count_automorphisms_vf2(self, color=None, edge_color=None, @return: the number of automorphisms of the graph @see: Graph.count_isomorphisms_vf2 """ - return self.count_isomorphisms_vf2(self, color1=color, color2=color, - edge_color1=edge_color, edge_color2=edge_color, - node_compat_fn=node_compat_fn, edge_compat_fn=edge_compat_fn) + return self.count_isomorphisms_vf2( + self, + color1=color, + color2=color, + edge_color1=edge_color, + edge_color2=edge_color, + node_compat_fn=node_compat_fn, + edge_compat_fn=edge_compat_fn, + ) - def get_automorphisms_vf2(self, color=None, edge_color=None, - node_compat_fn=None, edge_compat_fn=None): + def get_automorphisms_vf2( + self, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None + ): """Returns all the automorphisms of the graph This function simply calls C{get_isomorphisms_vf2} with the graph @@ -1064,9 +1112,15 @@ def get_automorphisms_vf2(self, color=None, edge_color=None, of the graph vertices to itself according to the automorphism @see: Graph.get_isomorphisms_vf2 """ - return self.get_isomorphisms_vf2(self, color1=color, color2=color, - edge_color1=edge_color, edge_color2=edge_color, - node_compat_fn=node_compat_fn, edge_compat_fn=edge_compat_fn) + return self.get_isomorphisms_vf2( + self, + color1=color, + color2=color, + edge_color1=edge_color, + edge_color2=edge_color, + node_compat_fn=node_compat_fn, + edge_compat_fn=edge_compat_fn, + ) # Various clustering algorithms -- mostly wrappers around GraphBase def community_fastgreedy(self, weights=None): @@ -1098,8 +1152,9 @@ def community_fastgreedy(self, weights=None): else: optimal_count = diff - return VertexDendrogram(self, merges, optimal_count, - modularity_params=dict(weights=weights)) + return VertexDendrogram( + self, merges, optimal_count, modularity_params=dict(weights=weights) + ) def community_infomap(self, edge_weights=None, vertex_weights=None, trials=10): """Finds the community structure of the network according to the Infomap @@ -1124,14 +1179,17 @@ def community_infomap(self, edge_weights=None, vertex_weights=None, trials=10): U{http://dx.doi.org/10.1140/epjst/e2010-01179-1}, U{http://arxiv.org/abs/0906.1405}. """ - membership, codelength = \ - GraphBase.community_infomap(self, edge_weights, vertex_weights, trials) - return VertexClustering(self, membership, \ - params={"codelength": codelength}, \ - modularity_params={"weights": edge_weights} ) - - def community_leading_eigenvector_naive(self, clusters = None, \ - return_merges = False): + membership, codelength = GraphBase.community_infomap( + self, edge_weights, vertex_weights, trials + ) + return VertexClustering( + self, + membership, + params={"codelength": codelength}, + modularity_params={"weights": edge_weights}, + ) + + def community_leading_eigenvector_naive(self, clusters=None, return_merges=False): """community_leading_eigenvector_naive(clusters=None, return_merges=False) @@ -1158,16 +1216,17 @@ def community_leading_eigenvector_naive(self, clusters = None, \ eigenvectors of matrices, arXiv:physics/0605087""" if clusters is None: clusters = -1 - cl, merges, q = GraphBase.community_leading_eigenvector_naive(self, \ - clusters, return_merges) + cl, merges, q = GraphBase.community_leading_eigenvector_naive( + self, clusters, return_merges + ) if merges is None: - return VertexClustering(self, cl, modularity = q) + return VertexClustering(self, cl, modularity=q) else: - return VertexDendrogram(self, merges, safemax(cl)+1) + return VertexDendrogram(self, merges, safemax(cl) + 1) - - def community_leading_eigenvector(self, clusters=None, weights=None, \ - arpack_options=None): + def community_leading_eigenvector( + self, clusters=None, weights=None, arpack_options=None + ): """community_leading_eigenvector(clusters=None, weights=None, arpack_options=None) @@ -1198,12 +1257,12 @@ def community_leading_eigenvector(self, clusters=None, weights=None, \ if arpack_options is not None: kwds["arpack_options"] = arpack_options - membership, _, q = GraphBase.community_leading_eigenvector(self, clusters, **kwds) - return VertexClustering(self, membership, modularity = q) - + membership, _, q = GraphBase.community_leading_eigenvector( + self, clusters, **kwds + ) + return VertexClustering(self, membership, modularity=q) - def community_label_propagation(self, weights = None, initial = None, \ - fixed = None): + def community_label_propagation(self, weights=None, initial=None, fixed=None): """community_label_propagation(weights=None, initial=None, fixed=None) Finds the community structure of the graph according to the label @@ -1236,13 +1295,10 @@ def community_label_propagation(self, weights = None, initial = None, \ networks. Phys Rev E 76:036106, 2007. U{http://arxiv.org/abs/0709.2938}. """ - if isinstance(fixed, basestring): + if isinstance(fixed, str): fixed = [bool(o) for o in g.vs[fixed]] - cl = GraphBase.community_label_propagation(self, \ - weights, initial, fixed) - return VertexClustering(self, cl, - modularity_params=dict(weights=weights)) - + cl = GraphBase.community_label_propagation(self, weights, initial, fixed) + return VertexClustering(self, cl, modularity_params=dict(weights=weights)) def community_multilevel(self, weights=None, return_levels=False): """Community structure based on the multilevel algorithm of @@ -1281,12 +1337,16 @@ def community_multilevel(self, weights=None, return_levels=False): levels, qs = GraphBase.community_multilevel(self, weights, True) result = [] for level, q in zip(levels, qs): - result.append(VertexClustering(self, level, q, - modularity_params=dict(weights=weights))) + result.append( + VertexClustering( + self, level, q, modularity_params=dict(weights=weights) + ) + ) else: membership = GraphBase.community_multilevel(self, weights, False) - result = VertexClustering(self, membership, - modularity_params=dict(weights=weights)) + result = VertexClustering( + self, membership, modularity_params=dict(weights=weights) + ) return result def community_optimal_modularity(self, *args, **kwds): @@ -1302,12 +1362,12 @@ def community_optimal_modularity(self, *args, **kwds): @return: the calculated membership vector and the corresponding modularity in a tuple.""" - membership, modularity = \ - GraphBase.community_optimal_modularity(self, *args, **kwds) + membership, modularity = GraphBase.community_optimal_modularity( + self, *args, **kwds + ) return VertexClustering(self, membership, modularity) - def community_edge_betweenness(self, clusters=None, directed=True, - weights=None): + def community_edge_betweenness(self, clusters=None, directed=True, weights=None): """Community structure based on the betweenness of the edges in the network. @@ -1338,11 +1398,12 @@ def community_edge_betweenness(self, clusters=None, directed=True, qs.reverse() if clusters is None: if qs: - clusters = qs.index(max(qs))+1 + clusters = qs.index(max(qs)) + 1 else: clusters = 1 - return VertexDendrogram(self, merges, clusters, - modularity_params=dict(weights=weights)) + return VertexDendrogram( + self, merges, clusters, modularity_params=dict(weights=weights) + ) def community_spinglass(self, *args, **kwds): """community_spinglass(weights=None, spins=25, parupdate=False, @@ -1397,11 +1458,10 @@ def community_spinglass(self, *args, **kwds): """ membership = GraphBase.community_spinglass(self, *args, **kwds) if "weights" in kwds: - modularity_params=dict(weights=kwds["weights"]) + modularity_params = dict(weights=kwds["weights"]) else: - modularity_params={} - return VertexClustering(self, membership, - modularity_params=modularity_params) + modularity_params = {} + return VertexClustering(self, membership, modularity_params=modularity_params) def community_walktrap(self, weights=None, steps=4): """Community detection algorithm of Latapy & Pons, based on random @@ -1425,11 +1485,12 @@ def community_walktrap(self, weights=None, steps=4): merges, qs = GraphBase.community_walktrap(self, weights, steps) qs.reverse() if qs: - optimal_count = qs.index(max(qs))+1 + optimal_count = qs.index(max(qs)) + 1 else: optimal_count = 1 - return VertexDendrogram(self, merges, optimal_count, - modularity_params=dict(weights=weights)) + return VertexDendrogram( + self, merges, optimal_count, modularity_params=dict(weights=weights) + ) def k_core(self, *args): """Returns some k-cores of the graph. @@ -1443,7 +1504,7 @@ def k_core(self, *args): all M{k}-cores in increasing order of M{k}. """ if len(args) == 0: - indices = xrange(self.vcount()) + indices = range(self.vcount()) return_single = False else: return_single = True @@ -1454,22 +1515,30 @@ def k_core(self, *args): except: indices.append(arg) - if len(indices)>1 or hasattr(args[0], "__iter__"): + if len(indices) > 1 or hasattr(args[0], "__iter__"): return_single = False corenesses = self.coreness() result = [] - vidxs = xrange(self.vcount()) + vidxs = range(self.vcount()) for idx in indices: core_idxs = [vidx for vidx in vidxs if corenesses[vidx] >= idx] result.append(self.subgraph(core_idxs)) - if return_single: return result[0] + if return_single: + return result[0] return result - def community_leiden(self, objective_function="CPM", weights=None, - resolution_parameter=1.0, beta=0.01, initial_membership=None, - n_iterations=2, node_weights=None): + def community_leiden( + self, + objective_function="CPM", + weights=None, + resolution_parameter=1.0, + beta=0.01, + initial_membership=None, + n_iterations=2, + node_weights=None, + ): """community_leiden(objective_function=CPM, weights=None, resolution_parameter=1.0, beta=0.01, initial_membership=None, n_iterations=2, node_weights=None) @@ -1506,20 +1575,24 @@ def community_leiden(self, objective_function="CPM", weights=None, reports, 9(1), 5233. doi: 10.1038/s41598-019-41695-z """ if objective_function.lower() not in ("cpm", "modularity"): - raise ValueError("objective_function must be \"CPM\" or \"modularity\".") + raise ValueError('objective_function must be "CPM" or "modularity".') - membership = GraphBase.community_leiden(self, - edge_weights=weights, node_weights=node_weights, - resolution_parameter=resolution_parameter, - normalize_resolution=(objective_function == "modularity"), - beta=beta, initial_membership=initial_membership, n_iterations=n_iterations) + membership = GraphBase.community_leiden( + self, + edge_weights=weights, + node_weights=node_weights, + resolution_parameter=resolution_parameter, + normalize_resolution=(objective_function == "modularity"), + beta=beta, + initial_membership=initial_membership, + n_iterations=n_iterations, + ) if weights is not None: - modularity_params=dict(weights=weights) + modularity_params = dict(weights=weights) else: - modularity_params={} - return VertexClustering(self, membership, - modularity_params=modularity_params) + modularity_params = {} + return VertexClustering(self, membership, modularity_params=modularity_params) def layout(self, layout=None, *args, **kwds): """Returns the layout of the graph according to a layout algorithm. @@ -1668,9 +1741,9 @@ def layout_auto(self, *args, **kwds): vattrs = self.vertex_attributes() if "x" in vattrs and "y" in vattrs: if dim == 3 and "z" in vattrs: - return Layout(zip(self.vs["x"], self.vs["y"], self.vs["z"])) + return Layout(list(zip(self.vs["x"], self.vs["y"], self.vs["z"]))) else: - return Layout(zip(self.vs["x"], self.vs["y"])) + return Layout(list(zip(self.vs["x"], self.vs["y"]))) if self.vcount() <= 100 and self.is_connected(): algo = "kk" @@ -1688,13 +1761,22 @@ def layout_grid_fruchterman_reingold(self, *args, **kwds): @see: Graph.layout_fruchterman_reingold() """ - deprecated("Graph.layout_grid_fruchterman_reingold() is deprecated since "\ - "igraph 0.8, please use Graph.layout_fruchterman_reingold(grid=True) instead") + deprecated( + "Graph.layout_grid_fruchterman_reingold() is deprecated since " + "igraph 0.8, please use Graph.layout_fruchterman_reingold(grid=True) instead" + ) kwds["grid"] = True return self.layout_fruchterman_reingold(*args, **kwds) - def layout_sugiyama(self, layers=None, weights=None, hgap=1, vgap=1, - maxiter=100, return_extended_graph=False): + def layout_sugiyama( + self, + layers=None, + weights=None, + hgap=1, + vgap=1, + maxiter=100, + return_extended_graph=False, + ): """layout_sugiyama(layers=None, weights=None, hgap=1, vgap=1, maxiter=100, return_extended_graph=False) @@ -1751,12 +1833,15 @@ def layout_sugiyama(self, layers=None, weights=None, hgap=1, vgap=1, feedback arc set problem. Information Processing Letters 47:319-323, 1993. """ if not return_extended_graph: - return Layout(GraphBase._layout_sugiyama(self, layers, weights, hgap, - vgap, maxiter, return_extended_graph)) - - layout, extd_graph, extd_to_orig_eids = \ - GraphBase._layout_sugiyama(self, layers, weights, hgap, - vgap, maxiter, return_extended_graph) + return Layout( + GraphBase._layout_sugiyama( + self, layers, weights, hgap, vgap, maxiter, return_extended_graph + ) + ) + + layout, extd_graph, extd_to_orig_eids = GraphBase._layout_sugiyama( + self, layers, weights, hgap, vgap, maxiter, return_extended_graph + ) extd_graph.es["_original_eid"] = extd_to_orig_eids return Layout(layout), extd_graph @@ -1836,21 +1921,19 @@ def from_networkx(klass, g): # Nodes vnames = list(g.nodes) - vattr = {'_nx_name': vnames} + vattr = {"_nx_name": vnames} vcount = len(vnames) vd = {v: i for i, v in enumerate(vnames)} # NOTE: we do not need a special class for multigraphs, it is taken # care for at the edge level rather than at the graph level. graph = klass( - n=vcount, - directed=g.is_directed(), - graph_attrs=gattr, - vertex_attrs=vattr) + n=vcount, directed=g.is_directed(), graph_attrs=gattr, vertex_attrs=vattr + ) # Node attributes for v, datum in g.nodes.data(): - for key, val in datum.items(): + for key, val in list(datum.items()): graph.vs[vd[v]][key] = val # Edges and edge attributes @@ -1859,16 +1942,14 @@ def from_networkx(klass, g): # third element is the "color" of the edge) for e, (_, _, datum) in zip(g.edges, g.edges.data()): eid = graph.add_edge(vd[e[0]], vd[e[1]]) - for key, val in datum.items(): + for key, val in list(datum.items()): eid[key] = val return graph def to_graph_tool( - self, - graph_attributes=None, - vertex_attributes=None, - edge_attributes=None): + self, graph_attributes=None, vertex_attributes=None, edge_attributes=None + ): """Converts the graph to graph-tool Data types: graph-tool only accepts specific data types. See the @@ -1904,7 +1985,7 @@ def to_graph_tool( # Graph attributes if graph_attributes is not None: - for x, dtype in graph_attributes.items(): + for x, dtype in list(graph_attributes.items()): # Strange syntax for setting internal properties gprop = g.new_graph_property(str(dtype)) g.graph_properties[x] = gprop @@ -1912,7 +1993,7 @@ def to_graph_tool( # Vertex attributes if vertex_attributes is not None: - for x, dtype in vertex_attributes.items(): + for x, dtype in list(vertex_attributes.items()): # Create a new vertex property g.vertex_properties[x] = g.new_vertex_property(str(dtype)) # Fill the values from the igraph.Graph @@ -1921,12 +2002,12 @@ def to_graph_tool( # Edges and edge attributes if edge_attributes is not None: - for x, dtype in edge_attributes.items(): + for x, dtype in list(edge_attributes.items()): g.edge_properties[x] = g.new_edge_property(str(dtype)) for edge in self.es: e = g.add_edge(edge.source, edge.target) if edge_attributes is not None: - for x, dtype in edge_attributes.items(): + for x, dtype in list(edge_attributes.items()): prop = edge.attributes().get(x, None) g.edge_properties[x][e] = prop @@ -1945,13 +2026,10 @@ def from_graph_tool(klass, g): vcount = g.num_vertices() # Graph - graph = klass( - n=vcount, - directed=g.is_directed(), - graph_attrs=gattr) + graph = klass(n=vcount, directed=g.is_directed(), graph_attrs=gattr) # Node attributes - for key, val in g.vertex_properties.items(): + for key, val in list(g.vertex_properties.items()): prop = val.get_array() for i in range(vcount): graph.vs[i][key] = prop[i] @@ -1961,7 +2039,7 @@ def from_graph_tool(klass, g): # attributes later on for e in g.edges(): edge = graph.add_edge(int(e.source()), int(e.target())) - for key, val in g.edge_properties.items(): + for key, val in list(g.edge_properties.items()): edge[key] = val[e] return graph @@ -1978,7 +2056,7 @@ def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds): note that igraph is able to read back the written adjacency matrix if and only if this is a single newline character """ - if isinstance(f, basestring): + if isinstance(f, str): f = open(f, "w") matrix = self.get_adjacency(*args, **kwds) for row in matrix: @@ -1987,8 +2065,9 @@ def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds): f.close() @classmethod - def Read_Adjacency(klass, f, sep=None, comment_char = "#", attribute=None, - *args, **kwds): + def Read_Adjacency( + klass, f, sep=None, comment_char="#", attribute=None, *args, **kwds + ): """Constructs a graph based on an adjacency matrix from the given file Additional positional and keyword arguments not mentioned here are @@ -2004,13 +2083,15 @@ def Read_Adjacency(klass, f, sep=None, comment_char = "#", attribute=None, no weights are stored, values larger than 1 are considered as edge multiplicities. @return: the created graph""" - if isinstance(f, basestring): + if isinstance(f, str): f = open(f) matrix, ri, weights = [], 0, {} for line in f: line = line.strip() - if len(line) == 0: continue - if line.startswith(comment_char): continue + if len(line) == 0: + continue + if line.startswith(comment_char): + continue row = [float(x) for x in line.split(sep)] matrix.append(row) ri += 1 @@ -2018,10 +2099,10 @@ def Read_Adjacency(klass, f, sep=None, comment_char = "#", attribute=None, f.close() if attribute is None: - graph=klass.Adjacency(matrix, *args, **kwds) + graph = klass.Adjacency(matrix, *args, **kwds) else: kwds["attr"] = attribute - graph=klass.Weighted_Adjacency(matrix, *args, **kwds) + graph = klass.Weighted_Adjacency(matrix, *args, **kwds) return graph @@ -2043,7 +2124,8 @@ def write_dimacs(self, f, source=None, target=None, capacity="capacity"): except KeyError: raise ValueError( "source vertex must be provided in the 'source' graph " - "attribute or in the 'source' argument of write_dimacs()") + "attribute or in the 'source' argument of write_dimacs()" + ) if target is None: try: @@ -2051,10 +2133,10 @@ def write_dimacs(self, f, source=None, target=None, capacity="capacity"): except KeyError: raise ValueError( "target vertex must be provided in the 'target' graph " - "attribute or in the 'target' argument of write_dimacs()") + "attribute or in the 'target' argument of write_dimacs()" + ) - if isinstance(capacity, basestring) and \ - capacity not in self.edge_attributes(): + if isinstance(capacity, str) and capacity not in self.edge_attributes(): warn("'%s' edge attribute does not exist" % capacity) capacity = [1] * self.ecount() @@ -2077,6 +2159,7 @@ def write_graphmlz(self, f, compresslevel=9): produces the least compression, and 9 is slowest and produces the most compression.""" from igraph.utils import named_temporary_file + with named_temporary_file() as tmpfile: self.write_graphml(tmpfile) outf = gzip.GzipFile(f, "wb", compresslevel) @@ -2129,6 +2212,7 @@ def Read_GraphMLz(cls, f, *params, **kwds): specify 0 here. @return: the loaded graph object""" from igraph.utils import named_temporary_file + with named_temporary_file() as tmpfile: outf = open(tmpfile, "wb") copyfileobj(gzip.GzipFile(f, "rb"), outf) @@ -2145,15 +2229,16 @@ def write_pickle(self, fname=None, version=-1): @return: C{None} if the graph was saved successfully to the given file, or a string if C{fname} was C{None}. """ - import cPickle as pickle + import pickle as pickle + if fname is None: return pickle.dumps(self, version) if not hasattr(fname, "write"): file_was_opened = True - fname = open(fname, 'wb') + fname = open(fname, "wb") else: - file_was_opened=False - result=pickle.dump(self, fname, version) + file_was_opened = False + result = pickle.dump(self, fname, version) if file_was_opened: fname.close() return result @@ -2172,7 +2257,8 @@ def write_picklez(self, fname=None, version=-1): @return: C{None} if the graph was saved successfully to the given file. """ - import cPickle as pickle + import pickle as pickle + if not hasattr(fname, "write"): file_was_opened = True fname = gzip.open(fname, "wb") @@ -2194,7 +2280,8 @@ def Read_Pickle(klass, fname=None): a string containing the pickled data. @return: the created graph object. """ - import cPickle as pickle + import pickle as pickle + if hasattr(fname, "read"): # Probably a file or a file-like object result = pickle.load(fname) @@ -2209,13 +2296,17 @@ def Read_Pickle(klass, fname=None): # directly. result = pickle.loads(fname) except TypeError: - raise IOError('Cannot load file. If fname is a file name, that filename may be incorrect.') + raise IOError( + "Cannot load file. If fname is a file name, that filename may be incorrect." + ) except IOError: try: # No file with the given name, try unpickling directly. result = pickle.loads(fname) except TypeError: - raise IOError('Cannot load file. If fname is a file name, that filename may be incorrect.') + raise IOError( + "Cannot load file. If fname is a file name, that filename may be incorrect." + ) if fp is not None: result = pickle.load(fp) fp.close() @@ -2229,7 +2320,8 @@ def Read_Picklez(klass, fname, *args, **kwds): @param fname: the name of the file or a stream to read from. @return: the created graph object. """ - import cPickle as pickle + import pickle as pickle + if hasattr(fname, "read"): # Probably a file or a file-like object if isinstance(fname, gzip.GzipFile): @@ -2248,7 +2340,8 @@ def Read_Picklez(klass, fname, *args, **kwds): @param fname: the name of the file or a stream to read from. @return: the created graph object. """ - import cPickle as pickle + import pickle as pickle + if hasattr(fname, "read"): # Probably a file or a file-like object if isinstance(fname, gzip.GzipFile): @@ -2264,11 +2357,22 @@ def Read_Picklez(klass, fname, *args, **kwds): # pylint: disable-msg=C0301,C0323 # C0301: line too long. # C0323: operator not followed by a space - well, print >>f looks OK - def write_svg(self, fname, layout="auto", width=None, height=None, \ - labels="label", colors="color", shapes="shape", \ - vertex_size=10, edge_colors="color", \ - edge_stroke_widths="width", \ - font_size=16, *args, **kwds): + def write_svg( + self, + fname, + layout="auto", + width=None, + height=None, + labels="label", + colors="color", + shapes="shape", + vertex_size=10, + edge_colors="color", + edge_stroke_widths="width", + font_size=16, + *args, + **kwds + ): """Saves the graph as an SVG (Scalable Vector Graphics) file The file will be Inkscape (http://inkscape.org) compatible. @@ -2327,7 +2431,7 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ try: labels = self.vs.get_attribute_values(labels) except KeyError: - labels = [x+1 for x in xrange(self.vcount())] + labels = [x + 1 for x in range(self.vcount())] elif labels is None: labels = [""] * self.vcount() @@ -2362,10 +2466,10 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ raise ValueError("font size can't contain a semicolon") vcount = self.vcount() - labels.extend(str(i+1) for i in xrange(len(labels), vcount)) + labels.extend(str(i + 1) for i in range(len(labels), vcount)) colors.extend(["red"] * (vcount - len(colors))) - if isinstance(fname, basestring): + if isinstance(fname, str): f = open(fname, "w") our_file = True else: @@ -2374,7 +2478,7 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ bbox = BoundingBox(layout.bounding_box()) - sizes = [width-2*vertex_size, height-2*vertex_size] + sizes = [width - 2 * vertex_size, height - 2 * vertex_size] w, h = bbox.width, bbox.height ratios = [] @@ -2387,21 +2491,30 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ else: ratios.append(sizes[1] / h) - layout = [[(row[0] - bbox.left) * ratios[0] + vertex_size, \ - (row[1] - bbox.top) * ratios[1] + vertex_size] \ - for row in layout] + layout = [ + [ + (row[0] - bbox.left) * ratios[0] + vertex_size, + (row[1] - bbox.top) * ratios[1] + vertex_size, + ] + for row in layout + ] directed = self.is_directed() - print >> f, '' - print >> f, '' - print >> f - print >> f, '> f, 'width="{0}px" height="{1}px">'.format(width, height), - + print('', file=f) + print( + "", + file=f, + ) + print(file=f) + print( + ''.format(width, height), end=" ", file=f) edge_color_dict = {} - print >> f, '' + print('', file=f) for e_col in set(edge_colors): if e_col == "#000000": marker_index = "" @@ -2409,23 +2522,34 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ marker_index = str(len(edge_color_dict)) # Print an arrow marker for each possible line color # This is a copy of Inkscape's standard Arrow 2 marker - print >> f, '> f, ' inkscape:stockid="Arrow2Lend{0}"'.format(marker_index) - print >> f, ' orient="auto"' - print >> f, ' refY="0.0"' - print >> f, ' refX="0.0"' - print >> f, ' id="Arrow2Lend{0}"'.format(marker_index) - print >> f, ' style="overflow:visible;">' - print >> f, ' > f, ' id="pathArrow{0}"'.format(marker_index) - print >> f, ' style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;fill:{0}"'.format(e_col) - print >> f, ' d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "' - print >> f, ' transform="scale(1.1) rotate(180) translate(1,0)" />' - print >> f, '' + print("', file=f) + print(" ', file=f) + print("", file=f) edge_color_dict[e_col] = "Arrow2Lend{0}".format(marker_index) - print >> f, '' - print >> f, '' + print("", file=f) + print( + '', + file=f, + ) for eidx, edge in enumerate(self.es): vidxs = edge.tuple @@ -2437,32 +2561,41 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ x2 = x2 - vertex_size * math.cos(angle) y2 = y2 - vertex_size * math.sin(angle) - print >> f, '> f, ' style="fill:none;stroke:{0};stroke-width:{2};stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none{1}"'\ - .format(edge_colors[eidx], ";marker-end:url(#{0})".\ - format(edge_color_dict[edge_colors[eidx]]) \ - if directed else "", edge_stroke_widths[eidx]) - print >> f, ' d="M {0},{1} {2},{3}"'.format(x1, y1, x2, y2) - print >> f, ' id="path{0}"'.format(eidx) - print >> f, ' inkscape:connector-type="polyline"' - print >> f, ' inkscape:connector-curvature="0"' - print >> f, ' inkscape:connection-start="#g{0}"'.format(edge.source) - print >> f, ' inkscape:connection-start-point="d4"' - print >> f, ' inkscape:connection-end="#g{0}"'.format(edge.target) - print >> f, ' inkscape:connection-end-point="d4" />' - - print >> f, " " - print >> f - - print >> f, ' ' - print >> f, ' ' + print("', file=f) + + print(" ", file=f) + print(file=f) + + print( + ' ', + file=f, + ) + print(" ", file=f) if any(x == 3 for x in shapes): # Only import tkFont if we really need it. Unfortunately, this will # flash up an unneccesary Tk window in some cases - import tkFont - import Tkinter as tk + import tkinter.font + import tkinter as tk # This allows us to dynamically size the width of the nodes. # Unfortunately this works only with font sizes specified in pixels. @@ -2472,54 +2605,103 @@ def write_svg(self, fname, layout="auto", width=None, height=None, \ try: font_size_in_pixels = int(font_size) except: - raise ValueError("font sizes must be specified in pixels " - "when any of the nodes has shape=3 (i.e. " - "node size determined by text size)") + raise ValueError( + "font sizes must be specified in pixels " + "when any of the nodes has shape=3 (i.e. " + "node size determined by text size)" + ) tk_window = tk.Tk() - font = tkFont.Font(root=tk_window, font=("Sans", font_size_in_pixels, tkFont.NORMAL)) + font = tkinter.font.Font( + root=tk_window, font=("Sans", font_size_in_pixels, tkinter.font.NORMAL) + ) else: tk_window = None for vidx in range(self.vcount()): - print >> f, ' '.\ - format(vidx, layout[vidx][0], layout[vidx][1]) + print( + ' '.format( + vidx, layout[vidx][0], layout[vidx][1] + ), + file=f, + ) if shapes[vidx] == 1: # Undocumented feature: can handle two colors but only for circles c = str(colors[vidx]) if " " in c: c = c.split(" ") vs = str(vertex_size) - print >> f, ' '.format(vs, c[0]) - print >> f, ' '.format(vs, c[1]) - print >> f, ' '\ - .format(vs) + print( + ' '.format( + vs, c[0] + ), + file=f, + ) + print( + ' '.format( + vs, c[1] + ), + file=f, + ) + print( + ' '.format(vs), + file=f, + ) else: - print >> f, ' '.\ - format(str(vertex_size), str(colors[vidx])) + print( + ' '.format( + str(vertex_size), str(colors[vidx]) + ), + file=f, + ) elif shapes[vidx] == 2: - print >> f, ' '.\ - format(vertex_size, vertex_size * 2, vidx, colors[vidx]) + print( + ' '.format( + vertex_size, vertex_size * 2, vidx, colors[vidx] + ), + file=f, + ) elif shapes[vidx] == 3: - (vertex_width, vertex_height) = (font.measure(str(labels[vidx])) + 2, font.metrics("linespace") + 2) - print >> f, ' '.\ - format(vertex_width / 2., vertex_height / 2., vertex_width, vertex_height, vidx, colors[vidx]) - - print >> f, ' '.format(vertex_size / 2.,vidx, font_size) - print >> f, '{2}'.format(vertex_size / 2.,vidx, str(labels[vidx])) - print >> f, ' ' - - print >> f, '' - print >> f - print >> f, '' + (vertex_width, vertex_height) = ( + font.measure(str(labels[vidx])) + 2, + font.metrics("linespace") + 2, + ) + print( + ' '.format( + vertex_width / 2.0, + vertex_height / 2.0, + vertex_width, + vertex_height, + vidx, + colors[vidx], + ), + file=f, + ) + + print( + ' '.format( + vertex_size / 2.0, vidx, font_size + ), + file=f, + ) + print( + '{2}'.format( + vertex_size / 2.0, vidx, str(labels[vidx]) + ), + file=f, + ) + print(" ", file=f) + + print("", file=f) + print(file=f) + print("", file=f) if our_file: f.close() if tk_window: tk_window.destroy() - @classmethod def _identify_format(klass, filename): """_identify_format(filename) @@ -2537,10 +2719,11 @@ def _identify_format(klass, filename): @return: the format of the file as a string. """ import os.path + if hasattr(filename, "name") and hasattr(filename, "read"): # It is most likely a file try: - filename=filename.name + filename = filename.name except: return None @@ -2555,9 +2738,25 @@ def _identify_format(klass, filename): elif ext2 == ".graphml": return "graphmlz" - if ext in [".graphml", ".graphmlz", ".lgl", ".ncol", ".pajek", - ".gml", ".dimacs", ".edgelist", ".edges", ".edge", ".net", - ".pickle", ".picklez", ".dot", ".gw", ".lgr", ".dl"]: + if ext in [ + ".graphml", + ".graphmlz", + ".lgl", + ".ncol", + ".pajek", + ".gml", + ".dimacs", + ".edgelist", + ".edges", + ".edge", + ".net", + ".pickle", + ".picklez", + ".dot", + ".gw", + ".lgr", + ".dl", + ]: return ext[1:] if ext == ".txt" or ext == ".dat": @@ -2623,8 +2822,8 @@ def Read(klass, f, format=None, *args, **kwds): raise IOError("no reader method for file format: %s" % str(format)) reader = getattr(klass, reader) return reader(f, *args, **kwds) - Load = Read + Load = Read def write(self, f, format=None, *args, **kwds): """Unified writing function for graphs. @@ -2680,15 +2879,22 @@ def write(self, f, format=None, *args, **kwds): raise IOError("no writer method for file format: %s" % str(format)) writer = getattr(self, writer) return writer(f, *args, **kwds) + save = write ##################################################### # Constructor for dict-like representation of graphs @classmethod - def DictList(klass, vertices, edges, directed=False, \ - vertex_name_attr="name", edge_foreign_keys=("source", "target"), \ - iterative=False): + def DictList( + klass, + vertices, + edges, + directed=False, + vertex_name_attr="name", + edge_foreign_keys=("source", "target"), + iterative=False, + ): """Constructs a graph from a list-of-dictionaries representation. This representation assumes that vertices and edges are encoded in @@ -2721,6 +2927,7 @@ def DictList(klass, vertices, edges, directed=False, \ add the edges in a batch from an edge list. @return: the graph that was constructed """ + def create_list_from_indices(l, n): result = [None] * n for i, v in l: @@ -2731,13 +2938,13 @@ def create_list_from_indices(l, n): vertex_attrs, n = {}, 0 if vertices: for idx, vertex_data in enumerate(vertices): - for k, v in vertex_data.iteritems(): + for k, v in vertex_data.items(): try: vertex_attrs[k].append((idx, v)) except KeyError: vertex_attrs[k] = [(idx, v)] n += 1 - for k, v in vertex_attrs.iteritems(): + for k, v in vertex_attrs.items(): vertex_attrs[k] = create_list_from_indices(v, n) else: vertex_attrs[vertex_name_attr] = [] @@ -2747,7 +2954,7 @@ def create_list_from_indices(l, n): if len(vertex_names) != len(set(vertex_names)): raise ValueError("vertex names are not unique") # Create a reverse mapping from vertex names to indices - vertex_name_map = UniqueIdGenerator(initial = vertex_names) + vertex_name_map = UniqueIdGenerator(initial=vertex_names) # Construct the edges efk_src, efk_dest = edge_foreign_keys @@ -2766,7 +2973,7 @@ def create_list_from_indices(l, n): g.vs[n][vertex_name_attr] = dst_name n += 1 g.add_edge(v1, v2) - for k, v in edge_data.iteritems(): + for k, v in edge_data.items(): g.es[idx][k] = v return g @@ -2777,13 +2984,13 @@ def create_list_from_indices(l, n): v2 = vertex_name_map[edge_data[efk_dest]] edge_list.append((v1, v2)) - for k, v in edge_data.iteritems(): + for k, v in edge_data.items(): try: edge_attrs[k].append((idx, v)) except KeyError: edge_attrs[k] = [(idx, v)] m += 1 - for k, v in edge_attrs.iteritems(): + for k, v in edge_attrs.items(): edge_attrs[k] = create_list_from_indices(v, m) # It may have happened that some vertices were added during @@ -2791,8 +2998,9 @@ def create_list_from_indices(l, n): if len(vertex_name_map) > n: diff = len(vertex_name_map) - n more = [None] * diff - for k, v in vertex_attrs.iteritems(): v.extend(more) - vertex_attrs[vertex_name_attr] = vertex_name_map.values() + for k, v in vertex_attrs.items(): + v.extend(more) + vertex_attrs[vertex_name_attr] = list(vertex_name_map.values()) n = len(vertex_name_map) # Create the graph @@ -2802,8 +3010,14 @@ def create_list_from_indices(l, n): # Constructor for tuple-like representation of graphs @classmethod - def TupleList(klass, edges, directed=False, \ - vertex_name_attr="name", edge_attrs=None, weights=False): + def TupleList( + klass, + edges, + directed=False, + vertex_name_attr="name", + edge_attrs=None, + weights=False, + ): """Constructs a graph from a list-of-tuples representation. This representation assumes that the edges of the graph are encoded @@ -2851,15 +3065,16 @@ def TupleList(klass, edges, directed=False, \ if not weights: edge_attrs = () else: - if not isinstance(weights, basestring): + if not isinstance(weights, str): weights = "weight" edge_attrs = [weights] else: if weights: - raise ValueError("`weights` must be False if `edge_attrs` is " - "not None") + raise ValueError( + "`weights` must be False if `edge_attrs` is " "not None" + ) - if isinstance(edge_attrs, basestring): + if isinstance(edge_attrs, str): edge_attrs = [edge_attrs] # Set up a vertex ID generator @@ -2881,7 +3096,7 @@ def TupleList(klass, edges, directed=False, \ # Set up the "name" vertex attribute vertex_attributes = {} - vertex_attributes[vertex_name_attr] = idgen.values() + vertex_attributes[vertex_name_attr] = list(idgen.values()) n = len(idgen) # Construct the graph @@ -2889,7 +3104,7 @@ def TupleList(klass, edges, directed=False, \ ################################# # Constructor for graph formulae - Formula=classmethod(construct_graph_from_formula) + Formula = classmethod(construct_graph_from_formula) ########################### # Vertex and edge sequence @@ -3109,45 +3324,50 @@ def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): raise ValueError("the data frame should contain at least two columns") if use_vids: - if str(edges.dtypes[0]).startswith('int') and \ - str(edges.dtypes[1]).startswith('int'): + if str(edges.dtypes[0]).startswith("int") and str( + edges.dtypes[1] + ).startswith("int"): names_edges = None else: - raise TypeError('vertex ids must be 0-based integers') + raise TypeError("vertex ids must be 0-based integers") else: # Handle if some elements are 'NA' if edges.iloc[:, :2].isna().values.any(): warn("In 'edges' NA elements were replaced with string \"NA\"") edges = edges.copy() - edges.iloc[:, :2].fillna('NA', inplace=True) + edges.iloc[:, :2].fillna("NA", inplace=True) names_edges = np.unique(edges.values[:, :2]) if (vertices is not None) and vertices.iloc[:, 0].isna().values.any(): - warn("In the first column of 'vertices' NA elements were replaced "+ - "with string \"NA\"") + warn( + "In the first column of 'vertices' NA elements were replaced " + + 'with string "NA"' + ) vertices = vertices.copy() - vertices.iloc[:, 0].fillna('NA', inplace=True) + vertices.iloc[:, 0].fillna("NA", inplace=True) if vertices is None: names = names_edges else: if vertices.shape[1] < 1: - raise ValueError('vertices has no columns') + raise ValueError("vertices has no columns") names_vertices = vertices.iloc[:, 0] if names_vertices.duplicated().any(): - raise ValueError('Vertex names must be unique') + raise ValueError("Vertex names must be unique") names_vertices = names_vertices.values - if (names_edges is not None) and \ - len(np.setdiff1d(names_edges, names_vertices)): + if (names_edges is not None) and len( + np.setdiff1d(names_edges, names_vertices) + ): raise ValueError( - 'Some vertices in the edge DataFrame are missing from '+ - 'vertices DataFrame') + "Some vertices in the edge DataFrame are missing from " + + "vertices DataFrame" + ) names = names_vertices @@ -3161,7 +3381,7 @@ def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): # vertex names if names is not None: for v, name in zip(g.vs, names): - v['name'] = name + v["name"] = name # vertex attributes if (vertices is not None) and (vertices.shape[1] > 1): @@ -3180,18 +3400,19 @@ def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): e1 = edges.values[:, 1] # add the edges - g.add_edges(zip(e0, e1)) + g.add_edges(list(zip(e0, e1))) # edge attributes if edges.shape[1] > 2: for e, (_, attr) in zip(g.es, edges.iloc[:, 2:].iterrows()): - for a_name, a_value in attr.items(): + for a_name, a_value in list(attr.items()): e[a_name] = a_value return g - def bipartite_projection(self, types="type", multiplicity=True, probe1=-1, - which="both"): + def bipartite_projection( + self, types="type", multiplicity=True, probe1=-1, which="both" + ): """Projects a bipartite graph into two one-mode graphs. Edge directions are ignored while projecting. @@ -3276,8 +3497,7 @@ def bipartite_projection_size(self, types="type", *args, **kwds): first projection, followed by the number of vertices and edges in the second projection. """ - return super(Graph, self).bipartite_projection_size(types, \ - *args, **kwds) + return super(Graph, self).bipartite_projection_size(types, *args, **kwds) def get_incidence(self, types="type", *args, **kwds): """get_incidence(self, types="type") @@ -3355,7 +3575,7 @@ def __iadd__(self, other): @see: L{__add__} """ - if isinstance(other, (int, basestring)): + if isinstance(other, (int, str)): self.add_vertices(other) return self elif isinstance(other, tuple) and len(other) == 2: @@ -3367,12 +3587,11 @@ def __iadd__(self, other): if isinstance(other[0], tuple): self.add_edges(other) return self - if isinstance(other[0], basestring): + if isinstance(other[0], str): self.add_vertices(other) return self return NotImplemented - def __add__(self, other): """Copies the graph and extends the copy depending on the type of the other object given. @@ -3385,18 +3604,18 @@ def __add__(self, other): is extended by multiple edges. If it is a L{Graph}, a disjoint union is performed. """ - if isinstance(other, (int, basestring)): + if isinstance(other, (int, str)): g = self.copy() g.add_vertices(other) elif isinstance(other, tuple) and len(other) == 2: g = self.copy() g.add_edges([other]) elif isinstance(other, list): - if len(other)>0: + if len(other) > 0: if isinstance(other[0], tuple): g = self.copy() g.add_edges(other) - elif isinstance(other[0], basestring): + elif isinstance(other[0], str): g = self.copy() g.add_vertices(other) elif isinstance(other[0], Graph): @@ -3413,7 +3632,6 @@ def __add__(self, other): return g - def __and__(self, other): """Graph intersection operator. @@ -3425,7 +3643,6 @@ def __and__(self, other): else: return NotImplemented - def __isub__(self, other): """In-place subtraction (difference). @@ -3438,7 +3655,7 @@ def __isub__(self, other): if len(other) > 0: if isinstance(other[0], tuple): self.delete_edges(other) - elif isinstance(other[0], (int, long, basestring)): + elif isinstance(other[0], (int, str)): self.delete_vertices(other) else: return NotImplemented @@ -3454,7 +3671,6 @@ def __isub__(self, other): return NotImplemented return self - def __sub__(self, other): """Removes the given object(s) from the graph @@ -3469,7 +3685,7 @@ def __sub__(self, other): return self.difference(other) result = self.copy() - if isinstance(other, (int, long, basestring)): + if isinstance(other, (int, str)): result.delete_vertices([other]) elif isinstance(other, tuple) and len(other) == 2: result.delete_edges([other]) @@ -3477,7 +3693,7 @@ def __sub__(self, other): if len(other) > 0: if isinstance(other[0], tuple): result.delete_edges(other) - elif isinstance(other[0], (int, long, basestring)): + elif isinstance(other[0], (int, str)): result.delete_vertices(other) else: return NotImplemented @@ -3516,9 +3732,8 @@ def __mul__(self, other): return NotImplemented - def __nonzero__(self): - """Returns True if the graph has at least one vertex, False otherwise. - """ + def __bool__(self): + """Returns True if the graph has at least one vertex, False otherwise.""" return self.vcount() > 0 def __or__(self, other): @@ -3532,14 +3747,13 @@ def __or__(self, other): else: return NotImplemented - def __coerce__(self, other): """Coercion rules. This method is needed to allow the graph to react to additions with lists, tuples, integers, strings, vertices, edges and so on. """ - if isinstance(other, (int, tuple, list, basestring)): + if isinstance(other, (int, tuple, list, str)): return self, other if isinstance(other, _igraph.Vertex): return self, other @@ -3571,12 +3785,18 @@ def __reduce__(self): vattrs[attr] = self.vs[attr] for attr in self.es.attribute_names(): eattrs[attr] = self.es[attr] - parameters = (self.vcount(), self.get_edgelist(), \ - self.is_directed(), gattrs, vattrs, eattrs) + parameters = ( + self.vcount(), + self.get_edgelist(), + self.is_directed(), + gattrs, + vattrs, + eattrs, + ) return (constructor, parameters, self.__dict__) - __iter__ = None # needed for PyPy - __hash__ = None # needed for PyPy + __iter__ = None # needed for PyPy + __hash__ = None # needed for PyPy def __plot__(self, context, bbox, palette, *args, **kwds): """Plots the graph to the given Cairo context in the given bounding box @@ -3780,11 +4000,11 @@ def __str__(self): output. """ params = dict( - verbosity=1, - width=78, - print_graph_attributes=False, - print_vertex_attributes=False, - print_edge_attributes=False + verbosity=1, + width=78, + print_graph_attributes=False, + print_vertex_attributes=False, + print_edge_attributes=False, ) return self.summary(**params) @@ -3820,7 +4040,7 @@ def disjoint_union(self, other): other = [other] return disjoint_union([self] + other) - def union(self, other, byname='auto'): + def union(self, other, byname="auto"): """union(self, other, byname="auto") Creates the union of two (or more) graphs. @@ -3834,7 +4054,7 @@ def union(self, other, byname='auto'): other = [other] return union([self] + other, byname=byname) - def intersection(self, other, byname='auto'): + def intersection(self, other, byname="auto"): """intersection(self, other, byname="auto") Creates the intersection of two (or more) graphs. @@ -3850,29 +4070,29 @@ def intersection(self, other, byname='auto'): return intersection([self] + other, byname=byname) _format_mapping = { - "ncol": ("Read_Ncol", "write_ncol"), - "lgl": ("Read_Lgl", "write_lgl"), - "graphdb": ("Read_GraphDB", None), - "graphmlz": ("Read_GraphMLz", "write_graphmlz"), - "graphml": ("Read_GraphML", "write_graphml"), - "gml": ("Read_GML", "write_gml"), - "dot": (None, "write_dot"), - "graphviz": (None, "write_dot"), - "net": ("Read_Pajek", "write_pajek"), - "pajek": ("Read_Pajek", "write_pajek"), - "dimacs": ("Read_DIMACS", "write_dimacs"), - "adjacency": ("Read_Adjacency", "write_adjacency"), - "adj": ("Read_Adjacency", "write_adjacency"), - "edgelist": ("Read_Edgelist", "write_edgelist"), - "edge": ("Read_Edgelist", "write_edgelist"), - "edges": ("Read_Edgelist", "write_edgelist"), - "pickle": ("Read_Pickle", "write_pickle"), - "picklez": ("Read_Picklez", "write_picklez"), - "svg": (None, "write_svg"), - "gw": (None, "write_leda"), - "leda": (None, "write_leda"), - "lgr": (None, "write_leda"), - "dl": ("Read_DL", None) + "ncol": ("Read_Ncol", "write_ncol"), + "lgl": ("Read_Lgl", "write_lgl"), + "graphdb": ("Read_GraphDB", None), + "graphmlz": ("Read_GraphMLz", "write_graphmlz"), + "graphml": ("Read_GraphML", "write_graphml"), + "gml": ("Read_GML", "write_gml"), + "dot": (None, "write_dot"), + "graphviz": (None, "write_dot"), + "net": ("Read_Pajek", "write_pajek"), + "pajek": ("Read_Pajek", "write_pajek"), + "dimacs": ("Read_DIMACS", "write_dimacs"), + "adjacency": ("Read_Adjacency", "write_adjacency"), + "adj": ("Read_Adjacency", "write_adjacency"), + "edgelist": ("Read_Edgelist", "write_edgelist"), + "edge": ("Read_Edgelist", "write_edgelist"), + "edges": ("Read_Edgelist", "write_edgelist"), + "pickle": ("Read_Pickle", "write_pickle"), + "picklez": ("Read_Picklez", "write_picklez"), + "svg": (None, "write_svg"), + "gw": (None, "write_leda"), + "leda": (None, "write_leda"), + "lgr": (None, "write_leda"), + "dl": ("Read_DL", None), } _layout_mapping = { @@ -3912,8 +4132,10 @@ def intersection(self, other, byname='auto'): # After adjusting something here, don't forget to update the docstring # of Graph.layout if necessary! + ############################################################## + class VertexSeq(_igraph.VertexSeq): """Class representing a sequence of vertices in the graph. @@ -4014,7 +4236,7 @@ def find(self, *args, **kwds): else: name = None - if name is not None and isinstance(name, (str, unicode)): + if name is not None and isinstance(name, str): args = [name] if args: @@ -4139,15 +4361,16 @@ def select(self, *args, **kwds): vs = _igraph.VertexSeq.select(self, *args) operators = { - "lt": operator.lt, \ - "gt": operator.gt, \ - "le": operator.le, \ - "ge": operator.ge, \ - "eq": operator.eq, \ - "ne": operator.ne, \ - "in": lambda a, b: a in b, \ - "notin": lambda a, b: a not in b } - for keyword, value in kwds.iteritems(): + "lt": operator.lt, + "gt": operator.gt, + "le": operator.le, + "ge": operator.ge, + "eq": operator.eq, + "ne": operator.ne, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, + } + for keyword, value in kwds.items(): if "_" not in keyword or keyword.rindex("_") == 0: keyword = keyword + "_eq" attr, _, op = keyword.rpartition("_") @@ -4157,12 +4380,12 @@ def select(self, *args, **kwds): # No such operator, assume that it's part of the attribute name attr, op, func = keyword, "eq", operators["eq"] - if attr[0] == '_': + if attr[0] == "_": # Method call, not an attribute values = getattr(vs.graph, attr[1:])(vs) else: values = vs[attr] - filtered_idxs=[i for i, v in enumerate(values) if func(v, value)] + filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] vs = vs.select(filtered_idxs) return vs @@ -4174,8 +4397,10 @@ def __call__(self, *args, **kwds): """ return self.select(*args, **kwds) + ############################################################## + class EdgeSeq(_igraph.EdgeSeq): """Class representing a sequence of edges in the graph. @@ -4433,14 +4658,15 @@ def _ensure_set(value): return value operators = { - "lt": operator.lt, \ - "gt": operator.gt, \ - "le": operator.le, \ - "ge": operator.ge, \ - "eq": operator.eq, \ - "ne": operator.ne, \ - "in": lambda a, b: a in b, \ - "notin": lambda a, b: a not in b } + "lt": operator.lt, + "gt": operator.gt, + "le": operator.le, + "ge": operator.ge, + "eq": operator.eq, + "ne": operator.ne, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, + } # TODO(ntamas): some keyword arguments should be prioritized over # others; for instance, we have optimized code paths for _source and @@ -4448,18 +4674,18 @@ def _ensure_set(value): # these should be executed first. This matters only if there are # multiple keyword arguments and es.is_all() is True. - for keyword, value in kwds.iteritems(): + for keyword, value in kwds.items(): if "_" not in keyword or keyword.rindex("_") == 0: keyword = keyword + "_eq" pos = keyword.rindex("_") - attr, op = keyword[0:pos], keyword[pos+1:] + attr, op = keyword[0:pos], keyword[pos + 1 :] try: func = operators[op] except KeyError: # No such operator, assume that it's part of the attribute name attr, op, func = keyword, "eq", operators["eq"] - if attr[0] == '_': + if attr[0] == "_": if attr in ("_source", "_from", "_target", "_to") and not is_directed: if op not in ("eq", "in"): raise RuntimeError("unsupported for undirected graphs") @@ -4467,7 +4693,7 @@ def _ensure_set(value): # translate to _incident to avoid confusion attr = "_incident" if func == operators["eq"]: - if hasattr(value, "__iter__") and not isinstance(value, (str, unicode)): + if hasattr(value, "__iter__") and not isinstance(value, str): value = set(value) else: value = set([value]) @@ -4497,7 +4723,7 @@ def _ensure_set(value): value = _ensure_set(value) elif attr == "_incident": - func = None # ignoring function, filtering here + func = None # ignoring function, filtering here value = _ensure_set(value) # Fetch all the edges that are incident on at least one of @@ -4508,13 +4734,15 @@ def _ensure_set(value): if not es.is_all(): # Find those that are in the current edge sequence - filtered_idxs = [i for i, e in enumerate(es) if e.index in candidates] + filtered_idxs = [ + i for i, e in enumerate(es) if e.index in candidates + ] else: # We are done, the filtered indexes are in the candidates set filtered_idxs = sorted(candidates) elif attr == "_within": - func = None # ignoring function, filtering here + func = None # ignoring function, filtering here value = _ensure_set(value) # Fetch all the edges that are incident on at least one of @@ -4525,18 +4753,28 @@ def _ensure_set(value): if not es.is_all(): # Find those where both endpoints are OK - filtered_idxs = [i for i, e in enumerate(es) if e.index in candidates - and e.source in value and e.target in value] + filtered_idxs = [ + i + for i, e in enumerate(es) + if e.index in candidates + and e.source in value + and e.target in value + ] else: # Optimized version when the edge sequence contains all the edges # exactly once in increasing order of edge IDs - filtered_idxs = [i for i in candidates - if es[i].source in value and es[i].target in value] + filtered_idxs = [ + i + for i in candidates + if es[i].source in value and es[i].target in value + ] elif attr == "_between": if len(value) != 2: - raise ValueError("_between selector requires two vertex ID lists") - func = None # ignoring function, filtering here + raise ValueError( + "_between selector requires two vertex ID lists" + ) + func = None # ignoring function, filtering here set1 = _ensure_set(value[0]) set2 = _ensure_set(value[1]) @@ -4550,15 +4788,21 @@ def _ensure_set(value): if not es.is_all(): # Find those where both endpoints are OK - filtered_idxs = [i for i, e in enumerate(es) - if (e.source in set1 and e.target in set2) or - (e.target in set1 and e.source in set2)] + filtered_idxs = [ + i + for i, e in enumerate(es) + if (e.source in set1 and e.target in set2) + or (e.target in set1 and e.source in set2) + ] else: # Optimized version when the edge sequence contains all the edges # exactly once in increasing order of edge IDs - filtered_idxs = [i for i in candidates - if (es[i].source in set1 and es[i].target in set2) or - (es[i].target in set1 and es[i].source in set2)] + filtered_idxs = [ + i + for i in candidates + if (es[i].source in set1 and es[i].target in set2) + or (es[i].target in set1 and es[i].source in set2) + ] else: # Method call, not an attribute @@ -4575,7 +4819,6 @@ def _ensure_set(value): return es - def __call__(self, *args, **kwds): """Shorthand notation to select() @@ -4583,9 +4826,11 @@ def __call__(self, *args, **kwds): """ return self.select(*args, **kwds) + ############################################################## # Additional methods of VertexSeq and EdgeSeq that call Graph methods + def _graphmethod(func=None, name=None): """Auxiliary decorator @@ -4604,10 +4849,13 @@ def _graphmethod(func=None, name=None): method = getattr(Graph, name) if hasattr(func, "__call__"): + def decorated(*args, **kwds): self = args[0].graph return func(args[0], method(self, *args, **kwds)) + else: + def decorated(*args, **kwds): self = args[0].graph return method(self, *args, **kwds) @@ -4619,10 +4867,13 @@ def decorated(*args, **kwds): restricted to this sequence, and returns the result. @see: Graph.%(name)s() for details. -""" % { "name": name } +""" % { + "name": name + } return decorated + def _add_proxy_methods(): # Proxy methods for VertexSeq and EdgeSeq that forward their arguments to @@ -4631,38 +4882,63 @@ def _add_proxy_methods(): # the C source whenever you add a proxy method here if that makes sense for # an individual vertex or edge decorated_methods = {} - decorated_methods[VertexSeq] = \ - ["degree", "betweenness", "bibcoupling", "closeness", "cocitation", - "constraint", "diversity", "eccentricity", "get_shortest_paths", "maxdegree", - "pagerank", "personalized_pagerank", "shortest_paths", "similarity_dice", - "similarity_jaccard", "subgraph", "indegree", "outdegree", "isoclass", - "delete_vertices", "is_separator", "is_minimal_separator"] - decorated_methods[EdgeSeq] = \ - ["count_multiple", "delete_edges", "is_loop", "is_multiple", - "is_mutual", "subgraph_edges"] + decorated_methods[VertexSeq] = [ + "degree", + "betweenness", + "bibcoupling", + "closeness", + "cocitation", + "constraint", + "diversity", + "eccentricity", + "get_shortest_paths", + "maxdegree", + "pagerank", + "personalized_pagerank", + "shortest_paths", + "similarity_dice", + "similarity_jaccard", + "subgraph", + "indegree", + "outdegree", + "isoclass", + "delete_vertices", + "is_separator", + "is_minimal_separator", + ] + decorated_methods[EdgeSeq] = [ + "count_multiple", + "delete_edges", + "is_loop", + "is_multiple", + "is_mutual", + "subgraph_edges", + ] rename_methods = {} - rename_methods[VertexSeq] = { - "delete_vertices": "delete" - } - rename_methods[EdgeSeq] = { - "delete_edges": "delete", - "subgraph_edges": "subgraph" - } + rename_methods[VertexSeq] = {"delete_vertices": "delete"} + rename_methods[EdgeSeq] = {"delete_edges": "delete", "subgraph_edges": "subgraph"} - for klass, methods in decorated_methods.iteritems(): + for klass, methods in decorated_methods.items(): for method in methods: new_method_name = rename_methods[klass].get(method, method) setattr(klass, new_method_name, _graphmethod(None, method)) - setattr(EdgeSeq, "edge_betweenness", _graphmethod( \ - lambda self, result: [result[i] for i in self.indices], "edge_betweenness")) + setattr( + EdgeSeq, + "edge_betweenness", + _graphmethod( + lambda self, result: [result[i] for i in self.indices], "edge_betweenness" + ), + ) + _add_proxy_methods() ############################################################## # Making sure that layout methods always return a Layout + def _layout_method_wrapper(func): """Wraps an existing layout method to ensure that it returns a Layout instead of a list of lists. @@ -4670,15 +4946,18 @@ def _layout_method_wrapper(func): @param func: the method to wrap. Must be a method of the Graph object. @return: a new method """ + def result(*args, **kwds): layout = func(*args, **kwds) if not isinstance(layout, Layout): layout = Layout(layout) return layout + result.__name__ = func.__name__ - result.__doc__ = func.__doc__ + result.__doc__ = func.__doc__ return result + for name in dir(Graph): if not name.startswith("layout_"): continue @@ -4689,6 +4968,7 @@ def result(*args, **kwds): ############################################################## # Adding aliases for the 3D versions of the layout methods + def _3d_version_for(func): """Creates an alias for the 3D version of the given layout algoritm. @@ -4698,22 +4978,30 @@ def _3d_version_for(func): @param func: must be a method of the Graph object. @return: a new method """ + def result(*args, **kwds): kwds["dim"] = 3 return func(*args, **kwds) + result.__name__ = "%s_3d" % func.__name__ - result.__doc__ = """Alias for L{%s()} with dim=3.\n\n@see: Graph.%s()""" \ - % (func.__name__, func.__name__) + result.__doc__ = """Alias for L{%s()} with dim=3.\n\n@see: Graph.%s()""" % ( + func.__name__, + func.__name__, + ) return result -Graph.layout_fruchterman_reingold_3d=_3d_version_for(Graph.layout_fruchterman_reingold) -Graph.layout_kamada_kawai_3d=_3d_version_for(Graph.layout_kamada_kawai) -Graph.layout_random_3d=_3d_version_for(Graph.layout_random) -Graph.layout_grid_3d=_3d_version_for(Graph.layout_grid) -Graph.layout_sphere=_3d_version_for(Graph.layout_circle) + +Graph.layout_fruchterman_reingold_3d = _3d_version_for( + Graph.layout_fruchterman_reingold +) +Graph.layout_kamada_kawai_3d = _3d_version_for(Graph.layout_kamada_kawai) +Graph.layout_random_3d = _3d_version_for(Graph.layout_random) +Graph.layout_grid_3d = _3d_version_for(Graph.layout_grid) +Graph.layout_sphere = _3d_version_for(Graph.layout_circle) ############################################################## + def autocurve(graph, attribute="curved", default=0): """Calculates curvature values for each of the edges in the graph to make sure that multiple edges are shown properly on a graph plot. @@ -4749,7 +5037,7 @@ def autocurve(graph, attribute="curved", default=0): multiplicities[u, v].append(edge.index) result = [default] * graph.ecount() - for pair, eids in multiplicities.iteritems(): + for pair, eids in multiplicities.items(): # Is it a single edge? if len(eids) < 2: continue @@ -4764,9 +5052,9 @@ def autocurve(graph, attribute="curved", default=0): for idx, eid in enumerate(eids): edge = graph.es[eid] if edge.source > edge.target: - result[eid] = -sign*curve + result[eid] = -sign * curve else: - result[eid] = sign*curve + result[eid] = sign * curve if idx % 2 == 1: curve += dcurve sign *= -1 @@ -4781,14 +5069,18 @@ def get_include(): """Returns the folder that contains the C API headers of the Python interface of igraph.""" import igraph + paths = [ # The following path works if python-igraph is installed already - os.path.join(sys.prefix, "include", - "python{0}.{1}".format(*sys.version_info), - "python-igraph"), + os.path.join( + sys.prefix, + "include", + "python{0}.{1}".format(*sys.version_info), + "python-igraph", + ), # Fallback for cases when python-igraph is not installed but # imported directly from the source tree - os.path.join(os.path.dirname(igraph.__file__), "..", "src") + os.path.join(os.path.dirname(igraph.__file__), "..", "src"), ] for path in paths: if os.path.exists(os.path.join(path, "igraphmodule_api.h")): @@ -4805,7 +5097,10 @@ def read(filename, *args, **kwds): @param filename: the name of the file to be loaded """ return Graph.Read(filename, *args, **kwds) -load=read + + +load = read + def write(graph, filename, *args, **kwds): """Saves a graph to the given file. @@ -4817,7 +5112,10 @@ def write(graph, filename, *args, **kwds): @param filename: the name of the file to be written """ return graph.write(filename, *args, **kwds) -save=write + + +save = write + def summary(obj, stream=None, *args, **kwds): """Prints a summary of object o to a given stream @@ -4837,5 +5135,6 @@ def summary(obj, stream=None, *args, **kwds): stream.write(str(obj)) stream.write("\n") + config = configuration.init() del construct_graph_from_formula diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index c58f014fa..9b9293055 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -19,7 +19,6 @@ Mac OS X users are likely to invoke igraph from the command line. """ -from __future__ import print_function import re import sys @@ -72,40 +71,41 @@ class TerminalController: @author: Edward Loper """ + # Cursor movement: - BOL = '' #: Move the cursor to the beginning of the line - UP = '' #: Move the cursor up one line - DOWN = '' #: Move the cursor down one line - LEFT = '' #: Move the cursor left one char - RIGHT = '' #: Move the cursor right one char + BOL = "" #: Move the cursor to the beginning of the line + UP = "" #: Move the cursor up one line + DOWN = "" #: Move the cursor down one line + LEFT = "" #: Move the cursor left one char + RIGHT = "" #: Move the cursor right one char # Deletion: - CLEAR_SCREEN = '' #: Clear the screen and move to home position - CLEAR_EOL = '' #: Clear to the end of the line. - CLEAR_BOL = '' #: Clear to the beginning of the line. - CLEAR_EOS = '' #: Clear to the end of the screen + CLEAR_SCREEN = "" #: Clear the screen and move to home position + CLEAR_EOL = "" #: Clear to the end of the line. + CLEAR_BOL = "" #: Clear to the beginning of the line. + CLEAR_EOS = "" #: Clear to the end of the screen # Output modes: - BOLD = '' #: Turn on bold mode - BLINK = '' #: Turn on blink mode - DIM = '' #: Turn on half-bright mode - REVERSE = '' #: Turn on reverse-video mode - NORMAL = '' #: Turn off all modes + BOLD = "" #: Turn on bold mode + BLINK = "" #: Turn on blink mode + DIM = "" #: Turn on half-bright mode + REVERSE = "" #: Turn on reverse-video mode + NORMAL = "" #: Turn off all modes # Cursor display: - HIDE_CURSOR = '' #: Make the cursor invisible - SHOW_CURSOR = '' #: Make the cursor visible + HIDE_CURSOR = "" #: Make the cursor invisible + SHOW_CURSOR = "" #: Make the cursor visible # Terminal size: - COLS = None #: Width of the terminal (None for unknown) - LINES = None #: Height of the terminal (None for unknown) + COLS = None #: Width of the terminal (None for unknown) + LINES = None #: Height of the terminal (None for unknown) # Foreground colors: - BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = '' + BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = "" # Background colors: - BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = '' - BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = '' + BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = "" + BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = "" _STRING_CAPABILITIES = """ BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1 @@ -137,35 +137,35 @@ def __init__(self, term_stream=sys.stdout): # terminal has no capabilities. try: curses.setupterm() - except StandardError: + except Exception: return # Look up numeric capabilities. - self.COLS = curses.tigetnum('cols') - self.LINES = curses.tigetnum('lines') + self.COLS = curses.tigetnum("cols") + self.LINES = curses.tigetnum("lines") # Look up string capabilities. for capability in self._STRING_CAPABILITIES: - (attrib, cap_name) = capability.split('=') - setattr(self, attrib, self._tigetstr(cap_name) or '') + (attrib, cap_name) = capability.split("=") + setattr(self, attrib, self._tigetstr(cap_name) or "") # Colors - set_fg = self._tigetstr('setf') + set_fg = self._tigetstr("setf") if set_fg: for i, color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, color, self._tparm(set_fg, i) or '') - set_fg_ansi = self._tigetstr('setaf') + setattr(self, color, self._tparm(set_fg, i) or "") + set_fg_ansi = self._tigetstr("setaf") if set_fg_ansi: for i, color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, color, self._tparm(set_fg_ansi, i) or '') - set_bg = self._tigetstr('setb') + setattr(self, color, self._tparm(set_fg_ansi, i) or "") + set_bg = self._tigetstr("setb") if set_bg: for i, color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, 'BG_'+color, self._tparm(set_bg, i) or '') - set_bg_ansi = self._tigetstr('setab') + setattr(self, "BG_" + color, self._tparm(set_bg, i) or "") + set_bg_ansi = self._tigetstr("setab") if set_bg_ansi: for i, color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, 'BG_'+color, self._tparm(set_bg_ansi, i) or '') + setattr(self, "BG_" + color, self._tparm(set_bg_ansi, i) or "") @staticmethod def _tigetstr(cap_name): @@ -175,14 +175,16 @@ def _tigetstr(cap_name): # For any modern terminal, we should be able to just ignore # these, so strip them out. import curses - cap = curses.tigetstr(cap_name) or b'' + + cap = curses.tigetstr(cap_name) or b"" cap = cap.decode("latin-1") - return re.sub(r'\$<\d+>[/*]?', '', cap) + return re.sub(r"\$<\d+>[/*]?", "", cap) @staticmethod def _tparm(cap_name, param): import curses - cap = curses.tparm(cap_name.encode("latin-1"), param) or b'' + + cap = curses.tparm(cap_name.encode("latin-1"), param) or b"" return cap.decode("latin-1") def render(self, template): @@ -191,12 +193,12 @@ def render(self, template): the corresponding terminal control string (if it's defined) or '' (if it's not). """ - return re.sub('r\$\$|\${\w+}', self._render_sub, template) + return re.sub("r\$\$|\${\w+}", self._render_sub, template) def _render_sub(self, match): """Helper function for L{render}""" s = match.group() - if s == '$$': + if s == "$$": return s else: return getattr(self, s[2:-1]) @@ -212,18 +214,21 @@ class ProgressBar: The progress bar is colored, if the terminal supports color output; and adjusts to the width of the terminal. """ - BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}' - HEADER = '${BOLD}${CYAN}%s${NORMAL}\n' + + BAR = "%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}" + HEADER = "${BOLD}${CYAN}%s${NORMAL}\n" def __init__(self, term): self.term = term if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL): - raise ValueError("Terminal isn't capable enough -- you " - "should use a simpler progress display.") + raise ValueError( + "Terminal isn't capable enough -- you " + "should use a simpler progress display." + ) self.width = self.term.COLS or 75 self.progress_bar = term.render(self.BAR) self.header = self.term.render(self.HEADER % "".center(self.width)) - self.cleared = True #: true if we haven't drawn the bar yet. + self.cleared = True #: true if we haven't drawn the bar yet. self.last_percent = 0 self.last_message = "" @@ -237,7 +242,7 @@ def update(self, percent=None, message=None): C{None}, the previous message will be used. """ if self.cleared: - sys.stdout.write("\n"+self.header) + sys.stdout.write("\n" + self.header) self.cleared = False if message is None: @@ -250,12 +255,16 @@ def update(self, percent=None, message=None): else: self.last_percent = percent - n = int((self.width-10)*(percent/100.0)) + n = int((self.width - 10) * (percent / 100.0)) sys.stdout.write( - self.term.BOL + self.term.UP + self.term.UP + self.term.CLEAR_EOL + - self.term.render(self.HEADER % message.center(self.width)) + - (self.progress_bar % (percent, '='*n, '-'*(self.width-10-n))) + "\n" - ) + self.term.BOL + + self.term.UP + + self.term.UP + + self.term.CLEAR_EOL + + self.term.render(self.HEADER % message.center(self.width)) + + (self.progress_bar % (percent, "=" * n, "-" * (self.width - 10 - n))) + + "\n" + ) def update_message(self, message): """Updates the message of the progress bar. @@ -267,9 +276,14 @@ def update_message(self, message): def clear(self): """Clears the progress bar (i.e. removes it from the screen)""" if not self.cleared: - sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL) + sys.stdout.write( + self.term.BOL + + self.term.CLEAR_EOL + + self.term.UP + + self.term.CLEAR_EOL + + self.term.UP + + self.term.CLEAR_EOL + ) self.cleared = True self.last_percent = 0 self.last_message = "" @@ -336,7 +350,7 @@ def __init__(self): try: sys.ps1 except AttributeError: - sys.ps1 = '>>> ' + sys.ps1 = ">>> " root = idlelib.PyShell.Tk(className="Idle") idlelib.PyShell.fixwordbreaks(root) @@ -421,6 +435,7 @@ def __init__(self): import sys from IPython import __version__ as ipython_version + self.ipython_version = ipython_version try: @@ -434,6 +449,7 @@ def __init__(self): except ImportError: # IPython 0.10 and earlier import IPython.Shell + self._shell = IPython.Shell.start() self._shell.IP.runsource("from igraph import *") sys.argv.append("-nosep") @@ -466,6 +482,7 @@ def __call__(self): """Starts the embedded shell.""" if self._shell is None: from code import InteractiveConsole + self._shell = InteractiveConsole() print("igraph %s running inside " % __version__, end="", file=sys.stderr) self._shell.runsource("from igraph import *") @@ -483,11 +500,16 @@ def main(): else: print("No configuration file, using defaults", file=sys.stderr) - if config.has_key("shells"): + if "shells" in config: parts = [part.strip() for part in config["shells"].split(",")] shell_classes = [] - available_classes = dict([(k, v) for k, v in globals().iteritems() - if isinstance(v, type) and issubclass(v, Shell)]) + available_classes = dict( + [ + (k, v) + for k, v in globals().items() + if isinstance(v, type) and issubclass(v, Shell) + ] + ) for part in parts: klass = available_classes.get(part, None) if klass is None: @@ -497,6 +519,7 @@ def main(): else: shell_classes = [IPythonShell, ClassicPythonShell] import platform + if platform.system() == "Windows": shell_classes.insert(0, IDLEShell) @@ -507,7 +530,7 @@ def main(): try: shell = shell_class() break - except StandardError: + except Exception: # Try the next one if "Classic" in str(shell_class): raise @@ -524,5 +547,6 @@ def main(): print("No suitable Python shell was found.", file=sys.stderr) print("Check configuration variable `general.shells'.", file=sys.stderr) -if __name__ == '__main__': + +if __name__ == "__main__": sys.exit(main()) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 8f519ddb1..43dfee021 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -25,12 +25,10 @@ """ from copy import deepcopy -from itertools import izip from math import pi -from cStringIO import StringIO +from io import StringIO from igraph import community_to_membership -from igraph.compat import property from igraph.configuration import Configuration from igraph.datatypes import UniqueIdGenerator from igraph.drawing.colors import ClusterColoringPalette @@ -38,6 +36,7 @@ from igraph.summary import _get_wrapper_for_width from igraph.utils import str_to_orientation + class Clustering(object): """Class representing a clustering of an arbitrary ordered set. @@ -80,7 +79,7 @@ class Clustering(object): @undocumented: _formatted_cluster_iterator """ - def __init__(self, membership, params = None): + def __init__(self, membership, params=None): """Constructor. @param membership: the membership list -- that is, the cluster @@ -88,8 +87,8 @@ def __init__(self, membership, params = None): @param params: additional parameters to be stored in this object's dictionary.""" self._membership = list(membership) - if len(self._membership)>0: - self._len = max(m for m in self._membership if m is not None)+1 + if len(self._membership) > 0: + self._len = max(m for m in self._membership if m is not None) + 1 else: self._len = 0 @@ -111,7 +110,7 @@ def __iter__(self): This method will return a generator that generates the clusters one by one.""" - clusters = [[] for _ in xrange(self._len)] + clusters = [[] for _ in range(self._len)] for idx, cluster in enumerate(self._membership): clusters[cluster].append(idx) return iter(clusters) @@ -171,7 +170,7 @@ def sizes(self, *args): return counts - def size_histogram(self, bin_width = 1): + def size_histogram(self, bin_width=1): """Returns the histogram of cluster sizes. @param bin_width: the bin width of the histogram @@ -190,19 +189,24 @@ def summary(self, verbosity=0, width=None): @return: the summary of the clustering as a string. """ out = StringIO() - print >>out, "Clustering with %d elements and %d clusters" % \ - (len(self._membership), len(self)) + print( + "Clustering with %d elements and %d clusters" + % ( + len(self._membership), + len(self), + ), + file=out, + ) if verbosity < 1: return out.getvalue().strip() ndigits = len(str(len(self))) - wrapper = _get_wrapper_for_width(width, - subsequent_indent = " " * (ndigits+3)) + wrapper = _get_wrapper_for_width(width, subsequent_indent=" " * (ndigits + 3)) for idx, cluster in enumerate(self._formatted_cluster_iterator()): wrapper.initial_indent = "[%*d] " % (ndigits, idx) - print >>out, "\n".join(wrapper.wrap(cluster)) + print("\n".join(wrapper.wrap(cluster)), file=out) return out.getvalue().strip() @@ -231,8 +235,14 @@ class VertexClustering(Clustering): # Allow None to be passed to __plot__ as the "palette" keyword argument _default_palette = None - def __init__(self, graph, membership = None, modularity = None, \ - params = None, modularity_params = None): + def __init__( + self, + graph, + membership=None, + modularity=None, + params=None, + modularity_params=None, + ): """Creates a clustering object for a given graph. @param graph: the graph that will be associated to the clustering @@ -248,7 +258,7 @@ def __init__(self, graph, membership = None, modularity = None, \ containing a C{weight} key with the appropriate value here. """ if membership is None: - Clustering.__init__(self, [0]*graph.vcount(), params) + Clustering.__init__(self, [0] * graph.vcount(), params) else: if len(membership) != graph.vcount(): raise ValueError("membership list has invalid length") @@ -355,8 +365,9 @@ def crossing(self): """Returns a boolean vector where element M{i} is C{True} iff edge M{i} lies between clusters, C{False} otherwise.""" membership = self.membership - return [membership[v1] != membership[v2] \ - for v1, v2 in self.graph.get_edgelist()] + return [ + membership[v1] != membership[v2] for v1, v2 in self.graph.get_edgelist() + ] @property def modularity(self): @@ -364,6 +375,7 @@ def modularity(self): if self._modularity_dirty: return self._recalculate_modularity_safe() return self._modularity + q = modularity @property @@ -381,8 +393,9 @@ def recalculate_modularity(self): @return: the new modularity score """ - self._modularity = self._graph.modularity(self._membership, - **self._modularity_params) + self._modularity = self._graph.modularity( + self._membership, **self._modularity_params + ) self._modularity_dirty = False return self._modularity @@ -410,7 +423,6 @@ def subgraph(self, idx): """ return self._graph.subgraph(self[idx]) - def subgraphs(self): """Gets all the subgraphs belonging to each of the clusters. @@ -420,7 +432,6 @@ def subgraphs(self): """ return [self._graph.subgraph(cl) for cl in self] - def giant(self): """Returns the largest cluster of the clustered graph. @@ -491,8 +502,9 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "edge_color" not in kwds and "color" not in self.graph.edge_attributes(): # Set up a default edge coloring based on internal vs external edges colors = ["grey20", "grey80"] - kwds["edge_color"] = [colors[is_crossing] - for is_crossing in self.crossing()] + kwds["edge_color"] = [ + colors[is_crossing] for is_crossing in self.crossing() + ] if palette is None: palette = ClusterColoringPalette(len(self)) @@ -502,7 +514,8 @@ def __plot__(self, context, bbox, palette, *args, **kwds): kwds["mark_groups"] = self else: kwds["mark_groups"] = _handle_mark_groups_arg_for_clustering( - kwds["mark_groups"], self) + kwds["mark_groups"], self + ) if "vertex_color" not in kwds: kwds["vertex_color"] = self.membership @@ -523,6 +536,7 @@ def _formatted_cluster_iterator(self): ############################################################################### + class Dendrogram(object): """The hierarchical clustering (dendrogram) of some dataset. @@ -563,7 +577,7 @@ def __init__(self, merges): self._merges = [tuple(pair) for pair in merges] self._nmerges = len(self._merges) if self._nmerges: - self._nitems = max(self._merges[-1])-self._nmerges+2 + self._nitems = max(self._merges[-1]) - self._nmerges + 2 else: self._nitems = 0 self._names = None @@ -577,7 +591,7 @@ def _convert_matrix_to_tuple_repr(merges, n=None): @return: the tuple representation of the clustering """ if n is None: - n = len(merges)+1 + n = len(merges) + 1 tuple_repr = range(n) idxs = range(n) for rowidx, row in enumerate(merges): @@ -587,8 +601,10 @@ def _convert_matrix_to_tuple_repr(merges, n=None): tuple_repr[idxi] = (tuple_repr[idxi], tuple_repr[idxj]) tuple_repr[idxj] = None except IndexError: - raise ValueError("malformed matrix, subgroup referenced "+ - "before being created in step %d" % rowidx) + raise ValueError( + "malformed matrix, subgroup referenced " + + "before being created in step %d" % rowidx + ) idxs.append(j) return [x for x in tuple_repr if x is not None] @@ -602,7 +618,7 @@ def _traverse_inorder(self): result = [] seen_nodes = set() - for node_index in reversed(xrange(self._nitems+self._nmerges)): + for node_index in reversed(range(self._nitems + self._nmerges)): if node_index in seen_nodes: continue @@ -617,7 +633,7 @@ def _traverse_inorder(self): else: # 'last' is a merge node, so let us proceed with the entry # where this merge node was created - stack.extend(self._merges[last-self._nitems]) + stack.extend(self._merges[last - self._nitems]) return result @@ -645,7 +661,7 @@ def format(self, format="newick"): else: nodes = list(self._names) if len(nodes) < n: - nodes.extend("" for _ in xrange(n - len(nodes))) + nodes.extend("" for _ in range(n - len(nodes))) for k, (i, j) in enumerate(self._merges, self._nitems): nodes[k] = "(%s,%s)%s" % (nodes[i], nodes[j], nodes[k]) nodes[i] = nodes[j] = None @@ -668,13 +684,15 @@ def summary(self, verbosity=0, max_leaf_count=40): @return: the summary of the dendrogram as a string. """ out = StringIO() - print >>out, "Dendrogram, %d elements, %d merges" % \ - (self._nitems, self._nmerges) + print("Dendrogram, %d elements, %d merges" % ( + self._nitems, + self._nmerges, + ), file=out) if self._nitems == 0 or verbosity < 1 or self._nitems > max_leaf_count: return out.getvalue().strip() - print >>out + print('', file=out) positions = [None] * self._nitems inorder = self._traverse_inorder() @@ -684,12 +702,12 @@ def summary(self, verbosity=0, max_leaf_count=40): for idx, element in enumerate(inorder): positions[element] = nextp inorder[idx] = str(element) - nextp += max(distance, len(inorder[idx])+1) + nextp += max(distance, len(inorder[idx]) + 1) - width = max(positions)+1 + width = max(positions) + 1 # Print the nodes on the lowest level - print >>out, (" " * (distance-1)).join(inorder) + print((" " * (distance - 1)).join(inorder), file=out) midx = 0 max_community_idx = self._nitems while midx < self._nmerges: @@ -698,8 +716,8 @@ def summary(self, verbosity=0, max_leaf_count=40): if position >= 0: char_array[position] = "|" char_str = "".join(char_array) - for _ in xrange(level_distance-1): - print >>out, char_str # Print the lines + for _ in range(level_distance - 1): + print(char_str, file=out) # Print the lines cidx_incr = 0 while midx < self._nmerges: @@ -713,16 +731,16 @@ def summary(self, verbosity=0, max_leaf_count=40): if pos1 > pos2: pos1, pos2 = pos2, pos1 - positions.append((pos1+pos2) // 2) + positions.append((pos1 + pos2) // 2) dashes = "-" * (pos2 - pos1 - 1) - char_array[pos1:(pos2+1)] = "`%s'" % dashes + char_array[pos1 : (pos2 + 1)] = "`%s'" % dashes cidx_incr += 1 max_community_idx += cidx_incr - print >>out, "".join(char_array) + print("".join(char_array), file=out) return out.getvalue().strip() @@ -732,7 +750,9 @@ def _item_box_size(self, context, horiz, idx): if self._names is None or self._names[idx] is None: x_bearing, _, _, height, x_advance, _ = context.text_extents("") else: - x_bearing, _, _, height, x_advance, _ = context.text_extents(str(self._names[idx])) + x_bearing, _, _, height, x_advance, _ = context.text_extents( + str(self._names[idx]) + ) if horiz: return x_advance - x_bearing, height @@ -753,12 +773,12 @@ def _plot_item(self, context, horiz, idx, x, y): height = self._item_box_size(context, True, idx)[1] if horiz: - context.move_to(x, y+height) + context.move_to(x, y + height) context.show_text(str(self._names[idx])) else: context.save() context.translate(x, y) - context.rotate(-pi/2.) + context.rotate(-pi / 2.0) context.move_to(0, height) context.show_text(str(self._names[idx])) context.restore() @@ -783,10 +803,11 @@ def __plot__(self, context, bbox, palette, *args, **kwds): from igraph.layout import Layout if self._names is None: - self._names = [str(x) for x in xrange(self._nitems)] + self._names = [str(x) for x in range(self._nitems)] - orientation = str_to_orientation(kwds.get("orientation", "lr"), - reversed_vertical=True) + orientation = str_to_orientation( + kwds.get("orientation", "lr"), reversed_vertical=True + ) horiz = orientation in ("lr", "rl") # Get the font height @@ -794,14 +815,15 @@ def __plot__(self, context, bbox, palette, *args, **kwds): # Calculate space needed for individual items at the # bottom of the dendrogram - item_boxes = [self._item_box_size(context, horiz, idx) \ - for idx in xrange(self._nitems)] + item_boxes = [ + self._item_box_size(context, horiz, idx) for idx in range(self._nitems) + ] # Small correction for cases when the right edge of the labels is # aligned with the tips of the dendrogram branches ygap = 2 if orientation == "bt" else 0 xgap = 2 if orientation == "lr" else 0 - item_boxes = [(x+xgap, y+ygap) for x, y in item_boxes] + item_boxes = [(x + xgap, y + ygap) for x, y in item_boxes] # Calculate coordinates layout = Layout([(0, 0)] * self._nitems, dim=2) @@ -814,7 +836,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): for id1, id2 in self._merges: y += 1 - layout.append(((layout[id1][0]+layout[id2][0])/2., y)) + layout.append(((layout[id1][0] + layout[id2][0]) / 2.0, y)) # Mirror or rotate the layout if necessary if orientation == "bt": @@ -827,7 +849,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): for id1, id2 in self._merges: x += 1 - layout.append((x, (layout[id1][1]+layout[id2][1])/2.)) + layout.append((x, (layout[id1][1] + layout[id2][1]) / 2.0)) # Mirror or rotate the layout if necessary if orientation == "rl": @@ -852,29 +874,31 @@ def __plot__(self, context, bbox, palette, *args, **kwds): delta_y = maxh if horiz: - delta_y += font_height / 2. + delta_y += font_height / 2.0 else: - delta_x += font_height / 2. - layout.fit_into((delta_x, delta_y, width - delta_x, height - delta_y), - keep_aspect_ratio=False) + delta_x += font_height / 2.0 + layout.fit_into( + (delta_x, delta_y, width - delta_x, height - delta_y), + keep_aspect_ratio=False, + ) context.save() context.translate(bbox.left, bbox.top) - context.set_source_rgb(0., 0., 0.) + context.set_source_rgb(0.0, 0.0, 0.0) context.set_line_width(1) # Draw items if horiz: sgn = 0 if orientation == "rl" else -1 - for idx in xrange(self._nitems): + for idx in range(self._nitems): x = layout[idx][0] + sgn * item_boxes[idx][0] - y = layout[idx][1] - item_boxes[idx][1]/2. + y = layout[idx][1] - item_boxes[idx][1] / 2.0 self._plot_item(context, horiz, idx, x, y) else: sgn = 1 if orientation == "bt" else 0 - for idx in xrange(self._nitems): - x = layout[idx][0] - item_boxes[idx][0]/2. + for idx in range(self._nitems): + x = layout[idx][0] - item_boxes[idx][0] / 2.0 y = layout[idx][1] + sgn * item_boxes[idx][1] self._plot_item(context, horiz, idx, x, y) @@ -926,15 +950,16 @@ def names(self, items): n = self._nitems + self._nmerges self._names = items[:n] if len(self._names) < n: - self._names.extend("" for _ in xrange(n-len(self._names))) + self._names.extend("" for _ in range(n - len(self._names))) class VertexDendrogram(Dendrogram): """The dendrogram resulting from the hierarchical clustering of the vertex set of a graph.""" - def __init__(self, graph, merges, optimal_count = None, params = None, - modularity_params = None): + def __init__( + self, graph, merges, optimal_count=None, params=None, modularity_params=None + ): """Creates a dendrogram object for a given graph. @param graph: the graph that will be associated to the clustering @@ -974,11 +999,11 @@ def as_clustering(self, n=None): n = self.optimal_count num_elts = self._graph.vcount() idgen = UniqueIdGenerator() - membership = community_to_membership(self._merges, num_elts, \ - num_elts - n) + membership = community_to_membership(self._merges, num_elts, num_elts - n) membership = [idgen[m] for m in membership] - return VertexClustering(self._graph, membership, - modularity_params=self._modularity_params) + return VertexClustering( + self._graph, membership, modularity_params=self._modularity_params + ) @property def optimal_count(self): @@ -994,11 +1019,11 @@ def optimal_count(self): n = self._graph.vcount() max_q, optimal_count = 0, 1 - for step in xrange(min(n-1, len(self._merges))): + for step in range(min(n - 1, len(self._merges))): membs = community_to_membership(self._merges, n, step) q = self._graph.modularity(membs, **self._modularity_params) if q > max_q: - optimal_count = n-step + optimal_count = n - step max_q = q self._optimal_count = optimal_count return optimal_count @@ -1020,16 +1045,19 @@ class VisualVertexBuilder(AttributeCollectorBase): builder = VisualVertexBuilder(self._graph.vs, kwds) self._names = [vertex.label for vertex in builder] - self._names = [name if name is not None else str(idx) - for idx, name in enumerate(self._names)] - result = Dendrogram.__plot__(self, context, bbox, palette, \ - *args, **kwds) + self._names = [ + name if name is not None else str(idx) + for idx, name in enumerate(self._names) + ] + result = Dendrogram.__plot__(self, context, bbox, palette, *args, **kwds) del self._names return result + ############################################################################### + class Cover(object): """Class representing a cover of an arbitrary ordered set. @@ -1107,7 +1135,7 @@ def __init__(self, clusters, n=0): self._clusters = [list(cluster) for cluster in clusters] try: - self._n = max(max(cluster)+1 for cluster in self._clusters if cluster) + self._n = max(max(cluster) + 1 for cluster in self._clusters if cluster) except ValueError: self._n = 0 self._n = max(n, self._n) @@ -1136,7 +1164,7 @@ def membership(self): length I{n}, where element I{i} contains the cluster indices of the I{i}th item. """ - result = [[] for _ in xrange(self._n)] + result = [[] for _ in range(self._n)] for idx, cluster in enumerate(self): for item in cluster: result[item].append(idx) @@ -1164,7 +1192,7 @@ def sizes(self, *args): return [len(self._clusters[idx]) for idx in args] return [len(cluster) for cluster in self] - def size_histogram(self, bin_width = 1): + def size_histogram(self, bin_width=1): """Returns the histogram of cluster sizes. @param bin_width: the bin width of the histogram @@ -1183,18 +1211,17 @@ def summary(self, verbosity=0, width=None): @return: the summary of the cover as a string. """ out = StringIO() - print >>out, "Cover with %d clusters" % len(self) + print("Cover with %d clusters" % len(self), file=out) if verbosity < 1: return out.getvalue().strip() ndigits = len(str(len(self))) - wrapper = _get_wrapper_for_width(width, - subsequent_indent = " " * (ndigits+3)) + wrapper = _get_wrapper_for_width(width, subsequent_indent=" " * (ndigits + 3)) for idx, cluster in enumerate(self._formatted_cluster_iterator()): wrapper.initial_indent = "[%*d] " % (ndigits, idx) - print >>out, "\n".join(wrapper.wrap(cluster)) + print("\n".join(wrapper.wrap(cluster)), file=out) return out.getvalue().strip() @@ -1219,7 +1246,7 @@ class VertexCover(Cover): @undocumented: _formatted_cluster_iterator """ - def __init__(self, graph, clusters = None): + def __init__(self, graph, clusters=None): """Creates a cover object for a given graph. @param graph: the graph that will be associated to the cover @@ -1229,10 +1256,12 @@ def __init__(self, graph, clusters = None): if clusters is None: clusters = [range(graph.vcount())] - Cover.__init__(self, clusters, n = graph.vcount()) + Cover.__init__(self, clusters, n=graph.vcount()) if self._n > graph.vcount(): - raise ValueError("cluster list contains vertex ID larger than the " - "number of vertices in the graph") + raise ValueError( + "cluster list contains vertex ID larger than the " + "number of vertices in the graph" + ) self._graph = graph @@ -1240,8 +1269,10 @@ def crossing(self): """Returns a boolean vector where element M{i} is C{True} iff edge M{i} lies between clusters, C{False} otherwise.""" membership = [frozenset(cluster) for cluster in self.membership] - return [membership[v1].isdisjoint(membership[v2]) \ - for v1, v2 in self.graph.get_edgelist()] + return [ + membership[v1].isdisjoint(membership[v2]) + for v1, v2 in self.graph.get_edgelist() + ] @property def graph(self): @@ -1318,8 +1349,9 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "edge_color" not in kwds and "color" not in self.graph.edge_attributes(): # Set up a default edge coloring based on internal vs external edges colors = ["grey20", "grey80"] - kwds["edge_color"] = [colors[is_crossing] - for is_crossing in self.crossing()] + kwds["edge_color"] = [ + colors[is_crossing] for is_crossing in self.crossing() + ] if "palette" in kwds: palette = kwds["palette"] @@ -1331,7 +1363,8 @@ def __plot__(self, context, bbox, palette, *args, **kwds): kwds["mark_groups"] = self else: kwds["mark_groups"] = _handle_mark_groups_arg_for_clustering( - kwds["mark_groups"], self) + kwds["mark_groups"], self + ) return self._graph.__plot__(context, bbox, palette, *args, **kwds) @@ -1358,7 +1391,7 @@ class CohesiveBlocks(VertexCover): block structures easier. """ - def __init__(self, graph, blocks = None, cohesion = None, parent = None): + def __init__(self, graph, blocks=None, cohesion=None, parent=None): """Constructs a new cohesive block structure for the given graph. If any of I{blocks}, I{cohesion} or I{parent} is C{None}, all the @@ -1406,15 +1439,17 @@ def hierarchy(self): In other words, the edges point downwards. """ from igraph import Graph - edges = [pair for pair in izip(self._parent, xrange(len(self))) - if pair[0] is not None] + + edges = [ + pair for pair in zip(self._parent, range(len(self))) if pair[0] is not None + ] return Graph(edges, directed=True) def max_cohesion(self, idx): """Finds the maximum cohesion score among all the groups that contain the given vertex.""" result = 0 - for cohesion, cluster in izip(self._cohesion, self._clusters): + for cohesion, cluster in zip(self._cohesion, self._clusters): if idx in cluster: result = max(result, cohesion) return result @@ -1423,7 +1458,7 @@ def max_cohesions(self): """For each vertex in the graph, returns the maximum cohesion score among all the groups that contain the vertex.""" result = [0] * self._graph.vcount() - for cohesion, cluster in izip(self._cohesion, self._clusters): + for cohesion, cluster in zip(self._cohesion, self._clusters): for idx in cluster: result[idx] = max(result[idx], cohesion) return result @@ -1458,8 +1493,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): prepare_groups = True if prepare_groups: - colors = [pair for pair in enumerate(self.cohesions()) - if pair[1] > 1] + colors = [pair for pair in enumerate(self.cohesions()) if pair[1] > 1] kwds["mark_groups"] = colors if "vertex_color" not in kwds: @@ -1467,6 +1501,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): return VertexCover.__plot__(self, context, bbox, palette, *args, **kwds) + def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): """Handles the mark_groups=... keyword argument in plotting methods of clusterings. @@ -1496,8 +1531,7 @@ def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): if isinstance(first, (int, long)): # Yes. Seems like we have a list of cluster indices. # Assign color indices automatically. - group_iter = ((group, color) - for color, group in enumerate(mark_groups)) + group_iter = ((group, color) for color, group in enumerate(mark_groups)) else: # No. Seems like we have good ol' group-color pairs. group_iter = mark_groups @@ -1517,8 +1551,10 @@ def cluster_index_resolver(): return cluster_index_resolver() + ############################################################## + def _prepare_community_comparison(comm1, comm2, remove_none=False): """Auxiliary method that takes two community structures either as membership lists or instances of L{Clustering}, and returns a @@ -1536,6 +1572,7 @@ def _prepare_community_comparison(comm1, comm2, remove_none=False): C{None} values are filtered away and only the remaining lists are compared. """ + def _ensure_list(obj): if isinstance(obj, Clustering): return obj.membership @@ -1546,8 +1583,9 @@ def _ensure_list(obj): raise ValueError("the two membership vectors must be equal in length") if remove_none and (None in vec1 or None in vec2): - idxs_to_remove = [i for i in xrange(len(vec1)) \ - if vec1[i] is None or vec2[i] is None] + idxs_to_remove = [ + i for i in range(len(vec1)) if vec1[i] is None or vec2[i] is None + ] idxs_to_remove.reverse() n = len(vec1) for i in idxs_to_remove: @@ -1601,6 +1639,7 @@ def compare_communities(comm1, comm2, method="vi", remove_none=False): Classification 2:193-218, 1985. """ import igraph._igraph + vec1, vec2 = _prepare_community_comparison(comm1, comm2, remove_none) return igraph._igraph._compare_communities(vec1, vec2, method) @@ -1656,5 +1695,6 @@ def split_join_distance(comm1, comm2, remove_none=False): sum of them. """ import igraph._igraph + vec1, vec2 = _prepare_community_comparison(comm1, comm2, remove_none) return igraph._igraph._split_join_distance(vec1, vec2) diff --git a/src/igraph/compat.py b/src/igraph/compat.py deleted file mode 100644 index 5c9bbc71a..000000000 --- a/src/igraph/compat.py +++ /dev/null @@ -1,75 +0,0 @@ -# vim:ts=4:sw=4:sts=4:et -# -*- coding: utf-8 -*- -""" -Compatibility methods and backported versions of newer Python features -to enable igraph to run on Python 2.5. -""" - -import sys - -__license__ = u"""\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - -############################################################################# -# Simulating math.isnan - -try: - from math import isnan -except ImportError: - def isnan(num): - return num != num - -############################################################################# -# Providing @property.setter syntax for Python 2.5 - -if sys.version_info < (2, 6): - _property = property - - class property(property): - def __init__(self, fget, *args, **kwds): - self.__doc__ = fget.__doc__ - super(property, self).__init__(fget, *args, **kwds) - - def setter(self, fset): - cls_ns = sys._getframe(1).f_locals - for k, v in cls_ns.iteritems(): - if v == self: - propname = k - break - cls_ns[propname] = property(self.fget, fset, self.fdel, self.__doc__) - return cls_ns[propname] -else: - if isinstance(__builtins__, dict): - # This branch is for CPython - property = __builtins__["property"] - else: - # This branch is for PyPy - property = __builtins__.property - -############################################################################# -# Providing BytesIO for Python 2.5 - -try: - from io import BytesIO -except ImportError: - # We are on Python 2.5 or earlier because Python 2.6 has a BytesIO - # class already - from cStringIO import StringIO - BytesIO = StringIO diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 4a50ce4ea..2a6921f21 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -29,8 +29,9 @@ """ import sys + if sys.version_info < (3, 2): - from ConfigParser import SafeConfigParser as ConfigParser + from configparser import SafeConfigParser as ConfigParser else: from configparser import ConfigParser @@ -46,9 +47,21 @@ def get_platform_image_viewer(): return "open" elif plat == "Linux": # Linux has a whole lot of choices, try to find one - choices = ["eog", "gthumb", "gqview", "kuickshow", "xnview", "display", - "gpicview", "gwenview", "qiv", "gimv", "ristretto", - "geeqie", "eom"] + choices = [ + "eog", + "gthumb", + "gqview", + "kuickshow", + "xnview", + "display", + "gpicview", + "gwenview", + "qiv", + "gimv", + "ristretto", + "geeqie", + "eom", + ] paths = ["/usr/bin", "/bin"] for path in paths: for choice in choices: @@ -58,9 +71,19 @@ def get_platform_image_viewer(): return "" elif plat == "FreeBSD": # FreeBSD also has a whole lot of choices, try to find one - choices = ["eog", "gthumb", "geeqie", "display", - "gpicview", "gwenview", "qiv", "gimv", "ristretto", - "geeqie", "eom"] + choices = [ + "eog", + "gthumb", + "geeqie", + "display", + "gpicview", + "gwenview", + "qiv", + "gimv", + "ristretto", + "geeqie", + "eom", + ] paths = ["%%LOCALBASE%%/bin"] for path in paths: for choice in choices: @@ -68,7 +91,7 @@ def get_platform_image_viewer(): if os.path.isfile(full_path): return full_path return "" - elif plat == "Windows" or plat == "Microsoft": # Thanks to Dale Hunscher + elif plat == "Windows" or plat == "Microsoft": # Thanks to Dale Hunscher # Use the built-in Windows image viewer, if available return "start" else: @@ -232,53 +255,21 @@ def setfloat(obj, section, key, value): obj.set(section, key, str(float(value))) _types = { - "boolean": { - "getter": ConfigParser.getboolean, - "setter": Types.setboolean - }, - "int": { - "getter": ConfigParser.getint, - "setter": Types.setint - }, - "float": { - "getter": ConfigParser.getfloat, - "setter": Types.setfloat - } + "boolean": {"getter": ConfigParser.getboolean, "setter": Types.setboolean}, + "int": {"getter": ConfigParser.getint, "setter": Types.setint}, + "float": {"getter": ConfigParser.getfloat, "setter": Types.setfloat}, } _sections = ("general", "apps", "plotting", "remote", "shell") _definitions = { - "general.shells": { - "default": "IPythonShell,ClassicPythonShell" - }, - "general.verbose": { - "default": True, - "type": "boolean" - }, - - "apps.image_viewer": { - "default": get_platform_image_viewer() - }, - - "plotting.layout": { - "default": "auto" - }, - "plotting.mark_groups": { - "default": False, - "type": "boolean" - }, - "plotting.palette": { - "default": "gray" - }, - "plotting.wrap_labels": { - "default": False, - "type": "boolean" - }, - - "shell.ipython.inlining.Plot": { - "default": True, - "type": "boolean" - } + "general.shells": {"default": "IPythonShell,ClassicPythonShell"}, + "general.verbose": {"default": True, "type": "boolean"}, + "apps.image_viewer": {"default": get_platform_image_viewer()}, + "plotting.layout": {"default": "auto"}, + "plotting.mark_groups": {"default": False, "type": "boolean"}, + "plotting.palette": {"default": "gray"}, + "plotting.wrap_labels": {"default": False, "type": "boolean"}, + "shell.ipython.inlining.Plot": {"default": True, "type": "boolean"}, } # The singleton instance we are using throughout other modules @@ -296,7 +287,7 @@ def __init__(self, filename=None): for sec in self._sections: self._config.add_section(sec) # Create default values - for name, definition in self._definitions.iteritems(): + for name, definition in self._definitions.items(): if "default" in definition: self[name] = definition["default"] @@ -410,7 +401,7 @@ def load(self, stream=None): loaded. """ stream = stream or get_user_config_file() - if isinstance(stream, basestring): + if isinstance(stream, str): stream = open(stream, "r") file_was_open = True self._config.readfp(stream) @@ -464,4 +455,3 @@ def init(): @return: the L{Configuration} object loaded or created.""" return Configuration.instance() - diff --git a/src/igraph/cut.py b/src/igraph/cut.py index 6d0100ab8..0acbaf500 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -24,13 +24,14 @@ 02110-1301 USA """ + class Cut(VertexClustering): """A cut of a given graph. This is a simple class used to represent cuts returned by L{Graph.mincut()}, L{Graph.all_st_cuts()} and other functions that calculate cuts. - + A cut is a special vertex clustering with only two clusters. Besides the usual L{VertexClustering} methods, it also has the following attributes: @@ -66,8 +67,7 @@ class Cut(VertexClustering): """ # pylint: disable-msg=R0913 - def __init__(self, graph, value=None, cut=None, partition=None, - partition2=None): + def __init__(self, graph, value=None, cut=None, partition=None, partition2=None): """Initializes the cut. This should not be called directly, everything is taken care of by @@ -92,14 +92,21 @@ def __init__(self, graph, value=None, cut=None, partition=None, self._cut = cut def __repr__(self): - return "%s(%r, %r, %r, %r)" % \ - (self.__class__.__name__, self._graph, \ - self._value, self._cut, self._partition) + return "%s(%r, %r, %r, %r)" % ( + self.__class__.__name__, + self._graph, + self._value, + self._cut, + self._partition, + ) def __str__(self): - return "Graph cut (%d edges, %d vs %d vertices, value=%.4f)" % \ - (len(self._cut), len(self._partition), - self._graph.vcount() - len(self._partition), self._value) + return "Graph cut (%d edges, %d vs %d vertices, value=%.4f)" % ( + len(self._cut), + len(self._partition), + self._graph.vcount() - len(self._partition), + self._value, + ) # pylint: disable-msg=C0103 @property @@ -131,7 +138,7 @@ class Flow(Cut): - C{graph} - the graph on which this flow is defined - - C{value} - the value (capacity) of the flow + - C{value} - the value (capacity) of the flow - C{flow} - the flow values on each edge. For directed graphs, this is simply a list where element M{i} corresponds to the @@ -174,19 +181,27 @@ def __init__(self, graph, value, flow, cut, partition): self._flow = flow def __repr__(self): - return "%s(%r, %r, %r, %r, %r)" % \ - (self.__class__.__name__, self._graph, \ - self._value, self._flow, self._cut, self._partition) + return "%s(%r, %r, %r, %r, %r)" % ( + self.__class__.__name__, + self._graph, + self._value, + self._flow, + self._cut, + self._partition, + ) def __str__(self): - return "Graph flow (%d edges, %d vs %d vertices, value=%.4f)" % \ - (len(self._cut), len(self._partition), - self._graph.vcount() - len(self._partition), self._value) + return "Graph flow (%d edges, %d vs %d vertices, value=%.4f)" % ( + len(self._cut), + len(self._partition), + self._graph.vcount() - len(self._partition), + self._value, + ) @property def flow(self): """Returns the flow values for each edge. - + For directed graphs, this is simply a list where element M{i} corresponds to the flow on edge M{i}. For undirected graphs, the direction of the flow is not constrained (since the edges are @@ -195,6 +210,3 @@ def flow(self): larger vertex ID to the smaller. """ return self._flow - - - diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index b7f3e1387..b2bf6a17d 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -24,6 +24,7 @@ 02110-1301 USA """ + class Matrix(object): """Simple matrix data type. @@ -63,7 +64,7 @@ def Fill(cls, value, *args): height, width = int(args[0]), int(args[0]) else: height, width = int(args[0]), int(args[1]) - mtrx = [[value]*width for _ in xrange(height)] + mtrx = [[value] * width for _ in range(height)] return cls(mtrx) # pylint: disable-msg=C0103 @@ -89,7 +90,7 @@ def Identity(cls, *args): """ # pylint: disable-msg=W0212 result = cls.Fill(0, *args) - for i in xrange(min(result.shape)): + for i in range(min(result.shape)): result._data[i][i] = 1 return result @@ -104,11 +105,12 @@ def _set_data(self, data=None): self._ncol = 0 for row in self._data: if len(row) < self._ncol: - row.extend([0]*(self._ncol-len(row))) + row.extend([0] * (self._ncol - len(row))) def _get_data(self): """Returns the data stored in the matrix as a list of lists""" return [list(row) for row in self._data] + data = property(_get_data, _set_data) @property @@ -127,20 +129,23 @@ def __add__(self, other): if isinstance(other, Matrix): if self.shape != other.shape: raise ValueError("matrix shapes do not match") - return self.__class__([ - [a+b for a, b in izip(row_a, row_b)] - for row_a, row_b in izip(self, other) - ]) + return self.__class__( + [ + [a + b for a, b in zip(row_a, row_b)] + for row_a, row_b in zip(self, other) + ] + ) else: - return self.__class__([ - [item+other for item in row] for row in self]) + return self.__class__([[item + other for item in row] for row in self]) def __eq__(self, other): """Checks whether a given matrix is equal to another one""" - return isinstance(other, Matrix) and \ - self._nrow == other._nrow and \ - self._ncol == other._ncol and \ - self._data == other._data + return ( + isinstance(other, Matrix) + and self._nrow == other._nrow + and self._ncol == other._ncol + and self._data == other._data + ) def __getitem__(self, i): """Returns a single item, a row or a column of the matrix @@ -181,12 +186,12 @@ def __iadd__(self, other): if isinstance(other, Matrix): if self.shape != other.shape: raise ValueError("matrix shapes do not match") - for row_a, row_b in izip(self._data, other): - for i in xrange(len(row_a)): + for row_a, row_b in zip(self._data, other): + for i in range(len(row_a)): row_a[i] += row_b[i] else: for row in self._data: - for i in xrange(len(row)): + for i in range(len(row)): row[i] += other return self @@ -195,12 +200,12 @@ def __isub__(self, other): if isinstance(other, Matrix): if self.shape != other.shape: raise ValueError("matrix shapes do not match") - for row_a, row_b in izip(self._data, other): - for i in xrange(len(row_a)): + for row_a, row_b in zip(self._data, other): + for i in range(len(row_a)): row_a[i] -= row_b[i] else: for row in self._data: - for i in xrange(len(row)): + for i in range(len(row)): row[i] -= other return self @@ -227,8 +232,7 @@ def __setitem__(self, i, value): if len(value) != len(self._data[i]): raise ValueError("new value must have %d items" % self._ncol) if any(len(row) != self._ncol for row in value): - raise ValueError("rows of new value must have %d items" % \ - self._ncol) + raise ValueError("rows of new value must have %d items" % self._ncol) self._data[i] = [list(row) for row in value] elif isinstance(i, tuple): try: @@ -263,13 +267,14 @@ def __sub__(self, other): if isinstance(other, Matrix): if self.shape != other.shape: raise ValueError("matrix shapes do not match") - return self.__class__([ - [a-b for a, b in izip(row_a, row_b)] - for row_a, row_b in izip(self, other) - ]) + return self.__class__( + [ + [a - b for a, b in zip(row_a, row_b)] + for row_a, row_b in zip(self, other) + ] + ) else: - return self.__class__([ - [item-other for item in row] for row in self]) + return self.__class__([[item - other for item in row] for row in self]) def __repr__(self): class_name = self.__class__.__name__ @@ -343,8 +348,8 @@ def __plot__(self, context, bbox, palette, **kwds): """ # pylint: disable-msg=W0142 # pylint: disable-msg=C0103 - grid_width = float(kwds.get("grid_width", 1.)) - border_width = float(kwds.get("border_width", 1.)) + grid_width = float(kwds.get("grid_width", 1.0)) + border_width = float(kwds.get("border_width", 1.0)) style = kwds.get("style", "boolean") row_names = kwds.get("row_names") col_names = kwds.get("col_names", row_names) @@ -361,11 +366,11 @@ def __plot__(self, context, bbox, palette, **kwds): if row_names is not None: row_names = [str(name) for name in islice(row_names, self._nrow)] if len(row_names) < self._nrow: - row_names.extend([""]*(self._nrow-len(row_names))) + row_names.extend([""] * (self._nrow - len(row_names))) if col_names is not None: col_names = [str(name) for name in islice(col_names, self._ncol)] if len(col_names) < self._ncol: - col_names.extend([""]*(self._ncol-len(col_names))) + col_names.extend([""] * (self._ncol - len(col_names))) if values == False: values = None if values == True: @@ -381,19 +386,19 @@ def __plot__(self, context, bbox, palette, **kwds): if row_names is not None or col_names is not None: te = context.text_extents space_width = te(" ")[4] - max_row_name_width = max([te(s)[4] for s in row_names])+space_width - max_col_name_width = max([te(s)[4] for s in col_names])+space_width + max_row_name_width = max([te(s)[4] for s in row_names]) + space_width + max_col_name_width = max([te(s)[4] for s in col_names]) + space_width else: max_row_name_width, max_col_name_width = 0, 0 # Calculate sizes - total_width = float(bbox.width)-max_row_name_width - total_height = float(bbox.height)-max_col_name_width + total_width = float(bbox.width) - max_row_name_width + total_height = float(bbox.height) - max_col_name_width dx = total_width / self.shape[1] dy = total_height / self.shape[0] if kwds.get("square", True): dx, dy = min(dx, dy), min(dx, dy) - total_width, total_height = dx*self.shape[1], dy*self.shape[0] + total_width, total_height = dx * self.shape[1], dy * self.shape[0] ox = bbox.left + (bbox.width - total_width - max_row_name_width) / 2.0 oy = bbox.top + (bbox.height - total_height - max_col_name_width) / 2.0 ox += max_row_name_width @@ -403,11 +408,11 @@ def __plot__(self, context, bbox, palette, **kwds): if style == "palette": mi, ma = self.min(), self.max() color_offset = mi - color_ratio = (len(palette)-1) / float(ma-mi) + color_ratio = (len(palette) - 1) / float(ma - mi) # Validate grid width - if dx < 3*grid_width or dy < 3*grid_width: - grid_width = 0. + if dx < 3 * grid_width or dy < 3 * grid_width: + grid_width = 0.0 if grid_width > 0: context.set_line_width(grid_width) else: @@ -418,12 +423,12 @@ def __plot__(self, context, bbox, palette, **kwds): context.set_line_width(1) # Draw row names (if any) - context.set_source_rgb(0., 0., 0.) + context.set_source_rgb(0.0, 0.0, 0.0) if row_names is not None: - x, y = ox, oy + x, y = ox, oy for heading in row_names: _, _, _, h, xa, _ = context.text_extents(heading) - context.move_to(x-xa-space_width, y + (dy+h)/2.) + context.move_to(x - xa - space_width, y + (dy + h) / 2.0) context.show_text(heading) y += dy @@ -431,11 +436,11 @@ def __plot__(self, context, bbox, palette, **kwds): if col_names is not None: context.save() context.translate(ox, oy) - context.rotate(-1.5707963285) # pi/2 - x, y = 0., 0. + context.rotate(-1.5707963285) # pi/2 + x, y = 0.0, 0.0 for heading in col_names: _, _, _, h, _, _ = context.text_extents(heading) - context.move_to(x+space_width, y + (dx+h)/2.) + context.move_to(x + space_width, y + (dx + h) / 2.0) context.show_text(heading) y += dx context.restore() @@ -453,11 +458,11 @@ def __plot__(self, context, bbox, palette, **kwds): continue if style == "boolean": if item: - context.set_source_rgb(0., 0., 0.) + context.set_source_rgb(0.0, 0.0, 0.0) else: - context.set_source_rgb(1., 1., 1.) + context.set_source_rgb(1.0, 1.0, 1.0) elif style == "palette": - cidx = int((item-color_offset)*color_ratio) + cidx = int((item - color_offset) * color_ratio) if cidx < 0: cidx = 0 context.set_source_rgba(*palette.get(cidx)) @@ -470,12 +475,12 @@ def __plot__(self, context, bbox, palette, **kwds): fill() context.stroke() x += dx - x, y = ox, y+dy + x, y = ox, y + dy # Draw cell values if values is not None: x, y = ox, oy - context.set_source_rgb(0., 0., 0.) + context.set_source_rgb(0.0, 0.0, 0.0) for row in values.data: if hasattr(value_format, "__call__"): values = [value_format(item) for item in row] @@ -483,19 +488,18 @@ def __plot__(self, context, bbox, palette, **kwds): values = [value_format % item for item in row] for item in values: th, tw = context.text_extents(item)[3:5] - context.move_to(x+(dx-tw)/2., y+(dy+th)/2.) + context.move_to(x + (dx - tw) / 2.0, y + (dy + th) / 2.0) context.show_text(item) x += dx - x, y = ox, y+dy + x, y = ox, y + dy # Draw borders if border_width > 0: context.set_line_width(border_width) - context.set_source_rgb(0., 0., 0.) - context.rectangle(ox, oy, dx*self.shape[1], dy*self.shape[0]) + context.set_source_rgb(0.0, 0.0, 0.0) + context.rectangle(ox, oy, dx * self.shape[1], dy * self.shape[0]) context.stroke() - def min(self, dim=None): """Returns the minimum of the matrix along the given dimension @@ -506,8 +510,7 @@ def min(self, dim=None): if dim == 1: return [min(row) for row in self._data] if dim == 0: - return [min(row[idx] for row in self._data) \ - for idx in xrange(self._ncol)] + return [min(row[idx] for row in self._data) for idx in range(self._ncol)] return min(min(row) for row in self._data) def max(self, dim=None): @@ -520,8 +523,7 @@ def max(self, dim=None): if dim == 1: return [max(row) for row in self._data] if dim == 0: - return [max(row[idx] for row in self._data) \ - for idx in xrange(self._ncol)] + return [max(row[idx] for row in self._data) for idx in range(self._ncol)] return max(max(row) for row in self._data) @@ -548,8 +550,18 @@ class DyadCensus(tuple): @undocumented: _remap """ - _remap = {"mutual": 0, "mut": 0, "sym": 0, "symm": 0, - "asy": 1, "asym": 1, "asymm": 1, "asymmetric": 1, "null": 2} + + _remap = { + "mutual": 0, + "mut": 0, + "sym": 0, + "symm": 0, + "asy": 1, + "asym": 1, + "asymm": 1, + "asymmetric": 1, + "null": 2, + } def __getitem__(self, idx): return tuple.__getitem__(self, self._remap.get(idx, idx)) @@ -608,18 +620,33 @@ class TriadCensus(tuple): >>> print tc["030C"] #doctest:+SKIP 1206 """ - _remap = {"003": 0, "012": 1, "102": 2, "021D": 3, "021U": 4, "021C": 5, \ - "111D": 6, "111U": 7, "030T": 8, "030C": 9, "201": 10, "120D": 11, \ - "120U": 12, "120C": 13, "210": 14, "300": 15} + + _remap = { + "003": 0, + "012": 1, + "102": 2, + "021D": 3, + "021U": 4, + "021C": 5, + "111D": 6, + "111U": 7, + "030T": 8, + "030C": 9, + "201": 10, + "120D": 11, + "120U": 12, + "120C": 13, + "210": 14, + "300": 15, + } def __getitem__(self, idx): - if isinstance(idx, basestring): + if isinstance(idx, str): idx = idx.upper() return tuple.__getitem__(self, self._remap.get(idx, idx)) def __getattr__(self, attr): - if isinstance(attr, basestring) and attr[0] == 't' \ - and attr[1:].upper() in self._remap: + if isinstance(attr, str) and attr[0] == "t" and attr[1:].upper() in self._remap: return tuple.__getitem__(self, self._remap[attr[1:].upper()]) raise AttributeError("no such attribute: %s" % attr) @@ -637,14 +664,16 @@ def __str__(self): if rowcount * colcount < maxidx: rowcount += 1 - invmap = dict((v, k) for k, v in self._remap.iteritems()) + invmap = dict((v, k) for k, v in self._remap.items()) result, row, idx = [], [], 0 - for _ in xrange(rowcount): - for _ in xrange(colcount): + for _ in range(rowcount): + for _ in range(colcount): if idx >= maxidx: - break - row.append("%-*s: %*d" % (captionwidth, invmap.get(idx, ""), - numwidth, self[idx])) + break + row.append( + "%-*s: %*d" + % (captionwidth, invmap.get(idx, ""), numwidth, self[idx]) + ) idx += 1 result.append(" | ".join(row)) row = [] @@ -657,7 +686,7 @@ class UniqueIdGenerator(object): names (say, vertex names). Usage: - + >>> gen = UniqueIdGenerator() >>> gen["A"] 0 @@ -688,6 +717,7 @@ def __init__(self, id_generator=None, initial=None): id_generator = 0 if isinstance(id_generator, int): import itertools + self._generator = itertools.count(id_generator) else: self._generator = id_generator @@ -706,7 +736,7 @@ def __getitem__(self, item): try: return self._ids[item] except KeyError: - self._ids[item] = self._generator.next() + self._ids[item] = next(self._generator) return self._ids[item] def __setitem__(self, item, value): @@ -720,15 +750,13 @@ def __len__(self): def reverse_dict(self): """Returns the reverse mapping, i.e., the one that maps from generated IDs to their corresponding objects""" - return dict((v, k) for k, v in self._ids.iteritems()) + return dict((v, k) for k, v in self._ids.items()) def values(self): """Returns the values stored so far. If the generator generates items according to the standard sorting order, the values returned will be exactly in the order they were added. This holds for integer IDs for instance (but for many other ID generators as well).""" - return sorted(self._ids.keys(), key = self._ids.__getitem__) + return sorted(list(self._ids.keys()), key=self._ids.__getitem__) add = __getitem__ - - diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 83b38c4e9..9e352fa31 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -15,20 +15,25 @@ replace it with C{cairocffi} as the two are API-compatible. """ -from __future__ import with_statement -from cStringIO import StringIO +from io import StringIO from warnings import warn import os import platform import time -from igraph.compat import property, BytesIO +from io import BytesIO from igraph.configuration import Configuration from igraph.drawing.colors import Palette, palettes from igraph.drawing.graph import DefaultGraphDrawer, MatplotlibGraphDrawer -from igraph.drawing.utils import BoundingBox, Point, Rectangle, find_cairo, find_matplotlib +from igraph.drawing.utils import ( + BoundingBox, + Point, + Rectangle, + find_cairo, + find_matplotlib, +) from igraph.utils import _is_running_in_ipython, named_temporary_file __all__ = ["BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot"] @@ -40,6 +45,7 @@ ##################################################################### + class Plot(object): """Class representing an arbitrary plot @@ -141,8 +147,9 @@ def __init__(self, target=None, bbox=None, palette=None, background=None): if target is None: self._need_tmpfile = True - self._surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \ - int(self.bbox.width), int(self.bbox.height)) + self._surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) + ) elif isinstance(target, cairo.Surface): self._surface = target else: @@ -150,17 +157,21 @@ def __init__(self, target=None, bbox=None, palette=None, background=None): _, ext = os.path.splitext(target) ext = ext.lower() if ext == ".pdf": - self._surface = cairo.PDFSurface(target, self.bbox.width, \ - self.bbox.height) + self._surface = cairo.PDFSurface( + target, self.bbox.width, self.bbox.height + ) elif ext == ".ps" or ext == ".eps": - self._surface = cairo.PSSurface(target, self.bbox.width, \ - self.bbox.height) + self._surface = cairo.PSSurface( + target, self.bbox.width, self.bbox.height + ) elif ext == ".png": - self._surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \ - int(self.bbox.width), int(self.bbox.height)) + self._surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) + ) elif ext == ".svg": - self._surface = cairo.SVGSurface(target, self.bbox.width, \ - self.bbox.height) + self._surface = cairo.SVGSurface( + target, self.bbox.width, self.bbox.height + ) else: raise ValueError("image format not handled by Cairo: %s" % ext) @@ -235,12 +246,12 @@ def remove(self, obj, bbox=None, idx=1): C{False} if the object was not on the plot at all or M{idx} was larger than the count of occurrences """ - for i in xrange(len(self._objects)): + for i in range(len(self._objects)): current_obj, current_bbox = self._objects[i][0:2] if current_obj is obj and (bbox is None or current_bbox == bbox): idx -= 1 if idx == 0: - self._objects[i:(i+1)] = [] + self._objects[i : (i + 1)] = [] self.mark_dirty() return True return False @@ -264,7 +275,7 @@ def redraw(self, context=None): palette = getattr(obj, "_default_palette", self._palette) plotter = getattr(obj, "__plot__", None) if plotter is None: - warn("%s does not support plotting" % (obj, )) + warn("%s does not support plotting" % (obj,)) else: if opacity < 1.0: ctx.push_group() @@ -293,10 +304,11 @@ def save(self, fname=None): self._surface.write_to_png(fname) return None - fname = fname or self._filename + fname = fname or self._filename if fname is None: - raise ValueError("no file name is known for the surface " + \ - "and none given") + raise ValueError( + "no file name is known for the surface " + "and none given" + ) return self._surface.write_to_png(fname) if fname is not None: @@ -305,12 +317,12 @@ def save(self, fname=None): self._ctx.show_page() self._surface.finish() - def show(self): """Saves the plot to a temporary file and shows it.""" if not isinstance(self._surface, cairo.ImageSurface): - sur = cairo.ImageSurface(cairo.FORMAT_ARGB32, - int(self.bbox.width), int(self.bbox.height)) + sur = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) + ) ctx = cairo.Context(sur) self.redraw(ctx) else: @@ -327,8 +339,9 @@ def show(self): # No image viewer was given and none was detected. This # should only happen on unknown platforms. plat = platform.system() - raise NotImplementedError("showing plots is not implemented " + \ - "on this platform: %s" % plat) + raise NotImplementedError( + "showing plots is not implemented " + "on this platform: %s" % plat + ) else: os.system("%s %s" % (imgviewer, tmpfile)) if platform.system() == "Darwin" or self._windows_hacks: @@ -357,11 +370,11 @@ def _repr_svg_(self): # Return the raw SVG representation result = io.getvalue() if hasattr(result, "encode"): - result = result.encode("utf-8") # for Python 2.x + result = result.encode("utf-8") # for Python 2.x else: - result = result.decode("utf-8") # for Python 3.x + result = result.decode("utf-8") # for Python 3.x - return result, {'isolated': True} # put it inside an iframe + return result, {"isolated": True} # put it inside an iframe @property def bounding_box(self): @@ -452,7 +465,7 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @see: Graph.__plot__ """ - if hasattr(plt, 'Axes') and isinstance(target, plt.Axes): + if hasattr(plt, "Axes") and isinstance(target, plt.Axes): result = MatplotlibGraphDrawer(ax=target) result.draw(obj, *args, **kwds) return @@ -496,5 +509,5 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): # Also return the plot itself return result -##################################################################### +##################################################################### diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index d06e76e4a..ab2c98dc7 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -2,12 +2,12 @@ Abstract base classes for the drawing routines. """ -from igraph.compat import property from igraph.drawing.utils import BoundingBox from math import pi ##################################################################### + # pylint: disable-msg=R0903 # R0903: too few public methods class AbstractDrawer(object): @@ -18,14 +18,16 @@ def draw(self, *args, **kwds): """Abstract method, must be implemented in derived classes.""" raise NotImplementedError("abstract class") + ##################################################################### + # pylint: disable-msg=R0903 # R0903: too few public methods class AbstractCairoDrawer(AbstractDrawer): """Abstract class that serves as a base class for anything that draws on a Cairo context within a given bounding box. - + A subclass of L{AbstractCairoDrawer} is guaranteed to have an attribute named C{context} that represents the Cairo context to draw on, and an attribute named C{bbox} for the L{BoundingBox} @@ -78,21 +80,22 @@ def _mark_point(self, x, y, color=0, size=4): @param size: the diameter of the marker. """ if isinstance(color, int): - colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), - (0, 1, 1), (1, 0, 1)] + colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 1)] color = colors[color % len(colors)] if len(color) == 3: - color += (0.5, ) + color += (0.5,) ctx = self.context ctx.save() ctx.set_source_rgba(*color) - ctx.arc(x, y, size / 2.0, 0, 2*pi) + ctx.arc(x, y, size / 2.0, 0, 2 * pi) ctx.fill() ctx.restore() + ##################################################################### + class AbstractXMLRPCDrawer(AbstractDrawer): """Abstract drawer that uses a remote service via XML-RPC to draw something on a remote display. @@ -101,7 +104,7 @@ class AbstractXMLRPCDrawer(AbstractDrawer): def __init__(self, url, service=None): """Constructs an abstract drawer using the XML-RPC service at the given URL. - + @param url: the URL where the XML-RPC calls for the service should be addressed to. @param service: the name of the service at the XML-RPC address. If @@ -109,9 +112,10 @@ def __init__(self, url, service=None): constructed by C{xmlrpclib.ServerProxy}; if not C{None}, the given attribute will be looked up in the server proxy object. """ - import xmlrpclib + import xmlrpc.client + url = self._resolve_hostname(url) - self.server = xmlrpclib.ServerProxy(url) + self.server = xmlrpc.client.ServerProxy(url) if service is None: self.service = self.server else: @@ -123,7 +127,7 @@ def _resolve_hostname(url): and returns a new URL with the resolved IP address. This speeds up things big time on Mac OS X where an IP lookup would be performed for every XML-RPC call otherwise.""" - from urlparse import urlparse, urlunparse + from urllib.parse import urlparse, urlunparse import re url_parts = urlparse(url) @@ -133,12 +137,12 @@ def _resolve_hostname(url): return url from socket import gethostbyname + if ":" in hostname: - hostname = hostname[0:hostname.index(":")] + hostname = hostname[0 : hostname.index(":")] hostname = gethostbyname(hostname) if url_parts.port is not None: hostname = "%s:%d" % (hostname, url_parts.port) url_parts = list(url_parts) url_parts[1] = hostname return urlunparse(url_parts) - diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 14fa328e8..c77487667 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -4,7 +4,7 @@ Color handling functions. """ -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -28,12 +28,27 @@ from igraph.utils import str_to_orientation from math import ceil -__all__ = ["Palette", "GradientPalette", "AdvancedGradientPalette", \ - "RainbowPalette", "PrecalculatedPalette", "ClusterColoringPalette", \ - "color_name_to_rgb", "color_name_to_rgba", \ - "hsv_to_rgb", "hsva_to_rgba", "hsl_to_rgb", "hsla_to_rgba", \ - "rgb_to_hsv", "rgba_to_hsva", "rgb_to_hsl", "rgba_to_hsla", \ - "palettes", "known_colors"] +__all__ = [ + "Palette", + "GradientPalette", + "AdvancedGradientPalette", + "RainbowPalette", + "PrecalculatedPalette", + "ClusterColoringPalette", + "color_name_to_rgb", + "color_name_to_rgba", + "hsv_to_rgb", + "hsva_to_rgba", + "hsl_to_rgb", + "hsla_to_rgba", + "rgb_to_hsv", + "rgba_to_hsva", + "rgb_to_hsl", + "rgba_to_hsla", + "palettes", + "known_colors", +] + class Palette(object): """Base class of color palettes. @@ -48,6 +63,7 @@ class Palette(object): Palettes can also be used as lists or dicts, for the C{__getitem__} method is overridden properly to call L{Palette.get}. """ + def __init__(self, n): self._length = n self._cache = {} @@ -88,7 +104,7 @@ def get(self, v): return self._cache[v] except KeyError: pass - if isinstance(v, (int, long)): + if isinstance(v, int): if v < 0: raise IndexError("color index must be non-negative") if v >= self._length: @@ -115,7 +131,7 @@ class will simply try to interpret it as a single color by @return: the colors as a list of RGBA quadruplets. The result will be a list even if you passed a single color index or color name. """ - if isinstance(colors, (basestring, int, long)): + if isinstance(colors, (str, int)): # Single color name or index return [self.get(colors)] # Multiple colors @@ -162,12 +178,12 @@ def __plot__(self, context, bbox, palette, *args, **kwds): C{rl} = C{right-left}, C{tb} = C{top-bottom}, C{bt} = C{bottom-top}. The default is C{left-right}. """ - border_width = float(kwds.get("border_width", 1.)) - grid_width = float(kwds.get("grid_width", 0.)) + border_width = float(kwds.get("border_width", 1.0)) + grid_width = float(kwds.get("grid_width", 0.0)) orientation = str_to_orientation(kwds.get("orientation", "lr")) # Construct a matrix and plot that - indices = range(len(self)) + indices = list(range(len(self))) if orientation in ("rl", "bt"): indices.reverse() if orientation in ("lr", "rl"): @@ -175,9 +191,15 @@ def __plot__(self, context, bbox, palette, *args, **kwds): else: matrix = Matrix([[i] for i in indices]) - return matrix.__plot__(context, bbox, self, style="palette", - square=False, grid_width=grid_width, - border_width=border_width) + return matrix.__plot__( + context, + bbox, + self, + style="palette", + square=False, + grid_width=grid_width, + border_width=border_width, + ) def __repr__(self): return "<%s with %d colors>" % (self.__class__.__name__, self._length) @@ -215,9 +237,10 @@ def _get(self, v): @param v: numerical index of the color to be retrieved @return: a 4-tuple containing the RGBA values""" - ratio = float(v)/(len(self)-1) - return tuple(self._color1[x]*(1-ratio) + \ - self._color2[x]*ratio for x in range(4)) + ratio = float(v) / (len(self) - 1) + return tuple( + self._color1[x] * (1 - ratio) + self._color2[x] * ratio for x in range(4) + ) class AdvancedGradientPalette(Palette): @@ -243,14 +266,15 @@ def __init__(self, colors, indices=None, n=256): Palette.__init__(self, n) if indices is None: - diff = float(n-1) / (len(colors)-1) - indices = [i * diff for i in xrange(len(colors))] + diff = float(n - 1) / (len(colors) - 1) + indices = [i * diff for i in range(len(colors))] elif not hasattr(indices, "__iter__"): indices = [float(x) for x in indices] - self._indices, self._colors = zip(*sorted(zip(indices, colors))) + self._indices, self._colors = list(zip(*sorted(zip(indices, colors)))) self._colors = [color_name_to_rgba(color) for color in self._colors] - self._dists = [curr-prev for curr, prev in \ - zip(self._indices[1:], self._indices)] + self._dists = [ + curr - prev for curr, prev in zip(self._indices[1:], self._indices) + ] def _get(self, v): """Returns the color corresponding to the given color index. @@ -258,13 +282,18 @@ def _get(self, v): @param v: numerical index of the color to be retrieved @return: a 4-tuple containing the RGBA values""" colors = self._colors - for i in xrange(len(self._indices)-1): - if self._indices[i] <= v and self._indices[i+1] >= v: + for i in range(len(self._indices) - 1): + if self._indices[i] <= v and self._indices[i + 1] >= v: dist = self._dists[i] - ratio = float(v-self._indices[i])/dist - return tuple([colors[i][x]*(1-ratio)+colors[i+1][x]*ratio \ - for x in range(4)]) - return (0., 0., 0., 1.) + ratio = float(v - self._indices[i]) / dist + return tuple( + [ + colors[i][x] * (1 - ratio) + colors[i + 1][x] * ratio + for x in range(4) + ] + ) + return (0.0, 0.0, 0.0, 1.0) + class RainbowPalette(Palette): """A palette that varies the hue of the colors along a scale. @@ -324,8 +353,7 @@ def _get(self, v): @param v: numerical index of the color to be retrieved @return: a 4-tuple containing the RGBA values""" - return hsva_to_rgba(self._start + v * self._dh, - self._s, self._v, self._alpha) + return hsva_to_rgba(self._start + v * self._dh, self._s, self._v, self._alpha) class PrecalculatedPalette(Palette): @@ -338,7 +366,7 @@ def __init__(self, l): L{color_name_to_rgba()} is OK here.""" Palette.__init__(self, len(l)) for idx, color in enumerate(l): - if isinstance(color, basestring): + if isinstance(color, str): color = color_name_to_rgba(color) self._cache[idx] = color @@ -365,8 +393,7 @@ class ClusterColoringPalette(PrecalculatedPalette): """ def __init__(self, n): - base_colors = ["red", "green", "blue", "yellow", \ - "magenta", "cyan", "#808080"] + base_colors = ["red", "green", "blue", "yellow", "magenta", "cyan", "#808080"] base_colors = [color_name_to_rgba(name) for name in base_colors] num_base_colors = len(base_colors) @@ -398,6 +425,7 @@ def clamp(value, min_value, max_value): return min_value return value + def color_name_to_rgb(color, palette=None): """Converts a color given in one of the supported color formats to R-G-B values. @@ -410,6 +438,7 @@ def color_name_to_rgb(color, palette=None): """ return color_name_to_rgba(color, palette)[:3] + def color_name_to_rgba(color, palette=None): """Converts a color given in one of the supported color formats to R-G-B-A values. @@ -462,7 +491,7 @@ def color_name_to_rgba(color, palette=None): Since these colors are primarily used by Cairo routines, the tuples contain floats in the range 0.0-1.0 """ - if not isinstance(color, basestring): + if not isinstance(color, str): if hasattr(color, "__iter__"): components = list(color) else: @@ -472,20 +501,20 @@ def color_name_to_rgba(color, palette=None): except AttributeError: raise ValueError("palette index used when no palette was given") if len(components) < 4: - components += [1.] * (4 - len(components)) + components += [1.0] * (4 - len(components)) else: - if color[0] == '#': + if color[0] == "#": color = color[1:] if len(color) == 3: - components = [int(i, 16) * 17. / 255. for i in color] + components = [int(i, 16) * 17.0 / 255.0 for i in color] components.append(1.0) elif len(color) == 4: - components = [int(i, 16) * 17. / 255. for i in color] + components = [int(i, 16) * 17.0 / 255.0 for i in color] elif len(color) == 6: - components = [int(color[i:i+2], 16) / 255. for i in (0, 2, 4)] + components = [int(color[i : i + 2], 16) / 255.0 for i in (0, 2, 4)] components.append(1.0) elif len(color) == 8: - components = [int(color[i:i+2], 16) / 255. for i in (0, 2, 4, 6)] + components = [int(color[i : i + 2], 16) / 255.0 for i in (0, 2, 4, 6)] elif color.lower() in known_colors: components = known_colors[color.lower()] else: @@ -493,7 +522,7 @@ def color_name_to_rgba(color, palette=None): maximums = (255.0, 255.0, 255.0, 1.0) for mode in ["rgb(", "rgba(", "hsv(", "hsva(", "hsl(", "hsla("]: if color.startswith(mode) and color[-1] == ")": - color = color[len(mode):-1] + color = color[len(mode) : -1] color_mode = mode[:-1] if mode[0] == "h": maximums = (360.0, 100.0, 100.0, 1.0) @@ -504,11 +533,11 @@ def color_name_to_rgba(color, palette=None): components = color.split() for idx, comp in enumerate(components): if comp[-1] == "%": - components[idx] = float(comp[:-1])/100. + components[idx] = float(comp[:-1]) / 100.0 else: - components[idx] = float(comp)/maximums[idx] + components[idx] = float(comp) / maximums[idx] if len(components) < 4: - components += [1.] * (4 - len(components)) + components += [1.0] * (4 - len(components)) if color_mode[:3] == "hsv": components = hsva_to_rgba(*components) elif color_mode[:3] == "hsl": @@ -517,7 +546,8 @@ def color_name_to_rgba(color, palette=None): components = palette.get(int(color)) # At this point, the components are floats - return tuple(clamp(val, 0., 1.) for val in components) + return tuple(clamp(val, 0.0, 1.0) for val in components) + def color_to_html_format(color): """Formats a color given as a 3-tuple or 4-tuple in HTML format. @@ -532,6 +562,7 @@ def color_to_html_format(color): return "#{0:02X}{1:02X}{2:02X}{3:02X}".format(*color) return "#{0:02X}{1:02X}{2:02X}".format(*color) + def darken(color, ratio=0.5): """Creates a darker version of a color given by an RGB triplet. @@ -543,7 +574,8 @@ def darken(color, ratio=0.5): red, green, blue, alpha = color return (red * ratio, green * ratio, blue * ratio, alpha) -def hsla_to_rgba(h, s, l, alpha = 1.0): + +def hsla_to_rgba(h, s, l, alpha=1.0): """Converts a color given by its HSLA coordinates (hue, saturation, lightness, alpha) to RGBA coordinates. @@ -551,25 +583,26 @@ def hsla_to_rgba(h, s, l, alpha = 1.0): """ # This is based on the formulae found at: # http://en.wikipedia.org/wiki/HSL_and_HSV - c = s*(1 - 2*abs(l - 0.5)) - h1 = (h*6) % 6 - x = c*(1 - abs(h1 % 2 - 1)) - m = l - c/2. + c = s * (1 - 2 * abs(l - 0.5)) + h1 = (h * 6) % 6 + x = c * (1 - abs(h1 % 2 - 1)) + m = l - c / 2.0 h1 = int(h1) if h1 < 3: if h1 < 1: - return (c+m, x+m, m, alpha) + return (c + m, x + m, m, alpha) elif h1 < 2: - return (x+m, c+m, m, alpha) + return (x + m, c + m, m, alpha) else: - return (m, c+m, x+m, alpha) + return (m, c + m, x + m, alpha) else: if h1 < 4: - return (m, x+m, c+m, alpha) + return (m, x + m, c + m, alpha) elif h1 < 5: - return (x+m, m, c+m, alpha) + return (x + m, m, c + m, alpha) else: - return (c+m, m, x+m, alpha) + return (c + m, m, x + m, alpha) + def hsl_to_rgb(h, s, l): """Converts a color given by its HSL coordinates (hue, saturation, @@ -579,7 +612,8 @@ def hsl_to_rgb(h, s, l): """ return hsla_to_rgba(h, s, l)[:3] -def hsva_to_rgba(h, s, v, alpha = 1.0): + +def hsva_to_rgba(h, s, v, alpha=1.0): """Converts a color given by its HSVA coordinates (hue, saturation, value, alpha) to RGB coordinates. @@ -587,25 +621,26 @@ def hsva_to_rgba(h, s, v, alpha = 1.0): """ # This is based on the formulae found at: # http://en.wikipedia.org/wiki/HSL_and_HSV - c = v*s - h1 = (h*6) % 6 - x = c*(1 - abs(h1 % 2 - 1)) - m = v-c + c = v * s + h1 = (h * 6) % 6 + x = c * (1 - abs(h1 % 2 - 1)) + m = v - c h1 = int(h1) if h1 < 3: if h1 < 1: - return (c+m, x+m, m, alpha) + return (c + m, x + m, m, alpha) elif h1 < 2: - return (x+m, c+m, m, alpha) + return (x + m, c + m, m, alpha) else: - return (m, c+m, x+m, alpha) + return (m, c + m, x + m, alpha) else: if h1 < 4: - return (m, x+m, c+m, alpha) + return (m, x + m, c + m, alpha) elif h1 < 5: - return (x+m, m, c+m, alpha) + return (x + m, m, c + m, alpha) else: - return (c+m, m, x+m, alpha) + return (c + m, m, x + m, alpha) + def hsv_to_rgb(h, s, v): """Converts a color given by its HSV coordinates (hue, saturation, @@ -615,6 +650,7 @@ def hsv_to_rgb(h, s, v): """ return hsva_to_rgba(h, s, v)[:3] + def rgba_to_hsla(r, g, b, alpha=1.0): """Converts a color given by its RGBA coordinates to HSLA coordinates (hue, saturation, lightness, alpha). @@ -640,11 +676,12 @@ def rgba_to_hsla(r, g, b, alpha=1.0): if g < b: hue += 1 elif rgb_max == g: - hue = 1/3.0 + (b - r) / d + hue = 1 / 3.0 + (b - r) / d else: - hue = 2/3.0 + (r - g) / d + hue = 2 / 3.0 + (r - g) / d return hue, sat, lightness, alpha + def rgba_to_hsva(r, g, b, alpha=1.0): """Converts a color given by its RGBA coordinates to HSVA coordinates (hue, saturation, value, alpha). @@ -671,11 +708,12 @@ def rgba_to_hsva(r, g, b, alpha=1.0): if hue < 0: hue += 1 elif rgb_max == g: - hue = 1/3.0 + (b - r) / 6.0 + hue = 1 / 3.0 + (b - r) / 6.0 else: - hue = 2/3.0 + (r - g) / 6.0 + hue = 2 / 3.0 + (r - g) / 6.0 return hue, sat, value, alpha + def rgb_to_hsl(r, g, b): """Converts a color given by its RGB coordinates to HSL coordinates (hue, saturation, lightness). @@ -684,6 +722,7 @@ def rgb_to_hsl(r, g, b): """ return rgba_to_hsla(r, g, b)[:3] + def rgb_to_hsv(r, g, b): """Converts a color given by its RGB coordinates to HSV coordinates (hue, saturation, value). @@ -692,6 +731,7 @@ def rgb_to_hsv(r, g, b): """ return rgba_to_hsva(r, g, b)[:3] + def lighten(color, ratio=0.5): """Creates a lighter version of a color given by an RGB triplet. @@ -700,2406 +740,1314 @@ def lighten(color, ratio=0.5): of 0.0 will yield the original color. """ red, green, blue, alpha = color - return (red + (1.0 - red) * ratio, green + (1.0 - green) * ratio, - blue + (1.0 - blue) * ratio, alpha) - -known_colors = \ -{ 'alice blue': (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), - 'aliceblue': (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), - 'antique white': ( 0.98039215686274506, - 0.92156862745098034, - 0.84313725490196079, - 1.0), - 'antiquewhite': ( 0.98039215686274506, - 0.92156862745098034, - 0.84313725490196079, - 1.0), - 'antiquewhite1': (1.0, 0.93725490196078431, 0.85882352941176465, 1.0), - 'antiquewhite2': ( 0.93333333333333335, - 0.87450980392156863, - 0.80000000000000004, - 1.0), - 'antiquewhite3': ( 0.80392156862745101, - 0.75294117647058822, - 0.69019607843137254, - 1.0), - 'antiquewhite4': ( 0.54509803921568623, - 0.51372549019607838, - 0.47058823529411764, - 1.0), - 'aqua': (0.0, 1.0, 1.0, 1.0), - 'aquamarine': (0.49803921568627452, 1.0, 0.83137254901960789, 1.0), - 'aquamarine1': (0.49803921568627452, 1.0, 0.83137254901960789, 1.0), - 'aquamarine2': ( 0.46274509803921571, - 0.93333333333333335, - 0.77647058823529413, - 1.0), - 'aquamarine3': ( 0.40000000000000002, - 0.80392156862745101, - 0.66666666666666663, - 1.0), - 'aquamarine4': ( 0.27058823529411763, - 0.54509803921568623, - 0.45490196078431372, - 1.0), - 'azure': (0.94117647058823528, 1.0, 1.0, 1.0), - 'azure1': (0.94117647058823528, 1.0, 1.0, 1.0), - 'azure2': ( 0.8784313725490196, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'azure3': ( 0.75686274509803919, - 0.80392156862745101, - 0.80392156862745101, - 1.0), - 'azure4': ( 0.51372549019607838, - 0.54509803921568623, - 0.54509803921568623, - 1.0), - 'beige': ( 0.96078431372549022, - 0.96078431372549022, - 0.86274509803921573, - 1.0), - 'bisque': (1.0, 0.89411764705882357, 0.7686274509803922, 1.0), - 'bisque1': (1.0, 0.89411764705882357, 0.7686274509803922, 1.0), - 'bisque2': ( 0.93333333333333335, - 0.83529411764705885, - 0.71764705882352942, - 1.0), - 'bisque3': ( 0.80392156862745101, - 0.71764705882352942, - 0.61960784313725492, - 1.0), - 'bisque4': ( 0.54509803921568623, - 0.49019607843137253, - 0.41960784313725491, - 1.0), - 'black': (0.0, 0.0, 0.0, 1.0), - 'blanched almond': (1.0, 0.92156862745098034, 0.80392156862745101, 1.0), - 'blanchedalmond': (1.0, 0.92156862745098034, 0.80392156862745101, 1.0), - 'blue': (0.0, 0.0, 1.0, 1.0), - 'blue violet': ( 0.54117647058823526, - 0.16862745098039217, - 0.88627450980392153, - 1.0), - 'blue1': (0.0, 0.0, 1.0, 1.0), - 'blue2': (0.0, 0.0, 0.93333333333333335, 1.0), - 'blue3': (0.0, 0.0, 0.80392156862745101, 1.0), - 'blue4': (0.0, 0.0, 0.54509803921568623, 1.0), - 'blueviolet': ( 0.54117647058823526, - 0.16862745098039217, - 0.88627450980392153, - 1.0), - 'brown': ( 0.6470588235294118, - 0.16470588235294117, - 0.16470588235294117, - 1.0), - 'brown1': (1.0, 0.25098039215686274, 0.25098039215686274, 1.0), - 'brown2': ( 0.93333333333333335, - 0.23137254901960785, - 0.23137254901960785, - 1.0), - 'brown3': ( 0.80392156862745101, - 0.20000000000000001, - 0.20000000000000001, - 1.0), - 'brown4': ( 0.54509803921568623, - 0.13725490196078433, - 0.13725490196078433, - 1.0), - 'burlywood': ( 0.87058823529411766, - 0.72156862745098038, - 0.52941176470588236, - 1.0), - 'burlywood1': (1.0, 0.82745098039215681, 0.60784313725490191, 1.0), - 'burlywood2': ( 0.93333333333333335, - 0.77254901960784317, - 0.56862745098039214, - 1.0), - 'burlywood3': ( 0.80392156862745101, - 0.66666666666666663, - 0.49019607843137253, - 1.0), - 'burlywood4': ( 0.54509803921568623, - 0.45098039215686275, - 0.33333333333333331, - 1.0), - 'cadet blue': ( 0.37254901960784315, - 0.61960784313725492, - 0.62745098039215685, - 1.0), - 'cadetblue': ( 0.37254901960784315, - 0.61960784313725492, - 0.62745098039215685, - 1.0), - 'cadetblue1': (0.59607843137254901, 0.96078431372549022, 1.0, 1.0), - 'cadetblue2': ( 0.55686274509803924, - 0.89803921568627454, - 0.93333333333333335, - 1.0), - 'cadetblue3': ( 0.47843137254901963, - 0.77254901960784317, - 0.80392156862745101, - 1.0), - 'cadetblue4': ( 0.32549019607843138, - 0.52549019607843139, - 0.54509803921568623, - 1.0), - 'chartreuse': (0.49803921568627452, 1.0, 0.0, 1.0), - 'chartreuse1': (0.49803921568627452, 1.0, 0.0, 1.0), - 'chartreuse2': (0.46274509803921571, 0.93333333333333335, 0.0, 1.0), - 'chartreuse3': (0.40000000000000002, 0.80392156862745101, 0.0, 1.0), - 'chartreuse4': (0.27058823529411763, 0.54509803921568623, 0.0, 1.0), - 'chocolate': ( 0.82352941176470584, - 0.41176470588235292, - 0.11764705882352941, - 1.0), - 'chocolate1': (1.0, 0.49803921568627452, 0.14117647058823529, 1.0), - 'chocolate2': ( 0.93333333333333335, - 0.46274509803921571, - 0.12941176470588237, - 1.0), - 'chocolate3': ( 0.80392156862745101, - 0.40000000000000002, - 0.11372549019607843, - 1.0), - 'chocolate4': ( 0.54509803921568623, - 0.27058823529411763, - 0.074509803921568626, - 1.0), - 'coral': (1.0, 0.49803921568627452, 0.31372549019607843, 1.0), - 'coral1': (1.0, 0.44705882352941179, 0.33725490196078434, 1.0), - 'coral2': ( 0.93333333333333335, - 0.41568627450980394, - 0.31372549019607843, - 1.0), - 'coral3': ( 0.80392156862745101, - 0.35686274509803922, - 0.27058823529411763, - 1.0), - 'coral4': ( 0.54509803921568623, - 0.24313725490196078, - 0.18431372549019609, - 1.0), - 'cornflower blue': ( 0.39215686274509803, - 0.58431372549019611, - 0.92941176470588238, - 1.0), - 'cornflowerblue': ( 0.39215686274509803, - 0.58431372549019611, - 0.92941176470588238, - 1.0), - 'cornsilk': (1.0, 0.97254901960784312, 0.86274509803921573, 1.0), - 'cornsilk1': (1.0, 0.97254901960784312, 0.86274509803921573, 1.0), - 'cornsilk2': ( 0.93333333333333335, - 0.90980392156862744, - 0.80392156862745101, - 1.0), - 'cornsilk3': ( 0.80392156862745101, - 0.78431372549019607, - 0.69411764705882351, - 1.0), - 'cornsilk4': ( 0.54509803921568623, - 0.53333333333333333, - 0.47058823529411764, - 1.0), - 'crimson': ( 0.8627450980392157, - 0.0784313725490196, - 0.23529411764705882, - 1.0), - 'cyan': (0.0, 1.0, 1.0, 1.0), - 'cyan1': (0.0, 1.0, 1.0, 1.0), - 'cyan2': (0.0, 0.93333333333333335, 0.93333333333333335, 1.0), - 'cyan3': (0.0, 0.80392156862745101, 0.80392156862745101, 1.0), - 'cyan4': (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), - 'dark blue': (0.0, 0.0, 0.54509803921568623, 1.0), - 'dark cyan': (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), - 'dark goldenrod': ( 0.72156862745098038, - 0.52549019607843139, - 0.043137254901960784, - 1.0), - 'dark gray': ( 0.66274509803921566, - 0.66274509803921566, - 0.66274509803921566, - 1.0), - 'dark green': (0.0, 0.39215686274509803, 0.0, 1.0), - 'dark grey': ( 0.66274509803921566, - 0.66274509803921566, - 0.66274509803921566, - 1.0), - 'dark khaki': ( 0.74117647058823533, - 0.71764705882352942, - 0.41960784313725491, - 1.0), - 'dark magenta': (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), - 'dark olive green': ( 0.33333333333333331, - 0.41960784313725491, - 0.18431372549019609, - 1.0), - 'dark orange': (1.0, 0.5490196078431373, 0.0, 1.0), - 'dark orchid': ( 0.59999999999999998, - 0.19607843137254902, - 0.80000000000000004, - 1.0), - 'dark red': (0.54509803921568623, 0.0, 0.0, 1.0), - 'dark salmon': ( 0.9137254901960784, - 0.58823529411764708, - 0.47843137254901963, - 1.0), - 'dark sea green': ( 0.5607843137254902, - 0.73725490196078436, - 0.5607843137254902, - 1.0), - 'dark slate blue': ( 0.28235294117647058, - 0.23921568627450981, - 0.54509803921568623, - 1.0), - 'dark slate gray': ( 0.18431372549019609, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'dark slate grey': ( 0.18431372549019609, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'dark turquoise': (0.0, 0.80784313725490198, 0.81960784313725488, 1.0), - 'dark violet': (0.58039215686274515, 0.0, 0.82745098039215681, 1.0), - 'darkblue': (0.0, 0.0, 0.54509803921568623, 1.0), - 'darkcyan': (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), - 'darkgoldenrod': ( 0.72156862745098038, - 0.52549019607843139, - 0.043137254901960784, - 1.0), - 'darkgoldenrod1': (1.0, 0.72549019607843135, 0.058823529411764705, 1.0), - 'darkgoldenrod2': ( 0.93333333333333335, - 0.67843137254901964, - 0.054901960784313725, - 1.0), - 'darkgoldenrod3': ( 0.80392156862745101, - 0.58431372549019611, - 0.047058823529411764, - 1.0), - 'darkgoldenrod4': ( 0.54509803921568623, - 0.396078431372549, - 0.031372549019607843, - 1.0), - 'darkgray': ( 0.66274509803921566, - 0.66274509803921566, - 0.66274509803921566, - 1.0), - 'darkgreen': (0.0, 0.39215686274509803, 0.0, 1.0), - 'darkgrey': ( 0.66274509803921566, - 0.66274509803921566, - 0.66274509803921566, - 1.0), - 'darkkhaki': ( 0.74117647058823533, - 0.71764705882352942, - 0.41960784313725491, - 1.0), - 'darkmagenta': (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), - 'darkolivegreen': ( 0.33333333333333331, - 0.41960784313725491, - 0.18431372549019609, - 1.0), - 'darkolivegreen1': (0.792156862745098, 1.0, 0.4392156862745098, 1.0), - 'darkolivegreen2': ( 0.73725490196078436, - 0.93333333333333335, - 0.40784313725490196, - 1.0), - 'darkolivegreen3': ( 0.63529411764705879, - 0.80392156862745101, - 0.35294117647058826, - 1.0), - 'darkolivegreen4': ( 0.43137254901960786, - 0.54509803921568623, - 0.23921568627450981, - 1.0), - 'darkorange': (1.0, 0.5490196078431373, 0.0, 1.0), - 'darkorange1': (1.0, 0.49803921568627452, 0.0, 1.0), - 'darkorange2': (0.93333333333333335, 0.46274509803921571, 0.0, 1.0), - 'darkorange3': (0.80392156862745101, 0.40000000000000002, 0.0, 1.0), - 'darkorange4': (0.54509803921568623, 0.27058823529411763, 0.0, 1.0), - 'darkorchid': ( 0.59999999999999998, - 0.19607843137254902, - 0.80000000000000004, - 1.0), - 'darkorchid1': (0.74901960784313726, 0.24313725490196078, 1.0, 1.0), - 'darkorchid2': ( 0.69803921568627447, - 0.22745098039215686, - 0.93333333333333335, - 1.0), - 'darkorchid3': ( 0.60392156862745094, - 0.19607843137254902, - 0.80392156862745101, - 1.0), - 'darkorchid4': ( 0.40784313725490196, - 0.13333333333333333, - 0.54509803921568623, - 1.0), - 'darkred': (0.54509803921568623, 0.0, 0.0, 1.0), - 'darksalmon': ( 0.9137254901960784, - 0.58823529411764708, - 0.47843137254901963, - 1.0), - 'darkseagreen': ( 0.5607843137254902, - 0.73725490196078436, - 0.5607843137254902, - 1.0), - 'darkseagreen1': (0.75686274509803919, 1.0, 0.75686274509803919, 1.0), - 'darkseagreen2': ( 0.70588235294117652, - 0.93333333333333335, - 0.70588235294117652, - 1.0), - 'darkseagreen3': ( 0.60784313725490191, - 0.80392156862745101, - 0.60784313725490191, - 1.0), - 'darkseagreen4': ( 0.41176470588235292, - 0.54509803921568623, - 0.41176470588235292, - 1.0), - 'darkslateblue': ( 0.28235294117647058, - 0.23921568627450981, - 0.54509803921568623, - 1.0), - 'darkslategray': ( 0.18431372549019609, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'darkslategray1': (0.59215686274509804, 1.0, 1.0, 1.0), - 'darkslategray2': ( 0.55294117647058827, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'darkslategray3': ( 0.47450980392156861, - 0.80392156862745101, - 0.80392156862745101, - 1.0), - 'darkslategray4': ( 0.32156862745098042, - 0.54509803921568623, - 0.54509803921568623, - 1.0), - 'darkslategrey': ( 0.18431372549019609, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'darkturquoise': (0.0, 0.80784313725490198, 0.81960784313725488, 1.0), - 'darkviolet': (0.58039215686274515, 0.0, 0.82745098039215681, 1.0), - 'deep pink': (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), - 'deep sky blue': (0.0, 0.74901960784313726, 1.0, 1.0), - 'deeppink': (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), - 'deeppink1': (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), - 'deeppink2': ( 0.93333333333333335, - 0.070588235294117646, - 0.53725490196078429, - 1.0), - 'deeppink3': ( 0.80392156862745101, - 0.062745098039215685, - 0.46274509803921571, - 1.0), - 'deeppink4': ( 0.54509803921568623, - 0.039215686274509803, - 0.31372549019607843, - 1.0), - 'deepskyblue': (0.0, 0.74901960784313726, 1.0, 1.0), - 'deepskyblue1': (0.0, 0.74901960784313726, 1.0, 1.0), - 'deepskyblue2': (0.0, 0.69803921568627447, 0.93333333333333335, 1.0), - 'deepskyblue3': (0.0, 0.60392156862745094, 0.80392156862745101, 1.0), - 'deepskyblue4': (0.0, 0.40784313725490196, 0.54509803921568623, 1.0), - 'dim gray': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'dim grey': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'dimgray': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'dimgrey': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'dodger blue': (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), - 'dodgerblue': (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), - 'dodgerblue1': (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), - 'dodgerblue2': ( 0.10980392156862745, - 0.52549019607843139, - 0.93333333333333335, - 1.0), - 'dodgerblue3': ( 0.094117647058823528, - 0.45490196078431372, - 0.80392156862745101, - 1.0), - 'dodgerblue4': ( 0.062745098039215685, - 0.30588235294117649, - 0.54509803921568623, - 1.0), - 'firebrick': ( 0.69803921568627447, - 0.13333333333333333, - 0.13333333333333333, - 1.0), - 'firebrick1': (1.0, 0.18823529411764706, 0.18823529411764706, 1.0), - 'firebrick2': ( 0.93333333333333335, - 0.17254901960784313, - 0.17254901960784313, - 1.0), - 'firebrick3': ( 0.80392156862745101, - 0.14901960784313725, - 0.14901960784313725, - 1.0), - 'firebrick4': ( 0.54509803921568623, - 0.10196078431372549, - 0.10196078431372549, - 1.0), - 'floral white': (1.0, 0.98039215686274506, 0.94117647058823528, 1.0), - 'floralwhite': (1.0, 0.98039215686274506, 0.94117647058823528, 1.0), - 'forest green': ( 0.13333333333333333, - 0.54509803921568623, - 0.13333333333333333, - 1.0), - 'forestgreen': ( 0.13333333333333333, - 0.54509803921568623, - 0.13333333333333333, - 1.0), - 'fuchsia': (1.0, 0.0, 1.0, 1.0), - 'gainsboro': ( 0.86274509803921573, - 0.86274509803921573, - 0.86274509803921573, - 1.0), - 'ghost white': (0.97254901960784312, 0.97254901960784312, 1.0, 1.0), - 'ghostwhite': (0.97254901960784312, 0.97254901960784312, 1.0, 1.0), - 'gold': (1.0, 0.84313725490196079, 0.0, 1.0), - 'gold1': (1.0, 0.84313725490196079, 0.0, 1.0), - 'gold2': (0.93333333333333335, 0.78823529411764703, 0.0, 1.0), - 'gold3': (0.80392156862745101, 0.67843137254901964, 0.0, 1.0), - 'gold4': (0.54509803921568623, 0.45882352941176469, 0.0, 1.0), - 'goldenrod': ( 0.85490196078431369, - 0.6470588235294118, - 0.12549019607843137, - 1.0), - 'goldenrod1': (1.0, 0.75686274509803919, 0.14509803921568629, 1.0), - 'goldenrod2': ( 0.93333333333333335, - 0.70588235294117652, - 0.13333333333333333, - 1.0), - 'goldenrod3': ( 0.80392156862745101, - 0.60784313725490191, - 0.11372549019607843, - 1.0), - 'goldenrod4': ( 0.54509803921568623, - 0.41176470588235292, - 0.078431372549019607, - 1.0), - 'gray': ( 0.74509803921568629, - 0.74509803921568629, - 0.74509803921568629, - 1.0), - 'gray0': (0.0, 0.0, 0.0, 1.0), - 'gray1': ( 0.011764705882352941, - 0.011764705882352941, - 0.011764705882352941, - 1.0), - 'gray10': ( 0.10196078431372549, - 0.10196078431372549, - 0.10196078431372549, - 1.0), - 'gray100': (1.0, 1.0, 1.0, 1.0), - 'gray11': ( 0.10980392156862745, - 0.10980392156862745, - 0.10980392156862745, - 1.0), - 'gray12': ( 0.12156862745098039, - 0.12156862745098039, - 0.12156862745098039, - 1.0), - 'gray13': ( 0.12941176470588237, - 0.12941176470588237, - 0.12941176470588237, - 1.0), - 'gray14': ( 0.14117647058823529, - 0.14117647058823529, - 0.14117647058823529, - 1.0), - 'gray15': ( 0.14901960784313725, - 0.14901960784313725, - 0.14901960784313725, - 1.0), - 'gray16': ( 0.16078431372549021, - 0.16078431372549021, - 0.16078431372549021, - 1.0), - 'gray17': ( 0.16862745098039217, - 0.16862745098039217, - 0.16862745098039217, - 1.0), - 'gray18': ( 0.1803921568627451, - 0.1803921568627451, - 0.1803921568627451, - 1.0), - 'gray19': ( 0.18823529411764706, - 0.18823529411764706, - 0.18823529411764706, - 1.0), - 'gray2': ( 0.019607843137254902, - 0.019607843137254902, - 0.019607843137254902, - 1.0), - 'gray20': ( 0.20000000000000001, - 0.20000000000000001, - 0.20000000000000001, - 1.0), - 'gray21': ( 0.21176470588235294, - 0.21176470588235294, - 0.21176470588235294, - 1.0), - 'gray22': ( 0.2196078431372549, - 0.2196078431372549, - 0.2196078431372549, - 1.0), - 'gray23': ( 0.23137254901960785, - 0.23137254901960785, - 0.23137254901960785, - 1.0), - 'gray24': ( 0.23921568627450981, - 0.23921568627450981, - 0.23921568627450981, - 1.0), - 'gray25': ( 0.25098039215686274, - 0.25098039215686274, - 0.25098039215686274, - 1.0), - 'gray26': ( 0.25882352941176473, - 0.25882352941176473, - 0.25882352941176473, - 1.0), - 'gray27': ( 0.27058823529411763, - 0.27058823529411763, - 0.27058823529411763, - 1.0), - 'gray28': ( 0.27843137254901962, - 0.27843137254901962, - 0.27843137254901962, - 1.0), - 'gray29': ( 0.29019607843137257, - 0.29019607843137257, - 0.29019607843137257, - 1.0), - 'gray3': ( 0.031372549019607843, - 0.031372549019607843, - 0.031372549019607843, - 1.0), - 'gray30': ( 0.30196078431372547, - 0.30196078431372547, - 0.30196078431372547, - 1.0), - 'gray31': ( 0.30980392156862746, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'gray32': ( 0.32156862745098042, - 0.32156862745098042, - 0.32156862745098042, - 1.0), - 'gray33': ( 0.32941176470588235, - 0.32941176470588235, - 0.32941176470588235, - 1.0), - 'gray34': ( 0.3411764705882353, - 0.3411764705882353, - 0.3411764705882353, - 1.0), - 'gray35': ( 0.34901960784313724, - 0.34901960784313724, - 0.34901960784313724, - 1.0), - 'gray36': ( 0.36078431372549019, - 0.36078431372549019, - 0.36078431372549019, - 1.0), - 'gray37': ( 0.36862745098039218, - 0.36862745098039218, - 0.36862745098039218, - 1.0), - 'gray38': ( 0.38039215686274508, - 0.38039215686274508, - 0.38039215686274508, - 1.0), - 'gray39': ( 0.38823529411764707, - 0.38823529411764707, - 0.38823529411764707, - 1.0), - 'gray4': ( 0.039215686274509803, - 0.039215686274509803, - 0.039215686274509803, - 1.0), - 'gray40': ( 0.40000000000000002, - 0.40000000000000002, - 0.40000000000000002, - 1.0), - 'gray41': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'gray42': ( 0.41960784313725491, - 0.41960784313725491, - 0.41960784313725491, - 1.0), - 'gray43': ( 0.43137254901960786, - 0.43137254901960786, - 0.43137254901960786, - 1.0), - 'gray44': ( 0.4392156862745098, - 0.4392156862745098, - 0.4392156862745098, - 1.0), - 'gray45': ( 0.45098039215686275, - 0.45098039215686275, - 0.45098039215686275, - 1.0), - 'gray46': ( 0.45882352941176469, - 0.45882352941176469, - 0.45882352941176469, - 1.0), - 'gray47': ( 0.47058823529411764, - 0.47058823529411764, - 0.47058823529411764, - 1.0), - 'gray48': ( 0.47843137254901963, - 0.47843137254901963, - 0.47843137254901963, - 1.0), - 'gray49': ( 0.49019607843137253, - 0.49019607843137253, - 0.49019607843137253, - 1.0), - 'gray5': ( 0.050980392156862744, - 0.050980392156862744, - 0.050980392156862744, - 1.0), - 'gray50': ( 0.49803921568627452, - 0.49803921568627452, - 0.49803921568627452, - 1.0), - 'gray51': ( 0.50980392156862742, - 0.50980392156862742, - 0.50980392156862742, - 1.0), - 'gray52': ( 0.52156862745098043, - 0.52156862745098043, - 0.52156862745098043, - 1.0), - 'gray53': ( 0.52941176470588236, - 0.52941176470588236, - 0.52941176470588236, - 1.0), - 'gray54': ( 0.54117647058823526, - 0.54117647058823526, - 0.54117647058823526, - 1.0), - 'gray55': ( 0.5490196078431373, - 0.5490196078431373, - 0.5490196078431373, - 1.0), - 'gray56': ( 0.5607843137254902, - 0.5607843137254902, - 0.5607843137254902, - 1.0), - 'gray57': ( 0.56862745098039214, - 0.56862745098039214, - 0.56862745098039214, - 1.0), - 'gray58': ( 0.58039215686274515, - 0.58039215686274515, - 0.58039215686274515, - 1.0), - 'gray59': ( 0.58823529411764708, - 0.58823529411764708, - 0.58823529411764708, - 1.0), - 'gray6': ( 0.058823529411764705, - 0.058823529411764705, - 0.058823529411764705, - 1.0), - 'gray60': ( 0.59999999999999998, - 0.59999999999999998, - 0.59999999999999998, - 1.0), - 'gray61': ( 0.61176470588235299, - 0.61176470588235299, - 0.61176470588235299, - 1.0), - 'gray62': ( 0.61960784313725492, - 0.61960784313725492, - 0.61960784313725492, - 1.0), - 'gray63': ( 0.63137254901960782, - 0.63137254901960782, - 0.63137254901960782, - 1.0), - 'gray64': ( 0.63921568627450975, - 0.63921568627450975, - 0.63921568627450975, - 1.0), - 'gray65': ( 0.65098039215686276, - 0.65098039215686276, - 0.65098039215686276, - 1.0), - 'gray66': ( 0.6588235294117647, - 0.6588235294117647, - 0.6588235294117647, - 1.0), - 'gray67': ( 0.6705882352941176, - 0.6705882352941176, - 0.6705882352941176, - 1.0), - 'gray68': ( 0.67843137254901964, - 0.67843137254901964, - 0.67843137254901964, - 1.0), - 'gray69': ( 0.69019607843137254, - 0.69019607843137254, - 0.69019607843137254, - 1.0), - 'gray7': ( 0.070588235294117646, - 0.070588235294117646, - 0.070588235294117646, - 1.0), - 'gray70': ( 0.70196078431372544, - 0.70196078431372544, - 0.70196078431372544, - 1.0), - 'gray71': ( 0.70980392156862748, - 0.70980392156862748, - 0.70980392156862748, - 1.0), - 'gray72': ( 0.72156862745098038, - 0.72156862745098038, - 0.72156862745098038, - 1.0), - 'gray73': ( 0.72941176470588232, - 0.72941176470588232, - 0.72941176470588232, - 1.0), - 'gray74': ( 0.74117647058823533, - 0.74117647058823533, - 0.74117647058823533, - 1.0), - 'gray75': ( 0.74901960784313726, - 0.74901960784313726, - 0.74901960784313726, - 1.0), - 'gray76': ( 0.76078431372549016, - 0.76078431372549016, - 0.76078431372549016, - 1.0), - 'gray77': ( 0.7686274509803922, - 0.7686274509803922, - 0.7686274509803922, - 1.0), - 'gray78': ( 0.7803921568627451, - 0.7803921568627451, - 0.7803921568627451, - 1.0), - 'gray79': ( 0.78823529411764703, - 0.78823529411764703, - 0.78823529411764703, - 1.0), - 'gray8': ( 0.078431372549019607, - 0.078431372549019607, - 0.078431372549019607, - 1.0), - 'gray80': ( 0.80000000000000004, - 0.80000000000000004, - 0.80000000000000004, - 1.0), - 'gray81': ( 0.81176470588235294, - 0.81176470588235294, - 0.81176470588235294, - 1.0), - 'gray82': ( 0.81960784313725488, - 0.81960784313725488, - 0.81960784313725488, - 1.0), - 'gray83': ( 0.83137254901960789, - 0.83137254901960789, - 0.83137254901960789, - 1.0), - 'gray84': ( 0.83921568627450982, - 0.83921568627450982, - 0.83921568627450982, - 1.0), - 'gray85': ( 0.85098039215686272, - 0.85098039215686272, - 0.85098039215686272, - 1.0), - 'gray86': ( 0.85882352941176465, - 0.85882352941176465, - 0.85882352941176465, - 1.0), - 'gray87': ( 0.87058823529411766, - 0.87058823529411766, - 0.87058823529411766, - 1.0), - 'gray88': ( 0.8784313725490196, - 0.8784313725490196, - 0.8784313725490196, - 1.0), - 'gray89': ( 0.8901960784313725, - 0.8901960784313725, - 0.8901960784313725, - 1.0), - 'gray9': ( 0.090196078431372548, - 0.090196078431372548, - 0.090196078431372548, - 1.0), - 'gray90': ( 0.89803921568627454, - 0.89803921568627454, - 0.89803921568627454, - 1.0), - 'gray91': ( 0.90980392156862744, - 0.90980392156862744, - 0.90980392156862744, - 1.0), - 'gray92': ( 0.92156862745098034, - 0.92156862745098034, - 0.92156862745098034, - 1.0), - 'gray93': ( 0.92941176470588238, - 0.92941176470588238, - 0.92941176470588238, - 1.0), - 'gray94': ( 0.94117647058823528, - 0.94117647058823528, - 0.94117647058823528, - 1.0), - 'gray95': ( 0.94901960784313721, - 0.94901960784313721, - 0.94901960784313721, - 1.0), - 'gray96': ( 0.96078431372549022, - 0.96078431372549022, - 0.96078431372549022, - 1.0), - 'gray97': ( 0.96862745098039216, - 0.96862745098039216, - 0.96862745098039216, - 1.0), - 'gray98': ( 0.98039215686274506, - 0.98039215686274506, - 0.98039215686274506, - 1.0), - 'gray99': ( 0.9882352941176471, - 0.9882352941176471, - 0.9882352941176471, - 1.0), - 'green': (0.0, 1.0, 0.0, 1.0), - 'green yellow': (0.67843137254901964, 1.0, 0.18431372549019609, 1.0), - 'green1': (0.0, 1.0, 0.0, 1.0), - 'green2': (0.0, 0.93333333333333335, 0.0, 1.0), - 'green3': (0.0, 0.80392156862745101, 0.0, 1.0), - 'green4': (0.0, 0.54509803921568623, 0.0, 1.0), - 'greenyellow': (0.67843137254901964, 1.0, 0.18431372549019609, 1.0), - 'grey': ( 0.74509803921568629, - 0.74509803921568629, - 0.74509803921568629, - 1.0), - 'grey0': (0.0, 0.0, 0.0, 1.0), - 'grey1': ( 0.011764705882352941, - 0.011764705882352941, - 0.011764705882352941, - 1.0), - 'grey10': ( 0.10196078431372549, - 0.10196078431372549, - 0.10196078431372549, - 1.0), - 'grey100': (1.0, 1.0, 1.0, 1.0), - 'grey11': ( 0.10980392156862745, - 0.10980392156862745, - 0.10980392156862745, - 1.0), - 'grey12': ( 0.12156862745098039, - 0.12156862745098039, - 0.12156862745098039, - 1.0), - 'grey13': ( 0.12941176470588237, - 0.12941176470588237, - 0.12941176470588237, - 1.0), - 'grey14': ( 0.14117647058823529, - 0.14117647058823529, - 0.14117647058823529, - 1.0), - 'grey15': ( 0.14901960784313725, - 0.14901960784313725, - 0.14901960784313725, - 1.0), - 'grey16': ( 0.16078431372549021, - 0.16078431372549021, - 0.16078431372549021, - 1.0), - 'grey17': ( 0.16862745098039217, - 0.16862745098039217, - 0.16862745098039217, - 1.0), - 'grey18': ( 0.1803921568627451, - 0.1803921568627451, - 0.1803921568627451, - 1.0), - 'grey19': ( 0.18823529411764706, - 0.18823529411764706, - 0.18823529411764706, - 1.0), - 'grey2': ( 0.019607843137254902, - 0.019607843137254902, - 0.019607843137254902, - 1.0), - 'grey20': ( 0.20000000000000001, - 0.20000000000000001, - 0.20000000000000001, - 1.0), - 'grey21': ( 0.21176470588235294, - 0.21176470588235294, - 0.21176470588235294, - 1.0), - 'grey22': ( 0.2196078431372549, - 0.2196078431372549, - 0.2196078431372549, - 1.0), - 'grey23': ( 0.23137254901960785, - 0.23137254901960785, - 0.23137254901960785, - 1.0), - 'grey24': ( 0.23921568627450981, - 0.23921568627450981, - 0.23921568627450981, - 1.0), - 'grey25': ( 0.25098039215686274, - 0.25098039215686274, - 0.25098039215686274, - 1.0), - 'grey26': ( 0.25882352941176473, - 0.25882352941176473, - 0.25882352941176473, - 1.0), - 'grey27': ( 0.27058823529411763, - 0.27058823529411763, - 0.27058823529411763, - 1.0), - 'grey28': ( 0.27843137254901962, - 0.27843137254901962, - 0.27843137254901962, - 1.0), - 'grey29': ( 0.29019607843137257, - 0.29019607843137257, - 0.29019607843137257, - 1.0), - 'grey3': ( 0.031372549019607843, - 0.031372549019607843, - 0.031372549019607843, - 1.0), - 'grey30': ( 0.30196078431372547, - 0.30196078431372547, - 0.30196078431372547, - 1.0), - 'grey31': ( 0.30980392156862746, - 0.30980392156862746, - 0.30980392156862746, - 1.0), - 'grey32': ( 0.32156862745098042, - 0.32156862745098042, - 0.32156862745098042, - 1.0), - 'grey33': ( 0.32941176470588235, - 0.32941176470588235, - 0.32941176470588235, - 1.0), - 'grey34': ( 0.3411764705882353, - 0.3411764705882353, - 0.3411764705882353, - 1.0), - 'grey35': ( 0.34901960784313724, - 0.34901960784313724, - 0.34901960784313724, - 1.0), - 'grey36': ( 0.36078431372549019, - 0.36078431372549019, - 0.36078431372549019, - 1.0), - 'grey37': ( 0.36862745098039218, - 0.36862745098039218, - 0.36862745098039218, - 1.0), - 'grey38': ( 0.38039215686274508, - 0.38039215686274508, - 0.38039215686274508, - 1.0), - 'grey39': ( 0.38823529411764707, - 0.38823529411764707, - 0.38823529411764707, - 1.0), - 'grey4': ( 0.039215686274509803, - 0.039215686274509803, - 0.039215686274509803, - 1.0), - 'grey40': ( 0.40000000000000002, - 0.40000000000000002, - 0.40000000000000002, - 1.0), - 'grey41': ( 0.41176470588235292, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'grey42': ( 0.41960784313725491, - 0.41960784313725491, - 0.41960784313725491, - 1.0), - 'grey43': ( 0.43137254901960786, - 0.43137254901960786, - 0.43137254901960786, - 1.0), - 'grey44': ( 0.4392156862745098, - 0.4392156862745098, - 0.4392156862745098, - 1.0), - 'grey45': ( 0.45098039215686275, - 0.45098039215686275, - 0.45098039215686275, - 1.0), - 'grey46': ( 0.45882352941176469, - 0.45882352941176469, - 0.45882352941176469, - 1.0), - 'grey47': ( 0.47058823529411764, - 0.47058823529411764, - 0.47058823529411764, - 1.0), - 'grey48': ( 0.47843137254901963, - 0.47843137254901963, - 0.47843137254901963, - 1.0), - 'grey49': ( 0.49019607843137253, - 0.49019607843137253, - 0.49019607843137253, - 1.0), - 'grey5': ( 0.050980392156862744, - 0.050980392156862744, - 0.050980392156862744, - 1.0), - 'grey50': ( 0.49803921568627452, - 0.49803921568627452, - 0.49803921568627452, - 1.0), - 'grey51': ( 0.50980392156862742, - 0.50980392156862742, - 0.50980392156862742, - 1.0), - 'grey52': ( 0.52156862745098043, - 0.52156862745098043, - 0.52156862745098043, - 1.0), - 'grey53': ( 0.52941176470588236, - 0.52941176470588236, - 0.52941176470588236, - 1.0), - 'grey54': ( 0.54117647058823526, - 0.54117647058823526, - 0.54117647058823526, - 1.0), - 'grey55': ( 0.5490196078431373, - 0.5490196078431373, - 0.5490196078431373, - 1.0), - 'grey56': ( 0.5607843137254902, - 0.5607843137254902, - 0.5607843137254902, - 1.0), - 'grey57': ( 0.56862745098039214, - 0.56862745098039214, - 0.56862745098039214, - 1.0), - 'grey58': ( 0.58039215686274515, - 0.58039215686274515, - 0.58039215686274515, - 1.0), - 'grey59': ( 0.58823529411764708, - 0.58823529411764708, - 0.58823529411764708, - 1.0), - 'grey6': ( 0.058823529411764705, - 0.058823529411764705, - 0.058823529411764705, - 1.0), - 'grey60': ( 0.59999999999999998, - 0.59999999999999998, - 0.59999999999999998, - 1.0), - 'grey61': ( 0.61176470588235299, - 0.61176470588235299, - 0.61176470588235299, - 1.0), - 'grey62': ( 0.61960784313725492, - 0.61960784313725492, - 0.61960784313725492, - 1.0), - 'grey63': ( 0.63137254901960782, - 0.63137254901960782, - 0.63137254901960782, - 1.0), - 'grey64': ( 0.63921568627450975, - 0.63921568627450975, - 0.63921568627450975, - 1.0), - 'grey65': ( 0.65098039215686276, - 0.65098039215686276, - 0.65098039215686276, - 1.0), - 'grey66': ( 0.6588235294117647, - 0.6588235294117647, - 0.6588235294117647, - 1.0), - 'grey67': ( 0.6705882352941176, - 0.6705882352941176, - 0.6705882352941176, - 1.0), - 'grey68': ( 0.67843137254901964, - 0.67843137254901964, - 0.67843137254901964, - 1.0), - 'grey69': ( 0.69019607843137254, - 0.69019607843137254, - 0.69019607843137254, - 1.0), - 'grey7': ( 0.070588235294117646, - 0.070588235294117646, - 0.070588235294117646, - 1.0), - 'grey70': ( 0.70196078431372544, - 0.70196078431372544, - 0.70196078431372544, - 1.0), - 'grey71': ( 0.70980392156862748, - 0.70980392156862748, - 0.70980392156862748, - 1.0), - 'grey72': ( 0.72156862745098038, - 0.72156862745098038, - 0.72156862745098038, - 1.0), - 'grey73': ( 0.72941176470588232, - 0.72941176470588232, - 0.72941176470588232, - 1.0), - 'grey74': ( 0.74117647058823533, - 0.74117647058823533, - 0.74117647058823533, - 1.0), - 'grey75': ( 0.74901960784313726, - 0.74901960784313726, - 0.74901960784313726, - 1.0), - 'grey76': ( 0.76078431372549016, - 0.76078431372549016, - 0.76078431372549016, - 1.0), - 'grey77': ( 0.7686274509803922, - 0.7686274509803922, - 0.7686274509803922, - 1.0), - 'grey78': ( 0.7803921568627451, - 0.7803921568627451, - 0.7803921568627451, - 1.0), - 'grey79': ( 0.78823529411764703, - 0.78823529411764703, - 0.78823529411764703, - 1.0), - 'grey8': ( 0.078431372549019607, - 0.078431372549019607, - 0.078431372549019607, - 1.0), - 'grey80': ( 0.80000000000000004, - 0.80000000000000004, - 0.80000000000000004, - 1.0), - 'grey81': ( 0.81176470588235294, - 0.81176470588235294, - 0.81176470588235294, - 1.0), - 'grey82': ( 0.81960784313725488, - 0.81960784313725488, - 0.81960784313725488, - 1.0), - 'grey83': ( 0.83137254901960789, - 0.83137254901960789, - 0.83137254901960789, - 1.0), - 'grey84': ( 0.83921568627450982, - 0.83921568627450982, - 0.83921568627450982, - 1.0), - 'grey85': ( 0.85098039215686272, - 0.85098039215686272, - 0.85098039215686272, - 1.0), - 'grey86': ( 0.85882352941176465, - 0.85882352941176465, - 0.85882352941176465, - 1.0), - 'grey87': ( 0.87058823529411766, - 0.87058823529411766, - 0.87058823529411766, - 1.0), - 'grey88': ( 0.8784313725490196, - 0.8784313725490196, - 0.8784313725490196, - 1.0), - 'grey89': ( 0.8901960784313725, - 0.8901960784313725, - 0.8901960784313725, - 1.0), - 'grey9': ( 0.090196078431372548, - 0.090196078431372548, - 0.090196078431372548, - 1.0), - 'grey90': ( 0.89803921568627454, - 0.89803921568627454, - 0.89803921568627454, - 1.0), - 'grey91': ( 0.90980392156862744, - 0.90980392156862744, - 0.90980392156862744, - 1.0), - 'grey92': ( 0.92156862745098034, - 0.92156862745098034, - 0.92156862745098034, - 1.0), - 'grey93': ( 0.92941176470588238, - 0.92941176470588238, - 0.92941176470588238, - 1.0), - 'grey94': ( 0.94117647058823528, - 0.94117647058823528, - 0.94117647058823528, - 1.0), - 'grey95': ( 0.94901960784313721, - 0.94901960784313721, - 0.94901960784313721, - 1.0), - 'grey96': ( 0.96078431372549022, - 0.96078431372549022, - 0.96078431372549022, - 1.0), - 'grey97': ( 0.96862745098039216, - 0.96862745098039216, - 0.96862745098039216, - 1.0), - 'grey98': ( 0.98039215686274506, - 0.98039215686274506, - 0.98039215686274506, - 1.0), - 'grey99': ( 0.9882352941176471, - 0.9882352941176471, - 0.9882352941176471, - 1.0), - 'honeydew': (0.94117647058823528, 1.0, 0.94117647058823528, 1.0), - 'honeydew1': (0.94117647058823528, 1.0, 0.94117647058823528, 1.0), - 'honeydew2': ( 0.8784313725490196, - 0.93333333333333335, - 0.8784313725490196, - 1.0), - 'honeydew3': ( 0.75686274509803919, - 0.80392156862745101, - 0.75686274509803919, - 1.0), - 'honeydew4': ( 0.51372549019607838, - 0.54509803921568623, - 0.51372549019607838, - 1.0), - 'hot pink': (1.0, 0.41176470588235292, 0.70588235294117652, 1.0), - 'hotpink': (1.0, 0.41176470588235292, 0.70588235294117652, 1.0), - 'hotpink1': (1.0, 0.43137254901960786, 0.70588235294117652, 1.0), - 'hotpink2': ( 0.93333333333333335, - 0.41568627450980394, - 0.65490196078431373, - 1.0), - 'hotpink3': ( 0.80392156862745101, - 0.37647058823529411, - 0.56470588235294117, - 1.0), - 'hotpink4': ( 0.54509803921568623, - 0.22745098039215686, - 0.3843137254901961, - 1.0), - 'indian red': ( 0.80392156862745101, - 0.36078431372549019, - 0.36078431372549019, - 1.0), - 'indianred': ( 0.80392156862745101, - 0.36078431372549019, - 0.36078431372549019, - 1.0), - 'indianred1': (1.0, 0.41568627450980394, 0.41568627450980394, 1.0), - 'indianred2': ( 0.93333333333333335, - 0.38823529411764707, - 0.38823529411764707, - 1.0), - 'indianred3': ( 0.80392156862745101, - 0.33333333333333331, - 0.33333333333333331, - 1.0), - 'indianred4': ( 0.54509803921568623, - 0.22745098039215686, - 0.22745098039215686, - 1.0), - 'indigo': (0.29411764705882354, 0.0, 0.5098039215686274, 1.0), - 'ivory': (1.0, 1.0, 0.94117647058823528, 1.0), - 'ivory1': (1.0, 1.0, 0.94117647058823528, 1.0), - 'ivory2': ( 0.93333333333333335, - 0.93333333333333335, - 0.8784313725490196, - 1.0), - 'ivory3': ( 0.80392156862745101, - 0.80392156862745101, - 0.75686274509803919, - 1.0), - 'ivory4': ( 0.54509803921568623, - 0.54509803921568623, - 0.51372549019607838, - 1.0), - 'khaki': ( 0.94117647058823528, - 0.90196078431372551, - 0.5490196078431373, - 1.0), - 'khaki1': (1.0, 0.96470588235294119, 0.5607843137254902, 1.0), - 'khaki2': ( 0.93333333333333335, - 0.90196078431372551, - 0.52156862745098043, - 1.0), - 'khaki3': ( 0.80392156862745101, - 0.77647058823529413, - 0.45098039215686275, - 1.0), - 'khaki4': ( 0.54509803921568623, - 0.52549019607843139, - 0.30588235294117649, - 1.0), - 'lavender': ( 0.90196078431372551, - 0.90196078431372551, - 0.98039215686274506, - 1.0), - 'lavender blush': (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), - 'lavenderblush': (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), - 'lavenderblush1': (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), - 'lavenderblush2': ( 0.93333333333333335, - 0.8784313725490196, - 0.89803921568627454, - 1.0), - 'lavenderblush3': ( 0.80392156862745101, - 0.75686274509803919, - 0.77254901960784317, - 1.0), - 'lavenderblush4': ( 0.54509803921568623, - 0.51372549019607838, - 0.52549019607843139, - 1.0), - 'lawn green': (0.48627450980392156, 0.9882352941176471, 0.0, 1.0), - 'lawngreen': (0.48627450980392156, 0.9882352941176471, 0.0, 1.0), - 'lemon chiffon': (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), - 'lemonchiffon': (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), - 'lemonchiffon1': (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), - 'lemonchiffon2': ( 0.93333333333333335, - 0.9137254901960784, - 0.74901960784313726, - 1.0), - 'lemonchiffon3': ( 0.80392156862745101, - 0.78823529411764703, - 0.6470588235294118, - 1.0), - 'lemonchiffon4': ( 0.54509803921568623, - 0.53725490196078429, - 0.4392156862745098, - 1.0), - 'light blue': ( 0.67843137254901964, - 0.84705882352941175, - 0.90196078431372551, - 1.0), - 'light coral': ( 0.94117647058823528, - 0.50196078431372548, - 0.50196078431372548, - 1.0), - 'light cyan': (0.8784313725490196, 1.0, 1.0, 1.0), - 'light goldenrod': ( 0.93333333333333335, - 0.8666666666666667, - 0.50980392156862742, - 1.0), - 'light goldenrod yellow': ( 0.98039215686274506, - 0.98039215686274506, - 0.82352941176470584, - 1.0), - 'light gray': ( 0.82745098039215681, - 0.82745098039215681, - 0.82745098039215681, - 1.0), - 'light green': ( 0.56470588235294117, - 0.93333333333333335, - 0.56470588235294117, - 1.0), - 'light grey': ( 0.82745098039215681, - 0.82745098039215681, - 0.82745098039215681, - 1.0), - 'light pink': (1.0, 0.71372549019607845, 0.75686274509803919, 1.0), - 'light salmon': (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), - 'light sea green': ( 0.12549019607843137, - 0.69803921568627447, - 0.66666666666666663, - 1.0), - 'light sky blue': ( 0.52941176470588236, - 0.80784313725490198, - 0.98039215686274506, - 1.0), - 'light slate blue': (0.51764705882352946, 0.4392156862745098, 1.0, 1.0), - 'light slate gray': ( 0.46666666666666667, - 0.53333333333333333, - 0.59999999999999998, - 1.0), - 'light slate grey': ( 0.46666666666666667, - 0.53333333333333333, - 0.59999999999999998, - 1.0), - 'light steel blue': ( 0.69019607843137254, - 0.7686274509803922, - 0.87058823529411766, - 1.0), - 'light yellow': (1.0, 1.0, 0.8784313725490196, 1.0), - 'lightblue': ( 0.67843137254901964, - 0.84705882352941175, - 0.90196078431372551, - 1.0), - 'lightblue1': (0.74901960784313726, 0.93725490196078431, 1.0, 1.0), - 'lightblue2': ( 0.69803921568627447, - 0.87450980392156863, - 0.93333333333333335, - 1.0), - 'lightblue3': ( 0.60392156862745094, - 0.75294117647058822, - 0.80392156862745101, - 1.0), - 'lightblue4': ( 0.40784313725490196, - 0.51372549019607838, - 0.54509803921568623, - 1.0), - 'lightcoral': ( 0.94117647058823528, - 0.50196078431372548, - 0.50196078431372548, - 1.0), - 'lightcyan': (0.8784313725490196, 1.0, 1.0, 1.0), - 'lightcyan1': (0.8784313725490196, 1.0, 1.0, 1.0), - 'lightcyan2': ( 0.81960784313725488, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'lightcyan3': ( 0.70588235294117652, - 0.80392156862745101, - 0.80392156862745101, - 1.0), - 'lightcyan4': ( 0.47843137254901963, - 0.54509803921568623, - 0.54509803921568623, - 1.0), - 'lightgoldenrod': ( 0.93333333333333335, - 0.8666666666666667, - 0.50980392156862742, - 1.0), - 'lightgoldenrod1': (1.0, 0.92549019607843142, 0.54509803921568623, 1.0), - 'lightgoldenrod2': ( 0.93333333333333335, - 0.86274509803921573, - 0.50980392156862742, - 1.0), - 'lightgoldenrod3': ( 0.80392156862745101, - 0.74509803921568629, - 0.4392156862745098, - 1.0), - 'lightgoldenrod4': ( 0.54509803921568623, - 0.50588235294117645, - 0.29803921568627451, - 1.0), - 'lightgoldenrodyellow': ( 0.98039215686274506, - 0.98039215686274506, - 0.82352941176470584, - 1.0), - 'lightgray': ( 0.82745098039215681, - 0.82745098039215681, - 0.82745098039215681, - 1.0), - 'lightgreen': ( 0.56470588235294117, - 0.93333333333333335, - 0.56470588235294117, - 1.0), - 'lightgrey': ( 0.82745098039215681, - 0.82745098039215681, - 0.82745098039215681, - 1.0), - 'lightpink': (1.0, 0.71372549019607845, 0.75686274509803919, 1.0), - 'lightpink1': (1.0, 0.68235294117647061, 0.72549019607843135, 1.0), - 'lightpink2': ( 0.93333333333333335, - 0.63529411764705879, - 0.67843137254901964, - 1.0), - 'lightpink3': ( 0.80392156862745101, - 0.5490196078431373, - 0.58431372549019611, - 1.0), - 'lightpink4': ( 0.54509803921568623, - 0.37254901960784315, - 0.396078431372549, - 1.0), - 'lightsalmon': (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), - 'lightsalmon1': (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), - 'lightsalmon2': ( 0.93333333333333335, - 0.58431372549019611, - 0.44705882352941179, - 1.0), - 'lightsalmon3': ( 0.80392156862745101, - 0.50588235294117645, - 0.3843137254901961, - 1.0), - 'lightsalmon4': ( 0.54509803921568623, - 0.3411764705882353, - 0.25882352941176473, - 1.0), - 'lightseagreen': ( 0.12549019607843137, - 0.69803921568627447, - 0.66666666666666663, - 1.0), - 'lightskyblue': ( 0.52941176470588236, - 0.80784313725490198, - 0.98039215686274506, - 1.0), - 'lightskyblue1': (0.69019607843137254, 0.88627450980392153, 1.0, 1.0), - 'lightskyblue2': ( 0.64313725490196083, - 0.82745098039215681, - 0.93333333333333335, - 1.0), - 'lightskyblue3': ( 0.55294117647058827, - 0.71372549019607845, - 0.80392156862745101, - 1.0), - 'lightskyblue4': ( 0.37647058823529411, - 0.4823529411764706, - 0.54509803921568623, - 1.0), - 'lightslateblue': (0.51764705882352946, 0.4392156862745098, 1.0, 1.0), - 'lightslategray': ( 0.46666666666666667, - 0.53333333333333333, - 0.59999999999999998, - 1.0), - 'lightslategrey': ( 0.46666666666666667, - 0.53333333333333333, - 0.59999999999999998, - 1.0), - 'lightsteelblue': ( 0.69019607843137254, - 0.7686274509803922, - 0.87058823529411766, - 1.0), - 'lightsteelblue1': (0.792156862745098, 0.88235294117647056, 1.0, 1.0), - 'lightsteelblue2': ( 0.73725490196078436, - 0.82352941176470584, - 0.93333333333333335, - 1.0), - 'lightsteelblue3': ( 0.63529411764705879, - 0.70980392156862748, - 0.80392156862745101, - 1.0), - 'lightsteelblue4': ( 0.43137254901960786, - 0.4823529411764706, - 0.54509803921568623, - 1.0), - 'lightyellow': (1.0, 1.0, 0.8784313725490196, 1.0), - 'lightyellow1': (1.0, 1.0, 0.8784313725490196, 1.0), - 'lightyellow2': ( 0.93333333333333335, - 0.93333333333333335, - 0.81960784313725488, - 1.0), - 'lightyellow3': ( 0.80392156862745101, - 0.80392156862745101, - 0.70588235294117652, - 1.0), - 'lightyellow4': ( 0.54509803921568623, - 0.54509803921568623, - 0.47843137254901963, - 1.0), - 'lime': (0.0, 1.0, 0.0, 1.0), - 'lime green': ( 0.19607843137254902, - 0.80392156862745101, - 0.19607843137254902, - 1.0), - 'limegreen': ( 0.19607843137254902, - 0.80392156862745101, - 0.19607843137254902, - 1.0), - 'linen': ( 0.98039215686274506, - 0.94117647058823528, - 0.90196078431372551, - 1.0), - 'magenta': (1.0, 0.0, 1.0, 1.0), - 'magenta1': (1.0, 0.0, 1.0, 1.0), - 'magenta2': (0.93333333333333335, 0.0, 0.93333333333333335, 1.0), - 'magenta3': (0.80392156862745101, 0.0, 0.80392156862745101, 1.0), - 'magenta4': (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), - 'maroon': ( 0.69019607843137254, - 0.18823529411764706, - 0.37647058823529411, - 1.0), - 'maroon1': (1.0, 0.20392156862745098, 0.70196078431372544, 1.0), - 'maroon2': ( 0.93333333333333335, - 0.18823529411764706, - 0.65490196078431373, - 1.0), - 'maroon3': ( 0.80392156862745101, - 0.16078431372549021, - 0.56470588235294117, - 1.0), - 'maroon4': ( 0.54509803921568623, - 0.10980392156862745, - 0.3843137254901961, - 1.0), - 'medium aquamarine': ( 0.40000000000000002, - 0.80392156862745101, - 0.66666666666666663, - 1.0), - 'medium blue': (0.0, 0.0, 0.80392156862745101, 1.0), - 'medium orchid': ( 0.72941176470588232, - 0.33333333333333331, - 0.82745098039215681, - 1.0), - 'medium purple': ( 0.57647058823529407, - 0.4392156862745098, - 0.85882352941176465, - 1.0), - 'medium sea green': ( 0.23529411764705882, - 0.70196078431372544, - 0.44313725490196076, - 1.0), - 'medium slate blue': ( 0.4823529411764706, - 0.40784313725490196, - 0.93333333333333335, - 1.0), - 'medium spring green': ( 0.0, - 0.98039215686274506, - 0.60392156862745094, - 1.0), - 'medium turquoise': ( 0.28235294117647058, - 0.81960784313725488, - 0.80000000000000004, - 1.0), - 'medium violet red': ( 0.7803921568627451, - 0.082352941176470587, - 0.52156862745098043, - 1.0), - 'mediumaquamarine': ( 0.40000000000000002, - 0.80392156862745101, - 0.66666666666666663, - 1.0), - 'mediumblue': (0.0, 0.0, 0.80392156862745101, 1.0), - 'mediumorchid': ( 0.72941176470588232, - 0.33333333333333331, - 0.82745098039215681, - 1.0), - 'mediumorchid1': (0.8784313725490196, 0.40000000000000002, 1.0, 1.0), - 'mediumorchid2': ( 0.81960784313725488, - 0.37254901960784315, - 0.93333333333333335, - 1.0), - 'mediumorchid3': ( 0.70588235294117652, - 0.32156862745098042, - 0.80392156862745101, - 1.0), - 'mediumorchid4': ( 0.47843137254901963, - 0.21568627450980393, - 0.54509803921568623, - 1.0), - 'mediumpurple': ( 0.57647058823529407, - 0.4392156862745098, - 0.85882352941176465, - 1.0), - 'mediumpurple1': (0.6705882352941176, 0.50980392156862742, 1.0, 1.0), - 'mediumpurple2': ( 0.62352941176470589, - 0.47450980392156861, - 0.93333333333333335, - 1.0), - 'mediumpurple3': ( 0.53725490196078429, - 0.40784313725490196, - 0.80392156862745101, - 1.0), - 'mediumpurple4': ( 0.36470588235294116, - 0.27843137254901962, - 0.54509803921568623, - 1.0), - 'mediumseagreen': ( 0.23529411764705882, - 0.70196078431372544, - 0.44313725490196076, - 1.0), - 'mediumslateblue': ( 0.4823529411764706, - 0.40784313725490196, - 0.93333333333333335, - 1.0), - 'mediumspringgreen': (0.0, 0.98039215686274506, 0.60392156862745094, 1.0), - 'mediumturquoise': ( 0.28235294117647058, - 0.81960784313725488, - 0.80000000000000004, - 1.0), - 'mediumvioletred': ( 0.7803921568627451, - 0.082352941176470587, - 0.52156862745098043, - 1.0), - 'midnight blue': ( 0.098039215686274508, - 0.098039215686274508, - 0.4392156862745098, - 1.0), - 'midnightblue': ( 0.098039215686274508, - 0.098039215686274508, - 0.4392156862745098, - 1.0), - 'mint cream': (0.96078431372549022, 1.0, 0.98039215686274506, 1.0), - 'mintcream': (0.96078431372549022, 1.0, 0.98039215686274506, 1.0), - 'misty rose': (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), - 'mistyrose': (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), - 'mistyrose1': (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), - 'mistyrose2': ( 0.93333333333333335, - 0.83529411764705885, - 0.82352941176470584, - 1.0), - 'mistyrose3': ( 0.80392156862745101, - 0.71764705882352942, - 0.70980392156862748, - 1.0), - 'mistyrose4': ( 0.54509803921568623, - 0.49019607843137253, - 0.4823529411764706, - 1.0), - 'moccasin': (1.0, 0.89411764705882357, 0.70980392156862748, 1.0), - 'navajo white': (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), - 'navajowhite': (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), - 'navajowhite1': (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), - 'navajowhite2': ( 0.93333333333333335, - 0.81176470588235294, - 0.63137254901960782, - 1.0), - 'navajowhite3': ( 0.80392156862745101, - 0.70196078431372544, - 0.54509803921568623, - 1.0), - 'navajowhite4': ( 0.54509803921568623, - 0.47450980392156861, - 0.36862745098039218, - 1.0), - 'navy': (0.0, 0.0, 0.50196078431372548, 1.0), - 'navy blue': (0.0, 0.0, 0.50196078431372548, 1.0), - 'navyblue': (0.0, 0.0, 0.50196078431372548, 1.0), - 'old lace': ( 0.99215686274509807, - 0.96078431372549022, - 0.90196078431372551, - 1.0), - 'oldlace': ( 0.99215686274509807, - 0.96078431372549022, - 0.90196078431372551, - 1.0), - 'olive': (0.5, 0.5, 0.0, 1.0), - 'olive drab': ( 0.41960784313725491, - 0.55686274509803924, - 0.13725490196078433, - 1.0), - 'olivedrab': ( 0.41960784313725491, - 0.55686274509803924, - 0.13725490196078433, - 1.0), - 'olivedrab1': (0.75294117647058822, 1.0, 0.24313725490196078, 1.0), - 'olivedrab2': ( 0.70196078431372544, - 0.93333333333333335, - 0.22745098039215686, - 1.0), - 'olivedrab3': ( 0.60392156862745094, - 0.80392156862745101, - 0.19607843137254902, - 1.0), - 'olivedrab4': ( 0.41176470588235292, - 0.54509803921568623, - 0.13333333333333333, - 1.0), - 'orange': (1.0, 0.6470588235294118, 0.0, 1.0), - 'orange red': (1.0, 0.27058823529411763, 0.0, 1.0), - 'orange1': (1.0, 0.6470588235294118, 0.0, 1.0), - 'orange2': (0.93333333333333335, 0.60392156862745094, 0.0, 1.0), - 'orange3': (0.80392156862745101, 0.52156862745098043, 0.0, 1.0), - 'orange4': (0.54509803921568623, 0.35294117647058826, 0.0, 1.0), - 'orangered': (1.0, 0.27058823529411763, 0.0, 1.0), - 'orangered1': (1.0, 0.27058823529411763, 0.0, 1.0), - 'orangered2': (0.93333333333333335, 0.25098039215686274, 0.0, 1.0), - 'orangered3': (0.80392156862745101, 0.21568627450980393, 0.0, 1.0), - 'orangered4': (0.54509803921568623, 0.14509803921568629, 0.0, 1.0), - 'orchid': ( 0.85490196078431369, - 0.4392156862745098, - 0.83921568627450982, - 1.0), - 'orchid1': (1.0, 0.51372549019607838, 0.98039215686274506, 1.0), - 'orchid2': ( 0.93333333333333335, - 0.47843137254901963, - 0.9137254901960784, - 1.0), - 'orchid3': ( 0.80392156862745101, - 0.41176470588235292, - 0.78823529411764703, - 1.0), - 'orchid4': ( 0.54509803921568623, - 0.27843137254901962, - 0.53725490196078429, - 1.0), - 'pale goldenrod': ( 0.93333333333333335, - 0.90980392156862744, - 0.66666666666666663, - 1.0), - 'pale green': ( 0.59607843137254901, - 0.98431372549019602, - 0.59607843137254901, - 1.0), - 'pale turquoise': ( 0.68627450980392157, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'pale violet red': ( 0.85882352941176465, - 0.4392156862745098, - 0.57647058823529407, - 1.0), - 'palegoldenrod': ( 0.93333333333333335, - 0.90980392156862744, - 0.66666666666666663, - 1.0), - 'palegreen': ( 0.59607843137254901, - 0.98431372549019602, - 0.59607843137254901, - 1.0), - 'palegreen1': (0.60392156862745094, 1.0, 0.60392156862745094, 1.0), - 'palegreen2': ( 0.56470588235294117, - 0.93333333333333335, - 0.56470588235294117, - 1.0), - 'palegreen3': ( 0.48627450980392156, - 0.80392156862745101, - 0.48627450980392156, - 1.0), - 'palegreen4': ( 0.32941176470588235, - 0.54509803921568623, - 0.32941176470588235, - 1.0), - 'paleturquoise': ( 0.68627450980392157, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'paleturquoise1': (0.73333333333333328, 1.0, 1.0, 1.0), - 'paleturquoise2': ( 0.68235294117647061, - 0.93333333333333335, - 0.93333333333333335, - 1.0), - 'paleturquoise3': ( 0.58823529411764708, - 0.80392156862745101, - 0.80392156862745101, - 1.0), - 'paleturquoise4': ( 0.40000000000000002, - 0.54509803921568623, - 0.54509803921568623, - 1.0), - 'palevioletred': ( 0.85882352941176465, - 0.4392156862745098, - 0.57647058823529407, - 1.0), - 'palevioletred1': (1.0, 0.50980392156862742, 0.6705882352941176, 1.0), - 'palevioletred2': ( 0.93333333333333335, - 0.47450980392156861, - 0.62352941176470589, - 1.0), - 'palevioletred3': ( 0.80392156862745101, - 0.40784313725490196, - 0.53725490196078429, - 1.0), - 'palevioletred4': ( 0.54509803921568623, - 0.27843137254901962, - 0.36470588235294116, - 1.0), - 'papaya whip': (1.0, 0.93725490196078431, 0.83529411764705885, 1.0), - 'papayawhip': (1.0, 0.93725490196078431, 0.83529411764705885, 1.0), - 'peach puff': (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), - 'peachpuff': (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), - 'peachpuff1': (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), - 'peachpuff2': ( 0.93333333333333335, - 0.79607843137254897, - 0.67843137254901964, - 1.0), - 'peachpuff3': ( 0.80392156862745101, - 0.68627450980392157, - 0.58431372549019611, - 1.0), - 'peachpuff4': ( 0.54509803921568623, - 0.46666666666666667, - 0.396078431372549, - 1.0), - 'peru': ( 0.80392156862745101, - 0.52156862745098043, - 0.24705882352941178, - 1.0), - 'pink': (1.0, 0.75294117647058822, 0.79607843137254897, 1.0), - 'pink1': (1.0, 0.70980392156862748, 0.77254901960784317, 1.0), - 'pink2': ( 0.93333333333333335, - 0.66274509803921566, - 0.72156862745098038, - 1.0), - 'pink3': ( 0.80392156862745101, - 0.56862745098039214, - 0.61960784313725492, - 1.0), - 'pink4': ( 0.54509803921568623, - 0.38823529411764707, - 0.42352941176470588, - 1.0), - 'plum': (0.8666666666666667, 0.62745098039215685, 0.8666666666666667, 1.0), - 'plum1': (1.0, 0.73333333333333328, 1.0, 1.0), - 'plum2': ( 0.93333333333333335, - 0.68235294117647061, - 0.93333333333333335, - 1.0), - 'plum3': ( 0.80392156862745101, - 0.58823529411764708, - 0.80392156862745101, - 1.0), - 'plum4': ( 0.54509803921568623, - 0.40000000000000002, - 0.54509803921568623, - 1.0), - 'powder blue': ( 0.69019607843137254, - 0.8784313725490196, - 0.90196078431372551, - 1.0), - 'powderblue': ( 0.69019607843137254, - 0.8784313725490196, - 0.90196078431372551, - 1.0), - 'purple': ( 0.62745098039215685, - 0.12549019607843137, - 0.94117647058823528, - 1.0), - 'purple1': (0.60784313725490191, 0.18823529411764706, 1.0, 1.0), - 'purple2': ( 0.56862745098039214, - 0.17254901960784313, - 0.93333333333333335, - 1.0), - 'purple3': ( 0.49019607843137253, - 0.14901960784313725, - 0.80392156862745101, - 1.0), - 'purple4': ( 0.33333333333333331, - 0.10196078431372549, - 0.54509803921568623, - 1.0), - 'rebecca purple': (0.4, 0.2, 0.6, 1.0), - 'rebeccapurple': (0.4, 0.2, 0.6, 1.0), - 'red': (1.0, 0.0, 0.0, 1.0), - 'red1': (1.0, 0.0, 0.0, 1.0), - 'red2': (0.93333333333333335, 0.0, 0.0, 1.0), - 'red3': (0.80392156862745101, 0.0, 0.0, 1.0), - 'red4': (0.54509803921568623, 0.0, 0.0, 1.0), - 'rosy brown': ( 0.73725490196078436, - 0.5607843137254902, - 0.5607843137254902, - 1.0), - 'rosybrown': ( 0.73725490196078436, - 0.5607843137254902, - 0.5607843137254902, - 1.0), - 'rosybrown1': (1.0, 0.75686274509803919, 0.75686274509803919, 1.0), - 'rosybrown2': ( 0.93333333333333335, - 0.70588235294117652, - 0.70588235294117652, - 1.0), - 'rosybrown3': ( 0.80392156862745101, - 0.60784313725490191, - 0.60784313725490191, - 1.0), - 'rosybrown4': ( 0.54509803921568623, - 0.41176470588235292, - 0.41176470588235292, - 1.0), - 'royal blue': ( 0.25490196078431371, - 0.41176470588235292, - 0.88235294117647056, - 1.0), - 'royalblue': ( 0.25490196078431371, - 0.41176470588235292, - 0.88235294117647056, - 1.0), - 'royalblue1': (0.28235294117647058, 0.46274509803921571, 1.0, 1.0), - 'royalblue2': ( 0.2627450980392157, - 0.43137254901960786, - 0.93333333333333335, - 1.0), - 'royalblue3': ( 0.22745098039215686, - 0.37254901960784315, - 0.80392156862745101, - 1.0), - 'royalblue4': ( 0.15294117647058825, - 0.25098039215686274, - 0.54509803921568623, - 1.0), - 'saddle brown': ( 0.54509803921568623, - 0.27058823529411763, - 0.074509803921568626, - 1.0), - 'saddlebrown': ( 0.54509803921568623, - 0.27058823529411763, - 0.074509803921568626, - 1.0), - 'salmon': ( 0.98039215686274506, - 0.50196078431372548, - 0.44705882352941179, - 1.0), - 'salmon1': (1.0, 0.5490196078431373, 0.41176470588235292, 1.0), - 'salmon2': ( 0.93333333333333335, - 0.50980392156862742, - 0.3843137254901961, - 1.0), - 'salmon3': ( 0.80392156862745101, - 0.4392156862745098, - 0.32941176470588235, - 1.0), - 'salmon4': ( 0.54509803921568623, - 0.29803921568627451, - 0.22352941176470589, - 1.0), - 'sandy brown': ( 0.95686274509803926, - 0.64313725490196083, - 0.37647058823529411, - 1.0), - 'sandybrown': ( 0.95686274509803926, - 0.64313725490196083, - 0.37647058823529411, - 1.0), - 'sea green': ( 0.1803921568627451, - 0.54509803921568623, - 0.3411764705882353, - 1.0), - 'seagreen': ( 0.1803921568627451, - 0.54509803921568623, - 0.3411764705882353, - 1.0), - 'seagreen1': (0.32941176470588235, 1.0, 0.62352941176470589, 1.0), - 'seagreen2': ( 0.30588235294117649, - 0.93333333333333335, - 0.58039215686274515, - 1.0), - 'seagreen3': ( 0.2627450980392157, - 0.80392156862745101, - 0.50196078431372548, - 1.0), - 'seagreen4': ( 0.1803921568627451, - 0.54509803921568623, - 0.3411764705882353, - 1.0), - 'seashell': (1.0, 0.96078431372549022, 0.93333333333333335, 1.0), - 'seashell1': (1.0, 0.96078431372549022, 0.93333333333333335, 1.0), - 'seashell2': ( 0.93333333333333335, - 0.89803921568627454, - 0.87058823529411766, - 1.0), - 'seashell3': ( 0.80392156862745101, - 0.77254901960784317, - 0.74901960784313726, - 1.0), - 'seashell4': ( 0.54509803921568623, - 0.52549019607843139, - 0.50980392156862742, - 1.0), - 'sienna': ( 0.62745098039215685, - 0.32156862745098042, - 0.17647058823529413, - 1.0), - 'sienna1': (1.0, 0.50980392156862742, 0.27843137254901962, 1.0), - 'sienna2': ( 0.93333333333333335, - 0.47450980392156861, - 0.25882352941176473, - 1.0), - 'sienna3': ( 0.80392156862745101, - 0.40784313725490196, - 0.22352941176470589, - 1.0), - 'sienna4': ( 0.54509803921568623, - 0.27843137254901962, - 0.14901960784313725, - 1.0), - 'silver': (0.75, 0.75, 0.75, 1.0), - 'sky blue': ( 0.52941176470588236, - 0.80784313725490198, - 0.92156862745098034, - 1.0), - 'skyblue': ( 0.52941176470588236, - 0.80784313725490198, - 0.92156862745098034, - 1.0), - 'skyblue1': (0.52941176470588236, 0.80784313725490198, 1.0, 1.0), - 'skyblue2': ( 0.49411764705882355, - 0.75294117647058822, - 0.93333333333333335, - 1.0), - 'skyblue3': ( 0.42352941176470588, - 0.65098039215686276, - 0.80392156862745101, - 1.0), - 'skyblue4': ( 0.29019607843137257, - 0.4392156862745098, - 0.54509803921568623, - 1.0), - 'slate blue': ( 0.41568627450980394, - 0.35294117647058826, - 0.80392156862745101, - 1.0), - 'slate gray': ( 0.4392156862745098, - 0.50196078431372548, - 0.56470588235294117, - 1.0), - 'slate grey': ( 0.4392156862745098, - 0.50196078431372548, - 0.56470588235294117, - 1.0), - 'slateblue': ( 0.41568627450980394, - 0.35294117647058826, - 0.80392156862745101, - 1.0), - 'slateblue1': (0.51372549019607838, 0.43529411764705883, 1.0, 1.0), - 'slateblue2': ( 0.47843137254901963, - 0.40392156862745099, - 0.93333333333333335, - 1.0), - 'slateblue3': ( 0.41176470588235292, - 0.34901960784313724, - 0.80392156862745101, - 1.0), - 'slateblue4': ( 0.27843137254901962, - 0.23529411764705882, - 0.54509803921568623, - 1.0), - 'slategray': ( 0.4392156862745098, - 0.50196078431372548, - 0.56470588235294117, - 1.0), - 'slategray1': (0.77647058823529413, 0.88627450980392153, 1.0, 1.0), - 'slategray2': ( 0.72549019607843135, - 0.82745098039215681, - 0.93333333333333335, - 1.0), - 'slategray3': ( 0.62352941176470589, - 0.71372549019607845, - 0.80392156862745101, - 1.0), - 'slategray4': ( 0.42352941176470588, - 0.4823529411764706, - 0.54509803921568623, - 1.0), - 'slategrey': ( 0.4392156862745098, - 0.50196078431372548, - 0.56470588235294117, - 1.0), - 'snow': (1.0, 0.98039215686274506, 0.98039215686274506, 1.0), - 'snow1': (1.0, 0.98039215686274506, 0.98039215686274506, 1.0), - 'snow2': ( 0.93333333333333335, - 0.9137254901960784, - 0.9137254901960784, - 1.0), - 'snow3': ( 0.80392156862745101, - 0.78823529411764703, - 0.78823529411764703, - 1.0), - 'snow4': ( 0.54509803921568623, - 0.53725490196078429, - 0.53725490196078429, - 1.0), - 'spring green': (0.0, 1.0, 0.49803921568627452, 1.0), - 'springgreen': (0.0, 1.0, 0.49803921568627452, 1.0), - 'springgreen1': (0.0, 1.0, 0.49803921568627452, 1.0), - 'springgreen2': (0.0, 0.93333333333333335, 0.46274509803921571, 1.0), - 'springgreen3': (0.0, 0.80392156862745101, 0.40000000000000002, 1.0), - 'springgreen4': (0.0, 0.54509803921568623, 0.27058823529411763, 1.0), - 'steel blue': ( 0.27450980392156865, - 0.50980392156862742, - 0.70588235294117652, - 1.0), - 'steelblue': ( 0.27450980392156865, - 0.50980392156862742, - 0.70588235294117652, - 1.0), - 'steelblue1': (0.38823529411764707, 0.72156862745098038, 1.0, 1.0), - 'steelblue2': ( 0.36078431372549019, - 0.67450980392156867, - 0.93333333333333335, - 1.0), - 'steelblue3': ( 0.30980392156862746, - 0.58039215686274515, - 0.80392156862745101, - 1.0), - 'steelblue4': ( 0.21176470588235294, - 0.39215686274509803, - 0.54509803921568623, - 1.0), - 'tan': (0.82352941176470584, 0.70588235294117652, 0.5490196078431373, 1.0), - 'tan1': (1.0, 0.6470588235294118, 0.30980392156862746, 1.0), - 'tan2': ( 0.93333333333333335, - 0.60392156862745094, - 0.28627450980392155, - 1.0), - 'tan3': ( 0.80392156862745101, - 0.52156862745098043, - 0.24705882352941178, - 1.0), - 'tan4': ( 0.54509803921568623, - 0.35294117647058826, - 0.16862745098039217, - 1.0), - 'teal': (0.0, 0.5, 0.5, 1.0), - 'thistle': ( 0.84705882352941175, - 0.74901960784313726, - 0.84705882352941175, - 1.0), - 'thistle1': (1.0, 0.88235294117647056, 1.0, 1.0), - 'thistle2': ( 0.93333333333333335, - 0.82352941176470584, - 0.93333333333333335, - 1.0), - 'thistle3': ( 0.80392156862745101, - 0.70980392156862748, - 0.80392156862745101, - 1.0), - 'thistle4': ( 0.54509803921568623, - 0.4823529411764706, - 0.54509803921568623, - 1.0), - 'tomato': (1.0, 0.38823529411764707, 0.27843137254901962, 1.0), - 'tomato1': (1.0, 0.38823529411764707, 0.27843137254901962, 1.0), - 'tomato2': ( 0.93333333333333335, - 0.36078431372549019, - 0.25882352941176473, - 1.0), - 'tomato3': ( 0.80392156862745101, - 0.30980392156862746, - 0.22352941176470589, - 1.0), - 'tomato4': ( 0.54509803921568623, - 0.21176470588235294, - 0.14901960784313725, - 1.0), - 'turquoise': ( 0.25098039215686274, - 0.8784313725490196, - 0.81568627450980391, - 1.0), - 'turquoise1': (0.0, 0.96078431372549022, 1.0, 1.0), - 'turquoise2': (0.0, 0.89803921568627454, 0.93333333333333335, 1.0), - 'turquoise3': (0.0, 0.77254901960784317, 0.80392156862745101, 1.0), - 'turquoise4': (0.0, 0.52549019607843139, 0.54509803921568623, 1.0), - 'violet': ( 0.93333333333333335, - 0.50980392156862742, - 0.93333333333333335, - 1.0), - 'violet red': ( 0.81568627450980391, - 0.12549019607843137, - 0.56470588235294117, - 1.0), - 'violetred': ( 0.81568627450980391, - 0.12549019607843137, - 0.56470588235294117, - 1.0), - 'violetred1': (1.0, 0.24313725490196078, 0.58823529411764708, 1.0), - 'violetred2': ( 0.93333333333333335, - 0.22745098039215686, - 0.5490196078431373, - 1.0), - 'violetred3': ( 0.80392156862745101, - 0.19607843137254902, - 0.47058823529411764, - 1.0), - 'violetred4': ( 0.54509803921568623, - 0.13333333333333333, - 0.32156862745098042, - 1.0), - 'web gray': ( 0.5019607843137255, - 0.5019607843137255, - 0.5019607843137255, - 1.0), - 'webgray': ( 0.5019607843137255, - 0.5019607843137255, - 0.5019607843137255, - 1.0), - 'web green': (0.0, 0.5019607843137255, 0.0, 1.0), - 'webgreen': (0.0, 0.5019607843137255, 0.0, 1.0), - 'webgray': ( 0.5019607843137255, - 0.5019607843137255, - 0.5019607843137255, - 1.0), - 'web grey': ( 0.5019607843137255, - 0.5019607843137255, - 0.5019607843137255, - 1.0), - 'webgrey': ( 0.5019607843137255, - 0.5019607843137255, - 0.5019607843137255, - 1.0), - 'web maroon': (0.5019607843137255, 0.0, 0.0, 1.0), - 'webmaroon': (0.5019607843137255, 0.0, 0.0, 1.0), - 'web purple': ( 0.4980392156862745, - 0.0, - 0.4980392156862745, - 1.0), - 'webpurple': ( 0.4980392156862745, - 0.0, - 0.4980392156862745, - 1.0), - 'wheat': ( 0.96078431372549022, - 0.87058823529411766, - 0.70196078431372544, - 1.0), - 'wheat1': (1.0, 0.90588235294117647, 0.72941176470588232, 1.0), - 'wheat2': ( 0.93333333333333335, - 0.84705882352941175, - 0.68235294117647061, - 1.0), - 'wheat3': ( 0.80392156862745101, - 0.72941176470588232, - 0.58823529411764708, - 1.0), - 'wheat4': ( 0.54509803921568623, - 0.49411764705882355, - 0.40000000000000002, - 1.0), - 'white': (1.0, 1.0, 1.0, 1.0), - 'white smoke': ( 0.96078431372549022, - 0.96078431372549022, - 0.96078431372549022, - 1.0), - 'whitesmoke': ( 0.96078431372549022, - 0.96078431372549022, - 0.96078431372549022, - 1.0), - 'yellow': (1.0, 1.0, 0.0, 1.0), - 'yellow green': ( 0.60392156862745094, - 0.80392156862745101, - 0.19607843137254902, - 1.0), - 'yellow1': (1.0, 1.0, 0.0, 1.0), - 'yellow2': (0.93333333333333335, 0.93333333333333335, 0.0, 1.0), - 'yellow3': (0.80392156862745101, 0.80392156862745101, 0.0, 1.0), - 'yellow4': (0.54509803921568623, 0.54509803921568623, 0.0, 1.0), - 'yellowgreen': ( 0.60392156862745094, - 0.80392156862745101, - 0.19607843137254902, - 1.0)} + return ( + red + (1.0 - red) * ratio, + green + (1.0 - green) * ratio, + blue + (1.0 - blue) * ratio, + alpha, + ) + + +known_colors = { + "alice blue": (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), + "aliceblue": (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), + "antique white": ( + 0.98039215686274506, + 0.92156862745098034, + 0.84313725490196079, + 1.0, + ), + "antiquewhite": ( + 0.98039215686274506, + 0.92156862745098034, + 0.84313725490196079, + 1.0, + ), + "antiquewhite1": (1.0, 0.93725490196078431, 0.85882352941176465, 1.0), + "antiquewhite2": ( + 0.93333333333333335, + 0.87450980392156863, + 0.80000000000000004, + 1.0, + ), + "antiquewhite3": ( + 0.80392156862745101, + 0.75294117647058822, + 0.69019607843137254, + 1.0, + ), + "antiquewhite4": ( + 0.54509803921568623, + 0.51372549019607838, + 0.47058823529411764, + 1.0, + ), + "aqua": (0.0, 1.0, 1.0, 1.0), + "aquamarine": (0.49803921568627452, 1.0, 0.83137254901960789, 1.0), + "aquamarine1": (0.49803921568627452, 1.0, 0.83137254901960789, 1.0), + "aquamarine2": (0.46274509803921571, 0.93333333333333335, 0.77647058823529413, 1.0), + "aquamarine3": (0.40000000000000002, 0.80392156862745101, 0.66666666666666663, 1.0), + "aquamarine4": (0.27058823529411763, 0.54509803921568623, 0.45490196078431372, 1.0), + "azure": (0.94117647058823528, 1.0, 1.0, 1.0), + "azure1": (0.94117647058823528, 1.0, 1.0, 1.0), + "azure2": (0.8784313725490196, 0.93333333333333335, 0.93333333333333335, 1.0), + "azure3": (0.75686274509803919, 0.80392156862745101, 0.80392156862745101, 1.0), + "azure4": (0.51372549019607838, 0.54509803921568623, 0.54509803921568623, 1.0), + "beige": (0.96078431372549022, 0.96078431372549022, 0.86274509803921573, 1.0), + "bisque": (1.0, 0.89411764705882357, 0.7686274509803922, 1.0), + "bisque1": (1.0, 0.89411764705882357, 0.7686274509803922, 1.0), + "bisque2": (0.93333333333333335, 0.83529411764705885, 0.71764705882352942, 1.0), + "bisque3": (0.80392156862745101, 0.71764705882352942, 0.61960784313725492, 1.0), + "bisque4": (0.54509803921568623, 0.49019607843137253, 0.41960784313725491, 1.0), + "black": (0.0, 0.0, 0.0, 1.0), + "blanched almond": (1.0, 0.92156862745098034, 0.80392156862745101, 1.0), + "blanchedalmond": (1.0, 0.92156862745098034, 0.80392156862745101, 1.0), + "blue": (0.0, 0.0, 1.0, 1.0), + "blue violet": (0.54117647058823526, 0.16862745098039217, 0.88627450980392153, 1.0), + "blue1": (0.0, 0.0, 1.0, 1.0), + "blue2": (0.0, 0.0, 0.93333333333333335, 1.0), + "blue3": (0.0, 0.0, 0.80392156862745101, 1.0), + "blue4": (0.0, 0.0, 0.54509803921568623, 1.0), + "blueviolet": (0.54117647058823526, 0.16862745098039217, 0.88627450980392153, 1.0), + "brown": (0.6470588235294118, 0.16470588235294117, 0.16470588235294117, 1.0), + "brown1": (1.0, 0.25098039215686274, 0.25098039215686274, 1.0), + "brown2": (0.93333333333333335, 0.23137254901960785, 0.23137254901960785, 1.0), + "brown3": (0.80392156862745101, 0.20000000000000001, 0.20000000000000001, 1.0), + "brown4": (0.54509803921568623, 0.13725490196078433, 0.13725490196078433, 1.0), + "burlywood": (0.87058823529411766, 0.72156862745098038, 0.52941176470588236, 1.0), + "burlywood1": (1.0, 0.82745098039215681, 0.60784313725490191, 1.0), + "burlywood2": (0.93333333333333335, 0.77254901960784317, 0.56862745098039214, 1.0), + "burlywood3": (0.80392156862745101, 0.66666666666666663, 0.49019607843137253, 1.0), + "burlywood4": (0.54509803921568623, 0.45098039215686275, 0.33333333333333331, 1.0), + "cadet blue": (0.37254901960784315, 0.61960784313725492, 0.62745098039215685, 1.0), + "cadetblue": (0.37254901960784315, 0.61960784313725492, 0.62745098039215685, 1.0), + "cadetblue1": (0.59607843137254901, 0.96078431372549022, 1.0, 1.0), + "cadetblue2": (0.55686274509803924, 0.89803921568627454, 0.93333333333333335, 1.0), + "cadetblue3": (0.47843137254901963, 0.77254901960784317, 0.80392156862745101, 1.0), + "cadetblue4": (0.32549019607843138, 0.52549019607843139, 0.54509803921568623, 1.0), + "chartreuse": (0.49803921568627452, 1.0, 0.0, 1.0), + "chartreuse1": (0.49803921568627452, 1.0, 0.0, 1.0), + "chartreuse2": (0.46274509803921571, 0.93333333333333335, 0.0, 1.0), + "chartreuse3": (0.40000000000000002, 0.80392156862745101, 0.0, 1.0), + "chartreuse4": (0.27058823529411763, 0.54509803921568623, 0.0, 1.0), + "chocolate": (0.82352941176470584, 0.41176470588235292, 0.11764705882352941, 1.0), + "chocolate1": (1.0, 0.49803921568627452, 0.14117647058823529, 1.0), + "chocolate2": (0.93333333333333335, 0.46274509803921571, 0.12941176470588237, 1.0), + "chocolate3": (0.80392156862745101, 0.40000000000000002, 0.11372549019607843, 1.0), + "chocolate4": (0.54509803921568623, 0.27058823529411763, 0.074509803921568626, 1.0), + "coral": (1.0, 0.49803921568627452, 0.31372549019607843, 1.0), + "coral1": (1.0, 0.44705882352941179, 0.33725490196078434, 1.0), + "coral2": (0.93333333333333335, 0.41568627450980394, 0.31372549019607843, 1.0), + "coral3": (0.80392156862745101, 0.35686274509803922, 0.27058823529411763, 1.0), + "coral4": (0.54509803921568623, 0.24313725490196078, 0.18431372549019609, 1.0), + "cornflower blue": ( + 0.39215686274509803, + 0.58431372549019611, + 0.92941176470588238, + 1.0, + ), + "cornflowerblue": ( + 0.39215686274509803, + 0.58431372549019611, + 0.92941176470588238, + 1.0, + ), + "cornsilk": (1.0, 0.97254901960784312, 0.86274509803921573, 1.0), + "cornsilk1": (1.0, 0.97254901960784312, 0.86274509803921573, 1.0), + "cornsilk2": (0.93333333333333335, 0.90980392156862744, 0.80392156862745101, 1.0), + "cornsilk3": (0.80392156862745101, 0.78431372549019607, 0.69411764705882351, 1.0), + "cornsilk4": (0.54509803921568623, 0.53333333333333333, 0.47058823529411764, 1.0), + "crimson": (0.8627450980392157, 0.0784313725490196, 0.23529411764705882, 1.0), + "cyan": (0.0, 1.0, 1.0, 1.0), + "cyan1": (0.0, 1.0, 1.0, 1.0), + "cyan2": (0.0, 0.93333333333333335, 0.93333333333333335, 1.0), + "cyan3": (0.0, 0.80392156862745101, 0.80392156862745101, 1.0), + "cyan4": (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), + "dark blue": (0.0, 0.0, 0.54509803921568623, 1.0), + "dark cyan": (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), + "dark goldenrod": ( + 0.72156862745098038, + 0.52549019607843139, + 0.043137254901960784, + 1.0, + ), + "dark gray": (0.66274509803921566, 0.66274509803921566, 0.66274509803921566, 1.0), + "dark green": (0.0, 0.39215686274509803, 0.0, 1.0), + "dark grey": (0.66274509803921566, 0.66274509803921566, 0.66274509803921566, 1.0), + "dark khaki": (0.74117647058823533, 0.71764705882352942, 0.41960784313725491, 1.0), + "dark magenta": (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), + "dark olive green": ( + 0.33333333333333331, + 0.41960784313725491, + 0.18431372549019609, + 1.0, + ), + "dark orange": (1.0, 0.5490196078431373, 0.0, 1.0), + "dark orchid": (0.59999999999999998, 0.19607843137254902, 0.80000000000000004, 1.0), + "dark red": (0.54509803921568623, 0.0, 0.0, 1.0), + "dark salmon": (0.9137254901960784, 0.58823529411764708, 0.47843137254901963, 1.0), + "dark sea green": ( + 0.5607843137254902, + 0.73725490196078436, + 0.5607843137254902, + 1.0, + ), + "dark slate blue": ( + 0.28235294117647058, + 0.23921568627450981, + 0.54509803921568623, + 1.0, + ), + "dark slate gray": ( + 0.18431372549019609, + 0.30980392156862746, + 0.30980392156862746, + 1.0, + ), + "dark slate grey": ( + 0.18431372549019609, + 0.30980392156862746, + 0.30980392156862746, + 1.0, + ), + "dark turquoise": (0.0, 0.80784313725490198, 0.81960784313725488, 1.0), + "dark violet": (0.58039215686274515, 0.0, 0.82745098039215681, 1.0), + "darkblue": (0.0, 0.0, 0.54509803921568623, 1.0), + "darkcyan": (0.0, 0.54509803921568623, 0.54509803921568623, 1.0), + "darkgoldenrod": ( + 0.72156862745098038, + 0.52549019607843139, + 0.043137254901960784, + 1.0, + ), + "darkgoldenrod1": (1.0, 0.72549019607843135, 0.058823529411764705, 1.0), + "darkgoldenrod2": ( + 0.93333333333333335, + 0.67843137254901964, + 0.054901960784313725, + 1.0, + ), + "darkgoldenrod3": ( + 0.80392156862745101, + 0.58431372549019611, + 0.047058823529411764, + 1.0, + ), + "darkgoldenrod4": ( + 0.54509803921568623, + 0.396078431372549, + 0.031372549019607843, + 1.0, + ), + "darkgray": (0.66274509803921566, 0.66274509803921566, 0.66274509803921566, 1.0), + "darkgreen": (0.0, 0.39215686274509803, 0.0, 1.0), + "darkgrey": (0.66274509803921566, 0.66274509803921566, 0.66274509803921566, 1.0), + "darkkhaki": (0.74117647058823533, 0.71764705882352942, 0.41960784313725491, 1.0), + "darkmagenta": (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), + "darkolivegreen": ( + 0.33333333333333331, + 0.41960784313725491, + 0.18431372549019609, + 1.0, + ), + "darkolivegreen1": (0.792156862745098, 1.0, 0.4392156862745098, 1.0), + "darkolivegreen2": ( + 0.73725490196078436, + 0.93333333333333335, + 0.40784313725490196, + 1.0, + ), + "darkolivegreen3": ( + 0.63529411764705879, + 0.80392156862745101, + 0.35294117647058826, + 1.0, + ), + "darkolivegreen4": ( + 0.43137254901960786, + 0.54509803921568623, + 0.23921568627450981, + 1.0, + ), + "darkorange": (1.0, 0.5490196078431373, 0.0, 1.0), + "darkorange1": (1.0, 0.49803921568627452, 0.0, 1.0), + "darkorange2": (0.93333333333333335, 0.46274509803921571, 0.0, 1.0), + "darkorange3": (0.80392156862745101, 0.40000000000000002, 0.0, 1.0), + "darkorange4": (0.54509803921568623, 0.27058823529411763, 0.0, 1.0), + "darkorchid": (0.59999999999999998, 0.19607843137254902, 0.80000000000000004, 1.0), + "darkorchid1": (0.74901960784313726, 0.24313725490196078, 1.0, 1.0), + "darkorchid2": (0.69803921568627447, 0.22745098039215686, 0.93333333333333335, 1.0), + "darkorchid3": (0.60392156862745094, 0.19607843137254902, 0.80392156862745101, 1.0), + "darkorchid4": (0.40784313725490196, 0.13333333333333333, 0.54509803921568623, 1.0), + "darkred": (0.54509803921568623, 0.0, 0.0, 1.0), + "darksalmon": (0.9137254901960784, 0.58823529411764708, 0.47843137254901963, 1.0), + "darkseagreen": (0.5607843137254902, 0.73725490196078436, 0.5607843137254902, 1.0), + "darkseagreen1": (0.75686274509803919, 1.0, 0.75686274509803919, 1.0), + "darkseagreen2": ( + 0.70588235294117652, + 0.93333333333333335, + 0.70588235294117652, + 1.0, + ), + "darkseagreen3": ( + 0.60784313725490191, + 0.80392156862745101, + 0.60784313725490191, + 1.0, + ), + "darkseagreen4": ( + 0.41176470588235292, + 0.54509803921568623, + 0.41176470588235292, + 1.0, + ), + "darkslateblue": ( + 0.28235294117647058, + 0.23921568627450981, + 0.54509803921568623, + 1.0, + ), + "darkslategray": ( + 0.18431372549019609, + 0.30980392156862746, + 0.30980392156862746, + 1.0, + ), + "darkslategray1": (0.59215686274509804, 1.0, 1.0, 1.0), + "darkslategray2": ( + 0.55294117647058827, + 0.93333333333333335, + 0.93333333333333335, + 1.0, + ), + "darkslategray3": ( + 0.47450980392156861, + 0.80392156862745101, + 0.80392156862745101, + 1.0, + ), + "darkslategray4": ( + 0.32156862745098042, + 0.54509803921568623, + 0.54509803921568623, + 1.0, + ), + "darkslategrey": ( + 0.18431372549019609, + 0.30980392156862746, + 0.30980392156862746, + 1.0, + ), + "darkturquoise": (0.0, 0.80784313725490198, 0.81960784313725488, 1.0), + "darkviolet": (0.58039215686274515, 0.0, 0.82745098039215681, 1.0), + "deep pink": (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), + "deep sky blue": (0.0, 0.74901960784313726, 1.0, 1.0), + "deeppink": (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), + "deeppink1": (1.0, 0.078431372549019607, 0.57647058823529407, 1.0), + "deeppink2": (0.93333333333333335, 0.070588235294117646, 0.53725490196078429, 1.0), + "deeppink3": (0.80392156862745101, 0.062745098039215685, 0.46274509803921571, 1.0), + "deeppink4": (0.54509803921568623, 0.039215686274509803, 0.31372549019607843, 1.0), + "deepskyblue": (0.0, 0.74901960784313726, 1.0, 1.0), + "deepskyblue1": (0.0, 0.74901960784313726, 1.0, 1.0), + "deepskyblue2": (0.0, 0.69803921568627447, 0.93333333333333335, 1.0), + "deepskyblue3": (0.0, 0.60392156862745094, 0.80392156862745101, 1.0), + "deepskyblue4": (0.0, 0.40784313725490196, 0.54509803921568623, 1.0), + "dim gray": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "dim grey": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "dimgray": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "dimgrey": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "dodger blue": (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), + "dodgerblue": (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), + "dodgerblue1": (0.11764705882352941, 0.56470588235294117, 1.0, 1.0), + "dodgerblue2": (0.10980392156862745, 0.52549019607843139, 0.93333333333333335, 1.0), + "dodgerblue3": ( + 0.094117647058823528, + 0.45490196078431372, + 0.80392156862745101, + 1.0, + ), + "dodgerblue4": ( + 0.062745098039215685, + 0.30588235294117649, + 0.54509803921568623, + 1.0, + ), + "firebrick": (0.69803921568627447, 0.13333333333333333, 0.13333333333333333, 1.0), + "firebrick1": (1.0, 0.18823529411764706, 0.18823529411764706, 1.0), + "firebrick2": (0.93333333333333335, 0.17254901960784313, 0.17254901960784313, 1.0), + "firebrick3": (0.80392156862745101, 0.14901960784313725, 0.14901960784313725, 1.0), + "firebrick4": (0.54509803921568623, 0.10196078431372549, 0.10196078431372549, 1.0), + "floral white": (1.0, 0.98039215686274506, 0.94117647058823528, 1.0), + "floralwhite": (1.0, 0.98039215686274506, 0.94117647058823528, 1.0), + "forest green": ( + 0.13333333333333333, + 0.54509803921568623, + 0.13333333333333333, + 1.0, + ), + "forestgreen": (0.13333333333333333, 0.54509803921568623, 0.13333333333333333, 1.0), + "fuchsia": (1.0, 0.0, 1.0, 1.0), + "gainsboro": (0.86274509803921573, 0.86274509803921573, 0.86274509803921573, 1.0), + "ghost white": (0.97254901960784312, 0.97254901960784312, 1.0, 1.0), + "ghostwhite": (0.97254901960784312, 0.97254901960784312, 1.0, 1.0), + "gold": (1.0, 0.84313725490196079, 0.0, 1.0), + "gold1": (1.0, 0.84313725490196079, 0.0, 1.0), + "gold2": (0.93333333333333335, 0.78823529411764703, 0.0, 1.0), + "gold3": (0.80392156862745101, 0.67843137254901964, 0.0, 1.0), + "gold4": (0.54509803921568623, 0.45882352941176469, 0.0, 1.0), + "goldenrod": (0.85490196078431369, 0.6470588235294118, 0.12549019607843137, 1.0), + "goldenrod1": (1.0, 0.75686274509803919, 0.14509803921568629, 1.0), + "goldenrod2": (0.93333333333333335, 0.70588235294117652, 0.13333333333333333, 1.0), + "goldenrod3": (0.80392156862745101, 0.60784313725490191, 0.11372549019607843, 1.0), + "goldenrod4": (0.54509803921568623, 0.41176470588235292, 0.078431372549019607, 1.0), + "gray": (0.74509803921568629, 0.74509803921568629, 0.74509803921568629, 1.0), + "gray0": (0.0, 0.0, 0.0, 1.0), + "gray1": (0.011764705882352941, 0.011764705882352941, 0.011764705882352941, 1.0), + "gray10": (0.10196078431372549, 0.10196078431372549, 0.10196078431372549, 1.0), + "gray100": (1.0, 1.0, 1.0, 1.0), + "gray11": (0.10980392156862745, 0.10980392156862745, 0.10980392156862745, 1.0), + "gray12": (0.12156862745098039, 0.12156862745098039, 0.12156862745098039, 1.0), + "gray13": (0.12941176470588237, 0.12941176470588237, 0.12941176470588237, 1.0), + "gray14": (0.14117647058823529, 0.14117647058823529, 0.14117647058823529, 1.0), + "gray15": (0.14901960784313725, 0.14901960784313725, 0.14901960784313725, 1.0), + "gray16": (0.16078431372549021, 0.16078431372549021, 0.16078431372549021, 1.0), + "gray17": (0.16862745098039217, 0.16862745098039217, 0.16862745098039217, 1.0), + "gray18": (0.1803921568627451, 0.1803921568627451, 0.1803921568627451, 1.0), + "gray19": (0.18823529411764706, 0.18823529411764706, 0.18823529411764706, 1.0), + "gray2": (0.019607843137254902, 0.019607843137254902, 0.019607843137254902, 1.0), + "gray20": (0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 1.0), + "gray21": (0.21176470588235294, 0.21176470588235294, 0.21176470588235294, 1.0), + "gray22": (0.2196078431372549, 0.2196078431372549, 0.2196078431372549, 1.0), + "gray23": (0.23137254901960785, 0.23137254901960785, 0.23137254901960785, 1.0), + "gray24": (0.23921568627450981, 0.23921568627450981, 0.23921568627450981, 1.0), + "gray25": (0.25098039215686274, 0.25098039215686274, 0.25098039215686274, 1.0), + "gray26": (0.25882352941176473, 0.25882352941176473, 0.25882352941176473, 1.0), + "gray27": (0.27058823529411763, 0.27058823529411763, 0.27058823529411763, 1.0), + "gray28": (0.27843137254901962, 0.27843137254901962, 0.27843137254901962, 1.0), + "gray29": (0.29019607843137257, 0.29019607843137257, 0.29019607843137257, 1.0), + "gray3": (0.031372549019607843, 0.031372549019607843, 0.031372549019607843, 1.0), + "gray30": (0.30196078431372547, 0.30196078431372547, 0.30196078431372547, 1.0), + "gray31": (0.30980392156862746, 0.30980392156862746, 0.30980392156862746, 1.0), + "gray32": (0.32156862745098042, 0.32156862745098042, 0.32156862745098042, 1.0), + "gray33": (0.32941176470588235, 0.32941176470588235, 0.32941176470588235, 1.0), + "gray34": (0.3411764705882353, 0.3411764705882353, 0.3411764705882353, 1.0), + "gray35": (0.34901960784313724, 0.34901960784313724, 0.34901960784313724, 1.0), + "gray36": (0.36078431372549019, 0.36078431372549019, 0.36078431372549019, 1.0), + "gray37": (0.36862745098039218, 0.36862745098039218, 0.36862745098039218, 1.0), + "gray38": (0.38039215686274508, 0.38039215686274508, 0.38039215686274508, 1.0), + "gray39": (0.38823529411764707, 0.38823529411764707, 0.38823529411764707, 1.0), + "gray4": (0.039215686274509803, 0.039215686274509803, 0.039215686274509803, 1.0), + "gray40": (0.40000000000000002, 0.40000000000000002, 0.40000000000000002, 1.0), + "gray41": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "gray42": (0.41960784313725491, 0.41960784313725491, 0.41960784313725491, 1.0), + "gray43": (0.43137254901960786, 0.43137254901960786, 0.43137254901960786, 1.0), + "gray44": (0.4392156862745098, 0.4392156862745098, 0.4392156862745098, 1.0), + "gray45": (0.45098039215686275, 0.45098039215686275, 0.45098039215686275, 1.0), + "gray46": (0.45882352941176469, 0.45882352941176469, 0.45882352941176469, 1.0), + "gray47": (0.47058823529411764, 0.47058823529411764, 0.47058823529411764, 1.0), + "gray48": (0.47843137254901963, 0.47843137254901963, 0.47843137254901963, 1.0), + "gray49": (0.49019607843137253, 0.49019607843137253, 0.49019607843137253, 1.0), + "gray5": (0.050980392156862744, 0.050980392156862744, 0.050980392156862744, 1.0), + "gray50": (0.49803921568627452, 0.49803921568627452, 0.49803921568627452, 1.0), + "gray51": (0.50980392156862742, 0.50980392156862742, 0.50980392156862742, 1.0), + "gray52": (0.52156862745098043, 0.52156862745098043, 0.52156862745098043, 1.0), + "gray53": (0.52941176470588236, 0.52941176470588236, 0.52941176470588236, 1.0), + "gray54": (0.54117647058823526, 0.54117647058823526, 0.54117647058823526, 1.0), + "gray55": (0.5490196078431373, 0.5490196078431373, 0.5490196078431373, 1.0), + "gray56": (0.5607843137254902, 0.5607843137254902, 0.5607843137254902, 1.0), + "gray57": (0.56862745098039214, 0.56862745098039214, 0.56862745098039214, 1.0), + "gray58": (0.58039215686274515, 0.58039215686274515, 0.58039215686274515, 1.0), + "gray59": (0.58823529411764708, 0.58823529411764708, 0.58823529411764708, 1.0), + "gray6": (0.058823529411764705, 0.058823529411764705, 0.058823529411764705, 1.0), + "gray60": (0.59999999999999998, 0.59999999999999998, 0.59999999999999998, 1.0), + "gray61": (0.61176470588235299, 0.61176470588235299, 0.61176470588235299, 1.0), + "gray62": (0.61960784313725492, 0.61960784313725492, 0.61960784313725492, 1.0), + "gray63": (0.63137254901960782, 0.63137254901960782, 0.63137254901960782, 1.0), + "gray64": (0.63921568627450975, 0.63921568627450975, 0.63921568627450975, 1.0), + "gray65": (0.65098039215686276, 0.65098039215686276, 0.65098039215686276, 1.0), + "gray66": (0.6588235294117647, 0.6588235294117647, 0.6588235294117647, 1.0), + "gray67": (0.6705882352941176, 0.6705882352941176, 0.6705882352941176, 1.0), + "gray68": (0.67843137254901964, 0.67843137254901964, 0.67843137254901964, 1.0), + "gray69": (0.69019607843137254, 0.69019607843137254, 0.69019607843137254, 1.0), + "gray7": (0.070588235294117646, 0.070588235294117646, 0.070588235294117646, 1.0), + "gray70": (0.70196078431372544, 0.70196078431372544, 0.70196078431372544, 1.0), + "gray71": (0.70980392156862748, 0.70980392156862748, 0.70980392156862748, 1.0), + "gray72": (0.72156862745098038, 0.72156862745098038, 0.72156862745098038, 1.0), + "gray73": (0.72941176470588232, 0.72941176470588232, 0.72941176470588232, 1.0), + "gray74": (0.74117647058823533, 0.74117647058823533, 0.74117647058823533, 1.0), + "gray75": (0.74901960784313726, 0.74901960784313726, 0.74901960784313726, 1.0), + "gray76": (0.76078431372549016, 0.76078431372549016, 0.76078431372549016, 1.0), + "gray77": (0.7686274509803922, 0.7686274509803922, 0.7686274509803922, 1.0), + "gray78": (0.7803921568627451, 0.7803921568627451, 0.7803921568627451, 1.0), + "gray79": (0.78823529411764703, 0.78823529411764703, 0.78823529411764703, 1.0), + "gray8": (0.078431372549019607, 0.078431372549019607, 0.078431372549019607, 1.0), + "gray80": (0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1.0), + "gray81": (0.81176470588235294, 0.81176470588235294, 0.81176470588235294, 1.0), + "gray82": (0.81960784313725488, 0.81960784313725488, 0.81960784313725488, 1.0), + "gray83": (0.83137254901960789, 0.83137254901960789, 0.83137254901960789, 1.0), + "gray84": (0.83921568627450982, 0.83921568627450982, 0.83921568627450982, 1.0), + "gray85": (0.85098039215686272, 0.85098039215686272, 0.85098039215686272, 1.0), + "gray86": (0.85882352941176465, 0.85882352941176465, 0.85882352941176465, 1.0), + "gray87": (0.87058823529411766, 0.87058823529411766, 0.87058823529411766, 1.0), + "gray88": (0.8784313725490196, 0.8784313725490196, 0.8784313725490196, 1.0), + "gray89": (0.8901960784313725, 0.8901960784313725, 0.8901960784313725, 1.0), + "gray9": (0.090196078431372548, 0.090196078431372548, 0.090196078431372548, 1.0), + "gray90": (0.89803921568627454, 0.89803921568627454, 0.89803921568627454, 1.0), + "gray91": (0.90980392156862744, 0.90980392156862744, 0.90980392156862744, 1.0), + "gray92": (0.92156862745098034, 0.92156862745098034, 0.92156862745098034, 1.0), + "gray93": (0.92941176470588238, 0.92941176470588238, 0.92941176470588238, 1.0), + "gray94": (0.94117647058823528, 0.94117647058823528, 0.94117647058823528, 1.0), + "gray95": (0.94901960784313721, 0.94901960784313721, 0.94901960784313721, 1.0), + "gray96": (0.96078431372549022, 0.96078431372549022, 0.96078431372549022, 1.0), + "gray97": (0.96862745098039216, 0.96862745098039216, 0.96862745098039216, 1.0), + "gray98": (0.98039215686274506, 0.98039215686274506, 0.98039215686274506, 1.0), + "gray99": (0.9882352941176471, 0.9882352941176471, 0.9882352941176471, 1.0), + "green": (0.0, 1.0, 0.0, 1.0), + "green yellow": (0.67843137254901964, 1.0, 0.18431372549019609, 1.0), + "green1": (0.0, 1.0, 0.0, 1.0), + "green2": (0.0, 0.93333333333333335, 0.0, 1.0), + "green3": (0.0, 0.80392156862745101, 0.0, 1.0), + "green4": (0.0, 0.54509803921568623, 0.0, 1.0), + "greenyellow": (0.67843137254901964, 1.0, 0.18431372549019609, 1.0), + "grey": (0.74509803921568629, 0.74509803921568629, 0.74509803921568629, 1.0), + "grey0": (0.0, 0.0, 0.0, 1.0), + "grey1": (0.011764705882352941, 0.011764705882352941, 0.011764705882352941, 1.0), + "grey10": (0.10196078431372549, 0.10196078431372549, 0.10196078431372549, 1.0), + "grey100": (1.0, 1.0, 1.0, 1.0), + "grey11": (0.10980392156862745, 0.10980392156862745, 0.10980392156862745, 1.0), + "grey12": (0.12156862745098039, 0.12156862745098039, 0.12156862745098039, 1.0), + "grey13": (0.12941176470588237, 0.12941176470588237, 0.12941176470588237, 1.0), + "grey14": (0.14117647058823529, 0.14117647058823529, 0.14117647058823529, 1.0), + "grey15": (0.14901960784313725, 0.14901960784313725, 0.14901960784313725, 1.0), + "grey16": (0.16078431372549021, 0.16078431372549021, 0.16078431372549021, 1.0), + "grey17": (0.16862745098039217, 0.16862745098039217, 0.16862745098039217, 1.0), + "grey18": (0.1803921568627451, 0.1803921568627451, 0.1803921568627451, 1.0), + "grey19": (0.18823529411764706, 0.18823529411764706, 0.18823529411764706, 1.0), + "grey2": (0.019607843137254902, 0.019607843137254902, 0.019607843137254902, 1.0), + "grey20": (0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 1.0), + "grey21": (0.21176470588235294, 0.21176470588235294, 0.21176470588235294, 1.0), + "grey22": (0.2196078431372549, 0.2196078431372549, 0.2196078431372549, 1.0), + "grey23": (0.23137254901960785, 0.23137254901960785, 0.23137254901960785, 1.0), + "grey24": (0.23921568627450981, 0.23921568627450981, 0.23921568627450981, 1.0), + "grey25": (0.25098039215686274, 0.25098039215686274, 0.25098039215686274, 1.0), + "grey26": (0.25882352941176473, 0.25882352941176473, 0.25882352941176473, 1.0), + "grey27": (0.27058823529411763, 0.27058823529411763, 0.27058823529411763, 1.0), + "grey28": (0.27843137254901962, 0.27843137254901962, 0.27843137254901962, 1.0), + "grey29": (0.29019607843137257, 0.29019607843137257, 0.29019607843137257, 1.0), + "grey3": (0.031372549019607843, 0.031372549019607843, 0.031372549019607843, 1.0), + "grey30": (0.30196078431372547, 0.30196078431372547, 0.30196078431372547, 1.0), + "grey31": (0.30980392156862746, 0.30980392156862746, 0.30980392156862746, 1.0), + "grey32": (0.32156862745098042, 0.32156862745098042, 0.32156862745098042, 1.0), + "grey33": (0.32941176470588235, 0.32941176470588235, 0.32941176470588235, 1.0), + "grey34": (0.3411764705882353, 0.3411764705882353, 0.3411764705882353, 1.0), + "grey35": (0.34901960784313724, 0.34901960784313724, 0.34901960784313724, 1.0), + "grey36": (0.36078431372549019, 0.36078431372549019, 0.36078431372549019, 1.0), + "grey37": (0.36862745098039218, 0.36862745098039218, 0.36862745098039218, 1.0), + "grey38": (0.38039215686274508, 0.38039215686274508, 0.38039215686274508, 1.0), + "grey39": (0.38823529411764707, 0.38823529411764707, 0.38823529411764707, 1.0), + "grey4": (0.039215686274509803, 0.039215686274509803, 0.039215686274509803, 1.0), + "grey40": (0.40000000000000002, 0.40000000000000002, 0.40000000000000002, 1.0), + "grey41": (0.41176470588235292, 0.41176470588235292, 0.41176470588235292, 1.0), + "grey42": (0.41960784313725491, 0.41960784313725491, 0.41960784313725491, 1.0), + "grey43": (0.43137254901960786, 0.43137254901960786, 0.43137254901960786, 1.0), + "grey44": (0.4392156862745098, 0.4392156862745098, 0.4392156862745098, 1.0), + "grey45": (0.45098039215686275, 0.45098039215686275, 0.45098039215686275, 1.0), + "grey46": (0.45882352941176469, 0.45882352941176469, 0.45882352941176469, 1.0), + "grey47": (0.47058823529411764, 0.47058823529411764, 0.47058823529411764, 1.0), + "grey48": (0.47843137254901963, 0.47843137254901963, 0.47843137254901963, 1.0), + "grey49": (0.49019607843137253, 0.49019607843137253, 0.49019607843137253, 1.0), + "grey5": (0.050980392156862744, 0.050980392156862744, 0.050980392156862744, 1.0), + "grey50": (0.49803921568627452, 0.49803921568627452, 0.49803921568627452, 1.0), + "grey51": (0.50980392156862742, 0.50980392156862742, 0.50980392156862742, 1.0), + "grey52": (0.52156862745098043, 0.52156862745098043, 0.52156862745098043, 1.0), + "grey53": (0.52941176470588236, 0.52941176470588236, 0.52941176470588236, 1.0), + "grey54": (0.54117647058823526, 0.54117647058823526, 0.54117647058823526, 1.0), + "grey55": (0.5490196078431373, 0.5490196078431373, 0.5490196078431373, 1.0), + "grey56": (0.5607843137254902, 0.5607843137254902, 0.5607843137254902, 1.0), + "grey57": (0.56862745098039214, 0.56862745098039214, 0.56862745098039214, 1.0), + "grey58": (0.58039215686274515, 0.58039215686274515, 0.58039215686274515, 1.0), + "grey59": (0.58823529411764708, 0.58823529411764708, 0.58823529411764708, 1.0), + "grey6": (0.058823529411764705, 0.058823529411764705, 0.058823529411764705, 1.0), + "grey60": (0.59999999999999998, 0.59999999999999998, 0.59999999999999998, 1.0), + "grey61": (0.61176470588235299, 0.61176470588235299, 0.61176470588235299, 1.0), + "grey62": (0.61960784313725492, 0.61960784313725492, 0.61960784313725492, 1.0), + "grey63": (0.63137254901960782, 0.63137254901960782, 0.63137254901960782, 1.0), + "grey64": (0.63921568627450975, 0.63921568627450975, 0.63921568627450975, 1.0), + "grey65": (0.65098039215686276, 0.65098039215686276, 0.65098039215686276, 1.0), + "grey66": (0.6588235294117647, 0.6588235294117647, 0.6588235294117647, 1.0), + "grey67": (0.6705882352941176, 0.6705882352941176, 0.6705882352941176, 1.0), + "grey68": (0.67843137254901964, 0.67843137254901964, 0.67843137254901964, 1.0), + "grey69": (0.69019607843137254, 0.69019607843137254, 0.69019607843137254, 1.0), + "grey7": (0.070588235294117646, 0.070588235294117646, 0.070588235294117646, 1.0), + "grey70": (0.70196078431372544, 0.70196078431372544, 0.70196078431372544, 1.0), + "grey71": (0.70980392156862748, 0.70980392156862748, 0.70980392156862748, 1.0), + "grey72": (0.72156862745098038, 0.72156862745098038, 0.72156862745098038, 1.0), + "grey73": (0.72941176470588232, 0.72941176470588232, 0.72941176470588232, 1.0), + "grey74": (0.74117647058823533, 0.74117647058823533, 0.74117647058823533, 1.0), + "grey75": (0.74901960784313726, 0.74901960784313726, 0.74901960784313726, 1.0), + "grey76": (0.76078431372549016, 0.76078431372549016, 0.76078431372549016, 1.0), + "grey77": (0.7686274509803922, 0.7686274509803922, 0.7686274509803922, 1.0), + "grey78": (0.7803921568627451, 0.7803921568627451, 0.7803921568627451, 1.0), + "grey79": (0.78823529411764703, 0.78823529411764703, 0.78823529411764703, 1.0), + "grey8": (0.078431372549019607, 0.078431372549019607, 0.078431372549019607, 1.0), + "grey80": (0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1.0), + "grey81": (0.81176470588235294, 0.81176470588235294, 0.81176470588235294, 1.0), + "grey82": (0.81960784313725488, 0.81960784313725488, 0.81960784313725488, 1.0), + "grey83": (0.83137254901960789, 0.83137254901960789, 0.83137254901960789, 1.0), + "grey84": (0.83921568627450982, 0.83921568627450982, 0.83921568627450982, 1.0), + "grey85": (0.85098039215686272, 0.85098039215686272, 0.85098039215686272, 1.0), + "grey86": (0.85882352941176465, 0.85882352941176465, 0.85882352941176465, 1.0), + "grey87": (0.87058823529411766, 0.87058823529411766, 0.87058823529411766, 1.0), + "grey88": (0.8784313725490196, 0.8784313725490196, 0.8784313725490196, 1.0), + "grey89": (0.8901960784313725, 0.8901960784313725, 0.8901960784313725, 1.0), + "grey9": (0.090196078431372548, 0.090196078431372548, 0.090196078431372548, 1.0), + "grey90": (0.89803921568627454, 0.89803921568627454, 0.89803921568627454, 1.0), + "grey91": (0.90980392156862744, 0.90980392156862744, 0.90980392156862744, 1.0), + "grey92": (0.92156862745098034, 0.92156862745098034, 0.92156862745098034, 1.0), + "grey93": (0.92941176470588238, 0.92941176470588238, 0.92941176470588238, 1.0), + "grey94": (0.94117647058823528, 0.94117647058823528, 0.94117647058823528, 1.0), + "grey95": (0.94901960784313721, 0.94901960784313721, 0.94901960784313721, 1.0), + "grey96": (0.96078431372549022, 0.96078431372549022, 0.96078431372549022, 1.0), + "grey97": (0.96862745098039216, 0.96862745098039216, 0.96862745098039216, 1.0), + "grey98": (0.98039215686274506, 0.98039215686274506, 0.98039215686274506, 1.0), + "grey99": (0.9882352941176471, 0.9882352941176471, 0.9882352941176471, 1.0), + "honeydew": (0.94117647058823528, 1.0, 0.94117647058823528, 1.0), + "honeydew1": (0.94117647058823528, 1.0, 0.94117647058823528, 1.0), + "honeydew2": (0.8784313725490196, 0.93333333333333335, 0.8784313725490196, 1.0), + "honeydew3": (0.75686274509803919, 0.80392156862745101, 0.75686274509803919, 1.0), + "honeydew4": (0.51372549019607838, 0.54509803921568623, 0.51372549019607838, 1.0), + "hot pink": (1.0, 0.41176470588235292, 0.70588235294117652, 1.0), + "hotpink": (1.0, 0.41176470588235292, 0.70588235294117652, 1.0), + "hotpink1": (1.0, 0.43137254901960786, 0.70588235294117652, 1.0), + "hotpink2": (0.93333333333333335, 0.41568627450980394, 0.65490196078431373, 1.0), + "hotpink3": (0.80392156862745101, 0.37647058823529411, 0.56470588235294117, 1.0), + "hotpink4": (0.54509803921568623, 0.22745098039215686, 0.3843137254901961, 1.0), + "indian red": (0.80392156862745101, 0.36078431372549019, 0.36078431372549019, 1.0), + "indianred": (0.80392156862745101, 0.36078431372549019, 0.36078431372549019, 1.0), + "indianred1": (1.0, 0.41568627450980394, 0.41568627450980394, 1.0), + "indianred2": (0.93333333333333335, 0.38823529411764707, 0.38823529411764707, 1.0), + "indianred3": (0.80392156862745101, 0.33333333333333331, 0.33333333333333331, 1.0), + "indianred4": (0.54509803921568623, 0.22745098039215686, 0.22745098039215686, 1.0), + "indigo": (0.29411764705882354, 0.0, 0.5098039215686274, 1.0), + "ivory": (1.0, 1.0, 0.94117647058823528, 1.0), + "ivory1": (1.0, 1.0, 0.94117647058823528, 1.0), + "ivory2": (0.93333333333333335, 0.93333333333333335, 0.8784313725490196, 1.0), + "ivory3": (0.80392156862745101, 0.80392156862745101, 0.75686274509803919, 1.0), + "ivory4": (0.54509803921568623, 0.54509803921568623, 0.51372549019607838, 1.0), + "khaki": (0.94117647058823528, 0.90196078431372551, 0.5490196078431373, 1.0), + "khaki1": (1.0, 0.96470588235294119, 0.5607843137254902, 1.0), + "khaki2": (0.93333333333333335, 0.90196078431372551, 0.52156862745098043, 1.0), + "khaki3": (0.80392156862745101, 0.77647058823529413, 0.45098039215686275, 1.0), + "khaki4": (0.54509803921568623, 0.52549019607843139, 0.30588235294117649, 1.0), + "lavender": (0.90196078431372551, 0.90196078431372551, 0.98039215686274506, 1.0), + "lavender blush": (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), + "lavenderblush": (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), + "lavenderblush1": (1.0, 0.94117647058823528, 0.96078431372549022, 1.0), + "lavenderblush2": ( + 0.93333333333333335, + 0.8784313725490196, + 0.89803921568627454, + 1.0, + ), + "lavenderblush3": ( + 0.80392156862745101, + 0.75686274509803919, + 0.77254901960784317, + 1.0, + ), + "lavenderblush4": ( + 0.54509803921568623, + 0.51372549019607838, + 0.52549019607843139, + 1.0, + ), + "lawn green": (0.48627450980392156, 0.9882352941176471, 0.0, 1.0), + "lawngreen": (0.48627450980392156, 0.9882352941176471, 0.0, 1.0), + "lemon chiffon": (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), + "lemonchiffon": (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), + "lemonchiffon1": (1.0, 0.98039215686274506, 0.80392156862745101, 1.0), + "lemonchiffon2": ( + 0.93333333333333335, + 0.9137254901960784, + 0.74901960784313726, + 1.0, + ), + "lemonchiffon3": ( + 0.80392156862745101, + 0.78823529411764703, + 0.6470588235294118, + 1.0, + ), + "lemonchiffon4": ( + 0.54509803921568623, + 0.53725490196078429, + 0.4392156862745098, + 1.0, + ), + "light blue": (0.67843137254901964, 0.84705882352941175, 0.90196078431372551, 1.0), + "light coral": (0.94117647058823528, 0.50196078431372548, 0.50196078431372548, 1.0), + "light cyan": (0.8784313725490196, 1.0, 1.0, 1.0), + "light goldenrod": ( + 0.93333333333333335, + 0.8666666666666667, + 0.50980392156862742, + 1.0, + ), + "light goldenrod yellow": ( + 0.98039215686274506, + 0.98039215686274506, + 0.82352941176470584, + 1.0, + ), + "light gray": (0.82745098039215681, 0.82745098039215681, 0.82745098039215681, 1.0), + "light green": (0.56470588235294117, 0.93333333333333335, 0.56470588235294117, 1.0), + "light grey": (0.82745098039215681, 0.82745098039215681, 0.82745098039215681, 1.0), + "light pink": (1.0, 0.71372549019607845, 0.75686274509803919, 1.0), + "light salmon": (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), + "light sea green": ( + 0.12549019607843137, + 0.69803921568627447, + 0.66666666666666663, + 1.0, + ), + "light sky blue": ( + 0.52941176470588236, + 0.80784313725490198, + 0.98039215686274506, + 1.0, + ), + "light slate blue": (0.51764705882352946, 0.4392156862745098, 1.0, 1.0), + "light slate gray": ( + 0.46666666666666667, + 0.53333333333333333, + 0.59999999999999998, + 1.0, + ), + "light slate grey": ( + 0.46666666666666667, + 0.53333333333333333, + 0.59999999999999998, + 1.0, + ), + "light steel blue": ( + 0.69019607843137254, + 0.7686274509803922, + 0.87058823529411766, + 1.0, + ), + "light yellow": (1.0, 1.0, 0.8784313725490196, 1.0), + "lightblue": (0.67843137254901964, 0.84705882352941175, 0.90196078431372551, 1.0), + "lightblue1": (0.74901960784313726, 0.93725490196078431, 1.0, 1.0), + "lightblue2": (0.69803921568627447, 0.87450980392156863, 0.93333333333333335, 1.0), + "lightblue3": (0.60392156862745094, 0.75294117647058822, 0.80392156862745101, 1.0), + "lightblue4": (0.40784313725490196, 0.51372549019607838, 0.54509803921568623, 1.0), + "lightcoral": (0.94117647058823528, 0.50196078431372548, 0.50196078431372548, 1.0), + "lightcyan": (0.8784313725490196, 1.0, 1.0, 1.0), + "lightcyan1": (0.8784313725490196, 1.0, 1.0, 1.0), + "lightcyan2": (0.81960784313725488, 0.93333333333333335, 0.93333333333333335, 1.0), + "lightcyan3": (0.70588235294117652, 0.80392156862745101, 0.80392156862745101, 1.0), + "lightcyan4": (0.47843137254901963, 0.54509803921568623, 0.54509803921568623, 1.0), + "lightgoldenrod": ( + 0.93333333333333335, + 0.8666666666666667, + 0.50980392156862742, + 1.0, + ), + "lightgoldenrod1": (1.0, 0.92549019607843142, 0.54509803921568623, 1.0), + "lightgoldenrod2": ( + 0.93333333333333335, + 0.86274509803921573, + 0.50980392156862742, + 1.0, + ), + "lightgoldenrod3": ( + 0.80392156862745101, + 0.74509803921568629, + 0.4392156862745098, + 1.0, + ), + "lightgoldenrod4": ( + 0.54509803921568623, + 0.50588235294117645, + 0.29803921568627451, + 1.0, + ), + "lightgoldenrodyellow": ( + 0.98039215686274506, + 0.98039215686274506, + 0.82352941176470584, + 1.0, + ), + "lightgray": (0.82745098039215681, 0.82745098039215681, 0.82745098039215681, 1.0), + "lightgreen": (0.56470588235294117, 0.93333333333333335, 0.56470588235294117, 1.0), + "lightgrey": (0.82745098039215681, 0.82745098039215681, 0.82745098039215681, 1.0), + "lightpink": (1.0, 0.71372549019607845, 0.75686274509803919, 1.0), + "lightpink1": (1.0, 0.68235294117647061, 0.72549019607843135, 1.0), + "lightpink2": (0.93333333333333335, 0.63529411764705879, 0.67843137254901964, 1.0), + "lightpink3": (0.80392156862745101, 0.5490196078431373, 0.58431372549019611, 1.0), + "lightpink4": (0.54509803921568623, 0.37254901960784315, 0.396078431372549, 1.0), + "lightsalmon": (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), + "lightsalmon1": (1.0, 0.62745098039215685, 0.47843137254901963, 1.0), + "lightsalmon2": ( + 0.93333333333333335, + 0.58431372549019611, + 0.44705882352941179, + 1.0, + ), + "lightsalmon3": (0.80392156862745101, 0.50588235294117645, 0.3843137254901961, 1.0), + "lightsalmon4": (0.54509803921568623, 0.3411764705882353, 0.25882352941176473, 1.0), + "lightseagreen": ( + 0.12549019607843137, + 0.69803921568627447, + 0.66666666666666663, + 1.0, + ), + "lightskyblue": ( + 0.52941176470588236, + 0.80784313725490198, + 0.98039215686274506, + 1.0, + ), + "lightskyblue1": (0.69019607843137254, 0.88627450980392153, 1.0, 1.0), + "lightskyblue2": ( + 0.64313725490196083, + 0.82745098039215681, + 0.93333333333333335, + 1.0, + ), + "lightskyblue3": ( + 0.55294117647058827, + 0.71372549019607845, + 0.80392156862745101, + 1.0, + ), + "lightskyblue4": ( + 0.37647058823529411, + 0.4823529411764706, + 0.54509803921568623, + 1.0, + ), + "lightslateblue": (0.51764705882352946, 0.4392156862745098, 1.0, 1.0), + "lightslategray": ( + 0.46666666666666667, + 0.53333333333333333, + 0.59999999999999998, + 1.0, + ), + "lightslategrey": ( + 0.46666666666666667, + 0.53333333333333333, + 0.59999999999999998, + 1.0, + ), + "lightsteelblue": ( + 0.69019607843137254, + 0.7686274509803922, + 0.87058823529411766, + 1.0, + ), + "lightsteelblue1": (0.792156862745098, 0.88235294117647056, 1.0, 1.0), + "lightsteelblue2": ( + 0.73725490196078436, + 0.82352941176470584, + 0.93333333333333335, + 1.0, + ), + "lightsteelblue3": ( + 0.63529411764705879, + 0.70980392156862748, + 0.80392156862745101, + 1.0, + ), + "lightsteelblue4": ( + 0.43137254901960786, + 0.4823529411764706, + 0.54509803921568623, + 1.0, + ), + "lightyellow": (1.0, 1.0, 0.8784313725490196, 1.0), + "lightyellow1": (1.0, 1.0, 0.8784313725490196, 1.0), + "lightyellow2": ( + 0.93333333333333335, + 0.93333333333333335, + 0.81960784313725488, + 1.0, + ), + "lightyellow3": ( + 0.80392156862745101, + 0.80392156862745101, + 0.70588235294117652, + 1.0, + ), + "lightyellow4": ( + 0.54509803921568623, + 0.54509803921568623, + 0.47843137254901963, + 1.0, + ), + "lime": (0.0, 1.0, 0.0, 1.0), + "lime green": (0.19607843137254902, 0.80392156862745101, 0.19607843137254902, 1.0), + "limegreen": (0.19607843137254902, 0.80392156862745101, 0.19607843137254902, 1.0), + "linen": (0.98039215686274506, 0.94117647058823528, 0.90196078431372551, 1.0), + "magenta": (1.0, 0.0, 1.0, 1.0), + "magenta1": (1.0, 0.0, 1.0, 1.0), + "magenta2": (0.93333333333333335, 0.0, 0.93333333333333335, 1.0), + "magenta3": (0.80392156862745101, 0.0, 0.80392156862745101, 1.0), + "magenta4": (0.54509803921568623, 0.0, 0.54509803921568623, 1.0), + "maroon": (0.69019607843137254, 0.18823529411764706, 0.37647058823529411, 1.0), + "maroon1": (1.0, 0.20392156862745098, 0.70196078431372544, 1.0), + "maroon2": (0.93333333333333335, 0.18823529411764706, 0.65490196078431373, 1.0), + "maroon3": (0.80392156862745101, 0.16078431372549021, 0.56470588235294117, 1.0), + "maroon4": (0.54509803921568623, 0.10980392156862745, 0.3843137254901961, 1.0), + "medium aquamarine": ( + 0.40000000000000002, + 0.80392156862745101, + 0.66666666666666663, + 1.0, + ), + "medium blue": (0.0, 0.0, 0.80392156862745101, 1.0), + "medium orchid": ( + 0.72941176470588232, + 0.33333333333333331, + 0.82745098039215681, + 1.0, + ), + "medium purple": ( + 0.57647058823529407, + 0.4392156862745098, + 0.85882352941176465, + 1.0, + ), + "medium sea green": ( + 0.23529411764705882, + 0.70196078431372544, + 0.44313725490196076, + 1.0, + ), + "medium slate blue": ( + 0.4823529411764706, + 0.40784313725490196, + 0.93333333333333335, + 1.0, + ), + "medium spring green": (0.0, 0.98039215686274506, 0.60392156862745094, 1.0), + "medium turquoise": ( + 0.28235294117647058, + 0.81960784313725488, + 0.80000000000000004, + 1.0, + ), + "medium violet red": ( + 0.7803921568627451, + 0.082352941176470587, + 0.52156862745098043, + 1.0, + ), + "mediumaquamarine": ( + 0.40000000000000002, + 0.80392156862745101, + 0.66666666666666663, + 1.0, + ), + "mediumblue": (0.0, 0.0, 0.80392156862745101, 1.0), + "mediumorchid": ( + 0.72941176470588232, + 0.33333333333333331, + 0.82745098039215681, + 1.0, + ), + "mediumorchid1": (0.8784313725490196, 0.40000000000000002, 1.0, 1.0), + "mediumorchid2": ( + 0.81960784313725488, + 0.37254901960784315, + 0.93333333333333335, + 1.0, + ), + "mediumorchid3": ( + 0.70588235294117652, + 0.32156862745098042, + 0.80392156862745101, + 1.0, + ), + "mediumorchid4": ( + 0.47843137254901963, + 0.21568627450980393, + 0.54509803921568623, + 1.0, + ), + "mediumpurple": (0.57647058823529407, 0.4392156862745098, 0.85882352941176465, 1.0), + "mediumpurple1": (0.6705882352941176, 0.50980392156862742, 1.0, 1.0), + "mediumpurple2": ( + 0.62352941176470589, + 0.47450980392156861, + 0.93333333333333335, + 1.0, + ), + "mediumpurple3": ( + 0.53725490196078429, + 0.40784313725490196, + 0.80392156862745101, + 1.0, + ), + "mediumpurple4": ( + 0.36470588235294116, + 0.27843137254901962, + 0.54509803921568623, + 1.0, + ), + "mediumseagreen": ( + 0.23529411764705882, + 0.70196078431372544, + 0.44313725490196076, + 1.0, + ), + "mediumslateblue": ( + 0.4823529411764706, + 0.40784313725490196, + 0.93333333333333335, + 1.0, + ), + "mediumspringgreen": (0.0, 0.98039215686274506, 0.60392156862745094, 1.0), + "mediumturquoise": ( + 0.28235294117647058, + 0.81960784313725488, + 0.80000000000000004, + 1.0, + ), + "mediumvioletred": ( + 0.7803921568627451, + 0.082352941176470587, + 0.52156862745098043, + 1.0, + ), + "midnight blue": ( + 0.098039215686274508, + 0.098039215686274508, + 0.4392156862745098, + 1.0, + ), + "midnightblue": ( + 0.098039215686274508, + 0.098039215686274508, + 0.4392156862745098, + 1.0, + ), + "mint cream": (0.96078431372549022, 1.0, 0.98039215686274506, 1.0), + "mintcream": (0.96078431372549022, 1.0, 0.98039215686274506, 1.0), + "misty rose": (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), + "mistyrose": (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), + "mistyrose1": (1.0, 0.89411764705882357, 0.88235294117647056, 1.0), + "mistyrose2": (0.93333333333333335, 0.83529411764705885, 0.82352941176470584, 1.0), + "mistyrose3": (0.80392156862745101, 0.71764705882352942, 0.70980392156862748, 1.0), + "mistyrose4": (0.54509803921568623, 0.49019607843137253, 0.4823529411764706, 1.0), + "moccasin": (1.0, 0.89411764705882357, 0.70980392156862748, 1.0), + "navajo white": (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), + "navajowhite": (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), + "navajowhite1": (1.0, 0.87058823529411766, 0.67843137254901964, 1.0), + "navajowhite2": ( + 0.93333333333333335, + 0.81176470588235294, + 0.63137254901960782, + 1.0, + ), + "navajowhite3": ( + 0.80392156862745101, + 0.70196078431372544, + 0.54509803921568623, + 1.0, + ), + "navajowhite4": ( + 0.54509803921568623, + 0.47450980392156861, + 0.36862745098039218, + 1.0, + ), + "navy": (0.0, 0.0, 0.50196078431372548, 1.0), + "navy blue": (0.0, 0.0, 0.50196078431372548, 1.0), + "navyblue": (0.0, 0.0, 0.50196078431372548, 1.0), + "old lace": (0.99215686274509807, 0.96078431372549022, 0.90196078431372551, 1.0), + "oldlace": (0.99215686274509807, 0.96078431372549022, 0.90196078431372551, 1.0), + "olive": (0.5, 0.5, 0.0, 1.0), + "olive drab": (0.41960784313725491, 0.55686274509803924, 0.13725490196078433, 1.0), + "olivedrab": (0.41960784313725491, 0.55686274509803924, 0.13725490196078433, 1.0), + "olivedrab1": (0.75294117647058822, 1.0, 0.24313725490196078, 1.0), + "olivedrab2": (0.70196078431372544, 0.93333333333333335, 0.22745098039215686, 1.0), + "olivedrab3": (0.60392156862745094, 0.80392156862745101, 0.19607843137254902, 1.0), + "olivedrab4": (0.41176470588235292, 0.54509803921568623, 0.13333333333333333, 1.0), + "orange": (1.0, 0.6470588235294118, 0.0, 1.0), + "orange red": (1.0, 0.27058823529411763, 0.0, 1.0), + "orange1": (1.0, 0.6470588235294118, 0.0, 1.0), + "orange2": (0.93333333333333335, 0.60392156862745094, 0.0, 1.0), + "orange3": (0.80392156862745101, 0.52156862745098043, 0.0, 1.0), + "orange4": (0.54509803921568623, 0.35294117647058826, 0.0, 1.0), + "orangered": (1.0, 0.27058823529411763, 0.0, 1.0), + "orangered1": (1.0, 0.27058823529411763, 0.0, 1.0), + "orangered2": (0.93333333333333335, 0.25098039215686274, 0.0, 1.0), + "orangered3": (0.80392156862745101, 0.21568627450980393, 0.0, 1.0), + "orangered4": (0.54509803921568623, 0.14509803921568629, 0.0, 1.0), + "orchid": (0.85490196078431369, 0.4392156862745098, 0.83921568627450982, 1.0), + "orchid1": (1.0, 0.51372549019607838, 0.98039215686274506, 1.0), + "orchid2": (0.93333333333333335, 0.47843137254901963, 0.9137254901960784, 1.0), + "orchid3": (0.80392156862745101, 0.41176470588235292, 0.78823529411764703, 1.0), + "orchid4": (0.54509803921568623, 0.27843137254901962, 0.53725490196078429, 1.0), + "pale goldenrod": ( + 0.93333333333333335, + 0.90980392156862744, + 0.66666666666666663, + 1.0, + ), + "pale green": (0.59607843137254901, 0.98431372549019602, 0.59607843137254901, 1.0), + "pale turquoise": ( + 0.68627450980392157, + 0.93333333333333335, + 0.93333333333333335, + 1.0, + ), + "pale violet red": ( + 0.85882352941176465, + 0.4392156862745098, + 0.57647058823529407, + 1.0, + ), + "palegoldenrod": ( + 0.93333333333333335, + 0.90980392156862744, + 0.66666666666666663, + 1.0, + ), + "palegreen": (0.59607843137254901, 0.98431372549019602, 0.59607843137254901, 1.0), + "palegreen1": (0.60392156862745094, 1.0, 0.60392156862745094, 1.0), + "palegreen2": (0.56470588235294117, 0.93333333333333335, 0.56470588235294117, 1.0), + "palegreen3": (0.48627450980392156, 0.80392156862745101, 0.48627450980392156, 1.0), + "palegreen4": (0.32941176470588235, 0.54509803921568623, 0.32941176470588235, 1.0), + "paleturquoise": ( + 0.68627450980392157, + 0.93333333333333335, + 0.93333333333333335, + 1.0, + ), + "paleturquoise1": (0.73333333333333328, 1.0, 1.0, 1.0), + "paleturquoise2": ( + 0.68235294117647061, + 0.93333333333333335, + 0.93333333333333335, + 1.0, + ), + "paleturquoise3": ( + 0.58823529411764708, + 0.80392156862745101, + 0.80392156862745101, + 1.0, + ), + "paleturquoise4": ( + 0.40000000000000002, + 0.54509803921568623, + 0.54509803921568623, + 1.0, + ), + "palevioletred": ( + 0.85882352941176465, + 0.4392156862745098, + 0.57647058823529407, + 1.0, + ), + "palevioletred1": (1.0, 0.50980392156862742, 0.6705882352941176, 1.0), + "palevioletred2": ( + 0.93333333333333335, + 0.47450980392156861, + 0.62352941176470589, + 1.0, + ), + "palevioletred3": ( + 0.80392156862745101, + 0.40784313725490196, + 0.53725490196078429, + 1.0, + ), + "palevioletred4": ( + 0.54509803921568623, + 0.27843137254901962, + 0.36470588235294116, + 1.0, + ), + "papaya whip": (1.0, 0.93725490196078431, 0.83529411764705885, 1.0), + "papayawhip": (1.0, 0.93725490196078431, 0.83529411764705885, 1.0), + "peach puff": (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), + "peachpuff": (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), + "peachpuff1": (1.0, 0.85490196078431369, 0.72549019607843135, 1.0), + "peachpuff2": (0.93333333333333335, 0.79607843137254897, 0.67843137254901964, 1.0), + "peachpuff3": (0.80392156862745101, 0.68627450980392157, 0.58431372549019611, 1.0), + "peachpuff4": (0.54509803921568623, 0.46666666666666667, 0.396078431372549, 1.0), + "peru": (0.80392156862745101, 0.52156862745098043, 0.24705882352941178, 1.0), + "pink": (1.0, 0.75294117647058822, 0.79607843137254897, 1.0), + "pink1": (1.0, 0.70980392156862748, 0.77254901960784317, 1.0), + "pink2": (0.93333333333333335, 0.66274509803921566, 0.72156862745098038, 1.0), + "pink3": (0.80392156862745101, 0.56862745098039214, 0.61960784313725492, 1.0), + "pink4": (0.54509803921568623, 0.38823529411764707, 0.42352941176470588, 1.0), + "plum": (0.8666666666666667, 0.62745098039215685, 0.8666666666666667, 1.0), + "plum1": (1.0, 0.73333333333333328, 1.0, 1.0), + "plum2": (0.93333333333333335, 0.68235294117647061, 0.93333333333333335, 1.0), + "plum3": (0.80392156862745101, 0.58823529411764708, 0.80392156862745101, 1.0), + "plum4": (0.54509803921568623, 0.40000000000000002, 0.54509803921568623, 1.0), + "powder blue": (0.69019607843137254, 0.8784313725490196, 0.90196078431372551, 1.0), + "powderblue": (0.69019607843137254, 0.8784313725490196, 0.90196078431372551, 1.0), + "purple": (0.62745098039215685, 0.12549019607843137, 0.94117647058823528, 1.0), + "purple1": (0.60784313725490191, 0.18823529411764706, 1.0, 1.0), + "purple2": (0.56862745098039214, 0.17254901960784313, 0.93333333333333335, 1.0), + "purple3": (0.49019607843137253, 0.14901960784313725, 0.80392156862745101, 1.0), + "purple4": (0.33333333333333331, 0.10196078431372549, 0.54509803921568623, 1.0), + "rebecca purple": (0.4, 0.2, 0.6, 1.0), + "rebeccapurple": (0.4, 0.2, 0.6, 1.0), + "red": (1.0, 0.0, 0.0, 1.0), + "red1": (1.0, 0.0, 0.0, 1.0), + "red2": (0.93333333333333335, 0.0, 0.0, 1.0), + "red3": (0.80392156862745101, 0.0, 0.0, 1.0), + "red4": (0.54509803921568623, 0.0, 0.0, 1.0), + "rosy brown": (0.73725490196078436, 0.5607843137254902, 0.5607843137254902, 1.0), + "rosybrown": (0.73725490196078436, 0.5607843137254902, 0.5607843137254902, 1.0), + "rosybrown1": (1.0, 0.75686274509803919, 0.75686274509803919, 1.0), + "rosybrown2": (0.93333333333333335, 0.70588235294117652, 0.70588235294117652, 1.0), + "rosybrown3": (0.80392156862745101, 0.60784313725490191, 0.60784313725490191, 1.0), + "rosybrown4": (0.54509803921568623, 0.41176470588235292, 0.41176470588235292, 1.0), + "royal blue": (0.25490196078431371, 0.41176470588235292, 0.88235294117647056, 1.0), + "royalblue": (0.25490196078431371, 0.41176470588235292, 0.88235294117647056, 1.0), + "royalblue1": (0.28235294117647058, 0.46274509803921571, 1.0, 1.0), + "royalblue2": (0.2627450980392157, 0.43137254901960786, 0.93333333333333335, 1.0), + "royalblue3": (0.22745098039215686, 0.37254901960784315, 0.80392156862745101, 1.0), + "royalblue4": (0.15294117647058825, 0.25098039215686274, 0.54509803921568623, 1.0), + "saddle brown": ( + 0.54509803921568623, + 0.27058823529411763, + 0.074509803921568626, + 1.0, + ), + "saddlebrown": ( + 0.54509803921568623, + 0.27058823529411763, + 0.074509803921568626, + 1.0, + ), + "salmon": (0.98039215686274506, 0.50196078431372548, 0.44705882352941179, 1.0), + "salmon1": (1.0, 0.5490196078431373, 0.41176470588235292, 1.0), + "salmon2": (0.93333333333333335, 0.50980392156862742, 0.3843137254901961, 1.0), + "salmon3": (0.80392156862745101, 0.4392156862745098, 0.32941176470588235, 1.0), + "salmon4": (0.54509803921568623, 0.29803921568627451, 0.22352941176470589, 1.0), + "sandy brown": (0.95686274509803926, 0.64313725490196083, 0.37647058823529411, 1.0), + "sandybrown": (0.95686274509803926, 0.64313725490196083, 0.37647058823529411, 1.0), + "sea green": (0.1803921568627451, 0.54509803921568623, 0.3411764705882353, 1.0), + "seagreen": (0.1803921568627451, 0.54509803921568623, 0.3411764705882353, 1.0), + "seagreen1": (0.32941176470588235, 1.0, 0.62352941176470589, 1.0), + "seagreen2": (0.30588235294117649, 0.93333333333333335, 0.58039215686274515, 1.0), + "seagreen3": (0.2627450980392157, 0.80392156862745101, 0.50196078431372548, 1.0), + "seagreen4": (0.1803921568627451, 0.54509803921568623, 0.3411764705882353, 1.0), + "seashell": (1.0, 0.96078431372549022, 0.93333333333333335, 1.0), + "seashell1": (1.0, 0.96078431372549022, 0.93333333333333335, 1.0), + "seashell2": (0.93333333333333335, 0.89803921568627454, 0.87058823529411766, 1.0), + "seashell3": (0.80392156862745101, 0.77254901960784317, 0.74901960784313726, 1.0), + "seashell4": (0.54509803921568623, 0.52549019607843139, 0.50980392156862742, 1.0), + "sienna": (0.62745098039215685, 0.32156862745098042, 0.17647058823529413, 1.0), + "sienna1": (1.0, 0.50980392156862742, 0.27843137254901962, 1.0), + "sienna2": (0.93333333333333335, 0.47450980392156861, 0.25882352941176473, 1.0), + "sienna3": (0.80392156862745101, 0.40784313725490196, 0.22352941176470589, 1.0), + "sienna4": (0.54509803921568623, 0.27843137254901962, 0.14901960784313725, 1.0), + "silver": (0.75, 0.75, 0.75, 1.0), + "sky blue": (0.52941176470588236, 0.80784313725490198, 0.92156862745098034, 1.0), + "skyblue": (0.52941176470588236, 0.80784313725490198, 0.92156862745098034, 1.0), + "skyblue1": (0.52941176470588236, 0.80784313725490198, 1.0, 1.0), + "skyblue2": (0.49411764705882355, 0.75294117647058822, 0.93333333333333335, 1.0), + "skyblue3": (0.42352941176470588, 0.65098039215686276, 0.80392156862745101, 1.0), + "skyblue4": (0.29019607843137257, 0.4392156862745098, 0.54509803921568623, 1.0), + "slate blue": (0.41568627450980394, 0.35294117647058826, 0.80392156862745101, 1.0), + "slate gray": (0.4392156862745098, 0.50196078431372548, 0.56470588235294117, 1.0), + "slate grey": (0.4392156862745098, 0.50196078431372548, 0.56470588235294117, 1.0), + "slateblue": (0.41568627450980394, 0.35294117647058826, 0.80392156862745101, 1.0), + "slateblue1": (0.51372549019607838, 0.43529411764705883, 1.0, 1.0), + "slateblue2": (0.47843137254901963, 0.40392156862745099, 0.93333333333333335, 1.0), + "slateblue3": (0.41176470588235292, 0.34901960784313724, 0.80392156862745101, 1.0), + "slateblue4": (0.27843137254901962, 0.23529411764705882, 0.54509803921568623, 1.0), + "slategray": (0.4392156862745098, 0.50196078431372548, 0.56470588235294117, 1.0), + "slategray1": (0.77647058823529413, 0.88627450980392153, 1.0, 1.0), + "slategray2": (0.72549019607843135, 0.82745098039215681, 0.93333333333333335, 1.0), + "slategray3": (0.62352941176470589, 0.71372549019607845, 0.80392156862745101, 1.0), + "slategray4": (0.42352941176470588, 0.4823529411764706, 0.54509803921568623, 1.0), + "slategrey": (0.4392156862745098, 0.50196078431372548, 0.56470588235294117, 1.0), + "snow": (1.0, 0.98039215686274506, 0.98039215686274506, 1.0), + "snow1": (1.0, 0.98039215686274506, 0.98039215686274506, 1.0), + "snow2": (0.93333333333333335, 0.9137254901960784, 0.9137254901960784, 1.0), + "snow3": (0.80392156862745101, 0.78823529411764703, 0.78823529411764703, 1.0), + "snow4": (0.54509803921568623, 0.53725490196078429, 0.53725490196078429, 1.0), + "spring green": (0.0, 1.0, 0.49803921568627452, 1.0), + "springgreen": (0.0, 1.0, 0.49803921568627452, 1.0), + "springgreen1": (0.0, 1.0, 0.49803921568627452, 1.0), + "springgreen2": (0.0, 0.93333333333333335, 0.46274509803921571, 1.0), + "springgreen3": (0.0, 0.80392156862745101, 0.40000000000000002, 1.0), + "springgreen4": (0.0, 0.54509803921568623, 0.27058823529411763, 1.0), + "steel blue": (0.27450980392156865, 0.50980392156862742, 0.70588235294117652, 1.0), + "steelblue": (0.27450980392156865, 0.50980392156862742, 0.70588235294117652, 1.0), + "steelblue1": (0.38823529411764707, 0.72156862745098038, 1.0, 1.0), + "steelblue2": (0.36078431372549019, 0.67450980392156867, 0.93333333333333335, 1.0), + "steelblue3": (0.30980392156862746, 0.58039215686274515, 0.80392156862745101, 1.0), + "steelblue4": (0.21176470588235294, 0.39215686274509803, 0.54509803921568623, 1.0), + "tan": (0.82352941176470584, 0.70588235294117652, 0.5490196078431373, 1.0), + "tan1": (1.0, 0.6470588235294118, 0.30980392156862746, 1.0), + "tan2": (0.93333333333333335, 0.60392156862745094, 0.28627450980392155, 1.0), + "tan3": (0.80392156862745101, 0.52156862745098043, 0.24705882352941178, 1.0), + "tan4": (0.54509803921568623, 0.35294117647058826, 0.16862745098039217, 1.0), + "teal": (0.0, 0.5, 0.5, 1.0), + "thistle": (0.84705882352941175, 0.74901960784313726, 0.84705882352941175, 1.0), + "thistle1": (1.0, 0.88235294117647056, 1.0, 1.0), + "thistle2": (0.93333333333333335, 0.82352941176470584, 0.93333333333333335, 1.0), + "thistle3": (0.80392156862745101, 0.70980392156862748, 0.80392156862745101, 1.0), + "thistle4": (0.54509803921568623, 0.4823529411764706, 0.54509803921568623, 1.0), + "tomato": (1.0, 0.38823529411764707, 0.27843137254901962, 1.0), + "tomato1": (1.0, 0.38823529411764707, 0.27843137254901962, 1.0), + "tomato2": (0.93333333333333335, 0.36078431372549019, 0.25882352941176473, 1.0), + "tomato3": (0.80392156862745101, 0.30980392156862746, 0.22352941176470589, 1.0), + "tomato4": (0.54509803921568623, 0.21176470588235294, 0.14901960784313725, 1.0), + "turquoise": (0.25098039215686274, 0.8784313725490196, 0.81568627450980391, 1.0), + "turquoise1": (0.0, 0.96078431372549022, 1.0, 1.0), + "turquoise2": (0.0, 0.89803921568627454, 0.93333333333333335, 1.0), + "turquoise3": (0.0, 0.77254901960784317, 0.80392156862745101, 1.0), + "turquoise4": (0.0, 0.52549019607843139, 0.54509803921568623, 1.0), + "violet": (0.93333333333333335, 0.50980392156862742, 0.93333333333333335, 1.0), + "violet red": (0.81568627450980391, 0.12549019607843137, 0.56470588235294117, 1.0), + "violetred": (0.81568627450980391, 0.12549019607843137, 0.56470588235294117, 1.0), + "violetred1": (1.0, 0.24313725490196078, 0.58823529411764708, 1.0), + "violetred2": (0.93333333333333335, 0.22745098039215686, 0.5490196078431373, 1.0), + "violetred3": (0.80392156862745101, 0.19607843137254902, 0.47058823529411764, 1.0), + "violetred4": (0.54509803921568623, 0.13333333333333333, 0.32156862745098042, 1.0), + "web gray": (0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0), + "webgray": (0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0), + "web green": (0.0, 0.5019607843137255, 0.0, 1.0), + "webgreen": (0.0, 0.5019607843137255, 0.0, 1.0), + "webgray": (0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0), + "web grey": (0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0), + "webgrey": (0.5019607843137255, 0.5019607843137255, 0.5019607843137255, 1.0), + "web maroon": (0.5019607843137255, 0.0, 0.0, 1.0), + "webmaroon": (0.5019607843137255, 0.0, 0.0, 1.0), + "web purple": (0.4980392156862745, 0.0, 0.4980392156862745, 1.0), + "webpurple": (0.4980392156862745, 0.0, 0.4980392156862745, 1.0), + "wheat": (0.96078431372549022, 0.87058823529411766, 0.70196078431372544, 1.0), + "wheat1": (1.0, 0.90588235294117647, 0.72941176470588232, 1.0), + "wheat2": (0.93333333333333335, 0.84705882352941175, 0.68235294117647061, 1.0), + "wheat3": (0.80392156862745101, 0.72941176470588232, 0.58823529411764708, 1.0), + "wheat4": (0.54509803921568623, 0.49411764705882355, 0.40000000000000002, 1.0), + "white": (1.0, 1.0, 1.0, 1.0), + "white smoke": (0.96078431372549022, 0.96078431372549022, 0.96078431372549022, 1.0), + "whitesmoke": (0.96078431372549022, 0.96078431372549022, 0.96078431372549022, 1.0), + "yellow": (1.0, 1.0, 0.0, 1.0), + "yellow green": ( + 0.60392156862745094, + 0.80392156862745101, + 0.19607843137254902, + 1.0, + ), + "yellow1": (1.0, 1.0, 0.0, 1.0), + "yellow2": (0.93333333333333335, 0.93333333333333335, 0.0, 1.0), + "yellow3": (0.80392156862745101, 0.80392156862745101, 0.0, 1.0), + "yellow4": (0.54509803921568623, 0.54509803921568623, 0.0, 1.0), + "yellowgreen": (0.60392156862745094, 0.80392156862745101, 0.19607843137254902, 1.0), +} palettes = { "gray": GradientPalette("black", "white"), @@ -3109,10 +2057,8 @@ def lighten(color, ratio=0.5): "red-yellow-green": AdvancedGradientPalette(["red", "yellow", "green"]), "red-black-green": AdvancedGradientPalette(["red", "black", "green"]), "rainbow": RainbowPalette(), - "heat": AdvancedGradientPalette(["red", "yellow", "white"], - indices=[0, 192, 255]), - "terrain": AdvancedGradientPalette(["hsv(120, 100%, 65%)", - "hsv(60, 100%, 90%)", "hsv(0, 0%, 95%)"]) + "heat": AdvancedGradientPalette(["red", "yellow", "white"], indices=[0, 192, 255]), + "terrain": AdvancedGradientPalette( + ["hsv(120, 100%, 65%)", "hsv(60, 100%, 90%)", "hsv(0, 0%, 95%)"] + ), } - - diff --git a/src/igraph/drawing/coord.py b/src/igraph/drawing/coord.py index 51253b76e..91db1a05a 100644 --- a/src/igraph/drawing/coord.py +++ b/src/igraph/drawing/coord.py @@ -10,6 +10,7 @@ ##################################################################### + # pylint: disable-msg=R0922 # R0922: Abstract class is only referenced 1 times class CoordinateSystem(AbstractCairoDrawer): @@ -42,7 +43,7 @@ def draw(self): def local_to_context(self, x, y): """Converts local coordinates to the context coordinate system (given by the bounding box). - + This method must be overridden in derived classes.""" raise NotImplementedError("abstract class") @@ -105,15 +106,17 @@ def draw(self): """Draws the coordinate system.""" # Draw the frame coords = self.bbox.coords - self.context.set_source_rgb(0., 0., 0.) + self.context.set_source_rgb(0.0, 0.0, 0.0) self.context.set_line_width(1) - self.context.rectangle(coords[0], coords[1], \ - coords[2]-coords[0], coords[3]-coords[1]) + self.context.rectangle( + coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1] + ) self.context.stroke() def local_to_context(self, x, y): """Converts local coordinates to the context coordinate system (given by the bounding box). """ - return (x-self._ox)*self._sx+self._ox2, self._oy2-(y-self._oy)*self._sy - + return (x - self._ox) * self._sx + self._ox2, self._oy2 - ( + y - self._oy + ) * self._sy diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 64e5ffc22..1afdfd0cc 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -2,9 +2,14 @@ Drawers for various edge styles in graph plots. """ -__all__ = ["AbstractEdgeDrawer", "AlphaVaryingEdgeDrawer", - "ArrowEdgeDrawer", "DarkToLightEdgeDrawer", - "LightToDarkEdgeDrawer", "TaperedEdgeDrawer"] +__all__ = [ + "AbstractEdgeDrawer", + "AlphaVaryingEdgeDrawer", + "ArrowEdgeDrawer", + "DarkToLightEdgeDrawer", + "LightToDarkEdgeDrawer", + "TaperedEdgeDrawer", +] __license__ = "GPL" @@ -16,6 +21,7 @@ cairo = find_cairo() + class AbstractEdgeDrawer(object): """Abstract edge drawer object from which all concrete edge drawer implementations are derived.""" @@ -44,19 +50,22 @@ def _curvature_to_float(value): def _construct_visual_edge_builder(self): """Construct the visual edge builder that will collect the visual attributes of an edge when it is being drawn.""" + class VisualEdgeBuilder(AttributeCollectorBase): """Builder that collects some visual properties of an edge for drawing""" + _kwds_prefix = "edge_" - arrow_size = 1.0 + arrow_size = 1.0 arrow_width = 1.0 - color = ("#444", self.palette.get) - curved = (0.0, self._curvature_to_float) - label = None + color = ("#444", self.palette.get) + curved = (0.0, self._curvature_to_float) + label = None label_color = ("black", self.palette.get) - label_size = 12.0 - font = 'sans-serif' - width = 1.0 + label_size = 12.0 + font = "sans-serif" + width = 1.0 + return VisualEdgeBuilder def draw_directed_edge(self, edge, src_vertex, dest_vertex): @@ -85,9 +94,9 @@ def draw_loop_edge(self, edge, vertex): ctx.set_source_rgba(*edge.color) ctx.set_line_width(edge.width) radius = vertex.size * 1.5 - center_x = vertex.position[0] + cos(pi/4) * radius / 2. - center_y = vertex.position[1] - sin(pi/4) * radius / 2. - ctx.arc(center_x, center_y, radius/2., 0, pi * 2) + center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 + center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 + ctx.arc(center_x, center_y, radius / 2.0, 0, pi * 2) ctx.stroke() def draw_undirected_edge(self, edge, src_vertex, dest_vertex): @@ -103,7 +112,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): @param dest_vertex: the target vertex. Visual properties are given again as attributes. """ - if src_vertex == dest_vertex: # TODO + if src_vertex == dest_vertex: # TODO return self.draw_loop_edge(edge, src_vertex) ctx = self.context @@ -113,10 +122,12 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1 = (2*x1+x2) / 3.0 - edge.curved * 0.5 * (y2-y1), \ - (2*y1+y2) / 3.0 + edge.curved * 0.5 * (x2-x1) - aux2 = (x1+2*x2) / 3.0 - edge.curved * 0.5 * (y2-y1), \ - (y1+2*y2) / 3.0 + edge.curved * 0.5 * (x2-x1) + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], *dest_vertex.position) else: ctx.line_to(*dest_vertex.position) @@ -145,13 +156,15 @@ def get_label_position(self, edge, src_vertex, dest_vertex): dy = dest_vertex.position[1] - src_vertex.position[1] if dx != 0 or dy != 0: # Note that we use -dy because the Y axis points downwards - angle = atan2(-dy, dx) % (2*pi) + angle = atan2(-dy, dx) % (2 * pi) else: angle = None # Determine the midpoint - pos = ((src_vertex.position[0] + dest_vertex.position[0]) / 2., \ - (src_vertex.position[1] + dest_vertex.position[1]) / 2) + pos = ( + (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, + (src_vertex.position[1] + dest_vertex.position[1]) / 2, + ) # Determine the alignment based on the angle pi4 = pi / 4 @@ -159,14 +172,26 @@ def get_label_position(self, edge, src_vertex, dest_vertex): halign, valign = TextAlignment.CENTER, TextAlignment.CENTER else: index = int((angle / pi4) % 8) - halign = [TextAlignment.RIGHT, TextAlignment.RIGHT, - TextAlignment.RIGHT, TextAlignment.RIGHT, - TextAlignment.LEFT, TextAlignment.LEFT, - TextAlignment.LEFT, TextAlignment.LEFT][index] - valign = [TextAlignment.BOTTOM, TextAlignment.CENTER, - TextAlignment.CENTER, TextAlignment.TOP, - TextAlignment.TOP, TextAlignment.CENTER, - TextAlignment.CENTER, TextAlignment.BOTTOM][index] + halign = [ + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.LEFT, + TextAlignment.LEFT, + TextAlignment.LEFT, + TextAlignment.LEFT, + ][index] + valign = [ + TextAlignment.BOTTOM, + TextAlignment.CENTER, + TextAlignment.CENTER, + TextAlignment.TOP, + TextAlignment.TOP, + TextAlignment.CENTER, + TextAlignment.CENTER, + TextAlignment.BOTTOM, + ][index] return pos, (halign, valign) @@ -177,62 +202,71 @@ class ArrowEdgeDrawer(AbstractEdgeDrawer): """ def draw_directed_edge(self, edge, src_vertex, dest_vertex): - if src_vertex == dest_vertex: # TODO + if src_vertex == dest_vertex: # TODO return self.draw_loop_edge(edge, src_vertex) ctx = self.context (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position (x_src, y_src), (x_dest, y_dest) = src_vertex.position, dest_vertex.position - - def bezier_cubic(x0,y0, x1,y1, x2,y2, x3,y3, t): - """ Computes the Bezier curve from point (x0,y0) to (x3,y3) + def bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t): + """Computes the Bezier curve from point (x0,y0) to (x3,y3) via control points (x1,y1) and (x2,y2) with parameter t. """ - xt = (1.0 - t) ** 3 * x0 + 3. *t * (1.0 - t) ** 2 * x1 + 3. * t**2 * (1. - t) * x2 + t**3 * x3 - yt = (1.0 - t) ** 3 * y0 + 3. *t * (1.0 - t) ** 2 * y1 + 3. * t**2 * (1. - t) * y2 + t**3 * y3 - return xt,yt - - def euclidean_distance(x1,y1,x2,y2): - """ Computes the Euclidean distance between points (x1,y1) and (x2,y2). - """ - return sqrt( (1.0*x1-x2) **2 + (1.0*y1-y2) **2 ) - - def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): - """ Binary search solver for finding the intersection of a Bezier curve + xt = ( + (1.0 - t) ** 3 * x0 + + 3.0 * t * (1.0 - t) ** 2 * x1 + + 3.0 * t ** 2 * (1.0 - t) * x2 + + t ** 3 * x3 + ) + yt = ( + (1.0 - t) ** 3 * y0 + + 3.0 * t * (1.0 - t) ** 2 * y1 + + 3.0 * t ** 2 * (1.0 - t) * y2 + + t ** 3 * y3 + ) + return xt, yt + + def euclidean_distance(x1, y1, x2, y2): + """Computes the Euclidean distance between points (x1,y1) and (x2,y2).""" + return sqrt((1.0 * x1 - x2) ** 2 + (1.0 * y1 - y2) ** 2) + + def intersect_bezier_circle( + x0, y0, x1, y1, x2, y2, x3, y3, radius, max_iter=10 + ): + """Binary search solver for finding the intersection of a Bezier curve and a circle centered at the curve's end point. Returns the x,y of the intersection point. TODO: implement safeguard to ensure convergence in ALL possible cases. """ precision = radius / 20.0 - source_target_distance = euclidean_distance(x0,y0,x3,y3) + source_target_distance = euclidean_distance(x0, y0, x3, y3) radius = float(radius) t0 = 1.0 t1 = 1.0 - radius / source_target_distance xt0, yt0 = x3, y3 - xt1, yt1 = bezier_cubic(x0,y0, x1,y1, x2,y2, x3,y3, t1) + xt1, yt1 = bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) distance_t0 = 0 - distance_t1 = euclidean_distance(x3,y3, xt1,yt1) + distance_t1 = euclidean_distance(x3, y3, xt1, yt1) counter = 0 while abs(distance_t1 - radius) > precision and counter < max_iter: - if ((distance_t1-radius) > 0) != ((distance_t0-radius) > 0): - t_new = (t0 + t1)/2.0 + if ((distance_t1 - radius) > 0) != ((distance_t0 - radius) > 0): + t_new = (t0 + t1) / 2.0 else: - if (abs(distance_t1 - radius) < abs(distance_t0 - radius)): + if abs(distance_t1 - radius) < abs(distance_t0 - radius): # If t1 gets us closer to the circumference step in the same direction - t_new = t1 + (t1 - t0)/ 2.0 + t_new = t1 + (t1 - t0) / 2.0 else: t_new = t1 - (t1 - t0) t_new = 1 if t_new > 1 else (0 if t_new < 0 else t_new) - t0,t1 = t1,t_new + t0, t1 = t1, t_new distance_t0 = distance_t1 - xt1, yt1 = bezier_cubic(x0,y0, x1,y1, x2,y2, x3,y3, t1) - distance_t1 = euclidean_distance(x3,y3, xt1,yt1) + xt1, yt1 = bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) + distance_t1 = euclidean_distance(x3, y3, xt1, yt1) counter += 1 - return bezier_cubic(x0,y0, x1,y1, x2,y2, x3,y3, t1) - + return bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) # Draw the edge ctx.set_source_rgba(*edge.color) @@ -241,10 +275,12 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): if edge.curved: # Calculate the curve - aux1 = (2*x1+x2) / 3.0 - edge.curved * 0.5 * (y2-y1), \ - (2*y1+y2) / 3.0 + edge.curved * 0.5 * (x2-x1) - aux2 = (x1+2*x2) / 3.0 - edge.curved * 0.5 * (y2-y1), \ - (y1+2*y2) / 3.0 + edge.curved * 0.5 * (x2-x1) + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) # Coordinates of the control points of the Bezier curve xc1, yc1 = aux1 @@ -252,38 +288,60 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): # Determine where the edge intersects the circumference of the # vertex shape: Tip of the arrow - x2, y2 = intersect_bezier_circle(x_src,y_src, xc1,yc1, xc2,yc2, x_dest,y_dest, dest_vertex.size/2.0) + x2, y2 = intersect_bezier_circle( + x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 + ) # Calculate the arrow head coordinates - angle = atan2(y_dest - y2, x_dest - x2) # navid - arrow_size = 15. * edge.arrow_size - arrow_width = 10. / edge.arrow_width + angle = atan2(y_dest - y2, x_dest - x2) # navid + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width aux_points = [ - (x2 - arrow_size * cos(angle - pi/arrow_width), - y2 - arrow_size * sin(angle - pi/arrow_width)), - (x2 - arrow_size * cos(angle + pi/arrow_width), - y2 - arrow_size * sin(angle + pi/arrow_width)), - ] + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), + ] # Midpoint of the base of the arrow triangle - x_arrow_mid , y_arrow_mid = (aux_points [0][0] + aux_points [1][0]) / 2.0, (aux_points [0][1] + aux_points [1][1]) / 2.0 + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 # Vector representing the base of the arrow triangle - x_arrow_base_vec, y_arrow_base_vec = (aux_points [0][0] - aux_points [1][0]) , (aux_points [0][1] - aux_points [1][1]) + x_arrow_base_vec, y_arrow_base_vec = ( + aux_points[0][0] - aux_points[1][0] + ), (aux_points[0][1] - aux_points[1][1]) # Recalculate the curve such that it lands on the base of the arrow triangle - aux1 = (2*x_src+x_arrow_mid) / 3.0 - edge.curved * 0.5 * (y_arrow_mid-y_src), \ - (2*y_src+y_arrow_mid) / 3.0 + edge.curved * 0.5 * (x_arrow_mid-x_src) - aux2 = (x_src+2*x_arrow_mid) / 3.0 - edge.curved * 0.5 * (y_arrow_mid-y_src), \ - (y_src+2*y_arrow_mid) / 3.0 + edge.curved * 0.5 * (x_arrow_mid-x_src) + aux1 = (2 * x_src + x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (2 * y_src + y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) + aux2 = (x_src + 2 * x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (y_src + 2 * y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) # Offset the second control point (aux2) such that it falls precisely on the normal to the arrow base vector # Strictly speaking, offset_length is the offset length divided by the length of the arrow base vector. - offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + (y_arrow_mid - aux2[1]) * y_arrow_base_vec - offset_length /= euclidean_distance(0,0, x_arrow_base_vec, y_arrow_base_vec) ** 2 - - aux2 = aux2[0] + x_arrow_base_vec * offset_length, \ - aux2[1] + y_arrow_base_vec * offset_length + offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + ( + y_arrow_mid - aux2[1] + ) * y_arrow_base_vec + offset_length /= ( + euclidean_distance(0, 0, x_arrow_base_vec, y_arrow_base_vec) ** 2 + ) + + aux2 = ( + aux2[0] + x_arrow_base_vec * offset_length, + aux2[1] + y_arrow_base_vec * offset_length, + ) # Draw tthe curve from the first vertex to the midpoint of the base of the arrow head ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], x_arrow_mid, y_arrow_mid) @@ -291,21 +349,28 @@ def intersect_bezier_circle(x0,y0, x1,y1, x2,y2, x3,y3, radius, max_iter=10): # Determine where the edge intersects the circumference of the # vertex shape. x2, y2 = dest_vertex.shape.intersection_point( - x2, y2, x1, y1, dest_vertex.size) + x2, y2, x1, y1, dest_vertex.size + ) # Draw the arrowhead angle = atan2(y_dest - y2, x_dest - x2) - arrow_size = 15. * edge.arrow_size - arrow_width = 10. / edge.arrow_width + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width aux_points = [ - (x2 - arrow_size * cos(angle - pi/arrow_width), - y2 - arrow_size * sin(angle - pi/arrow_width)), - (x2 - arrow_size * cos(angle + pi/arrow_width), - y2 - arrow_size * sin(angle + pi/arrow_width)), + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), ] # Midpoint of the base of the arrow triangle - x_arrow_mid , y_arrow_mid = (aux_points [0][0] + aux_points [1][0]) / 2.0, (aux_points [0][1] + aux_points [1][1]) / 2.0 + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 # Draw the line ctx.line_to(x_arrow_mid, y_arrow_mid) @@ -327,15 +392,14 @@ class TaperedEdgeDrawer(AbstractEdgeDrawer): """ def draw_directed_edge(self, edge, src_vertex, dest_vertex): - if src_vertex == dest_vertex: # TODO + if src_vertex == dest_vertex: # TODO return self.draw_loop_edge(edge, src_vertex) # Determine where the edge intersects the circumference of the # destination vertex. src_pos, dest_pos = src_vertex.position, dest_vertex.position dest_pos = dest_vertex.shape.intersection_point( - dest_pos[0], dest_pos[1], src_pos[0], src_pos[1], - dest_vertex.size + dest_pos[0], dest_pos[1], src_pos[0], src_pos[1], dest_vertex.size ) ctx = self.context @@ -343,13 +407,17 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): # Draw the edge ctx.set_source_rgba(*edge.color) ctx.set_line_width(edge.width) - angle = atan2(dest_pos[1]-src_pos[1], dest_pos[0]-src_pos[0]) - arrow_size = src_vertex.size / 4. + angle = atan2(dest_pos[1] - src_pos[1], dest_pos[0] - src_pos[0]) + arrow_size = src_vertex.size / 4.0 aux_points = [ - (src_pos[0] + arrow_size * cos(angle + pi/2), - src_pos[1] + arrow_size * sin(angle + pi/2)), - (src_pos[0] + arrow_size * cos(angle - pi/2), - src_pos[1] + arrow_size * sin(angle - pi/2)) + ( + src_pos[0] + arrow_size * cos(angle + pi / 2), + src_pos[1] + arrow_size * sin(angle + pi / 2), + ), + ( + src_pos[0] + arrow_size * cos(angle - pi / 2), + src_pos[1] + arrow_size * sin(angle - pi / 2), + ), ] ctx.move_to(*dest_pos) ctx.line_to(*aux_points[0]) @@ -366,11 +434,11 @@ class AlphaVaryingEdgeDrawer(AbstractEdgeDrawer): def __init__(self, context, alpha_at_src, alpha_at_dest): super(AlphaVaryingEdgeDrawer, self).__init__(context) - self.alpha_at_src = (clamp(float(alpha_at_src), 0., 1.), ) - self.alpha_at_dest = (clamp(float(alpha_at_dest), 0., 1.), ) + self.alpha_at_src = (clamp(float(alpha_at_src), 0.0, 1.0),) + self.alpha_at_dest = (clamp(float(alpha_at_dest), 0.0, 1.0),) def draw_directed_edge(self, edge, src_vertex, dest_vertex): - if src_vertex == dest_vertex: # TODO + if src_vertex == dest_vertex: # TODO return self.draw_loop_edge(edge, src_vertex) src_pos, dest_pos = src_vertex.position, dest_vertex.position @@ -413,4 +481,3 @@ class DarkToLightEdgeDrawer(AlphaVaryingEdgeDrawer): def __init__(self, context): super(DarkToLightEdgeDrawer, self).__init__(context, 1.0, 0.0) - diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index f713d2b67..6d59b5b66 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -14,15 +14,17 @@ """ from collections import defaultdict -from itertools import izip + from math import atan2, cos, pi, sin, tan, sqrt from warnings import warn from igraph._igraph import convex_hull, VertexSeq -from igraph.compat import property from igraph.configuration import Configuration -from igraph.drawing.baseclasses import AbstractDrawer, AbstractCairoDrawer, \ - AbstractXMLRPCDrawer +from igraph.drawing.baseclasses import ( + AbstractDrawer, + AbstractCairoDrawer, + AbstractXMLRPCDrawer, +) from igraph.drawing.colors import color_to_html_format, color_name_to_rgb from igraph.drawing.edge import ArrowEdgeDrawer from igraph.drawing.text import TextAlignment, TextDrawer @@ -39,6 +41,7 @@ ##################################################################### + # pylint: disable-msg=R0903 # R0903: too few public methods class AbstractGraphDrawer(AbstractDrawer): @@ -52,7 +55,7 @@ def draw(self, graph, *args, **kwds): """Abstract method, must be implemented in derived classes.""" raise NotImplementedError("abstract class") - def ensure_layout(self, layout, graph = None): + def ensure_layout(self, layout, graph=None): """Helper method that ensures that I{layout} is an instance of L{Layout}. If it is not, the method will try to convert it to a L{Layout} according to the following rules: @@ -84,11 +87,12 @@ def ensure_layout(self, layout, graph = None): layout = Layout(layout) return layout + ##################################################################### + class AbstractCairoGraphDrawer(AbstractGraphDrawer, AbstractCairoDrawer): - """Abstract base class for graph drawers that draw on a Cairo canvas. - """ + """Abstract base class for graph drawers that draw on a Cairo canvas.""" def __init__(self, context, bbox): """Constructs the graph drawer and associates it to the given @@ -103,8 +107,10 @@ def __init__(self, context, bbox): AbstractCairoDrawer.__init__(self, context, bbox) AbstractGraphDrawer.__init__(self) + ##################################################################### + class DefaultGraphDrawer(AbstractCairoGraphDrawer): """Class implementing the default visualisation of a graph. @@ -116,10 +122,14 @@ class DefaultGraphDrawer(AbstractCairoGraphDrawer): See L{Graph.__plot__()} for the keyword arguments understood by this drawer.""" - def __init__(self, context, bbox, \ - vertex_drawer_factory = DefaultVertexDrawer, - edge_drawer_factory = ArrowEdgeDrawer, - label_drawer_factory = TextDrawer): + def __init__( + self, + context, + bbox, + vertex_drawer_factory=DefaultVertexDrawer, + edge_drawer_factory=ArrowEdgeDrawer, + label_drawer_factory=TextDrawer, + ): """Constructs the graph drawer and associates it to the given Cairo context and the given L{BoundingBox}. @@ -175,11 +185,12 @@ def _determine_edge_order(self, graph, kwds): reverse = False if isinstance(edge_order_by, tuple): edge_order_by, reverse = edge_order_by - if isinstance(reverse, basestring): + if isinstance(reverse, str): reverse = reverse.lower().startswith("desc") attrs = graph.es[edge_order_by] - edge_order = sorted(range(len(attrs)), key=attrs.__getitem__, - reverse=bool(reverse)) + edge_order = sorted( + list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) + ) return edge_order @@ -203,11 +214,12 @@ def _determine_vertex_order(self, graph, kwds): reverse = False if isinstance(vertex_order_by, tuple): vertex_order_by, reverse = vertex_order_by - if isinstance(reverse, basestring): + if isinstance(reverse, str): reverse = reverse.lower().startswith("desc") attrs = graph.vs[vertex_order_by] - vertex_order = sorted(range(len(attrs)), key=attrs.__getitem__, - reverse=bool(reverse)) + vertex_order = sorted( + list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) + ) return vertex_order @@ -229,7 +241,7 @@ def draw(self, graph, palette, *args, **kwds): margin = list(margin) except TypeError: margin = [margin] - while len(margin)<4: + while len(margin) < 4: margin.extend(margin) # Contract the drawing area by the margin and fit the layout @@ -239,10 +251,14 @@ def draw(self, graph, palette, *args, **kwds): # Decide whether we need to calculate the curvature of edges # automatically -- and calculate them if needed. autocurve = kwds.get("autocurve", None) - if autocurve or (autocurve is None and \ - "edge_curved" not in kwds and "curved" not in graph.edge_attributes() \ - and graph.ecount() < 10000): + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in graph.edge_attributes() + and graph.ecount() < 10000 + ): from igraph import autocurve + default = kwds.get("edge_curved", 0) if default is True: default = 0.5 @@ -261,7 +277,7 @@ def draw(self, graph, palette, *args, **kwds): # Determine the order in which we will draw the vertices and edges vertex_order = self._determine_vertex_order(graph, kwds) - edge_order = self._determine_edge_order(graph, kwds) + edge_order = self._determine_edge_order(graph, kwds) # Draw the highlighted groups (if any) if "mark_groups" in kwds: @@ -275,18 +291,16 @@ def draw(self, graph, palette, *args, **kwds): if isinstance(mark_groups, dict): # Dictionary mapping vertex indices or tuples of vertex # indices to colors - group_iter = mark_groups.iteritems() + group_iter = iter(mark_groups.items()) elif isinstance(mark_groups, (VertexClustering, VertexCover)): # Vertex clustering - group_iter = ( - (group, color) for color, group in enumerate(mark_groups) - ) + group_iter = ((group, color) for color, group in enumerate(mark_groups)) elif hasattr(mark_groups, "__iter__"): # Lists, tuples, iterators etc group_iter = iter(mark_groups) else: # False - group_iter = {}.iteritems() + group_iter = iter({}.items()) # We will need a polygon drawer to draw the convex hulls polygon_drawer = PolygonDrawer(context, bbox) @@ -315,19 +329,21 @@ def draw(self, graph, palette, *args, **kwds): if len(polygon) == 2: # Expand the polygon (which is a flat line otherwise) a, b = Point(*polygon[0]), Point(*polygon[1]) - c = corner_radius * (a-b).normalized() + c = corner_radius * (a - b).normalized() n = Point(-c[1], c[0]) polygon = [a + n, b + n, b - c, b - n, a - n, a + c] else: # Expand the polygon around its center of mass - center = Point(*[sum(coords) / float(len(coords)) - for coords in zip(*polygon)]) - polygon = [Point(*point).towards(center, -corner_radius) - for point in polygon] + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] + ) + polygon = [ + Point(*point).towards(center, -corner_radius) + for point in polygon + ] # Draw the hull - context.set_source_rgba(color[0], color[1], color[2], - color[3]*0.25) + context.set_source_rgba(color[0], color[1], color[2], color[3] * 0.25) polygon_drawer.draw_path(polygon, corner_radius=corner_radius) context.fill_preserve() context.set_source_rgba(*color) @@ -337,7 +353,7 @@ def draw(self, graph, palette, *args, **kwds): es = graph.es if edge_order is None: # Default edge order - edge_coord_iter = izip(es, edge_builder) + edge_coord_iter = zip(es, edge_builder) else: # Specified edge order edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) @@ -356,11 +372,12 @@ def draw(self, graph, palette, *args, **kwds): vs = graph.vs if vertex_order is None: # Default vertex order - vertex_coord_iter = izip(vs, vertex_builder, layout) + vertex_coord_iter = zip(vs, vertex_builder, layout) else: # Specified vertex order - vertex_coord_iter = ((vs[i], vertex_builder[i], layout[i]) - for i in vertex_order) + vertex_coord_iter = ( + (vs[i], vertex_builder[i], layout[i]) for i in vertex_order + ) # Draw the vertices drawer_method = vertex_drawer.draw @@ -377,11 +394,10 @@ def draw(self, graph, palette, *args, **kwds): # Construct the iterator that we will use to draw the vertex labels if vertex_order is None: # Default vertex order - vertex_coord_iter = izip(vertex_builder, layout) + vertex_coord_iter = zip(vertex_builder, layout) else: # Specified vertex order - vertex_coord_iter = ((vertex_builder[i], layout[i]) - for i in vertex_order) + vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) # Draw the vertex labels for vertex, coords in vertex_coord_iter: @@ -389,8 +405,9 @@ def draw(self, graph, palette, *args, **kwds): continue # Set the font family, size, color and text - context.select_font_face(vertex.font, \ - cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + context.select_font_face( + vertex.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL + ) context.set_font_size(vertex.label_size) context.set_source_rgba(*vertex.label_color) label_drawer.text = vertex.label @@ -398,26 +415,26 @@ def draw(self, graph, palette, *args, **kwds): if vertex.label_dist: # Label is displaced from the center of the vertex. _, yb, w, h, _, _ = label_drawer.text_extents() - w, h = w/2.0, h/2.0 - radius = vertex.label_dist * vertex.size / 2. + w, h = w / 2.0, h / 2.0 + radius = vertex.label_dist * vertex.size / 2.0 # First we find the reference point that is at distance `radius' # from the vertex in the direction given by `label_angle'. # Then we place the label in a way that the line connecting the # center of the bounding box of the label with the center of the # vertex goes through the reference point and the reference # point lies exactly on the bounding box of the vertex. - alpha = vertex.label_angle % (2*pi) + alpha = vertex.label_angle % (2 * pi) cx = coords[0] + radius * cos(alpha) cy = coords[1] - radius * sin(alpha) # Now we have the reference point. We have to decide which side # of the label box will intersect with the line that connects # the center of the label with the center of the vertex. if w > 0: - beta = atan2(h, w) % (2*pi) + beta = atan2(h, w) % (2 * pi) else: - beta = pi/2. + beta = pi / 2.0 gamma = pi - beta - if alpha > 2*pi-beta or alpha <= beta: + if alpha > 2 * pi - beta or alpha <= beta: # Intersection at left edge of label cx += w cy -= tan(alpha) * w @@ -426,9 +443,9 @@ def draw(self, graph, palette, *args, **kwds): try: cx += h / tan(alpha) except: - pass # tan(alpha) == inf + pass # tan(alpha) == inf cy -= h - elif alpha > gamma and alpha <= gamma + 2*beta: + elif alpha > gamma and alpha <= gamma + 2 * beta: # Intersection at right edge of label cx -= w cy += tan(alpha) * w @@ -437,23 +454,27 @@ def draw(self, graph, palette, *args, **kwds): try: cx -= h / tan(alpha) except: - pass # tan(alpha) == inf + pass # tan(alpha) == inf cy += h # Draw the label - label_drawer.draw_at(cx-w, cy-h-yb, wrap=wrap) + label_drawer.draw_at(cx - w, cy - h - yb, wrap=wrap) else: # Label is exactly in the center of the vertex cx, cy = coords - half_size = vertex.size / 2. - label_drawer.bbox = (cx - half_size, cy - half_size, - cx + half_size, cy + half_size) + half_size = vertex.size / 2.0 + label_drawer.bbox = ( + cx - half_size, + cy - half_size, + cx + half_size, + cy + half_size, + ) label_drawer.draw(wrap=wrap) # Construct the iterator that we will use to draw the edge labels es = graph.es if edge_order is None: # Default edge order - edge_coord_iter = izip(es, edge_builder) + edge_coord_iter = zip(es, edge_builder) else: # Specified edge order edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) @@ -464,8 +485,9 @@ def draw(self, graph, palette, *args, **kwds): continue # Set the font family, size, color and text - context.select_font_face(visual_edge.font, \ - cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + context.select_font_face( + visual_edge.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL + ) context.set_font_size(visual_edge.label_size) context.set_source_rgba(*visual_edge.label_color) label_drawer.text = visual_edge.label @@ -473,8 +495,9 @@ def draw(self, graph, palette, *args, **kwds): # Ask the edge drawer to propose an anchor point for the label src, dest = edge.tuple src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - (x, y), (halign, valign) = \ - edge_drawer.get_label_position(edge, src_vertex, dest_vertex) + (x, y), (halign, valign) = edge_drawer.get_label_position( + edge, src_vertex, dest_vertex + ) # Measure the text _, yb, w, h, _, _ = label_drawer.text_extents() @@ -494,12 +517,13 @@ def draw(self, graph, palette, *args, **kwds): # Draw the edge label label_drawer.halign = halign label_drawer.valign = valign - label_drawer.bbox = (x-w, y-h, x+w, y+h) + label_drawer.bbox = (x - w, y - h, x + w, y + h) label_drawer.draw(wrap=wrap) ##################################################################### + class UbiGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): """Graph drawer that draws a given graph on an UbiGraph display using the XML-RPC API of UbiGraph. @@ -524,15 +548,8 @@ def __init__(self, url="http://localhost:20738/RPC2"): """Constructs an UbiGraph drawer using the display at the given URL.""" super(UbiGraphDrawer, self).__init__(url, "ubigraph") - self.vertex_defaults = dict( - color="#ff0000", - shape="cube", - size=1.0 - ) - self.edge_defaults = dict( - color="#ffffff", - width=1.0 - ) + self.vertex_defaults = dict(color="#ff0000", shape="cube", size=1.0) + self.edge_defaults = dict(color="#ffffff", width=1.0) def draw(self, graph, *args, **kwds): """Draws the given graph on an UbiGraph display. @@ -545,9 +562,9 @@ def draw(self, graph, *args, **kwds): if kwds.get("clear", True): display.clear() - for k, v in self.vertex_defaults.iteritems(): + for k, v in self.vertex_defaults.items(): display.set_vertex_style_attribute(0, k, str(v)) - for k, v in self.edge_defaults.iteritems(): + for k, v in self.edge_defaults.items(): display.set_edge_style_attribute(0, k, str(v)) # Custom color converter function @@ -557,14 +574,16 @@ def color_conv(color): # Construct the visual vertex/edge builders class VisualVertexBuilder(AttributeCollectorBase): """Collects some visual properties of a vertex for drawing""" + _kwds_prefix = "vertex_" color = (str(self.vertex_defaults["color"]), color_conv) label = None shape = str(self.vertex_defaults["shape"]) - size = float(self.vertex_defaults["size"]) + size = float(self.vertex_defaults["size"]) class VisualEdgeBuilder(AttributeCollectorBase): """Collects some visual properties of an edge for drawing""" + _kwds_prefix = "edge_" color = (str(self.edge_defaults["color"]), color_conv) label = None @@ -580,8 +599,10 @@ class VisualEdgeBuilder(AttributeCollectorBase): # Add the edges new_edge = display.new_edge - eids = [new_edge(vertex_ids[edge.source], vertex_ids[edge.target]) \ - for edge in graph.es] + eids = [ + new_edge(vertex_ids[edge.source], vertex_ids[edge.target]) + for edge in graph.es + ] # Add arrowheads if needed if graph.is_directed(): @@ -590,7 +611,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): # Set the vertex attributes set_attr = display.set_vertex_attribute vertex_defaults = self.vertex_defaults - for vertex_id, vertex in izip(vertex_ids, vertex_builder): + for vertex_id, vertex in zip(vertex_ids, vertex_builder): if vertex.color != vertex_defaults["color"]: set_attr(vertex_id, "color", vertex.color) if vertex.label: @@ -603,7 +624,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): # Set the edge attributes set_attr = display.set_edge_attribute edge_defaults = self.edge_defaults - for edge_id, edge in izip(eids, edge_builder): + for edge_id, edge in zip(eids, edge_builder): if edge.color != edge_defaults["color"]: set_attr(edge_id, "color", edge.color) if edge.label: @@ -611,8 +632,10 @@ class VisualEdgeBuilder(AttributeCollectorBase): if edge.width != edge_defaults["width"]: set_attr(edge_id, "width", str(edge.width)) + ##################################################################### + class CytoscapeGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): """Graph drawer that sends/receives graphs to/from Cytoscape using CytoscapeRPC. @@ -643,8 +666,7 @@ def __init__(self, url="http://localhost:9000/Cytoscape"): super(CytoscapeGraphDrawer, self).__init__(url, "Cytoscape") self.network_id = None - def draw(self, graph, name="Network from igraph", create_view=True, - *args, **kwds): + def draw(self, graph, name="Network from igraph", create_view=True, *args, **kwds): """Sends the given graph to Cytoscape as a new network. @param name: the name of the network in Cytoscape. @@ -655,7 +677,7 @@ def draw(self, graph, name="Network from igraph", create_view=True, vertex attribute or a list specifying the identifiers, one for each node in the graph. The default is C{None}, which simply uses the vertex index for each vertex.""" - from xmlrpclib import Fault + from xmlrpc.client import Fault cy = self.service @@ -664,8 +686,10 @@ def draw(self, graph, name="Network from igraph", create_view=True, try: network_id = cy.createNetwork(name, False) except Fault: - warn("CytoscapeRPC too old, cannot create network without view." - " Consider upgrading CytoscapeRPC to use this feature.") + warn( + "CytoscapeRPC too old, cannot create network without view." + " Consider upgrading CytoscapeRPC to use this feature." + ) network_id = cy.createNetwork(name) else: network_id = cy.createNetwork(name) @@ -677,7 +701,7 @@ def draw(self, graph, name="Network from igraph", create_view=True, if isinstance(node_ids, str): node_ids = graph.vs[node_ids] else: - node_ids = range(graph.vcount()) + node_ids = list(range(graph.vcount())) node_ids = [str(identifier) for identifier in node_ids] cy.createNodes(network_id, node_ids) @@ -686,11 +710,13 @@ def draw(self, graph, name="Network from igraph", create_view=True, for v1, v2 in graph.get_edgelist(): edgelists[0].append(node_ids[v1]) edgelists[1].append(node_ids[v2]) - edge_ids = cy.createEdges(network_id, - edgelists[0], edgelists[1], - ["unknown"] * graph.ecount(), - [graph.is_directed()] * graph.ecount(), - False + edge_ids = cy.createEdges( + network_id, + edgelists[0], + edgelists[1], + ["unknown"] * graph.ecount(), + [graph.is_directed()] * graph.ecount(), + False, ) if "layout" in kwds: @@ -698,9 +724,8 @@ def draw(self, graph, name="Network from igraph", create_view=True, layout = self.ensure_layout(kwds["layout"], graph) size = 100 * graph.vcount() ** 0.5 layout.fit_into((size, size), keep_aspect_ratio=True) - layout.translate(-size/2., -size/2.) - cy.setNodesPositions(network_id, - node_ids, *zip(*list(layout))) + layout.translate(-size / 2.0, -size / 2.0) + cy.setNodesPositions(network_id, node_ids, *list(zip(*list(layout)))) else: # Ask Cytoscape to perform the default layout so the user can # at least see something in Cytoscape while the attributes are @@ -717,8 +742,9 @@ def draw(self, graph, name="Network from igraph", create_view=True, # Resolve type conflicts (if any) try: - while attr in attr_names and \ - cy.getNetworkAttributeType(attr) != cy_type: + while ( + attr in attr_names and cy.getNetworkAttributeType(attr) != cy_type + ): attr += "_" except Fault: # getNetworkAttributeType is not available in some older versions @@ -730,11 +756,9 @@ def draw(self, graph, name="Network from igraph", create_view=True, attr_names = set(cy.getNodeAttributeNames()) for attr in graph.vertex_attributes(): cy_type, values = self.infer_cytoscape_type(graph.vs[attr]) - values = dict(pair for pair in izip(node_ids, values) - if pair[1] is not None) + values = dict(pair for pair in zip(node_ids, values) if pair[1] is not None) # Resolve type conflicts (if any) - while attr in attr_names and \ - cy.getNodeAttributeType(attr) != cy_type: + while attr in attr_names and cy.getNodeAttributeType(attr) != cy_type: attr += "_" # Send the attribute values cy.addNodeAttributes(attr, cy_type, values, True) @@ -743,16 +767,14 @@ def draw(self, graph, name="Network from igraph", create_view=True, attr_names = set(cy.getEdgeAttributeNames()) for attr in graph.edge_attributes(): cy_type, values = self.infer_cytoscape_type(graph.es[attr]) - values = dict(pair for pair in izip(edge_ids, values) - if pair[1] is not None) + values = dict(pair for pair in zip(edge_ids, values) if pair[1] is not None) # Resolve type conflicts (if any) - while attr in attr_names and \ - cy.getEdgeAttributeType(attr) != cy_type: + while attr in attr_names and cy.getEdgeAttributeType(attr) != cy_type: attr += "_" # Send the attribute values cy.addEdgeAttributes(attr, cy_type, values) - def fetch(self, name = None, directed = False, keep_canonical_names = False): + def fetch(self, name=None, directed=False, keep_canonical_names=False): """Fetches the network with the given name from Cytoscape. When fetching networks from Cytoscape, the C{canonicalName} attributes @@ -774,15 +796,15 @@ def fetch(self, name = None, directed = False, keep_canonical_names = False): version = version.split(" ")[0] version = tuple(map(int, version.split(".")[:2])) if version < (1, 3): - raise NotImplementedError("CytoscapeGraphDrawer requires " - "Cytoscape-RPC 1.3 or newer") + raise NotImplementedError( + "CytoscapeGraphDrawer requires " "Cytoscape-RPC 1.3 or newer" + ) # Find out the ID of the network we are interested in if name is None: network_id = cy.getNetworkID() else: - network_id = [k for k, v in cy.getNetworkList().iteritems() - if v == name] + network_id = [k for k, v in cy.getNetworkList().items() if v == name] if not network_id: raise ValueError("no such network: %r" % name) elif len(network_id) > 1: @@ -805,11 +827,11 @@ def fetch(self, name = None, directed = False, keep_canonical_names = False): continue has_attr = cy.nodesHaveAttribute(attr_name, vertices) filtered = [idx for idx, ok in enumerate(has_attr) if ok] - values = cy.getNodesAttributes(attr_name, - [name for name, ok in izip(vertices, has_attr) if ok] + values = cy.getNodesAttributes( + attr_name, [name for name, ok in zip(vertices, has_attr) if ok] ) attrs = [None] * n - for idx, value in izip(filtered, values): + for idx, value in zip(filtered, values): attrs[idx] = value vertex_attrs[attr_name] = attrs @@ -821,11 +843,11 @@ def fetch(self, name = None, directed = False, keep_canonical_names = False): continue has_attr = cy.edgesHaveAttribute(attr_name, edges) filtered = [idx for idx, ok in enumerate(has_attr) if ok] - values = cy.getEdgesAttributes(attr_name, - [name for name, ok in izip(edges, has_attr) if ok] + values = cy.getEdgesAttributes( + attr_name, [name for name, ok in zip(edges, has_attr) if ok] ) attrs = [None] * m - for idx, value in izip(filtered, values): + for idx, value in zip(filtered, values): attrs[idx] = value edge_attrs[attr_name] = attrs @@ -840,9 +862,14 @@ def fetch(self, name = None, directed = False, keep_canonical_names = False): edge_list.append((vertex_name_index[parts[0]], vertex_name_index[parts[2]])) del edges - return Graph(n, edge_list, directed=directed, - graph_attrs=graph_attrs, vertex_attrs=vertex_attrs, - edge_attrs=edge_attrs) + return Graph( + n, + edge_list, + directed=directed, + graph_attrs=graph_attrs, + vertex_attrs=vertex_attrs, + edge_attrs=edge_attrs, + ) @staticmethod def infer_cytoscape_type(values): @@ -858,17 +885,18 @@ def infer_cytoscape_type(values): types = [type(value) for value in values if value is not None] if all(t == bool for t in types): return "BOOLEAN", values - if all(issubclass(t, (int, long)) for t in types): + if all(issubclass(t, (int, int)) for t in types): return "INTEGER", values if all(issubclass(t, float) for t in types): return "FLOATING", values return "STRING", [ - str(value) if not isinstance(value, basestring) else value - for value in values + str(value) if not isinstance(value, str) else value for value in values ] + ##################################################################### + class GephiGraphStreamingDrawer(AbstractGraphDrawer): """Graph drawer that sends a graph to a file-like object (e.g., socket, URL connection, file) using the Gephi graph streaming format. @@ -913,6 +941,7 @@ def __init__(self, conn=None, *args, **kwds): super(GephiGraphStreamingDrawer, self).__init__() from igraph.remote.gephi import GephiGraphStreamer, GephiConnection + self.connection = conn or GephiConnection(*args, **kwds) self.streamer = GephiGraphStreamer() @@ -927,21 +956,21 @@ def draw(self, graph, *args, **kwds): """ self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) + ##################################################################### + class MatplotlibGraphDrawer(AbstractGraphDrawer): """Graph drawer that uses a pyplot.Axes as context""" _shape_dict = { - 'rectangle': 's', - 'circle': 'o', - 'hidden': 'none', - 'triangle-up': '^', - 'triangle-down': 'v', + "rectangle": "s", + "circle": "o", + "hidden": "none", + "triangle-up": "^", + "triangle-down": "v", } - - def __init__(self, ax): """Constructs the graph drawer and associates it with the mpl axes""" self.ax = ax @@ -956,9 +985,9 @@ def draw(self, graph, *args, **kwds): import numpy as np def shrink_vertex(ax, aux, vcoord, vsize_squared): - '''Shrink edge by vertex size''' + """Shrink edge by vertex size""" aux_display, vcoord_display = ax.transData.transform([aux, vcoord]) - d = sqrt(((aux_display - vcoord_display)**2).sum()) + d = sqrt(((aux_display - vcoord_display) ** 2).sum()) fr = sqrt(vsize_squared) / d end_display = vcoord_display + fr * (aux_display - vcoord_display) end = ax.transData.inverted().transform(end_display) @@ -982,7 +1011,7 @@ def callback_edge_offset(event): # FIXME: deal with unnamed *args # Get layout - layout = kwds.get('layout', graph.layout()) + layout = kwds.get("layout", graph.layout()) if isinstance(layout, str): layout = graph.layout(layout) @@ -993,7 +1022,7 @@ def callback_edge_offset(event): nv = graph.vcount() # Vertex size - vsizes = kwds.get('vertex_size', 5) + vsizes = kwds.get("vertex_size", 5) # Enforce numpy array for sizes, because (1) we need the square and (2) # they are needed to calculate autoshrinking of edges if np.isscalar(vsizes): @@ -1004,24 +1033,24 @@ def callback_edge_offset(event): vsizes **= 2 # Vertex color - c = kwds.get('vertex_color', 'steelblue') + c = kwds.get("vertex_color", "steelblue") # Vertex opacity - alpha = kwds.get('alpha', 1.0) + alpha = kwds.get("alpha", 1.0) # Vertex labels - label = kwds.get('vertex_label', None) + label = kwds.get("vertex_label", None) # Vertex label size - label_size = kwds.get('vertex_label_size', mpl.rcParams['font.size']) + label_size = kwds.get("vertex_label_size", mpl.rcParams["font.size"]) # Vertex zorder - vzorder = kwds.get('vertex_order', 2) + vzorder = kwds.get("vertex_order", 2) # Vertex shapes # mpl shapes use slightly different names from Cairo, but we want the # API to feel consistent, so we use a conversion dictionary - shapes = kwds.get('vertex_shape', 'o') + shapes = kwds.get("vertex_shape", "o") if shapes is not None: if isinstance(shapes, str): shapes = self._shape_dict.get(shapes, shapes) @@ -1038,19 +1067,19 @@ def callback_edge_offset(event): xi, yi = x[i], y[i] ax.text(xi, yi, lab, fontsize=label_size) - dx = (max(x) - min(x)) - dy = (max(y) - min(y)) + dx = max(x) - min(x) + dy = max(y) - min(y) ax.set_xlim(min(x) - 0.05 * dx, max(x) + 0.05 * dx) ax.set_ylim(min(y) - 0.05 * dy, max(y) + 0.05 * dy) # Edge properties ne = graph.ecount() - ec = kwds.get('edge_color', 'black') - edge_width = kwds.get('edge_width', 1) - arrow_width = kwds.get('edge_arrow_width', 2) - arrow_length = kwds.get('edge_arrow_size', 4) - ealpha = kwds.get('edge_alpha', 1.0) - ezorder = kwds.get('edge_order', 1.0) + ec = kwds.get("edge_color", "black") + edge_width = kwds.get("edge_width", 1) + arrow_width = kwds.get("edge_arrow_width", 2) + arrow_length = kwds.get("edge_arrow_size", 4) + ealpha = kwds.get("edge_alpha", 1.0) + ezorder = kwds.get("edge_order", 1.0) try: ezorder = float(ezorder) ezorder = [ezorder] * ne @@ -1060,10 +1089,14 @@ def callback_edge_offset(event): # Decide whether we need to calculate the curvature of edges # automatically -- and calculate them if needed. autocurve = kwds.get("autocurve", None) - if autocurve or (autocurve is None and \ - "edge_curved" not in kwds and "curved" not in graph.edge_attributes() \ - and graph.ecount() < 10000): + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in graph.edge_attributes() + and graph.ecount() < 10000 + ): from igraph import autocurve + default = kwds.get("edge_curved", 0) if default is True: default = 0.5 @@ -1073,14 +1106,16 @@ def callback_edge_offset(event): # Arrow style for directed and undirected graphs if graph.is_directed(): arrowstyle = ArrowStyle( - '-|>', head_length=arrow_length, head_width=arrow_width, + "-|>", + head_length=arrow_length, + head_width=arrow_width, ) else: - arrowstyle = '-' + arrowstyle = "-" # Edge coordinates and curvature nloops = [0 for x in range(ne)] - has_curved = 'curved' in graph.es.attributes() + has_curved = "curved" in graph.es.attributes() arrows = [] for ie, edge in enumerate(graph.es): src, tgt = edge.source, edge.target @@ -1097,7 +1132,7 @@ def callback_edge_offset(event): nloopstot += 1 continue xn, yn = vcoord[tgtn] - angles.append(180. / pi * atan2(yn - y1, xn - x1) % 360) + angles.append(180.0 / pi * atan2(yn - y1, xn - x1) % 360) # with .neighbors(mode=ALL), which is default, loops are double # counted nloopstot //= 2 @@ -1110,9 +1145,11 @@ def callback_edge_offset(event): # Only one self loop, use a quadrant only angles = [(ashift + 135) % 360, (ashift + 225) % 360] else: - nshift = 360. / nloopstot - angles = [(ashift + nshift * nloops[src]) % 360, - (ashift + nshift * (nloops[src] + 1)) % 360] + nshift = 360.0 / nloopstot + angles = [ + (ashift + nshift * nloops[src]) % 360, + (ashift + nshift * (nloops[src] + 1)) % 360, + ] nloops[src] += 1 else: angles.append(angles[0] + 360) @@ -1123,11 +1160,13 @@ def callback_edge_offset(event): if diffi > diff: idiff = i diff = diffi - angles = angles[idiff: idiff + 2] + angles = angles[idiff : idiff + 2] ashift = angles[0] nshift = (angles[1] - angles[0]) / nloopstot - angles = [(ashift + nshift * nloops[src]), - (ashift + nshift * (nloops[src] + 1))] + angles = [ + (ashift + nshift * nloops[src]), + (ashift + nshift * (nloops[src] + 1)), + ] nloops[src] += 1 # this is not great, but alright @@ -1138,32 +1177,40 @@ def callback_edge_offset(event): else: angmid1 = angles[0] + 0.5 * (angspan - 180) + 45 angmid2 = angles[1] - 0.5 * (angspan - 180) - 45 - aux1 = (x1 + 0.2 * dx * cos(pi / 180 * angmid1), - y1 + 0.2 * dy * sin(pi / 180 * angmid1)) - aux2 = (x1 + 0.2 * dx * cos(pi / 180 * angmid2), - y1 + 0.2 * dy * sin(pi / 180 * angmid2)) + aux1 = ( + x1 + 0.2 * dx * cos(pi / 180 * angmid1), + y1 + 0.2 * dy * sin(pi / 180 * angmid1), + ) + aux2 = ( + x1 + 0.2 * dx * cos(pi / 180 * angmid2), + y1 + 0.2 * dy * sin(pi / 180 * angmid2), + ) start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) path = Path( [start, aux1, aux2, end], # Cubic bezier by mpl - codes=[1, 4, 4, 4]) + codes=[1, 4, 4, 4], + ) else: - curved = edge['curved'] if has_curved else False + curved = edge["curved"] if has_curved else False if curved: - aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), \ - (2 * y1 + y2) / 3.0 + edge.curved * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), \ - (y1 + 2 * y2) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) path = Path( [start, aux1, aux2, end], # Cubic bezier by mpl - codes=[1, 4, 4, 4]) + codes=[1, 4, 4, 4], + ) else: start = shrink_vertex(ax, (x2, y2), (x1, y1), vsizes[src]) end = shrink_vertex(ax, (x1, y1), (x2, y2), vsizes[tgt]) @@ -1176,7 +1223,8 @@ def callback_edge_offset(event): lw=edge_width, color=ec, alpha=ealpha, - zorder=ezorder[ie]) + zorder=ezorder[ie], + ) ax.add_artist(arrow) # Store arrows and their sources and targets for autoscaling @@ -1184,6 +1232,6 @@ def callback_edge_offset(event): # Autoscaling during zoom, figure resize, reset axis limits callback = callback_factory(ax, vcoord, vsizes, arrows) - ax.get_figure().canvas.mpl_connect('resize_event', callback) - ax.callbacks.connect('xlim_changed', callback) - ax.callbacks.connect('ylim_changed', callback) + ax.get_figure().canvas.mpl_connect("resize_event", callback) + ax.callbacks.connect("xlim_changed", callback) + ax.callbacks.connect("ylim_changed", callback) diff --git a/src/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py index 44a22263e..3e78a39da 100644 --- a/src/igraph/drawing/metamagic.py +++ b/src/igraph/drawing/metamagic.py @@ -60,8 +60,8 @@ class VisualEdgeBuilder(AttributeCollectorBase): @see: AttributeCollectorMeta, AttributeCollectorBase """ -from ConfigParser import NoOptionError -from itertools import izip +from configparser import NoOptionError + from igraph.configuration import Configuration @@ -72,21 +72,21 @@ class VisualEdgeBuilder(AttributeCollectorBase): class AttributeSpecification(object): """Class that describes how the value of a given attribute should be retrieved. - + The class contains the following members: - + - C{name}: the name of the attribute. This is also used when we are trying to get its value from a vertex/edge attribute of a graph. - + - C{alt_name}: alternative name of the attribute. This is used when we are trying to get its value from a Python dict or an L{igraph.Configuration} object. If omitted at construction time, it will be equal to C{name}. - + - C{default}: the default value of the attribute when none of the sources we try can provide a meaningful value. - + - C{transform}: optional transformation to be performed on the attribute value. If C{None} or omitted, it defaults to the type of the default value. @@ -95,11 +95,9 @@ class AttributeSpecification(object): index in order to derive the value of the attribute. """ - __slots__ = ("name", "alt_name", "default", "transform", "accessor", - "func") + __slots__ = ("name", "alt_name", "default", "transform", "accessor", "func") - def __init__(self, name, default=None, alt_name=None, transform=None, - func=None): + def __init__(self, name, default=None, alt_name=None, transform=None, func=None): if isinstance(default, tuple): default, transform = default @@ -111,7 +109,7 @@ def __init__(self, name, default=None, alt_name=None, transform=None, self.accessor = None if self.transform and not hasattr(self.transform, "__call__"): - raise TypeError, "transform must be callable" + raise TypeError("transform must be callable") if self.transform is None and self.default is not None: self.transform = type(self.default) @@ -119,7 +117,7 @@ def __init__(self, name, default=None, alt_name=None, transform=None, class AttributeCollectorMeta(type): """Metaclass for attribute collector classes - + Classes that use this metaclass are intended to collect vertex/edge attributes from various sources (a Python dict, a vertex/edge sequence, default values from the igraph configuration and such) in a given @@ -154,7 +152,7 @@ class AttributeCollectorMeta(type): def __new__(mcs, name, bases, attrs): attr_specs = [] - for attr, value in attrs.iteritems(): + for attr, value in attrs.items(): if attr.startswith("_") or hasattr(value, "__call__"): continue if isinstance(value, AttributeSpecification): @@ -173,37 +171,37 @@ def __new__(mcs, name, bases, attrs): attrs["_attributes"] = attr_specs attrs["Element"] = mcs.record_generator( - "%s.Element" % name, - (attr_spec.name for attr_spec in attr_specs) + "%s.Element" % name, (attr_spec.name for attr_spec in attr_specs) ) - return super(AttributeCollectorMeta, mcs).__new__(mcs, \ - name, bases, attrs) + return super(AttributeCollectorMeta, mcs).__new__(mcs, name, bases, attrs) @classmethod def record_generator(mcs, name, slots): """Generates a simple class that has the given slots and nothing else""" + class Element(object): """A simple class that holds the attributes collected by the attribute collector""" + __slots__ = tuple(slots) + def __init__(self, attrs=()): for attr, value in attrs: setattr(self, attr, value) + Element.__name__ = name return Element -class AttributeCollectorBase(object): +class AttributeCollectorBase(object, metaclass=AttributeCollectorMeta): """Base class for attribute collector subclasses. Classes that inherit this class may use a declarative syntax to specify which vertex or edge attributes they intend to collect. See L{AttributeCollectorMeta} for the details. """ - __metaclass__ = AttributeCollectorMeta - - def __init__(self, seq, kwds = None): + def __init__(self, seq, kwds=None): """Constructs a new attribute collector that uses the given vertex/edge sequence and the given dict as data sources. @@ -213,15 +211,15 @@ def __init__(self, seq, kwds = None): attributes collected from I{seq} if necessary. """ elt = self.__class__.Element - self._cache = [elt() for _ in xrange(len(seq))] + self._cache = [elt() for _ in range(len(seq))] self.seq = seq self.kwds = kwds or {} for attr_spec in self._attributes: - values = self._collect_attributes(attr_spec) + values = self._collect_attributes(attr_spec) attr_name = attr_spec.name - for cache_elt, val in izip(self._cache, values): + for cache_elt, val in zip(self._cache, values): setattr(cache_elt, attr_name, val) def _collect_attributes(self, attr_spec, config=None): @@ -260,7 +258,7 @@ def _collect_attributes(self, attr_spec, config=None): n = len(seq) - # Special case if the attribute name is "label" + # Special case if the attribute name is "label" if attr_spec.name == "label": if attr_spec.alt_name in kwds and kwds[attr_spec.alt_name] is None: return [None] * n @@ -269,7 +267,7 @@ def _collect_attributes(self, attr_spec, config=None): # values, call it and store the results if attr_spec.func is not None: func = attr_spec.func - result = [func(i) for i in xrange(n)] + result = [func(i) for i in range(n)] return result # Get the configuration object @@ -294,8 +292,7 @@ def _collect_attributes(self, attr_spec, config=None): len(result) except TypeError: result = [result] * n - result = [result[idx] or attrs[idx] \ - for idx in xrange(len(result))] + result = [result[idx] or attrs[idx] for idx in range(len(result))] # Special case for string overrides, strings are not treated # as sequences here @@ -314,10 +311,10 @@ def _collect_attributes(self, attr_spec, config=None): # Ensure that the length is n while len(result) < n: - if len(result) <= n/2: + if len(result) <= n / 2: result.extend(result) else: - result.extend(result[0:(n-len(result))]) + result.extend(result[0 : (n - len(result))]) # By now, the length of the result vector should be n as requested # Get the configuration defaults @@ -330,7 +327,7 @@ def _collect_attributes(self, attr_spec, config=None): default = attr_spec.default # Fill the None values with the default values - for idx in xrange(len(result)): + for idx in range(len(result)): if result[idx] is None: result[idx] = default @@ -341,7 +338,6 @@ def _collect_attributes(self, attr_spec, config=None): return result - def __getitem__(self, index): """Returns the collected attributes of the vertex/edge with the given index.""" @@ -351,6 +347,3 @@ def __getitem__(self, index): def __len__(self): return len(self.seq) - - - diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 741aa9ef6..2a8882189 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -16,11 +16,10 @@ name in the C{shape} attribute of vertices. """ -from __future__ import division __all__ = ["ShapeDrawerDirectory"] -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -47,9 +46,10 @@ from igraph.drawing.utils import Point from igraph.utils import consecutive_pairs + class ShapeDrawer(object): """Static class, the ancestor of all vertex shape drawer classes. - + Custom shapes must implement at least the C{draw_path} method of the class. The method I{must not} stroke or fill, it should just set up the current Cairo path appropriately.""" @@ -72,8 +72,7 @@ def draw_path(ctx, center_x, center_y, width, height=None): # pylint: disable-msg=W0613 @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the shape centered at (center_x, center_y) intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @@ -94,6 +93,7 @@ class NullDrawer(ShapeDrawer): """Static drawer class which draws nothing. This class is used for graph vertices with unknown shapes""" + names = ["null", "none", "empty", "hidden", ""] @staticmethod @@ -104,6 +104,7 @@ def draw_path(ctx, center_x, center_y, width, height=None): class RectangleDrawer(ShapeDrawer): """Static class which draws rectangular vertices""" + names = "rectangle rect rectangular square box" @staticmethod @@ -112,62 +113,61 @@ def draw_path(ctx, center_x, center_y, width, height=None): or filling it. @see: ShapeDrawer.draw_path""" height = height or width - ctx.rectangle(center_x - width/2, center_y - height/2, - width, height) + ctx.rectangle(center_x - width / 2, center_y - height / 2, width, height) # pylint: disable-msg=C0103, R0911 # R0911: too many return statements @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the rectangle centered at (center_x, center_y) having the given width and height intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @see: ShapeDrawer.intersection_point""" height = height or width - delta_x, delta_y = center_x-source_x, center_y-source_y + delta_x, delta_y = center_x - source_x, center_y - source_y if delta_x == 0 and delta_y == 0: return center_x, center_y if delta_y > 0 and delta_x <= delta_y and delta_x >= -delta_y: # this is the top edge - ry = center_y - height/2 - ratio = (height/2) / delta_y - return center_x-ratio*delta_x, ry + ry = center_y - height / 2 + ratio = (height / 2) / delta_y + return center_x - ratio * delta_x, ry if delta_y < 0 and delta_x <= -delta_y and delta_x >= delta_y: # this is the bottom edge - ry = center_y + height/2 - ratio = (height/2) / -delta_y - return center_x-ratio*delta_x, ry + ry = center_y + height / 2 + ratio = (height / 2) / -delta_y + return center_x - ratio * delta_x, ry if delta_x > 0 and delta_y <= delta_x and delta_y >= -delta_x: # this is the left edge - rx = center_x - width/2 - ratio = (width/2) / delta_x - return rx, center_y-ratio*delta_y + rx = center_x - width / 2 + ratio = (width / 2) / delta_x + return rx, center_y - ratio * delta_y if delta_x < 0 and delta_y <= -delta_x and delta_y >= delta_x: # this is the right edge - rx = center_x + width/2 - ratio = (width/2) / -delta_x - return rx, center_y-ratio*delta_y + rx = center_x + width / 2 + ratio = (width / 2) / -delta_x + return rx, center_y - ratio * delta_y if delta_x == 0: if delta_y > 0: - return center_x, center_y - height/2 - return center_x, center_y + height/2 + return center_x, center_y - height / 2 + return center_x, center_y + height / 2 if delta_y == 0: if delta_x > 0: - return center_x - width/2, center_y - return center_x + width/2, center_y + return center_x - width / 2, center_y + return center_x + width / 2, center_y class CircleDrawer(ShapeDrawer): """Static class which draws circular vertices""" + names = "circle circular" @staticmethod @@ -178,41 +178,39 @@ def draw_path(ctx, center_x, center_y, width, height=None): Height is ignored, it is the width that determines the diameter of the circle. @see: ShapeDrawer.draw_path""" - ctx.arc(center_x, center_y, width/2, 0, 2*pi) + ctx.arc(center_x, center_y, width / 2, 0, 2 * pi) @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the circle centered at (center_x, center_y) intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @see: ShapeDrawer.intersection_point""" height = height or width - angle = atan2(center_y-source_y, center_x-source_x) - return center_x-width/2 * cos(angle), \ - center_y-height/2* sin(angle) + angle = atan2(center_y - source_y, center_x - source_x) + return center_x - width / 2 * cos(angle), center_y - height / 2 * sin(angle) class UpTriangleDrawer(ShapeDrawer): """Static class which draws upright triangles""" + names = "triangle triangle-up up-triangle arrow arrow-up up-arrow" @staticmethod def draw_path(ctx, center_x, center_y, width, height=None): """Draws an upright triangle on the Cairo context without stroking or filling it. - + @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x-width/2, center_y+height/2) - ctx.line_to(center_x, center_y-height/2) - ctx.line_to(center_x+width/2, center_y+height/2) + ctx.move_to(center_x - width / 2, center_y + height / 2) + ctx.line_to(center_x, center_y - height / 2) + ctx.line_to(center_x + width / 2, center_y + height / 2) ctx.close_path() @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the triangle centered at (center_x, center_y) intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @@ -222,25 +220,26 @@ def intersection_point(center_x, center_y, source_x, source_y, \ height = height or width return center_x, center_y + class DownTriangleDrawer(ShapeDrawer): """Static class which draws triangles pointing down""" + names = "down-triangle triangle-down arrow-down down-arrow" @staticmethod def draw_path(ctx, center_x, center_y, width, height=None): """Draws a triangle on the Cairo context without stroking or filling it. - + @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x-width/2, center_y-height/2) - ctx.line_to(center_x, center_y+height/2) - ctx.line_to(center_x+width/2, center_y-height/2) + ctx.move_to(center_x - width / 2, center_y - height / 2) + ctx.line_to(center_x, center_y + height / 2) + ctx.line_to(center_x + width / 2, center_y - height / 2) ctx.close_path() @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the triangle centered at (center_x, center_y) intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @@ -250,26 +249,27 @@ def intersection_point(center_x, center_y, source_x, source_y, \ height = height or width return center_x, center_y + class DiamondDrawer(ShapeDrawer): """Static class which draws diamonds (i.e. rhombuses)""" + names = "diamond rhombus" @staticmethod def draw_path(ctx, center_x, center_y, width, height=None): """Draws a rhombus on the Cairo context without stroking or filling it. - + @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x-width/2, center_y) - ctx.line_to(center_x, center_y+height/2) - ctx.line_to(center_x+width/2, center_y) - ctx.line_to(center_x, center_y-height/2) + ctx.move_to(center_x - width / 2, center_y) + ctx.line_to(center_x, center_y + height / 2) + ctx.line_to(center_x + width / 2, center_y) + ctx.line_to(center_x, center_y - height / 2) ctx.close_path() @staticmethod - def intersection_point(center_x, center_y, source_x, source_y, \ - width, height=None): + def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the rhombus centered at (center_x, center_y) intersects with a line drawn from (source_x, source_y) to (center_x, center_y). @@ -293,20 +293,22 @@ def intersection_point(center_x, center_y, source_x, source_y, \ height = copysign(height, delta_y) f = height / (height + width * delta_y / delta_x) - return center_x + f * width / 2, center_y + (1-f) * height / 2 + return center_x + f * width / 2, center_y + (1 - f) * height / 2 + ##################################################################### + class PolygonDrawer(AbstractCairoDrawer): """Class that is used to draw polygons. - + The corner points of the polygon can be set by the C{points} property of the drawer, or passed at construction time. Most drawing methods in this class also have an extra C{points} argument that can be used to override the set of points in the C{points} property.""" - def __init__(self, context, bbox=(1, 1), points = []): + def __init__(self, context, bbox=(1, 1), points=[]): """Constructs a new polygon drawer that draws on the given Cairo context. @@ -354,13 +356,12 @@ def draw_path(self, points=None, corner_radius=0): # is the smaller of the radii on the two sides adjacent to # the corner. points = [Point(*point) for point in points] - side_vecs = [v-u for u, v in consecutive_pairs(points, circular=True)] + side_vecs = [v - u for u, v in consecutive_pairs(points, circular=True)] half_side_lengths = [side.length() / 2 for side in side_vecs] corner_radii = [corner_radius] * len(points) - for idx in xrange(len(corner_radii)): + for idx in range(len(corner_radii)): prev_idx = -1 if idx == 0 else idx - 1 - radii = [corner_radius, half_side_lengths[prev_idx], - half_side_lengths[idx]] + radii = [corner_radius, half_side_lengths[prev_idx], half_side_lengths[idx]] corner_radii[idx] = min(radii) # Okay, move to the last corner, adjusted by corner_radii[-1] @@ -375,8 +376,9 @@ def draw_path(self, points=None, corner_radius=0): ctx.line_to(*v.towards(u, radius)) aux1 = v.towards(u, radius / 2) aux2 = v.towards(w, radius / 2) - ctx.curve_to(aux1.x, aux1.y, aux2.x, aux2.y, - *v.towards(w, corner_radii[idx])) + ctx.curve_to( + aux1.x, aux1.y, aux2.x, aux2.y, *v.towards(w, corner_radii[idx]) + ) u = v def draw(self, points=None): @@ -389,12 +391,14 @@ def draw(self, points=None): self.draw_path(points) self.context.stroke() + ##################################################################### + class ShapeDrawerDirectory(object): """Static class that resolves shape names to their corresponding shape drawer classes. - + Classes that are derived from L{ShapeDrawer} in this module are automatically registered by L{ShapeDrawerDirectory} when the module is loaded for the first time. @@ -409,7 +413,7 @@ def register(cls, drawer_class): @param drawer_class: the shape drawer class to be registered """ names = drawer_class.names - if isinstance(names, (str, unicode)): + if isinstance(names, str): names = names.split() for name in names: @@ -420,7 +424,7 @@ def register_namespace(cls, namespace): """Registers all L{ShapeDrawer} classes in the given namespace @param namespace: a Python dict mapping names to Python objects.""" - for name, value in namespace.iteritems(): + for name, value in namespace.items(): if name.startswith("__"): continue if isinstance(value, type): @@ -430,7 +434,7 @@ def register_namespace(cls, namespace): @classmethod def resolve(cls, shape): """Given a shape name, returns the corresponding shape drawer class - + @param shape: the name of the shape @return: the corresponding shape drawer class @@ -445,7 +449,7 @@ def resolve(cls, shape): def resolve_default(cls, shape, default=NullDrawer): """Given a shape name, returns the corresponding shape drawer class or the given default shape drawer if the shape name is unknown. - + @param shape: the name of the shape @param default: the default shape drawer to return when the shape is unknown @@ -454,5 +458,5 @@ def resolve_default(cls, shape, default=NullDrawer): """ return cls.known_shapes.get(shape, default) -ShapeDrawerDirectory.register_namespace(sys.modules[__name__].__dict__) +ShapeDrawerDirectory.register_namespace(sys.modules[__name__].__dict__) diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index bff01c897..323e8ec20 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -6,7 +6,6 @@ import re -from igraph.compat import property from igraph.drawing.baseclasses import AbstractCairoDrawer from warnings import warn @@ -17,14 +16,17 @@ ##################################################################### + class TextAlignment(object): """Text alignment constants.""" LEFT, CENTER, RIGHT = "left", "center", "right" TOP, BOTTOM = "top", "bottom" + ##################################################################### + class TextDrawer(AbstractCairoDrawer): """Class that draws text on a Cairo context. @@ -70,7 +72,7 @@ def draw(self, wrap=False): dy = bbox.height - total_height - yb + font_descent elif self.valign == self.CENTER: # Centered vertical alignment - dy = (bbox.height - total_height - yb + font_descent + line_height) / 2. + dy = (bbox.height - total_height - yb + font_descent + line_height) / 2.0 else: # Top vertical alignment dy = line_height @@ -80,7 +82,7 @@ def draw(self, wrap=False): ctx.show_text(line) ctx.new_path() - def get_text_layout(self, x = None, y = None, width = None, wrap = False): + def get_text_layout(self, x=None, y=None, width=None, wrap=False): """Calculates the layout of the current text. `x` and `y` denote the coordinates where the drawing should start. If they are both ``None``, the current position of the context will be used. @@ -131,7 +133,7 @@ def get_text_layout(self, x = None, y = None, width = None, wrap = False): if width is None: width = self.text_extents()[2] for line, line_width, x_bearing in iterlines: - result.append((x + (width-line_width)/2. - x_bearing, y, line)) + result.append((x + (width - line_width) / 2.0 - x_bearing, y, line)) y += line_height elif self.halign == self.RIGHT: @@ -146,12 +148,12 @@ def get_text_layout(self, x = None, y = None, width = None, wrap = False): else: # Left alignment for line, _, x_bearing in iterlines: - result.append((x-x_bearing, y, line)) + result.append((x - x_bearing, y, line)) y += line_height return result - def draw_at(self, x = None, y = None, width = None, wrap = False): + def draw_at(self, x=None, y=None, width=None, wrap=False): """Draws the text by setting up an appropriate path on the Cairo context and filling it. `x` and `y` denote the coordinates where the drawing should start. If they are both ``None``, the current position @@ -263,8 +265,14 @@ def text_extents(self): if len(lines) <= 1: return self.context.text_extents(self.text) - x_bearing, y_bearing, width, height, x_advance, y_advance = \ - self.context.text_extents(lines[0]) + ( + x_bearing, + y_bearing, + width, + height, + x_advance, + y_advance, + ) = self.context.text_extents(lines[0]) line_height = self.context.font_extents()[2] for line in lines[1:]: @@ -275,10 +283,12 @@ def text_extents(self): return x_bearing, y_bearing, width, height, x_advance, y_advance + def test(): """Testing routine for L{TextDrawer}""" import math from igraph.drawing.utils import find_cairo + cairo = find_cairo() text = "The quick brown fox\njumps over a\nlazy dog" @@ -289,7 +299,7 @@ def test(): drawer = TextDrawer(context, text) context.set_source_rgb(1, 1, 1) - context.set_font_size(16.) + context.set_font_size(16.0) context.rectangle(0, 0, width, height) context.fill() @@ -344,15 +354,17 @@ def mark_point(red, green, blue): context.set_source_rgb(0, 0, 0) drawer.halign = halign drawer.valign = valign - drawer.bbox = (i*200, j*200+200, i*200+200, j*200+400) + drawer.bbox = (i * 200, j * 200 + 200, i * 200 + 200, j * 200 + 400) drawer.draw() # Mark the new reference point mark_point(1, 0, 0) # Testing TextDrawer.wrap() - drawer.text = "Jackdaws love my big sphinx of quartz. Yay, wrapping! " + \ - "Jackdaws love my big sphinx of quartz.\n\n" + \ - "Jackdaws love my big sphinx of quartz." + drawer.text = ( + "Jackdaws love my big sphinx of quartz. Yay, wrapping! " + + "Jackdaws love my big sphinx of quartz.\n\n" + + "Jackdaws love my big sphinx of quartz." + ) drawer.valign = TextDrawer.TOP for i, halign in enumerate(("left", "center", "right")): context.move_to(i * 200, 840) @@ -370,6 +382,6 @@ def mark_point(red, green, blue): surface.write_to_png("test.png") + if __name__ == "__main__": test() - diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 205b55044..32ba062f8 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -2,8 +2,7 @@ Utility classes for drawing routines. """ -from igraph.compat import property -from itertools import izip + from math import atan2, cos, sin from operator import itemgetter @@ -12,6 +11,7 @@ ##################################################################### + class Rectangle(object): """Class representing a rectangle.""" @@ -174,13 +174,13 @@ def contract(self, margins): margins = [float(margins)] * 4 if len(margins) != 4: raise ValueError("margins must be a 4-tuple or a single number") - nx1, ny1 = self._left+margins[0], self._top+margins[1] - nx2, ny2 = self._right-margins[2], self._bottom-margins[3] + nx1, ny1 = self._left + margins[0], self._top + margins[1] + nx2, ny2 = self._right - margins[2], self._bottom - margins[3] if nx1 > nx2: - nx1 = (nx1+nx2)/2. + nx1 = (nx1 + nx2) / 2.0 nx2 = nx1 if ny1 > ny2: - ny1 = (ny1+ny2)/2. + ny1 = (ny1 + ny2) / 2.0 ny2 = ny1 return self.__class__(nx1, ny1, nx2, ny2) @@ -210,8 +210,12 @@ def isdisjoint(self, other): >>> r3.isdisjoint(r1) True """ - return self._left > other._right or self._right < other._left \ - or self._top > other._bottom or self._bottom < other._top + return ( + self._left > other._right + or self._right < other._left + or self._top > other._bottom + or self._bottom < other._top + ) def isempty(self): """Returns ``True`` if the rectangle is empty (i.e. it has zero @@ -249,10 +253,13 @@ def intersection(self, other): """ if self.isdisjoint(other): return Rectangle(0, 0, 0, 0) - return Rectangle(max(self._left, other._left), - max(self._top, other._top), - min(self._right, other._right), - min(self._bottom, other._bottom)) + return Rectangle( + max(self._left, other._left), + max(self._top, other._top), + min(self._right, other._right), + min(self._bottom, other._bottom), + ) + __and__ = intersection def translate(self, dx, dy): @@ -293,10 +300,13 @@ def union(self, other): >>> r1.union(r3) Rectangle(10.0, 10.0, 90.0, 90.0) """ - return Rectangle(min(self._left, other._left), - min(self._top, other._top), - max(self._right, other._right), - max(self._bottom, other._bottom)) + return Rectangle( + min(self._left, other._left), + min(self._top, other._top), + max(self._right, other._right), + max(self._bottom, other._bottom), + ) + __or__ = union def __ior__(self, other): @@ -315,15 +325,20 @@ def __ior__(self, other): >>> r1 Rectangle(10.0, 10.0, 90.0, 90.0) """ - self._left = min(self._left, other._left) - self._top = min(self._top, other._top) - self._right = max(self._right, other._right) + self._left = min(self._left, other._left) + self._top = min(self._top, other._top) + self._right = max(self._right, other._right) self._bottom = max(self._bottom, other._bottom) return self def __repr__(self): - return "%s(%s, %s, %s, %s)" % (self.__class__.__name__, \ - self._left, self._top, self._right, self._bottom) + return "%s(%s, %s, %s, %s)" % ( + self.__class__.__name__, + self._left, + self._top, + self._right, + self._bottom, + ) def __eq__(self, other): return self.coords == other.coords @@ -334,14 +349,13 @@ def __ne__(self, other): def __bool__(self): return self._left != self._right or self._top != self._bottom - def __nonzero__(self): - return self._left != self._right or self._top != self._bottom - def __hash__(self): return hash(self.coords) + ##################################################################### + class BoundingBox(Rectangle): """Class representing a bounding box (a rectangular area) that encloses some objects.""" @@ -358,9 +372,9 @@ def __ior__(self, other): >>> print(box1) BoundingBox(10.0, 20.0, 100.0, 90.0) """ - self._left = min(self._left, other._left) - self._top = min(self._top, other._top) - self._right = max(self._right, other._right) + self._left = min(self._left, other._left) + self._top = min(self._top, other._top) + self._right = max(self._right, other._right) self._bottom = max(self._bottom, other._bottom) return self @@ -378,10 +392,10 @@ def __or__(self, other): BoundingBox(10.0, 20.0, 100.0, 90.0) """ return self.__class__( - min(self._left, other._left), - min(self._top, other._top), - max(self._right, other._right), - max(self._bottom, other._bottom) + min(self._left, other._left), + min(self._top, other._top), + max(self._right, other._right), + max(self._bottom, other._bottom), ) @@ -394,13 +408,17 @@ class FakeModule(object): def __getattr__(self, _): raise AttributeError("plotting not available") + def __call__(self, _): raise TypeError("plotting not available") + def __setattr__(self, key, value): raise AttributeError("plotting not available") + ##################################################################### + def find_cairo(): """Tries to import the ``cairo`` Python module if it is installed, also trying ``cairocffi`` (a drop-in replacement of ``cairo``). @@ -416,8 +434,10 @@ def find_cairo(): pass return module + ##################################################################### + def find_matplotlib(): """Tries to import the ``cairo`` Python module if it is installed, also trying ``cairocffi`` (a drop-in replacement of ``cairo``). @@ -425,6 +445,7 @@ def find_matplotlib(): """ try: import matplotlib as mpl + has_mpl = True except ImportError: mpl = FakeModule() @@ -437,12 +458,15 @@ def find_matplotlib(): return mpl, plt + ##################################################################### + class Point(tuple): """Class representing a point on the 2D plane.""" + __slots__ = () - _fields = ('x', 'y') + _fields = ("x", "y") def __new__(cls, x, y): """Creates a new point with the given coordinates""" @@ -451,16 +475,16 @@ def __new__(cls, x, y): # pylint: disable-msg=W0622 # W0622: redefining built-in 'len' @classmethod - def _make(cls, iterable, new = tuple.__new__, len = len): + def _make(cls, iterable, new=tuple.__new__, len=len): """Creates a new point from a sequence or iterable""" result = new(cls, iterable) if len(result) != 2: - raise TypeError('Expected 2 arguments, got %d' % len(result)) + raise TypeError("Expected 2 arguments, got %d" % len(result)) return result def __repr__(self): """Returns a nicely formatted representation of the point""" - return 'Point(x=%r, y=%r)' % self + return "Point(x=%r, y=%r)" % self def _asdict(self): """Returns a new dict which maps field names to their values""" @@ -471,9 +495,9 @@ def _asdict(self): def _replace(self, **kwds): """Returns a new point object replacing specified fields with new values""" - result = self._make(map(kwds.pop, ('x', 'y'), self)) + result = self._make(map(kwds.pop, ("x", "y"), self)) if kwds: - raise ValueError('Got unexpected field names: %r' % kwds.keys()) + raise ValueError("Got unexpected field names: %r" % list(kwds.keys())) return result def __getnewargs__(self): @@ -485,20 +509,21 @@ def __getnewargs__(self): def __add__(self, other): """Adds the coordinates of a point to another one""" - return self.__class__(x = self.x + other.x, y = self.y + other.y) + return self.__class__(x=self.x + other.x, y=self.y + other.y) def __sub__(self, other): """Subtracts the coordinates of a point to another one""" - return self.__class__(x = self.x - other.x, y = self.y - other.y) + return self.__class__(x=self.x - other.x, y=self.y - other.y) def __mul__(self, scalar): """Multiplies the coordinates by a scalar""" - return self.__class__(x = self.x * scalar, y = self.y * scalar) + return self.__class__(x=self.x * scalar, y=self.y * scalar) + __rmul__ = __mul__ def __div__(self, scalar): """Divides the coordinates by a scalar""" - return self.__class__(x = self.x / scalar, y = self.y / scalar) + return self.__class__(x=self.x / scalar, y=self.y / scalar) def as_polar(self): """Returns the polar coordinate representation of the point. @@ -520,7 +545,7 @@ def distance(self, other): dx, dy = self.x - other.x, self.y - other.y return (dx * dx + dy * dy) ** 0.5 - def interpolate(self, other, ratio = 0.5): + def interpolate(self, other, ratio=0.5): """Linearly interpolates between the coordinates of this point and another one. @@ -529,8 +554,10 @@ def interpolate(self, other, ratio = 0.5): return this point, 1 will return the other point. """ ratio = float(ratio) - return Point(x = self.x * (1.0 - ratio) + other.x * ratio, \ - y = self.y * (1.0 - ratio) + other.y * ratio) + return Point( + x=self.x * (1.0 - ratio) + other.x * ratio, + y=self.y * (1.0 - ratio) + other.y * ratio, + ) def length(self): """Returns the length of the vector pointing from the origin to this @@ -542,23 +569,22 @@ def normalized(self): after normalization. Returns the normalized point.""" len = self.length() if len == 0: - return Point(x = self.x, y = self.y) - return Point(x = self.x / len, y = self.y / len) + return Point(x=self.x, y=self.y) + return Point(x=self.x / len, y=self.y / len) def sq_length(self): """Returns the squared length of the vector pointing from the origin to this point.""" - return (self.x ** 2 + self.y ** 2) + return self.x ** 2 + self.y ** 2 - def towards(self, other, distance = 0): + def towards(self, other, distance=0): """Returns the point that is at a given distance from this point towards another one.""" if not distance: return self angle = atan2(other.y - self.y, other.x - self.x) - return Point(self.x + distance * cos(angle), - self.y + distance * sin(angle)) + return Point(self.x + distance * cos(angle), self.y + distance * sin(angle)) @classmethod def FromPolar(cls, radius, angle): @@ -569,4 +595,3 @@ def FromPolar(cls, radius, angle): the origin. """ return cls(radius * cos(angle), radius * sin(angle)) - diff --git a/src/igraph/drawing/vertex.py b/src/igraph/drawing/vertex.py index a84ba53e4..bc6d6b2a8 100644 --- a/src/igraph/drawing/vertex.py +++ b/src/igraph/drawing/vertex.py @@ -10,10 +10,10 @@ from igraph.drawing.shapes import ShapeDrawerDirectory from math import pi -__all__ = ["AbstractVertexDrawer", "AbstractCairoVertexDrawer", \ - "DefaultVertexDrawer"] +__all__ = ["AbstractVertexDrawer", "AbstractCairoVertexDrawer", "DefaultVertexDrawer"] __license__ = "GPL" + class AbstractVertexDrawer(AbstractDrawer): """Abstract vertex drawer object from which all concrete vertex drawer implementations are derived.""" @@ -31,7 +31,7 @@ def __init__(self, palette, layout): def draw(self, visual_vertex, vertex, coords): """Draws the given vertex. - + @param visual_vertex: object specifying the visual properties of the vertex. Its structure is defined by the VisualVertexBuilder of the L{DefaultGraphDrawer}; see its source code. @@ -41,6 +41,7 @@ def draw(self, visual_vertex, vertex, coords): """ raise NotImplementedError("abstract class") + class AbstractCairoVertexDrawer(AbstractVertexDrawer, AbstractCairoDrawer): """Abstract base class for vertex drawers that draw on a Cairo canvas.""" @@ -60,6 +61,7 @@ def __init__(self, context, bbox, palette, layout): AbstractCairoDrawer.__init__(self, context, bbox) AbstractVertexDrawer.__init__(self, palette, layout) + class DefaultVertexDrawer(AbstractCairoVertexDrawer): """The default vertex drawer implementation of igraph.""" @@ -70,28 +72,38 @@ def __init__(self, context, bbox, palette, layout): def _construct_visual_vertex_builder(self): class VisualVertexBuilder(AttributeCollectorBase): """Collects some visual properties of a vertex for drawing""" + _kwds_prefix = "vertex_" color = ("red", self.palette.get) frame_color = ("black", self.palette.get) frame_width = 1.0 label = None - label_angle = -pi/2 - label_dist = 0.0 + label_angle = -pi / 2 + label_dist = 0.0 label_color = ("black", self.palette.get) - font = 'sans-serif' - label_size = 14.0 + font = "sans-serif" + label_size = 14.0 position = dict(func=self.layout.__getitem__) shape = ("circle", ShapeDrawerDirectory.resolve_default) size = 20.0 width = None height = None + return VisualVertexBuilder def draw(self, visual_vertex, vertex, coords): context = self.context - width = visual_vertex.width if visual_vertex.width is not None else visual_vertex.size - height = visual_vertex.height if visual_vertex.height is not None else visual_vertex.size + width = ( + visual_vertex.width + if visual_vertex.width is not None + else visual_vertex.size + ) + height = ( + visual_vertex.height + if visual_vertex.height is not None + else visual_vertex.size + ) visual_vertex.shape.draw_path(context, coords[0], coords[1], width, height) context.set_source_rgba(*visual_vertex.color) @@ -99,5 +111,3 @@ def draw(self, visual_vertex, vertex, coords): context.set_source_rgba(*visual_vertex.frame_color) context.set_line_width(visual_vertex.frame_width) context.stroke() - - diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 540febca7..78d826f1c 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -8,7 +8,7 @@ `igraph.Graph.Formula()`. """ -from cStringIO import StringIO +from io import StringIO from igraph.datatypes import UniqueIdGenerator import re @@ -17,7 +17,7 @@ __all__ = ["construct_graph_from_formula"] -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -37,13 +37,14 @@ 02110-1301 USA """ + def generate_edges(formula): """Parses an edge specification from the head of the given formula part and yields the following: - + - startpoint(s) of the edge by vertex names - endpoint(s) of the edge by names or an empty list if the vertices are isolated - - a pair of bools to denote whether we had arrowheads at the start and end vertices + - a pair of bools to denote whether we had arrowheads at the start and end vertices """ if formula == "": yield [], [""], [False, False] @@ -55,7 +56,7 @@ def generate_edges(formula): parsing_vertices = True # Tokenize the formula - token_gen = tokenize.generate_tokens(StringIO(formula).next) + token_gen = tokenize.generate_tokens(StringIO(formula).__next__) for token_info in token_gen: # Do the state transitions token_type, tok, _, _, _ = token_info @@ -90,7 +91,10 @@ def generate_edges(formula): # End markers are fine pass else: - msg = "invalid token found in edge specification: %s; token_type=%r; tok=%r" % (formula, token_type, tok) + msg = ( + "invalid token found in edge specification: %s; token_type=%r; tok=%r" + % (formula, token_type, tok) + ) raise SyntaxError(msg) else: # We are parsing an edge operator @@ -111,10 +115,9 @@ def generate_edges(formula): yield start_names, end_names, arrowheads -def construct_graph_from_formula(cls, formula = None, attr = "name", - simplify = True): +def construct_graph_from_formula(cls, formula=None, attr="name", simplify=True): """Graph.Formula(formula = None, attr = "name", simplify = True) - + Generates a graph from a graph formula A graph formula is a simple string representation of a graph. @@ -167,7 +170,7 @@ def construct_graph_from_formula(cls, formula = None, attr = "name", + attr: name (v) + edges (vertex names): A->B - + If you have may disconnected componnets, you can separate them with commas. You can also specify isolated vertices: @@ -199,10 +202,10 @@ def construct_graph_from_formula(cls, formula = None, attr = "name", @param simplify: whether the simplify the constructed graph @return: the constructed graph: """ - + # If we have no formula, return an empty graph if formula is None: - return cls(0, vertex_attrs = {attr: []}) + return cls(0, vertex_attrs={attr: []}) vertex_ids, edges, directed = UniqueIdGenerator(), [], False # Loop over each part in the formula @@ -212,26 +215,23 @@ def construct_graph_from_formula(cls, formula = None, attr = "name", # Parse the first vertex specification from the formula for start_names, end_names, arrowheads in generate_edges(part): start_ids = [vertex_ids[name] for name in start_names] - end_ids = [vertex_ids[name] for name in end_names] + end_ids = [vertex_ids[name] for name in end_names] if not arrowheads[0] and not arrowheads[1]: # This is an undirected edge. Do we have a directed graph? if not directed: # Nope, add the edge - edges.extend((id1, id2) for id1 in start_ids \ - for id2 in end_ids) + edges.extend((id1, id2) for id1 in start_ids for id2 in end_ids) else: # This is a directed edge directed = True if arrowheads[1]: - edges.extend((id1, id2) for id1 in start_ids \ - for id2 in end_ids) + edges.extend((id1, id2) for id1 in start_ids for id2 in end_ids) if arrowheads[0]: - edges.extend((id2, id1) for id1 in start_ids \ - for id2 in end_ids) + edges.extend((id2, id1) for id1 in start_ids for id2 in end_ids) # Grab the vertex names into a list vertex_attrs = {} - vertex_attrs[attr] = vertex_ids.values() + vertex_attrs[attr] = list(vertex_ids.values()) # Construct and return the graph result = cls(len(vertex_ids), edges, directed, vertex_attrs=vertex_attrs) if simplify: diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 7f347b070..1d3fd7623 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -6,13 +6,13 @@ This package contains the implementation of the L{Layout} object. """ -from itertools import izip + from math import sin, cos, pi from igraph.drawing.utils import BoundingBox from igraph.statistics import RunningMean -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -32,6 +32,7 @@ 02110-1301 USA """ + class Layout(object): """Represents the layout of a graph. @@ -64,7 +65,7 @@ class Layout(object): >>> print layout[1] [0, 3] """ - + def __init__(self, coords=None, dim=None): """Constructor. @@ -90,8 +91,10 @@ def __init__(self, coords=None, dim=None): self._dim = int(dim) for row in self._coords: if len(row) != self._dim: - raise ValueError("all items in the coordinate list "+ - "must have a length of %d" % self._dim) + raise ValueError( + "all items in the coordinate list " + + "must have a length of %d" % self._dim + ) def __len__(self): return len(self._coords) @@ -121,8 +124,11 @@ def __repr__(self): dim_count = "1 dimension" else: dim_count = "%d dimensions" % self.dim - return "<%s with %s and %s>" % (self.__class__.__name__, - vertex_count, dim_count) + return "<%s with %s and %s>" % ( + self.__class__.__name__, + vertex_count, + dim_count, + ) @property def dim(self): @@ -138,7 +144,7 @@ def append(self, value): """Appends a new point to the layout""" if len(value) < self._dim: raise ValueError("appended item must have %d elements" % self._dim) - self._coords.append([float(coord) for coord in value[0:self._dim]]) + self._coords.append([float(coord) for coord in value[0 : self._dim]]) def mirror(self, dim): """Mirrors the layout along the given dimension(s) @@ -154,7 +160,6 @@ def mirror(self, dim): for row in self._coords: row[current_dim] *= -1 - def rotate(self, angle, dim1=0, dim2=1, **kwds): """Rotates the layout by the given degrees on the plane defined by the given two dimensions. @@ -166,18 +171,17 @@ def rotate(self, angle, dim1=0, dim2=1, **kwds): origin will be the origin of the coordinate system. """ - origin = list(kwds.get("origin", [0.]*self._dim)) + origin = list(kwds.get("origin", [0.0] * self._dim)) if len(origin) != self._dim: raise ValueError("origin must have %d dimensions" % self._dim) - radian = angle * pi / 180. + radian = angle * pi / 180.0 cos_alpha, sin_alpha = cos(radian), sin(radian) - - for idx, row in enumerate(self._coords): - x, y = row[dim1] - origin[dim1], row[dim2] - origin[dim2] - row[dim1] = cos_alpha*x - sin_alpha*y + origin[dim1] - row[dim2] = sin_alpha*x + cos_alpha*y + origin[dim2] + for idx, row in enumerate(self._coords): + x, y = row[dim1] - origin[dim1], row[dim2] - origin[dim2] + row[dim1] = cos_alpha * x - sin_alpha * y + origin[dim1] + row[dim2] = sin_alpha * x + cos_alpha * y + origin[dim2] def scale(self, *args, **kwds): """Scales the layout. @@ -194,7 +198,7 @@ def scale(self, *args, **kwds): @keyword origin: the origin of scaling (this point will stay in place). Optional, defaults to the origin of the coordinate system being used. """ - origin = list(kwds.get("origin", [0.]*self._dim)) + origin = list(kwds.get("origin", [0.0] * self._dim)) if len(origin) != self._dim: raise ValueError("origin must have %d dimensions" % self._dim) @@ -205,16 +209,16 @@ def scale(self, *args, **kwds): raise ValueError("scaling factor must be given") elif len(scaling) == 1: if type(scaling[0]) == int or type(scaling[0]) == float: - scaling = scaling*self._dim + scaling = scaling * self._dim else: scaling = scaling[0] if len(scaling) != self._dim: - raise ValueError("scaling factor list must have %d elements" \ - % self._dim) + raise ValueError("scaling factor list must have %d elements" % self._dim) for idx, row in enumerate(self._coords): - self._coords[idx] = [(row[d]-origin[d])*scaling[d]+origin[d] \ - for d in xrange(self._dim)] + self._coords[idx] = [ + (row[d] - origin[d]) * scaling[d] + origin[d] for d in range(self._dim) + ] def translate(self, *args, **kwds): """Translates the layout. @@ -233,15 +237,12 @@ def translate(self, *args, **kwds): elif len(v) == 1 and type(v[0]) != int and type(v[0]) != float: v = v[0] if len(v) != self._dim: - raise ValueError("translation vector must have %d dimensions" \ - % self._dim) + raise ValueError("translation vector must have %d dimensions" % self._dim) for idx, row in enumerate(self._coords): - self._coords[idx] = [row[d]+v[d] for d in xrange(self._dim)] - + self._coords[idx] = [row[d] + v[d] for d in range(self._dim)] - def to_radial(self, min_angle = 100, max_angle = 80, \ - min_radius=0.0, max_radius=1.0): + def to_radial(self, min_angle=100, max_angle=80, min_radius=0.0, max_radius=1.0): """Converts a planar layout to a radial one This method applies only to 2D layouts. The X coordinate of the @@ -279,14 +280,13 @@ def to_radial(self, min_angle = 100, max_angle = 80, \ max_angle += 360 ratio_x = (max_angle - min_angle) / bbox.width - ratio_x *= pi / 180. - min_angle *= pi / 180. + ratio_x *= pi / 180.0 + min_angle *= pi / 180.0 ratio_y = (max_radius - min_radius) / bbox.height for idx, (x, y) in enumerate(self._coords): - alpha = (x-bbox.left) * ratio_x + min_angle - radius = (y-bbox.top) * ratio_y + min_radius - self._coords[idx] = [cos(alpha)*radius, -sin(alpha)*radius] - + alpha = (x - bbox.left) * ratio_x + min_angle + radius = (y - bbox.top) * ratio_y + min_radius + self._coords[idx] = [cos(alpha) * radius, -sin(alpha) * radius] def transform(self, function, *args, **kwds): """Performs an arbitrary transformation on the layout @@ -297,20 +297,20 @@ def transform(self, function, *args, **kwds): @param function: a function which receives the coordinates as a tuple and returns the transformed tuple. """ - self._coords = [list(function(tuple(row), *args, **kwds)) \ - for row in self._coords] - + self._coords = [ + list(function(tuple(row), *args, **kwds)) for row in self._coords + ] def centroid(self): """Returns the centroid of the layout. The centroid of the layout is the arithmetic mean of the points in the layout. - + @return: the centroid as a list of floats""" - centroid = [RunningMean() for _ in xrange(self._dim)] + centroid = [RunningMean() for _ in range(self._dim)] for row in self._coords: - for dim in xrange(self._dim): + for dim in range(self._dim): centroid[dim].add(row[dim]) return [rm.mean for rm in centroid] @@ -332,12 +332,12 @@ def boundaries(self, border=0): raise ValueError("layout contains no layout items") mins, maxs = [], [] - for dim in xrange(self._dim): + for dim in range(self._dim): col = [row[dim] for row in self._coords] - mins.append(min(col)-border) - maxs.append(max(col)+border) + mins.append(min(col) - border) + maxs.append(max(col) + border) return mins, maxs - + def bounding_box(self, border=0): """Returns the bounding box of the layout. @@ -360,7 +360,6 @@ def bounding_box(self, border=0): except ValueError: return BoundingBox(0, 0, 0, 0) - def center(self, *args, **kwds): """Centers the layout around the given point. @@ -373,18 +372,15 @@ def center(self, *args, **kwds): the operation.""" center = kwds.get("p") or args if len(center) == 0: - center = [0.] * self._dim - elif len(center) == 1 and type(center[0]) != int \ - and type(center[0]) != float: + center = [0.0] * self._dim + elif len(center) == 1 and type(center[0]) != int and type(center[0]) != float: center = center[0] if len(center) != self._dim: - raise ValueError("the given point must have %d dimensions" \ - % self._dim) + raise ValueError("the given point must have %d dimensions" % self._dim) centroid = self.centroid() - vec = [center[d]-centroid[d] for d in xrange(self._dim)] + vec = [center[d] - centroid[d] for d in range(self._dim)] self.translate(vec) - def copy(self): """Creates an exact copy of the layout.""" return self.__copy__() @@ -409,20 +405,21 @@ def fit_into(self, bbox, keep_aspect_ratio=True): raise TypeError("bounding boxes work for 2D layouts only") corner, target_sizes = [bbox.left, bbox.top], [bbox.width, bbox.height] elif len(bbox) == self._dim: - corner, target_sizes = [0.] * self._dim, list(bbox) + corner, target_sizes = [0.0] * self._dim, list(bbox) elif len(bbox) == 2 * self._dim: - corner, opposite_corner = list(bbox[0:self._dim]), list(bbox[self._dim:]) - for i in xrange(self._dim): + corner, opposite_corner = list(bbox[0 : self._dim]), list(bbox[self._dim :]) + for i in range(self._dim): if corner[i] > opposite_corner[i]: corner[i], opposite_corner[i] = opposite_corner[i], corner[i] - target_sizes = [max_val-min_val \ - for min_val, max_val in izip(corner, opposite_corner)] + target_sizes = [ + max_val - min_val for min_val, max_val in zip(corner, opposite_corner) + ] try: mins, maxs = self.boundaries() except ValueError: mins, maxs = [0.0] * self._dim, [0.0] * self._dim - sizes = [max_val - min_val for min_val, max_val in izip(mins, maxs)] + sizes = [max_val - min_val for min_val, max_val in zip(mins, maxs)] for i, size in enumerate(sizes): if size == 0: @@ -430,18 +427,19 @@ def fit_into(self, bbox, keep_aspect_ratio=True): mins[i] -= 1 maxs[i] += 1 - ratios = [float(target_size) / current_size \ - for current_size, target_size in izip(sizes, target_sizes)] + ratios = [ + float(target_size) / current_size + for current_size, target_size in zip(sizes, target_sizes) + ] if keep_aspect_ratio: min_ratio = min(ratios) ratios = [min_ratio] * self._dim translations = [] - for i in xrange(self._dim): - trans = (target_sizes[i] - ratios[i] * sizes[i]) / 2. + for i in range(self._dim): + trans = (target_sizes[i] - ratios[i] * sizes[i]) / 2.0 trans -= mins[i] * ratios[i] - corner[i] translations.append(trans) self.scale(*ratios) self.translate(*translations) - diff --git a/src/igraph/matching.py b/src/igraph/matching.py index 0e75ad9d2..85d40d226 100644 --- a/src/igraph/matching.py +++ b/src/igraph/matching.py @@ -5,7 +5,7 @@ from igraph.clustering import VertexClustering from igraph._igraph import Vertex -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -25,6 +25,7 @@ 02110-1301 USA """ + class Matching(object): """A matching of vertices in a graph. @@ -65,7 +66,7 @@ def __init__(self, graph, matching, types=None): self._num_matched = 0 self._types = None - if isinstance(types, basestring): + if isinstance(types, str): types = graph.vs[types] self.types = types @@ -76,11 +77,14 @@ def __len__(self): def __repr__(self): if self._types is not None: - return "%s(%r,%r,types=%r)" % \ - (self.__class__.__name__, self._graph, self._matching, self._types) + return "%s(%r,%r,types=%r)" % ( + self.__class__.__name__, + self._graph, + self._matching, + self._types, + ) else: - return "%s(%r,%r)" % \ - (self.__class__.__name__, self._graph, self._matching) + return "%s(%r,%r)" % (self.__class__.__name__, self._graph, self._matching) def __str__(self): if self._types is not None: @@ -95,8 +99,11 @@ def edges(self): of them will be returned. """ get_eid = self._graph.get_eid - eidxs = [get_eid(u, v, directed=False) \ - for u, v in enumerate(self._matching) if v != -1 and u <= v] + eidxs = [ + get_eid(u, v, directed=False) + for u, v in enumerate(self._matching) + if v != -1 and u <= v + ] return self._graph.es[eidxs] @property @@ -121,7 +128,7 @@ def is_matched(self, vertex): def match_of(self, vertex): """Returns the vertex a given vertex is matched to. - + @param vertex: the vertex we are interested in; either an integer index or an instance of L{Vertex}. @return: the index of the vertex matched to the given vertex, either as diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 00f8e0c13..a8c19a40d 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -2,11 +2,10 @@ # -*- coding: utf-8 -*- """Implementation of union, disjoint union and intersection operators.""" -from __future__ import with_statement __all__ = ("disjoint_union", "union", "intersection") __docformat__ = "restructuredtext en" -__license__ = u""" +__license__ = """ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -28,7 +27,6 @@ from igraph._igraph import GraphBase, _union, _intersection, _disjoint_union -from collections import defaultdict, Counter from warnings import warn @@ -49,7 +47,7 @@ def disjoint_union(graphs): @return: the disjoint union graph """ if any(not isinstance(g, GraphBase) for g in graphs): - raise TypeError('Not all elements are graphs') + raise TypeError("Not all elements are graphs") ngr = len(graphs) # Trivial cases @@ -81,16 +79,15 @@ def disjoint_union(graphs): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_union['{:}_{:}'.format(a_name, igf)] = \ - graph_union.pop(a_name) - graph_union['{:}_{:}'.format(a_name, ig)] = a_value + graph_union["{:}_{:}".format(a_name, igf)] = graph_union.pop(a_name) + graph_union["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes i = 0 for g in graphs: nv = g.vcount() for attr in g.vertex_attributes(): - graph_union.vs[i: i + nv][attr] = g.vs[attr] + graph_union.vs[i : i + nv][attr] = g.vs[attr] i += nv # Edge attributes @@ -98,13 +95,13 @@ def disjoint_union(graphs): for g in graphs: ne = g.ecount() for attr in g.edge_attributes(): - graph_union.es[i: i + ne][attr] = g.es[attr] + graph_union.es[i : i + ne][attr] = g.es[attr] i += ne return graph_union -def union(graphs, byname='auto'): +def union(graphs, byname="auto"): """Graph union. The union of two or more graphs is created. The graphs may have identical @@ -133,14 +130,14 @@ def union(graphs, byname='auto'): """ if any(not isinstance(g, GraphBase) for g in graphs): - raise TypeError('Not all elements are graphs') + raise TypeError("Not all elements are graphs") - if byname not in (True, False, 'auto'): + if byname not in (True, False, "auto"): raise ValueError('"byname" should be a bool or "auto"') ngr = len(graphs) n_named = sum(g.is_named() for g in graphs) - if byname == 'auto': + if byname == "auto": byname = n_named == ngr if n_named not in (0, ngr): warn("Some, but not all graphs are named, not using vertex names") @@ -156,7 +153,7 @@ def union(graphs, byname='auto'): # Now there are at least two graphs if byname: - allnames = [g.vs['name'] for g in graphs] + allnames = [g.vs["name"] for g in graphs] uninames = list(set.union(*(set(vns) for vns in allnames))) permutation_map = {x: i for i, x in enumerate(uninames)} nve = len(uninames) @@ -171,7 +168,7 @@ def union(graphs, byname='auto'): # Reorder vertices to match uninames # vertex k -> p[k] - permutation = [permutation_map[x] for x in ng.vs['name']] + permutation = [permutation_map[x] for x in ng.vs["name"]] ng = ng.permute_vertices(permutation) newgraphs.append(ng) @@ -182,8 +179,8 @@ def union(graphs, byname='auto'): edgemaps = any(len(g.edge_attributes()) for g in graphs) res = _union(newgraphs, edgemaps) if edgemaps: - graph_union = res['graph'] - edgemaps = res['edgemaps'] + graph_union = res["graph"] + edgemaps = res["edgemaps"] else: graph_union = res @@ -205,14 +202,13 @@ def union(graphs, byname='auto'): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_union['{:}_{:}'.format(a_name, igf)] = \ - graph_union.pop(a_name) - graph_union['{:}_{:}'.format(a_name, ig)] = a_value + graph_union["{:}_{:}".format(a_name, igf)] = graph_union.pop(a_name) + graph_union["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes if byname: - graph_union.vs['name'] = uninames - attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(['name']) + graph_union.vs["name"] = uninames + attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(["name"]) nve = graph_union.vcount() for a_name in attrs: # Check for conflicts at at least one vertex @@ -239,7 +235,7 @@ def union(graphs, byname='auto'): # There is a conflict, name after the graph number for ig, g in enumerate(newgraphs, 1): if a_name in g.vertex_attributes(): - graph_union.vs['{:}_{:}'.format(a_name, ig)] = g.vs[a_name] + graph_union.vs["{:}_{:}".format(a_name, ig)] = g.vs[a_name] # Edge attributes if edgemaps: @@ -259,7 +255,7 @@ def union(graphs, byname='auto'): vals[iu] = a_value continue if vals[iu] != a_value: - print(g, g.vs['name'], emap, a_value, iu, vals[iu]) + print(g, g.vs["name"], emap, a_value, iu, vals[iu]) conflict = True break if conflict: @@ -277,12 +273,12 @@ def union(graphs, byname='auto'): vals = [None for i in range(ne)] for iu, a_value in zip(emap, g.es[a_name]): vals[iu] = a_value - graph_union.es['{:}_{:}'.format(a_name, ig)] = vals + graph_union.es["{:}_{:}".format(a_name, ig)] = vals return graph_union -def intersection(graphs, byname='auto', keep_all_vertices=True): +def intersection(graphs, byname="auto", keep_all_vertices=True): """Graph intersection. The intersection of two or more graphs is created. The graphs may have @@ -313,14 +309,14 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): """ if any(not isinstance(g, GraphBase) for g in graphs): - raise TypeError('Not all elements are graphs') + raise TypeError("Not all elements are graphs") - if byname not in (True, False, 'auto'): + if byname not in (True, False, "auto"): raise ValueError('"byname" should be a bool or "auto"') ngr = len(graphs) n_named = sum(g.is_named() for g in graphs) - if byname == 'auto': + if byname == "auto": byname = n_named == ngr if n_named not in (0, ngr): warn("Some, but not all graphs are named, not using vertex names") @@ -336,7 +332,7 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): # Now there are at least two graphs if byname: - allnames = [g.vs['name'] for g in graphs] + allnames = [g.vs["name"] for g in graphs] if keep_all_vertices: uninames = list(set.union(*(set(vns) for vns in allnames))) @@ -361,7 +357,7 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): # Reorder vertices to match uninames # vertex k -> p[k] - permutation = [permutation_map[x] for x in ng.vs['name']] + permutation = [permutation_map[x] for x in ng.vs["name"]] ng = ng.permute_vertices(permutation) newgraphs.append(ng) @@ -372,8 +368,8 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): edgemaps = any(len(g.edge_attributes()) for g in graphs) res = _intersection(newgraphs, edgemaps) if edgemaps: - graph_intsec = res['graph'] - edgemaps = res['edgemaps'] + graph_intsec = res["graph"] + edgemaps = res["edgemaps"] else: graph_intsec = res @@ -395,14 +391,13 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_intsec['{:}_{:}'.format(a_name, igf)] = \ - graph_intsec.pop(a_name) - graph_intsec['{:}_{:}'.format(a_name, ig)] = a_value + graph_intsec["{:}_{:}".format(a_name, igf)] = graph_intsec.pop(a_name) + graph_intsec["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes if byname: - graph_intsec.vs['name'] = uninames - attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(['name']) + graph_intsec.vs["name"] = uninames + attrs = set.union(*(set(g.vertex_attributes()) for g in newgraphs)) - set(["name"]) nv = graph_intsec.vcount() for a_name in attrs: # Check for conflicts at at least one vertex @@ -430,7 +425,7 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): # There is a conflict, name after the graph number for ig, g in enumerate(newgraphs, 1): if a_name in g.vertex_attributes(): - graph_intsec.vs['{:}_{:}'.format(a_name, ig)] = g.vs[a_name] + graph_intsec.vs["{:}_{:}".format(a_name, ig)] = g.vs[a_name] # Edge attributes if edgemaps: @@ -471,6 +466,6 @@ def intersection(graphs, byname='auto', keep_all_vertices=True): if iu == -1: continue vals[iu] = a_value - graph_intsec.es['{:}_{:}'.format(a_name, ig)] = vals + graph_intsec.es["{:}_{:}".format(a_name, ig)] = vals return graph_intsec diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index adb362a60..67f48c90e 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -3,7 +3,7 @@ """Classes that help igraph communicate with Gephi (http://www.gephi.org).""" from igraph.compat import property -import urllib2 +import urllib.request, urllib.error, urllib.parse try: # JSON is optional so we don't blow up with Python < 2.6 @@ -15,11 +15,12 @@ except ImportError: # No simplejson either from igraph.drawing.utils import FakeModule + json = FakeModule() __all__ = ["GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat"] __docformat__ = "restructuredtext en" -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -66,7 +67,7 @@ def __init__(self, url=None, host="127.0.0.1", port=8080, workspace=1): def __del__(self): try: self.close() - except urllib2.URLError: + except urllib.error.URLError: # Happens when Gephi is closed before the connection is destroyed pass @@ -83,7 +84,7 @@ def flush(self): single request.""" data = b"".join(self._pending_operations) self._pending_operations = [] - conn = urllib2.urlopen(self._update_url, data=data) + conn = urllib.request.urlopen(self._update_url, data=data) return conn.read() @property @@ -241,7 +242,7 @@ def iterjsonobj(self, graph): to the destination.""" # Construct a unique ID prefix - id_prefix = "igraph:%s" % (hex(id(graph)), ) + id_prefix = "igraph:%s" % (hex(id(graph)),) # Add the vertices add_node = self.format.get_add_node_event @@ -252,10 +253,13 @@ def iterjsonobj(self, graph): add_edge = self.format.get_add_edge_event directed = graph.is_directed() for edge in graph.es: - yield add_edge("%s:e:%d:%d" % (id_prefix, edge.source, edge.target), - "%s:v:%d" % (id_prefix, edge.source), - "%s:v:%d" % (id_prefix, edge.target), - directed, edge.attributes()) + yield add_edge( + "%s:e:%d:%d" % (id_prefix, edge.source, edge.target), + "%s:v:%d" % (id_prefix, edge.source), + "%s:v:%d" % (id_prefix, edge.target), + directed, + edge.attributes(), + ) def post(self, graph, destination, encoder=None): """Posts the given graph to the destination of the streamer using the @@ -285,4 +289,3 @@ def send_event(self, event, destination, encoder=None, flush=True): destination.write(b"\r\n") if flush: destination.flush() - diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 15a0e1aa5..b62199244 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -4,7 +4,7 @@ Statistics related stuff in igraph """ -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamas Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -26,8 +26,16 @@ import math -__all__ = ["FittedPowerLaw", "Histogram", "RunningMean", "mean", "median", \ - "percentile", "quantile", "power_law_fit"] +__all__ = [ + "FittedPowerLaw", + "Histogram", + "RunningMean", + "mean", + "median", + "percentile", + "quantile", + "power_law_fit", +] class FittedPowerLaw(object): @@ -38,7 +46,7 @@ class FittedPowerLaw(object): >>> result = power_law_fit([1, 2, 3, 4, 5, 6]) >>> result # doctest:+ELLIPSIS FittedPowerLaw(continuous=False, alpha=2.425828..., xmin=3.0, L=-7.54633..., D=0.2138..., p=0.99311...) - >>> print result # doctest:+ELLIPSIS + >>> print(result) # doctest:+ELLIPSIS Fitted power-law distribution on discrete data Exponent (alpha) = 2.425828 @@ -69,9 +77,15 @@ def __init__(self, continuous, alpha, xmin, L, D, p): self.p = p def __repr__(self): - return "%s(continuous=%r, alpha=%r, xmin=%r, L=%r, D=%r, p=%r)" % \ - (self.__class__.__name__, self.continuous, self.alpha, \ - self.xmin, self.L, self.D, self.p) + return "%s(continuous=%r, alpha=%r, xmin=%r, L=%r, D=%r, p=%r)" % ( + self.__class__.__name__, + self.continuous, + self.alpha, + self.xmin, + self.L, + self.D, + self.p, + ) def __str__(self): return self.summary(significance=0.05) @@ -84,8 +98,10 @@ def summary(self, significance=0.05): distribution @return: the summary as a string """ - result = ["Fitted power-law distribution on %s data" % \ - ("discrete", "continuous")[bool(self.continuous)]] + result = [ + "Fitted power-law distribution on %s data" + % ("discrete", "continuous")[bool(self.continuous)] + ] result.append("") result.append("Exponent (alpha) = %f" % self.alpha) result.append("Cutoff (xmin) = %f" % self.xmin) @@ -98,29 +114,29 @@ def summary(self, significance=0.05): result.append("p-value = %f" % self.p) result.append("") if self.p < significance: - result.append("H0 rejected at significance level %g" \ - % significance) + result.append("H0 rejected at significance level %g" % significance) else: - result.append("H0 could not be rejected at significance "\ - "level %g" % significance) + result.append( + "H0 could not be rejected at significance " "level %g" % significance + ) return "\n".join(result) class Histogram(object): """Generic histogram class for real numbers - + Example: - + >>> h = Histogram(5) # Initializing, bin width = 5 >>> h << [2,3,2,7,8,5,5,0,7,9] # Adding more items - >>> print h + >>> print(h) N = 10, mean +- sd: 4.8000 +- 2.9740 [ 0, 5): **** (4) [ 5, 10): ****** (6) """ - def __init__(self, bin_width = 1, data = None): + def __init__(self, bin_width=1, data=None): """Initializes the histogram with the given data set. @param bin_width: the bin width of the histogram. @@ -135,7 +151,7 @@ def __init__(self, bin_width = 1, data = None): if data: self.add_many(data) - def _get_bin(self, num, create = False): + def _get_bin(self, num, create=False): """Returns the bin index corresponding to the given number. @param num: the number for which the bin is being sought @@ -145,31 +161,31 @@ def _get_bin(self, num, create = False): if len(self._bins) == 0: if not create: result = None - else: - self._min = int(num/self._bin_width)*self._bin_width - self._max = self._min+self._bin_width + else: + self._min = int(num / self._bin_width) * self._bin_width + self._max = self._min + self._bin_width self._bins = [0] result = 0 return result if num >= self._min: - binidx = int((num-self._min)/self._bin_width) + binidx = int((num - self._min) / self._bin_width) if binidx < len(self._bins): return binidx if not create: return None - extra_bins = binidx-len(self._bins)+1 - self._bins.extend([0]*extra_bins) - self._max = self._min + len(self._bins)*self._bin_width + extra_bins = binidx - len(self._bins) + 1 + self._bins.extend([0] * extra_bins) + self._max = self._min + len(self._bins) * self._bin_width return binidx if not create: return None - extra_bins = int(math.ceil((self._min-num)/self._bin_width)) - self._bins[0:0] = [0]*extra_bins - self._min -= extra_bins*self._bin_width - self._max = self._min + len(self._bins)*self._bin_width + extra_bins = int(math.ceil((self._min - num) / self._bin_width)) + self._bins[0:0] = [0] * extra_bins + self._min -= extra_bins * self._bin_width + self._max = self._min + len(self._bins) * self._bin_width return 0 @property @@ -196,13 +212,13 @@ def var(self): def add(self, num, repeat=1): """Adds a single number to the histogram. - + @param num: the number to be added @param repeat: number of repeated additions """ num = float(num) binidx = self._get_bin(num, True) - self._bins[binidx] += repeat + self._bins[binidx] += repeat self._running_mean.add(num, repeat) def add_many(self, data): @@ -215,6 +231,7 @@ def add_many(self, data): iterator = iter([data]) for x in iterator: self.add(x) + __lshift__ = add_many def clear(self): @@ -225,33 +242,43 @@ def clear(self): def bins(self): """Generator returning the bins of the histogram in increasing order - + @return: a tuple with the following elements: left bound, right bound, number of elements in the bin""" x = self._min for elem in self._bins: - yield (x, x+self._bin_width, elem) + yield (x, x + self._bin_width, elem) x += self._bin_width def __plot__(self, context, bbox, _, **kwds): """Plotting support""" from igraph.drawing.coord import DescartesCoordinateSystem - coord_system = DescartesCoordinateSystem(context, bbox, \ - (kwds.get("min", self._min), 0, \ - kwds.get("max", self._max), kwds.get("max_value", max(self._bins)) - )) + + coord_system = DescartesCoordinateSystem( + context, + bbox, + ( + kwds.get("min", self._min), + 0, + kwds.get("max", self._max), + kwds.get("max_value", max(self._bins)), + ), + ) # Draw the boxes context.set_line_width(1) - context.set_source_rgb(1., 0., 0.) + context.set_source_rgb(1.0, 0.0, 0.0) x = self._min for value in self._bins: top_left_x, top_left_y = coord_system.local_to_context(x, value) x += self._bin_width bottom_right_x, bottom_right_y = coord_system.local_to_context(x, 0) - context.rectangle(top_left_x, top_left_y, \ - bottom_right_x - top_left_x, \ - bottom_right_y - top_left_y) + context.rectangle( + top_left_x, + top_left_y, + bottom_right_x - top_left_x, + bottom_right_y - top_left_y, + ) context.fill() # Draw the axes @@ -277,8 +304,7 @@ def to_string(self, max_width=78, show_bars=True, show_counts=True): number_format = "%d" else: number_format = "%.3f" - num_length = max(len(number_format % self._min), \ - len(number_format % self._max)) + num_length = max(len(number_format % self._min), len(number_format % self._max)) number_format = "%" + str(num_length) + number_format[1:] format_string = "[%s, %s): %%s" % (number_format, number_format) @@ -287,13 +313,12 @@ def to_string(self, max_width=78, show_bars=True, show_counts=True): maxval = max(self._bins) if show_counts: maxval_length = len(str(maxval)) - scale = maxval // (max_width-2*num_length-maxval_length-9) + scale = maxval // (max_width - 2 * num_length - maxval_length - 9) else: - scale = maxval // (max_width-2*num_length-6) + scale = maxval // (max_width - 2 * num_length - 6) scale = max(scale, 1) - result = ["N = %d, mean +- sd: %.4f +- %.4f" % \ - (self.n, self.mean, self.sd)] + result = ["N = %d, mean +- sd: %.4f +- %.4f" % (self.n, self.mean, self.sd)] if show_bars: # Print the bars @@ -302,10 +327,12 @@ def to_string(self, max_width=78, show_bars=True, show_counts=True): if show_counts: format_string += " (%d)" for left, right, cnt in self.bins(): - result.append(format_string % (left, right, '*'*(cnt//scale), cnt)) + result.append( + format_string % (left, right, "*" * (cnt // scale), cnt) + ) else: for left, right, cnt in self.bins(): - result.append(format_string % (left, right, '*'*(cnt//scale))) + result.append(format_string % (left, right, "*" * (cnt // scale))) elif show_counts: # Print the counts only for left, right, cnt in self.bins(): @@ -317,10 +344,9 @@ def __str__(self): return self.to_string() - class RunningMean(object): """Running mean calculator. - + This class can be used to calculate the mean of elements from a list, tuple, iterable or any other data source. The mean is calculated on the fly without explicitly summing the values, @@ -332,9 +358,9 @@ class RunningMean(object): # pylint: disable-msg=C0103 def __init__(self, items=None, n=0.0, mean=0.0, sd=0.0): """RunningMean(items=None, n=0.0, mean=0.0, sd=0.0) - + Initializes the running mean calculator. - + There are two possible ways to initialize the calculator. First, one can provide an iterable of items; alternatively, one can specify the number of items, the mean and the @@ -359,15 +385,15 @@ def __init__(self, items=None, n=0.0, mean=0.0, sd=0.0): self._nitems = float(n) self._mean = float(mean) if n > 1: - self._sqdiff = float(sd) ** 2 * float(n-1) + self._sqdiff = float(sd) ** 2 * float(n - 1) self._sd = float(sd) else: self._sqdiff = 0.0 self._sd = 0.0 - + def add(self, value, repeat=1): """RunningMean.add(value, repeat=1) - + Adds the given value to the elements from which we calculate the mean and the standard deviation. @@ -377,24 +403,24 @@ def add(self, value, repeat=1): repeat = int(repeat) self._nitems += repeat delta = value - self._mean - self._mean += (repeat*delta / self._nitems) - self._sqdiff += (repeat*delta) * (value - self._mean) + self._mean += repeat * delta / self._nitems + self._sqdiff += (repeat * delta) * (value - self._mean) if self._nitems > 1: - self._sd = (self._sqdiff / (self._nitems-1)) ** 0.5 + self._sd = (self._sqdiff / (self._nitems - 1)) ** 0.5 def add_many(self, values): """RunningMean.add(values) - + Adds the values in the given iterable to the elements from which we calculate the mean. Can also accept a single number. The left shift (C{<<}) operator is aliased to this function, so you can use it to add elements as well: - + >>> rm=RunningMean() - >>> rm << [1,2,3,4] + >>> rm << [1,2,3,4] >>> rm.result # doctest:+ELLIPSIS (2.5, 1.290994...) - + @param values: the element(s) to be added @type values: iterable""" try: @@ -430,16 +456,18 @@ def var(self): return self._sd ** 2 def __repr__(self): - return "%s(n=%r, mean=%r, sd=%r)" % \ - (self.__class__.__name__, int(self._nitems), - self._mean, self._sd) + return "%s(n=%r, mean=%r, sd=%r)" % ( + self.__class__.__name__, + int(self._nitems), + self._mean, + self._sd, + ) def __str__(self): - return "Running mean (N=%d, %f +- %f)" % \ - (self._nitems, self._mean, self._sd) - + return "Running mean (N=%d, %f +- %f)" % (self._nitems, self._mean, self._sd) + __lshift__ = add_many - + def __float__(self): return float(self._mean) @@ -447,7 +475,7 @@ def __int__(self): return int(self._mean) def __long__(self): - return long(self._mean) + return int(self._mean) def __complex__(self): return complex(self._mean) @@ -471,6 +499,7 @@ def mean(xs): """ return RunningMean(xs).mean + def median(xs, sort=True): """Returns the median of an unsorted or sorted numeric vector. @@ -485,10 +514,11 @@ def median(xs, sort=True): mid = int(len(xs) / 2) if 2 * mid == len(xs): - return float(xs[mid-1] + xs[mid]) / 2 + return float(xs[mid - 1] + xs[mid]) / 2 else: return float(xs[mid]) + def percentile(xs, p=(25, 50, 75), sort=True): """Returns the pth percentile of an unsorted or sorted numeric vector. @@ -500,7 +530,7 @@ def percentile(xs, p=(25, 50, 75), sort=True): >>> round(percentile([15, 20, 40, 35, 50], 40), 2) 26.0 >>> for perc in percentile([15, 20, 40, 35, 50], (0, 25, 50, 75, 100)): - ... print "%.2f" % perc + ... print("%.2f" % perc) ... 15.00 17.50 @@ -519,8 +549,9 @@ def percentile(xs, p=(25, 50, 75), sort=True): list containing the percentiles for each item in the list. """ if hasattr(p, "__iter__"): - return quantile(xs, (x/100.0 for x in p), sort) - return quantile(xs, p/100.0, sort) + return quantile(xs, (x / 100.0 for x in p), sort) + return quantile(xs, p / 100.0, sort) + def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): """Fitting a power-law distribution to empirical data @@ -554,7 +585,7 @@ def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): @return: a L{FittedPowerLaw} object. The fitted C{xmin} value and the power-law exponent can be queried from the C{xmin} and C{alpha} properties of the returned object. - + @newfield ref: Reference @ref: MEJ Newman: Power laws, Pareto distributions and Zipf's law. Contemporary Physics 46, 323-351 (2005) @@ -573,12 +604,16 @@ def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): fit = FittedPowerLaw(*_power_law_fit(data, xmin, force_continuous)) if return_alpha_only: from igraph import deprecated - deprecated("The return_alpha_only keyword argument of power_law_fit is "\ - "deprecated from igraph 0.7 and will be removed in igraph 0.8") + + deprecated( + "The return_alpha_only keyword argument of power_law_fit is " + "deprecated from igraph 0.7 and will be removed in igraph 0.8" + ) return fit.alpha else: return fit + def quantile(xs, q=(0.25, 0.5, 0.75), sort=True): """Returns the qth quantile of an unsorted or sorted numeric vector. @@ -622,18 +657,19 @@ def quantile(xs, q=(0.25, 0.5, 0.75), sort=True): for q in qs: if q < 0 or q > 1: raise ValueError("q must be between 0 and 1") - n = float(q) * (len(xs)+1) - k, d = int(n), n-int(n) + n = float(q) * (len(xs) + 1) + k, d = int(n), n - int(n) if k >= len(xs): result.append(xs[-1]) elif k < 1: result.append(xs[0]) else: - result.append((1-d) * xs[k-1] + d * xs[k]) + result.append((1 - d) * xs[k - 1] + d * xs[k]) if return_single: result = result[0] return result + def sd(xs): """Returns the standard deviation of an iterable. @@ -649,6 +685,7 @@ def sd(xs): """ return RunningMean(xs).sd + def var(xs): """Returns the variance of an iterable. diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 143b597b0..2fda39ab0 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -13,7 +13,7 @@ __all__ = ["GraphSummary"] -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -33,6 +33,7 @@ 02110-1301 USA """ + class FakeWrapper(object): """Object whose interface is compatible with C{textwrap.TextWrapper} but does no wrapping.""" @@ -46,6 +47,7 @@ def fill(self, text): def wrap(self, text): return [text] + def _get_wrapper_for_width(width, *args, **kwds): """Returns a text wrapper that wraps text for the given width. @@ -56,6 +58,7 @@ def _get_wrapper_for_width(width, *args, **kwds): return FakeWrapper(*args, **kwds) return TextWrapper(width=width, *args, **kwds) + class GraphSummary(object): """Summary representation of a graph. @@ -87,14 +90,18 @@ class GraphSummary(object): _infer_column_alignment, _new_table, _vertex_attribute_iterator """ - - def __init__(self, graph, verbosity=0, width=78, - edge_list_format="auto", - max_rows=99999, - print_graph_attributes=False, - print_vertex_attributes=False, - print_edge_attributes=False, - full=False): + def __init__( + self, + graph, + verbosity=0, + width=78, + edge_list_format="auto", + max_rows=99999, + print_graph_attributes=False, + print_vertex_attributes=False, + print_edge_attributes=False, + full=False, + ): """Constructs a summary representation of a graph. @param verbosity: the verbosity of the summary. If zero, only @@ -131,8 +138,7 @@ def __init__(self, graph, verbosity=0, width=78, self.print_edge_attributes = print_edge_attributes self.verbosity = verbosity self.width = width - self.wrapper = _get_wrapper_for_width(self.width, - break_on_hyphens=False) + self.wrapper = _get_wrapper_for_width(self.width, break_on_hyphens=False) if self._graph.is_named(): self._edges_header = "+ edges (vertex names):" @@ -162,7 +168,7 @@ def _construct_edgelist_adjlist(self): maxlen = len(str(self._graph.vcount())) num_format = "%%%dd" % maxlen format_str = "%s %s %%s" % (num_format, self._arrow) - for v1 in xrange(self._graph.vcount()): + for v1 in range(self._graph.vcount()): neis = self._graph.successors(v1) neis = " ".join(num_format % v2 for v2 in neis) result.append(format_str % (v1, neis)) @@ -175,7 +181,7 @@ def _construct_edgelist_adjlist(self): # Rewrap to multiple columns nrows = len(result) - 1 colheight = int(ceil(nrows / float(colcount))) - newrows = [[] for _ in xrange(colheight)] + newrows = [[] for _ in range(colheight)] for i, row in enumerate(result[1:]): newrows[i % colheight].append(row.ljust(maxlen)) result[1:] = [" ".join(row) for row in newrows] @@ -190,8 +196,10 @@ def _construct_edgelist_compressed(self): if self._graph.is_named(): names = self._graph.vs["name"] - edges = ", ".join(arrow % (names[edge.source], names[edge.target]) - for edge in self._graph.es) + edges = ", ".join( + arrow % (names[edge.source], names[edge.target]) + for edge in self._graph.es + ) else: edges = " ".join(arrow % edge.tuple for edge in self._graph.es) @@ -204,9 +212,12 @@ def _construct_edgelist_edgelist(self): attrs = sorted(self._graph.edge_attributes()) table = self._new_table(headers=["", "edge"] + attrs) - table.add_rows(islice(self._edge_attribute_iterator(attrs), 0, self.max_rows), - header=False) - table.set_cols_align(["l", "l"] + self._infer_column_alignment(edge_attrs=attrs)) + table.add_rows( + islice(self._edge_attribute_iterator(attrs), 0, self.max_rows), header=False + ) + table.set_cols_align( + ["l", "l"] + self._infer_column_alignment(edge_attrs=attrs) + ) result = [self._edges_header] result.extend(table.draw().split("\n")) @@ -222,7 +233,7 @@ def _construct_graph_attributes(self): result = ["+ graph attributes:"] attrs.sort() for attr in attrs: - result.append("[[%s]]" % (attr, )) + result.append("[[%s]]" % (attr,)) result.append(str(self._graph[attr])) return result @@ -233,8 +244,10 @@ def _construct_vertex_attributes(self): return [] table = self._new_table(headers=[""] + attrs) - table.add_rows(islice(self._vertex_attribute_iterator(attrs), 0, self.max_rows), - header=False) + table.add_rows( + islice(self._vertex_attribute_iterator(attrs), 0, self.max_rows), + header=False, + ) table.set_cols_align(["l"] + self._infer_column_alignment(vertex_attrs=attrs)) result = ["+ vertex attributes:"] @@ -246,29 +259,31 @@ def _construct_header(self): """Constructs the header part of the summary.""" graph = self._graph params = dict( - directed="UD"[graph.is_directed()], - named="-N"[graph.is_named()], - weighted="-W"[graph.is_weighted()], - typed="-T"["type" in graph.vertex_attributes()], - vcount=graph.vcount(), - ecount=graph.ecount(), + directed="UD"[graph.is_directed()], + named="-N"[graph.is_named()], + weighted="-W"[graph.is_weighted()], + typed="-T"["type" in graph.vertex_attributes()], + vcount=graph.vcount(), + ecount=graph.ecount(), ) if "name" in graph.attributes(): params["name"] = graph["name"] else: params["name"] = "" - result = ["IGRAPH %(directed)s%(named)s%(weighted)s%(typed)s "\ - "%(vcount)d %(ecount)d -- %(name)s" % params] - - attrs = ["%s (g)" % (name, ) for name in sorted(graph.attributes())] - attrs.extend("%s (v)" % (name, ) for name in sorted(graph.vertex_attributes())) - attrs.extend("%s (e)" % (name, ) for name in sorted(graph.edge_attributes())) + result = [ + "IGRAPH %(directed)s%(named)s%(weighted)s%(typed)s " + "%(vcount)d %(ecount)d -- %(name)s" % params + ] + + attrs = ["%s (g)" % (name,) for name in sorted(graph.attributes())] + attrs.extend("%s (v)" % (name,) for name in sorted(graph.vertex_attributes())) + attrs.extend("%s (e)" % (name,) for name in sorted(graph.edge_attributes())) if attrs: result.append("+ attr: %s" % ", ".join(attrs)) if self.wrapper is not None: - self.wrapper.subsequent_indent = ' ' + self.wrapper.subsequent_indent = " " result[-1:] = self.wrapper.wrap(result[-1]) - self.wrapper.subsequent_indent = '' + self.wrapper.subsequent_indent = "" return result @@ -282,13 +297,15 @@ def _edge_attribute_iterator(self, attribute_order): names = self._graph.vs["name"] for edge in self._graph.es: formatted_edge = arrow % (names[edge.source], names[edge.target]) - yield ["[%d]" % edge.index, formatted_edge] + \ - [edge[attr] for attr in attribute_order] + yield ["[%d]" % edge.index, formatted_edge] + [ + edge[attr] for attr in attribute_order + ] else: for edge in self._graph.es: formatted_edge = arrow % edge.tuple - yield ["[%d]" % edge.index, formatted_edge] + \ - [edge[attr] for attr in attribute_order] + yield ["[%d]" % edge.index, formatted_edge] + [ + edge[attr] for attr in attribute_order + ] def _infer_column_alignment(self, vertex_attrs=None, edge_attrs=None): """Infers the preferred alignment for the given vertex and edge attributes @@ -347,7 +364,7 @@ def __str__(self): if self._graph.ecount() > 0: # Add the edge list if self.edge_list_format == "auto": - if (self.print_edge_attributes and self._graph.edge_attributes()): + if self.print_edge_attributes and self._graph.edge_attributes(): format = "edgelist" elif median(self._graph.degree(mode="out")) < 3: format = "compressed" @@ -364,4 +381,3 @@ def __str__(self): return "\n".join("\n".join(self.wrapper.wrap(line)) for line in output) return "\n".join(output) - diff --git a/src/igraph/test/foreign.py b/src/igraph/test/foreign.py index af8c1c950..eabaea1fd 100644 --- a/src/igraph/test/foreign.py +++ b/src/igraph/test/foreign.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - import io import unittest import warnings @@ -22,7 +20,8 @@ class ForeignTests(unittest.TestCase): def testDIMACS(self): - with temporary_file(u"""\ + with temporary_file( + """\ c c This is a simple example file to demonstrate the c DIMACS input file format for minimum-cost flow problems. @@ -40,17 +39,18 @@ def testDIMACS(self): a 2 3 2 a 2 4 3 a 3 4 5 - """) as tmpfname: + """ + ) as tmpfname: graph = Graph.Read_DIMACS(tmpfname, False) self.assertTrue(isinstance(graph, Graph)) self.assertTrue(graph.vcount() == 4 and graph.ecount() == 5) self.assertTrue(graph["source"] == 0 and graph["target"] == 3) - self.assertTrue(graph.es["capacity"] == [4,2,2,3,5]) + self.assertTrue(graph.es["capacity"] == [4, 2, 2, 3, 5]) graph.write_dimacs(tmpfname) - def testDL(self): - with temporary_file(u"""\ + with temporary_file( + """\ dl n=5 format = fullmatrix labels embedded @@ -61,16 +61,32 @@ def testDL(self): Lin 1 0 0 1 0 Pat 1 0 1 0 1 russ 0 1 0 1 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 12) self.assertTrue(g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ - (3,2),(3,4),(4,1),(4,3)]) - - with temporary_file(u"""\ + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 3), + (1, 0), + (1, 4), + (2, 0), + (2, 3), + (3, 0), + (3, 2), + (3, 4), + (4, 1), + (4, 3), + ] + ) + + with temporary_file( + """\ dl n=5 format = fullmatrix labels: @@ -83,16 +99,32 @@ def testDL(self): 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 12) self.assertTrue(g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ - (3,2),(3,4),(4,1),(4,3)]) - - with temporary_file(u"""\ + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 3), + (1, 0), + (1, 4), + (2, 0), + (2, 3), + (3, 0), + (3, 2), + (3, 4), + (4, 1), + (4, 3), + ] + ) + + with temporary_file( + """\ DL n=5 format = edgelist1 labels: @@ -104,60 +136,70 @@ def testDL(self): sally jim 4 billy george 5 jane jim 6 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname, False) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 5) self.assertTrue(not g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,2),(2,4)]) + self.assertTrue( + sorted(g.get_edgelist()) == [(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)] + ) def _testNCOLOrLGL(self, func, fname, can_be_reopened=True): - g = func(fname, names=False, weights=False, \ - directed=False) + g = func(fname, names=False, weights=False, directed=False) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 4 and g.ecount() == 5) self.assertTrue(not g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(1,1),(1,3),(2,3)]) - self.assertTrue("name" not in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + sorted(g.get_edgelist()) == [(0, 1), (0, 2), (1, 1), (1, 3), (2, 3)] + ) + self.assertTrue( + "name" not in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) if not can_be_reopened: return - g = func(fname, names=False, \ - directed=False) - self.assertTrue("name" not in g.vertex_attributes() and \ - "weight" in g.edge_attributes()) + g = func(fname, names=False, directed=False) + self.assertTrue( + "name" not in g.vertex_attributes() and "weight" in g.edge_attributes() + ) self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) g = func(fname, directed=False) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" in g.edge_attributes() + ) self.assertTrue(g.vs["name"] == ["eggs", "spam", "ham", "bacon"]) self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) def testNCOL(self): - with temporary_file(u"""\ + with temporary_file( + """\ eggs spam 1 ham eggs 2 ham bacon bacon spam 3 - spam spam""") as tmpfname: + spam spam""" + ) as tmpfname: self._testNCOLOrLGL(func=Graph.Read_Ncol, fname=tmpfname) - with temporary_file(u"""\ + with temporary_file( + """\ eggs spam ham eggs ham bacon bacon spam - spam spam""") as tmpfname: + spam spam""" + ) as tmpfname: g = Graph.Read_Ncol(tmpfname) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) def testLGL(self): - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam 1 # ham @@ -166,10 +208,12 @@ def testLGL(self): # bacon spam 3 # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=tmpfname) - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam # ham @@ -178,23 +222,28 @@ def testLGL(self): # bacon spam # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: with warnings.catch_warnings(): warnings.simplefilter("ignore") g = Graph.Read_Lgl(tmpfname) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) # This is not an LGL file; we are testing error handling here - with temporary_file(u"""\ + with temporary_file( + """\ 1 2 1 3 - """) as tmpfname: + """ + ) as tmpfname: with self.assertRaises(InternalError): Graph.Read_Lgl(tmpfname) def testLGLWithIOModule(self): - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam 1 # ham @@ -203,13 +252,16 @@ def testLGLWithIOModule(self): # bacon spam 3 # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: with io.open(tmpfname, "r") as fp: - self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=fp, - can_be_reopened=False) + self._testNCOLOrLGL( + func=Graph.Read_Lgl, fname=fp, can_be_reopened=False + ) def testAdjacency(self): - with temporary_file(u"""\ + with temporary_file( + """\ # Test comment line 0 1 1 0 0 0 1 0 1 0 0 0 @@ -217,22 +269,73 @@ def testAdjacency(self): 0 0 0 0 2 2 0 0 0 2 0 2 0 0 0 2 2 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_Adjacency(tmpfname) self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 6 and g.ecount() == 18 and - g.is_directed() and "weight" not in g.edge_attributes()) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 18 + and g.is_directed() + and "weight" not in g.edge_attributes() + ) g = Graph.Read_Adjacency(tmpfname, attribute="weight") self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 6 and g.ecount() == 12 and - g.is_directed() and g.es["weight"] == [1,1,1,1,1,1,2,2,2,2,2,2]) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 12 + and g.is_directed() + and g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] + ) g.write_adjacency(tmpfname) def testPickle(self): - pickle = [128, 2, 99, 105, 103, 114, 97, 112, 104, 10, 71, 114, 97, 112, - 104, 10, 113, 1, 40, 75, 3, 93, 113, 2, 75, 1, 75, 2, 134, 113, 3, 97, - 137, 125, 125, 125, 116, 82, 113, 4, 125, 98, 46] + pickle = [ + 128, + 2, + 99, + 105, + 103, + 114, + 97, + 112, + 104, + 10, + 71, + 114, + 97, + 112, + 104, + 10, + 113, + 1, + 40, + 75, + 3, + 93, + 113, + 2, + 75, + 1, + 75, + 2, + 134, + 113, + 3, + 97, + 137, + 125, + 125, + 125, + 116, + 82, + 113, + 4, + 125, + 98, + 46, + ] if sys.version_info > (3, 0): pickle = bytes(pickle) else: @@ -240,17 +343,16 @@ def testPickle(self): with temporary_file(pickle, "wb") as tmpfname: g = Graph.Read_Pickle(pickle) self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and - not g.is_directed()) + self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) @unittest.skipIf(nx is None, "test case depends on networkx") def testGraphNetworkx(self): # Undirected g = Graph.Ring(10) - g['gattr'] = 'graph_attribute' - g.vs['vattr'] = list(range(g.vcount())) - g.es['eattr'] = list(range(len(g.es))) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) # Go to networkx and back g_nx = g.to_networkx() @@ -263,16 +365,13 @@ def testGraphNetworkx(self): # Test attributes self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual( - sorted(['vattr', '_nx_name']), - sorted(g2.vertex_attributes())) + self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) for i, vertex in enumerate(g.vs): vertex2 = g2.vs[i] for an in vertex.attribute_names(): - if an == 'vattr': + if an == "vattr": continue - self.assertEqual( - vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) self.assertEqual(g.edge_attributes(), g2.edge_attributes()) for edge in g.es: eid = g2.get_eid(edge.source, edge.target) @@ -297,9 +396,9 @@ def testMultigraphNetworkx(self): # Undirected g = Graph.Ring(10) g.add_edge(0, 1) - g['gattr'] = 'graph_attribute' - g.vs['vattr'] = list(range(g.vcount())) - g.es['eattr'] = list(range(len(g.es))) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) # Go to networkx and back g_nx = g.to_networkx() @@ -312,9 +411,7 @@ def testMultigraphNetworkx(self): # Test attributes self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual( - sorted(['vattr', '_nx_name']), - sorted(g2.vertex_attributes())) + self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) self.assertEqual(g.edge_attributes(), g2.edge_attributes()) # Testing parallel edges is a bit more tricky edge2_found = set() @@ -356,15 +453,16 @@ def testMultigraphNetworkx(self): def testGraphGraphTool(self): # Undirected g = Graph.Ring(10) - g['gattr'] = 'graph_attribute' - g.vs['vattr'] = list(range(g.vcount())) - g.es['eattr'] = list(range(len(g.es))) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) # Go to graph-tool and back g_gt = g.to_graph_tool( - graph_attributes={'gattr': 'object'}, - vertex_attributes={'vattr': 'int'}, - edge_attributes={'eattr': 'int'}) + graph_attributes={"gattr": "object"}, + vertex_attributes={"vattr": "int"}, + edge_attributes={"eattr": "int"}, + ) g2 = Graph.from_graph_tool(g_gt) self.assertFalse(g2.is_directed()) @@ -378,8 +476,7 @@ def testGraphGraphTool(self): for i, vertex in enumerate(g.vs): vertex2 = g2.vs[i] for an in vertex.attribute_names(): - self.assertEqual( - vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) self.assertEqual(g.edge_attributes(), g2.edge_attributes()) for edge in g.es: eid = g2.get_eid(edge.source, edge.target) @@ -405,15 +502,16 @@ def testMultigraphGraphTool(self): # Undirected g = Graph.Ring(10) g.add_edge(0, 1) - g['gattr'] = 'graph_attribute' - g.vs['vattr'] = list(range(g.vcount())) - g.es['eattr'] = list(range(len(g.es))) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) # Go to graph-tool and back g_gt = g.to_graph_tool( - graph_attributes={'gattr': 'object'}, - vertex_attributes={'vattr': 'int'}, - edge_attributes={'eattr': 'int'}) + graph_attributes={"gattr": "object"}, + vertex_attributes={"vattr": "int"}, + edge_attributes={"eattr": "int"}, + ) g2 = Graph.from_graph_tool(g_gt) self.assertFalse(g2.is_directed()) @@ -427,8 +525,7 @@ def testMultigraphGraphTool(self): for i, vertex in enumerate(g.vs): vertex2 = g2.vs[i] for an in vertex.attribute_names(): - self.assertEqual( - vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) self.assertEqual(g.edge_attributes(), g2.edge_attributes()) # Testing parallel edges is a bit more tricky edge2_found = set() @@ -471,10 +568,11 @@ def suite(): foreign_suite = unittest.makeSuite(ForeignTests) return unittest.TestSuite([foreign_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/src/igraph/utils.py b/src/igraph/utils.py index ea88a81d9..b60eb666e 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -6,6 +6,7 @@ """ from contextlib import contextmanager + try: from collections.abc import MutableMapping except ImportError: @@ -17,13 +18,17 @@ import tempfile __all__ = ( - "dbl_epsilon", "multidict", "named_temporary_file", - "numpy_to_contiguous_memoryview", "rescale", - "safemin", "safemax" + "dbl_epsilon", + "multidict", + "named_temporary_file", + "numpy_to_contiguous_memoryview", + "rescale", + "safemin", + "safemax", ) __docformat__ = "restructuredtext en" -__license__ = u"""\ +__license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz Pázmány Péter sétány 1/a, 1117 Budapest, Hungary @@ -49,6 +54,7 @@ def _is_running_in_ipython(): IPython or not.""" try: from IPython import get_ipython + return get_ipython() is not None except ImportError: return False @@ -91,8 +97,7 @@ def numpy_to_contiguous_memoryview(obj): return memoryview(require(obj, dtype=dtype, requirements="AC")) -def rescale(values, out_range=(0., 1.), in_range=None, clamp=False, - scale=None): +def rescale(values, out_range=(0.0, 1.0), in_range=None, clamp=False, scale=None): """Rescales a list of numbers into a given range. `out_range` gives the range of the output values; by default, the minimum @@ -148,9 +153,9 @@ def rescale(values, out_range=(0., 1.), in_range=None, clamp=False, ratio = float(ma - mi) if not ratio: - return [(out_range[0] + out_range[1]) / 2.] * len(values) + return [(out_range[0] + out_range[1]) / 2.0] * len(values) - min_out, max_out = map(float, out_range) + min_out, max_out = list(map(float, out_range)) ratio = (max_out - min_out) / ratio result = [(x - mi) * ratio + min_out for x in values] @@ -160,9 +165,7 @@ def rescale(values, out_range=(0., 1.), in_range=None, clamp=False, return result -def str_to_orientation( - value, reversed_horizontal=False, reversed_vertical=False -): +def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False): """Tries to interpret a string as an orientation value. The following basic values are understood: ``left-right``, ``bottom-top``, @@ -186,9 +189,16 @@ def str_to_orientation( """ aliases = { - "left-right": "lr", "right-left": "rl", "top-bottom": "tb", - "bottom-top": "bt", "top-down": "tb", "bottom-up": "bt", - "top-bottom": "tb", "bottom-top": "bt", "td": "tb", "bu": "bt" + "left-right": "lr", + "right-left": "rl", + "top-bottom": "tb", + "bottom-top": "bt", + "top-down": "tb", + "bottom-up": "bt", + "top-bottom": "tb", + "bottom-top": "bt", + "td": "tb", + "bu": "bt", } dir = ["lr", "rl"][reversed_horizontal] @@ -227,7 +237,7 @@ def consecutive_pairs(iterable, circular=False): it = iter(iterable) try: - prev = it.next() + prev = next(it) except StopIteration: return first = prev @@ -257,8 +267,8 @@ def __init__(self, *args, **kwds): self._dict = {} if len(args) > 1: raise ValueError( - "%r expected at most 1 argument, got %d" % - (self.__class__.__name__, len(args)) + "%r expected at most 1 argument, got %d" + % (self.__class__.__name__, len(args)) ) if args: args = args[0] @@ -356,21 +366,21 @@ def getlist(self, key): def iterlists(self): """Iterates over ``(key, values)`` pairs where ``values`` is the list of values associated with ``key``.""" - return self._dict.iteritems() + return iter(self._dict.items()) def lists(self): """Returns a list of ``(key, values)`` pairs where ``values`` is the list of values associated with ``key``.""" - return self._dict.items() + return list(self._dict.items()) def update(self, arg, **kwds): if hasattr(arg, "keys") and callable(arg.keys): - for key in arg.keys(): + for key in list(arg.keys()): self.add(key, arg[key]) else: for key, value in arg: self.add(key, value) - for key, value in kwds.iteritems(): + for key, value in kwds.items(): self.add(key, value) @@ -389,7 +399,7 @@ def safemax(iterable, default=0): """ it = iter(iterable) try: - first = it.next() + first = next(it) except StopIteration: return default else: @@ -411,7 +421,7 @@ def safemin(iterable, default=0): """ it = iter(iterable) try: - first = it.next() + first = next(it) except StopIteration: return default else: diff --git a/tests/test_structural.py b/tests/test_structural.py index 2f192ce4c..e3e72d516 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -5,7 +5,7 @@ import warnings from igraph import * -from igraph.compat import isnan +from math import isnan class SimplePropertiesTests(unittest.TestCase): gfull = Graph.Full(10) diff --git a/tox.ini b/tox.ini index 055ea15f8..e70312f9f 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py36, py37, py38, py39, pypy, pypy3 +envlist = py36, py37, py38, py39, pypy, pypy3 [testenv] commands = python -m unittest @@ -16,9 +16,6 @@ deps = setenv = TESTING_IN_TOX=1 -[testenv:py27] -commands = python -m unittest discover - [testenv:py39] # py39 support is still sparse; most of the optional dependencies have no # wheels for Python 3.9 yet so we install only those where they do From 705da0a18f46db551cd2832037c24c01296b25fb Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 15 Jan 2021 21:18:24 +1100 Subject: [PATCH 0300/1892] 2to3 and black lint of tests --- tests/test_atlas.py | 109 +++++-- tests/test_attributes.py | 47 +-- tests/test_basic.py | 256 +++++++-------- tests/test_bipartite.py | 146 ++++++--- tests/test_cliques.py | 191 +++++++---- tests/test_colortests.py | 83 ++--- tests/test_conversion.py | 154 +++++---- tests/test_decomposition.py | 382 +++++++++++++++------- tests/test_edgeseq.py | 8 +- tests/test_flow.py | 96 +++--- tests/test_foreign.py | 227 +++++++++---- tests/test_games.py | 71 +++-- tests/test_generators.py | 161 +++++----- tests/test_homepage.py | 19 +- tests/test_indexing.py | 13 +- tests/test_isomorphism.py | 340 +++++++++++++------- tests/test_iterators.py | 33 +- tests/test_layouts.py | 141 ++++---- tests/test_matching.py | 56 +++- tests/test_operators.py | 345 ++++++++++++++------ tests/test_rng.py | 9 +- tests/test_separators.py | 20 +- tests/test_spectral.py | 59 ++-- tests/test_structural.py | 600 ++++++++++++++++++++++++----------- tests/test_unicode_issues.py | 12 +- tests/test_vertexseq.py | 8 +- tests/test_walks.py | 6 +- tests/utils.py | 10 +- 28 files changed, 2346 insertions(+), 1256 deletions(-) diff --git a/tests/test_atlas.py b/tests/test_atlas.py index 438c2a04a..322a61f89 100644 --- a/tests/test_atlas.py +++ b/tests/test_atlas.py @@ -1,5 +1,3 @@ -from __future__ import division - import warnings import unittest from igraph import * @@ -11,17 +9,27 @@ def testPageRank(self): try: pr = g.pagerank() except Exception as ex: - self.assertTrue(False, msg="PageRank calculation threw exception for graph #%d: %s" % (idx, ex)) + self.assertTrue( + False, + msg="PageRank calculation threw exception for graph #%d: %s" + % (idx, ex), + ) raise if g.vcount() == 0: self.assertEqual([], pr) continue - self.assertAlmostEqual(1.0, sum(pr), places=5, \ - msg="PageRank sum is not 1.0 for graph #%d (%r)" % (idx, pr)) - self.assertTrue(min(pr) >= 0, \ - msg="Minimum PageRank is less than 0 for graph #%d (%r)" % (idx, pr)) + self.assertAlmostEqual( + 1.0, + sum(pr), + places=5, + msg="PageRank sum is not 1.0 for graph #%d (%r)" % (idx, pr), + ) + self.assertTrue( + min(pr) >= 0, + msg="Minimum PageRank is less than 0 for graph #%d (%r)" % (idx, pr), + ) def testEigenvectorCentrality(self): # Temporarily turn off the warning handler because g.evcent() will print @@ -37,7 +45,11 @@ def testEigenvectorCentrality(self): try: ec, eval = g.evcent(return_eigenvalue=True) except Exception as ex: - self.assertTrue(False, msg="Eigenvector centrality threw exception for graph #%d: %s" % (idx, ex)) + self.assertTrue( + False, + msg="Eigenvector centrality threw exception for graph #%d: %s" + % (idx, ex), + ) raise if g.vcount() == 0: @@ -50,23 +62,40 @@ def testEigenvectorCentrality(self): n = g.vcount() if abs(eval) < 1e-4: - self.assertTrue(min(ec) >= -1e-10, - msg="Minimum eigenvector centrality is smaller than 0 for graph #%d" % idx) - self.assertTrue(max(ec) <= 1, - msg="Maximum eigenvector centrality is greater than 1 for graph #%d" % idx) + self.assertTrue( + min(ec) >= -1e-10, + msg="Minimum eigenvector centrality is smaller than 0 for graph #%d" + % idx, + ) + self.assertTrue( + max(ec) <= 1, + msg="Maximum eigenvector centrality is greater than 1 for graph #%d" + % idx, + ) continue - self.assertAlmostEqual(max(ec), 1, places=7, \ - msg="Maximum eigenvector centrality is %r (not 1) for graph #%d (%r)" % \ - (max(ec), idx, ec)) - self.assertTrue(min(ec) >= 0, \ - msg="Minimum eigenvector centrality is less than 0 for graph #%d" % idx) + self.assertAlmostEqual( + max(ec), + 1, + places=7, + msg="Maximum eigenvector centrality is %r (not 1) for graph #%d (%r)" + % (max(ec), idx, ec), + ) + self.assertTrue( + min(ec) >= 0, + msg="Minimum eigenvector centrality is less than 0 for graph #%d" + % idx, + ) ec2 = [sum(ec[u.index] for u in v.predecessors()) for v in g.vs] for i in range(n): - self.assertAlmostEqual(ec[i] * eval, ec2[i], places=7, \ - msg="Eigenvector centrality in graph #%d seems to be invalid "\ - "for vertex %d" % (idx, i)) + self.assertAlmostEqual( + ec[i] * eval, + ec2[i], + places=7, + msg="Eigenvector centrality in graph #%d seems to be invalid " + "for vertex %d" % (idx, i), + ) finally: # Reset the warning handler warnings.resetwarnings() @@ -78,10 +107,15 @@ def testHubScore(self): self.assertEqual([], sc) continue - self.assertAlmostEqual(max(sc), 1, places=7, \ - msg="Maximum authority score is not 1 for graph #%d" % idx) - self.assertTrue(min(sc) >= 0, \ - msg="Minimum hub score is less than 0 for graph #%d" % idx) + self.assertAlmostEqual( + max(sc), + 1, + places=7, + msg="Maximum authority score is not 1 for graph #%d" % idx, + ) + self.assertTrue( + min(sc) >= 0, msg="Minimum hub score is less than 0 for graph #%d" % idx + ) def testAuthorityScore(self): for idx, g in enumerate(self.__class__.graphs): @@ -90,29 +124,40 @@ def testAuthorityScore(self): self.assertEqual([], sc) continue - self.assertAlmostEqual(max(sc), 1, places=7, \ - msg="Maximum authority score is not 1 for graph #%d" % idx) - self.assertTrue(min(sc) >= 0, \ - msg="Minimum authority score is less than 0 for graph #%d" % idx) + self.assertAlmostEqual( + max(sc), + 1, + places=7, + msg="Maximum authority score is not 1 for graph #%d" % idx, + ) + self.assertTrue( + min(sc) >= 0, + msg="Minimum authority score is less than 0 for graph #%d" % idx, + ) + class GraphAtlasTests(unittest.TestCase, AtlasTestBase): graphs = [Graph.Atlas(i) for i in range(1253)] skip_graphs = set([180]) + class IsoclassTests(unittest.TestCase, AtlasTestBase): - graphs = [Graph.Isoclass(3, i, directed=True) for i in range(16)] + \ - [Graph.Isoclass(4, i, directed=True) for i in range(218)] + graphs = [Graph.Isoclass(3, i, directed=True) for i in range(16)] + [ + Graph.Isoclass(4, i, directed=True) for i in range(218) + ] skip_graphs = set([136]) + def suite(): atlas_suite = unittest.makeSuite(GraphAtlasTests) isoclass_suite = unittest.makeSuite(IsoclassTests) return unittest.TestSuite([atlas_suite, isoclass_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 4d81ee18f..a95c49261 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -3,6 +3,7 @@ import unittest from igraph import * + class AttributeTests(unittest.TestCase): def testGraphAttributes(self): g = Graph.Full(5) @@ -45,23 +46,23 @@ def testMassVertexAttributeAssignment(self): g = Graph.Full(5) g.vs.set_attribute_values("name", list(range(5))) self.assertTrue(g.vs.get_attribute_values("name") == list(range(5))) - g.vs["name"] = list(range(5,10)) - self.assertTrue(g.vs["name"] == list(range(5,10))) - g.vs["name2"] = (1,2,3,4,6) - self.assertTrue(g.vs["name2"] == [1,2,3,4,6]) + g.vs["name"] = list(range(5, 10)) + self.assertTrue(g.vs["name"] == list(range(5, 10))) + g.vs["name2"] = (1, 2, 3, 4, 6) + self.assertTrue(g.vs["name2"] == [1, 2, 3, 4, 6]) g.vs.set_attribute_values("name", [2]) - self.assertTrue(g.vs["name"] == [2]*5) + self.assertTrue(g.vs["name"] == [2] * 5) def testMassEdgeAttributeAssignment(self): g = Graph.Full(5) g.es.set_attribute_values("name", list(range(10))) self.assertTrue(g.es.get_attribute_values("name") == list(range(10))) - g.es["name"] = list(range(10,20)) - self.assertTrue(g.es["name"] == list(range(10,20))) - g.es["name2"] = (1,2,3,4,6,1,2,3,4,6) - self.assertTrue(g.es["name2"] == [1,2,3,4,6,1,2,3,4,6]) + g.es["name"] = list(range(10, 20)) + self.assertTrue(g.es["name"] == list(range(10, 20))) + g.es["name2"] = (1, 2, 3, 4, 6, 1, 2, 3, 4, 6) + self.assertTrue(g.es["name2"] == [1, 2, 3, 4, 6, 1, 2, 3, 4, 6]) g.es.set_attribute_values("name", [2]) - self.assertTrue(g.es["name"] == [2]*10) + self.assertTrue(g.es["name"] == [2] * 10) def testVertexNameIndexing(self): g = Graph.Famous("bull") @@ -71,10 +72,10 @@ def testVertexNameIndexing(self): g.vs[2]["name"] = "quack" self.assertRaises(ValueError, g.degree, "baz") self.assertTrue(g.degree("quack") == 3) - self.assertTrue(g.degree(u"quack") == 3) - self.assertTrue(g.degree([u"bar", u"thud", 0]) == [3, 1, 2]) + self.assertTrue(g.degree("quack") == 3) + self.assertTrue(g.degree(["bar", "thud", 0]) == [3, 1, 2]) del g.vs["name"] - self.assertRaises(ValueError, g.degree, [u"bar", u"thud", 0]) + self.assertRaises(ValueError, g.degree, ["bar", "thud", 0]) def testVertexNameIndexingBytes(self): g = Graph.Famous("bull") @@ -91,7 +92,7 @@ def testUnhashableVertexNames(self): g = Graph.Famous("bull") g.vs["name"] = [str(x) for x in range(4)] - value = "this is not hashable".split() + value = "this is not hashable".split() g.vs[2]["name"] = value # Trigger an indexing by doing a lookup by name @@ -108,7 +109,7 @@ def testUnhashableVertexNames(self): def testVertexNameIndexingBug196(self): g = Graph() - a, b = b'a', b'b' + a, b = b"a", b"b" g.add_vertices([a, b]) g.add_edges([(a, b)]) self.assertEqual(g.ecount(), 1) @@ -126,9 +127,10 @@ def testInvalidAttributeNames(self): self.assertRaises(TypeError, g.es[0].__setitem__, attr_name, "foo") self.assertRaises(TypeError, g.es[0].__getitem__, attr_name, "foo") + class AttributeCombinationTests(unittest.TestCase): def setUp(self): - el = [(0,1), (1,0), (1,2), (2,3), (2,3), (2,3), (3,3)] + el = [(0, 1), (1, 0), (1, 2), (2, 3), (2, 3), (2, 3), (3, 3)] self.g = Graph(el) self.g.es["weight"] = [1, 2, 3, 4, 5, 6, 7] self.g.es["weight2"] = [1, 2, 3, 4, 5, 6, 7] @@ -267,20 +269,23 @@ def testCombinationNone(self): class UnicodeAttributeTests(unittest.TestCase): def testUnicodeAttributeNameCombination(self): g = Graph.Erdos_Renyi(n=9, m=20) - g.es[u"test"] = 1 - g.contract_vertices([0,0,0,1,1,1,2,2,2]) + g.es["test"] = 1 + g.contract_vertices([0, 0, 0, 1, 1, 1, 2, 2, 2]) def suite(): attribute_suite = unittest.makeSuite(AttributeTests) attribute_combination_suite = unittest.makeSuite(AttributeCombinationTests) unicode_attributes_suite = unittest.makeSuite(UnicodeAttributeTests) - return unittest.TestSuite([attribute_suite, attribute_combination_suite, - unicode_attributes_suite]) + return unittest.TestSuite( + [attribute_suite, attribute_combination_suite, unicode_attributes_suite] + ) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() diff --git a/tests/test_basic.py b/tests/test_basic.py index 5368db09e..2d7c7be6a 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,8 +1,13 @@ import unittest from igraph import ( - ALL, Graph, IN, InternalError, is_degree_sequence, - is_graphical_degree_sequence, Matrix + ALL, + Graph, + IN, + InternalError, + is_degree_sequence, + is_graphical_degree_sequence, + Matrix, ) try: @@ -15,32 +20,35 @@ class BasicTests(unittest.TestCase): def testGraphCreation(self): g = Graph() self.assertTrue(isinstance(g, Graph)) - self.assertTrue( - g.vcount() == 0 and g.ecount() == 0 and not g.is_directed() - ) + self.assertTrue(g.vcount() == 0 and g.ecount() == 0 and not g.is_directed()) g = Graph(3, [(0, 1), (1, 2), (2, 0)]) self.assertTrue( - g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and - g.is_simple() + g.vcount() == 3 + and g.ecount() == 3 + and not g.is_directed() + and g.is_simple() ) g = Graph(2, [(0, 1), (1, 2), (2, 3)], True) self.assertTrue( - g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and - g.is_simple() + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and g.is_simple() ) g = Graph([(0, 1), (1, 2), (2, 1)]) self.assertTrue( - g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and - not g.is_simple() + g.vcount() == 3 + and g.ecount() == 3 + and not g.is_directed() + and not g.is_simple() ) g = Graph(((0, 1), (0, 0), (1, 2))) self.assertTrue( - g.vcount() == 3 and g.ecount() == 3 and not g.is_directed() and - not g.is_simple() + g.vcount() == 3 + and g.ecount() == 3 + and not g.is_directed() + and not g.is_simple() ) g = Graph(8, None) @@ -61,8 +69,7 @@ def testGraphCreationWithNumPy(self): arr = np.array([(0, 1), (1, 2), (2, 3)]) g = Graph(arr, directed=True) self.assertTrue( - g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and - g.is_simple() + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and g.is_simple() ) # Sliced NumPy array -- the sliced array is non-contiguous but we @@ -70,8 +77,7 @@ def testGraphCreationWithNumPy(self): arr = np.array([(0, 1), (10, 11), (1, 2), (11, 12), (2, 3), (12, 13)]) g = Graph(arr[::2, :], directed=True) self.assertTrue( - g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and - g.is_simple() + g.vcount() == 4 and g.ecount() == 3 and g.is_directed() and g.is_simple() ) # 1D NumPy array -- should raise a TypeError because we need a 2D array @@ -79,9 +85,7 @@ def testGraphCreationWithNumPy(self): self.assertRaises(TypeError, Graph, arr) # 3D NumPy array -- should raise a TypeError because we need a 2D array - arr = np.array( - [([0, 1], [10, 11]), ([1, 2], [11, 12]), ([2, 3], [12, 13])] - ) + arr = np.array([([0, 1], [10, 11]), ([1, 2], [11, 12]), ([2, 3], [12, 13])]) self.assertRaises(TypeError, Graph, arr) # NumPy array with strings -- should be a casting error @@ -117,9 +121,7 @@ def testAddVertex(self): vertex = g.add_vertex(name="frob", spam="cheese", ham=42) self.assertTrue(g.vcount() == 5 and g.ecount() == 0) self.assertEqual(4, vertex.index) - self.assertEqual( - sorted(g.vertex_attributes()), ["ham", "name", "spam"] - ) + self.assertEqual(sorted(g.vertex_attributes()), ["ham", "name", "spam"]) self.assertEqual(g.vs["spam"], [None] * 4 + ["cheese"]) self.assertEqual(g.vs["ham"], [None] * 4 + [42]) @@ -136,7 +138,7 @@ def testAddVertices(self): self.assertTrue(g.vcount() == 5 and g.ecount() == 0) self.assertEqual(g.vs[2:]["name"], ["spam", "bacon", "eggs"]) - g.add_vertices(2, attributes={'color': ['k', 'b']}) + g.add_vertices(2, attributes={"color": ["k", "b"]}) self.assertEqual(g.vs[2:]["name"], ["spam", "bacon", "eggs", None, None]) self.assertEqual(g.vs[5:]["color"], ["k", "b"]) @@ -214,17 +216,25 @@ def testAddEdges(self): g.add_edges([("spam", "eggs"), ("spam", "ham")]) self.assertEqual(g.vcount(), 4) - self.assertEqual(g.get_edgelist(), [ - (0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3) - ]) - - g.add_edges([(0, 0), (1, 1)], attributes={'color': ['k', 'b']}) - self.assertEqual(g.get_edgelist(), [ - (0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3), (0, 0), (1, 1), - ]) self.assertEqual( - g.es['color'], - [None, None, None, None, None, None, 'k', 'b']) + g.get_edgelist(), [(0, 1), (1, 2), (2, 3), (1, 3), (0, 2), (0, 3)] + ) + + g.add_edges([(0, 0), (1, 1)], attributes={"color": ["k", "b"]}) + self.assertEqual( + g.get_edgelist(), + [ + (0, 1), + (1, 2), + (2, 3), + (1, 3), + (0, 2), + (0, 3), + (0, 0), + (1, 1), + ], + ) + self.assertEqual(g.es["color"], [None, None, None, None, None, None, "k", "b"]) def testDeleteEdges(self): g = Graph.Famous("petersen") @@ -297,7 +307,7 @@ def testGraphGetEid(self): g = Graph.Famous("petersen") g.vs["name"] = list("ABCDEFGHIJ") edges_to_ids = dict((v, k) for k, v in enumerate(g.get_edgelist())) - for (source, target), edge_id in edges_to_ids.items(): + for (source, target), edge_id in list(edges_to_ids.items()): source_name, target_name = g.vs[(source, target)]["name"] self.assertEqual(edge_id, g.get_eid(source, target)) self.assertEqual(edge_id, g.get_eid(source_name, target_name)) @@ -343,28 +353,38 @@ def testMultiplesLoops(self): g.add_edges([(0, 1), (7, 7), (6, 6), (6, 6), (6, 6)]) # is_loop - self.assertTrue(g.is_loop() == [ - False, False, False, False, False, False, False, - True, True, True, True - ]) - self.assertTrue(g.is_loop(g.ecount()-2)) - self.assertTrue(g.is_loop(range(6, 8)) == [False, True]) + self.assertTrue( + g.is_loop() + == [False, False, False, False, False, False, False, True, True, True, True] + ) + self.assertTrue(g.is_loop(g.ecount() - 2)) + self.assertTrue(g.is_loop(list(range(6, 8))) == [False, True]) # is_multiple - self.assertTrue(g.is_multiple() == [ - False, False, False, False, False, False, True, - False, False, True, True - ]) + self.assertTrue( + g.is_multiple() + == [ + False, + False, + False, + False, + False, + False, + True, + False, + False, + True, + True, + ] + ) # has_multiple self.assertTrue(g.has_multiple()) # count_multiple - self.assertTrue( - g.count_multiple() == [2, 1, 1, 1, 1, 1, 2, 1, 3, 3, 3] - ) - self.assertTrue(g.count_multiple(g.ecount()-1) == 3) - self.assertTrue(g.count_multiple(range(2, 5)) == [1, 1, 1]) + self.assertTrue(g.count_multiple() == [2, 1, 1, 1, 1, 1, 2, 1, 3, 3, 3]) + self.assertTrue(g.count_multiple(g.ecount() - 1) == 3) + self.assertTrue(g.count_multiple(list(range(2, 5))) == [1, 1, 1]) # check if a mutual directed edge pair is reported as multiple g = Graph(2, [(0, 1), (1, 0)], directed=True) @@ -372,6 +392,7 @@ def testMultiplesLoops(self): def testPickling(self): import pickle + g = Graph([(0, 1), (1, 2)]) g["data"] = "abcdef" g.vs["data"] = [3, 4, 5] @@ -448,22 +469,16 @@ class GraphDictListTests(unittest.TestCase): def setUp(self): self.vertices = [ {"name": "Alice", "age": 48, "gender": "F"}, - {"name": "Bob", "age": 33, "gender": "M"}, + {"name": "Bob", "age": 33, "gender": "M"}, {"name": "Cecil", "age": 45, "gender": "F"}, - {"name": "David", "age": 34, "gender": "M"} + {"name": "David", "age": 34, "gender": "M"}, ] self.edges = [ {"source": "Alice", "target": "Bob", "friendship": 4, "advice": 4}, {"source": "Cecil", "target": "Bob", "friendship": 5, "advice": 5}, - { - "source": "Cecil", "target": "Alice", - "friendship": 5, "advice": 5 - }, - { - "source": "David", "target": "Alice", - "friendship": 2, "advice": 4 - }, - {"source": "David", "target": "Bob", "friendship": 1, "advice": 2} + {"source": "Cecil", "target": "Alice", "friendship": 5, "advice": 5}, + {"source": "David", "target": "Alice", "friendship": 2, "advice": 4}, + {"source": "David", "target": "Bob", "friendship": 1, "advice": 2}, ] def testGraphFromDictList(self): @@ -475,9 +490,7 @@ def testGraphFromDictList(self): def testGraphFromDictIterator(self): g = Graph.DictList(iter(self.vertices), iter(self.edges)) self.checkIfOK(g, "name") - g = Graph.DictList( - iter(self.vertices), iter(self.edges), iterative=True - ) + g = Graph.DictList(iter(self.vertices), iter(self.edges), iterative=True) self.checkIfOK(g, "name") def testGraphFromDictIteratorNoVertices(self): @@ -487,19 +500,15 @@ def testGraphFromDictIteratorNoVertices(self): self.checkIfOK(g, "name", check_vertex_attrs=False) def testGraphFromDictListExtraVertexName(self): - del self.vertices[2:] # No data for "Cecil" and "David" + del self.vertices[2:] # No data for "Cecil" and "David" g = Graph.DictList(self.vertices, self.edges) - self.assertTrue( - g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() - ) + self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and not g.is_directed()) self.assertTrue(g.vs["name"] == ["Alice", "Bob", "Cecil", "David"]) self.assertTrue(g.vs["age"] == [48, 33, None, None]) self.assertTrue(g.vs["gender"] == ["F", "M", None, None]) self.assertTrue(g.es["friendship"] == [4, 5, 5, 2, 1]) self.assertTrue(g.es["advice"] == [4, 5, 5, 4, 2]) - self.assertTrue(g.get_edgelist() == [ - (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) - ]) + self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) def testGraphFromDictListAlternativeName(self): for vdata in self.vertices: @@ -510,18 +519,16 @@ def testGraphFromDictListAlternativeName(self): ) self.checkIfOK(g, "name_alternative") g = Graph.DictList( - self.vertices, self.edges, vertex_name_attr="name_alternative", - iterative=True + self.vertices, + self.edges, + vertex_name_attr="name_alternative", + iterative=True, ) self.checkIfOK(g, "name_alternative") def checkIfOK(self, g, name_attr, check_vertex_attrs=True): - self.assertTrue( - g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() - ) - self.assertTrue(g.get_edgelist() == [ - (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) - ]) + self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and not g.is_directed()) + self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) if check_vertex_attrs: self.assertTrue(g.vs["age"] == [48, 33, 45, 34]) @@ -537,7 +544,7 @@ def setUp(self): ("Cecil", "Bob", 5, 5), ("Cecil", "Alice", 5, 5), ("David", "Alice", 2, 4), - ("David", "Bob", 1, 2) + ("David", "Bob", 1, 2), ] def testGraphFromTupleList(self): @@ -547,10 +554,10 @@ def testGraphFromTupleList(self): def testGraphFromTupleListWithEdgeAttributes(self): g = Graph.TupleList(self.edges, edge_attrs=("friendship", "advice")) self.checkIfOK(g, "name", ("friendship", "advice")) - g = Graph.TupleList(self.edges, edge_attrs=("friendship", )) - self.checkIfOK(g, "name", ("friendship", )) + g = Graph.TupleList(self.edges, edge_attrs=("friendship",)) + self.checkIfOK(g, "name", ("friendship",)) g = Graph.TupleList(self.edges, edge_attrs="friendship") - self.checkIfOK(g, "name", ("friendship", )) + self.checkIfOK(g, "name", ("friendship",)) def testGraphFromTupleListWithDifferentNameAttribute(self): g = Graph.TupleList(self.edges, vertex_name_attr="spam") @@ -558,29 +565,26 @@ def testGraphFromTupleListWithDifferentNameAttribute(self): def testGraphFromTupleListWithWeights(self): g = Graph.TupleList(self.edges, weights=True) - self.checkIfOK(g, "name", ("weight", )) + self.checkIfOK(g, "name", ("weight",)) g = Graph.TupleList(self.edges, weights="friendship") - self.checkIfOK(g, "name", ("friendship", )) + self.checkIfOK(g, "name", ("friendship",)) g = Graph.TupleList(self.edges, weights=False) self.checkIfOK(g, "name", ()) self.assertRaises( - ValueError, Graph.TupleList, [self.edges], weights=True, - edge_attrs="friendship" + ValueError, + Graph.TupleList, + [self.edges], + weights=True, + edge_attrs="friendship", ) def testNoneForMissingAttributes(self): - g = Graph.TupleList( - self.edges, edge_attrs=("friendship", "advice", "spam") - ) + g = Graph.TupleList(self.edges, edge_attrs=("friendship", "advice", "spam")) self.checkIfOK(g, "name", ("friendship", "advice", "spam")) def checkIfOK(self, g, name_attr, edge_attrs): - self.assertTrue( - g.vcount() == 4 and g.ecount() == 5 and not g.is_directed() - ) - self.assertTrue(g.get_edgelist() == [ - (0, 1), (1, 2), (0, 2), (0, 3), (1, 3) - ]) + self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and not g.is_directed()) + self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) self.assertTrue(g.attributes() == []) self.assertTrue(g.vertex_attributes() == [name_attr]) self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) @@ -609,14 +613,13 @@ def testIsDegreeSequence(self): self.assertFalse(is_degree_sequence([2, 1, -2])) self.assertFalse(is_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None - )) + self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None)) self.assertFalse(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) - self.assertTrue(is_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], - [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] - )) + self.assertTrue( + is_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + ) + ) def testIsGraphicalSequence(self): self.assertTrue(is_graphical_degree_sequence([])) @@ -627,26 +630,21 @@ def testIsGraphicalSequence(self): self.assertFalse(is_graphical_degree_sequence([1], [1])) self.assertFalse(is_graphical_degree_sequence([2])) self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1])) - self.assertTrue(is_graphical_degree_sequence( - [2, 1, 1, 1], [1, 1, 1, 2] - )) + self.assertTrue(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, 2])) self.assertFalse(is_graphical_degree_sequence([2, 1, -2])) - self.assertFalse(is_graphical_degree_sequence( - [2, 1, 1, 1], [1, 1, 1, -2] - )) - self.assertTrue(is_graphical_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3] - )) - self.assertTrue(is_graphical_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None - )) - self.assertFalse(is_graphical_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] - )) - self.assertTrue(is_graphical_degree_sequence( - [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], - [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] - )) + self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) + self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) + self.assertTrue( + is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None) + ) + self.assertFalse( + is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]) + ) + self.assertTrue( + is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + ) + ) self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 4])) @@ -686,10 +684,16 @@ def suite(): graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) - return unittest.TestSuite([ - basic_suite, datatype_suite, graph_dict_list_suite, - graph_tuple_list_suite, degree_sequence_suite, inheritance_suite - ]) + return unittest.TestSuite( + [ + basic_suite, + datatype_suite, + graph_dict_list_suite, + graph_tuple_list_suite, + degree_sequence_suite, + inheritance_suite, + ] + ) def test(): diff --git a/tests/test_bipartite.py b/tests/test_bipartite.py index 74a57a002..283686cf6 100644 --- a/tests/test_bipartite.py +++ b/tests/test_bipartite.py @@ -1,99 +1,149 @@ import unittest from igraph import * + class BipartiteTests(unittest.TestCase): def testCreateBipartite(self): - g = Graph.Bipartite([0, 1]*5, [(0,1),(2,3),(4,5),(6,7),(8,9)]) - self.assertTrue(g.vcount() == 10 and g.ecount() == 5 and g.is_directed() == False) + g = Graph.Bipartite([0, 1] * 5, [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]) + self.assertTrue( + g.vcount() == 10 and g.ecount() == 5 and g.is_directed() is False + ) self.assertTrue(g.is_bipartite()) - self.assertTrue(g.vs["type"] == [False, True]*5) + self.assertTrue(g.vs["type"] == [False, True] * 5) def testFullBipartite(self): g = Graph.Full_Bipartite(10, 5) - self.assertTrue(g.vcount() == 15 and g.ecount() == 50 and g.is_directed() == False) + self.assertTrue( + g.vcount() == 15 and g.ecount() == 50 and g.is_directed() is False + ) expected = sorted([(i, j) for i in range(10) for j in range(10, 15)]) self.assertTrue(sorted(g.get_edgelist()) == expected) - self.assertTrue(g.vs["type"] == [False]*10 + [True]*5) + self.assertTrue(g.vs["type"] == [False] * 10 + [True] * 5) g = Graph.Full_Bipartite(10, 5, directed=True, mode=OUT) - self.assertTrue(g.vcount() == 15 and g.ecount() == 50 and g.is_directed() == True) + self.assertTrue( + g.vcount() == 15 and g.ecount() == 50 and g.is_directed() is True + ) self.assertTrue(sorted(g.get_edgelist()) == expected) - self.assertTrue(g.vs["type"] == [False]*10 + [True]*5) + self.assertTrue(g.vs["type"] == [False] * 10 + [True] * 5) g = Graph.Full_Bipartite(10, 5, directed=True, mode=IN) - self.assertTrue(g.vcount() == 15 and g.ecount() == 50 and g.is_directed() == True) - self.assertTrue(sorted(g.get_edgelist()) == sorted([(i,j) for j, i in expected])) - self.assertTrue(g.vs["type"] == [False]*10 + [True]*5) + self.assertTrue( + g.vcount() == 15 and g.ecount() == 50 and g.is_directed() is True + ) + self.assertTrue( + sorted(g.get_edgelist()) == sorted([(i, j) for j, i in expected]) + ) + self.assertTrue(g.vs["type"] == [False] * 10 + [True] * 5) g = Graph.Full_Bipartite(10, 5, directed=True) - self.assertTrue(g.vcount() == 15 and g.ecount() == 100 and g.is_directed() == True) + self.assertTrue( + g.vcount() == 15 and g.ecount() == 100 and g.is_directed() is True + ) expected.extend([(j, i) for i, j in expected]) expected.sort() self.assertTrue(sorted(g.get_edgelist()) == expected) - self.assertTrue(g.vs["type"] == [False]*10 + [True]*5) + self.assertTrue(g.vs["type"] == [False] * 10 + [True] * 5) def testIncidence(self): g = Graph.Incidence([[0, 1, 1], [1, 2, 0]]) self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) - self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3)]) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True) self.assertTrue(all((g.vcount() == 5, g.ecount() == 5, not g.is_directed()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) - self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3),(1,3)]) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) + self.assertListEqual( + sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3), (1, 3)] + ) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True) self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) - self.assertListEqual(sorted(g.get_edgelist()), [(0,3),(0,4),(1,2),(1,3)]) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="in") self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) - self.assertListEqual(sorted(g.get_edgelist()), [(2,1),(3,0),(3,1),(4,0)]) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) + self.assertListEqual(sorted(g.get_edgelist()), [(2, 1), (3, 0), (3, 1), (4, 0)]) # Create a weighted Graph g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted=True) - self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertTrue( + all( + (g.vcount() == 5, g.ecount() == 4, not g.is_directed(), g.is_weighted()) + ) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) - self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Graph is not weighted when weighted=`str` g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="some_attr_name") - self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), not g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertTrue( + all( + ( + g.vcount() == 5, + g.ecount() == 4, + not g.is_directed(), + not g.is_weighted(), + ) + ) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es["some_attr_name"], [1, 1, 1, 2]) - self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Graph is not weighted when weighted="" g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="") - self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed(), not g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertTrue( + all( + ( + g.vcount() == 5, + g.ecount() == 4, + not g.is_directed(), + not g.is_weighted(), + ) + ) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es[""], [1, 1, 1, 2]) - self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Should work when directed=True and mode=out with weighted g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, weighted=True) - self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + self.assertTrue( + all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted())) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) - self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2),(1,3)]) + self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Should work when directed=True and mode=in with weighted - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="in", weighted=True) - self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + g = Graph.Incidence( + [[0, 1, 1], [1, 2, 0]], directed=True, mode="in", weighted=True + ) + self.assertTrue( + all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted())) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es["weight"], [1, 1, 1, 2]) self.assertListEqual(sorted(g.get_edgelist()), [(2, 1), (3, 0), (3, 1), (4, 0)]) # Should work when directed=True and mode=all with weighted - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="all", weighted=True) - self.assertTrue(all((g.vcount() == 5, g.ecount() == 8, g.is_directed(), g.is_weighted()))) - self.assertListEqual(g.vs["type"], [False]*2 + [True]*3) + g = Graph.Incidence( + [[0, 1, 1], [1, 2, 0]], directed=True, mode="all", weighted=True + ) + self.assertTrue( + all((g.vcount() == 5, g.ecount() == 8, g.is_directed(), g.is_weighted())) + ) + self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(g.es["weight"], [1, 1, 1, 1, 1, 1, 2, 2]) - self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (3, 1), (4, 0)]) + self.assertListEqual( + sorted(g.get_edgelist()), + [(0, 3), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (3, 1), (4, 0)], + ) def testIncidenceError(self): msg = "arguments weighted and multiple can not co-exist" @@ -152,26 +202,28 @@ def testBipartiteProjection(self): def testIsBipartite(self): g = Graph.Star(10) - self.assertTrue(g.is_bipartite() == True) - self.assertTrue(g.is_bipartite(True) == (True, [False] + [True]*9)) + self.assertTrue(g.is_bipartite() is True) + self.assertTrue(g.is_bipartite(True) == (True, [False] + [True] * 9)) g = Graph.Tree(100, 3) - self.assertTrue(g.is_bipartite() == True) + self.assertTrue(g.is_bipartite() is True) g = Graph.Ring(9) - self.assertTrue(g.is_bipartite() == False) + self.assertTrue(g.is_bipartite() is False) self.assertTrue(g.is_bipartite(True) == (False, None)) g = Graph.Ring(10) - self.assertTrue(g.is_bipartite() == True) + self.assertTrue(g.is_bipartite() is True) g += (2, 0) self.assertTrue(g.is_bipartite(True) == (False, None)) - + + def suite(): bipartite_suite = unittest.makeSuite(BipartiteTests) return unittest.TestSuite([bipartite_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 1cb2de48e..f972fd715 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest from igraph import * @@ -9,48 +7,89 @@ class CliqueTests(unittest.TestCase): def setUp(self): - self.g=Graph.Full(6) + self.g = Graph.Full(6) self.g.delete_edges([(0, 1), (0, 2), (3, 5)]) def testCliques(self): - tests = {(4, -1): [[1, 2, 3, 4], [1, 2, 4, 5]], - (2, 2): [[0, 3], [0, 4], [0, 5], - [1, 2], [1, 3], [1, 4], [1, 5], - [2, 3], [2, 4], [2, 5], [3, 4], [4, 5]], - (-1, -1): [[0], [1], [2], [3], [4], [5], - [0, 3], [0, 4], [0, 5], - [1, 2], [1, 3], [1, 4], [1, 5], - [2, 3], [2, 4], [2, 5], [3, 4], [4, 5], - [0, 3, 4], [0, 4, 5], - [1, 2, 3], [1, 2, 4], [1, 2, 5], - [1, 3, 4], [1, 4, 5], [2, 3, 4], [2, 4, 5], - [1, 2, 3, 4], [1, 2, 4, 5]]} - for (lo, hi), exp in tests.items(): + tests = { + (4, -1): [[1, 2, 3, 4], [1, 2, 4, 5]], + (2, 2): [ + [0, 3], + [0, 4], + [0, 5], + [1, 2], + [1, 3], + [1, 4], + [1, 5], + [2, 3], + [2, 4], + [2, 5], + [3, 4], + [4, 5], + ], + (-1, -1): [ + [0], + [1], + [2], + [3], + [4], + [5], + [0, 3], + [0, 4], + [0, 5], + [1, 2], + [1, 3], + [1, 4], + [1, 5], + [2, 3], + [2, 4], + [2, 5], + [3, 4], + [4, 5], + [0, 3, 4], + [0, 4, 5], + [1, 2, 3], + [1, 2, 4], + [1, 2, 5], + [1, 3, 4], + [1, 4, 5], + [2, 3, 4], + [2, 4, 5], + [1, 2, 3, 4], + [1, 2, 4, 5], + ], + } + for (lo, hi), exp in list(tests.items()): self.assertEqual(sorted(exp), sorted(map(sorted, self.g.cliques(lo, hi)))) def testLargestCliques(self): - self.assertEqual(sorted(map(sorted, self.g.largest_cliques())), - [[1, 2, 3, 4], [1, 2, 4, 5]]) + self.assertEqual( + sorted(map(sorted, self.g.largest_cliques())), [[1, 2, 3, 4], [1, 2, 4, 5]] + ) def testMaximalCliques(self): - self.assertEqual(sorted(map(sorted, self.g.maximal_cliques())), - [[0, 3, 4], [0, 4, 5], - [1, 2, 3, 4], [1, 2, 4, 5]]) - self.assertEqual(sorted(map(sorted, self.g.maximal_cliques(min=4))), - [[1, 2, 3, 4], [1, 2, 4, 5]]) - self.assertEqual(sorted(map(sorted, self.g.maximal_cliques(max=3))), - [[0, 3, 4], [0, 4, 5]]) + self.assertEqual( + sorted(map(sorted, self.g.maximal_cliques())), + [[0, 3, 4], [0, 4, 5], [1, 2, 3, 4], [1, 2, 4, 5]], + ) + self.assertEqual( + sorted(map(sorted, self.g.maximal_cliques(min=4))), + [[1, 2, 3, 4], [1, 2, 4, 5]], + ) + self.assertEqual( + sorted(map(sorted, self.g.maximal_cliques(max=3))), [[0, 3, 4], [0, 4, 5]] + ) def testMaximalCliquesFile(self): def read_cliques(fname): with open(fname) as fp: - return sorted(sorted(int(item) for item in line.split()) - for line in fp) + return sorted(sorted(int(item) for item in line.split()) for line in fp) with temporary_file() as fname: self.g.maximal_cliques(file=fname) - self.assertEqual([[0, 3, 4], [0, 4, 5], [1, 2, 3, 4], [1, 2, 4, 5]], - read_cliques(fname)) + self.assertEqual( + [[0, 3, 4], [0, 4, 5], [1, 2, 3, 4], [1, 2, 4, 5]], read_cliques(fname) + ) with temporary_file() as fname: self.g.maximal_cliques(min=4, file=fname) @@ -67,28 +106,52 @@ def testCliqueNumber(self): class IndependentVertexSetTests(unittest.TestCase): def setUp(self): - self.g1=Graph.Tree(5, 2, TREE_UNDIRECTED) - self.g2=Graph.Tree(10, 2, TREE_UNDIRECTED) + self.g1 = Graph.Tree(5, 2, TREE_UNDIRECTED) + self.g2 = Graph.Tree(10, 2, TREE_UNDIRECTED) def testIndependentVertexSets(self): - tests = {(4, -1): [], - (2, 2): [(0, 3), (0, 4), (1, 2), (2, 3), (2, 4), (3, 4)], - (-1, -1): [(0,), (1,), (2,), (3,), (4,), - (0, 3), (0, 4), (1, 2), (2, 3), (2, 4), - (3, 4), (0, 3, 4), (2, 3, 4)]} - for (lo, hi), exp in tests.items(): + tests = { + (4, -1): [], + (2, 2): [(0, 3), (0, 4), (1, 2), (2, 3), (2, 4), (3, 4)], + (-1, -1): [ + (0,), + (1,), + (2,), + (3,), + (4,), + (0, 3), + (0, 4), + (1, 2), + (2, 3), + (2, 4), + (3, 4), + (0, 3, 4), + (2, 3, 4), + ], + } + for (lo, hi), exp in list(tests.items()): self.assertEqual(exp, self.g1.independent_vertex_sets(lo, hi)) def testLargestIndependentVertexSets(self): - self.assertEqual(self.g1.largest_independent_vertex_sets(), - [(0, 3, 4), (2, 3, 4)]) + self.assertEqual( + self.g1.largest_independent_vertex_sets(), [(0, 3, 4), (2, 3, 4)] + ) def testMaximalIndependentVertexSets(self): - self.assertEqual(self.g2.maximal_independent_vertex_sets(), - [(0, 3, 4, 5, 6), (0, 3, 5, 6, 9), - (0, 4, 5, 6, 7, 8), (0, 5, 6, 7, 8, 9), - (1, 2, 7, 8, 9), (1, 5, 6, 7, 8, 9), - (2, 3, 4), (2, 3, 9), (2, 4, 7, 8)]) + self.assertEqual( + self.g2.maximal_independent_vertex_sets(), + [ + (0, 3, 4, 5, 6), + (0, 3, 5, 6, 9), + (0, 4, 5, 6, 7, 8), + (0, 5, 6, 7, 8, 9), + (1, 2, 7, 8, 9), + (1, 5, 6, 7, 8, 9), + (2, 3, 4), + (2, 3, 9), + (2, 4, 7, 8), + ], + ) def testIndependenceNumber(self): self.assertEqual(self.g2.independence_number(), 6) @@ -122,13 +185,14 @@ def testTriads(self): tc = self.g.triad_census() accessors = ["003", "012", "021d", "030C"] for a in accessors: - self.assertTrue(isinstance(getattr(tc, "t"+a), int)) + self.assertTrue(isinstance(getattr(tc, "t" + a), int)) self.assertTrue(isinstance(tc[a], int)) self.assertTrue(isinstance(list(tc), list)) self.assertTrue(isinstance(tuple(tc), tuple)) self.assertTrue(len(list(tc)) == 16) self.assertTrue(len(tuple(tc)) == 16) + class CliqueBenchmark(object): """This is a benchmark, not a real test case. You can run it using: @@ -140,6 +204,7 @@ class CliqueBenchmark(object): def __init__(self): from time import time import gc + self.time = time self.gc_collect = gc.collect @@ -163,15 +228,17 @@ def timeit(self, g): cl = g.maximal_cliques() end = self.time() self.gc_collect() - return len(cl), mid-start, end-mid + return len(cl), mid - start, end - mid def testRandom(self): - np = {100: [0.6, 0.7], - 300: [0.1, 0.2, 0.3, 0.4], - 500: [0.1, 0.2, 0.3], - 700: [0.1, 0.2], - 1000:[0.1, 0.2], - 10000: [0.001, 0.003, 0.005, 0.01, 0.02]} + np = { + 100: [0.6, 0.7], + 300: [0.1, 0.2, 0.3, 0.4], + 500: [0.1, 0.2, 0.3], + 700: [0.1, 0.2], + 1000: [0.1, 0.2], + 10000: [0.001, 0.003, 0.005, 0.01, 0.02], + } print() print("Erdos-Renyi random graphs") @@ -189,12 +256,19 @@ def testMoonMoser(self): print("Moon-Moser graphs") print(" n exp_clqs #cliques t1 t2") for n in ns: - n3 = n/3 - types = range(n3) * 3 - el = [(i, j) for i in range(n) for j in range(i+1,n) if types[i] != types[j]] + n3 = n / 3 + types = list(range(n3)) * 3 + el = [ + (i, j) + for i in range(n) + for j in range(i + 1, n) + if types[i] != types[j] + ] g = Graph(n, el) result = self.timeit(g) - print("%8d %8d %8d %8.4fs %8.4fs" % tuple([n, (3**(n/3))] + list(result))) + print( + "%8d %8d %8d %8.4fs %8.4fs" % tuple([n, (3 ** (n / 3))] + list(result)) + ) def testGRG(self): ns = [100, 1000, 5000, 10000, 25000, 50000] @@ -203,7 +277,7 @@ def testGRG(self): print("Geometric random graphs") print(" n d #cliques t1 t2") for n in ns: - d = 2. / (n ** 0.5) + d = 2.0 / (n ** 0.5) g = Graph.GRG(n, d) result = self.timeit(g) print("%8d %8.3f %8d %8.4fs %8.4fs" % tuple([n, d] + list(result))) @@ -215,10 +289,11 @@ def suite(): motif_suite = unittest.makeSuite(MotifTests) return unittest.TestSuite([clique_suite, indvset_suite, motif_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_colortests.py b/tests/test_colortests.py index df7332ef1..4cf99954c 100644 --- a/tests/test_colortests.py +++ b/tests/test_colortests.py @@ -1,42 +1,42 @@ import unittest -try: - from itertools import izip -except ImportError: - izip = zip # Python 3.x - from igraph import * + class ColorTests(unittest.TestCase): def assertAlmostEqualMany(self, items1, items2, eps): - for idx, (item1, item2) in enumerate(izip(items1, items2)): - self.assertAlmostEqual(item1, item2, places=eps, - msg="mismatch at index %d, %r != %r with %d digits" - % (idx, items1, items2, eps)) + for idx, (item1, item2) in enumerate(zip(items1, items2)): + self.assertAlmostEqual( + item1, + item2, + places=eps, + msg="mismatch at index %d, %r != %r with %d digits" + % (idx, items1, items2, eps), + ) def setUp(self): columns = ["r", "g", "b", "h", "v", "l", "s_hsv", "s_hsl", "alpha"] # Examples taken from http://en.wikipedia.org/wiki/HSL_and_HSV values = [ - (1, 1, 1, 0, 1, 1, 0, 0, 1), - (0.5, 0.5, 0.5, 0, 0.5, 0.5, 0, 0, 0.5), - (0, 0, 0, 0, 0, 0, 0, 0, 1), - (1, 0, 0, 0, 1, 0.5, 1, 1, 0.5), - (0.75, 0.75, 0, 60, 0.75, 0.375, 1, 1, 0.25), - (0, 0.5, 0, 120, 0.5, 0.25, 1, 1, 0.75), - (0.5, 1, 1, 180, 1, 0.75, 0.5, 1, 1), - (0.5, 0.5, 1, 240, 1, 0.75, 0.5, 1, 1), - (0.75, 0.25, 0.75, 300, 0.75, 0.5, 0.666666667, 0.5, 0.25), - (0.211, 0.149, 0.597, 248.3, 0.597, 0.373, 0.750, 0.601, 1), - (0.495, 0.493, 0.721, 240.5, 0.721, 0.607, 0.316, 0.290, 0.75), + (1, 1, 1, 0, 1, 1, 0, 0, 1), + (0.5, 0.5, 0.5, 0, 0.5, 0.5, 0, 0, 0.5), + (0, 0, 0, 0, 0, 0, 0, 0, 1), + (1, 0, 0, 0, 1, 0.5, 1, 1, 0.5), + (0.75, 0.75, 0, 60, 0.75, 0.375, 1, 1, 0.25), + (0, 0.5, 0, 120, 0.5, 0.25, 1, 1, 0.75), + (0.5, 1, 1, 180, 1, 0.75, 0.5, 1, 1), + (0.5, 0.5, 1, 240, 1, 0.75, 0.5, 1, 1), + (0.75, 0.25, 0.75, 300, 0.75, 0.5, 0.666666667, 0.5, 0.25), + (0.211, 0.149, 0.597, 248.3, 0.597, 0.373, 0.750, 0.601, 1), + (0.495, 0.493, 0.721, 240.5, 0.721, 0.607, 0.316, 0.290, 0.75), ] - self.data = [dict(zip(columns, value)) for value in values] + self.data = [dict(list(zip(columns, value))) for value in values] for row in self.data: - row["h"] /= 360. + row["h"] /= 360.0 def _testGeneric(self, method, args1, args2=("r", "g", "b")): - if len(args1) == len(args2)+1: - args2 += ("alpha", ) + if len(args1) == len(args2) + 1: + args2 += ("alpha",) for data in self.data: vals1 = [data.get(arg, 0.0) for arg in args1] vals2 = [data.get(arg, 0.0) for arg in args2] @@ -58,34 +58,38 @@ def testRGBtoHSL(self): self._testGeneric(rgb_to_hsl, "r g b".split(), "h s_hsl l".split()) def testRGBAtoHSLA(self): - self._testGeneric(rgba_to_hsla, "r g b alpha".split(), "h s_hsl l alpha".split()) + self._testGeneric( + rgba_to_hsla, "r g b alpha".split(), "h s_hsl l alpha".split() + ) def testRGBtoHSV(self): self._testGeneric(rgb_to_hsv, "r g b".split(), "h s_hsv v".split()) def testRGBAtoHSVA(self): - self._testGeneric(rgba_to_hsva, "r g b alpha".split(), "h s_hsv v alpha".split()) + self._testGeneric( + rgba_to_hsva, "r g b alpha".split(), "h s_hsv v alpha".split() + ) class PaletteTests(unittest.TestCase): def testGradientPalette(self): gp = GradientPalette("red", "blue", 3) - self.assertTrue(gp.get(0) == (1., 0., 0., 1.)) - self.assertTrue(gp.get(1) == (0.5, 0., 0.5, 1.)) - self.assertTrue(gp.get(2) == (0., 0., 1., 1.)) + self.assertTrue(gp.get(0) == (1.0, 0.0, 0.0, 1.0)) + self.assertTrue(gp.get(1) == (0.5, 0.0, 0.5, 1.0)) + self.assertTrue(gp.get(2) == (0.0, 0.0, 1.0, 1.0)) def testAdvancedGradientPalette(self): agp = AdvancedGradientPalette(["red", "black", "blue"], n=9) - self.assertTrue(agp.get(0) == (1., 0., 0., 1.)) - self.assertTrue(agp.get(2) == (0.5, 0., 0., 1.)) - self.assertTrue(agp.get(4) == (0., 0., 0., 1.)) - self.assertTrue(agp.get(5) == (0., 0., 0.25, 1.)) - self.assertTrue(agp.get(8) == (0., 0., 1., 1.)) + self.assertTrue(agp.get(0) == (1.0, 0.0, 0.0, 1.0)) + self.assertTrue(agp.get(2) == (0.5, 0.0, 0.0, 1.0)) + self.assertTrue(agp.get(4) == (0.0, 0.0, 0.0, 1.0)) + self.assertTrue(agp.get(5) == (0.0, 0.0, 0.25, 1.0)) + self.assertTrue(agp.get(8) == (0.0, 0.0, 1.0, 1.0)) agp = AdvancedGradientPalette(["red", "black", "blue"], [0, 8, 2], 9) - self.assertTrue(agp.get(0) == (1., 0., 0., 1.)) - self.assertTrue(agp.get(1) == (0.5, 0., 0.5, 1.)) - self.assertTrue(agp.get(5) == (0., 0., 0.5, 1.)) + self.assertTrue(agp.get(0) == (1.0, 0.0, 0.0, 1.0)) + self.assertTrue(agp.get(1) == (0.5, 0.0, 0.5, 1.0)) + self.assertTrue(agp.get(5) == (0.0, 0.0, 0.5, 1.0)) def suite(): @@ -93,10 +97,11 @@ def suite(): palette_suite = unittest.makeSuite(PaletteTests) return unittest.TestSuite([color_suite, palette_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 8a00cbe09..6c3860806 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -1,46 +1,50 @@ import unittest from igraph import * + class DirectedUndirectedTests(unittest.TestCase): def testToUndirected(self): - graph = Graph([(0,1), (0,2), (1,0)], directed=True) + graph = Graph([(0, 1), (0, 2), (1, 0)], directed=True) graph2 = graph.copy() graph2.to_undirected(mode=False) self.assertTrue(graph2.vcount() == graph.vcount()) self.assertTrue(graph2.is_directed() == False) - self.assertTrue(sorted(graph2.get_edgelist()) == [(0,1), (0,1), (0,2)]) + self.assertTrue(sorted(graph2.get_edgelist()) == [(0, 1), (0, 1), (0, 2)]) graph2 = graph.copy() graph2.to_undirected() self.assertTrue(graph2.vcount() == graph.vcount()) self.assertTrue(graph2.is_directed() == False) - self.assertTrue(sorted(graph2.get_edgelist()) == [(0,1), (0,2)]) + self.assertTrue(sorted(graph2.get_edgelist()) == [(0, 1), (0, 2)]) graph2 = graph.copy() - graph2.es["weight"] = [1,2,3] + graph2.es["weight"] = [1, 2, 3] graph2.to_undirected(mode="collapse", combine_edges="sum") self.assertTrue(graph2.vcount() == graph.vcount()) self.assertTrue(graph2.is_directed() == False) - self.assertTrue(sorted(graph2.get_edgelist()) == [(0,1), (0,2)]) - self.assertTrue(graph2.es["weight"] == [4,2]) + self.assertTrue(sorted(graph2.get_edgelist()) == [(0, 1), (0, 2)]) + self.assertTrue(graph2.es["weight"] == [4, 2]) - graph = Graph([(0,1),(1,0),(0,1),(1,0),(2,1),(1,2)], directed=True) + graph = Graph([(0, 1), (1, 0), (0, 1), (1, 0), (2, 1), (1, 2)], directed=True) graph2 = graph.copy() - graph2.es["weight"] = [1,2,3,4,5,6] + graph2.es["weight"] = [1, 2, 3, 4, 5, 6] graph2.to_undirected(mode="mutual", combine_edges="sum") self.assertTrue(graph2.vcount() == graph.vcount()) self.assertTrue(graph2.is_directed() == False) - self.assertTrue(sorted(graph2.get_edgelist()) == [(0,1), (0,1), (1,2)]) - self.assertTrue(graph2.es["weight"] == [7,3,11] or graph2.es["weight"] == [3,7,11]) + self.assertTrue(sorted(graph2.get_edgelist()) == [(0, 1), (0, 1), (1, 2)]) + self.assertTrue( + graph2.es["weight"] == [7, 3, 11] or graph2.es["weight"] == [3, 7, 11] + ) def testToDirected(self): - graph = Graph([(0,1), (0,2), (2,3), (2,4)], directed=False) + graph = Graph([(0, 1), (0, 2), (2, 3), (2, 4)], directed=False) graph.to_directed() self.assertTrue(graph.is_directed()) self.assertTrue(graph.vcount() == 5) - self.assertTrue(sorted(graph.get_edgelist()) == \ - [(0,1), (0,2), (1,0), (2,0), (2,3), (2,4), (3,2), (4,2)] + self.assertTrue( + sorted(graph.get_edgelist()) + == [(0, 1), (0, 2), (1, 0), (2, 0), (2, 3), (2, 4), (3, 2), (4, 2)] ) @@ -48,43 +52,64 @@ class GraphRepresentationTests(unittest.TestCase): def testGetAdjacency(self): # Undirected case g = Graph.Tree(6, 3) - g.es["weight"] = range(5) - self.assertTrue(g.get_adjacency() == Matrix([ - [0, 1, 1, 1, 0, 0], - [1, 0, 0, 0, 1, 1], - [1, 0, 0, 0, 0, 0], - [1, 0, 0, 0, 0, 0], - [0, 1, 0, 0, 0, 0], - [0, 1, 0, 0, 0, 0] - ])) - self.assertTrue(g.get_adjacency(attribute="weight") == Matrix([ - [0, 0, 1, 2, 0, 0], - [0, 0, 0, 0, 3, 4], - [1, 0, 0, 0, 0, 0], - [2, 0, 0, 0, 0, 0], - [0, 3, 0, 0, 0, 0], - [0, 4, 0, 0, 0, 0] - ])) - self.assertTrue(g.get_adjacency(eids=True) == Matrix([ - [0, 1, 2, 3, 0, 0], - [1, 0, 0, 0, 4, 5], - [2, 0, 0, 0, 0, 0], - [3, 0, 0, 0, 0, 0], - [0, 4, 0, 0, 0, 0], - [0, 5, 0, 0, 0, 0] - ])-1) + g.es["weight"] = list(range(5)) + self.assertTrue( + g.get_adjacency() + == Matrix( + [ + [0, 1, 1, 1, 0, 0], + [1, 0, 0, 0, 1, 1], + [1, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0], + ] + ) + ) + self.assertTrue( + g.get_adjacency(attribute="weight") + == Matrix( + [ + [0, 0, 1, 2, 0, 0], + [0, 0, 0, 0, 3, 4], + [1, 0, 0, 0, 0, 0], + [2, 0, 0, 0, 0, 0], + [0, 3, 0, 0, 0, 0], + [0, 4, 0, 0, 0, 0], + ] + ) + ) + self.assertTrue( + g.get_adjacency(eids=True) + == Matrix( + [ + [0, 1, 2, 3, 0, 0], + [1, 0, 0, 0, 4, 5], + [2, 0, 0, 0, 0, 0], + [3, 0, 0, 0, 0, 0], + [0, 4, 0, 0, 0, 0], + [0, 5, 0, 0, 0, 0], + ] + ) + - 1 + ) # Directed case g = Graph.Tree(6, 3, "tree_out") - g.add_edges([(0,1), (1,0)]) - self.assertTrue(g.get_adjacency() == Matrix([ - [0, 2, 1, 1, 0, 0], - [1, 0, 0, 0, 1, 1], - [0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0] - ])) + g.add_edges([(0, 1), (1, 0)]) + self.assertTrue( + g.get_adjacency() + == Matrix( + [ + [0, 2, 1, 1, 0, 0], + [1, 0, 0, 0, 1, 1], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + ] + ) + ) def testGetSparseAdjacency(self): try: @@ -95,32 +120,37 @@ def testGetSparseAdjacency(self): # Undirected case g = Graph.Tree(6, 3) - g.es["weight"] = range(5) - self.assertTrue(np.all( - (g.get_adjacency_sparse() == np.array(g.get_adjacency().data)) - )) - self.assertTrue(np.all( - (g.get_adjacency_sparse(attribute="weight") == np.array(g.get_adjacency(attribute="weight").data)) - )) + g.es["weight"] = list(range(5)) + self.assertTrue( + np.all((g.get_adjacency_sparse() == np.array(g.get_adjacency().data))) + ) + self.assertTrue( + np.all( + ( + g.get_adjacency_sparse(attribute="weight") + == np.array(g.get_adjacency(attribute="weight").data) + ) + ) + ) # Directed case g = Graph.Tree(6, 3, "tree_out") - g.add_edges([(0,1), (1,0)]) - self.assertTrue(np.all( - g.get_adjacency_sparse() == np.array(g.get_adjacency().data) - )) + g.add_edges([(0, 1), (1, 0)]) + self.assertTrue( + np.all(g.get_adjacency_sparse() == np.array(g.get_adjacency().data)) + ) def suite(): direction_suite = unittest.makeSuite(DirectedUndirectedTests) representation_suite = unittest.makeSuite(GraphRepresentationTests) - return unittest.TestSuite([direction_suite, - representation_suite]) + return unittest.TestSuite([direction_suite, representation_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 1f48c2f09..3eaef38fb 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -3,27 +3,31 @@ import math from igraph import * + try: set, frozenset except NameError: import sets + set, frozenset = sets.Set, sets.ImmutableSet class SubgraphTests(unittest.TestCase): def testSubgraph(self): g = Graph.Lattice([10, 10], circular=False, mutual=False) - g.vs["id"] = range(g.vcount()) + g.vs["id"] = list(range(g.vcount())) vs = [0, 1, 2, 10, 11, 12, 20, 21, 22] sg = g.subgraph(vs) - self.assertTrue(sg.isomorphic(Graph.Lattice([3, 3], circular=False, mutual=False))) + self.assertTrue( + sg.isomorphic(Graph.Lattice([3, 3], circular=False, mutual=False)) + ) self.assertTrue(sg.vs["id"] == vs) def testSubgraphEdges(self): g = Graph.Lattice([10, 10], circular=False, mutual=False) - g.es["id"] = range(g.ecount()) + g.es["id"] = list(range(g.ecount())) es = [0, 1, 2, 5, 20, 21, 22, 24, 38, 40] sg = g.subgraph_edges(es) @@ -36,20 +40,37 @@ def testSubgraphEdges(self): class DecompositionTests(unittest.TestCase): def testKCores(self): - g = Graph(11, [(0,1), (0,2), (0,3), (1,2), (1,3), (2,3), - (2,4), (2,5), (3,6), (3,7), (1,7), (7,8), - (1,9), (1,10), (9,10)]) - self.assertTrue(g.coreness() == [3,3,3,3,1,1,1,2,1,2,2]) + g = Graph( + 11, + [ + (0, 1), + (0, 2), + (0, 3), + (1, 2), + (1, 3), + (2, 3), + (2, 4), + (2, 5), + (3, 6), + (3, 7), + (1, 7), + (7, 8), + (1, 9), + (1, 10), + (9, 10), + ], + ) + self.assertTrue(g.coreness() == [3, 3, 3, 3, 1, 1, 1, 2, 1, 2, 2]) self.assertTrue(g.shell_index() == g.coreness()) - l=g.k_core(3).get_edgelist() + l = g.k_core(3).get_edgelist() l.sort() - self.assertTrue(l == [(0,1), (0,2), (0,3), (1,2), (1,3), (2,3)]) + self.assertTrue(l == [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]) class ClusteringTests(unittest.TestCase): def setUp(self): - self.cl = Clustering([0,0,0,1,1,2,1,1,4,4]) + self.cl = Clustering([0, 0, 0, 1, 1, 2, 1, 1, 4, 4]) def testClusteringIndex(self): self.assertTrue(self.cl[0] == [0, 1, 2]) @@ -62,7 +83,7 @@ def testClusteringLength(self): self.assertTrue(len(self.cl) == 5) def testClusteringMembership(self): - self.assertTrue(self.cl.membership == [0,0,0,1,1,2,1,1,4,4]) + self.assertTrue(self.cl.membership == [0, 0, 0, 1, 1, 2, 1, 1, 4, 4]) def testClusteringSizes(self): self.assertTrue(self.cl.sizes() == [3, 4, 1, 0, 2]) @@ -81,7 +102,7 @@ def setUp(self): def testFromStringAttribute(self): cl = VertexClustering.FromAttribute(self.graph, "string") - self.assertTrue(cl.membership == [0,0,0,1,1,2,2,2,0,1]) + self.assertTrue(cl.membership == [0, 0, 0, 1, 1, 2, 2, 2, 0, 1]) def testFromIntAttribute(self): cl = VertexClustering.FromAttribute(self.graph, "int") @@ -93,7 +114,7 @@ def testFromIntAttribute(self): def testClusterGraph(self): cl = VertexClustering(self.graph, [0, 0, 0, 1, 1, 1, 2, 2, 2, 2]) - self.graph.delete_edges(self.graph.es.select(_between=([0,1,2], [3,4,5]))) + self.graph.delete_edges(self.graph.es.select(_between=([0, 1, 2], [3, 4, 5]))) clg = cl.cluster_graph(dict(string="concat", int=max)) self.assertTrue(sorted(clg.get_edgelist()) == [(0, 2), (1, 2)]) @@ -102,8 +123,14 @@ def testClusterGraph(self): self.assertTrue(clg.vs["int"] == [41, 64, 47]) clg = cl.cluster_graph(dict(string="concat", int=max), False) - self.assertTrue(sorted(clg.get_edgelist()) == \ - [(0, 0)]*3 + [(0, 2)]*12 + [(1, 1)]*3 + [(1, 2)]*12 + [(2, 2)]*6) + self.assertTrue( + sorted(clg.get_edgelist()) + == [(0, 0)] * 3 + + [(0, 2)] * 12 + + [(1, 1)] * 3 + + [(1, 2)] * 12 + + [(2, 2)] * 6 + ) self.assertTrue(not clg.is_directed()) self.assertTrue(clg.vs["string"] == ["aaa", "bbc", "ccab"]) self.assertTrue(clg.vs["int"] == [41, 64, 47]) @@ -111,7 +138,7 @@ def testClusterGraph(self): class CoverTests(unittest.TestCase): def setUp(self): - self.cl = Cover([(0,1,2,3), (3,4,5,6,9), (), (8,9)]) + self.cl = Cover([(0, 1, 2, 3), (3, 4, 5, 6, 9), (), (8, 9)]) def testCoverIndex(self): self.assertTrue(self.cl[0] == [0, 1, 2, 3]) @@ -133,9 +160,9 @@ def testCoverHistogram(self): def testCoverConstructorWithN(self): self.assertTrue(self.cl.n == 10) - cl = Cover(self.cl, n = 15) + cl = Cover(self.cl, n=15) self.assertTrue(cl.n == 15) - cl = Cover(self.cl, n = 1) + cl = Cover(self.cl, n=1) self.assertTrue(cl.n == 10) @@ -151,29 +178,30 @@ def assertMembershipsEqual(self, observed, expected): observed = observed.membership if hasattr(expected, "membership"): expected = expected.membership - self.assertEqual(self.reindexMembership(expected), \ - self.reindexMembership(observed)) + self.assertEqual( + self.reindexMembership(expected), self.reindexMembership(observed) + ) def testClauset(self): # Two cliques of size 5 with one connecting edge g = Graph.Full(5) + Graph.Full(5) g.add_edges([(0, 5)]) cl = g.community_fastgreedy().as_clustering() - self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]) self.assertAlmostEqual(cl.q, 0.4523, places=3) # Lollipop, weighted g = Graph.Full(4) + Graph.Full(2) - g.add_edges([(3,4)]) + g.add_edges([(3, 4)]) weights = [1, 1, 1, 1, 1, 1, 10, 10] cl = g.community_fastgreedy(weights).as_clustering() - self.assertMembershipsEqual(cl, [0,0,0,1,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 1, 1, 1]) self.assertAlmostEqual(cl.q, 0.1708, places=3) # Same graph, different weights g.es["weight"] = [3] * g.ecount() cl = g.community_fastgreedy("weight").as_clustering() - self.assertMembershipsEqual(cl, [0,0,0,0,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 1, 1]) self.assertAlmostEqual(cl.q, 0.1796, places=3) # Disconnected graph @@ -184,34 +212,34 @@ def testClauset(self): # Empty graph g = Graph(20) cl = g.community_fastgreedy().as_clustering() - self.assertMembershipsEqual(cl, range(g.vcount())) + self.assertMembershipsEqual(cl, list(range(g.vcount()))) def testEdgeBetweenness(self): # Full graph, no weights g = Graph.Full(5) cl = g.community_edge_betweenness().as_clustering() - self.assertMembershipsEqual(cl, [0]*5) + self.assertMembershipsEqual(cl, [0] * 5) # Full graph with weights g.es["weight"] = 1 - g[0,1] = g[1,2] = g[2,0] = g[3,4] = 10 + g[0, 1] = g[1, 2] = g[2, 0] = g[3, 4] = 10 # We need to specify the desired cluster count explicitly; this is # because edge betweenness-based detection does not play well with # modularity-based cluster count selection (the edge weights have # different semantics) so we need to give igraph a hint cl = g.community_edge_betweenness(weights="weight").as_clustering(n=2) - self.assertMembershipsEqual(cl, [0,0,0,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 1, 1]) self.assertAlmostEqual(cl.q, 0.2750, places=3) def testEigenvector(self): g = Graph.Full(5) + Graph.Full(5) g.add_edges([(0, 5)]) cl = g.community_leading_eigenvector() - self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]) self.assertAlmostEqual(cl.q, 0.4523, places=3) cl = g.community_leading_eigenvector(2) - self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]) self.assertAlmostEqual(cl.q, 0.4523, places=3) def testInfomap(self): @@ -219,7 +247,11 @@ def testInfomap(self): cl = g.community_infomap() self.assertAlmostEqual(cl.codelength, 4.60605, places=3) self.assertAlmostEqual(cl.q, 0.40203, places=3) - self.assertMembershipsEqual(cl, [1,1,1,1,2,2,2,1,0,1,2,1,1,1,0,0,2,1,0,1,0,1] + [0]*12) + self.assertMembershipsEqual( + cl, + [1, 1, 1, 1, 2, 2, 2, 1, 0, 1, 2, 1, 1, 1, 0, 0, 2, 1, 0, 1, 0, 1] + + [0] * 12, + ) # Smoke testing with vertex and edge weights v_weights = [random.randint(1, 5) for _ in range(g.vcount())] @@ -234,29 +266,59 @@ def testLabelPropagation(self): # test. g = Graph.GRG(100, 0.2) cl = g.community_label_propagation() - g = Graph([(0,1),(1,2),(2,3)]) + g = Graph([(0, 1), (1, 2), (2, 3)]) g.es["weight"] = [2, 1, 2] g.vs["initial"] = [0, -1, -1, 1] - cl = g.community_label_propagation("weight", "initial", [1,0,0,1]) - self.assertMembershipsEqual(cl, [0,0,1,1]) - cl = g.community_label_propagation(initial="initial", fixed=[1,0,0,1]) - self.assertTrue(cl.membership == [0, 0, 1, 1] or \ - cl.membership == [0, 1, 1, 1] or \ - cl.membership == [0, 0, 0, 1]) + cl = g.community_label_propagation("weight", "initial", [1, 0, 0, 1]) + self.assertMembershipsEqual(cl, [0, 0, 1, 1]) + cl = g.community_label_propagation(initial="initial", fixed=[1, 0, 0, 1]) + self.assertTrue( + cl.membership == [0, 0, 1, 1] + or cl.membership == [0, 1, 1, 1] + or cl.membership == [0, 0, 0, 1] + ) def testMultilevel(self): # Example graph from the paper g = Graph(16) - g += [(0,2), (0,3), (0,4), (0,5), - (1,2), (1,4), (1,7), (2,4), (2,5), (2,6), - (3,7), (4,10), (5,7), (5,11), (6,7), (6,11), - (8,9), (8,10), (8,11), (8,14), (8,15), - (9,12), (9,14), (10,11), (10,12), (10,13), - (10,14), (11,13)] + g += [ + (0, 2), + (0, 3), + (0, 4), + (0, 5), + (1, 2), + (1, 4), + (1, 7), + (2, 4), + (2, 5), + (2, 6), + (3, 7), + (4, 10), + (5, 7), + (5, 11), + (6, 7), + (6, 11), + (8, 9), + (8, 10), + (8, 11), + (8, 14), + (8, 15), + (9, 12), + (9, 14), + (10, 11), + (10, 12), + (10, 13), + (10, 14), + (11, 13), + ] cls = g.community_multilevel(return_levels=True) self.assertTrue(len(cls) == 2) - self.assertMembershipsEqual(cls[0], [1,1,1,0,1,1,0,0,2,2,2,3,2,3,2,2]) - self.assertMembershipsEqual(cls[1], [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1]) + self.assertMembershipsEqual( + cls[0], [1, 1, 1, 0, 1, 1, 0, 0, 2, 2, 2, 3, 2, 3, 2, 2] + ) + self.assertMembershipsEqual( + cls[1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] + ) self.assertAlmostEqual(cls[0].q, 0.346301, places=5) self.assertAlmostEqual(cls[1].q, 0.392219, places=5) @@ -271,21 +333,59 @@ def testOptimalModularity(self): ws = [i % 5 for i in range(g.ecount())] cl = g.community_optimal_modularity(weights=ws) - self.assertAlmostEqual(cl.q, g.modularity(cl.membership, weights=ws), - places=7) + self.assertAlmostEqual( + cl.q, g.modularity(cl.membership, weights=ws), places=7 + ) g = Graph.Famous("zachary") cl = g.community_optimal_modularity() self.assertTrue(len(cl) == 4) - self.assertMembershipsEqual(cl, [0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 1, \ - 0, 0, 0, 2, 2, 1, 0, 2, 0, 2, 0, 2, 3, 3, 3, 2, 3, 3, \ - 2, 2, 3, 2, 2]) + self.assertMembershipsEqual( + cl, + [ + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 2, + 2, + 1, + 0, + 0, + 0, + 2, + 2, + 1, + 0, + 2, + 0, + 2, + 0, + 2, + 3, + 3, + 3, + 2, + 3, + 3, + 2, + 2, + 3, + 2, + 2, + ], + ) self.assertAlmostEqual(cl.q, 0.4197896, places=7) - ws = [2+(i % 3) for i in range(g.ecount())] + ws = [2 + (i % 3) for i in range(g.ecount())] cl = g.community_optimal_modularity(weights=ws) - self.assertAlmostEqual(cl.q, g.modularity(cl.membership, weights=ws), - places=7) + self.assertAlmostEqual( + cl.q, g.modularity(cl.membership, weights=ws), places=7 + ) except NotImplementedError: # Well, meh @@ -293,51 +393,71 @@ def testOptimalModularity(self): def testSpinglass(self): g = Graph.Full(5) + Graph.Full(5) + Graph.Full(5) - g += [(0,5), (5,10), (10, 0)] + g += [(0, 5), (5, 10), (10, 0)] # Spinglass community detection is a bit unstable, so run it three times ok = False for i in range(3): cl = g.community_spinglass() - if self.reindexMembership(cl) == [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2]: + if self.reindexMembership(cl) == [ + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + ]: ok = True break self.assertTrue(ok) def testWalktrap(self): g = Graph.Full(5) + Graph.Full(5) + Graph.Full(5) - g += [(0,5), (5,10), (10, 0)] + g += [(0, 5), (5, 10), (10, 0)] cl = g.community_walktrap().as_clustering() - self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]) cl = g.community_walktrap(steps=3).as_clustering() - self.assertMembershipsEqual(cl, [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2]) + self.assertMembershipsEqual(cl, [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]) def testLeiden(self): # Example from paper (Fig. C.1) high_weight = 3.0 - low_weight = 3.0/2.0 - edges = [(0, 1, high_weight), - (2, 3, high_weight), - (4, 2, high_weight), - (3, 4, high_weight), - (5, 6, high_weight), - (7, 5, high_weight), - (6, 7, high_weight), - (0, 2, low_weight), - (0, 3, low_weight), - (0, 4, low_weight), - (1, 5, low_weight), - (1, 6, low_weight), - (1, 7, low_weight)] + low_weight = 3.0 / 2.0 + edges = [ + (0, 1, high_weight), + (2, 3, high_weight), + (4, 2, high_weight), + (3, 4, high_weight), + (5, 6, high_weight), + (7, 5, high_weight), + (6, 7, high_weight), + (0, 2, low_weight), + (0, 3, low_weight), + (0, 4, low_weight), + (1, 5, low_weight), + (1, 6, low_weight), + (1, 7, low_weight), + ] G = Graph.TupleList(edges, weights=True) import random + random.seed(0) set_random_number_generator(random) # We don't find the optimal partition if we are greedy - cl = G.community_leiden("CPM", resolution_parameter=1, weights='weight', - beta=0, n_iterations=-1) + cl = G.community_leiden( + "CPM", resolution_parameter=1, weights="weight", beta=0, n_iterations=-1 + ) self.assertMembershipsEqual(cl, [0, 0, 1, 1, 1, 2, 2, 2]) random.seed(0) @@ -346,20 +466,27 @@ def testLeiden(self): # (The randomness is only present in the refinement, which is why we # start from all nodes in the same community: this should then be # refined). - cl = G.community_leiden("CPM", resolution_parameter=1, weights='weight', - beta=5, n_iterations=-1, - initial_membership=[0]*G.vcount()) + cl = G.community_leiden( + "CPM", + resolution_parameter=1, + weights="weight", + beta=5, + n_iterations=-1, + initial_membership=[0] * G.vcount(), + ) self.assertMembershipsEqual(cl, [0, 1, 0, 0, 0, 1, 1, 1]) + class CohesiveBlocksTests(unittest.TestCase): def genericTests(self, cbs): self.assertTrue(isinstance(cbs, CohesiveBlocks)) - self.assertTrue(all(cbs.cohesion(i) == c - for i, c in enumerate(cbs.cohesions()))) - self.assertTrue(all(cbs.parent(i) == c - for i, c in enumerate(cbs.parents()))) - self.assertTrue(all(cbs.max_cohesion(i) == c - for i, c in enumerate(cbs.max_cohesions()))) + self.assertTrue( + all(cbs.cohesion(i) == c for i, c in enumerate(cbs.cohesions())) + ) + self.assertTrue(all(cbs.parent(i) == c for i, c in enumerate(cbs.parents()))) + self.assertTrue( + all(cbs.max_cohesion(i) == c for i, c in enumerate(cbs.max_cohesions())) + ) def testCohesiveBlocks1(self): # Taken from the igraph R manual @@ -369,33 +496,52 @@ def testCohesiveBlocks1(self): cbs = g.cohesive_blocks() self.genericTests(cbs) - self.assertEqual(sorted(list(cbs)), - [list(range(0, 5)), list(range(18)), [0, 1, 2, 3, 4, 6, 7, 8, 9, 10], - list(range(6, 10)), list(range(12, 16)), list(range(12, 17))]) + self.assertEqual( + sorted(list(cbs)), + [ + list(range(0, 5)), + list(range(18)), + [0, 1, 2, 3, 4, 6, 7, 8, 9, 10], + list(range(6, 10)), + list(range(12, 16)), + list(range(12, 17)), + ], + ) self.assertEqual(cbs.cohesions(), [1, 2, 2, 4, 3, 3]) - self.assertEqual(cbs.max_cohesions(), [4, 4, 4, 4, 4, - 1, 3, 3, 3, 3, 2, 1, 3, 3, 3, 3, 2, 1]) + self.assertEqual( + cbs.max_cohesions(), [4, 4, 4, 4, 4, 1, 3, 3, 3, 3, 2, 1, 3, 3, 3, 3, 2, 1] + ) self.assertEqual(cbs.parents(), [None, 0, 0, 1, 2, 1]) def testCohesiveBlocks2(self): # Taken from the Moody-White paper - g = Graph.Formula("1-2:3:4:5:6, 2-3:4:5:7, 3-4:6:7, 4-5:6:7, " - "5-6:7:21, 6-7, 7-8:11:14:19, 8-9:11:14, 9-10, " - "10-12:13, 11-12:14, 12-16, 13-16, 14-15, 15-16, " - "17-18:19:20, 18-20:21, 19-20:22:23, 20-21, " - "21-22:23, 22-23") + g = Graph.Formula( + "1-2:3:4:5:6, 2-3:4:5:7, 3-4:6:7, 4-5:6:7, " + "5-6:7:21, 6-7, 7-8:11:14:19, 8-9:11:14, 9-10, " + "10-12:13, 11-12:14, 12-16, 13-16, 14-15, 15-16, " + "17-18:19:20, 18-20:21, 19-20:22:23, 20-21, " + "21-22:23, 22-23" + ) cbs = g.cohesive_blocks() self.genericTests(cbs) - expected_blocks = [list(range(7)), list(range(23)), list(range(7))+list(range(16, 23)), - list(range(6, 16)), [6, 7, 10, 13]] - observed_blocks = sorted(sorted(int(x)-1 for x in g.vs[bl]["name"]) for bl in cbs) + expected_blocks = [ + list(range(7)), + list(range(23)), + list(range(7)) + list(range(16, 23)), + list(range(6, 16)), + [6, 7, 10, 13], + ] + observed_blocks = sorted( + sorted(int(x) - 1 for x in g.vs[bl]["name"]) for bl in cbs + ) self.assertEqual(expected_blocks, observed_blocks) self.assertTrue(cbs.cohesions() == [1, 2, 2, 5, 3]) self.assertTrue(cbs.parents() == [None, 0, 0, 1, 2]) - self.assertTrue(sorted(cbs.hierarchy().get_edgelist()) == - [(0, 1), (0, 2), (1, 3), (2, 4)]) + self.assertTrue( + sorted(cbs.hierarchy().get_edgelist()) == [(0, 1), (0, 2), (1, 3), (2, 4)] + ) def testCohesiveBlockingErrors(self): g = Graph.GRG(100, 0.2) @@ -409,14 +555,17 @@ def setUp(self): ([0, 0, 0, 1, 1, 1], [1, 1, 1, 0, 0, 0]), ([0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 2, 2]), ([0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5]), - ([0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2], - [2, 0, 1, 0, 2, 0, 2, 0, 1, 0, 3, 1]) + ( + [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2], + [2, 0, 1, 0, 2, 0, 2, 0, 1, 0, 3, 1], + ), ] def _testMethod(self, method, expected): for clusters, result in zip(self.clusterings, expected): - self.assertAlmostEqual(compare_communities(method=method, *clusters), - result, places=3) + self.assertAlmostEqual( + compare_communities(method=method, *clusters), result, places=3 + ) def testCompareVI(self): expected = [0, 0.8675, math.log(6)] @@ -435,7 +584,7 @@ def testCompareSplitJoin(self): self.assertEqual(split_join_distance(l1, l2), (6, 5)) def testCompareRand(self): - expected = [1, 2/3., 0, 0.590909] + expected = [1, 2 / 3.0, 0, 0.590909] self._testMethod("rand", expected) def testCompareAdjustedRand(self): @@ -444,9 +593,11 @@ def testCompareAdjustedRand(self): def testRemoveNone(self): l1 = Clustering([1, 1, 1, None, None, 2, 2, 2, 2]) - l2 = Clustering([1, 1, 2, 2, None, 2, 3, 3, None]) - self.assertAlmostEqual(compare_communities(l1, l2, "nmi", remove_none=True), \ - 0.5158, places=3) + l2 = Clustering([1, 1, 2, 2, None, 2, 3, 3, None]) + self.assertAlmostEqual( + compare_communities(l1, l2, "nmi", remove_none=True), 0.5158, places=3 + ) + def suite(): decomposition_suite = unittest.makeSuite(DecompositionTests) @@ -456,14 +607,23 @@ def suite(): community_suite = unittest.makeSuite(CommunityTests) cohesive_blocks_suite = unittest.makeSuite(CohesiveBlocksTests) comparison_suite = unittest.makeSuite(ComparisonTests) - return unittest.TestSuite([decomposition_suite, clustering_suite, \ - vertex_clustering_suite, cover_suite, community_suite, \ - cohesive_blocks_suite, comparison_suite]) + return unittest.TestSuite( + [ + decomposition_suite, + clustering_suite, + vertex_clustering_suite, + cover_suite, + community_suite, + cohesive_blocks_suite, + comparison_suite, + ] + ) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index d5235882d..6ec581d70 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -52,7 +52,7 @@ def testRepr(self): output = repr(self.g.es[0]) self.assertEqual(output, "igraph.Edge(%r, 0, {})" % self.g) - self.g.es["weight"] = range(10, 0, -1) + self.g.es["weight"] = list(range(10, 0, -1)) output = repr(self.g.es[3]) self.assertEqual(output, "igraph.Edge(%r, 3, {'weight': 7})" % self.g) @@ -128,7 +128,7 @@ def assert_edges_unique_in(self, es): def setUp(self): self.g = Graph.Full(10) - self.g.es["test"] = range(45) + self.g.es["test"] = list(range(45)) def testCreation(self): self.assertTrue(len(EdgeSeq(self.g)) == 45) @@ -176,7 +176,7 @@ def testPartialAttributeAssignment(self): expected = [[0, i][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test"] == expected) - only_even["test2"] = range(23) + only_even["test2"] = list(range(23)) expected = [[i // 2, None][i % 2] for i in range(self.g.ecount())] self.assertTrue(self.g.es["test2"] == expected) @@ -255,7 +255,7 @@ def testIntegerFilteringSelect(self): self.assertTrue(subset["test"] == [2, 3, 4, 2]) def testIterableFilteringSelect(self): - subset = self.g.es.select(range(5, 8)) + subset = self.g.es.select(list(range(5, 8))) self.assertTrue(len(subset) == 3) self.assertTrue(subset["test"] == [5, 6, 7]) diff --git a/tests/test_flow.py b/tests/test_flow.py index b420c8995..e2319a4b2 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -4,6 +4,7 @@ from itertools import combinations from random import randint + class MaxFlowTests(unittest.TestCase): def setUp(self): self.g = Graph(4, [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)]) @@ -11,8 +12,7 @@ def setUp(self): self.g.es["capacity"] = self.capacities def testCapacities(self): - self.assertTrue(self.capacities == \ - self.g.es.get_attribute_values("capacity")) + self.assertTrue(self.capacities == self.g.es.get_attribute_values("capacity")) def testEdgeConnectivity(self): self.assertTrue(self.g.edge_connectivity(0, 3) == 2) @@ -48,8 +48,10 @@ def testMaxFlow(self): self.assertEqual(flow.value, 4) self.assertEqual(flow.cut, [3, 4]) self.assertEqual([e.index for e in flow.es], [3, 4]) - self.assertTrue(set(flow.partition[0]).union(flow.partition[1]) == \ - set(range(self.g.vcount()))) + self.assertTrue( + set(flow.partition[0]).union(flow.partition[1]) + == set(range(self.g.vcount())) + ) self.assertRaises(KeyError, self.g.maxflow, 0, 3, "unknown") @@ -61,9 +63,9 @@ def constructSimpleGraph(self, directed=False): return g def constructLadderGraph(self, directed=False): - el = list(zip(range(0, 5), range(1, 6))) - el += list(zip(range(6, 11), range(7, 12))) - el += list(zip(range(0, 6), range(6, 12))) + el = list(zip(list(range(0, 5)), list(range(1, 6)))) + el += list(zip(list(range(6, 11)), list(range(7, 12)))) + el += list(zip(list(range(0, 6)), list(range(6, 12)))) g = Graph(el, directed=directed) return g @@ -82,8 +84,9 @@ def testMinCut(self): mc = g.mincut() self.assertTrue(isinstance(mc, Cut)) self.assertTrue(mc.value == 2) - self.assertTrue(set(mc.partition[0]).union(mc.partition[1]) == \ - set(range(g.vcount()))) + self.assertTrue( + set(mc.partition[0]).union(mc.partition[1]) == set(range(g.vcount())) + ) self.assertTrue(isinstance(str(mc), str)) self.assertTrue(isinstance(repr(mc), str)) self.assertTrue(isinstance(mc.es, EdgeSeq)) @@ -98,8 +101,9 @@ def testMinCutWithSourceAndTarget(self): self.assertTrue(isinstance(mc, Cut)) self.assertTrue(mc.cut == [3, 4]) self.assertTrue(mc.value == 4) - self.assertTrue(set(mc.partition[0]).union(mc.partition[1]) == \ - set(range(g.vcount()))) + self.assertTrue( + set(mc.partition[0]).union(mc.partition[1]) == set(range(g.vcount())) + ) mc = g.mincut(0, 3) self.assertTrue(isinstance(mc, Cut)) self.assertTrue(mc.cut == [3, 4]) @@ -116,8 +120,9 @@ def testStMinCut(self): self.assertTrue(isinstance(mc, Cut)) self.assertTrue(mc.cut == [3, 4]) self.assertTrue(mc.value == 4) - self.assertTrue(set(mc.partition[0]).union(mc.partition[1]) == \ - set(range(g.vcount()))) + self.assertTrue( + set(mc.partition[0]).union(mc.partition[1]) == set(range(g.vcount())) + ) mc = g.st_mincut(0, 3) self.assertTrue(isinstance(mc, Cut)) self.assertTrue(mc.cut == [3, 4]) @@ -128,23 +133,29 @@ def testStMinCut(self): self.assertTrue(mc.value == 6) self.assertRaises(KeyError, g.st_mincut, 2, 0, capacity="unknown") - def testAllSTCuts1(self): # Simple graph with four vertices g = self.constructSimpleGraph(directed=True) - partitions = [((0, 1, 1, 1), 2), ((0, 0, 1, 1), 3), - ((0, 1, 0, 1), 2), ((0, 0, 0, 1), 2)] + partitions = [ + ((0, 1, 1, 1), 2), + ((0, 0, 1, 1), 3), + ((0, 1, 0, 1), 2), + ((0, 0, 0, 1), 2), + ] values = dict(partitions) partitions = [partition for partition, _ in partitions] - for cut in g.all_st_cuts(0,3): + for cut in g.all_st_cuts(0, 3): membership = tuple(cut.membership) - self.assertTrue(membership in partitions, - "%r not found among expected partitions" % (membership,)) + self.assertTrue( + membership in partitions, + "%r not found among expected partitions" % (membership,), + ) self.assertEqual(cut.value, values[membership]) self.assertEqual(len(cut.es), values[membership]) partitions.remove(membership) - self.assertTrue(partitions == [], - "expected partitions not seen: %r" % (partitions, )) + self.assertTrue( + partitions == [], "expected partitions not seen: %r" % (partitions,) + ) def testAllSTCuts2(self): # "Ladder graph" @@ -155,11 +166,11 @@ def testAllSTCuts2(self): for cut in cuts: g2 = g.copy() g2.delete_edges(cut.es) - self.assertFalse(g2.is_connected(), - "%r is not a real cut" % (cut.membership,)) + self.assertFalse( + g2.is_connected(), "%r is not a real cut" % (cut.membership,) + ) self.assertFalse(cut.value < 2 or cut.value > 6) - def testAllSTMinCuts2(self): # "Ladder graph" g = self.constructLadderGraph() @@ -171,14 +182,15 @@ def testAllSTMinCuts2(self): self.assertEqual(cut.value, 2) g2 = g.copy() g2.delete_edges(cut.es) - self.assertFalse(g2.is_connected(), - "%r is not a real cut" % (cut.membership,)) + self.assertFalse( + g2.is_connected(), "%r is not a real cut" % (cut.membership,) + ) g.es["capacity"] = [2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1] cuts = g.all_st_mincuts(0, 11, "capacity") self.assertEqual(len(cuts), 2) - self.assertEqual(cuts[0].membership, [0,0,1,1,1,1,0,0,1,1,1,1]) - self.assertEqual(cuts[1].membership, [0,0,0,0,1,1,0,0,0,0,1,1]) + self.assertEqual(cuts[0].membership, [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1]) + self.assertEqual(cuts[1].membership, [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1]) self.assertEqual(cuts[0].value, 2) self.assertEqual(cuts[1].value, 2) @@ -191,16 +203,22 @@ def testEmpty(self): self.assertEqual(0, t.ecount()) def testSimpleExample(self): - g = Graph(6, [(0,1),(0,2),(1,2),(1,3),(1,4),(2,4),(3,4),(3,5),(4,5)], \ - directed=False) - g.es["capacity"] = [1,7,1,3,2,4,1,6,2] + g = Graph( + 6, + [(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (2, 4), (3, 4), (3, 5), (4, 5)], + directed=False, + ) + g.es["capacity"] = [1, 7, 1, 3, 2, 4, 1, 6, 2] t = g.gomory_hu_tree("capacity") self.validate_gomory_hu_tree(g, t) def testDirected(self): - g = Graph(6, [(0,1),(0,2),(1,2),(1,3),(1,4),(2,4),(3,4),(3,5),(4,5)], \ - directed=True) - g.es["capacity"] = [1,7,1,3,2,4,1,6,2] + g = Graph( + 6, + [(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (2, 4), (3, 4), (3, 5), (4, 5)], + directed=True, + ) + g.es["capacity"] = [1, 7, 1, 3, 2, 4, 1, 6, 2] self.assertRaises(InternalError, g.gomory_hu_tree, "capacity") def testRandomGRG(self): @@ -213,7 +231,7 @@ def validate_gomory_hu_tree(self, g, t): n = g.vcount() self.assertEqual(n, t.vcount()) - self.assertEqual(n-1, t.ecount()) + self.assertEqual(n - 1, t.ecount()) self.assertFalse(t.is_directed()) if "capacity" in g.edge_attributes(): @@ -221,7 +239,7 @@ def validate_gomory_hu_tree(self, g, t): else: capacities = None - for i, j in combinations(range(n), 2): + for i, j in combinations(list(range(n)), 2): path = t.get_shortest_paths(i, j, output="epath") if path: path = path[0] @@ -229,16 +247,18 @@ def validate_gomory_hu_tree(self, g, t): observed_flow = g.maxflow_value(i, j, capacities) self.assertEqual(observed_flow, expected_flow) + def suite(): flow_suite = unittest.makeSuite(MaxFlowTests) cut_suite = unittest.makeSuite(CutTests) gomory_hu_suite = unittest.makeSuite(GomoryHuTests) return unittest.TestSuite([flow_suite, cut_suite, gomory_hu_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_foreign.py b/tests/test_foreign.py index ff30ec2af..8f2ace5d0 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - import io import unittest import warnings @@ -11,7 +9,8 @@ class ForeignTests(unittest.TestCase): def testDIMACS(self): - with temporary_file(u"""\ + with temporary_file( + """\ c c This is a simple example file to demonstrate the c DIMACS input file format for minimum-cost flow problems. @@ -29,17 +28,18 @@ def testDIMACS(self): a 2 3 2 a 2 4 3 a 3 4 5 - """) as tmpfname: + """ + ) as tmpfname: graph = Graph.Read_DIMACS(tmpfname, False) self.assertTrue(isinstance(graph, Graph)) self.assertTrue(graph.vcount() == 4 and graph.ecount() == 5) self.assertTrue(graph["source"] == 0 and graph["target"] == 3) - self.assertTrue(graph.es["capacity"] == [4,2,2,3,5]) + self.assertTrue(graph.es["capacity"] == [4, 2, 2, 3, 5]) graph.write_dimacs(tmpfname) - def testDL(self): - with temporary_file(u"""\ + with temporary_file( + """\ dl n=5 format = fullmatrix labels embedded @@ -50,16 +50,32 @@ def testDL(self): Lin 1 0 0 1 0 Pat 1 0 1 0 1 russ 0 1 0 1 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 12) self.assertTrue(g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ - (3,2),(3,4),(4,1),(4,3)]) + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 3), + (1, 0), + (1, 4), + (2, 0), + (2, 3), + (3, 0), + (3, 2), + (3, 4), + (4, 1), + (4, 3), + ] + ) - with temporary_file(u"""\ + with temporary_file( + """\ dl n=5 format = fullmatrix labels: @@ -72,16 +88,32 @@ def testDL(self): 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 12) self.assertTrue(g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,0),(1,4),(2,0),(2,3),(3,0),\ - (3,2),(3,4),(4,1),(4,3)]) + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 3), + (1, 0), + (1, 4), + (2, 0), + (2, 3), + (3, 0), + (3, 2), + (3, 4), + (4, 1), + (4, 3), + ] + ) - with temporary_file(u"""\ + with temporary_file( + """\ DL n=5 format = edgelist1 labels: @@ -93,60 +125,70 @@ def testDL(self): sally jim 4 billy george 5 jane jim 6 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_DL(tmpfname, False) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 5 and g.ecount() == 5) self.assertTrue(not g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(0,3),(1,2),(2,4)]) + self.assertTrue( + sorted(g.get_edgelist()) == [(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)] + ) def _testNCOLOrLGL(self, func, fname, can_be_reopened=True): - g = func(fname, names=False, weights=False, \ - directed=False) + g = func(fname, names=False, weights=False, directed=False) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 4 and g.ecount() == 5) self.assertTrue(not g.is_directed()) - self.assertTrue(sorted(g.get_edgelist()) == \ - [(0,1),(0,2),(1,1),(1,3),(2,3)]) - self.assertTrue("name" not in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + sorted(g.get_edgelist()) == [(0, 1), (0, 2), (1, 1), (1, 3), (2, 3)] + ) + self.assertTrue( + "name" not in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) if not can_be_reopened: return - g = func(fname, names=False, \ - directed=False) - self.assertTrue("name" not in g.vertex_attributes() and \ - "weight" in g.edge_attributes()) + g = func(fname, names=False, directed=False) + self.assertTrue( + "name" not in g.vertex_attributes() and "weight" in g.edge_attributes() + ) self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) g = func(fname, directed=False) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" in g.edge_attributes() + ) self.assertTrue(g.vs["name"] == ["eggs", "spam", "ham", "bacon"]) self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) def testNCOL(self): - with temporary_file(u"""\ + with temporary_file( + """\ eggs spam 1 ham eggs 2 ham bacon bacon spam 3 - spam spam""") as tmpfname: + spam spam""" + ) as tmpfname: self._testNCOLOrLGL(func=Graph.Read_Ncol, fname=tmpfname) - with temporary_file(u"""\ + with temporary_file( + """\ eggs spam ham eggs ham bacon bacon spam - spam spam""") as tmpfname: + spam spam""" + ) as tmpfname: g = Graph.Read_Ncol(tmpfname) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) def testLGL(self): - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam 1 # ham @@ -155,10 +197,12 @@ def testLGL(self): # bacon spam 3 # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=tmpfname) - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam # ham @@ -167,23 +211,28 @@ def testLGL(self): # bacon spam # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: with warnings.catch_warnings(): warnings.simplefilter("ignore") g = Graph.Read_Lgl(tmpfname) - self.assertTrue("name" in g.vertex_attributes() and \ - "weight" not in g.edge_attributes()) + self.assertTrue( + "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() + ) # This is not an LGL file; we are testing error handling here - with temporary_file(u"""\ + with temporary_file( + """\ 1 2 1 3 - """) as tmpfname: + """ + ) as tmpfname: with self.assertRaises(InternalError): Graph.Read_Lgl(tmpfname) def testLGLWithIOModule(self): - with temporary_file(u"""\ + with temporary_file( + """\ # eggs spam 1 # ham @@ -192,13 +241,16 @@ def testLGLWithIOModule(self): # bacon spam 3 # spam - spam""") as tmpfname: + spam""" + ) as tmpfname: with io.open(tmpfname, "r") as fp: - self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=fp, - can_be_reopened=False) + self._testNCOLOrLGL( + func=Graph.Read_Lgl, fname=fp, can_be_reopened=False + ) def testAdjacency(self): - with temporary_file(u"""\ + with temporary_file( + """\ # Test comment line 0 1 1 0 0 0 1 0 1 0 0 0 @@ -206,22 +258,73 @@ def testAdjacency(self): 0 0 0 0 2 2 0 0 0 2 0 2 0 0 0 2 2 0 - """) as tmpfname: + """ + ) as tmpfname: g = Graph.Read_Adjacency(tmpfname) self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 6 and g.ecount() == 18 and - g.is_directed() and "weight" not in g.edge_attributes()) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 18 + and g.is_directed() + and "weight" not in g.edge_attributes() + ) g = Graph.Read_Adjacency(tmpfname, attribute="weight") self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 6 and g.ecount() == 12 and - g.is_directed() and g.es["weight"] == [1,1,1,1,1,1,2,2,2,2,2,2]) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 12 + and g.is_directed() + and g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] + ) g.write_adjacency(tmpfname) def testPickle(self): - pickle = [128, 2, 99, 105, 103, 114, 97, 112, 104, 10, 71, 114, 97, 112, - 104, 10, 113, 1, 40, 75, 3, 93, 113, 2, 75, 1, 75, 2, 134, 113, 3, 97, - 137, 125, 125, 125, 116, 82, 113, 4, 125, 98, 46] + pickle = [ + 128, + 2, + 99, + 105, + 103, + 114, + 97, + 112, + 104, + 10, + 71, + 114, + 97, + 112, + 104, + 10, + 113, + 1, + 40, + 75, + 3, + 93, + 113, + 2, + 75, + 1, + 75, + 2, + 134, + 113, + 3, + 97, + 137, + 125, + 125, + 125, + 116, + 82, + 113, + 4, + 125, + 98, + 46, + ] if sys.version_info > (3, 0): pickle = bytes(pickle) else: @@ -229,8 +332,7 @@ def testPickle(self): with temporary_file(pickle, "wb", binary=True) as tmpfname: g = Graph.Read_Pickle(pickle) self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and - not g.is_directed()) + self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) @@ -238,10 +340,11 @@ def suite(): foreign_suite = unittest.makeSuite(ForeignTests) return unittest.TestSuite([foreign_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_games.py b/tests/test_games.py index 07bc62eb2..0af5b9aa2 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -1,6 +1,7 @@ import unittest from igraph import * + class GameTests(unittest.TestCase): def testGRG(self): g = Graph.GRG(50, 0.2) @@ -9,44 +10,44 @@ def testGRG(self): self.assertTrue(isinstance(g, Graph)) self.assertTrue("x" in g.vertex_attributes()) self.assertTrue("y" in g.vertex_attributes()) - self.assertTrue(isinstance(Layout(zip(g.vs["x"], g.vs["y"])), Layout)) + self.assertTrue(isinstance(Layout(list(zip(g.vs["x"], g.vs["y"]))), Layout)) def testForestFire(self): - g=Graph.Forest_Fire(100, 0.1) - self.assertTrue(isinstance(g, Graph) and g.is_directed() == False) - g=Graph.Forest_Fire(100, 0.1, directed=True) - self.assertTrue(isinstance(g, Graph) and g.is_directed() == True) + g = Graph.Forest_Fire(100, 0.1) + self.assertTrue(isinstance(g, Graph) and g.is_directed() is False) + g = Graph.Forest_Fire(100, 0.1, directed=True) + self.assertTrue(isinstance(g, Graph) and g.is_directed() is True) def testRecentDegree(self): - g=Graph.Recent_Degree(100, 5, 10) + g = Graph.Recent_Degree(100, 5, 10) self.assertTrue(isinstance(g, Graph)) def testPreference(self): - g=Graph.Preference(100, [1, 1], [[1, 0], [0, 1]]) + g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]]) self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) - g=Graph.Preference(100, [1, 1], [[1, 0], [0, 1]], attribute="type") - l=g.vs.get_attribute_values("type") + g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]], attribute="type") + l = g.vs.get_attribute_values("type") self.assertTrue(min(l) == 0 and max(l) == 1) def testAsymmetricPreference(self): - g=Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[0, 1], [1, 0]]) + g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[0, 1], [1, 0]]) self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) - g=Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]],\ - attribute="type") - l=g.vs.get_attribute_values("type") - l1=[i[0] for i in l] - l2=[i[1] for i in l] - self.assertTrue(min(l1) == 0 and max(l1) == 1 and - min(l2) == 0 and max(l2) == 1) + g = Graph.Asymmetric_Preference( + 100, [[0, 1], [1, 0]], [[1, 0], [0, 1]], attribute="type" + ) + l = g.vs.get_attribute_values("type") + l1 = [i[0] for i in l] + l2 = [i[1] for i in l] + self.assertTrue(min(l1) == 0 and max(l1) == 1 and min(l2) == 0 and max(l2) == 1) - g=Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]]) + g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]]) self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 1) def testWattsStrogatz(self): - g=Graph.Watts_Strogatz(1, 20, 1, 0.2) - self.assertTrue(isinstance(g, Graph) and g.vcount()==20 and g.ecount()==20) + g = Graph.Watts_Strogatz(1, 20, 1, 0.2) + self.assertTrue(isinstance(g, Graph) and g.vcount() == 20 and g.ecount() == 20) def testRandomBipartiteNP(self): # Test np mode, undirected @@ -54,14 +55,14 @@ def testRandomBipartiteNP(self): self.assertTrue(g.is_simple()) self.assertTrue(g.is_bipartite()) self.assertFalse(g.is_directed()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) # Test np mode, directed, "out" g = Graph.Random_Bipartite(10, 20, p=0.25, directed=True, neimode="out") self.assertTrue(g.is_simple()) self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) self.assertTrue(all(g.vs[e.tuple]["type"] == [False, True] for e in g.es)) # Test np mode, directed, "in" @@ -69,7 +70,7 @@ def testRandomBipartiteNP(self): self.assertTrue(g.is_simple()) self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) self.assertTrue(all(g.vs[e.tuple]["type"] == [True, False] for e in g.es)) # Test np mode, directed, "all" @@ -77,7 +78,7 @@ def testRandomBipartiteNP(self): self.assertTrue(g.is_simple()) self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) def testRandomBipartiteNM(self): # Test np mode, undirected @@ -86,7 +87,7 @@ def testRandomBipartiteNM(self): self.assertTrue(g.is_bipartite()) self.assertFalse(g.is_directed()) self.assertEqual(50, g.ecount()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) # Test np mode, directed, "out" g = Graph.Random_Bipartite(10, 20, m=50, directed=True, neimode="out") @@ -94,7 +95,7 @@ def testRandomBipartiteNM(self): self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) self.assertEqual(50, g.ecount()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) self.assertTrue(all(g.vs[e.tuple]["type"] == [False, True] for e in g.es)) # Test np mode, directed, "in" @@ -103,7 +104,7 @@ def testRandomBipartiteNM(self): self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) self.assertEqual(50, g.ecount()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) self.assertTrue(all(g.vs[e.tuple]["type"] == [True, False] for e in g.es)) # Test np mode, directed, "all" @@ -112,12 +113,12 @@ def testRandomBipartiteNM(self): self.assertTrue(g.is_bipartite()) self.assertTrue(g.is_directed()) self.assertEqual(50, g.ecount()) - self.assertEqual([False]*10 + [True]*20, g.vs["type"]) + self.assertEqual([False] * 10 + [True] * 20, g.vs["type"]) def testRewire(self): # Undirected graph - g=Graph.GRG(25, 0.4) - degrees=g.degree() + g = Graph.GRG(25, 0.4) + degrees = g.degree() # Rewiring without loops g.rewire(10000) @@ -131,14 +132,14 @@ def testRewire(self): # Rewiring with loops (2) g = Graph.Full(4) - g[1,3] = 0 + g[1, 3] = 0 degrees = g.degree() g.rewire(100, mode="loops") self.assertEqual(degrees, g.degree()) self.assertFalse(any(g.is_multiple())) # Directed graph - g=Graph.GRG(25, 0.4) + g = Graph.GRG(25, 0.4) g.to_directed("mutual") indeg, outdeg = g.indegree(), g.outdegree() g.rewire(10000) @@ -152,14 +153,16 @@ def testRewire(self): self.assertEqual(outdeg, g.outdegree()) self.assertFalse(any(g.is_multiple())) + def suite(): game_suite = unittest.makeSuite(GameTests) return unittest.TestSuite([game_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_generators.py b/tests/test_generators.py index e29e3a079..f2d26c75a 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -11,25 +11,25 @@ class GeneratorTests(unittest.TestCase): def testStar(self): - g=Graph.Star(5, "in") - el=[(1,0),(2,0),(3,0),(4,0)] + g = Graph.Star(5, "in") + el = [(1, 0), (2, 0), (3, 0), (4, 0)] self.assertTrue(g.is_directed()) self.assertTrue(g.get_edgelist() == el) - g=Graph.Star(5, "out", center=2) - el=[(2,0),(2,1),(2,3),(2,4)] + g = Graph.Star(5, "out", center=2) + el = [(2, 0), (2, 1), (2, 3), (2, 4)] self.assertTrue(g.is_directed()) self.assertTrue(g.get_edgelist() == el) - g=Graph.Star(5, "mutual", center=2) - el=[(0,2),(1,2),(2,0),(2,1),(2,3),(2,4),(3,2),(4,2)] + g = Graph.Star(5, "mutual", center=2) + el = [(0, 2), (1, 2), (2, 0), (2, 1), (2, 3), (2, 4), (3, 2), (4, 2)] self.assertTrue(g.is_directed()) self.assertTrue(sorted(g.get_edgelist()) == el) - g=Graph.Star(5, center=3) - el=[(0,3),(1,3),(2,3),(3,4)] + g = Graph.Star(5, center=3) + el = [(0, 3), (1, 3), (2, 3), (3, 4)] self.assertTrue(not g.is_directed()) self.assertTrue(sorted(g.get_edgelist()) == el) def testFamous(self): - g=Graph.Famous("tutte") + g = Graph.Famous("tutte") self.assertTrue(g.vcount() == 46 and g.ecount() == 69) self.assertRaises(InternalError, Graph.Famous, "unknown") @@ -40,43 +40,56 @@ def testFormula(self): ("A", ["A"], []), ("A-B", ["A", "B"], [(0, 1)]), ("A --- B", ["A", "B"], [(0, 1)]), - ("A--B, C--D, E--F, G--H, I, J, K", + ( + "A--B, C--D, E--F, G--H, I, J, K", ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], - [(0,1), (2,3), (4,5), (6,7)] + [(0, 1), (2, 3), (4, 5), (6, 7)], ), - ("A:B:C:D -- A:B:C:D", + ( + "A:B:C:D -- A:B:C:D", ["A", "B", "C", "D"], - [(0,1), (0,2), (0,3), (1,2), (1,3), (2,3)] + [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], ), - ("A -> B -> C", ["A", "B", "C"], [(0,1), (1,2)]), - ("A <- B -> C", ["A", "B", "C"], [(1,0), (1,2)]), - ("A <- B -- C", ["A", "B", "C"], [(1,0)]), - ("A <-> B <---> C <> D", ["A", "B", "C", "D"], - [(0,1), (1,0), (1,2), (2,1), (2,3), (3,2)]), - ("'this is' <- 'a silly' -> 'graph here'", - ["this is", "a silly", "graph here"], [(1,0), (1,2)]), - ("Alice-Bob-Cecil-Alice, Daniel-Cecil-Eugene, Cecil-Gordon", + ("A -> B -> C", ["A", "B", "C"], [(0, 1), (1, 2)]), + ("A <- B -> C", ["A", "B", "C"], [(1, 0), (1, 2)]), + ("A <- B -- C", ["A", "B", "C"], [(1, 0)]), + ( + "A <-> B <---> C <> D", + ["A", "B", "C", "D"], + [(0, 1), (1, 0), (1, 2), (2, 1), (2, 3), (3, 2)], + ), + ( + "'this is' <- 'a silly' -> 'graph here'", + ["this is", "a silly", "graph here"], + [(1, 0), (1, 2)], + ), + ( + "Alice-Bob-Cecil-Alice, Daniel-Cecil-Eugene, Cecil-Gordon", ["Alice", "Bob", "Cecil", "Daniel", "Eugene", "Gordon"], - [(0,1),(1,2),(0,2),(2,3),(2,4),(2,5)] + [(0, 1), (1, 2), (0, 2), (2, 3), (2, 4), (2, 5)], ), - ("Alice-Bob:Cecil:Daniel, Cecil:Daniel-Eugene:Gordon", + ( + "Alice-Bob:Cecil:Daniel, Cecil:Daniel-Eugene:Gordon", ["Alice", "Bob", "Cecil", "Daniel", "Eugene", "Gordon"], - [(0,1),(0,2),(0,3),(2,4),(2,5),(3,4),(3,5)] + [(0, 1), (0, 2), (0, 3), (2, 4), (2, 5), (3, 4), (3, 5)], ), - ("Alice <-> Bob --> Cecil <-- Daniel, Eugene --> Gordon:Helen", + ( + "Alice <-> Bob --> Cecil <-- Daniel, Eugene --> Gordon:Helen", ["Alice", "Bob", "Cecil", "Daniel", "Eugene", "Gordon", "Helen"], - [(0,1),(1,0),(1,2),(3,2),(4,5),(4,6)] + [(0, 1), (1, 0), (1, 2), (3, 2), (4, 5), (4, 6)], ), - ("Alice -- Bob -- Daniel, Cecil:Gordon, Helen", + ( + "Alice -- Bob -- Daniel, Cecil:Gordon, Helen", ["Alice", "Bob", "Daniel", "Cecil", "Gordon", "Helen"], - [(0,1),(1,2)] + [(0, 1), (1, 2)], ), - ('"+" -- "-", "*" -- "/", "%%" -- "%/%"', + ( + '"+" -- "-", "*" -- "/", "%%" -- "%/%"', ["+", "-", "*", "/", "%%", "%/%"], - [(0,1),(2,3),(4,5)] + [(0, 1), (2, 3), (4, 5)], ), - ("A-B-C\nC-D", ["A", "B", "C", "D"], [(0,1),(1,2),(2,3)]), - ("A-B-C\n C-D", ["A", "B", "C", "D"], [(0,1),(1,2),(2,3)]) + ("A-B-C\nC-D", ["A", "B", "C", "D"], [(0, 1), (1, 2), (2, 3)]), + ("A-B-C\n C-D", ["A", "B", "C", "D"], [(0, 1), (1, 2), (2, 3)]), ] for formula, names, edges in tests: g = Graph.Formula(formula) @@ -84,20 +97,22 @@ def testFormula(self): self.assertEqual(g.get_edgelist(), sorted(edges)) def testFull(self): - g=Graph.Full(20, directed=True) - el=g.get_edgelist() + g = Graph.Full(20, directed=True) + el = g.get_edgelist() el.sort() - self.assertTrue(g.get_edgelist() == [(x, y) for x in range(20) for y in range(20) if x!=y]) + self.assertTrue( + g.get_edgelist() == [(x, y) for x in range(20) for y in range(20) if x != y] + ) def testFullCitation(self): - g=Graph.Full_Citation(20) - el=g.get_edgelist() + g = Graph.Full_Citation(20) + el = g.get_edgelist() el.sort() self.assertTrue(not g.is_directed()) - self.assertTrue(el == [(x, y) for x in range(19) for y in range(x+1, 20)]) + self.assertTrue(el == [(x, y) for x in range(19) for y in range(x + 1, 20)]) - g=Graph.Full_Citation(20, True) - el=g.get_edgelist() + g = Graph.Full_Citation(20, True) + el = g.get_edgelist() el.sort() self.assertTrue(g.is_directed()) self.assertTrue(el == [(x, y) for x in range(1, 20) for y in range(x)]) @@ -105,24 +120,24 @@ def testFullCitation(self): self.assertRaises(InternalError, Graph.Full_Citation, -2) def testLCF(self): - g1=Graph.LCF(12, (5, -5), 6) - g2=Graph.Famous("Franklin") + g1 = Graph.LCF(12, (5, -5), 6) + g2 = Graph.Famous("Franklin") self.assertTrue(g1.isomorphic(g2)) self.assertRaises(InternalError, Graph.LCF, 12, (5, -5), -3) def testKautz(self): - g=Graph.Kautz(2, 2) - deg_in=g.degree(mode=IN) - deg_out=g.degree(mode=OUT) + g = Graph.Kautz(2, 2) + deg_in = g.degree(mode=IN) + deg_out = g.degree(mode=OUT) # This is not a proper test, but should spot most errors - self.assertTrue(g.is_directed() and deg_in==[2]*12 and deg_out==[2]*12) + self.assertTrue(g.is_directed() and deg_in == [2] * 12 and deg_out == [2] * 12) def testDeBruijn(self): - g=Graph.De_Bruijn(2, 3) - deg_in=g.degree(mode=IN, loops=True) - deg_out=g.degree(mode=OUT, loops=True) + g = Graph.De_Bruijn(2, 3) + deg_in = g.degree(mode=IN, loops=True) + deg_out = g.degree(mode=OUT, loops=True) # This is not a proper test, but should spot most errors - self.assertTrue(g.is_directed() and deg_in==[2]*8 and deg_out==[2]*8) + self.assertTrue(g.is_directed() and deg_in == [2] * 8 and deg_out == [2] * 8) def testSBM(self): pref_matrix = [[0.5, 0, 0], [0, 0, 0.5], [0, 0.5, 0]] @@ -133,8 +148,8 @@ def testSBM(self): # Simple smoke tests for the expected structure of the graph self.assertTrue(g.is_simple()) self.assertFalse(g.is_directed()) - self.assertEqual([0]*20 + [1]*40, g.clusters().membership) - g2 = g.subgraph(range(20, 60)) + self.assertEqual([0] * 20 + [1] * 40, g.clusters().membership) + g2 = g.subgraph(list(range(20, 60))) self.assertTrue(not any(e.source // 20 == e.target // 20 for e in g2.es)) # Check loops argument @@ -159,65 +174,67 @@ def testWeightedAdjacency(self): g = Graph.Weighted_Adjacency(mat, attr="w0") el = g.get_edgelist() - self.assertTrue(el == [(0,1), (0,2), (1,0), (2,2), (3,1)]) + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 2.5, 1]) g = Graph.Weighted_Adjacency(mat, mode="plus") el = g.get_edgelist() - self.assertTrue(el == [(0,1), (0,2), (1,3), (2,2)]) + self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2)]) self.assertTrue(g.es["weight"] == [3, 2, 1, 2.5]) g = Graph.Weighted_Adjacency(mat, attr="w0", loops=False) el = g.get_edgelist() - self.assertTrue(el == [(0,1), (0,2), (1,0), (3,1)]) + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) @unittest.skipIf((np is None) or (pd is None), "test case depends on NumPy/Pandas") def testDataFrame(self): edges = pd.DataFrame( - [['C', 'A', 0.4], ['A', 'B', 0.1]], - columns=[0, 1, 'weight']) + [["C", "A", 0.4], ["A", "B", 0.1]], columns=[0, 1, "weight"] + ) g = Graph.DataFrame(edges, directed=False) self.assertTrue(g.es["weight"] == [0.4, 0.1]) vertices = pd.DataFrame( - [['A', 'blue'], ['B', 'yellow'], ['C', 'blue']], - columns=[0, 'color']) + [["A", "blue"], ["B", "yellow"], ["C", "blue"]], columns=[0, "color"] + ) g = Graph.DataFrame(edges, directed=True, vertices=vertices) - self.assertTrue(g.vs['name'] == ['A', 'B', 'C']) - self.assertTrue(g.vs["color"] == ['blue', 'yellow', 'blue']) + self.assertTrue(g.vs["name"] == ["A", "B", "C"]) + self.assertTrue(g.vs["color"] == ["blue", "yellow", "blue"]) self.assertTrue(g.es["weight"] == [0.4, 0.1]) # Issue #347 - edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) - vertices = pd.DataFrame({ - 'node': [1, 2, 3, 4, 5, 6], - 'label': ['1', '2', '3', '4', '5', '6']})[['node', 'label']] + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame( + {"node": [1, 2, 3, 4, 5, 6], "label": ["1", "2", "3", "4", "5", "6"]} + )[["node", "label"]] g = Graph.DataFrame( edges, directed=True, vertices=vertices, - ) - self.assertTrue(g.vs['name'] == [1, 2, 3, 4, 5, 6]) - self.assertTrue(g.vs['label'] == ['1', '2', '3', '4', '5', '6']) + ) + self.assertTrue(g.vs["name"] == [1, 2, 3, 4, 5, 6]) + self.assertTrue(g.vs["label"] == ["1", "2", "3", "4", "5", "6"]) # Vertex ids - edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) g = Graph.DataFrame(edges) self.assertTrue(g.vcount() == 6) - edges = pd.DataFrame({'source': [1, 2, 3], 'target': [4, 5, 6]}) + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) g = Graph.DataFrame(edges, use_vids=True) self.assertTrue(g.vcount() == 7) + def suite(): generator_suite = unittest.makeSuite(GeneratorTests) return unittest.TestSuite([generator_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_homepage.py b/tests/test_homepage.py index a0e8dad1d..3dbb57129 100644 --- a/tests/test_homepage.py +++ b/tests/test_homepage.py @@ -2,6 +2,7 @@ from igraph import * + class HomepageExampleTests(unittest.TestCase): """Smoke tests for the Python examples found on the homepage to ensure that they do not break.""" @@ -11,7 +12,7 @@ def testErdosRenyiComponents(self): colors = ["lightgray", "cyan", "magenta", "yellow", "blue", "green", "red"] components = g.components() for component in components: - color = colors[min(6, len(components)-1)] + color = colors[min(6, len(components) - 1)] g.vs[component]["color"] = color # No plotting here, but we calculate the FR layout @@ -24,27 +25,27 @@ def testKautz(self): def testMSTofGRG(self): def distance(p1, p2): - return ((p1[0]-p2[0]) ** 2 + (p1[1]-p2[1]) ** 2) ** 0.5 + return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5 g = Graph.GRG(100, 0.2) - layout = Layout(zip(g.vs["x"], g.vs["y"])) + layout = Layout(list(zip(g.vs["x"], g.vs["y"]))) - weights = [distance(layout[edge.source], layout[edge.target]) \ - for edge in g.es] + weights = [distance(layout[edge.source], layout[edge.target]) for edge in g.es] max_weight = max(weights) - g.es["width"] = [6 - 5*weight / max_weight for weight in weights] + g.es["width"] = [6 - 5 * weight / max_weight for weight in weights] mst = g.spanning_tree(weights) # Plotting omitted + def suite(): homepage_example_suite = unittest.makeSuite(HomepageExampleTests) return unittest.TestSuite([homepage_example_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - - diff --git a/tests/test_indexing.py b/tests/test_indexing.py index 301afbc56..33fba0b7f 100644 --- a/tests/test_indexing.py +++ b/tests/test_indexing.py @@ -2,6 +2,7 @@ import unittest from igraph import * + class GraphAdjacencyMatrixLikeIndexingTests(unittest.TestCase): def testSingleEdgeRetrieval(self): g = Graph.Famous("krackhardt_kite") @@ -18,7 +19,7 @@ def testSingleEdgeRetrieval(self): def testSingleEdgeRetrievalWeights(self): g = Graph.Famous("krackhardt_kite") - g.es["weight"] = range(g.ecount()) + g.es["weight"] = list(range(g.ecount())) for idx, (v1, v2) in enumerate(g.get_edgelist()): self.assertEqual(g[v1, v2], idx) self.assertEqual(g[v2, v1], idx) @@ -29,10 +30,10 @@ def testSingleEdgeRetrievalWeights(self): def testSingleEdgeRetrievalAttrName(self): g = Graph.Famous("krackhardt_kite") - g.es["value"] = range(20, g.ecount()+20) + g.es["value"] = list(range(20, g.ecount() + 20)) for idx, (v1, v2) in enumerate(g.get_edgelist()): - self.assertEqual(g[v1, v2, "value"], idx+20) - self.assertEqual(g[v2, v1, "value"], idx+20) + self.assertEqual(g[v1, v2, "value"], idx + 20) + self.assertEqual(g[v2, v1, "value"], idx + 20) for v1 in range(g.vcount()): for v2 in set(range(g.vcount())) - set(g.neighbors(v1)): self.assertEqual(g[v1, v2, "value"], 0) @@ -43,9 +44,11 @@ def suite(): adjacency_suite = unittest.makeSuite(GraphAdjacencyMatrixLikeIndexingTests) return unittest.TestSuite([adjacency_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index b8e6c0256..d5042ec83 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -3,138 +3,206 @@ from itertools import permutations from random import shuffle + def node_compat(g1, g2, v1, v2): """Node compatibility function for isomorphism tests""" return g1.vs[v1]["color"] == g2.vs[v2]["color"] + def edge_compat(g1, g2, e1, e2): """Edge compatibility function for isomorphism tests""" return g1.es[e1]["color"] == g2.es[e2]["color"] + class IsomorphismTests(unittest.TestCase): def testIsomorphic(self): - g1 = Graph(8, [(0, 4), (0, 5), (0, 6), \ - (1, 4), (1, 5), (1, 7), \ - (2, 4), (2, 6), (2, 7), \ - (3, 5), (3, 6), (3, 7)]) - g2 = Graph(8, [(0, 1), (0, 3), (0, 4), \ - (2, 3), (2, 1), (2, 6), \ - (5, 1), (5, 4), (5, 6), \ - (7, 3), (7, 6), (7, 4)]) + g1 = Graph( + 8, + [ + (0, 4), + (0, 5), + (0, 6), + (1, 4), + (1, 5), + (1, 7), + (2, 4), + (2, 6), + (2, 7), + (3, 5), + (3, 6), + (3, 7), + ], + ) + g2 = Graph( + 8, + [ + (0, 1), + (0, 3), + (0, 4), + (2, 3), + (2, 1), + (2, 6), + (5, 1), + (5, 4), + (5, 6), + (7, 3), + (7, 6), + (7, 4), + ], + ) # Test the isomorphism of g1 and g2 self.assertTrue(g1.isomorphic(g2)) - self.assertTrue(g2.isomorphic_vf2(g1, return_mapping_21=True) \ - == (True, None, [0, 2, 5, 7, 1, 3, 4, 6])) - self.assertTrue(g2.isomorphic_bliss(g1, return_mapping_21=True, sh1="fl")\ - == (True, None, [0, 2, 5, 7, 1, 3, 4, 6])) + self.assertTrue( + g2.isomorphic_vf2(g1, return_mapping_21=True) + == (True, None, [0, 2, 5, 7, 1, 3, 4, 6]) + ) + self.assertTrue( + g2.isomorphic_bliss(g1, return_mapping_21=True, sh1="fl") + == (True, None, [0, 2, 5, 7, 1, 3, 4, 6]) + ) self.assertRaises(ValueError, g2.isomorphic_bliss, g1, sh2="nonexistent") # Test the automorphy of g1 self.assertTrue(g1.isomorphic()) - self.assertTrue(g1.isomorphic_vf2(return_mapping_21=True) \ - == (True, None, [0, 1, 2, 3, 4, 5, 6, 7])) + self.assertTrue( + g1.isomorphic_vf2(return_mapping_21=True) + == (True, None, [0, 1, 2, 3, 4, 5, 6, 7]) + ) # Test VF2 with colors - self.assertTrue(g1.isomorphic_vf2(g2, - color1=[0,1,0,1,0,1,0,1], - color2=[0,0,1,1,0,0,1,1])) - g1.vs["color"] = [0,1,0,1,0,1,0,1] - g2.vs["color"] = [0,0,1,1,0,1,1,0] + self.assertTrue( + g1.isomorphic_vf2( + g2, color1=[0, 1, 0, 1, 0, 1, 0, 1], color2=[0, 0, 1, 1, 0, 0, 1, 1] + ) + ) + g1.vs["color"] = [0, 1, 0, 1, 0, 1, 0, 1] + g2.vs["color"] = [0, 0, 1, 1, 0, 1, 1, 0] self.assertTrue(not g1.isomorphic_vf2(g2, "color", "color")) # Test bliss with colors - self.assertTrue(g1.isomorphic_bliss(g2, - color1=[0,0,0,0,0,0,0,0], - color2=[0,0,0,0,0,0,0,0])) - - self.assertTrue(g1.isomorphic_bliss(g2, - color1=[1,0,2,0,0,0,0,0], - color2=[1,0,2,0,0,0,0,0])) - - self.assertTrue(g1.isomorphic_bliss(g2, - color1=[0,1,0,1,0,1,0,1], - color2=[0,0,1,1,0,0,1,1])) + self.assertTrue( + g1.isomorphic_bliss( + g2, color1=[0, 0, 0, 0, 0, 0, 0, 0], color2=[0, 0, 0, 0, 0, 0, 0, 0] + ) + ) + + self.assertTrue( + g1.isomorphic_bliss( + g2, color1=[1, 0, 2, 0, 0, 0, 0, 0], color2=[1, 0, 2, 0, 0, 0, 0, 0] + ) + ) + + self.assertTrue( + g1.isomorphic_bliss( + g2, color1=[0, 1, 0, 1, 0, 1, 0, 1], color2=[0, 0, 1, 1, 0, 0, 1, 1] + ) + ) # Test VF2 with vertex and edge colors - self.assertTrue(g1.isomorphic_vf2(g2, - color1=[0,1,0,1,0,1,0,1], - color2=[0,0,1,1,0,0,1,1])) - g1.es["color"] = range(12) - g2.es["color"] = [0]*6 + [1]*6 + self.assertTrue( + g1.isomorphic_vf2( + g2, color1=[0, 1, 0, 1, 0, 1, 0, 1], color2=[0, 0, 1, 1, 0, 0, 1, 1] + ) + ) + g1.es["color"] = list(range(12)) + g2.es["color"] = [0] * 6 + [1] * 6 self.assertTrue(not g1.isomorphic_vf2(g2, "color", "color", "color", "color")) # Test VF2 with node compatibility function - g2.vs["color"] = [0,0,1,1,0,0,1,1] + g2.vs["color"] = [0, 0, 1, 1, 0, 0, 1, 1] self.assertTrue(g1.isomorphic_vf2(g2, node_compat_fn=node_compat)) - g2.vs["color"] = [0,0,1,1,0,1,1,0] + g2.vs["color"] = [0, 0, 1, 1, 0, 1, 1, 0] self.assertTrue(not g1.isomorphic_vf2(g2, node_compat_fn=node_compat)) # Test VF2 with node edge compatibility function - g2.vs["color"] = [0,0,1,1,0,0,1,1] - g1.es["color"] = range(12) - g2.es["color"] = [0]*6 + [1]*6 - self.assertTrue(not g1.isomorphic_vf2(g2, node_compat_fn=node_compat, - edge_compat_fn=edge_compat)) + g2.vs["color"] = [0, 0, 1, 1, 0, 0, 1, 1] + g1.es["color"] = list(range(12)) + g2.es["color"] = [0] * 6 + [1] * 6 + self.assertTrue( + not g1.isomorphic_vf2( + g2, node_compat_fn=node_compat, edge_compat_fn=edge_compat + ) + ) def testIsomorphicCallback(self): maps = [] + def callback(g1, g2, map1, map2): maps.append(map1) return True # Test VF2 callback - g = Graph(6, [(0,1), (2,3), (4,5), (0,2), (2,4), (1,3), (3,5)]) + g = Graph(6, [(0, 1), (2, 3), (4, 5), (0, 2), (2, 4), (1, 3), (3, 5)]) g.isomorphic_vf2(g, callback=callback) - expected_maps = [[0,1,2,3,4,5], [1,0,3,2,5,4], [4,5,2,3,0,1], [5,4,3,2,1,0]] + expected_maps = [ + [0, 1, 2, 3, 4, 5], + [1, 0, 3, 2, 5, 4], + [4, 5, 2, 3, 0, 1], + [5, 4, 3, 2, 1, 0], + ] self.assertTrue(sorted(maps) == expected_maps) maps[:] = [] g3 = Graph.Full(4) - g3.vs["color"] = [0,1,1,0] + g3.vs["color"] = [0, 1, 1, 0] g3.isomorphic_vf2(callback=callback, color1="color", color2="color") - expected_maps = [[0,1,2,3], [0,2,1,3], [3,1,2,0], [3,2,1,0]] + expected_maps = [[0, 1, 2, 3], [0, 2, 1, 3], [3, 1, 2, 0], [3, 2, 1, 0]] self.assertTrue(sorted(maps) == expected_maps) def testCountIsomorphisms(self): g = Graph.Full(4) self.assertTrue(g.count_automorphisms_vf2() == 24) - g = Graph(6, [(0,1), (2,3), (4,5), (0,2), (2,4), (1,3), (3,5)]) + g = Graph(6, [(0, 1), (2, 3), (4, 5), (0, 2), (2, 4), (1, 3), (3, 5)]) self.assertTrue(g.count_automorphisms_vf2() == 4) # Some more tests with colors g3 = Graph.Full(4) - g3.vs["color"] = [0,1,1,0] + g3.vs["color"] = [0, 1, 1, 0] self.assertTrue(g3.count_isomorphisms_vf2() == 24) self.assertTrue(g3.count_isomorphisms_vf2(color1="color", color2="color") == 4) - self.assertTrue(g3.count_isomorphisms_vf2(color1=[0,1,2,0], color2=(0,1,2,0)) == 2) - self.assertTrue(g3.count_isomorphisms_vf2(edge_color1=[0,1,0,0,0,1], - edge_color2=[0,1,0,0,0,1]) == 2) + self.assertTrue( + g3.count_isomorphisms_vf2(color1=[0, 1, 2, 0], color2=(0, 1, 2, 0)) == 2 + ) + self.assertTrue( + g3.count_isomorphisms_vf2( + edge_color1=[0, 1, 0, 0, 0, 1], edge_color2=[0, 1, 0, 0, 0, 1] + ) + == 2 + ) # Test VF2 with node/edge compatibility function - g3.vs["color"] = [0,1,1,0] + g3.vs["color"] = [0, 1, 1, 0] self.assertTrue(g3.count_isomorphisms_vf2(node_compat_fn=node_compat) == 4) - g3.vs["color"] = [0,1,2,0] + g3.vs["color"] = [0, 1, 2, 0] self.assertTrue(g3.count_isomorphisms_vf2(node_compat_fn=node_compat) == 2) - g3.es["color"] = [0,1,0,0,0,1] + g3.es["color"] = [0, 1, 0, 0, 0, 1] self.assertTrue(g3.count_isomorphisms_vf2(edge_compat_fn=edge_compat) == 2) def testGetIsomorphisms(self): - g = Graph(6, [(0,1), (2,3), (4,5), (0,2), (2,4), (1,3), (3,5)]) + g = Graph(6, [(0, 1), (2, 3), (4, 5), (0, 2), (2, 4), (1, 3), (3, 5)]) maps = g.get_automorphisms_vf2() - expected_maps = [[0,1,2,3,4,5], [1,0,3,2,5,4], [4,5,2,3,0,1], [5,4,3,2,1,0]] + expected_maps = [ + [0, 1, 2, 3, 4, 5], + [1, 0, 3, 2, 5, 4], + [4, 5, 2, 3, 0, 1], + [5, 4, 3, 2, 1, 0], + ] self.assertTrue(maps == expected_maps) g3 = Graph.Full(4) - g3.vs["color"] = [0,1,1,0] - expected_maps = [[0,1,2,3], [0,2,1,3], [3,1,2,0], [3,2,1,0]] - self.assertTrue(sorted(g3.get_automorphisms_vf2(color="color")) == expected_maps) + g3.vs["color"] = [0, 1, 1, 0] + expected_maps = [[0, 1, 2, 3], [0, 2, 1, 3], [3, 1, 2, 0], [3, 2, 1, 0]] + self.assertTrue( + sorted(g3.get_automorphisms_vf2(color="color")) == expected_maps + ) + class SubisomorphismTests(unittest.TestCase): def testSubisomorphicLAD(self): - g = Graph.Lattice([3,3], circular=False) - g2 = Graph([(0,1), (1,2), (1,3)]) - g3 = g + [(0,4), (2,4), (6,4), (8,4), (3,1), (1,5), (5,7), (7,3)] + g = Graph.Lattice([3, 3], circular=False) + g2 = Graph([(0, 1), (1, 2), (1, 3)]) + g3 = g + [(0, 4), (2, 4), (6, 4), (8, 4), (3, 1), (1, 5), (5, 7), (7, 3)] self.assertTrue(g.subisomorphic_lad(g2)) self.assertFalse(g2.subisomorphic_lad(g)) @@ -148,9 +216,19 @@ def testSubisomorphicLAD(self): self.assertTrue(g3.subisomorphic_lad(g2)) # Test with limited vertex matching - domains = [[4], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8]] + domains = [ + [4], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + ] self.assertTrue(g.subisomorphic_lad(g2, domains=domains)) - domains = [[], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8]] + domains = [ + [], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + ] self.assertTrue(not g.subisomorphic_lad(g2, domains=domains)) # Corner cases @@ -159,9 +237,9 @@ def testSubisomorphicLAD(self): self.assertTrue(empty.subisomorphic_lad(empty)) def testGetSubisomorphismsLAD(self): - g = Graph.Lattice([3,3], circular=False) - g2 = Graph([(0,1), (1,2), (2,3), (3,0)]) - g3 = g + [(0,4), (2,4), (6,4), (8,4), (3,1), (1,5), (5,7), (7,3)] + g = Graph.Lattice([3, 3], circular=False) + g2 = Graph([(0, 1), (1, 2), (2, 3), (3, 0)]) + g3 = g + [(0, 4), (2, 4), (6, 4), (8, 4), (3, 1), (1, 5), (5, 7), (7, 3)] all_subiso = "0143 0341 1034 1254 1430 1452 2145 2541 3014 3410 3476 \ 3674 4103 4125 4301 4367 4521 4587 4763 4785 5214 5412 5478 5874 6347 \ @@ -173,18 +251,32 @@ def testGetSubisomorphismsLAD(self): # Test 'induced' induced_subiso = "1375 1573 3751 5731 7513 7315 5137 3157" - induced_subiso = sorted([int(x) for x in item] for item in induced_subiso.split()) + induced_subiso = sorted( + [int(x) for x in item] for item in induced_subiso.split() + ) all_subiso_extra = sorted(all_subiso + induced_subiso) - self.assertEqual(induced_subiso, - sorted(g3.get_subisomorphisms_lad(g2, induced=True))) + self.assertEqual( + induced_subiso, sorted(g3.get_subisomorphisms_lad(g2, induced=True)) + ) self.assertEqual([], g3.get_subisomorphisms_lad(g, induced=True)) # Test with limited vertex matching limited_subiso = [iso for iso in all_subiso if iso[0] == 4] - domains = [[4], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8]] - self.assertEqual(limited_subiso, - sorted(g.get_subisomorphisms_lad(g2, domains=domains))) - domains = [[], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8], [0,1,2,3,5,6,7,8]] + domains = [ + [4], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + ] + self.assertEqual( + limited_subiso, sorted(g.get_subisomorphisms_lad(g2, domains=domains)) + ) + domains = [ + [], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + [0, 1, 2, 3, 5, 6, 7, 8], + ] self.assertEqual([], sorted(g.get_subisomorphisms_lad(g2, domains=domains))) # Corner cases @@ -193,42 +285,50 @@ def testGetSubisomorphismsLAD(self): self.assertEqual([], empty.get_subisomorphisms_lad(empty)) def testSubisomorphicVF2(self): - g = Graph.Lattice([3,3], circular=False) - g2 = Graph([(0,1), (1,2), (1,3)]) + g = Graph.Lattice([3, 3], circular=False) + g2 = Graph([(0, 1), (1, 2), (1, 3)]) self.assertTrue(g.subisomorphic_vf2(g2)) self.assertTrue(not g2.subisomorphic_vf2(g)) # Test with vertex colors - g.vs["color"] = [0,0,0,0,1,0,0,0,0] - g2.vs["color"] = [1,0,0,0] + g.vs["color"] = [0, 0, 0, 0, 1, 0, 0, 0, 0] + g2.vs["color"] = [1, 0, 0, 0] self.assertTrue(g.subisomorphic_vf2(g2, node_compat_fn=node_compat)) - g2.vs["color"] = [2,0,0,0] + g2.vs["color"] = [2, 0, 0, 0] self.assertTrue(not g.subisomorphic_vf2(g2, node_compat_fn=node_compat)) # Test with edge colors - g.es["color"] = [1] + [0]*(g.ecount()-1) - g2.es["color"] = [1] + [0]*(g2.ecount()-1) + g.es["color"] = [1] + [0] * (g.ecount() - 1) + g2.es["color"] = [1] + [0] * (g2.ecount() - 1) self.assertTrue(g.subisomorphic_vf2(g2, edge_compat_fn=edge_compat)) g2.es[0]["color"] = [2] self.assertTrue(not g.subisomorphic_vf2(g2, node_compat_fn=node_compat)) def testCountSubisomorphisms(self): - g = Graph.Lattice([3,3], circular=False) - g2 = Graph.Lattice([2,2], circular=False) - self.assertTrue(g.count_subisomorphisms_vf2(g2) == 4*4*2) + g = Graph.Lattice([3, 3], circular=False) + g2 = Graph.Lattice([2, 2], circular=False) + self.assertTrue(g.count_subisomorphisms_vf2(g2) == 4 * 4 * 2) self.assertTrue(g2.count_subisomorphisms_vf2(g) == 0) # Test with vertex colors - g.vs["color"] = [0,0,0,0,1,0,0,0,0] - g2.vs["color"] = [1,0,0,0] - self.assertTrue(g.count_subisomorphisms_vf2(g2, "color", "color") == 4*2) - self.assertTrue(g.count_subisomorphisms_vf2(g2, node_compat_fn=node_compat) == 4*2) + g.vs["color"] = [0, 0, 0, 0, 1, 0, 0, 0, 0] + g2.vs["color"] = [1, 0, 0, 0] + self.assertTrue(g.count_subisomorphisms_vf2(g2, "color", "color") == 4 * 2) + self.assertTrue( + g.count_subisomorphisms_vf2(g2, node_compat_fn=node_compat) == 4 * 2 + ) # Test with edge colors - g.es["color"] = [1] + [0]*(g.ecount()-1) - g2.es["color"] = [1] + [0]*(g2.ecount()-1) - self.assertTrue(g.count_subisomorphisms_vf2(g2, edge_color1="color", edge_color2="color") == 2) - self.assertTrue(g.count_subisomorphisms_vf2(g2, edge_compat_fn=edge_compat) == 2) + g.es["color"] = [1] + [0] * (g.ecount() - 1) + g2.es["color"] = [1] + [0] * (g2.ecount() - 1) + self.assertTrue( + g.count_subisomorphisms_vf2(g2, edge_color1="color", edge_color2="color") + == 2 + ) + self.assertTrue( + g.count_subisomorphisms_vf2(g2, edge_compat_fn=edge_compat) == 2 + ) + class PermutationTests(unittest.TestCase): def testCanonicalPermutation(self): @@ -246,16 +346,15 @@ def testCanonicalPermutation(self): self.assertTrue(sorted(g3.get_edgelist()) == sorted(g4.get_edgelist())) # Simple case with coloring - cp = g1.canonical_permutation(color = [0, 0, 1, 1]) + cp = g1.canonical_permutation(color=[0, 0, 1, 1]) g3 = g1.permute_vertices(cp) - cp = g2.canonical_permutation(color = [0, 0, 1, 1]) + cp = g2.canonical_permutation(color=[0, 0, 1, 1]) g4 = g2.permute_vertices(cp) self.assertTrue(g3.vcount() == g4.vcount()) self.assertTrue(sorted(g3.get_edgelist()) == sorted(g4.get_edgelist())) - # More complicated one: small GRG, random permutation g = Graph.GRG(10, 0.5) perm = list(range(10)) @@ -268,30 +367,59 @@ def testCanonicalPermutation(self): self.assertTrue(sorted(g3.get_edgelist()) == sorted(g4.get_edgelist())) def testPermuteVertices(self): - g1 = Graph(8, [(0, 4), (0, 5), (0, 6), \ - (1, 4), (1, 5), (1, 7), \ - (2, 4), (2, 6), (2, 7), \ - (3, 5), (3, 6), (3, 7)]) - g2 = Graph(8, [(0, 1), (0, 3), (0, 4), \ - (2, 3), (2, 1), (2, 6), \ - (5, 1), (5, 4), (5, 6), \ - (7, 3), (7, 6), (7, 4)]) + g1 = Graph( + 8, + [ + (0, 4), + (0, 5), + (0, 6), + (1, 4), + (1, 5), + (1, 7), + (2, 4), + (2, 6), + (2, 7), + (3, 5), + (3, 6), + (3, 7), + ], + ) + g2 = Graph( + 8, + [ + (0, 1), + (0, 3), + (0, 4), + (2, 3), + (2, 1), + (2, 6), + (5, 1), + (5, 4), + (5, 6), + (7, 3), + (7, 6), + (7, 4), + ], + ) _, _, mapping = g1.isomorphic_vf2(g2, return_mapping_21=True) g3 = g2.permute_vertices(mapping) self.assertTrue(g3.vcount() == g2.vcount() and g3.ecount() == g2.ecount()) self.assertTrue(set(g3.get_edgelist()) == set(g1.get_edgelist())) + def suite(): isomorphism_suite = unittest.makeSuite(IsomorphismTests) subisomorphism_suite = unittest.makeSuite(SubisomorphismTests) permutation_suite = unittest.makeSuite(PermutationTests) - return unittest.TestSuite([isomorphism_suite, subisomorphism_suite, \ - permutation_suite]) + return unittest.TestSuite( + [isomorphism_suite, subisomorphism_suite, permutation_suite] + ) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_iterators.py b/tests/test_iterators.py index b8777d275..578c1cf6e 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -1,6 +1,7 @@ import unittest from igraph import * + class IteratorTests(unittest.TestCase): def testBFS(self): g = Graph.Tree(10, 2) @@ -16,9 +17,18 @@ def testBFSIter(self): vs = [(v, d, p.index) for v, d, p in vs if p is not None] self.assertEqual( vs, - [(1, 1, 0), (2, 1, 0), (3, 2, 1), - (4, 2, 1), (5, 2, 2), (6, 2, 2), - (7, 3, 3), (8, 3, 3), (9, 3, 4)]) + [ + (1, 1, 0), + (2, 1, 0), + (3, 2, 1), + (4, 2, 1), + (5, 2, 2), + (6, 2, 2), + (7, 3, 3), + (8, 3, 3), + (9, 3, 4), + ], + ) def testDFS(self): g = Graph.Tree(10, 2) @@ -34,18 +44,29 @@ def testDFSIter(self): vs = [(v, d, p.index) for v, d, p in vs if p is not None] self.assertEqual( vs, - [(1, 1, 0), (3, 2, 1), (7, 3, 3), - (8, 3, 3), (4, 2, 1), (9, 3, 4), - (2, 1, 0), (5, 2, 2), (6, 2, 2)]) + [ + (1, 1, 0), + (3, 2, 1), + (7, 3, 3), + (8, 3, 3), + (4, 2, 1), + (9, 3, 4), + (2, 1, 0), + (5, 2, 2), + (6, 2, 2), + ], + ) def suite(): iterator_suite = unittest.makeSuite(IteratorTests) return unittest.TestSuite([iterator_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() diff --git a/tests/test_layouts.py b/tests/test_layouts.py index af4c3181c..d4982622f 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -4,14 +4,14 @@ class LayoutTests(unittest.TestCase): def testConstructor(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0)]) self.assertEqual(layout.dim, 3) - layout = Layout([(0,0,1), (0,1,0), (1,0,0)], 3) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0)], 3) self.assertEqual(layout.dim, 3) - self.assertRaises(ValueError, Layout, [(0,1), (1,0)], 3) + self.assertRaises(ValueError, Layout, [(0, 1), (1, 0)], 3) def testIndexing(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) self.assertEqual(len(layout), 4) self.assertEqual(layout[1], [0, 1, 0]) self.assertEqual(layout[3], [2, 1, 3]) @@ -24,56 +24,47 @@ def testIndexing(self): self.assertEqual(len(layout), 3) def testScaling(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) layout.scale(1.5) - self.assertEqual(layout.coords, [[0., 0., 1.5], \ - [0., 1.5, 0.], \ - [1.5, 0., 0.], \ - [3., 1.5, 4.5]]) + self.assertEqual( + layout.coords, + [[0.0, 0.0, 1.5], [0.0, 1.5, 0.0], [1.5, 0.0, 0.0], [3.0, 1.5, 4.5]], + ) - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) layout.scale(1, 1, 3) - self.assertEqual(layout.coords, [[0, 0, 3], \ - [0, 1, 0], \ - [1, 0, 0], \ - [2, 1, 9]]) + self.assertEqual(layout.coords, [[0, 0, 3], [0, 1, 0], [1, 0, 0], [2, 1, 9]]) - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) layout.scale((2, 2, 1)) - self.assertEqual(layout.coords, [[0, 0, 1], \ - [0, 2, 0], \ - [2, 0, 0], \ - [4, 2, 3]]) + self.assertEqual(layout.coords, [[0, 0, 1], [0, 2, 0], [2, 0, 0], [4, 2, 3]]) self.assertRaises(ValueError, layout.scale, 2, 3) def testTranslation(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) layout2 = layout.copy() - layout.translate(1,3,2) - self.assertEqual(layout.coords, [[1, 3, 3], \ - [1, 4, 2], \ - [2, 3, 2], \ - [3, 4, 5]]) + layout.translate(1, 3, 2) + self.assertEqual(layout.coords, [[1, 3, 3], [1, 4, 2], [2, 3, 2], [3, 4, 5]]) - layout.translate((-1,-3,-2)) + layout.translate((-1, -3, -2)) self.assertEqual(layout.coords, layout2.coords) self.assertRaises(ValueError, layout.translate, v=[3]) def testCentroid(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) centroid = layout.centroid() self.assertEqual(len(centroid), 3) self.assertAlmostEqual(centroid[0], 0.75) self.assertAlmostEqual(centroid[1], 0.5) - self.assertAlmostEqual(centroid[2], 1.) + self.assertAlmostEqual(centroid[2], 1.0) def testBoundaries(self): - layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)]) - self.assertEqual(layout.boundaries(), ([0,0,0],[2,1,3])) - self.assertEqual(layout.boundaries(1), ([-1,-1,-1],[3,2,4])) + layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)]) + self.assertEqual(layout.boundaries(), ([0, 0, 0], [2, 1, 3])) + self.assertEqual(layout.boundaries(1), ([-1, -1, -1], [3, 2, 4])) layout = Layout([]) self.assertRaises(ValueError, layout.boundaries) @@ -81,49 +72,51 @@ def testBoundaries(self): self.assertRaises(ValueError, layout.boundaries) def testBoundingBox(self): - layout = Layout([(0,1), (2,7)]) - self.assertEqual(layout.bounding_box(), BoundingBox(0,1,2,7)) - self.assertEqual(layout.bounding_box(1), BoundingBox(-1,0,3,8)) + layout = Layout([(0, 1), (2, 7)]) + self.assertEqual(layout.bounding_box(), BoundingBox(0, 1, 2, 7)) + self.assertEqual(layout.bounding_box(1), BoundingBox(-1, 0, 3, 8)) layout = Layout([]) - self.assertEqual(layout.bounding_box(), BoundingBox(0,0,0,0)) + self.assertEqual(layout.bounding_box(), BoundingBox(0, 0, 0, 0)) def testCenter(self): - layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)]) + layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)]) layout.center() - self.assertEqual(layout.coords, [[-1,1], [-1,-1], [1,-1], [1,1]]) - layout.center(5,5) - self.assertEqual(layout.coords, [[4,6], [4,4], [6,4], [6,6]]) + self.assertEqual(layout.coords, [[-1, 1], [-1, -1], [1, -1], [1, 1]]) + layout.center(5, 5) + self.assertEqual(layout.coords, [[4, 6], [4, 4], [6, 4], [6, 6]]) self.assertRaises(ValueError, layout.center, 3) self.assertRaises(TypeError, layout.center, p=6) def testFitInto(self): - layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)]) - layout.fit_into(BoundingBox(5,5,8,10), keep_aspect_ratio=False) + layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)]) + layout.fit_into(BoundingBox(5, 5, 8, 10), keep_aspect_ratio=False) self.assertEqual(layout.coords, [[5, 10], [5, 5], [8, 5], [8, 10]]) - layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)]) - layout.fit_into(BoundingBox(5,5,8,10)) + layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)]) + layout.fit_into(BoundingBox(5, 5, 8, 10)) self.assertEqual(layout.coords, [[5, 9], [5, 6], [8, 6], [8, 9]]) - layout = Layout([(-1,-1,-1), (0,0,0), (1,1,1), (2,2,0), (3,3,-1)]) - layout.fit_into((0,0,0,8,8,4)) - self.assertEqual(layout.coords, \ - [[0, 0, 0], [2, 2, 2], [4, 4, 4], [6, 6, 2], [8, 8, 0]] + layout = Layout([(-1, -1, -1), (0, 0, 0), (1, 1, 1), (2, 2, 0), (3, 3, -1)]) + layout.fit_into((0, 0, 0, 8, 8, 4)) + self.assertEqual( + layout.coords, [[0, 0, 0], [2, 2, 2], [4, 4, 4], [6, 6, 2], [8, 8, 0]] ) layout = Layout([]) - layout.fit_into((6,7,8,11)) + layout.fit_into((6, 7, 8, 11)) self.assertEqual(layout.coords, []) def testToPolar(self): layout = Layout([(0, 0), (-1, 1), (0, 1), (1, 1)]) layout.to_radial(min_angle=180, max_angle=0, max_radius=2) - exp = [[0., 0.], [-2., 0.], [0., 2.], [2, 0.]] + exp = [[0.0, 0.0], [-2.0, 0.0], [0.0, 2.0], [2, 0.0]] for idx in range(4): self.assertAlmostEqual(layout.coords[idx][0], exp[idx][0], places=3) self.assertAlmostEqual(layout.coords[idx][1], exp[idx][1], places=3) def testTransform(self): - def tr(coord, dx, dy): return coord[0]+dx, coord[1]+dy + def tr(coord, dx, dy): + return coord[0] + dx, coord[1] + dy + layout = Layout([(1, 2), (3, 4)]) layout.transform(tr, 2, -1) self.assertEqual(layout.coords, [[3, 1], [5, 3]]) @@ -155,30 +148,34 @@ def layout_test(graph, test_with_dims=(2, 3)): g["layout"] = "graphopt" layout_test(g, test_with_dims=()) - g.vs["x"] = range(20) - g.vs["y"] = range(20, 40) + g.vs["x"] = list(range(20)) + g.vs["y"] = list(range(20, 40)) layout_test(g, test_with_dims=()) del g["layout"] lo = layout_test(g, test_with_dims=(2,)) - self.assertEqual([tuple(item) for item in lo], - list(zip(range(20), range(20, 40)))) + self.assertEqual( + [tuple(item) for item in lo], + list(zip(list(range(20)), list(range(20, 40)))), + ) - g.vs["z"] = range(40, 60) + g.vs["z"] = list(range(40, 60)) lo = layout_test(g) - self.assertEqual([tuple(item) for item in lo], - list(zip(range(20), range(20, 40), range(40, 60)))) + self.assertEqual( + [tuple(item) for item in lo], + list(zip(list(range(20)), list(range(20, 40)), list(range(40, 60)))), + ) def testCircle(self): def test_is_proper_circular_layout(graph, layout): - xs, ys = zip(*layout) + xs, ys = list(zip(*layout)) n = graph.vcount() self.assertEqual(n, len(xs)) self.assertEqual(n, len(ys)) self.assertAlmostEqual(0, sum(xs)) self.assertAlmostEqual(0, sum(ys)) for x, y in zip(xs, ys): - self.assertAlmostEqual(1, x**2+y**2) + self.assertAlmostEqual(1, x ** 2 + y ** 2) g = Graph.Ring(8) layout = g.layout("circle") @@ -203,15 +200,17 @@ def testFruchtermanReingold(self): lo = g.layout("fr") self.assertTrue(isinstance(lo, Layout)) - lo = g.layout("fr", miny=range(100)) + lo = g.layout("fr", miny=list(range(100))) self.assertTrue(isinstance(lo, Layout)) self.assertTrue(all(lo[i][1] >= i for i in range(100))) - lo = g.layout("fr", miny=range(100), maxy=range(100)) + lo = g.layout("fr", miny=list(range(100)), maxy=list(range(100))) self.assertTrue(isinstance(lo, Layout)) self.assertTrue(all(lo[i][1] == i for i in range(100))) - lo = g.layout("fr", miny=[2]*100, maxy=[3]*100, minx=[4]*100, maxx=[6]*100) + lo = g.layout( + "fr", miny=[2] * 100, maxy=[3] * 100, minx=[4] * 100, maxx=[6] * 100 + ) self.assertTrue(isinstance(lo, Layout)) bbox = lo.bounding_box() self.assertTrue(bbox.top >= 2) @@ -222,13 +221,15 @@ def testFruchtermanReingold(self): def testFruchtermanReingoldGrid(self): g = Graph.Barabasi(100) for grid_opt in ["grid", "nogrid", "auto", True, False]: - lo = g.layout("fr", miny=range(100), grid=grid_opt) + lo = g.layout("fr", miny=list(range(100)), grid=grid_opt) self.assertTrue(isinstance(lo, Layout)) self.assertTrue(all(lo[i][1] >= i for i in range(100))) def testKamadaKawai(self): g = Graph.Barabasi(100) - lo = g.layout("kk", miny=[2]*100, maxy=[3]*100, minx=[4]*100, maxx=[6]*100) + lo = g.layout( + "kk", miny=[2] * 100, maxy=[3] * 100, minx=[4] * 100, maxx=[6] * 100 + ) self.assertTrue(isinstance(lo, Layout)) bbox = lo.bounding_box() self.assertTrue(bbox.top >= 2) @@ -257,9 +258,9 @@ def testReingoldTilford(self): self.assertEqual(ys, g.shortest_paths(root)[0]) g = Graph.Barabasi(100) + Graph.Barabasi(50) lo = g.layout("rt", root=[0, 100]) - self.assertEqual(lo[100][1]-lo[0][1], 0) + self.assertEqual(lo[100][1] - lo[0][1], 0) lo = g.layout("rt", root=[0, 100], rootlevel=[2, 10]) - self.assertEqual(lo[100][1]-lo[0][1], 8) + self.assertEqual(lo[100][1] - lo[0][1], 8) def testBipartite(self): g = Graph.Full_Bipartite(3, 2) @@ -273,8 +274,12 @@ def testBipartite(self): self.assertEqual([3, 3, 3, 0, 0], ys) lo = g.layout("bipartite", hgap=5) - self.assertEqual(set([0, 5, 10]), set(coord[0] for coord in lo if coord[1] == 1)) - self.assertEqual(set([2.5, 7.5]), set(coord[0] for coord in lo if coord[1] == 0)) + self.assertEqual( + set([0, 5, 10]), set(coord[0] for coord in lo if coord[1] == 1) + ) + self.assertEqual( + set([2.5, 7.5]), set(coord[0] for coord in lo if coord[1] == 0) + ) def testDRL(self): # Regression test for bug #1091891 diff --git a/tests/test_matching.py b/tests/test_matching.py index f84763e43..e7c91c989 100644 --- a/tests/test_matching.py +++ b/tests/test_matching.py @@ -2,6 +2,7 @@ from igraph import * + def powerset(iterable): items_powers = [(item, 1 << i) for i, item in enumerate(iterable)] for i in range(1 << len(items_powers)): @@ -10,17 +11,37 @@ def powerset(iterable): yield item -leda_graph = Graph([ - (0,8),(0,12),(0,14),(1,9),(1,10),(1,13), - (2,8),(2,9),(3,10),(3,11),(3,13),(4,9),(4,14), - (5,14),(6,9),(6,14),(7,8),(7,12),(7,14)]) -leda_graph.vs["type"] = [0]*8+[1]*7 +leda_graph = Graph( + [ + (0, 8), + (0, 12), + (0, 14), + (1, 9), + (1, 10), + (1, 13), + (2, 8), + (2, 9), + (3, 10), + (3, 11), + (3, 13), + (4, 9), + (4, 14), + (5, 14), + (6, 9), + (6, 14), + (7, 8), + (7, 12), + (7, 14), + ] +) +leda_graph.vs["type"] = [0] * 8 + [1] * 7 + class MatchingTests(unittest.TestCase): def setUp(self): - self.matching = Matching(leda_graph, - [12, 10, 8, 13, -1, 14, 9, -1, 2, 6, 1, -1, 0, 3, 5], - "type") + self.matching = Matching( + leda_graph, [12, 10, 8, 13, -1, 14, 9, -1, 2, 6, 1, -1, 0, 3, 5], "type" + ) def testIsMaximal(self): self.assertTrue(self.matching.is_maximal()) @@ -38,8 +59,10 @@ def testMatchingRetrieval(self): else: self.assertTrue(self.matching.is_matched(i)) self.assertEqual(self.matching.match_of(i), mate) - self.assertEqual(self.matching.match_of( - leda_graph.vs[i]).index, leda_graph.vs[mate].index) + self.assertEqual( + self.matching.match_of(leda_graph.vs[i]).index, + leda_graph.vs[mate].index, + ) class MaximumBipartiteMatchingTests(unittest.TestCase): @@ -57,12 +80,12 @@ def testBipartiteMatchingSimple(self): def testBipartiteMatchingErrors(self): # Type vector too short g = Graph([(0, 1), (1, 2), (2, 3)]) - self.assertRaises(InternalError, g.maximum_bipartite_matching, - types=[0,1,0]) + self.assertRaises(InternalError, g.maximum_bipartite_matching, types=[0, 1, 0]) # Graph not bipartite - self.assertRaises(InternalError, g.maximum_bipartite_matching, - types=[0,1,1,1]) + self.assertRaises( + InternalError, g.maximum_bipartite_matching, types=[0, 1, 1, 1] + ) def suite(): @@ -70,10 +93,11 @@ def suite(): bipartite_unweighted_suite = unittest.makeSuite(MaximumBipartiteMatchingTests) return unittest.TestSuite([matching_suite, bipartite_unweighted_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_operators.py b/tests/test_operators.py index 5261d4386..ec001dd46 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -9,6 +9,7 @@ except ImportError: np = None + class OperatorTests(unittest.TestCase): def testComplementer(self): g = Graph.Full(3) @@ -18,32 +19,53 @@ def testComplementer(self): g = Graph.Full(3) + Graph.Full(2) g2 = g.complementer(False) - self.assertTrue(sorted(g2.get_edgelist()) == [ - (0, 3), (0, 4), (1, 3), (1, 4), (2, 3), (2, 4) - ]) + self.assertTrue( + sorted(g2.get_edgelist()) + == [(0, 3), (0, 4), (1, 3), (1, 4), (2, 3), (2, 4)] + ) g2 = g.complementer(loops=True) - self.assertTrue(sorted(g2.get_edgelist()) == [ - (0, 0), (0, 3), (0, 4), (1, 1), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), - (3, 3), (4, 4) - ]) + self.assertTrue( + sorted(g2.get_edgelist()) + == [ + (0, 0), + (0, 3), + (0, 4), + (1, 1), + (1, 3), + (1, 4), + (2, 2), + (2, 3), + (2, 4), + (3, 3), + (4, 4), + ] + ) def testMultiplication(self): g = Graph.Full(3) * 3 - self.assertTrue(g.vcount() == 9 and g.ecount() == 9 - and g.clusters().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2]) + self.assertTrue( + g.vcount() == 9 + and g.ecount() == 9 + and g.clusters().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2] + ) def testDifference(self): g = Graph.Tree(7, 2) - Graph.Lattice([7]) self.assertTrue(g.vcount() == 7 and g.ecount() == 5) - self.assertTrue(sorted(g.get_edgelist()) == [(0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]) + self.assertTrue( + sorted(g.get_edgelist()) == [(0, 2), (1, 3), (1, 4), (2, 5), (2, 6)] + ) def testDifferenceWithSelfLoop(self): # https://github.com/igraph/igraph/issues/597# g = Graph.Ring(10) + [(0, 0)] g -= Graph.Ring(5) self.assertTrue(g.vcount() == 10 and g.ecount() == 7) - self.assertTrue(sorted(g.get_edgelist()) == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]) + self.assertTrue( + sorted(g.get_edgelist()) + == [(0, 0), (0, 9), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)] + ) def testIntersection(self): g = Graph.Tree(7, 2) & Graph.Lattice([7]) @@ -90,10 +112,23 @@ def testDisjointUnionSingle(self): def testUnion(self): g = Graph.Tree(7, 2) | Graph.Lattice([7]) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) - self.assertTrue(sorted(g.get_edgelist()) == [ - (0, 1), (0, 2), (0, 6), (1, 2), (1, 3), (1, 4), (2, 3), (2, 5), - (2, 6), (3, 4), (4, 5), (5, 6) - ]) + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 6), + (1, 2), + (1, 3), + (1, 4), + (2, 3), + (2, 5), + (2, 6), + (3, 4), + (4, 5), + (5, 6), + ] + ) def testUnionMethod(self): g = Graph.Tree(7, 2).union(Graph.Lattice([7])) @@ -117,36 +152,38 @@ def testUnionMany(self): def testUnionManyAttributes(self): gs = [ - Graph.Formula('A-B'), - Graph.Formula('A-B,C-D'), - ] - gs[0]['attr'] = 'graph1' - gs[0].vs['attr'] = ['set', 'set_too'] - gs[0].vs['attr2'] = ['set', 'set_too'] - gs[1].vs[0]['attr'] = 'set' - gs[1].vs[0]['attr2'] = 'conflict' + Graph.Formula("A-B"), + Graph.Formula("A-B,C-D"), + ] + gs[0]["attr"] = "graph1" + gs[0].vs["attr"] = ["set", "set_too"] + gs[0].vs["attr2"] = ["set", "set_too"] + gs[1].vs[0]["attr"] = "set" + gs[1].vs[0]["attr2"] = "conflict" g = union(gs) - names = g.vs['name'] - self.assertTrue(g['attr'] == 'graph1') - self.assertTrue(g.vs[names.index('A')]['attr'] == 'set') - self.assertTrue(g.vs[names.index('B')]['attr'] == 'set_too') + names = g.vs["name"] + self.assertTrue(g["attr"] == "graph1") + self.assertTrue(g.vs[names.index("A")]["attr"] == "set") + self.assertTrue(g.vs[names.index("B")]["attr"] == "set_too") self.assertTrue(g.ecount() == 2) - self.assertTrue(sorted(g.vertex_attributes()) == ['attr', 'attr2_1', 'attr2_2', 'name']) + self.assertTrue( + sorted(g.vertex_attributes()) == ["attr", "attr2_1", "attr2_2", "name"] + ) def testUnionManyEdgemap(self): gs = [ - Graph.Formula('A-B'), - Graph.Formula('C-D, A-B'), - ] - gs[0].es[0]['attr'] = 'set' - gs[1].es[0]['attr'] = 'set_too' + Graph.Formula("A-B"), + Graph.Formula("C-D, A-B"), + ] + gs[0].es[0]["attr"] = "set" + gs[1].es[0]["attr"] = "set_too" g = union(gs) for e in g.es: - vnames = [g.vs[e.source]['name'], g.vs[e.target]['name']] - if set(vnames) == set(['A', 'B']): - self.assertTrue(e['attr'] == 'set') + vnames = [g.vs[e.source]["name"], g.vs[e.target]["name"]] + if set(vnames) == set(["A", "B"]): + self.assertTrue(e["attr"] == "set") else: - self.assertTrue(e['attr'] == 'set_too') + self.assertTrue(e["attr"] == "set_too") def testIntersectionNoGraphs(self): self.assertRaises(ValueError, intersection, []) @@ -166,30 +203,30 @@ def testIntersectionMany(self): def testIntersectionManyAttributes(self): gs = [Graph.Tree(7, 2), Graph.Lattice([7])] - gs[0]['attr'] = 'graph1' - gs[0].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] - gs[1].vs['name'] = ['one', 'two', 'three', 'four', 'five', 'six', '7'] - gs[0].vs[0]['attr'] = 'set' - gs[1].vs[5]['attr'] = 'set_too' + gs[0]["attr"] = "graph1" + gs[0].vs["name"] = ["one", "two", "three", "four", "five", "six", "7"] + gs[1].vs["name"] = ["one", "two", "three", "four", "five", "six", "7"] + gs[0].vs[0]["attr"] = "set" + gs[1].vs[5]["attr"] = "set_too" g = intersection(gs) - names = g.vs['name'] - self.assertTrue(g['attr'] == 'graph1') - self.assertTrue(g.vs[names.index('one')]['attr'] == 'set') - self.assertTrue(g.vs[names.index('six')]['attr'] == 'set_too') + names = g.vs["name"] + self.assertTrue(g["attr"] == "graph1") + self.assertTrue(g.vs[names.index("one")]["attr"] == "set") + self.assertTrue(g.vs[names.index("six")]["attr"] == "set_too") self.assertTrue(g.ecount() == 1) self.assertTrue( - set(g.get_edgelist()[0]) == set([names.index('one'), names.index('two')]), + set(g.get_edgelist()[0]) == set([names.index("one"), names.index("two")]), ) def testIntersectionManyEdgemap(self): gs = [ - Graph.Formula('A-B'), - Graph.Formula('A-B,C-D'), - ] - gs[0].es[0]['attr'] = 'set' - gs[1].es[1]['attr'] = 'set_too' + Graph.Formula("A-B"), + Graph.Formula("A-B,C-D"), + ] + gs[0].es[0]["attr"] = "set" + gs[1].es[1]["attr"] = "set_too" g = intersection(gs) - self.assertTrue(g.es['attr'] == ['set']) + self.assertTrue(g.es["attr"] == ["set"]) def testInPlaceAddition(self): g = Graph.Full(3) @@ -197,28 +234,39 @@ def testInPlaceAddition(self): # Adding vertices g += 2 - self.assertTrue(g.vcount() == 5 and g.ecount() == 3 - and g.clusters().membership == [0,0,0,1,2]) + self.assertTrue( + g.vcount() == 5 + and g.ecount() == 3 + and g.clusters().membership == [0, 0, 0, 1, 2] + ) # Adding a vertex by name g += "spam" - self.assertTrue(g.vcount() == 6 and g.ecount() == 3 - and g.clusters().membership == [0,0,0,1,2,3]) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 3 + and g.clusters().membership == [0, 0, 0, 1, 2, 3] + ) # Adding a single edge g += (2, 3) - self.assertTrue(g.vcount() == 6 and g.ecount() == 4 - and g.clusters().membership == [0,0,0,0,1,2]) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 4 + and g.clusters().membership == [0, 0, 0, 0, 1, 2] + ) # Adding two edges g += [(3, 4), (2, 4), (4, 5)] - self.assertTrue(g.vcount() == 6 and g.ecount() == 7 - and g.clusters().membership == [0]*6) + self.assertTrue( + g.vcount() == 6 and g.ecount() == 7 and g.clusters().membership == [0] * 6 + ) # Adding two more vertices g += ["eggs", "bacon"] - self.assertEqual(g.vs["name"], [None, None, None, None, None, - "spam", "eggs", "bacon"]) + self.assertEqual( + g.vs["name"], [None, None, None, None, None, "spam", "eggs", "bacon"] + ) # Did we really use the original graph so far? # TODO: disjoint union should be modified so that this assertion @@ -227,45 +275,65 @@ def testInPlaceAddition(self): # Adding another graph g += Graph.Full(3) - self.assertTrue(g.vcount() == 11 and g.ecount() == 10 - and g.clusters().membership == [0,0,0,0,0,0,1,2,3,3,3]) + self.assertTrue( + g.vcount() == 11 + and g.ecount() == 10 + and g.clusters().membership == [0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3] + ) # Adding two graphs g += [Graph.Full(3), Graph.Full(2)] - self.assertTrue(g.vcount() == 16 and g.ecount() == 14 - and g.clusters().membership == [0,0,0,0,0,0,1,2,3,3,3,4,4,4,5,5]) + self.assertTrue( + g.vcount() == 16 + and g.ecount() == 14 + and g.clusters().membership + == [0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5] + ) def testAddition(self): g0 = Graph.Full(3) # Adding vertices - g = g0+2 - self.assertTrue(g.vcount() == 5 and g.ecount() == 3 - and g.clusters().membership == [0,0,0,1,2]) + g = g0 + 2 + self.assertTrue( + g.vcount() == 5 + and g.ecount() == 3 + and g.clusters().membership == [0, 0, 0, 1, 2] + ) g0 = g # Adding vertices by name - g = g0+"spam" - self.assertTrue(g.vcount() == 6 and g.ecount() == 3 - and g.clusters().membership == [0,0,0,1,2,3]) + g = g0 + "spam" + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 3 + and g.clusters().membership == [0, 0, 0, 1, 2, 3] + ) g0 = g # Adding a single edge - g = g0+(2,3) - self.assertTrue(g.vcount() == 6 and g.ecount() == 4 - and g.clusters().membership == [0,0,0,0,1,2]) + g = g0 + (2, 3) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 4 + and g.clusters().membership == [0, 0, 0, 0, 1, 2] + ) g0 = g # Adding two edges - g = g0+[(3, 4), (2, 4), (4, 5)] - self.assertTrue(g.vcount() == 6 and g.ecount() == 7 - and g.clusters().membership == [0]*6) + g = g0 + [(3, 4), (2, 4), (4, 5)] + self.assertTrue( + g.vcount() == 6 and g.ecount() == 7 and g.clusters().membership == [0] * 6 + ) g0 = g # Adding another graph - g = g0+Graph.Full(3) - self.assertTrue(g.vcount() == 9 and g.ecount() == 10 - and g.clusters().membership == [0,0,0,0,0,0,1,1,1]) + g = g0 + Graph.Full(3) + self.assertTrue( + g.vcount() == 9 + and g.ecount() == 10 + and g.clusters().membership == [0, 0, 0, 0, 0, 0, 1, 1, 1] + ) def testInPlaceSubtraction(self): g = Graph.Full(8) @@ -273,28 +341,43 @@ def testInPlaceSubtraction(self): # Deleting a vertex by vertex selector g -= 7 - self.assertTrue(g.vcount() == 7 and g.ecount() == 21 - and g.clusters().membership == [0,0,0,0,0,0,0]) + self.assertTrue( + g.vcount() == 7 + and g.ecount() == 21 + and g.clusters().membership == [0, 0, 0, 0, 0, 0, 0] + ) # Deleting a vertex g -= g.vs[6] - self.assertTrue(g.vcount() == 6 and g.ecount() == 15 - and g.clusters().membership == [0,0,0,0,0,0]) + self.assertTrue( + g.vcount() == 6 + and g.ecount() == 15 + and g.clusters().membership == [0, 0, 0, 0, 0, 0] + ) # Deleting two vertices g -= [4, 5] - self.assertTrue(g.vcount() == 4 and g.ecount() == 6 - and g.clusters().membership == [0,0,0,0]) + self.assertTrue( + g.vcount() == 4 + and g.ecount() == 6 + and g.clusters().membership == [0, 0, 0, 0] + ) # Deleting an edge g -= (1, 2) - self.assertTrue(g.vcount() == 4 and g.ecount() == 5 - and g.clusters().membership == [0,0,0,0]) + self.assertTrue( + g.vcount() == 4 + and g.ecount() == 5 + and g.clusters().membership == [0, 0, 0, 0] + ) # Deleting three more edges g -= [(1, 3), (0, 2), (0, 3)] - self.assertTrue(g.vcount() == 4 and g.ecount() == 2 - and g.clusters().membership == [0,0,1,1]) + self.assertTrue( + g.vcount() == 4 + and g.ecount() == 2 + and g.clusters().membership == [0, 0, 1, 1] + ) # Did we really use the original graph so far? self.assertTrue(id(g) == id(orig)) @@ -302,8 +385,11 @@ def testInPlaceSubtraction(self): # Subtracting a graph g2 = Graph.Tree(3, 2) g -= g2 - self.assertTrue(g.vcount() == 4 and g.ecount() == 1 - and g.clusters().membership == [0,1,2,2]) + self.assertTrue( + g.vcount() == 4 + and g.ecount() == 1 + and g.clusters().membership == [0, 1, 2, 2] + ) def testNonzero(self): self.assertTrue(Graph(1)) @@ -315,7 +401,7 @@ def testLength(self): self.assertTrue(len(Graph.Full(5).es) == 10) def testSimplify(self): - el = [(0,1), (1,0), (1,2), (2,3), (2,3), (2,3), (3,3)] + el = [(0, 1), (1, 0), (1, 2), (2, 3), (2, 3), (2, 3), (3, 3)] g = Graph(el) g.es["weight"] = [1, 2, 3, 4, 5, 6, 7] @@ -341,17 +427,49 @@ def testContractVertices(self): g2.contract_vertices([0, 1, 2, 3, 1, 0, 4, 5]) self.assertEqual(g2.vcount(), 6) self.assertEqual(g2.ecount(), g.ecount()) - self.assertEqual(sorted(g2.get_edgelist()), - [(0, 0), (0, 1), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), - (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (4, 5)]) + self.assertEqual( + sorted(g2.get_edgelist()), + [ + (0, 0), + (0, 1), + (0, 1), + (0, 2), + (0, 3), + (0, 4), + (0, 5), + (1, 1), + (1, 2), + (1, 3), + (1, 4), + (1, 5), + (2, 3), + (4, 5), + ], + ) g2 = g.copy() g2.contract_vertices([0, 1, 2, 3, 1, 0, 6, 7]) self.assertEqual(g2.vcount(), 8) self.assertEqual(g2.ecount(), g.ecount()) - self.assertEqual(sorted(g2.get_edgelist()), - [(0, 0), (0, 1), (0, 1), (0, 2), (0, 3), (0, 6), (0, 7), - (1, 1), (1, 2), (1, 3), (1, 6), (1, 7), (2, 3), (6, 7)]) + self.assertEqual( + sorted(g2.get_edgelist()), + [ + (0, 0), + (0, 1), + (0, 1), + (0, 2), + (0, 3), + (0, 6), + (0, 7), + (1, 1), + (1, 2), + (1, 3), + (1, 6), + (1, 7), + (2, 3), + (6, 7), + ], + ) g2 = Graph(10) g2.contract_vertices([0, 0, 1, 1, 2, 2, 3, 3, 4, 4]) @@ -365,19 +483,36 @@ def testContractVerticesWithNumPyIntegers(self): g2.contract_vertices([np.int32(x) for x in [0, 1, 2, 3, 1, 0, 6, 7]]) self.assertEqual(g2.vcount(), 8) self.assertEqual(g2.ecount(), g.ecount()) - self.assertEqual(sorted(g2.get_edgelist()), - [(0, 0), (0, 1), (0, 1), (0, 2), (0, 3), (0, 6), (0, 7), - (1, 1), (1, 2), (1, 3), (1, 6), (1, 7), (2, 3), (6, 7)]) + self.assertEqual( + sorted(g2.get_edgelist()), + [ + (0, 0), + (0, 1), + (0, 1), + (0, 2), + (0, 3), + (0, 6), + (0, 7), + (1, 1), + (1, 2), + (1, 3), + (1, 6), + (1, 7), + (2, 3), + (6, 7), + ], + ) def suite(): operator_suite = unittest.makeSuite(OperatorTests) return unittest.TestSuite([operator_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_rng.py b/tests/test_rng.py index 29ca51492..00f82d8c4 100644 --- a/tests/test_rng.py +++ b/tests/test_rng.py @@ -16,6 +16,7 @@ def randint(a, b): def gauss(mu, sigma): return 0.3 + class InvalidRNG(object): pass @@ -30,8 +31,7 @@ def testSetRandomNumberGenerator(self): self.assertEqual(graph.vs["x"], [0.1] * 10) self.assertEqual(graph.vs["y"], [0.1] * 10) - self.assertRaises(AttributeError, set_random_number_generator, - InvalidRNG) + self.assertRaises(AttributeError, set_random_number_generator, InvalidRNG) def testSeeding(self): state = random.getstate() @@ -45,10 +45,11 @@ def suite(): random_suite = unittest.makeSuite(RandomNumberGeneratorTests) return unittest.TestSuite([random_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_separators.py b/tests/test_separators.py index caabc54c0..187026f63 100644 --- a/tests/test_separators.py +++ b/tests/test_separators.py @@ -2,6 +2,7 @@ from igraph import * + def powerset(iterable): items_powers = [(item, 1 << i) for i, item in enumerate(iterable)] for i in range(1 << len(items_powers)): @@ -9,6 +10,7 @@ def powerset(iterable): if i & power: yield item + class IsSeparatorTests(unittest.TestCase): def testIsSeparator(self): g = Graph.Lattice([8, 4], circular=False) @@ -20,9 +22,9 @@ def testIsSeparator(self): g = Graph.Lattice([8, 4], circular=True) self.assertFalse(g.is_separator([3, 11, 19, 27])) self.assertFalse(g.is_separator([29, 20, 11, 2])) - self.assertFalse(g.is_separator(range(32))) + self.assertFalse(g.is_separator(list(range(32)))) - self.assertRaises(InternalError, g.is_separator, range(33)) + self.assertRaises(InternalError, g.is_separator, list(range(33))) def testIsMinimalSeparator(self): g = Graph.Lattice([8, 4], circular=False) @@ -30,14 +32,14 @@ def testIsMinimalSeparator(self): self.assertFalse(g.is_minimal_separator([3, 11, 19, 27, 28])) self.assertFalse(g.is_minimal_separator([16, 25, 17])) self.assertTrue(g.is_minimal_separator([16, 25])) - self.assertFalse(g.is_minimal_separator(range(32))) + self.assertFalse(g.is_minimal_separator(list(range(32)))) - self.assertRaises(InternalError, g.is_minimal_separator, range(33)) + self.assertRaises(InternalError, g.is_minimal_separator, list(range(33))) def testAllMinimalSTSeparators(self): g = Graph.Famous("petersen") min_st_seps = set(tuple(x) for x in g.all_minimal_st_separators()) - for vs in powerset(range(g.vcount())): + for vs in powerset(list(range(g.vcount()))): if vs in min_st_seps: self.assertTrue(g.is_minimal_separator(vs)) else: @@ -52,18 +54,20 @@ def testMinimumSizeSeparators(self): size = len(min_size_seps[0]) self.assertTrue(len(s) != size for s in min_size_seps) - self.assertTrue(sum(1 for s in min_st_seps if len(s) == size) == - len(min_size_seps)) + self.assertTrue( + sum(1 for s in min_st_seps if len(s) == size) == len(min_size_seps) + ) def suite(): is_separator_suite = unittest.makeSuite(IsSeparatorTests) return unittest.TestSuite([is_separator_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_spectral.py b/tests/test_spectral.py index f2d75f441..d0912fb13 100644 --- a/tests/test_spectral.py +++ b/tests/test_spectral.py @@ -2,44 +2,53 @@ import unittest from igraph import * + class SpectralTests(unittest.TestCase): - def assertAlmostEqualMatrix(self, mat1, mat2, eps = 1e-7): - self.assertTrue(all( - abs(obs-exp) < eps - for obs, exp in zip(sum(mat1, []), sum(mat2, [])) - )) + def assertAlmostEqualMatrix(self, mat1, mat2, eps=1e-7): + self.assertTrue( + all(abs(obs - exp) < eps for obs, exp in zip(sum(mat1, []), sum(mat2, []))) + ) def testLaplacian(self): - g=Graph.Full(3) + g = Graph.Full(3) g.es["weight"] = [1, 2, 3] - self.assertTrue(g.laplacian() == [[ 2, -1, -1],\ - [-1, 2, -1],\ - [-1, -1, 2]]) - self.assertAlmostEqualMatrix(g.laplacian(normalized=True), - [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]]) - - mx0 = [[1., -1/(12**0.5), -2/(15**0.5)], - [-1/(12**0.5), 1., -3/(20**0.5)], - [-2/(15**0.5), -3/(20**0.5), 1.]] + self.assertTrue(g.laplacian() == [[2, -1, -1], [-1, 2, -1], [-1, -1, 2]]) + self.assertAlmostEqualMatrix( + g.laplacian(normalized=True), + [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]], + ) + + mx0 = [ + [1.0, -1 / (12 ** 0.5), -2 / (15 ** 0.5)], + [-1 / (12 ** 0.5), 1.0, -3 / (20 ** 0.5)], + [-2 / (15 ** 0.5), -3 / (20 ** 0.5), 1.0], + ] self.assertAlmostEqualMatrix(g.laplacian("weight", True), mx0) - g=Graph.Tree(5, 2) + g = Graph.Tree(5, 2) g.add_vertices(1) - self.assertTrue(g.laplacian() == [[ 2, -1, -1, 0, 0, 0],\ - [-1, 3, 0, -1, -1, 0],\ - [-1, 0, 1, 0, 0, 0],\ - [ 0, -1, 0, 1, 0, 0],\ - [ 0, -1, 0, 0, 1, 0],\ - [ 0, 0, 0, 0, 0, 0]]) - + self.assertTrue( + g.laplacian() + == [ + [2, -1, -1, 0, 0, 0], + [-1, 3, 0, -1, -1, 0], + [-1, 0, 1, 0, 0, 0], + [0, -1, 0, 1, 0, 0], + [0, -1, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0], + ] + ) + + def suite(): spectral_suite = unittest.makeSuite(SpectralTests) return unittest.TestSuite([spectral_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_structural.py b/tests/test_structural.py index e3e72d516..aadf18033 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -1,5 +1,3 @@ -from __future__ import division - import math import unittest import warnings @@ -7,27 +5,29 @@ from igraph import * from math import isnan + class SimplePropertiesTests(unittest.TestCase): - gfull = Graph.Full(10) + gfull = Graph.Full(10) gempty = Graph(10) g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) - gdir = Graph(4, [(0, 1), (0, 2), (1, 2), (2, 1), (0, 3), (1, 3), (3, 0)], directed=True) + gdir = Graph( + 4, [(0, 1), (0, 2), (1, 2), (2, 1), (0, 3), (1, 3), (3, 0)], directed=True + ) tree = Graph.Tree(14, 3) def testDensity(self): self.assertAlmostEqual(1.0, self.gfull.density(), places=5) self.assertAlmostEqual(0.0, self.gempty.density(), places=5) - self.assertAlmostEqual(5/6, self.g.density(), places=5) - self.assertAlmostEqual(1/2, self.g.density(True), places=5) - self.assertAlmostEqual(7/12, self.gdir.density(), places=5) - self.assertAlmostEqual(7/16, self.gdir.density(True), places=5) - self.assertAlmostEqual(1/7, self.tree.density(), places=5) + self.assertAlmostEqual(5 / 6, self.g.density(), places=5) + self.assertAlmostEqual(1 / 2, self.g.density(True), places=5) + self.assertAlmostEqual(7 / 12, self.gdir.density(), places=5) + self.assertAlmostEqual(7 / 16, self.gdir.density(True), places=5) + self.assertAlmostEqual(1 / 7, self.tree.density(), places=5) def testDiameter(self): self.assertTrue(self.gfull.diameter() == 1) self.assertTrue(self.gempty.diameter(unconn=False) == 10) - self.assertTrue(self.gempty.diameter(unconn=False, weights=[]) \ - == float('inf')) + self.assertTrue(self.gempty.diameter(unconn=False, weights=[]) == float("inf")) self.assertTrue(self.g.diameter() == 2) self.assertTrue(self.gdir.diameter(False) == 2) self.assertTrue(self.gdir.diameter() == 3) @@ -47,15 +47,13 @@ def testDiameter(self): self.assertTrue(d == (13, 6, 15) or d == (6, 13, 15)) def testEccentricity(self): - self.assertEqual(self.gfull.eccentricity(), - [1] * self.gfull.vcount()) - self.assertEqual(self.gempty.eccentricity(), - [0] * self.gempty.vcount()) + self.assertEqual(self.gfull.eccentricity(), [1] * self.gfull.vcount()) + self.assertEqual(self.gempty.eccentricity(), [0] * self.gempty.vcount()) self.assertEqual(self.g.eccentricity(), [1, 1, 2, 2]) - self.assertEqual(self.gdir.eccentricity(), - [1, 2, 3, 2]) - self.assertEqual(self.tree.eccentricity(), - [3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5]) + self.assertEqual(self.gdir.eccentricity(), [1, 2, 3, 2]) + self.assertEqual( + self.tree.eccentricity(), [3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5] + ) self.assertEqual(Graph().eccentricity(), []) def testRadius(self): @@ -72,51 +70,59 @@ def testTransitivity(self): self.assertTrue(self.g.transitivity_undirected() == 0.75) def testLocalTransitivity(self): - self.assertTrue(self.gfull.transitivity_local_undirected() == - [1.0] * self.gfull.vcount()) - self.assertTrue(self.tree.transitivity_local_undirected(mode="zero") == - [0.0] * self.tree.vcount()) + self.assertTrue( + self.gfull.transitivity_local_undirected() == [1.0] * self.gfull.vcount() + ) + self.assertTrue( + self.tree.transitivity_local_undirected(mode="zero") + == [0.0] * self.tree.vcount() + ) l = self.g.transitivity_local_undirected(mode="zero") - self.assertAlmostEqual(2/3, l[0], places=4) - self.assertAlmostEqual(2/3, l[1], places=4) + self.assertAlmostEqual(2 / 3, l[0], places=4) + self.assertAlmostEqual(2 / 3, l[1], places=4) self.assertEqual(1, l[2]) self.assertEqual(1, l[3]) g = Graph.Full(4) + 1 + [(0, 4)] g.es["weight"] = [1, 1, 1, 1, 1, 1, 5] self.assertAlmostEqual( - g.transitivity_local_undirected(0, weights="weight"), - 0.25, places=4) + g.transitivity_local_undirected(0, weights="weight"), 0.25, places=4 + ) def testAvgLocalTransitivity(self): self.assertTrue(self.gfull.transitivity_avglocal_undirected() == 1.0) self.assertTrue(self.tree.transitivity_avglocal_undirected() == 0.0) - self.assertAlmostEqual(self.g.transitivity_avglocal_undirected(), 5/6., places=4) + self.assertAlmostEqual( + self.g.transitivity_avglocal_undirected(), 5 / 6.0, places=4 + ) def testModularity(self): - g = Graph.Full(5)+Graph.Full(5) - g.add_edges([(0,5)]) - cl = [0]*5+[1]*5 + g = Graph.Full(5) + Graph.Full(5) + g.add_edges([(0, 5)]) + cl = [0] * 5 + [1] * 5 self.assertAlmostEqual(g.modularity(cl), 0.4523, places=3) - ws = [1]*21 + ws = [1] * 21 self.assertAlmostEqual(g.modularity(cl, ws), 0.4523, places=3) - ws = [2]*21 + ws = [2] * 21 self.assertAlmostEqual(g.modularity(cl, ws), 0.4523, places=3) - ws = [2]*10+[1]*11 + ws = [2] * 10 + [1] * 11 self.assertAlmostEqual(g.modularity(cl, ws), 0.4157, places=3) self.assertRaises(InternalError, g.modularity, cl, ws[0:20]) + class DegreeTests(unittest.TestCase): - gfull = Graph.Full(10) + gfull = Graph.Full(10) gempty = Graph(10) g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (0, 0)]) - gdir = Graph(4, [(0, 1), (0, 2), (1, 2), (2, 1), (0, 3), (1, 3), (3, 0)], directed=True) + gdir = Graph( + 4, [(0, 1), (0, 2), (1, 2), (2, 1), (0, 3), (1, 3), (3, 0)], directed=True + ) tree = Graph.Tree(10, 3) def testKnn(self): knn, knnk = self.gfull.knn() - self.assertTrue(knn == [9.] * 10) + self.assertTrue(knn == [9.0] * 10) self.assertAlmostEqual(knnk[8], 9.0, places=6) # knn works for simple graphs only -- self.g is not simple @@ -127,11 +133,11 @@ def testKnn(self): g.simplify() knn, knnk = g.knn() - diff = max(abs(a-b) for a, b in zip(knn, [7/3., 7/3., 3, 3])) - self.assertAlmostEqual(diff, 0., places=6) + diff = max(abs(a - b) for a, b in zip(knn, [7 / 3.0, 7 / 3.0, 3, 3])) + self.assertAlmostEqual(diff, 0.0, places=6) self.assertEqual(len(knnk), 3) self.assertAlmostEqual(knnk[1], 3, places=6) - self.assertAlmostEqual(knnk[2], 7/3., places=6) + self.assertAlmostEqual(knnk[2], 7 / 3.0, places=6) def testDegree(self): self.assertTrue(self.gfull.degree() == [9] * 10) @@ -158,8 +164,10 @@ def testMaxDegree(self): def testStrength(self): # Turn off warnings about calling strength without weights import warnings - warnings.filterwarnings("ignore", "No edge weights for strength calculation", \ - RuntimeWarning) + + warnings.filterwarnings( + "ignore", "No edge weights for strength calculation", RuntimeWarning + ) # No weights self.assertTrue(self.gfull.strength() == [9] * 10) @@ -168,28 +176,21 @@ def testStrength(self): self.assertTrue(self.g.degree() == [5, 3, 2, 2]) # With weights ws = [1, 2, 3, 4, 5, 6] - self.assertTrue(self.g.strength(weights=ws, loops=False) == \ - [7, 9, 5, 9]) + self.assertTrue(self.g.strength(weights=ws, loops=False) == [7, 9, 5, 9]) self.assertTrue(self.g.strength(weights=ws) == [19, 9, 5, 9]) ws = [1, 2, 3, 4, 5, 6, 7] - self.assertTrue(self.gdir.strength(mode=IN, weights=ws) == \ - [7, 5, 5, 11]) - self.assertTrue(self.gdir.strength(mode=OUT, weights=ws) == \ - [8, 9, 4, 7]) - self.assertTrue(self.gdir.strength(mode=ALL, weights=ws) == \ - [15, 14, 9, 18]) + self.assertTrue(self.gdir.strength(mode=IN, weights=ws) == [7, 5, 5, 11]) + self.assertTrue(self.gdir.strength(mode=OUT, weights=ws) == [8, 9, 4, 7]) + self.assertTrue(self.gdir.strength(mode=ALL, weights=ws) == [15, 14, 9, 18]) vs = self.gdir.vs.select(0, 2) - self.assertTrue(self.gdir.strength(vs, mode=ALL, weights=ws) == \ - [15, 9]) - self.assertTrue(self.gdir.strength(self.gdir.vs[1], \ - mode=ALL, weights=ws) == 14) - + self.assertTrue(self.gdir.strength(vs, mode=ALL, weights=ws) == [15, 9]) + self.assertTrue(self.gdir.strength(self.gdir.vs[1], mode=ALL, weights=ws) == 14) class LocalTransitivityTests(unittest.TestCase): def testLocalTransitivityFull(self): trans = Graph.Full(10).transitivity_local_undirected() - self.assertTrue(trans == [1.0]*10) + self.assertTrue(trans == [1.0] * 10) def testLocalTransitivityTree(self): trans = Graph.Tree(10, 3).transitivity_local_undirected() @@ -203,61 +204,65 @@ def testLocalTransitivityHalf(self): def testLocalTransitivityPartial(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) - trans = g.transitivity_local_undirected([1,2]) + trans = g.transitivity_local_undirected([1, 2]) trans = [round(x, 3) for x in trans] self.assertTrue(trans == [0.667, 1.0]) class BiconnectedComponentTests(unittest.TestCase): g1 = Graph.Full(10) - g2 = Graph(5, [(0,1),(1,2),(2,3),(3,4)]) - g3 = Graph(6, [(0,1),(1,2),(2,3),(3,0),(2,4),(2,5),(4,5)]) + g2 = Graph(5, [(0, 1), (1, 2), (2, 3), (3, 4)]) + g3 = Graph(6, [(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (2, 5), (4, 5)]) def testBiconnectedComponents(self): s = self.g1.biconnected_components() - self.assertTrue(len(s) == 1 and s[0]==list(range(10))) + self.assertTrue(len(s) == 1 and s[0] == list(range(10))) s, ap = self.g1.biconnected_components(True) - self.assertTrue(len(s) == 1 and s[0]==list(range(10))) + self.assertTrue(len(s) == 1 and s[0] == list(range(10))) s = self.g3.biconnected_components() - self.assertTrue(len(s) == 2 and s[0]==[2,4,5] and s[1]==[0,1,2,3]) + self.assertTrue(len(s) == 2 and s[0] == [2, 4, 5] and s[1] == [0, 1, 2, 3]) s, ap = self.g3.biconnected_components(True) - self.assertTrue(len(s) == 2 and s[0]==[2,4,5] and \ - s[1]==[0,1,2,3] and ap == [2]) + self.assertTrue( + len(s) == 2 and s[0] == [2, 4, 5] and s[1] == [0, 1, 2, 3] and ap == [2] + ) def testArticulationPoints(self): self.assertTrue(self.g1.articulation_points() == []) - self.assertTrue(self.g2.cut_vertices() == [1,2,3]) + self.assertTrue(self.g2.cut_vertices() == [1, 2, 3]) self.assertTrue(self.g3.articulation_points() == [2]) class CentralityTests(unittest.TestCase): def testBetweennessCentrality(self): g = Graph.Star(5) - self.assertTrue(g.betweenness() == [6., 0., 0., 0., 0.]) + self.assertTrue(g.betweenness() == [6.0, 0.0, 0.0, 0.0, 0.0]) g = Graph(5, [(0, 1), (0, 2), (0, 3), (1, 4)]) - self.assertTrue(g.betweenness() == [5., 3., 0., 0., 0.]) - self.assertTrue(g.betweenness(cutoff=2) == [3., 1., 0., 0., 0.]) - self.assertTrue(g.betweenness(cutoff=1) == [0., 0., 0., 0., 0.]) + self.assertTrue(g.betweenness() == [5.0, 3.0, 0.0, 0.0, 0.0]) + self.assertTrue(g.betweenness(cutoff=2) == [3.0, 1.0, 0.0, 0.0, 0.0]) + self.assertTrue(g.betweenness(cutoff=1) == [0.0, 0.0, 0.0, 0.0, 0.0]) g = Graph.Lattice([3, 3], circular=False) - self.assertTrue(g.betweenness(cutoff=2) == [0.5, 2.0, 0.5, 2.0, 4.0, 2.0, 0.5, 2.0, 0.5]) + self.assertTrue( + g.betweenness(cutoff=2) == [0.5, 2.0, 0.5, 2.0, 4.0, 2.0, 0.5, 2.0, 0.5] + ) def testEdgeBetweennessCentrality(self): g = Graph.Star(5) - self.assertTrue(g.edge_betweenness() == [4., 4., 4., 4.]) + self.assertTrue(g.edge_betweenness() == [4.0, 4.0, 4.0, 4.0]) g = Graph(5, [(0, 1), (0, 2), (0, 3), (1, 4)]) - self.assertTrue(g.edge_betweenness() == [6., 4., 4., 4.]) - self.assertTrue(g.edge_betweenness(cutoff=2) == [4., 3., 3., 2.]) - self.assertTrue(g.edge_betweenness(cutoff=1) == [1., 1., 1., 1.]) + self.assertTrue(g.edge_betweenness() == [6.0, 4.0, 4.0, 4.0]) + self.assertTrue(g.edge_betweenness(cutoff=2) == [4.0, 3.0, 3.0, 2.0]) + self.assertTrue(g.edge_betweenness(cutoff=1) == [1.0, 1.0, 1.0, 1.0]) g = Graph.Ring(5) - self.assertTrue(g.edge_betweenness() == [3., 3., 3., 3., 3.]) - self.assertTrue(g.edge_betweenness(weights=[4, 1, 1, 1, 1]) == \ - [0.5, 3.5, 5.5, 5.5, 3.5]) + self.assertTrue(g.edge_betweenness() == [3.0, 3.0, 3.0, 3.0, 3.0]) + self.assertTrue( + g.edge_betweenness(weights=[4, 1, 1, 1, 1]) == [0.5, 3.5, 5.5, 5.5, 3.5] + ) def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness() - cl2 = [1., 0.57142, 0.57142, 0.57142, 0.57142] + cl2 = [1.0, 0.57142, 0.57142, 0.57142, 0.57142] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -265,7 +270,7 @@ def testClosenessCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1) - cl2 = [1., 0.25, 0.25, 0.25, 0.25] + cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -273,7 +278,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness(weights=weights) - cl2 = [1., 0.57142, 0.57142, 0.57142, 0.57142] + cl2 = [1.0, 0.57142, 0.57142, 0.57142, 0.57142] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -281,25 +286,72 @@ def testClosenessCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1, weights=weights) - cl2 = [1., 0.25, 0.25, 0.25, 0.25] + cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) # Test for igraph/igraph:#1078 - g = Graph([ - (0, 1), (0, 2), (0, 5), (0, 6), (0, 9), (1, 6), (1, 8), - (2, 4), (2, 6), (2, 7), (2, 8), (3, 6), (4, 8), - (5, 6), (5, 9), (6, 7), (6, 8), (7, 8), (7, 9), (8, 9) - ]) - weights = [0.69452, 0.329886, 0.131649, 0.503269, 0.472738, - 0.370933, 0.23857, 0.0354043, 0.189015, 0.355118, 0.768335, - 0.893289, 0.891709, 0.494896, 0.924684, 0.432001, 0.858159, - 0.246798, 0.881304, 0.64685] + g = Graph( + [ + (0, 1), + (0, 2), + (0, 5), + (0, 6), + (0, 9), + (1, 6), + (1, 8), + (2, 4), + (2, 6), + (2, 7), + (2, 8), + (3, 6), + (4, 8), + (5, 6), + (5, 9), + (6, 7), + (6, 8), + (7, 8), + (7, 9), + (8, 9), + ] + ) + weights = [ + 0.69452, + 0.329886, + 0.131649, + 0.503269, + 0.472738, + 0.370933, + 0.23857, + 0.0354043, + 0.189015, + 0.355118, + 0.768335, + 0.893289, + 0.891709, + 0.494896, + 0.924684, + 0.432001, + 0.858159, + 0.246798, + 0.881304, + 0.64685, + ] with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.closeness(weights=weights) - expected_cl = [1.63318, 1.52014, 2.03724, 0.760158, 1.91449, - 1.43224, 1.91761, 1.60198, 1.3891, 1.12829] + expected_cl = [ + 1.63318, + 1.52014, + 2.03724, + 0.760158, + 1.91449, + 1.43224, + 1.91761, + 1.60198, + 1.3891, + 1.12829, + ] for obs, exp in zip(cl, expected_cl): self.assertAlmostEqual(obs, exp, places=4) @@ -311,14 +363,14 @@ def testPageRank(self): def testPersonalizedPageRank(self): g = Graph.Star(11) - self.assertRaises(InternalError, g.personalized_pagerank, reset=[0]*11) - cent = g.personalized_pagerank(reset=[0,10]+[0]*9, damping=0.5) + self.assertRaises(InternalError, g.personalized_pagerank, reset=[0] * 11) + cent = g.personalized_pagerank(reset=[0, 10] + [0] * 9, damping=0.5) self.assertTrue(cent.index(max(cent)) == 1) self.assertAlmostEqual(cent[0], 0.3333, places=3) self.assertAlmostEqual(cent[1], 0.5166, places=3) self.assertAlmostEqual(cent[2], 0.0166, places=3) cent2 = g.personalized_pagerank(reset_vertices=g.vs[1], damping=0.5) - self.assertTrue(max(abs(x-y) for x, y in zip(cent, cent2)) < 0.001) + self.assertTrue(max(abs(x - y) for x, y in zip(cent, cent2)) < 0.001) def testEigenvectorCentrality(self): g = Graph.Star(11) @@ -327,9 +379,10 @@ def testEigenvectorCentrality(self): self.assertAlmostEqual(max(cent), 1.0, places=3) self.assertTrue(min(cent) >= 0) cent, ev = g.evcent(scale=False, return_eigenvalue=True) - if cent[0]<0: cent = [-x for x in cent] + if cent[0] < 0: + cent = [-x for x in cent] self.assertTrue(cent.index(max(cent)) == 0) - self.assertAlmostEqual(cent[1]/cent[0], 0.3162, places=3) + self.assertAlmostEqual(cent[1] / cent[0], 0.3162, places=3) self.assertAlmostEqual(ev, 3.162, places=3) def testAuthorityScore(self): @@ -337,41 +390,78 @@ def testAuthorityScore(self): asc = g.authority_score() self.assertAlmostEqual(max(asc), 1.0, places=3) asc, ev = g.hub_score(scale=False, return_eigenvalue=True) - if asc[0]<0: hs = [-x for x in asc] + if asc[0] < 0: + hs = [-x for x in asc] def testHubScore(self): g = Graph.Tree(15, 2, TREE_IN) hsc = g.hub_score() self.assertAlmostEqual(max(hsc), 1.0, places=3) hsc, ev = g.hub_score(scale=False, return_eigenvalue=True) - if hsc[0]<0: hsc = [-x for x in hsc] + if hsc[0] < 0: + hsc = [-x for x in hsc] def testCoreness(self): - g = Graph.Full(4) + Graph(4) + [(0,4), (1,5), (2,6), (3,7)] - self.assertEqual(g.coreness("A"), [3,3,3,3,1,1,1,1]) + g = Graph.Full(4) + Graph(4) + [(0, 4), (1, 5), (2, 6), (3, 7)] + self.assertEqual(g.coreness("A"), [3, 3, 3, 3, 1, 1, 1, 1]) class NeighborhoodTests(unittest.TestCase): def testNeighborhood(self): g = Graph.Ring(10, circular=False) - self.assertTrue(list(map(sorted, g.neighborhood())) == \ - [[0,1], [0,1,2], [1,2,3], [2,3,4], [3,4,5], [4,5,6], \ - [5,6,7], [6,7,8], [7,8,9], [8,9]]) - self.assertTrue(list(map(sorted, g.neighborhood(order=3))) == \ - [[0,1,2,3], [0,1,2,3,4], [0,1,2,3,4,5], [0,1,2,3,4,5,6], \ - [1,2,3,4,5,6,7], [2,3,4,5,6,7,8], [3,4,5,6,7,8,9], \ - [4,5,6,7,8,9], [5,6,7,8,9], [6,7,8,9]]) - self.assertTrue(list(map(sorted, g.neighborhood(order=3, mindist=2))) == \ - [[2,3], [3,4], [0,4,5], [0,1,5,6], \ - [1,2,6,7], [2,3,7,8], [3,4,8,9], \ - [4,5,9], [5,6], [6,7]]) + self.assertTrue( + list(map(sorted, g.neighborhood())) + == [ + [0, 1], + [0, 1, 2], + [1, 2, 3], + [2, 3, 4], + [3, 4, 5], + [4, 5, 6], + [5, 6, 7], + [6, 7, 8], + [7, 8, 9], + [8, 9], + ] + ) + self.assertTrue( + list(map(sorted, g.neighborhood(order=3))) + == [ + [0, 1, 2, 3], + [0, 1, 2, 3, 4], + [0, 1, 2, 3, 4, 5], + [0, 1, 2, 3, 4, 5, 6], + [1, 2, 3, 4, 5, 6, 7], + [2, 3, 4, 5, 6, 7, 8], + [3, 4, 5, 6, 7, 8, 9], + [4, 5, 6, 7, 8, 9], + [5, 6, 7, 8, 9], + [6, 7, 8, 9], + ] + ) + self.assertTrue( + list(map(sorted, g.neighborhood(order=3, mindist=2))) + == [ + [2, 3], + [3, 4], + [0, 4, 5], + [0, 1, 5, 6], + [1, 2, 6, 7], + [2, 3, 7, 8], + [3, 4, 8, 9], + [4, 5, 9], + [5, 6], + [6, 7], + ] + ) def testNeighborhoodSize(self): g = Graph.Ring(10, circular=False) - self.assertTrue(g.neighborhood_size() == [2,3,3,3,3,3,3,3,3,2]) - self.assertTrue(g.neighborhood_size(order=3) == [4,5,6,7,7,7,7,6,5,4]) - self.assertTrue(g.neighborhood_size(order=3, mindist=2) == \ - [2,2,3,4,4,4,4,3,2,2]) + self.assertTrue(g.neighborhood_size() == [2, 3, 3, 3, 3, 3, 3, 3, 3, 2]) + self.assertTrue(g.neighborhood_size(order=3) == [4, 5, 6, 7, 7, 7, 7, 6, 5, 4]) + self.assertTrue( + g.neighborhood_size(order=3, mindist=2) == [2, 2, 3, 4, 4, 4, 4, 3, 2, 2] + ) class MiscTests(unittest.TestCase): @@ -382,10 +472,10 @@ def testBridges(self): self.assertTrue(g.bridges() == [3]) g = Graph(3, [(0, 1), (1, 2), (2, 3)]) self.assertTrue(g.bridges() == [0, 1, 2]) - + def testConstraint(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) - self.assertTrue(isinstance(g.constraint(), list)) # TODO check more + self.assertTrue(isinstance(g.constraint(), list)) # TODO check more def testTopologicalSorting(self): g = Graph(5, [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], directed=True) @@ -410,7 +500,9 @@ def testLineGraph(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) el = g.linegraph().get_edgelist() el.sort() - self.assertTrue(el == [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (2, 4), (3, 4)]) + self.assertTrue( + el == [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (2, 4), (3, 4)] + ) g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)], directed=True) el = g.linegraph().get_edgelist() @@ -420,31 +512,56 @@ def testLineGraph(self): class PathTests(unittest.TestCase): def testShortestPaths(self): - g = Graph(10, [(0,1), (0,2), (0,3), (1,2), (1,4), (1,5), (2,3), (2,6), \ - (3,2), (3,6), (4,5), (4,7), (5,6), (5,8), (5,9), (7,5), (7,8), \ - (8,9), (5,2), (2,1)], directed=True) - ws = [0,2,1,0,5,2,1,1,0,2,2,8,1,1,3,1,1,4,2,1] + g = Graph( + 10, + [ + (0, 1), + (0, 2), + (0, 3), + (1, 2), + (1, 4), + (1, 5), + (2, 3), + (2, 6), + (3, 2), + (3, 6), + (4, 5), + (4, 7), + (5, 6), + (5, 8), + (5, 9), + (7, 5), + (7, 8), + (8, 9), + (5, 2), + (2, 1), + ], + directed=True, + ) + ws = [0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1] g.es["weight"] = ws - inf = float('inf') + inf = float("inf") expected = [ - [0, 0, 0, 1, 5, 2, 1, 13, 3, 5], - [inf, 0, 0, 1, 5, 2, 1, 13, 3, 5], - [inf, 1, 0, 1, 6, 3, 1, 14, 4, 6], - [inf, 1, 0, 0, 6, 3, 1, 14, 4, 6], - [inf, 5, 4, 5, 0, 2, 3, 8, 3, 5], - [inf, 3, 2, 3, 8, 0, 1, 16, 1, 3], - [inf, inf, inf, inf, inf, inf, 0, inf, inf, inf], - [inf, 4, 3, 4, 9, 1, 2, 0, 1, 4], - [inf, inf, inf, inf, inf, inf, inf, inf, 0, 4], - [inf, inf, inf, inf, inf, inf, inf, inf, inf, 0] + [0, 0, 0, 1, 5, 2, 1, 13, 3, 5], + [inf, 0, 0, 1, 5, 2, 1, 13, 3, 5], + [inf, 1, 0, 1, 6, 3, 1, 14, 4, 6], + [inf, 1, 0, 0, 6, 3, 1, 14, 4, 6], + [inf, 5, 4, 5, 0, 2, 3, 8, 3, 5], + [inf, 3, 2, 3, 8, 0, 1, 16, 1, 3], + [inf, inf, inf, inf, inf, inf, 0, inf, inf, inf], + [inf, 4, 3, 4, 9, 1, 2, 0, 1, 4], + [inf, inf, inf, inf, inf, inf, inf, inf, 0, 4], + [inf, inf, inf, inf, inf, inf, inf, inf, inf, 0], ] self.assertTrue(g.shortest_paths(weights=ws) == expected) self.assertTrue(g.shortest_paths(weights="weight") == expected) - self.assertTrue(g.shortest_paths(weights="weight", target=[2,3]) == - [row[2:4] for row in expected]) + self.assertTrue( + g.shortest_paths(weights="weight", target=[2, 3]) + == [row[2:4] for row in expected] + ) def testGetShortestPaths(self): - g = Graph(4, [(0,1), (0,2), (1,3), (3,2), (2,1)], directed=True) + g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) sps = g.get_shortest_paths(0) expected = [[0], [0, 1], [0, 2], [0, 1, 3]] self.assertTrue(sps == expected) @@ -457,7 +574,7 @@ def testGetShortestPaths(self): self.assertRaises(ValueError, g.get_shortest_paths, 0, output="x") def testGetAllShortestPaths(self): - g = Graph(4, [(0,1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)], directed=True) + g = Graph(4, [(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)], directed=True) sps = sorted(g.get_all_shortest_paths(0, 0)) expected = [[0]] @@ -474,28 +591,40 @@ def testGetAllShortestPaths(self): g = Graph.Lattice([5, 5], circular=False) sps = sorted(g.get_all_shortest_paths(0, 12)) - expected = [[0, 1, 2, 7, 12], [0, 1, 6, 7, 12], [0, 1, 6, 11, 12], \ - [0, 5, 6, 7, 12], [0, 5, 6, 11, 12], [0, 5, 10, 11, 12]] + expected = [ + [0, 1, 2, 7, 12], + [0, 1, 6, 7, 12], + [0, 1, 6, 11, 12], + [0, 5, 6, 7, 12], + [0, 5, 6, 11, 12], + [0, 5, 10, 11, 12], + ] self.assertEqual(expected, sps) g = Graph.Lattice([100, 100], circular=False) sps = sorted(g.get_all_shortest_paths(0, 202)) - expected = [[0, 1, 2, 102, 202], [0, 1, 101, 102, 202], [0, 1, 101, 201, 202], \ - [0, 100, 101, 102, 202], [0, 100, 101, 201, 202], [0, 100, 200, 201, 202]] + expected = [ + [0, 1, 2, 102, 202], + [0, 1, 101, 102, 202], + [0, 1, 101, 201, 202], + [0, 100, 101, 102, 202], + [0, 100, 101, 201, 202], + [0, 100, 200, 201, 202], + ] self.assertEqual(expected, sps) g = Graph.Lattice([100, 100], circular=False) sps = sorted(g.get_all_shortest_paths(0, [0, 202])) self.assertEqual([[0]] + expected, sps) - g = Graph([(0,1), (1,2), (0,2)]) + g = Graph([(0, 1), (1, 2), (0, 2)]) g.es["weight"] = [0.5, 0.5, 1] sps = sorted(g.get_all_shortest_paths(0, weights="weight")) - self.assertEqual([[0], [0,1], [0,1,2], [0,2]], sps) + self.assertEqual([[0], [0, 1], [0, 1, 2], [0, 2]], sps) g = Graph.Lattice([4, 4], circular=False) g.es["weight"] = 1 - g.es[2,8]["weight"] = 100 + g.es[2, 8]["weight"] = 100 sps = sorted(g.get_all_shortest_paths(0, [3, 12, 15], weights="weight")) self.assertEqual(20, len(sps)) self.assertEqual(4, sum(1 for path in sps if path[-1] == 3)) @@ -505,21 +634,27 @@ def testGetAllShortestPaths(self): def testGetAllSimplePaths(self): g = Graph.Ring(20) sps = sorted(g.get_all_simple_paths(0, 10)) - self.assertEqual([ - [0,1,2,3,4,5,6,7,8,9,10], - [0,19,18,17,16,15,14,13,12,11,10] - ], sps) + self.assertEqual( + [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + [0, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10], + ], + sps, + ) g = Graph.Ring(20, directed=True) sps = sorted(g.get_all_simple_paths(0, 10)) - self.assertEqual([ [0,1,2,3,4,5,6,7,8,9,10] ], sps) + self.assertEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]], sps) sps = sorted(g.get_all_simple_paths(0, 10, mode="in")) - self.assertEqual([ [0,19,18,17,16,15,14,13,12,11,10] ], sps) + self.assertEqual([[0, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10]], sps) sps = sorted(g.get_all_simple_paths(0, 10, mode="all")) - self.assertEqual([ - [0,1,2,3,4,5,6,7,8,9,10], - [0,19,18,17,16,15,14,13,12,11,10] - ], sps) + self.assertEqual( + [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + [0, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10], + ], + sps, + ) g = Graph.Lattice([4, 4], circular=False) g = Graph([(min(u, v), max(u, v)) for u, v in g.get_edgelist()], directed=True) @@ -537,9 +672,11 @@ def testPathLengthHist(self): g = Graph.Tree(15, 2) h = g.path_length_hist() self.assertTrue(h.unconnected == 0) - self.assertTrue([(int(l),x) for l,_,x in h.bins()] == \ - [(1,14),(2,19),(3,20),(4,20),(5,16),(6,16)]) - g = Graph.Full(5)+Graph.Full(4) + self.assertTrue( + [(int(l), x) for l, _, x in h.bins()] + == [(1, 14), (2, 19), (3, 20), (4, 20), (5, 16), (6, 16)] + ) + g = Graph.Full(5) + Graph.Full(4) h = g.path_length_hist() self.assertTrue(h.unconnected == 20) g.to_directed() @@ -548,11 +685,12 @@ def testPathLengthHist(self): h = g.path_length_hist(False) self.assertTrue(h.unconnected == 20) + class DominatorTests(unittest.TestCase): def compareDomTrees(self, alist, blist): - ''' + """ Required due to NaN use for isolated nodes - ''' + """ if len(alist) != len(blist): return False for i, (a, b) in enumerate(zip(alist, blist)): @@ -568,28 +706,119 @@ def testDominators(self): # examples taken from igraph's examples/simple/dominator_tree.out # initial - g = Graph(13, [(0,1), (0,7), (0,10), (1,2), (1,5), (2,3), (3,4), (4,3), - (4,0), (5,3), (5,6), (6,3), (7,8), (7,10), (7,11), (8,9), (9,4), - (9,8), (10,11), (11,12), (12,9) ], directed=True) - s = [-1, 0, 1, 0, 0, 1, 5, 0, 0, 0, 0, 0, 11 ] + g = Graph( + 13, + [ + (0, 1), + (0, 7), + (0, 10), + (1, 2), + (1, 5), + (2, 3), + (3, 4), + (4, 3), + (4, 0), + (5, 3), + (5, 6), + (6, 3), + (7, 8), + (7, 10), + (7, 11), + (8, 9), + (9, 4), + (9, 8), + (10, 11), + (11, 12), + (12, 9), + ], + directed=True, + ) + s = [-1, 0, 1, 0, 0, 1, 5, 0, 0, 0, 0, 0, 11] r = g.dominator(0) self.assertTrue(self.compareDomTrees(s, r)) # flipped edges - g = Graph(13, [(1,0), (2,0), (3,0), (4,1), (1,2), (4,2), (5,2), (6,3), - (7,3), (12,4), (8,5), (9,6), (9,7), (10,7), (5,8), (11,8), - (11,9), (9,10), (9,11), (0,11), (8,12)], directed=True) + g = Graph( + 13, + [ + (1, 0), + (2, 0), + (3, 0), + (4, 1), + (1, 2), + (4, 2), + (5, 2), + (6, 3), + (7, 3), + (12, 4), + (8, 5), + (9, 6), + (9, 7), + (10, 7), + (5, 8), + (11, 8), + (11, 9), + (9, 10), + (9, 11), + (0, 11), + (8, 12), + ], + directed=True, + ) s = [-1, 0, 0, 0, 0, 0, 3, 3, 0, 0, 7, 0, 4] r = g.dominator(0, mode=IN) self.assertTrue(self.compareDomTrees(s, r)) # disconnected components - g = Graph(20, [(0,1), (0,2), (0,3), (1,4), (2,1), (2,4), (2,8), (3,9), - (3,10), (4,15), (8,11), (9,12), (10,12), (10,13), (11,8), - (11,14), (12,14), (13,12), (14,12), (14,0), (15,11)], - directed=True) - s = [-1, 0, 0, 0, 0, float("nan"), float("nan"), float("nan"), 0, 3, 3, 0, - 0, 10, 0, 4, float("nan"), float("nan"), float("nan"), float("nan")] + g = Graph( + 20, + [ + (0, 1), + (0, 2), + (0, 3), + (1, 4), + (2, 1), + (2, 4), + (2, 8), + (3, 9), + (3, 10), + (4, 15), + (8, 11), + (9, 12), + (10, 12), + (10, 13), + (11, 8), + (11, 14), + (12, 14), + (13, 12), + (14, 12), + (14, 0), + (15, 11), + ], + directed=True, + ) + s = [ + -1, + 0, + 0, + 0, + 0, + float("nan"), + float("nan"), + float("nan"), + 0, + 3, + 3, + 0, + 0, + 10, + 0, + 4, + float("nan"), + float("nan"), + float("nan"), + float("nan"), + ] r = g.dominator(0, mode=OUT) self.assertTrue(self.compareDomTrees(s, r)) @@ -604,20 +833,25 @@ def suite(): path_suite = unittest.makeSuite(PathTests) misc_suite = unittest.makeSuite(MiscTests) dominator_suite = unittest.makeSuite(DominatorTests) - return unittest.TestSuite([simple_suite, - degree_suite, - local_transitivity_suite, - biconnected_suite, - centrality_suite, - neighborhood_suite, - path_suite, - misc_suite, - dominator_suite]) + return unittest.TestSuite( + [ + simple_suite, + degree_suite, + local_transitivity_suite, + biconnected_suite, + centrality_suite, + neighborhood_suite, + path_suite, + misc_suite, + dominator_suite, + ] + ) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) + if __name__ == "__main__": test() - diff --git a/tests/test_unicode_issues.py b/tests/test_unicode_issues.py index 3dccdc48b..543f871e5 100644 --- a/tests/test_unicode_issues.py +++ b/tests/test_unicode_issues.py @@ -1,27 +1,27 @@ -from __future__ import unicode_literals - import unittest from igraph import Graph + class UnicodeTests(unittest.TestCase): def testBug128(self): y = [1, 4, 9] - g = Graph(n=len(y), directed=True, vertex_attrs={'y': y}) + g = Graph(n=len(y), directed=True, vertex_attrs={"y": y}) self.assertEqual(3, g.vcount()) g.add_vertices(1) # Bug #128 would prevent us from reaching the next statement # because an exception would have been thrown here self.assertEqual(4, g.vcount()) - + def suite(): generator_suite = unittest.makeSuite(UnicodeTests) return unittest.TestSuite([generator_suite]) + def test(): runner = unittest.TextTestRunner() runner.run(suite()) - + + if __name__ == "__main__": test() - diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 2d085413c..a359cc9aa 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -77,7 +77,7 @@ def testIncident(self): for i in range(g.vcount()): vertex = g.vs[i] - for mode, method_name in method_table.items(): + for mode, method_name in list(method_table.items()): method = getattr(vertex, method_name) self.assertEqual( g.incident(i, mode=mode), @@ -156,7 +156,7 @@ def testProxyMethods(self): class VertexSeqTests(unittest.TestCase): def setUp(self): self.g = Graph.Full(10) - self.g.vs["test"] = range(10) + self.g.vs["test"] = list(range(10)) self.g.vs["name"] = list("ABCDEFGHIJ") def testCreation(self): @@ -204,7 +204,7 @@ def testPartialAttributeAssignment(self): only_even = self.g.vs.select(lambda v: (v.index % 2 == 0)) only_even["test"] = [0] * len(only_even) self.assertTrue(self.g.vs["test"] == [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]) - only_even["test2"] = range(5) + only_even["test2"] = list(range(5)) self.assertTrue( self.g.vs["test2"] == [0, None, 1, None, 2, None, 3, None, 4, None] ) @@ -293,7 +293,7 @@ def testStringFilteringFind(self): self.assertRaises(ValueError, self.g.vs.find, "NoSuchName") def testIterableFilteringSelect(self): - subset = self.g.vs.select(range(5, 8)) + subset = self.g.vs.select(list(range(5, 8))) self.assertTrue(len(subset) == 3) self.assertTrue(subset["test"] == [5, 6, 7]) diff --git a/tests/test_walks.py b/tests/test_walks.py index 8386bdecd..51a67de4e 100644 --- a/tests/test_walks.py +++ b/tests/test_walks.py @@ -16,7 +16,7 @@ def validate_walk(self, g, walk, start, length, mode="out"): def testRandomWalkUndirected(self): g = Graph.GRG(100, 0.2) for i in range(100): - start = random.randint(0, g.vcount()-1) + start = random.randint(0, g.vcount() - 1) length = random.randint(0, 10) walk = g.random_walk(start, length) self.validate_walk(g, walk, start, length) @@ -34,7 +34,7 @@ def testRandomWalkDirectedIn(self): g = Graph.Tree(121, 3, mode="out") mode = "in" for i in range(100): - start = random.randint(40, g.vcount()-1) + start = random.randint(40, g.vcount() - 1) length = random.randint(0, 4) walk = g.random_walk(start, length, mode) self.validate_walk(g, walk, start, length, mode) @@ -43,7 +43,7 @@ def testRandomWalkDirectedAll(self): g = Graph.Tree(121, 3, mode="out") mode = "all" for i in range(100): - start = random.randint(0, g.vcount()-1) + start = random.randint(0, g.vcount() - 1) length = random.randint(0, 10) walk = g.random_walk(start, length, mode) self.validate_walk(g, walk, start, length, mode) diff --git a/tests/utils.py b/tests/utils.py index 82b951a54..8bfbc88d4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -16,14 +16,17 @@ def _id(obj): return obj + try: from unittest import skip except ImportError: # Provide basic replacement for unittest.skip def skip(reason): """Unconditionally skip a test.""" + def decorator(test_item): - if not isinstance(test_item, (type, types.ClassType)): + if not isinstance(test_item, type): + @functools.wraps(test_item) def skip_wrapper(*args, **kwds): if reason: @@ -31,10 +34,13 @@ def skip_wrapper(*args, **kwds): else: sys.stderr.write("skipped, ") return + test_item = skip_wrapper return test_item + return decorator + try: from unittest import skipIf except ImportError: @@ -69,4 +75,4 @@ def temporary_file(content=None, mode=None, binary=False): os.unlink(tmpfname) -is_pypy = (platform.python_implementation() == "PyPy") +is_pypy = platform.python_implementation() == "PyPy" From 3455e2f62f6695ab18b2530d9e32444cacaa8aff Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 15 Jan 2021 21:23:29 +1100 Subject: [PATCH 0301/1892] Python 3.6 is the oldest support --- README.md | 4 +--- setup.py | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a084ce5e4..b89b58c09 100644 --- a/README.md +++ b/README.md @@ -163,9 +163,7 @@ of the non-EOL Python versions. Continuous integration tests are regularly executed on all non-EOL Python branches. -As for Python 2.x, the latest branch of `python-igraph` that supports Python 2 -is the 0.8.x series. Python 2 support will be dropped with the release of -`python-igraph` 0.9. +Python 2 support has been dropped with the release of `python-igraph` 0.9. ### PyPy diff --git a/setup.py b/setup.py index f92ddda81..df8bbbe35 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,8 @@ ########################################################################### # Check Python's version info and exit early if it is too old -if sys.version_info < (3, 5): - print("This module requires Python >= 3.5") +if sys.version_info < (3, 6): + print("This module requires Python >= 3.6") sys.exit(0) # Check whether we are compiling for PyPy. Headers will not be installed @@ -913,10 +913,10 @@ def use_educated_guess(self): "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics", From 41bbd12878e1e2dfbe9c96f0b79fa5baa8406ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 20 Jan 2021 10:38:02 +0100 Subject: [PATCH 0302/1892] drop PyPy2.7 from appveyor.yml --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4e3ee3605..27bad4eb4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,13 +10,13 @@ environment: matrix: - CIBW_BUILD: "*-win32" - CIBW_SKIP: "cp27-* cp35-*" + CIBW_SKIP: "pp27-* cp27-* cp35-*" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" - CIBW_BUILD: "*-win_amd64" - CIBW_SKIP: "cp27-* cp35-*" + CIBW_SKIP: "pp27-* cp27-* cp35-*" MSYSTEM: MINGW64 PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x64" From e30de8dab8299a4485ad9d607d3523213d9a726e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 20 Jan 2021 10:38:30 +0100 Subject: [PATCH 0303/1892] drop Python 2.7 from travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d4b4da247..8265b24c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ dist: bionic language: python python: - - "2.7" - "3.6" - "3.7" - "3.8" From 82b97c9a215ff75c40bacd6a4c02ebc3a5e929c5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Jan 2021 11:54:30 +0100 Subject: [PATCH 0304/1892] fix: changed default splitting heuristics of BLISS, see igraph/igraph#1170 --- src/_igraph/graphobject.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 1cc937635..535c324b7 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8318,7 +8318,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( PyObject *sh_o = Py_None; PyObject *color_o = Py_None; PyObject *list; - igraph_bliss_sh_t sh = IGRAPH_BLISS_FM; + igraph_bliss_sh_t sh = IGRAPH_BLISS_FL; igraph_vector_t labeling; igraph_vector_int_t *color = 0; int retval; @@ -8444,7 +8444,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, PyObject *color1_o=Py_None, *color2_o=Py_None; igraphmodule_GraphObject *other; igraph_vector_t mapping_12, mapping_21, *map12=0, *map21=0; - igraph_bliss_sh_t sh1=IGRAPH_BLISS_FM, sh2=IGRAPH_BLISS_FM; + igraph_bliss_sh_t sh1=IGRAPH_BLISS_FL, sh2=IGRAPH_BLISS_FL; igraph_vector_int_t *color1=0, *color2=0; int retval; @@ -14745,7 +14745,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"canonical_permutation", (PyCFunction) igraphmodule_Graph_canonical_permutation, METH_VARARGS | METH_KEYWORDS, - "canonical_permutation(sh=\"fm\", color=None)\n\n" + "canonical_permutation(sh=\"fl\", color=None)\n\n" "Calculates the canonical permutation of a graph using the BLISS isomorphism\n" "algorithm.\n\n" "Passing the permutation returned here to L{Graph.permute_vertices()} will\n" @@ -14800,7 +14800,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"isomorphic_bliss", (PyCFunction) igraphmodule_Graph_isomorphic_bliss, METH_VARARGS | METH_KEYWORDS, "isomorphic_bliss(other, return_mapping_12=False, return_mapping_21=False,\n" - " sh1=\"fm\", sh2=None, color1=None, color2=None)\n\n" + " sh1=\"fl\", sh2=None, color1=None, color2=None)\n\n" "Checks whether the graph is isomorphic to another graph, using the\n" "BLISS isomorphism algorithm.\n\n" "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" From b5423257daa3793b79e3340ff859251fb27c404e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 22 Jan 2021 09:43:39 +1100 Subject: [PATCH 0305/1892] Rebase on top of master, which abandons Python 2 --- src/igraph/__init__.py | 71 +++++++++++++++++++++++++++++++++++++- tests/test_foreign.py | 78 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index c87bfa415..6f05e44ac 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -53,7 +53,6 @@ import operator from collections import defaultdict - from shutil import copyfileobj from warnings import warn @@ -3410,6 +3409,76 @@ def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): return g + def get_vertex_dataframe(self): + """Export vertices with attributes to pandas.DataFrame + + @return: a pandas.DataFrame representing vertices and their attributes. + The index uses vertex IDs, from 0 to N - 1 where N is the number of + vertices. + + If you want to use vertex names as index, you can do: + + >>> df = graph.get_vertex_dataframe() + >>> df.set_index('name', inplace=True) + + """ + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + + df = pd.DataFrame( + {attr: self.vs[attr] for attr in self.vertex_attributes()}, + index=list(range(self.vcount())), + ) + df.index.name = "vertex ID" + + return df + + def get_edge_dataframe(self): + """Export edges with attributes to pandas.DataFrame + + @return: a pandas.DataFrame representing edges and their attributes. + The index uses edge IDs, from 0 to M - 1 where M is the number of + edges. The first two columns of the dataframe represent the IDs of + source and target vertices for each edge. These columns have names + "source" and "target". If your edges have attributes with the same + names, they will be present in the dataframe, but not in the first + two columns. + + If you want to use source and target vertex IDs as index, you can do: + + >>> df = graph.get_edge_dataframe() + >>> df.set_index(['source', 'target'], inplace=True) + + The index will be a pandas.MultiIndex. You can use the `drop=False` + option to keep the `source` and `target` columns. + + If you want to use vertex names in the source and target columns: + + >>> df = graph.get_edge_dataframe() + >>> df_vert = graph.get_vertex_dataframe() + >>> df['source'].replace(df_vert['name'], inplace=True) + >>> df['target'].replace(df_vert['name'], inplace=True) + >>> df_vert.set_index('name', inplace=True) # Optional + + """ + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + + df = pd.DataFrame( + {attr: self.es[attr] for attr in self.edge_attributes()}, + index=list(range(self.ecount())), + ) + df.index.name = "edge ID" + + df.insert(0, "source", [e.source for e in self.es], allow_duplicates=True) + df.insert(1, "target", [e.target for e in self.es], allow_duplicates=True) + + return df + def bipartite_projection( self, types="type", multiplicity=True, probe1=-1, which="both" ): diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 8f2ace5d0..ec754f50d 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -335,6 +335,84 @@ def testPickle(self): self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) + @skipIf(pd is None, "test case depends on Pandas") + def testVertexDataFrames(self): + g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) + + # No vertex names, no attributes + df = g.get_vertex_dataframe() + self.assertEqual(df.shape, (5, 0)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + + # Vertex names, no attributes + g.vs["name"] = ["eggs", "spam", "ham", "bacon", "yello"] + df = g.get_vertex_dataframe() + self.assertEqual(df.shape, (5, 1)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(list(df["name"]), g.vs["name"]) + self.assertEqual(list(df.columns), ["name"]) + + # Vertex names and attributes (common case) + g.vs["weight"] = [0, 5, 1, 4, 42] + df = g.get_vertex_dataframe() + self.assertEqual(df.shape, (5, 2)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(list(df["name"]), g.vs["name"]) + self.assertEqual(set(df.columns), set(["name", "weight"])) + self.assertEqual(list(df["weight"]), g.vs["weight"]) + + # No vertex names, with attributes (common case) + g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) + g.vs["weight"] = [0, 5, 1, 4, 42] + df = g.get_vertex_dataframe() + self.assertEqual(df.shape, (5, 1)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(list(df.columns), ["weight"]) + self.assertEqual(list(df["weight"]), g.vs["weight"]) + + @skipIf(pd is None, "test case depends on Pandas") + def testEdgeDataFrames(self): + g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) + + # No edge names, no attributes + df = g.get_edge_dataframe() + self.assertEqual(df.shape, (5, 2)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(list(df.columns), ["source", "target"]) + + # Edge names, no attributes + g.es["name"] = ["my", "list", "of", "five", "edges"] + df = g.get_edge_dataframe() + self.assertEqual(df.shape, (5, 3)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(list(df["name"]), g.es["name"]) + self.assertEqual(set(df.columns), set(["source", "target", "name"])) + + # No edge names, with attributes + g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) + g.es["weight"] = [6, -0.4, 0, 1, 3] + df = g.get_edge_dataframe() + self.assertEqual(df.shape, (5, 3)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual(set(df.columns), set(["source", "target", "weight"])) + self.assertEqual(list(df["weight"]), g.es["weight"]) + + # Edge names, with weird attributes + g.es["name"] = ["my", "list", "of", "five", "edges"] + g.es["weight"] = [6, -0.4, 0, 1, 3] + g.es["source"] = ["this", "is", "a", "little", "tricky"] + df = g.get_edge_dataframe() + self.assertEqual(df.shape, (5, 5)) + self.assertEqual(list(df.index), [0, 1, 2, 3, 4]) + self.assertEqual( + set(df.columns), set(["source", "target", "name", "source", "weight"]) + ) + self.assertEqual(list(df["name"]), g.es["name"]) + self.assertEqual(list(df["weight"]), g.es["weight"]) + + i = 2 + list(df.columns[2:]).index("source") + self.assertEqual(list(df.iloc[:, i]), g.es["source"]) + def suite(): foreign_suite = unittest.makeSuite(ForeignTests) From 90e8910f847087bfed577adddb522cd434656ada Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 21 Jan 2021 09:57:27 +1100 Subject: [PATCH 0306/1892] Tests for new index-only API --- appveyor.yml | 3 +++ tests/test_foreign.py | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 27bad4eb4..dca9b2d48 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,6 +38,9 @@ install: # install cibuildwheel - pip install cibuildwheel==1.6.1 + # install pandas (optional) + - pip install pandas + before_build: - git submodule update --init --recursive diff --git a/tests/test_foreign.py b/tests/test_foreign.py index ec754f50d..fc3d2ec69 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -4,7 +4,12 @@ from igraph import * -from .utils import temporary_file +from .utils import temporary_file, skipIf + +try: + import pandas as pd +except ImportError: + pd = None class ForeignTests(unittest.TestCase): From e1683ec2cd3053d02248d066a3994aa7ed40dcc9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 25 Jan 2021 13:12:16 +0100 Subject: [PATCH 0307/1892] fix: bringing codebase up-to-date with the develop branch of the C core --- setup.py | 2 +- src/_igraph/convert.c | 1 - src/_igraph/graphobject.c | 71 ++++++++++++++++++++++++--------------- tests/test_attributes.py | 14 +++----- vendor/source/igraph | 1 - 5 files changed, 49 insertions(+), 40 deletions(-) delete mode 160000 vendor/source/igraph diff --git a/setup.py b/setup.py index df8bbbe35..fd9b18fcf 100644 --- a/setup.py +++ b/setup.py @@ -808,7 +808,7 @@ def use_vendored_igraph(self): the include and library paths and the library names accordingly.""" building_on_windows = building_on_windows_msvc() - buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include")] + buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include", "igraph")] buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 1dcb2ec1f..4b050b550 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3047,7 +3047,6 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, static igraphmodule_enum_translation_table_entry_t pagerank_algo_tt[] = { {"prpack", IGRAPH_PAGERANK_ALGO_PRPACK}, {"arpack", IGRAPH_PAGERANK_ALGO_ARPACK}, - {"power", IGRAPH_PAGERANK_ALGO_POWER}, {0,0} }; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 535c324b7..51fee242b 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1563,7 +1563,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, igraph_vector_destroy(weights); free(weights); return PyFloat_FromDouble((double)i); } else { - igraph_integer_t i; + igraph_real_t i; if (igraph_diameter(&self->g, &i, 0, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); @@ -1628,8 +1628,8 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, PyObject *dir = Py_True, *vcount_if_unconnected = Py_True; PyObject *weights_o = Py_None; igraph_vector_t *weights = 0; - igraph_integer_t from, to, len; - igraph_real_t len_real; + igraph_integer_t from, to; + igraph_real_t len; static char *kwlist[] = { "directed", "unconn", "weights", NULL }; @@ -1642,7 +1642,7 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { - if (igraph_diameter_dijkstra(&self->g, weights, &len_real, &from, &to, 0, + if (igraph_diameter_dijkstra(&self->g, weights, &len, &from, &to, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); @@ -1650,8 +1650,8 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, } igraph_vector_destroy(weights); free(weights); if (from >= 0) - return Py_BuildValue("lld", (long)from, (long)to, (double)len_real); - return Py_BuildValue("OOd", Py_None, Py_None, (double)len_real); + return Py_BuildValue("lld", (long)from, (long)to, (double)len); + return Py_BuildValue("OOd", Py_None, Py_None, (double)len); } else { if (igraph_diameter(&self->g, &len, &from, &to, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { @@ -3657,7 +3657,7 @@ PyObject *igraphmodule_Graph_average_path_length(igraphmodule_GraphObject * &PyBool_Type, &unconn)) return NULL; - if (igraph_average_path_length(&self->g, &res, (directed == Py_True), + if (igraph_average_path_length(&self->g, &res, 0, (directed == Py_True), (unconn == Py_True))) { igraphmodule_handle_igraph_error(); return NULL; @@ -5092,7 +5092,6 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel PyObject *algo_o = Py_None; long niter=1000; float eps=0.001f; - igraph_pagerank_power_options_t popts; void *opts; int retval; @@ -5150,11 +5149,7 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel if (igraphmodule_PyObject_to_pagerank_algo_t(algo_o, &algo)) return NULL; - popts.niter = (igraph_integer_t) niter; popts.eps = eps; - - if (algo == IGRAPH_PAGERANK_ALGO_POWER) { - opts = &popts; - } else if (algo == IGRAPH_PAGERANK_ALGO_ARPACK) { + if (algo == IGRAPH_PAGERANK_ALGO_ARPACK) { opts = igraphmodule_ARPACKOptions_get(arpack_options); } else { opts = 0; @@ -11030,13 +11025,15 @@ PyObject *igraphmodule_Graph_coreness(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"membership", "weights", 0}; + static char *kwlist[] = {"membership", "weights", "resolution", "directed", 0}; igraph_vector_t membership; igraph_vector_t *weights=0; + double resolution; igraph_real_t modularity; PyObject *mvec, *wvec=Py_None; + PyObject *directed = Py_True; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &mvec, &wvec)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OdO", kwlist, &mvec, &wvec, &resolution, &directed)) return NULL; if (igraphmodule_PyObject_to_vector_t(mvec, &membership, 1)) @@ -11046,13 +11043,20 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, igraph_vector_destroy(&membership); return NULL; } - if (igraph_modularity(&self->g, &membership, &modularity, weights)) { + + if (igraph_modularity(&self->g, &membership, weights, resolution, PyObject_IsTrue(directed), &modularity)) { igraph_vector_destroy(&membership); - if (weights) { igraph_vector_destroy(weights); free(weights); } + if (weights) { + igraph_vector_destroy(weights); free(weights); + } return NULL; } + igraph_vector_destroy(&membership); - if (weights) { igraph_vector_destroy(weights); free(weights); } + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + return Py_BuildValue("d", (double)modularity); } @@ -11397,14 +11401,15 @@ PyObject *igraphmodule_Graph_community_label_propagation( PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = { "weights", "return_levels", NULL }; + static char *kwlist[] = { "weights", "return_levels", "resolution", NULL }; PyObject *return_levels = Py_False; PyObject *mss, *qs, *res, *weights = Py_None; igraph_matrix_t memberships; igraph_vector_t membership, modularity; + double resolution; igraph_vector_t *ws; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &weights, &return_levels)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOd", kwlist, &weights, &return_levels, &resolution)) { return NULL; } @@ -11415,7 +11420,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self igraph_vector_init(&membership, 0); igraph_vector_init(&modularity, 0); - if (igraph_community_multilevel(&self->g, ws, &membership, &memberships, + if (igraph_community_multilevel(&self->g, ws, resolution, &membership, &memberships, &modularity)) { if (ws) { igraph_vector_destroy(ws); free(ws); } igraph_vector_destroy(&membership); @@ -15474,16 +15479,17 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*********************************/ {"modularity", (PyCFunction) igraphmodule_Graph_modularity, METH_VARARGS | METH_KEYWORDS, - "modularity(membership, weights=None)\n\n" + "modularity(membership, weights=None, resolution=1, directed=True)\n\n" "Calculates the modularity of the graph with respect to some vertex types.\n\n" "The modularity of a graph w.r.t. some division measures how good the\n" "division is, or how separated are the different vertex types from each\n" - "other. It is defined as M{Q=1/(2m) * sum(Aij-ki*kj/(2m)delta(ci,cj),i,j)}.\n" + "other. It is defined as M{Q=1/(2m) * sum(Aij-gamma*ki*kj/(2m)delta(ci,cj),i,j)}.\n" "M{m} is the number of edges, M{Aij} is the element of the M{A} adjacency\n" "matrix in row M{i} and column M{j}, M{ki} is the degree of node M{i},\n" - "M{kj} is the degree of node M{j}, and M{Ci} and C{cj} are the types of\n" - "the two vertices (M{i} and M{j}). M{delta(x,y)} is one iff M{x=y}, 0\n" - "otherwise.\n\n" + "M{kj} is the degree of node M{j}, M{Ci} and C{cj} are the types of\n" + "the two vertices (M{i} and M{j}), and M{gamma} is a resolution parameter\n" + "that defaults to 1 for the classical definition of modularity. M{delta(x,y)}\n" + "is one iff M{x=y}, 0 otherwise.\n\n" "If edge weights are given, the definition of modularity is modified as\n" "follows: M{Aij} becomes the weight of the corresponding edge, M{ki}\n" "is the total weight of edges incident on vertex M{i}, M{kj} is the\n" @@ -15496,6 +15502,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " each vertex.\n" "@param weights: optional edge weights or C{None} if all edges are weighed\n" " equally.\n" + "@param resolution: the resolution parameter I{gamma} in the formula above.\n" + " The classical definition of modularity is retrieved when the resolution\n" + " parameter is set to 1.\n" + "@param directed: whether to consider edge directions if the graph is directed.\n" + " C{True} will use the directed variant of the modularity measure where the\n" + " in- and out-degrees of nodes are treated separately; C{False} will treat\n" + " directed graphs as undirected.\n" "@return: the modularity score. Score larger than 0.3 usually indicates\n" " strong community structure.\n" "@newfield ref: Reference\n" @@ -15623,7 +15636,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_multilevel", (PyCFunction) igraphmodule_Graph_community_multilevel, METH_VARARGS | METH_KEYWORDS, - "community_multilevel(weights=None, return_levels=True)\n\n" + "community_multilevel(weights=None, return_levels=True, resolution=1)\n\n" "Finds the community structure of the graph according to the multilevel\n" "algorithm of Blondel et al. This is a bottom-up algorithm: initially\n" "every vertex belongs to a separate community, and vertices are moved\n" @@ -15641,6 +15654,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param return_levels: if C{True}, returns the multilevel result. If\n" " C{False}, only the best level (corresponding to the best modularity)\n" " is returned.\n" + "@param resolution: the resolution parameter to use in the modularity measure.\n" + " Smaller values result in a smaller number of larger clusters, while higher\n" + " values yield a large number of small clusters. The classical modularity\n" + " measure assumes a resolution parameter of 1.\n" "@return: either a single list describing the community membership of each\n" " vertex (if C{return_levels} is C{False}), or a list of community membership\n" " vectors, one corresponding to each level and a list of corresponding\n" diff --git a/tests/test_attributes.py b/tests/test_attributes.py index a95c49261..4e2522f56 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -1,7 +1,8 @@ # vim:ts=4 sw=4 sts=4: import sys import unittest -from igraph import * + +from igraph import Graph class AttributeTests(unittest.TestCase): @@ -181,13 +182,6 @@ def testCombinationProd(self): self.assertTrue(g.es["weight"] == [2, 3, 120]) self.assertTrue(g.es["weight2"] == [2, 3, 120]) - def testCombinationMedian(self): - g = self.g - g.es["weight2"] = [1, 0, 2, 4, 8, 6, 7] - g.simplify(combine_edges="median") - self.assertTrue(g.es["weight"] == [1.5, 3, 5]) - self.assertTrue(g.es["weight2"] == [0.5, 2, 6]) - def testCombinationFirst(self): g = self.g g.es["weight2"] = [1, 0, 2, 6, 8, 4, 7] @@ -229,8 +223,8 @@ def testCombinationIgnoreAsNone(self): def testCombinationFunction(self): g = self.g - def join_dash(l): - return "-".join(l) + def join_dash(items): + return "-".join(items) g.es["name"] = list("ABCDEFG") g.simplify(combine_edges={"weight": max, "name": join_dash}) diff --git a/vendor/source/igraph b/vendor/source/igraph deleted file mode 160000 index cafe1e4d4..000000000 --- a/vendor/source/igraph +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cafe1e4d447dded9f640fd4f14b7973bef045d62 From 75e368aa5370b55ec65fdabb8debc2dbfe600dd9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 25 Jan 2021 13:59:17 +0100 Subject: [PATCH 0308/1892] fix: re-adding accidentally deleted submodule --- setup.py | 2 +- vendor/source/igraph | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 160000 vendor/source/igraph diff --git a/setup.py b/setup.py index fd9b18fcf..935196709 100644 --- a/setup.py +++ b/setup.py @@ -645,7 +645,7 @@ def run(self): return custom_sdist def compile_igraph_from_vendor_source(self): - """Compiles igraph from the vendored source code inside `vendor/igraph/source`. + """Compiles igraph from the vendored source code inside `vendor/source/igraph`. This folder typically comes from a git submodule. """ if os.path.exists(os.path.join("vendor", "install", "igraph")): diff --git a/vendor/source/igraph b/vendor/source/igraph new file mode 160000 index 000000000..1d422e68c --- /dev/null +++ b/vendor/source/igraph @@ -0,0 +1 @@ +Subproject commit 1d422e68c735888fff755e23912cc9dac269ce40 From 4dda6fd21c32a71f401c73ffcc6790775e9ee83b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 25 Jan 2021 16:31:18 +0100 Subject: [PATCH 0309/1892] fix: updated the interface of a few more functions according to the develop branch of igraph --- setup.py | 7 +++++-- src/_igraph/graphobject.c | 23 +++++++++-------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 935196709..d7177812f 100644 --- a/setup.py +++ b/setup.py @@ -476,10 +476,13 @@ def compile_in(self, source_folder, build_folder, install_folder): if retcode: return False + return [] + def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries ): - raise NotImplementedError + # Nothing to do; we already installed stuff in the compilation step + return True ########################################################################### @@ -690,7 +693,7 @@ def compile_igraph_from_vendor_source(self): finally: os.chdir(cwd) - if not libraries or not igraph_builder.copy_build_artifacts( + if not igraph_builder.copy_build_artifacts( source_folder=source_folder, build_folder=build_folder, install_folder=install_folder, diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 51fee242b..a9674919a 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3685,6 +3685,8 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, igraph_bool_t return_single = 0; igraph_vs_t vs; + /* nobigint is now unused but we kept here for sake of backwards compatibility */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, &directed, &cutoff, &weights_o, &nobigint)) { @@ -3707,8 +3709,7 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, } if (cutoff == Py_None) { - if (igraph_betweenness(&self->g, &res, vs, PyObject_IsTrue(directed), - weights, PyObject_IsTrue(nobigint))) { + if (igraph_betweenness(&self->g, &res, vs, PyObject_IsTrue(directed), weights)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -3724,8 +3725,7 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, return NULL; } if (igraph_betweenness_estimate(&self->g, &res, vs, PyObject_IsTrue(directed), - (igraph_real_t)PyFloat_AsDouble(cutoff_num), weights, - PyObject_IsTrue(nobigint))) { + (igraph_real_t)PyFloat_AsDouble(cutoff_num), weights)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -7078,6 +7078,9 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, PyObject *arpack_options_o = igraphmodule_arpack_options_default; PyObject *result; + /* arpack_options_o is now unused but we kept here for sake of backwards + * compatibility */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlO!", kwlist, &dist_o, &dim, &igraphmodule_ARPACKOptionsType, &arpack_options_o)) @@ -7103,9 +7106,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, return NULL; } - arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; - if (igraph_layout_mds(&self->g, &m, dist, dim, - igraphmodule_ARPACKOptions_get(arpack_options))) { + if (igraph_layout_mds(&self->g, &m, dist, dim)) { if (dist) { igraph_matrix_destroy(dist); free(dist); } @@ -12798,7 +12799,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_betweenness[_estimate] */ {"betweenness", (PyCFunction) igraphmodule_Graph_betweenness, METH_VARARGS | METH_KEYWORDS, - "betweenness(vertices=None, directed=True, cutoff=None, weights=None, nobigint=True)\n\n" + "betweenness(vertices=None, directed=True, cutoff=None, weights=None)\n\n" "Calculates or estimates the betweenness of vertices in a graph.\n\n" "Keyword arguments:\n" "@param vertices: the vertices for which the betweennesses must be returned.\n" @@ -12810,12 +12811,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" - "@param nobigint: if C{True}, igraph uses the longest available integer\n" - " type on the current platform to count shortest paths. For some large\n" - " networks that have a specific structure, the counters may overflow.\n" - " To prevent this, use C{nobigint=False}, which forces igraph to use\n" - " arbitrary precision integers at the expense of increased computation\n" - " time.\n" "@return: the (possibly estimated) betweenness of the given vertices in a list\n"}, /* interface to biconnected_components */ From 4c7e253d8544fc9535eadd0ca2f213e61798abe6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 25 Jan 2021 18:39:44 +0100 Subject: [PATCH 0310/1892] fix: link to libigraph.a statically in the CMake build --- setup.py | 20 ++++++++++++++++---- src/_igraph/graphobject.c | 1 - 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index d7177812f..addc0a5fd 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,9 @@ ########################################################################### +is_windows = platform.system() == "windows" + + def building_on_windows_msvc(): """Returns True when using the non-MinGW CPython interpreter on Windows""" return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" @@ -232,7 +235,7 @@ def wait_for_keypress(seconds): """Wait for a keypress or until the given number of seconds have passed, whichever happens first. """ - is_windows = platform.system() == "windows" + global is_windows while seconds > 0: if seconds > 1: @@ -410,11 +413,12 @@ def copy_build_artifacts( ): shutil.copy(fname, os.path.join(install_folder, "lib")) + return True + + def create_build_config_file(self, install_folder, libraries): with open(os.path.join(install_folder, "build.cfg"), "w") as f: f.write(repr(libraries)) - return True - @staticmethod def enhanced_env(**kwargs): env = os.environ.copy() @@ -444,6 +448,8 @@ def compile_in(self, source_folder, build_folder, install_folder): files. build_folder is the name of the folder where the build should be executed. Both must be absolute paths. """ + global is_windows + cmake = find_executable("cmake") if not cmake: print( @@ -476,7 +482,7 @@ def compile_in(self, source_folder, build_folder, install_folder): if retcode: return False - return [] + return ["igraph"] def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries @@ -484,6 +490,10 @@ def copy_build_artifacts( # Nothing to do; we already installed stuff in the compilation step return True + def create_build_config_file(self, install_folder, libraries): + with open(os.path.join(install_folder, "build.cfg"), "w") as f: + f.write(repr(libraries)) + ########################################################################### @@ -703,6 +713,8 @@ def compile_igraph_from_vendor_source(self): print("") sys.exit(1) + igraph_builder.create_build_config_file(install_folder, libraries) + self.use_vendored_igraph() return True diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index a9674919a..d091d5e93 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -7073,7 +7073,6 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, igraph_matrix_t m; igraph_matrix_t *dist = 0; long int dim = 2; - igraphmodule_ARPACKOptionsObject *arpack_options; PyObject *dist_o = Py_None; PyObject *arpack_options_o = igraphmodule_arpack_options_default; PyObject *result; From 6c2590ba18b81f22a67e6034a38c4dbcbcbde3d1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 26 Jan 2021 14:46:10 +0100 Subject: [PATCH 0311/1892] updating tests not to use deprecated constructs from igraph 0.8 --- setup.py | 60 +++++++++++++++++------------ src/_igraph/graphobject.c | 35 +++++++++-------- src/_igraph/igraphmodule.c | 77 +++++++++++++++++++++++++++++++++++-- tests/test_basic.py | 69 ++++++++++++++++++++++++++++++++- tests/test_decomposition.py | 29 ++++++++------ tests/test_structural.py | 37 +++++++++--------- 6 files changed, 231 insertions(+), 76 deletions(-) diff --git a/setup.py b/setup.py index addc0a5fd..a522c89b8 100644 --- a/setup.py +++ b/setup.py @@ -272,7 +272,38 @@ def wait_for_keypress(seconds): ########################################################################### -class IgraphCCoreAutotoolsBuilder(object): +class IgraphCCoreBuilder(object): + """Superclass for classes responsible for downloading and building the + C core of igraph if it is not installed yet. + """ + + def create_build_config_file(self, install_folder, libraries): + with open(os.path.join(install_folder, "build.cfg"), "w") as f: + f.write(repr(libraries)) + + def parse_pkgconfig_file(self, filename): + building_on_windows = building_on_windows_msvc() + + if building_on_windows: + libraries = ["igraph"] + else: + libraries = [] + with open(filename, "r") as fp: + for line in fp: + if line.startswith("Libs: ") or line.startswith("Libs.private: "): + words = line.strip().split() + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) + + if not libraries: + # Educated guess + libraries = ["igraph"] + + return libraries + + +class IgraphCCoreAutotoolsBuilder(IgraphCCoreBuilder): """Class responsible for downloading and building the C core of igraph if it is not installed yet, assuming that the C core uses `configure.ac` and its friends. This used to be the case before igraph 0.9. @@ -362,20 +393,7 @@ def compile_in(self, source_folder, build_folder, install_folder): if retcode: return False - if building_on_windows: - libraries = ["igraph"] - else: - libraries = [] - for line in open("igraph.pc"): - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) - - if not libraries: - # Educated guess - libraries = ["igraph"] + libraries = self.parse_pkgconfig_file("igraph.pc") return libraries @@ -415,10 +433,6 @@ def copy_build_artifacts( return True - def create_build_config_file(self, install_folder, libraries): - with open(os.path.join(install_folder, "build.cfg"), "w") as f: - f.write(repr(libraries)) - @staticmethod def enhanced_env(**kwargs): env = os.environ.copy() @@ -431,7 +445,7 @@ def enhanced_env(**kwargs): ########################################################################### -class IgraphCCoreCMakeBuilder(object): +class IgraphCCoreCMakeBuilder(IgraphCCoreBuilder): """Class responsible for downloading and building the C core of igraph if it is not installed yet, assuming that the C core uses CMake as the build tool. This is the case from igraph 0.9. @@ -482,7 +496,7 @@ def compile_in(self, source_folder, build_folder, install_folder): if retcode: return False - return ["igraph"] + return self.parse_pkgconfig_file(os.path.join(install_folder, "lib", "pkgconfig", "igraph.pc")) def copy_build_artifacts( self, source_folder, build_folder, install_folder, libraries @@ -490,10 +504,6 @@ def copy_build_artifacts( # Nothing to do; we already installed stuff in the compilation step return True - def create_build_config_file(self, install_folder, libraries): - with open(os.path.join(install_folder, "build.cfg"), "w") as f: - f.write(repr(libraries)) - ########################################################################### diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d091d5e93..195926804 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1539,6 +1539,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, PyObject *dir = Py_True, *vcount_if_unconnected = Py_True; PyObject *weights_o = Py_None; igraph_vector_t *weights = 0; + igraph_real_t diameter; static char *kwlist[] = { "directed", "unconn", "weights", NULL @@ -1553,23 +1554,28 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { - igraph_real_t i; - if (igraph_diameter_dijkstra(&self->g, weights, &i, 0, 0, 0, + if (igraph_diameter_dijkstra(&self->g, weights, &diameter, 0, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); return NULL; } igraph_vector_destroy(weights); free(weights); - return PyFloat_FromDouble((double)i); + return PyFloat_FromDouble((double)diameter); } else { - igraph_real_t i; - if (igraph_diameter(&self->g, &i, 0, 0, 0, PyObject_IsTrue(dir), + if (igraph_diameter(&self->g, &diameter, 0, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; } - return PyInt_FromLong((long)i); + + /* The diameter is integer in this case, except if igraph_diameter() + * returned NaN or infinity for some reason */ + if (ceilf(diameter) == diameter && isfinite(diameter)) { + return PyInt_FromLong((long)diameter); + } else { + return PyFloat_FromDouble((double)diameter); + } } } @@ -3724,8 +3730,8 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } - if (igraph_betweenness_estimate(&self->g, &res, vs, PyObject_IsTrue(directed), - (igraph_real_t)PyFloat_AsDouble(cutoff_num), weights)) { + if (igraph_betweenness_cutoff(&self->g, &res, vs, PyObject_IsTrue(directed), + weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4072,9 +4078,8 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, igraph_vs_destroy(&vs); igraph_vector_destroy(&res); return NULL; } - if (igraph_closeness_estimate(&self->g, &res, vs, mode, - (igraph_real_t)PyFloat_AsDouble(cutoff_num), weights, - PyObject_IsTrue(normalized_o))) { + if (igraph_closeness_cutoff(&self->g, &res, vs, mode, weights, + (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4457,8 +4462,8 @@ PyObject *igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject * self, if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_vector_destroy(&res); return NULL; } - if (igraph_edge_betweenness_estimate(&self->g, &res, PyObject_IsTrue(directed), - (igraph_real_t)PyFloat_AsDouble(cutoff_num), weights)) { + if (igraph_edge_betweenness_cutoff(&self->g, &res, PyObject_IsTrue(directed), + weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -11028,7 +11033,7 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, static char *kwlist[] = {"membership", "weights", "resolution", "directed", 0}; igraph_vector_t membership; igraph_vector_t *weights=0; - double resolution; + double resolution = 1; igraph_real_t modularity; PyObject *mvec, *wvec=Py_None; PyObject *directed = Py_True; @@ -11406,7 +11411,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self PyObject *mss, *qs, *res, *weights = Py_None; igraph_matrix_t memberships; igraph_vector_t membership, modularity; - double resolution; + double resolution = 1; igraph_vector_t *ws; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOd", kwlist, &weights, &return_levels, &resolution)) { diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 5e671486a..8b4da52df 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -494,6 +494,57 @@ PyObject* igraphmodule_is_graphical_degree_sequence(PyObject *self, } +PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kwds) { + static char* kwlist[] = { "out_deg", "in_deg", "loops", "multiple", NULL }; + PyObject *out_deg_o = 0, *in_deg_o = 0; + PyObject *loops = Py_False, *multiple = Py_False; + igraph_vector_t out_deg, in_deg; + igraph_bool_t is_directed, result; + int allowed_edge_types; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, + &out_deg_o, &in_deg_o, &loops, &multiple)) + return NULL; + + is_directed = (in_deg_o != 0 && in_deg_o != Py_None); + + if (igraphmodule_PyObject_to_vector_t(out_deg_o, &out_deg, 0)) + return NULL; + + if (is_directed && igraphmodule_PyObject_to_vector_t(in_deg_o, &in_deg, 0)) { + igraph_vector_destroy(&out_deg); + return NULL; + } + + allowed_edge_types = IGRAPH_SIMPLE_SW; + if (PyObject_IsTrue(loops)) { + allowed_edge_types |= IGRAPH_LOOPS_SW; + } + if (PyObject_IsTrue(multiple)) { + allowed_edge_types |= IGRAPH_MULTI_SW; + } + + if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, allowed_edge_types, &result)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&out_deg); + if (is_directed) { + igraph_vector_destroy(&in_deg); + } + return NULL; + } + + igraph_vector_destroy(&out_deg); + if (is_directed) { + igraph_vector_destroy(&in_deg); + } + + if (result) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + + PyObject* igraphmodule_power_law_fit(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "data", "xmin", "force_continuous", NULL }; PyObject *data_o, *force_continuous_o = Py_False; @@ -582,6 +633,7 @@ static PyMethodDef igraphmodule_methods[] = {"is_degree_sequence", (PyCFunction)igraphmodule_is_degree_sequence, METH_VARARGS | METH_KEYWORDS, "is_degree_sequence(out_deg, in_deg=None)\n\n" + "Deprecated since 0.9 in favour of L{is_graphical()}.\n\n" "Returns whether a list of degrees can be a degree sequence of some graph.\n\n" "Note that it is not required for the graph to be simple; in other words,\n" "this function may return C{True} for degree sequences that can be realized\n" @@ -596,13 +648,27 @@ static PyMethodDef igraphmodule_methods[] = "@param in_deg: the list of in-degrees for directed graphs. This parameter\n" " must be C{None} for undirected graphs.\n" "@return: C{True} if there exists some graph that can realize the given degree\n" - " sequence, C{False} otherwise." - "@see: L{is_graphical_degree_sequence()} if you do not want to allow multiple\n" - " or loop edges.\n" + " sequence, C{False} otherwise.\n" + }, + {"is_graphical", (PyCFunction)igraphmodule_is_graphical, + METH_VARARGS | METH_KEYWORDS, + "is_graphical(out_deg, in_deg=None, loops=False, multiple=False)\n\n" + "Returns whether a list of degrees can be a degree sequence of some graph,\n" + "with or without multiple and loop edges, depending on the allowed edge types\n" + "in the remaining arguments.\n\n" + "@param out_deg: the list of degrees. For directed graphs, this list must\n" + " contain the out-degrees of the vertices.\n" + "@param in_deg: the list of in-degrees for directed graphs. This parameter\n" + " must be C{None} for undirected graphs.\n" + "@param loops: whether loop edges are allowed.\n" + "@param multiple: whether multiple edges are allowed.\n" + "@return: C{True} if there exists some graph that can realize the given\n" + " degree sequence with the given edge types, C{False} otherwise.\n" }, {"is_graphical_degree_sequence", (PyCFunction)igraphmodule_is_graphical_degree_sequence, METH_VARARGS | METH_KEYWORDS, "is_graphical_degree_sequence(out_deg, in_deg=None)\n\n" + "Deprecated since 0.9 in favour of L{is_graphical()}.\n\n" "Returns whether a list of degrees can be a degree sequence of some simple graph.\n\n" "Note that it is required for the graph to be simple; in other words,\n" "this function will return C{False} for degree sequences that cannot be realized\n" @@ -613,7 +679,6 @@ static PyMethodDef igraphmodule_methods[] = " must be C{None} for undirected graphs.\n" "@return: C{True} if there exists some simple graph that can realize the given\n" " degree sequence, C{False} otherwise.\n" - "@see: L{is_degree_sequence()} if you want to allow multiple or loop edges.\n" }, {"set_progress_handler", igraphmodule_set_progress_handler, METH_O, "set_progress_handler(handler)\n\n" @@ -857,6 +922,10 @@ extern PyObject* igraphmodule_arpack_options_default; PyModule_AddIntConstant(m, "TRANSITIVITY_NAN", IGRAPH_TRANSITIVITY_NAN); PyModule_AddIntConstant(m, "TRANSITIVITY_ZERO", IGRAPH_TRANSITIVITY_ZERO); + PyModule_AddIntConstant(m, "SIMPLE_SW", IGRAPH_SIMPLE_SW); + PyModule_AddIntConstant(m, "LOOPS_SW", IGRAPH_LOOPS_SW); + PyModule_AddIntConstant(m, "MULTI_SW", IGRAPH_MULTI_SW); + /* More useful constants */ { const char* version; diff --git a/tests/test_basic.py b/tests/test_basic.py index 2d7c7be6a..469506597 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,4 +1,7 @@ import unittest +import warnings + +from functools import partial from igraph import ( ALL, @@ -6,6 +9,7 @@ IN, InternalError, is_degree_sequence, + is_graphical, is_graphical_degree_sequence, Matrix, ) @@ -601,6 +605,65 @@ def checkIfOK(self, g, name_attr, edge_attrs): class DegreeSequenceTests(unittest.TestCase): def testIsDegreeSequence(self): + # Catch and suppress warnings because is_degree_sequence() is now + # deprecated + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + self.assertTrue(is_degree_sequence([])) + self.assertTrue(is_degree_sequence([], [])) + self.assertTrue(is_degree_sequence([0])) + self.assertTrue(is_degree_sequence([0], [0])) + self.assertFalse(is_degree_sequence([1])) + self.assertTrue(is_degree_sequence([1], [1])) + self.assertTrue(is_degree_sequence([2])) + self.assertFalse(is_degree_sequence([2, 1, 1, 1])) + self.assertTrue(is_degree_sequence([2, 1, 1, 1], [1, 1, 1, 2])) + self.assertFalse(is_degree_sequence([2, 1, -2])) + self.assertFalse(is_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) + self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) + self.assertTrue(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None)) + self.assertFalse(is_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])) + self.assertTrue( + is_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + ) + ) + + def testIsGraphicalSequence(self): + # Catch and suppress warnings because is_graphical_degree_sequence() is now + # deprecated + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + self.assertTrue(is_graphical_degree_sequence([])) + self.assertTrue(is_graphical_degree_sequence([], [])) + self.assertTrue(is_graphical_degree_sequence([0])) + self.assertTrue(is_graphical_degree_sequence([0], [0])) + self.assertFalse(is_graphical_degree_sequence([1])) + self.assertFalse(is_graphical_degree_sequence([1], [1])) + self.assertFalse(is_graphical_degree_sequence([2])) + self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1])) + self.assertTrue(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, 2])) + self.assertFalse(is_graphical_degree_sequence([2, 1, -2])) + self.assertFalse(is_graphical_degree_sequence([2, 1, 1, 1], [1, 1, 1, -2])) + self.assertTrue( + is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3]) + ) + self.assertTrue( + is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3], None) + ) + self.assertFalse( + is_graphical_degree_sequence([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]) + ) + self.assertTrue( + is_graphical_degree_sequence( + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 3, 2, 3, 4, 4, 2, 2, 4, 2] + ) + ) + self.assertTrue(is_graphical_degree_sequence([3, 3, 3, 3, 4])) + + def testIsGraphicalNonSimple(self): + # Same as testIsDegreeSequence, but using is_graphical() + is_degree_sequence = partial(is_graphical, loops=True, multiple=True) self.assertTrue(is_degree_sequence([])) self.assertTrue(is_degree_sequence([], [])) self.assertTrue(is_degree_sequence([0])) @@ -621,7 +684,11 @@ def testIsDegreeSequence(self): ) ) - def testIsGraphicalSequence(self): + def testIsGraphicalSimple(self): + # Same as testIsGraphicalDegreeSequence, but using is_graphical() + is_graphical_degree_sequence = partial( + is_graphical, loops=False, multiple=False + ) self.assertTrue(is_graphical_degree_sequence([])) self.assertTrue(is_graphical_degree_sequence([], [])) self.assertTrue(is_graphical_degree_sequence([0])) diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 3eaef38fb..8413af0d6 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -1,15 +1,20 @@ +import math import random import unittest -import math - -from igraph import * - -try: - set, frozenset -except NameError: - import sets - set, frozenset = sets.Set, sets.ImmutableSet +from igraph import ( + Clustering, + CohesiveBlocks, + Cover, + Graph, + Histogram, + InternalError, + UniqueIdGenerator, + VertexClustering, + compare_communities, + split_join_distance, + set_random_number_generator, +) class SubgraphTests(unittest.TestCase): @@ -63,9 +68,9 @@ def testKCores(self): self.assertTrue(g.coreness() == [3, 3, 3, 3, 1, 1, 1, 2, 1, 2, 2]) self.assertTrue(g.shell_index() == g.coreness()) - l = g.k_core(3).get_edgelist() - l.sort() - self.assertTrue(l == [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]) + edgelist = g.k_core(3).get_edgelist() + edgelist.sort() + self.assertTrue(edgelist == [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]) class ClusteringTests(unittest.TestCase): diff --git a/tests/test_structural.py b/tests/test_structural.py index aadf18033..5fecf4f43 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -2,8 +2,8 @@ import unittest import warnings -from igraph import * -from math import isnan +from igraph import Graph, InternalError, IN, OUT, ALL, TREE_IN +from math import inf, isnan class SimplePropertiesTests(unittest.TestCase): @@ -26,8 +26,8 @@ def testDensity(self): def testDiameter(self): self.assertTrue(self.gfull.diameter() == 1) - self.assertTrue(self.gempty.diameter(unconn=False) == 10) - self.assertTrue(self.gempty.diameter(unconn=False, weights=[]) == float("inf")) + self.assertTrue(isnan(self.gempty.diameter(unconn=False))) + self.assertTrue(isnan(self.gempty.diameter(unconn=False, weights=[]))) self.assertTrue(self.g.diameter() == 2) self.assertTrue(self.gdir.diameter(False) == 2) self.assertTrue(self.gdir.diameter() == 3) @@ -78,11 +78,11 @@ def testLocalTransitivity(self): == [0.0] * self.tree.vcount() ) - l = self.g.transitivity_local_undirected(mode="zero") - self.assertAlmostEqual(2 / 3, l[0], places=4) - self.assertAlmostEqual(2 / 3, l[1], places=4) - self.assertEqual(1, l[2]) - self.assertEqual(1, l[3]) + transitivity = self.g.transitivity_local_undirected(mode="zero") + self.assertAlmostEqual(2 / 3, transitivity[0], places=4) + self.assertAlmostEqual(2 / 3, transitivity[1], places=4) + self.assertEqual(1, transitivity[2]) + self.assertEqual(1, transitivity[3]) g = Graph.Full(4) + 1 + [(0, 4)] g.es["weight"] = [1, 1, 1, 1, 1, 1, 5] @@ -269,7 +269,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) with warnings.catch_warnings(): warnings.simplefilter("ignore") - cl = g.closeness(cutoff=1) + cl = g.closeness(cutoff=0.9) cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -285,7 +285,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) with warnings.catch_warnings(): warnings.simplefilter("ignore") - cl = g.closeness(cutoff=1, weights=weights) + cl = g.closeness(cutoff=0.9, weights=weights) cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -389,17 +389,17 @@ def testAuthorityScore(self): g = Graph.Tree(15, 2, TREE_IN) asc = g.authority_score() self.assertAlmostEqual(max(asc), 1.0, places=3) - asc, ev = g.hub_score(scale=False, return_eigenvalue=True) - if asc[0] < 0: - hs = [-x for x in asc] + + # Smoke testing + g.authority_score(scale=False, return_eigenvalue=True) def testHubScore(self): g = Graph.Tree(15, 2, TREE_IN) hsc = g.hub_score() self.assertAlmostEqual(max(hsc), 1.0, places=3) - hsc, ev = g.hub_score(scale=False, return_eigenvalue=True) - if hsc[0] < 0: - hsc = [-x for x in hsc] + + # Smoke testing + g.hub_score(scale=False, return_eigenvalue=True) def testCoreness(self): g = Graph.Full(4) + Graph(4) + [(0, 4), (1, 5), (2, 6), (3, 7)] @@ -540,7 +540,6 @@ def testShortestPaths(self): ) ws = [0, 2, 1, 0, 5, 2, 1, 1, 0, 2, 2, 8, 1, 1, 3, 1, 1, 4, 2, 1] g.es["weight"] = ws - inf = float("inf") expected = [ [0, 0, 0, 1, 5, 2, 1, 13, 3, 5], [inf, 0, 0, 1, 5, 2, 1, 13, 3, 5], @@ -673,7 +672,7 @@ def testPathLengthHist(self): h = g.path_length_hist() self.assertTrue(h.unconnected == 0) self.assertTrue( - [(int(l), x) for l, _, x in h.bins()] + [(int(value), x) for value, _, x in h.bins()] == [(1, 14), (2, 19), (3, 20), (4, 20), (5, 16), (6, 16)] ) g = Graph.Full(5) + Graph.Full(4) From ddfded23b96ca9c94efd64961ca8bebacd60e27e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 26 Jan 2021 16:26:40 +0100 Subject: [PATCH 0312/1892] almost all test cases fixed now for 0.9 --- src/_igraph/graphobject.c | 613 +++++++++++++++++++------------------- tests/test_structural.py | 8 +- 2 files changed, 318 insertions(+), 303 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 195926804..73ef24061 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -454,11 +454,11 @@ PyObject *igraphmodule_Graph_is_matching(igraphmodule_GraphObject* self, if (igraphmodule_attrib_to_vector_long_t(matching_o, self, &matching, ATTRIBUTE_TYPE_VERTEX)) - return NULL; + return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) { if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } - return NULL; + return NULL; } if (igraph_is_matching(&self->g, types, matching, &result)) { @@ -496,11 +496,11 @@ PyObject *igraphmodule_Graph_is_maximal_matching(igraphmodule_GraphObject* self, if (igraphmodule_attrib_to_vector_long_t(matching_o, self, &matching, ATTRIBUTE_TYPE_VERTEX)) - return NULL; + return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) { if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } - return NULL; + return NULL; } if (igraph_is_maximal_matching(&self->g, types, matching, &result)) { @@ -768,7 +768,7 @@ PyObject *igraphmodule_Graph_diversity(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&result); return NULL; @@ -858,7 +858,7 @@ PyObject *igraphmodule_Graph_strength(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&result); return NULL; @@ -1551,7 +1551,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { if (igraph_diameter_dijkstra(&self->g, weights, &diameter, 0, 0, 0, @@ -1599,7 +1599,7 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; igraph_vector_init(&res, 0); if (weights) { @@ -1645,7 +1645,7 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { if (igraph_diameter_dijkstra(&self->g, weights, &len, &from, &to, 0, @@ -1655,9 +1655,11 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, return NULL; } igraph_vector_destroy(weights); free(weights); - if (from >= 0) + if (from >= 0) { return Py_BuildValue("lld", (long)from, (long)to, (double)len); - return Py_BuildValue("OOd", Py_None, Py_None, (double)len); + } else { + return Py_BuildValue("OOd", Py_None, Py_None, (double)len); + } } else { if (igraph_diameter(&self->g, &len, &from, &to, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { @@ -1665,9 +1667,22 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, return NULL; } - if (from >= 0) - return Py_BuildValue("lll", (long)from, (long)to, (long)len); - return Py_BuildValue("OOl", Py_None, Py_None, (long)len); + /* if len is finite and integer (which it typically is, unless it's + * infinite), then return a Python int as the third value; otherwise + * return a float */ + if (ceilf(len) == len && isfinite(len)) { + if (from >= 0) { + return Py_BuildValue("lll", (long)from, (long)to, (long)len); + } else { + return Py_BuildValue("OOl", Py_None, Py_None, (long)len); + } + } else { + if (from >= 0) { + return Py_BuildValue("lld", (long)from, (long)to, (double)len); + } else { + return Py_BuildValue("OOd", Py_None, Py_None, (double)len); + } + } } } @@ -1708,7 +1723,7 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, */ PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) { igraph_vector_t result; - PyObject *o; + PyObject *o; igraph_vector_init(&result, 0); if (igraph_convergence_degree(&self->g, &result, 0, 0)) { @@ -1733,10 +1748,10 @@ PyObject *igraphmodule_Graph_convergence_field_size(igraphmodule_GraphObject *se igraph_vector_init(&ins, 0); igraph_vector_init(&outs, 0); if (igraph_convergence_degree(&self->g, 0, &ins, &outs)) { - igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&ins); - igraph_vector_destroy(&outs); - return NULL; + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&ins); + igraph_vector_destroy(&outs); + return NULL; } o1=igraphmodule_vector_t_to_PyList(&ins, IGRAPHMODULE_TYPE_INT); @@ -1783,7 +1798,7 @@ PyObject *igraphmodule_Graph_knn(igraphmodule_GraphObject *self, } if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vs_destroy(&vids); igraph_vector_destroy(&knn); igraph_vector_destroy(&knnk); @@ -2127,7 +2142,7 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!O", kwlist, &PyList_Type, &outdeg, &PyList_Type, &indeg, - &method)) + &method)) return NULL; if (igraphmodule_PyObject_to_degseq_t(method, &meth)) return NULL; @@ -2323,7 +2338,7 @@ PyObject *igraphmodule_Graph_Forest_Fire(PyTypeObject * type, if (igraph_forest_fire_game(&g, (igraph_integer_t)n, (igraph_real_t)fw_prob, (igraph_real_t)bw_factor, (igraph_integer_t)ambs, - (igraph_bool_t)(PyObject_IsTrue(directed)))) { + (igraph_bool_t)(PyObject_IsTrue(directed)))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2359,7 +2374,7 @@ PyObject *igraphmodule_Graph_Full(PyTypeObject * type, } if (igraph_full(&g, (igraph_integer_t) n, PyObject_IsTrue(directed), - PyObject_IsTrue(loops))) { + PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2395,19 +2410,19 @@ PyObject *igraphmodule_Graph_Full_Bipartite(PyTypeObject * type, } if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) - return NULL; + return NULL; if (igraph_vector_bool_init(&vertex_types, n1+n2)) { igraphmodule_handle_igraph_error(); - return NULL; + return NULL; } if (igraph_full_bipartite(&g, &vertex_types, (igraph_integer_t) n1, (igraph_integer_t) n2, PyObject_IsTrue(directed), mode)) { - igraph_vector_bool_destroy(&vertex_types); + igraph_vector_bool_destroy(&vertex_types); igraphmodule_handle_igraph_error(); - return NULL; + return NULL; } CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -2567,29 +2582,29 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, static char *kwlist[] = { "matrix", "directed", "mode", "multiple", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OOO", kwlist, &PyList_Type, &matrix_o, - &directed, &mode_o, &multiple)) + &directed, &mode_o, &multiple)) return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; if (igraph_vector_bool_init(&vertex_types, 0)) { igraphmodule_handle_igraph_error(); - return NULL; + return NULL; } if (igraphmodule_PyList_to_matrix_t(matrix_o, &matrix)) { - igraph_vector_bool_destroy(&vertex_types); + igraph_vector_bool_destroy(&vertex_types); PyErr_SetString(PyExc_TypeError, "Error while converting incidence matrix"); return NULL; } if (igraph_incidence(&g, &vertex_types, &matrix, - PyObject_IsTrue(directed), mode, PyObject_IsTrue(multiple))) { - igraphmodule_handle_igraph_error(); - igraph_matrix_destroy(&matrix); - igraph_vector_bool_destroy(&vertex_types); - return NULL; + PyObject_IsTrue(directed), mode, PyObject_IsTrue(multiple))) { + igraphmodule_handle_igraph_error(); + igraph_matrix_destroy(&matrix); + igraph_vector_bool_destroy(&vertex_types); + return NULL; } igraph_matrix_destroy(&matrix); @@ -3012,15 +3027,15 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, return NULL; if (igraph_vector_bool_init(&vertex_types, n1+n2)) { - igraphmodule_handle_igraph_error(); - return NULL; + igraphmodule_handle_igraph_error(); + return NULL; } if (igraph_bipartite_game(&g, &vertex_types, t, - (igraph_integer_t) n1, (igraph_integer_t) n2, - (igraph_real_t) p, (igraph_integer_t) m, - PyObject_IsTrue(directed_o), neimode)) { - igraph_vector_bool_destroy(&vertex_types); + (igraph_integer_t) n1, (igraph_integer_t) n2, + (igraph_real_t) p, (igraph_integer_t) m, + PyObject_IsTrue(directed_o), neimode)) { + igraph_vector_bool_destroy(&vertex_types); igraphmodule_handle_igraph_error(); return NULL; } @@ -3030,7 +3045,7 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, vertex_types_o = igraphmodule_vector_bool_t_to_PyList(&vertex_types); igraph_vector_bool_destroy(&vertex_types); if (vertex_types_o == 0) - return NULL; + return NULL; return Py_BuildValue("NN", (PyObject *) self, vertex_types_o); } @@ -3150,7 +3165,7 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, igraph_vector_int_t block_sizes; static char *kwlist[] = { "n", "pref_matrix", "block_sizes", "directed", - "loops", NULL }; + "loops", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "lO!O!|OO", kwlist, &n, &PyList_Type, &pref_matrix_o, @@ -3487,8 +3502,8 @@ PyObject *igraphmodule_Graph_articulation_points(igraphmodule_GraphObject *self) igraph_vector_t res; PyObject *o; if (igraph_vector_init(&res, 0)) { - igraphmodule_handle_igraph_error(); - return NULL; + igraphmodule_handle_igraph_error(); + return NULL; } if (igraph_articulation_points(&self->g, &res)) { @@ -3608,14 +3623,14 @@ PyObject *igraphmodule_Graph_authority_score( igraph_vector_t res, *weights = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO!O", kwlist, &weights_o, - &scale_o, &igraphmodule_ARPACKOptionsType, + &scale_o, &igraphmodule_ARPACKOptionsType, &arpack_options_o, &return_eigenvalue)) return NULL; if (igraph_vector_init(&res, 0)) return igraphmodule_handle_igraph_error(); if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; if (igraph_authority_score(&self->g, &res, &value, PyObject_IsTrue(scale_o), @@ -3700,7 +3715,7 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -3809,7 +3824,7 @@ PyObject *igraphmodule_Graph_bibcoupling(igraphmodule_GraphObject * self, * \sa igraph_biconnected_components */ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *self, - PyObject *args, PyObject *kwds) { + PyObject *args, PyObject *kwds) { igraph_vector_ptr_t components; igraph_vector_t points; igraph_bool_t return_articulation_points; @@ -3822,20 +3837,20 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se return_articulation_points = PyObject_IsTrue(aps); if (igraph_vector_ptr_init(&components, 0)) { - igraphmodule_handle_igraph_error(); - return NULL; + igraphmodule_handle_igraph_error(); + return NULL; } if (return_articulation_points) { - if (igraph_vector_init(&points, 0)) { - igraphmodule_handle_igraph_error(); - igraph_vector_ptr_destroy(&components); - return NULL; - } + if (igraph_vector_init(&points, 0)) { + igraphmodule_handle_igraph_error(); + igraph_vector_ptr_destroy(&components); + return NULL; + } } if (igraph_biconnected_components(&self->g, &no, &components, 0, 0, return_articulation_points ? &points : 0)) { igraphmodule_handle_igraph_error(); - igraph_vector_ptr_destroy(&components); + igraph_vector_ptr_destroy(&components); if (return_articulation_points) igraph_vector_destroy(&points); return NULL; } @@ -3845,11 +3860,11 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se igraph_vector_ptr_destroy_all(&components); if (return_articulation_points) { - PyObject *result2; - igraph_vector_sort(&points); - result2 = igraphmodule_vector_t_to_PyList(&points, IGRAPHMODULE_TYPE_INT); + PyObject *result2; + igraph_vector_sort(&points); + result2 = igraphmodule_vector_t_to_PyList(&points, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&points); - return Py_BuildValue("NN", result, result2); /* references stolen */ + return Py_BuildValue("NN", result, result2); /* references stolen */ } return result; @@ -3861,7 +3876,7 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se * \sa igraph_bipartite_projection */ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * self, - PyObject* args, PyObject* kwds) { + PyObject* args, PyObject* kwds) { PyObject *types_o = Py_None, *multiplicity_o = Py_True, *mul1 = 0, *mul2 = 0; igraphmodule_GraphObject *result1 = 0, *result2 = 0; igraph_vector_bool_t* types = 0; @@ -3878,7 +3893,7 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) - return NULL; + return NULL; if (which == 0) { p_g2 = 0; @@ -3973,7 +3988,7 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel * \sa igraph_bipartite_projection_size */ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject * self, - PyObject* args, PyObject* kwds) { + PyObject* args, PyObject* kwds) { PyObject *types_o = Py_None; igraph_vector_bool_t* types = 0; igraph_integer_t vcount1, vcount2, ecount1, ecount2; @@ -3984,10 +3999,10 @@ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) - return NULL; + return NULL; if (igraph_bipartite_projection_size(&self->g, types, - &vcount1, &ecount1, &vcount2, &ecount2)) { + &vcount1, &ecount1, &vcount2, &ecount2)) { if (types) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; @@ -4007,8 +4022,8 @@ PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { igraph_vector_t res; PyObject *o; if (igraph_vector_init(&res, 0)) { - igraphmodule_handle_igraph_error(); - return NULL; + igraphmodule_handle_igraph_error(); + return NULL; } if (igraph_bridges(&self->g, &res)) { @@ -4033,7 +4048,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "vertices", "mode", "cutoff", "weights", - "normalized", NULL }; + "normalized", NULL }; PyObject *vobj = Py_None, *list = NULL, *cutoff = Py_None, *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; igraph_vector_t res, *weights = 0; @@ -4057,7 +4072,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); return NULL; @@ -4065,7 +4080,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, if (cutoff == Py_None) { if (igraph_closeness(&self->g, &res, vs, mode, weights, - PyObject_IsTrue(normalized_o))) { + PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4244,19 +4259,19 @@ PyObject *igraphmodule_Graph_cocitation(igraphmodule_GraphObject * self, * \sa igraph_contract_vertices */ PyObject *igraphmodule_Graph_contract_vertices(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) { + PyObject * args, PyObject * kwds) { static char* kwlist[] = {"mapping", "combine_attrs", NULL }; PyObject *mapping_o, *combination_o = Py_None; igraph_vector_t mapping; igraph_attribute_combination_t combination; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &mapping_o, - &combination_o)) - return NULL; + &combination_o)) + return NULL; if (igraphmodule_PyObject_to_attribute_combination_t( - combination_o, &combination)) - return NULL; + combination_o, &combination)) + return NULL; if (igraphmodule_PyObject_to_vector_t(mapping_o, &mapping, 1)) { igraph_attribute_combination_destroy(&combination); @@ -4999,7 +5014,7 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, } if (igraph_neighborhood(&self->g, &res, vs, (igraph_integer_t) order, mode, - mindist)) { + mindist)) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } @@ -5054,7 +5069,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, } if (igraph_neighborhood_size(&self->g, &res, vs, (igraph_integer_t) order, mode, - mindist)) { + mindist)) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } @@ -5102,7 +5117,7 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!Olf", kwlist, &vobj, &directed, &damping, &robj, - &rvsobj, &wobj, + &rvsobj, &wobj, &igraphmodule_ARPACKOptionsType, &arpack_options_o, &algo_o, &niter, &eps)) @@ -5162,10 +5177,10 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel if (rvsobj != Py_None) retval = igraph_personalized_pagerank_vs(&self->g, algo, &res, 0, vs, - PyObject_IsTrue(directed), damping, reset_vs, &weights, opts); + PyObject_IsTrue(directed), damping, reset_vs, &weights, opts); else retval = igraph_personalized_pagerank(&self->g, algo, &res, 0, vs, - PyObject_IsTrue(directed), damping, reset, &weights, opts); + PyObject_IsTrue(directed), damping, reset, &weights, opts); if (retval) { igraphmodule_handle_igraph_error(); @@ -5885,7 +5900,7 @@ PyObject } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vs_destroy(&vs); igraph_vector_destroy(&result); return NULL; @@ -5986,7 +6001,7 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, if (source < 0 && target < 0) { if (igraph_vertex_connectivity(&self->g, &res, PyObject_IsTrue(checks))) { igraphmodule_handle_igraph_error(); - return NULL; + return NULL; } } else if (source >= 0 && target >= 0) { if (igraphmodule_PyObject_to_vconn_nei_t(neis, &neighbors)) @@ -5997,8 +6012,8 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, return NULL; } } else { - PyErr_SetString(PyExc_ValueError, "if source or target is given, the other one must also be specified"); - return NULL; + PyErr_SetString(PyExc_ValueError, "if source or target is given, the other one must also be specified"); + return NULL; } if (!IGRAPH_FINITE(res)) return Py_BuildValue("d", (double)res); @@ -6420,7 +6435,7 @@ PyObject *igraphmodule_Graph_layout_random(igraphmodule_GraphObject * self, * \sa igraph_layout_grid, igraph_layout_grid_3d */ PyObject *igraphmodule_Graph_layout_grid(igraphmodule_GraphObject* self, - PyObject *args, PyObject *kwds) { + PyObject *args, PyObject *kwds) { static char *kwlist[] = { "width", "height", "dim", NULL }; igraph_matrix_t m; @@ -6469,7 +6484,7 @@ PyObject *igraphmodule_Graph_layout_grid(igraphmodule_GraphObject* self, * \sa igraph_layout_star */ PyObject *igraphmodule_Graph_layout_star(igraphmodule_GraphObject* self, - PyObject *args, PyObject *kwds) { + PyObject *args, PyObject *kwds) { static char *kwlist[] = { "center", "order", NULL }; @@ -6575,7 +6590,7 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * } } else { use_seed=1; - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; + if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; } /* Convert minimum and maximum x-y-z values */ @@ -6673,7 +6688,7 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel &weight_node_dist, &weight_border, &weight_edge_lengths, &weight_edge_crossings, &weight_node_edge_dist)) - return NULL; + return NULL; /* Provide default parameters based on the properties of the graph */ if (fineiter < 0) { @@ -6713,9 +6728,9 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel } } else { if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) { - return NULL; - } - use_seed=1; + return NULL; + } + use_seed=1; } retval = igraph_layout_davidson_harel(&self->g, &m, use_seed, @@ -6755,7 +6770,7 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOl", kwlist, &wobj, &seed_o, &fixed_o, &options_o, &dim)) - return NULL; + return NULL; if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); @@ -6768,47 +6783,47 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, if (fixed_o != 0 && fixed_o != Py_None) { fixed = (igraph_vector_bool_t*)malloc(sizeof(igraph_vector_bool_t)); if (!fixed) { - PyErr_NoMemory(); - return NULL; - } - if (igraphmodule_PyObject_to_vector_bool_t(fixed_o, fixed)) { - free(fixed); - return NULL; - } + PyErr_NoMemory(); + return NULL; + } + if (igraphmodule_PyObject_to_vector_bool_t(fixed_o, fixed)) { + free(fixed); + return NULL; + } } if (seed_o == 0 || seed_o == Py_None) { if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); - if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } + if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } return NULL; } } else { if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) { - if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } - return NULL; - } - use_seed=1; + if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } + return NULL; + } + use_seed=1; } /* Convert the weight parameter to a vector */ if (igraphmodule_attrib_to_vector_t(wobj, self, &weights, ATTRIBUTE_TYPE_EDGE)) { igraph_matrix_destroy(&m); - if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } + if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } igraphmodule_handle_igraph_error(); return NULL; } if (dim == 2) { - retval = igraph_layout_drl(&self->g, &m, use_seed, &options, weights, fixed); + retval = igraph_layout_drl(&self->g, &m, use_seed, &options, weights, fixed); } else { - retval = igraph_layout_drl_3d(&self->g, &m, use_seed, &options, weights, fixed); + retval = igraph_layout_drl_3d(&self->g, &m, use_seed, &options, weights, fixed); } if (retval) { igraph_matrix_destroy(&m); if (weights) { igraph_vector_destroy(weights); free(weights); } - if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } + if (fixed) { igraph_vector_bool_destroy(fixed); free(fixed); } igraphmodule_handle_igraph_error(); return NULL; } @@ -6886,7 +6901,7 @@ PyObject } } else { if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; - use_seed=1; + use_seed=1; } /* Convert the weight parameter to a vector */ @@ -6994,7 +7009,7 @@ PyObject *igraphmodule_Graph_layout_graphopt(igraphmodule_GraphObject *self, } else { use_seed=1; if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) - return NULL; + return NULL; } if (igraph_layout_graphopt(&self->g, &m, (igraph_integer_t) niter, @@ -7096,7 +7111,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, PyErr_NoMemory(); return NULL; } - if (igraphmodule_PyList_to_matrix_t(dist_o, dist)) { + if (igraphmodule_PyList_to_matrix_t(dist_o, dist)) { free(dist); return NULL; } @@ -7282,14 +7297,14 @@ PyObject *igraphmodule_Graph_layout_sugiyama( } if (igraphmodule_attrib_to_vector_t(layers_o, self, &layers, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { igraph_vector_destroy(&extd_to_orig_eids); igraph_matrix_destroy(&m); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (layers != 0) { igraph_vector_destroy(layers); free(layers); } igraph_vector_destroy(&extd_to_orig_eids); igraph_matrix_destroy(&m); @@ -7358,7 +7373,7 @@ PyObject *igraphmodule_Graph_layout_bipartite( } if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { igraph_matrix_destroy(&m); Py_DECREF(types_o); return NULL; @@ -7441,17 +7456,17 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, return NULL; if (igraph_vector_init(&row_ids, 0)) - return NULL; + return NULL; if (igraph_vector_init(&col_ids, 0)) { igraph_vector_destroy(&row_ids); - return NULL; + return NULL; } if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) { igraph_vector_destroy(&row_ids); igraph_vector_destroy(&col_ids); - return NULL; + return NULL; } if (igraph_matrix_init(&matrix, 1, 1)) { @@ -7504,7 +7519,7 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; if (igraph_matrix_init (&m, igraph_vcount(&self->g), igraph_vcount(&self->g))) { @@ -7514,7 +7529,7 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, } if (igraph_laplacian(&self->g, &m, /*sparseres=*/ 0, - PyObject_IsTrue(normalized), weights)) { + PyObject_IsTrue(normalized), weights)) { igraphmodule_handle_igraph_error(); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_matrix_destroy(&m); @@ -7579,7 +7594,7 @@ PyObject *igraphmodule_Graph_to_undirected(igraphmodule_GraphObject * self, return NULL; if (igraphmodule_PyObject_to_attribute_combination_t(comb_o, &comb)) - return NULL; + return NULL; if (igraph_to_undirected(&self->g, mode, &comb)) { igraph_attribute_combination_destroy(&comb); @@ -8259,7 +8274,7 @@ PyObject *igraphmodule_Graph_write_graphml(igraphmodule_GraphObject * self, return NULL; if (igraph_write_graph_graphml(&self->g, igraphmodule_filehandle_get(&fobj), - /*prefixattr=*/ 1)) { + /*prefixattr=*/ 1)) { igraphmodule_handle_igraph_error(); igraphmodule_filehandle_destroy(&fobj); return NULL; @@ -8286,7 +8301,7 @@ PyObject *igraphmodule_Graph_write_leda(igraphmodule_GraphObject * self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zz", kwlist, &fname, &vertex_attr_name, - &edge_attr_name)) + &edge_attr_name)) return NULL; if (igraphmodule_filehandle_init(&fobj, fname, "w")) @@ -8313,7 +8328,7 @@ PyObject *igraphmodule_Graph_write_leda(igraphmodule_GraphObject * self, * \sa igraph_canonical_permutation */ PyObject *igraphmodule_Graph_canonical_permutation( - igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "sh", "color", NULL }; PyObject *sh_o = Py_None; PyObject *color_o = Py_None; @@ -8327,24 +8342,24 @@ PyObject *igraphmodule_Graph_canonical_permutation( return NULL; if (igraphmodule_PyObject_to_bliss_sh_t(sh_o, &sh)) - return NULL; + return NULL; if (igraph_vector_init(&labeling, 0)) { - igraphmodule_handle_igraph_error(); - return NULL; + igraphmodule_handle_igraph_error(); + return NULL; } if (igraphmodule_attrib_to_vector_int_t(color_o, self, &color, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; retval = igraph_canonical_permutation(&self->g, color, &labeling, sh, 0); if (color) { igraph_vector_int_destroy(color); free(color); } if (retval) { - igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&labeling); - return NULL; + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&labeling); + return NULL; } list = igraphmodule_vector_t_to_PyList(&labeling, IGRAPHMODULE_TYPE_INT); @@ -8449,7 +8464,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, int retval; static char *kwlist[] = { "other", "return_mapping_12", - "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; + "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; /* TODO: convert igraph_bliss_info_t when needed */ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|O!OOOOOO", kwlist, &igraphmodule_GraphType, &o, @@ -8465,23 +8480,23 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, sh2 = sh1; if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, self, &color2, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (o == Py_None) other = self; else other = (igraphmodule_GraphObject *) o; if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); - map12 = &mapping_12; + igraph_vector_init(&mapping_12, 0); + map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); - map21 = &mapping_21; + igraph_vector_init(&mapping_21, 0); + map21 = &mapping_21; } retval = igraph_isomorphic_bliss(&self->g, &other->g, color1, color2, - &result, map12, map21, sh1, 0, 0); + &result, map12, map21, sh1, 0, 0); if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } @@ -8495,27 +8510,27 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, if (result) Py_RETURN_TRUE; Py_RETURN_FALSE; } else { - PyObject *iso, *m1, *m2; - iso = result ? Py_True : Py_False; - Py_INCREF(iso); - if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); - if (!m1) { - Py_DECREF(iso); - if (map21) igraph_vector_destroy(map21); - return NULL; - } - } else { m1 = Py_None; Py_INCREF(m1); } - if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); - if (!m2) { - Py_DECREF(iso); Py_DECREF(m1); - return NULL; - } - } else { m2 = Py_None; Py_INCREF(m2); } - return Py_BuildValue("NNN", iso, m1, m2); + PyObject *iso, *m1, *m2; + iso = result ? Py_True : Py_False; + Py_INCREF(iso); + if (map12) { + m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map12); + if (!m1) { + Py_DECREF(iso); + if (map21) igraph_vector_destroy(map21); + return NULL; + } + } else { m1 = Py_None; Py_INCREF(m1); } + if (map21) { + m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map21); + if (!m2) { + Py_DECREF(iso); Py_DECREF(m1); + return NULL; + } + } else { m2 = Py_None; Py_INCREF(m2); } + return Py_BuildValue("NNN", iso, m1, m2); } } @@ -8676,20 +8691,20 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -8697,12 +8712,12 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, } if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); - map12 = &mapping_12; + igraph_vector_init(&mapping_12, 0); + map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); - map21 = &mapping_21; + igraph_vector_init(&mapping_21, 0); + map21 = &mapping_21; } callback_data.graph1 = (PyObject*)self; @@ -8740,24 +8755,24 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, if (result) Py_RETURN_TRUE; Py_RETURN_FALSE; } else { - PyObject *m1, *m2; - if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); - if (!m1) { - if (map21) igraph_vector_destroy(map21); - return NULL; - } - } else { m1 = Py_None; Py_INCREF(m1); } - if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); - if (!m2) { - Py_DECREF(m1); - return NULL; - } - } else { m2 = Py_None; Py_INCREF(m2); } - return Py_BuildValue("ONN", result ? Py_True : Py_False, m1, m2); + PyObject *m1, *m2; + if (map12) { + m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map12); + if (!m1) { + if (map21) igraph_vector_destroy(map21); + return NULL; + } + } else { m1 = Py_None; Py_INCREF(m1); } + if (map21) { + m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map21); + if (!m2) { + Py_DECREF(m1); + return NULL; + } + } else { m2 = Py_None; Py_INCREF(m2); } + return Py_BuildValue("ONN", result ? Py_True : Py_False, m1, m2); } } @@ -8806,20 +8821,20 @@ PyObject *igraphmodule_Graph_count_isomorphisms_vf2(igraphmodule_GraphObject *se } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -8899,20 +8914,20 @@ PyObject *igraphmodule_Graph_get_isomorphisms_vf2(igraphmodule_GraphObject *self } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -9011,20 +9026,20 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -9032,12 +9047,12 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, } if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); - map12 = &mapping_12; + igraph_vector_init(&mapping_12, 0); + map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); - map21 = &mapping_21; + igraph_vector_init(&mapping_21, 0); + map21 = &mapping_21; } callback_data.graph1 = (PyObject*)self; @@ -9076,28 +9091,28 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, Py_RETURN_TRUE; Py_RETURN_FALSE; } else { - PyObject *m1, *m2; - if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); - if (!m1) { - if (map21) igraph_vector_destroy(map21); - return NULL; - } - } else { + PyObject *m1, *m2; + if (map12) { + m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map12); + if (!m1) { + if (map21) igraph_vector_destroy(map21); + return NULL; + } + } else { m1 = Py_None; Py_INCREF(m1); } - if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); - if (!m2) { - Py_DECREF(m1); - return NULL; - } - } else { + if (map21) { + m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(map21); + if (!m2) { + Py_DECREF(m1); + return NULL; + } + } else { m2 = Py_None; Py_INCREF(m2); } - return Py_BuildValue("ONN", result ? Py_True : Py_False, m1, m2); + return Py_BuildValue("ONN", result ? Py_True : Py_False, m1, m2); } } @@ -9143,20 +9158,20 @@ PyObject *igraphmodule_Graph_count_subisomorphisms_vf2(igraphmodule_GraphObject } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -9237,20 +9252,20 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_vf2(igraphmodule_GraphObject *s } if (igraphmodule_attrib_to_vector_int_t(color1_o, self, &color1, - ATTRIBUTE_TYPE_VERTEX)) return NULL; + ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_int_t(color2_o, other, &color2, - ATTRIBUTE_TYPE_VERTEX)) { + ATTRIBUTE_TYPE_VERTEX)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color1_o, self, &edge_color1, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } return NULL; } if (igraphmodule_attrib_to_vector_int_t(edge_color2_o, other, &edge_color2, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { if (color1) { igraph_vector_int_destroy(color1); free(color1); } if (color2) { igraph_vector_int_destroy(color2); free(color2); } if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } @@ -9325,13 +9340,13 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, } if (PyObject_IsTrue(return_mapping)) { - if (igraph_vector_init(&mapping, 0)) { + if (igraph_vector_init(&mapping, 0)) { if (p_domains) igraph_vector_ptr_destroy_all(p_domains); igraphmodule_handle_igraph_error(); return NULL; } - map = &mapping; + map = &mapping; } if (igraph_subisomorphic_lad(&other->g, &self->g, p_domains, &result, @@ -9350,11 +9365,11 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, Py_RETURN_TRUE; Py_RETURN_FALSE; } else { - PyObject *m = igraphmodule_vector_t_to_PyList(map, IGRAPHMODULE_TYPE_INT); + PyObject *m = igraphmodule_vector_t_to_PyList(map, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(map); - if (!m) - return NULL; - return Py_BuildValue("ON", result ? Py_True : Py_False, m); + if (!m) + return NULL; + return Py_BuildValue("ON", result ? Py_True : Py_False, m); } } @@ -9639,7 +9654,7 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, o = (igraphmodule_GraphObject *) other; if (igraph_compose(&g, &self->g, &o->g, /*edge_map1=*/ 0, - /*edge_map2=*/ 0)) { + /*edge_map2=*/ 0)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -9875,7 +9890,7 @@ PyObject *igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject * self, if (igraph_maxflow_value(&self->g, &result, v1, v2, &capacity_vector, - &stats)) { + &stats)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } @@ -9929,7 +9944,7 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, } if (igraph_maxflow(&self->g, &result, &flow, &cut, &partition, 0, - v1, v2, &capacity_vector, &stats)) { + v1, v2, &capacity_vector, &stats)) { igraph_vector_destroy(&capacity_vector); igraph_vector_destroy(&flow); igraph_vector_destroy(&cut); @@ -9991,11 +10006,11 @@ PyObject *igraphmodule_Graph_all_st_cuts(igraphmodule_GraphObject * self, return NULL; if (igraph_vector_ptr_init(&partition1s, 0)) { - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraph_vector_ptr_init(&cuts, 0)) { igraph_vector_ptr_destroy(&partition1s); - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraph_all_st_cuts(&self->g, &cuts, &partition1s, @@ -10047,11 +10062,11 @@ PyObject *igraphmodule_Graph_all_st_mincuts(igraphmodule_GraphObject * self, return NULL; if (igraph_vector_ptr_init(&partition1s, 0)) { - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraph_vector_ptr_init(&cuts, 0)) { igraph_vector_ptr_destroy(&partition1s); - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraphmodule_PyObject_to_attribute_values(capacity_o, @@ -10195,18 +10210,18 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, if (igraph_vector_init(&partition, 0)) { igraph_vector_destroy(&capacity_vector); - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraph_vector_init(&partition2, 0)) { igraph_vector_destroy(&partition); igraph_vector_destroy(&capacity_vector); - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (igraph_vector_init(&cut, 0)) { igraph_vector_destroy(&partition); igraph_vector_destroy(&partition2); igraph_vector_destroy(&capacity_vector); - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); } if (source == -1 && target == -1) { @@ -10238,7 +10253,7 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, if (!cut_o) { igraph_vector_destroy(&partition); igraph_vector_destroy(&partition2); - return 0; + return 0; } part_o=igraphmodule_vector_t_to_PyList(&partition, IGRAPHMODULE_TYPE_INT); @@ -10253,7 +10268,7 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, igraph_vector_destroy(&partition2); if (!part2_o) { Py_DECREF(part_o); - Py_DECREF(cut_o); + Py_DECREF(cut_o); return 0; } @@ -10712,11 +10727,11 @@ PyObject *igraphmodule_Graph_maximum_bipartite_matching(igraphmodule_GraphObject eps = DBL_EPSILON * 1000; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) - return NULL; + return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { if (types != 0) { igraph_vector_bool_destroy(types); free(types); } - return NULL; + return NULL; } if (igraph_vector_long_init(&result, 0)) { @@ -11081,7 +11096,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) return NULL; + ATTRIBUTE_TYPE_EDGE)) return NULL; if (igraph_matrix_init(&merges, 0, 0)) { if (weights != 0) { @@ -11181,7 +11196,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj n -= 1; if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_matrix_destroy(&m); igraph_vector_destroy(&members); return NULL; @@ -11293,7 +11308,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, } if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { - igraphmodule_handle_igraph_error(); + igraphmodule_handle_igraph_error(); return NULL; } @@ -11315,8 +11330,8 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, /*e_weight=*/ e_ws, /*v_weight=*/ v_ws, /*nb_trials=*/nb_trials, /*out*/ &membership, &codelength)) { - igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&membership); + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&membership); if (e_ws) { igraph_vector_destroy(e_ws); free(e_ws); @@ -11342,7 +11357,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, igraph_vector_destroy(&membership); if (!res) - return NULL; + return NULL; return Py_BuildValue("Nd", res, (double)codelength); } @@ -11465,7 +11480,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self * Optimal modularity by integer programming */ PyObject *igraphmodule_Graph_community_optimal_modularity( - igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"weights", NULL}; PyObject *weights_o = Py_None; igraph_real_t modularity; @@ -11478,20 +11493,20 @@ PyObject *igraphmodule_Graph_community_optimal_modularity( return NULL; if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { - igraphmodule_handle_igraph_error(); + igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vector_destroy(&membership); return NULL; } if (igraph_community_optimal_modularity(&self->g, &modularity, &membership, weights)) { - igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&membership); + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&membership); if (weights != 0) { igraph_vector_destroy(weights); free(weights); } @@ -11506,7 +11521,7 @@ PyObject *igraphmodule_Graph_community_optimal_modularity( igraph_vector_destroy(&membership); if (!res) - return NULL; + return NULL; return Py_BuildValue("Nd", res, (double)modularity); } @@ -11549,12 +11564,12 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, } if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { - igraphmodule_handle_igraph_error(); + igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + ATTRIBUTE_TYPE_EDGE)) { igraph_vector_destroy(&membership); return NULL; } @@ -11784,24 +11799,24 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self, igraph_vector_t walk; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OiOO", kwlist, &start_o, - &steps, &mode_o, &stuck_o)) + &steps, &mode_o, &stuck_o)) return NULL; if (igraphmodule_PyObject_to_vid(start_o, &start, &self->g)) - return NULL; + return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) - return NULL; + return NULL; if (igraphmodule_PyObject_to_random_walk_stuck_t(stuck_o, &stuck)) - return NULL; + return NULL; if (igraph_vector_init(&walk, steps)) - return igraphmodule_handle_igraph_error(); + return igraphmodule_handle_igraph_error(); if (igraph_random_walk(&self->g, &walk, start, mode, steps, stuck)) { - igraph_vector_destroy(&walk); - return igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&walk); + return igraphmodule_handle_igraph_error(); } res = igraphmodule_vector_t_to_PyList(&walk, IGRAPHMODULE_TYPE_INT); @@ -12296,17 +12311,17 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param loops: whether self-loops are allowed.\n"}, /* interface to igraph_famous */ - {"Famous", (PyCFunction) igraphmodule_Graph_Famous, - METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Famous(name)\n\n" - "Generates a famous graph based on its name.\n\n" - "Several famous graphs are known to C{igraph} including (but not limited to)\n" - "the Chvatal graph, the Petersen graph or the Tutte graph. This method\n" - "generates one of them based on its name (case insensitive). See the\n" - "documentation of the C interface of C{igraph} for the names available:\n" - "U{http://igraph.org/doc/c}.\n\n" - "@param name: the name of the graph to be generated.\n" - }, + {"Famous", (PyCFunction) igraphmodule_Graph_Famous, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "Famous(name)\n\n" + "Generates a famous graph based on its name.\n\n" + "Several famous graphs are known to C{igraph} including (but not limited to)\n" + "the Chvatal graph, the Petersen graph or the Tutte graph. This method\n" + "generates one of them based on its name (case insensitive). See the\n" + "documentation of the C interface of C{igraph} for the names available:\n" + "U{http://igraph.org/doc/c}.\n\n" + "@param name: the name of the graph to be generated.\n" + }, /* interface to igraph_forest_fire_game */ {"Forest_Fire", (PyCFunction) igraphmodule_Graph_Forest_Fire, @@ -12501,20 +12516,20 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param circular: whether the generated lattice is periodic.\n"}, /* interface to igraph_lcf */ - {"LCF", (PyCFunction) igraphmodule_Graph_LCF, - METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "LCF(n, shifts, repeats)\n\n" - "Generates a graph from LCF notation.\n\n" - "LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation\n" - "for 3-regular Hamiltonian graphs. It consists of three parameters,\n" - "the number of vertices in the graph, a list of shifts giving\n" - "additional edges to a cycle backbone and another integer giving how\n" - "many times the shifts should be performed. See\n" - "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" - "@param n: the number of vertices\n" - "@param shifts: the shifts in a list or tuple\n" - "@param repeats: the number of repeats\n" - }, + {"LCF", (PyCFunction) igraphmodule_Graph_LCF, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "LCF(n, shifts, repeats)\n\n" + "Generates a graph from LCF notation.\n\n" + "LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation\n" + "for 3-regular Hamiltonian graphs. It consists of three parameters,\n" + "the number of vertices in the graph, a list of shifts giving\n" + "additional edges to a cycle backbone and another integer giving how\n" + "many times the shifts should be performed. See\n" + "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" + "@param n: the number of vertices\n" + "@param shifts: the shifts in a list or tuple\n" + "@param repeats: the number of repeats\n" + }, // interface to igraph_ring {"Ring", (PyCFunction) igraphmodule_Graph_Ring, @@ -13076,9 +13091,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: a list with the (exact or estimated) edge betweennesses of all\n" " edges.\n"}, - {"eigen_adjacency", (PyCFunction) igraphmodule_Graph_eigen_adjacency, - METH_VARARGS | METH_KEYWORDS, - "" }, + {"eigen_adjacency", (PyCFunction) igraphmodule_Graph_eigen_adjacency, + METH_VARARGS | METH_KEYWORDS, + "" }, /* interface to igraph_[st_]edge_connectivity */ {"edge_connectivity", (PyCFunction) igraphmodule_Graph_edge_connectivity, @@ -13239,14 +13254,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"convergence_degree", (PyCFunction)igraphmodule_Graph_convergence_degree, METH_NOARGS, "convergence_degree()\n\n" - "Undocumented (yet)." + "Undocumented (yet)." }, /* interface to igraph_convergence_field_size */ {"convergence_field_size", (PyCFunction)igraphmodule_Graph_convergence_field_size, METH_NOARGS, "convergence_field_size()\n\n" - "Undocumented (yet)." + "Undocumented (yet)." }, /* interface to igraph_hub_score */ diff --git a/tests/test_structural.py b/tests/test_structural.py index 5fecf4f43..5e2a1510c 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -26,8 +26,8 @@ def testDensity(self): def testDiameter(self): self.assertTrue(self.gfull.diameter() == 1) - self.assertTrue(isnan(self.gempty.diameter(unconn=False))) - self.assertTrue(isnan(self.gempty.diameter(unconn=False, weights=[]))) + self.assertTrue(self.gempty.diameter(unconn=False) == inf) + self.assertTrue(self.gempty.diameter(unconn=False) == inf) self.assertTrue(self.g.diameter() == 2) self.assertTrue(self.gdir.diameter(False) == 2) self.assertTrue(self.gdir.diameter() == 3) @@ -35,7 +35,7 @@ def testDiameter(self): s, t, d = self.tree.farthest_points() self.assertTrue((s == 13 or t == 13) and d == 5) - self.assertTrue(self.gempty.farthest_points(unconn=False) == (None, None, 10)) + self.assertTrue(self.gempty.farthest_points(unconn=False) == (None, None, inf)) d = self.tree.get_diameter() self.assertTrue(d[0] == 13 or d[-1] == 13) @@ -262,7 +262,7 @@ def testEdgeBetweennessCentrality(self): def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness() - cl2 = [1.0, 0.57142, 0.57142, 0.57142, 0.57142] + cl2 = [1.0, 4 / 7.0, 4 / 7.0, 4 / 7.0, 4 / 7.0] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) From 9f7c150088c0d1d867783ccae65f6ea4b3a82bb2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 26 Jan 2021 16:37:21 +0100 Subject: [PATCH 0313/1892] fix: fix crashes when calling certain attribute combination functions with an empty vector, closes #358 --- src/_igraph/attributes.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index db746334c..0509a1e88 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -994,10 +994,7 @@ static PyObject* igraphmodule_i_ac_first(PyObject* values, igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int n = igraph_vector_size(v); - if (n == 0) - continue; - - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[0]); + item = n > 0 ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[0]) : Py_None; Py_INCREF(item); PyList_SET_ITEM(res, i, item); /* reference to item stolen */ } @@ -1032,19 +1029,20 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int n = igraph_vector_size(v); - if (n == 0) - continue; - - num = PyObject_CallObject(random_func, 0); - if (num == 0) { - Py_DECREF(random_func); - Py_DECREF(res); - return 0; + if (n == 0) { + num = PyObject_CallObject(random_func, 0); + if (num == 0) { + Py_DECREF(random_func); + Py_DECREF(res); + return 0; + } + item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[(long int)(n*PyFloat_AsDouble(num))]); + Py_DECREF(num); + } else { + item = Py_None; } - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[(long int)(n*PyFloat_AsDouble(num))]); Py_INCREF(item); - Py_DECREF(num); PyList_SET_ITEM(res, i, item); /* reference to item stolen */ } @@ -1069,10 +1067,7 @@ static PyObject* igraphmodule_i_ac_last(PyObject* values, igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int n = igraph_vector_size(v); - if (n == 0) - continue; - - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[n-1]); + item = (n > 0) ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[n-1]) : Py_None; Py_INCREF(item); PyList_SET_ITEM(res, i, item); /* reference to item stolen */ } @@ -1143,8 +1138,12 @@ static PyObject* igraphmodule_i_ac_median(PyObject* values, Py_DECREF(res); return 0; } - if (n % 2 == 1) { + if (n == 0) { + item = Py_None; + Py_INCREF(item); + } else if (n % 2 == 1) { item = PyList_GET_ITEM(list, n / 2); + Py_INCREF(item); } else { igraph_real_t num1, num2; item = PyList_GET_ITEM(list, n / 2 - 1); From 692e82ef1dec1f56b3bf4ae13d6da99cf46670f9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 26 Jan 2021 16:38:31 +0100 Subject: [PATCH 0314/1892] format: src/_igraph/attributes.c reformatted without tabs --- src/_igraph/attributes.c | 64 ++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 0509a1e88..0bfe8d269 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1349,12 +1349,12 @@ static int igraphmodule_i_attribute_combine_edges(const igraph_t *graph, /* Getting attribute names and types */ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, - igraph_strvector_t *gnames, - igraph_vector_t *gtypes, - igraph_strvector_t *vnames, - igraph_vector_t *vtypes, - igraph_strvector_t *enames, - igraph_vector_t *etypes) { + igraph_strvector_t *gnames, + igraph_vector_t *gtypes, + igraph_strvector_t *vnames, + igraph_vector_t *vtypes, + igraph_strvector_t *enames, + igraph_vector_t *etypes) { igraph_strvector_t *names[3] = { gnames, vnames, enames }; igraph_vector_t *types[3] = { gtypes, vtypes, etypes }; int retval; @@ -1427,8 +1427,8 @@ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, /* Checks whether the graph has a graph/vertex/edge attribute with the given name */ igraph_bool_t igraphmodule_i_attribute_has_attr(const igraph_t *graph, - igraph_attribute_elemtype_t type, - const char* name) { + igraph_attribute_elemtype_t type, + const char* name) { switch (type) { case IGRAPH_ATTRIBUTE_GRAPH: return igraphmodule_has_graph_attribute(graph, name); @@ -1443,9 +1443,9 @@ igraph_bool_t igraphmodule_i_attribute_has_attr(const igraph_t *graph, /* Returns the type of a given attribute */ int igraphmodule_i_attribute_get_type(const igraph_t *graph, - igraph_attribute_type_t *type, - igraph_attribute_elemtype_t elemtype, - const char *name) { + igraph_attribute_type_t *type, + igraph_attribute_elemtype_t elemtype, + const char *name) { long int attrnum, i, j; int is_numeric, is_string, is_boolean; PyObject *o, *dict; @@ -1511,7 +1511,7 @@ int igraphmodule_i_attribute_get_type(const igraph_t *graph, /* Getting Boolean graph attributes */ int igraphmodule_i_get_boolean_graph_attr(const igraph_t *graph, - const char *name, igraph_vector_bool_t *value) { + const char *name, igraph_vector_bool_t *value) { PyObject *dict, *o; dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_GRAPH]; /* No error checking, if we get here, the type has already been checked by previous @@ -1526,7 +1526,7 @@ int igraphmodule_i_get_boolean_graph_attr(const igraph_t *graph, /* Getting numeric graph attributes */ int igraphmodule_i_get_numeric_graph_attr(const igraph_t *graph, - const char *name, igraph_vector_t *value) { + const char *name, igraph_vector_t *value) { PyObject *dict, *o, *result; dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_GRAPH]; /* No error checking, if we get here, the type has already been checked by previous @@ -1549,7 +1549,7 @@ int igraphmodule_i_get_numeric_graph_attr(const igraph_t *graph, /* Getting string graph attributes */ int igraphmodule_i_get_string_graph_attr(const igraph_t *graph, - const char *name, igraph_strvector_t *value) { + const char *name, igraph_strvector_t *value) { PyObject *dict, *o, *str = 0; const char* c_str; @@ -1603,9 +1603,9 @@ int igraphmodule_i_get_string_graph_attr(const igraph_t *graph, /* Getting numeric vertex attributes */ int igraphmodule_i_get_numeric_vertex_attr(const igraph_t *graph, - const char *name, - igraph_vs_t vs, - igraph_vector_t *value) { + const char *name, + igraph_vs_t vs, + igraph_vector_t *value) { PyObject *dict, *list, *result, *o; igraph_vector_t newvalue; @@ -1643,9 +1643,9 @@ int igraphmodule_i_get_numeric_vertex_attr(const igraph_t *graph, /* Getting string vertex attributes */ int igraphmodule_i_get_string_vertex_attr(const igraph_t *graph, - const char *name, - igraph_vs_t vs, - igraph_strvector_t *value) { + const char *name, + igraph_vs_t vs, + igraph_strvector_t *value) { PyObject *dict, *list, *result; igraph_strvector_t newvalue; @@ -1697,9 +1697,9 @@ int igraphmodule_i_get_string_vertex_attr(const igraph_t *graph, /* Getting boolean vertex attributes */ int igraphmodule_i_get_boolean_vertex_attr(const igraph_t *graph, - const char *name, - igraph_vs_t vs, - igraph_vector_bool_t *value) { + const char *name, + igraph_vs_t vs, + igraph_vector_bool_t *value) { PyObject *dict, *list, *o; igraph_vector_bool_t newvalue; @@ -1733,9 +1733,9 @@ int igraphmodule_i_get_boolean_vertex_attr(const igraph_t *graph, /* Getting numeric edge attributes */ int igraphmodule_i_get_numeric_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_vector_t *value) { + const char *name, + igraph_es_t es, + igraph_vector_t *value) { PyObject *dict, *list, *result, *o; igraph_vector_t newvalue; @@ -1773,9 +1773,9 @@ int igraphmodule_i_get_numeric_edge_attr(const igraph_t *graph, /* Getting string edge attributes */ int igraphmodule_i_get_string_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_strvector_t *value) { + const char *name, + igraph_es_t es, + igraph_strvector_t *value) { PyObject *dict, *list, *result; igraph_strvector_t newvalue; @@ -1825,9 +1825,9 @@ int igraphmodule_i_get_string_edge_attr(const igraph_t *graph, /* Getting boolean edge attributes */ int igraphmodule_i_get_boolean_edge_attr(const igraph_t *graph, - const char *name, - igraph_es_t es, - igraph_vector_bool_t *value) { + const char *name, + igraph_es_t es, + igraph_vector_bool_t *value) { PyObject *dict, *list, *o; igraph_vector_bool_t newvalue; From b71d7af49bfc3330de450f85f0c9a497ee9a58ff Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Jan 2021 14:48:25 +0100 Subject: [PATCH 0315/1892] fix: fix 'random' attribute combination that I broke in the previous commit --- src/_igraph/attributes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 0bfe8d269..f0a027fa1 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1029,7 +1029,7 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int n = igraph_vector_size(v); - if (n == 0) { + if (n > 0) { num = PyObject_CallObject(random_func, 0); if (num == 0) { Py_DECREF(random_func); From e5adcf0891de6c9c827a3f68a3fcceb6569f467b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Jan 2021 14:49:17 +0100 Subject: [PATCH 0316/1892] chore: bumped to latest igraph development version --- src/_igraph/graphobject.c | 4 ++-- tests/test_structural.py | 4 ++-- vendor/source/igraph | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 73ef24061..bab3391ac 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4079,7 +4079,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, } if (cutoff == Py_None) { - if (igraph_closeness(&self->g, &res, vs, mode, weights, + if (igraph_closeness(&self->g, &res, 0, 0, vs, mode, weights, PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); @@ -4093,7 +4093,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, igraph_vs_destroy(&vs); igraph_vector_destroy(&res); return NULL; } - if (igraph_closeness_cutoff(&self->g, &res, vs, mode, weights, + if (igraph_closeness_cutoff(&self->g, &res, 0, 0, vs, mode, weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); diff --git a/tests/test_structural.py b/tests/test_structural.py index 5e2a1510c..f001bf37a 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -269,7 +269,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) with warnings.catch_warnings(): warnings.simplefilter("ignore") - cl = g.closeness(cutoff=0.9) + cl = g.closeness(cutoff=1.0) cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -285,7 +285,7 @@ def testClosenessCentrality(self): g = Graph.Star(5) with warnings.catch_warnings(): warnings.simplefilter("ignore") - cl = g.closeness(cutoff=0.9, weights=weights) + cl = g.closeness(cutoff=1.0, weights=weights) cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) diff --git a/vendor/source/igraph b/vendor/source/igraph index 1d422e68c..869be278f 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 1d422e68c735888fff755e23912cc9dac269ce40 +Subproject commit 869be278ffa5bc97e3cb7b08f58d2b111c9dd47b From 9e632a44ddc72f5f8446eb4095787097fbf97419 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Jan 2021 18:05:43 +0100 Subject: [PATCH 0317/1892] fix: unit tests now pass again --- tests/test_basic.py | 15 +++++++++++++++ tests/test_structural.py | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index 469506597..67367d504 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -725,24 +725,39 @@ def __new__(cls, *args, **kwds): result.new_called = True return result + @classmethod + def Adjacency(cls, *args, **kwds): + result = super(InheritedGraph, cls).Adjacency(*args, **kwds) + result.adjacency_called = True + return result + class InheritanceTests(unittest.TestCase): def testInitCalledProperly(self): g = InheritedGraph() + self.assertTrue(isinstance(g, InheritedGraph)) self.assertTrue(getattr(g, "init_called", False)) def testNewCalledProperly(self): g = InheritedGraph() + self.assertTrue(isinstance(g, InheritedGraph)) self.assertTrue(getattr(g, "new_called", False)) def testInitCalledProperlyWithClassMethod(self): g = InheritedGraph.Tree(3, 2) + self.assertTrue(isinstance(g, InheritedGraph)) self.assertTrue(getattr(g, "init_called", False)) def testNewCalledProperlyWithClassMethod(self): g = InheritedGraph.Tree(3, 2) + self.assertTrue(isinstance(g, InheritedGraph)) self.assertTrue(getattr(g, "new_called", False)) + def testCallingClassMethodInSuperclass(self): + g = InheritedGraph.Adjacency([[0, 1, 1], [1, 0, 0], [1, 0, 0]]) + self.assertTrue(isinstance(g, InheritedGraph)) + self.assertTrue(getattr(g, "adjacency_called", True)) + def suite(): basic_suite = unittest.makeSuite(BasicTests) diff --git a/tests/test_structural.py b/tests/test_structural.py index f001bf37a..1b5e25618 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -270,7 +270,7 @@ def testClosenessCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1.0) - cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] + cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -286,7 +286,7 @@ def testClosenessCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.closeness(cutoff=1.0, weights=weights) - cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] + cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) From 68cf55271447342c1a75ce81cbd22fd5747c4431 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 19:43:05 +1100 Subject: [PATCH 0318/1892] Try github actions --- .github/workflows/build.yml | 136 ++++++++++++++++++++++++++++++++++++ tox.ini | 8 +++ 2 files changed, 144 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..5c1bf328f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,136 @@ +name: "Build and deploy" + +on: + - push + - pull_request + +jobs: + build_linux: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + - pypy-3.7 + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install OS dependencies + run: + sudo apt-get install gfortran flex bison + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox + + build_osx: + runs-on: macos-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox + + wheels_linux: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + - pypy-3.7 + needs: build_linux + if: startsWith(${{ github.ref }}, 'refs/tags') + steps: + - name: Wheels (linux) + env: + - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + - CIBW_TEST_COMMAND="cd {project} && python -m unittest" + - CIBW_SKIP="cp35-*" + run: | + wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 + sudo python3 -m pip install cibuildwheel==1.6.1 + python setup.py -q sdist + python3 -m cibuildwheel --output-dir wheelhouse + + wheels_osx: + runs-on: macos-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + + needs: build_osx + if: startsWith(${{ github.ref }}, 'refs/tags') + steps: + - name: Wheels (OSX) + run: | + python3 -m pip install cibuildwheel==1.6.1 + python3 -m cibuildwheel --output-dir wheelhouse + env: + - CIBW_BEFORE_BUILD="python setup.py build_c_core" + - CIBW_TEST_COMMAND="cd {project} && python -m unittest" + + create_release: + runs-on: ubuntu-latest + needs: + - wheels_linux + - wheels_osx + if: startsWith(${{ github.ref }}, 'refs/tags') + steps: + - name: Config deploy + run: | + git config --local user.name "ntamas" + git config --local user.email "ntamas@gmail.com" + + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: true + prerelease: false + + - name: Upload binaries and source + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + diff --git a/tox.ini b/tox.ini index e70312f9f..212abe28b 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,14 @@ [tox] envlist = py36, py37, py38, py39, pypy, pypy3 +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + pypy-3.7: pypy3 + [testenv] commands = python -m unittest deps = From b09aa0ce345eae2448aee5662944d5de11f002fc Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 19:47:23 +1100 Subject: [PATCH 0319/1892] Env var syntax --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c1bf328f..1d4a120dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,9 +70,9 @@ jobs: steps: - name: Wheels (linux) env: - - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - - CIBW_TEST_COMMAND="cd {project} && python -m unittest" - - CIBW_SKIP="cp35-*" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp35-*" run: | wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 sudo python3 -m pip install cibuildwheel==1.6.1 @@ -97,8 +97,8 @@ jobs: python3 -m pip install cibuildwheel==1.6.1 python3 -m cibuildwheel --output-dir wheelhouse env: - - CIBW_BEFORE_BUILD="python setup.py build_c_core" - - CIBW_TEST_COMMAND="cd {project} && python -m unittest" + CIBW_BEFORE_BUILD: "python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" create_release: runs-on: ubuntu-latest From 948e303ebe0a714dd20d4e54d209686bbfd1e824 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 19:51:20 +1100 Subject: [PATCH 0320/1892] Syntax in workflow --- .github/workflows/build.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1d4a120dd..ebc5203b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -129,8 +129,5 @@ jobs: GITHUB_TOKEN: ${{ github.token }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' From 8a820c8e6eae0c49fb5edf25ca229112393b97c3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 19:59:35 +1100 Subject: [PATCH 0321/1892] C core submodule --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ebc5203b8..798cc326c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,8 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Install C core submodule + run: git submodule update --init - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: @@ -44,6 +46,8 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Install C core submodule + run: git submodule update --init - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From 6fd63f87fedc2fbed202db917379c18e5add893f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 20:21:31 +1100 Subject: [PATCH 0322/1892] Jobs -> steps --- .github/workflows/build.yml | 50 +++++++++---------------------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 798cc326c..8a59b01a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,6 +33,17 @@ jobs: pip install tox tox-gh-actions - name: Test with tox run: tox + - name: Wheels (linux) + if: startsWith(${{ github.ref }}, "refs/tags") + env: + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp35-*" + run: | + wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 + sudo python3 -m pip install cibuildwheel==1.6.1 + python setup.py -q sdist + python3 -m cibuildwheel --output-dir wheelhouse build_osx: runs-on: macos-latest @@ -58,45 +69,8 @@ jobs: pip install tox tox-gh-actions - name: Test with tox run: tox - - wheels_linux: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: - - 3.6 - - 3.7 - - 3.8 - - 3.9 - - pypy-3.7 - needs: build_linux - if: startsWith(${{ github.ref }}, 'refs/tags') - steps: - - name: Wheels (linux) - env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp35-*" - run: | - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - sudo python3 -m pip install cibuildwheel==1.6.1 - python setup.py -q sdist - python3 -m cibuildwheel --output-dir wheelhouse - - wheels_osx: - runs-on: macos-latest - strategy: - matrix: - python-version: - - 3.6 - - 3.7 - - 3.8 - - 3.9 - - needs: build_osx - if: startsWith(${{ github.ref }}, 'refs/tags') - steps: - name: Wheels (OSX) + if: startsWith(${{ github.ref }}, 'refs/tags') run: | python3 -m pip install cibuildwheel==1.6.1 python3 -m cibuildwheel --output-dir wheelhouse From a88c117e9bf893e787921bca872f71bba0e72e1d Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 23 Jan 2021 20:22:17 +1100 Subject: [PATCH 0323/1892] job name typo --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a59b01a4..d6fa4078a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,8 +81,8 @@ jobs: create_release: runs-on: ubuntu-latest needs: - - wheels_linux - - wheels_osx + - build_linux + - build_osx if: startsWith(${{ github.ref }}, 'refs/tags') steps: - name: Config deploy From 53abeee556009530703ae6f68e7fe1fe6aea898a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 14:39:26 +1100 Subject: [PATCH 0324/1892] pip, pypy, and cbuildwheel --- .github/workflows/build.yml | 39 ++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6fa4078a..b8d19ddb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Install C core submodule + - name: Init C core submodule run: git submodule update --init - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 @@ -29,8 +29,12 @@ jobs: sudo apt-get install gfortran flex bison - name: Install dependencies run: | + # Pypi has no pip by default, and ubuntu blocks python -m ensurepip + # However, Github runners are supposed to have pip installed by default + # https://docs.github.com/en/actions/guides/building-and-testing-python + #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install tox tox-gh-actions + pip install tox tox-gh-actions cbuildwheel=1.6.1 - name: Test with tox run: tox - name: Wheels (linux) @@ -40,10 +44,19 @@ jobs: CIBW_TEST_COMMAND: "cd {project} && python -m unittest" CIBW_SKIP: "cp35-*" run: | - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - sudo python3 -m pip install cibuildwheel==1.6.1 python setup.py -q sdist - python3 -m cibuildwheel --output-dir wheelhouse + python -m cibuildwheel --output-dir wheelhouse + - name: Upload source dist + uses: actions/upload-artifact@v2 + with: + name: source-dist + path: dist/python-igraph-*.tar.gz + - name: Upload linux wheels + uses: actions/upload-artifact@v2 + with: + name: linux-wheels + path: wheelhouse/*.whl + build_osx: runs-on: macos-latest @@ -57,7 +70,7 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Install C core submodule + - name: Init C core submodule run: git submodule update --init - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 @@ -66,24 +79,28 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions + pip install tox tox-gh-actions cbuildwheels=1.6.1 - name: Test with tox run: tox - name: Wheels (OSX) - if: startsWith(${{ github.ref }}, 'refs/tags') + if: startsWith(${{ github.ref }}, "refs/tags") run: | - python3 -m pip install cibuildwheel==1.6.1 - python3 -m cibuildwheel --output-dir wheelhouse + python -m cibuildwheel --output-dir wheelhouse env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + - name: Upload linux wheels + uses: actions/upload-artifact@v2 + with: + name: OSX-wheels + path: wheelhouse/*.whl create_release: runs-on: ubuntu-latest needs: - build_linux - build_osx - if: startsWith(${{ github.ref }}, 'refs/tags') + if: startsWith(${{ github.ref }}, "refs/tags") steps: - name: Config deploy run: | From 3240ad1e16dc48dbed0f2c6013138536f6e6d008 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 14:41:06 +1100 Subject: [PATCH 0325/1892] Typo in workflow --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8d19ddb2..049926491 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install tox tox-gh-actions cbuildwheel=1.6.1 + pip install tox tox-gh-actions cbuildwheel==1.6.1 - name: Test with tox run: tox - name: Wheels (linux) @@ -79,7 +79,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions cbuildwheels=1.6.1 + pip install tox tox-gh-actions cbuildwheels==1.6.1 - name: Test with tox run: tox - name: Wheels (OSX) From a5f574d435502f56f76313dd21ccdc84729c8cc6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 14:42:49 +1100 Subject: [PATCH 0326/1892] Typo in workflow --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 049926491..9eb2498d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install tox tox-gh-actions cbuildwheel==1.6.1 + pip install tox tox-gh-actions cibuildwheel==1.6.1 - name: Test with tox run: tox - name: Wheels (linux) @@ -79,7 +79,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions cbuildwheels==1.6.1 + pip install tox tox-gh-actions cibuildwheels==1.6.1 - name: Test with tox run: tox - name: Wheels (OSX) From 5d0dd85b87d894a0c4234c3aa5f26b19e53f9b8c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 14:45:11 +1100 Subject: [PATCH 0327/1892] Do not specify cibuildwheel version --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9eb2498d5..033f8a8d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install tox tox-gh-actions cibuildwheel==1.6.1 + pip install tox tox-gh-actions cibuildwheel - name: Test with tox run: tox - name: Wheels (linux) @@ -79,7 +79,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions cibuildwheels==1.6.1 + pip install tox tox-gh-actions cibuildwheels - name: Test with tox run: tox - name: Wheels (OSX) From c4607d831b26524369715508a2543d74ec850826 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 15:05:41 +1100 Subject: [PATCH 0328/1892] Skip wheels for Python 2.7 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 033f8a8d1..762228b44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,7 @@ jobs: env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp35-*" + CIBW_SKIP: "cp27-* pp27-* cp35-*" run: | python setup.py -q sdist python -m cibuildwheel --output-dir wheelhouse From 040a387dca283257c4100b329dd88e1b51294304 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 15:10:25 +1100 Subject: [PATCH 0329/1892] Separate jobs for wheels, which are in docker anyway --- .github/workflows/build.yml | 52 +++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 762228b44..32b01b711 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,11 +34,35 @@ jobs: # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install tox tox-gh-actions cibuildwheel + pip install tox tox-gh-actions - name: Test with tox run: tox + + wheels_manylinux: + runs-on: ubuntu-latest + python-version: 3.8 + if: startsWith(${{ github.ref }}, "refs/tags") + needs: build_linux + steps: + - uses: actions/checkout@v1 + - name: Init C core submodule + run: git submodule update --init + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install OS dependencies + run: + sudo apt-get install gfortran flex bison + - name: Install dependencies + run: | + # Pypi has no pip by default, and ubuntu blocks python -m ensurepip + # However, Github runners are supposed to have pip installed by default + # https://docs.github.com/en/actions/guides/building-and-testing-python + #wget -qO- https://bootstrap.pypa.io/get-pip.py | python + python -m pip install --upgrade pip + pip install cibuildwheel - name: Wheels (linux) - if: startsWith(${{ github.ref }}, "refs/tags") env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" @@ -82,6 +106,24 @@ jobs: pip install tox tox-gh-actions cibuildwheels - name: Test with tox run: tox + + wheels_osx: + runs-on: macos-latest + python-version: 3.8 + if: startsWith(${{ github.ref }}, "refs/tags") + needs: build_osx + steps: + - uses: actions/checkout@v1 + - name: Init C core submodule + run: git submodule update --init + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install cibuildwheels - name: Wheels (OSX) if: startsWith(${{ github.ref }}, "refs/tags") run: | @@ -97,10 +139,10 @@ jobs: create_release: runs-on: ubuntu-latest - needs: - - build_linux - - build_osx if: startsWith(${{ github.ref }}, "refs/tags") + needs: + - wheels_manylinux + - wheels_osx steps: - name: Config deploy run: | From 33afec16dba3ad7c743929890c9060174b22b4de Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 15:11:35 +1100 Subject: [PATCH 0330/1892] Syntax in workflow --- .github/workflows/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 32b01b711..02f420efa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,10 @@ jobs: wheels_manylinux: runs-on: ubuntu-latest - python-version: 3.8 + strategy: + matrix: + python-version: + - 3.8 if: startsWith(${{ github.ref }}, "refs/tags") needs: build_linux steps: @@ -109,7 +112,10 @@ jobs: wheels_osx: runs-on: macos-latest - python-version: 3.8 + strategy: + matrix: + python-version: + - 3.8 if: startsWith(${{ github.ref }}, "refs/tags") needs: build_osx steps: From 451c6b16f07e938847c70f5799f361df341e82fc Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 25 Jan 2021 15:17:00 +1100 Subject: [PATCH 0331/1892] No need for cibuildwheels during tox --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02f420efa..ed51c9158 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,7 +106,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions cibuildwheels + pip install tox tox-gh-actions - name: Test with tox run: tox From 3cb54ef68fffc85ede372ac004a16067f634b9d8 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 26 Jan 2021 10:27:06 +1100 Subject: [PATCH 0332/1892] Split build and deploy workflows --- .github/workflows/build.yml | 113 +--------------------------------- .github/workflows/deploy.yml | 115 +++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 112 deletions(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed51c9158..0c7d97584 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: "Build and deploy" +name: "Build and test with tox" on: - push @@ -38,53 +38,6 @@ jobs: - name: Test with tox run: tox - wheels_manylinux: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: - - 3.8 - if: startsWith(${{ github.ref }}, "refs/tags") - needs: build_linux - steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: git submodule update --init - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install OS dependencies - run: - sudo apt-get install gfortran flex bison - - name: Install dependencies - run: | - # Pypi has no pip by default, and ubuntu blocks python -m ensurepip - # However, Github runners are supposed to have pip installed by default - # https://docs.github.com/en/actions/guides/building-and-testing-python - #wget -qO- https://bootstrap.pypa.io/get-pip.py | python - python -m pip install --upgrade pip - pip install cibuildwheel - - name: Wheels (linux) - env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp27-* pp27-* cp35-*" - run: | - python setup.py -q sdist - python -m cibuildwheel --output-dir wheelhouse - - name: Upload source dist - uses: actions/upload-artifact@v2 - with: - name: source-dist - path: dist/python-igraph-*.tar.gz - - name: Upload linux wheels - uses: actions/upload-artifact@v2 - with: - name: linux-wheels - path: wheelhouse/*.whl - - build_osx: runs-on: macos-latest strategy: @@ -110,67 +63,3 @@ jobs: - name: Test with tox run: tox - wheels_osx: - runs-on: macos-latest - strategy: - matrix: - python-version: - - 3.8 - if: startsWith(${{ github.ref }}, "refs/tags") - needs: build_osx - steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: git submodule update --init - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install cibuildwheels - - name: Wheels (OSX) - if: startsWith(${{ github.ref }}, "refs/tags") - run: | - python -m cibuildwheel --output-dir wheelhouse - env: - CIBW_BEFORE_BUILD: "python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - - name: Upload linux wheels - uses: actions/upload-artifact@v2 - with: - name: OSX-wheels - path: wheelhouse/*.whl - - create_release: - runs-on: ubuntu-latest - if: startsWith(${{ github.ref }}, "refs/tags") - needs: - - wheels_manylinux - - wheels_osx - steps: - - name: Config deploy - run: | - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - - - name: Create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: true - prerelease: false - - - name: Upload binaries and source - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' - diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..521d11ed1 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,115 @@ +name: "Build wheels and deploy" + +on: + push: + tags: + - '*.*.*' + +jobs: + wheels_manylinux: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.8 + needs: build_linux + steps: + - uses: actions/checkout@v1 + - name: Init C core submodule + run: git submodule update --init + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install OS dependencies + run: + sudo apt-get install gfortran flex bison + - name: Install dependencies + run: | + # Pypi has no pip by default, and ubuntu blocks python -m ensurepip + # However, Github runners are supposed to have pip installed by default + # https://docs.github.com/en/actions/guides/building-and-testing-python + #wget -qO- https://bootstrap.pypa.io/get-pip.py | python + python -m pip install --upgrade pip + pip install cibuildwheel + - name: Wheels (linux) + env: + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp27-* pp27-* cp35-*" + run: | + python setup.py -q sdist + python -m cibuildwheel --output-dir wheelhouse + - name: Upload source dist + uses: actions/upload-artifact@v2 + with: + name: source-dist + path: dist/python-igraph-*.tar.gz + - name: Upload linux wheels + uses: actions/upload-artifact@v2 + with: + name: linux-wheels + path: wheelhouse/*.whl + + wheels_osx: + runs-on: macos-latest + strategy: + matrix: + python-version: + - 3.8 + needs: build_osx + steps: + - uses: actions/checkout@v1 + - name: Init C core submodule + run: git submodule update --init + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install cibuildwheels + - name: Wheels (OSX) + if: startsWith(${{ github.ref }}, "refs/tags") + run: | + python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BEFORE_BUILD: "python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + - name: Upload linux wheels + uses: actions/upload-artifact@v2 + with: + name: OSX-wheels + path: wheelhouse/*.whl + + create_release: + runs-on: ubuntu-latest + needs: + - wheels_manylinux + - wheels_osx + steps: + - name: Config deploy + run: | + git config --local user.name "ntamas" + git config --local user.email "ntamas@gmail.com" + + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: true + prerelease: false + + - name: Upload binaries and source + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + From 92550337bfd1148842127d91662e02a208654fa4 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 11:54:12 +1100 Subject: [PATCH 0333/1892] Brew autotools on OSX --- .github/workflows/build.yml | 7 +++++-- .github/workflows/deploy.yml | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c7d97584..30a219771 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: - name: Install OS dependencies run: sudo apt-get install gfortran flex bison - - name: Install dependencies + - name: Install Python dependencies run: | # Pypi has no pip by default, and ubuntu blocks python -m ensurepip # However, Github runners are supposed to have pip installed by default @@ -56,7 +56,10 @@ jobs: uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install OS dependencies + run: + brew install autoconf automake libtool + - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install tox tox-gh-actions diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 521d11ed1..b1ca0c641 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -24,7 +24,7 @@ jobs: - name: Install OS dependencies run: sudo apt-get install gfortran flex bison - - name: Install dependencies + - name: Install Python dependencies run: | # Pypi has no pip by default, and ubuntu blocks python -m ensurepip # However, Github runners are supposed to have pip installed by default @@ -66,7 +66,10 @@ jobs: uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install OS dependencies + run: + brew install autoconf automake libtool + - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install cibuildwheels From aae35eb0cb330181fbffa120b488eabc76d5d669 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 12:25:33 +1100 Subject: [PATCH 0334/1892] Test deploy workflow --- .github/workflows/deploy.yml | 45 ++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b1ca0c641..26fa1c81c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,9 +1,11 @@ name: "Build wheels and deploy" on: - push: - tags: - - '*.*.*' + #FIXME: for testing, remove comments + - push + #push: + # tags: + # - '*.*.*' jobs: wheels_manylinux: @@ -108,11 +110,36 @@ jobs: draft: true prerelease: false - - name: Upload binaries and source - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ github.token }} + - name: Download artifacts: source dist + uses: actions/download-artifact@v2 + with: + name: source-dist + path: dist + + - name: Download artifacts: linux wheels + uses: actions/download-artifact@v2 with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + name: linux-wheels + path: wheelhouse + + - name: Download artifacts: OSX wheels + uses: actions/download-artifact@v2 + with: + name: OSX-wheels + path: wheelhouse + + - name: List contents of artifact folders + run: | + echo "dist folder:" + ls -lh dist + echo "wheelhouse folder:" + ls -lh wheelhouse + + #- name: Upload binaries and source + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ github.token }} + # with: + # upload_url: ${{ steps.create_release.outputs.upload_url }} + # asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' From 2da38d3a0a72c70ab8ecf99523b23fc2cd19d654 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 12:26:41 +1100 Subject: [PATCH 0335/1892] Syntax in deploy yml --- .github/workflows/deploy.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 26fa1c81c..2a3b16820 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -110,25 +110,25 @@ jobs: draft: true prerelease: false - - name: Download artifacts: source dist + - name: "Download artifacts: source dist" uses: actions/download-artifact@v2 with: name: source-dist path: dist - - name: Download artifacts: linux wheels + - name: "Download artifacts: linux wheels" uses: actions/download-artifact@v2 with: name: linux-wheels path: wheelhouse - - name: Download artifacts: OSX wheels + - name: "Download artifacts: OSX wheels" uses: actions/download-artifact@v2 with: name: OSX-wheels path: wheelhouse - - name: List contents of artifact folders + - name: "List contents of artifact folders" run: | echo "dist folder:" ls -lh dist From 9449beb285dc115ced480ee10663e873365531e7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 12:27:19 +1100 Subject: [PATCH 0336/1892] Syntax in deploy yml, split in two --- .github/workflows/deploy.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2a3b16820..baa661f39 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,7 +14,6 @@ jobs: matrix: python-version: - 3.8 - needs: build_linux steps: - uses: actions/checkout@v1 - name: Init C core submodule @@ -59,7 +58,6 @@ jobs: matrix: python-version: - 3.8 - needs: build_osx steps: - uses: actions/checkout@v1 - name: Init C core submodule From c4de217410c51fa381376f77540106d7a585a55f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 13:16:57 +1100 Subject: [PATCH 0337/1892] Typo in cibuildwheel --- .github/workflows/deploy.yml | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index baa661f39..74d7de0f4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,18 +10,12 @@ on: jobs: wheels_manylinux: runs-on: ubuntu-latest - strategy: - matrix: - python-version: - - 3.8 steps: - uses: actions/checkout@v1 - name: Init C core submodule run: git submodule update --init - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - name: Install OS dependencies run: sudo apt-get install gfortran flex bison @@ -54,27 +48,20 @@ jobs: wheels_osx: runs-on: macos-latest - strategy: - matrix: - python-version: - - 3.8 steps: - uses: actions/checkout@v1 - name: Init C core submodule run: git submodule update --init - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - name: Install OS dependencies run: brew install autoconf automake libtool - name: Install Python dependencies run: | python -m pip install --upgrade pip - pip install cibuildwheels + pip install cibuildwheel - name: Wheels (OSX) - if: startsWith(${{ github.ref }}, "refs/tags") run: | python -m cibuildwheel --output-dir wheelhouse env: @@ -133,11 +120,10 @@ jobs: echo "wheelhouse folder:" ls -lh wheelhouse - #- name: Upload binaries and source - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ github.token }} - # with: - # upload_url: ${{ steps.create_release.outputs.upload_url }} - # asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + #- name: Upload binaries and source + # uses: alexellis/upload-assets@0.2.2 + # env: + # GITHUB_TOKEN: ${{ github.token }} + # with: + # asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' From 7fba20954d00accfacad3ab2fd5825a7ee299ba2 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 13:23:06 +1100 Subject: [PATCH 0338/1892] Skip python 2.7 on mac wheels --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 74d7de0f4..5dbe95f95 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -67,6 +67,7 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp27-* pp27-* cp35-*" - name: Upload linux wheels uses: actions/upload-artifact@v2 with: From d9cfb3ef8029b40b7c35e141a5c922817c0a1691 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 14:02:27 +1100 Subject: [PATCH 0339/1892] Remove git config, unnecessary --- .github/workflows/deploy.yml | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5dbe95f95..b82aa755b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -80,22 +80,6 @@ jobs: - wheels_manylinux - wheels_osx steps: - - name: Config deploy - run: | - git config --local user.name "ntamas" - git config --local user.email "ntamas@gmail.com" - - - name: Create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: true - prerelease: false - - name: "Download artifacts: source dist" uses: actions/download-artifact@v2 with: @@ -121,6 +105,17 @@ jobs: echo "wheelhouse folder:" ls -lh wheelhouse + - name: Create release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: true + prerelease: false + #- name: Upload binaries and source # uses: alexellis/upload-assets@0.2.2 # env: From 8f1c6456bfd9bfa47a453757bcf75354553b027c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 18:35:00 +1100 Subject: [PATCH 0340/1892] Restore tag workflow to tags --- .github/workflows/deploy.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b82aa755b..749349465 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,11 +1,9 @@ name: "Build wheels and deploy" on: - #FIXME: for testing, remove comments - - push - #push: - # tags: - # - '*.*.*' + push: + tags: + - '*.*.*' jobs: wheels_manylinux: @@ -116,10 +114,10 @@ jobs: draft: true prerelease: false - #- name: Upload binaries and source - # uses: alexellis/upload-assets@0.2.2 - # env: - # GITHUB_TOKEN: ${{ github.token }} - # with: - # asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' + - name: Upload binaries and source + uses: alexellis/upload-assets@0.2.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' From adb252ad2a4023f78362a6bf57626d5596dcac1f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 18:35:48 +1100 Subject: [PATCH 0341/1892] Remove travis.yml --- .travis.yml | 80 ----------------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8265b24c8..000000000 --- a/.travis.yml +++ /dev/null @@ -1,80 +0,0 @@ -dist: bionic -language: python - -python: - - "3.6" - - "3.7" - - "3.8" - - "3.9-dev" - - pypy3 - -addons: - apt: - packages: - - gfortran - - flex - - bison - -install: - - python -m pip install tox-travis - -script: - - tox - -jobs: - include: - - stage: test - services: docker - - - stage: wheels - services: docker - language: shell - env: - - CIBW_BEFORE_BUILD="yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" - - CIBW_TEST_COMMAND="cd {project} && python -m unittest" - - CIBW_SKIP="cp35-*" - install: - - wget -qO- https://bootstrap.pypa.io/get-pip.py | sudo python3 - - sudo python3 -m pip install cibuildwheel==1.6.1 - script: - - python setup.py -q sdist - - python3 -m cibuildwheel --output-dir wheelhouse - before_deploy: &before_deploy_releases - - git config --local user.name "ntamas" - - git config --local user.email "ntamas@gmail.com" - # - export TRAVIS_TAG=0.8.0 - # - git tag $TRAVIS_TAG - deploy: &deploy_releases - provider: releases - token: - secure: CAn8qENTIZSFed7VjqcQR42mjrPGV+QptW2XkncPaRwFooizPKgRsphgKzgv7k7peEQhQs/WOEtL0a3ofYRbbucOVbJ/nTVI0qGba9Lz/afsQ2UsbGnan0hXua9D/bo1wRhgqz8j0q6LHb3O8rgQOAKi8hWCChglr2saeRsy5Fc= - file: - - wheelhouse/*.whl - - dist/python-igraph-${TRAVIS_TAG}.tar.gz - file_glob: true - draft: true - edge: true - overwrite: true - cleanup: false - on: - repo: igraph/python-igraph - tags: true - - - stage: wheels - os: osx - osx_image: xcode11.2 - language: shell - env: - - CIBW_BEFORE_BUILD="python setup.py build_c_core" - - CIBW_TEST_COMMAND="cd {project} && python -m unittest" - install: - - python3 -m pip install cibuildwheel==1.6.1 - script: - - python3 -m cibuildwheel --output-dir wheelhouse - before_deploy: *before_deploy_releases - deploy: *deploy_releases - -notifications: - email: - on_success: change - on_failure: always From 08d73e424518d7099f4992e1bf27318dc758db8c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 19:50:55 +1100 Subject: [PATCH 0342/1892] Try different action for deploying --- .github/workflows/deploy.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 749349465..51a394fc8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -115,9 +115,7 @@ jobs: prerelease: false - name: Upload binaries and source - uses: alexellis/upload-assets@0.2.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + uses: AButler/upload-release-assets@v2.0 with: - asset_paths: '["wheelhouse/*.whl", "dist/python-igraph-*.tar.gz"]' - + files: 'wheelhouse/*.whl;dist/python-igraph-*.tar.gz' + repo-token: ${{ secrets.GITHUB_TOKEN }} From db0a8db181041ee49efc85d6a6ab6a39b8e00dec Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 19:53:46 +1100 Subject: [PATCH 0343/1892] Ignore build on tags --- .github/workflows/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 30a219771..7e54e0d98 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,14 @@ name: "Build and test with tox" on: - - push - - pull_request + push: + tags-ignore: + - '*.*.*' + pull_request: + tags-ignore: + - '*.*.*' + + jobs: build_linux: From 666e83b8e6b31635fdab8335d1d46ccaf313c27e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 27 Jan 2021 19:55:52 +1100 Subject: [PATCH 0344/1892] Syntax to ignore tags --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e54e0d98..db8c52171 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,13 @@ name: "Build and test with tox" on: push: + branches: + - '*' tags-ignore: - '*.*.*' pull_request: + branches: + - '*' tags-ignore: - '*.*.*' From 81b62499e11f718eafa391762fa56a7130ae6f9b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 08:33:16 +1100 Subject: [PATCH 0345/1892] Add manual trigger for deploy --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 51a394fc8..08f44b33f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,6 +5,8 @@ on: tags: - '*.*.*' + workflow_dispatch: + jobs: wheels_manylinux: runs-on: ubuntu-latest From 85dfd295e3b21049e1bc60dc637f67536d3518e0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 08:36:26 +1100 Subject: [PATCH 0346/1892] Test syntax for manual dispatch --- .github/workflows/deploy.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 08f44b33f..6b93f8232 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -6,6 +6,9 @@ on: - '*.*.*' workflow_dispatch: + inputs: + tags: + description: 'Test wheels and deploy' jobs: wheels_manylinux: From 4e4249b3f7874dabcb20b413e02e5a0304774efe Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 08:46:24 +1100 Subject: [PATCH 0347/1892] Add repository dispatch --- .github/workflows/deploy.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6b93f8232..6d954366e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,10 +5,8 @@ on: tags: - '*.*.*' + repository_dispatch: workflow_dispatch: - inputs: - tags: - description: 'Test wheels and deploy' jobs: wheels_manylinux: From 679ef11a6228b241456fe4219f062965edff7189 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 09:18:52 +1100 Subject: [PATCH 0348/1892] Remore repo dispatch and add instructions --- .github/workflows/deploy.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6d954366e..081f8d9c2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,11 +1,14 @@ name: "Build wheels and deploy" +# To trigger manually, make yourself an auth token including "workflow" scope and run: +# curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token " https://api.github.com/repos/igraph/python-igraph/actions/workflows/deploy.yml/dispatches -d '{"ref":"master"}' +# If you want to release from another branch and not "master", change the last string. + on: push: tags: - '*.*.*' - repository_dispatch: workflow_dispatch: jobs: From fb0370360a7ea5fa2a437c5c3fe985ffe7c05a3a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 16:25:17 +1100 Subject: [PATCH 0349/1892] Some bash magic to overcome manual triggering --- .github/workflows/deploy.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 081f8d9c2..218fe07ab 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,11 +5,11 @@ name: "Build wheels and deploy" # If you want to release from another branch and not "master", change the last string. on: + workflow_dispatch: push: tags: - '*.*.*' - workflow_dispatch: jobs: wheels_manylinux: @@ -109,14 +109,19 @@ jobs: echo "wheelhouse folder:" ls -lh wheelhouse + - name: Figure out version + id: get_version + run: | + echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> GITHUB_ENV + - name: Create release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} + tag_name: ${{ env.igraph_version }} + release_name: Release ${{ env.igraph_version }} draft: true prerelease: false @@ -125,3 +130,4 @@ jobs: with: files: 'wheelhouse/*.whl;dist/python-igraph-*.tar.gz' repo-token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ env.igraph_version }} From d84cfc50273f276bcbfa7c29a67da1b25d4329fe Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 28 Jan 2021 22:18:09 +1100 Subject: [PATCH 0350/1892] Check env variable --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 218fe07ab..f16f684ac 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -113,6 +113,7 @@ jobs: id: get_version run: | echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> GITHUB_ENV + tail -n 1 $GITHUB_ENV - name: Create release id: create_release From 01264d1ac58533f500502623a4458450734c7aa4 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 08:15:48 +1100 Subject: [PATCH 0351/1892] Better title for step --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f16f684ac..76ceaa136 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -109,7 +109,7 @@ jobs: echo "wheelhouse folder:" ls -lh wheelhouse - - name: Figure out version + - name: Store igraph version id: get_version run: | echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> GITHUB_ENV From f2c44e3b6fdf7f0ff99cbdab0b78cc6abf80f1a7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 17:02:55 +1100 Subject: [PATCH 0352/1892] Forgot $ in bash variable --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 76ceaa136..75f7d5264 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -112,7 +112,7 @@ jobs: - name: Store igraph version id: get_version run: | - echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> GITHUB_ENV + echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> $GITHUB_ENV tail -n 1 $GITHUB_ENV - name: Create release From 673d139a813ed2ea8d8e1cacffb392b5e46a1725 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 18:40:09 +1100 Subject: [PATCH 0353/1892] Make upload assets for loops by hand --- .github/workflows/deploy.yml | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 75f7d5264..3812df96f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -126,9 +126,33 @@ jobs: draft: true prerelease: false + #- name: Upload binaries and source + # uses: AButler/upload-release-assets@v2.0 + # with: + # files: 'wheelhouse/*.whl;dist/python-igraph-*.tar.gz' + # repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Move artifacts into one folder + run: | + mkdir upload + mv dist/* upload/ + mv wheelhouse/* upload/ + ls upload + - name: Upload binaries and source - uses: AButler/upload-release-assets@v2.0 + uses: actions/github-script@v3 with: - files: 'wheelhouse/*.whl;dist/python-igraph-*.tar.gz' - repo-token: ${{ secrets.GITHUB_TOKEN }} - release-tag: ${{ env.igraph_version }} + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const path = require('path'); + const fs = require('fs'); + const release_id = '${{ needs.create_release.outputs.id }}'; + for (let file of await fs.readdirSync('./upload/')) { + console.log('uploadReleaseAsset', file); + await github.repos.uploadReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: release_id, + name: file, + data: await fs.readFileSync(`./${file}`) + }); + } From 37e05108208994592c3e65c4bb21b352bdc586f3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 19:54:28 +1100 Subject: [PATCH 0354/1892] Syntax of github script --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3812df96f..3d04d14e8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -153,6 +153,6 @@ jobs: repo: context.repo.repo, release_id: release_id, name: file, - data: await fs.readFileSync(`./${file}`) + data: await fs.readFileSync(`./upload/${file}`) }); } From f39b03855ace3cdb646779f77ee3f17362a92659 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 21:08:19 +1100 Subject: [PATCH 0355/1892] Syntax in github script --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3d04d14e8..4ee06b956 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -145,7 +145,7 @@ jobs: script: | const path = require('path'); const fs = require('fs'); - const release_id = '${{ needs.create_release.outputs.id }}'; + const release_id = '${{ steps.create_release.outputs.id }}'; for (let file of await fs.readdirSync('./upload/')) { console.log('uploadReleaseAsset', file); await github.repos.uploadReleaseAsset({ From f02f420686bdb6f0e4386a07294cbdd257c35d3a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 20 Jan 2021 10:18:35 +1100 Subject: [PATCH 0356/1892] Generate graph from scipy sparse matrix --- src/igraph/__init__.py | 45 +++++++++++++++ src/igraph/sparse_matrix.py | 109 ++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/igraph/sparse_matrix.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 6f05e44ac..0f2c2fb41 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -41,6 +41,7 @@ from igraph.layout import * from igraph.matching import * from igraph.operators import * +from igraph.sparse_matrix import * from igraph.statistics import * from igraph.summary import * from igraph.utils import * @@ -2105,6 +2106,50 @@ def Read_Adjacency( return graph + @classmethod + def Adjacency(klass, matrix, mode=ADJ_DIRECTED): + """Generates a graph from its adjacency matrix. + + @param matrix: the adjacency matrix. Possible types are: + - a list of lists + - a numpy 2D array or matrix (will be converted to list of lists) + - a scipy.sparse matrix (will be converted to a COO matrix, but not + to a dense matrix) + @param mode: the mode to be used. Possible values are: + + - C{ADJ_DIRECTED} - the graph will be directed and a matrix + element gives the number of edges between two vertex. + - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience. + - C{ADJ_MAX} - undirected graph will be created and the number of + edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} + - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))} + - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)} + - C{ADJ_UPPER} - undirected graph with the upper right triangle of + the matrix (including the diagonal) + - C{ADJ_LOWER} - undirected graph with the lower left triangle of + the matrix (including the diagonal) + + These values can also be given as strings without the C{ADJ} prefix. + + """ + try: + import numpy as np + except ImportError: + np = None + + try: + from scipy import sparse + except ImportError: + sparse = None + + if (sparse is not None) and isinstance(matrix, sparse.spmatrix): + return _graph_from_sparse_matrix(klass, matrix, mode=mode) + + if (np is not None) and isinstance(matrix, np.ndarray): + matrix = matrix.tolist() + + return GraphBase.Adjacency(klass, matrix, mode=mode) + def write_dimacs(self, f, source=None, target=None, capacity="capacity"): """Writes the graph in DIMACS format to the given file. diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py new file mode 100644 index 000000000..dc86d0a37 --- /dev/null +++ b/src/igraph/sparse_matrix.py @@ -0,0 +1,109 @@ +# vim:ts=4:sw=4:sts=4:et +# -*- coding: utf-8 -*- +"""Implementation of union, disjoint union and intersection operators.""" + +from __future__ import with_statement + +__all__ = () +__docformat__ = "restructuredtext en" +__license__ = u""" +Copyright (C) 2021 igraph development team + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA +""" + +# pylint: disable-msg=W0401 +# W0401: wildcard import +from igraph._igraph import * + + +# Logic to get graph from scipy sparse matrix. This would be simple if there +# weren't so many modes. +def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): + # This function assumes there is scipy and the matrix is a scipy sparse + # matrix. The caller should make sure those conditions are met. + from scipy import sparse + + modes = ( + ADJ_DIRECTED, + ADJ_UNDIRECTED, + ADJ_MAX, + ADJ_MIN, + ADJ_PLUS, + ADJ_UPPER, + ADJ_LOWER, + ) + + if not isinstance(matrix, sparse.coo_matrix): + matrix = matrix.tocoo() + + # Shorthand notation + m = matrix + + if mode == ADJ_DIRECTED: + edges = sum( + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data)), + [], + ) + return klass( + edges=edges, directed=True, + ) + + if mode == ADJ_UNDIRECTED: + mode = ADJ_MAX + + if mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): + fun_dict = { + ADJ_MAX: max, + ADJ_MIN: min, + ADJ_PLUS: lambda *x: sum(x), + } + fun = fun_dict[mode] + nedges = {} + for i, j, n in zip(m.row, m.col, m.data): + # Fist time this pair of vertices + if (j, i) not in nedges: + nedges[(i, j)] = n + else: + nedges[(j, i)] = fun(nedges[(j, i)], n) + + edges = sum( + ([e] * n for e, n in nedges.items()), + [], + ) + return klass( + edges=edges, directed=False, + ) + + if mode == ADJ_UPPER: + edges = sum( + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j >= i), + [], + ) + return klass( + edges=edges, directed=True, + ) + + if mode == ADJ_LOWER: + edges = sum( + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j <= i), + [], + ) + return klass( + edges=edges, directed=True, + ) + + raise ValueError('mode should be one of ' + ' '.join(map(str, modes))) From 2680e61fe228726462fa88a99bcb9783417cdd8d Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 20 Jan 2021 11:18:57 +1100 Subject: [PATCH 0357/1892] Hack via _Adjacency --- src/_igraph/graphobject.c | 6 ++++++ src/_igraph/graphobject.h | 1 + src/igraph/__init__.py | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index bab3391ac..9787e455b 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1939,6 +1939,12 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, return (PyObject *) self; } +PyObject *igraphmodule_Graph__Adjacency(PyTypeObject * type, + PyObject * args, PyObject * kwds) { + return igraphmodule_Graph_Adjacency(type, args, kwds); +} + + /** \ingroup python_interface_graph * \brief Generates a graph from the Graph Atlas * \return a reference to the newly generated Python igraph object diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 618dbb97b..6a650251b 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -77,6 +77,7 @@ PyObject* igraphmodule_Graph_predecessors(igraphmodule_GraphObject *self, PyObje PyObject* igraphmodule_Graph_get_eid(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Adjacency(PyTypeObject *type, PyObject *args, PyObject *kwds); +PyObject* igraphmodule_Graph__Adjacency(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Asymmetric_Preference(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Atlas(PyTypeObject *type, PyObject *args); PyObject* igraphmodule_Graph_Barabasi(PyTypeObject *type, PyObject *args, PyObject *kwds); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 0f2c2fb41..0140f2d58 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2107,7 +2107,7 @@ def Read_Adjacency( return graph @classmethod - def Adjacency(klass, matrix, mode=ADJ_DIRECTED): + def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): """Generates a graph from its adjacency matrix. @param matrix: the adjacency matrix. Possible types are: @@ -2148,7 +2148,7 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED): if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() - return GraphBase.Adjacency(klass, matrix, mode=mode) + return klass._Adjacency(matrix, mode=mode) def write_dimacs(self, f, source=None, target=None, capacity="capacity"): """Writes the graph in DIMACS format to the given file. From 44487291d3867fc9af1d7fbacc792c9372182e0b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 29 Jan 2021 17:01:25 +1100 Subject: [PATCH 0358/1892] Use super() as suggested by everyone - sigh! --- src/_igraph/graphobject.c | 5 ----- src/_igraph/graphobject.h | 1 - src/igraph/__init__.py | 2 +- src/igraph/sparse_matrix.py | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9787e455b..87cb145a8 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1939,11 +1939,6 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, return (PyObject *) self; } -PyObject *igraphmodule_Graph__Adjacency(PyTypeObject * type, - PyObject * args, PyObject * kwds) { - return igraphmodule_Graph_Adjacency(type, args, kwds); -} - /** \ingroup python_interface_graph * \brief Generates a graph from the Graph Atlas diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 6a650251b..618dbb97b 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -77,7 +77,6 @@ PyObject* igraphmodule_Graph_predecessors(igraphmodule_GraphObject *self, PyObje PyObject* igraphmodule_Graph_get_eid(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Adjacency(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph__Adjacency(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Asymmetric_Preference(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Atlas(PyTypeObject *type, PyObject *args); PyObject* igraphmodule_Graph_Barabasi(PyTypeObject *type, PyObject *args, PyObject *kwds); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 0140f2d58..c735abcec 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2148,7 +2148,7 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() - return klass._Adjacency(matrix, mode=mode) + return super().Adjacency(matrix, mode=mode) def write_dimacs(self, f, source=None, target=None, capacity="capacity"): """Writes the graph in DIMACS format to the given file. diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index dc86d0a37..0c4daf398 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -4,7 +4,7 @@ from __future__ import with_statement -__all__ = () +__all__ = ['_graph_from_sparse_matrix'] __docformat__ = "restructuredtext en" __license__ = u""" Copyright (C) 2021 igraph development team From 63b7ba11d5776c09c78a0685dcb7dbba3431b156 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 30 Jan 2021 10:25:02 +1100 Subject: [PATCH 0359/1892] Weighted matrix functions --- src/igraph/__init__.py | 57 ++++++++++++- src/igraph/sparse_matrix.py | 160 ++++++++++++++++++++++++++---------- 2 files changed, 174 insertions(+), 43 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index c735abcec..e704de67d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -41,11 +41,14 @@ from igraph.layout import * from igraph.matching import * from igraph.operators import * -from igraph.sparse_matrix import * from igraph.statistics import * from igraph.summary import * from igraph.utils import * from igraph.version import __version__, __version_info__ +from igraph.sparse_matrix import ( + _graph_from_sparse_matrix, + _graph_from_weighted_sparse_matrix, + ) import os import math @@ -2150,6 +2153,58 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): return super().Adjacency(matrix, mode=mode) + @classmethod + def WeightedAdjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True): + """Generates a graph from its weighted adjacency matrix. + + @param matrix: the adjacency matrix. Possible types are: + - a list of lists + - a numpy 2D array or matrix (will be converted to list of lists) + - a scipy.sparse matrix (will be converted to a COO matrix, but not + to a dense matrix) + @param mode: the mode to be used. Possible values are: + + - C{ADJ_DIRECTED} - the graph will be directed and a matrix + element gives the number of edges between two vertex. + - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience. + - C{ADJ_MAX} - undirected graph will be created and the number of + edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} + - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))} + - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)} + - C{ADJ_UPPER} - undirected graph with the upper right triangle of + the matrix (including the diagonal) + - C{ADJ_LOWER} - undirected graph with the lower left triangle of + the matrix (including the diagonal) + + These values can also be given as strings without the C{ADJ} prefix. + @param attr: the name of the edge attribute that stores the edge + weights. + @param loops: whether to include loop edges. When C{False}, the diagonal + of the adjacency matrix will be ignored. + + """ + try: + import numpy as np + except ImportError: + np = None + + try: + from scipy import sparse + except ImportError: + sparse = None + + if (sparse is not None) and isinstance(matrix, sparse.spmatrix): + return _graph_from_weighted_sparse_matrix( + klass, matrix, mode=mode, attr=attr, + ) + + if (np is not None) and isinstance(matrix, np.ndarray): + matrix = matrix.tolist() + + return super().WeightedAdjacency( + matrix, mode=mode, attr=attr, loops=loops, + ) + def write_dimacs(self, f, source=None, target=None, capacity="capacity"): """Writes the graph in DIMACS format to the given file. diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index 0c4daf398..101a0c10f 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -1,10 +1,10 @@ # vim:ts=4:sw=4:sts=4:et # -*- coding: utf-8 -*- -"""Implementation of union, disjoint union and intersection operators.""" +"""Implementation of Python-level sparse matrix operations.""" from __future__ import with_statement -__all__ = ['_graph_from_sparse_matrix'] +__all__ = () __docformat__ = "restructuredtext en" __license__ = u""" Copyright (C) 2021 igraph development team @@ -25,14 +25,22 @@ 02110-1301 USA """ -# pylint: disable-msg=W0401 -# W0401: wildcard import -from igraph._igraph import * +from operator import add +from igraph._igraph import ( + ADJ_DIRECTED, + ADJ_UNDIRECTED, + ADJ_MAX, + ADJ_MIN, + ADJ_PLUS, + ADJ_UPPER, + ADJ_LOWER, +) # Logic to get graph from scipy sparse matrix. This would be simple if there # weren't so many modes. def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): + '''Construct graph from sparse matrix, unweighted''' # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. from scipy import sparse @@ -53,23 +61,20 @@ def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): # Shorthand notation m = matrix - if mode == ADJ_DIRECTED: - edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data)), - [], - ) - return klass( - edges=edges, directed=True, - ) - if mode == ADJ_UNDIRECTED: mode = ADJ_MAX - if mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): + if mode == ADJ_DIRECTED: + edges = sum( + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data)), + [], + ) + + elif mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): fun_dict = { - ADJ_MAX: max, - ADJ_MIN: min, - ADJ_PLUS: lambda *x: sum(x), + ADJ_MAX: max, + ADJ_MIN: min, + ADJ_PLUS: add, } fun = fun_dict[mode] nedges = {} @@ -81,29 +86,100 @@ def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): nedges[(j, i)] = fun(nedges[(j, i)], n) edges = sum( - ([e] * n for e, n in nedges.items()), - [], - ) - return klass( - edges=edges, directed=False, - ) - - if mode == ADJ_UPPER: + ([e] * n for e, n in nedges.items()), + [], + ) + + elif mode == ADJ_UPPER: edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j >= i), - [], - ) - return klass( - edges=edges, directed=True, - ) - - if mode == ADJ_LOWER: + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j >= i), + [], + ) + + elif mode == ADJ_LOWER: edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j <= i), - [], - ) - return klass( - edges=edges, directed=True, - ) - - raise ValueError('mode should be one of ' + ' '.join(map(str, modes))) + ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j <= i), + [], + ) + + else: + raise ValueError("mode should be one of " + " ".join(map(str, modes))) + + return klass( + edges=edges, + directed=mode == ADJ_DIRECTED, + ) + + +def _graph_from_weighted_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED, attr='weight'): + '''Construct graph from sparse matrix, weighted + + NOTE: Of course, you cannot emcompass a fully general weighted multigraph + with a single adjacency matrix, so we don't try to do it here either. + ''' + # This function assumes there is scipy and the matrix is a scipy sparse + # matrix. The caller should make sure those conditions are met. + from scipy import sparse + + modes = ( + ADJ_DIRECTED, + ADJ_UNDIRECTED, + ADJ_MAX, + ADJ_MIN, + ADJ_PLUS, + ADJ_UPPER, + ADJ_LOWER, + ) + + if not isinstance(matrix, sparse.coo_matrix): + matrix = matrix.tocoo() + + # Shorthand notation + m = matrix + + if mode == ADJ_UNDIRECTED: + mode = ADJ_MAX + + if mode == ADJ_DIRECTED: + edges = list(zip(m.row, m.col)) + weights = list(m.data) + + elif mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): + fun_dict = { + ADJ_MAX: max, + ADJ_MIN: min, + ADJ_PLUS: add, + } + fun = fun_dict[mode] + nedges = {} + for i, j, n in zip(m.row, m.col, m.data): + # Fist time this pair of vertices + if (j, i) not in nedges: + nedges[(i, j)] = n + else: + nedges[(j, i)] = fun(nedges[(j, i)], n) + + edges, weights = zip(*nedges.items()) + + elif mode == ADJ_UPPER: + edges, weights = [], [] + for i, j, n in zip(m.row, m.col, m.data): + if j >= i: + edges.append((i, j)) + weights.append(n) + + elif mode == ADJ_LOWER: + edges, weights = [], [] + for i, j, n in zip(m.row, m.col, m.data): + if j <= i: + edges.append((i, j)) + weights.append(n) + + else: + raise ValueError("mode should be one of " + " ".join(map(str, modes))) + + return klass( + edges=edges, + directed=mode == ADJ_DIRECTED, + edge_attrs={attr: weights}, + ) From 99d0bb5daf2c79e11f52e4e2a594a6e917a29a03 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 30 Jan 2021 10:30:26 +1100 Subject: [PATCH 0360/1892] Black lint --- src/igraph/__init__.py | 16 +++++++++++----- src/igraph/sparse_matrix.py | 8 ++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e704de67d..cedecac04 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -46,9 +46,9 @@ from igraph.utils import * from igraph.version import __version__, __version_info__ from igraph.sparse_matrix import ( - _graph_from_sparse_matrix, - _graph_from_weighted_sparse_matrix, - ) + _graph_from_sparse_matrix, + _graph_from_weighted_sparse_matrix, +) import os import math @@ -2195,14 +2195,20 @@ def WeightedAdjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=Tru if (sparse is not None) and isinstance(matrix, sparse.spmatrix): return _graph_from_weighted_sparse_matrix( - klass, matrix, mode=mode, attr=attr, + klass, + matrix, + mode=mode, + attr=attr, ) if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() return super().WeightedAdjacency( - matrix, mode=mode, attr=attr, loops=loops, + matrix, + mode=mode, + attr=attr, + loops=loops, ) def write_dimacs(self, f, source=None, target=None, capacity="capacity"): diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index 101a0c10f..4d1d8e1d2 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -40,7 +40,7 @@ # Logic to get graph from scipy sparse matrix. This would be simple if there # weren't so many modes. def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): - '''Construct graph from sparse matrix, unweighted''' + """Construct graph from sparse matrix, unweighted""" # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. from scipy import sparse @@ -111,12 +111,12 @@ def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): ) -def _graph_from_weighted_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED, attr='weight'): - '''Construct graph from sparse matrix, weighted +def _graph_from_weighted_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED, attr="weight"): + """Construct graph from sparse matrix, weighted NOTE: Of course, you cannot emcompass a fully general weighted multigraph with a single adjacency matrix, so we don't try to do it here either. - ''' + """ # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. from scipy import sparse From d8b1e3f1fb26f2cb8a1ce86b9fe9d11277dfec8d Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 30 Jan 2021 10:46:09 +1100 Subject: [PATCH 0361/1892] Add tests --- tests/test_generators.py | 99 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/tests/test_generators.py b/tests/test_generators.py index f2d26c75a..1e296c3ee 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -1,11 +1,20 @@ import unittest from igraph import * + try: import numpy as np - import pandas as pd except ImportError: np = None + +try: + import scipy.sparse as sparse +except ImportError: + sparse = None + +try: + import pandas as pd +except ImportError: pd = None @@ -169,6 +178,50 @@ def testSBM(self): pref_matrix[0][1] = 0.7 self.assertRaises(InternalError, Graph.SBM, 60, pref_matrix, types) + @unittest.skipIf(np is None, "test case depends on NumPy") + def testAdjacencyNumPy(self): + mat = np.array( + [[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 2, 0], [0, 1, 0, 0]], + ) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (2, 2), (3, 1)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (2, 2), (2, 2)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (2, 2), (2, 2), (1, 3)]) + + @unittest.skipIf( + (sparse is None) or (np is None), "test case depends on NumPy/SciPy" + ) + def testSparseAdjacency(self): + mat = sparse.coo_matrix( + [[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 2, 0], [0, 1, 0, 0]], + ) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (2, 2), (3, 1)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (2, 2), (2, 2)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (2, 2), (2, 2), (1, 3)]) + def testWeightedAdjacency(self): mat = [[0, 1, 2, 0], [2, 0, 0, 0], [0, 0, 2.5, 0], [0, 1, 0, 0]] @@ -187,6 +240,50 @@ def testWeightedAdjacency(self): self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + @unittest.skipIf(np is None, "test case depends on NumPy") + def testWeightedAdjacencyNumPy(self): + mat = np.array( + [[0, 1, 2, 0], [2, 0, 0, 0], [0, 0, 2.5, 0], [0, 1, 0, 0]], + ) + + g = Graph.Weighted_Adjacency(mat, attr="w0") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 2.5, 1]) + + g = Graph.Weighted_Adjacency(mat, mode="plus") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2)]) + self.assertTrue(g.es["weight"] == [3, 2, 1, 2.5]) + + g = Graph.Weighted_Adjacency(mat, attr="w0", loops=False) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + + @unittest.skipIf( + (sparse is None) or (np is None), "test case depends on NumPy/SciPy" + ) + def testSparseWeighedAdjacency(self): + mat = sparse.coo_matrix( + [[0, 1, 2, 0], [2, 0, 0, 0], [0, 0, 2.5, 0], [0, 1, 0, 0]] + ) + + g = Graph.Weighted_Adjacency(mat, attr="w0") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 2.5, 1]) + + g = Graph.Weighted_Adjacency(mat, mode="plus") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2)]) + self.assertTrue(g.es["weight"] == [3, 2, 1, 2.5]) + + g = Graph.Weighted_Adjacency(mat, attr="w0", loops=False) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + @unittest.skipIf((np is None) or (pd is None), "test case depends on NumPy/Pandas") def testDataFrame(self): edges = pd.DataFrame( From 085c8cc6fb92e3a84614f033da3cb761c3bba371 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 31 Jan 2021 13:33:30 +0100 Subject: [PATCH 0362/1892] fix: build igraph library with -fPIC on Linux --- setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.py b/setup.py index a522c89b8..25f7c70a2 100644 --- a/setup.py +++ b/setup.py @@ -480,6 +480,10 @@ def compile_in(self, source_folder, build_folder, install_folder): for deps in "ARPACK BLAS CXSPARSE GLPK LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") + # -fPIC is needed on Linux so we can link to a static igraph lib from a + # Python shared library + args.append("-DCMAKE_POSITION_INDEPENDENT_CODE=ON") + retcode = subprocess.call(args) if retcode: return False From f6281336a44d38faba65c2768e908141890a970f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 4 Feb 2021 19:40:43 +0100 Subject: [PATCH 0363/1892] fix: remove unneeded reference to igraph_i_fdiv() --- src/_igraph/igraphmodule.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 8b4da52df..392cdada5 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -42,8 +42,6 @@ #define IGRAPH_MODULE #include "igraphmodule_api.h" -extern double igraph_i_fdiv(double, double); - /** * \defgroup python_interface Python module implementation * \brief Functions implementing a Python interface to \a igraph From 4374f420f43c40e195bd335a526081164bd13513 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 6 Feb 2021 14:50:00 +0100 Subject: [PATCH 0364/1892] updated igraph C library, fixed deprecation warnings --- src/_igraph/attributes.c | 2 +- tests/test_basic.py | 6 +++--- vendor/source/igraph | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index f0a027fa1..4090bc04f 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1884,7 +1884,7 @@ static igraph_attribute_table_t igraphmodule_attribute_table = { }; void igraphmodule_initialize_attribute_handler(void) { - igraph_i_set_attribute_table(&igraphmodule_attribute_table); + igraph_set_attribute_table(&igraphmodule_attribute_table); } /** diff --git a/tests/test_basic.py b/tests/test_basic.py index 67367d504..28bca91e9 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -338,14 +338,14 @@ def testAdjacency(self): self.assertTrue(g.get_adjlist(IN) == [[2], [0], [1], [2]]) self.assertTrue(g.get_adjlist(ALL) == [[1, 2], [0, 2], [0, 1, 3], [2]]) - def testEdgeIncidency(self): + def testEdgeIncidence(self): g = Graph(4, [(0, 1), (1, 2), (2, 0), (2, 3)], directed=True) self.assertTrue(g.incident(2) == [2, 3]) self.assertTrue(g.incident(2, IN) == [1]) - self.assertTrue(g.incident(2, ALL) == [2, 3, 1]) + self.assertTrue(g.incident(2, ALL) == [2, 1, 3]) self.assertTrue(g.get_inclist() == [[0], [1], [2, 3], []]) self.assertTrue(g.get_inclist(IN) == [[2], [0], [1], [3]]) - self.assertTrue(g.get_inclist(ALL) == [[0, 2], [1, 0], [2, 3, 1], [3]]) + self.assertTrue(g.get_inclist(ALL) == [[0, 2], [0, 1], [2, 1, 3], [3]]) def testMultiplesLoops(self): g = Graph.Tree(7, 2) diff --git a/vendor/source/igraph b/vendor/source/igraph index 869be278f..c4c45e7ca 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 869be278ffa5bc97e3cb7b08f58d2b111c9dd47b +Subproject commit c4c45e7ca681ab0be76bfc8badb2ab95c9610877 From 7d3a3d8d91f8cb69e485f206cf69a94a446d7114 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Sat, 6 Feb 2021 15:55:48 +0100 Subject: [PATCH 0365/1892] Fix link in docs --- doc/source/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index b5aeb1599..22b16492f 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -24,7 +24,7 @@ are often called *binary packages*, while the raw source code is usually referre In general, you should almost always opt for the binary package unless a binary package is not available for your platform or you have some local modifications that you want to incorporate into |igraph|'s source. `Installation from a binary package`_ tells you how to -install |igraph| from a precompiled binary package on various platforms. `Compiling igraph +install |igraph| from a precompiled binary package on various platforms. `Compiling python-igraph from source`_ tells you how to compile |igraph| from the source package. Installation from a binary package From 60b2b88e0fe3a1d0a9f6fc4e70cbe05f3c7a01fd Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 6 Feb 2021 07:52:02 +1100 Subject: [PATCH 0366/1892] Remove star imports --- src/igraph/__init__.py | 122 ++++++++++++++++++++++++++++---- src/igraph/drawing/__init__.py | 2 +- src/igraph/drawing/colors.py | 4 +- src/igraph/drawing/edge.py | 4 +- src/igraph/drawing/graph.py | 2 +- src/igraph/drawing/metamagic.py | 2 +- src/igraph/drawing/shapes.py | 2 +- src/igraph/drawing/text.py | 2 +- src/igraph/drawing/utils.py | 2 +- src/igraph/drawing/vertex.py | 2 +- src/igraph/formula.py | 2 +- src/igraph/remote/gephi.py | 2 +- src/igraph/statistics.py | 4 +- src/igraph/summary.py | 2 +- src/igraph/test/foreign.py | 3 +- src/igraph/utils.py | 5 +- 16 files changed, 126 insertions(+), 36 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 6f05e44ac..fcd7ae25e 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -28,22 +28,114 @@ 02110-1301 USA """ -# pylint: disable-msg=W0401 -# W0401: wildcard import -from igraph._igraph import * -from igraph.clustering import * -from igraph.cut import * +from igraph._igraph import ( + ADJ_DIRECTED, + ADJ_LOWER, + ADJ_MAX, + ADJ_MIN, + ADJ_PLUS, + ADJ_UNDIRECTED, + ADJ_UPPER, + ALL, + ARPACKOptions, + BFSIter, + BLISS_F, + BLISS_FL, + BLISS_FLM, + BLISS_FM, + BLISS_FS, + BLISS_FSM, + DFSIter, + Edge, + EdgeSeq, + GET_ADJACENCY_BOTH, + GET_ADJACENCY_LOWER, + GET_ADJACENCY_UPPER, + GraphBase, + IN, + InternalError, + OUT, + REWIRING_SIMPLE, + REWIRING_SIMPLE_LOOPS, + STAR_IN, + STAR_MUTUAL, + STAR_OUT, + STAR_UNDIRECTED, + STRONG, + TRANSITIVITY_NAN, + TRANSITIVITY_ZERO, + TREE_IN, + TREE_OUT, + TREE_UNDIRECTED, + Vertex, + VertexSeq, + WEAK, + arpack_options, + community_to_membership, + convex_hull, + is_degree_sequence, + is_graphical_degree_sequence, + set_progress_handler, + set_random_number_generator, + set_status_handler, +) +from igraph.clustering import ( + Clustering, + VertexClustering, + Dendrogram, + VertexDendrogram, + Cover, + VertexCover, + CohesiveBlocks, +) +from igraph.cut import Cut, Flow from igraph.configuration import Configuration -from igraph.drawing import * -from igraph.drawing.colors import * -from igraph.datatypes import * -from igraph.formula import * -from igraph.layout import * -from igraph.matching import * -from igraph.operators import * -from igraph.statistics import * -from igraph.summary import * -from igraph.utils import * +from igraph.drawing import BoundingBox, DefaultGraphDrawer, Plot, Point, Rectangle, plot +from igraph.drawing.colors import ( + Palette, + GradientPalette, + AdvancedGradientPalette, + RainbowPalette, + PrecalculatedPalette, + ClusterColoringPalette, + color_name_to_rgb, + color_name_to_rgba, + hsv_to_rgb, + hsva_to_rgba, + hsl_to_rgb, + hsla_to_rgba, + rgb_to_hsv, + rgba_to_hsva, + rgb_to_hsl, + rgba_to_hsla, + palettes, + known_colors, +) +from igraph.datatypes import Matrix, DyadCensus, TriadCensus, UniqueIdGenerator +from igraph.formula import construct_graph_from_formula +from igraph.layout import Layout +from igraph.matching import Matching +from igraph.operators import disjoint_union, union, intersection +from igraph.statistics import ( + FittedPowerLaw, + Histogram, + RunningMean, + mean, + median, + percentile, + quantile, + power_law_fit, +) +from igraph.summary import GraphSummary +from igraph.utils import ( + dbl_epsilon, + multidict, + named_temporary_file, + numpy_to_contiguous_memoryview, + rescale, + safemin, + safemax, +) from igraph.version import __version__, __version_info__ import os diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 9e352fa31..9b91a4f08 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -36,7 +36,7 @@ ) from igraph.utils import _is_running_in_ipython, named_temporary_file -__all__ = ["BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot"] +__all__ = ("BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot") __license__ = "GPL" diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index c77487667..eedaa1fdb 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -28,7 +28,7 @@ from igraph.utils import str_to_orientation from math import ceil -__all__ = [ +__all__ = ( "Palette", "GradientPalette", "AdvancedGradientPalette", @@ -47,7 +47,7 @@ "rgba_to_hsla", "palettes", "known_colors", -] + ) class Palette(object): diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 1afdfd0cc..100cee5c6 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -2,14 +2,14 @@ Drawers for various edge styles in graph plots. """ -__all__ = [ +__all__ = ( "AbstractEdgeDrawer", "AlphaVaryingEdgeDrawer", "ArrowEdgeDrawer", "DarkToLightEdgeDrawer", "LightToDarkEdgeDrawer", "TaperedEdgeDrawer", -] +) __license__ = "GPL" diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 6d59b5b66..416ff4dfc 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -34,7 +34,7 @@ from igraph.drawing.vertex import DefaultVertexDrawer from igraph.layout import Layout -__all__ = ["DefaultGraphDrawer", "UbiGraphDrawer", "CytoscapeGraphDrawer"] +__all__ = ("DefaultGraphDrawer", "UbiGraphDrawer", "CytoscapeGraphDrawer") __license__ = "GPL" cairo = find_cairo() diff --git a/src/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py index 3e78a39da..164aef3a9 100644 --- a/src/igraph/drawing/metamagic.py +++ b/src/igraph/drawing/metamagic.py @@ -65,7 +65,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): from igraph.configuration import Configuration -__all__ = ["AttributeSpecification", "AttributeCollectorBase"] +__all__ = ("AttributeSpecification", "AttributeCollectorBase") # pylint: disable-msg=R0903 # R0903: too few public methods diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 2a8882189..0a3cd81a9 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -17,7 +17,7 @@ """ -__all__ = ["ShapeDrawerDirectory"] +__all__ = ("ShapeDrawerDirectory",) __license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index 323e8ec20..c6bd385cf 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -9,7 +9,7 @@ from igraph.drawing.baseclasses import AbstractCairoDrawer from warnings import warn -__all__ = ["TextAlignment", "TextDrawer"] +__all__ = ("TextAlignment", "TextDrawer") __license__ = "GPL" __docformat__ = "restructuredtext en" diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 32ba062f8..cde3e5266 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -6,7 +6,7 @@ from math import atan2, cos, sin from operator import itemgetter -__all__ = ["BoundingBox", "FakeModule", "Point", "Rectangle"] +__all__ = ("BoundingBox", "FakeModule", "Point", "Rectangle") __license__ = "GPL" ##################################################################### diff --git a/src/igraph/drawing/vertex.py b/src/igraph/drawing/vertex.py index bc6d6b2a8..9f4d082a0 100644 --- a/src/igraph/drawing/vertex.py +++ b/src/igraph/drawing/vertex.py @@ -10,7 +10,7 @@ from igraph.drawing.shapes import ShapeDrawerDirectory from math import pi -__all__ = ["AbstractVertexDrawer", "AbstractCairoVertexDrawer", "DefaultVertexDrawer"] +__all__ = ("AbstractVertexDrawer", "AbstractCairoVertexDrawer", "DefaultVertexDrawer") __license__ = "GPL" diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 78d826f1c..8d2fce8c4 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -15,7 +15,7 @@ import tokenize import token -__all__ = ["construct_graph_from_formula"] +__all__ = ("construct_graph_from_formula",) __license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index 67f48c90e..5cda23739 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -18,7 +18,7 @@ json = FakeModule() -__all__ = ["GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat"] +__all__ = ("GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat") __docformat__ = "restructuredtext en" __license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index b62199244..79c820ce9 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -26,7 +26,7 @@ import math -__all__ = [ +__all__ = ( "FittedPowerLaw", "Histogram", "RunningMean", @@ -35,7 +35,7 @@ "percentile", "quantile", "power_law_fit", -] + ) class FittedPowerLaw(object): diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 2fda39ab0..6dbffe1c5 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -11,7 +11,7 @@ from texttable import Texttable from textwrap import TextWrapper -__all__ = ["GraphSummary"] +__all__ = ("GraphSummary",) __license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz diff --git a/src/igraph/test/foreign.py b/src/igraph/test/foreign.py index eabaea1fd..49a4fa5d2 100644 --- a/src/igraph/test/foreign.py +++ b/src/igraph/test/foreign.py @@ -1,8 +1,9 @@ +import sys import io import unittest import warnings -from igraph import * +from igraph import Graph, InternalError from igraph.test.utils import temporary_file diff --git a/src/igraph/utils.py b/src/igraph/utils.py index b60eb666e..707afb0da 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -7,10 +7,7 @@ from contextlib import contextmanager -try: - from collections.abc import MutableMapping -except ImportError: - from collections import MutableMapping +from collections.abc import MutableMapping from ctypes import c_double, sizeof from itertools import chain From 55992adcc1ed7b6880dcdeb87189845121cf5908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Mon, 8 Feb 2021 11:03:30 +0100 Subject: [PATCH 0367/1892] added some missing imports that the test cases are complaining about --- src/igraph/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index fcd7ae25e..23116f551 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -74,6 +74,7 @@ community_to_membership, convex_hull, is_degree_sequence, + is_graphical, is_graphical_degree_sequence, set_progress_handler, set_random_number_generator, @@ -87,6 +88,7 @@ Cover, VertexCover, CohesiveBlocks, + compare_communities, ) from igraph.cut import Cut, Flow from igraph.configuration import Configuration From 2332e35922763253b4e3a656045e230a13f3eb95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Mon, 8 Feb 2021 11:10:09 +0100 Subject: [PATCH 0368/1892] we also need split_join_distance in the main igraph module --- src/igraph/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 23116f551..798c16d4d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -89,6 +89,7 @@ VertexCover, CohesiveBlocks, compare_communities, + split_join_distance, ) from igraph.cut import Cut, Flow from igraph.configuration import Configuration From 56a047a095c385de2c0f46ff14609c57770c6639 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Feb 2021 11:53:31 +0100 Subject: [PATCH 0369/1892] chore: blackened source [ci skip] --- src/igraph/app/__init__.py | 1 - src/igraph/clustering.py | 14 +++++++++----- src/igraph/drawing/colors.py | 2 +- src/igraph/remote/__init__.py | 1 - src/igraph/statistics.py | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/igraph/app/__init__.py b/src/igraph/app/__init__.py index 1dd82a624..049f302eb 100644 --- a/src/igraph/app/__init__.py +++ b/src/igraph/app/__init__.py @@ -1,2 +1 @@ """User interfaces of igraph""" - diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 43dfee021..a7e7d9238 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -684,15 +684,19 @@ def summary(self, verbosity=0, max_leaf_count=40): @return: the summary of the dendrogram as a string. """ out = StringIO() - print("Dendrogram, %d elements, %d merges" % ( - self._nitems, - self._nmerges, - ), file=out) + print( + "Dendrogram, %d elements, %d merges" + % ( + self._nitems, + self._nmerges, + ), + file=out, + ) if self._nitems == 0 or verbosity < 1 or self._nitems > max_leaf_count: return out.getvalue().strip() - print('', file=out) + print("", file=out) positions = [None] * self._nitems inorder = self._traverse_inorder() diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index eedaa1fdb..049cfeb99 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -47,7 +47,7 @@ "rgba_to_hsla", "palettes", "known_colors", - ) +) class Palette(object): diff --git a/src/igraph/remote/__init__.py b/src/igraph/remote/__init__.py index e9e07dbc1..ba7da4dc7 100644 --- a/src/igraph/remote/__init__.py +++ b/src/igraph/remote/__init__.py @@ -1,2 +1 @@ """Classes that help igraph communicate with remote applications.""" - diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 79c820ce9..dda450851 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -35,7 +35,7 @@ "percentile", "quantile", "power_law_fit", - ) +) class FittedPowerLaw(object): From 2893b07020b54345934d939f56fcf96d3b558f40 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 6 Feb 2021 08:06:48 +1100 Subject: [PATCH 0370/1892] Add harmonic centrality --- src/_igraph/graphobject.c | 114 +++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index bab3391ac..3e6bb5ddf 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4118,6 +4118,85 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, return list; } +/** \ingroup python_interface_graph + * \brief Calculates the harmonic centrality of some vertices in a graph. + * \return the harmonic centralities as a list (or a single float) + * \sa igraph_closeness + */ +PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + static char *kwlist[] = { "vertices", "mode", "cutoff", "weights", + "normalized", NULL }; + PyObject *vobj = Py_None, *list = NULL, *cutoff = Py_None, + *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; + igraph_vector_t res, *weights = 0; + igraph_neimode_t mode = IGRAPH_ALL; + int return_single = 0; + igraph_vs_t vs; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, + &mode_o, &cutoff, &weights_o, &normalized_o)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_vector_init(&res, 0)) { + igraph_vs_destroy(&vs); + return igraphmodule_handle_igraph_error(); + } + + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, + ATTRIBUTE_TYPE_EDGE)) { + igraph_vs_destroy(&vs); + igraph_vector_destroy(&res); + return NULL; + } + + if (cutoff == Py_None) { + if (igraph_harmonic_centrality(&self->g, &res, 0, 0, vs, mode, weights, + PyObject_IsTrue(normalized_o))) { + igraph_vs_destroy(&vs); + igraph_vector_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + } else if (PyNumber_Check(cutoff)) { + PyObject *cutoff_num = PyNumber_Float(cutoff); + if (cutoff_num == NULL) { + igraph_vs_destroy(&vs); igraph_vector_destroy(&res); + return NULL; + } + if (igraph_harmonic_centrality_cutoff(&self->g, &res, 0, 0, vs, mode, weights, + (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { + igraph_vs_destroy(&vs); + igraph_vector_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + Py_DECREF(cutoff_num); + return NULL; + } + Py_DECREF(cutoff_num); + } + + if (weights) { igraph_vector_destroy(weights); free(weights); } + + if (!return_single) + list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); + else + list = PyFloat_FromDouble(VECTOR(res)[0]); + + igraph_vector_destroy(&res); + igraph_vs_destroy(&vs); + + return list; +} + /** \ingroup python_interface_graph * \brief Calculates the (weakly or strongly) connected components in a graph. * \return a list containing the cluster ID for every vertex in the graph @@ -12878,7 +12957,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "The closeness centerality of a vertex measures how easily other\n" "vertices can be reached from it (or the other way: how easily it\n" "can be reached from the other vertices). It is defined as the\n" - "number of the number of vertices minus one divided by the sum of\n" + "number of vertices minus one divided by the sum of\n" "the lengths of all geodesics from/to the given vertex.\n\n" "If the graph is not connected, and there is no path between two\n" "vertices, the number of vertices is used instead the length of\n" @@ -12902,6 +12981,39 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " multiplying by the number of vertices minus one.\n" "@return: the calculated closenesses in a list\n"}, + /* interface to igraph_harmonic_centrality */ + {"harmonic_centrality", (PyCFunction) igraphmodule_Graph_harmonic_centrality, + METH_VARARGS | METH_KEYWORDS, + "harmonic_centrality(vertices=None, mode=ALL, cutoff=None, weights=None,\n" + " normalized=True)\n\n" + "Calculates the harmonic centralities of given vertices in a graph.\n\n" + "The harmonic centerality of a vertex measures how easily other\n" + "vertices can be reached from it (or the other way: how easily it\n" + "can be reached from the other vertices). It is defined as the\n" + "number of vertices minus one times the sum of one divided by \n" + "the length of each geodesic from/to the given vertex.\n\n" + "If the graph is not connected, and there is no path between two\n" + "vertices, the number of vertices is used instead the length of\n" + "the geodesic. This is always longer than the longest possible\n" + "geodesic.\n\n" + "@param vertices: the vertices for which the harmonic centrality must\n" + " be returned. If C{None}, uses all of the vertices in the graph.\n" + "@param mode: must be one of L{IN}, L{OUT} and L{ALL}. L{IN} means\n" + " that the length of the incoming paths, L{OUT} means that the\n" + " length of the outgoing paths must be calculated. L{ALL} means\n" + " that both of them must be calculated.\n" + "@param cutoff: if it is an integer, only paths less than or equal to this\n" + " length are considered, effectively resulting in an estimation of the\n" + " harmonic centrality for the given vertices (which is always an underestimation of the\n" + " real centrality, since some vertex pairs will appear as disconnected even\n" + " though they are connected).. If C{None}, the exact centrality is\n" + " returned.\n" + "@param weights: edge weights to be used. Can be a sequence or iterable or\n" + " even an edge attribute name.\n" + "@param normalized: Whether to normalize the raw centrality scores by\n" + " multiplying by the number of vertices minus one.\n" + "@return: the calculated harmonic centrality in a list\n"}, + /* interface to igraph_clusters */ {"clusters", (PyCFunction) igraphmodule_Graph_clusters, METH_VARARGS | METH_KEYWORDS, From 7ddb0a2375647897fc6ba0d877758fcccc4a3658 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 6 Feb 2021 09:41:27 +1100 Subject: [PATCH 0371/1892] Doc improvs --- src/_igraph/graphobject.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3e6bb5ddf..a641ae6d5 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12990,12 +12990,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "The harmonic centerality of a vertex measures how easily other\n" "vertices can be reached from it (or the other way: how easily it\n" "can be reached from the other vertices). It is defined as the\n" - "number of vertices minus one times the sum of one divided by \n" - "the length of each geodesic from/to the given vertex.\n\n" + "mean inverse distance to all other vertices.\n\n" "If the graph is not connected, and there is no path between two\n" - "vertices, the number of vertices is used instead the length of\n" - "the geodesic. This is always longer than the longest possible\n" - "geodesic.\n\n" + "vertices, the inverse distance is taken to be zero.\n\n" "@param vertices: the vertices for which the harmonic centrality must\n" " be returned. If C{None}, uses all of the vertices in the graph.\n" "@param mode: must be one of L{IN}, L{OUT} and L{ALL}. L{IN} means\n" @@ -13003,15 +13000,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " length of the outgoing paths must be calculated. L{ALL} means\n" " that both of them must be calculated.\n" "@param cutoff: if it is an integer, only paths less than or equal to this\n" - " length are considered, effectively resulting in an estimation of the\n" - " harmonic centrality for the given vertices (which is always an underestimation of the\n" - " real centrality, since some vertex pairs will appear as disconnected even\n" - " though they are connected).. If C{None}, the exact centrality is\n" - " returned.\n" + " length are considered.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" - "@param normalized: Whether to normalize the raw centrality scores by\n" - " multiplying by the number of vertices minus one.\n" + "@param normalized: Whether to normalize the result. If True, the \n" + " result is the mean inverse path length to other vertices, i.e. it \n" + " is normalized by the number of vertices minus one. If False, the \n" + " result is the sum of inverse path lengths to other vertices.\n" "@return: the calculated harmonic centrality in a list\n"}, /* interface to igraph_clusters */ From 907dbf2782441ae7f9c74488579b296af90c4fbc Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 6 Feb 2021 10:33:57 +1100 Subject: [PATCH 0372/1892] Doc mention and test --- doc/source/analysis.rst | 1 + tests/test_structural.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 8c15b4b83..1d3790c99 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -289,6 +289,7 @@ Structural: - :meth:`Graph.betweenness` - :meth:`Graph.bibcoupling` - :meth:`Graph.closeness` +- :meth:`Graph.harmonic_centrality` - :meth:`Graph.constraint` - :meth:`Graph.cocitation` - :meth:`Graph.coreness` (aka :meth:`Graph.shell_index`) diff --git a/tests/test_structural.py b/tests/test_structural.py index 1b5e25618..d4acfb5c6 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -355,6 +355,37 @@ def testClosenessCentrality(self): for obs, exp in zip(cl, expected_cl): self.assertAlmostEqual(obs, exp, places=4) + def testHarmonicCentrality(self): + g = Graph.Star(5) + cl = g.harmonic_centrality() + cl2 = [1.0] + [(1.0 + 1 / 2 * 3) / 4] * 4 + for idx in range(g.vcount()): + self.assertAlmostEqual(cl[idx], cl2[idx], places=3) + + g = Graph.Star(5) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + cl = g.harmonic_centrality(cutoff=1.0) + cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] + for idx in range(g.vcount()): + self.assertAlmostEqual(cl[idx], cl2[idx], places=3) + + weights = [1] * 4 + + g = Graph.Star(5) + cl = g.harmonic_centrality(weights=weights) + cl2 = [1.0] + [0.625] * 4 + for idx in range(g.vcount()): + self.assertAlmostEqual(cl[idx], cl2[idx], places=3) + + g = Graph.Star(5) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + cl = g.harmonic_centrality(cutoff=1.0, weights=weights) + cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] + for idx in range(g.vcount()): + self.assertAlmostEqual(cl[idx], cl2[idx], places=3) + def testPageRank(self): g = Graph.Star(11) cent = g.pagerank() From cca96545af93387c34be62405709426a2ef05993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 10 Feb 2021 13:16:20 +0100 Subject: [PATCH 0373/1892] doc improvements to Graph.harmonic_centrality() Based on the suggestions of @szhorvat in the PR review --- src/_igraph/graphobject.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index a641ae6d5..1ed053a4f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12999,15 +12999,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " that the length of the incoming paths, L{OUT} means that the\n" " length of the outgoing paths must be calculated. L{ALL} means\n" " that both of them must be calculated.\n" - "@param cutoff: if it is an integer, only paths less than or equal to this\n" + "@param cutoff: if it is not C{None}, only paths less than or equal to this\n" " length are considered.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" - "@param normalized: Whether to normalize the result. If True, the \n" - " result is the mean inverse path length to other vertices, i.e. it \n" - " is normalized by the number of vertices minus one. If False, the \n" + "@param normalized: Whether to normalize the result. If True, the\n" + " result is the mean inverse path length to other vertices, i.e. it\n" + " is normalized by the number of vertices minus one. If False, the\n" " result is the sum of inverse path lengths to other vertices.\n" - "@return: the calculated harmonic centrality in a list\n"}, + "@return: the calculated harmonic centralities in a list\n"}, /* interface to igraph_clusters */ {"clusters", (PyCFunction) igraphmodule_Graph_clusters, From 767469957080daba889db041663c84d24a1e50ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 10 Feb 2021 13:19:45 +0100 Subject: [PATCH 0374/1892] Keep alphabetic ordering of functions in the docs [ci skip] --- doc/source/analysis.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 1d3790c99..79ee0a437 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -289,12 +289,12 @@ Structural: - :meth:`Graph.betweenness` - :meth:`Graph.bibcoupling` - :meth:`Graph.closeness` -- :meth:`Graph.harmonic_centrality` - :meth:`Graph.constraint` - :meth:`Graph.cocitation` - :meth:`Graph.coreness` (aka :meth:`Graph.shell_index`) - :meth:`Graph.eccentricity` - :meth:`Graph.eigenvector_centrality` +- :meth:`Graph.harmonic_centrality` - :meth:`Graph.pagerank` - :meth:`Graph.personalized_pagerank` - :meth:`Graph.strength` From d8ae2365b0550cc4155113be7156c8a5640313bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 10 Feb 2021 13:33:22 +0100 Subject: [PATCH 0375/1892] fix argument list of igraph_harmonic_centrality() calls --- src/_igraph/graphobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 1ed053a4f..e0b3d8b31 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4158,7 +4158,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self } if (cutoff == Py_None) { - if (igraph_harmonic_centrality(&self->g, &res, 0, 0, vs, mode, weights, + if (igraph_harmonic_centrality(&self->g, &res, vs, mode, weights, PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); @@ -4172,7 +4172,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self igraph_vs_destroy(&vs); igraph_vector_destroy(&res); return NULL; } - if (igraph_harmonic_centrality_cutoff(&self->g, &res, 0, 0, vs, mode, weights, + if (igraph_harmonic_centrality_cutoff(&self->g, &res, vs, mode, weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); From bfdbd410beedbd3fca38f78538ae819b2a091885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 10 Feb 2021 13:47:45 +0100 Subject: [PATCH 0376/1892] fix test case of harmonic centrality --- tests/test_structural.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_structural.py b/tests/test_structural.py index d4acfb5c6..148cf8539 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -366,7 +366,7 @@ def testHarmonicCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.harmonic_centrality(cutoff=1.0) - cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] + cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) @@ -382,7 +382,7 @@ def testHarmonicCentrality(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") cl = g.harmonic_centrality(cutoff=1.0, weights=weights) - cl2 = [1.0, 1.0, 1.0, 1.0, 1.0] + cl2 = [1.0, 0.25, 0.25, 0.25, 0.25] for idx in range(g.vcount()): self.assertAlmostEqual(cl[idx], cl2[idx], places=3) From 087b0c144ab1eb13a1e1e428e5ad90ff048040d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 10 Feb 2021 14:06:43 +0100 Subject: [PATCH 0377/1892] fix memory leak in Graph.closeness_centrality() and Graph.harmonic_centrality() --- src/_igraph/graphobject.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e0b3d8b31..816de5589 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4091,6 +4091,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, PyObject *cutoff_num = PyNumber_Float(cutoff); if (cutoff_num == NULL) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } if (igraph_closeness_cutoff(&self->g, &res, 0, 0, vs, mode, weights, @@ -4170,6 +4171,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self PyObject *cutoff_num = PyNumber_Float(cutoff); if (cutoff_num == NULL) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } if (igraph_harmonic_centrality_cutoff(&self->g, &res, vs, mode, weights, From 3d3b327e22ec9737f96eb37afa3dceee1383c67b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 15 Feb 2021 12:35:07 +0100 Subject: [PATCH 0378/1892] chore: updated igraph to development branch --- src/_igraph/convert.c | 60 ++++++++++++++++++++++++-------------- src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 2 +- src/_igraph/igraphmodule.c | 2 +- vendor/source/igraph | 2 +- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 4b050b550..4815315ca 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1266,7 +1266,7 @@ int igraphmodule_PyObject_to_vector_bool_t(PyObject *list, item=PySequence_GetItem(list, i); if (item) { VECTOR(*v)[i]=PyObject_IsTrue(item); - Py_DECREF(item); + Py_DECREF(item); } else { /* this should not happen, but we return anyway. * an IndexError exception was set by PySequence_GetItem @@ -1322,10 +1322,11 @@ PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, list=PyList_New(n); for (i=0; i 0 ? min_cols : 0; + for (i = 0; i < nr; i++) { + row = PySequence_GetItem(o, i); if (!PySequence_Check(row)) { Py_DECREF(row); PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); return 1; } - n=PySequence_Size(row); + n = PySequence_Size(row); Py_DECREF(row); - if (n>nc) nc=n; + if (n > nc) { + nc = n; + } } igraph_matrix_init(m, nr, nc); - for (i=0; ig, (igraph_integer_t) vid, mode, &vids, &layers, &parents)) { igraphmodule_handle_igraph_error(); return NULL; diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 392cdada5..86cae3747 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -339,7 +339,7 @@ PyObject* igraphmodule_community_to_membership(PyObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!ll|O", kwlist, &PyList_Type, &merges_o, &nodes, &steps, &return_csize)) return NULL; - if (igraphmodule_PyList_to_matrix_t(merges_o, &merges)) return NULL; + if (igraphmodule_PyList_to_matrix_t_with_minimum_column_count(merges_o, &merges, 2)) return NULL; if (igraph_vector_init(&result, nodes)) { igraphmodule_handle_igraph_error(); diff --git a/vendor/source/igraph b/vendor/source/igraph index c4c45e7ca..7ac8a58e2 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit c4c45e7ca681ab0be76bfc8badb2ab95c9610877 +Subproject commit 7ac8a58e2925c2fd8d0afdcfd6b87e07569aa0d5 From 27407f5c98c8618ba4d2ca727736f3db7d37fdab Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 15 Feb 2021 12:35:52 +0100 Subject: [PATCH 0379/1892] fix: Graph.VertexSeq.find(name=x) now works correctly when x is an integer, fixes #367 --- src/igraph/__init__.py | 8 ++++++-- tests/test_vertexseq.py | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 798c16d4d..4f22a459f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -4400,8 +4400,12 @@ def find(self, *args, **kwds): else: name = None - if name is not None and isinstance(name, str): - args = [name] + if name is not None: + if isinstance(name, str): + args = [name] + else: + # put back what we popped + kwds["name"] = name if args: # Selecting first based on positional arguments, then checking diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index a359cc9aa..39037e4a1 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -341,13 +341,22 @@ def testGraphMethodProxying(self): def testBug73(self): # This is a regression test for igraph/python-igraph#73 g = Graph() - g.add_vertices(2) + g.add_vertices(3) g.vs[0]["name"] = 1 g.vs[1]["name"] = "h" + g.vs[2]["name"] = 17 self.assertEqual(1, g.vs.find("h").index) self.assertEqual(1, g.vs.find(1).index) self.assertEqual(0, g.vs.find(name=1).index) + self.assertEqual(2, g.vs.find(name=17).index) + + def testBug367(self): + # This is a regression test for igraph/python-igraph#367 + g = Graph() + g.add_vertices([1, 2, 5]) + self.assertEqual([1, 2, 5], g.vs["name"]) + self.assertEqual(2, g.vs.find(name=5).index) def suite(): From 6b8d652ad30577dbb6a95959027b35926cbff651 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Feb 2021 15:22:30 +0100 Subject: [PATCH 0380/1892] refactor: setup.py cleanup, getting rid of some old Python 2.x-based constructs --- setup.py | 305 +++++-------------------------------------------------- 1 file changed, 24 insertions(+), 281 deletions(-) diff --git a/setup.py b/setup.py index 25f7c70a2..73b432abe 100644 --- a/setup.py +++ b/setup.py @@ -21,14 +21,15 @@ from setuptools import setup, Command, Extension -import distutils.ccompiler import glob import shutil import subprocess import sys import sysconfig +from pathlib import Path from select import select +from shutil import which from time import sleep ########################################################################### @@ -48,20 +49,6 @@ def building_on_windows_msvc(): return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" -def create_dir_unless_exists(*args): - """Creates a directory unless it exists already.""" - path = os.path.join(*args) - if not os.path.isdir(path): - os.makedirs(path) - - -def ensure_dir_does_not_exist(*args): - """Ensures that the given directory does not exist.""" - path = os.path.join(*args) - if os.path.isdir(path): - shutil.rmtree(path) - - def exclude_from_list(items, items_to_exclude): """Excludes certain items from a list, keeping the original order of the remaining items.""" @@ -69,20 +56,6 @@ def exclude_from_list(items, items_to_exclude): return [item for item in items if item not in itemset] -def find_executable(name): - """Finds an executable with the given name on the system PATH and returns - its full path. - """ - try: - from shutil import which - - return which(name) # Python 3.3 and above - except ImportError: - import distutils.spawn - - return distutils.spawn.find_executable(name) # Earlier than Python 3.3 - - def find_static_library(library_name, library_path): """Given the raw name of a library in `library_name`, tries to find a static library with this name in the given `library_path`. `library_path` @@ -161,76 +134,6 @@ def is_unix_like(platform=None): ) -def find_msvc_source_folder(folder=".", requires_built=False): - """Finds the folder that contains the MSVC-specific source of igraph if there - is any. Returns `None` if no such folder is found. Prints a warning if the - choice is ambiguous. - """ - all_msvc_dirs = glob.glob(os.path.join(folder, "igraph-*-msvc")) - if len(all_msvc_dirs) > 0: - if len(all_msvc_dirs) > 1: - print("More than one MSVC build directory (..\\..\\igraph-*-msvc) found!") - print( - "It could happen that setup.py uses the wrong one! Please remove all but the right one!\n\n" - ) - - msvc_builddir = all_msvc_dirs[-1] - if requires_built and not os.path.exists( - os.path.join(msvc_builddir, "Release") - ): - print( - "There is no 'Release' dir in the MSVC build directory\n(%s)" - % msvc_builddir - ) - print("Please build the MSVC build first!\n") - return None - - return msvc_builddir - else: - return None - - -def preprocess_fallback_config(): - """Preprocesses the fallback include and library paths depending on the - platform.""" - global LIBIGRAPH_FALLBACK_INCLUDE_DIRS - global LIBIGRAPH_FALLBACK_LIBRARY_DIRS - global LIBIGRAPH_FALLBACK_LIBRARIES - - if ( - platform.system() == "Windows" - and distutils.ccompiler.get_default_compiler() == "msvc" - ): - # if this setup is run in the source checkout *and* the igraph msvc was build, - # this code adds the right library and include dir - msvc_builddir = find_msvc_source_folder( - os.path.join("..", ".."), requires_built=True - ) - - if msvc_builddir is not None: - print("Using MSVC build dir: %s\n\n" % msvc_builddir) - LIBIGRAPH_FALLBACK_INCLUDE_DIRS = [os.path.join(msvc_builddir, "include")] - LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [os.path.join(msvc_builddir, "Release")] - return True - else: - return False - - else: - return True - - -def quote_path_for_shell(s): - # On MinGW / MSYS, we need to use forward slash style and remove unsafe - # characters in order not to trip up the configure script - if "MSYSTEM" in os.environ: - s = s.replace("\\", "/") - if s[1:3] == ":/": - s = "/" + s[0] + s[2:] - - # Now the proper quoting - return "'" + s.replace("'", "'\\''") + "'" - - def wait_for_keypress(seconds): """Wait for a keypress or until the given number of seconds have passed, whichever happens first. @@ -278,8 +181,8 @@ class IgraphCCoreBuilder(object): """ def create_build_config_file(self, install_folder, libraries): - with open(os.path.join(install_folder, "build.cfg"), "w") as f: - f.write(repr(libraries)) + with (install_folder / "build.cfg").open("w") as fp: + fp.write(repr(libraries)) def parse_pkgconfig_file(self, filename): building_on_windows = building_on_windows_msvc() @@ -288,7 +191,7 @@ def parse_pkgconfig_file(self, filename): libraries = ["igraph"] else: libraries = [] - with open(filename, "r") as fp: + with filename.open("r") as fp: for line in fp: if line.startswith("Libs: ") or line.startswith("Libs.private: "): words = line.strip().split() @@ -303,145 +206,6 @@ def parse_pkgconfig_file(self, filename): return libraries -class IgraphCCoreAutotoolsBuilder(IgraphCCoreBuilder): - """Class responsible for downloading and building the C core of igraph - if it is not installed yet, assuming that the C core uses `configure.ac` - and its friends. This used to be the case before igraph 0.9. - """ - - def compile_in(self, source_folder, build_folder, install_folder): - """Compiles igraph from its source code in the given folder. - - source_folder is the name of the folder that contains igraph's source - files. build_folder is the name of the folder where the build should - be executed. Both must be absolute paths. - - Returns: - False if the build failed or the list of libraries to link to when - linking the Python interface to igraph - """ - build_to_source_folder = os.path.relpath(source_folder, build_folder) - - os.chdir(source_folder) - - # Run the bootstrap script if we have downloaded a tarball from - # Github - if os.path.isfile("bootstrap.sh") and not os.path.isfile("configure"): - print("Bootstrapping igraph...") - retcode = subprocess.call("sh bootstrap.sh", shell=True) - if retcode: - return False - - # Patch ltmain.sh so it does not freak out when the build directory - # contains spaces - with open("ltmain.sh") as infp: - with open("ltmain.sh.new", "w") as outfp: - for line in infp: - if line.endswith("cd $darwin_orig_dir\n"): - line = line.replace( - "cd $darwin_orig_dir\n", 'cd "$darwin_orig_dir"\n' - ) - outfp.write(line) - shutil.move("ltmain.sh.new", "ltmain.sh") - - os.chdir(build_folder) - - print("Configuring igraph...") - configure_args = ["--disable-tls", "--enable-silent-rules"] - if "IGRAPH_EXTRA_CONFIGURE_ARGS" in os.environ: - configure_args.extend(os.environ["IGRAPH_EXTRA_CONFIGURE_ARGS"].split(" ")) - retcode = subprocess.call( - "sh {0} {1}".format( - quote_path_for_shell(os.path.join(build_to_source_folder, "configure")), - " ".join(configure_args), - ), - env=self.enhanced_env(CFLAGS="-fPIC", CXXFLAGS="-fPIC"), - shell=True, - ) - if retcode: - return False - - building_on_windows = building_on_windows_msvc() - - if building_on_windows: - print("Creating Microsoft Visual Studio project...") - retcode = subprocess.call("make msvc", shell=True) - if retcode: - return False - - print("Building igraph...") - if building_on_windows: - msvc_source = find_msvc_source_folder() - if not msvc_source: - return False - - devenv = os.environ.get("DEVENV_EXECUTABLE") - os.chdir(msvc_source) - if devenv is None: - retcode = subprocess.call("devenv /upgrade igraph.vcproj", shell=True) - else: - retcode = subprocess.call([devenv, "/upgrade", "igraph.vcproj"]) - if retcode: - return False - - retcode = subprocess.call( - "msbuild.exe igraph.vcxproj /p:configuration=Release" - ) - else: - retcode = subprocess.call("make", shell=True) - - if retcode: - return False - - libraries = self.parse_pkgconfig_file("igraph.pc") - - return libraries - - def copy_build_artifacts( - self, source_folder, build_folder, install_folder, libraries - ): - building_on_windows = building_on_windows_msvc() - - create_dir_unless_exists(install_folder) - - ensure_dir_does_not_exist(install_folder, "include") - ensure_dir_does_not_exist(install_folder, "lib") - - shutil.copytree( - os.path.join(source_folder, "include"), - os.path.join(install_folder, "include"), - ) - create_dir_unless_exists(install_folder, "lib") - - for fname in glob.glob(os.path.join(build_folder, "include", "*.h")): - shutil.copy(fname, os.path.join(install_folder, "include")) - - if building_on_windows: - msvc_builddir = find_msvc_source_folder(build_folder, requires_built=True) - if msvc_builddir is not None: - print("Using MSVC build dir: %s\n\n" % msvc_builddir) - for fname in glob.glob(os.path.join(msvc_builddir, "Release", "*.lib")): - shutil.copy(fname, os.path.join(install_folder, "lib")) - else: - print("Cannot find MSVC build dir in %s\n\n" % build_folder) - return False - else: - for fname in glob.glob( - os.path.join(build_folder, "src", ".libs", "libigraph.*") - ): - shutil.copy(fname, os.path.join(install_folder, "lib")) - - return True - - @staticmethod - def enhanced_env(**kwargs): - env = os.environ.copy() - for k, v in kwargs.items(): - prev = os.environ.get(k) - env[k] = "{0} {1}".format(prev, v) if prev else v - return env - - ########################################################################### @@ -464,7 +228,7 @@ def compile_in(self, source_folder, build_folder, install_folder): """ global is_windows - cmake = find_executable("cmake") + cmake = which("cmake") if not cmake: print( "igraph uses CMake as the build system. You need to install CMake " @@ -476,7 +240,7 @@ def compile_in(self, source_folder, build_folder, install_folder): os.chdir(build_folder) print("Configuring build...") - args = [cmake, build_to_source_folder] + args = [cmake, str(build_to_source_folder)] for deps in "ARPACK BLAS CXSPARSE GLPK LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") @@ -496,17 +260,11 @@ def compile_in(self, source_folder, build_folder, install_folder): return False print("Installing build...") - retcode = subprocess.call([cmake, "--install", ".", "--prefix", install_folder]) + retcode = subprocess.call([cmake, "--install", ".", "--prefix", str(install_folder)]) if retcode: return False - return self.parse_pkgconfig_file(os.path.join(install_folder, "lib", "pkgconfig", "igraph.pc")) - - def copy_build_artifacts( - self, source_folder, build_folder, install_folder, libraries - ): - # Nothing to do; we already installed stuff in the compilation step - return True + return self.parse_pkgconfig_file(install_folder / "lib" / "pkgconfig" / "igraph.pc") ########################################################################### @@ -675,37 +433,34 @@ def compile_igraph_from_vendor_source(self): """Compiles igraph from the vendored source code inside `vendor/source/igraph`. This folder typically comes from a git submodule. """ - if os.path.exists(os.path.join("vendor", "install", "igraph")): + vendor_folder = Path("vendor") + source_folder = vendor_folder / "source" / "igraph" + build_folder = vendor_folder / "build" / "igraph" + install_folder = vendor_folder / "install" / "igraph" + + if install_folder.exists(): # Vendored igraph already compiled and installed, just use it self.use_vendored_igraph() return True - vendor_source_path = os.path.join("vendor", "source", "igraph") - if os.path.isfile(os.path.join(vendor_source_path, "CMakeLists.txt")): + if (source_folder / "CMakeLists.txt").exists(): igraph_builder = IgraphCCoreCMakeBuilder() - elif os.path.isfile(os.path.join(vendor_source_path, "configure.ac")): - igraph_builder = IgraphCCoreAutotoolsBuilder() else: - # No git submodule present with vendored source - print("Cannot find vendored igraph source in " + vendor_source_path) + print("Cannot find vendored igraph source in {0}".format(source_folder)) print("") return False - source_folder = os.path.join("vendor", "source", "igraph") - build_folder = os.path.join("vendor", "build", "igraph") - install_folder = os.path.join("vendor", "install", "igraph") - print("We are going to build the C core of igraph.") - print(" Source folder: %s" % source_folder) - print(" Build folder: %s" % build_folder) - print(" Install folder: %s" % install_folder) + print(" Source folder: {0}".format(source_folder)) + print(" Build folder: {0}".format(build_folder)) + print(" Install folder: {0}".format(install_folder)) print("") - source_folder = os.path.abspath(source_folder) - build_folder = os.path.abspath(build_folder) - install_folder = os.path.abspath(install_folder) + source_folder = source_folder.resolve() + build_folder = build_folder.resolve() + install_folder = install_folder.resolve() - create_dir_unless_exists(build_folder) + Path(build_folder).mkdir(parents=True, exist_ok=True) cwd = os.getcwd() try: @@ -717,16 +472,6 @@ def compile_igraph_from_vendor_source(self): finally: os.chdir(cwd) - if not igraph_builder.copy_build_artifacts( - source_folder=source_folder, - build_folder=build_folder, - install_folder=install_folder, - libraries=libraries, - ): - print("Could not compile the C core of igraph.") - print("") - sys.exit(1) - igraph_builder.create_build_config_file(install_folder, libraries) self.use_vendored_igraph() @@ -852,8 +597,6 @@ def use_educated_guess(self): """Tries to guess the proper library names, include and library paths if everything else failed.""" - preprocess_fallback_config() - global LIBIGRAPH_FALLBACK_LIBRARIES global LIBIGRAPH_FALLBACK_INCLUDE_DIRS global LIBIGRAPH_FALLBACK_LIBRARY_DIRS From b520fb8cd1764d5e86215153fc958ad78730faa1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Feb 2021 15:22:59 +0100 Subject: [PATCH 0381/1892] updating to igraph 0.9.0 --- src/_igraph/graphobject.c | 12 ++++++++---- vendor/source/igraph | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 126d3025d..6a5dcfd8a 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2273,7 +2273,7 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, if (igraph_establishment_game(&g, (igraph_integer_t) n, (igraph_integer_t) types, (igraph_integer_t) k, &td, &pm, - PyObject_IsTrue(directed))) { + PyObject_IsTrue(directed), 0)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&pm); igraph_vector_destroy(&td); @@ -2894,7 +2894,7 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, types; + long n, in_types, out_types; PyObject *type_dist_matrix, *pref_matrix; PyObject *loops = Py_False; igraph_matrix_t pm; @@ -2913,13 +2913,15 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, &attribute_key, &loops)) return NULL; - types = PyList_Size(type_dist_matrix); if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) return NULL; if (igraphmodule_PyList_to_matrix_t(type_dist_matrix, &td)) { igraph_matrix_destroy(&pm); return NULL; } + in_types = igraph_matrix_nrow(&pm); + out_types = igraph_matrix_ncol(&pm); + store_attribs = (attribute_key && attribute_key != Py_None); if (store_attribs) { if (igraph_vector_init(&in_type_vec, (igraph_integer_t) n)) { @@ -2938,7 +2940,9 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, } if (igraph_asymmetric_preference_game(&g, (igraph_integer_t) n, - (igraph_integer_t) types, &td, &pm, + (igraph_integer_t) in_types, + (igraph_integer_t) out_types, + &td, &pm, store_attribs ? &in_type_vec : 0, store_attribs ? &out_type_vec : 0, PyObject_IsTrue(loops))) { diff --git a/vendor/source/igraph b/vendor/source/igraph index 7ac8a58e2..6bb4e76c1 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 7ac8a58e2925c2fd8d0afdcfd6b87e07569aa0d5 +Subproject commit 6bb4e76c1d0f971363034e23d06b238a423315cf From 9f8ba30eaec25863e1dbf7c0508e0ac2fcad6407 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 20 Feb 2021 21:22:06 +0100 Subject: [PATCH 0382/1892] doc: clarified that the 'fixed' argument is ineffective in the DrL layout --- src/_igraph/graphobject.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 6a5dcfd8a..06dab05ac 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6866,6 +6866,12 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, return NULL; if (fixed_o != 0 && fixed_o != Py_None) { + /* Apparently the "fixed" argument does not do anything in the DrL + * implementation so we throw a warning if the user tries to use it */ + PyErr_Warn(PyExc_DeprecationWarning, "The fixed=... argument of the DrL " + "layout is ignored; it is kept only for sake of backwards " + "compatibility. The DrL layout algorithm does not support " + "permanently fixed nodes."); fixed = (igraph_vector_bool_t*)malloc(sizeof(igraph_vector_bool_t)); if (!fixed) { PyErr_NoMemory(); @@ -14299,11 +14305,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param seed: if C{None}, uses a random starting layout for the\n" " algorithm. If a matrix (list of lists), uses the given matrix\n" " as the starting position.\n" - "@param fixed: if a seed is given, you can specify some vertices to be\n" - " kept fixed at their original position in the seed by passing an\n" - " appropriate list here. The list must have exactly as many items as\n" - " the number of vertices in the graph. Items of the list that evaluate\n" - " to C{True} denote vertices that will not be moved.\n" + "@param fixed: ignored. We used to assume that the DrL layout supports\n" + " fixed nodes, but later it turned out that the argument has no effect\n" + " in the original DrL code. We kept the argument for sake of backwards\n" + " compatibility, but it will have no effect on the final layout.\n" "@param options: if you give a string argument here, you can select from\n" " five default preset parameterisations: C{default}, C{coarsen} for a\n" " coarser layout, C{coarsest} for an even coarser layout, C{refine} for\n" From d2c30b226efa94a62629a7313a0960e8ae6bf138 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Feb 2021 21:18:01 +0100 Subject: [PATCH 0383/1892] remove Python 2.7 from badge; not supported any more [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b89b58c09..196de140f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Travis CI](https://img.shields.io/travis/igraph/python-igraph)](https://travis-ci.org/igraph/python-igraph) -[![PyPI pyversions](https://img.shields.io/badge/python-2.7%20%7C%203.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) Python interface for the igraph library From 1b9d50957ac3bd313e7dbf65664629ea5d6c03ff Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Feb 2021 21:40:59 +0100 Subject: [PATCH 0384/1892] setup.py now accepts extra CMake arguments from environment --- setup.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 73b432abe..9a508814e 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ from setuptools import setup, Command, Extension import glob +import shlex import shutil import subprocess import sys @@ -240,7 +241,13 @@ def compile_in(self, source_folder, build_folder, install_folder): os.chdir(build_folder) print("Configuring build...") - args = [cmake, str(build_to_source_folder)] + args = [cmake] + + # Add any extra CMake args from environment variables + if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: + args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) + + # Build the Python interface with vendored libraries for deps in "ARPACK BLAS CXSPARSE GLPK LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") @@ -248,6 +255,9 @@ def compile_in(self, source_folder, build_folder, install_folder): # Python shared library args.append("-DCMAKE_POSITION_INDEPENDENT_CODE=ON") + # Finally, add the source folder path + args.append(str(build_to_source_folder)) + retcode = subprocess.call(args) if retcode: return False From 719c4d8e738c4e80bc1fb1813b354dd866d5ad6e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Feb 2021 21:44:12 +0100 Subject: [PATCH 0385/1892] ci: try to give a hint to CMake about the platform we are building for --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index dca9b2d48..98e059d0d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,18 +5,19 @@ environment: global: CIBW_BEFORE_BUILD: python setup.py build_c_core CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - IGRAPH_EXTRA_CONFIGURE_ARGS: "--disable-graphml" PYTHON: "C:\\Python37" matrix: - CIBW_BUILD: "*-win32" CIBW_SKIP: "pp27-* cp27-* cp35-*" + IGRAPH_EXTRA_CMAKE_ARGS: "-A Win32" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" - CIBW_BUILD: "*-win_amd64" CIBW_SKIP: "pp27-* cp27-* cp35-*" + IGRAPH_EXTRA_CMAKE_ARGS: "-A x64" MSYSTEM: MINGW64 PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x64" From 99fc5ce097397d1516dd2e18cd300a4d10f1e5cd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Feb 2021 22:04:29 +0100 Subject: [PATCH 0386/1892] ci: fix name of environment variable that passes extra args to cmake --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 98e059d0d..30e1daab8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,14 +10,14 @@ environment: matrix: - CIBW_BUILD: "*-win32" CIBW_SKIP: "pp27-* cp27-* cp35-*" - IGRAPH_EXTRA_CMAKE_ARGS: "-A Win32" + IGRAPH_CMAKE_EXTRA_ARGS: "-A Win32" MSYSTEM: MINGW32 PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x86" - CIBW_BUILD: "*-win_amd64" CIBW_SKIP: "pp27-* cp27-* cp35-*" - IGRAPH_EXTRA_CMAKE_ARGS: "-A x64" + IGRAPH_CMAKE_EXTRA_ARGS: "-A x64" MSYSTEM: MINGW64 PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% TARGET_ARCH: "x64" From 15bb29a550db66501db171855ce569cb82db1fce Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 17:29:51 +0100 Subject: [PATCH 0387/1892] added changelog, documenting all major changes since python-igraph 0.8.3 --- CHANGELOG.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..7c6acfca3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,64 @@ +# igraph Python interface changelog + +## [Unreleased] + +### Added + +* `Graph.DataFrame` now has a `use_vids=...` keyword argument that decides whether + the data frame contains vertex IDs (`True`) or vertex names (`False`). (PR #348) + +* Added `MatplotlibGraphDrawer` to draw a graph on an existing Matplotlib + figure. (PR #341) + +* Added a code path to choose between preferred image viewers on FreeBSD. (PR #354) + +* Added `Graph.harmonic_centrality()` that wraps `igraph_harmonic_centrality()` + from the underlying C library. + +### Changed + +* `python-igraph` is now compatible with `igraph` 0.9.0. + +* The setup script was adapted to the new CMake-based build system of `igraph`. + +* Dropped support for older Python versions; the oldest Python version that + `python-igraph` is tested on is now Python 3.6. + +* The default splitting heuristic of the BLISS isomorphism algorithm was changed + from `IGRAPH_BLISS_FM` (first maximally non-trivially connected non-singleton cell) + to `IGRAPH_BLISS_FL` (first largest non-singleton cell) as this seems to provide + better performance on a variety of graph classes. This change is a follow-up + of the change in the recommended heuristic in the core igraph C library. + +### Fixed + +* Fixed crashes in the Python-C glue code related to the handling of empty + vectors in certain attribute merging functions (see issue #358). + +* Fixed a memory leak in `Graph.closeness_centrality()` when an invalid `cutoff` + argument was provided to the function. + +* Clarified that the `fixed=...` argument is ineffective for the DrL layout + because the underlying C code does not handle it. The argument was _not_ + removed for sake of backwards compatibility. + +* `VertexSeq.find(name=x)` now works correctly when `x` is an integer; fixes + #367 + +### Miscellaneous + +* The Python codebase was piped through `black` for consistent formatting. + +* Wildcard imports were removed from the codebase. + +* CI tests were moved to Azure Pipelines from Travis. + +* The core C library is now built with `-fPIC` on Linux to allow linking to the + Python interface. + +## 0.8.3 + +This is the last released version of `python-igraph` without a changelog file. +Please refer to the commit logs at https://github.com/igraph/python-igraph for +a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 +are documented above. From e2b49bfaf617cce7bb122a9be429a38d7f860b61 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 18:13:03 +0100 Subject: [PATCH 0388/1892] chore: bumped version to 0.9.0 --- CHANGELOG.md | 2 +- doc/source/conf.py | 16 ++++++++-------- src/igraph/version.py | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c6acfca3..f4a6fc05a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,7 @@ * Wildcard imports were removed from the codebase. -* CI tests were moved to Azure Pipelines from Travis. +* CI tests were moved to Github Actions from Travis. * The core C library is now built with `-fPIC` on Linux to allow linking to the Python interface. diff --git a/doc/source/conf.py b/doc/source/conf.py index 3a1483d4e..16be2bd7f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -44,16 +44,16 @@ # General information about the project. project = u'python-igraph' -copyright = u'2010-{0}, Tamás Nepusz, Gábor Csárdi'.format(datetime.now().year) +copyright = u'2010-{0}, The igraph development team'.format(datetime.now().year) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.8.3' +version = '0.9.0' # The full version, including alpha/beta/rc tags. -release = '0.8.3' +release = '0.9.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -185,7 +185,7 @@ # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'python-igraph.tex', u'python-igraph Documentation', - u'Tamas Nepusz, Gabor Csardi', 'manual'), + u'The igraph development team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -218,7 +218,7 @@ # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'python-igraph', u'python-igraph Documentation', - [u'Tamas Nepusz, Gabor Csardi'], 1) + [u'The igraph development team'], 1) ] @@ -226,9 +226,9 @@ # Bibliographic Dublin Core info. epub_title = u'python-igraph' -epub_author = u'Tamas Nepusz, Gabor Csardi' -epub_publisher = u'Tamas Nepusz, Gabor Csardi' -epub_copyright = u'2010, Tamas Nepusz, Gabor Csardi' +epub_author = u'The igraph development team' +epub_publisher = u'The igraph development team' +epub_copyright = u'2010, The igraph development team' # The language of the text. It defaults to the language option # or en if the language is not set. diff --git a/src/igraph/version.py b/src/igraph/version.py index aea240828..1836d2e87 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 8, 3) +__version_info__ = (0, 9, 0) __version__ = ".".join("{0}".format(x) for x in __version_info__) From e6ca6ee969c6f2fdfa1b56128c10d74a065acc70 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 18:32:58 +0100 Subject: [PATCH 0389/1892] ci: it looks like we need a newer CMake in the Linux cibuildwheel env --- .github/workflows/deploy.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4ee06b956..7e3a6781f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,15 +23,15 @@ jobs: - name: Install OS dependencies run: sudo apt-get install gfortran flex bison - - name: Install Python dependencies + - name: Install CMake and cibuildwheel run: | # Pypi has no pip by default, and ubuntu blocks python -m ensurepip # However, Github runners are supposed to have pip installed by default # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install cibuildwheel - - name: Wheels (linux) + pip install cmake cibuildwheel + - name: Wheels (Linux) env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" @@ -44,7 +44,7 @@ jobs: with: name: source-dist path: dist/python-igraph-*.tar.gz - - name: Upload linux wheels + - name: Upload Linux wheels uses: actions/upload-artifact@v2 with: name: linux-wheels @@ -72,7 +72,7 @@ jobs: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" CIBW_SKIP: "cp27-* pp27-* cp35-*" - - name: Upload linux wheels + - name: Upload Linux wheels uses: actions/upload-artifact@v2 with: name: OSX-wheels @@ -90,7 +90,7 @@ jobs: name: source-dist path: dist - - name: "Download artifacts: linux wheels" + - name: "Download artifacts: Linux wheels" uses: actions/download-artifact@v2 with: name: linux-wheels From f1196ae80233aca059d72d4d88d7b12ad6d02486 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 18:43:45 +0100 Subject: [PATCH 0390/1892] ci: cmake is needed _inside_ cibuildwheel, not in the host environment --- .github/workflows/deploy.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7e3a6781f..65ef5466e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,17 +23,17 @@ jobs: - name: Install OS dependencies run: sudo apt-get install gfortran flex bison - - name: Install CMake and cibuildwheel + - name: Install cibuildwheel run: | # Pypi has no pip by default, and ubuntu blocks python -m ensurepip # However, Github runners are supposed to have pip installed by default # https://docs.github.com/en/actions/guides/building-and-testing-python #wget -qO- https://bootstrap.pypa.io/get-pip.py | python python -m pip install --upgrade pip - pip install cmake cibuildwheel + pip install cibuildwheel - name: Wheels (Linux) env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" CIBW_SKIP: "cp27-* pp27-* cp35-*" run: | @@ -69,7 +69,7 @@ jobs: run: | python -m cibuildwheel --output-dir wheelhouse env: - CIBW_BEFORE_BUILD: "python setup.py build_c_core" + CIBW_BEFORE_BUILD: "pip install cmake && python setup.py build_c_core" CIBW_TEST_COMMAND: "cd {project} && python -m unittest" CIBW_SKIP: "cp27-* pp27-* cp35-*" - name: Upload Linux wheels From b88389553e1f5780a4b12c2c129da673ab053d2b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 19:10:08 +0100 Subject: [PATCH 0391/1892] ci: setup.py now also looks for igraph.pc in lib64 --- setup.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9a508814e..b95fc67c0 100644 --- a/setup.py +++ b/setup.py @@ -274,7 +274,15 @@ def compile_in(self, source_folder, build_folder, install_folder): if retcode: return False - return self.parse_pkgconfig_file(install_folder / "lib" / "pkgconfig" / "igraph.pc") + pkgconfig_candidates = [ + install_folder / "lib" / "pkgconfig" / "igraph.pc", + install_folder / "lib64" / "pkgconfig" / "igraph.pc" + ] + for candidate in pkgconfig_candidates: + if candidate.exists(): + return self.parse_pkgconfig_file(candidate) + + raise RuntimeError("no igraph.pc was found in the installation folder of igraph") ########################################################################### From 83f8b7675d025633073520698a280646a749e4f7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 19:50:57 +0100 Subject: [PATCH 0392/1892] fix: use a slightly newer revision from upstream that fixes a problem w.r.t lib/ vs lib64/ in igraph.pc --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 6bb4e76c1..8bf4adbe3 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 6bb4e76c1d0f971363034e23d06b238a423315cf +Subproject commit 8bf4adbe32de8e0a746fbf8b31268ff040cbe175 From b45a51d963223d3d287fd3af101d05a716c8d08d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 20:19:28 +0100 Subject: [PATCH 0393/1892] fix: handle lib/ vs lib64/ properly in other places of setup.py --- setup.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index b95fc67c0..da407363b 100644 --- a/setup.py +++ b/setup.py @@ -600,16 +600,27 @@ def use_vendored_igraph(self): the include and library paths and the library names accordingly.""" building_on_windows = building_on_windows_msvc() - buildcfg.include_dirs = [os.path.join("vendor", "install", "igraph", "include", "igraph")] - buildcfg.library_dirs = [os.path.join("vendor", "install", "igraph", "lib")] + vendor_dir = Path("vendor") / "install" / "igraph" + + buildcfg.include_dirs = [str(vendor_dir / "include" / "igraph")] + buildcfg.library_dirs = [] + + for candidate in ("lib", "lib64"): + candidate = vendor_dir / candidate + if candidate.exists(): + buildcfg.library_dirs.append(str(candidate)) + break + else: + raise RuntimeError("cannot detect igraph library dir within " + str(vendor_dir)) + if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" if building_on_windows: buildcfg.define_macros.append(("IGRAPH_STATIC", "1")) - buildcfg_file = os.path.join("vendor", "install", "igraph", "build.cfg") - if os.path.exists(buildcfg_file): - buildcfg.libraries = eval(open(buildcfg_file).read()) + buildcfg_file = vendor_dir / "build.cfg" + if buildcfg_file.exists(): + buildcfg.libraries = eval(buildcfg_file.open("r").read()) def use_educated_guess(self): """Tries to guess the proper library names, include and library paths From abbef9bfddc964f15fd61cc0c5869ed1e0009a56 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 20:38:02 +0100 Subject: [PATCH 0394/1892] chore: finalize 0.9.0 release From 11baa7847ffb94c27d028313d1b0e45a96fccb6e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 20:52:16 +0100 Subject: [PATCH 0395/1892] fall back to official igraph 0.9.0 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 8bf4adbe3..6bb4e76c1 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 8bf4adbe32de8e0a746fbf8b31268ff040cbe175 +Subproject commit 6bb4e76c1d0f971363034e23d06b238a423315cf From 904d5d9f6fc6cb3867bde65df9186166df5f9781 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 20:55:03 +0100 Subject: [PATCH 0396/1892] chore: finalize changelog for 0.9.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a6fc05a..55496ca79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.9.0] ### Added From e6653b76646abad646f2c2493e625302461d2f0a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Feb 2021 22:20:08 +0100 Subject: [PATCH 0397/1892] fix: update MANIFEST.in for new directory structure of the igraph repo --- MANIFEST.in | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 2278efcb5..9bfa4b090 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,12 +8,9 @@ include scripts/epydoc.cfg include tests/*.py graft vendor/source/igraph -prune vendor/source/igraph/doc/abstracts -prune vendor/source/igraph/doc/papers -prune vendor/source/igraph/doc/presentations +prune vendor/source/igraph/etc/abstracts +prune vendor/source/igraph/etc/papers +prune vendor/source/igraph/etc/presentations prune vendor/source/igraph/interfaces -prune vendor/source/igraph/nexus -prune vendor/source/igraph/tools/virtual -prune vendor/source/igraph/optional/simpleraytracer -prune vendor/source/igraph/tools/virtual +prune vendor/source/igraph/vendor/simpleraytracer From 9cd20858871fe7fac3d173553ea1013fde56f7c7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Feb 2021 13:20:45 +0100 Subject: [PATCH 0398/1892] doc: getting rid of Python 2.x constructs and fixing markup errors, preparing for transition from Epydoc --- scripts/epydoc-patched | 20 ----------- src/_igraph/edgeobject.c | 2 +- src/_igraph/vertexobject.c | 2 +- src/igraph/__init__.py | 8 ++++- src/igraph/app/shell.py | 4 +-- src/igraph/clustering.py | 41 ++++++++++++---------- src/igraph/configuration.py | 10 +++--- src/igraph/cut.py | 6 ++-- src/igraph/datatypes.py | 14 ++++---- src/igraph/drawing/__init__.py | 2 +- src/igraph/drawing/coord.py | 1 - src/igraph/drawing/text.py | 64 +++++++++++++--------------------- src/igraph/formula.py | 8 ++--- src/igraph/layout.py | 6 ++-- src/igraph/operators.py | 6 ++-- src/igraph/remote/gephi.py | 19 ++-------- src/igraph/statistics.py | 12 +++---- src/igraph/summary.py | 10 +----- src/igraph/utils.py | 5 +-- 19 files changed, 92 insertions(+), 148 deletions(-) delete mode 100755 scripts/epydoc-patched diff --git a/scripts/epydoc-patched b/scripts/epydoc-patched deleted file mode 100755 index e71bb35ce..000000000 --- a/scripts/epydoc-patched +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -"""Patched version of Epydoc that does not blow up with `docutils` -newer than 0.6 when reST is used as a markup language""" - -from epydoc.cli import cli -from epydoc.markup.restructuredtext import parse_docstring -from epydoc.docwriter.latex import LatexWriter - -# Check whether Epydoc needs patching -doc = parse_docstring("aaa", []) -try: - doc.summary() -except AttributeError: - # Monkey-patching docutils so that Text nodes have a "data" property, - # which is always empty - from docutils.nodes import Text - Text.data="" - -LatexWriter.PREAMBLE += [r'\usepackage[T1]{fontenc}'] -cli() \ No newline at end of file diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index ab0d71b77..d438e9aa7 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -739,7 +739,7 @@ PyTypeObject igraphmodule_EdgeType = "The attributes of the edge can be accessed by using the edge\n" "as a hash:\n\n" " >>> e[\"weight\"] = 2 #doctest: +SKIP\n" - " >>> print e[\"weight\"] #doctest: +SKIP\n" + " >>> print(e[\"weight\"]) #doctest: +SKIP\n" " 2\n", // tp_doc 0, // tp_traverse 0, // tp_clear diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 9fe1b7495..834541834 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -873,7 +873,7 @@ PyTypeObject igraphmodule_VertexType = "The attributes of the vertex can be accessed by using the vertex\n" "as a hash:\n\n" " >>> v[\"color\"] = \"red\" #doctest: +SKIP\n" - " >>> print v[\"color\"] #doctest: +SKIP\n" + " >>> print(v[\"color\"]) #doctest: +SKIP\n" " red\n", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 4f22a459f..9d10f92c0 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3513,6 +3513,9 @@ def get_vertex_dataframe(self): If you want to use vertex names as index, you can do: + >>> from string import ascii_letters + >>> graph = Graph.GRG(25, 0.4) + >>> graph.vs["name"] = ascii_letters[:graph.vcount()] >>> df = graph.get_vertex_dataframe() >>> df.set_index('name', inplace=True) @@ -3543,6 +3546,9 @@ def get_edge_dataframe(self): If you want to use source and target vertex IDs as index, you can do: + >>> from string import ascii_letters + >>> graph = Graph.GRG(25, 0.4) + >>> graph.vs["name"] = ascii_letters[:graph.vcount()] >>> df = graph.get_edge_dataframe() >>> df.set_index(['source', 'target'], inplace=True) @@ -4591,7 +4597,7 @@ class EdgeSeq(_igraph.EdgeSeq): >>> g=Graph.Full(3) >>> for e in g.es: - ... print e.tuple + ... print(e.tuple) ... (0, 1) (0, 2) diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index 9b9293055..fcdf10eb8 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -43,14 +43,14 @@ class TerminalController: output to the terminal: >>> term = TerminalController() - >>> print 'This is '+term.GREEN+'green'+term.NORMAL + >>> print('This is '+term.GREEN+'green'+term.NORMAL) This is green Alternatively, the `render()` method can used, which replaces '${action}' with the string required to perform 'action': >>> term = TerminalController() - >>> print term.render('This is ${GREEN}green${NORMAL}') + >>> print(term.render('This is ${GREEN}green${NORMAL}')) This is green If the terminal doesn't support a given action, then the value of diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index a7e7d9238..7380e7e03 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -1,8 +1,6 @@ # vim:ts=4:sw=4:sts=4:et # -*- coding: utf-8 -*- -"""Classes related to graph clustering. - -@undocumented: _handle_mark_groups_arg_for_clustering, _prepare_community_comparison""" +"""Classes related to graph clustering.""" __license__ = u""" Copyright (C) 2006-2012 Tamás Nepusz @@ -63,7 +61,7 @@ class Clustering(object): of clusters: >>> for cluster in cl: - ... print " ".join(str(idx) for idx in cluster) + ... print(" ".join(str(idx) for idx in cluster)) ... 0 1 2 3 4 5 6 @@ -73,7 +71,7 @@ class Clustering(object): the clustering object to a list: >>> cluster_list = list(cl) - >>> print cluster_list + >>> print(cluster_list) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10]] @undocumented: _formatted_cluster_iterator @@ -347,7 +345,7 @@ def cluster_graph(self, combine_vertices=None, combine_edges=None): See L{Graph.contract_vertices()} for more details. @param combine_edges: specifies how to derive the attributes of the edges in the new graph from the attributes of the old ones. See - L{Graph.simplify()} for more details. If you specify C{False} + L{igraph.Graph.simplify()} for more details. If you specify C{False} here, edges will not be combined, and the number of edges between the vertices representing the original clusters will be equal to the number of edges between the members of those clusters in the @@ -416,19 +414,21 @@ def _recalculate_modularity_safe(self): def subgraph(self, idx): """Get the subgraph belonging to a given cluster. + Precondition: the vertex set of the graph hasn't been modified since the + moment the cover was constructed. + @param idx: the cluster index @return: a copy of the subgraph - @precondition: the vertex set of the graph hasn't been modified since - the moment the clustering was constructed. """ return self._graph.subgraph(self[idx]) def subgraphs(self): """Gets all the subgraphs belonging to each of the clusters. + Precondition: the vertex set of the graph hasn't been modified since the + moment the cover was constructed. + @return: a list containing copies of the subgraphs - @precondition: the vertex set of the graph hasn't been modified since - the moment the clustering was constructed. """ return [self._graph.subgraph(cl) for cl in self] @@ -439,12 +439,13 @@ def giant(self): the clustering. It may also be known as the I{giant community} if the clustering represents the result of a community detection function. + Precondition: the vertex set of the graph hasn't been modified since the + moment the cover was constructed. + @note: there can be multiple largest clusters, this method will return the copy of an arbitrary one if there are multiple largest clusters. @return: a copy of the largest cluster. - @precondition: the vertex set of the graph hasn't been modified since - the moment the clustering was constructed. """ ss = self.sizes() max_size = max(ss) @@ -657,7 +658,7 @@ def format(self, format="newick"): if format == "newick": n = self._nitems + self._nmerges if self._names is None: - nodes = range(n) + nodes = list(range(n)) else: nodes = list(self._names) if len(nodes) < n: @@ -1098,7 +1099,7 @@ class Cover(object): clusters: >>> for cluster in cl: - ... print " ".join(str(idx) for idx in cluster) + ... print(" ".join(str(idx) for idx in cluster)) ... 0 1 2 3 2 3 4 @@ -1108,7 +1109,7 @@ class Cover(object): the cover to a list: >>> cluster_list = list(cl) - >>> print cluster_list + >>> print(cluster_list) [[0, 1, 2, 3], [2, 3, 4], [0, 1, 6]] L{Clustering} objects can readily be converted to L{Cover} objects @@ -1286,19 +1287,21 @@ def graph(self): def subgraph(self, idx): """Get the subgraph belonging to a given cluster. + Precondition: the vertex set of the graph hasn't been modified since the + moment the cover was constructed. + @param idx: the cluster index @return: a copy of the subgraph - @precondition: the vertex set of the graph hasn't been modified since - the moment the cover was constructed. """ return self._graph.subgraph(self[idx]) def subgraphs(self): """Gets all the subgraphs belonging to each of the clusters. + Precondition: the vertex set of the graph hasn't been modified since the + moment the cover was constructed. + @return: a list containing copies of the subgraphs - @precondition: the vertex set of the graph hasn't been modified since - the moment the cover was constructed. """ return [self._graph.subgraph(cl) for cl in self] diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 2a6921f21..1c507c4f1 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -109,9 +109,9 @@ class Configuration(object): This object provides an interface to the configuration data using the syntax known from dict: - >>> c=Configuration() + >>> c = Configuration() >>> c["general.verbose"] = True - >>> print c["general.verbose"] + >>> print(c["general.verbose"]) True Configuration keys are organized into sections, and the name to be used @@ -121,9 +121,9 @@ class Configuration(object): If the name of the section is omitted, it defaults to C{general}, so C{general.verbose} can be referred to as C{verbose}: - >>> c=Configuration() + >>> c = Configuration() >>> c["verbose"] = True - >>> print c["general.verbose"] + >>> print(c["general.verbose"]) True User-level configuration is stored in C{~/.igraphrc} per default on Linux @@ -195,8 +195,6 @@ class Configuration(object): - B{ipython.inlining.Plot}: whether to show instances of the L{Plot} class inline in IPython's console if the console supports it. Default: C{True} - - @undocumented: _item_to_section_key, _types, _sections, _definitions, _instance """ # pylint: disable-msg=R0903 diff --git a/src/igraph/cut.py b/src/igraph/cut.py index 0acbaf500..2d7a5d590 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -59,9 +59,9 @@ class Cut(VertexClustering): >>> from igraph import Graph >>> g = Graph.Ring(20) >>> mc = g.mincut() - >>> print mc.value + >>> print(mc.value) 2.0 - >>> print min(map(len, mc)) + >>> print(min(len(x) for x in mc)) 1 >>> mc.es["color"] = "red" """ @@ -165,7 +165,7 @@ class Flow(Cut): >>> from igraph import Graph >>> g = Graph.Ring(20) >>> mf = g.maxflow(0, 10) - >>> print mf.value + >>> print(mf.value) 2.0 >>> mf.es["color"] = "red" """ diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index b2bf6a17d..75a7bae5f 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -539,16 +539,14 @@ class DyadCensus(tuple): >>> from igraph import Graph >>> g=Graph.Erdos_Renyi(100, 0.2, directed=True) >>> dc=g.dyad_census() - >>> print dc.mutual #doctest:+SKIP + >>> print(dc.mutual) #doctest:+SKIP 179 - >>> print dc["asym"] #doctest:+SKIP + >>> print(dc["asym"]) #doctest:+SKIP 1609 - >>> print tuple(dc), list(dc) #doctest:+SKIP + >>> print(tuple(dc), list(dc)) #doctest:+SKIP (179, 1609, 3162) [179, 1609, 3162] - >>> print sorted(dc.as_dict().items()) #doctest:+ELLIPSIS + >>> print(sorted(dc.as_dict().items())) #doctest:+ELLIPSIS [('asymmetric', ...), ('mutual', ...), ('null', ...)] - - @undocumented: _remap """ _remap = { @@ -615,9 +613,9 @@ class TriadCensus(tuple): >>> from igraph import Graph >>> g=Graph.Erdos_Renyi(100, 0.2, directed=True) >>> tc=g.triad_census() - >>> print tc.t003 #doctest:+SKIP + >>> print(tc.t003) #doctest:+SKIP 39864 - >>> print tc["030C"] #doctest:+SKIP + >>> print(tc["030C"]) #doctest:+SKIP 1206 """ diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 9b91a4f08..364eef307 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -222,7 +222,7 @@ def background(self, color): """Sets the background color of the plot. C{None} means a transparent background. You can use any color specification here that is understood by the C{get} method of the current palette - or by L{igraph.colors.color_name_to_rgb}. + or by L{igraph.drawing.colors.color_name_to_rgb}. """ if color is None: self._background = None diff --git a/src/igraph/drawing/coord.py b/src/igraph/drawing/coord.py index 91db1a05a..a5e51e622 100644 --- a/src/igraph/drawing/coord.py +++ b/src/igraph/drawing/coord.py @@ -2,7 +2,6 @@ Coordinate systems and related plotting routines """ -from igraph.compat import property from igraph.drawing.baseclasses import AbstractCairoDrawer from igraph.drawing.utils import BoundingBox diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index c6bd385cf..6de3b3b9f 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -1,7 +1,5 @@ """ Drawers for labels on plots. - -@undocumented: test """ import re @@ -51,10 +49,8 @@ def draw(self, wrap=False): has an attribute named ``bbox`` which will be used as a bounding box. - :Parameters: - wrap : boolean - whether to allow re-wrapping of the text if it does not fit - within the bounding box horizontally. + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the bounding box horizontally. """ ctx = self.context bbox = self.bbox @@ -90,26 +86,20 @@ def get_text_layout(self, x=None, y=None, width=None, wrap=False): Vertical alignment settings are not taken into account in this method as the text is not drawn within a box. - :Parameters: - x : float or ``None`` - The X coordinate of the reference point where the layout should + @param x: The X coordinate of the reference point where the layout should start. - y : float or ``None`` - The Y coordinate of the reference point where the layout should + @param y: The Y coordinate of the reference point where the layout should start. - width : float or ``None`` - The width of the box in which the text will be fitted. It matters - only when the text is right-aligned or centered. The text will - overflow the box if any of the lines is longer than the box width - and `wrap` is ``False``. - wrap : boolean - whether to allow re-wrapping of the text if it does not fit - within the given width. - - :Returns: - a list consisting of ``(x, y, line)`` tuples where ``x`` and ``y`` - refer to reference points on the Cairo canvas and ``line`` refers - to the corresponding text that should be plotted there. + @param width: The width of the box in which the text will be fitted. It + matters only when the text is right-aligned or centered. The text + will overflow the box if any of the lines is longer than the box + width and `wrap` is ``False``. + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the given width. + + @return: a list consisting of ``(x, y, line)`` tuples where ``x`` and + ``y`` refer to reference points on the Cairo canvas and ``line`` + refers to the corresponding text that should be plotted there. """ ctx = self.context @@ -162,20 +152,16 @@ def draw_at(self, x=None, y=None, width=None, wrap=False): Vertical alignment settings are not taken into account in this method as the text is not drawn within a box. - :Parameters: - x : float or ``None`` - The X coordinate of the reference point where the drawing should + @param x: The X coordinate of the reference point where the layout should start. - y : float or ``None`` - The Y coordinate of the reference point where the drawing should + @param y: The Y coordinate of the reference point where the layout should start. - width : float or ``None`` - The width of the box in which the text will be fitted. It matters - only when the text is right-aligned or centered. The text will - overflow the box if any of the lines is longer than the box width. - wrap : boolean - whether to allow re-wrapping of the text if it does not fit - within the given width. + @param width: The width of the box in which the text will be fitted. It + matters only when the text is right-aligned or centered. The text + will overflow the box if any of the lines is longer than the box + width and `wrap` is ``False``. + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the given width. """ ctx = self.context for ref_x, ref_y, line in self.get_text_layout(x, y, width, wrap): @@ -200,10 +186,8 @@ def _iterlines_wrapped(self, width): The difference between this method and `_iterlines()` is that this method is allowed to re-wrap the line if necessary. - :Parameters: - width : float or ``None`` - The width of the box in which the text will be fitted. Lines will - be wrapped if they are wider than this width. + @param width: The width of the box in which the text will be fitted. + Lines will be wrapped if they are wider than this width. """ ctx = self.context for line in self._text.split("\n"): diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 8d2fce8c4..2b1f26aa6 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -146,13 +146,13 @@ def construct_graph_from_formula(cls, formula=None, attr="name", simplify=True): Some simple examples: >>> from igraph import Graph - >>> print Graph.Formula() # empty graph + >>> print(Graph.Formula()) # empty graph IGRAPH UN-- 0 0 -- + attr: name (v) >>> g = Graph.Formula("A-B") # undirected graph >>> g.vs["name"] ['A', 'B'] - >>> print g + >>> print(g) IGRAPH UN-- 2 1 -- + attr: name (v) + edges (vertex names): @@ -165,7 +165,7 @@ def construct_graph_from_formula(cls, formula=None, attr="name", simplify=True): >>> g = Graph.Formula("A ---> B") # directed graph >>> g.vs["name"] ['A', 'B'] - >>> print g + >>> print(g) IGRAPH DN-- 2 1 -- + attr: name (v) + edges (vertex names): @@ -175,7 +175,7 @@ def construct_graph_from_formula(cls, formula=None, attr="name", simplify=True): with commas. You can also specify isolated vertices: >>> g = Graph.Formula("A--B, C--D, E--F, G--H, I, J, K") - >>> print ", ".join(g.vs["name"]) + >>> print(", ".join(g.vs["name"])) A, B, C, D, E, F, G, H, I, J, K >>> g.clusters().membership [0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6] diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 1d3fd7623..7dd9292df 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -56,13 +56,13 @@ class Layout(object): >>> layout = Layout([(0, 1), (0, 2)]) >>> coords = layout[1] - >>> print coords + >>> print(coords) [0, 2] >>> coords = (0, 3) - >>> print layout[1] + >>> print(layout[1]) [0, 2] >>> layout[1] = coords - >>> print layout[1] + >>> print(layout[1]) [0, 3] """ diff --git a/src/igraph/operators.py b/src/igraph/operators.py index a8c19a40d..8fe113b5c 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -43,7 +43,7 @@ def disjoint_union(graphs): An error is generated if some input graphs are directed and others are undirected. - @param graph: list of graphs. A lazy sequence is not acceptable. + @param graphs: list of graphs. A lazy sequence is not acceptable. @return: the disjoint union graph """ if any(not isinstance(g, GraphBase) for g in graphs): @@ -120,7 +120,7 @@ def union(graphs, byname="auto"): An error is generated if some input graphs are directed and others are undirected. - @param graph: list of graphs. A lazy sequence is not acceptable. + @param graphs: list of graphs. A lazy sequence is not acceptable. @param byname: bool or 'auto' specifying the function behaviour with respect to names vertices (i.e. vertices with the 'name' attribute). If False, ignore vertex names. If True, merge vertices based on names. If @@ -297,7 +297,7 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): An error is generated if some input graphs are directed and others are undirected. - @param graph: list of graphs. A lazy sequence is not acceptable. + @param graphs: list of graphs. A lazy sequence is not acceptable. @param byname: bool or 'auto' specifying the function behaviour with respect to names vertices (i.e. vertices with the 'name' attribute). If False, ignore vertex names. If True, merge vertices based on names. If diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index 5cda23739..74b9d0d46 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -2,22 +2,9 @@ # -*- coding: utf-8 -*- """Classes that help igraph communicate with Gephi (http://www.gephi.org).""" -from igraph.compat import property +import json import urllib.request, urllib.error, urllib.parse -try: - # JSON is optional so we don't blow up with Python < 2.6 - import json -except ImportError: - try: - # Try with simplejson for Python < 2.6 - import simplejson as json - except ImportError: - # No simplejson either - from igraph.drawing.utils import FakeModule - - json = FakeModule() - __all__ = ("GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat") __docformat__ = "restructuredtext en" __license__ = """\ @@ -202,7 +189,7 @@ class GephiGraphStreamer(object): The Gephi graph streaming format is a simple JSON-based format that can be used to post mutations to a graph (i.e. node and edge additions, removals and updates) - to a remote component. For instance, one can open up Gephi (http://www.gephi.org}), + to a remote component. For instance, one can open up Gephi (http://www.gephi.org), install the Gephi graph streaming plugin and then send a graph from igraph straight into the Gephi window by using `GephiGraphStreamer` with the appropriate URL where Gephi is listening. @@ -215,7 +202,7 @@ class GephiGraphStreamer(object): >>> streamer = GephiGraphStreamer() >>> graph = Graph.Formula("A --> B, B --> C") >>> streamer.post(graph, buf) - >>> print buf.getvalue() # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + >>> print(buf.getvalue()) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE {"an": {"igraph:...:v:0": {"name": "A"}}} {"an": {"igraph:...:v:1": {"name": "B"}}} {"an": {"igraph:...:v:2": {"name": "C"}}} diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index dda450851..85955d9f2 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -45,23 +45,23 @@ class FittedPowerLaw(object): >>> result = power_law_fit([1, 2, 3, 4, 5, 6]) >>> result # doctest:+ELLIPSIS - FittedPowerLaw(continuous=False, alpha=2.425828..., xmin=3.0, L=-7.54633..., D=0.2138..., p=0.99311...) + FittedPowerLaw(continuous=False, alpha=2.42..., xmin=3.0, L=-7.54..., D=0.21..., p=0.993...) >>> print(result) # doctest:+ELLIPSIS Fitted power-law distribution on discrete data - Exponent (alpha) = 2.425828 + Exponent (alpha) = 2.42... Cutoff (xmin) = 3.000000 - Log-likelihood = -7.546337 + Log-likelihood = -7.54... H0: data was drawn from the fitted distribution - KS test statistic = 0.213817 - p-value = 0.993111 + KS test statistic = 0.21... + p-value = 0.993... H0 could not be rejected at significance level 0.05 >>> result.alpha # doctest:+ELLIPSIS - 2.425828... + 2.42... >>> result.xmin 3.0 >>> result.continuous diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 6dbffe1c5..24fdf1113 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -1,9 +1,6 @@ # vim:ts=4:sw=4:sts=4:et # -*- coding: utf-8 -*- -"""Summary representation of a graph. - -@undocumented: _get_wrapper_for_width, FakeWrapper -""" +"""Summary representation of a graph.""" from igraph.statistics import median from itertools import islice @@ -83,11 +80,6 @@ class GraphSummary(object): Edges may be presented as an ordinary edge list or an adjacency list. By default, this depends on the number of edges; however, you can control it with the appropriate constructor arguments. - - @undocumented: _construct_edgelist_adjlist, _construct_edgelist_compressed, - _construct_edgelist_edgelist, _construct_graph_attributes, - _construct_vertex_attributes, _construct_header, _edge_attribute_iterator, - _infer_column_alignment, _new_table, _vertex_attribute_iterator """ def __init__( diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 707afb0da..085f4a5ff 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -1,9 +1,6 @@ # vim:ts=4:sw=4:sts=4:et # -*- coding: utf-8 -*- -"""Utility functions that cannot be categorised anywhere else. - -@undocumented: _is_running_in_ipython -""" +"""Utility functions that cannot be categorised anywhere else.""" from contextlib import contextmanager From dffaedfab3707e982c4002f1636c64cc2a85b5e5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Feb 2021 13:25:12 +0100 Subject: [PATCH 0399/1892] doc: updated status badges in README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 196de140f..33bd74214 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -[![Travis CI](https://img.shields.io/travis/igraph/python-igraph)](https://travis-ci.org/igraph/python-igraph) +[![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) +[![Build status](https://ci.appveyor.com/api/projects/status/55i1d4g65q11f9l5?svg=true)](https://ci.appveyor.com/project/ntamas/python-igraph-jst2e) [![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) From ed39d05d10fbecfd0ab4eb2c7234287a5640e196 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Feb 2021 13:34:00 +0100 Subject: [PATCH 0400/1892] build: GMP also has to be vendored --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index da407363b..f68e0dc7c 100644 --- a/setup.py +++ b/setup.py @@ -248,7 +248,7 @@ def compile_in(self, source_folder, build_folder, install_folder): args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) # Build the Python interface with vendored libraries - for deps in "ARPACK BLAS CXSPARSE GLPK LAPACK".split(): + for deps in "ARPACK BLAS CXSPARSE GLPK GMP LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") # -fPIC is needed on Linux so we can link to a static igraph lib from a From 82248f1e64aa6cd71b8cd1ecdc0c01dd2d047724 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Feb 2021 13:34:32 +0100 Subject: [PATCH 0401/1892] fix: extra CMake args in setup script should come after the default ones so they can be overridden --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index f68e0dc7c..88bd0d577 100644 --- a/setup.py +++ b/setup.py @@ -243,10 +243,6 @@ def compile_in(self, source_folder, build_folder, install_folder): print("Configuring build...") args = [cmake] - # Add any extra CMake args from environment variables - if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: - args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) - # Build the Python interface with vendored libraries for deps in "ARPACK BLAS CXSPARSE GLPK GMP LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") @@ -255,6 +251,10 @@ def compile_in(self, source_folder, build_folder, install_folder): # Python shared library args.append("-DCMAKE_POSITION_INDEPENDENT_CODE=ON") + # Add any extra CMake args from environment variables + if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: + args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) + # Finally, add the source folder path args.append(str(build_to_source_folder)) From 03640186d232192e458582a99c9010c8c6af70ad Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Feb 2021 14:00:51 +0100 Subject: [PATCH 0402/1892] doc: replaced autotools with CMake in README.md [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33bd74214..c65591029 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ code are picked up automatically by Python: python setup.py develop ``` -**NOTE**: Building requires `autotools`, a C compiler, and a few more dependencies. +**NOTE**: Building requires `CMake`, a C compiler, and a few more dependencies. Changes that you make to the Python code do not need any extra action. However, if you adjust the source code of the C extension, you need to rebuild it by running From f0c1cfa8ea0f1b2f0c6eac2661b3d3e048297796 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 1 Mar 2021 11:29:15 +0100 Subject: [PATCH 0403/1892] fix: nicer formatting of error messages when they do not end with a punctuation mark --- src/_igraph/error.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/_igraph/error.c b/src/_igraph/error.c index bb99960b8..2954ad7b7 100644 --- a/src/_igraph/error.c +++ b/src/_igraph/error.c @@ -41,11 +41,12 @@ PyObject* igraphmodule_InternalError; * \c NULL value to their callers until it is propagated to the Python * interpreter. */ -PyObject* igraphmodule_handle_igraph_error() -{ +PyObject* igraphmodule_handle_igraph_error() { if (!PyErr_Occurred()) { - PyErr_SetString(igraphmodule_InternalError, - "Internal igraph error. Please contact the author!"); + PyErr_SetString( + igraphmodule_InternalError, + "Internal igraph error. Please contact the author!" + ); } return NULL; @@ -56,7 +57,7 @@ PyObject* igraphmodule_handle_igraph_error() * \brief Warning hook for \c igraph */ void igraphmodule_igraph_warning_hook(const char *reason, const char *file, - int line, int igraph_errno) { + int line, int igraph_errno) { char buf[4096]; snprintf(buf, sizeof(buf), "%s at %s:%i", reason, file, line); PyErr_Warn(PyExc_RuntimeWarning, buf); @@ -67,18 +68,29 @@ void igraphmodule_igraph_warning_hook(const char *reason, const char *file, * \brief Error hook for \c igraph */ void igraphmodule_igraph_error_hook(const char *reason, const char *file, - int line, int igraph_errno) { + int line, int igraph_errno) { char buf[4096]; + char* punctuation = ""; PyObject *exc = igraphmodule_InternalError; if (igraph_errno == IGRAPH_UNIMPLEMENTED) - exc = PyExc_NotImplementedError; + exc = PyExc_NotImplementedError; if (igraph_errno == IGRAPH_ENOMEM) - exc = PyExc_MemoryError; + exc = PyExc_MemoryError; - snprintf(buf, sizeof(buf), "Error at %s:%i: %s, %s", file, line, reason, - igraph_strerror(igraph_errno)); + /* add a full stop at the end of the error message for nicer formatting */ + if (reason && strlen(reason) > 1) { + char last_char = reason[strlen(reason) - 1]; + if (last_char != '.' && last_char != '?' && last_char != '!') { + punctuation = "."; + } + } + + snprintf( + buf, sizeof(buf), "Error at %s:%i: %s%s -- %s", file, line, reason, + punctuation, igraph_strerror(igraph_errno) + ); IGRAPH_FINALLY_FREE(); /* make sure we are not masking already thrown exceptions */ From 01dc57b10a4a28f708d381db5be27b81af3b87df Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 5 Mar 2021 13:31:48 +0100 Subject: [PATCH 0404/1892] fix: removed all mentions of 'long', which is not present in Python 3 any more, fixes #372 --- src/igraph/clustering.py | 4 ++-- src/igraph/statistics.py | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 7380e7e03..4217f3dce 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -1535,7 +1535,7 @@ def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): first = None if first is not None: # Okay. Is the first element of the list a single number? - if isinstance(first, (int, long)): + if isinstance(first, int): # Yes. Seems like we have a list of cluster indices. # Assign color indices automatically. group_iter = ((group, color) for color, group in enumerate(mark_groups)) @@ -1552,7 +1552,7 @@ def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): def cluster_index_resolver(): for group, color in group_iter: - if isinstance(group, (int, long)): + if isinstance(group, int): group = clustering[group] yield group, color diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 85955d9f2..951db6d9c 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -474,9 +474,6 @@ def __float__(self): def __int__(self): return int(self._mean) - def __long__(self): - return int(self._mean) - def __complex__(self): return complex(self._mean) From c9b2ec21b0629ebabdf2739030464852f2689111 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 01:34:31 +0100 Subject: [PATCH 0405/1892] doc: documentation improvements; using __text_signature__ for C functions, started migrating to PyDoctor --- MANIFEST.in | 3 - scripts/epydoc.cfg | 9 - scripts/mkdoc.sh | 47 ++- src/_igraph/edgeobject.c | 10 +- src/_igraph/edgeseqobject.c | 12 +- src/_igraph/graphobject.c | 549 +++++++++++++++++----------------- src/_igraph/igraphmodule.c | 32 +- src/_igraph/vertexobject.c | 6 +- src/_igraph/vertexseqobject.c | 11 +- src/igraph/__init__.py | 5 +- src/igraph/clustering.py | 10 - 11 files changed, 333 insertions(+), 361 deletions(-) delete mode 100644 scripts/epydoc.cfg diff --git a/MANIFEST.in b/MANIFEST.in index 9bfa4b090..bbfa86415 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,10 +1,7 @@ -include setup.cfg include src/_igraph/*.h include MANIFEST.in include COPYING include scripts/mkdoc.sh -include scripts/epydoc-patched -include scripts/epydoc.cfg include tests/*.py graft vendor/source/igraph diff --git a/scripts/epydoc.cfg b/scripts/epydoc.cfg deleted file mode 100644 index a474af3af..000000000 --- a/scripts/epydoc.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[epydoc] - -name: igraph library -url: http://igraph.org - -modules: igraph, igraph.app, igraph.app.shell, igraph.statistics -exclude: igraph.compat, igraph.formula, igraph.test, igraph.vendor - -imports: yes diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index ccbbd6bbf..214027c4d 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Creates documentation for igraph's Python interface using epydoc +# Creates the API documentation for igraph's Python interface using PyDoctor # # Usage: ./mkdoc.sh [--sync] [directory] @@ -9,41 +9,38 @@ SCRIPTS_FOLDER=`dirname $0` cd ${SCRIPTS_FOLDER}/.. ROOT_FOLDER=`pwd` DOC_API_FOLDER=${ROOT_FOLDER}/doc/api -CONFIG=${ROOT_FOLDER}/scripts/epydoc.cfg cd ${ROOT_FOLDER} -mkdir -p ${DOC_API_FOLDER}/pdf -mkdir -p ${DOC_API_FOLDER}/html -EPYDOC="${ROOT_FOLDER}/scripts/epydoc-patched" -python -m epydoc.__init__ -if [ $? -gt 0 ]; then - echo "Epydoc not installed, exiting..." +if [ ! -d ".venv" ]; then + # Create a virtual environment for pydoctor + python3 -m venv .venv + .venv/bin/pip install pydoctor +fi + +PYDOCTOR=.venv/bin/pydoctor +if [ ! -f ${PYDOCTOR} ]; then + echo "PyDoctor not installed in the virtualenv of the project, exiting..." exit 1 fi PWD=`pwd` -echo "Checking symlinked _igraph.so in ${ROOT_FOLDER}/src/igraph..." -if [ ! -e ${ROOT_FOLDER}/src/igraph/_igraph.so -o ! -L ${ROOT_FOLDER}/src/igraph/_igraph.so ]; then - rm -f ${ROOT_FOLDER}/src/igraph/_igraph.so - cd ${ROOT_FOLDER}/src/igraph - ln -s ../../build/lib*/igraph/_igraph.so . - cd ${ROOT_FOLDER} -fi - echo "Removing existing documentation..." -rm -rf html +rm -rf "${DOC_API_FOLDER}/html" "${DOC_API_FOLDER}/pdf" -echo "Generating HTML documentation..." -PYTHONPATH=src ${EPYDOC} --html -v -o ${DOC_API_FOLDER}/html --config ${CONFIG} +IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` -PDF=0 -which latex >/dev/null && PDF=1 +echo "Generating HTML documentation..." +"$PYDOCTOR" \ + --project-name "python-igraph" \ + --project-url "https://igraph.org/python" \ + --introspect-c-modules \ + --make-html \ + --html-output "${DOC_API_FOLDER}/html" \ + ${IGRAPHDIR} -if [ $PDF -eq 1 ]; then - echo "Generating PDF documentation..." - PYTHONPATH=src ${EPYDOC} --pdf -v -o ${DOC_API_FOLDER}/pdf --config ${CONFIG} -fi +# PDF not supported by PyDoctor cd "$PWD" + diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index d438e9aa7..253f169b5 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -631,17 +631,17 @@ GRAPH_PROXY_METHOD(is_mutual, "is_mutual"); PyMethodDef igraphmodule_Edge_methods[] = { {"attributes", (PyCFunction)igraphmodule_Edge_attributes, METH_NOARGS, - "attributes() -> dict\n\n" + "attributes() -> dict\n--\n\n" "Returns a dict of attribute names and values for the edge\n" }, {"attribute_names", (PyCFunction)igraphmodule_Edge_attribute_names, - METH_NOARGS, - "attribute_names() -> list\n\n" - "Returns the list of edge attribute names\n" + METH_NOARGS, + "attribute_names() -> list\n--\n\n" + "Returns the list of edge attribute names\n" }, {"update_attributes", (PyCFunction)igraphmodule_Edge_update_attributes, METH_VARARGS | METH_KEYWORDS, - "update_attributes(E, **F) -> None\n\n" + "update_attributes(E, **F) -> None\n--\n\n" "Updates the attributes of the edge from dict/iterable E and F.\n\n" "If E has a C{keys()} method, it does: C{for k in E: self[k] = E[k]}.\n" "If E lacks a C{keys()} method, it does: C{for (k, v) in E: self[k] = v}.\n" diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index ee202203e..fc7af6629 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -797,36 +797,36 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyMethodDef igraphmodule_EdgeSeq_methods[] = { {"attribute_names", (PyCFunction)igraphmodule_EdgeSeq_attribute_names, METH_NOARGS, - "attribute_names() -> list\n\n" + "attribute_names() -> list\n--\n\n" "Returns the attribute name list of the graph's edges\n" }, {"find", (PyCFunction)igraphmodule_EdgeSeq_find, METH_VARARGS, - "find(condition) -> Edge\n\n" + "find(condition) -> Edge\n--\n\n" "For internal use only.\n" }, {"get_attribute_values", (PyCFunction)igraphmodule_EdgeSeq_get_attribute_values, METH_O, - "get_attribute_values(attrname) -> list\n\n" + "get_attribute_values(attrname) -> list\n--\n\n" "Returns the value of a given edge attribute for all edges.\n\n" "@param attrname: the name of the attribute\n" }, {"is_all", (PyCFunction)igraphmodule_EdgeSeq_is_all, METH_NOARGS, - "is_all() -> bool\n\n" + "is_all() -> bool\n--\n\n" "Returns whether the edge sequence contains all the edges exactly once, in\n" "the order of their edge IDs.\n\n" "This is used for optimizations in some of the edge selector routines.\n" }, {"set_attribute_values", (PyCFunction)igraphmodule_EdgeSeq_set_attribute_values, METH_VARARGS | METH_KEYWORDS, - "set_attribute_values(attrname, values) -> list\n" + "set_attribute_values(attrname, values) -> list\n--\n\n" "Sets the value of a given edge attribute for all vertices\n" "@param attrname: the name of the attribute\n" "@param values: the new attribute values in a list\n" }, {"select", (PyCFunction)igraphmodule_EdgeSeq_select, METH_VARARGS, - "select(...) -> VertexSeq\n\n" + "select(...) -> VertexSeq\n--\n\n" "For internal use only.\n" }, {NULL} diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 06dab05ac..e979b394a 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -280,7 +280,7 @@ PyObject* igraphmodule_Graph_subclass_from_igraph_t( PyObject* kwds; if (!PyType_IsSubtype(type, &igraphmodule_GraphType)) { - PyErr_SetString(PyExc_TypeError, "igraph.GraphBase expected"); + PyErr_SetString(PyExc_TypeError, "igraph._igraph.GraphBase expected"); return 0; } @@ -11998,21 +11998,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_vcount {"vcount", (PyCFunction) igraphmodule_Graph_vcount, METH_NOARGS, - "vcount()\n\n" + "vcount() -> int\n--\n\n" "Counts the number of vertices.\n" "@return: the number of vertices in the graph.\n" "@rtype: integer"}, // interface to igraph_ecount {"ecount", (PyCFunction) igraphmodule_Graph_ecount, METH_NOARGS, - "ecount()\n\n" + "ecount() -> int\n--\n\n" "Counts the number of edges.\n" "@return: the number of edges in the graph.\n" "@rtype: integer"}, // interface to igraph_is_dag {"is_dag", (PyCFunction) igraphmodule_Graph_is_dag, METH_NOARGS, - "is_dag()\n\n" + "is_dag() -> bool\n--\n\n" "Checks whether the graph is a DAG (directed acyclic graph).\n\n" "A DAG is a directed graph with no directed cycles.\n\n" "@return: C{True} if it is a DAG, C{False} otherwise.\n" @@ -12021,7 +12021,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_is_directed {"is_directed", (PyCFunction) igraphmodule_Graph_is_directed, METH_NOARGS, - "is_directed()\n\n" + "is_directed() -> bool\n--\n\n" "Checks whether the graph is directed.\n" "@return: C{True} if it is directed, C{False} otherwise.\n" "@rtype: boolean"}, @@ -12029,7 +12029,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_is_simple {"is_simple", (PyCFunction) igraphmodule_Graph_is_simple, METH_NOARGS, - "is_simple()\n\n" + "is_simple() -> bool\n--\n\n" "Checks whether the graph is simple (no loop or multiple edges).\n\n" "@return: C{True} if it is simple, C{False} otherwise.\n" "@rtype: boolean"}, @@ -12037,14 +12037,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_add_vertices */ {"add_vertices", (PyCFunction) igraphmodule_Graph_add_vertices, METH_VARARGS, - "add_vertices(n)\n\n" + "add_vertices(n: int) -> None\n--\n\n" "Adds vertices to the graph.\n\n" "@param n: the number of vertices to be added\n"}, /* interface to igraph_delete_vertices */ {"delete_vertices", (PyCFunction) igraphmodule_Graph_delete_vertices, METH_VARARGS, - "delete_vertices(vs)\n\n" + "delete_vertices(vs) -> None\n--\n\n" "Deletes vertices and all its edges from the graph.\n\n" "@param vs: a single vertex ID or the list of vertex IDs\n" " to be deleted. No argument deletes all vertices.\n"}, @@ -12052,7 +12052,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_add_edges */ {"add_edges", (PyCFunction) igraphmodule_Graph_add_edges, METH_VARARGS, - "add_edges(es)\n\n" + "add_edges(es) -> None\n--\n\n" "Adds edges to the graph.\n\n" "@param es: the list of edges to be added. Every edge is\n" " represented with a tuple, containing the vertex IDs of the\n" @@ -12061,7 +12061,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_delete_edges */ {"delete_edges", (PyCFunction) igraphmodule_Graph_delete_edges, METH_VARARGS | METH_KEYWORDS, - "delete_edges(es)\n\n" + "delete_edges(es) -> None\n--\n\n" "Removes edges from the graph.\n\n" "All vertices will be kept, even if they lose all their edges.\n" "Nonexistent edges will be silently ignored.\n\n" @@ -12072,7 +12072,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_degree */ {"degree", (PyCFunction) igraphmodule_Graph_degree, METH_VARARGS | METH_KEYWORDS, - "degree(vertices, mode=ALL, loops=True)\n\n" + "degree(vertices, mode=ALL, loops=True)\n--\n\n" "Returns some vertex degrees from the graph.\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the degree of the given vertices (in the\n" @@ -12087,7 +12087,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_strength */ {"strength", (PyCFunction) igraphmodule_Graph_strength, METH_VARARGS | METH_KEYWORDS, - "strength(vertices, mode=ALL, loops=True, weights=None)\n\n" + "strength(vertices, mode=ALL, loops=True, weights=None)\n--\n\n" "Returns the strength (weighted degree) of some vertices from the graph\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the strength (that is, the sum of the weights\n" @@ -12108,7 +12108,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_loop */ {"is_loop", (PyCFunction) igraphmodule_Graph_is_loop, METH_VARARGS | METH_KEYWORDS, - "is_loop(edges=None)\n\n" + "is_loop(edges=None) -> List[bool]\n--\n\n" "Checks whether a specific set of edges contain loop edges\n\n" "@param edges: edge indices which we want to check. If C{None}, all\n" " edges are checked.\n" @@ -12117,7 +12117,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_multiple */ {"is_multiple", (PyCFunction) igraphmodule_Graph_is_multiple, METH_VARARGS | METH_KEYWORDS, - "is_multiple(edges=None)\n\n" + "is_multiple(edges=None) -> List[bool]\n--\n\n" "Checks whether an edge is a multiple edge.\n\n" "Also works for a set of edges -- in this case, every edge is checked\n" "one by one. Note that if there are multiple edges going between a\n" @@ -12132,7 +12132,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_has_multiple */ {"has_multiple", (PyCFunction) igraphmodule_Graph_has_multiple, METH_NOARGS, - "has_multiple()\n\n" + "has_multiple() -> bool\n--\n\n" "Checks whether the graph has multiple edges.\n\n" "@return: C{True} if the graph has at least one multiple edge,\n" " C{False} otherwise.\n" @@ -12141,7 +12141,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_mutual */ {"is_mutual", (PyCFunction) igraphmodule_Graph_is_mutual, METH_VARARGS | METH_KEYWORDS, - "is_mutual(edges=None)\n\n" + "is_mutual(edges=None) -> Lis[bool]\n--\n\n" "Checks whether an edge has an opposite pair.\n\n" "Also works for a set of edges -- in this case, every edge is checked\n" "one by one. The result will be a list of booleans (or a single boolean\n" @@ -12160,7 +12160,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_count_multiple */ {"count_multiple", (PyCFunction) igraphmodule_Graph_count_multiple, METH_VARARGS | METH_KEYWORDS, - "count_multiple(edges=None)\n\n" + "count_multiple(edges=None) -> List[int]\n--\n\n" "Counts the multiplicities of the given edges.\n\n" "@param edges: edge indices for which we want to count their\n" " multiplicity. If C{None}, all edges are counted.\n" @@ -12169,7 +12169,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_neighbors */ {"neighbors", (PyCFunction) igraphmodule_Graph_neighbors, METH_VARARGS | METH_KEYWORDS, - "neighbors(vertex, mode=ALL)\n\n" + "neighbors(vertex, mode=ALL)\n--\n\n" "Returns adjacent vertices to a given vertex.\n\n" "@param vertex: a vertex ID\n" "@param mode: whether to return only successors (L{OUT}),\n" @@ -12178,20 +12178,20 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"successors", (PyCFunction) igraphmodule_Graph_successors, METH_VARARGS | METH_KEYWORDS, - "successors(vertex)\n\n" + "successors(vertex)\n--\n\n" "Returns the successors of a given vertex.\n\n" "Equivalent to calling the L{Graph.neighbors} method with type=L{OUT}."}, {"predecessors", (PyCFunction) igraphmodule_Graph_predecessors, METH_VARARGS | METH_KEYWORDS, - "predecessors(vertex)\n\n" + "predecessors(vertex)\n--\n\n" "Returns the predecessors of a given vertex.\n\n" "Equivalent to calling the L{Graph.neighbors} method with type=L{IN}."}, /* interface to igraph_get_eid */ {"get_eid", (PyCFunction) igraphmodule_Graph_get_eid, METH_VARARGS | METH_KEYWORDS, - "get_eid(v1, v2, directed=True, error=True)\n\n" + "get_eid(v1, v2, directed=True, error=True) -> int\n--\n\n" "Returns the edge ID of an arbitrary edge between vertices v1 and v2\n\n" "@param v1: the ID or name of the first vertex\n" "@param v2: the ID or name of the second vertex\n" @@ -12206,7 +12206,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_eids */ {"get_eids", (PyCFunction) igraphmodule_Graph_get_eids, METH_VARARGS | METH_KEYWORDS, - "get_eids(pairs=None, path=None, directed=True, error=True)\n\n" + "get_eids(pairs=None, path=None, directed=True, error=True) -> List[int]\n--\n\n" "Returns the edge IDs of some edges between some vertices.\n\n" "This method can operate in two different modes, depending on which\n" "of the keyword arguments C{pairs} and C{path} are given.\n\n" @@ -12234,7 +12234,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_incident */ {"incident", (PyCFunction) igraphmodule_Graph_incident, METH_VARARGS | METH_KEYWORDS, - "incident(vertex, mode=OUT)\n\n" + "incident(vertex, mode=OUT)\n--\n\n" "Returns the edges a given vertex is incident on.\n\n" "@param vertex: a vertex ID\n" "@param mode: whether to return only successors (L{OUT}),\n" @@ -12248,7 +12248,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_adjacency */ {"Adjacency", (PyCFunction) igraphmodule_Graph_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Adjacency(matrix, mode=ADJ_DIRECTED)\n\n" + "Adjacency(matrix, mode=ADJ_DIRECTED)\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" @@ -12272,7 +12272,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"Asymmetric_Preference", (PyCFunction) igraphmodule_Graph_Asymmetric_Preference, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Asymmetric_Preference(n, type_dist_matrix, pref_matrix, attribute=None, loops=False)\n\n" + "Asymmetric_Preference(n, type_dist_matrix, pref_matrix, attribute=None, loops=False)\n--\n\n" "Generates a graph based on asymmetric vertex types and connection probabilities.\n\n" "This is the asymmetric variant of L{Graph.Preference}.\n" "A given number of vertices are generated. Every vertex is assigned to an\n" @@ -12293,7 +12293,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_atlas {"Atlas", (PyCFunction) igraphmodule_Graph_Atlas, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Atlas(idx)\n\n" + "Atlas(idx: int)\n--\n\n" "Generates a graph from the Graph Atlas.\n\n" "@param idx: The index of the graph to be generated.\n" " Indices start from zero, graphs are listed:\n\n" @@ -12311,7 +12311,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"Barabasi", (PyCFunction) igraphmodule_Graph_Barabasi, METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Barabasi(n, m, outpref=False, directed=False, power=1,\n" - " zero_appeal=1, implementation=\"psumtree\", start_from=None)\n\n" + " zero_appeal=1, implementation=\"psumtree\", start_from=None)\n--\n\n" "Generates a graph based on the Barabasi-Albert model.\n\n" "@param n: the number of vertices\n" "@param m: either the number of outgoing edges generated for\n" @@ -12353,14 +12353,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_create_bipartite */ {"_Bipartite", (PyCFunction) igraphmodule_Graph_Bipartite, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Bipartite(types, edges, directed=False)\n\n" + "_Bipartite(types, edges, directed=False)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.Bipartite()\n\n"}, /* interface to igraph_de_bruijn */ {"De_Bruijn", (PyCFunction) igraphmodule_Graph_De_Bruijn, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "De_Bruijn(m, n)\n\n" + "De_Bruijn(m, n)\n--\n\n" "Generates a de Bruijn graph with parameters (m, n)\n\n" "A de Bruijn graph represents relationships between strings. An alphabet\n" "of M{m} letters are used and strings of length M{n} are considered.\n" @@ -12377,7 +12377,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_establishment_game {"Establishment", (PyCFunction) igraphmodule_Graph_Establishment, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Establishment(n, k, type_dist, pref_matrix, directed=False)\n\n" + "Establishment(n, k, type_dist, pref_matrix, directed=False)\n--\n\n" "Generates a graph based on a simple growing model with vertex types.\n\n" "A single vertex is added at each time step. This new vertex tries to\n" "connect to k vertices in the graph. The probability that such a\n" @@ -12393,7 +12393,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_erdos_renyi_game {"Erdos_Renyi", (PyCFunction) igraphmodule_Graph_Erdos_Renyi, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Erdos_Renyi(n, p, m, directed=False, loops=False)\n\n" + "Erdos_Renyi(n, p, m, directed=False, loops=False)\n--\n\n" "Generates a graph based on the Erdos-Renyi model.\n\n" "@param n: the number of vertices.\n" "@param p: the probability of edges. If given, C{m} must be missing.\n" @@ -12404,7 +12404,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_famous */ {"Famous", (PyCFunction) igraphmodule_Graph_Famous, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Famous(name)\n\n" + "Famous(name)\n--\n\n" "Generates a famous graph based on its name.\n\n" "Several famous graphs are known to C{igraph} including (but not limited to)\n" "the Chvatal graph, the Petersen graph or the Tutte graph. This method\n" @@ -12417,7 +12417,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_forest_fire_game */ {"Forest_Fire", (PyCFunction) igraphmodule_Graph_Forest_Fire, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Forest_Fire(n, fw_prob, bw_factor=0.0, ambs=1, directed=False)\n\n" + "Forest_Fire(n, fw_prob, bw_factor=0.0, ambs=1, directed=False)\n--\n\n" "Generates a graph based on the forest fire model\n\n" "The forest fire model is a growing graph model. In every time step, a new\n" "vertex is added to the graph. The new vertex chooses an ambassador (or\n" @@ -12437,7 +12437,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_full_citation */ {"Full_Citation", (PyCFunction) igraphmodule_Graph_Full_Citation, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Full_Citation(n, directed=False)\n\n" + "Full_Citation(n, directed=False)\n--\n\n" "Generates a full citation graph\n\n" "A full citation graph is a graph where the vertices are indexed from 0 to\n" "M{n-1} and vertex M{i} has a directed edge towards all vertices with an\n" @@ -12448,7 +12448,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_full */ {"Full", (PyCFunction) igraphmodule_Graph_Full, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Full(n, directed=False, loops=False)\n\n" + "Full(n, directed=False, loops=False)\n--\n\n" "Generates a full graph (directed or undirected, with or without loops).\n\n" "@param n: the number of vertices.\n" "@param directed: whether to generate a directed graph.\n" @@ -12457,21 +12457,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_full_bipartite */ {"_Full_Bipartite", (PyCFunction) igraphmodule_Graph_Full_Bipartite, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Full_Bipartite(n1, n2, directed=False, loops=False)\n\n" + "_Full_Bipartite(n1, n2, directed=False, loops=False)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.Full_Bipartite()\n\n"}, /* interface to igraph_grg_game */ {"_GRG", (PyCFunction) igraphmodule_Graph_GRG, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_GRG(n, radius, torus=False)\n\n" + "_GRG(n, radius, torus=False)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.GRG()\n\n"}, /* interface to igraph_growing_random_game */ {"Growing_Random", (PyCFunction) igraphmodule_Graph_Growing_Random, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Growing_Random(n, m, directed=False, citation=False)\n\n" + "Growing_Random(n, m, directed=False, citation=False)\n--\n\n" "Generates a growing random graph.\n\n" "@param n: The number of vertices in the graph\n" "@param m: The number of edges to add in each step (after adding a new vertex)\n" @@ -12482,14 +12482,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_incidence */ {"_Incidence", (PyCFunction) igraphmodule_Graph_Incidence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Incidence(matrix, directed=False, mode=ALL, multiple=False)\n\n" + "_Incidence(matrix, directed=False, mode=ALL, multiple=False)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.Incidence()\n\n"}, /* interface to igraph_kautz */ {"Kautz", (PyCFunction) igraphmodule_Graph_Kautz, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Kautz(m, n)\n\n" + "Kautz(m, n)\n--\n\n" "Generates a Kautz graph with parameters (m, n)\n\n" "A Kautz graph is a labeled graph, vertices are labeled by strings\n" "of length M{n+1} above an alphabet with M{m+1} letters, with\n" @@ -12505,7 +12505,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_k_regular */ {"K_Regular", (PyCFunction) igraphmodule_Graph_K_Regular, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "K_Regular(n, k, directed=False, multiple=False)\n\n" + "K_Regular(n, k, directed=False, multiple=False)\n--\n\n" "Generates a k-regular random graph\n\n" "A k-regular random graph is a random graph where each vertex has degree k.\n" "If the graph is directed, both the in-degree and the out-degree of each vertex\n" @@ -12520,7 +12520,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_preference_game */ {"Preference", (PyCFunction) igraphmodule_Graph_Preference, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Preference(n, type_dist, pref_matrix, attribute=None, directed=False, loops=False)\n\n" + "Preference(n, type_dist, pref_matrix, attribute=None, directed=False, loops=False)\n--\n\n" "Generates a graph based on vertex types and connection probabilities.\n\n" "This is practically the nongrowing variant of L{Graph.Establishment}.\n" "A given number of vertices are generated. Every vertex is assigned to a\n" @@ -12539,14 +12539,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_bipartite_game */ {"_Random_Bipartite", (PyCFunction) igraphmodule_Graph_Random_Bipartite, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Random_Bipartite(n1, n2, p=None, m=None, directed=False, neimode=\"all\")\n\n" + "_Random_Bipartite(n1, n2, p=None, m=None, directed=False, neimode=\"all\")\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.Random_Bipartite()\n\n"}, /* interface to igraph_recent_degree_game */ {"Recent_Degree", (PyCFunction) igraphmodule_Graph_Recent_Degree, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Recent_Degree(n, m, window, outpref=False, directed=False, power=1)\n\n" + "Recent_Degree(n, m, window, outpref=False, directed=False, power=1)\n--\n\n" "Generates a graph based on a stochastic model where the probability\n" "of an edge gaining a new node is proportional to the edges gained in\n" "a given time window.\n\n" @@ -12567,7 +12567,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_sbm_game */ {"SBM", (PyCFunction) igraphmodule_Graph_SBM, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "SBM(n, pref_matrix, block_sizes, directed=False, loops=False)\n\n" + "SBM(n, pref_matrix, block_sizes, directed=False, loops=False)\n--\n\n" "Generates a graph based on a stochastic blockmodel.\n\n" "A given number of vertices are generated. Every vertex is assigned to a\n" "vertex type according to the given block sizes. Vertices of the same\n" @@ -12586,7 +12586,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_star {"Star", (PyCFunction) igraphmodule_Graph_Star, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Star(n, mode=\"undirected\", center=0)\n\n" + "Star(n, mode=\"undirected\", center=0)\n--\n\n" "Generates a star graph.\n\n" "@param n: the number of vertices in the graph\n" "@param mode: Gives the type of the star graph to create. Should be\n" @@ -12596,7 +12596,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_lattice {"Lattice", (PyCFunction) igraphmodule_Graph_Lattice, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Lattice(dim, nei=1, directed=False, mutual=True, circular=True)\n\n" + "Lattice(dim, nei=1, directed=False, mutual=True, circular=True)\n--\n\n" "Generates a regular lattice.\n\n" "@param dim: list with the dimensions of the lattice\n" "@param nei: value giving the distance (number of steps) within which\n" @@ -12607,25 +12607,25 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param circular: whether the generated lattice is periodic.\n"}, /* interface to igraph_lcf */ - {"LCF", (PyCFunction) igraphmodule_Graph_LCF, - METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "LCF(n, shifts, repeats)\n\n" - "Generates a graph from LCF notation.\n\n" - "LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation\n" - "for 3-regular Hamiltonian graphs. It consists of three parameters,\n" - "the number of vertices in the graph, a list of shifts giving\n" - "additional edges to a cycle backbone and another integer giving how\n" - "many times the shifts should be performed. See\n" - "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" - "@param n: the number of vertices\n" - "@param shifts: the shifts in a list or tuple\n" - "@param repeats: the number of repeats\n" - }, + {"LCF", (PyCFunction) igraphmodule_Graph_LCF, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "LCF(n, shifts, repeats)\n--\n\n" + "Generates a graph from LCF notation.\n\n" + "LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation\n" + "for 3-regular Hamiltonian graphs. It consists of three parameters,\n" + "the number of vertices in the graph, a list of shifts giving\n" + "additional edges to a cycle backbone and another integer giving how\n" + "many times the shifts should be performed. See\n" + "U{http://mathworld.wolfram.com/LCFNotation.html} for details.\n\n" + "@param n: the number of vertices\n" + "@param shifts: the shifts in a list or tuple\n" + "@param repeats: the number of repeats\n" + }, // interface to igraph_ring {"Ring", (PyCFunction) igraphmodule_Graph_Ring, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Ring(n, directed=False, mutual=False, circular=True)\n\n" + "Ring(n, directed=False, mutual=False, circular=True)\n--\n\n" "Generates a ring graph.\n\n" "@param n: the number of vertices in the ring\n" "@param directed: whether to create a directed ring.\n" @@ -12635,7 +12635,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_static_fitness_game */ {"Static_Fitness", (PyCFunction) igraphmodule_Graph_Static_Fitness, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Static_Fitness(m, fitness_out, fitness_in=None, loops=False, multiple=False)\n\n" + "Static_Fitness(m, fitness_out, fitness_in=None, loops=False, multiple=False)\n--\n\n" "Generates a non-growing graph with edge probabilities proportional to node\n" "fitnesses.\n\n" "The algorithm randomly selects vertex pairs and connects them until the given\n" @@ -12659,8 +12659,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_static_power_law_game */ {"Static_Power_Law", (PyCFunction) igraphmodule_Graph_Static_Power_Law, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Static_Power_Law(n, m, exponent_out, exponent_in=-1, loops=False,\n" - " multiple=False, finite_size_correction=True)\n\n" + "Static_Power_Law(n, m, exponent_out, exponent_in=-1, loops=False, " + "multiple=False, finite_size_correction=True)\n--\n\n" "Generates a non-growing graph with prescribed power-law degree distributions.\n\n" "@param n: the number of vertices in the graph\n" "@param m: the number of edges in the graph\n" @@ -12691,7 +12691,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_tree {"Tree", (PyCFunction) igraphmodule_Graph_Tree, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Tree(n, children, type=TREE_UNDIRECTED)\n\n" + "Tree(n, children, type=TREE_UNDIRECTED)\n--\n\n" "Generates a tree in which almost all vertices have the same number of children.\n\n" "@param n: the number of vertices in the graph\n" "@param children: the number of children of a vertex in the graph\n" @@ -12702,7 +12702,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_degree_sequence_game */ {"Degree_Sequence", (PyCFunction) igraphmodule_Graph_Degree_Sequence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Degree_Sequence(out, in=None, method=\"simple\")\n\n" + "Degree_Sequence(out, in=None, method=\"simple\")\n--\n\n" "Generates a graph with a given degree sequence.\n\n" "@param out: the out-degree sequence for a directed graph. If the\n" " in-degree sequence is omitted, the generated graph\n" @@ -12736,7 +12736,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_isoclass_create */ {"Isoclass", (PyCFunction) igraphmodule_Graph_Isoclass, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Isoclass(n, class, directed=False)\n\n" + "Isoclass(n, class, directed=False)\n--\n\n" "Generates a graph with a given isomorphism class.\n\n" "@param n: the number of vertices in the graph (3 or 4)\n" "@param class: the isomorphism class\n" @@ -12745,7 +12745,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_watts_strogatz_game */ {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Watts_Strogatz(dim, size, nei, p, loops=False, multiple=False)\n\n" + "Watts_Strogatz(dim, size, nei, p, loops=False, multiple=False)\n--\n\n" "@param dim: the dimension of the lattice\n" "@param size: the size of the lattice along all dimensions\n" "@param nei: value giving the distance (number of steps) within which\n" @@ -12762,7 +12762,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_weighted_adjacency */ {"Weighted_Adjacency", (PyCFunction) igraphmodule_Graph_Weighted_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Weighted_Adjacency(matrix, mode=ADJ_DIRECTED, attr=\"weight\", loops=True)\n\n" + "Weighted_Adjacency(matrix, mode=ADJ_DIRECTED, attr=\"weight\", loops=True)\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" @@ -12793,7 +12793,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_are_connected {"are_connected", (PyCFunction) igraphmodule_Graph_are_connected, METH_VARARGS | METH_KEYWORDS, - "are_connected(v1, v2)\n\n" + "are_connected(v1, v2) -> bool\n--\n\n" "Decides whether two given vertices are directly connected.\n\n" "@param v1: the ID or name of the first vertex\n" "@param v2: the ID or name of the second vertex\n" @@ -12803,7 +12803,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_articulation_points */ {"articulation_points", (PyCFunction)igraphmodule_Graph_articulation_points, METH_NOARGS, - "articulation_points()\n\n" + "articulation_points()\n--\n\n" "Returns the list of articulation points in the graph.\n\n" "A vertex is an articulation point if its removal increases the number of\n" "connected components in the graph.\n" @@ -12812,7 +12812,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_assortativity */ {"assortativity", (PyCFunction)igraphmodule_Graph_assortativity, METH_VARARGS | METH_KEYWORDS, - "assortativity(types1, types2=None, directed=True)\n\n" + "assortativity(types1, types2=None, directed=True)\n--\n\n" "Returns the assortativity of the graph based on numeric properties\n" "of the vertices.\n\n" "This coefficient is basically the correlation between the actual\n" @@ -12842,7 +12842,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_assortativity_degree */ {"assortativity_degree", (PyCFunction)igraphmodule_Graph_assortativity_degree, METH_VARARGS | METH_KEYWORDS, - "assortativity_degree(directed=True)\n\n" + "assortativity_degree(directed=True)\n--\n\n" "Returns the assortativity of a graph based on vertex degrees.\n\n" "See L{assortativity()} for the details. L{assortativity_degree()} simply\n" "calls L{assortativity()} with the vertex degrees as types.\n\n" @@ -12855,7 +12855,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_assortativity_nominal */ {"assortativity_nominal", (PyCFunction)igraphmodule_Graph_assortativity_nominal, METH_VARARGS | METH_KEYWORDS, - "assortativity_nominal(types, directed=True)\n\n" + "assortativity_nominal(types, directed=True)\n--\n\n" "Returns the assortativity of the graph based on vertex categories.\n\n" "Assuming that the vertices belong to different categories, this\n" "function calculates the assortativity coefficient, which specifies\n" @@ -12878,7 +12878,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"average_path_length", (PyCFunction) igraphmodule_Graph_average_path_length, METH_VARARGS | METH_KEYWORDS, - "average_path_length(directed=True, unconn=True)\n\n" + "average_path_length(directed=True, unconn=True)\n--\n\n" "Calculates the average path length in a graph.\n\n" "@param directed: whether to consider directed paths in case of a\n" " directed graph. Ignored for undirected graphs.\n" @@ -12891,7 +12891,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_authority_score */ {"authority_score", (PyCFunction)igraphmodule_Graph_authority_score, METH_VARARGS | METH_KEYWORDS, - "authority_score(weights=None, scale=True, arpack_options=None, return_eigenvalue=False)\n\n" + "authority_score(weights=None, scale=True, arpack_options=None, return_eigenvalue=False)\n--\n\n" "Calculates Kleinberg's authority score for the vertices of the graph\n\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" @@ -12909,7 +12909,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_betweenness[_estimate] */ {"betweenness", (PyCFunction) igraphmodule_Graph_betweenness, METH_VARARGS | METH_KEYWORDS, - "betweenness(vertices=None, directed=True, cutoff=None, weights=None)\n\n" + "betweenness(vertices=None, directed=True, cutoff=None, weights=None)\n--\n\n" "Calculates or estimates the betweenness of vertices in a graph.\n\n" "Keyword arguments:\n" "@param vertices: the vertices for which the betweennesses must be returned.\n" @@ -12926,7 +12926,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to biconnected_components */ {"biconnected_components", (PyCFunction) igraphmodule_Graph_biconnected_components, METH_VARARGS | METH_KEYWORDS, - "biconnected_components(return_articulation_points=True)\n\n" + "biconnected_components(return_articulation_points=True)\n--\n\n" "Calculates the biconnected components of the graph.\n\n" "Components containing a single vertex only are not considered as being\n" "biconnected.\n\n" @@ -12940,21 +12940,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_bipartite_projection */ {"bipartite_projection", (PyCFunction) igraphmodule_Graph_bipartite_projection, METH_VARARGS | METH_KEYWORDS, - "bipartite_projection(types, multiplicity=True, probe1=-1, which=-1)\n\n" + "bipartite_projection(types, multiplicity=True, probe1=-1, which=-1)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.bipartite_projection()\n"}, /* interface to igraph_bipartite_projection_size */ {"bipartite_projection_size", (PyCFunction) igraphmodule_Graph_bipartite_projection_size, METH_VARARGS | METH_KEYWORDS, - "bipartite_projection_size(types)\n\n" + "bipartite_projection_size(types)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.bipartite_projection_size()\n"}, /* interface to igraph_bridges */ {"bridges", (PyCFunction)igraphmodule_Graph_bridges, METH_NOARGS, - "bridges()\n\n" + "bridges()\n--\n\n" "Returns the list of bridges in the graph.\n\n" "An edge is a bridge if its removal increases the number of (weakly) connected\n" "components in the graph.\n" @@ -12963,8 +12963,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_closeness */ {"closeness", (PyCFunction) igraphmodule_Graph_closeness, METH_VARARGS | METH_KEYWORDS, - "closeness(vertices=None, mode=ALL, cutoff=None, weights=None,\n" - " normalized=True)\n\n" + "closeness(vertices=None, mode=ALL, cutoff=None, weights=None, " + "normalized=True)\n--\n\n" "Calculates the closeness centralities of given vertices in a graph.\n\n" "The closeness centerality of a vertex measures how easily other\n" "vertices can be reached from it (or the other way: how easily it\n" @@ -12996,8 +12996,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_harmonic_centrality */ {"harmonic_centrality", (PyCFunction) igraphmodule_Graph_harmonic_centrality, METH_VARARGS | METH_KEYWORDS, - "harmonic_centrality(vertices=None, mode=ALL, cutoff=None, weights=None,\n" - " normalized=True)\n\n" + "harmonic_centrality(vertices=None, mode=ALL, cutoff=None, weights=None, " + "normalized=True)\n--\n\n" "Calculates the harmonic centralities of given vertices in a graph.\n\n" "The harmonic centerality of a vertex measures how easily other\n" "vertices can be reached from it (or the other way: how easily it\n" @@ -13024,7 +13024,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_clusters */ {"clusters", (PyCFunction) igraphmodule_Graph_clusters, METH_VARARGS | METH_KEYWORDS, - "clusters(mode=STRONG)\n\n" + "clusters(mode=STRONG)\n--\n\n" "Calculates the (strong or weak) clusters for a given graph.\n\n" "@attention: this function has a more convenient interface in class\n" " L{Graph} which wraps the result in a L{VertexClustering} object.\n" @@ -13034,7 +13034,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the component index for every node in the graph.\n"}, {"copy", (PyCFunction) igraphmodule_Graph_copy, METH_NOARGS, - "copy()\n\n" + "copy()\n--\n\n" "Creates a copy of the graph.\n\n" "Attributes are copied by reference; in other words, if you use\n" "mutable Python objects as attribute values, these objects will still\n" @@ -13043,7 +13043,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"decompose", (PyCFunction) igraphmodule_Graph_decompose, METH_VARARGS | METH_KEYWORDS, - "decompose(mode=STRONG, maxcompno=None, minelements=1)\n\n" + "decompose(mode=STRONG, maxcompno=None, minelements=1)\n--\n\n" "Decomposes the graph into subgraphs.\n\n" "@param mode: must be either STRONG or WEAK, depending on the\n" " clusters being sought.\n" @@ -13057,7 +13057,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_contract_vertices */ {"contract_vertices", (PyCFunction) igraphmodule_Graph_contract_vertices, METH_VARARGS | METH_KEYWORDS, - "contract_vertices(mapping, combine_attrs=None)\n\n" + "contract_vertices(mapping, combine_attrs=None)\n--\n\n" "Contracts some vertices in the graph, i.e. replaces groups of vertices\n" "with single vertices. Edges are not affected.\n\n" "@param mapping: numeric vector which gives the mapping between old and\n" @@ -13082,7 +13082,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_constraint */ {"constraint", (PyCFunction) igraphmodule_Graph_constraint, METH_VARARGS | METH_KEYWORDS, - "constraint(vertices=None, weights=None)\n\n" + "constraint(vertices=None, weights=None)\n--\n\n" "Calculates Burt's constraint scores for given vertices in a graph.\n\n" "Burt's constraint is higher if ego has less, or mutually stronger\n" "related (i.e. more redundant) contacts. Burt's measure of\n" @@ -13102,7 +13102,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_density */ {"density", (PyCFunction) igraphmodule_Graph_density, METH_VARARGS | METH_KEYWORDS, - "density(loops=False)\n\n" + "density(loops=False) -> float\n--\n\n" "Calculates the density of the graph.\n\n" "@param loops: whether to take loops into consideration. If C{True},\n" " the algorithm assumes that there might be some loops in the graph\n" @@ -13113,7 +13113,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interfaces to igraph_diameter */ {"diameter", (PyCFunction) igraphmodule_Graph_diameter, METH_VARARGS | METH_KEYWORDS, - "diameter(directed=True, unconn=True, weights=None)\n\n" + "diameter(directed=True, unconn=True, weights=None)\n--\n\n" "Calculates the diameter of the graph.\n\n" "@param directed: whether to consider directed paths.\n" "@param unconn: if C{True} and the graph is unconnected, the\n" @@ -13126,7 +13126,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the diameter"}, {"get_diameter", (PyCFunction) igraphmodule_Graph_get_diameter, METH_VARARGS | METH_KEYWORDS, - "get_diameter(directed=True, unconn=True, weights=None)\n\n" + "get_diameter(directed=True, unconn=True, weights=None)\n--\n\n" "Returns a path with the actual diameter of the graph.\n\n" "If there are many shortest paths with the length of the diameter,\n" "it returns the first one it founds.\n\n" @@ -13141,7 +13141,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the vertices in the path in order."}, {"farthest_points", (PyCFunction) igraphmodule_Graph_farthest_points, METH_VARARGS | METH_KEYWORDS, - "farthest_points(directed=True, unconn=True, weights=None)\n\n" + "farthest_points(directed=True, unconn=True, weights=None)\n--\n\n" "Returns two vertex IDs whose distance equals the actual diameter\n" "of the graph.\n\n" "If there are many shortest paths with the length of the diameter,\n" @@ -13161,7 +13161,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_diversity */ {"diversity", (PyCFunction) igraphmodule_Graph_diversity, METH_VARARGS | METH_KEYWORDS, - "diversity(vertices=None, weights=None)\n\n" + "diversity(vertices=None, weights=None)\n--\n\n" "Calculates the structural diversity index of the vertices.\n\n" "The structural diversity index of a vertex is simply the (normalized)\n" "Shannon entropy of the weights of the edges incident on the vertex.\n\n" @@ -13181,7 +13181,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_eccentricity */ {"eccentricity", (PyCFunction) igraphmodule_Graph_eccentricity, METH_VARARGS | METH_KEYWORDS, - "eccentricity(vertices=None, mode=ALL)\n\n" + "eccentricity(vertices=None, mode=ALL)\n--\n\n" "Calculates the eccentricities of given vertices in a graph.\n\n" "The eccentricity of a vertex is calculated by measuring the\n" "shortest distance from (or to) the vertex, to (or from) all other\n" @@ -13198,7 +13198,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_edge_betweenness[_estimate] */ {"edge_betweenness", (PyCFunction) igraphmodule_Graph_edge_betweenness, METH_VARARGS | METH_KEYWORDS, - "edge_betweenness(directed=True, cutoff=None, weights=None)\n\n" + "edge_betweenness(directed=True, cutoff=None, weights=None)\n--\n\n" "Calculates or estimates the edge betweennesses in a graph.\n\n" "@param directed: whether to consider directed paths.\n" "@param cutoff: if it is an integer, only paths less than or equal to this\n" @@ -13217,7 +13217,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_[st_]edge_connectivity */ {"edge_connectivity", (PyCFunction) igraphmodule_Graph_edge_connectivity, METH_VARARGS | METH_KEYWORDS, - "edge_connectivity(source=-1, target=-1, checks=True)\n\n" + "edge_connectivity(source=-1, target=-1, checks=True)\n--\n\n" "Calculates the edge connectivity of the graph or between some vertices.\n\n" "The edge connectivity between two given vertices is the number of edges\n" "that have to be removed in order to disconnect the two vertices into two\n" @@ -13243,7 +13243,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"eigenvector_centrality", (PyCFunction) igraphmodule_Graph_eigenvector_centrality, METH_VARARGS | METH_KEYWORDS, - "eigenvector_centrality(directed=True, scale=True, weights=None, return_eigenvalue=False, arpack_options=None)\n\n" + "eigenvector_centrality(directed=True, scale=True, weights=None, " + "return_eigenvalue=False, arpack_options=None)\n--\n\n" "Calculates the eigenvector centralities of the vertices in a graph.\n\n" "Eigenvector centrality is a measure of the importance of a node in a\n" "network. It assigns relative scores to all nodes in the network based\n" @@ -13278,7 +13279,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_feedback_arc_set */ {"feedback_arc_set", (PyCFunction) igraphmodule_Graph_feedback_arc_set, METH_VARARGS | METH_KEYWORDS, - "feedback_arc_set(weights=None, method=\"eades\")\n\n" + "feedback_arc_set(weights=None, method=\"eades\")\n--\n\n" "Calculates an approximately or exactly minimal feedback arc set.\n\n" "A feedback arc set is a set of edges whose removal makes the graph acyclic.\n" "Since this is always possible by removing all the edges, we are in general\n" @@ -13306,7 +13307,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_shortest_paths {"get_shortest_paths", (PyCFunction) igraphmodule_Graph_get_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "get_shortest_paths(v, to=None, weights=None, mode=OUT, output=\"vpath\")\n\n" + "get_shortest_paths(v, to=None, weights=None, mode=OUT, output=\"vpath\")\n--\n\n" "Calculates the shortest paths from/to a given node in a graph.\n\n" "@param v: the source/destination for the calculated paths\n" "@param to: a vertex selector describing the destination/source for\n" @@ -13331,7 +13332,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"get_all_shortest_paths", (PyCFunction) igraphmodule_Graph_get_all_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "get_all_shortest_paths(v, to=None, weights=None, mode=OUT)\n\n" + "get_all_shortest_paths(v, to=None, weights=None, mode=OUT)\n--\n\n" "Calculates all of the shortest paths from/to a given node in a graph.\n\n" "@param v: the source for the calculated paths\n" "@param to: a vertex selector describing the destination for\n" @@ -13352,7 +13353,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"_get_all_simple_paths", (PyCFunction) igraphmodule_Graph_get_all_simple_paths, METH_VARARGS | METH_KEYWORDS, - "_get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT)\n\n" + "_get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.get_all_simple_paths()\n\n" }, @@ -13360,7 +13361,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_girth */ {"girth", (PyCFunction)igraphmodule_Graph_girth, METH_VARARGS | METH_KEYWORDS, - "girth(return_shortest_circle=False)\n\n" + "girth(return_shortest_circle=False)\n--\n\n" "Returns the girth of the graph.\n\n" "The girth of a graph is the length of the shortest circle in it.\n\n" "@param return_shortest_circle: whether to return one of the shortest\n" @@ -13372,21 +13373,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_convergence_degree */ {"convergence_degree", (PyCFunction)igraphmodule_Graph_convergence_degree, METH_NOARGS, - "convergence_degree()\n\n" + "convergence_degree()\n--\n\n" "Undocumented (yet)." }, /* interface to igraph_convergence_field_size */ {"convergence_field_size", (PyCFunction)igraphmodule_Graph_convergence_field_size, METH_NOARGS, - "convergence_field_size()\n\n" + "convergence_field_size()\n--\n\n" "Undocumented (yet)." }, /* interface to igraph_hub_score */ {"hub_score", (PyCFunction)igraphmodule_Graph_hub_score, METH_VARARGS | METH_KEYWORDS, - "hub_score(weights=None, scale=True, arpack_options=None, return_eigenvalue=False)\n\n" + "hub_score(weights=None, scale=True, arpack_options=None, return_eigenvalue=False)\n--\n\n" "Calculates Kleinberg's hub score for the vertices of the graph\n\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" @@ -13404,7 +13405,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_induced_subgraph */ {"induced_subgraph", (PyCFunction) igraphmodule_Graph_induced_subgraph, METH_VARARGS | METH_KEYWORDS, - "induced_subgraph(vertices, implementation=\"auto\")\n\n" + "induced_subgraph(vertices, implementation=\"auto\")\n--\n\n" "Returns a subgraph spanned by the given vertices.\n\n" "@param vertices: a list containing the vertex IDs which\n" " should be included in the result.\n" @@ -13425,7 +13426,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_bipartite */ {"is_bipartite", (PyCFunction) igraphmodule_Graph_is_bipartite, METH_VARARGS | METH_KEYWORDS, - "is_bipartite(return_types=False)\n\n" + "is_bipartite(return_types=False) -> bool\n--\n\n" "Decides whether the graph is bipartite or not.\n\n" "Vertices of a bipartite graph can be partitioned into two groups A\n" "and B in a way that all edges go between the two groups.\n\n" @@ -13444,7 +13445,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_avg_nearest_neighbor_degree */ {"knn", (PyCFunction) igraphmodule_Graph_knn, METH_VARARGS | METH_KEYWORDS, - "knn(vids=None, weights=None)\n\n" + "knn(vids=None, weights=None)\n--\n\n" "Calculates the average degree of the neighbors for each vertex, and\n" "the same quantity as the function of vertex degree.\n\n" "@param vids: the vertices for which the calculation is performed.\n" @@ -13463,7 +13464,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_connected */ {"is_connected", (PyCFunction) igraphmodule_Graph_is_connected, METH_VARARGS | METH_KEYWORDS, - "is_connected(mode=STRONG)\n\n" + "is_connected(mode=STRONG) -> bool\n--\n\n" "Decides whether the graph is connected.\n\n" "@param mode: whether we should calculate strong or weak connectivity.\n" "@return: C{True} if the graph is connected, C{False} otherwise.\n"}, @@ -13471,7 +13472,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_linegraph */ {"linegraph", (PyCFunction) igraphmodule_Graph_linegraph, METH_VARARGS | METH_KEYWORDS, - "linegraph()\n\n" + "linegraph()\n--\n\n" "Returns the line graph of the graph.\n\n" "The line graph M{L(G)} of an undirected graph is defined as follows:\n" "M{L(G)} has one vertex for each edge in G and two vertices in M{L(G)}\n" @@ -13486,7 +13487,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_maxdegree */ {"maxdegree", (PyCFunction) igraphmodule_Graph_maxdegree, METH_VARARGS | METH_KEYWORDS, - "maxdegree(vertices=None, mode=ALL, loops=False)\n\n" + "maxdegree(vertices=None, mode=ALL, loops=False)\n--\n\n" "Returns the maximum degree of a vertex set in the graph.\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the degree of the given vertices (in the\n" @@ -13503,7 +13504,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_neighborhood */ {"neighborhood", (PyCFunction) igraphmodule_Graph_neighborhood, METH_VARARGS | METH_KEYWORDS, - "neighborhood(vertices=None, order=1, mode=ALL, mindist=0)\n\n" + "neighborhood(vertices=None, order=1, mode=ALL, mindist=0)\n--\n\n" "For each vertex specified by I{vertices}, returns the\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" @@ -13531,7 +13532,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_neighborhood_size */ {"neighborhood_size", (PyCFunction) igraphmodule_Graph_neighborhood_size, METH_VARARGS | METH_KEYWORDS, - "neighborhood_size(vertices=None, order=1, mode=ALL, mindist=0)\n\n" + "neighborhood_size(vertices=None, order=1, mode=ALL, mindist=0)\n--\n\n" "For each vertex specified by I{vertices}, returns the number of\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" @@ -13562,7 +13563,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "personalized_pagerank(vertices=None, directed=True, damping=0.85,\n" " reset=None, reset_vertices=None, weights=None, \n" " arpack_options=None, implementation=\"prpack\", niter=1000,\n" - " eps=0.001)\n\n" + " eps=0.001)\n--\n\n" "Calculates the personalized PageRank values of a graph.\n\n" "The personalized PageRank calculation is similar to the PageRank\n" "calculation, but the random walk is reset to a non-uniform distribution\n" @@ -13611,7 +13612,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_path_length_hist */ {"path_length_hist", (PyCFunction) igraphmodule_Graph_path_length_hist, METH_VARARGS | METH_KEYWORDS, - "path_length_hist(directed=True)\n\n" + "path_length_hist(directed=True)\n--\n\n" "Calculates the path length histogram of the graph\n" "@attention: this function is wrapped in a more convenient syntax in the\n" " derived class L{Graph}. It is advised to use that instead of this version.\n\n" @@ -13625,7 +13626,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_permute_vertices */ {"permute_vertices", (PyCFunction) igraphmodule_Graph_permute_vertices, METH_VARARGS | METH_KEYWORDS, - "permute_vertices(permutation)\n\n" + "permute_vertices(permutation)\n--\n\n" "Permutes the vertices of the graph according to the given permutation\n" "and returns the new graph.\n\n" "Vertex M{k} of the original graph will become vertex M{permutation[k]}\n" @@ -13637,7 +13638,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interfaces to igraph_radius */ {"radius", (PyCFunction) igraphmodule_Graph_radius, METH_VARARGS | METH_KEYWORDS, - "radius(mode=OUT)\n\n" + "radius(mode=OUT)\n--\n\n" "Calculates the radius of the graph.\n\n" "The radius of a graph is defined as the minimum eccentricity of\n" "its vertices (see L{eccentricity()}).\n" @@ -13653,7 +13654,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_reciprocity */ {"reciprocity", (PyCFunction) igraphmodule_Graph_reciprocity, METH_VARARGS | METH_KEYWORDS, - "reciprocity(ignore_loops=True, mode=\"default\")\n\n" + "reciprocity(ignore_loops=True, mode=\"default\") -> float\n--\n\n" "Reciprocity defines the proportion of mutual connections in a\n" "directed graph. It is most commonly defined as the probability\n" "that the opposite counterpart of a directed edge is also included\n" @@ -13677,7 +13678,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_rewire */ {"rewire", (PyCFunction) igraphmodule_Graph_rewire, METH_VARARGS | METH_KEYWORDS, - "rewire(n=1000, mode=\"simple\")\n\n" + "rewire(n=1000, mode=\"simple\")\n--\n\n" "Randomly rewires the graph while preserving the degree distribution.\n\n" "Please note that the rewiring is done \"in-place\", so the original\n" "graph will be modified. If you want to preserve the original graph,\n" @@ -13690,7 +13691,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_rewire_edges */ {"rewire_edges", (PyCFunction) igraphmodule_Graph_rewire_edges, METH_VARARGS | METH_KEYWORDS, - "rewire_edges(prob, loops=False, multiple=False)\n\n" + "rewire_edges(prob, loops=False, multiple=False)\n--\n\n" "Rewires the edges of a graph with constant probability.\n\n" "Each endpoint of each edge of the graph will be rewired with a constant\n" "probability, given in the first argument.\n\n" @@ -13705,7 +13706,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_shortest_paths */ {"shortest_paths", (PyCFunction) igraphmodule_Graph_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "shortest_paths(source=None, target=None, weights=None, mode=OUT)\n\n" + "shortest_paths(source=None, target=None, weights=None, mode=OUT)\n--\n\n" "Calculates shortest path lengths for given vertices in a graph.\n\n" "The algorithm used for the calculations is selected automatically:\n" "a simple BFS is used for unweighted graphs, Dijkstra's algorithm is\n" @@ -13728,7 +13729,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_simplify */ {"simplify", (PyCFunction) igraphmodule_Graph_simplify, METH_VARARGS | METH_KEYWORDS, - "simplify(multiple=True, loops=True, combine_edges=None)\n\n" + "simplify(multiple=True, loops=True, combine_edges=None)\n--\n\n" "Simplifies a graph by removing self-loops and/or multiple edges.\n\n" "\n" "For example, suppose you have a graph with an edge attribute named\n" @@ -13780,14 +13781,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_minimum_spanning_tree */ {"_spanning_tree", (PyCFunction) igraphmodule_Graph_spanning_tree, METH_VARARGS | METH_KEYWORDS, - "_spanning_tree(weights=None)\n\n" + "_spanning_tree(weights=None)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.spanning_tree()"}, // interface to igraph_subcomponent {"subcomponent", (PyCFunction) igraphmodule_Graph_subcomponent, METH_VARARGS | METH_KEYWORDS, - "subcomponent(v, mode=ALL)\n\n" + "subcomponent(v, mode=ALL)\n--\n\n" "Determines the indices of vertices which are in the same component as a given vertex.\n\n" "@param v: the index of the vertex used as the source/destination\n" "@param mode: if equals to L{IN}, returns the vertex IDs from\n" @@ -13802,7 +13803,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_subgraph_edges */ {"subgraph_edges", (PyCFunction) igraphmodule_Graph_subgraph_edges, METH_VARARGS | METH_KEYWORDS, - "subgraph_edges(edges, delete_vertices=True)\n\n" + "subgraph_edges(edges, delete_vertices=True)\n--\n\n" "Returns a subgraph spanned by the given edges.\n\n" "@param edges: a list containing the edge IDs which should\n" " be included in the result.\n" @@ -13815,7 +13816,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"topological_sorting", (PyCFunction) igraphmodule_Graph_topological_sorting, METH_VARARGS | METH_KEYWORDS, - "topological_sorting(mode=OUT)\n\n" + "topological_sorting(mode=OUT)\n--\n\n" "Calculates a possible topological sorting of the graph.\n\n" "Returns a partial sorting and issues a warning if the graph is not\n" "a directed acyclic graph.\n\n" @@ -13828,7 +13829,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"to_prufer", (PyCFunction) igraphmodule_Graph_to_prufer, METH_NOARGS, - "to_prufer()\n\n" + "to_prufer()\n--\n\n" "Converts a tree graph into a Prufer sequence.\n\n" "@return: the Prufer sequence as a list" }, @@ -13837,7 +13838,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"transitivity_undirected", (PyCFunction) igraphmodule_Graph_transitivity_undirected, METH_VARARGS | METH_KEYWORDS, - "transitivity_undirected(mode=\"nan\")\n\n" + "transitivity_undirected(mode=\"nan\")\n--\n\n" "Calculates the global transitivity (clustering coefficient) of the\n" "graph.\n\n" "The transitivity measures the probability that two neighbors of a\n" @@ -13863,7 +13864,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"transitivity_local_undirected", (PyCFunction) igraphmodule_Graph_transitivity_local_undirected, METH_VARARGS | METH_KEYWORDS, - "transitivity_local_undirected(vertices=None, mode=\"nan\", weights=None)\n\n" + "transitivity_local_undirected(vertices=None, mode=\"nan\", weights=None)\n--\n\n" "Calculates the local transitivity (clustering coefficient) of the\n" "given vertices in the graph.\n\n" "The transitivity measures the probability that two neighbors of a\n" @@ -13897,7 +13898,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"transitivity_avglocal_undirected", (PyCFunction) igraphmodule_Graph_transitivity_avglocal_undirected, METH_VARARGS | METH_KEYWORDS, - "transitivity_avglocal_undirected(mode=\"nan\")\n\n" + "transitivity_avglocal_undirected(mode=\"nan\")\n--\n\n" "Calculates the average of the vertex transitivities of the graph.\n\n" "The transitivity measures the probability that two neighbors of a\n" "vertex are connected. In case of the average local transitivity,\n" @@ -13922,7 +13923,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_unfold_tree */ {"unfold_tree", (PyCFunction) igraphmodule_Graph_unfold_tree, METH_VARARGS | METH_KEYWORDS, - "unfold_tree(sources=None, mode=OUT)\n\n" + "unfold_tree(sources=None, mode=OUT)\n--\n\n" "Unfolds the graph using a BFS to a tree by duplicating vertices as necessary.\n\n" "@param sources: the source vertices to start the unfolding from. It should be a\n" " list of vertex indices, preferably one vertex from each connected component.\n" @@ -13938,7 +13939,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_[st_]vertex_connectivity */ {"vertex_connectivity", (PyCFunction) igraphmodule_Graph_vertex_connectivity, METH_VARARGS | METH_KEYWORDS, - "vertex_connectivity(source=-1, target=-1, checks=True, neighbors=\"error\")\n\n" + "vertex_connectivity(source=-1, target=-1, checks=True, neighbors=\"error\")\n--\n\n" "Calculates the vertex connectivity of the graph or between some vertices.\n\n" "The vertex connectivity between two given vertices is the number of vertices\n" "that have to be removed in order to disconnect the two vertices into two\n" @@ -13971,7 +13972,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_bibcoupling */ {"bibcoupling", (PyCFunction) igraphmodule_Graph_bibcoupling, METH_VARARGS | METH_KEYWORDS, - "bibcoupling(vertices=None)\n\n" + "bibcoupling(vertices=None)\n--\n\n" "Calculates bibliographic coupling scores for given vertices in a graph.\n\n" "@param vertices: the vertices to be analysed. If C{None}, all vertices\n" " will be considered.\n" @@ -13979,7 +13980,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_cocitation */ {"cocitation", (PyCFunction) igraphmodule_Graph_cocitation, METH_VARARGS | METH_KEYWORDS, - "cocitation(vertices=None)\n\n" + "cocitation(vertices=None)\n--\n\n" "Calculates cocitation scores for given vertices in a graph.\n\n" "@param vertices: the vertices to be analysed. If C{None}, all vertices\n" " will be considered.\n" @@ -14014,7 +14015,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"similarity_inverse_log_weighted", (PyCFunction) igraphmodule_Graph_similarity_inverse_log_weighted, METH_VARARGS | METH_KEYWORDS, - "similarity_inverse_log_weighted(vertices=None, mode=IGRAPH_ALL)\n\n" + "similarity_inverse_log_weighted(vertices=None, mode=IGRAPH_ALL)\n--\n\n" "Inverse log-weighted similarity coefficient of vertices.\n\n" "Each vertex is assigned a weight which is 1 / log(degree). The\n" "log-weighted similarity of two vertices is the sum of the weights\n" @@ -14031,7 +14032,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_similarity_jaccard */ {"similarity_jaccard", (PyCFunction) igraphmodule_Graph_similarity_jaccard, METH_VARARGS | METH_KEYWORDS, - "similarity_jaccard(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n\n" + "similarity_jaccard(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n--\n\n" "Jaccard similarity coefficient of vertices.\n\n" "The Jaccard similarity coefficient of two vertices is the number of their\n" "common neighbors divided by the number of vertices that are adjacent to\n" @@ -14059,7 +14060,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /******************/ {"motifs_randesu", (PyCFunction) igraphmodule_Graph_motifs_randesu, METH_VARARGS | METH_KEYWORDS, - "motifs_randesu(size=3, cut_prob=None, callback=None)\n\n" + "motifs_randesu(size=3, cut_prob=None, callback=None)\n--\n\n" "Counts the number of motifs in the graph\n\n" "Motifs are small subgraphs of a given structure in a graph. It is\n" "argued that the motif profile (ie. the number of different motifs in\n" @@ -14090,7 +14091,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"motifs_randesu_no", (PyCFunction) igraphmodule_Graph_motifs_randesu_no, METH_VARARGS | METH_KEYWORDS, - "motifs_randesu_no(size=3, cut_prob=None)\n\n" + "motifs_randesu_no(size=3, cut_prob=None)\n--\n\n" "Counts the total number of motifs in the graph\n\n" "Motifs are small subgraphs of a given structure in a graph.\n" "This function counts the total number of motifs in a graph without\n" @@ -14107,7 +14108,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"motifs_randesu_estimate", (PyCFunction) igraphmodule_Graph_motifs_randesu_estimate, METH_VARARGS | METH_KEYWORDS, - "motifs_randesu_estimate(size=3, cut_prob=None, sample)\n\n" + "motifs_randesu_estimate(size=3, cut_prob=None, sample)\n--\n\n" "Counts the total number of motifs in the graph\n\n" "Motifs are small subgraphs of a given structure in a graph.\n" "This function estimates the total number of motifs in a graph without\n" @@ -14126,7 +14127,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"dyad_census", (PyCFunction) igraphmodule_Graph_dyad_census, METH_NOARGS, - "dyad_census()\n\n" + "dyad_census()\n--\n\n" "Dyad census, as defined by Holland and Leinhardt\n\n" "Dyad census means classifying each pair of vertices of a directed\n" "graph into three categories: mutual, there is an edge from I{a} to\n" @@ -14141,7 +14142,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"triad_census", (PyCFunction) igraphmodule_Graph_triad_census, METH_NOARGS, - "triad_census()\n\n" + "triad_census()\n--\n\n" "Triad census, as defined by Davis and Leinhardt\n\n" "Calculating the triad census means classifying every triplets of\n" "vertices in a directed graph. A triplet can be in one of 16 states,\n" @@ -14161,7 +14162,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_bipartite", (PyCFunction) igraphmodule_Graph_layout_bipartite, METH_VARARGS | METH_KEYWORDS, - "layout_bipartite(types=\"type\", hgap=1, vgap=1, maxiter=100)\n\n" + "layout_bipartite(types=\"type\", hgap=1, vgap=1, maxiter=100)\n--\n\n" "Place the vertices of a bipartite graph in two layers.\n\n" "The layout is created by placing the vertices in two rows, according\n" "to their types. The positions of the vertices within the rows are\n" @@ -14180,7 +14181,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_circle */ {"layout_circle", (PyCFunction) igraphmodule_Graph_layout_circle, METH_VARARGS | METH_KEYWORDS, - "layout_circle(dim=2, order=None)\n\n" + "layout_circle(dim=2, order=None)\n--\n\n" "Places the vertices of the graph uniformly on a circle or a sphere.\n\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" @@ -14191,7 +14192,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_grid */ {"layout_grid", (PyCFunction) igraphmodule_Graph_layout_grid, METH_VARARGS | METH_KEYWORDS, - "layout_grid(width=0, height=0, dim=2)\n\n" + "layout_grid(width=0, height=0, dim=2)\n--\n\n" "Places the vertices of a graph in a 2D or 3D grid.\n\n" "@param width: the number of vertices in a single row of the layout.\n" " Zero or negative numbers mean that the width should be determined\n" @@ -14206,7 +14207,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_star */ {"layout_star", (PyCFunction) igraphmodule_Graph_layout_star, METH_VARARGS | METH_KEYWORDS, - "layout_star(center=0, order=None)\n\n" + "layout_star(center=0, order=None)\n--\n\n" "Calculates a star-like layout for the graph.\n\n" "@param center: the ID of the vertex to put in the center\n" "@param order: a numeric vector giving the order of the vertices\n" @@ -14219,9 +14220,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_kamada_kawai", (PyCFunction) igraphmodule_Graph_layout_kamada_kawai, METH_VARARGS | METH_KEYWORDS, - "layout_kamada_kawai(maxiter=1000, seed=None, maxiter=1000, epsilon=0, \n" - " kkconst=None, minx=None, maxx=None, miny=None, maxy=None, \n" - " minz=None, maxz=None, dim=2)\n\n" + "layout_kamada_kawai(maxiter=1000, seed=None, maxiter=1000, epsilon=0, " + "kkconst=None, minx=None, maxx=None, miny=None, maxy=None, " + "minz=None, maxz=None, dim=2)\n--\n\n" "Places the vertices on a plane according to the Kamada-Kawai algorithm.\n\n" "This is a force directed layout, see Kamada, T. and Kawai, S.:\n" "An Algorithm for Drawing General Undirected Graphs.\n" @@ -14253,9 +14254,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_davidson_harel", (PyCFunction) igraphmodule_Graph_layout_davidson_harel, METH_VARARGS | METH_KEYWORDS, - "layout_davidson_harel(seed=None, maxiter=10, fineiter=-1, cool_fact=0.75,\n" - " weight_node_dist=1.0, weight_border=0.0, weight_edge_lengths=-1,\n" - " weight_edge_crossings=-1, weight_node_edge_dist=-1)\n\n" + "layout_davidson_harel(seed=None, maxiter=10, fineiter=-1, cool_fact=0.75, " + "weight_node_dist=1.0, weight_border=0.0, weight_edge_lengths=-1, " + "weight_edge_crossings=-1, weight_node_edge_dist=-1)\n--\n\n" "Places the vertices on a 2D plane according to the Davidson-Harel layout\n" "algorithm.\n\n" "The algorithm uses simulated annealing and a sophisticated energy function,\n" @@ -14293,7 +14294,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_drl", (PyCFunction) igraphmodule_Graph_layout_drl, METH_VARARGS | METH_KEYWORDS, - "layout_drl(weights=None, fixed=None, seed=None, options=None, dim=2)\n\n" + "layout_drl(weights=None, fixed=None, seed=None, options=None, dim=2)\n--\n\n" "Places the vertices on a 2D plane or in the 3D space ccording to the DrL\n" "layout algorithm.\n\n" "This is an algorithm suitable for quite large graphs, but it can be\n" @@ -14352,9 +14353,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_fruchterman_reingold", (PyCFunction) igraphmodule_Graph_layout_fruchterman_reingold, METH_VARARGS | METH_KEYWORDS, - "layout_fruchterman_reingold(weights=None, niter=500, seed=None, \n" - " start_temp=None, minx=None, maxx=None, miny=None, \n" - " maxy=None, minz=None, maxz=None, grid=\"auto\")\n\n" + "layout_fruchterman_reingold(weights=None, niter=500, seed=None, " + "start_temp=None, minx=None, maxx=None, miny=None, " + "maxy=None, minz=None, maxz=None, grid=\"auto\")\n--\n\n" "Places the vertices on a 2D plane according to the\n" "Fruchterman-Reingold algorithm.\n\n" "This is a force directed layout, see Fruchterman, T. M. J. and Reingold, E. M.:\n" @@ -14394,7 +14395,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_graphopt", (PyCFunction) igraphmodule_Graph_layout_graphopt, METH_VARARGS | METH_KEYWORDS, - "layout_graphopt(niter=500, node_charge=0.001, node_mass=30, spring_length=0, spring_constant=1, max_sa_movement=5, seed=None)\n\n" + "layout_graphopt(niter=500, node_charge=0.001, node_mass=30, " + "spring_length=0, spring_constant=1, max_sa_movement=5, seed=None)\n--\n\n" "This is a port of the graphopt layout algorithm by Michael Schmuhl.\n" "graphopt version 0.4.1 was rewritten in C and the support for layers\n" "was removed.\n\n" @@ -14420,7 +14422,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_lgl */ {"layout_lgl", (PyCFunction) igraphmodule_Graph_layout_lgl, METH_VARARGS | METH_KEYWORDS, - "layout_lgl(maxiter=150, maxdelta=-1, area=-1, coolexp=1.5, repulserad=-1, cellsize=-1, root=None)\n\n" + "layout_lgl(maxiter=150, maxdelta=-1, area=-1, coolexp=1.5, " + "repulserad=-1, cellsize=-1, root=None)\n--\n\n" "Places the vertices on a 2D plane according to the Large Graph Layout.\n\n" "@param maxiter: the number of iterations to perform.\n" "@param maxdelta: the maximum distance to move a vertex in\n" @@ -14446,7 +14449,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_mds", (PyCFunction) igraphmodule_Graph_layout_mds, METH_VARARGS | METH_KEYWORDS, - "layout_mds(dist=None, dim=2, arpack_options=None)\n" + "layout_mds(dist=None, dim=2, arpack_options=None)\n--\n" "Places the vertices in an Euclidean space with the given number of\n" "dimensions using multidimensional scaling.\n\n" "This layout requires a distance matrix, where the intersection of\n" @@ -14479,7 +14482,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_reingold_tilford", (PyCFunction) igraphmodule_Graph_layout_reingold_tilford, METH_VARARGS | METH_KEYWORDS, - "layout_reingold_tilford(mode=\"out\", root=None, rootlevel=None)\n" + "layout_reingold_tilford(mode=\"out\", root=None, rootlevel=None)\n--\n" "Places the vertices on a 2D plane according to the Reingold-Tilford\n" "layout algorithm.\n\n" "This is a tree layout. If the given graph is not a tree, a breadth-first\n" @@ -14509,7 +14512,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_reingold_tilford_circular", (PyCFunction) igraphmodule_Graph_layout_reingold_tilford_circular, METH_VARARGS | METH_KEYWORDS, - "layout_reingold_tilford_circular(mode=\"out\", root=None, rootlevel=None)\n" + "layout_reingold_tilford_circular(mode=\"out\", root=None, rootlevel=None)\n--\n" "Circular Reingold-Tilford layout for trees.\n\n" "This layout is similar to the Reingold-Tilford layout, but the vertices\n" "are placed in a circular way, with the root vertex in the center.\n\n" @@ -14523,7 +14526,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_random */ {"layout_random", (PyCFunction) igraphmodule_Graph_layout_random, METH_VARARGS | METH_KEYWORDS, - "layout_random(dim=2)\n" + "layout_random(dim=2)\n--\n" "Places the vertices of the graph randomly.\n\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" @@ -14541,7 +14544,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { //////////////////////////// {"bfs", (PyCFunction) igraphmodule_Graph_bfs, METH_VARARGS | METH_KEYWORDS, - "bfs(vid, mode=OUT)\n\n" + "bfs(vid, mode=OUT)\n--\n\n" "Conducts a breadth first search (BFS) on the graph.\n\n" "@param vid: the root vertex ID\n" "@param mode: either L{IN} or L{OUT} or L{ALL}, ignored\n" @@ -14552,7 +14555,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - The parent of every vertex in the BFS\n"}, {"bfsiter", (PyCFunction) igraphmodule_Graph_bfsiter, METH_VARARGS | METH_KEYWORDS, - "bfsiter(vid, mode=OUT, advanced=False)\n\n" + "bfsiter(vid, mode=OUT, advanced=False)\n--\n\n" "Constructs a breadth first search (BFS) iterator of the graph.\n\n" "@param vid: the root vertex ID\n" "@param mode: either L{IN} or L{OUT} or L{ALL}.\n" @@ -14563,7 +14566,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the BFS iterator as an L{igraph.BFSIter} object.\n"}, {"dfsiter", (PyCFunction) igraphmodule_Graph_dfsiter, METH_VARARGS | METH_KEYWORDS, - "dfsiter(vid, mode=OUT, advanced=False)\n\n" + "dfsiter(vid, mode=OUT, advanced=False)\n--\n\n" "Constructs a depth first search (DFS) iterator of the graph.\n\n" "@param vid: the root vertex ID\n" "@param mode: either L{IN} or L{OUT} or L{ALL}.\n" @@ -14580,7 +14583,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_adjacency {"get_adjacency", (PyCFunction) igraphmodule_Graph_get_adjacency, METH_VARARGS | METH_KEYWORDS, - "get_adjacency(type=GET_ADJACENCY_BOTH, eids=False)\n\n" + "get_adjacency(type=GET_ADJACENCY_BOTH, eids=False)\n--\n\n" "Returns the adjacency matrix of a graph.\n\n" "@param type: either C{GET_ADJACENCY_LOWER} (uses the\n" " lower triangle of the matrix) or C{GET_ADJACENCY_UPPER}\n" @@ -14596,19 +14599,19 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_edgelist {"get_edgelist", (PyCFunction) igraphmodule_Graph_get_edgelist, METH_NOARGS, - "get_edgelist()\n\n" "Returns the edge list of a graph."}, + "get_edgelist()\n--\n\n" "Returns the edge list of a graph."}, /* interface to igraph_get_incidence */ {"get_incidence", (PyCFunction) igraphmodule_Graph_get_incidence, METH_VARARGS | METH_KEYWORDS, - "get_incidence(types)\n\n" + "get_incidence(types)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.get_incidence()\n\n"}, // interface to igraph_to_directed {"to_directed", (PyCFunction) igraphmodule_Graph_to_directed, METH_VARARGS | METH_KEYWORDS, - "to_directed(mutual=True)\n\n" + "to_directed(mutual=True)\n--\n\n" "Converts an undirected graph to directed.\n\n" "@param mutual: C{True} if mutual directed edges should be\n" " created for every undirected edge. If C{False}, a directed\n" @@ -14617,7 +14620,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_to_undirected {"to_undirected", (PyCFunction) igraphmodule_Graph_to_undirected, METH_VARARGS | METH_KEYWORDS, - "to_undirected(mode=\"collapse\", combine_edges=None)\n\n" + "to_undirected(mode=\"collapse\", combine_edges=None)\n--\n\n" "Converts a directed graph to undirected.\n\n" "@param mode: specifies what to do with multiple directed edges\n" " going between the same vertex pair. C{True} or C{\"collapse\"}\n" @@ -14633,7 +14636,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_laplacian */ {"laplacian", (PyCFunction) igraphmodule_Graph_laplacian, METH_VARARGS | METH_KEYWORDS, - "laplacian(weights=None, normalized=False)\n\n" + "laplacian(weights=None, normalized=False)\n--\n\n" "Returns the Laplacian matrix of a graph.\n\n" "The Laplacian matrix is similar to the adjacency matrix, but the edges\n" "are denoted with -1 and the diagonal contains the node degrees.\n\n" @@ -14656,7 +14659,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_read_graph_dimacs {"Read_DIMACS", (PyCFunction) igraphmodule_Graph_Read_DIMACS, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_DIMACS(f, directed=False)\n\n" + "Read_DIMACS(f, directed=False)\n--\n\n" "Reads a graph from a file conforming to the DIMACS minimum-cost flow file format.\n\n" "For the exact description of the format, see\n" "U{http://lpsolve.sourceforge.net/5.5/DIMACS.htm}\n\n" @@ -14674,7 +14677,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_dl */ {"Read_DL", (PyCFunction) igraphmodule_Graph_Read_DL, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_DL(f, directed=True)\n\n" + "Read_DL(f, directed=True)\n--\n\n" "Reads an UCINET DL file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n" "@param directed: whether the generated graph should be directed.\n"}, @@ -14682,7 +14685,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_edgelist */ {"Read_Edgelist", (PyCFunction) igraphmodule_Graph_Read_Edgelist, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_Edgelist(f, directed=True)\n\n" + "Read_Edgelist(f, directed=True)\n--\n\n" "Reads an edge list from a file and creates a graph based on it.\n\n" "Please note that the vertex indices are zero-based. A vertex of zero\n" "degree will be created for every integer that is in range but does not\n" @@ -14692,7 +14695,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_graphdb */ {"Read_GraphDB", (PyCFunction) igraphmodule_Graph_Read_GraphDB, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_GraphDB(f, directed=False)\n\n" + "Read_GraphDB(f, directed=False)\n--\n\n" "Reads a GraphDB format file and creates a graph based on it.\n\n" "GraphDB is a binary format, used in the graph database for\n" "isomorphism testing (see U{http://amalfi.dis.unina.it/graph/}).\n\n" @@ -14701,7 +14704,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_graphml */ {"Read_GraphML", (PyCFunction) igraphmodule_Graph_Read_GraphML, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_GraphML(f, directed=True, index=0)\n\n" + "Read_GraphML(f, directed=True, index=0)\n--\n\n" "Reads a GraphML format file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n" "@param index: if the GraphML file contains multiple graphs,\n" @@ -14711,14 +14714,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_gml */ {"Read_GML", (PyCFunction) igraphmodule_Graph_Read_GML, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_GML(f)\n\n" + "Read_GML(f)\n--\n\n" "Reads a GML file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n" }, /* interface to igraph_read_graph_ncol */ {"Read_Ncol", (PyCFunction) igraphmodule_Graph_Read_Ncol, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_Ncol(f, names=True, weights=\"if_present\", directed=True)\n\n" + "Read_Ncol(f, names=True, weights=\"if_present\", directed=True)\n--\n\n" "Reads an .ncol file used by LGL.\n\n" "It is also useful for creating graphs from \"named\" (and\n" "optionally weighted) edge lists.\n\n" @@ -14743,7 +14746,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_lgl */ {"Read_Lgl", (PyCFunction) igraphmodule_Graph_Read_Lgl, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_Lgl(f, names=True, weights=\"if_present\", directed=True)\n\n" + "Read_Lgl(f, names=True, weights=\"if_present\", directed=True)\n--\n\n" "Reads an .lgl file used by LGL.\n\n" "It is also useful for creating graphs from \"named\" (and\n" "optionally weighted) edge lists.\n\n" @@ -14768,13 +14771,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_pajek */ {"Read_Pajek", (PyCFunction) igraphmodule_Graph_Read_Pajek, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_Pajek(f)\n\n" + "Read_Pajek(f)\n--\n\n" "Reads a Pajek format file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n"}, /* interface to igraph_write_graph_dimacs */ {"write_dimacs", (PyCFunction) igraphmodule_Graph_write_dimacs, METH_VARARGS | METH_KEYWORDS, - "write_dimacs(f, source, target, capacity=None)\n\n" + "write_dimacs(f, source, target, capacity=None)\n--\n\n" "Writes the graph in DIMACS format to the given file.\n\n" "@param f: the name of the file to be written or a Python file handle\n" "@param source: the source vertex ID\n" @@ -14785,7 +14788,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_write_graph_dot */ {"write_dot", (PyCFunction) igraphmodule_Graph_write_dot, METH_VARARGS | METH_KEYWORDS, - "write_dot(f)\n\n" + "write_dot(f)\n--\n\n" "Writes the graph in DOT format to the given file.\n\n" "DOT is the format used by the U{GraphViz }\n" "software package.\n\n" @@ -14794,14 +14797,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_write_graph_edgelist */ {"write_edgelist", (PyCFunction) igraphmodule_Graph_write_edgelist, METH_VARARGS | METH_KEYWORDS, - "write_edgelist(f)\n\n" + "write_edgelist(f)\n--\n\n" "Writes the edge list of a graph to a file.\n\n" "Directed edges are written in (from, to) order.\n\n" "@param f: the name of the file to be written or a Python file handle\n"}, /* interface to igraph_write_graph_gml */ {"write_gml", (PyCFunction) igraphmodule_Graph_write_gml, METH_VARARGS | METH_KEYWORDS, - "write_gml(f, creator=None, ids=None)\n\n" + "write_gml(f, creator=None, ids=None)\n--\n\n" "Writes the graph in GML format to the given file.\n\n" "@param f: the name of the file to be written or a Python file handle\n" "@param creator: optional creator information to be written to the file.\n" @@ -14813,7 +14816,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_write_graph_ncol */ {"write_ncol", (PyCFunction) igraphmodule_Graph_write_ncol, METH_VARARGS | METH_KEYWORDS, - "write_ncol(f, names=\"name\", weights=\"weights\")\n\n" + "write_ncol(f, names=\"name\", weights=\"weights\")\n--\n\n" "Writes the edge list of a graph to a file in .ncol format.\n\n" "Note that multiple edges and/or loops break the LGL software,\n" "but igraph does not check for this condition. Unless you know\n" @@ -14829,7 +14832,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_write_graph_lgl */ {"write_lgl", (PyCFunction) igraphmodule_Graph_write_lgl, METH_VARARGS | METH_KEYWORDS, - "write_lgl(f, names=\"name\", weights=\"weights\", isolates=True)\n\n" + "write_lgl(f, names=\"name\", weights=\"weights\", isolates=True)\n--\n\n" "Writes the edge list of a graph to a file in .lgl format.\n\n" "Note that multiple edges and/or loops break the LGL software,\n" "but igraph does not check for this condition. Unless you know\n" @@ -14846,21 +14849,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_write_graph_pajek */ {"write_pajek", (PyCFunction) igraphmodule_Graph_write_pajek, METH_VARARGS | METH_KEYWORDS, - "write_pajek(f)\n\n" + "write_pajek(f)\n--\n\n" "Writes the graph in Pajek format to the given file.\n\n" "@param f: the name of the file to be written or a Python file handle\n" }, /* interface to igraph_write_graph_edgelist */ {"write_graphml", (PyCFunction) igraphmodule_Graph_write_graphml, METH_VARARGS | METH_KEYWORDS, - "write_graphml(f)\n\n" + "write_graphml(f)\n--\n\n" "Writes the graph to a GraphML file.\n\n" "@param f: the name of the file to be written or a Python file handle\n" }, /* interface to igraph_write_graph_leda */ {"write_leda", (PyCFunction) igraphmodule_Graph_write_leda, METH_VARARGS | METH_KEYWORDS, - "write_leda(f, names=\"name\", weights=\"weights\")\n\n" + "write_leda(f, names=\"name\", weights=\"weights\")\n--\n\n" "Writes the graph to a file in LEDA native format.\n\n" "The LEDA format supports at most one attribute per vertex and edge. You can\n" "specify which vertex and edge attribute you want to use. Note that the\n" @@ -14882,7 +14885,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"canonical_permutation", (PyCFunction) igraphmodule_Graph_canonical_permutation, METH_VARARGS | METH_KEYWORDS, - "canonical_permutation(sh=\"fl\", color=None)\n\n" + "canonical_permutation(sh=\"fl\", color=None)\n--\n\n" "Calculates the canonical permutation of a graph using the BLISS isomorphism\n" "algorithm.\n\n" "Passing the permutation returned here to L{Graph.permute_vertices()} will\n" @@ -14909,7 +14912,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"isoclass", (PyCFunction) igraphmodule_Graph_isoclass, METH_VARARGS | METH_KEYWORDS, - "isoclass(vertices)\n\n" + "isoclass(vertices)\n--\n\n" "Returns the isomorphism class of the graph or its subgraph.\n\n" "Isomorphy class calculations are implemented only for graphs with\n" "3 or 4 vertices.\n\n" @@ -14919,7 +14922,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the isomorphism class of the (sub)graph\n\n"}, {"isomorphic", (PyCFunction) igraphmodule_Graph_isomorphic, METH_VARARGS | METH_KEYWORDS, - "isomorphic(other)\n\n" + "isomorphic(other) -> bool\n--\n\n" "Checks whether the graph is isomorphic to another graph.\n\n" "The algorithm being used is selected using a simple heuristic:\n\n" " - If one graph is directed and the other undirected, an exception\n" @@ -14937,7 +14940,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"isomorphic_bliss", (PyCFunction) igraphmodule_Graph_isomorphic_bliss, METH_VARARGS | METH_KEYWORDS, "isomorphic_bliss(other, return_mapping_12=False, return_mapping_21=False,\n" - " sh1=\"fl\", sh2=None, color1=None, color2=None)\n\n" + " sh1=\"fl\", sh2=None, color1=None, color2=None)\n--\n\n" "Checks whether the graph is isomorphic to another graph, using the\n" "BLISS isomorphism algorithm.\n\n" "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" @@ -14977,7 +14980,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "isomorphic_vf2(other=None, color1=None, color2=None, edge_color1=None,\n" " edge_color2=None, return_mapping_12=False, return_mapping_21=False,\n" - " node_compat_fn=None, edge_compat_fn=None, callback=None)\n\n" + " node_compat_fn=None, edge_compat_fn=None, callback=None)\n--\n\n" "Checks whether the graph is isomorphic to another graph, using the\n" "VF2 isomorphism algorithm.\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" @@ -15030,7 +15033,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { (PyCFunction) igraphmodule_Graph_count_isomorphisms_vf2, METH_VARARGS | METH_KEYWORDS, "count_isomorphisms_vf2(other=None, color1=None, color2=None, edge_color1=None,\n" - " edge_color2=None, node_compat_fn=None, edge_compat_fn=None)\n\n" + " edge_color2=None, node_compat_fn=None, edge_compat_fn=None)\n--\n\n" "Determines the number of isomorphisms between the graph and another one\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" "vertices and edges with the same color will be allowed to match each other.\n\n" @@ -15102,7 +15105,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "subisomorphic_vf2(other, color1=None, color2=None, edge_color1=None,\n" " edge_color2=None, return_mapping_12=False, return_mapping_21=False,\n" - " callback=None, node_compat_fn=None, edge_compat_fn=None)\n\n" + " callback=None, node_compat_fn=None, edge_compat_fn=None)\n--\n\n" "Checks whether a subgraph of the graph is isomorphic to another graph.\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" "vertices and edges with the same color will be allowed to match each other.\n\n" @@ -15156,7 +15159,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "count_subisomorphisms_vf2(other, color1=None, color2=None,\n" " edge_color1=None, edge_color2=None, node_compat_fn=None,\n" - " edge_compat_fn=None)\n\n" + " edge_compat_fn=None)\n--\n\n" "Determines the number of subisomorphisms between the graph and another one\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" "vertices and edges with the same color will be allowed to match each other.\n\n" @@ -15191,7 +15194,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "get_subisomorphisms_vf2(other, color1=None, color2=None,\n" " edge_color1=None, edge_color2=None, node_compat_fn=None,\n" - " edge_compat_fn=None)\n\n" + " edge_compat_fn=None)\n--\n\n" "Returns all subisomorphisms between the graph and another one\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" "vertices and edges with the same color will be allowed to match each other.\n\n" @@ -15226,7 +15229,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"subisomorphic_lad", (PyCFunction) igraphmodule_Graph_subisomorphic_lad, METH_VARARGS | METH_KEYWORDS, "subisomorphic_lad(other, domains=None, induced=False, time_limit=0, \n" - " return_mapping=False)\n\n" + " return_mapping=False)\n--\n\n" "Checks whether a subgraph of the graph is isomorphic to another graph.\n\n" "The optional C{domains} argument may be used to restrict vertices that\n" "may match each other. You can also specify whether you are interested\n" @@ -15253,7 +15256,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"get_subisomorphisms_lad", (PyCFunction) igraphmodule_Graph_get_subisomorphisms_lad, METH_VARARGS | METH_KEYWORDS, - "get_subisomorphisms_lad(other, domains=None, induced=False, time_limit=0)\n\n" + "get_subisomorphisms_lad(other, domains=None, induced=False, time_limit=0)\n--\n\n" "Returns all subisomorphisms between the graph and another one using the LAD\n" "algorithm.\n\n" "The optional C{domains} argument may be used to restrict vertices that\n" @@ -15276,14 +15279,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { //////////////////////// {"attributes", (PyCFunction) igraphmodule_Graph_attributes, METH_NOARGS, - "attributes()\n\n" "@return: the attribute name list of the graph\n"}, + "attributes() -> Sequence[str]\n--\n\n" + "@return: the attribute name list of the graph\n"}, {"vertex_attributes", (PyCFunction) igraphmodule_Graph_vertex_attributes, METH_NOARGS, - "vertex_attributes()\n\n" + "vertex_attributes() -> Sequence[str]\n--\n\n" "@return: the attribute name list of the graph's vertices\n"}, {"edge_attributes", (PyCFunction) igraphmodule_Graph_edge_attributes, METH_NOARGS, - "edge_attributes()\n\n" + "edge_attributes() -> Sequence[str]\n--\n\n" "@return: the attribute name list of the graph's edges\n"}, /////////////// @@ -15291,7 +15295,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /////////////// {"complementer", (PyCFunction) igraphmodule_Graph_complementer, METH_VARARGS | METH_KEYWORDS, - "complementer(loops=False)\n\n" + "complementer(loops=False)\n--\n\n" "Returns the complementer of the graph\n\n" "@param loops: whether to include loop edges in the complementer.\n" "@return: the complementer of the graph\n"}, @@ -15306,7 +15310,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /**********************/ {"dominator", (PyCFunction) igraphmodule_Graph_dominator, METH_VARARGS | METH_KEYWORDS, - "dominator(vid, mode=)\n\n" + "dominator(vid, mode=)\n--\n\n" "Returns the dominator tree from the given root node" "@param vid: the root vertex ID\n" "@param mode: either L{IN} or L{OUT}\n" @@ -15318,7 +15322,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*****************/ {"maxflow_value", (PyCFunction) igraphmodule_Graph_maxflow_value, METH_VARARGS | METH_KEYWORDS, - "maxflow_value(source, target, capacity=None)\n\n" + "maxflow_value(source, target, capacity=None)\n--\n\n" "Returns the value of the maximum flow between the source and target vertices.\n\n" "@param source: the source vertex ID\n" "@param target: the target vertex ID\n" @@ -15329,7 +15333,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"maxflow", (PyCFunction) igraphmodule_Graph_maxflow, METH_VARARGS | METH_KEYWORDS, - "maxflow(source, target, capacity=None)\n\n" + "maxflow(source, target, capacity=None)\n--\n\n" "Returns the maximum flow between the source and target vertices.\n\n" "@attention: this function has a more convenient interface in class\n" " L{Graph} which wraps the result in a L{Flow} object. It is advised\n" @@ -15353,7 +15357,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /**********************/ {"all_st_cuts", (PyCFunction) igraphmodule_Graph_all_st_cuts, METH_VARARGS | METH_KEYWORDS, - "all_st_cuts(source, target)\n\n" + "all_st_cuts(source, target)\n--\n\n" "Returns all the cuts between the source and target vertices in a\n" "directed graph.\n\n" "This function lists all edge-cuts between a source and a target vertex.\n" @@ -15369,7 +15373,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"all_st_mincuts", (PyCFunction) igraphmodule_Graph_all_st_mincuts, METH_VARARGS | METH_KEYWORDS, - "all_st_mincuts(source, target)\n\n" + "all_st_mincuts(source, target)\n--\n\n" "Returns all minimum cuts between the source and target vertices in a\n" "directed graph.\n\n" "@param source: the source vertex ID\n" @@ -15380,7 +15384,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"mincut_value", (PyCFunction) igraphmodule_Graph_mincut_value, METH_VARARGS | METH_KEYWORDS, - "mincut_value(source=-1, target=-1, capacity=None)\n\n" + "mincut_value(source=-1, target=-1, capacity=None)\n--\n\n" "Returns the minimum cut between the source and target vertices or within\n" "the whole graph.\n\n" "@param source: the source vertex ID. If negative, the calculation is\n" @@ -15394,7 +15398,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"mincut", (PyCFunction) igraphmodule_Graph_mincut, METH_VARARGS | METH_KEYWORDS, - "mincut(source=None, target=None, capacity=None)\n\n" + "mincut(source=None, target=None, capacity=None)\n--\n\n" "Calculates the minimum cut between the source and target vertices or\n" "within the whole graph.\n\n" "The minimum cut is the minimum set of edges that needs to be removed\n" @@ -15429,7 +15433,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"st_mincut", (PyCFunction) igraphmodule_Graph_st_mincut, METH_VARARGS | METH_KEYWORDS, - "st_mincut(source, target, capacity=None)\n\n" + "st_mincut(source, target, capacity=None)\n--\n\n" "Calculates the minimum cut between the source and target vertices in a\n" "graph.\n\n" "@param source: the source vertex ID\n" @@ -15447,7 +15451,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"gomory_hu_tree", (PyCFunction) igraphmodule_Graph_gomory_hu_tree, METH_VARARGS | METH_KEYWORDS, - "gomory_hu_tree(capacity=None)\n\n" + "gomory_hu_tree(capacity=None)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.gomory_hu_tree()\n\n" }, @@ -15457,7 +15461,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*********************/ {"all_minimal_st_separators", (PyCFunction) igraphmodule_Graph_all_minimal_st_separators, METH_NOARGS, - "all_minimal_st_separators()\n\n" + "all_minimal_st_separators()\n--\n\n" "Returns a list containing all the minimal s-t separators of a graph.\n\n" "A minimal separator is a set of vertices whose removal disconnects the graph,\n" "while the removal of any subset of the set keeps the graph connected.\n\n" @@ -15471,7 +15475,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"is_minimal_separator", (PyCFunction) igraphmodule_Graph_is_minimal_separator, METH_VARARGS | METH_KEYWORDS, - "is_minimal_separator(vertices)\n\n" + "is_minimal_separator(vertices)\n--\n\n" "Decides whether the given vertex set is a minimal separator.\n\n" "A minimal separator is a set of vertices whose removal disconnects the graph,\n" "while the removal of any subset of the set keeps the graph connected.\n\n" @@ -15481,14 +15485,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"is_separator", (PyCFunction) igraphmodule_Graph_is_separator, METH_VARARGS | METH_KEYWORDS, - "is_separator(vertices)\n\n" + "is_separator(vertices)\n--\n\n" "Decides whether the removal of the given vertices disconnects the graph.\n\n" "@param vertices: a single vertex ID or a list of vertex IDs\n" "@return: C{True} is the given vertex set is a separator, C{False} if not.\n"}, {"minimum_size_separators", (PyCFunction) igraphmodule_Graph_minimum_size_separators, METH_NOARGS, - "minimum_size_separators()\n\n" + "minimum_size_separators()\n--\n\n" "Returns a list containing all separator vertex sets of minimum size.\n\n" "A vertex set is a separator if its removal disconnects the graph. This method\n" "lists all the separators for which no smaller separator set exists in the\n" @@ -15504,7 +15508,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*******************/ {"cohesive_blocks", (PyCFunction) igraphmodule_Graph_cohesive_blocks, METH_NOARGS, - "cohesive_blocks()\n\n" + "cohesive_blocks()\n--\n\n" "Calculates the cohesive block structure of the graph.\n\n" "@attention: this function has a more convenient interface in class\n" " L{Graph} which wraps the result in a L{CohesiveBlocks} object.\n" @@ -15516,7 +15520,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /********************************/ {"cliques", (PyCFunction) igraphmodule_Graph_cliques, METH_VARARGS | METH_KEYWORDS, - "cliques(min=0, max=0)\n\n" + "cliques(min=0, max=0)\n--\n\n" "Returns some or all cliques of the graph as a list of tuples.\n\n" "A clique is a complete subgraph -- a set of vertices where an edge\n" "is present between any two of them (excluding loops)\n\n" @@ -15526,7 +15530,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " negative, no upper bound will be used."}, {"largest_cliques", (PyCFunction) igraphmodule_Graph_largest_cliques, METH_NOARGS, - "largest_cliques()\n\n" + "largest_cliques()\n--\n\n" "Returns the largest cliques of the graph as a list of tuples.\n\n" "Quite intuitively a clique is considered largest if there is no clique\n" "with more vertices in the whole graph. All largest cliques are maximal\n" @@ -15535,7 +15539,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " L{maximal_cliques()} for the maximal cliques"}, {"maximal_cliques", (PyCFunction) igraphmodule_Graph_maximal_cliques, METH_VARARGS | METH_KEYWORDS, - "maximal_cliques(min=0, max=0, file=None)\n\n" + "maximal_cliques(min=0, max=0, file=None)\n--\n\n" "Returns the maximal cliques of the graph as a list of tuples.\n\n" "A maximal clique is a clique which can't be extended by adding any other\n" "vertex to it. A maximal clique is not necessarily one of the largest\n" @@ -15554,14 +15558,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@see: L{largest_cliques()} for the largest cliques."}, {"clique_number", (PyCFunction) igraphmodule_Graph_clique_number, METH_NOARGS, - "clique_number()\n\n" + "clique_number() -> int\n--\n\n" "Returns the clique number of the graph.\n\n" "The clique number of the graph is the size of the largest clique.\n\n" "@see: L{largest_cliques()} for the largest cliques."}, {"independent_vertex_sets", (PyCFunction) igraphmodule_Graph_independent_vertex_sets, METH_VARARGS | METH_KEYWORDS, - "independent_vertex_sets(min=0, max=0)\n\n" + "independent_vertex_sets(min=0, max=0)\n--\n\n" "Returns some or all independent vertex sets of the graph as a list of tuples.\n\n" "Two vertices are independent if there is no edge between them. Members\n" "of an independent vertex set are mutually independent.\n\n" @@ -15572,7 +15576,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"largest_independent_vertex_sets", (PyCFunction) igraphmodule_Graph_largest_independent_vertex_sets, METH_NOARGS, - "largest_independent_vertex_sets()\n\n" + "largest_independent_vertex_sets()\n--\n\n" "Returns the largest independent vertex sets of the graph as a list of tuples.\n\n" "Quite intuitively an independent vertex set is considered largest if\n" "there is no other set with more vertices in the whole graph. All largest\n" @@ -15584,7 +15588,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"maximal_independent_vertex_sets", (PyCFunction) igraphmodule_Graph_maximal_independent_vertex_sets, METH_NOARGS, - "maximal_independent_vertex_sets()\n\n" + "maximal_independent_vertex_sets()\n--\n\n" "Returns the maximal independent vertex sets of the graph as a list of tuples.\n\n" "A maximal independent vertex set is an independent vertex set\n" "which can't be extended by adding any other vertex to it. A maximal\n" @@ -15599,7 +15603,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"independence_number", (PyCFunction) igraphmodule_Graph_independence_number, METH_NOARGS, - "independence_number()\n\n" + "independence_number() -> int\n--\n\n" "Returns the independence number of the graph.\n\n" "The independence number of the graph is the size of the largest\n" "independent vertex set.\n\n" @@ -15611,7 +15615,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*********************************/ {"modularity", (PyCFunction) igraphmodule_Graph_modularity, METH_VARARGS | METH_KEYWORDS, - "modularity(membership, weights=None, resolution=1, directed=True)\n\n" + "modularity(membership, weights=None, resolution=1, directed=True) -> float\n--\n\n" "Calculates the modularity of the graph with respect to some vertex types.\n\n" "The modularity of a graph w.r.t. some division measures how good the\n" "division is, or how separated are the different vertex types from each\n" @@ -15649,7 +15653,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"coreness", (PyCFunction) igraphmodule_Graph_coreness, METH_VARARGS | METH_KEYWORDS, - "coreness(mode=ALL)\n\n" + "coreness(mode=ALL) -> Sequence[int]\n--\n\n" "Finds the coreness (shell index) of the vertices of the network.\n\n" "The M{k}-core of a graph is a maximal subgraph in which each vertex\n" "has at least degree k. (Degree here means the degree in the\n" @@ -15665,7 +15669,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_fastgreedy", (PyCFunction) igraphmodule_Graph_community_fastgreedy, METH_VARARGS | METH_KEYWORDS, - "community_fastgreedy(weights=None)\n\n" + "community_fastgreedy(weights=None)\n--\n\n" "Finds the community structure of the graph according to the algorithm of\n" "Clauset et al based on the greedy optimization of modularity.\n\n" "This is a bottom-up algorithm: initially every vertex belongs to a separate\n" @@ -15688,7 +15692,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_infomap", (PyCFunction) igraphmodule_Graph_community_infomap, METH_VARARGS | METH_KEYWORDS, - "community_infomap(edge_weights=None, vertex_weights=None, trials=10)\n\n" + "community_infomap(edge_weights=None, vertex_weights=None, trials=10)\n--\n\n" "Finds the community structure of the network according to the Infomap\n" "method of Martin Rosvall and Carl T. Bergstrom.\n\n" "See U{http://www.mapequation.org} for a visualization of the algorithm\n" @@ -15711,7 +15715,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_label_propagation", (PyCFunction) igraphmodule_Graph_community_label_propagation, METH_VARARGS | METH_KEYWORDS, - "community_label_propagation(weights=None, initial=None, fixed=None)\n\n" + "community_label_propagation(weights=None, initial=None, fixed=None)\n--\n\n" "Finds the community structure of the graph according to the label\n" "propagation method of Raghavan et al.\n\n" "Initially, each vertex is assigned a different label. After that,\n" @@ -15744,7 +15748,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"community_leading_eigenvector", (PyCFunction) igraphmodule_Graph_community_leading_eigenvector, METH_VARARGS | METH_KEYWORDS, - "community_leading_eigenvector(n=-1, arpack_options=None, weights=None)\n\n" + "community_leading_eigenvector(n=-1, arpack_options=None, weights=None)\n--\n\n" "A proper implementation of Newman's eigenvector community structure\n" "detection. Each split is done by maximizing the modularity regarding\n" "the original network. See the reference for details.\n\n" @@ -15768,7 +15772,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_multilevel", (PyCFunction) igraphmodule_Graph_community_multilevel, METH_VARARGS | METH_KEYWORDS, - "community_multilevel(weights=None, return_levels=True, resolution=1)\n\n" + "community_multilevel(weights=None, return_levels=True, resolution=1)\n--\n\n" "Finds the community structure of the graph according to the multilevel\n" "algorithm of Blondel et al. This is a bottom-up algorithm: initially\n" "every vertex belongs to a separate community, and vertices are moved\n" @@ -15804,7 +15808,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_edge_betweenness", (PyCFunction)igraphmodule_Graph_community_edge_betweenness, METH_VARARGS | METH_KEYWORDS, - "community_edge_betweenness(directed=True, weights=None)\n\n" + "community_edge_betweenness(directed=True, weights=None)\n--\n\n" "Community structure detection based on the betweenness of the edges in\n" "the network. This algorithm was invented by M Girvan and MEJ Newman,\n" "see: M Girvan and MEJ Newman: Community structure in social and biological\n" @@ -15826,7 +15830,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_optimal_modularity", (PyCFunction) igraphmodule_Graph_community_optimal_modularity, METH_VARARGS | METH_KEYWORDS, - "community_optimal_modularity(weights=None)\n\n" + "community_optimal_modularity(weights=None)\n--\n\n" "Calculates the optimal modularity score of the graph and the\n" "corresponding community structure.\n\n" "This function uses the GNU Linear Programming Kit to solve a large\n" @@ -15845,7 +15849,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "community_spinglass(weights=None, spins=25, parupdate=False, " "start_temp=1, stop_temp=0.01, cool_fact=0.99, update_rule=\"config\", " - "gamma=1, implementation=\"orig\", lambda=1)\n\n" + "gamma=1, implementation=\"orig\", lambda=1)\n--\n\n" "Finds the community structure of the graph according to the spinglass\n" "community detection method of Reichardt & Bornholdt.\n\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" @@ -15883,35 +15887,35 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_leiden", (PyCFunction) igraphmodule_Graph_community_leiden, METH_VARARGS | METH_KEYWORDS, - "community_leiden(edge_weights=None, node_weights=None, \n" - " resolution_parameter=1.0, normalize_resolution=False, beta=0.01, \n" - " initial_membership=None, n_iterations=2)\n\n" - " Finds the community structure of the graph using the\n" - " Leiden algorithm of Traag, van Eck & Waltman \n\n" - " @param edge_weights: edge weights to be used. Can be a sequence or\n" - " iterable or even an edge attribute name.\n" - " @param node_weights: the node weights used in the Leiden algorithm.\n" - " @param resolution_parameter: the resolution parameter to use.\n" - " Higher resolutions lead to more smaller communities, while \n" - " lower resolutions lead to fewer larger communities.\n" - " @param normalize_resolution: if set to true, the resolution parameter\n" - " will be divided by the sum of the node weights. If this is not\n" - " supplied, it will default to the node degree, or weighted degree\n" - " in case edge_weights are supplied.\n" - " @param node_weights: the node weights used in the Leiden algorithm.\n" - " @param beta: parameter affecting the randomness in the Leiden \n" - " algorithm. This affects only the refinement step of the algorithm.\n" - " @param initial_membership: if provided, the Leiden algorithm\n" - " will try to improve this provided membership. If no argument is\n" - " provided, the aglorithm simply starts from the singleton partition.\n" - " @param n_iterations: the number of iterations to iterate the Leiden\n" - " algorithm. Each iteration may improve the partition further.\n" - " @return: the community membership vector.\n" + "community_leiden(edge_weights=None, node_weights=None, " + "resolution_parameter=1.0, normalize_resolution=False, beta=0.01, " + "initial_membership=None, n_iterations=2)\n--\n\n" + "Finds the community structure of the graph using the Leiden algorithm of\n" + "Traag, van Eck & Waltman.\n\n" + "@param edge_weights: edge weights to be used. Can be a sequence or\n" + " iterable or even an edge attribute name.\n" + "@param node_weights: the node weights used in the Leiden algorithm.\n" + "@param resolution_parameter: the resolution parameter to use.\n" + " Higher resolutions lead to more smaller communities, while \n" + " lower resolutions lead to fewer larger communities.\n" + "@param normalize_resolution: if set to true, the resolution parameter\n" + " will be divided by the sum of the node weights. If this is not\n" + " supplied, it will default to the node degree, or weighted degree\n" + " in case edge_weights are supplied.\n" + "@param node_weights: the node weights used in the Leiden algorithm.\n" + "@param beta: parameter affecting the randomness in the Leiden \n" + " algorithm. This affects only the refinement step of the algorithm.\n" + "@param initial_membership: if provided, the Leiden algorithm\n" + " will try to improve this provided membership. If no argument is\n" + " provided, the aglorithm simply starts from the singleton partition.\n" + "@param n_iterations: the number of iterations to iterate the Leiden\n" + " algorithm. Each iteration may improve the partition further.\n" + "@return: the community membership vector.\n" }, {"community_walktrap", (PyCFunction) igraphmodule_Graph_community_walktrap, METH_VARARGS | METH_KEYWORDS, - "community_walktrap(weights=None, steps=None)\n\n" + "community_walktrap(weights=None, steps=None)\n--\n\n" "Finds the community structure of the graph according to the random walk\n" "method of Latapy & Pons.\n\n" "The basic idea of the algorithm is that short random walks tend to stay\n" @@ -15934,18 +15938,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*************/ {"_is_matching", (PyCFunction)igraphmodule_Graph_is_matching, METH_VARARGS | METH_KEYWORDS, - "_is_matching(matching, types=None)\n\n" + "_is_matching(matching, types=None)\n--\n\n" "Internal function, undocumented.\n\n" }, {"_is_maximal_matching", (PyCFunction)igraphmodule_Graph_is_maximal_matching, METH_VARARGS | METH_KEYWORDS, - "_is_maximal_matching(matching, types=None)\n\n" + "_is_maximal_matching(matching, types=None)\n--\n\n" "Internal function, undocumented.\n\n" "Use L{Matching.is_maximal} instead.\n" }, {"_maximum_bipartite_matching", (PyCFunction)igraphmodule_Graph_maximum_bipartite_matching, METH_VARARGS | METH_KEYWORDS, - "_maximum_bipartite_matching(types, weights=None)\n\n" + "_maximum_bipartite_matching(types, weights=None)\n--\n\n" "Internal function, undocumented.\n\n" "@see: L{Graph.maximum_bipartite_matching}\n" }, @@ -15955,7 +15959,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /****************/ {"random_walk", (PyCFunction)igraphmodule_Graph_random_walk, METH_VARARGS | METH_KEYWORDS, - "random_walk(start, steps, mode=\"out\", stuck=\"return\")\n\n" + "random_walk(start, steps, mode=\"out\", stuck=\"return\")\n--\n\n" "Performs a random walk of a given length from a given node.\n\n" "@param start: the starting vertex of the walk\n" "@param steps: the number of steps that the random walk should take\n" @@ -15986,7 +15990,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"__graph_as_cobject", (PyCFunction) igraphmodule_Graph___graph_as_cobject__, METH_VARARGS | METH_KEYWORDS, - "__graph_as_cobject()\n\n" + "__graph_as_cobject()\n--\n\n" "Returns the igraph graph encapsulated by the Python object as\n" "a PyCObject\n\n." "A PyCObject is practically a regular C pointer, wrapped in a\n" @@ -15998,7 +16002,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"_raw_pointer", (PyCFunction) igraphmodule_Graph__raw_pointer, METH_NOARGS, - "_raw_pointer()\n\n" + "_raw_pointer() -> int\n--\n\n" "Returns the memory address of the igraph graph encapsulated by the Python\n" "object as an ordinary Python integer.\n\n" "This function should not be used directly by igraph users, it is useful\n" @@ -16008,7 +16012,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"__register_destructor", (PyCFunction) igraphmodule_Graph___register_destructor__, METH_VARARGS | METH_KEYWORDS, - "__register_destructor(destructor)\n\n" + "__register_destructor(destructor) -> None\n--\n\n" "Registers a destructor to be called when the object is freed by\n" "Python. This function should not be used directly by igraph users."}, @@ -16090,7 +16094,7 @@ PyNumberMethods igraphmodule_Graph_as_number = { */ PyTypeObject igraphmodule_GraphType = { PyVarObject_HEAD_INIT(0, 0) - "igraph.Graph", /* tp_name */ + "igraph._igraph.GraphBase", /* tp_name */ sizeof(igraphmodule_GraphObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) igraphmodule_Graph_dealloc, /* tp_dealloc */ @@ -16117,9 +16121,6 @@ PyTypeObject igraphmodule_GraphType = { Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "Low-level representation of a graph.\n\n" "Don't use it directly, use L{igraph.Graph} instead.\n\n" - "@undocumented: _Bipartite, _Full_Bipartite, _GRG, _Incidence, _is_matching,\n" - " _is_maximal_matching, _layout_sugiyama, _maximum_bipartite_matching,\n" - " _spanning_tree\n" "@deffield ref: Reference", /* tp_doc */ (traverseproc) igraphmodule_Graph_traverse, /* tp_traverse */ (inquiry) igraphmodule_Graph_clear, /* tp_clear */ diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 86cae3747..51091ccc5 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -606,19 +606,19 @@ static PyMethodDef igraphmodule_methods[] = { {"community_to_membership", (PyCFunction)igraphmodule_community_to_membership, METH_VARARGS | METH_KEYWORDS, - "community_to_membership(merges, nodes, steps, return_csize=False)" + "community_to_membership(merges, nodes, steps, return_csize=False)\n--\n\n" }, {"_compare_communities", (PyCFunction)igraphmodule_compare_communities, METH_VARARGS | METH_KEYWORDS, - "_compare_communities(comm1, comm2, method=\"vi\")" + "_compare_communities(comm1, comm2, method=\"vi\")\n--\n\n" }, {"_power_law_fit", (PyCFunction)igraphmodule_power_law_fit, METH_VARARGS | METH_KEYWORDS, - "_power_law_fit(data, xmin=-1, force_continuous=False)" + "_power_law_fit(data, xmin=-1, force_continuous=False)\n--\n\n" }, {"convex_hull", (PyCFunction)igraphmodule_convex_hull, METH_VARARGS | METH_KEYWORDS, - "convex_hull(vs, coords=False)\n\n" + "convex_hull(vs, coords=False)\n--\n\n" "Calculates the convex hull of a given point set.\n\n" "@param vs: the point set as a list of lists\n" "@param coords: if C{True}, the function returns the\n" @@ -630,7 +630,7 @@ static PyMethodDef igraphmodule_methods[] = }, {"is_degree_sequence", (PyCFunction)igraphmodule_is_degree_sequence, METH_VARARGS | METH_KEYWORDS, - "is_degree_sequence(out_deg, in_deg=None)\n\n" + "is_degree_sequence(out_deg, in_deg=None)\n--\n\n" "Deprecated since 0.9 in favour of L{is_graphical()}.\n\n" "Returns whether a list of degrees can be a degree sequence of some graph.\n\n" "Note that it is not required for the graph to be simple; in other words,\n" @@ -650,7 +650,7 @@ static PyMethodDef igraphmodule_methods[] = }, {"is_graphical", (PyCFunction)igraphmodule_is_graphical, METH_VARARGS | METH_KEYWORDS, - "is_graphical(out_deg, in_deg=None, loops=False, multiple=False)\n\n" + "is_graphical(out_deg, in_deg=None, loops=False, multiple=False)\n--\n\n" "Returns whether a list of degrees can be a degree sequence of some graph,\n" "with or without multiple and loop edges, depending on the allowed edge types\n" "in the remaining arguments.\n\n" @@ -665,7 +665,7 @@ static PyMethodDef igraphmodule_methods[] = }, {"is_graphical_degree_sequence", (PyCFunction)igraphmodule_is_graphical_degree_sequence, METH_VARARGS | METH_KEYWORDS, - "is_graphical_degree_sequence(out_deg, in_deg=None)\n\n" + "is_graphical_degree_sequence(out_deg, in_deg=None)\n--\n\n" "Deprecated since 0.9 in favour of L{is_graphical()}.\n\n" "Returns whether a list of degrees can be a degree sequence of some simple graph.\n\n" "Note that it is required for the graph to be simple; in other words,\n" @@ -679,7 +679,7 @@ static PyMethodDef igraphmodule_methods[] = " degree sequence, C{False} otherwise.\n" }, {"set_progress_handler", igraphmodule_set_progress_handler, METH_O, - "set_progress_handler(handler)\n\n" + "set_progress_handler(handler)\n--\n\n" "Sets the handler to be called when igraph is performing a long operation.\n" "@param handler: the progress handler function. It must accept two\n" " arguments, the first is the message informing the user about\n" @@ -687,7 +687,7 @@ static PyMethodDef igraphmodule_methods[] = " progress information (a percentage).\n" }, {"set_random_number_generator", igraph_rng_Python_set_generator, METH_O, - "set_random_number_generator(generator)\n\n" + "set_random_number_generator(generator)\n--\n\n" "Sets the random number generator used by igraph.\n" "@param generator: the generator to be used. It must be a Python object\n" " with at least three attributes: C{random}, C{randint} and C{gauss}.\n" @@ -701,7 +701,7 @@ static PyMethodDef igraphmodule_methods[] = " for random numbers, but you cannot set its seed or save its state.\n" }, {"set_status_handler", igraphmodule_set_status_handler, METH_O, - "set_status_handler(handler)\n\n" + "set_status_handler(handler)\n--\n\n" "Sets the handler to be called when igraph tries to display a status\n" "message.\n\n" "This is used to communicate the progress of some calculations where\n" @@ -713,28 +713,26 @@ static PyMethodDef igraphmodule_methods[] = }, {"_split_join_distance", (PyCFunction)igraphmodule_split_join_distance, METH_VARARGS | METH_KEYWORDS, - "_split_join_distance(comm1, comm2)" + "_split_join_distance(comm1, comm2)\n--\n\n" }, {"_disjoint_union", (PyCFunction)igraphmodule__disjoint_union, METH_VARARGS | METH_KEYWORDS, - "_disjoint_union(graphs)" + "_disjoint_union(graphs)\n--\n\n" }, {"_union", (PyCFunction)igraphmodule__union, METH_VARARGS | METH_KEYWORDS, - "_union(graphs, edgemaps)" + "_union(graphs, edgemaps)\n--\n\n" }, {"_intersection", (PyCFunction)igraphmodule__intersection, METH_VARARGS | METH_KEYWORDS, - "_intersection(graphs, edgemaps)" + "_intersection(graphs, edgemaps)\n--\n\n" }, {NULL, NULL, 0, NULL} }; #define MODULE_DOCS \ "Low-level Python interface for the igraph library. " \ - "Should not be used directly.\n\n" \ - "@undocumented: community_to_membership, _compare_communities, _power_law_fit, " \ - "_split_join_distance, _union, _intersection, _disjoint_union" + "Should not be used directly.\n" /** * Module definition table (only for Python 3.x) diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 834541834..138a225b1 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -750,17 +750,17 @@ GRAPH_PROXY_METHOD_PP(successors, "successors", _convert_to_vertex_list); PyMethodDef igraphmodule_Vertex_methods[] = { {"attributes", (PyCFunction)igraphmodule_Vertex_attributes, METH_NOARGS, - "attributes() -> dict\n\n" + "attributes() -> dict\n--\n\n" "Returns a dict of attribute names and values for the vertex\n" }, {"attribute_names", (PyCFunction)igraphmodule_Vertex_attribute_names, METH_NOARGS, - "attribute_names() -> list\n\n" + "attribute_names() -> list\n--\n\n" "Returns the list of vertex attribute names\n" }, {"update_attributes", (PyCFunction)igraphmodule_Vertex_update_attributes, METH_VARARGS | METH_KEYWORDS, - "update_attributes(E, **F) -> None\n\n" + "update_attributes(E, **F) -> None\n--\n\n" "Updates the attributes of the vertex from dict/iterable E and F.\n\n" "If E has a C{keys()} method, it does: C{for k in E: self[k] = E[k]}.\n" "If E lacks a C{keys()} method, it does: C{for (k, v) in E: self[k] = v}.\n" diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 533366e37..88e476e7d 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -899,17 +899,17 @@ PyObject* igraphmodule_VertexSeq__reindex_names(igraphmodule_VertexSeqObject* se PyMethodDef igraphmodule_VertexSeq_methods[] = { {"attribute_names", (PyCFunction)igraphmodule_VertexSeq_attribute_names, METH_NOARGS, - "attribute_names() -> list\n\n" + "attribute_names() -> list\n--\n\n" "Returns the attribute name list of the graph's vertices\n" }, {"find", (PyCFunction)igraphmodule_VertexSeq_find, METH_VARARGS, - "find(condition) -> Vertex\n\n" + "find(condition) -> Vertex\n--\n\n" "For internal use only.\n" }, {"get_attribute_values", (PyCFunction)igraphmodule_VertexSeq_get_attribute_values, METH_O, - "get_attribute_values(attrname) -> list\n" + "get_attribute_values(attrname) -> list\n--\n\n" "Returns the value of a given vertex attribute for all vertices in a list.\n\n" "The values stored in the list are exactly the same objects that are stored\n" "in the vertex attribute, meaning that in the case of mutable objects,\n" @@ -920,17 +920,18 @@ PyMethodDef igraphmodule_VertexSeq_methods[] = { }, {"set_attribute_values", (PyCFunction)igraphmodule_VertexSeq_set_attribute_values, METH_VARARGS | METH_KEYWORDS, - "set_attribute_values(attrname, values) -> list\n" + "set_attribute_values(attrname, values) -> list\n--\n\n" "Sets the value of a given vertex attribute for all vertices\n\n" "@param attrname: the name of the attribute\n" "@param values: the new attribute values in a list\n" }, {"select", (PyCFunction)igraphmodule_VertexSeq_select, METH_VARARGS, - "select(...) -> VertexSeq\n\n" + "select(...) -> VertexSeq\n--\n\n" "For internal use only.\n" }, {"_reindex_names", (PyCFunction)igraphmodule_VertexSeq__reindex_names, METH_NOARGS, + "_reindex_names() -> None\n--\n\n" "Re-creates the dictionary that maps vertex names to IDs.\n\n" "For internal use only.\n" }, diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 9d10f92c0..37a45534c 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2,9 +2,6 @@ # -*- coding: utf-8 -*- """ IGraph library. - -@undocumented: deprecated, _graphmethod, _add_proxy_methods, _layout_method_wrapper, - _3d_version_for """ @@ -163,7 +160,7 @@ class Graph(GraphBase): """Generic graph. This class is built on top of L{GraphBase}, so the order of the - methods in the Epydoc documentation is a little bit obscure: + methods in the generated API documentation is a little bit obscure: inherited methods come after the ones implemented directly in the subclass. L{Graph} provides many functions that L{GraphBase} does not, mostly because these functions are not speed critical and they were diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 4217f3dce..f1b57e345 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -73,8 +73,6 @@ class Clustering(object): >>> cluster_list = list(cl) >>> print(cluster_list) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10]] - - @undocumented: _formatted_cluster_iterator """ def __init__(self, membership, params=None): @@ -226,8 +224,6 @@ class VertexClustering(Clustering): @note: since this class is linked to a L{Graph}, destroying the graph by the C{del} operator does not free the memory occupied by the graph if there exists a L{VertexClustering} that references the L{Graph}. - - @undocumented: _formatted_cluster_iterator """ # Allow None to be passed to __plot__ as the "palette" keyword argument @@ -567,8 +563,6 @@ class Dendrogram(object): 3 -+ | | | 4 -+---+--- - - @undocumented: _item_box_size, _plot_item, _traverse_inorder """ def __init__(self, merges): @@ -1119,8 +1113,6 @@ class Cover(object): >>> cover = Cover(clustering) >>> list(clustering) == list(cover) True - - @undocumented: _formatted_cluster_iterator """ def __init__(self, clusters, n=0): @@ -1247,8 +1239,6 @@ class VertexCover(Cover): @note: since this class is linked to a L{Graph}, destroying the graph by the C{del} operator does not free the memory occupied by the graph if there exists a L{VertexCover} that references the L{Graph}. - - @undocumented: _formatted_cluster_iterator """ def __init__(self, graph, clusters=None): From 3654508b83c5e20eb06bc30ddeee9687e4c03836 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 02:01:34 +0100 Subject: [PATCH 0406/1892] fix: removed py2compat.h and other Python 2.x compatibility hacks --- src/_igraph/arpackobject.c | 45 +++++---- src/_igraph/attributes.c | 87 ++++------------ src/_igraph/bfsiter.c | 7 +- src/_igraph/convert.c | 154 ++++++++++------------------- src/_igraph/dfsiter.c | 7 +- src/_igraph/edgeobject.c | 36 ++----- src/_igraph/edgeobject.h | 3 +- src/_igraph/edgeseqobject.c | 17 ++-- src/_igraph/filehandle.c | 180 +--------------------------------- src/_igraph/graphobject.c | 97 +++++------------- src/_igraph/igraphmodule.c | 30 +----- src/_igraph/indexing.c | 9 +- src/_igraph/py2compat.c | 146 --------------------------- src/_igraph/py2compat.h | 94 ------------------ src/_igraph/pyhelpers.c | 87 +++++++++++++--- src/_igraph/pyhelpers.h | 8 ++ src/_igraph/random.c | 3 +- src/_igraph/vertexobject.c | 37 ++----- src/_igraph/vertexobject.h | 3 +- src/_igraph/vertexseqobject.c | 19 ++-- 20 files changed, 258 insertions(+), 811 deletions(-) delete mode 100644 src/_igraph/py2compat.c delete mode 100644 src/_igraph/py2compat.h diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 96eefa340..918a2f697 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -23,7 +23,6 @@ #include "arpackobject.h" #include "graphobject.h" #include "error.h" -#include "py2compat.h" PyObject* igraphmodule_arpack_options_default; @@ -70,45 +69,45 @@ PyObject* igraphmodule_ARPACKOptions_getattr( if (strcmp(attrname, "bmat") == 0) { char buf[2] = { self->params_out.bmat[0], 0 }; - result=PyString_FromString(buf); + result=PyUnicode_FromString(buf); } else if (strcmp(attrname, "n") == 0) { - result=PyInt_FromLong(self->params_out.n); + result=PyLong_FromLong(self->params_out.n); } else if (strcmp(attrname, "which") == 0) { char buf[3] = { self->params.which[0], self->params.which[1], 0 }; - result=PyString_FromString(buf); + result=PyUnicode_FromString(buf); } else if (strcmp(attrname, "nev") == 0) { - result=PyInt_FromLong(self->params.nev); + result=PyLong_FromLong(self->params.nev); } else if (strcmp(attrname, "tol") == 0) { result=PyFloat_FromDouble((double)self->params.tol); } else if (strcmp(attrname, "ncv") == 0) { - result=PyInt_FromLong(self->params.ncv); + result=PyLong_FromLong(self->params.ncv); } else if (strcmp(attrname, "ldv") == 0) { - result=PyInt_FromLong(self->params.ldv); + result=PyLong_FromLong(self->params.ldv); } else if (strcmp(attrname, "ishift") == 0) { - result=PyInt_FromLong(self->params.ishift); + result=PyLong_FromLong(self->params.ishift); } else if (strcmp(attrname, "maxiter") == 0 || strcmp(attrname, "mxiter") == 0) { - result=PyInt_FromLong(self->params.mxiter); + result=PyLong_FromLong(self->params.mxiter); } else if (strcmp(attrname, "nb") == 0) { - result=PyInt_FromLong(self->params.nb); + result=PyLong_FromLong(self->params.nb); } else if (strcmp(attrname, "mode") == 0) { - result=PyInt_FromLong(self->params.mode); + result=PyLong_FromLong(self->params.mode); } else if (strcmp(attrname, "start") == 0) { - result=PyInt_FromLong(self->params.start); + result=PyLong_FromLong(self->params.start); } else if (strcmp(attrname, "sigma") == 0) { result=PyFloat_FromDouble((double)self->params.sigma); } else if (strcmp(attrname, "info") == 0) { - result=PyInt_FromLong(self->params_out.info); + result=PyLong_FromLong(self->params_out.info); } else if (strcmp(attrname, "iter") == 0) { - result=PyInt_FromLong(self->params_out.iparam[2]); + result=PyLong_FromLong(self->params_out.iparam[2]); } else if (strcmp(attrname, "nconv") == 0) { - result=PyInt_FromLong(self->params_out.iparam[4]); + result=PyLong_FromLong(self->params_out.iparam[4]); } else if (strcmp(attrname, "numop") == 0) { - result=PyInt_FromLong(self->params_out.iparam[8]); + result=PyLong_FromLong(self->params_out.iparam[8]); } else if (strcmp(attrname, "numopb") == 0) { - result=PyInt_FromLong(self->params_out.iparam[9]); + result=PyLong_FromLong(self->params_out.iparam[9]); } else if (strcmp(attrname, "numreo") == 0) { - result=PyInt_FromLong(self->params_out.iparam[10]); + result=PyLong_FromLong(self->params_out.iparam[10]); } else { PyErr_SetString(PyExc_AttributeError, attrname); } @@ -127,8 +126,8 @@ int igraphmodule_ARPACKOptions_setattr( } if (strcmp(attrname, "maxiter") == 0 || strcmp(attrname, "mxiter") == 0) { - if (PyInt_Check(value)) { - long int n=PyInt_AsLong(value); + if (PyLong_Check(value)) { + long int n=PyLong_AsLong(value); if (n>0) self->params.mxiter=(igraph_integer_t)n; else { @@ -140,8 +139,8 @@ int igraphmodule_ARPACKOptions_setattr( return -1; } } else if (strcmp(attrname, "tol") == 0) { - if (PyInt_Check(value)) { - self->params.tol = (igraph_real_t) PyInt_AsLong(value); + if (PyLong_Check(value)) { + self->params.tol = (igraph_real_t) PyLong_AsLong(value); } else if (PyFloat_Check(value)) { self->params.tol = (igraph_real_t) PyFloat_AsDouble(value); } else { @@ -180,7 +179,7 @@ PyObject* igraphmodule_ARPACKOptions_str( igraphmodule_ARPACKOptionsObject *self) { PyObject *s; - s=PyString_FromFormat("ARPACK parameters"); + s=PyUnicode_FromFormat("ARPACK parameters"); return s; } diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 4090bc04f..8a8cf79a5 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -24,7 +24,6 @@ #include "attributes.h" #include "common.h" #include "convert.h" -#include "py2compat.h" #include "pyhelpers.h" int igraphmodule_i_attribute_struct_init(igraphmodule_i_attribute_struct *attrs) { @@ -76,7 +75,7 @@ int igraphmodule_i_attribute_struct_index_vertex_names( n = PyList_Size(name_list) - 1; while (n >= 0) { key = PyList_GET_ITEM(name_list, n); /* we don't own a reference to key */ - value = PyInt_FromLong(n); /* we do own a reference to value */ + value = PyLong_FromLong(n); /* we do own a reference to value */ if (value == 0) return 1; @@ -88,10 +87,7 @@ int igraphmodule_i_attribute_struct_index_vertex_names( PyExc_RuntimeError, "error while indexing vertex names; did you accidentally try to " "use a non-hashable object as a vertex name earlier?" -#ifdef IGRAPH_PYTHON3 - /* %R is not supported in Python 2.x */ " Check the name of vertex %R (%R)", value, key -#endif ); } @@ -126,33 +122,13 @@ void igraphmodule_index_vertex_names(igraph_t *graph, igraph_bool_t force) { } int igraphmodule_PyObject_matches_attribute_record(PyObject* object, igraph_attribute_record_t* record) { -#ifndef IGRAPH_PYTHON3 - int result; -#endif - if (record == 0) { return 0; } - if (PyString_Check(object)) { - return PyString_IsEqualToASCIIString(object, record->name); - } - -#ifndef IGRAPH_PYTHON3 - /* On Python 2.x, we need to handle Unicode strings as well because - * the user might use 'from __future__ import unicode_literals', which - * would turn some igraph attribute names into Unicode strings */ if (PyUnicode_Check(object)) { - PyObject* ascii = PyUnicode_AsASCIIString(object); - if (ascii == 0) { - return 0; - } - - result = PyString_IsEqualToASCIIString(ascii, record->name); - Py_DECREF(ascii); - return result; + return PyUnicode_IsEqualToASCIIString(object, record->name); } -#endif return 0; } @@ -170,21 +146,11 @@ int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_inte } if (o_vid == NULL) { -#ifdef IGRAPH_PYTHON3 PyErr_Format(PyExc_ValueError, "no such vertex: %R", o); -#else - PyObject* s = PyObject_Repr(o); - if (s) { - PyErr_Format(PyExc_ValueError, "no such vertex: %s", PyString_AS_STRING(s)); - Py_DECREF(s); - } else { - PyErr_Format(PyExc_ValueError, "no such vertex: %p", o); - } -#endif return 1; } - if (!PyInt_Check(o_vid)) { + if (!PyLong_Check(o_vid)) { PyErr_SetString(PyExc_ValueError, "non-numeric vertex ID assigned to vertex name. This is most likely a bug."); return 1; } @@ -350,9 +316,9 @@ static int igraphmodule_i_attribute_init(igraph_t *graph, igraph_vector_ptr_t *a case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s); if (s == 0) - value=PyString_FromString(""); + value=PyUnicode_FromString(""); else - value=PyString_FromString(s); + value=PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: value=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[0] ? Py_True : Py_False; @@ -498,7 +464,7 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, i break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyString_FromString(s); + o=PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; @@ -557,7 +523,7 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, i break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyString_FromString(s); + o=PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; @@ -679,7 +645,7 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyString_FromString(s); + o=PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; @@ -740,7 +706,7 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyString_FromString(s); + o=PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; @@ -888,11 +854,7 @@ static PyObject* igraphmodule_i_ac_builtin_func(PyObject* values, PyObject* func = 0; if (builtin_module_dict == 0) { -#ifdef IGRAPH_PYTHON3 PyObject* builtin_module = PyImport_ImportModule("builtins"); -#else - PyObject* builtin_module = PyImport_ImportModule("__builtin__"); -#endif if (builtin_module == 0) return 0; builtin_module_dict = PyModule_GetDict(builtin_module); @@ -1205,9 +1167,9 @@ static int igraphmodule_i_attribute_combine_dicts(PyObject *dict, /* Collect what to do for each attribute in the source dict */ pos = 0; i = 0; while (PyDict_Next(dict, &pos, &key, &value)) { - todo[i].name = PyString_CopyAsString(key); + todo[i].name = PyUnicode_CopyAsString(key); if (todo[i].name == 0) - IGRAPH_ERROR("PyString_CopyAsString failed", IGRAPH_FAILURE); + IGRAPH_ERROR("PyUnicode_CopyAsString failed", IGRAPH_FAILURE); igraph_attribute_combination_query(comb, todo[i].name, &todo[i].type, &todo[i].func); i++; @@ -1222,7 +1184,7 @@ static int igraphmodule_i_attribute_combine_dicts(PyObject *dict, PyObject *newvalue; /* Safety check */ - if (!PyString_IsEqualToASCIIString(key, todo[i].name)) { + if (!PyUnicode_IsEqualToASCIIString(key, todo[i].name)) { IGRAPH_ERROR("PyDict_Next iteration order not consistent. " "This should never happen. Please report the bug to the igraph " "developers!", IGRAPH_FAILURE); @@ -1276,7 +1238,7 @@ static int igraphmodule_i_attribute_combine_dicts(PyObject *dict, break; case IGRAPH_ATTRIBUTE_COMBINE_CONCAT: - empty_str = PyString_FromString(""); + empty_str = PyUnicode_FromString(""); func = PyObject_GetAttrString(empty_str, "join"); newvalue = igraphmodule_i_ac_func(value, merges, func); Py_DECREF(func); @@ -1559,7 +1521,6 @@ int igraphmodule_i_get_string_graph_attr(const igraph_t *graph, IGRAPH_ERROR("No such attribute", IGRAPH_EINVAL); IGRAPH_CHECK(igraph_strvector_resize(value, 1)); -#ifdef IGRAPH_PYTHON3 /* For Python 3.x, we simply call PyObject_Str, which produces a * Unicode string, then encode it into UTF-8, except when we * already have a PyBytes object -- this is assumed to be in @@ -1576,25 +1537,11 @@ int igraphmodule_i_get_string_graph_attr(const igraph_t *graph, Py_DECREF(unicode); } -#else - /* For Python 2.x, we check whether we have received a string or a - * Unicode string. Unicode strings are encoded into UTF-8, strings - * are used intact. - */ - if (PyUnicode_Check(o)) { - str = PyUnicode_AsEncodedString(o, "utf-8", "xmlcharrefreplace"); - } else { - str = PyObject_Str(o); - } -#endif - - if (str == 0) + if (str == 0) { IGRAPH_ERROR("Internal error in PyObject_Str", IGRAPH_EINVAL); -#ifdef IGRAPH_PYTHON3 + } + c_str = PyBytes_AS_STRING(str); -#else - c_str = PyString_AS_STRING(str); -#endif IGRAPH_CHECK(igraph_strvector_set(value, 0, c_str)); Py_XDECREF(str); @@ -1901,7 +1848,7 @@ int igraphmodule_attribute_name_check(PyObject* obj) { type_str = obj ? PyObject_Str((PyObject*)obj->ob_type) : 0; if (type_str != 0) { PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only, got %s", - PyString_AS_STRING(type_str)); + PyUnicode_AS_UNICODE(type_str)); Py_DECREF(type_str); } else { PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only"); diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 9f7e26dbd..9f7d12331 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -23,7 +23,6 @@ #include "bfsiter.h" #include "common.h" #include "error.h" -#include "py2compat.h" #include "vertexobject.h" /** @@ -50,7 +49,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, o->gref=g; o->graph=&g->g; - if (!PyInt_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { + if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); return NULL; } @@ -72,8 +71,8 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, return NULL; } - if (PyInt_Check(root)) { - r=PyInt_AsLong(root); + if (PyLong_Check(root)) { + r=PyLong_AsLong(root); } else { r=((igraphmodule_VertexObject*)root)->idx; } diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 4815315ca..762bbeaf9 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -25,15 +25,15 @@ #include #include #include "attributes.h" -#include "graphobject.h" -#include "vertexseqobject.h" -#include "vertexobject.h" +#include "convert.h" #include "edgeseqobject.h" #include "edgeobject.h" -#include "convert.h" #include "error.h" +#include "graphobject.h" #include "memory.h" -#include "py2compat.h" +#include "pyhelpers.h" +#include "vertexseqobject.h" +#include "vertexobject.h" #if defined(_MSC_VER) #define strcasecmp _stricmp @@ -42,13 +42,13 @@ /** * \brief Converts a Python integer to a C int * - * This is similar to PyInt_AsLong, but it checks for overflow first and throws + * This is similar to PyLong_AsLong, but it checks for overflow first and throws * an exception if necessary. * * Returns -1 if there was an error, 0 otherwise. */ int PyInt_AsInt(PyObject* obj, int* result) { - long dummy = PyInt_AsLong(obj); + long dummy = PyLong_AsLong(obj); if (dummy < INT_MIN) { PyErr_SetString(PyExc_OverflowError, "integer too small for conversion to C int"); @@ -114,11 +114,11 @@ int igraphmodule_PyObject_to_enum(PyObject *o, if (o == 0 || o == Py_None) return 0; - if (PyInt_Check(o)) + if (PyLong_Check(o)) return PyInt_AsInt(o, result); if (PyLong_Check(o)) return PyLong_AsInt(o, result); - s = PyString_CopyAsString(o); + s = PyUnicode_CopyAsString(o); if (s == 0) { PyErr_SetString(PyExc_TypeError, "int, long or string expected"); return -1; @@ -308,7 +308,6 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, if (object != Py_None) { while (PyDict_Next(object, &pos, &key, &value)) { char *kv; -#ifdef IGRAPH_PYTHON3 PyObject *temp_bytes; if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "Dict key must be string"); @@ -321,45 +320,34 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, } kv = strdup(PyBytes_AS_STRING(temp_bytes)); Py_DECREF(temp_bytes); -#else - if (!PyString_Check(key)) { - PyErr_SetString(PyExc_TypeError, "Dict key must be string"); - return -1; - } - kv=PyString_AsString(key); -#endif if (!strcasecmp(kv, "pos")) { igraphmodule_PyObject_to_enum(value, eigen_which_position_tt, (int*) &w->pos); } else if (!strcasecmp(kv, "howmany")) { - w->howmany = (int) PyInt_AsLong(value); + w->howmany = (int) PyLong_AsLong(value); } else if (!strcasecmp(kv, "il")) { - w->il = (int) PyInt_AsLong(value); + w->il = (int) PyLong_AsLong(value); } else if (!strcasecmp(kv, "iu")) { - w->iu = (int) PyInt_AsLong(value); + w->iu = (int) PyLong_AsLong(value); } else if (!strcasecmp(kv, "vl")) { w->vl = PyFloat_AsDouble(value); } else if (!strcasecmp(kv, "vu")) { w->vu = PyFloat_AsDouble(value); } else if (!strcasecmp(kv, "vestimate")) { - w->vestimate = (int) PyInt_AsLong(value); + w->vestimate = (int) PyLong_AsLong(value); } else if (!strcasecmp(kv, "balance")) { igraphmodule_PyObject_to_enum(value, lapack_dgeevc_balance_tt, (int*) &w->balance); } else { PyErr_SetString(PyExc_TypeError, "Unknown eigen parameter"); -#ifdef IGRAPH_PYTHON3 if (kv != 0) { free(kv); } -#endif return -1; } -#ifdef IGRAPH_PYTHON3 if (kv != 0) { free(kv); } -#endif } } return 0; @@ -717,9 +705,8 @@ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { return retval; *v = num; return 0; -#ifdef IGRAPH_PYTHON3 } else if (PyNumber_Check(object)) { - PyObject *i = PyNumber_Int(object); + PyObject *i = PyNumber_Long(object); if (i == NULL) return 1; retval = PyInt_AsInt(i, &num); @@ -729,25 +716,6 @@ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { *v = num; return 0; } -#else - } else if (PyInt_Check(object)) { - retval = PyInt_AsInt(object, &num); - if (retval) - return retval; - *v = num; - return 0; - } else if (PyNumber_Check(object)) { - PyObject *i = PyNumber_Int(object); - if (i == NULL) - return 1; - retval = PyInt_AsInt(i, &num); - Py_DECREF(i); - if (retval) - return retval; - *v = num; - return 0; - } -#endif PyErr_BadArgument(); return 1; } @@ -774,12 +742,6 @@ int igraphmodule_PyObject_to_real_t(PyObject *object, igraph_real_t *v) { double d = PyLong_AsDouble(object); *v=(igraph_real_t)d; return 0; -#ifndef IGRAPH_PYTHON3 - } else if (PyInt_Check(object)) { - long l = PyInt_AS_LONG((PyIntObject*)object); - *v=(igraph_real_t)l; - return 0; -#endif } else if (PyFloat_Check(object)) { double d = PyFloat_AS_DOUBLE((PyFloatObject*)object); *v=(igraph_real_t)d; @@ -1030,7 +992,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v PyErr_SetString(PyExc_TypeError, "iterable must return numbers"); ok=0; } else { - PyObject *item2 = PyNumber_Int(item); + PyObject *item2 = PyNumber_Long(item); if (item2 == 0) { PyErr_SetString(PyExc_TypeError, "can't convert a list item to integer"); ok = 0; @@ -1074,7 +1036,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v PyErr_SetString(PyExc_TypeError, "sequence elements must be integers"); ok=0; } else { - PyObject *item2 = PyNumber_Int(item); + PyObject *item2 = PyNumber_Long(item); if (item2 == 0) { PyErr_SetString(PyExc_TypeError, "can't convert sequence element to int"); ok=0; @@ -1142,12 +1104,12 @@ int igraphmodule_PyObject_to_vector_long_t(PyObject *list, igraph_vector_long_t PyErr_SetString(PyExc_TypeError, "iterable must return numbers"); ok=0; } else { - PyObject *item2 = PyNumber_Int(item); + PyObject *item2 = PyNumber_Long(item); if (item2 == 0) { PyErr_SetString(PyExc_TypeError, "can't convert a list item to integer"); ok = 0; } else { - value=(long)PyInt_AsLong(item); + value=(long)PyLong_AsLong(item); Py_DECREF(item2); } } @@ -1186,12 +1148,12 @@ int igraphmodule_PyObject_to_vector_long_t(PyObject *list, igraph_vector_long_t PyErr_SetString(PyExc_TypeError, "sequence elements must be integers"); ok=0; } else { - PyObject *item2 = PyNumber_Int(item); + PyObject *item2 = PyNumber_Long(item); if (item2 == 0) { PyErr_SetString(PyExc_TypeError, "can't convert sequence element to integer"); ok=0; } else { - value=(long)PyInt_AsLong(item2); + value=(long)PyLong_AsLong(item2); Py_DECREF(item2); } } @@ -1325,7 +1287,7 @@ PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, if (!igraph_finite(VECTOR(*v)[i])) { item = PyFloat_FromDouble((double)VECTOR(*v)[i]); } else { - item = PyInt_FromLong((long)VECTOR(*v)[i]); + item = PyLong_FromLong((long)VECTOR(*v)[i]); } } else if (type == IGRAPHMODULE_TYPE_FLOAT) { item=PyFloat_FromDouble((double)VECTOR(*v)[i]); @@ -1360,7 +1322,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { list=PyList_New(n); for (i=0; iname = 0; - else if (!PyString_Check(name)) { + else if (!PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, "keys must be strings or None in attribute combination specification dicts"); return 1; } else { -#ifdef IGRAPH_PYTHON3 - result->name = PyString_CopyAsString(name); -#else - result->name = PyString_AS_STRING(name); -#endif + result->name = PyUnicode_CopyAsString(name); } return 0; @@ -3035,9 +2989,7 @@ int igraphmodule_PyObject_to_attribute_combination_t(PyObject* object, return 1; } igraph_attribute_combination_add(result, rec.name, rec.type, rec.func); -#ifdef IGRAPH_PYTHON3 free((char*)rec.name); /* was allocated in pair_to_attribute_combination_record_t above */ -#endif } } else { /* assume it is a string or callable */ @@ -3047,9 +2999,7 @@ int igraphmodule_PyObject_to_attribute_combination_t(PyObject* object, } igraph_attribute_combination_add(result, 0, rec.type, rec.func); -#ifdef IGRAPH_PYTHON3 free((char*)rec.name); /* was allocated in pair_to_attribute_combination_record_t above */ -#endif } return 0; diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index d7d8105af..3ea3b3ff6 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -23,7 +23,6 @@ #include "dfsiter.h" #include "common.h" #include "error.h" -#include "py2compat.h" #include "vertexobject.h" /** @@ -50,7 +49,7 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, o->gref=g; o->graph=&g->g; - if (!PyInt_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { + if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); return NULL; } @@ -72,8 +71,8 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, return NULL; } - if (PyInt_Check(root)) { - r=PyInt_AsLong(root); + if (PyLong_Check(root)) { + r=PyLong_AsLong(root); } else { r = ((igraphmodule_VertexObject*)root)->idx; } diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 253f169b5..f42dfa326 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -27,7 +27,6 @@ #include "error.h" #include "graphobject.h" #include "pyhelpers.h" -#include "py2compat.h" #include "vertexobject.h" /** @@ -146,48 +145,31 @@ void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { PyObject *s; PyObject *attrs; -#ifndef IGRAPH_PYTHON3 - PyObject *grepr, *drepr; -#endif attrs = igraphmodule_Edge_attributes(self); if (attrs == 0) return NULL; -#ifdef IGRAPH_PYTHON3 s = PyUnicode_FromFormat("igraph.Edge(%R, %ld, %R)", (PyObject*)self->gref, (long int)self->idx, attrs); Py_DECREF(attrs); -#else - grepr=PyObject_Repr((PyObject*)self->gref); - drepr=PyObject_Repr(attrs); - Py_DECREF(attrs); - if (!grepr || !drepr) { - Py_XDECREF(grepr); - Py_XDECREF(drepr); - return NULL; - } - s=PyString_FromFormat("igraph.Edge(%s, %ld, %s)", PyString_AsString(grepr), - (long int)self->idx, PyString_AsString(drepr)); - Py_DECREF(grepr); - Py_DECREF(drepr); -#endif + return s; } /** \ingroup python_interface_edge * \brief Returns the hash code of the edge */ -Py_hash_t igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { - Py_hash_t hash_graph; - Py_hash_t hash_index; - Py_hash_t result; +long igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { + long hash_graph; + long hash_index; + long result; PyObject* index_o; if (self->hash != -1) return self->hash; - index_o = PyInt_FromLong((long int)self->idx); + index_o = PyLong_FromLong((long int)self->idx); if (index_o == 0) return -1; @@ -447,7 +429,7 @@ PyObject* igraphmodule_Edge_get_from(igraphmodule_EdgeObject* self, void* closur if (igraph_edge(&o->g, self->idx, &from, &to)) { igraphmodule_handle_igraph_error(); return NULL; } - return PyInt_FromLong((long int)from); + return PyLong_FromLong((long int)from); } /** @@ -482,7 +464,7 @@ PyObject* igraphmodule_Edge_get_to(igraphmodule_EdgeObject* self, void* closure) if (igraph_edge(&o->g, self->idx, &from, &to)) { igraphmodule_handle_igraph_error(); return NULL; } - return PyInt_FromLong((long)to); + return PyLong_FromLong((long)to); } /** @@ -508,7 +490,7 @@ PyObject* igraphmodule_Edge_get_target_vertex(igraphmodule_EdgeObject* self, voi * Returns the edge index */ PyObject* igraphmodule_Edge_get_index(igraphmodule_EdgeObject* self, void* closure) { - return PyInt_FromLong((long int)self->idx); + return PyLong_FromLong((long int)self->idx); } /** diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index 837e145e1..2d7f3a259 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -25,7 +25,6 @@ #include #include "graphobject.h" -#include "py2compat.h" /** * \ingroup python_interface_edge @@ -35,7 +34,7 @@ typedef struct { PyObject_HEAD igraphmodule_GraphObject* gref; igraph_integer_t idx; - Py_hash_t hash; + long hash; } igraphmodule_EdgeObject; int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self); diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index fc7af6629..311df20dd 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -28,7 +28,6 @@ #include "edgeseqobject.h" #include "edgeobject.h" #include "error.h" -#include "py2compat.h" #include "pyhelpers.h" #define GET_GRAPH(obj) (((igraphmodule_GraphObject*)obj->gref)->g) @@ -116,9 +115,9 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, if (esobj == Py_None) { /* If es is None, we are selecting all the edges */ igraph_es_all(&es, IGRAPH_EDGEORDER_ID); - } else if (PyInt_Check(esobj)) { + } else if (PyLong_Check(esobj)) { /* We selected a single edge */ - long int idx = PyInt_AsLong(esobj); + long int idx = PyLong_AsLong(esobj); if (idx < 0 || idx >= igraph_ecount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); return -1; @@ -372,7 +371,7 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject return -1; } - if (PyString_Check(values) || !PySequence_Check(values)) { + if (PyUnicode_Check(values) || !PySequence_Check(values)) { /* If values is a string or not a sequence, we construct a list with a * single element (the value itself) and then call ourselves again */ int result; @@ -542,10 +541,10 @@ PyObject* igraphmodule_EdgeSeq_find(igraphmodule_EdgeSeqObject *self, PyObject * Py_DECREF(call_result); Py_DECREF(edge); } - } else if (PyInt_Check(item)) { + } else if (PyLong_Check(item)) { /* Integers are interpreted as indices on the edge set and NOT on the * original, untouched edge sequence of the graph */ - return PySequence_GetItem((PyObject*)self, PyInt_AsLong(item)); + return PySequence_GetItem((PyObject*)self, PyLong_AsLong(item)); } PyErr_SetString(PyExc_IndexError, "no such edge"); @@ -622,7 +621,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } igraph_vector_destroy(&v); - } else if (PyInt_Check(item)) { + } else if (PyLong_Check(item)) { /* Integers are treated specially: from now on, all remaining items * in the argument list must be integers and they will be used together * to restrict the edge set. Integers are interpreted as indices on the @@ -648,14 +647,14 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); igraph_vector_destroy(&v); diff --git a/src/_igraph/filehandle.c b/src/_igraph/filehandle.c index f085d6f0b..94458fa99 100644 --- a/src/_igraph/filehandle.c +++ b/src/_igraph/filehandle.c @@ -21,104 +21,9 @@ */ #include "filehandle.h" -#include "py2compat.h" #include "pyhelpers.h" #ifndef PYPY_VERSION -# ifndef IGRAPH_PYTHON3 -static int igraphmodule_i_filehandle_init_cpython_2(igraphmodule_filehandle_t* handle, - PyObject* object, char* mode) { - FILE* fp; - PyObject* fileno_method; - PyObject* fileno_result; - int fileno = -1; - - if (object == 0) { - PyErr_SetString(PyExc_TypeError, "trying to convert a null object " - "to a file handle"); - return 1; - } - - handle->object = 0; - handle->need_close = 0; - - if (PyBaseString_Check(object)) { - /* We have received a string; we need to open the file denoted by this - * string now and mark that we opened the file ourselves (so we need - * to close it when igraphmodule_filehandle_destroy is invoked). */ - handle->object = PyFile_FromString(PyString_AsString(object), mode); - if (handle->object == 0) { - /* Could not open the file; just return an error code because an - * exception was raised already */ - return 1; - } - /* Remember that we need to close the file ourselves */ - handle->need_close = 1; - /* Get a FILE* object from the file */ - fp = PyFile_AsFile(handle->object); - } else if (PyFile_Check(object)) { - /* This is a file-like object; store a reference for it and - * we will handle it later */ - handle->object = object; - Py_INCREF(handle->object); - /* Get a FILE* object from the file */ - fp = PyFile_AsFile(handle->object); - } else { - /* Check whether the object has a fileno() method. If so, we convert - * that to a file descriptor and then fdopen() it */ - fileno_method = PyObject_GetAttrString(object, "fileno"); - if (fileno_method != 0) { - if (PyCallable_Check(fileno_method)) { - fileno_result = PyObject_CallObject(fileno_method, 0); - Py_DECREF(fileno_method); - if (fileno_result != 0) { - if (PyInt_Check(fileno_result)) { - fileno = (int)PyInt_AsLong(fileno_result); - Py_DECREF(fileno_result); - } else { - Py_DECREF(fileno_result); - PyErr_SetString(PyExc_TypeError, - "fileno() method of file-like object should return " - "an integer"); - return 1; - } - } else { - /* Exception set already by PyObject_CallObject() */ - return 1; - } - } else { - Py_DECREF(fileno_method); - PyErr_SetString(PyExc_TypeError, - "fileno() attribute of file-like object must be callable"); - return 1; - } - } else { - PyErr_SetString(PyExc_TypeError, "expected filename or file-like object"); - return 1; - } - - if (fileno > 0) { - fp = fdopen(fileno, mode); - } else { - PyErr_SetString(PyExc_ValueError, "fileno() method returned invalid " - "file descriptor"); - return 1; - } - } - - handle->fp = fp; - if (handle->fp == 0) { - igraphmodule_filehandle_destroy(handle); - /* This already called Py_DECREF(handle->object), no need to call it */ - PyErr_SetString(PyExc_RuntimeError, "PyFile_AsFile() failed unexpectedly"); - return 1; - } - - return 0; -} - -# else /* IGRAPH_PYTHON3 */ - static int igraphmodule_i_filehandle_init_cpython_3(igraphmodule_filehandle_t* handle, PyObject* object, char* mode) { int fp; @@ -135,7 +40,7 @@ static int igraphmodule_i_filehandle_init_cpython_3(igraphmodule_filehandle_t* h /* We have received a string; we need to open the file denoted by this * string now and mark that we opened the file ourselves (so we need * to close it when igraphmodule_filehandle_destroy is invoked). */ - handle->object = PyFile_FromObject(object, mode); + handle->object = igraphmodule_PyFile_FromObject(object, mode); if (handle->object == 0) { /* Could not open the file; just return an error code because an * exception was raised already */ @@ -170,75 +75,7 @@ static int igraphmodule_i_filehandle_init_cpython_3(igraphmodule_filehandle_t* h return 0; } -# endif /* IGRAPH_PYTHON3 */ -#endif /* PYPY_VERSION */ - -#ifdef PYPY_VERSION -# ifndef IGRAPH_PYTHON3 -static int igraphmodule_i_filehandle_init_pypy_2(igraphmodule_filehandle_t* handle, - PyObject* object, char* mode) { - int fp; - PyObject* fpobj; - char* fname; - - if (object == 0) { - PyErr_SetString(PyExc_TypeError, "trying to convert a null object " - "to a file handle"); - return 1; - } - - handle->need_close = 0; - handle->object = 0; - - if (PyBaseString_Check(object)) { - /* We have received a string; we need to open the file denoted by this - * string now and mark that we opened the file ourselves (so we need - * to close it when igraphmodule_filehandle_destroy is invoked). */ - handle->object = PyFile_FromString(PyString_AsString(object), mode); - if (handle->object == 0) { - /* Could not open the file; just return an error code because an - * exception was raised already */ - return 1; - } - /* Remember that we need to close the file ourselves */ - handle->need_close = 1; - } else { - /* This is probably a file-like object; store a reference for it and - * we will handle it later */ - handle->object = object; - Py_INCREF(handle->object); - } - - /* PyPy does not have PyFile_AsFile, so we will try to access the file - * descriptor instead by calling its fileno() method and then opening the - * file handle with fdopen */ - fpobj = PyObject_CallMethod(handle->object, "fileno", 0); - if (fpobj == 0 || !PyInt_Check(fpobj)) { - if (fpobj != 0) { - Py_DECREF(fpobj); - } - igraphmodule_filehandle_destroy(handle); - /* This already called Py_DECREF(handle->object), no need to call it. - * Also, an exception was raised by PyObject_CallMethod so no need to - * raise one ourselves */ - return 1; - } - fp = (int)PyInt_AsLong(fpobj); - Py_DECREF(fpobj); - - handle->fp = fdopen(fp, mode); - if (handle->fp == 0) { - igraphmodule_filehandle_destroy(handle); - /* This already called Py_DECREF(handle->object), no need to call it */ - PyErr_SetString(PyExc_RuntimeError, "fdopen() failed unexpectedly"); - return 1; - } - - return 0; -} - -# else /* IGRAPH_PYTHON3 */ - +#else /* PYPY_VERSION */ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* handle, PyObject* object, char* mode) { int fp; @@ -289,7 +126,6 @@ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* hand return 0; } -# endif /* IGRAPH_PYTHON3 */ #endif /** @@ -302,17 +138,9 @@ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* hand int igraphmodule_filehandle_init(igraphmodule_filehandle_t* handle, PyObject* object, char* mode) { #ifdef PYPY_VERSION -# ifdef IGRAPH_PYTHON3 return igraphmodule_i_filehandle_init_pypy_3(handle, object, mode); -# else - return igraphmodule_i_filehandle_init_pypy_2(handle, object, mode); -# endif #else -# ifdef IGRAPH_PYTHON3 return igraphmodule_i_filehandle_init_cpython_3(handle, object, mode); -# else - return igraphmodule_i_filehandle_init_cpython_2(handle, object, mode); -# endif #endif } @@ -333,11 +161,11 @@ void igraphmodule_filehandle_destroy(igraphmodule_filehandle_t* handle) { handle->fp = 0; if (handle->object != 0) { - /* PyFile_Close might mess up the stored exception, so let's + /* igraphmodule_PyFile_Close might mess up the stored exception, so let's * store the current exception state and restore it */ PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); if (handle->need_close) { - if (PyFile_Close(handle->object)) { + if (igraphmodule_PyFile_Close(handle->object)) { PyErr_WriteUnraisable(Py_None); } } diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e979b394a..748114d1d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -32,7 +32,6 @@ #include "graphobject.h" #include "indexing.h" #include "memory.h" -#include "py2compat.h" #include "pyhelpers.h" #include "vertexseqobject.h" #include @@ -347,11 +346,11 @@ PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph) { PyObject *igraphmodule_Graph_str(igraphmodule_GraphObject * self) { if (igraph_is_directed(&self->g)) - return PyString_FromFormat("Directed graph (|V| = %ld, |E| = %ld)", + return PyUnicode_FromFormat("Directed graph (|V| = %ld, |E| = %ld)", (long)igraph_vcount(&self->g), (long)igraph_ecount(&self->g)); else - return PyString_FromFormat("Undirected graph (|V| = %ld, |E| = %ld)", + return PyUnicode_FromFormat("Undirected graph (|V| = %ld, |E| = %ld)", (long)igraph_vcount(&self->g), (long)igraph_ecount(&self->g)); } @@ -729,7 +728,7 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, if (!return_single) list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); else - list = PyInt_FromLong((long int)VECTOR(result)[0]); + list = PyLong_FromLong((long int)VECTOR(result)[0]); igraph_vector_destroy(&result); igraph_vs_destroy(&vs); @@ -953,7 +952,7 @@ PyObject *igraphmodule_Graph_maxdegree(igraphmodule_GraphObject * self, igraph_vs_destroy(&vs); - return PyInt_FromLong((long)result); + return PyLong_FromLong((long)result); } /** \ingroup python_interface_graph @@ -1155,7 +1154,7 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, if (!return_single) list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); else - list = PyInt_FromLong((long int)VECTOR(result)[0]); + list = PyLong_FromLong((long int)VECTOR(result)[0]); igraph_vector_destroy(&result); igraph_es_destroy(&es); @@ -1572,7 +1571,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, /* The diameter is integer in this case, except if igraph_diameter() * returned NaN or infinity for some reason */ if (ceilf(diameter) == diameter && isfinite(diameter)) { - return PyInt_FromLong((long)diameter); + return PyLong_FromLong((long)diameter); } else { return PyFloat_FromDouble((double)diameter); } @@ -1714,7 +1713,7 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, igraph_vector_destroy(&vids); return o; } - return PyInt_FromLong((long)girth); + return PyLong_FromLong((long)girth); } /** @@ -2013,8 +2012,8 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, m = 1; } else if (m_obj != 0) { /* let's check whether we have a constant out-degree or a list */ - if (PyInt_Check(m_obj)) { - m = PyInt_AsLong(m_obj); + if (PyLong_Check(m_obj)) { + m = PyLong_AsLong(m_obj); igraph_vector_init(&outseq, 0); } else if (PyList_Check(m_obj)) { if (igraphmodule_PyObject_to_vector_t(m_obj, &outseq, 1)) { @@ -3084,8 +3083,8 @@ NULL }; } // let's check whether we have a constant out-degree or a list - if (PyInt_Check(m_obj)) { - m = PyInt_AsLong(m_obj); + if (PyLong_Check(m_obj)) { + m = PyLong_AsLong(m_obj); igraph_vector_init(&outseq, 0); } else if (PyList_Check(m_obj)) { @@ -3461,7 +3460,7 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, if (attr_o != Py_None) { s = PyObject_Str(attr_o); if (s) { - attr = PyString_CopyAsString(s); + attr = PyUnicode_CopyAsString(s); if (attr == 0) return NULL; } else return NULL; @@ -4744,13 +4743,13 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * igraph_vector_ptr_t *ptrvec=0; igraph_bool_t use_edges = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO!", kwlist, &from_o, - &to_o, &weights_o, &mode_o, &PyString_Type, &output_o)) + &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) return NULL; if (output_o == 0 || output_o == Py_None || - PyString_IsEqualToASCIIString(output_o, "vpath")) { + PyUnicode_IsEqualToASCIIString(output_o, "vpath")) { use_edges = 0; - } else if (PyString_IsEqualToASCIIString(output_o, "epath")) { + } else if (PyUnicode_IsEqualToASCIIString(output_o, "epath")) { use_edges = 1; } else { PyErr_SetString(PyExc_ValueError, "output argument must be \"vpath\" or \"epath\""); @@ -5164,7 +5163,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, if (!return_single) result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); else - result = PyInt_FromLong((long)VECTOR(res)[0]); + result = PyLong_FromLong((long)VECTOR(res)[0]); igraph_vector_destroy(&res); @@ -6319,7 +6318,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_no(igraphmodule_GraphObject *self, } igraph_vector_destroy(&cut_prob); - return PyInt_FromLong((long)result); + return PyLong_FromLong((long)result); } /** \ingroup python_interface_graph @@ -6356,9 +6355,9 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s } } - if (PyInt_Check(sample)) { + if (PyLong_Check(sample)) { /* samples chosen randomly */ - long int ns = PyInt_AsLong(sample); + long int ns = PyLong_AsLong(sample); if (igraph_motifs_randesu_estimate(&self->g, &result, (igraph_integer_t) size, &cut_prob, (igraph_integer_t) ns, 0)) { igraphmodule_handle_igraph_error(); @@ -6381,7 +6380,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s } igraph_vector_destroy(&cut_prob); - return PyInt_FromLong((long)result); + return PyLong_FromLong((long)result); } /** \ingroup python_interface_graph @@ -7458,7 +7457,7 @@ PyObject *igraphmodule_Graph_layout_bipartite( } if (types_o == Py_None) { - types_o = PyString_FromString("type"); + types_o = PyUnicode_FromString("type"); } else { Py_INCREF(types_o); } @@ -8097,7 +8096,7 @@ PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, return NULL; if (capacity_obj == Py_None) { - capacity_obj = PyString_FromString("capacity"); + capacity_obj = PyUnicode_FromString("capacity"); } else { Py_INCREF(capacity_obj); } @@ -8225,7 +8224,7 @@ PyObject *igraphmodule_Graph_write_gml(igraphmodule_GraphObject * self, igraphmodule_filehandle_destroy(&fobj); } - creator_str = PyString_CopyAsString(o); + creator_str = PyUnicode_CopyAsString(o); Py_DECREF(o); if (creator_str == 0) { @@ -8502,7 +8501,7 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, } } - return PyInt_FromLong((long)isoclass); + return PyLong_FromLong((long)isoclass); } /** \ingroup python_interface_graph @@ -10927,7 +10926,7 @@ PyObject *igraphmodule_Graph_clique_number(igraphmodule_GraphObject * self) if (igraph_clique_number(&self->g, &i)) return igraphmodule_handle_igraph_error(); - result = PyInt_FromLong((long)i); + result = PyLong_FromLong((long)i); return result; } @@ -11088,7 +11087,7 @@ PyObject *igraphmodule_Graph_independence_number(igraphmodule_GraphObject * if (igraph_independence_number(&self->g, &i)) return igraphmodule_handle_igraph_error(); - result = PyInt_FromLong((long)i); + result = PyLong_FromLong((long)i); return result; } @@ -11923,25 +11922,12 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self, /** \defgroup python_interface_internal Internal functions * \ingroup python_interface */ -#ifdef IGRAPH_PYTHON3 PyObject *igraphmodule_Graph___graph_as_capsule__(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { return PyCapsule_New((void *)&self->g, 0, 0); } -#else -/** \ingroup python_interface_internal - * \brief Returns the encapsulated igraph graph as a PyCObject - * \return a new PyCObject - */ -PyObject *igraphmodule_Graph___graph_as_cobject__(igraphmodule_GraphObject * - self, PyObject * args, - PyObject * kwds) -{ - return PyCObject_FromVoidPtr((void *)&self->g, 0); -} -#endif /** \ingroup python_interface_internal * \brief Returns the pointer of the encapsulated igraph graph as an ordinary @@ -11949,7 +11935,7 @@ PyObject *igraphmodule_Graph___graph_as_cobject__(igraphmodule_GraphObject * * module without any additional conversions. */ PyObject *igraphmodule_Graph__raw_pointer(igraphmodule_GraphObject *self) { - return PyInt_FromLong((long int)&self->g); + return PyLong_FromLong((long int)&self->g); } /** \ingroup python_interface_internal @@ -15975,7 +15961,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /**********************/ /* INTERNAL FUNCTIONS */ /**********************/ -#ifdef IGRAPH_PYTHON3 {"__graph_as_capsule", (PyCFunction) igraphmodule_Graph___graph_as_capsule__, METH_VARARGS | METH_KEYWORDS, @@ -15986,18 +15971,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Python object. This function should not be used directly by igraph\n" "users, it is useful only in the case when the underlying igraph object\n" "must be passed to other C code through Python.\n\n"}, -#else - {"__graph_as_cobject", - (PyCFunction) igraphmodule_Graph___graph_as_cobject__, - METH_VARARGS | METH_KEYWORDS, - "__graph_as_cobject()\n--\n\n" - "Returns the igraph graph encapsulated by the Python object as\n" - "a PyCObject\n\n." - "A PyCObject is practically a regular C pointer, wrapped in a\n" - "Python object. This function should not be used directly by igraph\n" - "users, it is useful only in the case when the underlying igraph object\n" - "must be passed to other C code through Python.\n\n"}, -#endif {"_raw_pointer", (PyCFunction) igraphmodule_Graph__raw_pointer, @@ -16040,9 +16013,6 @@ PyNumberMethods igraphmodule_Graph_as_number = { 0, /* nb_add */ 0, /*nb_subtract */ 0, /*nb_multiply */ -#ifndef IGRAPH_PYTHON3 - 0, /*nb_divide */ -#endif 0, /*nb_remainder */ 0, /*nb_divmod */ 0, /*nb_power */ @@ -16056,22 +16026,12 @@ PyNumberMethods igraphmodule_Graph_as_number = { 0, /*nb_and */ 0, /*nb_xor */ 0, /*nb_or */ -#ifndef IGRAPH_PYTHON3 - 0, /*nb_coerce */ -#endif 0, /*nb_int */ 0, /*nb_long (2.x) / nb_reserved (3.x)*/ 0, /*nb_float */ -#ifndef IGRAPH_PYTHON3 - 0, /*nb_oct */ - 0, /*nb_hex */ -#endif 0, /*nb_inplace_add */ 0, /*nb_inplace_subtract */ 0, /*nb_inplace_multiply */ -#ifndef IGRAPH_PYTHON3 - 0, /*nb_inplace_divide */ -#endif 0, /*nb_inplace_remainder */ 0, /*nb_inplace_power */ 0, /*nb_inplace_lshift */ @@ -16079,14 +16039,11 @@ PyNumberMethods igraphmodule_Graph_as_number = { 0, /*nb_inplace_and */ 0, /*nb_inplace_xor */ 0, /*nb_inplace_or */ - -#ifdef IGRAPH_PYTHON3 0, /*nb_floor_divide */ 0, /*nb_true_divide */ 0, /*nb_inplace_floor_divide */ 0, /*nb_inplace_true_divide */ 0, /*nb_index */ -#endif }; /** \ingroup python_interface_graph diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 51091ccc5..856d4bf7a 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -33,7 +33,6 @@ #include "edgeseqobject.h" #include "error.h" #include "graphobject.h" -#include "py2compat.h" #include "random.h" #include "vertexobject.h" #include "vertexseqobject.h" @@ -130,7 +129,6 @@ static struct module_state _state = { 0, 0 }; #define GETSTATE(m) (&_state) -#ifdef IGRAPH_PYTHON3 static int igraphmodule_traverse(PyObject *m, visitproc visit, void* arg) { Py_VISIT(GETSTATE(m)->progress_handler); Py_VISIT(GETSTATE(m)->status_handler); @@ -142,7 +140,6 @@ static int igraphmodule_clear(PyObject *m) { Py_CLEAR(GETSTATE(m)->status_handler); return 0; } -#endif static int igraphmodule_igraph_interrupt_hook(void* data) { if (PyErr_CheckSignals()) { @@ -735,9 +732,8 @@ static PyMethodDef igraphmodule_methods[] = "Should not be used directly.\n" /** - * Module definition table (only for Python 3.x) + * Module definition table */ -#ifdef IGRAPH_PYTHON3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "igraph._igraph", /* m_name */ @@ -749,7 +745,6 @@ static struct PyModuleDef moduledef = { igraphmodule_clear, /* m_clear */ 0 /* m_free */ }; -#endif /****************** Exported API functions *******************/ @@ -796,16 +791,8 @@ igraph_t* PyIGraph_ToCGraph(PyObject* graph) { extern PyObject* igraphmodule_InternalError; extern PyObject* igraphmodule_arpack_options_default; -#ifdef IGRAPH_PYTHON3 -# define INITERROR return NULL - PyObject* PyInit__igraph(void) -#else -# define INITERROR return -# ifndef PyMODINIT_FUNC -# define PyMODINIT_FUNC void -# endif - PyMODINIT_FUNC init_igraph(void) -#endif +#define INITERROR return NULL +PyObject* PyInit__igraph(void) { PyObject* m; static void *PyIGraph_API[PyIGraph_API_pointers]; @@ -845,12 +832,7 @@ extern PyObject* igraphmodule_arpack_options_default; INITERROR; /* Initialize the core module */ -#ifdef IGRAPH_PYTHON3 m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("igraph._igraph", igraphmodule_methods, MODULE_DOCS); -#endif - if (m == NULL) INITERROR; @@ -945,18 +927,12 @@ extern PyObject* igraphmodule_arpack_options_default; PyIGraph_API[PyIGraph_ToCGraph_NUM] = (void *)PyIGraph_ToCGraph; /* Create a CObject containing the API pointer array's address */ -#ifdef IGRAPH_PYTHON3 c_api_object = PyCapsule_New((void*)PyIGraph_API, "igraph._igraph._C_API", 0); -#else - c_api_object = PyCObject_FromVoidPtr((void*)PyIGraph_API, 0); -#endif if (c_api_object != 0) { PyModule_AddObject(m, "_C_API", c_api_object); } igraphmodule_initialized = 1; -#ifdef IGRAPH_PYTHON3 return m; -#endif } diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index f30729b17..8eececb9c 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -26,7 +26,6 @@ #include "error.h" #include "indexing.h" #include "platform.h" -#include "py2compat.h" #include "pyhelpers.h" /***************************************************************************/ @@ -41,7 +40,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_indexing_get_value_for_vertex_pa if (eid >= 0) { /* Edge found, get the value of the attribute */ if (values == 0) { - return PyInt_FromLong(1L); + return PyLong_FromLong(1L); } else { result = PyList_GetItem(values, eid); Py_XINCREF(result); @@ -49,7 +48,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_indexing_get_value_for_vertex_pa } } else { /* No such edge, return zero */ - return PyInt_FromLong(0L); + return PyLong_FromLong(0L); } } @@ -160,7 +159,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, if (values) item = PyList_GetItem(values, eid); else - item = PyInt_FromLong(1); + item = PyLong_FromLong(1); Py_INCREF(item); PyList_SetItem(result, v, item); /* reference stolen here */ } @@ -221,7 +220,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, */ static INLINE igraph_bool_t deleting_edge(PyObject* value) { return value == Py_None || value == Py_False || - (PyInt_Check(value) && PyInt_AsLong(value) == 0); + (PyLong_Check(value) && PyLong_AsLong(value) == 0); } /** diff --git a/src/_igraph/py2compat.c b/src/_igraph/py2compat.c deleted file mode 100644 index 31fbec867..000000000 --- a/src/_igraph/py2compat.c +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- mode: C -*- */ -/* vim: set ts=2 sw=2 sts=2 et: */ - -/* - IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#include "py2compat.h" - -/* Common utility functions that are useful both in Python 2.x and 3.x */ - -int PyFile_Close(PyObject* fileObj) { - PyObject *result; - - result = PyObject_CallMethod(fileObj, "close", 0); - if (result) { - Py_DECREF(result); - return 0; - } else { - /* Exception raised already */ - return 1; - } -} - - -#ifdef IGRAPH_PYTHON3 - -/* Python 3.x functions */ - -PyObject* PyFile_FromObject(PyObject* filename, const char* mode) { - PyObject *ioModule, *fileObj; - - ioModule = PyImport_ImportModule("io"); - if (ioModule == 0) - return 0; - - fileObj = PyObject_CallMethod(ioModule, "open", "Os", filename, mode); - Py_DECREF(ioModule); - - return fileObj; -} - -char* PyString_CopyAsString(PyObject* string) { - PyObject* bytes; - char* result; - - if (PyBytes_Check(string)) { - bytes = string; - Py_INCREF(bytes); - } else { - bytes = PyUnicode_AsUTF8String(string); - } - - if (bytes == 0) - return 0; - - result = strdup(PyBytes_AS_STRING(bytes)); - Py_DECREF(bytes); - - if (result == 0) - PyErr_NoMemory(); - - return result; -} - -int PyString_IsEqualToUTF8String(PyObject* py_string, - const char* c_string) { - PyObject* c_string_conv; - int result; - - if (!PyUnicode_Check(py_string)) - return 0; - - c_string_conv = PyUnicode_FromString(c_string); - if (c_string_conv == 0) - return 0; - - result = (PyUnicode_Compare(py_string, c_string_conv) == 0); - Py_DECREF(c_string_conv); - - return result; -} - -#else - -/* Python 2.x functions */ - -char* PyString_CopyAsString(PyObject* string) { - char* result; - - if (!PyBaseString_Check(string)) { - PyErr_SetString(PyExc_TypeError, "string or unicode object expected"); - return 0; - } - - result = PyString_AsString(string); - if (result == 0) - return 0; - - result = strdup(result); - if (result == 0) - PyErr_NoMemory(); - - return result; -} - -int PyString_IsEqualToASCIIString(PyObject* py_string, - const char* c_string) { - PyObject* c_string_conv; - int result; - - if (PyString_Check(py_string)) { - return strcmp(PyString_AS_STRING(py_string), c_string) == 0; - } - - if (!PyUnicode_Check(py_string)) - return 0; - - c_string_conv = PyUnicode_DecodeASCII(c_string, strlen(c_string), "strict"); - if (c_string_conv == 0) - return 0; - - result = (PyUnicode_Compare(py_string, c_string_conv) == 0); - Py_DECREF(c_string_conv); - - return result; -} - -#endif diff --git a/src/_igraph/py2compat.h b/src/_igraph/py2compat.h deleted file mode 100644 index 8ab6dd56f..000000000 --- a/src/_igraph/py2compat.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- mode: C -*- */ -/* vim: set ts=2 sw=2 sts=2 et: */ - -/* - IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - -*/ - -#ifndef PY_IGRAPH_PY2COMPAT_H -#define PY_IGRAPH_PY2COMPAT_H - -#include - -/* Common utility functions */ -int PyFile_Close(PyObject* fileObj); - -/* Compatibility hacks */ -#ifndef Py_hash_t -# define Py_hash_t long -#endif - -#if PY_MAJOR_VERSION >= 3 - -/* Python 3.x-specific part follows here */ -#define IGRAPH_PYTHON3 - -#define PyBaseString_Check(o) (PyUnicode_Check(o) || PyBytes_Check(o)) - -PyObject* PyFile_FromObject(PyObject* filename, const char* mode); - -#ifndef PYPY_VERSION - typedef PyLongObject PyIntObject; -#endif /* PYPY_VERSION */ -#define PyInt_AsLong PyLong_AsLong -#define PyInt_Check PyLong_Check -#define PyInt_FromLong PyLong_FromLong - -#define PyNumber_Int PyNumber_Long - -#define PyString_AS_STRING PyUnicode_AS_UNICODE -#define PyString_Check PyUnicode_Check -#define PyString_FromFormat PyUnicode_FromFormat -#define PyString_FromString PyUnicode_FromString -#define PyString_Type PyUnicode_Type -#define PyString_IsEqualToASCIIString(uni, string) \ - (PyUnicode_CompareWithASCIIString(uni, string) == 0) - -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -int PyString_IsEqualToUTF8String(PyObject* py_string, - const char* c_string); - -#else - -/* Python 2.x-specific part follows here */ - -#define PyBaseString_Check(o) (PyString_Check(o) || PyUnicode_Check(o)) - -int PyString_IsEqualToASCIIString(PyObject* py_string, - const char* c_string); - -#ifndef Py_TYPE -# define Py_TYPE(o) ((o)->ob_type) -#endif - -#ifndef PyVarObject_HEAD_INIT -# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif - -#endif - -char* PyString_CopyAsString(PyObject* string); - -#endif - diff --git a/src/_igraph/pyhelpers.c b/src/_igraph/pyhelpers.c index 633e4d73b..a51b60ca7 100644 --- a/src/_igraph/pyhelpers.c +++ b/src/_igraph/pyhelpers.c @@ -21,9 +21,41 @@ */ -#include "py2compat.h" #include "pyhelpers.h" +/** + * Closes a Python file-like object by calling its close() method. + */ +int igraphmodule_PyFile_Close(PyObject* fileObj) { + PyObject *result; + + result = PyObject_CallMethod(fileObj, "close", 0); + if (result) { + Py_DECREF(result); + return 0; + } else { + /* Exception raised already */ + return 1; + } +} + +/** + * Creates a Python file-like object from a Python object storing a string and + * an ordinary C string storing the mode to open the file in. + */ +PyObject* igraphmodule_PyFile_FromObject(PyObject* filename, const char* mode) { + PyObject *ioModule, *fileObj; + + ioModule = PyImport_ImportModule("io"); + if (ioModule == 0) + return 0; + + fileObj = PyObject_CallMethod(ioModule, "open", "Os", filename, mode); + Py_DECREF(ioModule); + + return fileObj; +} + /** * Creates a Python list and fills it with a pre-defined item. * @@ -51,7 +83,7 @@ PyObject* igraphmodule_PyList_NewFill(Py_ssize_t len, PyObject* item) { * \param len the length of the list to be created */ PyObject* igraphmodule_PyList_Zeroes(Py_ssize_t len) { - PyObject* zero = PyInt_FromLong(0); + PyObject* zero = PyLong_FromLong(0); PyObject* result; if (zero == 0) @@ -82,7 +114,7 @@ char* igraphmodule_PyObject_ConvertToCString(PyObject* string) { Py_INCREF(string); } - result = PyString_CopyAsString(string); + result = PyUnicode_CopyAsString(string); Py_DECREF(string); return result; @@ -101,22 +133,14 @@ PyObject* igraphmodule_PyRange_create(Py_ssize_t start, Py_ssize_t stop, Py_ssiz PyObject* result; if (builtin_module == 0) { -#ifdef IGRAPH_PYTHON3 builtin_module = PyImport_ImportModule("builtins"); -#else - builtin_module = PyImport_ImportModule("__builtin__"); -#endif if (builtin_module == 0) { return 0; } } if (range_func == 0) { -#ifdef IGRAPH_PYTHON3 range_func = PyObject_GetAttrString(builtin_module, "range"); -#else - range_func = PyObject_GetAttrString(builtin_module, "xrange"); -#endif if (range_func == 0) { return 0; } @@ -126,6 +150,47 @@ PyObject* igraphmodule_PyRange_create(Py_ssize_t start, Py_ssize_t stop, Py_ssiz return result; } +char* PyUnicode_CopyAsString(PyObject* string) { + PyObject* bytes; + char* result; + + if (PyBytes_Check(string)) { + bytes = string; + Py_INCREF(bytes); + } else { + bytes = PyUnicode_AsUTF8String(string); + } + + if (bytes == 0) + return 0; + + result = strdup(PyBytes_AS_STRING(bytes)); + Py_DECREF(bytes); + + if (result == 0) + PyErr_NoMemory(); + + return result; +} + +int PyUnicode_IsEqualToUTF8String(PyObject* py_string, + const char* c_string) { + PyObject* c_string_conv; + int result; + + if (!PyUnicode_Check(py_string)) + return 0; + + c_string_conv = PyUnicode_FromString(c_string); + if (c_string_conv == 0) + return 0; + + result = (PyUnicode_Compare(py_string, c_string_conv) == 0); + Py_DECREF(c_string_conv); + + return result; +} + /** * Generates a hash value for a plain C pointer. * diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 00c518e95..00bff1d86 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -26,12 +26,20 @@ #include +int igraphmodule_PyFile_Close(PyObject* fileObj); +PyObject* igraphmodule_PyFile_FromObject(PyObject* filename, const char* mode); PyObject* igraphmodule_PyList_NewFill(Py_ssize_t len, PyObject* item); PyObject* igraphmodule_PyList_Zeroes(Py_ssize_t len); char* igraphmodule_PyObject_ConvertToCString(PyObject* string); PyObject* igraphmodule_PyRange_create(Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step); +int PyUnicode_IsEqualToUTF8String(PyObject* py_string, const char* c_string); long igraphmodule_Py_HashPointer(void *p); +#define PyBaseString_Check(o) (PyUnicode_Check(o) || PyBytes_Check(o)) +#define PyUnicode_IsEqualToASCIIString(uni, string) \ + (PyUnicode_CompareWithASCIIString(uni, string) == 0) +char* PyUnicode_CopyAsString(PyObject* string); + #define PY_IGRAPH_DEPRECATED(msg) \ PyErr_WarnEx(PyExc_DeprecationWarning, (msg), 1) #define PY_IGRAPH_WARN(msg) \ diff --git a/src/_igraph/random.c b/src/_igraph/random.c index bb623dfcc..e267d13d0 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -21,7 +21,6 @@ */ -#include "py2compat.h" #include "random.h" #include #include @@ -115,7 +114,7 @@ unsigned long int igraph_rng_Python_get(void *state) { /* Fallback to the C random generator */ return rand() * LONG_MAX; } - retval = PyInt_AsLong(result); + retval = PyLong_AsLong(result); Py_DECREF(result); return retval; } diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 138a225b1..f64b2c608 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -146,48 +146,31 @@ void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { PyObject *s; PyObject *attrs; -#ifndef IGRAPH_PYTHON3 - PyObject *grepr, *drepr; -#endif attrs = igraphmodule_Vertex_attributes(self); if (attrs == 0) return NULL; -#ifdef IGRAPH_PYTHON3 s = PyUnicode_FromFormat("igraph.Vertex(%R, %ld, %R)", (PyObject*)self->gref, (long int)self->idx, attrs); Py_DECREF(attrs); -#else - grepr=PyObject_Repr((PyObject*)self->gref); - drepr=PyObject_Repr(igraphmodule_Vertex_attributes(self)); - Py_DECREF(attrs); - if (!grepr || !drepr) { - Py_XDECREF(grepr); - Py_XDECREF(drepr); - return NULL; - } - s=PyString_FromFormat("igraph.Vertex(%s,%ld,%s)", PyString_AsString(grepr), - (long int)self->idx, PyString_AsString(drepr)); - Py_DECREF(grepr); - Py_DECREF(drepr); -#endif + return s; } /** \ingroup python_interface_vertex * \brief Returns the hash code of the vertex */ -Py_hash_t igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { - Py_hash_t hash_graph; - Py_hash_t hash_index; - Py_hash_t result; +long igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { + long hash_graph; + long hash_index; + long result; PyObject* index_o; if (self->hash != -1) return self->hash; - index_o = PyInt_FromLong((long int)self->idx); + index_o = PyLong_FromLong((long int)self->idx); if (index_o == 0) return -1; @@ -505,7 +488,7 @@ int igraphmodule_Vertex_set_attribute(igraphmodule_VertexObject* self, PyObject* if (!igraphmodule_attribute_name_check(k)) return -1; - if (PyString_IsEqualToASCIIString(k, "name")) + if (PyUnicode_IsEqualToASCIIString(k, "name")) igraphmodule_invalidate_vertex_name_index(&o->g); if (v==NULL) @@ -567,7 +550,7 @@ int igraphmodule_Vertex_set_attribute(igraphmodule_VertexObject* self, PyObject* * Returns the vertex index */ PyObject* igraphmodule_Vertex_get_index(igraphmodule_VertexObject* self, void* closure) { - return PyInt_FromLong((long int)self->idx); + return PyLong_FromLong((long int)self->idx); } /** @@ -628,7 +611,7 @@ static PyObject* _convert_to_edge_list(igraphmodule_VertexObject* vertex, PyObje PyObject* v; int idx_int; - if (!PyInt_Check(idx)) { + if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_edge_list expected list of integers"); return NULL; } @@ -660,7 +643,7 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb PyObject* v; int idx_int; - if (!PyInt_Check(idx)) { + if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_vertex_list expected list of integers"); return NULL; } diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index b50b52351..f33d640eb 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -25,7 +25,6 @@ #include #include "graphobject.h" -#include "py2compat.h" /** * \ingroup python_interface_vertex @@ -36,7 +35,7 @@ typedef struct PyObject_HEAD igraphmodule_GraphObject* gref; igraph_integer_t idx; - Py_hash_t hash; + long hash; } igraphmodule_VertexObject; int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 88e476e7d..6560368cb 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -27,7 +27,6 @@ #include "common.h" #include "convert.h" #include "error.h" -#include "py2compat.h" #include "pyhelpers.h" #include "vertexseqobject.h" #include "vertexobject.h" @@ -115,9 +114,9 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, if (vsobj == Py_None) { /* If vs is None, we are selecting all the vertices */ igraph_vs_all(&vs); - } else if (PyInt_Check(vsobj)) { + } else if (PyLong_Check(vsobj)) { /* We selected a single vertex */ - long int idx = PyInt_AsLong(vsobj); + long int idx = PyLong_AsLong(vsobj); if (idx < 0 || idx >= igraph_vcount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); return -1; @@ -353,7 +352,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb if (!igraphmodule_attribute_name_check(attrname)) return -1; - if (PyString_IsEqualToASCIIString(attrname, "name")) + if (PyUnicode_IsEqualToASCIIString(attrname, "name")) igraphmodule_invalidate_vertex_name_index(&gr->g); if (values == 0) { @@ -363,7 +362,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb return -1; } - if (PyString_Check(values) || !PySequence_Check(values)) { + if (PyUnicode_Check(values) || !PySequence_Check(values)) { /* If values is a string or not a sequence, we construct a list with a * single element (the value itself) and then call ourselves again */ int result; @@ -541,10 +540,10 @@ PyObject* igraphmodule_VertexSeq_find(igraphmodule_VertexSeqObject *self, PyObje Py_DECREF(call_result); Py_DECREF(vertex); } - } else if (PyInt_Check(item)) { + } else if (PyLong_Check(item)) { /* Integers are interpreted as indices on the vertex set and NOT on the * original, untouched vertex sequence of the graph */ - return PySequence_GetItem((PyObject*)self, PyInt_AsLong(item)); + return PySequence_GetItem((PyObject*)self, PyLong_AsLong(item)); } else if (PyBaseString_Check(item)) { /* Strings are interpreted as vertex names */ if (igraphmodule_get_vertex_id_by_name(&self->gref->g, item, &i)) @@ -651,7 +650,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } igraph_vector_destroy(&v); - } else if (PyInt_Check(item)) { + } else if (PyLong_Check(item)) { /* Integers are treated specially: from now on, all remaining items * in the argument list must be integers and they will be used together * to restrict the vertex set. Integers are interpreted as indices on the @@ -677,14 +676,14 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); igraph_vector_destroy(&v); From 119a706d9e2df1e6d302fb9d6826087effdf47fc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 02:11:25 +0100 Subject: [PATCH 0407/1892] fix: fix compilation on PyPy 3.7 that I broke in the previous commit --- src/_igraph/filehandle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/filehandle.c b/src/_igraph/filehandle.c index 94458fa99..f7bc72f38 100644 --- a/src/_igraph/filehandle.c +++ b/src/_igraph/filehandle.c @@ -91,7 +91,7 @@ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* hand /* We have received a string; we need to open the file denoted by this * string now and mark that we opened the file ourselves (so we need * to close it when igraphmodule_filehandle_destroy is invoked). */ - handle->object = PyFile_FromObject(object, mode); + handle->object = igraphmodule_PyFile_FromObject(object, mode); if (handle->object == 0) { /* Could not open the file; just return an error code because an * exception was raised already */ From 3dc0ec00f67d8cbcee31077229d6f33a514a3387 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 02:26:41 +0100 Subject: [PATCH 0408/1892] doc: remove type annotations from __text_signature__ markup, it is not supported --- src/_igraph/arpackobject.c | 2 +- src/_igraph/edgeseqobject.c | 12 +++---- src/_igraph/graphobject.c | 62 +++++++++++++++++------------------ src/_igraph/vertexobject.c | 6 ++-- src/_igraph/vertexseqobject.c | 12 +++---- 5 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 918a2f697..7f31f506c 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -190,7 +190,7 @@ PyObject* igraphmodule_ARPACKOptions_str( PyMethodDef igraphmodule_ARPACKOptions_methods[] = { /*{"attributes", (PyCFunction)igraphmodule_Edge_attributes, METH_NOARGS, - "attributes() -> list\n\n" + "attributes()\n--\n\n" "Returns the attribute list of the graph's edges\n" },*/ {NULL} diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 311df20dd..507edd3ec 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -796,36 +796,36 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyMethodDef igraphmodule_EdgeSeq_methods[] = { {"attribute_names", (PyCFunction)igraphmodule_EdgeSeq_attribute_names, METH_NOARGS, - "attribute_names() -> list\n--\n\n" + "attribute_names()\n--\n\n" "Returns the attribute name list of the graph's edges\n" }, {"find", (PyCFunction)igraphmodule_EdgeSeq_find, METH_VARARGS, - "find(condition) -> Edge\n--\n\n" + "find(condition)\n--\n\n" "For internal use only.\n" }, {"get_attribute_values", (PyCFunction)igraphmodule_EdgeSeq_get_attribute_values, METH_O, - "get_attribute_values(attrname) -> list\n--\n\n" + "get_attribute_values(attrname)\n--\n\n" "Returns the value of a given edge attribute for all edges.\n\n" "@param attrname: the name of the attribute\n" }, {"is_all", (PyCFunction)igraphmodule_EdgeSeq_is_all, METH_NOARGS, - "is_all() -> bool\n--\n\n" + "is_all()\n--\n\n" "Returns whether the edge sequence contains all the edges exactly once, in\n" "the order of their edge IDs.\n\n" "This is used for optimizations in some of the edge selector routines.\n" }, {"set_attribute_values", (PyCFunction)igraphmodule_EdgeSeq_set_attribute_values, METH_VARARGS | METH_KEYWORDS, - "set_attribute_values(attrname, values) -> list\n--\n\n" + "set_attribute_values(attrname, values)\n--\n\n" "Sets the value of a given edge attribute for all vertices\n" "@param attrname: the name of the attribute\n" "@param values: the new attribute values in a list\n" }, {"select", (PyCFunction)igraphmodule_EdgeSeq_select, METH_VARARGS, - "select(...) -> VertexSeq\n--\n\n" + "select(...)\n--\n\n" "For internal use only.\n" }, {NULL} diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 748114d1d..a488697b4 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11984,21 +11984,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_vcount {"vcount", (PyCFunction) igraphmodule_Graph_vcount, METH_NOARGS, - "vcount() -> int\n--\n\n" + "vcount()\n--\n\n" "Counts the number of vertices.\n" "@return: the number of vertices in the graph.\n" "@rtype: integer"}, // interface to igraph_ecount {"ecount", (PyCFunction) igraphmodule_Graph_ecount, METH_NOARGS, - "ecount() -> int\n--\n\n" + "ecount()\n--\n\n" "Counts the number of edges.\n" "@return: the number of edges in the graph.\n" "@rtype: integer"}, // interface to igraph_is_dag {"is_dag", (PyCFunction) igraphmodule_Graph_is_dag, METH_NOARGS, - "is_dag() -> bool\n--\n\n" + "is_dag()\n--\n\n" "Checks whether the graph is a DAG (directed acyclic graph).\n\n" "A DAG is a directed graph with no directed cycles.\n\n" "@return: C{True} if it is a DAG, C{False} otherwise.\n" @@ -12007,7 +12007,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_is_directed {"is_directed", (PyCFunction) igraphmodule_Graph_is_directed, METH_NOARGS, - "is_directed() -> bool\n--\n\n" + "is_directed()\n--\n\n" "Checks whether the graph is directed.\n" "@return: C{True} if it is directed, C{False} otherwise.\n" "@rtype: boolean"}, @@ -12015,7 +12015,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_is_simple {"is_simple", (PyCFunction) igraphmodule_Graph_is_simple, METH_NOARGS, - "is_simple() -> bool\n--\n\n" + "is_simple()\n--\n\n" "Checks whether the graph is simple (no loop or multiple edges).\n\n" "@return: C{True} if it is simple, C{False} otherwise.\n" "@rtype: boolean"}, @@ -12023,14 +12023,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_add_vertices */ {"add_vertices", (PyCFunction) igraphmodule_Graph_add_vertices, METH_VARARGS, - "add_vertices(n: int) -> None\n--\n\n" + "add_vertices(n: int)\n--\n\n" "Adds vertices to the graph.\n\n" "@param n: the number of vertices to be added\n"}, /* interface to igraph_delete_vertices */ {"delete_vertices", (PyCFunction) igraphmodule_Graph_delete_vertices, METH_VARARGS, - "delete_vertices(vs) -> None\n--\n\n" + "delete_vertices(vs)\n--\n\n" "Deletes vertices and all its edges from the graph.\n\n" "@param vs: a single vertex ID or the list of vertex IDs\n" " to be deleted. No argument deletes all vertices.\n"}, @@ -12038,7 +12038,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_add_edges */ {"add_edges", (PyCFunction) igraphmodule_Graph_add_edges, METH_VARARGS, - "add_edges(es) -> None\n--\n\n" + "add_edges(es)\n--\n\n" "Adds edges to the graph.\n\n" "@param es: the list of edges to be added. Every edge is\n" " represented with a tuple, containing the vertex IDs of the\n" @@ -12047,7 +12047,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_delete_edges */ {"delete_edges", (PyCFunction) igraphmodule_Graph_delete_edges, METH_VARARGS | METH_KEYWORDS, - "delete_edges(es) -> None\n--\n\n" + "delete_edges(es)\n--\n\n" "Removes edges from the graph.\n\n" "All vertices will be kept, even if they lose all their edges.\n" "Nonexistent edges will be silently ignored.\n\n" @@ -12094,7 +12094,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_loop */ {"is_loop", (PyCFunction) igraphmodule_Graph_is_loop, METH_VARARGS | METH_KEYWORDS, - "is_loop(edges=None) -> List[bool]\n--\n\n" + "is_loop(edges=None)\n--\n\n" "Checks whether a specific set of edges contain loop edges\n\n" "@param edges: edge indices which we want to check. If C{None}, all\n" " edges are checked.\n" @@ -12103,7 +12103,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_multiple */ {"is_multiple", (PyCFunction) igraphmodule_Graph_is_multiple, METH_VARARGS | METH_KEYWORDS, - "is_multiple(edges=None) -> List[bool]\n--\n\n" + "is_multiple(edges=None)\n--\n\n" "Checks whether an edge is a multiple edge.\n\n" "Also works for a set of edges -- in this case, every edge is checked\n" "one by one. Note that if there are multiple edges going between a\n" @@ -12118,7 +12118,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_has_multiple */ {"has_multiple", (PyCFunction) igraphmodule_Graph_has_multiple, METH_NOARGS, - "has_multiple() -> bool\n--\n\n" + "has_multiple()\n--\n\n" "Checks whether the graph has multiple edges.\n\n" "@return: C{True} if the graph has at least one multiple edge,\n" " C{False} otherwise.\n" @@ -12127,7 +12127,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_mutual */ {"is_mutual", (PyCFunction) igraphmodule_Graph_is_mutual, METH_VARARGS | METH_KEYWORDS, - "is_mutual(edges=None) -> Lis[bool]\n--\n\n" + "is_mutual(edges=None)\n--\n\n" "Checks whether an edge has an opposite pair.\n\n" "Also works for a set of edges -- in this case, every edge is checked\n" "one by one. The result will be a list of booleans (or a single boolean\n" @@ -12146,7 +12146,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_count_multiple */ {"count_multiple", (PyCFunction) igraphmodule_Graph_count_multiple, METH_VARARGS | METH_KEYWORDS, - "count_multiple(edges=None) -> List[int]\n--\n\n" + "count_multiple(edges=None)\n--\n\n" "Counts the multiplicities of the given edges.\n\n" "@param edges: edge indices for which we want to count their\n" " multiplicity. If C{None}, all edges are counted.\n" @@ -12177,7 +12177,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_eid */ {"get_eid", (PyCFunction) igraphmodule_Graph_get_eid, METH_VARARGS | METH_KEYWORDS, - "get_eid(v1, v2, directed=True, error=True) -> int\n--\n\n" + "get_eid(v1, v2, directed=True, error=True)\n--\n\n" "Returns the edge ID of an arbitrary edge between vertices v1 and v2\n\n" "@param v1: the ID or name of the first vertex\n" "@param v2: the ID or name of the second vertex\n" @@ -12192,7 +12192,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_eids */ {"get_eids", (PyCFunction) igraphmodule_Graph_get_eids, METH_VARARGS | METH_KEYWORDS, - "get_eids(pairs=None, path=None, directed=True, error=True) -> List[int]\n--\n\n" + "get_eids(pairs=None, path=None, directed=True, error=True)\n--\n\n" "Returns the edge IDs of some edges between some vertices.\n\n" "This method can operate in two different modes, depending on which\n" "of the keyword arguments C{pairs} and C{path} are given.\n\n" @@ -12779,7 +12779,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_are_connected {"are_connected", (PyCFunction) igraphmodule_Graph_are_connected, METH_VARARGS | METH_KEYWORDS, - "are_connected(v1, v2) -> bool\n--\n\n" + "are_connected(v1, v2)\n--\n\n" "Decides whether two given vertices are directly connected.\n\n" "@param v1: the ID or name of the first vertex\n" "@param v2: the ID or name of the second vertex\n" @@ -13088,7 +13088,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_density */ {"density", (PyCFunction) igraphmodule_Graph_density, METH_VARARGS | METH_KEYWORDS, - "density(loops=False) -> float\n--\n\n" + "density(loops=False)\n--\n\n" "Calculates the density of the graph.\n\n" "@param loops: whether to take loops into consideration. If C{True},\n" " the algorithm assumes that there might be some loops in the graph\n" @@ -13412,7 +13412,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_bipartite */ {"is_bipartite", (PyCFunction) igraphmodule_Graph_is_bipartite, METH_VARARGS | METH_KEYWORDS, - "is_bipartite(return_types=False) -> bool\n--\n\n" + "is_bipartite(return_types=False)\n--\n\n" "Decides whether the graph is bipartite or not.\n\n" "Vertices of a bipartite graph can be partitioned into two groups A\n" "and B in a way that all edges go between the two groups.\n\n" @@ -13450,7 +13450,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_connected */ {"is_connected", (PyCFunction) igraphmodule_Graph_is_connected, METH_VARARGS | METH_KEYWORDS, - "is_connected(mode=STRONG) -> bool\n--\n\n" + "is_connected(mode=STRONG)\n--\n\n" "Decides whether the graph is connected.\n\n" "@param mode: whether we should calculate strong or weak connectivity.\n" "@return: C{True} if the graph is connected, C{False} otherwise.\n"}, @@ -13640,7 +13640,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_reciprocity */ {"reciprocity", (PyCFunction) igraphmodule_Graph_reciprocity, METH_VARARGS | METH_KEYWORDS, - "reciprocity(ignore_loops=True, mode=\"default\") -> float\n--\n\n" + "reciprocity(ignore_loops=True, mode=\"default\")\n--\n\n" "Reciprocity defines the proportion of mutual connections in a\n" "directed graph. It is most commonly defined as the probability\n" "that the opposite counterpart of a directed edge is also included\n" @@ -14908,7 +14908,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the isomorphism class of the (sub)graph\n\n"}, {"isomorphic", (PyCFunction) igraphmodule_Graph_isomorphic, METH_VARARGS | METH_KEYWORDS, - "isomorphic(other) -> bool\n--\n\n" + "isomorphic(other)\n--\n\n" "Checks whether the graph is isomorphic to another graph.\n\n" "The algorithm being used is selected using a simple heuristic:\n\n" " - If one graph is directed and the other undirected, an exception\n" @@ -15265,15 +15265,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { //////////////////////// {"attributes", (PyCFunction) igraphmodule_Graph_attributes, METH_NOARGS, - "attributes() -> Sequence[str]\n--\n\n" + "attributes()\n--\n\n" "@return: the attribute name list of the graph\n"}, {"vertex_attributes", (PyCFunction) igraphmodule_Graph_vertex_attributes, METH_NOARGS, - "vertex_attributes() -> Sequence[str]\n--\n\n" + "vertex_attributes()\n--\n\n" "@return: the attribute name list of the graph's vertices\n"}, {"edge_attributes", (PyCFunction) igraphmodule_Graph_edge_attributes, METH_NOARGS, - "edge_attributes() -> Sequence[str]\n--\n\n" + "edge_attributes()\n--\n\n" "@return: the attribute name list of the graph's edges\n"}, /////////////// @@ -15544,7 +15544,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@see: L{largest_cliques()} for the largest cliques."}, {"clique_number", (PyCFunction) igraphmodule_Graph_clique_number, METH_NOARGS, - "clique_number() -> int\n--\n\n" + "clique_number()\n--\n\n" "Returns the clique number of the graph.\n\n" "The clique number of the graph is the size of the largest clique.\n\n" "@see: L{largest_cliques()} for the largest cliques."}, @@ -15589,7 +15589,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"independence_number", (PyCFunction) igraphmodule_Graph_independence_number, METH_NOARGS, - "independence_number() -> int\n--\n\n" + "independence_number()\n--\n\n" "Returns the independence number of the graph.\n\n" "The independence number of the graph is the size of the largest\n" "independent vertex set.\n\n" @@ -15601,7 +15601,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*********************************/ {"modularity", (PyCFunction) igraphmodule_Graph_modularity, METH_VARARGS | METH_KEYWORDS, - "modularity(membership, weights=None, resolution=1, directed=True) -> float\n--\n\n" + "modularity(membership, weights=None, resolution=1, directed=True)\n--\n\n" "Calculates the modularity of the graph with respect to some vertex types.\n\n" "The modularity of a graph w.r.t. some division measures how good the\n" "division is, or how separated are the different vertex types from each\n" @@ -15639,7 +15639,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"coreness", (PyCFunction) igraphmodule_Graph_coreness, METH_VARARGS | METH_KEYWORDS, - "coreness(mode=ALL) -> Sequence[int]\n--\n\n" + "coreness(mode=ALL)\n--\n\n" "Finds the coreness (shell index) of the vertices of the network.\n\n" "The M{k}-core of a graph is a maximal subgraph in which each vertex\n" "has at least degree k. (Degree here means the degree in the\n" @@ -15975,7 +15975,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"_raw_pointer", (PyCFunction) igraphmodule_Graph__raw_pointer, METH_NOARGS, - "_raw_pointer() -> int\n--\n\n" + "_raw_pointer()\n--\n\n" "Returns the memory address of the igraph graph encapsulated by the Python\n" "object as an ordinary Python integer.\n\n" "This function should not be used directly by igraph users, it is useful\n" @@ -15985,7 +15985,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"__register_destructor", (PyCFunction) igraphmodule_Graph___register_destructor__, METH_VARARGS | METH_KEYWORDS, - "__register_destructor(destructor) -> None\n--\n\n" + "__register_destructor(destructor)\n--\n\n" "Registers a destructor to be called when the object is freed by\n" "Python. This function should not be used directly by igraph users."}, diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index f64b2c608..0e5f28b77 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -733,17 +733,17 @@ GRAPH_PROXY_METHOD_PP(successors, "successors", _convert_to_vertex_list); PyMethodDef igraphmodule_Vertex_methods[] = { {"attributes", (PyCFunction)igraphmodule_Vertex_attributes, METH_NOARGS, - "attributes() -> dict\n--\n\n" + "attributes()\n--\n\n" "Returns a dict of attribute names and values for the vertex\n" }, {"attribute_names", (PyCFunction)igraphmodule_Vertex_attribute_names, METH_NOARGS, - "attribute_names() -> list\n--\n\n" + "attribute_names()\n--\n\n" "Returns the list of vertex attribute names\n" }, {"update_attributes", (PyCFunction)igraphmodule_Vertex_update_attributes, METH_VARARGS | METH_KEYWORDS, - "update_attributes(E, **F) -> None\n--\n\n" + "update_attributes(E, **F)\n--\n\n" "Updates the attributes of the vertex from dict/iterable E and F.\n\n" "If E has a C{keys()} method, it does: C{for k in E: self[k] = E[k]}.\n" "If E lacks a C{keys()} method, it does: C{for (k, v) in E: self[k] = v}.\n" diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 6560368cb..2101b22d3 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -898,17 +898,17 @@ PyObject* igraphmodule_VertexSeq__reindex_names(igraphmodule_VertexSeqObject* se PyMethodDef igraphmodule_VertexSeq_methods[] = { {"attribute_names", (PyCFunction)igraphmodule_VertexSeq_attribute_names, METH_NOARGS, - "attribute_names() -> list\n--\n\n" + "attribute_names()\n--\n\n" "Returns the attribute name list of the graph's vertices\n" }, {"find", (PyCFunction)igraphmodule_VertexSeq_find, METH_VARARGS, - "find(condition) -> Vertex\n--\n\n" + "find(condition)\n--\n\n" "For internal use only.\n" }, {"get_attribute_values", (PyCFunction)igraphmodule_VertexSeq_get_attribute_values, METH_O, - "get_attribute_values(attrname) -> list\n--\n\n" + "get_attribute_values(attrname)\n--\n\n" "Returns the value of a given vertex attribute for all vertices in a list.\n\n" "The values stored in the list are exactly the same objects that are stored\n" "in the vertex attribute, meaning that in the case of mutable objects,\n" @@ -919,18 +919,18 @@ PyMethodDef igraphmodule_VertexSeq_methods[] = { }, {"set_attribute_values", (PyCFunction)igraphmodule_VertexSeq_set_attribute_values, METH_VARARGS | METH_KEYWORDS, - "set_attribute_values(attrname, values) -> list\n--\n\n" + "set_attribute_values(attrname, values)\n--\n\n" "Sets the value of a given vertex attribute for all vertices\n\n" "@param attrname: the name of the attribute\n" "@param values: the new attribute values in a list\n" }, {"select", (PyCFunction)igraphmodule_VertexSeq_select, METH_VARARGS, - "select(...) -> VertexSeq\n--\n\n" + "select(*args, **kwds)\n--\n\n" "For internal use only.\n" }, {"_reindex_names", (PyCFunction)igraphmodule_VertexSeq__reindex_names, METH_NOARGS, - "_reindex_names() -> None\n--\n\n" + "_reindex_names()\n--\n\n" "Re-creates the dictionary that maps vertex names to IDs.\n\n" "For internal use only.\n" }, From d37e883c3274faddf9092a3ce5b31a0beaa8760f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 11:35:17 +0100 Subject: [PATCH 0409/1892] doc: fix a few more docstrings to be compatible with __text_signature__ --- src/_igraph/graphobject.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index a488697b4..13c5d4d7c 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13974,7 +13974,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_similarity_dice */ {"similarity_dice", (PyCFunction) igraphmodule_Graph_similarity_dice, METH_VARARGS | METH_KEYWORDS, - "similarity_dice(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n\n" + "similarity_dice(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n--\n\n" "Dice similarity coefficient of vertices.\n\n" "The Dice similarity coefficient of two vertices is twice the number of\n" "their common neighbors divided by the sum of their degrees. This\n" @@ -14435,7 +14435,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_mds", (PyCFunction) igraphmodule_Graph_layout_mds, METH_VARARGS | METH_KEYWORDS, - "layout_mds(dist=None, dim=2, arpack_options=None)\n--\n" + "layout_mds(dist=None, dim=2, arpack_options=None)\n--\n\n" "Places the vertices in an Euclidean space with the given number of\n" "dimensions using multidimensional scaling.\n\n" "This layout requires a distance matrix, where the intersection of\n" @@ -14468,7 +14468,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_reingold_tilford", (PyCFunction) igraphmodule_Graph_layout_reingold_tilford, METH_VARARGS | METH_KEYWORDS, - "layout_reingold_tilford(mode=\"out\", root=None, rootlevel=None)\n--\n" + "layout_reingold_tilford(mode=\"out\", root=None, rootlevel=None)\n--\n\n" "Places the vertices on a 2D plane according to the Reingold-Tilford\n" "layout algorithm.\n\n" "This is a tree layout. If the given graph is not a tree, a breadth-first\n" @@ -14498,7 +14498,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_reingold_tilford_circular", (PyCFunction) igraphmodule_Graph_layout_reingold_tilford_circular, METH_VARARGS | METH_KEYWORDS, - "layout_reingold_tilford_circular(mode=\"out\", root=None, rootlevel=None)\n--\n" + "layout_reingold_tilford_circular(mode=\"out\", root=None, rootlevel=None)\n--\n\n" "Circular Reingold-Tilford layout for trees.\n\n" "This layout is similar to the Reingold-Tilford layout, but the vertices\n" "are placed in a circular way, with the root vertex in the center.\n\n" @@ -14512,7 +14512,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_layout_random */ {"layout_random", (PyCFunction) igraphmodule_Graph_layout_random, METH_VARARGS | METH_KEYWORDS, - "layout_random(dim=2)\n--\n" + "layout_random(dim=2)\n--\n\n" "Places the vertices of the graph randomly.\n\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" @@ -15053,8 +15053,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " number of automorphisms if C{other} is C{None}.\n"}, {"get_isomorphisms_vf2", (PyCFunction) igraphmodule_Graph_get_isomorphisms_vf2, METH_VARARGS | METH_KEYWORDS, - "get_isomorphisms_vf2(other=None, color1=None, color2=None, edge_color1=None,\n" - " edge_color2=None, node_compat_fn=None, edge_compat_fn=None)\n\n" + "get_isomorphisms_vf2(other=None, color1=None, color2=None, edge_color1=None, " + "edge_color2=None, node_compat_fn=None, edge_compat_fn=None)\n--\n\n" "Returns all isomorphisms between the graph and another one\n\n" "Vertex and edge colors may be used to restrict the isomorphisms, as only\n" "vertices and edges with the same color will be allowed to match each other.\n\n" @@ -15286,10 +15286,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param loops: whether to include loop edges in the complementer.\n" "@return: the complementer of the graph\n"}, {"compose", (PyCFunction) igraphmodule_Graph_compose, - METH_O, "compose(other)\n\nReturns the composition of two graphs."}, + METH_O, "compose(other)\n--\n\nReturns the composition of two graphs."}, {"difference", (PyCFunction) igraphmodule_Graph_difference, METH_O, - "difference(other)\n\nSubtracts the given graph from the original"}, + "difference(other)\n--\n\nSubtracts the given graph from the original"}, /**********************/ /* DOMINATORS */ From 10ed4ce0c2dbdab67a5d176a6dc4d14a9e934283 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 7 Mar 2021 11:36:58 +0100 Subject: [PATCH 0410/1892] doc: remove typings from text signatures in Edge class --- src/_igraph/edgeobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index f42dfa326..c69881899 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -613,17 +613,17 @@ GRAPH_PROXY_METHOD(is_mutual, "is_mutual"); PyMethodDef igraphmodule_Edge_methods[] = { {"attributes", (PyCFunction)igraphmodule_Edge_attributes, METH_NOARGS, - "attributes() -> dict\n--\n\n" + "attributes()\n--\n\n" "Returns a dict of attribute names and values for the edge\n" }, {"attribute_names", (PyCFunction)igraphmodule_Edge_attribute_names, METH_NOARGS, - "attribute_names() -> list\n--\n\n" + "attribute_names()\n--\n\n" "Returns the list of edge attribute names\n" }, {"update_attributes", (PyCFunction)igraphmodule_Edge_update_attributes, METH_VARARGS | METH_KEYWORDS, - "update_attributes(E, **F) -> None\n--\n\n" + "update_attributes(E, **F)\n--\n\n" "Updates the attributes of the edge from dict/iterable E and F.\n\n" "If E has a C{keys()} method, it does: C{for k in E: self[k] = E[k]}.\n" "If E lacks a C{keys()} method, it does: C{for (k, v) in E: self[k] = v}.\n" From 451658d31c7604d393a949c8132fd254b742bed7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Mar 2021 14:43:09 +0100 Subject: [PATCH 0411/1892] doc: documentation fixes for PyDoctor --- doc/source/tutorial.rst | 2 +- src/_igraph/convert.c | 16 ++ src/_igraph/convert.h | 1 + src/_igraph/edgeobject.c | 8 +- src/_igraph/edgeseqobject.c | 2 +- src/_igraph/graphobject.c | 295 ++++++++++++++++----------------- src/_igraph/vertexobject.c | 24 +-- src/_igraph/vertexseqobject.c | 2 +- src/igraph/__init__.py | 302 +++++++++++++++------------------- src/igraph/app/shell.py | 6 +- src/igraph/clustering.py | 13 +- src/igraph/layout.py | 5 +- 12 files changed, 328 insertions(+), 348 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 16ac2c6be..84480fa6c 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -140,7 +140,7 @@ Traceback (most recent call last): File "", line 6, in TypeError: iterable must return pairs of integers or strings -Most |igraph| functions will raise an :exc:`igraph.core.InternalError` if +Most |igraph| functions will raise an :exc:`igraph.InternalError` if something goes wrong. The message corresponding to the exception gives you a short textual explanation of what went wrong (``cannot add edges, invalid vertex id``) along with the corresponding line in the C source where the error diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 762bbeaf9..f92013947 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -476,6 +476,22 @@ int igraphmodule_PyObject_to_fas_algorithm_t(PyObject *o, return igraphmodule_PyObject_to_enum(o, fas_algorithm_tt, (int*)result); } +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_get_adjacency_t + */ +int igraphmodule_PyObject_to_get_adjacency_t(PyObject *o, + igraph_get_adjacency_t *result) { + static igraphmodule_enum_translation_table_entry_t get_adjacency_tt[] = { + {"lower", IGRAPH_GET_ADJACENCY_LOWER}, + {"upper", IGRAPH_GET_ADJACENCY_UPPER}, + {"both", IGRAPH_GET_ADJACENCY_BOTH}, + {0,0} + }; + + return igraphmodule_PyObject_to_enum(o, get_adjacency_tt, (int*)result); +} + /** * \brief Converts a Python object to an igraph \c igraph_layout_grid_t */ diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 7af034738..d777406d4 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -60,6 +60,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_get_adjacency_t(PyObject *o, igraph_get_adjacency_t *result); int igraphmodule_PyObject_to_layout_grid_t(PyObject *o, igraph_layout_grid_t *result); int igraphmodule_PyObject_to_neimode_t(PyObject *o, igraph_neimode_t *result); int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t *result); diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index c69881899..6f3010ee4 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -595,16 +595,16 @@ GRAPH_PROXY_METHOD(is_mutual, "is_mutual"); #define GRAPH_PROXY_METHOD_SPEC(FUNC, METHODNAME) \ {METHODNAME, (PyCFunction)igraphmodule_Edge_##FUNC, METH_VARARGS | METH_KEYWORDS, \ - "Proxy method to L{Graph." METHODNAME "()}\n\n" \ + "Proxy method to L{Graph." METHODNAME "()}\n\n" \ "This method calls the " METHODNAME " method of the L{Graph} class " \ "with this edge as the first argument, and returns the result.\n\n"\ - "@see: Graph." METHODNAME "() for details."} + "@see: L{Graph." METHODNAME "()} for details."} #define GRAPH_PROXY_METHOD_SPEC_2(FUNC, METHODNAME, METHODNAME_IN_GRAPH) \ {METHODNAME, (PyCFunction)igraphmodule_Edge_##FUNC, METH_VARARGS | METH_KEYWORDS, \ - "Proxy method to L{Graph." METHODNAME_IN_GRAPH "()}\n\n" \ + "Proxy method to L{Graph." METHODNAME_IN_GRAPH "()}\n\n" \ "This method calls the " METHODNAME_IN_GRAPH " method of the L{Graph} class " \ "with this edge as the first argument, and returns the result.\n\n"\ - "@see: Graph." METHODNAME_IN_GRAPH "() for details."} + "@see: L{Graph." METHODNAME_IN_GRAPH "()} for details."} /** * \ingroup python_interface_edge diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 507edd3ec..96ee3f19f 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -920,7 +920,7 @@ PyGetSetDef igraphmodule_EdgeSeq_getseters[] = { PyTypeObject igraphmodule_EdgeSeqType = { PyVarObject_HEAD_INIT(0, 0) - "igraph.core.EdgeSeq", /* tp_name */ + "igraph._igraph.EdgeSeq", /* tp_name */ sizeof(igraphmodule_EdgeSeqObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)igraphmodule_EdgeSeq_dealloc, /* tp_dealloc */ diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 13c5d4d7c..48cda7d44 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2136,7 +2136,7 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, igraph_bool_t has_inseq = 0; PyObject *outdeg = NULL, *indeg = NULL, *method = NULL; - static char *kwlist[] = { "out", "in", "method", NULL }; + static char *kwlist[] = { "out", "in_", "method", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!O", kwlist, &PyList_Type, &outdeg, @@ -2632,7 +2632,7 @@ PyObject *igraphmodule_Graph_Isoclass(PyTypeObject * type, igraphmodule_GraphObject *self; igraph_t g; - static char *kwlist[] = { "n", "class", "directed", NULL }; + static char *kwlist[] = { "n", "cls", "directed", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O", kwlist, &n, &isoclass, &directed)) @@ -7497,19 +7497,14 @@ PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "type", "eids", NULL }; - igraph_get_adjacency_t t = IGRAPH_GET_ADJACENCY_BOTH; + igraph_get_adjacency_t mode = IGRAPH_GET_ADJACENCY_BOTH; igraph_matrix_t m; - PyObject *result, *eids = Py_False; + PyObject *result, *mode_o = Py_None, *eids = Py_False; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &t, &eids)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &eids)) return NULL; - if (t != IGRAPH_GET_ADJACENCY_UPPER && t != IGRAPH_GET_ADJACENCY_LOWER && - t != IGRAPH_GET_ADJACENCY_BOTH) { - PyErr_SetString(PyExc_ValueError, - "type must be either GET_ADJACENCY_LOWER or GET_ADJACENCY_UPPER or GET_ADJACENCY_BOTH"); - return NULL; - } + if (igraphmodule_PyObject_to_get_adjacency_t(mode_o, &mode)) return NULL; if (igraph_matrix_init (&m, igraph_vcount(&self->g), igraph_vcount(&self->g))) { @@ -7517,7 +7512,7 @@ PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, return NULL; } - if (igraph_get_adjacency(&self->g, &m, t, PyObject_IsTrue(eids))) { + if (igraph_get_adjacency(&self->g, &m, mode, PyObject_IsTrue(eids))) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&m); return NULL; @@ -12023,7 +12018,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_add_vertices */ {"add_vertices", (PyCFunction) igraphmodule_Graph_add_vertices, METH_VARARGS, - "add_vertices(n: int)\n--\n\n" + "add_vertices(n)\n--\n\n" "Adds vertices to the graph.\n\n" "@param n: the number of vertices to be added\n"}, @@ -12058,7 +12053,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_degree */ {"degree", (PyCFunction) igraphmodule_Graph_degree, METH_VARARGS | METH_KEYWORDS, - "degree(vertices, mode=ALL, loops=True)\n--\n\n" + "degree(vertices, mode=\"all\", loops=True)\n--\n\n" "Returns some vertex degrees from the graph.\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the degree of the given vertices (in the\n" @@ -12066,14 +12061,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "parameter).\n" "\n" "@param vertices: a single vertex ID or a list of vertex IDs\n" - "@param mode: the type of degree to be returned (L{OUT} for\n" - " out-degrees, L{IN} IN for in-degrees or L{ALL} for the sum of\n" - " them).\n" "@param loops: whether self-loops should be counted.\n"}, + "@param mode: the type of degree to be returned (C{\"out\"} for\n" + " out-degrees, C{\"in\"} for in-degrees or C{\"all\"} for the sum of\n" + " them).\n" + "@param loops: whether self-loops should be counted.\n"}, /* interface to igraph_strength */ {"strength", (PyCFunction) igraphmodule_Graph_strength, METH_VARARGS | METH_KEYWORDS, - "strength(vertices, mode=ALL, loops=True, weights=None)\n--\n\n" + "strength(vertices, mode=\"all\", loops=True, weights=None)\n--\n\n" "Returns the strength (weighted degree) of some vertices from the graph\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the strength (that is, the sum of the weights\n" @@ -12082,8 +12078,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "parameter).\n" "\n" "@param vertices: a single vertex ID or a list of vertex IDs\n" - "@param mode: the type of degree to be returned (L{OUT} for\n" - " out-degrees, L{IN} IN for in-degrees or L{ALL} for the sum of\n" + "@param mode: the type of degree to be returned (C{\"out\"} for\n" + " out-degrees, C{\"in\"} for in-degrees or C{\"all\"} for the sum of\n" " them).\n" "@param loops: whether self-loops should be counted.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" @@ -12155,24 +12151,24 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_neighbors */ {"neighbors", (PyCFunction) igraphmodule_Graph_neighbors, METH_VARARGS | METH_KEYWORDS, - "neighbors(vertex, mode=ALL)\n--\n\n" + "neighbors(vertex, mode=\"all\")\n--\n\n" "Returns adjacent vertices to a given vertex.\n\n" "@param vertex: a vertex ID\n" - "@param mode: whether to return only successors (L{OUT}),\n" - " predecessors (L{IN}) or both (L{ALL}). Ignored for undirected\n" + "@param mode: whether to return only successors (C{\"out\"}),\n" + " predecessors (C{\"in\"}) or both (C{\"all\"}). Ignored for undirected\n" " graphs."}, {"successors", (PyCFunction) igraphmodule_Graph_successors, METH_VARARGS | METH_KEYWORDS, "successors(vertex)\n--\n\n" "Returns the successors of a given vertex.\n\n" - "Equivalent to calling the L{Graph.neighbors} method with type=L{OUT}."}, + "Equivalent to calling the L{neighbors()} method with type=C{\"out\"}."}, {"predecessors", (PyCFunction) igraphmodule_Graph_predecessors, METH_VARARGS | METH_KEYWORDS, "predecessors(vertex)\n--\n\n" "Returns the predecessors of a given vertex.\n\n" - "Equivalent to calling the L{Graph.neighbors} method with type=L{IN}."}, + "Equivalent to calling the L{neighbors()} method with type=C{\"in\"}."}, /* interface to igraph_get_eid */ {"get_eid", (PyCFunction) igraphmodule_Graph_get_eid, @@ -12220,11 +12216,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_incident */ {"incident", (PyCFunction) igraphmodule_Graph_incident, METH_VARARGS | METH_KEYWORDS, - "incident(vertex, mode=OUT)\n--\n\n" + "incident(vertex, mode=\"out\")\n--\n\n" "Returns the edges a given vertex is incident on.\n\n" "@param vertex: a vertex ID\n" - "@param mode: whether to return only successors (L{OUT}),\n" - " predecessors (L{IN}) or both (L{ALL}). Ignored for undirected\n" + "@param mode: whether to return only successors (C{\"out\"}),\n" + " predecessors (C{\"in\"}) or both (C{\"all\"}). Ignored for undirected\n" " graphs."}, ////////////////////// @@ -12234,24 +12230,22 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_adjacency */ {"Adjacency", (PyCFunction) igraphmodule_Graph_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Adjacency(matrix, mode=ADJ_DIRECTED)\n--\n\n" + "Adjacency(matrix, mode=\"directed\")\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" "\n" - " - C{ADJ_DIRECTED} - the graph will be directed and a matrix\n" - " element gives the number of edges between two vertex.\n" - " - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience.\n" - " - C{ADJ_MAX} - undirected graph will be created and the number of\n" + " - C{\"directed\"} - the graph will be directed and a matrix\n" + " element gives the number of edges between two vertices.\n" + " - C{\"undirected\"} - alias to C{\"max\"} for convenience.\n" + " - C{\"max\"} - undirected graph will be created and the number of\n" " edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))}\n" - " - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))}\n" - " - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)}\n" - " - C{ADJ_UPPER} - undirected graph with the upper right triangle of\n" + " - C{\"min\"} - like C{\"max\"}, but with M{min(A(i,j), A(j,i))}\n" + " - C{\"plus\"} - like C{\"max\"}, but with M{A(i,j) + A(j,i)}\n" + " - C{\"upper\"} - undirected graph with the upper right triangle of\n" " the matrix (including the diagonal)\n" - " - C{ADJ_LOWER} - undirected graph with the lower left triangle of\n" + " - C{\"lower\"} - undirected graph with the lower left triangle of\n" " the matrix (including the diagonal)\n" - "\n" - " These values can also be given as strings without the C{ADJ} prefix.\n" }, /* interface to igraph_asymmetric_preference_game */ @@ -12260,7 +12254,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Asymmetric_Preference(n, type_dist_matrix, pref_matrix, attribute=None, loops=False)\n--\n\n" "Generates a graph based on asymmetric vertex types and connection probabilities.\n\n" - "This is the asymmetric variant of L{Graph.Preference}.\n" + "This is the asymmetric variant of L{Preference()}.\n" "A given number of vertices are generated. Every vertex is assigned to an\n" "\"incoming\" and an \"outgoing\" vertex type according to the given joint\n" "type probabilities. Finally, every vertex pair is evaluated and a\n" @@ -12279,7 +12273,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_atlas {"Atlas", (PyCFunction) igraphmodule_Graph_Atlas, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Atlas(idx: int)\n--\n\n" + "Atlas(idx)\n--\n\n" "Generates a graph from the Graph Atlas.\n\n" "@param idx: The index of the graph to be generated.\n" " Indices start from zero, graphs are listed:\n\n" @@ -12330,7 +12324,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " it will generate multiple edges as well. igraph before\n" " 0.6 used this algorithm for I{power}s other than 1.\n\n" "@param start_from: if given and not C{None}, this must be another\n" - " L{Graph} object. igraph will use this graph as a starting\n" + " L{GraphBase} object. igraph will use this graph as a starting\n" " point for the preferential attachment model.\n\n" "@newfield ref: Reference\n" "@ref: Barabasi, A-L and Albert, R. 1999. Emergence of scaling\n" @@ -12468,7 +12462,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_incidence */ {"_Incidence", (PyCFunction) igraphmodule_Graph_Incidence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Incidence(matrix, directed=False, mode=ALL, multiple=False)\n--\n\n" + "_Incidence(matrix, directed=False, mode=\"all\", multiple=False)\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.Incidence()\n\n"}, @@ -12508,7 +12502,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Preference(n, type_dist, pref_matrix, attribute=None, directed=False, loops=False)\n--\n\n" "Generates a graph based on vertex types and connection probabilities.\n\n" - "This is practically the nongrowing variant of L{Graph.Establishment}.\n" + "This is practically the nongrowing variant of L{Establishment}.\n" "A given number of vertices are generated. Every vertex is assigned to a\n" "vertex type according to the given type probabilities. Finally, every\n" "vertex pair is evaluated and an edge is created between them with a\n" @@ -12677,24 +12671,24 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_tree {"Tree", (PyCFunction) igraphmodule_Graph_Tree, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Tree(n, children, type=TREE_UNDIRECTED)\n--\n\n" + "Tree(n, children, type=\"undirected\")\n--\n\n" "Generates a tree in which almost all vertices have the same number of children.\n\n" "@param n: the number of vertices in the graph\n" "@param children: the number of children of a vertex in the graph\n" "@param type: determines whether the tree should be directed, and if\n" " this is the case, also its orientation. Must be one of\n" - " C{TREE_IN}, C{TREE_OUT} and C{TREE_UNDIRECTED}.\n"}, + " C{\"in\"}, C{\"out\"} and C{\"undirected\"}.\n"}, /* interface to igraph_degree_sequence_game */ {"Degree_Sequence", (PyCFunction) igraphmodule_Graph_Degree_Sequence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Degree_Sequence(out, in=None, method=\"simple\")\n--\n\n" + "Degree_Sequence(out, in_=None, method=\"simple\")\n--\n\n" "Generates a graph with a given degree sequence.\n\n" "@param out: the out-degree sequence for a directed graph. If the\n" " in-degree sequence is omitted, the generated graph\n" " will be undirected, so this will be the in-degree\n" " sequence as well\n" - "@param in: the in-degree sequence for a directed graph.\n" + "@param in_: the in-degree sequence for a directed graph.\n" " If omitted, the generated graph will be undirected.\n" "@param method: the generation method to be used. One of the following:\n" " \n" @@ -12722,10 +12716,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_isoclass_create */ {"Isoclass", (PyCFunction) igraphmodule_Graph_Isoclass, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Isoclass(n, class, directed=False)\n--\n\n" + "Isoclass(n, cls, directed=False)\n--\n\n" "Generates a graph with a given isomorphism class.\n\n" "@param n: the number of vertices in the graph (3 or 4)\n" - "@param class: the isomorphism class\n" + "@param cls: the isomorphism class\n" "@param directed: whether the graph should be directed.\n"}, /* interface to igraph_watts_strogatz_game */ @@ -12748,24 +12742,22 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_weighted_adjacency */ {"Weighted_Adjacency", (PyCFunction) igraphmodule_Graph_Weighted_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Weighted_Adjacency(matrix, mode=ADJ_DIRECTED, attr=\"weight\", loops=True)\n--\n\n" + "Weighted_Adjacency(matrix, mode=\"directed\", attr=\"weight\", loops=True)\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" "\n" - " - C{ADJ_DIRECTED} - the graph will be directed and a matrix\n" - " element gives the number of edges between two vertex.\n" - " - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience.\n" - " - C{ADJ_MAX} - undirected graph will be created and the number of\n" + " - C{\"directed\"} - the graph will be directed and a matrix\n" + " element gives the number of edges between two vertices.\n" + " - C{\"undirected\"} - alias to C{\"max\"} for convenience.\n" + " - C{\"max\"} - undirected graph will be created and the number of\n" " edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))}\n" - " - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))}\n" - " - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)}\n" - " - C{ADJ_UPPER} - undirected graph with the upper right triangle of\n" + " - C{\"min\"} - like C{\"max\"}, but with M{min(A(i,j), A(j,i))}\n" + " - C{\"plus\"} - like C{\"max\"}, but with M{A(i,j) + A(j,i)}\n" + " - C{\"upper\"} - undirected graph with the upper right triangle of\n" " the matrix (including the diagonal)\n" - " - C{ADJ_LOWER} - undirected graph with the lower left triangle of\n" + " - C{\"lower\"} - undirected graph with the lower left triangle of\n" " the matrix (including the diagonal)\n" - "\n" - " These values can also be given as strings without the C{ADJ} prefix.\n" "@param attr: the name of the edge attribute that stores the edge\n" " weights.\n" "@param loops: whether to include loop edges. When C{False}, the diagonal\n" @@ -12949,7 +12941,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_closeness */ {"closeness", (PyCFunction) igraphmodule_Graph_closeness, METH_VARARGS | METH_KEYWORDS, - "closeness(vertices=None, mode=ALL, cutoff=None, weights=None, " + "closeness(vertices=None, mode=\"all\", cutoff=None, weights=None, " "normalized=True)\n--\n\n" "Calculates the closeness centralities of given vertices in a graph.\n\n" "The closeness centerality of a vertex measures how easily other\n" @@ -12963,9 +12955,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "geodesic.\n\n" "@param vertices: the vertices for which the closenesses must\n" " be returned. If C{None}, uses all of the vertices in the graph.\n" - "@param mode: must be one of L{IN}, L{OUT} and L{ALL}. L{IN} means\n" - " that the length of the incoming paths, L{OUT} means that the\n" - " length of the outgoing paths must be calculated. L{ALL} means\n" + "@param mode: must be one of C{\"in\"}, C{\"out\"} and C{\"all\"}. C{\"in\"} means\n" + " that the length of the incoming paths, C{\"out\"} means that the\n" + " length of the outgoing paths must be calculated. C{\"all\"} means\n" " that both of them must be calculated.\n" "@param cutoff: if it is an integer, only paths less than or equal to this\n" " length are considered, effectively resulting in an estimation of the\n" @@ -12982,7 +12974,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_harmonic_centrality */ {"harmonic_centrality", (PyCFunction) igraphmodule_Graph_harmonic_centrality, METH_VARARGS | METH_KEYWORDS, - "harmonic_centrality(vertices=None, mode=ALL, cutoff=None, weights=None, " + "harmonic_centrality(vertices=None, mode=\"all\", cutoff=None, weights=None, " "normalized=True)\n--\n\n" "Calculates the harmonic centralities of given vertices in a graph.\n\n" "The harmonic centerality of a vertex measures how easily other\n" @@ -12993,9 +12985,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "vertices, the inverse distance is taken to be zero.\n\n" "@param vertices: the vertices for which the harmonic centrality must\n" " be returned. If C{None}, uses all of the vertices in the graph.\n" - "@param mode: must be one of L{IN}, L{OUT} and L{ALL}. L{IN} means\n" - " that the length of the incoming paths, L{OUT} means that the\n" - " length of the outgoing paths must be calculated. L{ALL} means\n" + "@param mode: must be one of C{\"in\"}, C{\"out\"} and C{\"all\"}. C{\"in\"} means\n" + " that the length of the incoming paths, C{\"out\"} means that the\n" + " length of the outgoing paths must be calculated. C{\"all\"} means\n" " that both of them must be calculated.\n" "@param cutoff: if it is not C{None}, only paths less than or equal to this\n" " length are considered.\n" @@ -13010,13 +13002,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_clusters */ {"clusters", (PyCFunction) igraphmodule_Graph_clusters, METH_VARARGS | METH_KEYWORDS, - "clusters(mode=STRONG)\n--\n\n" + "clusters(mode=\"strong\")\n--\n\n" "Calculates the (strong or weak) clusters for a given graph.\n\n" "@attention: this function has a more convenient interface in class\n" " L{Graph} which wraps the result in a L{VertexClustering} object.\n" " It is advised to use that.\n" - "@param mode: must be either C{STRONG} or C{WEAK}, depending on\n" - " the clusters being sought. Optional, defaults to C{STRONG}.\n" + "@param mode: must be either C{\"strong\"} or C{\"weak\"}, depending on\n" + " the clusters being sought. Optional, defaults to C{\"strong\"}.\n" "@return: the component index for every node in the graph.\n"}, {"copy", (PyCFunction) igraphmodule_Graph_copy, METH_NOARGS, @@ -13029,10 +13021,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"decompose", (PyCFunction) igraphmodule_Graph_decompose, METH_VARARGS | METH_KEYWORDS, - "decompose(mode=STRONG, maxcompno=None, minelements=1)\n--\n\n" + "decompose(mode=\"strong\", maxcompno=None, minelements=1)\n--\n\n" "Decomposes the graph into subgraphs.\n\n" - "@param mode: must be either STRONG or WEAK, depending on the\n" - " clusters being sought.\n" + "@param mode: must be either C{\"strong\"} or C{\"weak\"}, depending on\n" + " the clusters being sought. Optional, defaults to C{\"strong\"}.\n" "@param maxcompno: maximum number of components to return.\n" " C{None} means all possible components.\n" "@param minelements: minimum number of vertices in a component.\n" @@ -13061,9 +13053,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " C{first}, C{last}, C{random}. You can also specify different\n" " combination functions for different attributes by passing a dict\n" " here which maps attribute names to functions. See\n" - " L{Graph.simplify()} for more details.\n" + " L{simplify()} for more details.\n" "@return: C{None}.\n" - "@see: L{Graph.simplify()}\n" + "@see: L{simplify()}\n" }, /* interface to igraph_constraint */ {"constraint", (PyCFunction) igraphmodule_Graph_constraint, @@ -13167,16 +13159,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_eccentricity */ {"eccentricity", (PyCFunction) igraphmodule_Graph_eccentricity, METH_VARARGS | METH_KEYWORDS, - "eccentricity(vertices=None, mode=ALL)\n--\n\n" + "eccentricity(vertices=None, mode=\"all\")\n--\n\n" "Calculates the eccentricities of given vertices in a graph.\n\n" "The eccentricity of a vertex is calculated by measuring the\n" "shortest distance from (or to) the vertex, to (or from) all other\n" "vertices in the graph, and taking the maximum.\n\n" "@param vertices: the vertices for which the eccentricity scores must\n" " be returned. If C{None}, uses all of the vertices in the graph.\n" - "@param mode: must be one of L{IN}, L{OUT} and L{ALL}. L{IN} means\n" - " that edge directions are followed; C{OUT} means that edge directions\n" - " are followed the opposite direction; C{ALL} means that directions are\n" + "@param mode: must be one of C{\"in\"}, C{\"out\"} and C{\"all\"}. C{\"in\"} means\n" + " that edge directions are followed; C{\"out\"} means that edge directions\n" + " are followed the opposite direction; C{\"all\"} means that directions are\n" " ignored. The argument has no effect for undirected graphs.\n" "@return: the calculated eccentricities in a list, or a single number if\n" " a single vertex was supplied.\n"}, @@ -13293,7 +13285,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_shortest_paths {"get_shortest_paths", (PyCFunction) igraphmodule_Graph_get_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "get_shortest_paths(v, to=None, weights=None, mode=OUT, output=\"vpath\")\n--\n\n" + "get_shortest_paths(v, to=None, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" "Calculates the shortest paths from/to a given node in a graph.\n\n" "@param v: the source/destination for the calculated paths\n" "@param to: a vertex selector describing the destination/source for\n" @@ -13303,13 +13295,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param weights: edge weights in a list or the name of an edge attribute\n" " holding edge weights. If C{None}, all edges are assumed to have\n" " equal weight.\n" - "@param mode: the directionality of the paths. L{IN} means to\n" - " calculate incoming paths, L{OUT} means to calculate outgoing\n" - " paths, L{ALL} means to calculate both ones.\n" + "@param mode: the directionality of the paths. C{\"in\"} means to\n" + " calculate incoming paths, C{\"out\"} means to calculate outgoing\n" + " paths, C{\"all\"} means to calculate both ones.\n" "@param output: determines what should be returned. If this is\n" " C{\"vpath\"}, a list of vertex IDs will be returned, one path\n" " for each target vertex. For unconnected graphs, some of the list\n" - " elements may be empty. Note that in case of mode=L{IN}, the vertices\n" + " elements may be empty. Note that in case of mode=C{\"in\"}, the vertices\n" " in a path are returned in reversed order. If C{output=\"epath\"},\n" " edge IDs are returned instead of vertex IDs.\n" "@return: see the documentation of the C{output} parameter.\n"}, @@ -13318,7 +13310,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"get_all_shortest_paths", (PyCFunction) igraphmodule_Graph_get_all_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "get_all_shortest_paths(v, to=None, weights=None, mode=OUT)\n--\n\n" + "get_all_shortest_paths(v, to=None, weights=None, mode=\"out\")\n--\n\n" "Calculates all of the shortest paths from/to a given node in a graph.\n\n" "@param v: the source for the calculated paths\n" "@param to: a vertex selector describing the destination for\n" @@ -13328,18 +13320,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param weights: edge weights in a list or the name of an edge attribute\n" " holding edge weights. If C{None}, all edges are assumed to have\n" " equal weight.\n" - "@param mode: the directionality of the paths. L{IN} means to\n" - " calculate incoming paths, L{OUT} means to calculate outgoing\n" - " paths, L{ALL} means to calculate both ones.\n" + "@param mode: the directionality of the paths. C{\"in\"} means to\n" + " calculate incoming paths, C{\"out\"} means to calculate outgoing\n" + " paths, C{\"all\"} means to calculate both ones.\n" "@return: all of the shortest path from the given node to every other\n" - " reachable node in the graph in a list. Note that in case of mode=L{IN},\n" + " reachable node in the graph in a list. Note that in case of mode=C{\"in\"},\n" " the vertices in a path are returned in reversed order!"}, /* interface to igraph_get_all_simple_paths */ {"_get_all_simple_paths", (PyCFunction) igraphmodule_Graph_get_all_simple_paths, METH_VARARGS | METH_KEYWORDS, - "_get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT)\n--\n\n" + "_get_all_simple_paths(v, to=None, cutoff=-1, mode=\"out\")\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.get_all_simple_paths()\n\n" }, @@ -13450,7 +13442,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_connected */ {"is_connected", (PyCFunction) igraphmodule_Graph_is_connected, METH_VARARGS | METH_KEYWORDS, - "is_connected(mode=STRONG)\n--\n\n" + "is_connected(mode=\"strong\")\n--\n\n" "Decides whether the graph is connected.\n\n" "@param mode: whether we should calculate strong or weak connectivity.\n" "@return: C{True} if the graph is connected, C{False} otherwise.\n"}, @@ -13473,7 +13465,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_maxdegree */ {"maxdegree", (PyCFunction) igraphmodule_Graph_maxdegree, METH_VARARGS | METH_KEYWORDS, - "maxdegree(vertices=None, mode=ALL, loops=False)\n--\n\n" + "maxdegree(vertices=None, mode=\"all\", loops=False)\n--\n\n" "Returns the maximum degree of a vertex set in the graph.\n\n" "This method accepts a single vertex ID or a list of vertex IDs as a\n" "parameter, and returns the degree of the given vertices (in the\n" @@ -13482,15 +13474,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "\n" "@param vertices: a single vertex ID or a list of vertex IDs, or\n" " C{None} meaning all the vertices in the graph.\n" - "@param mode: the type of degree to be returned (L{OUT} for\n" - " out-degrees, L{IN} IN for in-degrees or L{ALL} for the sum of\n" + "@param mode: the type of degree to be returned (C{\"out\"} for\n" + " out-degrees, C{\"in\"} IN for in-degrees or C{\"all\"} for the sum of\n" " them).\n" "@param loops: whether self-loops should be counted.\n"}, /* interface to igraph_neighborhood */ {"neighborhood", (PyCFunction) igraphmodule_Graph_neighborhood, METH_VARARGS | METH_KEYWORDS, - "neighborhood(vertices=None, order=1, mode=ALL, mindist=0)\n--\n\n" + "neighborhood(vertices=None, order=1, mode=\"all\", mindist=0)\n--\n\n" "For each vertex specified by I{vertices}, returns the\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" @@ -13518,7 +13510,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_neighborhood_size */ {"neighborhood_size", (PyCFunction) igraphmodule_Graph_neighborhood_size, METH_VARARGS | METH_KEYWORDS, - "neighborhood_size(vertices=None, order=1, mode=ALL, mindist=0)\n--\n\n" + "neighborhood_size(vertices=None, order=1, mode=\"all\", mindist=0)\n--\n\n" "For each vertex specified by I{vertices}, returns the number of\n" "vertices reachable from that vertex in at most I{order} steps. If\n" "I{mindist} is larger than zero, vertices that are reachable in less\n" @@ -13624,7 +13616,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interfaces to igraph_radius */ {"radius", (PyCFunction) igraphmodule_Graph_radius, METH_VARARGS | METH_KEYWORDS, - "radius(mode=OUT)\n--\n\n" + "radius(mode=\"out\")\n--\n\n" "Calculates the radius of the graph.\n\n" "The radius of a graph is defined as the minimum eccentricity of\n" "its vertices (see L{eccentricity()}).\n" @@ -13634,7 +13626,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " edge directions, C{ALL} ignores edge directions. The argument is\n" " ignored for undirected graphs.\n" "@return: the radius\n" - "@see: L{Graph.eccentricity()}" + "@see: L{eccentricity()}" }, /* interface to igraph_reciprocity */ @@ -13692,7 +13684,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_shortest_paths */ {"shortest_paths", (PyCFunction) igraphmodule_Graph_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "shortest_paths(source=None, target=None, weights=None, mode=OUT)\n--\n\n" + "shortest_paths(source=None, target=None, weights=None, mode=\"out\")\n--\n\n" "Calculates shortest path lengths for given vertices in a graph.\n\n" "The algorithm used for the calculations is selected automatically:\n" "a simple BFS is used for unweighted graphs, Dijkstra's algorithm is\n" @@ -13707,8 +13699,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " an attribute name (edge weights are retrieved from the given\n" " attribute) or C{None} (all edges have equal weight).\n" "@param mode: the type of shortest paths to be used for the\n" - " calculation in directed graphs. L{OUT} means only outgoing,\n" - " L{IN} means only incoming paths. L{ALL} means to consider\n" + " calculation in directed graphs. C{\"out\"} means only outgoing,\n" + " C{\"in\"} means only incoming paths. C{\"all\"} means to consider\n" " the directed graph as an undirected one.\n" "@return: the shortest path lengths for given vertices in a matrix\n"}, @@ -13774,16 +13766,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_subcomponent {"subcomponent", (PyCFunction) igraphmodule_Graph_subcomponent, METH_VARARGS | METH_KEYWORDS, - "subcomponent(v, mode=ALL)\n--\n\n" + "subcomponent(v, mode=\"all\")\n--\n\n" "Determines the indices of vertices which are in the same component as a given vertex.\n\n" "@param v: the index of the vertex used as the source/destination\n" - "@param mode: if equals to L{IN}, returns the vertex IDs from\n" - " where the given vertex can be reached. If equals to L{OUT},\n" + "@param mode: if equals to C{\"in\"}, returns the vertex IDs from\n" + " where the given vertex can be reached. If equals to C{\"out\"},\n" " returns the vertex IDs which are reachable from the given\n" - " vertex. If equals to L{ALL}, returns all vertices within the\n" + " vertex. If equals to C{\"all\"}, returns all vertices within the\n" " same component as the given vertex, ignoring edge directions.\n" " Note that this is not equal to calculating the union of the \n" - " results of L{IN} and L{OUT}.\n" + " results of C{\"in\"} and C{\"out\"}.\n" "@return: the indices of vertices which are in the same component as a given vertex.\n"}, /* interface to igraph_subgraph_edges */ @@ -13802,13 +13794,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"topological_sorting", (PyCFunction) igraphmodule_Graph_topological_sorting, METH_VARARGS | METH_KEYWORDS, - "topological_sorting(mode=OUT)\n--\n\n" + "topological_sorting(mode=\"out\")\n--\n\n" "Calculates a possible topological sorting of the graph.\n\n" "Returns a partial sorting and issues a warning if the graph is not\n" "a directed acyclic graph.\n\n" - "@param mode: if L{OUT}, vertices are returned according to the\n" + "@param mode: if C{\"out\"}, vertices are returned according to the\n" " forward topological order -- all vertices come before their\n" - " successors. If L{IN}, all vertices come before their ancestors.\n" + " successors. If C{\"in\"}, all vertices come before their ancestors.\n" "@return: a possible topological ordering as a list"}, /* interface to to_prufer */ @@ -13909,11 +13901,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_unfold_tree */ {"unfold_tree", (PyCFunction) igraphmodule_Graph_unfold_tree, METH_VARARGS | METH_KEYWORDS, - "unfold_tree(sources=None, mode=OUT)\n--\n\n" + "unfold_tree(sources=None, mode=\"out\")\n--\n\n" "Unfolds the graph using a BFS to a tree by duplicating vertices as necessary.\n\n" "@param sources: the source vertices to start the unfolding from. It should be a\n" " list of vertex indices, preferably one vertex from each connected component.\n" - " You can use L{Graph.topological_sorting()} to determine a suitable set. A single\n" + " You can use L{topological_sorting()} to determine a suitable set. A single\n" " vertex index is also accepted.\n" "@param mode: which edges to follow during the BFS. C{OUT} follows outgoing edges,\n" " C{IN} follows incoming edges, C{ALL} follows both. Ignored for undirected\n" @@ -13974,7 +13966,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_similarity_dice */ {"similarity_dice", (PyCFunction) igraphmodule_Graph_similarity_dice, METH_VARARGS | METH_KEYWORDS, - "similarity_dice(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n--\n\n" + "similarity_dice(vertices=None, pairs=None, mode=\"all\", loops=True)\n--\n\n" "Dice similarity coefficient of vertices.\n\n" "The Dice similarity coefficient of two vertices is twice the number of\n" "their common neighbors divided by the sum of their degrees. This\n" @@ -13986,7 +13978,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " must be C{None}, and the similarity values will be calculated only for the\n" " given pairs. Vertex pairs must be specified as tuples of vertex IDs.\n" "@param mode: which neighbors should be considered for directed graphs.\n" - " Can be L{ALL}, L{IN} or L{OUT}, ignored for undirected graphs.\n" + " Can be C{\"all\"}, C{\"in\"} or C{\"out\"}, ignored for undirected graphs.\n" "@param loops: whether vertices should be considered adjacent to\n" " themselves. Setting this to C{True} assumes a loop edge for all vertices\n" " even if none is present in the graph. Setting this to C{False} may\n" @@ -14001,7 +13993,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"similarity_inverse_log_weighted", (PyCFunction) igraphmodule_Graph_similarity_inverse_log_weighted, METH_VARARGS | METH_KEYWORDS, - "similarity_inverse_log_weighted(vertices=None, mode=IGRAPH_ALL)\n--\n\n" + "similarity_inverse_log_weighted(vertices=None, mode=\"all\")\n--\n\n" "Inverse log-weighted similarity coefficient of vertices.\n\n" "Each vertex is assigned a weight which is 1 / log(degree). The\n" "log-weighted similarity of two vertices is the sum of the weights\n" @@ -14009,8 +14001,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param vertices: the vertices to be analysed. If C{None}, all vertices\n" " will be considered.\n" "@param mode: which neighbors should be considered for directed graphs.\n" - " Can be L{ALL}, L{IN} or L{OUT}, ignored for undirected graphs.\n" - " L{IN} means that the weights are determined by the out-degrees, L{OUT}\n" + " Can be C{\"all\"}, C{\"in\"} or C{\"out\"}, ignored for undirected graphs.\n" + " C{\"in\"} means that the weights are determined by the out-degrees, C{\"out\"}\n" " means that the weights are determined by the in-degrees.\n" "@return: the pairwise similarity coefficients for the vertices specified,\n" " in the form of a matrix (list of lists).\n" @@ -14018,7 +14010,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_similarity_jaccard */ {"similarity_jaccard", (PyCFunction) igraphmodule_Graph_similarity_jaccard, METH_VARARGS | METH_KEYWORDS, - "similarity_jaccard(vertices=None, pairs=None, mode=IGRAPH_ALL, loops=True)\n--\n\n" + "similarity_jaccard(vertices=None, pairs=None, mode=\"all\", loops=True)\n--\n\n" "Jaccard similarity coefficient of vertices.\n\n" "The Jaccard similarity coefficient of two vertices is the number of their\n" "common neighbors divided by the number of vertices that are adjacent to\n" @@ -14029,7 +14021,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " must be C{None}, and the similarity values will be calculated only for the\n" " given pairs. Vertex pairs must be specified as tuples of vertex IDs.\n" "@param mode: which neighbors should be considered for directed graphs.\n" - " Can be L{ALL}, L{IN} or L{OUT}, ignored for undirected graphs.\n" + " Can be C{\"all\"}, C{\"in\"} or C{\"out\"}, ignored for undirected graphs.\n" "@param loops: whether vertices should be considered adjacent to\n" " themselves. Setting this to C{True} assumes a loop edge for all vertices\n" " even if none is present in the graph. Setting this to C{False} may\n" @@ -14070,7 +14062,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param callback: C{None} or a callable that will be called for every motif\n" " found in the graph. The callable must accept three parameters: the graph\n" " itself, the list of vertices in the motif and the isomorphism class of the\n" - " motif (see L{Graph.isoclass()}). The search will stop when the callback\n" + " motif (see L{isoclass()}). The search will stop when the callback\n" " returns an object with a non-zero truth value or raises an exception.\n" "@return: the list of motifs if I{callback} is C{None}, or C{None} otherwise\n" "@see: Graph.motifs_randesu_no()\n" @@ -14094,7 +14086,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"motifs_randesu_estimate", (PyCFunction) igraphmodule_Graph_motifs_randesu_estimate, METH_VARARGS | METH_KEYWORDS, - "motifs_randesu_estimate(size=3, cut_prob=None, sample)\n--\n\n" + "motifs_randesu_estimate(size=3, cut_prob=None, sample=None)\n--\n\n" "Counts the total number of motifs in the graph\n\n" "Motifs are small subgraphs of a given structure in a graph.\n" "This function estimates the total number of motifs in a graph without\n" @@ -14206,9 +14198,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_kamada_kawai", (PyCFunction) igraphmodule_Graph_layout_kamada_kawai, METH_VARARGS | METH_KEYWORDS, - "layout_kamada_kawai(maxiter=1000, seed=None, maxiter=1000, epsilon=0, " - "kkconst=None, minx=None, maxx=None, miny=None, maxy=None, " - "minz=None, maxz=None, dim=2)\n--\n\n" + "layout_kamada_kawai(maxiter=1000, epsilon=0, kkconst=None, seed=None, " + "minx=None, maxx=None, miny=None, maxy=None, minz=None, maxz=None, dim=2)\n--\n\n" "Places the vertices on a plane according to the Kamada-Kawai algorithm.\n\n" "This is a force directed layout, see Kamada, T. and Kawai, S.:\n" "An Algorithm for Drawing General Undirected Graphs.\n" @@ -14530,10 +14521,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { //////////////////////////// {"bfs", (PyCFunction) igraphmodule_Graph_bfs, METH_VARARGS | METH_KEYWORDS, - "bfs(vid, mode=OUT)\n--\n\n" + "bfs(vid, mode=\"out\")\n--\n\n" "Conducts a breadth first search (BFS) on the graph.\n\n" "@param vid: the root vertex ID\n" - "@param mode: either L{IN} or L{OUT} or L{ALL}, ignored\n" + "@param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}, ignored\n" " for undirected graphs.\n" "@return: a tuple with the following items:\n" " - The vertex IDs visited (in order)\n" @@ -14541,10 +14532,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - The parent of every vertex in the BFS\n"}, {"bfsiter", (PyCFunction) igraphmodule_Graph_bfsiter, METH_VARARGS | METH_KEYWORDS, - "bfsiter(vid, mode=OUT, advanced=False)\n--\n\n" + "bfsiter(vid, mode=\"out\", advanced=False)\n--\n\n" "Constructs a breadth first search (BFS) iterator of the graph.\n\n" "@param vid: the root vertex ID\n" - "@param mode: either L{IN} or L{OUT} or L{ALL}.\n" + "@param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}.\n" "@param advanced: if C{False}, the iterator returns the next\n" " vertex in BFS order in every step. If C{True}, the iterator\n" " returns the distance of the vertex from the root and the\n" @@ -14552,10 +14543,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the BFS iterator as an L{igraph.BFSIter} object.\n"}, {"dfsiter", (PyCFunction) igraphmodule_Graph_dfsiter, METH_VARARGS | METH_KEYWORDS, - "dfsiter(vid, mode=OUT, advanced=False)\n--\n\n" + "dfsiter(vid, mode=\"out\", advanced=False)\n--\n\n" "Constructs a depth first search (DFS) iterator of the graph.\n\n" "@param vid: the root vertex ID\n" - "@param mode: either L{IN} or L{OUT} or L{ALL}.\n" + "@param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}.\n" "@param advanced: if C{False}, the iterator returns the next\n" " vertex in DFS order in every step. If C{True}, the iterator\n" " returns the distance of the vertex from the root and the\n" @@ -14569,12 +14560,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_adjacency {"get_adjacency", (PyCFunction) igraphmodule_Graph_get_adjacency, METH_VARARGS | METH_KEYWORDS, - "get_adjacency(type=GET_ADJACENCY_BOTH, eids=False)\n--\n\n" + "get_adjacency(type=\"both\", eids=False)\n--\n\n" "Returns the adjacency matrix of a graph.\n\n" - "@param type: either C{GET_ADJACENCY_LOWER} (uses the\n" - " lower triangle of the matrix) or C{GET_ADJACENCY_UPPER}\n" - " (uses the upper triangle) or C{GET_ADJACENCY_BOTH}\n" - " (uses both parts). Ignored for directed graphs.\n" + "@param type: one of C{\"lower\"} (uses the lower triangle of the matrix),\n" + " C{\"upper\"} (uses the upper triangle) or C{\"both\"} (uses both parts).\n" + " Ignored for directed graphs.\n" "@param eids: if C{True}, the result matrix will contain\n" " zeros for non-edges and the ID of the edge plus one\n" " for edges in the appropriate cell. If C{False}, the\n" @@ -14616,7 +14606,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " creates one undirected edge for each mutual directed edge pair.\n" "@param combine_edges: specifies how to combine the attributes of\n" " multiple edges between the same pair of vertices into a single\n" - " attribute. See L{Graph.simplify()} for more details.\n" + " attribute. See L{simplify()} for more details.\n" }, /* interface to igraph_laplacian */ @@ -14874,7 +14864,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "canonical_permutation(sh=\"fl\", color=None)\n--\n\n" "Calculates the canonical permutation of a graph using the BLISS isomorphism\n" "algorithm.\n\n" - "Passing the permutation returned here to L{Graph.permute_vertices()} will\n" + "Passing the permutation returned here to L{permute_vertices()} will\n" "transform the graph into its canonical form.\n\n" "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" "about the BLISS algorithm and canonical permutations.\n\n" @@ -14918,9 +14908,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - If the graphs have three or four vertices, then an O(1) algorithm\n" " is used with precomputed data.\n\n" " - Otherwise if the graphs are directed, then the VF2 isomorphism\n" - " algorithm is used (see L{Graph.isomorphic_vf2}).\n\n" + " algorithm is used (see L{isomorphic_vf2}).\n\n" " - Otherwise the BLISS isomorphism algorithm is used, see\n" - " L{Graph.isomorphic_bliss}.\n\n" + " L{isomorphic_bliss}.\n\n" "@return: C{True} if the graphs are isomorphic, C{False} otherwise.\n" }, {"isomorphic_bliss", (PyCFunction) igraphmodule_Graph_isomorphic_bliss, @@ -15296,10 +15286,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /**********************/ {"dominator", (PyCFunction) igraphmodule_Graph_dominator, METH_VARARGS | METH_KEYWORDS, - "dominator(vid, mode=)\n--\n\n" + "dominator(vid, mode=\"out\")\n--\n\n" "Returns the dominator tree from the given root node" "@param vid: the root vertex ID\n" - "@param mode: either L{IN} or L{OUT}\n" + "@param mode: either C{\"in\"} or C{\"out\"}\n" "@return: a list containing the dominator tree for the current graph." }, @@ -15639,15 +15629,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { }, {"coreness", (PyCFunction) igraphmodule_Graph_coreness, METH_VARARGS | METH_KEYWORDS, - "coreness(mode=ALL)\n--\n\n" + "coreness(mode=\"all\")\n--\n\n" "Finds the coreness (shell index) of the vertices of the network.\n\n" "The M{k}-core of a graph is a maximal subgraph in which each vertex\n" "has at least degree k. (Degree here means the degree in the\n" "subgraph of course). The coreness of a vertex is M{k} if it\n" "is a member of the M{k}-core but not a member of the M{k+1}-core.\n\n" - "@param mode: whether to compute the in-corenesses (L{IN}), the\n" - " out-corenesses (L{OUT}) or the undirected corenesses (L{ALL}).\n" - " Ignored and assumed to be L{ALL} for undirected graphs.\n" + "@param mode: whether to compute the in-corenesses (C{\"in\"}), the\n" + " out-corenesses (C{\"out\"}) or the undirected corenesses (C{\"all\"}).\n" + " Ignored and assumed to be C{\"all\"} for undirected graphs.\n" "@return: the corenesses for each vertex.\n\n" "@newfield ref: Reference\n" "@ref: Vladimir Batagelj, Matjaz Zaversnik: I{An M{O(m)} Algorithm\n" @@ -15835,7 +15825,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "community_spinglass(weights=None, spins=25, parupdate=False, " "start_temp=1, stop_temp=0.01, cool_fact=0.99, update_rule=\"config\", " - "gamma=1, implementation=\"orig\", lambda=1)\n--\n\n" + "gamma=1, implementation=\"orig\", lambda_=1)\n--\n\n" "Finds the community structure of the graph according to the spinglass\n" "community detection method of Reichardt & Bornholdt.\n\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" @@ -15861,7 +15851,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " implementation is the default. The other implementation is able to take\n" " into account negative weights, this can be chosen by setting\n" " C{implementation} to C{\"neg\"}.\n" - "@param lambda: the lambda argument of the algorithm, which specifies the\n" + "@param lambda_: the lambda argument of the algorithm, which specifies the\n" " balance between the importance of present and missing negatively\n" " weighted edges within a community. Smaller values of lambda lead\n" " to communities with less negative intra-connectivity. If the argument\n" @@ -15888,7 +15878,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " will be divided by the sum of the node weights. If this is not\n" " supplied, it will default to the node degree, or weighted degree\n" " in case edge_weights are supplied.\n" - "@param node_weights: the node weights used in the Leiden algorithm.\n" "@param beta: parameter affecting the randomness in the Leiden \n" " algorithm. This affects only the refinement step of the algorithm.\n" "@param initial_membership: if provided, the Leiden algorithm\n" @@ -15931,13 +15920,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "_is_maximal_matching(matching, types=None)\n--\n\n" "Internal function, undocumented.\n\n" - "Use L{Matching.is_maximal} instead.\n" + "Use L{igraph.Matching.is_maximal} instead.\n" }, {"_maximum_bipartite_matching", (PyCFunction)igraphmodule_Graph_maximum_bipartite_matching, METH_VARARGS | METH_KEYWORDS, "_maximum_bipartite_matching(types, weights=None)\n--\n\n" "Internal function, undocumented.\n\n" - "@see: L{Graph.maximum_bipartite_matching}\n" + "@see: L{igraph.Graph.maximum_bipartite_matching}\n" }, /****************/ @@ -15949,8 +15938,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Performs a random walk of a given length from a given node.\n\n" "@param start: the starting vertex of the walk\n" "@param steps: the number of steps that the random walk should take\n" - "@param mode: whether to follow outbound edges only (L{OUT}),\n" - " inbound edges only (L{IN}) or both (L{ALL}). Ignored for undirected\n" + "@param mode: whether to follow outbound edges only (C{\"out\"}),\n" + " inbound edges only (C{\"in\"}) or both (C{\"all\"}). Ignored for undirected\n" " graphs." "@param stuck: what to do when the random walk gets stuck. C{\"return\"}\n" " returns a partial random walk; C{\"error\"} throws an exception.\n" diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 0e5f28b77..9d8f485e4 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -715,16 +715,16 @@ GRAPH_PROXY_METHOD_PP(successors, "successors", _convert_to_vertex_list); #define GRAPH_PROXY_METHOD_SPEC(FUNC, METHODNAME) \ {METHODNAME, (PyCFunction)igraphmodule_Vertex_##FUNC, METH_VARARGS | METH_KEYWORDS, \ - "Proxy method to L{Graph." METHODNAME "()}\n\n" \ - "This method calls the " METHODNAME " method of the L{Graph} class " \ + "Proxy method to L{Graph." METHODNAME "()}\n\n" \ + "This method calls the C{" METHODNAME "()} method of the L{Graph} class " \ "with this vertex as the first argument, and returns the result.\n\n"\ - "@see: Graph." METHODNAME "() for details."} + "@see: L{Graph." METHODNAME "()} for details."} #define GRAPH_PROXY_METHOD_SPEC_2(FUNC, METHODNAME, METHODNAME_IN_GRAPH) \ {METHODNAME, (PyCFunction)igraphmodule_Vertex_##FUNC, METH_VARARGS | METH_KEYWORDS, \ - "Proxy method to L{Graph." METHODNAME_IN_GRAPH "()}\n\n" \ - "This method calls the " METHODNAME_IN_GRAPH " method of the L{Graph} class " \ + "Proxy method to L{Graph." METHODNAME_IN_GRAPH "()}\n\n" \ + "This method calls the C{" METHODNAME_IN_GRAPH "} method of the L{Graph} class " \ "with this vertex as the first argument, and returns the result.\n\n"\ - "@see: Graph." METHODNAME_IN_GRAPH "() for details."} + "@see: L{Graph." METHODNAME_IN_GRAPH "()} for details."} /** * \ingroup python_interface_vertex @@ -752,23 +752,23 @@ PyMethodDef igraphmodule_Vertex_methods[] = { "dictionaries." }, {"all_edges", (PyCFunction)igraphmodule_Vertex_all_edges, METH_NOARGS, - "Proxy method to L{Graph.incident(..., mode=\"all\")}\n\n" \ + "Proxy method to L{Graph.incident(..., mode=\"all\")}\n\n" \ "This method calls the incident() method of the L{Graph} class " \ "with this vertex as the first argument and \"all\" as the mode " \ "argument, and returns the result.\n\n"\ - "@see: Graph.incident() for details."}, + "@see: L{Graph.incident()} for details."}, {"in_edges", (PyCFunction)igraphmodule_Vertex_in_edges, METH_NOARGS, - "Proxy method to L{Graph.incident(..., mode=\"in\")}\n\n" \ + "Proxy method to L{Graph.incident(..., mode=\"in\")}\n\n" \ "This method calls the incident() method of the L{Graph} class " \ "with this vertex as the first argument and \"in\" as the mode " \ "argument, and returns the result.\n\n"\ - "@see: Graph.incident() for details."}, + "@see: L{Graph.incident()} for details."}, {"out_edges", (PyCFunction)igraphmodule_Vertex_out_edges, METH_NOARGS, - "Proxy method to L{Graph.incident(..., mode=\"out\")}\n\n" \ + "Proxy method to L{Graph.incident(..., mode=\"out\")}\n\n" \ "This method calls the incident() method of the L{Graph} class " \ "with this vertex as the first argument and \"out\" as the mode " \ "argument, and returns the result.\n\n"\ - "@see: Graph.incident() for details."}, + "@see: L{Graph.incident()} for details."}, GRAPH_PROXY_METHOD_SPEC(betweenness, "betweenness"), GRAPH_PROXY_METHOD_SPEC(closeness, "closeness"), GRAPH_PROXY_METHOD_SPEC(constraint, "constraint"), diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 2101b22d3..77be5ce69 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -994,7 +994,7 @@ PyGetSetDef igraphmodule_VertexSeq_getseters[] = { PyTypeObject igraphmodule_VertexSeqType = { PyVarObject_HEAD_INIT(0, 0) - "igraph.core.VertexSeq", /* tp_name */ + "igraph._igraph.VertexSeq", /* tp_name */ sizeof(igraphmodule_VertexSeqObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)igraphmodule_VertexSeq_dealloc, /* tp_dealloc */ diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 37a45534c..946dd781d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -44,7 +44,7 @@ BLISS_FSM, DFSIter, Edge, - EdgeSeq, + EdgeSeq as _EdgeSeq, GET_ADJACENCY_BOTH, GET_ADJACENCY_LOWER, GET_ADJACENCY_UPPER, @@ -65,7 +65,7 @@ TREE_OUT, TREE_UNDIRECTED, Vertex, - VertexSeq, + VertexSeq as _VertexSeq, WEAK, arpack_options, community_to_membership, @@ -452,7 +452,7 @@ def adjacent(self, *args, **kwds): Returns the edges a given vertex is incident on. - @deprecated: replaced by L{Graph.incident()} since igraph 0.6 + @deprecated: replaced by L{incident()} since igraph 0.6 """ deprecated( "Graph.adjacent() is deprecated since igraph 0.6, please use " @@ -464,7 +464,7 @@ def as_directed(self, *args, **kwds): """as_directed(*args, **kwds) Returns a directed copy of this graph. Arguments are passed on - to L{Graph.to_directed()} that is invoked on the copy. + to L{to_directed()} that is invoked on the copy. """ copy = self.copy() copy.to_directed(*args, **kwds) @@ -474,7 +474,7 @@ def as_undirected(self, *args, **kwds): """as_undirected(*args, **kwds) Returns an undirected copy of this graph. Arguments are passed on - to L{Graph.to_undirected()} that is invoked on the copy. + to L{to_undirected()} that is invoked on the copy. """ copy = self.copy() copy.to_undirected(*args, **kwds) @@ -498,8 +498,8 @@ def delete_edges(self, *args, **kwds): source-target vertex pairs. When multiple edges are present between a given source-target vertex pair, only one is removed. - @deprecated: L{Graph.delete_edges(None)} has been replaced by - L{Graph.delete_edges()} - with no arguments - since igraph 0.8.3. + @deprecated: C{delete_edges(None)} has been replaced by + C{delete_edges()} - with no arguments - since igraph 0.8.3. """ if len(args) == 0 and len(kwds) == 0: return GraphBase.delete_edges(self) @@ -607,7 +607,7 @@ def clear(self): Clears the graph, deleting all vertices, edges, and attributes. - @see: L{Graph.delete_vertices} and L{Graph.delete_edges}. + @see: L{delete_vertices} and L{delete_edges}. """ self.delete_vertices() for attr in self.attributes(): @@ -782,28 +782,24 @@ def get_adjacency_sparse(self, attribute=None): mtx = mtx + sparse.triu(mtx, 1).T + sparse.tril(mtx, -1).T return mtx - def get_adjlist(self, mode=OUT): - """get_adjlist(mode=OUT) - - Returns the adjacency list representation of the graph. + def get_adjlist(self, mode="out"): + """Returns the adjacency list representation of the graph. The adjacency list representation is a list of lists. Each item of the outer list belongs to a single vertex of the graph. The inner list contains the neighbors of the given vertex. - @param mode: if L{OUT}, returns the successors of the vertex. If - L{IN}, returns the predecessors of the vertex. If L{ALL}, both + @param mode: if C{\"out\"}, returns the successors of the vertex. If + C{\"in\"}, returns the predecessors of the vertex. If C{\"all"\"}, both the predecessors and the successors will be returned. Ignored for undirected graphs. """ return [self.neighbors(idx, mode) for idx in range(self.vcount())] def get_adjedgelist(self, *args, **kwds): - """get_adjedgelist(mode=OUT) - - Returns the incidence list representation of the graph. + """Returns the incidence list representation of the graph. - @deprecated: replaced by L{Graph.get_inclist()} since igraph 0.6 + @deprecated: replaced by L{get_inclist()} since igraph 0.6 @see: Graph.get_inclist() """ deprecated( @@ -832,11 +828,11 @@ def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): means all the vertices. @param cutoff: maximum length of path that is considered. If negative, paths of all lengths are considered. - @param mode: the directionality of the paths. L{IN} means to calculate - incoming paths, L{OUT} means to calculate outgoing paths, L{ALL} means + @param mode: the directionality of the paths. C{\"in\"} means to calculate + incoming paths, C{\"out\"} means to calculate outgoing paths, C{\"all\"} means to calculate both ones. @return: all of the simple paths from the given node to every other - reachable node in the graph in a list. Note that in case of mode=L{IN}, + reachable node in the graph in a list. Note that in case of mode=C{\"in\"}, the vertices in a path are returned in reversed order! """ paths = self._get_all_simple_paths(v, to, cutoff, mode) @@ -858,8 +854,8 @@ def get_inclist(self, mode=OUT): The inner list contains the IDs of the incident edges of the given vertex. - @param mode: if L{OUT}, returns the successors of the vertex. If - L{IN}, returns the predecessors of the vertex. If L{ALL}, both + @param mode: if C{\"out\"}, returns the successors of the vertex. If + C{\"in\"}, returns the predecessors of the vertex. If C{\"all\"}, both the predecessors and the successors will be returned. Ignored for undirected graphs. """ @@ -1318,10 +1314,7 @@ def community_leading_eigenvector_naive(self, clusters=None, return_merges=False def community_leading_eigenvector( self, clusters=None, weights=None, arpack_options=None ): - """community_leading_eigenvector(clusters=None, weights=None, - arpack_options=None) - - Newman's leading eigenvector method for detecting community structure. + """Newman's leading eigenvector method for detecting community structure. This is the proper implementation of the recursive, divisive algorithm: each split is done by maximizing the modularity regarding the original network. @@ -1630,31 +1623,27 @@ def community_leiden( n_iterations=2, node_weights=None, ): - """community_leiden(objective_function=CPM, weights=None, - resolution_parameter=1.0, beta=0.01, initial_membership=None, - n_iterations=2, node_weights=None) - - Finds the community structure of the graph using the - Leiden algorithm of Traag, van Eck & Waltman. + """Finds the community structure of the graph using the Leiden + algorithm of Traag, van Eck & Waltman. - @keyword objective_function: whether to use the Constant Potts + @param objective_function: whether to use the Constant Potts Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. - @keyword weights: edge weights to be used. Can be a sequence or + @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. - @keyword resolution_parameter: the resolution parameter to use. + @param resolution_parameter: the resolution parameter to use. Higher resolutions lead to more smaller communities, while lower resolutions lead to fewer larger communities. - @keyword beta: parameter affecting the randomness in the Leiden + @param beta: parameter affecting the randomness in the Leiden algorithm. This affects only the refinement step of the algorithm. - @keyword initial_membership: if provided, the Leiden algorithm + @param initial_membership: if provided, the Leiden algorithm will try to improve this provided membership. If no argument is provided, the aglorithm simply starts from the singleton partition. - @keyword n_iterations: the number of iterations to iterate the Leiden + @param n_iterations: the number of iterations to iterate the Leiden algorithm. Each iteration may improve the partition further. Using a negative number of iterations will run until a stable iteration is encountered (i.e. the quality was not increased during that iteration). - @keyword node_weights: the node weights used in the Leiden algorithm. + @param node_weights: the node weights used in the Leiden algorithm. If this is not provided, it will be automatically determined on the basis of whether you want to use CPM or modularity. If you do provide this, please make sure that you understand what you are doing. @@ -1695,61 +1684,61 @@ def layout(self, layout=None, *args, **kwds): Registered layout names understood by this method are: - C{auto}, C{automatic}: automatic layout - (see L{Graph.layout_auto}) + (see L{layout_auto}) - - C{bipartite}: bipartite layout (see L{Graph.layout_bipartite}) + - C{bipartite}: bipartite layout (see L{layout_bipartite}) - C{circle}, C{circular}: circular layout - (see L{Graph.layout_circle}) + (see L{layout_circle}) - C{dh}, C{davidson_harel}: Davidson-Harel layout (see - L{Graph.layout_davidson_harel}) + L{layout_davidson_harel}) - - C{drl}: DrL layout for large graphs (see L{Graph.layout_drl}) + - C{drl}: DrL layout for large graphs (see L{layout_drl}) - C{drl_3d}: 3D DrL layout for large graphs - (see L{Graph.layout_drl}) + (see L{layout_drl}) - C{fr}, C{fruchterman_reingold}: Fruchterman-Reingold layout - (see L{Graph.layout_fruchterman_reingold}). + (see L{layout_fruchterman_reingold}). - C{fr_3d}, C{fr3d}, C{fruchterman_reingold_3d}: 3D Fruchterman- - Reingold layout (see L{Graph.layout_fruchterman_reingold}). + Reingold layout (see L{layout_fruchterman_reingold}). - - C{grid}: regular grid layout in 2D (see L{Graph.layout_grid}) + - C{grid}: regular grid layout in 2D (see L{layout_grid}) - - C{grid_3d}: regular grid layout in 3D (see L{Graph.layout_grid_3d}) + - C{grid_3d}: regular grid layout in 3D (see L{layout_grid_3d}) - - C{graphopt}: the graphopt algorithm (see L{Graph.layout_graphopt}) + - C{graphopt}: the graphopt algorithm (see L{layout_graphopt}) - C{kk}, C{kamada_kawai}: Kamada-Kawai layout - (see L{Graph.layout_kamada_kawai}) + (see L{layout_kamada_kawai}) - C{kk_3d}, C{kk3d}, C{kamada_kawai_3d}: 3D Kamada-Kawai layout - (see L{Graph.layout_kamada_kawai}) + (see L{layout_kamada_kawai}) - C{lgl}, C{large}, C{large_graph}: Large Graph Layout - (see L{Graph.layout_lgl}) + (see L{layout_lgl}) - - C{mds}: multidimensional scaling layout (see L{Graph.layout_mds}) + - C{mds}: multidimensional scaling layout (see L{layout_mds}) - - C{random}: random layout (see L{Graph.layout_random}) + - C{random}: random layout (see L{layout_random}) - - C{random_3d}: random 3D layout (see L{Graph.layout_random}) + - C{random_3d}: random 3D layout (see L{layout_random}) - C{rt}, C{tree}, C{reingold_tilford}: Reingold-Tilford tree - layout (see L{Graph.layout_reingold_tilford}) + layout (see L{layout_reingold_tilford}) - C{rt_circular}, C{reingold_tilford_circular}: circular Reingold-Tilford tree layout - (see L{Graph.layout_reingold_tilford_circular}) + (see L{layout_reingold_tilford_circular}) - C{sphere}, C{spherical}, C{circle_3d}, C{circular_3d}: spherical - layout (see L{Graph.layout_circle}) + layout (see L{layout_circle}) - - C{star}: star layout (see L{Graph.layout_star}) + - C{star}: star layout (see L{layout_star}) - - C{sugiyama}: Sugiyama layout (see L{Graph.layout_sugiyama}) + - C{sugiyama}: Sugiyama layout (see L{layout_sugiyama}) @param layout: the layout to use. This can be one of the registered layout names or a callable which returns either a L{Layout} object or @@ -1797,14 +1786,14 @@ def layout_auto(self, *args, **kwds): 3. Otherwise, if the graph is connected and has at most 100 vertices, the Kamada-Kawai layout will be used (see - L{Graph.layout_kamada_kawai()}). + L{layout_kamada_kawai()}). 4. Otherwise, if the graph has at most 1000 vertices, the Fruchterman-Reingold layout will be used (see - L{Graph.layout_fruchterman_reingold()}). + L{layout_fruchterman_reingold()}). 5. If everything else above failed, the DrL layout algorithm - will be used (see L{Graph.layout_drl()}). + will be used (see L{layout_drl()}). All the arguments of this function except C{dim} are passed on to the chosen layout function (in case we have to call some layout @@ -1868,10 +1857,7 @@ def layout_sugiyama( maxiter=100, return_extended_graph=False, ): - """layout_sugiyama(layers=None, weights=None, hgap=1, vgap=1, maxiter=100, - return_extended_graph=False) - - Places the vertices using a layered Sugiyama layout. + """Places the vertices using a layered Sugiyama layout. This is a layered layout that is most suitable for directed acyclic graphs, although it works on undirected or cyclic graphs as well. @@ -1973,18 +1959,18 @@ def to_networkx(self): # Graph: decide on directness and mutliplicity if any(self.is_multiple()): if self.is_directed(): - klass = nx.MultiDiGraph + cls = nx.MultiDiGraph else: - klass = nx.MultiGraph + cls = nx.MultiGraph else: if self.is_directed(): - klass = nx.DiGraph + cls = nx.DiGraph else: - klass = nx.Graph + cls = nx.Graph # Graph attributes kw = {x: self[x] for x in self.attributes()} - g = klass(**kw) + g = cls(**kw) # Nodes and node attributes for i, v in enumerate(self.vs): @@ -1997,7 +1983,7 @@ def to_networkx(self): return g @classmethod - def from_networkx(klass, g): + def from_networkx(cls, g): """Converts the graph from networkx Vertex names will be converted to "_nx_name" attribute and the vertices @@ -2018,7 +2004,7 @@ def from_networkx(klass, g): # NOTE: we do not need a special class for multigraphs, it is taken # care for at the edge level rather than at the graph level. - graph = klass( + graph = cls( n=vcount, directed=g.is_directed(), graph_attrs=gattr, vertex_attrs=vattr ) @@ -2105,7 +2091,7 @@ def to_graph_tool( return g @classmethod - def from_graph_tool(klass, g): + def from_graph_tool(cls, g): """Converts the graph from graph-tool @param g: graph-tool Graph @@ -2117,7 +2103,7 @@ def from_graph_tool(klass, g): vcount = g.num_vertices() # Graph - graph = klass(n=vcount, directed=g.is_directed(), graph_attrs=gattr) + graph = cls(n=vcount, directed=g.is_directed(), graph_attrs=gattr) # Node attributes for key, val in list(g.vertex_properties.items()): @@ -2157,12 +2143,12 @@ def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds): @classmethod def Read_Adjacency( - klass, f, sep=None, comment_char="#", attribute=None, *args, **kwds + cls, f, sep=None, comment_char="#", attribute=None, *args, **kwds ): - """Constructs a graph based on an adjacency matrix from the given file + """Constructs a graph based on an adjacency matrix from the given file. Additional positional and keyword arguments not mentioned here are - passed intact to L{Graph.Adjacency}. + passed intact to L{Adjacency}. @param f: the name of the file to be read or a file object @param sep: the string that separates the matrix elements in a row. @@ -2190,10 +2176,10 @@ def Read_Adjacency( f.close() if attribute is None: - graph = klass.Adjacency(matrix, *args, **kwds) + graph = cls.Adjacency(matrix, *args, **kwds) else: kwds["attr"] = attribute - graph = klass.Weighted_Adjacency(matrix, *args, **kwds) + graph = cls.Weighted_Adjacency(matrix, *args, **kwds) return graph @@ -2291,7 +2277,7 @@ def Read_DIMACS(cls, f, directed=False): return graph @classmethod - def Read_GraphMLz(cls, f, *params, **kwds): + def Read_GraphMLz(cls, f, directed=True, index=0): """Read_GraphMLz(f, directed=True, index=0) Reads a graph from a zipped GraphML file. @@ -2305,10 +2291,9 @@ def Read_GraphMLz(cls, f, *params, **kwds): from igraph.utils import named_temporary_file with named_temporary_file() as tmpfile: - outf = open(tmpfile, "wb") - copyfileobj(gzip.GzipFile(f, "rb"), outf) - outf.close() - return cls.Read_GraphML(tmpfile) + with open(tmpfile, "wb") as outf: + copyfileobj(gzip.GzipFile(f, "rb"), outf) + return cls.Read_GraphML(tmpfile, directed=directed, index=index) def write_pickle(self, fname=None, version=-1): """Saves the graph in Python pickled format @@ -2364,7 +2349,7 @@ def write_picklez(self, fname=None, version=-1): return result @classmethod - def Read_Pickle(klass, fname=None): + def Read_Pickle(cls, fname=None): """Reads a graph from Python pickled format @param fname: the name of the file, a stream to read from, or @@ -2404,7 +2389,7 @@ def Read_Pickle(klass, fname=None): return result @classmethod - def Read_Picklez(klass, fname, *args, **kwds): + def Read_Picklez(cls, fname, *args, **kwds): """Reads a graph from compressed Python pickled format, uncompressing it on-the-fly. @@ -2424,7 +2409,7 @@ def Read_Picklez(klass, fname, *args, **kwds): return result @classmethod - def Read_Picklez(klass, fname, *args, **kwds): + def Read_Picklez(cls, fname, *args, **kwds): """Reads a graph from compressed Python pickled format, uncompressing it on-the-fly. @@ -2441,8 +2426,8 @@ def Read_Picklez(klass, fname, *args, **kwds): result = pickle.load(gzip.GzipFile(mode="rb", fileobj=fname)) else: result = pickle.load(gzip.open(fname, "rb")) - if not isinstance(result, klass): - raise TypeError("unpickled object is not a %s" % klass.__name__) + if not isinstance(result, cls): + raise TypeError("unpickled object is not a %s" % cls.__name__) return result # pylint: disable-msg=C0301,C0323 @@ -2794,7 +2779,7 @@ def write_svg( tk_window.destroy() @classmethod - def _identify_format(klass, filename): + def _identify_format(cls, filename): """_identify_format(filename) Tries to identify the format of the graph stored in the file with the @@ -2880,7 +2865,7 @@ def _identify_format(klass, filename): return "adjacency" @classmethod - def Read(klass, f, format=None, *args, **kwds): + def Read(cls, f, format=None, *args, **kwds): """Unified reading function for graphs. This method tries to identify the format of the graph given in @@ -2904,14 +2889,14 @@ def Read(klass, f, format=None, *args, **kwds): none was given. """ if format is None: - format = klass._identify_format(f) + format = cls._identify_format(f) try: - reader = klass._format_mapping[format][0] + reader = cls._format_mapping[format][0] except (KeyError, IndexError): raise IOError("unknown file format: %s" % str(format)) if reader is None: raise IOError("no reader method for file format: %s" % str(format)) - reader = getattr(klass, reader) + reader = getattr(cls, reader) return reader(f, *args, **kwds) Load = Read @@ -2978,7 +2963,7 @@ def write(self, f, format=None, *args, **kwds): @classmethod def DictList( - klass, + cls, vertices, edges, directed=False, @@ -3050,7 +3035,7 @@ def create_list_from_indices(l, n): # Construct the edges efk_src, efk_dest = edge_foreign_keys if iterative: - g = klass(n, [], directed, {}, vertex_attrs) + g = cls(n, [], directed, {}, vertex_attrs) for idx, edge_data in enumerate(edges): src_name, dst_name = edge_data[efk_src], edge_data[efk_dest] v1 = vertex_name_map[src_name] @@ -3095,14 +3080,14 @@ def create_list_from_indices(l, n): n = len(vertex_name_map) # Create the graph - return klass(n, edge_list, directed, {}, vertex_attrs, edge_attrs) + return cls(n, edge_list, directed, {}, vertex_attrs, edge_attrs) ##################################################### # Constructor for tuple-like representation of graphs @classmethod def TupleList( - klass, + cls, edges, directed=False, vertex_name_attr="name", @@ -3191,7 +3176,7 @@ def TupleList( n = len(idgen) # Construct the graph - return klass(n, edge_list, directed, {}, vertex_attributes, edge_attributes) + return cls(n, edge_list, directed, {}, vertex_attributes, edge_attributes) ################################# # Constructor for graph formulae @@ -3214,10 +3199,8 @@ def es(self): # Friendlier interface for bipartite methods @classmethod - def Bipartite(klass, types, *args, **kwds): - """Bipartite(types, edges, directed=False) - - Creates a bipartite graph with the given vertex types and edges. + def Bipartite(cls, types, edges, directed=False, *args, **kwds): + """Creates a bipartite graph with the given vertex types and edges. This is similar to the default constructor of the graph, the only difference is that it checks whether all the edges go between the two vertex classes and it assigns the type vector @@ -3242,15 +3225,13 @@ def Bipartite(klass, types, *args, **kwds): @return: the graph with a binary vertex attribute named C{"type"} that stores the vertex classes. """ - result = klass._Bipartite(types, *args, **kwds) + result = cls._Bipartite(types, edges, directed, *args, **kwds) result.vs["type"] = [bool(x) for x in types] return result @classmethod - def Full_Bipartite(klass, *args, **kwds): - """Full_Bipartite(n1, n2, directed=False, mode=ALL) - - Generates a full bipartite graph (directed or undirected, with or + def Full_Bipartite(cls, n1, n2, directed=False, mode="all", *args, **kwds): + """Generates a full bipartite graph (directed or undirected, with or without loops). >>> g = Graph.Full_Bipartite(2, 3) @@ -3262,22 +3243,20 @@ def Full_Bipartite(klass, *args, **kwds): @param n1: the number of vertices of the first kind. @param n2: the number of vertices of the second kind. @param directed: whether tp generate a directed graph. - @param mode: if C{OUT}, then all vertices of the first kind are - connected to the others; C{IN} specifies the opposite direction, - C{ALL} creates mutual edges. Ignored for undirected graphs. + @param mode: if C{"out"}, then all vertices of the first kind are + connected to the others; C{"in"} specifies the opposite direction, + C{"all"} creates mutual edges. Ignored for undirected graphs. @return: the graph with a binary vertex attribute named C{"type"} that stores the vertex classes. """ - result, types = klass._Full_Bipartite(*args, **kwds) + result, types = cls._Full_Bipartite(n1, n2, directed, mode, *args, **kwds) result.vs["type"] = types return result @classmethod - def Random_Bipartite(klass, *args, **kwds): - """Random_Bipartite(n1, n2, p=None, m=None, directed=False, neimode=ALL) - - Generates a random bipartite graph with the given number of vertices and + def Random_Bipartite(cls, n1, n2, p=None, m=None, directed=False, neimode="all", *args, **kwds): + """Generates a random bipartite graph with the given number of vertices and edges (if m is given), or with the given number of vertices and the given connection probability (if p is given). @@ -3299,15 +3278,17 @@ def Random_Bipartite(klass, *args, **kwds): will always point from type 2 to type 1. This argument is ignored for undirected graphs. """ - result, types = klass._Random_Bipartite(*args, **kwds) + if p is None: + p = -1 + if m is None: + m = -1 + result, types = cls._Random_Bipartite(n1, n2, p, m, directed, neimode, *args, **kwds) result.vs["type"] = types return result @classmethod - def GRG(klass, n, radius, torus=False): - """GRG(n, radius, torus=False, return_coordinates=False) - - Generates a random geometric graph. + def GRG(cls, n, radius, torus=False): + """Generates a random geometric graph. The algorithm drops the vertices randomly on the 2D unit square and connects them if they are closer to each other than the given radius. @@ -3319,16 +3300,14 @@ def GRG(klass, n, radius, torus=False): @param torus: This should be C{True} if we want to use a torus instead of a square. """ - result, xs, ys = klass._GRG(n, radius, torus) + result, xs, ys = cls._GRG(n, radius, torus) result.vs["x"] = xs result.vs["y"] = ys return result @classmethod - def Incidence(klass, *args, **kwds): - """Incidence(matrix, directed=False, mode=ALL, multiple=False, weighted=None) - - Creates a bipartite graph from an incidence matrix. + def Incidence(cls, matrix, directed=False, mode="out", multiple=False, weighted=None, *args, **kwds): + """Creates a bipartite graph from an incidence matrix. Example: @@ -3337,10 +3316,10 @@ def Incidence(klass, *args, **kwds): @param matrix: the incidence matrix. @param directed: whether to create a directed graph. @param mode: defines the direction of edges in the graph. If - C{OUT}, then edges go from vertices of the first kind + C{"out"}, then edges go from vertices of the first kind (corresponding to rows of the matrix) to vertices of the - second kind (the columns of the matrix). If C{IN}, the - opposite direction is used. C{ALL} creates mutual edges. + second kind (the columns of the matrix). If C{"in"}, the + opposite direction is used. C{"all"} creates mutual edges. Ignored for undirected graphs. @param multiple: defines what to do with non-zero entries in the matrix. If C{False}, non-zero entries will create an edge no matter @@ -3360,28 +3339,25 @@ def Incidence(klass, *args, **kwds): @return: the graph with a binary vertex attribute named C{"type"} that stores the vertex classes. """ - weighted = kwds.pop("weighted", False) is_weighted = True if weighted or weighted == "" else False - multiple = kwds.get("multiple", False) if is_weighted and multiple: raise ValueError("arguments weighted and multiple can not co-exist") - result, types = klass._Incidence(*args, **kwds) + result, types = cls._Incidence(matrix, directed, mode, multiple, *args, **kwds) result.vs["type"] = types if is_weighted: weight_attr = "weight" if weighted == True else weighted - mat = args[0] _, rows, columns = result.get_incidence() num_vertices_of_first_kind = len(rows) for edge in result.es: source, target = edge.tuple if source in rows: - edge[weight_attr] = mat[source][target - num_vertices_of_first_kind] + edge[weight_attr] = matrix[source][target - num_vertices_of_first_kind] else: - edge[weight_attr] = mat[target][source - num_vertices_of_first_kind] + edge[weight_attr] = matrix[target][source - num_vertices_of_first_kind] return result @classmethod - def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): + def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): """DataFrame(edges, directed=True, vertices=None) Generates a graph from one or two dataframes. @@ -3504,10 +3480,6 @@ def DataFrame(klass, edges, directed=True, vertices=None, use_vids=False): def get_vertex_dataframe(self): """Export vertices with attributes to pandas.DataFrame - @return: a pandas.DataFrame representing vertices and their attributes. - The index uses vertex IDs, from 0 to N - 1 where N is the number of - vertices. - If you want to use vertex names as index, you can do: >>> from string import ascii_letters @@ -3516,6 +3488,9 @@ def get_vertex_dataframe(self): >>> df = graph.get_vertex_dataframe() >>> df.set_index('name', inplace=True) + @return: a pandas.DataFrame representing vertices and their attributes. + The index uses vertex IDs, from 0 to N - 1 where N is the number of + vertices. """ try: import pandas as pd @@ -3533,14 +3508,6 @@ def get_vertex_dataframe(self): def get_edge_dataframe(self): """Export edges with attributes to pandas.DataFrame - @return: a pandas.DataFrame representing edges and their attributes. - The index uses edge IDs, from 0 to M - 1 where M is the number of - edges. The first two columns of the dataframe represent the IDs of - source and target vertices for each edge. These columns have names - "source" and "target". If your edges have attributes with the same - names, they will be present in the dataframe, but not in the first - two columns. - If you want to use source and target vertex IDs as index, you can do: >>> from string import ascii_letters @@ -3560,6 +3527,13 @@ def get_edge_dataframe(self): >>> df['target'].replace(df_vert['name'], inplace=True) >>> df_vert.set_index('name', inplace=True) # Optional + @return: a pandas.DataFrame representing edges and their attributes. + The index uses edge IDs, from 0 to M - 1 where M is the number of + edges. The first two columns of the dataframe represent the IDs of + source and target vertices for each edge. These columns have names + "source" and "target". If your edges have attributes with the same + names, they will be present in the dataframe, but not in the first + two columns. """ try: import pandas as pd @@ -3667,9 +3641,7 @@ def bipartite_projection_size(self, types="type", *args, **kwds): return super(Graph, self).bipartite_projection_size(types, *args, **kwds) def get_incidence(self, types="type", *args, **kwds): - """get_incidence(self, types="type") - - Returns the incidence matrix of a bipartite graph. The incidence matrix + """Returns the incidence matrix of a bipartite graph. The incidence matrix is an M{n} times M{m} matrix, where M{n} and M{m} are the number of vertices in the two vertex classes. @@ -3689,7 +3661,7 @@ def dfs(self, vid, mode=OUT): """Conducts a depth first search (DFS) on the graph. @param vid: the root vertex ID - @param mode: either L{IN} or L{OUT} or L{ALL}, ignored + @param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}, ignored for undirected graphs. @return: a tuple with the following items: - The vertex IDs visited (in order) @@ -4014,10 +3986,10 @@ def __plot__(self, context, bbox, palette, *args, **kwds): The default is C{False}. - C{layout}: the layout to be used. If not an instance of - L{Layout}, it will be passed to L{Graph.layout} to calculate + L{Layout}, it will be passed to L{layout} to calculate the layout. Note that if you want a deterministic layout that does not change with every plot, you must either use a - deterministic layout function (like L{Graph.layout_circle}) or + deterministic layout function (like L{layout_circle}) or calculate the layout in advance and pass a L{Layout} object here. - C{margin}: the top, right, bottom, left margins as a 4-tuple. @@ -4303,7 +4275,7 @@ def intersection(self, other, byname="auto"): ############################################################## -class VertexSeq(_igraph.VertexSeq): +class VertexSeq(_VertexSeq): """Class representing a sequence of vertices in the graph. This class is most easily accessed by the C{vs} field of the @@ -4361,7 +4333,7 @@ class VertexSeq(_igraph.VertexSeq): Some methods of the vertex sequences are simply proxy methods to the corresponding methods in the L{Graph} object. One such example is - L{VertexSeq.degree()}: + C{VertexSeq.degree()}: >>> g=Graph.Tree(7, 2) >>> g.vs.degree() @@ -4572,7 +4544,7 @@ def __call__(self, *args, **kwds): ############################################################## -class EdgeSeq(_igraph.EdgeSeq): +class EdgeSeq(_EdgeSeq): """Class representing a sequence of edges in the graph. This class is most easily accessed by the C{es} field of the @@ -4633,7 +4605,7 @@ class EdgeSeq(_igraph.EdgeSeq): Some methods of the edge sequences are simply proxy methods to the corresponding methods in the L{Graph} object. One such example is - L{EdgeSeq.is_multiple()}: + C{EdgeSeq.is_multiple()}: >>> g=Graph(3, [(0,1), (1,0), (1,2)]) >>> g.es.is_multiple() @@ -5090,10 +5062,10 @@ def _add_proxy_methods(): rename_methods[VertexSeq] = {"delete_vertices": "delete"} rename_methods[EdgeSeq] = {"delete_edges": "delete", "subgraph_edges": "subgraph"} - for klass, methods in decorated_methods.items(): + for cls, methods in decorated_methods.items(): for method in methods: - new_method_name = rename_methods[klass].get(method, method) - setattr(klass, new_method_name, _graphmethod(None, method)) + new_method_name = rename_methods[cls].get(method, method) + setattr(cls, new_method_name, _graphmethod(None, method)) setattr( EdgeSeq, diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index fcdf10eb8..6defa2449 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -511,11 +511,11 @@ def main(): ] ) for part in parts: - klass = available_classes.get(part, None) - if klass is None: + cls = available_classes.get(part, None) + if cls is None: print("Warning: unknown shell class `%s'" % part, file=sys.stderr) continue - shell_classes.append(klass) + shell_classes.append(cls) else: shell_classes = [IPythonShell, ClassicPythonShell] import platform diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index f1b57e345..e54dc35ac 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -338,14 +338,15 @@ def cluster_graph(self, combine_vertices=None, combine_edges=None): @param combine_vertices: specifies how to derive the attributes of the vertices in the new graph from the attributes of the old ones. - See L{Graph.contract_vertices()} for more details. + See L{Graph.contract_vertices()} + for more details. @param combine_edges: specifies how to derive the attributes of the edges in the new graph from the attributes of the old ones. See - L{igraph.Graph.simplify()} for more details. If you specify C{False} - here, edges will not be combined, and the number of edges between - the vertices representing the original clusters will be equal to - the number of edges between the members of those clusters in the - original graph. + L{Graph.simplify()} for more details. + If you specify C{False} here, edges will not be combined, and the + number of edges between the vertices representing the original + clusters will be equal to the number of edges between the members of + those clusters in the original graph. @return: the new graph. """ diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 7dd9292df..38bd3150c 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -258,8 +258,9 @@ def to_radial(self, min_angle=100, max_angle=80, min_radius=0.0, max_radius=1.0) top-down ones (that's why the Y coordinate belongs to the radius). It can also be used in conjunction with the Fruchterman-Reingold layout algorithm via its I{miny} and I{maxy} parameters (see - L{Graph.layout_fruchterman_reingold}) to produce radial layouts - where the radius belongs to some property of the vertices. + L{Graph.layout_fruchterman_reingold()}) + to produce radial layouts where the radius belongs to some property of + the vertices. @param min_angle: the angle corresponding to the minimum X value @param max_angle: the angle corresponding to the maximum X value From d6d0d57c8f78587f244a37b69377ada2340aacd9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Mar 2021 15:01:12 +0100 Subject: [PATCH 0412/1892] chore: blackened source --- src/igraph/__init__.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 946dd781d..6b4da6516 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3255,7 +3255,9 @@ def Full_Bipartite(cls, n1, n2, directed=False, mode="all", *args, **kwds): return result @classmethod - def Random_Bipartite(cls, n1, n2, p=None, m=None, directed=False, neimode="all", *args, **kwds): + def Random_Bipartite( + cls, n1, n2, p=None, m=None, directed=False, neimode="all", *args, **kwds + ): """Generates a random bipartite graph with the given number of vertices and edges (if m is given), or with the given number of vertices and the given connection probability (if p is given). @@ -3282,7 +3284,9 @@ def Random_Bipartite(cls, n1, n2, p=None, m=None, directed=False, neimode="all", p = -1 if m is None: m = -1 - result, types = cls._Random_Bipartite(n1, n2, p, m, directed, neimode, *args, **kwds) + result, types = cls._Random_Bipartite( + n1, n2, p, m, directed, neimode, *args, **kwds + ) result.vs["type"] = types return result @@ -3306,7 +3310,16 @@ def GRG(cls, n, radius, torus=False): return result @classmethod - def Incidence(cls, matrix, directed=False, mode="out", multiple=False, weighted=None, *args, **kwds): + def Incidence( + cls, + matrix, + directed=False, + mode="out", + multiple=False, + weighted=None, + *args, + **kwds + ): """Creates a bipartite graph from an incidence matrix. Example: @@ -3351,9 +3364,13 @@ def Incidence(cls, matrix, directed=False, mode="out", multiple=False, weighted= for edge in result.es: source, target = edge.tuple if source in rows: - edge[weight_attr] = matrix[source][target - num_vertices_of_first_kind] + edge[weight_attr] = matrix[source][ + target - num_vertices_of_first_kind + ] else: - edge[weight_attr] = matrix[target][source - num_vertices_of_first_kind] + edge[weight_attr] = matrix[target][ + source - num_vertices_of_first_kind + ] return result @classmethod From a4be07e98eec4845f51673f4a26727011ed54a39 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 5 Mar 2021 11:22:30 +1100 Subject: [PATCH 0413/1892] Add matplotlib plotting to VertexClustering --- src/igraph/drawing/graph.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 416ff4dfc..0ab460f45 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1010,6 +1010,22 @@ def callback_edge_offset(event): # FIXME: deal with unnamed *args + # graph is not necessarily a graph, it can be a VertexClustering + # If so, extract the graph and set the coloring unless specified + # externally + from igraph.clustering import VertexClustering + if isinstance(graph, VertexClustering): + clustering = graph + graph = clustering.graph + + if "vertex_color" not in kwds: + clusters = sorted(set(clustering.membership)) + n_colors = len(clusters) + cmap = mpl.cm.get_cmap('viridis') + colors = [cmap(1.0 * i / n_colors) for i in range(n_colors)] + c = [colors[clusters.index(i)] for i in clustering.membership] + kwds["vertex_color"] = c + # Get layout layout = kwds.get("layout", graph.layout()) if isinstance(layout, str): From 3e70e1b6e6787e974ce5a4c8679c93b555a39917 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 6 Mar 2021 08:20:10 +1100 Subject: [PATCH 0414/1892] mark_groups in matplotlib plot --- src/igraph/drawing/graph.py | 61 ++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 0ab460f45..bdcd876c6 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -983,6 +983,8 @@ def draw(self, graph, *args, **kwds): from matplotlib.patches import FancyArrowPatch from matplotlib.patches import ArrowStyle import numpy as np + from collections import defaultdict + from igraph.clustering import VertexClustering def shrink_vertex(ax, aux, vcoord, vsize_squared): """Shrink edge by vertex size""" @@ -1010,14 +1012,34 @@ def callback_edge_offset(event): # FIXME: deal with unnamed *args - # graph is not necessarily a graph, it can be a VertexClustering - # If so, extract the graph and set the coloring unless specified - # externally - from igraph.clustering import VertexClustering + # graph is not necessarily a graph, it can be a VertexClustering. If so + # extract the graph. The clustering itself can be overridden using + # the "mark_groups" option + clustering = None if isinstance(graph, VertexClustering): clustering = graph graph = clustering.graph + # mark groups: the used data structure is eventually the dict option: + # tuples of vertex indices as the keys, colors as the values. We + # convert other formats into that one here + if 'mark_groups' in kwds: + if isinstance(kwds['mark_groups'], VertexClustering): + if clustering is not None: + raise ValueError( + 'mark_groups cannot override a clustering with another' + ) + else: + clustering = kwds.pop('mark_groups') + else: + try: + mg_iter = iter(kwds['mark_groups']) + except TypeError: + raise TypeError('mark_groups is not in the right format') + kwds['mark_groups'] = dict(mg_iter) + + # If a clustering is set, color vertices and mark groups if requested + if clustering is not None: if "vertex_color" not in kwds: clusters = sorted(set(clustering.membership)) n_colors = len(clusters) @@ -1026,6 +1048,16 @@ def callback_edge_offset(event): c = [colors[clusters.index(i)] for i in clustering.membership] kwds["vertex_color"] = c + # mark_groups if not explicitely marked + if 'mark_groups' not in kwds: + mark_groups = defaultdict(list) + for i, color in enumerate(c): + mark_groups[color].append(i) + + # Invert keys and values + mark_groups = {tuple(v): k for k, v in mark_groups.items()} + kwds['mark_groups'] = mark_groups + # Get layout layout = kwds.get("layout", graph.layout()) if isinstance(layout, str): @@ -1034,6 +1066,27 @@ def callback_edge_offset(event): # Vertex coordinates vcoord = layout.coords + # Mark groups + if 'mark_groups' in kwds: + # FIXME: does this generate a new dep? + from scipy.spatial import ConvexHull + for idx, color in kwds['mark_groups'].items(): + points = [vcoord[i] for i in idx] + ch = ConvexHull(points) + vertices = np.array([vcoord[idx[i]] for i in ch.vertices]) + # 15% expansion + vertices += 0.15 * (vertices - vertices.mean(axis=0)) + + # NOTE: we could include a corner cutting algorithm close to + # the vertices (e.g. Chaikin) for beautification + polygon = mpl.patches.Polygon( + vertices, + facecolor=color, alpha=0.3, + zorder=0, edgecolor=color, + lw=2, + ) + ax.add_artist(polygon) + # Vertex properties nv = graph.vcount() From 7b3625de4041c521d840f40439708a7748e86f5d Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 7 Mar 2021 07:21:53 +1100 Subject: [PATCH 0415/1892] Sort out the mark_group option a little --- src/igraph/drawing/graph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index bdcd876c6..2f7580bd1 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1030,7 +1030,7 @@ def callback_edge_offset(event): 'mark_groups cannot override a clustering with another' ) else: - clustering = kwds.pop('mark_groups') + clustering = kwds['mark_groups'] else: try: mg_iter = iter(kwds['mark_groups']) @@ -1049,7 +1049,7 @@ def callback_edge_offset(event): kwds["vertex_color"] = c # mark_groups if not explicitely marked - if 'mark_groups' not in kwds: + if ('mark_groups' in kwds) and (kwds['mark_groups'] == clustering): mark_groups = defaultdict(list) for i, color in enumerate(c): mark_groups[color].append(i) From bdddc4941f0064ec6c494df574d33b15b2c1e88b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 7 Mar 2021 07:24:55 +1100 Subject: [PATCH 0416/1892] Handle scipy import and format black --- src/igraph/drawing/graph.py | 39 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 2f7580bd1..4b0ad08ec 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1023,40 +1023,40 @@ def callback_edge_offset(event): # mark groups: the used data structure is eventually the dict option: # tuples of vertex indices as the keys, colors as the values. We # convert other formats into that one here - if 'mark_groups' in kwds: - if isinstance(kwds['mark_groups'], VertexClustering): + if "mark_groups" in kwds: + if isinstance(kwds["mark_groups"], VertexClustering): if clustering is not None: raise ValueError( - 'mark_groups cannot override a clustering with another' + "mark_groups cannot override a clustering with another" ) else: - clustering = kwds['mark_groups'] + clustering = kwds["mark_groups"] else: try: - mg_iter = iter(kwds['mark_groups']) + mg_iter = iter(kwds["mark_groups"]) except TypeError: - raise TypeError('mark_groups is not in the right format') - kwds['mark_groups'] = dict(mg_iter) + raise TypeError("mark_groups is not in the right format") + kwds["mark_groups"] = dict(mg_iter) # If a clustering is set, color vertices and mark groups if requested if clustering is not None: if "vertex_color" not in kwds: clusters = sorted(set(clustering.membership)) n_colors = len(clusters) - cmap = mpl.cm.get_cmap('viridis') + cmap = mpl.cm.get_cmap("viridis") colors = [cmap(1.0 * i / n_colors) for i in range(n_colors)] c = [colors[clusters.index(i)] for i in clustering.membership] kwds["vertex_color"] = c # mark_groups if not explicitely marked - if ('mark_groups' in kwds) and (kwds['mark_groups'] == clustering): + if ("mark_groups" in kwds) and (kwds["mark_groups"] == clustering): mark_groups = defaultdict(list) for i, color in enumerate(c): mark_groups[color].append(i) # Invert keys and values mark_groups = {tuple(v): k for k, v in mark_groups.items()} - kwds['mark_groups'] = mark_groups + kwds["mark_groups"] = mark_groups # Get layout layout = kwds.get("layout", graph.layout()) @@ -1067,10 +1067,15 @@ def callback_edge_offset(event): vcoord = layout.coords # Mark groups - if 'mark_groups' in kwds: - # FIXME: does this generate a new dep? - from scipy.spatial import ConvexHull - for idx, color in kwds['mark_groups'].items(): + if "mark_groups" in kwds: + try: + from scipy.spatial import ConvexHull + except ImportError: + raise ImportError( + "You should install scipy package in order to use mark_groups" + ) + + for idx, color in kwds["mark_groups"].items(): points = [vcoord[i] for i in idx] ch = ConvexHull(points) vertices = np.array([vcoord[idx[i]] for i in ch.vertices]) @@ -1081,8 +1086,10 @@ def callback_edge_offset(event): # the vertices (e.g. Chaikin) for beautification polygon = mpl.patches.Polygon( vertices, - facecolor=color, alpha=0.3, - zorder=0, edgecolor=color, + facecolor=color, + alpha=0.3, + zorder=0, + edgecolor=color, lw=2, ) ax.add_artist(polygon) From f87ece8fc737c15e6482e90a9a9873d283b18cbb Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 8 Mar 2021 18:57:33 +1100 Subject: [PATCH 0417/1892] Edit docs and enable mark_groups=True in matplotlib --- src/igraph/__init__.py | 6 ++++++ src/igraph/drawing/graph.py | 34 ++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 6b4da6516..901bad892 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -4018,6 +4018,12 @@ def __plot__(self, context, bbox, palette, *args, **kwds): - C{False}: no groups will be highlighted + - C{True}: only valid if the object plotted is a + L{VertexClustering} or L{VertexCover}. The vertex groups in the + clutering or cover will be highlighted such that the i-th + group will be colored by the i-th color from the current + palette. If used when plotting a graph, it will throw an error. + - A dict mapping tuples of vertex indices to color names. The given vertex groups will be highlighted by the given colors. diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 4b0ad08ec..3a41accec 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -984,7 +984,7 @@ def draw(self, graph, *args, **kwds): from matplotlib.patches import ArrowStyle import numpy as np from collections import defaultdict - from igraph.clustering import VertexClustering + from igraph.clustering import VertexClustering, VertexCover def shrink_vertex(ax, aux, vcoord, vsize_squared): """Shrink edge by vertex size""" @@ -1016,7 +1016,7 @@ def callback_edge_offset(event): # extract the graph. The clustering itself can be overridden using # the "mark_groups" option clustering = None - if isinstance(graph, VertexClustering): + if isinstance(graph, (VertexClustering, VertexCover)): clustering = graph graph = clustering.graph @@ -1024,13 +1024,19 @@ def callback_edge_offset(event): # tuples of vertex indices as the keys, colors as the values. We # convert other formats into that one here if "mark_groups" in kwds: - if isinstance(kwds["mark_groups"], VertexClustering): + if kwds["mark_groups"] is False: + del kwds["mark_groups"] + elif (kwds["mark_groups"] is True) and (clustering is not None): + pass + # Deferred import to avoid a cycle in the import graph + elif isinstance(kwds["mark_groups"], (VertexClustering, VertexCover)): if clustering is not None: raise ValueError( "mark_groups cannot override a clustering with another" ) else: clustering = kwds["mark_groups"] + kwds["mark_groups"] = True else: try: mg_iter = iter(kwds["mark_groups"]) @@ -1041,15 +1047,18 @@ def callback_edge_offset(event): # If a clustering is set, color vertices and mark groups if requested if clustering is not None: if "vertex_color" not in kwds: - clusters = sorted(set(clustering.membership)) + membership = clustering.membership + if isinstance(clustering, VertexCover): + membership = [x[0] for x in membership] + clusters = sorted(set(membership)) n_colors = len(clusters) cmap = mpl.cm.get_cmap("viridis") colors = [cmap(1.0 * i / n_colors) for i in range(n_colors)] - c = [colors[clusters.index(i)] for i in clustering.membership] + c = [colors[clusters.index(i)] for i in membership] kwds["vertex_color"] = c # mark_groups if not explicitely marked - if ("mark_groups" in kwds) and (kwds["mark_groups"] == clustering): + if ("mark_groups" in kwds) and (kwds["mark_groups"] is True): mark_groups = defaultdict(list) for i, color in enumerate(c): mark_groups[color].append(i) @@ -1068,22 +1077,15 @@ def callback_edge_offset(event): # Mark groups if "mark_groups" in kwds: - try: - from scipy.spatial import ConvexHull - except ImportError: - raise ImportError( - "You should install scipy package in order to use mark_groups" - ) - for idx, color in kwds["mark_groups"].items(): points = [vcoord[i] for i in idx] - ch = ConvexHull(points) - vertices = np.array([vcoord[idx[i]] for i in ch.vertices]) + vertices = np.asarray(convex_hull(points, coords=True)) # 15% expansion vertices += 0.15 * (vertices - vertices.mean(axis=0)) # NOTE: we could include a corner cutting algorithm close to - # the vertices (e.g. Chaikin) for beautification + # the vertices (e.g. Chaikin) for beautification, or a corner + # radius like it's done in the Cairo interface polygon = mpl.patches.Polygon( vertices, facecolor=color, From 78cce97beeced1ca05feaec0601a5cdcda94d99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Mon, 8 Mar 2021 14:59:14 +0100 Subject: [PATCH 0418/1892] fix up changes requested in review --- src/igraph/drawing/graph.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 3a41accec..49d580646 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -977,13 +977,14 @@ def __init__(self, ax): def draw(self, graph, *args, **kwds): # NOTE: matplotlib has numpy as a dependency, so we can use it in here + from collections import defaultdict import matplotlib as mpl import matplotlib.markers as mmarkers from matplotlib.path import Path from matplotlib.patches import FancyArrowPatch from matplotlib.patches import ArrowStyle import numpy as np - from collections import defaultdict + # Deferred import to avoid a cycle in the import graph from igraph.clustering import VertexClustering, VertexCover def shrink_vertex(ax, aux, vcoord, vsize_squared): @@ -1028,7 +1029,6 @@ def callback_edge_offset(event): del kwds["mark_groups"] elif (kwds["mark_groups"] is True) and (clustering is not None): pass - # Deferred import to avoid a cycle in the import graph elif isinstance(kwds["mark_groups"], (VertexClustering, VertexCover)): if clustering is not None: raise ValueError( @@ -1057,8 +1057,8 @@ def callback_edge_offset(event): c = [colors[clusters.index(i)] for i in membership] kwds["vertex_color"] = c - # mark_groups if not explicitely marked - if ("mark_groups" in kwds) and (kwds["mark_groups"] is True): + # mark_groups if not explicitly marked + if kwds.get("mark_groups") is True: mark_groups = defaultdict(list) for i, color in enumerate(c): mark_groups[color].append(i) From dd49def78581064cca94ebcd58b7bf0384e84151 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Mar 2021 19:00:21 +0100 Subject: [PATCH 0419/1892] doc: added missing python-igraph replacement template in global.rst [ci skip] --- doc/source/include/global.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/source/include/global.rst b/doc/source/include/global.rst index 361937c76..7a928c465 100644 --- a/doc/source/include/global.rst +++ b/doc/source/include/global.rst @@ -1 +1,3 @@ .. |igraph| replace:: *igraph* +.. |python-igraph| replace:: *python-igraph* + From a92409f1e7eaa5ebf1203e8511ff4fbcb8353f04 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 8 Mar 2021 19:49:18 +0100 Subject: [PATCH 0420/1892] doc: removed unneeded function signatures from many docstrings --- src/_igraph/graphobject.c | 18 ++-- src/igraph/__init__.py | 197 +++++++++++--------------------------- 2 files changed, 64 insertions(+), 151 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 48cda7d44..db09ad2b0 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11980,15 +11980,17 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"vcount", (PyCFunction) igraphmodule_Graph_vcount, METH_NOARGS, "vcount()\n--\n\n" - "Counts the number of vertices.\n" - "@return: the number of vertices in the graph.\n" "@rtype: integer"}, + "Counts the number of vertices.\n\n" + "@return: the number of vertices in the graph.\n" + "@rtype: integer\n"}, // interface to igraph_ecount {"ecount", (PyCFunction) igraphmodule_Graph_ecount, METH_NOARGS, "ecount()\n--\n\n" - "Counts the number of edges.\n" - "@return: the number of edges in the graph.\n" "@rtype: integer"}, + "Counts the number of edges.\n\n" + "@return: the number of edges in the graph.\n" + "@rtype: integer\n"}, // interface to igraph_is_dag {"is_dag", (PyCFunction) igraphmodule_Graph_is_dag, @@ -12003,7 +12005,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"is_directed", (PyCFunction) igraphmodule_Graph_is_directed, METH_NOARGS, "is_directed()\n--\n\n" - "Checks whether the graph is directed.\n" + "Checks whether the graph is directed.\n\n" "@return: C{True} if it is directed, C{False} otherwise.\n" "@rtype: boolean"}, @@ -15260,11 +15262,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"vertex_attributes", (PyCFunction) igraphmodule_Graph_vertex_attributes, METH_NOARGS, "vertex_attributes()\n--\n\n" - "@return: the attribute name list of the graph's vertices\n"}, + "@return: the attribute name list of the vertices of the graph\n"}, {"edge_attributes", (PyCFunction) igraphmodule_Graph_edge_attributes, METH_NOARGS, "edge_attributes()\n--\n\n" - "@return: the attribute name list of the graph's edges\n"}, + "@return: the attribute name list of the edges of the graph\n"}, /////////////// // OPERATORS // @@ -15287,7 +15289,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"dominator", (PyCFunction) igraphmodule_Graph_dominator, METH_VARARGS | METH_KEYWORDS, "dominator(vid, mode=\"out\")\n--\n\n" - "Returns the dominator tree from the given root node" + "Returns the dominator tree from the given root node\n\n" "@param vid: the root vertex ID\n" "@param mode: either C{\"in\"} or C{\"out\"}\n" "@return: a list containing the dominator tree for the current graph." diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 901bad892..ea9f6a20a 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -337,9 +337,7 @@ def __init__(self, *args, **kwds): self.es[key] = value def add_edge(self, source, target, **kwds): - """add_edge(source, target, **kwds) - - Adds a single edge to the graph. + """Adds a single edge to the graph. Keyword arguments (except the source and target arguments) will be assigned to the edge as attributes. @@ -359,9 +357,7 @@ def add_edge(self, source, target, **kwds): return edge def add_edges(self, es, attributes=None): - """add_edges(es, attributes=None) - - Adds some edges to the graph. + """Adds some edges to the graph. @param es: the list of edges to be added. Every edge is represented with a tuple containing the vertex IDs or names of the two @@ -379,9 +375,7 @@ def add_edges(self, es, attributes=None): return res def add_vertex(self, name=None, **kwds): - """add_vertex(name=None, **kwds) - - Adds a single vertex to the graph. Keyword arguments will be assigned + """Adds a single vertex to the graph. Keyword arguments will be assigned as vertex attributes. Note that C{name} as a keyword argument is treated specially; if a graph has C{name} as a vertex attribute, it allows one to refer to vertices by their names in most places where igraph expects @@ -401,9 +395,7 @@ def add_vertex(self, name=None, **kwds): return vertex def add_vertices(self, n, attributes=None): - """add_vertices(n, attributes=None) - - Adds some vertices to the graph. + """Adds some vertices to the graph. Note that if C{n} is a sequence of strings, indicating the names of the new vertices, and attributes has a key C{name}, the two conflict. In @@ -447,23 +439,8 @@ def add_vertices(self, n, attributes=None): self.vs[m:][key] = val return result - def adjacent(self, *args, **kwds): - """adjacent(vertex, mode=OUT) - - Returns the edges a given vertex is incident on. - - @deprecated: replaced by L{incident()} since igraph 0.6 - """ - deprecated( - "Graph.adjacent() is deprecated since igraph 0.6, please use " - "Graph.incident() instead" - ) - return self.incident(*args, **kwds) - def as_directed(self, *args, **kwds): - """as_directed(*args, **kwds) - - Returns a directed copy of this graph. Arguments are passed on + """Returns a directed copy of this graph. Arguments are passed on to L{to_directed()} that is invoked on the copy. """ copy = self.copy() @@ -471,9 +448,7 @@ def as_directed(self, *args, **kwds): return copy def as_undirected(self, *args, **kwds): - """as_undirected(*args, **kwds) - - Returns an undirected copy of this graph. Arguments are passed on + """Returns an undirected copy of this graph. Arguments are passed on to L{to_undirected()} that is invoked on the copy. """ copy = self.copy() @@ -603,9 +578,7 @@ def biconnected_components(self, return_articulation_points=False): blocks = biconnected_components def clear(self): - """clear() - - Clears the graph, deleting all vertices, edges, and attributes. + """Clears the graph, deleting all vertices, edges, and attributes. @see: L{delete_vertices} and L{delete_edges}. """ @@ -614,9 +587,7 @@ def clear(self): del self[attr] def cohesive_blocks(self): - """cohesive_blocks() - - Calculates the cohesive block structure of the graph. + """Calculates the cohesive block structure of the graph. Cohesive blocking is a method of determining hierarchical subsets of graph vertices based on their structural cohesion (i.e. vertex connectivity). @@ -633,23 +604,19 @@ def cohesive_blocks(self): """ return CohesiveBlocks(self, *GraphBase.cohesive_blocks(self)) - def clusters(self, mode=STRONG): - """clusters(mode=STRONG) - - Calculates the (strong or weak) clusters (connected components) for + def clusters(self, mode="strong"): + """Calculates the (strong or weak) clusters (connected components) for a given graph. - @param mode: must be either C{STRONG} or C{WEAK}, depending on the - clusters being sought. Optional, defaults to C{STRONG}. + @param mode: must be either C{"strong"} or C{"weak"}, depending on the + clusters being sought. Optional, defaults to C{"strong"}. @return: a L{VertexClustering} object""" return VertexClustering(self, GraphBase.clusters(self, mode)) components = clusters def degree_distribution(self, bin_width=1, *args, **kwds): - """degree_distribution(bin_width=1, ...) - - Calculates the degree distribution of the graph. + """Calculates the degree distribution of the graph. Unknown keyword arguments are directly passed to L{degree()}. @@ -661,9 +628,7 @@ def degree_distribution(self, bin_width=1, *args, **kwds): return result def dyad_census(self, *args, **kwds): - """dyad_census() - - Calculates the dyad census of the graph. + """Calculates the dyad census of the graph. Dyad census means classifying each pair of vertices of a directed graph into three categories: mutual (there is an edge from I{a} to @@ -796,22 +761,8 @@ def get_adjlist(self, mode="out"): """ return [self.neighbors(idx, mode) for idx in range(self.vcount())] - def get_adjedgelist(self, *args, **kwds): - """Returns the incidence list representation of the graph. - - @deprecated: replaced by L{get_inclist()} since igraph 0.6 - @see: Graph.get_inclist() - """ - deprecated( - "Graph.get_adjedgelist() is deprecated since igraph 0.6, " - "please use Graph.get_inclist() instead" - ) - return self.get_inclist(*args, **kwds) - - def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): - """get_all_simple_paths(v, to=None, cutoff=-1, mode=OUT) - - Calculates all the simple paths from a given node to some other nodes + def get_all_simple_paths(self, v, to=None, cutoff=-1, mode="out"): + """Calculates all the simple paths from a given node to some other nodes (or all of them) in a graph. A path is simple if its vertices are unique, i.e. no vertex is visited @@ -844,10 +795,8 @@ def get_all_simple_paths(self, v, to=None, cutoff=-1, mode=OUT): prev = index + 1 return result - def get_inclist(self, mode=OUT): - """get_inclist(mode=OUT) - - Returns the incidence list representation of the graph. + def get_inclist(self, mode="out"): + """Returns the incidence list representation of the graph. The incidence list representation is a list of lists. Each item of the outer list belongs to a single vertex of the graph. @@ -862,9 +811,7 @@ def get_inclist(self, mode=OUT): return [self.incident(idx, mode) for idx in range(self.vcount())] def gomory_hu_tree(self, capacity=None, flow="flow"): - """gomory_hu_tree(capacity=None, flow="flow") - - Calculates the Gomory-Hu tree of an undirected graph with optional + """Calculates the Gomory-Hu tree of an undirected graph with optional edge capacities. The Gomory-Hu tree is a concise representation of the value of all the @@ -887,25 +834,21 @@ def gomory_hu_tree(self, capacity=None, flow="flow"): return graph def is_named(self): - """is_named() + """Returns whether the graph is named. - Returns whether the graph is named, i.e., whether it has a "name" - vertex attribute. + A graph is named if and only if it has a C{"name"} vertex attribute. """ return "name" in self.vertex_attributes() def is_weighted(self): - """is_weighted() + """Returns whether the graph is weighted. - Returns whether the graph is weighted, i.e., whether it has a "weight" - edge attribute. + A graph is weighted if and only if it has a C{"weight"} edge attribute. """ return "weight" in self.edge_attributes() def maxflow(self, source, target, capacity=None): - """maxflow(source, target, capacity=None) - - Returns a maximum flow between the given source and target vertices + """Returns a maximum flow between the given source and target vertices in a graph. A maximum flow from I{source} to I{target} is an assignment of @@ -930,9 +873,7 @@ def maxflow(self, source, target, capacity=None): return Flow(self, *GraphBase.maxflow(self, source, target, capacity)) def mincut(self, source=None, target=None, capacity=None): - """mincut(source=None, target=None, capacity=None) - - Calculates the minimum cut between the given source and target vertices + """Calculates the minimum cut between the given source and target vertices or within the whole graph. The minimum cut is the minimum set of edges that needs to be removed to @@ -958,9 +899,7 @@ def mincut(self, source=None, target=None, capacity=None): return Cut(self, *GraphBase.mincut(self, source, target, capacity)) def st_mincut(self, source, target, capacity=None): - """st_mincut(source, target, capacity=None) - - Calculates the minimum cut between the source and target vertices in a + """Calculates the minimum cut between the source and target vertices in a graph. @param source: the source vertex ID @@ -975,9 +914,7 @@ def st_mincut(self, source, target, capacity=None): return Cut(self, *GraphBase.st_mincut(self, source, target, capacity)) def modularity(self, membership, weights=None): - """modularity(membership, weights=None) - - Calculates the modularity score of the graph with respect to a given + """Calculates the modularity score of the graph with respect to a given clustering. The modularity of a graph w.r.t. some division measures how good the @@ -1012,9 +949,7 @@ def modularity(self, membership, weights=None): return GraphBase.modularity(self, membership, weights) def path_length_hist(self, directed=True): - """path_length_hist(directed=True) - - Returns the path length histogram of the graph + """Returns the path length histogram of the graph @param directed: whether to consider directed paths. Ignored for undirected graphs. @@ -1042,7 +977,7 @@ def pagerank( niter=1000, eps=0.001, ): - """Calculates the Google PageRank values of a graph. + """Calculates the PageRank values of a graph. @param vertices: the indices of the vertices being queried. C{None} means all of the vertices. @@ -1150,9 +1085,7 @@ def transitivity_avglocal_undirected(self, mode="nan", weights=None): return sum(xs) / float(len(xs)) def triad_census(self, *args, **kwds): - """triad_census() - - Calculates the triad census of the graph. + """Calculates the triad census of the graph. @return: a L{TriadCensus} object. @newfield ref: Reference @@ -1277,11 +1210,9 @@ def community_infomap(self, edge_weights=None, vertex_weights=None, trials=10): ) def community_leading_eigenvector_naive(self, clusters=None, return_merges=False): - """community_leading_eigenvector_naive(clusters=None, - return_merges=False) + """Naive implementation of Newman's eigenvector community structure detection. - A naive implementation of Newman's eigenvector community structure - detection. This function splits the network into two components + This function splits the network into two components according to the leading eigenvector of the modularity matrix and then recursively takes the given number of steps by splitting the communities as individual networks. This is not the correct way, @@ -1315,6 +1246,7 @@ def community_leading_eigenvector( self, clusters=None, weights=None, arpack_options=None ): """Newman's leading eigenvector method for detecting community structure. + This is the proper implementation of the recursive, divisive algorithm: each split is done by maximizing the modularity regarding the original network. @@ -1347,10 +1279,9 @@ def community_leading_eigenvector( return VertexClustering(self, membership, modularity=q) def community_label_propagation(self, weights=None, initial=None, fixed=None): - """community_label_propagation(weights=None, initial=None, fixed=None) - - Finds the community structure of the graph according to the label + """Finds the community structure of the graph according to the label propagation method of Raghavan et al. + Initially, each vertex is assigned a different label. After that, each vertex chooses the dominant label in its neighbourhood in each iteration. Ties are broken randomly and the order in which the @@ -1490,38 +1421,34 @@ def community_edge_betweenness(self, clusters=None, directed=True, weights=None) ) def community_spinglass(self, *args, **kwds): - """community_spinglass(weights=None, spins=25, parupdate=False, - start_temp=1, stop_temp=0.01, cool_fact=0.99, update_rule="config", - gamma=1, implementation="orig", lambda_=1) - - Finds the community structure of the graph according to the + """Finds the community structure of the graph according to the spinglass community detection method of Reichardt & Bornholdt. - @keyword weights: edge weights to be used. Can be a sequence or + @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. - @keyword spins: integer, the number of spins to use. This is the + @param spins: integer, the number of spins to use. This is the upper limit for the number of communities. It is not a problem to supply a (reasonably) big number here, in which case some spin states will be unpopulated. - @keyword parupdate: whether to update the spins of the vertices in + @param parupdate: whether to update the spins of the vertices in parallel (synchronously) or not - @keyword start_temp: the starting temperature - @keyword stop_temp: the stop temperature - @keyword cool_fact: cooling factor for the simulated annealing - @keyword update_rule: specifies the null model of the simulation. + @param start_temp: the starting temperature + @param stop_temp: the stop temperature + @param cool_fact: cooling factor for the simulated annealing + @param update_rule: specifies the null model of the simulation. Possible values are C{"config"} (a random graph with the same vertex degrees as the input graph) or C{"simple"} (a random graph with the same number of edges) - @keyword gamma: the gamma argument of the algorithm, specifying the + @param gamma: the gamma argument of the algorithm, specifying the balance between the importance of present and missing edges within a community. The default value of 1.0 assigns equal importance to both of them. - @keyword implementation: currently igraph contains two implementations + @param implementation: currently igraph contains two implementations of the spinglass community detection algorithm. The faster original implementation is the default. The other implementation is able to take into account negative weights, this can be chosen by setting C{implementation} to C{"neg"} - @keyword lambda_: the lambda argument of the algorithm, which + @param lambda_: the lambda argument of the algorithm, which specifies the balance between the importance of present and missing negatively weighted edges within a community. Smaller values of lambda lead to communities with less negative intra-connectivity. @@ -1834,9 +1761,7 @@ def layout_auto(self, *args, **kwds): return self.layout(algo, *args, **kwds) def layout_grid_fruchterman_reingold(self, *args, **kwds): - """layout_grid_fruchterman_reingold(*args, **kwds) - - Compatibility alias to the Fruchterman-Reingold layout with the grid + """Compatibility alias to the Fruchterman-Reingold layout with the grid option turned on. @see: Graph.layout_fruchterman_reingold() @@ -2245,9 +2170,7 @@ def write_graphmlz(self, f, compresslevel=9): @classmethod def Read_DIMACS(cls, f, directed=False): - """Read_DIMACS(f, directed=False) - - Reads a graph from a file conforming to the DIMACS minimum-cost flow + """Reads a graph from a file conforming to the DIMACS minimum-cost flow file format. For the exact definition of the format, see @@ -2278,9 +2201,7 @@ def Read_DIMACS(cls, f, directed=False): @classmethod def Read_GraphMLz(cls, f, directed=True, index=0): - """Read_GraphMLz(f, directed=True, index=0) - - Reads a graph from a zipped GraphML file. + """Reads a graph from a zipped GraphML file. @param f: the name of the file @param index: if the GraphML file contains multiple graphs, @@ -3375,9 +3296,7 @@ def Incidence( @classmethod def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): - """DataFrame(edges, directed=True, vertices=None) - - Generates a graph from one or two dataframes. + """Generates a graph from one or two dataframes. @param edges: pandas DataFrame containing edges and metadata. The first two columns of this DataFrame contain the source and target vertices @@ -3640,9 +3559,7 @@ def bipartite_projection( return superclass_meth(types, False, probe1, which) def bipartite_projection_size(self, types="type", *args, **kwds): - """bipartite_projection(types="type") - - Calculates the number of vertices and edges in the bipartite + """Calculates the number of vertices and edges in the bipartite projections of this graph according to the specified vertex types. This is useful if you have a bipartite graph and you want to estimate the amount of memory you would need to calculate the projections @@ -4191,9 +4108,7 @@ def summary(self, verbosity=0, width=None, *args, **kwds): return str(GraphSummary(self, verbosity, width, *args, **kwds)) def disjoint_union(self, other): - """disjoint_union(self, other) - - Creates the disjoint union of two (or more) graphs. + """Creates the disjoint union of two (or more) graphs. @param other: graph or list of graphs to be united with the current one. @return: the disjoint union graph @@ -4203,9 +4118,7 @@ def disjoint_union(self, other): return disjoint_union([self] + other) def union(self, other, byname="auto"): - """union(self, other, byname="auto") - - Creates the union of two (or more) graphs. + """Creates the union of two (or more) graphs. @param other: graph or list of graphs to be united with the current one. @param byname: whether to use vertex names instead of ids. See @@ -4217,9 +4130,7 @@ def union(self, other, byname="auto"): return union([self] + other, byname=byname) def intersection(self, other, byname="auto"): - """intersection(self, other, byname="auto") - - Creates the intersection of two (or more) graphs. + """Creates the intersection of two (or more) graphs. @param other: graph or list of graphs to be intersected with the current one. From 450df181ae1d9f911f78f0e583b22af65bbb451c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 10:47:59 +0100 Subject: [PATCH 0421/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 6bb4e76c1..5414f567e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 6bb4e76c1d0f971363034e23d06b238a423315cf +Subproject commit 5414f567e45564eace90882ba292306b0fa5a117 From 876763809d3dab4c0143338de4aab8ef40ad5bcc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 11:05:07 +0100 Subject: [PATCH 0422/1892] build: GH actions should clone submodules with a larger depth --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db8c52171..42d29fff1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Init C core submodule - run: git submodule update --init + run: git submodule update --init --depth 1000 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From 23053853c7f1a2e728b67988a04859ef7e9569df Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 13:19:28 +0100 Subject: [PATCH 0423/1892] build: try to forcibly unshallow the vendored igraph repo in CI --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42d29fff1..3938dec11 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Init C core submodule - run: git submodule update --init --depth 1000 + run: git submodule update --init && cd vendor/source/igraph && git --unshallow - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From b8837522704bb0508a6800b45a08f25095d2d4d9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 13:24:35 +0100 Subject: [PATCH 0424/1892] build: add missing git command to unshallowing --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3938dec11..e5a4dcec9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Init C core submodule - run: git submodule update --init && cd vendor/source/igraph && git --unshallow + run: git submodule update --init && cd vendor/source/igraph && git fetch --unshallow - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From 555ee9109df2213f1aec42c26efd9bb88d622142 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 14:10:22 +0100 Subject: [PATCH 0425/1892] build: apparently the submodule is already unshallowed --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5a4dcec9..db8c52171 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Init C core submodule - run: git submodule update --init && cd vendor/source/igraph && git fetch --unshallow + run: git submodule update --init - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From 13e0436b5b5dd142bc9b27430da2e2308c94faaa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 14:28:38 +0100 Subject: [PATCH 0426/1892] fix: deprecated calling plot() without a target argument --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ src/igraph/configuration.py | 8 +++++++- src/igraph/drawing/__init__.py | 25 ++++++++++++++++++------- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55496ca79..ed42ab4a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # igraph Python interface changelog +## [0.9.1] + +### Changed + +* Calling `plot()` without a filename or a target surface is now deprecated. + The original intention was to plot to a temporary file and then open it in + the default image viewer of the platform of the user automatically, but this + has never worked reliably. The feature will be removed in 0.10.0. + +### Fixed + +* Fixed plotting of `VertexClustering` objects on Matplotlib axes. + +* The `IGRAPH_CMAKE_EXTRA_ARGS` environment variable is now applied _after_ the + default CMake arguments when building the C core of igraph from source. This + enables package maintainers to override any of the default arguments we pass + to CMake. + +* Fixed the documentation build by replacing Epydoc with PyDoctor. + +### Miscellaneous + +* Many old code constructs that were used to maintain compatibility with Python + 2.x are removed now that we have dropped support for Python 2.x. + + ## [0.9.0] ### Added @@ -56,6 +82,7 @@ * The core C library is now built with `-fPIC` on Linux to allow linking to the Python interface. + ## 0.8.3 This is the last released version of `python-igraph` without a changelog file. diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 1c507c4f1..f39a6cdd3 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -40,7 +40,13 @@ def get_platform_image_viewer(): - """Returns the path of an image viewer on the given platform""" + """Returns the path of an image viewer on the given platform. + + Deprecated since python-igraph 0.9.1 and will be removed in 0.10.0. + + @deprecated: This function was only used by the now-deprecated C{show()} + method of the Plot class. + """ plat = platform.system() if plat == "Darwin": # Most likely Mac OS X diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 364eef307..74cf7bdc4 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -318,7 +318,16 @@ def save(self, fname=None): self._surface.finish() def show(self): - """Saves the plot to a temporary file and shows it.""" + """Saves the plot to a temporary file and shows it. + + This method is deprecated from python-igraph 0.9.1 and will be removed in + 0.10.0. + + @deprecated: Opening an image viewer with a temporary file never worked + reliably across platforms. + """ + warn("Plot.show() is deprecated from python-igraph 0.9.1", DeprecationWarning) + if not isinstance(self._surface, cairo.ImageSurface): sur = cairo.ImageSurface( cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) @@ -340,7 +349,7 @@ def show(self): # should only happen on unknown platforms. plat = platform.system() raise NotImplementedError( - "showing plots is not implemented " + "on this platform: %s" % plat + "showing plots is not implemented on this platform: %s" % plat ) else: os.system("%s %s" % (imgviewer, tmpfile)) @@ -415,16 +424,18 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @param target: the target where the object should be plotted. It can be one of the following types: - - C{None} -- an appropriate surface will be created and the object will - be plotted there. + - C{string} -- a file with the given name will be created and an + appropriate Cairo surface will be attached to it. The supported image + formats are: PNG, PDF, SVG and PostScript. - C{cairo.Surface} -- the given Cairo surface will be used. This can refer to a PNG image, an arbitrary window, an SVG file, anything that Cairo can handle. - - C{string} -- a file with the given name will be created and an - appropriate Cairo surface will be attached to it. The supported image - formats are: PNG, PDF, SVG and PostScript. + - C{None} -- a temporary file will be created and the object will be + plotted there. igraph will attempt to open an image viewer and show + the temporary file. This feature is deprecated from python-igraph + version 0.9.1 and will be removed in 0.10.0. @param bbox: the bounding box of the plot. It must be a tuple with either two or four integers, or a L{BoundingBox} object. If this is a tuple From 2df5a5800a723c274393708a0565cd6190a64ca4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 14:39:41 +0100 Subject: [PATCH 0427/1892] build: try with a different igraph revision --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 5414f567e..02fd620c4 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 5414f567e45564eace90882ba292306b0fa5a117 +Subproject commit 02fd620c4d419dae3f76c7b79fdfd1cde8a0e007 From f4ddb0086c66324f0e3ea93c16aa2d5d0c355634 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 14:51:53 +0100 Subject: [PATCH 0428/1892] fix: include generated parser sources in Python tarball so we don't need flex and bison when building the wheels --- setup.py | 78 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/setup.py b/setup.py index 88bd0d577..b78b6740a 100644 --- a/setup.py +++ b/setup.py @@ -427,23 +427,71 @@ def sdist(self): """ from setuptools.command.sdist import sdist + def is_git_repo(folder): + return os.path.exists(os.path.join(folder, ".git")) + + def cleanup_git_repo(folder): + folder = str(folder) + cwd = os.getcwd() + try: + os.chdir(folder) + if os.path.exists(".git"): + retcode = subprocess.call("git clean -dfx", shell=True) + if retcode: + raise RuntimeError(f"Failed to clean {folder} with git") + finally: + os.chdir(cwd) + class custom_sdist(sdist): def run(self): - # Clean up vendor/source/igraph with git - cwd = os.getcwd() - try: - os.chdir(os.path.join("vendor", "source", "igraph")) - if os.path.exists(".git"): - retcode = subprocess.call("git clean -dfx", shell=True) - if retcode: - print("Failed to clean vendor/source/igraph with git") - print("") - return False - finally: - os.chdir(cwd) - - # Run the original sdist command - sdist.run(self) + igraph_source_repo = os.path.join("vendor", "source", "igraph") + igraph_build_dir = os.path.join("vendor", "build", "igraph") + version_file = os.path.join(igraph_source_repo, "IGRAPH_VERSION") + version = None + + # Check whether the source repo contains an IGRAPH_VERSION file + if not os.path.exists(version_file): + version_header = os.path.join(igraph_build_dir, "include", "igraph_version.h") + if not os.path.exists(version_header): + raise RuntimeError("You need to build the C core of igraph first before generating a source tarball of python-igraph") + + with open(version_header, "r") as fp: + lines = [line.strip() for line in fp if line.startswith("#define IGRAPH_VERSION ")] + if len(lines) == 1: + version = lines[0].split('"')[1] + + else: + with open(version_file, "r") as fp: + version = fp.read().strip().split("\n")[0] + + if not isinstance(version, str) or len(version) < 5: + raise RuntimeError(f"Cannot determine the version number of the C core in {igraph_source_repo}") + + if not is_git_repo(igraph_source_repo): + # python-igraph was extracted from an official tarball so + # there is no need to tweak anything + return sdist.run(self) + else: + # Clean up vendor/source/igraph with git + cleanup_git_repo(igraph_source_repo) + + # Copy the generated parser sources from the build folder + parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") + if not os.path.isdir(parser_dir): + raise RuntimeError(f"You need to build the C core of igraph first before generating a source tarball of python-igraph") + shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) + + # Add a version file to the tarball + with open(version_file, "w") as fp: + fp.write(version) + + # Run the original sdist command + retval = sdist.run(self) + + # Clean up vendor/source/igraph with git again + cleanup_git_repo(igraph_source_repo) + + return retval return custom_sdist From b1163a9bd3d809c867efe42e5b743cd2dc9a58d4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 15:06:23 +0100 Subject: [PATCH 0429/1892] fix: updated gitignore to ignore any .so files in src/igraph [ci skip] --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 06705accc..a285acca8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ build/ dist/ doc/api/ -igraph/*.so +src/igraph/*.so *.egg-info/ .python-version .eggs/ From 663ca4dc5343bd9faede1fa9fdd6fc740328f8ff Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 15:08:59 +0100 Subject: [PATCH 0430/1892] chore: updated CHANGELOG [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed42ab4a1..d15b63b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ ### Miscellaneous +* Building `python-igraph` from source should not require `flex` and `bison` + any more; sources of the parsers used by the C core are now included in the + Python source tarball. + * Many old code constructs that were used to maintain compatibility with Python 2.x are removed now that we have dropped support for Python 2.x. From 56ffbbb03a83cd7b77fb1dd6fc886bdef7544483 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 15:18:20 +0100 Subject: [PATCH 0431/1892] build: trying to debug CI failure --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db8c52171..372bf4445 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,10 @@ jobs: steps: - uses: actions/checkout@v1 - name: Init C core submodule - run: git submodule update --init + run: | + git submodule update --init + cat vendor/source/igraph/.git + cat .git/modules/vendor/source/igraph/HEAD - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: From 0c51f01e2a3f34f1bb05327021d8b0de59897b84 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 15:34:30 +0100 Subject: [PATCH 0432/1892] build: use git describe to determine version number from vendor/source/igraph --- setup.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index b78b6740a..2110dadc4 100644 --- a/setup.py +++ b/setup.py @@ -449,8 +449,25 @@ def run(self): version_file = os.path.join(igraph_source_repo, "IGRAPH_VERSION") version = None - # Check whether the source repo contains an IGRAPH_VERSION file - if not os.path.exists(version_file): + # Check whether the source repo contains an IGRAPH_VERSION file, + # and extract the version number from that + if os.path.exists(version_file): + with open(version_file, "r") as fp: + version = fp.read().strip().split("\n")[0] + + # If no IGRAPH_VERSION file exists, but we have a git repo, try + # git describe + if not version and is_git_repo(igraph_source_repo): + cwd = os.getcwd() + try: + os.chdir(igraph_source_repo) + version = subprocess.check_output("git describe", shell=True).decode("utf-8").strip() + finally: + os.chdir(cwd) + + # If we still don't have a version number, try to parse it from + # include/igraph_version.h + if not version: version_header = os.path.join(igraph_build_dir, "include", "igraph_version.h") if not os.path.exists(version_header): raise RuntimeError("You need to build the C core of igraph first before generating a source tarball of python-igraph") @@ -460,10 +477,6 @@ def run(self): if len(lines) == 1: version = lines[0].split('"')[1] - else: - with open(version_file, "r") as fp: - version = fp.read().strip().split("\n")[0] - if not isinstance(version, str) or len(version) < 5: raise RuntimeError(f"Cannot determine the version number of the C core in {igraph_source_repo}") From daba48d71f0825e3c3fc6de0ea13c56f0275da4e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 15:51:54 +0100 Subject: [PATCH 0433/1892] ci: allow setup.py to generate the parsers when running in tox --- setup.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 2110dadc4..bcc104dfe 100644 --- a/setup.py +++ b/setup.py @@ -490,9 +490,14 @@ def run(self): # Copy the generated parser sources from the build folder parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") - if not os.path.isdir(parser_dir): + if os.path.isdir(parser_dir): + shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) + elif os.environ.get("TESTING_IN_TOX"): + # we allow to proceed when running in tox in the CI environment; + # bison and flex will be used to generate the parsers + pass + else: raise RuntimeError(f"You need to build the C core of igraph first before generating a source tarball of python-igraph") - shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) # Add a version file to the tarball with open(version_file, "w") as fp: From 9b4185d98e38cfabe4216fd1989bb3fd40306f04 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 16:04:28 +0100 Subject: [PATCH 0434/1892] ci: we now install all deps with Python 3.9 as well --- tox.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tox.ini b/tox.ini index 212abe28b..73f8166ec 100644 --- a/tox.ini +++ b/tox.ini @@ -24,12 +24,6 @@ deps = setenv = TESTING_IN_TOX=1 -[testenv:py39] -# py39 support is still sparse; most of the optional dependencies have no -# wheels for Python 3.9 yet so we install only those where they do -deps = - networkx - [flake8] max-line-length = 80 select = C,E,F,W,B,B950 From dea92d46285af68429ee4278a8d934e734eb5830 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 16:04:52 +0100 Subject: [PATCH 0435/1892] ci: set TESTING_IN_TOX envvar also when building the sdist --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 372bf4445..b84ae4a72 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,4 +78,6 @@ jobs: pip install tox tox-gh-actions - name: Test with tox run: tox + env: + TESTING_IN_TOX: 1 From 849490bbc475e5391ab02e7303323a13aa75d0af Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 16:12:29 +0100 Subject: [PATCH 0436/1892] ci set TESTING_IN_TOX for both macOS and Linux jobs --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b84ae4a72..a2c207e6d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,6 +50,8 @@ jobs: pip install tox tox-gh-actions - name: Test with tox run: tox + env: + TESTING_IN_TOX: 1 build_osx: runs-on: macos-latest From a2a2ee529521c7e30253efd9aa8b3643005e1120 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 17:25:31 +0100 Subject: [PATCH 0437/1892] doc: fix docstring of two tests --- tests/test_cliques.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/test_cliques.py b/tests/test_cliques.py index f972fd715..70a958376 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -163,10 +163,8 @@ def setUp(self): self.g = Graph.Erdos_Renyi(100, 0.2, directed=True) def testDyads(self): - """ - @note: this test is not exhaustive, it only checks whether the - L{DyadCensus} objects "understand" attribute and item accessors - """ + # @note: this test is not exhaustive, it only checks whether the + # L{DyadCensus} objects "understand" attribute and item accessors dc = self.g.dyad_census() accessors = ["mut", "mutual", "asym", "asymm", "asymmetric", "null"] for a in accessors: @@ -178,10 +176,8 @@ def testDyads(self): self.assertTrue(len(tuple(dc)) == 3) def testTriads(self): - """ - @note: this test is not exhaustive, it only checks whether the - L{TriadCensus} objects "understand" attribute and item accessors - """ + # @note: this test is not exhaustive, it only checks whether the + # L{TriadCensus} objects "understand" attribute and item accessors tc = self.g.triad_census() accessors = ["003", "012", "021d", "030C"] for a in accessors: From ddc53b66c03cdf0ced19836addfa81fc045c1aab Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 17:26:06 +0100 Subject: [PATCH 0438/1892] fix: fix tests for SciPy sparse adjacency matrix constructor --- src/igraph/__init__.py | 9 +- src/igraph/drawing/graph.py | 1 + src/igraph/sparse_matrix.py | 180 ++++++++++++++++++++++-------------- tests/test_generators.py | 24 ++++- 4 files changed, 137 insertions(+), 77 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 8a9367561..9dc0792d2 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2157,7 +2157,7 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): return super().Adjacency(matrix, mode=mode) @classmethod - def WeightedAdjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True): + def Weighted_Adjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True): """Generates a graph from its weighted adjacency matrix. @param matrix: the adjacency matrix. Possible types are: @@ -2196,18 +2196,19 @@ def WeightedAdjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=Tru except ImportError: sparse = None - if (sparse is not None) and isinstance(matrix, sparse.spmatrix): + if sparse is not None and isinstance(matrix, sparse.spmatrix): return _graph_from_weighted_sparse_matrix( klass, matrix, mode=mode, attr=attr, + loops=loops, ) - if (np is not None) and isinstance(matrix, np.ndarray): + if np is not None and isinstance(matrix, np.ndarray): matrix = matrix.tolist() - return super().WeightedAdjacency( + return super().Weighted_Adjacency( matrix, mode=mode, attr=attr, diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 49d580646..d46b45538 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -984,6 +984,7 @@ def draw(self, graph, *args, **kwds): from matplotlib.patches import FancyArrowPatch from matplotlib.patches import ArrowStyle import numpy as np + # Deferred import to avoid a cycle in the import graph from igraph.clustering import VertexClustering, VertexCover diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index 4d1d8e1d2..132d68bc4 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -37,81 +37,109 @@ ) +_SUPPORTED_MODES = ("directed", "undirected", "max", "min", "plus", "lower", "upper") + + +def _convert_mode_argument(mode): + # resolve mode constants, convert to lowercase + mode = ( + { + ADJ_DIRECTED: "directed", + ADJ_UNDIRECTED: "undirected", + ADJ_MAX: "max", + ADJ_MIN: "min", + ADJ_PLUS: "plus", + ADJ_UPPER: "upper", + ADJ_LOWER: "lower", + } + .get(mode, mode) + .lower() + ) + + if mode not in _SUPPORTED_MODES: + raise ValueError("mode should be one of " + (" ".join(_SUPPORTED_MODES))) + + if mode == "undirected": + mode = "max" + + return mode + + # Logic to get graph from scipy sparse matrix. This would be simple if there # weren't so many modes. -def _graph_from_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED): +def _graph_from_sparse_matrix(klass, matrix, mode="directed"): """Construct graph from sparse matrix, unweighted""" # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. from scipy import sparse - modes = ( - ADJ_DIRECTED, - ADJ_UNDIRECTED, - ADJ_MAX, - ADJ_MIN, - ADJ_PLUS, - ADJ_UPPER, - ADJ_LOWER, - ) - if not isinstance(matrix, sparse.coo_matrix): matrix = matrix.tocoo() + nvert = max(matrix.shape) + if min(matrix.shape) != nvert: + raise ValueError("Matrix must be square") + # Shorthand notation m = matrix - if mode == ADJ_UNDIRECTED: - mode = ADJ_MAX + mode = _convert_mode_argument(mode) - if mode == ADJ_DIRECTED: + if mode == "directed": edges = sum( ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data)), [], ) - elif mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): - fun_dict = { - ADJ_MAX: max, - ADJ_MIN: min, - ADJ_PLUS: add, - } - fun = fun_dict[mode] + elif mode in ("max", "plus"): + fun = max if mode == "max" else add nedges = {} for i, j, n in zip(m.row, m.col, m.data): - # Fist time this pair of vertices - if (j, i) not in nedges: - nedges[(i, j)] = n - else: - nedges[(j, i)] = fun(nedges[(j, i)], n) + pair = (i, j) if i < j else (j, i) + nedges[pair] = fun(nedges.get(pair, 0), n) + + edges = sum( + ([e] * n for e, n in nedges.items()), + [], + ) + + elif mode == "min": + tmp = {(i, j): n for i, j, n in zip(m.row, m.col, m.data)} + + nedges = {} + for pair, weight in tmp.items(): + i, j = pair + if i == j: + nedges[pair] = weight + elif i < j: + nedges[pair] = min(weight, tmp.get((j, i), 0)) edges = sum( ([e] * n for e, n in nedges.items()), [], ) - elif mode == ADJ_UPPER: + elif mode == "upper": edges = sum( ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j >= i), [], ) - elif mode == ADJ_LOWER: + elif mode == "lower": edges = sum( ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j <= i), [], ) else: - raise ValueError("mode should be one of " + " ".join(map(str, modes))) + raise ValueError("invalid mode") - return klass( - edges=edges, - directed=mode == ADJ_DIRECTED, - ) + return klass(nvert, edges=edges, directed=(mode == "directed")) -def _graph_from_weighted_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED, attr="weight"): +def _graph_from_weighted_sparse_matrix( + klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True +): """Construct graph from sparse matrix, weighted NOTE: Of course, you cannot emcompass a fully general weighted multigraph @@ -121,65 +149,75 @@ def _graph_from_weighted_sparse_matrix(klass, matrix, mode=ADJ_DIRECTED, attr="w # matrix. The caller should make sure those conditions are met. from scipy import sparse - modes = ( - ADJ_DIRECTED, - ADJ_UNDIRECTED, - ADJ_MAX, - ADJ_MIN, - ADJ_PLUS, - ADJ_UPPER, - ADJ_LOWER, - ) - if not isinstance(matrix, sparse.coo_matrix): matrix = matrix.tocoo() + nvert = max(matrix.shape) + if min(matrix.shape) != nvert: + raise ValueError("Matrix must be square") + # Shorthand notation m = matrix - if mode == ADJ_UNDIRECTED: - mode = ADJ_MAX - - if mode == ADJ_DIRECTED: - edges = list(zip(m.row, m.col)) - weights = list(m.data) - - elif mode in (ADJ_MAX, ADJ_MIN, ADJ_PLUS): - fun_dict = { - ADJ_MAX: max, - ADJ_MIN: min, - ADJ_PLUS: add, - } - fun = fun_dict[mode] + mode = _convert_mode_argument(mode) + + if mode == "directed": + if not loops: + edges, weights = [], [] + for i, j, n in zip(m.row, m.col, m.data): + if i != j: + edges.append((i, j)) + weights.append(n) + else: + edges = list(zip(m.row, m.col)) + weights = list(m.data) + + elif mode in ("max", "plus"): + fun = max if mode == "max" else add nedges = {} for i, j, n in zip(m.row, m.col, m.data): - # Fist time this pair of vertices - if (j, i) not in nedges: - nedges[(i, j)] = n - else: - nedges[(j, i)] = fun(nedges[(j, i)], n) + if i == j and not loops: + continue + pair = (i, j) if i < j else (j, i) + nedges[pair] = fun(nedges.get(pair, 0), n) edges, weights = zip(*nedges.items()) - elif mode == ADJ_UPPER: + elif mode == "min": + tmp = {(i, j): n for i, j, n in zip(m.row, m.col, m.data)} + + nedges = {} + for pair, weight in tmp.items(): + i, j = pair + if i == j and loops: + nedges[pair] = weight + elif i < j: + nedges[pair] = min(weight, tmp.get((j, i), 0)) + + edges, weights = [], [] + for pair in sorted(nedges.keys()): + weight = nedges[pair] + if weight != 0: + edges.append(pair) + weights.append(nedges[pair]) + + elif mode == "upper": edges, weights = [], [] for i, j, n in zip(m.row, m.col, m.data): - if j >= i: + if j > i or (loops and j == i): edges.append((i, j)) weights.append(n) - elif mode == ADJ_LOWER: + elif mode == "lower": edges, weights = [], [] for i, j, n in zip(m.row, m.col, m.data): - if j <= i: + if j < i or (loops and j == i): edges.append((i, j)) weights.append(n) else: - raise ValueError("mode should be one of " + " ".join(map(str, modes))) + raise ValueError("invalid mode") return klass( - edges=edges, - directed=mode == ADJ_DIRECTED, - edge_attrs={attr: weights}, + nvert, edges=edges, directed=(mode == "directed"), edge_attrs={attr: weights} ) diff --git a/tests/test_generators.py b/tests/test_generators.py index 1e296c3ee..6895cac0a 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -210,16 +210,22 @@ def testSparseAdjacency(self): # ADJ_DIRECTED (default) g = Graph.Adjacency(mat) el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (2, 2), (3, 1)]) # ADJ MIN g = Graph.Adjacency(mat, mode="min") el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (2, 2), (2, 2)]) # ADJ LOWER g = Graph.Adjacency(mat, mode="lower") el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (2, 2), (2, 2), (1, 3)]) def testWeightedAdjacency(self): @@ -271,16 +277,30 @@ def testSparseWeighedAdjacency(self): g = Graph.Weighted_Adjacency(mat, attr="w0") el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 2.5, 1]) g = Graph.Weighted_Adjacency(mat, mode="plus") el = g.get_edgelist() - self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2)]) - self.assertTrue(g.es["weight"] == [3, 2, 1, 2.5]) + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2), (1, 3)]) + self.assertTrue(g.es["weight"] == [3, 2, 2.5, 1]) + + g = Graph.Weighted_Adjacency(mat, mode="min") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + print(repr(el)) + self.assertTrue(el == [(0, 1), (2, 2)]) + self.assertTrue(g.es["weight"] == [1, 2.5]) g = Graph.Weighted_Adjacency(mat, attr="w0", loops=False) el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) From e8269f49563fed28b3ddea4af44b91f552517800 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Mar 2021 17:26:19 +0100 Subject: [PATCH 0439/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 02fd620c4..55b9cdca9 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 02fd620c4d419dae3f76c7b79fdfd1cde8a0e007 +Subproject commit 55b9cdca9aa47832f841aa1edaf9c13aa1d46a98 From a337298d31882629463590e2d1d9a6f8354d71c5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 12 Mar 2021 10:13:18 +0100 Subject: [PATCH 0440/1892] fix: re-export __igraph_version__ from igraph._igraph --- src/igraph/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 9dc0792d2..23d674b6d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -76,6 +76,7 @@ set_progress_handler, set_random_number_generator, set_status_handler, + __igraph_version__ ) from igraph.clustering import ( Clustering, From d90cd39110cde57d7ff642a6884d5c295f94b3ed Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 14:09:07 +0100 Subject: [PATCH 0441/1892] fix: remove PyInt_AsInt() from compatibility functions, it is now the same as PyLong_As_int() in Python 3.x --- src/_igraph/attributes.c | 2 +- src/_igraph/convert.c | 55 ++++---------------------------------- src/_igraph/convert.h | 1 - src/_igraph/graphobject.c | 2 +- src/_igraph/vertexobject.c | 4 +-- 5 files changed, 9 insertions(+), 55 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 8a8cf79a5..124b34ed5 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -155,7 +155,7 @@ int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_inte return 1; } - if (PyInt_AsInt(o_vid, &tmp)) + if (PyLong_AsInt(o_vid, &tmp)) return 1; *vid = tmp; diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index f92013947..0fcebcf46 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -39,30 +39,6 @@ #define strcasecmp _stricmp #endif -/** - * \brief Converts a Python integer to a C int - * - * This is similar to PyLong_AsLong, but it checks for overflow first and throws - * an exception if necessary. - * - * Returns -1 if there was an error, 0 otherwise. - */ -int PyInt_AsInt(PyObject* obj, int* result) { - long dummy = PyLong_AsLong(obj); - if (dummy < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "integer too small for conversion to C int"); - return -1; - } - if (dummy > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "integer too large for conversion to C int"); - return -1; - } - *result = (int)dummy; - return 0; -} - /** * \brief Converts a Python long to a C int * @@ -74,13 +50,11 @@ int PyInt_AsInt(PyObject* obj, int* result) { int PyLong_AsInt(PyObject* obj, int* result) { long dummy = PyLong_AsLong(obj); if (dummy < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "long integer too small for conversion to C int"); + PyErr_SetString(PyExc_OverflowError, "long integer too small for conversion to C int"); return -1; } if (dummy > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "long integer too large for conversion to C int"); + PyErr_SetString(PyExc_OverflowError, "long integer too large for conversion to C int"); return -1; } *result = (int)dummy; @@ -114,8 +88,6 @@ int igraphmodule_PyObject_to_enum(PyObject *o, if (o == 0 || o == Py_None) return 0; - if (PyLong_Check(o)) - return PyInt_AsInt(o, result); if (PyLong_Check(o)) return PyLong_AsInt(o, result); s = PyUnicode_CopyAsString(o); @@ -725,7 +697,7 @@ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { PyObject *i = PyNumber_Long(object); if (i == NULL) return 1; - retval = PyInt_AsInt(i, &num); + retval = PyLong_AsInt(i, &num); Py_DECREF(i); if (retval) return retval; @@ -1013,7 +985,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v PyErr_SetString(PyExc_TypeError, "can't convert a list item to integer"); ok = 0; } else { - ok = (PyInt_AsInt(item, &value) == 0); + ok = (PyLong_AsInt(item, &value) == 0); Py_DECREF(item2); } } @@ -1057,7 +1029,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v PyErr_SetString(PyExc_TypeError, "can't convert sequence element to int"); ok=0; } else { - retval = PyInt_AsInt(item2, &value); + retval = PyLong_AsInt(item2, &value); if (retval) ok = 0; Py_DECREF(item2); @@ -2387,11 +2359,6 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g if (o == Py_None || o == 0) { *vid = 0; - } else if (PyLong_Check(o)) { - /* Single vertex ID */ - if (PyInt_AsInt(o, &tmp)) - return 1; - *vid = tmp; } else if (PyLong_Check(o)) { /* Single vertex ID */ if (PyLong_AsInt(o, &tmp)) @@ -2410,13 +2377,6 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g PyObject* num = PyNumber_Index(o); if (num) { if (PyLong_Check(num)) { - retval = PyInt_AsInt(num, &tmp); - if (retval) { - Py_DECREF(num); - return 1; - } - *vid = tmp; - } else if (PyLong_Check(num)) { retval = PyLong_AsInt(num, &tmp); if (retval) { Py_DECREF(num); @@ -2599,11 +2559,6 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g if (o == Py_None || o == 0) { *eid = 0; - } else if (PyLong_Check(o)) { - /* Single edge ID */ - if (PyInt_AsInt(o, &tmp)) - return 1; - *eid = tmp; } else if (PyLong_Check(o)) { /* Single edge ID */ if (PyLong_AsInt(o, &tmp)) diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index d777406d4..8834420cf 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -41,7 +41,6 @@ typedef struct { int value; } igraphmodule_enum_translation_table_entry_t; -int PyInt_AsInt(PyObject* obj, int* result); int PyLong_AsInt(PyObject* obj, int* result); /* Conversion from PyObject to enum types */ diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index fca586393..0ced8a25f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4962,7 +4962,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (PyInt_AsInt(cutoff_o, &cutoff)) + if (PyLong_AsInt(cutoff_o, &cutoff)) return NULL; if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 9d8f485e4..287ecba0e 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -616,7 +616,7 @@ static PyObject* _convert_to_edge_list(igraphmodule_VertexObject* vertex, PyObje return NULL; } - if (PyInt_AsInt(idx, &idx_int)) + if (PyLong_AsInt(idx, &idx_int)) return NULL; v = igraphmodule_Edge_New(vertex->gref, idx_int); @@ -648,7 +648,7 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb return NULL; } - if (PyInt_AsInt(idx, &idx_int)) + if (PyLong_AsInt(idx, &idx_int)) return NULL; v = igraphmodule_Vertex_New(vertex->gref, idx_int); From 26a8bb5e07f6e8d55cd6742ec8a3eb5e6a38950e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 14:10:13 +0100 Subject: [PATCH 0442/1892] fix: removed one more occurrence of PyInt_As_int --- src/_igraph/convert.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 0fcebcf46..cac8132e5 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2573,13 +2573,6 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g PyObject* num = PyNumber_Index(o); if (num) { if (PyLong_Check(num)) { - retval = PyInt_AsInt(num, &tmp); - if (retval) { - Py_DECREF(num); - return 1; - } - *eid = tmp; - } else if (PyLong_Check(num)) { retval = PyLong_AsInt(num, &tmp); if (retval) { Py_DECREF(num); From 6c20f7c7791a8d59a1722b41125a6fae22f0ac4b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 14:34:57 +0100 Subject: [PATCH 0443/1892] fix: updated to igraph 0.9.1, fixed a bug in the handling of the finally stack when converting Python integer tuples to edge sequences --- src/_igraph/convert.c | 103 ++++++++++++++++++++++++++++++------------ tests/test_basic.py | 4 ++ vendor/source/igraph | 2 +- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index cac8132e5..010f83877 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -842,7 +842,11 @@ int igraphmodule_PyObject_to_vector_t(PyObject *list, igraph_vector_t *v, igraph igraph_vector_destroy(v); return 1; } - igraph_vector_push_back(v, number); + if (igraph_vector_push_back(v, number)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(v); + return 1; + } } } @@ -1985,11 +1989,11 @@ PyObject* igraphmodule_matrix_t_to_PyList(const igraph_matrix_t *m, for (j=0; jvs)) { igraphmodule_handle_igraph_error(); return 1; } - if (return_single) + + if (return_single) { *return_single = 0; + } + return 0; } @@ -2458,21 +2466,27 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, if (start == 0 && slicelength == no_of_vertices) { igraph_vs_all(vs); } else { - IGRAPH_CHECK(igraph_vector_init(&vector, slicelength)); - IGRAPH_FINALLY(igraph_vector_destroy, &vector); + if (igraph_vector_init(&vector, slicelength)) { + igraphmodule_handle_igraph_error(); + return 1; + } for (i = 0; i < slicelength; i++, start += step) { VECTOR(vector)[i] = start; } - IGRAPH_CHECK(igraph_vs_vector_copy(vs, &vector)); + if (igraph_vs_vector_copy(vs, &vector)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&vector); + return 1; + } igraph_vector_destroy(&vector); - IGRAPH_FINALLY_CLEAN(1); } - if (return_single) + if (return_single) { *return_single = 0; + } return 0; } @@ -2500,9 +2514,10 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, return 1; } - IGRAPH_CHECK(igraph_vector_init(&vector, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &vector); - IGRAPH_CHECK(igraph_vector_reserve(&vector, 20)); + if (igraph_vector_init(&vector, 0)) { + igraphmodule_handle_igraph_error(); + return 1; + } while ((item = PyIter_Next(iterator))) { vid = -1; @@ -2511,22 +2526,31 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, break; Py_DECREF(item); - igraph_vector_push_back(&vector, vid); + + if (igraph_vector_push_back(&vector, vid)) { + igraphmodule_handle_igraph_error(); + /* no need to destroy 'vector' here; will be done outside the loop due + * to PyErr_Occurred */ + break; + } } + Py_DECREF(iterator); if (PyErr_Occurred()) { igraph_vector_destroy(&vector); - IGRAPH_FINALLY_CLEAN(1); return 1; } - IGRAPH_CHECK(igraph_vs_vector_copy(vs, &vector)); - igraph_vector_destroy(&vector); - IGRAPH_FINALLY_CLEAN(1); + if (igraph_vs_vector_copy(vs, &vector)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&vector); + return 1; + } - if (return_single) + if (return_single) { *return_single = 0; + } return 0; } @@ -2603,7 +2627,16 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g if (igraphmodule_PyObject_to_vid(o2, &vid2, graph)) return 1; - igraph_get_eid(graph, eid, vid1, vid2, 1, 0); + retval = igraph_get_eid(graph, eid, vid1, vid2, 1, 0); + if (retval == IGRAPH_EINVVID) { + PyErr_Format(PyExc_ValueError, "no edge from vertex #%ld to #%ld; no such vertex ID", + (long int)vid1, (long int)vid2); + return 1; + } else if (retval) { + igraphmodule_handle_igraph_error(); + return 1; + } + if (*eid < 0) { PyErr_Format(PyExc_ValueError, "no edge from vertex #%ld to #%ld", (long int)vid1, (long int)vid2); @@ -2679,24 +2712,32 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, return 1; } - IGRAPH_CHECK(igraph_vector_init(&vector, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &vector); - IGRAPH_CHECK(igraph_vector_reserve(&vector, 20)); + if (igraph_vector_init(&vector, 0)) { + igraphmodule_handle_igraph_error(); + return 1; + } while ((item = PyIter_Next(iterator))) { eid = -1; - if (igraphmodule_PyObject_to_eid(item, &eid, graph)) + if (igraphmodule_PyObject_to_eid(item, &eid, graph)) { break; + } Py_DECREF(item); - igraph_vector_push_back(&vector, eid); + + if (igraph_vector_push_back(&vector, eid)) { + igraphmodule_handle_igraph_error(); + /* no need to destroy 'vector' here; will be done outside the loop due + * to PyErr_Occurred */ + break; + } } + Py_DECREF(iterator); if (PyErr_Occurred()) { igraph_vector_destroy(&vector); - IGRAPH_FINALLY_CLEAN(1); return 1; } @@ -2707,17 +2748,19 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, } igraph_vector_destroy(&vector); - IGRAPH_FINALLY_CLEAN(1); - if (return_single) + if (return_single) { *return_single = 0; + } return 0; } /* The object can be converted into a single edge ID */ - if (return_single) + if (return_single) { *return_single = 1; + } + /* if (single_eid) *single_eid = eid; diff --git a/tests/test_basic.py b/tests/test_basic.py index 28bca91e9..f7eb08e28 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -287,11 +287,15 @@ def testDeleteEdges(self): self.assertEqual(3, g.ecount()) self.assertEqual(el, g.get_edgelist()) + print("GGGG") + # Deleting nonexistent edges self.assertRaises(ValueError, g.delete_edges, [(0, 2)]) self.assertRaises(ValueError, g.delete_edges, [("A", "C")]) self.assertRaises(ValueError, g.delete_edges, [(0, 15)]) + print("HHHH") + # Delete all edges g.delete_edges() self.assertEqual(0, g.ecount()) diff --git a/vendor/source/igraph b/vendor/source/igraph index 55b9cdca9..213abc889 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 55b9cdca9aa47832f841aa1edaf9c13aa1d46a98 +Subproject commit 213abc889d360775dfd0c11a406e859827c6dec8 From a02662e69d6ef4fe5a00e284a8acbe81b042bb1c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 14:35:58 +0100 Subject: [PATCH 0444/1892] fix: remove unneeded print() statements from tests --- tests/test_basic.py | 4 ---- tests/test_generators.py | 1 - 2 files changed, 5 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index f7eb08e28..28bca91e9 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -287,15 +287,11 @@ def testDeleteEdges(self): self.assertEqual(3, g.ecount()) self.assertEqual(el, g.get_edgelist()) - print("GGGG") - # Deleting nonexistent edges self.assertRaises(ValueError, g.delete_edges, [(0, 2)]) self.assertRaises(ValueError, g.delete_edges, [("A", "C")]) self.assertRaises(ValueError, g.delete_edges, [(0, 15)]) - print("HHHH") - # Delete all edges g.delete_edges() self.assertEqual(0, g.ecount()) diff --git a/tests/test_generators.py b/tests/test_generators.py index 6895cac0a..1d566b54e 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -293,7 +293,6 @@ def testSparseWeighedAdjacency(self): el = g.get_edgelist() self.assertFalse(g.is_directed()) self.assertEqual(4, g.vcount()) - print(repr(el)) self.assertTrue(el == [(0, 1), (2, 2)]) self.assertTrue(g.es["weight"] == [1, 2.5]) From 167c1bb7f1275e28a25b687cb8fd8214ce587c94 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 14:44:02 +0100 Subject: [PATCH 0445/1892] fix: fix deprecation warnings when compiling the Python interface --- src/_igraph/attributes.c | 10 ++++------ src/_igraph/igraphmodule.c | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 124b34ed5..191b9124b 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1840,16 +1840,14 @@ void igraphmodule_initialize_attribute_handler(void) { * Also raises a suitable Python exception if needed. */ int igraphmodule_attribute_name_check(PyObject* obj) { - PyObject* type_str; + PyObject* type_obj; if (obj != 0 && PyBaseString_Check(obj)) return 1; - type_str = obj ? PyObject_Str((PyObject*)obj->ob_type) : 0; - if (type_str != 0) { - PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only, got %s", - PyUnicode_AS_UNICODE(type_str)); - Py_DECREF(type_str); + type_obj = obj ? ((PyObject*)obj->ob_type) : 0; + if (type_obj != 0) { + PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only, got %R", type_obj); } else { PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only"); } diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 856d4bf7a..ea3661c3f 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -430,7 +430,7 @@ PyObject* igraphmodule_is_degree_sequence(PyObject *self, return NULL; } - if (igraph_is_degree_sequence(&out_deg, is_directed ? &in_deg : 0, &result)) { + if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, &result)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&out_deg); if (is_directed) @@ -470,7 +470,7 @@ PyObject* igraphmodule_is_graphical_degree_sequence(PyObject *self, return NULL; } - if (igraph_is_graphical_degree_sequence(&out_deg, is_directed ? &in_deg : 0, &result)) { + if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, IGRAPH_SIMPLE_SW, &result)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&out_deg); if (is_directed) From 35a47ba43219255812571cd87ed8deef9f127e19 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Mar 2021 20:45:41 +0100 Subject: [PATCH 0446/1892] fix: use deferred import for matplotlib to cut down on import time --- src/igraph/drawing/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 74cf7bdc4..6237e77a3 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -41,7 +41,6 @@ __license__ = "GPL" cairo = find_cairo() -matplotlib, plt = find_matplotlib() ##################################################################### @@ -476,6 +475,8 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @see: Graph.__plot__ """ + _, plt = find_matplotlib() + if hasattr(plt, "Axes") and isinstance(target, plt.Axes): result = MatplotlibGraphDrawer(ax=target) result.draw(obj, *args, **kwds) From c89fe03ac0b43506d7809a8fcb7a2bf3a0a6a147 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 25 Mar 2021 10:36:18 +0100 Subject: [PATCH 0447/1892] Add GraphML support for Windows wheels (#375) --- .github/workflows/build.yml | 185 +++++++++++++++++++++--------------- appveyor.yml | 65 ------------- setup.py | 23 +++++ src/igraph/__init__.py | 2 - tests/test_foreign.py | 2 + tox.ini | 1 + 6 files changed, 136 insertions(+), 142 deletions(-) delete mode 100644 appveyor.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2c207e6d..e205bff6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,85 +1,120 @@ -name: "Build and test with tox" - -on: - push: - branches: - - '*' - tags-ignore: - - '*.*.*' - pull_request: - branches: - - '*' - tags-ignore: - - '*.*.*' - +name: Build and test, upload to PyPI on release +on: [push, pull_request] jobs: - build_linux: - runs-on: ubuntu-latest + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: matrix: - python-version: - - 3.6 - - 3.7 - - 3.8 - - 3.9 - - pypy-3.7 + os: [ubuntu-20.04, macos-10.15] steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: | - git submodule update --init - cat vendor/source/igraph/.git - cat .git/modules/vendor/source/igraph/HEAD - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install OS dependencies - run: - sudo apt-get install gfortran flex bison - - name: Install Python dependencies - run: | - # Pypi has no pip by default, and ubuntu blocks python -m ensurepip - # However, Github runners are supposed to have pip installed by default - # https://docs.github.com/en/actions/guides/building-and-testing-python - #wget -qO- https://bootstrap.pypa.io/get-pip.py | python - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Test with tox - run: tox - env: - TESTING_IN_TOX: 1 - - build_osx: - runs-on: macos-latest - strategy: - matrix: - python-version: - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Install OS dependencies (macOS) + if: runner.os == 'macOS' + run: + brew install ninja autoconf automake libtool cmake + + - name: Build wheels + uses: joerick/cibuildwheel@v1.10.0 + env: + CIBW_BEFORE_BUILD_MACOS: "python setup.py build_c_core" + CIBW_BEFORE_BUILD_LINUX: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp27-* pp27-* cp35-*" + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + + build_wheel_win: + name: Build wheels on Windows + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Install OS dependencies + run: | + choco install winflexbison3 ninja + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe integrate install + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:x64-windows-static-md + shell: cmd + + - name: Build wheels + uses: joerick/cibuildwheel@v1.10.0 + env: + CIBW_BEFORE_BUILD: "pip install delvewheel && python setup.py build_c_core" + CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest" + CIBW_SKIP: "cp27-* pp27-* cp35-* *-win32" + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=x64-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake + IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/x64-windows-static-md/lib/ + IGRAPH_STATIC_EXTENSION: True + IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset + IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - name: Install OS dependencies + run: + sudo apt install ninja-build cmake flex bison + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Build sdist + run: | + python setup.py build_c_core + python setup.py sdist + + - uses: actions/upload-artifact@v2 + with: + path: dist/*.tar.gz + + upload_pypi: + needs: [build_wheels, build_wheel_win, build_sdist] + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: git submodule update --init - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install OS dependencies - run: - brew install autoconf automake libtool - - name: Install Python dependencies - run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Test with tox - run: tox - env: - TESTING_IN_TOX: 1 + - uses: actions/download-artifact@v2 + with: + name: artifact + path: dist + - uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_password }} + # To test: repository_url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 30e1daab8..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,65 +0,0 @@ -image: - - Visual Studio 2019 - -environment: - global: - CIBW_BEFORE_BUILD: python setup.py build_c_core - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - PYTHON: "C:\\Python37" - - matrix: - - CIBW_BUILD: "*-win32" - CIBW_SKIP: "pp27-* cp27-* cp35-*" - IGRAPH_CMAKE_EXTRA_ARGS: "-A Win32" - MSYSTEM: MINGW32 - PATH: C:\msys64\usr\bin;C:\msys64\mingw32\bin;C:\Windows\System32;C:\Windows;%PATH% - TARGET_ARCH: "x86" - - - CIBW_BUILD: "*-win_amd64" - CIBW_SKIP: "pp27-* cp27-* cp35-*" - IGRAPH_CMAKE_EXTRA_ARGS: "-A x64" - MSYSTEM: MINGW64 - PATH: C:\msys64\usr\bin;C:\msys64\mingw64\bin;C:\Windows\System32;C:\Windows;%PATH% - TARGET_ARCH: "x64" - -platform: - - x64 - -install: - # update msys2 - - bash -lc "pacman --needed --noconfirm -Sy pacman-mirrors" - - bash -lc "pacman --noconfirm -Sy" - - bash -lc "pacman --needed --noconfirm -S autoconf automake bison flex libtool mingw-w64-x86_64-libtool mingw-w64-i686-libxml2 mingw-w64-x86_64-libxml2 zip" - - # prepare Python - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - "python --version" - - "python -m pip install --upgrade pip" - - # install cibuildwheel - - pip install cibuildwheel==1.6.1 - - # install pandas (optional) - - pip install pandas - -before_build: - - git submodule update --init --recursive - -for: - - matrix: - only: - - MSYSTEM: MINGW32 - build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" - - cibuildwheel --output-dir wheelhouse - - matrix: - only: - - MSYSTEM: MINGW64 - build_script: - - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - - cibuildwheel --output-dir wheelhouse - -artifacts: - - path: "wheelhouse\\*.whl" - name: Wheels - diff --git a/setup.py b/setup.py index bcc104dfe..72f661952 100644 --- a/setup.py +++ b/setup.py @@ -68,6 +68,7 @@ def find_static_library(library_name, library_path): extra_libdirs = [ "/usr/local/lib64", "/usr/local/lib", + "/usr/lib/x86_64-linux-gnu", "/usr/lib64", "/usr/lib", "/lib64", @@ -391,6 +392,18 @@ def run(self): + buildcfg.library_dirs ) + # Add extra libraries that may have been specified + if "IGRAPH_EXTRA_LIBRARIES" in os.environ: + extra_libraries = os.environ["IGRAPH_EXTRA_LIBRARIES"].split(',') + buildcfg.libraries.extend(extra_libraries) + + # Override static specification based on environment variable + if "IGRAPH_STATIC_EXTENSION" in os.environ: + if os.environ["IGRAPH_STATIC_EXTENSION"].lower() in ['true', '1', 'on']: + buildcfg.static_extension = True + else: + buildcfg.static_extension = False + # Replaces library names with full paths to static libraries # where possible. libm.a is excluded because it caused problems # on Sabayon Linux where libm.a is probably not compiled with @@ -401,6 +414,11 @@ def run(self): else: buildcfg.replace_static_libraries(exclusions=["m"]) + # Add extra libraries that may have been specified + if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ: + extra_libraries = os.environ["IGRAPH_EXTRA_DYNAMIC_LIBRARIES"].split(',') + buildcfg.libraries.extend(extra_libraries) + # Prints basic build information buildcfg.print_build_info() @@ -658,8 +676,11 @@ def replace_static_libraries(self, only=None, exclusions=None): static_lib = find_static_library(library_name, self.library_dirs) if static_lib: + print(f"Found {library_name} as static library in {static_lib}.") self.libraries.remove(library_name) self.extra_objects.append(static_lib) + else: + print(f"Warning: could not find static library of {library_name}.") def use_vendored_igraph(self): """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up @@ -730,6 +751,8 @@ def use_educated_guess(self): buildcfg = BuildConfiguration() buildcfg.process_args_from_command_line() + + # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) igraph_extension = Extension("igraph._igraph", sources) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 23d674b6d..547c56a85 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1,5 +1,3 @@ -# vim:ts=4:sw=4:sts=4:et -# -*- coding: utf-8 -*- """ IGraph library. """ diff --git a/tests/test_foreign.py b/tests/test_foreign.py index fc3d2ec69..f8782a3d0 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -340,6 +340,8 @@ def testPickle(self): self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) + + @skipIf(pd is None, "test case depends on Pandas") def testVertexDataFrames(self): g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) diff --git a/tox.ini b/tox.ini index 73f8166ec..ba72a3bcd 100644 --- a/tox.ini +++ b/tox.ini @@ -21,6 +21,7 @@ deps = numpy; platform_python_implementation != "PyPy" networkx; platform_python_implementation != "PyPy" pandas; platform_python_implementation != "PyPy" +passenv = PATH setenv = TESTING_IN_TOX=1 From 70c06b17e568af78fcd6330813620fd396aa0599 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Mar 2021 10:52:00 +0100 Subject: [PATCH 0448/1892] fix: removed unused x11torgb.py script --- scripts/x11torgb.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100755 scripts/x11torgb.py diff --git a/scripts/x11torgb.py b/scripts/x11torgb.py deleted file mode 100755 index f85402a8a..000000000 --- a/scripts/x11torgb.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -"""Converts X11 color files to RGB formatted Python dicts""" -import sys -import pprint - -if len(sys.argv)<2: - print "Usage: %s filename" % sys.argv[0] - sys.exit(1) - -colors = { - "black": (0. , 0. , 0. , 1.), - "silver": (0.75, 0.75, 0.75, 1.), - "gray": (0.5 , 0.5 , 0.5 , 1.), - "white": (1. , 1. , 1. , 1.), - "maroon": (0.5 , 0. , 0. , 1.), - "red": (1. , 0. , 0. , 1.), - "purple": (0.5 , 0. , 0.5 , 1.), - "fuchsia": (1. , 0. , 1. , 1.), - "green": (0. , 0.5 , 0. , 1.), - "lime": (0. , 1. , 0. , 1.), - "olive": (0.5 , 0.5 , 0. , 1.), - "yellow": (1. , 1. , 0. , 1.), - "navy": (0. , 0. , 0.5 , 1.), - "blue": (0. , 0. , 1. , 1.), - "teal": (0. , 0.5 , 0.5 , 1.), - "aqua": (0. , 1. , 1. , 1.), -} - -f = open(sys.argv[1]) -for line in f: - if line[0] == '!': continue - parts = line.strip().split(None, 3) - for x in xrange(3): - parts[x] = float(parts[x])/255. - parts[3:3] = [1.] - colors[parts[4].lower()] = tuple(parts[0:4]) - -pp = pprint.PrettyPrinter(indent=4) -pp.pprint(colors) - From 5e08c52e68d0e9a046cd5714fd81fee5c59304c0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 25 Mar 2021 10:56:08 +0100 Subject: [PATCH 0449/1892] doc: remove Appveyor badge from README [ci skip] --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c65591029..21102ef74 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) -[![Build status](https://ci.appveyor.com/api/projects/status/55i1d4g65q11f9l5?svg=true)](https://ci.appveyor.com/project/ntamas/python-igraph-jst2e) [![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) From 2b9a6917c65e99a50d400834a37cb331f17b3d24 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 25 Mar 2021 20:48:59 +0100 Subject: [PATCH 0450/1892] Added unittest for GraphML (#377) --- tests/test_foreign.py | 62 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/tests/test_foreign.py b/tests/test_foreign.py index f8782a3d0..630a612fc 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -284,6 +284,66 @@ def testAdjacency(self): g.write_adjacency(tmpfname) + def testGraphML(self): + with temporary_file( + """\ + + + + + + + a + + + b + + + c + + + d + + + e + + + f + + + + + + + + + + + + + + + + + + """ + ) as tmpfname: + try: + g = Graph.Read_GraphML(tmpfname) + except NotImplementedError as e: + self.skipTest(str(e)) + + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(g.vcount(), 6) + self.assertEqual(g.ecount(), 7) + self.assertFalse(g.is_directed()) + self.assertTrue("name" in g.vertex_attributes()) + + g.write_graphml(tmpfname) + def testPickle(self): pickle = [ 128, @@ -340,8 +400,6 @@ def testPickle(self): self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) - - @skipIf(pd is None, "test case depends on Pandas") def testVertexDataFrames(self): g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) From 389c25595e5ff59e4315160850903b2b4792a4d2 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Fri, 26 Mar 2021 09:23:42 +0100 Subject: [PATCH 0451/1892] CI: Updated (#378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Nepusz --- .flake8 | 3 + .github/workflows/build.yml | 127 ++++++++++++++++++++-------- .github/workflows/deploy.yml | 158 ----------------------------------- setup.py | 4 - tox.ini | 31 ------- 5 files changed, 95 insertions(+), 228 deletions(-) create mode 100644 .flake8 delete mode 100644 .github/workflows/deploy.yml delete mode 100644 tox.ini diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..e4e5eb32d --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 88 +extend-ignore = E203, W503 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e205bff6a..7cd1e6844 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,14 +1,17 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] +env: + CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_SKIP: "cp27-* pp27-* cp35-*" jobs: build_wheels: - name: Build wheels on ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: Build wheels on Linux (${{ matrix.wheel_arch }}) + runs-on: ubuntu-20.04 strategy: matrix: - os: [ubuntu-20.04, macos-10.15] + wheel_arch: [x86_64, i686] steps: - uses: actions/checkout@v2 @@ -21,26 +24,64 @@ jobs: with: python-version: '3.8' - - name: Install OS dependencies (macOS) - if: runner.os == 'macOS' + - name: Build wheels + uses: joerick/cibuildwheel@v1.10.0 + env: + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" + CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + + build_wheel_macos: + name: Build wheels on macOS + runs-on: macos-10.15 + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - name: Cache installed C core + id: cache-c-core + uses: actions/cache@v2 + with: + path: vendor/install + key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }} + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Install OS dependencies + if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core run: brew install ninja autoconf automake libtool cmake - name: Build wheels uses: joerick/cibuildwheel@v1.10.0 env: - CIBW_BEFORE_BUILD_MACOS: "python setup.py build_c_core" - CIBW_BEFORE_BUILD_LINUX: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp27-* pp27-* cp35-*" + CIBW_BEFORE_BUILD: "python setup.py build_c_core" - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl build_wheel_win: - name: Build wheels on Windows + name: Build wheels on Windows (${{ matrix.cmake_arch }}) runs-on: windows-2019 + strategy: + matrix: + include: + - cmake_arch: Win32 + wheel_arch: win32 + vcpkg_arch: x86 + - cmake_arch: x64 + wheel_arch: win_amd64 + vcpkg_arch: x64 steps: - uses: actions/checkout@v2 @@ -53,31 +94,47 @@ jobs: with: python-version: '3.8' - - name: Install OS dependencies + - name: Cache installed C core + id: cache-c-core + uses: actions/cache@v2 + with: + path: vendor/install + key: C-core-build-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.gitmodules') }}- + + - name: Cache VCPKG + uses: actions/cache@v2 + with: + path: C:/vcpkg/installed/ + key: vcpkg-${{ runner.os }}-${{ matrix.vcpkg_arch }} + + - name: Install build dependencies + if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core + run: choco install winflexbison3 ninja + + - name: Install VCPKG libraries run: | - choco install winflexbison3 ninja %VCPKG_INSTALLATION_ROOT%\vcpkg.exe integrate install - %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:x64-windows-static-md + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md shell: cmd - name: Build wheels uses: joerick/cibuildwheel@v1.10.0 env: - CIBW_BEFORE_BUILD: "pip install delvewheel && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest" - CIBW_SKIP: "cp27-* pp27-* cp35-* *-win32" - IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=x64-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake - IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/x64-windows-static-md/lib/ + CIBW_BEFORE_BUILD: "python setup.py build_c_core" + CIBW_BUILD: "*-${{ matrix.wheel_arch }}" + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} + IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 + CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest" - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl build_sdist: - name: Build source distribution + name: Build sdist and test extra dependencies runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -85,7 +142,17 @@ jobs: submodules: true fetch-depth: 0 + - name: Cache installed C core + id: cache-c-core + uses: actions/cache@v2 + with: + path: | + vendor/build + vendor/install + key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }}-4 + - name: Install OS dependencies + if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core run: sudo apt install ninja-build cmake flex bison @@ -98,23 +165,13 @@ jobs: run: | python setup.py build_c_core python setup.py sdist + python setup.py install + + - name: Test + run: | + pip install numpy scipy pandas + python -m unittest - uses: actions/upload-artifact@v2 with: path: dist/*.tar.gz - - upload_pypi: - needs: [build_wheels, build_wheel_win, build_sdist] - runs-on: ubuntu-latest - if: github.event_name == 'release' && github.event.action == 'published' - steps: - - uses: actions/download-artifact@v2 - with: - name: artifact - path: dist - - - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.pypi_password }} - # To test: repository_url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 65ef5466e..000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,158 +0,0 @@ -name: "Build wheels and deploy" - -# To trigger manually, make yourself an auth token including "workflow" scope and run: -# curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token " https://api.github.com/repos/igraph/python-igraph/actions/workflows/deploy.yml/dispatches -d '{"ref":"master"}' -# If you want to release from another branch and not "master", change the last string. - -on: - workflow_dispatch: - push: - tags: - - '*.*.*' - - -jobs: - wheels_manylinux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: git submodule update --init - - name: Set up Python - uses: actions/setup-python@v2 - - name: Install OS dependencies - run: - sudo apt-get install gfortran flex bison - - name: Install cibuildwheel - run: | - # Pypi has no pip by default, and ubuntu blocks python -m ensurepip - # However, Github runners are supposed to have pip installed by default - # https://docs.github.com/en/actions/guides/building-and-testing-python - #wget -qO- https://bootstrap.pypa.io/get-pip.py | python - python -m pip install --upgrade pip - pip install cibuildwheel - - name: Wheels (Linux) - env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp27-* pp27-* cp35-*" - run: | - python setup.py -q sdist - python -m cibuildwheel --output-dir wheelhouse - - name: Upload source dist - uses: actions/upload-artifact@v2 - with: - name: source-dist - path: dist/python-igraph-*.tar.gz - - name: Upload Linux wheels - uses: actions/upload-artifact@v2 - with: - name: linux-wheels - path: wheelhouse/*.whl - - wheels_osx: - runs-on: macos-latest - steps: - - uses: actions/checkout@v1 - - name: Init C core submodule - run: git submodule update --init - - name: Set up Python - uses: actions/setup-python@v2 - - name: Install OS dependencies - run: - brew install autoconf automake libtool - - name: Install Python dependencies - run: | - python -m pip install --upgrade pip - pip install cibuildwheel - - name: Wheels (OSX) - run: | - python -m cibuildwheel --output-dir wheelhouse - env: - CIBW_BEFORE_BUILD: "pip install cmake && python setup.py build_c_core" - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" - CIBW_SKIP: "cp27-* pp27-* cp35-*" - - name: Upload Linux wheels - uses: actions/upload-artifact@v2 - with: - name: OSX-wheels - path: wheelhouse/*.whl - - create_release: - runs-on: ubuntu-latest - needs: - - wheels_manylinux - - wheels_osx - steps: - - name: "Download artifacts: source dist" - uses: actions/download-artifact@v2 - with: - name: source-dist - path: dist - - - name: "Download artifacts: Linux wheels" - uses: actions/download-artifact@v2 - with: - name: linux-wheels - path: wheelhouse - - - name: "Download artifacts: OSX wheels" - uses: actions/download-artifact@v2 - with: - name: OSX-wheels - path: wheelhouse - - - name: "List contents of artifact folders" - run: | - echo "dist folder:" - ls -lh dist - echo "wheelhouse folder:" - ls -lh wheelhouse - - - name: Store igraph version - id: get_version - run: | - echo "igraph_version=$(fn=$(ls dist); fn=${fn##*-}; echo ${fn%.tar.gz})" >> $GITHUB_ENV - tail -n 1 $GITHUB_ENV - - - name: Create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ env.igraph_version }} - release_name: Release ${{ env.igraph_version }} - draft: true - prerelease: false - - #- name: Upload binaries and source - # uses: AButler/upload-release-assets@v2.0 - # with: - # files: 'wheelhouse/*.whl;dist/python-igraph-*.tar.gz' - # repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Move artifacts into one folder - run: | - mkdir upload - mv dist/* upload/ - mv wheelhouse/* upload/ - ls upload - - - name: Upload binaries and source - uses: actions/github-script@v3 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const path = require('path'); - const fs = require('fs'); - const release_id = '${{ steps.create_release.outputs.id }}'; - for (let file of await fs.readdirSync('./upload/')) { - console.log('uploadReleaseAsset', file); - await github.repos.uploadReleaseAsset({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: release_id, - name: file, - data: await fs.readFileSync(`./upload/${file}`) - }); - } diff --git a/setup.py b/setup.py index 72f661952..dcb4bab94 100644 --- a/setup.py +++ b/setup.py @@ -510,10 +510,6 @@ def run(self): parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") if os.path.isdir(parser_dir): shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) - elif os.environ.get("TESTING_IN_TOX"): - # we allow to proceed when running in tox in the CI environment; - # bison and flex will be used to generate the parsers - pass else: raise RuntimeError(f"You need to build the C core of igraph first before generating a source tarball of python-igraph") diff --git a/tox.ini b/tox.ini deleted file mode 100644 index ba72a3bcd..000000000 --- a/tox.ini +++ /dev/null @@ -1,31 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py36, py37, py38, py39, pypy, pypy3 - -[gh-actions] -python = - 3.6: py36 - 3.7: py37 - 3.8: py38 - 3.9: py39 - pypy-3.7: pypy3 - -[testenv] -commands = python -m unittest -deps = - scipy; platform_python_implementation != "PyPy" - numpy; platform_python_implementation != "PyPy" - networkx; platform_python_implementation != "PyPy" - pandas; platform_python_implementation != "PyPy" -passenv = PATH -setenv = - TESTING_IN_TOX=1 - -[flake8] -max-line-length = 80 -select = C,E,F,W,B,B950 -ignore = W503,E501,E402,E203 From ace6896f6d7b501e8de9198ecac28d1d5c8e0e13 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Mar 2021 10:32:27 +0100 Subject: [PATCH 0452/1892] doc: fix a warning when generating the API docs [ci skip] --- src/igraph/drawing/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 6237e77a3..e099c0dd8 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -320,7 +320,7 @@ def show(self): """Saves the plot to a temporary file and shows it. This method is deprecated from python-igraph 0.9.1 and will be removed in - 0.10.0. + version 0.10.0. @deprecated: Opening an image viewer with a temporary file never worked reliably across platforms. From bdafc25a49eb3fde703cb81aef5b18ca8dad5104 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Mar 2021 10:33:06 +0100 Subject: [PATCH 0453/1892] doc: scripts/mkdoc.sh now ensures that python-igraph is installed from a wheel (PyDoctor does not like the bootstrap scripts added by Python eggs) --- scripts/mkdoc.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 214027c4d..356d13d64 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -15,7 +15,7 @@ cd ${ROOT_FOLDER} if [ ! -d ".venv" ]; then # Create a virtual environment for pydoctor python3 -m venv .venv - .venv/bin/pip install pydoctor + .venv/bin/pip install -U pydoctor wheel fi PYDOCTOR=.venv/bin/pydoctor @@ -29,6 +29,14 @@ PWD=`pwd` echo "Removing existing documentation..." rm -rf "${DOC_API_FOLDER}/html" "${DOC_API_FOLDER}/pdf" +echo "Removing existing python-igraph eggs from virtualenv..." +SITE_PACKAGES_DIR=`.venv/bin/python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'` +rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg +rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg-link + +echo "Installing python-igraph in virtualenv..." +rm -f dist/*.whl && .venv/bin/python setup.py bdist_wheel && .venv/bin/pip install dist/*.whl + IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` echo "Generating HTML documentation..." From 20d0b04343042759c9a8071651a5a0c0e4897149 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Mar 2021 10:39:54 +0100 Subject: [PATCH 0454/1892] test: restore tox.ini, it is useful to test things locally [ci skip] --- tox.ini | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 000000000..bd0355f4d --- /dev/null +++ b/tox.ini @@ -0,0 +1,27 @@ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py36, py37, py38, py39, pypy, pypy3 + +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + pypy-3.7: pypy3 + +[testenv] +commands = python -m unittest +deps = + scipy; platform_python_implementation != "PyPy" + numpy; platform_python_implementation != "PyPy" + networkx; platform_python_implementation != "PyPy" + pandas; platform_python_implementation != "PyPy" +passenv = PATH +setenv = + TESTING_IN_TOX=1 + From 1137bc1cbc962e59ce7a3702e0c530e705f2c493 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Mar 2021 10:41:02 +0100 Subject: [PATCH 0455/1892] chore: bumped version to 0.9.1 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 16be2bd7f..4eeb3ae08 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.0' +version = '0.9.1' # The full version, including alpha/beta/rc tags. -release = '0.9.0' +release = '0.9.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 1836d2e87..14ef391dc 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 0) +__version_info__ = (0, 9, 1) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 13965a03fd3390ebd301a483c607d0657e4008de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Fri, 26 Mar 2021 11:31:44 +0100 Subject: [PATCH 0456/1892] remove unneeded square brackets from version numbers in changelog [ci skip] --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d15b63b1c..b2cc5c137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [0.9.1] +## 0.9.1 ### Changed @@ -30,7 +30,7 @@ 2.x are removed now that we have dropped support for Python 2.x. -## [0.9.0] +## 0.9.0 ### Added From 30f5a1bec0d44fdc95ca9ae8cc07c534bee1dd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Fri, 26 Mar 2021 11:44:37 +0100 Subject: [PATCH 0457/1892] added missing entry about GraphML support on Windows in changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2cc5c137..c8fea258e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,9 @@ * Many old code constructs that were used to maintain compatibility with Python 2.x are removed now that we have dropped support for Python 2.x. +* Reading GraphML files is now also supported on Windows if you use one of the + official Python wheels. + ## 0.9.0 From a343616fa0e3e2bdaaec7390c1419a5326caa3e8 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Sat, 27 Mar 2021 19:59:41 +0100 Subject: [PATCH 0458/1892] Improved documentation for compiling from source on Windows. (#380) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Nepusz --- README.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 21102ef74..e276509f9 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ Python interface for the igraph library --------------------------------------- -igraph is a library for creating and manipulating graphs. +igraph is a library for creating and manipulating graphs. It is intended to be as powerful (ie. fast) as possible to enable the -analysis of large graphs. +analysis of large graphs. This repository contains the source code to the Python interface of igraph. @@ -23,7 +23,7 @@ running the following command should work without having to compile anything during installation: ``` -$ pip install python-igraph +pip install python-igraph ``` See details in [Installing Python Modules](https://docs.python.org/3/installing/). @@ -34,18 +34,72 @@ If you need to compile python-igraph from source for some reason, you need to install some dependencies first: ``` -$ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev bison flex +sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev ``` and then run ``` -$ pip install python-igraph +pip install python-igraph ``` This should compile the C core of igraph as well as the Python extension automatically. +### Installation from source on Windows + +It is now also possible to compile `python-igraph` from source under Windows for +Python 3.6 and later. Make sure that you have Microsoft Visual Studio 2015 or +later installed, and of course Python 3.6 or later. First extract the source to +a suitable directory. If you launch the Developer command prompt and navigate to +the directory where you extracted the source code, you should be able to build +and install python-igraph using `python setup.py install` + +You may need to set the architecture that you are building on explicitly by setting the environment variable + +``` +set IGRAPH_CMAKE_EXTRA_ARGS=-A [arch] +``` + +where `[arch]` is either `Win32` for 32-bit builds or `x64` for 64-bit builds. + +#### Enabling GraphML + +By default, GraphML is disabled, because `libxml2` is not available on Windows in +the standard installation. You can install `libxml2` on Windows using +[`vcpkg`](https://github.com/Microsoft/vcpkg). After installation of `vcpkg` you +can install `libxml2` as follows + +``` +vcpkg.exe install libxml2:x64-windows-static-md +``` + +for 64-bit version (for 32-bit versions you can use the `x86-windows-static-md` +triplet). You need to integrate `vcpkg` in the build environment using + +``` +vcpkg.exe integrate install +``` + +This mentions that + +> CMake projects should use: `-DCMAKE_TOOLCHAIN_FILE=[vcpkg build script]` + +which we will do next. In order to build `python-igraph` correctly, you also +need to set some other environment variables before building `python-igraph`: + +``` +set IGRAPH_CMAKE_EXTRA_ARGS=-DVCPKG_TARGET_TRIPLET=x64-windows-static-md -DCMAKE_TOOLCHAIN_FILE=[vcpkg build script] +set IGRAPH_EXTRA_LIBRARY_PATH=[vcpkg directory]/installed/x64-windows-static-md/lib/ +set IGRAPH_STATIC_EXTENSION=True +set IGRAPH_EXTRA_LIBRARIES=libxml2,lzma,zlib,iconv,charset +set IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 +``` + +You can now build and install `python-igraph` again by simply running `python +setup.py build`. Please make sure to use a clean source tree, if you built +previously without GraphML, it will not update the build. + ### Linking to an existing igraph installation The source code of the Python package includes the source code of the matching @@ -57,23 +111,23 @@ custom installation of igraph is discoverable with `pkg-config`. First, check whether `pkg-config` can tell you the required compiler and linker flags for igraph: -``` -$ pkg-config --cflags --libs igraph +```bash +pkg-config --cflags --libs igraph ``` If `pkg-config` responds with a set of compiler and linker flags and not an error message, you are probably okay. You can then proceed with the installation using pip: -``` -$ pip install python-igraph --install-option="--use-pkg-config" +```bash +pip install python-igraph --install-option="--use-pkg-config" ``` Alternatively, if you have already downloaded and extracted the source code of igraph, you can run `setup.py` directly: -``` -$ python setup.py build --use-pkg-config +```bash +python setup.py build --use-pkg-config ``` This option is primarily intended for package maintainers in Linux @@ -83,6 +137,9 @@ the packaged igraph library instead of bringing its own copy. It is also useful on macOS if you want to link to the igraph library installed from Homebrew. +Due to the lack of support of `pkg-config` on Window, it is currently not +possible to build against an external library on Windows. + ## Compiling the development version If you have downloaded the source code from Github and not PyPI, chances are @@ -90,15 +147,25 @@ that you have the latest development version, which contains a matching version of the C core of igraph as a git submodule. Therefore, to install the bleeding edge version, you need to instruct git to check out the submodules first: -``` +```bash git submodule update --init ``` +Compiling the development version additionally requires `flex` and `bison`. You +can install those on Ubuntu using + +```bash +sudo apt install bison flex +``` + +On macOS you can install these from Homebrew or MacPorts. On Windows you can +install `winflexbison3` from Chocolatey. + Then, running the setup script should work if you have a C compiler and the necessary build dependencies (see the previous section): -``` -$ sudo python setup.py build +```bash +python setup.py build ``` ## Running unit tests @@ -106,8 +173,8 @@ $ sudo python setup.py build Unit tests can be executed from the project directory with `tox` or with the built-in unittest module: -``` -$ python -m unittest +```bash +python -m unittest ``` ## Contributing From 2a9c85831a89a11fce0c8b500794f60c94bcde42 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 28 Mar 2021 22:11:28 +0200 Subject: [PATCH 0459/1892] test: print index of graph when hub or authority score calculation fails in the Graph Atlas unit tests --- tests/test_atlas.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tests/test_atlas.py b/tests/test_atlas.py index 322a61f89..b1327550c 100644 --- a/tests/test_atlas.py +++ b/tests/test_atlas.py @@ -102,7 +102,16 @@ def testEigenvectorCentrality(self): def testHubScore(self): for idx, g in enumerate(self.__class__.graphs): - sc = g.hub_score() + try: + sc = g.hub_score() + except Exception as ex: + self.assertTrue( + False, + msg="Hub score calculation threw exception for graph #%d: %s" + % (idx, ex), + ) + raise + if g.vcount() == 0: self.assertEqual([], sc) continue @@ -119,7 +128,16 @@ def testHubScore(self): def testAuthorityScore(self): for idx, g in enumerate(self.__class__.graphs): - sc = g.authority_score() + try: + sc = g.authority_score() + except Exception as ex: + self.assertTrue( + False, + msg="Authority score calculation threw exception for graph #%d: %s" + % (idx, ex), + ) + raise + if g.vcount() == 0: self.assertEqual([], sc) continue From 4b2ed40b18f59cd0885c3c61bbf6dd70f19b455c Mon Sep 17 00:00:00 2001 From: Willem van den Boom Date: Tue, 30 Mar 2021 16:40:17 +0800 Subject: [PATCH 0460/1892] Fix links to Python documentation (#381) --- doc/source/tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 84480fa6c..d72d0ee26 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -1050,6 +1050,6 @@ of the `Graph class`_. Should you get stuck, try asking in our `Discourse group`_ first - maybe there is someone out there who can help you out immediately. -.. _API documentation: https://igraph.org/python/doc/igraph-module.html -.. _Graph class: https://igraph.org/python/doc/igraph.Graph-class.html +.. _API documentation: https://igraph.org/python/doc/api/index.html +.. _Graph class: https://igraph.org/python/doc/api/igraph.Graph.html .. _Discourse group: https://igraph.discourse.group From 939c601ec46f2e563b086c62938e838c26749d6f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 30 Mar 2021 10:41:29 +0200 Subject: [PATCH 0461/1892] doc: make sure that an up-to-date wheel is installed when building docs [ci skip] --- scripts/mkdoc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 356d13d64..96826951c 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -35,7 +35,7 @@ rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg-link echo "Installing python-igraph in virtualenv..." -rm -f dist/*.whl && .venv/bin/python setup.py bdist_wheel && .venv/bin/pip install dist/*.whl +rm -f dist/*.whl && .venv/bin/python setup.py bdist_wheel && .venv/bin/pip install --force-reinstall dist/*.whl IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` From 5b77225b35e28c35bb4948157d3004fda6a38c79 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 30 Mar 2021 10:41:44 +0200 Subject: [PATCH 0462/1892] doc: fix a docstring in EdgeSeq.select() [ci skip] --- src/_igraph/edgeseqobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 96ee3f19f..dc7457784 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -825,7 +825,7 @@ PyMethodDef igraphmodule_EdgeSeq_methods[] = { }, {"select", (PyCFunction)igraphmodule_EdgeSeq_select, METH_VARARGS, - "select(...)\n--\n\n" + "select(*args, **kwds)\n--\n\n" "For internal use only.\n" }, {NULL} From a47e005fbb5c2a3cac83df1314a2b2563749ec17 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 30 Mar 2021 10:49:46 +0200 Subject: [PATCH 0463/1892] fix: more descriptive error message when cairo or cairocffi is not installed, refs #283 --- src/igraph/drawing/utils.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index cde3e5266..699c1cad9 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -6,7 +6,7 @@ from math import atan2, cos, sin from operator import itemgetter -__all__ = ("BoundingBox", "FakeModule", "Point", "Rectangle") +__all__ = ("BoundingBox", "Point", "Rectangle") __license__ = "GPL" ##################################################################### @@ -403,17 +403,28 @@ def __or__(self, other): # pylint: disable-msg=R0903 # R0903: too few public methods -class FakeModule(object): +class FakeModule: """Fake module that raises an exception for everything""" + def __init__(self, message): + """Constructor. + + Parameters: + message: message to print in exceptions raised from this module + """ + self._message = message + def __getattr__(self, _): - raise AttributeError("plotting not available") + raise AttributeError(self._message) def __call__(self, _): - raise TypeError("plotting not available") + raise TypeError(self._message) def __setattr__(self, key, value): - raise AttributeError("plotting not available") + if key == "_message": + super().__setattr__(key, value) + else: + raise AttributeError(self._message) ##################################################################### @@ -425,7 +436,7 @@ def find_cairo(): Returns a fake module if everything fails. """ module_names = ["cairo", "cairocffi"] - module = FakeModule() + module = FakeModule("Plotting not available; please install pycairo or cairocffi") for module_name in module_names: try: module = __import__(module_name) @@ -439,8 +450,7 @@ def find_cairo(): def find_matplotlib(): - """Tries to import the ``cairo`` Python module if it is installed, - also trying ``cairocffi`` (a drop-in replacement of ``cairo``). + """Tries to import the ``matplotlib`` Python module if it is installed. Returns a fake module if everything fails. """ try: @@ -448,13 +458,13 @@ def find_matplotlib(): has_mpl = True except ImportError: - mpl = FakeModule() + mpl = FakeModule("You need to install matplotlib to use this functionality") has_mpl = False if has_mpl: import matplotlib.pyplot as plt else: - plt = FakeModule() + plt = FakeModule("You need to install matplotlib.pyplot to use this functionality") return mpl, plt From 1ad768a99ea54731ef812044a68ef79621c5b8fc Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Wed, 7 Apr 2021 22:49:20 +0200 Subject: [PATCH 0464/1892] CI: Remove parallel option, explicitly install release config. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index dcb4bab94..c623e2e37 100644 --- a/setup.py +++ b/setup.py @@ -265,13 +265,13 @@ def compile_in(self, source_folder, build_folder, install_folder): print("Running build...") retcode = subprocess.call( - [cmake, "--build", ".", "--parallel", "--config", "Release"] + [cmake, "--build", ".", "--config", "Release"] ) if retcode: return False print("Installing build...") - retcode = subprocess.call([cmake, "--install", ".", "--prefix", str(install_folder)]) + retcode = subprocess.call([cmake, "--install", ".", "--prefix", str(install_folder), "--config", "Release"]) if retcode: return False From 91eb86c65ff1fd9af432dddf181e9262288ecd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Fri, 9 Apr 2021 09:43:26 +0200 Subject: [PATCH 0465/1892] doc: added a comment in setup.py explaining why we do not use parallel CMake builds --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index c623e2e37..ffa7dedac 100644 --- a/setup.py +++ b/setup.py @@ -264,6 +264,7 @@ def compile_in(self, source_folder, build_folder, install_folder): return False print("Running build...") + # We are _not_ using a parallel build; this is intentional, see igraph/igraph#1755 retcode = subprocess.call( [cmake, "--build", ".", "--config", "Release"] ) From 1cd379ee46dcb4ccee2b820ec883bbe75674f7f6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 19 Apr 2021 09:40:05 +0200 Subject: [PATCH 0466/1892] doc: documentation fix to prevent a PyDoctor warning [ci skip] --- src/igraph/drawing/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 699c1cad9..68f1b9b60 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -409,8 +409,7 @@ class FakeModule: def __init__(self, message): """Constructor. - Parameters: - message: message to print in exceptions raised from this module + @param message: message to print in exceptions raised from this module """ self._message = message From 405098376535d453b01c0ba8a3ad44a02423fe89 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 14:05:26 +1000 Subject: [PATCH 0467/1892] Realize_Degree_Sequence implementation with strings --- doc/source/generation.rst | 1 + src/_igraph/graphobject.c | 97 +++++++++++++++++++++++++++++++++++++++ src/_igraph/graphobject.h | 1 + tests/test_generators.py | 27 +++++++++++ 4 files changed, 126 insertions(+) diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 2e689dd36..4659406a1 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -170,5 +170,6 @@ Finally, there are some ways of generating graphs that are not covered by the pr - De Bruijn graphs :meth:`Graph.De_Bruijn` - Lederberg-Coxeter-Frucht graphs :meth:`Graph.LCF` - graphs with a specified isomorphism class :meth:`Graph.Isoclass` + - graphs with a specified degree sequence :meth:`Graph.Realize_Degree_Sequence` .. _API documentation: https://igraph.org/python/doc/igraph-module.html diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 0ced8a25f..114c101bb 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2791,6 +2791,88 @@ PyObject *igraphmodule_Graph_LCF(PyTypeObject *type, return (PyObject *) self; } +/** \ingroup python_interface_graph + * \brief Generates a graph with a specified degree sequence + * \return a reference to the newly generated Python igraph object + * \sa igraph_realize_degree_sequence + */ +PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, + PyObject *args, PyObject *kwds) { + + igraph_vector_t outdeg, indeg; + igraph_vector_t *indegp = 0; + igraph_edge_type_sw_t allowed_edge_types; + igraph_realize_degseq_t method; + PyObject *outdeg_o, *indeg_o, *edge_types_o, *method_o; + PyObject *repr; + igraphmodule_GraphObject *self; + igraph_t g; + + static char *kwlist[] = { "outdeg", "indeg", "allowed_edge_types", "method", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOO", kwlist, + &outdeg_o, &indeg_o, &edge_types_o, &method_o)) + return NULL; + + /* allowed edge types */ + repr = PyObject_Str(edge_types_o); + if (PyUnicode_CompareWithASCIIString(repr, "simple_sw") == 0) + allowed_edge_types = IGRAPH_SIMPLE_SW; + else if (PyUnicode_CompareWithASCIIString(repr, "multi_sw") == 0) + allowed_edge_types = IGRAPH_MULTI_SW; + else { + Py_XDECREF(repr); + PyErr_SetString(PyExc_ValueError, "allowed_edge_types must be 'simple_sw' or 'multi_sw' (undirected only)."); + return NULL; + } + Py_XDECREF(repr); + + /* methods */ + repr = PyObject_Str(method_o); + if (PyUnicode_CompareWithASCIIString(repr, "smallest") == 0) + method = IGRAPH_REALIZE_DEGSEQ_SMALLEST; + else if (PyUnicode_CompareWithASCIIString(repr, "largest") == 0) + method = IGRAPH_REALIZE_DEGSEQ_LARGEST; + else if (PyUnicode_CompareWithASCIIString(repr, "index") == 0) + method = IGRAPH_REALIZE_DEGSEQ_INDEX; + else { + Py_XDECREF(repr); + PyErr_SetString(PyExc_ValueError, "method must be 'smallest', 'largest', or 'index'"); + return NULL; + } + Py_XDECREF(repr); + + /* Outdegree vector */ + if (igraphmodule_PyObject_to_vector_t(outdeg_o, &outdeg, 0)) + return NULL; + + /* Indegree vector, PyNone means undirected graph */ + if (indeg_o != Py_None) { + if (igraphmodule_PyObject_to_vector_t(indeg_o, &indeg, 0)) { + igraph_vector_destroy(&outdeg); + return NULL; + } + indegp = &indeg; + } + + /* C function takes care of multi-sw and directed corner case */ + if (igraph_realize_degree_sequence(&g, &outdeg, indegp, allowed_edge_types, method)) { + igraph_vector_destroy(&outdeg); + if (indegp != 0) + igraph_vector_destroy(&indeg); + igraphmodule_handle_igraph_error(); + return NULL; + } + + igraph_vector_destroy(&outdeg); + if (indegp != 0) + igraph_vector_destroy(&indeg); + + CREATE_GRAPH_FROM_TYPE(self, g, type); + + return (PyObject *) self; +} + + /** \ingroup python_interface_graph * \brief Generates a graph based on vertex types and connection preferences * \return a reference to the newly generated Python igraph object @@ -12605,6 +12687,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param repeats: the number of repeats\n" }, + {"Realize_Degree_Sequence", (PyCFunction) igraphmodule_Graph_Realize_Degree_Sequence, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "Realize_Degree_Sequence(outdeg, indeg, allowed_edge_types, method)\n--\n\n" + "Generates a graph from a degree sequence.\n\n" + "@param outdeg: the degree sequence of an undirected graph (if indeg=None), " + "or the out-degree sequence of a directed graph.\n" + "@param indeg: None to generate an undirected graph, the in-degree sequence " + "to generate a directed graph.\n" + "@param allowed_edge_types: TODO!\n" + "@param method: possible values are\n" + " - REALIZE_DEGSEQ_SMALLEST: The vertex with smallest remaining degree first.\n" + " - REALIZE_DEGSEQ_LARGEST: The vertex with the largest remaining degree first.\n" + " - REALIZE_DEGSEQ_INDEX: The vertices are selected in order of their index.\n" + }, + // interface to igraph_ring {"Ring", (PyCFunction) igraphmodule_Graph_Ring, METH_VARARGS | METH_CLASS | METH_KEYWORDS, diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 618dbb97b..3ab836942 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -92,6 +92,7 @@ PyObject* igraphmodule_Graph_Growing_Random(PyTypeObject *type, PyObject *args, PyObject* igraphmodule_Graph_Isoclass(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Lattice(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_LCF(PyTypeObject *type, PyObject *args, PyObject *kwds); +PyObject* igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Preference(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Recent_Degree(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Ring(PyTypeObject *type, PyObject *args, PyObject *kwds); diff --git a/tests/test_generators.py b/tests/test_generators.py index 1d566b54e..7b6810ac9 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -134,6 +134,33 @@ def testLCF(self): self.assertTrue(g1.isomorphic(g2)) self.assertRaises(InternalError, Graph.LCF, 12, (5, -5), -3) + def testRealizeDegreeSequence(self): + g = Graph.Realize_Degree_Sequence( + [1, 1], None, "simple_sw", "smallest", + ) + self.assertFalse(g.is_directed()) + + g = Graph.Realize_Degree_Sequence( + [1, 1], None, "multi_sw", "index", + ) + self.assertFalse(g.is_directed()) + + g = Graph.Realize_Degree_Sequence( + [1, 1], [1, 1], "simple_sw", "largest", + ) + self.assertTrue(g.is_directed()) + + # Not implemented, should fail + self.assertRaises(NotImplementedError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "multi_sw", "largest") + + self.assertRaises(ValueError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "should_fail", "index") + self.assertRaises(ValueError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "multi_sw", "should_fail") + + + def testKautz(self): g = Graph.Kautz(2, 2) deg_in = g.degree(mode=IN) From 4a1966c94445e6a9ca0b6034f61f842045a9fcec Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 14:12:25 +1000 Subject: [PATCH 0468/1892] Implement all 4 cases for multi-edges and loops, and add docs --- src/_igraph/graphobject.c | 17 +++++++++++++---- tests/test_generators.py | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 114c101bb..8e6c56b54 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2817,8 +2817,12 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, repr = PyObject_Str(edge_types_o); if (PyUnicode_CompareWithASCIIString(repr, "simple_sw") == 0) allowed_edge_types = IGRAPH_SIMPLE_SW; + else if (PyUnicode_CompareWithASCIIString(repr, "loops_sw") == 0) + allowed_edge_types = IGRAPH_LOOPS_SW; else if (PyUnicode_CompareWithASCIIString(repr, "multi_sw") == 0) allowed_edge_types = IGRAPH_MULTI_SW; + else if (PyUnicode_CompareWithASCIIString(repr, "both_sw") == 0) + allowed_edge_types = IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW; else { Py_XDECREF(repr); PyErr_SetString(PyExc_ValueError, "allowed_edge_types must be 'simple_sw' or 'multi_sw' (undirected only)."); @@ -12695,11 +12699,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "or the out-degree sequence of a directed graph.\n" "@param indeg: None to generate an undirected graph, the in-degree sequence " "to generate a directed graph.\n" - "@param allowed_edge_types: TODO!\n" + "@param allowed_edge_types: for directed graphs, only 'simple_sw' is currently \n" + "implemented. Possible values for undirected graphs are\n" + " - 'simple_sw: simple graphs (no self-loops, no multi-edges)\n" + " - 'loops_sw': single self-loops allowed, but not multi-edges \n" + " - 'multi_sw': multi-edges allowed, but not self-loops \n" + " - 'both_sw': multi-edges and self-loops allowed \n" "@param method: possible values are\n" - " - REALIZE_DEGSEQ_SMALLEST: The vertex with smallest remaining degree first.\n" - " - REALIZE_DEGSEQ_LARGEST: The vertex with the largest remaining degree first.\n" - " - REALIZE_DEGSEQ_INDEX: The vertices are selected in order of their index.\n" + " - 'smallest': The vertex with smallest remaining degree first.\n" + " - 'largest': The vertex with the largest remaining degree first.\n" + " - 'index': The vertices are selected in order of their index.\n" }, // interface to igraph_ring diff --git a/tests/test_generators.py b/tests/test_generators.py index 7b6810ac9..b9bf37301 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -140,6 +140,15 @@ def testRealizeDegreeSequence(self): ) self.assertFalse(g.is_directed()) + # Not implemented, should fail + self.assertRaises(NotImplementedError, Graph.Realize_Degree_Sequence, + [1, 1], None, "loops_sw", "largest") + + g = Graph.Realize_Degree_Sequence( + [1, 1], None, "both_sw", "largest", + ) + self.assertFalse(g.is_directed()) + g = Graph.Realize_Degree_Sequence( [1, 1], None, "multi_sw", "index", ) From bdcae0cb0b9d7cae4017540384a73b52710231b2 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 17:38:45 +1000 Subject: [PATCH 0469/1892] use convert.c, but fails to raise error? --- src/_igraph/convert.c | 34 ++++++++++++++++++++++++++++++++++ src/_igraph/convert.h | 2 ++ src/_igraph/graphobject.c | 31 +++---------------------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 010f83877..d694ff57c 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3025,3 +3025,37 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t return igraphmodule_PyObject_to_enum(o, pagerank_algo_tt, (int*)result); } + +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_edge_type_sw_t + */ +int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result) { + static igraphmodule_enum_translation_table_entry_t edge_type_sw_tt[] = { + {"simple_sw", IGRAPH_SIMPLE_SW}, + {"loops_sw", IGRAPH_LOOPS_SW}, + {"multi_sw", IGRAPH_MULTI_SW}, + {"both_sw", IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW}, + {0,0} + }; + + return igraphmodule_PyObject_to_enum(o, edge_type_sw_tt, (int*)result); +} + +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_realize_degseq_t + */ +int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq_t *result) { + static igraphmodule_enum_translation_table_entry_t realize_degseq_tt[] = { + {"smallest", IGRAPH_REALIZE_DEGSEQ_SMALLEST}, + {"largest", IGRAPH_REALIZE_DEGSEQ_LARGEST}, + {"index", IGRAPH_REALIZE_DEGSEQ_INDEX}, + {0,0} + }; + + return igraphmodule_PyObject_to_enum(o, realize_degseq_tt, (int*)result); +} + + + diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 8834420cf..0d1d117a8 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -63,6 +63,8 @@ int igraphmodule_PyObject_to_get_adjacency_t(PyObject *o, igraph_get_adjacency_t int igraphmodule_PyObject_to_layout_grid_t(PyObject *o, igraph_layout_grid_t *result); int igraphmodule_PyObject_to_neimode_t(PyObject *o, igraph_neimode_t *result); int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t *result); +int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result); +int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq_t *result); int igraphmodule_PyObject_to_random_walk_stuck_t(PyObject *o, igraph_random_walk_stuck_t *result); int igraphmodule_PyObject_to_reciprocity_t(PyObject *o, igraph_reciprocity_t *result); int igraphmodule_PyObject_to_rewiring_t(PyObject *o, igraph_rewiring_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8e6c56b54..5bf29bc19 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2804,7 +2804,6 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, igraph_edge_type_sw_t allowed_edge_types; igraph_realize_degseq_t method; PyObject *outdeg_o, *indeg_o, *edge_types_o, *method_o; - PyObject *repr; igraphmodule_GraphObject *self; igraph_t g; @@ -2814,36 +2813,12 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, return NULL; /* allowed edge types */ - repr = PyObject_Str(edge_types_o); - if (PyUnicode_CompareWithASCIIString(repr, "simple_sw") == 0) - allowed_edge_types = IGRAPH_SIMPLE_SW; - else if (PyUnicode_CompareWithASCIIString(repr, "loops_sw") == 0) - allowed_edge_types = IGRAPH_LOOPS_SW; - else if (PyUnicode_CompareWithASCIIString(repr, "multi_sw") == 0) - allowed_edge_types = IGRAPH_MULTI_SW; - else if (PyUnicode_CompareWithASCIIString(repr, "both_sw") == 0) - allowed_edge_types = IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW; - else { - Py_XDECREF(repr); - PyErr_SetString(PyExc_ValueError, "allowed_edge_types must be 'simple_sw' or 'multi_sw' (undirected only)."); - return NULL; - } - Py_XDECREF(repr); + if (igraphmodule_PyObject_to_edge_type_sw_t(edge_types_o, &allowed_edge_types)) + return NULL; /* methods */ - repr = PyObject_Str(method_o); - if (PyUnicode_CompareWithASCIIString(repr, "smallest") == 0) - method = IGRAPH_REALIZE_DEGSEQ_SMALLEST; - else if (PyUnicode_CompareWithASCIIString(repr, "largest") == 0) - method = IGRAPH_REALIZE_DEGSEQ_LARGEST; - else if (PyUnicode_CompareWithASCIIString(repr, "index") == 0) - method = IGRAPH_REALIZE_DEGSEQ_INDEX; - else { - Py_XDECREF(repr); - PyErr_SetString(PyExc_ValueError, "method must be 'smallest', 'largest', or 'index'"); + if (igraphmodule_PyObject_to_realize_degseq_t(method_o, &method)) return NULL; - } - Py_XDECREF(repr); /* Outdegree vector */ if (igraphmodule_PyObject_to_vector_t(outdeg_o, &outdeg, 0)) From 0efc6c17b9897f956f1bf47ea7c93dee78f8b062 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 18:26:39 +1000 Subject: [PATCH 0470/1892] Add strict PyObject to enum conversion --- src/_igraph/convert.c | 57 +++++++++++++++++++++++++++++++++++++++---- src/_igraph/convert.h | 2 ++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index d694ff57c..9a2f9f80c 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -118,6 +118,56 @@ int igraphmodule_PyObject_to_enum(PyObject *o, return -1; } + +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to a corresponding igraph enum, strictly. + * + * The numeric value is returned as an integer that must be converted + * explicitly to the corresponding igraph enum type. This is to allow one + * to use the same common conversion routine for multiple enum types. + * + * \param o a Python object to be converted + * \param translation the translation table between strings and the + * enum values. Strings are treated as case-insensitive, but it is + * assumed that the translation table keys are lowercase. The last + * entry of the table must contain NULL values. + * \param result the result is returned here. The default value must be + * passed in before calling this function, since this value is + * returned untouched if the given Python object is Py_None. + * \return 0 if everything is OK, 1 otherwise. An appropriate exception + * is raised in this case. + */ +int igraphmodule_PyObject_to_enum_strict(PyObject *o, + igraphmodule_enum_translation_table_entry_t* table, + int *result) { + char *s; + + if (o == 0 || o == Py_None) + return 0; + if (PyLong_Check(o)) + return PyLong_AsInt(o, result); + s = PyUnicode_CopyAsString(o); + if (s == 0) { + PyErr_SetString(PyExc_TypeError, "int, long or string expected"); + return -1; + } + /* Do NOT convert string to lowercase */ + /* Search for exact matches */ + while (table->name != 0) { + if (strcmp(s, table->name) == 0) { + *result = table->value; + free(s); + return 0; + } + table++; + } + free(s); + PyErr_SetObject(PyExc_ValueError, o); + return -1; +} + + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_neimode_t @@ -3039,7 +3089,7 @@ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t * {0,0} }; - return igraphmodule_PyObject_to_enum(o, edge_type_sw_tt, (int*)result); + return igraphmodule_PyObject_to_enum_strict(o, edge_type_sw_tt, (int*)result); } /** @@ -3054,8 +3104,5 @@ int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq {0,0} }; - return igraphmodule_PyObject_to_enum(o, realize_degseq_tt, (int*)result); + return igraphmodule_PyObject_to_enum_strict(o, realize_degseq_tt, (int*)result); } - - - diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 0d1d117a8..24af08abf 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -47,6 +47,8 @@ int PyLong_AsInt(PyObject* obj, int* result); int igraphmodule_PyObject_to_enum(PyObject *o, igraphmodule_enum_translation_table_entry_t *table, int *result); +int igraphmodule_PyObject_to_enum_strict(PyObject *o, + igraphmodule_enum_translation_table_entry_t *table, int *result); int igraphmodule_PyObject_to_add_weights_t(PyObject *o, igraph_add_weights_t *result); int igraphmodule_PyObject_to_adjacency_t(PyObject *o, igraph_adjacency_t *result); int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, From d639eff315a64bf1046930860e39902000fed19c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 18:33:17 +1000 Subject: [PATCH 0471/1892] Restore case-insensitivity --- src/_igraph/convert.c | 6 ++++-- tests/test_generators.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 9a2f9f80c..2ceb9973a 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -141,7 +141,7 @@ int igraphmodule_PyObject_to_enum(PyObject *o, int igraphmodule_PyObject_to_enum_strict(PyObject *o, igraphmodule_enum_translation_table_entry_t* table, int *result) { - char *s; + char *s, *s2; if (o == 0 || o == Py_None) return 0; @@ -152,7 +152,9 @@ int igraphmodule_PyObject_to_enum_strict(PyObject *o, PyErr_SetString(PyExc_TypeError, "int, long or string expected"); return -1; } - /* Do NOT convert string to lowercase */ + /* Convert string to lowercase */ + for (s2=s; *s2; s2++) + *s2 = tolower(*s2); /* Search for exact matches */ while (table->name != 0) { if (strcmp(s, table->name) == 0) { diff --git a/tests/test_generators.py b/tests/test_generators.py index b9bf37301..49d515df9 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -135,8 +135,9 @@ def testLCF(self): self.assertRaises(InternalError, Graph.LCF, 12, (5, -5), -3) def testRealizeDegreeSequence(self): + # Test case insensitivity of options too g = Graph.Realize_Degree_Sequence( - [1, 1], None, "simple_sw", "smallest", + [1, 1], None, "simple_SW", "smallest", ) self.assertFalse(g.is_directed()) From 6a99a6ca34d74c588d9359f52e74a4a37f48d9f8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 19 Apr 2021 13:50:38 +0200 Subject: [PATCH 0472/1892] minor tweaks to Realize_Degree_Sequence(), extended tests --- src/_igraph/convert.c | 8 +++--- src/_igraph/graphobject.c | 50 ++++++++++++++++++++--------------- tests/test_generators.py | 55 ++++++++++++++++++++++++++------------- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 2ceb9973a..52adff732 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3084,10 +3084,10 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t */ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result) { static igraphmodule_enum_translation_table_entry_t edge_type_sw_tt[] = { - {"simple_sw", IGRAPH_SIMPLE_SW}, - {"loops_sw", IGRAPH_LOOPS_SW}, - {"multi_sw", IGRAPH_MULTI_SW}, - {"both_sw", IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW}, + {"simple", IGRAPH_SIMPLE_SW}, + {"loops", IGRAPH_LOOPS_SW}, + {"multi", IGRAPH_MULTI_SW}, + {"all", IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW}, {0,0} }; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 5bf29bc19..e45127ed7 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2801,14 +2801,15 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, igraph_vector_t outdeg, indeg; igraph_vector_t *indegp = 0; - igraph_edge_type_sw_t allowed_edge_types; - igraph_realize_degseq_t method; - PyObject *outdeg_o, *indeg_o, *edge_types_o, *method_o; + igraph_edge_type_sw_t allowed_edge_types = IGRAPH_SIMPLE_SW; + igraph_realize_degseq_t method = IGRAPH_REALIZE_DEGSEQ_SMALLEST; + PyObject *outdeg_o, *indeg_o = Py_None; + PyObject *edge_types_o = Py_None, *method_o = Py_None; igraphmodule_GraphObject *self; igraph_t g; - static char *kwlist[] = { "outdeg", "indeg", "allowed_edge_types", "method", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOO", kwlist, + static char *kwlist[] = { "out", "in_", "allowed_edge_types", "method", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &outdeg_o, &indeg_o, &edge_types_o, &method_o)) return NULL; @@ -12668,22 +12669,29 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"Realize_Degree_Sequence", (PyCFunction) igraphmodule_Graph_Realize_Degree_Sequence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Realize_Degree_Sequence(outdeg, indeg, allowed_edge_types, method)\n--\n\n" - "Generates a graph from a degree sequence.\n\n" - "@param outdeg: the degree sequence of an undirected graph (if indeg=None), " - "or the out-degree sequence of a directed graph.\n" - "@param indeg: None to generate an undirected graph, the in-degree sequence " - "to generate a directed graph.\n" - "@param allowed_edge_types: for directed graphs, only 'simple_sw' is currently \n" - "implemented. Possible values for undirected graphs are\n" - " - 'simple_sw: simple graphs (no self-loops, no multi-edges)\n" - " - 'loops_sw': single self-loops allowed, but not multi-edges \n" - " - 'multi_sw': multi-edges allowed, but not self-loops \n" - " - 'both_sw': multi-edges and self-loops allowed \n" - "@param method: possible values are\n" - " - 'smallest': The vertex with smallest remaining degree first.\n" - " - 'largest': The vertex with the largest remaining degree first.\n" - " - 'index': The vertices are selected in order of their index.\n" + "Realize_Degree_Sequence(out, in_=None, allowed_edge_types=\"simple\", method=\"smallest\")\n--\n\n" + "Generates a graph from a degree sequence.\n" + "\n" + "@param outdeg: the degree sequence of an undirected graph (if indeg=None),\n" + " or the out-degree sequence of a directed graph.\n" + "@param indeg: None to generate an undirected graph, the in-degree sequence\n" + " to generate a directed graph.\n" + "@param allowed_edge_types: controls whether loops or multi-edges are allowed\n" + " during the generation process. Note that not all combinations are supported\n" + " for all types of graphs; an exception will be raised for unsupported\n" + " combinations. Possible values are:\n" + "\n" + " - C{simple}: simple graphs (no self-loops, no multi-edges)\n" + " - C{loops}: single self-loops allowed, but not multi-edges\n" + " - C{multi}: multi-edges allowed, but not self-loops\n" + " - C{all}: multi-edges and self-loops allowed\n" + "\n" + "@param method: controls how the vertices are selected during the generation\n" + " process. Possible values are:\n" + "\n" + " - C{smallest}: The vertex with smallest remaining degree first.\n" + " - C{largest}: The vertex with the largest remaining degree first.\n" + " - C{index}: The vertices are selected in order of their index.\n" }, // interface to igraph_ring diff --git a/tests/test_generators.py b/tests/test_generators.py index 49d515df9..77ce8023b 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -1,5 +1,6 @@ import unittest -from igraph import * + +from igraph import Graph, InternalError try: @@ -137,51 +138,69 @@ def testLCF(self): def testRealizeDegreeSequence(self): # Test case insensitivity of options too g = Graph.Realize_Degree_Sequence( - [1, 1], None, "simple_SW", "smallest", + [1, 1], None, "simPLE", "smallest", ) self.assertFalse(g.is_directed()) + self.assertTrue(g.degree() == [1, 1]) # Not implemented, should fail - self.assertRaises(NotImplementedError, Graph.Realize_Degree_Sequence, - [1, 1], None, "loops_sw", "largest") + self.assertRaises( + NotImplementedError, Graph.Realize_Degree_Sequence, + [1, 1], None, "loops", "largest" + ) g = Graph.Realize_Degree_Sequence( - [1, 1], None, "both_sw", "largest", + [1, 1], None, "all", "largest", ) self.assertFalse(g.is_directed()) + self.assertTrue(g.degree() == [1, 1]) g = Graph.Realize_Degree_Sequence( - [1, 1], None, "multi_sw", "index", + [1, 1], None, "multi", "index", ) self.assertFalse(g.is_directed()) + self.assertTrue(g.degree() == [1, 1]) g = Graph.Realize_Degree_Sequence( - [1, 1], [1, 1], "simple_sw", "largest", + [1, 1], [1, 1], "simple", "largest", ) self.assertTrue(g.is_directed()) + self.assertTrue(g.indegree() == [1, 1]) + self.assertTrue(g.outdegree() == [1, 1]) # Not implemented, should fail - self.assertRaises(NotImplementedError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "multi_sw", "largest") - - self.assertRaises(ValueError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "should_fail", "index") - self.assertRaises(ValueError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "multi_sw", "should_fail") + self.assertRaises( + NotImplementedError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "multi", "largest" + ) + self.assertRaises( + ValueError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "should_fail", "index" + ) + self.assertRaises( + ValueError, Graph.Realize_Degree_Sequence, + [1, 1], [1, 1], "multi", "should_fail" + ) + # Degree sequence of Zachary karate club, using optional arguments + zachary = Graph.Famous("zachary") + degrees = zachary.degree() + g = Graph.Realize_Degree_Sequence(degrees) + self.assertFalse(g.is_directed()) + self.assertTrue(g.degree() == degrees) def testKautz(self): g = Graph.Kautz(2, 2) - deg_in = g.degree(mode=IN) - deg_out = g.degree(mode=OUT) + deg_in = g.degree(mode="in") + deg_out = g.degree(mode="out") # This is not a proper test, but should spot most errors self.assertTrue(g.is_directed() and deg_in == [2] * 12 and deg_out == [2] * 12) def testDeBruijn(self): g = Graph.De_Bruijn(2, 3) - deg_in = g.degree(mode=IN, loops=True) - deg_out = g.degree(mode=OUT, loops=True) + deg_in = g.degree(mode="in", loops=True) + deg_out = g.degree(mode="out", loops=True) # This is not a proper test, but should spot most errors self.assertTrue(g.is_directed() and deg_in == [2] * 8 and deg_out == [2] * 8) From db032acbcfcfb7b21ab4806e1e1da6853ae4ac50 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 19 Apr 2021 13:51:59 +0200 Subject: [PATCH 0473/1892] chore: bumped igraph to 0.9.2 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 213abc889..7cf14dd11 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 213abc889d360775dfd0c11a406e859827c6dec8 +Subproject commit 7cf14dd11cd1784f6dc12d4e59464350f8f66608 From 7bc508692ed9f5dbb8d567c9d1767ccddcf70d84 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 19 Apr 2021 13:58:37 +0200 Subject: [PATCH 0474/1892] doc: mention that Realize_Degree_Sequence uses a Havel-Hakimi-style generation process --- src/_igraph/graphobject.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e45127ed7..722fb6d50 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12672,6 +12672,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Realize_Degree_Sequence(out, in_=None, allowed_edge_types=\"simple\", method=\"smallest\")\n--\n\n" "Generates a graph from a degree sequence.\n" "\n" + "This method implements a Havel-Hakimi style graph construction from a given\n" + "degree sequence. In each step, the algorithm picks two vertices in a\n" + "deterministic manner and connects them. The way the vertices are picked is\n" + "defined by the C{method} parameter. The allowed edge types (i.e. whether\n" + "multiple or loop edges are allowed) are specified in the C{allowed_edge_types}\n" + "parameter.\n" + "\n" "@param outdeg: the degree sequence of an undirected graph (if indeg=None),\n" " or the out-degree sequence of a directed graph.\n" "@param indeg: None to generate an undirected graph, the in-degree sequence\n" From 6d4059e0569a3dc7625e5c21c2e02db974b9b66e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 09:37:32 +1000 Subject: [PATCH 0475/1892] First version, passes tests --- doc/source/generation.rst | 1 + src/_igraph/graphobject.c | 66 +++++++++++++++++++++++++++++++++++++- src/_igraph/graphobject.h | 1 + src/_igraph/igraphmodule.c | 3 ++ src/igraph/__init__.py | 2 ++ tests/test_games.py | 9 ++++++ 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 4659406a1..d41da27d4 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -148,6 +148,7 @@ Stochastic graphs can be created according to several different models or games: - Erdos-Renyi: :meth:`Graph.Erdos_Renyi` - Watts-Strogatz :meth:`Graph.Watts_Strogatz` - stochastic block model :meth:`Graph.SBM` + - random tree :meth:`Graph.Tree_Game` - forest fire game :meth:`Graph.Forest_Fire` - random geometric graph :meth:`Graph.GRG` - growing :meth:`Graph.Growing_Random` diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 722fb6d50..c118c3b62 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -674,7 +674,7 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, } /********************************************************************** - * tructural properties * + * structural properties * **********************************************************************/ /** \ingroup python_interface_graph @@ -3462,6 +3462,60 @@ PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, return (PyObject *) self; } +/** \ingroup python_interface_graph + * \brief Generates a random tree using one of a few methods. + * + * This method has three parameters: + * - n is the number of nodes in the tree. + * - directed is a bool that specifies if the edges should be directed. If so, they + * point away from the root. + * - method is one of: + * - igraph.RANDOM_TREE_PRUFER (Prufer, directed currently unsupported) + * - igraph.RANDOM_TREE_LERW (loop-erased random walk) + * + * \return a reference to the newly generated Python igraph object + * \sa igraph_tree + */ +PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, + PyObject * args, PyObject * kwds) +{ + long int n, directed_o, tree_method_o; + igraphmodule_GraphObject *self; + igraph_t g; + + static char *kwlist[] = { "n", "directed", "method", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "lll", kwlist, + &n, &directed_o, &tree_method_o)) + return NULL; + + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); + return NULL; + } + + switch(tree_method_o) { + case IGRAPH_RANDOM_TREE_PRUFER: + case IGRAPH_RANDOM_TREE_LERW: + break; + default: + PyErr_SetString(PyExc_ValueError, + "Tree method must be igraph.RANDOM_TREE_PRUFER or igraph.RANDOM_TREE_LERW"); + return NULL; + } + + /* The C function takes care of the unsupported case (Prufer/directed) */ + if (igraph_tree_game(&g, (igraph_integer_t) n, (igraph_bool_t) directed_o, + tree_method_o)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + CREATE_GRAPH_FROM_TYPE(self, g, type); + + return (PyObject *) self; +} + /** \ingroup python_interface_graph * \brief Generates a graph based on the Watts-Strogatz model * \return a reference to the newly generated Python igraph object @@ -12821,6 +12875,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param cls: the isomorphism class\n" "@param directed: whether the graph should be directed.\n"}, + /* interface to igraph_tree_game */ + {"Tree_Game", (PyCFunction) igraphmodule_Graph_Tree_Game, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "Tree_Game(n, directed, method)\n--\n\n" + "Generates a random tree.\n\n" + "@param n: the number of vertices in the tree\n" + "@param directed: whether the graph should be directed.\n" + "@param method: one of RANDOM_TREE_PRUFER or RANDOM_TREE_LERW.\n" + }, + /* interface to igraph_watts_strogatz_game */ {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, METH_VARARGS | METH_CLASS | METH_KEYWORDS, diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 3ab836942..d9d3c1fc8 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -99,6 +99,7 @@ PyObject* igraphmodule_Graph_Ring(PyTypeObject *type, PyObject *args, PyObject * PyObject* igraphmodule_Graph_SBM(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Star(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Tree(PyTypeObject *type, PyObject *args, PyObject *kwds); +PyObject* igraphmodule_Graph_Tree_Game(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_Watts_Strogatz(PyTypeObject *type, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_is_connected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index ea3661c3f..77d087dcc 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -904,6 +904,9 @@ PyObject* PyInit__igraph(void) PyModule_AddIntConstant(m, "LOOPS_SW", IGRAPH_LOOPS_SW); PyModule_AddIntConstant(m, "MULTI_SW", IGRAPH_MULTI_SW); + PyModule_AddIntConstant(m, "RANDOM_TREE_PRUFER", IGRAPH_RANDOM_TREE_PRUFER); + PyModule_AddIntConstant(m, "RANDOM_TREE_LERW", IGRAPH_RANDOM_TREE_LERW); + /* More useful constants */ { const char* version; diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 547c56a85..32417afa3 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -50,6 +50,8 @@ IN, InternalError, OUT, + RANDOM_TREE_PRUFER, + RANDOM_TREE_LERW, REWIRING_SIMPLE, REWIRING_SIMPLE_LOOPS, STAR_IN, diff --git a/tests/test_games.py b/tests/test_games.py index 0af5b9aa2..1d50ef672 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -45,6 +45,15 @@ def testAsymmetricPreference(self): g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]]) self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 1) + def testTreeGame(self): + # Prufer algorithm + g = Graph.Tree_Game(10, False, RANDOM_TREE_PRUFER) + self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + + # LERW algorithm + g = Graph.Tree_Game(10, False, RANDOM_TREE_LERW) + self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + def testWattsStrogatz(self): g = Graph.Watts_Strogatz(1, 20, 1, 0.2) self.assertTrue(isinstance(g, Graph) and g.vcount() == 20 and g.ecount() == 20) From 69e3e1f049729936a58cfcdc24cff8688253c465 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 19 Apr 2021 09:48:41 +1000 Subject: [PATCH 0476/1892] One more test that fails if Prufer + directed is chosen --- tests/test_games.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_games.py b/tests/test_games.py index 1d50ef672..a920d42a9 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -50,6 +50,9 @@ def testTreeGame(self): g = Graph.Tree_Game(10, False, RANDOM_TREE_PRUFER) self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + # Prufer with directed (should fail) + self.assertRaises(InternalError, Graph.Tree_Game, 10, True, RANDOM_TREE_PRUFER) + # LERW algorithm g = Graph.Tree_Game(10, False, RANDOM_TREE_LERW) self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) From 61c3428b8cb317a5690bd46fd56a33887ea2879f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 20 Apr 2021 08:11:19 +1000 Subject: [PATCH 0477/1892] Rebase on top of strict conversion function --- src/_igraph/convert.c | 15 +++++++++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 30 ++++++++++++++---------------- src/_igraph/igraphmodule.c | 3 --- src/igraph/__init__.py | 2 -- tests/test_games.py | 6 +++--- 6 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 52adff732..48277893f 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3108,3 +3108,18 @@ int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq return igraphmodule_PyObject_to_enum_strict(o, realize_degseq_tt, (int*)result); } + +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_random_tree_t + */ +int igraphmodule_PyObject_to_random_tree_t(PyObject *o, igraph_random_tree_t *result) { + static igraphmodule_enum_translation_table_entry_t random_tree_tt[] = { + {"prufer", IGRAPH_RANDOM_TREE_PRUFER}, + {"lerw", IGRAPH_RANDOM_TREE_LERW}, + {0,0} + }; + + return igraphmodule_PyObject_to_enum_strict(o, random_tree_tt, (int*)result); +} + diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 24af08abf..19cd98500 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -67,6 +67,7 @@ int igraphmodule_PyObject_to_neimode_t(PyObject *o, igraph_neimode_t *result); int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t *result); int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result); int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq_t *result); +int igraphmodule_PyObject_to_random_tree_t(PyObject *o, igraph_random_tree_t *result); int igraphmodule_PyObject_to_random_walk_stuck_t(PyObject *o, igraph_random_walk_stuck_t *result); int igraphmodule_PyObject_to_reciprocity_t(PyObject *o, igraph_reciprocity_t *result); int igraphmodule_PyObject_to_rewiring_t(PyObject *o, igraph_rewiring_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index c118c3b62..dddbf0fa9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3470,8 +3470,9 @@ PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, * - directed is a bool that specifies if the edges should be directed. If so, they * point away from the root. * - method is one of: - * - igraph.RANDOM_TREE_PRUFER (Prufer, directed currently unsupported) - * - igraph.RANDOM_TREE_LERW (loop-erased random walk) + * - 'Prufer' aka sample Pruefer sequences and convert to trees. + * - 'lerw' aka loop-erased random walk on the complete graph to sample spanning + * trees. * * \return a reference to the newly generated Python igraph object * \sa igraph_tree @@ -3479,13 +3480,16 @@ PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long int n, directed_o, tree_method_o; + long int n; + PyObject *directed_o, *tree_method_o; + igraph_bool_t directed; + igraph_random_tree_t tree_method; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "directed", "method", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lll", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "lOO", kwlist, &n, &directed_o, &tree_method_o)) return NULL; @@ -3494,19 +3498,13 @@ PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, return NULL; } - switch(tree_method_o) { - case IGRAPH_RANDOM_TREE_PRUFER: - case IGRAPH_RANDOM_TREE_LERW: - break; - default: - PyErr_SetString(PyExc_ValueError, - "Tree method must be igraph.RANDOM_TREE_PRUFER or igraph.RANDOM_TREE_LERW"); + directed = PyObject_IsTrue(directed_o); + + if (igraphmodule_PyObject_to_random_tree_t(tree_method_o, &tree_method)) return NULL; - } - /* The C function takes care of the unsupported case (Prufer/directed) */ - if (igraph_tree_game(&g, (igraph_integer_t) n, (igraph_bool_t) directed_o, - tree_method_o)) { + if (igraph_tree_game(&g, (igraph_integer_t) n, directed, + tree_method)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -12882,7 +12880,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Generates a random tree.\n\n" "@param n: the number of vertices in the tree\n" "@param directed: whether the graph should be directed.\n" - "@param method: one of RANDOM_TREE_PRUFER or RANDOM_TREE_LERW.\n" + "@param method: one of 'Prufer' or 'lerw'.\n" }, /* interface to igraph_watts_strogatz_game */ diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 77d087dcc..ea3661c3f 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -904,9 +904,6 @@ PyObject* PyInit__igraph(void) PyModule_AddIntConstant(m, "LOOPS_SW", IGRAPH_LOOPS_SW); PyModule_AddIntConstant(m, "MULTI_SW", IGRAPH_MULTI_SW); - PyModule_AddIntConstant(m, "RANDOM_TREE_PRUFER", IGRAPH_RANDOM_TREE_PRUFER); - PyModule_AddIntConstant(m, "RANDOM_TREE_LERW", IGRAPH_RANDOM_TREE_LERW); - /* More useful constants */ { const char* version; diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 32417afa3..547c56a85 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -50,8 +50,6 @@ IN, InternalError, OUT, - RANDOM_TREE_PRUFER, - RANDOM_TREE_LERW, REWIRING_SIMPLE, REWIRING_SIMPLE_LOOPS, STAR_IN, diff --git a/tests/test_games.py b/tests/test_games.py index a920d42a9..40a4d50f7 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -47,14 +47,14 @@ def testAsymmetricPreference(self): def testTreeGame(self): # Prufer algorithm - g = Graph.Tree_Game(10, False, RANDOM_TREE_PRUFER) + g = Graph.Tree_Game(10, False, "Prufer") self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) # Prufer with directed (should fail) - self.assertRaises(InternalError, Graph.Tree_Game, 10, True, RANDOM_TREE_PRUFER) + self.assertRaises(InternalError, Graph.Tree_Game, 10, True, "Prufer") # LERW algorithm - g = Graph.Tree_Game(10, False, RANDOM_TREE_LERW) + g = Graph.Tree_Game(10, False, "lerw") self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) def testWattsStrogatz(self): From f91bfd229b09f1ad6235f9b9a8fffe851d97d88e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 20 Apr 2021 15:52:26 +0200 Subject: [PATCH 0478/1892] feat: added Graph.is_tree() --- src/_igraph/graphobject.c | 88 ++++++++++++++++++++++++++++++++------- tests/test_structural.py | 40 ++++++++++++++++++ 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index dddbf0fa9..8c348dde1 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -536,6 +536,40 @@ PyObject *igraphmodule_Graph_is_simple(igraphmodule_GraphObject *self) { Py_RETURN_FALSE; } + +/** \ingroup python_interface_graph + * \brief Determines whether a graph is a (directed or undirected) tree + * \sa igraph_is_tree + */ +PyObject *igraphmodule_Graph_is_tree(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + static char *kwlist[] = { "mode", NULL }; + PyObject *mode_o = Py_None; + igraph_neimode_t mode = IGRAPH_OUT; + igraph_bool_t result; + int retval; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) { + return NULL; + } + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { + return NULL; + } + + if (igraph_is_tree(&self->g, &result, /* root = */ 0, mode)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (result) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + /** \ingroup python_interface_graph * \brief Adds vertices to an \c igraph.Graph * \return the extended \c igraph.Graph object @@ -674,7 +708,7 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, } /********************************************************************** - * structural properties * + * Structural properties * **********************************************************************/ /** \ingroup python_interface_graph @@ -3478,18 +3512,18 @@ PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, * \sa igraph_tree */ PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, - PyObject * args, PyObject * kwds) + PyObject * args, PyObject * kwds) { long int n; - PyObject *directed_o, *tree_method_o; + PyObject *directed_o = Py_False, *tree_method_o = Py_None; igraph_bool_t directed; - igraph_random_tree_t tree_method; + igraph_random_tree_t tree_method = IGRAPH_RANDOM_TREE_LERW; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "directed", "method", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|OO", kwlist, &n, &directed_o, &tree_method_o)) return NULL; @@ -12124,7 +12158,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: C{True} if it is directed, C{False} otherwise.\n" "@rtype: boolean"}, - // interface to igraph_is_simple + /* interface to igraph_is_simple */ {"is_simple", (PyCFunction) igraphmodule_Graph_is_simple, METH_NOARGS, "is_simple()\n--\n\n" @@ -12132,6 +12166,22 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: C{True} if it is simple, C{False} otherwise.\n" "@rtype: boolean"}, + /* interface to igraph_is_tree */ + {"is_tree", (PyCFunction) igraphmodule_Graph_is_tree, + METH_VARARGS | METH_KEYWORDS, + "is_tree(mode=\"out\")\n--\n\n" + "Checks whether the graph is a (directed or undirected) tree graph.\n\n" + "For directed trees, the function may require that the edges are oriented\n" + "outwards from the root or inwards to the root, depending on the value\n" + "of the C{mode} argument.\n\n" + "@param mode: for directed graphs, specifies how the edge directions\n" + " should be taken into account. C{\"all\"} means that the edge directions\n" + " must be ignored, C{\"out\"} means that the edges must be oriented away\n" + " from the root, C{\"in\"} means that the edges must be oriented\n" + " towards the root. Ignored for undirected graphs.\n" + "@return: C{True} if the graph is a tree, C{False} otherwise.\n" + "@rtype: boolean"}, + /* interface to igraph_add_vertices */ {"add_vertices", (PyCFunction) igraphmodule_Graph_add_vertices, METH_VARARGS, @@ -12740,10 +12790,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " for all types of graphs; an exception will be raised for unsupported\n" " combinations. Possible values are:\n" "\n" - " - C{simple}: simple graphs (no self-loops, no multi-edges)\n" - " - C{loops}: single self-loops allowed, but not multi-edges\n" - " - C{multi}: multi-edges allowed, but not self-loops\n" - " - C{all}: multi-edges and self-loops allowed\n" + " - C{\"simple\"}: simple graphs (no self-loops, no multi-edges)\n" + " - C{\"loops\"}: single self-loops allowed, but not multi-edges\n" + " - C{\"multi\"}: multi-edges allowed, but not self-loops\n" + " - C{\"all\"}: multi-edges and self-loops allowed\n" "\n" "@param method: controls how the vertices are selected during the generation\n" " process. Possible values are:\n" @@ -12876,12 +12926,20 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_tree_game */ {"Tree_Game", (PyCFunction) igraphmodule_Graph_Tree_Game, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Tree_Game(n, directed, method)\n--\n\n" - "Generates a random tree.\n\n" + "Tree_Game(n, directed=False, method=\"lerw\")\n--\n\n" + "Generates a random tree by sampling uniformly from the set of labelled\n" + "trees with a given number of nodes.\n\n" "@param n: the number of vertices in the tree\n" - "@param directed: whether the graph should be directed.\n" - "@param method: one of 'Prufer' or 'lerw'.\n" - }, + "@param directed: whether the graph should be directed\n" + "@param method: the generation method to be used. One of the following:\n" + " \n" + " - C{\"prufer\"} -- samples Prufer sequences uniformly, then converts\n" + " them to trees\n" + " - C{\"lerw\"} -- performs a loop-erased random walk on the complete\n" + " graph to uniformly sample its spanning trees (Wilson's algorithm).\n" + " This is the default choice as it supports both directed and\n" + " undirected graphs.\n" + }, /* interface to igraph_watts_strogatz_game */ {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, diff --git a/tests/test_structural.py b/tests/test_structural.py index 148cf8539..545733d1e 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -527,6 +527,46 @@ def testIsDAG(self): g = Graph.Ring(10, directed=True, mutual=False) self.assertFalse(g.is_dag()) + def testIsTree(self): + g = Graph() + self.assertFalse(g.is_tree()) + + g = Graph(directed=True) + self.assertFalse(g.is_tree()) + + g = Graph(1) + self.assertTrue(g.is_tree()) + + g = Graph(1, directed=True) + self.assertTrue(g.is_tree() and g.is_tree("out") and g.is_tree("in") and g.is_tree("all")) + + g = Graph(5, [(0, 1), (1, 2), (1, 3), (3, 4)]) + self.assertTrue(g.is_tree()) + + g = Graph(5, [(0, 1), (1, 2), (1, 3), (3, 4)], directed=True) + self.assertTrue(g.is_tree()) + self.assertTrue(g.is_tree("out")) + self.assertFalse(g.is_tree("in")) + self.assertTrue(g.is_tree("all")) + + g = Graph(5, [(0, 1), (1, 2), (3, 1), (3, 4)], directed=True) + self.assertFalse(g.is_tree()) + self.assertFalse(g.is_tree("in")) + self.assertFalse(g.is_tree("out")) + self.assertTrue(g.is_tree("all")) + + g = Graph(6, [(0, 4), (1, 5), (2, 1), (3, 1), (4, 3)], directed=True) + self.assertFalse(g.is_tree()) + self.assertTrue(g.is_tree("in")) + self.assertFalse(g.is_tree("out")) + self.assertTrue(g.is_tree("all")) + + g = Graph.Ring(10) + self.assertFalse( + g.is_tree() or g.is_tree("in") or g.is_tree("out") or + g.is_tree("all") + ) + def testLineGraph(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) el = g.linegraph().get_edgelist() From ee2f7be35812df608142c36a2832cba7c818c2dc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 20 Apr 2021 15:52:47 +0200 Subject: [PATCH 0479/1892] test: extended Tree_Game() tests with checks that validate whether the graph is indeed a tree --- tests/test_games.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_games.py b/tests/test_games.py index 40a4d50f7..5b1a35ed1 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -49,6 +49,8 @@ def testTreeGame(self): # Prufer algorithm g = Graph.Tree_Game(10, False, "Prufer") self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + self.assertFalse(g.is_directed()) + self.assertTrue(g.is_tree()) # Prufer with directed (should fail) self.assertRaises(InternalError, Graph.Tree_Game, 10, True, "Prufer") @@ -56,6 +58,20 @@ def testTreeGame(self): # LERW algorithm g = Graph.Tree_Game(10, False, "lerw") self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + self.assertFalse(g.is_directed()) + self.assertTrue(g.is_tree()) + + # Omitting the algorithm should default to LERW + g = Graph.Tree_Game(10, directed=True) + self.assertTrue(isinstance(g, Graph) and g.vcount() == 10) + self.assertTrue(g.is_directed()) + self.assertTrue(g.is_tree()) + + # Omitting the directed argument should use undirected graphs + g = Graph.Tree_Game(42, method="Prufer") + self.assertTrue(isinstance(g, Graph) and g.vcount() == 42) + self.assertFalse(g.is_directed()) + self.assertTrue(g.is_tree()) def testWattsStrogatz(self): g = Graph.Watts_Strogatz(1, 20, 1, 0.2) From 4578205f1a86cec1243ab70dca905ba6315b21f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 20 Apr 2021 15:56:11 +0200 Subject: [PATCH 0480/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8fea258e..613abf7bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # igraph Python interface changelog +## Unreleased + +### Added + +* Added `Graph.is_tree()` to test whether a graph is a tree. + +* Added `Graph.Realize_Degree_Sequence()` to construct a graph that realizes a + given degree sequence, using a deterministic (Havel-Hakimi-style) algorithm. + +* Added `Graph.Tree_Game()` to generate random trees with uniform sampling. + ## 0.9.1 ### Changed From fab33f15ebf094399123beed0b0286bf31a63f8d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 15:06:24 +0200 Subject: [PATCH 0481/1892] feat: trying to support Apple Silicon (arm64) wheels via cibuildwheel --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7cd1e6844..2e2683e2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,6 +64,7 @@ jobs: - name: Build wheels uses: joerick/cibuildwheel@v1.10.0 env: + CIBW_ARCHS_MACOS: "x86_64 arm64" CIBW_BEFORE_BUILD: "python setup.py build_c_core" - uses: actions/upload-artifact@v2 From ea91cc99b9a77d61daab4469daec0cae7dce89bc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 15:52:38 +0200 Subject: [PATCH 0482/1892] fix: handle build failures in the C core of igraph properly --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index ffa7dedac..37c34702f 100644 --- a/setup.py +++ b/setup.py @@ -571,6 +571,11 @@ def compile_igraph_from_vendor_source(self): finally: os.chdir(cwd) + if libraries is False: + print("Build failed for the C core of igraph.") + print("") + return False + igraph_builder.create_build_config_file(install_folder, libraries) self.use_vendored_igraph() From c789bebec1705dd420aa158f206dd192142719f8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 16:14:59 +0200 Subject: [PATCH 0483/1892] exit when building the C core fails --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 37c34702f..5f2e4a5b0 100644 --- a/setup.py +++ b/setup.py @@ -574,7 +574,7 @@ def compile_igraph_from_vendor_source(self): if libraries is False: print("Build failed for the C core of igraph.") print("") - return False + sys.exit(1) igraph_builder.create_build_config_file(install_folder, libraries) From fce6e1a6422297426b27cc79fefb95f8cfed1b5b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 16:17:02 +0200 Subject: [PATCH 0484/1892] fix: remove unused variable --- src/_igraph/graphobject.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8c348dde1..6dc02cfff 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -548,7 +548,6 @@ PyObject *igraphmodule_Graph_is_tree(igraphmodule_GraphObject * self, PyObject *mode_o = Py_None; igraph_neimode_t mode = IGRAPH_OUT; igraph_bool_t result; - int retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) { return NULL; From 921ee3e2b4931027e58aa67dcbf70bd0a69628de Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 16:19:00 +0200 Subject: [PATCH 0485/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 7cf14dd11..9fdd510c2 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 7cf14dd11cd1784f6dc12d4e59464350f8f66608 +Subproject commit 9fdd510c257ccbc0919be2637de1f16d3bff57da From 2077777ae38a0feff9b037552af42e48708e4e18 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 1 May 2021 16:19:15 +0200 Subject: [PATCH 0486/1892] style: minor formatting in src/_igraph/attributes.c --- src/_igraph/attributes.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 191b9124b..7c4eb8749 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -820,9 +820,11 @@ static PyObject* igraphmodule_i_ac_func(PyObject* values, PyObject *res, *list, *item; res = PyList_New(len); + for (i = 0; i < len; i++) { igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int j, n = igraph_vector_size(v); + list = PyList_New(n); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -831,10 +833,12 @@ static PyObject* igraphmodule_i_ac_func(PyObject* values, } item = PyObject_CallFunctionObjArgs(func, list, 0); Py_DECREF(list); + if (item == 0) { Py_DECREF(res); return 0; } + PyList_SET_ITEM(res, i, item); /* reference to item stolen */ } @@ -1150,6 +1154,7 @@ static int igraphmodule_i_attribute_combine_dicts(PyObject *dict, Py_ssize_t pos; igraph_attribute_combination_record_t* todo; Py_ssize_t i, n; + if (!PyDict_Check(dict) || !PyDict_Check(newdict)) return 1; /* Allocate memory for the attribute_combination_records */ @@ -1282,8 +1287,8 @@ static int igraphmodule_i_attribute_combine_vertices(const igraph_t *graph, int result; /* Get the attribute dicts */ - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; - newdict=ATTR_STRUCT_DICT(newgraph)[ATTRHASH_IDX_VERTEX]; + dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; + newdict = ATTR_STRUCT_DICT(newgraph)[ATTRHASH_IDX_VERTEX]; /* Combine the attribute dicts */ result = igraphmodule_i_attribute_combine_dicts(dict, newdict, From 4632c99e34756fe771472ea16efd780a66c81ca2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 May 2021 18:20:53 +0200 Subject: [PATCH 0487/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 9fdd510c2..ecbe39a4e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 9fdd510c257ccbc0919be2637de1f16d3bff57da +Subproject commit ecbe39a4eb8d4319633e3e364fd72fe7fe9ae109 From 1d3a465232c88f8fc218f81a80aa38417ae6080e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 May 2021 21:01:02 +0200 Subject: [PATCH 0488/1892] ci: bump cibuildwheel action to v1.11.0 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e2683e2b..2c05589e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,7 +119,7 @@ jobs: shell: cmd - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v1.11.0 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From a310852c554b223aa23532d9fba502cb536f81a2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 May 2021 23:08:12 +0200 Subject: [PATCH 0489/1892] feat: updated minimal Docker image file; we don't need to compile igraph in Docker now --- docker/minimal/Dockerfile | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/docker/minimal/Dockerfile b/docker/minimal/Dockerfile index 7a598ebb4..d389de1d5 100644 --- a/docker/minimal/Dockerfile +++ b/docker/minimal/Dockerfile @@ -1,25 +1,8 @@ -FROM alpine:latest AS builder +FROM python:latest MAINTAINER Tamas Nepusz LABEL Description="Simple Docker image that contains a pre-compiled version of igraph's Python interface" -RUN apk add --no-cache --update \ - make gcc g++ libstdc++ git python3-dev libxslt-dev libxml2-dev libc-dev \ - libffi-dev zlib-dev py-pip libxml2 zlib libtool autoconf automake \ - flex bison \ - && rm -rf /var/cache/apk/* +RUN pip3 install python-igraph cairocffi -RUN pip3 install git+https://github.com/igraph/python-igraph -RUN pip3 install cairocffi - -FROM alpine:latest - -RUN apk add --no-cache --update \ - python3 libstdc++ libxml2 libxslt zlib cairo \ - && rm -rf /var/cache/apk/* - -COPY --from=builder /usr/lib/python3.7/site-packages/cairocffi /usr/lib/python3.7/site-packages/cairocffi -COPY --from=builder /usr/lib/python3.7/site-packages/igraph /usr/lib/python3.7/site-packages/igraph -COPY --from=builder /usr/bin/igraph /usr/bin - -CMD /usr/bin/igraph +CMD /usr/local/bin/igraph From 2054f463ec7454e01d17ff774d7ffc81b808803b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 14:25:30 +0200 Subject: [PATCH 0490/1892] fix: removed unneeded manylinux.docker file as we now use cibuildwheel in Github Actions --- .gitignore | 1 - docker/manylinux.docker | 28 ---------------------------- 2 files changed, 29 deletions(-) delete mode 100644 docker/manylinux.docker diff --git a/.gitignore b/.gitignore index a285acca8..918256eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ src/igraph/*.so .tox .venv/ .vscode/ -docker/wheelhouse vendor/build/ vendor/install/ Pipfile diff --git a/docker/manylinux.docker b/docker/manylinux.docker deleted file mode 100644 index 77d8ce18e..000000000 --- a/docker/manylinux.docker +++ /dev/null @@ -1,28 +0,0 @@ -# manylinux.docker -- dockerfile for generating manylinux wheel - -FROM quay.io/pypa/manylinux2010_x86_64 -MAINTAINER awinter.public@gmail.com - -RUN echo "multilib_policy=best" >> /etc/yum.conf -RUN yum install -y flex bison zlib-devel libxml2-devel -# kill static libxml2 as per http://lists.gnu.org/archive/html/igraph-help/2014-05/msg00045.html -# RUN mv /usr/lib64/libxml2.a /usr/lib64/libxml2.a.org - -COPY ./ /python-igraph/ -RUN mkdir /wheelhouse -WORKDIR /python-igraph - -# Do not create bytecode files -- this will make setup.py try to compile the C -# extension first, without compiling the C core. This should be fixed in -# setup.py later, though. -ENV PYTHONDONTWRITEBYTECODE=1 - -RUN /bin/bash -c "for PYBIN in /opt/python/*/bin; do \ - echo \$PYBIN; \ - \$PYBIN/pip wheel . -w /wheelhouse; \ -done" - -# Bundle external shared libraries into the wheels -RUN /bin/bash -c "for whl in /wheelhouse/*.whl; do \ - auditwheel repair \$whl -w /wheelhouse/; \ -done" From 2baed119aac8355d561876cbd383f34c5004ee3a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 18:19:04 +0200 Subject: [PATCH 0491/1892] feat: added more modes for Graph.to_directed(), closes #376 --- CHANGELOG.md | 6 +++++ src/_igraph/convert.c | 25 +++++++++++++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 50 +++++++++++++++++++++++++++----------- tests/test_conversion.py | 51 +++++++++++++++++++++++++++++++++++++-- 5 files changed, 117 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 613abf7bc..7d7a9f11c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ * Added `Graph.Tree_Game()` to generate random trees with uniform sampling. +* `Graph.to_directed()` now supports a `mode=...` keyword argument. + +### Deprecated + +* `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. + ## 0.9.1 ### Changed diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 48277893f..b9f0ad18d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -641,6 +641,31 @@ int igraphmodule_PyObject_to_subgraph_implementation_t(PyObject *o, return igraphmodule_PyObject_to_enum(o, subgraph_impl_tt, (int*)result); } +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_to_directed_t + */ +int igraphmodule_PyObject_to_to_directed_t(PyObject *o, + igraph_to_directed_t *result) { + static igraphmodule_enum_translation_table_entry_t to_directed_tt[] = { + {"acyclic", IGRAPH_TO_DIRECTED_ACYCLIC}, + {"arbitrary", IGRAPH_TO_DIRECTED_ARBITRARY}, + {"mutual", IGRAPH_TO_DIRECTED_MUTUAL}, + {"random", IGRAPH_TO_DIRECTED_RANDOM}, + {0,0} + }; + + if (o == Py_True) { + *result = IGRAPH_TO_DIRECTED_MUTUAL; + return 0; + } else if (o == Py_False) { + *result = IGRAPH_TO_DIRECTED_ARBITRARY; + return 0; + } + + return igraphmodule_PyObject_to_enum(o, to_directed_tt, (int*)result); +} + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_to_undirected_t diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 19cd98500..bff912b83 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -75,6 +75,7 @@ int igraphmodule_PyObject_to_spinglass_implementation_t(PyObject *o, igraph_spin int igraphmodule_PyObject_to_spincomm_update_t(PyObject *o, igraph_spincomm_update_t *result); int igraphmodule_PyObject_to_star_mode_t(PyObject *o, igraph_star_mode_t *result); int igraphmodule_PyObject_to_subgraph_implementation_t(PyObject *o, igraph_subgraph_implementation_t *result); +int igraphmodule_PyObject_to_to_directed_t(PyObject *o, igraph_to_directed_t *result); int igraphmodule_PyObject_to_to_undirected_t(PyObject *o, igraph_to_undirected_t *result); int igraphmodule_PyObject_to_transitivity_mode_t(PyObject *o, igraph_transitivity_mode_t *result); int igraphmodule_PyObject_to_tree_mode_t(PyObject *o, igraph_tree_mode_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 6dc02cfff..cacb41592 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -608,9 +608,9 @@ PyObject *igraphmodule_Graph_delete_vertices(igraphmodule_GraphObject * self, /*Py_None also means all for now, but it is deprecated */ if (list == Py_None) { - PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " - "deprecated since igraph 0.8.3, please use " - "Graph.delete_vertices() instead"); + PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " + "deprecated since igraph 0.8.3, please use " + "Graph.delete_vertices() instead"); } /* this already converts no arguments and Py_None to all vertices */ @@ -7850,18 +7850,36 @@ PyObject *igraphmodule_Graph_to_undirected(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_to_directed(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *mutual = Py_True; + PyObject *mutual_o = Py_None; + PyObject *mode_o = Py_None; igraph_to_directed_t mode = IGRAPH_TO_DIRECTED_MUTUAL; - static char *kwlist[] = { "mutual", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mutual)) + static char *kwlist[] = { "mode", "mutual", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &mutual_o)) return NULL; - mode = - (PyObject_IsTrue(mutual) ? IGRAPH_TO_DIRECTED_MUTUAL : - IGRAPH_TO_DIRECTED_ARBITRARY); + + if (mode_o == Py_None) { + /* mode argument omitted so we fall back to 'mutual' for sake of + * compatibility and print a warning */ + if (mutual_o == Py_None) { + /* mutual was not given either, so this is okay */ + mode = IGRAPH_TO_DIRECTED_MUTUAL; + } else { + mode = PyObject_IsTrue(mutual_o) ? IGRAPH_TO_DIRECTED_MUTUAL : IGRAPH_TO_DIRECTED_ARBITRARY; + PyErr_Warn(PyExc_DeprecationWarning, "The 'mutual' argument is deprecated since " + "igraph 0.9.3, please use mode=... instead"); + } + } else { + if (igraphmodule_PyObject_to_to_directed_t(mode_o, &mode)) { + return NULL; + } + } + if (igraph_to_directed(&self->g, mode)) { igraphmodule_handle_igraph_error(); return NULL; } + Py_RETURN_NONE; } @@ -14802,14 +14820,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Internal function, undocumented.\n\n" "@see: Graph.get_incidence()\n\n"}, - // interface to igraph_to_directed + /* interface to igraph_to_directed */ {"to_directed", (PyCFunction) igraphmodule_Graph_to_directed, METH_VARARGS | METH_KEYWORDS, - "to_directed(mutual=True)\n--\n\n" + "to_directed(mode=\"mutual\")\n--\n\n" "Converts an undirected graph to directed.\n\n" - "@param mutual: C{True} if mutual directed edges should be\n" - " created for every undirected edge. If C{False}, a directed\n" - " edge with arbitrary direction is created.\n"}, + "@param mode: specifies how to convert undirected edges into\n" + " directed ones. C{True} or C{\"mutual\"} creates a mutual edge pair\n" + " for each undirected edge. C{False} or C{\"arbitrary\"} picks an\n" + " arbitrary (but deterministic) edge direction for each edge.\n" + " C{\"random\"} picks a random direction for each edge. C{\"acyclic\"}\n" + " picks the edge directions in a way that the resulting graph will be\n" + " acyclic if there were no self-loops in the original graph.\n" // interface to igraph_to_undirected {"to_undirected", (PyCFunction) igraphmodule_Graph_to_undirected, diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 6c3860806..aac08af5a 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -1,5 +1,7 @@ +import random import unittest -from igraph import * + +from igraph import Graph, Matrix class DirectedUndirectedTests(unittest.TestCase): @@ -37,7 +39,7 @@ def testToUndirected(self): graph2.es["weight"] == [7, 3, 11] or graph2.es["weight"] == [3, 7, 11] ) - def testToDirected(self): + def testToDirectedNoModeArg(self): graph = Graph([(0, 1), (0, 2), (2, 3), (2, 4)], directed=False) graph.to_directed() self.assertTrue(graph.is_directed()) @@ -47,6 +49,51 @@ def testToDirected(self): == [(0, 1), (0, 2), (1, 0), (2, 0), (2, 3), (2, 4), (3, 2), (4, 2)] ) + def testToDirectedMutual(self): + graph = Graph([(0, 1), (0, 2), (2, 3), (2, 4)], directed=False) + graph.to_directed("mutual") + self.assertTrue(graph.is_directed()) + self.assertTrue(graph.vcount() == 5) + self.assertTrue( + sorted(graph.get_edgelist()) + == [(0, 1), (0, 2), (1, 0), (2, 0), (2, 3), (2, 4), (3, 2), (4, 2)] + ) + + def testToDirectedAcyclic(self): + graph = Graph([(0, 1), (2, 0), (3, 0), (3, 0), (4, 2)], directed=False) + graph.to_directed("acyclic") + self.assertTrue(graph.is_directed()) + self.assertTrue(graph.vcount() == 5) + print(graph.get_edgelist()) + self.assertTrue( + sorted(graph.get_edgelist()) + == [(0, 1), (0, 2), (0, 3), (0, 3), (2, 4)] + ) + + def testToDirectedRandom(self): + random.seed(0) + + graph = Graph.Ring(200, directed=False) + graph.to_directed("random") + + self.assertTrue(graph.is_directed()) + self.assertTrue(graph.vcount() == 200) + edgelist1 = sorted(graph.get_edgelist()) + + graph = Graph.Ring(200, directed=False) + graph.to_directed("random") + + self.assertTrue(graph.is_directed()) + self.assertTrue(graph.vcount() == 200) + edgelist2 = sorted(graph.get_edgelist()) + + self.assertTrue(edgelist1 != edgelist2) + + def testToDirectedInvalidMode(self): + graph = Graph([(0, 1), (0, 2), (2, 3), (2, 4)], directed=False) + with self.assertRaises(ValueError): + graph.to_directed("no-such-mode") + class GraphRepresentationTests(unittest.TestCase): def testGetAdjacency(self): From 3146714fff466c486d0dca57ffcc599e92919874 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 18:19:14 +0200 Subject: [PATCH 0492/1892] feat: updated igraph to 0.9.3 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index ecbe39a4e..a4be06863 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit ecbe39a4eb8d4319633e3e364fd72fe7fe9ae109 +Subproject commit a4be0686333f2e9fe38b3bc7a23b9073e848f77a From 65b1e4c24edf9c60b3d83bfa9dc34b3697a3d381 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 18:20:14 +0200 Subject: [PATCH 0493/1892] doc: updated changelog, slowly preparing for 0.9.3 --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d7a9f11c..caaffc782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## Unreleased +## 0.9.3 ### Added @@ -13,10 +13,15 @@ * `Graph.to_directed()` now supports a `mode=...` keyword argument. +### Changed + +* Updated igraph dependency to 0.9.3. + ### Deprecated * `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. + ## 0.9.1 ### Changed From 10d9d2e010f0f18c5038e009d54a89e50922465d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 18:32:22 +0200 Subject: [PATCH 0494/1892] fix: added missing closing bracket that I accidentally removed in the previous commit --- src/_igraph/graphobject.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index cacb41592..31ffe0caf 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14832,6 +14832,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " C{\"random\"} picks a random direction for each edge. C{\"acyclic\"}\n" " picks the edge directions in a way that the resulting graph will be\n" " acyclic if there were no self-loops in the original graph.\n" + }, // interface to igraph_to_undirected {"to_undirected", (PyCFunction) igraphmodule_Graph_to_undirected, From 52df5180289cfe916766dab4022fc6cc35caf86b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 May 2021 18:32:51 +0200 Subject: [PATCH 0495/1892] fix: deprecated partial string matches in conversions to enum members, closes #387 --- CHANGELOG.md | 6 ++++ src/_igraph/convert.c | 82 ++++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caaffc782..b9edadb98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,12 @@ ### Deprecated +* Functions and methods that take string arguments that represent an underlying + enum in the C core of igraph now print a deprecation warning when provided + with a string that does not match one of the enum member names (as documented + in the docstrings) exactly. Partial matches will be removed in the next + minor or major version, whichever comes first. + * `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index b9f0ad18d..269b7bccc 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -83,42 +83,68 @@ int PyLong_AsInt(PyObject* obj, int* result) { int igraphmodule_PyObject_to_enum(PyObject *o, igraphmodule_enum_translation_table_entry_t* table, int *result) { - char *s, *s2; - int i, best, best_result, best_unique; - if (o == 0 || o == Py_None) + char *s, *s2; + int i, best, best_result, best_unique; + + if (o == 0 || o == Py_None) + return 0; + + if (PyLong_Check(o)) + return PyLong_AsInt(o, result); + + s = PyUnicode_CopyAsString(o); + if (s == 0) { + PyErr_SetString(PyExc_TypeError, "int, long or string expected"); + return -1; + } + + /* Convert string to lowercase */ + for (s2 = s; *s2; s2++) { + *s2 = tolower(*s2); + } + + /* Search for matches */ + best = 0; best_unique = 0; best_result = -1; + while (table->name != 0) { + if (strcmp(s, table->name) == 0) { + /* Exact match found */ + *result = table->value; + free(s); return 0; - if (PyLong_Check(o)) - return PyLong_AsInt(o, result); - s = PyUnicode_CopyAsString(o); - if (s == 0) { - PyErr_SetString(PyExc_TypeError, "int, long or string expected"); - return -1; } - /* Convert string to lowercase */ - for (s2=s; *s2; s2++) - *s2 = tolower(*s2); - best = 0; best_unique = 0; best_result = -1; - /* Search for matches */ - while (table->name != 0) { - if (strcmp(s, table->name) == 0) { - *result = table->value; - free(s); - return 0; - } - for (i=0; s[i] == table->name[i]; i++); - if (i > best) { - best = i; best_unique = 1; best_result = table->value; - } else if (i == best) best_unique = 0; - table++; + + /* Find length of longest prefix that matches */ + for (i = 0; s[i] == table->name[i]; i++); + + if (i > best) { + /* Found a better match than before */ + best = i; best_unique = 1; best_result = table->value; + } else if (i == best) { + /* Best match is not unique */ + best_unique = 0; } - free(s); - if (best_unique) { *result = best_result; return 0; } + + table++; + } + + free(s); + + if (best_unique) { + PyErr_Warn( + PyExc_DeprecationWarning, + "Partial string matches of enum members are deprecated since igraph 0.9.3; " + "use strings that identify an enum member unambiguously." + ); + + *result = best_result; + return 0; + } else { PyErr_SetObject(PyExc_ValueError, o); return -1; + } } - /** * \ingroup python_interface_conversion * \brief Converts a Python object to a corresponding igraph enum, strictly. From 1c87aa9a0118d66fde21fcc6de6ffb2f13851b5b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 21 May 2021 11:17:43 +0200 Subject: [PATCH 0496/1892] doc: fix quoting of 'None' in igraph.drawing.plot() --- src/igraph/drawing/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index e099c0dd8..8c9723b40 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -465,7 +465,7 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): is 20 on each side. @keyword inline: whether to try and show the plot object inline in the - current IPython notebook. Passing ``None`` here or omitting this keyword + current IPython notebook. Passing C{None} here or omitting this keyword argument will look up the preferred behaviour from the C{shell.ipython.inlining.Plot} configuration key. Note that this keyword argument has an effect only if igraph is run inside IPython and C{target} From f6eb8cf93443d3cca8d52716979bba971c047911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Thu, 27 May 2021 20:24:04 +0200 Subject: [PATCH 0497/1892] improve from_networkx performance --- src/igraph/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 547c56a85..8995047b5 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1920,6 +1920,7 @@ def from_networkx(cls, g): @param g: networkx Graph or DiGraph """ import networkx as nx + from collections import defaultdict # Graph attributes gattr = dict(g.graph) @@ -1942,13 +1943,15 @@ def from_networkx(cls, g): graph.vs[vd[v]][key] = val # Edges and edge attributes - # NOTE: we need to do both together to deal well with multigraphs - # Each e might have a length of 2 (graphs) or 3 (multigraphs, the - # third element is the "color" of the edge) - for e, (_, _, datum) in zip(g.edges, g.edges.data()): - eid = graph.add_edge(vd[e[0]], vd[e[1]]) - for key, val in list(datum.items()): - eid[key] = val + eattr_names = {name for (_, _, data) in g.edges.data() for name in data} + eattr = defaultdict(list) + edges = [] + for (u, v, data) in g.edges.data(): + edges.append((vd[u], vd[v])) + for name in eattr_names: + eattr[name].append(data.get(name)) + + graph.add_edges(edges, eattr) return graph From 941f43aea795a09308d4de32b61792e32a403b3c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 27 May 2021 22:28:56 +0200 Subject: [PATCH 0498/1892] test: test cleanup, moved leftover from src/igraph/test to tests/ --- src/igraph/test/foreign.py | 579 ------------------------------------- tests/test_cliques.py | 2 +- tests/test_edgeseq.py | 6 +- tests/test_foreign.py | 241 ++++++++++++++- tests/test_operators.py | 4 +- tests/test_vertexseq.py | 6 +- tests/utils.py | 44 +-- 7 files changed, 242 insertions(+), 640 deletions(-) delete mode 100644 src/igraph/test/foreign.py diff --git a/src/igraph/test/foreign.py b/src/igraph/test/foreign.py deleted file mode 100644 index 49a4fa5d2..000000000 --- a/src/igraph/test/foreign.py +++ /dev/null @@ -1,579 +0,0 @@ -import sys -import io -import unittest -import warnings - -from igraph import Graph, InternalError -from igraph.test.utils import temporary_file - - -try: - import networkx as nx -except ImportError: - nx = None - - -try: - import graph_tool as gt -except ImportError: - gt = None - - -class ForeignTests(unittest.TestCase): - def testDIMACS(self): - with temporary_file( - """\ - c - c This is a simple example file to demonstrate the - c DIMACS input file format for minimum-cost flow problems. - c - c problem line : - p max 4 5 - c - c node descriptor lines : - n 1 s - n 4 t - c - c arc descriptor lines : - a 1 2 4 - a 1 3 2 - a 2 3 2 - a 2 4 3 - a 3 4 5 - """ - ) as tmpfname: - graph = Graph.Read_DIMACS(tmpfname, False) - self.assertTrue(isinstance(graph, Graph)) - self.assertTrue(graph.vcount() == 4 and graph.ecount() == 5) - self.assertTrue(graph["source"] == 0 and graph["target"] == 3) - self.assertTrue(graph.es["capacity"] == [4, 2, 2, 3, 5]) - graph.write_dimacs(tmpfname) - - def testDL(self): - with temporary_file( - """\ - dl n=5 - format = fullmatrix - labels embedded - data: - larry david lin pat russ - Larry 0 1 1 1 0 - david 1 0 0 0 1 - Lin 1 0 0 1 0 - Pat 1 0 1 0 1 - russ 0 1 0 1 0 - """ - ) as tmpfname: - g = Graph.Read_DL(tmpfname) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 5 and g.ecount() == 12) - self.assertTrue(g.is_directed()) - self.assertTrue( - sorted(g.get_edgelist()) - == [ - (0, 1), - (0, 2), - (0, 3), - (1, 0), - (1, 4), - (2, 0), - (2, 3), - (3, 0), - (3, 2), - (3, 4), - (4, 1), - (4, 3), - ] - ) - - with temporary_file( - """\ - dl n=5 - format = fullmatrix - labels: - barry,david - lin,pat - russ - data: - 0 1 1 1 0 - 1 0 0 0 1 - 1 0 0 1 0 - 1 0 1 0 1 - 0 1 0 1 0 - """ - ) as tmpfname: - g = Graph.Read_DL(tmpfname) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 5 and g.ecount() == 12) - self.assertTrue(g.is_directed()) - self.assertTrue( - sorted(g.get_edgelist()) - == [ - (0, 1), - (0, 2), - (0, 3), - (1, 0), - (1, 4), - (2, 0), - (2, 3), - (3, 0), - (3, 2), - (3, 4), - (4, 1), - (4, 3), - ] - ) - - with temporary_file( - """\ - DL n=5 - format = edgelist1 - labels: - george, sally, jim, billy, jane - labels embedded: - data: - george sally 2 - george jim 3 - sally jim 4 - billy george 5 - jane jim 6 - """ - ) as tmpfname: - g = Graph.Read_DL(tmpfname, False) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 5 and g.ecount() == 5) - self.assertTrue(not g.is_directed()) - self.assertTrue( - sorted(g.get_edgelist()) == [(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)] - ) - - def _testNCOLOrLGL(self, func, fname, can_be_reopened=True): - g = func(fname, names=False, weights=False, directed=False) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 4 and g.ecount() == 5) - self.assertTrue(not g.is_directed()) - self.assertTrue( - sorted(g.get_edgelist()) == [(0, 1), (0, 2), (1, 1), (1, 3), (2, 3)] - ) - self.assertTrue( - "name" not in g.vertex_attributes() and "weight" not in g.edge_attributes() - ) - if not can_be_reopened: - return - - g = func(fname, names=False, directed=False) - self.assertTrue( - "name" not in g.vertex_attributes() and "weight" in g.edge_attributes() - ) - self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) - - g = func(fname, directed=False) - self.assertTrue( - "name" in g.vertex_attributes() and "weight" in g.edge_attributes() - ) - self.assertTrue(g.vs["name"] == ["eggs", "spam", "ham", "bacon"]) - self.assertTrue(g.es["weight"] == [1, 2, 0, 3, 0]) - - def testNCOL(self): - with temporary_file( - """\ - eggs spam 1 - ham eggs 2 - ham bacon - bacon spam 3 - spam spam""" - ) as tmpfname: - self._testNCOLOrLGL(func=Graph.Read_Ncol, fname=tmpfname) - - with temporary_file( - """\ - eggs spam - ham eggs - ham bacon - bacon spam - spam spam""" - ) as tmpfname: - g = Graph.Read_Ncol(tmpfname) - self.assertTrue( - "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() - ) - - def testLGL(self): - with temporary_file( - """\ - # eggs - spam 1 - # ham - eggs 2 - bacon - # bacon - spam 3 - # spam - spam""" - ) as tmpfname: - self._testNCOLOrLGL(func=Graph.Read_Lgl, fname=tmpfname) - - with temporary_file( - """\ - # eggs - spam - # ham - eggs - bacon - # bacon - spam - # spam - spam""" - ) as tmpfname: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - g = Graph.Read_Lgl(tmpfname) - self.assertTrue( - "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() - ) - - # This is not an LGL file; we are testing error handling here - with temporary_file( - """\ - 1 2 - 1 3 - """ - ) as tmpfname: - with self.assertRaises(InternalError): - Graph.Read_Lgl(tmpfname) - - def testLGLWithIOModule(self): - with temporary_file( - """\ - # eggs - spam 1 - # ham - eggs 2 - bacon - # bacon - spam 3 - # spam - spam""" - ) as tmpfname: - with io.open(tmpfname, "r") as fp: - self._testNCOLOrLGL( - func=Graph.Read_Lgl, fname=fp, can_be_reopened=False - ) - - def testAdjacency(self): - with temporary_file( - """\ - # Test comment line - 0 1 1 0 0 0 - 1 0 1 0 0 0 - 1 1 0 0 0 0 - 0 0 0 0 2 2 - 0 0 0 2 0 2 - 0 0 0 2 2 0 - """ - ) as tmpfname: - g = Graph.Read_Adjacency(tmpfname) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue( - g.vcount() == 6 - and g.ecount() == 18 - and g.is_directed() - and "weight" not in g.edge_attributes() - ) - g = Graph.Read_Adjacency(tmpfname, attribute="weight") - self.assertTrue(isinstance(g, Graph)) - self.assertTrue( - g.vcount() == 6 - and g.ecount() == 12 - and g.is_directed() - and g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] - ) - - g.write_adjacency(tmpfname) - - def testPickle(self): - pickle = [ - 128, - 2, - 99, - 105, - 103, - 114, - 97, - 112, - 104, - 10, - 71, - 114, - 97, - 112, - 104, - 10, - 113, - 1, - 40, - 75, - 3, - 93, - 113, - 2, - 75, - 1, - 75, - 2, - 134, - 113, - 3, - 97, - 137, - 125, - 125, - 125, - 116, - 82, - 113, - 4, - 125, - 98, - 46, - ] - if sys.version_info > (3, 0): - pickle = bytes(pickle) - else: - pickle = "".join(map(chr, pickle)) - with temporary_file(pickle, "wb") as tmpfname: - g = Graph.Read_Pickle(pickle) - self.assertTrue(isinstance(g, Graph)) - self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) - g.write_pickle(tmpfname) - - @unittest.skipIf(nx is None, "test case depends on networkx") - def testGraphNetworkx(self): - # Undirected - g = Graph.Ring(10) - g["gattr"] = "graph_attribute" - g.vs["vattr"] = list(range(g.vcount())) - g.es["eattr"] = list(range(len(g.es))) - - # Go to networkx and back - g_nx = g.to_networkx() - g2 = Graph.from_networkx(g_nx) - - self.assertFalse(g2.is_directed()) - self.assertTrue(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - # Test attributes - self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) - for i, vertex in enumerate(g.vs): - vertex2 = g2.vs[i] - for an in vertex.attribute_names(): - if an == "vattr": - continue - self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) - self.assertEqual(g.edge_attributes(), g2.edge_attributes()) - for edge in g.es: - eid = g2.get_eid(edge.source, edge.target) - edge2 = g2.es[eid] - for an in edge.attribute_names(): - self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) - - # Directed - g = Graph.Ring(10, directed=True) - - # Go to networkx and back - g_nx = g.to_networkx() - g2 = Graph.from_networkx(g_nx) - - self.assertTrue(g2.is_directed()) - self.assertTrue(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - @unittest.skipIf(nx is None, "test case depends on networkx") - def testMultigraphNetworkx(self): - # Undirected - g = Graph.Ring(10) - g.add_edge(0, 1) - g["gattr"] = "graph_attribute" - g.vs["vattr"] = list(range(g.vcount())) - g.es["eattr"] = list(range(len(g.es))) - - # Go to networkx and back - g_nx = g.to_networkx() - g2 = Graph.from_networkx(g_nx) - - self.assertFalse(g2.is_directed()) - self.assertFalse(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - # Test attributes - self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) - self.assertEqual(g.edge_attributes(), g2.edge_attributes()) - # Testing parallel edges is a bit more tricky - edge2_found = set() - for edge in g.es: - # Go through all parallel edges between these two vertices - for edge2 in g2.es: - if edge2 in edge2_found: - continue - if edge.source != edge2.source: - continue - if edge.target != edge2.target: - continue - # Check all attributes between these two - for an in edge.attribute_names(): - if edge.attributes()[an] != edge2.attributes()[an]: - break - else: - # Correspondence found - edge2_found.add(edge2) - break - - else: - self.assertTrue(False) - - # Directed - g = Graph.Ring(10, directed=True) - g.add_edge(0, 1) - - # Go to networkx and back - g_nx = g.to_networkx() - g2 = Graph.from_networkx(g_nx) - - self.assertTrue(g2.is_directed()) - self.assertFalse(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - @unittest.skipIf(gt is None, "test case depends on graph-tool") - def testGraphGraphTool(self): - # Undirected - g = Graph.Ring(10) - g["gattr"] = "graph_attribute" - g.vs["vattr"] = list(range(g.vcount())) - g.es["eattr"] = list(range(len(g.es))) - - # Go to graph-tool and back - g_gt = g.to_graph_tool( - graph_attributes={"gattr": "object"}, - vertex_attributes={"vattr": "int"}, - edge_attributes={"eattr": "int"}, - ) - g2 = Graph.from_graph_tool(g_gt) - - self.assertFalse(g2.is_directed()) - self.assertTrue(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - # Test attributes - self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) - for i, vertex in enumerate(g.vs): - vertex2 = g2.vs[i] - for an in vertex.attribute_names(): - self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) - self.assertEqual(g.edge_attributes(), g2.edge_attributes()) - for edge in g.es: - eid = g2.get_eid(edge.source, edge.target) - edge2 = g2.es[eid] - for an in edge.attribute_names(): - self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) - - # Directed - g = Graph.Ring(10, directed=True) - - # Go to graph-tool and back - g_gt = g.to_graph_tool() - - g2 = Graph.from_graph_tool(g_gt) - - self.assertTrue(g2.is_directed()) - self.assertTrue(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - @unittest.skipIf(gt is None, "test case depends on graph-tool") - def testMultigraphGraphTool(self): - # Undirected - g = Graph.Ring(10) - g.add_edge(0, 1) - g["gattr"] = "graph_attribute" - g.vs["vattr"] = list(range(g.vcount())) - g.es["eattr"] = list(range(len(g.es))) - - # Go to graph-tool and back - g_gt = g.to_graph_tool( - graph_attributes={"gattr": "object"}, - vertex_attributes={"vattr": "int"}, - edge_attributes={"eattr": "int"}, - ) - g2 = Graph.from_graph_tool(g_gt) - - self.assertFalse(g2.is_directed()) - self.assertFalse(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - # Test attributes - self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) - for i, vertex in enumerate(g.vs): - vertex2 = g2.vs[i] - for an in vertex.attribute_names(): - self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) - self.assertEqual(g.edge_attributes(), g2.edge_attributes()) - # Testing parallel edges is a bit more tricky - edge2_found = set() - for edge in g.es: - # Go through all parallel edges between these two vertices - for edge2 in g2.es: - if edge2 in edge2_found: - continue - if edge.source != edge2.source: - continue - if edge.target != edge2.target: - continue - # Check all attributes between these two - for an in edge.attribute_names(): - if edge.attributes()[an] != edge2.attributes()[an]: - break - else: - # Correspondence found - edge2_found.add(edge2) - break - - else: - self.assertTrue(False) - - # Directed - g = Graph.Ring(10, directed=True) - g.add_edge(0, 1) - - # Go to graph-tool and back - g_gt = g.to_graph_tool() - g2 = Graph.from_graph_tool(g_gt) - - self.assertTrue(g2.is_directed()) - self.assertFalse(g2.is_simple()) - self.assertEqual(g.vcount(), g2.vcount()) - self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) - - -def suite(): - foreign_suite = unittest.makeSuite(ForeignTests) - return unittest.TestSuite([foreign_suite]) - - -def test(): - runner = unittest.TextTestRunner() - runner.run(suite()) - - -if __name__ == "__main__": - test() diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 70a958376..0ef0c69ab 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -2,7 +2,7 @@ from igraph import * -from .utils import is_pypy, skipIf, temporary_file +from .utils import temporary_file class CliqueTests(unittest.TestCase): diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index 6ec581d70..74667b758 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -4,7 +4,7 @@ from igraph import * -from .utils import is_pypy, skipIf +from .utils import is_pypy try: import numpy as np @@ -85,7 +85,7 @@ def testPhantomEdge(self): self.assertRaises(ValueError, getattr, e, "tuple") self.assertRaises(ValueError, getattr, e, "vertex_tuple") - @skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") + @unittest.skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") def testProxyMethods(self): g = Graph.GRG(10, 0.5) e = g.es[0] @@ -148,7 +148,7 @@ def testIndexing(self): self.assertRaises(IndexError, self.g.es.__getitem__, -n - 1) self.assertRaises(TypeError, self.g.es.__getitem__, 1.5) - @skipIf(np is None, "test case depends on NumPy") + @unittest.skipIf(np is None, "test case depends on NumPy") def testNumPyIndexing(self): n = self.g.ecount() for i in range(n): diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 630a612fc..a3db0b869 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -2,9 +2,19 @@ import unittest import warnings -from igraph import * +from igraph import Graph, InternalError -from .utils import temporary_file, skipIf +from .utils import temporary_file + +try: + import networkx as nx +except ImportError: + nx = None + +try: + import graph_tool as gt +except ImportError: + gt = None try: import pandas as pd @@ -390,17 +400,14 @@ def testPickle(self): 98, 46, ] - if sys.version_info > (3, 0): - pickle = bytes(pickle) - else: - pickle = "".join(map(chr, pickle)) + pickle = bytes(pickle) with temporary_file(pickle, "wb", binary=True) as tmpfname: g = Graph.Read_Pickle(pickle) self.assertTrue(isinstance(g, Graph)) self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) - @skipIf(pd is None, "test case depends on Pandas") + @unittest.skipIf(pd is None, "test case depends on Pandas") def testVertexDataFrames(self): g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) @@ -435,7 +442,7 @@ def testVertexDataFrames(self): self.assertEqual(list(df.columns), ["weight"]) self.assertEqual(list(df["weight"]), g.vs["weight"]) - @skipIf(pd is None, "test case depends on Pandas") + @unittest.skipIf(pd is None, "test case depends on Pandas") def testEdgeDataFrames(self): g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) @@ -479,6 +486,224 @@ def testEdgeDataFrames(self): self.assertEqual(list(df.iloc[:, i]), g.es["source"]) + @unittest.skipIf(nx is None, "test case depends on networkx") + def testGraphNetworkx(self): + # Undirected + g = Graph.Ring(10) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertFalse(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + if an == "vattr": + continue + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + for edge in g.es: + eid = g2.get_eid(edge.source, edge.target) + edge2 = g2.es[eid] + for an in edge.attribute_names(): + self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) + + # Directed + g = Graph.Ring(10, directed=True) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertTrue(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(nx is None, "test case depends on networkx") + def testMultigraphNetworkx(self): + # Undirected + g = Graph.Ring(10) + g.add_edge(0, 1) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertFalse(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + # Testing parallel edges is a bit more tricky + edge2_found = set() + for edge in g.es: + # Go through all parallel edges between these two vertices + for edge2 in g2.es: + if edge2 in edge2_found: + continue + if edge.source != edge2.source: + continue + if edge.target != edge2.target: + continue + # Check all attributes between these two + for an in edge.attribute_names(): + if edge.attributes()[an] != edge2.attributes()[an]: + break + else: + # Correspondence found + edge2_found.add(edge2) + break + + else: + self.assertTrue(False) + + # Directed + g = Graph.Ring(10, directed=True) + g.add_edge(0, 1) + + # Go to networkx and back + g_nx = g.to_networkx() + g2 = Graph.from_networkx(g_nx) + + self.assertTrue(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(gt is None, "test case depends on graph-tool") + def testGraphGraphTool(self): + # Undirected + g = Graph.Ring(10) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) + + # Go to graph-tool and back + g_gt = g.to_graph_tool( + graph_attributes={"gattr": "object"}, + vertex_attributes={"vattr": "int"}, + edge_attributes={"eattr": "int"}, + ) + g2 = Graph.from_graph_tool(g_gt) + + self.assertFalse(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + for edge in g.es: + eid = g2.get_eid(edge.source, edge.target) + edge2 = g2.es[eid] + for an in edge.attribute_names(): + self.assertEqual(edge.attributes()[an], edge2.attributes()[an]) + + # Directed + g = Graph.Ring(10, directed=True) + + # Go to graph-tool and back + g_gt = g.to_graph_tool() + + g2 = Graph.from_graph_tool(g_gt) + + self.assertTrue(g2.is_directed()) + self.assertTrue(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + @unittest.skipIf(gt is None, "test case depends on graph-tool") + def testMultigraphGraphTool(self): + # Undirected + g = Graph.Ring(10) + g.add_edge(0, 1) + g["gattr"] = "graph_attribute" + g.vs["vattr"] = list(range(g.vcount())) + g.es["eattr"] = list(range(len(g.es))) + + # Go to graph-tool and back + g_gt = g.to_graph_tool( + graph_attributes={"gattr": "object"}, + vertex_attributes={"vattr": "int"}, + edge_attributes={"eattr": "int"}, + ) + g2 = Graph.from_graph_tool(g_gt) + + self.assertFalse(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + # Test attributes + self.assertEqual(g.attributes(), g2.attributes()) + self.assertEqual(g.vertex_attributes(), g2.vertex_attributes()) + for i, vertex in enumerate(g.vs): + vertex2 = g2.vs[i] + for an in vertex.attribute_names(): + self.assertEqual(vertex.attributes()[an], vertex2.attributes()[an]) + self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + # Testing parallel edges is a bit more tricky + edge2_found = set() + for edge in g.es: + # Go through all parallel edges between these two vertices + for edge2 in g2.es: + if edge2 in edge2_found: + continue + if edge.source != edge2.source: + continue + if edge.target != edge2.target: + continue + # Check all attributes between these two + for an in edge.attribute_names(): + if edge.attributes()[an] != edge2.attributes()[an]: + break + else: + # Correspondence found + edge2_found.add(edge2) + break + + else: + self.assertTrue(False) + + # Directed + g = Graph.Ring(10, directed=True) + g.add_edge(0, 1) + + # Go to graph-tool and back + g_gt = g.to_graph_tool() + g2 = Graph.from_graph_tool(g_gt) + + self.assertTrue(g2.is_directed()) + self.assertFalse(g2.is_simple()) + self.assertEqual(g.vcount(), g2.vcount()) + self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + + def suite(): foreign_suite = unittest.makeSuite(ForeignTests) return unittest.TestSuite([foreign_suite]) diff --git a/tests/test_operators.py b/tests/test_operators.py index ec001dd46..04a0fe08e 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -2,8 +2,6 @@ from igraph import * -from .utils import skipIf - try: import numpy as np except ImportError: @@ -476,7 +474,7 @@ def testContractVertices(self): self.assertEqual(g2.vcount(), 5) self.assertEqual(g2.ecount(), 0) - @skipIf(np is None, "test case depends on NumPy") + @unittest.skipIf(np is None, "test case depends on NumPy") def testContractVerticesWithNumPyIntegers(self): g = Graph.Full(4) + Graph.Full(4) + [(0, 5), (1, 4)] g2 = g.copy() diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 39037e4a1..12adf1aa1 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -4,7 +4,7 @@ from igraph import * -from .utils import is_pypy, skipIf +from .utils import is_pypy try: import numpy as np @@ -99,7 +99,7 @@ def testNeighbors(self): [edge.index for edge in vertex.neighbors(mode=mode)], ) - @skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") + @unittest.skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") def testProxyMethods(self): # We only test with connected graphs because disconnected graphs might # print a warning when shortest_paths() is invoked on them and we want @@ -177,7 +177,7 @@ def testIndexing(self): self.assertRaises(IndexError, self.g.vs.__getitem__, -n - 1) self.assertRaises(TypeError, self.g.vs.__getitem__, 1.5) - @skipIf(np is None, "test case depends on NumPy") + @unittest.skipIf(np is None, "test case depends on NumPy") def testNumPyIndexing(self): n = self.g.vcount() for i in range(self.g.vcount()): diff --git a/tests/utils.py b/tests/utils.py index 8bfbc88d4..fdea66dba 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,55 +1,13 @@ """Utility functions for unit testing.""" -import functools import os import platform -import sys import tempfile -import types from contextlib import contextmanager from textwrap import dedent -__all__ = ["skip", "skipIf", "temporary_file"] - - -def _id(obj): - return obj - - -try: - from unittest import skip -except ImportError: - # Provide basic replacement for unittest.skip - def skip(reason): - """Unconditionally skip a test.""" - - def decorator(test_item): - if not isinstance(test_item, type): - - @functools.wraps(test_item) - def skip_wrapper(*args, **kwds): - if reason: - sys.stderr.write("skipped, %s ... " % reason) - else: - sys.stderr.write("skipped, ") - return - - test_item = skip_wrapper - return test_item - - return decorator - - -try: - from unittest import skipIf -except ImportError: - # Provide basic replacement for unittest.skipIf - def skipIf(condition, reason): - """Skip a test if the condition is true.""" - if condition: - return skip(reason) - return _id +__all__ = ("temporary_file", ) @contextmanager From 8d356a97a6ed6bee3f34a11592a86263f0053ccf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 27 May 2021 22:39:44 +0200 Subject: [PATCH 0499/1892] test: fix deprecation warnings in unit tests --- src/_igraph/convert.c | 3 +++ src/igraph/clustering.py | 2 +- tests/test_conversion.py | 1 - tests/test_decomposition.py | 2 +- tests/test_structural.py | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 269b7bccc..e54548bff 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -266,6 +266,7 @@ int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, static igraphmodule_enum_translation_table_entry_t attribute_combination_type_tt[] = { {"ignore", IGRAPH_ATTRIBUTE_COMBINE_IGNORE}, {"sum", IGRAPH_ATTRIBUTE_COMBINE_SUM}, + {"prod", IGRAPH_ATTRIBUTE_COMBINE_PROD}, {"product", IGRAPH_ATTRIBUTE_COMBINE_PROD}, {"min", IGRAPH_ATTRIBUTE_COMBINE_MIN}, {"max", IGRAPH_ATTRIBUTE_COMBINE_MAX}, @@ -274,6 +275,7 @@ int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, {"last", IGRAPH_ATTRIBUTE_COMBINE_LAST}, {"mean", IGRAPH_ATTRIBUTE_COMBINE_MEAN}, {"median", IGRAPH_ATTRIBUTE_COMBINE_MEDIAN}, + {"concat", IGRAPH_ATTRIBUTE_COMBINE_CONCAT}, {"concatenate", IGRAPH_ATTRIBUTE_COMBINE_CONCAT}, {0, 0} }; @@ -483,6 +485,7 @@ int igraphmodule_PyObject_to_community_comparison_t(PyObject *o, {"nmi", IGRAPH_COMMCMP_NMI}, {"danon", IGRAPH_COMMCMP_NMI}, {"split-join", IGRAPH_COMMCMP_SPLIT_JOIN}, + {"split_join", IGRAPH_COMMCMP_SPLIT_JOIN}, {"rand", IGRAPH_COMMCMP_RAND}, {"adjusted_rand", IGRAPH_COMMCMP_ADJUSTED_RAND}, {0,0} diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index e54dc35ac..3c00b3c95 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -352,7 +352,7 @@ def cluster_graph(self, combine_vertices=None, combine_edges=None): """ result = self.graph.copy() result.contract_vertices(self.membership, combine_vertices) - if combine_edges != False: + if combine_edges is not False: result.simplify(combine_edges=combine_edges) return result diff --git a/tests/test_conversion.py b/tests/test_conversion.py index aac08af5a..b8600e9a3 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -64,7 +64,6 @@ def testToDirectedAcyclic(self): graph.to_directed("acyclic") self.assertTrue(graph.is_directed()) self.assertTrue(graph.vcount() == 5) - print(graph.get_edgelist()) self.assertTrue( sorted(graph.get_edgelist()) == [(0, 1), (0, 2), (0, 3), (0, 3), (2, 4)] diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 8413af0d6..21e25e6f8 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -583,7 +583,7 @@ def testCompareNMI(self): def testCompareSplitJoin(self): expected = [0, 3, 5, 11] - self._testMethod("split", expected) + self._testMethod("split_join", expected) l1 = [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3] l2 = [3, 1, 2, 1, 3, 1, 3, 1, 2, 1, 4, 2] self.assertEqual(split_join_distance(l1, l2), (6, 5)) diff --git a/tests/test_structural.py b/tests/test_structural.py index 545733d1e..9ea13d990 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -434,7 +434,7 @@ def testHubScore(self): def testCoreness(self): g = Graph.Full(4) + Graph(4) + [(0, 4), (1, 5), (2, 6), (3, 7)] - self.assertEqual(g.coreness("A"), [3, 3, 3, 3, 1, 1, 1, 1]) + self.assertEqual(g.coreness("all"), [3, 3, 3, 3, 1, 1, 1, 1]) class NeighborhoodTests(unittest.TestCase): From 5e937667ef7e7ac431b23b948483a98df5066655 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 11:47:39 +0200 Subject: [PATCH 0500/1892] fix: keep on supporting 'min' and 'max' as aliases to 'minimum' and 'maximum' in igraph_adjacency_t conversion --- src/_igraph/convert.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index e54548bff..f45cc4d3e 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -254,6 +254,8 @@ int igraphmodule_PyObject_to_adjacency_t(PyObject *o, {"lower", IGRAPH_ADJ_LOWER}, {"minimum", IGRAPH_ADJ_MIN}, {"maximum", IGRAPH_ADJ_MAX}, + {"min", IGRAPH_ADJ_MIN}, + {"max", IGRAPH_ADJ_MAX}, {"plus", IGRAPH_ADJ_PLUS}, {0,0} }; From 1650bc6a33625ae6f503551b81039eb05a59c96b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 11:49:04 +0200 Subject: [PATCH 0501/1892] style: fixing some linter warnings in __igraph__.py --- src/igraph/__init__.py | 229 ++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 120 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 8995047b5..7a55a9eb9 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -65,7 +65,7 @@ Vertex, VertexSeq as _VertexSeq, WEAK, - arpack_options, + arpack_options as default_arpack_options, community_to_membership, convex_hull, is_degree_sequence, @@ -88,7 +88,7 @@ split_join_distance, ) from igraph.cut import Cut, Flow -from igraph.configuration import Configuration +from igraph.configuration import Configuration, init as init_configuration from igraph.drawing import BoundingBox, DefaultGraphDrawer, Plot, Point, Rectangle, plot from igraph.drawing.colors import ( Palette, @@ -730,9 +730,8 @@ def get_adjacency_sparse(self, attribute=None): from scipy import sparse except ImportError: raise ImportError( - "You should install scipy package in order to use this function" + "You should install scipy in order to use this function" ) - import numpy as np edges = self.get_edgelist() if attribute is None: @@ -1012,7 +1011,7 @@ def pagerank( @return: a list with the Google PageRank values of the specified vertices.""" if arpack_options is None: - arpack_options = _igraph.arpack_options + arpack_options = default_arpack_options return self.personalized_pagerank( vertices, directed, @@ -1304,7 +1303,8 @@ def community_label_propagation(self, weights=None, initial=None, fixed=None): @param fixed: a list of booleans for each vertex. C{True} corresponds to vertices whose labeling should not change during the algorithm. It only makes sense if initial labels are also given. Unlabeled - vertices cannot be fixed. + vertices cannot be fixed. It may also be the name of a vertex + attribute; each attribute value will be interpreted as a Boolean. @return: an appropriate L{VertexClustering} object. @newfield ref: Reference @@ -1314,7 +1314,7 @@ def community_label_propagation(self, weights=None, initial=None, fixed=None): U{http://arxiv.org/abs/0709.2938}. """ if isinstance(fixed, str): - fixed = [bool(o) for o in g.vs[fixed]] + fixed = [bool(o) for o in self.vs[fixed]] cl = GraphBase.community_label_propagation(self, weights, initial, fixed) return VertexClustering(self, cl, modularity_params=dict(weights=weights)) @@ -1526,7 +1526,7 @@ def k_core(self, *args): for arg in args: try: indices.extend(arg) - except: + except Exception: indices.append(arg) if len(indices) > 1 or hasattr(args[0], "__iter__"): @@ -1691,10 +1691,10 @@ def layout(self, layout=None, *args, **kwds): method = getattr(self.__class__, self._layout_mapping[layout]) if not hasattr(method, "__call__"): raise ValueError("layout method must be callable") - l = method(self, *args, **kwds) - if not isinstance(l, Layout): - l = Layout(l) - return l + layout = method(self, *args, **kwds) + if not isinstance(layout, Layout): + layout = Layout(layout) + return layout def layout_auto(self, *args, **kwds): """Chooses and runs a suitable layout function based on simple @@ -1763,19 +1763,6 @@ def layout_auto(self, *args, **kwds): algo = "drl" return self.layout(algo, *args, **kwds) - def layout_grid_fruchterman_reingold(self, *args, **kwds): - """Compatibility alias to the Fruchterman-Reingold layout with the grid - option turned on. - - @see: Graph.layout_fruchterman_reingold() - """ - deprecated( - "Graph.layout_grid_fruchterman_reingold() is deprecated since " - "igraph 0.8, please use Graph.layout_fruchterman_reingold(grid=True) instead" - ) - kwds["grid"] = True - return self.layout_fruchterman_reingold(*args, **kwds) - def layout_sugiyama( self, layers=None, @@ -2093,7 +2080,8 @@ def Read_Adjacency( @return: the created graph""" if isinstance(f, str): f = open(f) - matrix, ri, weights = [], 0, {} + + matrix, ri = [], 0 for line in f: line = line.strip() if len(line) == 0: @@ -2115,7 +2103,7 @@ def Read_Adjacency( return graph @classmethod - def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): + def Adjacency(cls, matrix, mode="directed", *args, **kwargs): """Generates a graph from its adjacency matrix. @param matrix: the adjacency matrix. Possible types are: @@ -2124,21 +2112,17 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): - a scipy.sparse matrix (will be converted to a COO matrix, but not to a dense matrix) @param mode: the mode to be used. Possible values are: - - - C{ADJ_DIRECTED} - the graph will be directed and a matrix + - C{"directed"} - the graph will be directed and a matrix element gives the number of edges between two vertex. - - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience. - - C{ADJ_MAX} - undirected graph will be created and the number of + - C{"undirected"} - alias to C{"max"} for convenience. + - C{"max"} - undirected graph will be created and the number of edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} - - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))} - - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)} - - C{ADJ_UPPER} - undirected graph with the upper right triangle of + - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} + - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} + - C{"upper"} - undirected graph with the upper right triangle of the matrix (including the diagonal) - - C{ADJ_LOWER} - undirected graph with the lower left triangle of + - C{"lower"} - undirected graph with the lower left triangle of the matrix (including the diagonal) - - These values can also be given as strings without the C{ADJ} prefix. - """ try: import numpy as np @@ -2151,7 +2135,7 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): sparse = None if (sparse is not None) and isinstance(matrix, sparse.spmatrix): - return _graph_from_sparse_matrix(klass, matrix, mode=mode) + return _graph_from_sparse_matrix(cls, matrix, mode=mode) if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() @@ -2159,7 +2143,7 @@ def Adjacency(klass, matrix, mode=ADJ_DIRECTED, *args, **kwargs): return super().Adjacency(matrix, mode=mode) @classmethod - def Weighted_Adjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True): + def Weighted_Adjacency(cls, matrix, mode="directed", attr="weight", loops=True): """Generates a graph from its weighted adjacency matrix. @param matrix: the adjacency matrix. Possible types are: @@ -2168,17 +2152,16 @@ def Weighted_Adjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=Tr - a scipy.sparse matrix (will be converted to a COO matrix, but not to a dense matrix) @param mode: the mode to be used. Possible values are: - - - C{ADJ_DIRECTED} - the graph will be directed and a matrix + - C{"directed"} - the graph will be directed and a matrix element gives the number of edges between two vertex. - - C{ADJ_UNDIRECTED} - alias to C{ADJ_MAX} for convenience. - - C{ADJ_MAX} - undirected graph will be created and the number of + - C{"undirected"} - alias to C{"max"} for convenience. + - C{"max"} - undirected graph will be created and the number of edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} - - C{ADJ_MIN} - like C{ADJ_MAX}, but with M{min(A(i,j), A(j,i))} - - C{ADJ_PLUS} - like C{ADJ_MAX}, but with M{A(i,j) + A(j,i)} - - C{ADJ_UPPER} - undirected graph with the upper right triangle of + - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} + - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} + - C{"upper"} - undirected graph with the upper right triangle of the matrix (including the diagonal) - - C{ADJ_LOWER} - undirected graph with the lower left triangle of + - C{"lower"} - undirected graph with the lower left triangle of the matrix (including the diagonal) These values can also be given as strings without the C{ADJ} prefix. @@ -2200,7 +2183,7 @@ def Weighted_Adjacency(klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=Tr if sparse is not None and isinstance(matrix, sparse.spmatrix): return _graph_from_weighted_sparse_matrix( - klass, + cls, matrix, mode=mode, attr=attr, @@ -2269,8 +2252,6 @@ def write_graphmlz(self, f, compresslevel=9): @param compresslevel: the level of compression. 1 is fastest and produces the least compression, and 9 is slowest and produces the most compression.""" - from igraph.utils import named_temporary_file - with named_temporary_file() as tmpfile: self.write_graphml(tmpfile) outf = gzip.GzipFile(f, "wb", compresslevel) @@ -2318,8 +2299,6 @@ def Read_GraphMLz(cls, f, directed=True, index=0): start from zero, so if you want to load the first graph, specify 0 here. @return: the loaded graph object""" - from igraph.utils import named_temporary_file - with named_temporary_file() as tmpfile: with open(tmpfile, "wb") as outf: copyfileobj(gzip.GzipFile(f, "rb"), outf) @@ -2365,17 +2344,20 @@ def write_picklez(self, fname=None, version=-1): """ import pickle as pickle + file_was_opened = False + if not hasattr(fname, "write"): file_was_opened = True fname = gzip.open(fname, "wb") elif not isinstance(fname, gzip.GzipFile): file_was_opened = True fname = gzip.GzipFile(mode="wb", fileobj=fname) - else: - file_Was_opened = False + result = pickle.dump(self, fname, version) + if file_was_opened: fname.close() + return result @classmethod @@ -2392,7 +2374,6 @@ def Read_Pickle(cls, fname=None): # Probably a file or a file-like object result = pickle.load(fname) else: - fp = None try: fp = open(fname, "rb") except UnicodeDecodeError: @@ -2403,7 +2384,8 @@ def Read_Pickle(cls, fname=None): result = pickle.loads(fname) except TypeError: raise IOError( - "Cannot load file. If fname is a file name, that filename may be incorrect." + "Cannot load file. If fname is a file name, that " + "filename may be incorrect." ) except IOError: try: @@ -2411,35 +2393,20 @@ def Read_Pickle(cls, fname=None): result = pickle.loads(fname) except TypeError: raise IOError( - "Cannot load file. If fname is a file name, that filename may be incorrect." + "Cannot load file. If fname is a file name, that " + "filename may be incorrect." ) - if fp is not None: + else: result = pickle.load(fp) fp.close() - return result - - @classmethod - def Read_Picklez(cls, fname, *args, **kwds): - """Reads a graph from compressed Python pickled format, uncompressing - it on-the-fly. - @param fname: the name of the file or a stream to read from. - @return: the created graph object. - """ - import pickle as pickle + if not isinstance(result, cls): + raise TypeError("unpickled object is not a %s" % cls.__name__) - if hasattr(fname, "read"): - # Probably a file or a file-like object - if isinstance(fname, gzip.GzipFile): - result = pickle.load(fname) - else: - result = pickle.load(gzip.GzipFile(mode="rb", fileobj=fname)) - else: - result = pickle.load(gzip.open(fname, "rb")) return result @classmethod - def Read_Picklez(cls, fname, *args, **kwds): + def Read_Picklez(cls, fname): """Reads a graph from compressed Python pickled format, uncompressing it on-the-fly. @@ -2456,8 +2423,10 @@ def Read_Picklez(cls, fname, *args, **kwds): result = pickle.load(gzip.GzipFile(mode="rb", fileobj=fname)) else: result = pickle.load(gzip.open(fname, "rb")) + if not isinstance(result, cls): raise TypeError("unpickled object is not a %s" % cls.__name__) + return result # pylint: disable-msg=C0301,C0323 @@ -2609,12 +2578,18 @@ def write_svg( print('', file=f) print( - "", + "", file=f, ) print(file=f) print( - ''.format(width, height), end=" ", file=f) @@ -2638,13 +2613,15 @@ def write_svg( print(" ', file=f) @@ -2653,7 +2630,8 @@ def write_svg( edge_color_dict[e_col] = "Arrow2Lend{0}".format(marker_index) print("", file=f) print( - '', + '', file=f, ) @@ -2669,7 +2647,9 @@ def write_svg( print("'.format( + ' '.format( vertex_size, vertex_size * 2, vidx, colors[vidx] ), file=f, @@ -2774,7 +2755,9 @@ def write_svg( font.metrics("linespace") + 2, ) print( - ' '.format( + ' '.format( vertex_width / 2.0, vertex_height / 2.0, vertex_width, @@ -2786,13 +2769,19 @@ def write_svg( ) print( - ' '.format( + ' '.format( vertex_size / 2.0, vidx, font_size ), file=f, ) print( - '{2}'.format( + '' + '{2}'.format( vertex_size / 2.0, vidx, str(labels[vidx]) ), file=f, @@ -2830,7 +2819,7 @@ def _identify_format(cls, filename): # It is most likely a file try: filename = filename.name - except: + except Exception: return None root, ext = os.path.splitext(filename) @@ -3034,9 +3023,9 @@ def DictList( @return: the graph that was constructed """ - def create_list_from_indices(l, n): + def create_list_from_indices(indices, n): result = [None] * n - for i, v in l: + for i, v in indices: result[i] = v return result @@ -3388,8 +3377,8 @@ def Incidence( result, types = cls._Incidence(matrix, directed, mode, multiple, *args, **kwds) result.vs["type"] = types if is_weighted: - weight_attr = "weight" if weighted == True else weighted - _, rows, columns = result.get_incidence() + weight_attr = "weight" if weighted is True else weighted + _, rows, _ = result.get_incidence() num_vertices_of_first_kind = len(rows) for edge in result.es: source, target = edge.tuple @@ -3637,9 +3626,9 @@ def bipartite_projection( """ superclass_meth = super(Graph, self).bipartite_projection - if which == False: + if which is False: which = 0 - elif which == True: + elif which is True: which = 1 if which != 0 and which != 1: which = -1 @@ -3841,13 +3830,13 @@ def __isub__(self, other): self.delete_vertices(other) else: return NotImplemented - elif isinstance(other, _igraph.Vertex): + elif isinstance(other, Vertex): self.delete_vertices(other) - elif isinstance(other, _igraph.VertexSeq): + elif isinstance(other, VertexSeq): self.delete_vertices(other) - elif isinstance(other, _igraph.Edge): + elif isinstance(other, Edge): self.delete_edges(other) - elif isinstance(other, _igraph.EdgeSeq): + elif isinstance(other, EdgeSeq): self.delete_edges(other) else: return NotImplemented @@ -3881,13 +3870,13 @@ def __sub__(self, other): return NotImplemented else: return result - elif isinstance(other, _igraph.Vertex): + elif isinstance(other, Vertex): result.delete_vertices(other) - elif isinstance(other, _igraph.VertexSeq): + elif isinstance(other, VertexSeq): result.delete_vertices(other) - elif isinstance(other, _igraph.Edge): + elif isinstance(other, Edge): result.delete_edges(other) - elif isinstance(other, _igraph.EdgeSeq): + elif isinstance(other, EdgeSeq): result.delete_edges(other) else: return NotImplemented @@ -3937,13 +3926,13 @@ def __coerce__(self, other): """ if isinstance(other, (int, tuple, list, str)): return self, other - if isinstance(other, _igraph.Vertex): + if isinstance(other, Vertex): return self, other - if isinstance(other, _igraph.VertexSeq): + if isinstance(other, VertexSeq): return self, other - if isinstance(other, _igraph.Edge): + if isinstance(other, Edge): return self, other - if isinstance(other, _igraph.EdgeSeq): + if isinstance(other, EdgeSeq): return self, other return NotImplemented @@ -4428,7 +4417,7 @@ def find(self, *args, **kwds): if args: # Selecting first based on positional arguments, then checking # the criteria specified by the (remaining) keyword arguments - vertex = _igraph.VertexSeq.find(self, *args) + vertex = _VertexSeq.find(self, *args) if not kwds: return vertex vs = self.graph.vs.select(vertex.index) @@ -4544,7 +4533,7 @@ def select(self, *args, **kwds): >>> edges = g.vs.select(bs_gt=10, bs_lt=30) @return: the new, filtered vertex sequence""" - vs = _igraph.VertexSeq.select(self, *args) + vs = _VertexSeq.select(self, *args) operators = { "lt": operator.lt, @@ -4676,7 +4665,7 @@ def find(self, *args, **kwds): if args: # Selecting first based on positional arguments, then checking # the criteria specified by the keyword arguments - edge = _igraph.EdgeSeq.find(self, *args) + edge = _EdgeSeq.find(self, *args) if not kwds: return edge es = self.graph.es.select(edge.index) @@ -4833,7 +4822,7 @@ def select(self, *args, **kwds): @return: the new, filtered edge sequence """ - es = _igraph.EdgeSeq.select(self, *args) + es = _EdgeSeq.select(self, *args) is_directed = self.graph.is_directed() def _ensure_set(value): @@ -4947,8 +4936,8 @@ def _ensure_set(value): and e.target in value ] else: - # Optimized version when the edge sequence contains all the edges - # exactly once in increasing order of edge IDs + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs filtered_idxs = [ i for i in candidates @@ -4981,8 +4970,8 @@ def _ensure_set(value): or (e.target in set1 and e.source in set2) ] else: - # Optimized version when the edge sequence contains all the edges - # exactly once in increasing order of edge IDs + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs filtered_idxs = [ i for i in candidates @@ -5223,7 +5212,7 @@ def autocurve(graph, attribute="curved", default=0): multiplicities[u, v].append(edge.index) result = [default] * graph.ecount() - for pair, eids in multiplicities.items(): + for eids in multiplicities.values(): # Is it a single edge? if len(eids) < 2: continue @@ -5322,5 +5311,5 @@ def summary(obj, stream=None, *args, **kwds): stream.write("\n") -config = configuration.init() +config = init_configuration() del construct_graph_from_formula From 568958b43c7687149bee13170870ffade92f04a4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 12:05:15 +0200 Subject: [PATCH 0502/1892] chore: updated changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9edadb98..1e5c555e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ * Updated igraph dependency to 0.9.3. +### Fixed + +* Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` + on large graphs, thanks to @szhorvat and @iosonofabio for fixing the issue. + ### Deprecated * Functions and methods that take string arguments that represent an underlying From a7d4ca18f7a901d4d7509ba34e31d5b0aa2e8a58 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 12:14:51 +0200 Subject: [PATCH 0503/1892] refactor: moved the summary function to igraph.summary so PyDoctor generates nicer filenames in the API docs --- src/igraph/__init__.py | 21 +-------------------- src/igraph/summary.py | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 7a55a9eb9..e7bca8a96 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -125,7 +125,7 @@ quantile, power_law_fit, ) -from igraph.summary import GraphSummary +from igraph.summary import GraphSummary, summary from igraph.utils import ( dbl_epsilon, multidict, @@ -5292,24 +5292,5 @@ def write(graph, filename, *args, **kwds): save = write -def summary(obj, stream=None, *args, **kwds): - """Prints a summary of object o to a given stream - - Positional and keyword arguments not explicitly mentioned here are passed - on to the underlying C{summary()} method of the object if it has any. - - @param obj: the object about which a human-readable summary is requested. - @param stream: the stream to be used. If C{None}, the standard output - will be used. - """ - if stream is None: - stream = sys.stdout - if hasattr(obj, "summary"): - stream.write(obj.summary(*args, **kwds)) - else: - stream.write(str(obj)) - stream.write("\n") - - config = init_configuration() del construct_graph_from_formula diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 24fdf1113..27229dc66 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -8,7 +8,7 @@ from texttable import Texttable from textwrap import TextWrapper -__all__ = ("GraphSummary",) +__all__ = ("GraphSummary", "summary") __license__ = """\ Copyright (C) 2006-2012 Tamás Nepusz @@ -373,3 +373,22 @@ def __str__(self): return "\n".join("\n".join(self.wrapper.wrap(line)) for line in output) return "\n".join(output) + + +def summary(obj, stream=None, *args, **kwds): + """Prints a summary of object o to a given stream + + Positional and keyword arguments not explicitly mentioned here are passed + on to the underlying C{summary()} method of the object if it has any. + + @param obj: the object about which a human-readable summary is requested. + @param stream: the stream to be used. If C{None}, the standard output + will be used. + """ + if stream is None: + stream = sys.stdout + if hasattr(obj, "summary"): + stream.write(obj.summary(*args, **kwds)) + else: + stream.write(str(obj)) + stream.write("\n") From 58975cb05a7d4f1ef8c170833de65a0fb9cae326 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 12:35:20 +0200 Subject: [PATCH 0504/1892] doc: added Dash docset generator --- scripts/mkdoc.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 96826951c..71888b4ea 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -50,5 +50,26 @@ echo "Generating HTML documentation..." # PDF not supported by PyDoctor +DOC2DASH=`which doc2dash 2>/dev/null || true` +if [ "x$DOC2DASH" != x ]; then + echo "Generating Dash docset..." + "$DOC2DASH" \ + --online-redirect-url "https://igraph.org/python/doc/api" \ + --name "python-igraph" \ + -d "${DOC_API_FOLDER}" \ + -f \ + "${DOC_API_FOLDER}/html" + DASH_READY=1 +else + echo "WARNING: doc2dash not installed, skipping Dash docset generation." + DASH_READY=0 +fi + +echo "" +echo "HTML API documentation generated in ${DOC_API_FOLDER}/html" +if [ "x${DASH_READY}" = x1 ]; then + echo "Dash docset generated in ${DOC_API_FOLDER}/python-igraph.docset" +fi + cd "$PWD" From f8a3d04b5036a964f1c980fc427d5c34467457e6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 28 May 2021 10:29:14 +1000 Subject: [PATCH 0505/1892] Speed up from_graph_tool and clean up a little --- src/igraph/__init__.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e7bca8a96..45b59393d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1906,9 +1906,6 @@ def from_networkx(cls, g): @param g: networkx Graph or DiGraph """ - import networkx as nx - from collections import defaultdict - # Graph attributes gattr = dict(g.graph) @@ -1931,7 +1928,7 @@ def from_networkx(cls, g): # Edges and edge attributes eattr_names = {name for (_, _, data) in g.edges.data() for name in data} - eattr = defaultdict(list) + eattr = {name: [] for name in eattr_names} edges = [] for (u, v, data) in g.edges.data(): edges.append((vd[u], vd[v])) @@ -2029,13 +2026,19 @@ def from_graph_tool(cls, g): for i in range(vcount): graph.vs[i][key] = prop[i] - # Edges - # NOTE: the order the edges are put in is necessary to set the - # attributes later on + # Edges and edge attributes + # NOTE: graph-tool is quite strongly typed, so each property is always + # defined for all edges, using default values for the type. E.g. for a + # string property/attribute the missing edges get an empty string. + edges = [] + eattr_names = list(g.edge_properties) + eattr = {name: [] for name in eattr_names} for e in g.edges(): - edge = graph.add_edge(int(e.source()), int(e.target())) - for key, val in list(g.edge_properties.items()): - edge[key] = val[e] + edges.append((int(e.source()), int(e.target()))) + for name, attr_map in list(g.edge_properties.items()): + eattr[name].append(attr_map[e]) + + graph.add_edges(edges, eattr) return graph From 6915ff6b0d3ccc4e60b0096626456263339efc32 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 28 May 2021 20:19:50 +1000 Subject: [PATCH 0506/1892] Skip list constructor --- src/igraph/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 45b59393d..606b2d3d1 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2021,7 +2021,7 @@ def from_graph_tool(cls, g): graph = cls(n=vcount, directed=g.is_directed(), graph_attrs=gattr) # Node attributes - for key, val in list(g.vertex_properties.items()): + for key, val in g.vertex_properties.items(): prop = val.get_array() for i in range(vcount): graph.vs[i][key] = prop[i] @@ -2035,7 +2035,7 @@ def from_graph_tool(cls, g): eattr = {name: [] for name in eattr_names} for e in g.edges(): edges.append((int(e.source()), int(e.target()))) - for name, attr_map in list(g.edge_properties.items()): + for name, attr_map in g.edge_properties.items(): eattr[name].append(attr_map[e]) graph.add_edges(edges, eattr) From 0c0ebd77907a2be6373476dae0bbfc754f419f6b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 28 May 2021 14:02:45 +0200 Subject: [PATCH 0507/1892] feat: added Graph.to_networkx(create_using=...) --- CHANGELOG.md | 3 +++ src/igraph/__init__.py | 25 +++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e5c555e4..f6fd715fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ * `Graph.to_directed()` now supports a `mode=...` keyword argument. +* Added a `create_using=...` keyword argument to `Graph.to_networkx()` to + let the user specify which NetworkX class to use when converting the graph. + ### Changed * Updated igraph dependency to 0.9.3. diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 606b2d3d1..a32dfdcee 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1867,21 +1867,24 @@ def maximum_bipartite_matching(self, types="type", weights=None, eps=None): ############################################# # Auxiliary I/O functions - def to_networkx(self): - """Converts the graph to networkx format""" + def to_networkx(self, create_using=None): + """Converts the graph to networkx format. + + @param create_using: specifies which NetworkX graph class to use when + constructing the graph. C{None} means to let igraph infer the most + appropriate class based on whether the graph is directed and whether + it has multi-edges. + """ import networkx as nx # Graph: decide on directness and mutliplicity - if any(self.is_multiple()): - if self.is_directed(): - cls = nx.MultiDiGraph + if create_using is None: + if self.has_multiple(): + cls = nx.MultiDiGraph if self.is_directed() else nx.MultiGraph else: - cls = nx.MultiGraph + cls = nx.DiGraph if self.is_directed() else nx.Graph else: - if self.is_directed(): - cls = nx.DiGraph - else: - cls = nx.Graph + cls = create_using # Graph attributes kw = {x: self[x] for x in self.attributes()} @@ -1889,6 +1892,8 @@ def to_networkx(self): # Nodes and node attributes for i, v in enumerate(self.vs): + # TODO: use _nx_name if the attribute is present so we can achieve + # a lossless round-trip in terms of vertex names g.add_node(i, **v.attributes()) # Edges and edge attributes From d12808c6fac7b231128b86d8640ccc85c907fee1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 12:14:17 +0200 Subject: [PATCH 0508/1892] fix: fix comments in mkdoc.sh -- it takes no arguments now [ci skip] --- scripts/mkdoc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 71888b4ea..b49ffc3aa 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -2,7 +2,7 @@ # # Creates the API documentation for igraph's Python interface using PyDoctor # -# Usage: ./mkdoc.sh [--sync] [directory] +# Usage: ./mkdoc.sh SCRIPTS_FOLDER=`dirname $0` From c8997ad1c4825a3469341322036a9784be665436 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 31 May 2021 19:52:39 +1000 Subject: [PATCH 0509/1892] A bit more docs for matplotlib plotting --- doc/source/tutorial.rst | 17 +++++++++++++---- src/igraph/drawing/__init__.py | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index d72d0ee26..6564c9b67 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -435,7 +435,7 @@ degree or betweenness centrality. You can do that with the tools presented so fa some basic Python knowledge, but since it is a common task to select vertices and edges based on attributes or structural properties, |igraph| gives you an easier way to do that: ->>> g.vs.select(_degree = g.maxdegree())["name"] +>>> g.vs.select(_degree=g.maxdegree())["name"] ["Alice", "Bob"] The syntax may seem a little bit awkward for the first sight, so let's try to interpret @@ -741,7 +741,7 @@ For instance, we can plot our imaginary social network with the Kamada-Kawai layout algorithm as follows: >>> layout = g.layout("kk") ->>> plot(g, layout = layout) +>>> plot(g, layout=layout) This should open an external image viewer showing a visual representation of the network, something like the one on the following figure (although the exact placement of @@ -753,6 +753,13 @@ nodes may be different on your machine since the layout is not deterministic): Our social network with the Kamada-Kawai layout algorithm +If you prefer to use `matplotlib`_ as a default plotting engine, create an axes and use +the ``target`` argument: + +>>> import matplotlib.pyplot as plt +>>> fig, ax = plt.subplots() +>>> plot(g, layout=layout, target=ax) + Hmm, this is not too pretty so far. A trivial addition would be to use the names as the vertex labels and to color the vertices according to the gender. Vertex labels are taken from the ``label`` attribute by default and vertex colors are determined by the @@ -761,7 +768,8 @@ from the ``label`` attribute by default and vertex colors are determined by the >>> g.vs["label"] = g.vs["name"] >>> color_dict = {"m": "blue", "f": "pink"} >>> g.vs["color"] = [color_dict[gender] for gender in g.vs["gender"]] ->>> plot(g, layout = layout, bbox = (300, 300), margin = 20) +>>> plot(g, layout=layout, bbox=(300, 300), margin=20) +>>> plot(g, layout=layout, bbox=(300, 300), margin=20, target=ax) # matplotlib version Note that we are simply re-using the previous layout object here, but we also specified that we need a smaller plot (300 x 300 pixels) and a larger margin around the graph @@ -777,7 +785,7 @@ Instead of specifying the visual properties as vertex and edge attributes, you c also give them as keyword arguments to :func:`plot`: >>> color_dict = {"m": "blue", "f": "pink"} ->>> plot(g, layout = layout, vertex_color = [color_dict[gender] for gender in g.vs["gender"]]) +>>> plot(g, layout=layout, vertex_color=[color_dict[gender] for gender in g.vs["gender"]]) This latter approach is preferred if you want to keep the properties of the visual representation of your graph separate from the graph itself. You can simply set up @@ -1053,3 +1061,4 @@ out immediately. .. _API documentation: https://igraph.org/python/doc/api/index.html .. _Graph class: https://igraph.org/python/doc/api/igraph.Graph.html .. _Discourse group: https://igraph.discourse.group +.. _matplotlib: https://matplotlib.org/ diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 8c9723b40..372b8bac0 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -423,6 +423,10 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @param target: the target where the object should be plotted. It can be one of the following types: + - C{matplotib.axes.Axes} -- a matplotlib/pyplot axes in which the + graph will be plotted. Drawing, saving to file, etc. is mostly + delegated to the chosen matplotlib backend. + - C{string} -- a file with the given name will be created and an appropriate Cairo surface will be attached to it. The supported image formats are: PNG, PDF, SVG and PostScript. From 75e0c5fe18dadb73a9e5e4edcf1bacc3b2110c8a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 31 May 2021 20:18:26 +1000 Subject: [PATCH 0510/1892] Improvements in the wording --- doc/source/tutorial.rst | 4 ++-- src/igraph/drawing/__init__.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 6564c9b67..17a584f49 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -753,8 +753,8 @@ nodes may be different on your machine since the layout is not deterministic): Our social network with the Kamada-Kawai layout algorithm -If you prefer to use `matplotlib`_ as a default plotting engine, create an axes and use -the ``target`` argument: +If you prefer to use `matplotlib`_ as a plotting engine, create an axes and use the +``target`` argument: >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 372b8bac0..db34f5a0c 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -424,8 +424,9 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): of the following types: - C{matplotib.axes.Axes} -- a matplotlib/pyplot axes in which the - graph will be plotted. Drawing, saving to file, etc. is mostly - delegated to the chosen matplotlib backend. + graph will be plotted. Drawing is delegated to the chosen matplotlib + backend, and you can use interactive backends and matplotlib + functions to save to file as well. - C{string} -- a file with the given name will be created and an appropriate Cairo surface will be attached to it. The supported image From 420728378bb70225a30985f15b08eb1e609d9e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Fri, 28 May 2021 14:22:35 +0200 Subject: [PATCH 0511/1892] docs: clarify add_edge() performance --- src/igraph/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a32dfdcee..70681c303 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -344,13 +344,17 @@ def add_edge(self, source, target, **kwds): Keyword arguments (except the source and target arguments) will be assigned to the edge as attributes. + + The performance cost of adding a single edge or several edges + to a graph is similar. Thus, when adding several edges, a single + C{add_edges()} call is more efficient than multiple C{add_edge()} calls. @param source: the source vertex of the edge or its name. @param target: the target vertex of the edge or its name. @return: the newly added edge as an L{Edge} object. Use C{add_edges([(source, target)])} if you don't need the L{Edge} - object and want to avoid the overhead of creating t. + object and want to avoid the overhead of creating it. """ eid = self.ecount() self.add_edges([(source, target)]) From d53b9bc818122a0dd7cdf068090f717990808d78 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 13:02:34 +0200 Subject: [PATCH 0512/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index a4be06863..05e9977f1 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit a4be0686333f2e9fe38b3bc7a23b9073e848f77a +Subproject commit 05e9977f117821af26fe4b0dda0653d9d948c488 From 4fffe2e2c7e3474c5ea70c0aa50594e9b49d36a3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 13:57:52 +0200 Subject: [PATCH 0513/1892] fix: deprecate UbiGraphDrawer, list MatplotlibGraphDrawer in docstrings instead --- src/igraph/drawing/graph.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index d46b45538..5a70ce8af 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -4,7 +4,7 @@ This module contains routines to draw graphs on: - Cairo surfaces (L{DefaultGraphDrawer}) - - UbiGraph displays (L{UbiGraphDrawer}, see U{http://ubietylab.net/ubigraph}) + - Matplotlib axes (L{MatplotlibGraphDrawer}) It also contains routines to send an igraph graph directly to (U{Cytoscape}) using the @@ -34,7 +34,7 @@ from igraph.drawing.vertex import DefaultVertexDrawer from igraph.layout import Layout -__all__ = ("DefaultGraphDrawer", "UbiGraphDrawer", "CytoscapeGraphDrawer") +__all__ = ("DefaultGraphDrawer", "MatplotlibGraphDrawer", "CytoscapeGraphDrawer", "UbiGraphDrawer") __license__ = "GPL" cairo = find_cairo() @@ -542,6 +542,11 @@ class UbiGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): The drawer also has two attributes, C{vertex_defaults} and C{edge_defaults}. These are dictionaries that can be used to set default values for the vertex/edge attributes in Ubigraph. + + @deprecated: UbiGraph has not received updates since 2008 and is now not + available for download (at least not from the official sources). + The UbiGraph graph drawer will be removed from python-igraph in + 0.10.0. """ def __init__(self, url="http://localhost:20738/RPC2"): @@ -551,6 +556,11 @@ def __init__(self, url="http://localhost:20738/RPC2"): self.vertex_defaults = dict(color="#ff0000", shape="cube", size=1.0) self.edge_defaults = dict(color="#ffffff", width=1.0) + warn( + "UbiGraphDrawer is deprecated from python-igraph 0.9.4", + DeprecationWarning + ) + def draw(self, graph, *args, **kwds): """Draws the given graph on an UbiGraph display. From 89a8b9dc948d79443d2ac51c3e6b6046e94e3b2c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 13:58:42 +0200 Subject: [PATCH 0514/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6fd715fe..6a7910dab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ * `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. +* `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project + is not maintained since 2008. ## 0.9.1 From 56dc1b8dc3291fb4ac83a3da8f63588360bf20cd Mon Sep 17 00:00:00 2001 From: Casper van Elteren Date: Mon, 31 May 2021 13:58:58 +0200 Subject: [PATCH 0515/1892] fixed autocurve mpl (#406) * fixed autocurve mpl * fix: make sure that edge_curved=... is also respected when calling plot() Co-authored-by: Tamas Nepusz --- src/igraph/drawing/graph.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 5a70ce8af..c3302c06f 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1190,7 +1190,13 @@ def callback_edge_offset(event): if default is True: default = 0.5 default = float(default) - kwds["edge_curved"] = autocurve(graph, attribute=None, default=default) + ecurved = autocurve(graph, attribute=None, default=default) + elif "edge_curved" in kwds: + ecurved = kwds["edge_curved"] + elif "curved" in graph.edge_attributes(): + ecurved = graph.es["curved"] + else: + ecurved = [0] * ne # Arrow style for directed and undirected graphs if graph.is_directed(): @@ -1204,7 +1210,6 @@ def callback_edge_offset(event): # Edge coordinates and curvature nloops = [0 for x in range(ne)] - has_curved = "curved" in graph.es.attributes() arrows = [] for ie, edge in enumerate(graph.es): src, tgt = edge.source, edge.target @@ -1284,14 +1289,14 @@ def callback_edge_offset(event): ) else: - curved = edge["curved"] if has_curved else False + curved = ecurved[ie] if curved: - aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + aux1 = (2 * x1 + x2) / 3.0 - curved * 0.5 * (y2 - y1), ( 2 * y1 + y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + ) / 3.0 + curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - curved * 0.5 * (y2 - y1), ( y1 + 2 * y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + ) / 3.0 + curved * 0.5 * (x2 - x1) start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) From 0b74f994ceaf15ae47539167f5faadd291e656c0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 13:59:38 +0200 Subject: [PATCH 0516/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7910dab..8f56df502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ * Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` on large graphs, thanks to @szhorvat and @iosonofabio for fixing the issue. +* Fixed the `autocurve=...` keyword argument of `plot()` when using the + Matplotlib backend. + ### Deprecated * Functions and methods that take string arguments that represent an underlying From 6267902388b22a17ef16ab4ada6911cdffbb07d9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 14:05:53 +0200 Subject: [PATCH 0517/1892] chore: removed __license__ vars from most of the modules, a single LICENSE file at the root is enough [ci skip] --- src/igraph/clustering.py | 20 -------------------- src/igraph/configuration.py | 20 -------------------- src/igraph/cut.py | 20 -------------------- src/igraph/datatypes.py | 20 -------------------- src/igraph/drawing/__init__.py | 2 -- src/igraph/drawing/colors.py | 20 -------------------- src/igraph/drawing/coord.py | 2 -- src/igraph/drawing/edge.py | 2 -- src/igraph/drawing/graph.py | 21 +++++++++++---------- src/igraph/drawing/shapes.py | 20 -------------------- src/igraph/drawing/text.py | 1 - src/igraph/drawing/utils.py | 1 - src/igraph/drawing/vertex.py | 1 - src/igraph/formula.py | 20 -------------------- src/igraph/layout.py | 20 -------------------- src/igraph/matching.py | 21 --------------------- src/igraph/operators.py | 20 -------------------- src/igraph/remote/gephi.py | 19 ------------------- src/igraph/sparse_matrix.py | 18 ------------------ src/igraph/statistics.py | 20 -------------------- src/igraph/utils.py | 19 ------------------- 21 files changed, 11 insertions(+), 296 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 3c00b3c95..37200d0f6 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -2,26 +2,6 @@ # -*- coding: utf-8 -*- """Classes related to graph clustering.""" -__license__ = u""" -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - from copy import deepcopy from math import pi from io import StringIO diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index f39a6cdd3..039012b6d 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -8,26 +8,6 @@ as well as saving them to and retrieving them from disk. """ -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - import sys if sys.version_info < (3, 2): diff --git a/src/igraph/cut.py b/src/igraph/cut.py index 2d7a5d590..c2b39b7da 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -4,26 +4,6 @@ from igraph.clustering import VertexClustering -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - class Cut(VertexClustering): """A cut of a given graph. diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index 75a7bae5f..ce6ee6990 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -4,26 +4,6 @@ from itertools import islice -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - class Matrix(object): """Simple matrix data type. diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index db34f5a0c..6e90aa247 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -38,8 +38,6 @@ __all__ = ("BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot") -__license__ = "GPL" - cairo = find_cairo() ##################################################################### diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 049cfeb99..72e3e80ac 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -4,26 +4,6 @@ Color handling functions. """ -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - from igraph.datatypes import Matrix from igraph.utils import str_to_orientation from math import ceil diff --git a/src/igraph/drawing/coord.py b/src/igraph/drawing/coord.py index a5e51e622..57d742882 100644 --- a/src/igraph/drawing/coord.py +++ b/src/igraph/drawing/coord.py @@ -5,8 +5,6 @@ from igraph.drawing.baseclasses import AbstractCairoDrawer from igraph.drawing.utils import BoundingBox -__license__ = "GPL" - ##################################################################### diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 100cee5c6..f01c3e9a7 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -11,8 +11,6 @@ "TaperedEdgeDrawer", ) -__license__ = "GPL" - from igraph.drawing.colors import clamp from igraph.drawing.metamagic import AttributeCollectorBase from igraph.drawing.text import TextAlignment diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index c3302c06f..b47587b4f 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -13,8 +13,6 @@ network from Cytoscape and convert it to igraph format. """ -from collections import defaultdict - from math import atan2, cos, pi, sin, tan, sqrt from warnings import warn @@ -34,8 +32,10 @@ from igraph.drawing.vertex import DefaultVertexDrawer from igraph.layout import Layout -__all__ = ("DefaultGraphDrawer", "MatplotlibGraphDrawer", "CytoscapeGraphDrawer", "UbiGraphDrawer") -__license__ = "GPL" +__all__ = ( + "DefaultGraphDrawer", "MatplotlibGraphDrawer", "CytoscapeGraphDrawer", + "UbiGraphDrawer" +) cairo = find_cairo() @@ -442,7 +442,7 @@ def draw(self, graph, palette, *args, **kwds): # Intersection at bottom edge of label try: cx += h / tan(alpha) - except: + except Exception: pass # tan(alpha) == inf cy -= h elif alpha > gamma and alpha <= gamma + 2 * beta: @@ -453,7 +453,7 @@ def draw(self, graph, palette, *args, **kwds): # Intersection at top edge of label try: cx -= h / tan(alpha) - except: + except Exception: pass # tan(alpha) == inf cy += h # Draw the label @@ -913,10 +913,11 @@ class GephiGraphStreamingDrawer(AbstractGraphDrawer): The Gephi graph streaming format is a simple JSON-based format that can be used to post mutations to a graph (i.e. node and edge additions, removals and updates) - to a remote component. For instance, one can open up Gephi (U{http://www.gephi.org}), - install the Gephi graph streaming plugin and then send a graph from igraph - straight into the Gephi window by using C{GephiGraphStreamingDrawer} with the - appropriate URL where Gephi is listening. + to a remote component. For instance, one can open up Gephi + (U{http://www.gephi.org}), install the Gephi graph streaming plugin and then + send a graph from igraph straight into the Gephi window by using + C{GephiGraphStreamingDrawer} with the appropriate URL where Gephi is + listening. The C{connection} property exposes the L{GephiConnection} that the drawer uses. The drawer also has a property called C{streamer} which exposes the underlying diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 0a3cd81a9..bb7eec3e5 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -19,26 +19,6 @@ __all__ = ("ShapeDrawerDirectory",) -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - from math import atan2, copysign, cos, pi, sin import sys diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index 6de3b3b9f..7d00624bd 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -8,7 +8,6 @@ from warnings import warn __all__ = ("TextAlignment", "TextDrawer") -__license__ = "GPL" __docformat__ = "restructuredtext en" diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 68f1b9b60..39a16e8fe 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -7,7 +7,6 @@ from operator import itemgetter __all__ = ("BoundingBox", "Point", "Rectangle") -__license__ = "GPL" ##################################################################### diff --git a/src/igraph/drawing/vertex.py b/src/igraph/drawing/vertex.py index 9f4d082a0..fbae32e3f 100644 --- a/src/igraph/drawing/vertex.py +++ b/src/igraph/drawing/vertex.py @@ -11,7 +11,6 @@ from math import pi __all__ = ("AbstractVertexDrawer", "AbstractCairoVertexDrawer", "DefaultVertexDrawer") -__license__ = "GPL" class AbstractVertexDrawer(AbstractDrawer): diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 2b1f26aa6..9b31b0aed 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -17,26 +17,6 @@ __all__ = ("construct_graph_from_formula",) -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - def generate_edges(formula): """Parses an edge specification from the head of the given diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 38bd3150c..eaf3e54c6 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -12,26 +12,6 @@ from igraph.drawing.utils import BoundingBox from igraph.statistics import RunningMean -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - class Layout(object): """Represents the layout of a graph. diff --git a/src/igraph/matching.py b/src/igraph/matching.py index 85d40d226..5ec97a456 100644 --- a/src/igraph/matching.py +++ b/src/igraph/matching.py @@ -2,29 +2,8 @@ # -*- coding: utf-8 -*- """Classes representing matchings on graphs.""" -from igraph.clustering import VertexClustering from igraph._igraph import Vertex -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - class Matching(object): """A matching of vertices in a graph. diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 8fe113b5c..eaf5b0075 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -2,28 +2,8 @@ # -*- coding: utf-8 -*- """Implementation of union, disjoint union and intersection operators.""" - __all__ = ("disjoint_union", "union", "intersection") __docformat__ = "restructuredtext en" -__license__ = """ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" from igraph._igraph import GraphBase, _union, _intersection, _disjoint_union diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index 74b9d0d46..9ae527dba 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -7,25 +7,6 @@ __all__ = ("GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat") __docformat__ = "restructuredtext en" -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" class GephiConnection(object): diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index 132d68bc4..bcf5436fe 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -6,24 +6,6 @@ __all__ = () __docformat__ = "restructuredtext en" -__license__ = u""" -Copyright (C) 2021 igraph development team - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" from operator import add from igraph._igraph import ( diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 951db6d9c..2a46e044e 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -4,26 +4,6 @@ Statistics related stuff in igraph """ -__license__ = """\ -Copyright (C) 2006-2012 Tamas Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - import math __all__ = ( diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 085f4a5ff..4b86e5dd6 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -22,25 +22,6 @@ ) __docformat__ = "restructuredtext en" -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" def _is_running_in_ipython(): From 6fe65c8b9c05f35777a3e4ec3dc8f637332afd1d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 14:21:56 +0200 Subject: [PATCH 0518/1892] style: fix flake8 linter warnings --- src/igraph/__init__.py | 2 +- src/igraph/app/shell.py | 7 +++---- src/igraph/clustering.py | 6 +++--- src/igraph/datatypes.py | 6 +++--- src/igraph/drawing/__init__.py | 1 - src/igraph/drawing/colors.py | 10 +++++----- src/igraph/drawing/edge.py | 13 ++++++++----- src/igraph/drawing/metamagic.py | 1 + src/igraph/drawing/utils.py | 4 +++- src/igraph/formula.py | 9 ++++++--- src/igraph/remote/gephi.py | 4 +++- src/igraph/statistics.py | 3 ++- src/igraph/summary.py | 23 ++--------------------- 13 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 70681c303..0944b6c32 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -344,7 +344,7 @@ def add_edge(self, source, target, **kwds): Keyword arguments (except the source and target arguments) will be assigned to the edge as attributes. - + The performance cost of adding a single edge or several edges to a graph is similar. Thus, when adding several edges, a single C{add_edges()} call is more efficient than multiple C{add_edge()} calls. diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index 6defa2449..0b049d5fb 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -23,9 +23,8 @@ import re import sys -# pylint: disable-msg=W0401 -# W0401: wildcard import. That's exactly what we need for the shell. -from igraph import __version__, set_progress_handler, set_status_handler +from igraph import __version__ +from igraph._igraph import set_progress_handler, set_status_handler from igraph.configuration import Configuration @@ -193,7 +192,7 @@ def render(self, template): the corresponding terminal control string (if it's defined) or '' (if it's not). """ - return re.sub("r\$\$|\${\w+}", self._render_sub, template) + return re.sub("r\$\$|\${\w+}", self._render_sub, template) # noqa: W605 def _render_sub(self, match): """Helper function for L{render}""" diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 37200d0f6..644c06873 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -383,7 +383,7 @@ def _recalculate_modularity_safe(self): """ try: return self.recalculate_modularity() - except: + except Exception: return None finally: self._modularity_dirty = False @@ -1467,7 +1467,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: prepare_groups = True - elif kwds["mark_groups"] == True: + elif kwds["mark_groups"] is True: prepare_groups = True if prepare_groups: @@ -1501,7 +1501,7 @@ def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): # Lists, tuples try: first = mark_groups[0] - except: + except Exception: # Hmm. Maybe not a list or tuple? first = None if first is not None: diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index ce6ee6990..6dab7223a 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -351,9 +351,9 @@ def __plot__(self, context, bbox, palette, **kwds): col_names = [str(name) for name in islice(col_names, self._ncol)] if len(col_names) < self._ncol: col_names.extend([""] * (self._ncol - len(col_names))) - if values == False: + if values is False: values = None - if values == True: + if values is True: values = self if isinstance(values, list): values = Matrix(list) @@ -428,7 +428,7 @@ def __plot__(self, context, bbox, palette, **kwds): # Draw matrix x, y = ox, oy if style is None: - fill = lambda: None + fill = lambda: None # noqa: E731 else: fill = context.fill_preserve for row in self: diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 6e90aa247..c428f62e7 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -16,7 +16,6 @@ """ -from io import StringIO from warnings import warn import os diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 72e3e80ac..4532fb173 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -339,13 +339,13 @@ def _get(self, v): class PrecalculatedPalette(Palette): """A palette that returns colors from a pre-calculated list of colors""" - def __init__(self, l): + def __init__(self, items): """Creates the palette backed by the given list. The list must contain RGBA quadruplets or color names, which will be resolved first by L{color_name_to_rgba()}. Anything that is understood by L{color_name_to_rgba()} is OK here.""" - Palette.__init__(self, len(l)) - for idx, color in enumerate(l): + Palette.__init__(self, len(items)) + for idx, color in enumerate(items): if isinstance(color, str): color = color_name_to_rgba(color) self._cache[idx] = color @@ -555,7 +555,7 @@ def darken(color, ratio=0.5): return (red * ratio, green * ratio, blue * ratio, alpha) -def hsla_to_rgba(h, s, l, alpha=1.0): +def hsla_to_rgba(h, s, l, alpha=1.0): # noqa: E741 """Converts a color given by its HSLA coordinates (hue, saturation, lightness, alpha) to RGBA coordinates. @@ -584,7 +584,7 @@ def hsla_to_rgba(h, s, l, alpha=1.0): return (c + m, m, x + m, alpha) -def hsl_to_rgb(h, s, l): +def hsl_to_rgb(h, s, l): # noqa: E741 """Converts a color given by its HSL coordinates (hue, saturation, lightness) to RGB coordinates. diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index f01c3e9a7..95e87b1c2 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -243,7 +243,6 @@ def intersect_bezier_circle( t0 = 1.0 t1 = 1.0 - radius / source_target_distance - xt0, yt0 = x3, y3 xt1, yt1 = bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) distance_t0 = 0 @@ -254,7 +253,8 @@ def intersect_bezier_circle( t_new = (t0 + t1) / 2.0 else: if abs(distance_t1 - radius) < abs(distance_t0 - radius): - # If t1 gets us closer to the circumference step in the same direction + # If t1 gets us closer to the circumference step in the + # same direction t_new = t1 + (t1 - t0) / 2.0 else: t_new = t1 - (t1 - t0) @@ -327,8 +327,10 @@ def intersect_bezier_circle( x_arrow_mid - x_src ) - # Offset the second control point (aux2) such that it falls precisely on the normal to the arrow base vector - # Strictly speaking, offset_length is the offset length divided by the length of the arrow base vector. + # Offset the second control point (aux2) such that it falls precisely + # on the normal to the arrow base vector. Strictly speaking, + # offset_length is the offset length divided by the length of the + # arrow base vector. offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + ( y_arrow_mid - aux2[1] ) * y_arrow_base_vec @@ -341,7 +343,8 @@ def intersect_bezier_circle( aux2[1] + y_arrow_base_vec * offset_length, ) - # Draw tthe curve from the first vertex to the midpoint of the base of the arrow head + # Draw the curve from the first vertex to the midpoint of the base + # of the arrow head ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], x_arrow_mid, y_arrow_mid) else: # Determine where the edge intersects the circumference of the diff --git a/src/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py index 164aef3a9..150e1ceda 100644 --- a/src/igraph/drawing/metamagic.py +++ b/src/igraph/drawing/metamagic.py @@ -67,6 +67,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): __all__ = ("AttributeSpecification", "AttributeCollectorBase") + # pylint: disable-msg=R0903 # R0903: too few public methods class AttributeSpecification(object): diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 39a16e8fe..051d34ede 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -462,7 +462,9 @@ def find_matplotlib(): if has_mpl: import matplotlib.pyplot as plt else: - plt = FakeModule("You need to install matplotlib.pyplot to use this functionality") + plt = FakeModule( + "You need to install matplotlib.pyplot to use this functionality" + ) return mpl, plt diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 9b31b0aed..ad5473d15 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -23,8 +23,10 @@ def generate_edges(formula): formula part and yields the following: - startpoint(s) of the edge by vertex names - - endpoint(s) of the edge by names or an empty list if the vertices are isolated - - a pair of bools to denote whether we had arrowheads at the start and end vertices + - endpoint(s) of the edge by names or an empty list if the vertices are + isolated + - a pair of bools to denote whether we had arrowheads at the start and end + vertices """ if formula == "": yield [], [""], [False, False] @@ -72,7 +74,8 @@ def generate_edges(formula): pass else: msg = ( - "invalid token found in edge specification: %s; token_type=%r; tok=%r" + "invalid token found in edge specification: %s; " + "token_type=%r; tok=%r" % (formula, token_type, tok) ) raise SyntaxError(msg) diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index 9ae527dba..c75651935 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -3,7 +3,9 @@ """Classes that help igraph communicate with Gephi (http://www.gephi.org).""" import json -import urllib.request, urllib.error, urllib.parse +import urllib.error +import urllib.parse +import urllib.request __all__ = ("GephiConnection", "GephiGraphStreamer", "GephiGraphStreamingAPIFormat") __docformat__ = "restructuredtext en" diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 2a46e044e..c1e1be2cf 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -25,7 +25,8 @@ class FittedPowerLaw(object): >>> result = power_law_fit([1, 2, 3, 4, 5, 6]) >>> result # doctest:+ELLIPSIS - FittedPowerLaw(continuous=False, alpha=2.42..., xmin=3.0, L=-7.54..., D=0.21..., p=0.993...) + FittedPowerLaw(continuous=False, alpha=2.42..., xmin=3.0, L=-7.54..., \ +D=0.21..., p=0.993...) >>> print(result) # doctest:+ELLIPSIS Fitted power-law distribution on discrete data diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 27229dc66..022f50479 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -2,6 +2,8 @@ # -*- coding: utf-8 -*- """Summary representation of a graph.""" +import sys + from igraph.statistics import median from itertools import islice from math import ceil @@ -10,26 +12,6 @@ __all__ = ("GraphSummary", "summary") -__license__ = """\ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -""" - class FakeWrapper(object): """Object whose interface is compatible with C{textwrap.TextWrapper} @@ -143,7 +125,6 @@ def _construct_edgelist_adjlist(self): """Constructs the part in the summary that prints the edge list in an adjacency list format.""" result = [self._edges_header] - arrow = self._arrow_format if self._graph.vcount() == 0: return From c499db202663ed1bc4736ab62e30a1395713dffe Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 14:24:13 +0200 Subject: [PATCH 0519/1892] style: removed unneeded pylint linter comments as we use flake8 now --- src/igraph/__init__.py | 4 ---- src/igraph/app/shell.py | 7 ------- src/igraph/clustering.py | 4 ---- src/igraph/configuration.py | 2 -- src/igraph/cut.py | 3 --- src/igraph/datatypes.py | 6 ------ src/igraph/drawing/__init__.py | 4 ---- src/igraph/drawing/baseclasses.py | 4 ---- src/igraph/drawing/coord.py | 2 -- src/igraph/drawing/graph.py | 9 --------- src/igraph/drawing/metamagic.py | 4 ---- src/igraph/drawing/shapes.py | 3 --- src/igraph/drawing/utils.py | 6 ------ src/igraph/statistics.py | 2 -- 14 files changed, 60 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 0944b6c32..adf896538 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -158,7 +158,6 @@ def deprecated(message): warn(message, DeprecationWarning, stacklevel=3) -# pylint: disable-msg=E1101 class Graph(GraphBase): """Generic graph. @@ -2441,9 +2440,6 @@ def Read_Picklez(cls, fname): return result - # pylint: disable-msg=C0301,C0323 - # C0301: line too long. - # C0323: operator not followed by a space - well, print >>f looks OK def write_svg( self, fname, diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index 0b049d5fb..e553cf69d 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -28,9 +28,6 @@ from igraph.configuration import Configuration -# pylint: disable-msg=C0103,R0903 -# C0103: invalid name. Disabled because this is a third-party class. -# R0903: too few public methods. class TerminalController: """ A class that can be used to portably generate formatted output to @@ -311,14 +308,12 @@ def supports_status_messages(self): called C{_status_handler}.""" return hasattr(self, "_status_handler") - # pylint: disable-msg=E1101 def get_progress_handler(self): """Returns the progress handler (if exists) or None (if not).""" if self.supports_progress_bar(): return self._progress_handler return None - # pylint: disable-msg=E1101 def get_status_handler(self): """Returns the status handler (if exists) or None (if not).""" if self.supports_status_messages(): @@ -524,8 +519,6 @@ def main(): shell = None for shell_class in shell_classes: - # pylint: disable-msg=W0703 - # W0703: catch "Exception" try: shell = shell_class() break diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 644c06873..665fc9f3a 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -246,7 +246,6 @@ def __init__( else: self._modularity_params = dict(modularity_params) - # pylint: disable-msg=C0103 @classmethod def FromAttribute(cls, graph, attribute, intervals=None, params=None): """Creates a vertex clustering based on the value of a vertex attribute. @@ -738,7 +737,6 @@ def _item_box_size(self, context, horiz, idx): return x_advance - x_bearing, height return height, x_advance - x_bearing - # pylint: disable-msg=R0913 def _plot_item(self, context, horiz, idx, x, y): """Plots a dendrogram item to the given Cairo context @@ -763,8 +761,6 @@ def _plot_item(self, context, horiz, idx, x, y): context.show_text(str(self._names[idx])) context.restore() - # pylint: disable-msg=C0103,W0613 - # W0613 = unused argument 'palette' def __plot__(self, context, bbox, palette, *args, **kwds): """Draws the dendrogram on the given Cairo context diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 039012b6d..edfb00815 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -183,8 +183,6 @@ class Configuration(object): inline in IPython's console if the console supports it. Default: C{True} """ - # pylint: disable-msg=R0903 - # R0903: too few public methods class Types(object): """Static class for the implementation of custom getter/setter functions for configuration keys""" diff --git a/src/igraph/cut.py b/src/igraph/cut.py index c2b39b7da..0f49193bb 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -46,7 +46,6 @@ class Cut(VertexClustering): >>> mc.es["color"] = "red" """ - # pylint: disable-msg=R0913 def __init__(self, graph, value=None, cut=None, partition=None, partition2=None): """Initializes the cut. @@ -88,7 +87,6 @@ def __str__(self): self._value, ) - # pylint: disable-msg=C0103 @property def es(self): """Returns an edge selector restricted to the cut""" @@ -150,7 +148,6 @@ class Flow(Cut): >>> mf.es["color"] = "red" """ - # pylint: disable-msg=R0913 def __init__(self, graph, value, flow, cut, partition): """Initializes the flow. diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index 6dab7223a..2a4e31fde 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -25,7 +25,6 @@ def __init__(self, data=None): self._nrow, self._ncol, self._data = 0, 0, [] self.data = data - # pylint: disable-msg=C0103 @classmethod def Fill(cls, value, *args): """Creates a matrix filled with the given value @@ -47,7 +46,6 @@ def Fill(cls, value, *args): mtrx = [[value] * width for _ in range(height)] return cls(mtrx) - # pylint: disable-msg=C0103 @classmethod def Zero(cls, *args): """Creates a matrix filled with zeros. @@ -59,7 +57,6 @@ def Zero(cls, *args): result = cls.Fill(0, *args) return result - # pylint: disable-msg=C0103 @classmethod def Identity(cls, *args): """Creates an identity matrix. @@ -68,7 +65,6 @@ def Identity(cls, *args): two integers or a tuple. If a single integer is given here, the matrix is assumed to be square-shaped. """ - # pylint: disable-msg=W0212 result = cls.Fill(0, *args) for i in range(min(result.shape)): result._data[i][i] = 1 @@ -326,8 +322,6 @@ def __plot__(self, context, bbox, palette, **kwds): is square-shaped, the same names are used for both column and row names. """ - # pylint: disable-msg=W0142 - # pylint: disable-msg=C0103 grid_width = float(kwds.get("grid_width", 1.0)) border_width = float(kwds.get("border_width", 1.0)) style = kwds.get("style", "boolean") diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index c428f62e7..a59bb7f86 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -85,8 +85,6 @@ class Plot(object): added by the L{Plot.add} method and removed by the L{Plot.remove} method. """ - # pylint: disable-msg=E1101 - # E1101: Module 'cairo' has no 'foo' member - of course it has! :) def __init__(self, target=None, bbox=None, palette=None, background=None): """Creates a new plot. @@ -256,8 +254,6 @@ def mark_dirty(self): """Marks the plot as dirty (should be redrawn)""" self._is_dirty = True - # pylint: disable-msg=W0142 - # W0142: used * or ** magic def redraw(self, context=None): """Redraws the plot""" ctx = context or self._ctx diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index ab2c98dc7..ddbc9b9a4 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -8,8 +8,6 @@ ##################################################################### -# pylint: disable-msg=R0903 -# R0903: too few public methods class AbstractDrawer(object): """Abstract class that serves as a base class for anything that draws an igraph object.""" @@ -22,8 +20,6 @@ def draw(self, *args, **kwds): ##################################################################### -# pylint: disable-msg=R0903 -# R0903: too few public methods class AbstractCairoDrawer(AbstractDrawer): """Abstract class that serves as a base class for anything that draws on a Cairo context within a given bounding box. diff --git a/src/igraph/drawing/coord.py b/src/igraph/drawing/coord.py index 57d742882..fc0626bd8 100644 --- a/src/igraph/drawing/coord.py +++ b/src/igraph/drawing/coord.py @@ -8,8 +8,6 @@ ##################################################################### -# pylint: disable-msg=R0922 -# R0922: Abstract class is only referenced 1 times class CoordinateSystem(AbstractCairoDrawer): """Class implementing a coordinate system object. diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index b47587b4f..c8afe6f14 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -42,15 +42,10 @@ ##################################################################### -# pylint: disable-msg=R0903 -# R0903: too few public methods class AbstractGraphDrawer(AbstractDrawer): """Abstract class that serves as a base class for anything that draws an igraph.Graph.""" - # pylint: disable-msg=W0221 - # W0221: argument number differs from overridden method - # E1101: Module 'cairo' has no 'foo' member - of course it does :) def draw(self, graph, *args, **kwds): """Abstract method, must be implemented in derived classes.""" raise NotImplementedError("abstract class") @@ -223,10 +218,6 @@ def _determine_vertex_order(self, graph, kwds): return vertex_order - # pylint: disable-msg=W0142,W0221,E1101 - # W0142: Used * or ** magic - # W0221: argument number differs from overridden method - # E1101: Module 'cairo' has no 'foo' member - of course it does :) def draw(self, graph, palette, *args, **kwds): # Some abbreviations for sake of simplicity directed = graph.is_directed() diff --git a/src/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py index 150e1ceda..29bdd2f22 100644 --- a/src/igraph/drawing/metamagic.py +++ b/src/igraph/drawing/metamagic.py @@ -68,8 +68,6 @@ class VisualEdgeBuilder(AttributeCollectorBase): __all__ = ("AttributeSpecification", "AttributeCollectorBase") -# pylint: disable-msg=R0903 -# R0903: too few public methods class AttributeSpecification(object): """Class that describes how the value of a given attribute should be retrieved. @@ -342,8 +340,6 @@ def _collect_attributes(self, attr_spec, config=None): def __getitem__(self, index): """Returns the collected attributes of the vertex/edge with the given index.""" - # pylint: disable-msg=E1101 - # E1101: instance has no '_attributes' member return self._cache[index] def __len__(self): diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index bb7eec3e5..b81daf815 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -50,7 +50,6 @@ def draw_path(ctx, center_x, center_y, width, height=None): """ raise NotImplementedError("abstract class") - # pylint: disable-msg=W0613 @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the shape centered at (center_x, center_y) @@ -95,8 +94,6 @@ def draw_path(ctx, center_x, center_y, width, height=None): height = height or width ctx.rectangle(center_x - width / 2, center_y - height / 2, width, height) - # pylint: disable-msg=C0103, R0911 - # R0911: too many return statements @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): """Determines where the rectangle centered at (center_x, center_y) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 051d34ede..31174fd73 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -400,8 +400,6 @@ def __or__(self, other): ##################################################################### -# pylint: disable-msg=R0903 -# R0903: too few public methods class FakeModule: """Fake module that raises an exception for everything""" @@ -482,8 +480,6 @@ def __new__(cls, x, y): """Creates a new point with the given coordinates""" return tuple.__new__(cls, (x, y)) - # pylint: disable-msg=W0622 - # W0622: redefining built-in 'len' @classmethod def _make(cls, iterable, new=tuple.__new__, len=len): """Creates a new point from a sequence or iterable""" @@ -500,8 +496,6 @@ def _asdict(self): """Returns a new dict which maps field names to their values""" return dict(zip(self._fields, self)) - # pylint: disable-msg=W0141 - # W0141: used builtin function 'map' def _replace(self, **kwds): """Returns a new point object replacing specified fields with new values""" diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index c1e1be2cf..7657ab6a4 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -179,7 +179,6 @@ def mean(self): """Returns the mean of the elements in the histogram""" return self._running_mean.mean - # pylint: disable-msg=C0103 @property def sd(self): """Returns the standard deviation of the elements in @@ -336,7 +335,6 @@ class RunningMean(object): the fly) """ - # pylint: disable-msg=C0103 def __init__(self, items=None, n=0.0, mean=0.0, sd=0.0): """RunningMean(items=None, n=0.0, mean=0.0, sd=0.0) From 4af8463fea4f7996b4ee717af40322ac8a152102 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 19:28:28 +0200 Subject: [PATCH 0520/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 05e9977f1..2ceb15db7 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 05e9977f117821af26fe4b0dda0653d9d948c488 +Subproject commit 2ceb15db7983a15e499844daddd1e1aa72cb0138 From 917b8acd1fa0ad6c768e97118d88fd3690c46271 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 19:29:40 +0200 Subject: [PATCH 0521/1892] chore: updated changelog, preparing for release [ci skip] --- CHANGELOG.md | 4 ++-- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f56df502..e9aa1aec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## 0.9.3 +## 0.9.4 ### Added @@ -18,7 +18,7 @@ ### Changed -* Updated igraph dependency to 0.9.3. +* Updated igraph dependency to 0.9.4. ### Fixed diff --git a/doc/source/conf.py b/doc/source/conf.py index 4eeb3ae08..7bb53614e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.1' +version = '0.9.4' # The full version, including alpha/beta/rc tags. -release = '0.9.1' +release = '0.9.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 14ef391dc..c7f87fb0d 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 1) +__version_info__ = (0, 9, 4) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 2d841de1da3a1749d6cdaeb6cfa2078e00202215 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 May 2021 19:43:14 +0200 Subject: [PATCH 0522/1892] chore: trigger CI to build artifacts From 2ccf9e9b88c37fc277dbd8eb8e0bce0a73e33cae Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 1 Jun 2021 14:40:23 +0200 Subject: [PATCH 0523/1892] build: force C++ linker during build by adding a dummy C++ file --- setup.py | 11 ++++++----- src/_igraph/force_cpp_linker.cpp | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 src/_igraph/force_cpp_linker.cpp diff --git a/setup.py b/setup.py index 5f2e4a5b0..9163cabd2 100644 --- a/setup.py +++ b/setup.py @@ -420,6 +420,11 @@ def run(self): extra_libraries = os.environ["IGRAPH_EXTRA_DYNAMIC_LIBRARIES"].split(',') buildcfg.libraries.extend(extra_libraries) + # Remove C++ standard library as we will use the C++ linker + for lib in ("c++", "stdc++"): + if lib in buildcfg.libraries: + buildcfg.libraries.remove(lib) + # Prints basic build information buildcfg.print_build_info() @@ -664,11 +669,6 @@ def process_args_from_command_line(self): def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" - building_on_windows = building_on_windows_msvc() - - if not building_on_windows and "stdc++" not in self.libraries: - self.libraries.append("stdc++") - if exclusions is None: exclusions = [] @@ -757,6 +757,7 @@ def use_educated_guess(self): # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) +sources.append(os.path.join("src", "_igraph", "force_cpp_linker.cpp")) igraph_extension = Extension("igraph._igraph", sources) description = """Python interface to the igraph high performance graph diff --git a/src/_igraph/force_cpp_linker.cpp b/src/_igraph/force_cpp_linker.cpp new file mode 100644 index 000000000..d78b8f3e8 --- /dev/null +++ b/src/_igraph/force_cpp_linker.cpp @@ -0,0 +1,4 @@ +/* The purpose of this file is to make Python use the C++ linker instead of + * the standard C linker because igraph's core static library needs the C++ + * standard library */ + From c1c3d8a819253988c5102fc71511f56e654d044d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 2 Jun 2021 10:26:36 +0200 Subject: [PATCH 0524/1892] ci: run verbose unit tests, add NetworkX in CI env --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c05589e4..73259dc38 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: - CIBW_TEST_COMMAND: "cd {project} && python -m unittest" + CIBW_TEST_COMMAND: "cd {project} && python -m unittest -vvv" CIBW_SKIP: "cp27-* pp27-* cp35-*" jobs: @@ -128,7 +128,7 @@ jobs: IGRAPH_STATIC_EXTENSION: True IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 - CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest" + CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest -vvv" - uses: actions/upload-artifact@v2 with: @@ -170,8 +170,8 @@ jobs: - name: Test run: | - pip install numpy scipy pandas - python -m unittest + pip install numpy scipy pandas networkx + python -m unittest -vvv - uses: actions/upload-artifact@v2 with: From 883a05ebaed0d2c6b8492bd5d7acb4879ba48a59 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 3 Jun 2021 05:39:01 +1000 Subject: [PATCH 0525/1892] Matplotlib plotting and clustering color bugfix (#410) --- src/igraph/drawing/graph.py | 105 +++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index c8afe6f14..8c766ff08 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1024,32 +1024,54 @@ def callback_edge_offset(event): clustering = graph graph = clustering.graph + # Get layout + layout = kwds.get("layout", graph.layout()) + if isinstance(layout, str): + layout = graph.layout(layout) + + # Vertex coordinates + vcoord = layout.coords + # mark groups: the used data structure is eventually the dict option: # tuples of vertex indices as the keys, colors as the values. We # convert other formats into that one here - if "mark_groups" in kwds: - if kwds["mark_groups"] is False: - del kwds["mark_groups"] - elif (kwds["mark_groups"] is True) and (clustering is not None): - pass - elif isinstance(kwds["mark_groups"], (VertexClustering, VertexCover)): - if clustering is not None: - raise ValueError( - "mark_groups cannot override a clustering with another" - ) - else: - clustering = kwds["mark_groups"] - kwds["mark_groups"] = True + if "mark_groups" not in kwds: + kwds["mark_groups"] = False + if kwds["mark_groups"] is False: + pass + elif (kwds["mark_groups"] is True) and (clustering is not None): + pass + elif isinstance(kwds["mark_groups"], (VertexClustering, VertexCover)): + if clustering is not None: + raise ValueError( + "mark_groups cannot override a clustering with another" + ) else: - try: - mg_iter = iter(kwds["mark_groups"]) - except TypeError: - raise TypeError("mark_groups is not in the right format") - kwds["mark_groups"] = dict(mg_iter) + clustering = kwds["mark_groups"] + kwds["mark_groups"] = True + else: + try: + mg_iter = iter(kwds["mark_groups"]) + except TypeError: + raise TypeError("mark_groups is not in the right format") + kwds["mark_groups"] = dict(mg_iter) + + # If a clustering is set and marks are requested but without a specific + # colormap, make the colormap - # If a clustering is set, color vertices and mark groups if requested + # Two things need coloring: vertices and groups/clusters (polygon) + # The coloring needs to be coordinated between the two. if clustering is not None: - if "vertex_color" not in kwds: + # If mark_groups is a dict, we don't need a default color dict, we + # can just use the mark_groups dict. If mark_groups is False and + # vertex_color is set, we don't need either because the colors are + # already fully specified. In all other cases, we need a default + # color dict. + if isinstance(kwds["mark_groups"], dict): + group_colordict = kwds["mark_groups"] + elif (kwds["mark_groups"] is False) and ("vertex_color" in kwds): + pass + else: membership = clustering.membership if isinstance(clustering, VertexCover): membership = [x[0] for x in membership] @@ -1057,26 +1079,35 @@ def callback_edge_offset(event): n_colors = len(clusters) cmap = mpl.cm.get_cmap("viridis") colors = [cmap(1.0 * i / n_colors) for i in range(n_colors)] - c = [colors[clusters.index(i)] for i in membership] - kwds["vertex_color"] = c + cluster_colordict = {g: c for g, c in zip(clusters, colors)} # mark_groups if not explicitly marked - if kwds.get("mark_groups") is True: - mark_groups = defaultdict(list) - for i, color in enumerate(c): - mark_groups[color].append(i) - - # Invert keys and values - mark_groups = {tuple(v): k for k, v in mark_groups.items()} - kwds["mark_groups"] = mark_groups + group_colordict = defaultdict(list) + for i, g in enumerate(membership): + color = cluster_colordict[g] + group_colordict[color].append(i) + del cluster_colordict + # Invert keys and values + group_colordict = {tuple(v): k for k, v in group_colordict.items()} + + # If mark_groups is set but not defined, make a default colormap + if kwds["mark_groups"] is True: + kwds["mark_groups"] = group_colordict - # Get layout - layout = kwds.get("layout", graph.layout()) - if isinstance(layout, str): - layout = graph.layout(layout) - - # Vertex coordinates - vcoord = layout.coords + if "vertex_color" not in kwds: + kwds["vertex_color"] = ['none' for m in membership] + for group_vs, color in group_colordict.items(): + for i in group_vs: + kwds["vertex_color"][i] = color + + # Now mark_groups is either a dict or False + # If vertex_color is not set, we can rely on mark_groups if a dict, + # else we need to make up the same colormap as if we were requested groups + if "vertex_color" not in kwds: + if isinstance(kwds["mark_groups"], dict): + membership = clustering.membership + if isinstance(clustering, VertexCover): + membership = [x[0] for x in membership] # Mark groups if "mark_groups" in kwds: From 0abc0dd50a3d858d0f54ce7883e4c7f661667e45 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 8 Jun 2021 17:56:57 +0200 Subject: [PATCH 0526/1892] fix: set_random_number_generator(None) now properly restores the original igraph RNG, fixes #414 --- src/_igraph/random.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/_igraph/random.c b/src/_igraph/random.c index e267d13d0..ad3f96d22 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -38,6 +38,7 @@ typedef struct { static igraph_i_rng_Python_state_t igraph_rng_Python_state = {0, 0, 0}; static igraph_rng_t igraph_rng_Python = {0, 0, 0}; +static igraph_rng_t igraph_rng_default_saved = {0, 0, 0}; int igraph_rng_Python_init(void **state) { IGRAPH_ERROR("Python RNG error, unsupported function called", @@ -61,7 +62,7 @@ PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object) { if (object == Py_None) { /* Reverting to the default igraph random number generator instead * of the Python-based one */ - igraph_rng_set_default(igraph_rng_default()); + igraph_rng_set_default(&igraph_rng_default_saved); Py_RETURN_NONE; } @@ -182,6 +183,10 @@ igraph_rng_type_t igraph_rngtype_Python = { void igraphmodule_init_rng(PyObject* igraph_module) { PyObject* random_module; + if (igraph_rng_default_saved.type == 0) { + igraph_rng_default_saved = *igraph_rng_default(); + } + if (igraph_rng_Python.state != 0) return; @@ -200,5 +205,6 @@ void igraphmodule_init_rng(PyObject* igraph_module) { PyErr_Clear(); return; } + Py_DECREF(random_module); } From fb47e3ec48b15ee751a9a436a2fd300d27c6c271 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 8 Jun 2021 20:55:59 +0200 Subject: [PATCH 0527/1892] fix: PyObject_CallObject() is slightly faster when generating random numbers --- src/_igraph/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/random.c b/src/_igraph/random.c index ad3f96d22..235e427e0 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -125,7 +125,7 @@ unsigned long int igraph_rng_Python_get(void *state) { * \brief Generates a real number between 0 and 1 using the Python random number generator. */ igraph_real_t igraph_rng_Python_get_real(void *state) { - PyObject* result = PyObject_CallFunction(igraph_rng_Python_state.random_func, NULL); + PyObject* result = PyObject_CallObject(igraph_rng_Python_state.random_func, 0); double retval; if (result == 0) { From 1b2b0a30dff1fc9f8c00e4cc1dda81543eae7733 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 8 Jun 2021 22:09:38 +0200 Subject: [PATCH 0528/1892] fix: RNG performance improvements --- CHANGELOG.md | 17 +++++ src/_igraph/random.c | 165 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 153 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9aa1aec4..15cb0fe47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # igraph Python interface changelog +## 0.9.5 + +### Fixed + +* `set_random_number_generator(None)` now correctly switches back to igraph's + own random number generator instead of the default one that hooks into + the `random` module of Python. + +* Improved performance in cases when igraph has to call back to Python's + `random` module to generate random numbers. One example is + `Graph.Degree_Sequence(method="vl")`, whose performance suffered a more than + 30x slowdown on 32-bit platforms before, compared to the native C + implementation. Now the gap is smaller. Note that if you need performance and + do not care about seeding the random number generator from Python, you can + now use `set_random_number_generator(None)` to switch back to igraph's own + RNG that does not need a roundtrip to Python. + ## 0.9.4 ### Added diff --git a/src/_igraph/random.c b/src/_igraph/random.c index 235e427e0..0731ec7fa 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -28,14 +28,29 @@ /** * \ingroup python_interface_rng * \brief Internal data structure for storing references to the - * functions used from Python's random number generator. + * functions and arguments used from Python's random number generator. */ typedef struct { + PyObject* getrandbits_func; PyObject* randint_func; PyObject* random_func; PyObject* gauss_func; + + PyObject* rng_bits_as_pyobject; + PyObject* zero_as_pyobject; + PyObject* one_as_pyobject; + PyObject* rng_max_as_pyobject; } igraph_i_rng_Python_state_t; +/* igraph_rng_get_int31() is potentially faster if the max value of the RNG + * is 0x7FFFFFFF; however, in case of Python, it is actually _slower_ because + * Python long integers are not terribly efficient. We are better off with using + * any other value here */ +#define RNG_MAX 0xFFFFFFFF + +/* This must be consistent with the value of RNG_MAX above */ +#define RNG_BITS 32 + static igraph_i_rng_Python_state_t igraph_rng_Python_state = {0, 0, 0}; static igraph_rng_t igraph_rng_Python = {0, 0, 0}; static igraph_rng_t igraph_rng_default_saved = {0, 0, 0}; @@ -66,25 +81,67 @@ PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object) { Py_RETURN_NONE; } -#define GET_FUNC(name) {\ +#define GET_FUNC(name) { \ func = PyObject_GetAttrString(object, name); \ - if (func == 0) \ - return NULL; \ - if (!PyCallable_Check(func)) {\ - PyErr_SetString(PyExc_TypeError, name "attribute must be callable"); \ - return NULL; \ + if (func == 0) {\ + return 0; \ + } else if (!PyCallable_Check(func)) { \ + PyErr_SetString(PyExc_TypeError, "'" name "' attribute must be callable"); \ + return 0; \ } \ } +#define GET_OPTIONAL_FUNC(name) { \ + if (PyObject_HasAttrString(object, name)) { \ + func = PyObject_GetAttrString(object, name); \ + if (func == 0) { \ + return 0; \ + } else if (!PyCallable_Check(func)) { \ + PyErr_SetString(PyExc_TypeError, "'" name "' attribute must be callable"); \ + return 0; \ + } \ + } else { \ + func = 0; \ + } \ +} + + GET_OPTIONAL_FUNC("getrandbits"); new_state.getrandbits_func = func; GET_FUNC("randint"); new_state.randint_func = func; GET_FUNC("random"); new_state.random_func = func; GET_FUNC("gauss"); new_state.gauss_func = func; + /* construct the arguments of getrandbits(RNG_BITS) and randint(0, RNG_MAX) + * in advance */ + new_state.rng_bits_as_pyobject = PyLong_FromLong(RNG_BITS); + if (new_state.rng_bits_as_pyobject == 0) { + return 0; + } + new_state.zero_as_pyobject = PyLong_FromLong(0); + if (new_state.zero_as_pyobject == 0) { + return 0; + } + new_state.one_as_pyobject = PyLong_FromLong(1); + if (new_state.one_as_pyobject == 0) { + return 0; + } + new_state.rng_max_as_pyobject = PyLong_FromUnsignedLong(RNG_MAX); + if (new_state.rng_max_as_pyobject == 0) { + return 0; + } + +#undef GET_FUNC +#undef GET_OPTIONAL_FUNC + old_state = igraph_rng_Python_state; igraph_rng_Python_state = new_state; + Py_XDECREF(old_state.getrandbits_func); Py_XDECREF(old_state.randint_func); Py_XDECREF(old_state.random_func); Py_XDECREF(old_state.gauss_func); + Py_XDECREF(old_state.rng_bits_as_pyobject); + Py_XDECREF(old_state.zero_as_pyobject); + Py_XDECREF(old_state.one_as_pyobject); + Py_XDECREF(old_state.rng_max_as_pyobject); igraph_rng_set_default(&igraph_rng_Python); @@ -106,18 +163,47 @@ int igraph_rng_Python_seed(void *state, unsigned long int seed) { * \brief Generates an unsigned long integer using the Python random number generator. */ unsigned long int igraph_rng_Python_get(void *state) { - PyObject* result = PyObject_CallFunction(igraph_rng_Python_state.randint_func, "kk", 0, LONG_MAX); + PyObject* result; + PyObject* exc_type; unsigned long int retval; + if (igraph_rng_Python_state.getrandbits_func) { + /* This is the preferred code path if the random module given by the user + * supports getrandbits(); it is faster than randint() but still slower + * than simply calling random() */ + result = PyObject_CallFunctionObjArgs( + igraph_rng_Python_state.getrandbits_func, + igraph_rng_Python_state.rng_bits_as_pyobject, + 0 + ); + } else { + /* We want to avoid hitting this path at all costs because randint() is + * very costly in the Python layer */ + result = PyObject_CallFunctionObjArgs( + igraph_rng_Python_state.randint_func, + igraph_rng_Python_state.zero_as_pyobject, + igraph_rng_Python_state.rng_max_as_pyobject, + 0 + ); + } + if (result == 0) { - PyErr_WriteUnraisable(PyErr_Occurred()); - PyErr_Clear(); + exc_type = PyErr_Occurred(); + if (exc_type == PyExc_KeyboardInterrupt) { + /* KeyboardInterrupt is okay, we don't report it, just store it and let + * the caller handler it at the earliest convenience */ + } else { + /* All other exceptions are reported and cleared */ + PyErr_WriteUnraisable(exc_type); + PyErr_Clear(); + } /* Fallback to the C random generator */ - return rand() * LONG_MAX; + return rand() * RNG_MAX; + } else { + retval = PyLong_AsUnsignedLong(result); + Py_DECREF(result); + return retval; } - retval = PyLong_AsLong(result); - Py_DECREF(result); - return retval; } /** @@ -125,19 +211,27 @@ unsigned long int igraph_rng_Python_get(void *state) { * \brief Generates a real number between 0 and 1 using the Python random number generator. */ igraph_real_t igraph_rng_Python_get_real(void *state) { - PyObject* result = PyObject_CallObject(igraph_rng_Python_state.random_func, 0); + PyObject* exc_type; double retval; + PyObject* result = PyObject_CallObject(igraph_rng_Python_state.random_func, 0); if (result == 0) { - PyErr_WriteUnraisable(PyErr_Occurred()); - PyErr_Clear(); + exc_type = PyErr_Occurred(); + if (exc_type == PyExc_KeyboardInterrupt) { + /* KeyboardInterrupt is okay, we don't report it, just store it and let + * the caller handler it at the earliest convenience */ + } else { + /* All other exceptions are reported and cleared */ + PyErr_WriteUnraisable(exc_type); + PyErr_Clear(); + } /* Fallback to the C random generator */ return rand(); + } else { + retval = PyFloat_AsDouble(result); + Py_DECREF(result); + return retval; } - - retval = PyFloat_AsDouble(result); - Py_DECREF(result); - return retval; } /** @@ -146,19 +240,32 @@ igraph_real_t igraph_rng_Python_get_real(void *state) { * around zero with unit variance. */ igraph_real_t igraph_rng_Python_get_norm(void *state) { - PyObject* result = PyObject_CallFunction(igraph_rng_Python_state.gauss_func, "dd", 0.0, 1.0); + PyObject* exc_type; double retval; + PyObject* result = PyObject_CallFunctionObjArgs( + igraph_rng_Python_state.gauss_func, + igraph_rng_Python_state.zero_as_pyobject, + igraph_rng_Python_state.one_as_pyobject, + 0 + ); if (result == 0) { - PyErr_WriteUnraisable(PyErr_Occurred()); - PyErr_Clear(); + exc_type = PyErr_Occurred(); + if (exc_type == PyExc_KeyboardInterrupt) { + /* KeyboardInterrupt is okay, we don't report it, just store it and let + * the caller handler it at the earliest convenience */ + } else { + /* All other exceptions are reported and cleared */ + PyErr_WriteUnraisable(exc_type); + PyErr_Clear(); + } /* Fallback to the C random generator */ return 0; + } else { + retval = PyFloat_AsDouble(result); + Py_DECREF(result); + return retval; } - - retval = PyFloat_AsDouble(result); - Py_DECREF(result); - return retval; } /** @@ -169,7 +276,7 @@ igraph_real_t igraph_rng_Python_get_norm(void *state) { igraph_rng_type_t igraph_rngtype_Python = { /* name= */ "Python random generator", /* min= */ 0, - /* max= */ LONG_MAX, + /* max= */ RNG_MAX, /* init= */ igraph_rng_Python_init, /* destroy= */ igraph_rng_Python_destroy, /* seed= */ igraph_rng_Python_seed, From 0a153b39531c4073b70187167c236a9365a24f87 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 11 Jun 2021 13:01:13 +0200 Subject: [PATCH 0529/1892] chore: bumped version to 0.9.5 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 7bb53614e..1ad803559 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.4' +version = '0.9.5' # The full version, including alpha/beta/rc tags. -release = '0.9.4' +release = '0.9.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index c7f87fb0d..06e50590c 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 4) +__version_info__ = (0, 9, 5) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 4c19544a873b68c1406e379d9eb6f3371a4edd67 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 11 Jun 2021 17:17:05 +0200 Subject: [PATCH 0530/1892] chore: last tweaks to changelog [ci skip] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15cb0fe47..e8af890ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Fixed +* `plot(g, ..., mark_groups=True)` now works with the Matplotlib plotting backend. + * `set_random_number_generator(None)` now correctly switches back to igraph's own random number generator instead of the default one that hooks into the `random` module of Python. From 713b811ad472e122ef28047c3eba6f470c8f8c82 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 12 Jun 2021 00:21:11 +0200 Subject: [PATCH 0531/1892] fix: fix failing Matplotlib backend when mark_groups=... is not provided, fixes #415 --- src/igraph/drawing/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 8c766ff08..5b1397013 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1110,7 +1110,7 @@ def callback_edge_offset(event): membership = [x[0] for x in membership] # Mark groups - if "mark_groups" in kwds: + if "mark_groups" in kwds and isinstance(kwds["mark_groups"], dict): for idx, color in kwds["mark_groups"].items(): points = [vcoord[i] for i in idx] vertices = np.asarray(convex_hull(points, coords=True)) From 03368df2937dcf4871cfd1210eadc21a21c570ae Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 12 Jun 2021 00:23:14 +0200 Subject: [PATCH 0532/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8af890ea..1172c7cf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # igraph Python interface changelog +## 0.9.6 + +### Fixed + +* Version 0.9.5 accidentally broke the Matplotlib backend when it was invoked + without the `mark_groups=...` keyword argument; this version fixes the issue. + Thanks to @dschult for reporting it! + ## 0.9.5 ### Fixed From f657a59bc7a7c9b56aefa2b2dff7953d06d27d6f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 12 Jun 2021 10:07:29 +0200 Subject: [PATCH 0533/1892] chore: bumped version to 0.9.56 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 1ad803559..eb5b48839 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.5' +version = '0.9.6' # The full version, including alpha/beta/rc tags. -release = '0.9.5' +release = '0.9.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 06e50590c..fd77afc92 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 5) +__version_info__ = (0, 9, 6) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 27b8068faddfb64d6b43b428982803f2f63f48b3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 20 Jun 2021 19:41:35 +0200 Subject: [PATCH 0534/1892] fix: removed deprecated 'grid_fr' layout alias, refs #417 --- doc/source/tutorial.rst | 3 --- src/_igraph/graphobject.h | 1 - src/igraph/__init__.py | 3 --- 3 files changed, 7 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 17a584f49..6d992f67a 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -682,9 +682,6 @@ Method name Short name Algorithm description ``layout_fruchterman_reingold_3d`` ``fr3d``, Fruchterman-Reingold force-directed algorithm ``fr_3d`` in three dimensions ------------------------------------ --------------- --------------------------------------------- -``layout_grid_fruchterman_reingold`` ``grid_fr`` Fruchterman-Reingold force-directed algorithm - with grid heuristics for large graphs ------------------------------------- --------------- --------------------------------------------- ``layout_kamada_kawai`` ``kk`` Kamada-Kawai force-directed algorithm ------------------------------------ --------------- --------------------------------------------- ``layout_kamada_kawai_3d`` ``kk3d``, Kamada-Kawai force-directed algorithm diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index d9d3c1fc8..8ee6e4fab 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -145,7 +145,6 @@ PyObject* igraphmodule_Graph_layout_kamada_kawai_3d(igraphmodule_GraphObject *se PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_layout_fruchterman_reingold(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_layout_fruchterman_reingold_3d(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_grid_fruchterman_reingold(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); PyObject* igraphmodule_Graph_layout_reingold_tilford(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index adf896538..1c1fe4b51 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -4285,11 +4285,8 @@ def intersection(self, other, byname="auto"): "drl": "layout_drl", "fr": "layout_fruchterman_reingold", "fruchterman_reingold": "layout_fruchterman_reingold", - "gfr": "layout_grid_fruchterman_reingold", "graphopt": "layout_graphopt", "grid": "layout_grid", - "grid_fr": "layout_grid_fruchterman_reingold", - "grid_fruchterman_reingold": "layout_grid_fruchterman_reingold", "kk": "layout_kamada_kawai", "kamada_kawai": "layout_kamada_kawai", "lgl": "layout_lgl", From 2981fe193388adfe0ef001e0689858d2cbd2825f Mon Sep 17 00:00:00 2001 From: Fabian Witter Date: Tue, 22 Jun 2021 20:37:45 +0200 Subject: [PATCH 0535/1892] Reimplemented Graph.DataFrame with improved perfomance (#418) * Reimplemented Graph.DataFrame with improved perfomance * Fixed wrong import * Reverted change of default value for param use_vids --- src/igraph/__init__.py | 147 ++++++++++++++++++--------------------- tests/test_generators.py | 55 ++++++++++++++- 2 files changed, 121 insertions(+), 81 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 1c1fe4b51..df4126c1d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3406,14 +3406,16 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): @param edges: pandas DataFrame containing edges and metadata. The first two columns of this DataFrame contain the source and target vertices - for each edge. These indicate the vertex *names* rather than ids - unless `use_vids` is True and these are nonnegative integers. + for each edge. These indicate the vertex *names* rather than IDs + unless `use_vids` is True and these are non-negative integers. Further + columns may contain edge attributes. @param directed: bool setting whether the graph is directed @param vertices: None (default) or pandas DataFrame containing vertex - metadata. The first column must contain the unique ids of the - vertices and will be set as attribute 'name'. Although vertex names - are usually strings, they can be any hashable object. All other - columns will be added as vertex attributes by column name. + metadata. The first column of the DataFrame must contain the unique + vertex *names*. If `use_vids` is True, the DataFrame's index must + contain the vertex IDs as a sequence of intergers from `0` to + `len(vertices) - 1`. All other columns will be added as vertex + attributes by column name. @use_vids: whether to interpret the first two columns of the `edges` argument as vertex ids (0-based integers) instead of vertex names. If this argument is set to True and the first two columns of `edges` @@ -3426,96 +3428,81 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): to unexpected behaviour: fill your NaNs with values before calling this function to mitigate. """ - import numpy as np - import pandas as pd + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + try: + import numpy as np + except: + raise ImportError("You should install numpy in order to use this function") if edges.shape[1] < 2: - raise ValueError("the data frame should contain at least two columns") + raise ValueError("The 'edges' DataFrame must contain at least two columns") + if vertices is not None and vertices.shape[1] < 1: + raise ValueError("The 'vertices' DataFrame must contain at least one column") if use_vids: - if str(edges.dtypes[0]).startswith("int") and str( - edges.dtypes[1] - ).startswith("int"): - names_edges = None - else: - raise TypeError("vertex ids must be 0-based integers") - + if not (str(edges.dtypes[0]).startswith("int") and str(edges.dtypes[1]).startswith("int")): + raise TypeError(f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}") + elif (edges.iloc[:, :2] < 0).any(axis=None): + raise ValueError("Source and target IDs must not be negative") + if vertices is not None: + vertices = vertices.sort_index() + if not vertices.index.equals(pd.RangeIndex.from_range(range(vertices.shape[0]))): + if not str(vertices.index.dtype).startswith("int"): + raise TypeError(f"Vertex IDs must be 0-based integers, found type {vertices.index.dtype}") + elif (vertices.index < 0).any(axis=None): + raise ValueError("Vertex IDs must not be negative") + else: + raise ValueError(f"Vertex IDs must be an integer sequence from 0 to {vertices.shape[0] - 1}") else: - # Handle if some elements are 'NA' - if edges.iloc[:, :2].isna().values.any(): - warn("In 'edges' NA elements were replaced with string \"NA\"") + # Handle if some source and target names in 'edges' are 'NA' + if edges.iloc[:, :2].isna().any(axis=None): + warn("In the first two columns of 'edges' NA elements were replaced with string \"NA\"") edges = edges.copy() edges.iloc[:, :2].fillna("NA", inplace=True) - names_edges = np.unique(edges.values[:, :2]) - - if (vertices is not None) and vertices.iloc[:, 0].isna().values.any(): - warn( - "In the first column of 'vertices' NA elements were replaced " - + 'with string "NA"' - ) - vertices = vertices.copy() - vertices.iloc[:, 0].fillna("NA", inplace=True) + # Bring DataFrame(s) into same format as with 'use_vids=True' + if vertices is None: + vertices = pd.DataFrame({"name": np.unique(edges.values[:, :2])}) - if vertices is None: - names = names_edges - else: - if vertices.shape[1] < 1: - raise ValueError("vertices has no columns") + if vertices.iloc[:, 0].isna().any(): + warn("In the first column of 'vertices' NA elements were replaced with string \"NA\"") + vertices = vertices.copy() + vertices.iloc[:, 0].fillna("NA", inplace=True) - names_vertices = vertices.iloc[:, 0] - - if names_vertices.duplicated().any(): + if vertices.iloc[:, 0].duplicated().any(): raise ValueError("Vertex names must be unique") - names_vertices = names_vertices.values + if vertices.shape[1] > 1 and "name" in vertices.columns[1:]: + raise ValueError("Vertex attribute conflict: DataFrame already contains column 'name'") - if (names_edges is not None) and len( - np.setdiff1d(names_edges, names_vertices) - ): - raise ValueError( - "Some vertices in the edge DataFrame are missing from " - + "vertices DataFrame" - ) + vertices = vertices.rename({vertices.columns[0]: "name"}, axis=1).reset_index(drop=True) - names = names_vertices + # Map source and target names in 'edges' to IDs + vid_map = pd.Series(vertices.index, index=vertices.iloc[:, 0]) + edges = edges.copy() + edges.iloc[:, 0] = edges.iloc[:, 0].map(vid_map) + edges.iloc[:, 1] = edges.iloc[:, 1].map(vid_map) - # create graph - if names is not None: - nv = len(names) - else: - nv = edges.iloc[:, :2].values.max() + 1 - g = Graph(n=nv, directed=directed) - - # vertex names - if names is not None: - for v, name in zip(g.vs, names): - v["name"] = name - - # vertex attributes - if (vertices is not None) and (vertices.shape[1] > 1): - cols = vertices.columns - for v, (_, attr) in zip(g.vs, vertices.iterrows()): - for an in cols[1:]: - v[an] = attr[an] - - # create edge list - if names is not None: - names_idx = pd.Series(index=names, data=np.arange(len(names))) - e0 = names_idx[edges.values[:, 0]] - e1 = names_idx[edges.values[:, 1]] + # Create graph + if vertices is None: + nv = edges.iloc[:, :2].max().max() + 1 + g = Graph(n=nv, directed=directed) else: - e0 = edges.values[:, 0] - e1 = edges.values[:, 1] - - # add the edges - g.add_edges(list(zip(e0, e1))) - - # edge attributes - if edges.shape[1] > 2: - for e, (_, attr) in zip(g.es, edges.iloc[:, 2:].iterrows()): - for a_name, a_value in list(attr.items()): - e[a_name] = a_value + if not edges.iloc[:, :2].isin(vertices.index).all(axis=None): + raise ValueError("Some vertices in the edge DataFrame are missing from vertices DataFrame") + nv = vertices.shape[0] + g = Graph(n=nv, directed=directed) + # Add vertex attributes + for col in vertices.columns: + g.vs[col] = vertices[col].tolist() + + # add edges including optional attributes + e_list = list(edges.iloc[:, :2].itertuples(index=False, name=None)) + e_attr = edges.iloc[:, 2:].to_dict(orient='list') if edges.shape[1] > 2 else None + g.add_edges(e_list, e_attr) return g diff --git a/tests/test_generators.py b/tests/test_generators.py index 77ce8023b..576ca5b98 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -383,7 +383,7 @@ def testDataFrame(self): g = Graph.DataFrame( edges, directed=True, - vertices=vertices, + vertices=vertices ) self.assertTrue(g.vs["name"] == [1, 2, 3, 4, 5, 6]) self.assertTrue(g.vs["label"] == ["1", "2", "3", "4", "5", "6"]) @@ -397,6 +397,59 @@ def testDataFrame(self): g = Graph.DataFrame(edges, use_vids=True) self.assertTrue(g.vcount() == 7) + # Graph clone + g = Graph.Full(n=100, directed=True, loops=True) + g.vs["name"] = [f"v{i}" for i in range(g.vcount())] + g.vs["x"] = [float(i) for i in range(g.vcount())] + g.es["w"] = [1.0] * g.ecount() + df_edges = g.get_edge_dataframe() + df_vertices = g.get_vertex_dataframe() + g_clone = Graph.DataFrame(df_edges, g.is_directed(), df_vertices, True) + self.assertTrue(df_edges.equals(g_clone.get_edge_dataframe())) + self.assertTrue(df_vertices.equals(g_clone.get_vertex_dataframe())) + + # Invalid input + with self.assertRaisesRegex(ValueError, "two columns"): + edges = pd.DataFrame({"source": [1, 2, 3]}) + Graph.DataFrame(edges) + with self.assertRaisesRegex(ValueError, "one column"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + Graph.DataFrame(edges, vertices=pd.DataFrame()) + with self.assertRaisesRegex(TypeError, "integers"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}).astype(str) + Graph.DataFrame(edges, use_vids=True) + with self.assertRaisesRegex(ValueError, "negative"): + edges = -pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + Graph.DataFrame(edges, use_vids=True) + with self.assertRaisesRegex(TypeError, "integers"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3]}, index=["1", "2", "3"]) + Graph.DataFrame(edges, vertices=vertices, use_vids=True) + with self.assertRaisesRegex(ValueError, "negative"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3]}, index=[-1, 2, 3]) + Graph.DataFrame(edges, vertices=vertices, use_vids=True) + with self.assertRaisesRegex(ValueError, "sequence"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3]}, index=[1, 2, 4]) + Graph.DataFrame(edges, vertices=vertices, use_vids=True) + with self.assertRaisesRegex(TypeError, "integers"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3]}, index=pd.MultiIndex.from_tuples([(1, 1), (2, 2), (3, 3)])) + Graph.DataFrame(edges, vertices=vertices, use_vids=True) + with self.assertRaisesRegex(ValueError, "unique"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 2]}) + Graph.DataFrame(edges, vertices=vertices) + with self.assertRaisesRegex(ValueError, "already contains"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3], "name": [1, 2, 2]}) + Graph.DataFrame(edges, vertices=vertices) + with self.assertRaisesRegex(ValueError, "missing from"): + edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) + vertices = pd.DataFrame({0: [1, 2, 3]}, index=[0, 1, 2]) + Graph.DataFrame(edges, vertices=vertices, use_vids=True) + def suite(): generator_suite = unittest.makeSuite(GeneratorTests) From a08df14c00b3ffbe7bddc4d14c891994ad7f02f0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 22 Jun 2021 20:44:22 +0200 Subject: [PATCH 0536/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1172c7cf3..777587a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # igraph Python interface changelog -## 0.9.6 +## [Unreleased] + +### Changed + +* Improved performance of `Graph.DataFrame()`, thanks to + [@fwitter](https://github.com/user/fwitter). See PR + [#418](https://github.com/igraph/python-igraph/pull/418) for more details. + +## [0.9.6] ### Fixed @@ -8,7 +16,7 @@ without the `mark_groups=...` keyword argument; this version fixes the issue. Thanks to @dschult for reporting it! -## 0.9.5 +## [0.9.5] ### Fixed @@ -27,7 +35,7 @@ now use `set_random_number_generator(None)` to switch back to igraph's own RNG that does not need a roundtrip to Python. -## 0.9.4 +## [0.9.4] ### Added @@ -68,7 +76,7 @@ * `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project is not maintained since 2008. -## 0.9.1 +## [0.9.1] ### Changed @@ -101,7 +109,7 @@ official Python wheels. -## 0.9.0 +## [0.9.0] ### Added @@ -158,9 +166,17 @@ Python interface. -## 0.8.3 +## [0.8.3] This is the last released version of `python-igraph` without a changelog file. Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. + +[Unreleased]: https://github.com/igraph/igraph/compare/0.9.6..HEAD +[0.9.6]: https://github.com/igraph/igraph/compare/0.9.5...0.9.6 +[0.9.5]: https://github.com/igraph/igraph/compare/0.9.4...0.9.5 +[0.9.4]: https://github.com/igraph/igraph/compare/0.9.1...0.9.4 +[0.9.1]: https://github.com/igraph/igraph/compare/0.9.0...0.9.1 +[0.9.0]: https://github.com/igraph/igraph/compare/0.8.5...0.9.0 +[0.8.3]: https://github.com/igraph/igraph/releases/tag/0.8.3 From 8e3f00beb42d6a3bdc55a8cccf7dc7bba8e8f5c9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 22 Jun 2021 20:45:11 +0200 Subject: [PATCH 0537/1892] fix: fix links in changelog [ci skip] --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 777587a26..e6d9c4755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -173,10 +173,10 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/igraph/compare/0.9.6..HEAD -[0.9.6]: https://github.com/igraph/igraph/compare/0.9.5...0.9.6 -[0.9.5]: https://github.com/igraph/igraph/compare/0.9.4...0.9.5 -[0.9.4]: https://github.com/igraph/igraph/compare/0.9.1...0.9.4 -[0.9.1]: https://github.com/igraph/igraph/compare/0.9.0...0.9.1 -[0.9.0]: https://github.com/igraph/igraph/compare/0.8.5...0.9.0 -[0.8.3]: https://github.com/igraph/igraph/releases/tag/0.8.3 +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..HEAD +[0.9.6]: https://github.com/igraph/python-igraph/compare/0.9.5...0.9.6 +[0.9.5]: https://github.com/igraph/python-igraph/compare/0.9.4...0.9.5 +[0.9.4]: https://github.com/igraph/python-igraph/compare/0.9.1...0.9.4 +[0.9.1]: https://github.com/igraph/python-igraph/compare/0.9.0...0.9.1 +[0.9.0]: https://github.com/igraph/python-igraph/compare/0.8.5...0.9.0 +[0.8.3]: https://github.com/igraph/python-igraph/releases/tag/0.8.3 From 1e7d1dd9d674fdcc3115f245beb469bd48982496 Mon Sep 17 00:00:00 2001 From: Fabian Witter Date: Wed, 23 Jun 2021 20:16:24 +0200 Subject: [PATCH 0538/1892] Changed default value of param use_vids in Graph.DataFrame to False --- src/igraph/__init__.py | 19 ++++++++++--------- tests/test_generators.py | 31 ++++++++++++++++--------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index df4126c1d..7caf06f1f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -3401,21 +3401,22 @@ def Incidence( return result @classmethod - def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): + def DataFrame(cls, edges, directed=True, vertices=None, use_vids=True): """Generates a graph from one or two dataframes. @param edges: pandas DataFrame containing edges and metadata. The first two columns of this DataFrame contain the source and target vertices - for each edge. These indicate the vertex *names* rather than IDs - unless `use_vids` is True and these are non-negative integers. Further - columns may contain edge attributes. + for each edge. These indicate the vertex IDs as nonnegative integers + rather than vertex *names* unless `use_vids` is False. Further columns + may contain edge attributes. @param directed: bool setting whether the graph is directed @param vertices: None (default) or pandas DataFrame containing vertex - metadata. The first column of the DataFrame must contain the unique - vertex *names*. If `use_vids` is True, the DataFrame's index must - contain the vertex IDs as a sequence of intergers from `0` to - `len(vertices) - 1`. All other columns will be added as vertex - attributes by column name. + metadata. The DataFrame's index must contain the vertex IDs as a + sequence of intergers from `0` to `len(vertices) - 1`. If `use_vids` + is False, the first column must contain the unique vertex *names*. + Although vertex names are usually strings, they can be any hashable + object. All other columns will be added as vertex attributes by column + name. @use_vids: whether to interpret the first two columns of the `edges` argument as vertex ids (0-based integers) instead of vertex names. If this argument is set to True and the first two columns of `edges` diff --git a/tests/test_generators.py b/tests/test_generators.py index 576ca5b98..a492511c0 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -364,13 +364,13 @@ def testDataFrame(self): edges = pd.DataFrame( [["C", "A", 0.4], ["A", "B", 0.1]], columns=[0, 1, "weight"] ) - g = Graph.DataFrame(edges, directed=False) + g = Graph.DataFrame(edges, directed=False, use_vids=False) self.assertTrue(g.es["weight"] == [0.4, 0.1]) vertices = pd.DataFrame( [["A", "blue"], ["B", "yellow"], ["C", "blue"]], columns=[0, "color"] ) - g = Graph.DataFrame(edges, directed=True, vertices=vertices) + g = Graph.DataFrame(edges, directed=True, vertices=vertices, use_vids=False) self.assertTrue(g.vs["name"] == ["A", "B", "C"]) self.assertTrue(g.vs["color"] == ["blue", "yellow", "blue"]) self.assertTrue(g.es["weight"] == [0.4, 0.1]) @@ -383,18 +383,19 @@ def testDataFrame(self): g = Graph.DataFrame( edges, directed=True, - vertices=vertices + vertices=vertices, + use_vids=False ) self.assertTrue(g.vs["name"] == [1, 2, 3, 4, 5, 6]) self.assertTrue(g.vs["label"] == ["1", "2", "3", "4", "5", "6"]) # Vertex ids edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) - g = Graph.DataFrame(edges) + g = Graph.DataFrame(edges, use_vids=False) self.assertTrue(g.vcount() == 6) edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) - g = Graph.DataFrame(edges, use_vids=True) + g = Graph.DataFrame(edges) self.assertTrue(g.vcount() == 7) # Graph clone @@ -404,7 +405,7 @@ def testDataFrame(self): g.es["w"] = [1.0] * g.ecount() df_edges = g.get_edge_dataframe() df_vertices = g.get_vertex_dataframe() - g_clone = Graph.DataFrame(df_edges, g.is_directed(), df_vertices, True) + g_clone = Graph.DataFrame(df_edges, g.is_directed(), df_vertices) self.assertTrue(df_edges.equals(g_clone.get_edge_dataframe())) self.assertTrue(df_vertices.equals(g_clone.get_vertex_dataframe())) @@ -417,38 +418,38 @@ def testDataFrame(self): Graph.DataFrame(edges, vertices=pd.DataFrame()) with self.assertRaisesRegex(TypeError, "integers"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}).astype(str) - Graph.DataFrame(edges, use_vids=True) + Graph.DataFrame(edges) with self.assertRaisesRegex(ValueError, "negative"): edges = -pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) - Graph.DataFrame(edges, use_vids=True) + Graph.DataFrame(edges) with self.assertRaisesRegex(TypeError, "integers"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=["1", "2", "3"]) - Graph.DataFrame(edges, vertices=vertices, use_vids=True) + Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(ValueError, "negative"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=[-1, 2, 3]) - Graph.DataFrame(edges, vertices=vertices, use_vids=True) + Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(ValueError, "sequence"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=[1, 2, 4]) - Graph.DataFrame(edges, vertices=vertices, use_vids=True) + Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(TypeError, "integers"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=pd.MultiIndex.from_tuples([(1, 1), (2, 2), (3, 3)])) - Graph.DataFrame(edges, vertices=vertices, use_vids=True) + Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(ValueError, "unique"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 2]}) - Graph.DataFrame(edges, vertices=vertices) + Graph.DataFrame(edges, vertices=vertices, use_vids=False) with self.assertRaisesRegex(ValueError, "already contains"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3], "name": [1, 2, 2]}) - Graph.DataFrame(edges, vertices=vertices) + Graph.DataFrame(edges, vertices=vertices, use_vids=False) with self.assertRaisesRegex(ValueError, "missing from"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=[0, 1, 2]) - Graph.DataFrame(edges, vertices=vertices, use_vids=True) + Graph.DataFrame(edges, vertices=vertices) def suite(): From f0228316d2f3ec517bfef0e2aee43c96d3fa7cf0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 29 Jun 2021 18:14:45 +1000 Subject: [PATCH 0539/1892] Bugfix for pop --- src/igraph/operators.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index eaf5b0075..94c47fce4 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -59,7 +59,8 @@ def disjoint_union(graphs): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_union["{:}_{:}".format(a_name, igf)] = graph_union.pop(a_name) + graph_union["{:}_{:}".format(a_name, igf)] = graph_union[a_name] + del graph_union[a_name] graph_union["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes @@ -182,7 +183,10 @@ def union(graphs, byname="auto"): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_union["{:}_{:}".format(a_name, igf)] = graph_union.pop(a_name) + # Delete the previous attribute and set attribute with + # a record about the graph of origin + graph_union["{:}_{:}".format(a_name, igf)] = graph_union[a_name] + del graph_union[a_name] graph_union["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes @@ -371,7 +375,8 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): # New conflict a_conflict.add(a_name) igf = a_first_graph[a_name] - graph_intsec["{:}_{:}".format(a_name, igf)] = graph_intsec.pop(a_name) + graph_intsec["{:}_{:}".format(a_name, igf)] = graph_intsec[a_name] + del graph_intsec[a_name] graph_intsec["{:}_{:}".format(a_name, ig)] = a_value # Vertex attributes From 9416c1f9a92ba48c53f7fd3c97738edb2699f2fc Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 29 Jun 2021 18:21:04 +1000 Subject: [PATCH 0540/1892] Test function --- tests/test_operators.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/test_operators.py b/tests/test_operators.py index 04a0fe08e..fc3616624 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -128,6 +128,34 @@ def testUnion(self): ] ) + def testUnionWithConflict(self): + g1 = Graph.Tree(7, 2) + g1['name'] = 'Tree' + g2 = Graph.Lattice([7]) + g2['name'] = 'Lattice' + g = union([g1, g2]) # Issue 422 + self.assertTrue( + sorted(g.get_edgelist()) + == [ + (0, 1), + (0, 2), + (0, 6), + (1, 2), + (1, 3), + (1, 4), + (2, 3), + (2, 5), + (2, 6), + (3, 4), + (4, 5), + (5, 6), + ] + ) + self.assertTrue( + sorted(g.attributes()), + ['name_1', 'name_2'], + ) + def testUnionMethod(self): g = Graph.Tree(7, 2).union(Graph.Lattice([7])) self.assertTrue(g.vcount() == 7 and g.ecount() == 12) From 329b75795aa138134ee889aa5e7616eff4508b2e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 29 Jun 2021 19:25:35 +1000 Subject: [PATCH 0541/1892] Improve matplotlib tutorial (#424) --- doc/source/visualisation.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index 7f12491d2..a67fc90be 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -123,6 +123,27 @@ You can then further manipulate the axes and figure however you like via the `ax called them). This variant does not use `Cairo`_ directly and might be lacking some features that are available in the `Cairo`_ backend: please open an issue on Github to request specific features. +Plotting via `matplotlib`_ makes it easy to combine igraph with other plots. For instance, if you want to have a figure +with two panels showing different aspects of some data set, say a graph and a bar plot, you can easily do that: + +>>> import matplotlib.pyplot as plt +>>> fig, axs = plt.subplots(1, 2, figsize=(8, 4)) +>>> ig.plot(g, target=axs[0]) +>>> axs[1].bar(x=[0, 1, 2], height=[1, 5, 3], color='tomato') + +Another common situation is modifying the graph plot after the fact, to achieve some kind of customization. For instance, +you might want to change the size and color of the vertices: + +>>> import matplotlib.pyplot as plt +>>> fig, ax = plt.subplots() +>>> ig.plot(g, target=ax) +>>> dots = ax.get_children()[0] # This is a PathCollection +>>> dots.set_color('tomato') +>>> dots.set_sizes([250] * g.vcount()) + +That also helps as a workaround if you cannot figure out how to use the plotting options below: just use the defaults and +then customize the appearance of your graph via standard `matplotlib`_ tools. + Plotting graphs in Jupyter notebooks ++++++++++++++++++++++++++++++++++++ |igraph| supports inline plots within a `Jupyter`_ notebook via both the `Cairo`_ and `matplotlib`_ backend. If you are From 6fbe4f77bbbc19d8a9df74c1147156931b321399 Mon Sep 17 00:00:00 2001 From: szcf-weiya Date: Mon, 12 Jul 2021 17:39:56 +0800 Subject: [PATCH 0542/1892] add doc for font-family (#427) It seems no documentation on the customization of font-family, although this feature has been implemented in https://github.com/igraph/python-igraph/pull/32/commits Without such documentation, until I came across an old question posted in https://stackoverflow.com/questions/24231430/how-to-use-custom-typeface-for-vertex-labels-in-python-igraph, and then checked the related source code, I got how to specify the font family. --- doc/source/tutorial.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 6d992f67a..54cef9b68 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -824,6 +824,8 @@ Attribute name Keyword argument Purpose =============== ====================== ========================================== ``color`` ``vertex_color`` Color of the vertex --------------- ---------------------- ------------------------------------------ +``font`` ``vertex_font`` Font family of the vertex +--------------- ---------------------- ------------------------------------------ ``label`` ``vertex_label`` Label of the vertex --------------- ---------------------- ------------------------------------------ ``label_angle`` ``vertex_label_angle`` The placement of the vertex label on the @@ -871,6 +873,8 @@ Attribute name Keyword argument Purpose ``autocurve`` keyword argument to :func:`plot`. --------------- ---------------------- ------------------------------------------ +``font`` ``edge_font`` Font family of the edge +--------------- ---------------------- ------------------------------------------ ``arrow_size`` ``edge_arrow_size`` Size (length) of the arrowhead on the edge if the graph is directed, relative to 15 pixels. From 372b86c54a369343b84b2c4b0b67f762ecb2ede7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 8 Aug 2021 12:08:15 +1000 Subject: [PATCH 0543/1892] First int64 step: delete functions, adapt some signatures --- src/_igraph/convert.c | 212 +------------------------------------- src/_igraph/convert.h | 4 - src/_igraph/graphobject.c | 64 +++++++----- 3 files changed, 41 insertions(+), 239 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index f45cc4d3e..582800d38 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1165,116 +1165,6 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v return 0; } -/** - * \ingroup python_interface_conversion - * \brief Converts a Python list of ints to an igraph \c igraph_vector_long_t - * The incoming \c igraph_vector_long_t should be uninitialized. - * Raises suitable Python exceptions when needed. - * - * This function is almost identical to - * \ref igraphmodule_PyObject_to_vector_t . Make sure you fix bugs - * in both cases (if any). - * - * \param list the Python list to be converted - * \param v the \c igraph_vector_long_t containing the result - * \return 0 if everything was OK, 1 otherwise - */ -int igraphmodule_PyObject_to_vector_long_t(PyObject *list, igraph_vector_long_t *v) { - PyObject *item; - long value=0; - Py_ssize_t i, j, k; - int ok; - - if (PyBaseString_Check(list)) { - /* It is highly unlikely that a string (although it is a sequence) will - * provide us with integers or integer pairs */ - PyErr_SetString(PyExc_TypeError, "expected a sequence or an iterable containing integers"); - return 1; - } - - if (!PySequence_Check(list)) { - /* try to use an iterator */ - PyObject *it = PyObject_GetIter(list); - if (it) { - PyObject *item; - igraph_vector_long_init(v, 0); - while ((item = PyIter_Next(it)) != 0) { - ok = 1; - if (!PyNumber_Check(item)) { - PyErr_SetString(PyExc_TypeError, "iterable must return numbers"); - ok=0; - } else { - PyObject *item2 = PyNumber_Long(item); - if (item2 == 0) { - PyErr_SetString(PyExc_TypeError, "can't convert a list item to integer"); - ok = 0; - } else { - value=(long)PyLong_AsLong(item); - Py_DECREF(item2); - } - } - - if (ok == 0) { - igraph_vector_long_destroy(v); - Py_DECREF(item); - Py_DECREF(it); - return 1; - } - if (igraph_vector_long_push_back(v, value)) { - igraphmodule_handle_igraph_error(); - igraph_vector_long_destroy(v); - Py_DECREF(item); - Py_DECREF(it); - return 1; - } - Py_DECREF(item); - } - Py_DECREF(it); - return 0; - } else { - PyErr_SetString(PyExc_TypeError, "sequence or iterable expected"); - return 1; - } - return 0; - } - - j=PySequence_Size(list); - igraph_vector_long_init(v, j); - for (i=0, k=0; ig, types, matching, &result)) { - if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } + if (matching != 0) { igraph_vector_int_destroy(matching); free(matching); } if (types != 0) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; } - if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } + if (matching != 0) { igraph_vector_int_destroy(matching); free(matching); } if (types != 0) { igraph_vector_bool_destroy(types); free(types); } if (result) @@ -485,7 +485,7 @@ PyObject *igraphmodule_Graph_is_maximal_matching(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds) { static char* kwlist[] = { "matching", "types", NULL }; PyObject *matching_o, *types_o = Py_None; - igraph_vector_long_t* matching = 0; + igraph_vector_int_t* matching = 0; igraph_vector_bool_t* types = 0; igraph_bool_t result; @@ -493,23 +493,23 @@ PyObject *igraphmodule_Graph_is_maximal_matching(igraphmodule_GraphObject* self, &types_o)) return NULL; - if (igraphmodule_attrib_to_vector_long_t(matching_o, self, &matching, + if (igraphmodule_attrib_to_vector_int_t(matching_o, self, &matching, ATTRIBUTE_TYPE_VERTEX)) return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) { - if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } + if (matching != 0) { igraph_vector_int_destroy(matching); free(matching); } return NULL; } if (igraph_is_maximal_matching(&self->g, types, matching, &result)) { - if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } + if (matching != 0) { igraph_vector_int_destroy(matching); free(matching); } if (types != 0) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; } - if (matching != 0) { igraph_vector_long_destroy(matching); free(matching); } + if (matching != 0) { igraph_vector_int_destroy(matching); free(matching); } if (types != 0) { igraph_vector_bool_destroy(types); free(types); } if (result) @@ -1586,7 +1586,9 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { - if (igraph_diameter_dijkstra(&self->g, weights, &diameter, 0, 0, 0, + if (igraph_diameter_dijkstra(&self->g, weights, &diameter, + /* from, to, vertex_path, edge_path */ + 0, 0, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); @@ -1595,8 +1597,10 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, igraph_vector_destroy(weights); free(weights); return PyFloat_FromDouble((double)diameter); } else { - if (igraph_diameter(&self->g, &diameter, 0, 0, 0, PyObject_IsTrue(dir), - PyObject_IsTrue(vcount_if_unconnected))) { + if (igraph_diameter(&self->g, &diameter, + /* from, to, vertex_path, edge_path */ + 0, 0, 0, 0, + PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -1635,7 +1639,9 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, igraph_vector_init(&res, 0); if (weights) { - if (igraph_diameter_dijkstra(&self->g, weights, 0, 0, 0, &res, + if (igraph_diameter_dijkstra(&self->g, weights, 0, + /* from, to, vertex_path, edge_path */ + 0, 0, &res, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); @@ -1644,8 +1650,10 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, } igraph_vector_destroy(weights); free(weights); } else { - if (igraph_diameter(&self->g, 0, 0, 0, &res, PyObject_IsTrue(dir), - PyObject_IsTrue(vcount_if_unconnected))) { + if (igraph_diameter(&self->g, 0, + /* from, to, vertex_path, edge_path */ + 0, 0, &res, 0, + PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -1680,7 +1688,9 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, ATTRIBUTE_TYPE_EDGE)) return NULL; if (weights) { - if (igraph_diameter_dijkstra(&self->g, weights, &len, &from, &to, 0, + if (igraph_diameter_dijkstra(&self->g, weights, &len, + /* from, to, vertex_path, edge_path */ + &from, &to, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); @@ -1693,8 +1703,10 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, return Py_BuildValue("OOd", Py_None, Py_None, (double)len); } } else { - if (igraph_diameter(&self->g, &len, &from, &to, 0, PyObject_IsTrue(dir), - PyObject_IsTrue(vcount_if_unconnected))) { + if (igraph_diameter(&self->g, &len, + /* from, to, vertex_path, edge_path */ + &from, &to, 0, 0, + PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -5039,7 +5051,9 @@ PyObject *igraphmodule_Graph_get_all_shortest_paths(igraphmodule_GraphObject * return NULL; } - if (igraph_get_all_shortest_paths_dijkstra(&self->g, &res, + if (igraph_get_all_shortest_paths_dijkstra(&self->g, + /* vertices, edges */ + &res, NULL, NULL, from, to, weights, mode)) { igraphmodule_handle_igraph_error(); igraph_vector_ptr_destroy(&res); @@ -10967,7 +10981,7 @@ PyObject *igraphmodule_Graph_maximum_bipartite_matching(igraphmodule_GraphObject PyObject *types_o = Py_None, *weights_o = Py_None, *result_o; igraph_vector_bool_t* types = 0; igraph_vector_t* weights = 0; - igraph_vector_long_t result; + igraph_vector_int_t result; double eps = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Od", kwlist, &types_o, @@ -10985,7 +10999,7 @@ PyObject *igraphmodule_Graph_maximum_bipartite_matching(igraphmodule_GraphObject return NULL; } - if (igraph_vector_long_init(&result, 0)) { + if (igraph_vector_int_init(&result, 0)) { if (types != 0) { igraph_vector_bool_destroy(types); free(types); } if (weights != 0) { igraph_vector_destroy(weights); free(weights); } igraphmodule_handle_igraph_error(); @@ -10995,7 +11009,7 @@ PyObject *igraphmodule_Graph_maximum_bipartite_matching(igraphmodule_GraphObject if (igraph_maximum_bipartite_matching(&self->g, types, 0, 0, &result, weights, eps)) { if (types != 0) { igraph_vector_bool_destroy(types); free(types); } if (weights != 0) { igraph_vector_destroy(weights); free(weights); } - igraph_vector_long_destroy(&result); + igraph_vector_int_destroy(&result); igraphmodule_handle_igraph_error(); return NULL; } @@ -11003,8 +11017,8 @@ PyObject *igraphmodule_Graph_maximum_bipartite_matching(igraphmodule_GraphObject if (types != 0) { igraph_vector_bool_destroy(types); free(types); } if (weights != 0) { igraph_vector_destroy(weights); free(weights); } - result_o = igraphmodule_vector_long_t_to_PyList(&result); - igraph_vector_long_destroy(&result); + result_o = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return result_o; } From bc0cc6bebf89fe2c45f21d09c150e303007799ca Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 9 Aug 2021 13:10:11 +0200 Subject: [PATCH 0544/1892] chore: removed old references and workarounds for Python 2.x --- doc/source/install.rst | 4 +--- doc/source/tutorial.rst | 6 +++--- src/_igraph/common.h | 25 ------------------------- src/_igraph/convert.c | 5 +---- src/_igraph/edgeseqobject.c | 5 +---- src/_igraph/vertexseqobject.c | 6 +----- src/igraph/drawing/__init__.py | 7 +------ 7 files changed, 8 insertions(+), 50 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 22b16492f..45c3759fc 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -36,9 +36,7 @@ Installing |igraph| from the Python Package Index To ensure getting the latest binary release of |igraph|'s Python interface, it is recommended that you install it from the `Python Package Index `_ (PyPI), which has installers for Windows, Linux, -and macOS. Currently there are binary packages for Python 2.7, and Python 3.5 through 3.8, but -note that support for Python 2.7 will be discontinued with the version 0.9.0 release of -|igraph|'s Python interface. +and macOS. We aim to provide binary packages for the three latest minor versions of Python 3.x. To install |python-igraph| globally, use the following command (you probably need administrator/root priviledges): diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 54cef9b68..b9d7cf25e 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -24,8 +24,8 @@ Starting |igraph| ordinary Python module at the Python prompt:: $ python - Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) - [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin + Python 3.9.6 (default, Jun 29 2021, 05:25:02) + [Clang 12.0.5 (clang-1205.0.22.9)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import igraph @@ -57,7 +57,7 @@ When you start the script, you will see something like this:: $ igraph No configuration file, using defaults - igraph 0.6 running inside Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) + igraph 0.9.4 running inside Python 3.9.6 (default, Jun 29 2021, 05:25:02) Type "copyright", "credits" or "license" for more information. >>> diff --git a/src/_igraph/common.h b/src/_igraph/common.h index ca301faf0..e74a6fa67 100644 --- a/src/_igraph/common.h +++ b/src/_igraph/common.h @@ -41,35 +41,10 @@ # define RC_TRAVERSE(T, P) #endif -/* Compatibility stuff for Python 2.3 */ -#ifndef Py_RETURN_TRUE -#define Py_RETURN_TRUE { Py_INCREF(Py_True); return Py_True; } -#endif - -#ifndef Py_RETURN_FALSE -#define Py_RETURN_FALSE { Py_INCREF(Py_False); return Py_False; } -#endif - -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE { Py_INCREF(Py_None); return Py_None; } -#endif - -#ifndef Py_RETURN_NOTIMPLEMENTED -#define Py_RETURN_NOTIMPLEMENTED { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } -#endif - #ifndef Py_RETURN #define Py_RETURN(x) { if (x) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } #endif -/* Compatibility stuff for Python 2.4 */ -#if (PY_MAJOR_VERSION <= 2) & (PY_MINOR_VERSION <= 4) -#define lenfunc inquiry -#define ssizeargfunc intargfunc -#define ssizessizeargfunc intintargfunc -#define Py_ssize_t int -#endif - #define ATTRIBUTE_TYPE_VERTEX 1 #define ATTRIBUTE_TYPE_EDGE 2 diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index f45cc4d3e..717158136 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2565,10 +2565,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, Py_ssize_t no_of_vertices = igraph_vcount(graph); Py_ssize_t start, stop, step, slicelength, i; - /* Casting to void* because Python 2.x expects PySliceObject* - * but Python 3.x expects PyObject* */ - if (PySlice_GetIndicesEx((void*)o, no_of_vertices, - &start, &stop, &step, &slicelength)) + if (PySlice_GetIndicesEx(o, no_of_vertices, &start, &stop, &step, &slicelength)) return 1; if (start == 0 && slicelength == no_of_vertices) { diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index dc7457784..c2cef6a0f 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -708,10 +708,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyObject* range; igraph_bool_t ok; - /* Casting to void* because Python 2.x expects PySliceObject* - * but Python 3.x expects PyObject* */ - ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2), - &start, &stop, &step, &sl) == 0); + ok = (PySlice_GetIndicesEx(item, igraph_vector_size(&v2), &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); ok = (range != 0); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 77be5ce69..17c157945 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -740,11 +740,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject* range; igraph_bool_t ok; - /* Casting to void* because Python 2.x expects PySliceObject* - * but Python 3.x expects PyObject* */ - ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2), - &start, &stop, &step, &sl) == 0); - + ok = (PySlice_GetIndicesEx(item, igraph_vector_size(&v2), &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); ok = (range != 0); diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index a59bb7f86..84fd3e4a7 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -369,12 +369,7 @@ def _repr_svg_(self): context.show_page() surface.finish() # Return the raw SVG representation - result = io.getvalue() - if hasattr(result, "encode"): - result = result.encode("utf-8") # for Python 2.x - else: - result = result.decode("utf-8") # for Python 3.x - + result = io.getvalue().decode("utf-8") return result, {"isolated": True} # put it inside an iframe @property From aa09f40ed860eebc787750f52e8bcb137e43c093 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 9 Aug 2021 13:46:41 +0200 Subject: [PATCH 0545/1892] fix: remove all old Python 2.x-style classes and super() calls --- setup.py | 4 ++-- src/igraph/__init__.py | 8 ++++---- src/igraph/app/shell.py | 4 ++-- src/igraph/clustering.py | 6 +++--- src/igraph/configuration.py | 4 ++-- src/igraph/cut.py | 2 +- src/igraph/datatypes.py | 4 ++-- src/igraph/drawing/__init__.py | 2 +- src/igraph/drawing/baseclasses.py | 2 +- src/igraph/drawing/colors.py | 2 +- src/igraph/drawing/edge.py | 8 ++++---- src/igraph/drawing/graph.py | 6 +++--- src/igraph/drawing/metamagic.py | 6 +++--- src/igraph/drawing/shapes.py | 6 +++--- src/igraph/drawing/text.py | 4 ++-- src/igraph/drawing/utils.py | 2 +- src/igraph/layout.py | 2 +- src/igraph/matching.py | 2 +- src/igraph/remote/gephi.py | 6 +++--- src/igraph/statistics.py | 6 +++--- src/igraph/summary.py | 4 ++-- tests/test_atlas.py | 2 +- tests/test_basic.py | 4 ++-- tests/test_cliques.py | 2 +- tests/test_rng.py | 4 ++-- 25 files changed, 51 insertions(+), 51 deletions(-) diff --git a/setup.py b/setup.py index 9163cabd2..0b64a20f2 100644 --- a/setup.py +++ b/setup.py @@ -177,7 +177,7 @@ def wait_for_keypress(seconds): ########################################################################### -class IgraphCCoreBuilder(object): +class IgraphCCoreBuilder: """Superclass for classes responsible for downloading and building the C core of igraph if it is not installed yet. """ @@ -290,7 +290,7 @@ def compile_in(self, source_folder, build_folder, install_folder): ########################################################################### -class BuildConfiguration(object): +class BuildConfiguration: def __init__(self): self.include_dirs = [] self.library_dirs = [] diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index df4126c1d..530cbc3cb 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2294,7 +2294,7 @@ def Read_DIMACS(cls, f, directed=False): vertices are attached as graph attributes C{source} and C{target}, the edge capacities are stored in the C{capacity} edge attribute. """ - graph, source, target, cap = super(Graph, cls).Read_DIMACS(f, directed) + graph, source, target, cap = super().Read_DIMACS(f, directed) graph.es["capacity"] = cap graph["source"] = source graph["target"] = target @@ -3619,7 +3619,7 @@ def bipartite_projection( is not 1 or 2, or the projected one-mode graph specified by the C{which} argument if its value is 0, 1, C{False} or C{True}. """ - superclass_meth = super(Graph, self).bipartite_projection + superclass_meth = super().bipartite_projection if which is False: which = 0 @@ -3665,7 +3665,7 @@ def bipartite_projection_size(self, types="type", *args, **kwds): first projection, followed by the number of vertices and edges in the second projection. """ - return super(Graph, self).bipartite_projection_size(types, *args, **kwds) + return super().bipartite_projection_size(types, *args, **kwds) def get_incidence(self, types="type", *args, **kwds): """Returns the incidence matrix of a bipartite graph. The incidence matrix @@ -3680,7 +3680,7 @@ def get_incidence(self, types="type", *args, **kwds): original vertex IDs. The second list is the same for the column indices. """ - return super(Graph, self).get_incidence(types, *args, **kwds) + return super().get_incidence(types, *args, **kwds) ########################### # DFS (C version will come soon) diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index e553cf69d..cb450c32a 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -285,7 +285,7 @@ def clear(self): self.last_message = "" -class Shell(object): +class Shell: """Superclass of the embeddable shells supported by igraph""" def __init__(self): @@ -362,7 +362,7 @@ def __call__(self): self._root.destroy() -class ConsoleProgressBarMixin(object): +class ConsoleProgressBarMixin: """Mixin class for console shells that support a progress bar.""" def __init__(self): diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 665fc9f3a..67ef19bb7 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -15,7 +15,7 @@ from igraph.utils import str_to_orientation -class Clustering(object): +class Clustering: """Class representing a clustering of an arbitrary ordered set. This is now used as a base for L{VertexClustering}, but it might be @@ -514,7 +514,7 @@ def _formatted_cluster_iterator(self): ############################################################################### -class Dendrogram(object): +class Dendrogram: """The hierarchical clustering (dendrogram) of some dataset. A hierarchical clustering means that we know not only the way the @@ -1034,7 +1034,7 @@ class VisualVertexBuilder(AttributeCollectorBase): ############################################################################### -class Cover(object): +class Cover: """Class representing a cover of an arbitrary ordered set. Covers are similar to clusterings, but each element of the set may diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index edfb00815..43d890219 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -85,7 +85,7 @@ def get_platform_image_viewer(): return "" -class Configuration(object): +class Configuration: """Class representing igraph configuration details. General ideas @@ -183,7 +183,7 @@ class Configuration(object): inline in IPython's console if the console supports it. Default: C{True} """ - class Types(object): + class Types: """Static class for the implementation of custom getter/setter functions for configuration keys""" diff --git a/src/igraph/cut.py b/src/igraph/cut.py index 0f49193bb..c6be762d4 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -154,7 +154,7 @@ def __init__(self, graph, value, flow, cut, partition): This should not be called directly, everything is taken care of by L{Graph.maxflow}. """ - super(Flow, self).__init__(graph, value, cut, partition) + super().__init__(graph, value, cut, partition) self._flow = flow def __repr__(self): diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index 2a4e31fde..1a53bba07 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -5,7 +5,7 @@ from itertools import islice -class Matrix(object): +class Matrix: """Simple matrix data type. Of course there are much more advanced matrix data types for Python (for @@ -653,7 +653,7 @@ def __str__(self): return "\n".join(result) -class UniqueIdGenerator(object): +class UniqueIdGenerator: """A dictionary-like class that can be used to assign unique IDs to names (say, vertex names). diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 84fd3e4a7..244bb9116 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -42,7 +42,7 @@ ##################################################################### -class Plot(object): +class Plot: """Class representing an arbitrary plot Every plot has an associated surface object where the plotting is done. The diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index ddbc9b9a4..d434f7b75 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -8,7 +8,7 @@ ##################################################################### -class AbstractDrawer(object): +class AbstractDrawer: """Abstract class that serves as a base class for anything that draws an igraph object.""" diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 4532fb173..78ecc275f 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -30,7 +30,7 @@ ) -class Palette(object): +class Palette: """Base class of color palettes. Color palettes are mappings that assign integers from the range diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 95e87b1c2..605b2df5c 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -20,7 +20,7 @@ cairo = find_cairo() -class AbstractEdgeDrawer(object): +class AbstractEdgeDrawer: """Abstract edge drawer object from which all concrete edge drawer implementations are derived.""" @@ -434,7 +434,7 @@ class AlphaVaryingEdgeDrawer(AbstractEdgeDrawer): """ def __init__(self, context, alpha_at_src, alpha_at_dest): - super(AlphaVaryingEdgeDrawer, self).__init__(context) + super().__init__(context) self.alpha_at_src = (clamp(float(alpha_at_src), 0.0, 1.0),) self.alpha_at_dest = (clamp(float(alpha_at_dest), 0.0, 1.0),) @@ -469,7 +469,7 @@ class LightToDarkEdgeDrawer(AlphaVaryingEdgeDrawer): """ def __init__(self, context): - super(LightToDarkEdgeDrawer, self).__init__(context, 0.0, 1.0) + super().__init__(context, 0.0, 1.0) class DarkToLightEdgeDrawer(AlphaVaryingEdgeDrawer): @@ -481,4 +481,4 @@ class DarkToLightEdgeDrawer(AlphaVaryingEdgeDrawer): """ def __init__(self, context): - super(DarkToLightEdgeDrawer, self).__init__(context, 1.0, 0.0) + super().__init__(context, 1.0, 0.0) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 5b1397013..c47b19193 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -543,7 +543,7 @@ class UbiGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): def __init__(self, url="http://localhost:20738/RPC2"): """Constructs an UbiGraph drawer using the display at the given URL.""" - super(UbiGraphDrawer, self).__init__(url, "ubigraph") + super().__init__(url, "ubigraph") self.vertex_defaults = dict(color="#ff0000", shape="cube", size=1.0) self.edge_defaults = dict(color="#ffffff", width=1.0) @@ -664,7 +664,7 @@ class CytoscapeGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): def __init__(self, url="http://localhost:9000/Cytoscape"): """Constructs a Cytoscape graph drawer using the XML-RPC interface of Cytoscape at the given URL.""" - super(CytoscapeGraphDrawer, self).__init__(url, "Cytoscape") + super().__init__(url, "Cytoscape") self.network_id = None def draw(self, graph, name="Network from igraph", create_view=True, *args, **kwds): @@ -940,7 +940,7 @@ def __init__(self, conn=None, *args, **kwds): - C{GephiGraphStreamingDrawer(url="http://remote:1234/workspace7)} is the same as above, but with an explicit URL. """ - super(GephiGraphStreamingDrawer, self).__init__() + super().__init__() from igraph.remote.gephi import GephiGraphStreamer, GephiConnection diff --git a/src/igraph/drawing/metamagic.py b/src/igraph/drawing/metamagic.py index 29bdd2f22..a99684cdc 100644 --- a/src/igraph/drawing/metamagic.py +++ b/src/igraph/drawing/metamagic.py @@ -68,7 +68,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): __all__ = ("AttributeSpecification", "AttributeCollectorBase") -class AttributeSpecification(object): +class AttributeSpecification: """Class that describes how the value of a given attribute should be retrieved. @@ -173,13 +173,13 @@ def __new__(mcs, name, bases, attrs): "%s.Element" % name, (attr_spec.name for attr_spec in attr_specs) ) - return super(AttributeCollectorMeta, mcs).__new__(mcs, name, bases, attrs) + return super().__new__(mcs, name, bases, attrs) @classmethod def record_generator(mcs, name, slots): """Generates a simple class that has the given slots and nothing else""" - class Element(object): + class Element: """A simple class that holds the attributes collected by the attribute collector""" diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index b81daf815..a868cbf4a 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -27,7 +27,7 @@ from igraph.utils import consecutive_pairs -class ShapeDrawer(object): +class ShapeDrawer: """Static class, the ancestor of all vertex shape drawer classes. Custom shapes must implement at least the C{draw_path} method of the class. @@ -293,7 +293,7 @@ def __init__(self, context, bbox=(1, 1), points=[]): @param bbox: ignored, leave it at its default value @param points: the list of corner points """ - super(PolygonDrawer, self).__init__(context, bbox) + super().__init__(context, bbox) self.points = points def draw_path(self, points=None, corner_radius=0): @@ -372,7 +372,7 @@ def draw(self, points=None): ##################################################################### -class ShapeDrawerDirectory(object): +class ShapeDrawerDirectory: """Static class that resolves shape names to their corresponding shape drawer classes. diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index 7d00624bd..eb248e5e7 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -14,7 +14,7 @@ ##################################################################### -class TextAlignment(object): +class TextAlignment: """Text alignment constants.""" LEFT, CENTER, RIGHT = "left", "center", "right" @@ -36,7 +36,7 @@ class TextDrawer(AbstractCairoDrawer): def __init__(self, context, text="", halign="center", valign="center"): """Constructs a new instance that will draw the given `text` on the given Cairo `context`.""" - super(TextDrawer, self).__init__(context, (0, 0)) + super().__init__(context, (0, 0)) self.text = text self.halign = halign self.valign = valign diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 31174fd73..ecf546320 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -11,7 +11,7 @@ ##################################################################### -class Rectangle(object): +class Rectangle: """Class representing a rectangle.""" __slots__ = ("_left", "_top", "_right", "_bottom") diff --git a/src/igraph/layout.py b/src/igraph/layout.py index eaf3e54c6..d6a45814e 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -13,7 +13,7 @@ from igraph.statistics import RunningMean -class Layout(object): +class Layout: """Represents the layout of a graph. A layout is practically a list of coordinates in an n-dimensional diff --git a/src/igraph/matching.py b/src/igraph/matching.py index 5ec97a456..afc966407 100644 --- a/src/igraph/matching.py +++ b/src/igraph/matching.py @@ -5,7 +5,7 @@ from igraph._igraph import Vertex -class Matching(object): +class Matching: """A matching of vertices in a graph. A matching of an undirected graph is a set of edges such that each diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index c75651935..aa3075cfb 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -11,7 +11,7 @@ __docformat__ = "restructuredtext en" -class GephiConnection(object): +class GephiConnection: """Object that represents a connection to a Gephi master server.""" def __init__(self, url=None, host="127.0.0.1", port=8080, workspace=1): @@ -79,7 +79,7 @@ def __repr__(self): return "%s(url=%r)" % (self.__class__.__name__, self.url) -class GephiGraphStreamingAPIFormat(object): +class GephiGraphStreamingAPIFormat: """Object that implements the Gephi graph streaming API format and returns Python objects corresponding to the events defined in the API. """ @@ -166,7 +166,7 @@ def get_delete_edge_event(self, identifier): return {"de": {identifier: {}}} -class GephiGraphStreamer(object): +class GephiGraphStreamer: """Class that produces JSON event objects that stream an igraph graph to Gephi using the Gephi Graph Streaming API. diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 7657ab6a4..68350b86a 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -18,7 +18,7 @@ ) -class FittedPowerLaw(object): +class FittedPowerLaw: """Result of fitting a power-law to a vector of samples Example: @@ -104,7 +104,7 @@ def summary(self, significance=0.05): return "\n".join(result) -class Histogram(object): +class Histogram: """Generic histogram class for real numbers Example: @@ -324,7 +324,7 @@ def __str__(self): return self.to_string() -class RunningMean(object): +class RunningMean: """Running mean calculator. This class can be used to calculate the mean of elements from a diff --git a/src/igraph/summary.py b/src/igraph/summary.py index 022f50479..fffb20726 100644 --- a/src/igraph/summary.py +++ b/src/igraph/summary.py @@ -13,7 +13,7 @@ __all__ = ("GraphSummary", "summary") -class FakeWrapper(object): +class FakeWrapper: """Object whose interface is compatible with C{textwrap.TextWrapper} but does no wrapping.""" @@ -38,7 +38,7 @@ def _get_wrapper_for_width(width, *args, **kwds): return TextWrapper(width=width, *args, **kwds) -class GraphSummary(object): +class GraphSummary: """Summary representation of a graph. The summary representation includes a header line and the list of diff --git a/tests/test_atlas.py b/tests/test_atlas.py index b1327550c..546a28300 100644 --- a/tests/test_atlas.py +++ b/tests/test_atlas.py @@ -3,7 +3,7 @@ from igraph import * -class AtlasTestBase(object): +class AtlasTestBase: def testPageRank(self): for idx, g in enumerate(self.__class__.graphs): try: diff --git a/tests/test_basic.py b/tests/test_basic.py index 28bca91e9..e21e67905 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -717,7 +717,7 @@ def testIsGraphicalSimple(self): class InheritedGraph(Graph): def __init__(self, *args, **kwds): - super(InheritedGraph, self).__init__(*args, **kwds) + super().__init__(*args, **kwds) self.init_called = True def __new__(cls, *args, **kwds): @@ -727,7 +727,7 @@ def __new__(cls, *args, **kwds): @classmethod def Adjacency(cls, *args, **kwds): - result = super(InheritedGraph, cls).Adjacency(*args, **kwds) + result = super().Adjacency(*args, **kwds) result.adjacency_called = True return result diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 0ef0c69ab..62017c17e 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -189,7 +189,7 @@ def testTriads(self): self.assertTrue(len(tuple(tc)) == 16) -class CliqueBenchmark(object): +class CliqueBenchmark: """This is a benchmark, not a real test case. You can run it using: diff --git a/tests/test_rng.py b/tests/test_rng.py index 00f82d8c4..b9ccc2707 100644 --- a/tests/test_rng.py +++ b/tests/test_rng.py @@ -3,7 +3,7 @@ from igraph import * -class FakeRNG(object): +class FakeRNG: @staticmethod def random(): return 0.1 @@ -17,7 +17,7 @@ def gauss(mu, sigma): return 0.3 -class InvalidRNG(object): +class InvalidRNG: pass From 98af0ee7d9e1198e6e3046b693a41aa1c5712040 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 11:27:03 +1000 Subject: [PATCH 0546/1892] Converting types for test_basic.py --- src/_igraph/convert.c | 43 +++++++--- src/_igraph/convert.h | 2 +- src/_igraph/graphobject.c | 32 ++++---- src/_igraph/vertexseqobject.c | 147 +++++++++++++++++----------------- src/_igraph/vertexseqobject.h | 2 +- src/igraph/utils.py | 17 ++-- tox.ini | 2 +- 7 files changed, 137 insertions(+), 108 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 582800d38..63330e8a1 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -782,13 +782,36 @@ int igraphmodule_PyObject_to_igraph_t(PyObject *o, igraph_t **result) { return 0; } +/** + * \brief Converts a PyLong to an igraph \c igraph_integer_t + * + * Raises suitable Python exceptions when needed. + * + * This function differs from the next one because it is less generic, + * i.e. the Python object has to be a PyLong + * + * \param object the PyLong to be converted + * \param v the result is stored here + * \return 0 if everything was OK, 1 otherwise + */ +int PyLong_to_integer_t(PyObject* obj, int* v) { + if (IGRAPH_INTEGER_SIZE == 64) { + *v = (igraph_integer_t)PyLong_AsLong(obj); + } else { + int dummy; + PyLong_AsInt(obj, &dummy); + *v = (igraph_integer_t)dummy; + } + return 0; +} + /** * \brief Converts a Python object to an igraph \c igraph_integer_t * * Raises suitable Python exceptions when needed. * * \param object the Python object to be converted - * \param v the result is returned here + * \param v the result is stored here * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { @@ -796,16 +819,18 @@ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { if (object == NULL) { } else if (PyLong_Check(object)) { - retval = PyLong_AsInt(object, &num); + retval = PyLong_to_integer_t(object, &num); if (retval) return retval; *v = num; return 0; } else if (PyNumber_Check(object)) { + /* try to recast as PyLong */ PyObject *i = PyNumber_Long(object); if (i == NULL) return 1; - retval = PyLong_AsInt(i, &num); + /* as above, plus decrement the reference for the temp variable */ + retval = PyLong_to_integer_t(i, &num); Py_DECREF(i); if (retval) return retval; @@ -1404,7 +1429,7 @@ PyObject* igraphmodule_vector_t_to_PyList_pairs(const igraph_vector_t *v) { * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_edgelist( - PyObject *list, igraph_vector_t *v, igraph_t *graph, + PyObject *list, igraph_vector_int_t *v, igraph_t *graph, igraph_bool_t* list_is_owned ) { PyObject *item, *i1, *i2, *it; @@ -1449,7 +1474,7 @@ int igraphmodule_PyObject_to_edgelist( return 1; } - igraph_vector_view(v, buffer->buf, buffer->len / buffer->itemsize); + igraph_vector_int_view(v, buffer->buf, buffer->len / buffer->itemsize); if (list_is_owned) { *list_is_owned = 0; @@ -1462,7 +1487,7 @@ int igraphmodule_PyObject_to_edgelist( if (!it) return 1; - igraph_vector_init(v, 0); + igraph_vector_int_init(v, 0); if (list_is_owned) { *list_is_owned = 1; } @@ -1488,18 +1513,18 @@ int igraphmodule_PyObject_to_edgelist( Py_DECREF(item); if (ok) { - if (igraph_vector_push_back(v, idx1)) { + if (igraph_vector_int_push_back(v, idx1)) { igraphmodule_handle_igraph_error(); ok = 0; } - if (ok && igraph_vector_push_back(v, idx2)) { + if (ok && igraph_vector_int_push_back(v, idx2)) { igraphmodule_handle_igraph_error(); ok = 0; } } if (!ok) { - igraph_vector_destroy(v); + igraph_vector_int_destroy(v); Py_DECREF(it); return 1; } diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 8da50789f..8472d97d3 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -96,7 +96,7 @@ int igraphmodule_PyObject_to_vector_ptr_t(PyObject *list, igraph_vector_ptr_t *v igraph_bool_t need_non_negative); int igraphmodule_PyObject_to_edgelist( - PyObject *list, igraph_vector_t *v, igraph_t *graph, + PyObject *list, igraph_vector_int_t *v, igraph_t *graph, igraph_bool_t *list_is_owned ); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 6e38060a5..f95a69e84 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -204,7 +204,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, long int n = 0; PyObject *edges = NULL, *dir = Py_False, *ptr_o = 0; void* ptr = 0; - igraph_vector_t edges_vector; + igraph_vector_int_t edges_vector; igraph_bool_t edges_vector_owned = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOOO!", kwlist, @@ -232,7 +232,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, } } else if (edges) { /* Caller specified an edge list, so we use igraph_create */ - /* We have to convert the Python list to a igraph_vector_t */ + /* We have to convert the Python list to a igraph_vector_int_t */ if (igraphmodule_PyObject_to_edgelist(edges, &edges_vector, 0, &edges_vector_owned)) { igraphmodule_handle_igraph_error(); return -1; @@ -242,13 +242,13 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, (&self->g, &edges_vector, (igraph_integer_t) n, PyObject_IsTrue(dir))) { igraphmodule_handle_igraph_error(); if (edges_vector_owned) { - igraph_vector_destroy(&edges_vector); + igraph_vector_int_destroy(&edges_vector); } return -1; } if (edges_vector_owned) { - igraph_vector_destroy(&edges_vector); + igraph_vector_int_destroy(&edges_vector); } } else { /* No edge list was specified, and no previously initialized graph object @@ -7695,39 +7695,39 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, { static char *kwlist[] = { "types", NULL }; igraph_matrix_t matrix; - igraph_vector_t row_ids, col_ids; + igraph_vector_int_t row_ids, col_ids; igraph_vector_bool_t *types; PyObject *matrix_o, *row_ids_o, *col_ids_o, *types_o; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &types_o)) return NULL; - if (igraph_vector_init(&row_ids, 0)) + if (igraph_vector_int_init(&row_ids, 0)) return NULL; - if (igraph_vector_init(&col_ids, 0)) { - igraph_vector_destroy(&row_ids); + if (igraph_vector_int_init(&col_ids, 0)) { + igraph_vector_int_destroy(&row_ids); return NULL; } if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) { - igraph_vector_destroy(&row_ids); - igraph_vector_destroy(&col_ids); + igraph_vector_int_destroy(&row_ids); + igraph_vector_int_destroy(&col_ids); return NULL; } if (igraph_matrix_init(&matrix, 1, 1)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&row_ids); - igraph_vector_destroy(&col_ids); + igraph_vector_int_destroy(&row_ids); + igraph_vector_int_destroy(&col_ids); if (types) { igraph_vector_bool_destroy(types); free(types); } return NULL; } if (igraph_get_incidence(&self->g, types, &matrix, &row_ids, &col_ids)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&row_ids); - igraph_vector_destroy(&col_ids); + igraph_vector_int_destroy(&row_ids); + igraph_vector_int_destroy(&col_ids); if (types) { igraph_vector_bool_destroy(types); free(types); } igraph_matrix_destroy(&matrix); return NULL; @@ -7739,9 +7739,9 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, igraph_matrix_destroy(&matrix); row_ids_o = igraphmodule_vector_t_to_PyList(&row_ids, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&row_ids); + igraph_vector_int_destroy(&row_ids); col_ids_o = igraphmodule_vector_t_to_PyList(&col_ids, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&col_ids); + igraph_vector_int_destroy(&col_ids); return Py_BuildValue("NNN", matrix_o, row_ids_o, col_ids_o); } diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 77be5ce69..2dd2b8042 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -74,17 +74,17 @@ igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) { if (copy == NULL) return NULL; if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) { - igraph_vector_t v; + igraph_vector_int_t v; if (igraph_vector_copy(&v, o->vs.data.vecptr)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_vs_vector_copy(©->vs, &v)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return 0; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else { copy->vs = o->vs; } @@ -123,21 +123,21 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, } igraph_vs_1(&vs, (igraph_integer_t)idx); } else { - igraph_vector_t v; + igraph_vector_int_t v; igraph_integer_t n = igraph_vcount(&((igraphmodule_GraphObject*)g)->g); if (igraphmodule_PyObject_to_vector_t(vsobj, &v, 1)) return -1; - if (!igraph_vector_isininterval(&v, 0, n-1)) { - igraph_vector_destroy(&v); + if (!igraph_vector_int_isininterval(&v, 0, n-1)) { + igraph_vector_int_destroy(&v); PyErr_SetString(PyExc_ValueError, "vertex index out of range"); return -1; } if (igraph_vs_vector_copy(&vs, &v)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return -1; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } self->vs = vs; @@ -202,9 +202,9 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, case IGRAPH_VS_VECTOR: case IGRAPH_VS_VECTORPTR: if (i < 0) { - i = igraph_vector_size(self->vs.data.vecptr) + i; + i = igraph_vector_int_size(self->vs.data.vecptr) + i; } - if (i >= 0 && i < igraph_vector_size(self->vs.data.vecptr)) { + if (i >= 0 && i < igraph_vector_int_size(self->vs.data.vecptr)) { idx = (igraph_integer_t)VECTOR(*self->vs.data.vecptr)[i]; } break; @@ -278,7 +278,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje case IGRAPH_VS_VECTOR: case IGRAPH_VS_VECTORPTR: - n = igraph_vector_size(self->vs.data.vecptr); + n = igraph_vector_int_size(self->vs.data.vecptr); result = PyList_New(n); if (!result) return 0; @@ -343,7 +343,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values_mapping(igraphmodule_Verte int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqObject* self, PyObject* attrname, PyObject* values) { PyObject *dict, *list, *item; igraphmodule_GraphObject *gr; - igraph_vector_t vs; + igraph_vector_int_t vs; long i, j, n, no_of_nodes; gr = self->gref; @@ -421,19 +421,19 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb } else { /* We are working with a subset of the graph. Convert the sequence to a * vector and loop through it */ - if (igraph_vector_init(&vs, 0)) { + if (igraph_vector_int_init(&vs, 0)) { igraphmodule_handle_igraph_error(); return -1; } if (igraph_vs_as_vector(&gr->g, self->vs, &vs)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return -1; } - no_of_nodes = (long)igraph_vector_size(&vs); + no_of_nodes = (long)igraph_vector_int_size(&vs); if (n == 0 && no_of_nodes > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return -1; } /* Check if we already have attributes with the given name */ @@ -444,17 +444,17 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb if (j == n) j = 0; item = PySequence_GetItem(values, j); if (item == 0) { - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ if (PyList_SetItem(list, (long)VECTOR(vs)[i], item)) { Py_DECREF(item); - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return -1; } /* PyList_SetItem stole a reference to the item automatically */ } - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); } else if (values != 0) { /* We don't have attributes with the given name yet. Create an entry * in the dict, create a new list, fill with None for vertices not in the @@ -462,7 +462,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb long n2 = igraph_vcount(&gr->g); list = PyList_New(n2); if (list == 0) { - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return -1; } for (i=0; ivs); if (igraph_vs_vector_copy(&result->vs, &v)) { Py_DECREF(result); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return NULL; } } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else if (PyLong_Check(item)) { /* Integers are treated specially: from now on, all remaining items * in the argument list must be integers and they will be used together * to restrict the vertex set. Integers are interpreted as indices on the * vertex set and NOT on the original, untouched vertex sequence of the * graph */ - igraph_vector_t v, v2; - if (igraph_vector_init(&v, 0)) { + igraph_vector_int_t v, v2; + if (igraph_vector_int_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return 0; } if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); igraphmodule_handle_igraph_error(); return 0; } - m = igraph_vector_size(&v2); + m = igraph_vector_int_size(&v2); for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[idx])) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } } - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v2); igraph_vs_destroy(&result->vs); if (igraph_vs_vector_copy(&result->vs, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return NULL; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else { /* Iterators, slices and everything that was not handled directly */ PyObject *iter=0, *item2; - igraph_vector_t v, v2; + igraph_vector_int_t v, v2; /* Allocate stuff */ - if (igraph_vector_init(&v, 0)) { + if (igraph_vector_int_init(&v, 0)) { igraphmodule_handle_igraph_error(); Py_DECREF(result); return 0; } - if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); + if (igraph_vector_int_init(&v2, 0)) { + igraph_vector_int_destroy(&v); Py_DECREF(result); igraphmodule_handle_igraph_error(); return 0; } + if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); Py_DECREF(result); igraphmodule_handle_igraph_error(); return 0; } - m = igraph_vector_size(&v2); + m = igraph_vector_int_size(&v2); /* Create an appropriate iterator */ if (PySlice_Check(item)) { @@ -740,9 +741,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject* range; igraph_bool_t ok; - /* Casting to void* because Python 2.x expects PySliceObject* - * but Python 3.x expects PyObject* */ - ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2), + ok = (PySlice_GetIndicesEx(item, igraph_vector_int_size(&v2), &start, &stop, &step, &sl) == 0); if (ok) { @@ -755,8 +754,8 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, ok = (iter != 0); } if (!ok) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator"); Py_DECREF(result); return 0; @@ -768,8 +767,8 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, /* Did we manage to get an iterator? */ if (iter == 0) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); PyErr_SetString(PyExc_TypeError, "invalid vertex filter among positional arguments"); Py_DECREF(result); return 0; @@ -785,25 +784,25 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyErr_SetString(PyExc_ValueError, "vertex index out of range"); Py_DECREF(result); Py_DECREF(iter); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } } } /* Deallocate stuff */ - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v2); Py_DECREF(iter); if (PyErr_Occurred()) { - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); Py_DECREF(result); return 0; } @@ -811,10 +810,10 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, if (igraph_vs_vector_copy(&result->vs, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return NULL; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } } @@ -828,7 +827,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, * \return 0 if everything was ok, 1 otherwise */ int igraphmodule_VertexSeq_to_vector_t(igraphmodule_VertexSeqObject *self, - igraph_vector_t *v) { + igraph_vector_int_t *v) { return igraph_vs_as_vector(&self->gref->g, self->vs, v); } @@ -849,21 +848,21 @@ PyObject* igraphmodule_VertexSeq_get_graph(igraphmodule_VertexSeqObject* self, PyObject* igraphmodule_VertexSeq_get_indices(igraphmodule_VertexSeqObject* self, void* closure) { igraphmodule_GraphObject *gr = self->gref; - igraph_vector_t vs; + igraph_vector_int_t vs; PyObject *result; - if (igraph_vector_init(&vs, 0)) { + if (igraph_vector_int_init(&vs, 0)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_vs_as_vector(&gr->g, self->vs, &vs)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&vs); + igraph_vector_int_destroy(&vs); return 0; } - result = igraphmodule_vector_t_to_PyList(&vs, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&vs); + result = igraphmodule_vector_int_t_to_PyList(&vs); + igraph_vector_int_destroy(&vs); return result; } diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index 987f1f768..708889a97 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -51,7 +51,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject *args); int igraphmodule_VertexSeq_to_vector_t(igraphmodule_VertexSeqObject *self, - igraph_vector_t *v); + igraph_vector_int_t *v); PyObject* igraphmodule_VertexSeq_get_graph(igraphmodule_VertexSeqObject *self, void* closure); diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 4b86e5dd6..8cc381cb4 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -5,7 +5,7 @@ from contextlib import contextmanager from collections.abc import MutableMapping -from ctypes import c_double, sizeof +from ctypes import sizeof from itertools import chain import os @@ -59,13 +59,18 @@ def numpy_to_contiguous_memoryview(obj): directly when constructing a Graph. """ # Deferred import to prevent a hard dependency on NumPy - from numpy import float32, float64, require - - size = sizeof(c_double) + from numpy import int32, int64, require + + # TODO: we used to export to double, which is only dependent on the + # architecture. Now with integers and a compile-time flag, we have + # to figure out what is the integer bitness of the underlying C core. + # Think of how to do that, for now default to 64 bit ints! + size = 8 + #size = sizeof(c_double) if size == 8: - dtype = float64 + dtype = int64 elif size == 4: - dtype = float32 + dtype = int32 else: raise TypeError("size of C double (%d bytes) is not supported" % size) diff --git a/tox.ini b/tox.ini index bd0355f4d..03eb48125 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,7 @@ python = pypy-3.7: pypy3 [testenv] -commands = python -m unittest +commands = python -m unittest {posargs} deps = scipy; platform_python_implementation != "PyPy" numpy; platform_python_implementation != "PyPy" From 1c8c276884b643edca8bf702f4ea77692f830ca6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 15:27:38 +1000 Subject: [PATCH 0547/1892] More work on vertices, edges, and attributes --- src/_igraph/attributes.c | 56 +++++++++++++++++------------------ src/_igraph/convert.c | 56 +++++++++++++++++------------------ src/_igraph/convert.h | 6 ++-- src/_igraph/graphobject.c | 26 ++++++++-------- src/_igraph/vertexseqobject.c | 4 +-- 5 files changed, 73 insertions(+), 75 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 7c4eb8749..fa7bdd3ed 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -553,7 +553,7 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, i /* Permuting vertices */ static int igraphmodule_i_attribute_permute_vertices(const igraph_t *graph, - igraph_t *newgraph, const igraph_vector_t *idx) { + igraph_t *newgraph, const igraph_vector_int_t *idx) { long int n, i; PyObject *key, *value, *dict, *newdict, *newlist, *o; Py_ssize_t pos=0; @@ -564,7 +564,7 @@ static int igraphmodule_i_attribute_permute_vertices(const igraph_t *graph, newdict=PyDict_New(); if (!newdict) return 1; - n=igraph_vector_size(idx); + n=igraph_vector_int_size(idx); pos=0; while (PyDict_Next(dict, &pos, &key, &value)) { @@ -593,7 +593,7 @@ static int igraphmodule_i_attribute_permute_vertices(const igraph_t *graph, } /* Adding edges */ -static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vector_t *edges, igraph_vector_ptr_t *attr) { +static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, igraph_vector_ptr_t *attr) { /* Extend the end of every value in the edge hash with ne pieces of None */ PyObject *key, *value, *dict; Py_ssize_t pos=0; @@ -601,7 +601,7 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect igraph_bool_t *added_attrs=0; igraph_attribute_record_t *attr_rec; - ne=igraph_vector_size(edges)/2; + ne=igraph_vector_int_size(edges)/2; if (!graph->attr) return IGRAPH_SUCCESS; if (ne<0) return IGRAPH_SUCCESS; @@ -771,7 +771,7 @@ static void igraphmodule_i_attribute_delete_edges(igraph_t *graph, const igraph_ /* Permuting edges */ static int igraphmodule_i_attribute_permute_edges(const igraph_t *graph, - igraph_t *newgraph, const igraph_vector_t *idx) { + igraph_t *newgraph, const igraph_vector_int_t *idx) { long int n, i; PyObject *key, *value, *dict, *newdict, *newlist, *o; Py_ssize_t pos=0; @@ -782,7 +782,7 @@ static int igraphmodule_i_attribute_permute_edges(const igraph_t *graph, newdict=PyDict_New(); if (!newdict) return 1; - n=igraph_vector_size(idx); + n=igraph_vector_int_size(idx); pos=0; while (PyDict_Next(dict, &pos, &key, &value)) { @@ -822,8 +822,8 @@ static PyObject* igraphmodule_i_ac_func(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; - long int j, n = igraph_vector_size(v); + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; + long int j, n = igraph_vector_int_size(v); list = PyList_New(n); for (j = 0; j < n; j++) { @@ -889,9 +889,9 @@ static PyObject* igraphmodule_i_ac_sum(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 0.0, sum = 0.0; - long int j, n = igraph_vector_size(v); + long int j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -923,9 +923,9 @@ static PyObject* igraphmodule_i_ac_prod(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 1.0, prod = 1.0; - long int j, n = igraph_vector_size(v); + long int j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -957,8 +957,8 @@ static PyObject* igraphmodule_i_ac_first(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_size(v); + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; + long int n = igraph_vector_int_size(v); item = n > 0 ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[0]) : Py_None; Py_INCREF(item); @@ -992,8 +992,8 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_size(v); + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; + long int n = igraph_vector_int_size(v); if (n > 0) { num = PyObject_CallObject(random_func, 0); @@ -1030,8 +1030,8 @@ static PyObject* igraphmodule_i_ac_last(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_size(v); + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; + long int n = igraph_vector_int_size(v); item = (n > 0) ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[n-1]) : Py_None; Py_INCREF(item); @@ -1054,9 +1054,9 @@ static PyObject* igraphmodule_i_ac_mean(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 0.0, mean = 0.0; - long int j, n = igraph_vector_size(v); + long int j, n = igraph_vector_int_size(v); for (j = 0; j < n; ) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -1090,8 +1090,8 @@ static PyObject* igraphmodule_i_ac_median(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { - igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; - long int j, n = igraph_vector_size(v); + igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; + long int j, n = igraph_vector_int_size(v); list = PyList_New(n); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -1317,19 +1317,19 @@ static int igraphmodule_i_attribute_combine_edges(const igraph_t *graph, /* Getting attribute names and types */ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, igraph_strvector_t *gnames, - igraph_vector_t *gtypes, + igraph_vector_int_t *gtypes, igraph_strvector_t *vnames, - igraph_vector_t *vtypes, + igraph_vector_int_t *vtypes, igraph_strvector_t *enames, - igraph_vector_t *etypes) { + igraph_vector_int_t *etypes) { igraph_strvector_t *names[3] = { gnames, vnames, enames }; - igraph_vector_t *types[3] = { gtypes, vtypes, etypes }; + igraph_vector_int_t *types[3] = { gtypes, vtypes, etypes }; int retval; long int i, j, k, l, m; for (i=0; i<3; i++) { igraph_strvector_t *n = names[i]; - igraph_vector_t *t = types[i]; + igraph_vector_int_t *t = types[i]; PyObject *dict = ATTR_STRUCT_DICT(graph)[i]; PyObject *keys; PyObject *values; @@ -1344,7 +1344,7 @@ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, } if (t) { k=PyList_Size(keys); - igraph_vector_resize(t, k); + igraph_vector_int_resize(t, k); for (j=0; j 0) { + if (igraph_vector_int_size(&vector) > 0) { igraph_es_vector_copy(es, &vector); } else { igraph_es_none(es); } - igraph_vector_destroy(&vector); + igraph_vector_int_destroy(&vector); if (return_single) { *return_single = 0; diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 8472d97d3..e0edcb29c 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -144,9 +144,9 @@ PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v); PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, igraphmodule_conv_t type); PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v); -PyObject* igraphmodule_vector_t_pair_to_PyList(const igraph_vector_t *v1, - const igraph_vector_t *v2); -PyObject* igraphmodule_vector_t_to_PyList_pairs(const igraph_vector_t *v); +PyObject* igraphmodule_vector_int_t_pair_to_PyList(const igraph_vector_int_t *v1, + const igraph_vector_int_t *v2); +PyObject* igraphmodule_vector_int_t_to_PyList_pairs(const igraph_vector_int_t *v); PyObject* igraphmodule_vector_ptr_t_to_PyList(const igraph_vector_ptr_t *v, igraphmodule_conv_t type); PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f95a69e84..88ea1600a 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -638,7 +638,7 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { PyObject *list; - igraph_vector_t v; + igraph_vector_int_t v; igraph_bool_t v_owned = 0; if (!PyArg_ParseTuple(args, "O", &list)) @@ -651,13 +651,13 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, if (igraph_add_edges(&self->g, &v, 0)) { igraphmodule_handle_igraph_error(); if (v_owned) { - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } return NULL; } if (v_owned) { - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } Py_RETURN_NONE; @@ -3064,7 +3064,7 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, CREATE_GRAPH_FROM_TYPE(self, g, type); if (store_attribs) { - type_vec_o = igraphmodule_vector_t_pair_to_PyList(&in_type_vec, + type_vec_o = igraphmodule_vector_int_t_pair_to_PyList(&in_type_vec, &out_type_vec); if (type_vec_o == NULL) { igraph_matrix_destroy(&pm); @@ -5488,23 +5488,23 @@ PyObject *igraphmodule_Graph_permute_vertices(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "permutation", NULL }; igraph_t pg; - igraph_vector_t perm; + igraph_vector_int_t perm; igraphmodule_GraphObject *result; PyObject *list; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyList_Type, &list)) return NULL; - if (igraphmodule_PyObject_to_vector_t(list, &perm, 1)) + if (igraphmodule_PyObject_to_vector_int_t(list, &perm)) return NULL; if (igraph_permute_vertices(&self->g, &pg, &perm)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&perm); + igraph_vector_int_destroy(&perm); return NULL; } - igraph_vector_destroy(&perm); + igraph_vector_int_destroy(&perm); CREATE_GRAPH(result, pg); @@ -7804,18 +7804,18 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_get_edgelist(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_vector_t edgelist; + igraph_vector_int_t edgelist; PyObject *result; - igraph_vector_init(&edgelist, igraph_ecount(&self->g)); + igraph_vector_int_init(&edgelist, igraph_ecount(&self->g)); if (igraph_get_edgelist(&self->g, &edgelist, 0)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&edgelist); + igraph_vector_int_destroy(&edgelist); return NULL; } - result = igraphmodule_vector_t_to_PyList_pairs(&edgelist); - igraph_vector_destroy(&edgelist); + result = igraphmodule_vector_int_t_to_PyList_pairs(&edgelist); + igraph_vector_int_destroy(&edgelist); return (PyObject *) result; } diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 2dd2b8042..7ee4fcde4 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -125,7 +125,7 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, } else { igraph_vector_int_t v; igraph_integer_t n = igraph_vcount(&((igraphmodule_GraphObject*)g)->g); - if (igraphmodule_PyObject_to_vector_t(vsobj, &v, 1)) + if (igraphmodule_PyObject_to_vector_int_t(vsobj, &v)) return -1; if (!igraph_vector_int_isininterval(&v, 0, n-1)) { igraph_vector_int_destroy(&v); @@ -661,7 +661,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, igraphmodule_handle_igraph_error(); return 0; } - if (igraph_vector_init(&v2, 0)) { + if (igraph_vector_int_init(&v2, 0)) { igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return 0; From 8781af57a63079f68acc3a649e0b945d9036a8c2 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 15:41:32 +1000 Subject: [PATCH 0548/1892] Edge sequences --- src/_igraph/edgeseqobject.c | 150 ++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 76 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index dc7457784..cf6955fe4 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -74,17 +74,17 @@ igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { if (copy == NULL) return NULL; if (igraph_es_type(&o->es) == IGRAPH_ES_VECTOR) { - igraph_vector_t v; - if (igraph_vector_copy(&v, o->es.data.vecptr)) { + igraph_vector_int_t v; + if (igraph_vector_int_copy(&v, o->es.data.vecptr)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_vector_copy(©->es, &v)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return 0; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else { copy->es = o->es; } @@ -125,21 +125,21 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, igraph_es_1(&es, (igraph_integer_t)idx); } else { /* We selected multiple edges */ - igraph_vector_t v; + igraph_vector_int_t v; igraph_integer_t n = igraph_ecount(&((igraphmodule_GraphObject*)g)->g); - if (igraphmodule_PyObject_to_vector_t(esobj, &v, 1)) + if (igraphmodule_PyObject_to_vector_int_t(esobj, &v)) return -1; - if (!igraph_vector_isininterval(&v, 0, n-1)) { - igraph_vector_destroy(&v); + if (!igraph_vector_int_isininterval(&v, 0, n-1)) { + igraph_vector_int_destroy(&v); PyErr_SetString(PyExc_ValueError, "edge index out of range"); return -1; } if (igraph_es_vector_copy(&es, &v)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return -1; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } self->es = es; @@ -206,9 +206,9 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, case IGRAPH_ES_VECTOR: case IGRAPH_ES_VECTORPTR: if (i < 0) { - i = igraph_vector_size(self->es.data.vecptr) + i; + i = igraph_vector_int_size(self->es.data.vecptr) + i; } - if (i >= 0 && i < igraph_vector_size(self->es.data.vecptr)) { + if (i >= 0 && i < igraph_vector_int_size(self->es.data.vecptr)) { idx = (igraph_integer_t)VECTOR(*self->es.data.vecptr)[i]; } break; @@ -285,7 +285,7 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* case IGRAPH_ES_VECTOR: case IGRAPH_ES_VECTORPTR: - n = igraph_vector_size(self->es.data.vecptr); + n = igraph_vector_int_size(self->es.data.vecptr); result = PyList_New(n); if (!result) return 0; @@ -355,7 +355,7 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values_mapping(igraphmodule_EdgeSeq int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject* self, PyObject* attrname, PyObject* values) { PyObject *dict, *list, *item; igraphmodule_GraphObject *gr; - igraph_vector_t es; + igraph_vector_int_t es; long i, j, n, no_of_edges; gr = self->gref; @@ -430,19 +430,19 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject } else { /* We are working with a subset of the graph. Convert the sequence to a * vector and loop through it */ - if (igraph_vector_init(&es, 0)) { + if (igraph_vector_int_init(&es, 0)) { igraphmodule_handle_igraph_error(); return -1; } if (igraph_es_as_vector(&gr->g, self->es, &es)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&es); + igraph_vector_int_destroy(&es); return -1; } - no_of_edges = (long)igraph_vector_size(&es); + no_of_edges = (long)igraph_vector_int_size(&es); if (n == 0 && no_of_edges > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); - igraph_vector_destroy(&es); + igraph_vector_int_destroy(&es); return -1; } /* Check if we already have attributes with the given name */ @@ -452,22 +452,22 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject for (i=0, j=0; ig); list = PyList_New(n2); - if (list == 0) { igraph_vector_destroy(&es); return -1; } + if (list == 0) { igraph_vector_int_destroy(&es); return -1; } for (i=0; ies); if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return NULL; } } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else if (PyLong_Check(item)) { /* Integers are treated specially: from now on, all remaining items * in the argument list must be integers and they will be used together * to restrict the edge set. Integers are interpreted as indices on the * edge set and NOT on the original, untouched edge sequence of the * graph */ - igraph_vector_t v, v2; - if (igraph_vector_init(&v, 0)) { + igraph_vector_int_t v, v2; + if (igraph_vector_int_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } - if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); + if (igraph_vector_int_init(&v2, 0)) { + igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_as_vector(&gr->g, self->es, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); igraphmodule_handle_igraph_error(); return 0; } - m = igraph_vector_size(&v2); + m = igraph_vector_int_size(&v2); for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[idx])) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } } - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v2); igraph_es_destroy(&result->es); if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return NULL; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } else { /* Iterators and everything that was not handled directly */ PyObject *iter, *item2; - igraph_vector_t v, v2; + igraph_vector_int_t v, v2; /* Allocate stuff */ - if (igraph_vector_init(&v, 0)) { + if (igraph_vector_int_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } - if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); + if (igraph_vector_int_init(&v2, 0)) { + igraph_vector_int_destroy(&v); igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_as_vector(&gr->g, self->es, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); igraphmodule_handle_igraph_error(); return 0; } - m = igraph_vector_size(&v2); + m = igraph_vector_int_size(&v2); /* Create an appropriate iterator */ if (PySlice_Check(item)) { @@ -708,9 +708,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyObject* range; igraph_bool_t ok; - /* Casting to void* because Python 2.x expects PySliceObject* - * but Python 3.x expects PyObject* */ - ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2), + ok = (PySlice_GetIndicesEx(item, igraph_vector_int_size(&v2), &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); @@ -722,8 +720,8 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject ok = (iter != 0); } if (!ok) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator"); Py_DECREF(result); return 0; @@ -735,8 +733,8 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject /* Did we manage to get an iterator? */ if (iter == 0) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); PyErr_SetString(PyExc_TypeError, "invalid edge filter among positional arguments"); Py_DECREF(result); return 0; @@ -752,25 +750,25 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyErr_SetString(PyExc_ValueError, "edge index out of range"); Py_DECREF(result); Py_DECREF(iter); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v); + igraph_vector_int_destroy(&v2); return NULL; } } } /* Deallocate stuff */ - igraph_vector_destroy(&v2); + igraph_vector_int_destroy(&v2); Py_DECREF(iter); if (PyErr_Occurred()) { - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); Py_DECREF(result); return 0; } @@ -778,10 +776,10 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); return NULL; } - igraph_vector_destroy(&v); + igraph_vector_int_destroy(&v); } } @@ -881,21 +879,21 @@ PyObject* igraphmodule_EdgeSeq_get_graph(igraphmodule_EdgeSeqObject* self, PyObject* igraphmodule_EdgeSeq_get_indices(igraphmodule_EdgeSeqObject* self, void* closure) { igraphmodule_GraphObject *gr = self->gref; - igraph_vector_t es; + igraph_vector_int_t es; PyObject *result; - if (igraph_vector_init(&es, 0)) { + if (igraph_vector_int_init(&es, 0)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_as_vector(&gr->g, self->es, &es)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&es); + igraph_vector_int_destroy(&es); return 0; } - result = igraphmodule_vector_t_to_PyList(&es, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&es); + result = igraphmodule_vector_int_t_to_PyList(&es); + igraph_vector_int_destroy(&es); return result; } From 570a953c24925f24e9baa5c621fe62897f8e801a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 17:37:24 +1000 Subject: [PATCH 0549/1892] Passes test_basic --- src/_igraph/graphobject.c | 87 +++++++++++++++++++------------------- src/_igraph/igraphmodule.c | 48 ++++++++++----------- 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 88ea1600a..3fb559fcf 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1158,7 +1158,7 @@ PyObject *igraphmodule_Graph_has_multiple(igraphmodule_GraphObject *self) { PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { PyObject *list = Py_None; - igraph_vector_t result; + igraph_vector_int_t result; igraph_es_t es; igraph_bool_t return_single = 0; @@ -1172,7 +1172,7 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, return NULL; } - if (igraph_vector_init(&result, 0)) { + if (igraph_vector_int_init(&result, 0)) { igraph_es_destroy(&es); return NULL; } @@ -1180,12 +1180,12 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, if (igraph_count_multiple(&self->g, &result, es)) { igraphmodule_handle_igraph_error(); igraph_es_destroy(&es); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } if (!return_single) - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); + list = igraphmodule_vector_int_t_to_PyList(&result); else list = PyLong_FromLong((long int)VECTOR(result)[0]); @@ -1212,7 +1212,7 @@ PyObject *igraphmodule_Graph_neighbors(igraphmodule_GraphObject * self, PyObject *list, *dtype_o=Py_None, *dmode_o=Py_None, *index_o; igraph_neimode_t dmode = IGRAPH_ALL; igraph_integer_t idx; - igraph_vector_t result; + igraph_vector_int_t result; static char *kwlist[] = { "vertex", "mode", "type", NULL }; @@ -1231,17 +1231,17 @@ PyObject *igraphmodule_Graph_neighbors(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) return NULL; - if (igraph_vector_init(&result, 1)) + if (igraph_vector_int_init(&result, 1)) return igraphmodule_handle_igraph_error(); if (igraph_neighbors(&self->g, &result, idx, dmode)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return list; } @@ -1263,7 +1263,7 @@ PyObject *igraphmodule_Graph_incident(igraphmodule_GraphObject * self, PyObject *list, *dmode_o = Py_None, *dtype_o = Py_None, *index_o; igraph_neimode_t dmode = IGRAPH_OUT; igraph_integer_t idx; - igraph_vector_t result; + igraph_vector_int_t result; static char *kwlist[] = { "vertex", "mode", "type", NULL }; @@ -1282,15 +1282,15 @@ PyObject *igraphmodule_Graph_incident(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) return NULL; - igraph_vector_init(&result, 1); + igraph_vector_int_init(&result, 1); if (igraph_incident(&self->g, &result, idx, dmode)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return list; } @@ -1336,7 +1336,7 @@ PyObject *igraphmodule_Graph_successors(igraphmodule_GraphObject * self, { PyObject *list, *index_o; igraph_integer_t idx; - igraph_vector_t result; + igraph_vector_int_t result; static char *kwlist[] = { "vertex", NULL }; @@ -1346,15 +1346,15 @@ PyObject *igraphmodule_Graph_successors(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) return NULL; - igraph_vector_init(&result, 1); + igraph_vector_int_init(&result, 1); if (igraph_neighbors(&self->g, &result, idx, IGRAPH_OUT)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return list; } @@ -1373,7 +1373,7 @@ PyObject *igraphmodule_Graph_predecessors(igraphmodule_GraphObject * self, { PyObject *list, *index_o; igraph_integer_t idx; - igraph_vector_t result; + igraph_vector_int_t result; static char *kwlist[] = { "vertex", NULL }; @@ -1383,15 +1383,15 @@ PyObject *igraphmodule_Graph_predecessors(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) return NULL; - igraph_vector_init(&result, 1); + igraph_vector_int_init(&result, 1); if (igraph_neighbors(&self->g, &result, idx, IGRAPH_IN)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return list; } @@ -1498,7 +1498,7 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, PyObject *directed = Py_True; PyObject *error = Py_True; PyObject *result = NULL; - igraph_vector_t pairs, path, res; + igraph_vector_int_t pairs, path, res; igraph_bool_t pairs_owned = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, @@ -1506,21 +1506,21 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, &error)) return NULL; - if (igraph_vector_init(&res, 0)) + if (igraph_vector_int_init(&res, 0)) return igraphmodule_handle_igraph_error(); if (pairs_o != Py_None) { if (igraphmodule_PyObject_to_edgelist(pairs_o, &pairs, &self->g, &pairs_owned)) { - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } } if (path_o != Py_None) { - if (igraphmodule_PyObject_to_vector_t(path_o, &path, 1)) { - igraph_vector_destroy(&res); + if (igraphmodule_PyObject_to_vector_int_t(path_o, &path)) { + igraph_vector_int_destroy(&res); if (pairs_owned) { - igraph_vector_destroy(&pairs); + igraph_vector_int_destroy(&pairs); } return NULL; } @@ -1532,24 +1532,24 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, PyObject_IsTrue(directed), PyObject_IsTrue(error))) { if (pairs_owned) { - igraph_vector_destroy(&pairs); + igraph_vector_int_destroy(&pairs); } if (path_o != Py_None) { - igraph_vector_destroy(&path); + igraph_vector_int_destroy(&path); } - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return igraphmodule_handle_igraph_error(); } if (pairs_owned) { - igraph_vector_destroy(&pairs); + igraph_vector_int_destroy(&pairs); } if (path_o != Py_None) { - igraph_vector_destroy(&path); + igraph_vector_int_destroy(&path); } - result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + result = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return result; } @@ -5270,10 +5270,9 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, if (!return_single) result = igraphmodule_vector_ptr_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); else - result = igraphmodule_vector_t_to_PyList((igraph_vector_t*)VECTOR(res)[0], - IGRAPHMODULE_TYPE_INT); + result = igraphmodule_vector_int_t_to_PyList((igraph_vector_int_t*)VECTOR(res)[0]); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&res, igraph_vector_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&res, igraph_vector_int_destroy); igraph_vector_ptr_destroy_all(&res); return result; @@ -5296,7 +5295,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, igraph_neimode_t mode = IGRAPH_ALL; igraph_bool_t return_single = 0; igraph_vs_t vs; - igraph_vector_t res; + igraph_vector_int_t res; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlOi", kwlist, &vobj, &order, &mode_o, &mindist)) @@ -5309,7 +5308,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&res, 0)) { + if (igraph_vector_int_init(&res, 0)) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } @@ -5323,11 +5322,11 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, igraph_vs_destroy(&vs); if (!return_single) - result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); + result = igraphmodule_vector_int_t_to_PyList(&res); else result = PyLong_FromLong((long)VECTOR(res)[0]); - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return result; } diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index ea3661c3f..d19883e0c 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -413,7 +413,7 @@ PyObject* igraphmodule_is_degree_sequence(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "out_deg", "in_deg", NULL }; PyObject *out_deg_o = 0, *in_deg_o = 0; - igraph_vector_t out_deg, in_deg; + igraph_vector_int_t out_deg, in_deg; igraph_bool_t is_directed, result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, @@ -422,25 +422,25 @@ PyObject* igraphmodule_is_degree_sequence(PyObject *self, is_directed = (in_deg_o != 0 && in_deg_o != Py_None); - if (igraphmodule_PyObject_to_vector_t(out_deg_o, &out_deg, 0)) + if (igraphmodule_PyObject_to_vector_int_t(out_deg_o, &out_deg)) return NULL; - if (is_directed && igraphmodule_PyObject_to_vector_t(in_deg_o, &in_deg, 0)) { - igraph_vector_destroy(&out_deg); + if (is_directed && igraphmodule_PyObject_to_vector_int_t(in_deg_o, &in_deg)) { + igraph_vector_int_destroy(&out_deg); return NULL; } if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, &result)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); return NULL; } - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); if (result) Py_RETURN_TRUE; @@ -453,7 +453,7 @@ PyObject* igraphmodule_is_graphical_degree_sequence(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "out_deg", "in_deg", NULL }; PyObject *out_deg_o = 0, *in_deg_o = 0; - igraph_vector_t out_deg, in_deg; + igraph_vector_int_t out_deg, in_deg; igraph_bool_t is_directed, result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, @@ -462,25 +462,25 @@ PyObject* igraphmodule_is_graphical_degree_sequence(PyObject *self, is_directed = (in_deg_o != 0 && in_deg_o != Py_None); - if (igraphmodule_PyObject_to_vector_t(out_deg_o, &out_deg, 0)) + if (igraphmodule_PyObject_to_vector_int_t(out_deg_o, &out_deg)) return NULL; - if (is_directed && igraphmodule_PyObject_to_vector_t(in_deg_o, &in_deg, 0)) { - igraph_vector_destroy(&out_deg); + if (is_directed && igraphmodule_PyObject_to_vector_int_t(in_deg_o, &in_deg)) { + igraph_vector_int_destroy(&out_deg); return NULL; } if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, IGRAPH_SIMPLE_SW, &result)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); return NULL; } - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); if (result) Py_RETURN_TRUE; @@ -493,7 +493,7 @@ PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kw static char* kwlist[] = { "out_deg", "in_deg", "loops", "multiple", NULL }; PyObject *out_deg_o = 0, *in_deg_o = 0; PyObject *loops = Py_False, *multiple = Py_False; - igraph_vector_t out_deg, in_deg; + igraph_vector_int_t out_deg, in_deg; igraph_bool_t is_directed, result; int allowed_edge_types; @@ -503,11 +503,11 @@ PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kw is_directed = (in_deg_o != 0 && in_deg_o != Py_None); - if (igraphmodule_PyObject_to_vector_t(out_deg_o, &out_deg, 0)) + if (igraphmodule_PyObject_to_vector_int_t(out_deg_o, &out_deg)) return NULL; - if (is_directed && igraphmodule_PyObject_to_vector_t(in_deg_o, &in_deg, 0)) { - igraph_vector_destroy(&out_deg); + if (is_directed && igraphmodule_PyObject_to_vector_int_t(in_deg_o, &in_deg)) { + igraph_vector_int_destroy(&out_deg); return NULL; } @@ -521,16 +521,16 @@ PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kw if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, allowed_edge_types, &result)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) { - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); } return NULL; } - igraph_vector_destroy(&out_deg); + igraph_vector_int_destroy(&out_deg); if (is_directed) { - igraph_vector_destroy(&in_deg); + igraph_vector_int_destroy(&in_deg); } if (result) From d096d47a0b36efc443c657e9bbdf1d1df5a3ed40 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 18:18:49 +1000 Subject: [PATCH 0550/1892] A few more test files pass --- src/_igraph/convert.c | 6 +-- src/_igraph/convert.h | 2 +- src/_igraph/graphobject.c | 102 +++++++++++++++++++------------------- tests/test_attributes.py | 8 +-- tests/test_cliques.py | 5 +- 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 97f91dc77..ae458f03b 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1350,16 +1350,16 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { /** * \ingroup python_interface_conversion - * \brief Converts an igraph \c igraph_vector_t to a Python integer tuple + * \brief Converts an igraph \c igraph_vector_int_t to a Python integer tuple * * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer tuple as a \c PyObject*, or \c NULL if an error occurred */ -PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v) { +PyObject* igraphmodule_vector_int_t_to_PyTuple(const igraph_vector_int_t *v) { PyObject* tuple; Py_ssize_t n, i; - n=igraph_vector_size(v); + n=igraph_vector_int_size(v); if (n<0) return igraphmodule_handle_igraph_error(); tuple=PyTuple_New(n); diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index e0edcb29c..9f8de757d 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -143,7 +143,7 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v); PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, igraphmodule_conv_t type); -PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v); +PyObject* igraphmodule_vector_int_t_to_PyTuple(const igraph_vector_int_t *v); PyObject* igraphmodule_vector_int_t_pair_to_PyList(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2); PyObject* igraphmodule_vector_int_t_to_PyList_pairs(const igraph_vector_int_t *v); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3fb559fcf..aa2433286 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -723,7 +723,7 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, PyObject *dtype_o = Py_None; PyObject *dmode_o = Py_None; igraph_neimode_t dmode = IGRAPH_ALL; - igraph_vector_t result; + igraph_vector_int_t result; igraph_vs_t vs; igraph_bool_t return_single = 0; @@ -745,7 +745,7 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, return NULL; } - if (igraph_vector_init(&result, 0)) { + if (igraph_vector_int_init(&result, 0)) { igraph_vs_destroy(&vs); return NULL; } @@ -754,16 +754,16 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, dmode, PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); igraph_vs_destroy(&vs); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } if (!return_single) - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); + list = igraphmodule_vector_int_t_to_PyList(&result); else list = PyLong_FromLong((long int)VECTOR(result)[0]); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); igraph_vs_destroy(&vs); return list; @@ -4043,7 +4043,7 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel PyObject *types_o = Py_None, *multiplicity_o = Py_True, *mul1 = 0, *mul2 = 0; igraphmodule_GraphObject *result1 = 0, *result2 = 0; igraph_vector_bool_t* types = 0; - igraph_vector_t multiplicities[2]; + igraph_vector_int_t multiplicities[2]; igraph_t g1, g2; igraph_t *p_g1 = &g1, *p_g2 = &g2; long int probe1 = -1; @@ -4065,14 +4065,14 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel } if (PyObject_IsTrue(multiplicity_o)) { - if (igraph_vector_init(&multiplicities[0], 0)) { + if (igraph_vector_int_init(&multiplicities[0], 0)) { if (types) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_vector_init(&multiplicities[1], 0)) { - igraph_vector_destroy(&multiplicities[0]); + if (igraph_vector_int_init(&multiplicities[1], 0)) { + igraph_vector_int_destroy(&multiplicities[0]); if (types) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; @@ -4082,8 +4082,8 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel p_g1 ? &multiplicities[0] : 0, p_g2 ? &multiplicities[1] : 0, (igraph_integer_t) probe1)) { - igraph_vector_destroy(&multiplicities[0]); - igraph_vector_destroy(&multiplicities[1]); + igraph_vector_int_destroy(&multiplicities[0]); + igraph_vector_int_destroy(&multiplicities[1]); if (types) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; @@ -4108,23 +4108,23 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel if (PyObject_IsTrue(multiplicity_o)) { if (p_g1) { - mul1 = igraphmodule_vector_t_to_PyList(&multiplicities[0], IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&multiplicities[0]); + mul1 = igraphmodule_vector_int_t_to_PyList(&multiplicities[0]); + igraph_vector_int_destroy(&multiplicities[0]); if (mul1 == NULL) { - igraph_vector_destroy(&multiplicities[1]); + igraph_vector_int_destroy(&multiplicities[1]); return NULL; } } else { - igraph_vector_destroy(&multiplicities[0]); + igraph_vector_int_destroy(&multiplicities[0]); } if (p_g2) { - mul2 = igraphmodule_vector_t_to_PyList(&multiplicities[1], IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&multiplicities[1]); + mul2 = igraphmodule_vector_int_t_to_PyList(&multiplicities[1]); + igraph_vector_int_destroy(&multiplicities[1]); if (mul2 == NULL) return NULL; } else { - igraph_vector_destroy(&multiplicities[1]); + igraph_vector_int_destroy(&multiplicities[1]); } if (p_g1 && p_g2) { @@ -4506,7 +4506,7 @@ PyObject *igraphmodule_Graph_contract_vertices(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char* kwlist[] = {"mapping", "combine_attrs", NULL }; PyObject *mapping_o, *combination_o = Py_None; - igraph_vector_t mapping; + igraph_vector_int_t mapping; igraph_attribute_combination_t combination; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &mapping_o, @@ -4517,19 +4517,19 @@ PyObject *igraphmodule_Graph_contract_vertices(igraphmodule_GraphObject * self, combination_o, &combination)) return NULL; - if (igraphmodule_PyObject_to_vector_t(mapping_o, &mapping, 1)) { + if (igraphmodule_PyObject_to_vector_int_t(mapping_o, &mapping)) { igraph_attribute_combination_destroy(&combination); return NULL; } if (igraph_contract_vertices(&self->g, &mapping, &combination)) { igraph_attribute_combination_destroy(&combination); - igraph_vector_destroy(&mapping); + igraph_vector_int_destroy(&mapping); return NULL; } igraph_attribute_combination_destroy(&combination); - igraph_vector_destroy(&mapping); + igraph_vector_int_destroy(&mapping); Py_RETURN_NONE; } @@ -6550,20 +6550,20 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s * \sa igraph_triad_census */ PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self) { - igraph_vector_t result; + igraph_vector_int_t result; PyObject *list; - if (igraph_vector_init(&result, 16)) { + if (igraph_vector_int_init(&result, 16)) { return igraphmodule_handle_igraph_error(); } if (igraph_triad_census(&self->g, &result)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyTuple(&result); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyTuple(&result); + igraph_vector_int_destroy(&result); return list; } @@ -7737,9 +7737,9 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, matrix_o = igraphmodule_matrix_t_to_PyList(&matrix, IGRAPHMODULE_TYPE_INT); igraph_matrix_destroy(&matrix); - row_ids_o = igraphmodule_vector_t_to_PyList(&row_ids, IGRAPHMODULE_TYPE_INT); + row_ids_o = igraphmodule_vector_int_t_to_PyList(&row_ids); igraph_vector_int_destroy(&row_ids); - col_ids_o = igraphmodule_vector_t_to_PyList(&col_ids, IGRAPHMODULE_TYPE_INT); + col_ids_o = igraphmodule_vector_int_t_to_PyList(&col_ids); igraph_vector_int_destroy(&col_ids); return Py_BuildValue("NNN", matrix_o, row_ids_o, col_ids_o); @@ -10908,8 +10908,8 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); @@ -10952,11 +10952,11 @@ PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -10964,7 +10964,7 @@ PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); @@ -11058,11 +11058,11 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -11070,7 +11070,7 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); @@ -11138,11 +11138,11 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -11150,7 +11150,7 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); @@ -11184,11 +11184,11 @@ PyObject return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -11196,7 +11196,7 @@ PyObject else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); @@ -11230,11 +11230,11 @@ PyObject return NULL; for (i = 0; i < n; i++) { - igraph_vector_t *vec = (igraph_vector_t *) VECTOR(result)[i]; - item = igraphmodule_vector_t_to_PyTuple(vec); + igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; + item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -11242,7 +11242,7 @@ PyObject else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 4e2522f56..1f77a33be 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -271,9 +271,11 @@ def suite(): attribute_suite = unittest.makeSuite(AttributeTests) attribute_combination_suite = unittest.makeSuite(AttributeCombinationTests) unicode_attributes_suite = unittest.makeSuite(UnicodeAttributeTests) - return unittest.TestSuite( - [attribute_suite, attribute_combination_suite, unicode_attributes_suite] - ) + return unittest.TestSuite([ + attribute_suite, + attribute_combination_suite, + unicode_attributes_suite, + ]) def test(): diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 0ef0c69ab..c124f5332 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -2,7 +2,10 @@ from igraph import * -from .utils import temporary_file +try: + from .utils import temporary_file +except ImportError: + from utils import temporary_file class CliqueTests(unittest.TestCase): From eed1b2439a591ae7cf640c87e21ec27b8b05865a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 10 Aug 2021 18:53:38 +1000 Subject: [PATCH 0551/1892] Start fixing community detection algorithms --- src/_igraph/convert.c | 60 +++++++++---------- src/_igraph/graphobject.c | 118 ++++++++++++++++++++------------------ 2 files changed, 92 insertions(+), 86 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index ae458f03b..5ad48d8b3 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1908,36 +1908,35 @@ PyObject* igraphmodule_matrix_t_to_PyList(const igraph_matrix_t *m, // create a new Python list list=PyList_New(nr); // populate the list with data - for (i=0; ig, &blocks, &cohesion, &parents, 0)) { igraph_vector_ptr_destroy(&blocks); - igraph_vector_destroy(&cohesion); - igraph_vector_destroy(&parents); + igraph_vector_int_destroy(&cohesion); + igraph_vector_int_destroy(&parents); igraphmodule_handle_igraph_error(); return NULL; } @@ -10839,21 +10839,21 @@ PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&blocks, igraph_vector_destroy); igraph_vector_ptr_destroy_all(&blocks); if (blocks_o == NULL) { - igraph_vector_destroy(&parents); - igraph_vector_destroy(&cohesion); + igraph_vector_int_destroy(&parents); + igraph_vector_int_destroy(&cohesion); return NULL; } - cohesion_o = igraphmodule_vector_t_to_PyList(&cohesion, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&cohesion); + cohesion_o = igraphmodule_vector_int_t_to_PyList(&cohesion); + igraph_vector_int_destroy(&cohesion); if (cohesion_o == NULL) { Py_DECREF(blocks_o); - igraph_vector_destroy(&parents); + igraph_vector_int_destroy(&parents); return NULL; } - parents_o = igraphmodule_vector_t_to_PyList(&parents, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&parents); + parents_o = igraphmodule_vector_int_t_to_PyList(&parents); + igraph_vector_int_destroy(&parents); if (parents_o == NULL) { Py_DECREF(blocks_o); @@ -11433,7 +11433,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj static char *kwlist[] = { "n", "weights", "arpack_options", NULL }; long int n=-1; PyObject *cl, *res, *merges, *weights_obj = Py_None; - igraph_vector_t members; + igraph_vector_int_t membership; igraph_vector_t *weights = 0; igraph_matrix_t m; igraph_real_t q; @@ -11445,12 +11445,12 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj return NULL; } - if (igraph_vector_init(&members, 0)) + if (igraph_vector_int_init(&membership, 0)) return igraphmodule_handle_igraph_error(); if (igraph_matrix_init(&m, 0, 0)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&members); + igraph_vector_int_destroy(&membership); return 0; } @@ -11462,15 +11462,15 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, ATTRIBUTE_TYPE_EDGE)) { igraph_matrix_destroy(&m); - igraph_vector_destroy(&members); + igraph_vector_int_destroy(&membership); return NULL; } arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; - if (igraph_community_leading_eigenvector(&self->g, weights, &m, &members, (igraph_integer_t) n, + if (igraph_community_leading_eigenvector(&self->g, weights, &m, &membership, (igraph_integer_t) n, igraphmodule_ARPACKOptions_get(arpack_options), &q, 0, 0, 0, 0, 0, 0)){ igraph_matrix_destroy(&m); - igraph_vector_destroy(&members); + igraph_vector_int_destroy(&membership); if (weights != 0) { igraph_vector_destroy(weights); free(weights); } @@ -11481,8 +11481,8 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj igraph_vector_destroy(weights); free(weights); } - cl = igraphmodule_vector_t_to_PyList(&members, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&members); + cl = igraphmodule_vector_int_t_to_PyList(&membership); + igraph_vector_int_destroy(&membership); if (cl == 0) { igraph_matrix_destroy(&m); return 0; @@ -11561,7 +11561,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, unsigned int nb_trials = 10; igraph_vector_t *e_ws = 0, *v_ws = 0; - igraph_vector_t membership; + igraph_vector_int_t membership; PyObject *res = Py_False; igraph_real_t codelength; @@ -11571,18 +11571,18 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, return NULL; } - if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { + if (igraph_vector_int_init(&membership, igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(e_weights, self, &e_ws, ATTRIBUTE_TYPE_EDGE)) { - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); return NULL; } if (igraphmodule_attrib_to_vector_t(v_weights, self, &v_ws, ATTRIBUTE_TYPE_VERTEX)){ - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (e_ws) { igraph_vector_destroy(e_ws); free(e_ws); @@ -11595,7 +11595,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, /*nb_trials=*/nb_trials, /*out*/ &membership, &codelength)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (e_ws) { igraph_vector_destroy(e_ws); free(e_ws); @@ -11617,8 +11617,8 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, free(v_ws); } - res = igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&membership); + res = igraphmodule_vector_int_t_to_PyList(&membership); + igraph_vector_int_destroy(&membership); if (!res) return NULL; @@ -11636,7 +11636,8 @@ PyObject *igraphmodule_Graph_community_label_propagation( static char *kwlist[] = { "weights", "initial", "fixed", NULL }; PyObject *weights_o = Py_None, *initial_o = Py_None, *fixed_o = Py_None; PyObject *result; - igraph_vector_t membership, *ws = 0, *initial = 0; + igraph_vector_int_t membership; + igraph_vector_t *ws = 0, *initial = 0; igraph_vector_bool_t fixed; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &weights_o, &initial_o, &fixed_o)) { @@ -11659,13 +11660,13 @@ PyObject *igraphmodule_Graph_community_label_propagation( return NULL; } - igraph_vector_init(&membership, igraph_vcount(&self->g)); + igraph_vector_int_init(&membership, igraph_vcount(&self->g)); if (igraph_community_label_propagation(&self->g, &membership, ws, initial, (fixed_o != Py_None ? &fixed : 0), 0)) { if (fixed_o != Py_None) igraph_vector_bool_destroy(&fixed); if (ws) { igraph_vector_destroy(ws); free(ws); } if (initial) { igraph_vector_destroy(initial); free(initial); } - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); return igraphmodule_handle_igraph_error(); } @@ -11673,8 +11674,8 @@ PyObject *igraphmodule_Graph_community_label_propagation( if (ws) { igraph_vector_destroy(ws); free(ws); } if (initial) { igraph_vector_destroy(initial); free(initial); } - result=igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&membership); + result=igraphmodule_vector_int_t_to_PyList(&membership); + igraph_vector_int_destroy(&membership); return result; } @@ -11689,7 +11690,8 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self PyObject *return_levels = Py_False; PyObject *mss, *qs, *res, *weights = Py_None; igraph_matrix_t memberships; - igraph_vector_t membership, modularity; + igraph_vector_int_t membership; + igraph_vector_t modularity; double resolution = 1; igraph_vector_t *ws; @@ -11701,13 +11703,13 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self return NULL; igraph_matrix_init(&memberships, 0, 0); - igraph_vector_init(&membership, 0); + igraph_vector_int_init(&membership, 0); igraph_vector_init(&modularity, 0); if (igraph_community_multilevel(&self->g, ws, resolution, &membership, &memberships, &modularity)) { if (ws) { igraph_vector_destroy(ws); free(ws); } - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); igraph_vector_destroy(&modularity); igraph_matrix_destroy(&memberships); return igraphmodule_handle_igraph_error(); @@ -11718,7 +11720,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self qs=igraphmodule_vector_t_to_PyList(&modularity, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&modularity); if (!qs) { - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); igraph_matrix_destroy(&memberships); return NULL; } @@ -11731,10 +11733,10 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self res=Py_BuildValue("NN", mss, qs); /* steals references */ } } else { - res=igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); + res=igraphmodule_vector_int_t_to_PyList(&membership); } - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); igraph_matrix_destroy(&memberships); return res; @@ -11748,7 +11750,7 @@ PyObject *igraphmodule_Graph_community_optimal_modularity( static char *kwlist[] = {"weights", NULL}; PyObject *weights_o = Py_None; igraph_real_t modularity; - igraph_vector_t membership; + igraph_vector_int_t membership; igraph_vector_t* weights = 0; PyObject *res; @@ -11756,21 +11758,21 @@ PyObject *igraphmodule_Graph_community_optimal_modularity( &weights_o)) return NULL; - if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { + if (igraph_vector_int_init(&membership, igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); return NULL; } if (igraph_community_optimal_modularity(&self->g, &modularity, &membership, weights)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (weights != 0) { igraph_vector_destroy(weights); free(weights); } @@ -11781,8 +11783,8 @@ PyObject *igraphmodule_Graph_community_optimal_modularity( igraph_vector_destroy(weights); free(weights); } - res = igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&membership); + res = igraphmodule_vector_int_t_to_PyList(&membership); + igraph_vector_int_destroy(&membership); if (!res) return NULL; @@ -11812,7 +11814,8 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, igraph_spincomm_update_t update_rule = IGRAPH_SPINCOMM_UPDATE_CONFIG; double gamma = 1; double lambda = 1; - igraph_vector_t *weights = 0, membership; + igraph_vector_t *weights = 0; + igraph_vector_int_t membership; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlOdddOdOd", kwlist, &weights_o, &spins, &parupdate_o, &start_temp, &stop_temp, @@ -11827,14 +11830,14 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, return NULL; } - if (igraph_vector_init(&membership, igraph_vcount(&self->g))) { + if (igraph_vector_int_init(&membership, igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); return NULL; } @@ -11844,7 +11847,7 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, start_temp, stop_temp, cool_fact, update_rule, gamma, impl, lambda)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (weights != 0) { igraph_vector_destroy(weights); free(weights); @@ -11857,8 +11860,8 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, free(weights); } - res = igraphmodule_vector_t_to_PyList(&membership, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&membership); + res = igraphmodule_vector_int_t_to_PyList(&membership); + igraph_vector_int_destroy(&membership); return res; } @@ -11934,7 +11937,8 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, long int n_iterations = 2; double resolution_parameter = 1.0; double beta = 0.01; - igraph_vector_t *edge_weights = NULL, *node_weights = NULL, *membership = NULL; + igraph_vector_t *edge_weights = NULL, *node_weights = NULL; + igraph_vector_int_t *membership = NULL; igraph_bool_t start = 1; igraph_bool_t normalize_resolution = 0; igraph_integer_t nb_clusters = 0; @@ -11959,7 +11963,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } /* Get initial membership */ - if (!error && igraphmodule_attrib_to_vector_t(initial_membership_o, self, &membership, + if (!error && igraphmodule_attrib_to_vector_int_t(initial_membership_o, self, &membership, ATTRIBUTE_TYPE_VERTEX)) { igraphmodule_handle_igraph_error(); error = -1; @@ -11967,12 +11971,12 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, if (!error && membership == 0) { start = 0; - membership = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); + membership = (igraph_vector_int_t*)calloc(1, sizeof(igraph_vector_int_t)); if (membership==0) { PyErr_NoMemory(); error = -1; } else { - igraph_vector_init(membership, 0); + igraph_vector_int_init(membership, 0); } } @@ -12031,11 +12035,11 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } if (!error && membership != 0) { - res = igraphmodule_vector_t_to_PyList(membership, IGRAPHMODULE_TYPE_INT); + res = igraphmodule_vector_int_t_to_PyList(membership); } if (membership != 0) { - igraph_vector_destroy(membership); + igraph_vector_int_destroy(membership); free(membership); } From 33e0b4bb57dd87b1e94b5494fe0f91c2abdbe6c7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 11 Aug 2021 10:19:17 +1000 Subject: [PATCH 0552/1892] Some matrix conversions, passes test_edgeseq.py --- src/_igraph/convert.c | 73 +++++++++++++++++++++++++++++++++++ src/_igraph/convert.h | 2 + src/_igraph/graphobject.c | 16 ++++---- src/_igraph/igraphmodule.c | 38 +++++++++--------- src/_igraph/indexing.c | 58 ++++++++++++++-------------- src/_igraph/vertexseqobject.c | 2 +- tests/test_edgeseq.py | 5 ++- 7 files changed, 136 insertions(+), 58 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 5ad48d8b3..7afccb12d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2044,6 +2044,79 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap return 0; } +/** + * \ingroup python_interface_conversion + * \brief Converts a Python list of lists to an \c igraph_matrix_int_t + * + * \param o the Python object representing the list of lists + * \param m the address of an uninitialized \c igraph_matrix_int_t + * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. + */ +int igraphmodule_PyList_to_matrix_int_t(PyObject* o, igraph_matrix_int_t *m) { + return igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(o, m, 0); +} + +/** + * \ingroup python_interface_conversion + * \brief Converts a Python list of lists to an \c igraph_matrix_int_t, ensuring + * that the matrix has at least the given number of columns + * + * \param o the Python object representing the list of lists + * \param m the address of an uninitialized \c igraph_matrix_int_t + * \param num_cols the minimum number of columns in the matrix + * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. + */ +int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols) { + Py_ssize_t nr, nc, n, i, j; + PyObject *row, *item; + int was_warned = 0; + + /* calculate the matrix dimensions */ + if (!PySequence_Check(o) || PyUnicode_Check(o)) { + PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + return 1; + } + + nr = PySequence_Size(o); + nc = min_cols > 0 ? min_cols : 0; + for (i = 0; i < nr; i++) { + row = PySequence_GetItem(o, i); + if (!PySequence_Check(row)) { + Py_DECREF(row); + PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + return 1; + } + n = PySequence_Size(row); + Py_DECREF(row); + if (n > nc) { + nc = n; + } + } + + igraph_matrix_int_init(m, nr, nc); + for (i = 0; i < nr; i++) { + row = PySequence_GetItem(o, i); + n = PySequence_Size(row); + for (j = 0; j < n; j++) { + item = PySequence_GetItem(row, j); + if (PyLong_Check(item)) { + MATRIX(*m, i, j) = (igraph_integer_t)PyLong_AsLong(item); + } else if (PyLong_Check(item)) { + MATRIX(*m, i, j) = (igraph_integer_t)PyLong_AsLong(item); + } else if (PyFloat_Check(item)) { + MATRIX(*m, i, j) = (igraph_integer_t)PyFloat_AsDouble(item); + } else if (!was_warned) { + PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); + was_warned=1; + } + Py_DECREF(item); + } + Py_DECREF(row); + } + + return 0; +} + /** * \ingroup python_interface_conversion * \brief Converts a Python list of lists to an \c igraph_vector_ptr_t diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 9f8de757d..28a3ae14d 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -102,6 +102,8 @@ int igraphmodule_PyObject_to_edgelist( int igraphmodule_PyList_to_matrix_t(PyObject *o, igraph_matrix_t *m); int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igraph_matrix_t *m, int min_cols); +int igraphmodule_PyList_to_matrix_int_t(PyObject *o, igraph_matrix_int_t *m); +int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols); PyObject* igraphmodule_strvector_t_to_PyList(igraph_strvector_t *v); int igraphmodule_PyList_to_strvector_t(PyObject* v, igraph_strvector_t *result); int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(PyObject *it, diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d0fe304ba..439874876 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1953,7 +1953,7 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, PyObject * args, PyObject * kwds) { igraphmodule_GraphObject *self; igraph_t g; - igraph_matrix_t m; + igraph_matrix_int_t m; PyObject *matrix, *mode_o = Py_None; igraph_adjacency_t mode = IGRAPH_ADJ_DIRECTED; @@ -1964,7 +1964,7 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, return NULL; if (igraphmodule_PyObject_to_adjacency_t(mode_o, &mode)) return NULL; - if (igraphmodule_PyList_to_matrix_t(matrix, &m)) { + if (igraphmodule_PyList_to_matrix_int_t(matrix, &m)) { PyErr_SetString(PyExc_TypeError, "Error while converting adjacency matrix"); return NULL; @@ -1972,11 +1972,11 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, if (igraph_adjacency(&g, &m, mode)) { igraphmodule_handle_igraph_error(); - igraph_matrix_destroy(&m); + igraph_matrix_int_destroy(&m); return NULL; } - igraph_matrix_destroy(&m); + igraph_matrix_int_destroy(&m); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -2763,7 +2763,7 @@ PyObject *igraphmodule_Graph_K_Regular(PyTypeObject * type, PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, PyObject * args, PyObject * kwds) { - igraph_vector_t dimvector; + igraph_vector_int_t dimvector; long int nei = 1; igraph_bool_t directed; igraph_bool_t mutual; @@ -2784,17 +2784,17 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, mutual = PyObject_IsTrue(o_mutual); circular = PyObject_IsTrue(o_circular); - if (igraphmodule_PyObject_to_vector_t(o_dimvector, &dimvector, 1)) + if (igraphmodule_PyObject_to_vector_int_t(o_dimvector, &dimvector)) return NULL; if (igraph_lattice(&g, &dimvector, (igraph_integer_t) nei, directed, mutual, circular)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&dimvector); + igraph_vector_int_destroy(&dimvector); return NULL; } - igraph_vector_destroy(&dimvector); + igraph_vector_int_destroy(&dimvector); CREATE_GRAPH_FROM_TYPE(self, g, type); diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index d19883e0c..d26a62229 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -231,7 +231,7 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd static char* kwlist[] = {"vs", "coords", NULL}; PyObject *vs, *o, *o1=0, *o2=0, *coords = Py_False; igraph_matrix_t mtrx; - igraph_vector_t result; + igraph_vector_int_t result; igraph_matrix_t resmat; long no_of_nodes, i; @@ -290,7 +290,7 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd } if (!PyObject_IsTrue(coords)) { - if (igraph_vector_init(&result, 0)) { + if (igraph_vector_int_init(&result, 0)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&mtrx); return NULL; @@ -298,11 +298,11 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd if (igraph_convex_hull(&mtrx, &result, 0)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&mtrx); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - o=igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + o=igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); } else { if (igraph_matrix_init(&resmat, 0, 0)) { igraphmodule_handle_igraph_error(); @@ -329,42 +329,42 @@ PyObject* igraphmodule_community_to_membership(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "merges", "nodes", "steps", "return_csize", NULL }; PyObject *merges_o, *return_csize = Py_False, *result_o; - igraph_matrix_t merges; - igraph_vector_t result, csize, *csize_p = 0; + igraph_matrix_int_t merges; + igraph_vector_int_t result, csize, *csize_p = 0; long int nodes, steps; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!ll|O", kwlist, &PyList_Type, &merges_o, &nodes, &steps, &return_csize)) return NULL; - if (igraphmodule_PyList_to_matrix_t_with_minimum_column_count(merges_o, &merges, 2)) return NULL; + if (igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(merges_o, &merges, 2)) return NULL; - if (igraph_vector_init(&result, nodes)) { + if (igraph_vector_int_init(&result, nodes)) { igraphmodule_handle_igraph_error(); - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return NULL; } if (PyObject_IsTrue(return_csize)) { - igraph_vector_init(&csize, 0); + igraph_vector_int_init(&csize, 0); csize_p = &csize; } if (igraph_community_to_membership(&merges, (igraph_integer_t)nodes, (igraph_integer_t)steps, &result, csize_p)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); - if (csize_p) igraph_vector_destroy(csize_p); - igraph_matrix_destroy(&merges); + igraph_vector_int_destroy(&result); + if (csize_p) igraph_vector_int_destroy(csize_p); + igraph_matrix_int_destroy(&merges); return NULL; } - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); - result_o = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + result_o = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); if (csize_p) { - PyObject* csize_o = igraphmodule_vector_t_to_PyList(csize_p, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(csize_p); + PyObject* csize_o = igraphmodule_vector_int_t_to_PyList(csize_p); + igraph_vector_int_destroy(csize_p); if (csize_o) return Py_BuildValue("NN", result_o, csize_o); Py_DECREF(result_o); return NULL; diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index 8eececb9c..08cd04d95 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -133,7 +133,7 @@ PyObject* igraphmodule_Graph_adjmatrix_get_index(igraph_t* graph, static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, igraph_integer_t from, igraph_vs_t* to, igraph_neimode_t neimode, PyObject* values) { - igraph_vector_t eids; + igraph_vector_int_t eids; igraph_integer_t eid; igraph_vit_t vit; PyObject *result = 0, *item; @@ -142,11 +142,11 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, if (igraph_vs_is_all(to)) { /* Simple case: all edges */ - IGRAPH_PYCHECK(igraph_vector_init(&eids, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &eids); + IGRAPH_PYCHECK(igraph_vector_int_init(&eids, 0)); + IGRAPH_FINALLY(igraph_vector_int_destroy, &eids); IGRAPH_PYCHECK(igraph_incident(graph, &eids, from, neimode)); - n = igraph_vector_size(&eids); + n = igraph_vector_int_size(&eids); result = igraphmodule_PyList_Zeroes(igraph_vcount(graph)); if (result == 0) { IGRAPH_FINALLY_FREE(); @@ -165,7 +165,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, } IGRAPH_FINALLY_CLEAN(1); - igraph_vector_destroy(&eids); + igraph_vector_int_destroy(&eids); return result; } @@ -228,28 +228,28 @@ static INLINE igraph_bool_t deleting_edge(PyObject* value) { * adjacency matrix assignment. */ typedef struct { - igraph_vector_t to_add; + igraph_vector_int_t to_add; PyObject* to_add_values; - igraph_vector_t to_delete; + igraph_vector_int_t to_delete; } igraphmodule_i_Graph_adjmatrix_set_index_data_t; int igraphmodule_i_Graph_adjmatrix_set_index_data_init( igraphmodule_i_Graph_adjmatrix_set_index_data_t* data) { - if (igraph_vector_init(&data->to_add, 0)) { + if (igraph_vector_int_init(&data->to_add, 0)) { igraphmodule_handle_igraph_error(); return -1; } - if (igraph_vector_init(&data->to_delete, 0)) { + if (igraph_vector_int_init(&data->to_delete, 0)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&data->to_delete); + igraph_vector_int_destroy(&data->to_delete); return -1; } data->to_add_values = PyList_New(0); if (data->to_add_values == 0) { - igraph_vector_destroy(&data->to_add); - igraph_vector_destroy(&data->to_delete); + igraph_vector_int_destroy(&data->to_add); + igraph_vector_int_destroy(&data->to_delete); return -1; } @@ -258,8 +258,8 @@ int igraphmodule_i_Graph_adjmatrix_set_index_data_init( void igraphmodule_i_Graph_adjmatrix_set_index_data_destroy( igraphmodule_i_Graph_adjmatrix_set_index_data_t* data) { - igraph_vector_destroy(&data->to_add); - igraph_vector_destroy(&data->to_delete); + igraph_vector_int_destroy(&data->to_add); + igraph_vector_int_destroy(&data->to_delete); Py_DECREF(data->to_add_values); } @@ -311,9 +311,9 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (deleting_edge(item)) { /* Deleting edges if eid != -1 */ if (eid != -1) { - if (igraph_vector_push_back(&data->to_delete, eid)) { + if (igraph_vector_int_push_back(&data->to_delete, eid)) { igraphmodule_handle_igraph_error(); - igraph_vector_clear(&data->to_delete); + igraph_vector_int_clear(&data->to_delete); ok = 0; break; } @@ -321,10 +321,10 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, } else { if (eid == -1) { /* Adding edges */ - if (igraph_vector_push_back(&data->to_add, v1) || - igraph_vector_push_back(&data->to_add, v2)) { + if (igraph_vector_int_push_back(&data->to_add, v1) || + igraph_vector_int_push_back(&data->to_add, v2)) { igraphmodule_handle_igraph_error(); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); ok = 0; break; } @@ -332,7 +332,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, Py_INCREF(new_value); if (PyList_Append(data->to_add_values, new_value)) { Py_DECREF(new_value); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); ok = 0; break; } @@ -342,7 +342,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, Py_INCREF(item); if (PyList_SetItem(values, eid, item)) { Py_DECREF(item); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); } } } @@ -372,9 +372,9 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (deleting) { /* Deleting edges if eid != -1 */ if (eid != -1) { - if (igraph_vector_push_back(&data->to_delete, eid)) { + if (igraph_vector_int_push_back(&data->to_delete, eid)) { igraphmodule_handle_igraph_error(); - igraph_vector_clear(&data->to_delete); + igraph_vector_int_clear(&data->to_delete); ok = 0; break; } @@ -382,10 +382,10 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, } else { if (eid == -1) { /* Adding edges */ - if (igraph_vector_push_back(&data->to_add, v1) || - igraph_vector_push_back(&data->to_add, v2)) { + if (igraph_vector_int_push_back(&data->to_add, v1) || + igraph_vector_int_push_back(&data->to_add, v2)) { igraphmodule_handle_igraph_error(); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); ok = 0; break; } @@ -393,7 +393,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, Py_INCREF(new_value); if (PyList_Append(data->to_add_values, new_value)) { Py_DECREF(new_value); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); ok = 0; break; } @@ -403,7 +403,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, Py_INCREF(new_value); if (PyList_SetItem(values, eid, new_value)) { Py_DECREF(new_value); - igraph_vector_clear(&data->to_add); + igraph_vector_int_clear(&data->to_add); } } } @@ -517,7 +517,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, if (ok) { /* Third phase: add the new edges in one batch */ - if (!igraph_vector_empty(&data.to_add)) { + if (!igraph_vector_int_empty(&data.to_add)) { eid = igraph_ecount(graph); igraph_add_edges(graph, &data.to_add, 0); if (values != 0) { diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 7ee4fcde4..4b2e83a3b 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -75,7 +75,7 @@ igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) { if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) { igraph_vector_int_t v; - if (igraph_vector_copy(&v, o->vs.data.vecptr)) { + if (igraph_vector_int_copy(&v, o->vs.data.vecptr)) { igraphmodule_handle_igraph_error(); return 0; } diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index 74667b758..f1b451512 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -4,7 +4,10 @@ from igraph import * -from .utils import is_pypy +try: + from .utils import is_pypy +except ImportError: + from utils import is_pypy try: import numpy as np From afbcb5d790bf7ce11e307e9221bdb272474aae22 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 11 Aug 2021 11:24:17 +1000 Subject: [PATCH 0553/1892] Pass test_games.py and test_foreign.py --- src/_igraph/convert.c | 45 ++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 214 +++++++++++++++++++------------------ src/_igraph/igraphmodule.c | 32 +++--- tests/test_foreign.py | 25 ++--- tests/test_games.py | 9 +- 6 files changed, 189 insertions(+), 137 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 7afccb12d..7f3e626e6 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1939,6 +1939,51 @@ PyObject* igraphmodule_matrix_t_to_PyList(const igraph_matrix_t *m, return list; } +/** + * \ingroup python_interface_conversion + * \brief Converts an igraph \c igraph_matrix_int_t to a Python list of lists + * + * \param m the \c igraph_matrix_int_t containing the matrix to be converted + * \return the Python list of lists as a \c PyObject*, or \c NULL if an error occurred + */ +PyObject* igraphmodule_matrix_int_t_to_PyList(const igraph_matrix_int_t *m) { + PyObject *list, *row, *item; + Py_ssize_t nr, nc, i, j; + + nr = igraph_matrix_int_nrow(m); + nc = igraph_matrix_int_ncol(m); + if (nr<0 || nc<0) + return igraphmodule_handle_igraph_error(); + + // create a new Python list + list=PyList_New(nr); + // populate the list with data + for (i=0; ig)[ATTRHASH_IDX_VERTEX], attribute_key, type_vec_o) == -1) { Py_DECREF(type_vec_o); + igraph_vector_int_destroy(&in_type_vec); + igraph_vector_int_destroy(&out_type_vec); igraph_matrix_destroy(&pm); igraph_matrix_destroy(&td); - igraph_vector_destroy(&in_type_vec); - igraph_vector_destroy(&out_type_vec); Py_DECREF(self); return NULL; } } Py_DECREF(type_vec_o); - igraph_vector_destroy(&in_type_vec); - igraph_vector_destroy(&out_type_vec); + igraph_vector_int_destroy(&in_type_vec); + igraph_vector_int_destroy(&out_type_vec); } igraph_matrix_destroy(&pm); @@ -4372,7 +4372,7 @@ PyObject *igraphmodule_Graph_clusters(igraphmodule_GraphObject * self, { static char *kwlist[] = { "mode", NULL }; igraph_connectedness_t mode = IGRAPH_STRONG; - igraph_vector_t res1, res2; + igraph_vector_int_t res1, res2; igraph_integer_t no; PyObject *list, *mode_o = Py_None; @@ -4382,19 +4382,19 @@ PyObject *igraphmodule_Graph_clusters(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_connectedness_t(mode_o, &mode)) return NULL; - igraph_vector_init(&res1, igraph_vcount(&self->g)); - igraph_vector_init(&res2, 10); + igraph_vector_int_init(&res1, igraph_vcount(&self->g)); + igraph_vector_int_init(&res2, 10); if (igraph_clusters(&self->g, &res1, &res2, &no, mode)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&res1); - igraph_vector_destroy(&res2); + igraph_vector_int_destroy(&res1); + igraph_vector_int_destroy(&res2); return NULL; } - list = igraphmodule_vector_t_to_PyList(&res1, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res1); - igraph_vector_destroy(&res2); + list = igraphmodule_vector_int_t_to_PyList(&res1); + igraph_vector_int_destroy(&res1); + igraph_vector_int_destroy(&res2); return list; } @@ -4953,7 +4953,8 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * return NULL; } - res = (igraph_vector_t *) calloc(no_of_target_nodes, sizeof(igraph_vector_t)); + // FIXME: is this alright? + res = (igraph_vector_int_t *) calloc(no_of_target_nodes, sizeof(igraph_vector_int_t)); if (!res) { PyErr_SetString(PyExc_MemoryError, ""); igraph_vector_ptr_destroy(ptrvec); free(ptrvec); @@ -4964,13 +4965,13 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * for (i = 0; i < no_of_target_nodes; i++) { VECTOR(*ptrvec)[i] = &res[i]; - igraph_vector_init(&res[i], 0); + igraph_vector_int_init(&res[i], 0); } if (igraph_get_shortest_paths_dijkstra(&self->g, use_edges ? 0 : ptrvec, use_edges ? ptrvec : 0, from, to, weights, mode, 0, 0)) { igraphmodule_handle_igraph_error(); - for (j = 0; j < no_of_target_nodes; j++) igraph_vector_destroy(&res[j]); + for (j = 0; j < no_of_target_nodes; j++) igraph_vector_int_destroy(&res[j]); free(res); igraph_vector_ptr_destroy(ptrvec); free(ptrvec); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4984,25 +4985,25 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * list = PyList_New(no_of_target_nodes); if (!list) { - for (j = 0; j < no_of_target_nodes; j++) igraph_vector_destroy(&res[j]); + for (j = 0; j < no_of_target_nodes; j++) igraph_vector_int_destroy(&res[j]); free(res); return NULL; } for (i = 0; i < no_of_target_nodes; i++) { - item = igraphmodule_vector_t_to_PyList(&res[i], IGRAPHMODULE_TYPE_INT); + item = igraphmodule_vector_int_t_to_PyList(&res[i]); if (!item || PyList_SetItem(list, i, item)) { if (item) { Py_DECREF(item); } Py_DECREF(list); - for (j = 0; j < no_of_target_nodes; j++) igraph_vector_destroy(&res[j]); + for (j = 0; j < no_of_target_nodes; j++) igraph_vector_int_destroy(&res[j]); free(res); return NULL; } } - for (j = 0; j < no_of_target_nodes; j++) igraph_vector_destroy(&res[j]); + for (j = 0; j < no_of_target_nodes; j++) igraph_vector_int_destroy(&res[j]); free(res); return list; } @@ -10175,7 +10176,8 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, igraph_real_t result; long int vid1 = -1, vid2 = -1; igraph_integer_t v1, v2; - igraph_vector_t flow, cut, partition; + igraph_vector_t flow; + igraph_vector_int_t cut, partition; igraph_maxflow_stats_t stats; if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O", kwlist, @@ -10194,16 +10196,16 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&cut, 0)) { + if (igraph_vector_int_init(&cut, 0)) { igraph_vector_destroy(&capacity_vector); igraph_vector_destroy(&flow); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&partition, 0)) { + if (igraph_vector_int_init(&partition, 0)) { igraph_vector_destroy(&capacity_vector); igraph_vector_destroy(&flow); - igraph_vector_destroy(&cut); + igraph_vector_int_destroy(&cut); return igraphmodule_handle_igraph_error(); } @@ -10211,8 +10213,8 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, v1, v2, &capacity_vector, &stats)) { igraph_vector_destroy(&capacity_vector); igraph_vector_destroy(&flow); - igraph_vector_destroy(&cut); - igraph_vector_destroy(&partition); + igraph_vector_int_destroy(&cut); + igraph_vector_int_destroy(&partition); return igraphmodule_handle_igraph_error(); } @@ -10222,21 +10224,21 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, igraph_vector_destroy(&flow); if (flow_o == NULL) { - igraph_vector_destroy(&cut); - igraph_vector_destroy(&partition); + igraph_vector_int_destroy(&cut); + igraph_vector_int_destroy(&partition); return NULL; } - cut_o = igraphmodule_vector_t_to_PyList(&cut, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&cut); + cut_o = igraphmodule_vector_int_t_to_PyList(&cut); + igraph_vector_int_destroy(&cut); if (cut_o == NULL) { - igraph_vector_destroy(&partition); + igraph_vector_int_destroy(&partition); return NULL; } - partition_o = igraphmodule_vector_t_to_PyList(&partition, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&partition); + partition_o = igraphmodule_vector_int_t_to_PyList(&partition); + igraph_vector_int_destroy(&partition); if (partition_o == NULL) return NULL; @@ -10455,7 +10457,7 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, int retval; igraph_vector_t capacity_vector; igraph_real_t value; - igraph_vector_t partition, partition2, cut; + igraph_vector_int_t partition, partition2, cut; igraph_integer_t source = -1, target = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, @@ -10472,18 +10474,18 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, self, ATTRHASH_IDX_EDGE, 1.0)) return igraphmodule_handle_igraph_error(); - if (igraph_vector_init(&partition, 0)) { + if (igraph_vector_int_init(&partition, 0)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&partition2, 0)) { - igraph_vector_destroy(&partition); + if (igraph_vector_int_init(&partition2, 0)) { + igraph_vector_int_destroy(&partition); igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&cut, 0)) { - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + if (igraph_vector_int_init(&cut, 0)) { + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } @@ -10501,9 +10503,9 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, } if (retval) { - igraph_vector_destroy(&cut); - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&cut); + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); igraph_vector_destroy(&capacity_vector); if (!PyErr_Occurred()) igraphmodule_handle_igraph_error(); @@ -10512,24 +10514,24 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, igraph_vector_destroy(&capacity_vector); - cut_o=igraphmodule_vector_t_to_PyList(&cut, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&cut); + cut_o=igraphmodule_vector_int_t_to_PyList(&cut); + igraph_vector_int_destroy(&cut); if (!cut_o) { - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); return 0; } - part_o=igraphmodule_vector_t_to_PyList(&partition, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&partition); + part_o=igraphmodule_vector_int_t_to_PyList(&partition); + igraph_vector_int_destroy(&partition); if (!part_o) { Py_DECREF(cut_o); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&partition2); return 0; } - part2_o=igraphmodule_vector_t_to_PyList(&partition2, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&partition2); + part2_o=igraphmodule_vector_int_t_to_PyList(&partition2); + igraph_vector_int_destroy(&partition2); if (!part2_o) { Py_DECREF(part_o); Py_DECREF(cut_o); @@ -10603,7 +10605,7 @@ PyObject *igraphmodule_Graph_st_mincut(igraphmodule_GraphObject * self, PyObject *source_o, *target_o, *capacity_o = Py_None; igraph_vector_t capacity_vector; igraph_real_t value; - igraph_vector_t partition, partition2, cut; + igraph_vector_int_t partition, partition2, cut; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &source_o, &target_o, &capacity_o)) @@ -10619,51 +10621,51 @@ PyObject *igraphmodule_Graph_st_mincut(igraphmodule_GraphObject * self, self, ATTRHASH_IDX_EDGE, 1.0)) return igraphmodule_handle_igraph_error(); - if (igraph_vector_init(&partition, 0)) { + if (igraph_vector_int_init(&partition, 0)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&partition2, 0)) { - igraph_vector_destroy(&partition); + if (igraph_vector_int_init(&partition2, 0)) { + igraph_vector_int_destroy(&partition); igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&cut, 0)) { - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + if (igraph_vector_int_init(&cut, 0)) { + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } if (igraph_st_mincut(&self->g, &value, &cut, &partition, &partition2, source, target, &capacity_vector)) { - igraph_vector_destroy(&cut); - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&cut); + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } igraph_vector_destroy(&capacity_vector); - cut_o=igraphmodule_vector_t_to_PyList(&cut, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&cut); + cut_o=igraphmodule_vector_int_t_to_PyList(&cut); + igraph_vector_int_destroy(&cut); if (!cut_o) { - igraph_vector_destroy(&partition); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&partition); + igraph_vector_int_destroy(&partition2); return NULL; } - part_o=igraphmodule_vector_t_to_PyList(&partition, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&partition); + part_o=igraphmodule_vector_int_t_to_PyList(&partition); + igraph_vector_int_destroy(&partition); if (!part_o) { Py_DECREF(cut_o); - igraph_vector_destroy(&partition2); + igraph_vector_int_destroy(&partition2); return NULL; } - part2_o=igraphmodule_vector_t_to_PyList(&partition2, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&partition2); + part2_o=igraphmodule_vector_int_t_to_PyList(&partition2); + igraph_vector_int_destroy(&partition2); if (!part2_o) { Py_DECREF(part_o); Py_DECREF(cut_o); @@ -11689,7 +11691,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self static char *kwlist[] = { "weights", "return_levels", "resolution", NULL }; PyObject *return_levels = Py_False; PyObject *mss, *qs, *res, *weights = Py_None; - igraph_matrix_t memberships; + igraph_matrix_int_t memberships; igraph_vector_int_t membership; igraph_vector_t modularity; double resolution = 1; @@ -11702,7 +11704,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self if (igraphmodule_attrib_to_vector_t(weights, self, &ws, ATTRIBUTE_TYPE_EDGE)) return NULL; - igraph_matrix_init(&memberships, 0, 0); + igraph_matrix_int_init(&memberships, 0, 0); igraph_vector_int_init(&membership, 0); igraph_vector_init(&modularity, 0); @@ -11711,7 +11713,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self if (ws) { igraph_vector_destroy(ws); free(ws); } igraph_vector_int_destroy(&membership); igraph_vector_destroy(&modularity); - igraph_matrix_destroy(&memberships); + igraph_matrix_int_destroy(&memberships); return igraphmodule_handle_igraph_error(); } @@ -11721,12 +11723,12 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self igraph_vector_destroy(&modularity); if (!qs) { igraph_vector_int_destroy(&membership); - igraph_matrix_destroy(&memberships); + igraph_matrix_int_destroy(&memberships); return NULL; } if (PyObject_IsTrue(return_levels)) { - mss=igraphmodule_matrix_t_to_PyList(&memberships, IGRAPHMODULE_TYPE_INT); + mss=igraphmodule_matrix_int_t_to_PyList(&memberships); if (!mss) { res = mss; } else { @@ -11737,7 +11739,7 @@ PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self } igraph_vector_int_destroy(&membership); - igraph_matrix_destroy(&memberships); + igraph_matrix_int_destroy(&memberships); return res; } @@ -11873,7 +11875,7 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "weights", "steps", NULL }; PyObject *ms, *qs, *res, *weights = Py_None; - igraph_matrix_t merges; + igraph_matrix_int_t merges; int steps=4; igraph_vector_t q, *ws=0; @@ -11884,7 +11886,7 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, if (igraphmodule_attrib_to_vector_t(weights, self, &ws, ATTRIBUTE_TYPE_EDGE)) return NULL; - igraph_matrix_init(&merges, 0, 0); + igraph_matrix_int_init(&merges, 0, 0); igraph_vector_init(&q, 0); if (igraph_community_walktrap(&self->g, ws, steps, &merges, &q, 0)) { @@ -11892,7 +11894,7 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, igraph_vector_destroy(ws); free(ws); } igraph_vector_destroy(&q); - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return igraphmodule_handle_igraph_error(); } if (ws) { @@ -11902,12 +11904,12 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, qs = igraphmodule_vector_t_to_PyList(&q, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&q); if (!qs) { - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return NULL; } - ms = igraphmodule_matrix_t_to_PyList(&merges, IGRAPHMODULE_TYPE_INT); - igraph_matrix_destroy(&merges); + ms = igraphmodule_matrix_int_t_to_PyList(&merges); + igraph_matrix_int_destroy(&merges); if (ms == NULL) { Py_DECREF(qs); @@ -12064,7 +12066,7 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self, int steps=10; igraph_neimode_t mode = IGRAPH_OUT; igraph_random_walk_stuck_t stuck = IGRAPH_RANDOM_WALK_STUCK_RETURN; - igraph_vector_t walk; + igraph_vector_int_t walk; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OiOO", kwlist, &start_o, &steps, &mode_o, &stuck_o)) @@ -12079,16 +12081,16 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_random_walk_stuck_t(stuck_o, &stuck)) return NULL; - if (igraph_vector_init(&walk, steps)) + if (igraph_vector_int_init(&walk, steps)) return igraphmodule_handle_igraph_error(); if (igraph_random_walk(&self->g, &walk, start, mode, steps, stuck)) { - igraph_vector_destroy(&walk); + igraph_vector_int_destroy(&walk); return igraphmodule_handle_igraph_error(); } - res = igraphmodule_vector_t_to_PyList(&walk, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&walk); + res = igraphmodule_vector_int_t_to_PyList(&walk); + igraph_vector_int_destroy(&walk); return res; } diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index d26a62229..31946354e 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -378,7 +378,7 @@ PyObject* igraphmodule_compare_communities(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "comm1", "comm2", "method", NULL }; PyObject *comm1_o, *comm2_o, *method_o = Py_None; - igraph_vector_t comm1, comm2; + igraph_vector_int_t comm1, comm2; igraph_community_comparison_t method = IGRAPH_COMMCMP_VI; igraph_real_t result; @@ -389,21 +389,21 @@ PyObject* igraphmodule_compare_communities(PyObject *self, if (igraphmodule_PyObject_to_community_comparison_t(method_o, &method)) return NULL; - if (igraphmodule_PyObject_to_vector_t(comm1_o, &comm1, 0)) + if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) return NULL; - if (igraphmodule_PyObject_to_vector_t(comm2_o, &comm2, 0)) { - igraph_vector_destroy(&comm1); + if (igraphmodule_PyObject_to_vector_int_t(comm2_o, &comm2)) { + igraph_vector_int_destroy(&comm1); return NULL; } if (igraph_compare_communities(&comm1, &comm2, &result, method)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&comm1); - igraph_vector_destroy(&comm2); + igraph_vector_int_destroy(&comm1); + igraph_vector_int_destroy(&comm2); return NULL; } - igraph_vector_destroy(&comm1); - igraph_vector_destroy(&comm2); + igraph_vector_int_destroy(&comm1); + igraph_vector_int_destroy(&comm2); return PyFloat_FromDouble((double)result); } @@ -570,28 +570,28 @@ PyObject* igraphmodule_split_join_distance(PyObject *self, PyObject *args, PyObject *kwds) { static char* kwlist[] = { "comm1", "comm2", NULL }; PyObject *comm1_o, *comm2_o; - igraph_vector_t comm1, comm2; + igraph_vector_int_t comm1, comm2; igraph_integer_t distance12, distance21; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &comm1_o, &comm2_o)) return NULL; - if (igraphmodule_PyObject_to_vector_t(comm1_o, &comm1, 0)) + if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) return NULL; - if (igraphmodule_PyObject_to_vector_t(comm2_o, &comm2, 0)) { - igraph_vector_destroy(&comm1); + if (igraphmodule_PyObject_to_vector_int_t(comm2_o, &comm2)) { + igraph_vector_int_destroy(&comm1); return NULL; } if (igraph_split_join_distance(&comm1, &comm2, &distance12, &distance21)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&comm1); - igraph_vector_destroy(&comm2); + igraph_vector_int_destroy(&comm1); + igraph_vector_int_destroy(&comm2); return NULL; } - igraph_vector_destroy(&comm1); - igraph_vector_destroy(&comm2); + igraph_vector_int_destroy(&comm1); + igraph_vector_int_destroy(&comm2); return Py_BuildValue("ll", (long)distance12, (long)distance21); } diff --git a/tests/test_foreign.py b/tests/test_foreign.py index a3db0b869..5d5243e4b 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -4,7 +4,10 @@ from igraph import Graph, InternalError -from .utils import temporary_file +try: + from .utils import temporary_file +except ImportError: + from utils import temporary_file try: import networkx as nx @@ -277,20 +280,18 @@ def testAdjacency(self): ) as tmpfname: g = Graph.Read_Adjacency(tmpfname) self.assertTrue(isinstance(g, Graph)) - self.assertTrue( - g.vcount() == 6 - and g.ecount() == 18 - and g.is_directed() - and "weight" not in g.edge_attributes() - ) + self.assertEqual(g.vcount(), 6) + self.assertEqual(g.ecount(), 18) + self.assertTrue(g.is_directed()) + self.assertTrue("weight" not in g.edge_attributes()) + g = Graph.Read_Adjacency(tmpfname, attribute="weight") self.assertTrue(isinstance(g, Graph)) + self.assertEqual(g.vcount(), 6) + self.assertEqual(g.ecount(), 12) + self.assertTrue(g.is_directed()) self.assertTrue( - g.vcount() == 6 - and g.ecount() == 12 - and g.is_directed() - and g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] - ) + g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]) g.write_adjacency(tmpfname) diff --git a/tests/test_games.py b/tests/test_games.py index 5b1a35ed1..5f7723790 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -24,7 +24,8 @@ def testRecentDegree(self): def testPreference(self): g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(len(g.clusters()), 2) g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]], attribute="type") l = g.vs.get_attribute_values("type") @@ -32,7 +33,8 @@ def testPreference(self): def testAsymmetricPreference(self): g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[0, 1], [1, 0]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(len(g.clusters()), 2) g = Graph.Asymmetric_Preference( 100, [[0, 1], [1, 0]], [[1, 0], [0, 1]], attribute="type" @@ -43,7 +45,8 @@ def testAsymmetricPreference(self): self.assertTrue(min(l1) == 0 and max(l1) == 1 and min(l2) == 0 and max(l2) == 1) g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 1) + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(len(g.clusters()), 1) def testTreeGame(self): # Prufer algorithm From f78cbcbb2640a1cf842e59c7980bfdb6b49062fb Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 11 Aug 2021 21:51:41 +1000 Subject: [PATCH 0554/1892] Passes all tests except callback_function one --- src/_igraph/bfsiter.c | 8 +- src/_igraph/bfsiter.h | 2 +- src/_igraph/convert.c | 137 +++++++++++++++++- src/_igraph/convert.h | 3 + src/_igraph/dfsiter.c | 8 +- src/_igraph/dfsiter.h | 2 +- src/_igraph/graphobject.c | 293 +++++++++++++++++++------------------- src/_igraph/operators.c | 8 +- tests/test_isomorphism.py | 8 +- tests/test_structural.py | 6 +- tests/test_vertexseq.py | 5 +- 11 files changed, 309 insertions(+), 171 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 9f7d12331..c86c90702 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -65,7 +65,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_vector_init(&o->neis, 0)) { + if (igraph_vector_int_init(&o->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); igraph_dqueue_destroy(&o->queue); return NULL; @@ -80,7 +80,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_dqueue_push(&o->queue, 0) || igraph_dqueue_push(&o->queue, -1)) { igraph_dqueue_destroy(&o->queue); - igraph_vector_destroy(&o->neis); + igraph_vector_int_destroy(&o->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } @@ -132,7 +132,7 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { Py_XDECREF(tmp); igraph_dqueue_destroy(&self->queue); - igraph_vector_destroy(&self->neis); + igraph_vector_int_destroy(&self->neis); free(self->visited); self->visited=0; @@ -168,7 +168,7 @@ PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { return NULL; } - for (i=0; ineis); i++) { + for (i=0; ineis); i++) { igraph_integer_t neighbor = (igraph_integer_t)VECTOR(self->neis)[i]; if (self->visited[neighbor]==0) { self->visited[neighbor]=1; diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index 94ddb6113..e36f03069 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -35,7 +35,7 @@ typedef struct PyObject_HEAD igraphmodule_GraphObject* gref; igraph_dqueue_t queue; - igraph_vector_t neis; + igraph_vector_int_t neis; igraph_t *graph; char *visited; igraph_neimode_t mode; diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 7f3e626e6..397794ede 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1348,6 +1348,40 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { return list; } +/** + * \ingroup python_interface_conversion + * \brief Converts an igraph \c igraph_vector_int_t to a Python integer list, with nan + * + * \param v the \c igraph_vector_int_t containing the vector to be converted + * \return the Python integer list as a \c PyObject*, or \c NULL if an error occurred + */ +PyObject* igraphmodule_vector_int_t_to_PyList_with_nan(const igraph_vector_int_t *v, const igraph_integer_t nanvalue) { + PyObject *list, *item; + Py_ssize_t n, i; + igraph_integer_t val; + + n = igraph_vector_int_size(v); + if (n<0) + return igraphmodule_handle_igraph_error(); + + list=PyList_New(n); + for (i=0; ineis, 0)) { + if (igraph_vector_int_init(&o->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); igraph_stack_destroy(&o->stack); return NULL; @@ -81,7 +81,7 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_stack_push(&o->stack, 0) || igraph_stack_push(&o->stack, -1)) { igraph_stack_destroy(&o->stack); - igraph_vector_destroy(&o->neis); + igraph_vector_int_destroy(&o->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } @@ -133,7 +133,7 @@ int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { Py_XDECREF(tmp); igraph_stack_destroy(&self->stack); - igraph_vector_destroy(&self->neis); + igraph_vector_int_destroy(&self->neis); free(self->visited); self->visited = 0; @@ -193,7 +193,7 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { igraphmodule_handle_igraph_error(); return NULL; } - for (i=0; ineis); i++) { + for (i=0; ineis); i++) { igraph_integer_t neighbor = (igraph_integer_t)VECTOR(self->neis)[i]; /* new neighbor, push the next item onto the stack */ if (self->visited[neighbor] == 0) { diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h index 0a094c592..757caf798 100644 --- a/src/_igraph/dfsiter.h +++ b/src/_igraph/dfsiter.h @@ -35,7 +35,7 @@ typedef struct PyObject_HEAD igraphmodule_GraphObject* gref; igraph_stack_t stack; - igraph_vector_t neis; + igraph_vector_int_t neis; igraph_t *graph; char *visited; igraph_neimode_t mode; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d96b2e93f..3f6736acf 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1625,7 +1625,7 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, PyObject *dir = Py_True, *vcount_if_unconnected = Py_True, *result; PyObject *weights_o = Py_None; igraph_vector_t *weights = 0; - igraph_vector_t res; + igraph_vector_int_t res; static char *kwlist[] = { "directed", "unconn", "weights", NULL }; @@ -1637,7 +1637,7 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; - igraph_vector_init(&res, 0); + igraph_vector_int_init(&res, 0); if (weights) { if (igraph_diameter_dijkstra(&self->g, weights, 0, /* from, to, vertex_path, edge_path */ @@ -1645,7 +1645,7 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(weights); free(weights); - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } igraph_vector_destroy(weights); free(weights); @@ -1659,8 +1659,8 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, } } - result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + result = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return result; } @@ -2808,7 +2808,7 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, */ PyObject *igraphmodule_Graph_LCF(PyTypeObject *type, PyObject *args, PyObject *kwds) { - igraph_vector_t shifts; + igraph_vector_int_t shifts; long int repeats, n; PyObject *o_shifts; igraphmodule_GraphObject *self; @@ -2820,16 +2820,16 @@ PyObject *igraphmodule_Graph_LCF(PyTypeObject *type, &n, &o_shifts, &repeats)) return NULL; - if (igraphmodule_PyObject_to_vector_t(o_shifts, &shifts, 0)) + if (igraphmodule_PyObject_to_vector_int_t(o_shifts, &shifts)) return NULL; if (igraph_lcf_vector(&g, (igraph_integer_t) n, &shifts, (igraph_integer_t) repeats)) { - igraph_vector_destroy(&shifts); + igraph_vector_int_destroy(&shifts); igraphmodule_handle_igraph_error(); return NULL; } - igraph_vector_destroy(&shifts); + igraph_vector_int_destroy(&shifts); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -2844,8 +2844,8 @@ PyObject *igraphmodule_Graph_LCF(PyTypeObject *type, PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, PyObject *args, PyObject *kwds) { - igraph_vector_t outdeg, indeg; - igraph_vector_t *indegp = 0; + igraph_vector_int_t outdeg, indeg; + igraph_vector_int_t *indegp = 0; igraph_edge_type_sw_t allowed_edge_types = IGRAPH_SIMPLE_SW; igraph_realize_degseq_t method = IGRAPH_REALIZE_DEGSEQ_SMALLEST; PyObject *outdeg_o, *indeg_o = Py_None; @@ -2867,13 +2867,13 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, return NULL; /* Outdegree vector */ - if (igraphmodule_PyObject_to_vector_t(outdeg_o, &outdeg, 0)) + if (igraphmodule_PyObject_to_vector_int_t(outdeg_o, &outdeg)) return NULL; /* Indegree vector, PyNone means undirected graph */ if (indeg_o != Py_None) { - if (igraphmodule_PyObject_to_vector_t(indeg_o, &indeg, 0)) { - igraph_vector_destroy(&outdeg); + if (igraphmodule_PyObject_to_vector_int_t(indeg_o, &indeg)) { + igraph_vector_int_destroy(&outdeg); return NULL; } indegp = &indeg; @@ -2881,16 +2881,16 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, /* C function takes care of multi-sw and directed corner case */ if (igraph_realize_degree_sequence(&g, &outdeg, indegp, allowed_edge_types, method)) { - igraph_vector_destroy(&outdeg); + igraph_vector_int_destroy(&outdeg); if (indegp != 0) - igraph_vector_destroy(&indeg); + igraph_vector_int_destroy(&indeg); igraphmodule_handle_igraph_error(); return NULL; } - igraph_vector_destroy(&outdeg); + igraph_vector_int_destroy(&outdeg); if (indegp != 0) - igraph_vector_destroy(&indeg); + igraph_vector_int_destroy(&indeg); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -3662,22 +3662,22 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, * \sa igraph_articulation_points */ PyObject *igraphmodule_Graph_articulation_points(igraphmodule_GraphObject *self) { - igraph_vector_t res; + igraph_vector_int_t res; PyObject *o; - if (igraph_vector_init(&res, 0)) { + if (igraph_vector_int_init(&res, 0)) { igraphmodule_handle_igraph_error(); return NULL; } if (igraph_articulation_points(&self->g, &res)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } - igraph_vector_sort(&res); - o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + igraph_vector_int_sort(&res); + o = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return o; } @@ -3989,7 +3989,7 @@ PyObject *igraphmodule_Graph_bibcoupling(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { igraph_vector_ptr_t components; - igraph_vector_t points; + igraph_vector_int_t points; igraph_bool_t return_articulation_points; igraph_integer_t no; PyObject *result, *aps=Py_False; @@ -4004,7 +4004,7 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se return NULL; } if (return_articulation_points) { - if (igraph_vector_init(&points, 0)) { + if (igraph_vector_int_init(&points, 0)) { igraphmodule_handle_igraph_error(); igraph_vector_ptr_destroy(&components); return NULL; @@ -4014,19 +4014,19 @@ PyObject *igraphmodule_Graph_biconnected_components(igraphmodule_GraphObject *se if (igraph_biconnected_components(&self->g, &no, &components, 0, 0, return_articulation_points ? &points : 0)) { igraphmodule_handle_igraph_error(); igraph_vector_ptr_destroy(&components); - if (return_articulation_points) igraph_vector_destroy(&points); + if (return_articulation_points) igraph_vector_int_destroy(&points); return NULL; } - result = igraphmodule_vector_ptr_t_to_PyList(&components, IGRAPHMODULE_TYPE_INT); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&components, igraph_vector_destroy); + result = igraphmodule_vector_int_ptr_t_to_PyList(&components); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&components, igraph_vector_int_destroy); igraph_vector_ptr_destroy_all(&components); if (return_articulation_points) { PyObject *result2; - igraph_vector_sort(&points); - result2 = igraphmodule_vector_t_to_PyList(&points, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&points); + igraph_vector_int_sort(&points); + result2 = igraphmodule_vector_int_t_to_PyList(&points); + igraph_vector_int_destroy(&points); return Py_BuildValue("NN", result, result2); /* references stolen */ } @@ -4182,22 +4182,22 @@ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject * \sa igraph_bridges */ PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { - igraph_vector_t res; + igraph_vector_int_t res; PyObject *o; - if (igraph_vector_init(&res, 0)) { + if (igraph_vector_int_init(&res, 0)) { igraphmodule_handle_igraph_error(); return NULL; } if (igraph_bridges(&self->g, &res)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } igraph_vector_sort(&res); - o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + o = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return o; } @@ -5066,7 +5066,7 @@ PyObject *igraphmodule_Graph_get_all_shortest_paths(igraphmodule_GraphObject * igraph_vs_destroy(&to); if (weights) { igraph_vector_destroy(weights); free(weights); } - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&res, igraph_vector_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&res, igraph_vector_int_destroy); j = igraph_vector_ptr_size(&res); list = PyList_New(j); @@ -5077,9 +5077,8 @@ PyObject *igraphmodule_Graph_get_all_shortest_paths(igraphmodule_GraphObject * for (i = 0; i < j; i++) { item = - igraphmodule_vector_t_to_PyList((igraph_vector_t *) - igraph_vector_ptr_e(&res, i), - IGRAPHMODULE_TYPE_INT); + igraphmodule_vector_int_t_to_PyList( + (igraph_vector_int_t *)igraph_vector_ptr_e(&res, i)); if (!item) { Py_DECREF(list); igraph_vector_ptr_destroy_all(&res); @@ -5269,7 +5268,7 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, igraph_vs_destroy(&vs); if (!return_single) - result = igraphmodule_vector_ptr_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); + result = igraphmodule_vector_int_ptr_t_to_PyList(&res); else result = igraphmodule_vector_int_t_to_PyList((igraph_vector_int_t*)VECTOR(res)[0]); @@ -6192,7 +6191,7 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * PyObject *list, *mode_o=Py_None; PyObject *warnings_o=Py_True; igraph_neimode_t mode = IGRAPH_OUT; - igraph_vector_t result; + igraph_vector_int_t result; igraph_warning_handler_t* old_handler = 0; int retval; @@ -6200,7 +6199,7 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_init(&result, 0)) + if (igraph_vector_int_init(&result, 0)) return igraphmodule_handle_igraph_error(); if (!PyObject_IsTrue(warnings_o)) { @@ -6217,12 +6216,12 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * if (retval) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } - list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + list = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return list; } @@ -6737,7 +6736,7 @@ PyObject *igraphmodule_Graph_layout_star(igraphmodule_GraphObject* self, igraph_matrix_t m; PyObject *result, *order_o = Py_None, *center_o = Py_None; igraph_integer_t center = 0; - igraph_vector_t* order = 0; + igraph_vector_int_t* order = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, ¢er_o, &order_o)) @@ -6752,13 +6751,13 @@ PyObject *igraphmodule_Graph_layout_star(igraphmodule_GraphObject* self, return NULL; if (order_o != Py_None) { - order = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); + order = (igraph_vector_int_t*)calloc(1, sizeof(igraph_vector_int_t)); if (!order) { igraph_matrix_destroy(&m); PyErr_NoMemory(); return NULL; } - if (igraphmodule_PyObject_to_vector_t(order_o, order, 1)) { + if (igraphmodule_PyObject_to_vector_int_t(order_o, order)) { igraph_matrix_destroy(&m); free(order); igraphmodule_handle_igraph_error(); @@ -6768,7 +6767,7 @@ PyObject *igraphmodule_Graph_layout_star(igraphmodule_GraphObject* self, if (igraph_layout_star(&self->g, &m, center, order)) { if (order) { - igraph_vector_destroy(order); free(order); + igraph_vector_int_destroy(order); free(order); } igraph_matrix_destroy(&m); igraphmodule_handle_igraph_error(); @@ -7407,8 +7406,8 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford(igraphmodule_GraphObject { static char *kwlist[] = { "mode", "root", "rootlevel", NULL }; igraph_matrix_t m; - igraph_vector_t roots, *roots_p = 0; - igraph_vector_t rootlevels, *rootlevels_p = 0; + igraph_vector_int_t roots, *roots_p = 0; + igraph_vector_int_t rootlevels, *rootlevels_p = 0; PyObject *roots_o=Py_None, *rootlevels_o=Py_None, *mode_o=Py_None; igraph_neimode_t mode = IGRAPH_OUT; PyObject *result; @@ -7422,32 +7421,32 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford(igraphmodule_GraphObject if (roots_o != Py_None) { roots_p = &roots; - if (igraphmodule_PyObject_to_vector_t(roots_o, roots_p, 1)) return 0; + if (igraphmodule_PyObject_to_vector_int_t(roots_o, roots_p)) return 0; } if (rootlevels_o != Py_None) { rootlevels_p = &rootlevels; - if (igraphmodule_PyObject_to_vector_t(rootlevels_o, rootlevels_p, 1)) { - if (roots_p) igraph_vector_destroy(roots_p); + if (igraphmodule_PyObject_to_vector_int_t(rootlevels_o, rootlevels_p)) { + if (roots_p) igraph_vector_int_destroy(roots_p); return 0; } } if (igraph_matrix_init(&m, 1, 1)) { - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); igraphmodule_handle_igraph_error(); return NULL; } if (igraph_layout_reingold_tilford(&self->g, &m, mode, roots_p, rootlevels_p)) { igraph_matrix_destroy(&m); - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); igraphmodule_handle_igraph_error(); return NULL; } - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); result = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); igraph_matrix_destroy(&m); @@ -8723,7 +8722,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, PyObject *sho1=Py_None, *sho2=Py_None; PyObject *color1_o=Py_None, *color2_o=Py_None; igraphmodule_GraphObject *other; - igraph_vector_t mapping_12, mapping_21, *map12=0, *map21=0; + igraph_vector_int_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_bliss_sh_t sh1=IGRAPH_BLISS_FL, sh2=IGRAPH_BLISS_FL; igraph_vector_int_t *color1=0, *color2=0; int retval; @@ -8752,11 +8751,11 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, if (o == Py_None) other = self; else other = (igraphmodule_GraphObject *) o; if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); + igraph_vector_int_init(&mapping_12, 0); map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); + igraph_vector_int_init(&mapping_21, 0); map21 = &mapping_21; } @@ -8779,17 +8778,17 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, iso = result ? Py_True : Py_False; Py_INCREF(iso); if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); + m1 = igraphmodule_vector_int_t_to_PyList(map12); + igraph_vector_int_destroy(map12); if (!m1) { Py_DECREF(iso); - if (map21) igraph_vector_destroy(map21); + if (map21) igraph_vector_int_destroy(map21); return NULL; } } else { m1 = Py_None; Py_INCREF(m1); } if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); + m2 = igraphmodule_vector_int_t_to_PyList(map21); + igraph_vector_int_destroy(map21); if (!m2) { Py_DECREF(iso); Py_DECREF(m1); return NULL; @@ -8809,7 +8808,7 @@ typedef struct { } igraphmodule_i_Graph_isomorphic_vf2_callback_data_t; igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_callback_fn( - const igraph_vector_t *map12, const igraph_vector_t *map21, + const igraph_vector_int_t *map12, const igraph_vector_int_t *map21, void* extra) { igraphmodule_i_Graph_isomorphic_vf2_callback_data_t* data = (igraphmodule_i_Graph_isomorphic_vf2_callback_data_t*)extra; @@ -8817,14 +8816,14 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_callback_fn( PyObject *map12_o, *map21_o; PyObject *result; - map12_o = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); + map12_o = igraphmodule_vector_int_t_to_PyList(map12); if (map12_o == NULL) { /* Error in conversion, return 0 to stop the search */ PyErr_WriteUnraisable(data->callback_fn); return 0; } - map21_o = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); + map21_o = igraphmodule_vector_int_t_to_PyList(map21); if (map21_o == NULL) { /* Error in conversion, return 0 to stop the search */ PyErr_WriteUnraisable(data->callback_fn); @@ -8916,8 +8915,7 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, PyObject *callback_fn=Py_None; PyObject *node_compat_fn=Py_None, *edge_compat_fn=Py_None; igraphmodule_GraphObject *other; - igraph_vector_t mapping_12, mapping_21; - igraph_vector_t *map12=0, *map21=0; + igraph_vector_int_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_vector_int_t *color1=0, *color2=0; igraph_vector_int_t *edge_color1=0, *edge_color2=0; igraphmodule_i_Graph_isomorphic_vf2_callback_data_t callback_data; @@ -8977,11 +8975,11 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, } if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); + igraph_vector_int_init(&mapping_12, 0); map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); + igraph_vector_int_init(&mapping_21, 0); map21 = &mapping_21; } @@ -9022,16 +9020,16 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, } else { PyObject *m1, *m2; if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); + m1 = igraphmodule_vector_int_t_to_PyList(map12); + igraph_vector_int_destroy(map12); if (!m1) { - if (map21) igraph_vector_destroy(map21); + if (map21) igraph_vector_int_destroy(map21); return NULL; } } else { m1 = Py_None; Py_INCREF(m1); } if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); + m2 = igraphmodule_vector_int_t_to_PyList(map21); + igraph_vector_int_destroy(map21); if (!m2) { Py_DECREF(m1); return NULL; @@ -9232,9 +9230,9 @@ PyObject *igraphmodule_Graph_get_isomorphisms_vf2(igraphmodule_GraphObject *self if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } if (edge_color2) { igraph_vector_int_destroy(edge_color2); free(edge_color2); } - res = igraphmodule_vector_ptr_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); + res = igraphmodule_vector_int_ptr_t_to_PyList(&result); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&result, igraph_vector_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&result, igraph_vector_int_destroy); igraph_vector_ptr_destroy_all(&result); return res; @@ -9585,7 +9583,7 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, igraphmodule_GraphObject *other; igraph_vector_ptr_t domains; igraph_vector_ptr_t* p_domains = 0; - igraph_vector_t mapping, *map=0; + igraph_vector_int_t mapping, *map=0; static char *kwlist[] = { "pattern", "domains", "induced", "time_limit", "return_mapping", NULL }; @@ -9598,14 +9596,14 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, other=(igraphmodule_GraphObject*)o; if (domains_o != Py_None) { - if (igraphmodule_PyObject_to_vector_ptr_t(domains_o, &domains, 1)) + if (igraphmodule_PyObject_to_vector_int_ptr_t(domains_o, &domains)) return NULL; p_domains = &domains; } if (PyObject_IsTrue(return_mapping)) { - if (igraph_vector_init(&mapping, 0)) { + if (igraph_vector_int_init(&mapping, 0)) { if (p_domains) igraph_vector_ptr_destroy_all(p_domains); igraphmodule_handle_igraph_error(); @@ -9630,8 +9628,8 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, Py_RETURN_TRUE; Py_RETURN_FALSE; } else { - PyObject *m = igraphmodule_vector_t_to_PyList(map, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map); + PyObject *m = igraphmodule_vector_int_t_to_PyList(map); + igraph_vector_int_destroy(map); if (!m) return NULL; return Py_BuildValue("ON", result ? Py_True : Py_False, m); @@ -9663,7 +9661,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_lad( other=(igraphmodule_GraphObject*)o; if (domains_o != Py_None) { - if (igraphmodule_PyObject_to_vector_ptr_t(domains_o, &domains, 1)) + if (igraphmodule_PyObject_to_vector_int_ptr_t(domains_o, &domains)) return NULL; p_domains = &domains; @@ -9688,7 +9686,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_lad( if (p_domains) igraph_vector_ptr_destroy_all(p_domains); - result = igraphmodule_vector_ptr_t_to_PyList(&mappings, IGRAPHMODULE_TYPE_INT); + result = igraphmodule_vector_int_ptr_t_to_PyList(&mappings); igraph_vector_ptr_destroy_all(&mappings); return result; @@ -9946,22 +9944,23 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, long vid; PyObject *l1, *l2, *l3, *result, *mode_o=Py_None; igraph_neimode_t mode = IGRAPH_OUT; - igraph_vector_t vids; - igraph_vector_t layers; - igraph_vector_t parents; + igraph_vector_int_t vids; + igraph_vector_int_t layers; + igraph_vector_int_t parents; if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O", kwlist, &vid, &mode_o)) return NULL; if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_init(&vids, igraph_vcount(&self->g))) + if (igraph_vector_int_init(&vids, igraph_vcount(&self->g))) return igraphmodule_handle_igraph_error(); - if (igraph_vector_init(&layers, igraph_vcount(&self->g))) { - igraph_vector_destroy(&vids); + if (igraph_vector_int_init(&layers, igraph_vcount(&self->g))) { + igraph_vector_int_destroy(&vids); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&parents, igraph_vcount(&self->g))) { - igraph_vector_destroy(&vids); igraph_vector_destroy(&parents); + if (igraph_vector_int_init(&parents, igraph_vcount(&self->g))) { + igraph_vector_int_destroy(&vids); + igraph_vector_int_destroy(&parents); return igraphmodule_handle_igraph_error(); } if (igraph_bfs_simple @@ -9969,9 +9968,9 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, igraphmodule_handle_igraph_error(); return NULL; } - l1 = igraphmodule_vector_t_to_PyList(&vids, IGRAPHMODULE_TYPE_INT); - l2 = igraphmodule_vector_t_to_PyList(&layers, IGRAPHMODULE_TYPE_INT); - l3 = igraphmodule_vector_t_to_PyList(&parents, IGRAPHMODULE_TYPE_INT); + l1 = igraphmodule_vector_int_t_to_PyList(&vids); + l2 = igraphmodule_vector_int_t_to_PyList(&layers); + l3 = igraphmodule_vector_int_t_to_PyList(&parents); if (l1 && l2 && l3) { result = Py_BuildValue("NNN", l1, l2, l3); /* references stolen */ } else { @@ -9980,9 +9979,9 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, if (l3) { Py_DECREF(l3); } result = NULL; } - igraph_vector_destroy(&vids); - igraph_vector_destroy(&layers); - igraph_vector_destroy(&parents); + igraph_vector_int_destroy(&vids); + igraph_vector_int_destroy(&layers); + igraph_vector_int_destroy(&parents); return result; } @@ -10096,7 +10095,7 @@ PyObject *igraphmodule_Graph_dominator(igraphmodule_GraphObject * self, PyObject *list = Py_None; PyObject *mode_o = Py_None; long int root = -1; - igraph_vector_t dom; + igraph_vector_int_t dom; igraph_neimode_t mode = IGRAPH_OUT; int res ; @@ -10111,16 +10110,18 @@ PyObject *igraphmodule_Graph_dominator(igraphmodule_GraphObject * self, mode = IGRAPH_OUT; } - if (igraph_vector_init(&dom, 0)) { + if (igraph_vector_int_init(&dom, 0)) { return NULL; } res = igraph_dominator_tree(&self->g, root, &dom, NULL, NULL, mode); if(res) { - igraph_vector_destroy(&dom); + igraph_vector_int_destroy(&dom); return NULL; } - list = igraphmodule_vector_t_to_PyList(&dom, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&dom); + /* The igraph API uses -2 for vertices that are not reachable from the root, + * but the Python API seems to be using nan judging from the unit tests */ + list = igraphmodule_vector_int_t_to_PyList_with_nan(&dom, -2); + igraph_vector_int_destroy(&dom); return list; } @@ -10286,17 +10287,17 @@ PyObject *igraphmodule_Graph_all_st_cuts(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); } - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&cuts, igraph_vector_destroy); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&partition1s, igraph_vector_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&cuts, igraph_vector_int_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&partition1s, igraph_vector_int_destroy); - cuts_o = igraphmodule_vector_ptr_t_to_PyList(&cuts, IGRAPHMODULE_TYPE_INT); + cuts_o = igraphmodule_vector_int_ptr_t_to_PyList(&cuts); igraph_vector_ptr_destroy_all(&cuts); if (cuts_o == NULL) { igraph_vector_ptr_destroy_all(&partition1s); return NULL; } - partition1s_o = igraphmodule_vector_ptr_t_to_PyList(&partition1s, IGRAPHMODULE_TYPE_INT); + partition1s_o = igraphmodule_vector_int_ptr_t_to_PyList(&partition1s); igraph_vector_ptr_destroy_all(&partition1s); if (partition1s_o == NULL) return NULL; @@ -10353,17 +10354,17 @@ PyObject *igraphmodule_Graph_all_st_mincuts(igraphmodule_GraphObject * self, igraph_vector_destroy(&capacity_vector); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&cuts, igraph_vector_destroy); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&partition1s, igraph_vector_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&cuts, igraph_vector_int_destroy); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&partition1s, igraph_vector_int_destroy); - cuts_o = igraphmodule_vector_ptr_t_to_PyList(&cuts, IGRAPHMODULE_TYPE_INT); + cuts_o = igraphmodule_vector_int_ptr_t_to_PyList(&cuts); igraph_vector_ptr_destroy_all(&cuts); if (cuts_o == NULL) { igraph_vector_ptr_destroy_all(&partition1s); return NULL; } - partition1s_o = igraphmodule_vector_ptr_t_to_PyList(&partition1s, IGRAPHMODULE_TYPE_INT); + partition1s_o = igraphmodule_vector_int_ptr_t_to_PyList(&partition1s); igraph_vector_ptr_destroy_all(&partition1s); if (partition1s_o == NULL) return NULL; @@ -10837,8 +10838,8 @@ PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, return NULL; } - blocks_o = igraphmodule_vector_ptr_t_to_PyList(&blocks, IGRAPHMODULE_TYPE_INT); - IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&blocks, igraph_vector_destroy); + blocks_o = igraphmodule_vector_int_ptr_t_to_PyList(&blocks); + IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&blocks, igraph_vector_int_destroy); igraph_vector_ptr_destroy_all(&blocks); if (blocks_o == NULL) { igraph_vector_int_destroy(&parents); @@ -11280,7 +11281,7 @@ PyObject *igraphmodule_Graph_coreness(igraphmodule_GraphObject * self, { static char *kwlist[] = { "mode", NULL }; igraph_neimode_t mode = IGRAPH_ALL; - igraph_vector_t result; + igraph_vector_int_t result; PyObject *o, *mode_o = Py_None; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) @@ -11288,16 +11289,16 @@ PyObject *igraphmodule_Graph_coreness(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_init(&result, igraph_vcount(&self->g))) + if (igraph_vector_int_init(&result, igraph_vcount(&self->g))) return igraphmodule_handle_igraph_error(); if (igraph_coreness(&self->g, &result, mode)) { - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return igraphmodule_handle_igraph_error(); } - o = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + o = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return o; } @@ -11312,7 +11313,7 @@ PyObject *igraphmodule_Graph_coreness(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"membership", "weights", "resolution", "directed", 0}; - igraph_vector_t membership; + igraph_vector_int_t membership; igraph_vector_t *weights=0; double resolution = 1; igraph_real_t modularity; @@ -11322,23 +11323,23 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OdO", kwlist, &mvec, &wvec, &resolution, &directed)) return NULL; - if (igraphmodule_PyObject_to_vector_t(mvec, &membership, 1)) + if (igraphmodule_PyObject_to_vector_int_t(mvec, &membership)) return NULL; if (igraphmodule_attrib_to_vector_t(wvec, self, &weights, ATTRIBUTE_TYPE_EDGE)){ - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); return NULL; } if (igraph_modularity(&self->g, &membership, weights, resolution, PyObject_IsTrue(directed), &modularity)) { - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } - igraph_vector_destroy(&membership); + igraph_vector_int_destroy(&membership); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -11354,7 +11355,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject PyObject *directed = Py_True; PyObject *weights_o = Py_None; PyObject *res, *qs, *ms; - igraph_matrix_t merges; + igraph_matrix_int_t merges; igraph_vector_t q; igraph_vector_t *weights = 0; @@ -11364,7 +11365,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; - if (igraph_matrix_init(&merges, 0, 0)) { + if (igraph_matrix_int_init(&merges, 0, 0)) { if (weights != 0) { igraph_vector_destroy(weights); free(weights); } @@ -11372,7 +11373,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject } if (igraph_vector_init(&q, 0)) { - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); if (weights != 0) { igraph_vector_destroy(weights); free(weights); } @@ -11392,7 +11393,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject if (weights != 0) { igraph_vector_destroy(weights); free(weights); } - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); igraph_vector_destroy(&q); return NULL; } @@ -11407,7 +11408,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject qs=igraphmodule_vector_t_to_PyList(&q, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&q); if (!qs) { - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return NULL; } } else { @@ -11415,8 +11416,8 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject Py_INCREF(qs); } - ms=igraphmodule_matrix_t_to_PyList(&merges, IGRAPHMODULE_TYPE_INT); - igraph_matrix_destroy(&merges); + ms=igraphmodule_matrix_int_t_to_PyList(&merges); + igraph_matrix_int_destroy(&merges); if (ms == NULL) { Py_DECREF(qs); @@ -11508,7 +11509,7 @@ PyObject *igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject * sel { static char *kwlist[] = { "weights", NULL }; PyObject *ms, *qs, *res, *weights = Py_None; - igraph_matrix_t merges; + igraph_matrix_int_t merges; igraph_vector_t q, *ws=0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &weights)) { @@ -11518,14 +11519,14 @@ PyObject *igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject * sel if (igraphmodule_attrib_to_vector_t(weights, self, &ws, ATTRIBUTE_TYPE_EDGE)) return NULL; - igraph_matrix_init(&merges, 0, 0); + igraph_matrix_int_init(&merges, 0, 0); igraph_vector_init(&q, 0); if (igraph_community_fastgreedy(&self->g, ws, &merges, &q, 0)) { if (ws) { igraph_vector_destroy(ws); free(ws); } igraph_vector_destroy(&q); - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return igraphmodule_handle_igraph_error(); } if (ws) { @@ -11539,7 +11540,7 @@ PyObject *igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject * sel return NULL; } - ms=igraphmodule_matrix_t_to_PyList(&merges, IGRAPHMODULE_TYPE_INT); + ms=igraphmodule_matrix_int_t_to_PyList(&merges); igraph_matrix_destroy(&merges); if (ms == NULL) { @@ -11638,8 +11639,8 @@ PyObject *igraphmodule_Graph_community_label_propagation( static char *kwlist[] = { "weights", "initial", "fixed", NULL }; PyObject *weights_o = Py_None, *initial_o = Py_None, *fixed_o = Py_None; PyObject *result; - igraph_vector_int_t membership; - igraph_vector_t *ws = 0, *initial = 0; + igraph_vector_int_t membership, *initial = 0; + igraph_vector_t *ws = 0; igraph_vector_bool_t fixed; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &weights_o, &initial_o, &fixed_o)) { @@ -11656,7 +11657,7 @@ PyObject *igraphmodule_Graph_community_label_propagation( return NULL; } - if (igraphmodule_attrib_to_vector_t(initial_o, self, &initial, ATTRIBUTE_TYPE_VERTEX)){ + if (igraphmodule_attrib_to_vector_int_t(initial_o, self, &initial, ATTRIBUTE_TYPE_VERTEX)){ if (fixed_o != Py_None) igraph_vector_bool_destroy(&fixed); if (ws) { igraph_vector_destroy(ws); free(ws); } return NULL; @@ -11667,14 +11668,14 @@ PyObject *igraphmodule_Graph_community_label_propagation( ws, initial, (fixed_o != Py_None ? &fixed : 0), 0)) { if (fixed_o != Py_None) igraph_vector_bool_destroy(&fixed); if (ws) { igraph_vector_destroy(ws); free(ws); } - if (initial) { igraph_vector_destroy(initial); free(initial); } + if (initial) { igraph_vector_int_destroy(initial); free(initial); } igraph_vector_int_destroy(&membership); return igraphmodule_handle_igraph_error(); } if (fixed_o != Py_None) igraph_vector_bool_destroy(&fixed); if (ws) { igraph_vector_destroy(ws); free(ws); } - if (initial) { igraph_vector_destroy(initial); free(initial); } + if (initial) { igraph_vector_int_destroy(initial); free(initial); } result=igraphmodule_vector_int_t_to_PyList(&membership); igraph_vector_int_destroy(&membership); diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index e748e7a39..7d8db55bb 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -153,10 +153,10 @@ PyObject *igraphmodule__union(PyObject *self, for (i = 0; i < no_of_graphs; i++) { long int j; long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); - igraph_vector_t *map = VECTOR(edgemaps)[i]; + igraph_vector_int_t *map = VECTOR(edgemaps)[i]; PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); for (j = 0; j < no_of_edges; j++) { - PyObject *dest = PyLong_FromLong(VECTOR(*map)[j]); + PyObject *dest = PyLong_FromLong((long)VECTOR(*map)[j]); PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); } PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); @@ -263,10 +263,10 @@ PyObject *igraphmodule__intersection(PyObject *self, for (i = 0; i < no_of_graphs; i++) { long int j; long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); - igraph_vector_t *map = VECTOR(edgemaps)[i]; + igraph_vector_int_t *map = VECTOR(edgemaps)[i]; PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); for (j = 0; j < no_of_edges; j++) { - PyObject *dest = PyLong_FromLong(VECTOR(*map)[j]); + PyObject *dest = PyLong_FromLong((long)VECTOR(*map)[j]); PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); } PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index d5042ec83..d7416db9e 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -411,9 +411,11 @@ def suite(): isomorphism_suite = unittest.makeSuite(IsomorphismTests) subisomorphism_suite = unittest.makeSuite(SubisomorphismTests) permutation_suite = unittest.makeSuite(PermutationTests) - return unittest.TestSuite( - [isomorphism_suite, subisomorphism_suite, permutation_suite] - ) + return unittest.TestSuite([ + isomorphism_suite, + subisomorphism_suite, + permutation_suite, + ]) def test(): diff --git a/tests/test_structural.py b/tests/test_structural.py index 9ea13d990..edec2f8f4 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -498,11 +498,11 @@ def testNeighborhoodSize(self): class MiscTests(unittest.TestCase): def testBridges(self): g = Graph(5, [(0, 1), (1, 2), (2, 0), (0, 3), (3, 4)]) - self.assertTrue(g.bridges() == [3, 4]) + self.assertEqual(g.bridges(), [3, 4]) g = Graph(7, [(0, 1), (1, 2), (2, 0), (1, 6), (1, 3), (1, 4), (3, 5), (4, 5)]) - self.assertTrue(g.bridges() == [3]) + self.assertEqual(g.bridges(), [3]) g = Graph(3, [(0, 1), (1, 2), (2, 3)]) - self.assertTrue(g.bridges() == [0, 1, 2]) + self.assertEqual(g.bridges(), [0, 1, 2]) def testConstraint(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 12adf1aa1..89c9e8896 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -4,7 +4,10 @@ from igraph import * -from .utils import is_pypy +try: + from .utils import is_pypy +except ImportError: + from utils import is_pypy try: import numpy as np From 7c9f04aee529e744eeb539d57af924ecb493c435 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 12 Aug 2021 05:46:43 +1000 Subject: [PATCH 0555/1892] Compiler warnings, except one callback --- src/_igraph/convert.c | 29 ++++- src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 265 +++++++++++++++++++------------------- 3 files changed, 162 insertions(+), 133 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 397794ede..965a8f532 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1384,11 +1384,38 @@ PyObject* igraphmodule_vector_int_t_to_PyList_with_nan(const igraph_vector_int_t /** * \ingroup python_interface_conversion - * \brief Converts an igraph \c igraph_vector_int_t to a Python integer tuple + * \brief Converts an igraph \c igraph_vector_t to a Python integer tuple * * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer tuple as a \c PyObject*, or \c NULL if an error occurred */ +PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v) { + PyObject* tuple; + Py_ssize_t n, i; + + n=igraph_vector_size(v); + if (n<0) return igraphmodule_handle_igraph_error(); + + tuple=PyTuple_New(n); + for (i=0; ig, &girth, &vids)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&vids); + igraph_vector_int_destroy(&vids); return NULL; } if (PyObject_IsTrue(sc)) { PyObject* o; - o=igraphmodule_vector_t_to_PyList(&vids, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&vids); + o=igraphmodule_vector_int_t_to_PyList(&vids); + igraph_vector_int_destroy(&vids); return o; } return PyLong_FromLong((long)girth); @@ -2024,7 +2024,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, igraph_t g; long n, m = 1; float power = 1.0f, zero_appeal = 1.0f; - igraph_vector_t outseq; + igraph_vector_int_t outseq; igraph_t *start_from = 0; igraph_barabasi_algorithm_t algo = IGRAPH_BARABASI_PSUMTREE; PyObject *m_obj = 0, *outpref = Py_False, *directed = Py_False; @@ -2054,15 +2054,15 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, } if (m_obj == 0) { - igraph_vector_init(&outseq, 0); + igraph_vector_int_init(&outseq, 0); m = 1; } else if (m_obj != 0) { /* let's check whether we have a constant out-degree or a list */ if (PyLong_Check(m_obj)) { m = PyLong_AsLong(m_obj); - igraph_vector_init(&outseq, 0); + igraph_vector_int_init(&outseq, 0); } else if (PyList_Check(m_obj)) { - if (igraphmodule_PyObject_to_vector_t(m_obj, &outseq, 1)) { + if (igraphmodule_PyObject_to_vector_int_t(m_obj, &outseq)) { /* something bad happened during conversion */ return NULL; } @@ -2080,11 +2080,11 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, PyObject_IsTrue(directed), algo, start_from)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); return NULL; } - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -2102,7 +2102,7 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, igraphmodule_GraphObject *self; igraph_t g; igraph_vector_bool_t types; - igraph_vector_t edges; + igraph_vector_int_t edges; igraph_bool_t edges_owned = 0; PyObject *types_o, *edges_o, *directed = Py_False; @@ -2123,14 +2123,14 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, if (igraph_create_bipartite(&g, &types, &edges, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } igraph_vector_bool_destroy(&types); return NULL; } if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } igraph_vector_bool_destroy(&types); @@ -2177,7 +2177,7 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - igraph_vector_t outseq, inseq; + igraph_vector_int_t outseq, inseq; igraph_degseq_t meth = IGRAPH_DEGSEQ_SIMPLE; igraph_bool_t has_inseq = 0; PyObject *outdeg = NULL, *indeg = NULL, *method = NULL; @@ -2191,10 +2191,10 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, return NULL; if (igraphmodule_PyObject_to_degseq_t(method, &meth)) return NULL; - if (igraphmodule_PyObject_to_vector_t(outdeg, &outseq, 1)) return NULL; + if (igraphmodule_PyObject_to_vector_int_t(outdeg, &outseq)) return NULL; if (indeg) { - if (igraphmodule_PyObject_to_vector_t(indeg, &inseq, 1)) { - igraph_vector_destroy(&outseq); + if (igraphmodule_PyObject_to_vector_int_t(indeg, &inseq)) { + igraph_vector_int_destroy(&outseq); return NULL; } has_inseq=1; @@ -2202,15 +2202,15 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, if (igraph_degree_sequence_game(&g, &outseq, has_inseq ? &inseq : 0, meth)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); if (has_inseq) - igraph_vector_destroy(&inseq); + igraph_vector_int_destroy(&inseq); return NULL; } - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); if (has_inseq) - igraph_vector_destroy(&inseq); + igraph_vector_int_destroy(&inseq); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -3173,7 +3173,7 @@ PyObject *igraphmodule_Graph_Recent_Degree(PyTypeObject * type, igraph_t g; long n, m = 0, window = 0; float power = 0.0f, zero_appeal = 0.0f; - igraph_vector_t outseq; + igraph_vector_int_t outseq; PyObject *m_obj, *outpref = Py_False, *directed = Py_False; char *kwlist[] = @@ -3193,10 +3193,10 @@ NULL }; // let's check whether we have a constant out-degree or a list if (PyLong_Check(m_obj)) { m = PyLong_AsLong(m_obj); - igraph_vector_init(&outseq, 0); + igraph_vector_int_init(&outseq, 0); } else if (PyList_Check(m_obj)) { - if (igraphmodule_PyObject_to_vector_t(m_obj, &outseq, 1)) { + if (igraphmodule_PyObject_to_vector_int_t(m_obj, &outseq)) { // something bad happened during conversion return NULL; } @@ -3210,11 +3210,11 @@ NULL }; (igraph_real_t) zero_appeal, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); return NULL; } - igraph_vector_destroy(&outseq); + igraph_vector_int_destroy(&outseq); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -3691,18 +3691,18 @@ PyObject *igraphmodule_Graph_assortativity_nominal(igraphmodule_GraphObject *sel PyObject *types_o = Py_None, *directed = Py_True; igraph_real_t res; int ret; - igraph_vector_t *types = 0; + igraph_vector_int_t *types = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &types_o, &directed)) return NULL; - if (igraphmodule_attrib_to_vector_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) + if (igraphmodule_attrib_to_vector_int_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) return NULL; ret = igraph_assortativity_nominal(&self->g, types, &res, PyObject_IsTrue(directed)); if (types) { - igraph_vector_destroy(types); free(types); + igraph_vector_int_destroy(types); free(types); } if (ret) { @@ -4195,7 +4195,7 @@ PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { return NULL; } - igraph_vector_sort(&res); + igraph_vector_int_sort(&res); o = igraphmodule_vector_int_t_to_PyList(&res); igraph_vector_int_destroy(&res); @@ -4850,7 +4850,7 @@ PyObject *igraphmodule_Graph_feedback_arc_set( igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "weights", "method", NULL }; igraph_vector_t* weights = 0; - igraph_vector_t result; + igraph_vector_int_t result; igraph_fas_algorithm_t algo = IGRAPH_FAS_APPROX_EADES; PyObject *weights_o = Py_None, *result_o = NULL, *algo_o = NULL; @@ -4864,20 +4864,20 @@ PyObject *igraphmodule_Graph_feedback_arc_set( ATTRIBUTE_TYPE_EDGE)) return NULL; - if (igraph_vector_init(&result, 0)) { + if (igraph_vector_int_init(&result, 0)) { if (weights) { igraph_vector_destroy(weights); free(weights); } } if (igraph_feedback_arc_set(&self->g, &result, weights, algo)) { if (weights) { igraph_vector_destroy(weights); free(weights); } - igraph_vector_destroy(&result); + igraph_vector_int_destroy(&result); return NULL; } if (weights) { igraph_vector_destroy(weights); free(weights); } - result_o = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&result); + result_o = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); return result_o; } @@ -4893,7 +4893,8 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * PyObject * kwds) { static char *kwlist[] = { "v", "to", "weights", "mode", "output", NULL }; - igraph_vector_t *res, *weights=0; + igraph_vector_t *weights=0; + igraph_vector_int_t *res; igraph_neimode_t mode = IGRAPH_OUT; long int i, j; igraph_integer_t from, no_of_target_nodes; @@ -4953,7 +4954,6 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * return NULL; } - // FIXME: is this alright? res = (igraph_vector_int_t *) calloc(no_of_target_nodes, sizeof(igraph_vector_int_t)); if (!res) { PyErr_SetString(PyExc_MemoryError, ""); @@ -5123,7 +5123,7 @@ PyObject *igraphmodule_Graph_get_all_simple_paths(igraphmodule_GraphObject * if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (PyLong_AsInt(cutoff_o, &cutoff)) + if (igraphmodule_PyObject_to_integer_t(cutoff_o, &cutoff)) return NULL; if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) @@ -5708,15 +5708,15 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, igraph_matrix_destroy(&res); } else { /* Case #2: vertex pairs or edges, returning list */ - igraph_vector_t edges; + igraph_vector_int_t edges; igraph_vector_t res; igraph_bool_t edges_owned; if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0, &edges_owned)) return NULL; - if (igraph_vector_init(&res, igraph_vector_size(&edges) / 2)) { - igraph_vector_destroy(&edges); + if (igraph_vector_init(&res, igraph_vector_int_size(&edges) / 2)) { + igraph_vector_int_destroy(&edges); igraphmodule_handle_igraph_error(); return NULL; } @@ -5725,14 +5725,14 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, PyObject_IsTrue(loops))) { igraph_vector_destroy(&res); if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } igraphmodule_handle_igraph_error(); return NULL; } if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); @@ -5794,16 +5794,16 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, igraph_matrix_destroy(&res); } else { /* Case #2: vertex pairs or edges, returning list */ - igraph_vector_t edges; + igraph_vector_int_t edges; igraph_vector_t res; igraph_bool_t edges_owned; if (igraphmodule_PyObject_to_edgelist(pairs_o, &edges, 0, &edges_owned)) return NULL; - if (igraph_vector_init(&res, igraph_vector_size(&edges) / 2)) { + if (igraph_vector_init(&res, igraph_vector_int_size(&edges) / 2)) { if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } igraphmodule_handle_igraph_error(); return NULL; @@ -5813,14 +5813,14 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, PyObject_IsTrue(loops))) { igraph_vector_destroy(&res); if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } igraphmodule_handle_igraph_error(); return NULL; } if (edges_owned) { - igraph_vector_destroy(&edges); + igraph_vector_int_destroy(&edges); } list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); @@ -5883,32 +5883,32 @@ PyObject *igraphmodule_Graph_spanning_tree(igraphmodule_GraphObject * self, { static char *kwlist[] = { "weights", NULL }; igraph_vector_t* ws = 0; - igraph_vector_t res; + igraph_vector_int_t res; PyObject *weights_o = Py_None, *result = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &weights_o)) return NULL; - if (igraph_vector_init(&res, 0)) { + if (igraph_vector_int_init(&res, 0)) { igraphmodule_handle_igraph_error(); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &ws, ATTRIBUTE_TYPE_EDGE)) { - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } if (igraph_minimum_spanning_tree(&self->g, &res, ws)) { if (ws != 0) { igraph_vector_destroy(ws); free(ws); } - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); igraphmodule_handle_igraph_error(); return NULL; } if (ws != 0) { igraph_vector_destroy(ws); free(ws); } - result = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + result = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return result; } @@ -5953,7 +5953,7 @@ PyObject *igraphmodule_Graph_subcomponent(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "v", "mode", NULL }; - igraph_vector_t res; + igraph_vector_int_t res; igraph_neimode_t mode = IGRAPH_ALL; igraph_integer_t from; PyObject *list = NULL, *mode_o = Py_None, *from_o = Py_None; @@ -5967,15 +5967,15 @@ PyObject *igraphmodule_Graph_subcomponent(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) return NULL; - igraph_vector_init(&res, 0); + igraph_vector_int_init(&res, 0); if (igraph_subcomponent(&self->g, &res, from, mode)) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&res); + igraph_vector_int_destroy(&res); return NULL; } - list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&res); + list = igraphmodule_vector_int_t_to_PyList(&res); + igraph_vector_int_destroy(&res); return list; } @@ -6527,17 +6527,19 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s } } else { /* samples given in advance */ - igraph_vector_t samp; - if (igraphmodule_PyObject_to_vector_t(sample, &samp, 1)) { + igraph_vector_int_t samp; + if (igraphmodule_PyObject_to_vector_int_t(sample, &samp)) { igraph_vector_destroy(&cut_prob); return NULL; } if (igraph_motifs_randesu_estimate(&self->g, &result, (igraph_integer_t) size, &cut_prob, 0, &samp)) { igraphmodule_handle_igraph_error(); + igraph_vector_int_destroy(&samp); igraph_vector_destroy(&cut_prob); return NULL; } + igraph_vector_int_destroy(&samp); } igraph_vector_destroy(&cut_prob); @@ -6550,20 +6552,20 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s * \sa igraph_triad_census */ PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self) { - igraph_vector_int_t result; + igraph_vector_t result; PyObject *list; - if (igraph_vector_int_init(&result, 16)) { + if (igraph_vector_init(&result, 16)) { return igraphmodule_handle_igraph_error(); } if (igraph_triad_census(&self->g, &result)) { igraphmodule_handle_igraph_error(); - igraph_vector_int_destroy(&result); + igraph_vector_destroy(&result); return NULL; } - list = igraphmodule_vector_int_t_to_PyTuple(&result); - igraph_vector_int_destroy(&result); + list = igraphmodule_vector_t_to_PyTuple(&result); + igraph_vector_destroy(&result); return list; } @@ -7464,8 +7466,8 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford_circular( { static char *kwlist[] = { "mode", "root", "rootlevel", NULL }; igraph_matrix_t m; - igraph_vector_t roots, *roots_p = 0; - igraph_vector_t rootlevels, *rootlevels_p = 0; + igraph_vector_int_t roots, *roots_p = 0; + igraph_vector_int_t rootlevels, *rootlevels_p = 0; PyObject *roots_o=Py_None, *rootlevels_o=Py_None, *mode_o=Py_None; igraph_neimode_t mode = IGRAPH_OUT; PyObject *result; @@ -7478,19 +7480,19 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford_circular( if (roots_o != Py_None) { roots_p = &roots; - if (igraphmodule_PyObject_to_vector_t(roots_o, roots_p, 1)) return 0; + if (igraphmodule_PyObject_to_vector_int_t(roots_o, roots_p)) return 0; } if (rootlevels_o != Py_None) { rootlevels_p = &rootlevels; - if (igraphmodule_PyObject_to_vector_t(rootlevels_o, rootlevels_p, 1)) { - if (roots_p) igraph_vector_destroy(roots_p); + if (igraphmodule_PyObject_to_vector_int_t(rootlevels_o, rootlevels_p)) { + if (roots_p) igraph_vector_int_destroy(roots_p); return 0; } } if (igraph_matrix_init(&m, 1, 1)) { - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); igraphmodule_handle_igraph_error(); return NULL; } @@ -7498,13 +7500,13 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford_circular( if (igraph_layout_reingold_tilford_circular(&self->g, &m, mode, roots_p, rootlevels_p)) { igraph_matrix_destroy(&m); - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); igraphmodule_handle_igraph_error(); return NULL; } - if (roots_p) igraph_vector_destroy(roots_p); - if (rootlevels_p) igraph_vector_destroy(rootlevels_p); + if (roots_p) igraph_vector_int_destroy(roots_p); + if (rootlevels_p) igraph_vector_int_destroy(rootlevels_p); result = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); igraph_matrix_destroy(&m); @@ -7523,8 +7525,9 @@ PyObject *igraphmodule_Graph_layout_sugiyama( "return_extended_graph", NULL }; igraph_matrix_t m; igraph_t extd_graph; - igraph_vector_t extd_to_orig_eids; - igraph_vector_t *weights = 0, *layers = 0; + igraph_vector_int_t extd_to_orig_eids; + igraph_vector_t *weights = 0; + igraph_vector_int_t *layers = 0; double hgap = 1, vgap = 1; long int maxiter = 100; PyObject *layers_o = Py_None, *weights_o = Py_None, *extd_to_orig_eids_o = Py_None; @@ -7536,28 +7539,28 @@ PyObject *igraphmodule_Graph_layout_sugiyama( &layers_o, &weights_o, &hgap, &vgap, &maxiter, &return_extended_graph)) return NULL; - if (igraph_vector_init(&extd_to_orig_eids, 0)) { + if (igraph_vector_int_init(&extd_to_orig_eids, 0)) { igraphmodule_handle_igraph_error(); return NULL; } if (igraph_matrix_init(&m, 1, 1)) { - igraph_vector_destroy(&extd_to_orig_eids); + igraph_vector_int_destroy(&extd_to_orig_eids); igraphmodule_handle_igraph_error(); return NULL; } - if (igraphmodule_attrib_to_vector_t(layers_o, self, &layers, + if (igraphmodule_attrib_to_vector_int_t(layers_o, self, &layers, ATTRIBUTE_TYPE_VERTEX)) { - igraph_vector_destroy(&extd_to_orig_eids); + igraph_vector_int_destroy(&extd_to_orig_eids); igraph_matrix_destroy(&m); return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { - if (layers != 0) { igraph_vector_destroy(layers); free(layers); } - igraph_vector_destroy(&extd_to_orig_eids); + if (layers != 0) { igraph_vector_int_destroy(layers); free(layers); } + igraph_vector_int_destroy(&extd_to_orig_eids); igraph_matrix_destroy(&m); return NULL; } @@ -7566,15 +7569,15 @@ PyObject *igraphmodule_Graph_layout_sugiyama( (PyObject_IsTrue(return_extended_graph) ? &extd_graph : 0), (PyObject_IsTrue(return_extended_graph) ? &extd_to_orig_eids : 0), layers, hgap, vgap, maxiter, weights)) { - if (layers != 0) { igraph_vector_destroy(layers); free(layers); } + if (layers != 0) { igraph_vector_int_destroy(layers); free(layers); } if (weights != 0) { igraph_vector_destroy(weights); free(weights); } - igraph_vector_destroy(&extd_to_orig_eids); + igraph_vector_int_destroy(&extd_to_orig_eids); igraph_matrix_destroy(&m); igraphmodule_handle_igraph_error(); return NULL; } - if (layers != 0) { igraph_vector_destroy(layers); free(layers); } + if (layers != 0) { igraph_vector_int_destroy(layers); free(layers); } if (weights != 0) { igraph_vector_destroy(weights); free(weights); } result = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); @@ -7582,12 +7585,11 @@ PyObject *igraphmodule_Graph_layout_sugiyama( if (PyObject_IsTrue(return_extended_graph)) { CREATE_GRAPH(graph_o, extd_graph); - extd_to_orig_eids_o = igraphmodule_vector_t_to_PyList(&extd_to_orig_eids, - IGRAPHMODULE_TYPE_INT); + extd_to_orig_eids_o = igraphmodule_vector_int_t_to_PyList(&extd_to_orig_eids); result = Py_BuildValue("NNN", result, graph_o, extd_to_orig_eids_o); } - igraph_vector_destroy(&extd_to_orig_eids); + igraph_vector_int_destroy(&extd_to_orig_eids); return (PyObject *) result; } @@ -8598,8 +8600,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( PyObject *color_o = Py_None; PyObject *list; igraph_bliss_sh_t sh = IGRAPH_BLISS_FL; - igraph_vector_t labeling; - igraph_vector_int_t *color = 0; + igraph_vector_int_t labeling, *color = 0; int retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) @@ -8608,7 +8609,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( if (igraphmodule_PyObject_to_bliss_sh_t(sh_o, &sh)) return NULL; - if (igraph_vector_init(&labeling, 0)) { + if (igraph_vector_int_init(&labeling, 0)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -8622,13 +8623,13 @@ PyObject *igraphmodule_Graph_canonical_permutation( if (retval) { igraphmodule_handle_igraph_error(); - igraph_vector_destroy(&labeling); + igraph_vector_int_destroy(&labeling); return NULL; } - list = igraphmodule_vector_t_to_PyList(&labeling, IGRAPHMODULE_TYPE_INT); + list = igraphmodule_vector_int_t_to_PyList(&labeling); - igraph_vector_destroy(&labeling); + igraph_vector_int_destroy(&labeling); return list; } @@ -8657,10 +8658,10 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, } if (vids) { - igraph_vector_t vidsvec; - if (igraphmodule_PyObject_to_vector_t(vids, &vidsvec, 1)) { + igraph_vector_int_t vidsvec; + if (igraphmodule_PyObject_to_vector_int_t(vids, &vidsvec)) { PyErr_SetString(PyExc_ValueError, - "Error while converting PyList to igraph_vector_t"); + "Error while converting PyList to igraph_vector_int_t"); return NULL; } if (igraph_isoclass_subgraph(&self->g, &vidsvec, &isoclass)) { @@ -9254,7 +9255,7 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, PyObject *callback_fn=Py_None; PyObject *node_compat_fn=Py_None, *edge_compat_fn=Py_None; igraphmodule_GraphObject *other; - igraph_vector_t mapping_12, mapping_21, *map12=0, *map21=0; + igraph_vector_int_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_vector_int_t *color1=0, *color2=0; igraph_vector_int_t *edge_color1=0, *edge_color2=0; igraphmodule_i_Graph_isomorphic_vf2_callback_data_t callback_data; @@ -9310,11 +9311,11 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, } if (PyObject_IsTrue(return1)) { - igraph_vector_init(&mapping_12, 0); + igraph_vector_int_init(&mapping_12, 0); map12 = &mapping_12; } if (PyObject_IsTrue(return2)) { - igraph_vector_init(&mapping_21, 0); + igraph_vector_int_init(&mapping_21, 0); map21 = &mapping_21; } @@ -9356,18 +9357,18 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, } else { PyObject *m1, *m2; if (map12) { - m1 = igraphmodule_vector_t_to_PyList(map12, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map12); + m1 = igraphmodule_vector_int_t_to_PyList(map12); + igraph_vector_int_destroy(map12); if (!m1) { - if (map21) igraph_vector_destroy(map21); + if (map21) igraph_vector_int_destroy(map21); return NULL; } } else { m1 = Py_None; Py_INCREF(m1); } if (map21) { - m2 = igraphmodule_vector_t_to_PyList(map21, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(map21); + m2 = igraphmodule_vector_int_t_to_PyList(map21); + igraph_vector_int_destroy(map21); if (!m2) { Py_DECREF(m1); return NULL; @@ -10013,7 +10014,7 @@ PyObject *igraphmodule_Graph_unfold_tree(igraphmodule_GraphObject * self, PyObject *mapping_o, *mode_o=Py_None, *roots_o=Py_None; igraph_neimode_t mode = IGRAPH_OUT; igraph_vs_t vs; - igraph_vector_t mapping, vids; + igraph_vector_int_t mapping, vids; igraph_t result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &roots_o, &mode_o)) @@ -10022,37 +10023,37 @@ PyObject *igraphmodule_Graph_unfold_tree(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; if (igraphmodule_PyObject_to_vs_t(roots_o, &vs, &self->g, 0, 0)) return NULL; - if (igraph_vector_init(&mapping, igraph_vcount(&self->g))) { + if (igraph_vector_int_init(&mapping, igraph_vcount(&self->g))) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } - if (igraph_vector_init(&vids, 0)) { + if (igraph_vector_int_init(&vids, 0)) { igraph_vs_destroy(&vs); - igraph_vector_destroy(&mapping); + igraph_vector_int_destroy(&mapping); return igraphmodule_handle_igraph_error(); } if (igraph_vs_as_vector(&self->g, vs, &vids)) { igraph_vs_destroy(&vs); - igraph_vector_destroy(&vids); - igraph_vector_destroy(&mapping); + igraph_vector_int_destroy(&vids); + igraph_vector_int_destroy(&mapping); return igraphmodule_handle_igraph_error(); } igraph_vs_destroy(&vs); if (igraph_unfold_tree(&self->g, &result, mode, &vids, &mapping)) { - igraph_vector_destroy(&vids); - igraph_vector_destroy(&mapping); + igraph_vector_int_destroy(&vids); + igraph_vector_int_destroy(&mapping); igraphmodule_handle_igraph_error(); return NULL; } - igraph_vector_destroy(&vids); + igraph_vector_int_destroy(&vids); - mapping_o = igraphmodule_vector_t_to_PyList(&mapping, IGRAPHMODULE_TYPE_INT); - igraph_vector_destroy(&mapping); + mapping_o = igraphmodule_vector_int_t_to_PyList(&mapping); + igraph_vector_int_destroy(&mapping); if (!mapping_o) { igraph_destroy(&result); @@ -10915,7 +10916,7 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { for (j = i; j < n; j++) - igraph_vector_destroy((igraph_vector_t *) VECTOR(result)[j]); + igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; @@ -10923,7 +10924,7 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, else { PyList_SET_ITEM(list, i, item); } - igraph_vector_destroy(vec); + igraph_vector_int_destroy(vec); } igraph_vector_ptr_destroy_all(&result); @@ -11438,7 +11439,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj PyObject *cl, *res, *merges, *weights_obj = Py_None; igraph_vector_int_t membership; igraph_vector_t *weights = 0; - igraph_matrix_t m; + igraph_matrix_int_t m; igraph_real_t q; igraphmodule_ARPACKOptionsObject *arpack_options; PyObject *arpack_options_o = igraphmodule_arpack_options_default; @@ -11451,7 +11452,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj if (igraph_vector_int_init(&membership, 0)) return igraphmodule_handle_igraph_error(); - if (igraph_matrix_init(&m, 0, 0)) { + if (igraph_matrix_int_init(&m, 0, 0)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&membership); return 0; @@ -11464,7 +11465,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, ATTRIBUTE_TYPE_EDGE)) { - igraph_matrix_destroy(&m); + igraph_matrix_int_destroy(&m); igraph_vector_int_destroy(&membership); return NULL; } @@ -11472,7 +11473,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; if (igraph_community_leading_eigenvector(&self->g, weights, &m, &membership, (igraph_integer_t) n, igraphmodule_ARPACKOptions_get(arpack_options), &q, 0, 0, 0, 0, 0, 0)){ - igraph_matrix_destroy(&m); + igraph_matrix_int_destroy(&m); igraph_vector_int_destroy(&membership); if (weights != 0) { igraph_vector_destroy(weights); free(weights); @@ -11487,12 +11488,12 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj cl = igraphmodule_vector_int_t_to_PyList(&membership); igraph_vector_int_destroy(&membership); if (cl == 0) { - igraph_matrix_destroy(&m); + igraph_matrix_int_destroy(&m); return 0; } - merges = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_INT); - igraph_matrix_destroy(&m); + merges = igraphmodule_matrix_int_t_to_PyList(&m); + igraph_matrix_int_destroy(&m); if (merges == 0) return 0; @@ -11536,12 +11537,12 @@ PyObject *igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject * sel qs=igraphmodule_vector_t_to_PyList(&q, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&q); if (!qs) { - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); return NULL; } ms=igraphmodule_matrix_int_t_to_PyList(&merges); - igraph_matrix_destroy(&merges); + igraph_matrix_int_destroy(&merges); if (ms == NULL) { Py_DECREF(qs); From 3fa278754fbaae9bd18e7bc2c84719b775bd32e9 Mon Sep 17 00:00:00 2001 From: odidev Date: Tue, 31 Aug 2021 14:45:23 +0530 Subject: [PATCH 0556/1892] Add linux aarch64 wheels (#432) Signed-off-by: odidev --- .github/workflows/build.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73259dc38..6a0affaf7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,6 +34,31 @@ jobs: with: path: ./wheelhouse/*.whl + build_aarch64_wheels: + name: Build wheels on Linux AArch64 + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v1 + + - name: Build wheels + uses: joerick/cibuildwheel@v1.10.0 + env: + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" + CIBW_ARCHS_LINUX: aarch64 + CIBW_BUILD: "*-manylinux_aarch64" + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + build_wheel_macos: name: Build wheels on macOS runs-on: macos-10.15 From 3195c71da5dd6fce24f5c6896f928fe7fa64b738 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 1 Sep 2021 23:38:09 +0200 Subject: [PATCH 0557/1892] chore: clean up MANIFEST.in now that the C core is also cleaner --- MANIFEST.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index bbfa86415..a5592a432 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,9 +5,5 @@ include scripts/mkdoc.sh include tests/*.py graft vendor/source/igraph -prune vendor/source/igraph/etc/abstracts -prune vendor/source/igraph/etc/papers -prune vendor/source/igraph/etc/presentations prune vendor/source/igraph/interfaces -prune vendor/source/igraph/vendor/simpleraytracer From c77b369c430792a7ae136bb699c3677072685a75 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 2 Sep 2021 07:37:54 +0200 Subject: [PATCH 0558/1892] chore: repo root directory cleanup --- .flake8 | 3 - .gitignore | 2 - COPYING | 340 ----------------------------------------------- MANIFEST.in | 1 - requirements.txt | 1 - tox.ini | 4 + 6 files changed, 4 insertions(+), 347 deletions(-) delete mode 100644 .flake8 delete mode 100644 COPYING delete mode 100644 requirements.txt diff --git a/.flake8 b/.flake8 deleted file mode 100644 index e4e5eb32d..000000000 --- a/.flake8 +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -max-line-length = 88 -extend-ignore = E203, W503 diff --git a/.gitignore b/.gitignore index 918256eeb..323291f0c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,4 @@ src/igraph/*.so .vscode/ vendor/build/ vendor/install/ -Pipfile -Pipfile.lock diff --git a/COPYING b/COPYING deleted file mode 100644 index 3912109b5..000000000 --- a/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/MANIFEST.in b/MANIFEST.in index a5592a432..65b187f3e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include src/_igraph/*.h include MANIFEST.in -include COPYING include scripts/mkdoc.sh include tests/*.py diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d6e1198b1..000000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ --e . diff --git a/tox.ini b/tox.ini index bd0355f4d..805660bf5 100644 --- a/tox.ini +++ b/tox.ini @@ -25,3 +25,7 @@ passenv = PATH setenv = TESTING_IN_TOX=1 +[flake8] +max-line-length = 88 +extend-ignore = E203, W503 + From 7601bae07f3c29b281dfc3bf5b1d3d4c8783395f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 2 Sep 2021 09:48:15 +0200 Subject: [PATCH 0559/1892] tox: ensure that the plotting deps are installed, and switch to cairocffi --- setup.py | 2 +- tox.ini | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 0b64a20f2..127a0863b 100644 --- a/setup.py +++ b/setup.py @@ -788,7 +788,7 @@ def use_educated_guess(self): packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], - extras_require={"plotting": ["pycairo>=1.18.0"]}, + extras_require={"plotting": ["cairocffi>=1.2.0"]}, headers=headers, platforms="ALL", keywords=[ diff --git a/tox.ini b/tox.ini index 805660bf5..d144c3963 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py36, py37, py38, py39, pypy, pypy3 +envlist = py36, py37, py38, py39, pypy3 [gh-actions] python = @@ -21,6 +21,7 @@ deps = numpy; platform_python_implementation != "PyPy" networkx; platform_python_implementation != "PyPy" pandas; platform_python_implementation != "PyPy" +extras = plotting passenv = PATH setenv = TESTING_IN_TOX=1 From f97e0ac7b0d200ed23e338835d2cd046c0232f72 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 08:44:28 +0200 Subject: [PATCH 0560/1892] fix: igraph_get_adjacency() does not have an 'eids' argument any more --- src/_igraph/graphobject.c | 8 ++++---- tests/test_conversion.py | 14 -------------- vendor/source/igraph | 2 +- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f99d1bef6..3f9b5b812 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -7659,12 +7659,12 @@ PyObject *igraphmodule_Graph_layout_bipartite( PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "type", "eids", NULL }; + static char *kwlist[] = { "type", NULL }; igraph_get_adjacency_t mode = IGRAPH_GET_ADJACENCY_BOTH; igraph_matrix_t m; - PyObject *result, *mode_o = Py_None, *eids = Py_False; + PyObject *result, *mode_o = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &eids)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) return NULL; if (igraphmodule_PyObject_to_get_adjacency_t(mode_o, &mode)) return NULL; @@ -7675,7 +7675,7 @@ PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, return NULL; } - if (igraph_get_adjacency(&self->g, &m, mode, PyObject_IsTrue(eids))) { + if (igraph_get_adjacency(&self->g, &m, mode)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&m); return NULL; diff --git a/tests/test_conversion.py b/tests/test_conversion.py index b8600e9a3..5bfd443bb 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -125,20 +125,6 @@ def testGetAdjacency(self): ] ) ) - self.assertTrue( - g.get_adjacency(eids=True) - == Matrix( - [ - [0, 1, 2, 3, 0, 0], - [1, 0, 0, 0, 4, 5], - [2, 0, 0, 0, 0, 0], - [3, 0, 0, 0, 0, 0], - [0, 4, 0, 0, 0, 0], - [0, 5, 0, 0, 0, 0], - ] - ) - - 1 - ) # Directed case g = Graph.Tree(6, 3, "tree_out") diff --git a/vendor/source/igraph b/vendor/source/igraph index 2ceb15db7..fb17862e3 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2ceb15db7983a15e499844daddd1e1aa72cb0138 +Subproject commit fb17862e3c8096171449b1680581a3b1e55e8a29 From 6ea9ed089a27470a8ccab0b05b0ccadadc4e2d8a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 09:23:41 +0200 Subject: [PATCH 0561/1892] fix: all test cases pass on my machine, yay --- src/_igraph/attributes.c | 2 +- src/_igraph/convert.c | 1 + src/_igraph/edgeseqobject.c | 12 ++++++++++-- src/_igraph/graphobject.c | 26 +++++++++++++------------- src/_igraph/vertexseqobject.c | 6 ++++++ 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index fa7bdd3ed..7ffa56e73 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -413,7 +413,7 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, } /* Adding vertices */ -static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr) { +static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, igraph_vector_ptr_t *attr) { /* Extend the end of every value in the vertex hash with nv pieces of None */ PyObject *key, *value, *dict; long int i, j, k, l; diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index d2032e986..c36664d2e 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1337,6 +1337,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { list=PyList_New(n); for (i=0; ig); if (igraphmodule_PyObject_to_vector_int_t(esobj, &v)) @@ -228,9 +228,17 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, } break; + case IGRAPH_ES_NONE: + break; + /* TODO: IGRAPH_ES_PAIRS, IGRAPH_ES_ADJ, IGRAPH_ES_PATH, IGRAPH_ES_MULTIPATH - someday :) They are unused yet in the Python interface */ + + default: + return PyErr_Format( + igraphmodule_InternalError, "unsupported edge selector type: %d", igraph_es_type(&self->es) + ); } if (idx < 0) { PyErr_SetString(PyExc_IndexError, "edge index out of range"); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3f9b5b812..f5d46e09e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6352,18 +6352,18 @@ typedef struct { PyObject* graph; } igraphmodule_i_Graph_motifs_randesu_callback_data_t; -igraph_bool_t igraphmodule_i_Graph_motifs_randesu_callback(const igraph_t *graph, - igraph_vector_t *vids, int isoclass, void* extra) { +igraph_error_t igraphmodule_i_Graph_motifs_randesu_callback(const igraph_t *graph, + igraph_vector_int_t *vids, int isoclass, void* extra) { igraphmodule_i_Graph_motifs_randesu_callback_data_t* data = (igraphmodule_i_Graph_motifs_randesu_callback_data_t*)extra; PyObject* vector; PyObject* result; igraph_bool_t retval; - vector = igraphmodule_vector_t_to_PyList(vids, IGRAPHMODULE_TYPE_INT); + vector = igraphmodule_vector_int_t_to_PyList(vids); if (vector == NULL) { /* Error in conversion, return 1 */ - return 1; + return IGRAPH_FAILURE; } result = PyObject_CallFunction(data->func, "OOi", data->graph, vector, isoclass); @@ -6371,13 +6371,13 @@ igraph_bool_t igraphmodule_i_Graph_motifs_randesu_callback(const igraph_t *graph if (result == NULL) { /* Error in callback, return 1 */ - return 1; + return IGRAPH_FAILURE; } retval = PyObject_IsTrue(result); Py_DECREF(result); - return retval; + return retval ? IGRAPH_STOP : IGRAPH_SUCCESS; } /** \ingroup python_interface_graph @@ -8819,17 +8819,17 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_callback_fn( map12_o = igraphmodule_vector_int_t_to_PyList(map12); if (map12_o == NULL) { - /* Error in conversion, return 0 to stop the search */ + /* Error in conversion, return an error code */ PyErr_WriteUnraisable(data->callback_fn); - return 0; + return IGRAPH_FAILURE; } map21_o = igraphmodule_vector_int_t_to_PyList(map21); if (map21_o == NULL) { - /* Error in conversion, return 0 to stop the search */ + /* Error in conversion, return an error code */ PyErr_WriteUnraisable(data->callback_fn); Py_DECREF(map21_o); - return 0; + return IGRAPH_FAILURE; } result = PyObject_CallFunction(data->callback_fn, "OOOO", data->graph1, data->graph2, @@ -8838,15 +8838,15 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_callback_fn( Py_DECREF(map21_o); if (result == NULL) { - /* Error in callback, return 0 */ + /* Error in callback, return an error code */ PyErr_WriteUnraisable(data->callback_fn); - return 0; + return IGRAPH_FAILURE; } retval = PyObject_IsTrue(result); Py_DECREF(result); - return retval; + return retval ? IGRAPH_SUCCESS : IGRAPH_STOP; } igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_node_compat_fn( diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 4b2e83a3b..08cc5a002 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -213,6 +213,8 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, idx = self->vs.data.vid; } break; + case IGRAPH_VS_NONE: + break; case IGRAPH_VS_SEQ: if (i < 0) { i = self->vs.data.seq.to - self->vs.data.seq.from + i; @@ -223,6 +225,10 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, break; /* TODO: IGRAPH_VS_ADJ, IGRAPH_VS_NONADJ - someday :) They are unused yet in the Python interface */ + default: + return PyErr_Format( + igraphmodule_InternalError, "unsupported vertex selector type: %d", igraph_vs_type(&self->vs) + ); } if (idx < 0) { From 251a89cd21ff44822c710ec135de79271659d6e6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 09:29:43 +0200 Subject: [PATCH 0562/1892] feat: added 'test' extra to install all dependencies needed for unit tests --- .github/workflows/build.yml | 1 + setup.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a0affaf7..83ef87eb1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m unittest -vvv" + CIBW_TEST_EXTRAS: "test" CIBW_SKIP: "cp27-* pp27-* cp35-*" jobs: diff --git a/setup.py b/setup.py index 127a0863b..2aaa15a6c 100644 --- a/setup.py +++ b/setup.py @@ -788,7 +788,10 @@ def use_educated_guess(self): packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], - extras_require={"plotting": ["cairocffi>=1.2.0"]}, + extras_require={ + "plotting": ["cairocffi>=1.2.0"], + "test": ["networkx>=2.6.2", "numpy>=1.21.2", "pandas>=1.3.2", "scipy>=1.7.1"] + }, headers=headers, platforms="ALL", keywords=[ From 8c15abb6659ae470e030cafa6ca442cd2744c2f5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 09:36:18 +0200 Subject: [PATCH 0563/1892] style: blackened setup.py --- setup.py | 80 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/setup.py b/setup.py index 2aaa15a6c..ced505305 100644 --- a/setup.py +++ b/setup.py @@ -265,26 +265,36 @@ def compile_in(self, source_folder, build_folder, install_folder): print("Running build...") # We are _not_ using a parallel build; this is intentional, see igraph/igraph#1755 - retcode = subprocess.call( - [cmake, "--build", ".", "--config", "Release"] - ) + retcode = subprocess.call([cmake, "--build", ".", "--config", "Release"]) if retcode: return False print("Installing build...") - retcode = subprocess.call([cmake, "--install", ".", "--prefix", str(install_folder), "--config", "Release"]) + retcode = subprocess.call( + [ + cmake, + "--install", + ".", + "--prefix", + str(install_folder), + "--config", + "Release", + ] + ) if retcode: return False pkgconfig_candidates = [ install_folder / "lib" / "pkgconfig" / "igraph.pc", - install_folder / "lib64" / "pkgconfig" / "igraph.pc" + install_folder / "lib64" / "pkgconfig" / "igraph.pc", ] for candidate in pkgconfig_candidates: if candidate.exists(): return self.parse_pkgconfig_file(candidate) - raise RuntimeError("no igraph.pc was found in the installation folder of igraph") + raise RuntimeError( + "no igraph.pc was found in the installation folder of igraph" + ) ########################################################################### @@ -395,12 +405,16 @@ def run(self): # Add extra libraries that may have been specified if "IGRAPH_EXTRA_LIBRARIES" in os.environ: - extra_libraries = os.environ["IGRAPH_EXTRA_LIBRARIES"].split(',') + extra_libraries = os.environ["IGRAPH_EXTRA_LIBRARIES"].split(",") buildcfg.libraries.extend(extra_libraries) # Override static specification based on environment variable if "IGRAPH_STATIC_EXTENSION" in os.environ: - if os.environ["IGRAPH_STATIC_EXTENSION"].lower() in ['true', '1', 'on']: + if os.environ["IGRAPH_STATIC_EXTENSION"].lower() in [ + "true", + "1", + "on", + ]: buildcfg.static_extension = True else: buildcfg.static_extension = False @@ -417,7 +431,9 @@ def run(self): # Add extra libraries that may have been specified if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ: - extra_libraries = os.environ["IGRAPH_EXTRA_DYNAMIC_LIBRARIES"].split(',') + extra_libraries = os.environ[ + "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" + ].split(",") buildcfg.libraries.extend(extra_libraries) # Remove C++ standard library as we will use the C++ linker @@ -485,24 +501,38 @@ def run(self): cwd = os.getcwd() try: os.chdir(igraph_source_repo) - version = subprocess.check_output("git describe", shell=True).decode("utf-8").strip() + version = ( + subprocess.check_output("git describe", shell=True) + .decode("utf-8") + .strip() + ) finally: os.chdir(cwd) # If we still don't have a version number, try to parse it from # include/igraph_version.h if not version: - version_header = os.path.join(igraph_build_dir, "include", "igraph_version.h") + version_header = os.path.join( + igraph_build_dir, "include", "igraph_version.h" + ) if not os.path.exists(version_header): - raise RuntimeError("You need to build the C core of igraph first before generating a source tarball of python-igraph") + raise RuntimeError( + "You need to build the C core of igraph first before generating a source tarball of python-igraph" + ) with open(version_header, "r") as fp: - lines = [line.strip() for line in fp if line.startswith("#define IGRAPH_VERSION ")] + lines = [ + line.strip() + for line in fp + if line.startswith("#define IGRAPH_VERSION ") + ] if len(lines) == 1: version = lines[0].split('"')[1] if not isinstance(version, str) or len(version) < 5: - raise RuntimeError(f"Cannot determine the version number of the C core in {igraph_source_repo}") + raise RuntimeError( + f"Cannot determine the version number of the C core in {igraph_source_repo}" + ) if not is_git_repo(igraph_source_repo): # python-igraph was extracted from an official tarball so @@ -515,9 +545,14 @@ def run(self): # Copy the generated parser sources from the build folder parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") if os.path.isdir(parser_dir): - shutil.copytree(parser_dir, os.path.join(igraph_source_repo, "src", "io", "parsers")) + shutil.copytree( + parser_dir, + os.path.join(igraph_source_repo, "src", "io", "parsers"), + ) else: - raise RuntimeError(f"You need to build the C core of igraph first before generating a source tarball of python-igraph") + raise RuntimeError( + f"You need to build the C core of igraph first before generating a source tarball of python-igraph" + ) # Add a version file to the tarball with open(version_file, "w") as fp: @@ -700,7 +735,9 @@ def use_vendored_igraph(self): buildcfg.library_dirs.append(str(candidate)) break else: - raise RuntimeError("cannot detect igraph library dir within " + str(vendor_dir)) + raise RuntimeError( + "cannot detect igraph library dir within " + str(vendor_dir) + ) if not buildcfg.static_extension: buildcfg.static_extension = "only_igraph" @@ -754,7 +791,6 @@ def use_educated_guess(self): buildcfg.process_args_from_command_line() - # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) sources.append(os.path.join("src", "_igraph", "force_cpp_linker.cpp")) @@ -790,7 +826,13 @@ def use_educated_guess(self): install_requires=["texttable>=1.6.2"], extras_require={ "plotting": ["cairocffi>=1.2.0"], - "test": ["networkx>=2.6.2", "numpy>=1.21.2", "pandas>=1.3.2", "scipy>=1.7.1"] + "test": [ + "networkx>=2.6.2", + "numpy>=1.21.2", + "pandas>=1.3.2", + "scipy>=1.7.1", + "pytest>=6.2.5", + ], }, headers=headers, platforms="ALL", From 74d3771130bfedcff5a213e049096a3c57bc36b2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 09:36:30 +0200 Subject: [PATCH 0564/1892] test: use pytest as test runner --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83ef87eb1..7d0354422 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: - CIBW_TEST_COMMAND: "cd {project} && python -m unittest -vvv" + CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" CIBW_SKIP: "cp27-* pp27-* cp35-*" From fe946fd7808520b7b02aba49f553c148fb3a81cc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 10:03:13 +0200 Subject: [PATCH 0565/1892] fix: started sorting out integer conversions and getting rid of unnecessary casts --- src/_igraph/convert.c | 81 ++++++++++++++++++----------------- src/_igraph/vertexseqobject.c | 52 ++++++++++++---------- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index c36664d2e..ad261fccf 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -794,13 +794,16 @@ int igraphmodule_PyObject_to_igraph_t(PyObject *o, igraph_t **result) { * \param v the result is stored here * \return 0 if everything was OK, 1 otherwise */ -int PyLong_to_integer_t(PyObject* obj, int* v) { +int PyLong_to_integer_t(PyObject* obj, igraph_integer_t* v) { if (IGRAPH_INTEGER_SIZE == 64) { - *v = (igraph_integer_t)PyLong_AsLong(obj); + /* here the assumption is that sizeof(long long) == 64 bits; anyhow, this + * is the widest integer type that we can convert a PyLong to so we cannot + * do any better than this */ + *v = PyLong_AsLongLong(obj); } else { - int dummy; - PyLong_AsInt(obj, &dummy); - *v = (igraph_integer_t)dummy; + int dummy; + PyLong_AsInt(obj, &dummy); + *v = (igraph_integer_t)dummy; } return 0; } @@ -815,7 +818,8 @@ int PyLong_to_integer_t(PyObject* obj, int* v) { * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { - int retval, num; + int retval; + igraph_integer_t num; if (object == NULL) { } else if (PyLong_Check(object)) { @@ -1093,10 +1097,10 @@ int igraphmodule_PyObject_float_to_vector_t(PyObject *list, igraph_vector_t *v) * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v) { - PyObject *item; - int value=0; + PyObject *it = 0, *item; + igraph_integer_t value = 0; Py_ssize_t i, j, k; - int ok, retval; + int ok; if (PyBaseString_Check(list)) { /* It is highly unlikely that a string (although it is a sequence) will @@ -1107,24 +1111,20 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v if (!PySequence_Check(list)) { /* try to use an iterator */ - PyObject *it = PyObject_GetIter(list); + it = PyObject_GetIter(list); if (it) { - PyObject *item; - igraph_vector_int_init(v, 0); + if (igraph_vector_int_init(v, 0)) { + igraphmodule_handle_igraph_error(); + Py_DECREF(it); + return 1; + } + while ((item = PyIter_Next(it)) != 0) { - ok = 1; if (!PyNumber_Check(item)) { PyErr_SetString(PyExc_TypeError, "iterable must return numbers"); - ok=0; + ok = 0; } else { - PyObject *item2 = PyNumber_Long(item); - if (item2 == 0) { - PyErr_SetString(PyExc_TypeError, "can't convert a list item to integer"); - ok = 0; - } else { - ok = (PyLong_AsInt(item, &value) == 0); - Py_DECREF(item2); - } + ok = (igraphmodule_PyObject_to_integer_t(item, &value) == 0); } if (ok == 0) { @@ -1133,6 +1133,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v Py_DECREF(it); return 1; } + if (igraph_vector_int_push_back(v, value)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(v); @@ -1140,43 +1141,44 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v Py_DECREF(it); return 1; } + Py_DECREF(item); } + Py_DECREF(it); - return 0; } else { PyErr_SetString(PyExc_TypeError, "sequence or iterable expected"); return 1; } + return 0; } - j=PySequence_Size(list); - igraph_vector_int_init(v, j); - for (i=0, k=0; i= igraph_vcount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); return -1; } + igraph_vs_1(&vs, (igraph_integer_t)idx); } else { igraph_vector_int_t v; @@ -252,7 +258,7 @@ PyObject* igraphmodule_VertexSeq_attribute_names(igraphmodule_VertexSeqObject* s PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObject* self, PyObject* o) { igraphmodule_GraphObject *gr = self->gref; PyObject *result=0, *values, *item; - long int i, n; + igraph_integer_t i, n; if (!igraphmodule_attribute_name_check(o)) return 0; @@ -275,7 +281,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje result = PyList_New(n); if (!result) return 0; - for (i=0; ivs.data.vecptr)[i]); + for (i = 0; i < n; i++) { + item = PyList_GET_ITEM(values, VECTOR(*self->vs.data.vecptr)[i]); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } + break; case IGRAPH_VS_SEQ: @@ -300,11 +307,12 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje result = PyList_New(n); if (!result) return 0; - for (i=0; ivs.data.seq.from+i); + for (i = 0; i < n; i++) { + item = PyList_GET_ITEM(values, self->vs.data.seq.from + i); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } + break; default: @@ -315,7 +323,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje } PyObject* igraphmodule_VertexSeq_get_attribute_values_mapping(igraphmodule_VertexSeqObject *self, PyObject *o) { - long int index; + Py_ssize_t index; /* Handle integer indices according to the sequence protocol */ if (PyIndex_Check(o)) { @@ -350,7 +358,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb PyObject *dict, *list, *item; igraphmodule_GraphObject *gr; igraph_vector_int_t vs; - long i, j, n, no_of_nodes; + igraph_integer_t i, j, n, no_of_nodes; gr = self->gref; dict = ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_VERTEX]; @@ -382,10 +390,10 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb } n=PySequence_Size(values); - if (n<0) return -1; + if (n < 0) return -1; if (igraph_vs_type(&self->vs) == IGRAPH_VS_ALL) { - no_of_nodes = (long)igraph_vcount(&gr->g); + no_of_nodes = igraph_vcount(&gr->g); if (n == 0 && no_of_nodes > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); return -1; @@ -395,7 +403,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb list = PyDict_GetItem(dict, attrname); if (list != 0) { /* Yes, we have. Modify its items to the items found in values */ - for (i=0, j=0; i 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); igraph_vector_int_destroy(&vs); @@ -454,7 +462,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ - if (PyList_SetItem(list, (long)VECTOR(vs)[i], item)) { + if (PyList_SetItem(list, VECTOR(vs)[i], item)) { Py_DECREF(item); igraph_vector_int_destroy(&vs); return -1; @@ -465,7 +473,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb /* We don't have attributes with the given name yet. Create an entry * in the dict, create a new list, fill with None for vertices not in the * sequence and copy the rest */ - long n2 = igraph_vcount(&gr->g); + igraph_integer_t n2 = igraph_vcount(&gr->g); list = PyList_New(n2); if (list == 0) { igraph_vector_int_destroy(&vs); @@ -483,7 +491,7 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb Py_DECREF(list); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ - PyList_SET_ITEM(list, (long)VECTOR(vs)[i], item); + PyList_SET_ITEM(list, VECTOR(vs)[i], item); /* PyList_SET_ITEM stole a reference to the item automatically */ } igraph_vector_int_destroy(&vs); @@ -591,8 +599,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject *args) { igraphmodule_VertexSeqObject *result; igraphmodule_GraphObject *gr; - igraph_integer_t igraph_idx; - long i, j, n, m; + igraph_integer_t igraph_idx, i, j, n, m; gr=self->gref; result=igraphmodule_VertexSeq_copy(self); @@ -681,15 +688,14 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, m = igraph_vector_int_size(&v2); for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); igraph_vector_int_destroy(&v); @@ -794,7 +800,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_int_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); From 499642686e65feb7aec063bb5f5cb5bac01a3b60 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 10:11:12 +0200 Subject: [PATCH 0566/1892] fix: invalidate cached C core if it is updated --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d0354422..7ea5de7b5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }} + key: C-core-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python From 2e5bb504cf8c718149b5e356b2cce4adbef82127 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 10:15:06 +0200 Subject: [PATCH 0567/1892] fix: another attempt at cache invalidaiton --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ea5de7b5..250fecafc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v2-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python From 144876c5a39000819e64bb3ab5114074476e90d8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 14:49:18 +0200 Subject: [PATCH 0568/1892] fix: yet another attempt at cache invalidation --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 250fecafc..e8c785feb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,7 +75,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v2-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v1-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python @@ -126,7 +126,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-build-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.gitmodules') }}- + key: C-core-build-v1-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - name: Cache VCPKG uses: actions/cache@v2 @@ -176,7 +176,7 @@ jobs: path: | vendor/build vendor/install - key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }}-4 + key: C-core-v1-${{ runner.os }}-${{ hashFiles('.gitmodules') }}-4 - name: Install OS dependencies if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core From 49e2dbf157e8bc3b3b15dd8e9a3f66736d105fe6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 14:59:11 +0200 Subject: [PATCH 0569/1892] fix: fall back to earlier versions of test dependencies so they support Python 3.6 --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index ced505305..25fce3f4d 100644 --- a/setup.py +++ b/setup.py @@ -827,10 +827,10 @@ def use_educated_guess(self): extras_require={ "plotting": ["cairocffi>=1.2.0"], "test": [ - "networkx>=2.6.2", - "numpy>=1.21.2", - "pandas>=1.3.2", - "scipy>=1.7.1", + "networkx>=2.5", + "numpy>=1.19.0", + "pandas>=1.1.0", + "scipy>=1.5.0", "pytest>=6.2.5", ], }, From 8d4a3cf2ca6ad4622559323806fde72793cf3794 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 15:18:22 +0200 Subject: [PATCH 0570/1892] chore: updated vendored igraph to fix a compilation problem with PRId32 / PRId64 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index fb17862e3..6f154c7ac 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit fb17862e3c8096171449b1680581a3b1e55e8a29 +Subproject commit 6f154c7ac0946f7a0baf1ce403c520cacf6035d7 From 6fad0780bb33c7d550296c3839a2cff828819b9c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 15:53:40 +0200 Subject: [PATCH 0571/1892] test: don't attempt to install complicated test dependencies on PyPy --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 25fce3f4d..3f79ddb63 100644 --- a/setup.py +++ b/setup.py @@ -828,10 +828,10 @@ def use_educated_guess(self): "plotting": ["cairocffi>=1.2.0"], "test": [ "networkx>=2.5", - "numpy>=1.19.0", - "pandas>=1.1.0", - "scipy>=1.5.0", "pytest>=6.2.5", + 'numpy>=1.19.0 ; platform_python_implementation != "pypy"', + 'pandas>=1.1.0 ; platform_python_implementation != "pypy"', + 'scipy>=1.5.0 ; platform_python_implementation != "pypy"', ], }, headers=headers, From 75db285ce2d521788ac034961b0d4ddb58c5c4f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 21:34:50 +0200 Subject: [PATCH 0572/1892] chore: make it clear in setup.py that we don't support Python <3.6 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 3f79ddb63..ac341ad21 100644 --- a/setup.py +++ b/setup.py @@ -834,6 +834,7 @@ def use_educated_guess(self): 'scipy>=1.5.0 ; platform_python_implementation != "pypy"', ], }, + python_requires=">=3.6", headers=headers, platforms="ALL", keywords=[ From 0ce1d508be3f420fb014ca404224dc70f44194b2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 21:36:56 +0200 Subject: [PATCH 0573/1892] fix: fix PyPy detection in test dependencies in setup.py --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ac341ad21..573ef7ae6 100644 --- a/setup.py +++ b/setup.py @@ -829,9 +829,9 @@ def use_educated_guess(self): "test": [ "networkx>=2.5", "pytest>=6.2.5", - 'numpy>=1.19.0 ; platform_python_implementation != "pypy"', - 'pandas>=1.1.0 ; platform_python_implementation != "pypy"', - 'scipy>=1.5.0 ; platform_python_implementation != "pypy"', + 'numpy>=1.19.0 ; platform_python_implementation != "PyPy"', + 'pandas>=1.1.0 ; platform_python_implementation != "PyPy"', + 'scipy>=1.5.0 ; platform_python_implementation != "PyPy"', ], }, python_requires=">=3.6", From ae8bc40e9ecba0e2cca2e4b063b32eaaa3867114 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Sep 2021 23:33:34 +0200 Subject: [PATCH 0574/1892] fix: trying alternative format for PyPy detection in setup.py extras --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 573ef7ae6..b97a8904a 100644 --- a/setup.py +++ b/setup.py @@ -829,9 +829,9 @@ def use_educated_guess(self): "test": [ "networkx>=2.5", "pytest>=6.2.5", - 'numpy>=1.19.0 ; platform_python_implementation != "PyPy"', - 'pandas>=1.1.0 ; platform_python_implementation != "PyPy"', - 'scipy>=1.5.0 ; platform_python_implementation != "PyPy"', + "numpy>=1.19.0; platform_python_implementation != 'PyPy'", + "pandas>=1.1.0; platform_python_implementation != 'PyPy'", + "scipy>=1.5.0; platform_python_implementation != 'PyPy'", ], }, python_requires=">=3.6", From 3f65848ff5e40a1e9496c7a977757513bc362c55 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 4 Sep 2021 00:30:12 +0200 Subject: [PATCH 0575/1892] fix: restrict Pandas version in unit tests to ensure that we have wheels for all CPython versions --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b97a8904a..3ed791065 100644 --- a/setup.py +++ b/setup.py @@ -830,7 +830,7 @@ def use_educated_guess(self): "networkx>=2.5", "pytest>=6.2.5", "numpy>=1.19.0; platform_python_implementation != 'PyPy'", - "pandas>=1.1.0; platform_python_implementation != 'PyPy'", + "pandas>=1.1.0,<1.3.1; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", ], }, From 98d6b47edd500d16e78fbcafd7649b00712ed750 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 4 Sep 2021 10:13:45 +0200 Subject: [PATCH 0576/1892] fix: numpy_to_contiguous_memoryview() now works for 64-bit and 32-bit igraph as well --- src/_igraph/igraphmodule.c | 2 ++ src/igraph/utils.py | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 31946354e..e8639c366 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -904,6 +904,8 @@ PyObject* PyInit__igraph(void) PyModule_AddIntConstant(m, "LOOPS_SW", IGRAPH_LOOPS_SW); PyModule_AddIntConstant(m, "MULTI_SW", IGRAPH_MULTI_SW); + PyModule_AddIntConstant(m, "INTEGER_SIZE", IGRAPH_INTEGER_SIZE); + /* More useful constants */ { const char* version; diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 8cc381cb4..e1bce6541 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -60,19 +60,20 @@ def numpy_to_contiguous_memoryview(obj): """ # Deferred import to prevent a hard dependency on NumPy from numpy import int32, int64, require + from igraph._igraph import INTEGER_SIZE # TODO: we used to export to double, which is only dependent on the # architecture. Now with integers and a compile-time flag, we have # to figure out what is the integer bitness of the underlying C core. # Think of how to do that, for now default to 64 bit ints! - size = 8 - #size = sizeof(c_double) - if size == 8: + if INTEGER_SIZE == 64: dtype = int64 - elif size == 4: + elif INTEGER_SIZE == 32: dtype = int32 else: - raise TypeError("size of C double (%d bytes) is not supported" % size) + raise TypeError( + f"size of igraph_integer_t in the C layer ({INTEGER_SIZE} bits) is not supported" + ) return memoryview(require(obj, dtype=dtype, requirements="AC")) From 8a796015c0ec1ebfb480e509f590b02f62e2efc6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 4 Sep 2021 10:19:18 +0200 Subject: [PATCH 0577/1892] fix: conversion from memoryview to edge list needs to rely on the size of igraph_integer_t now --- src/_igraph/convert.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index ad261fccf..f50fb313a 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1516,9 +1516,9 @@ int igraphmodule_PyObject_to_edgelist( if (PyMemoryView_Check(list)) { buffer = PyMemoryView_GET_BUFFER(list); - if (buffer->itemsize != sizeof(igraph_real_t)) { + if (buffer->itemsize != sizeof(igraph_integer_t)) { PyErr_SetString( - PyExc_TypeError, "item size of buffer must match the size of igraph_real_t" + PyExc_TypeError, "item size of buffer must match the size of igraph_integer_t" ); return 1; } From 426b43d715917138e2d835550fe7bb4adef1e3a3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 4 Sep 2021 23:30:46 +0200 Subject: [PATCH 0578/1892] fix: conversion improvements, slowly getting rid of (long) casts --- src/_igraph/convert.c | 218 +++++++++++++++++++++++++------------- src/_igraph/convert.h | 8 +- src/_igraph/graphobject.c | 2 +- 3 files changed, 150 insertions(+), 78 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index f50fb313a..46080a8d0 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1258,6 +1258,48 @@ int igraphmodule_PyObject_to_vector_bool_t(PyObject *list, return 0; } +/** + * \ingroup python_interface_conversion + * \brief Converts an igraph \c igraph_integer_t to a Python integer + * + * \param value the \c igraph_integer_t value to be converted + * \return the Python integer as a \c PyObject*, or \c NULL if an + * error occurred + */ +PyObject* igraphmodule_integer_t_to_PyObject(igraph_integer_t value) { +#if IGRAPH_INTEGER_SIZE == 32 + /* minimum size of a long is 32 bits so we are okay */ + return PyLong_FromLong(value); +#elif IGRAPH_INTEGER_SIZE == 64 + /* minimum size of a long long is 64 bits so we are okay */ + return PyLong_FromLongLong(value); +#else +# error "Unknown igraph_integer_t size" +#endif +} + +/** + * \ingroup python_interface_conversion + * \brief Converts an igraph \c igraph_real_t to a Python float or integer + * + * \param value the \c igraph_real_t value to be converted + * \return the Python float or integer as a \c PyObject*, or \c NULL if an + * error occurred + */ +PyObject* igraphmodule_real_t_to_PyObject(igraph_real_t value, igraphmodule_conv_t type) { + if (type == IGRAPHMODULE_TYPE_INT) { + if (!igraph_finite(value)) { + return PyFloat_FromDouble(value); + } else { + return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); + } + } else if (type == IGRAPHMODULE_TYPE_FLOAT) { + return PyFloat_FromDouble(value); + } else { + Py_RETURN_NONE; + } +} + /** * \ingroup python_interface_conversion * \brief Converts an igraph \c igraph_vector_bool_t to a Python boolean list @@ -1291,28 +1333,22 @@ PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v) { * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer list as a \c PyObject*, or \c NULL if an error occurred */ -PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, - igraphmodule_conv_t type) { +PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, igraphmodule_conv_t type) { PyObject *list, *item; Py_ssize_t n, i; - n=igraph_vector_size(v); - if (n<0) return igraphmodule_handle_igraph_error(); + n = igraph_vector_size(v); + if (n < 0) { + return igraphmodule_handle_igraph_error(); + } - list=PyList_New(n); - for (i=0; i Date: Sun, 5 Sep 2021 14:46:23 +0200 Subject: [PATCH 0579/1892] fix: more conversion improvements --- src/_igraph/convert.c | 258 ++++++++++++++++++++++++++---------------- 1 file changed, 161 insertions(+), 97 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 46080a8d0..b51aa2211 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1312,12 +1312,17 @@ PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v) { PyObject *list, *item; Py_ssize_t n, i; - n=igraph_vector_bool_size(v); - if (n<0) + n = igraph_vector_bool_size(v); + if (n < 0) { return igraphmodule_handle_igraph_error(); + } - list=PyList_New(n); - for (i=0; i>=1; - list=PyList_New(n); - - /* populate the list with data */ - for (i=0, j=0; i>= 1; + list = PyList_New(n); + if (!list) { + return NULL; + } + + /* populate the list with data */ + for (i = 0, j = 0; i < n; i++, j += 2) { + first = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[j]); + if (!first) { + Py_DECREF(list); + return NULL; + } + + second = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[j + 1]); + if (!second) { + Py_DECREF(first); + Py_DECREF(list); + return NULL; + } + + pair = PyTuple_Pack(2, first, second); + if (pair == NULL) { + Py_DECREF(second); + Py_DECREF(first); + Py_DECREF(list); + return NULL; + } - return list; + Py_DECREF(first); + Py_DECREF(second); + first = second = 0; + + PyList_SET_ITEM(list, i, pair); + } + + return list; } /** @@ -1982,7 +2010,7 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * /** * \ingroup python_interface_conversion - * \brief Converts two igraph \c igraph_vector_t vectors to a Python list of integer pairs + * \brief Converts two igraph \c igraph_vector_int_t vectors to a Python list of integer pairs * * \param v1 the \c igraph_vector_int_t containing the 1st vector to be converted * \param v2 the \c igraph_vector_int_t containing the 2nd vector to be converted @@ -1990,28 +2018,51 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * */ PyObject* igraphmodule_vector_int_t_pair_to_PyList(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2) { - PyObject *list, *pair; - long n, i; - - n=igraph_vector_int_size(v1); - if (n<0) return igraphmodule_handle_igraph_error(); - if (igraph_vector_int_size(v2) != n) return igraphmodule_handle_igraph_error(); - - /* create a new Python list */ - list=PyList_New(n); - - /* populate the list with data */ - for (i=0; i Date: Sun, 5 Sep 2021 16:16:39 +0200 Subject: [PATCH 0580/1892] refactor: edgeobject.* is now free of unnecessary long int casts --- src/_igraph/convert.c | 16 +++++--- src/_igraph/edgeobject.c | 77 ++++++++++++++++++++++--------------- src/_igraph/edgeobject.h | 3 +- src/_igraph/edgeseqobject.c | 2 +- 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index b51aa2211..c84f66dfa 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2927,7 +2927,7 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g } else if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_EdgeType)) { /* Single edge ID from Edge object */ igraphmodule_EdgeObject *eo = (igraphmodule_EdgeObject*)o; - *eid = igraphmodule_Edge_get_index_igraph_integer(eo); + *eid = igraphmodule_Edge_get_index_as_igraph_integer(eo); } else if (PyIndex_Check(o)) { /* Other numeric type that can be converted to an index */ PyObject* num = PyNumber_Index(o); @@ -2965,8 +2965,11 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g retval = igraph_get_eid(graph, eid, vid1, vid2, 1, 0); if (retval == IGRAPH_EINVVID) { - PyErr_Format(PyExc_ValueError, "no edge from vertex #%ld to #%ld; no such vertex ID", - (long int)vid1, (long int)vid2); + PyErr_Format( + PyExc_ValueError, + "no edge from vertex #%" IGRAPH_PRId " to #%" IGRAPH_PRId "; no such vertex ID", + vid1, vid2 + ); return 1; } else if (retval) { igraphmodule_handle_igraph_error(); @@ -2974,8 +2977,11 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g } if (*eid < 0) { - PyErr_Format(PyExc_ValueError, "no edge from vertex #%ld to #%ld", - (long int)vid1, (long int)vid2); + PyErr_Format( + PyExc_ValueError, + "no edge from vertex #%" IGRAPH_PRId " to #%" IGRAPH_PRId, + vid1, vid2 + ); return 1; } } else { diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 6f3010ee4..491ebe1cb 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -23,6 +23,7 @@ */ #include "attributes.h" +#include "convert.h" #include "edgeobject.h" #include "error.h" #include "graphobject.h" @@ -150,8 +151,8 @@ PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { if (attrs == 0) return NULL; - s = PyUnicode_FromFormat("igraph.Edge(%R, %ld, %R)", - (PyObject*)self->gref, (long int)self->idx, attrs); + s = PyUnicode_FromFormat("igraph.Edge(%R, %" IGRAPH_PRId ", %R)", + (PyObject*)self->gref, self->idx, attrs); Py_DECREF(attrs); return s; @@ -169,7 +170,7 @@ long igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { if (self->hash != -1) return self->hash; - index_o = PyLong_FromLong((long int)self->idx); + index_o = igraphmodule_integer_t_to_PyObject(self->idx); if (index_o == 0) return -1; @@ -260,23 +261,25 @@ PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self) { PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self) { igraphmodule_GraphObject *o = self->gref; PyObject *names, *dict; - long int i, n; + Py_ssize_t i, n; - if (!igraphmodule_Edge_Validate((PyObject*)self)) - return 0; + if (!igraphmodule_Edge_Validate((PyObject*)self)) { + return NULL; + } - dict=PyDict_New(); - if (!dict) + dict = PyDict_New(); + if (!dict) { return NULL; + } - names=igraphmodule_Graph_edge_attributes(o); + names = igraphmodule_Graph_edge_attributes(o); if (!names) { Py_DECREF(dict); return NULL; } n = PyList_Size(names); - for (i=0; igref; igraph_integer_t from, to; - if (!igraphmodule_Edge_Validate((PyObject*)self)) + if (!igraphmodule_Edge_Validate((PyObject*)self)) { return NULL; + } if (igraph_edge(&o->g, self->idx, &from, &to)) { - igraphmodule_handle_igraph_error(); return NULL; + return igraphmodule_handle_igraph_error(); } - return PyLong_FromLong((long int)from); + + return igraphmodule_integer_t_to_PyObject(from); } /** @@ -458,13 +463,15 @@ PyObject* igraphmodule_Edge_get_to(igraphmodule_EdgeObject* self, void* closure) igraphmodule_GraphObject *o = self->gref; igraph_integer_t from, to; - if (!igraphmodule_Edge_Validate((PyObject*)self)) + if (!igraphmodule_Edge_Validate((PyObject*)self)) { return NULL; + } if (igraph_edge(&o->g, self->idx, &from, &to)) { - igraphmodule_handle_igraph_error(); return NULL; + return igraphmodule_handle_igraph_error(); } - return PyLong_FromLong((long)to); + + return igraphmodule_integer_t_to_PyObject(to); } /** @@ -490,25 +497,17 @@ PyObject* igraphmodule_Edge_get_target_vertex(igraphmodule_EdgeObject* self, voi * Returns the edge index */ PyObject* igraphmodule_Edge_get_index(igraphmodule_EdgeObject* self, void* closure) { - return PyLong_FromLong((long int)self->idx); + return igraphmodule_integer_t_to_PyObject(self->idx); } /** * \ingroup python_interface_edge * Returns the edge index as an igraph_integer_t */ -igraph_integer_t igraphmodule_Edge_get_index_igraph_integer(igraphmodule_EdgeObject* self) { +igraph_integer_t igraphmodule_Edge_get_index_as_igraph_integer(igraphmodule_EdgeObject* self) { return self->idx; } -/** - * \ingroup python_interface_edge - * Returns the edge index as an ordinary C long - */ -long igraphmodule_Edge_get_index_long(igraphmodule_EdgeObject* self) { - return (long)self->idx; -} - /** * \ingroup python_interface_edge * Returns the source and target vertex index of an edge @@ -516,14 +515,32 @@ long igraphmodule_Edge_get_index_long(igraphmodule_EdgeObject* self) { PyObject* igraphmodule_Edge_get_tuple(igraphmodule_EdgeObject* self, void* closure) { igraphmodule_GraphObject *o = self->gref; igraph_integer_t from, to; + PyObject *from_o, *to_o, *result; - if (!igraphmodule_Edge_Validate((PyObject*)self)) + if (!igraphmodule_Edge_Validate((PyObject*)self)) { return NULL; + } if (igraph_edge(&o->g, self->idx, &from, &to)) { - igraphmodule_handle_igraph_error(); return NULL; + return igraphmodule_handle_igraph_error(); + } + + from_o = igraphmodule_integer_t_to_PyObject(from); + if (!from_o) { + return NULL; } - return Py_BuildValue("(ii)", (long)from, (long)to); + + to_o = igraphmodule_integer_t_to_PyObject(to); + if (!to_o) { + Py_DECREF(from_o); + return NULL; + } + + result = PyTuple_Pack(2, from_o, to_o); + Py_DECREF(to_o); + Py_DECREF(from_o); + + return result; } /** @@ -567,7 +584,7 @@ PyObject* igraphmodule_Edge_get_graph(igraphmodule_EdgeObject* self, void* closu #define GRAPH_PROXY_METHOD(FUNC, METHODNAME) \ PyObject* igraphmodule_Edge_##FUNC(igraphmodule_EdgeObject* self, PyObject* args, PyObject* kwds) { \ PyObject *new_args, *item, *result; \ - long int i, num_args = args ? PyTuple_Size(args)+1 : 1; \ + Py_ssize_t i, num_args = args ? PyTuple_Size(args)+1 : 1; \ \ /* Prepend ourselves to args */ \ new_args = PyTuple_New(num_args); \ diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index 2d7f3a259..3c0f146f3 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -47,8 +47,7 @@ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self); PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self); PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self); -igraph_integer_t igraphmodule_Edge_get_index_igraph_integer(igraphmodule_EdgeObject* self); -long igraphmodule_Edge_get_index_long(igraphmodule_EdgeObject* self); +igraph_integer_t igraphmodule_Edge_get_index_as_igraph_integer(igraphmodule_EdgeObject* self); PyObject* igraphmodule_Edge_update_attributes(PyObject* self, PyObject* args, PyObject* kwds); diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 1e6c58bc0..bb575b461 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -612,7 +612,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } if (PyObject_IsTrue(call_result)) igraph_vector_int_push_back(&v, - igraphmodule_Edge_get_index_long((igraphmodule_EdgeObject*)edge)); + igraphmodule_Edge_get_index_as_igraph_integer((igraphmodule_EdgeObject*)edge)); else was_excluded=1; Py_DECREF(call_result); Py_DECREF(edge); From 66662b6f99c849fcf23956a06d2d59c62f6a6edf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 5 Sep 2021 22:12:40 +0200 Subject: [PATCH 0581/1892] refactor: removed some unnecessary casts from edgeseqobject.c --- src/_igraph/edgeseqobject.c | 157 ++++++++++++++++++++++------------ src/_igraph/edgeseqobject.h | 2 +- src/_igraph/vertexseqobject.c | 13 ++- src/_igraph/vertexseqobject.h | 2 +- 4 files changed, 114 insertions(+), 60 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index bb575b461..86de684ed 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -117,12 +117,18 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, igraph_es_all(&es, IGRAPH_EDGEORDER_ID); } else if (PyLong_Check(esobj)) { /* We selected a single edge */ - long int idx = PyLong_AsLong(esobj); + igraph_integer_t idx; + + if (igraphmodule_PyObject_to_integer_t(esobj, &idx)) { + return -1; + } + if (idx < 0 || idx >= igraph_ecount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); return -1; } - igraph_es_1(&es, (igraph_integer_t)idx); + + igraph_es_1(&es, idx); } else { /* We selected multiple edges */ igraph_vector_int_t v; @@ -170,7 +176,7 @@ void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self) { * \ingroup python_interface_edgeseq * \brief Returns the length of the sequence (i.e. the number of edges in the graph) */ -int igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject* self) { +Py_ssize_t igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject* self) { igraph_t *g; igraph_integer_t result; @@ -179,7 +185,7 @@ int igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject* self) { igraphmodule_handle_igraph_error(); return -1; } - return (int)result; + return result; } /** @@ -199,7 +205,7 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, i = igraph_ecount(g) + i; } if (i >= 0 && i < igraph_ecount(g)) { - idx = (igraph_integer_t)i; + idx = i; } break; @@ -209,7 +215,7 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, i = igraph_vector_int_size(self->es.data.vecptr) + i; } if (i >= 0 && i < igraph_vector_int_size(self->es.data.vecptr)) { - idx = (igraph_integer_t)VECTOR(*self->es.data.vecptr)[i]; + idx = VECTOR(*self->es.data.vecptr)[i]; } break; @@ -224,7 +230,7 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, i = self->es.data.seq.to - self->es.data.seq.from + i; } if (i >= 0 && i < self->es.data.seq.to - self->es.data.seq.from) { - idx = self->es.data.seq.from + (igraph_integer_t)i; + idx = self->es.data.seq.from + i; } break; @@ -261,33 +267,40 @@ PyObject* igraphmodule_EdgeSeq_attribute_names(igraphmodule_EdgeSeqObject* self) PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* self, PyObject* o) { igraphmodule_GraphObject *gr = self->gref; PyObject *result=0, *values, *item; - long int i, n; + Py_ssize_t i, n; if (!igraphmodule_attribute_name_check(o)) return 0; PyErr_Clear(); - values=PyDict_GetItem(ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE], o); + values = PyDict_GetItem(ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE], o); if (!values) { PyErr_SetString(PyExc_KeyError, "Attribute does not exist"); return NULL; - } else if (PyErr_Occurred()) return NULL; + } else if (PyErr_Occurred()) { + return NULL; + } switch (igraph_es_type(&self->es)) { case IGRAPH_ES_NONE: n = 0; result = PyList_New(0); + if (!result) { + return 0; + } break; case IGRAPH_ES_ALL: n = PyList_Size(values); result = PyList_New(n); - if (!result) return 0; + if (!result) { + return 0; + } - for (i=0; ies.data.vecptr); result = PyList_New(n); - if (!result) return 0; + if (!result) { + return 0; + } - for (i=0; ies.data.vecptr)[i]); + for (i = 0; i < n; i++) { + item = PyList_GET_ITEM(values, VECTOR(*self->es.data.vecptr)[i]); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } @@ -307,10 +322,12 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* case IGRAPH_ES_SEQ: n = self->es.data.seq.to - self->es.data.seq.from; result = PyList_New(n); - if (!result) return 0; + if (!result) { + return 0; + } - for (i=0; ies.data.seq.from+i); + for (i = 0; i < n; i++) { + item = PyList_GET_ITEM(values, self->es.data.seq.from + i); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } @@ -364,7 +381,8 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject PyObject *dict, *list, *item; igraphmodule_GraphObject *gr; igraph_vector_int_t es; - long i, j, n, no_of_edges; + Py_ssize_t i, j, n; + igraph_integer_t no_of_edges; gr = self->gref; dict = ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE]; @@ -384,7 +402,9 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject * single element (the value itself) and then call ourselves again */ int result; PyObject *newList = PyList_New(1); - if (newList == 0) return -1; + if (newList == 0) { + return -1; + } Py_INCREF(values); PyList_SET_ITEM(newList, 0, values); /* reference stolen here */ result = igraphmodule_EdgeSeq_set_attribute_values_mapping(self, attrname, newList); @@ -392,11 +412,13 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject return result; } - n=PySequence_Size(values); - if (n<0) return -1; + n = PySequence_Size(values); + if (n < 0) { + return -1; + } if (igraph_es_type(&self->es) == IGRAPH_ES_ALL) { - no_of_edges = (long)igraph_ecount(&gr->g); + no_of_edges = igraph_ecount(&gr->g); if (n == 0 && no_of_edges > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); return -1; @@ -406,10 +428,14 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject list = PyDict_GetItem(dict, attrname); if (list != 0) { /* Yes, we have. Modify its items to the items found in values */ - for (i=0, j=0; i 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); igraph_vector_int_destroy(&es); @@ -457,12 +489,16 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject list = PyDict_GetItem(dict, attrname); if (list != 0) { /* Yes, we have. Modify its items to the items found in values */ - for (i=0, j=0; ig); + igraph_integer_t n2 = igraph_ecount(&gr->g); list = PyList_New(n2); - if (list == 0) { igraph_vector_int_destroy(&es); return -1; } - for (i=0; igref; result=igraphmodule_EdgeSeq_copy(self); @@ -576,7 +621,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject /* First, filter by positional arguments */ n = PyTuple_Size(args); - for (i=0; i= m || idx < 0) { + Py_DECREF(result); PyErr_SetString(PyExc_ValueError, "edge index out of range"); igraph_vector_int_destroy(&v); igraph_vector_int_destroy(&v2); @@ -748,7 +797,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject return 0; } /* Do the iteration */ - while ((item2=PyIter_Next(iter)) != 0) { + while ((item2 = PyIter_Next(iter)) != 0) { if (igraphmodule_PyObject_to_integer_t(item2, &igraph_idx)) { /* We simply ignore elements that we don't know */ Py_DECREF(item2); @@ -762,7 +811,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject igraph_vector_int_destroy(&v2); return NULL; } - if (igraph_vector_int_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_int_push_back(&v, VECTOR(v2)[igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); diff --git a/src/_igraph/edgeseqobject.h b/src/_igraph/edgeseqobject.h index 7a410b9e1..ffca889fc 100644 --- a/src/_igraph/edgeseqobject.h +++ b/src/_igraph/edgeseqobject.h @@ -46,7 +46,7 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, PyObject *args, PyObject *kwds); void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self); -int igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject *self); +Py_ssize_t igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject *self); PyObject* igraphmodule_EdgeSeq_find(igraphmodule_EdgeSeqObject *self, PyObject *args); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 3c015a3ba..15a826419 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -173,16 +173,21 @@ void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self) { * \ingroup python_interface_vertexseq * \brief Returns the length of the sequence */ -int igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject* self) { +Py_ssize_t igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject* self) { igraph_t *g; igraph_integer_t result; - if (!self->gref) return -1; - g=&GET_GRAPH(self); + + if (!self->gref) { + return -1; + } + + g = &GET_GRAPH(self); if (igraph_vs_size(g, &self->vs, &result)) { igraphmodule_handle_igraph_error(); return -1; } - return (int)result; + + return result; } /** diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index 708889a97..95cbf416b 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -43,7 +43,7 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject* self, PyObject* args, PyObject* kwds); void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self); -int igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject *self); +Py_ssize_t igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject *self); PyObject* igraphmodule_VertexSeq_find(igraphmodule_VertexSeqObject *self, PyObject *args); From 759cd5727953e69bdb2c7ebae32bf407b7336694 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 5 Sep 2021 23:06:05 +0200 Subject: [PATCH 0582/1892] refactor: BFSIter now uses dqueue_int --- src/_igraph/bfsiter.c | 70 ++++++++++++++++++++++++------------------- src/_igraph/bfsiter.h | 2 +- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index c86c90702..2108b19a1 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -22,6 +22,7 @@ #include "bfsiter.h" #include "common.h" +#include "convert.h" #include "error.h" #include "vertexobject.h" @@ -42,9 +43,9 @@ PyTypeObject igraphmodule_BFSIterType; */ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_neimode_t mode, igraph_bool_t advanced) { igraphmodule_BFSIterObject* o; - long int no_of_nodes, r; + igraph_integer_t no_of_nodes, r; - o=PyObject_GC_New(igraphmodule_BFSIterObject, &igraphmodule_BFSIterType); + o = PyObject_GC_New(igraphmodule_BFSIterObject, &igraphmodule_BFSIterType); Py_INCREF(g); o->gref=g; o->graph=&g->g; @@ -54,39 +55,47 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, return NULL; } - no_of_nodes=igraph_vcount(&g->g); + no_of_nodes = igraph_vcount(&g->g); o->visited=(char*)calloc(no_of_nodes, sizeof(char)); if (o->visited == 0) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_dqueue_init(&o->queue, 100)) { + if (igraph_dqueue_int_init(&o->queue, 100)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } + if (igraph_vector_int_init(&o->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); - igraph_dqueue_destroy(&o->queue); + igraph_dqueue_int_destroy(&o->queue); return NULL; } if (PyLong_Check(root)) { - r=PyLong_AsLong(root); + if (igraphmodule_PyObject_to_integer_t(root, &r)) { + igraph_dqueue_int_destroy(&o->queue); + return NULL; + } } else { - r=((igraphmodule_VertexObject*)root)->idx; + r = ((igraphmodule_VertexObject*)root)->idx; } - if (igraph_dqueue_push(&o->queue, r) || - igraph_dqueue_push(&o->queue, 0) || - igraph_dqueue_push(&o->queue, -1)) { - igraph_dqueue_destroy(&o->queue); + + if (igraph_dqueue_int_push(&o->queue, r) || + igraph_dqueue_int_push(&o->queue, 0) || + igraph_dqueue_int_push(&o->queue, -1)) { + igraph_dqueue_int_destroy(&o->queue); igraph_vector_int_destroy(&o->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } o->visited[r]=1; - if (!igraph_is_directed(&g->g)) mode=IGRAPH_ALL; + if (!igraph_is_directed(&g->g)) { + mode=IGRAPH_ALL; + } + o->mode=mode; o->advanced=advanced; @@ -131,7 +140,7 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { self->gref=NULL; Py_XDECREF(tmp); - igraph_dqueue_destroy(&self->queue); + igraph_dqueue_int_destroy(&self->queue); igraph_vector_int_destroy(&self->neis); free(self->visited); self->visited=0; @@ -157,27 +166,28 @@ PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { } PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { - if (!igraph_dqueue_empty(&self->queue)) { - igraph_integer_t vid = (igraph_integer_t)igraph_dqueue_pop(&self->queue); - igraph_integer_t dist = (igraph_integer_t)igraph_dqueue_pop(&self->queue); - igraph_integer_t parent = (igraph_integer_t)igraph_dqueue_pop(&self->queue); - long int i; + if (!igraph_dqueue_int_empty(&self->queue)) { + igraph_integer_t vid = igraph_dqueue_int_pop(&self->queue); + igraph_integer_t dist = igraph_dqueue_int_pop(&self->queue); + igraph_integer_t parent = igraph_dqueue_int_pop(&self->queue); + igraph_integer_t i, n; if (igraph_neighbors(self->graph, &self->neis, vid, self->mode)) { igraphmodule_handle_igraph_error(); return NULL; } - - for (i=0; ineis); i++) { - igraph_integer_t neighbor = (igraph_integer_t)VECTOR(self->neis)[i]; - if (self->visited[neighbor]==0) { - self->visited[neighbor]=1; - if (igraph_dqueue_push(&self->queue, neighbor) || - igraph_dqueue_push(&self->queue, dist+1) || - igraph_dqueue_push(&self->queue, vid)) { - igraphmodule_handle_igraph_error(); - return NULL; - } + + n = igraph_vector_int_size(&self->neis); + for (i = 0; i < n; i++) { + igraph_integer_t neighbor = VECTOR(self->neis)[i]; + if (self->visited[neighbor] == 0) { + self->visited[neighbor] = 1; + if (igraph_dqueue_int_push(&self->queue, neighbor) || + igraph_dqueue_int_push(&self->queue, dist+1) || + igraph_dqueue_int_push(&self->queue, vid)) { + igraphmodule_handle_igraph_error(); + return NULL; + } } } @@ -194,7 +204,7 @@ PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { Py_INCREF(Py_None); parentobj=Py_None; } - return Py_BuildValue("NlN", vertexobj, (long int)dist, parentobj); + return Py_BuildValue("NnN", vertexobj, (Py_ssize_t)dist, parentobj); } else { return igraphmodule_Vertex_New(self->gref, vid); } diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index e36f03069..f713ba4ee 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -34,7 +34,7 @@ typedef struct { PyObject_HEAD igraphmodule_GraphObject* gref; - igraph_dqueue_t queue; + igraph_dqueue_int_t queue; igraph_vector_int_t neis; igraph_t *graph; char *visited; From 1d3a2926e87a4284ba09ce415d54b8936db6cc83 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 5 Sep 2021 23:06:20 +0200 Subject: [PATCH 0583/1892] refactor: more type casting cleanup --- src/_igraph/igraphmodule.c | 9 ++++-- src/_igraph/operators.c | 52 +++++++++++++++++++---------------- src/_igraph/vertexobject.c | 10 +------ src/_igraph/vertexobject.h | 1 - src/_igraph/vertexseqobject.c | 4 +-- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index e8639c366..9dbd3afa0 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -577,8 +577,10 @@ PyObject* igraphmodule_split_join_distance(PyObject *self, &comm1_o, &comm2_o)) return NULL; - if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) + if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) { return NULL; + } + if (igraphmodule_PyObject_to_vector_int_t(comm2_o, &comm2)) { igraph_vector_int_destroy(&comm1); return NULL; @@ -590,10 +592,13 @@ PyObject* igraphmodule_split_join_distance(PyObject *self, igraph_vector_int_destroy(&comm2); return NULL; } + igraph_vector_int_destroy(&comm1); igraph_vector_int_destroy(&comm2); - return Py_BuildValue("ll", (long)distance12, (long)distance21); + /* sizeof(Py_ssize_t) is most likely the same as sizeof(igraph_integer_t), + * but even if it isn't, we cast explicitly so we are safe */ + return Py_BuildValue("nn", (Py_ssize_t)distance12, (Py_ssize_t)distance21); } /** \ingroup python_interface diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 7d8db55bb..0ad5a0293 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -34,7 +34,7 @@ PyObject *igraphmodule__disjoint_union(PyObject *self, { static char* kwlist[] = { "graphs", NULL }; PyObject *it, *graphs; - long int no_of_graphs; + Py_ssize_t no_of_graphs; igraph_vector_ptr_t gs; PyObject *result; PyTypeObject *result_type; @@ -62,7 +62,7 @@ PyObject *igraphmodule__disjoint_union(PyObject *self, return NULL; } Py_DECREF(it); - no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + no_of_graphs = igraph_vector_ptr_size(&gs); /* Create disjoint union */ if (igraph_disjoint_union_many(&g, &gs)) { @@ -98,7 +98,7 @@ PyObject *igraphmodule__union(PyObject *self, static char* kwlist[] = { "graphs", "edgemaps", NULL }; PyObject *it, *em_list = 0, *graphs, *with_edgemaps_o; int with_edgemaps = 0; - long int no_of_graphs; + Py_ssize_t i, j, no_of_graphs; igraph_vector_ptr_t gs; igraphmodule_GraphObject *o; PyObject *result; @@ -130,7 +130,8 @@ PyObject *igraphmodule__union(PyObject *self, return NULL; } Py_DECREF(it); - no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + + no_of_graphs = igraph_vector_ptr_size(&gs); if (with_edgemaps) { /* prepare edgemaps */ @@ -148,22 +149,24 @@ PyObject *igraphmodule__union(PyObject *self, } /* extract edgemaps */ - long int i; - em_list = PyList_New((Py_ssize_t) no_of_graphs); + em_list = PyList_New(no_of_graphs); for (i = 0; i < no_of_graphs; i++) { - long int j; - long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); + Py_ssize_t no_of_edges = igraph_ecount(VECTOR(gs)[i]); igraph_vector_int_t *map = VECTOR(edgemaps)[i]; - PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); + PyObject *emi = PyList_New(no_of_edges); for (j = 0; j < no_of_edges; j++) { - PyObject *dest = PyLong_FromLong((long)VECTOR(*map)[j]); - PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); + PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); + if (!dest) { + Py_DECREF(emi); + Py_DECREF(em_list); + return NULL; + } + PyList_SET_ITEM(emi, j, dest); } - PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); + PyList_SET_ITEM(em_list, i, emi); } igraph_vector_ptr_destroy(&edgemaps); - } - else { + } else { /* Create union */ if (igraph_union_many(&g, &gs, /* edgemaps */ 0)) { igraph_vector_ptr_destroy(&gs); @@ -209,7 +212,7 @@ PyObject *igraphmodule__intersection(PyObject *self, static char* kwlist[] = { "graphs", "edgemaps", NULL }; PyObject *it, *em_list = 0, *graphs, *with_edgemaps_o; int with_edgemaps = 0; - long int no_of_graphs; + Py_ssize_t i, j, no_of_graphs; igraph_vector_ptr_t gs; igraphmodule_GraphObject *o; PyObject *result; @@ -241,7 +244,7 @@ PyObject *igraphmodule__intersection(PyObject *self, return NULL; } Py_DECREF(it); - no_of_graphs = (long int) igraph_vector_ptr_size(&gs); + no_of_graphs = igraph_vector_ptr_size(&gs); if (with_edgemaps) { /* prepare edgemaps */ @@ -258,18 +261,21 @@ PyObject *igraphmodule__intersection(PyObject *self, return NULL; } - long int i; em_list = PyList_New((Py_ssize_t) no_of_graphs); for (i = 0; i < no_of_graphs; i++) { - long int j; - long int no_of_edges = (long int) igraph_ecount(VECTOR(gs)[i]); + Py_ssize_t no_of_edges = igraph_ecount(VECTOR(gs)[i]); igraph_vector_int_t *map = VECTOR(edgemaps)[i]; - PyObject *emi = PyList_New((Py_ssize_t) no_of_edges); + PyObject *emi = PyList_New(no_of_edges); for (j = 0; j < no_of_edges; j++) { - PyObject *dest = PyLong_FromLong((long)VECTOR(*map)[j]); - PyList_SET_ITEM(emi, (Py_ssize_t) j, dest); + PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); + if (!dest) { + Py_DECREF(emi); + Py_DECREF(em_list); + return NULL; + } + PyList_SET_ITEM(emi, j, dest); } - PyList_SET_ITEM(em_list, (Py_ssize_t) i, emi); + PyList_SET_ITEM(em_list, i, emi); } igraph_vector_ptr_destroy(&edgemaps); diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 287ecba0e..bcef9561e 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -550,7 +550,7 @@ int igraphmodule_Vertex_set_attribute(igraphmodule_VertexObject* self, PyObject* * Returns the vertex index */ PyObject* igraphmodule_Vertex_get_index(igraphmodule_VertexObject* self, void* closure) { - return PyLong_FromLong((long int)self->idx); + return igraphmodule_integer_t_to_PyObject(self->idx); } /** @@ -561,14 +561,6 @@ igraph_integer_t igraphmodule_Vertex_get_index_igraph_integer(igraphmodule_Verte return self->idx; } -/** - * \ingroup python_interface_vertex - * Returns the vertex index as an ordinary C long - */ -long igraphmodule_Vertex_get_index_long(igraphmodule_VertexObject* self) { - return (long)self->idx; -} - /** * \ingroup python_interface_vertexseq * Returns the graph where the vertex belongs diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index f33d640eb..a50a6adf8 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -49,7 +49,6 @@ PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self); PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self); PyObject* igraphmodule_Vertex_attribute_names(igraphmodule_VertexObject* self); igraph_integer_t igraphmodule_Vertex_get_index_igraph_integer(igraphmodule_VertexObject* self); -long igraphmodule_Vertex_get_index_long(igraphmodule_VertexObject* self); PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, PyObject* kwds); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 15a826419..403f01a90 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -186,7 +186,7 @@ Py_ssize_t igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject* self) igraphmodule_handle_igraph_error(); return -1; } - + return result; } @@ -651,7 +651,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } if (PyObject_IsTrue(call_result)) igraph_vector_int_push_back(&v, - igraphmodule_Vertex_get_index_long((igraphmodule_VertexObject*)vertex)); + igraphmodule_Vertex_get_index_igraph_integer((igraphmodule_VertexObject*)vertex)); else was_excluded=1; Py_DECREF(call_result); Py_DECREF(vertex); From 1bb7f39a26036e668c7bfcc9d48d83ed885455de Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Sep 2021 22:52:39 +0200 Subject: [PATCH 0584/1892] refactor: DFSIter now uses igraph_integer_t properly --- src/_igraph/bfsiter.c | 1 + src/_igraph/dfsiter.c | 101 +++++++++++++++++++++---------------- src/_igraph/dfsiter.h | 2 +- src/_igraph/vertexobject.c | 6 +-- 4 files changed, 63 insertions(+), 47 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 2108b19a1..03615ceb9 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -76,6 +76,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, if (PyLong_Check(root)) { if (igraphmodule_PyObject_to_integer_t(root, &r)) { igraph_dqueue_int_destroy(&o->queue); + igraph_vector_int_destroy(&o->neis); return NULL; } } else { diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 97793aca0..dbbf1c546 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -20,6 +20,7 @@ */ +#include "convert.h" #include "dfsiter.h" #include "common.h" #include "error.h" @@ -42,7 +43,7 @@ PyTypeObject igraphmodule_DFSIterType; */ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_neimode_t mode, igraph_bool_t advanced) { igraphmodule_DFSIterObject* o; - long int no_of_nodes, r; + igraph_integer_t no_of_nodes, r; o=PyObject_GC_New(igraphmodule_DFSIterObject, &igraphmodule_DFSIterType); Py_INCREF(g); @@ -54,42 +55,51 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, return NULL; } - no_of_nodes=igraph_vcount(&g->g); - o->visited=(char*)calloc(no_of_nodes, sizeof(char)); + no_of_nodes = igraph_vcount(&g->g); + o->visited = (char*)calloc(no_of_nodes, sizeof(char)); if (o->visited == 0) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_stack_init(&o->stack, 100)) { + if (igraph_stack_int_init(&o->stack, 100)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } + if (igraph_vector_int_init(&o->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); - igraph_stack_destroy(&o->stack); + igraph_stack_int_destroy(&o->stack); return NULL; } if (PyLong_Check(root)) { - r=PyLong_AsLong(root); + if (igraphmodule_PyObject_to_integer_t(root, &r)) { + igraph_stack_int_destroy(&o->stack); + igraph_vector_int_destroy(&o->neis); + return NULL; + } } else { r = ((igraphmodule_VertexObject*)root)->idx; } + /* push the root onto the stack */ - if (igraph_stack_push(&o->stack, r) || - igraph_stack_push(&o->stack, 0) || - igraph_stack_push(&o->stack, -1)) { - igraph_stack_destroy(&o->stack); + if (igraph_stack_int_push(&o->stack, r) || + igraph_stack_int_push(&o->stack, 0) || + igraph_stack_int_push(&o->stack, -1)) { + igraph_stack_int_destroy(&o->stack); igraph_vector_int_destroy(&o->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } o->visited[r] = 1; - if (!igraph_is_directed(&g->g)) mode=IGRAPH_ALL; - o->mode=mode; - o->advanced=advanced; + if (!igraph_is_directed(&g->g)) { + mode = IGRAPH_ALL; + } + + o->mode = mode; + o->advanced = advanced; PyObject_GC_Track(o); @@ -112,8 +122,10 @@ int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, RC_TRAVERSE("DFSIter", self); if (self->gref) { - vret=visit((PyObject*)self->gref, arg); - if (vret != 0) return vret; + vret = visit((PyObject*)self->gref, arg); + if (vret != 0) { + return vret; + } } return 0; @@ -128,11 +140,11 @@ int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { PyObject_GC_UnTrack(self); - tmp=(PyObject*)self->gref; + tmp = (PyObject*)self->gref; self->gref = NULL; Py_XDECREF(tmp); - igraph_stack_destroy(&self->stack); + igraph_stack_int_destroy(&self->stack); igraph_vector_int_destroy(&self->neis); free(self->visited); self->visited = 0; @@ -164,28 +176,29 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { igraph_bool_t any = 0; /* nothing on the stack, end of iterator */ - if(igraph_stack_empty(&self->stack)) { + if (igraph_stack_int_empty(&self->stack)) { return NULL; } /* peek at the top element on the stack * because we save three things, pop 3 in inverse order and push them back */ - parent_out = (igraph_integer_t)igraph_stack_pop(&self->stack); - dist_out = (igraph_integer_t)igraph_stack_pop(&self->stack); - vid_out = (igraph_integer_t)igraph_stack_pop(&self->stack); - igraph_stack_push(&self->stack, (long int) vid_out); - igraph_stack_push(&self->stack, (long int) dist_out); - igraph_stack_push(&self->stack, (long int) parent_out); + parent_out = igraph_stack_int_pop(&self->stack); + dist_out = igraph_stack_int_pop(&self->stack); + vid_out = igraph_stack_int_pop(&self->stack); + igraph_stack_int_push(&self->stack, vid_out); + igraph_stack_int_push(&self->stack, dist_out); + igraph_stack_int_push(&self->stack, parent_out); + + /* look for neighbors until we find one or until we have exhausted the graph */ + while (!any && !igraph_stack_int_empty(&self->stack)) { + igraph_integer_t parent = igraph_stack_int_pop(&self->stack); + igraph_integer_t dist = igraph_stack_int_pop(&self->stack); + igraph_integer_t vid = igraph_stack_int_pop(&self->stack); + igraph_stack_int_push(&self->stack, vid); + igraph_stack_int_push(&self->stack, dist); + igraph_stack_int_push(&self->stack, parent); + igraph_integer_t i, n; - /* look for neighbors until you found one or until you have exausted the graph */ - while (!any && !igraph_stack_empty(&self->stack)) { - igraph_integer_t parent = (igraph_integer_t)igraph_stack_pop(&self->stack); - igraph_integer_t dist = (igraph_integer_t)igraph_stack_pop(&self->stack); - igraph_integer_t vid = (igraph_integer_t)igraph_stack_pop(&self->stack); - igraph_stack_push(&self->stack, (long int) vid); - igraph_stack_push(&self->stack, (long int) dist); - igraph_stack_push(&self->stack, (long int) parent); - long int i; /* the values above are returned at at this stage. However, we must * prepare for the next iteration by putting the next unvisited * neighbor onto the stack */ @@ -193,15 +206,17 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { igraphmodule_handle_igraph_error(); return NULL; } - for (i=0; ineis); i++) { - igraph_integer_t neighbor = (igraph_integer_t)VECTOR(self->neis)[i]; + + n = igraph_vector_int_size(&self->neis); + for (i = 0; i < n; i++) { + igraph_integer_t neighbor = VECTOR(self->neis)[i]; /* new neighbor, push the next item onto the stack */ if (self->visited[neighbor] == 0) { any = 1; self->visited[neighbor]=1; - if (igraph_stack_push(&self->stack, neighbor) || - igraph_stack_push(&self->stack, dist+1) || - igraph_stack_push(&self->stack, vid)) { + if (igraph_stack_int_push(&self->stack, neighbor) || + igraph_stack_int_push(&self->stack, dist+1) || + igraph_stack_int_push(&self->stack, vid)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -210,9 +225,9 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { } /* no new neighbors, end of subtree */ if (!any) { - igraph_stack_pop(&self->stack); - igraph_stack_pop(&self->stack); - igraph_stack_pop(&self->stack); + igraph_stack_int_pop(&self->stack); + igraph_stack_int_pop(&self->stack); + igraph_stack_int_pop(&self->stack); } } @@ -229,9 +244,9 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { return NULL; } else { Py_INCREF(Py_None); - parentobj=Py_None; + parentobj = Py_None; } - return Py_BuildValue("NlN", vertexobj, (long int)dist_out, parentobj); + return Py_BuildValue("NnN", vertexobj, (Py_ssize_t) dist_out, parentobj); } else { return vertexobj; } diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h index 757caf798..18236196d 100644 --- a/src/_igraph/dfsiter.h +++ b/src/_igraph/dfsiter.h @@ -34,7 +34,7 @@ typedef struct { PyObject_HEAD igraphmodule_GraphObject* gref; - igraph_stack_t stack; + igraph_stack_int_t stack; igraph_vector_int_t neis; igraph_t *graph; char *visited; diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index bcef9561e..9a470d66c 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -151,8 +151,8 @@ PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { if (attrs == 0) return NULL; - s = PyUnicode_FromFormat("igraph.Vertex(%R, %ld, %R)", - (PyObject*)self->gref, (long int)self->idx, attrs); + s = PyUnicode_FromFormat("igraph.Vertex(%R, %" IGRAPH_PRId ", %R)", + (PyObject*)self->gref, self->idx, attrs); Py_DECREF(attrs); return s; @@ -170,7 +170,7 @@ long igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { if (self->hash != -1) return self->hash; - index_o = PyLong_FromLong((long int)self->idx); + index_o = igraphmodule_integer_t_to_PyObject(self->idx); if (index_o == 0) return -1; From 41d649b1f450fae718d82bec8481e367dc0a0a4e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 6 Sep 2021 23:47:10 +0200 Subject: [PATCH 0585/1892] refactor: (long) casts eliminated from graphobject.c --- src/_igraph/convert.c | 12 ++- src/_igraph/convert.h | 7 +- src/_igraph/graphobject.c | 189 +++++++++++++++++++------------------- 3 files changed, 108 insertions(+), 100 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index c84f66dfa..dd4f9e3ef 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1287,14 +1287,20 @@ PyObject* igraphmodule_integer_t_to_PyObject(igraph_integer_t value) { * error occurred */ PyObject* igraphmodule_real_t_to_PyObject(igraph_real_t value, igraphmodule_conv_t type) { + if (!igraph_finite(value)) { + return PyFloat_FromDouble(value); + } + if (type == IGRAPHMODULE_TYPE_INT) { - if (!igraph_finite(value)) { + return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); + } else if (type == IGRAPHMODULE_TYPE_FLOAT) { + return PyFloat_FromDouble(value); + } else if (type == IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT) { + if (ceil(value) != value) { return PyFloat_FromDouble(value); } else { return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); } - } else if (type == IGRAPHMODULE_TYPE_FLOAT) { - return PyFloat_FromDouble(value); } else { Py_RETURN_NONE; } diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index f18be5347..12139427a 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -33,8 +33,11 @@ #include #include "graphobject.h" -typedef enum { IGRAPHMODULE_TYPE_INT=0, IGRAPHMODULE_TYPE_FLOAT } -igraphmodule_conv_t; +typedef enum { + IGRAPHMODULE_TYPE_INT = 0, + IGRAPHMODULE_TYPE_FLOAT = 1, + IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT = 2 +} igraphmodule_conv_t; typedef struct { const char* name; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 23d4d7152..fd4c44d86 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -345,14 +345,17 @@ PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph) { */ PyObject *igraphmodule_Graph_str(igraphmodule_GraphObject * self) { - if (igraph_is_directed(&self->g)) - return PyUnicode_FromFormat("Directed graph (|V| = %ld, |E| = %ld)", - (long)igraph_vcount(&self->g), - (long)igraph_ecount(&self->g)); - else - return PyUnicode_FromFormat("Undirected graph (|V| = %ld, |E| = %ld)", - (long)igraph_vcount(&self->g), - (long)igraph_ecount(&self->g)); + if (igraph_is_directed(&self->g)) { + return PyUnicode_FromFormat( + "Directed graph (|V| = %" IGRAPH_PRId ", |E| = %" IGRAPH_PRId ")", + igraph_vcount(&self->g), igraph_ecount(&self->g) + ); + } else { + return PyUnicode_FromFormat( + "Undirected graph (|V| = %" IGRAPH_PRId ", |E| = %" IGRAPH_PRId ")", + igraph_vcount(&self->g), igraph_ecount(&self->g) + ); + } } /** \ingroup python_interface_copy @@ -385,9 +388,7 @@ PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject * self) */ PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) { - PyObject *result; - result = Py_BuildValue("l", (long)igraph_vcount(&self->g)); - return result; + return igraphmodule_integer_t_to_PyObject(igraph_vcount(&self->g)); } /** \ingroup python_interface_graph @@ -397,9 +398,7 @@ PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) */ PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject * self) { - PyObject *result; - result = Py_BuildValue("l", (long)igraph_ecount(&self->g)); - return result; + return igraphmodule_integer_t_to_PyObject(igraph_ecount(&self->g)); } /** \ingroup python_interface_graph @@ -985,7 +984,7 @@ PyObject *igraphmodule_Graph_maxdegree(igraphmodule_GraphObject * self, igraph_vs_destroy(&vs); - return PyLong_FromLong((long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -1483,7 +1482,7 @@ PyObject *igraphmodule_Graph_get_eid(igraphmodule_GraphObject * self, PyObject_IsTrue(directed), PyObject_IsTrue(error))) return igraphmodule_handle_igraph_error(); - return Py_BuildValue("l", (long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -1595,7 +1594,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, return NULL; } igraph_vector_destroy(weights); free(weights); - return PyFloat_FromDouble((double)diameter); + return igraphmodule_real_t_to_PyObject(diameter, IGRAPHMODULE_TYPE_FLOAT); } else { if (igraph_diameter(&self->g, &diameter, /* from, to, vertex_path, edge_path */ @@ -1607,11 +1606,7 @@ PyObject *igraphmodule_Graph_diameter(igraphmodule_GraphObject * self, /* The diameter is integer in this case, except if igraph_diameter() * returned NaN or infinity for some reason */ - if (ceilf(diameter) == diameter && isfinite(diameter)) { - return PyLong_FromLong((long)diameter); - } else { - return PyFloat_FromDouble((double)diameter); - } + return igraphmodule_real_t_to_PyObject(diameter, IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT); } } @@ -1698,7 +1693,7 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, } igraph_vector_destroy(weights); free(weights); if (from >= 0) { - return Py_BuildValue("lld", (long)from, (long)to, (double)len); + return Py_BuildValue("nnd", (Py_ssize_t)from, (Py_ssize_t)to, (double)len); } else { return Py_BuildValue("OOd", Py_None, Py_None, (double)len); } @@ -1714,15 +1709,15 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, /* if len is finite and integer (which it typically is, unless it's * infinite), then return a Python int as the third value; otherwise * return a float */ - if (ceilf(len) == len && isfinite(len)) { + if (ceil(len) == len && isfinite(len)) { if (from >= 0) { - return Py_BuildValue("lll", (long)from, (long)to, (long)len); + return Py_BuildValue("nnn", (Py_ssize_t)from, (Py_ssize_t)to, (Py_ssize_t)len); } else { - return Py_BuildValue("OOl", Py_None, Py_None, (long)len); + return Py_BuildValue("OOn", Py_None, Py_None, (Py_ssize_t)len); } } else { if (from >= 0) { - return Py_BuildValue("lld", (long)from, (long)to, (double)len); + return Py_BuildValue("nnd", (Py_ssize_t)from, (Py_ssize_t)to, (double)len); } else { return Py_BuildValue("OOd", Py_None, Py_None, (double)len); } @@ -1742,10 +1737,15 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, igraph_integer_t girth; igraph_vector_int_t vids; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sc)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sc)) { + return NULL; + } + + if (igraph_vector_int_init(&vids, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } - igraph_vector_int_init(&vids, 0); if (igraph_girth(&self->g, &girth, &vids)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&vids); @@ -1754,11 +1754,12 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, if (PyObject_IsTrue(sc)) { PyObject* o; - o=igraphmodule_vector_int_t_to_PyList(&vids); + o = igraphmodule_vector_int_t_to_PyList(&vids); igraph_vector_int_destroy(&vids); return o; } - return PyLong_FromLong((long)girth); + + return igraphmodule_integer_t_to_PyObject(girth); } /** @@ -4173,7 +4174,7 @@ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject if (types) { igraph_vector_bool_destroy(types); free(types); } - return Py_BuildValue("llll", (long)vcount1, (long)ecount1, (long)vcount2, (long)ecount2); + return Py_BuildValue("nnnn", (Py_ssize_t)vcount1, (Py_ssize_t)ecount1, (Py_ssize_t)vcount2, (Py_ssize_t)ecount2); } /** \ingroup python_interface_graph @@ -5321,10 +5322,11 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, igraph_vs_destroy(&vs); - if (!return_single) + if (!return_single) { result = igraphmodule_vector_int_t_to_PyList(&res); - else - result = PyLong_FromLong((long)VECTOR(res)[0]); + } else { + result = igraphmodule_integer_t_to_PyObject(VECTOR(res)[0]); + } igraph_vector_int_destroy(&res); @@ -6235,7 +6237,7 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "source", "target", "checks", "neighbors", NULL }; PyObject *checks = Py_True, *neis = Py_None; - long int source = -1, target = -1, result; + long int source = -1, target = -1; igraph_integer_t res; igraph_vconn_nei_t neighbors = IGRAPH_VCONN_NEI_ERROR; @@ -6261,10 +6263,7 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, return NULL; } - if (!IGRAPH_FINITE(res)) return Py_BuildValue("d", (double)res); - - result = (long)res; - return Py_BuildValue("l", result); + return igraphmodule_integer_t_to_PyObject(res); } /********************************************************************** @@ -6337,14 +6336,12 @@ PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, */ PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { igraph_integer_t mut, asym, nul; - PyObject *list; if (igraph_dyad_census(&self->g, &mut, &asym, &nul)) { return igraphmodule_handle_igraph_error(); } - list = Py_BuildValue("lll", (long)mut, (long)asym, (long)nul); - return list; + return Py_BuildValue("nnn", (Py_ssize_t)mut, (Py_ssize_t)asym, (Py_ssize_t)nul); } typedef struct { @@ -6479,7 +6476,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_no(igraphmodule_GraphObject *self, } igraph_vector_destroy(&cut_prob); - return PyLong_FromLong((long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -6543,7 +6540,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s } igraph_vector_destroy(&cut_prob); - return PyLong_FromLong((long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -7950,8 +7947,8 @@ PyObject *igraphmodule_Graph_Read_DIMACS(PyTypeObject * type, CREATE_GRAPH_FROM_TYPE(self, g, type); - return Py_BuildValue("NiiN", (PyObject *) self, (long)source, - (long)target, capacity_obj); + return Py_BuildValue("NnnN", (PyObject *) self, (Py_ssize_t)source, + (Py_ssize_t)target, capacity_obj); } /** \ingroup python_interface_graph @@ -8676,7 +8673,7 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, } } - return PyLong_FromLong((long)isoclass); + return igraphmodule_integer_t_to_PyObject(isoclass); } /** \ingroup python_interface_graph @@ -8858,8 +8855,8 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_node_compat_fn( igraph_bool_t retval; PyObject *result; - result = PyObject_CallFunction(data->node_compat_fn, "OOll", - data->graph1, data->graph2, (long)cand1, (long)cand2); + result = PyObject_CallFunction(data->node_compat_fn, "OOnn", + data->graph1, data->graph2, (Py_ssize_t)cand1, (Py_ssize_t)cand2); if (result == NULL) { /* Error in callback, return 0 */ @@ -8882,8 +8879,8 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_edge_compat_fn( igraph_bool_t retval; PyObject *result; - result = PyObject_CallFunction(data->edge_compat_fn, "OOll", - data->graph1, data->graph2, (long)cand1, (long)cand2); + result = PyObject_CallFunction(data->edge_compat_fn, "OOnn", + data->graph1, data->graph2, (Py_ssize_t)cand1, (Py_ssize_t)cand2); if (result == NULL) { /* Error in callback, return 0 */ @@ -9129,7 +9126,7 @@ PyObject *igraphmodule_Graph_count_isomorphisms_vf2(igraphmodule_GraphObject *se if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } if (edge_color2) { igraph_vector_int_destroy(edge_color2); free(edge_color2); } - return Py_BuildValue("l", (long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -9466,7 +9463,7 @@ PyObject *igraphmodule_Graph_count_subisomorphisms_vf2(igraphmodule_GraphObject if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } if (edge_color2) { igraph_vector_int_destroy(edge_color2); free(edge_color2); } - return Py_BuildValue("l", (long)result); + return igraphmodule_integer_t_to_PyObject(result); } /** \ingroup python_interface_graph @@ -10888,7 +10885,7 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, static char *kwlist[] = { "min", "max", NULL }; PyObject *list, *item; long int min_size = 0, max_size = 0; - long int i, j, n; + igraph_integer_t i, j, n; igraph_vector_ptr_t result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ll", kwlist, @@ -10906,22 +10903,23 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); } - n = (long)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); - if (!list) + if (!list) { return NULL; + } for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -10937,7 +10935,7 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) { PyObject *list, *item; - long int i, j, n; + igraph_integer_t i, j, n; igraph_vector_ptr_t result; if (igraph_vector_ptr_init(&result, 0)) { @@ -10950,22 +10948,23 @@ PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) return igraphmodule_handle_igraph_error(); } - n = (long)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); - if (!list) + if (!list) { return NULL; + } for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -11065,13 +11064,13 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -11098,14 +11097,13 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_clique_number(igraphmodule_GraphObject * self) { - PyObject *result; igraph_integer_t i; - if (igraph_clique_number(&self->g, &i)) + if (igraph_clique_number(&self->g, &i)) { return igraphmodule_handle_igraph_error(); + } - result = PyLong_FromLong((long)i); - return result; + return igraphmodule_integer_t_to_PyObject(i); } /** \ingroup python_interface_graph @@ -11118,7 +11116,7 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject static char *kwlist[] = { "min", "max", NULL }; PyObject *list, *item; long int min_size = 0, max_size = 0; - long int i, j, n; + igraph_integer_t i, j, n; igraph_vector_ptr_t result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ll", kwlist, @@ -11136,22 +11134,23 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject return igraphmodule_handle_igraph_error(); } - n = (long)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); - if (!list) + if (!list) { return NULL; + } for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -11169,7 +11168,7 @@ PyObject * self) { PyObject *list, *item; - long int i, j, n; + igraph_integer_t i, j, n; igraph_vector_ptr_t result; if (igraph_vector_ptr_init(&result, 0)) { @@ -11182,7 +11181,7 @@ PyObject return igraphmodule_handle_igraph_error(); } - n = (long)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); if (!list) return NULL; @@ -11191,13 +11190,13 @@ PyObject igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -11215,7 +11214,7 @@ PyObject * self) { PyObject *list, *item; - long int i, j, n; + igraph_integer_t i, j, n; igraph_vector_ptr_t result; if (igraph_vector_ptr_init(&result, 0)) { @@ -11228,22 +11227,23 @@ PyObject return igraphmodule_handle_igraph_error(); } - n = (long)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); - if (!list) + if (!list) { return NULL; + } for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); if (!item) { - for (j = i; j < n; j++) + for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); + } igraph_vector_ptr_destroy_all(&result); Py_DECREF(list); return NULL; - } - else { + } else { PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); @@ -11259,14 +11259,13 @@ PyObject PyObject *igraphmodule_Graph_independence_number(igraphmodule_GraphObject * self) { - PyObject *result; igraph_integer_t i; - if (igraph_independence_number(&self->g, &i)) + if (igraph_independence_number(&self->g, &i)) { return igraphmodule_handle_igraph_error(); + } - result = PyLong_FromLong((long)i); - return result; + return igraphmodule_integer_t_to_PyObject(i); } /********************************************************************** From 197b8736b8f7f2ad86c966af354e459b96704121 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Sep 2021 00:02:18 +0200 Subject: [PATCH 0586/1892] refactor: explicit (long int) casts also eliminated --- src/_igraph/attributes.c | 8 +++++--- src/_igraph/graphobject.c | 16 +++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 7ffa56e73..4b9406d11 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -976,7 +976,7 @@ static PyObject* igraphmodule_i_ac_first(PyObject* values, */ static PyObject* igraphmodule_i_ac_random(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item, *num; PyObject *random_module = PyImport_ImportModule("random"); PyObject *random_func; @@ -993,7 +993,7 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_int_size(v); + igraph_integer_t n = igraph_vector_int_size(v); if (n > 0) { num = PyObject_CallObject(random_func, 0); @@ -1002,7 +1002,9 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, Py_DECREF(res); return 0; } - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[(long int)(n*PyFloat_AsDouble(num))]); + item = PyList_GET_ITEM( + values, VECTOR(*v)[(igraph_integer_t)(n * PyFloat_AsDouble(num))] + ); Py_DECREF(num); } else { item = Py_None; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index fd4c44d86..35c147c78 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -757,10 +757,11 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, return NULL; } - if (!return_single) + if (!return_single) { list = igraphmodule_vector_int_t_to_PyList(&result); - else - list = PyLong_FromLong((long int)VECTOR(result)[0]); + } else { + list = igraphmodule_integer_t_to_PyObject(VECTOR(result)[0]); + } igraph_vector_int_destroy(&result); igraph_vs_destroy(&vs); @@ -1183,10 +1184,11 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, return NULL; } - if (!return_single) + if (!return_single) { list = igraphmodule_vector_int_t_to_PyList(&result); - else - list = PyLong_FromLong((long int)VECTOR(result)[0]); + } else { + list = igraphmodule_integer_t_to_PyObject(VECTOR(result)[0]); + } igraph_vector_int_destroy(&result); igraph_es_destroy(&es); @@ -12116,7 +12118,7 @@ PyObject *igraphmodule_Graph___graph_as_capsule__(igraphmodule_GraphObject * * module without any additional conversions. */ PyObject *igraphmodule_Graph__raw_pointer(igraphmodule_GraphObject *self) { - return PyLong_FromLong((long int)&self->g); + return PyLong_FromVoidPtr(&self->g); } /** \ingroup python_interface_internal From 2794f983fba516d1db4bbd02252a79a83cd68166 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Sep 2021 00:07:52 +0200 Subject: [PATCH 0587/1892] refactor: igraph_*_size functions return an igraph_integer_t so use that --- src/_igraph/attributes.c | 28 ++++++++++++++-------------- src/_igraph/vertexobject.c | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 4b9406d11..1bd7aa831 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -816,14 +816,14 @@ static int igraphmodule_i_attribute_permute_edges(const igraph_t *graph, */ static PyObject* igraphmodule_i_ac_func(PyObject* values, const igraph_vector_ptr_t *merges, PyObject* func) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *list, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; - long int j, n = igraph_vector_int_size(v); + igraph_integer_t j, n = igraph_vector_int_size(v); list = PyList_New(n); for (j = 0; j < n; j++) { @@ -884,14 +884,14 @@ static PyObject* igraphmodule_i_ac_builtin_func(PyObject* values, */ static PyObject* igraphmodule_i_ac_sum(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 0.0, sum = 0.0; - long int j, n = igraph_vector_int_size(v); + igraph_integer_t j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -918,14 +918,14 @@ static PyObject* igraphmodule_i_ac_sum(PyObject* values, */ static PyObject* igraphmodule_i_ac_prod(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 1.0, prod = 1.0; - long int j, n = igraph_vector_int_size(v); + igraph_integer_t j, n = igraph_vector_int_size(v); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -952,13 +952,13 @@ static PyObject* igraphmodule_i_ac_prod(PyObject* values, */ static PyObject* igraphmodule_i_ac_first(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_int_size(v); + igraph_integer_t n = igraph_vector_int_size(v); item = n > 0 ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[0]) : Py_None; Py_INCREF(item); @@ -1027,13 +1027,13 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, */ static PyObject* igraphmodule_i_ac_last(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; - long int n = igraph_vector_int_size(v); + igraph_integer_t n = igraph_vector_int_size(v); item = (n > 0) ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[n-1]) : Py_None; Py_INCREF(item); @@ -1051,14 +1051,14 @@ static PyObject* igraphmodule_i_ac_last(PyObject* values, */ static PyObject* igraphmodule_i_ac_mean(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; igraph_real_t num = 0.0, mean = 0.0; - long int j, n = igraph_vector_int_size(v); + igraph_integer_t j, n = igraph_vector_int_size(v); for (j = 0; j < n; ) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); @@ -1087,13 +1087,13 @@ static PyObject* igraphmodule_i_ac_mean(PyObject* values, */ static PyObject* igraphmodule_i_ac_median(PyObject* values, const igraph_vector_ptr_t *merges) { - long int i, len = igraph_vector_ptr_size(merges); + igraph_integer_t i, len = igraph_vector_ptr_size(merges); PyObject *res, *list, *item; res = PyList_New(len); for (i = 0; i < len; i++) { igraph_vector_int_t *v = (igraph_vector_int_t*)VECTOR(*merges)[i]; - long int j, n = igraph_vector_int_size(v); + igraph_integer_t j, n = igraph_vector_int_size(v); list = PyList_New(n); for (j = 0; j < n; j++) { item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 9a470d66c..6da7cb720 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -654,7 +654,7 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb #define GRAPH_PROXY_METHOD_PP(FUNC, METHODNAME, POSTPROCESS) \ PyObject* igraphmodule_Vertex_##FUNC(igraphmodule_VertexObject* self, PyObject* args, PyObject* kwds) { \ PyObject *new_args, *item, *result; \ - long int i, num_args = args ? PyTuple_Size(args)+1 : 1; \ + Py_ssize_t i, num_args = args ? PyTuple_Size(args)+1 : 1; \ \ /* Prepend ourselves to args */ \ new_args = PyTuple_New(num_args); \ From a72ee5d807a1883792f3a3cecc1f039b918d5d26 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Sep 2021 20:38:04 +0200 Subject: [PATCH 0588/1892] refactor: removed a few more casts --- src/_igraph/arpackobject.c | 2 +- src/_igraph/graphobject.c | 43 +++++++++++++++++++------------------- src/_igraph/igraphmodule.c | 23 ++++++++++++-------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 7f31f506c..d10cc8d9d 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -78,7 +78,7 @@ PyObject* igraphmodule_ARPACKOptions_getattr( } else if (strcmp(attrname, "nev") == 0) { result=PyLong_FromLong(self->params.nev); } else if (strcmp(attrname, "tol") == 0) { - result=PyFloat_FromDouble((double)self->params.tol); + result=PyFloat_FromDouble(self->params.tol); } else if (strcmp(attrname, "ncv") == 0) { result=PyLong_FromLong(self->params.ncv); } else if (strcmp(attrname, "ldv") == 0) { diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 35c147c78..983230934 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -938,7 +938,7 @@ PyObject *igraphmodule_Graph_density(igraphmodule_GraphObject * self, return NULL; } - return Py_BuildValue("d", (double)result); + return igraphmodule_real_t_to_PyObject(result, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -1320,7 +1320,7 @@ PyObject *igraphmodule_Graph_reciprocity(igraphmodule_GraphObject * self, return NULL; } - return Py_BuildValue("d", (double)result); + return igraphmodule_real_t_to_PyObject(result, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -1914,7 +1914,7 @@ PyObject *igraphmodule_Graph_radius(igraphmodule_GraphObject * self, return NULL; } - return PyFloat_FromDouble((double)radius); + return igraphmodule_real_t_to_PyObject(radius, IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT); } /** \ingroup python_interface_graph @@ -3713,7 +3713,7 @@ PyObject *igraphmodule_Graph_assortativity_nominal(igraphmodule_GraphObject *sel return NULL; } - return Py_BuildValue("d", (double)(res)); + return igraphmodule_real_t_to_PyObject(res, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -3748,7 +3748,7 @@ PyObject *igraphmodule_Graph_assortativity(igraphmodule_GraphObject *self, PyObj return NULL; } - return Py_BuildValue("d", (double)(res)); + return igraphmodule_real_t_to_PyObject(res, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -3769,7 +3769,7 @@ PyObject *igraphmodule_Graph_assortativity_degree(igraphmodule_GraphObject *self return NULL; } - return Py_BuildValue("d", (double)(res)); + return igraphmodule_real_t_to_PyObject(res, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -3814,7 +3814,7 @@ PyObject *igraphmodule_Graph_authority_score( if (res_o == NULL) return igraphmodule_handle_igraph_error(); if (PyObject_IsTrue(return_eigenvalue)) { - PyObject *ev_o = PyFloat_FromDouble((double)value); + PyObject *ev_o = igraphmodule_real_t_to_PyObject(value, IGRAPHMODULE_TYPE_FLOAT); if (ev_o == NULL) { Py_DECREF(res_o); return igraphmodule_handle_igraph_error(); @@ -4445,10 +4445,11 @@ PyObject *igraphmodule_Graph_constraint(igraphmodule_GraphObject * self, return NULL; } - if (!return_single) + if (!return_single) { list = igraphmodule_vector_t_to_PyList(&result, IGRAPHMODULE_TYPE_FLOAT); - else - list = PyFloat_FromDouble((double)VECTOR(result)[0]); + } else { + list = igraphmodule_real_t_to_PyObject(VECTOR(result)[0], IGRAPHMODULE_TYPE_FLOAT); + } igraph_vs_destroy(&vids); igraph_vector_destroy(&result); @@ -4833,7 +4834,7 @@ PyObject *igraphmodule_Graph_eigenvector_centrality( if (res_o == NULL) return igraphmodule_handle_igraph_error(); if (PyObject_IsTrue(return_eigenvalue)) { - PyObject *ev_o = PyFloat_FromDouble((double)value); + PyObject *ev_o = igraphmodule_real_t_to_PyObject(value, IGRAPHMODULE_TYPE_FLOAT); if (ev_o == NULL) { Py_DECREF(res_o); return igraphmodule_handle_igraph_error(); @@ -5196,7 +5197,7 @@ PyObject *igraphmodule_Graph_hub_score( if (res_o == NULL) return igraphmodule_handle_igraph_error(); if (PyObject_IsTrue(return_eigenvalue)) { - PyObject *ev_o = PyFloat_FromDouble((double)value); + PyObject *ev_o = igraphmodule_real_t_to_PyObject(value, IGRAPHMODULE_TYPE_FLOAT); if (ev_o == NULL) { Py_DECREF(res_o); return igraphmodule_handle_igraph_error(); @@ -6065,7 +6066,7 @@ PyObject *igraphmodule_Graph_transitivity_undirected(igraphmodule_GraphObject { static char *kwlist[] = { "mode", NULL }; igraph_real_t res; - PyObject *r, *mode_o = Py_None; + PyObject *mode_o = Py_None; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) @@ -6080,8 +6081,7 @@ PyObject *igraphmodule_Graph_transitivity_undirected(igraphmodule_GraphObject return NULL; } - r = Py_BuildValue("d", (double)(res)); - return r; + return igraphmodule_real_t_to_PyObject(res, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -6094,7 +6094,7 @@ PyObject *igraphmodule_Graph_transitivity_avglocal_undirected(igraphmodule_Graph { static char *kwlist[] = { "mode", NULL }; igraph_real_t res; - PyObject *r, *mode_o = Py_None; + PyObject *mode_o = Py_None; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) @@ -6108,8 +6108,7 @@ PyObject *igraphmodule_Graph_transitivity_avglocal_undirected(igraphmodule_Graph return NULL; } - r = Py_BuildValue("d", (double)(res)); - return r; + return igraphmodule_real_t_to_PyObject(res, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -10162,7 +10161,8 @@ PyObject *igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject * self, } igraph_vector_destroy(&capacity_vector); - return Py_BuildValue("d", (double)result); + + return igraphmodule_real_t_to_PyObject(result, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -10443,7 +10443,8 @@ PyObject *igraphmodule_Graph_mincut_value(igraphmodule_GraphObject * self, } igraph_vector_destroy(&capacity_vector); - return Py_BuildValue("d", (double)result); + + return igraphmodule_real_t_to_PyObject(result, IGRAPHMODULE_TYPE_FLOAT); } /** \ingroup python_interface_graph @@ -11346,7 +11347,7 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, igraph_vector_destroy(weights); free(weights); } - return Py_BuildValue("d", (double)modularity); + return igraphmodule_real_t_to_PyObject(modularity, IGRAPHMODULE_TYPE_FLOAT); } /** diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 9dbd3afa0..bdc0eda59 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -152,16 +152,16 @@ static int igraphmodule_igraph_interrupt_hook(void* data) { int igraphmodule_igraph_progress_hook(const char* message, igraph_real_t percent, void* data) { PyObject* progress_handler = GETSTATE(0)->progress_handler; + PyObject *result; if (progress_handler) { - PyObject *result; if (PyCallable_Check(progress_handler)) { - result=PyObject_CallFunction(progress_handler, - "sd", message, (double)percent); - if (result) + result = PyObject_CallFunction(progress_handler, "sd", message, (double)percent); + if (result) { Py_DECREF(result); - else + } else { return IGRAPH_INTERRUPTED; + } } } @@ -383,14 +383,18 @@ PyObject* igraphmodule_compare_communities(PyObject *self, igraph_real_t result; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, - &comm1_o, &comm2_o, &method_o)) + &comm1_o, &comm2_o, &method_o)) { return NULL; + } - if (igraphmodule_PyObject_to_community_comparison_t(method_o, &method)) + if (igraphmodule_PyObject_to_community_comparison_t(method_o, &method)) { return NULL; + } - if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) + if (igraphmodule_PyObject_to_vector_int_t(comm1_o, &comm1)) { return NULL; + } + if (igraphmodule_PyObject_to_vector_int_t(comm2_o, &comm2)) { igraph_vector_int_destroy(&comm1); return NULL; @@ -402,10 +406,11 @@ PyObject* igraphmodule_compare_communities(PyObject *self, igraph_vector_int_destroy(&comm2); return NULL; } + igraph_vector_int_destroy(&comm1); igraph_vector_int_destroy(&comm2); - return PyFloat_FromDouble((double)result); + return igraphmodule_real_t_to_PyObject(result, IGRAPHMODULE_TYPE_FLOAT); } From e7e9ff9e9739c248f84260a607a939f3236ee9b2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 14:28:34 +0200 Subject: [PATCH 0589/1892] refactor: gotten rid of PyLong_AsInt() where the result could be larger than an int --- src/_igraph/attributes.c | 6 ++--- src/_igraph/convert.c | 51 +++++++++++++++++++++++--------------- src/_igraph/convert.h | 2 -- src/_igraph/vertexobject.c | 18 +++++++++++--- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 1bd7aa831..e74a296c4 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -136,7 +136,6 @@ int igraphmodule_PyObject_matches_attribute_record(PyObject* object, igraph_attr int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_integer_t* vid) { igraphmodule_i_attribute_struct* attrs = ATTR_STRUCT(graph); PyObject* o_vid = NULL; - int tmp; if (graph) { attrs = ATTR_STRUCT(graph); @@ -155,10 +154,9 @@ int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_inte return 1; } - if (PyLong_AsInt(o_vid, &tmp)) + if (igraphmodule_PyObject_to_integer_t(o_vid, vid)) { return 1; - - *vid = tmp; + } return 0; } diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index dd4f9e3ef..0571cc706 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -43,7 +43,8 @@ * \brief Converts a Python long to a C int * * This is similar to PyLong_AsLong, but it checks for overflow first and - * throws an exception if necessary. + * throws an exception if necessary. This variant is needed for enum conversions + * because we assume that enums fit into an int. * * Returns -1 if there was an error, 0 otherwise. */ @@ -799,11 +800,21 @@ int PyLong_to_integer_t(PyObject* obj, igraph_integer_t* v) { /* here the assumption is that sizeof(long long) == 64 bits; anyhow, this * is the widest integer type that we can convert a PyLong to so we cannot * do any better than this */ - *v = PyLong_AsLongLong(obj); + long long int dummy = PyLong_AsLongLong(obj); + if (PyErr_Occurred()) { + return 1; + } + *v = dummy; } else { - int dummy; - PyLong_AsInt(obj, &dummy); - *v = (igraph_integer_t)dummy; + /* this is either 32-bit igraph, or some weird, officially not-yet-supported + * igraph flavour. Let's try to be on the safe side and assume 32-bit. long + * ints are at least 32 bits so we will fit, otherwise Python will raise + * an OverflowError on its own */ + long int dummy = PyLong_AsLong(obj); + if (PyErr_Occurred()) { + return 1; + } + *v = dummy; } return 0; } @@ -2706,8 +2717,6 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph) { - int retval, tmp; - if (o == Py_None || o == 0) { *vid = 0; } else if (PyLong_Check(o)) { @@ -2727,20 +2736,19 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g PyObject* num = PyNumber_Index(o); if (num) { if (PyLong_Check(num)) { - retval = PyLong_AsInt(num, &tmp); - if (retval) { + if (igraphmodule_PyObject_to_integer_t(num, vid)) { Py_DECREF(num); return 1; } - *vid = tmp; } else { PyErr_SetString(PyExc_TypeError, "PyNumber_Index returned invalid type"); Py_DECREF(num); return 1; } Py_DECREF(num); - } else + } else { return 1; + } } else { PyErr_SetString(PyExc_TypeError, "only numbers, strings or igraph.Vertex objects can be converted to vertex IDs"); return 1; @@ -2921,7 +2929,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *graph) { - int retval, tmp; + int retval; igraph_integer_t vid1, vid2; if (o == Py_None || o == 0) { @@ -2939,35 +2947,38 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g PyObject* num = PyNumber_Index(o); if (num) { if (PyLong_Check(num)) { - retval = PyLong_AsInt(num, &tmp); - if (retval) { + if (igraphmodule_PyObject_to_integer_t(num, eid)) { Py_DECREF(num); return 1; } - *eid = tmp; } else { PyErr_SetString(PyExc_TypeError, "PyNumber_Index returned invalid type"); Py_DECREF(num); return 1; } Py_DECREF(num); - } else + } else { return 1; + } } else if (graph != 0 && PyTuple_Check(o)) { PyObject *o1, *o2; o1 = PyTuple_GetItem(o, 0); - if (!o1) + if (!o1) { return 1; + } - o2 = PyTuple_GetItem(o, 1); + o2 = PyTuple_GetItem(o, 1); { if (!o2) return 1; + } - if (igraphmodule_PyObject_to_vid(o1, &vid1, graph)) + if (igraphmodule_PyObject_to_vid(o1, &vid1, graph)) { return 1; - if (igraphmodule_PyObject_to_vid(o2, &vid2, graph)) + } + if (igraphmodule_PyObject_to_vid(o2, &vid2, graph)) { return 1; + } retval = igraph_get_eid(graph, eid, vid1, vid2, 1, 0); if (retval == IGRAPH_EINVVID) { diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 12139427a..0bbcdd2fa 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -44,8 +44,6 @@ typedef struct { int value; } igraphmodule_enum_translation_table_entry_t; -int PyLong_AsInt(PyObject* obj, int* result); - /* Conversion from PyObject to enum types */ int igraphmodule_PyObject_to_enum(PyObject *o, diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 6da7cb720..ba3d50186 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -601,17 +601,22 @@ static PyObject* _convert_to_edge_list(igraphmodule_VertexObject* vertex, PyObje for (i = 0; i < n; i++) { PyObject* idx = PyList_GET_ITEM(obj, i); PyObject* v; - int idx_int; + igraph_integer_t idx_int; if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_edge_list expected list of integers"); return NULL; } - if (PyLong_AsInt(idx, &idx_int)) + if (igraphmodule_PyObject_to_integer_t(idx, &idx_int)) { return NULL; + } v = igraphmodule_Edge_New(vertex->gref, idx_int); + if (!v) { + return NULL; + } + PyList_SetItem(obj, i, v); /* reference to v stolen, reference to idx discarded */ } @@ -633,17 +638,22 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb for (i = 0; i < n; i++) { PyObject* idx = PyList_GET_ITEM(obj, i); PyObject* v; - int idx_int; + igraph_integer_t idx_int; if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_vertex_list expected list of integers"); return NULL; } - if (PyLong_AsInt(idx, &idx_int)) + if (igraphmodule_PyObject_to_integer_t(idx, &idx_int)) { return NULL; + } v = igraphmodule_Vertex_New(vertex->gref, idx_int); + if (!v) { + return NULL; + } + PyList_SetItem(obj, i, v); /* reference to v stolen, reference to idx discarded */ } From 73686f07fde7f38ba33be89e10ab3de5157dcdc4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 15:01:04 +0200 Subject: [PATCH 0590/1892] refactor: eliminating PyLong_AsLong() in a few places --- src/_igraph/arpackobject.c | 19 ++++++++++++++----- src/_igraph/graphobject.c | 33 ++++++++++++++++++++------------- src/_igraph/indexing.c | 2 +- src/_igraph/vertexseqobject.c | 9 +++++++-- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index d10cc8d9d..5fa78d6f7 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -21,6 +21,7 @@ */ #include "arpackobject.h" +#include "convert.h" #include "graphobject.h" #include "error.h" @@ -120,6 +121,8 @@ PyObject* igraphmodule_ARPACKOptions_getattr( int igraphmodule_ARPACKOptions_setattr( igraphmodule_ARPACKOptionsObject* self, char* attrname, PyObject* value) { + igraph_integer_t igraph_int; + if (value == 0) { PyErr_SetString(PyExc_TypeError, "attribute can not be deleted"); return -1; @@ -127,10 +130,13 @@ int igraphmodule_ARPACKOptions_setattr( if (strcmp(attrname, "maxiter") == 0 || strcmp(attrname, "mxiter") == 0) { if (PyLong_Check(value)) { - long int n=PyLong_AsLong(value); - if (n>0) - self->params.mxiter=(igraph_integer_t)n; - else { + if (igraphmodule_PyObject_to_integer_t(value, &igraph_int)) { + return -1; + } + + if (igraph_int > 0) { + self->params.mxiter = igraph_int; + } else { PyErr_SetString(PyExc_ValueError, "maxiter must be positive"); return -1; } @@ -140,7 +146,10 @@ int igraphmodule_ARPACKOptions_setattr( } } else if (strcmp(attrname, "tol") == 0) { if (PyLong_Check(value)) { - self->params.tol = (igraph_real_t) PyLong_AsLong(value); + if (igraphmodule_PyObject_to_integer_t(value, &igraph_int)) { + return -1; + } + self->params.tol = igraph_int; } else if (PyFloat_Check(value)) { self->params.tol = (igraph_real_t) PyFloat_AsDouble(value); } else { diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 983230934..50b7d20ca 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2025,8 +2025,9 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, m = 1; + long n; float power = 1.0f, zero_appeal = 1.0f; + igraph_integer_t m = 1; igraph_vector_int_t outseq; igraph_t *start_from = 0; igraph_barabasi_algorithm_t algo = IGRAPH_BARABASI_PSUMTREE; @@ -2044,8 +2045,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, &start_from_o)) return NULL; - if (igraphmodule_PyObject_to_barabasi_algorithm_t(implementation_o, - &algo)) + if (igraphmodule_PyObject_to_barabasi_algorithm_t(implementation_o, &algo)) return NULL; if (igraphmodule_PyObject_to_igraph_t(start_from_o, &start_from)) @@ -2062,12 +2062,13 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, } else if (m_obj != 0) { /* let's check whether we have a constant out-degree or a list */ if (PyLong_Check(m_obj)) { - m = PyLong_AsLong(m_obj); + if (igraphmodule_PyObject_to_integer_t(m_obj, &m)) { + return NULL; + } igraph_vector_int_init(&outseq, 0); } else if (PyList_Check(m_obj)) { if (igraphmodule_PyObject_to_vector_int_t(m_obj, &outseq)) { - /* something bad happened during conversion */ - return NULL; + return NULL; } } else { PyErr_SetString(PyExc_TypeError, "m must be an integer or a list of integers"); @@ -2077,7 +2078,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, if (igraph_barabasi_game(&g, (igraph_integer_t) n, (igraph_real_t) power, - (igraph_integer_t) m, + m, &outseq, PyObject_IsTrue(outpref), (igraph_real_t) zero_appeal, PyObject_IsTrue(directed), algo, @@ -3174,8 +3175,9 @@ PyObject *igraphmodule_Graph_Recent_Degree(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, m = 0, window = 0; + long n, window = 0; float power = 0.0f, zero_appeal = 0.0f; + igraph_integer_t m = 0; igraph_vector_int_t outseq; PyObject *m_obj, *outpref = Py_False, *directed = Py_False; @@ -3195,7 +3197,9 @@ NULL }; // let's check whether we have a constant out-degree or a list if (PyLong_Check(m_obj)) { - m = PyLong_AsLong(m_obj); + if (igraphmodule_PyObject_to_integer_t(m_obj, &m)) { + return NULL; + } igraph_vector_int_init(&outseq, 0); } else if (PyList_Check(m_obj)) { @@ -3208,7 +3212,7 @@ NULL }; if (igraph_recent_degree_game(&g, (igraph_integer_t) n, (igraph_real_t) power, (igraph_integer_t) window, - (igraph_integer_t) m, &outseq, + m, &outseq, PyObject_IsTrue(outpref), (igraph_real_t) zero_appeal, PyObject_IsTrue(directed))) { @@ -6516,9 +6520,12 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s if (PyLong_Check(sample)) { /* samples chosen randomly */ - long int ns = PyLong_AsLong(sample); - if (igraph_motifs_randesu_estimate(&self->g, &result, (igraph_integer_t) size, - &cut_prob, (igraph_integer_t) ns, 0)) { + igraph_integer_t ns; + if (igraphmodule_PyObject_to_integer_t(sample, &ns)) { + igraph_vector_destroy(&cut_prob); + return NULL; + } + if (igraph_motifs_randesu_estimate(&self->g, &result, size, &cut_prob, ns, 0)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&cut_prob); return NULL; diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index 08cd04d95..3c05cb0f8 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -220,7 +220,7 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, */ static INLINE igraph_bool_t deleting_edge(PyObject* value) { return value == Py_None || value == Py_False || - (PyLong_Check(value) && PyLong_AsLong(value) == 0); + (PyLong_Check(value) && PyLong_AsLongLong(value) == 0); } /** diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 403f01a90..2299eb074 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -542,7 +542,7 @@ PyObject* igraphmodule_VertexSeq_find(igraphmodule_VertexSeqObject *self, PyObje /* Call the callable for every vertex in the current sequence and return * the first one for which it evaluates to True */ n = PySequence_Size((PyObject*)self); - for (i=0; igref->g, item, &i)) From 2df8ecabcf8a4d278dd7c6af891bc81af1dd97e7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 15:38:37 +0200 Subject: [PATCH 0591/1892] refactor: replaced long int with igraph_integer_t in attributes.c --- src/_igraph/attributes.c | 471 +++++++++++++++++++++------------------ 1 file changed, 250 insertions(+), 221 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index e74a296c4..d6e6a3440 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -287,44 +287,42 @@ PyObject* igraphmodule_create_or_get_edge_attribute_values(const igraph_t* graph /* Initialization */ static int igraphmodule_i_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) { igraphmodule_i_attribute_struct* attrs; - long int i, n; + igraph_integer_t i, n; - attrs=(igraphmodule_i_attribute_struct*)calloc(1, sizeof(igraphmodule_i_attribute_struct)); - if (!attrs) + attrs = (igraphmodule_i_attribute_struct*)calloc(1, sizeof(igraphmodule_i_attribute_struct)); + if (!attrs) { IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); + } if (igraphmodule_i_attribute_struct_init(attrs)) { PyErr_PrintEx(0); free(attrs); IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); } - graph->attr=(void*)attrs; + graph->attr = (void*)attrs; /* See if we have graph attributes */ if (attr) { - PyObject *dict=attrs->attrs[0], *value; + PyObject *dict = attrs->attrs[0], *value; char *s; n = igraph_vector_ptr_size(attr); - for (i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - value=PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]); + value = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]); break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s); - if (s == 0) - value=PyUnicode_FromString(""); - else - value=PyUnicode_FromString(s); + value = PyUnicode_FromString(s ? s : ""); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - value=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[0] ? Py_True : Py_False; + value = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[0] ? Py_True : Py_False; Py_INCREF(value); break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - value=0; + value = 0; break; } if (value) { @@ -336,7 +334,7 @@ static int igraphmodule_i_attribute_init(igraph_t *graph, igraph_vector_ptr_t *a IGRAPH_FAILURE); } Py_DECREF(value); - value=0; + value = 0; } } } @@ -350,7 +348,7 @@ static void igraphmodule_i_attribute_destroy(igraph_t *graph) { /* printf("Destroying attribute table\n"); */ if (graph->attr) { - attrs=(igraphmodule_i_attribute_struct*)graph->attr; + attrs = (igraphmodule_i_attribute_struct*)graph->attr; igraphmodule_i_attribute_struct_destroy(attrs); free(attrs); } @@ -362,8 +360,8 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, igraphmodule_i_attribute_struct *fromattrs, *toattrs; PyObject *key, *value, *newval, *o=NULL; igraph_bool_t copy_attrs[3] = { ga, va, ea }; - int i, j; - Py_ssize_t pos = 0; + int i; + Py_ssize_t j, pos = 0; if (from->attr) { fromattrs=ATTR_STRUCT(from); @@ -378,7 +376,7 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, } to->attr=toattrs; - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { if (!copy_attrs[i]) continue; @@ -391,15 +389,15 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, pos = 0; while (PyDict_Next(fromattrs->attrs[i], &pos, &key, &value)) { /* value is only borrowed, so copy it */ - if (i>0) { + if (i > 0) { newval=PyList_New(PyList_GET_SIZE(value)); - for (j=0; jattrs[i], key, newval); @@ -414,77 +412,90 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, igraph_vector_ptr_t *attr) { /* Extend the end of every value in the vertex hash with nv pieces of None */ PyObject *key, *value, *dict; - long int i, j, k, l; + igraph_integer_t i, j, k, l; igraph_attribute_record_t *attr_rec; igraph_bool_t *added_attrs=0; Py_ssize_t pos = 0; - if (!graph->attr) return IGRAPH_SUCCESS; - if (nv<0) return IGRAPH_SUCCESS; + if (!graph->attr) { + return IGRAPH_SUCCESS; + } + + if (nv < 0) { + return IGRAPH_SUCCESS; + } if (attr) { added_attrs = (igraph_bool_t*)calloc((size_t)igraph_vector_ptr_size(attr), sizeof(igraph_bool_t)); - if (!added_attrs) + if (!added_attrs) { IGRAPH_ERROR("can't add vertex attributes", IGRAPH_ENOMEM); + } IGRAPH_FINALLY(free, added_attrs); } - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; - if (!PyDict_Check(dict)) + dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; + if (!PyDict_Check(dict)) { IGRAPH_ERROR("vertex attribute hash type mismatch", IGRAPH_EINVAL); + } while (PyDict_Next(dict, &pos, &key, &value)) { - if (!PyList_Check(value)) + if (!PyList_Check(value)) { IGRAPH_ERROR("vertex attribute hash member is not a list", IGRAPH_EINVAL); + } + /* Check if we have specific values for the given attribute */ - attr_rec=0; + attr_rec = 0; if (attr) { - j=igraph_vector_ptr_size(attr); - for (i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - o=PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyUnicode_FromString(s); + o = PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; Py_INCREF(o); break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o=0; + o = 0; break; } if (o) { - if (PyList_Append(value, o) == -1) + if (PyList_Append(value, o) == -1) { IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); - else Py_DECREF(o); + } else { + Py_DECREF(o); + } } } /* Invalidate the vertex name index if needed */ - if (!strcmp(attr_rec->name, "name")) + if (!strcmp(attr_rec->name, "name")) { igraphmodule_i_attribute_struct_invalidate_vertex_name_index(ATTR_STRUCT(graph)); + } } else { - for (i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - o=PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyUnicode_FromString(s); + o = PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; Py_INCREF(o); break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o=0; + o = 0; break; } - if (o) PyList_SET_ITEM(value, i+j, o); + if (o) { + PyList_SET_ITEM(value, i + j, o); + } } /* Invalidate the vertex name index if needed */ - if (!strcmp(attr_rec->name, "name")) + if (!strcmp(attr_rec->name, "name")) { igraphmodule_i_attribute_struct_invalidate_vertex_name_index(ATTR_STRUCT(graph)); + } PyDict_SetItemString(dict, attr_rec->name, value); Py_DECREF(value); /* compensate for PyDict_SetItemString */ } + free(added_attrs); IGRAPH_FINALLY_CLEAN(1); } @@ -552,23 +569,27 @@ static int igraphmodule_i_attribute_add_vertices(igraph_t *graph, igraph_integer /* Permuting vertices */ static int igraphmodule_i_attribute_permute_vertices(const igraph_t *graph, igraph_t *newgraph, const igraph_vector_int_t *idx) { - long int n, i; + igraph_integer_t i, n; PyObject *key, *value, *dict, *newdict, *newlist, *o; - Py_ssize_t pos=0; + Py_ssize_t pos = 0; - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; - if (!PyDict_Check(dict)) return 1; + dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; + if (!PyDict_Check(dict)) { + return 1; + } - newdict=PyDict_New(); - if (!newdict) return 1; + newdict = PyDict_New(); + if (!newdict) { + return 1; + } - n=igraph_vector_int_size(idx); - pos=0; + n = igraph_vector_int_size(idx); + pos = 0; while (PyDict_Next(dict, &pos, &key, &value)) { - newlist=PyList_New(n); - for (i=0; iattr) return IGRAPH_SUCCESS; - if (ne<0) return IGRAPH_SUCCESS; - + if (!graph->attr) { + return IGRAPH_SUCCESS; + } + + ne = igraph_vector_int_size(edges) / 2; + if (ne < 0) { + return IGRAPH_SUCCESS; + } + if (attr) { added_attrs = (igraph_bool_t*)calloc((size_t)igraph_vector_ptr_size(attr), sizeof(igraph_bool_t)); - if (!added_attrs) + if (!added_attrs) { IGRAPH_ERROR("can't add vertex attributes", IGRAPH_ENOMEM); + } IGRAPH_FINALLY(free, added_attrs); } - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; - if (!PyDict_Check(dict)) + dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; + if (!PyDict_Check(dict)) { IGRAPH_ERROR("edge attribute hash type mismatch", IGRAPH_EINVAL); + } + while (PyDict_Next(dict, &pos, &key, &value)) { - if (!PyList_Check(value)) + if (!PyList_Check(value)) { IGRAPH_ERROR("edge attribute hash member is not a list", IGRAPH_EINVAL); + } /* Check if we have specific values for the given attribute */ - attr_rec=0; + attr_rec = 0; if (attr) { - j=igraph_vector_ptr_size(attr); - for (i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - o=PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyUnicode_FromString(s); + o = PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; Py_INCREF(o); break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o=0; + o = 0; break; } if (o) { - if (PyList_Append(value, o) == -1) + if (PyList_Append(value, o) == -1) { IGRAPH_ERROR("can't extend an edge attribute hash member", IGRAPH_FAILURE); - else Py_DECREF(o); + } else { + Py_DECREF(o); + } } } } else { - for (i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - o=PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); break; case IGRAPH_ATTRIBUTE_STRING: igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s); - o=PyUnicode_FromString(s); + o = PyUnicode_FromString(s); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - o=VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; Py_INCREF(o); break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o=0; + o = 0; break; } - if (o) PyList_SET_ITEM(value, i+j, o); + if (o) { + PyList_SET_ITEM(value, i + j, o); + } } PyDict_SetItemString(dict, attr_rec->name, value); @@ -728,65 +764,30 @@ static int igraphmodule_i_attribute_add_edges(igraph_t *graph, const igraph_vect return IGRAPH_SUCCESS; } -/* Deleting edges, currently unused */ -/* -static void igraphmodule_i_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) { - long int n, i, ndeleted=0; - PyObject *key, *value, *dict, *o; - Py_ssize_t pos=0; - - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; - if (!PyDict_Check(dict)) return; - - n=igraph_vector_size(idx); - for (i=0; i0) { + if (attrnum > 0) { - for (i=0; i Date: Thu, 9 Sep 2021 16:02:59 +0200 Subject: [PATCH 0592/1892] refactor: centralized the code that determines what is acceptable in an igraph bool/numeric/string attribute --- src/_igraph/attributes.c | 45 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index d6e6a3440..8da624063 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -26,6 +26,18 @@ #include "convert.h" #include "pyhelpers.h" +static inline int PyObject_allowed_in_boolean_attribute(PyObject* o) { + return o == Py_None || o == Py_False || o == Py_True; +} + +static inline int PyObject_allowed_in_numeric_attribute(PyObject* o) { + return o == Py_None || PyNumber_Check(o); +} + +static inline int PyObject_allowed_in_string_attribute(PyObject* o) { + return o == Py_None || PyBaseString_Check(o); +} + int igraphmodule_i_attribute_struct_init(igraphmodule_i_attribute_struct *attrs) { int i; for (i=0; i<3; i++) { @@ -1359,31 +1371,28 @@ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, if (PyList_Check(values)) { m = PyList_Size(values); for (l = 0; l < m && is_numeric; l++) { - o = PyList_GetItem(values, l); - if (o != Py_None && !PyNumber_Check(o)) { - is_numeric=0; + if (!PyObject_allowed_in_numeric_attribute(PyList_GetItem(values, l))) { + is_numeric = 0; } } for (l = 0; l < m && is_string; l++) { - o = PyList_GetItem(values, l); - if (o != Py_None && !PyBaseString_Check(o)) { + if (!PyObject_allowed_in_string_attribute(PyList_GetItem(values, l))) { is_string = 0; } } for (l = 0; l < m && is_boolean; l++) { - o = PyList_GetItem(values, l); - if (o != Py_None && o != Py_False && o != Py_True) { + if (!PyObject_allowed_in_boolean_attribute(PyList_GetItem(values, l))) { is_boolean = 0; } } } else { - if (values != Py_None && !PyNumber_Check(values)) { + if (!PyObject_allowed_in_numeric_attribute(values)) { is_numeric = 0; } - if (values != Py_None && !PyBaseString_Check(values)) { + if (!PyObject_allowed_in_string_attribute(values)) { is_string = 0; } - if (values != Py_None && values != Py_False && values != Py_True) { + if (!PyObject_allowed_in_boolean_attribute(values)) { is_boolean = 0; } } @@ -1461,33 +1470,29 @@ int igraphmodule_i_attribute_get_type(const igraph_t *graph, /* Go on with the checks */ is_numeric = is_string = is_boolean = 1; if (attrnum > 0) { - for (i = 0; i < j && is_numeric; i++) { - PyObject *item = PyList_GET_ITEM(o, i); - if (item != Py_None && !PyNumber_Check(item)) { + if (!PyObject_allowed_in_numeric_attribute(PyList_GET_ITEM(o, i))) { is_numeric = 0; } } for (i = 0; i < j && is_string; i++) { - PyObject *item = PyList_GET_ITEM(o, i); - if (item != Py_None && !PyBaseString_Check(item)) { + if (!PyObject_allowed_in_string_attribute(PyList_GET_ITEM(o, i))) { is_string = 0; } } for (i = 0; i < j && is_boolean; i++) { - PyObject *item = PyList_GET_ITEM(o, i); - if (item != Py_None && item != Py_True && item != Py_False) { + if (!PyObject_allowed_in_boolean_attribute(PyList_GET_ITEM(o, i))) { is_boolean = 0; } } } else { - if (o != Py_None && !PyNumber_Check(o)) { + if (!PyObject_allowed_in_numeric_attribute(o)) { is_numeric = 0; } - if (o != Py_None && !PyBaseString_Check(o)) { + if (!PyObject_allowed_in_string_attribute(o)) { is_string = 0; } - if (o != Py_None && o != Py_True && o != Py_False) { + if (!PyObject_allowed_in_boolean_attribute(o)) { is_boolean = 0; } } From 46e379fa22b79a1591dc3396904fa2b4db5478c1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 16:16:08 +0200 Subject: [PATCH 0593/1892] fix: use platform-independent inline declaration --- src/_igraph/attributes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 8da624063..d005993aa 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -24,17 +24,18 @@ #include "attributes.h" #include "common.h" #include "convert.h" +#include "platform.h" #include "pyhelpers.h" -static inline int PyObject_allowed_in_boolean_attribute(PyObject* o) { +static INLINE int PyObject_allowed_in_boolean_attribute(PyObject* o) { return o == Py_None || o == Py_False || o == Py_True; } -static inline int PyObject_allowed_in_numeric_attribute(PyObject* o) { +static INLINE int PyObject_allowed_in_numeric_attribute(PyObject* o) { return o == Py_None || PyNumber_Check(o); } -static inline int PyObject_allowed_in_string_attribute(PyObject* o) { +static INLINE int PyObject_allowed_in_string_attribute(PyObject* o) { return o == Py_None || PyBaseString_Check(o); } From cbb0f9a249f766134ed471c39f585c857e5b97ea Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 16:16:32 +0200 Subject: [PATCH 0594/1892] refactor: getting rid of (int) casts --- src/_igraph/convert.c | 49 ++++++++++++++++++++++++++++---------- src/_igraph/edgeobject.c | 32 ++++++++++++------------- src/_igraph/graphobject.c | 4 ++-- src/_igraph/vertexobject.c | 32 ++++++++++++------------- 4 files changed, 70 insertions(+), 47 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 0571cc706..38b994356 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -58,7 +58,7 @@ int PyLong_AsInt(PyObject* obj, int* result) { PyErr_SetString(PyExc_OverflowError, "long integer too large for conversion to C int"); return -1; } - *result = (int)dummy; + *result = dummy; return 0; } @@ -379,17 +379,25 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, igraphmodule_PyObject_to_enum(value, eigen_which_position_tt, (int*) &w->pos); } else if (!strcasecmp(kv, "howmany")) { - w->howmany = (int) PyLong_AsLong(value); + if (PyLong_AsInt(value, &w->howmany)) { + return -1; + } } else if (!strcasecmp(kv, "il")) { - w->il = (int) PyLong_AsLong(value); + if (PyLong_AsInt(value, &w->il)) { + return -1; + } } else if (!strcasecmp(kv, "iu")) { - w->iu = (int) PyLong_AsLong(value); + if (PyLong_AsInt(value, &w->iu)) { + return -1; + } } else if (!strcasecmp(kv, "vl")) { w->vl = PyFloat_AsDouble(value); } else if (!strcasecmp(kv, "vu")) { w->vu = PyFloat_AsDouble(value); } else if (!strcasecmp(kv, "vestimate")) { - w->vestimate = (int) PyLong_AsLong(value); + if (PyLong_AsInt(value, &w->vestimate)) { + return -1; + } } else if (!strcasecmp(kv, "balance")) { igraphmodule_PyObject_to_enum(value, lapack_dgeevc_balance_tt, (int*) &w->balance); @@ -1843,43 +1851,58 @@ int igraphmodule_attrib_to_vector_int_t(PyObject *o, igraphmodule_GraphObject *s if (PyUnicode_Check(o)) { igraph_vector_t* dummy = 0; - long int i, n; + igraph_integer_t i, n; - if (igraphmodule_attrib_to_vector_t(o, self, &dummy, attr_type)) + if (igraphmodule_attrib_to_vector_t(o, self, &dummy, attr_type)) { return 1; + } - if (dummy == 0) + if (dummy == 0) { return 0; + } n = igraph_vector_size(dummy); result = (igraph_vector_int_t*)calloc(1, sizeof(igraph_vector_int_t)); - igraph_vector_int_init(result, n); - if (result==0) { + if (result == 0) { igraph_vector_destroy(dummy); free(dummy); PyErr_NoMemory(); return 1; } - for (i=0; ig), i; - result=PyList_New(n); - for (i=0; ig); + result = PyList_New(n); + for (i = 0; i < n; i++) { if (i != self->idx) { - Py_INCREF(Py_None); - if (PyList_SetItem(result, i, Py_None) == -1) { - Py_DECREF(Py_None); - Py_DECREF(result); - return -1; - } + Py_INCREF(Py_None); + if (PyList_SetItem(result, i, Py_None) == -1) { + Py_DECREF(Py_None); + Py_DECREF(result); + return -1; + } } else { - /* Same game with the reference count here */ - Py_INCREF(v); - if (PyList_SetItem(result, i, v) == -1) { - Py_DECREF(v); - Py_DECREF(result); - return -1; - } + /* Same game with the reference count here */ + Py_INCREF(v); + if (PyList_SetItem(result, i, v) == -1) { + Py_DECREF(v); + Py_DECREF(result); + return -1; + } } } if (PyDict_SetItem(((PyObject**)o->g.attr)[2], k, result) == -1) { diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 50b7d20ca..e507d2e78 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -9619,7 +9619,7 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, } if (igraph_subisomorphic_lad(&other->g, &self->g, p_domains, &result, - map, 0, PyObject_IsTrue(induced), (int)time_limit)) { + map, 0, PyObject_IsTrue(induced), (igraph_integer_t) time_limit)) { if (p_domains) igraph_vector_ptr_destroy_all(p_domains); igraphmodule_handle_igraph_error(); @@ -9681,7 +9681,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_lad( } if (igraph_subisomorphic_lad(&other->g, &self->g, p_domains, 0, 0, &mappings, - PyObject_IsTrue(induced), (int)time_limit)) { + PyObject_IsTrue(induced), (igraph_integer_t) time_limit)) { igraphmodule_handle_igraph_error(); igraph_vector_ptr_destroy_all(&mappings); if (p_domains) diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index ba3d50186..041761634 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -514,24 +514,24 @@ int igraphmodule_Vertex_set_attribute(igraphmodule_VertexObject* self, PyObject* /* result is NULL, check whether there was an error */ if (!PyErr_Occurred()) { /* no, there wasn't, so we must simply add the attribute */ - int n=(int)igraph_vcount(&o->g), i; - result=PyList_New(n); - for (i=0; ig); + result = PyList_New(n); + for (i = 0; i < n; i++) { if (i != self->idx) { - Py_INCREF(Py_None); - if (PyList_SetItem(result, i, Py_None) == -1) { - Py_DECREF(Py_None); - Py_DECREF(result); - return -1; - } + Py_INCREF(Py_None); + if (PyList_SetItem(result, i, Py_None) == -1) { + Py_DECREF(Py_None); + Py_DECREF(result); + return -1; + } } else { - /* Same game with the reference count here */ - Py_INCREF(v); - if (PyList_SetItem(result, i, v) == -1) { - Py_DECREF(v); - Py_DECREF(result); - return -1; - } + /* Same game with the reference count here */ + Py_INCREF(v); + if (PyList_SetItem(result, i, v) == -1) { + Py_DECREF(v); + Py_DECREF(result); + return -1; + } } } if (PyDict_SetItem(((PyObject**)o->g.attr)[1], k, result) == -1) { From 2d2f97a63e00b3682251030e1225be124ca40a15 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 16:16:48 +0200 Subject: [PATCH 0595/1892] fix: make sure that the user cannot link a 64-bit igraph to a 32-bit Python instance --- src/_igraph/igraphmodule.c | 4 ++++ src/_igraph/pyhelpers.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index bdc0eda59..7e3c2b0c2 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -33,6 +33,7 @@ #include "edgeseqobject.h" #include "error.h" #include "graphobject.h" +#include "pyhelpers.h" #include "random.h" #include "vertexobject.h" #include "vertexseqobject.h" @@ -808,6 +809,9 @@ PyObject* PyInit__igraph(void) static void *PyIGraph_API[PyIGraph_API_pointers]; PyObject *c_api_object; + /* Prevent linking 64-bit igraph to 32-bit Python */ + PY_IGRAPH_ASSERT_AT_BUILD_TIME(sizeof(igraph_integer_t) >= sizeof(Py_ssize_t)); + /* Check if the module is already initialized (possibly in another Python * interpreter. If so, bail out as we don't support this. */ if (igraphmodule_initialized) { diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 00bff1d86..2bb848834 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -40,6 +40,8 @@ long igraphmodule_Py_HashPointer(void *p); (PyUnicode_CompareWithASCIIString(uni, string) == 0) char* PyUnicode_CopyAsString(PyObject* string); +#define PY_IGRAPH_ASSERT_AT_BUILD_TIME(condition) \ + ((void)sizeof(char[1 - 2*!(condition)])) #define PY_IGRAPH_DEPRECATED(msg) \ PyErr_WarnEx(PyExc_DeprecationWarning, (msg), 1) #define PY_IGRAPH_WARN(msg) \ From 935ff19461ccbb7d10665095c0c9d41007390711 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 21:29:39 +0200 Subject: [PATCH 0596/1892] refactor: long int to Py_ssize_t replacements --- src/_igraph/attributes.c | 3 +- src/_igraph/convert.c | 18 ++-- src/_igraph/graphobject.c | 180 +++++++++++++++++----------------- src/_igraph/igraphmodule.c | 10 +- src/_igraph/indexing.c | 11 +-- src/_igraph/pyhelpers.h | 22 +++++ src/_igraph/vertexseqobject.c | 16 +-- tests/test_generators.py | 2 +- 8 files changed, 146 insertions(+), 116 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index d005993aa..ac6b0f717 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1341,13 +1341,12 @@ static int igraphmodule_i_attribute_get_info(const igraph_t *graph, int i, retval; Py_ssize_t j, k, l, m; - for (i=0; i<3; i++) { + for (i = 0; i < 3; i++) { igraph_strvector_t *n = names[i]; igraph_vector_int_t *t = types[i]; PyObject *dict = ATTR_STRUCT_DICT(graph)[i]; PyObject *keys; PyObject *values; - PyObject *o = 0; keys = PyDict_Keys(dict); if (!keys) { diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 38b994356..176f8a23f 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2373,7 +2373,7 @@ int igraphmodule_PyList_to_matrix_int_t(PyObject* o, igraph_matrix_int_t *m) { int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols) { Py_ssize_t nr, nc, n, i, j; PyObject *row, *item; - int was_warned = 0; + int ok, was_warned = 0; /* calculate the matrix dimensions */ if (!PySequence_Check(o) || PyUnicode_Check(o)) { @@ -2403,16 +2403,22 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i n = PySequence_Size(row); for (j = 0; j < n; j++) { item = PySequence_GetItem(row, j); + ok = 1; if (PyLong_Check(item)) { - MATRIX(*m, i, j) = (igraph_integer_t)PyLong_AsLong(item); - } else if (PyLong_Check(item)) { - MATRIX(*m, i, j) = (igraph_integer_t)PyLong_AsLong(item); + if (igraphmodule_PyObject_to_integer_t(item, &MATRIX(*m, i, j))) { + ok = 0; + } } else if (PyFloat_Check(item)) { MATRIX(*m, i, j) = (igraph_integer_t)PyFloat_AsDouble(item); - } else if (!was_warned) { + } else { + ok = 0; + } + + if (!ok && !was_warned) { PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); - was_warned=1; + was_warned = 1; } + Py_DECREF(item); } Py_DECREF(row); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e507d2e78..ac8f89b5c 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -201,13 +201,13 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) int igraphmodule_Graph_init(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "n", "edges", "directed", "__ptr", NULL }; - long int n = 0; PyObject *edges = NULL, *dir = Py_False, *ptr_o = 0; void* ptr = 0; + Py_ssize_t n = 0; igraph_vector_int_t edges_vector; igraph_bool_t edges_vector_owned = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOOO!", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nOOO!", kwlist, &n, &edges, &dir, &PyCapsule_Type, &ptr_o)) return -1; @@ -222,6 +222,15 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, return -1; } + if (n < 0) { + PyErr_SetString(PyExc_OverflowError, "vertex count must be non-negative"); + return -1; + } + if (n > IGRAPH_INTEGER_MAX) { + PyErr_SetString(PyExc_OverflowError, "vertex count too large"); + return -1; + } + if (ptr_o) { /* We must take ownership of an igraph graph */ ptr = PyCapsule_GetPointer(ptr_o, "__igraph_t"); @@ -238,8 +247,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, return -1; } - if (igraph_create - (&self->g, &edges_vector, (igraph_integer_t) n, PyObject_IsTrue(dir))) { + if (igraph_create(&self->g, &edges_vector, n, PyObject_IsTrue(dir))) { igraphmodule_handle_igraph_error(); if (edges_vector_owned) { igraph_vector_int_destroy(&edges_vector); @@ -253,7 +261,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, } else { /* No edge list was specified, and no previously initialized graph object * was fed into our object, so let's use igraph_empty */ - if (igraph_empty(&self->g, (igraph_integer_t) n, PyObject_IsTrue(dir))) { + if (igraph_empty(&self->g, n, PyObject_IsTrue(dir))) { igraphmodule_handle_igraph_error(); return -1; } @@ -575,12 +583,15 @@ PyObject *igraphmodule_Graph_is_tree(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_add_vertices(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - long n; + Py_ssize_t n; - if (!PyArg_ParseTuple(args, "l", &n)) + if (!PyArg_ParseTuple(args, "n", &n)) { return NULL; + } + + CHECK_SSIZE_T_RANGE(n, "vertex count"); - if (igraph_add_vertices(&self->g, (igraph_integer_t) n, 0)) { + if (igraph_add_vertices(&self->g, n, 0)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -605,15 +616,16 @@ PyObject *igraphmodule_Graph_delete_vertices(igraphmodule_GraphObject * self, /* no arguments means delete all. */ - /*Py_None also means all for now, but it is deprecated */ + /* Py_None used to mean 'all', but not any more */ if (list == Py_None) { - PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " - "deprecated since igraph 0.8.3, please use " - "Graph.delete_vertices() instead"); + PyErr_SetString(PyExc_ValueError, "expected number of vertices to delete, got None"); + return NULL; } - /* this already converts no arguments and Py_None to all vertices */ - if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, 0, 0)) return NULL; + /* this already converts no arguments to all vertices */ + if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, 0, 0)) { + return NULL; + } if (igraph_delete_vertices(&self->g, vs)) { igraphmodule_handle_igraph_error(); @@ -1994,14 +2006,15 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, */ PyObject *igraphmodule_Graph_Atlas(PyTypeObject * type, PyObject * args) { - long n; + Py_ssize_t n; igraphmodule_GraphObject *self; igraph_t g; - if (!PyArg_ParseTuple(args, "l", &n)) + if (!PyArg_ParseTuple(args, "n", &n)) { return NULL; + } - if (igraph_atlas(&g, (igraph_integer_t) n)) { + if (igraph_atlas(&g, n)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2025,7 +2038,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n; + Py_ssize_t n; float power = 1.0f, zero_appeal = 1.0f; igraph_integer_t m = 1; igraph_vector_int_t outseq; @@ -2039,7 +2052,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, { "n", "m", "outpref", "directed", "power", "zero_appeal", "implementation", "start_from", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|OOOffOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OOOffOO", kwlist, &n, &m_obj, &outpref, &directed, &power, &zero_appeal, &implementation_o, &start_from_o)) @@ -2051,10 +2064,7 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, if (igraphmodule_PyObject_to_igraph_t(start_from_o, &start_from)) return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "vertex count"); if (m_obj == 0) { igraph_vector_int_init(&outseq, 0); @@ -2076,11 +2086,9 @@ PyObject *igraphmodule_Graph_Barabasi(PyTypeObject * type, } } - if (igraph_barabasi_game(&g, (igraph_integer_t) n, - (igraph_real_t) power, - m, + if (igraph_barabasi_game(&g, n, power, m, &outseq, PyObject_IsTrue(outpref), - (igraph_real_t) zero_appeal, + zero_appeal, PyObject_IsTrue(directed), algo, start_from)) { igraphmodule_handle_igraph_error(); @@ -2149,15 +2157,18 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, */ PyObject *igraphmodule_Graph_De_Bruijn(PyTypeObject *type, PyObject *args, PyObject *kwds) { - long int m, n; + Py_ssize_t m, n; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = {"m", "n", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll", kwlist, &m, &n)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn", kwlist, &m, &n)) return NULL; - if (igraph_de_bruijn(&g, (igraph_integer_t) m, (igraph_integer_t) n)) { + CHECK_SSIZE_T_RANGE(m, "alphabet size (m)"); + CHECK_SSIZE_T_RANGE(n, "label length (n)"); + + if (igraph_de_bruijn(&g, m, n)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2231,19 +2242,22 @@ PyObject *igraphmodule_Graph_Erdos_Renyi(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, m = -1; + Py_ssize_t n, m = -1; double p = -1.0; igraph_erdos_renyi_t t; PyObject *loops = Py_False, *directed = Py_False; static char *kwlist[] = { "n", "p", "m", "directed", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|dlOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|dnOO", kwlist, &n, &p, &m, &directed, &loops)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE((m < 0 ? 0 : m), "edge count"); + if (m == -1 && p == -1.0) { /* no density parameters were given, throw exception */ PyErr_SetString(PyExc_TypeError, "Either m or p must be given."); @@ -2257,8 +2271,7 @@ PyObject *igraphmodule_Graph_Erdos_Renyi(PyTypeObject * type, t = (m == -1) ? IGRAPH_ERDOS_RENYI_GNP : IGRAPH_ERDOS_RENYI_GNM; - if (igraph_erdos_renyi_game(&g, t, (igraph_integer_t) n, - (igraph_real_t) (m == -1 ? p : m), + if (igraph_erdos_renyi_game(&g, t, n, (m == -1 ? p : m), PyObject_IsTrue(directed), PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); @@ -2280,7 +2293,7 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, types, k; + Py_ssize_t n, types, k; PyObject *type_dist, *pref_matrix; PyObject *directed = Py_False; igraph_matrix_t pm; @@ -2288,7 +2301,7 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, char *kwlist[] = { "n", "k", "type_dist", "pref_matrix", "directed", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "llO!O!|O", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nnO!O!|O", kwlist, &n, &k, &PyList_Type, &type_dist, &PyList_Type, &pref_matrix, &directed)) return NULL; @@ -2298,6 +2311,10 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, "Number of vertices and the amount of connection trials per step must be positive."); return NULL; } + + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(k, "connection trials per set"); + types = PyList_Size(type_dist); if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) { @@ -2319,10 +2336,7 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, return NULL; } - if (igraph_establishment_game(&g, (igraph_integer_t) n, - (igraph_integer_t) types, - (igraph_integer_t) k, &td, &pm, - PyObject_IsTrue(directed), 0)) { + if (igraph_establishment_game(&g, n, types, k, &td, &pm, PyObject_IsTrue(directed), 0)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&pm); igraph_vector_destroy(&td); @@ -2374,20 +2388,20 @@ PyObject *igraphmodule_Graph_Forest_Fire(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, ambs=1; + Py_ssize_t n, ambs = 1; double fw_prob, bw_factor=0.0; PyObject *directed = Py_False; static char *kwlist[] = {"n", "fw_prob", "bw_factor", "ambs", "directed", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ld|dlO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nd|dnO", kwlist, &n, &fw_prob, &bw_factor, &ambs, &directed)) return NULL; - if (igraph_forest_fire_game(&g, (igraph_integer_t)n, - (igraph_real_t)fw_prob, (igraph_real_t)bw_factor, - (igraph_integer_t)ambs, - (igraph_bool_t)(PyObject_IsTrue(directed)))) { + CHECK_SSIZE_T_RANGE(n, "number of nodes"); + CHECK_SSIZE_T_RANGE(n, "number of ambassadors"); + + if (igraph_forest_fire_game(&g, n, fw_prob, bw_factor, ambs, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2408,22 +2422,17 @@ PyObject *igraphmodule_Graph_Full(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n; + Py_ssize_t n; PyObject *loops = Py_False, *directed = Py_False; char *kwlist[] = { "n", "directed", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|OO", kwlist, &n, - &directed, &loops)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OO", kwlist, &n, &directed, &loops)) return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "number of nodes"); - if (igraph_full(&g, (igraph_integer_t) n, PyObject_IsTrue(directed), - PyObject_IsTrue(loops))) { + if (igraph_full(&g, n, PyObject_IsTrue(directed), PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2444,31 +2453,28 @@ PyObject *igraphmodule_Graph_Full_Bipartite(PyTypeObject * type, igraph_t g; igraph_vector_bool_t vertex_types; igraph_neimode_t mode = IGRAPH_ALL; - long int n1, n2; + Py_ssize_t n1, n2; PyObject *mode_o = Py_None, *directed = Py_False, *vertex_types_o = 0; static char *kwlist[] = { "n1", "n2", "directed", "mode", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|OO", kwlist, &n1, &n2, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|OO", kwlist, &n1, &n2, &directed, &mode_o)) return NULL; - if (n1 < 0 || n2 < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); + CHECK_SSIZE_T_RANGE(n1, "number of vertices in first partition"); + CHECK_SSIZE_T_RANGE(n2, "number of vertices in second partition"); + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; } - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) - return NULL; - if (igraph_vector_bool_init(&vertex_types, n1+n2)) { igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_full_bipartite(&g, &vertex_types, - (igraph_integer_t) n1, (igraph_integer_t) n2, - PyObject_IsTrue(directed), mode)) { + if (igraph_full_bipartite(&g, &vertex_types, n1, n2, PyObject_IsTrue(directed), mode)) { igraph_vector_bool_destroy(&vertex_types); igraphmodule_handle_igraph_error(); return NULL; @@ -2492,16 +2498,17 @@ PyObject *igraphmodule_Graph_Full_Citation(PyTypeObject *type, { igraphmodule_GraphObject *self; igraph_t g; - long n; + Py_ssize_t n; PyObject *directed = Py_False; char *kwlist[] = { "n", "directed", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O", kwlist, &n, &directed)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|O", kwlist, &n, &directed)) return NULL; - if (igraph_full_citation(&g, (igraph_integer_t) n, - (igraph_bool_t) PyObject_IsTrue(directed))) { + CHECK_SSIZE_T_RANGE(n, "vertex count"); + + if (igraph_full_citation(&g, n, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2521,7 +2528,7 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n; + Py_ssize_t n; double r; PyObject *torus = Py_False; PyObject *o_xs, *o_ys; @@ -2529,7 +2536,7 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, static char *kwlist[] = { "n", "radius", "torus", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ld|O", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nd|O", kwlist, &n, &r, &torus)) return NULL; @@ -2542,8 +2549,9 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, return NULL; } - if (igraph_grg_game(&g, (igraph_integer_t) n, (igraph_real_t) r, - PyObject_IsTrue(torus), &xs, &ys)) { + CHECK_SSIZE_T_RANGE(n, "vertex count"); + + if (igraph_grg_game(&g, n, r, PyObject_IsTrue(torus), &xs, &ys)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&xs); igraph_vector_destroy(&ys); @@ -2557,6 +2565,7 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, igraph_vector_destroy(&ys); return NULL; } + o_ys = igraphmodule_vector_t_to_PyList(&ys, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&ys); if (!o_ys) { @@ -2566,6 +2575,7 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, } CREATE_GRAPH_FROM_TYPE(self, g, type); + return Py_BuildValue("NNN", (PyObject*)self, o_xs, o_ys); } @@ -2577,33 +2587,21 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, PyObject *igraphmodule_Graph_Growing_Random(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long n, m; - PyObject *directed = NULL, *citation = NULL; + Py_ssize_t n, m; + PyObject *directed = Py_False, *citation = Py_False; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "m", "directed", "citation", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O!O!", kwlist, &n, &m, - &PyBool_Type, &directed, - &PyBool_Type, &citation)) - return NULL; - - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|OO", kwlist, &n, &m, &directed, &citation)) { return NULL; } - if (m < 0) { - PyErr_SetString(PyExc_ValueError, - "Number of new edges per iteration must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE_POSITIVE(m, "number of new edges per iteration"); - if (igraph_growing_random_game(&g, (igraph_integer_t) n, - (igraph_integer_t) m, - (directed == Py_True), - (citation == Py_True))) { + if (igraph_growing_random_game(&g, n, m, PyObject_IsTrue(directed), PyObject_IsTrue(citation))) { igraphmodule_handle_igraph_error(); return NULL; } diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 7e3c2b0c2..8c08de894 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -332,13 +332,16 @@ PyObject* igraphmodule_community_to_membership(PyObject *self, PyObject *merges_o, *return_csize = Py_False, *result_o; igraph_matrix_int_t merges; igraph_vector_int_t result, csize, *csize_p = 0; - long int nodes, steps; + Py_ssize_t nodes, steps; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!ll|O", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!nn|O", kwlist, &PyList_Type, &merges_o, &nodes, &steps, &return_csize)) return NULL; if (igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(merges_o, &merges, 2)) return NULL; + CHECK_SSIZE_T_RANGE(nodes, "number of nodes"); + CHECK_SSIZE_T_RANGE(steps, "number of steps"); + if (igraph_vector_int_init(&result, nodes)) { igraphmodule_handle_igraph_error(); igraph_matrix_int_destroy(&merges); @@ -350,8 +353,7 @@ PyObject* igraphmodule_community_to_membership(PyObject *self, csize_p = &csize; } - if (igraph_community_to_membership(&merges, (igraph_integer_t)nodes, - (igraph_integer_t)steps, &result, csize_p)) { + if (igraph_community_to_membership(&merges, nodes, steps, &result, csize_p)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&result); if (csize_p) igraph_vector_int_destroy(csize_p); diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index 3c05cb0f8..70b76ef94 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -134,11 +134,9 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, igraph_integer_t from, igraph_vs_t* to, igraph_neimode_t neimode, PyObject* values) { igraph_vector_int_t eids; - igraph_integer_t eid; + igraph_integer_t eid, i, n, v; igraph_vit_t vit; PyObject *result = 0, *item; - long int i, n; - igraph_integer_t v; if (igraph_vs_is_all(to)) { /* Simple case: all edges */ @@ -154,12 +152,13 @@ static PyObject* igraphmodule_i_Graph_adjmatrix_get_index_row(igraph_t* graph, } for (i = 0; i < n; i++) { - eid = (igraph_integer_t)VECTOR(eids)[i]; + eid = VECTOR(eids)[i]; v = IGRAPH_OTHER(graph, eid, from); - if (values) + if (values) { item = PyList_GetItem(values, eid); - else + } else { item = PyLong_FromLong(1); + } Py_INCREF(item); PyList_SetItem(result, v, item); /* reference stolen here */ } diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 2bb848834..01cc689eb 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -47,4 +47,26 @@ char* PyUnicode_CopyAsString(PyObject* string); #define PY_IGRAPH_WARN(msg) \ PyErr_WarnEx(PyExc_RuntimeWarning, (msg), 1) +#define CHECK_SSIZE_T_RANGE(value, message) { \ + if ((value) < 0) { \ + PyErr_SetString(PyExc_ValueError, message " must be non-negative"); \ + return NULL; \ + } \ + if ((value) > IGRAPH_INTEGER_MAX) { \ + PyErr_SetString(PyExc_OverflowError, message " too large"); \ + return NULL; \ + } \ +} + +#define CHECK_SSIZE_T_RANGE_POSITIVE(value, message) { \ + if ((value) <= 0) { \ + PyErr_SetString(PyExc_ValueError, message " must be positive"); \ + return NULL; \ + } \ + if ((value) > IGRAPH_INTEGER_MAX) { \ + PyErr_SetString(PyExc_OverflowError, message " too large"); \ + return NULL; \ + } \ +} + #endif diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 2299eb074..717b080c7 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -127,7 +127,7 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, return -1; } - igraph_vs_1(&vs, (igraph_integer_t)idx); + igraph_vs_1(&vs, idx); } else { igraph_vector_int_t v; igraph_integer_t n = igraph_vcount(&((igraphmodule_GraphObject*)g)->g); @@ -199,15 +199,19 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, igraph_t *g; igraph_integer_t idx = -1; - if (!self->gref) return NULL; - g=&GET_GRAPH(self); + if (!self->gref) { + return NULL; + } + + g = &GET_GRAPH(self); + switch (igraph_vs_type(&self->vs)) { case IGRAPH_VS_ALL: if (i < 0) { i = igraph_vcount(g) + i; } if (i >= 0 && i < igraph_vcount(g)) { - idx = (igraph_integer_t)i; + idx = i; } break; case IGRAPH_VS_VECTOR: @@ -216,7 +220,7 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, i = igraph_vector_int_size(self->vs.data.vecptr) + i; } if (i >= 0 && i < igraph_vector_int_size(self->vs.data.vecptr)) { - idx = (igraph_integer_t)VECTOR(*self->vs.data.vecptr)[i]; + idx = VECTOR(*self->vs.data.vecptr)[i]; } break; case IGRAPH_VS_1: @@ -231,7 +235,7 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, i = self->vs.data.seq.to - self->vs.data.seq.from + i; } if (i >= 0 && i < self->vs.data.seq.to - self->vs.data.seq.from) { - idx = self->vs.data.seq.from + (igraph_integer_t)i; + idx = self->vs.data.seq.from + i; } break; /* TODO: IGRAPH_VS_ADJ, IGRAPH_VS_NONADJ - someday :) They are unused diff --git a/tests/test_generators.py b/tests/test_generators.py index 576ca5b98..ac55a3b78 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -127,7 +127,7 @@ def testFullCitation(self): self.assertTrue(g.is_directed()) self.assertTrue(el == [(x, y) for x in range(1, 20) for y in range(x)]) - self.assertRaises(InternalError, Graph.Full_Citation, -2) + self.assertRaises(ValueError, Graph.Full_Citation, -2) def testLCF(self): g1 = Graph.LCF(12, (5, -5), 6) From d0e70d421f08a5280d12e2081196a7e09a2a62e4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 22:05:52 +0200 Subject: [PATCH 0597/1892] refactor: getting rid of more (igraph_integer_t) conversions --- src/_igraph/arpackobject.c | 2 +- src/_igraph/convert.c | 22 ++-- src/_igraph/graphobject.c | 245 +++++++++++++++++++------------------ src/_igraph/igraphmodule.c | 4 +- 4 files changed, 138 insertions(+), 135 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 5fa78d6f7..738362b50 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -151,7 +151,7 @@ int igraphmodule_ARPACKOptions_setattr( } self->params.tol = igraph_int; } else if (PyFloat_Check(value)) { - self->params.tol = (igraph_real_t) PyFloat_AsDouble(value); + self->params.tol = PyFloat_AsDouble(value); } else { PyErr_SetString(PyExc_ValueError, "integer or float expected"); return -1; diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 176f8a23f..5b75dac96 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -883,20 +883,18 @@ int igraphmodule_PyObject_to_real_t(PyObject *object, igraph_real_t *v) { if (object == NULL) { } else if (PyLong_Check(object)) { - double d = PyLong_AsDouble(object); - *v=(igraph_real_t)d; + *v = PyLong_AsDouble(object); return 0; } else if (PyFloat_Check(object)) { - double d = PyFloat_AS_DOUBLE((PyFloatObject*)object); - *v=(igraph_real_t)d; + *v = PyFloat_AS_DOUBLE((PyFloatObject*)object); return 0; } else if (PyNumber_Check(object)) { PyObject *i = PyNumber_Float(object); - double d; - if (i == NULL) return 1; - d = PyFloat_AS_DOUBLE((PyFloatObject*)i); + if (i == NULL) { + return 1; + } + *v = PyFloat_AS_DOUBLE((PyFloatObject*)i); Py_DECREF(i); - *v = (igraph_real_t)d; return 0; } PyErr_BadArgument(); @@ -2331,11 +2329,11 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap for (j = 0; j < n; j++) { item = PySequence_GetItem(row, j); if (PyLong_Check(item)) { - MATRIX(*m, i, j) = (igraph_real_t)PyLong_AsLong(item); + MATRIX(*m, i, j) = PyLong_AsLong(item); } else if (PyLong_Check(item)) { - MATRIX(*m, i, j) = (igraph_real_t)PyLong_AsLong(item); + MATRIX(*m, i, j) = PyLong_AsLong(item); } else if (PyFloat_Check(item)) { - MATRIX(*m, i, j) = (igraph_real_t)PyFloat_AsDouble(item); + MATRIX(*m, i, j) = PyFloat_AsDouble(item); } else if (!was_warned) { PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); was_warned=1; @@ -2418,7 +2416,7 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); was_warned = 1; } - + Py_DECREF(item); } Py_DECREF(row); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index ac8f89b5c..4ef1dce6e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2398,7 +2398,7 @@ PyObject *igraphmodule_Graph_Forest_Fire(PyTypeObject * type, &n, &fw_prob, &bw_factor, &ambs, &directed)) return NULL; - CHECK_SSIZE_T_RANGE(n, "number of nodes"); + CHECK_SSIZE_T_RANGE(n, "vertex count"); CHECK_SSIZE_T_RANGE(n, "number of ambassadors"); if (igraph_forest_fire_game(&g, n, fw_prob, bw_factor, ambs, PyObject_IsTrue(directed))) { @@ -2430,7 +2430,7 @@ PyObject *igraphmodule_Graph_Full(PyTypeObject * type, if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OO", kwlist, &n, &directed, &loops)) return NULL; - CHECK_SSIZE_T_RANGE(n, "number of nodes"); + CHECK_SSIZE_T_RANGE(n, "vertex count"); if (igraph_full(&g, n, PyObject_IsTrue(directed), PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); @@ -2675,14 +2675,14 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, PyObject *igraphmodule_Graph_Isoclass(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long int n, isoclass; + Py_ssize_t n, isoclass; PyObject *directed = Py_False; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "cls", "directed", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|O", kwlist, &n, &isoclass, &directed)) return NULL; @@ -2692,8 +2692,7 @@ PyObject *igraphmodule_Graph_Isoclass(PyTypeObject * type, return NULL; } - if (igraph_isoclass_create(&g, (igraph_integer_t) n, - (igraph_integer_t) isoclass, PyObject_IsTrue(directed))) { + if (igraph_isoclass_create(&g, n, isoclass, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2709,15 +2708,19 @@ PyObject *igraphmodule_Graph_Isoclass(PyTypeObject * type, */ PyObject *igraphmodule_Graph_Kautz(PyTypeObject *type, PyObject *args, PyObject *kwds) { - long int m, n; + Py_ssize_t m, n; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = {"m", "n", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll", kwlist, &m, &n)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn", kwlist, &m, &n)) { return NULL; + } + + CHECK_SSIZE_T_RANGE(m, "m"); + CHECK_SSIZE_T_RANGE(n, "n"); - if (igraph_kautz(&g, (igraph_integer_t) m, (igraph_integer_t) n)) { + if (igraph_kautz(&g, m, n)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2737,17 +2740,19 @@ PyObject *igraphmodule_Graph_K_Regular(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long int n, k; + Py_ssize_t n, k; PyObject *directed_o = Py_False, *multiple_o = Py_False; static char *kwlist[] = { "n", "k", "directed", "multiple", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|OO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|OO", kwlist, &n, &k, &directed_o, &multiple_o)) return NULL; - if (igraph_k_regular_game(&g, (igraph_integer_t) n, (igraph_integer_t) k, - PyObject_IsTrue(directed_o), PyObject_IsTrue(multiple_o))) { + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(k, "degree"); + + if (igraph_k_regular_game(&g, n, k, PyObject_IsTrue(directed_o), PyObject_IsTrue(multiple_o))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2766,7 +2771,7 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, PyObject * args, PyObject * kwds) { igraph_vector_int_t dimvector; - long int nei = 1; + Py_ssize_t nei = 1; igraph_bool_t directed; igraph_bool_t mutual; igraph_bool_t circular; @@ -2777,7 +2782,7 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, static char *kwlist[] = { "dim", "nei", "directed", "mutual", "circular", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|lOOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|nOOO", kwlist, &PyList_Type, &o_dimvector, &nei, &o_directed, &o_mutual, &o_circular)) return NULL; @@ -2789,8 +2794,9 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, if (igraphmodule_PyObject_to_vector_int_t(o_dimvector, &dimvector)) return NULL; - if (igraph_lattice(&g, &dimvector, (igraph_integer_t) nei, - directed, mutual, circular)) { + CHECK_SSIZE_T_RANGE_POSITIVE(nei, "number of neighbors"); + + if (igraph_lattice(&g, &dimvector, nei, directed, mutual, circular)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&dimvector); return NULL; @@ -2811,21 +2817,24 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, PyObject *igraphmodule_Graph_LCF(PyTypeObject *type, PyObject *args, PyObject *kwds) { igraph_vector_int_t shifts; - long int repeats, n; - PyObject *o_shifts; + Py_ssize_t repeats, n; + PyObject *shifts_o; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "shifts", "repeats", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lOl", kwlist, - &n, &o_shifts, &repeats)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nOn", kwlist, + &n, &shifts_o, &repeats)) return NULL; - if (igraphmodule_PyObject_to_vector_int_t(o_shifts, &shifts)) + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(repeats, "repeat count"); + + if (igraphmodule_PyObject_to_vector_int_t(shifts_o, &shifts)) return NULL; - if (igraph_lcf_vector(&g, (igraph_integer_t) n, &shifts, (igraph_integer_t) repeats)) { + if (igraph_lcf_vector(&g, n, &shifts, repeats)) { igraph_vector_int_destroy(&shifts); igraphmodule_handle_igraph_error(); return NULL; @@ -2910,7 +2919,7 @@ PyObject *igraphmodule_Graph_Preference(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, types; + Py_ssize_t n, types; PyObject *type_dist, *pref_matrix; PyObject *directed = Py_False; PyObject *loops = Py_False; @@ -2925,12 +2934,13 @@ PyObject *igraphmodule_Graph_Preference(PyTypeObject * type, { "n", "type_dist", "pref_matrix", "attribute", "directed", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lO!O!|OOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nO!O!|OOO", kwlist, &n, &PyList_Type, &type_dist, &PyList_Type, &pref_matrix, &attribute_key, &directed, &loops)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); types = PyList_Size(type_dist); if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) return NULL; @@ -2940,15 +2950,14 @@ NULL }; } store_attribs = (attribute_key && attribute_key != Py_None); - if (store_attribs && igraph_vector_int_init(&type_vec, (igraph_integer_t) n)) { + if (store_attribs && igraph_vector_int_init(&type_vec, n)) { igraph_matrix_destroy(&pm); igraph_vector_destroy(&td); igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_preference_game(&g, (igraph_integer_t) n, - (igraph_integer_t) types, &td, 0, &pm, + if (igraph_preference_game(&g, n, types, &td, 0, &pm, store_attribs ? &type_vec : 0, PyObject_IsTrue(directed), PyObject_IsTrue(loops))) { @@ -3003,7 +3012,7 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, in_types, out_types; + Py_ssize_t n, in_types, out_types; PyObject *type_dist_matrix, *pref_matrix; PyObject *loops = Py_False; igraph_matrix_t pm; @@ -3016,12 +3025,14 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, char *kwlist[] = { "n", "type_dist_matrix", "pref_matrix", "attribute", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lO!O!|OO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nO!O!|OO", kwlist, &n, &PyList_Type, &type_dist_matrix, &PyList_Type, &pref_matrix, &attribute_key, &loops)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); + if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) return NULL; if (igraphmodule_PyList_to_matrix_t(type_dist_matrix, &td)) { igraph_matrix_destroy(&pm); @@ -3033,13 +3044,13 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, store_attribs = (attribute_key && attribute_key != Py_None); if (store_attribs) { - if (igraph_vector_int_init(&in_type_vec, (igraph_integer_t) n)) { + if (igraph_vector_int_init(&in_type_vec, n)) { igraph_matrix_destroy(&pm); igraph_matrix_destroy(&td); igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_vector_int_init(&out_type_vec, (igraph_integer_t) n)) { + if (igraph_vector_int_init(&out_type_vec, n)) { igraph_matrix_destroy(&pm); igraph_matrix_destroy(&td); igraph_vector_int_destroy(&in_type_vec); @@ -3048,10 +3059,7 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, } } - if (igraph_asymmetric_preference_game(&g, (igraph_integer_t) n, - (igraph_integer_t) in_types, - (igraph_integer_t) out_types, - &td, &pm, + if (igraph_asymmetric_preference_game(&g, n, in_types, out_types, &td, &pm, store_attribs ? &in_type_vec : 0, store_attribs ? &out_type_vec : 0, PyObject_IsTrue(loops))) { @@ -3109,7 +3117,7 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long int n1, n2, m = -1; + Py_ssize_t n1, n2, m = -1; double p = -1.0; igraph_erdos_renyi_t t; igraph_neimode_t neimode = IGRAPH_ALL; @@ -3119,10 +3127,13 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, static char *kwlist[] = { "n1", "n2", "p", "m", "directed", "neimode", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|dlOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|dnOO", kwlist, &n1, &n2, &p, &m, &directed_o, &neimode_o)) return NULL; + CHECK_SSIZE_T_RANGE(n1, "number of vertices in first partition"); + CHECK_SSIZE_T_RANGE(n2, "number of vertices in second partition"); + if (m == -1 && p == -1.0) { /* no density parameters were given, throw exception */ PyErr_SetString(PyExc_TypeError, "Either m or p must be given."); @@ -3144,10 +3155,7 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, return NULL; } - if (igraph_bipartite_game(&g, &vertex_types, t, - (igraph_integer_t) n1, (igraph_integer_t) n2, - (igraph_real_t) p, (igraph_integer_t) m, - PyObject_IsTrue(directed_o), neimode)) { + if (igraph_bipartite_game(&g, &vertex_types, t, n1, n2, p, m, PyObject_IsTrue(directed_o), neimode)) { igraph_vector_bool_destroy(&vertex_types); igraphmodule_handle_igraph_error(); return NULL; @@ -3173,7 +3181,7 @@ PyObject *igraphmodule_Graph_Recent_Degree(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long n, window = 0; + Py_ssize_t n, window = 0; float power = 0.0f, zero_appeal = 0.0f; igraph_integer_t m = 0; igraph_vector_int_t outseq; @@ -3183,15 +3191,13 @@ PyObject *igraphmodule_Graph_Recent_Degree(PyTypeObject * type, { "n", "m", "window", "outpref", "directed", "power", "zero_appeal", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lOl|OOff", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nOn|OOff", kwlist, &n, &m_obj, &window, &outpref, &directed, &power, &zero_appeal)) return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(window, "window size"); // let's check whether we have a constant out-degree or a list if (PyLong_Check(m_obj)) { @@ -3199,20 +3205,16 @@ NULL }; return NULL; } igraph_vector_int_init(&outseq, 0); - } - else if (PyList_Check(m_obj)) { + } else if (PyList_Check(m_obj)) { if (igraphmodule_PyObject_to_vector_int_t(m_obj, &outseq)) { // something bad happened during conversion return NULL; } } - if (igraph_recent_degree_game(&g, (igraph_integer_t) n, - (igraph_real_t) power, - (igraph_integer_t) window, - m, &outseq, + if (igraph_recent_degree_game(&g, n, power, window, m, &outseq, PyObject_IsTrue(outpref), - (igraph_real_t) zero_appeal, + zero_appeal, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&outseq); @@ -3234,26 +3236,20 @@ NULL }; PyObject *igraphmodule_Graph_Ring(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long n; + Py_ssize_t n; PyObject *directed = Py_False, *mutual = Py_False, *circular = Py_True; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "directed", "mutual", "circular", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O!O!O!", kwlist, &n, - &PyBool_Type, &directed, - &PyBool_Type, &mutual, - &PyBool_Type, &circular)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OOO", kwlist, &n, + &directed, &mutual, &circular)) return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "vertex count"); - if (igraph_ring(&g, (igraph_integer_t) n, (directed == Py_True), - (mutual == Py_True), (circular == Py_True))) { + if (igraph_ring(&g, n, PyObject_IsTrue(directed), PyObject_IsTrue(mutual), PyObject_IsTrue(circular))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -3273,7 +3269,7 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, { igraphmodule_GraphObject *self; igraph_t g; - long int n; + Py_ssize_t n; PyObject *block_sizes_o, *pref_matrix_o; PyObject *directed_o = Py_False; PyObject *loops_o = Py_False; @@ -3283,20 +3279,24 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, static char *kwlist[] = { "n", "pref_matrix", "block_sizes", "directed", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "lO!O!|OO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nO!O!|OO", kwlist, &n, &PyList_Type, &pref_matrix_o, &PyList_Type, &block_sizes_o, &directed_o, &loops_o)) return NULL; - if (igraphmodule_PyList_to_matrix_t(pref_matrix_o, &pref_matrix)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); + + if (igraphmodule_PyList_to_matrix_t(pref_matrix_o, &pref_matrix)) { + return NULL; + } + if (igraphmodule_PyObject_to_vector_int_t(block_sizes_o, &block_sizes)) { igraph_matrix_destroy(&pref_matrix); return NULL; } - if (igraph_sbm_game(&g, (igraph_integer_t) n, &pref_matrix, &block_sizes, - PyObject_IsTrue(directed_o), PyObject_IsTrue(loops_o))) { + if (igraph_sbm_game(&g, n, &pref_matrix, &block_sizes, PyObject_IsTrue(directed_o), PyObject_IsTrue(loops_o))) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&pref_matrix); igraph_vector_int_destroy(&block_sizes); @@ -3307,6 +3307,7 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, igraph_vector_int_destroy(&block_sizes); CREATE_GRAPH_FROM_TYPE(self, g, type); + return (PyObject *) self; } @@ -3837,17 +3838,14 @@ PyObject *igraphmodule_Graph_average_path_length(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - char *kwlist[] = { "directed", "unconn", NULL }; + static char *kwlist[] = { "directed", "unconn", NULL }; PyObject *directed = Py_True, *unconn = Py_True; igraph_real_t res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!", kwlist, - &PyBool_Type, &directed, - &PyBool_Type, &unconn)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &directed, &unconn)) return NULL; - if (igraph_average_path_length(&self->g, &res, 0, (directed == Py_True), - (unconn == Py_True))) { + if (igraph_average_path_length(&self->g, &res, 0, PyObject_IsTrue(directed), PyObject_IsTrue(unconn))) { igraphmodule_handle_igraph_error(); return NULL; } @@ -3914,7 +3912,7 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, return NULL; } if (igraph_betweenness_cutoff(&self->g, &res, vs, PyObject_IsTrue(directed), - weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num))) { + weights, PyFloat_AsDouble(cutoff_num))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4263,7 +4261,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, return NULL; } if (igraph_closeness_cutoff(&self->g, &res, 0, 0, vs, mode, weights, - (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { + PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4343,7 +4341,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self return NULL; } if (igraph_harmonic_centrality_cutoff(&self->g, &res, vs, mode, weights, - (igraph_real_t)PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { + PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -4728,7 +4726,7 @@ PyObject *igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject * self, igraph_vector_destroy(&res); return NULL; } if (igraph_edge_betweenness_cutoff(&self->g, &res, PyObject_IsTrue(directed), - weights, (igraph_real_t)PyFloat_AsDouble(cutoff_num))) { + weights, PyFloat_AsDouble(cutoff_num))) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -10140,25 +10138,27 @@ PyObject *igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "source", "target", "capacity", NULL }; - PyObject *capacity_object = Py_None; + PyObject *capacity_object = Py_None, *v1_o, *v2_o; igraph_vector_t capacity_vector; igraph_real_t result; - long int vid1 = -1, vid2 = -1; igraph_integer_t v1, v2; igraph_maxflow_stats_t stats; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O", kwlist, - &vid1, &vid2, &capacity_object)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, + &v1_o, &v2_o, &capacity_object)) + return NULL; + + if (igraphmodule_PyObject_to_vid(v1_o, &v1, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_vid(v2_o, &v2, &self->g)) return NULL; - v1 = (igraph_integer_t) vid1; - v2 = (igraph_integer_t) vid2; if (igraphmodule_PyObject_to_attribute_values(capacity_object, &capacity_vector, self, ATTRHASH_IDX_EDGE, 1.0)) return igraphmodule_handle_igraph_error(); - if (igraph_maxflow_value(&self->g, &result, v1, v2, &capacity_vector, &stats)) { igraph_vector_destroy(&capacity_vector); @@ -10177,21 +10177,24 @@ PyObject *igraphmodule_Graph_maxflow(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "source", "target", "capacity", NULL }; - PyObject *capacity_object = Py_None, *flow_o, *cut_o, *partition_o; + PyObject *capacity_object = Py_None, *flow_o, *cut_o, *partition_o, *v1_o, *v2_o; igraph_vector_t capacity_vector; igraph_real_t result; - long int vid1 = -1, vid2 = -1; igraph_integer_t v1, v2; igraph_vector_t flow; igraph_vector_int_t cut, partition; igraph_maxflow_stats_t stats; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|O", kwlist, - &vid1, &vid2, &capacity_object)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, + &v1_o, &v2_o, &capacity_object)) + return NULL; + + if (igraphmodule_PyObject_to_vid(v1_o, &v1, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_vid(v2_o, &v2, &self->g)) return NULL; - v1 = (igraph_integer_t) vid1; - v2 = (igraph_integer_t) vid2; if (igraphmodule_PyObject_to_attribute_values(capacity_object, &capacity_vector, self, ATTRHASH_IDX_EDGE, 1.0)) @@ -10384,15 +10387,13 @@ PyObject *igraphmodule_Graph_mincut_value(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "source", "target", "capacity", NULL }; - PyObject *capacity_object = Py_None; + PyObject *capacity_object = Py_None, *v1_o = Py_None, *v2_o = Py_None; igraph_vector_t capacity_vector; igraph_real_t result, mincut; - igraph_integer_t v1, v2; - long vid1 = -1, vid2 = -1; - long n; + igraph_integer_t n, v1 = -1, v2 = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|llO", kwlist, - &vid1, &vid2, &capacity_object)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, + &v1_o, &v2_o, &capacity_object)) return NULL; if (igraphmodule_PyObject_to_attribute_values(capacity_object, @@ -10400,20 +10401,24 @@ PyObject *igraphmodule_Graph_mincut_value(igraphmodule_GraphObject * self, self, ATTRHASH_IDX_EDGE, 1.0)) return igraphmodule_handle_igraph_error(); - v1 = (igraph_integer_t) vid1; - v2 = (igraph_integer_t) vid2; + if (v1_o != Py_None && igraphmodule_PyObject_to_vid(v1_o, &v1, &self->g)) + return NULL; + + if (v2_o != Py_None && igraphmodule_PyObject_to_vid(v2_o, &v2, &self->g)) + return NULL; + if (v1 == -1 && v2 == -1) { if (igraph_mincut_value(&self->g, &result, &capacity_vector)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - } - else if (v1 == -1) { + } else if (v1 == -1) { n = igraph_vcount(&self->g); result = -1; for (v1 = 0; v1 < n; v1++) { - if (v2 == v1) + if (v2 == v1) { continue; + } if (igraph_st_mincut_value(&self->g, &mincut, v1, v2, &capacity_vector)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); @@ -10421,26 +10426,27 @@ PyObject *igraphmodule_Graph_mincut_value(igraphmodule_GraphObject * self, if (result < 0 || result > mincut) result = mincut; } - if (result < 0) + if (result < 0) { result = 0.0; - } - else if (v2 == -1) { + } + } else if (v2 == -1) { n = igraph_vcount(&self->g); result = -1; for (v2 = 0; v2 < n; v2++) { - if (v2 == v1) + if (v2 == v1) { continue; + } if (igraph_st_mincut_value(&self->g, &mincut, v1, v2, &capacity_vector)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); } - if (result < 0.0 || result > mincut) + if (result < 0.0 || result > mincut) { result = mincut; + } } if (result < 0) result = 0.0; - } - else { + } else { if (igraph_st_mincut_value(&self->g, &result, v1, v2, &capacity_vector)) { igraph_vector_destroy(&capacity_vector); return igraphmodule_handle_igraph_error(); @@ -11040,17 +11046,15 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, PyObject* args, PyObject* kwds) { static char* kwlist[] = { "min", "max", "file", NULL }; PyObject *list, *item, *file = Py_None; - long int i = 0, j = 0; - igraph_integer_t min, max; - Py_ssize_t n; + Py_ssize_t min = 0, max = 0, i, j, n; igraph_vector_ptr_t result; igraphmodule_filehandle_t filehandle; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|llO", kwlist, &i, &j, &file)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nnO", kwlist, &min, &max, &file)) return NULL; - min = (igraph_integer_t) i; - max = (igraph_integer_t) j; + CHECK_SSIZE_T_RANGE(min, "minimum clique size"); + CHECK_SSIZE_T_RANGE(max, "maximum clique size"); if (file == Py_None) { if (igraph_vector_ptr_init(&result, 0)) { @@ -11063,10 +11067,11 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, return igraphmodule_handle_igraph_error(); } - n = (Py_ssize_t)igraph_vector_ptr_size(&result); + n = igraph_vector_ptr_size(&result); list = PyList_New(n); - if (!list) + if (!list) { return NULL; + } for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 8c08de894..f25b82be1 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -284,8 +284,8 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd igraph_matrix_destroy(&mtrx); return NULL; } - MATRIX(mtrx, i, 0)=(igraph_real_t)PyFloat_AsDouble(o1); - MATRIX(mtrx, i, 1)=(igraph_real_t)PyFloat_AsDouble(o2); + MATRIX(mtrx, i, 0) = PyFloat_AsDouble(o1); + MATRIX(mtrx, i, 1) = PyFloat_AsDouble(o2); Py_DECREF(o1); Py_DECREF(o2); } From 4195609e6ac7f0bce3f8d41774b7ce563eb7505b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 22:16:01 +0200 Subject: [PATCH 0598/1892] refactor: getting rid of even more (igraph_integer_t) conversions --- src/_igraph/graphobject.c | 94 ++++++++++++++++++--------------------- tests/test_generators.py | 4 +- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 4ef1dce6e..8d0d2e416 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3319,7 +3319,7 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, PyObject *igraphmodule_Graph_Star(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long n, center = 0; + Py_ssize_t n, center = 0; igraph_star_mode_t mode = IGRAPH_STAR_UNDIRECTED; PyObject* mode_o = Py_None; igraphmodule_GraphObject *self; @@ -3327,28 +3327,22 @@ PyObject *igraphmodule_Graph_Star(PyTypeObject * type, static char *kwlist[] = { "n", "mode", "center", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|Ol", kwlist, - &n, &mode_o, ¢er)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|On", kwlist, &n, &mode_o, ¢er)) return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); - return NULL; - } + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(center, "central vertex ID"); - if (center >= n || center < 0) { - PyErr_SetString(PyExc_ValueError, - "Central vertex ID should be between 0 and n-1"); + if (center >= n) { + PyErr_SetString(PyExc_ValueError, "central vertex ID should be between 0 and n-1"); return NULL; } if (igraphmodule_PyObject_to_star_mode_t(mode_o, &mode)) { - PyErr_SetString(PyExc_ValueError, - "Mode should be either \"in\", \"out\", \"mutual\" or \"undirected\""); return NULL; } - if (igraph_star(&g, (igraph_integer_t) n, mode, (igraph_integer_t) center)) { + if (igraph_star(&g, n, mode, center)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -3368,7 +3362,7 @@ PyObject *igraphmodule_Graph_Static_Fitness(PyTypeObject *type, PyObject* args, PyObject* kwds) { igraphmodule_GraphObject *self; igraph_t g; - long int m; + Py_ssize_t m; PyObject *fitness_out_o = Py_None, *fitness_in_o = Py_None; PyObject *fitness_o = Py_None; PyObject *multiple = Py_False, *loops = Py_False; @@ -3377,11 +3371,13 @@ PyObject *igraphmodule_Graph_Static_Fitness(PyTypeObject *type, static char *kwlist[] = { "m", "fitness_out", "fitness_in", "loops", "multiple", "fitness", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|OOOOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OOOOO", kwlist, &m, &fitness_out_o, &fitness_in_o, &loops, &multiple, &fitness_o)) return NULL; + CHECK_SSIZE_T_RANGE(m, "edge count"); + /* This trickery allows us to use "fitness" or "fitness_out" as * keyword argument, with "fitness_out" taking precedence over * "fitness" */ @@ -3403,7 +3399,7 @@ PyObject *igraphmodule_Graph_Static_Fitness(PyTypeObject *type, } } - if (igraph_static_fitness_game(&g, (igraph_integer_t) m, &fitness_out, + if (igraph_static_fitness_game(&g, m, &fitness_out, fitness_in_o == Py_None ? 0 : &fitness_in, PyObject_IsTrue(loops), PyObject_IsTrue(multiple))) { igraph_vector_destroy(&fitness_out); @@ -3431,7 +3427,7 @@ PyObject *igraphmodule_Graph_Static_Power_Law(PyTypeObject *type, PyObject* args, PyObject* kwds) { igraphmodule_GraphObject *self; igraph_t g; - long int n, m; + Py_ssize_t n, m; float exponent_out = -1.0f, exponent_in = -1.0f, exponent = -1.0f; PyObject *multiple = Py_False, *loops = Py_False; PyObject *finite_size_correction = Py_True; @@ -3439,12 +3435,15 @@ PyObject *igraphmodule_Graph_Static_Power_Law(PyTypeObject *type, static char *kwlist[] = { "n", "m", "exponent_out", "exponent_in", "loops", "multiple", "finite_size_correction", "exponent", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|ffOOOf", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|ffOOOf", kwlist, &n, &m, &exponent_out, &exponent_in, &loops, &multiple, &finite_size_correction, &exponent)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(m, "edge count"); + /* This trickery allows us to use "exponent" or "exponent_out" as * keyword argument, with "exponent_out" taking precedence over * "exponent" */ @@ -3456,8 +3455,7 @@ PyObject *igraphmodule_Graph_Static_Power_Law(PyTypeObject *type, return NULL; } - if (igraph_static_power_law_game(&g, (igraph_integer_t) n, (igraph_integer_t) m, - exponent_out, exponent_in, + if (igraph_static_power_law_game(&g, n, m, exponent_out, exponent_in, PyObject_IsTrue(loops), PyObject_IsTrue(multiple), PyObject_IsTrue(finite_size_correction))) { igraphmodule_handle_igraph_error(); @@ -3465,6 +3463,7 @@ PyObject *igraphmodule_Graph_Static_Power_Law(PyTypeObject *type, } CREATE_GRAPH_FROM_TYPE(self, g, type); + return (PyObject *) self; } @@ -3476,34 +3475,31 @@ PyObject *igraphmodule_Graph_Static_Power_Law(PyTypeObject *type, PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long int n, children; - PyObject *tree_mode_o = Py_None, *tree_type_o = Py_None; + Py_ssize_t n, children; + PyObject *tree_mode_o = Py_None; igraph_tree_mode_t mode = IGRAPH_TREE_UNDIRECTED; igraphmodule_GraphObject *self; igraph_t g; - static char *kwlist[] = { "n", "children", "mode", "type", NULL }; + static char *kwlist[] = { "n", "children", "mode", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll|OO", kwlist, - &n, &children, - &tree_mode_o, &tree_type_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn|O", kwlist, + &n, &children, &tree_mode_o)) return NULL; + CHECK_SSIZE_T_RANGE(n, "vertex count"); + CHECK_SSIZE_T_RANGE(children, "number of children per vertex"); + if (n < 0) { PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); return NULL; } - if (tree_mode_o == Py_None && tree_type_o != Py_None) { - tree_mode_o = tree_type_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); - } - if (igraphmodule_PyObject_to_tree_mode_t(tree_mode_o, &mode)) { return NULL; } - if (igraph_tree(&g, (igraph_integer_t) n, (igraph_integer_t) children, mode)) { + if (igraph_tree(&g, n, children, mode)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -3531,31 +3527,25 @@ PyObject *igraphmodule_Graph_Tree(PyTypeObject * type, PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long int n; - PyObject *directed_o = Py_False, *tree_method_o = Py_None; - igraph_bool_t directed; + Py_ssize_t n; + PyObject *directed = Py_False, *tree_method_o = Py_None; igraph_random_tree_t tree_method = IGRAPH_RANDOM_TREE_LERW; igraphmodule_GraphObject *self; igraph_t g; static char *kwlist[] = { "n", "directed", "method", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|OO", kwlist, - &n, &directed_o, &tree_method_o)) - return NULL; - - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "Number of vertices must be positive."); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|OO", kwlist, + &n, &directed, &tree_method_o)) return NULL; - } - directed = PyObject_IsTrue(directed_o); + CHECK_SSIZE_T_RANGE(n, "vertex count"); - if (igraphmodule_PyObject_to_random_tree_t(tree_method_o, &tree_method)) + if (igraphmodule_PyObject_to_random_tree_t(tree_method_o, &tree_method)) { return NULL; + } - if (igraph_tree_game(&g, (igraph_integer_t) n, directed, - tree_method)) { + if (igraph_tree_game(&g, n, PyObject_IsTrue(directed), tree_method)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -3573,7 +3563,7 @@ PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, PyObject *igraphmodule_Graph_Watts_Strogatz(PyTypeObject * type, PyObject * args, PyObject * kwds) { - long int nei = 1, dim, size; + Py_ssize_t dim, size, nei; double p; PyObject* loops = Py_False; PyObject* multiple = Py_False; @@ -3582,13 +3572,15 @@ PyObject *igraphmodule_Graph_Watts_Strogatz(PyTypeObject * type, static char *kwlist[] = { "dim", "size", "nei", "p", "loops", "multiple", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "llld|OO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nnnd|OO", kwlist, &dim, &size, &nei, &p, &loops, &multiple)) return NULL; - if (igraph_watts_strogatz_game(&g, (igraph_integer_t) dim, - (igraph_integer_t) size, (igraph_integer_t) nei, p, - PyObject_IsTrue(loops), PyObject_IsTrue(multiple))) { + CHECK_SSIZE_T_RANGE(dim, "dimensionality"); + CHECK_SSIZE_T_RANGE(size, "size"); + CHECK_SSIZE_T_RANGE(nei, "number of neighbors"); + + if (igraph_watts_strogatz_game(&g, dim, size, nei, p, PyObject_IsTrue(loops), PyObject_IsTrue(multiple))) { igraphmodule_handle_igraph_error(); return NULL; } diff --git a/tests/test_generators.py b/tests/test_generators.py index ac55a3b78..c7963a4b5 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -133,7 +133,7 @@ def testLCF(self): g1 = Graph.LCF(12, (5, -5), 6) g2 = Graph.Famous("Franklin") self.assertTrue(g1.isomorphic(g2)) - self.assertRaises(InternalError, Graph.LCF, 12, (5, -5), -3) + self.assertRaises(ValueError, Graph.LCF, 12, (5, -5), -3) def testRealizeDegreeSequence(self): # Test case insensitivity of options too @@ -229,7 +229,7 @@ def testSBM(self): self.assertTrue(sum(g.is_loop()) == 0) # Check error conditions - self.assertRaises(InternalError, Graph.SBM, -1, pref_matrix, types) + self.assertRaises(ValueError, Graph.SBM, -1, pref_matrix, types) self.assertRaises(InternalError, Graph.SBM, 61, pref_matrix, types) pref_matrix[0][1] = 0.7 self.assertRaises(InternalError, Graph.SBM, 60, pref_matrix, types) From 1eeb41fed06ec883b0aff03bdc57e02d23a7eb48 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Sep 2021 22:24:32 +0200 Subject: [PATCH 0599/1892] refactor: igraphmodule_convex_hull does not use long any more --- src/_igraph/igraphmodule.c | 78 +++++++++++++++++++-------------- test.sh | 20 +++++++++ warnings_converted_to_errors.py | 11 +++++ 3 files changed, 77 insertions(+), 32 deletions(-) create mode 100755 test.sh create mode 100644 warnings_converted_to_errors.py diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index f25b82be1..34557347f 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -230,64 +230,78 @@ PyObject* igraphmodule_set_status_handler(PyObject* self, PyObject* o) { PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwds) { static char* kwlist[] = {"vs", "coords", NULL}; - PyObject *vs, *o, *o1=0, *o2=0, *coords = Py_False; + PyObject *vs, *o, *o1, *o2, *o1_float, *o2_float, *coords = Py_False; igraph_matrix_t mtrx; igraph_vector_int_t result; igraph_matrix_t resmat; - long no_of_nodes, i; + Py_ssize_t no_of_nodes, i; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, &PyList_Type, &vs, &coords)) return NULL; - no_of_nodes=PyList_Size(vs); + no_of_nodes = PyList_Size(vs); if (igraph_matrix_init(&mtrx, no_of_nodes, 2)) { igraphmodule_handle_igraph_error(); return NULL; } - for (i=0; i= 2) { - o1=PyList_GetItem(o, 0); - o2=PyList_GetItem(o, 1); - if (PyList_Size(o) > 2) + + for (i = 0; i < no_of_nodes; i++) { + o = PyList_GetItem(vs, i); + + if (PySequence_Check(o)) { + if (PySequence_Size(o) >= 2) { + o1 = PySequence_GetItem(o, 0); + if (!o1) { + igraph_matrix_destroy(&mtrx); + return NULL; + } + + o2 = PySequence_GetItem(o, 1); + if (!o2) { + Py_DECREF(o1); + igraph_matrix_destroy(&mtrx); + return NULL; + } + + if (PySequence_Size(o) > 2) { PyErr_Warn(PyExc_Warning, "vertex with more than 2 coordinates found, considering only the first 2"); + } } else { PyErr_SetString(PyExc_TypeError, "vertex with less than 2 coordinates found"); igraph_matrix_destroy(&mtrx); - return NULL; - } - } else if (PyTuple_Check(o)) { - if (PyTuple_Size(o) >= 2) { - o1=PyTuple_GetItem(o, 0); - o2=PyTuple_GetItem(o, 1); - if (PyTuple_Size(o) > 2) - PyErr_Warn(PyExc_Warning, "vertex with more than 2 coordinates found, considering only the first 2"); - } else { - PyErr_SetString(PyExc_TypeError, "vertex with less than 2 coordinates found"); - igraph_matrix_destroy(&mtrx); - return NULL; + return NULL; } } if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) { PyErr_SetString(PyExc_TypeError, "vertex coordinates must be numeric"); + Py_DECREF(o2); + Py_DECREF(o1); igraph_matrix_destroy(&mtrx); return NULL; } - /* o, o1 and o2 were borrowed, but now o1 and o2 are actual references! */ - o1=PyNumber_Float(o1); o2=PyNumber_Float(o2); - if (!o1 || !o2) { - PyErr_SetString(PyExc_TypeError, "vertex coordinate conversion to float failed"); - Py_XDECREF(o1); - Py_XDECREF(o2); + + o1_float = PyNumber_Float(o1); + if (!o1_float) { + Py_DECREF(o2); + Py_DECREF(o1); igraph_matrix_destroy(&mtrx); return NULL; } - MATRIX(mtrx, i, 0) = PyFloat_AsDouble(o1); - MATRIX(mtrx, i, 1) = PyFloat_AsDouble(o2); Py_DECREF(o1); + + o2_float = PyNumber_Float(o2); + if (!o2_float) { + Py_DECREF(o2); + igraph_matrix_destroy(&mtrx); + return NULL; + } Py_DECREF(o2); + + MATRIX(mtrx, i, 0) = PyFloat_AsDouble(o1_float); + MATRIX(mtrx, i, 1) = PyFloat_AsDouble(o2_float); + Py_DECREF(o1_float); + Py_DECREF(o2_float); } if (!PyObject_IsTrue(coords)) { @@ -302,7 +316,7 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd igraph_vector_int_destroy(&result); return NULL; } - o=igraphmodule_vector_int_t_to_PyList(&result); + o = igraphmodule_vector_int_t_to_PyList(&result); igraph_vector_int_destroy(&result); } else { if (igraph_matrix_init(&resmat, 0, 0)) { @@ -316,7 +330,7 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd igraph_matrix_destroy(&resmat); return NULL; } - o=igraphmodule_matrix_t_to_PyList(&resmat, IGRAPHMODULE_TYPE_FLOAT); + o = igraphmodule_matrix_t_to_PyList(&resmat, IGRAPHMODULE_TYPE_FLOAT); igraph_matrix_destroy(&resmat); } diff --git a/test.sh b/test.sh new file mode 100755 index 000000000..007cc8cef --- /dev/null +++ b/test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +VENV_DIR=.venv +PYTHON=python3 + +############################################################################### + +set -e + +if [ ! -d $VENV_DIR ]; then + $PYTHON -m venv $VENV_DIR + $VENV_DIR/bin/pip install -U pip wheel +fi + +rm -rf build/ +$VENV_DIR/bin/python setup.py build +$VENV_DIR/bin/pip install --use-feature=in-tree-build .[plotting,test] +$VENV_DIR/bin/pytest tests + + diff --git a/warnings_converted_to_errors.py b/warnings_converted_to_errors.py new file mode 100644 index 000000000..76ee5230b --- /dev/null +++ b/warnings_converted_to_errors.py @@ -0,0 +1,11 @@ +from igraph import Graph +import warnings + +warnings.simplefilter('error', 'Cannot shuffle graph') +degseq = [1,2,2,3] +try: + testgraph = Graph.Degree_Sequence(degseq,method = "vl") +except RuntimeWarning: + print(degseq) +else: + print("go on") From 2b4f56f060ff35a9e290792da67c51355b29398f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 00:41:49 +0200 Subject: [PATCH 0600/1892] refactor: all conversions from Python objects to long int are replaced with Py_ssize_t now --- src/_igraph/convert.c | 6 +- src/_igraph/graphobject.c | 481 ++++++++++++++++++++++++-------------- 2 files changed, 304 insertions(+), 183 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 5b75dac96..ca14f4e24 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2748,12 +2748,14 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g *vid = 0; } else if (PyLong_Check(o)) { /* Single vertex ID */ - if (igraphmodule_PyObject_to_integer_t(o, vid)) + if (igraphmodule_PyObject_to_integer_t(o, vid)) { return 1; + } } else if (graph != 0 && PyBaseString_Check(o)) { /* Single vertex ID from vertex name */ - if (igraphmodule_get_vertex_id_by_name(graph, o, vid)) + if (igraphmodule_get_vertex_id_by_name(graph, o, vid)) { return 1; + } } else if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_VertexType)) { /* Single vertex ID from Vertex object */ igraphmodule_VertexObject *vo = (igraphmodule_VertexObject*)o; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8d0d2e416..58eab13b2 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3688,7 +3688,7 @@ PyObject *igraphmodule_Graph_assortativity_nominal(igraphmodule_GraphObject *sel static char *kwlist[] = { "types", "directed", NULL }; PyObject *types_o = Py_None, *directed = Py_True; igraph_real_t res; - int ret; + igraph_error_t ret; igraph_vector_int_t *types = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &types_o, &directed)) @@ -3720,7 +3720,7 @@ PyObject *igraphmodule_Graph_assortativity(igraphmodule_GraphObject *self, PyObj static char *kwlist[] = { "types1", "types2", "directed", NULL }; PyObject *types1_o = Py_None, *types2_o = Py_None, *directed = Py_True; igraph_real_t res; - int ret; + igraph_error_t ret; igraph_vector_t *types1 = 0, *types2 = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &types1_o, &types2_o, &directed)) @@ -4041,18 +4041,28 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel igraph_vector_int_t multiplicities[2]; igraph_t g1, g2; igraph_t *p_g1 = &g1, *p_g2 = &g2; - long int probe1 = -1; - long int which = -1; + Py_ssize_t probe1 = -1, which = -1; static char* kwlist[] = {"types", "multiplicity", "probe1", "which", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oll", kwlist, &types_o, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Onn", kwlist, &types_o, &multiplicity_o, &probe1, &which)) return NULL; if (igraphmodule_attrib_to_vector_bool_t(types_o, self, &types, ATTRIBUTE_TYPE_VERTEX)) return NULL; + if (which >= 0) { + CHECK_SSIZE_T_RANGE(which, "'which'"); + } else { + which = -1; + } + if (probe1 >= 0) { + CHECK_SSIZE_T_RANGE(probe1, "'probe1'"); + } else { + probe1 = -1; + } + if (which == 0) { p_g2 = 0; } else if (which == 1) { @@ -4076,7 +4086,7 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel if (igraph_bipartite_projection(&self->g, types, p_g1, p_g2, p_g1 ? &multiplicities[0] : 0, p_g2 ? &multiplicities[1] : 0, - (igraph_integer_t) probe1)) { + probe1)) { igraph_vector_int_destroy(&multiplicities[0]); igraph_vector_int_destroy(&multiplicities[1]); if (types) { igraph_vector_bool_destroy(types); free(types); } @@ -4084,8 +4094,7 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel return NULL; } } else { - if (igraph_bipartite_projection(&self->g, types, p_g1, p_g2, 0, 0, - (igraph_integer_t) probe1)) { + if (igraph_bipartite_projection(&self->g, types, p_g1, p_g2, 0, 0, probe1)) { if (types) { igraph_vector_bool_destroy(types); free(types); } igraphmodule_handle_igraph_error(); return NULL; @@ -4542,14 +4551,27 @@ PyObject *igraphmodule_Graph_decompose(igraphmodule_GraphObject * self, igraph_connectedness_t mode = IGRAPH_STRONG; PyObject *list, *mode_o = Py_None; igraphmodule_GraphObject *o; - long maxcompno = -1, minelements = -1, n, i; + Py_ssize_t maxcompno = -1, minelements = -1; + igraph_integer_t i, n; igraph_vector_ptr_t components; igraph_t *g; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oll", kwlist, &mode_o, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Onn", kwlist, &mode_o, &maxcompno, &minelements)) return NULL; + if (maxcompno >= 0) { + CHECK_SSIZE_T_RANGE(maxcompno, "maximum number of components"); + } else { + maxcompno = -1; + } + + if (minelements >= 0) { + CHECK_SSIZE_T_RANGE(minelements, "minimum number of vertices per component"); + } else { + minelements = -1; + } + if (igraphmodule_PyObject_to_connectedness_t(mode_o, &mode)) return NULL; @@ -4747,33 +4769,37 @@ PyObject *igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_edge_connectivity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "source", "target", "checks", NULL }; - PyObject *checks = Py_True; - long int source = -1, target = -1, result; + PyObject *checks = Py_True, *source_o = Py_None, *target_o = Py_None; + igraph_integer_t source = -1, target = -1; igraph_integer_t res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|llO", kwlist, - &source, &target, &checks)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &source_o, &target_o, &checks)) + return NULL; + + if (source_o != Py_None && igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { + return NULL; + } + + if (target_o != Py_None && igraphmodule_PyObject_to_vid(target_o, &target, &self->g)) { return NULL; + } if (source < 0 && target < 0) { if (igraph_edge_connectivity(&self->g, &res, PyObject_IsTrue(checks))) { igraphmodule_handle_igraph_error(); - return NULL; + return NULL; } } else if (source >= 0 && target >= 0) { - if (igraph_st_edge_connectivity(&self->g, &res, (igraph_integer_t) source, - (igraph_integer_t) target)) { + if (igraph_st_edge_connectivity(&self->g, &res, source, target)) { igraphmodule_handle_igraph_error(); return NULL; } } else { - PyErr_SetString(PyExc_ValueError, "if source or target is given, the other one must also be specified"); - return NULL; + PyErr_SetString(PyExc_ValueError, "if source or target is given, the other one must also be specified"); + return NULL; } - result = res; - - return Py_BuildValue("l", result); + return igraphmodule_integer_t_to_PyObject(res); } /** \ingroup python_interface_graph @@ -5232,19 +5258,22 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, PyObject *vobj = Py_None; PyObject *mode_o = 0; PyObject *result; - long int order = 1; - int mindist = 0; + Py_ssize_t order = 1, mindist = 0; igraph_neimode_t mode = IGRAPH_ALL; igraph_bool_t return_single = 0; igraph_vs_t vs; igraph_vector_ptr_t res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlOi", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOn", kwlist, &vobj, &order, &mode_o, &mindist)) return NULL; - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + CHECK_SSIZE_T_RANGE(order, "neighborhood order"); + CHECK_SSIZE_T_RANGE(mindist, "minimum distance"); + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; + } if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { return igraphmodule_handle_igraph_error(); @@ -5255,18 +5284,18 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, return igraphmodule_handle_igraph_error(); } - if (igraph_neighborhood(&self->g, &res, vs, (igraph_integer_t) order, mode, - mindist)) { + if (igraph_neighborhood(&self->g, &res, vs, order, mode, mindist)) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } igraph_vs_destroy(&vs); - if (!return_single) + if (!return_single) { result = igraphmodule_vector_int_ptr_t_to_PyList(&res); - else + } else { result = igraphmodule_vector_int_t_to_PyList((igraph_vector_int_t*)VECTOR(res)[0]); + } IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&res, igraph_vector_int_destroy); igraph_vector_ptr_destroy_all(&res); @@ -5286,19 +5315,22 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, PyObject *vobj = Py_None; PyObject *mode_o = 0; PyObject *result; - long int order = 1; - int mindist = 0; + Py_ssize_t order = 1, mindist = 0; igraph_neimode_t mode = IGRAPH_ALL; igraph_bool_t return_single = 0; igraph_vs_t vs; igraph_vector_int_t res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlOi", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOn", kwlist, &vobj, &order, &mode_o, &mindist)) return NULL; - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + CHECK_SSIZE_T_RANGE(order, "neighborhood order"); + CHECK_SSIZE_T_RANGE(mindist, "minimum distance"); + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; + } if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { return igraphmodule_handle_igraph_error(); @@ -5309,8 +5341,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, return igraphmodule_handle_igraph_error(); } - if (igraph_neighborhood_size(&self->g, &res, vs, (igraph_integer_t) order, mode, - mindist)) { + if (igraph_neighborhood_size(&self->g, &res, vs, order, mode, mindist)) { igraph_vs_destroy(&vs); return igraphmodule_handle_igraph_error(); } @@ -5352,20 +5383,22 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel igraph_vs_t vs, reset_vs; igraph_pagerank_algo_t algo=IGRAPH_PAGERANK_ALGO_PRPACK; PyObject *algo_o = Py_None; - long niter=1000; + Py_ssize_t niter = 1000; float eps=0.001f; void *opts; - int retval; + igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!Olf", kwlist, &vobj, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!Onf", kwlist, &vobj, &directed, &damping, &robj, - &rvsobj, &wobj, + &rvsobj, &wobj, &igraphmodule_ARPACKOptionsType, &arpack_options_o, &algo_o, &niter, &eps)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); + if (robj != Py_None && rvsobj != Py_None) { PyErr_SetString(PyExc_ValueError, "only reset or reset_vs can be defined, not both"); return NULL; @@ -5516,17 +5549,20 @@ PyObject *igraphmodule_Graph_rewire(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "n", "mode", NULL }; - long int n = 1000; + Py_ssize_t n = 1000; PyObject *mode_o = Py_None; igraph_rewiring_t mode = IGRAPH_REWIRING_SIMPLE; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO", kwlist, &n, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nO", kwlist, &n, &mode_o)) return NULL; - if (igraphmodule_PyObject_to_rewiring_t(mode_o, &mode)) + CHECK_SSIZE_T_RANGE(n, "number of rewiring attempts"); + + if (igraphmodule_PyObject_to_rewiring_t(mode_o, &mode)) { return NULL; + } - if (igraph_rewire(&self->g, (igraph_integer_t) n, mode)) { + if (igraph_rewire(&self->g, n, mode)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -6121,7 +6157,7 @@ PyObject igraph_bool_t return_single = 0; igraph_vs_t vs; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; - int retval; + igraph_error_t retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &vobj, &mode_o, &weights_o)) return NULL; @@ -6188,7 +6224,7 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * igraph_neimode_t mode = IGRAPH_OUT; igraph_vector_int_t result; igraph_warning_handler_t* old_handler = 0; - int retval; + igraph_error_t retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &warnings_o)) return NULL; @@ -6229,25 +6265,32 @@ PyObject *igraphmodule_Graph_topological_sorting(igraphmodule_GraphObject * PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "source", "target", "checks", "neighbors", NULL }; - PyObject *checks = Py_True, *neis = Py_None; - long int source = -1, target = -1; - igraph_integer_t res; + PyObject *checks = Py_True, *neis = Py_None, *source_o = Py_None, *target_o = Py_None; + igraph_integer_t source = -1, target = -1, res; igraph_vconn_nei_t neighbors = IGRAPH_VCONN_NEI_ERROR; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|llOO", kwlist, - &source, &target, &checks, &neis)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, + &source_o, &target_o, &checks, &neis)) return NULL; + if (source_o != Py_None && igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { + return NULL; + } + + if (target_o != Py_None && igraphmodule_PyObject_to_vid(target_o, &target, &self->g)) { + return NULL; + } + if (source < 0 && target < 0) { if (igraph_vertex_connectivity(&self->g, &res, PyObject_IsTrue(checks))) { igraphmodule_handle_igraph_error(); return NULL; } } else if (source >= 0 && target >= 0) { - if (igraphmodule_PyObject_to_vconn_nei_t(neis, &neighbors)) + if (igraphmodule_PyObject_to_vconn_nei_t(neis, &neighbors)) { return NULL; - if (igraph_st_vertex_connectivity(&self->g, &res, - (igraph_integer_t) source, (igraph_integer_t) target, neighbors)) { + } + if (igraph_st_vertex_connectivity(&self->g, &res, source, target, neighbors)) { igraphmodule_handle_igraph_error(); return NULL; } @@ -6378,16 +6421,18 @@ igraph_error_t igraphmodule_i_Graph_motifs_randesu_callback(const igraph_t *grap PyObject *igraphmodule_Graph_motifs_randesu(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { igraph_vector_t result, cut_prob; - long int size=3; + Py_ssize_t size = 3; PyObject* cut_prob_list=Py_None; PyObject* callback=Py_None; PyObject *list; static char* kwlist[] = {"size", "cut_prob", "callback", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOO", kwlist, &size, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nOO", kwlist, &size, &cut_prob_list, &callback)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(size, "motif size"); + if (cut_prob_list == Py_None) { if (igraph_vector_init(&cut_prob, size)) { return igraphmodule_handle_igraph_error(); @@ -6403,7 +6448,7 @@ PyObject *igraphmodule_Graph_motifs_randesu(igraphmodule_GraphObject *self, igraph_vector_destroy(&cut_prob); return igraphmodule_handle_igraph_error(); } - if (igraph_motifs_randesu(&self->g, &result, (igraph_integer_t) size, &cut_prob)) { + if (igraph_motifs_randesu(&self->g, &result, size, &cut_prob)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&result); igraph_vector_destroy(&cut_prob); @@ -6419,7 +6464,7 @@ PyObject *igraphmodule_Graph_motifs_randesu(igraphmodule_GraphObject *self, igraphmodule_i_Graph_motifs_randesu_callback_data_t data; data.graph = (PyObject*)self; data.func = callback; - if (igraph_motifs_randesu_callback(&self->g, (igraph_integer_t) size, &cut_prob, + if (igraph_motifs_randesu_callback(&self->g, size, &cut_prob, igraphmodule_i_Graph_motifs_randesu_callback, &data)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&cut_prob); @@ -6445,13 +6490,15 @@ PyObject *igraphmodule_Graph_motifs_randesu_no(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { igraph_vector_t cut_prob; igraph_integer_t result; - long int size=3; + Py_ssize_t size = 3; PyObject* cut_prob_list=Py_None; static char* kwlist[] = {"size", "cut_prob", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO", kwlist, &size, &cut_prob_list)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nO", kwlist, &size, &cut_prob_list)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(size, "motif size"); + if (cut_prob_list == Py_None) { if (igraph_vector_init(&cut_prob, size)) { return igraphmodule_handle_igraph_error(); @@ -6462,7 +6509,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_no(igraphmodule_GraphObject *self, return NULL; } } - if (igraph_motifs_randesu_no(&self->g, &result, (igraph_integer_t) size, &cut_prob)) { + if (igraph_motifs_randesu_no(&self->g, &result, size, &cut_prob)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&cut_prob); return NULL; @@ -6481,15 +6528,17 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s PyObject *args, PyObject *kwds) { igraph_vector_t cut_prob; igraph_integer_t result; - long size=3; + Py_ssize_t size = 3; PyObject* cut_prob_list=Py_None; PyObject *sample=Py_None; static char* kwlist[] = {"size", "cut_prob", "sample", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nOO", kwlist, &size, &cut_prob_list, &sample)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(size, "motif size"); + if (sample == Py_None) { PyErr_SetString(PyExc_TypeError, "sample size must be given"); return NULL; @@ -6525,7 +6574,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s igraph_vector_destroy(&cut_prob); return NULL; } - if (igraph_motifs_randesu_estimate(&self->g, &result, (igraph_integer_t) size, + if (igraph_motifs_randesu_estimate(&self->g, &result, size, &cut_prob, 0, &samp)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&samp); @@ -6576,16 +6625,17 @@ PyObject *igraphmodule_Graph_layout_circle(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { igraph_matrix_t m; - int ret; - long dim = 2; + igraph_error_t ret; + Py_ssize_t dim = 2; PyObject *result; PyObject *order_o = Py_None; igraph_vs_t order; static char *kwlist[] = { "dim", "order", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lO", kwlist, &dim, &order_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nO", kwlist, &dim, &order_o)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; @@ -6636,14 +6686,15 @@ PyObject *igraphmodule_Graph_layout_random(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { igraph_matrix_t m; - int ret; - long dim = 2; + igraph_error_t ret; + Py_ssize_t dim = 2; PyObject *result; static char *kwlist[] = { "dim", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &dim)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|n", kwlist, &dim)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; @@ -6680,32 +6731,39 @@ PyObject *igraphmodule_Graph_layout_grid(igraphmodule_GraphObject* self, igraph_matrix_t m; PyObject *result; - long int width = 0, height = 0, dim = 2; - int ret; + Py_ssize_t width = 0, height = 0, dim = 2; + igraph_error_t ret; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lll", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nnn", kwlist, &width, &height, &dim)) return NULL; - if (dim == 2 && height > 0) { - PyErr_SetString(PyExc_ValueError, "height must not be given if dim=2"); - return NULL; - } - + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; } + CHECK_SSIZE_T_RANGE(width, "width"); + if (dim == 2) { + if (height > 0) { + PyErr_SetString(PyExc_ValueError, "height must not be given if dim=2"); + return NULL; + } + } else { + CHECK_SSIZE_T_RANGE(height, "height"); + } + if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); return NULL; } - if (dim == 2) + if (dim == 2) { ret = igraph_layout_grid(&self->g, &m, width); - else + } else { ret = igraph_layout_grid_3d(&self->g, &m, width, height); + } if (ret != IGRAPH_SUCCESS) { igraphmodule_handle_igraph_error(); @@ -6788,8 +6846,8 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * "miny", "maxy", "minz", "maxz", "dim", NULL }; igraph_matrix_t m; igraph_bool_t use_seed=0; - int ret; - long int niter = 1000, dim = 2; + igraph_error_t ret; + Py_ssize_t niter = 1000, dim = 2; double kkconst, epsilon = 0.0; PyObject *result, *seed_o=Py_None; PyObject *minx_o=Py_None, *maxx_o=Py_None; @@ -6810,7 +6868,7 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * kkconst = igraph_vcount(&self->g); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lddOOOOOOOl", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nddOOOOOOOn", kwlist, &niter, &epsilon, &kkconst, &seed_o, &minx_o, &maxx_o, @@ -6818,11 +6876,14 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * &minz_o, &maxz_o, &dim)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; } + CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); + if (seed_o == 0 || seed_o == Py_None) { if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); @@ -6874,11 +6935,11 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * } if (dim == 2) ret = igraph_layout_kamada_kawai - (&self->g, &m, use_seed, (igraph_integer_t) niter, epsilon, kkconst, + (&self->g, &m, use_seed, niter, epsilon, kkconst, /*weights=*/ 0, /*bounds*/ minx, maxx, miny, maxy); else ret = igraph_layout_kamada_kawai_3d - (&self->g, &m, use_seed, (igraph_integer_t) niter, epsilon, kkconst, + (&self->g, &m, use_seed, niter, epsilon, kkconst, /*weights=*/ 0, /*bounds*/ minx, maxx, miny, maxy, minz, maxz); DESTROY_VECTORS; @@ -6910,8 +6971,7 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel "weight_node_edge_dist", NULL }; igraph_matrix_t m; igraph_bool_t use_seed=0; - long int maxiter=10; - long int fineiter=-1; + Py_ssize_t maxiter = 10, fineiter = -1; double cool_fact=0.75; double weight_node_dist=1.0; double weight_border=0.0; @@ -6921,9 +6981,9 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel igraph_real_t density; PyObject *result; PyObject *seed_o=Py_None; - int retval; + igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Olldddddd", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Onndddddd", kwlist, &seed_o, &maxiter, &fineiter, &cool_fact, &weight_node_dist, &weight_border, &weight_edge_lengths, &weight_edge_crossings, @@ -6974,7 +7034,7 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel } retval = igraph_layout_davidson_harel(&self->g, &m, use_seed, - (igraph_integer_t) maxiter, (igraph_integer_t) fineiter, cool_fact, + maxiter, fineiter, cool_fact, weight_node_dist, weight_border, weight_edge_lengths, weight_edge_crossings, weight_node_edge_dist); if (retval) { @@ -7005,13 +7065,14 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, igraph_layout_drl_options_t options; PyObject *result; PyObject *wobj=Py_None, *fixed_o=Py_None, *seed_o=Py_None, *options_o=Py_None; - long dim = 2; - int retval; + Py_ssize_t dim = 2; + igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOl", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOn", kwlist, &wobj, &seed_o, &fixed_o, &options_o, &dim)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; @@ -7102,8 +7163,8 @@ PyObject igraph_vector_t *miny=0, *maxy=0; igraph_vector_t *minz=0, *maxz=0; igraph_layout_grid_t grid = IGRAPH_LAYOUT_AUTOGRID; - int ret; - long int niter = 500, dim = 2; + igraph_error_t ret; + Py_ssize_t niter = 500, dim = 2; double start_temp; PyObject *result; PyObject *wobj=Py_None, *seed_o=Py_None; @@ -7124,13 +7185,15 @@ PyObject start_temp = sqrt(igraph_vcount(&self->g)) / 10.0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OldOOOOOOOlO", kwlist, &wobj, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OndOOOOOOOnO", kwlist, &wobj, &niter, &start_temp, &seed_o, &minx_o, &maxx_o, &miny_o, &maxy_o, &minz_o, &maxz_o, &dim, &grid_o)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); + if (dim != 2 && dim != 3) { PyErr_SetString(PyExc_ValueError, "number of dimensions must be either 2 or 3"); return NULL; @@ -7198,11 +7261,11 @@ PyObject if (dim == 2) { ret = igraph_layout_fruchterman_reingold - (&self->g, &m, use_seed, (igraph_integer_t) niter, + (&self->g, &m, use_seed, niter, start_temp, grid, weights, minx, maxx, miny, maxy); } else { ret = igraph_layout_fruchterman_reingold_3d - (&self->g, &m, use_seed, (igraph_integer_t) niter, + (&self->g, &m, use_seed, niter, start_temp, weights, minx, maxx, miny, maxy, minz, maxz); } @@ -7234,31 +7297,32 @@ PyObject *igraphmodule_Graph_layout_graphopt(igraphmodule_GraphObject *self, { "niter", "node_charge", "node_mass", "spring_length", "spring_constant", "max_sa_movement", "seed", NULL }; igraph_matrix_t m; - long int niter = 500; + Py_ssize_t niter = 500; double node_charge = 0.001, node_mass = 30; - long spring_length = 0; - double spring_constant = 1, max_sa_movement = 5; + double spring_constant = 1, max_sa_movement = 5, spring_length = 0; PyObject *result, *seed_o = Py_None; igraph_bool_t use_seed=0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lddlddO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ndddddO", kwlist, &niter, &node_charge, &node_mass, &spring_length, &spring_constant, &max_sa_movement, &seed_o)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); + if (seed_o == 0 || seed_o == Py_None) { if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); return NULL; } } else { - use_seed=1; + use_seed = 1; if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; } - if (igraph_layout_graphopt(&self->g, &m, (igraph_integer_t) niter, + if (igraph_layout_graphopt(&self->g, &m, niter, node_charge, node_mass, spring_length, spring_constant, max_sa_movement, use_seed)) { igraph_matrix_destroy(&m); @@ -7284,7 +7348,7 @@ PyObject *igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject * self, NULL }; igraph_matrix_t m; PyObject *result, *root_o = Py_None; - long int maxiter = 150; + Py_ssize_t maxiter = 150; igraph_integer_t proot = -1; double maxdelta, area, coolexp, repulserad, cellsize; @@ -7294,11 +7358,13 @@ PyObject *igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject * self, repulserad = -1; cellsize = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ldddddO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ndddddO", kwlist, &maxiter, &maxdelta, &area, &coolexp, &repulserad, &cellsize, &root_o)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(maxiter, "maximum number of iterations"); + if (area <= 0) area = igraph_vcount(&self->g)*igraph_vcount(&self->g); if (repulserad <= 0) @@ -7314,7 +7380,7 @@ PyObject *igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject * self, return NULL; } - if (igraph_layout_lgl(&self->g, &m, (igraph_integer_t) maxiter, maxdelta, + if (igraph_layout_lgl(&self->g, &m, maxiter, maxdelta, area, coolexp, repulserad, cellsize, proot)) { igraph_matrix_destroy(&m); igraphmodule_handle_igraph_error(); @@ -7338,7 +7404,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, { "dist", "dim", "arpack_options", NULL }; igraph_matrix_t m; igraph_matrix_t *dist = 0; - long int dim = 2; + Py_ssiez_t dim = 2; PyObject *dist_o = Py_None; PyObject *arpack_options_o = igraphmodule_arpack_options_default; PyObject *result; @@ -7346,11 +7412,13 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, /* arpack_options_o is now unused but we kept here for sake of backwards * compatibility */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlO!", kwlist, &dist_o, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnO!", kwlist, &dist_o, &dim, &igraphmodule_ARPACKOptionsType, &arpack_options_o)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); + if (dist_o != Py_None) { dist = (igraph_matrix_t*)malloc(sizeof(igraph_matrix_t)); if (!dist) { @@ -7522,16 +7590,18 @@ PyObject *igraphmodule_Graph_layout_sugiyama( igraph_vector_t *weights = 0; igraph_vector_int_t *layers = 0; double hgap = 1, vgap = 1; - long int maxiter = 100; + Py_ssize_t maxiter = 100; PyObject *layers_o = Py_None, *weights_o = Py_None, *extd_to_orig_eids_o = Py_None; PyObject *return_extended_graph = Py_False; PyObject *result; igraphmodule_GraphObject *graph_o; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOddlO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOddnO", kwlist, &layers_o, &weights_o, &hgap, &vgap, &maxiter, &return_extended_graph)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(maxiter, "maximum number of iterations"); + if (igraph_vector_int_init(&extd_to_orig_eids, 0)) { igraphmodule_handle_igraph_error(); return NULL; @@ -7599,14 +7669,16 @@ PyObject *igraphmodule_Graph_layout_bipartite( igraph_matrix_t m; igraph_vector_bool_t *types = 0; double hgap = 1, vgap = 1; - long int maxiter = 100; + Py_ssize_t maxiter = 100; PyObject *types_o = Py_None; PyObject *result; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oddl", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oddn", kwlist, &types_o, &hgap, &vgap, &maxiter)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(maxiter, "maximum number of iterations"); + if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); return NULL; @@ -8215,20 +8287,22 @@ PyObject *igraphmodule_Graph_Read_GraphML(PyTypeObject * type, { igraphmodule_GraphObject *self; PyObject *fname = NULL; - long int index = 0; + Py_ssize_t index = 0; igraph_t g; igraphmodule_filehandle_t fobj; static char *kwlist[] = { "f", "index", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|l", kwlist, &fname, &index)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n", kwlist, &fname, &index)) return NULL; - if (igraphmodule_filehandle_init(&fobj, fname, "r")) + CHECK_SSIZE_T_RANGE(index, "graph index"); + + if (igraphmodule_filehandle_init(&fobj, fname, "r")) { return NULL; + } - if (igraph_read_graph_graphml(&g, igraphmodule_filehandle_get(&fobj), - (igraph_integer_t) index)) { + if (igraph_read_graph_graphml(&g, igraphmodule_filehandle_get(&fobj), index)) { igraphmodule_handle_igraph_error(); igraphmodule_filehandle_destroy(&fobj); return NULL; @@ -8248,8 +8322,8 @@ PyObject *igraphmodule_Graph_Read_GraphML(PyTypeObject * type, PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - long source = 0, target = 0; - PyObject *capacity_obj = Py_None, *fname = NULL; + PyObject *capacity_obj = Py_None, *fname = NULL, *source_o, *target_o; + igraph_integer_t source, target; igraphmodule_filehandle_t fobj; igraph_vector_t* capacity = 0; @@ -8257,12 +8331,21 @@ PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, "f", "source", "target", "capacity", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oll|O", kwlist, &fname, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|O", kwlist, &fname, &source, &target, &capacity_obj)) return NULL; - if (igraphmodule_filehandle_init(&fobj, fname, "w")) + if (igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { + return NULL; + } + + if (igraphmodule_PyObject_to_vid(target_o, &target, &self->g)) { + return NULL; + } + + if (igraphmodule_filehandle_init(&fobj, fname, "w")) { return NULL; + } if (capacity_obj == Py_None) { capacity_obj = PyUnicode_FromString("capacity"); @@ -8594,7 +8677,7 @@ PyObject *igraphmodule_Graph_canonical_permutation( PyObject *list; igraph_bliss_sh_t sh = IGRAPH_BLISS_FL; igraph_vector_int_t labeling, *color = 0; - int retval; + igraph_error_t retval; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) return NULL; @@ -8719,7 +8802,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, igraph_vector_int_t mapping_12, mapping_21, *map12=0, *map21=0; igraph_bliss_sh_t sh1=IGRAPH_BLISS_FL, sh2=IGRAPH_BLISS_FL; igraph_vector_int_t *color1=0, *color2=0; - int retval; + igraph_error_t retval; static char *kwlist[] = { "other", "return_mapping_12", "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; @@ -8913,7 +8996,7 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, igraph_vector_int_t *color1=0, *color2=0; igraph_vector_int_t *edge_color1=0, *edge_color2=0; igraphmodule_i_Graph_isomorphic_vf2_callback_data_t callback_data; - int retval; + igraph_error_t retval; static char *kwlist[] = { "other", "color1", "color2", "edge_color1", "edge_color2", @@ -9252,7 +9335,7 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, igraph_vector_int_t *color1=0, *color2=0; igraph_vector_int_t *edge_color1=0, *edge_color2=0; igraphmodule_i_Graph_isomorphic_vf2_callback_data_t callback_data; - int retval; + igraph_error_t retval; static char *kwlist[] = { "other", "color1", "color2", "edge_color1", "edge_color2", "return_mapping_12", "return_mapping_21", @@ -9935,33 +10018,42 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "vid", "mode", NULL }; - long vid; - PyObject *l1, *l2, *l3, *result, *mode_o=Py_None; + PyObject *l1, *l2, *l3, *result, *mode_o = Py_None, *vid_o; + igraph_integer_t vid; igraph_neimode_t mode = IGRAPH_OUT; igraph_vector_int_t vids; igraph_vector_int_t layers; igraph_vector_int_t parents; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O", kwlist, &vid, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &vid_o, &mode_o)) return NULL; + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; - if (igraph_vector_int_init(&vids, igraph_vcount(&self->g))) + if (igraphmodule_PyObject_to_vid(vid_o, &vid, &self->g)) { + return NULL; + } + + if (igraph_vector_int_init(&vids, igraph_vcount(&self->g))) { return igraphmodule_handle_igraph_error(); + } + if (igraph_vector_int_init(&layers, igraph_vcount(&self->g))) { igraph_vector_int_destroy(&vids); return igraphmodule_handle_igraph_error(); } + if (igraph_vector_int_init(&parents, igraph_vcount(&self->g))) { igraph_vector_int_destroy(&vids); igraph_vector_int_destroy(&parents); return igraphmodule_handle_igraph_error(); } - if (igraph_bfs_simple - (&self->g, (igraph_integer_t) vid, mode, &vids, &layers, &parents)) { + + if (igraph_bfs_simple(&self->g, vid, mode, &vids, &layers, &parents)) { igraphmodule_handle_igraph_error(); return NULL; } + l1 = igraphmodule_vector_int_t_to_PyList(&vids); l2 = igraphmodule_vector_int_t_to_PyList(&layers); l3 = igraphmodule_vector_int_t_to_PyList(&parents); @@ -9973,9 +10065,11 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, if (l3) { Py_DECREF(l3); } result = NULL; } + igraph_vector_int_destroy(&vids); igraph_vector_int_destroy(&layers); igraph_vector_int_destroy(&parents); + return result; } @@ -10086,20 +10180,24 @@ PyObject *igraphmodule_Graph_dominator(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "vid", "mode", NULL }; - PyObject *list = Py_None; - PyObject *mode_o = Py_None; - long int root = -1; + PyObject *list = Py_None, *mode_o = Py_None, *root_o; + igraph_integer_t root; igraph_vector_int_t dom; igraph_neimode_t mode = IGRAPH_OUT; - int res ; + igraph_error_t res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|O", kwlist, &root, &mode_o)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &root_o, &mode_o)) { + return NULL; + } + + if (igraphmodule_PyObject_to_vid(root_o, &root, &self->g)) { return NULL; } if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; } + if (mode == IGRAPH_ALL) { mode = IGRAPH_OUT; } @@ -10107,15 +10205,19 @@ PyObject *igraphmodule_Graph_dominator(igraphmodule_GraphObject * self, if (igraph_vector_int_init(&dom, 0)) { return NULL; } + res = igraph_dominator_tree(&self->g, root, &dom, NULL, NULL, mode); - if(res) { + + if (res) { igraph_vector_int_destroy(&dom); return NULL; } + /* The igraph API uses -2 for vertices that are not reachable from the root, * but the Python API seems to be using nan judging from the unit tests */ list = igraphmodule_vector_int_t_to_PyList_with_nan(&dom, -2); igraph_vector_int_destroy(&dom); + return list; } @@ -10459,7 +10561,7 @@ PyObject *igraphmodule_Graph_mincut(igraphmodule_GraphObject * self, static char *kwlist[] = { "source", "target", "capacity", NULL }; PyObject *capacity_object = Py_None, *cut_o, *part_o, *part2_o, *result; PyObject *source_o = Py_None, *target_o = Py_None; - int retval; + igraph_error_t retval; igraph_vector_t capacity_vector; igraph_real_t value; igraph_vector_int_t partition, partition2, cut; @@ -10890,21 +10992,23 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, { static char *kwlist[] = { "min", "max", NULL }; PyObject *list, *item; - long int min_size = 0, max_size = 0; + Py_ssize_t min_size = 0, max_size = 0; igraph_integer_t i, j, n; igraph_vector_ptr_t result; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ll", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nn", kwlist, &min_size, &max_size)) return NULL; + CHECK_SSIZE_T_RANGE(min_size, "minimum size"); + CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + if (igraph_vector_ptr_init(&result, 0)) { PyErr_SetString(PyExc_MemoryError, ""); return NULL; } - if (igraph_cliques(&self->g, &result, (igraph_integer_t) min_size, - (igraph_integer_t) max_size)) { + if (igraph_cliques(&self->g, &result, min_size, max_size)) { igraph_vector_ptr_destroy(&result); return igraphmodule_handle_igraph_error(); } @@ -11120,21 +11224,23 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject { static char *kwlist[] = { "min", "max", NULL }; PyObject *list, *item; - long int min_size = 0, max_size = 0; + Py_ssize_t min_size = 0, max_size = 0; igraph_integer_t i, j, n; igraph_vector_ptr_t result; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ll", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nn", kwlist, &min_size, &max_size)) return NULL; + CHECK_SSIZE_T_RANGE(min_size, "minimum size"); + CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + if (igraph_vector_ptr_init(&result, 0)) { PyErr_SetString(PyExc_MemoryError, ""); return NULL; } - if (igraph_independent_vertex_sets(&self->g, &result, - (igraph_integer_t) min_size, (igraph_integer_t) max_size)) { + if (igraph_independent_vertex_sets(&self->g, &result, min_size, max_size)) { igraph_vector_ptr_destroy(&result); return igraphmodule_handle_igraph_error(); } @@ -11439,7 +11545,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject */ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "n", "weights", "arpack_options", NULL }; - long int n=-1; + Py_ssizeE_t n = -1; PyObject *cl, *res, *merges, *weights_obj = Py_None; igraph_vector_int_t membership; igraph_vector_t *weights = 0; @@ -11448,13 +11554,21 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj igraphmodule_ARPACKOptionsObject *arpack_options; PyObject *arpack_options_o = igraphmodule_arpack_options_default; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOO!", kwlist, &n, &weights_obj, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nOO!", kwlist, &n, &weights_obj, &igraphmodule_ARPACKOptionsType, &arpack_options_o)) { return NULL; } - if (igraph_vector_int_init(&membership, 0)) + if (n < 0) { + n = igraph_vcount(&self->g); + } else { + CHECK_SSIZE_T_RANGE(n, "number of communities"); + n -= 1; + } + + if (igraph_vector_int_init(&membership, 0)) { return igraphmodule_handle_igraph_error(); + } if (igraph_matrix_int_init(&m, 0, 0)) { igraphmodule_handle_igraph_error(); @@ -11462,20 +11576,14 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj return 0; } - if (n<0) - n = igraph_vcount(&self->g); - else - n -= 1; - - if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, - ATTRIBUTE_TYPE_EDGE)) { + if (igraphmodule_attrib_to_vector_t(weights_obj, self, &weights, ATTRIBUTE_TYPE_EDGE)) { igraph_matrix_int_destroy(&m); igraph_vector_int_destroy(&membership); return NULL; } arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; - if (igraph_community_leading_eigenvector(&self->g, weights, &m, &membership, (igraph_integer_t) n, + if (igraph_community_leading_eigenvector(&self->g, weights, &m, &membership, n, igraphmodule_ARPACKOptions_get(arpack_options), &q, 0, 0, 0, 0, 0, 0)){ igraph_matrix_int_destroy(&m); igraph_vector_int_destroy(&membership); @@ -11566,7 +11674,7 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, { static char *kwlist[] = { "edge_weights", "vertex_weights", "trials", NULL }; PyObject *e_weights = Py_None, *v_weights = Py_None; - unsigned int nb_trials = 10; + Py_ssize_t nb_trials = 10; igraph_vector_t *e_ws = 0, *v_ws = 0; igraph_vector_int_t membership; @@ -11574,11 +11682,13 @@ PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject * self, igraph_real_t codelength; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOI", kwlist, &e_weights, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOn", kwlist, &e_weights, &v_weights, &nb_trials)) { return NULL; } + CHECK_SSIZE_T_RANGE_POSITIVE(nb_trials, "number of trials"); + if (igraph_vector_int_init(&membership, igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); return NULL; @@ -11814,7 +11924,7 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, PyObject *impl_o = Py_None; PyObject *res; - long int spins = 25; + Py_ssize_t spins = 25; double start_temp = 1.0; double stop_temp = 0.01; double cool_fact = 0.99; @@ -11825,11 +11935,13 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, igraph_vector_t *weights = 0; igraph_vector_int_t membership; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlOdddOdOd", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOdddOdOd", kwlist, &weights_o, &spins, &parupdate_o, &start_temp, &stop_temp, &cool_fact, &update_rule_o, &gamma, &impl_o, &lambda)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(spins, "number of spins"); + if (igraphmodule_PyObject_to_spincomm_update_t(update_rule_o, &update_rule)) { return NULL; } @@ -11850,7 +11962,7 @@ PyObject *igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject *self, } if (igraph_community_spinglass(&self->g, weights, - 0, 0, &membership, 0, (igraph_integer_t) spins, + 0, 0, &membership, 0, spins, PyObject_IsTrue(parupdate_o), start_temp, stop_temp, cool_fact, update_rule, gamma, impl, lambda)) { @@ -11882,15 +11994,17 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, static char *kwlist[] = { "weights", "steps", NULL }; PyObject *ms, *qs, *res, *weights = Py_None; igraph_matrix_int_t merges; - int steps=4; + Py_ssize_t steps = 4; igraph_vector_t q, *ws=0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &weights, - &steps)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On", kwlist, &weights, &steps)) return NULL; - if (igraphmodule_attrib_to_vector_t(weights, self, &ws, ATTRIBUTE_TYPE_EDGE)) + CHECK_SSIZE_T_RANGE_POSITIVE(steps, "number of steps"); + + if (igraphmodule_attrib_to_vector_t(weights, self, &ws, ATTRIBUTE_TYPE_EDGE)) { return NULL; + } igraph_matrix_int_init(&merges, 0, 0); igraph_vector_init(&q, 0); @@ -11939,23 +12053,25 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, PyObject *edge_weights_o = Py_None; PyObject *node_weights_o = Py_None; PyObject *initial_membership_o = Py_None; + PyObject *normalize_resolution = Py_False; PyObject *res = Py_None; int error = 0, i; - long int n_iterations = 2; + Py_ssize_t n_iterations = 2; double resolution_parameter = 1.0; double beta = 0.01; igraph_vector_t *edge_weights = NULL, *node_weights = NULL; igraph_vector_int_t *membership = NULL; igraph_bool_t start = 1; - igraph_bool_t normalize_resolution = 0; igraph_integer_t nb_clusters = 0; igraph_real_t quality = 0.0, prev_quality = -IGRAPH_INFINITY; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdidOl", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOdOn", kwlist, &edge_weights_o, &node_weights_o, &resolution_parameter, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) return NULL; + CHECK_SSIZE_T_RANGE_POSITIVE(n_iterations, "number of iterations"); + /* Get edge weights */ if (igraphmodule_attrib_to_vector_t(edge_weights_o, self, &edge_weights, ATTRIBUTE_TYPE_EDGE)) { @@ -11988,7 +12104,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } } - if (normalize_resolution) + if (PyObject_IsTrue(normalize_resolution)) { /* If we need to normalize the resolution parameter, * we will need to have node weights. */ @@ -12051,10 +12167,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, free(membership); } - if (!error) - { return res; } - else - { return NULL; } + return error ? NULL : res; } /********************************************************************** @@ -12069,26 +12182,32 @@ PyObject *igraphmodule_Graph_random_walk(igraphmodule_GraphObject * self, static char *kwlist[] = { "start", "steps", "mode", "stuck", NULL }; PyObject *start_o, *mode_o = Py_None, *stuck_o = Py_None, *res; igraph_integer_t start; - int steps=10; + Py_ssize_t steps = 10; igraph_neimode_t mode = IGRAPH_OUT; igraph_random_walk_stuck_t stuck = IGRAPH_RANDOM_WALK_STUCK_RETURN; igraph_vector_int_t walk; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OiOO", kwlist, &start_o, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOO", kwlist, &start_o, &steps, &mode_o, &stuck_o)) return NULL; - if (igraphmodule_PyObject_to_vid(start_o, &start, &self->g)) + CHECK_SSIZE_T_RANGE(steps, "number of steps"); + + if (igraphmodule_PyObject_to_vid(start_o, &start, &self->g)) { return NULL; + } - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; + } - if (igraphmodule_PyObject_to_random_walk_stuck_t(stuck_o, &stuck)) + if (igraphmodule_PyObject_to_random_walk_stuck_t(stuck_o, &stuck)) { return NULL; + } - if (igraph_vector_int_init(&walk, steps)) + if (igraph_vector_int_init(&walk, steps)) { return igraphmodule_handle_igraph_error(); + } if (igraph_random_walk(&self->g, &walk, start, mode, steps, stuck)) { igraph_vector_int_destroy(&walk); From c7a17adaaffb23829993b96c87a4a32d4493ddfd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 00:47:22 +0200 Subject: [PATCH 0601/1892] fix: fix typos and failing tests introduced by the previous commit --- src/_igraph/graphobject.c | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 58eab13b2..82057dece 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -7404,7 +7404,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, { "dist", "dim", "arpack_options", NULL }; igraph_matrix_t m; igraph_matrix_t *dist = 0; - Py_ssiez_t dim = 2; + Py_ssize_t dim = 2; PyObject *dist_o = Py_None; PyObject *arpack_options_o = igraphmodule_arpack_options_default; PyObject *result; @@ -8332,7 +8332,7 @@ PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|O", kwlist, &fname, - &source, &target, &capacity_obj)) + &source_o, &target_o, &capacity_obj)) return NULL; if (igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { @@ -11000,8 +11000,17 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, &min_size, &max_size)) return NULL; - CHECK_SSIZE_T_RANGE(min_size, "minimum size"); - CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + if (min_size >= 0) { + CHECK_SSIZE_T_RANGE(min_size, "minimum size"); + } else { + min_size = -1; + } + + if (max_size >= 0) { + CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + } else { + max_size = -1; + } if (igraph_vector_ptr_init(&result, 0)) { PyErr_SetString(PyExc_MemoryError, ""); @@ -11149,8 +11158,8 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nnO", kwlist, &min, &max, &file)) return NULL; - CHECK_SSIZE_T_RANGE(min, "minimum clique size"); - CHECK_SSIZE_T_RANGE(max, "maximum clique size"); + CHECK_SSIZE_T_RANGE(min, "minimum size"); + CHECK_SSIZE_T_RANGE(max, "maximum size"); if (file == Py_None) { if (igraph_vector_ptr_init(&result, 0)) { @@ -11232,8 +11241,17 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject &min_size, &max_size)) return NULL; - CHECK_SSIZE_T_RANGE(min_size, "minimum size"); - CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + if (min_size >= 0) { + CHECK_SSIZE_T_RANGE(min_size, "minimum size"); + } else { + min_size = -1; + } + + if (max_size >= 0) { + CHECK_SSIZE_T_RANGE(max_size, "maximum size"); + } else { + max_size = -1; + } if (igraph_vector_ptr_init(&result, 0)) { PyErr_SetString(PyExc_MemoryError, ""); @@ -11545,7 +11563,7 @@ PyObject *igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject */ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "n", "weights", "arpack_options", NULL }; - Py_ssizeE_t n = -1; + Py_ssize_t n = -1; PyObject *cl, *res, *merges, *weights_obj = Py_None; igraph_vector_int_t membership; igraph_vector_t *weights = 0; @@ -12070,7 +12088,11 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, &edge_weights_o, &node_weights_o, &resolution_parameter, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) return NULL; - CHECK_SSIZE_T_RANGE_POSITIVE(n_iterations, "number of iterations"); + if (n_iterations >= 0) { + CHECK_SSIZE_T_RANGE(n_iterations, "number of iterations"); + } else { + n_iterations = -1; + } /* Get edge weights */ if (igraphmodule_attrib_to_vector_t(edge_weights_o, self, &edge_weights, From 16d4737fe6e583d3b863141c5bacc042e523e245 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 00:55:06 +0200 Subject: [PATCH 0602/1892] refactor: removed last remaining instances of "long int"; Python interface should be fully 64-bit compatible now --- src/_igraph/convert.c | 67 +++++++++++++++++++++++--------------- src/_igraph/graphobject.c | 6 ++-- src/_igraph/vertexobject.c | 14 ++++---- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index ca14f4e24..715afc7eb 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1741,14 +1741,19 @@ int igraphmodule_attrib_to_vector_t(PyObject *o, igraphmodule_GraphObject *self, igraph_vector_t *result; *vptr = 0; - if (attr_type != ATTRIBUTE_TYPE_EDGE && attr_type != ATTRIBUTE_TYPE_VERTEX) + if (attr_type != ATTRIBUTE_TYPE_EDGE && attr_type != ATTRIBUTE_TYPE_VERTEX) { return 1; - if (o == Py_None) return 0; + } + + if (o == Py_None) { + return 0; + } + if (PyUnicode_Check(o)) { /* Check whether the attribute exists and is numeric */ igraph_attribute_type_t at; igraph_attribute_elemtype_t et; - long int n; + igraph_integer_t n; char *name = PyUnicode_CopyAsString(o); if (attr_type == ATTRIBUTE_TYPE_VERTEX) { @@ -1772,7 +1777,7 @@ int igraphmodule_attrib_to_vector_t(PyObject *o, igraphmodule_GraphObject *self, /* Now that the attribute type has been checked, allocate the target * vector */ result = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); - if (result==0) { + if (result == 0) { PyErr_NoMemory(); free(name); return 1; @@ -1801,7 +1806,7 @@ int igraphmodule_attrib_to_vector_t(PyObject *o, igraphmodule_GraphObject *self, *vptr = result; } else if (PySequence_Check(o)) { result = (igraph_vector_t*)calloc(1, sizeof(igraph_vector_t)); - if (result==0) { + if (result == 0) { PyErr_NoMemory(); return 1; } @@ -1942,7 +1947,7 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * return 0; if (PyUnicode_Check(o)) { - long int i, n; + igraph_integer_t i, n; /* First, check if the attribute is a "real" boolean */ igraph_attribute_type_t at; @@ -1967,7 +1972,7 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * /* The attribute is a real Boolean attribute. Allocate the target * vector */ result = (igraph_vector_bool_t*)calloc(1, sizeof(igraph_vector_bool_t)); - if (result==0) { + if (result == 0) { PyErr_NoMemory(); free(name); return 1; @@ -2009,12 +2014,12 @@ int igraphmodule_attrib_to_vector_bool_t(PyObject *o, igraphmodule_GraphObject * n = igraph_vector_size(dummy); result = (igraph_vector_bool_t*)calloc(1, sizeof(igraph_vector_bool_t)); igraph_vector_bool_init(result, n); - if (result==0) { + if (result == 0) { igraph_vector_destroy(dummy); free(dummy); PyErr_NoMemory(); return 1; } - for (i=0; ig); - else if (type == ATTRHASH_IDX_EDGE) n=igraph_ecount(&g->g); - else n=1; + if (type == ATTRHASH_IDX_VERTEX) { + n = igraph_vcount(&g->g); + } else if (type == ATTRHASH_IDX_EDGE) { + n = igraph_ecount(&g->g); + } else { + n = 1; + } + + if (igraph_vector_init(v, n)) { + return 1; + } - if (igraph_vector_init(v, n)) return 1; - for (i=0; igref; PyObject *names, *dict; - long i, n; + Py_ssize_t i, n; if (!igraphmodule_Vertex_Validate((PyObject*)self)) return 0; - dict=PyDict_New(); - if (!dict) return NULL; + dict = PyDict_New(); + if (!dict) { + return NULL; + } - names=igraphmodule_Graph_vertex_attributes(o); + names = igraphmodule_Graph_vertex_attributes(o); if (!names) { Py_DECREF(dict); return NULL; } - n=PyList_Size(names); - for (i=0; i Date: Fri, 10 Sep 2021 11:40:13 +0200 Subject: [PATCH 0603/1892] chore: setup.py cleanup + added typing to setup.py --- setup.py | 248 +++++++++++++++++++++++++++---------------------------- tox.ini | 5 +- 2 files changed, 126 insertions(+), 127 deletions(-) diff --git a/setup.py b/setup.py index 3ed791065..4d2a7ffcf 100644 --- a/setup.py +++ b/setup.py @@ -11,12 +11,6 @@ print("This module requires Python >= 3.6") sys.exit(0) -# Check whether we are compiling for PyPy. Headers will not be installed -# for PyPy. -SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ( - "SKIP_HEADER_INSTALL" in os.environ -) - ########################################################################### from setuptools import setup, Command, Extension @@ -28,10 +22,12 @@ import sys import sysconfig +from contextlib import contextmanager from pathlib import Path from select import select from shutil import which from time import sleep +from typing import List, Iterable, Iterator, Optional, Tuple, TypeVar, Union ########################################################################### @@ -39,25 +35,31 @@ LIBIGRAPH_FALLBACK_LIBRARIES = ["igraph"] LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [] +# Check whether we are compiling for PyPy. Headers will not be installed +# for PyPy. +SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ( + "SKIP_HEADER_INSTALL" in os.environ +) + ########################################################################### -is_windows = platform.system() == "windows" +T = TypeVar("T") -def building_on_windows_msvc(): +def building_on_windows_msvc() -> bool: """Returns True when using the non-MinGW CPython interpreter on Windows""" return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" -def exclude_from_list(items, items_to_exclude): +def exclude_from_list(items: Iterable[T], items_to_exclude: Iterable[T]) -> List[T]: """Excludes certain items from a list, keeping the original order of the remaining items.""" itemset = set(items_to_exclude) return [item for item in items if item not in itemset] -def find_static_library(library_name, library_path): +def find_static_library(library_name: str, library_path: List[str]) -> Optional[str]: """Given the raw name of a library in `library_name`, tries to find a static library with this name in the given `library_path`. `library_path` is automatically extended with common library directories on Linux and Mac @@ -88,15 +90,17 @@ def find_static_library(library_name, library_path): return full_path -def first(iterable): +def first(iterable: Iterable[T]) -> T: """Returns the first element from the given iterable.""" for item in iterable: return item raise ValueError("iterable is empty") -def get_output(args, encoding="utf-8"): - """Returns the output of a command returning a single line of output.""" +def get_output(args, encoding: str = "utf-8") -> Tuple[str, int]: + """Returns the output of a command returning a single line of output, and + the exit code of the command. + """ PIPE = subprocess.PIPE try: p = subprocess.Popen(args, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE) @@ -105,25 +109,23 @@ def get_output(args, encoding="utf-8"): except OSError: stdout, stderr = None, None returncode = 77 - if encoding and type(stdout).__name__ == "bytes": + if isinstance(stdout, bytes): stdout = str(stdout, encoding=encoding) - if encoding and type(stderr).__name__ == "bytes": + if isinstance(stderr, bytes): stderr = str(stderr, encoding=encoding) - return stdout, returncode + return (stdout or ""), returncode -def get_output_single_line(args, encoding="utf-8"): - """Returns the output of a command returning a single line of output, - stripped from any trailing newlines.""" +def get_output_single_line(args, encoding: str = "utf-8") -> Tuple[str, int]: + """Returns the first line of the output of a command, stripped from any + trailing newlines, and the exit code of the command. + """ stdout, returncode = get_output(args, encoding=encoding) - if stdout is not None: - line, _, _ = stdout.partition("\n") - else: - line = None + line, _, _ = stdout.partition("\n") return line, returncode -def is_unix_like(platform=None): +def is_unix_like(platform: str = sys.platform) -> bool: """Returns whether the given platform is a Unix-like platform with the usual Unix filesystem. When the parameter is omitted, it defaults to ``sys.platform`` """ @@ -136,12 +138,10 @@ def is_unix_like(platform=None): ) -def wait_for_keypress(seconds): +def wait_for_keypress(seconds: float) -> None: """Wait for a keypress or until the given number of seconds have passed, whichever happens first. """ - global is_windows - while seconds > 0: if seconds > 1: plural = "s" @@ -154,10 +154,10 @@ def wait_for_keypress(seconds): ) sys.stdout.flush() - if is_windows: - from msvcrt import kbhit + if platform.system() == "Windows": + from msvcrt import kbhit # type: ignore - for i in range(10): + for _ in range(10): if kbhit(): seconds = 0 break @@ -174,62 +174,48 @@ def wait_for_keypress(seconds): sys.stdout.write("\r" + " " * 65 + "\r") -########################################################################### - - -class IgraphCCoreBuilder: - """Superclass for classes responsible for downloading and building the - C core of igraph if it is not installed yet. - """ - - def create_build_config_file(self, install_folder, libraries): - with (install_folder / "build.cfg").open("w") as fp: - fp.write(repr(libraries)) - - def parse_pkgconfig_file(self, filename): - building_on_windows = building_on_windows_msvc() - - if building_on_windows: - libraries = ["igraph"] - else: - libraries = [] - with filename.open("r") as fp: - for line in fp: - if line.startswith("Libs: ") or line.startswith("Libs.private: "): - words = line.strip().split() - libraries.extend( - word[2:] for word in words if word.startswith("-l") - ) - - if not libraries: - # Educated guess - libraries = ["igraph"] - - return libraries +@contextmanager +def working_directory(dir: Union[str, Path]) -> Iterator[None]: + cwd = os.getcwd() + os.chdir(dir) + try: + yield + finally: + os.chdir(cwd) ########################################################################### -class IgraphCCoreCMakeBuilder(IgraphCCoreBuilder): +class IgraphCCoreCMakeBuilder: """Class responsible for downloading and building the C core of igraph if it is not installed yet, assuming that the C core uses CMake as the build tool. This is the case from igraph 0.9. - - Returns: - False if the build failed or the list of libraries to link to when - linking the Python interface to igraph """ - def compile_in(self, source_folder, build_folder, install_folder): + def compile_in( + self, source_folder: Path, build_folder: Path, install_folder: Path + ) -> Union[bool, List[str]]: """Compiles igraph from its source code in the given folder. - source_folder is the name of the folder that contains igraph's source - files. build_folder is the name of the folder where the build should - be executed. Both must be absolute paths. + Parameters: + source_folder: absolute path to the folder that contains igraph's + source files + build_folder: absolute path to the folder where the build should be + executed + install_folder: absolute path to the folder where the built library + should be installed + + Returns: + False if the build failed or the list of libraries to link to when + linking the Python interface to igraph """ - global is_windows + with working_directory(build_folder): + return self._compile_in(source_folder, build_folder, install_folder) + def _compile_in( + self, source_folder: Path, build_folder: Path, install_folder: Path + ) -> Union[bool, List[str]]: cmake = which("cmake") if not cmake: print( @@ -239,7 +225,6 @@ def compile_in(self, source_folder, build_folder, install_folder): return False build_to_source_folder = os.path.relpath(source_folder, build_folder) - os.chdir(build_folder) print("Configuring build...") args = [cmake] @@ -290,12 +275,39 @@ def compile_in(self, source_folder, build_folder, install_folder): ] for candidate in pkgconfig_candidates: if candidate.exists(): - return self.parse_pkgconfig_file(candidate) + return self._parse_pkgconfig_file(candidate) raise RuntimeError( "no igraph.pc was found in the installation folder of igraph" ) + def create_build_config_file( + self, install_folder: Path, libraries: List[str] + ) -> None: + with (install_folder / "build.cfg").open("w") as fp: + fp.write(repr(libraries)) + + def _parse_pkgconfig_file(self, filename: Path) -> List[str]: + building_on_windows = building_on_windows_msvc() + + if building_on_windows: + libraries = ["igraph"] + else: + libraries = [] + with filename.open("r") as fp: + for line in fp: + if line.startswith("Libs: ") or line.startswith("Libs.private: "): + words = line.strip().split() + libraries.extend( + word[2:] for word in words if word.startswith("-l") + ) + + if not libraries: + # Educated guess + libraries = ["igraph"] + + return libraries + ########################################################################### @@ -312,25 +324,26 @@ def __init__(self): self.extra_objects = [] self.static_extension = False self.use_pkgconfig = False + self.c_core_built = False self._has_pkgconfig = None self.excluded_include_dirs = [] self.excluded_library_dirs = [] self.wait = platform.system() != "Windows" @property - def has_pkgconfig(self): + def has_pkgconfig(self) -> bool: """Returns whether ``pkg-config`` is available on the current system and it knows about igraph or not.""" if self._has_pkgconfig is None: if self.use_pkgconfig: - line, exit_code = get_output_single_line(["pkg-config", "igraph"]) + _, exit_code = get_output_single_line(["pkg-config", "igraph"]) self._has_pkgconfig = exit_code == 0 else: self._has_pkgconfig = False return self._has_pkgconfig @property - def build_c_core(self): + def build_c_core(self) -> Command: """Returns a class representing a custom setup.py command that builds the C core of igraph. @@ -359,7 +372,7 @@ def run(self): return build_c_core @property - def build_ext(self): + def build_ext(self) -> Command: """Returns a class that can be used as a replacement for the ``build_ext`` command in ``setuptools`` and that will compile the C core of igraph before compiling the Python extension. @@ -467,60 +480,48 @@ def sdist(self): """ from setuptools.command.sdist import sdist - def is_git_repo(folder): - return os.path.exists(os.path.join(folder, ".git")) + def is_git_repo(folder) -> bool: + return (Path(folder) / ".git").exists() - def cleanup_git_repo(folder): - folder = str(folder) - cwd = os.getcwd() - try: - os.chdir(folder) + def cleanup_git_repo(folder) -> None: + with working_directory(folder): if os.path.exists(".git"): retcode = subprocess.call("git clean -dfx", shell=True) if retcode: raise RuntimeError(f"Failed to clean {folder} with git") - finally: - os.chdir(cwd) class custom_sdist(sdist): def run(self): - igraph_source_repo = os.path.join("vendor", "source", "igraph") - igraph_build_dir = os.path.join("vendor", "build", "igraph") - version_file = os.path.join(igraph_source_repo, "IGRAPH_VERSION") + igraph_source_repo = Path("vendor", "source", "igraph") + igraph_build_dir = Path("vendor", "build", "igraph") + version_file = igraph_source_repo / "IGRAPH_VERSION" version = None # Check whether the source repo contains an IGRAPH_VERSION file, # and extract the version number from that - if os.path.exists(version_file): - with open(version_file, "r") as fp: - version = fp.read().strip().split("\n")[0] + if version_file.exists(): + version = version_file.read_text().strip().split("\n")[0] # If no IGRAPH_VERSION file exists, but we have a git repo, try # git describe if not version and is_git_repo(igraph_source_repo): - cwd = os.getcwd() - try: - os.chdir(igraph_source_repo) + with working_directory(igraph_source_repo): version = ( subprocess.check_output("git describe", shell=True) .decode("utf-8") .strip() ) - finally: - os.chdir(cwd) # If we still don't have a version number, try to parse it from # include/igraph_version.h if not version: - version_header = os.path.join( - igraph_build_dir, "include", "igraph_version.h" - ) - if not os.path.exists(version_header): + version_header = igraph_build_dir / "include" / "igraph_version.h" + if not version_header.exists(): raise RuntimeError( "You need to build the C core of igraph first before generating a source tarball of python-igraph" ) - with open(version_header, "r") as fp: + with version_header.open("r") as fp: lines = [ line.strip() for line in fp @@ -543,20 +544,20 @@ def run(self): cleanup_git_repo(igraph_source_repo) # Copy the generated parser sources from the build folder - parser_dir = os.path.join(igraph_build_dir, "src", "io", "parsers") - if os.path.isdir(parser_dir): + parser_dir = igraph_build_dir / "src" / "io" / "parsers" + if parser_dir.is_dir(): shutil.copytree( parser_dir, - os.path.join(igraph_source_repo, "src", "io", "parsers"), + igraph_source_repo / "src" / "io" / "parsers" ) else: raise RuntimeError( - f"You need to build the C core of igraph first before generating a source tarball of python-igraph" + "You need to build the C core of igraph first before " + "generating a source tarball of python-igraph" ) # Add a version file to the tarball - with open(version_file, "w") as fp: - fp.write(version) + version_file.write_text(version) # Run the original sdist command retval = sdist.run(self) @@ -568,7 +569,7 @@ def run(self): return custom_sdist - def compile_igraph_from_vendor_source(self): + def compile_igraph_from_vendor_source(self) -> bool: """Compiles igraph from the vendored source code inside `vendor/source/igraph`. This folder typically comes from a git submodule. """ @@ -601,27 +602,25 @@ def compile_igraph_from_vendor_source(self): Path(build_folder).mkdir(parents=True, exist_ok=True) - cwd = os.getcwd() - try: - libraries = igraph_builder.compile_in( - source_folder=source_folder, - build_folder=build_folder, - install_folder=install_folder, - ) - finally: - os.chdir(cwd) + libraries = igraph_builder.compile_in( + source_folder=source_folder, + build_folder=build_folder, + install_folder=install_folder, + ) if libraries is False: print("Build failed for the C core of igraph.") print("") sys.exit(1) + assert not isinstance(libraries, bool) + igraph_builder.create_build_config_file(install_folder, libraries) self.use_vendored_igraph() return True - def configure(self, ext): + def configure(self, ext) -> None: """Configures the given Extension object using this build configuration.""" ext.include_dirs = exclude_from_list( self.include_dirs, self.excluded_include_dirs @@ -636,7 +635,7 @@ def configure(self, ext): ext.extra_objects = self.extra_objects ext.define_macros = self.define_macros - def detect_from_pkgconfig(self): + def detect_from_pkgconfig(self) -> bool: """Detects the igraph include directory, library directory and the list of libraries to link to using ``pkg-config``.""" if not buildcfg.has_pkgconfig: @@ -655,7 +654,7 @@ def detect_from_pkgconfig(self): self.include_dirs = [opt[2:] for opt in opts if opt.startswith("-I")] return True - def print_build_info(self): + def print_build_info(self) -> None: """Prints the include and library path being used for debugging purposes.""" if self.static_extension == "only_igraph": build_type = "dynamic extension with vendored igraph source" @@ -719,7 +718,7 @@ def replace_static_libraries(self, only=None, exclusions=None): else: print(f"Warning: could not find static library of {library_name}.") - def use_vendored_igraph(self): + def use_vendored_igraph(self) -> None: """Assumes that igraph is installed already in ``vendor/install/igraph`` and sets up the include and library paths and the library names accordingly.""" building_on_windows = building_on_windows_msvc() @@ -748,7 +747,7 @@ def use_vendored_igraph(self): if buildcfg_file.exists(): buildcfg.libraries = eval(buildcfg_file.open("r").read()) - def use_educated_guess(self): + def use_educated_guess(self) -> None: """Tries to guess the proper library names, include and library paths if everything else failed.""" @@ -790,7 +789,6 @@ def use_educated_guess(self): buildcfg = BuildConfiguration() buildcfg.process_args_from_command_line() - # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) sources.append(os.path.join("src", "_igraph", "force_cpp_linker.cpp")) diff --git a/tox.ini b/tox.ini index d144c3963..c51b45b25 100644 --- a/tox.ini +++ b/tox.ini @@ -27,6 +27,7 @@ setenv = TESTING_IN_TOX=1 [flake8] -max-line-length = 88 -extend-ignore = E203, W503 +max-line-length = 80 +select = C,E,F,W,B,B950 +ignore = E203,E501,W503 From 93d540f42a2255f3d6a4680e50afbdf5ec277ae2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 11:41:15 +0200 Subject: [PATCH 0604/1892] fix: IGRAPH_USE_INTERNAL_CXSPARSE is not an option any more in igraph's C core --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4d2a7ffcf..c7dbb458c 100644 --- a/setup.py +++ b/setup.py @@ -230,7 +230,7 @@ def _compile_in( args = [cmake] # Build the Python interface with vendored libraries - for deps in "ARPACK BLAS CXSPARSE GLPK GMP LAPACK".split(): + for deps in "ARPACK BLAS GLPK GMP LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") # -fPIC is needed on Linux so we can link to a static igraph lib from a From 449ac36e800b5c52a080f5bd150fc49538d4b73b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 11:41:15 +0200 Subject: [PATCH 0605/1892] fix: IGRAPH_USE_INTERNAL_CXSPARSE is not an option any more in igraph's C core --- warnings_converted_to_errors.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 warnings_converted_to_errors.py diff --git a/warnings_converted_to_errors.py b/warnings_converted_to_errors.py deleted file mode 100644 index 76ee5230b..000000000 --- a/warnings_converted_to_errors.py +++ /dev/null @@ -1,11 +0,0 @@ -from igraph import Graph -import warnings - -warnings.simplefilter('error', 'Cannot shuffle graph') -degseq = [1,2,2,3] -try: - testgraph = Graph.Degree_Sequence(degseq,method = "vl") -except RuntimeWarning: - print(degseq) -else: - print("go on") From 90536171a36a5e2ab4ca74c69d3cd1adc071b738 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 13:47:18 +0200 Subject: [PATCH 0606/1892] refactor: centralized inclusion of Python.h, started migrating to Python's limited API --- src/_igraph/arpackobject.c | 126 ++++++++++------------------------ src/_igraph/arpackobject.h | 12 ++-- src/_igraph/attributes.c | 1 - src/_igraph/attributes.h | 3 +- src/_igraph/bfsiter.h | 3 +- src/_igraph/common.h | 2 +- src/_igraph/convert.c | 1 - src/_igraph/convert.h | 3 +- src/_igraph/dfsiter.h | 3 +- src/_igraph/edgeobject.h | 3 +- src/_igraph/edgeseqobject.h | 3 +- src/_igraph/error.h | 3 +- src/_igraph/filehandle.h | 3 +- src/_igraph/graphobject.c | 16 ++--- src/_igraph/graphobject.h | 3 +- src/_igraph/igraphmodule.c | 10 +-- src/_igraph/indexing.h | 3 +- src/_igraph/operators.h | 2 +- src/_igraph/preamble.h | 29 ++++++++ src/_igraph/pyhelpers.h | 2 +- src/_igraph/random.h | 2 +- src/_igraph/vertexobject.h | 3 +- src/_igraph/vertexseqobject.c | 1 - src/_igraph/vertexseqobject.h | 3 +- 24 files changed, 112 insertions(+), 128 deletions(-) create mode 100644 src/_igraph/preamble.h diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 7f31f506c..142f0a074 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -24,25 +24,16 @@ #include "graphobject.h" #include "error.h" +PyTypeObject* igraphmodule_ARPACKOptionsType; PyObject* igraphmodule_arpack_options_default; -/** - * \ingroup python_interface_arpack - * \brief Checks if the object is an ARPACK parameter object - */ -int igraphmodule_ARPACKOptions_Check(PyObject *ob) { - if (ob) return PyType_IsSubtype(ob->ob_type, &igraphmodule_ARPACKOptionsType); - return 0; -} - /** * \ingroup python_interface_arpack * \brief Allocates a new ARPACK parameters object */ PyObject* igraphmodule_ARPACKOptions_new() { igraphmodule_ARPACKOptionsObject* self; - self=PyObject_New(igraphmodule_ARPACKOptionsObject, - &igraphmodule_ARPACKOptionsType); + self = PyObject_New(igraphmodule_ARPACKOptionsObject, igraphmodule_ARPACKOptionsType); if (self) { igraph_arpack_options_init(&self->params); igraph_arpack_options_init(&self->params_out); @@ -54,16 +45,16 @@ PyObject* igraphmodule_ARPACKOptions_new() { * \ingroup python_interface_arpack * \brief Deallocates a Python representation of a given ARPACK parameters object */ -void igraphmodule_ARPACKOptions_dealloc( - igraphmodule_ARPACKOptionsObject* self) { - /*igraph_arpack_options_destroy(&self->params);*/ +static void igraphmodule_ARPACKOptions_dealloc(igraphmodule_ARPACKOptionsObject* self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_Del((PyObject*)self); + Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } /** \ingroup python_interface_arpack * \brief Returns one of the attributes of a given ARPACK parameters object */ -PyObject* igraphmodule_ARPACKOptions_getattr( +static PyObject* igraphmodule_ARPACKOptions_getattr( igraphmodule_ARPACKOptionsObject* self, char* attrname) { PyObject *result = NULL; @@ -117,7 +108,7 @@ PyObject* igraphmodule_ARPACKOptions_getattr( /** \ingroup python_interface_arpack * \brief Sets one of the attributes of a given ARPACK parameters object */ -int igraphmodule_ARPACKOptions_setattr( +static int igraphmodule_ARPACKOptions_setattr( igraphmodule_ARPACKOptionsObject* self, char* attrname, PyObject* value) { if (value == 0) { @@ -175,63 +166,12 @@ igraph_arpack_options_t *igraphmodule_ARPACKOptions_get( * * \return the formatted textual representation as a \c PyObject */ -PyObject* igraphmodule_ARPACKOptions_str( - igraphmodule_ARPACKOptionsObject *self) { - PyObject *s; - - s=PyUnicode_FromFormat("ARPACK parameters"); - return s; +PyObject* igraphmodule_ARPACKOptions_str(igraphmodule_ARPACKOptionsObject *self) { + return PyUnicode_FromString("ARPACK parameters"); } -/** - * \ingroup python_interface_arpack - * Method table for the \c igraph.ARPACKOptions object - */ -PyMethodDef igraphmodule_ARPACKOptions_methods[] = { - /*{"attributes", (PyCFunction)igraphmodule_Edge_attributes, - METH_NOARGS, - "attributes()\n--\n\n" - "Returns the attribute list of the graph's edges\n" - },*/ - {NULL} -}; - -/** - * \ingroup python_interface_edge - * Getter/setter table for the \c igraph.ARPACKOptions object - */ -PyGetSetDef igraphmodule_ARPACKOptions_getseters[] = { - /*{"tuple", (getter)igraphmodule_Edge_get_tuple, NULL, - "Source and target node index of this edge as a tuple", NULL - },*/ - {NULL} -}; - -/** \ingroup python_interface_edge - * Python type object referencing the methods Python calls when it performs - * various operations on an ARPACK parameters object - */ -PyTypeObject igraphmodule_ARPACKOptionsType = { - PyVarObject_HEAD_INIT(0, 0) - "igraph.ARPACKOptions", /* tp_name */ - sizeof(igraphmodule_ARPACKOptionsObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)igraphmodule_ARPACKOptions_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc)igraphmodule_ARPACKOptions_getattr, /* tp_getattr */ - (setattrfunc)igraphmodule_ARPACKOptions_setattr, /* tp_setattr */ - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)igraphmodule_ARPACKOptions_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ +PyDoc_STRVAR( + igraphmodule_ARPACKOptions_doc, "Class representing the parameters of the ARPACK module.\n\n" "ARPACK is a Fortran implementation of the implicitly restarted\n" "Arnoldi method, an algorithm for calculating some of the\n" @@ -257,24 +197,30 @@ PyTypeObject igraphmodule_ARPACKOptionsType = { " - C{numop}: total number of OP*x operations\n\n" " - C{numopb}: total number of B*x operations if C{bmat} is C{'G'}\n\n" " - C{numreo}: total number of steps of re-orthogonalization\n\n" - "", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - igraphmodule_ARPACKOptions_methods, /* tp_methods */ - 0, /* tp_members */ - igraphmodule_ARPACKOptions_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - (newfunc)igraphmodule_ARPACKOptions_new, /* tp_new */ - 0, /* tp_free */ +); + +PyType_Slot igraphmodule_ARPACKOptions_slots[] = { + { Py_tp_new, igraphmodule_ARPACKOptions_new }, + { Py_tp_dealloc, igraphmodule_ARPACKOptions_dealloc }, + { Py_tp_getattr, igraphmodule_ARPACKOptions_getattr }, + { Py_tp_setattr, igraphmodule_ARPACKOptions_setattr }, + { Py_tp_str, igraphmodule_ARPACKOptions_str }, + { Py_tp_doc, (void*) igraphmodule_ARPACKOptions_doc }, + { 0 } }; +/** \ingroup python_interface_arpack + * Python type specification for \c igraph.ARPACKOptions + */ +PyType_Spec igraphmodule_ARPACKOptions_spec = { + "igraph.ARPACKOptions", /* name */ + sizeof(igraphmodule_ARPACKOptionsObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + igraphmodule_ARPACKOptions_slots, /* slots */ +}; + +int igraphmodule_ARPACKOptions_register_type() { + igraphmodule_ARPACKOptionsType = (PyTypeObject*) PyType_FromSpec(&igraphmodule_ARPACKOptions_spec); + return igraphmodule_ARPACKOptionsType == 0; +} diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index b9d663d30..5d5fd31d0 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -23,7 +23,9 @@ #ifndef PYTHON_ARPACKOBJECT_H #define PYTHON_ARPACKOBJECT_H -#include +#define Py_LIMITED_API 0x03060000 +#include "preamble.h" + #include #include "graphobject.h" @@ -31,7 +33,6 @@ * \ingroup python_interface * \defgroup python_interface_arpack ARPACK parameters object */ -extern PyTypeObject igraphmodule_ARPACKOptionsType; /** * \ingroup python_interface_arpack @@ -43,13 +44,12 @@ typedef struct { igraph_arpack_options_t params_out; } igraphmodule_ARPACKOptionsObject; +extern PyTypeObject* igraphmodule_ARPACKOptionsType; extern PyObject* igraphmodule_arpack_options_default; -void igraphmodule_ARPACKOptions_dealloc(igraphmodule_ARPACKOptionsObject* self); +int igraphmodule_ARPACKOptions_register_type(); PyObject* igraphmodule_ARPACKOptions_new(void); -PyObject* igraphmodule_ARPACKOptions_str(igraphmodule_ARPACKOptionsObject *self); -#define igraphmodule_ARPACKOptions_CheckExact(ob) ((ob)->ob_type == &igraphmodule_ARPACKOptionsType) igraph_arpack_options_t *igraphmodule_ARPACKOptions_get(igraphmodule_ARPACKOptionsObject *self); -int igraphmodule_ARPACKOptions_Check(PyObject *ob); + #endif diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 7c4eb8749..95375559a 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -20,7 +20,6 @@ */ -#include #include "attributes.h" #include "common.h" #include "convert.h" diff --git a/src/_igraph/attributes.h b/src/_igraph/attributes.h index 5e68f2a2b..c3faa95ac 100644 --- a/src/_igraph/attributes.h +++ b/src/_igraph/attributes.h @@ -23,7 +23,8 @@ #ifndef PY_IGRAPH_ATTRIBUTES_H #define PY_IGRAPH_ATTRIBUTES_H -#include +#include "preamble.h" + #include #include #include diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index 94ddb6113..4fa665462 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -23,7 +23,8 @@ #ifndef PYTHON_BFSITER_H #define PYTHON_BFSITER_H -#include +#include "preamble.h" + #include "graphobject.h" /** diff --git a/src/_igraph/common.h b/src/_igraph/common.h index e74a6fa67..31a434353 100644 --- a/src/_igraph/common.h +++ b/src/_igraph/common.h @@ -23,7 +23,7 @@ #ifndef PYTHON_COMMON_H #define PYTHON_COMMON_H -#include +#include "preamble.h" #ifdef RC_DEBUG # define RC_ALLOC(T, P) fprintf(stderr, "[ alloc ] " T " @ %p\n", P) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 717158136..8b2330b57 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -22,7 +22,6 @@ /************************ Miscellaneous functions *************************/ -#include #include #include "attributes.h" #include "convert.h" diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index bff912b83..4c50219a2 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -28,7 +28,8 @@ #ifndef PYTHON_CONVERT_H #define PYTHON_CONVERT_H -#include +#include "preamble.h" + #include #include #include "graphobject.h" diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h index 0a094c592..880965fcd 100644 --- a/src/_igraph/dfsiter.h +++ b/src/_igraph/dfsiter.h @@ -23,7 +23,8 @@ #ifndef PYTHON_DFSITER_H #define PYTHON_DFSITER_H -#include +#include "preamble.h" + #include "graphobject.h" /** diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index 2d7f3a259..ac0a93668 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -23,7 +23,8 @@ #ifndef PYTHON_EDGEOBJECT_H #define PYTHON_EDGEOBJECT_H -#include +#include "preamble.h" + #include "graphobject.h" /** diff --git a/src/_igraph/edgeseqobject.h b/src/_igraph/edgeseqobject.h index 7a410b9e1..b8fd2f127 100644 --- a/src/_igraph/edgeseqobject.h +++ b/src/_igraph/edgeseqobject.h @@ -23,7 +23,8 @@ #ifndef PYTHON_EDGESEQOBJECT_H #define PYTHON_EDGESEQOBJECT_H -#include +#include "preamble.h" + #include "graphobject.h" /** diff --git a/src/_igraph/error.h b/src/_igraph/error.h index 8d54e728c..03c50ab10 100644 --- a/src/_igraph/error.h +++ b/src/_igraph/error.h @@ -23,7 +23,8 @@ #ifndef PYTHON_ERROR_H #define PYTHON_ERROR_H -#include +#include "preamble.h" + #include /** \defgroup python_interface_errors Error handling diff --git a/src/_igraph/filehandle.h b/src/_igraph/filehandle.h index 68bf3c3be..6f3c5acf7 100644 --- a/src/_igraph/filehandle.h +++ b/src/_igraph/filehandle.h @@ -23,7 +23,8 @@ #ifndef PYTHON_FILEHANDLE_H #define PYTHON_FILEHANDLE_H -#include +#include "preamble.h" + #include /** diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 31ffe0caf..2bb48112b 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3774,7 +3774,7 @@ PyObject *igraphmodule_Graph_authority_score( igraph_vector_t res, *weights = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO!O", kwlist, &weights_o, - &scale_o, &igraphmodule_ARPACKOptionsType, + &scale_o, igraphmodule_ARPACKOptionsType, &arpack_options_o, &return_eigenvalue)) return NULL; @@ -4634,7 +4634,7 @@ PyObject* igraphmodule_Graph_eigen_adjacency(igraphmodule_GraphObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO!", kwlist, &algorithm_o, &which_o, - &igraphmodule_ARPACKOptionsType, + igraphmodule_ARPACKOptionsType, &arpack_options)) { return NULL; } @@ -4789,7 +4789,7 @@ PyObject *igraphmodule_Graph_eigenvector_centrality( if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO!O", kwlist, &directed_o, &scale_o, &weights_o, - &igraphmodule_ARPACKOptionsType, + igraphmodule_ARPACKOptionsType, &arpack_options, &return_eigenvalue)) return NULL; @@ -5154,7 +5154,7 @@ PyObject *igraphmodule_Graph_hub_score( igraph_vector_t res, *weights = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO!O", kwlist, &weights_o, - &scale_o, &igraphmodule_ARPACKOptionsType, + &scale_o, igraphmodule_ARPACKOptionsType, &arpack_options, &return_eigenvalue)) return NULL; @@ -5349,8 +5349,8 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!Olf", kwlist, &vobj, &directed, &damping, &robj, - &rvsobj, &wobj, - &igraphmodule_ARPACKOptionsType, + &rvsobj, &wobj, + igraphmodule_ARPACKOptionsType, &arpack_options_o, &algo_o, &niter, &eps)) @@ -7339,7 +7339,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, * compatibility */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OlO!", kwlist, &dist_o, - &dim, &igraphmodule_ARPACKOptionsType, + &dim, igraphmodule_ARPACKOptionsType, &arpack_options_o)) return NULL; @@ -11428,7 +11428,7 @@ PyObject *igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObj PyObject *arpack_options_o = igraphmodule_arpack_options_default; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|lOO!", kwlist, &n, &weights_obj, - &igraphmodule_ARPACKOptionsType, &arpack_options_o)) { + igraphmodule_ARPACKOptionsType, &arpack_options_o)) { return NULL; } diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 8ee6e4fab..949b990bb 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -23,7 +23,8 @@ #ifndef PYTHON_GRAPHOBJECT_H #define PYTHON_GRAPHOBJECT_H -#include +#include "preamble.h" + #include #include "structmember.h" #include "common.h" diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index ea3661c3f..f35a102bd 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -20,8 +20,8 @@ */ -#include -#include +#include "preamble.h" + #include #include "arpackobject.h" #include "attributes.h" @@ -822,14 +822,14 @@ PyObject* PyInit__igraph(void) INITERROR; /* Initialize Graph, BFSIter, ARPACKOptions etc */ + if (igraphmodule_ARPACKOptions_register_type()) + INITERROR; if (PyType_Ready(&igraphmodule_GraphType) < 0) INITERROR; if (PyType_Ready(&igraphmodule_BFSIterType) < 0) INITERROR; if (PyType_Ready(&igraphmodule_DFSIterType) < 0) INITERROR; - if (PyType_Ready(&igraphmodule_ARPACKOptionsType) < 0) - INITERROR; /* Initialize the core module */ m = PyModule_Create(&moduledef); @@ -843,7 +843,7 @@ PyObject* PyInit__igraph(void) PyModule_AddObject(m, "GraphBase", (PyObject*)&igraphmodule_GraphType); PyModule_AddObject(m, "BFSIter", (PyObject*)&igraphmodule_BFSIterType); PyModule_AddObject(m, "DFSIter", (PyObject*)&igraphmodule_DFSIterType); - PyModule_AddObject(m, "ARPACKOptions", (PyObject*)&igraphmodule_ARPACKOptionsType); + PyModule_AddObject(m, "ARPACKOptions", (PyObject*)igraphmodule_ARPACKOptionsType); PyModule_AddObject(m, "Edge", (PyObject*)&igraphmodule_EdgeType); PyModule_AddObject(m, "EdgeSeq", (PyObject*)&igraphmodule_EdgeSeqType); PyModule_AddObject(m, "Vertex", (PyObject*)&igraphmodule_VertexType); diff --git a/src/_igraph/indexing.h b/src/_igraph/indexing.h index 105a64f00..6b34ff09c 100644 --- a/src/_igraph/indexing.h +++ b/src/_igraph/indexing.h @@ -24,7 +24,8 @@ #ifndef PYTHON_INDEXING_H #define PYTHON_INDEXING_H -#include +#include "preamble.h" + #include PyObject* igraphmodule_Graph_adjmatrix_get_index(igraph_t* graph, diff --git a/src/_igraph/operators.h b/src/_igraph/operators.h index 3823a55ae..e90dd88e1 100644 --- a/src/_igraph/operators.h +++ b/src/_igraph/operators.h @@ -23,7 +23,7 @@ #ifndef PYTHON_OPERATORS_H #define PYTHON_OPERATORS_H -#include +#include "preamble.h" PyObject* igraphmodule__disjoint_union(PyObject* self, PyObject* args, PyObject* kwds); PyObject* igraphmodule__union(PyObject* self, PyObject* args, PyObject* kwds); diff --git a/src/_igraph/preamble.h b/src/_igraph/preamble.h new file mode 100644 index 000000000..218b304ca --- /dev/null +++ b/src/_igraph/preamble.h @@ -0,0 +1,29 @@ +/* -*- mode: C -*- */ +/* + IGraph library. + Copyright (C) 2006-2021 The igraph development team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#ifndef PYTHON_IGRAPH_PREAMBLE_H +#define PYTHON_IGRAPH_PREAMBLE_H + +#define PY_SSIZE_T_CLEAN +#include + +#endif /* PYTHON_IGRAPH_PREAMBLE_H */ diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 00bff1d86..9c1f2d876 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -24,7 +24,7 @@ #ifndef PYTHON_HELPERS_H #define PYTHON_HELPERS_H -#include +#include "preamble.h" int igraphmodule_PyFile_Close(PyObject* fileObj); PyObject* igraphmodule_PyFile_FromObject(PyObject* filename, const char* mode); diff --git a/src/_igraph/random.h b/src/_igraph/random.h index 5fca144e9..4902e8697 100644 --- a/src/_igraph/random.h +++ b/src/_igraph/random.h @@ -23,7 +23,7 @@ #ifndef PYTHON_RANDOM_H #define PYTHON_RANDOM_H -#include +#include "preamble.h" void igraphmodule_init_rng(PyObject*); PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object); diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index f33d640eb..abc2d88b6 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -23,7 +23,8 @@ #ifndef PYTHON_VERTEXOBJECT_H #define PYTHON_VERTEXOBJECT_H -#include +#include "preamble.h" + #include "graphobject.h" /** diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 17c157945..32709b64d 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -22,7 +22,6 @@ */ -#include #include "attributes.h" #include "common.h" #include "convert.h" diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index 987f1f768..38739ff2c 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -23,7 +23,8 @@ #ifndef PYTHON_VERTEXSEQOBJECT_H #define PYTHON_VERTEXSEQOBJECT_H -#include +#include "preamble.h" + #include "graphobject.h" /** From 50d419b36d9e40ccb6d95296683972a77919c622 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 14:22:54 +0200 Subject: [PATCH 0607/1892] refactor: attributes.c now uses the limited Python API only --- src/_igraph/attributes.c | 219 ++++++++++++++++++++++++++++++++------- 1 file changed, 182 insertions(+), 37 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 95375559a..371162cfb 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -20,6 +20,8 @@ */ +#define Py_LIMITED_API 0x03060000 + #include "attributes.h" #include "common.h" #include "convert.h" @@ -73,10 +75,15 @@ int igraphmodule_i_attribute_struct_index_vertex_names( n = PyList_Size(name_list) - 1; while (n >= 0) { - key = PyList_GET_ITEM(name_list, n); /* we don't own a reference to key */ + key = PyList_GetItem(name_list, n); /* we don't own a reference to key */ + if (key == 0) { + return 1; + } + value = PyLong_FromLong(n); /* we do own a reference to value */ - if (value == 0) + if (value == 0) { return 1; + } if (PyDict_SetItem(attrs->vertex_name_index, key, value)) { /* probably unhashable vertex name. If the error is a TypeError, convert @@ -227,7 +234,11 @@ PyObject* igraphmodule_create_edge_attribute(const igraph_t* graph, for (i = 0; i < n; i++) { Py_INCREF(Py_None); - PyList_SET_ITEM(values, i, Py_None); /* reference stolen */ + if (PyList_SetItem(values, i, Py_None)) { /* reference stolen */ + Py_DECREF(values); + Py_DECREF(Py_None); + return 0; + } } if (PyDict_SetItemString(dict, name, values)) { @@ -393,8 +404,8 @@ static int igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t *from, while (PyDict_Next(fromattrs->attrs[i], &pos, &key, &value)) { /* value is only borrowed, so copy it */ if (i>0) { - newval=PyList_New(PyList_GET_SIZE(value)); - for (j=0; jname, value); @@ -789,11 +809,18 @@ static int igraphmodule_i_attribute_permute_edges(const igraph_t *graph, for (i=0; i 0 ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[0]) : Py_None; + item = n > 0 ? PyList_GetItem(values, (Py_ssize_t)VECTOR(*v)[0]) : Py_None; + if (item == 0) { + Py_DECREF(res); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(res, i, item); /* reference to item stolen */ + if (PyList_SetItem(res, i, item)) { /* reference to item stolen */ + Py_DECREF(item); + Py_DECREF(res); + return 0; + } } return res; @@ -1001,14 +1071,26 @@ static PyObject* igraphmodule_i_ac_random(PyObject* values, Py_DECREF(res); return 0; } - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[(long int)(n*PyFloat_AsDouble(num))]); + + item = PyList_GetItem(values, (Py_ssize_t)VECTOR(*v)[(long int)(n*PyFloat_AsDouble(num))]); + if (item == 0) { + Py_DECREF(random_func); + Py_DECREF(res); + return 0; + } + Py_DECREF(num); } else { item = Py_None; } Py_INCREF(item); - PyList_SET_ITEM(res, i, item); /* reference to item stolen */ + if (PyList_SetItem(res, i, item)) { /* reference to item stolen */ + Py_DECREF(item); + Py_DECREF(random_func); + Py_DECREF(res); + return 0; + } } Py_DECREF(random_func); @@ -1032,9 +1114,19 @@ static PyObject* igraphmodule_i_ac_last(PyObject* values, igraph_vector_t *v = (igraph_vector_t*)VECTOR(*merges)[i]; long int n = igraph_vector_size(v); - item = (n > 0) ? PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[n-1]) : Py_None; + item = (n > 0) ? PyList_GetItem(values, (Py_ssize_t)VECTOR(*v)[n-1]) : Py_None; + if (item == 0) { + Py_DECREF(res); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(res, i, item); /* reference to item stolen */ + + if (PyList_SetItem(res, i, item)) { /* reference to item stolen */ + Py_DECREF(item); + Py_DECREF(res); + return 0; + } } return res; @@ -1058,7 +1150,12 @@ static PyObject* igraphmodule_i_ac_mean(PyObject* values, long int j, n = igraph_vector_size(v); for (j = 0; j < n; ) { - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); + item = PyList_GetItem(values, (Py_ssize_t)VECTOR(*v)[j]); + if (item == 0) { + Py_DECREF(res); + return 0; + } + if (igraphmodule_PyObject_to_real_t(item, &num)) { PyErr_SetString(PyExc_TypeError, "mean can only be invoked on numeric attributes"); Py_DECREF(res); @@ -1070,7 +1167,12 @@ static PyObject* igraphmodule_i_ac_mean(PyObject* values, } /* reference to new float stolen */ - PyList_SET_ITEM(res, i, PyFloat_FromDouble((double)mean)); + item = PyFloat_FromDouble((double)mean); + if (PyList_SetItem(res, i, item)) { /* reference to item stolen */ + Py_DECREF(item); + Py_DECREF(res); + return 0; + } } return res; @@ -1093,40 +1195,78 @@ static PyObject* igraphmodule_i_ac_median(PyObject* values, long int j, n = igraph_vector_size(v); list = PyList_New(n); for (j = 0; j < n; j++) { - item = PyList_GET_ITEM(values, (Py_ssize_t)VECTOR(*v)[j]); + item = PyList_GetItem(values, (Py_ssize_t)VECTOR(*v)[j]); + if (item == 0) { + Py_DECREF(res); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(list, j, item); /* reference to item stolen */ + if (PyList_SetItem(list, j, item)) { /* reference to item stolen */ + Py_DECREF(item); + Py_DECREF(list); + Py_DECREF(res); + return 0; + } } + /* sort the list */ if (PyList_Sort(list)) { Py_DECREF(list); Py_DECREF(res); return 0; } + if (n == 0) { item = Py_None; Py_INCREF(item); } else if (n % 2 == 1) { - item = PyList_GET_ITEM(list, n / 2); + item = PyList_GetItem(list, n / 2); + if (item == 0) { + Py_DECREF(list); + Py_DECREF(res); + return 0; + } + Py_INCREF(item); } else { igraph_real_t num1, num2; - item = PyList_GET_ITEM(list, n / 2 - 1); + item = PyList_GetItem(list, n / 2 - 1); + if (item == 0) { + Py_DECREF(list); + Py_DECREF(res); + return 0; + } + if (igraphmodule_PyObject_to_real_t(item, &num1)) { Py_DECREF(list); Py_DECREF(res); return 0; } - item = PyList_GET_ITEM(list, n / 2); + + item = PyList_GetItem(list, n / 2); + if (item == 0) { + Py_DECREF(list); + Py_DECREF(res); + return 0; + } + if (igraphmodule_PyObject_to_real_t(item, &num2)) { Py_DECREF(list); Py_DECREF(res); return 0; } + item = PyFloat_FromDouble((num1 + num2) / 2); } + /* reference to item stolen */ - PyList_SET_ITEM(res, i, item); + if (PyList_SetItem(res, i, item)) { + Py_DECREF(item); + Py_DECREF(list); + Py_DECREF(res); + return 0; + } } return res; @@ -1443,16 +1583,16 @@ int igraphmodule_i_attribute_get_type(const igraph_t *graph, if (attrnum>0) { for (i=0; i Date: Fri, 10 Sep 2021 14:23:56 +0200 Subject: [PATCH 0608/1892] feat: test.sh now allows cleaning the compiled igraph C core --- test.sh | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/test.sh b/test.sh index 007cc8cef..d5c4193cb 100755 --- a/test.sh +++ b/test.sh @@ -7,14 +7,31 @@ PYTHON=python3 set -e +CLEAN=0 + +while getopts ":c" OPTION; do + case $OPTION in + c) + CLEAN=1 + ;; + \?) + echo "Usage: $0 [-c]" + ;; + esac +done +shift $((OPTIND -1)) + if [ ! -d $VENV_DIR ]; then - $PYTHON -m venv $VENV_DIR + $PYTHON -m venv $VENV_DIR $VENV_DIR/bin/pip install -U pip wheel fi rm -rf build/ +if [ x$CLEAN = x1 ]; then + rm -rf vendor/build vendor/install +fi + $VENV_DIR/bin/python setup.py build $VENV_DIR/bin/pip install --use-feature=in-tree-build .[plotting,test] $VENV_DIR/bin/pytest tests - From 3d903100d4d01fc817c3d9ee441d3bb95a84c5f8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 15:10:25 +0200 Subject: [PATCH 0609/1892] refactor: BFSIter and DFSIter now use ony the Python limited API --- src/_igraph/arpackobject.c | 41 ++++++------- src/_igraph/arpackobject.h | 2 +- src/_igraph/bfsiter.c | 118 ++++++++++++++----------------------- src/_igraph/bfsiter.h | 16 ++--- src/_igraph/dfsiter.c | 103 +++++++++++--------------------- src/_igraph/dfsiter.h | 16 ++--- src/_igraph/graphobject.c | 14 +---- src/_igraph/igraphmodule.c | 15 ++--- 8 files changed, 128 insertions(+), 197 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 3e160e9f8..c4e020450 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -208,28 +208,25 @@ PyDoc_STRVAR( " - C{numreo}: total number of steps of re-orthogonalization\n\n" ); -PyType_Slot igraphmodule_ARPACKOptions_slots[] = { - { Py_tp_new, igraphmodule_ARPACKOptions_new }, - { Py_tp_dealloc, igraphmodule_ARPACKOptions_dealloc }, - { Py_tp_getattr, igraphmodule_ARPACKOptions_getattr }, - { Py_tp_setattr, igraphmodule_ARPACKOptions_setattr }, - { Py_tp_str, igraphmodule_ARPACKOptions_str }, - { Py_tp_doc, (void*) igraphmodule_ARPACKOptions_doc }, - { 0 } -}; - -/** \ingroup python_interface_arpack - * Python type specification for \c igraph.ARPACKOptions - */ -PyType_Spec igraphmodule_ARPACKOptions_spec = { - "igraph.ARPACKOptions", /* name */ - sizeof(igraphmodule_ARPACKOptionsObject), /* basicsize */ - 0, /* itemsize */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ - igraphmodule_ARPACKOptions_slots, /* slots */ -}; - int igraphmodule_ARPACKOptions_register_type() { - igraphmodule_ARPACKOptionsType = (PyTypeObject*) PyType_FromSpec(&igraphmodule_ARPACKOptions_spec); + PyType_Slot slots[] = { + { Py_tp_new, igraphmodule_ARPACKOptions_new }, + { Py_tp_dealloc, igraphmodule_ARPACKOptions_dealloc }, + { Py_tp_getattr, igraphmodule_ARPACKOptions_getattr }, + { Py_tp_setattr, igraphmodule_ARPACKOptions_setattr }, + { Py_tp_str, igraphmodule_ARPACKOptions_str }, + { Py_tp_doc, (void*) igraphmodule_ARPACKOptions_doc }, + { 0 } + }; + + PyType_Spec spec = { + "igraph.ARPACKOptions", /* name */ + sizeof(igraphmodule_ARPACKOptionsObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + slots, /* slots */ + }; + + igraphmodule_ARPACKOptionsType = (PyTypeObject*) PyType_FromSpec(&spec); return igraphmodule_ARPACKOptionsType == 0; } diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index 5d5fd31d0..ea482444b 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -47,7 +47,7 @@ typedef struct { extern PyTypeObject* igraphmodule_ARPACKOptionsType; extern PyObject* igraphmodule_arpack_options_default; -int igraphmodule_ARPACKOptions_register_type(); +int igraphmodule_ARPACKOptions_register_type(void); PyObject* igraphmodule_ARPACKOptions_new(void); igraph_arpack_options_t *igraphmodule_ARPACKOptions_get(igraphmodule_ARPACKOptionsObject *self); diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 03615ceb9..eafaa3c06 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -20,6 +20,8 @@ */ +#define Py_LIMITED_API 0x03060000 + #include "bfsiter.h" #include "common.h" #include "convert.h" @@ -31,7 +33,7 @@ * \defgroup python_interface_bfsiter BFS iterator object */ -PyTypeObject igraphmodule_BFSIterType; +PyTypeObject* igraphmodule_BFSIterType; /** * \ingroup python_interface_bfsiter @@ -45,10 +47,10 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraphmodule_BFSIterObject* o; igraph_integer_t no_of_nodes, r; - o = PyObject_GC_New(igraphmodule_BFSIterObject, &igraphmodule_BFSIterType); + o = PyObject_GC_New(igraphmodule_BFSIterObject, igraphmodule_BFSIterType); Py_INCREF(g); - o->gref=g; - o->graph=&g->g; + o->gref = g; + o->graph = &g->g; if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); @@ -56,7 +58,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, } no_of_nodes = igraph_vcount(&g->g); - o->visited=(char*)calloc(no_of_nodes, sizeof(char)); + o->visited = (char*)calloc(no_of_nodes, sizeof(char)); if (o->visited == 0) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; @@ -91,14 +93,14 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - o->visited[r]=1; + o->visited[r] = 1; if (!igraph_is_directed(&g->g)) { mode=IGRAPH_ALL; } - o->mode=mode; - o->advanced=advanced; + o->mode = mode; + o->advanced = advanced; PyObject_GC_Track(o); @@ -116,15 +118,9 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, */ int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, visitproc visit, void *arg) { - int vret; - RC_TRAVERSE("BFSIter", self); - - if (self->gref) { - vret=visit((PyObject*)self->gref, arg); - if (vret != 0) return vret; - } - + Py_VISIT(self->gref); + Py_VISIT(Py_TYPE(self)); /* needed because heap-allocated types are refcounted */ return 0; } @@ -137,12 +133,13 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { PyObject_GC_UnTrack(self); - tmp=(PyObject*)self->gref; - self->gref=NULL; + tmp = (PyObject*)self->gref; + self->gref = NULL; Py_XDECREF(tmp); igraph_dqueue_int_destroy(&self->queue); igraph_vector_int_destroy(&self->neis); + free(self->visited); self->visited=0; @@ -154,11 +151,14 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { * \brief Deallocates a Python representation of a given BFS iterator object */ void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { + PyTypeObject *tp = Py_TYPE(self); + igraphmodule_BFSIter_clear(self); RC_DEALLOC("BFSIter", self); PyObject_GC_Del(self); + Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { @@ -214,58 +214,30 @@ PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { } } -/** - * \ingroup python_interface_bfsiter - * Method table for the \c igraph.BFSIter object - */ -PyMethodDef igraphmodule_BFSIter_methods[] = { - {NULL} -}; - -/** \ingroup python_interface_bfsiter - * Python type object referencing the methods Python calls when it performs various operations on - * a BFS iterator of a graph - */ -PyTypeObject igraphmodule_BFSIterType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph.BFSIter", // tp_name - sizeof(igraphmodule_BFSIterObject), // tp_basicsize - 0, // tp_itemsize - (destructor)igraphmodule_BFSIter_dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, // tp_flags - "igraph BFS iterator object", // tp_doc - (traverseproc) igraphmodule_BFSIter_traverse, /* tp_traverse */ - (inquiry) igraphmodule_BFSIter_clear, /* tp_clear */ - 0, // tp_richcompare - 0, // tp_weaklistoffset - (getiterfunc)igraphmodule_BFSIter_iter, /* tp_iter */ - (iternextfunc)igraphmodule_BFSIter_iternext, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ -}; - +PyDoc_STRVAR( + igraphmodule_BFSIter_doc, + "igraph BFS iterator object" +); + +int igraphmodule_BFSIter_register_type() { + PyType_Slot slots[] = { + { Py_tp_dealloc, igraphmodule_BFSIter_dealloc }, + { Py_tp_traverse, igraphmodule_BFSIter_traverse }, + { Py_tp_clear, igraphmodule_BFSIter_clear }, + { Py_tp_iter, igraphmodule_BFSIter_iter }, + { Py_tp_iternext, igraphmodule_BFSIter_iternext }, + { Py_tp_doc, (void*) igraphmodule_BFSIter_doc }, + { 0 } + }; + + PyType_Spec spec = { + "igraph.BFSIter", /* name */ + sizeof(igraphmodule_BFSIterObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* flags */ + slots, /* slots */ + }; + + igraphmodule_BFSIterType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_BFSIterType == 0; +} diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index 2295963a9..60469c011 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -31,8 +31,7 @@ * \ingroup python_interface_bfsiter * \brief A structure representing a BFS iterator of a graph */ -typedef struct -{ +typedef struct { PyObject_HEAD igraphmodule_GraphObject* gref; igraph_dqueue_int_t queue; @@ -43,12 +42,13 @@ typedef struct igraph_bool_t advanced; } igraphmodule_BFSIterObject; -PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *o, igraph_neimode_t mode, igraph_bool_t advanced); -int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, - visitproc visit, void *arg); -int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self); -void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self); +extern PyTypeObject* igraphmodule_BFSIterType; -extern PyTypeObject igraphmodule_BFSIterType; +int igraphmodule_BFSIter_register_type(void); + +PyObject* igraphmodule_BFSIter_new( + igraphmodule_GraphObject *g, PyObject *o, igraph_neimode_t mode, + igraph_bool_t advanced +); #endif diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index dbbf1c546..3f4ca8f06 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -20,6 +20,8 @@ */ +#define Py_LIMITED_API 0x03060000 + #include "convert.h" #include "dfsiter.h" #include "common.h" @@ -31,7 +33,7 @@ * \defgroup python_interface_dfsiter DFS iterator object */ -PyTypeObject igraphmodule_DFSIterType; +PyTypeObject* igraphmodule_DFSIterType; /** * \ingroup python_interface_dfsiter @@ -45,10 +47,10 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraphmodule_DFSIterObject* o; igraph_integer_t no_of_nodes, r; - o=PyObject_GC_New(igraphmodule_DFSIterObject, &igraphmodule_DFSIterType); + o = PyObject_GC_New(igraphmodule_DFSIterObject, igraphmodule_DFSIterType); Py_INCREF(g); - o->gref=g; - o->graph=&g->g; + o->gref = g; + o->graph = &g->g; if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); @@ -117,17 +119,9 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, */ int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, visitproc visit, void *arg) { - int vret; - RC_TRAVERSE("DFSIter", self); - - if (self->gref) { - vret = visit((PyObject*)self->gref, arg); - if (vret != 0) { - return vret; - } - } - + Py_VISIT(self->gref); + Py_VISIT(Py_TYPE(self)); /* needed because heap-allocated types are refcounted */ return 0; } @@ -157,11 +151,14 @@ int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { * \brief Deallocates a Python representation of a given DFS iterator object */ void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { + PyTypeObject *tp = Py_TYPE(self); + igraphmodule_DFSIter_clear(self); RC_DEALLOC("DFSIter", self); PyObject_GC_Del(self); + Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { @@ -252,58 +249,30 @@ PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { } } -/** - * \ingroup python_interface_dfsiter - * Method table for the \c igraph.DFSIter object - */ -PyMethodDef igraphmodule_DFSIter_methods[] = { - {NULL} -}; +PyDoc_STRVAR( + igraphmodule_DFSIter_doc, + "igraph DFS iterator object" +); -/** \ingroup python_interface_dfsiter - * Python type object referencing the methods Python calls when it performs various operations on - * a DFS iterator of a graph - */ -PyTypeObject igraphmodule_DFSIterType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph.DFSIter", // tp_name - sizeof(igraphmodule_DFSIterObject), // tp_basicsize - 0, // tp_itemsize - (destructor)igraphmodule_DFSIter_dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, // tp_flags - "igraph DFS iterator object", // tp_doc - (traverseproc) igraphmodule_DFSIter_traverse, /* tp_traverse */ - (inquiry) igraphmodule_DFSIter_clear, /* tp_clear */ - 0, // tp_richcompare - 0, // tp_weaklistoffset - (getiterfunc)igraphmodule_DFSIter_iter, /* tp_iter */ - (iternextfunc)igraphmodule_DFSIter_iternext, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ -}; +int igraphmodule_DFSIter_register_type() { + PyType_Slot slots[] = { + { Py_tp_dealloc, igraphmodule_DFSIter_dealloc }, + { Py_tp_traverse, igraphmodule_DFSIter_traverse }, + { Py_tp_clear, igraphmodule_DFSIter_clear }, + { Py_tp_iter, igraphmodule_DFSIter_iter }, + { Py_tp_iternext, igraphmodule_DFSIter_iternext }, + { Py_tp_doc, (void*) igraphmodule_DFSIter_doc }, + { 0 } + }; + + PyType_Spec spec = { + "igraph.DFSIter", /* name */ + sizeof(igraphmodule_DFSIterObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* flags */ + slots, /* slots */ + }; + igraphmodule_DFSIterType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_DFSIterType == 0; +} diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h index 5e8c74f63..1b21c7139 100644 --- a/src/_igraph/dfsiter.h +++ b/src/_igraph/dfsiter.h @@ -31,8 +31,7 @@ * \ingroup python_interface_dfsiter * \brief A structure representing a DFS iterator of a graph */ -typedef struct -{ +typedef struct { PyObject_HEAD igraphmodule_GraphObject* gref; igraph_stack_int_t stack; @@ -43,12 +42,13 @@ typedef struct igraph_bool_t advanced; } igraphmodule_DFSIterObject; -PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *o, igraph_neimode_t mode, igraph_bool_t advanced); -int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, - visitproc visit, void *arg); -int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self); -void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self); +extern PyTypeObject* igraphmodule_DFSIterType; -extern PyTypeObject igraphmodule_DFSIterType; +int igraphmodule_DFSIter_register_type(void); + +PyObject* igraphmodule_DFSIter_new( + igraphmodule_GraphObject *g, PyObject *o, igraph_neimode_t mode, + igraph_bool_t advanced +); #endif diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d58d327cb..1989fabea 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -133,21 +133,13 @@ int igraphmodule_Graph_clear(igraphmodule_GraphObject * self) int igraphmodule_Graph_traverse(igraphmodule_GraphObject * self, visitproc visit, void *arg) { - int vret, i; - RC_TRAVERSE("Graph", self); - if (self->destructor) { - vret = visit(self->destructor, arg); - if (vret != 0) - return vret; - } + Py_VISIT(self->destructor); if (self->g.attr) { - for (i = 0; i < 3; i++) { - vret = visit(((PyObject **) (self->g.attr))[i], arg); - if (vret != 0) - return vret; + for (int i = 0; i < 3; i++) { + Py_VISIT(((PyObject**)self->g.attr)[i]); } } diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 374e1bd62..728601a1c 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -852,14 +852,15 @@ PyObject* PyInit__igraph(void) INITERROR; /* Initialize Graph, BFSIter, ARPACKOptions etc */ - if (igraphmodule_ARPACKOptions_register_type()) + if ( + igraphmodule_ARPACKOptions_register_type() || + igraphmodule_BFSIter_register_type() || + igraphmodule_DFSIter_register_type() + ) { INITERROR; + } if (PyType_Ready(&igraphmodule_GraphType) < 0) INITERROR; - if (PyType_Ready(&igraphmodule_BFSIterType) < 0) - INITERROR; - if (PyType_Ready(&igraphmodule_DFSIterType) < 0) - INITERROR; /* Initialize the core module */ m = PyModule_Create(&moduledef); @@ -871,8 +872,8 @@ PyObject* PyInit__igraph(void) /* Add the types to the core module */ PyModule_AddObject(m, "GraphBase", (PyObject*)&igraphmodule_GraphType); - PyModule_AddObject(m, "BFSIter", (PyObject*)&igraphmodule_BFSIterType); - PyModule_AddObject(m, "DFSIter", (PyObject*)&igraphmodule_DFSIterType); + PyModule_AddObject(m, "BFSIter", (PyObject*)igraphmodule_BFSIterType); + PyModule_AddObject(m, "DFSIter", (PyObject*)igraphmodule_DFSIterType); PyModule_AddObject(m, "ARPACKOptions", (PyObject*)igraphmodule_ARPACKOptionsType); PyModule_AddObject(m, "Edge", (PyObject*)&igraphmodule_EdgeType); PyModule_AddObject(m, "EdgeSeq", (PyObject*)&igraphmodule_EdgeSeqType); From 085bf11f1ee580e96c6fca74a7f06a181f8394a9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 15:54:37 +0200 Subject: [PATCH 0610/1892] refactor: Edge and Vertex now use the limited Python API only --- src/_igraph/bfsiter.c | 10 +- src/_igraph/convert.c | 4 +- src/_igraph/dfsiter.c | 12 +-- src/_igraph/edgeobject.c | 149 +++++++++++++++--------------- src/_igraph/edgeobject.h | 14 +-- src/_igraph/igraphmodule.c | 19 ++-- src/_igraph/vertexobject.c | 182 +++++++++++++++++++++---------------- src/_igraph/vertexobject.h | 15 +-- 8 files changed, 203 insertions(+), 202 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index eafaa3c06..0f8dffd40 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -52,7 +52,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, o->gref = g; o->graph = &g->g; - if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { + if (!PyLong_Check(root) && !igraphmodule_Vertex_Check(root)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); return NULL; } @@ -116,7 +116,7 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, * This is necessary because the \c igraph.BFSIter object contains several * other \c PyObject pointers and they might point back to itself. */ -int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, +static int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, visitproc visit, void *arg) { RC_TRAVERSE("BFSIter", self); Py_VISIT(self->gref); @@ -150,7 +150,7 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { * \ingroup python_interface_bfsiter * \brief Deallocates a Python representation of a given BFS iterator object */ -void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { +static void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { PyTypeObject *tp = Py_TYPE(self); igraphmodule_BFSIter_clear(self); @@ -161,12 +161,12 @@ void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } -PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { +static PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { Py_INCREF(self); return (PyObject*)self; } -PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { +static PyObject* igraphmodule_BFSIter_iternext(igraphmodule_BFSIterObject* self) { if (!igraph_dqueue_int_empty(&self->queue)) { igraph_integer_t vid = igraph_dqueue_int_pop(&self->queue); igraph_integer_t dist = igraph_dqueue_int_pop(&self->queue); diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index aa40b9115..2d9234328 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2760,7 +2760,7 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g if (igraphmodule_get_vertex_id_by_name(graph, o, vid)) { return 1; } - } else if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_VertexType)) { + } else if (igraphmodule_Vertex_Check(o)) { /* Single vertex ID from Vertex object */ igraphmodule_VertexObject *vo = (igraphmodule_VertexObject*)o; *vid = igraphmodule_Vertex_get_index_igraph_integer(vo); @@ -2971,7 +2971,7 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g /* Single edge ID */ if (igraphmodule_PyObject_to_integer_t(o, eid)) return 1; - } else if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_EdgeType)) { + } else if (igraphmodule_Edge_Check(o)) { /* Single edge ID from Edge object */ igraphmodule_EdgeObject *eo = (igraphmodule_EdgeObject*)o; *eid = igraphmodule_Edge_get_index_as_igraph_integer(eo); diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 3f4ca8f06..d1e419d7c 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -52,7 +52,7 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, o->gref = g; o->graph = &g->g; - if (!PyLong_Check(root) && !PyObject_IsInstance(root, (PyObject*)&igraphmodule_VertexType)) { + if (!PyLong_Check(root) && !igraphmodule_Vertex_Check(root)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); return NULL; } @@ -117,7 +117,7 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, * This is necessary because the \c igraph.DFSIter object contains several * other \c PyObject pointers and they might point back to itself. */ -int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, +static int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, visitproc visit, void *arg) { RC_TRAVERSE("DFSIter", self); Py_VISIT(self->gref); @@ -129,7 +129,7 @@ int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, * \ingroup python_interface_dfsiter * \brief Clears the iterator's subobject (before deallocation) */ -int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { +static int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { PyObject *tmp; PyObject_GC_UnTrack(self); @@ -150,7 +150,7 @@ int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { * \ingroup python_interface_dfsiter * \brief Deallocates a Python representation of a given DFS iterator object */ -void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { +static void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { PyTypeObject *tp = Py_TYPE(self); igraphmodule_DFSIter_clear(self); @@ -161,12 +161,12 @@ void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } -PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { +static PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { Py_INCREF(self); return (PyObject*)self; } -PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { +static PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) { /* the design is to return the top of the stack and then proceed until * we have found an unvisited neighbor and push that on top */ igraph_integer_t parent_out, dist_out, vid_out; diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 7410412a6..b0ef72d3b 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -22,6 +22,8 @@ */ +#define Py_LIMITED_API 0x03060000 + #include "attributes.h" #include "convert.h" #include "edgeobject.h" @@ -35,17 +37,16 @@ * \defgroup python_interface_edge Edge object */ -PyTypeObject igraphmodule_EdgeType; +PyTypeObject* igraphmodule_EdgeType; + +PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self); /** * \ingroup python_interface_edge * \brief Checks whether the given Python object is an edge */ int igraphmodule_Edge_Check(PyObject* obj) { - if (!obj) - return 0; - - return PyObject_IsInstance(obj, (PyObject*)(&igraphmodule_EdgeType)); + return obj ? PyObject_IsInstance(obj, (PyObject*)(igraphmodule_EdgeType)) : 0; } /** @@ -101,13 +102,13 @@ int igraphmodule_Edge_Validate(PyObject* obj) { */ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { igraphmodule_EdgeObject* self; - self=PyObject_New(igraphmodule_EdgeObject, &igraphmodule_EdgeType); + self = PyObject_New(igraphmodule_EdgeObject, igraphmodule_EdgeType); if (self) { RC_ALLOC("Edge", self); Py_INCREF(gref); - self->gref=gref; - self->idx=idx; - self->hash=-1; + self->gref = gref; + self->idx = idx; + self->hash = -1; } return (PyObject*)self; } @@ -130,12 +131,15 @@ int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { * \ingroup python_interface_edge * \brief Deallocates a Python representation of a given edge object */ -void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { +static void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { + PyTypeObject* tp = Py_TYPE(self); + igraphmodule_Edge_clear(self); RC_DEALLOC("Edge", self); PyObject_Del((PyObject*)self); + Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } /** \ingroup python_interface_edge @@ -143,7 +147,7 @@ void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { * * \return the formatted textual representation as a \c PyObject */ -PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { +static PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { PyObject *s; PyObject *attrs; @@ -161,7 +165,7 @@ PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { /** \ingroup python_interface_edge * \brief Returns the hash code of the edge */ -long igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { +static long igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { long hash_graph; long hash_index; long result; @@ -198,7 +202,7 @@ long igraphmodule_Edge_hash(igraphmodule_EdgeObject* self) { /** \ingroup python_interface_edge * \brief Rich comparison of an edge with another */ -PyObject* igraphmodule_Edge_richcompare(igraphmodule_EdgeObject *a, +static PyObject* igraphmodule_Edge_richcompare(igraphmodule_EdgeObject *a, PyObject *b, int op) { igraphmodule_EdgeObject* self = a; @@ -242,17 +246,18 @@ PyObject* igraphmodule_Edge_richcompare(igraphmodule_EdgeObject *a, Py_ssize_t igraphmodule_Edge_attribute_count(igraphmodule_EdgeObject* self) { igraphmodule_GraphObject *o = self->gref; - if (!o) return 0; - if (!((PyObject**)o->g.attr)[1]) return 0; - return PyDict_Size(((PyObject**)o->g.attr)[1]); + if (!o || !((PyObject**)o->g.attr)[1]) { + return 0; + } else { + return PyDict_Size(((PyObject**)o->g.attr)[1]); + } } /** \ingroup python_interface_edge * \brief Returns the list of attribute names */ PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self) { - if (!self->gref) return NULL; - return igraphmodule_Graph_edge_attributes(self->gref); + return self->gref ? igraphmodule_Graph_edge_attributes(self->gref) : 0; } /** \ingroup python_interface_edge @@ -290,7 +295,15 @@ PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self) { /* no need to Py_INCREF, PyDict_SetItem will do that */ PyDict_SetItem(dict, name, value); } + } else { + Py_DECREF(dict); + Py_DECREF(names); + return NULL; } + } else { + Py_DECREF(dict); + Py_DECREF(names); + return NULL; } } @@ -584,18 +597,25 @@ PyObject* igraphmodule_Edge_get_graph(igraphmodule_EdgeObject* self, void* closu #define GRAPH_PROXY_METHOD(FUNC, METHODNAME) \ PyObject* igraphmodule_Edge_##FUNC(igraphmodule_EdgeObject* self, PyObject* args, PyObject* kwds) { \ PyObject *new_args, *item, *result; \ - Py_ssize_t i, num_args = args ? PyTuple_Size(args)+1 : 1; \ + Py_ssize_t i, num_args = args ? PyTuple_Size(args) + 1 : 1; \ \ /* Prepend ourselves to args */ \ new_args = PyTuple_New(num_args); \ - Py_INCREF(self); PyTuple_SET_ITEM(new_args, 0, (PyObject*)self); \ + Py_INCREF(self); \ + PyTuple_SetItem(new_args, 0, (PyObject*)self); \ for (i = 1; i < num_args; i++) { \ - item = PyTuple_GET_ITEM(args, i-1); \ - Py_INCREF(item); PyTuple_SET_ITEM(new_args, i, item); \ + item = PyTuple_GetItem(args, i - 1); \ + Py_INCREF(item); \ + PyTuple_SetItem(new_args, i, item); \ } \ \ /* Get the method instance */ \ item = PyObject_GetAttrString((PyObject*)(self->gref), METHODNAME); \ + if (item == 0) { \ + Py_DECREF(new_args); \ + return 0; \ + } \ + \ result = PyObject_Call(item, new_args, kwds); \ Py_DECREF(item); \ Py_DECREF(new_args); \ @@ -691,46 +711,8 @@ PyGetSetDef igraphmodule_Edge_getseters[] = { {NULL} }; -/** \ingroup python_interface_edge - * This structure is the collection of functions necessary to implement - * the edge as a mapping (i.e. to allow the retrieval and setting of - * igraph attributes in Python as if it were of a Python mapping type) - */ -PyMappingMethods igraphmodule_Edge_as_mapping = { - // returns the number of edge attributes - (lenfunc)igraphmodule_Edge_attribute_count, - // returns an attribute by name - (binaryfunc)igraphmodule_Edge_get_attribute, - // sets an attribute by name - (objobjargproc)igraphmodule_Edge_set_attribute -}; - -/** \ingroup python_interface_edge - * Python type object referencing the methods Python calls when it performs various operations on - * an edge of a graph - */ -PyTypeObject igraphmodule_EdgeType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph.Edge", // tp_name - sizeof(igraphmodule_EdgeObject), // tp_basicsize - 0, // tp_itemsize - (destructor)igraphmodule_Edge_dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - (reprfunc)igraphmodule_Edge_repr, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - &igraphmodule_Edge_as_mapping, // tp_as_mapping - (hashfunc)igraphmodule_Edge_hash, /* tp_hash */ - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags +PyDoc_STRVAR( + igraphmodule_Edge_doc, "Class representing a single edge in a graph.\n\n" "The edge is referenced by its index, so if the underlying graph\n" "changes, the semantics of the edge object might change as well\n" @@ -739,15 +721,34 @@ PyTypeObject igraphmodule_EdgeType = "as a hash:\n\n" " >>> e[\"weight\"] = 2 #doctest: +SKIP\n" " >>> print(e[\"weight\"]) #doctest: +SKIP\n" - " 2\n", // tp_doc - 0, // tp_traverse - 0, // tp_clear - (richcmpfunc)igraphmodule_Edge_richcompare, /* tp_richcompare */ - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - igraphmodule_Edge_methods, // tp_methods - 0, // tp_members - igraphmodule_Edge_getseters, // tp_getset -}; - + " 2\n" +); + +int igraphmodule_Edge_register_type() { + PyType_Slot slots[] = { + { Py_tp_dealloc, igraphmodule_Edge_dealloc }, + { Py_tp_hash, igraphmodule_Edge_hash }, + { Py_tp_repr, igraphmodule_Edge_repr }, + { Py_tp_richcompare, igraphmodule_Edge_richcompare }, + { Py_tp_methods, igraphmodule_Edge_methods }, + { Py_tp_getset, igraphmodule_Edge_getseters }, + { Py_tp_doc, (void*) igraphmodule_Edge_doc }, + + { Py_mp_length, igraphmodule_Edge_attribute_count }, + { Py_mp_subscript, igraphmodule_Edge_get_attribute }, + { Py_mp_ass_subscript, igraphmodule_Edge_set_attribute }, + + { 0 } + }; + + PyType_Spec spec = { + "igraph.Edge", /* name */ + sizeof(igraphmodule_EdgeObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + slots, /* slots */ + }; + + igraphmodule_EdgeType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_EdgeType == 0; +} diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index b2192674b..7432d22a3 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -38,20 +38,12 @@ typedef struct { long hash; } igraphmodule_EdgeObject; -int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self); -void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self); +extern PyTypeObject* igraphmodule_EdgeType; -int igraphmodule_Edge_Check(PyObject *obj); -int igraphmodule_Edge_Validate(PyObject *obj); +int igraphmodule_Edge_register_type(void); +int igraphmodule_Edge_Check(PyObject* obj); PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx); -PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self); -PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self); -PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self); igraph_integer_t igraphmodule_Edge_get_index_as_igraph_integer(igraphmodule_EdgeObject* self); -PyObject* igraphmodule_Edge_update_attributes(PyObject* self, PyObject* args, - PyObject* kwds); - -extern PyTypeObject igraphmodule_EdgeType; #endif diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 728601a1c..0fad4c359 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -842,20 +842,13 @@ PyObject* PyInit__igraph(void) if (PyType_Ready(&igraphmodule_EdgeSeqType) < 0) INITERROR; - /* Initialize Vertex, Edge */ - igraphmodule_VertexType.tp_clear = (inquiry)igraphmodule_Vertex_clear; - if (PyType_Ready(&igraphmodule_VertexType) < 0) - INITERROR; - - igraphmodule_EdgeType.tp_clear = (inquiry)igraphmodule_Edge_clear; - if (PyType_Ready(&igraphmodule_EdgeType) < 0) - INITERROR; - - /* Initialize Graph, BFSIter, ARPACKOptions etc */ + /* Initialize types */ if ( igraphmodule_ARPACKOptions_register_type() || igraphmodule_BFSIter_register_type() || - igraphmodule_DFSIter_register_type() + igraphmodule_DFSIter_register_type() || + igraphmodule_Edge_register_type() || + igraphmodule_Vertex_register_type() ) { INITERROR; } @@ -875,9 +868,9 @@ PyObject* PyInit__igraph(void) PyModule_AddObject(m, "BFSIter", (PyObject*)igraphmodule_BFSIterType); PyModule_AddObject(m, "DFSIter", (PyObject*)igraphmodule_DFSIterType); PyModule_AddObject(m, "ARPACKOptions", (PyObject*)igraphmodule_ARPACKOptionsType); - PyModule_AddObject(m, "Edge", (PyObject*)&igraphmodule_EdgeType); + PyModule_AddObject(m, "Edge", (PyObject*)igraphmodule_EdgeType); PyModule_AddObject(m, "EdgeSeq", (PyObject*)&igraphmodule_EdgeSeqType); - PyModule_AddObject(m, "Vertex", (PyObject*)&igraphmodule_VertexType); + PyModule_AddObject(m, "Vertex", (PyObject*)igraphmodule_VertexType); PyModule_AddObject(m, "VertexSeq", (PyObject*)&igraphmodule_VertexSeqType); /* Internal error exception type */ diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 71dc24c9b..699634789 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -22,6 +22,8 @@ */ +#define Py_LIMITED_API 0x03060000 + #include "attributes.h" #include "convert.h" #include "edgeobject.h" @@ -35,7 +37,9 @@ * \defgroup python_interface_vertex Vertex object */ -PyTypeObject igraphmodule_VertexType; +PyTypeObject* igraphmodule_VertexType; + +PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self); /** * \ingroup python_interface_vertex @@ -45,7 +49,7 @@ int igraphmodule_Vertex_Check(PyObject* obj) { if (!obj) return 0; - return PyObject_IsInstance(obj, (PyObject*)(&igraphmodule_VertexType)); + return PyObject_IsInstance(obj, (PyObject*)igraphmodule_VertexType); } /** @@ -101,13 +105,13 @@ int igraphmodule_Vertex_Validate(PyObject* obj) { */ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { igraphmodule_VertexObject* self; - self=PyObject_New(igraphmodule_VertexObject, &igraphmodule_VertexType); + self = PyObject_New(igraphmodule_VertexObject, igraphmodule_VertexType); if (self) { RC_ALLOC("Vertex", self); Py_INCREF(gref); - self->gref=gref; - self->idx=idx; - self->hash=-1; + self->gref = gref; + self->idx = idx; + self->hash = -1; } return (PyObject*)self; } @@ -130,12 +134,15 @@ int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { * \ingroup python_interface_vertex * \brief Deallocates a Python representation of a given vertex object */ -void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { +static void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { + PyTypeObject* tp = Py_TYPE(self); + igraphmodule_Vertex_clear(self); RC_DEALLOC("Vertex", self); PyObject_Del((PyObject*)self); + Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ } /** \ingroup python_interface_vertex @@ -143,13 +150,14 @@ void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { * * \return the formatted textual representation as a \c PyObject */ -PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { +static PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { PyObject *s; PyObject *attrs; attrs = igraphmodule_Vertex_attributes(self); - if (attrs == 0) + if (attrs == 0) { return NULL; + } s = PyUnicode_FromFormat("igraph.Vertex(%R, %" IGRAPH_PRId ", %R)", (PyObject*)self->gref, self->idx, attrs); @@ -161,7 +169,7 @@ PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { /** \ingroup python_interface_vertex * \brief Returns the hash code of the vertex */ -long igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { +static long igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { long hash_graph; long hash_index; long result; @@ -198,7 +206,7 @@ long igraphmodule_Vertex_hash(igraphmodule_VertexObject* self) { /** \ingroup python_interface_vertex * \brief Rich comparison of a vertex with another */ -PyObject* igraphmodule_Vertex_richcompare(igraphmodule_VertexObject *a, +static PyObject* igraphmodule_Vertex_richcompare(igraphmodule_VertexObject *a, PyObject *b, int op) { igraphmodule_VertexObject* self = a; @@ -242,17 +250,18 @@ PyObject* igraphmodule_Vertex_richcompare(igraphmodule_VertexObject *a, Py_ssize_t igraphmodule_Vertex_attribute_count(igraphmodule_VertexObject* self) { igraphmodule_GraphObject *o = self->gref; - if (!o) return 0; - if (!((PyObject**)o->g.attr)[1]) return 0; - return PyDict_Size(((PyObject**)o->g.attr)[1]); + if (!o || !((PyObject**)o->g.attr)[1]) { + return 0; + } else { + return PyDict_Size(((PyObject**)o->g.attr)[1]); + } } /** \ingroup python_interface_vertex * \brief Returns the list of attribute names */ PyObject* igraphmodule_Vertex_attribute_names(igraphmodule_VertexObject* self) { - if (!self->gref) return NULL; - return igraphmodule_Graph_vertex_attributes(self->gref); + return self->gref ? igraphmodule_Graph_vertex_attributes(self->gref) : 0; } /** \ingroup python_interface_vertex @@ -263,8 +272,9 @@ PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self) { PyObject *names, *dict; Py_ssize_t i, n; - if (!igraphmodule_Vertex_Validate((PyObject*)self)) + if (!igraphmodule_Vertex_Validate((PyObject*)self)) { return 0; + } dict = PyDict_New(); if (!dict) { @@ -289,7 +299,15 @@ PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self) { /* No need to Py_INCREF, PyDict_SetItem will do that */ PyDict_SetItem(dict, name, value); } + } else { + Py_DECREF(dict); + Py_DECREF(names); + return NULL; } + } else { + Py_DECREF(dict); + Py_DECREF(names); + return NULL; } } @@ -601,10 +619,14 @@ static PyObject* _convert_to_edge_list(igraphmodule_VertexObject* vertex, PyObje n = PyList_Size(obj); for (i = 0; i < n; i++) { - PyObject* idx = PyList_GET_ITEM(obj, i); - PyObject* v; + PyObject* idx = PyList_GetItem(obj, i); + PyObject* edge; igraph_integer_t idx_int; + if (!idx) { + return NULL; + } + if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_edge_list expected list of integers"); return NULL; @@ -614,15 +636,19 @@ static PyObject* _convert_to_edge_list(igraphmodule_VertexObject* vertex, PyObje return NULL; } - v = igraphmodule_Edge_New(vertex->gref, idx_int); - if (!v) { + edge = igraphmodule_Edge_New(vertex->gref, idx_int); + if (!edge) { return NULL; } - PyList_SetItem(obj, i, v); /* reference to v stolen, reference to idx discarded */ + if (PyList_SetItem(obj, i, edge)) { /* reference to v stolen, reference to idx discarded */ + Py_DECREF(edge); + return NULL; + } } Py_INCREF(obj); + return obj; } @@ -638,10 +664,14 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb n = PyList_Size(obj); for (i = 0; i < n; i++) { - PyObject* idx = PyList_GET_ITEM(obj, i); + PyObject* idx = PyList_GetItem(obj, i); PyObject* v; igraph_integer_t idx_int; + if (!idx) { + return NULL; + } + if (!PyLong_Check(idx)) { PyErr_SetString(PyExc_TypeError, "_convert_to_vertex_list expected list of integers"); return NULL; @@ -656,7 +686,10 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb return NULL; } - PyList_SetItem(obj, i, v); /* reference to v stolen, reference to idx discarded */ + if (PyList_SetItem(obj, i, v)) { /* reference to v stolen, reference to idx discarded */ + Py_DECREF(v); + return NULL; + } } Py_INCREF(obj); @@ -666,18 +699,25 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb #define GRAPH_PROXY_METHOD_PP(FUNC, METHODNAME, POSTPROCESS) \ PyObject* igraphmodule_Vertex_##FUNC(igraphmodule_VertexObject* self, PyObject* args, PyObject* kwds) { \ PyObject *new_args, *item, *result; \ - Py_ssize_t i, num_args = args ? PyTuple_Size(args)+1 : 1; \ + Py_ssize_t i, num_args = args ? PyTuple_Size(args) + 1 : 1; \ \ /* Prepend ourselves to args */ \ new_args = PyTuple_New(num_args); \ - Py_INCREF(self); PyTuple_SET_ITEM(new_args, 0, (PyObject*)self); \ + Py_INCREF(self); \ + PyTuple_SetItem(new_args, 0, (PyObject*)self); \ for (i = 1; i < num_args; i++) { \ - item = PyTuple_GET_ITEM(args, i-1); \ - Py_INCREF(item); PyTuple_SET_ITEM(new_args, i, item); \ + item = PyTuple_GetItem(args, i - 1); \ + Py_INCREF(item); \ + PyTuple_SetItem(new_args, i, item); \ } \ \ /* Get the method instance */ \ item = PyObject_GetAttrString((PyObject*)(self->gref), METHODNAME); \ + if (item == 0) { \ + Py_DECREF(new_args); \ + return 0; \ + } \ + \ result = PyObject_Call(item, new_args, kwds); \ Py_DECREF(item); \ Py_DECREF(new_args); \ @@ -688,6 +728,7 @@ static PyObject* _convert_to_vertex_list(igraphmodule_VertexObject* vertex, PyOb Py_DECREF(result); \ return pp_result; \ } \ + \ return NULL; \ } @@ -799,20 +840,6 @@ PyMethodDef igraphmodule_Vertex_methods[] = { #undef GRAPH_PROXY_METHOD_SPEC #undef GRAPH_PROXY_METHOD_SPEC_2 -/** \ingroup python_interface_vertex - * This structure is the collection of functions necessary to implement - * the vertex as a mapping (i.e. to allow the retrieval and setting of - * igraph attributes in Python as if it were of a Python mapping type) - */ -PyMappingMethods igraphmodule_Vertex_as_mapping = { - // returns the number of vertex attributes - (lenfunc)igraphmodule_Vertex_attribute_count, - // returns an attribute by name - (binaryfunc)igraphmodule_Vertex_get_attribute, - // sets an attribute by name - (objobjargproc)igraphmodule_Vertex_set_attribute -}; - /** * \ingroup python_interface_vertex * Getter/setter table for the \c igraph.Vertex object @@ -827,32 +854,8 @@ PyGetSetDef igraphmodule_Vertex_getseters[] = { {NULL} }; -/** \ingroup python_interface_vertex - * Python type object referencing the methods Python calls when it performs various operations on - * a vertex of a graph - */ -PyTypeObject igraphmodule_VertexType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph.Vertex", /* tp_name */ - sizeof(igraphmodule_VertexObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)igraphmodule_Vertex_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - (reprfunc)igraphmodule_Vertex_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - &igraphmodule_Vertex_as_mapping, /* tp_as_mapping */ - (hashfunc)igraphmodule_Vertex_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ +PyDoc_STRVAR( + igraphmodule_Vertex_doc, "Class representing a single vertex in a graph.\n\n" "The vertex is referenced by its index, so if the underlying graph\n" "changes, the semantics of the vertex object might change as well\n" @@ -861,15 +864,34 @@ PyTypeObject igraphmodule_VertexType = "as a hash:\n\n" " >>> v[\"color\"] = \"red\" #doctest: +SKIP\n" " >>> print(v[\"color\"]) #doctest: +SKIP\n" - " red\n", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)igraphmodule_Vertex_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - igraphmodule_Vertex_methods, /* tp_methods */ - 0, /* tp_members */ - igraphmodule_Vertex_getseters, /* tp_getset */ -}; - + " red\n" +); + +int igraphmodule_Vertex_register_type() { + PyType_Slot slots[] = { + { Py_tp_dealloc, igraphmodule_Vertex_dealloc }, + { Py_tp_hash, igraphmodule_Vertex_hash }, + { Py_tp_repr, igraphmodule_Vertex_repr }, + { Py_tp_richcompare, igraphmodule_Vertex_richcompare }, + { Py_tp_methods, igraphmodule_Vertex_methods }, + { Py_tp_getset, igraphmodule_Vertex_getseters }, + { Py_tp_doc, (void*) igraphmodule_Vertex_doc }, + + { Py_mp_length, igraphmodule_Vertex_attribute_count }, + { Py_mp_subscript, igraphmodule_Vertex_get_attribute }, + { Py_mp_ass_subscript, igraphmodule_Vertex_set_attribute }, + + { 0 } + }; + + PyType_Spec spec = { + "igraph.Vertex", /* name */ + sizeof(igraphmodule_VertexObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + slots, /* slots */ + }; + + igraphmodule_VertexType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_VertexType == 0; +} diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index d1667e3b9..e16e8c37c 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -39,20 +39,13 @@ typedef struct long hash; } igraphmodule_VertexObject; -int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self); -void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self); +extern PyTypeObject* igraphmodule_VertexType; -int igraphmodule_Vertex_Check(PyObject *obj); -int igraphmodule_Vertex_Validate(PyObject *obj); +int igraphmodule_Vertex_register_type(void); +int igraphmodule_Vertex_Check(PyObject* obj); PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer_t idx); -PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self); -PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self); -PyObject* igraphmodule_Vertex_attribute_names(igraphmodule_VertexObject* self); igraph_integer_t igraphmodule_Vertex_get_index_igraph_integer(igraphmodule_VertexObject* self); -PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, - PyObject* kwds); - -extern PyTypeObject igraphmodule_VertexType; +PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, PyObject* kwds); #endif From c0165da6afacc484ae3b02994daf47c2e8aceae6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 16:21:03 +0200 Subject: [PATCH 0611/1892] fix: re-added missing tp_clear slots to Edge and Vertex --- src/_igraph/edgeobject.c | 3 ++- src/_igraph/vertexobject.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index b0ef72d3b..f0cbfb9d0 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -117,7 +117,7 @@ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t * \ingroup python_interface_edge * \brief Clears the edge's subobject (before deallocation) */ -int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { +static int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { PyObject *tmp; tmp=(PyObject*)self->gref; @@ -727,6 +727,7 @@ PyDoc_STRVAR( int igraphmodule_Edge_register_type() { PyType_Slot slots[] = { { Py_tp_dealloc, igraphmodule_Edge_dealloc }, + { Py_tp_clear, igraphmodule_Edge_clear }, { Py_tp_hash, igraphmodule_Edge_hash }, { Py_tp_repr, igraphmodule_Edge_repr }, { Py_tp_richcompare, igraphmodule_Edge_richcompare }, diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 699634789..0d146c39b 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -120,7 +120,7 @@ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer * \ingroup python_interface_vertex * \brief Clears the vertex's subobject (before deallocation) */ -int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { +static int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { PyObject *tmp; tmp=(PyObject*)self->gref; @@ -869,6 +869,7 @@ PyDoc_STRVAR( int igraphmodule_Vertex_register_type() { PyType_Slot slots[] = { + { Py_tp_clear, igraphmodule_Vertex_clear }, { Py_tp_dealloc, igraphmodule_Vertex_dealloc }, { Py_tp_hash, igraphmodule_Vertex_hash }, { Py_tp_repr, igraphmodule_Vertex_repr }, From 1f9b550481bfad559470ef4ae799c9d388018821 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 19:12:43 +0200 Subject: [PATCH 0612/1892] fix: fix a compiler warning about uninitialized variables --- src/_igraph/igraphmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 0fad4c359..947541c54 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -230,7 +230,7 @@ PyObject* igraphmodule_set_status_handler(PyObject* self, PyObject* o) { PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwds) { static char* kwlist[] = {"vs", "coords", NULL}; - PyObject *vs, *o, *o1, *o2, *o1_float, *o2_float, *coords = Py_False; + PyObject *vs, *o, *o1 = 0, *o2 = 0, *o1_float, *o2_float, *coords = Py_False; igraph_matrix_t mtrx; igraph_vector_int_t result; igraph_matrix_t resmat; From dbae48d6264a0321eded778327f70d151c31e2db Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 19:18:17 +0200 Subject: [PATCH 0613/1892] test: use pytest in all environments in CI --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e8c785feb..ed176ec2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -154,7 +154,7 @@ jobs: IGRAPH_STATIC_EXTENSION: True IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 - CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest -vvv" + CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" - uses: actions/upload-artifact@v2 with: @@ -196,8 +196,8 @@ jobs: - name: Test run: | - pip install numpy scipy pandas networkx - python -m unittest -vvv + pip install numpy scipy pandas networkx pytest + python -m pytest tests - uses: actions/upload-artifact@v2 with: From ea9c651edd2d9e63b79204bd6eeb0ece9db3958e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 19:20:37 +0200 Subject: [PATCH 0614/1892] test: try skipping Python 3.6 temporarily to see if the build fails with newer versions --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed176ec2b..62624ef20 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "cp27-* pp27-* cp35-*" + CIBW_SKIP: "cp27-* pp27-* cp35-* cp36-*" jobs: build_wheels: From 1b52627bd6a13deb8d77a59a6124d10de0f74438 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 20:21:22 +0200 Subject: [PATCH 0615/1892] test: temporarily exclude Python 3.7 as well --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 62624ef20..9d4d7874f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "cp27-* pp27-* cp35-* cp36-*" + CIBW_SKIP: "cp27-* pp27-* cp35-* cp36-* cp37-*" jobs: build_wheels: From 95077121135099bd73540dcb68f708f3864fc283 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 20:21:41 +0200 Subject: [PATCH 0616/1892] refactor: use Py_CLEAR macro --- src/_igraph/bfsiter.c | 6 ++---- src/_igraph/dfsiter.c | 9 +++------ src/_igraph/edgeobject.c | 7 +------ src/_igraph/vertexobject.c | 7 +------ 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 0f8dffd40..257cf5168 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -132,10 +132,8 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { PyObject *tmp; PyObject_GC_UnTrack(self); - - tmp = (PyObject*)self->gref; - self->gref = NULL; - Py_XDECREF(tmp); + + Py_CLEAR(self->gref); igraph_dqueue_int_destroy(&self->queue); igraph_vector_int_destroy(&self->neis); diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index d1e419d7c..9ff624cf7 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -130,16 +130,13 @@ static int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, * \brief Clears the iterator's subobject (before deallocation) */ static int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { - PyObject *tmp; - PyObject_GC_UnTrack(self); - - tmp = (PyObject*)self->gref; - self->gref = NULL; - Py_XDECREF(tmp); + + Py_CLEAR(self->gref); igraph_stack_int_destroy(&self->stack); igraph_vector_int_destroy(&self->neis); + free(self->visited); self->visited = 0; diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index f0cbfb9d0..1d09cda1d 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -118,12 +118,7 @@ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t * \brief Clears the edge's subobject (before deallocation) */ static int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { - PyObject *tmp; - - tmp=(PyObject*)self->gref; - self->gref=NULL; - Py_XDECREF(tmp); - + Py_CLEAR(self->gref); return 0; } diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 0d146c39b..bf6655f19 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -121,12 +121,7 @@ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer * \brief Clears the vertex's subobject (before deallocation) */ static int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { - PyObject *tmp; - - tmp=(PyObject*)self->gref; - self->gref=NULL; - Py_XDECREF(tmp); - + Py_CLEAR(self->gref); return 0; } From bc427c2ee4a2096b7f0260b5d99f7642d36fad77 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 21:24:39 +0200 Subject: [PATCH 0617/1892] test: re-add Python 3.6 and 3.7 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d4d7874f..ed176ec2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "cp27-* pp27-* cp35-* cp36-* cp37-*" + CIBW_SKIP: "cp27-* pp27-* cp35-*" jobs: build_wheels: From 05c9edc5096e2fd32ac9ab7b57e2c03c1db99b65 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Sep 2021 22:28:39 +0200 Subject: [PATCH 0618/1892] fix: fix reference counting errors with heap-allocated types --- .gitignore | 1 + src/_igraph/arpackobject.c | 1 + src/_igraph/bfsiter.c | 8 ++++++-- src/_igraph/dfsiter.c | 5 +++++ src/_igraph/edgeobject.c | 6 +++++- src/_igraph/vertexobject.c | 6 ++---- test.sh | 9 ++++++--- 7 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 323291f0c..2391ed900 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ src/igraph/*.so .eggs/ .tox .venv/ +.venv-*/ .vscode/ vendor/build/ vendor/install/ diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index c4e020450..f8523c289 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -36,6 +36,7 @@ PyObject* igraphmodule_ARPACKOptions_new() { igraphmodule_ARPACKOptionsObject* self; self = PyObject_New(igraphmodule_ARPACKOptionsObject, igraphmodule_ARPACKOptionsType); if (self) { + Py_INCREF(igraphmodule_ARPACKOptionsType); /* needed because heap-allocated types are refcounted */ igraph_arpack_options_init(&self->params); igraph_arpack_options_init(&self->params_out); } diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 257cf5168..3bab05eb1 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -48,6 +48,12 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_integer_t no_of_nodes, r; o = PyObject_GC_New(igraphmodule_BFSIterObject, igraphmodule_BFSIterType); + if (!o) { + return NULL; + } + + Py_INCREF(igraphmodule_BFSIterType); + Py_INCREF(g); o->gref = g; o->graph = &g->g; @@ -129,8 +135,6 @@ static int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, * \brief Clears the iterator's subobject (before deallocation) */ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { - PyObject *tmp; - PyObject_GC_UnTrack(self); Py_CLEAR(self->gref); diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 9ff624cf7..d9b32761d 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -48,6 +48,11 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_integer_t no_of_nodes, r; o = PyObject_GC_New(igraphmodule_DFSIterObject, igraphmodule_DFSIterType); + if (!o) { + return NULL; + } + Py_INCREF(igraphmodule_DFSIterType); + Py_INCREF(g); o->gref = g; o->graph = &g->g; diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 1d09cda1d..1e811c09f 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -46,7 +46,7 @@ PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self); * \brief Checks whether the given Python object is an edge */ int igraphmodule_Edge_Check(PyObject* obj) { - return obj ? PyObject_IsInstance(obj, (PyObject*)(igraphmodule_EdgeType)) : 0; + return obj ? PyObject_IsInstance(obj, (PyObject*)igraphmodule_EdgeType) : 0; } /** @@ -102,14 +102,18 @@ int igraphmodule_Edge_Validate(PyObject* obj) { */ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { igraphmodule_EdgeObject* self; + + self = PyObject_New(igraphmodule_EdgeObject, igraphmodule_EdgeType); if (self) { RC_ALLOC("Edge", self); + Py_INCREF(igraphmodule_EdgeType); Py_INCREF(gref); self->gref = gref; self->idx = idx; self->hash = -1; } + return (PyObject*)self; } diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index bf6655f19..eec5bdc6f 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -46,10 +46,7 @@ PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self); * \brief Checks whether the given Python object is a vertex */ int igraphmodule_Vertex_Check(PyObject* obj) { - if (!obj) - return 0; - - return PyObject_IsInstance(obj, (PyObject*)igraphmodule_VertexType); + return obj ? PyObject_IsInstance(obj, (PyObject*)igraphmodule_VertexType) : 0; } /** @@ -108,6 +105,7 @@ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer self = PyObject_New(igraphmodule_VertexObject, igraphmodule_VertexType); if (self) { RC_ALLOC("Vertex", self); + Py_INCREF(igraphmodule_VertexType); Py_INCREF(gref); self->gref = gref; self->idx = idx; diff --git a/test.sh b/test.sh index d5c4193cb..64d9b8789 100755 --- a/test.sh +++ b/test.sh @@ -1,6 +1,5 @@ #!/bin/bash -VENV_DIR=.venv PYTHON=python3 ############################################################################### @@ -8,18 +7,22 @@ PYTHON=python3 set -e CLEAN=0 +VENV_DIR=.venv -while getopts ":c" OPTION; do +while getopts ":ce:" OPTION; do case $OPTION in c) CLEAN=1 ;; + e) + VENV_DIR=$OPTARG + ;; \?) echo "Usage: $0 [-c]" ;; esac + shift $((OPTIND -1)) done -shift $((OPTIND -1)) if [ ! -d $VENV_DIR ]; then $PYTHON -m venv $VENV_DIR From c4a3731fcf5c1dda0a3cfbd0c397287c87665dea Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 12 Sep 2021 00:45:16 +0200 Subject: [PATCH 0619/1892] feat: EdgeSeq and VertexSeq are heap-allocated --- src/_igraph/arpackobject.c | 28 +-- src/_igraph/arpackobject.h | 3 +- src/_igraph/attributes.c | 9 +- src/_igraph/bfsiter.c | 58 +++--- src/_igraph/convert.c | 58 +++--- src/_igraph/dfsiter.c | 61 +++--- src/_igraph/edgeobject.c | 14 +- src/_igraph/edgeseqobject.c | 346 +++++++++++++++++++--------------- src/_igraph/edgeseqobject.h | 21 +-- src/_igraph/graphobject.c | 58 +----- src/_igraph/graphobject.h | 1 - src/_igraph/igraphmodule.c | 19 +- src/_igraph/pyhelpers.h | 15 ++ src/_igraph/vertexobject.c | 17 +- src/_igraph/vertexseqobject.c | 330 ++++++++++++++++++-------------- src/_igraph/vertexseqobject.h | 21 +-- test.sh | 11 +- 17 files changed, 540 insertions(+), 530 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index f8523c289..86d07f307 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -22,8 +22,9 @@ #include "arpackobject.h" #include "convert.h" -#include "graphobject.h" #include "error.h" +#include "graphobject.h" +#include "pyhelpers.h" PyTypeObject* igraphmodule_ARPACKOptionsType; PyObject* igraphmodule_arpack_options_default; @@ -32,15 +33,17 @@ PyObject* igraphmodule_arpack_options_default; * \ingroup python_interface_arpack * \brief Allocates a new ARPACK parameters object */ -PyObject* igraphmodule_ARPACKOptions_new() { - igraphmodule_ARPACKOptionsObject* self; - self = PyObject_New(igraphmodule_ARPACKOptionsObject, igraphmodule_ARPACKOptionsType); - if (self) { - Py_INCREF(igraphmodule_ARPACKOptionsType); /* needed because heap-allocated types are refcounted */ - igraph_arpack_options_init(&self->params); - igraph_arpack_options_init(&self->params_out); +int igraphmodule_ARPACKOptions_init(igraphmodule_ARPACKOptionsObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) { + return -1; } - return (PyObject*)self; + + igraph_arpack_options_init(&self->params); + igraph_arpack_options_init(&self->params_out); + + return 0; } /** @@ -48,9 +51,8 @@ PyObject* igraphmodule_ARPACKOptions_new() { * \brief Deallocates a Python representation of a given ARPACK parameters object */ static void igraphmodule_ARPACKOptions_dealloc(igraphmodule_ARPACKOptionsObject* self) { - PyTypeObject *tp = Py_TYPE(self); - PyObject_Del((PyObject*)self); - Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ + RC_DEALLOC("ARPACKOptions", self); + PY_FREE_AND_DECREF_TYPE(self); } /** \ingroup python_interface_arpack @@ -211,7 +213,7 @@ PyDoc_STRVAR( int igraphmodule_ARPACKOptions_register_type() { PyType_Slot slots[] = { - { Py_tp_new, igraphmodule_ARPACKOptions_new }, + { Py_tp_init, igraphmodule_ARPACKOptions_init }, { Py_tp_dealloc, igraphmodule_ARPACKOptions_dealloc }, { Py_tp_getattr, igraphmodule_ARPACKOptions_getattr }, { Py_tp_setattr, igraphmodule_ARPACKOptions_setattr }, diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index ea482444b..affc94718 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -23,7 +23,7 @@ #ifndef PYTHON_ARPACKOBJECT_H #define PYTHON_ARPACKOBJECT_H -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "preamble.h" #include @@ -49,7 +49,6 @@ extern PyObject* igraphmodule_arpack_options_default; int igraphmodule_ARPACKOptions_register_type(void); -PyObject* igraphmodule_ARPACKOptions_new(void); igraph_arpack_options_t *igraphmodule_ARPACKOptions_get(igraphmodule_ARPACKOptionsObject *self); #endif diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 765f902f2..86400f521 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -20,7 +20,7 @@ */ -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "attributes.h" #include "common.h" @@ -2025,12 +2025,13 @@ void igraphmodule_initialize_attribute_handler(void) { * Also raises a suitable Python exception if needed. */ int igraphmodule_attribute_name_check(PyObject* obj) { - PyObject* type_obj; + PyTypeObject* type_obj; - if (obj != 0 && PyBaseString_Check(obj)) + if (obj != 0 && PyBaseString_Check(obj)) { return 1; + } - type_obj = obj ? ((PyObject*)obj->ob_type) : 0; + type_obj = Py_TYPE(obj); if (type_obj != 0) { PyErr_Format(PyExc_TypeError, "igraph supports string attribute names only, got %R", type_obj); } else { diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 3bab05eb1..bb26e23e1 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -20,12 +20,13 @@ */ -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "bfsiter.h" #include "common.h" #include "convert.h" #include "error.h" +#include "pyhelpers.h" #include "vertexobject.h" /** @@ -44,19 +45,17 @@ PyTypeObject* igraphmodule_BFSIterType; * \return the allocated PyObject */ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_neimode_t mode, igraph_bool_t advanced) { - igraphmodule_BFSIterObject* o; + igraphmodule_BFSIterObject* self; igraph_integer_t no_of_nodes, r; - o = PyObject_GC_New(igraphmodule_BFSIterObject, igraphmodule_BFSIterType); - if (!o) { + self = (igraphmodule_BFSIterObject*) PyType_GenericNew(igraphmodule_BFSIterType, 0, 0); + if (!self) { return NULL; } - - Py_INCREF(igraphmodule_BFSIterType); Py_INCREF(g); - o->gref = g; - o->graph = &g->g; + self->gref = g; + self->graph = &g->g; if (!PyLong_Check(root) && !igraphmodule_Vertex_Check(root)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); @@ -64,55 +63,53 @@ PyObject* igraphmodule_BFSIter_new(igraphmodule_GraphObject *g, PyObject *root, } no_of_nodes = igraph_vcount(&g->g); - o->visited = (char*)calloc(no_of_nodes, sizeof(char)); - if (o->visited == 0) { + self->visited = (char*)calloc(no_of_nodes, sizeof(char)); + if (self->visited == 0) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_dqueue_int_init(&o->queue, 100)) { + if (igraph_dqueue_int_init(&self->queue, 100)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_vector_int_init(&o->neis, 0)) { + if (igraph_vector_int_init(&self->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); - igraph_dqueue_int_destroy(&o->queue); + igraph_dqueue_int_destroy(&self->queue); return NULL; } if (PyLong_Check(root)) { if (igraphmodule_PyObject_to_integer_t(root, &r)) { - igraph_dqueue_int_destroy(&o->queue); - igraph_vector_int_destroy(&o->neis); + igraph_dqueue_int_destroy(&self->queue); + igraph_vector_int_destroy(&self->neis); return NULL; } } else { r = ((igraphmodule_VertexObject*)root)->idx; } - if (igraph_dqueue_int_push(&o->queue, r) || - igraph_dqueue_int_push(&o->queue, 0) || - igraph_dqueue_int_push(&o->queue, -1)) { - igraph_dqueue_int_destroy(&o->queue); - igraph_vector_int_destroy(&o->neis); + if (igraph_dqueue_int_push(&self->queue, r) || + igraph_dqueue_int_push(&self->queue, 0) || + igraph_dqueue_int_push(&self->queue, -1)) { + igraph_dqueue_int_destroy(&self->queue); + igraph_vector_int_destroy(&self->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - o->visited[r] = 1; + self->visited[r] = 1; if (!igraph_is_directed(&g->g)) { mode=IGRAPH_ALL; } - o->mode = mode; - o->advanced = advanced; - - PyObject_GC_Track(o); + self->mode = mode; + self->advanced = advanced; - RC_ALLOC("BFSIter", o); + RC_ALLOC("BFSIter", self); - return (PyObject*)o; + return (PyObject*)self; } /** @@ -153,14 +150,11 @@ int igraphmodule_BFSIter_clear(igraphmodule_BFSIterObject *self) { * \brief Deallocates a Python representation of a given BFS iterator object */ static void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { - PyTypeObject *tp = Py_TYPE(self); + RC_DEALLOC("BFSIter", self); igraphmodule_BFSIter_clear(self); - RC_DEALLOC("BFSIter", self); - - PyObject_GC_Del(self); - Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ + PY_FREE_AND_DECREF_TYPE(self); } static PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 2d9234328..762d60366 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2764,7 +2764,7 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g /* Single vertex ID from Vertex object */ igraphmodule_VertexObject *vo = (igraphmodule_VertexObject*)o; *vid = igraphmodule_Vertex_get_index_igraph_integer(vo); - } else if (PyIndex_Check(o)) { + } else { /* Other numeric type that can be converted to an index */ PyObject* num = PyNumber_Index(o); if (num) { @@ -2774,17 +2774,15 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g return 1; } } else { - PyErr_SetString(PyExc_TypeError, "PyNumber_Index returned invalid type"); + PyErr_SetString(PyExc_TypeError, "PyNumber_Index() returned invalid type"); Py_DECREF(num); return 1; } Py_DECREF(num); } else { + PyErr_SetString(PyExc_TypeError, "only numbers, strings or igraph.Vertex objects can be converted to vertex IDs"); return 1; } - } else { - PyErr_SetString(PyExc_TypeError, "only numbers, strings or igraph.Vertex objects can be converted to vertex IDs"); - return 1; } if (*vid < 0) { @@ -2823,7 +2821,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, return 0; } - if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_VertexSeqType)) { + if (igraphmodule_VertexSeq_Check(o)) { /* Returns a vertex sequence from a VertexSeq object */ igraphmodule_VertexSeqObject *vso = (igraphmodule_VertexSeqObject*)o; @@ -2975,24 +2973,6 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g /* Single edge ID from Edge object */ igraphmodule_EdgeObject *eo = (igraphmodule_EdgeObject*)o; *eid = igraphmodule_Edge_get_index_as_igraph_integer(eo); - } else if (PyIndex_Check(o)) { - /* Other numeric type that can be converted to an index */ - PyObject* num = PyNumber_Index(o); - if (num) { - if (PyLong_Check(num)) { - if (igraphmodule_PyObject_to_integer_t(num, eid)) { - Py_DECREF(num); - return 1; - } - } else { - PyErr_SetString(PyExc_TypeError, "PyNumber_Index returned invalid type"); - Py_DECREF(num); - return 1; - } - Py_DECREF(num); - } else { - return 1; - } } else if (graph != 0 && PyTuple_Check(o)) { PyObject *o1, *o2; @@ -3001,8 +2981,8 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g return 1; } - o2 = PyTuple_GetItem(o, 1); { - if (!o2) + o2 = PyTuple_GetItem(o, 1); + if (!o2) { return 1; } @@ -3035,10 +3015,26 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g return 1; } } else { - PyErr_SetString(PyExc_TypeError, - "only numbers, igraph.Edge objects or tuples of vertex IDs can be " - "converted to edge IDs"); - return 1; + /* Other numeric type that can be converted to an index */ + PyObject* num = PyNumber_Index(o); + if (num) { + if (PyLong_Check(num)) { + if (igraphmodule_PyObject_to_integer_t(num, eid)) { + Py_DECREF(num); + return 1; + } + } else { + PyErr_SetString(PyExc_TypeError, "PyNumber_Index() returned invalid type"); + Py_DECREF(num); + return 1; + } + Py_DECREF(num); + } else { + PyErr_SetString(PyExc_TypeError, + "only numbers, igraph.Edge objects or tuples of vertex IDs can be " + "converted to edge IDs"); + return 1; + } } if (*eid < 0) { @@ -3075,7 +3071,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, return 0; } - if (PyObject_IsInstance(o, (PyObject*)&igraphmodule_EdgeSeqType)) { + if (igraphmodule_EdgeSeq_Check(o)) { /* Returns an edge sequence from an EdgeSeq object */ igraphmodule_EdgeSeqObject *eso = (igraphmodule_EdgeSeqObject*)o; if (igraph_es_copy(es, &eso->es)) { diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index d9b32761d..4f0bcdbc9 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -20,12 +20,13 @@ */ -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "convert.h" -#include "dfsiter.h" #include "common.h" +#include "dfsiter.h" #include "error.h" +#include "pyhelpers.h" #include "vertexobject.h" /** @@ -44,18 +45,17 @@ PyTypeObject* igraphmodule_DFSIterType; * \return the allocated PyObject */ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, igraph_neimode_t mode, igraph_bool_t advanced) { - igraphmodule_DFSIterObject* o; + igraphmodule_DFSIterObject* self; igraph_integer_t no_of_nodes, r; - o = PyObject_GC_New(igraphmodule_DFSIterObject, igraphmodule_DFSIterType); - if (!o) { + self = (igraphmodule_DFSIterObject*) PyType_GenericNew(igraphmodule_DFSIterType, 0, 0); + if (!self) { return NULL; } - Py_INCREF(igraphmodule_DFSIterType); Py_INCREF(g); - o->gref = g; - o->graph = &g->g; + self->gref = g; + self->graph = &g->g; if (!PyLong_Check(root) && !igraphmodule_Vertex_Check(root)) { PyErr_SetString(PyExc_TypeError, "root must be integer or igraph.Vertex"); @@ -63,27 +63,27 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, } no_of_nodes = igraph_vcount(&g->g); - o->visited = (char*)calloc(no_of_nodes, sizeof(char)); - if (o->visited == 0) { + self->visited = (char*)calloc(no_of_nodes, sizeof(char)); + if (self->visited == 0) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_stack_int_init(&o->stack, 100)) { + if (igraph_stack_int_init(&self->stack, 100)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - if (igraph_vector_int_init(&o->neis, 0)) { + if (igraph_vector_int_init(&self->neis, 0)) { PyErr_SetString(PyExc_MemoryError, "out of memory"); - igraph_stack_int_destroy(&o->stack); + igraph_stack_int_destroy(&self->stack); return NULL; } if (PyLong_Check(root)) { if (igraphmodule_PyObject_to_integer_t(root, &r)) { - igraph_stack_int_destroy(&o->stack); - igraph_vector_int_destroy(&o->neis); + igraph_stack_int_destroy(&self->stack); + igraph_vector_int_destroy(&self->neis); return NULL; } } else { @@ -91,28 +91,26 @@ PyObject* igraphmodule_DFSIter_new(igraphmodule_GraphObject *g, PyObject *root, } /* push the root onto the stack */ - if (igraph_stack_int_push(&o->stack, r) || - igraph_stack_int_push(&o->stack, 0) || - igraph_stack_int_push(&o->stack, -1)) { - igraph_stack_int_destroy(&o->stack); - igraph_vector_int_destroy(&o->neis); + if (igraph_stack_int_push(&self->stack, r) || + igraph_stack_int_push(&self->stack, 0) || + igraph_stack_int_push(&self->stack, -1)) { + igraph_stack_int_destroy(&self->stack); + igraph_vector_int_destroy(&self->neis); PyErr_SetString(PyExc_MemoryError, "out of memory"); return NULL; } - o->visited[r] = 1; + self->visited[r] = 1; if (!igraph_is_directed(&g->g)) { mode = IGRAPH_ALL; } - o->mode = mode; - o->advanced = advanced; - - PyObject_GC_Track(o); + self->mode = mode; + self->advanced = advanced; - RC_ALLOC("DFSIter", o); + RC_ALLOC("DFSIter", self); - return (PyObject*)o; + return (PyObject*)self; } /** @@ -153,14 +151,9 @@ static int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { * \brief Deallocates a Python representation of a given DFS iterator object */ static void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { - PyTypeObject *tp = Py_TYPE(self); - - igraphmodule_DFSIter_clear(self); - RC_DEALLOC("DFSIter", self); - - PyObject_GC_Del(self); - Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ + igraphmodule_DFSIter_clear(self); + PY_FREE_AND_DECREF_TYPE(self); } static PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 1e811c09f..5120456a5 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -22,7 +22,7 @@ */ -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "attributes.h" #include "convert.h" @@ -103,11 +103,10 @@ int igraphmodule_Edge_Validate(PyObject* obj) { PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { igraphmodule_EdgeObject* self; + self = (igraphmodule_EdgeObject*) PyType_GenericNew(igraphmodule_EdgeType, 0, 0); - self = PyObject_New(igraphmodule_EdgeObject, igraphmodule_EdgeType); if (self) { RC_ALLOC("Edge", self); - Py_INCREF(igraphmodule_EdgeType); Py_INCREF(gref); self->gref = gref; self->idx = idx; @@ -131,14 +130,9 @@ static int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { * \brief Deallocates a Python representation of a given edge object */ static void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { - PyTypeObject* tp = Py_TYPE(self); - - igraphmodule_Edge_clear(self); - RC_DEALLOC("Edge", self); - - PyObject_Del((PyObject*)self); - Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ + igraphmodule_Edge_clear(self); + PY_FREE_AND_DECREF_TYPE(self); } /** \ingroup python_interface_edge diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 86de684ed..fbb9c6703 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -22,6 +22,8 @@ */ +#define Py_LIMITED_API 0x03060100 + #include "attributes.h" #include "common.h" #include "convert.h" @@ -37,28 +39,16 @@ * \defgroup python_interface_edgeseq Edge sequence object */ -PyTypeObject igraphmodule_EdgeSeqType; +PyTypeObject* igraphmodule_EdgeSeqType; + +PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject *args); /** * \ingroup python_interface_edgeseq - * \brief Allocate a new edge sequence object for a given graph - * \param g the graph object being referenced - * \return the allocated PyObject + * \brief Checks whether the given Python object is an edge sequence */ -PyObject* igraphmodule_EdgeSeq_new(PyTypeObject *subtype, - PyObject *args, PyObject *kwds) { - igraphmodule_EdgeSeqObject* o; - - o=(igraphmodule_EdgeSeqObject*)PyType_GenericNew(subtype, args, kwds); - if (o == NULL) return NULL; - - igraph_es_all(&o->es, IGRAPH_EDGEORDER_ID); - o->gref=0; - o->weakreflist=0; - - RC_ALLOC("EdgeSeq", o); - - return (PyObject*)o; +int igraphmodule_EdgeSeq_Check(PyObject* obj) { + return obj ? PyObject_IsInstance(obj, (PyObject*)igraphmodule_EdgeSeqType) : 0; } /** @@ -70,8 +60,10 @@ igraphmodule_EdgeSeqObject* igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { igraphmodule_EdgeSeqObject *copy; - copy=(igraphmodule_EdgeSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0); - if (copy == NULL) return NULL; + copy = (igraphmodule_EdgeSeqObject*) PyType_GenericNew(Py_TYPE(o), 0, 0); + if (copy == NULL) { + return NULL; + } if (igraph_es_type(&o->es) == IGRAPH_ES_VECTOR) { igraph_vector_int_t v; @@ -90,7 +82,10 @@ igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { } copy->gref = o->gref; - if (o->gref) Py_INCREF(o->gref); + if (o->gref) { + Py_INCREF(o->gref); + } + RC_ALLOC("EdgeSeq(copy)", copy); return copy; @@ -102,15 +97,15 @@ igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { * \brief Initialize a new edge sequence object for a given graph * \return the initialized PyObject */ -int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, - PyObject *args, PyObject *kwds) { +int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "graph", "edges", NULL }; - PyObject *g, *esobj=Py_None; + PyObject *g, *esobj = Py_None; igraph_es_t es; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, - &igraphmodule_GraphType, &g, &esobj)) - return -1; + &igraphmodule_GraphType, &g, &esobj)) { + return -1; + } if (esobj == Py_None) { /* If es is None, we are selecting all the edges */ @@ -130,11 +125,12 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, igraph_es_1(&es, idx); } else { - /* We selected multiple edges */ + /* We selected multiple edges */ igraph_vector_int_t v; igraph_integer_t n = igraph_ecount(&((igraphmodule_GraphObject*)g)->g); - if (igraphmodule_PyObject_to_vector_int_t(esobj, &v)) + if (igraphmodule_PyObject_to_vector_int_t(esobj, &v)) { return -1; + } if (!igraph_vector_int_isininterval(&v, 0, n-1)) { igraph_vector_int_destroy(&v); PyErr_SetString(PyExc_ValueError, "edge index out of range"); @@ -160,16 +156,19 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, * \brief Deallocates a Python representation of a given edge sequence object */ void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self) { - if (self->weakreflist != NULL) + RC_DEALLOC("EdgeSeq", self); + + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *)self); + } + if (self->gref) { igraph_es_destroy(&self->es); Py_DECREF(self->gref); self->gref=0; } - Py_TYPE(self)->tp_free((PyObject*)self); - RC_DEALLOC("EdgeSeq", self); + PY_FREE_AND_DECREF_TYPE(self); } /** @@ -180,11 +179,13 @@ Py_ssize_t igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject* self) { igraph_t *g; igraph_integer_t result; - g=&GET_GRAPH(self); + g = &GET_GRAPH(self); + if (igraph_es_size(g, &self->es, &result)) { igraphmodule_handle_igraph_error(); return -1; } + return result; } @@ -197,8 +198,12 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, igraph_t *g; igraph_integer_t idx = -1; - if (!self->gref) return NULL; - g=&GET_GRAPH(self); + if (!self->gref) { + return NULL; + } + + g = &GET_GRAPH(self); + switch (igraph_es_type(&self->es)) { case IGRAPH_ES_ALL: if (i < 0) { @@ -246,6 +251,7 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, igraphmodule_InternalError, "unsupported edge selector type: %d", igraph_es_type(&self->es) ); } + if (idx < 0) { PyErr_SetString(PyExc_IndexError, "edge index out of range"); return NULL; @@ -269,8 +275,9 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* PyObject *result=0, *values, *item; Py_ssize_t i, n; - if (!igraphmodule_attribute_name_check(o)) + if (!igraphmodule_attribute_name_check(o)) { return 0; + } PyErr_Clear(); values = PyDict_GetItem(ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE], o); @@ -298,9 +305,19 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* } for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, i); + item = PyList_GetItem(values, i); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -313,9 +330,19 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* } for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, VECTOR(*self->es.data.vecptr)[i]); + item = PyList_GetItem(values, VECTOR(*self->es.data.vecptr)[i]); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -327,9 +354,19 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* } for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, self->es.data.seq.from + i); + item = PyList_GetItem(values, self->es.data.seq.from + i); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -341,35 +378,53 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* } PyObject* igraphmodule_EdgeSeq_is_all(igraphmodule_EdgeSeqObject* self) { - if (igraph_es_is_all(&self->es)) + if (igraph_es_is_all(&self->es)) { Py_RETURN_TRUE; - Py_RETURN_FALSE; + } else { + Py_RETURN_FALSE; + } } PyObject* igraphmodule_EdgeSeq_get_attribute_values_mapping(igraphmodule_EdgeSeqObject *self, PyObject *o) { Py_ssize_t index; - - /* Handle integer indices according to the sequence protocol */ - if (PyIndex_Check(o)) { - index = PyNumber_AsSsize_t(o, 0); - return igraphmodule_EdgeSeq_sq_item(self, index); - } + PyObject *index_o; /* Handle strings according to the mapping protocol */ - if (PyBaseString_Check(o)) + if (PyBaseString_Check(o)) { return igraphmodule_EdgeSeq_get_attribute_values(self, o); + } /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; - args = Py_BuildValue("(O)", o); - if (!args) + args = PyTuple_Pack(1, o); + + if (!args) { return NULL; + } + result = igraphmodule_EdgeSeq_select(self, args); Py_DECREF(args); + return result; } + /* Handle integer indices according to the sequence protocol */ + index_o = PyNumber_Index(o); + if (index_o) { + index = PyLong_AsSsize_t(index_o); + if (PyErr_Occurred()) { + Py_DECREF(index_o); + return NULL; + } else { + Py_DECREF(index_o); + return igraphmodule_EdgeSeq_sq_item(self, index); + } + } else { + /* clear TypeError raised by PyNumber_Index() */ + PyErr_Clear(); + } + /* Handle everything else according to the mapping protocol */ return igraphmodule_EdgeSeq_get_attribute_values(self, o); } @@ -387,12 +442,14 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject gr = self->gref; dict = ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE]; - if (!igraphmodule_attribute_name_check(attrname)) + if (!igraphmodule_attribute_name_check(attrname)) { return -1; + } if (values == 0) { - if (igraph_es_type(&self->es) == IGRAPH_ES_ALL) + if (igraph_es_type(&self->es) == IGRAPH_ES_ALL) { return PyDict_DelItem(dict, attrname); + } PyErr_SetString(PyExc_TypeError, "can't delete attribute from an edge sequence not representing the whole graph"); return -1; } @@ -406,7 +463,11 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject return -1; } Py_INCREF(values); - PyList_SET_ITEM(newList, 0, values); /* reference stolen here */ + + if (PyList_SetItem(newList, 0, values)) { /* reference stolen here */ + return -1; + } + result = igraphmodule_EdgeSeq_set_attribute_values_mapping(self, attrname, newList); Py_DECREF(newList); return result; @@ -458,7 +519,11 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject Py_DECREF(list); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ - PyList_SET_ITEM(list, i, item); + if (PyList_SetItem(list, i, item)) { + Py_DECREF(item); + Py_DECREF(list); + return -1; + } /* PyList_SET_ITEM stole a reference to the item automatically */ } if (PyDict_SetItem(dict, attrname, list)) { @@ -512,11 +577,16 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject igraph_integer_t n2 = igraph_ecount(&gr->g); list = PyList_New(n2); if (list == 0) { - igraph_vector_int_destroy(&es); return -1; + igraph_vector_int_destroy(&es); + return -1; } for (i = 0; i < n2; i++) { Py_INCREF(Py_None); - PyList_SET_ITEM(list, i, Py_None); + if (PyList_SetItem(list, i, Py_None)) { + Py_DECREF(Py_None); + Py_DECREF(list); + return -1; + } } for (i = 0, j = 0; i < no_of_edges; i++, j++) { if (j == n) { @@ -525,10 +595,15 @@ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject item = PySequence_GetItem(values, j); if (item == 0) { igraph_vector_int_destroy(&es); - Py_DECREF(list); return -1; + Py_DECREF(list); + return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ - PyList_SET_ITEM(list, VECTOR(es)[i], item); + if (PyList_SetItem(list, VECTOR(es)[i], item)) { + Py_DECREF(item); + Py_DECREF(list); + return -1; + } /* PyList_SET_ITEM stole a reference to the item automatically */ } igraph_vector_int_destroy(&es); @@ -614,16 +689,20 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject igraph_integer_t igraph_idx; Py_ssize_t i, j, n, m; - gr=self->gref; - result=igraphmodule_EdgeSeq_copy(self); - if (result == 0) + gr = self->gref; + result = igraphmodule_EdgeSeq_copy(self); + if (result == 0) { return NULL; + } /* First, filter by positional arguments */ n = PyTuple_Size(args); for (i = 0; i < n; i++) { - PyObject *item = PyTuple_GET_ITEM(args, i); - if (item == Py_None) { + PyObject *item = PyTuple_GetItem(args, i); + if (item == 0) { + Py_DECREF(result); + return NULL; + } else if (item == Py_None) { /* None means: select nothing */ igraph_es_destroy(&result->es); igraph_es_none(&result->es); @@ -698,8 +777,15 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } m = igraph_vector_int_size(&v2); for (; i= m || idx < 0) { @@ -886,39 +974,6 @@ PyMethodDef igraphmodule_EdgeSeq_methods[] = { {NULL} }; -/** - * \ingroup python_interface_edgeseq - * This is the collection of functions necessary to implement the - * edge sequence as a real sequence (e.g. allowing to reference - * edges by indices) - */ -static PySequenceMethods igraphmodule_EdgeSeq_as_sequence = { - (lenfunc)igraphmodule_EdgeSeq_sq_length, - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)igraphmodule_EdgeSeq_sq_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -/** - * \ingroup python_interface_edgeseq - * This is the collection of functions necessary to implement the - * edge sequence as a mapping (which maps attribute names to values) - */ -static PyMappingMethods igraphmodule_EdgeSeq_as_mapping = { - /* returns the number of edge attributes */ - (lenfunc) 0, - /* returns the values of an attribute by name */ - (binaryfunc) igraphmodule_EdgeSeq_get_attribute_values_mapping, - /* sets the values of an attribute by name */ - (objobjargproc) igraphmodule_EdgeSeq_set_attribute_values_mapping, -}; - /** * \ingroup python_interface_edgeseq * Returns the graph where the edge sequence belongs @@ -968,57 +1023,48 @@ PyGetSetDef igraphmodule_EdgeSeq_getseters[] = { {NULL} }; -/** \ingroup python_interface_edgeseq - * Python type object referencing the methods Python calls when it performs various operations on - * an edge sequence of a graph +/** + * \ingroup python_interface_edgeseq + * Member table for the \c igraph.EdgeSeq object */ -PyTypeObject igraphmodule_EdgeSeqType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph._igraph.EdgeSeq", /* tp_name */ - sizeof(igraphmodule_EdgeSeqObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)igraphmodule_EdgeSeq_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - &igraphmodule_EdgeSeq_as_sequence, /* tp_as_sequence */ - &igraphmodule_EdgeSeq_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ +PyMemberDef igraphmodule_EdgeSeq_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(igraphmodule_EdgeSeqObject, weakreflist), READONLY}, + { 0 } +}; + +PyDoc_STRVAR( + igraphmodule_EdgeSeq_doc, "Low-level representation of an edge sequence.\n\n" /* tp_doc */ "Don't use it directly, use L{igraph.EdgeSeq} instead.\n\n" - "@deffield ref: Reference", - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(igraphmodule_EdgeSeqObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - igraphmodule_EdgeSeq_methods, /* tp_methods */ - 0, /* tp_members */ - igraphmodule_EdgeSeq_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc) igraphmodule_EdgeSeq_init, /* tp_init */ - 0, /* tp_alloc */ - (newfunc) igraphmodule_EdgeSeq_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weakreflist */ -}; + "@deffield ref: Reference" +); + +int igraphmodule_EdgeSeq_register_type() { + PyType_Slot slots[] = { + { Py_tp_init, igraphmodule_EdgeSeq_init }, + { Py_tp_dealloc, igraphmodule_EdgeSeq_dealloc }, + { Py_tp_members, igraphmodule_EdgeSeq_members }, + { Py_tp_methods, igraphmodule_EdgeSeq_methods }, + { Py_tp_getset, igraphmodule_EdgeSeq_getseters }, + { Py_tp_doc, (void*) igraphmodule_EdgeSeq_doc }, + + { Py_sq_length, igraphmodule_EdgeSeq_sq_length }, + { Py_sq_item, igraphmodule_EdgeSeq_sq_item }, + + { Py_mp_subscript, igraphmodule_EdgeSeq_get_attribute_values_mapping }, + { Py_mp_ass_subscript, igraphmodule_EdgeSeq_set_attribute_values_mapping }, + + { 0 } + }; + + PyType_Spec spec = { + "igraph._igraph.EdgeSeq", /* name */ + sizeof(igraphmodule_EdgeSeqObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + slots, /* slots */ + }; + + igraphmodule_EdgeSeqType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_EdgeSeqType == 0; +} diff --git a/src/_igraph/edgeseqobject.h b/src/_igraph/edgeseqobject.h index 24307eef5..982368d69 100644 --- a/src/_igraph/edgeseqobject.h +++ b/src/_igraph/edgeseqobject.h @@ -39,24 +39,9 @@ typedef struct PyObject* weakreflist; } igraphmodule_EdgeSeqObject; -PyObject* igraphmodule_EdgeSeq_new(PyTypeObject *subtype, - PyObject *args, PyObject *kwds); -igraphmodule_EdgeSeqObject* igraphmodule_EdgeSeq_copy( - igraphmodule_EdgeSeqObject *o); -int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, - PyObject *args, PyObject *kwds); -void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self); +extern PyTypeObject* igraphmodule_EdgeSeqType; -Py_ssize_t igraphmodule_EdgeSeq_sq_length(igraphmodule_EdgeSeqObject *self); - -PyObject* igraphmodule_EdgeSeq_find(igraphmodule_EdgeSeqObject *self, - PyObject *args); -PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, - PyObject *args); - -PyObject* igraphmodule_EdgeSeq_get_graph(igraphmodule_EdgeSeqObject *self, - void* closure); - -extern PyTypeObject igraphmodule_EdgeSeqType; +int igraphmodule_EdgeSeq_Check(PyObject* obj); +int igraphmodule_EdgeSeq_register_type(void); #endif diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 1989fabea..6708e4705 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -57,56 +57,6 @@ PyTypeObject igraphmodule_GraphType; /** \defgroup python_interface_graph Graph object * \ingroup python_interface */ -/** - * \ingroup python_interface_internal - * \brief Initializes the internal structures in an \c igraph.Graph object's - * C representation. - * - * This function must be called whenever we create a new Graph object with - * \c tp_alloc - */ -void igraphmodule_Graph_init_internal(igraphmodule_GraphObject * self) -{ - if (!self) return; - - self->destructor = NULL; - self->weakreflist = NULL; -} - -/** - * \ingroup python_interface_graph - * \brief Creates a new igraph object in Python - * - * This function is called whenever a new \c igraph.Graph object is created in - * Python. An optional \c n parameter can be passed from Python, - * representing the number of vertices in the graph. If it is omitted, - * the default value is 0. - * - * Example call from Python: -\verbatim -g = igraph.Graph(5); -\endverbatim - * - * In fact, the parameters are processed by \c igraphmodule_Graph_init - * - * \return the new \c igraph.Graph object or NULL if an error occurred. - * - * \sa igraphmodule_Graph_init - * \sa igraph_empty - */ -PyObject *igraphmodule_Graph_new(PyTypeObject * type, PyObject * args, - PyObject * kwds) -{ - igraphmodule_GraphObject *self; - - self = (igraphmodule_GraphObject *) type->tp_alloc(type, 0); - RC_ALLOC("Graph", self); - - igraphmodule_Graph_init_internal(self); - - return (PyObject *) self; -} - /** * \ingroup python_interface_graph * \brief Clears the graph object's subobject (before deallocation) @@ -199,6 +149,9 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, igraph_vector_int_t edges_vector; igraph_bool_t edges_vector_owned = 0; + self->destructor = NULL; + self->weakreflist = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nOOO!", kwlist, &n, &edges, &dir, &PyCapsule_Type, &ptr_o)) @@ -741,8 +694,9 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); } - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) + if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { return NULL; + } if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, &return_single, 0)) { return NULL; @@ -16481,7 +16435,7 @@ PyTypeObject igraphmodule_GraphType = { 0, /* tp_dictoffset */ (initproc) igraphmodule_Graph_init, /* tp_init */ 0, /* tp_alloc */ - igraphmodule_Graph_new, /* tp_new */ + PyType_GenericNew, /* tp_new */ 0, /* tp_free */ }; diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 949b990bb..67521ad2c 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -50,7 +50,6 @@ typedef struct PyObject* weakreflist; } igraphmodule_GraphObject; -void igraphmodule_Graph_init_internal(igraphmodule_GraphObject *self); PyObject* igraphmodule_Graph_new(PyTypeObject *type, PyObject *args, PyObject *kwds); int igraphmodule_Graph_clear(igraphmodule_GraphObject *self); int igraphmodule_Graph_traverse(igraphmodule_GraphObject *self, visitproc visit, void *arg); diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 947541c54..8b9274113 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -836,19 +836,15 @@ PyObject* PyInit__igraph(void) INITERROR; } - /* Initialize VertexSeq, EdgeSeq */ - if (PyType_Ready(&igraphmodule_VertexSeqType) < 0) - INITERROR; - if (PyType_Ready(&igraphmodule_EdgeSeqType) < 0) - INITERROR; - /* Initialize types */ if ( igraphmodule_ARPACKOptions_register_type() || igraphmodule_BFSIter_register_type() || igraphmodule_DFSIter_register_type() || igraphmodule_Edge_register_type() || - igraphmodule_Vertex_register_type() + igraphmodule_EdgeSeq_register_type() || + igraphmodule_Vertex_register_type() || + igraphmodule_VertexSeq_register_type() ) { INITERROR; } @@ -869,9 +865,9 @@ PyObject* PyInit__igraph(void) PyModule_AddObject(m, "DFSIter", (PyObject*)igraphmodule_DFSIterType); PyModule_AddObject(m, "ARPACKOptions", (PyObject*)igraphmodule_ARPACKOptionsType); PyModule_AddObject(m, "Edge", (PyObject*)igraphmodule_EdgeType); - PyModule_AddObject(m, "EdgeSeq", (PyObject*)&igraphmodule_EdgeSeqType); + PyModule_AddObject(m, "EdgeSeq", (PyObject*)igraphmodule_EdgeSeqType); PyModule_AddObject(m, "Vertex", (PyObject*)igraphmodule_VertexType); - PyModule_AddObject(m, "VertexSeq", (PyObject*)&igraphmodule_VertexSeqType); + PyModule_AddObject(m, "VertexSeq", (PyObject*)igraphmodule_VertexSeqType); /* Internal error exception type */ igraphmodule_InternalError = @@ -879,7 +875,10 @@ PyObject* PyInit__igraph(void) PyModule_AddObject(m, "InternalError", igraphmodule_InternalError); /* ARPACK default options variable */ - igraphmodule_arpack_options_default = igraphmodule_ARPACKOptions_new(); + igraphmodule_arpack_options_default = PyObject_CallFunction((PyObject*) igraphmodule_ARPACKOptionsType, 0); + if (igraphmodule_arpack_options_default == NULL) + INITERROR; + PyModule_AddObject(m, "arpack_options", igraphmodule_arpack_options_default); /* Useful constants */ diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 724c1166a..56fd4d399 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -47,6 +47,21 @@ char* PyUnicode_CopyAsString(PyObject* string); #define PY_IGRAPH_WARN(msg) \ PyErr_WarnEx(PyExc_RuntimeWarning, (msg), 1) +/* Calling Py_DECREF() on heap-allocated types in tp_dealloc was not needed + * before Python 3.8 (see Python issue 35810) */ +#if PY_VERSION_HEX >= 0x03080000 + #define PY_FREE_AND_DECREF_TYPE(obj) { \ + PyTypeObject* _tp = Py_TYPE(obj); \ + ((freefunc)PyType_GetSlot(_tp, Py_tp_free))(obj); \ + Py_DECREF(_tp); \ + } +#else + #define PY_FREE_AND_DECREF_TYPE(obj) { \ + PyTypeObject* _tp = Py_TYPE(obj); \ + ((freefunc)PyType_GetSlot(_tp, Py_tp_free))(obj); \ + } +#endif + #define CHECK_SSIZE_T_RANGE(value, message) { \ if ((value) < 0) { \ PyErr_SetString(PyExc_ValueError, message " must be non-negative"); \ diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index eec5bdc6f..a51578fdc 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -22,7 +22,7 @@ */ -#define Py_LIMITED_API 0x03060000 +#define Py_LIMITED_API 0x03060100 #include "attributes.h" #include "convert.h" @@ -102,15 +102,17 @@ int igraphmodule_Vertex_Validate(PyObject* obj) { */ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { igraphmodule_VertexObject* self; - self = PyObject_New(igraphmodule_VertexObject, igraphmodule_VertexType); + + self = (igraphmodule_VertexObject*) PyType_GenericNew(igraphmodule_VertexType, 0, 0); + if (self) { RC_ALLOC("Vertex", self); - Py_INCREF(igraphmodule_VertexType); Py_INCREF(gref); self->gref = gref; self->idx = idx; self->hash = -1; } + return (PyObject*)self; } @@ -128,14 +130,9 @@ static int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { * \brief Deallocates a Python representation of a given vertex object */ static void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { - PyTypeObject* tp = Py_TYPE(self); - - igraphmodule_Vertex_clear(self); - RC_DEALLOC("Vertex", self); - - PyObject_Del((PyObject*)self); - Py_DECREF(tp); /* needed because heap-allocated types are refcounted */ + igraphmodule_Vertex_clear(self); + PY_FREE_AND_DECREF_TYPE(self); } /** \ingroup python_interface_vertex diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index ff0e6c200..02160beb5 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -22,6 +22,8 @@ */ +#define Py_LIMITED_API 0x03060100 + #include "attributes.h" #include "common.h" #include "convert.h" @@ -37,27 +39,16 @@ * \defgroup python_interface_vertexseq Vertex sequence object */ -PyTypeObject igraphmodule_VertexSeqType; +PyTypeObject* igraphmodule_VertexSeqType; + +PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject *args); /** * \ingroup python_interface_vertexseq - * \brief Allocate a new vertex sequence object for a given graph - * \return the allocated PyObject + * \brief Checks whether the given Python object is a vertex sequence */ -PyObject* igraphmodule_VertexSeq_new(PyTypeObject *subtype, - PyObject *args, PyObject *kwds) { - igraphmodule_VertexSeqObject *o; - - o=(igraphmodule_VertexSeqObject*)PyType_GenericNew(subtype, args, kwds); - if (o == NULL) return NULL; - - igraph_vs_all(&o->vs); - o->gref=0; - o->weakreflist=0; - - RC_ALLOC("VertexSeq", o); - - return (PyObject*)o; +int igraphmodule_VertexSeq_Check(PyObject* obj) { + return obj ? PyObject_IsInstance(obj, (PyObject*)igraphmodule_VertexSeqType) : 0; } /** @@ -69,8 +60,10 @@ igraphmodule_VertexSeqObject* igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) { igraphmodule_VertexSeqObject *copy; - copy=(igraphmodule_VertexSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0); - if (copy == NULL) return NULL; + copy = (igraphmodule_VertexSeqObject*) PyType_GenericNew(Py_TYPE(o), 0, 0); + if (copy == NULL) { + return NULL; + } if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) { igraph_vector_int_t v; @@ -157,15 +150,19 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, * \brief Deallocates a Python representation of a given vertex sequence object */ void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self) { - if (self->weakreflist != NULL) + RC_DEALLOC("VertexSeq", self); + + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); + } + if (self->gref) { igraph_vs_destroy(&self->vs); Py_DECREF(self->gref); self->gref=0; } - Py_TYPE(self)->tp_free((PyObject*)self); - RC_DEALLOC("VertexSeq", self); + + PY_FREE_AND_DECREF_TYPE(self); } /** @@ -287,12 +284,24 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje case IGRAPH_VS_ALL: n = PyList_Size(values); result = PyList_New(n); - if (!result) return 0; + if (!result) { + return 0; + } for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, i); + item = PyList_GetItem(values, i); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -300,12 +309,24 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje case IGRAPH_VS_VECTORPTR: n = igraph_vector_int_size(self->vs.data.vecptr); result = PyList_New(n); - if (!result) return 0; + if (!result) { + return 0; + } for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, VECTOR(*self->vs.data.vecptr)[i]); + item = PyList_GetItem(values, VECTOR(*self->vs.data.vecptr)[i]); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -316,9 +337,19 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje if (!result) return 0; for (i = 0; i < n; i++) { - item = PyList_GET_ITEM(values, self->vs.data.seq.from + i); + item = PyList_GetItem(values, self->vs.data.seq.from + i); + if (!item) { + Py_DECREF(result); + return 0; + } + Py_INCREF(item); - PyList_SET_ITEM(result, i, item); + + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } break; @@ -332,29 +363,44 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje PyObject* igraphmodule_VertexSeq_get_attribute_values_mapping(igraphmodule_VertexSeqObject *self, PyObject *o) { Py_ssize_t index; - - /* Handle integer indices according to the sequence protocol */ - if (PyIndex_Check(o)) { - index = PyNumber_AsSsize_t(o, 0); - return igraphmodule_VertexSeq_sq_item(self, index); - } + PyObject* index_o; /* Handle strings according to the mapping protocol */ - if (PyBaseString_Check(o)) + if (PyBaseString_Check(o)) { return igraphmodule_VertexSeq_get_attribute_values(self, o); + } /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; - args = Py_BuildValue("(O)", o); + args = PyTuple_Pack(1, o); - if (!args) + if (!args) { return NULL; + } + result = igraphmodule_VertexSeq_select(self, args); Py_DECREF(args); + return result; } + /* Handle integer indices according to the sequence protocol */ + index_o = PyNumber_Index(o); + if (index_o) { + index = PyLong_AsSsize_t(index_o); + if (PyErr_Occurred()) { + Py_DECREF(index_o); + return NULL; + } else { + Py_DECREF(index_o); + return igraphmodule_VertexSeq_sq_item(self, index); + } + } else { + /* clear TypeError raised by PyNumber_Index() */ + PyErr_Clear(); + } + /* Handle everything else according to the mapping protocol */ return igraphmodule_VertexSeq_get_attribute_values(self, o); } @@ -389,16 +435,25 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb * single element (the value itself) and then call ourselves again */ int result; PyObject *newList = PyList_New(1); - if (newList == 0) return -1; + if (newList == 0) { + return -1; + } + Py_INCREF(values); - PyList_SET_ITEM(newList, 0, values); /* reference stolen here */ + if (PyList_SetItem(newList, 0, values)) { /* reference stolen here */ + return -1; + } + result = igraphmodule_VertexSeq_set_attribute_values_mapping(self, attrname, newList); Py_DECREF(newList); + return result; } - n=PySequence_Size(values); - if (n < 0) return -1; + n = PySequence_Size(values); + if (n < 0) { + return -1; + } if (igraph_vs_type(&self->vs) == IGRAPH_VS_ALL) { no_of_nodes = igraph_vcount(&gr->g); @@ -429,9 +484,16 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb for (i = 0, j = 0; i < no_of_nodes; i++, j++) { if (j == n) j = 0; item = PySequence_GetItem(values, j); - if (item == 0) { Py_DECREF(list); return -1; } + if (item == 0) { + Py_DECREF(list); + return -1; + } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ - PyList_SET_ITEM(list, i, item); + if (PyList_SetItem(list, i, item)) { + Py_DECREF(item); + Py_DECREF(list); + return -1; + } /* PyList_SET_ITEM stole a reference to the item automatically */ } if (PyDict_SetItem(dict, attrname, list)) { @@ -487,19 +549,31 @@ int igraphmodule_VertexSeq_set_attribute_values_mapping(igraphmodule_VertexSeqOb igraph_vector_int_destroy(&vs); return -1; } - for (i=0; igref; - result=igraphmodule_VertexSeq_copy(self); - if (result==0) + gr = self->gref; + result = igraphmodule_VertexSeq_copy(self); + if (result == 0) { return NULL; + } /* First, filter by positional arguments */ n = PyTuple_Size(args); - for (i=0; ivs); igraph_vs_none(&result->vs); @@ -700,8 +777,14 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } m = igraph_vector_int_size(&v2); for (; i= m || idx < 0) { + Py_DECREF(result); PyErr_SetString(PyExc_ValueError, "vertex index out of range"); igraph_vector_int_destroy(&v); igraph_vector_int_destroy(&v2); @@ -880,6 +964,7 @@ PyObject* igraphmodule_VertexSeq_get_indices(igraphmodule_VertexSeqObject* self, igraphmodule_handle_igraph_error(); return 0; } + if (igraph_vs_as_vector(&gr->g, self->vs, &vs)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&vs); @@ -900,8 +985,11 @@ PyObject* igraphmodule_VertexSeq__name_index(igraphmodule_VertexSeqObject* self, void* closure) { igraphmodule_GraphObject *gr = self->gref; PyObject* result = ATTR_NAME_INDEX(&gr->g); - if (result == 0) + + if (result == 0) { Py_RETURN_NONE; + } + Py_INCREF(result); return result; } @@ -961,39 +1049,6 @@ PyMethodDef igraphmodule_VertexSeq_methods[] = { {NULL} }; -/** - * \ingroup python_interface_vertexseq - * This is the collection of functions necessary to implement the - * vertex sequence as a real sequence (e.g. allowing to reference - * vertices by indices) - */ -static PySequenceMethods igraphmodule_VertexSeq_as_sequence = { - (lenfunc)igraphmodule_VertexSeq_sq_length, - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)igraphmodule_VertexSeq_sq_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - 0, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -/** - * \ingroup python_interface_vertexseq - * This is the collection of functions necessary to implement the - * vertex sequence as a mapping (which maps attribute names to values) - */ -static PyMappingMethods igraphmodule_VertexSeq_as_mapping = { - /* this must be null, otherwise it f.cks up sq_length when inherited */ - (lenfunc) 0, - /* returns the values of an attribute by name */ - (binaryfunc) igraphmodule_VertexSeq_get_attribute_values_mapping, - /* sets the values of an attribute by name */ - (objobjargproc) igraphmodule_VertexSeq_set_attribute_values_mapping, -}; - /** * \ingroup python_interface_vertexseq * Getter/setter table for the \c igraph.VertexSeq object @@ -1011,57 +1066,48 @@ PyGetSetDef igraphmodule_VertexSeq_getseters[] = { {NULL} }; -/** \ingroup python_interface_vertexseq - * Python type object referencing the methods Python calls when it performs various operations on - * a vertex sequence of a graph +/** + * \ingroup python_interface_vertexseq + * Member table for the \c igraph.VertexSeq object */ -PyTypeObject igraphmodule_VertexSeqType = -{ - PyVarObject_HEAD_INIT(0, 0) - "igraph._igraph.VertexSeq", /* tp_name */ - sizeof(igraphmodule_VertexSeqObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)igraphmodule_VertexSeq_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - &igraphmodule_VertexSeq_as_sequence, /* tp_as_sequence */ - &igraphmodule_VertexSeq_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ +PyMemberDef igraphmodule_VertexSeq_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(igraphmodule_VertexSeqObject, weakreflist), READONLY}, + { 0 } +}; + +PyDoc_STRVAR( + igraphmodule_VertexSeq_doc, "Low-level representation of a vertex sequence.\n\n" /* tp_doc */ "Don't use it directly, use L{igraph.VertexSeq} instead.\n\n" - "@deffield ref: Reference", - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(igraphmodule_VertexSeqObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - igraphmodule_VertexSeq_methods, /* tp_methods */ - 0, /* tp_members */ - igraphmodule_VertexSeq_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc) igraphmodule_VertexSeq_init, /* tp_init */ - 0, /* tp_alloc */ - (newfunc) igraphmodule_VertexSeq_new, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weakreflist */ -}; + "@deffield ref: Reference" +); + +int igraphmodule_VertexSeq_register_type() { + PyType_Slot slots[] = { + { Py_tp_init, igraphmodule_VertexSeq_init }, + { Py_tp_dealloc, igraphmodule_VertexSeq_dealloc }, + { Py_tp_members, igraphmodule_VertexSeq_members }, + { Py_tp_methods, igraphmodule_VertexSeq_methods }, + { Py_tp_getset, igraphmodule_VertexSeq_getseters }, + { Py_tp_doc, (void*) igraphmodule_VertexSeq_doc }, + + { Py_sq_length, igraphmodule_VertexSeq_sq_length }, + { Py_sq_item, igraphmodule_VertexSeq_sq_item }, + + { Py_mp_subscript, igraphmodule_VertexSeq_get_attribute_values_mapping }, + { Py_mp_ass_subscript, igraphmodule_VertexSeq_set_attribute_values_mapping }, + + { 0 } + }; + + PyType_Spec spec = { + "igraph._igraph.VertexSeq", /* name */ + sizeof(igraphmodule_VertexSeqObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* flags */ + slots, /* slots */ + }; + + igraphmodule_VertexSeqType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_VertexSeqType == 0; +} diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index de195bb78..e27c47f08 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -38,24 +38,9 @@ typedef struct { PyObject* weakreflist; } igraphmodule_VertexSeqObject; -PyObject* igraphmodule_VertexSeq_new(PyTypeObject *subtype, - PyObject* args, PyObject* kwds); -int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject* self, - PyObject* args, PyObject* kwds); -void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self); +extern PyTypeObject* igraphmodule_VertexSeqType; -Py_ssize_t igraphmodule_VertexSeq_sq_length(igraphmodule_VertexSeqObject *self); - -PyObject* igraphmodule_VertexSeq_find(igraphmodule_VertexSeqObject *self, - PyObject *args); -PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, - PyObject *args); - -int igraphmodule_VertexSeq_to_vector_t(igraphmodule_VertexSeqObject *self, - igraph_vector_int_t *v); -PyObject* igraphmodule_VertexSeq_get_graph(igraphmodule_VertexSeqObject *self, - void* closure); - -extern PyTypeObject igraphmodule_VertexSeqType; +int igraphmodule_VertexSeq_Check(PyObject* obj); +int igraphmodule_VertexSeq_register_type(void); #endif diff --git a/test.sh b/test.sh index 64d9b8789..b3e124265 100755 --- a/test.sh +++ b/test.sh @@ -7,9 +7,11 @@ PYTHON=python3 set -e CLEAN=0 +PYTEST_ARGS= VENV_DIR=.venv -while getopts ":ce:" OPTION; do +while getopts ":ce:k:" OPTION; do + echo "$OPTION" case $OPTION in c) CLEAN=1 @@ -17,12 +19,15 @@ while getopts ":ce:" OPTION; do e) VENV_DIR=$OPTARG ;; + k) + PYTEST_ARGS="${PYTEST_ARGS} -k $OPTARG" + ;; \?) echo "Usage: $0 [-c]" ;; esac - shift $((OPTIND -1)) done +shift $((OPTIND -1)) if [ ! -d $VENV_DIR ]; then $PYTHON -m venv $VENV_DIR @@ -36,5 +41,5 @@ fi $VENV_DIR/bin/python setup.py build $VENV_DIR/bin/pip install --use-feature=in-tree-build .[plotting,test] -$VENV_DIR/bin/pytest tests +$VENV_DIR/bin/pytest tests ${PYTEST_ARGS} From b83dc3dc17782641db42d535e897135a1489f577 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 12 Sep 2021 00:56:45 +0200 Subject: [PATCH 0620/1892] fix: remove some deprecated constructs; uniformize deprecation and runtime warnings --- src/_igraph/convert.c | 7 ++- src/_igraph/error.c | 4 +- src/_igraph/graphobject.c | 108 +++++++++++++++---------------------- src/_igraph/igraphmodule.c | 2 +- src/_igraph/indexing.c | 7 +-- 5 files changed, 55 insertions(+), 73 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 762d60366..8fabe973a 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -131,8 +131,7 @@ int igraphmodule_PyObject_to_enum(PyObject *o, free(s); if (best_unique) { - PyErr_Warn( - PyExc_DeprecationWarning, + PY_IGRAPH_DEPRECATED( "Partial string matches of enum members are deprecated since igraph 0.9.3; " "use strings that identify an enum member unambiguously." ); @@ -2339,7 +2338,7 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap } else if (PyFloat_Check(item)) { MATRIX(*m, i, j) = PyFloat_AsDouble(item); } else if (!was_warned) { - PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); + PY_IGRAPH_WARN("non-numeric value in matrix ignored"); was_warned=1; } Py_DECREF(item); @@ -2417,7 +2416,7 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i } if (!ok && !was_warned) { - PyErr_Warn(PyExc_Warning, "non-numeric value in matrix ignored"); + PY_IGRAPH_WARN("non-numeric value in matrix ignored"); was_warned = 1; } diff --git a/src/_igraph/error.c b/src/_igraph/error.c index 2954ad7b7..8666ce02d 100644 --- a/src/_igraph/error.c +++ b/src/_igraph/error.c @@ -21,6 +21,8 @@ */ #include "error.h" +#include "pyhelpers.h" + #include /** \ingroup python_interface_errors @@ -60,7 +62,7 @@ void igraphmodule_igraph_warning_hook(const char *reason, const char *file, int line, int igraph_errno) { char buf[4096]; snprintf(buf, sizeof(buf), "%s at %s:%i", reason, file, line); - PyErr_Warn(PyExc_RuntimeWarning, buf); + PY_IGRAPH_WARN(buf); } /** diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 6708e4705..c1c361181 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -639,11 +639,9 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, /* no arguments means delete all. */ - /*Py_None also means all for now, but it is deprecated */ + /* Py_None means "do nothing" since igraph 0.10 */ if (list == Py_None) { - PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " - "deprecated since igraph 0.8.3, please use " - "Graph.delete_vertices() instead"); + Py_RETURN_NONE; } /* this already converts no arguments and Py_None to all vertices */ @@ -676,24 +674,18 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, { PyObject *list = Py_None; PyObject *loops = Py_True; - PyObject *dtype_o = Py_None; PyObject *dmode_o = Py_None; igraph_neimode_t dmode = IGRAPH_ALL; igraph_vector_int_t result; igraph_vs_t vs; igraph_bool_t return_single = 0; - static char *kwlist[] = { "vertices", "mode", "loops", "type", NULL }; + static char *kwlist[] = { "vertices", "mode", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, - &list, &dmode_o, &loops, &dtype_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, + &list, &dmode_o, &loops)) return NULL; - if (dmode_o == Py_None && dtype_o != Py_None) { - dmode_o = dtype_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); - } - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { return NULL; } @@ -813,7 +805,6 @@ PyObject *igraphmodule_Graph_strength(igraphmodule_GraphObject * self, { PyObject *list = Py_None; PyObject *loops = Py_True; - PyObject *dtype_o = Py_None; PyObject *dmode_o = Py_None; PyObject *weights_o = Py_None; igraph_neimode_t dmode = IGRAPH_ALL; @@ -821,21 +812,15 @@ PyObject *igraphmodule_Graph_strength(igraphmodule_GraphObject * self, igraph_vs_t vs; igraph_bool_t return_single = 0; - static char *kwlist[] = { "vertices", "mode", "loops", "weights", - "type", NULL }; + static char *kwlist[] = { "vertices", "mode", "loops", "weights", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, - &list, &dmode_o, &loops, &weights_o, - &dtype_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, + &list, &dmode_o, &loops, &weights_o)) return NULL; - if (dmode_o == Py_None && dtype_o != Py_None) { - dmode_o = dtype_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); - } - - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) + if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { return NULL; + } if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, &return_single, 0)) { igraphmodule_handle_igraph_error(); @@ -909,33 +894,27 @@ PyObject *igraphmodule_Graph_maxdegree(igraphmodule_GraphObject * self, { PyObject *list = Py_None; igraph_neimode_t dmode = IGRAPH_ALL; - PyObject *dtype_o = Py_None; PyObject *dmode_o = Py_None; PyObject *loops = Py_False; igraph_integer_t result; igraph_vs_t vs; igraph_bool_t return_single = 0; - static char *kwlist[] = { "vertices", "mode", "loops", "type", NULL }; + static char *kwlist[] = { "vertices", "mode", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, - &list, &dmode_o, &loops, &dtype_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &list, &dmode_o, &loops)) return NULL; - if (dmode_o == Py_None && dtype_o != Py_None) { - dmode_o = dtype_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); + if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { + return NULL; } - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) return NULL; - if (igraphmodule_PyObject_to_vs_t(list, &vs, &self->g, &return_single, 0)) { igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_maxdegree(&self->g, &result, vs, - dmode, PyObject_IsTrue(loops))) { + if (igraph_maxdegree(&self->g, &result, vs, dmode, PyObject_IsTrue(loops))) { igraphmodule_handle_igraph_error(); igraph_vs_destroy(&vs); return NULL; @@ -1168,30 +1147,28 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, PyObject *igraphmodule_Graph_neighbors(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *list, *dtype_o=Py_None, *dmode_o=Py_None, *index_o; + PyObject *list, *dmode_o = Py_None, *index_o; igraph_neimode_t dmode = IGRAPH_ALL; igraph_integer_t idx; igraph_vector_int_t result; - static char *kwlist[] = { "vertex", "mode", "type", NULL }; + static char *kwlist[] = { "vertex", "mode", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, - &index_o, &dmode_o, &dtype_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &index_o, &dmode_o)) return NULL; - if (dmode_o == Py_None && dtype_o != Py_None) { - dmode_o = dtype_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); + if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { + return NULL; } - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) + if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) { return NULL; + } - if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) + if (igraph_vector_int_init(&result, 1)) { + igraphmodule_handle_igraph_error(); return NULL; - - if (igraph_vector_int_init(&result, 1)) - return igraphmodule_handle_igraph_error(); + } if (igraph_neighbors(&self->g, &result, idx, dmode)) { igraphmodule_handle_igraph_error(); @@ -1219,29 +1196,29 @@ PyObject *igraphmodule_Graph_neighbors(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_incident(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *list, *dmode_o = Py_None, *dtype_o = Py_None, *index_o; + PyObject *list, *dmode_o = Py_None, *index_o; igraph_neimode_t dmode = IGRAPH_OUT; igraph_integer_t idx; igraph_vector_int_t result; - static char *kwlist[] = { "vertex", "mode", "type", NULL }; + static char *kwlist[] = { "vertex", "mode", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, - &index_o, &dmode_o, &dtype_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &index_o, &dmode_o)) return NULL; - if (dmode_o == Py_None && dtype_o != Py_None) { - dmode_o = dtype_o; - PY_IGRAPH_DEPRECATED("type=... keyword argument is deprecated since igraph 0.6, use mode=... instead"); + if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) { + return NULL; } - if (igraphmodule_PyObject_to_neimode_t(dmode_o, &dmode)) + if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) { return NULL; + } - if (igraphmodule_PyObject_to_vid(index_o, &idx, &self->g)) + if (igraph_vector_int_init(&result, 1)) { + igraphmodule_handle_igraph_error(); return NULL; + } - igraph_vector_int_init(&result, 1); if (igraph_incident(&self->g, &result, idx, dmode)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&result); @@ -7028,10 +7005,11 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, if (fixed_o != 0 && fixed_o != Py_None) { /* Apparently the "fixed" argument does not do anything in the DrL * implementation so we throw a warning if the user tries to use it */ - PyErr_Warn(PyExc_DeprecationWarning, "The fixed=... argument of the DrL " - "layout is ignored; it is kept only for sake of backwards " - "compatibility. The DrL layout algorithm does not support " - "permanently fixed nodes."); + PY_IGRAPH_DEPRECATED( + "The fixed=... argument of the DrL layout is ignored; it is kept only " + "for sake of backwards compatibility. The DrL layout algorithm does not " + "support permanently fixed nodes." + ); fixed = (igraph_vector_bool_t*)malloc(sizeof(igraph_vector_bool_t)); if (!fixed) { PyErr_NoMemory(); @@ -7890,8 +7868,10 @@ PyObject *igraphmodule_Graph_to_directed(igraphmodule_GraphObject * self, mode = IGRAPH_TO_DIRECTED_MUTUAL; } else { mode = PyObject_IsTrue(mutual_o) ? IGRAPH_TO_DIRECTED_MUTUAL : IGRAPH_TO_DIRECTED_ARBITRARY; - PyErr_Warn(PyExc_DeprecationWarning, "The 'mutual' argument is deprecated since " - "igraph 0.9.3, please use mode=... instead"); + PY_IGRAPH_DEPRECATED( + "The 'mutual' argument is deprecated since igraph 0.9.3, please use " + "mode=... instead" + ); } } else { if (igraphmodule_PyObject_to_to_directed_t(mode_o, &mode)) { diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 8b9274113..d4dfa1e7d 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -264,7 +264,7 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd } if (PySequence_Size(o) > 2) { - PyErr_Warn(PyExc_Warning, "vertex with more than 2 coordinates found, considering only the first 2"); + PY_IGRAPH_WARN("vertex with more than 2 coordinates found, considering only the first 2"); } } else { PyErr_SetString(PyExc_TypeError, "vertex with less than 2 coordinates found"); diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index 70b76ef94..7dedd2677 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -349,9 +349,10 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, IGRAPH_VIT_NEXT(vit); } if (!IGRAPH_VIT_END(vit)) { - PyErr_WarnEx(PyExc_RuntimeWarning, - "iterable was shorter than the number of vertices in the vertex " - "sequence", 1); + PY_IGRAPH_WARN( + "iterable was shorter than the number of vertices in the vertex " + "sequence" + ); } } else { /* The new value is not an iterable; setting the same value for From 70be1404339bac1bb4b7b636887962c81420d209 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 14:51:43 +0200 Subject: [PATCH 0621/1892] refactor: module now uses Python's limited API only and thus we can ship a single wheel per platform --- setup.py | 2 +- src/_igraph/arpackobject.h | 1 - src/_igraph/attributes.c | 2 - src/_igraph/bfsiter.c | 2 - src/_igraph/convert.c | 152 +++++++++++++------- src/_igraph/dfsiter.c | 2 - src/_igraph/edgeobject.c | 2 - src/_igraph/edgeseqobject.c | 4 +- src/_igraph/graphobject.c | 260 ++++++++++++++-------------------- src/_igraph/graphobject.h | 175 +---------------------- src/_igraph/igraphmodule.c | 5 +- src/_igraph/operators.c | 52 ++++--- src/_igraph/preamble.h | 4 + src/_igraph/pyhelpers.c | 24 +++- src/_igraph/vertexobject.c | 2 - src/_igraph/vertexseqobject.c | 4 +- src/igraph/utils.py | 4 - tests/test_basic.py | 64 ++++++++- 18 files changed, 335 insertions(+), 426 deletions(-) diff --git a/setup.py b/setup.py index c7dbb458c..5ba9f0e12 100644 --- a/setup.py +++ b/setup.py @@ -792,7 +792,7 @@ def use_educated_guess(self) -> None: # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) sources.append(os.path.join("src", "_igraph", "force_cpp_linker.cpp")) -igraph_extension = Extension("igraph._igraph", sources) +igraph_extension = Extension("igraph._igraph", sources, py_limited_api=True) description = """Python interface to the igraph high performance graph library, primarily aimed at complex network research and analysis. diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index affc94718..18ab29d4c 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -23,7 +23,6 @@ #ifndef PYTHON_ARPACKOBJECT_H #define PYTHON_ARPACKOBJECT_H -#define Py_LIMITED_API 0x03060100 #include "preamble.h" #include diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 86400f521..dfada5c38 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -20,8 +20,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "attributes.h" #include "common.h" #include "convert.h" diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index bb26e23e1..a250bbedd 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -20,8 +20,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "bfsiter.h" #include "common.h" #include "convert.h" diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 8fabe973a..b790689bd 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -371,7 +371,15 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, /* Exception set already by PyUnicode_AsEncodedString */ return -1; } - kv = strdup(PyBytes_AS_STRING(temp_bytes)); + kv = PyBytes_AsString(temp_bytes); + if (kv == 0) { + /* Exception set already by PyBytes_AsString */ + return -1; + } + kv = strdup(kv); + if (kv == 0) { + PyErr_SetString(PyExc_MemoryError, "Not enough memory"); + } Py_DECREF(temp_bytes); if (!strcasecmp(kv, "pos")) { igraphmodule_PyObject_to_enum(value, eigen_which_position_tt, @@ -779,9 +787,8 @@ int igraphmodule_PyObject_to_igraph_t(PyObject *o, igraph_t **result) { if (o == Py_None) return 0; - if (!PyObject_TypeCheck(o, &igraphmodule_GraphType)) { - PyErr_Format(PyExc_TypeError, - "expected graph object, got %s", o->ob_type->tp_name); + if (!PyObject_TypeCheck(o, igraphmodule_GraphType)) { + PyErr_Format(PyExc_TypeError, "expected graph object, got %R", Py_TYPE(o)); return 1; } @@ -872,31 +879,31 @@ int igraphmodule_PyObject_to_integer_t(PyObject *object, igraph_integer_t *v) { * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_real_t(PyObject *object, igraph_real_t *v) { -#ifdef PYPY_VERSION - /* PyFloatObject is not defined in pypy, but PyFloat_AS_DOUBLE() is - * supported on PyObject: /pypy/module/cpyext/floatobject.py. Also, - * don't worry, the typedef is local to this function. */ - typedef PyObject PyFloatObject; -#endif /* PYPY_VERSION */ + igraph_real_t value; if (object == NULL) { } else if (PyLong_Check(object)) { - *v = PyLong_AsDouble(object); - return 0; + value = PyLong_AsDouble(object); } else if (PyFloat_Check(object)) { - *v = PyFloat_AS_DOUBLE((PyFloatObject*)object); - return 0; + value = PyFloat_AsDouble(object); } else if (PyNumber_Check(object)) { PyObject *i = PyNumber_Float(object); if (i == NULL) { return 1; } - *v = PyFloat_AS_DOUBLE((PyFloatObject*)i); + value = PyFloat_AsDouble(i); Py_DECREF(i); + } else { + PyErr_BadArgument(); + return 1; + } + + if (PyErr_Occurred()) { + return 1; + } else { + *v = value; return 0; } - PyErr_BadArgument(); - return 1; } /** @@ -1346,7 +1353,7 @@ PyObject* igraphmodule_vector_bool_t_to_PyList(const igraph_vector_bool_t *v) { for (i = 0; i < n; i++) { item = VECTOR(*v)[i] ? Py_True : Py_False; Py_INCREF(item); - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -1379,7 +1386,7 @@ PyObject* igraphmodule_vector_t_to_PyList(const igraph_vector_t *v, igraphmodule Py_DECREF(list); return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -1412,7 +1419,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v) { Py_DECREF(list); return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -1446,7 +1453,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList_with_nan(const igraph_vector_int_t for (i = 0; i < n; i++) { val = VECTOR(*v)[i]; if (val == nanvalue) { - item = Py_BuildValue("d", NAN); + item = PyFloat_FromDouble(NAN); } else { item = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[i]); } @@ -1454,7 +1461,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList_with_nan(const igraph_vector_int_t Py_DECREF(list); return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -1490,7 +1497,7 @@ PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v, igraphmodul return NULL; } - PyTuple_SET_ITEM(tuple, i, item); + PyTuple_SetItem(tuple, i, item); /* will not fail */ } return tuple; @@ -1523,7 +1530,7 @@ PyObject* igraphmodule_vector_int_t_to_PyTuple(const igraph_vector_int_t *v) { Py_DECREF(tuple); return NULL; } - PyTuple_SET_ITEM(tuple, i, item); + PyTuple_SetItem(tuple, i, item); /* will not fail */ } return tuple; @@ -1579,7 +1586,7 @@ PyObject* igraphmodule_vector_int_t_to_PyList_pairs(const igraph_vector_int_t *v Py_DECREF(second); first = second = 0; - PyList_SET_ITEM(list, i, pair); + PyList_SetItem(list, i, pair); /* will not fail */ } return list; @@ -1609,8 +1616,7 @@ int igraphmodule_PyObject_to_edgelist( PyObject *list, igraph_vector_int_t *v, igraph_t *graph, igraph_bool_t* list_is_owned ) { - PyObject *item, *i1, *i2, *it; - Py_buffer *buffer; + PyObject *item, *i1, *i2, *it, *expected; int ok; igraph_integer_t idx1=0, idx2=0; @@ -1626,35 +1632,75 @@ int igraphmodule_PyObject_to_edgelist( * way items are laid out in an igraph_vector_int_t, and that's an implementation * detail that we don't want to commit ourselves to */ if (PyMemoryView_Check(list)) { - buffer = PyMemoryView_GET_BUFFER(list); - - if (buffer->itemsize != sizeof(igraph_integer_t)) { + item = PyObject_GetAttrString(list, "itemsize"); + expected = PyLong_FromSize_t(sizeof(igraph_integer_t)); + ok = item && PyObject_RichCompareBool(item, expected, Py_EQ); + Py_XDECREF(expected); + Py_XDECREF(item); + if (!ok) { PyErr_SetString( PyExc_TypeError, "item size of buffer must match the size of igraph_integer_t" ); return 1; } - if (buffer->ndim != 2) { + item = PyObject_GetAttrString(list, "ndim"); + expected = PyLong_FromSize_t(2); + ok = item && PyObject_RichCompareBool(item, expected, Py_EQ); + Py_XDECREF(expected); + Py_XDECREF(item); + if (!ok) { PyErr_SetString(PyExc_TypeError, "edge list buffers must be two-dimensional"); return 1; } - if (buffer->shape[1] != 2) { + item = PyObject_GetAttrString(list, "shape"); + it = item && PySequence_Check(item) ? PySequence_GetItem(item, 1) : 0; + expected = PyLong_FromSize_t(2); + ok = it && PyObject_RichCompareBool(it, expected, Py_EQ); + Py_XDECREF(expected); + Py_XDECREF(item); + Py_XDECREF(it); + if (!ok) { PyErr_SetString(PyExc_TypeError, "edge list buffers must have two columns"); return 1; } - if (buffer->strides[0] != 2 * buffer->itemsize || - buffer->strides[1] != buffer->itemsize) { + item = PyObject_GetAttrString(list, "c_contiguous"); + ok = item == Py_True; + Py_XDECREF(item); + if (!ok) { PyErr_SetString(PyExc_TypeError, "edge list buffers must be contiguous"); return 1; } - igraph_vector_int_view(v, buffer->buf, buffer->len / buffer->itemsize); + /* If we are allowed to use the entire Python API, we can extract the buffer + * from the memoryview here and return a _view_ into the buffer so we can + * avoid copying. However, if we need to use the limited Python API, we + * cannot get access to the buffer so we need to convert the memoryview + * into a list first, and then cast that list into a _real_ igraph vector. + */ + { +#ifdef PY_IGRAPH_ALLOW_ENTIRE_PYTHON_API + Py_buffer *buffer = PyMemoryView_GET_BUFFER(item); + igraph_vector_int_view(v, buffer->buf, buffer->len / buffer->itemsize); + + if (list_is_owned) { + *list_is_owned = 0; + } +#else + PyObject *unfolded_list = PyObject_CallMethod(list, "tolist", 0); + if (!unfolded_list) { + return 1; + } + + if (igraphmodule_PyObject_to_edgelist(unfolded_list, v, graph, list_is_owned)) { + Py_DECREF(unfolded_list); + return 1; + } - if (list_is_owned) { - *list_is_owned = 0; + Py_DECREF(unfolded_list); +#endif } return 0; @@ -1673,14 +1719,10 @@ int igraphmodule_PyObject_to_edgelist( ok = 1; if (!PySequence_Check(item) || PySequence_Size(item) != 2) { PyErr_SetString(PyExc_TypeError, "iterable must return pairs of integers or strings"); - ok=0; + ok = 0; } else { - i1 = PySequence_ITEM(item, 0); - if (i1 == 0) { - i2 = 0; - } else { - i2 = PySequence_ITEM(item, 1); - } + i1 = PySequence_GetItem(item, 0); + i2 = i1 ? PySequence_GetItem(item, 1) : 0; ok = (i1 != 0 && i2 != 0); ok = ok && !igraphmodule_PyObject_to_vid(i1, &idx1, graph); ok = ok && !igraphmodule_PyObject_to_vid(i2, &idx2, graph); @@ -2100,7 +2142,7 @@ PyObject* igraphmodule_vector_int_t_pair_to_PyList(const igraph_vector_int_t *v1 Py_DECREF(second); first = second = 0; - PyList_SET_ITEM(list, i, pair); + PyList_SetItem(list, i, pair); /* will not fail */ } return list; @@ -2148,10 +2190,10 @@ PyObject* igraphmodule_matrix_t_to_PyList(const igraph_matrix_t *m, return NULL; } - PyList_SET_ITEM(row, j, item); + PyList_SetItem(row, j, item); /* will not fail */ } - PyList_SET_ITEM(list, i, row); + PyList_SetItem(list, i, row); /* will not fail */ } // return the list @@ -2198,10 +2240,10 @@ PyObject* igraphmodule_matrix_int_t_to_PyList(const igraph_matrix_int_t *m) { return NULL; } - PyList_SET_ITEM(row, j, item); + PyList_SetItem(row, j, item); /* will not fail */ } - PyList_SET_ITEM(list, i, row); + PyList_SetItem(list, i, row); /* will not fail */ } // return the list @@ -2236,7 +2278,7 @@ PyObject* igraphmodule_vector_ptr_t_to_PyList(const igraph_vector_ptr_t *v, Py_DECREF(list); return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -2269,7 +2311,7 @@ PyObject* igraphmodule_vector_int_ptr_t_to_PyList(const igraph_vector_ptr_t *v) Py_DECREF(list); return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } return list; @@ -2599,7 +2641,7 @@ PyObject* igraphmodule_strvector_t_to_PyList(igraph_strvector_t *v) { return NULL; } - PyList_SET_ITEM(list, i, item); + PyList_SetItem(list, i, item); /* will not fail */ } /* return the list */ @@ -2688,7 +2730,7 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(PyObject *it, PyObject *t; while ((t=PyIter_Next(it))) { - if (!PyObject_TypeCheck(t, &igraphmodule_GraphType)) { + if (!PyObject_TypeCheck(t, igraphmodule_GraphType)) { PyErr_SetString(PyExc_TypeError, "iterable argument must contain graphs"); Py_DECREF(t); return 1; @@ -2718,8 +2760,8 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, PyObject *t; int first = 1; - while ((t=PyIter_Next(it))) { - if (!PyObject_TypeCheck(t, &igraphmodule_GraphType)) { + while ((t = PyIter_Next(it))) { + if (!PyObject_TypeCheck(t, igraphmodule_GraphType)) { PyErr_SetString(PyExc_TypeError, "iterable argument must contain graphs"); Py_DECREF(t); return 1; diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 4f0bcdbc9..226496224 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -20,8 +20,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "convert.h" #include "common.h" #include "dfsiter.h" diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 5120456a5..fb8006f34 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -22,8 +22,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "attributes.h" #include "convert.h" #include "edgeobject.h" diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index fbb9c6703..4fc48684f 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -22,8 +22,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "attributes.h" #include "common.h" #include "convert.h" @@ -103,7 +101,7 @@ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, PyObject *args, igraph_es_t es; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, - &igraphmodule_GraphType, &g, &esobj)) { + igraphmodule_GraphType, &g, &esobj)) { return -1; } diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index c1c361181..3dc212f20 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -36,7 +36,7 @@ #include "vertexseqobject.h" #include -PyTypeObject igraphmodule_GraphType; +PyTypeObject* igraphmodule_GraphType; #define CREATE_GRAPH_FROM_TYPE(py_graph, c_graph, py_type) { \ py_graph = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( \ @@ -93,6 +93,8 @@ int igraphmodule_Graph_traverse(igraphmodule_GraphObject * self, } } + Py_VISIT(Py_TYPE(self)); + return 0; } @@ -104,9 +106,12 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) { PyObject *r; + RC_DEALLOC("Graph", self); + /* Clear weak references */ - if (self->weakreflist != NULL) + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); + } igraph_destroy(&self->g); @@ -119,9 +124,7 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) igraphmodule_Graph_clear(self); - RC_DEALLOC("Graph", self); - - Py_TYPE(self)->tp_free((PyObject*)self); + PY_FREE_AND_DECREF_TYPE(self); } /** @@ -136,7 +139,6 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) * Throws \c AssertionError in Python if \c vcount is less than or equal to zero. * \return the new \c igraph.Graph object or NULL if an error occurred. * - * \sa igraphmodule_Graph_new * \sa igraph_empty * \sa igraph_create */ @@ -231,7 +233,7 @@ PyObject* igraphmodule_Graph_subclass_from_igraph_t( PyObject* args; PyObject* kwds; - if (!PyType_IsSubtype(type, &igraphmodule_GraphType)) { + if (!PyType_IsSubtype(type, igraphmodule_GraphType)) { PyErr_SetString(PyExc_TypeError, "igraph._igraph.GraphBase expected"); return 0; } @@ -284,7 +286,7 @@ PyObject* igraphmodule_Graph_subclass_from_igraph_t( */ PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph) { return igraphmodule_Graph_subclass_from_igraph_t( - &igraphmodule_GraphType, graph + igraphmodule_GraphType, graph ); } @@ -4511,8 +4513,15 @@ PyObject *igraphmodule_Graph_decompose(igraphmodule_GraphObject * self, for (i = 0; i < n; i++) { g = (igraph_t *) VECTOR(components)[i]; CREATE_GRAPH(o, *g); - PyList_SET_ITEM(list, i, (PyObject *) o); - /* reference has been transferred by PyList_SET_ITEM, no need to DECREF + + if (PyList_SetItem(list, i, (PyObject *) o)) { + Py_DECREF(o); + Py_DECREF(list); + igraph_vector_ptr_destroy(&components); + return 0; + } + + /* reference has been transferred by PyList_SetItem, no need to DECREF. * * we mustn't call igraph_destroy here, because it would free the vertices * and the edges as well, but we need them in o->g. So just call free */ @@ -4937,12 +4946,12 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * for (i = 0; i < no_of_target_nodes; i++) { item = igraphmodule_vector_int_t_to_PyList(&res[i]); if (!item || PyList_SetItem(list, i, item)) { - if (item) { - Py_DECREF(item); + for (j = 0; j < no_of_target_nodes; j++) { + igraph_vector_int_destroy(&res[j]); } - Py_DECREF(list); - for (j = 0; j < no_of_target_nodes; j++) igraph_vector_int_destroy(&res[j]); free(res); + Py_XDECREF(item); + Py_DECREF(list); return NULL; } } @@ -8693,7 +8702,7 @@ PyObject *igraphmodule_Graph_isomorphic(igraphmodule_GraphObject * self, static char *kwlist[] = { "other", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", kwlist, - &igraphmodule_GraphType, &o)) + igraphmodule_GraphType, &o)) return NULL; if (o == Py_None) other = self; else other = (igraphmodule_GraphObject *) o; @@ -8732,7 +8741,7 @@ PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, "return_mapping_21", "sh1", "sh2", "color1", "color2", NULL }; /* TODO: convert igraph_bliss_info_t when needed */ if (!PyArg_ParseTupleAndKeywords - (args, kwds, "|O!OOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "|O!OOOOOO", kwlist, igraphmodule_GraphType, &o, &return1, &return2, &sho1, &sho2, &color1_o, &color2_o)) return NULL; if (igraphmodule_PyObject_to_bliss_sh_t(sho1, &sh1)) return NULL; @@ -8929,7 +8938,7 @@ PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "|O!OOOOOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "|O!OOOOOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &return1, &return2, &callback_fn, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9064,7 +9073,7 @@ PyObject *igraphmodule_Graph_count_isomorphisms_vf2(igraphmodule_GraphObject *se "node_compat_fn", "edge_compat_fn", NULL }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "|O!OOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "|O!OOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9157,7 +9166,7 @@ PyObject *igraphmodule_Graph_get_isomorphisms_vf2(igraphmodule_GraphObject *self "edge_color1", "edge_color2", "node_compat_fn", "edge_compat_fn", NULL }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "|O!OOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "|O!OOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9267,7 +9276,7 @@ PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, NULL }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "O!|OOOOOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "O!|OOOOOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &return1, &return2, &callback_fn, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9404,7 +9413,7 @@ PyObject *igraphmodule_Graph_count_subisomorphisms_vf2(igraphmodule_GraphObject "edge_color2", "node_compat_fn", "edge_compat_fn", NULL }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "O!|OOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "O!|OOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9494,7 +9503,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_vf2(igraphmodule_GraphObject *s "edge_color2", "node_compat_fn", "edge_compat_fn", NULL }; if (!PyArg_ParseTupleAndKeywords - (args, kwds, "O!|OOOOOO", kwlist, &igraphmodule_GraphType, &o, + (args, kwds, "O!|OOOOOO", kwlist, igraphmodule_GraphType, &o, &color1_o, &color2_o, &edge_color1_o, &edge_color2_o, &node_compat_fn, &edge_compat_fn)) return NULL; @@ -9590,7 +9599,7 @@ PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, "return_mapping", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OOfO", kwlist, - &igraphmodule_GraphType, &o, &domains_o, &induced, + igraphmodule_GraphType, &o, &domains_o, &induced, &time_limit, &return_mapping)) return NULL; @@ -9656,7 +9665,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_lad( static char *kwlist[] = { "pattern", "domains", "induced", "time_limit", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OOf", kwlist, - &igraphmodule_GraphType, &o, &domains_o, &induced, &time_limit)) + igraphmodule_GraphType, &o, &domains_o, &induced, &time_limit)) return NULL; other=(igraphmodule_GraphObject*)o; @@ -9720,14 +9729,21 @@ PyObject *igraphmodule_Graph_mp_subscript(igraphmodule_GraphObject * self, if (PyTuple_Check(s) && PyTuple_Size(s) >= 2) { /* Adjacency matrix representation */ - PyObject *ri = PyTuple_GET_ITEM(s, 0); - PyObject *ci = PyTuple_GET_ITEM(s, 1); + PyObject *ri = PyTuple_GetItem(s, 0); + PyObject *ci = PyTuple_GetItem(s, 1); PyObject *attr; + if (ri == 0 || ci == 0) { + return 0; + } + if (PyTuple_Size(s) == 2) { attr = 0; } else if (PyTuple_Size(s) == 3) { - attr = PyTuple_GET_ITEM(s, 2); + attr = PyTuple_GetItem(s, 2); + if (attr == 0) { + return 0; + } } else { PyErr_SetString(PyExc_TypeError, "adjacency matrix indexing must use at most three arguments"); return 0; @@ -9773,13 +9789,20 @@ int igraphmodule_Graph_mp_assign_subscript(igraphmodule_GraphObject * self, return -1; } - ri = PyTuple_GET_ITEM(k, 0); - ci = PyTuple_GET_ITEM(k, 1); + ri = PyTuple_GetItem(k, 0); + ci = PyTuple_GetItem(k, 1); + + if (ri == 0 || ci == 0) { + return -1; + } if (PyTuple_Size(k) == 2) { attr = 0; } else if (PyTuple_Size(k) == 3) { - attr = PyTuple_GET_ITEM(k, 2); + attr = PyTuple_GetItem(k, 2); + if (attr == 0) { + return -1; + } } else { PyErr_SetString(PyExc_TypeError, "adjacency matrix indexing must use at most three arguments"); return 0; @@ -9836,7 +9859,7 @@ PyObject *igraphmodule_Graph_difference(igraphmodule_GraphObject * self, igraphmodule_GraphObject *o, *result; igraph_t g; - if (!PyObject_TypeCheck(other, &igraphmodule_GraphType)) { + if (!PyObject_TypeCheck(other, igraphmodule_GraphType)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -9911,7 +9934,7 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, igraphmodule_GraphObject *o, *result; igraph_t g; - if (!PyObject_TypeCheck(other, &igraphmodule_GraphType)) { + if (!PyObject_TypeCheck(other, igraphmodule_GraphType)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -10955,15 +10978,14 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -11000,15 +11022,14 @@ PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -11105,15 +11126,14 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -11196,15 +11216,14 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -11242,15 +11261,14 @@ PyObject for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -11289,15 +11307,14 @@ PyObject for (i = 0; i < n; i++) { igraph_vector_int_t *vec = (igraph_vector_int_t *) VECTOR(result)[i]; item = igraphmodule_vector_int_t_to_PyTuple(vec); - if (!item) { + if (!item || PyList_SetItem(list, i, item)) { for (j = i; j < n; j++) { igraph_vector_int_destroy((igraph_vector_int_t *) VECTOR(result)[j]); } igraph_vector_ptr_destroy_all(&result); + Py_XDECREF(item); Py_DECREF(list); return NULL; - } else { - PyList_SET_ITEM(list, i, item); } igraph_vector_int_destroy(vec); } @@ -16312,111 +16329,52 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {NULL} }; -/** \ingroup python_interface_graph - * This structure is the collection of functions necessary to implement - * the graph as a mapping (i.e. to allow the retrieval and setting of - * igraph attributes in Python as if it were of a Python mapping type) - */ -PyMappingMethods igraphmodule_Graph_as_mapping = { - /* __len__ function intentionally left unimplemented */ - 0, - /* returns an attribute by name or returns part of the adjacency matrix */ - (binaryfunc) igraphmodule_Graph_mp_subscript, - /* sets an attribute by name or sets part of the adjacency matrix */ - (objobjargproc) igraphmodule_Graph_mp_assign_subscript -}; - -/** \ingroup python_interface - * \brief Collection of methods to allow numeric operators to be used on the graph +/** + * \ingroup python_interface_graph + * Member table for the \c igraph._igraph.GraphBase object */ -PyNumberMethods igraphmodule_Graph_as_number = { - 0, /* nb_add */ - 0, /*nb_subtract */ - 0, /*nb_multiply */ - 0, /*nb_remainder */ - 0, /*nb_divmod */ - 0, /*nb_power */ - 0, /*nb_negative */ - 0, /*nb_positive */ - 0, /*nb_absolute */ - 0, /*nb_nonzero (2.x) / nb_bool (3.x) */ - (unaryfunc) igraphmodule_Graph_complementer_op, /*nb_invert */ - 0, /*nb_lshift */ - 0, /*nb_rshift */ - 0, /*nb_and */ - 0, /*nb_xor */ - 0, /*nb_or */ - 0, /*nb_int */ - 0, /*nb_long (2.x) / nb_reserved (3.x)*/ - 0, /*nb_float */ - 0, /*nb_inplace_add */ - 0, /*nb_inplace_subtract */ - 0, /*nb_inplace_multiply */ - 0, /*nb_inplace_remainder */ - 0, /*nb_inplace_power */ - 0, /*nb_inplace_lshift */ - 0, /*nb_inplace_rshift */ - 0, /*nb_inplace_and */ - 0, /*nb_inplace_xor */ - 0, /*nb_inplace_or */ - 0, /*nb_floor_divide */ - 0, /*nb_true_divide */ - 0, /*nb_inplace_floor_divide */ - 0, /*nb_inplace_true_divide */ - 0, /*nb_index */ +PyMemberDef igraphmodule_Graph_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(igraphmodule_GraphObject, weakreflist), READONLY}, + { 0 } }; -/** \ingroup python_interface_graph - * Python type object referencing the methods Python calls when it performs various operations on an igraph (creating, printing and so on) - */ -PyTypeObject igraphmodule_GraphType = { - PyVarObject_HEAD_INIT(0, 0) - "igraph._igraph.GraphBase", /* tp_name */ - sizeof(igraphmodule_GraphObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) igraphmodule_Graph_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare (2.x) / tp_reserved (3.x) */ - 0, /* tp_repr */ - &igraphmodule_Graph_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - &igraphmodule_Graph_as_mapping, /* tp_as_mapping */ -#ifndef PYPY_VERSION - (hashfunc) PyObject_HashNotImplemented, /* tp_hash */ -#else - /* PyObject_HashNotImplemented raises an exception but it is not handled - * properly by PyPy so we don't use it */ - 0, /* tp_hash */ -#endif - 0, /* tp_call */ - (reprfunc) igraphmodule_Graph_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ +PyDoc_STRVAR( + igraphmodule_Graph_doc, "Low-level representation of a graph.\n\n" "Don't use it directly, use L{igraph.Graph} instead.\n\n" - "@deffield ref: Reference", /* tp_doc */ - (traverseproc) igraphmodule_Graph_traverse, /* tp_traverse */ - (inquiry) igraphmodule_Graph_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(igraphmodule_GraphObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - igraphmodule_Graph_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc) igraphmodule_Graph_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ -}; + "@deffield ref: Reference" /* tp_doc */ +); + +int igraphmodule_Graph_register_type() { + PyType_Slot slots[] = { + { Py_tp_init, igraphmodule_Graph_init }, + { Py_tp_dealloc, igraphmodule_Graph_dealloc }, + { Py_tp_members, igraphmodule_Graph_members }, + { Py_tp_methods, igraphmodule_Graph_methods }, + { Py_tp_hash, PyObject_HashNotImplemented }, + { Py_tp_traverse, igraphmodule_Graph_traverse }, + { Py_tp_clear, igraphmodule_Graph_clear }, + { Py_tp_str, igraphmodule_Graph_str }, + { Py_tp_doc, (void*) igraphmodule_Graph_doc }, + + { Py_nb_invert, igraphmodule_Graph_complementer_op }, + + { Py_mp_subscript, igraphmodule_Graph_mp_subscript }, + { Py_mp_ass_subscript, igraphmodule_Graph_mp_assign_subscript }, + + { 0 } + }; + + PyType_Spec spec = { + "igraph._igraph.GraphBase", /* name */ + sizeof(igraphmodule_GraphObject), /* basicsize */ + 0, /* itemsize */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* flags */ + slots, /* slots */ + }; + + igraphmodule_GraphType = (PyTypeObject*) PyType_FromSpec(&spec); + return igraphmodule_GraphType == 0; +} #undef CREATE_GRAPH diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 67521ad2c..164b875cb 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -29,7 +29,7 @@ #include "structmember.h" #include "common.h" -extern PyTypeObject igraphmodule_GraphType; +extern PyTypeObject* igraphmodule_GraphType; /** * \ingroup python_interface @@ -50,182 +50,13 @@ typedef struct PyObject* weakreflist; } igraphmodule_GraphObject; -PyObject* igraphmodule_Graph_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -int igraphmodule_Graph_clear(igraphmodule_GraphObject *self); -int igraphmodule_Graph_traverse(igraphmodule_GraphObject *self, visitproc visit, void *arg); -void igraphmodule_Graph_dealloc(igraphmodule_GraphObject* self); -int igraphmodule_Graph_init(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); +int igraphmodule_Graph_register_type(void); + PyObject* igraphmodule_Graph_subclass_from_igraph_t(PyTypeObject* type, igraph_t *graph); PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph); -PyObject* igraphmodule_Graph_str(igraphmodule_GraphObject *self); - -PyObject* igraphmodule_Graph_vcount(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_ecount(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_is_dag(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_is_directed(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_is_simple(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_add_vertices(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_delete_vertices(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_add_edges(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_delete_edges(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_degree(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_is_loop(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_neighbors(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_successors(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_predecessors(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_get_eid(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_Adjacency(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Asymmetric_Preference(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Atlas(PyTypeObject *type, PyObject *args); -PyObject* igraphmodule_Graph_Barabasi(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Degree_Sequence(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Establishment(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Erdos_Renyi(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Famous(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Forest_Fire(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Full_Citation(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Full(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_GRG(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Growing_Random(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Isoclass(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Lattice(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_LCF(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Preference(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Recent_Degree(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Ring(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_SBM(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Star(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Tree(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Tree_Game(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Watts_Strogatz(PyTypeObject *type, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_is_connected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_are_connected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_adjacency_spectral_embedding(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_articulation_points(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_average_path_length(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_betweenness(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_bibcoupling(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_closeness(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_clusters(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_cocitation(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_constraint(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_copy(igraphmodule_GraphObject *self); -PyObject* igraphmodule_Graph_decompose(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_density(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_diameter(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_eigen_adjacency(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_get_all_shortest_paths(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_maxdegree(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_pagerank(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_path_length_hist(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_reciprocity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_rewire(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_shortest_paths(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_spanning_tree(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_simplify(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_subcomponent(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_subgraph(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_transitivity_undirected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_transitivity_local_undirected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_scan1(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_layout_circle(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_sphere(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_random(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_random_3d(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_kamada_kawai_3d(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_fruchterman_reingold(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_fruchterman_reingold_3d(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_layout_reingold_tilford(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_get_edgelist(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_to_undirected(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_to_directed(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_laplacian(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph_Read_DIMACS(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_Edgelist(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_GML(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_Ncol(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_Lgl(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_Pajek(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_Read_GraphML(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_dot(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_edgelist(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_ncol(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_lgl(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_gml(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_write_graphml(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_isoclass(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_isomorphic(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_count_isomorphisms(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_get_isomorphisms(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_subisomorphic(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_count_subisomorphisms(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_get_subisomorphisms(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); - -Py_ssize_t igraphmodule_Graph_attribute_count(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_get_attribute(igraphmodule_GraphObject* self, PyObject* s); -int igraphmodule_Graph_set_attribute(igraphmodule_GraphObject* self, PyObject* k, PyObject* v); PyObject* igraphmodule_Graph_attributes(igraphmodule_GraphObject* self); PyObject* igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject* self); PyObject* igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_get_vertices(igraphmodule_GraphObject* self, void* closure); -PyObject* igraphmodule_Graph_get_edges(igraphmodule_GraphObject* self, void* closure); - -PyObject* igraphmodule_Graph_complementer(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_complementer_op(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_compose(igraphmodule_GraphObject* self, PyObject* other); -PyObject* igraphmodule_Graph_difference(igraphmodule_GraphObject* self, PyObject* other); -PyObject* igraphmodule_Graph_disjoint_union(igraphmodule_GraphObject* self, PyObject* other); - -PyObject* igraphmodule_Graph_bfs(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_bfsiter(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); - -PyObject* igraphmodule_Graph_maxflow(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_mincut(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_mincut_value(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); - -PyObject* igraphmodule_Graph_cliques(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_clique_number(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_independent_sets(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds); -PyObject* igraphmodule_Graph_maximal_independent_sets(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_largest_independent_sets(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_independence_number(igraphmodule_GraphObject* self); - -PyObject* igraphmodule_Graph_community_edge_betweenness(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_fastgreedy(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject *igraphmodule_Graph_community_infomap(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_label_propagation(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_leading_eigenvector(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject *igraphmodule_Graph_community_multilevel(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject *igraphmodule_Graph_community_optimal_modularity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_spinglass(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_modularity(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph_leiden(igraphmodule_GraphObject* self, PyObject *args, PyObject *kwds); - -PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - -PyObject* igraphmodule_Graph___graph_as_cobject__(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); -PyObject* igraphmodule_Graph___register_destructor__(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds); - #endif diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index d4dfa1e7d..7725b1622 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -843,13 +843,12 @@ PyObject* PyInit__igraph(void) igraphmodule_DFSIter_register_type() || igraphmodule_Edge_register_type() || igraphmodule_EdgeSeq_register_type() || + igraphmodule_Graph_register_type() || igraphmodule_Vertex_register_type() || igraphmodule_VertexSeq_register_type() ) { INITERROR; } - if (PyType_Ready(&igraphmodule_GraphType) < 0) - INITERROR; /* Initialize the core module */ m = PyModule_Create(&moduledef); @@ -860,7 +859,7 @@ PyObject* PyInit__igraph(void) igraphmodule_init_rng(m); /* Add the types to the core module */ - PyModule_AddObject(m, "GraphBase", (PyObject*)&igraphmodule_GraphType); + PyModule_AddObject(m, "GraphBase", (PyObject*)igraphmodule_GraphType); PyModule_AddObject(m, "BFSIter", (PyObject*)igraphmodule_BFSIterType); PyModule_AddObject(m, "DFSIter", (PyObject*)igraphmodule_DFSIterType); PyModule_AddObject(m, "ARPACKOptions", (PyObject*)igraphmodule_ARPACKOptionsType); diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 0ad5a0293..52be31514 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -154,16 +154,26 @@ PyObject *igraphmodule__union(PyObject *self, Py_ssize_t no_of_edges = igraph_ecount(VECTOR(gs)[i]); igraph_vector_int_t *map = VECTOR(edgemaps)[i]; PyObject *emi = PyList_New(no_of_edges); - for (j = 0; j < no_of_edges; j++) { - PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); - if (!dest) { - Py_DECREF(emi); - Py_DECREF(em_list); - return NULL; + if (emi) { + for (j = 0; j < no_of_edges; j++) { + PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); + if (!dest || PyList_SetItem(emi, j, dest)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + Py_XDECREF(dest); + Py_DECREF(emi); + Py_DECREF(em_list); + return NULL; + } } - PyList_SET_ITEM(emi, j, dest); } - PyList_SET_ITEM(em_list, i, emi); + if (!emi || PyList_SetItem(em_list, i, emi)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + Py_XDECREF(emi); + Py_DECREF(em_list); + return NULL; + } } igraph_vector_ptr_destroy(&edgemaps); } else { @@ -266,16 +276,26 @@ PyObject *igraphmodule__intersection(PyObject *self, Py_ssize_t no_of_edges = igraph_ecount(VECTOR(gs)[i]); igraph_vector_int_t *map = VECTOR(edgemaps)[i]; PyObject *emi = PyList_New(no_of_edges); - for (j = 0; j < no_of_edges; j++) { - PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); - if (!dest) { - Py_DECREF(emi); - Py_DECREF(em_list); - return NULL; + if (emi) { + for (j = 0; j < no_of_edges; j++) { + PyObject *dest = igraphmodule_integer_t_to_PyObject(VECTOR(*map)[j]); + if (!dest || PyList_SetItem(emi, j, dest)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + Py_XDECREF(dest); + Py_DECREF(emi); + Py_DECREF(em_list); + return NULL; + } } - PyList_SET_ITEM(emi, j, dest); } - PyList_SET_ITEM(em_list, i, emi); + if (!emi || PyList_SetItem(em_list, i, emi)) { + igraph_vector_ptr_destroy(&gs); + igraph_vector_ptr_destroy(&edgemaps); + Py_XDECREF(emi); + Py_DECREF(em_list); + return NULL; + } } igraph_vector_ptr_destroy(&edgemaps); diff --git a/src/_igraph/preamble.h b/src/_igraph/preamble.h index 218b304ca..fa427ccac 100644 --- a/src/_igraph/preamble.h +++ b/src/_igraph/preamble.h @@ -23,6 +23,10 @@ #ifndef PYTHON_IGRAPH_PREAMBLE_H #define PYTHON_IGRAPH_PREAMBLE_H +#ifndef PY_IGRAPH_ALLOW_ENTIRE_PYTHON_API +# define Py_LIMITED_API 0x03060100 +#endif + #define PY_SSIZE_T_CLEAN #include diff --git a/src/_igraph/pyhelpers.c b/src/_igraph/pyhelpers.c index a51b60ca7..5cf0e075e 100644 --- a/src/_igraph/pyhelpers.c +++ b/src/_igraph/pyhelpers.c @@ -66,12 +66,17 @@ PyObject* igraphmodule_PyList_NewFill(Py_ssize_t len, PyObject* item) { Py_ssize_t i; PyObject* result = PyList_New(len); - if (result == 0) + if (result == 0) { return 0; + } for (i = 0; i < len; i++) { Py_INCREF(item); - PyList_SET_ITEM(result, i, item); /* reference to item stolen */ + if (PyList_SetItem(result, i, item)) { + Py_DECREF(item); + Py_DECREF(result); + return 0; + } } return result; @@ -161,14 +166,21 @@ char* PyUnicode_CopyAsString(PyObject* string) { bytes = PyUnicode_AsUTF8String(string); } - if (bytes == 0) + if (bytes == 0) { + return 0; + } + + result = PyBytes_AsString(bytes); + if (result == 0) { + Py_DECREF(bytes); return 0; - - result = strdup(PyBytes_AS_STRING(bytes)); + } Py_DECREF(bytes); - if (result == 0) + result = strdup(result); + if (result == 0) { PyErr_NoMemory(); + } return result; } diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index a51578fdc..df8897cb4 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -22,8 +22,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "attributes.h" #include "convert.h" #include "edgeobject.h" diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 02160beb5..2862d3e3d 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -22,8 +22,6 @@ */ -#define Py_LIMITED_API 0x03060100 - #include "attributes.h" #include "common.h" #include "convert.h" @@ -100,7 +98,7 @@ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, - &igraphmodule_GraphType, &g, &vsobj)) + igraphmodule_GraphType, &g, &vsobj)) return -1; if (vsobj == Py_None) { diff --git a/src/igraph/utils.py b/src/igraph/utils.py index e1bce6541..d195a6263 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -62,10 +62,6 @@ def numpy_to_contiguous_memoryview(obj): from numpy import int32, int64, require from igraph._igraph import INTEGER_SIZE - # TODO: we used to export to double, which is only dependent on the - # architecture. Now with integers and a compile-time flag, we have - # to figure out what is the integer bitness of the underlying C core. - # Think of how to do that, for now default to 64 bit ints! if INTEGER_SIZE == 64: dtype = int64 elif INTEGER_SIZE == 32: diff --git a/tests/test_basic.py b/tests/test_basic.py index e21e67905..db7146d30 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,10 +1,15 @@ +import gc +import sys import unittest import warnings +from contextlib import contextmanager from functools import partial from igraph import ( ALL, + Edge, + EdgeSeq, Graph, IN, InternalError, @@ -12,7 +17,10 @@ is_graphical, is_graphical_degree_sequence, Matrix, + Vertex, + VertexSeq ) +from igraph._igraph import EdgeSeq as _EdgeSeq, VertexSeq as _VertexSeq try: import numpy as np @@ -721,7 +729,7 @@ def __init__(self, *args, **kwds): self.init_called = True def __new__(cls, *args, **kwds): - result = Graph.__new__(cls, *args, **kwds) + result = Graph.__new__(cls) result.new_called = True return result @@ -759,6 +767,58 @@ def testCallingClassMethodInSuperclass(self): self.assertTrue(getattr(g, "adjacency_called", True)) +@contextmanager +def assert_reference_not_leaked(case, *args): + gc.collect() + refs_before = [sys.getrefcount(obj) for obj in args] + try: + yield + finally: + gc.collect() + refs_after = [sys.getrefcount(obj) for obj in args] + case.assertListEqual(refs_before, refs_after) + + +class ReferenceCountTests(unittest.TestCase): + def testEdgeReferenceCounting(self): + with assert_reference_not_leaked(self, Edge, EdgeSeq, _EdgeSeq): + g = Graph.Tree(3, 2) + edge = g.es[1] + del edge, g + + def testEdgeSeqReferenceCounting(self): + with assert_reference_not_leaked(self, Edge, EdgeSeq, _EdgeSeq): + g = Graph.Tree(3, 2) + es = g.es + es2 = EdgeSeq(g) + del es, es2, g + + def testGraphReferenceCounting(self): + with assert_reference_not_leaked(self, Graph, InheritedGraph): + g = Graph.Tree(3, 2) + self.assertTrue(gc.is_tracked(g)) + del g + + def testInheritedGraphReferenceCounting(self): + with assert_reference_not_leaked(self, Graph, InheritedGraph): + g = InheritedGraph.Tree(3, 2) + self.assertTrue(gc.is_tracked(g)) + del g + + def testVertexReferenceCounting(self): + with assert_reference_not_leaked(self, Vertex, VertexSeq, _VertexSeq): + g = Graph.Tree(3, 2) + vertex = g.vs[2] + del vertex, g + + def testVertexSeqReferenceCounting(self): + with assert_reference_not_leaked(self, Vertex, VertexSeq, _VertexSeq): + g = Graph.Tree(3, 2) + vs = g.vs + vs2 = VertexSeq(g) + del vs2, vs, g + + def suite(): basic_suite = unittest.makeSuite(BasicTests) datatype_suite = unittest.makeSuite(DatatypeTests) @@ -766,6 +826,7 @@ def suite(): graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) + refcount_suite = unittest.makeSuite(ReferenceCountTests) return unittest.TestSuite( [ basic_suite, @@ -774,6 +835,7 @@ def suite(): graph_tuple_list_suite, degree_sequence_suite, inheritance_suite, + refcount_suite ] ) From a53fc18a1b61834da5b7af169c5aef2d28958a77 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 14:58:47 +0200 Subject: [PATCH 0622/1892] chore: updated cibuildwheel to 2.1.1 --- .github/workflows/build.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d0354422..7fec758fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,6 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "cp27-* pp27-* cp35-*" jobs: build_wheels: @@ -26,7 +25,7 @@ jobs: python-version: '3.8' - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -50,7 +49,7 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +87,7 @@ jobs: brew install ninja autoconf automake libtool cmake - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_ARCHS_MACOS: "x86_64 arm64" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -145,7 +144,7 @@ jobs: shell: cmd - name: Build wheels - uses: joerick/cibuildwheel@v1.11.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From a2122bfd1f717fd5ec0aff7db77b60cf9e41226a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 15:28:01 +0200 Subject: [PATCH 0623/1892] ci: skip testing on Python 3.10 until NumPy / SciPy / Pandas publish wheels --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fec758fe..cf561c68e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,8 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" + # skip testing on Python 3.10 until NumPy/SciPy/Pandas publish wheels + CIBW_TEST_SKIP: "cp310-*" jobs: build_wheels: @@ -148,12 +150,12 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" + CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 - CIBW_TEST_COMMAND: "cd /d {project} && python -m unittest -vvv" - uses: actions/upload-artifact@v2 with: From eeec9887e0531febbecfa28fee69292b3d38a14f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 16:07:42 +0200 Subject: [PATCH 0624/1892] refactor: added __init__ implementation to Vertex and Edge --- src/_igraph/convert.c | 15 ++++++++---- src/_igraph/edgeobject.c | 45 +++++++++++++++++++++-------------- src/_igraph/edgeseqobject.c | 4 +--- src/_igraph/vertexobject.c | 45 +++++++++++++++++++++-------------- src/_igraph/vertexseqobject.c | 3 +-- 5 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index b790689bd..192ff0232 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2789,8 +2789,9 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph) { - if (o == Py_None || o == 0) { - *vid = 0; + if (o == 0) { + PyErr_SetString(PyExc_TypeError, "only numbers, strings or igraph.Vertex objects can be converted to vertex IDs"); + return 1; } else if (PyLong_Check(o)) { /* Single vertex ID */ if (igraphmodule_PyObject_to_integer_t(o, vid)) { @@ -3004,12 +3005,16 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g int retval; igraph_integer_t vid1, vid2; - if (o == Py_None || o == 0) { - *eid = 0; + if (!o) { + PyErr_SetString(PyExc_TypeError, + "only numbers, igraph.Edge objects or tuples of vertex IDs can be " + "converted to edge IDs"); + return 1; } else if (PyLong_Check(o)) { /* Single edge ID */ - if (igraphmodule_PyObject_to_integer_t(o, eid)) + if (igraphmodule_PyObject_to_integer_t(o, eid)) { return 1; + } } else if (igraphmodule_Edge_Check(o)) { /* Single edge ID from Edge object */ igraphmodule_EdgeObject *eo = (igraphmodule_EdgeObject*)o; diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index fb8006f34..3d97d61c0 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -99,27 +99,36 @@ int igraphmodule_Edge_Validate(PyObject* obj) { * (or they might even get invalidated). */ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { - igraphmodule_EdgeObject* self; - - self = (igraphmodule_EdgeObject*) PyType_GenericNew(igraphmodule_EdgeType, 0, 0); - - if (self) { - RC_ALLOC("Edge", self); - Py_INCREF(gref); - self->gref = gref; - self->idx = idx; - self->hash = -1; - } - - return (PyObject*)self; + return PyObject_CallFunction(igraphmodule_EdgeType, "On", gref, (Py_ssize_t) idx); } /** * \ingroup python_interface_edge - * \brief Clears the edge's subobject (before deallocation) + * \brief Initialize a new edge object for a given graph + * \return the initialized PyObject */ -static int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { - Py_CLEAR(self->gref); +static int igraphmodule_Edge_init(igraphmodule_EdgeObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { "graph", "eid", NULL }; + PyObject *g, *index_o = Py_None; + igraph_integer_t eid; + igraph_t *graph; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, + igraphmodule_GraphType, &g, &index_o)) { + return -1; + } + + graph = &((igraphmodule_GraphObject*)g)->g; + + if (igraphmodule_PyObject_to_eid(index_o, &eid, graph)) { + return -1; + } + + Py_INCREF(g); + self->gref = (igraphmodule_GraphObject*)g; + self->idx = eid; + self->hash = -1; + return 0; } @@ -129,7 +138,7 @@ static int igraphmodule_Edge_clear(igraphmodule_EdgeObject *self) { */ static void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { RC_DEALLOC("Edge", self); - igraphmodule_Edge_clear(self); + Py_CLEAR(self->gref); PY_FREE_AND_DECREF_TYPE(self); } @@ -717,8 +726,8 @@ PyDoc_STRVAR( int igraphmodule_Edge_register_type() { PyType_Slot slots[] = { + { Py_tp_init, igraphmodule_Edge_init }, { Py_tp_dealloc, igraphmodule_Edge_dealloc }, - { Py_tp_clear, igraphmodule_Edge_clear }, { Py_tp_hash, igraphmodule_Edge_hash }, { Py_tp_repr, igraphmodule_Edge_repr }, { Py_tp_richcompare, igraphmodule_Edge_richcompare }, diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 4fc48684f..bd94219d7 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -89,7 +89,6 @@ igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { return copy; } - /** * \ingroup python_interface_edgeseq * \brief Initialize a new edge sequence object for a given graph @@ -162,10 +161,9 @@ void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self) { if (self->gref) { igraph_es_destroy(&self->es); - Py_DECREF(self->gref); - self->gref=0; } + Py_CLEAR(self->gref); PY_FREE_AND_DECREF_TYPE(self); } diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index df8897cb4..50ee8034b 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -99,27 +99,36 @@ int igraphmodule_Vertex_Validate(PyObject* obj) { * (or they might even get invalidated). */ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { - igraphmodule_VertexObject* self; - - self = (igraphmodule_VertexObject*) PyType_GenericNew(igraphmodule_VertexType, 0, 0); - - if (self) { - RC_ALLOC("Vertex", self); - Py_INCREF(gref); - self->gref = gref; - self->idx = idx; - self->hash = -1; - } - - return (PyObject*)self; + return PyObject_CallFunction(igraphmodule_VertexType, "On", gref, (Py_ssize_t) idx); } /** * \ingroup python_interface_vertex - * \brief Clears the vertex's subobject (before deallocation) + * \brief Initialize a new vertex object for a given graph + * \return the initialized PyObject */ -static int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { - Py_CLEAR(self->gref); +static int igraphmodule_Vertex_init(igraphmodule_EdgeObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { "graph", "vid", NULL }; + PyObject *g, *index_o = Py_None; + igraph_integer_t vid; + igraph_t *graph; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, + igraphmodule_GraphType, &g, &index_o)) { + return -1; + } + + graph = &((igraphmodule_GraphObject*)g)->g; + + if (igraphmodule_PyObject_to_vid(index_o, &vid, graph)) { + return -1; + } + + Py_INCREF(g); + self->gref = (igraphmodule_GraphObject*)g; + self->idx = vid; + self->hash = -1; + return 0; } @@ -129,7 +138,7 @@ static int igraphmodule_Vertex_clear(igraphmodule_VertexObject *self) { */ static void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { RC_DEALLOC("Vertex", self); - igraphmodule_Vertex_clear(self); + Py_CLEAR(self->gref); PY_FREE_AND_DECREF_TYPE(self); } @@ -857,7 +866,7 @@ PyDoc_STRVAR( int igraphmodule_Vertex_register_type() { PyType_Slot slots[] = { - { Py_tp_clear, igraphmodule_Vertex_clear }, + { Py_tp_init, igraphmodule_Vertex_init }, { Py_tp_dealloc, igraphmodule_Vertex_dealloc }, { Py_tp_hash, igraphmodule_Vertex_hash }, { Py_tp_repr, igraphmodule_Vertex_repr }, diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 2862d3e3d..947b699f0 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -156,10 +156,9 @@ void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self) { if (self->gref) { igraph_vs_destroy(&self->vs); - Py_DECREF(self->gref); - self->gref=0; } + Py_CLEAR(self->gref); PY_FREE_AND_DECREF_TYPE(self); } From 0034011f6aa47ff9d05c6465d54796dca1001492 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 16:34:20 +0200 Subject: [PATCH 0625/1892] fix: worked around refcounting bug in Python <3.8 --- src/_igraph/arpackobject.c | 2 +- src/_igraph/bfsiter.c | 2 +- src/_igraph/dfsiter.c | 2 +- src/_igraph/edgeobject.c | 4 ++-- src/_igraph/edgeseqobject.c | 2 +- src/_igraph/graphobject.c | 2 +- src/_igraph/pyhelpers.h | 7 +++++-- src/_igraph/vertexobject.c | 4 ++-- src/_igraph/vertexseqobject.c | 2 +- 9 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 86d07f307..047dbba01 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -52,7 +52,7 @@ int igraphmodule_ARPACKOptions_init(igraphmodule_ARPACKOptionsObject *self, PyOb */ static void igraphmodule_ARPACKOptions_dealloc(igraphmodule_ARPACKOptionsObject* self) { RC_DEALLOC("ARPACKOptions", self); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_ARPACKOptionsType); } /** \ingroup python_interface_arpack diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index a250bbedd..03d5308e3 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -152,7 +152,7 @@ static void igraphmodule_BFSIter_dealloc(igraphmodule_BFSIterObject* self) { igraphmodule_BFSIter_clear(self); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_BFSIterType); } static PyObject* igraphmodule_BFSIter_iter(igraphmodule_BFSIterObject* self) { diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 226496224..12fb9a503 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -151,7 +151,7 @@ static int igraphmodule_DFSIter_clear(igraphmodule_DFSIterObject *self) { static void igraphmodule_DFSIter_dealloc(igraphmodule_DFSIterObject* self) { RC_DEALLOC("DFSIter", self); igraphmodule_DFSIter_clear(self); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_DFSIterType); } static PyObject* igraphmodule_DFSIter_iter(igraphmodule_DFSIterObject* self) { diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 3d97d61c0..56304434e 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -99,7 +99,7 @@ int igraphmodule_Edge_Validate(PyObject* obj) { * (or they might even get invalidated). */ PyObject* igraphmodule_Edge_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { - return PyObject_CallFunction(igraphmodule_EdgeType, "On", gref, (Py_ssize_t) idx); + return PyObject_CallFunction((PyObject*) igraphmodule_EdgeType, "On", gref, (Py_ssize_t) idx); } /** @@ -139,7 +139,7 @@ static int igraphmodule_Edge_init(igraphmodule_EdgeObject *self, PyObject *args, static void igraphmodule_Edge_dealloc(igraphmodule_EdgeObject* self) { RC_DEALLOC("Edge", self); Py_CLEAR(self->gref); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_EdgeType); } /** \ingroup python_interface_edge diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index bd94219d7..64f3f0372 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -164,7 +164,7 @@ void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self) { } Py_CLEAR(self->gref); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_EdgeSeqType); } /** diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3dc212f20..af80fa817 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -124,7 +124,7 @@ void igraphmodule_Graph_dealloc(igraphmodule_GraphObject * self) igraphmodule_Graph_clear(self); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_GraphType); } /** diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 56fd4d399..6189a34c8 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -50,15 +50,18 @@ char* PyUnicode_CopyAsString(PyObject* string); /* Calling Py_DECREF() on heap-allocated types in tp_dealloc was not needed * before Python 3.8 (see Python issue 35810) */ #if PY_VERSION_HEX >= 0x03080000 - #define PY_FREE_AND_DECREF_TYPE(obj) { \ + #define PY_FREE_AND_DECREF_TYPE(obj, base_type) { \ PyTypeObject* _tp = Py_TYPE(obj); \ ((freefunc)PyType_GetSlot(_tp, Py_tp_free))(obj); \ Py_DECREF(_tp); \ } #else - #define PY_FREE_AND_DECREF_TYPE(obj) { \ + #define PY_FREE_AND_DECREF_TYPE(obj, base_type) { \ PyTypeObject* _tp = Py_TYPE(obj); \ ((freefunc)PyType_GetSlot(_tp, Py_tp_free))(obj); \ + if (_tp == base_type) { \ + Py_DECREF(_tp); \ + } \ } #endif diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 50ee8034b..c1bd338a1 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -99,7 +99,7 @@ int igraphmodule_Vertex_Validate(PyObject* obj) { * (or they might even get invalidated). */ PyObject* igraphmodule_Vertex_New(igraphmodule_GraphObject *gref, igraph_integer_t idx) { - return PyObject_CallFunction(igraphmodule_VertexType, "On", gref, (Py_ssize_t) idx); + return PyObject_CallFunction((PyObject*) igraphmodule_VertexType, "On", gref, (Py_ssize_t) idx); } /** @@ -139,7 +139,7 @@ static int igraphmodule_Vertex_init(igraphmodule_EdgeObject *self, PyObject *arg static void igraphmodule_Vertex_dealloc(igraphmodule_VertexObject* self) { RC_DEALLOC("Vertex", self); Py_CLEAR(self->gref); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_VertexType); } /** \ingroup python_interface_vertex diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 947b699f0..819d18046 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -159,7 +159,7 @@ void igraphmodule_VertexSeq_dealloc(igraphmodule_VertexSeqObject* self) { } Py_CLEAR(self->gref); - PY_FREE_AND_DECREF_TYPE(self); + PY_FREE_AND_DECREF_TYPE(self, igraphmodule_VertexSeqType); } /** From fd549a6ea9e4e9680f269a66b99b6ed520846478 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 16:37:44 +0200 Subject: [PATCH 0626/1892] fix: tp_traverse() needs to visit Py_TYPE(self) only in Python >= 3.9 --- src/_igraph/bfsiter.c | 5 ++++- src/_igraph/dfsiter.c | 5 ++++- src/_igraph/graphobject.c | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index 03d5308e3..f4b384bdf 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -121,7 +121,10 @@ static int igraphmodule_BFSIter_traverse(igraphmodule_BFSIterObject *self, visitproc visit, void *arg) { RC_TRAVERSE("BFSIter", self); Py_VISIT(self->gref); - Py_VISIT(Py_TYPE(self)); /* needed because heap-allocated types are refcounted */ +#if PY_VERSION_HEX >= 0x03090000 + // This was not needed before Python 3.9 (Python issue 35810 and 40217) + Py_VISIT(Py_TYPE(self)); +#endif return 0; } diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index 12fb9a503..b3dd00cc9 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -122,7 +122,10 @@ static int igraphmodule_DFSIter_traverse(igraphmodule_DFSIterObject *self, visitproc visit, void *arg) { RC_TRAVERSE("DFSIter", self); Py_VISIT(self->gref); - Py_VISIT(Py_TYPE(self)); /* needed because heap-allocated types are refcounted */ +#if PY_VERSION_HEX >= 0x03090000 + // This was not needed before Python 3.9 (Python issue 35810 and 40217) + Py_VISIT(Py_TYPE(self)); +#endif return 0; } diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index af80fa817..429e183cd 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -93,7 +93,10 @@ int igraphmodule_Graph_traverse(igraphmodule_GraphObject * self, } } +#if PY_VERSION_HEX >= 0x03090000 + // This was not needed before Python 3.9 (Python issue 35810 and 40217) Py_VISIT(Py_TYPE(self)); +#endif return 0; } From 81048cd75fd220e12ab6da80356c2c27221cad6d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 17:24:18 +0200 Subject: [PATCH 0627/1892] test: refcount-related tests should not be run on PyPy --- tests/test_basic.py | 5 ++++- tests/test_cliques.py | 5 +---- tests/test_edgeseq.py | 5 +---- tests/test_foreign.py | 5 +---- tests/test_vertexseq.py | 5 +---- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index db7146d30..aed0677b5 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -22,6 +22,8 @@ ) from igraph._igraph import EdgeSeq as _EdgeSeq, VertexSeq as _VertexSeq +from .utils import is_pypy + try: import numpy as np except ImportError: @@ -826,7 +828,8 @@ def suite(): graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) - refcount_suite = unittest.makeSuite(ReferenceCountTests) + if not is_pypy: + refcount_suite = unittest.makeSuite(ReferenceCountTests) return unittest.TestSuite( [ basic_suite, diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 064363e5a..62017c17e 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -2,10 +2,7 @@ from igraph import * -try: - from .utils import temporary_file -except ImportError: - from utils import temporary_file +from .utils import temporary_file class CliqueTests(unittest.TestCase): diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index f1b451512..74667b758 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -4,10 +4,7 @@ from igraph import * -try: - from .utils import is_pypy -except ImportError: - from utils import is_pypy +from .utils import is_pypy try: import numpy as np diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 5d5243e4b..e86051b27 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -4,10 +4,7 @@ from igraph import Graph, InternalError -try: - from .utils import temporary_file -except ImportError: - from utils import temporary_file +from .utils import temporary_file try: import networkx as nx diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 89c9e8896..12adf1aa1 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -4,10 +4,7 @@ from igraph import * -try: - from .utils import is_pypy -except ImportError: - from utils import is_pypy +from .utils import is_pypy try: import numpy as np From 53b540e430e5d4f97e460e0c4110d458f9f4c574 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Sep 2021 17:45:33 +0200 Subject: [PATCH 0628/1892] test: pytest test discovery still discovered refcount tests on PyPy, this is now fixed --- tests/test_basic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index aed0677b5..340621966 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -781,6 +781,7 @@ def assert_reference_not_leaked(case, *args): case.assertListEqual(refs_before, refs_after) +@unittest.skipIf(is_pypy, "reference counts are not relevant for PyPy") class ReferenceCountTests(unittest.TestCase): def testEdgeReferenceCounting(self): with assert_reference_not_leaked(self, Edge, EdgeSeq, _EdgeSeq): @@ -828,8 +829,7 @@ def suite(): graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) - if not is_pypy: - refcount_suite = unittest.makeSuite(ReferenceCountTests) + refcount_suite = unittest.makeSuite(ReferenceCountTests) return unittest.TestSuite( [ basic_suite, From 7b14aaaedebb3c3071a268e50c835cc6919d4dc7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 15 Sep 2021 00:14:25 +1000 Subject: [PATCH 0629/1892] Revamping (yes!) the plotting interface: matplotlib and plotly (#425) * Initial works on vertex and edge drawers * Introduce more mpl switches across the library * Matrix drawing factories * Support palette plotting in mpl * Switch igraph.plot, works * Mark groups transitioning to general infra * Full switch to infra except labels * Move dendrogram plotting code into module * Move more Cairo stuff out of Dendrogram * Dendrogram plot in matplotlib * Edge labels (no alignment yet) * Rounded hull for clustering * Edge label alignment * Try to restructure the Plot class via composition * Testing infrastructure for matplotlib plots * Store baseline images properly, plotting tests work now in CLI * Despine matplotlib plot * Plotting works * More plotting tests * Fix plotting test skipping within unittest * Tests for mpl post-facto editing of vertices * Doc on new config option for matplotlib backend * Bugfix on vertex labels and improved tutorial * doc: the Configuration singleton can be accessed as ig.config * fix: make sure that the backend variable is one of the known backends * chore: format source code using black * fix: remove _checked_on_freetype_version decorator to get rid of dependency on pytest * chore: reformatted tests/drawing with black * test: use a fixed circle layout for the large clustering test; the default layout depends on the random seed a bit * refactor: renamed DefaultDendrogramDrawer to CairoDendrogramDrawer * refactor: keep DefaultDendrogramDrawer as an alias * doc: remove all references to Matplotlib from the documentation of CairoPlot * fix: fix plotting of Palette objects * chore: code formatting, remove unused import * fix: fix plotting with the Cairo backend so the "margin" argument takes effect properly * Support matplotlib plot for histogram * Remove matplotlib example/demo folder, will do a separate PR * remove bbox and palette args and deprecation warn for *args in draw * Small bugfix and typo * chore: nitpicking * fix: fix drawing of palettes in Cairo * refactor: started separating Cairo-related stuff into igraph.drawing.cairo [WIP] * refactor: remove default image viewer config setting and support for invoking an external image viewer automatically * fix: use ABCMeta and @abstractmethod annotations for abstract methods * refactor: moved TextDrawer and AbstractCairoDrawer to Cairo-specific module * refactor: DescartesCoordinateSystem is now in igraph.drawing.cairo * refactor: vertex drawers moved to Cairo or Matplotlib-specific submodules * refactor: edge drawers are now also in the correct (Cairo or Matplotlib) submodule * refactor: matrix drawers are now in the Matplotlib and Cairo submodules * chore: removed deprecated UbiGraphDrawer, updated changelog * refactor: graph drawers moved to Cairo or Matplotlib submodule * refactor: dendrogram drawers are now in the Matplotlib and Cairo submodules * refactor: polygon drawers are now in the Cairo and Matplotlib packages, respectively * Drawer factory * Forgot one file * Start supporting plotly * Empty __init__ file for plotly * More plotly code, perhaps could work * Typo in edge * more typos * Passes mpl tests locally * Passes basic tests for plotly * Passes all plotly tests (no control image) * Testing suite for plotly (first version) * Cairo unit tests * Cairo passes all tests * fix: make sure that result_images/cairo exists; also handle Path objects properly with cairocffi * fix: make sure that Cairo, Matplotlib and Plotly are all installed in the test env and fix find_open_image_png_function() for PIL * fix: use an easily diffable JSON representation for expected Plotly images * fix: move Matplotlib baseline images to their right places * fix: make sure that plot dependencies are installed when building wheels * fix: temporarily remove Cairo from CI tests; it requires additional deps in the CI env * fix: apparently Matplotlib tests also require pytest * Switch mpl tests to PDF and move other images around * variable not needed * Use png images * fix * Skip entire test module if missing mpl/plotly/cairo * Fix layout for plotly and investigate graph_objects import * Increase tolerance on mpl, fix layout on plotly * Plotly figure dict comparator with tolerance * Back to PDF (should work on i686) and install ghostscript on CI * Ugly custom converter lifted from mpl to enforce ghostscript as gs * Try encorcing manylinux2014 which should have ghostscript 9 * Fix layout in mpl tests * Revert to PNG, ghostscript conversion is unreliable across archs and old Python versions * Mysterious failure on numpy for pypy and OSX, trying switching to pytest * Try skipping mpl/numpy on pypy * chore: updated cibuildwheel to 2.1.1 * ci: skip testing on Python 3.10 until NumPy / SciPy / Pandas publish wheels * test: allow using older Matplotlib version because of Python 3.6 * test: don't install cairocffi in CI env because we don't have Cairo DLLs there * test: use pytest with PyPy as well * fix: don't require matplotlib >= 3.4 because that would exclude Python 3.6 users from using matplotlib [ci skip] Co-authored-by: Tamas Nepusz --- .github/workflows/build.yml | 13 +- .gitignore | 1 + CHANGELOG.md | 89 +- .../figures/tutorial_social_network_1_mpl.png | Bin 0 -> 24681 bytes .../figures/tutorial_social_network_2_mpl.png | Bin 0 -> 30944 bytes doc/source/tutorial.rst | 23 +- doc/source/visualisation.rst | 20 +- setup.py | 10 +- src/igraph/__init__.py | 109 +- src/igraph/app/shell.py | 6 +- src/igraph/clustering.py | 232 +- src/igraph/configuration.py | 93 +- src/igraph/datatypes.py | 163 +- src/igraph/drawing/__init__.py | 589 +--- src/igraph/drawing/baseclasses.py | 335 +- src/igraph/drawing/cairo/__init__.py | 3 + src/igraph/drawing/cairo/base.py | 84 + src/igraph/drawing/{ => cairo}/coord.py | 22 +- src/igraph/drawing/cairo/dendrogram.py | 247 ++ src/igraph/drawing/{ => cairo}/edge.py | 190 +- src/igraph/drawing/cairo/graph.py | 425 +++ src/igraph/drawing/cairo/histogram.py | 59 + src/igraph/drawing/cairo/matrix.py | 250 ++ src/igraph/drawing/cairo/palette.py | 53 + src/igraph/drawing/cairo/plot.py | 360 ++ src/igraph/drawing/cairo/polygon.py | 86 + src/igraph/drawing/cairo/text.py | 358 ++ src/igraph/drawing/cairo/utils.py | 20 + src/igraph/drawing/{ => cairo}/vertex.py | 44 +- src/igraph/drawing/colors.py | 64 +- src/igraph/drawing/graph.py | 1032 +----- src/igraph/drawing/matplotlib/__init__.py | 0 src/igraph/drawing/matplotlib/dendrogram.py | 176 + src/igraph/drawing/matplotlib/edge.py | 274 ++ src/igraph/drawing/matplotlib/graph.py | 317 ++ src/igraph/drawing/matplotlib/histogram.py | 37 + src/igraph/drawing/matplotlib/matrix.py | 26 + src/igraph/drawing/matplotlib/palette.py | 49 + src/igraph/drawing/matplotlib/polygon.py | 88 + src/igraph/drawing/matplotlib/utils.py | 26 + src/igraph/drawing/matplotlib/vertex.py | 71 + src/igraph/drawing/plotly/__init__.py | 0 src/igraph/drawing/plotly/edge.py | 270 ++ src/igraph/drawing/plotly/graph.py | 281 ++ src/igraph/drawing/plotly/polygon.py | 104 + src/igraph/drawing/plotly/utils.py | 74 + src/igraph/drawing/plotly/vertex.py | 95 + src/igraph/drawing/shapes.py | 194 +- src/igraph/drawing/text.py | 367 +- src/igraph/drawing/utils.py | 250 +- src/igraph/formula.py | 3 +- src/igraph/statistics.py | 35 +- src/igraph/utils.py | 48 - tests/drawing/__init__.py | 0 tests/drawing/cairo/__init__.py | 0 .../baseline_images/clustering_directed.png | Bin 0 -> 30616 bytes .../clustering_directed_large.png | Bin 0 -> 64832 bytes .../cairo/baseline_images/graph_basic.png | Bin 0 -> 17231 bytes .../cairo/baseline_images/graph_directed.png | Bin 0 -> 17911 bytes .../graph_mark_groups_directed.png | Bin 0 -> 17911 bytes .../graph_mark_groups_squares_directed.png | Bin 0 -> 15413 bytes tests/drawing/cairo/test_graph.py | 99 + tests/drawing/cairo/utils.py | 170 + tests/drawing/matplotlib/__init__.py | 0 .../test_graph/clustering_directed.png | Bin 0 -> 36485 bytes .../test_graph/clustering_directed_large.png | Bin 0 -> 67108 bytes .../test_graph/graph_basic.png | Bin 0 -> 25084 bytes .../test_graph/graph_directed.png | Bin 0 -> 26545 bytes .../test_graph/graph_edit_children.png | Bin 0 -> 24552 bytes .../test_graph/graph_mark_groups_directed.png | Bin 0 -> 26545 bytes tests/drawing/matplotlib/test_graph.py | 176 + tests/drawing/matplotlib/utils.py | 122 + tests/drawing/plotly/__init__.py | 0 .../baseline_images/clustering_directed.json | 1056 ++++++ .../clustering_directed_large.json | 2991 +++++++++++++++++ .../plotly/baseline_images/graph_basic.json | 963 ++++++ .../baseline_images/graph_directed.json | 1048 ++++++ .../baseline_images/graph_edit_children.json | 963 ++++++ .../graph_mark_groups_directed.json | 1048 ++++++ tests/drawing/plotly/test_graph.py | 185 + tests/drawing/plotly/utils.py | 274 ++ tests/test_attributes.py | 3 +- tox.ini | 5 +- 83 files changed, 13925 insertions(+), 2943 deletions(-) create mode 100644 doc/source/figures/tutorial_social_network_1_mpl.png create mode 100644 doc/source/figures/tutorial_social_network_2_mpl.png create mode 100644 src/igraph/drawing/cairo/__init__.py create mode 100644 src/igraph/drawing/cairo/base.py rename src/igraph/drawing/{ => cairo}/coord.py (85%) create mode 100644 src/igraph/drawing/cairo/dendrogram.py rename src/igraph/drawing/{ => cairo}/edge.py (64%) create mode 100644 src/igraph/drawing/cairo/graph.py create mode 100644 src/igraph/drawing/cairo/histogram.py create mode 100644 src/igraph/drawing/cairo/matrix.py create mode 100644 src/igraph/drawing/cairo/palette.py create mode 100644 src/igraph/drawing/cairo/plot.py create mode 100644 src/igraph/drawing/cairo/polygon.py create mode 100644 src/igraph/drawing/cairo/text.py create mode 100644 src/igraph/drawing/cairo/utils.py rename src/igraph/drawing/{ => cairo}/vertex.py (63%) create mode 100644 src/igraph/drawing/matplotlib/__init__.py create mode 100644 src/igraph/drawing/matplotlib/dendrogram.py create mode 100644 src/igraph/drawing/matplotlib/edge.py create mode 100644 src/igraph/drawing/matplotlib/graph.py create mode 100644 src/igraph/drawing/matplotlib/histogram.py create mode 100644 src/igraph/drawing/matplotlib/matrix.py create mode 100644 src/igraph/drawing/matplotlib/palette.py create mode 100644 src/igraph/drawing/matplotlib/polygon.py create mode 100644 src/igraph/drawing/matplotlib/utils.py create mode 100644 src/igraph/drawing/matplotlib/vertex.py create mode 100644 src/igraph/drawing/plotly/__init__.py create mode 100644 src/igraph/drawing/plotly/edge.py create mode 100644 src/igraph/drawing/plotly/graph.py create mode 100644 src/igraph/drawing/plotly/polygon.py create mode 100644 src/igraph/drawing/plotly/utils.py create mode 100644 src/igraph/drawing/plotly/vertex.py create mode 100644 tests/drawing/__init__.py create mode 100644 tests/drawing/cairo/__init__.py create mode 100644 tests/drawing/cairo/baseline_images/clustering_directed.png create mode 100644 tests/drawing/cairo/baseline_images/clustering_directed_large.png create mode 100644 tests/drawing/cairo/baseline_images/graph_basic.png create mode 100644 tests/drawing/cairo/baseline_images/graph_directed.png create mode 100644 tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png create mode 100644 tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png create mode 100644 tests/drawing/cairo/test_graph.py create mode 100644 tests/drawing/cairo/utils.py create mode 100644 tests/drawing/matplotlib/__init__.py create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_directed.png create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png create mode 100644 tests/drawing/matplotlib/test_graph.py create mode 100644 tests/drawing/matplotlib/utils.py create mode 100644 tests/drawing/plotly/__init__.py create mode 100644 tests/drawing/plotly/baseline_images/clustering_directed.json create mode 100644 tests/drawing/plotly/baseline_images/clustering_directed_large.json create mode 100644 tests/drawing/plotly/baseline_images/graph_basic.json create mode 100644 tests/drawing/plotly/baseline_images/graph_directed.json create mode 100644 tests/drawing/plotly/baseline_images/graph_edit_children.json create mode 100644 tests/drawing/plotly/baseline_images/graph_mark_groups_directed.json create mode 100644 tests/drawing/plotly/test_graph.py create mode 100644 tests/drawing/plotly/utils.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed176ec2b..afd7a2df1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,8 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "cp27-* pp27-* cp35-*" + # skip testing on Python 3.10 until NumPy/SciPy/Pandas publish wheels + CIBW_TEST_SKIP: "cp310-*" jobs: build_wheels: @@ -26,7 +27,7 @@ jobs: python-version: '3.8' - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -50,7 +51,7 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +89,7 @@ jobs: brew install ninja autoconf automake libtool cmake - name: Build wheels - uses: joerick/cibuildwheel@v1.10.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_ARCHS_MACOS: "x86_64 arm64" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -145,16 +146,16 @@ jobs: shell: cmd - name: Build wheels - uses: joerick/cibuildwheel@v1.11.0 + uses: joerick/cibuildwheel@v2.1.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" + CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 - CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" - uses: actions/upload-artifact@v2 with: diff --git a/.gitignore b/.gitignore index 2391ed900..44657c996 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build/ dist/ doc/api/ src/igraph/*.so +result_images/ *.egg-info/ .python-version .eggs/ diff --git a/CHANGELOG.md b/CHANGELOG.md index e6d9c4755..bc13f2d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,22 @@ ### Changed -* Improved performance of `Graph.DataFrame()`, thanks to +- Improved performance of `Graph.DataFrame()`, thanks to [@fwitter](https://github.com/user/fwitter). See PR [#418](https://github.com/igraph/python-igraph/pull/418) for more details. +### Removed + +- Removed deprecated `UbiGraphDrawer`. + +- Removed deprecated `show()` method of `Plot` instances as well as the feature + that automatically shows the plot when `plot()` is called with no target. + ## [0.9.6] ### Fixed -* Version 0.9.5 accidentally broke the Matplotlib backend when it was invoked +- Version 0.9.5 accidentally broke the Matplotlib backend when it was invoked without the `mark_groups=...` keyword argument; this version fixes the issue. Thanks to @dschult for reporting it! @@ -20,13 +27,13 @@ ### Fixed -* `plot(g, ..., mark_groups=True)` now works with the Matplotlib plotting backend. +- `plot(g, ..., mark_groups=True)` now works with the Matplotlib plotting backend. -* `set_random_number_generator(None)` now correctly switches back to igraph's +- `set_random_number_generator(None)` now correctly switches back to igraph's own random number generator instead of the default one that hooks into the `random` module of Python. -* Improved performance in cases when igraph has to call back to Python's +- Improved performance in cases when igraph has to call back to Python's `random` module to generate random numbers. One example is `Graph.Degree_Sequence(method="vl")`, whose performance suffered a more than 30x slowdown on 32-bit platforms before, compared to the native C @@ -39,101 +46,100 @@ ### Added -* Added `Graph.is_tree()` to test whether a graph is a tree. +- Added `Graph.is_tree()` to test whether a graph is a tree. -* Added `Graph.Realize_Degree_Sequence()` to construct a graph that realizes a +- Added `Graph.Realize_Degree_Sequence()` to construct a graph that realizes a given degree sequence, using a deterministic (Havel-Hakimi-style) algorithm. -* Added `Graph.Tree_Game()` to generate random trees with uniform sampling. +- Added `Graph.Tree_Game()` to generate random trees with uniform sampling. -* `Graph.to_directed()` now supports a `mode=...` keyword argument. +- `Graph.to_directed()` now supports a `mode=...` keyword argument. -* Added a `create_using=...` keyword argument to `Graph.to_networkx()` to +- Added a `create_using=...` keyword argument to `Graph.to_networkx()` to let the user specify which NetworkX class to use when converting the graph. ### Changed -* Updated igraph dependency to 0.9.4. +- Updated igraph dependency to 0.9.4. ### Fixed -* Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` +- Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` on large graphs, thanks to @szhorvat and @iosonofabio for fixing the issue. -* Fixed the `autocurve=...` keyword argument of `plot()` when using the +- Fixed the `autocurve=...` keyword argument of `plot()` when using the Matplotlib backend. ### Deprecated -* Functions and methods that take string arguments that represent an underlying +- Functions and methods that take string arguments that represent an underlying enum in the C core of igraph now print a deprecation warning when provided with a string that does not match one of the enum member names (as documented in the docstrings) exactly. Partial matches will be removed in the next minor or major version, whichever comes first. -* `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. +- `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. -* `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project +- `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project is not maintained since 2008. ## [0.9.1] ### Changed -* Calling `plot()` without a filename or a target surface is now deprecated. +- Calling `plot()` without a filename or a target surface is now deprecated. The original intention was to plot to a temporary file and then open it in the default image viewer of the platform of the user automatically, but this has never worked reliably. The feature will be removed in 0.10.0. ### Fixed -* Fixed plotting of `VertexClustering` objects on Matplotlib axes. +- Fixed plotting of `VertexClustering` objects on Matplotlib axes. -* The `IGRAPH_CMAKE_EXTRA_ARGS` environment variable is now applied _after_ the +- The `IGRAPH_CMAKE_EXTRA_ARGS` environment variable is now applied _after_ the default CMake arguments when building the C core of igraph from source. This enables package maintainers to override any of the default arguments we pass to CMake. -* Fixed the documentation build by replacing Epydoc with PyDoctor. +- Fixed the documentation build by replacing Epydoc with PyDoctor. ### Miscellaneous -* Building `python-igraph` from source should not require `flex` and `bison` +- Building `python-igraph` from source should not require `flex` and `bison` any more; sources of the parsers used by the C core are now included in the Python source tarball. -* Many old code constructs that were used to maintain compatibility with Python +- Many old code constructs that were used to maintain compatibility with Python 2.x are removed now that we have dropped support for Python 2.x. -* Reading GraphML files is now also supported on Windows if you use one of the +- Reading GraphML files is now also supported on Windows if you use one of the official Python wheels. - ## [0.9.0] ### Added -* `Graph.DataFrame` now has a `use_vids=...` keyword argument that decides whether +- `Graph.DataFrame` now has a `use_vids=...` keyword argument that decides whether the data frame contains vertex IDs (`True`) or vertex names (`False`). (PR #348) -* Added `MatplotlibGraphDrawer` to draw a graph on an existing Matplotlib +- Added `MatplotlibGraphDrawer` to draw a graph on an existing Matplotlib figure. (PR #341) -* Added a code path to choose between preferred image viewers on FreeBSD. (PR #354) +- Added a code path to choose between preferred image viewers on FreeBSD. (PR #354) -* Added `Graph.harmonic_centrality()` that wraps `igraph_harmonic_centrality()` +- Added `Graph.harmonic_centrality()` that wraps `igraph_harmonic_centrality()` from the underlying C library. ### Changed -* `python-igraph` is now compatible with `igraph` 0.9.0. +- `python-igraph` is now compatible with `igraph` 0.9.0. -* The setup script was adapted to the new CMake-based build system of `igraph`. +- The setup script was adapted to the new CMake-based build system of `igraph`. -* Dropped support for older Python versions; the oldest Python version that +- Dropped support for older Python versions; the oldest Python version that `python-igraph` is tested on is now Python 3.6. -* The default splitting heuristic of the BLISS isomorphism algorithm was changed +- The default splitting heuristic of the BLISS isomorphism algorithm was changed from `IGRAPH_BLISS_FM` (first maximally non-trivially connected non-singleton cell) to `IGRAPH_BLISS_FL` (first largest non-singleton cell) as this seems to provide better performance on a variety of graph classes. This change is a follow-up @@ -141,31 +147,30 @@ ### Fixed -* Fixed crashes in the Python-C glue code related to the handling of empty +- Fixed crashes in the Python-C glue code related to the handling of empty vectors in certain attribute merging functions (see issue #358). -* Fixed a memory leak in `Graph.closeness_centrality()` when an invalid `cutoff` +- Fixed a memory leak in `Graph.closeness_centrality()` when an invalid `cutoff` argument was provided to the function. -* Clarified that the `fixed=...` argument is ineffective for the DrL layout +- Clarified that the `fixed=...` argument is ineffective for the DrL layout because the underlying C code does not handle it. The argument was _not_ removed for sake of backwards compatibility. -* `VertexSeq.find(name=x)` now works correctly when `x` is an integer; fixes +- `VertexSeq.find(name=x)` now works correctly when `x` is an integer; fixes #367 ### Miscellaneous -* The Python codebase was piped through `black` for consistent formatting. +- The Python codebase was piped through `black` for consistent formatting. -* Wildcard imports were removed from the codebase. +- Wildcard imports were removed from the codebase. -* CI tests were moved to Github Actions from Travis. +- CI tests were moved to Github Actions from Travis. -* The core C library is now built with `-fPIC` on Linux to allow linking to the +- The core C library is now built with `-fPIC` on Linux to allow linking to the Python interface. - ## [0.8.3] This is the last released version of `python-igraph` without a changelog file. @@ -173,7 +178,7 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..HEAD +[unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..HEAD [0.9.6]: https://github.com/igraph/python-igraph/compare/0.9.5...0.9.6 [0.9.5]: https://github.com/igraph/python-igraph/compare/0.9.4...0.9.5 [0.9.4]: https://github.com/igraph/python-igraph/compare/0.9.1...0.9.4 diff --git a/doc/source/figures/tutorial_social_network_1_mpl.png b/doc/source/figures/tutorial_social_network_1_mpl.png new file mode 100644 index 0000000000000000000000000000000000000000..e7b6bf4d323d47f656768d76d00b210ee4293a01 GIT binary patch literal 24681 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index b9d7cf25e..8f732c00f 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -659,8 +659,9 @@ the screen or to a PDF, PNG or SVG file using the `Cairo library >> fig, ax = plt.subplots() >>> plot(g, layout=layout, target=ax) +.. figure:: figures/tutorial_social_network_1_mpl.png + :alt: The visual representation of our social network (matplotlib backend) + :align: center + Hmm, this is not too pretty so far. A trivial addition would be to use the names as the vertex labels and to color the vertices according to the gender. Vertex labels are taken from the ``label`` attribute by default and vertex colors are determined by the @@ -765,8 +770,8 @@ from the ``label`` attribute by default and vertex colors are determined by the >>> g.vs["label"] = g.vs["name"] >>> color_dict = {"m": "blue", "f": "pink"} >>> g.vs["color"] = [color_dict[gender] for gender in g.vs["gender"]] ->>> plot(g, layout=layout, bbox=(300, 300), margin=20) ->>> plot(g, layout=layout, bbox=(300, 300), margin=20, target=ax) # matplotlib version +>>> plot(g, layout=layout, bbox=(300, 300), margin=20) # Cairo backend +>>> plot(g, layout=layout, target=ax) # matplotlib backend Note that we are simply re-using the previous layout object here, but we also specified that we need a smaller plot (300 x 300 pixels) and a larger margin around the graph @@ -778,6 +783,14 @@ to fit the labels (20 pixels). The result is: Our social network - with names as labels and genders as colors +and for matplotlib: + +.. figure:: figures/tutorial_social_network_2_mpl.png + :alt: The visual representation of our social network - with names and genders + :align: center + + Our social network - with names as labels and genders as colors + Instead of specifying the visual properties as vertex and edge attributes, you can also give them as keyword arguments to :func:`plot`: diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index a67fc90be..629324cd4 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -137,13 +137,27 @@ you might want to change the size and color of the vertices: >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> ig.plot(g, target=ax) ->>> dots = ax.get_children()[0] # This is a PathCollection ->>> dots.set_color('tomato') ->>> dots.set_sizes([250] * g.vcount()) +>>> dot = ax.get_children()[0] # This is a Circle for the first vertex +>>> dot.set_color('tomato') +>>> dot.radius *= 2 # double the default radius That also helps as a workaround if you cannot figure out how to use the plotting options below: just use the defaults and then customize the appearance of your graph via standard `matplotlib`_ tools. +.. note:: The order of `ax.get_children()` is the following: (i) patches for clustering hulls if requested; + (ii) patches for vertices; (iii) patches for edges: for undirected graphs, there's one patch per edge. For directed graphs, there's a *pair* of patches, associated with the arrow body and head, respectively. + +To use `matplotlib_` as your default plotting backend, you can set: + +>>> ig.config['plotting.backend'] = 'matplotlib' + +Then you don't have to specify an `Axes` anymore: + +>>> ig.plot(g) + +will automatically make a new `Axes` for you and return it. + + Plotting graphs in Jupyter notebooks ++++++++++++++++++++++++++++++++++++ |igraph| supports inline plots within a `Jupyter`_ notebook via both the `Cairo`_ and `matplotlib`_ backend. If you are diff --git a/setup.py b/setup.py index 5ba9f0e12..e9a1c647b 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ ########################################################################### -from setuptools import setup, Command, Extension +from setuptools import find_packages, setup, Command, Extension import glob import shlex @@ -819,10 +819,14 @@ def use_educated_guess(self) -> None: author_email="ntamas@gmail.com", ext_modules=[igraph_extension], package_dir={"igraph": "src/igraph"}, - packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], + packages=find_packages(where="src"), scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], extras_require={ + "cairo": ["cairocffi>=1.2.0"], + "matplotlib": ["matplotlib>=3.3.0; platform_python_implementation != 'PyPy'"], + "plotly": ["plotly>=5.3.0"], + # compatibility alias to 'cairo' for python-igraph <= 0.9.6 "plotting": ["cairocffi>=1.2.0"], "test": [ "networkx>=2.5", @@ -830,6 +834,8 @@ def use_educated_guess(self) -> None: "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0,<1.3.1; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", + "matplotlib>=3.3.4; platform_python_implementation != 'PyPy'", + "plotly>=5.3.0", ], }, python_requires=">=3.6", diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 530cbc3cb..31609a5ce 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -74,7 +74,7 @@ set_progress_handler, set_random_number_generator, set_status_handler, - __igraph_version__ + __igraph_version__, ) from igraph.clustering import ( Clustering, @@ -89,7 +89,16 @@ ) from igraph.cut import Cut, Flow from igraph.configuration import Configuration, init as init_configuration -from igraph.drawing import BoundingBox, DefaultGraphDrawer, Plot, Point, Rectangle, plot +from igraph.drawing import ( + BoundingBox, + CairoGraphDrawer, + DefaultGraphDrawer, + MatplotlibGraphDrawer, + Plot, + Point, + Rectangle, + plot, +) from igraph.drawing.colors import ( Palette, GradientPalette, @@ -732,9 +741,7 @@ def get_adjacency_sparse(self, attribute=None): try: from scipy import sparse except ImportError: - raise ImportError( - "You should install scipy in order to use this function" - ) + raise ImportError("You should install scipy in order to use this function") edges = self.get_edgelist() if attribute is None: @@ -2454,7 +2461,7 @@ def write_svg( edge_stroke_widths="width", font_size=16, *args, - **kwds + **kwds, ): """Saves the graph as an SVG (Scalable Vector Graphics) file @@ -2622,13 +2629,13 @@ def write_svg( print(' id="pathArrow{0}"'.format(marker_index), file=f) print( ' style="font-size:12.0;fill-rule:evenodd;' - 'stroke-width:0.62500000;stroke-linejoin:round;' + "stroke-width:0.62500000;stroke-linejoin:round;" 'fill:{0}"'.format(e_col), file=f, ) print( ' d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 ' - 'L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 ' + "L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 " '6.9831476,1.6157441 8.7185878,4.0337352 z "', file=f, ) @@ -2656,7 +2663,7 @@ def write_svg( print("'.format( + "/>".format( vertex_width / 2.0, vertex_height / 2.0, vertex_width, @@ -2779,19 +2786,15 @@ def write_svg( print( ' '.format( - vertex_size / 2.0, vidx, font_size - ), + "font-weight:normal;text-align:center;line-height:125%;" + "letter-spacing:0px;word-spacing:0px;text-anchor:middle;" + "fill:#000000;fill-opacity:1;stroke:none;" + 'font-family:Sans">'.format(vertex_size / 2.0, vidx, font_size), file=f, ) print( '' - '{2}'.format( - vertex_size / 2.0, vidx, str(labels[vidx]) - ), + "{2}".format(vertex_size / 2.0, vidx, str(labels[vidx])), file=f, ) print(" ", file=f) @@ -3345,7 +3348,7 @@ def Incidence( multiple=False, weighted=None, *args, - **kwds + **kwds, ): """Creates a bipartite graph from an incidence matrix. @@ -3440,26 +3443,41 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): if edges.shape[1] < 2: raise ValueError("The 'edges' DataFrame must contain at least two columns") if vertices is not None and vertices.shape[1] < 1: - raise ValueError("The 'vertices' DataFrame must contain at least one column") + raise ValueError( + "The 'vertices' DataFrame must contain at least one column" + ) if use_vids: - if not (str(edges.dtypes[0]).startswith("int") and str(edges.dtypes[1]).startswith("int")): - raise TypeError(f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}") + if not ( + str(edges.dtypes[0]).startswith("int") + and str(edges.dtypes[1]).startswith("int") + ): + raise TypeError( + f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}" + ) elif (edges.iloc[:, :2] < 0).any(axis=None): raise ValueError("Source and target IDs must not be negative") if vertices is not None: vertices = vertices.sort_index() - if not vertices.index.equals(pd.RangeIndex.from_range(range(vertices.shape[0]))): + if not vertices.index.equals( + pd.RangeIndex.from_range(range(vertices.shape[0])) + ): if not str(vertices.index.dtype).startswith("int"): - raise TypeError(f"Vertex IDs must be 0-based integers, found type {vertices.index.dtype}") + raise TypeError( + f"Vertex IDs must be 0-based integers, found type {vertices.index.dtype}" + ) elif (vertices.index < 0).any(axis=None): raise ValueError("Vertex IDs must not be negative") else: - raise ValueError(f"Vertex IDs must be an integer sequence from 0 to {vertices.shape[0] - 1}") + raise ValueError( + f"Vertex IDs must be an integer sequence from 0 to {vertices.shape[0] - 1}" + ) else: # Handle if some source and target names in 'edges' are 'NA' if edges.iloc[:, :2].isna().any(axis=None): - warn("In the first two columns of 'edges' NA elements were replaced with string \"NA\"") + warn( + "In the first two columns of 'edges' NA elements were replaced with string \"NA\"" + ) edges = edges.copy() edges.iloc[:, :2].fillna("NA", inplace=True) @@ -3468,7 +3486,9 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): vertices = pd.DataFrame({"name": np.unique(edges.values[:, :2])}) if vertices.iloc[:, 0].isna().any(): - warn("In the first column of 'vertices' NA elements were replaced with string \"NA\"") + warn( + "In the first column of 'vertices' NA elements were replaced with string \"NA\"" + ) vertices = vertices.copy() vertices.iloc[:, 0].fillna("NA", inplace=True) @@ -3476,9 +3496,13 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): raise ValueError("Vertex names must be unique") if vertices.shape[1] > 1 and "name" in vertices.columns[1:]: - raise ValueError("Vertex attribute conflict: DataFrame already contains column 'name'") + raise ValueError( + "Vertex attribute conflict: DataFrame already contains column 'name'" + ) - vertices = vertices.rename({vertices.columns[0]: "name"}, axis=1).reset_index(drop=True) + vertices = vertices.rename( + {vertices.columns[0]: "name"}, axis=1 + ).reset_index(drop=True) # Map source and target names in 'edges' to IDs vid_map = pd.Series(vertices.index, index=vertices.iloc[:, 0]) @@ -3492,7 +3516,9 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): g = Graph(n=nv, directed=directed) else: if not edges.iloc[:, :2].isin(vertices.index).all(axis=None): - raise ValueError("Some vertices in the edge DataFrame are missing from vertices DataFrame") + raise ValueError( + "Some vertices in the edge DataFrame are missing from vertices DataFrame" + ) nv = vertices.shape[0] g = Graph(n=nv, directed=directed) # Add vertex attributes @@ -3501,7 +3527,9 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): # add edges including optional attributes e_list = list(edges.iloc[:, :2].itertuples(index=False, name=None)) - e_attr = edges.iloc[:, 2:].to_dict(orient='list') if edges.shape[1] > 2 else None + e_attr = ( + edges.iloc[:, 2:].to_dict(orient="list") if edges.shape[1] > 2 else None + ) g.add_edges(e_list, e_attr) return g @@ -3964,8 +3992,8 @@ def __reduce__(self): __iter__ = None # needed for PyPy __hash__ = None # needed for PyPy - def __plot__(self, context, bbox, palette, *args, **kwds): - """Plots the graph to the given Cairo context in the given bounding box + def __plot__(self, backend, context, *args, **kwds): + """Plots the graph to the given Cairo context or matplotlib Axes. The visual style of vertices and edges can be modified at three places in the following order of precedence (lower indices override @@ -4155,11 +4183,14 @@ def __plot__(self, context, bbox, palette, *args, **kwds): specifies whether the order is reversed (C{True}, C{False}, C{"asc"} and C{"desc"} are accepted values). """ - drawer_factory = kwds.get("drawer_factory", DefaultGraphDrawer) - if "drawer_factory" in kwds: - del kwds["drawer_factory"] - drawer = drawer_factory(context, bbox) - drawer.draw(self, palette, *args, **kwds) + from igraph.drawing import DrawerDirectory + + drawer = kwds.pop( + "drawer_factory", + DrawerDirectory.resolve(self, backend)(context), + + ) + drawer.draw(self, *args, **kwds) def __str__(self): """Returns a string representation of the graph. diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index cb450c32a..86f901075 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -20,6 +20,7 @@ """ +from abc import ABCMeta, abstractmethod import re import sys @@ -285,14 +286,15 @@ def clear(self): self.last_message = "" -class Shell: +class Shell(metaclass=ABCMeta): """Superclass of the embeddable shells supported by igraph""" def __init__(self): pass + @abstractmethod def __call__(self): - raise NotImplementedError("abstract class") + raise NotImplementedError def supports_progress_bar(self): """Checks whether the shell supports progress bars. diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 67ef19bb7..92631d31c 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -3,16 +3,16 @@ """Classes related to graph clustering.""" from copy import deepcopy -from math import pi from io import StringIO from igraph import community_to_membership from igraph.configuration import Configuration from igraph.datatypes import UniqueIdGenerator from igraph.drawing.colors import ClusterColoringPalette +from igraph.drawing.cairo.dendrogram import CairoDendrogramDrawer +from igraph.drawing.matplotlib.dendrogram import MatplotlibDendrogramDrawer from igraph.statistics import Histogram from igraph.summary import _get_wrapper_for_width -from igraph.utils import str_to_orientation class Clustering: @@ -427,9 +427,8 @@ def giant(self): max_size = max(ss) return self.subgraph(ss.index(max_size)) - def __plot__(self, context, bbox, palette, *args, **kwds): - """Plots the clustering to the given Cairo context in the given - bounding box. + def __plot__(self, backend, context, *args, **kwds): + """Plots the clustering to the given Cairo context or matplotlib Axes. This is done by calling L{Graph.__plot__()} with the same arguments, but coloring the graph vertices according to the current clustering (unless @@ -476,15 +475,18 @@ def __plot__(self, context, bbox, palette, *args, **kwds): @see: L{Graph.__plot__()} for more supported keyword arguments. """ + from igraph.drawing.colors import default_edge_colors + if "edge_color" not in kwds and "color" not in self.graph.edge_attributes(): # Set up a default edge coloring based on internal vs external edges - colors = ["grey20", "grey80"] + colors = default_edge_colors[backend] kwds["edge_color"] = [ colors[is_crossing] for is_crossing in self.crossing() ] + palette = kwds.get('palette', None) if palette is None: - palette = ClusterColoringPalette(len(self)) + kwds['palette'] = ClusterColoringPalette(len(self)) if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: @@ -496,8 +498,9 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "vertex_color" not in kwds: kwds["vertex_color"] = self.membership + result = self._graph.__plot__(backend, context, *args, **kwds) - return self._graph.__plot__(context, bbox, palette, *args, **kwds) + return result def _formatted_cluster_iterator(self): """Iterates over the clusters and formats them into a string to be @@ -723,46 +726,8 @@ def summary(self, verbosity=0, max_leaf_count=40): return out.getvalue().strip() - def _item_box_size(self, context, horiz, idx): - """Calculates the amount of space needed for drawing an - individual vertex at the bottom of the dendrogram.""" - if self._names is None or self._names[idx] is None: - x_bearing, _, _, height, x_advance, _ = context.text_extents("") - else: - x_bearing, _, _, height, x_advance, _ = context.text_extents( - str(self._names[idx]) - ) - - if horiz: - return x_advance - x_bearing, height - return height, x_advance - x_bearing - - def _plot_item(self, context, horiz, idx, x, y): - """Plots a dendrogram item to the given Cairo context - - @param context: the Cairo context we are plotting on - @param horiz: whether the dendrogram is horizontally oriented - @param idx: the index of the item - @param x: the X position of the item - @param y: the Y position of the item - """ - if self._names is None or self._names[idx] is None: - return - - height = self._item_box_size(context, True, idx)[1] - if horiz: - context.move_to(x, y + height) - context.show_text(str(self._names[idx])) - else: - context.save() - context.translate(x, y) - context.rotate(-pi / 2.0) - context.move_to(0, height) - context.show_text(str(self._names[idx])) - context.restore() - - def __plot__(self, context, bbox, palette, *args, **kwds): - """Draws the dendrogram on the given Cairo context + def __plot__(self, backend, context, *args, **kwds): + """Draws the dendrogram on the given Cairo context or matplotlib Axes. Supported keyword arguments are: @@ -776,131 +741,18 @@ def __plot__(self, context, bbox, palette, *args, **kwds): The default is C{left-right}. """ - from igraph.layout import Layout - - if self._names is None: - self._names = [str(x) for x in range(self._nitems)] - - orientation = str_to_orientation( - kwds.get("orientation", "lr"), reversed_vertical=True - ) - horiz = orientation in ("lr", "rl") - - # Get the font height - font_height = context.font_extents()[2] - - # Calculate space needed for individual items at the - # bottom of the dendrogram - item_boxes = [ - self._item_box_size(context, horiz, idx) for idx in range(self._nitems) - ] - - # Small correction for cases when the right edge of the labels is - # aligned with the tips of the dendrogram branches - ygap = 2 if orientation == "bt" else 0 - xgap = 2 if orientation == "lr" else 0 - item_boxes = [(x + xgap, y + ygap) for x, y in item_boxes] - - # Calculate coordinates - layout = Layout([(0, 0)] * self._nitems, dim=2) - inorder = self._traverse_inorder() - if not horiz: - x, y = 0, 0 - for idx, element in enumerate(inorder): - layout[element] = (x, 0) - x += max(font_height, item_boxes[element][0]) - - for id1, id2 in self._merges: - y += 1 - layout.append(((layout[id1][0] + layout[id2][0]) / 2.0, y)) - - # Mirror or rotate the layout if necessary - if orientation == "bt": - layout.mirror(1) + if backend == "matplotlib": + drawer = MatplotlibDendrogramDrawer(context) else: - x, y = 0, 0 - for idx, element in enumerate(inorder): - layout[element] = (0, y) - y += max(font_height, item_boxes[element][1]) - - for id1, id2 in self._merges: - x += 1 - layout.append((x, (layout[id1][1] + layout[id2][1]) / 2.0)) - - # Mirror or rotate the layout if necessary - if orientation == "rl": - layout.mirror(0) - - # Rescale layout to the bounding box - maxw = max(e[0] for e in item_boxes) - maxh = max(e[1] for e in item_boxes) - - # w, h: width and height of the area containing the dendrogram - # tree without the items. - # delta_x, delta_y: displacement of the dendrogram tree - width, height = float(bbox.width), float(bbox.height) - delta_x, delta_y = 0, 0 - if horiz: - width -= maxw - if orientation == "lr": - delta_x = maxw - else: - height -= maxh - if orientation == "tb": - delta_y = maxh + bbox = kwds.pop('bbox', None) + palette = kwds.pop('palette', None) + if bbox is None: + raise ValueError('bbox is required for cairo plots') + if palette is None: + raise ValueError('palette is required for cairo plots') + drawer = CairoDendrogramDrawer(context, bbox, palette) - if horiz: - delta_y += font_height / 2.0 - else: - delta_x += font_height / 2.0 - layout.fit_into( - (delta_x, delta_y, width - delta_x, height - delta_y), - keep_aspect_ratio=False, - ) - - context.save() - - context.translate(bbox.left, bbox.top) - context.set_source_rgb(0.0, 0.0, 0.0) - context.set_line_width(1) - - # Draw items - if horiz: - sgn = 0 if orientation == "rl" else -1 - for idx in range(self._nitems): - x = layout[idx][0] + sgn * item_boxes[idx][0] - y = layout[idx][1] - item_boxes[idx][1] / 2.0 - self._plot_item(context, horiz, idx, x, y) - else: - sgn = 1 if orientation == "bt" else 0 - for idx in range(self._nitems): - x = layout[idx][0] - item_boxes[idx][0] / 2.0 - y = layout[idx][1] + sgn * item_boxes[idx][1] - self._plot_item(context, horiz, idx, x, y) - - # Draw dendrogram lines - if not horiz: - for idx, (id1, id2) in enumerate(self._merges): - x0, y0 = layout[id1] - x1, y1 = layout[id2] - x2, y2 = layout[idx + self._nitems] - context.move_to(x0, y0) - context.line_to(x0, y2) - context.line_to(x1, y2) - context.line_to(x1, y1) - context.stroke() - else: - for idx, (id1, id2) in enumerate(self._merges): - x0, y0 = layout[id1] - x1, y1 = layout[id2] - x2, y2 = layout[idx + self._nitems] - context.move_to(x0, y0) - context.line_to(x2, y0) - context.line_to(x2, y1) - context.line_to(x1, y1) - context.stroke() - - context.restore() + drawer.draw(self, **kwds) @property def merges(self): @@ -1008,8 +860,8 @@ def optimal_count(self): def optimal_count(self, value): self._optimal_count = max(int(value), 1) - def __plot__(self, context, bbox, palette, *args, **kwds): - """Draws the vertex dendrogram on the given Cairo context + def __plot__(self, backend, context, *args, **kwds): + """Draws the vertex dendrogram on the given Cairo context or matplotlib Axes See L{Dendrogram.__plot__} for the list of supported keyword arguments.""" @@ -1025,7 +877,9 @@ class VisualVertexBuilder(AttributeCollectorBase): name if name is not None else str(idx) for idx, name in enumerate(self._names) ] - result = Dendrogram.__plot__(self, context, bbox, palette, *args, **kwds) + result = Dendrogram.__plot__( + self, backend, context, *args, **kwds + ) del self._names return result @@ -1272,9 +1126,8 @@ def subgraphs(self): """ return [self._graph.subgraph(cl) for cl in self] - def __plot__(self, context, bbox, palette, *args, **kwds): - """Plots the cover to the given Cairo context in the given - bounding box. + def __plot__(self, backend, context, *args, **kwds): + """Plots the cover to the given Cairo context or matplotlib Axes. This is done by calling L{Graph.__plot__()} with the same arguments, but drawing nice colored blobs around the vertex groups. @@ -1322,15 +1175,18 @@ def __plot__(self, context, bbox, palette, *args, **kwds): """ if "edge_color" not in kwds and "color" not in self.graph.edge_attributes(): # Set up a default edge coloring based on internal vs external edges - colors = ["grey20", "grey80"] + if backend == 'matplotlib': + colors = ["dimgrey", "silver"] + else: + colors = ["grey20", "grey80"] + kwds["edge_color"] = [ colors[is_crossing] for is_crossing in self.crossing() ] - if "palette" in kwds: - palette = kwds["palette"] - else: - palette = ClusterColoringPalette(len(self)) + palette = kwds.get("palette", None) + if palette is None: + kwds["palette"] = ClusterColoringPalette(len(self)) if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: @@ -1340,7 +1196,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): kwds["mark_groups"], self ) - return self._graph.__plot__(context, bbox, palette, *args, **kwds) + return self._graph.__plot__(backend, context, *args, **kwds) def _formatted_cluster_iterator(self): """Iterates over the clusters and formats them into a string to be @@ -1447,9 +1303,9 @@ def parents(self): if the given group is the root.""" return self._parent[:] - def __plot__(self, context, bbox, palette, *args, **kwds): - """Plots the cohesive block structure to the given Cairo context in - the given bounding box. + def __plot__(self, backend, context, *args, **kwds): + """Plots the cohesive block structure to the given Cairo context or + matplotlib Axes. Since a L{CohesiveBlocks} instance is also a L{VertexCover}, keyword arguments accepted by L{VertexCover.__plot__()} are also accepted here. @@ -1473,7 +1329,9 @@ def __plot__(self, context, bbox, palette, *args, **kwds): if "vertex_color" not in kwds: kwds["vertex_color"] = self.max_cohesions() - return VertexCover.__plot__(self, context, bbox, palette, *args, **kwds) + return VertexCover.__plot__( + self, backend, context, *args, **kwds + ) def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 43d890219..758c4adfd 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -8,81 +8,10 @@ as well as saving them to and retrieving them from disk. """ -import sys - -if sys.version_info < (3, 2): - from configparser import SafeConfigParser as ConfigParser -else: - from configparser import ConfigParser - -import platform import os.path +import platform - -def get_platform_image_viewer(): - """Returns the path of an image viewer on the given platform. - - Deprecated since python-igraph 0.9.1 and will be removed in 0.10.0. - - @deprecated: This function was only used by the now-deprecated C{show()} - method of the Plot class. - """ - plat = platform.system() - if plat == "Darwin": - # Most likely Mac OS X - return "open" - elif plat == "Linux": - # Linux has a whole lot of choices, try to find one - choices = [ - "eog", - "gthumb", - "gqview", - "kuickshow", - "xnview", - "display", - "gpicview", - "gwenview", - "qiv", - "gimv", - "ristretto", - "geeqie", - "eom", - ] - paths = ["/usr/bin", "/bin"] - for path in paths: - for choice in choices: - full_path = os.path.join(path, choice) - if os.path.isfile(full_path): - return full_path - return "" - elif plat == "FreeBSD": - # FreeBSD also has a whole lot of choices, try to find one - choices = [ - "eog", - "gthumb", - "geeqie", - "display", - "gpicview", - "gwenview", - "qiv", - "gimv", - "ristretto", - "geeqie", - "eom", - ] - paths = ["%%LOCALBASE%%/bin"] - for path in paths: - for choice in choices: - full_path = os.path.join(path, choice) - if os.path.isfile(full_path): - return full_path - return "" - elif plat == "Windows" or plat == "Microsoft": # Thanks to Dale Hunscher - # Use the built-in Windows image viewer, if available - return "start" - else: - # Unknown system - return "" +from configparser import ConfigParser class Configuration: @@ -140,25 +69,15 @@ class Configuration: - B{verbose}: whether L{igraph} should talk more than really necessary. For instance, if set to C{True}, some functions display progress bars. - Application settings - -------------------- - - These settings specify the external applications that are possibly - used by C{igraph}. They are all stored in section C{apps}. - - - B{image_viewer}: image viewer application. If set to an empty string, - it will be determined automatically from the platform C{igraph} runs - on. On Mac OS X, it defaults to the Preview application. On Linux, - it chooses a viewer from several well-known Linux viewers like - C{gthumb}, C{kuickview} and so on (see the source code for the full - list). On Windows, it defaults to the system's built-in image viewer. - Plotting settings ----------------- These settings specify the default values used by plotting functions. They are all stored in section C{plotting}. + - B{backend}: either "cairo" if you want to use Cairo for plotting + or "matplotlib" if you want to use the Matplotlib plotting backend. + - B{layout}: default graph layout algorithm to be used. - B{mark_groups}: whether to mark the clusters by polygons when @@ -246,7 +165,7 @@ def setfloat(obj, section, key, value): _definitions = { "general.shells": {"default": "IPythonShell,ClassicPythonShell"}, "general.verbose": {"default": True, "type": "boolean"}, - "apps.image_viewer": {"default": get_platform_image_viewer()}, + "plotting.backend": {"default": "cairo"}, "plotting.layout": {"default": "auto"}, "plotting.mark_groups": {"default": False, "type": "boolean"}, "plotting.palette": {"default": "gray"}, diff --git a/src/igraph/datatypes.py b/src/igraph/datatypes.py index 1a53bba07..ebae642db 100644 --- a/src/igraph/datatypes.py +++ b/src/igraph/datatypes.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """Additional auxiliary data types""" -from itertools import islice +__all__ = ("Matrix",) class Matrix: @@ -271,8 +271,8 @@ def __iter__(self): the original matrix.""" return (list(row) for row in self._data) - def __plot__(self, context, bbox, palette, **kwds): - """Plots the matrix to the given Cairo context in the given box + def __plot__(self, backend, context, **kwds): + """Plots the matrix to the given Cairo context or matplotlib Axes. Besides the usual self-explanatory plotting parameters (C{context}, C{bbox}, C{palette}), it accepts the following keyword arguments: @@ -322,157 +322,10 @@ def __plot__(self, context, bbox, palette, **kwds): is square-shaped, the same names are used for both column and row names. """ - grid_width = float(kwds.get("grid_width", 1.0)) - border_width = float(kwds.get("border_width", 1.0)) - style = kwds.get("style", "boolean") - row_names = kwds.get("row_names") - col_names = kwds.get("col_names", row_names) - values = kwds.get("values") - value_format = kwds.get("value_format", str) - - # Validations - if style not in ("boolean", "palette", "none", None): - raise ValueError("invalid style") - if style == "none": - style = None - if row_names is None and col_names is not None: - row_names = col_names - if row_names is not None: - row_names = [str(name) for name in islice(row_names, self._nrow)] - if len(row_names) < self._nrow: - row_names.extend([""] * (self._nrow - len(row_names))) - if col_names is not None: - col_names = [str(name) for name in islice(col_names, self._ncol)] - if len(col_names) < self._ncol: - col_names.extend([""] * (self._ncol - len(col_names))) - if values is False: - values = None - if values is True: - values = self - if isinstance(values, list): - values = Matrix(list) - if values is not None and not isinstance(values, Matrix): - raise TypeError("values must be None, False, True or a matrix") - if values is not None and values.shape != self.shape: - raise ValueError("values must be a matrix of size %s" % self.shape) - - # Calculate text extents if needed - if row_names is not None or col_names is not None: - te = context.text_extents - space_width = te(" ")[4] - max_row_name_width = max([te(s)[4] for s in row_names]) + space_width - max_col_name_width = max([te(s)[4] for s in col_names]) + space_width - else: - max_row_name_width, max_col_name_width = 0, 0 - - # Calculate sizes - total_width = float(bbox.width) - max_row_name_width - total_height = float(bbox.height) - max_col_name_width - dx = total_width / self.shape[1] - dy = total_height / self.shape[0] - if kwds.get("square", True): - dx, dy = min(dx, dy), min(dx, dy) - total_width, total_height = dx * self.shape[1], dy * self.shape[0] - ox = bbox.left + (bbox.width - total_width - max_row_name_width) / 2.0 - oy = bbox.top + (bbox.height - total_height - max_col_name_width) / 2.0 - ox += max_row_name_width - oy += max_col_name_width - - # Determine rescaling factors for the palette if needed - if style == "palette": - mi, ma = self.min(), self.max() - color_offset = mi - color_ratio = (len(palette) - 1) / float(ma - mi) - - # Validate grid width - if dx < 3 * grid_width or dy < 3 * grid_width: - grid_width = 0.0 - if grid_width > 0: - context.set_line_width(grid_width) - else: - # When the grid width is zero, we will still stroke the - # rectangles, but with the same color as the fill color - # of the cell - otherwise we would get thin white lines - # between the cells as a drawing artifact - context.set_line_width(1) - - # Draw row names (if any) - context.set_source_rgb(0.0, 0.0, 0.0) - if row_names is not None: - x, y = ox, oy - for heading in row_names: - _, _, _, h, xa, _ = context.text_extents(heading) - context.move_to(x - xa - space_width, y + (dy + h) / 2.0) - context.show_text(heading) - y += dy - - # Draw column names (if any) - if col_names is not None: - context.save() - context.translate(ox, oy) - context.rotate(-1.5707963285) # pi/2 - x, y = 0.0, 0.0 - for heading in col_names: - _, _, _, h, _, _ = context.text_extents(heading) - context.move_to(x + space_width, y + (dx + h) / 2.0) - context.show_text(heading) - y += dx - context.restore() - - # Draw matrix - x, y = ox, oy - if style is None: - fill = lambda: None # noqa: E731 - else: - fill = context.fill_preserve - for row in self: - for item in row: - if item is None: - x += dx - continue - if style == "boolean": - if item: - context.set_source_rgb(0.0, 0.0, 0.0) - else: - context.set_source_rgb(1.0, 1.0, 1.0) - elif style == "palette": - cidx = int((item - color_offset) * color_ratio) - if cidx < 0: - cidx = 0 - context.set_source_rgba(*palette.get(cidx)) - context.rectangle(x, y, dx, dy) - if grid_width > 0: - fill() - context.set_source_rgb(0.5, 0.5, 0.5) - context.stroke() - else: - fill() - context.stroke() - x += dx - x, y = ox, y + dy - - # Draw cell values - if values is not None: - x, y = ox, oy - context.set_source_rgb(0.0, 0.0, 0.0) - for row in values.data: - if hasattr(value_format, "__call__"): - values = [value_format(item) for item in row] - else: - values = [value_format % item for item in row] - for item in values: - th, tw = context.text_extents(item)[3:5] - context.move_to(x + (dx - tw) / 2.0, y + (dy + th) / 2.0) - context.show_text(item) - x += dx - x, y = ox, y + dy - - # Draw borders - if border_width > 0: - context.set_line_width(border_width) - context.set_source_rgb(0.0, 0.0, 0.0) - context.rectangle(ox, oy, dx * self.shape[1], dy * self.shape[0]) - context.stroke() + from igraph.drawing import DrawerDirectory + + drawer = DrawerDirectory.resolve(self, backend)(context) + drawer.draw(self, **kwds) def min(self, dim=None): """Returns the minimum of the matrix along the given dimension @@ -716,7 +569,7 @@ def __setitem__(self, item, value): self._ids[item] = value def __len__(self): - """"Returns the number of items""" + """ "Returns the number of items""" return len(self._ids) def reverse_dict(self): diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 244bb9116..a1f53d00d 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -1,402 +1,119 @@ """ Drawing and plotting routines for IGraph. -Plotting is dependent on the C{pycairo} or C{cairocffi} libraries that provide -Python bindings to the popular U{Cairo library}. +IGraph has two plotting backends at the moment: Cairo and Matplotlib. + +The Cairo backend is dependent on the C{pycairo} or C{cairocffi} libraries that +provide Python bindings to the popular U{Cairo library}. This means that if you don't have U{pycairo} or U{cairocffi} installed, you won't be able -to use the plotting capabilities. However, you can still use L{Graph.write_svg} -to save the graph to an SVG file and view it from +to use the Cairo plotting backend. Whenever the documentation refers to the +C{pycairo} library, you can safely replace it with C{cairocffi} as the two are +API-compatible. + +The Matplotlib backend uses the U{Matplotlib library}. +You will need to install it from PyPI if you want to use the Matplotlib +plotting backend. + +If you do not want to (or cannot) install any of the dependencies outlined +above, you can still save the graph to an SVG file and view it from U{Mozilla Firefox} (free) or edit it in U{Inkscape} (free), U{Skencil} (formerly known as Sketch, also free) or Adobe Illustrator. - -Whenever the documentation refers to the C{pycairo} library, you can safely -replace it with C{cairocffi} as the two are API-compatible. """ +from pathlib import Path from warnings import warn -import os -import platform -import time - -from io import BytesIO from igraph.configuration import Configuration +from igraph.drawing.cairo.utils import find_cairo +from igraph.drawing.matplotlib.utils import find_matplotlib +from igraph.drawing.plotly.utils import find_plotly +from igraph.drawing.cairo.plot import CairoPlot from igraph.drawing.colors import Palette, palettes -from igraph.drawing.graph import DefaultGraphDrawer, MatplotlibGraphDrawer -from igraph.drawing.utils import ( - BoundingBox, - Point, - Rectangle, - find_cairo, - find_matplotlib, -) -from igraph.utils import _is_running_in_ipython, named_temporary_file - -__all__ = ("BoundingBox", "DefaultGraphDrawer", "Plot", "Point", "Rectangle", "plot") - -cairo = find_cairo() - -##################################################################### +from igraph.drawing.cairo.graph import CairoGraphDrawer +from igraph.drawing.cairo.matrix import CairoMatrixDrawer +from igraph.drawing.cairo.histogram import CairoHistogramDrawer +from igraph.drawing.cairo.palette import CairoPaletteDrawer +from igraph.drawing.matplotlib.graph import MatplotlibGraphDrawer +from igraph.drawing.matplotlib.matrix import MatplotlibMatrixDrawer +from igraph.drawing.matplotlib.histogram import MatplotlibHistogramDrawer +from igraph.drawing.matplotlib.palette import MatplotlibPaletteDrawer +from igraph.drawing.plotly.graph import PlotlyGraphDrawer + +from igraph.drawing.utils import BoundingBox, Point, Rectangle +from igraph.utils import _is_running_in_ipython + +__all__ = ( + "BoundingBox", + "CairoGraphDrawer", + "MatplotlibGraphDrawer", + "DefaultGraphDrawer", + "Plot", + "Point", + "Rectangle", + "plot", + "DrawerDirectory", +) -class Plot: - """Class representing an arbitrary plot - - Every plot has an associated surface object where the plotting is done. The - surface is an instance of C{cairo.Surface}, a member of the C{pycairo} - library. The surface itself provides a unified API to various plotting - targets like SVG files, X11 windows, PostScript files, PNG files and so on. - C{igraph} usually does not know on which surface it is plotting right now, - since C{pycairo} takes care of the actual drawing. Everything that's supported - by C{pycairo} should be supported by this class as well. - - Current Cairo surfaces include: - - - C{cairo.GlitzSurface} -- OpenGL accelerated surface for the X11 - Window System. - - - C{cairo.ImageSurface} -- memory buffer surface. Can be written to a - C{PNG} image file. - - - C{cairo.PDFSurface} -- PDF document surface. - - - C{cairo.PSSurface} -- PostScript document surface. - - - C{cairo.SVGSurface} -- SVG (Scalable Vector Graphics) document surface. - - - C{cairo.Win32Surface} -- Microsoft Windows screen rendering. +# TODO: deprecate +Plot = CairoPlot - - C{cairo.XlibSurface} -- X11 Window System screen rendering. +# TODO: deprecate +DefaultGraphDrawer = CairoGraphDrawer - If you create a C{Plot} object with a string given as the target surface, - the string will be treated as a filename, and its extension will decide - which surface class will be used. Please note that not all surfaces might - be available, depending on your C{pycairo} installation. - A C{Plot} has an assigned default palette (see L{igraph.drawing.colors.Palette}) - which is used for plotting objects. +class DrawerDirectory: + """Static class that finds the object/backend drawer - A C{Plot} object also has a list of objects to be plotted with their - respective bounding boxes, palettes and opacities. Palettes assigned - to an object override the default palette of the plot. Objects can be - added by the L{Plot.add} method and removed by the L{Plot.remove} method. + This directory is used by the __plot__ functions. """ - - def __init__(self, target=None, bbox=None, palette=None, background=None): - """Creates a new plot. - - @param target: the target surface to write to. It can be one of the - following types: - - - C{None} -- an appropriate surface will be created and the object - will be plotted there. - - - C{cairo.Surface} -- the given Cairo surface will be used. - - - C{string} -- a file with the given name will be created and an - appropriate Cairo surface will be attached to it. - - @param bbox: the bounding box of the surface. It is interpreted - differently with different surfaces: PDF and PS surfaces will - treat it as points (1 point = 1/72 inch). Image surfaces will - treat it as pixels. SVG surfaces will treat it as an abstract - unit, but it will mostly be interpreted as pixels when viewing - the SVG file in Firefox. - - @param palette: the palette primarily used on the plot if the - added objects do not specify a private palette. Must be either - an L{igraph.drawing.colors.Palette} object or a string referring - to a valid key of C{igraph.drawing.colors.palettes} (see module - L{igraph.drawing.colors}) or C{None}. In the latter case, the default - palette given by the configuration key C{plotting.palette} is used. - - @param background: the background color. If C{None}, the background - will be transparent. You can use any color specification here that - is understood by L{igraph.drawing.colors.color_name_to_rgba}. - """ - self._filename = None - self._surface_was_created = not isinstance(target, cairo.Surface) - self._need_tmpfile = False - - # Several Windows-specific hacks will be used from now on, thanks - # to Dale Hunscher for debugging and fixing all that stuff - self._windows_hacks = "Windows" in platform.platform() - - if bbox is None: - self.bbox = BoundingBox(600, 600) - elif isinstance(bbox, tuple) or isinstance(bbox, list): - self.bbox = BoundingBox(bbox) - else: - self.bbox = bbox - - if palette is None: - config = Configuration.instance() - palette = config["plotting.palette"] - if not isinstance(palette, Palette): - palette = palettes[palette] - self._palette = palette - - if target is None: - self._need_tmpfile = True - self._surface = cairo.ImageSurface( - cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) - ) - elif isinstance(target, cairo.Surface): - self._surface = target - else: - self._filename = target - _, ext = os.path.splitext(target) - ext = ext.lower() - if ext == ".pdf": - self._surface = cairo.PDFSurface( - target, self.bbox.width, self.bbox.height - ) - elif ext == ".ps" or ext == ".eps": - self._surface = cairo.PSSurface( - target, self.bbox.width, self.bbox.height - ) - elif ext == ".png": - self._surface = cairo.ImageSurface( - cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) - ) - elif ext == ".svg": - self._surface = cairo.SVGSurface( - target, self.bbox.width, self.bbox.height - ) - else: - raise ValueError("image format not handled by Cairo: %s" % ext) - - self._ctx = cairo.Context(self._surface) - self._objects = [] - self._is_dirty = False - - self.background = background - - def add(self, obj, bbox=None, palette=None, opacity=1.0, *args, **kwds): - """Adds an object to the plot. - - Arguments not specified here are stored and passed to the object's - plotting function when necessary. Since you are most likely interested - in the arguments acceptable by graphs, see L{Graph.__plot__} for more - details. - - @param obj: the object to be added - @param bbox: the bounding box of the object. If C{None}, the object - will fill the entire area of the plot. - @param palette: the color palette used for drawing the object. If the - object tries to get a color assigned to a positive integer, it - will use this palette. If C{None}, defaults to the global palette - of the plot. - @param opacity: the opacity of the object being plotted, in the range - 0.0-1.0 - - @see: Graph.__plot__ - """ - if opacity < 0.0 or opacity > 1.0: - raise ValueError("opacity must be between 0.0 and 1.0") - if bbox is None: - bbox = self.bbox - if not isinstance(bbox, BoundingBox): - bbox = BoundingBox(bbox) - self._objects.append((obj, bbox, palette, opacity, args, kwds)) - self.mark_dirty() - - @property - def background(self): - """Returns the background color of the plot. C{None} means a - transparent background. - """ - return self._background - - @background.setter - def background(self, color): - """Sets the background color of the plot. C{None} means a - transparent background. You can use any color specification here - that is understood by the C{get} method of the current palette - or by L{igraph.drawing.colors.color_name_to_rgb}. - """ - if color is None: - self._background = None - else: - self._background = self._palette.get(color) - - def remove(self, obj, bbox=None, idx=1): - """Removes an object from the plot. - - If the object has been added multiple times and no bounding box - was specified, it removes the instance which occurs M{idx}th - in the list of identical instances of the object. - - @param obj: the object to be removed - @param bbox: optional bounding box specification for the object. - If given, only objects with exactly this bounding box will be - considered. - @param idx: if multiple objects match the specification given by - M{obj} and M{bbox}, only the M{idx}th occurrence will be removed. - @return: C{True} if the object has been removed successfully, - C{False} if the object was not on the plot at all or M{idx} - was larger than the count of occurrences - """ - for i in range(len(self._objects)): - current_obj, current_bbox = self._objects[i][0:2] - if current_obj is obj and (bbox is None or current_bbox == bbox): - idx -= 1 - if idx == 0: - self._objects[i : (i + 1)] = [] - self.mark_dirty() - return True - return False - - def mark_dirty(self): - """Marks the plot as dirty (should be redrawn)""" - self._is_dirty = True - - def redraw(self, context=None): - """Redraws the plot""" - ctx = context or self._ctx - if self._background is not None: - ctx.set_source_rgba(*self._background) - ctx.rectangle(0, 0, self.bbox.width, self.bbox.height) - ctx.fill() - - for obj, bbox, palette, opacity, args, kwds in self._objects: - if palette is None: - palette = getattr(obj, "_default_palette", self._palette) - plotter = getattr(obj, "__plot__", None) - if plotter is None: - warn("%s does not support plotting" % (obj,)) - else: - if opacity < 1.0: - ctx.push_group() - else: - ctx.save() - plotter(ctx, bbox, palette, *args, **kwds) - if opacity < 1.0: - ctx.pop_group_to_source() - ctx.paint_with_alpha(opacity) - else: - ctx.restore() - - self._is_dirty = False - - def save(self, fname=None): - """Saves the plot. - - @param fname: the filename to save to. It is ignored if the surface - of the plot is not an C{ImageSurface}. + valid_backends = ('cairo', 'matplotlib') + valid_objects = ( + 'Graph', + 'Matrix', + 'Histogram', + 'Palette', + ) + known_drawers = { + 'cairo': { + 'Graph': CairoGraphDrawer, + 'Matrix': CairoMatrixDrawer, + 'Histogram': CairoHistogramDrawer, + 'Palette': CairoPaletteDrawer, + + }, + 'matplotlib': { + 'Graph': MatplotlibGraphDrawer, + 'Matrix': MatplotlibMatrixDrawer, + 'Histogram': MatplotlibHistogramDrawer, + 'Palette': MatplotlibPaletteDrawer, + }, + 'plotly': { + 'Graph': PlotlyGraphDrawer, + }, + } + + @classmethod + def resolve(cls, obj, backend): + """Given a shape name, returns the corresponding shape drawer class + + @param: obj: an instance of the object to plot + @param backend: the name of the backend + @return: the corresponding shape drawer class + + @raise ValueError: if no drawer is available for this backend/object """ - if self._is_dirty: - self.redraw() - if isinstance(self._surface, cairo.ImageSurface): - if fname is None and self._need_tmpfile: - with named_temporary_file(prefix="igraph", suffix=".png") as fname: - self._surface.write_to_png(fname) - return None - - fname = fname or self._filename - if fname is None: - raise ValueError( - "no file name is known for the surface " + "and none given" - ) - return self._surface.write_to_png(fname) - - if fname is not None: - warn("filename is ignored for surfaces other than ImageSurface") - - self._ctx.show_page() - self._surface.finish() - - def show(self): - """Saves the plot to a temporary file and shows it. - - This method is deprecated from python-igraph 0.9.1 and will be removed in - version 0.10.0. + object_name = str(obj.__class__).split('.')[-1].strip("<'>") - @deprecated: Opening an image viewer with a temporary file never worked - reliably across platforms. - """ - warn("Plot.show() is deprecated from python-igraph 0.9.1", DeprecationWarning) - - if not isinstance(self._surface, cairo.ImageSurface): - sur = cairo.ImageSurface( - cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) - ) - ctx = cairo.Context(sur) - self.redraw(ctx) - else: - sur = self._surface - ctx = self._ctx - if self._is_dirty: - self.redraw(ctx) - - with named_temporary_file(prefix="igraph", suffix=".png") as tmpfile: - sur.write_to_png(tmpfile) - config = Configuration.instance() - imgviewer = config["apps.image_viewer"] - if not imgviewer: - # No image viewer was given and none was detected. This - # should only happen on unknown platforms. - plat = platform.system() - raise NotImplementedError( - "showing plots is not implemented on this platform: %s" % plat + try: + return cls.known_drawers[backend][object_name] + except KeyError: + raise ValueError( + f"unknown drawer for {object_name} and backend {backend}", ) - else: - os.system("%s %s" % (imgviewer, tmpfile)) - if platform.system() == "Darwin" or self._windows_hacks: - # On Mac OS X and Windows, launched applications are likely to - # fork and give control back to Python immediately. - # Chances are that the temporary image file gets removed - # before the image viewer has a chance to open it, so - # we wait here a little bit. Yes, this is quite hackish :( - time.sleep(5) - - def _repr_svg_(self): - """Returns an SVG representation of this plot as a string. - - This method is used by IPython to display this plot inline. - """ - io = BytesIO() - # Create a new SVG surface and use that to get the SVG representation, - # which will end up in io - surface = cairo.SVGSurface(io, self.bbox.width, self.bbox.height) - context = cairo.Context(surface) - # Plot the graph on this context - self.redraw(context) - # No idea why this is needed but python crashes without - context.show_page() - surface.finish() - # Return the raw SVG representation - result = io.getvalue().decode("utf-8") - return result, {"isolated": True} # put it inside an iframe - - @property - def bounding_box(self): - """Returns the bounding box of the Cairo surface as a - L{BoundingBox} object""" - return BoundingBox(self.bbox) - - @property - def height(self): - """Returns the height of the Cairo surface on which the plot - is drawn""" - return self.bbox.height - - @property - def surface(self): - """Returns the Cairo surface on which the plot is drawn""" - return self._surface - - @property - def width(self): - """Returns the width of the Cairo surface on which the plot - is drawn""" - return self.bbox.width - - -##################################################################### def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @@ -424,10 +141,9 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): refer to a PNG image, an arbitrary window, an SVG file, anything that Cairo can handle. - - C{None} -- a temporary file will be created and the object will be - plotted there. igraph will attempt to open an image viewer and show - the temporary file. This feature is deprecated from python-igraph - version 0.9.1 and will be removed in 0.10.0. + - C{None} -- no plotting will be performed; igraph simply returns a + CairoPlot_ object that you can use to manipulate the plot and save it + to a file later. @param bbox: the bounding box of the plot. It must be a tuple with either two or four integers, or a L{BoundingBox} object. If this is a tuple @@ -436,14 +152,14 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): SVG and PostScript plots, where 72 pt = 1 inch = 2.54 cm). If this is a tuple with four integers, the first two denotes the X and Y coordinates of a corner and the latter two denoting the X and Y coordinates of the - opposite corner. + opposite corner. Ignored for Matplotlib plots. @keyword opacity: the opacity of the object being plotted. It can be used to overlap several plots of the same graph if you use the same layout for them -- for instance, you might plot a graph with opacity 0.5 and then plot its spanning tree over it with opacity 0.1. To achieve this, you'll need to modify the L{Plot} object returned with - L{Plot.add}. + L{Plot.add}. Ignored for Matplotlib plots. @keyword palette: the palette primarily used on the plot if the added objects do not specify a private palette. Must be either @@ -455,7 +171,7 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @keyword margin: the top, right, bottom, left margins as a 4-tuple. If it has less than 4 elements or is a single float, the elements will be re-used until the length is at least 4. The default margin - is 20 on each side. + is 20 units on each side. Ignored for Matplotlib plots. @keyword inline: whether to try and show the plot object inline in the current IPython notebook. Passing C{None} here or omitting this keyword @@ -464,55 +180,102 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): argument has an effect only if igraph is run inside IPython and C{target} is C{None}. - @return: an appropriate L{Plot} object. + @return: an appropriate L{CairoPlot} object for the Cairo backend or the + Matplotlib C{Axes} object for the Matplotlib backend @see: Graph.__plot__ """ + + VALID_BACKENDS = ("cairo", "matplotlib", "plotly") + _, plt = find_matplotlib() + cairo = find_cairo() + plotly = find_plotly() + # Switch backend based on target (first) and config (second) if hasattr(plt, "Axes") and isinstance(target, plt.Axes): - result = MatplotlibGraphDrawer(ax=target) - result.draw(obj, *args, **kwds) - return + backend = "matplotlib" + elif hasattr(plotly, "graph_objects") and isinstance( + target, plotly.graph_objects.Figure): + backend = "plotly" + elif hasattr(cairo, "Surface") and isinstance(target, cairo.Surface): + backend = "cairo" + else: + backend = Configuration.instance()["plotting.backend"] - if not isinstance(bbox, BoundingBox): - bbox = BoundingBox(bbox) + if backend not in VALID_BACKENDS: + raise ValueError("unknown plotting backend: {0!r}".format(backend)) - result = Plot(target, bbox, background=kwds.get("background", "white")) + if backend in ("matplotlib", "plotly"): + # Choose palette + # If explicit, use it. If not or None, ask the object: None is an + # acceptable response from the object (e.g. for clusterings), it means + # the palette is handled internally. If no response, default to config. + palette = kwds.pop("palette", None) + if palette is None: + palette = getattr( + obj, + "_default_palette", + Configuration.instance()["plotting.palette"], + ) + if palette is not None and not isinstance(palette, Palette): + palette = palettes[palette] - if "margin" in kwds: - bbox = bbox.contract(kwds["margin"]) - del kwds["margin"] - else: - bbox = bbox.contract(20) - result.add(obj, bbox, *args, **kwds) + if target is None: + if backend == "matplotlib": + # Create a new axes if needed + _, target = plt.subplots() + + elif backend == "plotly": + # Create a new figure if needed + target = plotly.graph_objects.Figure() + + # Get the plotting function from the object + plotter = getattr(obj, "__plot__", None) + if plotter is None: + warn("%s does not support plotting" % (obj,)) + return + else: + plotter( + backend, + target, + palette=palette, + *args, + **kwds, + ) + return target + # Cairo backend + inline = False if target is None and _is_running_in_ipython(): - # Get the default value of the `inline` argument from the configuration if - # needed inline = kwds.get("inline") if inline is None: - config = Configuration.instance() - inline = config["shell.ipython.inlining.Plot"] - - # If we requested an inline plot, just return the result and IPython will - # call its _repr_svg_ method. If we requested a non-inline plot, show the - # plot in a separate window and return nothing - if inline: - return result - else: - result.show() - return + inline = Configuration.instance()["shell.ipython.inlining.Plot"] + + palette = kwds.pop("palette", None) + background = kwds.pop("background", "white") + margin = float(kwds.pop("margin", 20)) + result = CairoPlot( + target=target, + bbox=bbox, + palette=palette, + background=background, + ) + item_bbox = result.bbox.contract(margin) + result.add(obj, item_bbox, *args, **kwds) + + # If we requested an inline plot, just return the result and IPython will + # call its _repr_svg_ method. If we requested a non-inline plot, show the + # plot in a separate window and return nothing + if inline: + return result # We are either not in IPython or the user specified an explicit plot target, # so just show or save the result - if target is None: - result.show() - elif isinstance(target, str): + + if isinstance(target, (str, Path)): + # save result.save() # Also return the plot itself return result - - -##################################################################### diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index d434f7b75..e786b064d 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -2,91 +2,22 @@ Abstract base classes for the drawing routines. """ -from igraph.drawing.utils import BoundingBox -from math import pi - -##################################################################### - - -class AbstractDrawer: - """Abstract class that serves as a base class for anything that - draws an igraph object.""" - - def draw(self, *args, **kwds): - """Abstract method, must be implemented in derived classes.""" - raise NotImplementedError("abstract class") +from abc import ABCMeta, abstractmethod +from math import atan2, pi +from .text import TextAlignment ##################################################################### -class AbstractCairoDrawer(AbstractDrawer): +class AbstractDrawer(metaclass=ABCMeta): """Abstract class that serves as a base class for anything that - draws on a Cairo context within a given bounding box. - - A subclass of L{AbstractCairoDrawer} is guaranteed to have an - attribute named C{context} that represents the Cairo context - to draw on, and an attribute named C{bbox} for the L{BoundingBox} - of the drawing area. - """ - - def __init__(self, context, bbox): - """Constructs the drawer and associates it to the given - Cairo context and the given L{BoundingBox}. - - @param context: the context on which we will draw - @param bbox: the bounding box within which we will draw. - Can be anything accepted by the constructor - of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple - or a L{BoundingBox} object). - """ - self.context = context - self._bbox = None - self.bbox = bbox - - @property - def bbox(self): - """The bounding box of the drawing area where this drawer will - draw.""" - return self._bbox - - @bbox.setter - def bbox(self, bbox): - """Sets the bounding box of the drawing area where this drawer - will draw.""" - if not isinstance(bbox, BoundingBox): - self._bbox = BoundingBox(bbox) - else: - self._bbox = bbox + draws an igraph object.""" + @abstractmethod def draw(self, *args, **kwds): """Abstract method, must be implemented in derived classes.""" - raise NotImplementedError("abstract class") - - def _mark_point(self, x, y, color=0, size=4): - """Marks the given point with a small circle on the canvas. - Used primarily for debugging purposes. - - @param x: the X coordinate of the point to mark - @param y: the Y coordinate of the point to mark - @param color: the color of the marker. It can be a - 3-tuple (RGB components, alpha=0.5), a 4-tuple - (RGBA components) or an index where zero means red, 1 means - green, 2 means blue and so on. - @param size: the diameter of the marker. - """ - if isinstance(color, int): - colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 1)] - color = colors[color % len(colors)] - if len(color) == 3: - color += (0.5,) - - ctx = self.context - ctx.save() - ctx.set_source_rgba(*color) - ctx.arc(x, y, size / 2.0, 0, 2 * pi) - ctx.fill() - ctx.restore() + raise NotImplementedError ##################################################################### @@ -142,3 +73,255 @@ def _resolve_hostname(url): url_parts = list(url_parts) url_parts[1] = hostname return urlunparse(url_parts) + + +##################################################################### + + +class AbstractEdgeDrawer(metaclass=ABCMeta): + """Abstract edge drawer object from which all concrete edge drawer + implementations are derived. + """ + + @staticmethod + def _curvature_to_float(value): + """Converts values given to the 'curved' edge style argument + in plotting calls to floating point values.""" + if value is None or value is False: + return 0.0 + if value is True: + return 0.5 + return float(value) + + @abstractmethod + def draw_directed_edge(self, edge, src_vertex, dest_vertex): + """Draws a directed edge. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. Visual properties are defined + by the attributes of this object. + @param dest_vertex: the source vertex. Visual properties are defined + by the attributes of this object. + """ + raise NotImplementedError + + @abstractmethod + def draw_undirected_edge(self, edge, src_vertex, dest_vertex): + """Draws an undirected edge. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. Visual properties are defined + by the attributes of this object. + @param dest_vertex: the source vertex. Visual properties are defined + by the attributes of this object. + """ + raise NotImplementedError + + def get_label_position(self, edge, src_vertex, dest_vertex): + """Returns the position where the label of an edge should be drawn. The + default implementation returns the midpoint of the edge and an alignment + that tries to avoid overlapping the label with the edge. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. Visual properties are given + again as attributes. + @param dest_vertex: the target vertex. Visual properties are given + again as attributes. + @return: a tuple containing two more tuples: the desired position of the + label and the desired alignment of the label, where the position is + given as C{(x, y)} and the alignment is given as C{(horizontal, vertical)}. + Members of the alignment tuple are taken from constants in the + L{TextAlignment} class. + """ + # TODO: curved edges don't play terribly well with this function, + # we could try to get the mid point of the actual curved arrow + # (Bezier curve) and use that. + + # Determine the angle of the line + dx = dest_vertex.position[0] - src_vertex.position[0] + dy = dest_vertex.position[1] - src_vertex.position[1] + if dx != 0 or dy != 0: + # Note that we use -dy because the Y axis points downwards + angle = atan2(-dy, dx) % (2 * pi) + else: + angle = None + + # Determine the midpoint + pos = ( + (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, + (src_vertex.position[1] + dest_vertex.position[1]) / 2, + ) + + # Determine the alignment based on the angle + pi4 = pi / 4 + if angle is None: + halign, valign = TextAlignment.CENTER, TextAlignment.CENTER + else: + index = int((angle / pi4) % 8) + halign = [ + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.RIGHT, + TextAlignment.LEFT, + TextAlignment.LEFT, + TextAlignment.LEFT, + TextAlignment.LEFT, + ][index] + valign = [ + TextAlignment.BOTTOM, + TextAlignment.CENTER, + TextAlignment.CENTER, + TextAlignment.TOP, + TextAlignment.TOP, + TextAlignment.CENTER, + TextAlignment.CENTER, + TextAlignment.BOTTOM, + ][index] + + return pos, (halign, valign) + + +##################################################################### + + +class AbstractVertexDrawer(AbstractDrawer): + """Abstract vertex drawer object from which all concrete vertex drawer + implementations are derived.""" + + def __init__(self, palette, layout): + """Constructs the vertex drawer and associates it to the given + palette. + + @param palette: the palette that can be used to map integer + color indices to colors when drawing vertices + @param layout: the layout of the vertices in the graph being drawn + """ + self.layout = layout + self.palette = palette + + @abstractmethod + def draw(self, visual_vertex, vertex, coords): + """Draws the given vertex. + + @param visual_vertex: object specifying the visual properties of the + vertex. Its structure is defined by the VisualVertexBuilder of the + L{CairoGraphDrawer}; see its source code. + @param vertex: the raw igraph vertex being drawn + @param coords: the X and Y coordinates of the vertex as specified by the + layout algorithm, scaled into the bounding box. + """ + raise NotImplementedError + + +##################################################################### + + +class AbstractGraphDrawer(AbstractDrawer): + """Abstract class that serves as a base class for anything that + draws an igraph.Graph. + """ + + @abstractmethod + def draw(self, graph, *args, **kwds): + """Abstract method, must be implemented in derived classes.""" + raise NotImplementedError + + @staticmethod + def ensure_layout(layout, graph=None): + """Helper method that ensures that I{layout} is an instance + of L{Layout}. If it is not, the method will try to convert + it to a L{Layout} according to the following rules: + + - If I{layout} is a string, it is assumed to be a name + of an igraph layout, and it will be passed on to the + C{layout} method of the given I{graph} if I{graph} is + not C{None}. + + - If I{layout} is C{None}, the C{layout} method of + I{graph} will be invoked with no parameters, which + will call the default layout algorithm. + + - Otherwise, I{layout} will be passed on to the constructor + of L{Layout}. This handles lists of lists, lists of tuples + and such. + + If I{layout} is already a L{Layout} instance, it will still + be copied and a copy will be returned. This is because graph + drawers are allowed to transform the layout for their purposes, + and we don't want the transformation to propagate back to the + caller. + """ + from igraph.layout import Layout # avoid circular imports + + if isinstance(layout, Layout): + layout = Layout(layout.coords) + elif isinstance(layout, str) or layout is None: + layout = graph.layout(layout) + else: + layout = Layout(layout) + + return layout + + @staticmethod + def _determine_edge_order(graph, kwds): + """Returns the order in which the edge of the given graph have to be + drawn, assuming that the relevant keyword arguments (C{edge_order} and + C{edge_order_by}) are given in C{kwds} as a dictionary. If neither + C{edge_order} nor C{edge_order_by} is present in C{kwds}, this + function returns C{None} to indicate that the graph drawer is free to + choose the most convenient edge ordering.""" + if "edge_order" in kwds: + # Edge order specified explicitly + return kwds["edge_order"] + + if kwds.get("edge_order_by") is None: + # No edge order specified + return None + + # Order edges by the value of some attribute + edge_order_by = kwds["edge_order_by"] + reverse = False + if isinstance(edge_order_by, tuple): + edge_order_by, reverse = edge_order_by + if isinstance(reverse, str): + reverse = reverse.lower().startswith("desc") + attrs = graph.es[edge_order_by] + edge_order = sorted( + list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) + ) + + return edge_order + + @staticmethod + def _determine_vertex_order(graph, kwds): + """Returns the order in which the vertices of the given graph have to be + drawn, assuming that the relevant keyword arguments (C{vertex_order} and + C{vertex_order_by}) are given in C{kwds} as a dictionary. If neither + C{vertex_order} nor C{vertex_order_by} is present in C{kwds}, this + function returns C{None} to indicate that the graph drawer is free to + choose the most convenient vertex ordering.""" + if "vertex_order" in kwds: + # Vertex order specified explicitly + return kwds["vertex_order"] + + if kwds.get("vertex_order_by") is None: + # No vertex order specified + return None + + # Order vertices by the value of some attribute + vertex_order_by = kwds["vertex_order_by"] + reverse = False + if isinstance(vertex_order_by, tuple): + vertex_order_by, reverse = vertex_order_by + if isinstance(reverse, str): + reverse = reverse.lower().startswith("desc") + attrs = graph.vs[vertex_order_by] + vertex_order = sorted( + list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) + ) + + return vertex_order diff --git a/src/igraph/drawing/cairo/__init__.py b/src/igraph/drawing/cairo/__init__.py new file mode 100644 index 000000000..14142ca42 --- /dev/null +++ b/src/igraph/drawing/cairo/__init__.py @@ -0,0 +1,3 @@ +from .plot import CairoPlot + +__all__ = ("CairoPlot",) diff --git a/src/igraph/drawing/cairo/base.py b/src/igraph/drawing/cairo/base.py new file mode 100644 index 000000000..49ccf358b --- /dev/null +++ b/src/igraph/drawing/cairo/base.py @@ -0,0 +1,84 @@ +from math import pi +from typing import Tuple, Union + +from igraph.drawing.baseclasses import AbstractDrawer +from igraph.drawing.utils import BoundingBox + +__all__ = ("AbstractCairoDrawer",) + + +class AbstractCairoDrawer(AbstractDrawer): + """Abstract class that serves as a base class for anything that + draws on a Cairo context within a given bounding box. + + A subclass of L{AbstractCairoDrawer} is guaranteed to have an + attribute named C{context} that represents the Cairo context + to draw on, and an attribute named C{bbox} for the L{BoundingBox} + of the drawing area. + """ + + _bbox: BoundingBox + + def __init__(self, context, bbox: BoundingBox or None): + """Constructs the drawer and associates it to the given + Cairo context and the given L{BoundingBox}. + + @param context: the context on which we will draw + @param bbox: the bounding box within which we will draw. + Can be anything accepted by the constructor + of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple + or a L{BoundingBox} object). + """ + self.context = context + self._bbox = None # type: ignore + # can be set at drawing time + if bbox is not None: + self.bbox = bbox + + @property + def bbox(self) -> BoundingBox: + """The bounding box of the drawing area where this drawer will + draw.""" + return self._bbox + + @bbox.setter + def bbox(self, bbox): + """Sets the bounding box of the drawing area where this drawer + will draw.""" + if not isinstance(bbox, BoundingBox): + self._bbox = BoundingBox(bbox) + else: + self._bbox = bbox + + def _mark_point( + self, + x: float, + y: float, + color: Union[int, Tuple[float, ...]] = 0, + size: float = 4, + ) -> None: + """Marks the given point with a small circle on the canvas. + Used primarily for debugging purposes. + + @param x: the X coordinate of the point to mark + @param y: the Y coordinate of the point to mark + @param color: the color of the marker. It can be a + 3-tuple (RGB components, alpha=0.5), a 4-tuple + (RGBA components) or an index where zero means red, 1 means + green, 2 means blue and so on. + @param size: the diameter of the marker. + """ + if isinstance(color, int): + colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 1)] + color_tuple = colors[color % len(colors)] + elif len(color) == 3: + color_tuple = color + (0.5,) + else: + color_tuple = color + + ctx = self.context + ctx.save() + ctx.set_source_rgba(*color_tuple) + ctx.arc(x, y, size / 2.0, 0, 2 * pi) + ctx.fill() + ctx.restore() diff --git a/src/igraph/drawing/coord.py b/src/igraph/drawing/cairo/coord.py similarity index 85% rename from src/igraph/drawing/coord.py rename to src/igraph/drawing/cairo/coord.py index fc0626bd8..bebdd69fa 100644 --- a/src/igraph/drawing/coord.py +++ b/src/igraph/drawing/cairo/coord.py @@ -2,7 +2,9 @@ Coordinate systems and related plotting routines """ -from igraph.drawing.baseclasses import AbstractCairoDrawer +from abc import abstractmethod + +from igraph.drawing.cairo.base import AbstractCairoDrawer from igraph.drawing.utils import BoundingBox ##################################################################### @@ -18,29 +20,21 @@ class CoordinateSystem(AbstractCairoDrawer): implement an own coordinate system not present in igraph yet. """ - def __init__(self, context, bbox): - """Initializes the coordinate system. - - @param context: the context on which the coordinate system will - be drawn. - @param bbox: the bounding box that will contain the coordinate - system. - """ - AbstractCairoDrawer.__init__(self, context, bbox) - + @abstractmethod def draw(self): """Draws the coordinate system. This method must be overridden in derived classes. """ - raise NotImplementedError("abstract class") + raise NotImplementedError + @abstractmethod def local_to_context(self, x, y): """Converts local coordinates to the context coordinate system (given by the bounding box). This method must be overridden in derived classes.""" - raise NotImplementedError("abstract class") + raise NotImplementedError class DescartesCoordinateSystem(CoordinateSystem): @@ -59,7 +53,7 @@ def __init__(self, context, bbox, bounds): self._sx, self._sy = None, None self._ox, self._oy, self._ox2, self._oy2 = None, None, None, None - CoordinateSystem.__init__(self, context, bbox) + super().__init__(context, bbox) self.bbox = bbox self.bounds = bounds diff --git a/src/igraph/drawing/cairo/dendrogram.py b/src/igraph/drawing/cairo/dendrogram.py new file mode 100644 index 000000000..27c225ea9 --- /dev/null +++ b/src/igraph/drawing/cairo/dendrogram.py @@ -0,0 +1,247 @@ +"""This module provides a dendrogram drawer for the Cairo backend.""" + +from math import pi + +from igraph.drawing.utils import str_to_orientation + +from .base import AbstractCairoDrawer + +__all__ = ("CairoDendrogramDrawer",) + + +class CairoDendrogramDrawer(AbstractCairoDrawer): + """Default Cairo drawer object for dendrograms.""" + + def __init__(self, context, bbox, palette): + """Constructs the drawer and associates it to the given palette. + + @param context: the context on which we will draw + @param bbox: the bounding box within which we will draw. + Can be anything accepted by the constructor + of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple + or a L{BoundingBox} object). + @param palette: the palette that can be used to map integer + color indices to colors when drawing vertices + """ + AbstractCairoDrawer.__init__(self, context, bbox) + self.palette = palette + + @staticmethod + def _item_box_size(dendro, context, horiz, idx): + """Calculates the amount of space needed for drawing an + individual vertex at the bottom of the dendrogram.""" + if dendro._names is None or dendro._names[idx] is None: + x_bearing, _, _, height, x_advance, _ = context.text_extents("") + else: + x_bearing, _, _, height, x_advance, _ = context.text_extents( + str(dendro._names[idx]) + ) + + if horiz: + return x_advance - x_bearing, height + return height, x_advance - x_bearing + + def _plot_item(self, dendro, context, horiz, idx, x, y): + """Plots a dendrogram item to the given Cairo context + + @param context: the Cairo context we are plotting on + @param horiz: whether the dendrogram is horizontally oriented + @param idx: the index of the item + @param x: the X position of the item + @param y: the Y position of the item + """ + if dendro._names is None or dendro._names[idx] is None: + return + + height = self._item_box_size(dendro, context, True, idx)[1] + if horiz: + context.move_to(x, y + height) + context.show_text(str(dendro._names[idx])) + else: + context.save() + context.translate(x, y) + context.rotate(-pi / 2.0) + context.move_to(0, height) + context.show_text(str(dendro._names[idx])) + context.restore() + + def draw(self, dendro, **kwds): + """Draws the given Dendrogram in a Cairo context. + + @param dendro: the igraph.Dendrogram to plot. + + It accepts the following keyword arguments: + + - C{style}: the style of the plot. C{boolean} is useful for plotting + matrices with boolean (C{True}/C{False} or 0/1) values: C{False} + will be shown with a white box and C{True} with a black box. + C{palette} uses the given palette to represent numbers by colors, + the minimum will be assigned to palette color index 0 and the maximum + will be assigned to the length of the palette. C{None} draws transparent + cell backgrounds only. The default style is C{boolean} (but it may + change in the future). C{None} values in the matrix are treated + specially in both cases: nothing is drawn in the cell corresponding + to C{None}. + + - C{square}: whether the cells of the matrix should be square or not. + Default is C{True}. + + - C{grid_width}: line width of the grid shown on the matrix. If zero or + negative, the grid is turned off. The grid is also turned off if the size + of a cell is less than three times the given line width. Default is C{1}. + Fractional widths are also allowed. + + - C{border_width}: line width of the border drawn around the matrix. + If zero or negative, the border is turned off. Default is C{1}. + + - C{row_names}: the names of the rows + + - C{col_names}: the names of the columns. + + - C{values}: values to be displayed in the cells. If C{None} or + C{False}, no values are displayed. If C{True}, the values come + from the matrix being plotted. If it is another matrix, the + values of that matrix are shown in the cells. In this case, + the shape of the value matrix must match the shape of the + matrix being plotted. + + - C{value_format}: a format string or a callable that specifies how + the values should be plotted. If it is a callable, it must be a + function that expects a single value and returns a string. + Example: C{"%#.2f"} for floating-point numbers with always exactly + two digits after the decimal point. See the Python documentation of + the C{%} operator for details on the format string. If the format + string is not given, it defaults to the C{str} function. + + If only the row names or the column names are given and the matrix + is square-shaped, the same names are used for both column and row + names. + """ + from igraph.layout import Layout + + context = self.context + bbox = self.bbox + + if dendro._names is None: + dendro._names = [str(x) for x in range(dendro._nitems)] + + orientation = str_to_orientation( + kwds.get("orientation", "lr"), reversed_vertical=True + ) + horiz = orientation in ("lr", "rl") + + # Get the font height + font_height = context.font_extents()[2] + + # Calculate space needed for individual items at the + # bottom of the dendrogram + item_boxes = [ + dendro._item_box_size(context, horiz, idx) for idx in range(dendro._nitems) + ] + + # Small correction for cases when the right edge of the labels is + # aligned with the tips of the dendrogram branches + ygap = 2 if orientation == "bt" else 0 + xgap = 2 if orientation == "lr" else 0 + item_boxes = [(x + xgap, y + ygap) for x, y in item_boxes] + + # Calculate coordinates + layout = Layout([(0, 0)] * dendro._nitems, dim=2) + inorder = dendro._traverse_inorder() + if not horiz: + x, y = 0, 0 + for idx, element in enumerate(inorder): + layout[element] = (x, 0) + x += max(font_height, item_boxes[element][0]) + + for id1, id2 in dendro._merges: + y += 1 + layout.append(((layout[id1][0] + layout[id2][0]) / 2.0, y)) + + # Mirror or rotate the layout if necessary + if orientation == "bt": + layout.mirror(1) + else: + x, y = 0, 0 + for idx, element in enumerate(inorder): + layout[element] = (0, y) + y += max(font_height, item_boxes[element][1]) + + for id1, id2 in dendro._merges: + x += 1 + layout.append((x, (layout[id1][1] + layout[id2][1]) / 2.0)) + + # Mirror or rotate the layout if necessary + if orientation == "rl": + layout.mirror(0) + + # Rescale layout to the bounding box + maxw = max(e[0] for e in item_boxes) + maxh = max(e[1] for e in item_boxes) + + # w, h: width and height of the area containing the dendrogram + # tree without the items. + # delta_x, delta_y: displacement of the dendrogram tree + width, height = float(bbox.width), float(bbox.height) + delta_x, delta_y = 0, 0 + if horiz: + width -= maxw + if orientation == "lr": + delta_x = maxw + else: + height -= maxh + if orientation == "tb": + delta_y = maxh + + if horiz: + delta_y += font_height / 2.0 + else: + delta_x += font_height / 2.0 + layout.fit_into( + (delta_x, delta_y, width - delta_x, height - delta_y), + keep_aspect_ratio=False, + ) + + context.save() + + context.translate(bbox.left, bbox.top) + context.set_source_rgb(0.0, 0.0, 0.0) + context.set_line_width(1) + + # Draw items + if horiz: + sgn = 0 if orientation == "rl" else -1 + for idx in range(dendro._nitems): + x = layout[idx][0] + sgn * item_boxes[idx][0] + y = layout[idx][1] - item_boxes[idx][1] / 2.0 + self._plot_item(dendro, context, horiz, idx, x, y) + else: + sgn = 1 if orientation == "bt" else 0 + for idx in range(dendro._nitems): + x = layout[idx][0] - item_boxes[idx][0] / 2.0 + y = layout[idx][1] + sgn * item_boxes[idx][1] + dendro._plot_item(dendro, context, horiz, idx, x, y) + + # Draw dendrogram lines + if not horiz: + for idx, (id1, id2) in enumerate(dendro._merges): + x0, y0 = layout[id1] + x1, y1 = layout[id2] + x2, y2 = layout[idx + dendro._nitems] + context.move_to(x0, y0) + context.line_to(x0, y2) + context.line_to(x1, y2) + context.line_to(x1, y1) + context.stroke() + else: + for idx, (id1, id2) in enumerate(dendro._merges): + x0, y0 = layout[id1] + x1, y1 = layout[id2] + x2, y2 = layout[idx + dendro._nitems] + context.move_to(x0, y0) + context.line_to(x2, y0) + context.line_to(x2, y1) + context.line_to(x1, y1) + context.stroke() + + context.restore() diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/cairo/edge.py similarity index 64% rename from src/igraph/drawing/edge.py rename to src/igraph/drawing/cairo/edge.py index 605b2df5c..68ad84f8c 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/cairo/edge.py @@ -2,49 +2,41 @@ Drawers for various edge styles in graph plots. """ +from math import atan2, cos, pi, sin + +from igraph.drawing.baseclasses import AbstractEdgeDrawer +from igraph.drawing.colors import clamp +from igraph.drawing.metamagic import AttributeCollectorBase +from igraph.drawing.utils import euclidean_distance, intersect_bezier_curve_and_circle + +from .utils import find_cairo + __all__ = ( - "AbstractEdgeDrawer", + "AbstractCairoEdgeDrawer", "AlphaVaryingEdgeDrawer", - "ArrowEdgeDrawer", + "CairoArrowEdgeDrawer", "DarkToLightEdgeDrawer", "LightToDarkEdgeDrawer", "TaperedEdgeDrawer", ) -from igraph.drawing.colors import clamp -from igraph.drawing.metamagic import AttributeCollectorBase -from igraph.drawing.text import TextAlignment -from igraph.drawing.utils import find_cairo -from math import atan2, cos, pi, sin, sqrt - cairo = find_cairo() -class AbstractEdgeDrawer: - """Abstract edge drawer object from which all concrete edge drawer - implementations are derived.""" +class AbstractCairoEdgeDrawer(AbstractEdgeDrawer): + """Cairo-specific abstract edge drawer object.""" def __init__(self, context, palette): """Constructs the edge drawer. @param context: a Cairo context on which the edges will be drawn. - @param palette: the palette that can be used to map integer - color indices to colors when drawing edges + @param palette: the palette that can be used to map integer color + indices to colors when drawing edges """ self.context = context self.palette = palette self.VisualEdgeBuilder = self._construct_visual_edge_builder() - @staticmethod - def _curvature_to_float(value): - """Converts values given to the 'curved' edge style argument - in plotting calls to floating point values.""" - if value is None or value is False: - return 0.0 - if value is True: - return 0.5 - return float(value) - def _construct_visual_edge_builder(self): """Construct the visual edge builder that will collect the visual attributes of an edge when it is being drawn.""" @@ -66,18 +58,6 @@ class VisualEdgeBuilder(AttributeCollectorBase): return VisualEdgeBuilder - def draw_directed_edge(self, edge, src_vertex, dest_vertex): - """Draws a directed edge. - - @param edge: the edge to be drawn. Visual properties of the edge - are defined by the attributes of this object. - @param src_vertex: the source vertex. Visual properties are given - again as attributes. - @param dest_vertex: the target vertex. Visual properties are given - again as attributes. - """ - raise NotImplementedError() - def draw_loop_edge(self, edge, vertex): """Draws a loop edge. @@ -132,69 +112,8 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): ctx.stroke() - def get_label_position(self, edge, src_vertex, dest_vertex): - """Returns the position where the label of an edge should be drawn. The - default implementation returns the midpoint of the edge and an alignment - that tries to avoid overlapping the label with the edge. - - @param edge: the edge to be drawn. Visual properties of the edge - are defined by the attributes of this object. - @param src_vertex: the source vertex. Visual properties are given - again as attributes. - @param dest_vertex: the target vertex. Visual properties are given - again as attributes. - @return: a tuple containing two more tuples: the desired position of the - label and the desired alignment of the label, where the position is - given as C{(x, y)} and the alignment is given as C{(horizontal, vertical)}. - Members of the alignment tuple are taken from constants in the - L{TextAlignment} class. - """ - # Determine the angle of the line - dx = dest_vertex.position[0] - src_vertex.position[0] - dy = dest_vertex.position[1] - src_vertex.position[1] - if dx != 0 or dy != 0: - # Note that we use -dy because the Y axis points downwards - angle = atan2(-dy, dx) % (2 * pi) - else: - angle = None - - # Determine the midpoint - pos = ( - (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, - (src_vertex.position[1] + dest_vertex.position[1]) / 2, - ) - # Determine the alignment based on the angle - pi4 = pi / 4 - if angle is None: - halign, valign = TextAlignment.CENTER, TextAlignment.CENTER - else: - index = int((angle / pi4) % 8) - halign = [ - TextAlignment.RIGHT, - TextAlignment.RIGHT, - TextAlignment.RIGHT, - TextAlignment.RIGHT, - TextAlignment.LEFT, - TextAlignment.LEFT, - TextAlignment.LEFT, - TextAlignment.LEFT, - ][index] - valign = [ - TextAlignment.BOTTOM, - TextAlignment.CENTER, - TextAlignment.CENTER, - TextAlignment.TOP, - TextAlignment.TOP, - TextAlignment.CENTER, - TextAlignment.CENTER, - TextAlignment.BOTTOM, - ][index] - - return pos, (halign, valign) - - -class ArrowEdgeDrawer(AbstractEdgeDrawer): +class CairoArrowEdgeDrawer(AbstractCairoEdgeDrawer): """Edge drawer implementation that draws undirected edges as straight lines and directed edges as arrows. """ @@ -207,65 +126,6 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position (x_src, y_src), (x_dest, y_dest) = src_vertex.position, dest_vertex.position - def bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t): - """Computes the Bezier curve from point (x0,y0) to (x3,y3) - via control points (x1,y1) and (x2,y2) with parameter t. - """ - xt = ( - (1.0 - t) ** 3 * x0 - + 3.0 * t * (1.0 - t) ** 2 * x1 - + 3.0 * t ** 2 * (1.0 - t) * x2 - + t ** 3 * x3 - ) - yt = ( - (1.0 - t) ** 3 * y0 - + 3.0 * t * (1.0 - t) ** 2 * y1 - + 3.0 * t ** 2 * (1.0 - t) * y2 - + t ** 3 * y3 - ) - return xt, yt - - def euclidean_distance(x1, y1, x2, y2): - """Computes the Euclidean distance between points (x1,y1) and (x2,y2).""" - return sqrt((1.0 * x1 - x2) ** 2 + (1.0 * y1 - y2) ** 2) - - def intersect_bezier_circle( - x0, y0, x1, y1, x2, y2, x3, y3, radius, max_iter=10 - ): - """Binary search solver for finding the intersection of a Bezier curve - and a circle centered at the curve's end point. - Returns the x,y of the intersection point. - TODO: implement safeguard to ensure convergence in ALL possible cases. - """ - precision = radius / 20.0 - source_target_distance = euclidean_distance(x0, y0, x3, y3) - radius = float(radius) - t0 = 1.0 - t1 = 1.0 - radius / source_target_distance - - xt1, yt1 = bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) - - distance_t0 = 0 - distance_t1 = euclidean_distance(x3, y3, xt1, yt1) - counter = 0 - while abs(distance_t1 - radius) > precision and counter < max_iter: - if ((distance_t1 - radius) > 0) != ((distance_t0 - radius) > 0): - t_new = (t0 + t1) / 2.0 - else: - if abs(distance_t1 - radius) < abs(distance_t0 - radius): - # If t1 gets us closer to the circumference step in the - # same direction - t_new = t1 + (t1 - t0) / 2.0 - else: - t_new = t1 - (t1 - t0) - t_new = 1 if t_new > 1 else (0 if t_new < 0 else t_new) - t0, t1 = t1, t_new - distance_t0 = distance_t1 - xt1, yt1 = bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) - distance_t1 = euclidean_distance(x3, y3, xt1, yt1) - counter += 1 - return bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t1) - # Draw the edge ctx.set_source_rgba(*edge.color) ctx.set_line_width(edge.width) @@ -286,7 +146,7 @@ def intersect_bezier_circle( # Determine where the edge intersects the circumference of the # vertex shape: Tip of the arrow - x2, y2 = intersect_bezier_circle( + x2, y2 = intersect_bezier_curve_and_circle( x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 ) @@ -386,7 +246,7 @@ def intersect_bezier_circle( ctx.fill() -class TaperedEdgeDrawer(AbstractEdgeDrawer): +class TaperedEdgeDrawer(AbstractCairoEdgeDrawer): """Edge drawer implementation that draws undirected edges as straight lines and directed edges as tapered lines that are wider at the source and narrow at the destination. @@ -427,14 +287,14 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): ctx.fill() -class AlphaVaryingEdgeDrawer(AbstractEdgeDrawer): +class AlphaVaryingEdgeDrawer(AbstractCairoEdgeDrawer): """Edge drawer implementation that draws undirected edges as straight lines and directed edges by varying the alpha value of the specified edge color between the source and the destination. """ - def __init__(self, context, alpha_at_src, alpha_at_dest): - super().__init__(context) + def __init__(self, context, palette, alpha_at_src, alpha_at_dest): + super().__init__(context, palette) self.alpha_at_src = (clamp(float(alpha_at_src), 0.0, 1.0),) self.alpha_at_dest = (clamp(float(alpha_at_dest), 0.0, 1.0),) @@ -468,8 +328,8 @@ class LightToDarkEdgeDrawer(AlphaVaryingEdgeDrawer): interpolated in-between. """ - def __init__(self, context): - super().__init__(context, 0.0, 1.0) + def __init__(self, context, palette): + super().__init__(context, palette, 0.0, 1.0) class DarkToLightEdgeDrawer(AlphaVaryingEdgeDrawer): @@ -480,5 +340,5 @@ class DarkToLightEdgeDrawer(AlphaVaryingEdgeDrawer): interpolated in-between. """ - def __init__(self, context): - super().__init__(context, 1.0, 0.0) + def __init__(self, context, palette): + super().__init__(context, palette, 1.0, 0.0) diff --git a/src/igraph/drawing/cairo/graph.py b/src/igraph/drawing/cairo/graph.py new file mode 100644 index 000000000..d66ce7b36 --- /dev/null +++ b/src/igraph/drawing/cairo/graph.py @@ -0,0 +1,425 @@ +""" +Drawing routines to draw graphs. + +This module contains routines to draw graphs on: + + - Cairo surfaces (L{DefaultGraphDrawer}) + - Matplotlib axes (L{MatplotlibGraphDrawer}) + +It also contains routines to send an igraph graph directly to +(U{Cytoscape}) using the +(U{CytoscapeRPC plugin}), see +L{CytoscapeGraphDrawer}. L{CytoscapeGraphDrawer} can also fetch the current +network from Cytoscape and convert it to igraph format. +""" + +from math import atan2, cos, pi, sin, tan +from warnings import warn + +from igraph._igraph import convex_hull, VertexSeq +from igraph.configuration import Configuration +from igraph.drawing.baseclasses import AbstractGraphDrawer +from igraph.drawing.text import TextAlignment +from igraph.drawing.utils import Point + +from .base import AbstractCairoDrawer +from .edge import CairoArrowEdgeDrawer +from .polygon import CairoPolygonDrawer +from .text import CairoTextDrawer +from .utils import find_cairo +from .vertex import CairoVertexDrawer + +__all__ = ("CairoGraphDrawer",) + +cairo = find_cairo() + +##################################################################### + + +##################################################################### + + +class AbstractCairoGraphDrawer(AbstractGraphDrawer, AbstractCairoDrawer): + """Abstract base class for graph drawers that draw on a Cairo canvas.""" + + def __init__(self, context, bbox): + """Constructs the graph drawer and associates it to the given + Cairo context and the given L{BoundingBox}. + + @param context: the context on which we will draw + @param bbox: the bounding box within which we will draw. + Can be anything accepted by the constructor + of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple + or a L{BoundingBox} object). + """ + AbstractCairoDrawer.__init__(self, context, bbox) + AbstractGraphDrawer.__init__(self) + + +##################################################################### + + +class CairoGraphDrawer(AbstractCairoGraphDrawer): + """Class implementing the default visualisation of a graph. + + The default visualisation of a graph draws the nodes on a 2D plane + according to a given L{Layout}, then draws a straight or curved + edge between nodes connected by edges. This is the visualisation + used when one invokes the L{plot()} function on a L{Graph} object. + + See L{Graph.__plot__()} for the keyword arguments understood by + this drawer.""" + + def __init__( + self, + context, + bbox=None, + vertex_drawer_factory=CairoVertexDrawer, + edge_drawer_factory=CairoArrowEdgeDrawer, + label_drawer_factory=CairoTextDrawer, + ): + """Constructs the graph drawer and associates it to the given + Cairo context and the given L{BoundingBox}. + + @param context: the context on which we will draw + @param bbox: the bounding box within which we will draw. + Can be anything accepted by the constructor + of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple + or a L{BoundingBox} object). + @param vertex_drawer_factory: a factory method that returns an + L{AbstractCairoVertexDrawer} instance bound to a + given Cairo context. The factory method must take + four parameters: the Cairo context, the bounding + box of the drawing area, the palette to be + used for drawing colored vertices, and the graph layout. + The default vertex drawer is L{DefaultVertexDrawer}. + @param edge_drawer_factory: a factory method that returns an + L{AbstractCairoEdgeDrawer} instance bound to a + given Cairo context. The factory method must take + two parameters: the Cairo context and the palette + to be used for drawing colored edges. You can use + any of the actual L{AbstractEdgeDrawer} + implementations here to control the style of + edges drawn by igraph. The default edge drawer is + L{CairoArrowEdgeDrawer}. + @param label_drawer_factory: a factory method that returns a + L{CairoTextDrawer} instance bound to a given Cairo + context. The method must take one parameter: the + Cairo context. The default label drawer is + L{CairoTextDrawer}. + """ + AbstractCairoGraphDrawer.__init__(self, context, bbox) + self.vertex_drawer_factory = vertex_drawer_factory + self.edge_drawer_factory = edge_drawer_factory + self.label_drawer_factory = label_drawer_factory + + def draw(self, graph, *args, **kwds): + # Positional arguments are not used + if args: + warn( + "Positional arguments to plot functions are ignored " + "and will be deprecated soon.", + DeprecationWarning, + ) + + bbox = kwds.pop('bbox', None) + if bbox is None: + raise ValueError('bbox is required for cairo plots') + # Validate it through set/get + self.bbox = bbox + bbox = self.bbox + + # Some abbreviations for sake of simplicity + directed = graph.is_directed() + context = self.context + + # Palette + palette = kwds.pop("palette", None) + + # Calculate/get the layout of the graph + layout = self.ensure_layout(kwds.get("layout", None), graph) + + # Determine the size of the margin on each side + margin = kwds.get("margin", 0) + try: + margin = list(margin) # type: ignore + except TypeError: + margin = [margin] + while len(margin) < 4: + margin.extend(margin) + + # Contract the drawing area by the margin and fit the layout + bbox = self.bbox.contract(margin) + layout.fit_into(bbox, keep_aspect_ratio=kwds.get("keep_aspect_ratio", False)) + + # Decide whether we need to calculate the curvature of edges + # automatically -- and calculate them if needed. + autocurve = kwds.get("autocurve", None) + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in graph.edge_attributes() + and graph.ecount() < 10000 + ): + from igraph import autocurve + + default = kwds.get("edge_curved", 0) + if default is True: + default = 0.5 + default = float(default) + kwds["edge_curved"] = autocurve(graph, attribute=None, default=default) + + # Construct the vertex, edge and label drawers + vertex_drawer = self.vertex_drawer_factory(context, bbox, palette, layout) + edge_drawer = self.edge_drawer_factory(context, palette) + label_drawer = self.label_drawer_factory(context) + + # Construct the visual vertex/edge builders based on the specifications + # provided by the vertex_drawer and the edge_drawer + vertex_builder = vertex_drawer.VisualVertexBuilder(graph.vs, kwds) + edge_builder = edge_drawer.VisualEdgeBuilder(graph.es, kwds) + + # Determine the order in which we will draw the vertices and edges + vertex_order = self._determine_vertex_order(graph, kwds) + edge_order = self._determine_edge_order(graph, kwds) + + # Draw the highlighted groups (if any) + if "mark_groups" in kwds: + mark_groups = kwds["mark_groups"] + + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + # Figure out what to do with mark_groups in order to be able to + # iterate over it and get memberlist-color pairs + if isinstance(mark_groups, dict): + # Dictionary mapping vertex indices or tuples of vertex + # indices to colors + group_iter = iter(mark_groups.items()) + elif isinstance(mark_groups, (VertexClustering, VertexCover)): + # Vertex clustering + group_iter = ((group, color) for color, group in enumerate(mark_groups)) + elif hasattr(mark_groups, "__iter__"): + # Lists, tuples, iterators etc + group_iter = iter(mark_groups) + else: + # False + group_iter = iter({}.items()) + + # We will need a polygon drawer to draw the convex hulls + polygon_drawer = CairoPolygonDrawer(context, bbox) + + # Iterate over color-memberlist pairs + for group, color_id in group_iter: + if not group or color_id is None: + continue + + color = palette.get(color_id) + + if isinstance(group, VertexSeq): + group = [vertex.index for vertex in group] + if not hasattr(group, "__iter__"): + raise TypeError("group membership list must be iterable") + + # Get the vertex indices that constitute the convex hull + hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] + + # Calculate the preferred rounding radius for the corners + corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) + + # Construct the polygon + polygon = [layout[idx] for idx in hull] + + if len(polygon) == 2: + # Expand the polygon (which is a flat line otherwise) + a, b = Point(*polygon[0]), Point(*polygon[1]) + c = corner_radius * (a - b).normalized() + n = Point(-c[1], c[0]) + polygon = [a + n, b + n, b - c, b - n, a - n, a + c] + else: + # Expand the polygon around its center of mass + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] + ) + polygon = [ + Point(*point).towards(center, -corner_radius) + for point in polygon + ] + + # Draw the hull + context.set_source_rgba(color[0], color[1], color[2], color[3] * 0.25) + polygon_drawer.draw_path(polygon, corner_radius=corner_radius) + context.fill_preserve() + context.set_source_rgba(*color) + context.stroke() + + # Construct the iterator that we will use to draw the edges + es = graph.es + if edge_order is None: + # Default edge order + edge_coord_iter = zip(es, edge_builder) + else: + # Specified edge order + edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) + + # Draw the edges + if directed: + drawer_method = edge_drawer.draw_directed_edge + else: + drawer_method = edge_drawer.draw_undirected_edge + for edge, visual_edge in edge_coord_iter: + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + drawer_method(visual_edge, src_vertex, dest_vertex) + + # Construct the iterator that we will use to draw the vertices + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vs, vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ( + (vs[i], vertex_builder[i], layout[i]) for i in vertex_order + ) + + # Draw the vertices + drawer_method = vertex_drawer.draw + context.set_line_width(1) + for vertex, visual_vertex, coords in vertex_coord_iter: + drawer_method(visual_vertex, vertex, coords) + + # Decide whether the labels have to be wrapped + wrap = kwds.get("wrap_labels") + if wrap is None: + wrap = Configuration.instance()["plotting.wrap_labels"] + wrap = bool(wrap) + + # Construct the iterator that we will use to draw the vertex labels + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) + + # Draw the vertex labels + for vertex, coords in vertex_coord_iter: + if vertex.label is None: + continue + + # Set the font family, size, color and text + context.select_font_face( + vertex.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL + ) + context.set_font_size(vertex.label_size) + context.set_source_rgba(*vertex.label_color) + label_drawer.text = vertex.label + + if vertex.label_dist: + # Label is displaced from the center of the vertex. + _, yb, w, h, _, _ = label_drawer.text_extents() + w, h = w / 2.0, h / 2.0 + radius = vertex.label_dist * vertex.size / 2.0 + # First we find the reference point that is at distance `radius' + # from the vertex in the direction given by `label_angle'. + # Then we place the label in a way that the line connecting the + # center of the bounding box of the label with the center of the + # vertex goes through the reference point and the reference + # point lies exactly on the bounding box of the vertex. + alpha = vertex.label_angle % (2 * pi) + cx = coords[0] + radius * cos(alpha) + cy = coords[1] - radius * sin(alpha) + # Now we have the reference point. We have to decide which side + # of the label box will intersect with the line that connects + # the center of the label with the center of the vertex. + if w > 0: + beta = atan2(h, w) % (2 * pi) + else: + beta = pi / 2.0 + gamma = pi - beta + if alpha > 2 * pi - beta or alpha <= beta: + # Intersection at left edge of label + cx += w + cy -= tan(alpha) * w + elif alpha > beta and alpha <= gamma: + # Intersection at bottom edge of label + try: + cx += h / tan(alpha) + except Exception: + pass # tan(alpha) == inf + cy -= h + elif alpha > gamma and alpha <= gamma + 2 * beta: + # Intersection at right edge of label + cx -= w + cy += tan(alpha) * w + else: + # Intersection at top edge of label + try: + cx -= h / tan(alpha) + except Exception: + pass # tan(alpha) == inf + cy += h + # Draw the label + label_drawer.draw_at(cx - w, cy - h - yb, wrap=wrap) + else: + # Label is exactly in the center of the vertex + cx, cy = coords + half_size = vertex.size / 2.0 + label_drawer.bbox = ( + cx - half_size, + cy - half_size, + cx + half_size, + cy + half_size, + ) + label_drawer.draw(wrap=wrap) + + # Construct the iterator that we will use to draw the edge labels + es = graph.es + if edge_order is None: + # Default edge order + edge_coord_iter = zip(es, edge_builder) + else: + # Specified edge order + edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) + + # Draw the edge labels + for edge, visual_edge in edge_coord_iter: + if visual_edge.label is None: + continue + + # Set the font family, size, color and text + context.select_font_face( + visual_edge.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL + ) + context.set_font_size(visual_edge.label_size) + context.set_source_rgba(*visual_edge.label_color) + label_drawer.text = visual_edge.label + + # Ask the edge drawer to propose an anchor point for the label + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + (x, y), (halign, valign) = edge_drawer.get_label_position( + edge, src_vertex, dest_vertex + ) + + # Measure the text + _, yb, w, h, _, _ = label_drawer.text_extents() + w /= 2.0 + h /= 2.0 + + # Place the text relative to the edge + if halign == TextAlignment.RIGHT: + x -= w + elif halign == TextAlignment.LEFT: + x += w + if valign == TextAlignment.BOTTOM: + y -= h - yb / 2.0 + elif valign == TextAlignment.TOP: + y += h + + # Draw the edge label + label_drawer.halign = halign + label_drawer.valign = valign + label_drawer.bbox = (x - w, y - h, x + w, y + h) + label_drawer.draw(wrap=wrap) diff --git a/src/igraph/drawing/cairo/histogram.py b/src/igraph/drawing/cairo/histogram.py new file mode 100644 index 000000000..de984fe8e --- /dev/null +++ b/src/igraph/drawing/cairo/histogram.py @@ -0,0 +1,59 @@ +"""This module provides implementation for a Cairo-specific histogram drawer""" + +from igraph.drawing.cairo.base import AbstractCairoDrawer + +__all__ = ("CairoHistogramDrawer",) + + +class CairoHistogramDrawer(AbstractCairoDrawer): + """Default Cairo drawer object for histograms""" + + def __init__(self, context): + """Constructs the vertex drawer and associates it to the given + palette. + + @param context: the context on which we will draw + """ + super().__init__(context, bbox=None) + + def draw(self, histogram, **kwds): + """TODO""" + from igraph.drawing.cairo.coord import DescartesCoordinateSystem + + context = self.context + + bbox = self.bbox = kwds.pop('bbox', None) + if bbox is None: + raise ValueError('bbox is required for cairo plots') + + xmin = kwds.get("min", self._min) + ymin = 0 + xmax = kwds.get("max", self._max) + ymax = kwds.get("max_value", max(self._bins)) + width = self._bin_width + + coord_system = DescartesCoordinateSystem( + context, + bbox, + (xmin, ymin, xmax, ymax), + ) + + # Draw the boxes + context.set_line_width(1) + context.set_source_rgb(1.0, 0.0, 0.0) + x = self._min + for value in self._bins: + top_left_x, top_left_y = coord_system.local_to_context(x, value) + x += width + bottom_right_x, bottom_right_y = coord_system.local_to_context(x, 0) + context.rectangle( + top_left_x, + top_left_y, + bottom_right_x - top_left_x, + bottom_right_y - top_left_y, + ) + context.fill() + + # Draw the axes + coord_system.draw() + diff --git a/src/igraph/drawing/cairo/matrix.py b/src/igraph/drawing/cairo/matrix.py new file mode 100644 index 000000000..a5e506bda --- /dev/null +++ b/src/igraph/drawing/cairo/matrix.py @@ -0,0 +1,250 @@ +"""This module provides implementation for a Cairo-specific matrix drawer.""" + +from itertools import islice +from math import pi + +from igraph.drawing.cairo.base import AbstractCairoDrawer + +__all__ = ("CairoMatrixDrawer",) + + +class CairoMatrixDrawer(AbstractCairoDrawer): + """Default Cairo drawer object for matrices.""" + + def __init__(self, context): + """Constructs the vertex drawer and associates it to the given + palette. + + @param context: the context on which we will draw + """ + super().__init__(context, bbox=None) + + def draw(self, matrix, **kwds): + """Draws the given Matrix in a Cairo context. + + @param matrix: the igraph.Matrix to plot. + + It accepts the following keyword arguments: + + - C{bbox}: the bounding box within which we will draw. + Can be anything accepted by the constructor of L{BoundingBox} + (i.e., a 2-tuple, a 4-tuple or a L{BoundingBox} object). + + - C{palette}: the palette that can be used to map integer color + indices to colors when drawing vertices + + - C{style}: the style of the plot. C{boolean} is useful for plotting + matrices with boolean (C{True}/C{False} or 0/1) values: C{False} + will be shown with a white box and C{True} with a black box. + C{palette} uses the given palette to represent numbers by colors, + the minimum will be assigned to palette color index 0 and the maximum + will be assigned to the length of the palette. C{None} draws transparent + cell backgrounds only. The default style is C{boolean} (but it may + change in the future). C{None} values in the matrix are treated + specially in both cases: nothing is drawn in the cell corresponding + to C{None}. + + - C{square}: whether the cells of the matrix should be square or not. + Default is C{True}. + + - C{grid_width}: line width of the grid shown on the matrix. If zero or + negative, the grid is turned off. The grid is also turned off if the size + of a cell is less than three times the given line width. Default is C{1}. + Fractional widths are also allowed. + + - C{border_width}: line width of the border drawn around the matrix. + If zero or negative, the border is turned off. Default is C{1}. + + - C{row_names}: the names of the rows + + - C{col_names}: the names of the columns. + + - C{values}: values to be displayed in the cells. If C{None} or + C{False}, no values are displayed. If C{True}, the values come + from the matrix being plotted. If it is another matrix, the + values of that matrix are shown in the cells. In this case, + the shape of the value matrix must match the shape of the + matrix being plotted. + + - C{value_format}: a format string or a callable that specifies how + the values should be plotted. If it is a callable, it must be a + function that expects a single value and returns a string. + Example: C{"%#.2f"} for floating-point numbers with always exactly + two digits after the decimal point. See the Python documentation of + the C{%} operator for details on the format string. If the format + string is not given, it defaults to the C{str} function. + + If only the row names or the column names are given and the matrix + is square-shaped, the same names are used for both column and row + names. + """ + context = self.context + Matrix = matrix.__class__ + + bbox = self.bbox = kwds.pop("bbox", None) + palette = kwds.pop("palette", None) + if bbox is None: + raise ValueError("bbox is required for Cairo plots") + if palette is None: + raise ValueError("palette is required for Cairo plots") + + grid_width = float(kwds.get("grid_width", 1.0)) + border_width = float(kwds.get("border_width", 1.0)) + style = kwds.get("style", "boolean") + row_names = kwds.get("row_names") + col_names = kwds.get("col_names", row_names) + values = kwds.get("values") + value_format = kwds.get("value_format", str) + + # Validations + if style not in ("boolean", "palette", "none", None): + raise ValueError("invalid style") + if style == "none": + style = None + if row_names is None and col_names is not None: + row_names = col_names + if row_names is not None: + row_names = [str(name) for name in islice(row_names, matrix._nrow)] + if len(row_names) < matrix._nrow: + row_names.extend([""] * (matrix._nrow - len(row_names))) + if col_names is not None: + col_names = [str(name) for name in islice(col_names, matrix._ncol)] + if len(col_names) < matrix._ncol: + col_names.extend([""] * (matrix._ncol - len(col_names))) + if values is False: + values = None + if values is True: + values = matrix + if isinstance(values, list): + values = Matrix(list) + if values is not None and not isinstance(values, Matrix): + raise TypeError("values must be None, False, True or a matrix") + if values is not None and values.shape != matrix.shape: + raise ValueError("values must be a matrix of size %s" % matrix.shape) + + # Calculate text extents if needed + if row_names is not None or col_names is not None: + te = context.text_extents + space_width = te(" ")[4] + if row_names is not None: + max_row_name_width = max([te(s)[4] for s in row_names]) + space_width + else: + max_row_name_width = 0 + if col_names is not None: + max_col_name_width = max([te(s)[4] for s in col_names]) + space_width + else: + max_col_name_width = 0 + else: + max_row_name_width, max_col_name_width = 0, 0 + space_width = 0 + + # Calculate sizes + total_width = float(bbox.width) - max_row_name_width + total_height = float(bbox.height) - max_col_name_width + dx = total_width / matrix.shape[1] + dy = total_height / matrix.shape[0] + if kwds.get("square", True): + dx, dy = min(dx, dy), min(dx, dy) + total_width, total_height = dx * matrix.shape[1], dy * matrix.shape[0] + ox = bbox.left + (bbox.width - total_width - max_row_name_width) / 2.0 + oy = bbox.top + (bbox.height - total_height - max_col_name_width) / 2.0 + ox += max_row_name_width + oy += max_col_name_width + + # Determine rescaling factors for the palette if needed + if style == "palette": + mi, ma = matrix.min(), matrix.max() + color_offset = mi + color_ratio = (len(palette) - 1) / float(ma - mi) + else: + color_offset, color_ratio = 0, 1 + + # Validate grid width + if dx < 3 * grid_width or dy < 3 * grid_width: + grid_width = 0.0 + if grid_width > 0: + context.set_line_width(grid_width) + else: + # When the grid width is zero, we will still stroke the + # rectangles, but with the same color as the fill color + # of the cell - otherwise we would get thin white lines + # between the cells as a drawing artifact + context.set_line_width(1) + + # Draw row names (if any) + context.set_source_rgb(0.0, 0.0, 0.0) + if row_names is not None: + x, y = ox, oy + for heading in row_names: + _, _, _, h, xa, _ = context.text_extents(heading) + context.move_to(x - xa - space_width, y + (dy + h) / 2.0) + context.show_text(heading) + y += dy + + # Draw column names (if any) + if col_names is not None: + context.save() + context.translate(ox, oy) + context.rotate(-pi / 2) + x, y = 0.0, 0.0 + for heading in col_names: + _, _, _, h, _, _ = context.text_extents(heading) + context.move_to(x + space_width, y + (dx + h) / 2.0) + context.show_text(heading) + y += dx + context.restore() + + # Draw matrix + x, y = ox, oy + if style is None: + fill = lambda: None # noqa: E731 + else: + fill = context.fill_preserve + for row in matrix: + for item in row: + if item is None: + x += dx + continue + if style == "boolean": + if item: + context.set_source_rgb(0.0, 0.0, 0.0) + else: + context.set_source_rgb(1.0, 1.0, 1.0) + elif style == "palette": + cidx = int((item - color_offset) * color_ratio) + if cidx < 0: + cidx = 0 + context.set_source_rgba(*palette.get(cidx)) + context.rectangle(x, y, dx, dy) + if grid_width > 0: + fill() + context.set_source_rgb(0.5, 0.5, 0.5) + context.stroke() + else: + fill() + context.stroke() + x += dx + x, y = ox, y + dy + + # Draw cell values + if values is not None: + x, y = ox, oy + context.set_source_rgb(0.0, 0.0, 0.0) + for row in values.data: + if hasattr(value_format, "__call__"): + values = [value_format(item) for item in row] + else: + values = [value_format % item for item in row] + for item in values: + th, tw = context.text_extents(item)[3:5] + context.move_to(x + (dx - tw) / 2.0, y + (dy + th) / 2.0) + context.show_text(item) + x += dx + x, y = ox, y + dy + + # Draw borders + if border_width > 0: + context.set_line_width(border_width) + context.set_source_rgb(0.0, 0.0, 0.0) + context.rectangle(ox, oy, dx * matrix.shape[1], dy * matrix.shape[0]) + context.stroke() diff --git a/src/igraph/drawing/cairo/palette.py b/src/igraph/drawing/cairo/palette.py new file mode 100644 index 000000000..9c0e67a16 --- /dev/null +++ b/src/igraph/drawing/cairo/palette.py @@ -0,0 +1,53 @@ +"""This module provides implementation for a Cairo-specific palette drawer""" + +from igraph.drawing.cairo.base import AbstractCairoDrawer + +__all__ = ("CairoPaletteDrawer",) + + +class CairoPaletteDrawer(AbstractCairoDrawer): + """Default Cairo drawer object for palettes""" + + def __init__(self, context): + """Constructs the vertex drawer and associates it to the given + palette. + + @param context: the context on which we will draw + """ + super().__init__(context, bbox=None) + + def draw(self, palette, **kwds): + """TODO""" + from igraph.datatypes import Matrix + from igraph.drawing.utils import str_to_orientation + + context = self.context + orientation = str_to_orientation(kwds.get("orientation", "lr")) + + # Construct a matrix and plot that + indices = list(range(len(self))) + if orientation in ("rl", "bt"): + indices.reverse() + if orientation in ("lr", "rl"): + matrix = Matrix([indices]) + else: + matrix = Matrix([[i] for i in indices]) + + bbox = self.bbox = kwds.pop("bbox", None) + if bbox is None: + raise ValueError("bbox is required for Cairo plots") + + border_width = float(kwds.get("border_width", 1.0)) + grid_width = float(kwds.get("grid_width", 0.0)) + + return matrix.__plot__( + 'cairo', + context, + bbox=bbox, + palette=self, + style="palette", + square=False, + grid_width=grid_width, + border_width=border_width, + ) + diff --git a/src/igraph/drawing/cairo/plot.py b/src/igraph/drawing/cairo/plot.py new file mode 100644 index 000000000..663975378 --- /dev/null +++ b/src/igraph/drawing/cairo/plot.py @@ -0,0 +1,360 @@ +""" +Drawing and plotting routines for IGraph. + +IGraph has two plotting backends at the moment: Cairo and Matplotlib. + +The Cairo backend is dependent on the C{pycairo} or C{cairocffi} libraries that +provide Python bindings to the popular U{Cairo library}. +This means that if you don't have U{pycairo} +or U{cairocffi} installed, you won't be able +to use the Cairo plotting backend. Whenever the documentation refers to the +C{pycairo} library, you can safely replace it with C{cairocffi} as the two are +API-compatible. + +The Matplotlib backend uses the U{Matplotlib library}. +You will need to install it from PyPI if you want to use the Matplotlib +plotting backend. + +If you do not want to (or cannot) install any of the dependencies outlined +above, you can still save the graph to an SVG file and view it from +U{Mozilla Firefox} (free) or edit it in +U{Inkscape} (free), U{Skencil} +(formerly known as Sketch, also free) or Adobe Illustrator. +""" + + +import os + +from io import BytesIO +from warnings import warn + +from igraph.configuration import Configuration +from igraph.drawing.cairo.utils import find_cairo +from igraph.drawing.colors import Palette, palettes +from igraph.drawing.utils import BoundingBox +from igraph.utils import named_temporary_file + +__all__ = ("CairoPlot",) + +cairo = find_cairo() + +##################################################################### + + +class CairoPlot: + """Class representing an arbitrary plot that uses the Cairo plotting + backend. + + Objects that you can plot include graphs, matrices, palettes, clusterings, + covers, and dendrograms. + + In Cairo, every plot has an associated surface object. The surface is an + instance of C{cairo.Surface}, a member of the C{pycairo} library. The + surface itself provides a unified API to various plotting targets like SVG + files, X11 windows, PostScript files, PNG files and so on. C{igraph} does + not usually know on which surface it is plotting at each point in time, + since C{pycairo} takes care of the actual drawing. Everything that's + supported by C{pycairo} should be supported by this class as well. + + Current Cairo surfaces include: + + - C{cairo.GlitzSurface} -- OpenGL accelerated surface for the X11 + Window System. + + - C{cairo.ImageSurface} -- memory buffer surface. Can be written to a + C{PNG} image file. + + - C{cairo.PDFSurface} -- PDF document surface. + + - C{cairo.PSSurface} -- PostScript document surface. + + - C{cairo.SVGSurface} -- SVG (Scalable Vector Graphics) document surface. + + - C{cairo.Win32Surface} -- Microsoft Windows screen rendering. + + - C{cairo.XlibSurface} -- X11 Window System screen rendering. + + If you create a C{Plot} object with a string given as the target surface, + the string will be treated as a filename, and its extension will decide + which surface class will be used. Please note that not all surfaces might + be available, depending on your C{pycairo} installation. + + A C{Plot} has an assigned default palette (see L{igraph.drawing.colors.Palette}) + which is used for plotting objects. + + A C{Plot} object also has a list of objects to be plotted with their + respective bounding boxes, palettes and opacities. Palettes assigned to an + object override the default palette of the plot. Objects can be added by the + L{Plot.add} method and removed by the L{Plot.remove} method. + """ + + def __init__( + self, + target=None, + bbox=None, + palette=None, + background=None, + ): + """Creates a new plot. + + @param target: the target surface to write to. It can be one of the + following types: + + - C{None} -- a Cairo surface will be created and the object will be + plotted there. + + - C{cairo.Surface} -- the given Cairo surface will be used. + + - C{string} -- a file with the given name will be created and an + appropriate Cairo surface will be attached to it. + + @param bbox: the bounding box of the surface. It is interpreted + differently with different surfaces: PDF and PS surfaces will treat it + as points (1 point = 1/72 inch). Image surfaces will treat it as + pixels. SVG surfaces will treat it as an abstract unit, but it will + mostly be interpreted as pixels when viewing the SVG file in Firefox. + + @param palette: the palette primarily used on the plot if the + added objects do not specify a private palette. Must be either + an L{igraph.drawing.colors.Palette} object or a string referring + to a valid key of C{igraph.drawing.colors.palettes} (see module + L{igraph.drawing.colors}) or C{None}. In the latter case, the default + palette given by the configuration key C{plotting.palette} is used. + + @param background: the background color. If C{None}, the background + will be transparent. You can use any color specification here that is + understood by L{igraph.drawing.colors.color_name_to_rgba}. + """ + + self._filename = None + self._need_tmpfile = False + + if bbox is None: + self.bbox = BoundingBox(600, 600) + elif isinstance(bbox, tuple) or isinstance(bbox, list): + self.bbox = BoundingBox(bbox) + else: + self.bbox = bbox + + if palette is None: + config = Configuration.instance() + palette = config["plotting.palette"] + if not isinstance(palette, Palette): + palette = palettes[palette] + self._palette = palette + + if target is None: + self._need_tmpfile = True + self._surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) + ) + elif isinstance(target, cairo.Surface): + self._surface = target + else: + self._filename = target + _, ext = os.path.splitext(target) + ext = ext.lower() + if ext == ".pdf": + self._surface = cairo.PDFSurface( + target, self.bbox.width, self.bbox.height + ) + elif ext == ".ps" or ext == ".eps": + self._surface = cairo.PSSurface( + target, self.bbox.width, self.bbox.height + ) + elif ext == ".png": + self._surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, int(self.bbox.width), int(self.bbox.height) + ) + elif ext == ".svg": + self._surface = cairo.SVGSurface( + target, self.bbox.width, self.bbox.height + ) + else: + raise ValueError("image format not handled by Cairo: %s" % ext) + + self._ctx = cairo.Context(self._surface) + + self._objects = [] + self._is_dirty = False + + if background is None: + background = "white" + self.background = background + + def add(self, obj, bbox=None, palette=None, opacity=1.0, *args, **kwds): + """Adds an object to the plot. + + Arguments not specified here are stored and passed to the object's + plotting function when necessary. Since you are most likely interested + in the arguments acceptable by graphs, see L{Graph.__plot__} for more + details. + + @param obj: the object to be added + @param bbox: the bounding box of the object. If C{None}, the object + will fill the entire area of the plot. + @param palette: the color palette used for drawing the object. If the + object tries to get a color assigned to a positive integer, it + will use this palette. If C{None}, defaults to the global palette + of the plot. + @param opacity: the opacity of the object being plotted, in the range + 0.0-1.0 + + @see: Graph.__plot__ + """ + if opacity < 0.0 or opacity > 1.0: + raise ValueError("opacity must be between 0.0 and 1.0") + if bbox is None: + bbox = self.bbox + if (bbox is not None) and (not isinstance(bbox, BoundingBox)): + bbox = BoundingBox(bbox) + self._objects.append((obj, bbox, palette, opacity, args, kwds)) + self.mark_dirty() + + @property + def background(self): + """Returns the background color of the plot. C{None} means a + transparent background. + """ + return self._background + + @background.setter + def background(self, color): + """Sets the background color of the plot. C{None} means a + transparent background. You can use any color specification here + that is understood by the C{get} method of the current palette + or by L{igraph.drawing.colors.color_name_to_rgb}. + """ + if color is None: + self._background = None + else: + self._background = self._palette.get(color) + + def remove(self, obj, bbox=None, idx=1): + """Removes an object from the plot. + + If the object has been added multiple times and no bounding box + was specified, it removes the instance which occurs M{idx}th + in the list of identical instances of the object. + + @param obj: the object to be removed + @param bbox: optional bounding box specification for the object. + If given, only objects with exactly this bounding box will be + considered. + @param idx: if multiple objects match the specification given by + M{obj} and M{bbox}, only the M{idx}th occurrence will be removed. + @return: C{True} if the object has been removed successfully, + C{False} if the object was not on the plot at all or M{idx} + was larger than the count of occurrences + """ + for i in range(len(self._objects)): + current_obj, current_bbox = self._objects[i][0:2] + if current_obj is obj and (bbox is None or current_bbox == bbox): + idx -= 1 + if idx == 0: + self._objects[i : (i + 1)] = [] + self.mark_dirty() + return True + return False + + def mark_dirty(self): + """Marks the plot as dirty (should be redrawn)""" + self._is_dirty = True + + def redraw(self, context=None): + """Redraws the plot""" + ctx = context or self._ctx + if self._background is not None: + ctx.set_source_rgba(*self._background) + ctx.rectangle(0, 0, self.bbox.width, self.bbox.height) + ctx.fill() + + for obj, bbox, palette, opacity, args, kwds in self._objects: + if palette is None: + palette = getattr(obj, "_default_palette", self._palette) + plotter = getattr(obj, "__plot__", None) + if plotter is None: + warn("%s does not support plotting" % (obj,)) + else: + if opacity < 1.0: + ctx.push_group() + else: + ctx.save() + plotter("cairo", ctx, bbox=bbox, palette=palette, *args, **kwds) + if opacity < 1.0: + ctx.pop_group_to_source() + ctx.paint_with_alpha(opacity) + else: + ctx.restore() + + self._is_dirty = False + + def save(self, fname=None): + """Saves the plot. + + @param fname: the filename to save to. It is ignored if the surface + of the plot is not an C{ImageSurface}. + """ + if self._is_dirty: + self.redraw() + if isinstance(self._surface, cairo.ImageSurface): + if fname is None and self._need_tmpfile: + with named_temporary_file(prefix="igraph", suffix=".png") as fname: + self._surface.write_to_png(fname) + return None + + fname = fname or self._filename + if fname is None: + raise ValueError("no file name is known for the surface and none given") + + # Conversion to string is needed because the user might pass a Path + # object and cairocffi expects a string + return self._surface.write_to_png(str(fname)) + + if fname is not None: + warn("filename is ignored for surfaces other than ImageSurface") + + self._ctx.show_page() + self._surface.finish() + + def _repr_svg_(self): + """Returns an SVG representation of this plot as a string. + + This method is used by IPython to display this plot inline. + """ + io = BytesIO() + # Create a new SVG surface and use that to get the SVG representation, + # which will end up in io + surface = cairo.SVGSurface(io, self.bbox.width, self.bbox.height) + context = cairo.Context(surface) + # Plot the graph on this context + self.redraw(context) + # No idea why this is needed but python crashes without + context.show_page() + surface.finish() + # Return the raw SVG representation + result = io.getvalue().decode("utf-8") + return result, {"isolated": True} # put it inside an iframe + + @property + def bounding_box(self): + """Returns the bounding box of the Cairo surface as a + L{BoundingBox} object""" + return BoundingBox(self.bbox) + + @property + def height(self): + """Returns the height of the Cairo surface on which the plot + is drawn""" + return self.bbox.height + + @property + def surface(self): + """Returns the Cairo surface on which the plot is drawn""" + return self._surface + + @property + def width(self): + """Returns the width of the Cairo surface on which the plot + is drawn""" + return self.bbox.width diff --git a/src/igraph/drawing/cairo/polygon.py b/src/igraph/drawing/cairo/polygon.py new file mode 100644 index 000000000..8b350d6d5 --- /dev/null +++ b/src/igraph/drawing/cairo/polygon.py @@ -0,0 +1,86 @@ +from igraph.drawing.utils import calculate_corner_radii +from igraph.utils import consecutive_pairs + +from .base import AbstractCairoDrawer + +__all__ = ("CairoPolygonDrawer",) + + +class CairoPolygonDrawer(AbstractCairoDrawer): + """Class that is used to draw polygons in Cairo. + + The corner points of the polygon can be set by the C{points} + property of the drawer, or passed at construction time. Most + drawing methods in this class also have an extra C{points} + argument that can be used to override the set of points in the + C{points} property.""" + + def __init__(self, context, bbox=(1, 1)): + """Constructs a new polygon drawer that draws on the given + Cairo context. + + @param context: the Cairo context to draw on + @param bbox: ignored, leave it at its default value + @param points: the list of corner points + """ + super().__init__(context, bbox) + + def draw_path(self, points, corner_radius=0): + """Sets up a Cairo path for the outline of a polygon on the given + Cairo context. + + @param points: the coordinates of the corners of the polygon, + in clockwise or counter-clockwise order. + @param corner_radius: if zero, an ordinary polygon will be drawn. + If positive, the corners of the polygon will be rounded with + the given radius. + """ + self.context.new_path() + + if len(points) < 2: + # Well, a polygon must have at least two corner points + return + + ctx = self.context + if corner_radius <= 0: + # No rounded corners, this is simple + ctx.move_to(*points[-1]) + for point in points: + ctx.line_to(*point) + return + + # Rounded corners. First, we will take each side of the + # polygon and find what the corner radius should be on + # each corner. If the side is longer than 2r (where r is + # equal to corner_radius), the radius allowed by that side + # is r; if the side is shorter, the radius is the length + # of the side / 2. For each corner, the final corner radius + # is the smaller of the radii on the two sides adjacent to + # the corner. + corner_radii = calculate_corner_radii(points, corner_radius) + + # Okay, move to the last corner, adjusted by corner_radii[-1] + # towards the first corner + ctx.move_to(*(points[-1].towards(points[0], corner_radii[-1]))) + # Now, for each point in points, draw a line towards the + # corner, stopping before it in a distance of corner_radii[idx], + # then draw the corner + u = points[-1] + for idx, (v, w) in enumerate(consecutive_pairs(points, True)): + radius = corner_radii[idx] + ctx.line_to(*v.towards(u, radius)) + aux1 = v.towards(u, radius / 2) + aux2 = v.towards(w, radius / 2) + ctx.curve_to( + aux1.x, aux1.y, aux2.x, aux2.y, *v.towards(w, corner_radii[idx]) + ) + u = v + + def draw(self, points): + """Draws the polygon using the current stroke of the Cairo context. + + @param points: the coordinates of the corners of the polygon, + in clockwise or counter-clockwise order. + """ + self.draw_path(points) + self.context.stroke() diff --git a/src/igraph/drawing/cairo/text.py b/src/igraph/drawing/cairo/text.py new file mode 100644 index 000000000..5e922996d --- /dev/null +++ b/src/igraph/drawing/cairo/text.py @@ -0,0 +1,358 @@ +""" +Drawers for labels on plots. +""" + +import re +from warnings import warn + +from igraph.drawing.cairo.base import AbstractCairoDrawer + +__all__ = ("CairoTextDrawer", ) + + +class CairoTextDrawer(AbstractCairoDrawer): + """Class that draws text on a Cairo context. + + This class supports multi-line text unlike the original Cairo text + drawing methods.""" + + LEFT, CENTER, RIGHT = "left", "center", "right" + TOP, BOTTOM = "top", "bottom" + + def __init__(self, context, text="", halign="center", valign="center"): + """Constructs a new instance that will draw the given `text` on + the given Cairo `context`.""" + super().__init__(context, (0, 0)) + self.text = text + self.halign = halign + self.valign = valign + + def draw(self, wrap=False): + """Draws the text in the current bounding box of the drawer. + + Since the class itself is an instance of `AbstractCairoDrawer`, it + has an attribute named ``bbox`` which will be used as a bounding + box. + + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the bounding box horizontally. + """ + ctx = self.context + bbox = self.bbox + + text_layout = self.get_text_layout(bbox.left, bbox.top, bbox.width, wrap) + if not text_layout: + return + + _, font_descent, line_height = ctx.font_extents()[:3] + yb = ctx.text_extents(text_layout[0][2])[1] + total_height = len(text_layout) * line_height + + if self.valign == self.BOTTOM: + # Bottom vertical alignment + dy = bbox.height - total_height - yb + font_descent + elif self.valign == self.CENTER: + # Centered vertical alignment + dy = (bbox.height - total_height - yb + font_descent + line_height) / 2.0 + else: + # Top vertical alignment + dy = line_height + + for ref_x, ref_y, line in text_layout: + ctx.move_to(ref_x, ref_y + dy) + ctx.show_text(line) + ctx.new_path() + + def get_text_layout(self, x=None, y=None, width=None, wrap=False): + """Calculates the layout of the current text. `x` and `y` denote the + coordinates where the drawing should start. If they are both ``None``, + the current position of the context will be used. + + Vertical alignment settings are not taken into account in this method + as the text is not drawn within a box. + + @param x: The X coordinate of the reference point where the layout should + start. + @param y: The Y coordinate of the reference point where the layout should + start. + @param width: The width of the box in which the text will be fitted. It + matters only when the text is right-aligned or centered. The text + will overflow the box if any of the lines is longer than the box + width and `wrap` is ``False``. + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the given width. + + @return: a list consisting of ``(x, y, line)`` tuples where ``x`` and + ``y`` refer to reference points on the Cairo canvas and ``line`` + refers to the corresponding text that should be plotted there. + """ + ctx = self.context + + if x is None or y is None: + x, y = ctx.get_current_point() + + line_height = ctx.font_extents()[2] + + if wrap: + if width and width > 0: + iterlines = self._iterlines_wrapped(width) + else: + warn("ignoring wrap=True as no width was specified") + else: + iterlines = self._iterlines() + + result = [] + + if self.halign == self.CENTER: + # Centered alignment + if width is None: + width = self.text_extents()[2] + for line, line_width, x_bearing in iterlines: + result.append((x + (width - line_width) / 2.0 - x_bearing, y, line)) + y += line_height + + elif self.halign == self.RIGHT: + # Right alignment + if width is None: + width = self.text_extents()[2] + x += width + for line, line_width, x_bearing in iterlines: + result.append((x - line_width - x_bearing, y, line)) + y += line_height + + else: + # Left alignment + for line, _, x_bearing in iterlines: + result.append((x - x_bearing, y, line)) + y += line_height + + return result + + def draw_at(self, x=None, y=None, width=None, wrap=False): + """Draws the text by setting up an appropriate path on the Cairo + context and filling it. `x` and `y` denote the coordinates where the + drawing should start. If they are both ``None``, the current position + of the context will be used. + + Vertical alignment settings are not taken into account in this method + as the text is not drawn within a box. + + @param x: The X coordinate of the reference point where the layout should + start. + @param y: The Y coordinate of the reference point where the layout should + start. + @param width: The width of the box in which the text will be fitted. It + matters only when the text is right-aligned or centered. The text + will overflow the box if any of the lines is longer than the box + width and `wrap` is ``False``. + @param wrap: whether to allow re-wrapping of the text if it does not + fit within the given width. + """ + ctx = self.context + for ref_x, ref_y, line in self.get_text_layout(x, y, width, wrap): + ctx.move_to(ref_x, ref_y) + ctx.show_text(line) + ctx.new_path() + + def _iterlines(self): + """Iterates over the label line by line and returns a tuple containing + the folloing for each line: the line itself, the width of the line and + the X-bearing of the line.""" + ctx = self.context + for line in self._text.split("\n"): + xb, _, line_width, _, _, _ = ctx.text_extents(line) + yield (line, line_width, xb) + + def _iterlines_wrapped(self, width): + """Iterates over the label line by line and returns a tuple containing + the folloing for each line: the line itself, the width of the line and + the X-bearing of the line. + + The difference between this method and `_iterlines()` is that this + method is allowed to re-wrap the line if necessary. + + @param width: The width of the box in which the text will be fitted. + Lines will be wrapped if they are wider than this width. + """ + ctx = self.context + for line in self._text.split("\n"): + xb, _, line_width, _, _, _ = ctx.text_extents(line) + if line_width <= width: + yield (line, line_width, xb) + continue + + # We have to wrap the line + current_line, current_width, last_sep_width = [], 0, 0 + for match in re.finditer(r"(\S+)(\s+)?", line): + word, sep = match.groups() + word_width = ctx.text_extents(word)[4] + if sep: + sep_width = ctx.text_extents(sep)[4] + else: + sep_width = 0 + current_width += word_width + if current_width >= width and current_line: + yield ("".join(current_line), current_width - word_width, 0) + # Starting a new line + current_line, current_width = [word], word_width + if sep is not None: + current_line.append(sep) + else: + current_width += last_sep_width + current_line.append(word) + if sep is not None: + current_line.append(sep) + last_sep_width = sep_width + if current_line: + yield ("".join(current_line), current_width, 0) + + @property + def text(self): + """Returns the text to be drawn.""" + return self._text + + @text.setter + def text(self, text): + """Sets the text that will be drawn. + + If `text` is ``None``, it will be mapped to an empty string; otherwise, + it will be converted to a string.""" + if text is None: + self._text = "" + else: + self._text = str(text) + + def text_extents(self): + """Returns the X-bearing, Y-bearing, width, height, X-advance and + Y-advance of the text. + + For multi-line text, the X-bearing and Y-bearing correspond to the + first line, while the X-advance is extracted from the last line. + and the Y-advance is the sum of all the Y-advances. The width and + height correspond to the entire bounding box of the text.""" + lines = self.text.split("\n") + if len(lines) <= 1: + return self.context.text_extents(self.text) + + ( + x_bearing, + y_bearing, + width, + height, + x_advance, + y_advance, + ) = self.context.text_extents(lines[0]) + + line_height = self.context.font_extents()[2] + for line in lines[1:]: + _, _, w, _, x_advance, ya = self.context.text_extents(line) + width = max(width, w) + height += line_height + y_advance += ya + + return x_bearing, y_bearing, width, height, x_advance, y_advance + + +def test(): + """Testing routine for L{CairoTextDrawer}""" + import math + from igraph.drawing.cairo.utils import find_cairo + from igraph.drawing.text import TextAlignment + + cairo = find_cairo() + + text = "The quick brown fox\njumps over a\nlazy dog" + width, height = (600, 1000) + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + drawer = CairoTextDrawer(context, text) + + context.set_source_rgb(1, 1, 1) + context.set_font_size(16.0) + context.rectangle(0, 0, width, height) + context.fill() + + context.set_source_rgb(0.5, 0.5, 0.5) + for i in range(200, width, 200): + context.move_to(i, 0) + context.line_to(i, height) + context.stroke() + for i in range(200, height, 200): + context.move_to(0, i) + context.line_to(width, i) + context.stroke() + context.set_source_rgb(0.75, 0.75, 0.75) + context.set_line_width(0.5) + for i in range(100, width, 200): + context.move_to(i, 0) + context.line_to(i, height) + context.stroke() + for i in range(100, height, 200): + context.move_to(0, i) + context.line_to(width, i) + context.stroke() + + def mark_point(red, green, blue): + """Marks the current point on the canvas by the given color""" + x, y = context.get_current_point() + context.set_source_rgba(red, green, blue, 0.5) + context.arc(x, y, 4, 0, 2 * math.pi) + context.fill() + + # Testing drawer.draw_at() + alignments = TextAlignment.LEFT, TextAlignment.CENTER, TextAlignment.RIGHT + for i, halign in enumerate(alignments): + # Mark the reference points + context.move_to(i * 200, 40) + mark_point(0, 0, 1) + context.move_to(i * 200, 140) + mark_point(0, 0, 1) + + # Draw the text + context.set_source_rgb(0, 0, 0) + drawer.halign = halign + drawer.draw_at(i * 200, 40) + drawer.draw_at(i * 200, 140, width=200) + + # Mark the new reference point + mark_point(1, 0, 0) + + # Testing TextDrawer.draw() + for i, halign in enumerate(("left", "center", "right")): + for j, valign in enumerate(("top", "center", "bottom")): + # Draw the text + context.set_source_rgb(0, 0, 0) + drawer.halign = halign + drawer.valign = valign + drawer.bbox = (i * 200, j * 200 + 200, i * 200 + 200, j * 200 + 400) + drawer.draw() + # Mark the new reference point + mark_point(1, 0, 0) + + # Testing TextDrawer.wrap() + drawer.text = ( + "Jackdaws love my big sphinx of quartz. Yay, wrapping! " + + "Jackdaws love my big sphinx of quartz.\n\n" + + "Jackdaws love my big sphinx of quartz." + ) + drawer.valign = TextAlignment.TOP + for i, halign in enumerate(("left", "center", "right")): + context.move_to(i * 200, 840) + + # Mark the reference point + mark_point(0, 0, 1) + + # Draw the text + context.set_source_rgb(0, 0, 0) + drawer.halign = halign + drawer.draw_at(i * 200, 840, width=199, wrap=True) + + # Mark the new reference point + mark_point(1, 0, 0) + + surface.write_to_png("test.png") + + +if __name__ == "__main__": + test() diff --git a/src/igraph/drawing/cairo/utils.py b/src/igraph/drawing/cairo/utils.py new file mode 100644 index 000000000..753652b83 --- /dev/null +++ b/src/igraph/drawing/cairo/utils.py @@ -0,0 +1,20 @@ +from igraph.drawing.utils import FakeModule +from typing import Any + +__all__ = ("find_cairo", ) + + +def find_cairo() -> Any: + """Tries to import the ``cairo`` Python module if it is installed, + also trying ``cairocffi`` (a drop-in replacement of ``cairo``). + Returns a fake module if everything fails. + """ + module_names = ["cairo", "cairocffi"] + module = FakeModule("Plotting not available; please install pycairo or cairocffi") + for module_name in module_names: + try: + module = __import__(module_name) + break + except ImportError: + pass + return module diff --git a/src/igraph/drawing/vertex.py b/src/igraph/drawing/cairo/vertex.py similarity index 63% rename from src/igraph/drawing/vertex.py rename to src/igraph/drawing/cairo/vertex.py index fbae32e3f..8d5fdf8ab 100644 --- a/src/igraph/drawing/vertex.py +++ b/src/igraph/drawing/cairo/vertex.py @@ -1,44 +1,16 @@ +"""This module provides implementations of Cairo-specific vertex drawers, i.e. +drawers that the Cairo graph drawer will use to draw vertices. """ -Drawing routines to draw the vertices of graphs. -This module provides implementations of vertex drawers, i.e. drawers that the -default graph drawer will use to draw vertices. -""" +from math import pi -from igraph.drawing.baseclasses import AbstractDrawer, AbstractCairoDrawer +from igraph.drawing.baseclasses import AbstractVertexDrawer from igraph.drawing.metamagic import AttributeCollectorBase from igraph.drawing.shapes import ShapeDrawerDirectory -from math import pi - -__all__ = ("AbstractVertexDrawer", "AbstractCairoVertexDrawer", "DefaultVertexDrawer") - - -class AbstractVertexDrawer(AbstractDrawer): - """Abstract vertex drawer object from which all concrete vertex drawer - implementations are derived.""" - - def __init__(self, palette, layout): - """Constructs the vertex drawer and associates it to the given - palette. - @param palette: the palette that can be used to map integer - color indices to colors when drawing vertices - @param layout: the layout of the vertices in the graph being drawn - """ - self.layout = layout - self.palette = palette +from .base import AbstractCairoDrawer - def draw(self, visual_vertex, vertex, coords): - """Draws the given vertex. - - @param visual_vertex: object specifying the visual properties of the - vertex. Its structure is defined by the VisualVertexBuilder of the - L{DefaultGraphDrawer}; see its source code. - @param vertex: the raw igraph vertex being drawn - @param coords: the X and Y coordinates of the vertex as specified by the - layout algorithm, scaled into the bounding box. - """ - raise NotImplementedError("abstract class") +__all__ = ("AbstractCairoVertexDrawer", "CairoVertexDrawer") class AbstractCairoVertexDrawer(AbstractVertexDrawer, AbstractCairoDrawer): @@ -61,11 +33,11 @@ def __init__(self, context, bbox, palette, layout): AbstractVertexDrawer.__init__(self, palette, layout) -class DefaultVertexDrawer(AbstractCairoVertexDrawer): +class CairoVertexDrawer(AbstractCairoVertexDrawer): """The default vertex drawer implementation of igraph.""" def __init__(self, context, bbox, palette, layout): - AbstractCairoVertexDrawer.__init__(self, context, bbox, palette, layout) + super().__init__(context, bbox, palette, layout) self.VisualVertexBuilder = self._construct_visual_vertex_builder() def _construct_visual_vertex_builder(self): diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 78ecc275f..72813dc4b 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -4,8 +4,7 @@ Color handling functions. """ -from igraph.datatypes import Matrix -from igraph.utils import str_to_orientation +from abc import ABCMeta, abstractmethod from math import ceil __all__ = ( @@ -26,11 +25,12 @@ "rgb_to_hsl", "rgba_to_hsla", "palettes", + "default_edge_colors", "known_colors", ) -class Palette: +class Palette(metaclass=ABCMeta): """Base class of color palettes. Color palettes are mappings that assign integers from the range @@ -117,6 +117,7 @@ class will simply try to interpret it as a single color by # Multiple colors return [self.get(color) for color in colors] + @abstractmethod def _get(self, v): """Override this method in a subclass to create a custom palette. @@ -125,7 +126,7 @@ def _get(self, v): @param v: numerical index of the color to be retrieved @return: a 4-tuple containing the RGBA values""" - raise NotImplementedError("abstract class") + raise NotImplementedError __getitem__ = get @@ -138,10 +139,19 @@ def __len__(self): """Returns the number of colors in this palette""" return self._length - def __plot__(self, context, bbox, palette, *args, **kwds): - """Plots the colors of the palette on the given Cairo context + def __plot__(self, backend, context, *args, **kwds): + """Plots the colors of the palette on the given Cairo context/mpl Axes - Supported keyword arguments are: + Supported keywork arguments in both Cairo and matplotlib are: + + - C{orientation}: the orientation of the palette. Must be one of + the following values: C{left-right}, C{bottom-top}, C{right-left} + or C{top-bottom}. Possible aliases: C{horizontal} = C{left-right}, + C{vertical} = C{bottom-top}, C{lr} = C{left-right}, + C{rl} = C{right-left}, C{tb} = C{top-bottom}, C{bt} = C{bottom-top}. + The default is C{left-right}. + + Additional supported keyword arguments in Cairo are: - C{border_width}: line width of the border shown around the palette. If zero or negative, the border is turned off. Default is C{1}. @@ -151,35 +161,12 @@ def __plot__(self, context, bbox, palette, *args, **kwds): turned off if the size of a cell is less than three times the given line width. Default is C{0}. Fractional widths are also allowed. - - C{orientation}: the orientation of the palette. Must be one of - the following values: C{left-right}, C{bottom-top}, C{right-left} - or C{top-bottom}. Possible aliases: C{horizontal} = C{left-right}, - C{vertical} = C{bottom-top}, C{lr} = C{left-right}, - C{rl} = C{right-left}, C{tb} = C{top-bottom}, C{bt} = C{bottom-top}. - The default is C{left-right}. + Keyword arguments in matplotlib are passes to Axes.imshow. """ - border_width = float(kwds.get("border_width", 1.0)) - grid_width = float(kwds.get("grid_width", 0.0)) - orientation = str_to_orientation(kwds.get("orientation", "lr")) - - # Construct a matrix and plot that - indices = list(range(len(self))) - if orientation in ("rl", "bt"): - indices.reverse() - if orientation in ("lr", "rl"): - matrix = Matrix([indices]) - else: - matrix = Matrix([[i] for i in indices]) - - return matrix.__plot__( - context, - bbox, - self, - style="palette", - square=False, - grid_width=grid_width, - border_width=border_width, - ) + from igraph.drawing import DrawerDirectory + + drawer = DrawerDirectory.resolve(self, backend)(context) + drawer.draw(self, **kwds) def __repr__(self): return "<%s with %d colors>" % (self.__class__.__name__, self._length) @@ -728,6 +715,13 @@ def lighten(color, ratio=0.5): ) +default_edge_colors = { + "cairo": ["grey20", "grey80"], + "matplotlib": ["dimgrey", "silver"], + "plotly": ["rgb(51,51,51)", "rgb(204,204,204)"], +} + + known_colors = { "alice blue": (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), "aliceblue": (0.94117647058823528, 0.97254901960784312, 1.0, 1.0), diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index c47b19193..cdca21f0d 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -13,628 +13,11 @@ network from Cytoscape and convert it to igraph format. """ -from math import atan2, cos, pi, sin, tan, sqrt from warnings import warn -from igraph._igraph import convex_hull, VertexSeq -from igraph.configuration import Configuration -from igraph.drawing.baseclasses import ( - AbstractDrawer, - AbstractCairoDrawer, - AbstractXMLRPCDrawer, -) -from igraph.drawing.colors import color_to_html_format, color_name_to_rgb -from igraph.drawing.edge import ArrowEdgeDrawer -from igraph.drawing.text import TextAlignment, TextDrawer -from igraph.drawing.metamagic import AttributeCollectorBase -from igraph.drawing.shapes import PolygonDrawer -from igraph.drawing.utils import find_cairo, Point -from igraph.drawing.vertex import DefaultVertexDrawer -from igraph.layout import Layout +from igraph.drawing.baseclasses import AbstractGraphDrawer, AbstractXMLRPCDrawer -__all__ = ( - "DefaultGraphDrawer", "MatplotlibGraphDrawer", "CytoscapeGraphDrawer", - "UbiGraphDrawer" -) - -cairo = find_cairo() - -##################################################################### - - -class AbstractGraphDrawer(AbstractDrawer): - """Abstract class that serves as a base class for anything that - draws an igraph.Graph.""" - - def draw(self, graph, *args, **kwds): - """Abstract method, must be implemented in derived classes.""" - raise NotImplementedError("abstract class") - - def ensure_layout(self, layout, graph=None): - """Helper method that ensures that I{layout} is an instance - of L{Layout}. If it is not, the method will try to convert - it to a L{Layout} according to the following rules: - - - If I{layout} is a string, it is assumed to be a name - of an igraph layout, and it will be passed on to the - C{layout} method of the given I{graph} if I{graph} is - not C{None}. - - - If I{layout} is C{None}, the C{layout} method of - I{graph} will be invoked with no parameters, which - will call the default layout algorithm. - - - Otherwise, I{layout} will be passed on to the constructor - of L{Layout}. This handles lists of lists, lists of tuples - and such. - - If I{layout} is already a L{Layout} instance, it will still - be copied and a copy will be returned. This is because graph - drawers are allowed to transform the layout for their purposes, - and we don't want the transformation to propagate back to the - caller. - """ - if isinstance(layout, Layout): - layout = Layout(layout.coords) - elif isinstance(layout, str) or layout is None: - layout = graph.layout(layout) - else: - layout = Layout(layout) - return layout - - -##################################################################### - - -class AbstractCairoGraphDrawer(AbstractGraphDrawer, AbstractCairoDrawer): - """Abstract base class for graph drawers that draw on a Cairo canvas.""" - - def __init__(self, context, bbox): - """Constructs the graph drawer and associates it to the given - Cairo context and the given L{BoundingBox}. - - @param context: the context on which we will draw - @param bbox: the bounding box within which we will draw. - Can be anything accepted by the constructor - of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple - or a L{BoundingBox} object). - """ - AbstractCairoDrawer.__init__(self, context, bbox) - AbstractGraphDrawer.__init__(self) - - -##################################################################### - - -class DefaultGraphDrawer(AbstractCairoGraphDrawer): - """Class implementing the default visualisation of a graph. - - The default visualisation of a graph draws the nodes on a 2D plane - according to a given L{Layout}, then draws a straight or curved - edge between nodes connected by edges. This is the visualisation - used when one invokes the L{plot()} function on a L{Graph} object. - - See L{Graph.__plot__()} for the keyword arguments understood by - this drawer.""" - - def __init__( - self, - context, - bbox, - vertex_drawer_factory=DefaultVertexDrawer, - edge_drawer_factory=ArrowEdgeDrawer, - label_drawer_factory=TextDrawer, - ): - """Constructs the graph drawer and associates it to the given - Cairo context and the given L{BoundingBox}. - - @param context: the context on which we will draw - @param bbox: the bounding box within which we will draw. - Can be anything accepted by the constructor - of L{BoundingBox} (i.e., a 2-tuple, a 4-tuple - or a L{BoundingBox} object). - @param vertex_drawer_factory: a factory method that returns an - L{AbstractCairoVertexDrawer} instance bound to a - given Cairo context. The factory method must take - three parameters: the Cairo context, the bounding - box of the drawing area and the palette to be - used for drawing colored vertices. The default - vertex drawer is L{DefaultVertexDrawer}. - @param edge_drawer_factory: a factory method that returns an - L{AbstractEdgeDrawer} instance bound to a - given Cairo context. The factory method must take - two parameters: the Cairo context and the palette - to be used for drawing colored edges. You can use - any of the actual L{AbstractEdgeDrawer} - implementations here to control the style of - edges drawn by igraph. The default edge drawer is - L{ArrowEdgeDrawer}. - @param label_drawer_factory: a factory method that returns a - L{TextDrawer} instance bound to a given Cairo - context. The method must take one parameter: the - Cairo context. The default label drawer is - L{TextDrawer}. - """ - AbstractCairoGraphDrawer.__init__(self, context, bbox) - self.vertex_drawer_factory = vertex_drawer_factory - self.edge_drawer_factory = edge_drawer_factory - self.label_drawer_factory = label_drawer_factory - - def _determine_edge_order(self, graph, kwds): - """Returns the order in which the edge of the given graph have to be - drawn, assuming that the relevant keyword arguments (C{edge_order} and - C{edge_order_by}) are given in C{kwds} as a dictionary. If neither - C{edge_order} nor C{edge_order_by} is present in C{kwds}, this - function returns C{None} to indicate that the graph drawer is free to - choose the most convenient edge ordering.""" - if "edge_order" in kwds: - # Edge order specified explicitly - return kwds["edge_order"] - - if kwds.get("edge_order_by") is None: - # No edge order specified - return None - - # Order edges by the value of some attribute - edge_order_by = kwds["edge_order_by"] - reverse = False - if isinstance(edge_order_by, tuple): - edge_order_by, reverse = edge_order_by - if isinstance(reverse, str): - reverse = reverse.lower().startswith("desc") - attrs = graph.es[edge_order_by] - edge_order = sorted( - list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) - ) - - return edge_order - - def _determine_vertex_order(self, graph, kwds): - """Returns the order in which the vertices of the given graph have to be - drawn, assuming that the relevant keyword arguments (C{vertex_order} and - C{vertex_order_by}) are given in C{kwds} as a dictionary. If neither - C{vertex_order} nor C{vertex_order_by} is present in C{kwds}, this - function returns C{None} to indicate that the graph drawer is free to - choose the most convenient vertex ordering.""" - if "vertex_order" in kwds: - # Vertex order specified explicitly - return kwds["vertex_order"] - - if kwds.get("vertex_order_by") is None: - # No vertex order specified - return None - - # Order vertices by the value of some attribute - vertex_order_by = kwds["vertex_order_by"] - reverse = False - if isinstance(vertex_order_by, tuple): - vertex_order_by, reverse = vertex_order_by - if isinstance(reverse, str): - reverse = reverse.lower().startswith("desc") - attrs = graph.vs[vertex_order_by] - vertex_order = sorted( - list(range(len(attrs))), key=attrs.__getitem__, reverse=bool(reverse) - ) - - return vertex_order - - def draw(self, graph, palette, *args, **kwds): - # Some abbreviations for sake of simplicity - directed = graph.is_directed() - context = self.context - - # Calculate/get the layout of the graph - layout = self.ensure_layout(kwds.get("layout", None), graph) - - # Determine the size of the margin on each side - margin = kwds.get("margin", 0) - try: - margin = list(margin) - except TypeError: - margin = [margin] - while len(margin) < 4: - margin.extend(margin) - - # Contract the drawing area by the margin and fit the layout - bbox = self.bbox.contract(margin) - layout.fit_into(bbox, keep_aspect_ratio=kwds.get("keep_aspect_ratio", False)) - - # Decide whether we need to calculate the curvature of edges - # automatically -- and calculate them if needed. - autocurve = kwds.get("autocurve", None) - if autocurve or ( - autocurve is None - and "edge_curved" not in kwds - and "curved" not in graph.edge_attributes() - and graph.ecount() < 10000 - ): - from igraph import autocurve - - default = kwds.get("edge_curved", 0) - if default is True: - default = 0.5 - default = float(default) - kwds["edge_curved"] = autocurve(graph, attribute=None, default=default) - - # Construct the vertex, edge and label drawers - vertex_drawer = self.vertex_drawer_factory(context, bbox, palette, layout) - edge_drawer = self.edge_drawer_factory(context, palette) - label_drawer = self.label_drawer_factory(context) - - # Construct the visual vertex/edge builders based on the specifications - # provided by the vertex_drawer and the edge_drawer - vertex_builder = vertex_drawer.VisualVertexBuilder(graph.vs, kwds) - edge_builder = edge_drawer.VisualEdgeBuilder(graph.es, kwds) - - # Determine the order in which we will draw the vertices and edges - vertex_order = self._determine_vertex_order(graph, kwds) - edge_order = self._determine_edge_order(graph, kwds) - - # Draw the highlighted groups (if any) - if "mark_groups" in kwds: - mark_groups = kwds["mark_groups"] - - # Deferred import to avoid a cycle in the import graph - from igraph.clustering import VertexClustering, VertexCover - - # Figure out what to do with mark_groups in order to be able to - # iterate over it and get memberlist-color pairs - if isinstance(mark_groups, dict): - # Dictionary mapping vertex indices or tuples of vertex - # indices to colors - group_iter = iter(mark_groups.items()) - elif isinstance(mark_groups, (VertexClustering, VertexCover)): - # Vertex clustering - group_iter = ((group, color) for color, group in enumerate(mark_groups)) - elif hasattr(mark_groups, "__iter__"): - # Lists, tuples, iterators etc - group_iter = iter(mark_groups) - else: - # False - group_iter = iter({}.items()) - - # We will need a polygon drawer to draw the convex hulls - polygon_drawer = PolygonDrawer(context, bbox) - - # Iterate over color-memberlist pairs - for group, color_id in group_iter: - if not group or color_id is None: - continue - - color = palette.get(color_id) - - if isinstance(group, VertexSeq): - group = [vertex.index for vertex in group] - if not hasattr(group, "__iter__"): - raise TypeError("group membership list must be iterable") - - # Get the vertex indices that constitute the convex hull - hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] - - # Calculate the preferred rounding radius for the corners - corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) - - # Construct the polygon - polygon = [layout[idx] for idx in hull] - - if len(polygon) == 2: - # Expand the polygon (which is a flat line otherwise) - a, b = Point(*polygon[0]), Point(*polygon[1]) - c = corner_radius * (a - b).normalized() - n = Point(-c[1], c[0]) - polygon = [a + n, b + n, b - c, b - n, a - n, a + c] - else: - # Expand the polygon around its center of mass - center = Point( - *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] - ) - polygon = [ - Point(*point).towards(center, -corner_radius) - for point in polygon - ] - - # Draw the hull - context.set_source_rgba(color[0], color[1], color[2], color[3] * 0.25) - polygon_drawer.draw_path(polygon, corner_radius=corner_radius) - context.fill_preserve() - context.set_source_rgba(*color) - context.stroke() - - # Construct the iterator that we will use to draw the edges - es = graph.es - if edge_order is None: - # Default edge order - edge_coord_iter = zip(es, edge_builder) - else: - # Specified edge order - edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) - - # Draw the edges - if directed: - drawer_method = edge_drawer.draw_directed_edge - else: - drawer_method = edge_drawer.draw_undirected_edge - for edge, visual_edge in edge_coord_iter: - src, dest = edge.tuple - src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - drawer_method(visual_edge, src_vertex, dest_vertex) - - # Construct the iterator that we will use to draw the vertices - vs = graph.vs - if vertex_order is None: - # Default vertex order - vertex_coord_iter = zip(vs, vertex_builder, layout) - else: - # Specified vertex order - vertex_coord_iter = ( - (vs[i], vertex_builder[i], layout[i]) for i in vertex_order - ) - - # Draw the vertices - drawer_method = vertex_drawer.draw - context.set_line_width(1) - for vertex, visual_vertex, coords in vertex_coord_iter: - drawer_method(visual_vertex, vertex, coords) - - # Decide whether the labels have to be wrapped - wrap = kwds.get("wrap_labels") - if wrap is None: - wrap = Configuration.instance()["plotting.wrap_labels"] - wrap = bool(wrap) - - # Construct the iterator that we will use to draw the vertex labels - if vertex_order is None: - # Default vertex order - vertex_coord_iter = zip(vertex_builder, layout) - else: - # Specified vertex order - vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) - - # Draw the vertex labels - for vertex, coords in vertex_coord_iter: - if vertex.label is None: - continue - - # Set the font family, size, color and text - context.select_font_face( - vertex.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL - ) - context.set_font_size(vertex.label_size) - context.set_source_rgba(*vertex.label_color) - label_drawer.text = vertex.label - - if vertex.label_dist: - # Label is displaced from the center of the vertex. - _, yb, w, h, _, _ = label_drawer.text_extents() - w, h = w / 2.0, h / 2.0 - radius = vertex.label_dist * vertex.size / 2.0 - # First we find the reference point that is at distance `radius' - # from the vertex in the direction given by `label_angle'. - # Then we place the label in a way that the line connecting the - # center of the bounding box of the label with the center of the - # vertex goes through the reference point and the reference - # point lies exactly on the bounding box of the vertex. - alpha = vertex.label_angle % (2 * pi) - cx = coords[0] + radius * cos(alpha) - cy = coords[1] - radius * sin(alpha) - # Now we have the reference point. We have to decide which side - # of the label box will intersect with the line that connects - # the center of the label with the center of the vertex. - if w > 0: - beta = atan2(h, w) % (2 * pi) - else: - beta = pi / 2.0 - gamma = pi - beta - if alpha > 2 * pi - beta or alpha <= beta: - # Intersection at left edge of label - cx += w - cy -= tan(alpha) * w - elif alpha > beta and alpha <= gamma: - # Intersection at bottom edge of label - try: - cx += h / tan(alpha) - except Exception: - pass # tan(alpha) == inf - cy -= h - elif alpha > gamma and alpha <= gamma + 2 * beta: - # Intersection at right edge of label - cx -= w - cy += tan(alpha) * w - else: - # Intersection at top edge of label - try: - cx -= h / tan(alpha) - except Exception: - pass # tan(alpha) == inf - cy += h - # Draw the label - label_drawer.draw_at(cx - w, cy - h - yb, wrap=wrap) - else: - # Label is exactly in the center of the vertex - cx, cy = coords - half_size = vertex.size / 2.0 - label_drawer.bbox = ( - cx - half_size, - cy - half_size, - cx + half_size, - cy + half_size, - ) - label_drawer.draw(wrap=wrap) - - # Construct the iterator that we will use to draw the edge labels - es = graph.es - if edge_order is None: - # Default edge order - edge_coord_iter = zip(es, edge_builder) - else: - # Specified edge order - edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) - - # Draw the edge labels - for edge, visual_edge in edge_coord_iter: - if visual_edge.label is None: - continue - - # Set the font family, size, color and text - context.select_font_face( - visual_edge.font, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL - ) - context.set_font_size(visual_edge.label_size) - context.set_source_rgba(*visual_edge.label_color) - label_drawer.text = visual_edge.label - - # Ask the edge drawer to propose an anchor point for the label - src, dest = edge.tuple - src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - (x, y), (halign, valign) = edge_drawer.get_label_position( - edge, src_vertex, dest_vertex - ) - - # Measure the text - _, yb, w, h, _, _ = label_drawer.text_extents() - w /= 2.0 - h /= 2.0 - - # Place the text relative to the edge - if halign == TextAlignment.RIGHT: - x -= w - elif halign == TextAlignment.LEFT: - x += w - if valign == TextAlignment.BOTTOM: - y -= h - yb / 2.0 - elif valign == TextAlignment.TOP: - y += h - - # Draw the edge label - label_drawer.halign = halign - label_drawer.valign = valign - label_drawer.bbox = (x - w, y - h, x + w, y + h) - label_drawer.draw(wrap=wrap) - - -##################################################################### - - -class UbiGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): - """Graph drawer that draws a given graph on an UbiGraph display - using the XML-RPC API of UbiGraph. - - The following vertex attributes are supported: C{color}, C{label}, - C{shape}, C{size}. See the Ubigraph documentation for supported shape - names. Sizes are relative to the default Ubigraph size. - - The following edge attributes are supported: C{color}, C{label}, - C{width}. Edge widths are relative to the default Ubigraph width. - - All color specifications supported by igraph (e.g., color names, - palette indices, RGB triplets, RGBA quadruplets, HTML format) - are understood by the Ubigraph graph drawer. - - The drawer also has two attributes, C{vertex_defaults} and - C{edge_defaults}. These are dictionaries that can be used to - set default values for the vertex/edge attributes in Ubigraph. - - @deprecated: UbiGraph has not received updates since 2008 and is now not - available for download (at least not from the official sources). - The UbiGraph graph drawer will be removed from python-igraph in - 0.10.0. - """ - - def __init__(self, url="http://localhost:20738/RPC2"): - """Constructs an UbiGraph drawer using the display at the given - URL.""" - super().__init__(url, "ubigraph") - self.vertex_defaults = dict(color="#ff0000", shape="cube", size=1.0) - self.edge_defaults = dict(color="#ffffff", width=1.0) - - warn( - "UbiGraphDrawer is deprecated from python-igraph 0.9.4", - DeprecationWarning - ) - - def draw(self, graph, *args, **kwds): - """Draws the given graph on an UbiGraph display. - - @keyword clear: whether to clear the current UbiGraph display before - plotting. Default: C{True}.""" - display = self.service - - # Clear the display and set the default visual attributes - if kwds.get("clear", True): - display.clear() - - for k, v in self.vertex_defaults.items(): - display.set_vertex_style_attribute(0, k, str(v)) - for k, v in self.edge_defaults.items(): - display.set_edge_style_attribute(0, k, str(v)) - - # Custom color converter function - def color_conv(color): - return color_to_html_format(color_name_to_rgb(color)) - - # Construct the visual vertex/edge builders - class VisualVertexBuilder(AttributeCollectorBase): - """Collects some visual properties of a vertex for drawing""" - - _kwds_prefix = "vertex_" - color = (str(self.vertex_defaults["color"]), color_conv) - label = None - shape = str(self.vertex_defaults["shape"]) - size = float(self.vertex_defaults["size"]) - - class VisualEdgeBuilder(AttributeCollectorBase): - """Collects some visual properties of an edge for drawing""" - - _kwds_prefix = "edge_" - color = (str(self.edge_defaults["color"]), color_conv) - label = None - width = float(self.edge_defaults["width"]) - - vertex_builder = VisualVertexBuilder(graph.vs, kwds) - edge_builder = VisualEdgeBuilder(graph.es, kwds) - - # Add the vertices - n = graph.vcount() - new_vertex = display.new_vertex - vertex_ids = [new_vertex() for _ in range(n)] - - # Add the edges - new_edge = display.new_edge - eids = [ - new_edge(vertex_ids[edge.source], vertex_ids[edge.target]) - for edge in graph.es - ] - - # Add arrowheads if needed - if graph.is_directed(): - display.set_edge_style_attribute(0, "arrow", "true") - - # Set the vertex attributes - set_attr = display.set_vertex_attribute - vertex_defaults = self.vertex_defaults - for vertex_id, vertex in zip(vertex_ids, vertex_builder): - if vertex.color != vertex_defaults["color"]: - set_attr(vertex_id, "color", vertex.color) - if vertex.label: - set_attr(vertex_id, "label", str(vertex.label)) - if vertex.shape != vertex_defaults["shape"]: - set_attr(vertex_id, "shape", vertex.shape) - if vertex.size != vertex_defaults["size"]: - set_attr(vertex_id, "size", str(vertex.size)) - - # Set the edge attributes - set_attr = display.set_edge_attribute - edge_defaults = self.edge_defaults - for edge_id, edge in zip(eids, edge_builder): - if edge.color != edge_defaults["color"]: - set_attr(edge_id, "color", edge.color) - if edge.label: - set_attr(edge_id, "label", edge.label) - if edge.width != edge_defaults["width"]: - set_attr(edge_id, "width", str(edge.width)) - - -##################################################################### +__all__ = ("CytoscapeGraphDrawer",) class CytoscapeGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): @@ -680,6 +63,14 @@ def draw(self, graph, name="Network from igraph", create_view=True, *args, **kwd simply uses the vertex index for each vertex.""" from xmlrpc.client import Fault + # Positional arguments are not used + if args: + warn( + "Positional arguments to plot functions are ignored " + "and will be deprecated soon.", + DeprecationWarning, + ) + cy = self.service # Create the network @@ -798,7 +189,7 @@ def fetch(self, name=None, directed=False, keep_canonical_names=False): version = tuple(map(int, version.split(".")[:2])) if version < (1, 3): raise NotImplementedError( - "CytoscapeGraphDrawer requires " "Cytoscape-RPC 1.3 or newer" + "CytoscapeGraphDrawer requires Cytoscape-RPC 1.3 or newer" ) # Find out the ID of the network we are interested in @@ -956,399 +347,12 @@ def draw(self, graph, *args, **kwds): - ``encoder`` lets one specify an instance of ``json.JSONEncoder`` that will be used to encode the JSON objects. """ - self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) - - -##################################################################### - - -class MatplotlibGraphDrawer(AbstractGraphDrawer): - """Graph drawer that uses a pyplot.Axes as context""" - - _shape_dict = { - "rectangle": "s", - "circle": "o", - "hidden": "none", - "triangle-up": "^", - "triangle-down": "v", - } - - def __init__(self, ax): - """Constructs the graph drawer and associates it with the mpl axes""" - self.ax = ax - - def draw(self, graph, *args, **kwds): - # NOTE: matplotlib has numpy as a dependency, so we can use it in here - from collections import defaultdict - import matplotlib as mpl - import matplotlib.markers as mmarkers - from matplotlib.path import Path - from matplotlib.patches import FancyArrowPatch - from matplotlib.patches import ArrowStyle - import numpy as np - - # Deferred import to avoid a cycle in the import graph - from igraph.clustering import VertexClustering, VertexCover - - def shrink_vertex(ax, aux, vcoord, vsize_squared): - """Shrink edge by vertex size""" - aux_display, vcoord_display = ax.transData.transform([aux, vcoord]) - d = sqrt(((aux_display - vcoord_display) ** 2).sum()) - fr = sqrt(vsize_squared) / d - end_display = vcoord_display + fr * (aux_display - vcoord_display) - end = ax.transData.inverted().transform(end_display) - return end - - def callback_factory(ax, vcoord, vsizes, arrows): - def callback_edge_offset(event): - for arrow, src, tgt in arrows: - v1, v2 = vcoord[src], vcoord[tgt] - # This covers both cases (curved and straight) - aux1, aux2 = arrow._path_original.vertices[[1, -2]] - start = shrink_vertex(ax, aux1, v1, vsizes[src]) - end = shrink_vertex(ax, aux2, v2, vsizes[tgt]) - arrow._path_original.vertices[0] = start - arrow._path_original.vertices[-1] = end - - return callback_edge_offset - - ax = self.ax - - # FIXME: deal with unnamed *args - - # graph is not necessarily a graph, it can be a VertexClustering. If so - # extract the graph. The clustering itself can be overridden using - # the "mark_groups" option - clustering = None - if isinstance(graph, (VertexClustering, VertexCover)): - clustering = graph - graph = clustering.graph - - # Get layout - layout = kwds.get("layout", graph.layout()) - if isinstance(layout, str): - layout = graph.layout(layout) - - # Vertex coordinates - vcoord = layout.coords - - # mark groups: the used data structure is eventually the dict option: - # tuples of vertex indices as the keys, colors as the values. We - # convert other formats into that one here - if "mark_groups" not in kwds: - kwds["mark_groups"] = False - if kwds["mark_groups"] is False: - pass - elif (kwds["mark_groups"] is True) and (clustering is not None): - pass - elif isinstance(kwds["mark_groups"], (VertexClustering, VertexCover)): - if clustering is not None: - raise ValueError( - "mark_groups cannot override a clustering with another" - ) - else: - clustering = kwds["mark_groups"] - kwds["mark_groups"] = True - else: - try: - mg_iter = iter(kwds["mark_groups"]) - except TypeError: - raise TypeError("mark_groups is not in the right format") - kwds["mark_groups"] = dict(mg_iter) - - # If a clustering is set and marks are requested but without a specific - # colormap, make the colormap - - # Two things need coloring: vertices and groups/clusters (polygon) - # The coloring needs to be coordinated between the two. - if clustering is not None: - # If mark_groups is a dict, we don't need a default color dict, we - # can just use the mark_groups dict. If mark_groups is False and - # vertex_color is set, we don't need either because the colors are - # already fully specified. In all other cases, we need a default - # color dict. - if isinstance(kwds["mark_groups"], dict): - group_colordict = kwds["mark_groups"] - elif (kwds["mark_groups"] is False) and ("vertex_color" in kwds): - pass - else: - membership = clustering.membership - if isinstance(clustering, VertexCover): - membership = [x[0] for x in membership] - clusters = sorted(set(membership)) - n_colors = len(clusters) - cmap = mpl.cm.get_cmap("viridis") - colors = [cmap(1.0 * i / n_colors) for i in range(n_colors)] - cluster_colordict = {g: c for g, c in zip(clusters, colors)} - - # mark_groups if not explicitly marked - group_colordict = defaultdict(list) - for i, g in enumerate(membership): - color = cluster_colordict[g] - group_colordict[color].append(i) - del cluster_colordict - # Invert keys and values - group_colordict = {tuple(v): k for k, v in group_colordict.items()} - - # If mark_groups is set but not defined, make a default colormap - if kwds["mark_groups"] is True: - kwds["mark_groups"] = group_colordict - - if "vertex_color" not in kwds: - kwds["vertex_color"] = ['none' for m in membership] - for group_vs, color in group_colordict.items(): - for i in group_vs: - kwds["vertex_color"][i] = color - - # Now mark_groups is either a dict or False - # If vertex_color is not set, we can rely on mark_groups if a dict, - # else we need to make up the same colormap as if we were requested groups - if "vertex_color" not in kwds: - if isinstance(kwds["mark_groups"], dict): - membership = clustering.membership - if isinstance(clustering, VertexCover): - membership = [x[0] for x in membership] - - # Mark groups - if "mark_groups" in kwds and isinstance(kwds["mark_groups"], dict): - for idx, color in kwds["mark_groups"].items(): - points = [vcoord[i] for i in idx] - vertices = np.asarray(convex_hull(points, coords=True)) - # 15% expansion - vertices += 0.15 * (vertices - vertices.mean(axis=0)) - - # NOTE: we could include a corner cutting algorithm close to - # the vertices (e.g. Chaikin) for beautification, or a corner - # radius like it's done in the Cairo interface - polygon = mpl.patches.Polygon( - vertices, - facecolor=color, - alpha=0.3, - zorder=0, - edgecolor=color, - lw=2, - ) - ax.add_artist(polygon) - - # Vertex properties - nv = graph.vcount() - - # Vertex size - vsizes = kwds.get("vertex_size", 5) - # Enforce numpy array for sizes, because (1) we need the square and (2) - # they are needed to calculate autoshrinking of edges - if np.isscalar(vsizes): - vsizes = np.repeat(vsizes, nv) - else: - vsizes = np.asarray(vsizes) - # ax.scatter uses the *square* of diameter - vsizes **= 2 - - # Vertex color - c = kwds.get("vertex_color", "steelblue") - - # Vertex opacity - alpha = kwds.get("alpha", 1.0) - - # Vertex labels - label = kwds.get("vertex_label", None) - - # Vertex label size - label_size = kwds.get("vertex_label_size", mpl.rcParams["font.size"]) - - # Vertex zorder - vzorder = kwds.get("vertex_order", 2) - - # Vertex shapes - # mpl shapes use slightly different names from Cairo, but we want the - # API to feel consistent, so we use a conversion dictionary - shapes = kwds.get("vertex_shape", "o") - if shapes is not None: - if isinstance(shapes, str): - shapes = self._shape_dict.get(shapes, shapes) - elif isinstance(shapes, mmarkers.MarkerStyle): - pass - - # Scatter vertices - x, y = list(zip(*vcoord)) - ax.scatter(x, y, s=vsizes, c=c, marker=shapes, zorder=vzorder, alpha=alpha) - - # Vertex labels - if label is not None: - for i, lab in enumerate(label): - xi, yi = x[i], y[i] - ax.text(xi, yi, lab, fontsize=label_size) - - dx = max(x) - min(x) - dy = max(y) - min(y) - ax.set_xlim(min(x) - 0.05 * dx, max(x) + 0.05 * dx) - ax.set_ylim(min(y) - 0.05 * dy, max(y) + 0.05 * dy) - - # Edge properties - ne = graph.ecount() - ec = kwds.get("edge_color", "black") - edge_width = kwds.get("edge_width", 1) - arrow_width = kwds.get("edge_arrow_width", 2) - arrow_length = kwds.get("edge_arrow_size", 4) - ealpha = kwds.get("edge_alpha", 1.0) - ezorder = kwds.get("edge_order", 1.0) - try: - ezorder = float(ezorder) - ezorder = [ezorder] * ne - except TypeError: - pass - - # Decide whether we need to calculate the curvature of edges - # automatically -- and calculate them if needed. - autocurve = kwds.get("autocurve", None) - if autocurve or ( - autocurve is None - and "edge_curved" not in kwds - and "curved" not in graph.edge_attributes() - and graph.ecount() < 10000 - ): - from igraph import autocurve - - default = kwds.get("edge_curved", 0) - if default is True: - default = 0.5 - default = float(default) - ecurved = autocurve(graph, attribute=None, default=default) - elif "edge_curved" in kwds: - ecurved = kwds["edge_curved"] - elif "curved" in graph.edge_attributes(): - ecurved = graph.es["curved"] - else: - ecurved = [0] * ne - - # Arrow style for directed and undirected graphs - if graph.is_directed(): - arrowstyle = ArrowStyle( - "-|>", - head_length=arrow_length, - head_width=arrow_width, - ) - else: - arrowstyle = "-" - - # Edge coordinates and curvature - nloops = [0 for x in range(ne)] - arrows = [] - for ie, edge in enumerate(graph.es): - src, tgt = edge.source, edge.target - x1, y1 = vcoord[src] - x2, y2 = vcoord[tgt] - - # Loops require special treatment - if src == tgt: - # Find all non-loop edges - nloopstot = 0 - angles = [] - for tgtn in graph.neighbors(src): - if tgtn == src: - nloopstot += 1 - continue - xn, yn = vcoord[tgtn] - angles.append(180.0 / pi * atan2(yn - y1, xn - x1) % 360) - # with .neighbors(mode=ALL), which is default, loops are double - # counted - nloopstot //= 2 - angles = sorted(set(angles)) - - # Only loops or one non-loop - if len(angles) < 2: - ashift = angles[0] if angles else 270 - if nloopstot == 1: - # Only one self loop, use a quadrant only - angles = [(ashift + 135) % 360, (ashift + 225) % 360] - else: - nshift = 360.0 / nloopstot - angles = [ - (ashift + nshift * nloops[src]) % 360, - (ashift + nshift * (nloops[src] + 1)) % 360, - ] - nloops[src] += 1 - else: - angles.append(angles[0] + 360) - idiff = 0 - diff = 0 - for i in range(len(angles) - 1): - diffi = abs(angles[i + 1] - angles[i]) - if diffi > diff: - idiff = i - diff = diffi - angles = angles[idiff : idiff + 2] - ashift = angles[0] - nshift = (angles[1] - angles[0]) / nloopstot - angles = [ - (ashift + nshift * nloops[src]), - (ashift + nshift * (nloops[src] + 1)), - ] - nloops[src] += 1 - - # this is not great, but alright - angspan = angles[1] - angles[0] - if angspan < 180: - angmid1 = angles[0] + 0.1 * angspan - angmid2 = angles[1] - 0.1 * angspan - else: - angmid1 = angles[0] + 0.5 * (angspan - 180) + 45 - angmid2 = angles[1] - 0.5 * (angspan - 180) - 45 - aux1 = ( - x1 + 0.2 * dx * cos(pi / 180 * angmid1), - y1 + 0.2 * dy * sin(pi / 180 * angmid1), - ) - aux2 = ( - x1 + 0.2 * dx * cos(pi / 180 * angmid2), - y1 + 0.2 * dy * sin(pi / 180 * angmid2), - ) - start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) - end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) - - path = Path( - [start, aux1, aux2, end], - # Cubic bezier by mpl - codes=[1, 4, 4, 4], - ) - - else: - curved = ecurved[ie] - if curved: - aux1 = (2 * x1 + x2) / 3.0 - curved * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + curved * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - curved * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + curved * 0.5 * (x2 - x1) - start = shrink_vertex(ax, aux1, (x1, y1), vsizes[src]) - end = shrink_vertex(ax, aux2, (x2, y2), vsizes[tgt]) - - path = Path( - [start, aux1, aux2, end], - # Cubic bezier by mpl - codes=[1, 4, 4, 4], - ) - else: - start = shrink_vertex(ax, (x2, y2), (x1, y1), vsizes[src]) - end = shrink_vertex(ax, (x1, y1), (x2, y2), vsizes[tgt]) - - path = Path([start, end], codes=[1, 2]) - - arrow = FancyArrowPatch( - path=path, - arrowstyle=arrowstyle, - lw=edge_width, - color=ec, - alpha=ealpha, - zorder=ezorder[ie], + # Positional arguments are not used + if args: + warn( + "Positional arguments to plot functions are ignored " + "and will be deprecated soon.", + DeprecationWarning, ) - ax.add_artist(arrow) - - # Store arrows and their sources and targets for autoscaling - arrows.append((arrow, src, tgt)) - # Autoscaling during zoom, figure resize, reset axis limits - callback = callback_factory(ax, vcoord, vsizes, arrows) - ax.get_figure().canvas.mpl_connect("resize_event", callback) - ax.callbacks.connect("xlim_changed", callback) - ax.callbacks.connect("ylim_changed", callback) + self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) diff --git a/src/igraph/drawing/matplotlib/__init__.py b/src/igraph/drawing/matplotlib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/igraph/drawing/matplotlib/dendrogram.py b/src/igraph/drawing/matplotlib/dendrogram.py new file mode 100644 index 000000000..8be43b231 --- /dev/null +++ b/src/igraph/drawing/matplotlib/dendrogram.py @@ -0,0 +1,176 @@ +""" +Drawing routines to draw the matrices. + +This module provides implementations of matrix drawers. +""" + +from igraph.drawing.baseclasses import AbstractDrawer +from igraph.drawing.utils import str_to_orientation + +from .utils import find_matplotlib + +__all__ = ("MatplotlibDendrogramDrawer",) + +mpl, _ = find_matplotlib() + + +class MatplotlibDendrogramDrawer(AbstractDrawer): + """Matplotlib drawer object for dendrograms.""" + + def __init__(self, ax): + """Constructs the drawer and associates it to the given Axes. + + @param ax: the Axes on which we will draw + """ + super().__init__() + self.context = ax + + def _plot_item(self, dendro, ax, orientation, idx, x, y): + """Plots a dendrogram item to the given Cairo context + + @param context: the Cairo context we are plotting on + @param horiz: whether the dendrogram is horizontally oriented + @param idx: the index of the item + @param x: the X position of the item + @param y: the Y position of the item + """ + if dendro._names is None or dendro._names[idx] is None: + return + + if orientation == "lr": + ha, va, rotation = "right", "center", 0 + elif orientation == "rl": + ha, va, rotation = "left", "center", 0 + elif orientation == "tb": + ha, va, rotation = "center", "bottom", 90 + else: + ha, va, rotation = "center", "top", 90 + + # TODO: offset a little? But remember zoom in callbacks + + ax.text( + x, + y, + dendro._names[idx], + ha=ha, + va=va, + rotation=rotation, + ) + + def draw(self, dendro, orientation="lr", **kwds): + """Draws the given Dendrogram in a matplotlib Axes. + + @param dendro: the igraph.Dendrogram to plot. + @orientation: the direction of the plot. Accepted values are "lr" (root + on the right), "rl" (root on the left), "tb" (root at the bottom), + and "bt" (root at the top). A few aliases are available (see + L{igraph.utils.str_to_orientation}). + + Other keyword arguments are passed to mpl.patches.Polygon. + """ + from igraph.layout import Layout + + ax = self.context + + # Styling defaults + kwds["edgecolor"] = kwds.pop("color", "black") + if ("lw" not in kwds) and ("linewidth" not in kwds): + kwds["linewidth"] = 1 + + if dendro._names is None: + dendro._names = [str(x) for x in range(dendro._nitems)] + + orientation = str_to_orientation(orientation, reversed_vertical=True) + horiz = orientation in ("lr", "rl") + + # Calculate node coordinates + layout = Layout([(0, 0)] * dendro._nitems, dim=2) + inorder = dendro._traverse_inorder() + if not horiz: + x, y = 0, 0 + # Leaves + for idx, element in enumerate(inorder): + layout[element] = (x, 0) + x += 1 + + # Internal nodes + for id1, id2 in dendro._merges: + x = (layout[id1][0] + layout[id2][0]) / 2.0 + # TODO: this is a little restrictive, but alright + # for such a simple layout. More complex tree layouts + # should be in a separate Layout anyway + y += 1 + layout.append((x, y)) + + # Mirror or rotate the layout if necessary + if orientation == "bt": + layout.mirror(1) + else: + x, y = 0, 0 + for idx, element in enumerate(inorder): + layout[element] = (0, y) + y += 1 + + for id1, id2 in dendro._merges: + y = (layout[id1][1] + layout[id2][1]) / 2.0 + # TODO: this is a little restrictive, but alright + # for such a simple layout. More complex tree layouts + # should be in a separate Layout anyway + x += 1 + layout.append((x, y)) + + # Mirror or rotate the layout if necessary + if orientation == "rl": + layout.mirror(0) + + # Draw leaf names + # + # for idx in range(dendro._nitems): + # x, y = layout[idx] + # self._plot_item(dendro, ax, orientation, idx, x, y) + ticks, ticklabels = [], [] + for idx in range(dendro._nitems): + x, y = layout[idx] + if not horiz: + ticks.append(x) + else: + ticks.append(y) + ticklabels.append(dendro._names[idx]) + + if not horiz: + ax.set_xticks(ticks) + ax.set_xticklabels(ticklabels) + ax.set_yticks([]) + else: + ax.set_yticks(ticks) + ax.set_yticklabels(ticklabels) + ax.set_xticks([]) + + # Draw dendrogram lines + # Each path is a U-shaped fork + if not horiz: + for idx, (id1, id2) in enumerate(dendro._merges): + x0, y0 = layout[id1] + x1, y1 = layout[id2] + x2, y2 = layout[idx + dendro._nitems] + poly = mpl.patches.Polygon( + [[x0, y0], [x0, y2], [x1, y2], [x1, y1]], + closed=False, + facecolor="none", + **kwds, + ) + ax.add_patch(poly) + else: + for idx, (id1, id2) in enumerate(dendro._merges): + x0, y0 = layout[id1] + x1, y1 = layout[id2] + x2, y2 = layout[idx + dendro._nitems] + poly = mpl.patches.Polygon( + [[x0, y0], [x2, y0], [x2, y1], [x1, y1]], + closed=False, + facecolor="none", + **kwds, + ) + ax.add_patch(poly) + + ax.autoscale_view() diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py new file mode 100644 index 000000000..e2998fac6 --- /dev/null +++ b/src/igraph/drawing/matplotlib/edge.py @@ -0,0 +1,274 @@ +"""Drawers for various edge styles in Matplotlib graph plots.""" + +from math import atan2, cos, pi, sin + +from igraph.drawing.baseclasses import AbstractEdgeDrawer +from igraph.drawing.metamagic import AttributeCollectorBase +from igraph.drawing.matplotlib.utils import find_matplotlib +from igraph.drawing.utils import euclidean_distance, intersect_bezier_curve_and_circle + +__all__ = ("MatplotlibEdgeDrawer",) + +mpl, plt = find_matplotlib() + + +class MatplotlibEdgeDrawer(AbstractEdgeDrawer): + """Matplotlib-specific abstract edge drawer object.""" + + def __init__(self, context, palette): + """Constructs the edge drawer. + + @param context: a Matplotlib axes object on which the edges will be + drawn. + @param palette: the palette that can be used to map integer color + indices to colors when drawing edges + """ + self.context = context + self.palette = palette + self.VisualEdgeBuilder = self._construct_visual_edge_builder() + + def _construct_visual_edge_builder(self): + """Construct the visual edge builder that will collect the visual + attributes of an edge when it is being drawn.""" + + class VisualEdgeBuilder(AttributeCollectorBase): + """Builder that collects some visual properties of an edge for + drawing""" + + _kwds_prefix = "edge_" + arrow_size = 0.007 + arrow_width = 1.4 + color = ("#444", self.palette.get) + curved = (0.0, self._curvature_to_float) + label = None + label_color = ("black", self.palette.get) + label_size = 12.0 + font = "sans-serif" + width = 2.0 + + return VisualEdgeBuilder + + def draw_directed_edge(self, edge, src_vertex, dest_vertex): + if src_vertex == dest_vertex: # TODO + return self.draw_loop_edge(edge, src_vertex) + + ax = self.context + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + (x_src, y_src), (x_dest, y_dest) = src_vertex.position, dest_vertex.position + + # Draw the edge + path = {"vertices": [], "codes": []} + path["vertices"].append([x1, y1]) + path["codes"].append("MOVETO") + + if edge.curved: + # Calculate the curve + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + + # Coordinates of the control points of the Bezier curve + xc1, yc1 = aux1 + xc2, yc2 = aux2 + + # Determine where the edge intersects the circumference of the + # vertex shape: Tip of the arrow + x2, y2 = intersect_bezier_curve_and_circle( + x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 + ) + + # Calculate the arrow head coordinates + angle = atan2(y_dest - y2, x_dest - x2) # navid + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width + aux_points = [ + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), + ] + + # Midpoint of the base of the arrow triangle + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 + + # Vector representing the base of the arrow triangle + x_arrow_base_vec, y_arrow_base_vec = ( + aux_points[0][0] - aux_points[1][0] + ), (aux_points[0][1] - aux_points[1][1]) + + # Recalculate the curve such that it lands on the base of the arrow triangle + aux1 = (2 * x_src + x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (2 * y_src + y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) + aux2 = (x_src + 2 * x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (y_src + 2 * y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) + + # Offset the second control point (aux2) such that it falls precisely + # on the normal to the arrow base vector. Strictly speaking, + # offset_length is the offset length divided by the length of the + # arrow base vector. + offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + ( + y_arrow_mid - aux2[1] + ) * y_arrow_base_vec + offset_length /= ( + euclidean_distance(0, 0, x_arrow_base_vec, y_arrow_base_vec) ** 2 + ) + + aux2 = ( + aux2[0] + x_arrow_base_vec * offset_length, + aux2[1] + y_arrow_base_vec * offset_length, + ) + + # Draw the curve from the first vertex to the midpoint of the base + # of the arrow head + path["vertices"].append(aux1) + path["vertices"].append(aux2) + path["vertices"].append([x_arrow_mid, y_arrow_mid]) + path["codes"].extend(["CURVE4"] * 3) + + else: + # Determine where the edge intersects the circumference of the + # vertex shape. + x2, y2 = dest_vertex.shape.intersection_point( + x2, y2, x1, y1, dest_vertex.size + ) + + # Draw the arrowhead + angle = atan2(y_dest - y2, x_dest - x2) + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width + aux_points = [ + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), + ] + + # Midpoint of the base of the arrow triangle + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 + # Draw the line + path["vertices"].append([x_arrow_mid, y_arrow_mid]) + path["codes"].append("LINETO") + + # Draw the edge + stroke = mpl.patches.PathPatch( + mpl.path.Path( + path["vertices"], + codes=[getattr(mpl.path.Path, x) for x in path["codes"]], + ), + edgecolor=edge.color, + facecolor="none", + linewidth=edge.width, + ) + ax.add_patch(stroke) + + # Draw the arrow head + arrowhead = mpl.patches.Polygon( + [ + [x2, y2], + aux_points[0], + aux_points[1], + ], + closed=True, + facecolor=edge.color, + edgecolor="none", + ) + ax.add_patch(arrowhead) + + def draw_loop_edge(self, edge, vertex): + """Draws a loop edge. + + The default implementation draws a small circle. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param vertex: the vertex to which the edge is attached. Visual + properties are given again as attributes. + """ + ax = self.context + radius = vertex.size * 1.5 + center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 + center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 + stroke = mpl.patches.Arc( + (center_x, center_y), + radius / 2.0, + radius / 2.0, + theta1=0, + theta2=360.0, + linewidth=edge.width, + facecolor="none", + edgecolor=edge.color, + ) + # FIXME: make a PathCollection?? + ax.add_patch(stroke) + + def draw_undirected_edge(self, edge, src_vertex, dest_vertex): + """Draws an undirected edge. + + The default implementation of this method draws undirected edges + as straight lines. Loop edges are drawn as small circles. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. Visual properties are given + again as attributes. + @param dest_vertex: the target vertex. Visual properties are given + again as attributes. + """ + if src_vertex == dest_vertex: + return self.draw_loop_edge(edge, src_vertex) + + ax = self.context + + path = {"vertices": [], "codes": []} + path["vertices"].append(src_vertex.position) + path["codes"].append("MOVETO") + + if edge.curved: + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + + path["vertices"].append(aux1) + path["vertices"].append(aux2) + path["vertices"].append(dest_vertex.position) + path["codes"].extend(["CURVE4"] * 3) + else: + path["vertices"].append(dest_vertex.position) + path["codes"].append("LINETO") + + stroke = mpl.patches.PathPatch( + mpl.path.Path( + path["vertices"], + codes=[getattr(mpl.path.Path, x) for x in path["codes"]], + ), + edgecolor=edge.color, + facecolor="none", + linewidth=edge.width, + ) + # FIXME: make a PathCollection?? + ax.add_artist(stroke) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py new file mode 100644 index 000000000..4578249e2 --- /dev/null +++ b/src/igraph/drawing/matplotlib/graph.py @@ -0,0 +1,317 @@ +""" +Drawing routines to draw graphs. + +This module contains routines to draw graphs on: + + - Cairo surfaces (L{DefaultGraphDrawer}) + - Matplotlib axes (L{MatplotlibGraphDrawer}) + +It also contains routines to send an igraph graph directly to +(U{Cytoscape}) using the +(U{CytoscapeRPC plugin}), see +L{CytoscapeGraphDrawer}. L{CytoscapeGraphDrawer} can also fetch the current +network from Cytoscape and convert it to igraph format. +""" + +from warnings import warn + +from igraph._igraph import convex_hull, VertexSeq +from igraph.drawing.baseclasses import AbstractGraphDrawer +from igraph.drawing.utils import Point + +from .edge import MatplotlibEdgeDrawer +from .polygon import MatplotlibPolygonDrawer +from .utils import find_matplotlib +from .vertex import MatplotlibVertexDrawer + +__all__ = ("MatplotlibGraphDrawer",) + +_, plt = find_matplotlib() + +##################################################################### + + +class MatplotlibGraphDrawer(AbstractGraphDrawer): + """Graph drawer that uses a pyplot.Axes as context""" + + _shape_dict = { + "rectangle": "s", + "circle": "o", + "hidden": "none", + "triangle-up": "^", + "triangle-down": "v", + } + + def __init__( + self, + ax, + vertex_drawer_factory=MatplotlibVertexDrawer, + edge_drawer_factory=MatplotlibEdgeDrawer, + ): + """Constructs the graph drawer and associates it with the mpl Axes + + @param ax: the matplotlib Axes to draw into. + @param vertex_drawer_factory: a factory method that returns an + L{AbstractVertexDrawer} instance bound to the given Matplotlib axes. + The factory method must take three parameters: the axes and the + palette to be used for drawing colored vertices, and the layout of + the graph. The default vertex drawer is L{MatplotlibVertexDrawer}. + @param edge_drawer_factory: a factory method that returns an + L{AbstractEdgeDrawer} instance bound to a given Matplotlib Axes. + The factory method must take two parameters: the Axes and the palette + to be used for drawing colored edges. The default edge drawer is + L{MatplotlibEdgeDrawer}. + """ + self.ax = ax + self.vertex_drawer_factory = vertex_drawer_factory + self.edge_drawer_factory = edge_drawer_factory + + def draw(self, graph, *args, **kwds): + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + # Positional arguments are not used + if args: + warn( + "Positional arguments to plot functions are ignored " + "and will be deprecated soon.", + DeprecationWarning, + ) + + # Some abbreviations for sake of simplicity + directed = graph.is_directed() + ax = self.ax + + # Palette + palette = kwds.pop("palette", None) + + # Calculate/get the layout of the graph + layout = self.ensure_layout(kwds.get("layout", None), graph) + + # Decide whether we need to calculate the curvature of edges + # automatically -- and calculate them if needed. + autocurve = kwds.get("autocurve", None) + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in graph.edge_attributes() + and graph.ecount() < 10000 + ): + from igraph import autocurve + + default = kwds.get("edge_curved", 0) + if default is True: + default = 0.5 + default = float(default) + kwds["edge_curved"] = autocurve( + graph, + attribute=None, + default=default, + ) + + # Construct the vertex, edge and label drawers + vertex_drawer = self.vertex_drawer_factory(ax, palette, layout) + edge_drawer = self.edge_drawer_factory(ax, palette) + + # Construct the visual vertex/edge builders based on the specifications + # provided by the vertex_drawer and the edge_drawer + vertex_builder = vertex_drawer.VisualVertexBuilder(graph.vs, kwds) + edge_builder = edge_drawer.VisualEdgeBuilder(graph.es, kwds) + + # Draw the highlighted groups (if any) + if "mark_groups" in kwds: + mark_groups = kwds["mark_groups"] + + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + # Figure out what to do with mark_groups in order to be able to + # iterate over it and get memberlist-color pairs + if isinstance(mark_groups, dict): + # Dictionary mapping vertex indices or tuples of vertex + # indices to colors + group_iter = iter(mark_groups.items()) + elif isinstance(mark_groups, (VertexClustering, VertexCover)): + # Vertex clustering + group_iter = ((group, color) for color, group in enumerate(mark_groups)) + elif hasattr(mark_groups, "__iter__"): + # Lists, tuples, iterators etc + group_iter = iter(mark_groups) + else: + # False + group_iter = iter({}.items()) + + if kwds.get("legend", False): + legend_info = { + "handles": [], + "labels": [], + } + + # Iterate over color-memberlist pairs + for group, color_id in group_iter: + if not group or color_id is None: + continue + + color = palette.get(color_id) + + if isinstance(group, VertexSeq): + group = [vertex.index for vertex in group] + if not hasattr(group, "__iter__"): + raise TypeError("group membership list must be iterable") + + # Get the vertex indices that constitute the convex hull + hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] + + # Calculate the preferred rounding radius for the corners + corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) + + # Construct the polygon + polygon = [layout[idx] for idx in hull] + + if len(polygon) == 2: + # Expand the polygon (which is a flat line otherwise) + a, b = Point(*polygon[0]), Point(*polygon[1]) + c = corner_radius * (a - b).normalized() + n = Point(-c[1], c[0]) + polygon = [a + n, b + n, b - c, b - n, a - n, a + c] + else: + # Expand the polygon around its center of mass + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] + ) + polygon = [ + Point(*point).towards(center, -corner_radius) + for point in polygon + ] + + # Draw the hull + facecolor = (color[0], color[1], color[2], 0.25 * color[3]) + drawer = MatplotlibPolygonDrawer(ax) + drawer.draw( + polygon, + corner_radius=corner_radius, + facecolor=facecolor, + edgecolor=color, + ) + + if kwds.get("legend", False): + legend_info["handles"].append( + plt.Rectangle( + (0, 0), + 0, + 0, + facecolor=facecolor, + edgecolor=color, + ) + ) + legend_info["labels"].append(str(color_id)) + + if kwds.get("legend", False): + ax.legend( + legend_info["handles"], + legend_info["labels"], + ) + + # Determine the order in which we will draw the vertices and edges + vertex_order = self._determine_vertex_order(graph, kwds) + edge_order = self._determine_edge_order(graph, kwds) + + # Construct the iterator that we will use to draw the vertices + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vs, vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ( + (vs[i], vertex_builder[i], layout[i]) for i in vertex_order + ) + + # Draw the vertices + drawer_method = vertex_drawer.draw + for vertex, visual_vertex, coords in vertex_coord_iter: + drawer_method(visual_vertex, vertex, coords) + + # Construct the iterator that we will use to draw the vertex labels + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) + + # Draw the vertex labels + for vertex, coords in vertex_coord_iter: + if vertex.label is None: + continue + + label_size = kwds.get( + "vertex_label_size", + vertex.label_size, + ) + + ax.text( + *coords, + vertex.label, + fontsize=label_size, + # TODO: alignment, overlap, offset, etc. + ) + + # Construct the iterator that we will use to draw the edges + es = graph.es + if edge_order is None: + # Default edge order + edge_coord_iter = zip(es, edge_builder) + else: + # Specified edge order + edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) + + # Draw the edges + if directed: + drawer_method = edge_drawer.draw_directed_edge + else: + drawer_method = edge_drawer.draw_undirected_edge + for edge, visual_edge in edge_coord_iter: + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + drawer_method(visual_edge, src_vertex, dest_vertex) + + # Draw the edge labels + labels = kwds.get("edge_label", None) + if labels is not None: + edge_label_iter = ( + (labels[i], edge_builder[i], graph.es[i]) for i in range(graph.ecount()) + ) + for label, visual_edge, edge in edge_label_iter: + # Ask the edge drawer to propose an anchor point for the label + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + (x, y), (halign, valign) = edge_drawer.get_label_position( + edge, + src_vertex, + dest_vertex, + ) + + ax.text( + x, + y, + label, + fontsize=visual_edge.label_size, + color=visual_edge.label_color, + ha=halign, + va=valign, + # TODO: offset, etc. + ) + + # Despine + ax.spines["right"].set_visible(False) + ax.spines["top"].set_visible(False) + ax.spines["left"].set_visible(False) + ax.spines["bottom"].set_visible(False) + + # Remove axis ticks + ax.set_xticks([]) + ax.set_yticks([]) + + ax.autoscale_view() diff --git a/src/igraph/drawing/matplotlib/histogram.py b/src/igraph/drawing/matplotlib/histogram.py new file mode 100644 index 000000000..0084875c1 --- /dev/null +++ b/src/igraph/drawing/matplotlib/histogram.py @@ -0,0 +1,37 @@ +"""This module provides implementation for a Matplotlib-specific histogram drawer.""" + +from igraph.drawing.baseclasses import AbstractDrawer + +__all__ = ("MatplotlibHistogramDrawer",) + + +class MatplotlibHistogramDrawer(AbstractDrawer): + """Matplotlib drawer object for matrices.""" + + def __init__(self, ax): + """Constructs the drawer and associates it to the given Axes. + + @param ax: the Axes on which we will draw + """ + self.context = ax + + def draw(self, matrix, **kwds): + """Draws the given Matrix in a matplotlib Axes. + + @param matrix: the igraph.Histogram to plot. + + """ + ax = self.context + + xmin = kwds.get("min", self._min) + ymin = 0 + xmax = kwds.get("max", self._max) + ymax = kwds.get("max_value", max(self._bins)) + width = self._bin_width + + x = [self._min + width * i for i, _ in enumerate(self._bins)] + y = self._bins + # Draw the boxes/bars + ax.bar(x, y, align='left') + ax.set_xlim(xmin, xmax) + ax.set_ylim(ymin, ymax) diff --git a/src/igraph/drawing/matplotlib/matrix.py b/src/igraph/drawing/matplotlib/matrix.py new file mode 100644 index 000000000..5a255ee08 --- /dev/null +++ b/src/igraph/drawing/matplotlib/matrix.py @@ -0,0 +1,26 @@ +"""This module provides implementation for a Matplotlib-specific matrix drawer.""" + +from igraph.drawing.baseclasses import AbstractDrawer + +__all__ = ("MatplotlibMatrixDrawer",) + + +class MatplotlibMatrixDrawer(AbstractDrawer): + """Matplotlib drawer object for matrices.""" + + def __init__(self, ax): + """Constructs the drawer and associates it to the given Axes. + + @param ax: the Axes on which we will draw + """ + self.context = ax + + def draw(self, matrix, **kwds): + """Draws the given Matrix in a matplotlib Axes. + + @param matrix: the igraph.Matrix to plot. + + Keyword arguments are passed to Axes.imshow. + """ + ax = self.context + ax.imshow(matrix.data, interpolation="nearest", **kwds) diff --git a/src/igraph/drawing/matplotlib/palette.py b/src/igraph/drawing/matplotlib/palette.py new file mode 100644 index 000000000..fb9fc3850 --- /dev/null +++ b/src/igraph/drawing/matplotlib/palette.py @@ -0,0 +1,49 @@ +"""This module provides implementation for a Matplotlib-specific palette drawer.""" + +from igraph.drawing.baseclasses import AbstractDrawer + +__all__ = ("MatplotlibPaletteDrawer",) + + +class MatplotlibPaletteDrawer(AbstractDrawer): + """Matplotlib drawer object for matrices.""" + + def __init__(self, ax): + """Constructs the drawer and associates it to the given Axes. + + @param ax: the Axes on which we will draw + """ + self.context = ax + + def draw(self, matrix, **kwds): + """Draws the given Matrix in a matplotlib Axes. + + @param matrix: the igraph.Histogram to plot. + + """ + from igraph.datatypes import Matrix + from igraph.drawing.utils import find_matplotlib, str_to_orientation + + mpl, _ = find_matplotlib() + ax = self.context + + orientation = str_to_orientation(kwds.get("orientation", "lr")) + + # Construct a matrix and plot that + indices = list(range(len(self))) + if orientation in ("rl", "bt"): + indices.reverse() + if orientation in ("lr", "rl"): + matrix = Matrix([indices]) + else: + matrix = Matrix([[i] for i in indices]) + + cmap = mpl.colors.ListedColormap( + [self.get(i) for i in range(self.length)], + ) + matrix.__plot__( + 'matplotlib', + ax, + cmap=cmap, + **kwds, + ) diff --git a/src/igraph/drawing/matplotlib/polygon.py b/src/igraph/drawing/matplotlib/polygon.py new file mode 100644 index 000000000..9267b806d --- /dev/null +++ b/src/igraph/drawing/matplotlib/polygon.py @@ -0,0 +1,88 @@ +from igraph.drawing.utils import calculate_corner_radii +from igraph.utils import consecutive_pairs + +from .utils import find_matplotlib + +__all__ = ("MatplotlibPolygonDrawer",) + +mpl, plt = find_matplotlib() + + +class MatplotlibPolygonDrawer: + """Class that is used to draw polygons in matplotlib. + + The corner points of the polygon can be set by the C{points} + property of the drawer, or passed at construction time. Most + drawing methods in this class also have an extra C{points} + argument that can be used to override the set of points in the + C{points} property.""" + + def __init__(self, ax): + """Constructs a new polygon drawer that draws on the given + Matplotlib axes. + + @param ax: the matplotlib Axes to draw on + @param points: the list of corner points + """ + self.context = ax + + def draw(self, points, corner_radius=0, **kwds): + """Draws a polygon to the associated axes. + + @param points: the coordinates of the corners of the polygon, + in clockwise or counter-clockwise order, or C{None} if we are + about to use the C{points} property of the class. + @param corner_radius: if zero, an ordinary polygon will be drawn. + If positive, the corners of the polygon will be rounded with + the given radius. + """ + if len(points) < 2: + # Well, a polygon must have at least two corner points + return + + ax = self.context + if corner_radius <= 0: + # No rounded corners, this is simple + stroke = mpl.patches.Polygon(points, **kwds) + ax.add_patch(stroke) + + # Rounded corners. First, we will take each side of the + # polygon and find what the corner radius should be on + # each corner. If the side is longer than 2r (where r is + # equal to corner_radius), the radius allowed by that side + # is r; if the side is shorter, the radius is the length + # of the side / 2. For each corner, the final corner radius + # is the smaller of the radii on the two sides adjacent to + # the corner. + corner_radii = calculate_corner_radii(points, corner_radius) + + # Okay, move to the last corner, adjusted by corner_radii[-1] + # towards the first corner + path = [] + codes = [] + path.append((points[-1].towards(points[0], corner_radii[-1]))) + codes.append(mpl.path.Path.MOVETO) + + # Now, for each point in points, draw a line towards the + # corner, stopping before it in a distance of corner_radii[idx], + # then draw the corner + u = points[-1] + for idx, (v, w) in enumerate(consecutive_pairs(points, True)): + radius = corner_radii[idx] + path.append(v.towards(u, radius)) + codes.append(mpl.path.Path.LINETO) + + aux1 = v.towards(u, radius / 2) + aux2 = v.towards(w, radius / 2) + + path.append(aux1) + path.append(aux2) + path.append(v.towards(w, corner_radii[idx])) + codes.extend([mpl.path.Path.CURVE4] * 3) + u = v + + stroke = mpl.patches.PathPatch( + mpl.path.Path(path, codes=codes, closed=True), + **kwds, + ) + ax.add_patch(stroke) diff --git a/src/igraph/drawing/matplotlib/utils.py b/src/igraph/drawing/matplotlib/utils.py new file mode 100644 index 000000000..3c842c656 --- /dev/null +++ b/src/igraph/drawing/matplotlib/utils.py @@ -0,0 +1,26 @@ +from igraph.drawing.utils import FakeModule +from typing import Any + +__all__ = ("find_matplotlib", ) + + +def find_matplotlib() -> Any: + """Tries to import the ``matplotlib`` Python module if it is installed. + Returns a fake module if everything fails. + """ + try: + import matplotlib as mpl + + has_mpl = True + except ImportError: + mpl = FakeModule("You need to install matplotlib to use this functionality") + has_mpl = False + + if has_mpl: + import matplotlib.pyplot as plt + else: + plt = FakeModule( + "You need to install matplotlib.pyplot to use this functionality" + ) + + return mpl, plt diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py new file mode 100644 index 000000000..3a7db0d90 --- /dev/null +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -0,0 +1,71 @@ +"""This module provides implementations of Matplotlib-specific vertex drawers, +i.e. drawers that the Matplotlib graph drawer will use to draw vertices. +""" + +from math import pi + +from igraph.drawing.baseclasses import AbstractVertexDrawer +from igraph.drawing.metamagic import AttributeCollectorBase +from igraph.drawing.shapes import ShapeDrawerDirectory + +__all__ = ("MatplotlibVertexDrawer",) + + +class MatplotlibVertexDrawer(AbstractVertexDrawer): + """Matplotlib backend-specific vertex drawer.""" + + def __init__(self, ax, palette, layout): + self.context = ax + super().__init__(palette, layout) + self.VisualVertexBuilder = self._construct_visual_vertex_builder() + + def _construct_visual_vertex_builder(self): + class VisualVertexBuilder(AttributeCollectorBase): + """Collects some visual properties of a vertex for drawing""" + + _kwds_prefix = "vertex_" + color = ("red", self.palette.get) + frame_color = ("black", self.palette.get) + frame_width = 1.0 + label = None + label_angle = -pi / 2 + label_dist = 0.0 + label_color = ("black", self.palette.get) + font = "sans-serif" + label_size = 12.0 + # FIXME? mpl.rcParams["font.size"]) + position = dict(func=self.layout.__getitem__) + shape = ("circle", ShapeDrawerDirectory.resolve_default) + size = 0.2 + width = None + height = None + zorder = 2 + + return VisualVertexBuilder + + def draw(self, visual_vertex, vertex, coords): + ax = self.context + + width = ( + visual_vertex.width + if visual_vertex.width is not None + else visual_vertex.size + ) + height = ( + visual_vertex.height + if visual_vertex.height is not None + else visual_vertex.size + ) + + stroke = visual_vertex.shape.draw_path( + ax, + coords[0], + coords[1], + width, + height, + facecolor=visual_vertex.color, + edgecolor=visual_vertex.frame_color, + linewidth=visual_vertex.frame_width, + zorder=visual_vertex.zorder, + ) + ax.add_patch(stroke) diff --git a/src/igraph/drawing/plotly/__init__.py b/src/igraph/drawing/plotly/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/igraph/drawing/plotly/edge.py b/src/igraph/drawing/plotly/edge.py new file mode 100644 index 000000000..410b04d5f --- /dev/null +++ b/src/igraph/drawing/plotly/edge.py @@ -0,0 +1,270 @@ +"""Drawers for various edge styles in Matplotlib graph plots.""" + +from math import atan2, cos, pi, sin + +from igraph.drawing.baseclasses import AbstractEdgeDrawer +from igraph.drawing.metamagic import AttributeCollectorBase +from igraph.drawing.plotly.utils import find_plotly, format_path_step, format_arc, format_rgba +from igraph.drawing.utils import Point, euclidean_distance, intersect_bezier_curve_and_circle + +__all__ = ("PlotlyEdgeDrawer",) + +plotly = find_plotly() + + +class PlotlyEdgeDrawer(AbstractEdgeDrawer): + """Matplotlib-specific abstract edge drawer object.""" + + def __init__(self, context, palette): + """Constructs the edge drawer. + + @param context: a plotly Figure object on which the edges will be + drawn. + @param palette: the palette that can be used to map integer color + indices to colors when drawing edges + """ + self.context = context + self.palette = palette + self.VisualEdgeBuilder = self._construct_visual_edge_builder() + + def _construct_visual_edge_builder(self): + """Construct the visual edge builder that will collect the visual + attributes of an edge when it is being drawn.""" + + class VisualEdgeBuilder(AttributeCollectorBase): + """Builder that collects some visual properties of an edge for + drawing""" + + _kwds_prefix = "edge_" + arrow_size = 0.007 + arrow_width = 1.4 + color = "#444" + curved = (0.0, self._curvature_to_float) + label = None + label_color = ("black", self.palette.get) + label_size = 12.0 + font = "sans-serif" + width = 2.0 + + return VisualEdgeBuilder + + def draw_directed_edge(self, edge, src_vertex, dest_vertex): + if src_vertex == dest_vertex: # TODO + return self.draw_loop_edge(edge, src_vertex) + + fig = self.context + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + (x_src, y_src), (x_dest, y_dest) = src_vertex.position, dest_vertex.position + + # Draw the edge + path = [ + format_path_step("M", [x1, y1]), + ] + + if edge.curved: + # Calculate the curve + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + + # Coordinates of the control points of the Bezier curve + xc1, yc1 = aux1 + xc2, yc2 = aux2 + + # Determine where the edge intersects the circumference of the + # vertex shape: Tip of the arrow + x2, y2 = intersect_bezier_curve_and_circle( + x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 + ) + + # Calculate the arrow head coordinates + angle = atan2(y_dest - y2, x_dest - x2) # navid + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width + aux_points = [ + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), + ] + + # Midpoint of the base of the arrow triangle + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 + + # Vector representing the base of the arrow triangle + x_arrow_base_vec, y_arrow_base_vec = ( + aux_points[0][0] - aux_points[1][0] + ), (aux_points[0][1] - aux_points[1][1]) + + # Recalculate the curve such that it lands on the base of the arrow triangle + aux1 = (2 * x_src + x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (2 * y_src + y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) + aux2 = (x_src + 2 * x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( + y_arrow_mid - y_src + ), (y_src + 2 * y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( + x_arrow_mid - x_src + ) + + # Offset the second control point (aux2) such that it falls precisely + # on the normal to the arrow base vector. Strictly speaking, + # offset_length is the offset length divided by the length of the + # arrow base vector. + offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + ( + y_arrow_mid - aux2[1] + ) * y_arrow_base_vec + offset_length /= ( + euclidean_distance(0, 0, x_arrow_base_vec, y_arrow_base_vec) ** 2 + ) + + aux2 = ( + aux2[0] + x_arrow_base_vec * offset_length, + aux2[1] + y_arrow_base_vec * offset_length, + ) + + # Draw the curve from the first vertex to the midpoint of the base + # of the arrow head + path.append(format_path_step( + "C", [aux1, aux2, [x_arrow_mid, y_arrow_mid]] + )) + + else: + # FIXME: this is tricky in plotly, let's skip for now + ## Determine where the edge intersects the circumference of the + ## vertex shape. + #x2, y2 = dest_vertex.shape.intersection_point( + # x2, y2, x1, y1, dest_vertex.size + #) + + # Draw the arrowhead + angle = atan2(y_dest - y2, x_dest - x2) + arrow_size = 15.0 * edge.arrow_size + arrow_width = 10.0 / edge.arrow_width + aux_points = [ + ( + x2 - arrow_size * cos(angle - pi / arrow_width), + y2 - arrow_size * sin(angle - pi / arrow_width), + ), + ( + x2 - arrow_size * cos(angle + pi / arrow_width), + y2 - arrow_size * sin(angle + pi / arrow_width), + ), + ] + + # Midpoint of the base of the arrow triangle + x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( + aux_points[0][1] + aux_points[1][1] + ) / 2.0 + # Draw the line + path.append(format_path_step( + "L", Point(x_arrow_mid, y_arrow_mid), + )) + + path = ' '.join(path) + + # Draw the edge + stroke = dict( + type='path', + path=path, + line_color=format_rgba(edge.color), + line_width=edge.width, + ) + fig.add_shape(stroke) + + # Draw the arrow head + arrowhead = plotly.graph_objects.Scatter( + x=[x2, aux_points[0][0], aux_points[1][0], x2], + y=[y2, aux_points[0][1], aux_points[1][1], y2], + fillcolor=format_rgba(edge.color), + mode="lines", + ) + fig.add_trace(arrowhead) + + def draw_loop_edge(self, edge, vertex): + """Draws a loop edge. + + The default implementation draws a small circle. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param vertex: the vertex to which the edge is attached. Visual + properties are given again as attributes. + """ + fig = self.context + radius = vertex.size * 1.5 + center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 + center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 + stroke = dict( + type='path', + path=format_arc( + (center_x, center_y), + radius / 2.0, + radius / 2.0, + theta1=0, + theta2=360.0, + ), + line_color=edge.color, + line_width=edge.width, + ) + fig.add_shape(stroke) + + def draw_undirected_edge(self, edge, src_vertex, dest_vertex): + """Draws an undirected edge. + + The default implementation of this method draws undirected edges + as straight lines. Loop edges are drawn as small circles. + + @param edge: the edge to be drawn. Visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. Visual properties are given + again as attributes. + @param dest_vertex: the target vertex. Visual properties are given + again as attributes. + """ + if src_vertex == dest_vertex: + return self.draw_loop_edge(edge, src_vertex) + + fig = self.context + + path = [ + format_path_step("M", src_vertex.position) + ] + + if edge.curved: + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + + path.append(format_path_step( + "C", [aux1, aux2, dest_vertex.position], + )) + + else: + path.append(format_path_step( + "L", dest_vertex.position, + )) + + path = ' '.join(path) + + stroke = dict( + type='path', + path=path, + line_color=format_rgba(edge.color), + line_width=edge.width, + ) + fig.add_shape(stroke) diff --git a/src/igraph/drawing/plotly/graph.py b/src/igraph/drawing/plotly/graph.py new file mode 100644 index 000000000..e45e7d3db --- /dev/null +++ b/src/igraph/drawing/plotly/graph.py @@ -0,0 +1,281 @@ +""" +Drawing routines to draw graphs. + +This module contains routines to draw graphs on plotly surfaces. + +""" + +from collections import defaultdict +from warnings import warn + +from igraph._igraph import convex_hull, VertexSeq +from igraph.drawing.baseclasses import AbstractGraphDrawer +from igraph.drawing.utils import Point + +from .edge import PlotlyEdgeDrawer +from .polygon import PlotlyPolygonDrawer +from .utils import find_plotly, format_rgba +from .vertex import PlotlyVerticesDrawer + +__all__ = ("PlotlyGraphDrawer",) + +plotly = find_plotly() + +##################################################################### + + +class PlotlyGraphDrawer(AbstractGraphDrawer): + """Graph drawer that uses a pyplot.Axes as context""" + + # These need conversions, plus default passthrough for arbitrary + # plotly shapes + _shape_dict = { + "rectangle": "square", + "hidden": "none", + } + + def __init__( + self, + fig, + vertex_drawer_factory=PlotlyVerticesDrawer, + edge_drawer_factory=PlotlyEdgeDrawer, + ): + """Constructs the graph drawer and associates it with the plotly Figure + + @param fig: the plotly.graph_objects.Figure to draw into. + + """ + self.fig = fig + self.vertex_drawer_factory = vertex_drawer_factory + self.edge_drawer_factory = edge_drawer_factory + + def draw(self, graph, *args, **kwds): + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + # Positional arguments are not used + if args: + warn( + "Positional arguments to plot functions are ignored " + "and will be deprecated soon.", + DeprecationWarning, + ) + + # Some abbreviations for sake of simplicity + directed = graph.is_directed() + fig = self.fig + + # Palette + palette = kwds.pop("palette", None) + + # Calculate/get the layout of the graph + layout = self.ensure_layout(kwds.get("layout", None), graph) + + # Decide whether we need to calculate the curvature of edges + # automatically -- and calculate them if needed. + autocurve = kwds.get("autocurve", None) + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in graph.edge_attributes() + and graph.ecount() < 10000 + ): + from igraph import autocurve + + default = kwds.get("edge_curved", 0) + if default is True: + default = 0.5 + default = float(default) + kwds["edge_curved"] = autocurve( + graph, + attribute=None, + default=default, + ) + + # Construct the vertex, edge and label drawers + vertex_drawer = self.vertex_drawer_factory(fig, palette, layout) + edge_drawer = self.edge_drawer_factory(fig, palette) + + # Construct the visual edge builders based on the specifications + # provided by the edge_drawer + vertex_builder = vertex_drawer.VisualVertexBuilder(graph.vs, kwds) + edge_builder = edge_drawer.VisualEdgeBuilder(graph.es, kwds) + + # Draw the highlighted groups (if any) + if "mark_groups" in kwds: + mark_groups = kwds["mark_groups"] + + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + # Figure out what to do with mark_groups in order to be able to + # iterate over it and get memberlist-color pairs + if isinstance(mark_groups, dict): + # Dictionary mapping vertex indices or tuples of vertex + # indices to colors + group_iter = iter(mark_groups.items()) + elif isinstance(mark_groups, (VertexClustering, VertexCover)): + # Vertex clustering + group_iter = ((group, color) for color, group in enumerate(mark_groups)) + elif hasattr(mark_groups, "__iter__"): + # Lists, tuples, iterators etc + group_iter = iter(mark_groups) + else: + # False + group_iter = iter({}.items()) + + # Iterate over color-memberlist pairs + for group, color_id in group_iter: + if not group or color_id is None: + continue + + color = palette.get(color_id) + + if isinstance(group, VertexSeq): + group = [vertex.index for vertex in group] + if not hasattr(group, "__iter__"): + raise TypeError("group membership list must be iterable") + + # Get the vertex indices that constitute the convex hull + hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] + + # Calculate the preferred rounding radius for the corners + #FIXME + corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) + + # Construct the polygon + polygon = [layout[idx] for idx in hull] + + if len(polygon) == 2: + # Expand the polygon (which is a flat line otherwise) + a, b = Point(*polygon[0]), Point(*polygon[1]) + c = corner_radius * (a - b).normalized() + n = Point(-c[1], c[0]) + polygon = [a + n, b + n, b - c, b - n, a - n, a + c] + else: + # Expand the polygon around its center of mass + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] + ) + polygon = [ + Point(*point).towards(center, -corner_radius) + for point in polygon + ] + + # Draw the hull + facecolor = (color[0], color[1], color[2], 0.25 * color[3]) + drawer = PlotlyPolygonDrawer(fig) + drawer.draw( + polygon, + corner_radius=corner_radius, + fillcolor=format_rgba(facecolor), + line_color=format_rgba(color), + ) + + if kwds.get("legend", False): + # Proxy artist for legend + fig.add_trace( + plotly.graph_objects.Bar( + name=str(color_id), + x=[], y=[], + fillcolor=facecolor, + line_color=color, + ) + ) + + if kwds.get("legend", False): + fig.update_layout(showlegend=True) + + # Determine the order in which we will draw the vertices and edges + vertex_order = self._determine_vertex_order(graph, kwds) + edge_order = self._determine_edge_order(graph, kwds) + + # Construct the iterator that we will use to draw the vertices + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vs, vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ( + (vs[i], vertex_builder[i], layout[i]) for i in vertex_order + ) + + # Draw the vertices + drawer_method = vertex_drawer.draw + for vertex, visual_vertex, coords in vertex_coord_iter: + drawer_method(visual_vertex, vertex, coords) + + # Construct the iterator that we will use to draw the vertex labels + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) + + # Draw the vertex labels + for vertex, coords in vertex_coord_iter: + vertex_drawer.draw_label(vertex, coords, **kwds) + + # Construct the iterator that we will use to draw the edges + es = graph.es + if edge_order is None: + # Default edge order + edge_coord_iter = zip(es, edge_builder) + else: + # Specified edge order + edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) + + # Draw the edges and labels + # We need the vertex builder to get the layout and offsets + if directed: + drawer_method = edge_drawer.draw_directed_edge + else: + drawer_method = edge_drawer.draw_undirected_edge + for edge, visual_edge in edge_coord_iter: + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + drawer_method(visual_edge, src_vertex, dest_vertex) + + # Draw the edge labels + labels = kwds.get("edge_label", None) + if labels is not None: + edge_label_iter = ( + (labels[i], edge_builder[i], graph.es[i]) for i in range(graph.ecount()) + ) + lab_args = { + 'text': [], + 'x': [], + 'y': [], + 'color': [], + # FIXME: horizontal/vertical alignment, offset, etc? + } + for label, visual_edge, edge in edge_label_iter: + # Ask the edge drawer to propose an anchor point for the label + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + (x, y), (halign, valign) = edge_drawer.get_label_position( + edge, + src_vertex, + dest_vertex, + ) + if label is None: + continue + + lab_args['text'].append(label) + lab_args['x'].append(x) + lab_args['y'].append(y) + lab_args['color'].append(visual_edge.label_color) + stroke = plotly.graph_objects.Scatter( + mode='text', + **lab_args, + ) + fig.add_trace(stroke) + + # Despine + fig.update_layout( + yaxis={'visible': False, 'showticklabels': False}, + xaxis={'visible': False, 'showticklabels': False}, + ) diff --git a/src/igraph/drawing/plotly/polygon.py b/src/igraph/drawing/plotly/polygon.py new file mode 100644 index 000000000..c0978e42b --- /dev/null +++ b/src/igraph/drawing/plotly/polygon.py @@ -0,0 +1,104 @@ +from igraph.drawing.utils import calculate_corner_radii +from igraph.utils import consecutive_pairs + +from .utils import find_plotly, format_path_step + +__all__ = ("PlotlyPolygonDrawer",) + +plotly = find_plotly() + + +class PlotlyPolygonDrawer: + """Class that is used to draw polygons in matplotlib. + + The corner points of the polygon can be set by the C{points} + property of the drawer, or passed at construction time. Most + drawing methods in this class also have an extra C{points} + argument that can be used to override the set of points in the + C{points} property.""" + + def __init__(self, fig): + """Constructs a new polygon drawer that draws on the given + Matplotlib axes. + + @param fig: the plotly Figure to draw on + @param points: the list of corner points + """ + self.context = fig + + def draw(self, points, corner_radius=0, **kwds): + """Draws a polygon to the associated axes. + + @param points: the coordinates of the corners of the polygon, + in clockwise or counter-clockwise order, or C{None} if we are + about to use the C{points} property of the class. + @param corner_radius: if zero, an ordinary polygon will be drawn. + If positive, the corners of the polygon will be rounded with + the given radius. + """ + if len(points) < 2: + # Well, a polygon must have at least two corner points + return + + fig = self.context + if corner_radius <= 0: + # No rounded corners, this is simple + # We need to repeat the initial point to get a closed shape + x = [p[0] for p in points] + [points[0][0]] + y = [p[1] for p in points] + [points[0][1]] + kwds['mode'] = kwds.get('mode', 'line') + stroke = plotly.graph_objects.Scatter( + x=x, + y=y, + **kwds, + ) + fig.add_trace(stroke) + + # Rounded corners. First, we will take each side of the + # polygon and find what the corner radius should be on + # each corner. If the side is longer than 2r (where r is + # equal to corner_radius), the radius allowed by that side + # is r; if the side is shorter, the radius is the length + # of the side / 2. For each corner, the final corner radius + # is the smaller of the radii on the two sides adjacent to + # the corner. + corner_radii = calculate_corner_radii(points, corner_radius) + + # Okay, move to the last corner, adjusted by corner_radii[-1] + # towards the first corner + path = [] + path.append(format_path_step( + "M", + [points[-1].towards(points[0], corner_radii[-1])], + )) + + # Now, for each point in points, draw a line towards the + # corner, stopping before it in a distance of corner_radii[idx], + # then draw the corner + u = points[-1] + for idx, (v, w) in enumerate(consecutive_pairs(points, True)): + radius = corner_radii[idx] + path.append(format_path_step( + "L", + [v.towards(u, radius)], + )) + + aux1 = v.towards(u, radius / 2) + aux2 = v.towards(w, radius / 2) + + path.append(format_path_step( + "C", + [aux1, aux2, v.towards(w, corner_radii[idx])], + )) + u = v + + # Close path + path = "".join(path).strip(" ")+" Z" + stroke = dict( + type="path", + path=path, + **kwds, + ) + fig.update_layout( + shapes=[stroke], + ) diff --git a/src/igraph/drawing/plotly/utils.py b/src/igraph/drawing/plotly/utils.py new file mode 100644 index 000000000..be28dfc50 --- /dev/null +++ b/src/igraph/drawing/plotly/utils.py @@ -0,0 +1,74 @@ +from igraph.drawing.utils import FakeModule, Point +from typing import Any + +__all__ = ("find_plotly", ) + + +def find_plotly() -> Any: + """Tries to import the ``plotly`` Python module if it is installed. + Returns a fake module if everything fails. + """ + try: + import plotly + + except ImportError: + plotly = FakeModule("You need to install plotly to use this functionality") + + return plotly + + +def format_path_step(code, point_or_points): + """Format step in SVG path for plotly""" + if isinstance(point_or_points[0], (float, int)): + points = [point_or_points] + else: + points = point_or_points + + step = f"{code}" + for point in points: + x, y = point[0], point[1] + step += f" {x},{y}" + return step + + +# Adapted from https://community.plotly.com/t/arc-shape-with-path/7205/3 +def format_arc(center, radius_x, radius_y, theta1, theta2, N=100, closed=False): + """Approximation of an SVG-style arc + + NOTE: plotly does not currently support the native SVG "A/a" commands""" + import math + + xc, yc = center + dt = 1.0 * (theta2 - theta1) + t = [theta1 + dt * i / (N-1) for i in range(N)] + x = [xc + radius_x * math.cos(i) for i in t] + y = [yc + radius_y * math.sin(i) for i in t] + path = f'M {x[0]}, {y[0]}' + for k in range(1, len(t)): + path += f'L{x[k]}, {y[k]}' + if closed: + path += ' Z' + return path + + +def format_rgba(color): + """Format colors in a way understood by plotly""" + if isinstance(color, str): + return color + + if isinstance(color, float): + if color > 1: + color /= 255. + color = [color] * 3 + + r = int(255 * color[0]) + g = int(255 * color[1]) + b = int(255 * color[2]) + if len(color) > 3: + a = int(255 * color[3]) + else: + a = 255 + + colstr = f'rgba({r},{g},{b},{a})' + return colstr + diff --git a/src/igraph/drawing/plotly/vertex.py b/src/igraph/drawing/plotly/vertex.py new file mode 100644 index 000000000..4d6f6df52 --- /dev/null +++ b/src/igraph/drawing/plotly/vertex.py @@ -0,0 +1,95 @@ +"""Vertices drawer. Unlike other backends, all vertices are drawn at once""" + +from math import pi + +from igraph.drawing.baseclasses import AbstractVertexDrawer +from igraph.drawing.metamagic import AttributeCollectorBase +from .utils import find_plotly, format_rgba + +__all__ = ('PlotlyVerticesDrawer',) + +plotly = find_plotly() + + +class PlotlyVerticesDrawer(AbstractVertexDrawer): + """Plotly backend-specific vertex drawer.""" + + def __init__(self, fig, palette, layout): + self.fig = fig + super().__init__(palette, layout) + self.VisualVertexBuilder = self._construct_visual_vertex_builder() + + def _construct_visual_vertex_builder(self): + class VisualVertexBuilder(AttributeCollectorBase): + """Collects some visual properties of a vertex for drawing""" + + _kwds_prefix = "vertex_" + color = ("red", self.palette.get) + frame_color = ("black", self.palette.get) + frame_width = 1.0 + label = None + label_angle = -pi / 2 + label_dist = 0.0 + label_color = "black" + font = "sans-serif" + label_size = 12.0 + # FIXME? mpl.rcParams["font.size"]) + position = dict(func=self.layout.__getitem__) + shape = "circle" + size = 0.2 + width = None + height = None + zorder = 2 + + return VisualVertexBuilder + + + def draw(self, visual_vertex, vertex, point): + if visual_vertex.size <= 0: + return + + fig = self.fig + + marker_kwds = {} + marker_kwds['x'] = [point[0]] + marker_kwds['y'] = [point[1]] + marker_kwds['marker'] = { + 'symbol': visual_vertex.shape, + 'size': visual_vertex.size, + 'color': format_rgba(visual_vertex.color), + 'line_color': format_rgba(visual_vertex.frame_color), + } + + #if visual_vertex.label is not None: + # text_kwds['x'].append(point[0]) + # text_kwds['y'].append(point[1]) + # text_kwds['text'].append(visual_vertex.label) + + # Draw dots + stroke = plotly.graph_objects.Scatter( + mode='markers', + **marker_kwds, + ) + fig.add_trace(stroke) + + def draw_label(self, visual_vertex, point, **kwds): + if visual_vertex.label is None: + return + + fig = self.fig + + text_kwds = {} + text_kwds['x'] = [point[0]] + text_kwds['y'] = [point[1]] + text_kwds['text'].append(visual_vertex.label) + + # TODO: add more options + + # Draw text labels + stroke = plotly.graph_objects.Scatter( + mode='text', + **text_kwds, + ) + fig.add_trace(stroke) + + diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index a868cbf4a..79a274043 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -19,15 +19,16 @@ __all__ = ("ShapeDrawerDirectory",) +from abc import ABCMeta, abstractmethod from math import atan2, copysign, cos, pi, sin import sys -from igraph.drawing.baseclasses import AbstractCairoDrawer -from igraph.drawing.utils import Point -from igraph.utils import consecutive_pairs +from igraph.drawing.matplotlib.utils import find_matplotlib +mpl, plt = find_matplotlib() -class ShapeDrawer: + +class ShapeDrawer(metaclass=ABCMeta): """Static class, the ancestor of all vertex shape drawer classes. Custom shapes must implement at least the C{draw_path} method of the class. @@ -35,7 +36,8 @@ class ShapeDrawer: Cairo path appropriately.""" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + @abstractmethod + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws the path of the shape on the given Cairo context, without stroking or filling it. @@ -48,7 +50,7 @@ def draw_path(ctx, center_x, center_y, width, height=None): @param width: the width of the object @param height: the height of the object. If C{None}, equals to the width. """ - raise NotImplementedError("abstract class") + raise NotImplementedError @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -84,15 +86,20 @@ def draw_path(ctx, center_x, center_y, width, height=None): class RectangleDrawer(ShapeDrawer): """Static class which draws rectangular vertices""" - names = "rectangle rect rectangular square box" + names = "rectangle rect rectangular square box s" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws a rectangle-shaped path on the Cairo context without stroking or filling it. @see: ShapeDrawer.draw_path""" height = height or width - ctx.rectangle(center_x - width / 2, center_y - height / 2, width, height) + if isinstance(ctx, plt.Axes): + return mpl.patches.Rectangle( + (center_x - width / 2, center_y - height / 2), width, height, **kwargs + ) + else: + ctx.rectangle(center_x - width / 2, center_y - height / 2, width, height) @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -145,17 +152,20 @@ def intersection_point(center_x, center_y, source_x, source_y, width, height=Non class CircleDrawer(ShapeDrawer): """Static class which draws circular vertices""" - names = "circle circular" + names = "circle circular o" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws a circular path on the Cairo context without stroking or filling it. Height is ignored, it is the width that determines the diameter of the circle. @see: ShapeDrawer.draw_path""" - ctx.arc(center_x, center_y, width / 2, 0, 2 * pi) + if isinstance(ctx, plt.Axes): + return mpl.patches.Circle((center_x, center_y), width / 2, **kwargs) + else: + ctx.arc(center_x, center_y, width / 2, 0, 2 * pi) @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -172,19 +182,27 @@ def intersection_point(center_x, center_y, source_x, source_y, width, height=Non class UpTriangleDrawer(ShapeDrawer): """Static class which draws upright triangles""" - names = "triangle triangle-up up-triangle arrow arrow-up up-arrow" + names = "triangle triangle-up up-triangle arrow arrow-up up-arrow ^" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws an upright triangle on the Cairo context without stroking or filling it. @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x - width / 2, center_y + height / 2) - ctx.line_to(center_x, center_y - height / 2) - ctx.line_to(center_x + width / 2, center_y + height / 2) - ctx.close_path() + if isinstance(ctx, plt.Axes): + vertices = [ + [center_x - 0.5 * width, center_y - 0.333 * height], + [center_x + 0.5 * width, center_y - 0.333 * height], + [center_x, center_x + 0.667 * height], + ] + return mpl.patches.Polygon(vertices, closed=True, **kwargs) + else: + ctx.move_to(center_x - width / 2, center_y + height / 2) + ctx.line_to(center_x, center_y - height / 2) + ctx.line_to(center_x + width / 2, center_y + height / 2) + ctx.close_path() @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -201,19 +219,28 @@ def intersection_point(center_x, center_y, source_x, source_y, width, height=Non class DownTriangleDrawer(ShapeDrawer): """Static class which draws triangles pointing down""" - names = "down-triangle triangle-down arrow-down down-arrow" + names = "down-triangle triangle-down arrow-down down-arrow v" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws a triangle on the Cairo context without stroking or filling it. @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x - width / 2, center_y - height / 2) - ctx.line_to(center_x, center_y + height / 2) - ctx.line_to(center_x + width / 2, center_y - height / 2) - ctx.close_path() + if isinstance(ctx, plt.Axes): + vertices = [ + [center_x - 0.5 * width, center_y + 0.333 * height], + [center_x + 0.5 * width, center_y + 0.333 * height], + [center_x, center_y - 0.667 * height], + ] + return mpl.patches.Polygon(vertices, closed=True, **kwargs) + + else: + ctx.move_to(center_x - width / 2, center_y - height / 2) + ctx.line_to(center_x, center_y + height / 2) + ctx.line_to(center_x + width / 2, center_y - height / 2) + ctx.close_path() @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -230,20 +257,29 @@ def intersection_point(center_x, center_y, source_x, source_y, width, height=Non class DiamondDrawer(ShapeDrawer): """Static class which draws diamonds (i.e. rhombuses)""" - names = "diamond rhombus" + names = "diamond rhombus d" @staticmethod - def draw_path(ctx, center_x, center_y, width, height=None): + def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): """Draws a rhombus on the Cairo context without stroking or filling it. @see: ShapeDrawer.draw_path""" height = height or width - ctx.move_to(center_x - width / 2, center_y) - ctx.line_to(center_x, center_y + height / 2) - ctx.line_to(center_x + width / 2, center_y) - ctx.line_to(center_x, center_y - height / 2) - ctx.close_path() + if isinstance(ctx, plt.Axes): + vertices = [ + [center_x - 0.5 * width, center_y], + [center_x, center_y - 0.5 * height], + [center_x + 0.5 * width, center_y], + [center_x, center_y + 0.5 * height], + ] + return mpl.patches.Polygon(vertices, closed=True, **kwargs) + else: + ctx.move_to(center_x - width / 2, center_y) + ctx.line_to(center_x, center_y + height / 2) + ctx.line_to(center_x + width / 2, center_y) + ctx.line_to(center_x, center_y - height / 2) + ctx.close_path() @staticmethod def intersection_point(center_x, center_y, source_x, source_y, width, height=None): @@ -276,102 +312,6 @@ def intersection_point(center_x, center_y, source_x, source_y, width, height=Non ##################################################################### -class PolygonDrawer(AbstractCairoDrawer): - """Class that is used to draw polygons. - - The corner points of the polygon can be set by the C{points} - property of the drawer, or passed at construction time. Most - drawing methods in this class also have an extra C{points} - argument that can be used to override the set of points in the - C{points} property.""" - - def __init__(self, context, bbox=(1, 1), points=[]): - """Constructs a new polygon drawer that draws on the given - Cairo context. - - @param context: the Cairo context to draw on - @param bbox: ignored, leave it at its default value - @param points: the list of corner points - """ - super().__init__(context, bbox) - self.points = points - - def draw_path(self, points=None, corner_radius=0): - """Sets up a Cairo path for the outline of a polygon on the given - Cairo context. - - @param points: the coordinates of the corners of the polygon, - in clockwise or counter-clockwise order, or C{None} if we are - about to use the C{points} property of the class. - @param corner_radius: if zero, an ordinary polygon will be drawn. - If positive, the corners of the polygon will be rounded with - the given radius. - """ - if points is None: - points = self.points - - self.context.new_path() - - if len(points) < 2: - # Well, a polygon must have at least two corner points - return - - ctx = self.context - if corner_radius <= 0: - # No rounded corners, this is simple - ctx.move_to(*points[-1]) - for point in points: - ctx.line_to(*point) - return - - # Rounded corners. First, we will take each side of the - # polygon and find what the corner radius should be on - # each corner. If the side is longer than 2r (where r is - # equal to corner_radius), the radius allowed by that side - # is r; if the side is shorter, the radius is the length - # of the side / 2. For each corner, the final corner radius - # is the smaller of the radii on the two sides adjacent to - # the corner. - points = [Point(*point) for point in points] - side_vecs = [v - u for u, v in consecutive_pairs(points, circular=True)] - half_side_lengths = [side.length() / 2 for side in side_vecs] - corner_radii = [corner_radius] * len(points) - for idx in range(len(corner_radii)): - prev_idx = -1 if idx == 0 else idx - 1 - radii = [corner_radius, half_side_lengths[prev_idx], half_side_lengths[idx]] - corner_radii[idx] = min(radii) - - # Okay, move to the last corner, adjusted by corner_radii[-1] - # towards the first corner - ctx.move_to(*(points[-1].towards(points[0], corner_radii[-1]))) - # Now, for each point in points, draw a line towards the - # corner, stopping before it in a distance of corner_radii[idx], - # then draw the corner - u = points[-1] - for idx, (v, w) in enumerate(consecutive_pairs(points, True)): - radius = corner_radii[idx] - ctx.line_to(*v.towards(u, radius)) - aux1 = v.towards(u, radius / 2) - aux2 = v.towards(w, radius / 2) - ctx.curve_to( - aux1.x, aux1.y, aux2.x, aux2.y, *v.towards(w, corner_radii[idx]) - ) - u = v - - def draw(self, points=None): - """Draws the polygon using the current stroke of the Cairo context. - - @param points: the coordinates of the corners of the polygon, - in clockwise or counter-clockwise order, or C{None} if we are - about to use the C{points} property of the class. - """ - self.draw_path(points) - self.context.stroke() - - -##################################################################### - - class ShapeDrawerDirectory: """Static class that resolves shape names to their corresponding shape drawer classes. diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index eb248e5e7..df48bbdb9 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -2,369 +2,18 @@ Drawers for labels on plots. """ -import re +from enum import Enum -from igraph.drawing.baseclasses import AbstractCairoDrawer -from warnings import warn - -__all__ = ("TextAlignment", "TextDrawer") - -__docformat__ = "restructuredtext en" +__all__ = ("TextAlignment", ) ##################################################################### -class TextAlignment: +class TextAlignment(Enum): """Text alignment constants.""" - LEFT, CENTER, RIGHT = "left", "center", "right" - TOP, BOTTOM = "top", "bottom" - - -##################################################################### - - -class TextDrawer(AbstractCairoDrawer): - """Class that draws text on a Cairo context. - - This class supports multi-line text unlike the original Cairo text - drawing methods.""" - - LEFT, CENTER, RIGHT = "left", "center", "right" - TOP, BOTTOM = "top", "bottom" - - def __init__(self, context, text="", halign="center", valign="center"): - """Constructs a new instance that will draw the given `text` on - the given Cairo `context`.""" - super().__init__(context, (0, 0)) - self.text = text - self.halign = halign - self.valign = valign - - def draw(self, wrap=False): - """Draws the text in the current bounding box of the drawer. - - Since the class itself is an instance of `AbstractCairoDrawer`, it - has an attribute named ``bbox`` which will be used as a bounding - box. - - @param wrap: whether to allow re-wrapping of the text if it does not - fit within the bounding box horizontally. - """ - ctx = self.context - bbox = self.bbox - - text_layout = self.get_text_layout(bbox.left, bbox.top, bbox.width, wrap) - if not text_layout: - return - - _, font_descent, line_height = ctx.font_extents()[:3] - yb = ctx.text_extents(text_layout[0][2])[1] - total_height = len(text_layout) * line_height - - if self.valign == self.BOTTOM: - # Bottom vertical alignment - dy = bbox.height - total_height - yb + font_descent - elif self.valign == self.CENTER: - # Centered vertical alignment - dy = (bbox.height - total_height - yb + font_descent + line_height) / 2.0 - else: - # Top vertical alignment - dy = line_height - - for ref_x, ref_y, line in text_layout: - ctx.move_to(ref_x, ref_y + dy) - ctx.show_text(line) - ctx.new_path() - - def get_text_layout(self, x=None, y=None, width=None, wrap=False): - """Calculates the layout of the current text. `x` and `y` denote the - coordinates where the drawing should start. If they are both ``None``, - the current position of the context will be used. - - Vertical alignment settings are not taken into account in this method - as the text is not drawn within a box. - - @param x: The X coordinate of the reference point where the layout should - start. - @param y: The Y coordinate of the reference point where the layout should - start. - @param width: The width of the box in which the text will be fitted. It - matters only when the text is right-aligned or centered. The text - will overflow the box if any of the lines is longer than the box - width and `wrap` is ``False``. - @param wrap: whether to allow re-wrapping of the text if it does not - fit within the given width. - - @return: a list consisting of ``(x, y, line)`` tuples where ``x`` and - ``y`` refer to reference points on the Cairo canvas and ``line`` - refers to the corresponding text that should be plotted there. - """ - ctx = self.context - - if x is None or y is None: - x, y = ctx.get_current_point() - - line_height = ctx.font_extents()[2] - - if wrap: - if width and width > 0: - iterlines = self._iterlines_wrapped(width) - else: - warn("ignoring wrap=True as no width was specified") - else: - iterlines = self._iterlines() - - result = [] - - if self.halign == self.CENTER: - # Centered alignment - if width is None: - width = self.text_extents()[2] - for line, line_width, x_bearing in iterlines: - result.append((x + (width - line_width) / 2.0 - x_bearing, y, line)) - y += line_height - - elif self.halign == self.RIGHT: - # Right alignment - if width is None: - width = self.text_extents()[2] - x += width - for line, line_width, x_bearing in iterlines: - result.append((x - line_width - x_bearing, y, line)) - y += line_height - - else: - # Left alignment - for line, _, x_bearing in iterlines: - result.append((x - x_bearing, y, line)) - y += line_height - - return result - - def draw_at(self, x=None, y=None, width=None, wrap=False): - """Draws the text by setting up an appropriate path on the Cairo - context and filling it. `x` and `y` denote the coordinates where the - drawing should start. If they are both ``None``, the current position - of the context will be used. - - Vertical alignment settings are not taken into account in this method - as the text is not drawn within a box. - - @param x: The X coordinate of the reference point where the layout should - start. - @param y: The Y coordinate of the reference point where the layout should - start. - @param width: The width of the box in which the text will be fitted. It - matters only when the text is right-aligned or centered. The text - will overflow the box if any of the lines is longer than the box - width and `wrap` is ``False``. - @param wrap: whether to allow re-wrapping of the text if it does not - fit within the given width. - """ - ctx = self.context - for ref_x, ref_y, line in self.get_text_layout(x, y, width, wrap): - ctx.move_to(ref_x, ref_y) - ctx.show_text(line) - ctx.new_path() - - def _iterlines(self): - """Iterates over the label line by line and returns a tuple containing - the folloing for each line: the line itself, the width of the line and - the X-bearing of the line.""" - ctx = self.context - for line in self._text.split("\n"): - xb, _, line_width, _, _, _ = ctx.text_extents(line) - yield (line, line_width, xb) - - def _iterlines_wrapped(self, width): - """Iterates over the label line by line and returns a tuple containing - the folloing for each line: the line itself, the width of the line and - the X-bearing of the line. - - The difference between this method and `_iterlines()` is that this - method is allowed to re-wrap the line if necessary. - - @param width: The width of the box in which the text will be fitted. - Lines will be wrapped if they are wider than this width. - """ - ctx = self.context - for line in self._text.split("\n"): - xb, _, line_width, _, _, _ = ctx.text_extents(line) - if line_width <= width: - yield (line, line_width, xb) - continue - - # We have to wrap the line - current_line, current_width, last_sep_width = [], 0, 0 - for match in re.finditer(r"(\S+)(\s+)?", line): - word, sep = match.groups() - word_width = ctx.text_extents(word)[4] - if sep: - sep_width = ctx.text_extents(sep)[4] - else: - sep_width = 0 - current_width += word_width - if current_width >= width and current_line: - yield ("".join(current_line), current_width - word_width, 0) - # Starting a new line - current_line, current_width = [word], word_width - if sep is not None: - current_line.append(sep) - else: - current_width += last_sep_width - current_line.append(word) - if sep is not None: - current_line.append(sep) - last_sep_width = sep_width - if current_line: - yield ("".join(current_line), current_width, 0) - - @property - def text(self): - """Returns the text to be drawn.""" - return self._text - - @text.setter - def text(self, text): - """Sets the text that will be drawn. - - If `text` is ``None``, it will be mapped to an empty string; otherwise, - it will be converted to a string.""" - if text is None: - self._text = "" - else: - self._text = str(text) - - def text_extents(self): - """Returns the X-bearing, Y-bearing, width, height, X-advance and - Y-advance of the text. - - For multi-line text, the X-bearing and Y-bearing correspond to the - first line, while the X-advance is extracted from the last line. - and the Y-advance is the sum of all the Y-advances. The width and - height correspond to the entire bounding box of the text.""" - lines = self.text.split("\n") - if len(lines) <= 1: - return self.context.text_extents(self.text) - - ( - x_bearing, - y_bearing, - width, - height, - x_advance, - y_advance, - ) = self.context.text_extents(lines[0]) - - line_height = self.context.font_extents()[2] - for line in lines[1:]: - _, _, w, _, x_advance, ya = self.context.text_extents(line) - width = max(width, w) - height += line_height - y_advance += ya - - return x_bearing, y_bearing, width, height, x_advance, y_advance - - -def test(): - """Testing routine for L{TextDrawer}""" - import math - from igraph.drawing.utils import find_cairo - - cairo = find_cairo() - - text = "The quick brown fox\njumps over a\nlazy dog" - width, height = (600, 1000) - - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - drawer = TextDrawer(context, text) - - context.set_source_rgb(1, 1, 1) - context.set_font_size(16.0) - context.rectangle(0, 0, width, height) - context.fill() - - context.set_source_rgb(0.5, 0.5, 0.5) - for i in range(200, width, 200): - context.move_to(i, 0) - context.line_to(i, height) - context.stroke() - for i in range(200, height, 200): - context.move_to(0, i) - context.line_to(width, i) - context.stroke() - context.set_source_rgb(0.75, 0.75, 0.75) - context.set_line_width(0.5) - for i in range(100, width, 200): - context.move_to(i, 0) - context.line_to(i, height) - context.stroke() - for i in range(100, height, 200): - context.move_to(0, i) - context.line_to(width, i) - context.stroke() - - def mark_point(red, green, blue): - """Marks the current point on the canvas by the given color""" - x, y = context.get_current_point() - context.set_source_rgba(red, green, blue, 0.5) - context.arc(x, y, 4, 0, 2 * math.pi) - context.fill() - - # Testing drawer.draw_at() - for i, halign in enumerate(("left", "center", "right")): - # Mark the reference points - context.move_to(i * 200, 40) - mark_point(0, 0, 1) - context.move_to(i * 200, 140) - mark_point(0, 0, 1) - - # Draw the text - context.set_source_rgb(0, 0, 0) - drawer.halign = halign - drawer.draw_at(i * 200, 40) - drawer.draw_at(i * 200, 140, width=200) - - # Mark the new reference point - mark_point(1, 0, 0) - - # Testing TextDrawer.draw() - for i, halign in enumerate(("left", "center", "right")): - for j, valign in enumerate(("top", "center", "bottom")): - # Draw the text - context.set_source_rgb(0, 0, 0) - drawer.halign = halign - drawer.valign = valign - drawer.bbox = (i * 200, j * 200 + 200, i * 200 + 200, j * 200 + 400) - drawer.draw() - # Mark the new reference point - mark_point(1, 0, 0) - - # Testing TextDrawer.wrap() - drawer.text = ( - "Jackdaws love my big sphinx of quartz. Yay, wrapping! " - + "Jackdaws love my big sphinx of quartz.\n\n" - + "Jackdaws love my big sphinx of quartz." - ) - drawer.valign = TextDrawer.TOP - for i, halign in enumerate(("left", "center", "right")): - context.move_to(i * 200, 840) - - # Mark the reference point - mark_point(0, 0, 1) - - # Draw the text - context.set_source_rgb(0, 0, 0) - drawer.halign = halign - drawer.draw_at(i * 200, 840, width=199, wrap=True) - - # Mark the new reference point - mark_point(1, 0, 0) - - surface.write_to_png("test.png") - - -if __name__ == "__main__": - test() + LEFT = "left" + CENTER = "center" + RIGHT = "right" + TOP = "top" + BOTTOM = "bottom" diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index ecf546320..216d13298 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -2,11 +2,21 @@ Utility classes for drawing routines. """ - -from math import atan2, cos, sin -from operator import itemgetter - -__all__ = ("BoundingBox", "Point", "Rectangle") +from math import atan2, cos, hypot, sin +from typing import NamedTuple + +from igraph.utils import consecutive_pairs + +__all__ = ( + "BoundingBox", + "Point", + "Rectangle", + "calculate_corner_radii", + "euclidean_distance", + "evaluate_cubic_bezier", + "intersect_bezier_curve_and_circle", + "str_to_orientation", +) ##################################################################### @@ -400,6 +410,7 @@ def __or__(self, other): ##################################################################### + class FakeModule: """Fake module that raises an exception for everything""" @@ -426,91 +437,9 @@ def __setattr__(self, key, value): ##################################################################### -def find_cairo(): - """Tries to import the ``cairo`` Python module if it is installed, - also trying ``cairocffi`` (a drop-in replacement of ``cairo``). - Returns a fake module if everything fails. - """ - module_names = ["cairo", "cairocffi"] - module = FakeModule("Plotting not available; please install pycairo or cairocffi") - for module_name in module_names: - try: - module = __import__(module_name) - break - except ImportError: - pass - return module - - -##################################################################### - - -def find_matplotlib(): - """Tries to import the ``matplotlib`` Python module if it is installed. - Returns a fake module if everything fails. - """ - try: - import matplotlib as mpl - - has_mpl = True - except ImportError: - mpl = FakeModule("You need to install matplotlib to use this functionality") - has_mpl = False - - if has_mpl: - import matplotlib.pyplot as plt - else: - plt = FakeModule( - "You need to install matplotlib.pyplot to use this functionality" - ) - - return mpl, plt - - -##################################################################### - - -class Point(tuple): +class Point(NamedTuple("_Point", [("x", float), ("y", float)])): """Class representing a point on the 2D plane.""" - __slots__ = () - _fields = ("x", "y") - - def __new__(cls, x, y): - """Creates a new point with the given coordinates""" - return tuple.__new__(cls, (x, y)) - - @classmethod - def _make(cls, iterable, new=tuple.__new__, len=len): - """Creates a new point from a sequence or iterable""" - result = new(cls, iterable) - if len(result) != 2: - raise TypeError("Expected 2 arguments, got %d" % len(result)) - return result - - def __repr__(self): - """Returns a nicely formatted representation of the point""" - return "Point(x=%r, y=%r)" % self - - def _asdict(self): - """Returns a new dict which maps field names to their values""" - return dict(zip(self._fields, self)) - - def _replace(self, **kwds): - """Returns a new point object replacing specified fields with new - values""" - result = self._make(map(kwds.pop, ("x", "y"), self)) - if kwds: - raise ValueError("Got unexpected field names: %r" % list(kwds.keys())) - return result - - def __getnewargs__(self): - """Return self as a plain tuple. Used by copy and pickle.""" - return tuple(self) - - x = property(itemgetter(0), doc="Alias for field number 0") - y = property(itemgetter(1), doc="Alias for field number 1") - def __add__(self, other): """Adds the coordinates of a point to another one""" return self.__class__(x=self.x + other.x, y=self.y + other.y) @@ -558,7 +487,7 @@ def interpolate(self, other, ratio=0.5): return this point, 1 will return the other point. """ ratio = float(ratio) - return Point( + return self.__class__( x=self.x * (1.0 - ratio) + other.x * ratio, y=self.y * (1.0 - ratio) + other.y * ratio, ) @@ -573,8 +502,8 @@ def normalized(self): after normalization. Returns the normalized point.""" len = self.length() if len == 0: - return Point(x=self.x, y=self.y) - return Point(x=self.x / len, y=self.y / len) + return self.__class__(x=self.x, y=self.y) + return self.__class__(x=self.x / len, y=self.y / len) def sq_length(self): """Returns the squared length of the vector pointing from the origin @@ -588,7 +517,9 @@ def towards(self, other, distance=0): return self angle = atan2(other.y - self.y, other.x - self.x) - return Point(self.x + distance * cos(angle), self.y + distance * sin(angle)) + return self.__class__( + self.x + distance * cos(angle), self.y + distance * sin(angle) + ) @classmethod def FromPolar(cls, radius, angle): @@ -599,3 +530,138 @@ def FromPolar(cls, radius, angle): the origin. """ return cls(radius * cos(angle), radius * sin(angle)) + + +def calculate_corner_radii(points, corner_radius): + """Given a list of points and a desired corner radius, returns a list + containing proposed corner radii for each of the points such that it is + ensured that the corner radius at a point is never larger than half of + the minimum distance between the point and its neighbors. + """ + points = [Point(*point) for point in points] + side_vecs = [v - u for u, v in consecutive_pairs(points, circular=True)] + half_side_lengths = [side.length() / 2 for side in side_vecs] + corner_radii = [corner_radius] * len(points) + for idx in range(len(corner_radii)): + prev_idx = -1 if idx == 0 else idx - 1 + radii = [corner_radius, half_side_lengths[prev_idx], half_side_lengths[idx]] + corner_radii[idx] = min(radii) + return corner_radii + + +def euclidean_distance(x1, y1, x2, y2): + """Computes the Euclidean distance between points (x1,y1) and (x2,y2).""" + return hypot(x2 - x1, y2 - y1) + + +def evaluate_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3, t): + """Evaluates the Bezier curve from point (x0,y0) to (x3,y3) + via control points (x1,y1) and (x2,y2) at t. t is typically in the range + [0; 1] such that 0 returns (x0, y0) and 1 returns (x3, y3). + """ + xt = ( + (1.0 - t) ** 3 * x0 + + 3.0 * t * (1.0 - t) ** 2 * x1 + + 3.0 * t ** 2 * (1.0 - t) * x2 + + t ** 3 * x3 + ) + yt = ( + (1.0 - t) ** 3 * y0 + + 3.0 * t * (1.0 - t) ** 2 * y1 + + 3.0 * t ** 2 * (1.0 - t) * y2 + + t ** 3 * y3 + ) + return xt, yt + + +def intersect_bezier_curve_and_circle( + x0, y0, x1, y1, x2, y2, x3, y3, radius, max_iter=10 +): + """Binary search solver for finding the intersection of a Bezier curve + and a circle centered at the curve's end point. + + Returns the x, y coordinates of the intersection point. + """ + # The exact formulation of the problem is a quartic equation and it is + # probably not worth coding up an exact quartic solver. The solution below + # uses binary search. Another solution would be simply to intersect the + # circle with the line pointing from (x2, y2) to (x3, y3) as the difference + # is likely to be negligible. + + precision = radius / 20.0 + source_target_distance = euclidean_distance(x0, y0, x3, y3) + radius = float(radius) + t0 = 1.0 + t1 = 1.0 - radius / source_target_distance + + xt1, yt1 = evaluate_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3, t1) + + distance_t0 = 0 + distance_t1 = euclidean_distance(x3, y3, xt1, yt1) + counter = 0 + while abs(distance_t1 - radius) > precision and counter < max_iter: + if ((distance_t1 - radius) > 0) != ((distance_t0 - radius) > 0): + t_new = (t0 + t1) / 2.0 + else: + if abs(distance_t1 - radius) < abs(distance_t0 - radius): + # If t1 gets us closer to the circumference step in the + # same direction + t_new = t1 + (t1 - t0) / 2.0 + else: + t_new = t1 - (t1 - t0) + t_new = 1 if t_new > 1 else (0 if t_new < 0 else t_new) + t0, t1 = t1, t_new + distance_t0 = distance_t1 + xt1, yt1 = evaluate_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3, t1) + distance_t1 = euclidean_distance(x3, y3, xt1, yt1) + counter += 1 + + return evaluate_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3, t1) + + +def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False): + """Tries to interpret a string as an orientation value. + + The following basic values are understood: ``left-right``, ``bottom-top``, + ``right-left``, ``top-bottom``. Possible aliases are: + + - ``horizontal``, ``horiz``, ``h`` and ``lr`` for ``left-right`` + + - ``vertical``, ``vert``, ``v`` and ``tb`` for top-bottom. + + - ``lr`` for ``left-right``. + + - ``rl`` for ``right-left``. + + ``reversed_horizontal`` reverses the meaning of ``horizontal``, ``horiz`` + and ``h`` to ``rl`` (instead of ``lr``); similarly, ``reversed_vertical`` + reverses the meaning of ``vertical``, ``vert`` and ``v`` to ``bt`` + (instead of ``tb``). + + Returns one of ``lr``, ``rl``, ``tb`` or ``bt``, or throws ``ValueError`` + if the string cannot be interpreted as an orientation. + """ + + aliases = { + "left-right": "lr", + "right-left": "rl", + "top-bottom": "tb", + "bottom-top": "bt", + "top-down": "tb", + "bottom-up": "bt", + "top-bottom": "tb", + "bottom-top": "bt", + "td": "tb", + "bu": "bt", + } + + dir = ["lr", "rl"][reversed_horizontal] + aliases.update(horizontal=dir, horiz=dir, h=dir) + + dir = ["tb", "bt"][reversed_vertical] + aliases.update(vertical=dir, vert=dir, v=dir) + + result = aliases.get(value, value) + if result not in ("lr", "rl", "tb", "bt"): + raise ValueError("unknown orientation: %s" % result) + return result diff --git a/src/igraph/formula.py b/src/igraph/formula.py index ad5473d15..6ea24ce21 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -75,8 +75,7 @@ def generate_edges(formula): else: msg = ( "invalid token found in edge specification: %s; " - "token_type=%r; tok=%r" - % (formula, token_type, tok) + "token_type=%r; tok=%r" % (formula, token_type, tok) ) raise SyntaxError(msg) else: diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 68350b86a..73773aec3 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -230,39 +230,12 @@ def bins(self): yield (x, x + self._bin_width, elem) x += self._bin_width - def __plot__(self, context, bbox, _, **kwds): + def __plot__(self, backend, context, **kwds): """Plotting support""" - from igraph.drawing.coord import DescartesCoordinateSystem - - coord_system = DescartesCoordinateSystem( - context, - bbox, - ( - kwds.get("min", self._min), - 0, - kwds.get("max", self._max), - kwds.get("max_value", max(self._bins)), - ), - ) - - # Draw the boxes - context.set_line_width(1) - context.set_source_rgb(1.0, 0.0, 0.0) - x = self._min - for value in self._bins: - top_left_x, top_left_y = coord_system.local_to_context(x, value) - x += self._bin_width - bottom_right_x, bottom_right_y = coord_system.local_to_context(x, 0) - context.rectangle( - top_left_x, - top_left_y, - bottom_right_x - top_left_x, - bottom_right_y - top_left_y, - ) - context.fill() + from igraph.drawing import DrawerDirectory - # Draw the axes - coord_system.draw() + drawer = DrawerDirectory.resolve(self, backend)(context) + drawer.draw(self, **kwds) def to_string(self, max_width=78, show_bars=True, show_counts=True): """Returns the string representation of the histogram. diff --git a/src/igraph/utils.py b/src/igraph/utils.py index d195a6263..f919ef717 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -142,54 +142,6 @@ def rescale(values, out_range=(0.0, 1.0), in_range=None, clamp=False, scale=None return result -def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False): - """Tries to interpret a string as an orientation value. - - The following basic values are understood: ``left-right``, ``bottom-top``, - ``right-left``, ``top-bottom``. Possible aliases are: - - - ``horizontal``, ``horiz``, ``h`` and ``lr`` for ``left-right`` - - - ``vertical``, ``vert``, ``v`` and ``tb`` for top-bottom. - - - ``lr`` for ``left-right``. - - - ``rl`` for ``right-left``. - - ``reversed_horizontal`` reverses the meaning of ``horizontal``, ``horiz`` - and ``h`` to ``rl`` (instead of ``lr``); similarly, ``reversed_vertical`` - reverses the meaning of ``vertical``, ``vert`` and ``v`` to ``bt`` - (instead of ``tb``). - - Returns one of ``lr``, ``rl``, ``tb`` or ``bt``, or throws ``ValueError`` - if the string cannot be interpreted as an orientation. - """ - - aliases = { - "left-right": "lr", - "right-left": "rl", - "top-bottom": "tb", - "bottom-top": "bt", - "top-down": "tb", - "bottom-up": "bt", - "top-bottom": "tb", - "bottom-top": "bt", - "td": "tb", - "bu": "bt", - } - - dir = ["lr", "rl"][reversed_horizontal] - aliases.update(horizontal=dir, horiz=dir, h=dir) - - dir = ["tb", "bt"][reversed_vertical] - aliases.update(vertical=dir, vert=dir, v=dir) - - result = aliases.get(value, value) - if result not in ("lr", "rl", "tb", "bt"): - raise ValueError("unknown orientation: %s" % result) - return result - - def consecutive_pairs(iterable, circular=False): """Returns consecutive pairs of items from the given iterable. diff --git a/tests/drawing/__init__.py b/tests/drawing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/drawing/cairo/__init__.py b/tests/drawing/cairo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/drawing/cairo/baseline_images/clustering_directed.png b/tests/drawing/cairo/baseline_images/clustering_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..32baed2ca0a88cf68d3f8283a6b951b1fd0613b1 GIT binary patch literal 30616 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 l+ww`H3IY{DQ8_Iiu=#kWLfG}!dEvmnH literal 0 HcmV?d00001 diff --git a/tests/drawing/cairo/baseline_images/clustering_directed_large.png b/tests/drawing/cairo/baseline_images/clustering_directed_large.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6b54aa62cfba120ae0694cdd8c977fcd374e20 GIT binary patch literal 64832 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

    jML#C)Z~u=x^Rd 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 Xx;GVnxVMQO1-aks)JcEQE|DP3B~t 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/cairo/baseline_images/graph_directed.png b/tests/drawing/cairo/baseline_images/graph_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..c85c3b668ad66ff9355f7e9d467ecfa5019c9c6a GIT binary patch literal 17911 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..c85c3b668ad66ff9355f7e9d467ecfa5019c9c6a GIT binary patch literal 17911 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..51608e9245d547b872aedea2c1cbae494eaaeab4 GIT binary patch literal 15413 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 H*&F`{h$tl;(%lUT(k%$m-SwTp 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 lRKjZ%!T8NAdR>!t&&CO@NYvvD_UuUiOz1;gw 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png new file mode 100644 index 0000000000000000000000000000000000000000..551d858ccd9fdded438742b1690c0039977a0af4 GIT binary patch literal 25084 zcmeFZc{rBs_6GczB@so)OhihCLdGOKnjb1nqzFyM%u`a5kOxT#g`^2h5*d<2GNlO_ zLL_CLr|-N}?{6Q+_y70Tw~zhq_VIQ<_k9iPTI*crI@cAleXG#|4j~Q-g|dKZY(S$> zn8Ya*Mss#n{F|$8fsXh?!*!#%tEs~gS9dFC8_E_dSI6THuE*^UiM!c2yVyINR9U6E zN<~53&ehe?Wu2npiT@s0<=||qSdm~*g_q28G~VMvp>SJ~e;97-rrA>{R`yhb^=2ON zzrMQr#B_WO=>K^!NZVlJIfc`iMSJe=<0)Zzuy-n&naPVPM$^ul_Bk^iH?xsZx~V}Cfn7=M^7Wir4Yw0Z$?@>uO_N+fw`E$eywk@8qc4}VCf zhA~Lu54jWn|4;wFU8ZYx)l9~8v!>&X&mub${S&B*WCv;{dmnj>JM)GxQ$9%X>RYQ7f_~$T;YIo6}wf4NKoTCjI8YoP5f61{O=- zDNFT=6@`@sfo}Kr*8F<-wyWudrtVk~H~ZQA-bYm0_#xQSkjRnB__E9!8$7#zq?K`; z?c#LZCjE@v&OET{5z83&>Um@Cs^t^r7u(jII#gYKW4}*-$+`0>9K|p?d&OJZ5-Y1E zHh3I)$$Zr?c_^%8Y~FUM1yv$U77T_4l6gE4F0PX!oI>lOe}Bzg#O3W{N*g~yzPaG; z?u_sLev|tWyuJ&DUoiY37TWJ3z9Pxfg6(94fyWxrG}Bx+t-h8s@gCno7`8}J*{Z~n z@w=FiMY6T|Tb5dQkL(d;)Cnya<0~p*D-qY0?Pk@kvv?H{Sy;XOyy-TLv;I2Msz$<22GxhD zwSMFT37&X+d8KPXm!yS%+k)SlWyZzwXIJf7?>&EPhpI_?^#)I;0qb?HT?>bd>5r>$ z#%QnQ6%^XP%~x#yy4$iN$0J@PP}ENM9%a=<1M>rET)lpM3|p?M&hwI{*2^X^L`vJF z7)TbKDwyEQ*m}MEQHO#KMTnwU(q{JMS>)h4_aoC2!|NlYsgtj;%r+@Hz7u_8Z4ra! z%4J{HbGrnDQ!K(uK4*F;ExGQmvoHJP0=#y@0_R_@ZE7%aR$5m#G553>n|8(eqYQZq zBUIXwBgPV&r&o13N&oQnWW|c?c*jR`8K&n?E|TVCB^{ZLtkc zogAu*qXRonhkl+ucj4>vQ}exqsr4&%lhthdo!cvu=OTM1P&6faKgE?RSWx+(UUjlD zEo*M^JgjP^pO>}?^ACxqN;6N%N47)>s+d1Hy0f~?xYj~YoSt$q(`)$Xt#?;9#wM}J z*>w60f08r3#k?+9ny-|sQBb;R8l$EE8H*hsSk`S!-khMN(X~U`K7+j7@XESV@*+2P zbhBt13%Q1rT$!ldv_3+D>TLsCRDL;7r7J7TKi})(V>_06=DC**BzcCG(}z})^^`jP zB`>afJ$IzchX8BkvXNg6XGAyB^GoJFx!J4XZuM^eQ!ECwJ=Ww^`omY(d=VO2X#cR| zZo#g*yH-|fNZUKi4dM2uB!>CPHA$t$p=S$uf<;Z#d*0@yJS^3X!|Js5JgWL0Wq$G0 zdTu&vloU_pZ(2=rzX8qj&j2+#<2UeL5yH|O*Y4Y)wKdkIYJt~cEG^(LQeS7XM}?g3p&#$#w7u7Ay8l*i-qQ9u%(Hi} zN|5Cu$B_!!uu$KA<+4Q^&M|9+Nb@O1SEMXW-b9zbcwN(7*?XkN%&{U)B^U$X^Pawe z373Y8#9<6oGe0dWw#eAiUwdxa$EYsBE8#U%lQ&w#7NmcpcUqgim>IJ&TXnoS|N56l zwrNkz-d)#>HCNcxGkogj$JE26;pq{q3xpPOoE;l@t7!k_p5S%0<1PIhL%d_l9T)U{ z+~?p_E|L+ z?N>cH(#>TU7R#Z*@9)w-lRcTgWL0~v1zkw(Wc-CNE|GPPpRIyL>IO>>DXq$F=e?Cb zCYd3_JJph;vv2iUhO~{6K0C5k5pS|!=~~YJj{VBDCmYSJ&mOM1xv|;P_x-IcrVZ)v zPK6S|!nAKHCmNoHxm2zT^%V1c)$S3WylG0%q{=YKTfL&9`-A7?i%~oLqFRbtt3y0r z>LECvjl0w@uR5@|=gE!j=aa+N-Fd@dbbs%Y+O?fI*ELmaUvth}HFi9;H(|JCGux^# z!!Ks{g=YQwH~Nhgi?M3crGKfAJ(R?f5w5AR?hX0tzNoR)!f_jD5;d5GED*%*PA;# z?_OXoEst3d`eLmxR}}tJPy6uTfF}O^<=6HFme_(KHnH}P`%bp@z1065R+_`Ud`0gq zrTJYvT!V=Qf!7?KhfF!O-QN4;=$xNd!EBpX#BF|fsN{lVQPz=nR}W=G7$!eH`a%B5 z%Np`xvvm6F5bnm8XXoe4)F1O44pUQ?;kDYXwbeave&mnB?Ja^yhB5L}!w&v!rMfdt zdhd;Ei{{=+-z>A|>G3_?TV}~2ni&2W`a);LiqN$u>ahe{uB|nDuwNr=QS3eVlw%n$ zURM{L@%;5p?Z?p0^R7%ce|Y${96o5U{8f-O{p!xUwVBjK-JdeHB^!nbsGV$F-^{X^ z9!OTiSSCtg&%=~A9HpT~aRHt(*k8S42Gwe#*ShFmG@#%E5#UR^hq&6b$Zv^6f@H|I|c zygihWvGOpD4U}PvLv%p~Zf~1J|y{Y`hjPysD?^I#7zsRDbCruHey$yjc+m@27`9 zAg(+vu%^l@Asp<~>-UHUBum|;PC(PgjC^X-weAmh(*l!C)3&NQG{qZB!(iTKU|Z{- z9FtqV+}O7wQ8#hrH8s;`F0yAe-Fe@YOXkv+$?s0re}ClNo3b(qS=nHCmfB}dZPOFB zFA(FLU0lKzQadgKzw;G7IFP#>Z(%9LN%)-a>kaR9Z%-85M9MDpt80!Oag3I_yX(HB znp*6KyStgHpE(_dDeRW-|&ZwgpC#VbFw%hFuK#GK}ZZmtN*>^-;Gp?S-oG1;K?~CV!zkK-;D~@>{ z)!d2q*w@|Wxv_nZ=O*o#=$I9|YaiKe`}p9%d_A}lK~1-Nu%OL23F(~m`M#QuY^%1i zls4wL5LlM=30u<&2P3rhxSgZ*`4=0F{rq&E9Q(xOwwfw`4%40Vayp8FC>e0WLRjQkvenVJS(uVvC%9@_1MRYS%*u7Bw*i%)9)Y@2&L`x%=8&|#v<>@J}Hu^sXs6{m=2pOjH1$ZV2e|W zzQ4N`2S0!G?BSw77N1XI1z|#KRJZ(n4TQ}qWouDZOFDRJ6L>f0lYtkxG8qk z%8~l*%MB2kFE9r;Sewyd4Te<-+FvrQm?-bAsoC~?&N4ioqFjXCWXePkF>~CUsB_)s z?PWgi6Y9dZV2SP)#?-roMl9h(8DguOS(U3uVnbY5PbSUmSyEdc~I<7g_iRDobg+hRbpV1%;6bY;ejh zwRLVi#z1}Z&g$F8o68sQE12t9SXgw&n_=$-G@Mg#%K!!WO{4a;%qe0c2B zgF_j*Q+>su%tkQv1zbPGi5tX{rAnsY$%_I?FX3V2ab)bXPc*DW1^j7hIVIBU+ggXF{nF}~Mc?(J8tj1NzB^o+J(;RoSNymJ zSJU-1S8ddB`H2~vcKid*xA=VmJ?a$ngnl1#zxl4 zX)m?e_IG0re2*-j1kmN7&zV*@xV+fmdWWTJj~kb~#^3FEXid%fbWUFa8+>{1S8{O4 zUNvU|-@rlsK+@m6MLR-g!Vc)t5V4jiVKdFsHo$no;^)Wvn@V28{LO(Z@Qz}ut7;Aj z9O1AtQ@9UIB0a@tA)EyK3I`3YrZ+`lCy5C+ zwk7JMvuk|6a#&#Pae)~5ogA==ju-|>n`ek(1Z**vBE$i|2!-*_3&$xMw_u>LsKL}G zMt)tpaOrS__GMTqoG{mU{OSsRHPG=E0F)q~=cj&Nm_t7B=r{}**2#iP%9mg^DFWg& zmRP`~=dSjVeBpqzaMW&YYw^ey79-4cnsoy&g=8!a&H2a%L;~6(bQ2mJ3a$g-5GzO^ zFNiXhHqY~Ll3#nI;!4r2E!Qr*$cKMRZ|SN_U!zZmwcmnPOSshe@^uEfP?+ zKJS0hxZalayjf+*9HcOZhsq1>Z!$}#oh4^>mpWGHykRmdp600ruz`8L4Hwa*NEy`5 zDCwm*%ZNs(_|Htimv-t*dz;?hy9QYM5=S`D$HEYUTJ@}y3wH2WLq9($@<|ZBML^3V zlSlH0x1cypa7k#%e-WJ)tT%egFiZ#z{BxER0Fa8hbj*bx@6+BF_|KXJ5%PmmNc9bS z;@8>t=HGpq)->VY;}YyjxNJ8ybfSsqWN#V z?pjOb6jrZ>9V;*yaF|1-?1V=``Ul;9IFq|u!!R!qkR0C+^Uj3G(={D1K~Fxjg39BXija_9SPx;BLY3_uEt0;0C*#4#|j3P{Z5 z$R=Ols;hcx3nGVVznLA??l;3-d;p%Ed{qh?8dM;XM0Ulp7n?=NM*doaLkIRNb8Z?8f&$FDy9$-@8ofh>VigXDO=&>EpPIj*p8=pIB^I3)(?0X zlIv~==Bi6Kl|`VZt=5_7l49i&zOt^(t=>MZCc{!!%7D&5%qp7VqQH8mMU5-~edFSn2d(05YO3p<0-M7>8-@>!d?k;_w zwykrpN>_2D-cfxs7TmO`2F7~y!n{eqqcw%9PW(dgZ?C zBS@j0>UJ2hsBN3`$pAF>4&*-l{PWQtEGDmB|JZ&5Ts}GYJNF~uu}$<{i?FM#pTc=K zAesrRPy3w}8P?xYsGJO}l-2;-2_2Qwn{Mv-xI6vjEC1PR*hcM@RoDJ{@fJk94OyRT zZEfG<+?zQ*2Cg!RDKEcDm)@z>`(jiyyV*}O%bYWy^15bJY^-gNvEVC;TpMWd-Lpe! zn?1Va5=^9@sdt?oDVAw@=y)aKj#+D1cJnPn*<~}rAqIiVHeFu)h4#e${Vil7`*WNl zTgd7E^5x4iomlB~kKX*rRWS247`;tEv{jikT~yo4vFfY);9^J5Y9^5Y#nUQMJi9)o z7i-Rr`m3I(A4<}()DpD?E=&JFGTcmnX}p=1%JE-TSyo=Y?zW&bm96)>dy^F=h%nL_ z@ABr|JMx)>_{{kD_)zzU(8+*nXGFh?-(%exZdi7-HYmHv+o7OoT=P$?02vmq5w&vP zQv^AnNre3kNT46vwT8w?$L#3M8|1>kmx)F&Ri|!R;x*FqBe8+TVjB>>19R_)cd4|Z ztXAl3@=yg@cVE&S2P2S6;Uw!*XPJ?m(GD*T9r)&I~Dz9 z7-K1ld3}s1VCYZ)FX4kzD(9kxh^E`(NsXhhNb9r7*ob^%Dotbb`!xsUL$A)mi{rQq zb=4H>Hm7owQ{>KwdUZ)W$o;*piD@gR*A?Dq=1Pv>Js)rLFrDMH0zLFE4*73`i=t)K zWF0mF5w^dlJ48Bt%4_hQnxKx4dWZpI0P5;PX;fM_LTa;Y|tj>Ko36q&sp zF#E}eS(uwxn^eTqh-RFy+h?ovUuGC;%3O?+wmGlX=b?eXJo;*6O=2Icx`5Y*Lx!%3y!A(b*-j0hoIncNTB z@6md;(fRF4!}DhA$1I%%2VXCBs7_@pWh<1^i-Fba&ZvXBrrK1;*(OjEb$n?>{TTFM zu%&|qnMOV=N@XXg?xt;wE8jsCOK z`QgSLm+-pd?=J1*{Jm%NHkLlg#h6|mvFgC{#e3$(t+rzHpBYRHTbLeScCpv(ZRFV- z3*-7qyY$61g*q;6;FmwB)Rdw4>XWV~V@ zg#yuL8Ciqq{tn9n7l)VP1`_j1+&Hcvt6}M zj-gaRFHfHhzm%5fceP+?1|JUBkRdDG(a5r7 zf8qV?rmJ348UE9uY+^nDZ{@2ohw~ZO& zU%xIgq)t!aXa^0~*5uv0MSG@fo8QYPpDeCDKYTgmVG+(SvQv@z$2W>zp5089zP;T4 zcs{4A&FIQSiZ6z0iEZ!Hi;~&$joW{0LwEm&-InjxeA<6F$k^umzRdC@JJs@MxxL?G z3<9(8WqlpC2cd=<)6u5S+Uc7DQDrh)4^}^{dHT0|dMPn{lK2EHqE0x#$WOJNU83yR zqBlY5n2vb2pwP2sd5u(fOIcdNK-zYC3he{1mfvJU^DWWY>0W;|O!w7Fa~t!&M0~TT z*ZEF5wUXN_i78V=U6$ACWSCIibdxusce_wA7d!;Ya_Yx6e-rJQ5=FnFDp(jrmd?y- z90!d4Y^rus+`!BEQ<{-2_mbG^x%ZtG3)auuo6eh&HzFjP;Bg3qIbFG8tiLU1c4pEv zA|vO!kl)CoL>Bc(>Fk3sPBnJX{wT)90~EN{qYi*?wo%idX z*o%eq2`rrNmFaMWZNDgo(}L<>ckYh0L~SDg1B^KR72odtMXzDZP)$1 z3|p6hP1BvIiFnp}ZYeE73{fD#XP^wrs~p8Z<3d6j(O;$WHdxHh_}YU5IjnXfVFPLh zjf6U{%-b)*QL}dOp`%})H~Lm-E9`$BEjHa{WFN0jPw{o{h}lg_HEE){V=ZS$sgo1K z8}wLmj{~#Nu^OwsanXNd&z+5u@v+9$E92VrTQYfl64d*2R`XmD2vb($Pu?*-F(jgX z38edFU>eE+L*Jg=n%uu$NEMiJwi~}FBNM`fFZz@%NGe%-OCNdh! zcyG99ZCxSGW;d_yb8r5uU5tKPt!D!NpH<|QD`R|n2@4DsXLt9gq&X1}`c$#pv1?SEG+tX4U)<&r_5 zi5~wYirYi)`JcZ1qpC9u-FETcM>%OKRPmPg=x>rAf?J~G%TwtlACVqcV*BI0eA>d) zoIzZ%sa=X@;Jn0{1;UIFA?w#OAe|x@UlDo2m(IjT2rCkcZ*D~WZ%2Vn*itnaSy|cP z8j#3mHqgziK)f`%zTdLn?Tby(0_mNOtj6cOCw`=Pwwz|82&_Ixv5j{!EL;TTiC={F zhyXdc-B~=6F`~VJF|99KGiLdWrFj{)N>XW#e(>Fcp_WsU!(+r1A(|{WDW1-#qNm)b z#`LOWHI*haIbP*oS%m{s*Eab(w~9T|zZ@_eX7y1c)@Cl zE_|}|*CxX#`8$F1_MVVS$P&dqi%3Wrg{$hPIIRBr=9qhq>J^B$Ch&l#Go;$zsWo$w zFO$CqQ%@_KA6(q%)^K8@r1h)wJcj2%P4xT7y5hW*Ca{yb83W1_pfdxro4i)wn+FB4 zuUYj5^kGLl`}dqja(0wif0 z@{4&M%5nmj6P5*aSch#vz)~6kJU1(j1Xw?FI9YU|v~BJ{mGFlcAOlHt>8zx@I-~@q z@O5r){?a~cniu&#v5i_;-jGYNv8Cj!^@LvnK{tT#&Y~3;t@C%$Ofrn6^-)$)|9S6G z0H!`Y+RTmbYyaEVT1DQF>Rfk+O0B`o6c9}%zp|SvXQ!KISv0RivyxFlT9a}RYKe)V zAEwg!=Qssl0w`E zc@dKeKdq2Rg#X8}SyuedV0w`D9Re*h)fcSGe6X|fI@qF1$ab)Pu6_R&sQlKwdkUaY z-cV()Gh>bCcrW?U|Ni;`&?0h>)dveHph89atZPq`b=j8*gKc>D=n+OF4j>_kvpF%^ zTZO!zF=6w%)nsMK{@YlB4MpYZ8=LMJ19@inC#f%Bj`jX{X3p-#$ZNDbR?EgaG9C=N zJ%t0)sFr<@NPJQruGG}LCb8k1BgihMOw`)R3s6SHN9x_lN67XKEW<;DRBa2_ADqjG4?iH~ZrBY!gEDn({!4|QAW?KK8pogB#E0xv5-6*>QB~oZFBu7`YeZ+Fdsf=Nj^^8%Tq3 z1aERK%wfdPS$3qF@DUO{m`jB6`Jv7H7v7^sn({nBYx<%zN@mA`_{?W`QNSwbc7?KD zJFz(VE80A@ppYo2FmLi2{rzrgd=N{ntQSOL%uWMu$rMOhU{60j+>PbAStuw@)FF40 z?(Di>{w7k&zTxRgI6?*UObjKu3^REOmq7TBl8tXrQ^Kp_$|*dN#>{=hM)`Jv3_u-4 z8s#j8gW#_SlYoj5mPr{SB+{vJ%7;5U4?{A6{8lJHF@G#DFHcL#z}`0C4VFl50|=-v z6t9+qTtd>6g`(F%Hd8~TKa){@lMr)>;IT|VfPsMla}*y6qvT8l#GT3JbDF;JI%OCk zx@GHDE*RKcg);RlgQP?83M!4Yevt(D3g-Ruc1#F}o3H@RV=xM+G9E-JB%Pg<`cRNk zIPhGxrOYf+P~4dqt>8V-*{H-_1s6`SG_xksPvnw|2%AF0G*0}rkeujN2Y_Q1EJ!U1${?=tm(#s0n4ATtPqW0gI!F}##DcZCw=a7YwrJPiEn2tS z@cc+HgCq%JDQDcqT7#n!6SqM%#DLAvfKeEpCki>7FuDmT#R;mN6dvyWz;y7-LmRRk ze$x|V0EYr@zu{M?f{-QU%#Q4n2LMpQ9X7tfk;TMpHmY_pEY>0?fJUu<#7oDN31S9h zEqnLQ1~3I|wr!$r6)HAyy8b$(ei~5~t6x_riR=CeEG4ea^ZWY=4z5UW) z7}1R_9$$aAoR!Idpc8o~C_b4%-;qUu@Iq&H$^{06l@|^cc79{wUj?4h^VgG4S5)nJ z6}3l&=j+aD4HtX}H?ZU5sFCJR=GY$cb)TmjgXZZ4Hx^dCm{Oj9Sm~SPuddsBbCh+} zTbZ9*x(QskWCYc9NxqXl=e0>0=8H!e%dkmAlon>;*MS zroFQ>P0|`AFv5>)_8Hk@;nm8L-}p34re^t)(nG>*?LNa!%QF>^3FZcD)MMxq>@!iX zsI#WOw5E^T-}fFu-)G-0tWZZu&!qM4hkSUNyagGU?;32vVIr)7{(=JKP!K#uKWGY- zBNYNy*B*TZ_^raPJ*nW?@KkAm`Qp%iwwBn!vO=q#eLfWHEKT!OjLxT*@Xq_VEJ|yE z@ZcBQDbET45*#YEJB10j;hj19MDg$GjJbnw<5DW(?g;Z(6k6gj{9(8K*PAR%lOr7u z!*Z+FyvZ;#`t60y^ zK`ygy)FDgf$;KCgS$$W_GJnj*N@6gIDoUyKRF>k{KW{TW!)iYJabLXCYr%N;N)6(i z!lJBKF&PjXOHD;md1}8~*)l-LGb`MG9g=Vqt5z?Jds%2xDBG{TDBw#*!PelXCp<~S zjF(q|nevO##5Krl;?pN2UbgMjCcv{{h1y7t?=s0h+6o1>d6Afcus{CGWQEM`` zva%|S+PRuBhzZ;uTE3z%ZgKzKa8&||G==abzQt-C*2{Nx|zJreLn1#u|- z71{T}T-VmyBANn;#@pq(PIFa%DLfp)yiKd086lF(D;^*z(w!{WGRe5j&L1ND3{n>? z^-vN`I|33tWyR^-(@t%#m8@O{1*D~`b1vlh53ac;%^-~%XkruV+pb{vA}Lr-BAe2A zws@$!rg%_%8DcsKqCb*;eaRkFoL=$HRezn^`jC=C7e&@wu#}B@%;9x~ro8xb zmd$)_tv-m0qrF+r?}yf!%GQCz*t&R$rQ@mUGtoD_^g0a!V=X--x^|RnGZ{3U+fA1i zi7tzhHC5qlWdkc${#-gLZ~Axc`iLFB1;qylT&-On2SzA9#(3cZuS>L#ET8#8S+osv z{&S)ypjUNo_D^(CZVA3}KR_y(Py3Nc;$I)h^wg=%@KC?{yFgLt1^RmLIoa>mVngO; zc^v1QVm99++%^6Cs0rJA8)qq;HmDq8z!kHKG0CxU!rgXir!@W8x&m&ffF@AV8;nR7;E0;$8iq; zj_v-p*=sj@iOie2PT)YLW`x>l5i)rhrkyKxb9r4PYfOANmkDy1&ymJ`yRdi<%UW04 zCU_pHK1@~@;t0Cyc2vLhk|&18n;nk-d|>yTAwxE5zhlkD^$|3(dIaaJTaE-z0+q!o zYx-!Q=&k4>uCsRA3v@mma6jF*O1mvNt3>d!w8%vxQSXcAP}o}|WV5HbSUAP0 z@N1#i?3mG3?cusVrcOYNbj%eLGzV*=<$}6DrXG`i`8tVhon8dP3)I|M9Z|Dj)82aa z(4XL%Zm{O~=S#7-He1;YckdVAdL)B${64BMLtn!0)UPMNzN%eL^1^@p)3OIphUWDR zysgOC8QPY-Lx(Uj} z+ZS$SSjXhRs{TH<&@O3@YI%TN^f8CLNc%@eoCeBd+0=I)f&I;)sZ%K4f!@912BpG{ z4Qx7hc7?q^{ph9DO!4o*B|kDb1Q=Aq3dWmCWE=t zkSY&f)a*OjU%N?>hvO_N`V6yvKbF0Y5UaZN^n?cY?WG}oE-m(M8C#=2yD&XEy`zvC z$v%AgM$K~FoPI-oh5c`k;BEtCGwBl?_SM=W)jQ{-w}38I^dFy(zhHFpZ?4I9Xs%m2 zdBC}BnGXWj=6Ll;YFp{xsD{fMu3(M%>T4s#*=S4NUq04-c-3my%X$UF zC*?63y;Fmp&%E6U8BcUYw8^W(UpW`@eF@}?i2dMg3Zyg8MVQ_nX^E_E{#69W3EIX- zPBf!lPI5T%PjN7}ZR^XkS|Atl0C%)>Tx2%wez5s~x3Q|p`|an;%cNuI)R$$_x%v`r zXdU7_Yc3GVGus`Uj#GQ9V~0`Ac%5lZwzqqw&g60V-4EiM6fMx`@F!Bpi~3JF;h+Ax zwtWsSVo+W2>Fm|$zMVV<2E7VJBX5%Ey@pT>8kMA^q=3{-u{7k@074<9ZPvE7QP;0; z0a$@7V%Zw)bO zu73{FZBijBWa3T{Z6+ia7QJXeiZY@P2@~nB^2WY}PJuVwteyY;>ak}7<=82{>PweXS~293Til8ce4@MhZ4$!$^AE8;Hb=b#e+mdO!CjKZ@z=hZF4V}yxxD~ z&_AapP9zU+E=ly%Kbar!2mogoE+I(28QDw;9K&Y_>?mmoUh;^r zs~$etSC1aPIZQHXLo{PQKSh8kpg4XDk*$Rqqiq9e{FwvqI{PvYGC(qCgVHWV*t;hS zf}r#F?%e}`_O$xrWb6}3OeYC;N310yD$8sq3#Q%R@sVtHg!~Oby+nfw?M(^PK@{ly z7r@NYkbW0&-E#hyD7Zszz=!hxAxxPX-*Se{k0|@OTY1DByI2iRzj(}zb_VIUuX13fPs=no5)d&tb;|2lz$n}xARiSA^860vUCch)0#}IoGp*4beNKm|B!DX8vtb?&--^Hh|n3M zP=elzak9OEYr#Ft`;$%5 zSW&blRjzLU`fP6gV%5+bZPn_3h0onut!J=&vB~{F(jmEXKlBoW-s>PVja#V^D$nXb z;%7uQ3zkrL`i9pk%#oH(+Gr4)`e`|9qW$~JBU#()r*;J_l3OGw&M3|sLLpmgwnKZo zJxU9YrI!|IC%j<#H$h!LEpDB$gWdgG)V{vjxa7d%7K3tY*7E@w z+&7n!;V8_`j28SYtwBJrD!1n$j`uAUJEJo z2fi26w*PzJCQ;i6DjhPA*C7ra4ET|@4K@&{7m_{N$t>nSrSwnH0#EArc4fAJn7rw~ zpXXhJC<;mRAyCVdc+c-~=x$IM7E+Ain^`J1_lg)>2;-0Zlg^oL)i~Sq!aJ?W&Rl-e ze=mW=Qxuu?;mMI-lz7LN^N6dkQxyV7heN_h@(h~iW4jtjaInST$QaZox{?Va2vH1( zF1{)XPYWRj%CEtb*P`(W3Rq4(yi9PN>+(Nh&mXz}y$Fpk9RK-n5Cs{-mIS>F5kx>(4vOP32n+_2Sa%dboJEd57!Zae(5B@0LzIH! z_P7_%ka(VcuK@%SaW*9v_$Z|Rj64JfL|)|o?;(YTJWmxkfbU@M*^-d1l7kDiEqT-I zzcsp74{{IupA~dG6q4H_e|A9#Vgp%w@ZUoU^-oVMB?}1#kb=Mw3|B$}`wc>#3ry#q z{aB;v)^ia10h*O903c5V^$MV+H{_x4e-AB#9)_GV=!GcTlMNRT0*#;taJL@Bewmn| z>!t@jKK5zVIWCd%QZau{Jy3W=a}7B^DE4$~0ddCsra+biCJ=bb(NY3GJAlF%)Ak%^ z8^ds6Dsh{jvNc%GQwRaVu@@c#z9w(@<30+4unLL^7~K-^{bkB}%;fa4$VD1E0!{aK z-_2mW6car;U0Nawtj_SPxW%o`FUuR5&S(3}NtdX7?QWej@Kl@cb@#aP(vlY}W;9LhPT} z^S`Su_m$ucQu(cGBT_7gliAcGqebzhuajFw9mz3Gg)5m@5&=xw-9I~3HCqiiH0s2) zrLbHQgntY`cRKK?U}nwm7;0S$kiySL(f7q)6Oj`^?TrQ9rTHk{&J4uvcPimy*each z)T@vbxXkKhwk1@2b#K1zlTI2}5C@^YXKs1? zeyfzCV#b@vlT_k1TS!nfDTidoaCT<;OV(jFitKe)UYN6rPD%zgB#*4*GOL-X@u6Q0 zu|)js*yvQM1o6bp8aq@rY{1q9Nb1JSImSr`gi}b-gF)|7s-X!*wEa}a*sHEGv_{ZyQx&p62xz(L{)K>Ooxnyvlo zQ)*9>{$O&%v5L5hmcr9eu`LaN>r(nZcTq0JWT02G(wv;8AIFHt5L6C=CuG?EmvRSmL}Zmu zgPD-+f2@Xv3eqv)GgMW=6=AGM#B2RSQESBVjW&662SB}`0-&)M zT})(5M*`UAj#KmEh|;pEs!kL#nZ;4tLE#VOj7jnuUA%?>>tE1~KI=^ICSB1K=)B3$ zhyV#&d!gvh)-vb1Gc>w4`w|3BL4}W%Q=kyU+d_P)#43Qj?|StzstIrfG)XqKDb&K> zpI+l5&Lr!@B4&~8AVpG9&vu>!uWq@6qdyOwJh^I4FknjMi}>S8Qz}M~zmmrGG|^_S zpZ6gPTZRCA;q9N8Mf>grJ?&US^9&?Z)xg5Sz>iipxa3MvL(854CgzW?+T064a-THdqIt5TFb_@Arzh4Ma!r=!lX-tG?S}e!t${ z6Z;EvG)~lCdjEV44gskt3cEKtZG3tH-X{U|{}rf*tb6in?9SZ>-*y*F?2Hs)pqm6k zYz_yCdfPkbz3t!E>?l${|rK>wh~YVPHq2P0!j z@;u^2LYNnHf9&|SNimg(Ku&$!Lk?y@1`Um}b4pB~vA()3yMdULPv-R-wrwD4mcTEF zq;r~xzSC^x&s^o8X@4%m>$*uMhoU|tuIta~vGfY_=8J}V7KZM)?`-q@fb%@xi4oFp z%{ILTpl&b9$J+1|^mV-+H5->W&7mEdkf1o@}tqx z1a0d~o0(^X!X7T?Z>#RW|K9e>vuJ z3{o2;wraI9&kR?n{As6$%5pU-^r`3tJKpegK>&1Fkws_NqGDqBaE`t!>y^iW@9BS( zI1|0Z!Y8ufw4dG{3oXATV@|5&l~>nz9(~EYRd;$Q$p{I-`LpwvkP-;u_PoNZQqi}W zR>f~BE4fgxe*|?FDUWJQUQ}5=He@;jx_Awti-lTBTUYlQN>169FNVI~toyRU9(^1` zbO|t$RGf5SseOtmr(n6!*s&zm_2=uQQL=-3wJM#~b3aaWV_Xtc>|^#s-XVVw9jC7B zXg8;^JVEy)bPYww@aFPJ=q+!-p95^pE1ay1VL}$M^g%&FnPNf3n6rQwB_?2A2=lwA z4rxC%Ix}&^$#iz=k)~BeMMXX_#31YTH<7P{&CUskcNAX2Wg_i0MxN?%DVspS1zjx+ z?N^Ukd%PvD^17+FGmhyz#8|SV|L+Wxo?iwvIf}?{-|$EYFixq0TGrEUNj1M%GJlCO z8ieM=iVM+-l|+8OKZiE}fn5p35A+KN_F2B5u9Tp_=(Az7)aU3Gxw?`LOPl zswae|SJ?Sb_OsQ68hXMflPfFCD#?usU?@|*CI3l)KaO20XMnJD0$J3CUCUpAAEjNm zS*VdE5CtY=PK`=5Dr3TddQT5s@-c`oL~pJcjg%?8n2862{yLy?cjU^sVJHRmPe+u%?r_qf6S ze<}REZ@I~zAK(@PYlu?|e~)!xw?P{n1vXn}j+Lvsw?~ER{?1S}GJSr=x9-1)JY@Zx zI{6Ywwn-+u`F}EVs=OS2wwNpUhtKbv&7fgLQ|q=cNVaAw%F|P#(YH^BKUN(cyNpW{ zaM#NM=uem77$sL~_iE{!Fa07wZXHo}?5Qy_y}RpHR$wJPT0WSuNDX9q&3& z27vVB&FrpRw-Z2su@~q-eT%|&z4GUvO9#wOb?TA|s_1Nwt!^8^^O#d=2}Q10XS{t8 zt^iX1ji4t->P|vQ8`UegLEOQ;t#<#t9|vP+&oDy$EvS;y#evttvVX^qHFKy{zjN;;@v`4jmRDlNo=@DXc|n}cr1Y3KbzH{2=2Dx4f2 z=y-g*Dc3bKg4Y!hw0^5NH<=)s@7o|p|LD?tkF z|3uYg3yKmdG0LiEEsQ5$4DXulxh${Flp_2Ly5*el@7Dy`dZrtO2a+l38oW0?^p_5n z|I9E=r=|MNyg&j^Whp~CyeH2?sd+dfqtjSAy=MXlN^tc-y`z)A$kj9;16niHx}xRR zA&_)67wAG`*RIrJOKvLK#VBi(Y-a!QBHCekld?DaLYE4-tjQ-$hBsh^^ZFn8`C8Dn zI@`fgQm}7kH=Xm6vlIyb=~JKjyNbC7d#&k%wy1{c} zx~5{wMMCx*PXY)A!B#cjQMoe+D#i+P*kinElcJNQWYI8UTLeeIrsN&Fz|URl&D((A zydTJ8^9r}F66CFlG^Uji)&(pls71bjMO)QRBXzq3sXSstEe?k*c6EGuWp-aDn`nzy z%gLm@g(|+WwgHwKCF>mOqvus=8<7}$z4Kb9G3iVFRuWn;IHBEXJYo=n!Tu;D{o~Mm z5H6;$#z^d4Uu*H`PlY4`zva?MPVMJD_)hg=si!J`Tkv}BA{PTe zT7AO#7BB7_1m2jP?2=kF|Exgt=32RyxO~cQmfsf)&O@;!HZvsa2lN|#?ZoD0EhA!4 z@K7=J@|kMhm61L3=9Xs%Qm`a^;htrIXaGWz3L$}au6X-%lx_lfcV)>TB~jm@9fpm5 zn)72>ornd0+bInudz*koT#HengJ%Q zVzL^t;x1k3HQvi7z2P>A!pr&ycCHT zt%dUvhYWvcKZ40XwdHL2|J|&1vR{1((}~mfn5G)32l-Z?{aVxSEdBB_?$Hra`);H= zK95L0p{!VOBO_(1PZ(DrJwde>JzQlFKXDbJ+*1Y;vXy@)HGqM3uZECw`l_LZWg#VRs4`^?LQFBIkBf8SW|AzfE2Y01y7&!}7fVMS4=-gZTA`-jbPosqQ+7w4E#VKDFNfAs9(v&^BC$GDO(>SO*-_XgNeq zq7=P?Q$c}dUmdW+*6>02Ciw*DjLCLDm_eG8an}fRHwe9ernivHL*u@pi)V#2&eR<{ zjF>10$!$^;l&Z;PY%Oo3B9P=$Nlhn)0iQBUAkqM^`M7?9^WZ4=7N8BIKjhln6EH$R(;0nKbTg*?n%5{1&9e2hD;;5g%)*=Y>0wjR~vs!aOGTa;ejqH`?PYw8+K|B46CB=P7@ zW<1KZgo^k$GG?mFgq<^B& zlzL}5cujlqhU4C-mY|j=P5K4#{=m6j4mH{ISC}tjHr$xx`fnP%asvO`ZFzs6n%`({ zv!EE=Bzo>53}nf3x7EN=qfHw?Y_&&UOP&8Qh(0@>Hk_0a<|63#0`A;2`_9MDuk8N2 z(Ttdg{2o#jnw}g@%gkK(x52fu{ALPm?t%~S5TQ#Hx3ZA8GX3wB0_wjWzemU{=$Dwg zM?;<&t3K&KN`erA&hdD)R9PjvYH?hj0xp+^3X$=hOIQ!zY?k@_MBqJ_5jvHMl%nug zHkT1n`L5&o6)6mAq8_*a7yHQ0v3TT8im|@dKP;ZK4I`5Q&2T_CMEL`u`tT4EBT5p! zNiI_1)1A9*w05_a(aj4dAsi&d3%&+I^5Lxf;qOv5;}R;G5_!V&{nt_1M6dU3tHF^xHDv{ zjC!b_%(=6n>J4)*gV;8m`97|pF(!+?z8>3!IIXb%*}?#+aCPW9@}mAQc`2K*QZzZt zFOb{^K$N_=UV}lsC$pHmFdY{{08^K{qF#|2*=Zcjg=<&RAV;sbx@P_y-$!006`@5E z4_rl)qK6qQJ3*A-0;>bI=}s@6Bm7P_s$az|K3)6ikHN4~Z7y~iyCwl0kO~Z`9aGTh zB#YY^iEGx1lP0?36y-`6>G~yE<`;=3A8whEGX7+*hNBTo_ za1b1epn!n3WE2pn6A(qv%QdPZt)HU*4-H;88*>f@r9_tsrBd>(UoZkHU-jt(DRKh< zqTHZx*?Qaa9VwQ@qQ5B;j~PGyIL=XcS%;T5{oqUzG-38^?{_ z`_!>jUuJ9ko0NHr#=3A1rE|kt3M5eX6!yM4RA(Yn#`-WoeLMSc7JeHWC0+jHzPqt) zJ^xR8XX4c4wT5vF2n19Xg<2{g7-VsafEXNB*%Gaww3eb=s0&NgsVLM^b|a`Lpb1c1 zFp3G0%rKA^EUPq%K&8We+bR_ZOMnOhxooCXxzEY1e?({Q3^OnTdBw}3jlanEK=?$@({sFY8<-=-z%kmZmVj9mEc{~m>U(%}6&k$Rf zJ@D+U2}zU}kzE#TJ^d_S(m{pNDHA>5QO+$bbz^G;P9QT-dB{pcBkt~Y&IBKgSVD4p zeL++4=i$=_tPKb5#}!OUsy*fm6HC`lJE;PV^bOo#rg@?qS=Jfr;y!Iaw_G#$;yCwJ z-lp#2U5S z`9g_?^s<+ptkaq&C8xhA6J&8PCFH4}&c@LG-a>ely}oZh&rCSBz0JC6`ps#F)IXja z5dum$KXUt-`OeZ1O&*chm@xbLpbQ1i=c}rB@jUD+Z+1j$StZo-1+>(~)X)JsPHV^h z60nfGca(}~r16Lt=Yi064#b@AwnpA*taFZuv*Adazf77}pRtXGr)UI(!goda48_yc z7t9dgB1FtCVaeSM&~$Yp@1D`z3lGLw7ystK1R=L_S(S}p;XU7#eaTa<#LPhGtU>sH zZ0X_hb$PO6yZZg7 zb-nX-)txw*qTI`io7m0^*l626RjhEHZivclIP`FE4uk>}59IfJFck#$;~s4s_=hb- zUauG9vxgzCIFN+ZHFftb)e3b7UB(W>!f~UZ>1$B!LJ9 zG?-|;s=xj+VcU!$)kJt^vddU2JIlNH+{-g00vkR!--Mv+Wtxbs9Kl3A@WWTVHIG7T z5fbT37&ZOVDrd#MnF2X|`51+C`Ugo&4J1r}N|;=`D%6Akq-laTu;aDK$~c3i-?11lgpBf zXJ~j`4ElH3{ywTmC`xtvZLA6tVX2b&6T) zrRsMzTKhaJ)eOfPq-;9Mzhx%nKqsIRvW%4e)TX zJh1D$!f923Dl^59+J>K27gHF{CPh65{1hX#Q-Kiwp(hJq>OwoN1?6kC_+*e<+{`}S zwPt4`f;ZSp+03++mrR>#%@aMqUtnVqnQtLh=%gZym3f!J;Ro!>DBo@I?&rycE}QXC zt?a7+npSSz7I5c8BGay$^v&xFQ9geB?cBlSg~k3EcZpG<{x}lSumfg!lkDRPHr!%(u3f;Nt1W*>dFrN__Gh4PebHt|uYdh*%~y8XI{j_Ve6F5y?E z&TSQikQdFa2@b9{lCpk?x|CXx?W_E#Hpq;9T|-ET^tLQmPV4zm_6Uj&nkL@-&Qu{f zK4jsYHO1oJ-VLK7a7rC=B(#k>>`Y{3lJ6W__0>Z){I7a5w4V3WyW%J{2x1JV=A_F}+3Gm0TD*kSNypTcLgBC?e;Dp*rrJ>`M+IqG zTa7$p`&vDsjk-FXpTyQ)>j*ZrziuN{e9t}7N! zqte2t5=&ofWx0-ji%^kT6NZ1*zhV?2|J~vL|G)p=UyZwD@6ysuA0J;)t3J*jE@tp8 zalGy5JEgYkI#kL%zRPtY{3%C7wz`XK-6v1m%zbwQxAk`A>TQ;$Qa4mTnm<0#@XSWr zK(&k8`}dD>zp1{Jbva>4ql-ktD-YKRQ)!ZYJkkeVzP!9V=FezD(a^_(FPF2bYK!m- zgfy_do)~(-z&ROdGefCn8TOx^JgHp0e#=&ot%ds@_IOS9j{f*?bvwJt`8_?2!D2Mq ztIS$qNdnO-u44I1glfX)COAy*a2`5ietCgwH4%PRY zUIv7g4(_?MHbnWX`0R+#SksA&1RGktOjdwSn0(XIQ$Kq?B(h|b3@ywT4>x<0VNou5 z>?Fg{9f?{$-gjJ(Fzl(jv%M~qYL{xdg-YXnkePYi&_E-`!@@VRa!C2mS@zt;&zKE@ zwM_OEZW{0#WY~36kySN}+Q;2UUQZVZZLimp>G)vR;F%H>$q}%#^y-ju&aE*<^DE^hPmV29H`pBd`)4DI02VY7 zTN&XT=lPZO)wR_Xw@U}kvgZUIpww1$R{!Z)`)H;i{%r7CT1nN$HDO6X+0LCi59A+v z&Y*W=P+!HHwP@uZn{_V(h5TNhVG&&A#!qXK(I%7XdQ{l|wOLee)xqE@meQ^*KXuM) zD76H{OY2I$aw`*bUdgs^aXnAX|dN2)D* z>yx)ugeEy;ljVAmZTser{YR;%%mPX01;#rw3{wr3Dh5&=Lddk2rR=)3aC&rManXGa zw<|kihLubGup|J@)nL){5)@y;sS?cZY!#k6Tdg zF=n4aYv#*ZB0cNEMi;|K={rsGk1RDl#~vzX9B^2^66<;{ScFz$NhW??|7o9bPlbg5 zL#PqoyaC)f{`*HdhpN`i^r@jnN#pwqZf+0Do8Q1iOZhfhZ&l>OM@%Tcj8oY=GG#}? zbcOuoX_#47h2R_UtW|By0@S4`S|a?-4~yD{wCJX`^PlMqRtu(XknUL{`s;LiqGzmQ zg^-XNH?2u*G34bDZS31yN(v{xY);u7 zUxQN`v+)Gag-Yt~3)@=a^y%t70ixeR_gu=8KA2srF|~l~MJ4t^awXg1#W89gj`y9a zesmA$3+EUjN({ ze%c+si%|%~r%!s!sh;{#mt~_(2B0uEt27cuyO|_+lBP$wy>{8%se#(lLOxs8aZi4z z(4ljZt&+Fue07a{79$GkZAc}fx6buJ60?`1?zH*1c?ce8TQ?I`5(V zkG{Qg8Rh!3!AW@VRg#e(Gc0P;O>^jL`6nhOUUm-k^|vK#J!kZ} z2aaqhpW>(fXX9=Dno)<`c{vzXMr;{#yT!!Md)di8!+i6^dqZM-0>t)oFP!@MQO@R7 zkWt5<>5*C*m8-ecf1r3=M*hX#62F<-8vEsAzFm1E+x?tH(9%VoHvZLt9DqD1u>K4^83aQ zt^_$rnH4w%PANGw<-T5|{qVr!E9wmwm#$XskG6@Pd#9~`x#Dxlr`kO(`xuH}SRL8- zu&Q~WSo_u{hqM2=8p&mC{&T*e%YtP~rd1I5rbr*hW}BVrirhT?daW5_3+sZYBU53e7H3+VqGLBXL~rnte|vM|V$~be zJ}%h0UB1+zr@1;ECfSE8-N%;(mVNv7ja!1>_`VU%rpY2oU+l@;?9`Kvr$6uQH+kJU zq^urL@1k_gbjyHKbkuUzM^7e?zq%&0yQ?blT(Bsuuo|X5X}1JI9$xy)XTp6v zWM^XT@eh*5$}lhOWZlU6XwPwJlgxlOGS8y-w|Smp5?OZfW#_0!frz|7fhhM^%}VOE z)f>M)n;J+xJ)Z5;DnpBr;d7(V=)K|kViP|eWL)769w?dfE1WuNYx@o^%BbU5L(0+> z>-Xu~eEr%`#9l6%uPkBy1F~l9UT6auY!2Lb#*c9 zd9Y8~K)GXqfod<6Zc)z=Y|pcg_G zemObW$HK$QDvQ0}J=ibHuJOn6MaST#+FMak6%|7MMQ=49VA98plD3{(SUwXWn)b7Dzyd-KqOxjz+} z?ghJ*`M;MkaePY(H*hi1qNg2Z2u*Ua1l;-7-JQBq`N-RwpTF5hF0X5&kTyv;D0gmdg)zlHDqo>|78W3S5= zfrwlcaP}6oE~uKSeF{-KkL5_*QS)(cC^3}8gtXGT$f+E zkDq*hZ|{A3w;%5-l`ix4pIt0tSs5l;?$_d^tlwR8dtzq5e|K}9!_}ETVGG)Kw2DeB z{g`fA7R0N7C}iO?#H=-?3FO#n{fH{S3=+i)-zQDd+XZ_qAXycJJ=) z$PzjjmWSv=XT{kz4tYxDPq zZL_EL^#$!&rxhi0sNh?e-my=aR&vSVNdh?mI`xhwS=Kv_yV*>R_WEG6np>6l*>l?b zrjo062C@s>+xPGQU&H;PH1lFr*!UVvP5=CmEVyFV&$dzU3JDb7^^e-?wsT0IF$x>~iI6#}8CFTv zyCFr}m3mXdSM^PlY+L{AyJH9j#~L3AM6Ta&U}J52m$(U>PM_3qU_kLr zk)-<2%jMIZLUVu0$MelU-`|_KbH}riWA8*rEI|Iv-9Qit=j3;-mAV(zIZ)UQu-y&Ie1u;!Y;_B9LT~3nAGTMxN zI~wODhUoM)`;AN|97J^C_HAihc@sU!O=WuXmFuxsZsL@xLi*E6Y z7u&wSy%ojR0YJJ5A8G2J#dG@CoN#O}i|x9}$sX7cZ6djvN6KW2qoZRem;CYf>txqT zr)eS3MUwpoh7~tfh6CGfWz~Vm3V#n&1i!kR?Ls|%TKMeG*Tq<7!=Fi5%8J*aYo&$5 zbc2|+=1Z>?YmaP-2ZeB3eg4+&eD76%$t&*q!~|)@MQ4^E|IiP zWXJ^sp~BG`bwq3WYh2c{hOfhvHa>lqW+?unF(dv}F8%vW{FRrN7xqxJ3fA@Mp=r)V zUWFq`Y!xdle4YpUz5i7>@N7ql(T9fzm9E)|&a@z2^fqP){rvclDX-<=VYqAjwj4y1 zUC2Z8;-`Qe1x_98i?th4b|KI(-Bvwy7n%3_M~BqN&u>mo`wR~c(?yeDutBTj&R$uu zeqpRW-3#ec?i(Bygq4QW-A8c*;8VES-eJ=3d**!#c6;)LZj&@w09jetQ--xO<8AQ= z9iNnQ;oF$-%zYpapg#-$ncwqZ@K=7DA5h3M-_!7baj$a2uDmJo8tK94S8uYXNC}5s z31rr)mz6r0myXjk)_fAqP?=v$Ts&2$W6+?AJ|XAPZ#F;LZ-}jj{|t5*-PAw z70%sZ;%>)2AFYm-I|mQv=rQ-}mwi*7!!1dEoa(Wq7pazdti5d|nyZx@7qqvZ*K-@B*3fxZhE$klT5d(u`7QIRnGO%#lz%cFC;MO?b^ZGF*Di}jp2AT)TpGY& z-;~Rmd0wY!BM)a<&}9I!*@UbQzwjq4DwYIJO&4>^r`!C(j62)L0o=q*l(6w^ICJx-St( zS1CJL-ak)hp(VWXFJTbKs^}7i0FBsj`URV@U!T)fjysT?3r7~Hn`{2G)5UHfcAQ(d zRCgv;^;c$DL2t?}*aaaVn9~yy0-m^b^GNVtxNrd|1KXOG{SKKcpOT~gI&NJXYntSb zoLUW=!S?5AT*J58rZ3)dd|LV2c0OlL{tUl>xf&q#g)je``hq-4NijSHC;Io)r@f!} zl~cP)@fat(3x(hBPsb9$&7Uyyl^8v1bEXv&rU;Aj8u`8~q$0m?&ir(r@!|7{R%I7? z*lD&e#N&Nl>{4otkQCPDcV2Lgg+q+*8aYjN)(n-L7_}7g6msB3Mq+TxHKzxe@E^H( zc(^WW-P?1AafPIjC16Lg@q>Mc9oNIdx8t;)4K6X{ku|SgEL&7+y#LUOW5M8(6yQeQ zUz_`08^2p56cGO!-$qHgGC_%oDUnHEe;6eVYv~91crA9JXK&CtH>r{}E^9>iwFxxQq(DPr;n^ z#s$@Tzzp^^Jzj4d|5`kp7U%VycXlYme-AdaZFWrQ=Ef5@@!S=5LfTuKALXeoV2jEz$tDf7WUlpI*d|lx~dv2{NECaRN0C#qj*;JmW>?yrJX8b zJc%2xk96*5YH$2ewy@oGjZid)&w?WE%b7BQsh^)s)&C4q==q!@t}W#2mJsE6=!uJH zXGKW&ISvgS-+@1!A>v9(`7djpc>g|rq&hlOk{@yLu=ZTgO+~w~`7C*z!dl(1Tyc%b zp0yX3@LIEmf=IgVVmUiK(V}X-U~alwlT|dFe>vMbh0p}?x`I`;hLoa(`U}K%B>F7B z`tEqi%&N`ytGZ)d4Vo;BzW7Z!0N%30Rsu!ZYOAWghH48+_uc&<<5^SxGo)!VW6c>Dg?aI$?fh-wVrTfG1zsgsAT@NYLakHh@8VE%A`PCp;!%e(dL30``^b3>?Q ze8P5z?OX*bdseeIWS=@ArXQz|$T!{-4a{o={02tsbd+G@y}fG%J=+;>NSV?PpSJ-P zZ1&aPw{PG5c~k?CvnP$7tX?HcYx;_4*^O{u5P2PobpuetbX(FA8wLp`aCFMuzj9)f z?YPPUo^MfZ*DpCD=5$=KYCKX>Zs_w-mC2q&kDtn5f8@toTsaUsKRvAQ`1$dggkg&P zcx_I0_Aw+k$ImAMgdsp4cojiSoAv@1Rxt7X*5z_*id$b(WJ`;g-ld4GQfrdUz;PF~ z&Bd|q)~F1>ydZUfz_FF-3k^5|C+^Wjzj#hLz_sT#gdEB_vecvX)XI}ZL$3sFk9|z% z#j(O>;U}#><=4_**`Y07D6A(cMa_U3^YqP;gug>bq^X}4)&_yhQu1jQ#rsePKd3QQX_CW3>!1^r9 z=Vz@oJ&mk7@5yz-^o#7ewn@p0-}8~bEl%V4SB|X zX*^Vccb0*f*FQk<52^67`(b1b*5v(oIJjWV8AX325PC^Ir8iC~g0)!}I{)5f+WgPk zpPw^K6eOmAv!@1H9LPfV%Gx!_bxa(aOOvC_t4^2R*%~OZlhz*X6umb*ecB41{v~%GN#56Pls=vU>4Yy^yEEyE_IQ8mlc86u1z1C?gt5dq zely+&Hl5fRHSny{qHECqt#;}2Ep5+yfkPNhd`zb`KglTg%2uQLGd=hA?y%ewUpzaP zIu`%_XvC_5B6bQRdRZU57sGLygi-xg_|O~LSlS5gdreC&!;`a(D>OE{l& z^WvL`gUNm+r%r=mEYDk03|e9H@awfQjuA=pU%wkIj(&R`n#Sc)PZM`W%6o8Ik_#2Y z-iqJTIkhfJBASO8oR$r~_GsI?XHThBpg>-kZ|9Kb{iNxld-gvYk;|pZbQegk-xNIX7|re4;XWc zMyeY;m$cn>hcli*;2b;s#nZqtYOu=1C{#>TuTaw>yt^XzuTnUoe_ZvWL~85{ln_o} zAj%c;dNIX!_o^-s5LxH#HSoq-=-Kr|3DKEBx4OoHd1YN@YS5`$m=o}-~7)3iSIFk@jEy*(Y1pP>tXR|gB z9(r_|fObhxq0*8qkb_pfeY?+e+VVa~GVAoDqjiKn_7w1{0+vaBC@mU-B z&Q?d>>^0mX%l(36DA|d7kAJv7KTKYi>7fclv3Mg^)J9XE3_P2H8Sz?UR?n`LM=y7~ zq!`V`=KQiF(D2T-3kiujVO7zHOK0G5QgvS&?p7}+5Jm5j(N2>sx-q|wMM!K7TxWHm z^u!&`)~6mEWVM5Sd?{8_`r>JGd`c7LRl?zsPgvp;!JEG>N{JX*Emh2tzMI;EOdCZj zn(Zg>P$o&|r>ENH^3Lnn1~4Z@sAOq#q+HnMv)t`E*XW`>8SW13%IyL3<0%L?P`$j` zu|W7SsHeGG@Is|rB9Ycu9m1m|9Jt1}gk4pKHHLLFC!5@{*PIAHbb zgCWLUm3g}EvB@ENFQ#!?1@UJ2M)7XUgxoPo`&BHnYm#H(chMBrqDD16>vZ$Fm-OeB;9v-{OEul4YnX(L* zmHFf2MKfPclafG>PFT_sIja{7W+xj_e$4i6u&~S;d7(X=ojaW3=3@7ywcoL*#A$N5Tib|QoX9N zcY2fdXwP%zEzQRw0$KAeRWr#@4g_v1I+)5nH#=V9^(}rb3D^#0dTQFeoEp`u$a^aUo`P0z4HDkIejFmc<3 zB+GK^rN{Y>nTi=imrel!T`_(@_y4$oFWFXP>qD)xY=D*&womdGPVC*s6JKG?J^N?> zTDA38_emdc`YMrHN9q{rqkC}rDYd#`$m4nvLxw>cq~v8h{UKSS+!@r)NaHPK3=`g$ zVg44(Pi1YbxTa?O#7Or@*^duCGavT*jC|P7$@cE9t=`!2PuBsb!tuY!<1GbQ7q*8P zInJD9eKPsufy&Hi!@0%ONLQZgOU7~70;l>5IRc)aV`)g%iwal{MUx+n-y#mpX{X~; zU>ZAe8w?h22sQHaT9LkFCHvgy{xzXG3!))QX^-`voiKBH&Yad)0w}&2i}9Q}tV(XN z&c!J&2Imd>VG)%$g+AmYz8_N`Z?Rzw)eT^#mR;C(=luX8asZ@MY+ok2<7>UTZ$~vf z>yA4et?X88Z9h!^3<|;N5f;O)`@%NiM@7TB2AVT& zpqHNXAYS)17;{E^ z#}VH_{e@~bjjA94S)WlvzB8H~aJV3T_j8w}m#DNt8LUs=<3=6{ zVU*}QKJ2$xsvKjaYPv-}77RVL?+HE=KRYV!J=()y@3l)n-CGg(`9S9LB>HO@0olhD zAx_HGKtXR15|`L}9TM1hoI9gr*1NPaslFV~#GVxeif0WhGeedV>sC)Iy}>2#@=ZtY z(x?Ji7ATBp2BtSw&g_o3zNfxWGTN(AeZ zRRyO?pgBI{^xvvRrau%-I+*W>5xTsQ&L2cgXhEz#+eMrT6=pqrXXRzBo`zHom=XV= zA*o@u&b)5aL(y-@gIE$kD-uvb(yULGbh)g5 z$HQpyu&u3}=b)wE$gMWYLEYC#wFo%*yfqdSFvgJh%p&G<%j%g!O5L#)!!A?zT zjqbIxs5a3gZ%OV;fBiRm{@IuzE-PEhb(dbrc-M%*nQVY<CjLPyzKsb$uvt#}jiTGPoo3JBDpEUI@F~S=Xi0*Cc^e}3B4C00<*#WP~5sY-j0IiV8!nH080NY=O z7ec|Y%1Pc<}Ft66P3)#uLkkO)W za1jh8N9Or^-~MgR0$7esMQ}1GcZv@{=MBykYJW!;M$a?e2Iqzh_$1bN_{HA|CyAhJ z{`^yxjU6Z|3g~nJGDbvNGDb^=y~pPrs4^U=q%=$$)DvT-bvfJQSl^p4QN6QEQ{BSl+GL$S7Gkm`f{%eF7LE#An2{E$ORLn}rJxvP;AedomlLqgcuVPp zo-k@}6xOJ`z`2tydKmI5>{hm0Z+$>`npAecx{b_>V=syVbU2(~wS&xp^5%y0S|z0@ z+c!6uWA$yXF>4XKO}d@^_&h1~QHTQKneWtrZMk|l6^AaO6ahF=alG+S@msEJpNV0- zH$5}pp3dI`F}V>c4Xc&{XSga2u(^e(1QI()I+TYOqRc^&GR;1Z7iOcJj-Te{{M}c( z{PzzJMh$gV9Gw5q{FXF19Msc+-BCy_uD3Z~7OQy(+j_usi_zi##UaV7Qo>CucsRX; zuqwF~AYUsmb*K}BDQ!L@OR@SlIA_i>YsqYjLIl1GqBBTHGY&}uWe}MyF-Zvg5SAjv zcsNltq|vj|ASBFhb#Io{eO(o~9@bhf0%C``me^mKvV#CC84JkWF3{R{5dq2jKo<^- zI+L<4pqqi8pWlz456Z7fd@2Y%yXzKWHS*%{Lw6WA9&b#sHDFiKoPw3?4dpmstO`S$ z-)i^MeUDcnvr5DpQGyK0fS3|2>8lW--Pq~8iD-yrQ197@()7!#;o>>%4>IWf`xLnD z7_ZX`Hwn_+!knky^?3<5W&L(xv64})#ny6PHT@C}Jh9%v-rEvm4zUzcW4kX!UNlXI zzVmzPLy8o>^t?-q+2p`SL6T?rd*5u82_1qLF9_^GH-d}@PZO975riJyAy=8+}K zbm2F%zOgwkmOT}Y#0oZQC40Ck~>Pz|%N&bNv4wTc9UE{4$nvk1G z`F!VfQL=AWu(XnT6@TVxK-rn6zaZp(ZLMe3%P`6ux10J$Cgz)FDT8bGu)obKCx~QR zrkyK>U@j|1az4~#{$%h9hiDsZ8-NJM}3?;GqPX^19}8c;h4g&E};K zhz+8%KdCX!znh7J0m9rLN4J%xl?Isv8E&$l*NyDAIJE-Mgh70L$v+1txeWPd`z4em zi*HDGhI_^~Kzz=$@r=J%`1DfG_5uIyPcny03f&z_)2hT5Un0jm?Nc#odavBc|LqD7&TTfu{EKi_o z&w+Cso@;m#w-S=*R4Hr6h8gd1cXb`WtJiM^k=v^00US+^_vzI-MYk;!NQu6-n`)Bj zDF@!=WZm8>=6^nZ?9(BS)^epbzc-&;{+QoYce0bOgkBP%#~7pA{NGbLQam=l?(H=T z)vuTA*&upYIn%CH73HsI35gM2Je(_H&aMclVA4l(PSssN&Fhhx)1_WpStPbD4R~~U zfvozR559@Fk!+K8`fyc*gi(l=G8KC6^n>!1%>&O?y9JTB07jSAwARqvC)9?E6%8a3 zR;>YVvrOvb{x=l&X5`#n<1^zbGE5pT?U{cqmmb*o0NTuXC)4DBDv1bBNP|?*8aqzL zo0H~5DKWop^^ON|$SKB*HK8)bJ{h?cQfr2Ho`MrM@m~*iXs%b|lJFR> z@??s>4jR2hS@P+^!(`D25X-GVq|QfGYT#Apw0O^k@^uWO$VhzJ&&0acsBEo}K(r+4 z@FZ*J7Uzn0IoceLg0!Lq+@h_oFPNkViE_30H6GgWMZs=-!eZ~dQz-v_M_bTp;D&Us z;I-jXbyj0_p6v$hvi=i`k!>6+CX zsaB~5{L9$n7G7czIIgC_5`0CgU@iamV731CQ2*KRW9V#1cR}~SJR0BvI+z-K)qK*` z#!-f8oA6UDk)q{p_u@@if|yk=lu5OnKKaFSWS3(>$3krl-RsO+Bt15|OCUXzDxOH? zP2j+_DXlN8zAV|$aKKWrPKwXgNwKPY|Dp1uIY*qq`?5q!D!?@*b+i>n zEKbPLaz>N3kj<>d>p{TFq|R@s{l<7&JtP!_2smZLI;3^y9J3PKQ~sEAqI(u?=La(TJ9yw7V+gJ_lT1EGt=D>_FR4Jh|lG)#n- z@>_~*kmKr@@r(uY|0bg-3}}7~>OyPPaQ7Sk=Jg8|k#fjPYh7#AE1-b7GHnVb16)F^ zdy`$P_m4CmOh-RfIh3|r^Q~rgwXhoh_f_qsT4(und_OR_=gQkCWOBZq8#*DlL3&=Y zExBU7%Ztn6!#lH_M^0496y4(%tD zy>9(2F(|-gT0UnK+Z|WE7^6y5I6B-FCYt7ZVn?Fl(hK*Z_36Sf)L8v&74ExhxUG%X zy*z6Y^e3dDa{c~voj2d#_IiH{ZE1b5vO@5*6l7RZ6LXYFV;;^Y3lTZ{LP;)n>W2|| z`Q05?-3tcLzord=Ti#SRlri0tKQqXm-2zirWuHMU8V}LRv*}?ybe%}7Ten6qB>eX6 zUGDCiAdXA`Zv7`#0a7dqGnPQB1L1Vg3IGXVWw^KkI(vxF+AyT|eOiOe?L=rci8Kxg z*)IdF$Zda7U%kQAa%)n}B6SN0-hK^ts=5C%VN5f+@h=k?eQ-n8qK51ck-|Vh;Qn(} zhtsFfCI9)RJQN8a33*8t7G^T`$9Eel^u>)A|M`HssLZ|5lP!J;t9b+J$I!mw)MO<5 z;uRjw`Bdo%^fa|7eGq(td9EAl9QeWL7P%V%#FXhP0f{koCvyiSh&jjLud5Ax0OfWhG zha|Tmxh@0|<1kl`RKcI4>t|w_wX{S+-w&XFib|V10c1*&8J8|y3e;mlDD+ARdiMy+ zpbrK6kylosHlwSFRG3f~wC2Z1tB{`&DSc*_%hN>dkQC%a0OG(iM@L?-4RHbyO9yZ7 zAXvtDHy+^utVLL!9mx-o$AXDw%tWnE9?7OfdN;{|qs&}bIn+lvQ)6A&-u3Jrf9hDD z#7ab?N9`kB{`te17YOiM%*_QMJKRWtFv|MZr>yt)jZYMYq@hgPc*sM5WAh*d=OTT7 zN&TiB{=O?CJ?2xc_=AP+(pUoQ&VH5z*L5{re6J3Keg988a+HbJsUVJGaKE;aUhms|NUf-6@ zqL7-JH#OQ@2I0lo2X7J4uv=5TRIAF3hm&ER+1u<5!sE%$ zM}_oeQY9cdFqA15U-J7)CPjf#k3_B`{dflDgkVG!%~Gv;2u}a~n)rNBA#OiT&Ad0< z-BqtAEA28ME3pm_kl0Xl71?k+i06&JZ~B3>1d?bp(J(r0vSq=vBJ-Ph%IFZ-P&u+2 zStd&YAZ>AOJ=JKcVRRqQC==q(R0%?NDBE5j;xhc{JL#_%ui;D27^2&CwCVi)N;W!2 z6hJt_;3$M9ef{RmTIdsE^(RHK3>kz=H{Iwz>$8xZpXkdNdRm?+fIg(o>lvFi;Td}T z^#TNwq-+}^@*Zf5hb)mP6CO$dnkg`nU_2e-nY98)EQs7_;Wr@)|6>EpL?HsOjFc*|yTE3% zSeDF;*?>JG4GMp0%SAYE;02#UMWl_K7ENO+6bPYgq0uEuRq{|yz~6_GTj8~c{1}ZA z(iChu2Vt5>u@ej_h?szRV|ok96v{9`a9S%U=t#8u>rd9>O^^QfrVpeK8A4xZq821T zs6vVdc`IPNC^iEp&|5|J??6*y5eku8l#)XiNtE!`fRNC(vjjj^ zDUTpHhE^IpbQ)AnLJzl;9-PT@NhztrXl=%}71g{!1FCdqkOi(cYE4)Uljl?!-Vpa`W#3Zcv#g!uDY{MYkOk0d z8a6{_CP-@CD8Dkp?f>2NBnV+|gN;cwx2Z)?l_?s05nxDrp84RvFdFtL* z1-EGNZR7qbt=Yw#d))q#2Tck@E{)GS|XH}RMF0m}TxRk>0Gx(eoIJ6Sq!F-b;?hlCSh@{%> z1`T{^c4jIEbUX!i@e&Pil{Gc&VD6uu4|~=u6-Af{QikPwi|$Fa=>yq^S)r$;qW=K! z>^;XDi_>OE4xWtG>lNRG<|5G-MLlq4fl!4q&NrHb2<}4QBUYjj%yPpJc$XygJ^*%w z)1T0^JTUqUOJ3ZyJuKoKw3^%CDd=6K!6tOA_5qEgJ}0()Dv;^HCxID-l74Rb3(4a$p_w+)%avu7cmTzg)fP zI&g!|#R9Y?Ua>VP0P~6j#jBPHvGSFDOF`%vCYG@Hc#bX5hx39E$6^C&80FzRTF`!z zZpN{mRVZ_GfM1kJA=I4!yxiB6TaMP~1E9dJ&tX=X$Vd@@Bu}F{`7PQexPvqz^;KB7 zREpM|B%ShT7y=Y~g$n$_E!cfDVJX6~qaJCr6SXiRlOmnN9uv;Uwo|GlYR+M%JRlQwk!NRDDAQqq) zrJIBz9OKT11MudO%|6;OXMh;CqOA@+ng9p4iKco1G!sToUv@epSXQ8^mthOiBP8~z zs39SmRH62_knO^@(f-z3=s2@z^+0+1EBX?3woAf01OjOho(nY~%Im5sYqWXrJC!n! zAF^QKn=oZ%6rlW1l>m!Gczh7>Pjdx_1x`KA5GQF zv^-E+b%sAnkpmcij;h5pAk)$MBpT&>nH5?}N}<;ggh%#4sV`H9x(%idZmHx?4mkIL zA>ZvlT6zTC$N3D?EZ?|wAwR7r>JUR(7pbB?KKAac0!(#fTM5(^X((q?P*c$@0k952 z7N+>vw`{3W9kv2~unUwc(TMEm|JH;aWbd(Gyq19a_1$TyabM?VO6H=PX3-({nkIgm z+fpRWCnw+%8fhGhhIT@tfE;gr#;=Gdtz>Shbr=bgGj45ajQ>d z!uEULq){J%4nqED4L=$+D&sd^omkA1nU*=YU#PjjYP(BQu5jw969|yXD8;GtB%I?H z4W&k!W)uyxA;mfJvpE6OQ=p#AlkED)Gu$FSxA57(h%AQje-(VIp*jMT5aof5>DC=AKQN40c5sUDN7`)2UO4 z`9@8s5fs#1ShQ51QEX?T&$6p~ldX4nL;NwrvLpe>=kzo`_FMv~vmm@Tn%bD0AnR}f z*8`8J2pRWsG$?(C)Ly|ONT_!5)K6v2(Do(mtMY;zBhFJdutYDKR_C)tslcw-Tki0u z4MZNxrTPHskM4iX4v-k|2K9lv;_ENiI7I@!HXQ-nNHDxoz7#6Ro~C8Tj0pB^WrxCrY8z>em~Mg zl++@q5&{6(1Zd*SGEo8rz1N|MN)-K9P&0hTn#qwh<0zR^uPqs5RAOQ}Q$IcNwy<>I z?q0V0`@1Vymn%cfPi~Q^;#|xlm4Mn4vT&XNqAnv=vC2~2%SU8Msc;I3(Tdi^j0EKGZeUXy52+#?Vgjh>|_MHkx_8L>g9cL`9?^>}Su zk(@1CMtLVcw_Cy?BT6hc`^es|s-lS+HIOpGL__KF1Nr40)I`$Fo^S=AXJLc)=rLeN zekXYv#oXi362xRPzt6V%UcI7mGUvLO5*RlKhbExG%1yIh89dROgtdqzci=3-Zr!>i zDTLhfFfjTJjx_G9fCvT{SLdBTq3_QRhdC0Z{)aOwzdDn`0_&l|l<(gVy!dh1h8ofG z1C3HhtHD3+01j~!k~O*`5NuG4qYV+6a}Fk zfEy@q;<7-kcL2x9?@P>>=vB9ya>V1G4KljgWN{THdT}mf$VYu}Zlar%TydueHPVW7 zXTf>fB38`DT~fXR$cH?tev=9#{Yo)f2lZn&$Gq!G_o0lk+!yCs!l%3ex6&lZ+anMn zBhob10K-#@Qna)XUE=#99f?SNv0k522Cbtt-&#Fm_tc%yE%hxmE`?Nxh$J}4(0Pf* zo+Q34Ph1%Yoj}AxU@=JRseto>qzKX=D&#xHd#=iEf>OYJjPn|Swd9(fzrh$HzSJsh z0R52mMi%^G@JVS*1gOkC6B%B1-LIlwuqBRzJkHWji z;NApKZA9KrfzlR-xeL9fz%xm$wiq0_F{t!afNRp5S9{j|juoXfN#X}^ndEW+2DB{m zqInQr;20Sb=^8L9_C7^<#z9Inhu?^D|N8;B2L%X~E%hcy(l}pP!1EG#{(ZWs!Vd@- zZjs6jbEy)}>}%mba`TVTm1#(_zd?7d<1h}aYZI&@R;m?ttubAeGpR8pP_q!K+1Xh1$>lKH#c_POANk?^Fo+i z+#ZvIIv%>P&jzof=_Vq?-YD#Uy8f|mZ*r7NjY`*V<2_YoSpW2&C;i`q<+mO2mfER^ zx}BxshDFN12FudSp16c+K0rGmPLf_^7!X#-vE0qG`>#_Oir`<6UCTW7MH8#*bLN!` zqIKvr_!VnX6CjPc(W(* z&^Iafw?Tt~v2Ma;LosVR=qlLoE}5r;+v5Cx$!Ua?-xI`3-Ifk!9RKjgr(+wTRB;yp zZV9Q5RS74zP@o0oy+B94=)bEM*l4)q1g#;&JmwPrmcLVrup)G% z+-v3(PERI!x}N!X-M>zT57AIoV#%{dYeSRjf8vIhBczG8H=lGuAtaqIGfyy-9FSUL z`x5#0Dje7livJ?jYR3bN{DRl$X{HKaya$Ta8+!FYQQ3e&oo~w}S!M7ZJ>Hjyi@0sa;OB>{Q5HU-r@2^V7OU17RIwOb-8qqm z_BEew0n!zHW2C=dHSFOD9rCvF6Chv+j}1>tQT6DrhDHvZYe+wn+(^WRYcun2Jv9xr zi!-m2_#V-AeYIh3CmMBIS<0>$+<1hWn^+ZV`yZ|Sd_b4Hu<+>rb(1!n#7(xC&3 z*QNPn21M*7bhH1{?|fsy6<*3bol09-CWRiH`MFJ4kS3;rmITlC=PbCHWAu>DpYESJ zV7s^a`OO+U#M|eGThdQtE+ibA7xM++Y$-t1>hGsZnk6rGb$7eY4*1vlYffHj*e-mL z8t%rX+`v)VS}G8_D2r{ypAn0>D(01Ddyb^Y&G-nwe=E%QZQn1=vp=Mr{rGx8FkHwa z(f70#Dgm&m|92k+ochg*0ntd(x`5sZPgKC3{QiE+6p(UsGV2n5^mqOTX9@$<)-Kz0 zvCPb`E0S=4&=;w_rCn*PZ44zn@i-Ju@qYLE;jTACIBQDCI3%({L}r5ycf@0EykCXT z5~Kxf=aSX0y07v$n<-cGLh^rRr>I-auF?mkTJ090i!OvN+JDHE=!q1M8_|z0{qpZ4 zFx@^U|He?ADlMY+f>f&mx@qPF#2X?E;@gObpii$uyRp6$Pbcw+XG-R7D}C|4>M63d zTjzY-ka8-;;Y@n#W_K=*#*Bdk3%4Dx%0@5z4#8PEg8 z(>%9`B)k57a* z++QKxoGT1|19uj&tNq%5OQWJ+joRLV6S2JlS>Zd>h*16FAW44#+^vF(n_2xB(&`pC zPSZSlUK|S0LR=vgX=qf3gaGMr*^{TDFEPNXTmPh?IQdHn2|y(2pWsMAzog~jCX(a; zd?wPCFq=^G63X(^@SVy(L!EZWMiD3@cj8_G?xx$Ps33-Pc6~nH_DmguLDJD5bDxwu zAkPiaoLx0fbOM~fT1$Y6B~b;V^Jc33)FA|^$OST%E6o@$uZE8@$zmv=gN^{ukmew= zSPHmtVW-2q+5f6m4U1pN1*>UVjt)$c;Db>AKkZ%nJJe|#pCKg`MNV66F)AvRbRef% z)(piOvr$B8C7qB%R4cR{s3p^2Dd#EagiP6vY_wwEC|RK`<+vKBQ7MPaes13VAKo9{ z>*~6?a+sO#^Zh>ebKjp+D)mMyf*^(@?+pC{l!iP90#Zx@+l2}hRabS1|GP|^rlyJ* z6s zfNIhEx2KJg1zLF?@ew6Ah2>Z+&^-e&YDUptzA zoSE-k8-$0G6dl-2ygHz87wF>+AgM=oMC>V*nKM%%J}Jo-_B~k#J(3`@8x3*YGNEM8 z0@~{Q5?dw{s3?3Jyo+F1x{dMe3>0wOb->DwZau2QgHE1G9v2E>9u;M{JQ&rSmST!L<;64Fwka+|4gZdbBt zumPq{Z?W4?_+}hA)at+ES5CtZi0B3GP=`&pw6zYigfwibF79uOO~$fK^!<@9w1mqJ z3D%<79=Jv4HR0aB#`n={ z!M(3jf!M_RuciT~4Y)ry*X7@!3OrL>$q*VM>g%uv{`F4Vs_7-j<7JKJ$FuWyKFi|G z4bX}f4MUq<5y6zL7x}6%DCz)A*Nww$gJocL+M>j4;TEI-n9*PZAd5jbHnDxk9idy7 zhNVxi$NdfIBGw&}PymTC{!iCVS_S}roKeZWhxCz3dHhiLjZldf;zux9k1(w8;AsF3 z0MSpK>UzNXf_Qh^to0uOiorSgHG*6wTcJ~?;3D1d@tk5yEOO;tJ^RF`WUXwds;Jn8 zy)sUu@CjPx-$J=Fa0Kh_0Bp$hPLMtWBcuWX zi~t4}_;PQN(>P37$;Q<;Zn&=Nv?(8BDG6=S%`kV?UYbF(%{VG4To2iR&`Y$Z;l|iT zR;WSI1IgnJwKRjIiZp&<;Xn;==V1-Flkw@J=maM{H@sa86tOlGh8&>WSWQ7EaBso4 zcvDkCD1lNhMUV=Ebh)$>5f(;UilVzRKx&*)UlO7f9kXHWS|&m}+JUIZQIaAZ9{>j? zrr3|CeCfBCDtBKe7*bKI5SWdz;Q5>j=f!N%a#$>Bm!mApWkByh zR4bgL`1Jf3dQ(lj(wDqYvntHzVJ$zef=eL?6&1{w1=jV0Jyy)1#od@MHU=g(mO3i7z!`;sWV1<@e1{D;O793aZiYBeoufv3cJRfa#tQPseRpvYVQ1jDd(nwx?mCuZr{?vFO znoErpe9n!?MROEq%7`P6ZQ68L`;^n?mOlbQHmdD)yV>08ai4s4)V{y<|E%7DSpx%= zIW#vjs0?C4CA96iM4;zegbUY~?WTV27%NrG29hWB$H~w94%*3sAa`K9Oi2vveN0*q z+{!0qIcZ*S#`5G(bSlhFWj|GT%uJD0J<#kL@Wy_Qv^-BLQ*Enr^>n!}uh=5ze8^WQ zbyM%6j2lzT~fAFAXlKV zIAx_bA|8Ps6LZY~>WMZd2$@bA)rK6say(W;$3UW^jXJPftD??{-|TAJj~liWs9_Up ziiik%Y&J?*TxWD>pvw!76zUndK~pPhke`QL9rH1^38x|8n>dSAui2%pr|)iG=D_;3 zSyH@%vFdo~dVAJqSfH2g8wvGWt)IIdhb}+HCLmAuHhv}9EUe!l-SVrS_rDJ72*5Gb zBdN{9wfYZwCrRpI-&8HxJF|Bvwwcf9VIo;X zVu5pLAQB|v%1!*^s?+dF*;!6?y*Jf+Vc-IXv;ZjIcy@9wVvNZ8Pj>!O-MG+lCq@3l}vxwJdzI>e+%|Y}SuOO&3ufDcDwLECJv53ic=j6E0WF z-63Mdson-tMmxoiwp&oAqGUd@R4Gx?&&*%a$6fS$^XcjH9@bA_9F?#bt8KntGzcfh`9v2`wf{kX^ z*%K#NCiJ#uh`6}-zN-+xdP3!_X=*3VKHT=e_f<;ujwcGp7$DsRS0B;xWJVptNp+wz z0R8ExO>TW%9u~f#y(KVZMYcH0<}bI|j#+{s^}a)I(CA*kfkuerSX_N4m}9^AekXLt zT8S~&it~86HT%*7DWK3(bn@9F$ppKC>z1Q7X+8Nuu=y`QCb}lD^ek+qe+7eMjpg`mo z(NN&}ZqSZ~KfDnRSl!09)}`XT z3KAQr-Wzsgcp6s*l+P{&Vn<=^b_kWKXwB=L$Kei&wv|rYpR%fB)gMXke=s@78CmZC z?tzY@tD0JGho0Ak=6}kAi4HN=uA7PsDJvg! z){l~;&yh>5CXNu<=PL7WNVlB`Sihjmvwr`QpKE%8-(>6*{P|J*9%VgIiE|+ZH%XXI zNuV*WzL=lHtA>Oq&f>!(g--Z{QbWZ4Y9wre>EYW1K+oW{8%yO-*sFIm&` z>ru+*y62HSv0HbBwv5->NyEu6BATpqPES3dX|zXU$%fQ-ud4JCCS$wtZy`jXYU}S^ z4YQFJrp~;U?KJwe+qc?LXC_=^Zqb<$%T(U`vj6pP@A4lWPtSU`(<+zc`+^?f#z^$% z{pm9i5(6$XGpv z`|_Pw=qG`HEfz}h9lMdvqtt86c`>dkNTw(9h`<2egG|Ba&Q$;{FdWJZP}K1Q;K zPjV9uKcw{Gu_?(2Sy4$3Pl5H}+&E5QC|PZCW@r~>aS#`~u;kG|n1LxaikRl4SWn~w%CjiWNZ|JiVF;os-{*eqoR7(oD|&bsk)*5FSv zOHIK^L$Pq~OfP1>&cO5jf#bpA8v3s-dK%6m)2asZZ$w%GD`6_#1-?)eFyqeH-?VK& m_|E$8m;e9I|NYe%ly)SVWeMt;LHO@;7#tf1>+9>bM*Rcqte%(v literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png new file mode 100644 index 0000000000000000000000000000000000000000..6763b66929d395f778bb8fb7bc36772b8869dd3a GIT binary patch literal 24552 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..41279222155db204ff509001afff978525b6a811 GIT binary patch literal 26545 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py new file mode 100644 index 000000000..d188a882c --- /dev/null +++ b/tests/drawing/matplotlib/test_graph.py @@ -0,0 +1,176 @@ +import random +import unittest + + +from igraph import Graph, InternalError, plot, VertexClustering + +# FIXME: find a better way to do this that works for both direct call and module +# import e.g. tox +try: + from .utils import find_image_comparison +except ImportError: + from utils import find_image_comparison + +try: + import matplotlib as mpl + import matplotlib.pyplot as plt +except ImportError: + raise unittest.SkipTest("matplotlib/pyplot not found, skipping tests") + +image_comparison = find_image_comparison() + + +class GraphTestRunner(unittest.TestCase): + @property + def layout_small_ring(self): + coords = [ + [1.015318095035966, 0.03435580194714975], + [0.29010409851547664, 1.0184451153265959], + [-0.8699239050738742, 0.6328259400443561], + [-0.8616466426732888, -0.5895891303732176], + [0.30349699041342515, -0.9594640169691343], + ] + return coords + + @image_comparison(baseline_images=["graph_basic"], remove_text=True) + def test_basic(self): + plt.close("all") + g = Graph.Ring(5) + fig, ax = plt.subplots() + plot(g, target=ax, layout=self.layout_small_ring) + + @image_comparison(baseline_images=["graph_directed"], remove_text=True) + def test_directed(self): + plt.close("all") + g = Graph.Ring(5, directed=True) + fig, ax = plt.subplots() + plot(g, target=ax, layout=self.layout_small_ring) + + @image_comparison(baseline_images=["graph_mark_groups_directed"], remove_text=True) + def test_mark_groups(self): + plt.close("all") + g = Graph.Ring(5, directed=True) + fig, ax = plt.subplots() + plot(g, target=ax, mark_groups=True, layout=self.layout_small_ring) + + @image_comparison( + baseline_images=["graph_mark_groups_squares_directed"], remove_text=True + ) + def test_mark_groups_squares(self): + plt.close("all") + g = Graph.Ring(5, directed=True) + fig, ax = plt.subplots() + plot(g, target=ax, mark_groups=True, vertex_shape="s", + layout=self.layout_small_ring) + + @image_comparison(baseline_images=["graph_edit_children"], remove_text=True) + def test_mark_groups_squares(self): + plt.close("all") + g = Graph.Ring(5) + fig, ax = plt.subplots() + plot(g, target=ax, vertex_shape="o", + layout=self.layout_small_ring) + dot = ax.get_children()[0] + dot.set_facecolor("blue") + dot.radius *= 0.5 + + +class ClusteringTestRunner(unittest.TestCase): + @property + def layout_small_ring(self): + coords = [ + [1.015318095035966, 0.03435580194714975], + [0.29010409851547664, 1.0184451153265959], + [-0.8699239050738742, 0.6328259400443561], + [-0.8616466426732888, -0.5895891303732176], + [0.30349699041342515, -0.9594640169691343], + ] + return coords + + @property + def layout_large_ring(self): + coords = [ + (2.5, 0.0), + (2.4802867532861947, 0.31333308391076065), + (2.4214579028215777, 0.621724717912137), + (2.324441214720628, 0.9203113817116949), + (2.190766700109659, 1.2043841852542883), + (2.0225424859373686, 1.469463130731183), + (1.822421568553529, 1.7113677648217218), + (1.5935599743717241, 1.926283106939473), + (1.3395669874474914, 2.110819813755038), + (1.0644482289126818, 2.262067631165049), + (0.7725424859373686, 2.3776412907378837), + (0.4684532864643113, 2.4557181268217216), + (0.15697629882328326, 2.495066821070679), + (-0.1569762988232835, 2.495066821070679), + (-0.46845328646431206, 2.4557181268217216), + (-0.7725424859373689, 2.3776412907378837), + (-1.0644482289126818, 2.2620676311650487), + (-1.3395669874474923, 2.1108198137550374), + (-1.5935599743717244, 1.926283106939473), + (-1.8224215685535292, 1.7113677648217211), + (-2.022542485937368, 1.4694631307311832), + (-2.190766700109659, 1.204384185254288), + (-2.3244412147206286, 0.9203113817116944), + (-2.4214579028215777, 0.621724717912137), + (-2.4802867532861947, 0.3133330839107602), + (-2.5, -8.040613248383183e-16), + (-2.4802867532861947, -0.3133330839107607), + (-2.4214579028215777, -0.6217247179121376), + (-2.324441214720628, -0.9203113817116958), + (-2.1907667001096587, -1.2043841852542885), + (-2.022542485937368, -1.4694631307311834), + (-1.822421568553529, -1.7113677648217218), + (-1.5935599743717237, -1.9262831069394735), + (-1.339566987447491, -2.1108198137550382), + (-1.0644482289126804, -2.2620676311650496), + (-0.7725424859373689, -2.3776412907378837), + (-0.46845328646431156, -2.4557181268217216), + (-0.156976298823283, -2.495066821070679), + (0.1569762988232843, -2.495066821070679), + (0.46845328646431283, -2.4557181268217216), + (0.7725424859373681, -2.377641290737884), + (1.0644482289126815, -2.262067631165049), + (1.3395669874474918, -2.1108198137550374), + (1.593559974371725, -1.9262831069394726), + (1.8224215685535297, -1.7113677648217207), + (2.0225424859373695, -1.4694631307311814), + (2.190766700109659, -1.2043841852542883), + (2.3244412147206286, -0.9203113817116947), + (2.421457902821578, -0.6217247179121362), + (2.4802867532861947, -0.3133330839107595), + ] + return coords + + @image_comparison(baseline_images=["clustering_directed"], remove_text=True) + def test_clustering_directed_small(self): + plt.close("all") + g = Graph.Ring(5, directed=True) + clu = VertexClustering(g, [0] * 5) + fig, ax = plt.subplots() + plot(clu, target=ax, mark_groups=True, + layout=self.layout_small_ring) + + @image_comparison(baseline_images=["clustering_directed_large"], remove_text=True) + def test_clustering_directed_large(self): + plt.close("all") + g = Graph.Ring(50, directed=True) + clu = VertexClustering(g, [0] * 3 + [1] * 17 + [2] * 30) + fig, ax = plt.subplots() + plot(clu, layout=self.layout_large_ring, target=ax, mark_groups=True) + + +def suite(): + graph = unittest.makeSuite(GraphTestRunner) + clustering = unittest.makeSuite(ClusteringTestRunner) + return unittest.TestSuite([graph, clustering]) + + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + + +if __name__ == "__main__": + test() diff --git a/tests/drawing/matplotlib/utils.py b/tests/drawing/matplotlib/utils.py new file mode 100644 index 000000000..c9872a2fd --- /dev/null +++ b/tests/drawing/matplotlib/utils.py @@ -0,0 +1,122 @@ +# Functions adapted from matplotlib.testing. Credit for the original functions +# goes to the amazing folks over at matplotlib. +from pathlib import Path +import sys +import inspect +import functools + +try: + import matplotlib + from matplotlib.testing.decorators import _ImageComparisonBase + from matplotlib.testing.compare import comparable_formats + import matplotlib.pyplot as plt +except ImportError: + matplotlib = None + +__all__ = ("find_image_comparison",) + + +def find_image_comparison(): + def dummy_comparison(*args, **kwargs): + return lambda *args, **kwargs: None + + if matplotlib is None: + return dummy_comparison + return image_comparison + + +# NOTE: Parametrizing this requires pytest (see matplotlib's test suite) +_default_extension = "png" + + +def _unittest_image_comparison( + baseline_images, tol, remove_text, savefig_kwargs, style +): + """ + Decorate function with image comparison for unittest. + This function creates a decorator that wraps a figure-generating function + with image comparison code. + """ + import unittest + + def decorator(func): + old_sig = inspect.signature(func) + + @functools.wraps(func) + @matplotlib.style.context(style) + @functools.wraps(func) + def wrapper(*args, **kwargs): + __tracebackhide__ = True + + img = _ImageComparisonBase( + func, tol=tol, remove_text=remove_text, savefig_kwargs=savefig_kwargs + ) + matplotlib.testing.set_font_settings_for_testing() + + func(*args, **kwargs) + + assert len(plt.get_fignums()) == len( + baseline_images + ), "Test generated {} images but there are {} baseline images".format( + len(plt.get_fignums()), len(baseline_images) + ) + for idx, baseline in enumerate(baseline_images): + img.compare(idx, baseline, _default_extension, _lock=False) + + parameters = list(old_sig.parameters.values()) + new_sig = old_sig.replace(parameters=parameters) + wrapper.__signature__ = new_sig + + return wrapper + + return decorator + + +def image_comparison( + baseline_images, + tol=0.01, + remove_text=False, + savefig_kwarg=None, + # Default of mpl_test_settings fixture and cleanup too. + style=("classic", "_classic_test_patch"), +): + """ + Compare images generated by the test with those specified in + *baseline_images*, which must correspond, else an `ImageComparisonFailure` + exception will be raised. + Parameters + ---------- + baseline_images : list or None + A list of strings specifying the names of the images generated by + calls to `.Figure.savefig`. + If *None*, the test function must use the ``baseline_images`` fixture, + either as a parameter or with `pytest.mark.usefixtures`. This value is + only allowed when using pytest. + tol : float, default: 0 + The RMS threshold above which the test is considered failed. + Due to expected small differences in floating-point calculations, on + 32-bit systems an additional 0.06 is added to this threshold. + remove_text : bool + Remove the title and tick text from the figure before comparison. This + is useful to make the baseline images independent of variations in text + rendering between different versions of FreeType. + This does not remove other, more deliberate, text, such as legends and + annotations. + savefig_kwarg : dict + Optional arguments that are passed to the savefig method. + style : str, dict, or list + The optional style(s) to apply to the image test. The test itself + can also apply additional styles if desired. Defaults to ``["classic", + "_classic_test_patch"]``. + """ + if savefig_kwarg is None: + savefig_kwarg = dict() # default no kwargs to savefig + if sys.maxsize <= 2 ** 32: + tol += 0.06 + return _unittest_image_comparison( + baseline_images=baseline_images, + tol=tol, + remove_text=remove_text, + savefig_kwargs=savefig_kwarg, + style=style, + ) diff --git a/tests/drawing/plotly/__init__.py b/tests/drawing/plotly/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/drawing/plotly/baseline_images/clustering_directed.json b/tests/drawing/plotly/baseline_images/clustering_directed.json new file mode 100644 index 000000000..db9b712ef --- /dev/null +++ b/tests/drawing/plotly/baseline_images/clustering_directed.json @@ -0,0 +1,1056 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.29010409851547664, + 0.1950972580065446, + 0.1950972580065446, + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959, + 1.0631519409409285, + 0.9737382897122633, + 1.0184451153265959 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8699239050738742, + -0.9649307455828062, + -0.9649307455828062, + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561, + 0.6775327656586887, + 0.5881191144300235, + 0.6328259400443561 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8616466426732888, + -0.9566534831822209, + -0.9566534831822209, + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176, + -0.544882304758885, + -0.6342959559875502, + -0.5895891303732176 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.30349699041342515, + 0.2084901499044931, + 0.2084901499044931, + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343, + -0.9147571913548017, + -1.004170842583467, + -0.9594640169691343 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.015318095035966, + 0.9203112545270339, + 0.9203112545270339, + 1.015318095035966 + ], + "y": [ + 0.03435580194714975, + 0.07906262756148238, + -0.010351023667182872, + 0.03435580194714975 + ] + } + ], + "layout": { + "shapes": [ + { + "fillcolor": "rgba(255,0,0,63)", + "line": { + "color": "rgba(255,0,0,255)" + }, + "path": "M 1.1197388996537003,-0.16719602520017673L 0.5279328528097523,-0.9934550030368812C 0.45514612062341064,-1.0950773018577296 0.26321850173201045,-1.1588783220760186 0.14407761502695185,-1.1210570434734595L -0.8246194958406551,-0.8135441121460627C -0.9437603825457136,-0.7757228335435037 -1.0637476544979572,-0.6129044204457357 -1.0645940397451423,-0.4879072859505267L -1.0714757322212005,0.5284051354266215C -1.0723221174683857,0.6534022699218305 -0.9545507108608489,0.8178306034288613 -0.8359329190061271,0.8572618024406833L 0.12851107201115136,1.1778644907130693C 0.2471288638658731,1.2172956897248912 0.4399028680044583,1.1560995754479715 0.5140590802883218,1.0554722621592298L 1.1169999394586567,0.23730319901900315C 1.1911561517425202,0.13667588573026146 1.1925256318400421,-0.06557372637932848 1.1197388996537003,-0.16719602520017673 Z", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.1950972580065446,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.9649307455828062,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.9566534831822209,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.2084901499044931,-0.9594640169691344", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.30349699041342515,-0.9594640169691343 L 0.9203112545270339,0.03435580194714975", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/baseline_images/clustering_directed_large.json b/tests/drawing/plotly/baseline_images/clustering_directed_large.json new file mode 100644 index 000000000..8f525f7de --- /dev/null +++ b/tests/drawing/plotly/baseline_images/clustering_directed_large.json @@ -0,0 +1,2991 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.5 + ], + "y": [ + 0 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.4802867532861947 + ], + "y": [ + 0.31333308391076065 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.4214579028215777 + ], + "y": [ + 0.621724717912137 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.324441214720628 + ], + "y": [ + 0.9203113817116949 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.190766700109659 + ], + "y": [ + 1.2043841852542883 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.0225424859373686 + ], + "y": [ + 1.469463130731183 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.822421568553529 + ], + "y": [ + 1.7113677648217218 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.5935599743717241 + ], + "y": [ + 1.926283106939473 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.3395669874474914 + ], + "y": [ + 2.110819813755038 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.0644482289126818 + ], + "y": [ + 2.262067631165049 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.7725424859373686 + ], + "y": [ + 2.3776412907378837 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.4684532864643113 + ], + "y": [ + 2.4557181268217216 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.15697629882328326 + ], + "y": [ + 2.495066821070679 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.1569762988232835 + ], + "y": [ + 2.495066821070679 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.46845328646431206 + ], + "y": [ + 2.4557181268217216 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.7725424859373689 + ], + "y": [ + 2.3776412907378837 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.0644482289126818 + ], + "y": [ + 2.2620676311650487 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.3395669874474923 + ], + "y": [ + 2.1108198137550374 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.5935599743717244 + ], + "y": [ + 1.926283106939473 + ] + }, + { + "marker": { + "color": "rgba(0,255,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.8224215685535292 + ], + "y": [ + 1.7113677648217211 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.022542485937368 + ], + "y": [ + 1.4694631307311832 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.190766700109659 + ], + "y": [ + 1.204384185254288 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.3244412147206286 + ], + "y": [ + 0.9203113817116944 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.4214579028215777 + ], + "y": [ + 0.621724717912137 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.4802867532861947 + ], + "y": [ + 0.3133330839107602 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.5 + ], + "y": [ + -8.040613248383183e-16 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.4802867532861947 + ], + "y": [ + -0.3133330839107607 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.4214579028215777 + ], + "y": [ + -0.6217247179121376 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.324441214720628 + ], + "y": [ + -0.9203113817116958 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.1907667001096587 + ], + "y": [ + -1.2043841852542885 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -2.022542485937368 + ], + "y": [ + -1.4694631307311834 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.822421568553529 + ], + "y": [ + -1.7113677648217218 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.5935599743717237 + ], + "y": [ + -1.9262831069394735 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.339566987447491 + ], + "y": [ + -2.1108198137550382 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -1.0644482289126804 + ], + "y": [ + -2.2620676311650496 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.7725424859373689 + ], + "y": [ + -2.3776412907378837 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.46845328646431156 + ], + "y": [ + -2.4557181268217216 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.156976298823283 + ], + "y": [ + -2.495066821070679 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.1569762988232843 + ], + "y": [ + -2.495066821070679 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.46845328646431283 + ], + "y": [ + -2.4557181268217216 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.7725424859373681 + ], + "y": [ + -2.377641290737884 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.0644482289126815 + ], + "y": [ + -2.262067631165049 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.3395669874474918 + ], + "y": [ + -2.1108198137550374 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.593559974371725 + ], + "y": [ + -1.9262831069394726 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.8224215685535297 + ], + "y": [ + -1.7113677648217207 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.0225424859373695 + ], + "y": [ + -1.4694631307311814 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.190766700109659 + ], + "y": [ + -1.2043841852542883 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.3244412147206286 + ], + "y": [ + -0.9203113817116947 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.421457902821578 + ], + "y": [ + -0.6217247179121362 + ] + }, + { + "marker": { + "color": "rgba(0,0,255,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 2.4802867532861947 + ], + "y": [ + -0.3133330839107595 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.4802867532861947, + 2.385279912777263, + 2.385279912777263, + 2.4802867532861947 + ], + "y": [ + 0.31333308391076065, + 0.3580399095250933, + 0.268626258296428, + 0.31333308391076065 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.4214579028215777, + 2.3264510623126458, + 2.3264510623126458, + 2.4214579028215777 + ], + "y": [ + 0.621724717912137, + 0.6664315435264696, + 0.5770178922978044, + 0.621724717912137 + ] + }, + { + "fillcolor": "rgb(204,204,204)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.324441214720628, + 2.229434374211696, + 2.229434374211696, + 2.324441214720628 + ], + "y": [ + 0.9203113817116949, + 0.9650182073260275, + 0.8756045560973623, + 0.9203113817116949 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.190766700109659, + 2.095759859600727, + 2.095759859600727, + 2.190766700109659 + ], + "y": [ + 1.2043841852542883, + 1.2490910108686208, + 1.1596773596399557, + 1.2043841852542883 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.0225424859373686, + 1.9275356454284365, + 1.9275356454284365, + 2.0225424859373686 + ], + "y": [ + 1.469463130731183, + 1.5141699563455155, + 1.4247563051168504, + 1.469463130731183 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.822421568553529, + 1.7274147280445968, + 1.7274147280445968, + 1.822421568553529 + ], + "y": [ + 1.7113677648217218, + 1.7560745904360544, + 1.6666609392073892, + 1.7113677648217218 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.5935599743717241, + 1.498553133862792, + 1.498553133862792, + 1.5935599743717241 + ], + "y": [ + 1.926283106939473, + 1.9709899325538056, + 1.8815762813251404, + 1.926283106939473 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.3395669874474914, + 1.2445601469385592, + 1.2445601469385592, + 1.3395669874474914 + ], + "y": [ + 2.110819813755038, + 2.1555266393693704, + 2.066112988140705, + 2.110819813755038 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.0644482289126818, + 0.9694413884037497, + 0.9694413884037497, + 1.0644482289126818 + ], + "y": [ + 2.262067631165049, + 2.3067744567793818, + 2.2173608055507166, + 2.262067631165049 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.7725424859373686, + 0.6775356454284366, + 0.6775356454284366, + 0.7725424859373686 + ], + "y": [ + 2.3776412907378837, + 2.4223481163522163, + 2.332934465123551, + 2.3776412907378837 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.4684532864643113, + 0.37344644595537924, + 0.37344644595537924, + 0.4684532864643113 + ], + "y": [ + 2.4557181268217216, + 2.5004249524360542, + 2.411011301207389, + 2.4557181268217216 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.15697629882328326, + 0.0619694583143512, + 0.0619694583143512, + 0.15697629882328326 + ], + "y": [ + 2.495066821070679, + 2.5397736466850116, + 2.4503599954563464, + 2.495066821070679 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.1569762988232835, + -0.25198313933221556, + -0.25198313933221556, + -0.1569762988232835 + ], + "y": [ + 2.495066821070679, + 2.5397736466850116, + 2.4503599954563464, + 2.495066821070679 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.46845328646431206, + -0.5634601269732441, + -0.5634601269732441, + -0.46845328646431206 + ], + "y": [ + 2.4557181268217216, + 2.5004249524360542, + 2.411011301207389, + 2.4557181268217216 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.7725424859373689, + -0.8675493264463009, + -0.8675493264463009, + -0.7725424859373689 + ], + "y": [ + 2.3776412907378837, + 2.4223481163522163, + 2.332934465123551, + 2.3776412907378837 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.0644482289126818, + -1.159455069421614, + -1.159455069421614, + -1.0644482289126818 + ], + "y": [ + 2.2620676311650487, + 2.3067744567793813, + 2.217360805550716, + 2.2620676311650487 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.3395669874474923, + -1.4345738279564244, + -1.4345738279564244, + -1.3395669874474923 + ], + "y": [ + 2.1108198137550374, + 2.15552663936937, + 2.0661129881407048, + 2.1108198137550374 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.5935599743717244, + -1.6885668148806565, + -1.6885668148806565, + -1.5935599743717244 + ], + "y": [ + 1.926283106939473, + 1.9709899325538056, + 1.8815762813251404, + 1.926283106939473 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.8224215685535292, + -1.9174284090624614, + -1.9174284090624614, + -1.8224215685535292 + ], + "y": [ + 1.7113677648217211, + 1.7560745904360537, + 1.6666609392073886, + 1.7113677648217211 + ] + }, + { + "fillcolor": "rgb(204,204,204)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.022542485937368, + -2.1175493264463, + -2.1175493264463, + -2.022542485937368 + ], + "y": [ + 1.4694631307311832, + 1.5141699563455158, + 1.4247563051168506, + 1.4694631307311832 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.190766700109659, + -2.285773540618591, + -2.285773540618591, + -2.190766700109659 + ], + "y": [ + 1.204384185254288, + 1.2490910108686206, + 1.1596773596399554, + 1.204384185254288 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.3244412147206286, + -2.4194480552295605, + -2.4194480552295605, + -2.3244412147206286 + ], + "y": [ + 0.9203113817116944, + 0.9650182073260269, + 0.8756045560973618, + 0.9203113817116944 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.4214579028215777, + -2.5164647433305096, + -2.5164647433305096, + -2.4214579028215777 + ], + "y": [ + 0.621724717912137, + 0.6664315435264696, + 0.5770178922978044, + 0.621724717912137 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.4802867532861947, + -2.5752935937951267, + -2.5752935937951267, + -2.4802867532861947 + ], + "y": [ + 0.3133330839107602, + 0.35803990952509285, + 0.26862625829642756, + 0.3133330839107602 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.5, + -2.595006840508932, + -2.595006840508932, + -2.5 + ], + "y": [ + -8.040613248383183e-16, + 0.04470682561433182, + -0.04470682561433343, + -8.040613248383183e-16 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.4802867532861947, + -2.5752935937951267, + -2.5752935937951267, + -2.4802867532861947 + ], + "y": [ + -0.3133330839107607, + -0.26862625829642806, + -0.35803990952509335, + -0.3133330839107607 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.4214579028215777, + -2.5164647433305096, + -2.5164647433305096, + -2.4214579028215777 + ], + "y": [ + -0.6217247179121376, + -0.577017892297805, + -0.6664315435264702, + -0.6217247179121376 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.324441214720628, + -2.41944805522956, + -2.41944805522956, + -2.324441214720628 + ], + "y": [ + -0.9203113817116958, + -0.8756045560973632, + -0.9650182073260284, + -0.9203113817116958 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.1907667001096587, + -2.2857735406185906, + -2.2857735406185906, + -2.1907667001096587 + ], + "y": [ + -1.2043841852542885, + -1.1596773596399559, + -1.249091010868621, + -1.2043841852542885 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -2.022542485937368, + -2.1175493264463, + -2.1175493264463, + -2.022542485937368 + ], + "y": [ + -1.4694631307311834, + -1.4247563051168508, + -1.514169956345516, + -1.4694631307311834 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.822421568553529, + -1.9174284090624611, + -1.9174284090624611, + -1.822421568553529 + ], + "y": [ + -1.7113677648217218, + -1.6666609392073892, + -1.7560745904360544, + -1.7113677648217218 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.5935599743717237, + -1.6885668148806559, + -1.6885668148806559, + -1.5935599743717237 + ], + "y": [ + -1.9262831069394735, + -1.8815762813251409, + -1.970989932553806, + -1.9262831069394735 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.339566987447491, + -1.434573827956423, + -1.434573827956423, + -1.339566987447491 + ], + "y": [ + -2.1108198137550382, + -2.0661129881407057, + -2.155526639369371, + -2.1108198137550382 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -1.0644482289126804, + -1.1594550694216126, + -1.1594550694216126, + -1.0644482289126804 + ], + "y": [ + -2.2620676311650496, + -2.217360805550717, + -2.306774456779382, + -2.2620676311650496 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.7725424859373689, + -0.8675493264463009, + -0.8675493264463009, + -0.7725424859373689 + ], + "y": [ + -2.3776412907378837, + -2.332934465123551, + -2.4223481163522163, + -2.3776412907378837 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.46845328646431156, + -0.5634601269732437, + -0.5634601269732437, + -0.46845328646431156 + ], + "y": [ + -2.4557181268217216, + -2.411011301207389, + -2.5004249524360542, + -2.4557181268217216 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + -0.156976298823283, + -0.25198313933221506, + -0.25198313933221506, + -0.156976298823283 + ], + "y": [ + -2.495066821070679, + -2.4503599954563464, + -2.5397736466850116, + -2.495066821070679 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.1569762988232843, + 0.06196945831435223, + 0.06196945831435223, + 0.1569762988232843 + ], + "y": [ + -2.495066821070679, + -2.4503599954563464, + -2.5397736466850116, + -2.495066821070679 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.46845328646431283, + 0.3734464459553808, + 0.3734464459553808, + 0.46845328646431283 + ], + "y": [ + -2.4557181268217216, + -2.411011301207389, + -2.5004249524360542, + -2.4557181268217216 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 0.7725424859373681, + 0.677535645428436, + 0.677535645428436, + 0.7725424859373681 + ], + "y": [ + -2.377641290737884, + -2.3329344651235515, + -2.4223481163522167, + -2.377641290737884 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.0644482289126815, + 0.9694413884037495, + 0.9694413884037495, + 1.0644482289126815 + ], + "y": [ + -2.262067631165049, + -2.2173608055507166, + -2.3067744567793818, + -2.262067631165049 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.3395669874474918, + 1.2445601469385597, + 1.2445601469385597, + 1.3395669874474918 + ], + "y": [ + -2.1108198137550374, + -2.0661129881407048, + -2.15552663936937, + -2.1108198137550374 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.593559974371725, + 1.4985531338627929, + 1.4985531338627929, + 1.593559974371725 + ], + "y": [ + -1.9262831069394726, + -1.88157628132514, + -1.9709899325538052, + -1.9262831069394726 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 1.8224215685535297, + 1.7274147280445975, + 1.7274147280445975, + 1.8224215685535297 + ], + "y": [ + -1.7113677648217207, + -1.6666609392073881, + -1.7560745904360533, + -1.7113677648217207 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.0225424859373695, + 1.9275356454284374, + 1.9275356454284374, + 2.0225424859373695 + ], + "y": [ + -1.4694631307311814, + -1.4247563051168488, + -1.514169956345514, + -1.4694631307311814 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.190766700109659, + 2.095759859600727, + 2.095759859600727, + 2.190766700109659 + ], + "y": [ + -1.2043841852542883, + -1.1596773596399557, + -1.2490910108686208, + -1.2043841852542883 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.3244412147206286, + 2.2294343742116967, + 2.2294343742116967, + 2.3244412147206286 + ], + "y": [ + -0.9203113817116947, + -0.8756045560973621, + -0.9650182073260273, + -0.9203113817116947 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.421457902821578, + 2.326451062312646, + 2.326451062312646, + 2.421457902821578 + ], + "y": [ + -0.6217247179121362, + -0.5770178922978036, + -0.6664315435264688, + -0.6217247179121362 + ] + }, + { + "fillcolor": "rgb(51,51,51)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.4802867532861947, + 2.385279912777263, + 2.385279912777263, + 2.4802867532861947 + ], + "y": [ + -0.3133330839107595, + -0.26862625829642683, + -0.3580399095250921, + -0.3133330839107595 + ] + }, + { + "fillcolor": "rgb(204,204,204)", + "mode": "lines", + "type": "scatter", + "x": [ + 2.5, + 2.404993159491068, + 2.404993159491068, + 2.5 + ], + "y": [ + 0, + 0.044706825614332625, + -0.044706825614332625, + 0 + ] + } + ], + "layout": { + "shapes": [ + { + "fillcolor": "rgba(0,0,255,63)", + "line": { + "color": "rgba(0,0,255,255)" + }, + "path": "M 0.08467188267459153,-2.7297732924988862L 0.08155152177765243,-2.7299214387141904C -0.009367696129893549,-2.7342380349273507 -0.1909500767190293,-2.7304844316164045 -0.28161323940061905,-2.722414232092298L -0.2847409075439839,-2.722135828987712C -0.3769679042972561,-2.7139264279113124 -0.5593295859951877,-2.684528544914581 -0.6494642709398472,-2.6633400629942487L -0.6518360308590739,-2.6627825196667407C -0.7431565957633468,-2.641315266082655 -0.921699356285265,-2.5853143022647096 -1.0089215519029104,-2.55078059203085L -1.0106573132672392,-2.550093355490123C -1.0978795088848847,-2.5155596452562636 -1.266366877669369,-2.4341616609851098 -1.347632050836208,-2.3872973869478153L -1.3497426540803754,-2.386080237153332C -1.4299525256251309,-2.339824538013279 -1.5830127061525752,-2.236419510991894 -1.6558630151352642,-2.1792701831105616L -1.6583335671282884,-2.1773320940637357C -1.729948600114465,-2.1211518107058165 -1.8648859771397523,-1.999586376639347 -1.9282083211788628,-1.9342012259307966L -1.9303815533160236,-1.9319571979661154C -1.9926172812865535,-1.8676940612399058 -2.1081776870619855,-1.731601158295806 -2.161502364866888,-1.659771392077916L -2.1631196779521384,-1.6575928281259733C -2.215635699214415,-1.5868523438840547 -2.311295509855163,-1.4392954418783066 -2.3544392992336345,-1.3624790241144775L -2.3555105624439965,-1.3605716672622477C -2.398118720217287,-1.2847089279245334 -2.473583896959723,-1.1282792807827042 -2.506440915928869,-1.047712372978589L -2.5070810151735397,-1.0461428204613852C -2.5396179845203504,-0.9663606889158721 -2.5946343855076077,-0.8034009279178234 -2.6171138171480544,-0.7202232984652875L -2.61744961335299,-0.7189807967529462C -2.6397611468909687,-0.6364244181565811 -2.674109931734575,-0.46920125293896836 -2.686147183040202,-0.3845344663177207L -2.6862833838572926,-0.3835764664201169C -2.698252534754375,-0.2993886797476711 -2.711810564600415,-0.1301813690722769 -2.7133994435493722,-0.045161845069328466L -2.713412967029626,-0.04443821545942635C -2.7149950842384567,0.04021949373857103 -2.7078003322721127,0.20909357538870527 -2.699023463096938,0.29330994784084213L -2.698967550250878,0.2938464463318956C -2.690218637498733,0.3777945695385057 -2.662520663182241,0.5439908777104231 -2.643571601617894,0.6262390626757304L -2.643481710215066,0.6266292352814542C -2.6245775943521323,0.7086823339438996 -2.5768702239744856,0.8698584325875697 -2.548066969459773,0.9489814325687944L -2.5479658817830115,0.94925912203067C -2.519213171106679,1.0282432772809569 -2.452251751203909,1.1820960487271361 -2.414043041977471,1.2569646649230286L -2.413944710679318,1.2571573416286943C -2.3757851671019568,1.331929619471754 -2.2905915065957196,1.4762348833329115 -2.2435573896668433,1.5457678693510093L -2.2435573896668433,1.5457678693510093C -2.196523272737967,1.615300855369107 -2.0714375110137118,1.6539310090799837 -1.993385866218333,1.6230281767727623L 2.564155000068931,-0.18142990343059492C 2.6422066448643093,-0.2123327357378162 2.70694608097404,-0.3261200020467362 2.693633872288393,-0.40900443604843495L 2.693633872288393,-0.40900443604843495C 2.680321663602745,-0.4918888700501337 2.6436414186205517,-0.655401953919702 2.620273382324006,-0.7360306037875716L 2.6202131664742097,-0.7362383714668104C 2.5968150222527657,-0.8169709051742993 2.540308327176887,-0.9749629950037181 2.507199776322452,-1.052222551125648L 2.5070833745499557,-1.0524941773080927C 2.4739166228092726,-1.1298895465212448 2.398361167239949,-1.2800398082461453 2.355972463411309,-1.3527947007578938L 2.355770899895785,-1.353140659246398C 2.313281414309383,-1.4260685310023984 2.219703166854112,-1.5661809938114277 2.168614404985243,-1.6333655848644568L 2.168287905206504,-1.6337949504100493C 2.1170358934482656,-1.7011942242358744 2.0066783780538446,-1.8292232783798599 1.947572874417662,-1.88985305869802L 1.9470676576696004,-1.8903713045222426C 1.887709545659387,-1.951260207752514 1.7619957924271628,-2.0653259186720234 1.695640151205152,-2.1185027263612617L 1.6948850690250796,-2.1191078423565233C 1.628151886713033,-2.172587208043392 1.488640566378044,-2.270974288008281 1.4158624283551022,-2.3158820022863016L 1.414767092505202,-2.3165578787338457C 1.34144128655731,-2.361803531235638 1.189782423469918,-2.442934766460868 1.111449366330418,-2.4788203491843053L 1.1099083214293617,-2.479526325642991C 1.0308047418393333,-2.5157648965957717 0.8687095332988997,-2.578137733423335 0.7857179043484942,-2.6042719992981183L 0.783631311463264,-2.6049290724743495C 0.6995963860702434,-2.631391874937248 0.5288537349802286,-2.673472580731123 0.44214600928323433,-2.6890904840620995L 0.43947570913498357,-2.6895714618440083C 0.351432833363864,-2.705429854065939 0.17403092013366794,-2.725530769393378 0.08467188267459153,-2.7297732924988862 Z", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.5,0.0 L 2.385279912777263,0.31333308391076065", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.4802867532861947,0.31333308391076065 L 2.3264510623126458,0.621724717912137", + "type": "path" + }, + { + "line": { + "color": "rgb(204,204,204)", + "width": 2 + }, + "path": "M 2.4214579028215777,0.621724717912137 L 2.229434374211696,0.9203113817116949", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.324441214720628,0.9203113817116949 L 2.095759859600727,1.2043841852542883", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.190766700109659,1.2043841852542883 L 1.9275356454284365,1.469463130731183", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.0225424859373686,1.469463130731183 L 1.7274147280445968,1.7113677648217218", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.822421568553529,1.7113677648217218 L 1.498553133862792,1.926283106939473", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.5935599743717241,1.926283106939473 L 1.2445601469385592,2.110819813755038", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.3395669874474914,2.110819813755038 L 0.9694413884037497,2.262067631165049", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.0644482289126818,2.262067631165049 L 0.6775356454284366,2.3776412907378837", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.7725424859373686,2.3776412907378837 L 0.37344644595537924,2.4557181268217216", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.4684532864643113,2.4557181268217216 L 0.0619694583143512,2.495066821070679", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.15697629882328326,2.495066821070679 L -0.25198313933221556,2.495066821070679", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.1569762988232835,2.495066821070679 L -0.5634601269732441,2.4557181268217216", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.46845328646431206,2.4557181268217216 L -0.8675493264463009,2.3776412907378837", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.7725424859373689,2.3776412907378837 L -1.159455069421614,2.2620676311650487", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.0644482289126818,2.2620676311650487 L -1.4345738279564244,2.1108198137550374", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.3395669874474923,2.1108198137550374 L -1.6885668148806565,1.926283106939473", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.5935599743717244,1.926283106939473 L -1.9174284090624614,1.7113677648217211", + "type": "path" + }, + { + "line": { + "color": "rgb(204,204,204)", + "width": 2 + }, + "path": "M -1.8224215685535292,1.7113677648217211 L -2.1175493264463,1.4694631307311832", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.022542485937368,1.4694631307311832 L -2.285773540618591,1.204384185254288", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.190766700109659,1.204384185254288 L -2.4194480552295605,0.9203113817116944", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.3244412147206286,0.9203113817116944 L -2.5164647433305096,0.621724717912137", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.4214579028215777,0.621724717912137 L -2.5752935937951267,0.3133330839107602", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.4802867532861947,0.3133330839107602 L -2.595006840508932,-8.049116928532385e-16", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.5,-8.040613248383183e-16 L -2.5752935937951267,-0.3133330839107607", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.4802867532861947,-0.3133330839107607 L -2.5164647433305096,-0.6217247179121376", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.4214579028215777,-0.6217247179121376 L -2.41944805522956,-0.9203113817116958", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.324441214720628,-0.9203113817116958 L -2.2857735406185906,-1.2043841852542885", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.1907667001096587,-1.2043841852542885 L -2.1175493264463,-1.4694631307311834", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -2.022542485937368,-1.4694631307311834 L -1.9174284090624611,-1.7113677648217218", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.822421568553529,-1.7113677648217218 L -1.6885668148806559,-1.9262831069394735", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.5935599743717237,-1.9262831069394735 L -1.434573827956423,-2.1108198137550382", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.339566987447491,-2.1108198137550382 L -1.1594550694216126,-2.2620676311650496", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -1.0644482289126804,-2.2620676311650496 L -0.8675493264463009,-2.3776412907378837", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.7725424859373689,-2.3776412907378837 L -0.5634601269732437,-2.4557181268217216", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.46845328646431156,-2.4557181268217216 L -0.25198313933221506,-2.495066821070679", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M -0.156976298823283,-2.495066821070679 L 0.06196945831435223,-2.495066821070679", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.1569762988232843,-2.495066821070679 L 0.3734464459553808,-2.4557181268217216", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.46845328646431283,-2.4557181268217216 L 0.677535645428436,-2.377641290737884", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 0.7725424859373681,-2.377641290737884 L 0.9694413884037495,-2.262067631165049", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.0644482289126815,-2.262067631165049 L 1.2445601469385597,-2.1108198137550374", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.3395669874474918,-2.1108198137550374 L 1.4985531338627929,-1.9262831069394726", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.593559974371725,-1.9262831069394726 L 1.7274147280445975,-1.7113677648217207", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 1.8224215685535297,-1.7113677648217207 L 1.9275356454284374,-1.4694631307311814", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.0225424859373695,-1.4694631307311814 L 2.095759859600727,-1.2043841852542883", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.190766700109659,-1.2043841852542883 L 2.2294343742116967,-0.9203113817116947", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.3244412147206286,-0.9203113817116947 L 2.326451062312646,-0.6217247179121362", + "type": "path" + }, + { + "line": { + "color": "rgb(51,51,51)", + "width": 2 + }, + "path": "M 2.421457902821578,-0.6217247179121362 L 2.385279912777263,-0.3133330839107595", + "type": "path" + }, + { + "line": { + "color": "rgb(204,204,204)", + "width": 2 + }, + "path": "M 2.4802867532861947,-0.3133330839107595 L 2.404993159491068,0.0", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/baseline_images/graph_basic.json b/tests/drawing/plotly/baseline_images/graph_basic.json new file mode 100644 index 000000000..48df85504 --- /dev/null +++ b/tests/drawing/plotly/baseline_images/graph_basic.json @@ -0,0 +1,963 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + } + ], + "layout": { + "shapes": [ + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.29010409851547664,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.8699239050738742,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.8616466426732888,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.30349699041342515,-0.9594640169691343", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.30349699041342515,-0.9594640169691343", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/baseline_images/graph_directed.json b/tests/drawing/plotly/baseline_images/graph_directed.json new file mode 100644 index 000000000..b30d80114 --- /dev/null +++ b/tests/drawing/plotly/baseline_images/graph_directed.json @@ -0,0 +1,1048 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.29010409851547664, + 0.1950972580065446, + 0.1950972580065446, + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959, + 1.0631519409409285, + 0.9737382897122633, + 1.0184451153265959 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8699239050738742, + -0.9649307455828062, + -0.9649307455828062, + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561, + 0.6775327656586887, + 0.5881191144300235, + 0.6328259400443561 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8616466426732888, + -0.9566534831822209, + -0.9566534831822209, + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176, + -0.544882304758885, + -0.6342959559875502, + -0.5895891303732176 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.30349699041342515, + 0.2084901499044931, + 0.2084901499044931, + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343, + -0.9147571913548017, + -1.004170842583467, + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 1.015318095035966, + 0.9203112545270339, + 0.9203112545270339, + 1.015318095035966 + ], + "y": [ + 0.03435580194714975, + 0.07906262756148238, + -0.010351023667182872, + 0.03435580194714975 + ] + } + ], + "layout": { + "shapes": [ + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.1950972580065446,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.9649307455828062,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.9566534831822209,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.2084901499044931,-0.9594640169691344", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.30349699041342515,-0.9594640169691343 L 0.9203112545270339,0.03435580194714975", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/baseline_images/graph_edit_children.json b/tests/drawing/plotly/baseline_images/graph_edit_children.json new file mode 100644 index 000000000..48df85504 --- /dev/null +++ b/tests/drawing/plotly/baseline_images/graph_edit_children.json @@ -0,0 +1,963 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + } + ], + "layout": { + "shapes": [ + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.29010409851547664,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.8699239050738742,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.8616466426732888,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.30349699041342515,-0.9594640169691343", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.30349699041342515,-0.9594640169691343", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/baseline_images/graph_mark_groups_directed.json b/tests/drawing/plotly/baseline_images/graph_mark_groups_directed.json new file mode 100644 index 000000000..b30d80114 --- /dev/null +++ b/tests/drawing/plotly/baseline_images/graph_mark_groups_directed.json @@ -0,0 +1,1048 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 0.2, + "symbol": "circle" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.29010409851547664, + 0.1950972580065446, + 0.1950972580065446, + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959, + 1.0631519409409285, + 0.9737382897122633, + 1.0184451153265959 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8699239050738742, + -0.9649307455828062, + -0.9649307455828062, + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561, + 0.6775327656586887, + 0.5881191144300235, + 0.6328259400443561 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8616466426732888, + -0.9566534831822209, + -0.9566534831822209, + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176, + -0.544882304758885, + -0.6342959559875502, + -0.5895891303732176 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.30349699041342515, + 0.2084901499044931, + 0.2084901499044931, + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343, + -0.9147571913548017, + -1.004170842583467, + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 1.015318095035966, + 0.9203112545270339, + 0.9203112545270339, + 1.015318095035966 + ], + "y": [ + 0.03435580194714975, + 0.07906262756148238, + -0.010351023667182872, + 0.03435580194714975 + ] + } + ], + "layout": { + "shapes": [ + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.1950972580065446,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.9649307455828062,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.9566534831822209,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.2084901499044931,-0.9594640169691344", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2 + }, + "path": "M 0.30349699041342515,-0.9594640169691343 L 0.9203112545270339,0.03435580194714975", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} diff --git a/tests/drawing/plotly/test_graph.py b/tests/drawing/plotly/test_graph.py new file mode 100644 index 000000000..288ebeb7f --- /dev/null +++ b/tests/drawing/plotly/test_graph.py @@ -0,0 +1,185 @@ +import random +import unittest + + +from igraph import Graph, InternalError, plot, VertexClustering + +# FIXME: find a better way to do this that works for both direct call and module +# import e.g. tox +try: + from .utils import find_image_comparison +except ImportError: + from utils import find_image_comparison + +try: + import plotly +except ImportError: + raise unittest.SkipTest("plotly not found, skipping tests") + +# FIXME: trying to debug this specific import on CI +try: + from plotly import graph_objects as go +except ImportError: + raise ImportError('Cannot import graph_objects, dir(plotly): '+str(dir(plotly))) + +image_comparison = find_image_comparison() + + +class GraphTestRunner(unittest.TestCase): + @property + def layout_small_ring(self): + coords = [ + [1.015318095035966, 0.03435580194714975], + [0.29010409851547664, 1.0184451153265959], + [-0.8699239050738742, 0.6328259400443561], + [-0.8616466426732888, -0.5895891303732176], + [0.30349699041342515, -0.9594640169691343], + ] + return coords + + @image_comparison(baseline_images=["graph_basic"]) + def test_basic(self): + g = Graph.Ring(5) + fig = go.Figure() + plot(g, target=fig, layout=self.layout_small_ring) + return fig + + @image_comparison(baseline_images=["graph_directed"]) + def test_directed(self): + g = Graph.Ring(5, directed=True) + fig = go.Figure() + plot(g, target=fig, layout=self.layout_small_ring) + return fig + + @image_comparison(baseline_images=["graph_mark_groups_directed"]) + def test_mark_groups(self): + g = Graph.Ring(5, directed=True) + fig = go.Figure() + plot(g, target=fig, mark_groups=True, + layout=self.layout_small_ring) + return fig + + @image_comparison( + baseline_images=["graph_mark_groups_squares_directed"] + ) + def test_mark_groups_squares(self): + g = Graph.Ring(5, directed=True) + fig = go.Figure() + plot(g, target=fig, mark_groups=True, vertex_shape="square", + layout=self.layout_small_ring) + return fig + + @image_comparison(baseline_images=["graph_edit_children"]) + def test_mark_groups_squares(self): + g = Graph.Ring(5) + fig = go.Figure() + plot(g, target=fig, vertex_shape="circle", + layout=self.layout_small_ring) + # FIXME + #dot = ax.get_children()[0] + #dot.set_facecolor("blue") + #dot.radius *= 0.5 + return fig + + +class ClusteringTestRunner(unittest.TestCase): + @property + def layout_small_ring(self): + coords = [ + [1.015318095035966, 0.03435580194714975], + [0.29010409851547664, 1.0184451153265959], + [-0.8699239050738742, 0.6328259400443561], + [-0.8616466426732888, -0.5895891303732176], + [0.30349699041342515, -0.9594640169691343], + ] + return coords + + @property + def layout_large_ring(self): + coords = [ + (2.5, 0.0), + (2.4802867532861947, 0.31333308391076065), + (2.4214579028215777, 0.621724717912137), + (2.324441214720628, 0.9203113817116949), + (2.190766700109659, 1.2043841852542883), + (2.0225424859373686, 1.469463130731183), + (1.822421568553529, 1.7113677648217218), + (1.5935599743717241, 1.926283106939473), + (1.3395669874474914, 2.110819813755038), + (1.0644482289126818, 2.262067631165049), + (0.7725424859373686, 2.3776412907378837), + (0.4684532864643113, 2.4557181268217216), + (0.15697629882328326, 2.495066821070679), + (-0.1569762988232835, 2.495066821070679), + (-0.46845328646431206, 2.4557181268217216), + (-0.7725424859373689, 2.3776412907378837), + (-1.0644482289126818, 2.2620676311650487), + (-1.3395669874474923, 2.1108198137550374), + (-1.5935599743717244, 1.926283106939473), + (-1.8224215685535292, 1.7113677648217211), + (-2.022542485937368, 1.4694631307311832), + (-2.190766700109659, 1.204384185254288), + (-2.3244412147206286, 0.9203113817116944), + (-2.4214579028215777, 0.621724717912137), + (-2.4802867532861947, 0.3133330839107602), + (-2.5, -8.040613248383183e-16), + (-2.4802867532861947, -0.3133330839107607), + (-2.4214579028215777, -0.6217247179121376), + (-2.324441214720628, -0.9203113817116958), + (-2.1907667001096587, -1.2043841852542885), + (-2.022542485937368, -1.4694631307311834), + (-1.822421568553529, -1.7113677648217218), + (-1.5935599743717237, -1.9262831069394735), + (-1.339566987447491, -2.1108198137550382), + (-1.0644482289126804, -2.2620676311650496), + (-0.7725424859373689, -2.3776412907378837), + (-0.46845328646431156, -2.4557181268217216), + (-0.156976298823283, -2.495066821070679), + (0.1569762988232843, -2.495066821070679), + (0.46845328646431283, -2.4557181268217216), + (0.7725424859373681, -2.377641290737884), + (1.0644482289126815, -2.262067631165049), + (1.3395669874474918, -2.1108198137550374), + (1.593559974371725, -1.9262831069394726), + (1.8224215685535297, -1.7113677648217207), + (2.0225424859373695, -1.4694631307311814), + (2.190766700109659, -1.2043841852542883), + (2.3244412147206286, -0.9203113817116947), + (2.421457902821578, -0.6217247179121362), + (2.4802867532861947, -0.3133330839107595), + ] + return coords + + @image_comparison(baseline_images=["clustering_directed"]) + def test_clustering_directed_small(self): + g = Graph.Ring(5, directed=True) + clu = VertexClustering(g, [0] * 5) + fig = go.Figure() + plot(clu, target=fig, mark_groups=True, layout=self.layout_small_ring) + return fig + + @image_comparison(baseline_images=["clustering_directed_large"]) + def test_clustering_directed_large(self): + g = Graph.Ring(50, directed=True) + clu = VertexClustering(g, [0] * 3 + [1] * 17 + [2] * 30) + fig = go.Figure() + plot(clu, layout=self.layout_large_ring, target=fig, mark_groups=True) + return fig + + +def suite(): + graph = unittest.makeSuite(GraphTestRunner) + clustering = unittest.makeSuite(ClusteringTestRunner) + return unittest.TestSuite([ + graph, + clustering, + ]) + + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + + +if __name__ == "__main__": + test() diff --git a/tests/drawing/plotly/utils.py b/tests/drawing/plotly/utils.py new file mode 100644 index 000000000..eaf54dca9 --- /dev/null +++ b/tests/drawing/plotly/utils.py @@ -0,0 +1,274 @@ +# Functions adapted from matplotlib.testing. Credit for the original functions +# goes to the amazing folks over at matplotlib. +from pathlib import Path +import os +import sys +import inspect +import functools + +try: + import plotly +except ImportError: + plotly = None + +__all__ = ("find_image_comparison",) + + +def find_image_comparison(): + def dummy_comparison(*args, **kwargs): + return lambda *args, **kwargs: None + + if plotly is None: + return dummy_comparison + return image_comparison + + +def _load_baseline_image(filename, fmt): + import json + + if fmt == "json": + with open(filename, "rt") as handle: + image = json.load(handle) + return image + + raise NotImplementedError(f"Image format {fmt} not implemented yet") + + +def _load_baseline_images(filenames, fmt="json"): + baseline_folder = Path(__file__).parent / "baseline_images" + + images = [] + for fn in filenames: + fn_abs = baseline_folder / f"{fn}.{fmt}" + image = _load_baseline_image(fn_abs, fmt) + images.append(image) + return images + + +def _store_result_image_json(fig, result_fn): + import os + import json + + os.makedirs(result_fn.parent, exist_ok=True) + + # This produces a Python dict that's JSON compatible. We print it to a + # file in a way that is easy to diff and lists properties in a predictable + # order + fig_json = fig.to_dict() + with open(result_fn, "wt") as handle: + json.dump(fig_json, handle, indent=2, sort_keys=True) + + +def _store_result_image(image, filename, fmt="json"): + result_folder = Path("result_images") / 'plotly' + result_fn = result_folder / (filename + f".{fmt}") + + if fmt == "json": + return _store_result_image_json(image, result_fn) + + raise NotImplementedError(f"Image format {fmt} not implemented yet") + + +def _compare_image_json(baseline, fig, tol=0.001): + '''This function compares the two JSON dictionaries within some tolerance''' + def is_coords(path_element): + if ',' not in path_element: + return False + coords = path_element.split(',') + for coord in coords: + try: + float(coord) + except ValueError: + return False + return True + + def same_coords(path_elem1, path_elem2, tol): + coords1 = [float(x) for x in path_elem1.split(',')] + coords2 = [float(x) for x in path_elem2.split(',')] + for coord1, coord2 in zip(coords1, coords2): + if abs(coord1 - coord2) > tol: + return False + return True + + # Fig has two keys, 'data' and 'layout' + figd = fig.to_dict() + # 'data' has a list of dots and lines. The order is required to match + if len(baseline['data']) != len(figd['data']): + return False + for stroke1, stroke2 in zip(baseline['data'], figd['data']): + # Some properties are strings, no tolerance + for prop in ['fillcolor', 'mode', 'type']: + if (prop in stroke1) != (prop in stroke2): + return False + if prop not in stroke1: + continue + if stroke1[prop] != stroke2[prop]: + return False + + # Other properties are numeric, recast as float and use tolerance + for prop in ['x', 'y']: + if (prop in stroke1) != (prop in stroke2): + return False + if prop not in stroke1: + continue + if len(stroke1[prop]) != len(stroke2[prop]): + return False + for prop_elem1, prop_elem2 in zip(stroke1[prop], stroke2[prop]): + if abs(float(prop_elem1) - float(prop_elem2)) > tol: + return False + + # 'layout' has a dict of various things, some of which should be identical + if sorted(baseline['layout'].keys()) != sorted(figd['layout'].keys()): + return False + if baseline['layout']['xaxis'] != baseline['layout']['xaxis']: + return False + if baseline['layout']['yaxis'] != baseline['layout']['yaxis']: + return False + # 'shapes' is a list of shape, should be the same up to tolerance + if len(baseline['layout']['shapes']) != len(figd['layout']['shapes']): + return False + for shape1, shape2 in zip(baseline['layout']['shapes'], figd['layout']['shapes']): + if sorted(shape1.keys()) != sorted(shape2.keys()): + return False + if shape1['type'] != shape2['type']: + return False + if 'line' in shape1: + if shape1['line']['color'] != shape2['line']['color']: + return False + if ('width' in shape1['line']) != ('width' in shape2['line']): + return False + if 'width' in shape1['line']: + w1 = float(shape1['line']['width']) + w2 = float(shape2['line']['width']) + if abs(w1 - w2) > tol: + return False + + if 'path' in shape1: + # SVG path + path1, path2 = shape1['path'].split(), shape2['path'].split() + if len(path1) != len(path2): + return False + for path_elem1, path_elem2 in zip(path1, path2): + is_coords1 = is_coords(path_elem1) + is_coords2 = is_coords(path_elem2) + if is_coords1 != is_coords2: + return False + if is_coords1: + if not same_coords(path_elem1, path_elem2, tol): + return False + + # 'layout': skipping that for now, seems mostly plotly internals + + return True + + +def compare_image(baseline, fig, tol=0, fmt="json"): + if fmt == "json": + return _compare_image_json(baseline, fig) + + raise NotImplementedError(f"Image format {fmt} not implemented yet") + + +def _unittest_image_comparison( + baseline_images, + tol, + remove_text, +): + """ + Decorate function with image comparison for unittest. + This function creates a decorator that wraps a figure-generating function + with image comparison code. + """ + import unittest + + def decorator(func): + old_sig = inspect.signature(func) + + # This saves us to lift name, docstring, etc. + # NOTE: not super sure why we need this additional layer of wrapping + # seems to have to do with stripping arguments from the test function + # probably redundant in this adaptation + @functools.wraps(func) + def wrapper(*args, **kwargs): + + # Three steps: + # 1. run the function and store the results + figs = func(*args, **kwargs) + if isinstance(figs, plotly.graph_objects.Figure): + figs = [figs] + + # Store images (used to bootstrap new tests) + for fig, image_file in zip(figs, baseline_images): + _store_result_image(fig, image_file) + + assert len(baseline_images) == len( + figs + ), "Test generated {} images but there are {} baseline images".format( + len(figs), len(baseline_images) + ) + + # 2. load the control images + baselines = _load_baseline_images(baseline_images) + + # 3. compare them one by one + for i, (baseline, fig) in enumerate(zip(baselines, figs)): + if remove_text: + # TODO + pass + + # FIXME: what does tolerance mean for json? + res = compare_image(baseline, fig, tol) + assert res, f"Image {i} does not match the corresponding baseline" + + return figs + + parameters = list(old_sig.parameters.values()) + new_sig = old_sig.replace(parameters=parameters) + wrapper.__signature__ = new_sig + + return wrapper + + return decorator + + +def image_comparison( + baseline_images, + tol=0, + remove_text=False, +): + """ + Compare images generated by the test with those specified in + *baseline_images*, which must correspond, else an `ImageComparisonFailure` + exception will be raised. + Parameters + ---------- + baseline_images : list or None + A list of strings specifying the names of the images generated by + calls to `.Figure.savefig`. + If *None*, the test function must use the ``baseline_images`` fixture, + either as a parameter or with `pytest.mark.usefixtures`. This value is + only allowed when using pytest. + tol : float, default: 0 + The RMS threshold above which the test is considered failed. + Due to expected small differences in floating-point calculations, on + 32-bit systems an additional 0.06 is added to this threshold. + remove_text : bool + Remove the title and tick text from the figure before comparison. This + is useful to make the baseline images independent of variations in text + rendering between different versions of FreeType. + This does not remove other, more deliberate, text, such as legends and + annotations. + savefig_kwarg : dict + Optional arguments that are passed to the savefig method. + style : str, dict, or list + The optional style(s) to apply to the image test. The test itself + can also apply additional styles if desired. Defaults to ``["classic", + "_classic_test_patch"]``. + """ + if sys.maxsize <= 2 ** 32: + tol += 0.06 + return _unittest_image_comparison( + baseline_images=baseline_images, + tol=tol, + remove_text=remove_text, + ) diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 1f77a33be..e7f0d6786 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -105,8 +105,7 @@ def testUnhashableVertexNames(self): # Check the exception self.assertTrue(isinstance(err, RuntimeError)) - if sys.version_info >= (3, 4): - self.assertTrue(repr(value) in str(err)) + self.assertTrue(repr(value) in str(err)) def testVertexNameIndexingBug196(self): g = Graph() diff --git a/tox.ini b/tox.ini index 099458469..1ec3997ed 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,10 @@ deps = numpy; platform_python_implementation != "PyPy" networkx; platform_python_implementation != "PyPy" pandas; platform_python_implementation != "PyPy" -extras = plotting + matplotlib; platform_python_implementation != "PyPy" + pytest; platform_python_implementation != "PyPy" +extras = + test passenv = PATH setenv = TESTING_IN_TOX=1 From df440be8f664dcceb4bd45df75cf9fbd85a4bcab Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 14 Sep 2021 16:24:49 +0200 Subject: [PATCH 0630/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc13f2d05..81ff00f20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ [@fwitter](https://github.com/user/fwitter). See PR [#418](https://github.com/igraph/python-igraph/pull/418) for more details. +- Changed default value of the `use_vids=...` argument of `Graph.DataFrame()` + to `True`, thanks to [@fwitter](https://github.com/user/fwitter). + ### Removed - Removed deprecated `UbiGraphDrawer`. From cdf08b03b1dd7d5b78bf1bc276eb61cd34498501 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Sep 2021 12:18:55 +0200 Subject: [PATCH 0631/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 6f154c7ac..9b636bc9f 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 6f154c7ac0946f7a0baf1ce403c520cacf6035d7 +Subproject commit 9b636bc9fe56ce2162791a081c487e2459c901f6 From e1a31bcbd78cca34777db563052cc0603fd37694 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 20 Sep 2021 12:59:14 +0200 Subject: [PATCH 0632/1892] doc: removed reference to Nexus from tutorial, fixes #438 --- doc/source/assets/zachary.zip | Bin 0 -> 766 bytes doc/source/tutorial.rst | 18 ++++++++---------- 2 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 doc/source/assets/zachary.zip diff --git a/doc/source/assets/zachary.zip b/doc/source/assets/zachary.zip new file mode 100644 index 0000000000000000000000000000000000000000..d6a99901fad4ba6563510025b0b3fde3c4f464f0 GIT binary patch literal 766 zcmWIWW@Zs#U|`^2NJ%vbK5_0@lNS>MLn2U!pFxJ9Dls`Dv8Ylny(qCDBR3~Bgp+}J zcdAFCUz$f^X$3a}BgR{w?wo9-^5GaRax3!y%M`8 z3Ux4Ce|KAavK8ynq;KK18_)dNy!rFnGizLn$}8)N>SnE5e_Jhd%h##Nvli*TUgmZ6 zx;}s2ns=LggGzs%E)3~=waou&p+p?tyzkFnmi^M({l}&%_x8F^YBO(HY(M|ycfrfo z=GQ;}+++LN^UOZ~d)xi{=XWozJa>23%l18*XYTA>&;K{2HmAF0##A{?!>j*{_$rv!2YqtYqK+qE{#1?8q})_qXfl%F`jWGCQYE)jZq(=ZndbS68N# zrgvTRPQ9!*X_@X>mE1qKmEZq*Gk4~-vwQNcy?&N(S7zPp#igI~?#is6{hdjSbM}E= zmI9Rt%8as{Z#){@nQVnVOgzxfTBmb$E|~g|+$hieC*r|zCVR0TnT_*-#LB||C*NCz z%-LsK+B#FM-S|mtYTMBnJF;9XlZ$#!GW*CSed3t>-k`GQWP0%lKYlrpMs?Q*fr1_B zX5nwRc+Z4Kzu?qPIm9({!!1PtyT%WkE&d9BSY^AD(t6aAO`aFIeHB}~`^H|^w`abJ zeUOw^;knj#EFr6)FQdSk(QFEHK~CF^PY>&L{Ka0oFR){i)@JiAUbx+2t?df+UMrRa zHgERX9EwtkF3Jm*JG?LysN#FG*!Z-&@`2!q7dbvhC3XL=2CC?GSZulA>E1h&&ZY`1 z@MO=p)XlbO#~Vu*StXN~97lIK%O;tyZ*i^czb16+veetm-fvsfOqdo5wkS^6v(Ngp z*~z!6QQLm<26!_v$uZ+floG(i%D@0jbqq@yK`e|U$_h!MXvs6co0ScuoDm2^f%Ifx IDraB-08kA}FaQ7m literal 0 HcmV?d00001 diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index b9d7cf25e..5c12742b9 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -1010,20 +1010,18 @@ Pickled graph ``pickle`` :meth:`Graph.Read_Pickle` :meth:`Graph.write_p As an exercise, download the graph representation of the well-known `Zachary karate club study `_ -from igraph's own graph repository called `Nexus `_, -unzip it and try to load it into |igraph|. Since it is a GraphML file, you must -must use the GraphML reader method from the table above (make sure you use the -appropriate path to the downloaded file): +from :download:`this file `, unzip it and try to load it into +|igraph|. Since it is a GraphML file, you must use the GraphML reader method from +the table above (make sure you use the appropriate path to the downloaded file): ->>> karate = Graph.Read_GraphML("karate.GraphML") +>>> karate = Graph.Read_GraphML("zachary.graphml") >>> summary(karate) IGRAPH UNW- 34 78 -- Zachary's karate club network -+ attr: Author (g), Citation (g), name (g), Faction (v), id (v), name (v), weight (e) If you want to convert the very same graph into, say, Pajek's format, you can do it with the Pajek writer method from the table above: ->>> karate.write_pajek("karate.net") +>>> karate.write_pajek("zachary.net") .. note:: Most of the formats have their own limitations; for instance, not all of them can store attributes. Your best bet is probably GraphML or GML if you @@ -1042,9 +1040,9 @@ the preferred format is again inferred from the extension. The format detection :func:`load` and :meth:`Graph.save` can be overridden by the ``format`` keyword argument which accepts the short names of the formats from the above table: ->>> karate = load("karate.GraphML") ->>> karate.save("karate.net") ->>> karate.save("karate.my_extension", format="gml") +>>> karate = load("zachary.graphml") +>>> karate.save("zachary.net") +>>> karate.save("zachary.my_extension", format="gml") Where to go next From 845fbc9ddda461160ec7962a7c6ebd66e7668307 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 20 Sep 2021 12:59:43 +0200 Subject: [PATCH 0633/1892] doc: added 'doc' extra to setup.py to document what's needed for building the docs --- setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.py b/setup.py index 4d2a7ffcf..fc8945562 100644 --- a/setup.py +++ b/setup.py @@ -831,6 +831,10 @@ def use_educated_guess(self) -> None: "pandas>=1.1.0,<1.3.1; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", ], + "doc": [ + "Sphinx>=4.2.0", + "sphinxbootstrap4theme>=0.6.0" + ] }, python_requires=">=3.6", headers=headers, From 9bde4c29f714a971f6ee5c58a4567b0debd79aab Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 20 Sep 2021 14:05:52 +0200 Subject: [PATCH 0634/1892] doc: update igraph version in example output of the documentation --- doc/source/tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 5c12742b9..854c9195b 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -36,7 +36,7 @@ following: >>> import igraph >>> print(igraph.__version__) -0.6 +0.9.6 Another way to make use of |igraph| is to import all its objects and methods into the main Python namespace (so you do not have to type the namespace-qualification every time). @@ -57,7 +57,7 @@ When you start the script, you will see something like this:: $ igraph No configuration file, using defaults - igraph 0.9.4 running inside Python 3.9.6 (default, Jun 29 2021, 05:25:02) + igraph 0.9.6 running inside Python 3.9.6 (default, Jun 29 2021, 05:25:02) Type "copyright", "credits" or "license" for more information. >>> From 8a518d6ed7585f473c3d52af3d84e483d6ed5161 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 22 Sep 2021 00:13:29 +1000 Subject: [PATCH 0635/1892] Graph.is_chordal (#437) * Implement Graph.is_chordal in its simplest form * feat: added 'alpha' and 'alpham1' arguments to is_chordal() * feat: added Graph.maximum_cardinality_search() * feat: added Graph.chordal_completion() * doc: mention that chordal_completion() can be suboptimal Co-authored-by: Tamas Nepusz --- src/_igraph/graphobject.c | 249 ++++++++++++++++++++++++++++++++++++++ tests/test_structural.py | 114 +++++++++++++++++ 2 files changed, 363 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 429e183cd..26a6405c2 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4134,6 +4134,84 @@ PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { return o; } +PyObject *igraphmodule_Graph_chordal_completion( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "alpha", "alpham1", NULL }; + PyObject *alpha_o = Py_None, *alpham1_o = Py_None, *res_o; + igraph_vector_int_t alpha, alpham1, edges; + igraph_vector_int_t *alpha_ptr = 0, *alpham1_ptr = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &alpha_o, &alpham1_o)) { + return NULL; + } + + if (alpha_o != Py_None) { + if (igraphmodule_PyObject_to_vector_int_t(alpha_o, &alpha)) { + return NULL; + } + + alpha_ptr = α + } + + if (alpham1_o != Py_None) { + if (igraphmodule_PyObject_to_vector_int_t(alpham1_o, &alpham1)) { + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + return NULL; + } + + alpham1_ptr = &alpham1; + } + + if (igraph_vector_int_init(&edges, 0)) { + igraphmodule_handle_igraph_error(); + if (alpham1_ptr) { + igraph_vector_int_destroy(alpham1_ptr); + } + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + return NULL; + } + + if (igraph_is_chordal( + &self->g, + alpha_ptr, /* alpha */ + alpham1_ptr, /* alpham1 */ + 0, /* chordal */ + &edges, /* fill_in */ + NULL /* new_graph */ + )) { + igraph_vector_int_destroy(&edges); + + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_int_destroy(alpham1_ptr); + } + + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_int_destroy(alpham1_ptr); + } + + res_o = igraphmodule_vector_int_t_to_PyList_pairs(&edges); + igraph_vector_int_destroy(&edges); + + return res_o; +} + /** \ingroup python_interface_graph * \brief Calculates the closeness centrality of some vertices in a graph. * \return the closeness centralities as a list (or a single float) @@ -5159,6 +5237,68 @@ PyObject *igraphmodule_Graph_hub_score( return res_o; } +PyObject *igraphmodule_Graph_is_chordal( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "alpha", "alpham1", NULL }; + PyObject *alpha_o = Py_None, *alpham1_o = Py_None; + igraph_vector_int_t alpha, alpham1; + igraph_vector_int_t *alpha_ptr = 0, *alpham1_ptr = 0; + igraph_bool_t res; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &alpha_o, &alpham1_o)) { + return NULL; + } + + if (alpha_o != Py_None) { + if (igraphmodule_PyObject_to_vector_int_t(alpha_o, &alpha)) { + return NULL; + } + + alpha_ptr = α + } + + if (alpham1_o != Py_None) { + if (igraphmodule_PyObject_to_vector_int_t(alpham1_o, &alpham1)) { + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + return NULL; + } + + alpham1_ptr = &alpham1; + } + + if (igraph_is_chordal( + &self->g, + alpha_ptr, /* alpha */ + alpham1_ptr, /* alpham1 */ + &res, + NULL, /* fill_in */ + NULL /* new_graph */ + )) { + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_int_destroy(alpham1_ptr); + } + + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (alpha_ptr) { + igraph_vector_int_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_int_destroy(alpham1_ptr); + } + + return res ? Py_True : Py_False; +} /** \ingroup python_interface_graph * \brief Returns the line graph of the graph @@ -5179,6 +5319,51 @@ PyObject *igraphmodule_Graph_linegraph(igraphmodule_GraphObject * self) { return (PyObject *) result; } +/** + * \ingroup python_interface_graph + * \brief Conducts a maximum cardinality search on the graph. + * \sa igraph_maximum_cardinality_search + */ +PyObject *igraphmodule_Graph_maximum_cardinality_search(igraphmodule_GraphObject *self) { + igraph_vector_int_t alpha, alpham1; + PyObject *alpha_o, *alpham1_o; + + if (igraph_vector_int_init(&alpha, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_vector_int_init(&alpham1, 0)) { + igraph_vector_int_destroy(&alpha); + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_maximum_cardinality_search(&self->g, &alpha, &alpham1)) { + igraph_vector_int_destroy(&alpha); + igraph_vector_int_destroy(&alpham1); + return NULL; + } + + alpha_o = igraphmodule_vector_int_t_to_PyList(&alpha); + igraph_vector_int_destroy(&alpha); + + if (!alpha_o) { + igraph_vector_int_destroy(&alpham1); + return NULL; + } + + alpham1_o = igraphmodule_vector_int_t_to_PyList(&alpham1); + igraph_vector_int_destroy(&alpham1); + + if (!alpham1_o) { + Py_DECREF(alpha_o); + return NULL; + } + + return PyTuple_Pack(2, alpha_o, alpham1_o); +} + /** * \ingroup python_interface_graph * \brief Returns the k-neighborhood of some vertices in the @@ -13284,6 +13469,33 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "components in the graph.\n" }, + /* interface to igraph_is_chordal with alternative arguments */ + {"chordal_completion", (PyCFunction)igraphmodule_Graph_chordal_completion, + METH_VARARGS | METH_KEYWORDS, + "chordal_complation(alpha=None, alpham1=None)\n--\n\n" + "Returns the list of edges needed to be added to the graph to make it chordal.\n\n" + "A graph is chordal if each of its cycles of four or more nodes\n" + "has a chord, i.e. an edge joining two nodes that are not\n" + "adjacent in the cycle. An equivalent definition is that any\n" + "chordless cycles have at most three nodes.\n\n" + "The chordal completion of a graph is the list of edges that needed to be\n" + "added to the graph to make it chordal. It is an empty list if the graph is\n" + "already chordal.\n\n" + "Note that at the moment igraph does not guarantee that the returned\n" + "chordal completion is I{minimal}; there may exist a subset of the returned\n" + "chordal completion that is still a valid chordal completion.\n\n" + "@param alpha: the alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the alpha vector; simply passing C{None} here will make igraph\n" + " calculate the alpha vector on its own.\n" + "@param alpham1: the inverse alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the inverse alpha vector; simply passing C{None} here will make\n" + " igraph calculate the inverse alpha vector on its own.\n" + "@return: the list of edges to add to the graph; each item in the list is a\n" + " source-target pair of vertex indices.\n" + }, + /* interface to igraph_closeness */ {"closeness", (PyCFunction) igraphmodule_Graph_closeness, METH_VARARGS | METH_KEYWORDS, @@ -13766,6 +13978,26 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" }, + /* interface to igraph_is_chordal */ + {"is_chordal", (PyCFunction)igraphmodule_Graph_is_chordal, + METH_VARARGS | METH_KEYWORDS, + "is_chordal(alpha=None, alpham1=None)\n--\n\n" + "Returns whether the graph is chordal or not.\n\n" + "A graph is chordal if each of its cycles of four or more nodes\n" + "has a chord, i.e. an edge joining two nodes that are not\n" + "adjacent in the cycle. An equivalent definition is that any\n" + "chordless cycles have at most three nodes.\n\n" + "@param alpha: the alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the alpha vector; simply passing C{None} here will make igraph\n" + " calculate the alpha vector on its own.\n" + "@param alpham1: the inverse alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the inverse alpha vector; simply passing C{None} here will make\n" + " igraph calculate the inverse alpha vector on its own.\n" + "@return: C{True} if the graph is chordal, C{False} otherwise.\n" + }, + /* interface to igraph_avg_nearest_neighbor_degree */ {"knn", (PyCFunction) igraphmodule_Graph_knn, METH_VARARGS | METH_KEYWORDS, @@ -13825,6 +14057,23 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " them).\n" "@param loops: whether self-loops should be counted.\n"}, + /* interface to maximum_cardinality_search */ + {"maximum_cardinality_search", (PyCFunction) igraphmodule_Graph_maximum_cardinality_search, + METH_NOARGS, + "maximum_cardinality_search()\n--\n\n" + "Conducts a maximum cardinality search on the graph. The function computes\n" + "a rank I{alpha} for each vertex such that visiting vertices in decreasing\n" + "rank order corresponds to always choosing the vertex with the most already\n" + "visited neighbors as the next one to visit.\n\n" + "Maximum cardinality search is useful in deciding the chordality of a graph:\n" + "a graph is chordal if and only if any two neighbors of a vertex that are\n" + "higher in rank than the original vertex are connected to each other.\n\n" + "The result of this function can be passed to L{is_chordal()} to speed up\n" + "the chordality computation if you also need the result of the maximum\n" + "cardinality search for other purposes.\n\n" + "@return: a tuple consisting of the rank vector and its inverse.\n" + }, + /* interface to igraph_neighborhood */ {"neighborhood", (PyCFunction) igraphmodule_Graph_neighborhood, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/test_structural.py b/tests/test_structural.py index edec2f8f4..dccf2921d 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -496,6 +496,27 @@ def testNeighborhoodSize(self): class MiscTests(unittest.TestCase): + def assert_valid_maximum_cardinality_search_result(self, graph, alpha, alpham1): + visited = [] + n = graph.vcount() + not_visited = list(range(n)) + + # Check if alpham1 is a valid visiting order + for vertex in reversed(alpham1): + neis = graph.neighbors(vertex) + visited_neis = sum(1 for v in neis if v in visited) + for other_vertex in not_visited: + neis = graph.neighbors(other_vertex) + other_visited_neis = sum(1 for v in neis if v in visited) + self.assertTrue(other_visited_neis <= visited_neis) + + visited.append(vertex) + not_visited.remove(vertex) + + # Check if alpha is the inverse of alpham1 + for index, vertex in enumerate(alpham1): + self.assertEqual(alpha[vertex], index) + def testBridges(self): g = Graph(5, [(0, 1), (1, 2), (2, 0), (0, 3), (3, 4)]) self.assertEqual(g.bridges(), [3, 4]) @@ -504,6 +525,45 @@ def testBridges(self): g = Graph(3, [(0, 1), (1, 2), (2, 3)]) self.assertEqual(g.bridges(), [0, 1, 2]) + def testChordalCompletion(self): + g = Graph() + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Full(3) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Full(5) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(4) + cc = g.chordal_completion() + self.assertEqual(len(cc), 1) + g += cc + self.assertTrue(g.is_chordal()) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(5) + cc = g.chordal_completion() + self.assertEqual(len(cc), 2) + g += cc + self.assertListEqual([], g.chordal_completion()) + + def testChordalCompletionWithHints(self): + g = Graph.Ring(4) + alpha, _ = g.maximum_cardinality_search() + cc = g.chordal_completion(alpha=alpha) + self.assertEqual(len(cc), 1) + g += cc + self.assertTrue(g.is_chordal()) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(5) + _, alpham1 = g.maximum_cardinality_search() + cc = g.chordal_completion(alpham1=alpham1) + self.assertEqual(len(cc), 2) + g += cc + self.assertListEqual([], g.chordal_completion()) + def testConstraint(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) self.assertTrue(isinstance(g.constraint(), list)) # TODO check more @@ -567,6 +627,43 @@ def testIsTree(self): g.is_tree("all") ) + def testIsChordal(self): + g = Graph() + self.assertTrue(g.is_chordal()) + + g = Graph.Full(3) + self.assertTrue(g.is_chordal()) + + g = Graph.Full(5) + self.assertTrue(g.is_chordal()) + + g = Graph.Ring(4) + self.assertFalse(g.is_chordal()) + + g = Graph.Ring(5) + self.assertFalse(g.is_chordal()) + + def testIsChordalWithHint(self): + g = Graph() + alpha, _ = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpha=alpha)) + + g = Graph.Full(3) + alpha, _ = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpha=alpha)) + + g = Graph.Ring(5) + alpha, _ = g.maximum_cardinality_search() + self.assertFalse(g.is_chordal(alpha=alpha)) + + g = Graph.Ring(4) + _, alpham1 = g.maximum_cardinality_search() + self.assertFalse(g.is_chordal(alpham1=alpham1)) + + g = Graph.Full(5) + _, alpham1 = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpham1=alpham1)) + def testLineGraph(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) el = g.linegraph().get_edgelist() @@ -580,6 +677,23 @@ def testLineGraph(self): el.sort() self.assertTrue(el == [(0, 2), (0, 4)]) + def testMaximumCardinalitySearch(self): + g = Graph() + alpha, alpham1 = g.maximum_cardinality_search() + self.assertListEqual([], alpha) + self.assertListEqual([], alpham1) + + g = Graph.Famous("petersen") + alpha, alpham1 = g.maximum_cardinality_search() + + print(repr(alpha), repr(alpham1)) + self.assert_valid_maximum_cardinality_search_result(g, alpha, alpham1) + + g = Graph.GRG(100, 0.2) + alpha, alpham1 = g.maximum_cardinality_search() + + self.assert_valid_maximum_cardinality_search_result(g, alpha, alpham1) + class PathTests(unittest.TestCase): def testShortestPaths(self): From 25e4f2e65a990b10540d374b34dc62b5e4f517d7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 22 Sep 2021 00:13:29 +1000 Subject: [PATCH 0636/1892] Graph.is_chordal (#437) * Implement Graph.is_chordal in its simplest form * feat: added 'alpha' and 'alpham1' arguments to is_chordal() * feat: added Graph.maximum_cardinality_search() * feat: added Graph.chordal_completion() * doc: mention that chordal_completion() can be suboptimal Co-authored-by: Tamas Nepusz --- src/_igraph/graphobject.c | 249 ++++++++++++++++++++++++++++++++++++++ tests/test_structural.py | 114 +++++++++++++++++ 2 files changed, 363 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 2bb48112b..ca0409bf9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4190,6 +4190,84 @@ PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { return o; } +PyObject *igraphmodule_Graph_chordal_completion( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "alpha", "alpham1", NULL }; + PyObject *alpha_o = Py_None, *alpham1_o = Py_None, *res_o; + igraph_vector_t alpha, alpham1, edges; + igraph_vector_t *alpha_ptr = 0, *alpham1_ptr = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &alpha_o, &alpham1_o)) { + return NULL; + } + + if (alpha_o != Py_None) { + if (igraphmodule_PyObject_to_vector_t(alpha_o, &alpha, IGRAPHMODULE_TYPE_INT)) { + return NULL; + } + + alpha_ptr = α + } + + if (alpham1_o != Py_None) { + if (igraphmodule_PyObject_to_vector_t(alpham1_o, &alpham1, IGRAPHMODULE_TYPE_INT)) { + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + return NULL; + } + + alpham1_ptr = &alpham1; + } + + if (igraph_vector_init(&edges, 0)) { + igraphmodule_handle_igraph_error(); + if (alpham1_ptr) { + igraph_vector_destroy(alpham1_ptr); + } + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + return NULL; + } + + if (igraph_is_chordal( + &self->g, + alpha_ptr, /* alpha */ + alpham1_ptr, /* alpham1 */ + 0, /* chordal */ + &edges, /* fill_in */ + NULL /* new_graph */ + )) { + igraph_vector_destroy(&edges); + + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_destroy(alpham1_ptr); + } + + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_destroy(alpham1_ptr); + } + + res_o = igraphmodule_vector_t_to_PyList_pairs(&edges); + igraph_vector_destroy(&edges); + + return res_o; +} + /** \ingroup python_interface_graph * \brief Calculates the closeness centrality of some vertices in a graph. * \return the closeness centralities as a list (or a single float) @@ -5190,6 +5268,68 @@ PyObject *igraphmodule_Graph_hub_score( return res_o; } +PyObject *igraphmodule_Graph_is_chordal( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "alpha", "alpham1", NULL }; + PyObject *alpha_o = Py_None, *alpham1_o = Py_None; + igraph_vector_t alpha, alpham1; + igraph_vector_t *alpha_ptr = 0, *alpham1_ptr = 0; + igraph_bool_t res; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &alpha_o, &alpham1_o)) { + return NULL; + } + + if (alpha_o != Py_None) { + if (igraphmodule_PyObject_to_vector_t(alpha_o, &alpha, IGRAPHMODULE_TYPE_INT)) { + return NULL; + } + + alpha_ptr = α + } + + if (alpham1_o != Py_None) { + if (igraphmodule_PyObject_to_vector_t(alpham1_o, &alpham1, IGRAPHMODULE_TYPE_INT)) { + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + return NULL; + } + + alpham1_ptr = &alpham1; + } + + if (igraph_is_chordal( + &self->g, + alpha_ptr, /* alpha */ + alpham1_ptr, /* alpham1 */ + &res, + NULL, /* fill_in */ + NULL /* new_graph */ + )) { + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_destroy(alpham1_ptr); + } + + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (alpha_ptr) { + igraph_vector_destroy(alpha_ptr); + } + + if (alpham1_ptr) { + igraph_vector_destroy(alpham1_ptr); + } + + return res ? Py_True : Py_False; +} /** \ingroup python_interface_graph * \brief Returns the line graph of the graph @@ -5210,6 +5350,51 @@ PyObject *igraphmodule_Graph_linegraph(igraphmodule_GraphObject * self) { return (PyObject *) result; } +/** + * \ingroup python_interface_graph + * \brief Conducts a maximum cardinality search on the graph. + * \sa igraph_maximum_cardinality_search + */ +PyObject *igraphmodule_Graph_maximum_cardinality_search(igraphmodule_GraphObject *self) { + igraph_vector_t alpha, alpham1; + PyObject *alpha_o, *alpham1_o; + + if (igraph_vector_init(&alpha, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_vector_init(&alpham1, 0)) { + igraph_vector_destroy(&alpha); + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_maximum_cardinality_search(&self->g, &alpha, &alpham1)) { + igraph_vector_destroy(&alpha); + igraph_vector_destroy(&alpham1); + return NULL; + } + + alpha_o = igraphmodule_vector_t_to_PyList(&alpha, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(&alpha); + + if (!alpha_o) { + igraph_vector_destroy(&alpham1); + return NULL; + } + + alpham1_o = igraphmodule_vector_t_to_PyList(&alpham1, IGRAPHMODULE_TYPE_INT); + igraph_vector_destroy(&alpham1); + + if (!alpham1_o) { + Py_DECREF(alpha_o); + return NULL; + } + + return PyTuple_Pack(2, alpha_o, alpham1_o); +} + /** * \ingroup python_interface_graph * \brief Returns the k-neighborhood of some vertices in the @@ -13174,6 +13359,33 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "components in the graph.\n" }, + /* interface to igraph_is_chordal with alternative arguments */ + {"chordal_completion", (PyCFunction)igraphmodule_Graph_chordal_completion, + METH_VARARGS | METH_KEYWORDS, + "chordal_complation(alpha=None, alpham1=None)\n--\n\n" + "Returns the list of edges needed to be added to the graph to make it chordal.\n\n" + "A graph is chordal if each of its cycles of four or more nodes\n" + "has a chord, i.e. an edge joining two nodes that are not\n" + "adjacent in the cycle. An equivalent definition is that any\n" + "chordless cycles have at most three nodes.\n\n" + "The chordal completion of a graph is the list of edges that needed to be\n" + "added to the graph to make it chordal. It is an empty list if the graph is\n" + "already chordal.\n\n" + "Note that at the moment igraph does not guarantee that the returned\n" + "chordal completion is I{minimal}; there may exist a subset of the returned\n" + "chordal completion that is still a valid chordal completion.\n\n" + "@param alpha: the alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the alpha vector; simply passing C{None} here will make igraph\n" + " calculate the alpha vector on its own.\n" + "@param alpham1: the inverse alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the inverse alpha vector; simply passing C{None} here will make\n" + " igraph calculate the inverse alpha vector on its own.\n" + "@return: the list of edges to add to the graph; each item in the list is a\n" + " source-target pair of vertex indices.\n" + }, + /* interface to igraph_closeness */ {"closeness", (PyCFunction) igraphmodule_Graph_closeness, METH_VARARGS | METH_KEYWORDS, @@ -13656,6 +13868,26 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" }, + /* interface to igraph_is_chordal */ + {"is_chordal", (PyCFunction)igraphmodule_Graph_is_chordal, + METH_VARARGS | METH_KEYWORDS, + "is_chordal(alpha=None, alpham1=None)\n--\n\n" + "Returns whether the graph is chordal or not.\n\n" + "A graph is chordal if each of its cycles of four or more nodes\n" + "has a chord, i.e. an edge joining two nodes that are not\n" + "adjacent in the cycle. An equivalent definition is that any\n" + "chordless cycles have at most three nodes.\n\n" + "@param alpha: the alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the alpha vector; simply passing C{None} here will make igraph\n" + " calculate the alpha vector on its own.\n" + "@param alpham1: the inverse alpha vector from the result of calling\n" + " L{maximum_cardinality_search()} on the graph. Useful only if you already\n" + " have the inverse alpha vector; simply passing C{None} here will make\n" + " igraph calculate the inverse alpha vector on its own.\n" + "@return: C{True} if the graph is chordal, C{False} otherwise.\n" + }, + /* interface to igraph_avg_nearest_neighbor_degree */ {"knn", (PyCFunction) igraphmodule_Graph_knn, METH_VARARGS | METH_KEYWORDS, @@ -13715,6 +13947,23 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " them).\n" "@param loops: whether self-loops should be counted.\n"}, + /* interface to maximum_cardinality_search */ + {"maximum_cardinality_search", (PyCFunction) igraphmodule_Graph_maximum_cardinality_search, + METH_NOARGS, + "maximum_cardinality_search()\n--\n\n" + "Conducts a maximum cardinality search on the graph. The function computes\n" + "a rank I{alpha} for each vertex such that visiting vertices in decreasing\n" + "rank order corresponds to always choosing the vertex with the most already\n" + "visited neighbors as the next one to visit.\n\n" + "Maximum cardinality search is useful in deciding the chordality of a graph:\n" + "a graph is chordal if and only if any two neighbors of a vertex that are\n" + "higher in rank than the original vertex are connected to each other.\n\n" + "The result of this function can be passed to L{is_chordal()} to speed up\n" + "the chordality computation if you also need the result of the maximum\n" + "cardinality search for other purposes.\n\n" + "@return: a tuple consisting of the rank vector and its inverse.\n" + }, + /* interface to igraph_neighborhood */ {"neighborhood", (PyCFunction) igraphmodule_Graph_neighborhood, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/test_structural.py b/tests/test_structural.py index 9ea13d990..eaeef42d6 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -496,6 +496,27 @@ def testNeighborhoodSize(self): class MiscTests(unittest.TestCase): + def assert_valid_maximum_cardinality_search_result(self, graph, alpha, alpham1): + visited = [] + n = graph.vcount() + not_visited = list(range(n)) + + # Check if alpham1 is a valid visiting order + for vertex in reversed(alpham1): + neis = graph.neighbors(vertex) + visited_neis = sum(1 for v in neis if v in visited) + for other_vertex in not_visited: + neis = graph.neighbors(other_vertex) + other_visited_neis = sum(1 for v in neis if v in visited) + self.assertTrue(other_visited_neis <= visited_neis) + + visited.append(vertex) + not_visited.remove(vertex) + + # Check if alpha is the inverse of alpham1 + for index, vertex in enumerate(alpham1): + self.assertEqual(alpha[vertex], index) + def testBridges(self): g = Graph(5, [(0, 1), (1, 2), (2, 0), (0, 3), (3, 4)]) self.assertTrue(g.bridges() == [3, 4]) @@ -504,6 +525,45 @@ def testBridges(self): g = Graph(3, [(0, 1), (1, 2), (2, 3)]) self.assertTrue(g.bridges() == [0, 1, 2]) + def testChordalCompletion(self): + g = Graph() + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Full(3) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Full(5) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(4) + cc = g.chordal_completion() + self.assertEqual(len(cc), 1) + g += cc + self.assertTrue(g.is_chordal()) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(5) + cc = g.chordal_completion() + self.assertEqual(len(cc), 2) + g += cc + self.assertListEqual([], g.chordal_completion()) + + def testChordalCompletionWithHints(self): + g = Graph.Ring(4) + alpha, _ = g.maximum_cardinality_search() + cc = g.chordal_completion(alpha=alpha) + self.assertEqual(len(cc), 1) + g += cc + self.assertTrue(g.is_chordal()) + self.assertListEqual([], g.chordal_completion()) + + g = Graph.Ring(5) + _, alpham1 = g.maximum_cardinality_search() + cc = g.chordal_completion(alpham1=alpham1) + self.assertEqual(len(cc), 2) + g += cc + self.assertListEqual([], g.chordal_completion()) + def testConstraint(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) self.assertTrue(isinstance(g.constraint(), list)) # TODO check more @@ -567,6 +627,43 @@ def testIsTree(self): g.is_tree("all") ) + def testIsChordal(self): + g = Graph() + self.assertTrue(g.is_chordal()) + + g = Graph.Full(3) + self.assertTrue(g.is_chordal()) + + g = Graph.Full(5) + self.assertTrue(g.is_chordal()) + + g = Graph.Ring(4) + self.assertFalse(g.is_chordal()) + + g = Graph.Ring(5) + self.assertFalse(g.is_chordal()) + + def testIsChordalWithHint(self): + g = Graph() + alpha, _ = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpha=alpha)) + + g = Graph.Full(3) + alpha, _ = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpha=alpha)) + + g = Graph.Ring(5) + alpha, _ = g.maximum_cardinality_search() + self.assertFalse(g.is_chordal(alpha=alpha)) + + g = Graph.Ring(4) + _, alpham1 = g.maximum_cardinality_search() + self.assertFalse(g.is_chordal(alpham1=alpham1)) + + g = Graph.Full(5) + _, alpham1 = g.maximum_cardinality_search() + self.assertTrue(g.is_chordal(alpham1=alpham1)) + def testLineGraph(self): g = Graph(4, [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]) el = g.linegraph().get_edgelist() @@ -580,6 +677,23 @@ def testLineGraph(self): el.sort() self.assertTrue(el == [(0, 2), (0, 4)]) + def testMaximumCardinalitySearch(self): + g = Graph() + alpha, alpham1 = g.maximum_cardinality_search() + self.assertListEqual([], alpha) + self.assertListEqual([], alpham1) + + g = Graph.Famous("petersen") + alpha, alpham1 = g.maximum_cardinality_search() + + print(repr(alpha), repr(alpham1)) + self.assert_valid_maximum_cardinality_search_result(g, alpha, alpham1) + + g = Graph.GRG(100, 0.2) + alpha, alpham1 = g.maximum_cardinality_search() + + self.assert_valid_maximum_cardinality_search_result(g, alpha, alpham1) + class PathTests(unittest.TestCase): def testShortestPaths(self): From 2fded26f050ff55cb72e188490262c8f71384bb6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 21 Sep 2021 16:25:37 +0200 Subject: [PATCH 0637/1892] chore: updated changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6d9c4755..312aeb0b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## [Unreleased] +### Added + +* Added `Graph.is_chordal()` to test whether a graph is chordal and + `Graph.chordal_completion()` to return a possible (not necessary minimal) + chordal completion of a graph. + +* Added `Graph.maximum_cardinality_search()`, primarily as an aid for + `Graph.is_chordal()`. + ### Changed * Improved performance of `Graph.DataFrame()`, thanks to From 55df7b2409155521d60f4f90d0ba777e555b9857 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 25 Sep 2021 22:44:39 +0200 Subject: [PATCH 0638/1892] ci: build macOS x86_64 and arm64 wheels separately --- .github/workflows/build.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index afd7a2df1..9f9fd128c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ env: CIBW_TEST_SKIP: "cp310-*" jobs: - build_wheels: + build_wheel_linux: name: Build wheels on Linux (${{ matrix.wheel_arch }}) runs-on: ubuntu-20.04 strategy: @@ -36,8 +36,8 @@ jobs: with: path: ./wheelhouse/*.whl - build_aarch64_wheels: - name: Build wheels on Linux AArch64 + build_wheel_linux_aarch64: + name: Build wheels on Linux (aarch64) if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') runs-on: ubuntu-20.04 steps: @@ -62,8 +62,15 @@ jobs: path: ./wheelhouse/*.whl build_wheel_macos: - name: Build wheels on macOS + name: Build wheels on macOS (${{ matrix.wheel_arch }}) runs-on: macos-10.15 + strategy: + matrix: + include: + - cmake_arch: x86_64 + wheel_arch: x86_64 + - cmake_arch: arm64 + wheel_arch: arm64 steps: - uses: actions/checkout@v2 @@ -76,7 +83,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v1-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v1-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python @@ -91,8 +98,9 @@ jobs: - name: Build wheels uses: joerick/cibuildwheel@v2.1.1 env: - CIBW_ARCHS_MACOS: "x86_64 arm64" + CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_APPLE_SILICON_PROCESSOR=${{ matrix.cmake_arch }} - uses: actions/upload-artifact@v2 with: From 604ef60e5031652cea88b24ddcd4c2b89e2f1944 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 26 Sep 2021 17:09:49 +0200 Subject: [PATCH 0639/1892] chore: more project URLs in setup.py --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 020e8a6bb..aa8e4c816 100644 --- a/setup.py +++ b/setup.py @@ -817,6 +817,12 @@ def use_educated_guess(self) -> None: license="GNU General Public License (GPL)", author="Tamas Nepusz", author_email="ntamas@gmail.com", + project_urls={ + "Bug Tracker": "https://github.com/igraph/python-igraph/issues", + "CI": "https://github.com/igraph/python-igraph/actions", + "Documentation": "https://igraph.org/python/doc", + "Source Code": "https://github.com/igraph/python-igraph", + }, ext_modules=[igraph_extension], package_dir={"igraph": "src/igraph"}, packages=find_packages(where="src"), From f322b9342058d87c3d2595f737bd1f0251c66716 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Sep 2021 17:31:52 +0200 Subject: [PATCH 0640/1892] ci: another attempt at compiling the C core for Apple Silicon --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f9fd128c..395e66f78 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: - cmake_arch: x86_64 wheel_arch: x86_64 - cmake_arch: arm64 + cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=etc/arith_apple_m1.h wheel_arch: arm64 steps: @@ -83,7 +84,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v1-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python @@ -100,7 +101,7 @@ jobs: env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" - IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_APPLE_SILICON_PROCESSOR=${{ matrix.cmake_arch }} + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} - uses: actions/upload-artifact@v2 with: From 7b9267f536c244754ca796362f1f957dd53507db Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 29 Sep 2021 01:39:22 +1000 Subject: [PATCH 0641/1892] Construct graph from a few more input data structures (mimicking networkx) (#434) * First pass, poor docs * Forgot classmethod decorator * Some polishing and one more input constructor * Graph constructor from pandas adjacency matrix * Move adjacency constructors to module * Move more constructors to dedicated module * Clean up namespace at the end * Small constructor modules * IO module * fix: remove licenses from igraph.io, it is enough to have it in __init__.py * refactor: prefix names of internal functions in igraph.io with an underscore * refactor: moved _first to igraph.utils * style: blackened igraph.io source * Export to dict of sequences * Recover and refine lost PR on use_vids * Match export graph functions for dict/list/tuple types * Include PR #408 in this one * Docstrings and documentation * Bugfix on dict-dict * Implement most of Vincent's suggestions * Running local tests helps... sigh * style: nitpicking, probably ready to merge Co-authored-by: Tamas Nepusz --- doc/source/generation.rst | 23 +- src/igraph/__init__.py | 1830 +++--------------------------------- src/igraph/io/__init__.py | 0 src/igraph/io/adjacency.py | 146 +++ src/igraph/io/bipartite.py | 152 +++ src/igraph/io/files.py | 487 ++++++++++ src/igraph/io/images.py | 365 +++++++ src/igraph/io/libraries.py | 267 ++++++ src/igraph/io/objects.py | 831 ++++++++++++++++ src/igraph/io/random.py | 17 + tests/test_basic.py | 86 ++ tests/test_foreign.py | 157 +++- tests/test_generators.py | 3 +- 13 files changed, 2651 insertions(+), 1713 deletions(-) create mode 100644 src/igraph/io/__init__.py create mode 100644 src/igraph/io/adjacency.py create mode 100644 src/igraph/io/bipartite.py create mode 100644 src/igraph/io/files.py create mode 100644 src/igraph/io/images.py create mode 100644 src/igraph/io/libraries.py create mode 100644 src/igraph/io/objects.py create mode 100644 src/igraph/io/random.py diff --git a/doc/source/generation.rst b/doc/source/generation.rst index d41da27d4..b83317f6f 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -29,13 +29,30 @@ To specify edge weights (or any other vertex/edge attributes), use dictionaries: >>> edge_attrs={'weight': [0.1, 0.2]}, >>> vertex_attrs={'color': ['b', 'g', 'g', 'y']}) -Variations on this constructor is :meth:`Graph.DictList`, which constructs a graph from a list-of-dictionaries representation, and :meth:`Graph.TupleList`, which constructs a graph from a list-of-tuples representation. - To create a bipartite graph from a list of types and a list of edges, use :meth:`Graph.Bipartite`. +From Python builtin structures (lists, tuples, dicts) ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +|igraph| supports a number of "conversion" methods to import graphs from Python builtin data structures such as dictionaries, lists and tuples: + + - :meth:`Graph.DictList`: from a list of dictionaries + - :meth:`Graph.TupleList`: from a list of tuples + - :meth:`Graph.ListDict`: from a dict of lists + - :meth:`Graph.DictDict`: from a dict of dictionaries + +Equivalent methods are available to export a graph, i.e. to convert a graph into +a representation that uses Python builtin data structures: + + - :meth:`Graph.to_dict_list` + - :meth:`Graph.to_tuple_list` + - :meth:`Graph.to_list_dict` + - :meth:`Graph.to_dict_dict` + +See the `API documentation`_ of each function for details and examples. + From matrices +++++++++++++ -To create a graph from an adjecency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`: +To create a graph from an adjacency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`: >>> g = Graph.Adjacency([[0, 1, 1], [0, 0, 0], [0, 0, 1]]) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index d3cacd368..94541a63e 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -4,8 +4,7 @@ __license__ = """ -Copyright (C) 2006-2012 Tamás Nepusz -Pázmány Péter sétány 1/a, 1117 Budapest, Hungary +Copyright (C) 2006- The igraph development team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -121,6 +120,53 @@ ) from igraph.datatypes import Matrix, DyadCensus, TriadCensus, UniqueIdGenerator from igraph.formula import construct_graph_from_formula +from igraph.io.files import ( + _construct_graph_from_graphmlz_file, + _construct_graph_from_dimacs_file, + _construct_graph_from_pickle_file, + _construct_graph_from_picklez_file, + _construct_graph_from_adjacency_file, + _construct_graph_from_file, + _write_graph_to_adjacency_file, + _write_graph_to_dimacs_file, + _write_graph_to_graphmlz_file, + _write_graph_to_pickle_file, + _write_graph_to_picklez_file, + _write_graph_to_file, +) +from igraph.io.objects import ( + _construct_graph_from_dict_list, + _export_graph_to_dict_list, + _construct_graph_from_tuple_list, + _export_graph_to_tuple_list, + _construct_graph_from_list_dict, + _export_graph_to_list_dict, + _construct_graph_from_dict_dict, + _export_graph_to_dict_dict, + _construct_graph_from_dataframe, + _export_vertex_dataframe, + _export_edge_dataframe, +) +from igraph.io.adjacency import ( + _construct_graph_from_adjacency, + _construct_graph_from_weighted_adjacency, +) +from igraph.io.libraries import ( + _construct_graph_from_networkx, + _export_graph_to_networkx, + _construct_graph_from_graph_tool, + _export_graph_to_graph_tool, +) +from igraph.io.random import ( + _construct_random_geometric_graph, +) +from igraph.io.bipartite import ( + _construct_bipartite_graph, + _construct_incidence_bipartite_graph, + _construct_full_bipartite_graph, + _construct_random_bipartite_graph, +) +from igraph.io.images import _write_graph_to_svg from igraph.layout import Layout from igraph.matching import Matching from igraph.operators import disjoint_union, union, intersection @@ -145,14 +191,8 @@ safemax, ) from igraph.version import __version__, __version_info__ -from igraph.sparse_matrix import ( - _graph_from_sparse_matrix, - _graph_from_weighted_sparse_matrix, -) import os -import math -import gzip import sys import operator @@ -1877,1339 +1917,76 @@ def maximum_bipartite_matching(self, types="type", weights=None, eps=None): ############################################# # Auxiliary I/O functions - def to_networkx(self, create_using=None): - """Converts the graph to networkx format. - - @param create_using: specifies which NetworkX graph class to use when - constructing the graph. C{None} means to let igraph infer the most - appropriate class based on whether the graph is directed and whether - it has multi-edges. - """ - import networkx as nx - - # Graph: decide on directness and mutliplicity - if create_using is None: - if self.has_multiple(): - cls = nx.MultiDiGraph if self.is_directed() else nx.MultiGraph - else: - cls = nx.DiGraph if self.is_directed() else nx.Graph - else: - cls = create_using - - # Graph attributes - kw = {x: self[x] for x in self.attributes()} - g = cls(**kw) - - # Nodes and node attributes - for i, v in enumerate(self.vs): - # TODO: use _nx_name if the attribute is present so we can achieve - # a lossless round-trip in terms of vertex names - g.add_node(i, **v.attributes()) - - # Edges and edge attributes - for edge in self.es: - g.add_edge(edge.source, edge.target, **edge.attributes()) - - return g - - @classmethod - def from_networkx(cls, g): - """Converts the graph from networkx - - Vertex names will be converted to "_nx_name" attribute and the vertices - will get new ids from 0 up (as standard in igraph). - - @param g: networkx Graph or DiGraph - """ - # Graph attributes - gattr = dict(g.graph) - - # Nodes - vnames = list(g.nodes) - vattr = {"_nx_name": vnames} - vcount = len(vnames) - vd = {v: i for i, v in enumerate(vnames)} - - # NOTE: we do not need a special class for multigraphs, it is taken - # care for at the edge level rather than at the graph level. - graph = cls( - n=vcount, directed=g.is_directed(), graph_attrs=gattr, vertex_attrs=vattr - ) - - # Node attributes - for v, datum in g.nodes.data(): - for key, val in list(datum.items()): - graph.vs[vd[v]][key] = val - - # Edges and edge attributes - eattr_names = {name for (_, _, data) in g.edges.data() for name in data} - eattr = {name: [] for name in eattr_names} - edges = [] - for (u, v, data) in g.edges.data(): - edges.append((vd[u], vd[v])) - for name in eattr_names: - eattr[name].append(data.get(name)) - - graph.add_edges(edges, eattr) - - return graph - - def to_graph_tool( - self, graph_attributes=None, vertex_attributes=None, edge_attributes=None - ): - """Converts the graph to graph-tool - - Data types: graph-tool only accepts specific data types. See the - following web page for a list: - - https://graph-tool.skewed.de/static/doc/quickstart.html - - Note: because of the restricted data types in graph-tool, vertex and - edge attributes require to be type-consistent across all vertices or - edges. If you set the property for only some vertices/edges, the other - will be tagged as None in python-igraph, so they can only be converted - to graph-tool with the type 'object' and any other conversion will - fail. - - @param graph_attributes: dictionary of graph attributes to transfer. - Keys are attributes from the graph, values are data types (see - below). C{None} means no graph attributes are transferred. - @param vertex_attributes: dictionary of vertex attributes to transfer. - Keys are attributes from the vertices, values are data types (see - below). C{None} means no vertex attributes are transferred. - @param edge_attributes: dictionary of edge attributes to transfer. - Keys are attributes from the edges, values are data types (see - below). C{None} means no vertex attributes are transferred. - """ - import graph_tool as gt - - # Graph - g = gt.Graph(directed=self.is_directed()) - - # Nodes - vc = self.vcount() - g.add_vertex(vc) - - # Graph attributes - if graph_attributes is not None: - for x, dtype in list(graph_attributes.items()): - # Strange syntax for setting internal properties - gprop = g.new_graph_property(str(dtype)) - g.graph_properties[x] = gprop - g.graph_properties[x] = self[x] - - # Vertex attributes - if vertex_attributes is not None: - for x, dtype in list(vertex_attributes.items()): - # Create a new vertex property - g.vertex_properties[x] = g.new_vertex_property(str(dtype)) - # Fill the values from the igraph.Graph - for i in range(vc): - g.vertex_properties[x][g.vertex(i)] = self.vs[i][x] - - # Edges and edge attributes - if edge_attributes is not None: - for x, dtype in list(edge_attributes.items()): - g.edge_properties[x] = g.new_edge_property(str(dtype)) - for edge in self.es: - e = g.add_edge(edge.source, edge.target) - if edge_attributes is not None: - for x, dtype in list(edge_attributes.items()): - prop = edge.attributes().get(x, None) - g.edge_properties[x][e] = prop - - return g - - @classmethod - def from_graph_tool(cls, g): - """Converts the graph from graph-tool - - @param g: graph-tool Graph - """ - # Graph attributes - gattr = dict(g.graph_properties) - - # Nodes - vcount = g.num_vertices() - - # Graph - graph = cls(n=vcount, directed=g.is_directed(), graph_attrs=gattr) - - # Node attributes - for key, val in g.vertex_properties.items(): - prop = val.get_array() - for i in range(vcount): - graph.vs[i][key] = prop[i] - - # Edges and edge attributes - # NOTE: graph-tool is quite strongly typed, so each property is always - # defined for all edges, using default values for the type. E.g. for a - # string property/attribute the missing edges get an empty string. - edges = [] - eattr_names = list(g.edge_properties) - eattr = {name: [] for name in eattr_names} - for e in g.edges(): - edges.append((int(e.source()), int(e.target()))) - for name, attr_map in g.edge_properties.items(): - eattr[name].append(attr_map[e]) - - graph.add_edges(edges, eattr) - - return graph - - def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds): - """Writes the adjacency matrix of the graph to the given file - - All the remaining arguments not mentioned here are passed intact - to L{Graph.get_adjacency}. - - @param f: the name of the file to be written. - @param sep: the string that separates the matrix elements in a row - @param eol: the string that separates the rows of the matrix. Please - note that igraph is able to read back the written adjacency matrix - if and only if this is a single newline character - """ - if isinstance(f, str): - f = open(f, "w") - matrix = self.get_adjacency(*args, **kwds) - for row in matrix: - f.write(sep.join(map(str, row))) - f.write(eol) - f.close() - - @classmethod - def Read_Adjacency( - cls, f, sep=None, comment_char="#", attribute=None, *args, **kwds - ): - """Constructs a graph based on an adjacency matrix from the given file. - - Additional positional and keyword arguments not mentioned here are - passed intact to L{Adjacency}. - - @param f: the name of the file to be read or a file object - @param sep: the string that separates the matrix elements in a row. - C{None} means an arbitrary sequence of whitespace characters. - @param comment_char: lines starting with this string are treated - as comments. - @param attribute: an edge attribute name where the edge weights are - stored in the case of a weighted adjacency matrix. If C{None}, - no weights are stored, values larger than 1 are considered as - edge multiplicities. - @return: the created graph""" - if isinstance(f, str): - f = open(f) - - matrix, ri = [], 0 - for line in f: - line = line.strip() - if len(line) == 0: - continue - if line.startswith(comment_char): - continue - row = [float(x) for x in line.split(sep)] - matrix.append(row) - ri += 1 - - f.close() - - if attribute is None: - graph = cls.Adjacency(matrix, *args, **kwds) - else: - kwds["attr"] = attribute - graph = cls.Weighted_Adjacency(matrix, *args, **kwds) - - return graph - - @classmethod - def Adjacency(cls, matrix, mode="directed", *args, **kwargs): - """Generates a graph from its adjacency matrix. - - @param matrix: the adjacency matrix. Possible types are: - - a list of lists - - a numpy 2D array or matrix (will be converted to list of lists) - - a scipy.sparse matrix (will be converted to a COO matrix, but not - to a dense matrix) - @param mode: the mode to be used. Possible values are: - - C{"directed"} - the graph will be directed and a matrix - element gives the number of edges between two vertex. - - C{"undirected"} - alias to C{"max"} for convenience. - - C{"max"} - undirected graph will be created and the number of - edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} - - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} - - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} - - C{"upper"} - undirected graph with the upper right triangle of - the matrix (including the diagonal) - - C{"lower"} - undirected graph with the lower left triangle of - the matrix (including the diagonal) - """ - try: - import numpy as np - except ImportError: - np = None - - try: - from scipy import sparse - except ImportError: - sparse = None - - if (sparse is not None) and isinstance(matrix, sparse.spmatrix): - return _graph_from_sparse_matrix(cls, matrix, mode=mode) - - if (np is not None) and isinstance(matrix, np.ndarray): - matrix = matrix.tolist() - - return super().Adjacency(matrix, mode=mode) + # Graph libraries + from_networkx = classmethod(_construct_graph_from_networkx) + to_networkx = _export_graph_to_networkx - @classmethod - def Weighted_Adjacency(cls, matrix, mode="directed", attr="weight", loops=True): - """Generates a graph from its weighted adjacency matrix. - - @param matrix: the adjacency matrix. Possible types are: - - a list of lists - - a numpy 2D array or matrix (will be converted to list of lists) - - a scipy.sparse matrix (will be converted to a COO matrix, but not - to a dense matrix) - @param mode: the mode to be used. Possible values are: - - C{"directed"} - the graph will be directed and a matrix - element gives the number of edges between two vertex. - - C{"undirected"} - alias to C{"max"} for convenience. - - C{"max"} - undirected graph will be created and the number of - edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} - - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} - - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} - - C{"upper"} - undirected graph with the upper right triangle of - the matrix (including the diagonal) - - C{"lower"} - undirected graph with the lower left triangle of - the matrix (including the diagonal) - - These values can also be given as strings without the C{ADJ} prefix. - @param attr: the name of the edge attribute that stores the edge - weights. - @param loops: whether to include loop edges. When C{False}, the diagonal - of the adjacency matrix will be ignored. - - """ - try: - import numpy as np - except ImportError: - np = None - - try: - from scipy import sparse - except ImportError: - sparse = None - - if sparse is not None and isinstance(matrix, sparse.spmatrix): - return _graph_from_weighted_sparse_matrix( - cls, - matrix, - mode=mode, - attr=attr, - loops=loops, - ) - - if np is not None and isinstance(matrix, np.ndarray): - matrix = matrix.tolist() + from_graph_tool = classmethod(_construct_graph_from_graph_tool) + to_graph_tool = _export_graph_to_graph_tool - return super().Weighted_Adjacency( - matrix, - mode=mode, - attr=attr, - loops=loops, - ) - - def write_dimacs(self, f, source=None, target=None, capacity="capacity"): - """Writes the graph in DIMACS format to the given file. - - @param f: the name of the file to be written or a Python file handle. - @param source: the source vertex ID. If C{None}, igraph will try to - infer it from the C{source} graph attribute. - @param target: the target vertex ID. If C{None}, igraph will try to - infer it from the C{target} graph attribute. - @param capacity: the capacities of the edges in a list or the name of - an edge attribute that holds the capacities. If there is no such - edge attribute, every edge will have a capacity of 1. - """ - if source is None: - try: - source = self["source"] - except KeyError: - raise ValueError( - "source vertex must be provided in the 'source' graph " - "attribute or in the 'source' argument of write_dimacs()" - ) - - if target is None: - try: - target = self["target"] - except KeyError: - raise ValueError( - "target vertex must be provided in the 'target' graph " - "attribute or in the 'target' argument of write_dimacs()" - ) + # Files + Read_DIMACS = classmethod(_construct_graph_from_dimacs_file) + write_dimacs = _write_graph_to_dimacs_file - if isinstance(capacity, str) and capacity not in self.edge_attributes(): - warn("'%s' edge attribute does not exist" % capacity) - capacity = [1] * self.ecount() + Read_GraphMLz = classmethod(_construct_graph_from_graphmlz_file) + write_graphmlz = _write_graph_to_graphmlz_file - return GraphBase.write_dimacs(self, f, source, target, capacity) + Read_Pickle = classmethod(_construct_graph_from_pickle_file) + write_pickle = _write_graph_to_pickle_file - def write_graphmlz(self, f, compresslevel=9): - """Writes the graph to a zipped GraphML file. + Read_Picklez = classmethod(_construct_graph_from_picklez_file) + write_picklez = _write_graph_to_picklez_file - The library uses the gzip compression algorithm, so the resulting - file can be unzipped with regular gzip uncompression (like - C{gunzip} or C{zcat} from Unix command line) or the Python C{gzip} - module. - - Uses a temporary file to store intermediate GraphML data, so - make sure you have enough free space to store the unzipped - GraphML file as well. - - @param f: the name of the file to be written. - @param compresslevel: the level of compression. 1 is fastest and - produces the least compression, and 9 is slowest and produces - the most compression.""" - with named_temporary_file() as tmpfile: - self.write_graphml(tmpfile) - outf = gzip.GzipFile(f, "wb", compresslevel) - copyfileobj(open(tmpfile, "rb"), outf) - outf.close() - - @classmethod - def Read_DIMACS(cls, f, directed=False): - """Reads a graph from a file conforming to the DIMACS minimum-cost flow - file format. - - For the exact definition of the format, see - U{http://lpsolve.sourceforge.net/5.5/DIMACS.htm}. - - Restrictions compared to the official description of the format are - as follows: - - - igraph's DIMACS reader requires only three fields in an arc - definition, describing the edge's source and target node and - its capacity. - - Source vertices are identified by 's' in the FLOW field, target - vertices are identified by 't'. - - Node indices start from 1. Only a single source and target node - is allowed. - - @param f: the name of the file or a Python file handle - @param directed: whether the generated graph should be directed. - @return: the generated graph. The indices of the source and target - vertices are attached as graph attributes C{source} and C{target}, - the edge capacities are stored in the C{capacity} edge attribute. - """ - graph, source, target, cap = super().Read_DIMACS(f, directed) - graph.es["capacity"] = cap - graph["source"] = source - graph["target"] = target - return graph - - @classmethod - def Read_GraphMLz(cls, f, directed=True, index=0): - """Reads a graph from a zipped GraphML file. - - @param f: the name of the file - @param index: if the GraphML file contains multiple graphs, - specified the one that should be loaded. Graph indices - start from zero, so if you want to load the first graph, - specify 0 here. - @return: the loaded graph object""" - with named_temporary_file() as tmpfile: - with open(tmpfile, "wb") as outf: - copyfileobj(gzip.GzipFile(f, "rb"), outf) - return cls.Read_GraphML(tmpfile, directed=directed, index=index) - - def write_pickle(self, fname=None, version=-1): - """Saves the graph in Python pickled format - - @param fname: the name of the file or a stream to save to. If - C{None}, saves the graph to a string and returns the string. - @param version: pickle protocol version to be used. If -1, uses - the highest protocol available - @return: C{None} if the graph was saved successfully to the - given file, or a string if C{fname} was C{None}. - """ - import pickle as pickle - - if fname is None: - return pickle.dumps(self, version) - if not hasattr(fname, "write"): - file_was_opened = True - fname = open(fname, "wb") - else: - file_was_opened = False - result = pickle.dump(self, fname, version) - if file_was_opened: - fname.close() - return result - - def write_picklez(self, fname=None, version=-1): - """Saves the graph in Python pickled format, compressed with - gzip. - - Saving in this format is a bit slower than saving in a Python pickle - without compression, but the final file takes up much less space on - the hard drive. - - @param fname: the name of the file or a stream to save to. - @param version: pickle protocol version to be used. If -1, uses - the highest protocol available - @return: C{None} if the graph was saved successfully to the - given file. - """ - import pickle as pickle - - file_was_opened = False - - if not hasattr(fname, "write"): - file_was_opened = True - fname = gzip.open(fname, "wb") - elif not isinstance(fname, gzip.GzipFile): - file_was_opened = True - fname = gzip.GzipFile(mode="wb", fileobj=fname) - - result = pickle.dump(self, fname, version) - - if file_was_opened: - fname.close() - - return result - - @classmethod - def Read_Pickle(cls, fname=None): - """Reads a graph from Python pickled format - - @param fname: the name of the file, a stream to read from, or - a string containing the pickled data. - @return: the created graph object. - """ - import pickle as pickle - - if hasattr(fname, "read"): - # Probably a file or a file-like object - result = pickle.load(fname) - else: - try: - fp = open(fname, "rb") - except UnicodeDecodeError: - try: - # We are on Python 3.6 or above and we are passing a pickled - # stream that cannot be decoded as Unicode. Try unpickling - # directly. - result = pickle.loads(fname) - except TypeError: - raise IOError( - "Cannot load file. If fname is a file name, that " - "filename may be incorrect." - ) - except IOError: - try: - # No file with the given name, try unpickling directly. - result = pickle.loads(fname) - except TypeError: - raise IOError( - "Cannot load file. If fname is a file name, that " - "filename may be incorrect." - ) - else: - result = pickle.load(fp) - fp.close() - - if not isinstance(result, cls): - raise TypeError("unpickled object is not a %s" % cls.__name__) - - return result - - @classmethod - def Read_Picklez(cls, fname): - """Reads a graph from compressed Python pickled format, uncompressing - it on-the-fly. - - @param fname: the name of the file or a stream to read from. - @return: the created graph object. - """ - import pickle as pickle - - if hasattr(fname, "read"): - # Probably a file or a file-like object - if isinstance(fname, gzip.GzipFile): - result = pickle.load(fname) - else: - result = pickle.load(gzip.GzipFile(mode="rb", fileobj=fname)) - else: - result = pickle.load(gzip.open(fname, "rb")) - - if not isinstance(result, cls): - raise TypeError("unpickled object is not a %s" % cls.__name__) - - return result - - def write_svg( - self, - fname, - layout="auto", - width=None, - height=None, - labels="label", - colors="color", - shapes="shape", - vertex_size=10, - edge_colors="color", - edge_stroke_widths="width", - font_size=16, - *args, - **kwds, - ): - """Saves the graph as an SVG (Scalable Vector Graphics) file - - The file will be Inkscape (http://inkscape.org) compatible. - In Inkscape, as nodes are rearranged, the edges auto-update. - - @param fname: the name of the file or a Python file handle - @param layout: the layout of the graph. Can be either an - explicitly specified layout (using a list of coordinate - pairs) or the name of a layout algorithm (which should - refer to a method in the L{Graph} object, but without - the C{layout_} prefix. - @param width: the preferred width in pixels (default: 400) - @param height: the preferred height in pixels (default: 400) - @param labels: the vertex labels. Either it is the name of - a vertex attribute to use, or a list explicitly specifying - the labels. It can also be C{None}. - @param colors: the vertex colors. Either it is the name of - a vertex attribute to use, or a list explicitly specifying - the colors. A color can be anything acceptable in an SVG - file. - @param shapes: the vertex shapes. Either it is the name of - a vertex attribute to use, or a list explicitly specifying - the shapes as integers. Shape 0 means hidden (nothing is drawn), - shape 1 is a circle, shape 2 is a rectangle and shape 3 is a - rectangle that automatically sizes to the inner text. - @param vertex_size: vertex size in pixels - @param edge_colors: the edge colors. Either it is the name - of an edge attribute to use, or a list explicitly specifying - the colors. A color can be anything acceptable in an SVG - file. - @param edge_stroke_widths: the stroke widths of the edges. Either - it is the name of an edge attribute to use, or a list explicitly - specifying the stroke widths. The stroke width can be anything - acceptable in an SVG file. - @param font_size: font size. If it is a string, it is written into - the SVG file as-is (so you can specify anything which is valid - as the value of the C{font-size} style). If it is a number, it - is interpreted as pixel size and converted to the proper attribute - value accordingly. - """ - if width is None and height is None: - width = 400 - height = 400 - elif width is None: - width = height - elif height is None: - height = width - - if width <= 0 or height <= 0: - raise ValueError("width and height must be positive") - - if isinstance(layout, str): - layout = self.layout(layout, *args, **kwds) - - if isinstance(labels, str): - try: - labels = self.vs.get_attribute_values(labels) - except KeyError: - labels = [x + 1 for x in range(self.vcount())] - elif labels is None: - labels = [""] * self.vcount() - - if isinstance(colors, str): - try: - colors = self.vs.get_attribute_values(colors) - except KeyError: - colors = ["red"] * self.vcount() - - if isinstance(shapes, str): - try: - shapes = self.vs.get_attribute_values(shapes) - except KeyError: - shapes = [1] * self.vcount() - - if isinstance(edge_colors, str): - try: - edge_colors = self.es.get_attribute_values(edge_colors) - except KeyError: - edge_colors = ["black"] * self.ecount() - - if isinstance(edge_stroke_widths, str): - try: - edge_stroke_widths = self.es.get_attribute_values(edge_stroke_widths) - except KeyError: - edge_stroke_widths = [2] * self.ecount() - - if not isinstance(font_size, str): - font_size = "%spx" % str(font_size) - else: - if ";" in font_size: - raise ValueError("font size can't contain a semicolon") - - vcount = self.vcount() - labels.extend(str(i + 1) for i in range(len(labels), vcount)) - colors.extend(["red"] * (vcount - len(colors))) - - if isinstance(fname, str): - f = open(fname, "w") - our_file = True - else: - f = fname - our_file = False - - bbox = BoundingBox(layout.bounding_box()) - - sizes = [width - 2 * vertex_size, height - 2 * vertex_size] - w, h = bbox.width, bbox.height - - ratios = [] - if w == 0: - ratios.append(1.0) - else: - ratios.append(sizes[0] / w) - if h == 0: - ratios.append(1.0) - else: - ratios.append(sizes[1] / h) - - layout = [ - [ - (row[0] - bbox.left) * ratios[0] + vertex_size, - (row[1] - bbox.top) * ratios[1] + vertex_size, - ] - for row in layout - ] - - directed = self.is_directed() - - print('', file=f) - print( - "", - file=f, - ) - print(file=f) - print( - ''.format(width, height), end=" ", file=f) - - edge_color_dict = {} - print('', file=f) - for e_col in set(edge_colors): - if e_col == "#000000": - marker_index = "" - else: - marker_index = str(len(edge_color_dict)) - # Print an arrow marker for each possible line color - # This is a copy of Inkscape's standard Arrow 2 marker - print("', file=f) - print(" ', file=f) - print("", file=f) - - edge_color_dict[e_col] = "Arrow2Lend{0}".format(marker_index) - print("", file=f) - print( - '', - file=f, - ) - - for eidx, edge in enumerate(self.es): - vidxs = edge.tuple - x1 = layout[vidxs[0]][0] - y1 = layout[vidxs[0]][1] - x2 = layout[vidxs[1]][0] - y2 = layout[vidxs[1]][1] - angle = math.atan2(y2 - y1, x2 - x1) - x2 = x2 - vertex_size * math.cos(angle) - y2 = y2 - vertex_size * math.sin(angle) - - print("', file=f) - - print(" ", file=f) - print(file=f) - - print( - ' ', - file=f, - ) - print(" ", file=f) - - if any(x == 3 for x in shapes): - # Only import tkFont if we really need it. Unfortunately, this will - # flash up an unneccesary Tk window in some cases - import tkinter.font - import tkinter as tk - - # This allows us to dynamically size the width of the nodes. - # Unfortunately this works only with font sizes specified in pixels. - if font_size.endswith("px"): - font_size_in_pixels = int(font_size[:-2]) - else: - try: - font_size_in_pixels = int(font_size) - except Exception: - raise ValueError( - "font sizes must be specified in pixels " - "when any of the nodes has shape=3 (i.e. " - "node size determined by text size)" - ) - tk_window = tk.Tk() - font = tkinter.font.Font( - root=tk_window, font=("Sans", font_size_in_pixels, tkinter.font.NORMAL) - ) - else: - tk_window = None - - for vidx in range(self.vcount()): - print( - ' '.format( - vidx, layout[vidx][0], layout[vidx][1] - ), - file=f, - ) - if shapes[vidx] == 1: - # Undocumented feature: can handle two colors but only for circles - c = str(colors[vidx]) - if " " in c: - c = c.split(" ") - vs = str(vertex_size) - print( - ' '.format( - vs, c[0] - ), - file=f, - ) - print( - ' '.format( - vs, c[1] - ), - file=f, - ) - print( - ' '.format(vs), - file=f, - ) - else: - print( - ' '.format( - str(vertex_size), str(colors[vidx]) - ), - file=f, - ) - elif shapes[vidx] == 2: - print( - ' '.format( - vertex_size, vertex_size * 2, vidx, colors[vidx] - ), - file=f, - ) - elif shapes[vidx] == 3: - (vertex_width, vertex_height) = ( - font.measure(str(labels[vidx])) + 2, - font.metrics("linespace") + 2, - ) - print( - ' ".format( - vertex_width / 2.0, - vertex_height / 2.0, - vertex_width, - vertex_height, - vidx, - colors[vidx], - ), - file=f, - ) - - print( - ' '.format(vertex_size / 2.0, vidx, font_size), - file=f, - ) - print( - '' - "{2}".format(vertex_size / 2.0, vidx, str(labels[vidx])), - file=f, - ) - print(" ", file=f) - - print("", file=f) - print(file=f) - print("", file=f) - - if our_file: - f.close() - if tk_window: - tk_window.destroy() - - @classmethod - def _identify_format(cls, filename): - """_identify_format(filename) - - Tries to identify the format of the graph stored in the file with the - given filename. It identifies most file formats based on the extension - of the file (and not on syntactic evaluation). The only exception is - the adjacency matrix format and the edge list format: the first few - lines of the file are evaluated to decide between the two. - - @note: Internal function, should not be called directly. - - @param filename: the name of the file or a file object whose C{name} - attribute is set. - @return: the format of the file as a string. - """ - import os.path - - if hasattr(filename, "name") and hasattr(filename, "read"): - # It is most likely a file - try: - filename = filename.name - except Exception: - return None - - root, ext = os.path.splitext(filename) - ext = ext.lower() - - if ext == ".gz": - _, ext2 = os.path.splitext(root) - ext2 = ext2.lower() - if ext2 == ".pickle": - return "picklez" - elif ext2 == ".graphml": - return "graphmlz" - - if ext in [ - ".graphml", - ".graphmlz", - ".lgl", - ".ncol", - ".pajek", - ".gml", - ".dimacs", - ".edgelist", - ".edges", - ".edge", - ".net", - ".pickle", - ".picklez", - ".dot", - ".gw", - ".lgr", - ".dl", - ]: - return ext[1:] - - if ext == ".txt" or ext == ".dat": - # Most probably an adjacency matrix or an edge list - f = open(filename, "r") - line = f.readline() - if line is None: - return "edges" - parts = line.strip().split() - if len(parts) == 2: - line = f.readline() - if line is None: - return "edges" - parts = line.strip().split() - if len(parts) == 2: - line = f.readline() - if line is None: - # This is a 2x2 matrix, it can be a matrix or an edge - # list as well and we cannot decide - return None - else: - parts = line.strip().split() - if len(parts) == 0: - return None - return "edges" - else: - # Not a matrix - return None - else: - return "adjacency" - - @classmethod - def Read(cls, f, format=None, *args, **kwds): - """Unified reading function for graphs. - - This method tries to identify the format of the graph given in - the first parameter and calls the corresponding reader method. - - The remaining arguments are passed to the reader method without - any changes. - - @param f: the file containing the graph to be loaded - @param format: the format of the file (if known in advance). - C{None} means auto-detection. Possible values are: C{"ncol"} - (NCOL format), C{"lgl"} (LGL format), C{"graphdb"} (GraphDB - format), C{"graphml"}, C{"graphmlz"} (GraphML and gzipped - GraphML format), C{"gml"} (GML format), C{"net"}, C{"pajek"} - (Pajek format), C{"dimacs"} (DIMACS format), C{"edgelist"}, - C{"edges"} or C{"edge"} (edge list), C{"adjacency"} - (adjacency matrix), C{"dl"} (DL format used by UCINET), - C{"pickle"} (Python pickled format), - C{"picklez"} (gzipped Python pickled format) - @raises IOError: if the file format can't be identified and - none was given. - """ - if format is None: - format = cls._identify_format(f) - try: - reader = cls._format_mapping[format][0] - except (KeyError, IndexError): - raise IOError("unknown file format: %s" % str(format)) - if reader is None: - raise IOError("no reader method for file format: %s" % str(format)) - reader = getattr(cls, reader) - return reader(f, *args, **kwds) + Read_Adjacency = classmethod(_construct_graph_from_adjacency_file) + write_adjacency = _write_graph_to_adjacency_file + Read = classmethod(_construct_graph_from_file) Load = Read + write = _write_graph_to_file + save = write - def write(self, f, format=None, *args, **kwds): - """Unified writing function for graphs. - - This method tries to identify the format of the graph given in - the first parameter (based on extension) and calls the corresponding - writer method. - - The remaining arguments are passed to the writer method without - any changes. - - @param f: the file containing the graph to be saved - @param format: the format of the file (if one wants to override the - format determined from the filename extension, or the filename itself - is a stream). C{None} means auto-detection. Possible values are: - - - C{"adjacency"}: adjacency matrix format - - - C{"dimacs"}: DIMACS format + # Various objects + # list of dict representation of graphs + DictList = classmethod(_construct_graph_from_dict_list) + to_dict_list = _export_graph_to_dict_list - - C{"dot"}, C{"graphviz"}: GraphViz DOT format + # tuple-like representation of graphs + TupleList = classmethod(_construct_graph_from_tuple_list) + to_tuple_list = _export_graph_to_tuple_list - - C{"edgelist"}, C{"edges"} or C{"edge"}: numeric edge list format + # dict of sequence representation of graphs + ListDict = classmethod(_construct_graph_from_list_dict) + to_list_dict = _export_graph_to_list_dict - - C{"gml"}: GML format + # dict of dicts representation of graphs + DictDict = classmethod(_construct_graph_from_dict_dict) + to_dict_dict = _export_graph_to_dict_dict - - C{"graphml"} and C{"graphmlz"}: standard and gzipped GraphML - format + # adjacency matrix + Adjacency = classmethod(_construct_graph_from_adjacency) - - C{"gw"}, C{"leda"}, C{"lgr"}: LEDA native format + Weighted_Adjacency = classmethod(_construct_graph_from_weighted_adjacency) - - C{"lgl"}: LGL format + # pandas dataframe(s) + DataFrame = classmethod(_construct_graph_from_dataframe) - - C{"ncol"}: NCOL format + get_vertex_dataframe = _export_vertex_dataframe - - C{"net"}, C{"pajek"}: Pajek format + get_edge_dataframe = _export_edge_dataframe - - C{"pickle"}, C{"picklez"}: standard and gzipped Python pickled - format + # Bipartite graphs + Bipartite = classmethod(_construct_bipartite_graph) - - C{"svg"}: SVG format + Incidence = classmethod(_construct_incidence_bipartite_graph) - @raises IOError: if the file format can't be identified and - none was given. - """ - if format is None: - format = self._identify_format(f) - try: - writer = self._format_mapping[format][1] - except (KeyError, IndexError): - raise IOError("unknown file format: %s" % str(format)) - if writer is None: - raise IOError("no writer method for file format: %s" % str(format)) - writer = getattr(self, writer) - return writer(f, *args, **kwds) + Full_Bipartite = classmethod(_construct_full_bipartite_graph) - save = write + Random_Bipartite = classmethod(_construct_random_bipartite_graph) - ##################################################### - # Constructor for dict-like representation of graphs + # Other constructors + GRG = classmethod(_construct_random_geometric_graph) - @classmethod - def DictList( - cls, - vertices, - edges, - directed=False, - vertex_name_attr="name", - edge_foreign_keys=("source", "target"), - iterative=False, - ): - """Constructs a graph from a list-of-dictionaries representation. - - This representation assumes that vertices and edges are encoded in - two lists, each list containing a Python dict for each vertex and - each edge, respectively. A distinguished element of the vertex dicts - contain a vertex ID which is used in the edge dicts to refer to - source and target vertices. All the remaining elements of the dict - are considered vertex and edge attributes. Note that the implementation - does not assume that the objects passed to this method are indeed - lists of dicts, but they should be iterable and they should yield - objects that behave as dicts. So, for instance, a database query - result is likely to be fit as long as it's iterable and yields - dict-like objects with every iteration. - - @param vertices: the data source for the vertices or C{None} if - there are no special attributes assigned to vertices and we - should simply use the edge list of dicts to infer vertex names. - @param edges: the data source for the edges. - @param directed: whether the constructed graph will be directed - @param vertex_name_attr: the name of the distinguished key in the - dicts in the vertex data source that contains the vertex names. - Ignored if C{vertices} is C{None}. - @param edge_foreign_keys: the name of the attributes in the dicts - in the edge data source that contain the source and target - vertex names. - @param iterative: whether to add the edges to the graph one by one, - iteratively, or to build a large edge list first and use that to - construct the graph. The latter approach is faster but it may - not be suitable if your dataset is large. The default is to - add the edges in a batch from an edge list. - @return: the graph that was constructed - """ - - def create_list_from_indices(indices, n): - result = [None] * n - for i, v in indices: - result[i] = v - return result - - # Construct the vertices - vertex_attrs, n = {}, 0 - if vertices: - for idx, vertex_data in enumerate(vertices): - for k, v in vertex_data.items(): - try: - vertex_attrs[k].append((idx, v)) - except KeyError: - vertex_attrs[k] = [(idx, v)] - n += 1 - for k, v in vertex_attrs.items(): - vertex_attrs[k] = create_list_from_indices(v, n) - else: - vertex_attrs[vertex_name_attr] = [] - - vertex_names = vertex_attrs[vertex_name_attr] - # Check for duplicates in vertex_names - if len(vertex_names) != len(set(vertex_names)): - raise ValueError("vertex names are not unique") - # Create a reverse mapping from vertex names to indices - vertex_name_map = UniqueIdGenerator(initial=vertex_names) - - # Construct the edges - efk_src, efk_dest = edge_foreign_keys - if iterative: - g = cls(n, [], directed, {}, vertex_attrs) - for idx, edge_data in enumerate(edges): - src_name, dst_name = edge_data[efk_src], edge_data[efk_dest] - v1 = vertex_name_map[src_name] - if v1 == n: - g.add_vertices(1) - g.vs[n][vertex_name_attr] = src_name - n += 1 - v2 = vertex_name_map[dst_name] - if v2 == n: - g.add_vertices(1) - g.vs[n][vertex_name_attr] = dst_name - n += 1 - g.add_edge(v1, v2) - for k, v in edge_data.items(): - g.es[idx][k] = v - - return g - else: - edge_list, edge_attrs, m = [], {}, 0 - for idx, edge_data in enumerate(edges): - v1 = vertex_name_map[edge_data[efk_src]] - v2 = vertex_name_map[edge_data[efk_dest]] - - edge_list.append((v1, v2)) - for k, v in edge_data.items(): - try: - edge_attrs[k].append((idx, v)) - except KeyError: - edge_attrs[k] = [(idx, v)] - m += 1 - for k, v in edge_attrs.items(): - edge_attrs[k] = create_list_from_indices(v, m) - - # It may have happened that some vertices were added during - # the process - if len(vertex_name_map) > n: - diff = len(vertex_name_map) - n - more = [None] * diff - for k, v in vertex_attrs.items(): - v.extend(more) - vertex_attrs[vertex_name_attr] = list(vertex_name_map.values()) - n = len(vertex_name_map) - - # Create the graph - return cls(n, edge_list, directed, {}, vertex_attrs, edge_attrs) - - ##################################################### - # Constructor for tuple-like representation of graphs - - @classmethod - def TupleList( - cls, - edges, - directed=False, - vertex_name_attr="name", - edge_attrs=None, - weights=False, - ): - """Constructs a graph from a list-of-tuples representation. - - This representation assumes that the edges of the graph are encoded - in a list of tuples (or lists). Each item in the list must have at least - two elements, which specify the source and the target vertices of the edge. - The remaining elements (if any) specify the edge attributes of that edge, - where the names of the edge attributes originate from the C{edge_attrs} - list. The names of the vertices will be stored in the vertex attribute - given by C{vertex_name_attr}. - - The default parameters of this function are suitable for creating - unweighted graphs from lists where each item contains the source vertex - and the target vertex. If you have a weighted graph, you can use items - where the third item contains the weight of the edge by setting - C{edge_attrs} to C{"weight"} or C{["weight"]}. If you have even more - edge attributes, add them to the end of each item in the C{edges} - list and also specify the corresponding edge attribute names in - C{edge_attrs} as a list. - - @param edges: the data source for the edges. This must be a list - where each item is a tuple (or list) containing at least two - items: the name of the source and the target vertex. Note that - names will be assigned to the C{name} vertex attribute (or another - vertex attribute if C{vertex_name_attr} is specified), even if - all the vertex names in the list are in fact numbers. - @param directed: whether the constructed graph will be directed - @param vertex_name_attr: the name of the vertex attribute that will - contain the vertex names. - @param edge_attrs: the names of the edge attributes that are filled - with the extra items in the edge list (starting from index 2, since - the first two items are the source and target vertices). C{None} - means that only the source and target vertices will be extracted - from each item. If you pass a string here, it will be wrapped in - a list for convenience. - @param weights: alternative way to specify that the graph is - weighted. If you set C{weights} to C{true} and C{edge_attrs} is - not given, it will be assumed that C{edge_attrs} is C{["weight"]} - and igraph will parse the third element from each item into an - edge weight. If you set C{weights} to a string, it will be assumed - that C{edge_attrs} contains that string only, and igraph will - store the edge weights in that attribute. - @return: the graph that was constructed - """ - if edge_attrs is None: - if not weights: - edge_attrs = () - else: - if not isinstance(weights, str): - weights = "weight" - edge_attrs = [weights] - else: - if weights: - raise ValueError( - "`weights` must be False if `edge_attrs` is " "not None" - ) - - if isinstance(edge_attrs, str): - edge_attrs = [edge_attrs] - - # Set up a vertex ID generator - idgen = UniqueIdGenerator() - - # Construct the edges and the edge attributes - edge_list = [] - edge_attributes = {} - for name in edge_attrs: - edge_attributes[name] = [] - - for item in edges: - edge_list.append((idgen[item[0]], idgen[item[1]])) - for index, name in enumerate(edge_attrs, 2): - try: - edge_attributes[name].append(item[index]) - except IndexError: - edge_attributes[name].append(None) - - # Set up the "name" vertex attribute - vertex_attributes = {} - vertex_attributes[vertex_name_attr] = list(idgen.values()) - n = len(idgen) - - # Construct the graph - return cls(n, edge_list, directed, {}, vertex_attributes, edge_attributes) - - ################################# - # Constructor for graph formulae + # Graph formulae Formula = classmethod(construct_graph_from_formula) ########################### @@ -3225,390 +2002,6 @@ def es(self): """The edge sequence of the graph""" return EdgeSeq(self) - ############################################# - # Friendlier interface for bipartite methods - - @classmethod - def Bipartite(cls, types, edges, directed=False, *args, **kwds): - """Creates a bipartite graph with the given vertex types and edges. - This is similar to the default constructor of the graph, the - only difference is that it checks whether all the edges go - between the two vertex classes and it assigns the type vector - to a C{type} attribute afterwards. - - Examples: - - >>> g = Graph.Bipartite([0, 1, 0, 1], [(0, 1), (2, 3), (0, 3)]) - >>> g.is_bipartite() - True - >>> g.vs["type"] - [False, True, False, True] - - @param types: the vertex types as a boolean list. Anything that - evaluates to C{False} will denote a vertex of the first kind, - anything that evaluates to C{True} will denote a vertex of the - second kind. - @param edges: the edges as a list of tuples. - @param directed: whether to create a directed graph. Bipartite - networks are usually undirected, so the default is C{False} - - @return: the graph with a binary vertex attribute named C{"type"} that - stores the vertex classes. - """ - result = cls._Bipartite(types, edges, directed, *args, **kwds) - result.vs["type"] = [bool(x) for x in types] - return result - - @classmethod - def Full_Bipartite(cls, n1, n2, directed=False, mode="all", *args, **kwds): - """Generates a full bipartite graph (directed or undirected, with or - without loops). - - >>> g = Graph.Full_Bipartite(2, 3) - >>> g.is_bipartite() - True - >>> g.vs["type"] - [False, False, True, True, True] - - @param n1: the number of vertices of the first kind. - @param n2: the number of vertices of the second kind. - @param directed: whether tp generate a directed graph. - @param mode: if C{"out"}, then all vertices of the first kind are - connected to the others; C{"in"} specifies the opposite direction, - C{"all"} creates mutual edges. Ignored for undirected graphs. - - @return: the graph with a binary vertex attribute named C{"type"} that - stores the vertex classes. - """ - result, types = cls._Full_Bipartite(n1, n2, directed, mode, *args, **kwds) - result.vs["type"] = types - return result - - @classmethod - def Random_Bipartite( - cls, n1, n2, p=None, m=None, directed=False, neimode="all", *args, **kwds - ): - """Generates a random bipartite graph with the given number of vertices and - edges (if m is given), or with the given number of vertices and the given - connection probability (if p is given). - - If m is given but p is not, the generated graph will have n1 vertices of - type 1, n2 vertices of type 2 and m randomly selected edges between them. If - p is given but m is not, the generated graph will have n1 vertices of type 1 - and n2 vertices of type 2, and each edge will exist between them with - probability p. - - @param n1: the number of vertices of type 1. - @param n2: the number of vertices of type 2. - @param p: the probability of edges. If given, C{m} must be missing. - @param m: the number of edges. If given, C{p} must be missing. - @param directed: whether to generate a directed graph. - @param neimode: if the graph is directed, specifies how the edges will be - generated. If it is C{"all"}, edges will be generated in both directions - (from type 1 to type 2 and vice versa) independently. If it is C{"out"} - edges will always point from type 1 to type 2. If it is C{"in"}, edges - will always point from type 2 to type 1. This argument is ignored for - undirected graphs. - """ - if p is None: - p = -1 - if m is None: - m = -1 - result, types = cls._Random_Bipartite( - n1, n2, p, m, directed, neimode, *args, **kwds - ) - result.vs["type"] = types - return result - - @classmethod - def GRG(cls, n, radius, torus=False): - """Generates a random geometric graph. - - The algorithm drops the vertices randomly on the 2D unit square and - connects them if they are closer to each other than the given radius. - The coordinates of the vertices are stored in the vertex attributes C{x} - and C{y}. - - @param n: The number of vertices in the graph - @param radius: The given radius - @param torus: This should be C{True} if we want to use a torus instead of a - square. - """ - result, xs, ys = cls._GRG(n, radius, torus) - result.vs["x"] = xs - result.vs["y"] = ys - return result - - @classmethod - def Incidence( - cls, - matrix, - directed=False, - mode="out", - multiple=False, - weighted=None, - *args, - **kwds, - ): - """Creates a bipartite graph from an incidence matrix. - - Example: - - >>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) - - @param matrix: the incidence matrix. - @param directed: whether to create a directed graph. - @param mode: defines the direction of edges in the graph. If - C{"out"}, then edges go from vertices of the first kind - (corresponding to rows of the matrix) to vertices of the - second kind (the columns of the matrix). If C{"in"}, the - opposite direction is used. C{"all"} creates mutual edges. - Ignored for undirected graphs. - @param multiple: defines what to do with non-zero entries in the - matrix. If C{False}, non-zero entries will create an edge no matter - what the value is. If C{True}, non-zero entries are rounded up to - the nearest integer and this will be the number of multiple edges - created. - @param weighted: defines whether to create a weighted graph from the - incidence matrix. If it is c{None} then an unweighted graph is created - and the multiple argument is used to determine the edges of the graph. - If it is a string then for every non-zero matrix entry, an edge is created - and the value of the entry is added as an edge attribute named by the - weighted argument. If it is C{True} then a weighted graph is created and - the name of the edge attribute will be ‘weight’. - - @raise ValueError: if the weighted and multiple are passed together. - - @return: the graph with a binary vertex attribute named C{"type"} that - stores the vertex classes. - """ - is_weighted = True if weighted or weighted == "" else False - if is_weighted and multiple: - raise ValueError("arguments weighted and multiple can not co-exist") - result, types = cls._Incidence(matrix, directed, mode, multiple, *args, **kwds) - result.vs["type"] = types - if is_weighted: - weight_attr = "weight" if weighted is True else weighted - _, rows, _ = result.get_incidence() - num_vertices_of_first_kind = len(rows) - for edge in result.es: - source, target = edge.tuple - if source in rows: - edge[weight_attr] = matrix[source][ - target - num_vertices_of_first_kind - ] - else: - edge[weight_attr] = matrix[target][ - source - num_vertices_of_first_kind - ] - return result - - @classmethod - def DataFrame(cls, edges, directed=True, vertices=None, use_vids=True): - """Generates a graph from one or two dataframes. - - @param edges: pandas DataFrame containing edges and metadata. The first - two columns of this DataFrame contain the source and target vertices - for each edge. These indicate the vertex IDs as nonnegative integers - rather than vertex *names* unless `use_vids` is False. Further columns - may contain edge attributes. - @param directed: bool setting whether the graph is directed - @param vertices: None (default) or pandas DataFrame containing vertex - metadata. The DataFrame's index must contain the vertex IDs as a - sequence of intergers from `0` to `len(vertices) - 1`. If `use_vids` - is False, the first column must contain the unique vertex *names*. - Although vertex names are usually strings, they can be any hashable - object. All other columns will be added as vertex attributes by column - name. - @use_vids: whether to interpret the first two columns of the `edges` - argument as vertex ids (0-based integers) instead of vertex names. - If this argument is set to True and the first two columns of `edges` - are not integers, an error is thrown. - - @return: the graph - - Vertex names in either the `edges` or `vertices` arguments that are set - to NaN (not a number) will be set to the string "NA". That might lead - to unexpected behaviour: fill your NaNs with values before calling this - function to mitigate. - """ - try: - import pandas as pd - except ImportError: - raise ImportError("You should install pandas in order to use this function") - try: - import numpy as np - except: - raise ImportError("You should install numpy in order to use this function") - - if edges.shape[1] < 2: - raise ValueError("The 'edges' DataFrame must contain at least two columns") - if vertices is not None and vertices.shape[1] < 1: - raise ValueError( - "The 'vertices' DataFrame must contain at least one column" - ) - - if use_vids: - if not ( - str(edges.dtypes[0]).startswith("int") - and str(edges.dtypes[1]).startswith("int") - ): - raise TypeError( - f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}" - ) - elif (edges.iloc[:, :2] < 0).any(axis=None): - raise ValueError("Source and target IDs must not be negative") - if vertices is not None: - vertices = vertices.sort_index() - if not vertices.index.equals( - pd.RangeIndex.from_range(range(vertices.shape[0])) - ): - if not str(vertices.index.dtype).startswith("int"): - raise TypeError( - f"Vertex IDs must be 0-based integers, found type {vertices.index.dtype}" - ) - elif (vertices.index < 0).any(axis=None): - raise ValueError("Vertex IDs must not be negative") - else: - raise ValueError( - f"Vertex IDs must be an integer sequence from 0 to {vertices.shape[0] - 1}" - ) - else: - # Handle if some source and target names in 'edges' are 'NA' - if edges.iloc[:, :2].isna().any(axis=None): - warn( - "In the first two columns of 'edges' NA elements were replaced with string \"NA\"" - ) - edges = edges.copy() - edges.iloc[:, :2].fillna("NA", inplace=True) - - # Bring DataFrame(s) into same format as with 'use_vids=True' - if vertices is None: - vertices = pd.DataFrame({"name": np.unique(edges.values[:, :2])}) - - if vertices.iloc[:, 0].isna().any(): - warn( - "In the first column of 'vertices' NA elements were replaced with string \"NA\"" - ) - vertices = vertices.copy() - vertices.iloc[:, 0].fillna("NA", inplace=True) - - if vertices.iloc[:, 0].duplicated().any(): - raise ValueError("Vertex names must be unique") - - if vertices.shape[1] > 1 and "name" in vertices.columns[1:]: - raise ValueError( - "Vertex attribute conflict: DataFrame already contains column 'name'" - ) - - vertices = vertices.rename( - {vertices.columns[0]: "name"}, axis=1 - ).reset_index(drop=True) - - # Map source and target names in 'edges' to IDs - vid_map = pd.Series(vertices.index, index=vertices.iloc[:, 0]) - edges = edges.copy() - edges.iloc[:, 0] = edges.iloc[:, 0].map(vid_map) - edges.iloc[:, 1] = edges.iloc[:, 1].map(vid_map) - - # Create graph - if vertices is None: - nv = edges.iloc[:, :2].max().max() + 1 - g = Graph(n=nv, directed=directed) - else: - if not edges.iloc[:, :2].isin(vertices.index).all(axis=None): - raise ValueError( - "Some vertices in the edge DataFrame are missing from vertices DataFrame" - ) - nv = vertices.shape[0] - g = Graph(n=nv, directed=directed) - # Add vertex attributes - for col in vertices.columns: - g.vs[col] = vertices[col].tolist() - - # add edges including optional attributes - e_list = list(edges.iloc[:, :2].itertuples(index=False, name=None)) - e_attr = ( - edges.iloc[:, 2:].to_dict(orient="list") if edges.shape[1] > 2 else None - ) - g.add_edges(e_list, e_attr) - - return g - - def get_vertex_dataframe(self): - """Export vertices with attributes to pandas.DataFrame - - If you want to use vertex names as index, you can do: - - >>> from string import ascii_letters - >>> graph = Graph.GRG(25, 0.4) - >>> graph.vs["name"] = ascii_letters[:graph.vcount()] - >>> df = graph.get_vertex_dataframe() - >>> df.set_index('name', inplace=True) - - @return: a pandas.DataFrame representing vertices and their attributes. - The index uses vertex IDs, from 0 to N - 1 where N is the number of - vertices. - """ - try: - import pandas as pd - except ImportError: - raise ImportError("You should install pandas in order to use this function") - - df = pd.DataFrame( - {attr: self.vs[attr] for attr in self.vertex_attributes()}, - index=list(range(self.vcount())), - ) - df.index.name = "vertex ID" - - return df - - def get_edge_dataframe(self): - """Export edges with attributes to pandas.DataFrame - - If you want to use source and target vertex IDs as index, you can do: - - >>> from string import ascii_letters - >>> graph = Graph.GRG(25, 0.4) - >>> graph.vs["name"] = ascii_letters[:graph.vcount()] - >>> df = graph.get_edge_dataframe() - >>> df.set_index(['source', 'target'], inplace=True) - - The index will be a pandas.MultiIndex. You can use the `drop=False` - option to keep the `source` and `target` columns. - - If you want to use vertex names in the source and target columns: - - >>> df = graph.get_edge_dataframe() - >>> df_vert = graph.get_vertex_dataframe() - >>> df['source'].replace(df_vert['name'], inplace=True) - >>> df['target'].replace(df_vert['name'], inplace=True) - >>> df_vert.set_index('name', inplace=True) # Optional - - @return: a pandas.DataFrame representing edges and their attributes. - The index uses edge IDs, from 0 to M - 1 where M is the number of - edges. The first two columns of the dataframe represent the IDs of - source and target vertices for each edge. These columns have names - "source" and "target". If your edges have attributes with the same - names, they will be present in the dataframe, but not in the first - two columns. - """ - try: - import pandas as pd - except ImportError: - raise ImportError("You should install pandas in order to use this function") - - df = pd.DataFrame( - {attr: self.es[attr] for attr in self.edge_attributes()}, - index=list(range(self.ecount())), - ) - df.index.name = "edge ID" - - df.insert(0, "source", [e.source for e in self.es], allow_duplicates=True) - df.insert(1, "target", [e.target for e in self.es], allow_duplicates=True) - - return df - def bipartite_projection( self, types="type", multiplicity=True, probe1=-1, which="both" ): @@ -4189,7 +2582,6 @@ def __plot__(self, backend, context, *args, **kwds): drawer = kwds.pop( "drawer_factory", DrawerDirectory.resolve(self, backend)(context), - ) drawer.draw(self, *args, **kwds) @@ -5317,4 +3709,34 @@ def write(graph, filename, *args, **kwds): config = init_configuration() -del construct_graph_from_formula + +# Remove constructors from namespace +del ( + construct_graph_from_formula, + _construct_graph_from_graphmlz_file, + _construct_graph_from_dimacs_file, + _construct_graph_from_pickle_file, + _construct_graph_from_picklez_file, + _construct_graph_from_adjacency_file, + _construct_graph_from_file, + _construct_graph_from_dict_list, + _construct_graph_from_tuple_list, + _construct_graph_from_list_dict, + _construct_graph_from_dict_dict, + _construct_graph_from_adjacency, + _construct_graph_from_weighted_adjacency, + _construct_graph_from_dataframe, + _construct_random_geometric_graph, + _construct_bipartite_graph, + _construct_incidence_bipartite_graph, + _construct_full_bipartite_graph, + _construct_random_bipartite_graph, + _construct_graph_from_networkx, + _export_graph_to_networkx, + _construct_graph_from_graph_tool, + _export_graph_to_graph_tool, + _export_graph_to_list_dict, + _export_graph_to_dict_dict, + _export_graph_to_dict_list, + _export_graph_to_tuple_list, +) diff --git a/src/igraph/io/__init__.py b/src/igraph/io/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/igraph/io/adjacency.py b/src/igraph/io/adjacency.py new file mode 100644 index 000000000..0cb81688e --- /dev/null +++ b/src/igraph/io/adjacency.py @@ -0,0 +1,146 @@ +from igraph.sparse_matrix import ( + _graph_from_sparse_matrix, + _graph_from_weighted_sparse_matrix, +) + + +def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwargs): + """Generates a graph from its adjacency matrix. + + @param matrix: the adjacency matrix. Possible types are: + - a list of lists + - a numpy 2D array or matrix (will be converted to list of lists) + - a scipy.sparse matrix (will be converted to a COO matrix, but not + to a dense matrix) + - a pandas.DataFrame (column/row names must match, and will be used + as vertex names). + @param mode: the mode to be used. Possible values are: + - C{"directed"} - the graph will be directed and a matrix + element gives the number of edges between two vertex. + - C{"undirected"} - alias to C{"max"} for convenience. + - C{"max"} - undirected graph will be created and the number of + edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} + - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} + - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} + - C{"upper"} - undirected graph with the upper right triangle of + the matrix (including the diagonal) + - C{"lower"} - undirected graph with the lower left triangle of + the matrix (including the diagonal) + """ + # Deferred import to avoid cycles + from igraph import Graph + + try: + import numpy as np + except ImportError: + np = None + + try: + from scipy import sparse + except ImportError: + sparse = None + + try: + import pandas as pd + except ImportError: + pd = None + + if (sparse is not None) and isinstance(matrix, sparse.spmatrix): + return _graph_from_sparse_matrix(cls, matrix, mode=mode) + + if (pd is not None) and isinstance(matrix, pd.DataFrame): + vertex_names = matrix.index.tolist() + matrix = matrix.values + else: + vertex_names = None + + if (np is not None) and isinstance(matrix, np.ndarray): + matrix = matrix.tolist() + + graph = super(Graph, cls).Adjacency(matrix, mode=mode) + + # Add vertex names if present + if vertex_names is not None: + graph.vs["name"] = vertex_names + + return graph + + +def _construct_graph_from_weighted_adjacency( + cls, matrix, mode="directed", attr="weight", loops=True +): + """Generates a graph from its weighted adjacency matrix. + + @param matrix: the adjacency matrix. Possible types are: + - a list of lists + - a numpy 2D array or matrix (will be converted to list of lists) + - a scipy.sparse matrix (will be converted to a COO matrix, but not + to a dense matrix) + @param mode: the mode to be used. Possible values are: + - C{"directed"} - the graph will be directed and a matrix + element gives the number of edges between two vertex. + - C{"undirected"} - alias to C{"max"} for convenience. + - C{"max"} - undirected graph will be created and the number of + edges between vertex M{i} and M{j} is M{max(A(i,j), A(j,i))} + - C{"min"} - like C{"max"}, but with M{min(A(i,j), A(j,i))} + - C{"plus"} - like C{"max"}, but with M{A(i,j) + A(j,i)} + - C{"upper"} - undirected graph with the upper right triangle of + the matrix (including the diagonal) + - C{"lower"} - undirected graph with the lower left triangle of + the matrix (including the diagonal) + + These values can also be given as strings without the C{ADJ} prefix. + @param attr: the name of the edge attribute that stores the edge + weights. + @param loops: whether to include loop edges. When C{False}, the diagonal + of the adjacency matrix will be ignored. + + """ + # Deferred import to avoid cycles + from igraph import Graph + + try: + import numpy as np + except ImportError: + np = None + + try: + from scipy import sparse + except ImportError: + sparse = None + + try: + import pandas as pd + except ImportError: + pd = None + + if (sparse is not None) and isinstance(matrix, sparse.spmatrix): + return _graph_from_weighted_sparse_matrix( + cls, + matrix, + mode=mode, + attr=attr, + loops=loops, + ) + + if (pd is not None) and isinstance(matrix, pd.DataFrame): + vertex_names = matrix.index.tolist() + matrix = matrix.values + else: + vertex_names = None + + if (np is not None) and isinstance(matrix, np.ndarray): + matrix = matrix.tolist() + + graph = super(Graph, cls).Weighted_Adjacency( + matrix, + mode=mode, + attr=attr, + loops=loops, + ) + + # Add vertex names if present + if vertex_names is not None: + graph.vs["name"] = vertex_names + + return graph diff --git a/src/igraph/io/bipartite.py b/src/igraph/io/bipartite.py new file mode 100644 index 000000000..aa359b8f1 --- /dev/null +++ b/src/igraph/io/bipartite.py @@ -0,0 +1,152 @@ +def _construct_incidence_bipartite_graph( + cls, + matrix, + directed=False, + mode="out", + multiple=False, + weighted=None, + *args, + **kwds +): + """Creates a bipartite graph from an incidence matrix. + + Example: + + >>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) + + @param matrix: the incidence matrix. + @param directed: whether to create a directed graph. + @param mode: defines the direction of edges in the graph. If + C{"out"}, then edges go from vertices of the first kind + (corresponding to rows of the matrix) to vertices of the + second kind (the columns of the matrix). If C{"in"}, the + opposite direction is used. C{"all"} creates mutual edges. + Ignored for undirected graphs. + @param multiple: defines what to do with non-zero entries in the + matrix. If C{False}, non-zero entries will create an edge no matter + what the value is. If C{True}, non-zero entries are rounded up to + the nearest integer and this will be the number of multiple edges + created. + @param weighted: defines whether to create a weighted graph from the + incidence matrix. If it is c{None} then an unweighted graph is created + and the multiple argument is used to determine the edges of the graph. + If it is a string then for every non-zero matrix entry, an edge is created + and the value of the entry is added as an edge attribute named by the + weighted argument. If it is C{True} then a weighted graph is created and + the name of the edge attribute will be ‘weight’. + + @raise ValueError: if the weighted and multiple are passed together. + + @return: the graph with a binary vertex attribute named C{"type"} that + stores the vertex classes. + """ + is_weighted = True if weighted or weighted == "" else False + if is_weighted and multiple: + raise ValueError("arguments weighted and multiple can not co-exist") + result, types = cls._Incidence(matrix, directed, mode, multiple, *args, **kwds) + result.vs["type"] = types + if is_weighted: + weight_attr = "weight" if weighted is True else weighted + _, rows, _ = result.get_incidence() + num_vertices_of_first_kind = len(rows) + for edge in result.es: + source, target = edge.tuple + if source in rows: + edge[weight_attr] = matrix[source][target - num_vertices_of_first_kind] + else: + edge[weight_attr] = matrix[target][source - num_vertices_of_first_kind] + return result + + +def _construct_bipartite_graph(cls, types, edges, directed=False, *args, **kwds): + """Creates a bipartite graph with the given vertex types and edges. + This is similar to the default constructor of the graph, the + only difference is that it checks whether all the edges go + between the two vertex classes and it assigns the type vector + to a C{type} attribute afterwards. + + Examples: + + >>> g = Graph.Bipartite([0, 1, 0, 1], [(0, 1), (2, 3), (0, 3)]) + >>> g.is_bipartite() + True + >>> g.vs["type"] + [False, True, False, True] + + @param types: the vertex types as a boolean list. Anything that + evaluates to C{False} will denote a vertex of the first kind, + anything that evaluates to C{True} will denote a vertex of the + second kind. + @param edges: the edges as a list of tuples. + @param directed: whether to create a directed graph. Bipartite + networks are usually undirected, so the default is C{False} + + @return: the graph with a binary vertex attribute named C{"type"} that + stores the vertex classes. + """ + result = cls._Bipartite(types, edges, directed, *args, **kwds) + result.vs["type"] = [bool(x) for x in types] + return result + + +def _construct_full_bipartite_graph( + cls, n1, n2, directed=False, mode="all", *args, **kwds +): + """Generates a full bipartite graph (directed or undirected, with or + without loops). + + >>> g = Graph.Full_Bipartite(2, 3) + >>> g.is_bipartite() + True + >>> g.vs["type"] + [False, False, True, True, True] + + @param n1: the number of vertices of the first kind. + @param n2: the number of vertices of the second kind. + @param directed: whether tp generate a directed graph. + @param mode: if C{"out"}, then all vertices of the first kind are + connected to the others; C{"in"} specifies the opposite direction, + C{"all"} creates mutual edges. Ignored for undirected graphs. + + @return: the graph with a binary vertex attribute named C{"type"} that + stores the vertex classes. + """ + result, types = cls._Full_Bipartite(n1, n2, directed, mode, *args, **kwds) + result.vs["type"] = types + return result + + +def _construct_random_bipartite_graph( + cls, n1, n2, p=None, m=None, directed=False, neimode="all", *args, **kwds +): + """Generates a random bipartite graph with the given number of vertices and + edges (if m is given), or with the given number of vertices and the given + connection probability (if p is given). + + If m is given but p is not, the generated graph will have n1 vertices of + type 1, n2 vertices of type 2 and m randomly selected edges between them. If + p is given but m is not, the generated graph will have n1 vertices of type 1 + and n2 vertices of type 2, and each edge will exist between them with + probability p. + + @param n1: the number of vertices of type 1. + @param n2: the number of vertices of type 2. + @param p: the probability of edges. If given, C{m} must be missing. + @param m: the number of edges. If given, C{p} must be missing. + @param directed: whether to generate a directed graph. + @param neimode: if the graph is directed, specifies how the edges will be + generated. If it is C{"all"}, edges will be generated in both directions + (from type 1 to type 2 and vice versa) independently. If it is C{"out"} + edges will always point from type 1 to type 2. If it is C{"in"}, edges + will always point from type 2 to type 1. This argument is ignored for + undirected graphs. + """ + if p is None: + p = -1 + if m is None: + m = -1 + result, types = cls._Random_Bipartite( + n1, n2, p, m, directed, neimode, *args, **kwds + ) + result.vs["type"] = types + return result diff --git a/src/igraph/io/files.py b/src/igraph/io/files.py new file mode 100644 index 000000000..96c2ea41e --- /dev/null +++ b/src/igraph/io/files.py @@ -0,0 +1,487 @@ +import gzip +from shutil import copyfileobj +from warnings import warn + +from igraph._igraph import GraphBase +from igraph.utils import ( + named_temporary_file, +) + + +def _identify_format(filename): + """_identify_format(filename) + + Tries to identify the format of the graph stored in the file with the + given filename. It identifies most file formats based on the extension + of the file (and not on syntactic evaluation). The only exception is + the adjacency matrix format and the edge list format: the first few + lines of the file are evaluated to decide between the two. + + @note: Internal function, should not be called directly. + + @param filename: the name of the file or a file object whose C{name} + attribute is set. + @return: the format of the file as a string. + """ + import os.path + + if hasattr(filename, "name") and hasattr(filename, "read"): + # It is most likely a file + try: + filename = filename.name + except Exception: + return None + + root, ext = os.path.splitext(filename) + ext = ext.lower() + + if ext == ".gz": + _, ext2 = os.path.splitext(root) + ext2 = ext2.lower() + if ext2 == ".pickle": + return "picklez" + elif ext2 == ".graphml": + return "graphmlz" + + if ext in [ + ".graphml", + ".graphmlz", + ".lgl", + ".ncol", + ".pajek", + ".gml", + ".dimacs", + ".edgelist", + ".edges", + ".edge", + ".net", + ".pickle", + ".picklez", + ".dot", + ".gw", + ".lgr", + ".dl", + ]: + return ext[1:] + + if ext == ".txt" or ext == ".dat": + # Most probably an adjacency matrix or an edge list + f = open(filename, "r") + line = f.readline() + if line is None: + return "edges" + parts = line.strip().split() + if len(parts) == 2: + line = f.readline() + if line is None: + return "edges" + parts = line.strip().split() + if len(parts) == 2: + line = f.readline() + if line is None: + # This is a 2x2 matrix, it can be a matrix or an edge + # list as well and we cannot decide + return None + else: + parts = line.strip().split() + if len(parts) == 0: + return None + return "edges" + else: + # Not a matrix + return None + else: + return "adjacency" + + +def _construct_graph_from_adjacency_file( + cls, f, sep=None, comment_char="#", attribute=None, *args, **kwds +): + """Constructs a graph based on an adjacency matrix from the given file. + + Additional positional and keyword arguments not mentioned here are + passed intact to L{Adjacency}. + + @param f: the name of the file to be read or a file object + @param sep: the string that separates the matrix elements in a row. + C{None} means an arbitrary sequence of whitespace characters. + @param comment_char: lines starting with this string are treated + as comments. + @param attribute: an edge attribute name where the edge weights are + stored in the case of a weighted adjacency matrix. If C{None}, + no weights are stored, values larger than 1 are considered as + edge multiplicities. + @return: the created graph""" + if isinstance(f, str): + f = open(f) + + matrix, ri = [], 0 + for line in f: + line = line.strip() + if len(line) == 0: + continue + if line.startswith(comment_char): + continue + row = [float(x) for x in line.split(sep)] + matrix.append(row) + ri += 1 + + f.close() + + if attribute is None: + graph = cls.Adjacency(matrix, *args, **kwds) + else: + kwds["attr"] = attribute + graph = cls.Weighted_Adjacency(matrix, *args, **kwds) + + return graph + + +def _construct_graph_from_dimacs_file(cls, f, directed=False): + """Reads a graph from a file conforming to the DIMACS minimum-cost flow + file format. + + For the exact definition of the format, see + U{http://lpsolve.sourceforge.net/5.5/DIMACS.htm}. + + Restrictions compared to the official description of the format are + as follows: + + - igraph's DIMACS reader requires only three fields in an arc + definition, describing the edge's source and target node and + its capacity. + - Source vertices are identified by 's' in the FLOW field, target + vertices are identified by 't'. + - Node indices start from 1. Only a single source and target node + is allowed. + + @param f: the name of the file or a Python file handle + @param directed: whether the generated graph should be directed. + @return: the generated graph. The indices of the source and target + vertices are attached as graph attributes C{source} and C{target}, + the edge capacities are stored in the C{capacity} edge attribute. + """ + # Deferred import to avoid cycles + from igraph import Graph + + graph, source, target, cap = super(Graph, cls).Read_DIMACS(f, directed) + graph.es["capacity"] = cap + graph["source"] = source + graph["target"] = target + return graph + + +def _construct_graph_from_graphmlz_file(cls, f, directed=True, index=0): + """Reads a graph from a zipped GraphML file. + + @param f: the name of the file + @param index: if the GraphML file contains multiple graphs, + specified the one that should be loaded. Graph indices + start from zero, so if you want to load the first graph, + specify 0 here. + @return: the loaded graph object""" + with named_temporary_file() as tmpfile: + with open(tmpfile, "wb") as outf: + copyfileobj(gzip.GzipFile(f, "rb"), outf) + return cls.Read_GraphML(tmpfile, directed=directed, index=index) + + +def _construct_graph_from_pickle_file(cls, fname=None): + """Reads a graph from Python pickled format + + @param fname: the name of the file, a stream to read from, or + a string containing the pickled data. + @return: the created graph object. + """ + import pickle as pickle + + if hasattr(fname, "read"): + # Probably a file or a file-like object + result = pickle.load(fname) + else: + try: + fp = open(fname, "rb") + except UnicodeDecodeError: + try: + # We are on Python 3.6 or above and we are passing a pickled + # stream that cannot be decoded as Unicode. Try unpickling + # directly. + result = pickle.loads(fname) + except TypeError: + raise IOError( + "Cannot load file. If fname is a file name, that " + "filename may be incorrect." + ) + except IOError: + try: + # No file with the given name, try unpickling directly. + result = pickle.loads(fname) + except TypeError: + raise IOError( + "Cannot load file. If fname is a file name, that " + "filename may be incorrect." + ) + else: + result = pickle.load(fp) + fp.close() + + if not isinstance(result, cls): + raise TypeError("unpickled object is not a %s" % cls.__name__) + + return result + + +def _construct_graph_from_picklez_file(cls, fname): + """Reads a graph from compressed Python pickled format, uncompressing + it on-the-fly. + + @param fname: the name of the file or a stream to read from. + @return: the created graph object. + """ + import pickle as pickle + + if hasattr(fname, "read"): + # Probably a file or a file-like object + if isinstance(fname, gzip.GzipFile): + result = pickle.load(fname) + else: + result = pickle.load(gzip.GzipFile(mode="rb", fileobj=fname)) + else: + result = pickle.load(gzip.open(fname, "rb")) + + if not isinstance(result, cls): + raise TypeError("unpickled object is not a %s" % cls.__name__) + + return result + + +def _construct_graph_from_file(cls, f, format=None, *args, **kwds): + """Unified reading function for graphs. + + This method tries to identify the format of the graph given in + the first parameter and calls the corresponding reader method. + + The remaining arguments are passed to the reader method without + any changes. + + @param f: the file containing the graph to be loaded + @param format: the format of the file (if known in advance). + C{None} means auto-detection. Possible values are: C{"ncol"} + (NCOL format), C{"lgl"} (LGL format), C{"graphdb"} (GraphDB + format), C{"graphml"}, C{"graphmlz"} (GraphML and gzipped + GraphML format), C{"gml"} (GML format), C{"net"}, C{"pajek"} + (Pajek format), C{"dimacs"} (DIMACS format), C{"edgelist"}, + C{"edges"} or C{"edge"} (edge list), C{"adjacency"} + (adjacency matrix), C{"dl"} (DL format used by UCINET), + C{"pickle"} (Python pickled format), + C{"picklez"} (gzipped Python pickled format) + @raises IOError: if the file format can't be identified and + none was given. + """ + if format is None: + format = _identify_format(f) + try: + reader = cls._format_mapping[format][0] + except (KeyError, IndexError): + raise IOError("unknown file format: %s" % str(format)) + if reader is None: + raise IOError("no reader method for file format: %s" % str(format)) + reader = getattr(cls, reader) + return reader(f, *args, **kwds) + + +def _write_graph_to_adjacency_file(graph, f, sep=" ", eol="\n", *args, **kwds): + """Writes the adjacency matrix of the graph to the given file + + All the remaining arguments not mentioned here are passed intact + to L{Graph.get_adjacency}. + + @param f: the name of the file to be written. + @param sep: the string that separates the matrix elements in a row + @param eol: the string that separates the rows of the matrix. Please + note that igraph is able to read back the written adjacency matrix + if and only if this is a single newline character + """ + if isinstance(f, str): + f = open(f, "w") + matrix = graph.get_adjacency(*args, **kwds) + for row in matrix: + f.write(sep.join(map(str, row))) + f.write(eol) + f.close() + + +def _write_graph_to_dimacs_file( + graph, f, source=None, target=None, capacity="capacity" +): + """Writes the graph in DIMACS format to the given file. + + @param f: the name of the file to be written or a Python file handle. + @param source: the source vertex ID. If C{None}, igraph will try to + infer it from the C{source} graph attribute. + @param target: the target vertex ID. If C{None}, igraph will try to + infer it from the C{target} graph attribute. + @param capacity: the capacities of the edges in a list or the name of + an edge attribute that holds the capacities. If there is no such + edge attribute, every edge will have a capacity of 1. + """ + if source is None: + try: + source = graph["source"] + except KeyError: + raise ValueError( + "source vertex must be provided in the 'source' graph " + "attribute or in the 'source' argument of write_dimacs()" + ) + + if target is None: + try: + target = graph["target"] + except KeyError: + raise ValueError( + "target vertex must be provided in the 'target' graph " + "attribute or in the 'target' argument of write_dimacs()" + ) + + if isinstance(capacity, str) and capacity not in graph.edge_attributes(): + warn("'%s' edge attribute does not exist" % capacity) + capacity = [1] * graph.ecount() + + return GraphBase.write_dimacs(graph, f, source, target, capacity) + + +def _write_graph_to_graphmlz_file(graph, f, compresslevel=9): + """Writes the graph to a zipped GraphML file. + + The library uses the gzip compression algorithm, so the resulting + file can be unzipped with regular gzip uncompression (like + C{gunzip} or C{zcat} from Unix command line) or the Python C{gzip} + module. + + Uses a temporary file to store intermediate GraphML data, so + make sure you have enough free space to store the unzipped + GraphML file as well. + + @param f: the name of the file to be written. + @param compresslevel: the level of compression. 1 is fastest and + produces the least compression, and 9 is slowest and produces + the most compression.""" + with named_temporary_file() as tmpfile: + graph.write_graphml(tmpfile) + outf = gzip.GzipFile(f, "wb", compresslevel) + copyfileobj(open(tmpfile, "rb"), outf) + outf.close() + + +def _write_graph_to_pickle_file(graph, fname=None, version=-1): + """Saves the graph in Python pickled format + + @param fname: the name of the file or a stream to save to. If + C{None}, saves the graph to a string and returns the string. + @param version: pickle protocol version to be used. If -1, uses + the highest protocol available + @return: C{None} if the graph was saved successfully to the + given file, or a string if C{fname} was C{None}. + """ + import pickle as pickle + + if fname is None: + return pickle.dumps(graph, version) + if not hasattr(fname, "write"): + file_was_opened = True + fname = open(fname, "wb") + else: + file_was_opened = False + result = pickle.dump(graph, fname, version) + if file_was_opened: + fname.close() + return result + + +def _write_graph_to_picklez_file(graph, fname=None, version=-1): + """Saves the graph in Python pickled format, compressed with + gzip. + + Saving in this format is a bit slower than saving in a Python pickle + without compression, but the final file takes up much less space on + the hard drive. + + @param fname: the name of the file or a stream to save to. + @param version: pickle protocol version to be used. If -1, uses + the highest protocol available + @return: C{None} if the graph was saved successfully to the + given file. + """ + import pickle as pickle + + file_was_opened = False + + if not hasattr(fname, "write"): + file_was_opened = True + fname = gzip.open(fname, "wb") + elif not isinstance(fname, gzip.GzipFile): + file_was_opened = True + fname = gzip.GzipFile(mode="wb", fileobj=fname) + + result = pickle.dump(graph, fname, version) + + if file_was_opened: + fname.close() + + return result + + +def _write_graph_to_file(graph, f, format=None, *args, **kwds): + """Unified writing function for graphs. + + This method tries to identify the format of the graph given in + the first parameter (based on extension) and calls the corresponding + writer method. + + The remaining arguments are passed to the writer method without + any changes. + + @param f: the file containing the graph to be saved + @param format: the format of the file (if one wants to override the + format determined from the filename extension, or the filename itself + is a stream). C{None} means auto-detection. Possible values are: + + - C{"adjacency"}: adjacency matrix format + + - C{"dimacs"}: DIMACS format + + - C{"dot"}, C{"graphviz"}: GraphViz DOT format + + - C{"edgelist"}, C{"edges"} or C{"edge"}: numeric edge list format + + - C{"gml"}: GML format + + - C{"graphml"} and C{"graphmlz"}: standard and gzipped GraphML + format + + - C{"gw"}, C{"leda"}, C{"lgr"}: LEDA native format + + - C{"lgl"}: LGL format + + - C{"ncol"}: NCOL format + + - C{"net"}, C{"pajek"}: Pajek format + + - C{"pickle"}, C{"picklez"}: standard and gzipped Python pickled + format + + - C{"svg"}: SVG format + + @raises IOError: if the file format can't be identified and + none was given. + """ + if format is None: + format = _identify_format(f) + try: + writer = graph._format_mapping[format][1] + except (KeyError, IndexError): + raise IOError("unknown file format: %s" % str(format)) + if writer is None: + raise IOError("no writer method for file format: %s" % str(format)) + writer = getattr(graph, writer) + return writer(f, *args, **kwds) diff --git a/src/igraph/io/images.py b/src/igraph/io/images.py new file mode 100644 index 000000000..934ab01c0 --- /dev/null +++ b/src/igraph/io/images.py @@ -0,0 +1,365 @@ +import math + +from igraph.drawing import BoundingBox + + +def _write_graph_to_svg( + graph, + fname, + layout="auto", + width=None, + height=None, + labels="label", + colors="color", + shapes="shape", + vertex_size=10, + edge_colors="color", + edge_stroke_widths="width", + font_size=16, + *args, + **kwds +): + """Saves the graph as an SVG (Scalable Vector Graphics) file + + The file will be Inkscape (http://inkscape.org) compatible. + In Inkscape, as nodes are rearranged, the edges auto-update. + + @param fname: the name of the file or a Python file handle + @param layout: the layout of the graph. Can be either an + explicitly specified layout (using a list of coordinate + pairs) or the name of a layout algorithm (which should + refer to a method in the L{Graph} object, but without + the C{layout_} prefix. + @param width: the preferred width in pixels (default: 400) + @param height: the preferred height in pixels (default: 400) + @param labels: the vertex labels. Either it is the name of + a vertex attribute to use, or a list explicitly specifying + the labels. It can also be C{None}. + @param colors: the vertex colors. Either it is the name of + a vertex attribute to use, or a list explicitly specifying + the colors. A color can be anything acceptable in an SVG + file. + @param shapes: the vertex shapes. Either it is the name of + a vertex attribute to use, or a list explicitly specifying + the shapes as integers. Shape 0 means hidden (nothing is drawn), + shape 1 is a circle, shape 2 is a rectangle and shape 3 is a + rectangle that automatically sizes to the inner text. + @param vertex_size: vertex size in pixels + @param edge_colors: the edge colors. Either it is the name + of an edge attribute to use, or a list explicitly specifying + the colors. A color can be anything acceptable in an SVG + file. + @param edge_stroke_widths: the stroke widths of the edges. Either + it is the name of an edge attribute to use, or a list explicitly + specifying the stroke widths. The stroke width can be anything + acceptable in an SVG file. + @param font_size: font size. If it is a string, it is written into + the SVG file as-is (so you can specify anything which is valid + as the value of the C{font-size} style). If it is a number, it + is interpreted as pixel size and converted to the proper attribute + value accordingly. + """ + if width is None and height is None: + width = 400 + height = 400 + elif width is None: + width = height + elif height is None: + height = width + + if width <= 0 or height <= 0: + raise ValueError("width and height must be positive") + + if isinstance(layout, str): + layout = graph.layout(layout, *args, **kwds) + + if isinstance(labels, str): + try: + labels = graph.vs.get_attribute_values(labels) + except KeyError: + labels = [x + 1 for x in range(graph.vcount())] + elif labels is None: + labels = [""] * graph.vcount() + + if isinstance(colors, str): + try: + colors = graph.vs.get_attribute_values(colors) + except KeyError: + colors = ["red"] * graph.vcount() + + if isinstance(shapes, str): + try: + shapes = graph.vs.get_attribute_values(shapes) + except KeyError: + shapes = [1] * graph.vcount() + + if isinstance(edge_colors, str): + try: + edge_colors = graph.es.get_attribute_values(edge_colors) + except KeyError: + edge_colors = ["black"] * graph.ecount() + + if isinstance(edge_stroke_widths, str): + try: + edge_stroke_widths = graph.es.get_attribute_values(edge_stroke_widths) + except KeyError: + edge_stroke_widths = [2] * graph.ecount() + + if not isinstance(font_size, str): + font_size = "%spx" % str(font_size) + else: + if ";" in font_size: + raise ValueError("font size can't contain a semicolon") + + vcount = graph.vcount() + labels.extend(str(i + 1) for i in range(len(labels), vcount)) + colors.extend(["red"] * (vcount - len(colors))) + + if isinstance(fname, str): + f = open(fname, "w") + our_file = True + else: + f = fname + our_file = False + + bbox = BoundingBox(layout.bounding_box()) + + sizes = [width - 2 * vertex_size, height - 2 * vertex_size] + w, h = bbox.width, bbox.height + + ratios = [] + if w == 0: + ratios.append(1.0) + else: + ratios.append(sizes[0] / w) + if h == 0: + ratios.append(1.0) + else: + ratios.append(sizes[1] / h) + + layout = [ + [ + (row[0] - bbox.left) * ratios[0] + vertex_size, + (row[1] - bbox.top) * ratios[1] + vertex_size, + ] + for row in layout + ] + + directed = graph.is_directed() + + print('', file=f) + print( + "", + file=f, + ) + print(file=f) + print( + ''.format(width, height), end=" ", file=f) + + edge_color_dict = {} + print('', file=f) + for e_col in set(edge_colors): + if e_col == "#000000": + marker_index = "" + else: + marker_index = str(len(edge_color_dict)) + # Print an arrow marker for each possible line color + # This is a copy of Inkscape's standard Arrow 2 marker + print("', file=f) + print(" ', file=f) + print("", file=f) + + edge_color_dict[e_col] = "Arrow2Lend{0}".format(marker_index) + print("", file=f) + print( + '', + file=f, + ) + + for eidx, edge in enumerate(graph.es): + vidxs = edge.tuple + x1 = layout[vidxs[0]][0] + y1 = layout[vidxs[0]][1] + x2 = layout[vidxs[1]][0] + y2 = layout[vidxs[1]][1] + angle = math.atan2(y2 - y1, x2 - x1) + x2 = x2 - vertex_size * math.cos(angle) + y2 = y2 - vertex_size * math.sin(angle) + + print("', file=f) + + print(" ", file=f) + print(file=f) + + print( + ' ', + file=f, + ) + print(" ", file=f) + + if any(x == 3 for x in shapes): + # Only import tkFont if we really need it. Unfortunately, this will + # flash up an unneccesary Tk window in some cases + import tkinter.font + import tkinter as tk + + # This allows us to dynamically size the width of the nodes. + # Unfortunately this works only with font sizes specified in pixels. + if font_size.endswith("px"): + font_size_in_pixels = int(font_size[:-2]) + else: + try: + font_size_in_pixels = int(font_size) + except Exception: + raise ValueError( + "font sizes must be specified in pixels " + "when any of the nodes has shape=3 (i.e. " + "node size determined by text size)" + ) + tk_window = tk.Tk() + font = tkinter.font.Font( + root=tk_window, font=("Sans", font_size_in_pixels, tkinter.font.NORMAL) + ) + else: + tk_window = None + + for vidx in range(graph.vcount()): + print( + ' '.format( + vidx, layout[vidx][0], layout[vidx][1] + ), + file=f, + ) + if shapes[vidx] == 1: + # Undocumented feature: can handle two colors but only for circles + c = str(colors[vidx]) + if " " in c: + c = c.split(" ") + vs = str(vertex_size) + print( + ' '.format( + vs, c[0] + ), + file=f, + ) + print( + ' '.format( + vs, c[1] + ), + file=f, + ) + print( + ' '.format(vs), + file=f, + ) + else: + print( + ' '.format( + str(vertex_size), str(colors[vidx]) + ), + file=f, + ) + elif shapes[vidx] == 2: + print( + ' '.format( + vertex_size, vertex_size * 2, vidx, colors[vidx] + ), + file=f, + ) + elif shapes[vidx] == 3: + (vertex_width, vertex_height) = ( + font.measure(str(labels[vidx])) + 2, + font.metrics("linespace") + 2, + ) + print( + ' ".format( + vertex_width / 2.0, + vertex_height / 2.0, + vertex_width, + vertex_height, + vidx, + colors[vidx], + ), + file=f, + ) + + print( + ' '.format(vertex_size / 2.0, vidx, font_size), + file=f, + ) + print( + '' + "{2}".format(vertex_size / 2.0, vidx, str(labels[vidx])), + file=f, + ) + print(" ", file=f) + + print("", file=f) + print(file=f) + print("", file=f) + + if our_file: + f.close() + if tk_window: + tk_window.destroy() diff --git a/src/igraph/io/libraries.py b/src/igraph/io/libraries.py new file mode 100644 index 000000000..43512acfa --- /dev/null +++ b/src/igraph/io/libraries.py @@ -0,0 +1,267 @@ +def _export_graph_to_networkx( + graph, create_using=None, vertex_attr_hashable="_nx_name" +): + """Converts the graph to networkx format. + + igraph has ordered vertices and edges, but networkx does not. To keep + track of the original order, the '_igraph_index' vertex property is + added to both vertices and edges. + + @param create_using: specifies which NetworkX graph class to use when + constructing the graph. C{None} means to let igraph infer the most + appropriate class based on whether the graph is directed and whether + it has multi-edges. + @param vertex_attr_hashable (str): vertex attribute used to name vertices + in the exported network. The default "_nx_name" ensures round trip + conversions to/from networkx are lossless. + """ + import networkx as nx + + # Graph: decide on directness and mutliplicity + if create_using is None: + if graph.has_multiple(): + cls = nx.MultiDiGraph if graph.is_directed() else nx.MultiGraph + else: + cls = nx.DiGraph if graph.is_directed() else nx.Graph + else: + cls = create_using + + # Graph attributes + kw = {x: graph[x] for x in graph.attributes()} + g = cls(**kw) + + multigraph = isinstance(g, (nx.MultiGraph, nx.MultiDiGraph)) + + # Nodes and node attributes + for i, v in enumerate(graph.vs): + vattr = v.attributes() + vattr["_igraph_index"] = i + + # use _nx_name if the attribute is present so we can achieve + # a lossless round-trip in terms of vertex names + if vertex_attr_hashable in vattr: + hashable = vattr.pop(vertex_attr_hashable) + else: + hashable = i + + # adding nodes one at a time is not slower in networkx + g.add_node(hashable, **vattr) + + # Edges and edge attributes + for i, edge in enumerate(graph.es): + eattr = edge.attributes() + eattr["_igraph_index"] = i + + if multigraph and "_nx_multiedge_key" in eattr: + eattr["key"] = eattr.pop["_nx_multiedge_key"] + + if vertex_attr_hashable in graph.vertex_attributes(): + hashable_source = graph.vs[vertex_attr_hashable][edge.source] + hashable_target = graph.vs[vertex_attr_hashable][edge.target] + else: + hashable_source = edge.source + hashable_target = edge.target + + # adding edges one at a time is not slower in networkx + g.add_edge(hashable_source, hashable_target, **eattr) + + return g + + +def _construct_graph_from_networkx(cls, g, vertex_attr_hashable="_nx_name"): + """Converts the graph from networkx + + Vertex names will be stored as a vertex_attr_hashable attribute (usually + "_nx_name", but see below). Because python-igraph stored vertices in an + ordered manner, vertices will get new ids from 0 up. In case of + multigraphs, each edge will have an "_nx_multiedge_key" attribute, to + distinguish edges that connect the same two vertices. + + @param g: networkx Graph or DiGraph + @param vertex_attr_hashable (str): attribute used to store the Python + hashable used by networkx to identify each vertex. The default value + '_nx_name' ensures lossless round trip conversions to/from networkx. An + alternative choice is 'name': in that case, using strings for vertex + names is recommended and, if the graph is re-exported to networkx, + Graph.to_networkx(vertex_attr_hashable="name") must be used to recover + the correct vertex nomenclature in the exported network. + + """ + import networkx as nx + + # Graph attributes + gattr = dict(g.graph) + + # Nodes + vnames = list(g.nodes) + vattr = {vertex_attr_hashable: vnames} + vcount = len(vnames) + + # Dictionary connecting networkx hashables with igraph indices + if len(g) and "_igraph_index" in g.nodes[0]: + # Collect _igraph_index and fill gaps + idx = [x["_igraph_index"] for v, x in g.nodes.data()] + idx.sort() + idx_dict = {x: i for i, x in enumerate(idx)} + + vd = {} + for v, datum in g.nodes.data(): + vd[v] = idx_dict[datum["_igraph_index"]] + else: + vd = {v: i for i, v in enumerate(vnames)} + + # NOTE: we do not need a special class for multigraphs, it is taken + # care for at the edge level rather than at the graph level. + graph = cls( + n=vcount, directed=g.is_directed(), graph_attrs=gattr, vertex_attrs=vattr + ) + + # Vertex attributes + for v, datum in g.nodes.data(): + for key, val in list(datum.items()): + # Get rid of _igraph_index (we used it already) + if key == "_igraph_index": + continue + graph.vs[vd[v]][key] = val + + # Edges and edge attributes + eattr_names = {name for (_, _, data) in g.edges.data() for name in data} + eattr = {name: [] for name in eattr_names} + edges = [] + # Multigraphs need a hidden attribute for multiedges + if isinstance(g, (nx.MultiGraph, nx.MultiDiGraph)): + eattr["_nx_multiedge_key"] = [] + for (u, v, edgekey, data) in g.edges.data(keys=True): + edges.append((vd[u], vd[v])) + for name in eattr_names: + eattr[name].append(data.get(name)) + eattr["_nx_multiedge_key"].append(edgekey) + + else: + for (u, v, data) in g.edges.data(): + edges.append((vd[u], vd[v])) + for name in eattr_names: + eattr[name].append(data.get(name)) + + # Sort edges if there is a trace of a previous igraph ordering + if "_igraph_index" in eattr: + # Poor man's argsort + sortd = [(i, x) for i, x in enumerate(eattr["_igraph_index"])] + sortd.sort(key=lambda x: x[1]) + idx = [i for i, x in sortd] + + # Get rid of the _igraph_index now + del eattr["_igraph_index"] + + # Sort edges + edges = [edges[i] for i in idx] + # Sort each attribute + eattr = {key: [val[i] for i in idx] for key, val in eattr.items()} + + graph.add_edges(edges, eattr) + + return graph + + +def _export_graph_to_graph_tool( + graph, graph_attributes=None, vertex_attributes=None, edge_attributes=None +): + """Converts the graph to graph-tool + + Data types: graph-tool only accepts specific data types. See the + following web page for a list: + + https://graph-tool.skewed.de/static/doc/quickstart.html + + Note: because of the restricted data types in graph-tool, vertex and + edge attributes require to be type-consistent across all vertices or + edges. If you set the property for only some vertices/edges, the other + will be tagged as None in python-igraph, so they can only be converted + to graph-tool with the type 'object' and any other conversion will + fail. + + @param graph_attributes: dictionary of graph attributes to transfer. + Keys are attributes from the graph, values are data types (see + below). C{None} means no graph attributes are transferred. + @param vertex_attributes: dictionary of vertex attributes to transfer. + Keys are attributes from the vertices, values are data types (see + below). C{None} means no vertex attributes are transferred. + @param edge_attributes: dictionary of edge attributes to transfer. + Keys are attributes from the edges, values are data types (see + below). C{None} means no vertex attributes are transferred. + """ + import graph_tool as gt + + # Graph + g = gt.Graph(directed=graph.is_directed()) + + # Nodes + vc = graph.vcount() + g.add_vertex(vc) + + # Graph attributes + if graph_attributes is not None: + for x, dtype in list(graph_attributes.items()): + # Strange syntax for setting internal properties + gprop = g.new_graph_property(str(dtype)) + g.graph_properties[x] = gprop + g.graph_properties[x] = graph[x] + + # Vertex attributes + if vertex_attributes is not None: + for x, dtype in list(vertex_attributes.items()): + # Create a new vertex property + g.vertex_properties[x] = g.new_vertex_property(str(dtype)) + # Fill the values from the igraph.Graph + for i in range(vc): + g.vertex_properties[x][g.vertex(i)] = graph.vs[i][x] + + # Edges and edge attributes + if edge_attributes is not None: + for x, dtype in list(edge_attributes.items()): + g.edge_properties[x] = g.new_edge_property(str(dtype)) + for edge in graph.es: + e = g.add_edge(edge.source, edge.target) + if edge_attributes is not None: + for x, dtype in list(edge_attributes.items()): + prop = edge.attributes().get(x, None) + g.edge_properties[x][e] = prop + + return g + + +def _construct_graph_from_graph_tool(cls, g): + """Converts the graph from graph-tool + + @param g: graph-tool Graph + """ + # Graph attributes + gattr = dict(g.graph_properties) + + # Nodes + vcount = g.num_vertices() + + # Graph + graph = cls(n=vcount, directed=g.is_directed(), graph_attrs=gattr) + + # Node attributes + for key, val in g.vertex_properties.items(): + prop = val.get_array() + for i in range(vcount): + graph.vs[i][key] = prop[i] + + # Edges and edge attributes + # NOTE: graph-tool is quite strongly typed, so each property is always + # defined for all edges, using default values for the type. E.g. for a + # string property/attribute the missing edges get an empty string. + edges = [] + eattr_names = list(g.edge_properties) + eattr = {name: [] for name in eattr_names} + for e in g.edges(): + edges.append((int(e.source()), int(e.target()))) + for name, attr_map in g.edge_properties.items(): + eattr[name].append(attr_map[e]) + + graph.add_edges(edges, eattr) + + return graph diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py new file mode 100644 index 000000000..8300e1e03 --- /dev/null +++ b/src/igraph/io/objects.py @@ -0,0 +1,831 @@ +from collections import defaultdict +from itertools import repeat +from warnings import warn + +from igraph.datatypes import UniqueIdGenerator + + +def _construct_graph_from_dict_list( + cls, + vertices, + edges, + directed=False, + vertex_name_attr="name", + edge_foreign_keys=("source", "target"), + iterative=False, +): + """Constructs a graph from a list-of-dictionaries representation. + + This function is useful when you have two lists of dictionaries, one for + vertices and one for edges, each containing their attributes (e.g. name, + weight). Of course, the edge dictionary must also contain two special keys + that indicate the source and target vertices connected by that edge. + Non-list iterables should work as long as they yield dictionaries or + dict-like objects (they should have the 'items' and '__getitem__' methods). + For instance, a database query result is likely to be fit as long as it's + iterable and yields dict-like objects with every iteration. + + @param vertices: the list of dictionaries for the vertices or C{None} if + there are no special attributes assigned to vertices and we + should simply use the edge list of dicts to infer vertex names. + @param edges: the list of dictionaries for the edges. Each dict must have + at least the two keys specified by edge_foreign_keys to label the source + and target vertices, while additional items will be treated as edge + attributes. + @param directed: whether the constructed graph will be directed + @param vertex_name_attr: the name of the distinguished key in the + dicts in the vertex data source that contains the vertex names. + Ignored if C{vertices} is C{None}. + @param edge_foreign_keys: tuple specifying the attributes in each edge + dictionary that contain the source (1st) and target (2nd) vertex names. + These items of each dictionary are also added as edge_attributes. + @param iterative: whether to add the edges to the graph one by one, + iteratively, or to build a large edge list first and use that to + construct the graph. The latter approach is faster but it may + not be suitable if your dataset is large. The default is to + add the edges in a batch from an edge list. + @return: the graph that was constructed + + Example: + + >>> vertices = [{'name': 'apple'}, {'name': 'pear'}, {'name': 'peach'}] + >>> edges = [{'source': 'apple', 'target': 'pear', 'weight': 1.2}, + ... {'source': 'apple', 'target': 'peach', 'weight': 0.9}] + >>> g = Graph.DictList(vertices, edges) + + The graph has three vertices with names and two edges with weights. + """ + + def create_list_from_indices(indices, n): + result = [None] * n + for i, v in indices: + result[i] = v + return result + + # Construct the vertices + vertex_attrs = {} + n = 0 + if vertices: + for idx, vertex_data in enumerate(vertices): + for k, v in vertex_data.items(): + try: + vertex_attrs[k].append((idx, v)) + except KeyError: + vertex_attrs[k] = [(idx, v)] + n += 1 + for k, v in vertex_attrs.items(): + vertex_attrs[k] = create_list_from_indices(v, n) + else: + vertex_attrs[vertex_name_attr] = [] + + if vertex_name_attr not in vertex_attrs: + raise AttributeError( + f'{vertex_name_attr} is not a key of your vertex dictionaries', + ) + vertex_names = vertex_attrs[vertex_name_attr] + + # Check for duplicates in vertex_names + if len(vertex_names) != len(set(vertex_names)): + raise ValueError("vertex names are not unique") + # Create a reverse mapping from vertex names to indices + vertex_name_map = UniqueIdGenerator(initial=vertex_names) + + # Construct the edges + efk_src, efk_dest = edge_foreign_keys + if iterative: + g = cls(n, [], directed, {}, vertex_attrs) + for idx, edge_data in enumerate(edges): + src_name = edge_data[efk_src] + dst_name = edge_data[efk_dest] + v1 = vertex_name_map[src_name] + if v1 == n: + g.add_vertices(1) + g.vs[n][vertex_name_attr] = src_name + n += 1 + v2 = vertex_name_map[dst_name] + if v2 == n: + g.add_vertices(1) + g.vs[n][vertex_name_attr] = dst_name + n += 1 + g.add_edge(v1, v2) + for k, v in edge_data.items(): + g.es[idx][k] = v + + return g + else: + edge_list = [] + edge_attrs = {} + m = 0 + for idx, edge_data in enumerate(edges): + v1 = vertex_name_map[edge_data[efk_src]] + v2 = vertex_name_map[edge_data[efk_dest]] + + edge_list.append((v1, v2)) + for k, v in edge_data.items(): + try: + edge_attrs[k].append((idx, v)) + except KeyError: + edge_attrs[k] = [(idx, v)] + m += 1 + for k, v in edge_attrs.items(): + edge_attrs[k] = create_list_from_indices(v, m) + + # It may have happened that some vertices were added during + # the process + if len(vertex_name_map) > n: + diff = len(vertex_name_map) - n + more = [None] * diff + for k, v in vertex_attrs.items(): + v.extend(more) + vertex_attrs[vertex_name_attr] = list(vertex_name_map.values()) + n = len(vertex_name_map) + + # Create the graph + return cls(n, edge_list, directed, {}, vertex_attrs, edge_attrs) + + +def _construct_graph_from_tuple_list( + cls, + edges, + directed=False, + vertex_name_attr="name", + edge_attrs=None, + weights=False, +): + """Constructs a graph from a list-of-tuples representation. + + This representation assumes that the edges of the graph are encoded + in a list of tuples (or lists). Each item in the list must have at least + two elements, which specify the source and the target vertices of the edge. + The remaining elements (if any) specify the edge attributes of that edge, + where the names of the edge attributes originate from the C{edge_attrs} + list. The names of the vertices will be stored in the vertex attribute + given by C{vertex_name_attr}. + + The default parameters of this function are suitable for creating + unweighted graphs from lists where each item contains the source vertex + and the target vertex. If you have a weighted graph, you can use items + where the third item contains the weight of the edge by setting + C{edge_attrs} to C{"weight"} or C{["weight"]}. If you have even more + edge attributes, add them to the end of each item in the C{edges} + list and also specify the corresponding edge attribute names in + C{edge_attrs} as a list. + + @param edges: the data source for the edges. This must be a list + where each item is a tuple (or list) containing at least two + items: the name of the source and the target vertex. Note that + names will be assigned to the C{name} vertex attribute (or another + vertex attribute if C{vertex_name_attr} is specified), even if + all the vertex names in the list are in fact numbers. + @param directed: whether the constructed graph will be directed + @param vertex_name_attr: the name of the vertex attribute that will + contain the vertex names. + @param edge_attrs: the names of the edge attributes that are filled + with the extra items in the edge list (starting from index 2, since + the first two items are the source and target vertices). If C{None} + or an empty sequence, only the source and target vertices will be + extracted and additional tuple items will be ignored. If a string, it is + interpreted as a single edge attribute. + @param weights: alternative way to specify that the graph is + weighted. If you set C{weights} to C{true} and C{edge_attrs} is + not given, it will be assumed that C{edge_attrs} is C{["weight"]} + and igraph will parse the third element from each item into an + edge weight. If you set C{weights} to a string, it will be assumed + that C{edge_attrs} contains that string only, and igraph will + store the edge weights in that attribute. + @return: the graph that was constructed + """ + if edge_attrs is None: + if not weights: + edge_attrs = () + else: + if not isinstance(weights, str): + weights = "weight" + edge_attrs = [weights] + else: + if weights: + raise ValueError("`weights` must be False if `edge_attrs` is " "not None") + + if isinstance(edge_attrs, str): + edge_attrs = [edge_attrs] + + # Set up a vertex ID generator + idgen = UniqueIdGenerator() + + # Construct the edges and the edge attributes + edge_list = [] + edge_attributes = {} + for name in edge_attrs: + edge_attributes[name] = [] + + for item in edges: + edge_list.append((idgen[item[0]], idgen[item[1]])) + for index, name in enumerate(edge_attrs, 2): + try: + edge_attributes[name].append(item[index]) + except IndexError: + edge_attributes[name].append(None) + + # Set up the name vertex attribute + vertex_attributes = {} + vertex_attributes[vertex_name_attr] = list(idgen.values()) + n = len(idgen) + + # Construct the graph + return cls(n, edge_list, directed, {}, vertex_attributes, edge_attributes) + + +def _construct_graph_from_list_dict( + cls, + edges, + directed=False, + vertex_name_attr="name", +): + """Constructs a graph from a dict-of-lists representation. + + This function is used to construct a graph from a dictionary of + lists. Other, non-list sequences (e.g. tuples) and lazy iterators are + are accepted. For each key x, its corresponding value must be a sequence of + multiple values y: the edge (x,y) will be created in the graph. x and y + must be either one of: + + - two integers: the vertices with those ids will be connected + - two strings: the vertices with those names will be connected + + If names are used, the order of vertices is not guaranteed, and each + vertex will be given the vertex_name_attr attribute. + + @param edges: the dict of sequences describing the edges + @param directed (bool): whether to create a directed graph + @vertex_name_attr (str): vertex attribute that will store the names + + @returns: a Graph object + + Example: + + >>> mydict = {'apple': ['pear', 'peach'], 'pear': ['peach']} + >>> g = Graph.ListDict(mydict) + + # The graph has three vertices with names and three edges connecting + # each pair. + """ + first_item = next(iter(edges), 0) + + if not isinstance(first_item, (int, str)): + raise ValueError("Keys must be integers or strings") + + vertex_attributes = {} + if isinstance(first_item, str): + name_map = UniqueIdGenerator() + edge_list = [] + for source, sequence in edges.items(): + source_id = name_map[source] + edge_list.extend((source_id, name_map[target]) for target in sequence) + vertex_attributes[vertex_name_attr] = name_map.values() + n = len(name_map) + + else: + edge_list = [] + n = -1 + for source, sequence in edges.items(): + n = max(n, source, *sequence) + edge_list.extend(zip(repeat(source), sequence)) + n += 1 + + # Construct the graph + return cls(n, edge_list, directed, {}, vertex_attributes, {}) + + +def _construct_graph_from_dict_dict( + cls, + edges, + directed=False, + vertex_name_attr="name", +): + """Constructs a graph from a dict-of-dicts representation. + + Each key can be an integer or a string and represent a vertex. Each value + is a dict representing edges (outgoing if the graph is directed) from that + vertex. Each dict key is an integer/string for a target vertex, such that + an edge will be created between those two vertices. Integers are + interpreted as vertex_ids from 0 (as used in igraph), strings are + interpreted as vertex names, in which case vertices are given separate + numeric ids. Each value is a dictionary of edge attributes for that edge. + + @param edges: the dict of dict of dicts specifying the edges and their + attributes + @param directed (bool): whether to create a directed graph + @vertex_name_attr (str): vertex attribute that will store the names + + @returns: a Graph object + + Example: + + {'Alice': {'Bob': {'weight': 1.5}, 'David': {'weight': 2}}} + + creates a graph with three vertices (Alice, Bob, and David) and two edges: + + - Alice - Bob (with weight 1.5) + - Alice - David (with weight 2) + """ + first_item = next(iter(edges), 0) + + if not isinstance(first_item, (int, str)): + raise ValueError("Keys must be integers or strings") + + vertex_attributes = {} + edge_attribute_list = [] + if isinstance(first_item, str): + name_map = UniqueIdGenerator() + edge_list = [] + for source, target_dict in edges.items(): + source_id = name_map[source] + for target, edge_attrs in target_dict.items(): + edge_list.append((source_id, name_map[target])) + edge_attribute_list.append(edge_attrs) + vertex_attributes[vertex_name_attr] = name_map.values() + n = len(name_map) + + else: + edge_list = [] + n = -1 + for source, target_dict in edges.items(): + n = max(n, source, *target_dict) + for target, edge_attrs in target_dict.items(): + edge_list.append((source, target)) + edge_attribute_list.append(edge_attrs) + n += 1 + + # Construct graph without edge attributes + graph = cls(n, edge_list, directed, {}, vertex_attributes, {}) + + # Add edge attributes + for edge, edge_attrs in zip(graph.es, edge_attribute_list): + for key, val in edge_attrs.items(): + edge[key] = val + + return graph + + +def _construct_graph_from_dataframe( + cls, + edges, + directed=True, + vertices=None, + use_vids=True, +): + """Generates a graph from one or two dataframes. + + @param edges: pandas DataFrame containing edges and metadata. The first + two columns of this DataFrame contain the source and target vertices + for each edge. These indicate the vertex IDs as nonnegative integers + rather than vertex names unless `use_vids` is False. Further columns + may contain edge attributes. + @param directed: bool setting whether the graph is directed + @param vertices: None (default) or pandas DataFrame containing vertex + metadata. The DataFrame's index must contain the vertex IDs as a + sequence of intergers from `0` to `len(vertices) - 1`. If `use_vids` + is False, the first column must contain the unique vertex *names*. + Vertex names should be strings for full compatibility, but many functions + will work if you set the name with any hashable object. All other columns + will be added as vertex attributes by column name. + @param use_vids: whether to interpret the first two columns of the `edges` + argument as vertex ids (0-based integers) instead of vertex names. + If this argument is set to True and the first two columns of `edges` + are not integers, an error is thrown. + + @return: the graph + + Vertex names in either the `edges` or `vertices` arguments that are set + to NaN (not a number) will be set to the string "NA". That might lead + to unexpected behaviour: fill your NaNs with values before calling this + function to mitigate. + """ + # Deferred import to avoid cycles + from igraph import Graph + + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + try: + import numpy as np + except: + raise ImportError("You should install numpy in order to use this function") + + if edges.shape[1] < 2: + raise ValueError("The 'edges' DataFrame must contain at least two columns") + if vertices is not None and vertices.shape[1] < 1: + raise ValueError("The 'vertices' DataFrame must contain at least one column") + + if use_vids: + if not ( + str(edges.dtypes[0]).startswith("int") + and str(edges.dtypes[1]).startswith("int") + ): + raise TypeError( + f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}" + ) + elif (edges.iloc[:, :2] < 0).any(axis=None): + raise ValueError("Source and target IDs must not be negative") + if vertices is not None: + vertices = vertices.sort_index() + if not vertices.index.equals( + pd.RangeIndex.from_range(range(vertices.shape[0])) + ): + if not str(vertices.index.dtype).startswith("int"): + raise TypeError( + f"Vertex IDs must be 0-based integers, found type {vertices.index.dtype}" + ) + elif (vertices.index < 0).any(axis=None): + raise ValueError("Vertex IDs must not be negative") + else: + raise ValueError( + f"Vertex IDs must be an integer sequence from 0 to {vertices.shape[0] - 1}" + ) + else: + # Handle if some source and target names in 'edges' are 'NA' + if edges.iloc[:, :2].isna().any(axis=None): + warn( + "In the first two columns of 'edges' NA elements were replaced with string \"NA\"" + ) + edges = edges.copy() + edges.iloc[:, :2].fillna("NA", inplace=True) + + # Bring DataFrame(s) into same format as with 'use_vids=True' + if vertices is None: + vertices = pd.DataFrame({"name": np.unique(edges.values[:, :2])}) + + if vertices.iloc[:, 0].isna().any(): + warn( + "In the first column of 'vertices' NA elements were replaced with string \"NA\"" + ) + vertices = vertices.copy() + vertices.iloc[:, 0].fillna("NA", inplace=True) + + if vertices.iloc[:, 0].duplicated().any(): + raise ValueError("Vertex names must be unique") + + if vertices.shape[1] > 1 and "name" in vertices.columns[1:]: + raise ValueError( + "Vertex attribute conflict: DataFrame already contains column 'name'" + ) + + vertices = vertices.rename({vertices.columns[0]: "name"}, axis=1).reset_index( + drop=True + ) + + # Map source and target names in 'edges' to IDs + vid_map = pd.Series(vertices.index, index=vertices.iloc[:, 0]) + edges = edges.copy() + edges.iloc[:, 0] = edges.iloc[:, 0].map(vid_map) + edges.iloc[:, 1] = edges.iloc[:, 1].map(vid_map) + + # Create graph + if vertices is None: + nv = edges.iloc[:, :2].max().max() + 1 + g = cls(n=nv, directed=directed) + else: + if not edges.iloc[:, :2].isin(vertices.index).all(axis=None): + raise ValueError( + "Some vertices in the edge DataFrame are missing from vertices DataFrame" + ) + nv = vertices.shape[0] + g = cls(n=nv, directed=directed) + # Add vertex attributes + for col in vertices.columns: + g.vs[col] = vertices[col].tolist() + + # add edges including optional attributes + e_list = list(edges.iloc[:, :2].itertuples(index=False, name=None)) + e_attr = edges.iloc[:, 2:].to_dict(orient="list") if edges.shape[1] > 2 else None + g.add_edges(e_list, e_attr) + + return g + + +def _export_graph_to_dict_list( + graph, use_vids=True, skip_none=False, vertex_name_attr="name" +): + """Export graph as two lists of dictionaries, for vertices and edges. + + This function is the reverse of Graph.DictList. + + @param use_vids (bool): whether to label vertices in the output data + structure by their ids or their vertex_name_attr attribute. If + use_vids=False but vertices lack a vertex_name_attr attribute, an + AttributeError is raised. + @param skip_none (bool): whether to skip, for each edge, attributes that + have a value of None. This is useful if only some edges are expected to + possess an attribute. + @vertex_name_attr (str): only used with use_vids=False to choose what + vertex attribute to use to name your vertices in the output data + structure. + + @return: a tuple with two lists of dictionaries, representing the vertices + and the edges, respectively, with their attributes. + + Example: + + >>> g = Graph([(0, 1), (1, 2)]) + >>> g.vs["name"] = ["apple", "pear", "peach"] + >>> g.es["name"] = ["first_edge", "second"] + + >>> g.to_dict_list() + ([{"name": "apple"}, {"name": "pear"}, {"name": "peach"}], + [{"source": 0, "target": 1, "name": "first_edge"}, + {"source" 0, "target": 2, name": "second"}]) + + >>> g.to_dict_list(use_vids=False) + ([{"name": "apple"}, {"name": "pear"}, {"name": "peach"}], + [{"source": "apple", "target": "pear", "name": "first_edge"}, + {"source" "apple", "target": "peach", name": "second"}]) + """ + # Output data structures + res_vs, res_es = [], [] + + if not use_vids: + if vertex_name_attr not in graph.vertex_attributes(): + raise AttributeError(f"No vertex attribute {vertex_name_attr}") + + vs_names = graph.vs[vertex_name_attr] + + for vertex in graph.vs: + if skip_none: + attrdic = {k: v for k, v in vertex.attributes() if v is not None} + else: + attrdic = vertex.attributes() + res_vs.append(attrdic) + + for edge in graph.es: + source, target = edge.tuple + if not use_vids: + source, target = vs_names[source], vs_names[target] + if skip_none: + attrdic = {k: v for k, v in edge.attributes() if v is not None} + else: + attrdic = edge.attributes() + + attrdic["source"] = source + attrdic["target"] = target + res_es.append(attrdic) + + return (res_vs, res_es) + + +def _export_graph_to_tuple_list( + graph, use_vids=True, edge_attrs=None, vertex_name_attr="name" +): + """Export graph to a list of edge tuples + + This function is the reverse of Graph.TupleList. + + @param use_vids (bool): whether to label vertices in the output data + structure by their ids or their vertex_name_attr attribute. If + use_vids=False but vertices lack a vertex_name_attr attribute, an + AttributeError is raised. + @param edge_attrs (str or list of str): list of edge attributes to export + in addition to source and target vertex, which are always the first two + elements of each tuple. None (default) is equivalent to an empty list. A + string is acceptable to signify a single attribute and will be wrapped in + a list internally. + @vertex_name_attr (str): only used with use_vids=False to choose what + vertex attribute to use to name your vertices in the output data + structure. + + @return: a list of tuples, each representing an edge of the graph. + + Example: + + >>> g = Graph.Full(3) + >>> g.vs["name"] = ["apple", "pear", "peach"] + >>> g.es["name"] = ["first_edge", "second", "third"] + + # Get name of the edge + >>> g.to_tuple_list(edge_attrs=["name"]) + [(0, 1, "first_edge"), (0, 2, "second"), (1, 2, "third")] + + # Use vertex names, no edge attributes + >>> g.to_tuple_list(use_vids=False) + [("apple", "pear"), ("apple", "peach"), ("pear", "peach")] + """ + # Output data structure + res = [] + + if edge_attrs is not None: + if isinstance(edge_attrs, str): + edge_attrs = [edge_attrs] + missing_attrs = list(set(edge_attrs) - set(graph.edge_attributes())) + if missing_attrs: + raise AttributeError(f"Missing attributes: {missing_attrs}") + else: + edge_attrs = [] + + if use_vids is False: + if vertex_name_attr not in graph.vertex_attributes(): + raise AttributeError(f"No vertex attribute {vertex_name_attr}") + + vs_names = graph.vs[vertex_name_attr] + + for edge in graph.es: + source, target = edge.tuple + if not use_vids: + source, target = vs_names[source], vs_names[target] + attrlist = [source, target] + attrlist += [edge[attrname] for attrname in edge_attrs] + res.append(tuple(attrlist)) + + return res + + +def _export_graph_to_list_dict( + graph, use_vids=True, sequence_constructor=list, vertex_name_attr="name", +): + """Export graph to a dictionary of lists (or other sequences). + + This function is the reverse of Graph.ListDict. + + @param use_vids (bool): whether to label vertices in the output data + structure by their ids or their vertex_name_attr attribute. If + use_vids=False but vertices lack a vertex_name_attr attribute, an + AttributeError is raised. + @param sequence_constructor (function): constructor for the data structure + to be used as values of the dictionary. The default (list) makes a dict + of lists, with each list representing the neighbors of the vertex + specified in the respective dictionary key. + @vertex_name_attr (str): only used with use_vids=False to choose what + vertex attribute to use to name your vertices in the output data + structure. + + @return: dictionary of sequences, keyed by vertices, with each value + containing the neighbors of that vertex. + + Example: + + >>> g = Graph.Full(3) + >>> g.to_sequence_dict() -> {0: [1, 2], 1: [2]} + >>> g.to_sequence_dict(sequence_constructor=tuple) -> {0: (1, 2), 1: (2,)} + >>> g.vs['name'] = ['apple', 'pear', 'peach'] + >>> g.to_sequence_dict(use_vids=False) + {'apple': ['pear', 'peach'], 'pear': ['peach']} + """ + if not use_vids: + if vertex_name_attr not in graph.vertex_attributes(): + raise AttributeError(f'Vertices do not have a {vertex_name_attr} attribute') + vs_names = graph.vs[vertex_name_attr] + + # Temporary output data structure + res = defaultdict(list) + + for edge in graph.es: + source, target = edge.tuple + + if not use_vids: + source = vs_names[source] + target = vs_names[target] + + res[source].append(target) + + res = {key: sequence_constructor(val) for key, val in res.items()} + return res + + +def _export_graph_to_dict_dict(graph, use_vids=True, edge_attrs=None, skip_none=False, vertex_name_attr="name"): + """Export graph to dictionary of dicts of edge attributes + + This function is the reverse of Graph.DictDict. + + @param use_vids (bool): whether to label vertices in the output data + structure by their ids or their vertex_name_attr attribute. If + use_vids=False but vertices lack a vertex_name_attr attribute, an + AttributeError is raised. + @param edge_attrs (str or list of str): list of edge attributes to export. + None (default) signified all attributes (unlike Graph.to_tuple_list). A + string is acceptable to signify a single attribute and will be wrapped + in a list internally. + @param skip_none (bool): whether to skip, for each edge, attributes that + have a value of None. This is useful if only some edges are expected to + possess an attribute. + @vertex_name_attr (str): only used with use_vids=False to choose what + vertex attribute to use to name your vertices in the output data + structure. + + @return: dictionary of dictionaries of dictionaries, with the outer keys + vertex ids/names, the middle keys ids/names of their neighbors, and the + innermost dictionary representing attributes of that edge. + + Example: + >>> g = Graph.Full(3) + >>> g.es['name'] = ['first_edge', 'second', 'third'] + >>> g.to_dict_dict() + {0: {1: {'name': 'first_edge'}, 2: {'name': 'second'}}, + 1: {2: {'name': 'third'}}} + """ + if edge_attrs is not None: + if isinstance(edge_attrs, str): + edge_attrs = [edge_attrs] + missing_attrs = list(set(edge_attrs) - set(graph.edge_attributes())) + if missing_attrs: + raise AttributeError(f"Missing attributes: {missing_attrs}") + + if not use_vids: + if vertex_name_attr not in graph.vertex_attributes(): + raise AttributeError(f'Vertices do not have a {vertex_name_attr} attribute') + vs_names = graph.vs[vertex_name_attr] + + # Temporary output data structure + res = defaultdict(lambda: defaultdict(dict)) + + for edge in graph.es: + source, target = edge.tuple + + if not use_vids: + source = vs_names[source] + target = vs_names[target] + + attrdic = edge.attributes() + if edge_attrs is not None: + attrdic = {k: attrdic[k] for k in edge_attrs} + if skip_none: + attrdic = {k: v for k, v in attrdic.items() if v is not None} + + res[source][target] = attrdic + + res = {key: dict(val) for key, val in res.items()} + return res + + +def _export_vertex_dataframe(graph): + """Export vertices with attributes to pandas.DataFrame + + If you want to use vertex names as index, you can do: + + >>> from string import ascii_letters + >>> graph = Graph.GRG(25, 0.4) + >>> graph.vs["name"] = ascii_letters[:graph.vcount()] + >>> df = graph.get_vertex_dataframe() + >>> df.set_index('name', inplace=True) + + @return: a pandas.DataFrame representing vertices and their attributes. + The index uses vertex IDs, from 0 to N - 1 where N is the number of + vertices. + """ + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + + df = pd.DataFrame( + {attr: graph.vs[attr] for attr in graph.vertex_attributes()}, + index=list(range(graph.vcount())), + ) + df.index.name = "vertex ID" + + return df + + +def _export_edge_dataframe(graph): + """Export edges with attributes to pandas.DataFrame + + If you want to use source and target vertex IDs as index, you can do: + + >>> from string import ascii_letters + >>> graph = Graph.GRG(25, 0.4) + >>> graph.vs["name"] = ascii_letters[:graph.vcount()] + >>> df = graph.get_edge_dataframe() + >>> df.set_index(['source', 'target'], inplace=True) + + The index will be a pandas.MultiIndex. You can use the `drop=False` + option to keep the `source` and `target` columns. + + If you want to use vertex names in the source and target columns: + + >>> df = graph.get_edge_dataframe() + >>> df_vert = graph.get_vertex_dataframe() + >>> df['source'].replace(df_vert['name'], inplace=True) + >>> df['target'].replace(df_vert['name'], inplace=True) + >>> df_vert.set_index('name', inplace=True) # Optional + + @return: a pandas.DataFrame representing edges and their attributes. + The index uses edge IDs, from 0 to M - 1 where M is the number of + edges. The first two columns of the dataframe represent the IDs of + source and target vertices for each edge. These columns have names + "source" and "target". If your edges have attributes with the same + names, they will be present in the dataframe, but not in the first + two columns. + """ + try: + import pandas as pd + except ImportError: + raise ImportError("You should install pandas in order to use this function") + + df = pd.DataFrame( + {attr: graph.es[attr] for attr in graph.edge_attributes()}, + index=list(range(graph.ecount())), + ) + df.index.name = "edge ID" + + df.insert(0, "source", [e.source for e in graph.es], allow_duplicates=True) + df.insert(1, "target", [e.target for e in graph.es], allow_duplicates=True) + + return df diff --git a/src/igraph/io/random.py b/src/igraph/io/random.py new file mode 100644 index 000000000..7ae8e416a --- /dev/null +++ b/src/igraph/io/random.py @@ -0,0 +1,17 @@ +def _construct_random_geometric_graph(cls, n, radius, torus=False): + """Generates a random geometric graph. + + The algorithm drops the vertices randomly on the 2D unit square and + connects them if they are closer to each other than the given radius. + The coordinates of the vertices are stored in the vertex attributes C{x} + and C{y}. + + @param n: The number of vertices in the graph + @param radius: The given radius + @param torus: This should be C{True} if we want to use a torus instead of a + square. + """ + result, xs, ys = cls._GRG(n, radius, torus) + result.vs["x"] = xs + result.vs["y"] = ys + return result diff --git a/tests/test_basic.py b/tests/test_basic.py index 340621966..a46df8458 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -613,6 +613,88 @@ def checkIfOK(self, g, name_attr, edge_attrs): self.assertTrue(g.edge_attributes() == []) +class GraphListDictTests(unittest.TestCase): + def setUp(self): + self.eids = { + 0: [1], + 2: [1, 0], + 3: [0, 1], + } + self.edges = { + "Alice": ["Bob"], + "Cecil": ["Bob", "Alice"], + "David": ["Alice", "Bob"], + } + + def testEmptyGraphListDict(self): + g = Graph.ListDict({}) + self.assertEqual(g.vcount(), 0) + + def testGraphFromListDict(self): + g = Graph.ListDict(self.eids) + self.checkIfOK(g, ()) + + def testGraphFromListDictWithNames(self): + g = Graph.ListDict(self.edges) + self.checkIfOK(g, "name") + + def checkIfOK(self, g, name_attr): + self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and not g.is_directed()) + self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) + self.assertTrue(g.attributes() == []) + if name_attr: + self.assertTrue(g.vertex_attributes() == [name_attr]) + self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) + self.assertTrue(g.edge_attributes() == []) + + +class GraphDictDictTests(unittest.TestCase): + def setUp(self): + self.eids = { + 0: {1: {}}, + 2: {1: {}, 0: {}}, + 3: {0: {}, 1: {}}, + } + self.edges = { + "Alice": {"Bob": {}}, + "Cecil": {"Bob": {}, "Alice": {}}, + "David": {"Alice": {}, "Bob": {}}, + } + self.eids_with_props = { + 0: {1: {"weight": 5.6, "additional": 'abc'}}, + 2: {1: {"weight": 3.4}, 0: {"weight": 2}}, + 3: {0: {"weight": 1}, 1: {"weight": 5.6}}, + } + + def testEmptyGraphDictDict(self): + g = Graph.DictDict({}) + self.assertEqual(g.vcount(), 0) + + def testGraphFromDictDict(self): + g = Graph.DictDict(self.eids) + self.checkIfOK(g, ()) + + def testGraphFromDictDict(self): + g = Graph.DictDict(self.eids_with_props) + self.checkIfOK(g, (), edge_attrs=["additional", "weight"]) + + def testGraphFromDictDictWithNames(self): + g = Graph.DictDict(self.edges) + self.checkIfOK(g, "name") + + def checkIfOK(self, g, name_attr, edge_attrs=None): + self.assertTrue(g.vcount() == 4 and g.ecount() == 5 and not g.is_directed()) + self.assertTrue(g.get_edgelist() == [(0, 1), (1, 2), (0, 2), (0, 3), (1, 3)]) + self.assertTrue(g.attributes() == []) + if name_attr: + self.assertTrue(g.vertex_attributes() == [name_attr]) + self.assertTrue(g.vs[name_attr] == ["Alice", "Bob", "Cecil", "David"]) + if edge_attrs is None: + self.assertEqual(g.edge_attributes(), []) + else: + self.assertEqual(sorted(g.edge_attributes()), sorted(edge_attrs)) + + class DegreeSequenceTests(unittest.TestCase): def testIsDegreeSequence(self): # Catch and suppress warnings because is_degree_sequence() is now @@ -827,6 +909,8 @@ def suite(): datatype_suite = unittest.makeSuite(DatatypeTests) graph_dict_list_suite = unittest.makeSuite(GraphDictListTests) graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) + graph_list_dict_suite = unittest.makeSuite(GraphListDictTests) + graph_dict_dict_suite = unittest.makeSuite(GraphDictDictTests) degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) inheritance_suite = unittest.makeSuite(InheritanceTests) refcount_suite = unittest.makeSuite(ReferenceCountTests) @@ -836,6 +920,8 @@ def suite(): datatype_suite, graph_dict_list_suite, graph_tuple_list_suite, + graph_list_dict_suite, + graph_dict_dict_suite, degree_sequence_suite, inheritance_suite, refcount_suite diff --git a/tests/test_foreign.py b/tests/test_foreign.py index e86051b27..7ad7e2fd4 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -287,8 +287,7 @@ def testAdjacency(self): self.assertEqual(g.vcount(), 6) self.assertEqual(g.ecount(), 12) self.assertTrue(g.is_directed()) - self.assertTrue( - g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]) + self.assertTrue(g.es["weight"] == [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]) g.write_adjacency(tmpfname) @@ -405,6 +404,148 @@ def testPickle(self): self.assertTrue(g.vcount() == 3 and g.ecount() == 1 and not g.is_directed()) g.write_pickle(tmpfname) + def testDictList(self): + g = Graph.Full(3) + + # Check with vertex ids + self.assertEqual( + g.to_dict_list(), + ( + [{}, {}, {}], + [ + {"source": 0, "target": 1}, + {"source": 0, "target": 2}, + {"source": 1, "target": 2}, + ], + ), + ) + + # Check failure for vertex names + self.assertRaises(AttributeError, g.to_dict_list, False) + + # Check with vertex names + g.vs["name"] = ["apple", "pear", "peach"] + self.assertEqual( + g.to_dict_list(), + ( + [{"name": "apple"}, {"name": "pear"}, {"name": "peach"}], + [ + {"source": 0, "target": 1}, + {"source": 0, "target": 2}, + {"source": 1, "target": 2}, + ], + ), + ) + self.assertEqual( + g.to_dict_list(use_vids=False), + ( + [{"name": "apple"}, {"name": "pear"}, {"name": "peach"}], + [ + {"source": "apple", "target": "pear"}, + {"source": "apple", "target": "peach"}, + {"source": "pear", "target": "peach"}, + ], + ), + ) + + def testTupleList(self): + g = Graph.Full(3) + + # Check with vertex ids + self.assertEqual( + g.to_tuple_list(), + [(0, 1), (0, 2), (1, 2)], + ) + + # Check failure for edge names + self.assertRaises(AttributeError, g.to_tuple_list, True, "name") + + # Edge attributes + g.es["name"] = ["first_edge", "second", None] + self.assertEqual( + g.to_tuple_list(edge_attrs="name"), + [(0, 1, "first_edge"), (0, 2, "second"), (1, 2, None)], + ) + self.assertEqual( + g.to_tuple_list(edge_attrs=["name"]), + [(0, 1, "first_edge"), (0, 2, "second"), (1, 2, None)], + ) + + # Missing vertex names + self.assertRaises(AttributeError, g.to_tuple_list, False) + + # Vertex names + g.vs["name"] = ["apple", "pear", "peach"] + self.assertEqual( + g.to_tuple_list(use_vids=False, edge_attrs="name"), + [ + ("apple", "pear", "first_edge"), + ("apple", "peach", "second"), + ("pear", "peach", None), + ], + ) + + def testSequenceDict(self): + g = Graph.Full(3) + + # Check with vertex ids + self.assertEqual(g.to_list_dict(), {0: [1, 2], 1: [2]}) + self.assertEqual( + g.to_list_dict(sequence_constructor=tuple), + {0: (1, 2), 1: (2,)}, + ) + + # Check failure for vertex names + self.assertRaises(AttributeError, g.to_list_dict, False) + + # Check with vertex names + g.vs["name"] = ["apple", "pear", "peach"] + self.assertEqual( + g.to_list_dict(use_vids=False), + {"apple": ["pear", "peach"], "pear": ["peach"]}, + ) + + def testDictDict(self): + g = Graph([(0, 1), (0, 2), (1, 2)]) + + # Check with vertex ids, no edge attrs + self.assertEqual( + g.to_dict_dict(), + {0: {1: {}, 2: {}}, 1: {2: {}}}, + ) + + # With vertex ids, edge attrs + g.es["name"] = ["first_edge", "second", None] + # Check with vertex ids, incomplete edge attrs + self.assertEqual( + g.to_dict_dict(), + { + 0: {1: {"name": "first_edge"}, 2: {"name": "second"}}, + 1: {2: {"name": None}}, + }, + ) + self.assertEqual( + g.to_dict_dict(skip_none=True), + {0: {1: {"name": "first_edge"}, 2: {"name": "second"}}, 1: {2: {}}}, + ) + + # With vertex names + g.vs["name"] = ["apple", "pear", "peach"] + self.assertEqual( + g.to_dict_dict(use_vids=False), + { + "apple": {"pear": {"name": "first_edge"}, "peach": {"name": "second"}}, + "pear": {"peach": {"name": None}}, + }, + ) + self.assertEqual( + g.to_dict_dict(use_vids=False, skip_none=True), + { + "apple": {"pear": {"name": "first_edge"}, "peach": {"name": "second"}}, + "pear": {"peach": {}}, + }, + ) + @unittest.skipIf(pd is None, "test case depends on Pandas") def testVertexDataFrames(self): g = Graph([(0, 1), (0, 2), (0, 3), (1, 2), (2, 4)]) @@ -483,7 +624,6 @@ def testEdgeDataFrames(self): i = 2 + list(df.columns[2:]).index("source") self.assertEqual(list(df.iloc[:, i]), g.es["source"]) - @unittest.skipIf(nx is None, "test case depends on networkx") def testGraphNetworkx(self): # Undirected @@ -549,8 +689,15 @@ def testMultigraphNetworkx(self): # Test attributes self.assertEqual(g.attributes(), g2.attributes()) - self.assertEqual(sorted(["vattr", "_nx_name"]), sorted(g2.vertex_attributes())) - self.assertEqual(g.edge_attributes(), g2.edge_attributes()) + self.assertEqual( + sorted(["vattr", "_nx_name"]), + sorted(g2.vertex_attributes()), + ) + self.assertEqual( + sorted(["eattr", "_nx_multiedge_key"]), + sorted(g2.edge_attributes()), + ) + # Testing parallel edges is a bit more tricky edge2_found = set() for edge in g.es: diff --git a/tests/test_generators.py b/tests/test_generators.py index 054b5313a..7a0a9a444 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -389,11 +389,12 @@ def testDataFrame(self): self.assertTrue(g.vs["name"] == [1, 2, 3, 4, 5, 6]) self.assertTrue(g.vs["label"] == ["1", "2", "3", "4", "5", "6"]) - # Vertex ids + # Vertex names edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) g = Graph.DataFrame(edges, use_vids=False) self.assertTrue(g.vcount() == 6) + # Vertex ids edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) g = Graph.DataFrame(edges) self.assertTrue(g.vcount() == 7) From 0d9f989096129213650b26654dc73407ccef339a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Sep 2021 17:41:17 +0200 Subject: [PATCH 0642/1892] ci: fix the path to arith_apple_m1.h --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 395e66f78..539cf065d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,7 +70,7 @@ jobs: - cmake_arch: x86_64 wheel_arch: x86_64 - cmake_arch: arm64 - cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=etc/arith_apple_m1.h + cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h wheel_arch: arm64 steps: From c272841ff6d1017d0fa2edb96f3454afe1b1a870 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Sep 2021 17:47:03 +0200 Subject: [PATCH 0643/1892] ci: added missing etc/arith_apple_m1.h --- etc/arith_apple_m1.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 etc/arith_apple_m1.h diff --git a/etc/arith_apple_m1.h b/etc/arith_apple_m1.h new file mode 100644 index 000000000..86d7e1a1b --- /dev/null +++ b/etc/arith_apple_m1.h @@ -0,0 +1,10 @@ +/* pre-generated arith.h for f2c when compiling on Apple M1 */ +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Long int +#define Intcast (int)(long) +#define Double_Align +#define X64_bit_pointers +#define NANCHECK +#define QNaN0 0x0 +#define QNaN1 0x7ff80000 From d53a98d8319a7ebbd142719c5013ab9538d2aca2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 25 Sep 2021 22:44:39 +0200 Subject: [PATCH 0644/1892] ci: build macOS x86_64 and arm64 wheels separately --- .github/workflows/build.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf561c68e..663c7facb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ env: CIBW_TEST_SKIP: "cp310-*" jobs: - build_wheels: + build_wheel_linux: name: Build wheels on Linux (${{ matrix.wheel_arch }}) runs-on: ubuntu-20.04 strategy: @@ -36,8 +36,8 @@ jobs: with: path: ./wheelhouse/*.whl - build_aarch64_wheels: - name: Build wheels on Linux AArch64 + build_wheel_linux_aarch64: + name: Build wheels on Linux (aarch64) if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') runs-on: ubuntu-20.04 steps: @@ -62,8 +62,15 @@ jobs: path: ./wheelhouse/*.whl build_wheel_macos: - name: Build wheels on macOS + name: Build wheels on macOS (${{ matrix.wheel_arch }}) runs-on: macos-10.15 + strategy: + matrix: + include: + - cmake_arch: x86_64 + wheel_arch: x86_64 + - cmake_arch: arm64 + wheel_arch: arm64 steps: - uses: actions/checkout@v2 @@ -76,7 +83,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }} + key: C-core-cache-v1-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python @@ -91,8 +98,9 @@ jobs: - name: Build wheels uses: joerick/cibuildwheel@v2.1.1 env: - CIBW_ARCHS_MACOS: "x86_64 arm64" + CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_APPLE_SILICON_PROCESSOR=${{ matrix.cmake_arch }} - uses: actions/upload-artifact@v2 with: From f89de44f25be8638223c69ce0cd851979d774f28 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 26 Sep 2021 17:09:49 +0200 Subject: [PATCH 0645/1892] chore: more project URLs in setup.py --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index fc8945562..5d5138f0d 100644 --- a/setup.py +++ b/setup.py @@ -817,6 +817,12 @@ def use_educated_guess(self) -> None: license="GNU General Public License (GPL)", author="Tamas Nepusz", author_email="ntamas@gmail.com", + project_urls={ + "Bug Tracker": "https://github.com/igraph/python-igraph/issues", + "CI": "https://github.com/igraph/python-igraph/actions", + "Documentation": "https://igraph.org/python/doc", + "Source Code": "https://github.com/igraph/python-igraph", + }, ext_modules=[igraph_extension], package_dir={"igraph": "src/igraph"}, packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], From 4672cdc0947bcec89147500e1dab2b39836c1556 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 28 Sep 2021 17:31:52 +0200 Subject: [PATCH 0646/1892] ci: another attempt at compiling the C core for Apple Silicon --- .github/workflows/build.yml | 5 +++-- etc/arith_apple_m1.h | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 etc/arith_apple_m1.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 663c7facb..d3b6b97b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: - cmake_arch: x86_64 wheel_arch: x86_64 - cmake_arch: arm64 + cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h wheel_arch: arm64 steps: @@ -83,7 +84,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v1-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - uses: actions/setup-python@v2 name: Install Python @@ -100,7 +101,7 @@ jobs: env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" - IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_APPLE_SILICON_PROCESSOR=${{ matrix.cmake_arch }} + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} - uses: actions/upload-artifact@v2 with: diff --git a/etc/arith_apple_m1.h b/etc/arith_apple_m1.h new file mode 100644 index 000000000..cbdbd5fdf --- /dev/null +++ b/etc/arith_apple_m1.h @@ -0,0 +1,9 @@ +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Long int +#define Intcast (int)(long) +#define Double_Align +#define X64_bit_pointers +#define NANCHECK +#define QNaN0 0x0 +#define QNaN1 0x7ff80000 From f517c62a1ebf76505f8ad0c6956adad7b0d58988 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 29 Sep 2021 12:41:20 +1000 Subject: [PATCH 0647/1892] Update changelog --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81ff00f20..b03f5450c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ ## [Unreleased] + +### Added + +- More robust support for Matplotlib and initial support for plotly as graph + plotting backends, controlled by a configuration option. See PR + [#425](https://github.com/igraph/python-igraph/pull/425) for more details. + +- Added support for additional ways to construct a graph, such as from a + dictionary of dictionaries, and to export a graph object back to those + data structures. See PR [#434](https://github.com/igraph/python-igraph/pull/434) + for more details. + +- Added support for graph chordality which was already available in the C core: + `Graph.is_chordal()`, `Graph.chordal_completion()`, and + `Graph.maximal_cardinality_search()`. See PR + [#437](https://github.com/igraph/python-igraph/pull/437) for more details. + Thanks to [@cptwunderlich](https://github.com/cptwunderlich) for requesting + this. + ### Changed - Improved performance of `Graph.DataFrame()`, thanks to From 3ef065005f20621525eea739d3ec6f842c54358d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 1 Oct 2021 17:44:05 +0200 Subject: [PATCH 0648/1892] chore: updated changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 312aeb0b0..78aa7fa13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ [@fwitter](https://github.com/user/fwitter). See PR [#418](https://github.com/igraph/python-igraph/pull/418) for more details. +### Fixed + +* Fixed the Apple Silicon wheels so they should now work out of the box on + newer Macs with Apple M1 CPUs. + ## [0.9.6] ### Fixed From 97be0c1762ef96feacc2180bd39a3d357bd7e1d2 Mon Sep 17 00:00:00 2001 From: John Boy Date: Fri, 1 Oct 2021 18:17:14 +0200 Subject: [PATCH 0649/1892] fix: handle text wrapping if width=0 (#439) Co-authored-by: John D. Boy --- src/igraph/drawing/text.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index eb248e5e7..2895d9061 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -107,11 +107,11 @@ def get_text_layout(self, x=None, y=None, width=None, wrap=False): line_height = ctx.font_extents()[2] - if wrap: - if width and width > 0: - iterlines = self._iterlines_wrapped(width) - else: - warn("ignoring wrap=True as no width was specified") + if wrap and width and width > 0: + iterlines = self._iterlines_wrapped(width) + elif wrap: + warn("ignoring wrap=True as no width was specified") + iterlines = self._iterlines() else: iterlines = self._iterlines() From d51b33fc790810d03615c02f5bce3ec2d1c85ebf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 1 Oct 2021 18:19:32 +0200 Subject: [PATCH 0650/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78aa7fa13..dfd77b13a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ * Fixed the Apple Silicon wheels so they should now work out of the box on newer Macs with Apple M1 CPUs. +* Fixed a bug that resulted in an unexpected error when plotting a graph with + `wrap_labels=True` if the size of one of the vertices was zero or negative, + thanks to [@jboynyc](https://github.com/user/jboynyc). See PR + [#439](https://github.com/igraph/python-igraph/pull/439) for more details. + ## [0.9.6] ### Fixed From 21b4d8013f545729e29925a621323e558e1fd1c3 Mon Sep 17 00:00:00 2001 From: "John D. Boy" Date: Mon, 4 Oct 2021 11:26:55 +0200 Subject: [PATCH 0651/1892] fix: recognize SVG format from file extension The list in Graph._identify_format omitted the .svg extension. I added it and alphabetized the list to make it easier to spot other omissions. --- src/igraph/__init__.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 530cbc3cb..e6194a9d2 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2842,23 +2842,24 @@ def _identify_format(cls, filename): return "graphmlz" if ext in [ + ".dimacs", + ".dl", + ".dot", + ".edge", + ".edgelist", + ".edges", + ".gml", ".graphml", ".graphmlz", + ".gw", ".lgl", + ".lgr", ".ncol", - ".pajek", - ".gml", - ".dimacs", - ".edgelist", - ".edges", - ".edge", ".net", + ".pajek", ".pickle", ".picklez", - ".dot", - ".gw", - ".lgr", - ".dl", + ".svg", ]: return ext[1:] From 2ea15a612cf0b03db9a4aa0d6f00f8746c2041eb Mon Sep 17 00:00:00 2001 From: "John D. Boy" Date: Mon, 4 Oct 2021 10:59:42 +0200 Subject: [PATCH 0652/1892] fix: handle PathLike in Graph.write and Graph.Read os.PathLike was introduced in Python 3.6, and given igraph's aim of supporting the three most recent minor versions of Python 3, depending on it should not be an issue. This is a minimal fix, which simply turns PathLike objects into their string representation and otherwise keeps existing behavior. A more ambitious fix would be to rewrite how files and paths are handled using pathlib.Path. --- src/igraph/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e6194a9d2..1e9178902 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2916,6 +2916,8 @@ def Read(cls, f, format=None, *args, **kwds): @raises IOError: if the file format can't be identified and none was given. """ + if isinstance(f, os.PathLike): + f = str(f) if format is None: format = cls._identify_format(f) try: @@ -2973,6 +2975,8 @@ def write(self, f, format=None, *args, **kwds): @raises IOError: if the file format can't be identified and none was given. """ + if isinstance(f, os.PathLike): + f = str(f) if format is None: format = self._identify_format(f) try: From 800f619c1ee6b8e9a41a47550016c7da14457fc4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Oct 2021 13:27:42 +0200 Subject: [PATCH 0653/1892] chore: fixing up changelog format to be consistent with the develop branch [ci skip] --- CHANGELOG.md | 96 ++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfd77b13a..31a504c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,25 +4,25 @@ ### Added -* Added `Graph.is_chordal()` to test whether a graph is chordal and - `Graph.chordal_completion()` to return a possible (not necessary minimal) - chordal completion of a graph. - -* Added `Graph.maximum_cardinality_search()`, primarily as an aid for - `Graph.is_chordal()`. +- Added support for graph chordality which was already available in the C core: + `Graph.is_chordal()`, `Graph.chordal_completion()`, and + `Graph.maximal_cardinality_search()`. See PR + [#437](https://github.com/igraph/python-igraph/pull/437) for more details. + Thanks to [@cptwunderlich](https://github.com/cptwunderlich) for requesting + this. ### Changed -* Improved performance of `Graph.DataFrame()`, thanks to +- Improved performance of `Graph.DataFrame()`, thanks to [@fwitter](https://github.com/user/fwitter). See PR [#418](https://github.com/igraph/python-igraph/pull/418) for more details. ### Fixed -* Fixed the Apple Silicon wheels so they should now work out of the box on +- Fixed the Apple Silicon wheels so they should now work out of the box on newer Macs with Apple M1 CPUs. -* Fixed a bug that resulted in an unexpected error when plotting a graph with +- Fixed a bug that resulted in an unexpected error when plotting a graph with `wrap_labels=True` if the size of one of the vertices was zero or negative, thanks to [@jboynyc](https://github.com/user/jboynyc). See PR [#439](https://github.com/igraph/python-igraph/pull/439) for more details. @@ -31,7 +31,7 @@ ### Fixed -* Version 0.9.5 accidentally broke the Matplotlib backend when it was invoked +- Version 0.9.5 accidentally broke the Matplotlib backend when it was invoked without the `mark_groups=...` keyword argument; this version fixes the issue. Thanks to @dschult for reporting it! @@ -39,13 +39,13 @@ ### Fixed -* `plot(g, ..., mark_groups=True)` now works with the Matplotlib plotting backend. +- `plot(g, ..., mark_groups=True)` now works with the Matplotlib plotting backend. -* `set_random_number_generator(None)` now correctly switches back to igraph's +- `set_random_number_generator(None)` now correctly switches back to igraph's own random number generator instead of the default one that hooks into the `random` module of Python. -* Improved performance in cases when igraph has to call back to Python's +- Improved performance in cases when igraph has to call back to Python's `random` module to generate random numbers. One example is `Graph.Degree_Sequence(method="vl")`, whose performance suffered a more than 30x slowdown on 32-bit platforms before, compared to the native C @@ -58,73 +58,73 @@ ### Added -* Added `Graph.is_tree()` to test whether a graph is a tree. +- Added `Graph.is_tree()` to test whether a graph is a tree. -* Added `Graph.Realize_Degree_Sequence()` to construct a graph that realizes a +- Added `Graph.Realize_Degree_Sequence()` to construct a graph that realizes a given degree sequence, using a deterministic (Havel-Hakimi-style) algorithm. -* Added `Graph.Tree_Game()` to generate random trees with uniform sampling. +- Added `Graph.Tree_Game()` to generate random trees with uniform sampling. -* `Graph.to_directed()` now supports a `mode=...` keyword argument. +- `Graph.to_directed()` now supports a `mode=...` keyword argument. -* Added a `create_using=...` keyword argument to `Graph.to_networkx()` to +- Added a `create_using=...` keyword argument to `Graph.to_networkx()` to let the user specify which NetworkX class to use when converting the graph. ### Changed -* Updated igraph dependency to 0.9.4. +- Updated igraph dependency to 0.9.4. ### Fixed -* Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` +- Improved performance of `Graph.from_networkx()` and `Graph.from_graph_tool()` on large graphs, thanks to @szhorvat and @iosonofabio for fixing the issue. -* Fixed the `autocurve=...` keyword argument of `plot()` when using the +- Fixed the `autocurve=...` keyword argument of `plot()` when using the Matplotlib backend. ### Deprecated -* Functions and methods that take string arguments that represent an underlying +- Functions and methods that take string arguments that represent an underlying enum in the C core of igraph now print a deprecation warning when provided with a string that does not match one of the enum member names (as documented in the docstrings) exactly. Partial matches will be removed in the next minor or major version, whichever comes first. -* `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. +- `Graph.to_directed(mutual=...)` is now deprecated, use `mode=...` instead. -* `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project +- `igraph.graph.drawing.UbiGraphDrawer` is deprecated as the upstream project is not maintained since 2008. ## [0.9.1] ### Changed -* Calling `plot()` without a filename or a target surface is now deprecated. +- Calling `plot()` without a filename or a target surface is now deprecated. The original intention was to plot to a temporary file and then open it in the default image viewer of the platform of the user automatically, but this has never worked reliably. The feature will be removed in 0.10.0. ### Fixed -* Fixed plotting of `VertexClustering` objects on Matplotlib axes. +- Fixed plotting of `VertexClustering` objects on Matplotlib axes. -* The `IGRAPH_CMAKE_EXTRA_ARGS` environment variable is now applied _after_ the +- The `IGRAPH_CMAKE_EXTRA_ARGS` environment variable is now applied _after_ the default CMake arguments when building the C core of igraph from source. This enables package maintainers to override any of the default arguments we pass to CMake. -* Fixed the documentation build by replacing Epydoc with PyDoctor. +- Fixed the documentation build by replacing Epydoc with PyDoctor. ### Miscellaneous -* Building `python-igraph` from source should not require `flex` and `bison` +- Building `python-igraph` from source should not require `flex` and `bison` any more; sources of the parsers used by the C core are now included in the Python source tarball. -* Many old code constructs that were used to maintain compatibility with Python +- Many old code constructs that were used to maintain compatibility with Python 2.x are removed now that we have dropped support for Python 2.x. -* Reading GraphML files is now also supported on Windows if you use one of the +- Reading GraphML files is now also supported on Windows if you use one of the official Python wheels. @@ -132,27 +132,27 @@ ### Added -* `Graph.DataFrame` now has a `use_vids=...` keyword argument that decides whether +- `Graph.DataFrame` now has a `use_vids=...` keyword argument that decides whether the data frame contains vertex IDs (`True`) or vertex names (`False`). (PR #348) -* Added `MatplotlibGraphDrawer` to draw a graph on an existing Matplotlib +- Added `MatplotlibGraphDrawer` to draw a graph on an existing Matplotlib figure. (PR #341) -* Added a code path to choose between preferred image viewers on FreeBSD. (PR #354) +- Added a code path to choose between preferred image viewers on FreeBSD. (PR #354) -* Added `Graph.harmonic_centrality()` that wraps `igraph_harmonic_centrality()` +- Added `Graph.harmonic_centrality()` that wraps `igraph_harmonic_centrality()` from the underlying C library. ### Changed -* `python-igraph` is now compatible with `igraph` 0.9.0. +- `python-igraph` is now compatible with `igraph` 0.9.0. -* The setup script was adapted to the new CMake-based build system of `igraph`. +- The setup script was adapted to the new CMake-based build system of `igraph`. -* Dropped support for older Python versions; the oldest Python version that +- Dropped support for older Python versions; the oldest Python version that `python-igraph` is tested on is now Python 3.6. -* The default splitting heuristic of the BLISS isomorphism algorithm was changed +- The default splitting heuristic of the BLISS isomorphism algorithm was changed from `IGRAPH_BLISS_FM` (first maximally non-trivially connected non-singleton cell) to `IGRAPH_BLISS_FL` (first largest non-singleton cell) as this seems to provide better performance on a variety of graph classes. This change is a follow-up @@ -160,28 +160,28 @@ ### Fixed -* Fixed crashes in the Python-C glue code related to the handling of empty +- Fixed crashes in the Python-C glue code related to the handling of empty vectors in certain attribute merging functions (see issue #358). -* Fixed a memory leak in `Graph.closeness_centrality()` when an invalid `cutoff` +- Fixed a memory leak in `Graph.closeness_centrality()` when an invalid `cutoff` argument was provided to the function. -* Clarified that the `fixed=...` argument is ineffective for the DrL layout +- Clarified that the `fixed=...` argument is ineffective for the DrL layout because the underlying C code does not handle it. The argument was _not_ removed for sake of backwards compatibility. -* `VertexSeq.find(name=x)` now works correctly when `x` is an integer; fixes +- `VertexSeq.find(name=x)` now works correctly when `x` is an integer; fixes #367 ### Miscellaneous -* The Python codebase was piped through `black` for consistent formatting. +- The Python codebase was piped through `black` for consistent formatting. -* Wildcard imports were removed from the codebase. +- Wildcard imports were removed from the codebase. -* CI tests were moved to Github Actions from Travis. +- CI tests were moved to Github Actions from Travis. -* The core C library is now built with `-fPIC` on Linux to allow linking to the +- The core C library is now built with `-fPIC` on Linux to allow linking to the Python interface. @@ -192,7 +192,7 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..HEAD +[unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..master [0.9.6]: https://github.com/igraph/python-igraph/compare/0.9.5...0.9.6 [0.9.5]: https://github.com/igraph/python-igraph/compare/0.9.4...0.9.5 [0.9.4]: https://github.com/igraph/python-igraph/compare/0.9.1...0.9.4 From f224e9995d4e23329b58a8e61ce3423d317f9af1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Oct 2021 20:49:16 +0200 Subject: [PATCH 0654/1892] doc: fix a few broken links --- src/_igraph/graphobject.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index ca0409bf9..39fcf0311 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12759,7 +12759,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "the Chvatal graph, the Petersen graph or the Tutte graph. This method\n" "generates one of them based on its name (case insensitive). See the\n" "documentation of the C interface of C{igraph} for the names available:\n" - "U{http://igraph.org/doc/c}.\n\n" + "U{https://igraph.org/c/doc}.\n\n" "@param name: the name of the graph to be generated.\n" }, @@ -13113,7 +13113,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " graphs are to be generated and execution time is not a concern.\n" " igraph uses the original implementation of Fabien Viger; see the\n" " following URL and the paper cited on it for the details of the\n" - " algorithm: U{http://www-rp.lip6.fr/~latapy/FV/generation.html}.\n" + " algorithm: U{https://www-complexnetworks.lip6.fr/~latapy/FV/generation.html}.\n" }, /* interface to igraph_isoclass_create */ @@ -15192,8 +15192,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "It is also useful for creating graphs from \"named\" (and\n" "optionally weighted) edge lists.\n\n" "This format is used by the Large Graph Layout program. See the\n" - "U{documentation of LGL }\n" - "regarding the exact format description.\n\n" + "U{repository of LGL }\n" + "for more information.\n\n" "LGL originally cannot deal with graphs containing multiple or loop\n" "edges, but this condition is not checked here, as igraph is happy\n" "with these.\n\n" From d0264f660a696de43869ece533f4acd42ad69123 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Oct 2021 20:53:18 +0200 Subject: [PATCH 0655/1892] chore: updated changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31a504c50..f2a1472cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Thanks to [@cptwunderlich](https://github.com/cptwunderlich) for requesting this. +- `Graph.write()` and `Graph.Read()` now accept `Path` objects as well as + strings. See PR [#441](https://github.com/igraph/python-igraph/pull/441) for + more details. Thanks to [@jboynyc](https://github.com/jboynyc) for the + implementation. + ### Changed - Improved performance of `Graph.DataFrame()`, thanks to From 51e16d29c53c7bbfe4d757d2cec57ef6b9756b30 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Oct 2021 20:53:35 +0200 Subject: [PATCH 0656/1892] ci: NumPy and Pandas now have wheels for Python 3.10; still waiting for SciPy --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3b6b97b0..ebd7e5fad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - # skip testing on Python 3.10 until NumPy/SciPy/Pandas publish wheels + # skip testing on Python 3.10 until SciPy publishes wheels CIBW_TEST_SKIP: "cp310-*" jobs: From 38cdc604a80a82a57244b4d214cad2795a53dacc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 13:53:22 +0200 Subject: [PATCH 0657/1892] test: added regression test for #446 --- tests/test_foreign.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_foreign.py b/tests/test_foreign.py index a3db0b869..df45281bb 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -201,6 +201,13 @@ def testNCOL(self): "name" in g.vertex_attributes() and "weight" not in g.edge_attributes() ) + @unittest.skipIf(pd is None, "test case depends on Pandas") + def testNCOLWithDataFrame(self): + # Regression test for https://github.com/igraph/python-igraph/issues/446 + from pandas import DataFrame + df = DataFrame({'from': [1, 2], 'to': [2, 3]}) + self.assertRaises(TypeError, Graph.Read_Ncol, df) + def testLGL(self): with temporary_file( """\ From fd831b262239bd6add6b6dce512715da7ed10b73 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 14:21:22 +0200 Subject: [PATCH 0658/1892] test: remove a debug statement from a test case --- tests/test_structural.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_structural.py b/tests/test_structural.py index eaeef42d6..8db1ed194 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -686,7 +686,6 @@ def testMaximumCardinalitySearch(self): g = Graph.Famous("petersen") alpha, alpham1 = g.maximum_cardinality_search() - print(repr(alpha), repr(alpham1)) self.assert_valid_maximum_cardinality_search_result(g, alpha, alpham1) g = Graph.GRG(100, 0.2) From 633c4bd4b09cda3326d4cdbe800d470e4fc0e4ff Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 14:21:53 +0200 Subject: [PATCH 0659/1892] chore: ignore more virtualenv folders --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 323291f0c..2391ed900 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ src/igraph/*.so .eggs/ .tox .venv/ +.venv-*/ .vscode/ vendor/build/ vendor/install/ From 53258b0fb73f0fd302725861de853f922f7f062d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 14:56:57 +0200 Subject: [PATCH 0660/1892] refactor: code cleanup --- src/_igraph/filehandle.c | 7 +++++-- src/_igraph/graphobject.c | 12 +++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/_igraph/filehandle.c b/src/_igraph/filehandle.c index f7bc72f38..1e0a9f3b2 100644 --- a/src/_igraph/filehandle.c +++ b/src/_igraph/filehandle.c @@ -33,6 +33,7 @@ static int igraphmodule_i_filehandle_init_cpython_3(igraphmodule_filehandle_t* h return 1; } + handle->fp = 0; handle->need_close = 0; handle->object = 0; @@ -85,7 +86,9 @@ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* hand return 1; } + handle->fp = 0; handle->need_close = 0; + handle->object = 0; if (PyBaseString_Check(object)) { /* We have received a string; we need to open the file denoted by this @@ -116,6 +119,7 @@ static int igraphmodule_i_filehandle_init_pypy_3(igraphmodule_filehandle_t* hand /* This already called Py_DECREF(handle->object), no need to call it */ return 1; } + handle->fp = fdopen(fp, mode); if (handle->fp == 0) { igraphmodule_filehandle_destroy(handle); @@ -156,9 +160,8 @@ void igraphmodule_filehandle_destroy(igraphmodule_filehandle_t* handle) { if (handle->need_close && !handle->object) { fclose(handle->fp); } + handle->fp = 0; } - - handle->fp = 0; if (handle->object != 0) { /* igraphmodule_PyFile_Close might mess up the stored exception, so let's diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 39fcf0311..4b797c98f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2858,7 +2858,7 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, if (igraphmodule_PyObject_to_vector_t(outdeg_o, &outdeg, 0)) return NULL; - /* Indegree vector, PyNone means undirected graph */ + /* Indegree vector, Py_None means undirected graph */ if (indeg_o != Py_None) { if (igraphmodule_PyObject_to_vector_t(indeg_o, &indeg, 0)) { igraph_vector_destroy(&outdeg); @@ -2870,15 +2870,17 @@ PyObject *igraphmodule_Graph_Realize_Degree_Sequence(PyTypeObject *type, /* C function takes care of multi-sw and directed corner case */ if (igraph_realize_degree_sequence(&g, &outdeg, indegp, allowed_edge_types, method)) { igraph_vector_destroy(&outdeg); - if (indegp != 0) - igraph_vector_destroy(&indeg); + if (indegp != 0) { + igraph_vector_destroy(indegp); + } igraphmodule_handle_igraph_error(); return NULL; } igraph_vector_destroy(&outdeg); - if (indegp != 0) - igraph_vector_destroy(&indeg); + if (indegp != 0) { + igraph_vector_destroy(indegp); + } CREATE_GRAPH_FROM_TYPE(self, g, type); From 07d3969c723fa30b5c124bb93c4a9245bd7a3724 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 14:59:48 +0200 Subject: [PATCH 0661/1892] refactor: more code cleanup --- src/_igraph/convert.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 8b2330b57..2bfa6349d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -160,7 +160,7 @@ int igraphmodule_PyObject_to_enum(PyObject *o, * \param result the result is returned here. The default value must be * passed in before calling this function, since this value is * returned untouched if the given Python object is Py_None. - * \return 0 if everything is OK, 1 otherwise. An appropriate exception + * \return 0 if everything is OK, -1 otherwise. An appropriate exception * is raised in this case. */ int igraphmodule_PyObject_to_enum_strict(PyObject *o, @@ -168,33 +168,41 @@ int igraphmodule_PyObject_to_enum_strict(PyObject *o, int *result) { char *s, *s2; - if (o == 0 || o == Py_None) + if (o == 0 || o == Py_None) { return 0; - if (PyLong_Check(o)) + } + + if (PyLong_Check(o)) { return PyLong_AsInt(o, result); + } + s = PyUnicode_CopyAsString(o); if (s == 0) { - PyErr_SetString(PyExc_TypeError, "int, long or string expected"); - return -1; + PyErr_SetString(PyExc_TypeError, "int, long or string expected"); + return -1; } + /* Convert string to lowercase */ - for (s2=s; *s2; s2++) + for (s2 = s; *s2; s2++) { *s2 = tolower(*s2); + } + /* Search for exact matches */ while (table->name != 0) { - if (strcmp(s, table->name) == 0) { - *result = table->value; - free(s); - return 0; - } - table++; + if (strcmp(s, table->name) == 0) { + *result = table->value; + free(s); + return 0; + } + table++; } + free(s); PyErr_SetObject(PyExc_ValueError, o); + return -1; } - /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_neimode_t From be01f0162caa67c14986de3ff68d40a607498c82 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 15:00:11 +0200 Subject: [PATCH 0662/1892] fix: fix crash in Graph.Realize_Degree_Sequence() on Python 3.7 (maybe other versions) --- src/_igraph/convert.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 2bfa6349d..2f8ee29ca 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3143,6 +3143,7 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t * \brief Converts a Python object to an igraph \c igraph_edge_type_sw_t */ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result) { + int result_int, retval; static igraphmodule_enum_translation_table_entry_t edge_type_sw_tt[] = { {"simple", IGRAPH_SIMPLE_SW}, {"loops", IGRAPH_LOOPS_SW}, @@ -3151,7 +3152,14 @@ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t * {0,0} }; - return igraphmodule_PyObject_to_enum_strict(o, edge_type_sw_tt, (int*)result); + retval = igraphmodule_PyObject_to_enum_strict(o, edge_type_sw_tt, &result_int); + + if (retval) { + return retval; + } + + *result = result_int; + return 0; } /** From 78adc9e776eabfa7ba2f63602d5241a9040fc483 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 14 Oct 2021 15:12:26 +0200 Subject: [PATCH 0663/1892] fix: make sure that igraphmodule_PyObject_to_edge_type_sw_t() respects the default value passed in --- src/_igraph/convert.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 2f8ee29ca..80fe02a8d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3143,7 +3143,8 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t * \brief Converts a Python object to an igraph \c igraph_edge_type_sw_t */ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result) { - int result_int, retval; + int result_int = *result; + int retval; static igraphmodule_enum_translation_table_entry_t edge_type_sw_tt[] = { {"simple", IGRAPH_SIMPLE_SW}, {"loops", IGRAPH_LOOPS_SW}, From 1b665ae59bac96d9b81be80b6e72af3ef747f69d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Oct 2021 12:12:47 +0200 Subject: [PATCH 0664/1892] chore: updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2a1472cd..462823bc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,10 @@ thanks to [@jboynyc](https://github.com/user/jboynyc). See PR [#439](https://github.com/igraph/python-igraph/pull/439) for more details. +- Fixed a bug that sometimes caused random crashes in + `Graph.Realize_Degree_Sequence()` and at other times caused weird errors in + `Graph.Read_Ncol()` when it received an invalid data type. + ## [0.9.6] ### Fixed From 477577961dfacc878c21454c86be81ba934515b9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Oct 2021 12:22:11 +0200 Subject: [PATCH 0665/1892] chore: bumped version to 0.9.7 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index eb5b48839..e94dd981f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.6' +version = '0.9.7' # The full version, including alpha/beta/rc tags. -release = '0.9.6' +release = '0.9.7' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index fd77afc92..752360a77 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 6) +__version_info__ = (0, 9, 7) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 55f88b642b4a19910ea0ee1fd78c63be095ac9c9 Mon Sep 17 00:00:00 2001 From: Gwyn Ciesla Date: Fri, 15 Oct 2021 09:41:48 -0500 Subject: [PATCH 0666/1892] Fix for #448. --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 5d5138f0d..88daf42a2 100644 --- a/setup.py +++ b/setup.py @@ -378,14 +378,13 @@ def build_ext(self) -> Command: of igraph before compiling the Python extension. """ from setuptools.command.build_ext import build_ext - from distutils.sysconfig import get_python_inc buildcfg = self class custom_build_ext(build_ext): def run(self): # Bail out if we don't have the Python include files - include_dir = get_python_inc() + include_dir = sysconfig.get_path('include') if not os.path.isfile(os.path.join(include_dir, "Python.h")): print("You will need the Python headers to compile this extension.") sys.exit(1) From 4105e3c0c3a025cd37f3f77cd7863113431b6021 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 15 Oct 2021 17:34:30 +0200 Subject: [PATCH 0667/1892] chore: updated changelog --- CHANGELOG.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 462823bc7..6d6851f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # igraph Python interface changelog -## [Unreleased] +## [0.9.8] + +### Fixed + +- `setup.py` no longer uses `distutils`, thanks to + [@limburgher](https://github.com/limburgher). + ([#449](https://github.com/igraph/python-igraph/pull/449)) + +## [0.9.7] ### Added @@ -201,7 +209,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[unreleased]: https://github.com/igraph/python-igraph/compare/0.9.6..master +[unreleased]: https://github.com/igraph/python-igraph/compare/0.9.7..master +[0.9.7]: https://github.com/igraph/python-igraph/compare/0.9.6...0.9.7 [0.9.6]: https://github.com/igraph/python-igraph/compare/0.9.5...0.9.6 [0.9.5]: https://github.com/igraph/python-igraph/compare/0.9.4...0.9.5 [0.9.4]: https://github.com/igraph/python-igraph/compare/0.9.1...0.9.4 From cd22d6c5bd01fb037e17b5a38fab95f54fe82009 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Wed, 13 Oct 2021 22:47:25 +0200 Subject: [PATCH 0668/1892] doc: Removed mentions of test in conda section. --- doc/source/install.rst | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 45c3759fc..a29159be3 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -61,7 +61,7 @@ The unit tests of `python-igraph` are implemented with the standard `unittest` m run them like this from your virtualenv: $ python -m unittest discover - + As usual, you can also do this without activating the virtualenv: $ venv/bin/python -m unittest discover @@ -75,14 +75,6 @@ using conda. That can be achieved by running the following command: $ conda install -c conda-forge python-igraph -To test the installed package, launch Python and run the following: - - >>> import igraph.test - >>> igraph.test.run_tests() - -The above commands run the bundled test cases to ensure that everything is fine with your -|igraph| installation. - |igraph| on Windows ------------------- From e42310eb0e64f93f8d8bc646dd8c43f33a09da6a Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Fri, 15 Oct 2021 12:20:18 +0200 Subject: [PATCH 0669/1892] doc: only explain tests when building from source. --- doc/source/install.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index a29159be3..11499ac65 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -57,15 +57,6 @@ in it directly: $ python -m venv venv $ venv/bin/pip install python-igraph -The unit tests of `python-igraph` are implemented with the standard `unittest` module so you can -run them like this from your virtualenv: - - $ python -m unittest discover - -As usual, you can also do this without activating the virtualenv: - - $ venv/bin/python -m unittest discover - Installing |igraph| via Conda ----------------------------- @@ -214,3 +205,11 @@ script to install it from there: $ python setup.py install .. note:: The `setup.py` script takes a number of options to customize the install location. + +Testing your installation +------------------------- + +The unit tests of `python-igraph` are implemented with the standard `unittest` module so you can +run them like this from your the source folder: + + $ python -m unittest discover From 18646292b068b38b12d94523733601d62f12a58f Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Fri, 15 Oct 2021 14:39:22 +0200 Subject: [PATCH 0670/1892] doc: corrected formatting for install. --- doc/source/install.rst | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 11499ac65..01e32fa7e 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -39,20 +39,20 @@ that you install it from the `Python Package Index and macOS. We aim to provide binary packages for the three latest minor versions of Python 3.x. To install |python-igraph| globally, use the following command (you probably need -administrator/root priviledges): +administrator/root priviledges):: $ pip install python-igraph Many users like to install packages into a project-specific `virtual environment `_. -A variation of the following commands should work on most platforms: +A variation of the following commands should work on most platforms:: $ python -m venv venv $ source venv/bin/activate $ pip install python-igraph -Alternatively, if you do not want to activate the virtualenv, you can call the `pip` executable -in it directly: +Alternatively, if you do not want to activate the virtualenv, you can call the ``pip`` executable +in it directly:: $ python -m venv venv $ venv/bin/pip install python-igraph @@ -62,7 +62,7 @@ Installing |igraph| via Conda Users of the `Anaconda Python distribution `_ or the `conda package manager `_ may opt to install |igraph|'s Python interface -using conda. That can be achieved by running the following command: +using conda. That can be achieved by running the following command:: $ conda install -c conda-forge python-igraph @@ -105,7 +105,7 @@ Graph plotting in |igraph| is implemented using a third-party package called `Ca on macOS, you must also install Cairo and its Python bindings. The Cairo project does not provide pre-compiled binaries for macOS, but the `Homebrew package manager `, so you can use it to install Cairo. After installing Homebrew itself, you -can run: +can run:: $ brew install cairo @@ -148,27 +148,27 @@ Both will be covered in the next sections. Compiling using pip ------------------- -If you want the development version of |python-igraph|, call: +If you want the development version of |python-igraph|, call:: $ pip install git+https://github.com/igraph/python-igraph -`pip` is smart enough to download the sources from Github, initialize the submodule for the |igraph| C core, +``pip`` is smart enough to download the sources from Github, initialize the submodule for the |igraph| C core, compile it, and then compile |python-igraph| against it and install it. As above, a virtual environment is a commonly used sandbox to test experimental packages. -If you want the latest release from PyPI but prefer to (or have to) install from source, call: +If you want the latest release from PyPI but prefer to (or have to) install from source, call:: $ pip install --no-binary ':all:' python-igraph -.. note:: If there is no binary for your system anyway, you can just try without the `--no-binary` option and +.. note:: If there is no binary for your system anyway, you can just try without the ``--no-binary`` option and obtain the same result. Compiling step by step ---------------------- This section should be rarely used in practice but explains how to compile and install |python-igraph| step -by step without `pip`. +by step without ``pip``. -First, obtain the bleeding-edge source code from Github: +First, obtain the bleeding-edge source code from Github:: $ git clone https://github.com/igraph/python-igraph.git @@ -176,40 +176,40 @@ or download a recent release from `PyPI `. Decompress the archive if needed. -Second, go into the folder: +Second, go into the folder:: $ cd python-igraph (it might have a slightly different name depending on the release). -Third, if you cloned the source from Github, initialize the `git` submodule for the |igraph| C core: +Third, if you cloned the source from Github, initialize the ``git`` submodule for the |igraph| C core:: $ git submodule update --init .. note:: If you prefer to compile and link |python-igraph| against an existing |igraph| C core, for instance - the one you installed with your package manager, you can skip the `git` submodule initialization step. If you - downloaded a tarball, you also need to remove the `vendor/source/igraph` folder because the setup script + the one you installed with your package manager, you can skip the ``git`` submodule initialization step. If you + downloaded a tarball, you also need to remove the ``vendor/source/igraph`` folder because the setup script will look for the vendored |igraph| copy first. However, a particular version of |python-igraph| is guaranteed - to work only with the version of the C core that is bundled with it (or with the revision that the `git` + to work only with the version of the C core that is bundled with it (or with the revision that the ``git`` submodule points to). -Fourth, call the standard Python `setup.py` script, e.g. for compiling: +Fourth, call the standard Python ``setup.py`` script, e.g. for compiling:: $ python setup.py build (press Enter when prompted). That will compile the |python-igraph| package in a subfolder called -`build/lib.`, e.g. `build/lib.linux-x86_64-3.8`. You can add -that folder to your `PYTHONPATH` if you want to import directly from it, or you can call the `setup.py` -script to install it from there: +``build/lib.``, e.g. `build/lib.linux-x86_64-3.8`. You can add +that folder to your ``PYTHONPATH`` if you want to import directly from it, or you can call the ``setup.py`` +script to install it from there:: $ python setup.py install -.. note:: The `setup.py` script takes a number of options to customize the install location. +.. note:: The ``setup.py`` script takes a number of options to customize the install location. Testing your installation ------------------------- -The unit tests of `python-igraph` are implemented with the standard `unittest` module so you can -run them like this from your the source folder: +The unit tests of ``python-igraph`` are implemented with the standard ``unittest`` module so you can +run them like this from your the source folder:: $ python -m unittest discover From 977547a4a7ba4ee31ba50ee47e4b8209f264848a Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Fri, 15 Oct 2021 14:40:55 +0200 Subject: [PATCH 0671/1892] doc: corrected link in install section. --- doc/source/install.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 01e32fa7e..290945aec 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -104,7 +104,7 @@ Graph plotting in |igraph| is implemented using a third-party package called `Ca `_. If you want to create publication-quality plots in |igraph| on macOS, you must also install Cairo and its Python bindings. The Cairo project does not provide pre-compiled binaries for macOS, but the `Homebrew package manager -`, so you can use it to install Cairo. After installing Homebrew itself, you +`_, so you can use it to install Cairo. After installing Homebrew itself, you can run:: $ brew install cairo @@ -172,8 +172,8 @@ First, obtain the bleeding-edge source code from Github:: $ git clone https://github.com/igraph/python-igraph.git -or download a recent release from `PyPI ` or from the -`Github releases page `. Decompress the archive if +or download a recent release from `PyPI `_ or from the +`Github releases page `_. Decompress the archive if needed. Second, go into the folder:: From 879c0a418d8dacaa2ea2c68073b035a5b3caad82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Fri, 15 Oct 2021 17:51:09 +0200 Subject: [PATCH 0672/1892] doc: fix typo --- doc/source/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 290945aec..c02177cf6 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -39,7 +39,7 @@ that you install it from the `Python Package Index and macOS. We aim to provide binary packages for the three latest minor versions of Python 3.x. To install |python-igraph| globally, use the following command (you probably need -administrator/root priviledges):: +administrator/root privileges):: $ pip install python-igraph From e79ac0a34143616273f35023c2d692ae14809284 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 17 Oct 2021 21:45:13 +0200 Subject: [PATCH 0673/1892] chore: mention Python 3.10 support in more places --- README.md | 8 ++++---- setup.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e276509f9..7c10bd183 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) -[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue)](https://pypi.python.org/pypi/python-igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/python-igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) Python interface for the igraph library @@ -18,9 +18,9 @@ You can learn more about python-igraph [on our website](http://igraph.org/python ## Installation from PyPI We aim to provide wheels on PyPI for most of the stock Python versions; -typically the three most recent minor releases from Python 3.x. Therefore, -running the following command should work without having to compile anything -during installation: +typically at least the three most recent minor releases from Python 3.x. +Therefore, running the following command should work without having to compile +anything during installation: ``` pip install python-igraph diff --git a/setup.py b/setup.py index 88daf42a2..4fffda6a7 100644 --- a/setup.py +++ b/setup.py @@ -863,6 +863,7 @@ def use_educated_guess(self) -> None: "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics", From a7e8fa3ef3b8f3760aec389805e9dfa4e88963b9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 18 Oct 2021 12:40:14 +0200 Subject: [PATCH 0674/1892] doc: markup fixes; code blocks should be indented and they should be preceded by '::', refs #447 --- doc/source/analysis.rst | 194 +++++++-------- doc/source/generation.rst | 99 ++++---- doc/source/install.rst | 4 +- doc/source/intro.rst | 1 - doc/source/misc.rst | 1 - doc/source/tutorial.rst | 444 ++++++++++++++++++----------------- doc/source/visualisation.rst | 111 ++++----- 7 files changed, 450 insertions(+), 404 deletions(-) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 79ee0a437..3fb657225 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -2,17 +2,18 @@ Graph analysis ============== + |igraph| enables analysis of graphs/networks from simple operations such as adding and removing nodes to complex theoretical constructs such as community detection. Read the `API documentation`_ for details on each function and class. -The context for the following examples will be to import |igraph| (commonly as `ig`), have the :class:`Graph` class and to have one or more graphs available: +The context for the following examples will be to import |igraph| (commonly as `ig`), have the :class:`Graph` class and to have one or more graphs available:: ->>> import igraph as ig ->>> from igraph import Graph ->>> g = Graph(edges=[[0, 1], [2, 3]]) + >>> import igraph as ig + >>> from igraph import Graph + >>> g = Graph(edges=[[0, 1], [2, 3]]) -To get a summary representation of the graph, use :meth:`Graph.summary`. For instance +To get a summary representation of the graph, use :meth:`Graph.summary`. For instance:: ->>> g.summary(verbosity=1) + >>> g.summary(verbosity=1) will provide a fairly detailed description. @@ -20,31 +21,32 @@ To copy a graph, use :meth:`Graph.copy`. This is a "shallow" copy: any mutable o If you want to copy a graph including all its attributes, use Python's `deepcopy` module. Vertices and edges -+++++++++++++++++++++++++++ +++++++++++++++++++ + Vertices are numbered 0 to `n-1`, where n is the number of vertices in the graph. These are called the "vertex ids". -To count vertices, use :meth:`Graph.vcount`: +To count vertices, use :meth:`Graph.vcount`:: ->>> n = g.vcount() + >>> n = g.vcount() -Edges also have ids from 0 to `m-1` and are counted by :meth:`Graph.ecount`: +Edges also have ids from 0 to `m-1` and are counted by :meth:`Graph.ecount`:: ->>> m = g.ecount() + >>> m = g.ecount() -To get a sequence of vertices, use their ids and :attr:`Graph.vs`: +To get a sequence of vertices, use their ids and :attr:`Graph.vs`:: ->>> for v in g.vs: ->>> print(v) + >>> for v in g.vs: + >>> print(v) -Similarly for edges, use :attr:`Graph.es`: +Similarly for edges, use :attr:`Graph.es`:: ->>> for e in g.es: ->>> print(e) + >>> for e in g.es: + >>> print(e) -You can index and slice vertices and edges similar to a list: +You can index and slice vertices and edges like indexing and slicing a list:: ->>> g.vs[:4] ->>> g.vs[0, 2, 4] ->>> g.es[3] + >>> g.vs[:4] + >>> g.vs[0, 2, 4] + >>> g.es[3] .. note:: The `vs` and `es` attributes are special sequences with their own useful methods. See `API documentation`_ for a full list. @@ -52,46 +54,47 @@ If you prefer a vanilla edge list, you can use :meth:`Graph.get_edge_list`. Incidence ++++++++++++++++++++++++++++++ -To get the vertices at the two ends of an edge, use :attr:`Edge.source` and :attr:`Edge.target`: +To get the vertices at the two ends of an edge, use :attr:`Edge.source` and :attr:`Edge.target`:: ->>> e = g.es[0] ->>> v1, v2 = e.source, e.target + >>> e = g.es[0] + >>> v1, v2 = e.source, e.target Vice versa, to get the edge if from the source and target vertices, you can use :meth:`Graph.get_eid` or, for multiple pairs of source/targets, :meth:`Graph.get_eids`. The boolean version, asking whether two vertices are directly connected, is :meth:`Graph.are_connected`. To get the edges incident on a vertex, you can use :meth:`Vertex.incident`, :meth:`Vertex.out_edges` and -:meth:`Vertex.in_edges`. The three are equivalent on undirected graphs but not directed ones, of course: +:meth:`Vertex.in_edges`. The three are equivalent on undirected graphs but not directed ones of course:: ->>> v = g.vs[0] ->>> edges = v.incident() + >>> v = g.vs[0] + >>> edges = v.incident() -The :meth:`Graph.incident` function fulfills the same purpose with a slightly different syntax based on vertex ids: +The :meth:`Graph.incident` function fulfills the same purpose with a slightly different syntax based on vertex IDs:: ->>> edges = g.incident(0) + >>> edges = g.incident(0) To get the full adjacency/incidence list representation of the graph, use :meth:`Graph.get_adjlist`, :meth:`Graph.g.get_inclist()` or, for a bipartite graph, :meth:`Graph.get_incidence`. Neighborhood -+++++++++++++ +++++++++++++ + To compute the neighbors, successors, and predecessors, the methods :meth:`Graph.neighbors`, :meth:`Graph.successors` and -:meth:`Graph.predecessors` are available. The three give the same answer in undirected graphs and have a similar dual syntax: +:meth:`Graph.predecessors` are available. The three give the same answer in undirected graphs and have a similar dual syntax:: ->>> neis = g.vs[0].neighbors() ->>> neis = g.neighbors(0) + >>> neis = g.vs[0].neighbors() + >>> neis = g.neighbors(0) -To get the list of vertices within a certain distance from one or more initial vertices, you can use :meth:`Graph.neighborhood`: +To get the list of vertices within a certain distance from one or more initial vertices, you can use :meth:`Graph.neighborhood`:: ->>> g.neighborhood([0, 1], order=2) + >>> g.neighborhood([0, 1], order=2) and to find the neighborhood size, there is :meth:`Graph.neighborhood_size`. Degrees +++++++ -To compute the degree, in-degree, or out-degree of a node, use :meth:`Vertex.degree`, :meth:`Vertex.indegree`, and :meth:`Vertex.outdegree`: +To compute the degree, in-degree, or out-degree of a node, use :meth:`Vertex.degree`, :meth:`Vertex.indegree`, and :meth:`Vertex.outdegree`:: ->>> deg = g.vs[0].degree() ->>> deg = g.degree(0) + >>> deg = g.vs[0].degree() + >>> deg = g.degree(0) To compute the max degree in a list of vertices, use :meth:`Graph.maxdegree`. @@ -100,81 +103,84 @@ To compute the max degree in a list of vertices, use :meth:`Graph.maxdegree`. Adding and removing vertices and edges ++++++++++++++++++++++++++++++++++++++ -To add nodes to a graph, use :meth:`Graph.add_vertex` and :meth:`Graph.add_vertices`: +To add nodes to a graph, use :meth:`Graph.add_vertex` and :meth:`Graph.add_vertices`:: ->>> g.add_vertex() ->>> g.add_vertices(5) + >>> g.add_vertex() + >>> g.add_vertices(5) This changes the graph `g` in place. You can specify the name of the vertices if you wish. -To remove nodes, use :meth:`Graph.delete_vertices`: +To remove nodes, use :meth:`Graph.delete_vertices`:: ->>> g.delete_vertices([1, 2]) + >>> g.delete_vertices([1, 2]) Again, you can specify the names or the actual :class:`Vertex` objects instead. -To add edges, use :meth:`Graph.add_edge` and :meth:`Graph.add_edges`: +To add edges, use :meth:`Graph.add_edge` and :meth:`Graph.add_edges`:: ->>> g.add_edge(0, 2) ->>> g.add_edges([(0, 2), (1, 3)]) + >>> g.add_edge(0, 2) + >>> g.add_edges([(0, 2), (1, 3)]) -To remove edges, use :meth:`Graph.delete_edges`: +To remove edges, use :meth:`Graph.delete_edges`:: ->>> g.delete_edges([0, 5]) # remove by edge id + >>> g.delete_edges([0, 5]) # remove by edge id You can also remove edges between source and target nodes. To contract vertices, use :meth:`Graph.contract_vertices`. Edges between contracted vertices will become loops. Graph operators -+++++++++++++++++ ++++++++++++++++ + It is possible to compute the union, intersection, difference, and other set operations (operators) between graphs. -To compute the union of the graphs (nodes/edges in either are kept): +To compute the union of the graphs (nodes/edges in either are kept):: ->>> gu = ig.union([g, g2, g3]) + >>> gu = ig.union([g, g2, g3]) -Similarly for the intersection (nodes/edges present in all are kept): +Similarly for the intersection (nodes/edges present in all are kept):: ->>> gu = ig.intersection([g, g2, g3]) + >>> gu = ig.intersection([g, g2, g3]) These two operations preserve attributes and can be performed with a few variations. The most important one is that vertices can be matched across the graphs by id (number) or by name. -These and other operations are also available as methods of the :class:`Graph` class: +These and other operations are also available as methods of the :class:`Graph` class:: ->>> g.union(g2) ->>> g.intersection(g2) ->>> g.disjoint_union(g2) ->>> g.difference(g2) ->>> g.complementer() # complement graph, same nodes but missing edges + >>> g.union(g2) + >>> g.intersection(g2) + >>> g.disjoint_union(g2) + >>> g.difference(g2) + >>> g.complementer() # complement graph, same nodes but missing edges -and even as numerical operators: +and even as numerical operators:: ->>> g |= g2 ->>> g_intersection = g and g2 + >>> g |= g2 + >>> g_intersection = g and g2 Topological sorting +++++++++++++++++++ -To sort a graph topologically, use :meth:`Graph.topological_sorting`: ->>> g = ig.Graph.Tree(10, 2, mode=ig.TREE_OUT) ->>> g.topological_sorting() +To sort a graph topologically, use :meth:`Graph.topological_sorting`:: + + >>> g = ig.Graph.Tree(10, 2, mode=ig.TREE_OUT) + >>> g.topological_sorting() Graph traversal -+++++++++++++++++++++ -A common operation is traversing the graph. |igraph| currently exposes breadth-first search (BFS) via :meth:`Graph.bfs` and :meth:`Graph.bfsiter`: ++++++++++++++++ ->>> [vertices, layers, parents] = g.bfs() ->>> it = g.bfsiter() # Lazy version +A common operation is traversing the graph. |igraph| currently exposes breadth-first search (BFS) via :meth:`Graph.bfs` and :meth:`Graph.bfsiter`:: -Depth-first search has a similar infrastructure via :meth:`Graph.dfs` and :meth:`Graph.dfsiter`: + >>> [vertices, layers, parents] = g.bfs() + >>> it = g.bfsiter() # Lazy version ->>> [vertices, parents] = g.dfs() ->>> it = g.dfsiter() # Lazy version +Depth-first search has a similar infrastructure via :meth:`Graph.dfs` and :meth:`Graph.dfsiter`:: -To perform a random walk from a certain vertex, use :meth:`Graph.random_walk`: + >>> [vertices, parents] = g.dfs() + >>> it = g.dfsiter() # Lazy version ->>> vids = g.random_walk(0, 3) +To perform a random walk from a certain vertex, use :meth:`Graph.random_walk`:: + + >>> vids = g.random_walk(0, 3) Pathfinding and cuts ++++++++++++++++++++ @@ -198,7 +204,8 @@ As well as functions related to cuts and paths: See also the section on flow. Global properties -+++++++++++++++++++++ ++++++++++++++++++ + A number of global graph measures are available. Basic: @@ -347,20 +354,20 @@ Clustering Simplification, permutations and rewiring +++++++++++++++++++++++++++++++++++++++++ -To check is a graph is simple, you can use :meth:`Graph.is_simple`. +To check is a graph is simple, you can use :meth:`Graph.is_simple`:: ->>> g.is_simple() + >>> g.is_simple() -To simplify a graph (remove multiedges and loops), use :meth:`Graph.simplify`: +To simplify a graph (remove multiedges and loops), use :meth:`Graph.simplify`:: ->>> g_simple = g.simplify() + >>> g_simple = g.simplify() To return a directed/undirected copy of the graph, use :meth:`Graph.as_directed` and :meth:`Graph.as_undirected`, respectively. -To permute the order of vertices, you can use :meth:`Graph.permute_vertices`: +To permute the order of vertices, you can use :meth:`Graph.permute_vertices`:: ->>> g = ig.Tree(6, 2) ->>> g_perm = g.permute_vertices([1, 0, 2, 3, 4, 5]) + >>> g = ig.Tree(6, 2) + >>> g_perm = g.permute_vertices([1, 0, 2, 3, 4, 5]) The canonical permutation can be obtained via :meth:`Graph.canonical_permutation`, which can then be directly passed to the function above. @@ -371,22 +378,23 @@ To rewire the graph at random, there are: Line graph ++++++++++ -To compute the line graph of a graph `g`, which represents the connectedness of the *edges* of g, you can use :meth:`Graph.linegraph`: ->>> g = Graph(n=4, edges=[[0, 1], [0, 2]]) ->>> gl = g.linegraph() +To compute the line graph of a graph `g`, which represents the connectedness of the *edges* of g, you can use :meth:`Graph.linegraph`:: + + >>> g = Graph(n=4, edges=[[0, 1], [0, 2]]) + >>> gl = g.linegraph() -In this case, the line graph has two vertices, representing the two edges of the original graph, and one edge, representing the point where -those two original edges touch. +In this case, the line graph has two vertices, representing the two edges of the original graph, and one edge, representing the point where those two original edges touch. Composition and subgraphs -++++++++++++++++++++++++++ ++++++++++++++++++++++++++ + The function :meth:`Graph.decompose` decomposes the graph into subgraphs. Vice versa, the function :meth:`Graph.compose` returns the composition of two graphs. -To compute the subgraph spannes by some vertices/edges, use :meth:`Graph.subgraph` (aka :meth:`Graph.induced_subgraph`) and :meth:`Graph.subgraph_edges`: +To compute the subgraph spannes by some vertices/edges, use :meth:`Graph.subgraph` (aka :meth:`Graph.induced_subgraph`) and :meth:`Graph.subgraph_edges`:: ->>> g_sub = g.subgraph([0, 1]) ->>> g_sub = g.subgraph_edges([0]) + >>> g_sub = g.subgraph([0, 1]) + >>> g_sub = g.subgraph_edges([0]) To compute the minimum spanning tree, use :meth:`Graph.spanning_tree`. @@ -397,7 +405,8 @@ The dominator tree from a given node can be obtained with :meth:`Graph.dominator Bipartite graphs can be decomposed using :meth:`Graph.bipartite_projection`. The size of the projections can be computed using :meth:`Graph.bipartite_projection_size`. Morphisms -++++++++++++++++++ ++++++++++ + |igraph| enables comparisons between graphs: - :meth:`Graph.isomorphic` @@ -414,6 +423,7 @@ Morphisms Flow ++++ + Flow is a characteristic of directed graphs. The following functions are available: - :meth:`Graph.maxflow` between two nodes diff --git a/doc/source/generation.rst b/doc/source/generation.rst index d41da27d4..47e048e90 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -5,29 +5,32 @@ Graph generation The first step of most |igraph| applications is to generate a graph. This section will explain a number of ways to do that. Read the `API documentation`_ for details on each function and class. -The :class:`Graph` class is the main object used to generate graphs: +The :class:`Graph` class is the main object used to generate graphs:: ->>> from igraph import Graph + >>> from igraph import Graph -To copy a graph, use :meth:`Graph.copy`: +To copy a graph, use :meth:`Graph.copy`:: ->>> g_new = g.copy() + >>> g_new = g.copy() From nodes and edges ++++++++++++++++++++ + Nodes are always numbered from 0 upwards. To create a generic graph with a specified number of nodes (e.g. 10) and a list of edges between them, you can use the generic constructor: ->>> g = Graph(n=10, edges=[[0, 1], [2, 3]]) + >>> g = Graph(n=10, edges=[[0, 1], [2, 3]]) -If not specified, the graph is undirected. To make a directed graph: +If not specified, the graph is undirected. To make a directed graph:: ->>> g = Graph(n=10, edges=[[0, 1], [2, 3]], directed=True) + >>> g = Graph(n=10, edges=[[0, 1], [2, 3]], directed=True) -To specify edge weights (or any other vertex/edge attributes), use dictionaries: +To specify edge weights (or any other vertex/edge attributes), use dictionaries:: ->>> g = Graph(n=4, edges=[[0, 1], [2, 3]], ->>> edge_attrs={'weight': [0.1, 0.2]}, ->>> vertex_attrs={'color': ['b', 'g', 'g', 'y']}) + >>> g = Graph( + ... n=4, edges=[[0, 1], [2, 3]], + ... edge_attrs={'weight': [0.1, 0.2]}, + ... vertex_attrs={'color': ['b', 'g', 'g', 'y']} + ... ) Variations on this constructor is :meth:`Graph.DictList`, which constructs a graph from a list-of-dictionaries representation, and :meth:`Graph.TupleList`, which constructs a graph from a list-of-tuples representation. @@ -35,71 +38,79 @@ To create a bipartite graph from a list of types and a list of edges, use :meth: From matrices +++++++++++++ -To create a graph from an adjecency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`: +To create a graph from an adjecency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`:: ->>> g = Graph.Adjacency([[0, 1, 1], [0, 0, 0], [0, 0, 1]]) + >>> g = Graph.Adjacency([[0, 1, 1], [0, 0, 0], [0, 0, 1]]) This graph is directed and has edges `[0, 1]`, `[0, 2]` and `[2, 2]` (a loop). -To create a bipartite graph from an incidence matrix, use :meth:`Graph.Incidence`: +To create a bipartite graph from an incidence matrix, use :meth:`Graph.Incidence`:: ->>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) + >>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) From file +++++++++ -To load a graph from a preexisting file in any of the supported formats, use :meth:`Graph.Load`. For instance: ->>> g = Graph.Load('myfile.gml', format='gml') +To load a graph from a preexisting file in any of the supported formats, use :meth:`Graph.Load`. For instance:: + + >>> g = Graph.Load('myfile.gml', format='gml') If you don't specify a format, |igraph| will try to figure it out or, if that fails, it will complain. From external libraries +++++++++++++++++++++++ -|igraph| can read from and write to `networkx` and `graph-tool` graph formats: ->>> g = Graph.from_networkx(nwx) +|igraph| can read from and write to `networkx` and `graph-tool` graph formats:: + + >>> g = Graph.from_networkx(nwx) and ->>> g = Graph.from_graph_tool(gt) +:: + + >>> g = Graph.from_graph_tool(gt) From pandas DataFrame(s) ++++++++++++++++++++++++ + A common practice is to store edges in a `pandas.DataFrame`, where the two first columns are the source and target vertex ids, -and any additional column indicates edge attributes. You can generate a graph via :meth:`Graph.DataFrame`: +and any additional column indicates edge attributes. You can generate a graph via :meth:`Graph.DataFrame`:: ->>> g = Graph.DataFrame(edges, directed=False) + >>> g = Graph.DataFrame(edges, directed=False) It is possible to set vertex attributes at the same time via a separate DataFrame. The first column is assumed to contain all -vertex ids (including any vertices without edges) and any additional columns are vertex attributes: +vertex ids (including any vertices without edges) and any additional columns are vertex attributes:: ->>> g = Graph.DataFrame(edges, directed=False, vertices=vertices) + >>> g = Graph.DataFrame(edges, directed=False, vertices=vertices) From a formula ++++++++++++++ -To create a graph from a string formula, use :meth:`Graph.Formula`, e.g.: ->>> g = Graph.Formula('D-A:B:F:G, A-C-F-A, B-E-G-B, A-B, F-G, H-F:G, H-I-J') +To create a graph from a string formula, use :meth:`Graph.Formula`, e.g.:: + + >>> g = Graph.Formula('D-A:B:F:G, A-C-F-A, B-E-G-B, A-B, F-G, H-F:G, H-I-J') .. note:: This particular formula also assigns the 'name' attribute to vertices. Full graphs +++++++++++ -To create a full graph, use :meth:`Graph.Full`: ->>> g = Graph.Full(n=3) +To create a full graph, use :meth:`Graph.Full`:: + + >>> g = Graph.Full(n=3) -where `n` is the number of nodes. You can specify directedness and whether self loops are allowed: +where `n` is the number of nodes. You can specify directedness and whether self loops are allowed:: ->>> g = Graph.Full(n=3, directed=True, loops=True) + >>> g = Graph.Full(n=3, directed=True, loops=True) A similar method, :meth:`Graph.Full_Bipartite`, generates a full bipartite graph. Finally, the metho :meth:`Graph.Full_Citation` created the full citation graph, in which each vertex `i` has a directed edge to all vertices strictly smaller than `i`. Tree and star +++++++++++++ -:meth:`Graph.Tree` can be used to generate regular trees, in which almost each vertex has the same number of children: ->>> g = Graph.Tree(n=7, n_children=2) +:meth:`Graph.Tree` can be used to generate regular trees, in which almost each vertex has the same number of children:: + + >>> g = Graph.Tree(n=7, n_children=2) creates a tree with seven vertices - of which four are leaves. The root (0) has two children (1 and 2), each of which has two children (the four leaves). Regular trees can be directed or undirected (default). @@ -107,21 +118,23 @@ The method :meth:`Graph.Star` creates a star graph, which is a subtype of a tree Lattice +++++++ -:meth:`Graph.Lattice` creates a regular lattice of the chosen size. For instance: ->>> g = Graph.Lattice(dim=[3, 3], circular=False) +:meth:`Graph.Lattice` creates a regular lattice of the chosen size. For instance:: + + >>> g = Graph.Lattice(dim=[3, 3], circular=False) creates a 3x3 grid in two dimensions (9 vertices total). `circular` is used to connect each edge of the lattice back onto the other side, a process also known as "periodic boundary condition" that is sometimes helpful to smoothen out edge effects. -The one dimensional case (path graph or ring) is important enough to deserve its own constructor :meth:`Graph.Ring`, which can be circular or not: +The one dimensional case (path graph or ring) is important enough to deserve its own constructor :meth:`Graph.Ring`, which can be circular or not:: ->>> g = Graph.Ring(n=4, circular=False) + >>> g = Graph.Ring(n=4, circular=False) -Graph atlas +Graph Atlas +++++++++++ -The book ‘An Atlas of Graphs’ by Roland C. Read and Robin J. Wilson contains all undirected graphs with up to seven vertices, numbered from 0 up to 1252. You can create any graph from this list by index with :meth:`Graph.Atlas`, e.g.: ->>> g = Graph.Atlas(44) +The book ‘An Atlas of Graphs’ by Roland C. Read and Robin J. Wilson contains all undirected graphs with up to seven vertices, numbered from 0 up to 1252. You can create any graph from this list by index with :meth:`Graph.Atlas`, e.g.:: + + >>> g = Graph.Atlas(44) The graphs are listed: @@ -130,12 +143,12 @@ The graphs are listed: - for fixed numbers of nodes and edges, in increasing order of the degree sequence, for example 111223 < 112222; - for fixed degree sequence, in increasing number of automorphisms. - Famous graphs +++++++++++++ -A curated list of famous graphs, which are often used in the literature for benchmarking and other purposes, is available on the `igraph C core manual `_. You can generate any graph in that list by name, e.g.: ->>> g = Graph.Famous('Zachary') +A curated list of famous graphs, which are often used in the literature for benchmarking and other purposes, is available on the `igraph C core manual `_. You can generate any graph in that list by name, e.g.:: + + >>> g = Graph.Famous('Zachary') will teach you some about martial arts. @@ -162,9 +175,9 @@ Stochastic graphs can be created according to several different models or games: - random graph with a given degree sequence :meth:`Graph.Degree_Sequence` - bipartite :meth:`Graph.Random_Bipartite` - Other graphs ++++++++++++ + Finally, there are some ways of generating graphs that are not covered by the previous sections: - Kautz graphs :meth:`Graph.Kautz` diff --git a/doc/source/install.rst b/doc/source/install.rst index c02177cf6..f786c12d6 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -73,8 +73,6 @@ Precompiled Windows wheels for |igraph|'s Python interface are available on the `_ (see `Installing igraph from the Python Package Index`_). -TODO: Check if Windows still requires special steps to get PyCairo running. - Graph plotting in |igraph| is implemented using a third-party package called `Cairo `_. If you want to create publication-quality plots in |igraph| on Windows, you must also install Cairo and its Python bindings. The Cairo project does not @@ -148,6 +146,7 @@ Both will be covered in the next sections. Compiling using pip ------------------- + If you want the development version of |python-igraph|, call:: $ pip install git+https://github.com/igraph/python-igraph @@ -165,6 +164,7 @@ If you want the latest release from PyPI but prefer to (or have to) install from Compiling step by step ---------------------- + This section should be rarely used in practice but explains how to compile and install |python-igraph| step by step without ``pip``. diff --git a/doc/source/intro.rst b/doc/source/intro.rst index 34db9acf7..8ed105ac9 100644 --- a/doc/source/intro.rst +++ b/doc/source/intro.rst @@ -14,4 +14,3 @@ Things you should know before starting out Reporting bugs and providing feedback ===================================== - diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 966896a45..65cd44207 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -2,4 +2,3 @@ Miscellaneous topics ==================== .. note:: TODO. This is a placeholder section; it is not written yet. - diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 854c9195b..57e972502 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -32,18 +32,18 @@ ordinary Python module at the Python prompt:: This imports |igraph|'s objects and methods inside an own namespace called :mod:`igraph`. Whenever you would like to call any of |igraph|'s methods, you will have to provide the appropriate namespace-qualification. E.g., to check which |igraph| version you are using, you could do the -following: +following:: ->>> import igraph ->>> print(igraph.__version__) -0.9.6 + >>> import igraph + >>> print(igraph.__version__) + 0.9.6 Another way to make use of |igraph| is to import all its objects and methods into the main Python namespace (so you do not have to type the namespace-qualification every time). This is fine as long as your own objects and methods do not conflict with the ones -provided by |igraph|: +provided by |igraph|:: ->>> from igraph import * + >>> from igraph import * The third way to start |igraph| is to simply call the startup script that was supplied with the |igraph| package you installed. Not too surprisingly, the script is called :command:`igraph`, @@ -88,32 +88,34 @@ Creating a graph from scratch ============================= Assuming that you have started |igraph| successfully, it is time to create your first -|igraph| graph. This is pretty simple: +|igraph| graph. This is pretty simple:: ->>> g = Graph() + >>> g = Graph() The above statement created an undirected graph with no vertices or edges and assigned it to the variable `g`. To confirm that it's really an |igraph| graph, we can -print it: +print it:: ->>> g - + >>> g + This tells us that `g` is an instance of |igraph|'s :class:`Graph` class and that it is currently living at the memory address ``0x4c87a0`` (the exact output will almost surely be different for your platform). To obtain a more user-friendly output, we can try to print the graph using Python's -``print`` statement: +``print`` statement:: ->>> print(g) -IGRAPH U--- 0 0 -- + >>> print(g) + IGRAPH U--- 0 0 -- This summary consists of `IGRAPH`, followed by a four-character long code, the number of vertices, the number of edges, two dashes (`--`) and the name of the graph (i.e. the contents of the `name` attribute, if any) This is not too exciting so far; a graph with no vertices and no edges is not really useful for us. Let's add some vertices first! ->>> g.add_vertices(3) +:: + + >>> g.add_vertices(3) :meth:`Graph.add_vertices` (i.e., the :meth:`~Graph.add_vertices` method of the :class:`Graph` class) adds the given number of vertices to the graph. @@ -125,20 +127,20 @@ first vertex of your graph has index zero, the second vertex has index 1 and so Edges are specified by pairs of integers, so ``[(0,1), (1,2)]`` denotes a list of two edges: one between the first and the second, and the other one between the second and the third vertices of the graph. Passing this list to :meth:`Graph.add_edges` adds these two edges -to your graph: +to your graph:: ->>> g.add_edges([(0,1), (1,2)]) + >>> g.add_edges([(0,1), (1,2)]) :meth:`~Graph.add_edges` is clever enough to figure out what you want to do in most of the cases: if you supply a single pair of integers, it will automatically assume that you want to add a single edge. However, if you try to add edges to vertices with invalid IDs (i.e., you try to add an edge to vertex 5 when you only have three vertices), you will get an -exception: +exception:: ->>> g.add_edges((5, 0)) -Traceback (most recent call last): - File "", line 6, in -TypeError: iterable must return pairs of integers or strings + >>> g.add_edges((5, 0)) + Traceback (most recent call last): + File "", line 6, in + TypeError: iterable must return pairs of integers or strings Most |igraph| functions will raise an :exc:`igraph.InternalError` if something goes wrong. The message corresponding to the exception gives you a @@ -148,15 +150,15 @@ occurred. The exact filename and line number may not be too informative to you, but it is invaluable for |igraph| developers if you think you found an error in |igraph| and you want to report it. -Let us go on with our graph ``g`` and add some more vertices and edges to it: +Let us go on with our graph ``g`` and add some more vertices and edges to it:: ->>> g.add_edges([(2, 0)]) ->>> g.add_vertices(3) ->>> g.add_edges([(2, 3), (3, 4), (4, 5), (5, 3)]) ->>> print(g) -IGRAPH U---- 6 7 -- -+ edges: -0--1 1--2 0--2 2--3 3--4 4--5 3--5 + >>> g.add_edges([(2, 0)]) + >>> g.add_vertices(3) + >>> g.add_edges([(2, 3), (3, 4), (4, 5), (5, 3)]) + >>> print(g) + IGRAPH U---- 6 7 -- + + edges: + 0--1 1--2 0--2 2--3 3--4 4--5 3--5 Now, this is better. We have an undirected graph with six vertices and seven edges, and you can also see the list of edges in |igraph|'s output. Edges also @@ -174,11 +176,13 @@ vertices at its two endpoints, you can use :meth:`~Graph.get_eid` to get the edge ID. Remember, all these are *methods* of the :class:`Graph` class and you must call them on the appropriate :class:`Graph` instance! ->>> g.get_eid(2, 3) -3 ->>> g.delete_edges(3) ->>> summary(g) -IGRAPH U--- 6 6 -- +:: + + >>> g.get_eid(2, 3) + 3 + >>> g.delete_edges(3) + >>> summary(g) + IGRAPH U--- 6 6 -- :meth:`summary` is a new command that you haven't seen before; it is a member of |igraph|'s own namespace and it can be used to get an overview of a given graph object. Its output @@ -198,20 +202,20 @@ creating trees, regular lattices, rings, extended chordal rings, several famous and so on, while stochastic generators are used to create Erdős-Rényi random networks, Barabási-Albert networks, geometric random graphs and such. |igraph| has too many generators to cover them all in this tutorial, so we will only try a -deterministic and a stochastic generator instead: +deterministic and a stochastic generator instead:: ->>> g = Graph.Tree(127, 2) ->>> summary(g) -IGRAPH U--- 127 126 -- + >>> g = Graph.Tree(127, 2) + >>> summary(g) + IGRAPH U--- 127 126 -- :meth:`Graph.Tree` generates a regular tree graph. The one that we generated has 127 vertices and each vertex (apart from the leaves) has two children (and of course one parent). No matter how many times you call :meth:`Graph.Tree`, the generated graph will -always be the same if you use the same parameters: +always be the same if you use the same parameters:: ->>> g2 = Graph.Tree(127, 2) ->>> g2.get_edgelist() == g.get_edgelist() -True + >>> g2 = Graph.Tree(127, 2) + >>> g2.get_edgelist() == g.get_edgelist() + True The above code snippet also shows you that the :meth:`~Graph.get_edgelist()` method of :class:`Graph` graph objects return a list that contains pairs of integers, one for @@ -219,15 +223,19 @@ each edge. The first member of the pair is the source vertex ID and the second m is the target vertex ID of the corresponding edge. This list is too long, so let's just print the first 10 elements! ->>> g2.get_edgelist()[0:10] -[(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6), (3, 7), (3, 8), (4, 9), (4, 10)] +:: + + >>> g2.get_edgelist()[0:10] + [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6), (3, 7), (3, 8), (4, 9), (4, 10)] Let's do the same with a stochastic generator! ->>> g = Graph.GRG(100, 0.2) ->>> summary(g) -IGRAPH U---- 100 516 -- -+ attr: x (v), y (v) +:: + + >>> g = Graph.GRG(100, 0.2) + >>> summary(g) + IGRAPH U---- 100 516 -- + + attr: x (v), y (v) where ``+ attr`` shows names of the attributes for vertices (v) and edges (e). @@ -238,13 +246,13 @@ the random nature of the algorithm, chances are that the exact graph you got is from the one that was generated when I wrote this tutorial, hence the values above in the summary will not match the ones you got. This is normal and expected. Even if you generate two geometric random graphs on the same machine, they will be different for the same parameter -set: +set:: ->>> g2 = Graph.GRG(100, 0.2) ->>> g.get_edgelist() == g2.get_edgelist() -False ->>> g.isomorphic(g2) -False + >>> g2 = Graph.GRG(100, 0.2) + >>> g.get_edgelist() == g2.get_edgelist() + False + >>> g.isomorphic(g2) + False :meth:`~Graph.isomorphic()` tells you whether two graphs are isomorphic or not. In general, it might take quite a lot of time, especially for large graphs, but in our case, the @@ -280,21 +288,23 @@ and the value representing the attribute itself. Let us create a simple imaginary social network the usual way by hand. ->>> g = Graph([(0,1), (0,2), (2,3), (3,4), (4,2), (2,5), (5,0), (6,3), (5,6)]) +:: + + >>> g = Graph([(0,1), (0,2), (2,3), (3,4), (4,2), (2,5), (5,0), (6,3), (5,6)]) Now, let us assume that we want to store the names, ages and genders of people in this network as vertex attributes, and for every connection, we want to store whether this is an informal friendship tie or a formal tie. Every :class:`Graph` object contains two special members called :attr:`~Graph.vs` and :attr:`~Graph.es`, standing for the sequence of all vertices and all edges, respectively. If you try to use :attr:`~Graph.vs` or :attr:`~Graph.es` as -a Python dictionary, you will manipulate the attribute storage area of the graph: +a Python dictionary, you will manipulate the attribute storage area of the graph:: ->>> g.vs - ->>> g.vs["name"] = ["Alice", "Bob", "Claire", "Dennis", "Esther", "Frank", "George"] ->>> g.vs["age"] = [25, 31, 18, 47, 22, 23, 50] ->>> g.vs["gender"] = ["f", "m", "f", "m", "f", "m", "m"] ->>> g.es["is_formal"] = [False, False, True, True, True, False, True, False, False] + >>> g.vs + + >>> g.vs["name"] = ["Alice", "Bob", "Claire", "Dennis", "Esther", "Frank", "George"] + >>> g.vs["age"] = [25, 31, 18, 47, 22, 23, 50] + >>> g.vs["gender"] = ["f", "m", "f", "m", "f", "m", "m"] + >>> g.es["is_formal"] = [False, False, True, True, True, False, True, False, False] Whenever you use :attr:`~Graph.vs` or :attr:`~Graph.es` as a dictionary, you are assigning attributes to *all* vertices/edges of the graph. However, you can simply alter the attributes @@ -303,15 +313,15 @@ with integers as if they were lists (remember, they are sequences, they contain vertices or all the edges). When you index them, you obtain a :class:`Vertex` or :class:`Edge` object, which refers to (I am sure you already guessed that) a single vertex or a single edge of the graph. :class:`Vertex` and :class:`Edge` objects can also be used -as dictionaries to alter the attributes of that single vertex or edge: +as dictionaries to alter the attributes of that single vertex or edge:: ->>> g.es[0] -igraph.Edge(,0,{'is_formal': False}) ->>> g.es[0].attributes() -{'is_formal': False} ->>> g.es[0]["is_formal"] = True ->>> g.es[0] -igraph.Edge(,0,{'is_formal': True}) + >>> g.es[0] + igraph.Edge(,0,{'is_formal': False}) + >>> g.es[0].attributes() + {'is_formal': False} + >>> g.es[0]["is_formal"] = True + >>> g.es[0] + igraph.Edge(,0,{'is_formal': True}) The above snippet illustrates that indexing an :class:`EdgeSeq` object returns :class:`Edge` objects; the representation above shows the graph the object belongs to, @@ -332,23 +342,23 @@ we will see methods that can filter :class:`EdgeSeq` objects and return other :class:`EdgeSeq` objects that are restricted to a subset of edges, and of course the same applies to :class:`VertexSeq` objects. But before we dive into that, let's see how we can assign attributes to the whole graph. Not too surprisingly, :class:`Graph` objects -themselves can also behave as dictionaries: +themselves can also behave as dictionaries:: ->>> g["date"] = "2009-01-10" ->>> print(g["date"]) -2009-01-10 + >>> g["date"] = "2009-01-10" + >>> print(g["date"]) + 2009-01-10 Finally, it should be mentioned that attributes can be deleted by the Python keyword -``del`` just as you would do with any member of an ordinary dictionary: +``del`` just as you would do with any member of an ordinary dictionary:: ->>> g.vs[3]["foo"] = "bar" ->>> g.vs["foo"] -[None, None, None, 'bar', None, None, None] ->>> del g.vs["foo"] ->>> g.vs["foo"] -Traceback (most recent call last): - File "", line 25, in -KeyError: 'Attribute does not exist' + >>> g.vs[3]["foo"] = "bar" + >>> g.vs["foo"] + [None, None, None, 'bar', None, None, None] + >>> del g.vs["foo"] + >>> g.vs["foo"] + Traceback (most recent call last): + File "", line 25, in + KeyError: 'Attribute does not exist' Structural properties of graphs =============================== @@ -363,20 +373,20 @@ Probably the simplest property one can think of is the :dfn:`vertex degree`. The degree of a vertex equals the number of edges adjacent to it. In case of directed networks, we can also define :dfn:`in-degree` (the number of edges pointing towards the vertex) and :dfn:`out-degree` (the number of edges originating from the vertex). -|igraph| is able to calculate all of them using a simple syntax: +|igraph| is able to calculate all of them using a simple syntax:: ->>> g.degree() -[3, 1, 4, 3, 2, 3, 2] + >>> g.degree() + [3, 1, 4, 3, 2, 3, 2] If the graph was directed, we would have been able to calculate the in- and out-degrees separately using ``g.degree(mode="in")`` and ``g.degree(mode="out")``. You can also pass a single vertex ID or a list of vertex IDs to :meth:`~Graph.degree` if you -want to calculate the degrees for only a subset of vertices: +want to calculate the degrees for only a subset of vertices:: ->>> g.degree(6) -2 ->>> g.degree([2,3,4]) -[4, 3, 2] + >>> g.degree(6) + 2 + >>> g.degree([2,3,4]) + [4, 3, 2] This calling convention applies to most of the structural properties |igraph| can calculate. For vertex properties, the methods accept a vertex ID or a list of vertex IDs @@ -397,30 +407,30 @@ restrict them to exactly the vertices or edges you want. Besides degree, |igraph| includes built-in routines to calculate many other centrality properties, including vertex and edge betweenness (:meth:`Graph.betweenness`, :meth:`Graph.edge_betweenness`) or Google's PageRank (:meth:`Graph.pagerank`) -just to name a few. Here we just illustrate edge betweenness: +just to name a few. Here we just illustrate edge betweenness:: ->>> g.edge_betweenness() -[6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] + >>> g.edge_betweenness() + [6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] Now we can also figure out which connections have the highest betweenness centrality -with some Python magic: +with some Python magic:: ->>> ebs = g.edge_betweenness() ->>> max_eb = max(ebs) ->>> [g.es[idx].tuple for idx, eb in enumerate(ebs) if eb == max_eb] -[(0, 1), (0, 2)] + >>> ebs = g.edge_betweenness() + >>> max_eb = max(ebs) + >>> [g.es[idx].tuple for idx, eb in enumerate(ebs) if eb == max_eb] + [(0, 1), (0, 2)] Most structural properties can also be retrieved for a subset of vertices or edges or for a single vertex or edge by calling the appropriate method on the :class:`VertexSeq`, :class:`EdgeSeq`, :class:`Vertex` or :class:`Edge` object of -interest: +interest:: ->>> g.vs.degree() -[3, 1, 4, 3, 2, 3, 2] ->>> g.es.edge_betweenness() -[6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] ->>> g.vs[2].degree() -4 + >>> g.vs.degree() + [3, 1, 4, 3, 2, 3, 2] + >>> g.es.edge_betweenness() + [6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] + >>> g.vs[2].degree() + 4 .. _querying_vertices_and_edges: @@ -433,10 +443,10 @@ Selecting vertices and edges Imagine that in a given social network, you would like to find out who has the largest degree or betweenness centrality. You can do that with the tools presented so far and some basic Python knowledge, but since it is a common task to select vertices and edges -based on attributes or structural properties, |igraph| gives you an easier way to do that: +based on attributes or structural properties, |igraph| gives you an easier way to do that:: ->>> g.vs.select(_degree=g.maxdegree())["name"] -["Alice", "Bob"] + >>> g.vs.select(_degree=g.maxdegree())["name"] + ["Alice", "Bob"] The syntax may seem a little bit awkward for the first sight, so let's try to interpret it step by step. :meth:`~VertexSeq.select` is a method of :class:`VertexSeq` and its @@ -446,50 +456,50 @@ arguments. Positional arguments (the ones without an explicit name like ``_degree`` above) are always processed before keyword arguments as follows: - If the first positional argument is ``None``, an empty sequence (containing no - vertices) is returned: + vertices) is returned:: - >>> seq = g.vs.select(None) - >>> len(seq) - 0 + >>> seq = g.vs.select(None) + >>> len(seq) + 0 - If the first positional argument is a callable object (i.e., a function, a bound method or anything that behaves like a function), the object will be called for every vertex that's currently in the sequence. If the function returns ``True``, - the vertex will be included, otherwise it will be excluded: + the vertex will be included, otherwise it will be excluded:: - >>> graph = Graph.Full(10) - >>> only_odd_vertices = graph.vs.select(lambda vertex: vertex.index % 2 == 1) - >>> len(only_odd_vertices) - 5 + >>> graph = Graph.Full(10) + >>> only_odd_vertices = graph.vs.select(lambda vertex: vertex.index % 2 == 1) + >>> len(only_odd_vertices) + 5 - If the first positional argument is an iterable (i.e., a list, a generator or anything that can be iterated over), it *must* return integers and these integers will be considered as indices into the current vertex set (which is *not* necessarily the whole graph). Only those vertices that match the given indices will be included in the filtered vertex set. Floats, strings, invalid vertex IDs will silently be - ignored: - - >>> seq = graph.vs.select([2, 3, 7]) - >>> len(seq) - 3 - >>> [v.index for v in seq] - [2, 3, 7] - >>> seq = seq.select([0, 2]) # filtering an existing vertex set - >>> [v.index for v in seq] - [2, 7] - >>> seq = graph.vs.select([2, 3, 7, "foo", 3.5]) - >>> len(seq) - 3 + ignored:: + + >>> seq = graph.vs.select([2, 3, 7]) + >>> len(seq) + 3 + >>> [v.index for v in seq] + [2, 3, 7] + >>> seq = seq.select([0, 2]) # filtering an existing vertex set + >>> [v.index for v in seq] + [2, 7] + >>> seq = graph.vs.select([2, 3, 7, "foo", 3.5]) + >>> len(seq) + 3 - If the first positional argument is an integer, all remaining arguments are also expected to be integers and they are interpreted as indices into the current vertex set. This is just syntactic sugar, you could achieve an equivalent effect by passing a list as the first positional argument, but this way you can omit the - square brackets: + square brackets:: - >>> seq = graph.vs.select(2, 3, 7) - >>> len(seq) - 3 + >>> seq = graph.vs.select(2, 3, 7) + >>> len(seq) + 3 Keyword arguments can be used to filter the vertices based on their attributes or their structural properties. The name of each keyword argument should consist @@ -528,9 +538,9 @@ Keyword argument Meaning ================ ================================================================ For instance, the following command gives you people younger than 30 years in -our imaginary social network: +our imaginary social network:: ->>> g.vs.select(age_lt=30) + >>> g.vs.select(age_lt=30) .. note:: Due to the syntactical constraints of Python, you cannot use the admittedly @@ -538,26 +548,26 @@ our imaginary social network: allowed to appear in an argument list in Python. To save you some typing, you can even omit the :meth:`~VertexSeq.select` method if -you wish: +you wish:: ->>> g.vs(age_lt=30) + >>> g.vs(age_lt=30) Theoretically, it can happen that there exists an attribute and a structural property with the same name (e.g., you could have a vertex attribute named ``degree``). In that case, we would not be able to decide whether the user meant ``degree`` as a structural property or as a vertex attribute. To resolve this ambiguity, structural property names *must* always be preceded by an underscore (``_``) when used for filtering. For example, to -find vertices with degree larger than 2: +find vertices with degree larger than 2:: ->>> g.vs(_degree_gt=2) + >>> g.vs(_degree_gt=2) There are also a few special structural properties for selecting edges: - Using ``_source`` or ``_from`` in the keyword argument list of :meth:`EdgeSeq.select` filters based on the source vertices of the edges. E.g., to select all the edges - originating from Claire (who has vertex index 2): + originating from Claire (who has vertex index 2):: - >>> g.es.select(_source=2) + >>> g.es.select(_source=2) - Using ``_target`` or ``_to`` filters based on the target vertices. This is different from ``_source`` and ``_from`` if the graph is directed. @@ -565,22 +575,22 @@ There are also a few special structural properties for selecting edges: - ``_within`` takes a :class:`VertexSeq` object or a list or set of vertex indices and selects all the edges that originate and terminate in the given vertex set. For instance, the following expression selects all the edges between - Claire (vertex index 2), Dennis (vertex index 3) and Esther (vertex index 4): + Claire (vertex index 2), Dennis (vertex index 3) and Esther (vertex index 4):: - >>> g.es.select(_within=[2,3,4]) + >>> g.es.select(_within=[2,3,4]) - We could also have used a :class:`VertexSeq` object: + We could also have used a :class:`VertexSeq` object:: - >>> g.es.select(_within=g.vs[2:5]) + >>> g.es.select(_within=g.vs[2:5]) - ``_between`` takes a tuple consisting of two :class:`VertexSeq` objects or lists containing vertex indices or :class:`Vertex` objects and selects all the edges that originate in one of the sets and terminate in the other. E.g., to select all the - edges that connect men to women: + edges that connect men to women:: - >>> men = g.vs.select(gender="m") - >>> women = g.vs.select(gender="f") - >>> g.es.select(_between=(men, women)) + >>> men = g.vs.select(gender="m") + >>> women = g.vs.select(gender="f") + >>> g.es.select(_between=(men, women)) Finding a single vertex or edge with some properties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -593,20 +603,20 @@ looking up vertices by their names in the ``name`` property. :class:`VertexSeq` :meth:`~VertexSeq.find` works similarly to :meth:`~VertexSeq.select`, but it returns only the first match if there are multiple matches, and throws an exception if no match is found. For instance, to look up the vertex corresponding to Claire, one can -do this: +do this:: ->>> claire = g.vs.find(name="Claire") ->>> type(claire) -igraph.Vertex ->>> claire.index -2 + >>> claire = g.vs.find(name="Claire") + >>> type(claire) + igraph.Vertex + >>> claire.index + 2 -Looking up an unknown name will yield an exception: +Looking up an unknown name will yield an exception:: ->>> g.vs.find(name="Joe") -Traceback (most recent call last): - File "", line 1, in -ValueError: no such vertex + >>> g.vs.find(name="Joe") + Traceback (most recent call last): + File "", line 1, in + ValueError: no such vertex Looking up vertices by names ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -618,15 +628,15 @@ can be looked up by their names in amortized constant time. To make things even |igraph| accepts vertex names (almost) anywhere where it expects vertex IDs, and also accepts collections (list, tuples etc) of vertex names anywhere where it expects lists of vertex IDs or :class:`VertexSeq` instances. E.g, you can simply look up the degree -(number of connections) of Dennis as follows: +(number of connections) of Dennis as follows:: ->>> g.degree("Dennis") -3 + >>> g.degree("Dennis") + 3 or, alternatively: ->>> g.vs.find("Dennis").degree() -3 + >>> g.vs.find("Dennis").degree() + 3 The mapping between vertex names and IDs is maintained transparently by |igraph| in the background; whenever the graph changes, |igraph| also updates the internal mapping. @@ -640,8 +650,18 @@ Treating a graph as an adjacency matrix Adjacency matrix is another way to form a graph. In adjacency matrix, rows and columns are labeled by graph vertices: the elements of the matrix indicate whether the vertices *i* and *j* have a common edge (*i, j*). The adjacency matrix for the example graph is ->>> g.get_adjacency() -Matrix([[0, 1, 1, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 1, 1, 1, 0], [0, 0, 1, 0, 1, 0, 1], [0, 0, 1, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 0, 1, 0]]) +:: + + >>> g.get_adjacency() + Matrix([ + [0, 1, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 1, 1, 1, 0], + [0, 0, 1, 0, 1, 0, 1], + [0, 0, 1, 1, 0, 0, 0], + [1, 0, 1, 0, 0, 0, 1], + [0, 0, 0, 1, 0, 1, 0] + ]) For example, Claire (``[1, 0, 0, 1, 1, 1, 0]``) is directly connected to Alice (who has vertex index 0), Dennis (index 3), Esther (index 4), and Frank (index 5), but not to Bob (index 1) nor George (index 6). @@ -711,18 +731,18 @@ Method name Short name Algorithm description .. _Large Graph Layout: http://sourceforge.net/projects/lgl/ Layout algorithms can either be called directly or using the common layout method called -:meth:`~Graph.layout`: +:meth:`~Graph.layout`:: ->>> layout = g.layout_kamada_kawai() ->>> layout = g.layout("kamada_kawai") + >>> layout = g.layout_kamada_kawai() + >>> layout = g.layout("kamada_kawai") The first argument of the :meth:`~Graph.layout` method must be the short name of the layout algorithm (see the table above). All the remaining positional and keyword arguments are passed intact to the chosen layout method. For instance, the following two calls are -completely equivalent: +completely equivalent:: ->>> layout = g.layout_reingold_tilford(root=[2]) ->>> layout = g.layout("rt", [2]) + >>> layout = g.layout_reingold_tilford(root=[2]) + >>> layout = g.layout("rt", [2]) Layout methods return a :class:`Layout` object which behaves mostly like a list of lists. Each list entry in a :class:`Layout` object corresponds to a vertex in the original graph @@ -735,10 +755,10 @@ Drawing a graph using a layout ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For instance, we can plot our imaginary social network with the Kamada-Kawai -layout algorithm as follows: +layout algorithm as follows:: ->>> layout = g.layout("kk") ->>> plot(g, layout=layout) + >>> layout = g.layout("kk") + >>> plot(g, layout=layout) This should open an external image viewer showing a visual representation of the network, something like the one on the following figure (although the exact placement of @@ -751,22 +771,22 @@ nodes may be different on your machine since the layout is not deterministic): Our social network with the Kamada-Kawai layout algorithm If you prefer to use `matplotlib`_ as a plotting engine, create an axes and use the -``target`` argument: +``target`` argument:: ->>> import matplotlib.pyplot as plt ->>> fig, ax = plt.subplots() ->>> plot(g, layout=layout, target=ax) + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> plot(g, layout=layout, target=ax) Hmm, this is not too pretty so far. A trivial addition would be to use the names as the vertex labels and to color the vertices according to the gender. Vertex labels are taken from the ``label`` attribute by default and vertex colors are determined by the -``color`` attribute, so we can simply create these attributes and re-plot the graph: +``color`` attribute, so we can simply create these attributes and re-plot the graph:: ->>> g.vs["label"] = g.vs["name"] ->>> color_dict = {"m": "blue", "f": "pink"} ->>> g.vs["color"] = [color_dict[gender] for gender in g.vs["gender"]] ->>> plot(g, layout=layout, bbox=(300, 300), margin=20) ->>> plot(g, layout=layout, bbox=(300, 300), margin=20, target=ax) # matplotlib version + >>> g.vs["label"] = g.vs["name"] + >>> color_dict = {"m": "blue", "f": "pink"} + >>> g.vs["color"] = [color_dict[gender] for gender in g.vs["gender"]] + >>> plot(g, layout=layout, bbox=(300, 300), margin=20) + >>> plot(g, layout=layout, bbox=(300, 300), margin=20, target=ax) # matplotlib version Note that we are simply re-using the previous layout object here, but we also specified that we need a smaller plot (300 x 300 pixels) and a larger margin around the graph @@ -779,10 +799,10 @@ to fit the labels (20 pixels). The result is: Our social network - with names as labels and genders as colors Instead of specifying the visual properties as vertex and edge attributes, you can -also give them as keyword arguments to :func:`plot`: +also give them as keyword arguments to :func:`plot`:: ->>> color_dict = {"m": "blue", "f": "pink"} ->>> plot(g, layout=layout, vertex_color=[color_dict[gender] for gender in g.vs["gender"]]) + >>> color_dict = {"m": "blue", "f": "pink"} + >>> plot(g, layout=layout, vertex_color=[color_dict[gender] for gender in g.vs["gender"]]) This latter approach is preferred if you want to keep the properties of the visual representation of your graph separate from the graph itself. You can simply set up @@ -790,15 +810,15 @@ a Python dictionary containing the keyword arguments you would pass to :func:`pl and then use the double asterisk (``**``) operator to pass your specific styling attributes to :func:`plot`:: ->>> visual_style = {} ->>> visual_style["vertex_size"] = 20 ->>> visual_style["vertex_color"] = [color_dict[gender] for gender in g.vs["gender"]] ->>> visual_style["vertex_label"] = g.vs["name"] ->>> visual_style["edge_width"] = [1 + 2 * int(is_formal) for is_formal in g.es["is_formal"]] ->>> visual_style["layout"] = layout ->>> visual_style["bbox"] = (300, 300) ->>> visual_style["margin"] = 20 ->>> plot(g, **visual_style) + >>> visual_style = {} + >>> visual_style["vertex_size"] = 20 + >>> visual_style["vertex_color"] = [color_dict[gender] for gender in g.vs["gender"]] + >>> visual_style["vertex_label"] = g.vs["name"] + >>> visual_style["edge_width"] = [1 + 2 * int(is_formal) for is_formal in g.es["is_formal"]] + >>> visual_style["layout"] = layout + >>> visual_style["bbox"] = (300, 300) + >>> visual_style["margin"] = 20 + >>> plot(g, **visual_style) The final plot shows the formal ties with thick lines while informal ones with thin lines: @@ -955,7 +975,7 @@ SVG or PDF files can then later be converted to PostScript (``.ps``) or Encapsul PostScript (``.eps``) format if you prefer that, while PNG files can be converted to TIF (``.tif``):: ->>> plot(g, "social_network.pdf", **visual_style) + >>> plot(g, "social_network.pdf", **visual_style) |igraph| and the outside world @@ -1012,16 +1032,16 @@ As an exercise, download the graph representation of the well-known `Zachary karate club study `_ from :download:`this file `, unzip it and try to load it into |igraph|. Since it is a GraphML file, you must use the GraphML reader method from -the table above (make sure you use the appropriate path to the downloaded file): +the table above (make sure you use the appropriate path to the downloaded file):: ->>> karate = Graph.Read_GraphML("zachary.graphml") ->>> summary(karate) -IGRAPH UNW- 34 78 -- Zachary's karate club network + >>> karate = Graph.Read_GraphML("zachary.graphml") + >>> summary(karate) + IGRAPH UNW- 34 78 -- Zachary's karate club network If you want to convert the very same graph into, say, Pajek's format, you can do it -with the Pajek writer method from the table above: +with the Pajek writer method from the table above:: ->>> karate.write_pajek("zachary.net") + >>> karate.write_pajek("zachary.net") .. note:: Most of the formats have their own limitations; for instance, not all of them can store attributes. Your best bet is probably GraphML or GML if you @@ -1038,11 +1058,11 @@ reader methods which tries to infer the appropriate format from the file extensi :meth:`Graph.save` is the opposite of :func:`load`: it lets you save a graph where the preferred format is again inferred from the extension. The format detection of :func:`load` and :meth:`Graph.save` can be overridden by the ``format`` keyword -argument which accepts the short names of the formats from the above table: +argument which accepts the short names of the formats from the above table:: ->>> karate = load("zachary.graphml") ->>> karate.save("zachary.net") ->>> karate.save("zachary.my_extension", format="gml") + >>> karate = load("zachary.graphml") + >>> karate.save("zachary.net") + >>> karate.save("zachary.my_extension", format="gml") Where to go next diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index a67fc90be..a7ce000b2 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -6,10 +6,10 @@ Visualisation of graphs |igraph| includes functionality to visualize graphs. There are two main components: graph layouts and graph plotting. In the following examples, we will assume |igraph| is imported as `ig` and a -:class:`Graph` object has been previously created, e.g.: +:class:`Graph` object has been previously created, e.g.:: ->>> import igraph as ig ->>> g = ig.Graph(edges=[[0, 1], [2, 3]]) + >>> import igraph as ig + >>> g = ig.Graph(edges=[[0, 1], [2, 3]]) Read the `API documentation`_ for details on each function and class. The `tutorial`_ contains examples to get started. @@ -19,9 +19,9 @@ A graph *layout* is a low-dimensional (usually: 2 dimensional) representation of graph can be computed and typically preserve or highlight distinct properties of the graph itself. Some layouts only make sense for specific kinds of graphs, such as trees. -|igraph| offers several graph layouts. The general function to compute a graph layout is :meth:`Graph.layout`: +|igraph| offers several graph layouts. The general function to compute a graph layout is :meth:`Graph.layout`:: ->>> layout = g.layout(layout='auto') + >>> layout = g.layout(layout='auto') See below for a list of supported layouts. The resulting object is an instance of `igraph.layout.Layout` and has some useful properties: @@ -35,14 +35,14 @@ and methods: - :meth:`Layout.bounding_box` the boundary, but as an `igraph.drawing.utils.BoundingBox` (see below) - :meth:`Layout.centroid` the coordinates of the centroid of the graph layout -Indexing and slicing can be performed and returns the coordinates of the requested vertices: +Indexing and slicing can be performed and returns the coordinates of the requested vertices:: ->>> coords_subgraph = layout[:2] # Coordinates of the first two vertices + >>> coords_subgraph = layout[:2] # Coordinates of the first two vertices .. note:: The returned object is a list of lists with the coordinates, not an `igraph.layout.Layout` object. You can wrap the result into such an object easily: - - >>> layout_subgraph = ig.Layout(coords=layout[:2]) + + >>> layout_subgraph = ig.Layout(coords=layout[:2]) It is possible to perform linear transformations to the layout: @@ -94,111 +94,116 @@ function, `igraph.plot`. Plotting with the default image viewer ++++++++++++++++++++++++++++++++++++++ -A naked call to `igraph.plot` generates a temporary file and opens it with the default image viewer: ->>> ig.plot(g) +A naked call to `igraph.plot` generates a temporary file and opens it with the default image viewer:: + + >>> ig.plot(g) (see below if you are using this in a `Jupyter`_ notebook). This uses the `Cairo`_ library behind the scenes. Saving a plot to a file +++++++++++++++++++++++ + A call to `igraph.plot` with a `target` argument stores the graph image in the specified file and does *not* open it automatically. Based on the filename extension, any of the following output formats can be chosen: -PNG, PDF, SVG and PostScript: +PNG, PDF, SVG and PostScript:: ->>> ig.plot(g, target='myfile.pdf') + >>> ig.plot(g, target='myfile.pdf') .. note:: PNG is a raster image format while PDF, SVG, and Postscript are vector image formats. Choose one of the last three formats if you are planning on refining the image with a vector image editor such as Inkscape or Illustrator. Plotting graphs within Matplotlib figures +++++++++++++++++++++++++++++++++++++++++ -If the target argument is a `matplotlib`_ axes, the graph will be plotted inside that axes: ->>> import matplotlib.pyplot as plt ->>> fig, ax = plt.subplots() ->>> ig.plot(g, target=ax) +If the target argument is a `matplotlib`_ axes, the graph will be plotted inside that axes:: + + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> ig.plot(g, target=ax) You can then further manipulate the axes and figure however you like via the `ax` and `fig` variables (or whatever you called them). This variant does not use `Cairo`_ directly and might be lacking some features that are available in the `Cairo`_ backend: please open an issue on Github to request specific features. Plotting via `matplotlib`_ makes it easy to combine igraph with other plots. For instance, if you want to have a figure -with two panels showing different aspects of some data set, say a graph and a bar plot, you can easily do that: +with two panels showing different aspects of some data set, say a graph and a bar plot, you can easily do that:: ->>> import matplotlib.pyplot as plt ->>> fig, axs = plt.subplots(1, 2, figsize=(8, 4)) ->>> ig.plot(g, target=axs[0]) ->>> axs[1].bar(x=[0, 1, 2], height=[1, 5, 3], color='tomato') + >>> import matplotlib.pyplot as plt + >>> fig, axs = plt.subplots(1, 2, figsize=(8, 4)) + >>> ig.plot(g, target=axs[0]) + >>> axs[1].bar(x=[0, 1, 2], height=[1, 5, 3], color='tomato') Another common situation is modifying the graph plot after the fact, to achieve some kind of customization. For instance, -you might want to change the size and color of the vertices: +you might want to change the size and color of the vertices:: ->>> import matplotlib.pyplot as plt ->>> fig, ax = plt.subplots() ->>> ig.plot(g, target=ax) ->>> dots = ax.get_children()[0] # This is a PathCollection ->>> dots.set_color('tomato') ->>> dots.set_sizes([250] * g.vcount()) + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> ig.plot(g, target=ax) + >>> dots = ax.get_children()[0] # This is a PathCollection + >>> dots.set_color('tomato') + >>> dots.set_sizes([250] * g.vcount()) That also helps as a workaround if you cannot figure out how to use the plotting options below: just use the defaults and then customize the appearance of your graph via standard `matplotlib`_ tools. Plotting graphs in Jupyter notebooks ++++++++++++++++++++++++++++++++++++ + |igraph| supports inline plots within a `Jupyter`_ notebook via both the `Cairo`_ and `matplotlib`_ backend. If you are calling `igraph.plot` from a notebook cell without a `matplotlib`_ axes, the image will be shown inline in the corresponding output cell. Use the `bbox` argument to scale the image while preserving the size of the vertices, text, and other artists. -For instance, to get a compact plot: +For instance, to get a compact plot:: ->>> ig.plot(g, bbox=(0, 0, 100, 100)) + >>> ig.plot(g, bbox=(0, 0, 100, 100)) These inline plots can be either in PNG or SVG format. There is currently an open bug that makes SVG fail if more than one graph per notebook is plotted: we are working on a fix for that. In the meanwhile, you can use PNG representation. If you want to use the `matplotlib`_ engine in a Jupyter notebook, you can use the recipe above. First create an axes, then -tell `igraph.plot` about it via the `target` argument: +tell `igraph.plot` about it via the `target` argument:: ->>> import matplotlib.pyplot as plt ->>> fig, ax = plt.subplots() ->>> ig.plot(g, target=ax) + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> ig.plot(g, target=ax) Exporting to other graph formats ++++++++++++++++++++++++++++++++++ If igraph is missing a certain plotting feature and you cannot wait for us to include it, you can always export your graph to a number of formats and use an external graph plotting tool. We support both conversion to file (e.g. DOT format used by -`graphviz`_) and to popular graph libraries such as `networkx`_ and `graph-tool`_: +`graphviz`_) and to popular graph libraries such as `networkx`_ and `graph-tool`_:: ->>> dot = g.write('/myfolder/myfile.dot') ->>> n = g.to_networkx() ->>> gt = g.to_graph_tool() + >>> dot = g.write('/myfolder/myfile.dot') + >>> n = g.to_networkx() + >>> gt = g.to_graph_tool() You do not need to have any libraries installed if you export to file, but you do need them to convert directly to external Python objects (`networkx`_, `graph-tool`_). Plotting options -==================== -You can add an argument `layout` to the `plot` function to specify a precomputed layout, e.g.: +================ + +You can add an argument `layout` to the `plot` function to specify a precomputed layout, e.g.:: ->>> layout = g.layout("kamada_kawai") ->>> ig.plot(g, layout=layout) + >>> layout = g.layout("kamada_kawai") + >>> ig.plot(g, layout=layout) -It is also possible to use the name of the layout algorithm directly: +It is also possible to use the name of the layout algorithm directly:: ->>> ig.plot(g, layout="kamada_kawai") + >>> ig.plot(g, layout="kamada_kawai") If the layout is left unspecified, igraph uses the dedicated `layout_auto()` function, which chooses between one of several possible layouts based on the number of vertices and edges. -You can also specify vertex and edge color, size, and labels - and more - via additional arguments, e.g.: +You can also specify vertex and edge color, size, and labels - and more - via additional arguments, e.g.:: ->>> ig.plot(g, ->>> vertex_size=20, ->>> vertex_color=['blue', 'red', 'green', 'yellow'], ->>> vertex_label=['first', 'second', 'third', 'fourth'], ->>> edge_width=[1, 4], ->>> edge_color=['black', 'grey'], ->>> ) + >>> ig.plot(g, + ... vertex_size=20, + ... vertex_color=['blue', 'red', 'green', 'yellow'], + ... vertex_label=['first', 'second', 'third', 'fourth'], + ... edge_width=[1, 4], + ... edge_color=['black', 'grey'], + ... ) See the `tutorial`_ for examples and a full list of options. From b32c47c08b71ebe356a3baa9e64c5236ce08071c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 20 Oct 2021 17:21:50 +0200 Subject: [PATCH 0675/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 2ceb15db7..b29e741ea 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2ceb15db7983a15e499844daddd1e1aa72cb0138 +Subproject commit b29e741ea4106b259318d1d1d37404d317b2a185 From c4e50cbad72817e0d7edd76b1a2cd63bd0339769 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 12:57:39 +0200 Subject: [PATCH 0676/1892] chore: minor setup.py tweaks --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4fffda6a7..c4944ee0b 100644 --- a/setup.py +++ b/setup.py @@ -818,6 +818,7 @@ def use_educated_guess(self) -> None: author_email="ntamas@gmail.com", project_urls={ "Bug Tracker": "https://github.com/igraph/python-igraph/issues", + "Changelog": "https://github.com/igraph/python-igraph/blob/master/CHANGELOG.md", "CI": "https://github.com/igraph/python-igraph/actions", "Documentation": "https://igraph.org/python/doc", "Source Code": "https://github.com/igraph/python-igraph", @@ -858,12 +859,13 @@ def use_educated_guess(self) -> None: "Intended Audience :: Science/Research", "Operating System :: OS Independent", "Programming Language :: C", - "Programming Language :: Python", + "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics", From 9f93b0379d27f2c27b68d8b7fb979da217a66eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Fri, 22 Oct 2021 16:02:06 +0200 Subject: [PATCH 0677/1892] docs: mention the keyword "cycle" when discussion ring graphs in the tutorial --- doc/source/generation.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 47e048e90..5aa01a669 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -38,6 +38,7 @@ To create a bipartite graph from a list of types and a list of edges, use :meth: From matrices +++++++++++++ + To create a graph from an adjecency matrix, use :meth:`Graph.Adjacency` or, for weighted matrices, :meth:`Graph.Weighted_Adjacency`:: >>> g = Graph.Adjacency([[0, 1, 1], [0, 0, 0], [0, 0, 1]]) @@ -119,13 +120,13 @@ The method :meth:`Graph.Star` creates a star graph, which is a subtype of a tree Lattice +++++++ -:meth:`Graph.Lattice` creates a regular lattice of the chosen size. For instance:: +:meth:`Graph.Lattice` creates a regular square lattice of the chosen size. For instance:: >>> g = Graph.Lattice(dim=[3, 3], circular=False) creates a 3x3 grid in two dimensions (9 vertices total). `circular` is used to connect each edge of the lattice back onto the other side, a process also known as "periodic boundary condition" that is sometimes helpful to smoothen out edge effects. -The one dimensional case (path graph or ring) is important enough to deserve its own constructor :meth:`Graph.Ring`, which can be circular or not:: +The one dimensional case (path graph or cycle graph) is important enough to deserve its own constructor :meth:`Graph.Ring`, which can be circular or not:: >>> g = Graph.Ring(n=4, circular=False) @@ -155,6 +156,7 @@ will teach you some about martial arts. Random graphs +++++++++++++ + Stochastic graphs can be created according to several different models or games: - Barabasi-Albert model: :meth:`Graph.Barabasi` From 27a0bff14e17f57b37886f2fa905d52147ebf73a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 2 Oct 2021 15:04:43 +1000 Subject: [PATCH 0678/1892] Community module --- src/igraph/__init__.py | 487 +++---------------------------- src/igraph/community/__init__.py | 478 ++++++++++++++++++++++++++++++ 2 files changed, 517 insertions(+), 448 deletions(-) create mode 100644 src/igraph/community/__init__.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 94541a63e..7a53fd765 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -75,6 +75,20 @@ set_status_handler, __igraph_version__, ) +from igraph.community import ( + _community_fastgreedy, + _community_infomap, + _community_leading_eigenvector_naive, + _community_leading_eigenvector, + _community_label_propagation, + _community_multilevel, + _community_optimal_modularity, + _community_edge_betweenness, + _community_spinglass, + _community_walktrap, + _k_core, + _community_leiden, +) from igraph.clustering import ( Clustering, VertexClustering, @@ -1195,464 +1209,29 @@ def get_automorphisms_vf2( ) # Various clustering algorithms -- mostly wrappers around GraphBase - def community_fastgreedy(self, weights=None): - """Community structure based on the greedy optimization of modularity. - - This algorithm merges individual nodes into communities in a way that - greedily maximizes the modularity score of the graph. It can be proven - that if no merge can increase the current modularity score, the - algorithm can be stopped since no further increase can be achieved. - - This algorithm is said to run almost in linear time on sparse graphs. - - @param weights: edge attribute name or a list containing edge - weights - @return: an appropriate L{VertexDendrogram} object. - - @newfield ref: Reference - @ref: A Clauset, MEJ Newman and C Moore: Finding community structure - in very large networks. Phys Rev E 70, 066111 (2004). - """ - merges, qs = GraphBase.community_fastgreedy(self, weights) - - # qs may be shorter than |V|-1 if we are left with a few separated - # communities in the end; take this into account - diff = self.vcount() - len(qs) - qs.reverse() - if qs: - optimal_count = qs.index(max(qs)) + diff + 1 - else: - optimal_count = diff - - return VertexDendrogram( - self, merges, optimal_count, modularity_params=dict(weights=weights) - ) - - def community_infomap(self, edge_weights=None, vertex_weights=None, trials=10): - """Finds the community structure of the network according to the Infomap - method of Martin Rosvall and Carl T. Bergstrom. - - @param edge_weights: name of an edge attribute or a list containing - edge weights. - @param vertex_weights: name of an vertex attribute or a list containing - vertex weights. - @param trials: the number of attempts to partition the network. - @return: an appropriate L{VertexClustering} object with an extra attribute - called C{codelength} that stores the code length determined by the - algorithm. - - @newfield ref: Reference - @ref: M. Rosvall and C. T. Bergstrom: Maps of information flow reveal - community structure in complex networks, PNAS 105, 1118 (2008). - U{http://dx.doi.org/10.1073/pnas.0706851105}, - U{http://arxiv.org/abs/0707.0609}. - @ref: M. Rosvall, D. Axelsson, and C. T. Bergstrom: The map equation, - Eur. Phys. J. Special Topics 178, 13 (2009). - U{http://dx.doi.org/10.1140/epjst/e2010-01179-1}, - U{http://arxiv.org/abs/0906.1405}. - """ - membership, codelength = GraphBase.community_infomap( - self, edge_weights, vertex_weights, trials - ) - return VertexClustering( - self, - membership, - params={"codelength": codelength}, - modularity_params={"weights": edge_weights}, - ) - - def community_leading_eigenvector_naive(self, clusters=None, return_merges=False): - """Naive implementation of Newman's eigenvector community structure detection. - - This function splits the network into two components - according to the leading eigenvector of the modularity matrix and - then recursively takes the given number of steps by splitting the - communities as individual networks. This is not the correct way, - however, see the reference for explanation. Consider using the - correct L{community_leading_eigenvector} method instead. - - @param clusters: the desired number of communities. If C{None}, the - algorithm tries to do as many splits as possible. Note that the - algorithm won't split a community further if the signs of the leading - eigenvector are all the same, so the actual number of discovered - communities can be less than the desired one. - @param return_merges: whether the returned object should be a - dendrogram instead of a single clustering. - @return: an appropriate L{VertexClustering} or L{VertexDendrogram} - object. - - @newfield ref: Reference - @ref: MEJ Newman: Finding community structure in networks using the - eigenvectors of matrices, arXiv:physics/0605087""" - if clusters is None: - clusters = -1 - cl, merges, q = GraphBase.community_leading_eigenvector_naive( - self, clusters, return_merges - ) - if merges is None: - return VertexClustering(self, cl, modularity=q) - else: - return VertexDendrogram(self, merges, safemax(cl) + 1) - - def community_leading_eigenvector( - self, clusters=None, weights=None, arpack_options=None - ): - """Newman's leading eigenvector method for detecting community structure. - - This is the proper implementation of the recursive, divisive algorithm: - each split is done by maximizing the modularity regarding the - original network. - - @param clusters: the desired number of communities. If C{None}, the - algorithm tries to do as many splits as possible. Note that the - algorithm won't split a community further if the signs of the leading - eigenvector are all the same, so the actual number of discovered - communities can be less than the desired one. - @param weights: name of an edge attribute or a list containing - edge weights. - @param arpack_options: an L{ARPACKOptions} object used to fine-tune - the ARPACK eigenvector calculation. If omitted, the module-level - variable called C{arpack_options} is used. - @return: an appropriate L{VertexClustering} object. - - @newfield ref: Reference - @ref: MEJ Newman: Finding community structure in networks using the - eigenvectors of matrices, arXiv:physics/0605087""" - if clusters is None: - clusters = -1 - - kwds = dict(weights=weights) - if arpack_options is not None: - kwds["arpack_options"] = arpack_options - - membership, _, q = GraphBase.community_leading_eigenvector( - self, clusters, **kwds - ) - return VertexClustering(self, membership, modularity=q) - - def community_label_propagation(self, weights=None, initial=None, fixed=None): - """Finds the community structure of the graph according to the label - propagation method of Raghavan et al. - - Initially, each vertex is assigned a different label. After that, - each vertex chooses the dominant label in its neighbourhood in each - iteration. Ties are broken randomly and the order in which the - vertices are updated is randomized before every iteration. The - algorithm ends when vertices reach a consensus. - Note that since ties are broken randomly, there is no guarantee that - the algorithm returns the same community structure after each run. - In fact, they frequently differ. See the paper of Raghavan et al - on how to come up with an aggregated community structure. - @param weights: name of an edge attribute or a list containing - edge weights - @param initial: name of a vertex attribute or a list containing - the initial vertex labels. Labels are identified by integers from - zero to M{n-1} where M{n} is the number of vertices. Negative - numbers may also be present in this vector, they represent unlabeled - vertices. - @param fixed: a list of booleans for each vertex. C{True} corresponds - to vertices whose labeling should not change during the algorithm. - It only makes sense if initial labels are also given. Unlabeled - vertices cannot be fixed. It may also be the name of a vertex - attribute; each attribute value will be interpreted as a Boolean. - @return: an appropriate L{VertexClustering} object. - - @newfield ref: Reference - @ref: Raghavan, U.N. and Albert, R. and Kumara, S. Near linear - time algorithm to detect community structures in large-scale - networks. Phys Rev E 76:036106, 2007. - U{http://arxiv.org/abs/0709.2938}. - """ - if isinstance(fixed, str): - fixed = [bool(o) for o in self.vs[fixed]] - cl = GraphBase.community_label_propagation(self, weights, initial, fixed) - return VertexClustering(self, cl, modularity_params=dict(weights=weights)) - - def community_multilevel(self, weights=None, return_levels=False): - """Community structure based on the multilevel algorithm of - Blondel et al. - - This is a bottom-up algorithm: initially every vertex belongs to a - separate community, and vertices are moved between communities - iteratively in a way that maximizes the vertices' local contribution - to the overall modularity score. When a consensus is reached (i.e. no - single move would increase the modularity score), every community in - the original graph is shrank to a single vertex (while keeping the - total weight of the adjacent edges) and the process continues on the - next level. The algorithm stops when it is not possible to increase - the modularity any more after shrinking the communities to vertices. - - This algorithm is said to run almost in linear time on sparse graphs. - - @param weights: edge attribute name or a list containing edge - weights - @param return_levels: if C{True}, the communities at each level are - returned in a list. If C{False}, only the community structure with - the best modularity is returned. - @return: a list of L{VertexClustering} objects, one corresponding to - each level (if C{return_levels} is C{True}), or a L{VertexClustering} - corresponding to the best modularity. + community_fastgreedy = _community_fastgreedy - @newfield ref: Reference - @ref: VD Blondel, J-L Guillaume, R Lambiotte and E Lefebvre: Fast - unfolding of community hierarchies in large networks, J Stat Mech - P10008 (2008), http://arxiv.org/abs/0803.0476 - """ - if self.is_directed(): - raise ValueError("input graph must be undirected") - - if return_levels: - levels, qs = GraphBase.community_multilevel(self, weights, True) - result = [] - for level, q in zip(levels, qs): - result.append( - VertexClustering( - self, level, q, modularity_params=dict(weights=weights) - ) - ) - else: - membership = GraphBase.community_multilevel(self, weights, False) - result = VertexClustering( - self, membership, modularity_params=dict(weights=weights) - ) - return result + community_infomap = _community_infomap - def community_optimal_modularity(self, *args, **kwds): - """Calculates the optimal modularity score of the graph and the - corresponding community structure. - - This function uses the GNU Linear Programming Kit to solve a large - integer optimization problem in order to find the optimal modularity - score and the corresponding community structure, therefore it is - unlikely to work for graphs larger than a few (less than a hundred) - vertices. Consider using one of the heuristic approaches instead if - you have such a large graph. - - @return: the calculated membership vector and the corresponding - modularity in a tuple.""" - membership, modularity = GraphBase.community_optimal_modularity( - self, *args, **kwds - ) - return VertexClustering(self, membership, modularity) - - def community_edge_betweenness(self, clusters=None, directed=True, weights=None): - """Community structure based on the betweenness of the edges in the - network. - - The idea is that the betweenness of the edges connecting two - communities is typically high, as many of the shortest paths between - nodes in separate communities go through them. So we gradually remove - the edge with the highest betweenness and recalculate the betweennesses - after every removal. This way sooner or later the network falls of to - separate components. The result of the clustering will be represented - by a dendrogram. - - @param clusters: the number of clusters we would like to see. This - practically defines the "level" where we "cut" the dendrogram to - get the membership vector of the vertices. If C{None}, the dendrogram - is cut at the level which maximizes the modularity when the graph is - unweighted; otherwise the dendrogram is cut at at a single cluster - (because cluster count selection based on modularities does not make - sense for this method if not all the weights are equal). - @param directed: whether the directionality of the edges should be - taken into account or not. - @param weights: name of an edge attribute or a list containing - edge weights. - @return: a L{VertexDendrogram} object, initally cut at the maximum - modularity or at the desired number of clusters. - """ - merges, qs = GraphBase.community_edge_betweenness(self, directed, weights) - if qs is not None: - qs.reverse() - if clusters is None: - if qs: - clusters = qs.index(max(qs)) + 1 - else: - clusters = 1 - return VertexDendrogram( - self, merges, clusters, modularity_params=dict(weights=weights) - ) + community_leading_eigenvector_naive = _community_leading_eigenvector_naive - def community_spinglass(self, *args, **kwds): - """Finds the community structure of the graph according to the - spinglass community detection method of Reichardt & Bornholdt. - - @param weights: edge weights to be used. Can be a sequence or - iterable or even an edge attribute name. - @param spins: integer, the number of spins to use. This is the - upper limit for the number of communities. It is not a problem - to supply a (reasonably) big number here, in which case some - spin states will be unpopulated. - @param parupdate: whether to update the spins of the vertices in - parallel (synchronously) or not - @param start_temp: the starting temperature - @param stop_temp: the stop temperature - @param cool_fact: cooling factor for the simulated annealing - @param update_rule: specifies the null model of the simulation. - Possible values are C{"config"} (a random graph with the same - vertex degrees as the input graph) or C{"simple"} (a random - graph with the same number of edges) - @param gamma: the gamma argument of the algorithm, specifying the - balance between the importance of present and missing edges - within a community. The default value of 1.0 assigns equal - importance to both of them. - @param implementation: currently igraph contains two implementations - of the spinglass community detection algorithm. The faster - original implementation is the default. The other implementation - is able to take into account negative weights, this can be - chosen by setting C{implementation} to C{"neg"} - @param lambda_: the lambda argument of the algorithm, which - specifies the balance between the importance of present and missing - negatively weighted edges within a community. Smaller values of - lambda lead to communities with less negative intra-connectivity. - If the argument is zero, the algorithm reduces to a graph coloring - algorithm, using the number of spins as colors. This argument is - ignored if the original implementation is used. Note the underscore - at the end of the argument name; this is due to the fact that - lambda is a reserved keyword in Python. - @return: an appropriate L{VertexClustering} object. + community_leading_eigenvector = _community_leading_eigenvector - @newfield ref: Reference - @ref: Reichardt J and Bornholdt S: Statistical mechanics of - community detection. Phys Rev E 74:016110 (2006). - U{http://arxiv.org/abs/cond-mat/0603718}. - @ref: Traag VA and Bruggeman J: Community detection in networks - with positive and negative links. Phys Rev E 80:036115 (2009). - U{http://arxiv.org/abs/0811.2329}. - """ - membership = GraphBase.community_spinglass(self, *args, **kwds) - if "weights" in kwds: - modularity_params = dict(weights=kwds["weights"]) - else: - modularity_params = {} - return VertexClustering(self, membership, modularity_params=modularity_params) + community_label_propagation = _community_label_propagation - def community_walktrap(self, weights=None, steps=4): - """Community detection algorithm of Latapy & Pons, based on random - walks. + community_multilevel = _community_multilevel - The basic idea of the algorithm is that short random walks tend to stay - in the same community. The result of the clustering will be represented - as a dendrogram. + community_optimal_modularity = _community_optimal_modularity - @param weights: name of an edge attribute or a list containing - edge weights - @param steps: length of random walks to perform + community_edge_betweenness = _community_edge_betweenness - @return: a L{VertexDendrogram} object, initially cut at the maximum - modularity. + community_spinglass = _community_spinglass - @newfield ref: Reference - @ref: Pascal Pons, Matthieu Latapy: Computing communities in large - networks using random walks, U{http://arxiv.org/abs/physics/0512106}. - """ - merges, qs = GraphBase.community_walktrap(self, weights, steps) - qs.reverse() - if qs: - optimal_count = qs.index(max(qs)) + 1 - else: - optimal_count = 1 - return VertexDendrogram( - self, merges, optimal_count, modularity_params=dict(weights=weights) - ) + community_walktrap = _community_walktrap - def k_core(self, *args): - """Returns some k-cores of the graph. + k_core = _k_core - The method accepts an arbitrary number of arguments representing - the desired indices of the M{k}-cores to be returned. The arguments - can also be lists or tuples. The result is a single L{Graph} object - if an only integer argument was given, otherwise the result is a - list of L{Graph} objects representing the desired k-cores in the - order the arguments were specified. If no argument is given, returns - all M{k}-cores in increasing order of M{k}. - """ - if len(args) == 0: - indices = range(self.vcount()) - return_single = False - else: - return_single = True - indices = [] - for arg in args: - try: - indices.extend(arg) - except Exception: - indices.append(arg) - - if len(indices) > 1 or hasattr(args[0], "__iter__"): - return_single = False - - corenesses = self.coreness() - result = [] - vidxs = range(self.vcount()) - for idx in indices: - core_idxs = [vidx for vidx in vidxs if corenesses[vidx] >= idx] - result.append(self.subgraph(core_idxs)) - - if return_single: - return result[0] - return result - - def community_leiden( - self, - objective_function="CPM", - weights=None, - resolution_parameter=1.0, - beta=0.01, - initial_membership=None, - n_iterations=2, - node_weights=None, - ): - """Finds the community structure of the graph using the Leiden - algorithm of Traag, van Eck & Waltman. - - @param objective_function: whether to use the Constant Potts - Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. - @param weights: edge weights to be used. Can be a sequence or - iterable or even an edge attribute name. - @param resolution_parameter: the resolution parameter to use. - Higher resolutions lead to more smaller communities, while - lower resolutions lead to fewer larger communities. - @param beta: parameter affecting the randomness in the Leiden - algorithm. This affects only the refinement step of the algorithm. - @param initial_membership: if provided, the Leiden algorithm - will try to improve this provided membership. If no argument is - provided, the aglorithm simply starts from the singleton partition. - @param n_iterations: the number of iterations to iterate the Leiden - algorithm. Each iteration may improve the partition further. Using - a negative number of iterations will run until a stable iteration is - encountered (i.e. the quality was not increased during that - iteration). - @param node_weights: the node weights used in the Leiden algorithm. - If this is not provided, it will be automatically determined on the - basis of whether you want to use CPM or modularity. If you do provide - this, please make sure that you understand what you are doing. - @return: an appropriate L{VertexClustering} object. - - @newfield ref: Reference - @ref: Traag, V. A., Waltman, L., & van Eck, N. J. (2019). From Louvain - to Leiden: guaranteeing well-connected communities. Scientific - reports, 9(1), 5233. doi: 10.1038/s41598-019-41695-z - """ - if objective_function.lower() not in ("cpm", "modularity"): - raise ValueError('objective_function must be "CPM" or "modularity".') - - membership = GraphBase.community_leiden( - self, - edge_weights=weights, - node_weights=node_weights, - resolution_parameter=resolution_parameter, - normalize_resolution=(objective_function == "modularity"), - beta=beta, - initial_membership=initial_membership, - n_iterations=n_iterations, - ) - - if weights is not None: - modularity_params = dict(weights=weights) - else: - modularity_params = {} - return VertexClustering(self, membership, modularity_params=modularity_params) + community_leiden = _community_leiden def layout(self, layout=None, *args, **kwds): """Returns the layout of the graph according to a layout algorithm. @@ -3710,7 +3289,7 @@ def write(graph, filename, *args, **kwds): config = init_configuration() -# Remove constructors from namespace +# Remove modular methods from namespace del ( construct_graph_from_formula, _construct_graph_from_graphmlz_file, @@ -3739,4 +3318,16 @@ def write(graph, filename, *args, **kwds): _export_graph_to_dict_dict, _export_graph_to_dict_list, _export_graph_to_tuple_list, + _community_fastgreedy, + _community_infomap, + _community_leading_eigenvector_naive, + _community_leading_eigenvector, + _community_label_propagation, + _community_multilevel, + _community_optimal_modularity, + _community_edge_betweenness, + _community_spinglass, + _community_walktrap, + _k_core, + _community_leiden, ) diff --git a/src/igraph/community/__init__.py b/src/igraph/community/__init__.py new file mode 100644 index 000000000..cf5b56410 --- /dev/null +++ b/src/igraph/community/__init__.py @@ -0,0 +1,478 @@ +from igraph._igraph import GraphBase +from igraph.clustering import VertexDendrogram, VertexClustering +from igraph.utils import ( + safemax, +) + + +def _community_fastgreedy(graph, weights=None): + """Community structure based on the greedy optimization of modularity. + + This algorithm merges individual nodes into communities in a way that + greedily maximizes the modularity score of the graph. It can be proven + that if no merge can increase the current modularity score, the + algorithm can be stopped since no further increase can be achieved. + + This algorithm is said to run almost in linear time on sparse graphs. + + @param weights: edge attribute name or a list containing edge + weights + @return: an appropriate L{VertexDendrogram} object. + + @newfield ref: Reference + @ref: A Clauset, MEJ Newman and C Moore: Finding community structure + in very large networks. Phys Rev E 70, 066111 (2004). + """ + merges, qs = GraphBase.community_fastgreedy(graph, weights) + + # qs may be shorter than |V|-1 if we are left with a few separated + # communities in the end; take this into account + diff = graph.vcount() - len(qs) + qs.reverse() + if qs: + optimal_count = qs.index(max(qs)) + diff + 1 + else: + optimal_count = diff + + return VertexDendrogram( + graph, merges, optimal_count, modularity_params=dict(weights=weights) + ) + + +def _community_infomap(graph, edge_weights=None, vertex_weights=None, trials=10): + """Finds the community structure of the network according to the Infomap + method of Martin Rosvall and Carl T. Bergstrom. + + @param edge_weights: name of an edge attribute or a list containing + edge weights. + @param vertex_weights: name of an vertex attribute or a list containing + vertex weights. + @param trials: the number of attempts to partition the network. + @return: an appropriate L{VertexClustering} object with an extra attribute + called C{codelength} that stores the code length determined by the + algorithm. + + @newfield ref: Reference + @ref: M. Rosvall and C. T. Bergstrom: Maps of information flow reveal + community structure in complex networks, PNAS 105, 1118 (2008). + U{http://dx.doi.org/10.1073/pnas.0706851105}, + U{http://arxiv.org/abs/0707.0609}. + @ref: M. Rosvall, D. Axelsson, and C. T. Bergstrom: The map equation, + Eur. Phys. J. Special Topics 178, 13 (2009). + U{http://dx.doi.org/10.1140/epjst/e2010-01179-1}, + U{http://arxiv.org/abs/0906.1405}. + """ + membership, codelength = GraphBase.community_infomap( + graph, edge_weights, vertex_weights, trials + ) + return VertexClustering( + graph, + membership, + params={"codelength": codelength}, + modularity_params={"weights": edge_weights}, + ) + + +def _community_leading_eigenvector_naive(graph, clusters=None, return_merges=False): + """Naive implementation of Newman's eigenvector community structure detection. + + This function splits the network into two components + according to the leading eigenvector of the modularity matrix and + then recursively takes the given number of steps by splitting the + communities as individual networks. This is not the correct way, + however, see the reference for explanation. Consider using the + correct L{community_leading_eigenvector} method instead. + + @param clusters: the desired number of communities. If C{None}, the + algorithm tries to do as many splits as possible. Note that the + algorithm won't split a community further if the signs of the leading + eigenvector are all the same, so the actual number of discovered + communities can be less than the desired one. + @param return_merges: whether the returned object should be a + dendrogram instead of a single clustering. + @return: an appropriate L{VertexClustering} or L{VertexDendrogram} + object. + + @newfield ref: Reference + @ref: MEJ Newman: Finding community structure in networks using the + eigenvectors of matrices, arXiv:physics/0605087""" + if clusters is None: + clusters = -1 + cl, merges, q = GraphBase.community_leading_eigenvector_naive( + graph, clusters, return_merges + ) + if merges is None: + return VertexClustering(graph, cl, modularity=q) + else: + return VertexDendrogram(graph, merges, safemax(cl) + 1) + + +def _community_leading_eigenvector( + graph, clusters=None, weights=None, arpack_options=None +): + """Newman's leading eigenvector method for detecting community structure. + + This is the proper implementation of the recursive, divisive algorithm: + each split is done by maximizing the modularity regarding the + original network. + + @param clusters: the desired number of communities. If C{None}, the + algorithm tries to do as many splits as possible. Note that the + algorithm won't split a community further if the signs of the leading + eigenvector are all the same, so the actual number of discovered + communities can be less than the desired one. + @param weights: name of an edge attribute or a list containing + edge weights. + @param arpack_options: an L{ARPACKOptions} object used to fine-tune + the ARPACK eigenvector calculation. If omitted, the module-level + variable called C{arpack_options} is used. + @return: an appropriate L{VertexClustering} object. + + @newfield ref: Reference + @ref: MEJ Newman: Finding community structure in networks using the + eigenvectors of matrices, arXiv:physics/0605087""" + if clusters is None: + clusters = -1 + + kwds = dict(weights=weights) + if arpack_options is not None: + kwds["arpack_options"] = arpack_options + + membership, _, q = GraphBase.community_leading_eigenvector( + graph, clusters, **kwds + ) + return VertexClustering(graph, membership, modularity=q) + + +def _community_label_propagation(graph, weights=None, initial=None, fixed=None): + """Finds the community structure of the graph according to the label + propagation method of Raghavan et al. + + Initially, each vertex is assigned a different label. After that, + each vertex chooses the dominant label in its neighbourhood in each + iteration. Ties are broken randomly and the order in which the + vertices are updated is randomized before every iteration. The + algorithm ends when vertices reach a consensus. + Note that since ties are broken randomly, there is no guarantee that + the algorithm returns the same community structure after each run. + In fact, they frequently differ. See the paper of Raghavan et al + on how to come up with an aggregated community structure. + @param weights: name of an edge attribute or a list containing + edge weights + @param initial: name of a vertex attribute or a list containing + the initial vertex labels. Labels are identified by integers from + zero to M{n-1} where M{n} is the number of vertices. Negative + numbers may also be present in this vector, they represent unlabeled + vertices. + @param fixed: a list of booleans for each vertex. C{True} corresponds + to vertices whose labeling should not change during the algorithm. + It only makes sense if initial labels are also given. Unlabeled + vertices cannot be fixed. It may also be the name of a vertex + attribute; each attribute value will be interpreted as a Boolean. + @return: an appropriate L{VertexClustering} object. + + @newfield ref: Reference + @ref: Raghavan, U.N. and Albert, R. and Kumara, S. Near linear + time algorithm to detect community structures in large-scale + networks. Phys Rev E 76:036106, 2007. + U{http://arxiv.org/abs/0709.2938}. + """ + if isinstance(fixed, str): + fixed = [bool(o) for o in graph.vs[fixed]] + cl = GraphBase.community_label_propagation(graph, weights, initial, fixed) + return VertexClustering(graph, cl, modularity_params=dict(weights=weights)) + + +def _community_multilevel(graph, weights=None, return_levels=False): + """Community structure based on the multilevel algorithm of + Blondel et al. + + This is a bottom-up algorithm: initially every vertex belongs to a + separate community, and vertices are moved between communities + iteratively in a way that maximizes the vertices' local contribution + to the overall modularity score. When a consensus is reached (i.e. no + single move would increase the modularity score), every community in + the original graph is shrank to a single vertex (while keeping the + total weight of the adjacent edges) and the process continues on the + next level. The algorithm stops when it is not possible to increase + the modularity any more after shrinking the communities to vertices. + + This algorithm is said to run almost in linear time on sparse graphs. + + @param weights: edge attribute name or a list containing edge + weights + @param return_levels: if C{True}, the communities at each level are + returned in a list. If C{False}, only the community structure with + the best modularity is returned. + @return: a list of L{VertexClustering} objects, one corresponding to + each level (if C{return_levels} is C{True}), or a L{VertexClustering} + corresponding to the best modularity. + + @newfield ref: Reference + @ref: VD Blondel, J-L Guillaume, R Lambiotte and E Lefebvre: Fast + unfolding of community hierarchies in large networks, J Stat Mech + P10008 (2008), http://arxiv.org/abs/0803.0476 + """ + if graph.is_directed(): + raise ValueError("input graph must be undirected") + + if return_levels: + levels, qs = GraphBase.community_multilevel(graph, weights, True) + result = [] + for level, q in zip(levels, qs): + result.append( + VertexClustering( + graph, level, q, modularity_params=dict(weights=weights) + ) + ) + else: + membership = GraphBase.community_multilevel(graph, weights, False) + result = VertexClustering( + graph, membership, modularity_params=dict(weights=weights) + ) + return result + + +def _community_optimal_modularity(graph, *args, **kwds): + """Calculates the optimal modularity score of the graph and the + corresponding community structure. + + This function uses the GNU Linear Programming Kit to solve a large + integer optimization problem in order to find the optimal modularity + score and the corresponding community structure, therefore it is + unlikely to work for graphs larger than a few (less than a hundred) + vertices. Consider using one of the heuristic approaches instead if + you have such a large graph. + + @return: the calculated membership vector and the corresponding + modularity in a tuple.""" + membership, modularity = GraphBase.community_optimal_modularity( + graph, *args, **kwds + ) + return VertexClustering(graph, membership, modularity) + + +def _community_edge_betweenness(graph, clusters=None, directed=True, weights=None): + """Community structure based on the betweenness of the edges in the + network. + + The idea is that the betweenness of the edges connecting two + communities is typically high, as many of the shortest paths between + nodes in separate communities go through them. So we gradually remove + the edge with the highest betweenness and recalculate the betweennesses + after every removal. This way sooner or later the network falls of to + separate components. The result of the clustering will be represented + by a dendrogram. + + @param clusters: the number of clusters we would like to see. This + practically defines the "level" where we "cut" the dendrogram to + get the membership vector of the vertices. If C{None}, the dendrogram + is cut at the level which maximizes the modularity when the graph is + unweighted; otherwise the dendrogram is cut at at a single cluster + (because cluster count selection based on modularities does not make + sense for this method if not all the weights are equal). + @param directed: whether the directionality of the edges should be + taken into account or not. + @param weights: name of an edge attribute or a list containing + edge weights. + @return: a L{VertexDendrogram} object, initally cut at the maximum + modularity or at the desired number of clusters. + """ + merges, qs = GraphBase.community_edge_betweenness(graph, directed, weights) + if qs is not None: + qs.reverse() + if clusters is None: + if qs: + clusters = qs.index(max(qs)) + 1 + else: + clusters = 1 + return VertexDendrogram( + graph, merges, clusters, modularity_params=dict(weights=weights) + ) + + +def _community_spinglass(graph, *args, **kwds): + """Finds the community structure of the graph according to the + spinglass community detection method of Reichardt & Bornholdt. + + @param weights: edge weights to be used. Can be a sequence or + iterable or even an edge attribute name. + @param spins: integer, the number of spins to use. This is the + upper limit for the number of communities. It is not a problem + to supply a (reasonably) big number here, in which case some + spin states will be unpopulated. + @param parupdate: whether to update the spins of the vertices in + parallel (synchronously) or not + @param start_temp: the starting temperature + @param stop_temp: the stop temperature + @param cool_fact: cooling factor for the simulated annealing + @param update_rule: specifies the null model of the simulation. + Possible values are C{"config"} (a random graph with the same + vertex degrees as the input graph) or C{"simple"} (a random + graph with the same number of edges) + @param gamma: the gamma argument of the algorithm, specifying the + balance between the importance of present and missing edges + within a community. The default value of 1.0 assigns equal + importance to both of them. + @param implementation: currently igraph contains two implementations + of the spinglass community detection algorithm. The faster + original implementation is the default. The other implementation + is able to take into account negative weights, this can be + chosen by setting C{implementation} to C{"neg"} + @param lambda_: the lambda argument of the algorithm, which + specifies the balance between the importance of present and missing + negatively weighted edges within a community. Smaller values of + lambda lead to communities with less negative intra-connectivity. + If the argument is zero, the algorithm reduces to a graph coloring + algorithm, using the number of spins as colors. This argument is + ignored if the original implementation is used. Note the underscore + at the end of the argument name; this is due to the fact that + lambda is a reserved keyword in Python. + @return: an appropriate L{VertexClustering} object. + + @newfield ref: Reference + @ref: Reichardt J and Bornholdt S: Statistical mechanics of + community detection. Phys Rev E 74:016110 (2006). + U{http://arxiv.org/abs/cond-mat/0603718}. + @ref: Traag VA and Bruggeman J: Community detection in networks + with positive and negative links. Phys Rev E 80:036115 (2009). + U{http://arxiv.org/abs/0811.2329}. + """ + membership = GraphBase.community_spinglass(graph, *args, **kwds) + if "weights" in kwds: + modularity_params = dict(weights=kwds["weights"]) + else: + modularity_params = {} + return VertexClustering(graph, membership, modularity_params=modularity_params) + + +def _community_walktrap(graph, weights=None, steps=4): + """Community detection algorithm of Latapy & Pons, based on random + walks. + + The basic idea of the algorithm is that short random walks tend to stay + in the same community. The result of the clustering will be represented + as a dendrogram. + + @param weights: name of an edge attribute or a list containing + edge weights + @param steps: length of random walks to perform + + @return: a L{VertexDendrogram} object, initially cut at the maximum + modularity. + + @newfield ref: Reference + @ref: Pascal Pons, Matthieu Latapy: Computing communities in large + networks using random walks, U{http://arxiv.org/abs/physics/0512106}. + """ + merges, qs = GraphBase.community_walktrap(graph, weights, steps) + qs.reverse() + if qs: + optimal_count = qs.index(max(qs)) + 1 + else: + optimal_count = 1 + return VertexDendrogram( + graph, merges, optimal_count, modularity_params=dict(weights=weights) + ) + + +def _k_core(graph, *args): + """Returns some k-cores of the graph. + + The method accepts an arbitrary number of arguments representing + the desired indices of the M{k}-cores to be returned. The arguments + can also be lists or tuples. The result is a single L{Graph} object + if an only integer argument was given, otherwise the result is a + list of L{Graph} objects representing the desired k-cores in the + order the arguments were specified. If no argument is given, returns + all M{k}-cores in increasing order of M{k}. + """ + if len(args) == 0: + indices = range(graph.vcount()) + return_single = False + else: + return_single = True + indices = [] + for arg in args: + try: + indices.extend(arg) + except Exception: + indices.append(arg) + + if len(indices) > 1 or hasattr(args[0], "__iter__"): + return_single = False + + corenesses = graph.coreness() + result = [] + vidxs = range(graph.vcount()) + for idx in indices: + core_idxs = [vidx for vidx in vidxs if corenesses[vidx] >= idx] + result.append(graph.subgraph(core_idxs)) + + if return_single: + return result[0] + return result + + +def _community_leiden( + graph, + objective_function="CPM", + weights=None, + resolution_parameter=1.0, + beta=0.01, + initial_membership=None, + n_iterations=2, + node_weights=None, +): + """Finds the community structure of the graph using the Leiden + algorithm of Traag, van Eck & Waltman. + + @param objective_function: whether to use the Constant Potts + Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. + @param weights: edge weights to be used. Can be a sequence or + iterable or even an edge attribute name. + @param resolution_parameter: the resolution parameter to use. + Higher resolutions lead to more smaller communities, while + lower resolutions lead to fewer larger communities. + @param beta: parameter affecting the randomness in the Leiden + algorithm. This affects only the refinement step of the algorithm. + @param initial_membership: if provided, the Leiden algorithm + will try to improve this provided membership. If no argument is + provided, the aglorithm simply starts from the singleton partition. + @param n_iterations: the number of iterations to iterate the Leiden + algorithm. Each iteration may improve the partition further. Using + a negative number of iterations will run until a stable iteration is + encountered (i.e. the quality was not increased during that + iteration). + @param node_weights: the node weights used in the Leiden algorithm. + If this is not provided, it will be automatically determined on the + basis of whether you want to use CPM or modularity. If you do provide + this, please make sure that you understand what you are doing. + @return: an appropriate L{VertexClustering} object. + + @newfield ref: Reference + @ref: Traag, V. A., Waltman, L., & van Eck, N. J. (2019). From Louvain + to Leiden: guaranteeing well-connected communities. Scientific + reports, 9(1), 5233. doi: 10.1038/s41598-019-41695-z + """ + if objective_function.lower() not in ("cpm", "modularity"): + raise ValueError('objective_function must be "CPM" or "modularity".') + + membership = GraphBase.community_leiden( + graph, + edge_weights=weights, + node_weights=node_weights, + resolution_parameter=resolution_parameter, + normalize_resolution=(objective_function == "modularity"), + beta=beta, + initial_membership=initial_membership, + n_iterations=n_iterations, + ) + + if weights is not None: + modularity_params = dict(weights=weights) + else: + modularity_params = {} + return VertexClustering(graph, membership, modularity_params=modularity_params) + + From dff42bf6566d0e59d70ca3579cf20dc22cda4ae6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 2 Oct 2021 15:37:31 +1000 Subject: [PATCH 0679/1892] Vertex/EdgeSeq, __plot__, operators --- src/igraph/__init__.py | 1146 +---------------- src/igraph/drawing/graph.py | 202 ++- src/igraph/drawing/utils.py | 65 + src/igraph/operators/__init__.py | 35 + .../{operators.py => operators/functions.py} | 0 src/igraph/operators/methods.py | 211 +++ src/igraph/seq/__init__.py | 700 ++++++++++ src/igraph/seq/edgeseq.py | 431 +++++++ 8 files changed, 1662 insertions(+), 1128 deletions(-) create mode 100644 src/igraph/operators/__init__.py rename src/igraph/{operators.py => operators/functions.py} (100%) create mode 100644 src/igraph/operators/methods.py create mode 100644 src/igraph/seq/__init__.py create mode 100644 src/igraph/seq/edgeseq.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 7a53fd765..974822571 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -132,6 +132,8 @@ palettes, known_colors, ) +from igraph.drawing.graph import __plot__ as _graph_plot +from igraph.drawing.utils import autocurve from igraph.datatypes import Matrix, DyadCensus, TriadCensus, UniqueIdGenerator from igraph.formula import construct_graph_from_formula from igraph.io.files import ( @@ -183,7 +185,13 @@ from igraph.io.images import _write_graph_to_svg from igraph.layout import Layout from igraph.matching import Matching -from igraph.operators import disjoint_union, union, intersection +from igraph.operators import ( + disjoint_union, + union, + intersection, + operator_method_registry as _operator_method_registry, +) +from igraph.seq import EdgeSeq, VertexSeq from igraph.statistics import ( FittedPowerLaw, Histogram, @@ -1736,184 +1744,24 @@ def _as_parameter_(self): ################### # Custom operators + __iadd__ = _operator_method_registry['__iadd__'] - def __iadd__(self, other): - """In-place addition (disjoint union). - - @see: L{__add__} - """ - if isinstance(other, (int, str)): - self.add_vertices(other) - return self - elif isinstance(other, tuple) and len(other) == 2: - self.add_edges([other]) - return self - elif isinstance(other, list): - if not other: - return self - if isinstance(other[0], tuple): - self.add_edges(other) - return self - if isinstance(other[0], str): - self.add_vertices(other) - return self - return NotImplemented - - def __add__(self, other): - """Copies the graph and extends the copy depending on the type of - the other object given. - - @param other: if it is an integer, the copy is extended by the given - number of vertices. If it is a string, the copy is extended by a - single vertex whose C{name} attribute will be equal to the given - string. If it is a tuple with two elements, the copy - is extended by a single edge. If it is a list of tuples, the copy - is extended by multiple edges. If it is a L{Graph}, a disjoint - union is performed. - """ - if isinstance(other, (int, str)): - g = self.copy() - g.add_vertices(other) - elif isinstance(other, tuple) and len(other) == 2: - g = self.copy() - g.add_edges([other]) - elif isinstance(other, list): - if len(other) > 0: - if isinstance(other[0], tuple): - g = self.copy() - g.add_edges(other) - elif isinstance(other[0], str): - g = self.copy() - g.add_vertices(other) - elif isinstance(other[0], Graph): - return self.disjoint_union(other) - else: - return NotImplemented - else: - return self.copy() - - elif isinstance(other, Graph): - return self.disjoint_union(other) - else: - return NotImplemented + __add__ = _operator_method_registry['__add__'] - return g + __and__ = _operator_method_registry['__and__'] - def __and__(self, other): - """Graph intersection operator. + __isub__ = _operator_method_registry['__isub__'] - @param other: the other graph to take the intersection with. - @return: the intersected graph. - """ - if isinstance(other, Graph): - return self.intersection(other) - else: - return NotImplemented - - def __isub__(self, other): - """In-place subtraction (difference). - - @see: L{__sub__}""" - if isinstance(other, int): - self.delete_vertices([other]) - elif isinstance(other, tuple) and len(other) == 2: - self.delete_edges([other]) - elif isinstance(other, list): - if len(other) > 0: - if isinstance(other[0], tuple): - self.delete_edges(other) - elif isinstance(other[0], (int, str)): - self.delete_vertices(other) - else: - return NotImplemented - elif isinstance(other, Vertex): - self.delete_vertices(other) - elif isinstance(other, VertexSeq): - self.delete_vertices(other) - elif isinstance(other, Edge): - self.delete_edges(other) - elif isinstance(other, EdgeSeq): - self.delete_edges(other) - else: - return NotImplemented - return self - - def __sub__(self, other): - """Removes the given object(s) from the graph - - @param other: if it is an integer, removes the vertex with the given - ID from the graph (note that the remaining vertices will get - re-indexed!). If it is a tuple, removes the given edge. If it is - a graph, takes the difference of the two graphs. Accepts - lists of integers or lists of tuples as well, but they can't be - mixed! Also accepts L{Edge} and L{EdgeSeq} objects. - """ - if isinstance(other, Graph): - return self.difference(other) - - result = self.copy() - if isinstance(other, (int, str)): - result.delete_vertices([other]) - elif isinstance(other, tuple) and len(other) == 2: - result.delete_edges([other]) - elif isinstance(other, list): - if len(other) > 0: - if isinstance(other[0], tuple): - result.delete_edges(other) - elif isinstance(other[0], (int, str)): - result.delete_vertices(other) - else: - return NotImplemented - else: - return result - elif isinstance(other, Vertex): - result.delete_vertices(other) - elif isinstance(other, VertexSeq): - result.delete_vertices(other) - elif isinstance(other, Edge): - result.delete_edges(other) - elif isinstance(other, EdgeSeq): - result.delete_edges(other) - else: - return NotImplemented + __sub__ = _operator_method_registry['__sub__'] - return result + __mul__ = _operator_method_registry['__mul__'] - def __mul__(self, other): - """Copies exact replicas of the original graph an arbitrary number of - times. - - @param other: if it is an integer, multiplies the graph by creating the - given number of identical copies and taking the disjoint union of - them. - """ - if isinstance(other, int): - if other == 0: - return Graph() - elif other == 1: - return self - elif other > 1: - return self.disjoint_union([self] * (other - 1)) - else: - return NotImplemented - - return NotImplemented + __or__ = _operator_method_registry['__or__'] def __bool__(self): """Returns True if the graph has at least one vertex, False otherwise.""" return self.vcount() > 0 - def __or__(self, other): - """Graph union operator. - - @param other: the other graph to take the union with. - @return: the union graph. - """ - if isinstance(other, Graph): - return self.union(other) - else: - return NotImplemented - def __coerce__(self, other): """Coercion rules. @@ -1965,204 +1813,7 @@ def __reduce__(self): __iter__ = None # needed for PyPy __hash__ = None # needed for PyPy - def __plot__(self, backend, context, *args, **kwds): - """Plots the graph to the given Cairo context or matplotlib Axes. - - The visual style of vertices and edges can be modified at three - places in the following order of precedence (lower indices override - higher indices): - - 1. Keyword arguments of this function (or of L{plot()} which is - passed intact to C{Graph.__plot__()}. - - 2. Vertex or edge attributes, specified later in the list of - keyword arguments. - - 3. igraph-wide plotting defaults (see - L{igraph.config.Configuration}) - - 4. Built-in defaults. - - E.g., if the C{vertex_size} keyword attribute is not present, - but there exists a vertex attribute named C{size}, the sizes of - the vertices will be specified by that attribute. - - Besides the usual self-explanatory plotting parameters (C{context}, - C{bbox}, C{palette}), it accepts the following keyword arguments: - - - C{autocurve}: whether to use curves instead of straight lines for - multiple edges on the graph plot. This argument may be C{True} - or C{False}; when omitted, C{True} is assumed for graphs with - less than 10.000 edges and C{False} otherwise. - - - C{drawer_factory}: a subclass of L{AbstractCairoGraphDrawer} - which will be used to draw the graph. You may also provide - a function here which takes two arguments: the Cairo context - to draw on and a bounding box (an instance of L{BoundingBox}). - If this keyword argument is missing, igraph will use the - default graph drawer which should be suitable for most purposes. - It is safe to omit this keyword argument unless you need to use - a specific graph drawer. - - - C{keep_aspect_ratio}: whether to keep the aspect ratio of the layout - that igraph calculates to place the nodes. C{True} means that the - layout will be scaled proportionally to fit into the bounding box - where the graph is to be drawn but the aspect ratio will be kept - the same (potentially leaving empty space next to, below or above - the graph). C{False} means that the layout will be scaled independently - along the X and Y axis in order to fill the entire bounding box. - The default is C{False}. - - - C{layout}: the layout to be used. If not an instance of - L{Layout}, it will be passed to L{layout} to calculate - the layout. Note that if you want a deterministic layout that - does not change with every plot, you must either use a - deterministic layout function (like L{layout_circle}) or - calculate the layout in advance and pass a L{Layout} object here. - - - C{margin}: the top, right, bottom, left margins as a 4-tuple. - If it has less than 4 elements or is a single float, the elements - will be re-used until the length is at least 4. - - - C{mark_groups}: whether to highlight some of the vertex groups by - colored polygons. This argument can be one of the following: - - - C{False}: no groups will be highlighted - - - C{True}: only valid if the object plotted is a - L{VertexClustering} or L{VertexCover}. The vertex groups in the - clutering or cover will be highlighted such that the i-th - group will be colored by the i-th color from the current - palette. If used when plotting a graph, it will throw an error. - - - A dict mapping tuples of vertex indices to color names. - The given vertex groups will be highlighted by the given - colors. - - - A list containing pairs or an iterable yielding pairs, where - the first element of each pair is a list of vertex indices and - the second element is a color. - - - A L{VertexClustering} or L{VertexCover} instance. The vertex - groups in the clustering or cover will be highlighted such that - the i-th group will be colored by the i-th color from the - current palette. - - In place of lists of vertex indices, you may also use L{VertexSeq} - instances. - - In place of color names, you may also use color indices into the - current palette. C{None} as a color name will mean that the - corresponding group is ignored. - - - C{vertex_size}: size of the vertices. The corresponding vertex - attribute is called C{size}. The default is 10. Vertex sizes - are measured in the unit of the Cairo context on which igraph - is drawing. - - - C{vertex_color}: color of the vertices. The corresponding vertex - attribute is C{color}, the default is red. Colors can be - specified either by common X11 color names (see the source - code of L{igraph.drawing.colors} for a list of known colors), by - 3-tuples of floats (ranging between 0 and 255 for the R, G and - B components), by CSS-style string specifications (C{#rrggbb}) - or by integer color indices of the specified palette. - - - C{vertex_frame_color}: color of the frame (i.e. stroke) of the - vertices. The corresponding vertex attribute is C{frame_color}, - the default is black. See C{vertex_color} for the possible ways - of specifying a color. - - - C{vertex_frame_width}: the width of the frame (i.e. stroke) of the - vertices. The corresponding vertex attribute is C{frame_width}. - The default is 1. Vertex frame widths are measured in the unit of the - Cairo context on which igraph is drawing. - - - C{vertex_shape}: shape of the vertices. Alternatively it can - be specified by the C{shape} vertex attribute. Possibilities - are: C{square}, {circle}, {triangle}, {triangle-down} or - C{hidden}. See the source code of L{igraph.drawing} for a - list of alternative shape names that are also accepted and - mapped to these. - - - C{vertex_label}: labels drawn next to the vertices. - The corresponding vertex attribute is C{label}. - - - C{vertex_label_dist}: distance of the midpoint of the vertex - label from the center of the corresponding vertex. - The corresponding vertex attribute is C{label_dist}. - - - C{vertex_label_color}: color of the label. Corresponding - vertex attribute: C{label_color}. See C{vertex_color} for - color specification syntax. - - - C{vertex_label_size}: font size of the label, specified - in the unit of the Cairo context on which we are drawing. - Corresponding vertex attribute: C{label_size}. - - - C{vertex_label_angle}: the direction of the line connecting - the midpoint of the vertex with the midpoint of the label. - This can be used to position the labels relative to the - vertices themselves in conjunction with C{vertex_label_dist}. - Corresponding vertex attribute: C{label_angle}. The - default is C{-math.pi/2}. - - - C{vertex_order}: drawing order of the vertices. This must be - a list or tuple containing vertex indices; vertices are then - drawn according to this order. - - - C{vertex_order_by}: an alternative way to specify the drawing - order of the vertices; this attribute is interpreted as the name - of a vertex attribute, and vertices are drawn such that those - with a smaller attribute value are drawn first. You may also - reverse the order by passing a tuple here; the first element of - the tuple should be the name of the attribute, the second element - specifies whether the order is reversed (C{True}, C{False}, - C{"asc"} and C{"desc"} are accepted values). - - - C{edge_color}: color of the edges. The corresponding edge - attribute is C{color}, the default is red. See C{vertex_color} - for color specification syntax. - - - C{edge_curved}: whether the edges should be curved. Positive - numbers correspond to edges curved in a counter-clockwise - direction, negative numbers correspond to edges curved in a - clockwise direction. Zero represents straight edges. C{True} - is interpreted as 0.5, C{False} is interpreted as 0. The - default is 0 which makes all the edges straight. - - - C{edge_width}: width of the edges in the default unit of the - Cairo context on which we are drawing. The corresponding - edge attribute is C{width}, the default is 1. - - - C{edge_arrow_size}: arrow size of the edges. The - corresponding edge attribute is C{arrow_size}, the default - is 1. - - - C{edge_arrow_width}: width of the arrowhead on the edge. The - corresponding edge attribute is C{arrow_width}, the default - is 1. - - - C{edge_order}: drawing order of the edges. This must be - a list or tuple containing edge indices; edges are then - drawn according to this order. - - - C{edge_order_by}: an alternative way to specify the drawing - order of the edges; this attribute is interpreted as the name - of an edge attribute, and edges are drawn such that those - with a smaller attribute value are drawn first. You may also - reverse the order by passing a tuple here; the first element of - the tuple should be the name of the attribute, the second element - specifies whether the order is reversed (C{True}, C{False}, - C{"asc"} and C{"desc"} are accepted values). - """ - from igraph.drawing import DrawerDirectory - - drawer = kwds.pop( - "drawer_factory", - DrawerDirectory.resolve(self, backend)(context), - ) - drawer.draw(self, *args, **kwds) + __plot__ = _graph_plot def __str__(self): """Returns a string representation of the graph. @@ -2299,704 +1950,6 @@ def intersection(self, other, byname="auto"): # of Graph.layout if necessary! -############################################################## - - -class VertexSeq(_VertexSeq): - """Class representing a sequence of vertices in the graph. - - This class is most easily accessed by the C{vs} field of the - L{Graph} object, which returns an ordered sequence of all vertices in - the graph. The vertex sequence can be refined by invoking the - L{VertexSeq.select()} method. L{VertexSeq.select()} can also be - accessed by simply calling the L{VertexSeq} object. - - An alternative way to create a vertex sequence referring to a given - graph is to use the constructor directly: - - >>> g = Graph.Full(3) - >>> vs = VertexSeq(g) - >>> restricted_vs = VertexSeq(g, [0, 1]) - - The individual vertices can be accessed by indexing the vertex sequence - object. It can be used as an iterable as well, or even in a list - comprehension: - - >>> g=Graph.Full(3) - >>> for v in g.vs: - ... v["value"] = v.index ** 2 - ... - >>> [v["value"] ** 0.5 for v in g.vs] - [0.0, 1.0, 2.0] - - The vertex set can also be used as a dictionary where the keys are the - attribute names. The values corresponding to the keys are the values - of the given attribute for every vertex selected by the sequence. - - >>> g=Graph.Full(3) - >>> for idx, v in enumerate(g.vs): - ... v["weight"] = idx*(idx+1) - ... - >>> g.vs["weight"] - [0, 2, 6] - >>> g.vs.select(1,2)["weight"] = [10, 20] - >>> g.vs["weight"] - [0, 10, 20] - - If you specify a sequence that is shorter than the number of vertices in - the VertexSeq, the sequence is reused: - - >>> g = Graph.Tree(7, 2) - >>> g.vs["color"] = ["red", "green"] - >>> g.vs["color"] - ['red', 'green', 'red', 'green', 'red', 'green', 'red'] - - You can even pass a single string or integer, it will be considered as a - sequence of length 1: - - >>> g.vs["color"] = "red" - >>> g.vs["color"] - ['red', 'red', 'red', 'red', 'red', 'red', 'red'] - - Some methods of the vertex sequences are simply proxy methods to the - corresponding methods in the L{Graph} object. One such example is - C{VertexSeq.degree()}: - - >>> g=Graph.Tree(7, 2) - >>> g.vs.degree() - [2, 3, 3, 1, 1, 1, 1] - >>> g.vs.degree() == g.degree() - True - """ - - def attributes(self): - """Returns the list of all the vertex attributes in the graph - associated to this vertex sequence.""" - return self.graph.vertex_attributes() - - def find(self, *args, **kwds): - """Returns the first vertex of the vertex sequence that matches some - criteria. - - The selection criteria are equal to the ones allowed by L{VertexSeq.select}. - See L{VertexSeq.select} for more details. - - For instance, to find the first vertex with name C{foo} in graph C{g}: - - >>> g.vs.find(name="foo") #doctest:+SKIP - - To find an arbitrary isolated vertex: - - >>> g.vs.find(_degree=0) #doctest:+SKIP - """ - # Shortcut: if "name" is in kwds, there are no positional arguments, - # and the specified name is a string, we try that first because that - # attribute is indexed. Note that we cannot do this if name is an - # integer, because it would then translate to g.vs.select(name), which - # searches by _index_ if the argument is an integer - if not args: - if "name" in kwds: - name = kwds.pop("name") - elif "name_eq" in kwds: - name = kwds.pop("name_eq") - else: - name = None - - if name is not None: - if isinstance(name, str): - args = [name] - else: - # put back what we popped - kwds["name"] = name - - if args: - # Selecting first based on positional arguments, then checking - # the criteria specified by the (remaining) keyword arguments - vertex = _VertexSeq.find(self, *args) - if not kwds: - return vertex - vs = self.graph.vs.select(vertex.index) - else: - vs = self - - # Selecting based on keyword arguments - vs = vs.select(**kwds) - if vs: - return vs[0] - raise ValueError("no such vertex") - - def select(self, *args, **kwds): - """Selects a subset of the vertex sequence based on some criteria - - The selection criteria can be specified by the positional and the keyword - arguments. Positional arguments are always processed before keyword - arguments. - - - If the first positional argument is C{None}, an empty sequence is - returned. - - - If the first positional argument is a callable object, the object - will be called for every vertex in the sequence. If it returns - C{True}, the vertex will be included, otherwise it will - be excluded. - - - If the first positional argument is an iterable, it must return - integers and they will be considered as indices of the current - vertex set (NOT the whole vertex set of the graph -- the - difference matters when one filters a vertex set that has - already been filtered by a previous invocation of - L{VertexSeq.select()}. In this case, the indices do not refer - directly to the vertices of the graph but to the elements of - the filtered vertex sequence. - - - If the first positional argument is an integer, all remaining - arguments are expected to be integers. They are considered as - indices of the current vertex set again. - - Keyword arguments can be used to filter the vertices based on their - attributes. The name of the keyword specifies the name of the attribute - and the filtering operator, they should be concatenated by an - underscore (C{_}) character. Attribute names can also contain - underscores, but operator names don't, so the operator is always the - largest trailing substring of the keyword name that does not contain - an underscore. Possible operators are: - - - C{eq}: equal to - - - C{ne}: not equal to - - - C{lt}: less than - - - C{gt}: greater than - - - C{le}: less than or equal to - - - C{ge}: greater than or equal to - - - C{in}: checks if the value of an attribute is in a given list - - - C{notin}: checks if the value of an attribute is not in a given - list - - For instance, if you want to filter vertices with a numeric C{age} - property larger than 200, you have to write: - - >>> g.vs.select(age_gt=200) #doctest: +SKIP - - Similarly, to filter vertices whose C{type} is in a list of predefined - types: - - >>> list_of_types = ["HR", "Finance", "Management"] - >>> g.vs.select(type_in=list_of_types) #doctest: +SKIP - - If the operator is omitted, it defaults to C{eq}. For instance, the - following selector selects vertices whose C{cluster} property equals - to 2: - - >>> g.vs.select(cluster=2) #doctest: +SKIP - - In the case of an unknown operator, it is assumed that the - recognized operator is part of the attribute name and the actual - operator is C{eq}. - - Attribute names inferred from keyword arguments are treated specially - if they start with an underscore (C{_}). These are not real attributes - but refer to specific properties of the vertices, e.g., its degree. - The rule is as follows: if an attribute name starts with an underscore, - the rest of the name is interpreted as a method of the L{Graph} object. - This method is called with the vertex sequence as its first argument - (all others left at default values) and vertices are filtered - according to the value returned by the method. For instance, if you - want to exclude isolated vertices: - - >>> g = Graph.Famous("zachary") - >>> non_isolated = g.vs.select(_degree_gt=0) - - For properties that take a long time to be computed (e.g., betweenness - centrality for large graphs), it is advised to calculate the values - in advance and store it in a graph attribute. The same applies when - you are selecting based on the same property more than once in the - same C{select()} call to avoid calculating it twice unnecessarily. - For instance, the following would calculate betweenness centralities - twice: - - >>> edges = g.vs.select(_betweenness_gt=10, _betweenness_lt=30) - - It is advised to use this instead: - - >>> g.vs["bs"] = g.betweenness() - >>> edges = g.vs.select(bs_gt=10, bs_lt=30) - - @return: the new, filtered vertex sequence""" - vs = _VertexSeq.select(self, *args) - - operators = { - "lt": operator.lt, - "gt": operator.gt, - "le": operator.le, - "ge": operator.ge, - "eq": operator.eq, - "ne": operator.ne, - "in": lambda a, b: a in b, - "notin": lambda a, b: a not in b, - } - for keyword, value in kwds.items(): - if "_" not in keyword or keyword.rindex("_") == 0: - keyword = keyword + "_eq" - attr, _, op = keyword.rpartition("_") - try: - func = operators[op] - except KeyError: - # No such operator, assume that it's part of the attribute name - attr, op, func = keyword, "eq", operators["eq"] - - if attr[0] == "_": - # Method call, not an attribute - values = getattr(vs.graph, attr[1:])(vs) - else: - values = vs[attr] - filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] - vs = vs.select(filtered_idxs) - - return vs - - def __call__(self, *args, **kwds): - """Shorthand notation to select() - - This method simply passes all its arguments to L{VertexSeq.select()}. - """ - return self.select(*args, **kwds) - - -############################################################## - - -class EdgeSeq(_EdgeSeq): - """Class representing a sequence of edges in the graph. - - This class is most easily accessed by the C{es} field of the - L{Graph} object, which returns an ordered sequence of all edges in - the graph. The edge sequence can be refined by invoking the - L{EdgeSeq.select()} method. L{EdgeSeq.select()} can also be - accessed by simply calling the L{EdgeSeq} object. - - An alternative way to create an edge sequence referring to a given - graph is to use the constructor directly: - - >>> g = Graph.Full(3) - >>> es = EdgeSeq(g) - >>> restricted_es = EdgeSeq(g, [0, 1]) - - The individual edges can be accessed by indexing the edge sequence - object. It can be used as an iterable as well, or even in a list - comprehension: - - >>> g=Graph.Full(3) - >>> for e in g.es: - ... print(e.tuple) - ... - (0, 1) - (0, 2) - (1, 2) - >>> [max(e.tuple) for e in g.es] - [1, 2, 2] - - The edge sequence can also be used as a dictionary where the keys are the - attribute names. The values corresponding to the keys are the values - of the given attribute of every edge in the graph: - - >>> g=Graph.Full(3) - >>> for idx, e in enumerate(g.es): - ... e["weight"] = idx*(idx+1) - ... - >>> g.es["weight"] - [0, 2, 6] - >>> g.es["weight"] = range(3) - >>> g.es["weight"] - [0, 1, 2] - - If you specify a sequence that is shorter than the number of edges in - the EdgeSeq, the sequence is reused: - - >>> g = Graph.Tree(7, 2) - >>> g.es["color"] = ["red", "green"] - >>> g.es["color"] - ['red', 'green', 'red', 'green', 'red', 'green'] - - You can even pass a single string or integer, it will be considered as a - sequence of length 1: - - >>> g.es["color"] = "red" - >>> g.es["color"] - ['red', 'red', 'red', 'red', 'red', 'red'] - - Some methods of the edge sequences are simply proxy methods to the - corresponding methods in the L{Graph} object. One such example is - C{EdgeSeq.is_multiple()}: - - >>> g=Graph(3, [(0,1), (1,0), (1,2)]) - >>> g.es.is_multiple() - [False, True, False] - >>> g.es.is_multiple() == g.is_multiple() - True - """ - - def attributes(self): - """Returns the list of all the edge attributes in the graph - associated to this edge sequence.""" - return self.graph.edge_attributes() - - def find(self, *args, **kwds): - """Returns the first edge of the edge sequence that matches some - criteria. - - The selection criteria are equal to the ones allowed by L{VertexSeq.select}. - See L{VertexSeq.select} for more details. - - For instance, to find the first edge with weight larger than 5 in graph C{g}: - - >>> g.es.find(weight_gt=5) #doctest:+SKIP - """ - if args: - # Selecting first based on positional arguments, then checking - # the criteria specified by the keyword arguments - edge = _EdgeSeq.find(self, *args) - if not kwds: - return edge - es = self.graph.es.select(edge.index) - else: - es = self - - # Selecting based on positional arguments - es = es.select(**kwds) - if es: - return es[0] - raise ValueError("no such edge") - - def select(self, *args, **kwds): - """Selects a subset of the edge sequence based on some criteria - - The selection criteria can be specified by the positional and the - keyword arguments. Positional arguments are always processed before - keyword arguments. - - - If the first positional argument is C{None}, an empty sequence is - returned. - - - If the first positional argument is a callable object, the object - will be called for every edge in the sequence. If it returns - C{True}, the edge will be included, otherwise it will - be excluded. - - - If the first positional argument is an iterable, it must return - integers and they will be considered as indices of the current - edge set (NOT the whole edge set of the graph -- the - difference matters when one filters an edge set that has - already been filtered by a previous invocation of - L{EdgeSeq.select()}. In this case, the indices do not refer - directly to the edges of the graph but to the elements of - the filtered edge sequence. - - - If the first positional argument is an integer, all remaining - arguments are expected to be integers. They are considered as - indices of the current edge set again. - - Keyword arguments can be used to filter the edges based on their - attributes and properties. The name of the keyword specifies the name - of the attribute and the filtering operator, they should be - concatenated by an underscore (C{_}) character. Attribute names can - also contain underscores, but operator names don't, so the operator is - always the largest trailing substring of the keyword name that does not - contain an underscore. Possible operators are: - - - C{eq}: equal to - - - C{ne}: not equal to - - - C{lt}: less than - - - C{gt}: greater than - - - C{le}: less than or equal to - - - C{ge}: greater than or equal to - - - C{in}: checks if the value of an attribute is in a given list - - - C{notin}: checks if the value of an attribute is not in a given - list - - For instance, if you want to filter edges with a numeric C{weight} - property larger than 50, you have to write: - - >>> g.es.select(weight_gt=50) #doctest: +SKIP - - Similarly, to filter edges whose C{type} is in a list of predefined - types: - - >>> list_of_types = ["inhibitory", "excitatory"] - >>> g.es.select(type_in=list_of_types) #doctest: +SKIP - - If the operator is omitted, it defaults to C{eq}. For instance, the - following selector selects edges whose C{type} property is - C{intracluster}: - - >>> g.es.select(type="intracluster") #doctest: +SKIP - - In the case of an unknown operator, it is assumed that the - recognized operator is part of the attribute name and the actual - operator is C{eq}. - - Keyword arguments are treated specially if they start with an - underscore (C{_}). These are not real attributes but refer to specific - properties of the edges, e.g., their centrality. The rules are as - follows: - - 1. C{_source} or {_from} means the source vertex of an edge. For - undirected graphs, only the C{eq} operator is supported and it - is treated as {_incident} (since undirected graphs have no notion - of edge directionality). - - 2. C{_target} or {_to} means the target vertex of an edge. For - undirected graphs, only the C{eq} operator is supported and it - is treated as {_incident} (since undirected graphs have no notion - of edge directionality). - - 3. C{_within} ignores the operator and checks whether both endpoints - of the edge lie within a specified set. - - 4. C{_between} ignores the operator and checks whether I{one} - endpoint of the edge lies within a specified set and the I{other} - endpoint lies within another specified set. The two sets must be - given as a tuple. - - 5. C{_incident} ignores the operator and checks whether the edge is - incident on a specific vertex or a set of vertices. - - 6. Otherwise, the rest of the name is interpreted as a method of the - L{Graph} object. This method is called with the edge sequence as - its first argument (all others left at default values) and edges - are filtered according to the value returned by the method. - - For instance, if you want to exclude edges with a betweenness - centrality less than 2: - - >>> g = Graph.Famous("zachary") - >>> excl = g.es.select(_edge_betweenness_ge = 2) - - To select edges originating from vertices 2 and 4: - - >>> edges = g.es.select(_source_in = [2, 4]) - - To select edges lying entirely within the subgraph spanned by vertices - 2, 3, 4 and 7: - - >>> edges = g.es.select(_within = [2, 3, 4, 7]) - - To select edges with one endpoint in the vertex set containing vertices - 2, 3, 4 and 7 and the other endpoint in the vertex set containing - vertices 8 and 9: - - >>> edges = g.es.select(_between = ([2, 3, 4, 7], [8, 9])) - - For properties that take a long time to be computed (e.g., betweenness - centrality for large graphs), it is advised to calculate the values - in advance and store it in a graph attribute. The same applies when - you are selecting based on the same property more than once in the - same C{select()} call to avoid calculating it twice unnecessarily. - For instance, the following would calculate betweenness centralities - twice: - - >>> edges = g.es.select(_edge_betweenness_gt=10, # doctest:+SKIP - ... _edge_betweenness_lt=30) - - It is advised to use this instead: - - >>> g.es["bs"] = g.edge_betweenness() - >>> edges = g.es.select(bs_gt=10, bs_lt=30) - - @return: the new, filtered edge sequence - """ - es = _EdgeSeq.select(self, *args) - is_directed = self.graph.is_directed() - - def _ensure_set(value): - if isinstance(value, VertexSeq): - value = set(v.index for v in value) - elif not isinstance(value, (set, frozenset)): - value = set(value) - return value - - operators = { - "lt": operator.lt, - "gt": operator.gt, - "le": operator.le, - "ge": operator.ge, - "eq": operator.eq, - "ne": operator.ne, - "in": lambda a, b: a in b, - "notin": lambda a, b: a not in b, - } - - # TODO(ntamas): some keyword arguments should be prioritized over - # others; for instance, we have optimized code paths for _source and - # _target in directed and undirected graphs if es.is_all() is True; - # these should be executed first. This matters only if there are - # multiple keyword arguments and es.is_all() is True. - - for keyword, value in kwds.items(): - if "_" not in keyword or keyword.rindex("_") == 0: - keyword = keyword + "_eq" - pos = keyword.rindex("_") - attr, op = keyword[0:pos], keyword[pos + 1 :] - try: - func = operators[op] - except KeyError: - # No such operator, assume that it's part of the attribute name - attr, op, func = keyword, "eq", operators["eq"] - - if attr[0] == "_": - if attr in ("_source", "_from", "_target", "_to") and not is_directed: - if op not in ("eq", "in"): - raise RuntimeError("unsupported for undirected graphs") - - # translate to _incident to avoid confusion - attr = "_incident" - if func == operators["eq"]: - if hasattr(value, "__iter__") and not isinstance(value, str): - value = set(value) - else: - value = set([value]) - - if attr in ("_source", "_from"): - if es.is_all() and op == "eq": - # shortcut here: use .incident() as it is much faster - filtered_idxs = sorted(es.graph.incident(value, mode="out")) - func = None - # TODO(ntamas): there are more possibilities; we could - # optimize "ne", "in" and "notin" in similar ways - else: - values = [e.source for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) - - elif attr in ("_target", "_to"): - if es.is_all() and op == "eq": - # shortcut here: use .incident() as it is much faster - filtered_idxs = sorted(es.graph.incident(value, mode="in")) - func = None - # TODO(ntamas): there are more possibilities; we could - # optimize "ne", "in" and "notin" in similar ways - else: - values = [e.target for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) - - elif attr == "_incident": - func = None # ignoring function, filtering here - value = _ensure_set(value) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in value: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those that are in the current edge sequence - filtered_idxs = [ - i for i, e in enumerate(es) if e.index in candidates - ] - else: - # We are done, the filtered indexes are in the candidates set - filtered_idxs = sorted(candidates) - - elif attr == "_within": - func = None # ignoring function, filtering here - value = _ensure_set(value) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in value: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those where both endpoints are OK - filtered_idxs = [ - i - for i, e in enumerate(es) - if e.index in candidates - and e.source in value - and e.target in value - ] - else: - # Optimized version when the edge sequence contains all - # the edges exactly once in increasing order of edge IDs - filtered_idxs = [ - i - for i in candidates - if es[i].source in value and es[i].target in value - ] - - elif attr == "_between": - if len(value) != 2: - raise ValueError( - "_between selector requires two vertex ID lists" - ) - func = None # ignoring function, filtering here - set1 = _ensure_set(value[0]) - set2 = _ensure_set(value[1]) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in set1: - candidates.update(es.graph.incident(v)) - for v in set2: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those where both endpoints are OK - filtered_idxs = [ - i - for i, e in enumerate(es) - if (e.source in set1 and e.target in set2) - or (e.target in set1 and e.source in set2) - ] - else: - # Optimized version when the edge sequence contains all - # the edges exactly once in increasing order of edge IDs - filtered_idxs = [ - i - for i in candidates - if (es[i].source in set1 and es[i].target in set2) - or (es[i].target in set1 and es[i].source in set2) - ] - - else: - # Method call, not an attribute - values = getattr(es.graph, attr[1:])(es) - else: - values = es[attr] - - # If we have a function to apply on the values, do that; otherwise - # we assume that filtered_idxs has already been calculated. - if func is not None: - filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] - - es = es.select(filtered_idxs) - - return es - - def __call__(self, *args, **kwds): - """Shorthand notation to select() - - This method simply passes all its arguments to L{EdgeSeq.select()}. - """ - return self.select(*args, **kwds) - - ############################################################## # Additional methods of VertexSeq and EdgeSeq that call Graph methods @@ -3172,69 +2125,6 @@ def result(*args, **kwds): ############################################################## -def autocurve(graph, attribute="curved", default=0): - """Calculates curvature values for each of the edges in the graph to make - sure that multiple edges are shown properly on a graph plot. - - This function checks the multiplicity of each edge in the graph and - assigns curvature values (numbers between -1 and 1, corresponding to - CCW (-1), straight (0) and CW (1) curved edges) to them. The assigned - values are either stored in an edge attribute or returned as a list, - depending on the value of the I{attribute} argument. - - @param graph: the graph on which the calculation will be run - @param attribute: the name of the edge attribute to save the curvature - values to. The default value is C{curved}, which is the name of the - edge attribute the default graph plotter checks to decide whether an - edge should be curved on the plot or not. If I{attribute} is C{None}, - the result will not be stored. - @param default: the default curvature for single edges. Zero means that - single edges will be straight. If you want single edges to be curved - as well, try passing 0.5 or -0.5 here. - @return: the list of curvature values if I{attribute} is C{None}, - otherwise C{None}. - """ - - # The following loop could be re-written in C if it turns out to be a - # bottleneck. Unfortunately we cannot use Graph.count_multiple() here - # because we have to ignore edge directions. - multiplicities = defaultdict(list) - for edge in graph.es: - u, v = edge.tuple - if u > v: - multiplicities[v, u].append(edge.index) - else: - multiplicities[u, v].append(edge.index) - - result = [default] * graph.ecount() - for eids in multiplicities.values(): - # Is it a single edge? - if len(eids) < 2: - continue - - if len(eids) % 2 == 1: - # Odd number of edges; the last will be straight - result[eids.pop()] = 0 - - # Arrange the remaining edges - curve = 2.0 / (len(eids) + 2) - dcurve, sign = curve, 1 - for idx, eid in enumerate(eids): - edge = graph.es[eid] - if edge.source > edge.target: - result[eid] = -sign * curve - else: - result[eid] = sign * curve - if idx % 2 == 1: - curve += dcurve - sign *= -1 - - if attribute is None: - return result - - graph.es[attribute] = result - - def get_include(): """Returns the folder that contains the C API headers of the Python interface of igraph.""" @@ -3330,4 +2220,6 @@ def write(graph, filename, *args, **kwds): _community_walktrap, _k_core, _community_leiden, + _graph_plot, + _operator_method_registry, ) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index cdca21f0d..6c3732a38 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -17,7 +17,7 @@ from igraph.drawing.baseclasses import AbstractGraphDrawer, AbstractXMLRPCDrawer -__all__ = ("CytoscapeGraphDrawer",) +__all__ = ("CytoscapeGraphDrawer", "__plot__") class CytoscapeGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): @@ -356,3 +356,203 @@ def draw(self, graph, *args, **kwds): ) self.streamer.post(graph, self.connection, encoder=kwds.get("encoder")) + + +def __plot__(self, backend, context, *args, **kwds): + """Plots the graph to the given Cairo context or matplotlib Axes. + + The visual style of vertices and edges can be modified at three + places in the following order of precedence (lower indices override + higher indices): + + 1. Keyword arguments of this function (or of L{plot()} which is + passed intact to C{Graph.__plot__()}. + + 2. Vertex or edge attributes, specified later in the list of + keyword arguments. + + 3. igraph-wide plotting defaults (see + L{igraph.config.Configuration}) + + 4. Built-in defaults. + + E.g., if the C{vertex_size} keyword attribute is not present, + but there exists a vertex attribute named C{size}, the sizes of + the vertices will be specified by that attribute. + + Besides the usual self-explanatory plotting parameters (C{context}, + C{bbox}, C{palette}), it accepts the following keyword arguments: + + - C{autocurve}: whether to use curves instead of straight lines for + multiple edges on the graph plot. This argument may be C{True} + or C{False}; when omitted, C{True} is assumed for graphs with + less than 10.000 edges and C{False} otherwise. + + - C{drawer_factory}: a subclass of L{AbstractCairoGraphDrawer} + which will be used to draw the graph. You may also provide + a function here which takes two arguments: the Cairo context + to draw on and a bounding box (an instance of L{BoundingBox}). + If this keyword argument is missing, igraph will use the + default graph drawer which should be suitable for most purposes. + It is safe to omit this keyword argument unless you need to use + a specific graph drawer. + + - C{keep_aspect_ratio}: whether to keep the aspect ratio of the layout + that igraph calculates to place the nodes. C{True} means that the + layout will be scaled proportionally to fit into the bounding box + where the graph is to be drawn but the aspect ratio will be kept + the same (potentially leaving empty space next to, below or above + the graph). C{False} means that the layout will be scaled independently + along the X and Y axis in order to fill the entire bounding box. + The default is C{False}. + + - C{layout}: the layout to be used. If not an instance of + L{Layout}, it will be passed to L{layout} to calculate + the layout. Note that if you want a deterministic layout that + does not change with every plot, you must either use a + deterministic layout function (like L{layout_circle}) or + calculate the layout in advance and pass a L{Layout} object here. + + - C{margin}: the top, right, bottom, left margins as a 4-tuple. + If it has less than 4 elements or is a single float, the elements + will be re-used until the length is at least 4. + + - C{mark_groups}: whether to highlight some of the vertex groups by + colored polygons. This argument can be one of the following: + + - C{False}: no groups will be highlighted + + - C{True}: only valid if the object plotted is a + L{VertexClustering} or L{VertexCover}. The vertex groups in the + clutering or cover will be highlighted such that the i-th + group will be colored by the i-th color from the current + palette. If used when plotting a graph, it will throw an error. + + - A dict mapping tuples of vertex indices to color names. + The given vertex groups will be highlighted by the given + colors. + + - A list containing pairs or an iterable yielding pairs, where + the first element of each pair is a list of vertex indices and + the second element is a color. + + - A L{VertexClustering} or L{VertexCover} instance. The vertex + groups in the clustering or cover will be highlighted such that + the i-th group will be colored by the i-th color from the + current palette. + + In place of lists of vertex indices, you may also use L{VertexSeq} + instances. + + In place of color names, you may also use color indices into the + current palette. C{None} as a color name will mean that the + corresponding group is ignored. + + - C{vertex_size}: size of the vertices. The corresponding vertex + attribute is called C{size}. The default is 10. Vertex sizes + are measured in the unit of the Cairo context on which igraph + is drawing. + + - C{vertex_color}: color of the vertices. The corresponding vertex + attribute is C{color}, the default is red. Colors can be + specified either by common X11 color names (see the source + code of L{igraph.drawing.colors} for a list of known colors), by + 3-tuples of floats (ranging between 0 and 255 for the R, G and + B components), by CSS-style string specifications (C{#rrggbb}) + or by integer color indices of the specified palette. + + - C{vertex_frame_color}: color of the frame (i.e. stroke) of the + vertices. The corresponding vertex attribute is C{frame_color}, + the default is black. See C{vertex_color} for the possible ways + of specifying a color. + + - C{vertex_frame_width}: the width of the frame (i.e. stroke) of the + vertices. The corresponding vertex attribute is C{frame_width}. + The default is 1. Vertex frame widths are measured in the unit of the + Cairo context on which igraph is drawing. + + - C{vertex_shape}: shape of the vertices. Alternatively it can + be specified by the C{shape} vertex attribute. Possibilities + are: C{square}, {circle}, {triangle}, {triangle-down} or + C{hidden}. See the source code of L{igraph.drawing} for a + list of alternative shape names that are also accepted and + mapped to these. + + - C{vertex_label}: labels drawn next to the vertices. + The corresponding vertex attribute is C{label}. + + - C{vertex_label_dist}: distance of the midpoint of the vertex + label from the center of the corresponding vertex. + The corresponding vertex attribute is C{label_dist}. + + - C{vertex_label_color}: color of the label. Corresponding + vertex attribute: C{label_color}. See C{vertex_color} for + color specification syntax. + + - C{vertex_label_size}: font size of the label, specified + in the unit of the Cairo context on which we are drawing. + Corresponding vertex attribute: C{label_size}. + + - C{vertex_label_angle}: the direction of the line connecting + the midpoint of the vertex with the midpoint of the label. + This can be used to position the labels relative to the + vertices themselves in conjunction with C{vertex_label_dist}. + Corresponding vertex attribute: C{label_angle}. The + default is C{-math.pi/2}. + + - C{vertex_order}: drawing order of the vertices. This must be + a list or tuple containing vertex indices; vertices are then + drawn according to this order. + + - C{vertex_order_by}: an alternative way to specify the drawing + order of the vertices; this attribute is interpreted as the name + of a vertex attribute, and vertices are drawn such that those + with a smaller attribute value are drawn first. You may also + reverse the order by passing a tuple here; the first element of + the tuple should be the name of the attribute, the second element + specifies whether the order is reversed (C{True}, C{False}, + C{"asc"} and C{"desc"} are accepted values). + + - C{edge_color}: color of the edges. The corresponding edge + attribute is C{color}, the default is red. See C{vertex_color} + for color specification syntax. + + - C{edge_curved}: whether the edges should be curved. Positive + numbers correspond to edges curved in a counter-clockwise + direction, negative numbers correspond to edges curved in a + clockwise direction. Zero represents straight edges. C{True} + is interpreted as 0.5, C{False} is interpreted as 0. The + default is 0 which makes all the edges straight. + + - C{edge_width}: width of the edges in the default unit of the + Cairo context on which we are drawing. The corresponding + edge attribute is C{width}, the default is 1. + + - C{edge_arrow_size}: arrow size of the edges. The + corresponding edge attribute is C{arrow_size}, the default + is 1. + + - C{edge_arrow_width}: width of the arrowhead on the edge. The + corresponding edge attribute is C{arrow_width}, the default + is 1. + + - C{edge_order}: drawing order of the edges. This must be + a list or tuple containing edge indices; edges are then + drawn according to this order. + + - C{edge_order_by}: an alternative way to specify the drawing + order of the edges; this attribute is interpreted as the name + of an edge attribute, and edges are drawn such that those + with a smaller attribute value are drawn first. You may also + reverse the order by passing a tuple here; the first element of + the tuple should be the name of the attribute, the second element + specifies whether the order is reversed (C{True}, C{False}, + C{"asc"} and C{"desc"} are accepted values). + """ + from igraph.drawing import DrawerDirectory + + drawer = kwds.pop( + "drawer_factory", + DrawerDirectory.resolve(self, backend)(context), + ) + drawer.draw(self, *args, **kwds) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index 216d13298..c7ef8fa2d 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -2,6 +2,7 @@ Utility classes for drawing routines. """ +from collections import defaultdict from math import atan2, cos, hypot, sin from typing import NamedTuple @@ -16,6 +17,7 @@ "evaluate_cubic_bezier", "intersect_bezier_curve_and_circle", "str_to_orientation", + "autocurve", ) ##################################################################### @@ -665,3 +667,66 @@ def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False if result not in ("lr", "rl", "tb", "bt"): raise ValueError("unknown orientation: %s" % result) return result + + +def autocurve(graph, attribute="curved", default=0): + """Calculates curvature values for each of the edges in the graph to make + sure that multiple edges are shown properly on a graph plot. + + This function checks the multiplicity of each edge in the graph and + assigns curvature values (numbers between -1 and 1, corresponding to + CCW (-1), straight (0) and CW (1) curved edges) to them. The assigned + values are either stored in an edge attribute or returned as a list, + depending on the value of the I{attribute} argument. + + @param graph: the graph on which the calculation will be run + @param attribute: the name of the edge attribute to save the curvature + values to. The default value is C{curved}, which is the name of the + edge attribute the default graph plotter checks to decide whether an + edge should be curved on the plot or not. If I{attribute} is C{None}, + the result will not be stored. + @param default: the default curvature for single edges. Zero means that + single edges will be straight. If you want single edges to be curved + as well, try passing 0.5 or -0.5 here. + @return: the list of curvature values if I{attribute} is C{None}, + otherwise C{None}. + """ + + # The following loop could be re-written in C if it turns out to be a + # bottleneck. Unfortunately we cannot use Graph.count_multiple() here + # because we have to ignore edge directions. + multiplicities = defaultdict(list) + for edge in graph.es: + u, v = edge.tuple + if u > v: + multiplicities[v, u].append(edge.index) + else: + multiplicities[u, v].append(edge.index) + + result = [default] * graph.ecount() + for eids in multiplicities.values(): + # Is it a single edge? + if len(eids) < 2: + continue + + if len(eids) % 2 == 1: + # Odd number of edges; the last will be straight + result[eids.pop()] = 0 + + # Arrange the remaining edges + curve = 2.0 / (len(eids) + 2) + dcurve, sign = curve, 1 + for idx, eid in enumerate(eids): + edge = graph.es[eid] + if edge.source > edge.target: + result[eid] = -sign * curve + else: + result[eid] = sign * curve + if idx % 2 == 1: + curve += dcurve + sign *= -1 + + if attribute is None: + return result + + graph.es[attribute] = result diff --git a/src/igraph/operators/__init__.py b/src/igraph/operators/__init__.py new file mode 100644 index 000000000..cb3407a4c --- /dev/null +++ b/src/igraph/operators/__init__.py @@ -0,0 +1,35 @@ +# vim:ts=4:sw=4:sts=4:et +# -*- coding: utf-8 -*- +"""Implementation of union, disjoint union and intersection operators.""" + +__all__ = ( + "disjoint_union", + "union", + "intersection", + "operator_method_registry", + ) + +from igraph.operators.functions import ( + disjoint_union, + union, + intersection, +) +from igraph.operators.methods import ( + __iadd__, + __add__, + __and__, + __isub__, + __sub__, + __mul__, + __or__, +) + +operator_method_registry = { + '__iadd__': __iadd__, + '__add__': __add__, + '__and__': __and__, + '__isub__': __isub__, + '__sub__': __sub__, + '__mul__': __mul__, + '__or__': __or__, +} diff --git a/src/igraph/operators.py b/src/igraph/operators/functions.py similarity index 100% rename from src/igraph/operators.py rename to src/igraph/operators/functions.py diff --git a/src/igraph/operators/methods.py b/src/igraph/operators/methods.py new file mode 100644 index 000000000..86ccd2821 --- /dev/null +++ b/src/igraph/operators/methods.py @@ -0,0 +1,211 @@ +from igraph._igraph import ( + Vertex, + Edge, +) +from igraph.seq import VertexSeq, EdgeSeq + + +__all__ = ( + "__iadd__", + "__add__", + "__and__", + "__isub__", + "__sub__", + "__mul__", + "__or__", +) + + +def __iadd__(self, other): + """In-place addition (disjoint union). + + @see: L{__add__} + """ + if isinstance(other, (int, str)): + self.add_vertices(other) + return self + elif isinstance(other, tuple) and len(other) == 2: + self.add_edges([other]) + return self + elif isinstance(other, list): + if not other: + return self + if isinstance(other[0], tuple): + self.add_edges(other) + return self + if isinstance(other[0], str): + self.add_vertices(other) + return self + return NotImplemented + + +def __add__(self, other): + """Copies the graph and extends the copy depending on the type of + the other object given. + + @param other: if it is an integer, the copy is extended by the given + number of vertices. If it is a string, the copy is extended by a + single vertex whose C{name} attribute will be equal to the given + string. If it is a tuple with two elements, the copy + is extended by a single edge. If it is a list of tuples, the copy + is extended by multiple edges. If it is a L{Graph}, a disjoint + union is performed. + """ + # Deferred import to avoid cycles + from igraph import Graph + + if isinstance(other, (int, str)): + g = self.copy() + g.add_vertices(other) + elif isinstance(other, tuple) and len(other) == 2: + g = self.copy() + g.add_edges([other]) + elif isinstance(other, list): + if len(other) > 0: + if isinstance(other[0], tuple): + g = self.copy() + g.add_edges(other) + elif isinstance(other[0], str): + g = self.copy() + g.add_vertices(other) + elif isinstance(other[0], Graph): + return self.disjoint_union(other) + else: + return NotImplemented + else: + return self.copy() + + elif isinstance(other, Graph): + return self.disjoint_union(other) + else: + return NotImplemented + + return g + + +def __and__(self, other): + """Graph intersection operator. + + @param other: the other graph to take the intersection with. + @return: the intersected graph. + """ + # Deferred import to avoid cycles + from igraph import Graph + + if isinstance(other, Graph): + return self.intersection(other) + else: + return NotImplemented + + +def __isub__(self, other): + """In-place subtraction (difference). + + @see: L{__sub__}""" + if isinstance(other, int): + self.delete_vertices([other]) + elif isinstance(other, tuple) and len(other) == 2: + self.delete_edges([other]) + elif isinstance(other, list): + if len(other) > 0: + if isinstance(other[0], tuple): + self.delete_edges(other) + elif isinstance(other[0], (int, str)): + self.delete_vertices(other) + else: + return NotImplemented + elif isinstance(other, Vertex): + self.delete_vertices(other) + elif isinstance(other, VertexSeq): + self.delete_vertices(other) + elif isinstance(other, Edge): + self.delete_edges(other) + elif isinstance(other, EdgeSeq): + self.delete_edges(other) + else: + return NotImplemented + return self + + +def __sub__(self, other): + """Removes the given object(s) from the graph + + @param other: if it is an integer, removes the vertex with the given + ID from the graph (note that the remaining vertices will get + re-indexed!). If it is a tuple, removes the given edge. If it is + a graph, takes the difference of the two graphs. Accepts + lists of integers or lists of tuples as well, but they can't be + mixed! Also accepts L{Edge} and L{EdgeSeq} objects. + """ + # Deferred import to avoid cycles + from igraph import Graph + + if isinstance(other, Graph): + return self.difference(other) + + result = self.copy() + if isinstance(other, (int, str)): + result.delete_vertices([other]) + elif isinstance(other, tuple) and len(other) == 2: + result.delete_edges([other]) + elif isinstance(other, list): + if len(other) > 0: + if isinstance(other[0], tuple): + result.delete_edges(other) + elif isinstance(other[0], (int, str)): + result.delete_vertices(other) + else: + return NotImplemented + else: + return result + elif isinstance(other, Vertex): + result.delete_vertices(other) + elif isinstance(other, VertexSeq): + result.delete_vertices(other) + elif isinstance(other, Edge): + result.delete_edges(other) + elif isinstance(other, EdgeSeq): + result.delete_edges(other) + else: + return NotImplemented + + return result + + +def __mul__(self, other): + """Copies exact replicas of the original graph an arbitrary number of + times. + + @param other: if it is an integer, multiplies the graph by creating the + given number of identical copies and taking the disjoint union of + them. + """ + # Deferred import to avoid cycles + from igraph import Graph + + if isinstance(other, int): + if other == 0: + return Graph() + elif other == 1: + return self + elif other > 1: + return self.disjoint_union([self] * (other - 1)) + else: + return NotImplemented + + return NotImplemented + + +def __or__(self, other): + """Graph union operator. + + @param other: the other graph to take the union with. + @return: the union graph. + """ + # Deferred import to avoid cycles + from igraph import Graph + + if isinstance(other, Graph): + return self.union(other) + else: + return NotImplemented diff --git a/src/igraph/seq/__init__.py b/src/igraph/seq/__init__.py new file mode 100644 index 000000000..de065bb79 --- /dev/null +++ b/src/igraph/seq/__init__.py @@ -0,0 +1,700 @@ +import operator + +from igraph._igraph import ( + EdgeSeq as _EdgeSeq, + VertexSeq as _VertexSeq, +) + + +class VertexSeq(_VertexSeq): + """Class representing a sequence of vertices in the graph. + + This class is most easily accessed by the C{vs} field of the + L{Graph} object, which returns an ordered sequence of all vertices in + the graph. The vertex sequence can be refined by invoking the + L{VertexSeq.select()} method. L{VertexSeq.select()} can also be + accessed by simply calling the L{VertexSeq} object. + + An alternative way to create a vertex sequence referring to a given + graph is to use the constructor directly: + + >>> g = Graph.Full(3) + >>> vs = VertexSeq(g) + >>> restricted_vs = VertexSeq(g, [0, 1]) + + The individual vertices can be accessed by indexing the vertex sequence + object. It can be used as an iterable as well, or even in a list + comprehension: + + >>> g=Graph.Full(3) + >>> for v in g.vs: + ... v["value"] = v.index ** 2 + ... + >>> [v["value"] ** 0.5 for v in g.vs] + [0.0, 1.0, 2.0] + + The vertex set can also be used as a dictionary where the keys are the + attribute names. The values corresponding to the keys are the values + of the given attribute for every vertex selected by the sequence. + + >>> g=Graph.Full(3) + >>> for idx, v in enumerate(g.vs): + ... v["weight"] = idx*(idx+1) + ... + >>> g.vs["weight"] + [0, 2, 6] + >>> g.vs.select(1,2)["weight"] = [10, 20] + >>> g.vs["weight"] + [0, 10, 20] + + If you specify a sequence that is shorter than the number of vertices in + the VertexSeq, the sequence is reused: + + >>> g = Graph.Tree(7, 2) + >>> g.vs["color"] = ["red", "green"] + >>> g.vs["color"] + ['red', 'green', 'red', 'green', 'red', 'green', 'red'] + + You can even pass a single string or integer, it will be considered as a + sequence of length 1: + + >>> g.vs["color"] = "red" + >>> g.vs["color"] + ['red', 'red', 'red', 'red', 'red', 'red', 'red'] + + Some methods of the vertex sequences are simply proxy methods to the + corresponding methods in the L{Graph} object. One such example is + C{VertexSeq.degree()}: + + >>> g=Graph.Tree(7, 2) + >>> g.vs.degree() + [2, 3, 3, 1, 1, 1, 1] + >>> g.vs.degree() == g.degree() + True + """ + + def attributes(self): + """Returns the list of all the vertex attributes in the graph + associated to this vertex sequence.""" + return self.graph.vertex_attributes() + + def find(self, *args, **kwds): + """Returns the first vertex of the vertex sequence that matches some + criteria. + + The selection criteria are equal to the ones allowed by L{VertexSeq.select}. + See L{VertexSeq.select} for more details. + + For instance, to find the first vertex with name C{foo} in graph C{g}: + + >>> g.vs.find(name="foo") #doctest:+SKIP + + To find an arbitrary isolated vertex: + + >>> g.vs.find(_degree=0) #doctest:+SKIP + """ + # Shortcut: if "name" is in kwds, there are no positional arguments, + # and the specified name is a string, we try that first because that + # attribute is indexed. Note that we cannot do this if name is an + # integer, because it would then translate to g.vs.select(name), which + # searches by _index_ if the argument is an integer + if not args: + if "name" in kwds: + name = kwds.pop("name") + elif "name_eq" in kwds: + name = kwds.pop("name_eq") + else: + name = None + + if name is not None: + if isinstance(name, str): + args = [name] + else: + # put back what we popped + kwds["name"] = name + + if args: + # Selecting first based on positional arguments, then checking + # the criteria specified by the (remaining) keyword arguments + vertex = _VertexSeq.find(self, *args) + if not kwds: + return vertex + vs = self.graph.vs.select(vertex.index) + else: + vs = self + + # Selecting based on keyword arguments + vs = vs.select(**kwds) + if vs: + return vs[0] + raise ValueError("no such vertex") + + def select(self, *args, **kwds): + """Selects a subset of the vertex sequence based on some criteria + + The selection criteria can be specified by the positional and the keyword + arguments. Positional arguments are always processed before keyword + arguments. + + - If the first positional argument is C{None}, an empty sequence is + returned. + + - If the first positional argument is a callable object, the object + will be called for every vertex in the sequence. If it returns + C{True}, the vertex will be included, otherwise it will + be excluded. + + - If the first positional argument is an iterable, it must return + integers and they will be considered as indices of the current + vertex set (NOT the whole vertex set of the graph -- the + difference matters when one filters a vertex set that has + already been filtered by a previous invocation of + L{VertexSeq.select()}. In this case, the indices do not refer + directly to the vertices of the graph but to the elements of + the filtered vertex sequence. + + - If the first positional argument is an integer, all remaining + arguments are expected to be integers. They are considered as + indices of the current vertex set again. + + Keyword arguments can be used to filter the vertices based on their + attributes. The name of the keyword specifies the name of the attribute + and the filtering operator, they should be concatenated by an + underscore (C{_}) character. Attribute names can also contain + underscores, but operator names don't, so the operator is always the + largest trailing substring of the keyword name that does not contain + an underscore. Possible operators are: + + - C{eq}: equal to + + - C{ne}: not equal to + + - C{lt}: less than + + - C{gt}: greater than + + - C{le}: less than or equal to + + - C{ge}: greater than or equal to + + - C{in}: checks if the value of an attribute is in a given list + + - C{notin}: checks if the value of an attribute is not in a given + list + + For instance, if you want to filter vertices with a numeric C{age} + property larger than 200, you have to write: + + >>> g.vs.select(age_gt=200) #doctest: +SKIP + + Similarly, to filter vertices whose C{type} is in a list of predefined + types: + + >>> list_of_types = ["HR", "Finance", "Management"] + >>> g.vs.select(type_in=list_of_types) #doctest: +SKIP + + If the operator is omitted, it defaults to C{eq}. For instance, the + following selector selects vertices whose C{cluster} property equals + to 2: + + >>> g.vs.select(cluster=2) #doctest: +SKIP + + In the case of an unknown operator, it is assumed that the + recognized operator is part of the attribute name and the actual + operator is C{eq}. + + Attribute names inferred from keyword arguments are treated specially + if they start with an underscore (C{_}). These are not real attributes + but refer to specific properties of the vertices, e.g., its degree. + The rule is as follows: if an attribute name starts with an underscore, + the rest of the name is interpreted as a method of the L{Graph} object. + This method is called with the vertex sequence as its first argument + (all others left at default values) and vertices are filtered + according to the value returned by the method. For instance, if you + want to exclude isolated vertices: + + >>> g = Graph.Famous("zachary") + >>> non_isolated = g.vs.select(_degree_gt=0) + + For properties that take a long time to be computed (e.g., betweenness + centrality for large graphs), it is advised to calculate the values + in advance and store it in a graph attribute. The same applies when + you are selecting based on the same property more than once in the + same C{select()} call to avoid calculating it twice unnecessarily. + For instance, the following would calculate betweenness centralities + twice: + + >>> edges = g.vs.select(_betweenness_gt=10, _betweenness_lt=30) + + It is advised to use this instead: + + >>> g.vs["bs"] = g.betweenness() + >>> edges = g.vs.select(bs_gt=10, bs_lt=30) + + @return: the new, filtered vertex sequence""" + vs = _VertexSeq.select(self, *args) + + operators = { + "lt": operator.lt, + "gt": operator.gt, + "le": operator.le, + "ge": operator.ge, + "eq": operator.eq, + "ne": operator.ne, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, + } + for keyword, value in kwds.items(): + if "_" not in keyword or keyword.rindex("_") == 0: + keyword = keyword + "_eq" + attr, _, op = keyword.rpartition("_") + try: + func = operators[op] + except KeyError: + # No such operator, assume that it's part of the attribute name + attr, op, func = keyword, "eq", operators["eq"] + + if attr[0] == "_": + # Method call, not an attribute + values = getattr(vs.graph, attr[1:])(vs) + else: + values = vs[attr] + filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] + vs = vs.select(filtered_idxs) + + return vs + + def __call__(self, *args, **kwds): + """Shorthand notation to select() + + This method simply passes all its arguments to L{VertexSeq.select()}. + """ + return self.select(*args, **kwds) + + +class EdgeSeq(_EdgeSeq): + """Class representing a sequence of edges in the graph. + + This class is most easily accessed by the C{es} field of the + L{Graph} object, which returns an ordered sequence of all edges in + the graph. The edge sequence can be refined by invoking the + L{EdgeSeq.select()} method. L{EdgeSeq.select()} can also be + accessed by simply calling the L{EdgeSeq} object. + + An alternative way to create an edge sequence referring to a given + graph is to use the constructor directly: + + >>> g = Graph.Full(3) + >>> es = EdgeSeq(g) + >>> restricted_es = EdgeSeq(g, [0, 1]) + + The individual edges can be accessed by indexing the edge sequence + object. It can be used as an iterable as well, or even in a list + comprehension: + + >>> g=Graph.Full(3) + >>> for e in g.es: + ... print(e.tuple) + ... + (0, 1) + (0, 2) + (1, 2) + >>> [max(e.tuple) for e in g.es] + [1, 2, 2] + + The edge sequence can also be used as a dictionary where the keys are the + attribute names. The values corresponding to the keys are the values + of the given attribute of every edge in the graph: + + >>> g=Graph.Full(3) + >>> for idx, e in enumerate(g.es): + ... e["weight"] = idx*(idx+1) + ... + >>> g.es["weight"] + [0, 2, 6] + >>> g.es["weight"] = range(3) + >>> g.es["weight"] + [0, 1, 2] + + If you specify a sequence that is shorter than the number of edges in + the EdgeSeq, the sequence is reused: + + >>> g = Graph.Tree(7, 2) + >>> g.es["color"] = ["red", "green"] + >>> g.es["color"] + ['red', 'green', 'red', 'green', 'red', 'green'] + + You can even pass a single string or integer, it will be considered as a + sequence of length 1: + + >>> g.es["color"] = "red" + >>> g.es["color"] + ['red', 'red', 'red', 'red', 'red', 'red'] + + Some methods of the edge sequences are simply proxy methods to the + corresponding methods in the L{Graph} object. One such example is + C{EdgeSeq.is_multiple()}: + + >>> g=Graph(3, [(0,1), (1,0), (1,2)]) + >>> g.es.is_multiple() + [False, True, False] + >>> g.es.is_multiple() == g.is_multiple() + True + """ + + def attributes(self): + """Returns the list of all the edge attributes in the graph + associated to this edge sequence.""" + return self.graph.edge_attributes() + + def find(self, *args, **kwds): + """Returns the first edge of the edge sequence that matches some + criteria. + + The selection criteria are equal to the ones allowed by L{VertexSeq.select}. + See L{VertexSeq.select} for more details. + + For instance, to find the first edge with weight larger than 5 in graph C{g}: + + >>> g.es.find(weight_gt=5) #doctest:+SKIP + """ + if args: + # Selecting first based on positional arguments, then checking + # the criteria specified by the keyword arguments + edge = _EdgeSeq.find(self, *args) + if not kwds: + return edge + es = self.graph.es.select(edge.index) + else: + es = self + + # Selecting based on positional arguments + es = es.select(**kwds) + if es: + return es[0] + raise ValueError("no such edge") + + def select(self, *args, **kwds): + """Selects a subset of the edge sequence based on some criteria + + The selection criteria can be specified by the positional and the + keyword arguments. Positional arguments are always processed before + keyword arguments. + + - If the first positional argument is C{None}, an empty sequence is + returned. + + - If the first positional argument is a callable object, the object + will be called for every edge in the sequence. If it returns + C{True}, the edge will be included, otherwise it will + be excluded. + + - If the first positional argument is an iterable, it must return + integers and they will be considered as indices of the current + edge set (NOT the whole edge set of the graph -- the + difference matters when one filters an edge set that has + already been filtered by a previous invocation of + L{EdgeSeq.select()}. In this case, the indices do not refer + directly to the edges of the graph but to the elements of + the filtered edge sequence. + + - If the first positional argument is an integer, all remaining + arguments are expected to be integers. They are considered as + indices of the current edge set again. + + Keyword arguments can be used to filter the edges based on their + attributes and properties. The name of the keyword specifies the name + of the attribute and the filtering operator, they should be + concatenated by an underscore (C{_}) character. Attribute names can + also contain underscores, but operator names don't, so the operator is + always the largest trailing substring of the keyword name that does not + contain an underscore. Possible operators are: + + - C{eq}: equal to + + - C{ne}: not equal to + + - C{lt}: less than + + - C{gt}: greater than + + - C{le}: less than or equal to + + - C{ge}: greater than or equal to + + - C{in}: checks if the value of an attribute is in a given list + + - C{notin}: checks if the value of an attribute is not in a given + list + + For instance, if you want to filter edges with a numeric C{weight} + property larger than 50, you have to write: + + >>> g.es.select(weight_gt=50) #doctest: +SKIP + + Similarly, to filter edges whose C{type} is in a list of predefined + types: + + >>> list_of_types = ["inhibitory", "excitatory"] + >>> g.es.select(type_in=list_of_types) #doctest: +SKIP + + If the operator is omitted, it defaults to C{eq}. For instance, the + following selector selects edges whose C{type} property is + C{intracluster}: + + >>> g.es.select(type="intracluster") #doctest: +SKIP + + In the case of an unknown operator, it is assumed that the + recognized operator is part of the attribute name and the actual + operator is C{eq}. + + Keyword arguments are treated specially if they start with an + underscore (C{_}). These are not real attributes but refer to specific + properties of the edges, e.g., their centrality. The rules are as + follows: + + 1. C{_source} or {_from} means the source vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). + + 2. C{_target} or {_to} means the target vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). + + 3. C{_within} ignores the operator and checks whether both endpoints + of the edge lie within a specified set. + + 4. C{_between} ignores the operator and checks whether I{one} + endpoint of the edge lies within a specified set and the I{other} + endpoint lies within another specified set. The two sets must be + given as a tuple. + + 5. C{_incident} ignores the operator and checks whether the edge is + incident on a specific vertex or a set of vertices. + + 6. Otherwise, the rest of the name is interpreted as a method of the + L{Graph} object. This method is called with the edge sequence as + its first argument (all others left at default values) and edges + are filtered according to the value returned by the method. + + For instance, if you want to exclude edges with a betweenness + centrality less than 2: + + >>> g = Graph.Famous("zachary") + >>> excl = g.es.select(_edge_betweenness_ge = 2) + + To select edges originating from vertices 2 and 4: + + >>> edges = g.es.select(_source_in = [2, 4]) + + To select edges lying entirely within the subgraph spanned by vertices + 2, 3, 4 and 7: + + >>> edges = g.es.select(_within = [2, 3, 4, 7]) + + To select edges with one endpoint in the vertex set containing vertices + 2, 3, 4 and 7 and the other endpoint in the vertex set containing + vertices 8 and 9: + + >>> edges = g.es.select(_between = ([2, 3, 4, 7], [8, 9])) + + For properties that take a long time to be computed (e.g., betweenness + centrality for large graphs), it is advised to calculate the values + in advance and store it in a graph attribute. The same applies when + you are selecting based on the same property more than once in the + same C{select()} call to avoid calculating it twice unnecessarily. + For instance, the following would calculate betweenness centralities + twice: + + >>> edges = g.es.select(_edge_betweenness_gt=10, # doctest:+SKIP + ... _edge_betweenness_lt=30) + + It is advised to use this instead: + + >>> g.es["bs"] = g.edge_betweenness() + >>> edges = g.es.select(bs_gt=10, bs_lt=30) + + @return: the new, filtered edge sequence + """ + es = _EdgeSeq.select(self, *args) + is_directed = self.graph.is_directed() + + def _ensure_set(value): + if isinstance(value, VertexSeq): + value = set(v.index for v in value) + elif not isinstance(value, (set, frozenset)): + value = set(value) + return value + + operators = { + "lt": operator.lt, + "gt": operator.gt, + "le": operator.le, + "ge": operator.ge, + "eq": operator.eq, + "ne": operator.ne, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, + } + + # TODO(ntamas): some keyword arguments should be prioritized over + # others; for instance, we have optimized code paths for _source and + # _target in directed and undirected graphs if es.is_all() is True; + # these should be executed first. This matters only if there are + # multiple keyword arguments and es.is_all() is True. + + for keyword, value in kwds.items(): + if "_" not in keyword or keyword.rindex("_") == 0: + keyword = keyword + "_eq" + pos = keyword.rindex("_") + attr, op = keyword[0:pos], keyword[pos + 1 :] + try: + func = operators[op] + except KeyError: + # No such operator, assume that it's part of the attribute name + attr, op, func = keyword, "eq", operators["eq"] + + if attr[0] == "_": + if attr in ("_source", "_from", "_target", "_to") and not is_directed: + if op not in ("eq", "in"): + raise RuntimeError("unsupported for undirected graphs") + + # translate to _incident to avoid confusion + attr = "_incident" + if func == operators["eq"]: + if hasattr(value, "__iter__") and not isinstance(value, str): + value = set(value) + else: + value = set([value]) + + if attr in ("_source", "_from"): + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="out")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.source for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) + + elif attr in ("_target", "_to"): + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="in")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.target for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) + + elif attr == "_incident": + func = None # ignoring function, filtering here + value = _ensure_set(value) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in value: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those that are in the current edge sequence + filtered_idxs = [ + i for i, e in enumerate(es) if e.index in candidates + ] + else: + # We are done, the filtered indexes are in the candidates set + filtered_idxs = sorted(candidates) + + elif attr == "_within": + func = None # ignoring function, filtering here + value = _ensure_set(value) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in value: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those where both endpoints are OK + filtered_idxs = [ + i + for i, e in enumerate(es) + if e.index in candidates + and e.source in value + and e.target in value + ] + else: + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs + filtered_idxs = [ + i + for i in candidates + if es[i].source in value and es[i].target in value + ] + + elif attr == "_between": + if len(value) != 2: + raise ValueError( + "_between selector requires two vertex ID lists" + ) + func = None # ignoring function, filtering here + set1 = _ensure_set(value[0]) + set2 = _ensure_set(value[1]) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in set1: + candidates.update(es.graph.incident(v)) + for v in set2: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those where both endpoints are OK + filtered_idxs = [ + i + for i, e in enumerate(es) + if (e.source in set1 and e.target in set2) + or (e.target in set1 and e.source in set2) + ] + else: + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs + filtered_idxs = [ + i + for i in candidates + if (es[i].source in set1 and es[i].target in set2) + or (es[i].target in set1 and es[i].source in set2) + ] + + else: + # Method call, not an attribute + values = getattr(es.graph, attr[1:])(es) + else: + values = es[attr] + + # If we have a function to apply on the values, do that; otherwise + # we assume that filtered_idxs has already been calculated. + if func is not None: + filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] + + es = es.select(filtered_idxs) + + return es + + def __call__(self, *args, **kwds): + """Shorthand notation to select() + + This method simply passes all its arguments to L{EdgeSeq.select()}. + """ + return self.select(*args, **kwds) + + diff --git a/src/igraph/seq/edgeseq.py b/src/igraph/seq/edgeseq.py new file mode 100644 index 000000000..8ab03e2c2 --- /dev/null +++ b/src/igraph/seq/edgeseq.py @@ -0,0 +1,431 @@ +import operator + +from igraph._igraph import EdgeSeq as _EdgeSeq + + +class EdgeSeq(_EdgeSeq): + """Class representing a sequence of edges in the graph. + + This class is most easily accessed by the C{es} field of the + L{Graph} object, which returns an ordered sequence of all edges in + the graph. The edge sequence can be refined by invoking the + L{EdgeSeq.select()} method. L{EdgeSeq.select()} can also be + accessed by simply calling the L{EdgeSeq} object. + + An alternative way to create an edge sequence referring to a given + graph is to use the constructor directly: + + >>> g = Graph.Full(3) + >>> es = EdgeSeq(g) + >>> restricted_es = EdgeSeq(g, [0, 1]) + + The individual edges can be accessed by indexing the edge sequence + object. It can be used as an iterable as well, or even in a list + comprehension: + + >>> g=Graph.Full(3) + >>> for e in g.es: + ... print(e.tuple) + ... + (0, 1) + (0, 2) + (1, 2) + >>> [max(e.tuple) for e in g.es] + [1, 2, 2] + + The edge sequence can also be used as a dictionary where the keys are the + attribute names. The values corresponding to the keys are the values + of the given attribute of every edge in the graph: + + >>> g=Graph.Full(3) + >>> for idx, e in enumerate(g.es): + ... e["weight"] = idx*(idx+1) + ... + >>> g.es["weight"] + [0, 2, 6] + >>> g.es["weight"] = range(3) + >>> g.es["weight"] + [0, 1, 2] + + If you specify a sequence that is shorter than the number of edges in + the EdgeSeq, the sequence is reused: + + >>> g = Graph.Tree(7, 2) + >>> g.es["color"] = ["red", "green"] + >>> g.es["color"] + ['red', 'green', 'red', 'green', 'red', 'green'] + + You can even pass a single string or integer, it will be considered as a + sequence of length 1: + + >>> g.es["color"] = "red" + >>> g.es["color"] + ['red', 'red', 'red', 'red', 'red', 'red'] + + Some methods of the edge sequences are simply proxy methods to the + corresponding methods in the L{Graph} object. One such example is + C{EdgeSeq.is_multiple()}: + + >>> g=Graph(3, [(0,1), (1,0), (1,2)]) + >>> g.es.is_multiple() + [False, True, False] + >>> g.es.is_multiple() == g.is_multiple() + True + """ + + def attributes(self): + """Returns the list of all the edge attributes in the graph + associated to this edge sequence.""" + return self.graph.edge_attributes() + + def find(self, *args, **kwds): + """Returns the first edge of the edge sequence that matches some + criteria. + + The selection criteria are equal to the ones allowed by L{VertexSeq.select}. + See L{VertexSeq.select} for more details. + + For instance, to find the first edge with weight larger than 5 in graph C{g}: + + >>> g.es.find(weight_gt=5) #doctest:+SKIP + """ + if args: + # Selecting first based on positional arguments, then checking + # the criteria specified by the keyword arguments + edge = _EdgeSeq.find(self, *args) + if not kwds: + return edge + es = self.graph.es.select(edge.index) + else: + es = self + + # Selecting based on positional arguments + es = es.select(**kwds) + if es: + return es[0] + raise ValueError("no such edge") + + def select(self, *args, **kwds): + """Selects a subset of the edge sequence based on some criteria + + The selection criteria can be specified by the positional and the + keyword arguments. Positional arguments are always processed before + keyword arguments. + + - If the first positional argument is C{None}, an empty sequence is + returned. + + - If the first positional argument is a callable object, the object + will be called for every edge in the sequence. If it returns + C{True}, the edge will be included, otherwise it will + be excluded. + + - If the first positional argument is an iterable, it must return + integers and they will be considered as indices of the current + edge set (NOT the whole edge set of the graph -- the + difference matters when one filters an edge set that has + already been filtered by a previous invocation of + L{EdgeSeq.select()}. In this case, the indices do not refer + directly to the edges of the graph but to the elements of + the filtered edge sequence. + + - If the first positional argument is an integer, all remaining + arguments are expected to be integers. They are considered as + indices of the current edge set again. + + Keyword arguments can be used to filter the edges based on their + attributes and properties. The name of the keyword specifies the name + of the attribute and the filtering operator, they should be + concatenated by an underscore (C{_}) character. Attribute names can + also contain underscores, but operator names don't, so the operator is + always the largest trailing substring of the keyword name that does not + contain an underscore. Possible operators are: + + - C{eq}: equal to + + - C{ne}: not equal to + + - C{lt}: less than + + - C{gt}: greater than + + - C{le}: less than or equal to + + - C{ge}: greater than or equal to + + - C{in}: checks if the value of an attribute is in a given list + + - C{notin}: checks if the value of an attribute is not in a given + list + + For instance, if you want to filter edges with a numeric C{weight} + property larger than 50, you have to write: + + >>> g.es.select(weight_gt=50) #doctest: +SKIP + + Similarly, to filter edges whose C{type} is in a list of predefined + types: + + >>> list_of_types = ["inhibitory", "excitatory"] + >>> g.es.select(type_in=list_of_types) #doctest: +SKIP + + If the operator is omitted, it defaults to C{eq}. For instance, the + following selector selects edges whose C{type} property is + C{intracluster}: + + >>> g.es.select(type="intracluster") #doctest: +SKIP + + In the case of an unknown operator, it is assumed that the + recognized operator is part of the attribute name and the actual + operator is C{eq}. + + Keyword arguments are treated specially if they start with an + underscore (C{_}). These are not real attributes but refer to specific + properties of the edges, e.g., their centrality. The rules are as + follows: + + 1. C{_source} or {_from} means the source vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). + + 2. C{_target} or {_to} means the target vertex of an edge. For + undirected graphs, only the C{eq} operator is supported and it + is treated as {_incident} (since undirected graphs have no notion + of edge directionality). + + 3. C{_within} ignores the operator and checks whether both endpoints + of the edge lie within a specified set. + + 4. C{_between} ignores the operator and checks whether I{one} + endpoint of the edge lies within a specified set and the I{other} + endpoint lies within another specified set. The two sets must be + given as a tuple. + + 5. C{_incident} ignores the operator and checks whether the edge is + incident on a specific vertex or a set of vertices. + + 6. Otherwise, the rest of the name is interpreted as a method of the + L{Graph} object. This method is called with the edge sequence as + its first argument (all others left at default values) and edges + are filtered according to the value returned by the method. + + For instance, if you want to exclude edges with a betweenness + centrality less than 2: + + >>> g = Graph.Famous("zachary") + >>> excl = g.es.select(_edge_betweenness_ge = 2) + + To select edges originating from vertices 2 and 4: + + >>> edges = g.es.select(_source_in = [2, 4]) + + To select edges lying entirely within the subgraph spanned by vertices + 2, 3, 4 and 7: + + >>> edges = g.es.select(_within = [2, 3, 4, 7]) + + To select edges with one endpoint in the vertex set containing vertices + 2, 3, 4 and 7 and the other endpoint in the vertex set containing + vertices 8 and 9: + + >>> edges = g.es.select(_between = ([2, 3, 4, 7], [8, 9])) + + For properties that take a long time to be computed (e.g., betweenness + centrality for large graphs), it is advised to calculate the values + in advance and store it in a graph attribute. The same applies when + you are selecting based on the same property more than once in the + same C{select()} call to avoid calculating it twice unnecessarily. + For instance, the following would calculate betweenness centralities + twice: + + >>> edges = g.es.select(_edge_betweenness_gt=10, # doctest:+SKIP + ... _edge_betweenness_lt=30) + + It is advised to use this instead: + + >>> g.es["bs"] = g.edge_betweenness() + >>> edges = g.es.select(bs_gt=10, bs_lt=30) + + @return: the new, filtered edge sequence + """ + es = _EdgeSeq.select(self, *args) + is_directed = self.graph.is_directed() + + def _ensure_set(value): + if isinstance(value, VertexSeq): + value = set(v.index for v in value) + elif not isinstance(value, (set, frozenset)): + value = set(value) + return value + + operators = { + "lt": operator.lt, + "gt": operator.gt, + "le": operator.le, + "ge": operator.ge, + "eq": operator.eq, + "ne": operator.ne, + "in": lambda a, b: a in b, + "notin": lambda a, b: a not in b, + } + + # TODO(ntamas): some keyword arguments should be prioritized over + # others; for instance, we have optimized code paths for _source and + # _target in directed and undirected graphs if es.is_all() is True; + # these should be executed first. This matters only if there are + # multiple keyword arguments and es.is_all() is True. + + for keyword, value in kwds.items(): + if "_" not in keyword or keyword.rindex("_") == 0: + keyword = keyword + "_eq" + pos = keyword.rindex("_") + attr, op = keyword[0:pos], keyword[pos + 1 :] + try: + func = operators[op] + except KeyError: + # No such operator, assume that it's part of the attribute name + attr, op, func = keyword, "eq", operators["eq"] + + if attr[0] == "_": + if attr in ("_source", "_from", "_target", "_to") and not is_directed: + if op not in ("eq", "in"): + raise RuntimeError("unsupported for undirected graphs") + + # translate to _incident to avoid confusion + attr = "_incident" + if func == operators["eq"]: + if hasattr(value, "__iter__") and not isinstance(value, str): + value = set(value) + else: + value = set([value]) + + if attr in ("_source", "_from"): + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="out")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.source for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) + + elif attr in ("_target", "_to"): + if es.is_all() and op == "eq": + # shortcut here: use .incident() as it is much faster + filtered_idxs = sorted(es.graph.incident(value, mode="in")) + func = None + # TODO(ntamas): there are more possibilities; we could + # optimize "ne", "in" and "notin" in similar ways + else: + values = [e.target for e in es] + if op == "in" or op == "notin": + value = _ensure_set(value) + + elif attr == "_incident": + func = None # ignoring function, filtering here + value = _ensure_set(value) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in value: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those that are in the current edge sequence + filtered_idxs = [ + i for i, e in enumerate(es) if e.index in candidates + ] + else: + # We are done, the filtered indexes are in the candidates set + filtered_idxs = sorted(candidates) + + elif attr == "_within": + func = None # ignoring function, filtering here + value = _ensure_set(value) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in value: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those where both endpoints are OK + filtered_idxs = [ + i + for i, e in enumerate(es) + if e.index in candidates + and e.source in value + and e.target in value + ] + else: + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs + filtered_idxs = [ + i + for i in candidates + if es[i].source in value and es[i].target in value + ] + + elif attr == "_between": + if len(value) != 2: + raise ValueError( + "_between selector requires two vertex ID lists" + ) + func = None # ignoring function, filtering here + set1 = _ensure_set(value[0]) + set2 = _ensure_set(value[1]) + + # Fetch all the edges that are incident on at least one of + # the vertices specified + candidates = set() + for v in set1: + candidates.update(es.graph.incident(v)) + for v in set2: + candidates.update(es.graph.incident(v)) + + if not es.is_all(): + # Find those where both endpoints are OK + filtered_idxs = [ + i + for i, e in enumerate(es) + if (e.source in set1 and e.target in set2) + or (e.target in set1 and e.source in set2) + ] + else: + # Optimized version when the edge sequence contains all + # the edges exactly once in increasing order of edge IDs + filtered_idxs = [ + i + for i in candidates + if (es[i].source in set1 and es[i].target in set2) + or (es[i].target in set1 and es[i].source in set2) + ] + + else: + # Method call, not an attribute + values = getattr(es.graph, attr[1:])(es) + else: + values = es[attr] + + # If we have a function to apply on the values, do that; otherwise + # we assume that filtered_idxs has already been calculated. + if func is not None: + filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] + + es = es.select(filtered_idxs) + + return es + + def __call__(self, *args, **kwds): + """Shorthand notation to select() + + This method simply passes all its arguments to L{EdgeSeq.select()}. + """ + return self.select(*args, **kwds) + + From b1523554603454409743584486ddcd367c5004ea Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 2 Oct 2021 15:42:32 +1000 Subject: [PATCH 0680/1892] Rename self -> graph to make it a little more readable --- src/igraph/operators/methods.py | 76 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/igraph/operators/methods.py b/src/igraph/operators/methods.py index 86ccd2821..9024111f2 100644 --- a/src/igraph/operators/methods.py +++ b/src/igraph/operators/methods.py @@ -16,30 +16,30 @@ ) -def __iadd__(self, other): +def __iadd__(graph, other): """In-place addition (disjoint union). @see: L{__add__} """ if isinstance(other, (int, str)): - self.add_vertices(other) - return self + graph.add_vertices(other) + return graph elif isinstance(other, tuple) and len(other) == 2: - self.add_edges([other]) - return self + graph.add_edges([other]) + return graph elif isinstance(other, list): if not other: - return self + return graph if isinstance(other[0], tuple): - self.add_edges(other) - return self + graph.add_edges(other) + return graph if isinstance(other[0], str): - self.add_vertices(other) - return self + graph.add_vertices(other) + return graph return NotImplemented -def __add__(self, other): +def __add__(graph, other): """Copies the graph and extends the copy depending on the type of the other object given. @@ -55,35 +55,35 @@ def __add__(self, other): from igraph import Graph if isinstance(other, (int, str)): - g = self.copy() + g = graph.copy() g.add_vertices(other) elif isinstance(other, tuple) and len(other) == 2: - g = self.copy() + g = graph.copy() g.add_edges([other]) elif isinstance(other, list): if len(other) > 0: if isinstance(other[0], tuple): - g = self.copy() + g = graph.copy() g.add_edges(other) elif isinstance(other[0], str): - g = self.copy() + g = graph.copy() g.add_vertices(other) elif isinstance(other[0], Graph): - return self.disjoint_union(other) + return graph.disjoint_union(other) else: return NotImplemented else: - return self.copy() + return graph.copy() elif isinstance(other, Graph): - return self.disjoint_union(other) + return graph.disjoint_union(other) else: return NotImplemented return g -def __and__(self, other): +def __and__(graph, other): """Graph intersection operator. @param other: the other graph to take the intersection with. @@ -93,41 +93,41 @@ def __and__(self, other): from igraph import Graph if isinstance(other, Graph): - return self.intersection(other) + return graph.intersection(other) else: return NotImplemented -def __isub__(self, other): +def __isub__(graph, other): """In-place subtraction (difference). @see: L{__sub__}""" if isinstance(other, int): - self.delete_vertices([other]) + graph.delete_vertices([other]) elif isinstance(other, tuple) and len(other) == 2: - self.delete_edges([other]) + graph.delete_edges([other]) elif isinstance(other, list): if len(other) > 0: if isinstance(other[0], tuple): - self.delete_edges(other) + graph.delete_edges(other) elif isinstance(other[0], (int, str)): - self.delete_vertices(other) + graph.delete_vertices(other) else: return NotImplemented elif isinstance(other, Vertex): - self.delete_vertices(other) + graph.delete_vertices(other) elif isinstance(other, VertexSeq): - self.delete_vertices(other) + graph.delete_vertices(other) elif isinstance(other, Edge): - self.delete_edges(other) + graph.delete_edges(other) elif isinstance(other, EdgeSeq): - self.delete_edges(other) + graph.delete_edges(other) else: return NotImplemented - return self + return graph -def __sub__(self, other): +def __sub__(graph, other): """Removes the given object(s) from the graph @param other: if it is an integer, removes the vertex with the given @@ -141,9 +141,9 @@ def __sub__(self, other): from igraph import Graph if isinstance(other, Graph): - return self.difference(other) + return graph.difference(other) - result = self.copy() + result = graph.copy() if isinstance(other, (int, str)): result.delete_vertices([other]) elif isinstance(other, tuple) and len(other) == 2: @@ -172,7 +172,7 @@ def __sub__(self, other): return result -def __mul__(self, other): +def __mul__(graph, other): """Copies exact replicas of the original graph an arbitrary number of times. @@ -187,16 +187,16 @@ def __mul__(self, other): if other == 0: return Graph() elif other == 1: - return self + return graph elif other > 1: - return self.disjoint_union([self] * (other - 1)) + return graph.disjoint_union([graph] * (other - 1)) else: return NotImplemented return NotImplemented -def __or__(self, other): +def __or__(graph, other): """Graph union operator. @param other: the other graph to take the union with. @@ -206,6 +206,6 @@ def __or__(self, other): from igraph import Graph if isinstance(other, Graph): - return self.union(other) + return graph.union(other) else: return NotImplemented From c29061e8bdc260ba32f7c69b031371f4451d9165 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 2 Oct 2021 20:22:26 +1000 Subject: [PATCH 0681/1892] Basic add/delete methods --- src/igraph/__init__.py | 173 ++++++----------------------------- src/igraph/basic/__init__.py | 144 +++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 143 deletions(-) create mode 100644 src/igraph/basic/__init__.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 974822571..d35c93320 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -75,6 +75,13 @@ set_status_handler, __igraph_version__, ) +from igraph.basic import ( + _add_edge, + _add_edges, + _add_vertex, + _add_vertices, + _delete_edges, +) from igraph.community import ( _community_fastgreedy, _community_infomap, @@ -409,113 +416,6 @@ def __init__(self, *args, **kwds): key = str(key) self.es[key] = value - def add_edge(self, source, target, **kwds): - """Adds a single edge to the graph. - - Keyword arguments (except the source and target arguments) will be - assigned to the edge as attributes. - - The performance cost of adding a single edge or several edges - to a graph is similar. Thus, when adding several edges, a single - C{add_edges()} call is more efficient than multiple C{add_edge()} calls. - - @param source: the source vertex of the edge or its name. - @param target: the target vertex of the edge or its name. - - @return: the newly added edge as an L{Edge} object. Use - C{add_edges([(source, target)])} if you don't need the L{Edge} - object and want to avoid the overhead of creating it. - """ - eid = self.ecount() - self.add_edges([(source, target)]) - edge = self.es[eid] - for key, value in kwds.items(): - edge[key] = value - return edge - - def add_edges(self, es, attributes=None): - """Adds some edges to the graph. - - @param es: the list of edges to be added. Every edge is represented - with a tuple containing the vertex IDs or names of the two - endpoints. Vertices are enumerated from zero. - @param attributes: dict of sequences, all of length equal to the - number of edges to be added, containing the attributes of the new - edges. - """ - eid = self.ecount() - res = GraphBase.add_edges(self, es) - n = self.ecount() - eid - if (attributes is not None) and (n > 0): - for key, val in list(attributes.items()): - self.es[eid:][key] = val - return res - - def add_vertex(self, name=None, **kwds): - """Adds a single vertex to the graph. Keyword arguments will be assigned - as vertex attributes. Note that C{name} as a keyword argument is treated - specially; if a graph has C{name} as a vertex attribute, it allows one - to refer to vertices by their names in most places where igraph expects - a vertex ID. - - @return: the newly added vertex as a L{Vertex} object. Use - C{add_vertices(1)} if you don't need the L{Vertex} object and want - to avoid the overhead of creating t. - """ - vid = self.vcount() - self.add_vertices(1) - vertex = self.vs[vid] - for key, value in kwds.items(): - vertex[key] = value - if name is not None: - vertex["name"] = name - return vertex - - def add_vertices(self, n, attributes=None): - """Adds some vertices to the graph. - - Note that if C{n} is a sequence of strings, indicating the names of the - new vertices, and attributes has a key C{name}, the two conflict. In - that case the attribute will be applied. - - @param n: the number of vertices to be added, or the name of a single - vertex to be added, or a sequence of strings, each corresponding to the - name of a vertex to be added. Names will be assigned to the C{name} - vertex attribute. - @param attributes: dict of sequences, all of length equal to the - number of vertices to be added, containing the attributes of the new - vertices. If n is a string (so a single vertex is added), then the - values of this dict are the attributes themselves, but if n=1 then - they have to be lists of length 1. - """ - if isinstance(n, str): - # Adding a single vertex with a name - m = self.vcount() - result = GraphBase.add_vertices(self, 1) - self.vs[m]["name"] = n - if attributes is not None: - for key, val in list(attributes.items()): - self.vs[m][key] = val - elif hasattr(n, "__iter__"): - m = self.vcount() - if not hasattr(n, "__len__"): - names = list(n) - else: - names = n - result = GraphBase.add_vertices(self, len(names)) - if len(names) > 0: - self.vs[m:]["name"] = names - if attributes is not None: - for key, val in list(attributes.items()): - self.vs[m:][key] = val - else: - result = GraphBase.add_vertices(self, n) - if (attributes is not None) and (n > 0): - m = self.vcount() - n - for key, val in list(attributes.items()): - self.vs[m:][key] = val - return result - def as_directed(self, *args, **kwds): """Returns a directed copy of this graph. Arguments are passed on to L{to_directed()} that is invoked on the copy. @@ -532,36 +432,27 @@ def as_undirected(self, *args, **kwds): copy.to_undirected(*args, **kwds) return copy - def delete_edges(self, *args, **kwds): - """Deletes some edges from the graph. - - The set of edges to be deleted is determined by the positional and - keyword arguments. If the function is called without any arguments, - all edges are deleted. If any keyword argument is present, or the - first positional argument is callable, an edge sequence is derived by - calling L{EdgeSeq.select} with the same positional and keyword - arguments. Edges in the derived edge sequence will be removed. - Otherwise the first positional argument is considered as follows: - - - C{None} - deletes all edges (deprecated since 0.8.3) - - a single integer - deletes the edge with the given ID - - a list of integers - deletes the edges denoted by the given IDs - - a list of 2-tuples - deletes the edges denoted by the given - source-target vertex pairs. When multiple edges are present - between a given source-target vertex pair, only one is removed. - - @deprecated: C{delete_edges(None)} has been replaced by - C{delete_edges()} - with no arguments - since igraph 0.8.3. + def clear(self): + """Clears the graph, deleting all vertices, edges, and attributes. + + @see: L{delete_vertices} and L{delete_edges}. """ - if len(args) == 0 and len(kwds) == 0: - return GraphBase.delete_edges(self) + self.delete_vertices() + for attr in self.attributes(): + del self[attr] - if len(kwds) > 0 or (callable(args[0]) and not isinstance(args[0], EdgeSeq)): - edge_seq = self.es(*args, **kwds) - else: - edge_seq = args[0] - return GraphBase.delete_edges(self, edge_seq) + # Basic operations + add_edge = _add_edge + + add_edges = _add_edges + add_vertex = _add_vertex + + add_vertices = _add_vertices + + delete_edges = _delete_edges + + # Structural properties def indegree(self, *args, **kwds): """Returns the in-degrees in a list. @@ -654,15 +545,6 @@ def biconnected_components(self, return_articulation_points=False): blocks = biconnected_components - def clear(self): - """Clears the graph, deleting all vertices, edges, and attributes. - - @see: L{delete_vertices} and L{delete_edges}. - """ - self.delete_vertices() - for attr in self.attributes(): - del self[attr] - def cohesive_blocks(self): """Calculates the cohesive block structure of the graph. @@ -2222,4 +2104,9 @@ def write(graph, filename, *args, **kwds): _community_leiden, _graph_plot, _operator_method_registry, + _add_edge, + _add_edges, + _add_vertex, + _add_vertices, + _delete_edges, ) diff --git a/src/igraph/basic/__init__.py b/src/igraph/basic/__init__.py new file mode 100644 index 000000000..7b7df7187 --- /dev/null +++ b/src/igraph/basic/__init__.py @@ -0,0 +1,144 @@ +from igraph._igraph import GraphBase +from igraph.seq import EdgeSeq + + +def _add_edge(graph, source, target, **kwds): + """Adds a single edge to the graph. + + Keyword arguments (except the source and target arguments) will be + assigned to the edge as attributes. + + The performance cost of adding a single edge or several edges + to a graph is similar. Thus, when adding several edges, a single + C{add_edges()} call is more efficient than multiple C{add_edge()} calls. + + @param source: the source vertex of the edge or its name. + @param target: the target vertex of the edge or its name. + + @return: the newly added edge as an L{Edge} object. Use + C{add_edges([(source, target)])} if you don't need the L{Edge} + object and want to avoid the overhead of creating it. + """ + eid = graph.ecount() + graph.add_edges([(source, target)]) + edge = graph.es[eid] + for key, value in kwds.items(): + edge[key] = value + return edge + + +def _add_edges(graph, es, attributes=None): + """Adds some edges to the graph. + + @param es: the list of edges to be added. Every edge is represented + with a tuple containing the vertex IDs or names of the two + endpoints. Vertices are enumerated from zero. + @param attributes: dict of sequences, all of length equal to the + number of edges to be added, containing the attributes of the new + edges. + """ + eid = graph.ecount() + res = GraphBase.add_edges(graph, es) + n = graph.ecount() - eid + if (attributes is not None) and (n > 0): + for key, val in list(attributes.items()): + graph.es[eid:][key] = val + return res + + +def _add_vertex(graph, name=None, **kwds): + """Adds a single vertex to the graph. Keyword arguments will be assigned + as vertex attributes. Note that C{name} as a keyword argument is treated + specially; if a graph has C{name} as a vertex attribute, it allows one + to refer to vertices by their names in most places where igraph expects + a vertex ID. + + @return: the newly added vertex as a L{Vertex} object. Use + C{add_vertices(1)} if you don't need the L{Vertex} object and want + to avoid the overhead of creating t. + """ + vid = graph.vcount() + graph.add_vertices(1) + vertex = graph.vs[vid] + for key, value in kwds.items(): + vertex[key] = value + if name is not None: + vertex["name"] = name + return vertex + + +def _add_vertices(graph, n, attributes=None): + """Adds some vertices to the graph. + + Note that if C{n} is a sequence of strings, indicating the names of the + new vertices, and attributes has a key C{name}, the two conflict. In + that case the attribute will be applied. + + @param n: the number of vertices to be added, or the name of a single + vertex to be added, or a sequence of strings, each corresponding to the + name of a vertex to be added. Names will be assigned to the C{name} + vertex attribute. + @param attributes: dict of sequences, all of length equal to the + number of vertices to be added, containing the attributes of the new + vertices. If n is a string (so a single vertex is added), then the + values of this dict are the attributes themselves, but if n=1 then + they have to be lists of length 1. + """ + if isinstance(n, str): + # Adding a single vertex with a name + m = graph.vcount() + result = GraphBase.add_vertices(graph, 1) + graph.vs[m]["name"] = n + if attributes is not None: + for key, val in list(attributes.items()): + graph.vs[m][key] = val + elif hasattr(n, "__iter__"): + m = graph.vcount() + if not hasattr(n, "__len__"): + names = list(n) + else: + names = n + result = GraphBase.add_vertices(graph, len(names)) + if len(names) > 0: + graph.vs[m:]["name"] = names + if attributes is not None: + for key, val in list(attributes.items()): + graph.vs[m:][key] = val + else: + result = GraphBase.add_vertices(graph, n) + if (attributes is not None) and (n > 0): + m = graph.vcount() - n + for key, val in list(attributes.items()): + graph.vs[m:][key] = val + return result + + +def _delete_edges(graph, *args, **kwds): + """Deletes some edges from the graph. + + The set of edges to be deleted is determined by the positional and + keyword arguments. If the function is called without any arguments, + all edges are deleted. If any keyword argument is present, or the + first positional argument is callable, an edge sequence is derived by + calling L{EdgeSeq.select} with the same positional and keyword + arguments. Edges in the derived edge sequence will be removed. + Otherwise the first positional argument is considered as follows: + + - C{None} - deletes all edges (deprecated since 0.8.3) + - a single integer - deletes the edge with the given ID + - a list of integers - deletes the edges denoted by the given IDs + - a list of 2-tuples - deletes the edges denoted by the given + source-target vertex pairs. When multiple edges are present + between a given source-target vertex pair, only one is removed. + + @deprecated: C{delete_edges(None)} has been replaced by + C{delete_edges()} - with no arguments - since igraph 0.8.3. + """ + if len(args) == 0 and len(kwds) == 0: + return GraphBase.delete_edges(graph) + + if len(kwds) > 0 or (callable(args[0]) and not isinstance(args[0], EdgeSeq)): + edge_seq = graph.es(*args, **kwds) + else: + edge_seq = args[0] + return GraphBase.delete_edges(graph, edge_seq) From 6f6accd2a93ce561cae26072da6f8572ee4ff164 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 2 Oct 2021 20:30:19 +1000 Subject: [PATCH 0682/1892] More operators --- src/igraph/__init__.py | 41 ++++------------------------ src/igraph/operators/__init__.py | 6 ++++ src/igraph/operators/methods.py | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index d35c93320..15ace8548 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1640,6 +1640,12 @@ def _as_parameter_(self): __or__ = _operator_method_registry['__or__'] + disjoint_union = _operator_method_registry['disjoint_union'] + + union = _operator_method_registry['union'] + + intersection = _operator_method_registry['intersection'] + def __bool__(self): """Returns True if the graph has at least one vertex, False otherwise.""" return self.vcount() > 0 @@ -1736,41 +1742,6 @@ def summary(self, verbosity=0, width=None, *args, **kwds): """ return str(GraphSummary(self, verbosity, width, *args, **kwds)) - def disjoint_union(self, other): - """Creates the disjoint union of two (or more) graphs. - - @param other: graph or list of graphs to be united with the current one. - @return: the disjoint union graph - """ - if isinstance(other, GraphBase): - other = [other] - return disjoint_union([self] + other) - - def union(self, other, byname="auto"): - """Creates the union of two (or more) graphs. - - @param other: graph or list of graphs to be united with the current one. - @param byname: whether to use vertex names instead of ids. See - L{igraph.union} for details. - @return: the union graph - """ - if isinstance(other, GraphBase): - other = [other] - return union([self] + other, byname=byname) - - def intersection(self, other, byname="auto"): - """Creates the intersection of two (or more) graphs. - - @param other: graph or list of graphs to be intersected with - the current one. - @param byname: whether to use vertex names instead of ids. See - L{igraph.intersection} for details. - @return: the intersection graph - """ - if isinstance(other, GraphBase): - other = [other] - return intersection([self] + other, byname=byname) - _format_mapping = { "ncol": ("Read_Ncol", "write_ncol"), "lgl": ("Read_Lgl", "write_lgl"), diff --git a/src/igraph/operators/__init__.py b/src/igraph/operators/__init__.py index cb3407a4c..0b6e86291 100644 --- a/src/igraph/operators/__init__.py +++ b/src/igraph/operators/__init__.py @@ -22,6 +22,9 @@ __sub__, __mul__, __or__, + _disjoint_union, + _union, + _intersection, ) operator_method_registry = { @@ -32,4 +35,7 @@ '__sub__': __sub__, '__mul__': __mul__, '__or__': __or__, + 'disjoint_union': _disjoint_union, + 'union': _union, + 'intersection': _intersection, } diff --git a/src/igraph/operators/methods.py b/src/igraph/operators/methods.py index 9024111f2..1822103d9 100644 --- a/src/igraph/operators/methods.py +++ b/src/igraph/operators/methods.py @@ -1,8 +1,14 @@ from igraph._igraph import ( + GraphBase, Vertex, Edge, ) from igraph.seq import VertexSeq, EdgeSeq +from igraph.operators.functions import ( + disjoint_union, + union, + intersection, +) __all__ = ( @@ -13,9 +19,50 @@ "__sub__", "__mul__", "__or__", + "_disjoint_union", + "_union", + "_intersection", ) +def _disjoint_union(graph, other): + """Creates the disjoint union of two (or more) graphs. + + @param other: graph or list of graphs to be united with the current one. + @return: the disjoint union graph + """ + if isinstance(other, GraphBase): + other = [other] + return disjoint_union([graph] + other) + + +def _union(graph, other, byname="auto"): + """Creates the union of two (or more) graphs. + + @param other: graph or list of graphs to be united with the current one. + @param byname: whether to use vertex names instead of ids. See + L{igraph.union} for details. + @return: the union graph + """ + if isinstance(other, GraphBase): + other = [other] + return union([graph] + other, byname=byname) + + +def _intersection(graph, other, byname="auto"): + """Creates the intersection of two (or more) graphs. + + @param other: graph or list of graphs to be intersected with + the current one. + @param byname: whether to use vertex names instead of ids. See + L{igraph.intersection} for details. + @return: the intersection graph + """ + if isinstance(other, GraphBase): + other = [other] + return intersection([graph] + other, byname=byname) + + def __iadd__(graph, other): """In-place addition (disjoint union). From 72074a17676fe06a3d9c2c1c6fe50a11b04b3a3f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 5 Oct 2021 07:37:50 +1100 Subject: [PATCH 0683/1892] More layout functions/methods --- src/igraph/__init__.py | 290 +++------------------------------------- src/igraph/layout.py | 292 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+), 274 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 15ace8548..6885653a7 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -190,7 +190,14 @@ _construct_random_bipartite_graph, ) from igraph.io.images import _write_graph_to_svg -from igraph.layout import Layout +from igraph.layout import ( + Layout, + _layout, + _layout_auto, + _layout_sugiyama, + _layout_method_wrapper, + _3d_version_for, +) from igraph.matching import Matching from igraph.operators import ( disjoint_union, @@ -1123,238 +1130,11 @@ def get_automorphisms_vf2( community_leiden = _community_leiden - def layout(self, layout=None, *args, **kwds): - """Returns the layout of the graph according to a layout algorithm. - - Parameters and keyword arguments not specified here are passed to the - layout algorithm directly. See the documentation of the layout - algorithms for the explanation of these parameters. - - Registered layout names understood by this method are: - - - C{auto}, C{automatic}: automatic layout - (see L{layout_auto}) - - - C{bipartite}: bipartite layout (see L{layout_bipartite}) - - - C{circle}, C{circular}: circular layout - (see L{layout_circle}) - - - C{dh}, C{davidson_harel}: Davidson-Harel layout (see - L{layout_davidson_harel}) - - - C{drl}: DrL layout for large graphs (see L{layout_drl}) - - - C{drl_3d}: 3D DrL layout for large graphs - (see L{layout_drl}) - - - C{fr}, C{fruchterman_reingold}: Fruchterman-Reingold layout - (see L{layout_fruchterman_reingold}). - - - C{fr_3d}, C{fr3d}, C{fruchterman_reingold_3d}: 3D Fruchterman- - Reingold layout (see L{layout_fruchterman_reingold}). - - - C{grid}: regular grid layout in 2D (see L{layout_grid}) - - - C{grid_3d}: regular grid layout in 3D (see L{layout_grid_3d}) - - - C{graphopt}: the graphopt algorithm (see L{layout_graphopt}) - - - C{kk}, C{kamada_kawai}: Kamada-Kawai layout - (see L{layout_kamada_kawai}) + layout = _layout - - C{kk_3d}, C{kk3d}, C{kamada_kawai_3d}: 3D Kamada-Kawai layout - (see L{layout_kamada_kawai}) + layout_auto = _layout_auto - - C{lgl}, C{large}, C{large_graph}: Large Graph Layout - (see L{layout_lgl}) - - - C{mds}: multidimensional scaling layout (see L{layout_mds}) - - - C{random}: random layout (see L{layout_random}) - - - C{random_3d}: random 3D layout (see L{layout_random}) - - - C{rt}, C{tree}, C{reingold_tilford}: Reingold-Tilford tree - layout (see L{layout_reingold_tilford}) - - - C{rt_circular}, C{reingold_tilford_circular}: circular - Reingold-Tilford tree layout - (see L{layout_reingold_tilford_circular}) - - - C{sphere}, C{spherical}, C{circle_3d}, C{circular_3d}: spherical - layout (see L{layout_circle}) - - - C{star}: star layout (see L{layout_star}) - - - C{sugiyama}: Sugiyama layout (see L{layout_sugiyama}) - - @param layout: the layout to use. This can be one of the registered - layout names or a callable which returns either a L{Layout} object or - a list of lists containing the coordinates. If C{None}, uses the - value of the C{plotting.layout} configuration key. - @return: a L{Layout} object. - """ - if layout is None: - layout = config["plotting.layout"] - if hasattr(layout, "__call__"): - method = layout - else: - layout = layout.lower() - if layout[-3:] == "_3d": - kwds["dim"] = 3 - layout = layout[:-3] - elif layout[-2:] == "3d": - kwds["dim"] = 3 - layout = layout[:-2] - method = getattr(self.__class__, self._layout_mapping[layout]) - if not hasattr(method, "__call__"): - raise ValueError("layout method must be callable") - layout = method(self, *args, **kwds) - if not isinstance(layout, Layout): - layout = Layout(layout) - return layout - - def layout_auto(self, *args, **kwds): - """Chooses and runs a suitable layout function based on simple - topological properties of the graph. - - This function tries to choose an appropriate layout function for - the graph using the following rules: - - 1. If the graph has an attribute called C{layout}, it will be - used. It may either be a L{Layout} instance, a list of - coordinate pairs, the name of a layout function, or a - callable function which generates the layout when called - with the graph as a parameter. - - 2. Otherwise, if the graph has vertex attributes called C{x} - and C{y}, these will be used as coordinates in the layout. - When a 3D layout is requested (by setting C{dim} to 3), - a vertex attribute named C{z} will also be needed. - - 3. Otherwise, if the graph is connected and has at most 100 - vertices, the Kamada-Kawai layout will be used (see - L{layout_kamada_kawai()}). - - 4. Otherwise, if the graph has at most 1000 vertices, the - Fruchterman-Reingold layout will be used (see - L{layout_fruchterman_reingold()}). - - 5. If everything else above failed, the DrL layout algorithm - will be used (see L{layout_drl()}). - - All the arguments of this function except C{dim} are passed on - to the chosen layout function (in case we have to call some layout - function). - - @keyword dim: specifies whether we would like to obtain a 2D or a - 3D layout. - @return: a L{Layout} object. - """ - if "layout" in self.attributes(): - layout = self["layout"] - if isinstance(layout, Layout): - # Layouts are used intact - return layout - if isinstance(layout, (list, tuple)): - # Lists/tuples are converted to layouts - return Layout(layout) - if hasattr(layout, "__call__"): - # Callables are called - return Layout(layout(*args, **kwds)) - # Try Graph.layout() - return self.layout(layout, *args, **kwds) - - dim = kwds.get("dim", 2) - vattrs = self.vertex_attributes() - if "x" in vattrs and "y" in vattrs: - if dim == 3 and "z" in vattrs: - return Layout(list(zip(self.vs["x"], self.vs["y"], self.vs["z"]))) - else: - return Layout(list(zip(self.vs["x"], self.vs["y"]))) - - if self.vcount() <= 100 and self.is_connected(): - algo = "kk" - elif self.vcount() <= 1000: - algo = "fr" - else: - algo = "drl" - return self.layout(algo, *args, **kwds) - - def layout_sugiyama( - self, - layers=None, - weights=None, - hgap=1, - vgap=1, - maxiter=100, - return_extended_graph=False, - ): - """Places the vertices using a layered Sugiyama layout. - - This is a layered layout that is most suitable for directed acyclic graphs, - although it works on undirected or cyclic graphs as well. - - Each vertex is assigned to a layer and each layer is placed on a horizontal - line. Vertices within the same layer are then permuted using the barycenter - heuristic that tries to minimize edge crossings. - - Dummy vertices will be added on edges that span more than one layer. The - returned layout therefore contains more rows than the number of nodes in - the original graph; the extra rows correspond to the dummy vertices. - - @param layers: a vector specifying a non-negative integer layer index for - each vertex, or the name of a numeric vertex attribute that contains - the layer indices. If C{None}, a layering will be determined - automatically. For undirected graphs, a spanning tree will be extracted - and vertices will be assigned to layers using a breadth first search from - the node with the largest degree. For directed graphs, cycles are broken - by reversing the direction of edges in an approximate feedback arc set - using the heuristic of Eades, Lin and Smyth, and then using longest path - layering to place the vertices in layers. - @param weights: edge weights to be used. Can be a sequence or iterable or - even an edge attribute name. - @param hgap: minimum horizontal gap between vertices in the same layer. - @param vgap: vertical gap between layers. The layer index will be - multiplied by I{vgap} to obtain the Y coordinate. - @param maxiter: maximum number of iterations to take in the crossing - reduction step. Increase this if you feel that you are getting too many - edge crossings. - @param return_extended_graph: specifies that the extended graph with the - added dummy vertices should also be returned. When this is C{True}, the - result will be a tuple containing the layout and the extended graph. The - first |V| nodes of the extended graph will correspond to the nodes of the - original graph, the remaining ones are dummy nodes. Plotting the extended - graph with the returned layout and hidden dummy nodes will produce a layout - that is similar to the original graph, but with the added edge bends. - The extended graph also contains an edge attribute called C{_original_eid} - which specifies the ID of the edge in the original graph from which the - edge of the extended graph was created. - @return: the calculated layout, which may (and usually will) have more rows - than the number of vertices; the remaining rows correspond to the dummy - nodes introduced in the layering step. When C{return_extended_graph} is - C{True}, it will also contain the extended graph. - - @newfield ref: Reference - @ref: K Sugiyama, S Tagawa, M Toda: Methods for visual understanding of - hierarchical system structures. IEEE Systems, Man and Cybernetics\ - 11(2):109-125, 1981. - @ref: P Eades, X Lin and WF Smyth: A fast effective heuristic for the - feedback arc set problem. Information Processing Letters 47:319-323, 1993. - """ - if not return_extended_graph: - return Layout( - GraphBase._layout_sugiyama( - self, layers, weights, hgap, vgap, maxiter, return_extended_graph - ) - ) - - layout, extd_graph, extd_to_orig_eids = GraphBase._layout_sugiyama( - self, layers, weights, hgap, vgap, maxiter, return_extended_graph - ) - extd_graph.es["_original_eid"] = extd_to_orig_eids - return Layout(layout), extd_graph + layout_sugiyama = _layout_sugiyama def maximum_bipartite_matching(self, types="type", weights=None, eps=None): """Finds a maximum matching in a bipartite graph. @@ -1914,26 +1694,6 @@ def _add_proxy_methods(): ############################################################## # Making sure that layout methods always return a Layout - -def _layout_method_wrapper(func): - """Wraps an existing layout method to ensure that it returns a Layout - instead of a list of lists. - - @param func: the method to wrap. Must be a method of the Graph object. - @return: a new method - """ - - def result(*args, **kwds): - layout = func(*args, **kwds) - if not isinstance(layout, Layout): - layout = Layout(layout) - return layout - - result.__name__ = func.__name__ - result.__doc__ = func.__doc__ - return result - - for name in dir(Graph): if not name.startswith("layout_"): continue @@ -1944,29 +1704,6 @@ def result(*args, **kwds): ############################################################## # Adding aliases for the 3D versions of the layout methods - -def _3d_version_for(func): - """Creates an alias for the 3D version of the given layout algoritm. - - This function is a decorator that creates a method which calls I{func} after - attaching C{dim=3} to the list of keyword arguments. - - @param func: must be a method of the Graph object. - @return: a new method - """ - - def result(*args, **kwds): - kwds["dim"] = 3 - return func(*args, **kwds) - - result.__name__ = "%s_3d" % func.__name__ - result.__doc__ = """Alias for L{%s()} with dim=3.\n\n@see: Graph.%s()""" % ( - func.__name__, - func.__name__, - ) - return result - - Graph.layout_fruchterman_reingold_3d = _3d_version_for( Graph.layout_fruchterman_reingold ) @@ -2080,4 +1817,9 @@ def write(graph, filename, *args, **kwds): _add_vertex, _add_vertices, _delete_edges, + _layout, + _layout_auto, + _layout_sugiyama, + _layout_method_wrapper, + _3d_version_for, ) diff --git a/src/igraph/layout.py b/src/igraph/layout.py index d6a45814e..3aaacdc49 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -9,10 +9,21 @@ from math import sin, cos, pi +from igraph._igraph import GraphBase from igraph.drawing.utils import BoundingBox from igraph.statistics import RunningMean +__all__ = ( + 'Layout', + '_layout', + '_layout_auto', + '_layout_sugiyama', + '_layout_method_wrapper', + '_3d_version_for', +) + + class Layout: """Represents the layout of a graph. @@ -424,3 +435,284 @@ def fit_into(self, bbox, keep_aspect_ratio=True): self.scale(*ratios) self.translate(*translations) + + +def _layout(self, layout=None, *args, **kwds): + """Returns the layout of the graph according to a layout algorithm. + + Parameters and keyword arguments not specified here are passed to the + layout algorithm directly. See the documentation of the layout + algorithms for the explanation of these parameters. + + Registered layout names understood by this method are: + + - C{auto}, C{automatic}: automatic layout + (see L{layout_auto}) + + - C{bipartite}: bipartite layout (see L{layout_bipartite}) + + - C{circle}, C{circular}: circular layout + (see L{layout_circle}) + + - C{dh}, C{davidson_harel}: Davidson-Harel layout (see + L{layout_davidson_harel}) + + - C{drl}: DrL layout for large graphs (see L{layout_drl}) + + - C{drl_3d}: 3D DrL layout for large graphs + (see L{layout_drl}) + + - C{fr}, C{fruchterman_reingold}: Fruchterman-Reingold layout + (see L{layout_fruchterman_reingold}). + + - C{fr_3d}, C{fr3d}, C{fruchterman_reingold_3d}: 3D Fruchterman- + Reingold layout (see L{layout_fruchterman_reingold}). + + - C{grid}: regular grid layout in 2D (see L{layout_grid}) + + - C{grid_3d}: regular grid layout in 3D (see L{layout_grid_3d}) + + - C{graphopt}: the graphopt algorithm (see L{layout_graphopt}) + + - C{kk}, C{kamada_kawai}: Kamada-Kawai layout + (see L{layout_kamada_kawai}) + + - C{kk_3d}, C{kk3d}, C{kamada_kawai_3d}: 3D Kamada-Kawai layout + (see L{layout_kamada_kawai}) + + - C{lgl}, C{large}, C{large_graph}: Large Graph Layout + (see L{layout_lgl}) + + - C{mds}: multidimensional scaling layout (see L{layout_mds}) + + - C{random}: random layout (see L{layout_random}) + + - C{random_3d}: random 3D layout (see L{layout_random}) + + - C{rt}, C{tree}, C{reingold_tilford}: Reingold-Tilford tree + layout (see L{layout_reingold_tilford}) + + - C{rt_circular}, C{reingold_tilford_circular}: circular + Reingold-Tilford tree layout + (see L{layout_reingold_tilford_circular}) + + - C{sphere}, C{spherical}, C{circle_3d}, C{circular_3d}: spherical + layout (see L{layout_circle}) + + - C{star}: star layout (see L{layout_star}) + + - C{sugiyama}: Sugiyama layout (see L{layout_sugiyama}) + + @param layout: the layout to use. This can be one of the registered + layout names or a callable which returns either a L{Layout} object or + a list of lists containing the coordinates. If C{None}, uses the + value of the C{plotting.layout} configuration key. + @return: a L{Layout} object. + """ + # Deferred import to avoid cycles + from igraph import config + + if layout is None: + layout = config["plotting.layout"] + if hasattr(layout, "__call__"): + method = layout + else: + layout = layout.lower() + if layout[-3:] == "_3d": + kwds["dim"] = 3 + layout = layout[:-3] + elif layout[-2:] == "3d": + kwds["dim"] = 3 + layout = layout[:-2] + method = getattr(self.__class__, self._layout_mapping[layout]) + if not hasattr(method, "__call__"): + raise ValueError("layout method must be callable") + layout = method(self, *args, **kwds) + if not isinstance(layout, Layout): + layout = Layout(layout) + return layout + + +def _layout_auto(self, *args, **kwds): + """Chooses and runs a suitable layout function based on simple + topological properties of the graph. + + This function tries to choose an appropriate layout function for + the graph using the following rules: + + 1. If the graph has an attribute called C{layout}, it will be + used. It may either be a L{Layout} instance, a list of + coordinate pairs, the name of a layout function, or a + callable function which generates the layout when called + with the graph as a parameter. + + 2. Otherwise, if the graph has vertex attributes called C{x} + and C{y}, these will be used as coordinates in the layout. + When a 3D layout is requested (by setting C{dim} to 3), + a vertex attribute named C{z} will also be needed. + + 3. Otherwise, if the graph is connected and has at most 100 + vertices, the Kamada-Kawai layout will be used (see + L{layout_kamada_kawai()}). + + 4. Otherwise, if the graph has at most 1000 vertices, the + Fruchterman-Reingold layout will be used (see + L{layout_fruchterman_reingold()}). + + 5. If everything else above failed, the DrL layout algorithm + will be used (see L{layout_drl()}). + + All the arguments of this function except C{dim} are passed on + to the chosen layout function (in case we have to call some layout + function). + + @keyword dim: specifies whether we would like to obtain a 2D or a + 3D layout. + @return: a L{Layout} object. + """ + if "layout" in self.attributes(): + layout = self["layout"] + if isinstance(layout, Layout): + # Layouts are used intact + return layout + if isinstance(layout, (list, tuple)): + # Lists/tuples are converted to layouts + return Layout(layout) + if hasattr(layout, "__call__"): + # Callables are called + return Layout(layout(*args, **kwds)) + # Try Graph.layout() + return self.layout(layout, *args, **kwds) + + dim = kwds.get("dim", 2) + vattrs = self.vertex_attributes() + if "x" in vattrs and "y" in vattrs: + if dim == 3 and "z" in vattrs: + return Layout(list(zip(self.vs["x"], self.vs["y"], self.vs["z"]))) + else: + return Layout(list(zip(self.vs["x"], self.vs["y"]))) + + if self.vcount() <= 100 and self.is_connected(): + algo = "kk" + elif self.vcount() <= 1000: + algo = "fr" + else: + algo = "drl" + return self.layout(algo, *args, **kwds) + + +def _layout_sugiyama( + self, + layers=None, + weights=None, + hgap=1, + vgap=1, + maxiter=100, + return_extended_graph=False, +): + """Places the vertices using a layered Sugiyama layout. + + This is a layered layout that is most suitable for directed acyclic graphs, + although it works on undirected or cyclic graphs as well. + + Each vertex is assigned to a layer and each layer is placed on a horizontal + line. Vertices within the same layer are then permuted using the barycenter + heuristic that tries to minimize edge crossings. + + Dummy vertices will be added on edges that span more than one layer. The + returned layout therefore contains more rows than the number of nodes in + the original graph; the extra rows correspond to the dummy vertices. + + @param layers: a vector specifying a non-negative integer layer index for + each vertex, or the name of a numeric vertex attribute that contains + the layer indices. If C{None}, a layering will be determined + automatically. For undirected graphs, a spanning tree will be extracted + and vertices will be assigned to layers using a breadth first search from + the node with the largest degree. For directed graphs, cycles are broken + by reversing the direction of edges in an approximate feedback arc set + using the heuristic of Eades, Lin and Smyth, and then using longest path + layering to place the vertices in layers. + @param weights: edge weights to be used. Can be a sequence or iterable or + even an edge attribute name. + @param hgap: minimum horizontal gap between vertices in the same layer. + @param vgap: vertical gap between layers. The layer index will be + multiplied by I{vgap} to obtain the Y coordinate. + @param maxiter: maximum number of iterations to take in the crossing + reduction step. Increase this if you feel that you are getting too many + edge crossings. + @param return_extended_graph: specifies that the extended graph with the + added dummy vertices should also be returned. When this is C{True}, the + result will be a tuple containing the layout and the extended graph. The + first |V| nodes of the extended graph will correspond to the nodes of the + original graph, the remaining ones are dummy nodes. Plotting the extended + graph with the returned layout and hidden dummy nodes will produce a layout + that is similar to the original graph, but with the added edge bends. + The extended graph also contains an edge attribute called C{_original_eid} + which specifies the ID of the edge in the original graph from which the + edge of the extended graph was created. + @return: the calculated layout, which may (and usually will) have more rows + than the number of vertices; the remaining rows correspond to the dummy + nodes introduced in the layering step. When C{return_extended_graph} is + C{True}, it will also contain the extended graph. + + @newfield ref: Reference + @ref: K Sugiyama, S Tagawa, M Toda: Methods for visual understanding of + hierarchical system structures. IEEE Systems, Man and Cybernetics\ + 11(2):109-125, 1981. + @ref: P Eades, X Lin and WF Smyth: A fast effective heuristic for the + feedback arc set problem. Information Processing Letters 47:319-323, 1993. + """ + if not return_extended_graph: + return Layout( + GraphBase._layout_sugiyama( + self, layers, weights, hgap, vgap, maxiter, return_extended_graph + ) + ) + + layout, extd_graph, extd_to_orig_eids = GraphBase._layout_sugiyama( + self, layers, weights, hgap, vgap, maxiter, return_extended_graph + ) + extd_graph.es["_original_eid"] = extd_to_orig_eids + return Layout(layout), extd_graph + + +def _layout_method_wrapper(func): + """Wraps an existing layout method to ensure that it returns a Layout + instead of a list of lists. + + @param func: the method to wrap. Must be a method of the Graph object. + @return: a new method + """ + + def result(*args, **kwds): + layout = func(*args, **kwds) + if not isinstance(layout, Layout): + layout = Layout(layout) + return layout + + result.__name__ = func.__name__ + result.__doc__ = func.__doc__ + return result + + +def _3d_version_for(func): + """Creates an alias for the 3D version of the given layout algoritm. + + This function is a decorator that creates a method which calls I{func} after + attaching C{dim=3} to the list of keyword arguments. + + @param func: must be a method of the Graph object. + @return: a new method + """ + + def result(*args, **kwds): + kwds["dim"] = 3 + return func(*args, **kwds) + + result.__name__ = "%s_3d" % func.__name__ + result.__doc__ = """Alias for L{%s()} with dim=3.\n\n@see: Graph.%s()""" % ( + func.__name__, + func.__name__, + ) + return result + From 9d2a947e5152836862ee81c6ff18ff534c20aaf9 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 5 Oct 2021 07:45:16 +1100 Subject: [PATCH 0684/1892] Automorphisms and fix in layout --- src/igraph/__init__.py | 51 ++++++------------------------------ src/igraph/automorphisms.py | 52 +++++++++++++++++++++++++++++++++++++ src/igraph/layout.py | 32 +++++++++++------------ 3 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 src/igraph/automorphisms.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 6885653a7..e7f65ec19 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -107,6 +107,10 @@ compare_communities, split_join_distance, ) +from igraph.automorphisms import ( + _count_automorphisms_vf2, + _get_automorphisms_vf2, +) from igraph.cut import Cut, Flow from igraph.configuration import Configuration, init as init_configuration from igraph.drawing import ( @@ -1060,50 +1064,9 @@ def triad_census(self, *args, **kwds): return TriadCensus(GraphBase.triad_census(self, *args, **kwds)) # Automorphisms - def count_automorphisms_vf2( - self, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None - ): - """Returns the number of automorphisms of the graph. - - This function simply calls C{count_isomorphisms_vf2} with the graph - itself. See C{count_isomorphisms_vf2} for an explanation of the - parameters. - - @return: the number of automorphisms of the graph - @see: Graph.count_isomorphisms_vf2 - """ - return self.count_isomorphisms_vf2( - self, - color1=color, - color2=color, - edge_color1=edge_color, - edge_color2=edge_color, - node_compat_fn=node_compat_fn, - edge_compat_fn=edge_compat_fn, - ) + count_automorphisms_vf2 = _count_automorphisms_vf2 - def get_automorphisms_vf2( - self, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None - ): - """Returns all the automorphisms of the graph - - This function simply calls C{get_isomorphisms_vf2} with the graph - itself. See C{get_isomorphisms_vf2} for an explanation of the - parameters. - - @return: a list of lists, each item containing a possible mapping - of the graph vertices to itself according to the automorphism - @see: Graph.get_isomorphisms_vf2 - """ - return self.get_isomorphisms_vf2( - self, - color1=color, - color2=color, - edge_color1=edge_color, - edge_color2=edge_color, - node_compat_fn=node_compat_fn, - edge_compat_fn=edge_compat_fn, - ) + get_automorphisms_vf2 = _get_automorphisms_vf2 # Various clustering algorithms -- mostly wrappers around GraphBase community_fastgreedy = _community_fastgreedy @@ -1822,4 +1785,6 @@ def write(graph, filename, *args, **kwds): _layout_sugiyama, _layout_method_wrapper, _3d_version_for, + _count_automorphisms_vf2, + _get_automorphisms_vf2, ) diff --git a/src/igraph/automorphisms.py b/src/igraph/automorphisms.py new file mode 100644 index 000000000..84178e9cf --- /dev/null +++ b/src/igraph/automorphisms.py @@ -0,0 +1,52 @@ +__all__ = ( + '_count_automorphisms_vf2', + '_get_automorphisms_vf2', +) + + +def _count_automorphisms_vf2( + graph, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None +): + """Returns the number of automorphisms of the graph. + + This function simply calls C{count_isomorphisms_vf2} with the graph + itgraph. See C{count_isomorphisms_vf2} for an explanation of the + parameters. + + @return: the number of automorphisms of the graph + @see: Graph.count_isomorphisms_vf2 + """ + return graph.count_isomorphisms_vf2( + graph, + color1=color, + color2=color, + edge_color1=edge_color, + edge_color2=edge_color, + node_compat_fn=node_compat_fn, + edge_compat_fn=edge_compat_fn, + ) + + +def _get_automorphisms_vf2( + graph, color=None, edge_color=None, node_compat_fn=None, edge_compat_fn=None +): + """Returns all the automorphisms of the graph + + This function simply calls C{get_isomorphisms_vf2} with the graph + itgraph. See C{get_isomorphisms_vf2} for an explanation of the + parameters. + + @return: a list of lists, each item containing a possible mapping + of the graph vertices to itgraph according to the automorphism + @see: Graph.get_isomorphisms_vf2 + """ + return graph.get_isomorphisms_vf2( + graph, + color1=color, + color2=color, + edge_color1=edge_color, + edge_color2=edge_color, + node_compat_fn=node_compat_fn, + edge_compat_fn=edge_compat_fn, + ) + diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 3aaacdc49..7ef002f1b 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -437,7 +437,7 @@ def fit_into(self, bbox, keep_aspect_ratio=True): self.translate(*translations) -def _layout(self, layout=None, *args, **kwds): +def _layout(graph, layout=None, *args, **kwds): """Returns the layout of the graph according to a layout algorithm. Parameters and keyword arguments not specified here are passed to the @@ -524,16 +524,16 @@ def _layout(self, layout=None, *args, **kwds): elif layout[-2:] == "3d": kwds["dim"] = 3 layout = layout[:-2] - method = getattr(self.__class__, self._layout_mapping[layout]) + method = getattr(graph.__class__, graph._layout_mapping[layout]) if not hasattr(method, "__call__"): raise ValueError("layout method must be callable") - layout = method(self, *args, **kwds) + layout = method(graph, *args, **kwds) if not isinstance(layout, Layout): layout = Layout(layout) return layout -def _layout_auto(self, *args, **kwds): +def _layout_auto(graph, *args, **kwds): """Chooses and runs a suitable layout function based on simple topological properties of the graph. @@ -570,8 +570,8 @@ def _layout_auto(self, *args, **kwds): 3D layout. @return: a L{Layout} object. """ - if "layout" in self.attributes(): - layout = self["layout"] + if "layout" in graph.attributes(): + layout = graph["layout"] if isinstance(layout, Layout): # Layouts are used intact return layout @@ -582,27 +582,27 @@ def _layout_auto(self, *args, **kwds): # Callables are called return Layout(layout(*args, **kwds)) # Try Graph.layout() - return self.layout(layout, *args, **kwds) + return graph.layout(layout, *args, **kwds) dim = kwds.get("dim", 2) - vattrs = self.vertex_attributes() + vattrs = graph.vertex_attributes() if "x" in vattrs and "y" in vattrs: if dim == 3 and "z" in vattrs: - return Layout(list(zip(self.vs["x"], self.vs["y"], self.vs["z"]))) + return Layout(list(zip(graph.vs["x"], graph.vs["y"], graph.vs["z"]))) else: - return Layout(list(zip(self.vs["x"], self.vs["y"]))) + return Layout(list(zip(graph.vs["x"], graph.vs["y"]))) - if self.vcount() <= 100 and self.is_connected(): + if graph.vcount() <= 100 and graph.is_connected(): algo = "kk" - elif self.vcount() <= 1000: + elif graph.vcount() <= 1000: algo = "fr" else: algo = "drl" - return self.layout(algo, *args, **kwds) + return graph.layout(algo, *args, **kwds) def _layout_sugiyama( - self, + graph, layers=None, weights=None, hgap=1, @@ -665,12 +665,12 @@ def _layout_sugiyama( if not return_extended_graph: return Layout( GraphBase._layout_sugiyama( - self, layers, weights, hgap, vgap, maxiter, return_extended_graph + graph, layers, weights, hgap, vgap, maxiter, return_extended_graph ) ) layout, extd_graph, extd_to_orig_eids = GraphBase._layout_sugiyama( - self, layers, weights, hgap, vgap, maxiter, return_extended_graph + graph, layers, weights, hgap, vgap, maxiter, return_extended_graph ) extd_graph.es["_original_eid"] = extd_to_orig_eids return Layout(layout), extd_graph From a37947217405997aa7863a599dfce73b80cd0b1b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 5 Oct 2021 09:13:58 +1100 Subject: [PATCH 0685/1892] More modules, code blocks in __init__.py, reordering --- src/igraph/__init__.py | 1354 ++++++++---------------------- src/igraph/adjacency.py | 175 ++++ src/igraph/basic/__init__.py | 27 + src/igraph/bipartite.py | 125 +++ src/igraph/clustering.py | 61 ++ src/igraph/community/__init__.py | 34 + src/igraph/components.py | 0 src/igraph/cut.py | 142 ++++ src/igraph/io/__init__.py | 25 + src/igraph/layout.py | 34 + src/igraph/seq/__init__.py | 104 +++ src/igraph/seq/edgeseq.py | 431 ---------- src/igraph/structural.py | 95 +++ 13 files changed, 1162 insertions(+), 1445 deletions(-) create mode 100644 src/igraph/adjacency.py create mode 100644 src/igraph/bipartite.py create mode 100644 src/igraph/components.py delete mode 100644 src/igraph/seq/edgeseq.py create mode 100644 src/igraph/structural.py diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index e7f65ec19..a8c9fc59e 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -75,12 +75,31 @@ set_status_handler, __igraph_version__, ) +from igraph.adjacency import ( + _get_adjacency, + _get_adjacency_sparse, + _get_adjlist, + _get_incidence, + _get_inclist, +) +from igraph.automorphisms import ( + _count_automorphisms_vf2, + _get_automorphisms_vf2, +) from igraph.basic import ( _add_edge, _add_edges, _add_vertex, _add_vertices, _delete_edges, + _clear, + _as_directed, + _as_undirected, +) +from igraph.bipartite import ( + _maximum_bipartite_matching, + _bipartite_projection, + _bipartite_projection_size, ) from igraph.community import ( _community_fastgreedy, @@ -95,6 +114,7 @@ _community_walktrap, _k_core, _community_leiden, + _modularity, ) from igraph.clustering import ( Clustering, @@ -106,12 +126,20 @@ CohesiveBlocks, compare_communities, split_join_distance, + _biconnected_components, + _cohesive_blocks, + _clusters, ) -from igraph.automorphisms import ( - _count_automorphisms_vf2, - _get_automorphisms_vf2, +from igraph.cut import ( + Cut, + Flow, + _all_st_cuts, + _all_st_mincuts, + _gomory_hu_tree, + _maxflow, + _mincut, + _st_mincut, ) -from igraph.cut import Cut, Flow from igraph.configuration import Configuration, init as init_configuration from igraph.drawing import ( BoundingBox, @@ -147,6 +175,7 @@ from igraph.drawing.utils import autocurve from igraph.datatypes import Matrix, DyadCensus, TriadCensus, UniqueIdGenerator from igraph.formula import construct_graph_from_formula +from igraph.io import _format_mapping from igraph.io.files import ( _construct_graph_from_graphmlz_file, _construct_graph_from_dimacs_file, @@ -201,6 +230,7 @@ _layout_sugiyama, _layout_method_wrapper, _3d_version_for, + _layout_mapping, ) from igraph.matching import Matching from igraph.operators import ( @@ -209,7 +239,7 @@ intersection, operator_method_registry as _operator_method_registry, ) -from igraph.seq import EdgeSeq, VertexSeq +from igraph.seq import EdgeSeq, VertexSeq, _add_proxy_methods from igraph.statistics import ( FittedPowerLaw, Histogram, @@ -220,6 +250,12 @@ quantile, power_law_fit, ) +from igraph.structural import ( + _indegree, + _outdegree, + _degree_distribution, + _pagerank, +) from igraph.summary import GraphSummary, summary from igraph.utils import ( dbl_epsilon, @@ -427,307 +463,238 @@ def __init__(self, *args, **kwds): key = str(key) self.es[key] = value - def as_directed(self, *args, **kwds): - """Returns a directed copy of this graph. Arguments are passed on - to L{to_directed()} that is invoked on the copy. - """ - copy = self.copy() - copy.to_directed(*args, **kwds) - return copy - - def as_undirected(self, *args, **kwds): - """Returns an undirected copy of this graph. Arguments are passed on - to L{to_undirected()} that is invoked on the copy. - """ - copy = self.copy() - copy.to_undirected(*args, **kwds) - return copy + ############################################# + # Auxiliary I/O functions + # Graph libraries + from_networkx = classmethod(_construct_graph_from_networkx) + to_networkx = _export_graph_to_networkx - def clear(self): - """Clears the graph, deleting all vertices, edges, and attributes. + from_graph_tool = classmethod(_construct_graph_from_graph_tool) + to_graph_tool = _export_graph_to_graph_tool - @see: L{delete_vertices} and L{delete_edges}. - """ - self.delete_vertices() - for attr in self.attributes(): - del self[attr] + # Files + Read_DIMACS = classmethod(_construct_graph_from_dimacs_file) + write_dimacs = _write_graph_to_dimacs_file - # Basic operations - add_edge = _add_edge + Read_GraphMLz = classmethod(_construct_graph_from_graphmlz_file) + write_graphmlz = _write_graph_to_graphmlz_file - add_edges = _add_edges + Read_Pickle = classmethod(_construct_graph_from_pickle_file) + write_pickle = _write_graph_to_pickle_file - add_vertex = _add_vertex + Read_Picklez = classmethod(_construct_graph_from_picklez_file) + write_picklez = _write_graph_to_picklez_file - add_vertices = _add_vertices + Read_Adjacency = classmethod(_construct_graph_from_adjacency_file) + write_adjacency = _write_graph_to_adjacency_file - delete_edges = _delete_edges + Read = classmethod(_construct_graph_from_file) + Load = Read + write = _write_graph_to_file + save = write - # Structural properties - def indegree(self, *args, **kwds): - """Returns the in-degrees in a list. + # Various objects + # list of dict representation of graphs + DictList = classmethod(_construct_graph_from_dict_list) + to_dict_list = _export_graph_to_dict_list - See L{degree} for possible arguments. - """ - kwds["mode"] = IN - return self.degree(*args, **kwds) + # tuple-like representation of graphs + TupleList = classmethod(_construct_graph_from_tuple_list) + to_tuple_list = _export_graph_to_tuple_list - def outdegree(self, *args, **kwds): - """Returns the out-degrees in a list. + # dict of sequence representation of graphs + ListDict = classmethod(_construct_graph_from_list_dict) + to_list_dict = _export_graph_to_list_dict - See L{degree} for possible arguments. - """ - kwds["mode"] = OUT - return self.degree(*args, **kwds) + # dict of dicts representation of graphs + DictDict = classmethod(_construct_graph_from_dict_dict) + to_dict_dict = _export_graph_to_dict_dict - def all_st_cuts(self, source, target): - """\ - Returns all the cuts between the source and target vertices in a - directed graph. + # adjacency matrix + Adjacency = classmethod(_construct_graph_from_adjacency) + Weighted_Adjacency = classmethod(_construct_graph_from_weighted_adjacency) - This function lists all edge-cuts between a source and a target vertex. - Every cut is listed exactly once. + # pandas dataframe(s) + DataFrame = classmethod(_construct_graph_from_dataframe) + get_vertex_dataframe = _export_vertex_dataframe + get_edge_dataframe = _export_edge_dataframe - @param source: the source vertex ID - @param target: the target vertex ID - @return: a list of L{Cut} objects. + # Bipartite graphs + Bipartite = classmethod(_construct_bipartite_graph) + Incidence = classmethod(_construct_incidence_bipartite_graph) + Full_Bipartite = classmethod(_construct_full_bipartite_graph) + Random_Bipartite = classmethod(_construct_random_bipartite_graph) - @newfield ref: Reference - @ref: JS Provan and DR Shier: A paradigm for listing (s,t)-cuts in - graphs. Algorithmica 15, 351--372, 1996. - """ - return [ - Cut(self, cut=cut, partition=part) - for cut, part in zip(*GraphBase.all_st_cuts(self, source, target)) - ] + # Other constructors + GRG = classmethod(_construct_random_geometric_graph) - def all_st_mincuts(self, source, target, capacity=None): - """\ - Returns all the mincuts between the source and target vertices in a - directed graph. + # Graph formulae + Formula = classmethod(construct_graph_from_formula) - This function lists all minimum edge-cuts between a source and a target - vertex. + ############################################# + # Summary/string representation + def __str__(self): + """Returns a string representation of the graph. - @param source: the source vertex ID - @param target: the target vertex ID - @param capacity: the edge capacities (weights). If C{None}, all - edges have equal weight. May also be an attribute name. - @return: a list of L{Cut} objects. + Behind the scenes, this method constructs a L{GraphSummary} + instance and invokes its C{__str__} method with a verbosity of 1 + and attribute printing turned off. - @newfield ref: Reference - @ref: JS Provan and DR Shier: A paradigm for listing (s,t)-cuts in - graphs. Algorithmica 15, 351--372, 1996. - """ - value, cuts, parts = GraphBase.all_st_mincuts(self, source, target, capacity) - return [ - Cut(self, value, cut=cut, partition=part) for cut, part in zip(cuts, parts) - ] - - def biconnected_components(self, return_articulation_points=False): - """\ - Calculates the biconnected components of the graph. - - @param return_articulation_points: whether to return the articulation - points as well - @return: a L{VertexCover} object describing the biconnected components, - and optionally the list of articulation points as well + See the documentation of L{GraphSummary} for more details about the + output. """ - if return_articulation_points: - trees, aps = GraphBase.biconnected_components(self, True) - else: - trees = GraphBase.biconnected_components(self, False) - - clusters = [] - if trees: - edgelist = self.get_edgelist() - for tree in trees: - cluster = set() - for edge_id in tree: - cluster.update(edgelist[edge_id]) - clusters.append(sorted(cluster)) + params = dict( + verbosity=1, + width=78, + print_graph_attributes=False, + print_vertex_attributes=False, + print_edge_attributes=False, + ) + return self.summary(**params) - clustering = VertexCover(self, clusters) + def summary(self, verbosity=0, width=None, *args, **kwds): + """Returns the summary of the graph. - if return_articulation_points: - return clustering, aps - else: - return clustering + The output of this method is similar to the output of the + C{__str__} method. If I{verbosity} is zero, only the header line + is returned (see C{__str__} for more details), otherwise the + header line and the edge list is printed. - blocks = biconnected_components + Behind the scenes, this method constructs a L{GraphSummary} + object and invokes its C{__str__} method. - def cohesive_blocks(self): - """Calculates the cohesive block structure of the graph. - - Cohesive blocking is a method of determining hierarchical subsets of graph - vertices based on their structural cohesion (i.e. vertex connectivity). - For a given graph G, a subset of its vertices S is said to be maximally - k-cohesive if there is no superset of S with vertex connectivity greater - than or equal to k. Cohesive blocking is a process through which, given a - k-cohesive set of vertices, maximally l-cohesive subsets are recursively - identified with l > k. Thus a hierarchy of vertex subsets is obtained in - the end, with the entire graph G at its root. - - @return: an instance of L{CohesiveBlocks}. See the documentation of - L{CohesiveBlocks} for more information. - @see: L{CohesiveBlocks} + @param verbosity: if zero, only the header line is returned + (see C{__str__} for more details), otherwise the header line + and the full edge list is printed. + @param width: the number of characters to use in one line. + If C{None}, no limit will be enforced on the line lengths. + @return: the summary of the graph. """ - return CohesiveBlocks(self, *GraphBase.cohesive_blocks(self)) - - def clusters(self, mode="strong"): - """Calculates the (strong or weak) clusters (connected components) for - a given graph. - - @param mode: must be either C{"strong"} or C{"weak"}, depending on the - clusters being sought. Optional, defaults to C{"strong"}. - @return: a L{VertexClustering} object""" - return VertexClustering(self, GraphBase.clusters(self, mode)) + return str(GraphSummary(self, verbosity, width, *args, **kwds)) - components = clusters + ############################################# + # Commonly used attributes + def is_named(self): + """Returns whether the graph is named. - def degree_distribution(self, bin_width=1, *args, **kwds): - """Calculates the degree distribution of the graph. + A graph is named if and only if it has a C{"name"} vertex attribute. + """ + return "name" in self.vertex_attributes() - Unknown keyword arguments are directly passed to L{degree()}. + def is_weighted(self): + """Returns whether the graph is weighted. - @param bin_width: the bin width of the histogram - @return: a histogram representing the degree distribution of the - graph. + A graph is weighted if and only if it has a C{"weight"} edge attribute. """ - result = Histogram(bin_width, self.degree(*args, **kwds)) - return result - - def dyad_census(self, *args, **kwds): - """Calculates the dyad census of the graph. + return "weight" in self.edge_attributes() - Dyad census means classifying each pair of vertices of a directed - graph into three categories: mutual (there is an edge from I{a} to - I{b} and also from I{b} to I{a}), asymmetric (there is an edge - from I{a} to I{b} or from I{b} to I{a} but not the other way round) - and null (there is no connection between I{a} and I{b}). + ############################################# + # Vertex and edge sequence + @property + def vs(self): + """The vertex sequence of the graph""" + return VertexSeq(self) - @return: a L{DyadCensus} object. - @newfield ref: Reference - @ref: Holland, P.W. and Leinhardt, S. (1970). A Method for Detecting - Structure in Sociometric Data. American Journal of Sociology, 70, - 492-513. - """ - return DyadCensus(GraphBase.dyad_census(self, *args, **kwds)) + @property + def es(self): + """The edge sequence of the graph""" + return EdgeSeq(self) - def get_adjacency( - self, type=GET_ADJACENCY_BOTH, attribute=None, default=0, eids=False - ): - """Returns the adjacency matrix of a graph. - - @param type: either C{GET_ADJACENCY_LOWER} (uses the lower - triangle of the matrix) or C{GET_ADJACENCY_UPPER} - (uses the upper triangle) or C{GET_ADJACENCY_BOTH} - (uses both parts). Ignored for directed graphs. - @param attribute: if C{None}, returns the ordinary adjacency - matrix. When the name of a valid edge attribute is given - here, the matrix returned will contain the default value - at the places where there is no edge or the value of the - given attribute where there is an edge. Multiple edges are - not supported, the value written in the matrix in this case - will be unpredictable. This parameter is ignored if - I{eids} is C{True} - @param default: the default value written to the cells in the - case of adjacency matrices with attributes. - @param eids: specifies whether the edge IDs should be returned - in the adjacency matrix. Since zero is a valid edge ID, the - cells in the matrix that correspond to unconnected vertex - pairs will contain -1 instead of 0 if I{eids} is C{True}. - If I{eids} is C{False}, the number of edges will be returned - in the matrix for each vertex pair. - @return: the adjacency matrix as a L{Matrix}. - """ - if ( - type != GET_ADJACENCY_LOWER - and type != GET_ADJACENCY_UPPER - and type != GET_ADJACENCY_BOTH - ): - # Maybe it was called with the first argument as the attribute name - type, attribute = attribute, type - if type is None: - type = GET_ADJACENCY_BOTH - - if eids: - result = Matrix(GraphBase.get_adjacency(self, type, eids)) - result -= 1 - return result - - if attribute is None: - return Matrix(GraphBase.get_adjacency(self, type)) - - if attribute not in self.es.attribute_names(): - raise ValueError("Attribute does not exist") - - data = [[default] * self.vcount() for _ in range(self.vcount())] - - if self.is_directed(): - for edge in self.es: - data[edge.source][edge.target] = edge[attribute] - return Matrix(data) - - if type == GET_ADJACENCY_BOTH: - for edge in self.es: - source, target = edge.tuple - data[source][target] = edge[attribute] - data[target][source] = edge[attribute] - elif type == GET_ADJACENCY_UPPER: - for edge in self.es: - data[min(edge.tuple)][max(edge.tuple)] = edge[attribute] - else: - for edge in self.es: - data[max(edge.tuple)][min(edge.tuple)] = edge[attribute] + ############################################# + # Basic operations + add_edge = _add_edge + add_edges = _add_edges + add_vertex = _add_vertex + add_vertices = _add_vertices + delete_edges = _delete_edges + clear = _clear + as_directed = _as_directed + as_undirected = _as_undirected - return Matrix(data) + ################### + # Graph operators + __iadd__ = _operator_method_registry['__iadd__'] + __add__ = _operator_method_registry['__add__'] + __and__ = _operator_method_registry['__and__'] + __isub__ = _operator_method_registry['__isub__'] + __sub__ = _operator_method_registry['__sub__'] + __mul__ = _operator_method_registry['__mul__'] + __or__ = _operator_method_registry['__or__'] + disjoint_union = _operator_method_registry['disjoint_union'] + union = _operator_method_registry['union'] + intersection = _operator_method_registry['intersection'] - def get_adjacency_sparse(self, attribute=None): - """Returns the adjacency matrix of a graph as a SciPy CSR matrix. + ############################################# + # Adjacency/incidence + get_adjacency = _get_adjacency + get_adjacency_sparse = _get_adjacency_sparse + get_adjlist = _get_adjlist + get_incidence = _get_incidence + get_inclist = _get_inclist - @param attribute: if C{None}, returns the ordinary adjacency - matrix. When the name of a valid edge attribute is given - here, the matrix returned will contain the default value - at the places where there is no edge or the value of the - given attribute where there is an edge. - @return: the adjacency matrix as a C{scipy.sparse.csr_matrix}. - """ - try: - from scipy import sparse - except ImportError: - raise ImportError("You should install scipy in order to use this function") + ############################################# + # Structural properties + indegree = _indegree + outdegree = _outdegree + degree_distribution = _degree_distribution + pagerank = _pagerank - edges = self.get_edgelist() - if attribute is None: - weights = [1] * len(edges) - else: - if attribute not in self.es.attribute_names(): - raise ValueError("Attribute does not exist") + ############################################# + # Flow + all_st_cuts = _all_st_cuts + all_st_mincuts = _all_st_mincuts + gomory_hu_tree = _gomory_hu_tree + maxflow = _maxflow + mincut = _mincut + st_mincut = _st_mincut - weights = self.es[attribute] + ############################################# + # Connected components + biconnected_components = _biconnected_components + cohesive_blocks = _cohesive_blocks + clusters = _clusters + blocks = biconnected_components + components = clusters - N = self.vcount() - mtx = sparse.csr_matrix((weights, list(zip(*edges))), shape=(N, N)) + ############################################# + # Community detection/clustering + community_fastgreedy = _community_fastgreedy + community_infomap = _community_infomap + community_leading_eigenvector_naive = _community_leading_eigenvector_naive + community_leading_eigenvector = _community_leading_eigenvector + community_label_propagation = _community_label_propagation + community_multilevel = _community_multilevel + community_optimal_modularity = _community_optimal_modularity + community_edge_betweenness = _community_edge_betweenness + community_spinglass = _community_spinglass + community_walktrap = _community_walktrap + k_core = _k_core + community_leiden = _community_leiden + modularity = _modularity - if not self.is_directed(): - mtx = mtx + sparse.triu(mtx, 1).T + sparse.tril(mtx, -1).T - return mtx + ############################################# + # Layout + layout = _layout + layout_auto = _layout_auto + layout_sugiyama = _layout_sugiyama - def get_adjlist(self, mode="out"): - """Returns the adjacency list representation of the graph. + ############################################# + # Plotting + __plot__ = _graph_plot - The adjacency list representation is a list of lists. Each item of the - outer list belongs to a single vertex of the graph. The inner list - contains the neighbors of the given vertex. + ############################################# + # Bipartite + maximum_bipartite_matching = _maximum_bipartite_matching + bipartite_projection = _bipartite_projection + bipartite_projection_size = _bipartite_projection_size - @param mode: if C{\"out\"}, returns the successors of the vertex. If - C{\"in\"}, returns the predecessors of the vertex. If C{\"all"\"}, both - the predecessors and the successors will be returned. Ignored - for undirected graphs. - """ - return [self.neighbors(idx, mode) for idx in range(self.vcount())] + ############################################# + # Automorphisms + count_automorphisms_vf2 = _count_automorphisms_vf2 + get_automorphisms_vf2 = _get_automorphisms_vf2 + ########################### + # Paths/traversals def get_all_simple_paths(self, v, to=None, cutoff=-1, mode="out"): """Calculates all the simple paths from a given node to some other nodes (or all of them) in a graph. @@ -762,159 +729,6 @@ def get_all_simple_paths(self, v, to=None, cutoff=-1, mode="out"): prev = index + 1 return result - def get_inclist(self, mode="out"): - """Returns the incidence list representation of the graph. - - The incidence list representation is a list of lists. Each - item of the outer list belongs to a single vertex of the graph. - The inner list contains the IDs of the incident edges of the - given vertex. - - @param mode: if C{\"out\"}, returns the successors of the vertex. If - C{\"in\"}, returns the predecessors of the vertex. If C{\"all\"}, both - the predecessors and the successors will be returned. Ignored - for undirected graphs. - """ - return [self.incident(idx, mode) for idx in range(self.vcount())] - - def gomory_hu_tree(self, capacity=None, flow="flow"): - """Calculates the Gomory-Hu tree of an undirected graph with optional - edge capacities. - - The Gomory-Hu tree is a concise representation of the value of all the - maximum flows (or minimum cuts) in a graph. The vertices of the tree - correspond exactly to the vertices of the original graph in the same order. - Edges of the Gomory-Hu tree are annotated by flow values. The value of - the maximum flow (or minimum cut) between an arbitrary (u,v) vertex - pair in the original graph is then given by the minimum flow value (i.e. - edge annotation) along the shortest path between u and v in the - Gomory-Hu tree. - - @param capacity: the edge capacities (weights). If C{None}, all - edges have equal weight. May also be an attribute name. - @param flow: the name of the edge attribute in the returned graph - in which the flow values will be stored. - @return: the Gomory-Hu tree as a L{Graph} object. - """ - graph, flow_values = GraphBase.gomory_hu_tree(self, capacity) - graph.es[flow] = flow_values - return graph - - def is_named(self): - """Returns whether the graph is named. - - A graph is named if and only if it has a C{"name"} vertex attribute. - """ - return "name" in self.vertex_attributes() - - def is_weighted(self): - """Returns whether the graph is weighted. - - A graph is weighted if and only if it has a C{"weight"} edge attribute. - """ - return "weight" in self.edge_attributes() - - def maxflow(self, source, target, capacity=None): - """Returns a maximum flow between the given source and target vertices - in a graph. - - A maximum flow from I{source} to I{target} is an assignment of - non-negative real numbers to the edges of the graph, satisfying - two properties: - - 1. For each edge, the flow (i.e. the assigned number) is not - more than the capacity of the edge (see the I{capacity} - argument) - - 2. For every vertex except the source and the target, the - incoming flow is the same as the outgoing flow. - - The value of the flow is the incoming flow of the target or the - outgoing flow of the source (which are equal). The maximum flow - is the maximum possible such value. - - @param capacity: the edge capacities (weights). If C{None}, all - edges have equal weight. May also be an attribute name. - @return: a L{Flow} object describing the maximum flow - """ - return Flow(self, *GraphBase.maxflow(self, source, target, capacity)) - - def mincut(self, source=None, target=None, capacity=None): - """Calculates the minimum cut between the given source and target vertices - or within the whole graph. - - The minimum cut is the minimum set of edges that needs to be removed to - separate the source and the target (if they are given) or to disconnect the - graph (if neither the source nor the target are given). The minimum is - calculated using the weights (capacities) of the edges, so the cut with - the minimum total capacity is calculated. - - For undirected graphs and no source and target, the method uses the - Stoer-Wagner algorithm. For a given source and target, the method uses the - push-relabel algorithm; see the references below. - - @param source: the source vertex ID. If C{None}, the target must also be - C{None} and the calculation will be done for the entire graph (i.e. - all possible vertex pairs). - @param target: the target vertex ID. If C{None}, the source must also be - C{None} and the calculation will be done for the entire graph (i.e. - all possible vertex pairs). - @param capacity: the edge capacities (weights). If C{None}, all - edges have equal weight. May also be an attribute name. - @return: a L{Cut} object describing the minimum cut - """ - return Cut(self, *GraphBase.mincut(self, source, target, capacity)) - - def st_mincut(self, source, target, capacity=None): - """Calculates the minimum cut between the source and target vertices in a - graph. - - @param source: the source vertex ID - @param target: the target vertex ID - @param capacity: the capacity of the edges. It must be a list or a valid - attribute name or C{None}. In the latter case, every edge will have the - same capacity. - @return: the value of the minimum cut, the IDs of vertices in the - first and second partition, and the IDs of edges in the cut, - packed in a 4-tuple - """ - return Cut(self, *GraphBase.st_mincut(self, source, target, capacity)) - - def modularity(self, membership, weights=None): - """Calculates the modularity score of the graph with respect to a given - clustering. - - The modularity of a graph w.r.t. some division measures how good the - division is, or how separated are the different vertex types from each - other. It's defined as M{Q=1/(2m)*sum(Aij-ki*kj/(2m)delta(ci,cj),i,j)}. - M{m} is the number of edges, M{Aij} is the element of the M{A} - adjacency matrix in row M{i} and column M{j}, M{ki} is the degree of - node M{i}, M{kj} is the degree of node M{j}, and M{Ci} and C{cj} are - the types of the two vertices (M{i} and M{j}). M{delta(x,y)} is one iff - M{x=y}, 0 otherwise. - - If edge weights are given, the definition of modularity is modified as - follows: M{Aij} becomes the weight of the corresponding edge, M{ki} - is the total weight of edges adjacent to vertex M{i}, M{kj} is the - total weight of edges adjacent to vertex M{j} and M{m} is the total - edge weight in the graph. - - @param membership: a membership list or a L{VertexClustering} object - @param weights: optional edge weights or C{None} if all edges are - weighed equally. Attribute names are also allowed. - @return: the modularity score - - @newfield ref: Reference - @ref: MEJ Newman and M Girvan: Finding and evaluating community - structure in networks. Phys Rev E 69 026113, 2004. - """ - if isinstance(membership, VertexClustering): - if membership.graph != self: - raise ValueError("clustering object belongs to another graph") - return GraphBase.modularity(self, membership.membership, weights) - else: - return GraphBase.modularity(self, membership, weights) - def path_length_hist(self, directed=True): """Returns the path length histogram of the graph @@ -933,69 +747,55 @@ def path_length_hist(self, directed=True): hist.unconnected = int(unconn) return hist - def pagerank( - self, - vertices=None, - directed=True, - damping=0.85, - weights=None, - arpack_options=None, - implementation="prpack", - niter=1000, - eps=0.001, - ): - """Calculates the PageRank values of a graph. - - @param vertices: the indices of the vertices being queried. - C{None} means all of the vertices. - @param directed: whether to consider directed paths. - @param damping: the damping factor. M{1-damping} is the PageRank value - for nodes with no incoming links. It is also the probability of - resetting the random walk to a uniform distribution in each step. - @param weights: edge weights to be used. Can be a sequence or iterable - or even an edge attribute name. - @param arpack_options: an L{ARPACKOptions} object used to fine-tune - the ARPACK eigenvector calculation. If omitted, the module-level - variable called C{arpack_options} is used. This argument is - ignored if not the ARPACK implementation is used, see the - I{implementation} argument. - @param implementation: which implementation to use to solve the - PageRank eigenproblem. Possible values are: - - C{"prpack"}: use the PRPACK library. This is a new - implementation in igraph 0.7 - - C{"arpack"}: use the ARPACK library. This implementation - was used from version 0.5, until version 0.7. - - C{"power"}: use a simple power method. This is the - implementation that was used before igraph version 0.5. - @param niter: The number of iterations to use in the power method - implementation. It is ignored in the other implementations - @param eps: The power method implementation will consider the - calculation as complete if the difference of PageRank values between - iterations change less than this value for every node. It is - ignored by the other implementations. - @return: a list with the Google PageRank values of the specified - vertices.""" - if arpack_options is None: - arpack_options = default_arpack_options - return self.personalized_pagerank( - vertices, - directed, - damping, - None, - None, - weights, - arpack_options, - implementation, - niter, - eps, - ) - - def spanning_tree(self, weights=None, return_tree=True): - """Calculates a minimum spanning tree for a graph. + # DFS (C version will come soon) + def dfs(self, vid, mode=OUT): + """Conducts a depth first search (DFS) on the graph. - @param weights: a vector containing weights for every edge in - the graph. C{None} means that the graph is unweighted. - @param return_tree: whether to return the minimum spanning tree (when + @param vid: the root vertex ID + @param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}, ignored + for undirected graphs. + @return: a tuple with the following items: + - The vertex IDs visited (in order) + - The parent of every vertex in the DFS + """ + nv = self.vcount() + added = [False for v in range(nv)] + stack = [] + + # prepare output + vids = [] + parents = [] + + # ok start from vid + stack.append((vid, self.neighbors(vid, mode=mode))) + vids.append(vid) + parents.append(vid) + added[vid] = True + + # go down the rabbit hole + while stack: + vid, neighbors = stack[-1] + if neighbors: + # Get next neighbor to visit + neighbor = neighbors.pop() + if not added[neighbor]: + # Add hanging subtree neighbor + stack.append((neighbor, self.neighbors(neighbor, mode=mode))) + vids.append(neighbor) + parents.append(vid) + added[neighbor] = True + else: + # No neighbor found, end of subtree + stack.pop() + + return (vids, parents) + + def spanning_tree(self, weights=None, return_tree=True): + """Calculates a minimum spanning tree for a graph. + + @param weights: a vector containing weights for every edge in + the graph. C{None} means that the graph is unweighted. + @param return_tree: whether to return the minimum spanning tree (when C{return_tree} is C{True}) or to return the IDs of the edges in the minimum spanning tree instead (when C{return_tree} is C{False}). The default is C{True} for historical reasons as this argument was @@ -1013,6 +813,39 @@ def spanning_tree(self, weights=None, return_tree=True): return self.subgraph_edges(result, delete_vertices=False) return result + ########################### + # Dyad/triad census + def dyad_census(self, *args, **kwds): + """Calculates the dyad census of the graph. + + Dyad census means classifying each pair of vertices of a directed + graph into three categories: mutual (there is an edge from I{a} to + I{b} and also from I{b} to I{a}), asymmetric (there is an edge + from I{a} to I{b} or from I{b} to I{a} but not the other way round) + and null (there is no connection between I{a} and I{b}). + + @return: a L{DyadCensus} object. + @newfield ref: Reference + @ref: Holland, P.W. and Leinhardt, S. (1970). A Method for Detecting + Structure in Sociometric Data. American Journal of Sociology, 70, + 492-513. + """ + return DyadCensus(GraphBase.dyad_census(self, *args, **kwds)) + + def triad_census(self, *args, **kwds): + """Calculates the triad census of the graph. + + @return: a L{TriadCensus} object. + @newfield ref: Reference + @ref: Davis, J.A. and Leinhardt, S. (1972). The Structure of + Positive Interpersonal Relations in Small Groups. In: + J. Berger (Ed.), Sociological Theories in Progress, Volume 2, + 218-251. Boston: Houghton Mifflin. + """ + return TriadCensus(GraphBase.triad_census(self, *args, **kwds)) + + ########################### + # Other functions def transitivity_avglocal_undirected(self, mode="nan", weights=None): """Calculates the average of the vertex transitivities of the graph. @@ -1051,344 +884,13 @@ def transitivity_avglocal_undirected(self, mode="nan", weights=None): xs = self.transitivity_local_undirected(mode=mode, weights=weights) return sum(xs) / float(len(xs)) - def triad_census(self, *args, **kwds): - """Calculates the triad census of the graph. - - @return: a L{TriadCensus} object. - @newfield ref: Reference - @ref: Davis, J.A. and Leinhardt, S. (1972). The Structure of - Positive Interpersonal Relations in Small Groups. In: - J. Berger (Ed.), Sociological Theories in Progress, Volume 2, - 218-251. Boston: Houghton Mifflin. - """ - return TriadCensus(GraphBase.triad_census(self, *args, **kwds)) - - # Automorphisms - count_automorphisms_vf2 = _count_automorphisms_vf2 - - get_automorphisms_vf2 = _get_automorphisms_vf2 - - # Various clustering algorithms -- mostly wrappers around GraphBase - community_fastgreedy = _community_fastgreedy - - community_infomap = _community_infomap - - community_leading_eigenvector_naive = _community_leading_eigenvector_naive - - community_leading_eigenvector = _community_leading_eigenvector - - community_label_propagation = _community_label_propagation - - community_multilevel = _community_multilevel - - community_optimal_modularity = _community_optimal_modularity - - community_edge_betweenness = _community_edge_betweenness - - community_spinglass = _community_spinglass - - community_walktrap = _community_walktrap - - k_core = _k_core - - community_leiden = _community_leiden - - layout = _layout - - layout_auto = _layout_auto - - layout_sugiyama = _layout_sugiyama - - def maximum_bipartite_matching(self, types="type", weights=None, eps=None): - """Finds a maximum matching in a bipartite graph. - - A maximum matching is a set of edges such that each vertex is incident on - at most one matched edge and the number (or weight) of such edges in the - set is as large as possible. - - @param types: vertex types in a list or the name of a vertex attribute - holding vertex types. Types should be denoted by zeros and ones (or - C{False} and C{True}) for the two sides of the bipartite graph. - If omitted, it defaults to C{type}, which is the default vertex type - attribute for bipartite graphs. - @param weights: edge weights to be used. Can be a sequence or iterable or - even an edge attribute name. - @param eps: a small real number used in equality tests in the weighted - bipartite matching algorithm. Two real numbers are considered equal in - the algorithm if their difference is smaller than this value. This - is required to avoid the accumulation of numerical errors. If you - pass C{None} here, igraph will try to determine an appropriate value - automatically. - @return: an instance of L{Matching}.""" - if eps is None: - eps = -1 - - matches = GraphBase._maximum_bipartite_matching(self, types, weights, eps) - return Matching(self, matches, types=types) - - ############################################# - # Auxiliary I/O functions - - # Graph libraries - from_networkx = classmethod(_construct_graph_from_networkx) - to_networkx = _export_graph_to_networkx - - from_graph_tool = classmethod(_construct_graph_from_graph_tool) - to_graph_tool = _export_graph_to_graph_tool - - # Files - Read_DIMACS = classmethod(_construct_graph_from_dimacs_file) - write_dimacs = _write_graph_to_dimacs_file - - Read_GraphMLz = classmethod(_construct_graph_from_graphmlz_file) - write_graphmlz = _write_graph_to_graphmlz_file - - Read_Pickle = classmethod(_construct_graph_from_pickle_file) - write_pickle = _write_graph_to_pickle_file - - Read_Picklez = classmethod(_construct_graph_from_picklez_file) - write_picklez = _write_graph_to_picklez_file - - Read_Adjacency = classmethod(_construct_graph_from_adjacency_file) - write_adjacency = _write_graph_to_adjacency_file - - Read = classmethod(_construct_graph_from_file) - Load = Read - write = _write_graph_to_file - save = write - - # Various objects - # list of dict representation of graphs - DictList = classmethod(_construct_graph_from_dict_list) - to_dict_list = _export_graph_to_dict_list - - # tuple-like representation of graphs - TupleList = classmethod(_construct_graph_from_tuple_list) - to_tuple_list = _export_graph_to_tuple_list - - # dict of sequence representation of graphs - ListDict = classmethod(_construct_graph_from_list_dict) - to_list_dict = _export_graph_to_list_dict - - # dict of dicts representation of graphs - DictDict = classmethod(_construct_graph_from_dict_dict) - to_dict_dict = _export_graph_to_dict_dict - - # adjacency matrix - Adjacency = classmethod(_construct_graph_from_adjacency) - - Weighted_Adjacency = classmethod(_construct_graph_from_weighted_adjacency) - - # pandas dataframe(s) - DataFrame = classmethod(_construct_graph_from_dataframe) - - get_vertex_dataframe = _export_vertex_dataframe - - get_edge_dataframe = _export_edge_dataframe - - # Bipartite graphs - Bipartite = classmethod(_construct_bipartite_graph) - - Incidence = classmethod(_construct_incidence_bipartite_graph) - - Full_Bipartite = classmethod(_construct_full_bipartite_graph) - - Random_Bipartite = classmethod(_construct_random_bipartite_graph) - - # Other constructors - GRG = classmethod(_construct_random_geometric_graph) - - # Graph formulae - Formula = classmethod(construct_graph_from_formula) - - ########################### - # Vertex and edge sequence - - @property - def vs(self): - """The vertex sequence of the graph""" - return VertexSeq(self) - - @property - def es(self): - """The edge sequence of the graph""" - return EdgeSeq(self) - - def bipartite_projection( - self, types="type", multiplicity=True, probe1=-1, which="both" - ): - """Projects a bipartite graph into two one-mode graphs. Edge directions - are ignored while projecting. - - Examples: - - >>> g = Graph.Full_Bipartite(10, 5) - >>> g1, g2 = g.bipartite_projection() - >>> g1.isomorphic(Graph.Full(10)) - True - >>> g2.isomorphic(Graph.Full(5)) - True - - @param types: an igraph vector containing the vertex types, or an - attribute name. Anything that evalulates to C{False} corresponds to - vertices of the first kind, everything else to the second kind. - @param multiplicity: if C{True}, then igraph keeps the multiplicity of - the edges in the projection in an edge attribute called C{"weight"}. - E.g., if there is an A-C-B and an A-D-B triplet in the bipartite - graph and there is no other X (apart from X=B and X=D) for which an - A-X-B triplet would exist in the bipartite graph, the multiplicity - of the A-B edge in the projection will be 2. - @param probe1: this argument can be used to specify the order of the - projections in the resulting list. If given and non-negative, then - it is considered as a vertex ID; the projection containing the - vertex will be the first one in the result. - @param which: this argument can be used to specify which of the two - projections should be returned if only one of them is needed. Passing - 0 here means that only the first projection is returned, while 1 means - that only the second projection is returned. (Note that we use 0 and 1 - because Python indexing is zero-based). C{False} is equivalent to 0 and - C{True} is equivalent to 1. Any other value means that both projections - will be returned in a tuple. - @return: a tuple containing the two projected one-mode graphs if C{which} - is not 1 or 2, or the projected one-mode graph specified by the - C{which} argument if its value is 0, 1, C{False} or C{True}. - """ - superclass_meth = super().bipartite_projection - - if which is False: - which = 0 - elif which is True: - which = 1 - if which != 0 and which != 1: - which = -1 - - if multiplicity: - if which == 0: - g1, w1 = superclass_meth(types, True, probe1, which) - g2, w2 = None, None - elif which == 1: - g1, w1 = None, None - g2, w2 = superclass_meth(types, True, probe1, which) - else: - g1, g2, w1, w2 = superclass_meth(types, True, probe1, which) - - if g1 is not None: - g1.es["weight"] = w1 - if g2 is not None: - g2.es["weight"] = w2 - return g1, g2 - else: - return g1 - else: - g2.es["weight"] = w2 - return g2 - else: - return superclass_meth(types, False, probe1, which) - - def bipartite_projection_size(self, types="type", *args, **kwds): - """Calculates the number of vertices and edges in the bipartite - projections of this graph according to the specified vertex types. - This is useful if you have a bipartite graph and you want to estimate - the amount of memory you would need to calculate the projections - themselves. - - @param types: an igraph vector containing the vertex types, or an - attribute name. Anything that evalulates to C{False} corresponds to - vertices of the first kind, everything else to the second kind. - @return: a 4-tuple containing the number of vertices and edges in the - first projection, followed by the number of vertices and edges in the - second projection. - """ - return super().bipartite_projection_size(types, *args, **kwds) - - def get_incidence(self, types="type", *args, **kwds): - """Returns the incidence matrix of a bipartite graph. The incidence matrix - is an M{n} times M{m} matrix, where M{n} and M{m} are the number of - vertices in the two vertex classes. - - @param types: an igraph vector containing the vertex types, or an - attribute name. Anything that evalulates to C{False} corresponds to - vertices of the first kind, everything else to the second kind. - @return: the incidence matrix and two lists in a triplet. The first - list defines the mapping between row indices of the matrix and the - original vertex IDs. The second list is the same for the column - indices. - """ - return super().get_incidence(types, *args, **kwds) - - ########################### - # DFS (C version will come soon) - def dfs(self, vid, mode=OUT): - """Conducts a depth first search (DFS) on the graph. - - @param vid: the root vertex ID - @param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}, ignored - for undirected graphs. - @return: a tuple with the following items: - - The vertex IDs visited (in order) - - The parent of every vertex in the DFS - """ - nv = self.vcount() - added = [False for v in range(nv)] - stack = [] - - # prepare output - vids = [] - parents = [] - - # ok start from vid - stack.append((vid, self.neighbors(vid, mode=mode))) - vids.append(vid) - parents.append(vid) - added[vid] = True - - # go down the rabbit hole - while stack: - vid, neighbors = stack[-1] - if neighbors: - # Get next neighbor to visit - neighbor = neighbors.pop() - if not added[neighbor]: - # Add hanging subtree neighbor - stack.append((neighbor, self.neighbors(neighbor, mode=mode))) - vids.append(neighbor) - parents.append(vid) - added[neighbor] = True - else: - # No neighbor found, end of subtree - stack.pop() - - return (vids, parents) - ########################### # ctypes support - @property def _as_parameter_(self): return self._raw_pointer() - ################### - # Custom operators - __iadd__ = _operator_method_registry['__iadd__'] - - __add__ = _operator_method_registry['__add__'] - - __and__ = _operator_method_registry['__and__'] - - __isub__ = _operator_method_registry['__isub__'] - - __sub__ = _operator_method_registry['__sub__'] - - __mul__ = _operator_method_registry['__mul__'] - - __or__ = _operator_method_registry['__or__'] - - disjoint_union = _operator_method_registry['disjoint_union'] - - union = _operator_method_registry['union'] - - intersection = _operator_method_registry['intersection'] - + # Other type functions def __bool__(self): """Returns True if the graph has at least one vertex, False otherwise.""" return self.vcount() > 0 @@ -1444,219 +946,24 @@ def __reduce__(self): __iter__ = None # needed for PyPy __hash__ = None # needed for PyPy - __plot__ = _graph_plot - - def __str__(self): - """Returns a string representation of the graph. - - Behind the scenes, this method constructs a L{GraphSummary} - instance and invokes its C{__str__} method with a verbosity of 1 - and attribute printing turned off. - - See the documentation of L{GraphSummary} for more details about the - output. - """ - params = dict( - verbosity=1, - width=78, - print_graph_attributes=False, - print_vertex_attributes=False, - print_edge_attributes=False, - ) - return self.summary(**params) - def summary(self, verbosity=0, width=None, *args, **kwds): - """Returns the summary of the graph. - - The output of this method is similar to the output of the - C{__str__} method. If I{verbosity} is zero, only the header line - is returned (see C{__str__} for more details), otherwise the - header line and the edge list is printed. - - Behind the scenes, this method constructs a L{GraphSummary} - object and invokes its C{__str__} method. - - @param verbosity: if zero, only the header line is returned - (see C{__str__} for more details), otherwise the header line - and the full edge list is printed. - @param width: the number of characters to use in one line. - If C{None}, no limit will be enforced on the line lengths. - @return: the summary of the graph. - """ - return str(GraphSummary(self, verbosity, width, *args, **kwds)) - - _format_mapping = { - "ncol": ("Read_Ncol", "write_ncol"), - "lgl": ("Read_Lgl", "write_lgl"), - "graphdb": ("Read_GraphDB", None), - "graphmlz": ("Read_GraphMLz", "write_graphmlz"), - "graphml": ("Read_GraphML", "write_graphml"), - "gml": ("Read_GML", "write_gml"), - "dot": (None, "write_dot"), - "graphviz": (None, "write_dot"), - "net": ("Read_Pajek", "write_pajek"), - "pajek": ("Read_Pajek", "write_pajek"), - "dimacs": ("Read_DIMACS", "write_dimacs"), - "adjacency": ("Read_Adjacency", "write_adjacency"), - "adj": ("Read_Adjacency", "write_adjacency"), - "edgelist": ("Read_Edgelist", "write_edgelist"), - "edge": ("Read_Edgelist", "write_edgelist"), - "edges": ("Read_Edgelist", "write_edgelist"), - "pickle": ("Read_Pickle", "write_pickle"), - "picklez": ("Read_Picklez", "write_picklez"), - "svg": (None, "write_svg"), - "gw": (None, "write_leda"), - "leda": (None, "write_leda"), - "lgr": (None, "write_leda"), - "dl": ("Read_DL", None), - } - - _layout_mapping = { - "auto": "layout_auto", - "automatic": "layout_auto", - "bipartite": "layout_bipartite", - "circle": "layout_circle", - "circular": "layout_circle", - "davidson_harel": "layout_davidson_harel", - "dh": "layout_davidson_harel", - "drl": "layout_drl", - "fr": "layout_fruchterman_reingold", - "fruchterman_reingold": "layout_fruchterman_reingold", - "graphopt": "layout_graphopt", - "grid": "layout_grid", - "kk": "layout_kamada_kawai", - "kamada_kawai": "layout_kamada_kawai", - "lgl": "layout_lgl", - "large": "layout_lgl", - "large_graph": "layout_lgl", - "mds": "layout_mds", - "random": "layout_random", - "rt": "layout_reingold_tilford", - "tree": "layout_reingold_tilford", - "reingold_tilford": "layout_reingold_tilford", - "rt_circular": "layout_reingold_tilford_circular", - "reingold_tilford_circular": "layout_reingold_tilford_circular", - "sphere": "layout_sphere", - "spherical": "layout_sphere", - "star": "layout_star", - "sugiyama": "layout_sugiyama", - } - - # After adjusting something here, don't forget to update the docstring - # of Graph.layout if necessary! +############################################################## +# I/O format mapping +Graph._format_mapping = _format_mapping ############################################################## # Additional methods of VertexSeq and EdgeSeq that call Graph methods +_add_proxy_methods() -def _graphmethod(func=None, name=None): - """Auxiliary decorator - - This decorator allows some methods of L{VertexSeq} and L{EdgeSeq} to - call their respective counterparts in L{Graph} to avoid code duplication. - - @param func: the function being decorated. This function will be - called on the results of the original L{Graph} method. - If C{None}, defaults to the identity function. - @param name: the name of the corresponding method in L{Graph}. If - C{None}, it defaults to the name of the decorated function. - @return: the decorated function - """ - if name is None: - name = func.__name__ - method = getattr(Graph, name) - - if hasattr(func, "__call__"): - - def decorated(*args, **kwds): - self = args[0].graph - return func(args[0], method(self, *args, **kwds)) - - else: - - def decorated(*args, **kwds): - self = args[0].graph - return method(self, *args, **kwds) - - decorated.__name__ = name - decorated.__doc__ = """Proxy method to L{Graph.%(name)s()} - -This method calls the C{%(name)s()} method of the L{Graph} class -restricted to this sequence, and returns the result. - -@see: Graph.%(name)s() for details. -""" % { - "name": name - } - - return decorated - - -def _add_proxy_methods(): - - # Proxy methods for VertexSeq and EdgeSeq that forward their arguments to - # the corresponding Graph method are constructed here. Proxy methods for - # Vertex and Edge are added in the C source code. Make sure that you update - # the C source whenever you add a proxy method here if that makes sense for - # an individual vertex or edge - decorated_methods = {} - decorated_methods[VertexSeq] = [ - "degree", - "betweenness", - "bibcoupling", - "closeness", - "cocitation", - "constraint", - "diversity", - "eccentricity", - "get_shortest_paths", - "maxdegree", - "pagerank", - "personalized_pagerank", - "shortest_paths", - "similarity_dice", - "similarity_jaccard", - "subgraph", - "indegree", - "outdegree", - "isoclass", - "delete_vertices", - "is_separator", - "is_minimal_separator", - ] - decorated_methods[EdgeSeq] = [ - "count_multiple", - "delete_edges", - "is_loop", - "is_multiple", - "is_mutual", - "subgraph_edges", - ] - - rename_methods = {} - rename_methods[VertexSeq] = {"delete_vertices": "delete"} - rename_methods[EdgeSeq] = {"delete_edges": "delete", "subgraph_edges": "subgraph"} - - for cls, methods in decorated_methods.items(): - for method in methods: - new_method_name = rename_methods[cls].get(method, method) - setattr(cls, new_method_name, _graphmethod(None, method)) - - setattr( - EdgeSeq, - "edge_betweenness", - _graphmethod( - lambda self, result: [result[i] for i in self.indices], "edge_betweenness" - ), - ) +############################################################## +# Layout mapping +Graph._layout_mapping = _layout_mapping -_add_proxy_methods() - ############################################################## # Making sure that layout methods always return a Layout - for name in dir(Graph): if not name.startswith("layout_"): continue @@ -1664,9 +971,9 @@ def _add_proxy_methods(): continue setattr(Graph, name, _layout_method_wrapper(getattr(Graph, name))) + ############################################################## # Adding aliases for the 3D versions of the layout methods - Graph.layout_fruchterman_reingold_3d = _3d_version_for( Graph.layout_fruchterman_reingold ) @@ -1675,9 +982,9 @@ def _add_proxy_methods(): Graph.layout_grid_3d = _3d_version_for(Graph.layout_grid) Graph.layout_sphere = _3d_version_for(Graph.layout_circle) -############################################################## - +############################################################## +# Auxiliary global functions def get_include(): """Returns the folder that contains the C API headers of the Python interface of igraph.""" @@ -1730,8 +1037,12 @@ def write(graph, filename, *args, **kwds): save = write +############################################################## +# Configuration singleton instance config = init_configuration() + +############################################################## # Remove modular methods from namespace del ( construct_graph_from_formula, @@ -1741,6 +1052,7 @@ def write(graph, filename, *args, **kwds): _construct_graph_from_picklez_file, _construct_graph_from_adjacency_file, _construct_graph_from_file, + _format_mapping, _construct_graph_from_dict_list, _construct_graph_from_tuple_list, _construct_graph_from_list_dict, @@ -1773,6 +1085,7 @@ def write(graph, filename, *args, **kwds): _community_walktrap, _k_core, _community_leiden, + _modularity, _graph_plot, _operator_method_registry, _add_edge, @@ -1780,11 +1093,24 @@ def write(graph, filename, *args, **kwds): _add_vertex, _add_vertices, _delete_edges, + _as_directed, + _as_undirected, _layout, _layout_auto, _layout_sugiyama, _layout_method_wrapper, _3d_version_for, + _layout_mapping, _count_automorphisms_vf2, _get_automorphisms_vf2, + _get_adjacency, + _get_adjacency_sparse, + _get_adjlist, + _maximum_bipartite_matching, + _bipartite_projection, + _bipartite_projection_size, + _biconnected_components, + _cohesive_blocks, + _clusters, + _add_proxy_methods, ) diff --git a/src/igraph/adjacency.py b/src/igraph/adjacency.py new file mode 100644 index 000000000..65ae88606 --- /dev/null +++ b/src/igraph/adjacency.py @@ -0,0 +1,175 @@ +from igraph._igraph import ( + ADJ_DIRECTED, + ADJ_LOWER, + ADJ_MAX, + ADJ_MIN, + ADJ_PLUS, + ADJ_UNDIRECTED, + ADJ_UPPER, + GET_ADJACENCY_BOTH, + GET_ADJACENCY_LOWER, + GET_ADJACENCY_UPPER, + GraphBase, +) +from igraph.datatypes import Matrix + + +__all__ = ( + '_get_adjacency', + '_get_adjacency_sparse', + '_get_adjlist', + '_get_incidence', + '_get_inclist', +) + + +def _get_adjacency( + self, type=GET_ADJACENCY_BOTH, attribute=None, default=0, eids=False +): + """Returns the adjacency matrix of a graph. + + @param type: either C{GET_ADJACENCY_LOWER} (uses the lower + triangle of the matrix) or C{GET_ADJACENCY_UPPER} + (uses the upper triangle) or C{GET_ADJACENCY_BOTH} + (uses both parts). Ignored for directed graphs. + @param attribute: if C{None}, returns the ordinary adjacency + matrix. When the name of a valid edge attribute is given + here, the matrix returned will contain the default value + at the places where there is no edge or the value of the + given attribute where there is an edge. Multiple edges are + not supported, the value written in the matrix in this case + will be unpredictable. This parameter is ignored if + I{eids} is C{True} + @param default: the default value written to the cells in the + case of adjacency matrices with attributes. + @param eids: specifies whether the edge IDs should be returned + in the adjacency matrix. Since zero is a valid edge ID, the + cells in the matrix that correspond to unconnected vertex + pairs will contain -1 instead of 0 if I{eids} is C{True}. + If I{eids} is C{False}, the number of edges will be returned + in the matrix for each vertex pair. + @return: the adjacency matrix as a L{Matrix}. + """ + if ( + type != GET_ADJACENCY_LOWER + and type != GET_ADJACENCY_UPPER + and type != GET_ADJACENCY_BOTH + ): + # Maybe it was called with the first argument as the attribute name + type, attribute = attribute, type + if type is None: + type = GET_ADJACENCY_BOTH + + if eids: + result = Matrix(GraphBase.get_adjacency(self, type, eids)) + result -= 1 + return result + + if attribute is None: + return Matrix(GraphBase.get_adjacency(self, type)) + + if attribute not in self.es.attribute_names(): + raise ValueError("Attribute does not exist") + + data = [[default] * self.vcount() for _ in range(self.vcount())] + + if self.is_directed(): + for edge in self.es: + data[edge.source][edge.target] = edge[attribute] + return Matrix(data) + + if type == GET_ADJACENCY_BOTH: + for edge in self.es: + source, target = edge.tuple + data[source][target] = edge[attribute] + data[target][source] = edge[attribute] + elif type == GET_ADJACENCY_UPPER: + for edge in self.es: + data[min(edge.tuple)][max(edge.tuple)] = edge[attribute] + else: + for edge in self.es: + data[max(edge.tuple)][min(edge.tuple)] = edge[attribute] + + return Matrix(data) + + +def _get_adjacency_sparse(self, attribute=None): + """Returns the adjacency matrix of a graph as a SciPy CSR matrix. + + @param attribute: if C{None}, returns the ordinary adjacency + matrix. When the name of a valid edge attribute is given + here, the matrix returned will contain the default value + at the places where there is no edge or the value of the + given attribute where there is an edge. + @return: the adjacency matrix as a C{scipy.sparse.csr_matrix}. + """ + try: + from scipy import sparse + except ImportError: + raise ImportError("You should install scipy in order to use this function") + + edges = self.get_edgelist() + if attribute is None: + weights = [1] * len(edges) + else: + if attribute not in self.es.attribute_names(): + raise ValueError("Attribute does not exist") + + weights = self.es[attribute] + + N = self.vcount() + mtx = sparse.csr_matrix((weights, list(zip(*edges))), shape=(N, N)) + + if not self.is_directed(): + mtx = mtx + sparse.triu(mtx, 1).T + sparse.tril(mtx, -1).T + return mtx + + +def _get_adjlist(self, mode="out"): + """Returns the adjacency list representation of the graph. + + The adjacency list representation is a list of lists. Each item of the + outer list belongs to a single vertex of the graph. The inner list + contains the neighbors of the given vertex. + + @param mode: if C{\"out\"}, returns the successors of the vertex. If + C{\"in\"}, returns the predecessors of the vertex. If C{\"all"\"}, both + the predecessors and the successors will be returned. Ignored + for undirected graphs. + """ + return [self.neighbors(idx, mode) for idx in range(self.vcount())] + + +def _get_incidence(graph, types="type", *args, **kwds): + """Returns the incidence matrix of a bipartite graph. The incidence matrix + is an M{n} times M{m} matrix, where M{n} and M{m} are the number of + vertices in the two vertex classes. + + @param types: an igraph vector containing the vertex types, or an + attribute name. Anything that evalulates to C{False} corresponds to + vertices of the first kind, everything else to the second kind. + @return: the incidence matrix and two lists in a triplet. The first + list defines the mapping between row indices of the matrix and the + original vertex IDs. The second list is the same for the column + indices. + """ + # Deferred import to avoid cycles + from igraph import Graph + + return super(Graph, graph).get_incidence(types, *args, **kwds) + + +def _get_inclist(graph, mode="out"): + """Returns the incidence list representation of the graph. + + The incidence list representation is a list of lists. Each + item of the outer list belongs to a single vertex of the graph. + The inner list contains the IDs of the incident edges of the + given vertex. + + @param mode: if C{\"out\"}, returns the successors of the vertex. If + C{\"in\"}, returns the predecessors of the vertex. If C{\"all\"}, both + the predecessors and the successors will be returned. Ignored + for undirected graphs. + """ + return [graph.incident(idx, mode) for idx in range(graph.vcount())] diff --git a/src/igraph/basic/__init__.py b/src/igraph/basic/__init__.py index 7b7df7187..f02006a63 100644 --- a/src/igraph/basic/__init__.py +++ b/src/igraph/basic/__init__.py @@ -142,3 +142,30 @@ def _delete_edges(graph, *args, **kwds): else: edge_seq = args[0] return GraphBase.delete_edges(graph, edge_seq) + + +def _clear(graph): + """Clears the graph, deleting all vertices, edges, and attributes. + + @see: L{delete_vertices} and L{delete_edges}. + """ + graph.delete_vertices() + for attr in graph.attributes(): + del graph[attr] + + +def _as_directed(graph, *args, **kwds): + """Returns a directed copy of this graph. Arguments are passed on + to L{to_directed()} that is invoked on the copy. + """ + copy = graph.copy() + copy.to_directed(*args, **kwds) + return copy + +def _as_undirected(graph, *args, **kwds): + """Returns an undirected copy of this graph. Arguments are passed on + to L{to_undirected()} that is invoked on the copy. + """ + copy = graph.copy() + copy.to_undirected(*args, **kwds) + return copy diff --git a/src/igraph/bipartite.py b/src/igraph/bipartite.py new file mode 100644 index 000000000..881559401 --- /dev/null +++ b/src/igraph/bipartite.py @@ -0,0 +1,125 @@ +from igraph._igraph import GraphBase +from igraph.matching import Matching + + +def _maximum_bipartite_matching(graph, types="type", weights=None, eps=None): + """Finds a maximum matching in a bipartite graph. + + A maximum matching is a set of edges such that each vertex is incident on + at most one matched edge and the number (or weight) of such edges in the + set is as large as possible. + + @param types: vertex types in a list or the name of a vertex attribute + holding vertex types. Types should be denoted by zeros and ones (or + C{False} and C{True}) for the two sides of the bipartite graph. + If omitted, it defaults to C{type}, which is the default vertex type + attribute for bipartite graphs. + @param weights: edge weights to be used. Can be a sequence or iterable or + even an edge attribute name. + @param eps: a small real number used in equality tests in the weighted + bipartite matching algorithm. Two real numbers are considered equal in + the algorithm if their difference is smaller than this value. This + is required to avoid the accumulation of numerical errors. If you + pass C{None} here, igraph will try to determine an appropriate value + automatically. + @return: an instance of L{Matching}.""" + if eps is None: + eps = -1 + + matches = GraphBase._maximum_bipartite_matching(graph, types, weights, eps) + return Matching(graph, matches, types=types) + + +def _bipartite_projection( + graph, types="type", multiplicity=True, probe1=-1, which="both" +): + """Projects a bipartite graph into two one-mode graphs. Edge directions + are ignored while projecting. + + Examples: + + >>> g = Graph.Full_Bipartite(10, 5) + >>> g1, g2 = g.bipartite_projection() + >>> g1.isomorphic(Graph.Full(10)) + True + >>> g2.isomorphic(Graph.Full(5)) + True + + @param types: an igraph vector containing the vertex types, or an + attribute name. Anything that evalulates to C{False} corresponds to + vertices of the first kind, everything else to the second kind. + @param multiplicity: if C{True}, then igraph keeps the multiplicity of + the edges in the projection in an edge attribute called C{"weight"}. + E.g., if there is an A-C-B and an A-D-B triplet in the bipartite + graph and there is no other X (apart from X=B and X=D) for which an + A-X-B triplet would exist in the bipartite graph, the multiplicity + of the A-B edge in the projection will be 2. + @param probe1: this argument can be used to specify the order of the + projections in the resulting list. If given and non-negative, then + it is considered as a vertex ID; the projection containing the + vertex will be the first one in the result. + @param which: this argument can be used to specify which of the two + projections should be returned if only one of them is needed. Passing + 0 here means that only the first projection is returned, while 1 means + that only the second projection is returned. (Note that we use 0 and 1 + because Python indexing is zero-based). C{False} is equivalent to 0 and + C{True} is equivalent to 1. Any other value means that both projections + will be returned in a tuple. + @return: a tuple containing the two projected one-mode graphs if C{which} + is not 1 or 2, or the projected one-mode graph specified by the + C{which} argument if its value is 0, 1, C{False} or C{True}. + """ + # Deferred import to avoid cycles + from igraph import Graph + + superclass_meth = super(Graph, graph).bipartite_projection + + if which is False: + which = 0 + elif which is True: + which = 1 + if which != 0 and which != 1: + which = -1 + + if multiplicity: + if which == 0: + g1, w1 = superclass_meth(types, True, probe1, which) + g2, w2 = None, None + elif which == 1: + g1, w1 = None, None + g2, w2 = superclass_meth(types, True, probe1, which) + else: + g1, g2, w1, w2 = superclass_meth(types, True, probe1, which) + + if g1 is not None: + g1.es["weight"] = w1 + if g2 is not None: + g2.es["weight"] = w2 + return g1, g2 + else: + return g1 + else: + g2.es["weight"] = w2 + return g2 + else: + return superclass_meth(types, False, probe1, which) + + +def _bipartite_projection_size(graph, types="type", *args, **kwds): + """Calculates the number of vertices and edges in the bipartite + projections of this graph according to the specified vertex types. + This is useful if you have a bipartite graph and you want to estimate + the amount of memory you would need to calculate the projections + themselves. + + @param types: an igraph vector containing the vertex types, or an + attribute name. Anything that evalulates to C{False} corresponds to + vertices of the first kind, everything else to the second kind. + @return: a 4-tuple containing the number of vertices and edges in the + first projection, followed by the number of vertices and edges in the + second projection. + """ + # Deferred import to avoid cycles + from igraph import Graph + + return super(Graph, graph).bipartite_projection_size(types, *args, **kwds) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 92631d31c..72c7310fe 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -5,6 +5,7 @@ from copy import deepcopy from io import StringIO +from igraph._igraph import GraphBase from igraph import community_to_membership from igraph.configuration import Configuration from igraph.datatypes import UniqueIdGenerator @@ -1530,3 +1531,63 @@ def split_join_distance(comm1, comm2, remove_none=False): vec1, vec2 = _prepare_community_comparison(comm1, comm2, remove_none) return igraph._igraph._split_join_distance(vec1, vec2) + + +def _biconnected_components(graph, return_articulation_points=False): + """\ + Calculates the biconnected components of the graph. + + @param return_articulation_points: whether to return the articulation + points as well + @return: a L{VertexCover} object describing the biconnected components, + and optionally the list of articulation points as well + """ + if return_articulation_points: + trees, aps = GraphBase.biconnected_components(graph, True) + else: + trees = GraphBase.biconnected_components(graph, False) + + clusters = [] + if trees: + edgelist = graph.get_edgelist() + for tree in trees: + cluster = set() + for edge_id in tree: + cluster.update(edgelist[edge_id]) + clusters.append(sorted(cluster)) + + clustering = VertexCover(graph, clusters) + + if return_articulation_points: + return clustering, aps + else: + return clustering + + +def _cohesive_blocks(graph): + """Calculates the cohesive block structure of the graph. + + Cohesive blocking is a method of determining hierarchical subsets of graph + vertices based on their structural cohesion (i.e. vertex connectivity). + For a given graph G, a subset of its vertices S is said to be maximally + k-cohesive if there is no superset of S with vertex connectivity greater + than or equal to k. Cohesive blocking is a process through which, given a + k-cohesive set of vertices, maximally l-cohesive subsets are recursively + identified with l > k. Thus a hierarchy of vertex subsets is obtained in + the end, with the entire graph G at its root. + + @return: an instance of L{CohesiveBlocks}. See the documentation of + L{CohesiveBlocks} for more information. + @see: L{CohesiveBlocks} + """ + return CohesiveBlocks(graph, *GraphBase.cohesive_blocks(graph)) + + +def _clusters(graph, mode="strong"): + """Calculates the (strong or weak) clusters (connected components) for + a given graph. + + @param mode: must be either C{"strong"} or C{"weak"}, depending on the + clusters being sought. Optional, defaults to C{"strong"}. + @return: a L{VertexClustering} object""" + return VertexClustering(graph, GraphBase.clusters(graph, mode)) diff --git a/src/igraph/community/__init__.py b/src/igraph/community/__init__.py index cf5b56410..578dc4568 100644 --- a/src/igraph/community/__init__.py +++ b/src/igraph/community/__init__.py @@ -476,3 +476,37 @@ def _community_leiden( return VertexClustering(graph, membership, modularity_params=modularity_params) +def _modularity(self, membership, weights=None): + """Calculates the modularity score of the graph with respect to a given + clustering. + + The modularity of a graph w.r.t. some division measures how good the + division is, or how separated are the different vertex types from each + other. It's defined as M{Q=1/(2m)*sum(Aij-ki*kj/(2m)delta(ci,cj),i,j)}. + M{m} is the number of edges, M{Aij} is the element of the M{A} + adjacency matrix in row M{i} and column M{j}, M{ki} is the degree of + node M{i}, M{kj} is the degree of node M{j}, and M{Ci} and C{cj} are + the types of the two vertices (M{i} and M{j}). M{delta(x,y)} is one iff + M{x=y}, 0 otherwise. + + If edge weights are given, the definition of modularity is modified as + follows: M{Aij} becomes the weight of the corresponding edge, M{ki} + is the total weight of edges adjacent to vertex M{i}, M{kj} is the + total weight of edges adjacent to vertex M{j} and M{m} is the total + edge weight in the graph. + + @param membership: a membership list or a L{VertexClustering} object + @param weights: optional edge weights or C{None} if all edges are + weighed equally. Attribute names are also allowed. + @return: the modularity score + + @newfield ref: Reference + @ref: MEJ Newman and M Girvan: Finding and evaluating community + structure in networks. Phys Rev E 69 026113, 2004. + """ + if isinstance(membership, VertexClustering): + if membership.graph != self: + raise ValueError("clustering object belongs to another graph") + return GraphBase.modularity(self, membership.membership, weights) + else: + return GraphBase.modularity(self, membership, weights) diff --git a/src/igraph/components.py b/src/igraph/components.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/igraph/cut.py b/src/igraph/cut.py index c6be762d4..4cf62d937 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -2,6 +2,9 @@ # -*- coding: utf-8 -*- """Classes representing cuts and flows on graphs.""" +from igraph._igraph import ( + GraphBase, +) from igraph.clustering import VertexClustering @@ -187,3 +190,142 @@ def flow(self): larger vertex ID to the smaller. """ return self._flow + + +def _all_st_cuts(graph, source, target): + """\ + Returns all the cuts between the source and target vertices in a + directed graph. + + This function lists all edge-cuts between a source and a target vertex. + Every cut is listed exactly once. + + @param source: the source vertex ID + @param target: the target vertex ID + @return: a list of L{Cut} objects. + + @newfield ref: Reference + @ref: JS Provan and DR Shier: A paradigm for listing (s,t)-cuts in + graphs. Algorithmica 15, 351--372, 1996. + """ + return [ + Cut(graph, cut=cut, partition=part) + for cut, part in zip(*GraphBase.all_st_cuts(graph, source, target)) + ] + + +def _all_st_mincuts(graph, source, target, capacity=None): + """\ + Returns all the mincuts between the source and target vertices in a + directed graph. + + This function lists all minimum edge-cuts between a source and a target + vertex. + + @param source: the source vertex ID + @param target: the target vertex ID + @param capacity: the edge capacities (weights). If C{None}, all + edges have equal weight. May also be an attribute name. + @return: a list of L{Cut} objects. + + @newfield ref: Reference + @ref: JS Provan and DR Shier: A paradigm for listing (s,t)-cuts in + graphs. Algorithmica 15, 351--372, 1996. + """ + value, cuts, parts = GraphBase.all_st_mincuts(graph, source, target, capacity) + return [ + Cut(graph, value, cut=cut, partition=part) for cut, part in zip(cuts, parts) + ] + + +def _gomory_hu_tree(graph, capacity=None, flow="flow"): + """Calculates the Gomory-Hu tree of an undirected graph with optional + edge capacities. + + The Gomory-Hu tree is a concise representation of the value of all the + maximum flows (or minimum cuts) in a graph. The vertices of the tree + correspond exactly to the vertices of the original graph in the same order. + Edges of the Gomory-Hu tree are annotated by flow values. The value of + the maximum flow (or minimum cut) between an arbitrary (u,v) vertex + pair in the original graph is then given by the minimum flow value (i.e. + edge annotation) along the shortest path between u and v in the + Gomory-Hu tree. + + @param capacity: the edge capacities (weights). If C{None}, all + edges have equal weight. May also be an attribute name. + @param flow: the name of the edge attribute in the returned graph + in which the flow values will be stored. + @return: the Gomory-Hu tree as a L{Graph} object. + """ + graph, flow_values = GraphBase.gomory_hu_tree(graph, capacity) + graph.es[flow] = flow_values + return graph + + +def _maxflow(graph, source, target, capacity=None): + """Returns a maximum flow between the given source and target vertices + in a graph. + + A maximum flow from I{source} to I{target} is an assignment of + non-negative real numbers to the edges of the graph, satisfying + two properties: + + 1. For each edge, the flow (i.e. the assigned number) is not + more than the capacity of the edge (see the I{capacity} + argument) + + 2. For every vertex except the source and the target, the + incoming flow is the same as the outgoing flow. + + The value of the flow is the incoming flow of the target or the + outgoing flow of the source (which are equal). The maximum flow + is the maximum possible such value. + + @param capacity: the edge capacities (weights). If C{None}, all + edges have equal weight. May also be an attribute name. + @return: a L{Flow} object describing the maximum flow + """ + return Flow(graph, *GraphBase.maxflow(graph, source, target, capacity)) + + +def _mincut(graph, source=None, target=None, capacity=None): + """Calculates the minimum cut between the given source and target vertices + or within the whole graph. + + The minimum cut is the minimum set of edges that needs to be removed to + separate the source and the target (if they are given) or to disconnect the + graph (if neither the source nor the target are given). The minimum is + calculated using the weights (capacities) of the edges, so the cut with + the minimum total capacity is calculated. + + For undirected graphs and no source and target, the method uses the + Stoer-Wagner algorithm. For a given source and target, the method uses the + push-relabel algorithm; see the references below. + + @param source: the source vertex ID. If C{None}, the target must also be + C{None} and the calculation will be done for the entire graph (i.e. + all possible vertex pairs). + @param target: the target vertex ID. If C{None}, the source must also be + C{None} and the calculation will be done for the entire graph (i.e. + all possible vertex pairs). + @param capacity: the edge capacities (weights). If C{None}, all + edges have equal weight. May also be an attribute name. + @return: a L{Cut} object describing the minimum cut + """ + return Cut(graph, *GraphBase.mincut(graph, source, target, capacity)) + + +def _st_mincut(graph, source, target, capacity=None): + """Calculates the minimum cut between the source and target vertices in a + graph. + + @param source: the source vertex ID + @param target: the target vertex ID + @param capacity: the capacity of the edges. It must be a list or a valid + attribute name or C{None}. In the latter case, every edge will have the + same capacity. + @return: the value of the minimum cut, the IDs of vertices in the + first and second partition, and the IDs of edges in the cut, + packed in a 4-tuple + """ + return Cut(graph, *GraphBase.st_mincut(graph, source, target, capacity)) diff --git a/src/igraph/io/__init__.py b/src/igraph/io/__init__.py index e69de29bb..aae930b26 100644 --- a/src/igraph/io/__init__.py +++ b/src/igraph/io/__init__.py @@ -0,0 +1,25 @@ +_format_mapping = { + "ncol": ("Read_Ncol", "write_ncol"), + "lgl": ("Read_Lgl", "write_lgl"), + "graphdb": ("Read_GraphDB", None), + "graphmlz": ("Read_GraphMLz", "write_graphmlz"), + "graphml": ("Read_GraphML", "write_graphml"), + "gml": ("Read_GML", "write_gml"), + "dot": (None, "write_dot"), + "graphviz": (None, "write_dot"), + "net": ("Read_Pajek", "write_pajek"), + "pajek": ("Read_Pajek", "write_pajek"), + "dimacs": ("Read_DIMACS", "write_dimacs"), + "adjacency": ("Read_Adjacency", "write_adjacency"), + "adj": ("Read_Adjacency", "write_adjacency"), + "edgelist": ("Read_Edgelist", "write_edgelist"), + "edge": ("Read_Edgelist", "write_edgelist"), + "edges": ("Read_Edgelist", "write_edgelist"), + "pickle": ("Read_Pickle", "write_pickle"), + "picklez": ("Read_Picklez", "write_picklez"), + "svg": (None, "write_svg"), + "gw": (None, "write_leda"), + "leda": (None, "write_leda"), + "lgr": (None, "write_leda"), + "dl": ("Read_DL", None), +} diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 7ef002f1b..79ecced3a 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -21,6 +21,7 @@ '_layout_sugiyama', '_layout_method_wrapper', '_3d_version_for', + '_layout_mapping', ) @@ -716,3 +717,36 @@ def result(*args, **kwds): ) return result + +# After adjusting something here, don't forget to update the docstring +# of Graph.layout if necessary! +_layout_mapping = { + "auto": "layout_auto", + "automatic": "layout_auto", + "bipartite": "layout_bipartite", + "circle": "layout_circle", + "circular": "layout_circle", + "davidson_harel": "layout_davidson_harel", + "dh": "layout_davidson_harel", + "drl": "layout_drl", + "fr": "layout_fruchterman_reingold", + "fruchterman_reingold": "layout_fruchterman_reingold", + "graphopt": "layout_graphopt", + "grid": "layout_grid", + "kk": "layout_kamada_kawai", + "kamada_kawai": "layout_kamada_kawai", + "lgl": "layout_lgl", + "large": "layout_lgl", + "large_graph": "layout_lgl", + "mds": "layout_mds", + "random": "layout_random", + "rt": "layout_reingold_tilford", + "tree": "layout_reingold_tilford", + "reingold_tilford": "layout_reingold_tilford", + "rt_circular": "layout_reingold_tilford_circular", + "reingold_tilford_circular": "layout_reingold_tilford_circular", + "sphere": "layout_sphere", + "spherical": "layout_sphere", + "star": "layout_star", + "sugiyama": "layout_sugiyama", +} diff --git a/src/igraph/seq/__init__.py b/src/igraph/seq/__init__.py index de065bb79..eee305181 100644 --- a/src/igraph/seq/__init__.py +++ b/src/igraph/seq/__init__.py @@ -698,3 +698,107 @@ def __call__(self, *args, **kwds): return self.select(*args, **kwds) +def _graphmethod(func=None, name=None): + """Auxiliary decorator + + This decorator allows some methods of L{VertexSeq} and L{EdgeSeq} to + call their respective counterparts in L{Graph} to avoid code duplication. + + @param func: the function being decorated. This function will be + called on the results of the original L{Graph} method. + If C{None}, defaults to the identity function. + @param name: the name of the corresponding method in L{Graph}. If + C{None}, it defaults to the name of the decorated function. + @return: the decorated function + """ + # Delay import to avoid cycles + from igraph import Graph + + if name is None: + name = func.__name__ + method = getattr(Graph, name) + + if hasattr(func, "__call__"): + + def decorated(*args, **kwds): + self = args[0].graph + return func(args[0], method(self, *args, **kwds)) + + else: + + def decorated(*args, **kwds): + self = args[0].graph + return method(self, *args, **kwds) + + decorated.__name__ = name + decorated.__doc__ = """Proxy method to L{Graph.%(name)s()} + +This method calls the C{%(name)s()} method of the L{Graph} class +restricted to this sequence, and returns the result. + +@see: Graph.%(name)s() for details. +""" % { + "name": name + } + + return decorated + + +def _add_proxy_methods(): + + # Proxy methods for VertexSeq and EdgeSeq that forward their arguments to + # the corresponding Graph method are constructed here. Proxy methods for + # Vertex and Edge are added in the C source code. Make sure that you update + # the C source whenever you add a proxy method here if that makes sense for + # an individual vertex or edge + decorated_methods = {} + decorated_methods[VertexSeq] = [ + "degree", + "betweenness", + "bibcoupling", + "closeness", + "cocitation", + "constraint", + "diversity", + "eccentricity", + "get_shortest_paths", + "maxdegree", + "pagerank", + "personalized_pagerank", + "shortest_paths", + "similarity_dice", + "similarity_jaccard", + "subgraph", + "indegree", + "outdegree", + "isoclass", + "delete_vertices", + "is_separator", + "is_minimal_separator", + ] + decorated_methods[EdgeSeq] = [ + "count_multiple", + "delete_edges", + "is_loop", + "is_multiple", + "is_mutual", + "subgraph_edges", + ] + + rename_methods = {} + rename_methods[VertexSeq] = {"delete_vertices": "delete"} + rename_methods[EdgeSeq] = {"delete_edges": "delete", "subgraph_edges": "subgraph"} + + for cls, methods in decorated_methods.items(): + for method in methods: + new_method_name = rename_methods[cls].get(method, method) + setattr(cls, new_method_name, _graphmethod(None, method)) + + setattr( + EdgeSeq, + "edge_betweenness", + _graphmethod( + lambda self, result: [result[i] for i in self.indices], "edge_betweenness" + ), + ) + diff --git a/src/igraph/seq/edgeseq.py b/src/igraph/seq/edgeseq.py deleted file mode 100644 index 8ab03e2c2..000000000 --- a/src/igraph/seq/edgeseq.py +++ /dev/null @@ -1,431 +0,0 @@ -import operator - -from igraph._igraph import EdgeSeq as _EdgeSeq - - -class EdgeSeq(_EdgeSeq): - """Class representing a sequence of edges in the graph. - - This class is most easily accessed by the C{es} field of the - L{Graph} object, which returns an ordered sequence of all edges in - the graph. The edge sequence can be refined by invoking the - L{EdgeSeq.select()} method. L{EdgeSeq.select()} can also be - accessed by simply calling the L{EdgeSeq} object. - - An alternative way to create an edge sequence referring to a given - graph is to use the constructor directly: - - >>> g = Graph.Full(3) - >>> es = EdgeSeq(g) - >>> restricted_es = EdgeSeq(g, [0, 1]) - - The individual edges can be accessed by indexing the edge sequence - object. It can be used as an iterable as well, or even in a list - comprehension: - - >>> g=Graph.Full(3) - >>> for e in g.es: - ... print(e.tuple) - ... - (0, 1) - (0, 2) - (1, 2) - >>> [max(e.tuple) for e in g.es] - [1, 2, 2] - - The edge sequence can also be used as a dictionary where the keys are the - attribute names. The values corresponding to the keys are the values - of the given attribute of every edge in the graph: - - >>> g=Graph.Full(3) - >>> for idx, e in enumerate(g.es): - ... e["weight"] = idx*(idx+1) - ... - >>> g.es["weight"] - [0, 2, 6] - >>> g.es["weight"] = range(3) - >>> g.es["weight"] - [0, 1, 2] - - If you specify a sequence that is shorter than the number of edges in - the EdgeSeq, the sequence is reused: - - >>> g = Graph.Tree(7, 2) - >>> g.es["color"] = ["red", "green"] - >>> g.es["color"] - ['red', 'green', 'red', 'green', 'red', 'green'] - - You can even pass a single string or integer, it will be considered as a - sequence of length 1: - - >>> g.es["color"] = "red" - >>> g.es["color"] - ['red', 'red', 'red', 'red', 'red', 'red'] - - Some methods of the edge sequences are simply proxy methods to the - corresponding methods in the L{Graph} object. One such example is - C{EdgeSeq.is_multiple()}: - - >>> g=Graph(3, [(0,1), (1,0), (1,2)]) - >>> g.es.is_multiple() - [False, True, False] - >>> g.es.is_multiple() == g.is_multiple() - True - """ - - def attributes(self): - """Returns the list of all the edge attributes in the graph - associated to this edge sequence.""" - return self.graph.edge_attributes() - - def find(self, *args, **kwds): - """Returns the first edge of the edge sequence that matches some - criteria. - - The selection criteria are equal to the ones allowed by L{VertexSeq.select}. - See L{VertexSeq.select} for more details. - - For instance, to find the first edge with weight larger than 5 in graph C{g}: - - >>> g.es.find(weight_gt=5) #doctest:+SKIP - """ - if args: - # Selecting first based on positional arguments, then checking - # the criteria specified by the keyword arguments - edge = _EdgeSeq.find(self, *args) - if not kwds: - return edge - es = self.graph.es.select(edge.index) - else: - es = self - - # Selecting based on positional arguments - es = es.select(**kwds) - if es: - return es[0] - raise ValueError("no such edge") - - def select(self, *args, **kwds): - """Selects a subset of the edge sequence based on some criteria - - The selection criteria can be specified by the positional and the - keyword arguments. Positional arguments are always processed before - keyword arguments. - - - If the first positional argument is C{None}, an empty sequence is - returned. - - - If the first positional argument is a callable object, the object - will be called for every edge in the sequence. If it returns - C{True}, the edge will be included, otherwise it will - be excluded. - - - If the first positional argument is an iterable, it must return - integers and they will be considered as indices of the current - edge set (NOT the whole edge set of the graph -- the - difference matters when one filters an edge set that has - already been filtered by a previous invocation of - L{EdgeSeq.select()}. In this case, the indices do not refer - directly to the edges of the graph but to the elements of - the filtered edge sequence. - - - If the first positional argument is an integer, all remaining - arguments are expected to be integers. They are considered as - indices of the current edge set again. - - Keyword arguments can be used to filter the edges based on their - attributes and properties. The name of the keyword specifies the name - of the attribute and the filtering operator, they should be - concatenated by an underscore (C{_}) character. Attribute names can - also contain underscores, but operator names don't, so the operator is - always the largest trailing substring of the keyword name that does not - contain an underscore. Possible operators are: - - - C{eq}: equal to - - - C{ne}: not equal to - - - C{lt}: less than - - - C{gt}: greater than - - - C{le}: less than or equal to - - - C{ge}: greater than or equal to - - - C{in}: checks if the value of an attribute is in a given list - - - C{notin}: checks if the value of an attribute is not in a given - list - - For instance, if you want to filter edges with a numeric C{weight} - property larger than 50, you have to write: - - >>> g.es.select(weight_gt=50) #doctest: +SKIP - - Similarly, to filter edges whose C{type} is in a list of predefined - types: - - >>> list_of_types = ["inhibitory", "excitatory"] - >>> g.es.select(type_in=list_of_types) #doctest: +SKIP - - If the operator is omitted, it defaults to C{eq}. For instance, the - following selector selects edges whose C{type} property is - C{intracluster}: - - >>> g.es.select(type="intracluster") #doctest: +SKIP - - In the case of an unknown operator, it is assumed that the - recognized operator is part of the attribute name and the actual - operator is C{eq}. - - Keyword arguments are treated specially if they start with an - underscore (C{_}). These are not real attributes but refer to specific - properties of the edges, e.g., their centrality. The rules are as - follows: - - 1. C{_source} or {_from} means the source vertex of an edge. For - undirected graphs, only the C{eq} operator is supported and it - is treated as {_incident} (since undirected graphs have no notion - of edge directionality). - - 2. C{_target} or {_to} means the target vertex of an edge. For - undirected graphs, only the C{eq} operator is supported and it - is treated as {_incident} (since undirected graphs have no notion - of edge directionality). - - 3. C{_within} ignores the operator and checks whether both endpoints - of the edge lie within a specified set. - - 4. C{_between} ignores the operator and checks whether I{one} - endpoint of the edge lies within a specified set and the I{other} - endpoint lies within another specified set. The two sets must be - given as a tuple. - - 5. C{_incident} ignores the operator and checks whether the edge is - incident on a specific vertex or a set of vertices. - - 6. Otherwise, the rest of the name is interpreted as a method of the - L{Graph} object. This method is called with the edge sequence as - its first argument (all others left at default values) and edges - are filtered according to the value returned by the method. - - For instance, if you want to exclude edges with a betweenness - centrality less than 2: - - >>> g = Graph.Famous("zachary") - >>> excl = g.es.select(_edge_betweenness_ge = 2) - - To select edges originating from vertices 2 and 4: - - >>> edges = g.es.select(_source_in = [2, 4]) - - To select edges lying entirely within the subgraph spanned by vertices - 2, 3, 4 and 7: - - >>> edges = g.es.select(_within = [2, 3, 4, 7]) - - To select edges with one endpoint in the vertex set containing vertices - 2, 3, 4 and 7 and the other endpoint in the vertex set containing - vertices 8 and 9: - - >>> edges = g.es.select(_between = ([2, 3, 4, 7], [8, 9])) - - For properties that take a long time to be computed (e.g., betweenness - centrality for large graphs), it is advised to calculate the values - in advance and store it in a graph attribute. The same applies when - you are selecting based on the same property more than once in the - same C{select()} call to avoid calculating it twice unnecessarily. - For instance, the following would calculate betweenness centralities - twice: - - >>> edges = g.es.select(_edge_betweenness_gt=10, # doctest:+SKIP - ... _edge_betweenness_lt=30) - - It is advised to use this instead: - - >>> g.es["bs"] = g.edge_betweenness() - >>> edges = g.es.select(bs_gt=10, bs_lt=30) - - @return: the new, filtered edge sequence - """ - es = _EdgeSeq.select(self, *args) - is_directed = self.graph.is_directed() - - def _ensure_set(value): - if isinstance(value, VertexSeq): - value = set(v.index for v in value) - elif not isinstance(value, (set, frozenset)): - value = set(value) - return value - - operators = { - "lt": operator.lt, - "gt": operator.gt, - "le": operator.le, - "ge": operator.ge, - "eq": operator.eq, - "ne": operator.ne, - "in": lambda a, b: a in b, - "notin": lambda a, b: a not in b, - } - - # TODO(ntamas): some keyword arguments should be prioritized over - # others; for instance, we have optimized code paths for _source and - # _target in directed and undirected graphs if es.is_all() is True; - # these should be executed first. This matters only if there are - # multiple keyword arguments and es.is_all() is True. - - for keyword, value in kwds.items(): - if "_" not in keyword or keyword.rindex("_") == 0: - keyword = keyword + "_eq" - pos = keyword.rindex("_") - attr, op = keyword[0:pos], keyword[pos + 1 :] - try: - func = operators[op] - except KeyError: - # No such operator, assume that it's part of the attribute name - attr, op, func = keyword, "eq", operators["eq"] - - if attr[0] == "_": - if attr in ("_source", "_from", "_target", "_to") and not is_directed: - if op not in ("eq", "in"): - raise RuntimeError("unsupported for undirected graphs") - - # translate to _incident to avoid confusion - attr = "_incident" - if func == operators["eq"]: - if hasattr(value, "__iter__") and not isinstance(value, str): - value = set(value) - else: - value = set([value]) - - if attr in ("_source", "_from"): - if es.is_all() and op == "eq": - # shortcut here: use .incident() as it is much faster - filtered_idxs = sorted(es.graph.incident(value, mode="out")) - func = None - # TODO(ntamas): there are more possibilities; we could - # optimize "ne", "in" and "notin" in similar ways - else: - values = [e.source for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) - - elif attr in ("_target", "_to"): - if es.is_all() and op == "eq": - # shortcut here: use .incident() as it is much faster - filtered_idxs = sorted(es.graph.incident(value, mode="in")) - func = None - # TODO(ntamas): there are more possibilities; we could - # optimize "ne", "in" and "notin" in similar ways - else: - values = [e.target for e in es] - if op == "in" or op == "notin": - value = _ensure_set(value) - - elif attr == "_incident": - func = None # ignoring function, filtering here - value = _ensure_set(value) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in value: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those that are in the current edge sequence - filtered_idxs = [ - i for i, e in enumerate(es) if e.index in candidates - ] - else: - # We are done, the filtered indexes are in the candidates set - filtered_idxs = sorted(candidates) - - elif attr == "_within": - func = None # ignoring function, filtering here - value = _ensure_set(value) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in value: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those where both endpoints are OK - filtered_idxs = [ - i - for i, e in enumerate(es) - if e.index in candidates - and e.source in value - and e.target in value - ] - else: - # Optimized version when the edge sequence contains all - # the edges exactly once in increasing order of edge IDs - filtered_idxs = [ - i - for i in candidates - if es[i].source in value and es[i].target in value - ] - - elif attr == "_between": - if len(value) != 2: - raise ValueError( - "_between selector requires two vertex ID lists" - ) - func = None # ignoring function, filtering here - set1 = _ensure_set(value[0]) - set2 = _ensure_set(value[1]) - - # Fetch all the edges that are incident on at least one of - # the vertices specified - candidates = set() - for v in set1: - candidates.update(es.graph.incident(v)) - for v in set2: - candidates.update(es.graph.incident(v)) - - if not es.is_all(): - # Find those where both endpoints are OK - filtered_idxs = [ - i - for i, e in enumerate(es) - if (e.source in set1 and e.target in set2) - or (e.target in set1 and e.source in set2) - ] - else: - # Optimized version when the edge sequence contains all - # the edges exactly once in increasing order of edge IDs - filtered_idxs = [ - i - for i in candidates - if (es[i].source in set1 and es[i].target in set2) - or (es[i].target in set1 and es[i].source in set2) - ] - - else: - # Method call, not an attribute - values = getattr(es.graph, attr[1:])(es) - else: - values = es[attr] - - # If we have a function to apply on the values, do that; otherwise - # we assume that filtered_idxs has already been calculated. - if func is not None: - filtered_idxs = [i for i, v in enumerate(values) if func(v, value)] - - es = es.select(filtered_idxs) - - return es - - def __call__(self, *args, **kwds): - """Shorthand notation to select() - - This method simply passes all its arguments to L{EdgeSeq.select()}. - """ - return self.select(*args, **kwds) - - diff --git a/src/igraph/structural.py b/src/igraph/structural.py new file mode 100644 index 000000000..eb7e38c75 --- /dev/null +++ b/src/igraph/structural.py @@ -0,0 +1,95 @@ +from igraph._igraph import ( + IN, + OUT, + arpack_options as default_arpack_options, +) +from igraph.statistics import Histogram + + +def _indegree(self, *args, **kwds): + """Returns the in-degrees in a list. + + See L{degree} for possible arguments. + """ + kwds["mode"] = IN + return self.degree(*args, **kwds) + + +def _outdegree(self, *args, **kwds): + """Returns the out-degrees in a list. + + See L{degree} for possible arguments. + """ + kwds["mode"] = OUT + return self.degree(*args, **kwds) + + +def _degree_distribution(self, bin_width=1, *args, **kwds): + """Calculates the degree distribution of the graph. + + Unknown keyword arguments are directly passed to L{degree()}. + + @param bin_width: the bin width of the histogram + @return: a histogram representing the degree distribution of the + graph. + """ + result = Histogram(bin_width, self.degree(*args, **kwds)) + return result + + +def _pagerank( + self, + vertices=None, + directed=True, + damping=0.85, + weights=None, + arpack_options=None, + implementation="prpack", + niter=1000, + eps=0.001, +): + """Calculates the PageRank values of a graph. + + @param vertices: the indices of the vertices being queried. + C{None} means all of the vertices. + @param directed: whether to consider directed paths. + @param damping: the damping factor. M{1-damping} is the PageRank value + for nodes with no incoming links. It is also the probability of + resetting the random walk to a uniform distribution in each step. + @param weights: edge weights to be used. Can be a sequence or iterable + or even an edge attribute name. + @param arpack_options: an L{ARPACKOptions} object used to fine-tune + the ARPACK eigenvector calculation. If omitted, the module-level + variable called C{arpack_options} is used. This argument is + ignored if not the ARPACK implementation is used, see the + I{implementation} argument. + @param implementation: which implementation to use to solve the + PageRank eigenproblem. Possible values are: + - C{"prpack"}: use the PRPACK library. This is a new + implementation in igraph 0.7 + - C{"arpack"}: use the ARPACK library. This implementation + was used from version 0.5, until version 0.7. + - C{"power"}: use a simple power method. This is the + implementation that was used before igraph version 0.5. + @param niter: The number of iterations to use in the power method + implementation. It is ignored in the other implementations + @param eps: The power method implementation will consider the + calculation as complete if the difference of PageRank values between + iterations change less than this value for every node. It is + ignored by the other implementations. + @return: a list with the Google PageRank values of the specified + vertices.""" + if arpack_options is None: + arpack_options = default_arpack_options + return self.personalized_pagerank( + vertices, + directed, + damping, + None, + None, + weights, + arpack_options, + implementation, + niter, + eps, + ) From 679f3525017c236bd4540e84b8dde16648005d88 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 5 Oct 2021 09:15:08 +1100 Subject: [PATCH 0686/1892] self -> graph in structural.py --- src/igraph/structural.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/igraph/structural.py b/src/igraph/structural.py index eb7e38c75..f751adf20 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -6,25 +6,25 @@ from igraph.statistics import Histogram -def _indegree(self, *args, **kwds): +def _indegree(graph, *args, **kwds): """Returns the in-degrees in a list. See L{degree} for possible arguments. """ kwds["mode"] = IN - return self.degree(*args, **kwds) + return graph.degree(*args, **kwds) -def _outdegree(self, *args, **kwds): +def _outdegree(graph, *args, **kwds): """Returns the out-degrees in a list. See L{degree} for possible arguments. """ kwds["mode"] = OUT - return self.degree(*args, **kwds) + return graph.degree(*args, **kwds) -def _degree_distribution(self, bin_width=1, *args, **kwds): +def _degree_distribution(graph, bin_width=1, *args, **kwds): """Calculates the degree distribution of the graph. Unknown keyword arguments are directly passed to L{degree()}. @@ -33,12 +33,12 @@ def _degree_distribution(self, bin_width=1, *args, **kwds): @return: a histogram representing the degree distribution of the graph. """ - result = Histogram(bin_width, self.degree(*args, **kwds)) + result = Histogram(bin_width, graph.degree(*args, **kwds)) return result def _pagerank( - self, + graph, vertices=None, directed=True, damping=0.85, @@ -81,7 +81,7 @@ def _pagerank( vertices.""" if arpack_options is None: arpack_options = default_arpack_options - return self.personalized_pagerank( + return graph.personalized_pagerank( vertices, directed, damping, From b93b1f15aa615e0b87eb3bbee874a7d6c99a3827 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 18 Oct 2021 16:18:13 +1100 Subject: [PATCH 0687/1892] Move module __init__ files into main modules --- src/igraph/{basic/__init__.py => basic.py} | 0 src/igraph/{community/__init__.py => community.py} | 0 src/igraph/{seq/__init__.py => seq.py} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/igraph/{basic/__init__.py => basic.py} (100%) rename src/igraph/{community/__init__.py => community.py} (100%) rename src/igraph/{seq/__init__.py => seq.py} (100%) diff --git a/src/igraph/basic/__init__.py b/src/igraph/basic.py similarity index 100% rename from src/igraph/basic/__init__.py rename to src/igraph/basic.py diff --git a/src/igraph/community/__init__.py b/src/igraph/community.py similarity index 100% rename from src/igraph/community/__init__.py rename to src/igraph/community.py diff --git a/src/igraph/seq/__init__.py b/src/igraph/seq.py similarity index 100% rename from src/igraph/seq/__init__.py rename to src/igraph/seq.py From 34f02b90c294d5ae2adeeb4d47b83f2564c6608c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 15:04:49 +0200 Subject: [PATCH 0688/1892] chore: reformatted code with black --- src/igraph/__init__.py | 20 ++++++++++---------- src/igraph/adjacency.py | 10 +++++----- src/igraph/automorphisms.py | 5 ++--- src/igraph/basic.py | 1 + src/igraph/clustering.py | 22 +++++++++------------- src/igraph/community.py | 4 +--- src/igraph/io/objects.py | 15 ++++++++++----- src/igraph/layout.py | 14 +++++++------- src/igraph/operators/__init__.py | 22 +++++++++++----------- src/igraph/seq.py | 3 +-- 10 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a8c9fc59e..9ad3fde19 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -613,16 +613,16 @@ def es(self): ################### # Graph operators - __iadd__ = _operator_method_registry['__iadd__'] - __add__ = _operator_method_registry['__add__'] - __and__ = _operator_method_registry['__and__'] - __isub__ = _operator_method_registry['__isub__'] - __sub__ = _operator_method_registry['__sub__'] - __mul__ = _operator_method_registry['__mul__'] - __or__ = _operator_method_registry['__or__'] - disjoint_union = _operator_method_registry['disjoint_union'] - union = _operator_method_registry['union'] - intersection = _operator_method_registry['intersection'] + __iadd__ = _operator_method_registry["__iadd__"] + __add__ = _operator_method_registry["__add__"] + __and__ = _operator_method_registry["__and__"] + __isub__ = _operator_method_registry["__isub__"] + __sub__ = _operator_method_registry["__sub__"] + __mul__ = _operator_method_registry["__mul__"] + __or__ = _operator_method_registry["__or__"] + disjoint_union = _operator_method_registry["disjoint_union"] + union = _operator_method_registry["union"] + intersection = _operator_method_registry["intersection"] ############################################# # Adjacency/incidence diff --git a/src/igraph/adjacency.py b/src/igraph/adjacency.py index 65ae88606..94fbd2822 100644 --- a/src/igraph/adjacency.py +++ b/src/igraph/adjacency.py @@ -15,11 +15,11 @@ __all__ = ( - '_get_adjacency', - '_get_adjacency_sparse', - '_get_adjlist', - '_get_incidence', - '_get_inclist', + "_get_adjacency", + "_get_adjacency_sparse", + "_get_adjlist", + "_get_incidence", + "_get_inclist", ) diff --git a/src/igraph/automorphisms.py b/src/igraph/automorphisms.py index 84178e9cf..6c8b5a417 100644 --- a/src/igraph/automorphisms.py +++ b/src/igraph/automorphisms.py @@ -1,6 +1,6 @@ __all__ = ( - '_count_automorphisms_vf2', - '_get_automorphisms_vf2', + "_count_automorphisms_vf2", + "_get_automorphisms_vf2", ) @@ -49,4 +49,3 @@ def _get_automorphisms_vf2( node_compat_fn=node_compat_fn, edge_compat_fn=edge_compat_fn, ) - diff --git a/src/igraph/basic.py b/src/igraph/basic.py index f02006a63..a0ce23abd 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -162,6 +162,7 @@ def _as_directed(graph, *args, **kwds): copy.to_directed(*args, **kwds) return copy + def _as_undirected(graph, *args, **kwds): """Returns an undirected copy of this graph. Arguments are passed on to L{to_undirected()} that is invoked on the copy. diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 72c7310fe..c302a3d68 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -485,9 +485,9 @@ def __plot__(self, backend, context, *args, **kwds): colors[is_crossing] for is_crossing in self.crossing() ] - palette = kwds.get('palette', None) + palette = kwds.get("palette", None) if palette is None: - kwds['palette'] = ClusterColoringPalette(len(self)) + kwds["palette"] = ClusterColoringPalette(len(self)) if "mark_groups" not in kwds: if Configuration.instance()["plotting.mark_groups"]: @@ -745,12 +745,12 @@ def __plot__(self, backend, context, *args, **kwds): if backend == "matplotlib": drawer = MatplotlibDendrogramDrawer(context) else: - bbox = kwds.pop('bbox', None) - palette = kwds.pop('palette', None) + bbox = kwds.pop("bbox", None) + palette = kwds.pop("palette", None) if bbox is None: - raise ValueError('bbox is required for cairo plots') + raise ValueError("bbox is required for cairo plots") if palette is None: - raise ValueError('palette is required for cairo plots') + raise ValueError("palette is required for cairo plots") drawer = CairoDendrogramDrawer(context, bbox, palette) drawer.draw(self, **kwds) @@ -878,9 +878,7 @@ class VisualVertexBuilder(AttributeCollectorBase): name if name is not None else str(idx) for idx, name in enumerate(self._names) ] - result = Dendrogram.__plot__( - self, backend, context, *args, **kwds - ) + result = Dendrogram.__plot__(self, backend, context, *args, **kwds) del self._names return result @@ -1176,7 +1174,7 @@ def __plot__(self, backend, context, *args, **kwds): """ if "edge_color" not in kwds and "color" not in self.graph.edge_attributes(): # Set up a default edge coloring based on internal vs external edges - if backend == 'matplotlib': + if backend == "matplotlib": colors = ["dimgrey", "silver"] else: colors = ["grey20", "grey80"] @@ -1330,9 +1328,7 @@ def __plot__(self, backend, context, *args, **kwds): if "vertex_color" not in kwds: kwds["vertex_color"] = self.max_cohesions() - return VertexCover.__plot__( - self, backend, context, *args, **kwds - ) + return VertexCover.__plot__(self, backend, context, *args, **kwds) def _handle_mark_groups_arg_for_clustering(mark_groups, clustering): diff --git a/src/igraph/community.py b/src/igraph/community.py index 578dc4568..644501577 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -138,9 +138,7 @@ def _community_leading_eigenvector( if arpack_options is not None: kwds["arpack_options"] = arpack_options - membership, _, q = GraphBase.community_leading_eigenvector( - graph, clusters, **kwds - ) + membership, _, q = GraphBase.community_leading_eigenvector(graph, clusters, **kwds) return VertexClustering(graph, membership, modularity=q) diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 8300e1e03..0864fe3b7 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -80,7 +80,7 @@ def create_list_from_indices(indices, n): if vertex_name_attr not in vertex_attrs: raise AttributeError( - f'{vertex_name_attr} is not a key of your vertex dictionaries', + f"{vertex_name_attr} is not a key of your vertex dictionaries", ) vertex_names = vertex_attrs[vertex_name_attr] @@ -639,7 +639,10 @@ def _export_graph_to_tuple_list( def _export_graph_to_list_dict( - graph, use_vids=True, sequence_constructor=list, vertex_name_attr="name", + graph, + use_vids=True, + sequence_constructor=list, + vertex_name_attr="name", ): """Export graph to a dictionary of lists (or other sequences). @@ -671,7 +674,7 @@ def _export_graph_to_list_dict( """ if not use_vids: if vertex_name_attr not in graph.vertex_attributes(): - raise AttributeError(f'Vertices do not have a {vertex_name_attr} attribute') + raise AttributeError(f"Vertices do not have a {vertex_name_attr} attribute") vs_names = graph.vs[vertex_name_attr] # Temporary output data structure @@ -690,7 +693,9 @@ def _export_graph_to_list_dict( return res -def _export_graph_to_dict_dict(graph, use_vids=True, edge_attrs=None, skip_none=False, vertex_name_attr="name"): +def _export_graph_to_dict_dict( + graph, use_vids=True, edge_attrs=None, skip_none=False, vertex_name_attr="name" +): """Export graph to dictionary of dicts of edge attributes This function is the reverse of Graph.DictDict. @@ -730,7 +735,7 @@ def _export_graph_to_dict_dict(graph, use_vids=True, edge_attrs=None, skip_none= if not use_vids: if vertex_name_attr not in graph.vertex_attributes(): - raise AttributeError(f'Vertices do not have a {vertex_name_attr} attribute') + raise AttributeError(f"Vertices do not have a {vertex_name_attr} attribute") vs_names = graph.vs[vertex_name_attr] # Temporary output data structure diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 79ecced3a..7f02349ff 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -15,13 +15,13 @@ __all__ = ( - 'Layout', - '_layout', - '_layout_auto', - '_layout_sugiyama', - '_layout_method_wrapper', - '_3d_version_for', - '_layout_mapping', + "Layout", + "_layout", + "_layout_auto", + "_layout_sugiyama", + "_layout_method_wrapper", + "_3d_version_for", + "_layout_mapping", ) diff --git a/src/igraph/operators/__init__.py b/src/igraph/operators/__init__.py index 0b6e86291..b2db4c2b7 100644 --- a/src/igraph/operators/__init__.py +++ b/src/igraph/operators/__init__.py @@ -7,7 +7,7 @@ "union", "intersection", "operator_method_registry", - ) +) from igraph.operators.functions import ( disjoint_union, @@ -28,14 +28,14 @@ ) operator_method_registry = { - '__iadd__': __iadd__, - '__add__': __add__, - '__and__': __and__, - '__isub__': __isub__, - '__sub__': __sub__, - '__mul__': __mul__, - '__or__': __or__, - 'disjoint_union': _disjoint_union, - 'union': _union, - 'intersection': _intersection, + "__iadd__": __iadd__, + "__add__": __add__, + "__and__": __and__, + "__isub__": __isub__, + "__sub__": __sub__, + "__mul__": __mul__, + "__or__": __or__, + "disjoint_union": _disjoint_union, + "union": _union, + "intersection": _intersection, } diff --git a/src/igraph/seq.py b/src/igraph/seq.py index eee305181..4d32e3c02 100644 --- a/src/igraph/seq.py +++ b/src/igraph/seq.py @@ -3,7 +3,7 @@ from igraph._igraph import ( EdgeSeq as _EdgeSeq, VertexSeq as _VertexSeq, -) +) class VertexSeq(_VertexSeq): @@ -801,4 +801,3 @@ def _add_proxy_methods(): lambda self, result: [result[i] for i in self.indices], "edge_betweenness" ), ) - From 56d97278f0dfaa4681e0093eef3c0b43dc143c72 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 15:05:30 +0200 Subject: [PATCH 0689/1892] chore: removed empty components.py --- src/igraph/components.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/igraph/components.py diff --git a/src/igraph/components.py b/src/igraph/components.py deleted file mode 100644 index e69de29bb..000000000 From 9b401abf767f79942c8209ecb8c809d05d4f6098 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 16:33:47 +0200 Subject: [PATCH 0690/1892] style: fixed a few linter warnings --- src/igraph/__init__.py | 3 --- src/igraph/adjacency.py | 7 ------- src/igraph/configuration.py | 1 - src/igraph/io/objects.py | 5 +---- src/igraph/utils.py | 1 - 5 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 9ad3fde19..8cb6a9955 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -270,10 +270,7 @@ import os import sys -import operator -from collections import defaultdict -from shutil import copyfileobj from warnings import warn diff --git a/src/igraph/adjacency.py b/src/igraph/adjacency.py index 94fbd2822..48d35fe38 100644 --- a/src/igraph/adjacency.py +++ b/src/igraph/adjacency.py @@ -1,11 +1,4 @@ from igraph._igraph import ( - ADJ_DIRECTED, - ADJ_LOWER, - ADJ_MAX, - ADJ_MIN, - ADJ_PLUS, - ADJ_UNDIRECTED, - ADJ_UPPER, GET_ADJACENCY_BOTH, GET_ADJACENCY_LOWER, GET_ADJACENCY_UPPER, diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 758c4adfd..1ae5bd016 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -9,7 +9,6 @@ """ import os.path -import platform from configparser import ConfigParser diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 0864fe3b7..430f81c70 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -401,16 +401,13 @@ def _construct_graph_from_dataframe( to unexpected behaviour: fill your NaNs with values before calling this function to mitigate. """ - # Deferred import to avoid cycles - from igraph import Graph - try: import pandas as pd except ImportError: raise ImportError("You should install pandas in order to use this function") try: import numpy as np - except: + except ImportError: raise ImportError("You should install numpy in order to use this function") if edges.shape[1] < 2: diff --git a/src/igraph/utils.py b/src/igraph/utils.py index f919ef717..ec36f8764 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -5,7 +5,6 @@ from contextlib import contextmanager from collections.abc import MutableMapping -from ctypes import sizeof from itertools import chain import os From e431cc8ba5c29c45d7fbb1cea589767d165680d4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 16:37:02 +0200 Subject: [PATCH 0691/1892] ci: restrict Pillow to <8.4 --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index 7a31ed1ff..d2c36165a 100644 --- a/setup.py +++ b/setup.py @@ -841,6 +841,11 @@ def use_educated_guess(self) -> None: "scipy>=1.5.0; platform_python_implementation != 'PyPy'", "matplotlib>=3.3.4; platform_python_implementation != 'PyPy'", "plotly>=5.3.0", + # matplotlib requires Pillow; however, Pillow >= 8.4 does not + # provide manylinux2010 wheels any more, but we need those in + # cibuildwheel for Linux so we need to restrict Pillow's version + # range + "Pillow>=8,<8.4; platform_python_implementation != 'PyPy'", ], "doc": [ "Sphinx>=4.2.0", From cd63424ef759cafddae0650054ee7d470c298c7f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 17:37:00 +0200 Subject: [PATCH 0692/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 6f154c7ac..24b6ef417 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 6f154c7ac0946f7a0baf1ce403c520cacf6035d7 +Subproject commit 24b6ef417a2929a7b3bc2e95d9bd792213a80134 From bb3de00be2bdd53bfe570bb0d8b04cdd3cc1c11f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 18:43:55 +0200 Subject: [PATCH 0693/1892] fix: reinstantiated Graph.write_svg() --- src/igraph/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 8cb6a9955..87df9bea5 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -485,6 +485,8 @@ def __init__(self, *args, **kwds): Read_Adjacency = classmethod(_construct_graph_from_adjacency_file) write_adjacency = _write_graph_to_adjacency_file + write_svg = _write_graph_to_svg + Read = classmethod(_construct_graph_from_file) Load = Read write = _write_graph_to_file From 20b3cfc211373838042764b4d95c45a15ca3a075 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Oct 2021 18:48:05 +0200 Subject: [PATCH 0694/1892] style: blackened entire source --- src/igraph/clustering.py | 4 +- src/igraph/drawing/__init__.py | 43 +++++++-------- src/igraph/drawing/cairo/graph.py | 4 +- src/igraph/drawing/cairo/histogram.py | 5 +- src/igraph/drawing/cairo/palette.py | 3 +- src/igraph/drawing/cairo/text.py | 2 +- src/igraph/drawing/cairo/utils.py | 2 +- src/igraph/drawing/matplotlib/histogram.py | 2 +- src/igraph/drawing/matplotlib/palette.py | 2 +- src/igraph/drawing/matplotlib/utils.py | 2 +- src/igraph/drawing/plotly/edge.py | 62 +++++++++++++--------- src/igraph/drawing/plotly/graph.py | 27 +++++----- src/igraph/drawing/plotly/polygon.py | 40 ++++++++------ src/igraph/drawing/plotly/utils.py | 15 +++--- src/igraph/drawing/plotly/vertex.py | 31 +++++------ src/igraph/drawing/text.py | 2 +- 16 files changed, 131 insertions(+), 115 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index c302a3d68..bc632bdcb 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -748,9 +748,9 @@ def __plot__(self, backend, context, *args, **kwds): bbox = kwds.pop("bbox", None) palette = kwds.pop("palette", None) if bbox is None: - raise ValueError("bbox is required for cairo plots") + raise ValueError("bbox is required for Cairo plots") if palette is None: - raise ValueError("palette is required for cairo plots") + raise ValueError("palette is required for Cairo plots") drawer = CairoDendrogramDrawer(context, bbox, palette) drawer.draw(self, **kwds) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index a1f53d00d..67094084c 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -70,29 +70,29 @@ class DrawerDirectory: This directory is used by the __plot__ functions. """ - valid_backends = ('cairo', 'matplotlib') + + valid_backends = ("cairo", "matplotlib") valid_objects = ( - 'Graph', - 'Matrix', - 'Histogram', - 'Palette', + "Graph", + "Matrix", + "Histogram", + "Palette", ) known_drawers = { - 'cairo': { - 'Graph': CairoGraphDrawer, - 'Matrix': CairoMatrixDrawer, - 'Histogram': CairoHistogramDrawer, - 'Palette': CairoPaletteDrawer, - + "cairo": { + "Graph": CairoGraphDrawer, + "Matrix": CairoMatrixDrawer, + "Histogram": CairoHistogramDrawer, + "Palette": CairoPaletteDrawer, }, - 'matplotlib': { - 'Graph': MatplotlibGraphDrawer, - 'Matrix': MatplotlibMatrixDrawer, - 'Histogram': MatplotlibHistogramDrawer, - 'Palette': MatplotlibPaletteDrawer, + "matplotlib": { + "Graph": MatplotlibGraphDrawer, + "Matrix": MatplotlibMatrixDrawer, + "Histogram": MatplotlibHistogramDrawer, + "Palette": MatplotlibPaletteDrawer, }, - 'plotly': { - 'Graph': PlotlyGraphDrawer, + "plotly": { + "Graph": PlotlyGraphDrawer, }, } @@ -106,14 +106,14 @@ def resolve(cls, obj, backend): @raise ValueError: if no drawer is available for this backend/object """ - object_name = str(obj.__class__).split('.')[-1].strip("<'>") + object_name = str(obj.__class__).split(".")[-1].strip("<'>") try: return cls.known_drawers[backend][object_name] except KeyError: raise ValueError( f"unknown drawer for {object_name} and backend {backend}", - ) + ) def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): @@ -196,7 +196,8 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): if hasattr(plt, "Axes") and isinstance(target, plt.Axes): backend = "matplotlib" elif hasattr(plotly, "graph_objects") and isinstance( - target, plotly.graph_objects.Figure): + target, plotly.graph_objects.Figure + ): backend = "plotly" elif hasattr(cairo, "Surface") and isinstance(target, cairo.Surface): backend = "cairo" diff --git a/src/igraph/drawing/cairo/graph.py b/src/igraph/drawing/cairo/graph.py index d66ce7b36..44bbef880 100644 --- a/src/igraph/drawing/cairo/graph.py +++ b/src/igraph/drawing/cairo/graph.py @@ -122,9 +122,9 @@ def draw(self, graph, *args, **kwds): DeprecationWarning, ) - bbox = kwds.pop('bbox', None) + bbox = kwds.pop("bbox", None) if bbox is None: - raise ValueError('bbox is required for cairo plots') + raise ValueError("bbox is required for Cairo plots") # Validate it through set/get self.bbox = bbox bbox = self.bbox diff --git a/src/igraph/drawing/cairo/histogram.py b/src/igraph/drawing/cairo/histogram.py index de984fe8e..81de8b3bd 100644 --- a/src/igraph/drawing/cairo/histogram.py +++ b/src/igraph/drawing/cairo/histogram.py @@ -22,9 +22,9 @@ def draw(self, histogram, **kwds): context = self.context - bbox = self.bbox = kwds.pop('bbox', None) + bbox = self.bbox = kwds.pop("bbox", None) if bbox is None: - raise ValueError('bbox is required for cairo plots') + raise ValueError("bbox is required for Cairo plots") xmin = kwds.get("min", self._min) ymin = 0 @@ -56,4 +56,3 @@ def draw(self, histogram, **kwds): # Draw the axes coord_system.draw() - diff --git a/src/igraph/drawing/cairo/palette.py b/src/igraph/drawing/cairo/palette.py index 9c0e67a16..22180ae0e 100644 --- a/src/igraph/drawing/cairo/palette.py +++ b/src/igraph/drawing/cairo/palette.py @@ -41,7 +41,7 @@ def draw(self, palette, **kwds): grid_width = float(kwds.get("grid_width", 0.0)) return matrix.__plot__( - 'cairo', + "cairo", context, bbox=bbox, palette=self, @@ -50,4 +50,3 @@ def draw(self, palette, **kwds): grid_width=grid_width, border_width=border_width, ) - diff --git a/src/igraph/drawing/cairo/text.py b/src/igraph/drawing/cairo/text.py index cbf29e0f3..a075a9fa1 100644 --- a/src/igraph/drawing/cairo/text.py +++ b/src/igraph/drawing/cairo/text.py @@ -7,7 +7,7 @@ from igraph.drawing.cairo.base import AbstractCairoDrawer -__all__ = ("CairoTextDrawer", ) +__all__ = ("CairoTextDrawer",) class CairoTextDrawer(AbstractCairoDrawer): diff --git a/src/igraph/drawing/cairo/utils.py b/src/igraph/drawing/cairo/utils.py index 753652b83..5bc8fa819 100644 --- a/src/igraph/drawing/cairo/utils.py +++ b/src/igraph/drawing/cairo/utils.py @@ -1,7 +1,7 @@ from igraph.drawing.utils import FakeModule from typing import Any -__all__ = ("find_cairo", ) +__all__ = ("find_cairo",) def find_cairo() -> Any: diff --git a/src/igraph/drawing/matplotlib/histogram.py b/src/igraph/drawing/matplotlib/histogram.py index 0084875c1..8100ebf47 100644 --- a/src/igraph/drawing/matplotlib/histogram.py +++ b/src/igraph/drawing/matplotlib/histogram.py @@ -32,6 +32,6 @@ def draw(self, matrix, **kwds): x = [self._min + width * i for i, _ in enumerate(self._bins)] y = self._bins # Draw the boxes/bars - ax.bar(x, y, align='left') + ax.bar(x, y, align="left") ax.set_xlim(xmin, xmax) ax.set_ylim(ymin, ymax) diff --git a/src/igraph/drawing/matplotlib/palette.py b/src/igraph/drawing/matplotlib/palette.py index fb9fc3850..05f38a7f1 100644 --- a/src/igraph/drawing/matplotlib/palette.py +++ b/src/igraph/drawing/matplotlib/palette.py @@ -42,7 +42,7 @@ def draw(self, matrix, **kwds): [self.get(i) for i in range(self.length)], ) matrix.__plot__( - 'matplotlib', + "matplotlib", ax, cmap=cmap, **kwds, diff --git a/src/igraph/drawing/matplotlib/utils.py b/src/igraph/drawing/matplotlib/utils.py index 3c842c656..ab36f43f0 100644 --- a/src/igraph/drawing/matplotlib/utils.py +++ b/src/igraph/drawing/matplotlib/utils.py @@ -1,7 +1,7 @@ from igraph.drawing.utils import FakeModule from typing import Any -__all__ = ("find_matplotlib", ) +__all__ = ("find_matplotlib",) def find_matplotlib() -> Any: diff --git a/src/igraph/drawing/plotly/edge.py b/src/igraph/drawing/plotly/edge.py index 410b04d5f..f0e416188 100644 --- a/src/igraph/drawing/plotly/edge.py +++ b/src/igraph/drawing/plotly/edge.py @@ -4,8 +4,17 @@ from igraph.drawing.baseclasses import AbstractEdgeDrawer from igraph.drawing.metamagic import AttributeCollectorBase -from igraph.drawing.plotly.utils import find_plotly, format_path_step, format_arc, format_rgba -from igraph.drawing.utils import Point, euclidean_distance, intersect_bezier_curve_and_circle +from igraph.drawing.plotly.utils import ( + find_plotly, + format_path_step, + format_arc, + format_rgba, +) +from igraph.drawing.utils import ( + Point, + euclidean_distance, + intersect_bezier_curve_and_circle, +) __all__ = ("PlotlyEdgeDrawer",) @@ -135,17 +144,15 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): # Draw the curve from the first vertex to the midpoint of the base # of the arrow head - path.append(format_path_step( - "C", [aux1, aux2, [x_arrow_mid, y_arrow_mid]] - )) + path.append(format_path_step("C", [aux1, aux2, [x_arrow_mid, y_arrow_mid]])) else: # FIXME: this is tricky in plotly, let's skip for now ## Determine where the edge intersects the circumference of the ## vertex shape. - #x2, y2 = dest_vertex.shape.intersection_point( + # x2, y2 = dest_vertex.shape.intersection_point( # x2, y2, x1, y1, dest_vertex.size - #) + # ) # Draw the arrowhead angle = atan2(y_dest - y2, x_dest - x2) @@ -167,15 +174,18 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): aux_points[0][1] + aux_points[1][1] ) / 2.0 # Draw the line - path.append(format_path_step( - "L", Point(x_arrow_mid, y_arrow_mid), - )) + path.append( + format_path_step( + "L", + Point(x_arrow_mid, y_arrow_mid), + ) + ) - path = ' '.join(path) + path = " ".join(path) # Draw the edge stroke = dict( - type='path', + type="path", path=path, line_color=format_rgba(edge.color), line_width=edge.width, @@ -206,7 +216,7 @@ def draw_loop_edge(self, edge, vertex): center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 stroke = dict( - type='path', + type="path", path=format_arc( (center_x, center_y), radius / 2.0, @@ -237,9 +247,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): fig = self.context - path = [ - format_path_step("M", src_vertex.position) - ] + path = [format_path_step("M", src_vertex.position)] if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position @@ -250,19 +258,25 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): y1 + 2 * y2 ) / 3.0 + edge.curved * 0.5 * (x2 - x1) - path.append(format_path_step( - "C", [aux1, aux2, dest_vertex.position], - )) + path.append( + format_path_step( + "C", + [aux1, aux2, dest_vertex.position], + ) + ) else: - path.append(format_path_step( - "L", dest_vertex.position, - )) + path.append( + format_path_step( + "L", + dest_vertex.position, + ) + ) - path = ' '.join(path) + path = " ".join(path) stroke = dict( - type='path', + type="path", path=path, line_color=format_rgba(edge.color), line_width=edge.width, diff --git a/src/igraph/drawing/plotly/graph.py b/src/igraph/drawing/plotly/graph.py index e45e7d3db..e24cc1102 100644 --- a/src/igraph/drawing/plotly/graph.py +++ b/src/igraph/drawing/plotly/graph.py @@ -140,7 +140,7 @@ def draw(self, graph, *args, **kwds): hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] # Calculate the preferred rounding radius for the corners - #FIXME + # FIXME corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) # Construct the polygon @@ -177,7 +177,8 @@ def draw(self, graph, *args, **kwds): fig.add_trace( plotly.graph_objects.Bar( name=str(color_id), - x=[], y=[], + x=[], + y=[], fillcolor=facecolor, line_color=color, ) @@ -246,10 +247,10 @@ def draw(self, graph, *args, **kwds): (labels[i], edge_builder[i], graph.es[i]) for i in range(graph.ecount()) ) lab_args = { - 'text': [], - 'x': [], - 'y': [], - 'color': [], + "text": [], + "x": [], + "y": [], + "color": [], # FIXME: horizontal/vertical alignment, offset, etc? } for label, visual_edge, edge in edge_label_iter: @@ -264,18 +265,18 @@ def draw(self, graph, *args, **kwds): if label is None: continue - lab_args['text'].append(label) - lab_args['x'].append(x) - lab_args['y'].append(y) - lab_args['color'].append(visual_edge.label_color) + lab_args["text"].append(label) + lab_args["x"].append(x) + lab_args["y"].append(y) + lab_args["color"].append(visual_edge.label_color) stroke = plotly.graph_objects.Scatter( - mode='text', + mode="text", **lab_args, ) fig.add_trace(stroke) # Despine fig.update_layout( - yaxis={'visible': False, 'showticklabels': False}, - xaxis={'visible': False, 'showticklabels': False}, + yaxis={"visible": False, "showticklabels": False}, + xaxis={"visible": False, "showticklabels": False}, ) diff --git a/src/igraph/drawing/plotly/polygon.py b/src/igraph/drawing/plotly/polygon.py index c0978e42b..49f96ce87 100644 --- a/src/igraph/drawing/plotly/polygon.py +++ b/src/igraph/drawing/plotly/polygon.py @@ -46,11 +46,11 @@ def draw(self, points, corner_radius=0, **kwds): # We need to repeat the initial point to get a closed shape x = [p[0] for p in points] + [points[0][0]] y = [p[1] for p in points] + [points[0][1]] - kwds['mode'] = kwds.get('mode', 'line') + kwds["mode"] = kwds.get("mode", "line") stroke = plotly.graph_objects.Scatter( - x=x, - y=y, - **kwds, + x=x, + y=y, + **kwds, ) fig.add_trace(stroke) @@ -67,10 +67,12 @@ def draw(self, points, corner_radius=0, **kwds): # Okay, move to the last corner, adjusted by corner_radii[-1] # towards the first corner path = [] - path.append(format_path_step( - "M", - [points[-1].towards(points[0], corner_radii[-1])], - )) + path.append( + format_path_step( + "M", + [points[-1].towards(points[0], corner_radii[-1])], + ) + ) # Now, for each point in points, draw a line towards the # corner, stopping before it in a distance of corner_radii[idx], @@ -78,22 +80,26 @@ def draw(self, points, corner_radius=0, **kwds): u = points[-1] for idx, (v, w) in enumerate(consecutive_pairs(points, True)): radius = corner_radii[idx] - path.append(format_path_step( - "L", - [v.towards(u, radius)], - )) + path.append( + format_path_step( + "L", + [v.towards(u, radius)], + ) + ) aux1 = v.towards(u, radius / 2) aux2 = v.towards(w, radius / 2) - path.append(format_path_step( - "C", - [aux1, aux2, v.towards(w, corner_radii[idx])], - )) + path.append( + format_path_step( + "C", + [aux1, aux2, v.towards(w, corner_radii[idx])], + ) + ) u = v # Close path - path = "".join(path).strip(" ")+" Z" + path = "".join(path).strip(" ") + " Z" stroke = dict( type="path", path=path, diff --git a/src/igraph/drawing/plotly/utils.py b/src/igraph/drawing/plotly/utils.py index be28dfc50..7402d5c5f 100644 --- a/src/igraph/drawing/plotly/utils.py +++ b/src/igraph/drawing/plotly/utils.py @@ -1,7 +1,7 @@ from igraph.drawing.utils import FakeModule, Point from typing import Any -__all__ = ("find_plotly", ) +__all__ = ("find_plotly",) def find_plotly() -> Any: @@ -40,14 +40,14 @@ def format_arc(center, radius_x, radius_y, theta1, theta2, N=100, closed=False): xc, yc = center dt = 1.0 * (theta2 - theta1) - t = [theta1 + dt * i / (N-1) for i in range(N)] + t = [theta1 + dt * i / (N - 1) for i in range(N)] x = [xc + radius_x * math.cos(i) for i in t] y = [yc + radius_y * math.sin(i) for i in t] - path = f'M {x[0]}, {y[0]}' + path = f"M {x[0]}, {y[0]}" for k in range(1, len(t)): - path += f'L{x[k]}, {y[k]}' + path += f"L{x[k]}, {y[k]}" if closed: - path += ' Z' + path += " Z" return path @@ -58,7 +58,7 @@ def format_rgba(color): if isinstance(color, float): if color > 1: - color /= 255. + color /= 255.0 color = [color] * 3 r = int(255 * color[0]) @@ -69,6 +69,5 @@ def format_rgba(color): else: a = 255 - colstr = f'rgba({r},{g},{b},{a})' + colstr = f"rgba({r},{g},{b},{a})" return colstr - diff --git a/src/igraph/drawing/plotly/vertex.py b/src/igraph/drawing/plotly/vertex.py index 4d6f6df52..fe39c3a56 100644 --- a/src/igraph/drawing/plotly/vertex.py +++ b/src/igraph/drawing/plotly/vertex.py @@ -6,7 +6,7 @@ from igraph.drawing.metamagic import AttributeCollectorBase from .utils import find_plotly, format_rgba -__all__ = ('PlotlyVerticesDrawer',) +__all__ = ("PlotlyVerticesDrawer",) plotly = find_plotly() @@ -43,7 +43,6 @@ class VisualVertexBuilder(AttributeCollectorBase): return VisualVertexBuilder - def draw(self, visual_vertex, vertex, point): if visual_vertex.size <= 0: return @@ -51,23 +50,23 @@ def draw(self, visual_vertex, vertex, point): fig = self.fig marker_kwds = {} - marker_kwds['x'] = [point[0]] - marker_kwds['y'] = [point[1]] - marker_kwds['marker'] = { - 'symbol': visual_vertex.shape, - 'size': visual_vertex.size, - 'color': format_rgba(visual_vertex.color), - 'line_color': format_rgba(visual_vertex.frame_color), + marker_kwds["x"] = [point[0]] + marker_kwds["y"] = [point[1]] + marker_kwds["marker"] = { + "symbol": visual_vertex.shape, + "size": visual_vertex.size, + "color": format_rgba(visual_vertex.color), + "line_color": format_rgba(visual_vertex.frame_color), } - #if visual_vertex.label is not None: + # if visual_vertex.label is not None: # text_kwds['x'].append(point[0]) # text_kwds['y'].append(point[1]) # text_kwds['text'].append(visual_vertex.label) # Draw dots stroke = plotly.graph_objects.Scatter( - mode='markers', + mode="markers", **marker_kwds, ) fig.add_trace(stroke) @@ -79,17 +78,15 @@ def draw_label(self, visual_vertex, point, **kwds): fig = self.fig text_kwds = {} - text_kwds['x'] = [point[0]] - text_kwds['y'] = [point[1]] - text_kwds['text'].append(visual_vertex.label) + text_kwds["x"] = [point[0]] + text_kwds["y"] = [point[1]] + text_kwds["text"].append(visual_vertex.label) # TODO: add more options # Draw text labels stroke = plotly.graph_objects.Scatter( - mode='text', + mode="text", **text_kwds, ) fig.add_trace(stroke) - - diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index df48bbdb9..57d2f9a90 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -4,7 +4,7 @@ from enum import Enum -__all__ = ("TextAlignment", ) +__all__ = ("TextAlignment",) ##################################################################### From a31499e62cd8cca27a4bcbf284e003835afdbf28 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Oct 2021 21:52:12 +0200 Subject: [PATCH 0695/1892] chore: preparing for the rename of python-igraph to igraph --- README.md | 34 +++++++++--------- doc/Makefile | 8 ++--- doc/source/conf.py | 12 +++---- doc/source/include/global.rst | 1 - doc/source/index.rst | 6 ++-- doc/source/install.rst | 66 ++++++++++++++++++---------------- docker/jupyter/Dockerfile | 5 +-- docker/minimal/Dockerfile | 2 +- scripts/mkdoc.sh | 8 +++-- setup.py | 19 +++++----- src/igraph/__init__.py | 15 ++++---- src/igraph/configuration.py | 2 +- src/igraph/drawing/__init__.py | 8 ++--- src/igraph/drawing/graph.py | 5 ++- 14 files changed, 94 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 7c10bd183..f097cd460 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) -[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/python-igraph) -[![PyPI wheels](https://img.shields.io/pypi/wheel/python-igraph.svg)](https://pypi.python.org/pypi/python-igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/igraph) +[![PyPI wheels](https://img.shields.io/pypi/wheel/igraph.svg)](https://pypi.python.org/pypi/igraph) Python interface for the igraph library --------------------------------------- @@ -13,7 +13,7 @@ analysis of large graphs. This repository contains the source code to the Python interface of igraph. -You can learn more about python-igraph [on our website](http://igraph.org/python/). +You can learn more about igraph [on our website](http://igraph.org/python/). ## Installation from PyPI @@ -23,14 +23,14 @@ Therefore, running the following command should work without having to compile anything during installation: ``` -pip install python-igraph +pip install igraph ``` See details in [Installing Python Modules](https://docs.python.org/3/installing/). ### Installation from source with pip on Debian / Ubuntu and derivatives -If you need to compile python-igraph from source for some reason, you need to +If you need to compile igraph from source for some reason, you need to install some dependencies first: ``` @@ -40,7 +40,7 @@ sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev and then run ``` -pip install python-igraph +pip install igraph ``` This should compile the C core of igraph as well as the Python extension @@ -48,12 +48,12 @@ automatically. ### Installation from source on Windows -It is now also possible to compile `python-igraph` from source under Windows for +It is now also possible to compile `igraph` from source under Windows for Python 3.6 and later. Make sure that you have Microsoft Visual Studio 2015 or later installed, and of course Python 3.6 or later. First extract the source to a suitable directory. If you launch the Developer command prompt and navigate to the directory where you extracted the source code, you should be able to build -and install python-igraph using `python setup.py install` +and install igraph using `python setup.py install` You may need to set the architecture that you are building on explicitly by setting the environment variable @@ -85,8 +85,8 @@ This mentions that > CMake projects should use: `-DCMAKE_TOOLCHAIN_FILE=[vcpkg build script]` -which we will do next. In order to build `python-igraph` correctly, you also -need to set some other environment variables before building `python-igraph`: +which we will do next. In order to build `igraph` correctly, you also +need to set some other environment variables before building `igraph`: ``` set IGRAPH_CMAKE_EXTRA_ARGS=-DVCPKG_TARGET_TRIPLET=x64-windows-static-md -DCMAKE_TOOLCHAIN_FILE=[vcpkg build script] @@ -96,7 +96,7 @@ set IGRAPH_EXTRA_LIBRARIES=libxml2,lzma,zlib,iconv,charset set IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 ``` -You can now build and install `python-igraph` again by simply running `python +You can now build and install `igraph` again by simply running `python setup.py build`. Please make sure to use a clean source tree, if you built previously without GraphML, it will not update the build. @@ -120,7 +120,7 @@ error message, you are probably okay. You can then proceed with the installation using pip: ```bash -pip install python-igraph --install-option="--use-pkg-config" +pip install igraph --install-option="--use-pkg-config" ``` Alternatively, if you have already downloaded and extracted the source code @@ -179,13 +179,13 @@ python -m unittest ## Contributing -Contributions to `python-igraph` are welcome! +Contributions to `igraph` are welcome! If you want to add a feature, fix a bug, or suggest an improvement, open an issue on this repository and we'll try to answer. If you have a piece of code that you would like to see included in the main tree, open a PR on this repo. -To start developing `python-igraph`, follow the steps below (these are +To start developing `igraph`, follow the steps below (these are for Linux, Windows users should change the system commands a little). First, clone this repo (e.g. via https) and enter the folder: @@ -224,17 +224,15 @@ We aim to keep up with the development cycle of Python and support all official Python versions that have not reached their end of life yet. Currently this means that we support Python 3.6 to 3.9, inclusive. Please refer to [this page](https://devguide.python.org/#branchstatus) for the status of Python -branches and let us know if you encounter problems with `python-igraph` on any +branches and let us know if you encounter problems with `igraph` on any of the non-EOL Python versions. Continuous integration tests are regularly executed on all non-EOL Python branches. -Python 2 support has been dropped with the release of `python-igraph` 0.9. - ### PyPy -This version of python-igraph is compatible with [PyPy](http://pypy.org/) and +This version of igraph is compatible with [PyPy](http://pypy.org/) and is regularly tested on [PyPy](http://pypy.org/) with ``tox``. However, the PyPy version falls behind the CPython version in terms of performance; for instance, running all the tests takes ~5 seconds on my machine with CPython and diff --git a/doc/Makefile b/doc/Makefile index 2d2eb292b..aa1a6dbf8 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -72,17 +72,17 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-igraph.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/igraph.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-igraph.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/igraph.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/python-igraph" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/python-igraph" + @echo "# mkdir -p $$HOME/.local/share/devhelp/igraph" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/igraph" @echo "# devhelp" epub: diff --git a/doc/source/conf.py b/doc/source/conf.py index e94dd981f..f2c503a29 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# python-igraph documentation build configuration file, created by +# igraph documentation build configuration file, created by # sphinx-quickstart on Thu Jun 17 11:36:14 2010. # # This file is execfile()d with the current directory set to its containing dir. @@ -43,7 +43,7 @@ master_doc = 'index' # General information about the project. -project = u'python-igraph' +project = u'igraph' copyright = u'2010-{0}, The igraph development team'.format(datetime.now().year) # The version info for the project you're documenting, acts as replacement for @@ -170,7 +170,7 @@ #html_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'python-igraphdoc' +htmlhelp_basename = 'igraphdoc' # -- Options for LaTeX output -------------------------------------------------- @@ -184,7 +184,7 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'python-igraph.tex', u'python-igraph Documentation', + ('index', 'igraph.tex', u'igraph Documentation', u'The igraph development team', 'manual'), ] @@ -217,7 +217,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'python-igraph', u'python-igraph Documentation', + ('index', 'igraph', u'igraph Documentation', [u'The igraph development team'], 1) ] @@ -225,7 +225,7 @@ # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -epub_title = u'python-igraph' +epub_title = u'igraph' epub_author = u'The igraph development team' epub_publisher = u'The igraph development team' epub_copyright = u'2010, The igraph development team' diff --git a/doc/source/include/global.rst b/doc/source/include/global.rst index 7a928c465..d9462c53a 100644 --- a/doc/source/include/global.rst +++ b/doc/source/include/global.rst @@ -1,3 +1,2 @@ .. |igraph| replace:: *igraph* -.. |python-igraph| replace:: *python-igraph* diff --git a/doc/source/index.rst b/doc/source/index.rst index cb4afaa66..3203cf801 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,11 +1,11 @@ -.. python-igraph documentation master file, created by sphinx-quickstart on Thu Dec 11 16:02:35 2008. +.. igraph documentation master file, created by sphinx-quickstart on Thu Dec 11 16:02:35 2008. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. .. include:: include/global.rst -Welcome to python-igraph's documentation! -========================================= +Welcome to the documentation of the Python interface of igraph +============================================================== Contents: diff --git a/doc/source/install.rst b/doc/source/install.rst index f786c12d6..665339bf7 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -24,7 +24,7 @@ are often called *binary packages*, while the raw source code is usually referre In general, you should almost always opt for the binary package unless a binary package is not available for your platform or you have some local modifications that you want to incorporate into |igraph|'s source. `Installation from a binary package`_ tells you how to -install |igraph| from a precompiled binary package on various platforms. `Compiling python-igraph +install |igraph| from a precompiled binary package on various platforms. `Compiling igraph from source`_ tells you how to compile |igraph| from the source package. Installation from a binary package @@ -35,13 +35,13 @@ Installing |igraph| from the Python Package Index To ensure getting the latest binary release of |igraph|'s Python interface, it is recommended that you install it from the `Python Package Index -`_ (PyPI), which has installers for Windows, Linux, +`_ (PyPI), which has installers for Windows, Linux, and macOS. We aim to provide binary packages for the three latest minor versions of Python 3.x. -To install |python-igraph| globally, use the following command (you probably need -administrator/root privileges):: +To install the Python interface of |igraph| globally, use the following command +(you probably need administrator/root privileges):: - $ pip install python-igraph + $ pip install igraph Many users like to install packages into a project-specific `virtual environment `_. @@ -49,13 +49,13 @@ A variation of the following commands should work on most platforms:: $ python -m venv venv $ source venv/bin/activate - $ pip install python-igraph + $ pip install igraph Alternatively, if you do not want to activate the virtualenv, you can call the ``pip`` executable in it directly:: $ python -m venv venv - $ venv/bin/pip install python-igraph + $ venv/bin/pip install igraph Installing |igraph| via Conda ----------------------------- @@ -70,7 +70,7 @@ using conda. That can be achieved by running the following command:: ------------------- Precompiled Windows wheels for |igraph|'s Python interface are available on the `Python Package Index -`_ (see `Installing igraph from the Python Package +`_ (see `Installing igraph from the Python Package Index`_). Graph plotting in |igraph| is implemented using a third-party package called `Cairo @@ -95,7 +95,7 @@ If PyCairo was successfully installed, this will display a Petersen graph. ----------------- Precompiled macOS wheels for |igraph|'s Python interface are available on the `Python Package Index -`_ (see `Installing igraph from the Python Package +`_ (see `Installing igraph from the Python Package Index`_). Graph plotting in |igraph| is implemented using a third-party package called `Cairo @@ -120,44 +120,47 @@ If Cairo was successfully installed, this will display a Petersen graph. |igraph|'s Python interface and its dependencies have been packaged for most popular Linux distributions, including Arch Linux, Debian, Fedora, GNU Guix, NixOS, and Ubuntu. -|python-igraph| and its underlying |igraph| C core are usually in two different packages, but +|igraph| and its underlying C core are usually in two different packages, but your package manager should take care of that dependency for you. .. note:: Distribution packages can be outdated: if you find that's the case for you, you may - choose to install |igraph| from the `Python Package Index `_ + choose to install |igraph| from the `Python Package Index `_ instead to get a more recent release (see `Installing igraph from the Python Package Index`_). -Compiling |python-igraph| from source +Compiling |igraph| from source ===================================== -|python-igraph| binds itself into the main |igraph| library using some glue code written in C, so you'll need -both a C compiler and the library itself. Source tarballs of |python-igraph| obtained from PyPI already -contain a matching version of the C core of |igraph|. +|igraph| binds itself into the main |igraph| library using some glue code +written in C, so you'll need both a C compiler and the library itself. Source +tarballs of |igraph| obtained from PyPI already contain a matching version of +the C core of |igraph|. -There are two common scenarios to compile |python-igraph| from source: +There are two common scenarios to compile |igraph| from source: -1. Your would like to use the latest development version from Github, usually to try out some recently - added features +1. Your would like to use the latest development version from Github, usually + to try out some recently added features -2. The PyPI repository does not include precompiled binaries for your system. This can happen if your operating - system is not covered by our continuous development. +2. The PyPI repository does not include precompiled binaries for your system. + This can happen if your operating system is not covered by our continuous + development. Both will be covered in the next sections. Compiling using pip ------------------- -If you want the development version of |python-igraph|, call:: +If you want the development version of |igraph|, call:: $ pip install git+https://github.com/igraph/python-igraph -``pip`` is smart enough to download the sources from Github, initialize the submodule for the |igraph| C core, -compile it, and then compile |python-igraph| against it and install it. As above, a virtual environment is +``pip`` is smart enough to download the sources from Github, initialize the +submodule for the |igraph| C core, compile it, and then compile the Python +interface against it and install it. As above, a virtual environment is a commonly used sandbox to test experimental packages. If you want the latest release from PyPI but prefer to (or have to) install from source, call:: - $ pip install --no-binary ':all:' python-igraph + $ pip install --no-binary ':all:' igraph .. note:: If there is no binary for your system anyway, you can just try without the ``--no-binary`` option and obtain the same result. @@ -165,8 +168,8 @@ If you want the latest release from PyPI but prefer to (or have to) install from Compiling step by step ---------------------- -This section should be rarely used in practice but explains how to compile and install |python-igraph| step -by step without ``pip``. +This section should be rarely used in practice but explains how to compile and +install |igraph| step by step without ``pip``. First, obtain the bleeding-edge source code from Github:: @@ -186,18 +189,19 @@ Third, if you cloned the source from Github, initialize the ``git`` submodule fo $ git submodule update --init -.. note:: If you prefer to compile and link |python-igraph| against an existing |igraph| C core, for instance +.. note:: If you prefer to compile and link |igraph| against an existing |igraph| C core, for instance the one you installed with your package manager, you can skip the ``git`` submodule initialization step. If you downloaded a tarball, you also need to remove the ``vendor/source/igraph`` folder because the setup script - will look for the vendored |igraph| copy first. However, a particular version of |python-igraph| is guaranteed - to work only with the version of the C core that is bundled with it (or with the revision that the ``git`` + will look for the vendored |igraph| copy first. However, a particular + version of the Python interface is guaranteed to work only with the version + of the C core that is bundled with it (or with the revision that the ``git`` submodule points to). Fourth, call the standard Python ``setup.py`` script, e.g. for compiling:: $ python setup.py build -(press Enter when prompted). That will compile the |python-igraph| package in a subfolder called +(press Enter when prompted). That will compile the Python interface in a subfolder called ``build/lib.``, e.g. `build/lib.linux-x86_64-3.8`. You can add that folder to your ``PYTHONPATH`` if you want to import directly from it, or you can call the ``setup.py`` script to install it from there:: @@ -209,7 +213,7 @@ script to install it from there:: Testing your installation ------------------------- -The unit tests of ``python-igraph`` are implemented with the standard ``unittest`` module so you can +The unit tests are implemented with the standard ``unittest`` module so you can run them like this from your the source folder:: $ python -m unittest discover diff --git a/docker/jupyter/Dockerfile b/docker/jupyter/Dockerfile index 46609ae8f..e80376cf9 100644 --- a/docker/jupyter/Dockerfile +++ b/docker/jupyter/Dockerfile @@ -2,7 +2,4 @@ FROM jupyter/notebook MAINTAINER Tamas Nepusz LABEL Description="Docker image that contains Jupyter with a pre-compiled version of igraph's Python interface" RUN apt-get -y update && apt-get -y install build-essential libxml2-dev zlib1g-dev python-dev python-pip pkg-config libffi-dev libcairo-dev -RUN pip2 install python-igraph -RUN pip2 install cairocffi -RUN pip3 install python-igraph -RUN pip3 install cairocffi \ No newline at end of file +RUN pip3 install igraph cairocffi matplotlib \ No newline at end of file diff --git a/docker/minimal/Dockerfile b/docker/minimal/Dockerfile index d389de1d5..dba6d1442 100644 --- a/docker/minimal/Dockerfile +++ b/docker/minimal/Dockerfile @@ -2,7 +2,7 @@ FROM python:latest MAINTAINER Tamas Nepusz LABEL Description="Simple Docker image that contains a pre-compiled version of igraph's Python interface" -RUN pip3 install python-igraph cairocffi +RUN pip3 install igraph cairocffi CMD /usr/local/bin/igraph diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index b49ffc3aa..f5ac87264 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -29,19 +29,21 @@ PWD=`pwd` echo "Removing existing documentation..." rm -rf "${DOC_API_FOLDER}/html" "${DOC_API_FOLDER}/pdf" -echo "Removing existing python-igraph eggs from virtualenv..." +echo "Removing existing igraph and python-igraph eggs from virtualenv..." SITE_PACKAGES_DIR=`.venv/bin/python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'` +rm -rf "${SITE_PACKAGES_DIR}"/igraph*.egg +rm -rf "${SITE_PACKAGES_DIR}"/igraph*.egg-link rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg-link -echo "Installing python-igraph in virtualenv..." +echo "Installing igraph in virtualenv..." rm -f dist/*.whl && .venv/bin/python setup.py bdist_wheel && .venv/bin/pip install --force-reinstall dist/*.whl IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` echo "Generating HTML documentation..." "$PYDOCTOR" \ - --project-name "python-igraph" \ + --project-name "igraph" \ --project-url "https://igraph.org/python" \ --introspect-c-modules \ --make-html \ diff --git a/setup.py b/setup.py index c4944ee0b..5f15a6520 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,6 @@ import shlex import shutil import subprocess -import sys import sysconfig from contextlib import contextmanager @@ -517,7 +516,7 @@ def run(self): version_header = igraph_build_dir / "include" / "igraph_version.h" if not version_header.exists(): raise RuntimeError( - "You need to build the C core of igraph first before generating a source tarball of python-igraph" + "You need to build the C core of igraph first before generating a source tarball of the Python interface of igraph" ) with version_header.open("r") as fp: @@ -535,8 +534,8 @@ def run(self): ) if not is_git_repo(igraph_source_repo): - # python-igraph was extracted from an official tarball so - # there is no need to tweak anything + # The Python interface was extracted from an official + # tarball so there is no need to tweak anything return sdist.run(self) else: # Clean up vendor/source/igraph with git @@ -552,7 +551,7 @@ def run(self): else: raise RuntimeError( "You need to build the C core of igraph first before " - "generating a source tarball of python-igraph" + "generating a source tarball of the Python interface" ) # Add a version file to the tarball @@ -781,7 +780,7 @@ def use_educated_guess(self) -> None: # Import version number from version.py so we only need to change it in # one place when a new release is created -__version__ = None +__version__: str = "" exec(open("src/igraph/version.py").read()) # Process command line options @@ -800,15 +799,15 @@ def use_educated_guess(self) -> None: sure you install the Python bindings of Cairo if you want to generate publication-quality graph plots. You can try either `pycairo `_ or `cairocffi `_, -``cairocffi`` is recommended, in particular if you are on Python 3.x because -there were bug reports affecting igraph graph plots in Jupyter notebooks -when using ``pycairo`` (but not with ``cairocffi``). +``cairocffi`` is recommended because there were bug reports affecting igraph +graph plots in Jupyter notebooks when using ``pycairo`` (but not with +``cairocffi``). """ headers = ["src/_igraph/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] options = dict( - name="python-igraph", + name="igraph", version=__version__, url="https://igraph.org/python", description="High performance graph data structures and algorithms", diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 1e9178902..96f7de493 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1960,9 +1960,8 @@ def to_graph_tool( Note: because of the restricted data types in graph-tool, vertex and edge attributes require to be type-consistent across all vertices or edges. If you set the property for only some vertices/edges, the other - will be tagged as None in python-igraph, so they can only be converted - to graph-tool with the type 'object' and any other conversion will - fail. + will be tagged as None in igraph, so they can only be converted to + graph-tool with the type 'object' and any other conversion will fail. @param graph_attributes: dictionary of graph attributes to transfer. Keys are attributes from the graph, values are data types (see @@ -5243,21 +5242,21 @@ def get_include(): import igraph paths = [ - # The following path works if python-igraph is installed already + # The following path works if igraph is installed already os.path.join( sys.prefix, "include", "python{0}.{1}".format(*sys.version_info), - "python-igraph", + "igraph", ), - # Fallback for cases when python-igraph is not installed but + # Fallback for cases when igraph is not installed but # imported directly from the source tree - os.path.join(os.path.dirname(igraph.__file__), "..", "src"), + os.path.join(os.path.dirname(igraph.__file__), "..", "src", "_igraph"), ] for path in paths: if os.path.exists(os.path.join(path, "igraphmodule_api.h")): return os.path.abspath(path) - raise ValueError("cannot find the header files of python-igraph") + raise ValueError("cannot find the header files of the Python interface of igraph") def read(filename, *args, **kwds): diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index 43d890219..e81a1dfa4 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -22,7 +22,7 @@ def get_platform_image_viewer(): """Returns the path of an image viewer on the given platform. - Deprecated since python-igraph 0.9.1 and will be removed in 0.10.0. + Deprecated since igraph 0.9.1 and will be removed in 0.10.0. @deprecated: This function was only used by the now-deprecated C{show()} method of the Plot class. diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 244bb9116..288b66468 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -312,13 +312,13 @@ def save(self, fname=None): def show(self): """Saves the plot to a temporary file and shows it. - This method is deprecated from python-igraph 0.9.1 and will be removed in + This method is deprecated from igraph 0.9.1 and will be removed in version 0.10.0. @deprecated: Opening an image viewer with a temporary file never worked reliably across platforms. """ - warn("Plot.show() is deprecated from python-igraph 0.9.1", DeprecationWarning) + warn("Plot.show() is deprecated from igraph 0.9.1", DeprecationWarning) if not isinstance(self._surface, cairo.ImageSurface): sur = cairo.ImageSurface( @@ -426,8 +426,8 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): - C{None} -- a temporary file will be created and the object will be plotted there. igraph will attempt to open an image viewer and show - the temporary file. This feature is deprecated from python-igraph - version 0.9.1 and will be removed in 0.10.0. + the temporary file. This feature is deprecated from igraph version + 0.9.1 and will be removed in 0.10.0. @param bbox: the bounding box of the plot. It must be a tuple with either two or four integers, or a L{BoundingBox} object. If this is a tuple diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index c47b19193..41a950110 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -536,8 +536,7 @@ class UbiGraphDrawer(AbstractXMLRPCDrawer, AbstractGraphDrawer): @deprecated: UbiGraph has not received updates since 2008 and is now not available for download (at least not from the official sources). - The UbiGraph graph drawer will be removed from python-igraph in - 0.10.0. + The UbiGraph graph drawer will be removed from igraph in 0.10.0. """ def __init__(self, url="http://localhost:20738/RPC2"): @@ -548,7 +547,7 @@ def __init__(self, url="http://localhost:20738/RPC2"): self.edge_defaults = dict(color="#ffffff", width=1.0) warn( - "UbiGraphDrawer is deprecated from python-igraph 0.9.4", + "UbiGraphDrawer is deprecated from igraph 0.9.4", DeprecationWarning ) From d17cd6cb29815da6ae640a3a4b92974d8f142fce Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Oct 2021 22:03:39 +0200 Subject: [PATCH 0696/1892] ci: use pytest exclusively --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ebd7e5fad..34fc3d24d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -206,8 +206,8 @@ jobs: - name: Test run: | - pip install numpy scipy pandas networkx - python -m unittest -vvv + pip install numpy scipy pandas networkx pytest + python -m pytest tests - uses: actions/upload-artifact@v2 with: From 47bbe4a4be0a7625ffb58a4be93b90680125de84 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Oct 2021 22:10:06 +0200 Subject: [PATCH 0697/1892] chore: bumped version to 0.9.8 --- CHANGELOG.md | 8 ++++++++ doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d6851f34..83715dd40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## [0.9.8] +### Changed + +- `python-igraph` is now simply `igraph` on PyPI. `python-igraph` will be + updated until Sep 1, 2022 but it will only be a stub package that pulls in + `igraph` as its only dependency, with a matching version number. Please + update your projects to depend on `igraph` instead of `python-igraph` to + keep on receiving updates after Sep 1, 2022. + ### Fixed - `setup.py` no longer uses `distutils`, thanks to diff --git a/doc/source/conf.py b/doc/source/conf.py index f2c503a29..4aa58a76e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.7' +version = '0.9.8' # The full version, including alpha/beta/rc tags. -release = '0.9.7' +release = '0.9.8' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 752360a77..543a50026 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 7) +__version_info__ = (0, 9, 8) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 0c5478c937c333db0801ca8691d28e9768f73f1b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 2 Nov 2021 19:38:08 +0100 Subject: [PATCH 0698/1892] Issue #452: Convert five statements to the usage of augmented assignments Augmented assignment statements became available with Python 2. https://docs.python.org/3/whatsnew/2.0.html#augmented-assignment Thus improve five source code places accordingly. Signed-off-by: Markus Elfring --- src/igraph/__init__.py | 8 ++++---- src/igraph/layout.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 96f7de493..65f44c4ee 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2649,8 +2649,8 @@ def write_svg( x2 = layout[vidxs[1]][0] y2 = layout[vidxs[1]][1] angle = math.atan2(y2 - y1, x2 - x1) - x2 = x2 - vertex_size * math.cos(angle) - y2 = y2 - vertex_size * math.sin(angle) + x2 -= vertex_size * math.cos(angle) + y2 -= vertex_size * math.sin(angle) print(" Date: Sat, 30 Oct 2021 10:55:31 +1100 Subject: [PATCH 0699/1892] Fix docstrings for pydoctor --- scripts/mkdoc.sh | 7 +- scripts/patch-pydoctor.sh | 23 +++ scripts/patch_modularized_graph_methods.py | 46 ++++++ scripts/pydoctor-21.2.2.patch | 167 +++++++++++++++++++++ 4 files changed, 242 insertions(+), 1 deletion(-) create mode 100755 scripts/patch-pydoctor.sh create mode 100644 scripts/patch_modularized_graph_methods.py create mode 100644 scripts/pydoctor-21.2.2.patch diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index f5ac87264..c4fa154ac 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -26,6 +26,9 @@ fi PWD=`pwd` +echo "Patch pydoctor until they fix it" +$SCRIPTS_FOLDER/patch-pydoctor.sh ${ROOT_FOLDER} ${SCRIPTS_FOLDER} + echo "Removing existing documentation..." rm -rf "${DOC_API_FOLDER}/html" "${DOC_API_FOLDER}/pdf" @@ -39,9 +42,11 @@ rm -rf "${SITE_PACKAGES_DIR}"/python_igraph*.egg-link echo "Installing igraph in virtualenv..." rm -f dist/*.whl && .venv/bin/python setup.py bdist_wheel && .venv/bin/pip install --force-reinstall dist/*.whl -IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` +echo "Patching modularized Graph methods" +.venv/bin/python3 ${SCRIPTS_FOLDER}/patch_modularized_graph_methods.py echo "Generating HTML documentation..." +IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` "$PYDOCTOR" \ --project-name "igraph" \ --project-url "https://igraph.org/python" \ diff --git a/scripts/patch-pydoctor.sh b/scripts/patch-pydoctor.sh new file mode 100755 index 000000000..d6ff5a4f7 --- /dev/null +++ b/scripts/patch-pydoctor.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Patches PyDoctor to make it suitable to build python-igraph's documentation +# until our patches get upstreamed + +if [ "x$1" = x ]; then + echo "Usage: $0 ROOT_FOLDER PATCH_FOLDER" + exit 1 +fi + +set -e + +ROOT_FOLDER=$1 +PATCH_FOLDER=$(realpath $2) +${ROOT_FOLDER}/.venv/bin/pip uninstall -y pydoctor +${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.2.2 +PYDOCTOR_DIR=`.venv/bin/python -c 'import os,pydoctor;print(os.path.dirname(pydoctor.__file__))'` + +cd "${PYDOCTOR_DIR}" +# patch is confirmed to work with pydoctor 21.2.2 +patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2.patch 2>/dev/null +rm -f deleteme.rej + + diff --git a/scripts/patch_modularized_graph_methods.py b/scripts/patch_modularized_graph_methods.py new file mode 100644 index 000000000..1521f8fa2 --- /dev/null +++ b/scripts/patch_modularized_graph_methods.py @@ -0,0 +1,46 @@ +import os +import sys +import inspect + +import igraph + + +# Get instance and classmethods +g = igraph.Graph() +methods = inspect.getmembers(g, predicate=inspect.ismethod) + +# Get the source code for each method and replace the method name +# in the signature +methodsources = {} +for mname, method in methods: + source = inspect.getsourcelines(method)[0] + fname = source[0][source[0].find('def ') + 4: source[0].find('(')] + newsource = [source[0].replace(fname, mname)] + source[1:] + methodsources[mname] = newsource + +# Make .new file with replacements +newmodule = igraph.__file__ + '.new' +with open(newmodule, 'wt') as fout: + with open(igraph.__file__, 'rt') as f: + for line in f: + for mname in methodsources: + # Catch the methods, excluding factories (e.g. 3d layouts) + if (mname + ' = _' in line) and ('(' not in line): + break + else: + fout.write(line) + continue + + # Method found, substitute + fout.write('\n') + for mline in methodsources[mname]: + # Correct indentation + fout.write(' ' + mline) + +# Move the new file back +with open(igraph.__file__, 'wt') as fout: + with open(newmodule, 'rt') as f: + fout.write(f.read()) + +# Delete .new file +os.remove(newmodule) diff --git a/scripts/pydoctor-21.2.2.patch b/scripts/pydoctor-21.2.2.patch new file mode 100644 index 000000000..15a23623f --- /dev/null +++ b/scripts/pydoctor-21.2.2.patch @@ -0,0 +1,167 @@ +diff --git a/pydoctor/astbuilder.py b/pydoctor/astbuilder.py +index 6b274c9..393ddab 100644 +--- a/pydoctor/astbuilder.py ++++ b/pydoctor/astbuilder.py +@@ -188,7 +188,7 @@ class ModuleVistor(ast.NodeVisitor): + self.newAttr = None + + def visit_Module(self, node: ast.Module) -> None: +- assert self.module.docstring is None ++ # assert self.module.docstring is None + + self.builder.push(self.module, 0) + if len(node.body) > 0 and isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Str): +diff --git a/pydoctor/epydoc2stan.py b/pydoctor/epydoc2stan.py +index 1b418ae..841c773 100644 +--- a/pydoctor/epydoc2stan.py ++++ b/pydoctor/epydoc2stan.py +@@ -191,6 +191,11 @@ class _EpydocLinker(DocstringLinker): + target = src.resolveName(identifier) + if target is not None: + return target ++ if isinstance(src, model.Class): ++ for base in src.allbases(): ++ target = base.resolveName(identifier) ++ if target is not None: ++ return target + src = src.parent + + # Walk up the object tree again and see if 'identifier' refers to an +@@ -528,7 +533,7 @@ class FieldHandler: + + def handleUnknownField(self, field: Field) -> None: + name = field.tag +- field.report(f"Unknown field '{name}'" ) ++ # field.report(f"Unknown field '{name}'" ) + self.unknowns[name].append(FieldDesc(name=field.arg, body=field.format())) + + def handle(self, field: Field) -> None: +diff --git a/pydoctor/model.py b/pydoctor/model.py +index d233639..a14a4df 100644 +--- a/pydoctor/model.py ++++ b/pydoctor/model.py +@@ -14,7 +14,7 @@ import platform + import sys + import types + from enum import Enum +-from inspect import Signature ++from inspect import signature, Signature + from optparse import Values + from pathlib import Path + from typing import ( +@@ -514,7 +514,8 @@ class Function(Inheritable): + is_async: bool + annotations: Mapping[str, Optional[ast.expr]] + decorators: Optional[Sequence[ast.expr]] +- signature: Signature ++ signature: Optional[Signature] ++ text_signature: str = "" + + def setup(self) -> None: + super().setup() +@@ -776,15 +777,24 @@ class System: + + def _introspectThing(self, thing: object, parent: Documentable, parentMod: _ModuleT) -> None: + for k, v in thing.__dict__.items(): +- if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType)) ++ # TODO(ntamas): MethodDescriptorType and ClassMethodDescriptorType are Python 3.7 only. ++ if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType, types.MethodDescriptorType, types.ClassMethodDescriptorType)) + # In PyPy 7.3.1, functions from extensions are not + # instances of the above abstract types. +- or v.__class__.__name__ == 'builtin_function_or_method'): ++ or (hasattr(v, "__class__") and v.__class__.__name__ == 'builtin_function_or_method')): + f = self.Function(self, k, parent) + f.parentMod = parentMod + f.docstring = v.__doc__ + f.decorators = None +- f.signature = Signature() ++ try: ++ f.signature = signature(v) ++ except Exception: ++ f.text_signature = (getattr(v, "__text_signature__") or "") + " (INVALID)" ++ f.signature = None ++ f.is_async = False ++ f.annotations = { ++ name: None for name in (f.signature.parameters if f.signature else {}) ++ } + self.addObject(f) + elif isinstance(v, type): + c = self.Class(self, k, parent) +@@ -912,7 +922,8 @@ class System: + mod.state = ProcessingState.PROCESSED + head = self.processing_modules.pop() + assert head == mod.fullName() +- self.unprocessed_modules.remove(mod) ++ if mod in self.unprocessed_modules: ++ self.unprocessed_modules.remove(mod) + self.progress( + 'process', + self.module_count - len(self.unprocessed_modules), +diff --git a/pydoctor/templatewriter/pages/__init__.py b/pydoctor/templatewriter/pages/__init__.py +index e5f4050..3d326b3 100644 +--- a/pydoctor/templatewriter/pages/__init__.py ++++ b/pydoctor/templatewriter/pages/__init__.py +@@ -49,7 +49,7 @@ def format_decorators(obj: Union[model.Function, model.Attribute]) -> Iterator[A + + def signature(function: model.Function) -> str: + """Return a nicely-formatted source-like function signature.""" +- return str(function.signature) ++ return str(function.signature) if function.signature else function.text_signature or "(...)" + + class DocGetter: + """L{epydoc2stan} bridge.""" +diff --git a/pydoctor/templates/common.html b/pydoctor/templates/common.html +index e5f4050..3d326b3 100644 +--- a/pydoctor/templates/common.html ++++ b/pydoctor/templates/common.html +@@ -63,7 +63,7 @@ +

    +
    + API Documentation for Some +- Project, generated by pydoctor at some time. ++ Project, generated by pydoctor . +
    + +
    +diff --git a/pydoctor/templatewriter/summary.py b/pydoctor/templatewriter/summary.py +index e5f4050..3d326b3 100644 +--- a/pydoctor/templatewriter/summary.py ++++ b/pydoctor/templatewriter/summary.py +@@ -22,7 +22,7 @@ + return r + ul = tags.ul() + for m in sorted(contents, key=lambda m:m.fullName()): +- ul(moduleSummary(m, page_url)) ++ ul(moduleSummary(m, page_url), "\n") + return r(ul) + + def _lckey(x): +@@ -45,6 +45,7 @@ + r = [] + for o in self.system.rootobjects: + r.append(moduleSummary(o, self.filename)) ++ r.append("\n") + return tag.clear()(r) + @renderer + def heading(self, request, tag): +@@ -105,7 +106,7 @@ + if len(scs) > 0: + ul = tags.ul() + for sc in sorted(scs, key=_lckey): +- ul(subclassesFrom(hostsystem, sc, anchors, page_url)) ++ ul(subclassesFrom(hostsystem, sc, anchors, page_url), "\n") + r(ul) + return r + +@@ -136,9 +137,10 @@ + if o: + ul = tags.ul() + for sc in sorted(o, key=_lckey): +- ul(subclassesFrom(self.system, sc, anchors, self.filename)) ++ ul(subclassesFrom(self.system, sc, anchors, self.filename), "\n") + item(ul) + t(item) ++ t("\n") + return t + + @renderer From 8587c9ada4ce461d70d3c73615450393da312ec1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 18:32:38 +0100 Subject: [PATCH 0700/1892] fix: fix Read_GraphMLz function by removing 'directed' argument, closes #454 --- src/_igraph/graphobject.c | 2 +- src/igraph/__init__.py | 4 +- tests/test_foreign.py | 108 ++++++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 4b797c98f..388064a8c 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -15172,7 +15172,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_graphml */ {"Read_GraphML", (PyCFunction) igraphmodule_Graph_Read_GraphML, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_GraphML(f, directed=True, index=0)\n--\n\n" + "Read_GraphML(f, index=0)\n--\n\n" "Reads a GraphML format file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n" "@param index: if the GraphML file contains multiple graphs,\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 65f44c4ee..7f616ef1f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -2300,7 +2300,7 @@ def Read_DIMACS(cls, f, directed=False): return graph @classmethod - def Read_GraphMLz(cls, f, directed=True, index=0): + def Read_GraphMLz(cls, f, index=0): """Reads a graph from a zipped GraphML file. @param f: the name of the file @@ -2312,7 +2312,7 @@ def Read_GraphMLz(cls, f, directed=True, index=0): with named_temporary_file() as tmpfile: with open(tmpfile, "wb") as outf: copyfileobj(gzip.GzipFile(f, "rb"), outf) - return cls.Read_GraphML(tmpfile, directed=directed, index=index) + return cls.Read_GraphML(tmpfile, index=index) def write_pickle(self, fname=None, version=-1): """Saves the graph in Python pickled format diff --git a/tests/test_foreign.py b/tests/test_foreign.py index df45281bb..cb0cf3e60 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -1,3 +1,4 @@ +import gzip import io import unittest import warnings @@ -22,6 +23,51 @@ pd = None +GRAPHML_EXAMPLE_FILE = """\ + + + + + + + a + + + b + + + c + + + d + + + e + + + f + + + + + + + + + + + + + + + + + +""" + class ForeignTests(unittest.TestCase): def testDIMACS(self): with temporary_file( @@ -302,52 +348,7 @@ def testAdjacency(self): g.write_adjacency(tmpfname) def testGraphML(self): - with temporary_file( - """\ - - - - - - - a - - - b - - - c - - - d - - - e - - - f - - - - - - - - - - - - - - - - - - """ - ) as tmpfname: + with temporary_file(GRAPHML_EXAMPLE_FILE) as tmpfname: try: g = Graph.Read_GraphML(tmpfname) except NotImplementedError as e: @@ -361,6 +362,21 @@ def testGraphML(self): g.write_graphml(tmpfname) + def testGraphMLz(self): + with temporary_file(gzip.compress(GRAPHML_EXAMPLE_FILE.encode("utf-8"))) as tmpfname: + try: + g = Graph.Read_GraphMLz(tmpfname) + except NotImplementedError as e: + self.skipTest(str(e)) + + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(g.vcount(), 6) + self.assertEqual(g.ecount(), 7) + self.assertFalse(g.is_directed()) + self.assertTrue("name" in g.vertex_attributes()) + + g.write_graphmlz(tmpfname) + def testPickle(self): pickle = [ 128, From 6fc5a29a18da6516b90f1ed46d425638ea513af9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 18:54:37 +0100 Subject: [PATCH 0701/1892] fix: fix failing test case on Windows x64 --- tests/test_foreign.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_foreign.py b/tests/test_foreign.py index cb0cf3e60..6359ccb7b 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -375,8 +375,6 @@ def testGraphMLz(self): self.assertFalse(g.is_directed()) self.assertTrue("name" in g.vertex_attributes()) - g.write_graphmlz(tmpfname) - def testPickle(self): pickle = [ 128, From 46ed90e518028653a73c93c5a527ac4e90f9368f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 19:23:15 +0100 Subject: [PATCH 0702/1892] fix: fix failing test case on Windows x64, hopefully it works this time --- tests/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/utils.py b/tests/utils.py index fdea66dba..c4158416b 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -30,7 +30,13 @@ def temporary_file(content=None, mode=None, binary=False): tmpf.close() yield tmpfname - os.unlink(tmpfname) + try: + os.unlink(tmpfname) + except Exception: + # ignore exceptions; it happens sometimes on Windows in the CI environment + # that it cannot remove the temporary file because another process (?) is + # using it... + pass is_pypy = platform.python_implementation() == "PyPy" From e72c4ca609181a507a9a98096b4e435184eae5e5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 19:32:56 +0100 Subject: [PATCH 0703/1892] chore: reformatted test.sh --- test.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test.sh b/test.sh index b3e124265..7604b5582 100755 --- a/test.sh +++ b/test.sh @@ -17,11 +17,11 @@ while getopts ":ce:k:" OPTION; do CLEAN=1 ;; e) - VENV_DIR=$OPTARG + VENV_DIR=$OPTARG + ;; + k) + PYTEST_ARGS="${PYTEST_ARGS} -k $OPTARG" ;; - k) - PYTEST_ARGS="${PYTEST_ARGS} -k $OPTARG" - ;; \?) echo "Usage: $0 [-c]" ;; From d1e86d573cb001362d24b1d88fc702ee74cd6c17 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 18:32:38 +0100 Subject: [PATCH 0704/1892] fix: fix Read_GraphMLz function by removing 'directed' argument, closes #454 --- src/_igraph/graphobject.c | 2 +- tests/test_foreign.py | 108 ++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 47 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3f8758d3c..51bddd737 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -15282,7 +15282,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_read_graph_graphml */ {"Read_GraphML", (PyCFunction) igraphmodule_Graph_Read_GraphML, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - "Read_GraphML(f, directed=True, index=0)\n--\n\n" + "Read_GraphML(f, index=0)\n--\n\n" "Reads a GraphML format file and creates a graph based on it.\n\n" "@param f: the name of the file or a Python file handle\n" "@param index: if the GraphML file contains multiple graphs,\n" diff --git a/tests/test_foreign.py b/tests/test_foreign.py index c4c77978d..3640110e5 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -1,3 +1,4 @@ +import gzip import io import unittest import warnings @@ -22,6 +23,51 @@ pd = None +GRAPHML_EXAMPLE_FILE = """\ + + + + + + + a + + + b + + + c + + + d + + + e + + + f + + + + + + + + + + + + + + + + + +""" + class ForeignTests(unittest.TestCase): def testDIMACS(self): with temporary_file( @@ -299,52 +345,7 @@ def testAdjacency(self): g.write_adjacency(tmpfname) def testGraphML(self): - with temporary_file( - """\ - - - - - - - a - - - b - - - c - - - d - - - e - - - f - - - - - - - - - - - - - - - - - - """ - ) as tmpfname: + with temporary_file(GRAPHML_EXAMPLE_FILE) as tmpfname: try: g = Graph.Read_GraphML(tmpfname) except NotImplementedError as e: @@ -358,6 +359,21 @@ def testGraphML(self): g.write_graphml(tmpfname) + def testGraphMLz(self): + with temporary_file(gzip.compress(GRAPHML_EXAMPLE_FILE.encode("utf-8"))) as tmpfname: + try: + g = Graph.Read_GraphMLz(tmpfname) + except NotImplementedError as e: + self.skipTest(str(e)) + + self.assertTrue(isinstance(g, Graph)) + self.assertEqual(g.vcount(), 6) + self.assertEqual(g.ecount(), 7) + self.assertFalse(g.is_directed()) + self.assertTrue("name" in g.vertex_attributes()) + + g.write_graphmlz(tmpfname) + def testPickle(self): pickle = [ 128, From cf8213d9b2a8520e2fbd82ec587c31bb2551c290 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 18:54:37 +0100 Subject: [PATCH 0705/1892] fix: fix failing test case on Windows x64 --- tests/test_foreign.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 3640110e5..5e117179a 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -372,8 +372,6 @@ def testGraphMLz(self): self.assertFalse(g.is_directed()) self.assertTrue("name" in g.vertex_attributes()) - g.write_graphmlz(tmpfname) - def testPickle(self): pickle = [ 128, From 8d1ae5493007092367c6a30e059afa7ea3fa63fe Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 19:23:15 +0100 Subject: [PATCH 0706/1892] fix: fix failing test case on Windows x64, hopefully it works this time --- tests/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/utils.py b/tests/utils.py index fdea66dba..c4158416b 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -30,7 +30,13 @@ def temporary_file(content=None, mode=None, binary=False): tmpf.close() yield tmpfname - os.unlink(tmpfname) + try: + os.unlink(tmpfname) + except Exception: + # ignore exceptions; it happens sometimes on Windows in the CI environment + # that it cannot remove the temporary file because another process (?) is + # using it... + pass is_pypy = platform.python_implementation() == "PyPy" From c149b16663b6f8a5c1e7eedd690aacbc70244702 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 3 Nov 2021 19:56:41 +0100 Subject: [PATCH 0707/1892] fix: fix incorrect merge --- src/igraph/io/files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/io/files.py b/src/igraph/io/files.py index a39ae438f..64c70c4d2 100644 --- a/src/igraph/io/files.py +++ b/src/igraph/io/files.py @@ -174,7 +174,7 @@ def _construct_graph_from_dimacs_file(cls, f, directed=False): return graph -def _construct_graph_from_graphmlz_file(cls, f, directed=True, index=0): +def _construct_graph_from_graphmlz_file(cls, f, index=0): """Reads a graph from a zipped GraphML file. @param f: the name of the file @@ -186,7 +186,7 @@ def _construct_graph_from_graphmlz_file(cls, f, directed=True, index=0): with named_temporary_file() as tmpfile: with open(tmpfile, "wb") as outf: copyfileobj(gzip.GzipFile(f, "rb"), outf) - return cls.Read_GraphML(tmpfile, directed=directed, index=index) + return cls.Read_GraphML(tmpfile, index=index) def _construct_graph_from_pickle_file(cls, fname=None): From 29248d26b16e3bd0b99d2cd04ba4b86599f98340 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 5 Nov 2021 10:26:50 +0100 Subject: [PATCH 0708/1892] fix: replace obsolete DrL layout URL --- doc/source/tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 57e972502..86a29a4a4 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -727,7 +727,7 @@ Method name Short name Algorithm description ``circular_3d`` ==================================== =============== ============================================= -.. _Distributed Recursive Layout: http://www.cs.sandia.gov/~smartin/software.html +.. _Distributed Recursive Layout: https://www.osti.gov/doecode/biblio/54626 .. _Large Graph Layout: http://sourceforge.net/projects/lgl/ Layout algorithms can either be called directly or using the common layout method called From 7f3cd5a41e2de3d8a4fe356249db1d0c21b82acc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 9 Nov 2021 10:29:04 +0100 Subject: [PATCH 0709/1892] fix: further tweak the text of an error message to make it clear that node IDs must be integers (floats are not okay, even if they are integral), refs #42 --- src/_igraph/convert.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 80fe02a8d..a33d8f40b 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2511,7 +2511,7 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g } else return 1; } else { - PyErr_SetString(PyExc_TypeError, "only numbers, strings or igraph.Vertex objects can be converted to vertex IDs"); + PyErr_SetString(PyExc_TypeError, "only non-negative integers, strings or igraph.Vertex objects can be converted to vertex IDs"); return 1; } @@ -2756,7 +2756,7 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g } } else { PyErr_SetString(PyExc_TypeError, - "only numbers, igraph.Edge objects or tuples of vertex IDs can be " + "only non-negative integers, igraph.Edge objects or tuples of vertex IDs can be " "converted to edge IDs"); return 1; } From 6c03726af49639af16a8eede97ad9ebb01c48cc1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 9 Nov 2021 15:36:40 +0100 Subject: [PATCH 0710/1892] chore: upgraded vendored igraph to almost-0.9.5 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b29e741ea..4459083d8 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b29e741ea4106b259318d1d1d37404d317b2a185 +Subproject commit 4459083d848baf7da637955e904132600273db09 From 0316fdda50155400df280427b8ae9f5b2ad0f9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Tue, 9 Nov 2021 22:01:27 +0100 Subject: [PATCH 0711/1892] docs: update Reingold-Tilford documentation --- src/_igraph/graphobject.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 388064a8c..0de916250 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14958,11 +14958,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " This parameter also influences how the root vertices are calculated\n" " if they are not given. See the I{root} parameter.\n" "@param root: the index of the root vertex or root vertices.\n" - " if this is a non-empty vector then the supplied vertex IDs are\n" + " If this is a non-empty vector then the supplied vertex IDs are\n" " used as the roots of the trees (or a single tree if the graph is\n" - " connected. If this is C{None} or an empty list, the root vertices\n" - " are automatically calculated based on topological sorting,\n" - " performed with the opposite of the I{mode} argument.\n" + " connected). If this is C{None} or an empty list, the root vertices\n" + " are automatically calculated in such a way so that all other vertices\n" + " would be reachable from them. Currently, automatic root selection\n" + " prefers low eccentricity vertices in small graphs (fewer than 500\n" + " vertices) and high degree vertices in large graphs. This heuristic\n" + " may change in future versions. Specify roots manually for a consistent\n" + " output.\n" "@param rootlevel: this argument is useful when drawing forests which are\n" " not trees. It specifies the level of the root vertices for every tree\n" " in the forest.\n" From d51040e5015019cd8a30c078826af8464c545992 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Nov 2021 09:29:55 +0100 Subject: [PATCH 0712/1892] fix: porting PyDoctor patch over to the master branch so we can test the Dash docset --- scripts/mkdoc.sh | 3 + scripts/patch-pydoctor.sh | 23 +++++ scripts/pydoctor-21.2.2.patch | 167 ++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100755 scripts/patch-pydoctor.sh create mode 100644 scripts/pydoctor-21.2.2.patch diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index f5ac87264..ebb340588 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -26,6 +26,9 @@ fi PWD=`pwd` +echo "Patching PyDoctor..." +$SCRIPTS_FOLDER/patch-pydoctor.sh ${ROOT_FOLDER} ${SCRIPTS_FOLDER} + echo "Removing existing documentation..." rm -rf "${DOC_API_FOLDER}/html" "${DOC_API_FOLDER}/pdf" diff --git a/scripts/patch-pydoctor.sh b/scripts/patch-pydoctor.sh new file mode 100755 index 000000000..d6ff5a4f7 --- /dev/null +++ b/scripts/patch-pydoctor.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Patches PyDoctor to make it suitable to build python-igraph's documentation +# until our patches get upstreamed + +if [ "x$1" = x ]; then + echo "Usage: $0 ROOT_FOLDER PATCH_FOLDER" + exit 1 +fi + +set -e + +ROOT_FOLDER=$1 +PATCH_FOLDER=$(realpath $2) +${ROOT_FOLDER}/.venv/bin/pip uninstall -y pydoctor +${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.2.2 +PYDOCTOR_DIR=`.venv/bin/python -c 'import os,pydoctor;print(os.path.dirname(pydoctor.__file__))'` + +cd "${PYDOCTOR_DIR}" +# patch is confirmed to work with pydoctor 21.2.2 +patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2.patch 2>/dev/null +rm -f deleteme.rej + + diff --git a/scripts/pydoctor-21.2.2.patch b/scripts/pydoctor-21.2.2.patch new file mode 100644 index 000000000..15a23623f --- /dev/null +++ b/scripts/pydoctor-21.2.2.patch @@ -0,0 +1,167 @@ +diff --git a/pydoctor/astbuilder.py b/pydoctor/astbuilder.py +index 6b274c9..393ddab 100644 +--- a/pydoctor/astbuilder.py ++++ b/pydoctor/astbuilder.py +@@ -188,7 +188,7 @@ class ModuleVistor(ast.NodeVisitor): + self.newAttr = None + + def visit_Module(self, node: ast.Module) -> None: +- assert self.module.docstring is None ++ # assert self.module.docstring is None + + self.builder.push(self.module, 0) + if len(node.body) > 0 and isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Str): +diff --git a/pydoctor/epydoc2stan.py b/pydoctor/epydoc2stan.py +index 1b418ae..841c773 100644 +--- a/pydoctor/epydoc2stan.py ++++ b/pydoctor/epydoc2stan.py +@@ -191,6 +191,11 @@ class _EpydocLinker(DocstringLinker): + target = src.resolveName(identifier) + if target is not None: + return target ++ if isinstance(src, model.Class): ++ for base in src.allbases(): ++ target = base.resolveName(identifier) ++ if target is not None: ++ return target + src = src.parent + + # Walk up the object tree again and see if 'identifier' refers to an +@@ -528,7 +533,7 @@ class FieldHandler: + + def handleUnknownField(self, field: Field) -> None: + name = field.tag +- field.report(f"Unknown field '{name}'" ) ++ # field.report(f"Unknown field '{name}'" ) + self.unknowns[name].append(FieldDesc(name=field.arg, body=field.format())) + + def handle(self, field: Field) -> None: +diff --git a/pydoctor/model.py b/pydoctor/model.py +index d233639..a14a4df 100644 +--- a/pydoctor/model.py ++++ b/pydoctor/model.py +@@ -14,7 +14,7 @@ import platform + import sys + import types + from enum import Enum +-from inspect import Signature ++from inspect import signature, Signature + from optparse import Values + from pathlib import Path + from typing import ( +@@ -514,7 +514,8 @@ class Function(Inheritable): + is_async: bool + annotations: Mapping[str, Optional[ast.expr]] + decorators: Optional[Sequence[ast.expr]] +- signature: Signature ++ signature: Optional[Signature] ++ text_signature: str = "" + + def setup(self) -> None: + super().setup() +@@ -776,15 +777,24 @@ class System: + + def _introspectThing(self, thing: object, parent: Documentable, parentMod: _ModuleT) -> None: + for k, v in thing.__dict__.items(): +- if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType)) ++ # TODO(ntamas): MethodDescriptorType and ClassMethodDescriptorType are Python 3.7 only. ++ if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType, types.MethodDescriptorType, types.ClassMethodDescriptorType)) + # In PyPy 7.3.1, functions from extensions are not + # instances of the above abstract types. +- or v.__class__.__name__ == 'builtin_function_or_method'): ++ or (hasattr(v, "__class__") and v.__class__.__name__ == 'builtin_function_or_method')): + f = self.Function(self, k, parent) + f.parentMod = parentMod + f.docstring = v.__doc__ + f.decorators = None +- f.signature = Signature() ++ try: ++ f.signature = signature(v) ++ except Exception: ++ f.text_signature = (getattr(v, "__text_signature__") or "") + " (INVALID)" ++ f.signature = None ++ f.is_async = False ++ f.annotations = { ++ name: None for name in (f.signature.parameters if f.signature else {}) ++ } + self.addObject(f) + elif isinstance(v, type): + c = self.Class(self, k, parent) +@@ -912,7 +922,8 @@ class System: + mod.state = ProcessingState.PROCESSED + head = self.processing_modules.pop() + assert head == mod.fullName() +- self.unprocessed_modules.remove(mod) ++ if mod in self.unprocessed_modules: ++ self.unprocessed_modules.remove(mod) + self.progress( + 'process', + self.module_count - len(self.unprocessed_modules), +diff --git a/pydoctor/templatewriter/pages/__init__.py b/pydoctor/templatewriter/pages/__init__.py +index e5f4050..3d326b3 100644 +--- a/pydoctor/templatewriter/pages/__init__.py ++++ b/pydoctor/templatewriter/pages/__init__.py +@@ -49,7 +49,7 @@ def format_decorators(obj: Union[model.Function, model.Attribute]) -> Iterator[A + + def signature(function: model.Function) -> str: + """Return a nicely-formatted source-like function signature.""" +- return str(function.signature) ++ return str(function.signature) if function.signature else function.text_signature or "(...)" + + class DocGetter: + """L{epydoc2stan} bridge.""" +diff --git a/pydoctor/templates/common.html b/pydoctor/templates/common.html +index e5f4050..3d326b3 100644 +--- a/pydoctor/templates/common.html ++++ b/pydoctor/templates/common.html +@@ -63,7 +63,7 @@ +
    +
    + API Documentation for Some +- Project, generated by pydoctor at some time. ++ Project, generated by pydoctor . +
    + +
    +diff --git a/pydoctor/templatewriter/summary.py b/pydoctor/templatewriter/summary.py +index e5f4050..3d326b3 100644 +--- a/pydoctor/templatewriter/summary.py ++++ b/pydoctor/templatewriter/summary.py +@@ -22,7 +22,7 @@ + return r + ul = tags.ul() + for m in sorted(contents, key=lambda m:m.fullName()): +- ul(moduleSummary(m, page_url)) ++ ul(moduleSummary(m, page_url), "\n") + return r(ul) + + def _lckey(x): +@@ -45,6 +45,7 @@ + r = [] + for o in self.system.rootobjects: + r.append(moduleSummary(o, self.filename)) ++ r.append("\n") + return tag.clear()(r) + @renderer + def heading(self, request, tag): +@@ -105,7 +106,7 @@ + if len(scs) > 0: + ul = tags.ul() + for sc in sorted(scs, key=_lckey): +- ul(subclassesFrom(hostsystem, sc, anchors, page_url)) ++ ul(subclassesFrom(hostsystem, sc, anchors, page_url), "\n") + r(ul) + return r + +@@ -136,9 +137,10 @@ + if o: + ul = tags.ul() + for sc in sorted(o, key=_lckey): +- ul(subclassesFrom(self.system, sc, anchors, self.filename)) ++ ul(subclassesFrom(self.system, sc, anchors, self.filename), "\n") + item(ul) + t(item) ++ t("\n") + return t + + @renderer From 66711348f90cc322da0b03e3104157f31e99c41d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 11 Nov 2021 21:19:50 +0100 Subject: [PATCH 0713/1892] chore: updated vendored igraph to 0.9.5 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 4459083d8..8bb3224ab 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 4459083d848baf7da637955e904132600273db09 +Subproject commit 8bb3224ab3cfb71bacb0621412d3d43b61a5d676 From c6794ca8ece71fcceb12a1fbd7cf19af9477704b Mon Sep 17 00:00:00 2001 From: Sriram-Pattabiraman <59712515+Sriram-Pattabiraman@users.noreply.github.com> Date: Sat, 13 Nov 2021 11:41:53 -0600 Subject: [PATCH 0714/1892] Changed get_label_position func to account for edge curvature get_label_position now computes the bezier curve for the edge that would be drawn, then finds the parameter based midpoint by putting `.5` as the parameter and taking the output as the label position. --- src/igraph/drawing/edge.py | 40 ++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 605b2df5c..88cc1909e 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -158,11 +158,43 @@ def get_label_position(self, edge, src_vertex, dest_vertex): else: angle = None + + def bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t): + """Computes the Bezier curve from point (x0,y0) to (x3,y3) + via control points (x1,y1) and (x2,y2) with parameter t. + """ + xt = ( + (1.0 - t) ** 3 * x0 + + 3.0 * t * (1.0 - t) ** 2 * x1 + + 3.0 * t ** 2 * (1.0 - t) * x2 + + t ** 3 * x3 + ) + yt = ( + (1.0 - t) ** 3 * y0 + + 3.0 * t * (1.0 - t) ** 2 * y1 + + 3.0 * t ** 2 * (1.0 - t) * y2 + + t ** 3 * y3 + ) + return xt, yt + # Determine the midpoint - pos = ( - (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, - (src_vertex.position[1] + dest_vertex.position[1]) / 2, - ) + if edge['curved']: + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + aux1 = (2 * x1 + x2) / 3.0 - edge['curved'] * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + edge['curved'] * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - edge['curved'] * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + edge['curved'] * 0.5 * (x2 - x1) + + + pos = bezier_cubic(x1, y1, *aux1, *aux2, x2, y2, .5) + + else: + pos = ( + (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, + (src_vertex.position[1] + dest_vertex.position[1]) / 2, + ) # Determine the alignment based on the angle pi4 = pi / 4 From 19ee0490962fd2db204f2203fb45205f7b347169 Mon Sep 17 00:00:00 2001 From: Sriram-Pattabiraman <59712515+Sriram-Pattabiraman@users.noreply.github.com> Date: Tue, 16 Nov 2021 13:24:33 -0600 Subject: [PATCH 0715/1892] refactored to Bezier curve control point function Previously, the code for calculating the bezier control points was repeated multiple times. Now, there is a function to calculate bezier curve control points accordingly using the start point, the end point, and the edge curvature in a function called get_bezier_control_points_for_curved_edge --- src/igraph/drawing/edge.py | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 88cc1909e..294e540fa 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -19,6 +19,16 @@ cairo = find_cairo() +def get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, curvature): + aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) + + aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) + + return aux1, aux2 class AbstractEdgeDrawer: """Abstract edge drawer object from which all concrete edge drawer @@ -120,12 +130,9 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + + aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge['curved']) + ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], *dest_vertex.position) else: ctx.line_to(*dest_vertex.position) @@ -180,13 +187,8 @@ def bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t): # Determine the midpoint if edge['curved']: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1 = (2 * x1 + x2) / 3.0 - edge['curved'] * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + edge['curved'] * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - edge['curved'] * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + edge['curved'] * 0.5 * (x2 - x1) + aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge['curved']) pos = bezier_cubic(x1, y1, *aux1, *aux2, x2, y2, .5) @@ -305,12 +307,7 @@ def intersect_bezier_circle( if edge.curved: # Calculate the curve - aux1 = (2 * x1 + x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - edge.curved * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + edge.curved * 0.5 * (x2 - x1) + aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, x2, y1, y2, edge.curved) # Coordinates of the control points of the Bezier curve xc1, yc1 = aux1 From f12cd47979f6e7399783703df32519cf5c58b054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 17 Nov 2021 11:56:57 +0100 Subject: [PATCH 0716/1892] fix: fixed indentation and added docstring for get_bezier_control_points_for_curved_edge() --- src/igraph/drawing/edge.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index 294e540fa..fc41b7b2d 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -20,15 +20,18 @@ cairo = find_cairo() def get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, curvature): - aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) + """Helper function that calculates the Bezier control points for a + curved edge that goes from (x1, y1) to (x2, y2). + """ + aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) - aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) + aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) - return aux1, aux2 + return aux1, aux2 class AbstractEdgeDrawer: """Abstract edge drawer object from which all concrete edge drawer From 9bbc594876ddee545bb021e83bc0135195e00266 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Nov 2021 12:12:15 +0100 Subject: [PATCH 0717/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 24b6ef417..63a49e749 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 24b6ef417a2929a7b3bc2e95d9bd792213a80134 +Subproject commit 63a49e74932a73b00ae4b58d2af7721e4fc82636 From 9eb7a4299a613381ff7f0213cbc9acd15c5492c2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Nov 2021 15:15:03 +0100 Subject: [PATCH 0718/1892] refactor: move Bezier curve related stuff to igraph.drawing.utils --- src/igraph/drawing/edge.py | 39 ++----------------------------------- src/igraph/drawing/utils.py | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/igraph/drawing/edge.py b/src/igraph/drawing/edge.py index fc41b7b2d..b72f1f4a3 100644 --- a/src/igraph/drawing/edge.py +++ b/src/igraph/drawing/edge.py @@ -14,25 +14,11 @@ from igraph.drawing.colors import clamp from igraph.drawing.metamagic import AttributeCollectorBase from igraph.drawing.text import TextAlignment -from igraph.drawing.utils import find_cairo +from igraph.drawing.utils import evaluate_cubic_bezier_curve, find_cairo, get_bezier_control_points_for_curved_edge from math import atan2, cos, pi, sin, sqrt cairo = find_cairo() -def get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, curvature): - """Helper function that calculates the Bezier control points for a - curved edge that goes from (x1, y1) to (x2, y2). - """ - aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) - - aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) - - return aux1, aux2 - class AbstractEdgeDrawer: """Abstract edge drawer object from which all concrete edge drawer implementations are derived.""" @@ -169,32 +155,11 @@ def get_label_position(self, edge, src_vertex, dest_vertex): angle = None - def bezier_cubic(x0, y0, x1, y1, x2, y2, x3, y3, t): - """Computes the Bezier curve from point (x0,y0) to (x3,y3) - via control points (x1,y1) and (x2,y2) with parameter t. - """ - xt = ( - (1.0 - t) ** 3 * x0 - + 3.0 * t * (1.0 - t) ** 2 * x1 - + 3.0 * t ** 2 * (1.0 - t) * x2 - + t ** 3 * x3 - ) - yt = ( - (1.0 - t) ** 3 * y0 - + 3.0 * t * (1.0 - t) ** 2 * y1 - + 3.0 * t ** 2 * (1.0 - t) * y2 - + t ** 3 * y3 - ) - return xt, yt - # Determine the midpoint if edge['curved']: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge['curved']) - - pos = bezier_cubic(x1, y1, *aux1, *aux2, x2, y2, .5) - + pos = evaluate_cubic_bezier_curve(x1, y1, *aux1, *aux2, x2, y2, .5) else: pos = ( (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index ecf546320..42ce51833 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -599,3 +599,39 @@ def FromPolar(cls, radius, angle): the origin. """ return cls(radius * cos(angle), radius * sin(angle)) + + +def evaluate_cubic_bezier_curve(x0, y0, x1, y1, x2, y2, x3, y3, t): + """Evaluates the Bezier curve from point (x0,y0) to (x3,y3) via control points + (x1,y1) and (x2,y2) with parameter t. + """ + xt = ( + (1.0 - t) ** 3 * x0 + + 3.0 * t * (1.0 - t) ** 2 * x1 + + 3.0 * t ** 2 * (1.0 - t) * x2 + + t ** 3 * x3 + ) + yt = ( + (1.0 - t) ** 3 * y0 + + 3.0 * t * (1.0 - t) ** 2 * y1 + + 3.0 * t ** 2 * (1.0 - t) * y2 + + t ** 3 * y3 + ) + return xt, yt + + +def get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, curvature): + """Helper function that calculates the Bezier control points for a + curved edge that goes from (x1, y1) to (x2, y2). + """ + aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + 2 * y1 + y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) + + aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( + y1 + 2 * y2 + ) / 3.0 + curvature * 0.5 * (x2 - x1) + + return aux1, aux2 + + From 98c9123a6436483227c261b375366aee56d61df3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Nov 2021 15:57:45 +0100 Subject: [PATCH 0719/1892] chore: updated changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83715dd40..ced031e44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- Edge labels now take the curvature of the edge into account, thanks to + [@Sriram-Pattabiraman](https://github.com/Sriram-Pattabiraman). + ([#457](https://github.com/igraph/python-igraph/pull/457)) + ## [0.9.8] ### Changed From 50dc1a477662ba84ce720a5687df2067f99d9b6e Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 20 Nov 2021 00:49:27 +1100 Subject: [PATCH 0720/1892] Add quickstart.rst This is a tutorial file that just gives ~50 lines of code to create a new graph. --- doc/source/tutorial/assets/america.gml | 43 ++++++++++++++++ doc/source/tutorial/figures/america.png | Bin 0 -> 18733 bytes doc/source/tutorial/quickstart.rst | 63 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 doc/source/tutorial/assets/america.gml create mode 100644 doc/source/tutorial/figures/america.png create mode 100644 doc/source/tutorial/quickstart.rst diff --git a/doc/source/tutorial/assets/america.gml b/doc/source/tutorial/assets/america.gml new file mode 100644 index 000000000..a23a3434b --- /dev/null +++ b/doc/source/tutorial/assets/america.gml @@ -0,0 +1,43 @@ +Creator "igraph version 0.9.3 Sun Nov 14 18:16:32 2021" +Version 1 +graph +[ + directed 0 + title "Cities of America" + node + [ + id 0 + name "New York" + population 8622357 + ] + node + [ + id 1 + name "San Francisco" + population 874961 + ] + node + [ + id 2 + name "Los Angeles" + population 4085014 + ] + edge + [ + source 1 + target 0 + distance 4160 + ] + edge + [ + source 2 + target 1 + distance 559 + ] + edge + [ + source 2 + target 0 + distance 3980 + ] +] diff --git a/doc/source/tutorial/figures/america.png b/doc/source/tutorial/figures/america.png new file mode 100644 index 0000000000000000000000000000000000000000..62db60fc800a9691c70f35bd3e699fe55d225e4c GIT binary patch literal 18733 zcmeHvXH-_%w&ej)DGZ=uR=`M7zI}oqVi>ks&MEj6$%4u{{ENd@K}nMnf4OlUyNLh)!)nhVTZZ8_rhnKT%SD*t z7q{3c9<EjS9ExZ{rl*9CMlHT|oTt5b9`JN~#Y zWm#G?HtN_`mDcxy-|<(&zLezT%DxeV!>^yygYH=vX0)YwCNJNzP3d~tNXM6EU%xeX zJdK71TjHXPb1raka;m+*v(~=5aZGl@$!7;QdJH>BnicPZjMQ+E<7`7YH^6-w328Y)zQ&Wm$8vPOZV2#&yJRa?&h{{E>^-Xa&d7LzPd8s zGQ+blOesn$`c89kWa#RB{z9Und$C+?d3n~#CVV*8AAcN((M{A$b2y#R`S-M>3~e9T z{@O_;j}PofG%Ha*b}TGbKgFi(`YeXo{ZeD=z`@h}k&0Sx9WQpP*hd~ZE*x@Cv;C)M zmgmchv;5Z|zr0ddOl<#-3)2hyCCx1ij1o>BXsbxvyZhRb134FFltico%DK(!Xeje|pJQjLeGQmRW&)TUFPgF+OqG!OQ)n3X=cclO-5k}#z?N`;>u zZu5Qc;E7;>lY)$EZ*gmRd{3#K)Mh?RoQ{M?QYF%j8HLWw%dod zO1iy{O?y(iON^V|yBEr7@2SZU)bdHNsM`AR?z$a1afVukhSin<*0;jmyxF6qjym*RghwDD9ZRh~3#EgFR_Id1Y}%WukHEAsMcH@7}&uI*}JpQk~&yIr(s! zLtFRDIjVbn{5PGBnlyFh9v|%(-Ef?0)UmfdK4FF7d+|~J8%;w@iyoQwcYZZ1e;!_u zXzuvM93L6SC*$&1Gg93rZ2P$>!qU>iGi9SueOA=62l@MT+nAdUNJJ{FGOf30QqjF& z=-#8XRzF#7DmR~|zW#&f@$sIv2G5SXvKWcSUl!Hr&SiaV4ZT@E@e&87Rc@raw6D=1(`~@f+OfGV`e!UEfSfk`Gikaym^-uymqJ{ev2!S0*J3!)A_3psoCYtoxvljEuoYf5}@{ zu3S;REfn0-Qa09bbdzQElSqw-YL|x2bKJ6O2(hv5ir%&_Ewz80Gpk65eDL4_B@TYB z#aQ|j!*DG%obp;_zT;l==9({wZ9d_-Ei#{FQ2LiyaZLY5P?&dEBVxanrsi!5_w;n> z_#Zey_Or~I?BU_z1ot6_$y29ByA5f0RtXBeH;Feb z2vJOR`Wdol(-)^Aejny6gRnqHuhRHkf#)XJnKF@0hyQF#TY8dHMKi94|62 zm)creA3&Yqoj*SU)d?ZG*H7F?J1;<{zNsk^rKb75W#-q53mBH$HRh#^uvXM48``*?=2$?O#Lc^R@7BAnW|)3%b{=kT6dRQC#KV8FA2%^EL)k$=JP;`BUibBD z@aV`;OG{i<0~W*Fn#FPws;sIii8GRO?Ax}C~SmV)Sh4Wl4z2zq)JxARPGF(c=pP$ao zbKU#aty=-k4GZ1zo9{k+(6qBl(AU>5&hqqhc5-@bS(90jY#rLw)%78Oi;)lB#r(~? zO8K@L7MtKP;u8Moky-KM0~ODXdg&%v#1P1IHx?)>DXpWIJwKa`vuL2dztMB_ho@b4 zL%=I zZ*O0;*(yj{TDmw|M?B_G{4Nwk6IGNt`4!AfapEonf__FGk?|+;%qo+uE3!PZDv~V4 z`T6;;E?B34j2++n$+Oumy5%AKEHeil&E%7QjG7UNYU;nuF&3{8jLO)AkS_&O_(%ZAL1XZgzQbQ1^X#V-BF)gor10MIo<4(ul-zmut-jQfoBimLU zzkAlKS-Qzq!9-9}?OV)HX102crjI`^g~vre(eIF@NTW8l)!tyCghaq4_UK*qP14${stAXr?vtoqtTt%q*%jMlXU+bEL1v zFD@>wBEdBD?%f5)j~~A$GlyXfDKPAw+2!SjfT6li51(1TVFN-@dISWtxhgG*0uAAR zy8QY16-N*SJMr{iRaFL{F-2uYo-uO-_n)LwL|*8=I2EbvE7DZuSfhonrBg~i${}Di zUqth9(6ght%`Y#_sYrK@r{~_@5+o3#Bs?BpZr4^JNd?48507&LI=eq?$U8YYJTUmx zi=TJt(zPc}oB-^qV)K1V%t~HgUF_@UccNF5VLZGTj&_YpvsV>IsPdow{B(O{WaJ`A zv)eB$Yhv-<<3Nc@c#U7qqF04sES526roPF|-97e8ZY=a@?lsddFHRGn$PPBH(2CVR zgcQq1nA+FBn@bB?vV@IOngeKwB3VRedGB5%BKqyekNd#QZhLuo0Vr zLai644rTOKm=kzAIVBTcTr6dAS7t7w#yN|{dV6`^+Nd7^uKSJLex9dHxim+x865$V z>J|_}(yiaBttP7mHISu%^>p2Qe*C>zV}3AdMqqDid8lEAi}2R1x@aB_WVrNfbRV>P zDCb#CkF#IHTKO&^6opvClxTa0hP*6B)V`D=FO^C%QFA!*J zZ?6T=>>2nGC<D)LM;Q*3bcKGb`Bw*y_Q2j?c!}Q16}k9 zaPy2WPaxhXRWQ3Hw-Of|IP3=QV2R#C%y&@xu9V9qE+nUzE>lJiJc*U(5re?Y+9 zkSR| zy1KeBkCDN*IXOGDqqPuLnudk}RNX;qIBVxgNlEpzebHIG=~O<*@J5@uJ;V}X^pdm( zy6PoOJ}dz6R?>D4p>Fi=$jr>7(;(gs^oztlgN>orHB)SkC!Q=&_y_b$p2{J>`ttlY z`XSOo!BYtREG#T0(2sZ4tl+S)mGun`{s?p{FK8-`Pn>>!Yc7wED1CA$bi;{HC(-v( zdxG{zkic)r7IiOf{!IYmT5;$t?Mf*&^&5}82o{8#X$H+LPO<%w;5J}0Ffh<`RjT@ipC7%)?Hf0O z9z0lrlElgpz~`@5yv%#RPt2hEf6Tjz4A-Pqhcp~*kQ!EWH{>7lZnKrVczWkqdU0T2 zv_o43HS|CVVg^KPvh4`$h?jzNh^$+8;D5?HwUgNSt{KQX`^Nn3zw_<_(Fy!#)b8ti zs9{L$a|uUtXI{I=Rx69Q?FvVYGY23JHr%(gt9vtR#-fdT&>5%~J=&+0;bOn==a>~Is|>O2GLVyENaZ?tG;#p`gOF0ymRJ+K6$bRJ5P*;T}T4S zSMq4zV(NtN-MdHZ2c2+9nxiEc-^pwiTScn9C}6mAJ|b+gPg+{qU|&aET-K;=?sfh$ zqAFm1lc!9HvZ;UP0-ea$-`@;KLu`hbZ20Q(TuI`j($4DlH=R~Ld^l*eYQPgP!)Qbd z+NZKugAItsy2S{0g&YV0=&heLM<-ie29MeKnqO54Sl+ z?e!D$-*DpE@W@C>vh`8wNal+hZp6+=lYTnv_38+^h^yT{bNNNVmG<6QQ=p+L6JBQM zx-TFgfQy@3=g5%|C>Exm1j*v`6K6;$La>+3H*yP3NZ3e0g7DHhdGhfD<}KZ9m5s_| zrHX^0e4ep#jBZqf_T$cLdc|t6Ek_NJxUy&m-u5j8L*m<;Dh7(J%Sq z#6W7;YT2R=#Xll>E<8M3cp?G8gC>A)?V;y8f0NJJTD-3lCy~#I){vqeT7k!4lc0S^ zwE;GC(Z-WE9NH`2&RRDfJDoRtfqvjS#VFi%{hh{?fJ7!phH5T}HvjhWlJefY6v$IS zCbL&)#^_33<(D&rrdNu>s+Hy8o-x#(*7ft}fjxUJ9yxl{*Vp$rlH@!Pn^|q;;Gm7z zro^Of^x-xgC|NpC7ePI{zg-bGgRrq=)+8q(EL`H=L;|9dZbW!5+G_Wh=xuhkJh3;z z*!_XBr|GkSPt3rce@VbA^VV)OEnJCWDJ&$k=Ynw~mWLEk%f_kR;GRG~-;X95CMJ)j z=iETpL5RURc<0UyN1rJyE}qvK$#4nafV#H)7x)p&CdClICxXv~2$BEAGAjl}=)TMx zc{Xf{Jli+)zXhSYNu(f65*zVIH87TB3keCeUkx9Nem8ysfvCPg3_;&Ndv|W2!4}jiMo@TL484#2_0ig5gyF1-`mSvhc~F z_}dVSR_(ph_*O8m7+P07y7cy{G*N_{lx6is@U}T9H)?MnwrWBKNhdan{G)InsrPsO z^`N#~I)M_5hmGVD$^ z+o3h{N@DbMiXv3Y0Dk~G0pR-#ep!74Z*xUr^c``d*x&F+w1%;=BKSLa@b2u{vuXLD zD$OWT^d$B_V%d%hC;Qr~o_}cres{94e3st3+rpuLotrAUWy_(Vz79V$9pK;;$R&{) zyT^uq$blZ2BFy@LILvUcZlakfegs*dfl35o_z3mt?Uyfl!NI}0&yQUKq@eiK^3i91 zv4Q-8E}WO2KMw69X~*-$^wqEel3#QTofWq^w%1);AS92aXD@Xf{+T;LM|Xg}lw#Ww zZR(XJO$&DdWT~G9r$2$Ec%H#hDsO>#n*ROgA6wlA6A1l?K0pL;8ElFud2w0~m0Uzr z^gRmSD1!t^7XS3=lUdQDt4EF;xsBdti){l<0dC&BNkDu>Jo7O^+GgkUx)q25u$n{9 z!=_AM5QOX#LL8Hr4;sR|V8LS%ttbN7B47$$bh9)Pq*F~ZN>iyLb10VdxvPt%qMUy< zpk(+!$K>VZU6~^>(e}-xJ(Skmzkfg0?t5y}eGrS|3ofh_77{-?eTgvX8kAIOYB#9Y#Kb@k=q%;BTCEY$#c1>o448hnyAD!J0jdST z{k}k110>B` zv9*Oxz`F?BB2eRm-=E;454YIv>PY`}4b?nm0{kp9dhT3XvgJsxN>DbUml^O$N=l+? z0rAuna12=_UUsB=ypP!Dzp+3t&@BXbh~`}A2G%2=Y4Yq~@dPSDJcQ1zGXV{xNkIx% zR#7SbcwdUvvjFP}$`;aoa`*3?97u&CKm*g^{-4xvD(u+N(_N(6(o<$s29XchROd>M z%Xf8l=1&k(D74Y|L@*Ozj5d0$o`T){O@E)ChD_~Rg+o;fqTIu9>A&Y5kdHD-`^mxJ z-?=w11ra8+@iMP)$kV41t5&WgAsr1{0c1)D?vKDdOyAsCMsn+K=Ba_hVktCHWigM- zcvM$+42`J~`VQiW=sh(f_Aedz6*#7e>Wo&4cnwP-4i$#jXklSt0$v!rY9FWq?J-_B z@z~qh$4{I<6?QsCXPaY%+{2#F{qMO4&4_Xjy6Cry3(oUl=~jEL%Z(<3K87vb=Fo^8 zav7-i8_zw9%7g!ud$qwJ+04v1lmUMULNyBz zK-`T){=RBgRiG_;n{htFj4D74?QT!&KnI~g+6)D>(yi5R^YT=;Z{H4XQ~JB_t6WD* z*+y+1_VKMryf8Y@P51Zt981)t(*F3d(CO-Q63H88P99~)u4Kzt+1lRvt-}0c?tzhO zK0BhAG1B{ml-cqPXXMcHF;;;{_l@WT!^6T(LV4qwIkVJ@-{UcaBH;<(15BLiRjHjv zE1CN8$g{`TDdOQM19L$Na`{|UXe384yl`P8^g3ZFsj}8cD=S1V!~NIM>oSinUgTW0 zYE=`8x(l>Ang-su!85Q};Mz=v`RxT592_5yf+ZvHrz&D)oi|840;n@37{yUaxUS~np|fMB5c-!?q~b>yo1d>nYB9}p$~WB1 zqpHj+FD51iAu9CS_wO`?TDZZak*3bv+KlJ{~2Wk9Vwz%h)3nTY)l3lTsi>CU$M9&A3~;o)Icm6{k5 z8rt(-JPYT_y%71ungqd29fy7_z8sJ&eE;JkOaTwYX#1|!)21$*CXX~1jQF;Us*aTv zL=lX|NZr~0aBKLi6}uWSGSU8zeEjuk+wXk*$OGYP9&t1Wxzy2f(f;}nr}qvCq$~4|4c{{Z5Spwh7y*9 zd%z?HkD=?1zHUtG$kafoqf%g2EQASfaqGS0Y2%L{t*)+iX^Baq#sZSt4lt&{x?8H$ zLr6m14)hp|gqCloljOYi$0M=hHT^kqvY8%H>WNXGjM6+>PTRMXmHD-7lFrYCCLDn` zGQ*c9RXcotJprng~~K+PNNI%-*&9PC)_ycKHTP zb8H}OLSjMTM034-{(L{Vj9%SO`(kA5M^$U&Bp%-cuSm`8k5X{yy}2@DK!010`>)e8 zTFMnI6i0_&bd*98FM)Hz{ntmSuAZKfyX%hHb=4`odik>Q=jqCHXAPga=H{qqojB0` zwio>TD1}BI1B$5CDD@-^kUE3tdY_lqQJM?gO`pgFXmfkhvk|EPHjE(p;U9 zHhaz->ORqZ8-a+b0}#iV0raDMklwM*ip9>JBhs3EI$q{)1^JuHS`KBU^`g6QftrO` z;|fwCS{dosQN2jwFbgu}Tppgz`(F~iw7HD*l$GG*YDTy+ zA)%R}r5kLG&jYy>RvPng4uI$34PdRMEKUci>`EnSR53}x&j(Sp#>+(=2z_m75eG_+ zxm=Zzhb%D}Mp_=-0)03saUedT($f0Be&p#u7bSHWy!?A?;H$3ahB*JL_nW32ZSSa- zLW=^e2YrbFspA*~k{nL2Plb(wePpOF8pFkkr(bJwU!!r=u(ImpuP#G=ufg;w(X?n6 z1+=oC*jgou@&tS}>3t}?1%M{#4E$B87J!mLR3Fbdsp#41ys*zS|HW``SgMcE4IM@^ z#E`M~d4EL&A{oM!O=)nQVjBU1y&R3{>B{5-KHY6eHO)xo(W2a*8Um!w>94qS5~cgq+8k`!|tb)rBS9^3aJVcgYb&y$FD$j7E_|a zRSLriYG|}-pzI(H+6 zHpWz;2&gz0!)u5vH6^E|>qipUcchs$MHG4df;B4^T58qS_K_@_DuWTCcqoCb>L@E; zrvA^z$EM|E&-KmQw!JSeA9&$9x-DU}(RBoF4-&Oz@JaV`*BAj-$%cY-PVG_oUd74H zUH0bYibNP-FjN?n%G)zKcRZu6e?X@kNsZ#hjoqlHz=4{&Qq)))GP1Xr-fR}3%wsAGYykG7dnlt-MsnW1!EyW!QE08mHAntJ>uv8 z{IjyxpE?;7M3AP@oIvkb?HGSJ7{b^lO=$$E`q;I2$z#Ic`Rf^`!WgQj_G}LK91D62 znIH_6i~<_J;W+F>XRjuZ?B}7dbg;WD{MXoG7Q|DHpWj|lmOulEMiEc?7I~`txrpA2 zCm5-UD7iG;J8?T8z~jsJ8o3P^hhWUO7f)$brP^yju&0d@k6SG3mJDGE?OYhYNB>vH z4yoxoz>H}|OfzK6uTFviXANa$lVDD&Hf2|`^>;l>exx}T8KGn3-V@8mEk5a%Dy$~3 zl3584UD)(6Gs$n0X}#XA@GB{@wThGX!l6XEXjoWSTI#h9s%Ang956A^wMLo4v2m+_ zg$!2^0kuU}u+(Gf>{oto^fuGF@~*!_K@ zDzzi}EsbrPddlZC>DZ>8RJbQIs)+I;M$ z-mLWvhClDY*5X))Md-$xTtye1+5c@?eSJN(nV7iV+v?Ez7@}x(QQK^r>wJOM_$EE* z#kY(XT)uRv0Oaa1LhEE#-CK~Je5k9(d!;KUQJozAM8Em@^TF~{n@FF5EiP>NiWSF! zb38nU@suDvwTHlf8nA^If&q~4!5T2@aDgIMjJan@>ek+lsP??O0)Ue+QTWyHzr>@>sbVbcf=vhV4Fkh4ZQD_DHCMnBVYXriW>>E=uw0d#&XsQMoQykN<}8d(tAqwa_qh~!9g zm*^PLDB$bYug}X*p&^{SJDtYv@Hia=D}dz&N(-TfL6(QX@7_-vD5x2-^N)DJ5N0{j z=8YE;0(u)>ItbwW7>zm2(8<&Vx*Y!_m_@q98$mIn%qRW*PB>xmm{D3_T8i{9Mz;iD z!N=VoMk;Y&A}{d0An5gVbwVpw?nL82O2_5-;ugI-c@=1Zt2f&<=Etn4h6;wEn>l1E zavY!;!Fwvud)CexXo?7gPe~B(Nni%dgU>R9$z@$TP9D&ft-v=z8~cx_ zPqmAL2A~C}X}sXyY!ocg9REG!QKAv@YUR(5e+-y9bvJc}tl|Fe*Dqha>TA4!28aP} zT}q0(cD*x86cG@}Zgr-SFwz?1ncZO7KFI70mqf5Ts?Ai?aatgQlCH};x6y-+Z{czz zfwBCQZou!Ran0VwB7Y+h4LrQ9@$eJ}OGzqt|daAGAAI&?Nd#nVnVFXzPjqNh*3ML0+b_3Hd zfreWQmkB`VUF)T6cXFopUnj57UuP#n_yJ$K1@XktxqdE^>dp8JR^#D64pp^?~>~S0$>w{GJX*8%jcZ&x{R0E z?2R%({(^#ng00S7VekCJ&9)(ZYmz#hs9S>iF&_2o12gI4te^?fupg%aG!R8_EL*mW4xAi;=$Y=z z%pyw^JT%sg`OEMW&RGPC7>!D$EFRFjAB{T>c{1r{Z_21LlGg;G08IllCIMa(`d*OJ zYffii{9|Xj9%3X{qeRb&E;I#$-c9#oJ@}=We3# z@a|~t-1+CbJ8R8*rGxS*cOTK53lkb(UxH(Yq0B(tt;^otw@b{l;0niKz>EZ~)&`Rj zsE)T`A3#@d9Qq{uT#y>}qb~SGM@QpJ73fQ)XQT2#&%c8Qfjv+k<;XlmmMxdw*2wk8 z-{CNbRg@5I-emEhaYHGwJT7 zu}N?z{8?pD26jQO@h_pD;p&KSRz>S2W|UC8((nHe`Yf0l*_n1-ZS6atk7&w?QNV1b zk|)#mKz6kMC^)7v)B_V$4l9gtnc8a<`c$1=MtDDr>P zuYVi)%m7?l%;bFPDi$vmMYROa_Z8OI1%`&+=* zV{rVwq@)B<#l?xE?OKOE1pN(80uz^J^l0i3(}1H?HYQ3!uL)`d#Zu z>_W{JqTamWqXq=z-?g5(fw#zZhkd#T^BaHygr7(7bx<;1Fn)|-5CUR@>vCq8YI9#L zX2n<>VT^5qH|cTcwxiIvLTLfKF_rW1lp{4&U}%UH==Jx>Y7Cr2^AL%94j9NHdsy3O zz|MvyG3Lyc}?Mh)y4nTK~=$Dv%bq3=KHY11SM0z&Dt2@bw~9 z0iOk%*$9m5&yUrt~&^FVE zVZNc$cGMI&M>gUl#;q{yYqxFF!%Pm}OU(?q=i!}zo}~mxwXy#CehD)ymARf>$m-w4 z`yj|0o!ms3zY&MGrofBu}N$tVGE^-z&V zw_D`Ba0AUN;Xy^El|O@fdv6@^y%_JU2FCz3fQ4M^%$YMZv%uJ`zP%j`ml4Vb)(`CZ z=YWS7=AQ$eY~Jh=BySN#Cys$>3wg?6@c~K5m2xR z*f=`sOc0wVhc^5sHmn@5Luo6Jt%|3{=KupFpxn9@imF4`E1<@Z?+4dPvV*b5e0MS2 zAnbva3a%Ip65!#z?`f~nL%?pp;nvDwPx|UXhR}nd^8~W_K?{SX;_?>N9lQ_Koo=YG zC!0gE)l^sa!Ix^s>PNy~OECvPJ%9#DbDYw%GZsK_tK6AOHVfb&{w3VeGGji968hU5 zm}EaX>`WFyz%m&lFhZTU6T)IK*PPgbs1q8-4EmaOoZ(u09IiNE6V6|_(EQM``T$Z* zD{Rj!1OU@MiH%d9?*9;bAx8Y2>xe{cep?Cg44bl`Sx9`V{-xY_^3*c{w?X zi;6-~Cf_dzMczS^Ns*bwNbKQZ$=@|MGxMqG@T=+2v9*myBhd|VYmWVcf7t<%ewb%D zb4H@LpddIZN@UBm(7{0$n2)2MK2?(qRHZ5Y#fw(>#=|^t3riH#)Wo4@d~3Z#OGl># z*#Rw2-Pt(>5N40bNGiV6>K53!pX8=Z?-qm>7OE#EB)n)mK>PYS_ClJ;-UmXV zpI==ad-*aKzLUgq+`T0K3DQl{wm}7P&Xl1FR|>ehyVKm=dtFpajFzWo79kW?O1=8( z)vw!d>U(jGz`is;U*M=WD%~TxiiA#$y!VNyRPYy-wmCD*H0+pterf5Wt}dH}M@cWi z9M%*=7ZEWrZC%|(yVDs)2hT7mn50&_cE~I|N@HndAG(HlBG6qM?zTWM0s})#mh(8} zYq>ekD{S=`PWE0WA}+3@r+1&mo@Dd`4kI;euxU&dcyZPabMt8I(=qP@J9eCV?Y(eC zV4h%LUIavwR2(@g8vAcv{N)Q>g?qaoG&OZAI(VofiY`szes++hL_{u+?Ppkjoryb` zt@WqEGSYirFQD;ts@2!CxIq=}<1>5iym@f57SMhSn{Wtpit6g>YU=8W9Q9tbc(Ekz z;zH_C#)(2Sr`;G{hG$gehC9!hnVBKb;QFTtHe%;=MS>Cy7hr4qGKY;>z{4T%WFFUf zO(P@mquy}jl$4i8!u>|oADOoZvg-I_=%t?&S5~gcsu9nsiF@>DHRcrNsH?CV5fgXox{T2=<&3})^#OXadE0N#a_27F)^{ZqoeHXzmbaeC^Jkc4%MKix0gmz>t8>PjonWMC5R4&Za)>_d=VA7thyZ^wJ~$>NcMS! zWn^l=>M)Ekv$QOO6a|I43mDaF)YvJ%ug>;$f6=6Z+_oASbL6}8c9TX#^_*6Dvl1w+C*>A>B+~k1YJ{@9%#bQ!ZesIhX@R zCgbm#ybBLSrKRb?A9wrv=KnF$nXFlC7mYZloTJMHb(^oTpJBPUxNO9wCKN?@)YZ^h zQbsVI4BN%`nA)uvk371?NG287YIL6+Ilp@UgGLlpMgr!K_x27BQO}>N{|vlWFIsOR!6*z~uDi`%kFC#@T^sSy@IHiUcpoJz#I2=;G>%V+?=(d_8>A zbiHQMs6WF9xb6HC+w)~bXG=vz1uhb8Je*hd`Lh#}FFaiF*6Mxg*4EF+&G^Th)zd$> zFbu167n2(EE1|f|{*~9z;9$bn#H^OKrS{aPYHEfRcBmAMq$uiUd1UN=u=(c|bDFT= zc&_4GRYp9Mp6>HB- zrNK8{=8}|@Y;J7KpC+D8?Gw^O*@v{)j}NwJz)wStaX23A2NKQA&FNMPeHv~sYJoO> z3Xl<1B8`LuRkUxy5ZZcrFp|u{lq8n>8mr1~^sc7kkGcG@!#gX~L`S~AGLr4(x3+9H z`o&iOLu(K2(Kh3sQmGoZP;8h8^t?0j@(&+Aq{P83zqyn|9~97Ko|;$GS+ zCBEysu?C+o{DA^dVPQKB3=FtX>LKQ>Y$7vnf@x7*kIO10ln#=tS7O_g@gw+ZpD^GK z6&At$57bOd8m^9Fn!~C&v!YgF)6o#SRIR}d(FeS_uU<7_(11(KKk!kj;YtwNx^>V$ zU!fEg={|FPh z&O2SnHoef@@wHJ=4=x|5AuH*oP;9K2voxQ~*zhlOS_QaUw(>rh5m?^U?*sY7kZ0EeuTHCKG zZ2daBeZVL+HI>voCG~y#u99ON*R>6k$`FiFGdq}XI=;7WpG1!V#L|J_23}JcfIOPQ z*}xj8!;%_J09K@ArWK literal 0 HcmV?d00001 diff --git a/doc/source/tutorial/quickstart.rst b/doc/source/tutorial/quickstart.rst new file mode 100644 index 000000000..cabc25eeb --- /dev/null +++ b/doc/source/tutorial/quickstart.rst @@ -0,0 +1,63 @@ +=========== +Quick Start +=========== +This is a short condensed segment aimed at those who want a very quick and dirty rundown on the basics of *igraph*. For a more in depth explanation about what each part of this code is doing, check out `tutorial link.<>`_ + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + # Construct a graph with 3 vertices + n_vertices = 3 + edges = [(0, 1), (1, 2), (2, 0)] + g = ig.Graph(n_vertices, edges) + + # Set attributes for the graph, nodes, and edges + g["title"] = "Cities of America" + g.vs["name"] = ["New York City", "San Francisco", "Los Angeles"] + g.vs["population"] = [8.62e+6, 8.74e+5, 4.08e+6] + g.es["distance"] = [4160, 559, 3980] + + # Set individual attributes + g.vs[2]["name"] = "Chicago" + g.vs[2]["population"] = 2.71e+6 + g.es[1]["distance"] = 2960 + g.es[2]["distance"] = 1180 + + # Plot in matplotlib + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout=g.layout("circle"), # print nodes in a circular layout + vertex_size=10, + vertex_color=["lightblue", "orange", "orange"], + vertex_shape="s", # square + vertex_label=g.vs["name"], + vertex_label_size=8, + ) + # Remove the axes borders + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['bottom'].set_visible(False) + ax.spines['left'].set_visible(False) + ax.get_xaxis().set_ticks([]) + ax.get_yaxis().set_ticks([]) + + plt.show() + + # Save the graph as an image file + fig.savefig('america.png') + fig.savefig('america.jpg') + fig.savefig('america.pdf') + + # Export and import a graph as a GML file. + g.save("america.gml") + g = ig.load("america.gml") + +... and here is the graph generated by the code + +.. figure:: ./figures/america.png + :alt: The visual representation of our city network + :align: center \ No newline at end of file From 5a3a5f8ec62d1184173200e38569861632d78c05 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Nov 2021 15:32:42 +0100 Subject: [PATCH 0721/1892] ci: try to re-enable Python 3.10 tests now that SciPy also has wheels --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34fc3d24d..6627fb0cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,8 +4,6 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - # skip testing on Python 3.10 until SciPy publishes wheels - CIBW_TEST_SKIP: "cp310-*" jobs: build_wheel_linux: From 699f7150081a7e16c477a49607e9367fac08cc8e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Nov 2021 19:26:32 +0100 Subject: [PATCH 0722/1892] ci: update cibuildwheel, skip musllinux wheels for the time being --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6627fb0cb..45d75f6d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" + CIBW_SKIP: "*musllinux*" jobs: build_wheel_linux: @@ -25,7 +26,7 @@ jobs: python-version: '3.8' - name: Build wheels - uses: joerick/cibuildwheel@v2.1.1 + uses: joerick/cibuildwheel@v2.2.2 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" From ca6f675c545d978cf7ad3c888f4213580162214d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Nov 2021 20:06:10 +0100 Subject: [PATCH 0723/1892] ci: move on to manylinux2014 wheels like Pandas (otherwise we cannot test on Python 3.10) --- .github/workflows/build.yml | 5 +++++ setup.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45d75f6d4..2dc74637a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,12 +5,17 @@ env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" CIBW_SKIP: "*musllinux*" + CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" + CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" + CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" + CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" jobs: build_wheel_linux: name: Build wheels on Linux (${{ matrix.wheel_arch }}) runs-on: ubuntu-20.04 strategy: + fail-fast: false matrix: wheel_arch: [x86_64, i686] diff --git a/setup.py b/setup.py index 5f15a6520..86b13d57b 100644 --- a/setup.py +++ b/setup.py @@ -833,7 +833,7 @@ def use_educated_guess(self) -> None: "networkx>=2.5", "pytest>=6.2.5", "numpy>=1.19.0; platform_python_implementation != 'PyPy'", - "pandas>=1.1.0,<1.3.1; platform_python_implementation != 'PyPy'", + "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", ], "doc": [ From a735431a4f7a1b9c27037312e1e9c739ee35a7e4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 19 Nov 2021 21:28:04 +0100 Subject: [PATCH 0724/1892] ci: skip Python 3.10 tests on 32-bit Windows and Linux because there are no SciPy wheels there --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2dc74637a..260901552 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,6 +60,9 @@ jobs: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" + # Skip tests for Python 3.10 because SciPy does not have a 32-bit + # wheel for Linux yet + CIBW_TEST_SKIP: "cp310-manylinux_i686" - uses: actions/upload-artifact@v2 with: @@ -163,6 +166,9 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" + # Skip tests for Python 3.10 because SciPy does not have a 32-bit + # wheel for Python 3.10 yet + CIBW_TEST_SKIP: "cp310-win32" CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ From 666cbe2441026a4ef665339bed48c92c4d4a907b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 20 Nov 2021 00:38:46 +0100 Subject: [PATCH 0725/1892] ci: fix Linux i686 build; CIBW_TEST_SKIP was inserted in the wrong place --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 260901552..de9259cf0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,6 +35,9 @@ jobs: env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" + # Skip tests for Python 3.10 because SciPy does not have a 32-bit + # wheel for Linux yet + CIBW_TEST_SKIP: "cp310-manylinux_i686" - uses: actions/upload-artifact@v2 with: @@ -60,9 +63,6 @@ jobs: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - # Skip tests for Python 3.10 because SciPy does not have a 32-bit - # wheel for Linux yet - CIBW_TEST_SKIP: "cp310-manylinux_i686" - uses: actions/upload-artifact@v2 with: From d3c075c36cc7b0d4417983767864d422aa9b1cda Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 21 Nov 2021 16:03:52 +1100 Subject: [PATCH 0726/1892] Update tutorial for develop branch --- doc/source/tutorial/assets/america.gml | 16 ++++++++-------- doc/source/tutorial/figures/america.png | Bin 18733 -> 16021 bytes doc/source/tutorial/quickstart.rst | 22 +++++++++------------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/doc/source/tutorial/assets/america.gml b/doc/source/tutorial/assets/america.gml index a23a3434b..acf490020 100644 --- a/doc/source/tutorial/assets/america.gml +++ b/doc/source/tutorial/assets/america.gml @@ -1,4 +1,4 @@ -Creator "igraph version 0.9.3 Sun Nov 14 18:16:32 2021" +Creator "igraph version 0.10.0-dev+63a49e74 Sun Nov 21 16:02:47 2021" Version 1 graph [ @@ -7,20 +7,20 @@ graph node [ id 0 - name "New York" - population 8622357 + name "New York City" + population 8620000 ] node [ id 1 name "San Francisco" - population 874961 + population 874000 ] node [ id 2 - name "Los Angeles" - population 4085014 + name "Chicago" + population 2710000 ] edge [ @@ -32,12 +32,12 @@ graph [ source 2 target 1 - distance 559 + distance 2960 ] edge [ source 2 target 0 - distance 3980 + distance 1180 ] ] diff --git a/doc/source/tutorial/figures/america.png b/doc/source/tutorial/figures/america.png index 62db60fc800a9691c70f35bd3e699fe55d225e4c..d86d613dbda293553b139a717c14b4d5d6a4dc3a 100644 GIT binary patch literal 16021 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 literal 18733 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 diff --git a/doc/source/tutorial/quickstart.rst b/doc/source/tutorial/quickstart.rst index cabc25eeb..1b48e1b7d 100644 --- a/doc/source/tutorial/quickstart.rst +++ b/doc/source/tutorial/quickstart.rst @@ -26,24 +26,20 @@ This is a short condensed segment aimed at those who want a very quick and dirty g.es[2]["distance"] = 1180 # Plot in matplotlib - fig, ax = plt.subplots() + fig, ax = plt.subplots(figsize=(5,5)) ig.plot( g, target=ax, layout=g.layout("circle"), # print nodes in a circular layout - vertex_size=10, - vertex_color=["lightblue", "orange", "orange"], - vertex_shape="s", # square + vertex_size=0.07, # set vertex_size of all vertices at once + vertex_color=["lightblue", "orange", "orange"], # set colours individually + vertex_frame_color=["white", "white", "white"], + vertex_frame_width=2.0, + vertex_shape=["circle", "rectangle", "triangle-down"], vertex_label=g.vs["name"], - vertex_label_size=8, + vertex_label_size=7.0, + edge_width=[1.2+dist/4000.0 for dist in g.es["distance"]], # longer distances = thicker edges ) - # Remove the axes borders - ax.spines['top'].set_visible(False) - ax.spines['right'].set_visible(False) - ax.spines['bottom'].set_visible(False) - ax.spines['left'].set_visible(False) - ax.get_xaxis().set_ticks([]) - ax.get_yaxis().set_ticks([]) plt.show() @@ -56,7 +52,7 @@ This is a short condensed segment aimed at those who want a very quick and dirty g.save("america.gml") g = ig.load("america.gml") -... and here is the graph generated by the code +... and here is the graph generated by the code: .. figure:: ./figures/america.png :alt: The visual representation of our city network From 6e91dea439a9b35da3954be24f334ff769e26f8c Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Mon, 22 Nov 2021 00:49:32 +1100 Subject: [PATCH 0727/1892] Add tutorial for get_shortest_paths() --- doc/source/tutorial/figures/shortest_path.png | Bin 0 -> 30009 bytes doc/source/tutorial/shortest_paths.rst | 60 ++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 doc/source/tutorial/figures/shortest_path.png create mode 100644 doc/source/tutorial/shortest_paths.rst diff --git a/doc/source/tutorial/figures/shortest_path.png b/doc/source/tutorial/figures/shortest_path.png new file mode 100644 index 0000000000000000000000000000000000000000..b48156a38a4b5aa190729a4cfef443bc940b9924 GIT binary patch literal 30009 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 0 -> 2 -> 4. + results = g.get_shortest_paths(1, to=4, output="vpath") + + if len(results[0]) > 0: + # Number of edges is the number of nodes in the shortest path minus one. + print("Shortest distance is: ", len(results[0])-1) + else: + print("End node could not be reached") + +...and if the edges have distances or weights associated with them, we pass them in as an argument. Also note that we specify the output format as ``"epath"``, in order to receive the path as an edge list which we can use to calculate the distance. + +.. code-block:: python + + # Find the shortest path on a weighted graph + g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] + + # g.get_shortest_paths() returns a list of edge ID paths. + # In this case, results = [[1, 3, 5]]. + results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") + + if len(results[0]) > 0: + # Add up the weights across all edges on the shortest path. + distance = 0 + for e in results[0]: + distance += g.es[e]["weight"] + print("Shortest distance is: ", distance) + else: + print("End node could not be reached") + +.. figure:: ./figures/shortest_path.png + :alt: The visual representation of a weighted network for finding shortest paths + :align: center + + Graph ``g``, as seen in the examples. + + NOTE: Currently, the develop branch is bugged so that I can't display edge weights on the sample figure. I'll find some time to generate a graph from Cairo instead. + +.. TODO Update this figure + +- If you're wondering why :meth:`get_shortest_paths` returns a list of lists, it's becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. +- If you're interested in finding *all* shortest paths, check out :meth:`get_all_shortest_paths`. + + + From 2d22fc92dc8a8969303b72d3ff8372fded3cbd5e Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Mon, 22 Nov 2021 00:55:49 +1100 Subject: [PATCH 0728/1892] Remove america.gml Currently it's not being used in the tutorial, so I'll just remove it for now. --- doc/source/tutorial/assets/america.gml | 43 -------------------------- doc/source/tutorial/shortest_paths.rst | 4 +-- 2 files changed, 1 insertion(+), 46 deletions(-) delete mode 100644 doc/source/tutorial/assets/america.gml diff --git a/doc/source/tutorial/assets/america.gml b/doc/source/tutorial/assets/america.gml deleted file mode 100644 index acf490020..000000000 --- a/doc/source/tutorial/assets/america.gml +++ /dev/null @@ -1,43 +0,0 @@ -Creator "igraph version 0.10.0-dev+63a49e74 Sun Nov 21 16:02:47 2021" -Version 1 -graph -[ - directed 0 - title "Cities of America" - node - [ - id 0 - name "New York City" - population 8620000 - ] - node - [ - id 1 - name "San Francisco" - population 874000 - ] - node - [ - id 2 - name "Chicago" - population 2710000 - ] - edge - [ - source 1 - target 0 - distance 4160 - ] - edge - [ - source 2 - target 1 - distance 2960 - ] - edge - [ - source 2 - target 0 - distance 1180 - ] -] diff --git a/doc/source/tutorial/shortest_paths.rst b/doc/source/tutorial/shortest_paths.rst index 525b5e7fc..166ed6355 100644 --- a/doc/source/tutorial/shortest_paths.rst +++ b/doc/source/tutorial/shortest_paths.rst @@ -49,9 +49,7 @@ For finding the shortest path or distance between two nodes, we can use :meth:`g Graph ``g``, as seen in the examples. - NOTE: Currently, the develop branch is bugged so that I can't display edge weights on the sample figure. I'll find some time to generate a graph from Cairo instead. - -.. TODO Update this figure + TODO: Currently, the develop branch is bugged so that I can't display edge weights on the sample figure. I'll find some time to generate a graph from Cairo instead later. - If you're wondering why :meth:`get_shortest_paths` returns a list of lists, it's becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. - If you're interested in finding *all* shortest paths, check out :meth:`get_all_shortest_paths`. From faaf8333d98014d0f5012febf0dc861af08008cc Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Tue, 23 Nov 2021 03:11:50 +1100 Subject: [PATCH 0729/1892] Add maxflow.rst and bipartite_matching.rst --- .../bipartite_matching/assets/maxflow2.py | 39 ++++++++++++ .../bipartite_matching/bipartite_matching.rst | 60 ++++++++++++++++++ .../bipartite_matching/figures/maxflow2.png | Bin 0 -> 50120 bytes .../tutorials/maxflow/assets/maxflow.py | 30 +++++++++ .../tutorials/maxflow/figures/maxflow.png | Bin 0 -> 27217 bytes doc/source/tutorials/maxflow/maxflow.rst | 41 ++++++++++++ .../quickstart}/figures/america.png | Bin .../quickstart}/quickstart.rst | 0 .../shortest_paths}/figures/shortest_path.png | Bin .../shortest_paths}/shortest_paths.rst | 0 10 files changed, 170 insertions(+) create mode 100644 doc/source/tutorials/bipartite_matching/assets/maxflow2.py create mode 100644 doc/source/tutorials/bipartite_matching/bipartite_matching.rst create mode 100644 doc/source/tutorials/bipartite_matching/figures/maxflow2.png create mode 100644 doc/source/tutorials/maxflow/assets/maxflow.py create mode 100644 doc/source/tutorials/maxflow/figures/maxflow.png create mode 100644 doc/source/tutorials/maxflow/maxflow.rst rename doc/source/{tutorial => tutorials/quickstart}/figures/america.png (100%) rename doc/source/{tutorial => tutorials/quickstart}/quickstart.rst (100%) rename doc/source/{tutorial => tutorials/shortest_paths}/figures/shortest_path.png (100%) rename doc/source/{tutorial => tutorials/shortest_paths}/shortest_paths.rst (100%) diff --git a/doc/source/tutorials/bipartite_matching/assets/maxflow2.py b/doc/source/tutorials/bipartite_matching/assets/maxflow2.py new file mode 100644 index 000000000..ad8f36f6a --- /dev/null +++ b/doc/source/tutorials/bipartite_matching/assets/maxflow2.py @@ -0,0 +1,39 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph( + 9, + [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], + directed=True +) + +# Assign nodes 0-3 to one side, and the nodes 4-8 to the other side +for i in range(4): + g.vs[i]["type"] = True +for i in range(4, 9): + g.vs[i]["type"] = False + +# Add source and sink as nodes 9 and 10 +g.add_vertices(2) +g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side +g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other + +flow = g.maxflow(9, 10) +print("Maximal Matching is:", flow.value) + +# Manually set the position of source and sink to display nicely +layout = g.layout_bipartite() +layout[9] = (2, -1) +layout[10] = (2, 2) + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], + edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] +) +plt.show() diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst new file mode 100644 index 000000000..b5e6d44a6 --- /dev/null +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -0,0 +1,60 @@ +========================== +Maximal Bipartite Matching +========================== + +This example demonstrates how to visualise bipartite matching using max flow. + +.. code-block:: python + + # Generate the graph + g = ig.Graph( + 9, + [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], + directed=True + ) + + # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side + for i in range(4): + g.vs[i]["type"] = True + for i in range(4, 9): + g.vs[i]["type"] = False + + g.add_vertices(2) + g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side + g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other + + flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1 + print("Maximal Matching is:", flow.value) + +And to display the flow graph nicely, with the matchings added + +.. code-block:: python + + # Manually set the position of source and sink to display nicely + layout = g.layout_bipartite() + layout[9] = (2, -1) + layout[10] = (2, 2) + + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout=layout, + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], + edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] + ) + plt.show() + +The received output is: + +.. code-block:: + + Maximal Matching is: 4.0 + +.. figure:: ./figures/maxflow2.png + :alt: The visual representation of maximal bipartite matching + :align: center + + Maximal Bipartite Matching \ No newline at end of file diff --git a/doc/source/tutorials/bipartite_matching/figures/maxflow2.png b/doc/source/tutorials/bipartite_matching/figures/maxflow2.png new file mode 100644 index 0000000000000000000000000000000000000000..86a6fb1bbbcdfc709431df4f216d7f8cd1433c27 GIT binary patch literal 50120 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
  • v1rtwQuh(6Rat3QXuUpL9ee_v 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 I?D>cO2NEF>V*mgE literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/maxflow/assets/maxflow.py b/doc/source/tutorials/maxflow/assets/maxflow.py new file mode 100644 index 000000000..b28b81bfc --- /dev/null +++ b/doc/source/tutorials/maxflow/assets/maxflow.py @@ -0,0 +1,30 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph( + 6, + [(3, 2), (3, 4), (2, 1), (4,1), (4, 5), (1, 0), (5, 0)], + directed=True +) +g.es["capacity"] = [7, 8, 1, 2, 3, 4, 5] # capacity of each edge + +# Runs max flow, and returns a Flow object +flow = g.maxflow(3, 0, capacity=g.es["capacity"]) + +print("Max flow:", flow.value) +print("Edge assignments:", flow.flow) + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout="circle", + vertex_label=range(g.vcount()), + vertex_color="lightblue" +) +plt.show() + +# Output: +# Max flow: 6.0 +# Edge assignments [1.0, 5.0, 1.0, 2.0, 3.0, 3.0, 3.0] + diff --git a/doc/source/tutorials/maxflow/figures/maxflow.png b/doc/source/tutorials/maxflow/figures/maxflow.png new file mode 100644 index 0000000000000000000000000000000000000000..8cd123fe71d00501773db7b412696f4f462893e1 GIT binary patch literal 27217 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 bu^;#T Date: Tue, 23 Nov 2021 16:29:12 +1100 Subject: [PATCH 0730/1892] Fix Typos in Maximum Bipartite Matching --- .../tutorials/bipartite_matching/bipartite_matching.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index b5e6d44a6..4dcef0291 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -1,5 +1,5 @@ ========================== -Maximal Bipartite Matching +Maximum Bipartite Matching ========================== This example demonstrates how to visualise bipartite matching using max flow. @@ -24,7 +24,7 @@ This example demonstrates how to visualise bipartite matching using max flow. g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1 - print("Maximal Matching is:", flow.value) + print("Size of the Maximum Matching is:", flow.value) And to display the flow graph nicely, with the matchings added From 588ddbaf36f4440e6f9fcd53c12bea3af7083966 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Tue, 23 Nov 2021 17:27:16 +1100 Subject: [PATCH 0731/1892] Update tutorial to use maximum_bipartite_matching instead of max flow The max flow tutorial has been moved into the "archived" folder, in case we want to use it later. --- .../bipartite_matching/assets/maxflow2.py | 2 +- .../bipartite_matching/bipartite_matching.rst | 60 ++++++++++++++++++ .../bipartite_matching/figures/maxflow2.png | Bin .../assets/bipartite_mathing.py | 45 +++++++++++++ .../bipartite_matching/bipartite_matching.rst | 50 ++++++++++----- .../bipartite_matching/figures/bipartite.png | Bin 0 -> 33545 bytes 6 files changed, 139 insertions(+), 18 deletions(-) rename doc/source/tutorials/{ => archived}/bipartite_matching/assets/maxflow2.py (94%) create mode 100644 doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst rename doc/source/tutorials/{ => archived}/bipartite_matching/figures/maxflow2.png (100%) create mode 100644 doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py create mode 100644 doc/source/tutorials/bipartite_matching/figures/bipartite.png diff --git a/doc/source/tutorials/bipartite_matching/assets/maxflow2.py b/doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py similarity index 94% rename from doc/source/tutorials/bipartite_matching/assets/maxflow2.py rename to doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py index ad8f36f6a..844d12306 100644 --- a/doc/source/tutorials/bipartite_matching/assets/maxflow2.py +++ b/doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py @@ -19,7 +19,7 @@ g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other flow = g.maxflow(9, 10) -print("Maximal Matching is:", flow.value) +print("Size of the Maximal Matching is:", flow.value) # Manually set the position of source and sink to display nicely layout = g.layout_bipartite() diff --git a/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst new file mode 100644 index 000000000..4dcef0291 --- /dev/null +++ b/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst @@ -0,0 +1,60 @@ +========================== +Maximum Bipartite Matching +========================== + +This example demonstrates how to visualise bipartite matching using max flow. + +.. code-block:: python + + # Generate the graph + g = ig.Graph( + 9, + [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], + directed=True + ) + + # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side + for i in range(4): + g.vs[i]["type"] = True + for i in range(4, 9): + g.vs[i]["type"] = False + + g.add_vertices(2) + g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side + g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other + + flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1 + print("Size of the Maximum Matching is:", flow.value) + +And to display the flow graph nicely, with the matchings added + +.. code-block:: python + + # Manually set the position of source and sink to display nicely + layout = g.layout_bipartite() + layout[9] = (2, -1) + layout[10] = (2, 2) + + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout=layout, + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], + edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] + ) + plt.show() + +The received output is: + +.. code-block:: + + Maximal Matching is: 4.0 + +.. figure:: ./figures/maxflow2.png + :alt: The visual representation of maximal bipartite matching + :align: center + + Maximal Bipartite Matching \ No newline at end of file diff --git a/doc/source/tutorials/bipartite_matching/figures/maxflow2.png b/doc/source/tutorials/archived/bipartite_matching/figures/maxflow2.png similarity index 100% rename from doc/source/tutorials/bipartite_matching/figures/maxflow2.png rename to doc/source/tutorials/archived/bipartite_matching/figures/maxflow2.png diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py new file mode 100644 index 000000000..7a1f95fcb --- /dev/null +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py @@ -0,0 +1,45 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph( + 9, + [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] +) + +# Assign nodes 0-4 to one side, and the nodes 5-8 to the other side +for i in range(5): + g.vs[i]["type"] = True +for i in range(5, 9): + g.vs[i]["type"] = False + + +matching = g.maximum_bipartite_matching() + +# Print pairings for each node on one side +matching_size = 0 +print("Matching is:") +for i in range(5): + print(f"{i} - {matching.match_of(i)}") + if matching.match_of(i): + matching_size += 1 +print("Size of Maximum Matching is:", matching_size) + +fig, ax = plt.subplots(figsize=(7, 3)) +ig.plot( + g, + target=ax, + layout=g.layout_bipartite(), + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color="lightblue", + edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] +) +plt.show() + +# Matching is: +# 0 - 5 +# 1 - 7 +# 2 - 8 +# 3 - None +# 4 - 6 +# Size of Maximum Matching is: 4 diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 4dcef0291..c8a2339f0 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -2,31 +2,41 @@ Maximum Bipartite Matching ========================== -This example demonstrates how to visualise bipartite matching using max flow. +This example demonstrates how to find and visualise a maximum biparite matching. First construct a bipartite graph .. code-block:: python - # Generate the graph + import igraph as ig + import matplotlib.pyplot as plt + g = ig.Graph( 9, - [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], - directed=True + [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) - # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side - for i in range(4): + # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side + for i in range(5): g.vs[i]["type"] = True - for i in range(4, 9): + for i in range(5, 9): g.vs[i]["type"] = False - g.add_vertices(2) - g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side - g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other +Then run the maximum matching, + +.. code-block:: python + + matching = g.maximum_bipartite_matching() + + # Print pairings for each node on one side + matching_size = 0 + print("Matching is:") + for i in range(5): + print(f"{i} - {matching.match_of(i)}") + if matching.match_of(i): + matching_size += 1 + print("Size of Maximum Matching is:", matching_size) - flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1 - print("Size of the Maximum Matching is:", flow.value) -And to display the flow graph nicely, with the matchings added +And finally display the bipartite graph with matchings highlighted. .. code-block:: python @@ -47,14 +57,20 @@ And to display the flow graph nicely, with the matchings added ) plt.show() -The received output is: +The received output is .. code-block:: - Maximal Matching is: 4.0 + Matching is: + 0 - 5 + 1 - 7 + 2 - 8 + 3 - None + 4 - 6 + Size of Maximum Matching is: 4 -.. figure:: ./figures/maxflow2.png +.. figure:: ./figures/bipartite.png :alt: The visual representation of maximal bipartite matching :align: center - Maximal Bipartite Matching \ No newline at end of file + Maximum Bipartite Matching \ No newline at end of file diff --git a/doc/source/tutorials/bipartite_matching/figures/bipartite.png b/doc/source/tutorials/bipartite_matching/figures/bipartite.png new file mode 100644 index 0000000000000000000000000000000000000000..3565aba619105e82297afe4aa60406949e319645 GIT binary patch literal 33545 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 literal 0 HcmV?d00001 From 993e913b4603aad1502a9232642673b1c5e198bc Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Tue, 23 Nov 2021 17:41:40 +1100 Subject: [PATCH 0732/1892] Update shortest_paths format to be more in line with recent tutorials - Add a short summary of the example at the beginning - Remove full stops from comments - Included output of print statements at the end - Made the tone _slightly_ more formal (library is aimed at researchers doing graph analysis) --- .../shortest_paths/shortest_paths.rst | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 166ed6355..21834b3d1 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -2,57 +2,66 @@ Shortest Paths ============== -For finding the shortest path or distance between two nodes, we can use :meth:`get_shortest_paths()`. If we're only interested in counting the unweighted distance, then we use: +This example will demonstrate how to find the shortest distance between two vertices on a weighted and unweighted graph. + +To find the shortest path or distance between two nodes, we can use :meth:`get_shortest_paths()`. If we're only interested in counting the unweighted distance, then .. code-block:: python + import igraph as ig + import matplotlib.pyplot as plt + # Find the shortest path on an unweighted graph g = ig.Graph( 6, [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] ) - # g.get_shortest_paths() returns a list of vertex ID paths. - # In this case, results = [[1, 0, 2, 4]], to indicate that the shortest - # path goes through nodes 1 -> 0 -> 2 -> 4. - results = g.get_shortest_paths(1, to=4, output="vpath") + # g.get_shortest_paths() returns a list of vertex ID paths + results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] if len(results[0]) > 0: - # Number of edges is the number of nodes in the shortest path minus one. + # The distance is the number of vertices in the shortest path minus one. print("Shortest distance is: ", len(results[0])-1) else: - print("End node could not be reached") + print("End node could not be reached!") -...and if the edges have distances or weights associated with them, we pass them in as an argument. Also note that we specify the output format as ``"epath"``, in order to receive the path as an edge list which we can use to calculate the distance. +If the edges have associated distances or weights, we pass them in as an argument. Note that we specify the output format as ``"epath"``, in order to receive the path as an edge list. This is used to calculate the length of the path. .. code-block:: python # Find the shortest path on a weighted graph g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - # g.get_shortest_paths() returns a list of edge ID paths. - # In this case, results = [[1, 3, 5]]. - results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") + # g.get_shortest_paths() returns a list of edge ID paths + results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] if len(results[0]) > 0: - # Add up the weights across all edges on the shortest path. + # Add up the weights across all edges on the shortest path distance = 0 for e in results[0]: distance += g.es[e]["weight"] - print("Shortest distance is: ", distance) + print("Shortest weighted distance is: ", distance) else: - print("End node could not be reached") + print("End node could not be reached!") + +The output of these these two shortest paths are: + +.. code-block:: + + Shortest distance is: 3 + Shortest weighted distance is: 8 .. figure:: ./figures/shortest_path.png :alt: The visual representation of a weighted network for finding shortest paths :align: center - Graph ``g``, as seen in the examples. + The graph `g` - TODO: Currently, the develop branch is bugged so that I can't display edge weights on the sample figure. I'll find some time to generate a graph from Cairo instead later. +.. TODO: Add in edge weights when possible! Matplotlib does not support displaying edge weights (and the develop branch implementation is bugged). -- If you're wondering why :meth:`get_shortest_paths` returns a list of lists, it's becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. -- If you're interested in finding *all* shortest paths, check out :meth:`get_all_shortest_paths`. +- Note that :meth:`get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. +- If you're interested in finding *all* shortest paths, take a look at :meth:`get_all_shortest_paths`. From dce50b337cc5d0adf4e509106c1d29c7fd566a27 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Tue, 23 Nov 2021 19:08:40 +1100 Subject: [PATCH 0733/1892] Update quickstart.rst example to be more neutral --- .../tutorials/quickstart/assets/quickstart.py | 44 +++++++++++++ .../tutorials/quickstart/figures/america.png | Bin 16021 -> 0 bytes .../quickstart/figures/social_network.png | Bin 0 -> 26448 bytes .../tutorials/quickstart/quickstart.rst | 59 ++++++++++-------- 4 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 doc/source/tutorials/quickstart/assets/quickstart.py delete mode 100644 doc/source/tutorials/quickstart/figures/america.png create mode 100644 doc/source/tutorials/quickstart/figures/social_network.png diff --git a/doc/source/tutorials/quickstart/assets/quickstart.py b/doc/source/tutorials/quickstart/assets/quickstart.py new file mode 100644 index 000000000..2db46d73b --- /dev/null +++ b/doc/source/tutorials/quickstart/assets/quickstart.py @@ -0,0 +1,44 @@ +import igraph as ig +import matplotlib.pyplot as plt + +# Construct a graph with 3 vertices +n_vertices = 3 +edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (3, 4)] +g = ig.Graph(n_vertices, edges) + +# Set attributes for the graph, nodes, and edges +g["title"] = "Small Social Network" +g.vs["name"] = ["Daniel Morillas", "Kathy Archer", "Kyle Ding", "Joshua Walton", "Jana Hoyer"] +g.vs["gender"] = ["M", "F", "F", "M", "F"] +g.es["married"] = [False, False, False, False, False, False, False, True] + +# Set individual attributes +g.vs[1]["name"] = "Kathy Morillas" +g.es[0]["married"] = True + +# Plot in matplotlib +# Note that attributes can be set globally (e.g. vertex_size), or set individually using arrays (e.g. vertex_color) +fig, ax = plt.subplots(figsize=(5,5)) +ig.plot( + g, + target=ax, + layout="circle", # print nodes in a circular layout + vertex_size=0.1, + vertex_color=["lightblue" if gender == "M" else "pink" for gender in g.vs["gender"]], + vertex_frame_width=2.0, + vertex_frame_color="white", + vertex_label=g.vs["name"], + vertex_label_size=7.0, + edge_width=[2 if married else 1 for married in g.es["married"]], +) + +plt.show() + +# Save the graph as an image file +fig.savefig('social_network.png') +fig.savefig('social_network.jpg') +fig.savefig('social_network.pdf') + +# Export and import a graph as a GML file. +g.save("social_network.gml") +g = ig.load("social_network.gml") diff --git a/doc/source/tutorials/quickstart/figures/america.png b/doc/source/tutorials/quickstart/figures/america.png deleted file mode 100644 index d86d613dbda293553b139a717c14b4d5d6a4dc3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16021 zcmeHuc|4cv`tB==CPUFkWhz5x6(us0u*@PAQc+0Cn0ZK=(U(#hC_{z}k<7!QA}R_Y zV;M3PnP=yEwD;QkcYee9=bZn}{(RQnd-=ZaGu+Q}-}iN2*Zp4A(NbNxY{N2&qE@OM zP}ZX;x)JgZ(-Qop;&baY{11bJqM88{{^P-P@(TWa>A3^O4iv>=PX3{blY44~Kkju@ zIpnBsXX)r-Zf`-^nme95W9N9r>i8CC3wsAEyR%z%iS7{HwSCKJN5^wgVq*V#K-A9u zl-R@NiBS}_g;G;iFu3rbzuDE%U~%~Ty!J9CfB#fojiM`Mo0wQxnapp!zvQXiYgqI$ zCL_bv_J^HVyJWRY^{Jf7%JoN%y!gwId)#mpoiW3ihA`GKF6G_EB|J8Vlnw}uPV*{h zKE1e%R<3!rCB;Fqv_?PPO>b}4`+SZB#Tld=snePnqva8VTFmTroYq!bvb zB0451iei?pqNC1He$12)J*y){ar#8kQ*G4$fAs&o1;iE?&d(0iCYwmVe)UQ~R8&hf zkTZLrac10m-bF=4MR50S!{^VRyY(eysvoPCp6*Yt^mCi0e5Q>WelC7+wmHY?aJGGn zbASC~p@Rtm!onI~zkcPnZ!DY}O&R@mUCgU5FEUbIv~G6(p>2Jt`MBps%BSrclT6u% z2YaL3MtkGcZwt|);sGA%$*42c|MSlqQ{w|E zeRV0VqqDV1M~uV@CY~HWe%!IG$k)9fh@O!-&aBX@xBhulj`NR%iZC&osgWMH9~pIg zYCSzY*442$rJVcYzLs3ppe38;3k8)%F>^`9ohS_~FDnb?o9)r|)|(#t!LfQZZ%Uo} z<{%!b&3*FxyvL;1{OD?z8HdhyMss7fM2%DPqDr{~4HKDJkcdfazaJI2<^1is$w*f4%5cAHxzrTl3 z*5zyQCEq@itaD!<{fx4yOP+gueJutkobRnooI8?vc2aI`;>3JnNN>4l3+s~{OJvz9@uBFL) zsN?M_*DN~f_4)FAzNUR5?`_;lbyuo2dW$4A35(1RMJ{2UJFv@)w&cwLtJayzb9aW~ zJ!B)&($ZeowaQA^elcKUW81Lfm=9mPMwqCS+ekN;-L%%zrjp{~ks5vN#j;u&8r7|H zW0|=*LBdAK-QQkc-ynWEm`{+0=SjWio6=GnEWkdudBZNt8+=v`X%ANxZAFUQ!;^(3f=B!x=hGOXvIX)x_Hx-R&$0uUm2qX ztMy)Zl~~q3GuA)x=7#Rsv&nq%c-gly$snHQA=_%wYBbtgOF!>9F=(!NZ>I`wjo9<) z3-hz%8RjKRL=L6OpFe;8OTPQK$-okdY11PmmbBTY(J6(3Gj@e$UmO&z4UKZbc~$(4 zj82}6CN?*ODyT=_j$68s# ztZt*VMjUI_#PVz0VZT>6_QgiZu{#(+cYh#fJREDbuW&B$k^9fRaPK(17zZJ1IY*W z{}!<;d~gYETMJC~P18{mkD1)o2Zx0{ogbf{i}3n&-RyMZOIv>~>Rcs$NIO-zX|~s> z@RM*#-jk#wnX86>KM!W?rzO%v%?da#)Mj|sytF;CKHzaymgFUW z|Inf*6!ny++u~JAzPm+u?8`F^dS^c8IN7-F+vN1)%k5Np>gSb6#*grv&f!Uecs>5w zc>V9mvZn@G^3%3!+}~p-y4wZ@Tv4KvdA6BJnu=ud+oY^5H~Ru7%g(_O69gZ7Bz z;JH&%|Nd@Uq1`qOX)*gY1#R*i(Jf}Cf|aW-_ImkwHO|dWTNvNjeWqUL%vc$3P}z3;=^0NN-}#(kW_ITD6P4xI!y_4Y>@_Zu$&K~)$tpYP3xko{ zD?a5o^<8@(j+K?{VBfr1EbO}XEhdU%sRGNBV+^w|l`b>CP1|l^X}RV;8{WNucNg#K z&g8=Vx?>^8%Ntd{T}tY3fVluSw{I%FPYK(|7NMJwtRCy#94;u6VhO!D_< zIGA7{80St={R&v1_(iYAk5Q_fqiz|9s>jXkK0mwHbT$)lQmLM<$Q-jYu#Gh0c5SUl z`?+o`R`Y)O59dU?)&d+Nr(Y!Ft%nMQKkA>KP}kI~O*oinprfO6at#LuKc@1Uox(~5 zzLQ;E!b-lqTI!l_nshWf?NB{}9uFQV-Q<1)rrN85m26);`|{bd?J=>j){{e>uZvr< z&Y$4t=eH{Ip~GC|>v297e{^R)+~=wnA0L1CPkoc}ak}y85RgU;3reROopInJeW=u({`y=S1D8`9mTe`HFW|E5fW3a(e$d3~x#j;A{-igD8gd9lKoG|P8)A9E`O zurHm?cKAN>L3-fyr)afsId54quuo*Wv;^joo1d(dIPqr1N-n7vW$|MU-#_#;yR_E6 zy1H7zu4NzY;BE{lymEthm4;Y;G*)nWV(_a0{2nzNzHT&rJ_q*cUG2{_<=~o>hA+rSk`?V^bK($4}*E9hZd{#kR(;(bW6c)+e+VP(iJr@NvSIX9*j0QRK6A0yt#f??1B39^mHT> zasF-FY`Wgv!(sdRL`Er-+%GrzR{Lal?3mR8 zY>o^B7>puwlw-Wjas>zK#mowxvB=Hnz!^kDH20isO2q-3TjCcOi5q&yYo>j3McQ`F zyE_!j&CPuqZVMZYd{o{1cE<|bPLo2fW~?*PgST6N16inMSLHt5inP$XcjJ(J87+-c zOlwDasylyOK+KqtXW)tvLfDs^`WS>|Hk}>kDml9@;Lqxs44b+$uzLAgKjtIK`}bSp zcoB92%yHuQDU?RzDcOPlR;;IM6J>R*PuPERL%8JmC)+D%rR};GE?hX~JUiudFIKQ* zhd6G4NxoYxS=AY=YPEGu+~bZ8M3fl(w~DedgJoTc84KrI?Fd;DqvWH{u~&inOj6~c zSFSK28sa&%kgf5Uz_;P%#yuUQZdg3oFnn`@k%7xX@4|&Fcsv$etu1G=z2C~pYUc{2 z&0Z6a5qZy$Gv3YW7-|Is2REWw7-O$q(Pd?2MccP+Q-yPohdl;;)6&z)J?mGg(iJsG zF*SjwV8@mFhHqGZezyK@bDpdIu2UaEOWQv(ZuW=-UTDY?r0Oq5Mjc(ce0jD1($z5F zBhN8oL=oW~xm;t|oaRF*1oAi?Y$hf(bq7|jB`7EuzR%VEd1~b&nIoHmRJ~{W%$#sD zH||;N^GTsfH~G?~OIH2$&k?jMWyT*^*Clh^?du{Ig-o3^H1=GnuSEq=z(wL+;3Gmpk*FG9XT`rav3IAAZ2|Nf7FW9Q} zAkL-5RrOTmqYQFX>lwHL*KF93z{b1(^qU*&ry44~Vy8y?7|HX8Q;+#>)eMi$Z1uXI zN-t2yBqiiuRi(3X{ssY>^;e?WkB zch%!?S`Z`UbuPk(A&0c>o{_t%%19jPua zFV{0L2$coO%&q&2tE02is^?RTx`u}Enn56QE1+v!1-+>KH_v=wrG7Fiu<-bqdUbsN zZbKf^)D&6c99F@>ZjM=9Tg2*vSM9ibTprY)u&gn zE9u%kAXTu93<=B0nE|XDSz9M)J(N0lvdccZrqJ6P$v{v@s2mSQ3Lri+H1Nw`sB81I&nnQ{jHI$WBCRZd?=>N7m=~eF)R0Ti!&< z{?%T3{oUEi%|D!lrKG+*T1;mkiTuKpgN4ajoIF|9H`?3%F-pafo10txz=2@%b#C2{ zFZUa>%3nh6y%K4}xp?tnQfpWkzb+OPWF6~ze?M%_o)YpecNU{0eX-C8S@~Un6p+X^qcnHpfVY?4zRme0&13vZj5XlR~V*Rf-?o zyBCi)NBbM}Hw9hB4f=zDi)m3H|XO~Crfz-4rY~^>W=FDoOB_P z`O%cE4}6a5z;_au>cxptW~c5d1*B?Zy_C*Pf9BnhR{!)Pb)YFby?*=Ft@~jy)Y%x} zxw$mu%-gM?T*bB`*ZBv{D*OxPcy5gP6!9E@XIn9|!47iyr2MRK3J8E$zVL1vn2#0` zQi~nq0oH{F)Jw)MHSbvQ`t@rz=c2C*cRDl{_CW%*1<0*`hO-GO{UL z<{JCiEL@TH0s-%M`sbu06+2eoshg?v%u3`YmuO)jAvi#Qw&%vUJr?T%aI{F#m$#5b z>#pfx`n51<+EI6Nl1~aGR7EA!tcsv~;iU8^UhLBYH zPIltNfoTY3O2{bp?%jKBi849NeBHI6ps-V+~3 zRa49yx_V*fXNdE9m_WLTTs@MfwhSfRp#)4^eA93!r=VKl7o_o&v?{N7oV#xv~ zWZ>%j_}`&r-<<)(QmU??J^mm-_i#o6fG$c00Nn!5=~b9z!4_W`N`p3&;AWV7G~Un8 zk0%`k8G>8S^U_Vc{XXv(4n*?p)z#ZV!^0C$4ze$I580~O;heiv`WP>Xd|Xvs60(#PCbIIocZ7ANaG2TbPaj$=Y>jd}4xT*Npn8e{A} z6Zh(sGSK9eRC95$9c#3+`S$86NqgXsEZSpz(!u*F{3@bnVJMb$?5^Tb?SLm$ zOAq8lA%j`X%}n}p3D7Zc$?FinES5h)i`9-u2B7CyKAk&IkO&)Ex8%9{b7isMq4?8P zk-lDI=@C{)v>RkSF5F6ukn=XxkNs2E-ad`w{HCU(KoaHK{FoyRYEiHeK8b+Z;3ZDMBVDcP4pfV}3|Evye z{2{t#3?&P^{9bH4I4+<;ogDIzARfYPM>4>&06Kje{v%-4<;He952NrBM}>vx`(L2o z6jMN}Em`1@Rj&XA@4GB}{@W`a^Fr(pOJ7k^1qkodSzG3QMd%jPF+bY(Iw+7V_^wv{Bg%B+-<7o>Gex8C@ccZyGvN)YC0>z0DK9K z^NG52`LeK}pxPaao_nVr>7G1!^4Oh_kf@OnM-=@45%Q>CcAs6=v>EqHG0rqU2ew7b z8)@G>e+b3Kig&20;sMFZ+kc(@^1>$`AnEWy-u*Y2 z{PTfFe2q;_A9Ynmq`+r;AG)-BL_i>RRj#6IlO|C1)fKkzKTZS?|BXkISa^QT_Ct{b z%Kpe~-P)hZp}^>q%L*)w0ANL!-kzASYnMF1rjpufZsxmOANXSwNCpNBT+~m6)2HJC zn7I;2?cNz?_L-h#AM4#tfYgsqRLBc0ZhayMXm8$V>VEY9O@B$&qL4@eO92kNr#(pS zr8^g;K=>_CyFwx&Nr#Gr4<@2O zmTtmBHtEoFMKB~l@j^QtvXA!Gr9_~<3*T*PT^(?4*+Tv(vIQhgG)$t^_0_`O*9aD$ z8vBumEFv?}c5%1um7zeAMi>VxLHHV`n2J=SUArU$3g0BQnxjEP*|iLfZYz6}rOy4Vrs6nFrr;4;f* z=6Abx?hL(k>+!_I1-Kg^M17V>Ii{v8t^i0YD*6G%W}I!7Ld-}hoRiv7`R*Mdncc?v z1%pbJ>e-++MXs=i!DQgq6DNw#C=Wd7FcWfyFIpFqQUr*;E5@KS2NBZ z3Ehe{bymp*cmjf9EoPph2agrF4qMu`eKi$W^fec7xk1!yQP>fjn-`KbQxe_wZ_|InFNdRSnonOCsQw|*2U;puqtu75= zR#FG%lyd5guCG7zKVao%x(g0>wtRbUOoj4GyZj6V?py%F(1QqAKXHO%)vDtq&RJ#) zuIH0>8i0GJ=5U}nc*}e|ffN z)hmo^hvUK&*0t)G0<{)zzr~7wOo8el0+kquuIukXZG!iy$#-`tHr>B~)u;!@=I3T{ z@IYw-yWKl(sUitOZc(VW-M=uyIod@=mh!aim^``unacGwxDhh$V|@L)e@6w$kErpG zo_Frrb^YHd<_e1vXO6WCYbbhKFgIm`MIzmz=ATo$pFDZu2(u34eL$%#0T?DTGg#95Ddzf{ zpv@`irz)+HiQK+Fbm3Ejfw`f$# zPCvUNX69w2@C>y9Vlt9#{_%7Kqr*5p!=pzZ;DtZ9WZXzn)8qsYL8@YG%0ddea<@U&A2ttcm6W$v@5+w-ziDm;OXiTwSCWz_S*YeD;T(cXf*Q ztPSSYitwJxHofq5F&tKC*Dig;Zsw!jzrMW=-(gl(JB#|6SOH}cTp|?i z-yg95#=6IddHF--!cwk7(R_l4$S562Kp5>!OtD5vBt>mo*=&T&c#}f{M3gsyT*7Kn z-g6#p&U|m%f3Z)-6gJl7{`gh8xeh0AMCRA4)%=53IKsuPXe7yu_8ugx%*7=ur#|!< zi9UB#vt4qIEK}YrK%0uX{A5pVIdH^?L2= zzz;FSF3+aFR}Z?J0F3QzNPikGVG|4ANr3#=>gpK??}-tD=|~k){P+Z2%#kbQ&vw7e}@Vyh~mDr zHV}UZi7s+~?VjJlQ)xAyK0g^TuM0VxXqz1ONm+_=5}c231u#rhO2Je@*(msR-Hx^M zJiNSwvB{sC>T7k+G2uaL%6+bUkM`sg>2IZC-Tn9G-CJZNBo2B{R+tgG2SVy;=vK64 zLD!(MFM3+v_`+&9zw*RDFQzEZT<@z~(lkn`7f7_TonqdC1g8=4 zTioXJb`s%GsXc^5JX>V8;j9LtmN7Lx23HPTfcW(M+={EeD>Ptz4hU@nA(%ORYoPC#>snmlv6K*>Vze&n1 z@H%<=^?|xbg^P};g@78rB`2Hxv5A9{zc+f|$GL~Omm@RdR+*Cd4%FIRS zBtS%lmbv-Dqbze}35mcsH=~Fng>G@-pX1iN8!Z=sUkGrZxd*t+4Gh8Pn~ip$L6=xI zZ>amsn^Dp^bthAg<<^K!Qg3fVH1j~_oQPy6aV0;$MG!a3)1DOxM;wHHAYoloh0w#k zVS|v-fh)&1C?_0jW_p<8rr+9BcCer_MLn5Sf{Eo|$OiL-!&gsK4Unj>psS-3iTs63 z$hFsASMp2no|J~ovUNFbdNu@5q^h^M$ZYcf)^r3)IMQT+I+H~7s-4GtO z!UagsjS9$LF2xQE6Ur1(`4ljekh!RBORRi-Rg;*b5 zJieolYv{_AYriVr^^*tWu2g=nhV}&U#R)2?+NBg#S=3ZF*ZsjWxI0>a3-R-uHUZkt z4m}2|V_{*TCbVMm?jI+_Jtod6o+Ys+OBjg#Hz{u2=2^KejYfnQNuI*l-EpaFv5}^aKZ2je#`cc%6lZQvf)a)Zl87X? zY6#2~J$0?DqM{m->216YV&MQ*kafOY{A3xcqUnB&?-N}dEM}ah460zN>%JYI8Vvn; z;#d19T0P)Kp*4gJuSg< zxG;E3@h2-L;p_#~P9CuQ@L)ZYE21Ki_@I!m*I_X zvHk|%V2ITR)YR0_{y}l4Y?%-R{&s>yB3}l*a=RMIa$rx0(4lDh*I@G!ANwwF?L;z? zogL9P$+lOa)kLeUhPoj$R(~P^O)c*?7Bgcnf4=SAv~amgu0?LP7a{ z;}dctj-`{{AJomYd9K5Yxb0fMi?_Tu9RXlnlz2X(@q zbKDgUqE>I~TUmh20^p5O|^Us}Fa2*8t8gBB9( z9;FtWeW(CN;P1yR@C|OomBZdbLP9v!u2n5#V~5?<%aCix1ra&?LV$JXrEMdOsu&oF zJ)esJFOs4yJE;tTMi0aWUp(+F;nbV5cX6x6;~EdrqrB20Wa)J4{3a$>)Gja!fFILd zbwXsgJC5}m$2@)7cU`OiOGg<>Uax=7%Y9h{mT!sy`UT~nY3A|k($MfQzZ#dc^9p~? z)YW)*;C$D+^?26?5Y0EZ6jc^1iV=3(F|s3(4T@+*$R_=!ew7hcX#b{%bp7yog5hUE zATSCey+Nqu?-1BS{*(gZNeF*JX{o<})PYe@$N-OJxJtL>B1CYQ8XDfw)7Q`Nm>iNX zL!l{DvV&=F`AX1I#h@by+i;CTcoDZZP5=VI;motP!_GzdI7p!f?WI9vKHQZR{(1i@ zn=vwRNTC~G7vA=bLRURFG(Ag;MhOk>FylT=qrg&5ZVvx(B(~TWtg-LmMqWzyDdjuXoV}pICU}W6f7zH}6Nc9zXTfzn2HXB3uY=7XuW!b^Y3%A)tA+OWfYy zu5J_enz^9J+yth6OC0&#wsC8<_$X*RoWo>@wro6rcp`xQZaXGPFcGZmfFyrY94UN) z;^N}0L(t_L^0?c!!;n{TtG=XJT*pp~%slyFDy4uGACUk_k#v6#!vl~v0&E!MZ=o{c zcY9%QUA%s2*GjrmaQmOvTL%3+?l^|5g&MMMn%)8{VUzqGMrNd)6Mr5kOzU4 zKpyA*yMP7|^A3|Sdi3xUE{;l>uRY>AM<_56uEXu{@C{6^ zgwFqsh!ny3V;^Yda*Xu*_3r||Anb|G&X2Ij(!Dxbki7i{|4D_Wpfu)JyLRJ74ImoO z@eV-9W}HeBiyyP((Z8A17xHBY002cS%a^CSDpCAk!I*DHM5GY@7SZR_hX=R#i1vYK zQwuF|>E5;-3|!~#=H=}ZG08Ci^iffiJ=-L?a{W&KV0vaa@MVIUP)ifgWmhn{pN86< zi*%}J%Z!Es@>vcCP=2s>XA{8eiwnPwlaLNg2zWsjS6Bwb;KC2X}e79sf{|JXlc!aNma2*)lZTzQZ86Ck1p{Z!YwI;8l zjM%sY^H_YfmQaM<+tU_?3%K;uLjc#$S`naX%hg2`yk;xHzQw0 z`cfCVKeaLJGC$@S`7kjvX8(QYw4#j+masstCZagrJ&1Qzfja?B&{;*pX)OmW2|`2( zoe#JMkvu%zML@1SG|S3INhr{_vks|la#ap6XSJtZ@^%-EXOZ82L!TvzEol}Sc%L*^ z_;bqNldtl%I}h+6U*_Q8z^{g@i@l)hVk0-SK~~4Mh@)BOxLJn~P}OK)v3bE*qy0jW zIr2};IuBAJj{t9?5c>v$9R4Sz+Ci0z`voo=z;UZkWTROl&mSh)~D6ca=EwEqndQT!JpOP&)zMD%nx`F{dLROCrEN68OA7OEe_OjU!+umYJ2V}=M+&qX5$f1<_S_Rc?hnb1<=!{*n)D`?Wfle9L78v^& z3*K!<$RqD&Sl>n_u~$Ko>q zKp=+!fVc^>({y$ZH=~cYVwG+eC|^m|p~h9KR)KLwZ}Qo8OG?L?%`tSnnfGi4@(T(F zel^l;)0~@09L}wq`+g?957g@t=gZ7oka5f3y$eNQ4Nkc1cbim8Cl&c%OLyvfq(9K= zAQMQY^qd~M-T344MHbo9*cibEp*geD<7n0(>@ckZiVu3b&?XU&c2Z(?U<1|o2Jq%c zq$p^Rzh=-tfe$NaMCw`?1I?k$B%4=@XMi6?)EGd>K#_$8Z(_Z+6%1So>0tf9qQYFH z;`O1U2f-JOraN*plFJoTuQsNi3c?gX7$imh2Y5sQ6-2%2Z^=Ibd8w!Ye1gI zi825>8Gkh}Zc`e_1-&KLW#A6qLG-hqQ*Mb=pa-b%0VZfq24o;j_gDwO8j{Q0tJT`4 zLA3dEQfKy8{d)L+z(^DX`hrV9FSx+C3Z&UbZQ06|sLUbFBAieY$oeW|5&%t1g8n&@ z!9Wg>T!$Jy10k;HA*&-XB2MF^vEh~u$iWx@nR#IVQHFfKVL+d(^HDG-3T3_p=z}av zm<)9LHX>hBE*B$>bO5sujl(RArO+7_gm>=z zM5YHIkTyVZ17Cm{0yoJB;c5cbfD(#AERkHH;Ia;M(2W~t7H*L*D=8_V=T2GRiWX6R zev#7t05#AL(N6CKkNqd)iGhRRBavb<19Y^Cy%++ZeGCK&e3HPYM))w$-9!UXWTrS)D2Sc<%@}b*dPQYMaPL1EBmB;;Ahr#^6G0hq z4T7@z0(XiU$r>_70(MR;)sMww&CDS4pwUr8Edj2zr2}2jIKmSlp&{j5^Y=h+%7&dMnYckmu_>_ZENo3d zgHyM*_f!Z7XkImRHddjL7BqZz(I{F677$ZR4Dkyohpro>9p-%dn;x{qsz$XlIx}3^ z2VwOSh-fry8<9>t(xS{q^eUuIqLg0a{5n6H;!SE^j?J4>mag8~jV^}Ud}x|dMq?iQ zAfJ5IQZ_Ii_LH8DVv-81x=4EYbFkpdO(p|hGBk*kL1_Gr5N%@m4bslf&=(Jaaeq(# zcuO_DP|0xku7&2!1)gc7RBlcesZJM|6;YRzIru4mvg`hr9H&GfqvU5W53q)5IbahY zQ6jK?B93i?lw%y}V8XDsyOgk!oq<)h;^*4ranCdf34xxPg|R_(=|N=u{k_#&Z7-g% z#KA^VpQz~_J{%5ZG#V4wKyE}YW(4W0#0M^ks4dU{Qy0vw#HWTD(+FxFI~wG|D#&*p za0d5+W0ZW=Ie$|<(I2$2`Rw}FwvKuZh6A+SN9PKcH_l#PsFg^iFgH;uXN|%E{MD!N zmiO>n35#-eQtg1oslf#XMP6a$NX4~DDvAkae9>5&sdiaTbm)|PGk=bK&y85`nZhs= z>1P?z+Jv-1)#io{CXNjo+)D3r;=?M$o>)-HY6OxJ%>xbc0_Z3*Ha3Q=dXJB&<)mde z`DpeNfXdTo^`J$go2Cb?s$_Y~mMtSl9yN2=hZBn^0SV5>VWF&H?Bjtio@sx)t`zN> zazHHR!2BQD35L`DUtDIc1Eq6HX3W`c)qeC0IZO~uoA{#OGZC-gY~-6P>%TwL5?f&A zOuZ&8;2{K{Lqpi^4m`whb3f{{nZ*_B9{6%^&}Ke5;7NZRMXu)xZ^;b*TM z^fJdUI@b}|2;~&`GSUa(2|fj?`_eD7bW}OBR(9A6t@#Lp9%iw*RfmuC4sKS+@AICm z^FDay%rkPph(@a%s5p6a?FBR!hB(i=f2_#K6UlIUd&h~QKA<0kTTb(j3Z}zn)9X6yJcCmB7WvRUrZ4iTqB|zv wP3_p?NUdX)qE;|*QA_-pDSAc5|MWAHzDHfu*_eBx7=uz%(Na!UJm&Ym0AVn9f&c&j diff --git a/doc/source/tutorials/quickstart/figures/social_network.png b/doc/source/tutorials/quickstart/figures/social_network.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1b2d2fa9dafd78cb14b1922ee400724b65baa8 GIT binary patch literal 26448 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 1b48e1b7d..c8a57c355 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -1,7 +1,16 @@ =========== Quick Start =========== -This is a short condensed segment aimed at those who want a very quick and dirty rundown on the basics of *igraph*. For a more in depth explanation about what each part of this code is doing, check out `tutorial link.<>`_ + +This quick start will demonstrate the following: + +- Construct a *igraph* graph from scratch +- Set the attributes of nodes and edges +- Plot out a graph using matplotlib +- Save a graph as an image +- Export and import a graph as a ``.gml`` file + +This example is aimed at those with some familiarity with python and/or graphing packages, who would like to get some code up and running as fast as possible. .. code-block:: python @@ -10,50 +19,50 @@ This is a short condensed segment aimed at those who want a very quick and dirty # Construct a graph with 3 vertices n_vertices = 3 - edges = [(0, 1), (1, 2), (2, 0)] + edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (3, 4)] g = ig.Graph(n_vertices, edges) # Set attributes for the graph, nodes, and edges - g["title"] = "Cities of America" - g.vs["name"] = ["New York City", "San Francisco", "Los Angeles"] - g.vs["population"] = [8.62e+6, 8.74e+5, 4.08e+6] - g.es["distance"] = [4160, 559, 3980] + g["title"] = "Small Social Network" + g.vs["name"] = ["Daniel Morillas", "Kathy Archer", "Kyle Ding", "Joshua Walton", "Jana Hoyer"] + g.vs["gender"] = ["M", "F", "F", "M", "F"] + g.es["married"] = [False, False, False, False, False, False, False, True] # Set individual attributes - g.vs[2]["name"] = "Chicago" - g.vs[2]["population"] = 2.71e+6 - g.es[1]["distance"] = 2960 - g.es[2]["distance"] = 1180 + g.vs[1]["name"] = "Kathy Morillas" + g.es[0]["married"] = True # Plot in matplotlib + # Note that attributes can be set globally (e.g. vertex_size), or set individually using arrays (e.g. vertex_color) fig, ax = plt.subplots(figsize=(5,5)) ig.plot( g, target=ax, - layout=g.layout("circle"), # print nodes in a circular layout - vertex_size=0.07, # set vertex_size of all vertices at once - vertex_color=["lightblue", "orange", "orange"], # set colours individually - vertex_frame_color=["white", "white", "white"], + layout="circle", # print nodes in a circular layout + vertex_size=0.1, + vertex_color=["lightblue" if gender == "M" else "pink" for gender in g.vs["gender"]], vertex_frame_width=2.0, - vertex_shape=["circle", "rectangle", "triangle-down"], + vertex_frame_color="white", vertex_label=g.vs["name"], vertex_label_size=7.0, - edge_width=[1.2+dist/4000.0 for dist in g.es["distance"]], # longer distances = thicker edges + edge_width=[2 if married else 1 for married in g.es["married"]], ) plt.show() # Save the graph as an image file - fig.savefig('america.png') - fig.savefig('america.jpg') - fig.savefig('america.pdf') + fig.savefig('social_network.png') + fig.savefig('social_network.jpg') + fig.savefig('social_network.pdf') # Export and import a graph as a GML file. - g.save("america.gml") - g = ig.load("america.gml") + g.save("social_network.gml") + g = ig.load("social_network.gml") + -... and here is the graph generated by the code: +The output of the code is pictured below -.. figure:: ./figures/america.png - :alt: The visual representation of our city network - :align: center \ No newline at end of file +.. figure:: ./figures/social_network.png + :alt: The visual representation of a small friendship group + :align: center + The Output Graph From c83e057f6fa9c992e09a3edf2df124d1b43155dd Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Tue, 23 Nov 2021 19:14:39 +1100 Subject: [PATCH 0734/1892] Fix some minor mistakes --- .../assets/bipartite_mathing.py | 1 + .../bipartite_matching/bipartite_matching.rst | 13 +++---- .../shortest_paths/assets/shortest_path.py | 36 +++++++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 doc/source/tutorials/shortest_paths/assets/shortest_path.py diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py index 7a1f95fcb..790957270 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py @@ -36,6 +36,7 @@ ) plt.show() +# Output: # Matching is: # 0 - 5 # 1 - 7 diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index c8a2339f0..46703524d 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -40,20 +40,15 @@ And finally display the bipartite graph with matchings highlighted. .. code-block:: python - # Manually set the position of source and sink to display nicely - layout = g.layout_bipartite() - layout[9] = (2, -1) - layout[10] = (2, 2) - - fig, ax = plt.subplots() + fig, ax = plt.subplots(figsize=(7, 3)) ig.plot( g, target=ax, - layout=layout, + layout=g.layout_bipartite(), vertex_size=0.4, vertex_label=range(g.vcount()), - vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], - edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] + vertex_color="lightblue", + edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] ) plt.show() diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path.py b/doc/source/tutorials/shortest_paths/assets/shortest_path.py new file mode 100644 index 000000000..1234c1e14 --- /dev/null +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path.py @@ -0,0 +1,36 @@ +import igraph as ig +import matplotlib.pyplot as plt + +# Find the shortest path on an unweighted graph +g = ig.Graph( + 6, + [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] +) + +# g.get_shortest_paths() returns a list of vertex ID paths +results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] + +if len(results[0]) > 0: + # The distance is the number of vertices in the shortest path minus one. + print("Shortest distance is: ", len(results[0])-1) +else: + print("End node could not be reached!") + +# Find the shortest path on a weighted graph +g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] + +# g.get_shortest_paths() returns a list of edge ID paths +results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] + +if len(results[0]) > 0: + # Add up the weights across all edges on the shortest path + distance = 0 + for e in results[0]: + distance += g.es[e]["weight"] + print("Shortest weighted distance is: ", distance) +else: + print("End node could not be reached!") + +# Output: +# Shortest distance is: 3 +# Shortest weighted distance is: 8 \ No newline at end of file From 3d074b2f3433abbfbbf4e7748c328a1c91da39a7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 24 Nov 2021 20:32:25 +0100 Subject: [PATCH 0735/1892] fix: fix drawing of graphs with a single graph and a single loop edge when using the Maptlotlib backend, fixes #462 --- src/igraph/drawing/graph.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 41a950110..5210eb256 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -993,7 +993,7 @@ def shrink_vertex(ax, aux, vcoord, vsize_squared): """Shrink edge by vertex size""" aux_display, vcoord_display = ax.transData.transform([aux, vcoord]) d = sqrt(((aux_display - vcoord_display) ** 2).sum()) - fr = sqrt(vsize_squared) / d + fr = sqrt(vsize_squared) / d if d > 0 else 0 end_display = vcoord_display + fr * (aux_display - vcoord_display) end = ax.transData.inverted().transform(end_display) return end @@ -1178,10 +1178,19 @@ def callback_edge_offset(event): xi, yi = x[i], y[i] ax.text(xi, yi, lab, fontsize=label_size) - dx = max(x) - min(x) - dy = max(y) - min(y) - ax.set_xlim(min(x) - 0.05 * dx, max(x) + 0.05 * dx) - ax.set_ylim(min(y) - 0.05 * dy, max(y) + 0.05 * dy) + # Find the X and Y range of coordinates; use a minimum range even if there + # is only one vertex to avoid singularities and division by zero later + dx, dy = max(x) - min(x), max(y) - min(y) + if dx <= 0: + dx = 1 + ax.set_xlim(min(x) - dx / 2, max(x) + dx / 2) + else: + ax.set_xlim(min(x) - 0.05 * dx, max(x) + 0.05 * dx) + if dy <= 0: + dy = 1 + ax.set_ylim(min(y) - dy / 2, max(y) + dy / 2) + else: + ax.set_ylim(min(y) - 0.05 * dy, max(y) + 0.05 * dy) # Edge properties ne = graph.ecount() From 8e715812d3f5efaffa1eee5f0582756498e5f180 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 26 Nov 2021 00:57:36 +1100 Subject: [PATCH 0736/1892] Unarchive bipartite matching using max flow --- .../bipartite_matching/bipartite_matching.rst | 60 ------------- .../assets/bipartite_matching_maxflow.py} | 13 ++- .../bipartite_matching_maxflow.rst | 84 ++++++++++++++++++ .../figures/bipartite_matching_maxflow.png} | Bin doc/source/tutorials/maxflow/maxflow.rst | 4 - 5 files changed, 96 insertions(+), 65 deletions(-) delete mode 100644 doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst rename doc/source/tutorials/{archived/bipartite_matching/assets/maxflow2.py => bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py} (69%) create mode 100644 doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst rename doc/source/tutorials/{archived/bipartite_matching/figures/maxflow2.png => bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png} (100%) diff --git a/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst deleted file mode 100644 index 4dcef0291..000000000 --- a/doc/source/tutorials/archived/bipartite_matching/bipartite_matching.rst +++ /dev/null @@ -1,60 +0,0 @@ -========================== -Maximum Bipartite Matching -========================== - -This example demonstrates how to visualise bipartite matching using max flow. - -.. code-block:: python - - # Generate the graph - g = ig.Graph( - 9, - [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], - directed=True - ) - - # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side - for i in range(4): - g.vs[i]["type"] = True - for i in range(4, 9): - g.vs[i]["type"] = False - - g.add_vertices(2) - g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side - g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other - - flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1 - print("Size of the Maximum Matching is:", flow.value) - -And to display the flow graph nicely, with the matchings added - -.. code-block:: python - - # Manually set the position of source and sink to display nicely - layout = g.layout_bipartite() - layout[9] = (2, -1) - layout[10] = (2, 2) - - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout=layout, - vertex_size=0.4, - vertex_label=range(g.vcount()), - vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], - edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] - ) - plt.show() - -The received output is: - -.. code-block:: - - Maximal Matching is: 4.0 - -.. figure:: ./figures/maxflow2.png - :alt: The visual representation of maximal bipartite matching - :align: center - - Maximal Bipartite Matching \ No newline at end of file diff --git a/doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py similarity index 69% rename from doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py rename to doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py index 844d12306..5fa0c3e82 100644 --- a/doc/source/tutorials/archived/bipartite_matching/assets/maxflow2.py +++ b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py @@ -19,7 +19,18 @@ g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other flow = g.maxflow(9, 10) -print("Size of the Maximal Matching is:", flow.value) +print("Size of Maximum Matching (maxflow) is:", flow.value) + +# Compare this to the "maximum_bipartite_matching()" function +g2 = g.copy() +g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded for this function. +matching = g2.maximum_bipartite_matching() + +matching_size = 0 +for i in range(4): + if matching.match_of(i): + matching_size += 1 +print("Size of Maximum Matching (maximum_bipartite_matching) is:", matching_size) # Manually set the position of source and sink to display nicely layout = g.layout_bipartite() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst new file mode 100644 index 000000000..2f7145a05 --- /dev/null +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -0,0 +1,84 @@ +========================================== +Maximum Bipartite Matching by Maximum Flow +========================================== + +This example presents how to visualise bipartite matching using maximum flow. Please note that the *igraph* already has :meth:`maximum_bipartite_matching` which is better suited for finding the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching<>`_. This particular example is purely for demonstrative purposes. + +.. TODO: add link to Maximum Bipartite Matching + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + # Generate the graph + g = ig.Graph( + 9, + [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], + directed=True + ) + + # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side + for i in range(4): + g.vs[i]["type"] = True + for i in range(4, 9): + g.vs[i]["type"] = False + + g.add_vertices(2) + g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side + g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other + + flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1.0 + print("Size of Maximum Matching (maxflow) is:", flow.value) + +Let's compare the output against :meth:`maximum_bipartite_matching` + +.. code-block:: python + + # Compare this to the "maximum_bipartite_matching()" function + g2 = g.copy() + g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded + + matching = g2.maximum_bipartite_matching() + + matching_size = 0 + for i in range(4): + if matching.match_of(i): + matching_size += 1 + print("Size of Maximum Matching (maximum_bipartite_matching) is:", matching_size) + +And finally, display the flow graph nicely with the matchings added + +.. code-block:: python + + # Manually set the position of source and sink to display nicely + layout = g.layout_bipartite() + layout[9] = (2, -1) + layout[10] = (2, 2) + + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout=layout, + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], + edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] + ) + plt.show() + +The received output is: + +.. code-block:: + + Size of Maximum Matching (maxflow) is: 4.0 + Size of Maximum Matching (maximum_bipartite_matching) is: 4 + +.. figure:: ./figures/bipartite_matching_maxflow.png + :alt: The visual representation of maximal bipartite matching + :align: center + + Maximal Bipartite Matching + +Note that maximum flow will represent the capacities as real values, which is why our result is ``4.0`` instead of ``4``. diff --git a/doc/source/tutorials/archived/bipartite_matching/figures/maxflow2.png b/doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png similarity index 100% rename from doc/source/tutorials/archived/bipartite_matching/figures/maxflow2.png rename to doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index 152aec214..84cd755fa 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -9,10 +9,6 @@ This example shows how to construct a max flow on a directed graph with edge cap import igraph as ig import matplotlib.pyplot as plt -Max flow on a directed weighted flow graph - -.. code-block:: python - # Generate the graph with its capacities g = ig.Graph( 6, From a204c7670edd7569b011e5ca14c66d394c191795 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 26 Nov 2021 00:57:51 +1100 Subject: [PATCH 0737/1892] Update bipartite_matching to use Graph.Bipartite --- .../assets/bipartite_mathing.py | 18 ++++++----------- .../bipartite_matching/bipartite_matching.rst | 20 +++++++++---------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py index 790957270..65c5d83dc 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py @@ -1,17 +1,12 @@ import igraph as ig import matplotlib.pyplot as plt -g = ig.Graph( - 9, +# Assign nodes 0-4 to one side, and the nodes 5-8 to the other side +g = ig.Graph.Bipartite( + [0,0,0,0,0,1,1,1,1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) - -# Assign nodes 0-4 to one side, and the nodes 5-8 to the other side -for i in range(5): - g.vs[i]["type"] = True -for i in range(5, 9): - g.vs[i]["type"] = False - +assert(g.is_bipartite()) matching = g.maximum_bipartite_matching() @@ -36,11 +31,10 @@ ) plt.show() -# Output: # Matching is: # 0 - 5 # 1 - 7 # 2 - 8 -# 3 - None -# 4 - 6 +# 3 - 6 +# 4 - None # Size of Maximum Matching is: 4 diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 46703524d..59c636a52 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -2,23 +2,21 @@ Maximum Bipartite Matching ========================== -This example demonstrates how to find and visualise a maximum biparite matching. First construct a bipartite graph +This example demonstrates an efficient way to find and visualise a maximum biparite matching. First construct a bipartite graph .. code-block:: python import igraph as ig import matplotlib.pyplot as plt - g = ig.Graph( - 9, + # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side + g = ig.Graph.Bipartite( + [0,0,0,0,0,1,1,1,1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) + assert(g.is_bipartite()) - # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side - for i in range(5): - g.vs[i]["type"] = True - for i in range(5, 9): - g.vs[i]["type"] = False + matching = g.maximum_bipartite_matching() Then run the maximum matching, @@ -60,12 +58,12 @@ The received output is 0 - 5 1 - 7 2 - 8 - 3 - None - 4 - 6 + 3 - 6 + 4 - None Size of Maximum Matching is: 4 .. figure:: ./figures/bipartite.png :alt: The visual representation of maximal bipartite matching :align: center - Maximum Bipartite Matching \ No newline at end of file + Maximum Bipartite Matching From 2f94b19c3a9410d6a9ef569c0d48d9d0537bd756 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 26 Nov 2021 01:19:50 +1100 Subject: [PATCH 0738/1892] Add Erdos Renyi Graph generator example --- .../bipartite_matching_maxflow.rst | 4 +- .../erdos_renyi/assets/erdos_renyi.py | 57 +++++++++++ .../tutorials/erdos_renyi/erdos_renyi.rst | 91 ++++++++++++++++++ .../erdos_renyi/figures/erdos_renyi_m.png | Bin 0 -> 153627 bytes .../erdos_renyi/figures/erdos_renyi_p.png | Bin 0 -> 100941 bytes 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py create mode 100644 doc/source/tutorials/erdos_renyi/erdos_renyi.rst create mode 100644 doc/source/tutorials/erdos_renyi/figures/erdos_renyi_m.png create mode 100644 doc/source/tutorials/erdos_renyi/figures/erdos_renyi_p.png diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 2f7145a05..97b36c08d 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -4,7 +4,7 @@ Maximum Bipartite Matching by Maximum Flow This example presents how to visualise bipartite matching using maximum flow. Please note that the *igraph* already has :meth:`maximum_bipartite_matching` which is better suited for finding the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching<>`_. This particular example is purely for demonstrative purposes. -.. TODO: add link to Maximum Bipartite Matching +.. TODO: add link to Maximum Bipartite Matching .. code-block:: python @@ -47,7 +47,7 @@ Let's compare the output against :meth:`maximum_bipartite_matching` matching_size += 1 print("Size of Maximum Matching (maximum_bipartite_matching) is:", matching_size) -And finally, display the flow graph nicely with the matchings added +And finally, display the original flow graph nicely with the matchings added .. code-block:: python diff --git a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py new file mode 100644 index 000000000..1b8127965 --- /dev/null +++ b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py @@ -0,0 +1,57 @@ +import igraph as ig +import matplotlib.pyplot as plt +import random + +# Set a random seed for reproducibility +random.seed(0) + +# Generate two Erdos Renyi graphs based on probability +g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) +g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) + +# Generate two Erdos Renyi graphs based on number of edges +g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) +g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) + +# Print out summaries of each graph +ig.summary(g1) +ig.summary(g2) +ig.summary(g3) +ig.summary(g4) + +fig, axs = plt.subplots(1, 2, figsize=(10, 5)) +ig.plot( + g1, + target=axs[0], + layout="circle", + vertex_color="lightblue" +) +ig.plot( + g2, + target=axs[1], + layout="circle", + vertex_color="lightblue" +) +plt.show() + +fig, axs = plt.subplots(1, 2, figsize=(10, 5)) +ig.plot( + g3, + target=axs[0], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 +) +ig.plot( + g4, + target=axs[1], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 +) +plt.show() + +# IGRAPH U--- 15 18 -- +# IGRAPH U--- 15 21 -- +# IGRAPH U--- 20 35 -- +# IGRAPH U--- 20 35 -- diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst new file mode 100644 index 000000000..cee25705e --- /dev/null +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -0,0 +1,91 @@ +================= +Erdős-Rényi Graph +================= + +This example demonstrates how to generate `Erdős-Rényi Graphs`_. There are two variants of graphs: + +- :meth:`Erdos_Renyi(n, m)` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. +- :meth:`Erdos_Renyi(n, p)` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. + +We generate two graphs of each, so we can confirm that our graph generator is truly random. + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import random + + # Set a random seed for reproducibility + random.seed(0) + + # Generate two Erdos Renyi graphs based on probability + g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) + g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) + + # Generate two Erdos Renyi graphs based on number of edges + g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) + g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) + + # Print out summaries of each graph + ig.summary(g1) + ig.summary(g2) + ig.summary(g3) + ig.summary(g4) + + fig, axs = plt.subplots(1, 2, figsize=(10, 5)) + ig.plot( + g1, + target=axs[0], + layout="circle", + vertex_color="lightblue" + ) + ig.plot( + g2, + target=axs[1], + layout="circle", + vertex_color="lightblue" + ) + plt.show() + + fig, axs = plt.subplots(1, 2, figsize=(10, 5)) + ig.plot( + g3, + target=axs[0], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 + ) + ig.plot( + g4, + target=axs[1], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 + ) + plt.show() + +The received output is: + +.. code-block:: + + IGRAPH U--- 15 18 -- + IGRAPH U--- 15 21 -- + IGRAPH U--- 20 35 -- + IGRAPH U--- 20 35 -- + +.. figure:: ./figures/erdos_renyi_p.png + :alt: The visual representation of a randomly generated Erdos Renyi graph + :align: center + + Erdos Renyi random graphs with probability ``p`` = 0.2 + +.. figure:: ./figures/erdos_renyi_m.png + :alt: The second visual representation of a randomly generated Erdos Renyi graph + :align: center + + Erdos Renyi random graphs with ``m`` = 35 edges + +Note that even when using the same random seed, results can still differ depending on the machine the code is being run from. + + + diff --git a/doc/source/tutorials/erdos_renyi/figures/erdos_renyi_m.png b/doc/source/tutorials/erdos_renyi/figures/erdos_renyi_m.png new file mode 100644 index 0000000000000000000000000000000000000000..455c3bd28862d68fcd61e27084bb9309b79400ba GIT binary patch literal 153627 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
    +jKwqQ*f&j!qIg{)8^XJ3$E>@FM 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 literal 0 HcmV?d00001 From 0950bb4903c43120312c7118db2eb22370a902e4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Nov 2021 10:04:36 +0100 Subject: [PATCH 0739/1892] fix: setup.py develop works again, refs #464 --- setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 86b13d57b..d4d5202a9 100644 --- a/setup.py +++ b/setup.py @@ -823,7 +823,12 @@ def use_educated_guess(self) -> None: "Source Code": "https://github.com/igraph/python-igraph", }, ext_modules=[igraph_extension], - package_dir={"igraph": "src/igraph"}, + package_dir={ + # make sure to use the next line and not the more logical and restrictive + # "igraph": "src/igraph" because that one breaks 'setup.py develop'. + # See: https://github.com/igraph/python-igraph/issues/464 + "": "src" + }, packages=["igraph", "igraph.app", "igraph.drawing", "igraph.remote"], scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], From 9704fb59a5a84507ce845298d0b25f9200f1aa5d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 26 Nov 2021 10:06:37 +0100 Subject: [PATCH 0740/1892] fix: add Homebrew lib dir to the list of folders where we look for igraph libs --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index d4d5202a9..8e9d29b76 100644 --- a/setup.py +++ b/setup.py @@ -67,6 +67,7 @@ def find_static_library(library_name: str, library_path: List[str]) -> Optional[ variants = ["lib{0}.a", "{0}.a", "{0}.lib", "lib{0}.lib"] if is_unix_like(): extra_libdirs = [ + "/opt/homebrew/lib", # for newer Homebrew installations on macOS "/usr/local/lib64", "/usr/local/lib", "/usr/lib/x86_64-linux-gnu", From 25c0f9bbbf462a591c41140f292b71c1f4c9e3b0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 29 Nov 2021 09:16:22 +0100 Subject: [PATCH 0741/1892] fix: tutorial incorrectly indicated that colors as RGB tuples/lists use the range 0-255, fixes #465 --- doc/source/tutorial.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 86a29a4a4..df8a0cf2a 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -959,8 +959,8 @@ Color specification in CSS syntax - ``rgb(R, G, B)``, components range from 0 to 255 or from 0% to 100%. Example: ``"rgb(0, 127, 255)"`` or ``"rgb(0%, 50%, 100%)"``. -List, tuple or whitespace-separated string of RGB values - Example: ``(255, 128, 0)``, ``[255, 128, 0]`` or ``"255, 128, 0"``. +Lists or tuples of RGB values in the range 0-1 + Example: ``(1.0, 0.5, 0)`` or ``[1.0, 0.5, 0]``. Saving plots From c2a48432fc3aa6123052673678e2375cba36b2aa Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 30 Nov 2021 07:15:19 +1100 Subject: [PATCH 0742/1892] fix: center vertex labels in matplotlib --- src/igraph/drawing/matplotlib/graph.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 4578249e2..3c7742efc 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -255,7 +255,9 @@ def draw(self, graph, *args, **kwds): *coords, vertex.label, fontsize=label_size, - # TODO: alignment, overlap, offset, etc. + ha='center', + va='center', + # TODO: overlap, offset, etc. ) # Construct the iterator that we will use to draw the edges From faeb9bf3e6c0580c7164a0e6deb5e3be7f14f336 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 30 Nov 2021 15:23:41 +1100 Subject: [PATCH 0743/1892] Custom edge colors --- .../tutorials/quickstart/assets/quickstart.py | 1 + .../quickstart/figures/social_network.png | Bin 26448 -> 26637 bytes .../tutorials/quickstart/quickstart.rst | 1 + 3 files changed, 2 insertions(+) diff --git a/doc/source/tutorials/quickstart/assets/quickstart.py b/doc/source/tutorials/quickstart/assets/quickstart.py index 2db46d73b..2114377c9 100644 --- a/doc/source/tutorials/quickstart/assets/quickstart.py +++ b/doc/source/tutorials/quickstart/assets/quickstart.py @@ -30,6 +30,7 @@ vertex_label=g.vs["name"], vertex_label_size=7.0, edge_width=[2 if married else 1 for married in g.es["married"]], + edge_color=["#F00" if married else "#000" for married in g.es["married"]], ) plt.show() diff --git a/doc/source/tutorials/quickstart/figures/social_network.png b/doc/source/tutorials/quickstart/figures/social_network.png index 4c1b2d2fa9dafd78cb14b1922ee400724b65baa8..562ca0541aaaaad10b70de9702f69209113b5f3c 100644 GIT binary patch literal 26637 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 z'yf9Qc*%Di>9ziNF=+1$dyxaiEm!lo={1`cNRf5sk!9*ooGkt&DwXAdACTDi! zOLus_c`4h@JJkEBxyI3}B4A9X>Irsj11dXFM@{o`F8y!f*4Mk7Qtg#+l~f z;9@WMCPZh{+pvdd)4-V#ekJ^R`ucT&WE9qpj@N+S9F8P9WcOBto_v&NMwXRD)6dV( zr0Wsj)2_(iuIdiz{C=+g&hqs3!}m3$5;9M}ji0EStHw=?NlV*;l9fp}B@wS2#Z6(~ zOxnA*dUd(Fz@|EgBCumpLq{nxD32Q7Iyot+D||e6b$P*VtUcQdXa{Ho3+8!i8=2Q- zvZF_B^C_?KtVMXr zoqXxmZ2B}4TAdL!HI1fd+e7=jqjg5v*toe9hL)yFN)!mXwDXR^hwyuei4m%zk=tZt zS^bt~gF-_oKjmBHKex%7Q}Q4meory{j%?@7kmU#A;S{O9C>~i&JfljuhTY&;ICW

  • v1rtwQuh(6Rat3QXuUpL9ee_v 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 I?D>cO2NEF>V*mgE diff --git a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py index 1b8127965..b546d0dfd 100644 --- a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py +++ b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py @@ -26,12 +26,14 @@ layout="circle", vertex_color="lightblue" ) +axs[0].set_aspect(1) ig.plot( g2, target=axs[1], layout="circle", vertex_color="lightblue" ) +axs[1].set_aspect(1) plt.show() fig, axs = plt.subplots(1, 2, figsize=(10, 5)) @@ -42,6 +44,7 @@ vertex_color="lightblue", vertex_size=0.15 ) +axs[0].set_aspect(1) ig.plot( g4, target=axs[1], @@ -49,6 +52,7 @@ vertex_color="lightblue", vertex_size=0.15 ) +axs[1].set_aspect(1) plt.show() # IGRAPH U--- 15 18 -- diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index cee25705e..41da76d88 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -39,12 +39,14 @@ We generate two graphs of each, so we can confirm that our graph generator is tr layout="circle", vertex_color="lightblue" ) + axs[0].set_aspect(1) ig.plot( g2, target=axs[1], layout="circle", vertex_color="lightblue" ) + axs[1].set_aspect(1) plt.show() fig, axs = plt.subplots(1, 2, figsize=(10, 5)) @@ -55,6 +57,7 @@ We generate two graphs of each, so we can confirm that our graph generator is tr vertex_color="lightblue", vertex_size=0.15 ) + axs[0].set_aspect(1) ig.plot( g4, target=axs[1], @@ -62,6 +65,7 @@ We generate two graphs of each, so we can confirm that our graph generator is tr vertex_color="lightblue", vertex_size=0.15 ) + axs[1].set_aspect(1) plt.show() The received output is: diff --git a/doc/source/tutorials/erdos_renyi/figures/erdos_renyi_m.png b/doc/source/tutorials/erdos_renyi/figures/erdos_renyi_m.png index 455c3bd28862d68fcd61e27084bb9309b79400ba..0d644d2116358fc9b83c4ae9b21dce84efaade3e 100644 GIT binary patch literal 135643 zcmeFZg;!N;)Hk{T>6Da^5D5tdrKCYDkWQ6GLK^7~326|e8%aqKLApUfLg@|(>F&65 zo$r0`xPQYP-x4g`;wSDs39)%({Kz^a+N#wppp`lPuWu(+xlGi33wbWi7VsC9K z`LW}DGsJ!ujOXO6hp&9|nXEE-_8OzQ8Ucy2G|5%VlF6bxt-N8GQcRgo20fdR$7Ont zNaAOG=Id5>MK^bK^-X%QsC%Bfm(<1j%nK3ulStz*A-^3L{q;J$@_+u0d;v}Pzc0gY zH^|r}+5Y$YUZF6T|M&0j2+~n0|NHaNXyoZ+|MOZ*cYV+u{`c=PSV}$$|NFX~D7-%0 z|9xR<$^XxrVEo@V`EOnS?{fXmj{3j5>;La{LjGUF`6TrG`E!@O<*QS5?${YhID~|R zUoD1-%+1Xk+|8jRF0$&qFC$J5H<@{PufBQnrf*de_-Z*Bf+?lvUYYhz33rc-ypwnU|^TFr=|o&bFnu9@bH5(>OInUtC;F zf^%ho&q%s6EeyK$yJs^(MCGQv?L$Q`4Qg$9AIVolnF*fFhI48OI#VVJT7>K__4FSj z?L9j-IXTSh{B-^}G)}9upV+F};m)>wfHV`)=8jb9lDXE)mo4MtNq!E}Ps)()-g(8_ z+q*lS7h{oAl*eq2Jip!L{O{G+gs_e+g9l}TTwzPpq%ep|c;khxdNWA)Qb=7joA^?p zW|TZuLtEcP*)%=P@Fz!p-Zc;|j}{pu4LaJ|bT2Bb!xheh^uMhJs)RcpcY0ZB3DI7? zdi9#1HJt?6O@ES|G_tE#eR0WH^{2+Tm+u=s%WvOtiVqT5QkdD!dYq@%Ag*}trvDi& zY@|+aC2Q;3LJ@EM{4Dw2lz#j6XnD%kQrL^Sz+7FHpR&Wwwt}zi(Aj2tZB#Yk3EPK? zG(jf+&P><|oj-p3kSSAy4b07LrItTT5+UxJT_5|&OEK_QUnKc!oZ2nt&6x_LMVv~5iX_s&9mwL8&9{garc~k%VWdGWIbMlpe z{4TGlj~tqhBI(5pOihD=h#4+ozh9MpSLkxI#k97z)|d5IQLR9mIwT|{DlYDEim)T^ zn*nwgS63z`rrFBw^@;EHF57eWFA`t>>XI%gctJtH6YtlU&iLumr!9CdG0zinA|j&Y z$z0-r0yW>v%p2t7FV+?|Yn{P?yk4$aJr-K2dnq*yxKfyS`4y&0X{+Y5wB;l-GJf$Wp|f zjGzDb=_$Y#`=Eo?PNuh|R^tM??Oefs|Gp9u64D+W>!_+W-etO7j8bNqlul~yZ3V(XmG=;pw zn52A`uz$0*hZ}8ZT;wM6;sIf2*AD|&QCoX^&f&SV*w|R1H*@3y^bOrFS%;R6gtUm3 z!#X>kgk2YjjpLP@`}Zfew5+TN{!o6HMFXEG^XX@Syccz>LJIGCx9wc^kI?8RYq1pK zLvN|(H2(QRHdsKRlb=eWBEUZVKFT|vj7_0&pqtbrU)w#+x``_c?aDIbGZ z*&+?5WB1Lb>%}G}CiIPrRB!*ARaREc(Fe)x35ebw9j)>_xOrfuLo6mH#-&$J7ZDM0H#$NQhsii#UZ|?N+HmxX zao+GJ>NNq&Al=I*B_%bkz3m^kdUhsy?C58;c7Kn(7bKq~&;&hZaAlxHyZ6_!u!|7+M-K9nqYpMug&Mr?-0%>b z9hvrK=3zuV2qd_*>q;u!svIK1bSdqAxY73RDsy`NAfE2y9-{%iP(7?ARC=BoTHT|F zwlR!c9{o(-#a~I-?(Xg%9{b5Zdq%KQ$zDDDosY)6qIJF_(uJXt=W!%`Te{TSblpm{ zAqMeCJ4%6v2c7ClYBIx2%ro?MbXhqsn?^^e;a)E6?6UetP5aIZX=!OS!q>7)wOYjH zu2d6IZ+Femp$gPKN5GG3c^`=u4CO~ky~UaxDKlEQI~^b2VV2i+S&=Ul8tZa)#Jf3v z5jHP0GCpoJRqJ}q%*?L>TQO_6v#f!j2QB@Lx?@{P?la+0nMy^k;^}l0)Cj_bS0@pJB~nmPWHQ≈T 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
    +jKwqQ*f&j!qIg{)8^XJ3$E>@FM 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

    wAN<}J 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 literal 100941 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 diff --git a/doc/source/tutorials/maxflow/assets/maxflow.py b/doc/source/tutorials/maxflow/assets/maxflow.py index b28b81bfc..643e135b7 100644 --- a/doc/source/tutorials/maxflow/assets/maxflow.py +++ b/doc/source/tutorials/maxflow/assets/maxflow.py @@ -22,6 +22,7 @@ vertex_label=range(g.vcount()), vertex_color="lightblue" ) +ax.set_aspect(1) plt.show() # Output: diff --git a/doc/source/tutorials/maxflow/figures/maxflow.png b/doc/source/tutorials/maxflow/figures/maxflow.png index 8cd123fe71d00501773db7b412696f4f462893e1..b370748d1c9b93745e094beb37ab4234ee90412b 100644 GIT binary patch literal 27330 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 literal 27217 zcmeGEhd-9@A3l!XNV`M{B}!I^kUc9ai9%LnlOiM8t7(?3BC`?|B`FdaW$%%Yy(ydQ z@jEWB_viEb{te&9x5wl4c;UXU`#P`le4fYi`82TU^|IK+I3b*PMt&| z_aTwUy0>n|Uxe!0`|-a`H&36{+=_o5Th09N`!+iz-J2v5l`-)j*=w0(EBsN+QC`PU z!`8yl+1SCHWMk}TXKm|fZDn%U$=u$lB&5|7EB+VqN3iI#j5i_lLJnflr2F6NL{`91Uk<*{aQ&0=vGB313KgFHVZ zv*X?Kn+weZqV`bZUrx_eM-uTvxjvT<3;sDNP+pLelPjuuO$zYy^J`(Cl_g%5cuCHQ zS4}K6N%DAkG-!JQUiFK;NVX5JrVIXm7yrL|!t8~`ef*>Xf`a;IM;ePtNvlo}%L7C>g=HxH!$%7jEC7+;QO0Mb=8h zOS#dTH*ZGUv%@}LZ+2KHqdtA+Og1&cVpeeNQyH126zyb-hX+1cH9jbLc(AX(KiuD6 zJ}4qI^!uYj5<2-_Qi@*dv8JVu?Eel{=X-kKbKhvaJHYodwLE7c@7#|EyX+l*`kd>x zXH;PiD<9s&(t7dgRn8rByk?65wE6*l2}U6%;b~JWY}}eJaRW|^*F z3!vpw&3bPz(vc%_DMd?Y$;Q8h6+4VO$6;Xm`a-FU&KJ8Q*)xNE5&LZ$Km5zlbem!e zRLEfu^KZ;&HW_;GdFA8c!525=8Zs=^Fh7b@y~To)hy2Xm`}u8^UYR`egx5g1lbq6Z z;GOf;mL&tOpDy(;YE`aX<4WE=p|)J*k##%gV%BhDGL@mn6y=pGR~Qy{%Y9@b25?qc zndR_dAHI@@Kgx?ERDXQ4>dfY-;pH9abXIl{XwypTPO(~R4-71>tqrD(?Tf2RgKHx5`8MamavdI;d6Q;78+Zh5oUeQvbp-MHt7sN+eo8A;23&HjP@7XMPMto2X&>hb+D`S&O7 zm{w|Jlc6H(OM|bD{&Qmzc9V6d^uCGs%-vP!4H10WWXLgCW203a`F-&5V(!wPlvKU! z(C_zmTwc8;_wfL&Y>1=ytv~y!yF9{%TSQA#qvRug|BJJd=~1N0@ElWqG}d;e|5aeW z8!sR2wO>hXoH7AVj?EXCs;ztZ`5#^G8yqc~@A6dqe61;UN=r^a9sxysRMEb@(v5=` zo|gpHeu`gc(fL&yT{zN3MeQ|vg5UXupmn?1vrm6l>P&+ty3TbE-|nv&DgSl+^6LxF zPrG$JPb{-NB?<-a77PPtX zwUSwOK<^e4r#DId+|yTbive;g_DdnPQ&q8B;;n9qxz91KF3l_E*ZRK`h*FsyYYx6S zRNJ>akn8wVhD4_=GQFS2tp29MP<8P9PqBLsm@J3uo-bATb*SUXH~(!;v&3fJx#UQ0 z{#LX0Loaq{^VY-V=+B}ANl0QEBC6<0PuhjYM!1g0AQf11a zB+gqq^Un-%IRP`POaC5NQ1b^MJ>FMg-y83>#8BIuqSlvrNO1PE*P7EVZ2sq7mCj7d zU$pf;B{}tpER4?7o;`cEyiO%_^__0UgEtzF1Dj_y7K4f7F+X`NitvdWI!&thV5MM)2#|(>4dP#%7C3 zo#_RheF)>w{pNP-!C>epA208tT?d6vn3e5$uEXPU#ardOKCk5%#V$;i`HVqZv~WxaWuX^8D0GM}w(o>bIB^ ztmteMbxtBVr^)S>79FoebE;jPH!SOqzvXdzIGp3b|3LyVHeD-LS*E=(Vr$&=;g-a1 zCP`UMP0a^pdzWeH=t=>B3<73b&-m^(?<;wzc1v^e*SpJ%k}f_E-nE&ZR<0Bk6|Dn` zj<#k*fB7Q%vd_fv@I*Rzu)Zb&$rP>meq2f7Azc@uwQIvklubp&VQQrxSLnR z?^_51T*q-{+Mg67?fLAOMp9k&O-nq>_mRfnJmo_t)(ukiB}}CSM=oVM8H9#~wPxAI z6O$Ez$)a=``z>G7?#g-bd1%voY-s4|?#RLzaSzhOv5Ysfz328%ytMOI@8{EujFoWK zlZr1hEG{k0uua3NKn zvL;UI`achr;G0XcR!OR{6?i^Zth-g~N45yAO9I{&0)N8&&z~FGOXvCYa&sEl2k&LA z8wNS#1(&6kdZW1KP2(qqhn4I-EsA!(0e~Oo<=x%PC?;UmHKclv+{(~sIm^~_xHdkC zME+&a&a(Nvf#cZkrnielUWr2x36+7dJR$%>mfoxy8?09>& zf3|6xc8h{y$M?p@FmlT6^oQg>zW(y%i>3JX;gONEjY;RNn%>fyS3aR^7$-T1_Xd1E zs&{F2jMHJD!rXCZh{`J>WPg9YF6cgI-D~n7&QtkxF+r?+SXv(yEWuuU1^H z2tPKH6@0xefy{q?e5y44sAf&VKv=`k(K<494UK=;VJO{AZYxJ{h2+bUJsR(@38S2B z>6GfPiU>R)bd7lSH*YVcG`zjUjbHCYw}k}{H>K+Ct&I^ATl#w=n#ZSfZY)W*@Q!Bc z)z)XxEV{A3FpWNU?^47{-0Ce&d%D-wRC^bD=Q*RwfMUn1T}+mit2a1)g$Y`!{?4?i zM2tm=-{Pu{7V&;Ny~T=7_14v{xZ~XW!(8}|+zr!Xmu7!plk%iKTO)brK?rx4qON#c)Z3|{hU z6Jc4j|F@l+LnVGfn}_9y@Pqj-?=E6GYlwCyX!nuOrrC+E_@=+V1jlj=)IQhfC>S;ub6`n^|1$ z{&w1(l`PZFsh?=#u=&__P* z6n@#N`!(FNEzfdn^zfMsYn_w69npElJ$ER%yiGE=v{K8yQ|@T_Y$bJ&u2$$|<+E19 z>9)Cd_jnB6PIEX_j&!ZB&F4SFgVSD0)d~6eQ`2HoP_j(H*<-q#W9NaBoQ;NtMOrA} z5`SDz`&JSqXc;LrCF9axasK|Z&jL1|{;dWSZ}L15;N154sLP)aNyQ?_Pq!9R~!GzU%}nCXe6oBN93C{qrYq@tgjErv}vOO!q09q zv^(BQ-emYb_^$?U$P`bnsY&GWqGIYZ{;20?dvzJJd!_Y6s7&kCOm>a*MN@yw@Aom#qob~KKcoH{)eTb$phfTZv6rP1mh zRkgTNX?Z{~4;$P4vFlnNOy0^&@z<-wOULGUF6-H>vqagftt{?5D7-URKYK*7BDlG0 zEGR52tZ6PjG^XlT#5rAtlm3bKTn4M6&Sc%_NX_&PNmao{4&XKTS|qbJMYaF99?>9N zl`s;$6`fho(Kr(|@5(3rXtgctqm$DfOSK0?#FYdytCfecy^GW@qNn54@4ibVZL~N& z5dKa*Hk0DPRKwqDyPMu~uS|MPOE1(!sxf4p12o^K>MoE_uPGuMqo0x-7rWUz+NL5r&H$(|onD=XPUai&dgFKvEB zlWu@EeG?@m_0kaa)N*cauFgj@|0Y9Q46Q0!gv#fId>{=YV^B^`4$*w2)QkDB)E*WV zesX^Y-Sk)%GH~d0UHnk(`ohg8a--E9InKHtjL4#eZCHea{ymqeeO;?k`sh$=h9wn; zYE1X^K;5H3{?jz+KILX6GlSK$;~mkr{{E8sxI%{b;0p`$Z%G15<*m+LcAFos zMup0xyLPxwT2NJ0bzyO_XKv_s%->({`cNS;OzW}e`fpDt(-3!^W<9D9boj)H$8A}* zGIQzTy2m1yCI!^6X+(!xh&1d9Xdyt~OC`|stTIe0MIIE^Ee_Ua~{=}i|e zUc}=DAHSSA`6;>TEh#`M$G&efu_mR=-X4F3%w{dIwS-4IzeOKad}Oz}bnDLDyHj&> zHFeGV(#>(VX%TgGb)5{0U7ky`J(`uG@AQg^zRr~yx0lMsQ>198 zv9qxBM$L!l#zz5wE@a&>Al>NrTKv?|E9zJpx5;(fdX2@lGdJj<$fJaW!&h7fA}oLV zZck_-Dx(v|-#4LBRE`zD6=%g9^)Jfa&d#VRlE1$qVu#Nm38zVPBIXs>16yd0Z#q7` z$$MpL3-;dV@6UhV)KEC$y(r63Secy`r*7N3f4_o~($@Ty=}HZ$&f?h z`htU)Wte=>3=3M;Fvfm8;v}y~l8;N!&vqb^PSrD^K$I^%!wU<+=TW|0S}S^g>8+-J zt@LsbgP_HQJdZ_=&YC*E-hWGf(;7b*pE+z3@&~=gWyj}Fm9&zvKH=ZLf8V-e$4k4O z?>|$tCu{=~9-FmzbpO30uL6o^T%5pIINTdron4sOFV! zh6NSvsh84%uG9U-n6tq#43>zVGavoTgz=FaO6Sj;_ZInsC?l)Ob-j7T^WUX_eaG%( zWr+|Uj*T&xp2ka}c7KZgK~|QuZQC|d?&@6I&$pKXY1ovzhlWals7wn3B>-hky-%E2@2b&A3x0n7 zos6Q7%gU5U3PJRR5)-+mI!qx|37BVkaKS_fyU&l45utOf>8-gP7j@gMxlvtgW(Cyi zyLa#2w0W~S+R>M$QuVhfwk#mSk;+1jZYeA*#8OmsYqBsX9yJQdxAzXZmA}%#Z0cY3 zl8u9-Z(>3X*OLy3JC@N5P$i%@A|`{x%F4QD&mLK2<$%IBasrQl2we+^17dL>3zr-? zVdPWjFK69`wcJWYwIxCGjXF@LtwnY}ULs)uDG#4K8IBZjFh+^B58y8O9f+m-=_>W( zO#ORlX%k0ljcGzoCacD>u(ECC8aV7)71G+_u6hbmP{Kk6EQO0Og=!*Mid8k_r6k_==^r<(%XHcWVLt; z6b73)Xwsz-P3zSA_m|))Np=nn6``g)Aytl}E&O?FOV(}0) zA|>WH*7lef3`jFclrdp=6Qe5b1UAzE&&MEolI zJAee54-a$z7r7A^eX{F0&8z=~B#Y{H`1j|OjhT)SyZHrdCJFrJE6?S*%^V-!18^?p zdAO2l;$>{}PN=X-pc6ad{wQ5epn-^hxi;I|pYDgPVqzT}1VkfliAhNGVU&5*edtU? zokkbY7i%Dl8oCw=2-!-x!fTIJUOBY}uA$5q?ag#N$Y0xf#J@qT9Ty z;hz`}9Q!sZT|$$diOm-|5xv|S$oFg_A;jR;aNTWuIJw>8wE197>~%YqkXe-SIho$; zYt}NjAW6!7?!&FWS|mwH$;qiHe#7I@1|5dfhe7_5JZ7pzKr_@KR!73V$$VxBrrx{v zjFC}-t9yYDS*ueJo5?Qc@pfbEuE8;ssp_vU9HH229*1mDpO5LCEArp#|L~#Ei4dhF zgj~l`7eAo;^VN>8pNT1aitGqtuRYK6pbvr5gVoUoW4La9L%8QI^ahgT6chwZOLpGf z>n|xm3mVA#kg2P?yX7+f6D2q6uDn=q3gnNuwRuZ|7)J$rZ9V&t!)XX*j*~t)J96ehWL7d*4}9oO z71n8MO;YjuNELQuM2ltw_&NN{t`?`_=y;O!@SsQ%@N;vrz^`cAyz)xE{GDKH_Mx8^ z4ewuRhB9~en(w;1g-SS$!);;GIB#+AAQ2yN+Y`(#A29XT8AKz_qxWg6QqJG| zX=!|74*e%YFa7Es8S&4`%5rtbk|2T6M=JGCX_DA3H_)Fe5&$c?G9E z7y9?NIT-aMxm|D3HpIF)_M4&xS-ABOQWDRVTzaL0ri+VK) z+VVu-pFh{^-lmp!bR3eAkzqX4n0EyvPZdyl7w&t4R<>LVm1yJ%<2$ZFO>ZJ=4b2fJe%d8z{Wi4uvW$}KFMR-6g0_Jh+^@L*^ssB*cH!N%~31uw@4-b*m)h#I=Lm%IRbXAuF6`FlamsoRcx zgUvPgY|lp|>L=BO6=}3#6B)yzuc;{-g9x&v^sH zSWD(eWAaVZ6NkrYXy0AV5*7{dyxRQ!5OV64Zeo|lNwsy$nM@Fa+lVU(=W(;POdHwX z->!Rlc-Yz5oe+)i1oFFecUBw}w(idA@)8t{Xc5H9h7w!zq*bWvWhAuHz<>ag-=C}o z$BchGxcI^76vf`wc*K-|UAOFvlabM3R3_M5?n!v22FR2^0Co~YreDOC#Q1?jeSkaC z&osk$kxrK%-I{Z6P-LN;+TnxAI`JQ*ep4q4=NU>f<*~K3eV8uC)Q2X(3|uCuzdXzr z=r$r~x@XIlExF&mP0h}3GD16o#-OcR(~He`IFuSR!V-G<5$twM2uoCy`OlLbJ;BF zs;o@jFfMaB!{Yp1jq=9V+G$L--~R0pVJ#QhH0){o{R^)G!3{aK}!=ElxJ`Xv)Z>uc!wF9Ls) zKo1!Gg1E&aW|OGh-~%QFg=%$jv7gRe3~VPcFhTD%4_HD-ul2J( zW}i@+t9z+PRq^Ebjsi5WRgKit*HPp}ClDjr%`9DoqA=8MzV0TRNRNTApPK|etXacRHbDJv(p39x=bG{kHRmyZb%^*kBQ6IX<7 zJ9qlzEl&th+HkH4j=QeN1(vC>Iu@ijn0(rb<6-H5p-SR=vD zHf>M9*pTc{Fj&;a+1Rm^S6~75Y()4_y!RlmX47FvsX>P%_5)np z1R?;KCD!fj>_hITjfs+zm*>CrM{{Nl?9QerceTgBDfXV# zLiUN`<>XWXkS2o;k3_+x*))A~nxW;=?8x9){Y%9e^w|uNO4jnX$tmfjJ-)cQqv*xs;BSO#U%oH+fa$lj zrN2mp=>`BFJPh^0gF6Zi+UA~u&I*{xOvK+#UacefAg7$bEWq_atl9;#aFq>k6}E0E z09$hV(@QA=et{?lFs%f(Npt0bJ@H!TAtqT1`J7>6HuXU!+!pEtx>pam`>&*74+{V( zXXcPk{DXo}%bC%l(s@n6#9S+WDY%SuC_avuQeM4%p{ zlv_A5C^0I$Ux(-spNM%bodn540@H|A(l;d~g&5WJ$IGvv6V%_RW1h}xX}wg~1ytA~tFGQa;hirx4v3BER-ai=iUx0i$+!{$cC%(-ykzk!#SYD2%8=+gqh921fe6UjGD6h#}dhXM?48=NQZsrmY zA)q=aea=1Q<%dXuI;~!lG!V718rZ=1C-T>slrDd0E-fwfh)7aWAkYul0=6C!H1tw5 zt!r~rsER$il|GxvEIn0>^WP|4-RF73IMjq~sTc(A!D4eTQfc%&Qqc(LaaVVO%ql67 zo{XHFw3A+))!4l2K#?=NGiZb?O2bu9Y}U#VQ}3}j@Dv-J>;l@KPLG-M7@gF$#-v?* zxs&81Km>=VD7_C7vGm%4>4TjN-?1W9m3vWIRDMVeO$TC{5Qu4kl4Z0dox%snpC4V| z%r`xGfiNgRot>R7E-oayfeKpbg>H%mRLnJL`D;sceV0fXe3maMlzwf@+l|iLaxnK* zZ3KJly|zNsjza?j@?fxAKw6`8b{#bZGa7aF4QmEMSsv@@>INW!7hun!L%Rx~e<^_A ze7K9vX$-rW=z5?WB)jE4B3T%6`Aq-Z2mq*%woEAl)zMEk@bc(`mK|M@scR}^D&!_9`?=9poa5SF6i(#Rt{N2)wsSvEHN zvu70qlMon4k>ENrNI0JmOzv>xU5adXDl!91tHfPB0eI9`rt73%6KsnqC*2X5)4o>)vP>}*oEG!e+^w+U8Sa`#J5LEy&+W` zg$MNnsN$JS#AL8D*hNs=n-U+k6IGbAvj{r7E&_%@oWI28{*s-&I@YI2%HW`tbuB}; zgPU$#83GsM|IiX!IRwqh!5HQKa(x4X5m-NntC1grJ%V^QmB)SBZ6v%83e{9!shHC! z{qyI~iPa*?-uCu(PMr^j(On9z&m*TvO|GEK-Mo|j@yNs}R&L!)YX%gGq;Ot?XaD2% zo*dKvaw6VidfOH%CNrc%{V#TfE0)1rK3TS1>?cqDTro5=OI%Di^@vf76YnJYR#1k} zy(19n=D*!TlKYI{bW-qrJR9ieX9PgJcaNuUvgeHKZ~C`Na(!FA)|h#7#CfBW`r@z5jF^v1@Tg*yw6~{gG~33Q6sx`}|r!jxWcpXL;p; zX+qD?7XW*B^i0neJvk)l@|fSWbb3Zj=3-yO=96P}51(GKRoxw| z$gJZM+A^Foy4)j?`CebS<@svvKdp1*6dV^32izP_lb@4E7PE42%uJOs?*$89_@a2Y zXNI3o#MY`w;wIzo>{$7|(rmrKjRY$XNknFDJ3qC%Y;3-&OA!lOH8oFdv%rHcyCrbZl6sc3q@_kJDpqacF7aSlAnq#S!Rd zj>9b>@lK-&ja!+2&mLOI^6gx&x!-6E?`IM7^Zc93CAZogzG&on$m7-1vFz(ojD%+H zT)7_~N%u4LVi@w*#Y83Q>-lUUJjbM^<4)b(Y!CP*VHe4Qdq-;!>ZSc&|M~goOvc64 ztx}$A<HAp5!_sl5ICa)2U%Gvr_pl-b!YR*YA=fwi&`eH@$zl z7Xo(vjn*>%Rd*(RXhDl9k?k9MxH-?J0dU zIr8F?<{N{F+oepaw?x7es1nW6O{`m|rJz!rpST>7oIoB)3H@;9+Uk;=es)Re%oB}V zeae(^88$Y`{5jiDmkB1r8=Z@F@rL>P3fKQlDDURjGPge0cBZn#uO)1Cd48tHmzmtE z(f|#=Myd`!N}I%5l=g2{8_uylV_X<&H{ZvzG^+h4Zf$iBv*R^+zOG=aM%%5Aoj%!C zwVf{us6B$+9L|J+%5&{l#m#9OtnHmOoLlJ5IHUhLsngn1%APiMdMu>Oa_h zo=y$Tb1Cc3b||j7J~t^|y!wmgy+LrIW$hKPv3gQ>m9+N!KZtWK@6dr)Nl6Va71iD= zc6R^hE*|0XCgpqNlPPj=JX@`mD{nf!1^!~T(Mhr!`q{H}Hv^ug6f6tw-*dn%1{KQ- zQw;_+%DR&3IH_o8)B?kT-W8hZoo*i3lkE?`mN)GfT5#&I-aXb{Gs7pc&{pam!BefY z&e!^(=Q3;;wx1bUbj#8D5VC#(NXkz)I(|ci83CUo3h!E3na|-|%5eWj;e%~Pan6Vy09Kn>b*L!OJ_%+vOk59my~=hv2V>(dWDY;*kZ zCy(y@LilmR<75SJxwuv9HLUmXF)hac^twC9ek`uc)Phb6u4&wp^AQb7=8cZ+K9KxT z(uj)xalTsqn{bn$RjkROc%YGUQ6ptkkZW4pb;o|M;h}l&{kK+scS&d2w>@I)TIcqf z$XA1Pp)7W}^@%XNnE6+Pc{n-!kh8?8=F^w*E`Mu|R~t+-D)LU6Hu=GhC3(Cu50jc1$8#m@zBJ86MLzb) zNcnq4#(D9kSbCBBwqQ@MA!=y|o7DUEnSE9vSlWZMSn2Nm@{?9w_dV`^OU+yFHRrxC z)6{&mJ@Y7YwVujpYo0#e-1(vzUYHyQ-!XYc30>chVlc~%m-@0PI##43UliJs%x5&b`~QBvi4p6YC|4(7&(Q% zzkj+Ouj}LO2@my9l4srMOgx`&95wC6m*4tq@}+OK$6PRnbmpbBwZz1vkEn@Ml-NyD zu|YC!TK;aDg0gOb`cBKh#h{3j$a_s@FYsQi4%^N<_x%DqT&mpHEnRm=NiwaaWUfAN z_&a!>py5+2!jLpRUCePBdm)#-eIM5oF_G##ZzXA7_9g$|>VNuIDzwweQQ``SKk<8h zqy5WN0sXc9vJf~TY7698eq~&5=BQ0}ZBDZX57oRo=n}#6-#Irzunx&_HcW`u7H35^21#kF&xHkmTbTM$ZV=y^eQ%aVXN3P9u@YnDK0s= zR_1kMe|2)FTIU@rZQ0JRw@?ayjD>#!78vVJCJCq1Codmc4?v46Xp9Y>=TT6NteAdN zyf6~oRMdGkhi=kWkWS-WO{LnmU>MyIuU|ZuGq)RUzCiZrl)v{Cse%4clYgEfSDT(} ze)l`cU8aWD>ght)^2}S_kWmD-;jR4hOkHNIv`+qI{3h$fg{Z3>?jqO)unkR6OA>{iCb#@X_>Rp^Q9M@7v^{MO)!59eENS zUIb^H5|Vua^mNqdgi6Pd1_wxgWqkbSjJt6w-71;lF53qxo+cxcD=3y{V*10u0IV+z zADz3=QMLGCuRKp#Ek%m`jNRpuq3xNCHBHh_( zZMaM;@?Kv+{84N6hrZF(9*MQ7dPPx*>z}^{^%{L_3ah#Yb3ujn>w=r|=O$~jEA64I zpA3dLZdYZbI@(sfcys8}iDWZZD2PS?HDG^lf4|&?3wuz{h=@N?O7eg7C`ogqLGz7v zeERJ|ILPUralje5{ov>S%EChWRtZ*RPo>&n=c<4fB}9`xwP z1NoaRGaXq~+jna%hVj6%;J#_orpKT+WNYK3VBi^tgD6n9uyC|>|hAm z5bTtS=wZGnYHN!wUW=#xIzjitVRY44@VbR}Imi~PhD3j3vC;bq1-kH{y}-vIz7I!j<-wQv?%*)5cs7a$lEQ$xSkP>M3mI^{qNzm zoz|N^@z5tD0c6Xwke3SfGlS>#{vD9bIdych%qlieV4SUJX6%k`YV4tVzP=J74(8KeAL!mO>UPc-`xt7&b`1D^`wtvmEb?9%Zz;s}VQ$Mei$ z^J+5z`?-aSPB(Na)&AzQFFEZ4PMM+uMQ<){+UcXj9{A{y1uPuxxvqPCAokUR*F}}w z@*Yj3^zx|SojXZk61Gc%M=S>!JIgLnCIyK9f=yw@9MuNA`IZ#nY2@z3_nvm4r&IH_cNubG zskx_-V05Y?ocG~>XDmT+`>07T$|1&1_uCO9}Sun$>@aOg5Hl*1STIlBP20yU}uj~myexA&r> zFI(j8a#aQ)sD$+zA~c@vS5L2)w12Tb@bv5xlnM*8jcTpnMo4IbhYZ)3p04o*t`q|_ zqr`5qKjoG3Py-pU8m?{V+2o@c8sf;P#bgDcx4$-?*#~W1hE*dw_%fXvP+tb8pK_=% zA)mdP=9re@HO#BR{i%pWdBY%T-H#z7u+CpfmgcBR;M6hS--Me?U8wrE^3>LatcNp$t zpHFOL@M{xRERHsuYFnP4*wRp<{hx5-Hw6(i5M(5Aaup+0`xhhWI^B%}!iD8UTQRpf zIEzeJ9kPb1qf3!PF#Ks3PzJ`oQgsJyAm%#^e5{Feko))|GLoJU=ei5;qDbC!o%&;&6_JwvMt z^5Gy@%j0f&3I(lCvA~}ZdBk}&5_ZxytPMXuQFT4uFp~N#29&@(d2vG&_iuTG)7$(W z3wHbYuBa@}jm0mGGjjP5AEJ|pfrlTzyx#}Tr4LY05Mu?6M48I;}=}Y<3Q81AS)0O%;@OO0!Y$e2EITRio5UY8|_U^n4xQH)#jOK zU4yVMGH^%$;*R|D)AxrPUR8F*@jgHL-!M`^dd`lv?sZvsdoH9ZJTlTRKRS#ctB|^4q}=!W zz%L25feH`Sl8KnvOHEBCi090dMw_^?B8F%FP7C@0p#) z;S3{!ZQOARx;de}ATs89QDcBXct9|yv9Yk-zQEuWN@>z{aYnNQ;M|vL{g~VSYx&(%$uszt`Q?`;e{gUsjqU7QAmyU1XzvF&L2f_7Yo(x@k2H zYlzs;ykcI>H@%09svpBfn@!)nZ>pAF&i$yRI{mTB-8(Z zOaz<1ZCknx6_ezGS|u}3JGsJe8|-KEuiyqfY4dxZPaqwi0J?8XA465VOnjHu@~*N& zrX6~5N^;}YfOP#_7wR(4uLK}t+7;mUTJ9YkRe@2`=Gbju9nsoC3Ot($IbJL6%C426 z_l{DjSNdzmet!lE3Ra}eEa0+#|^M@Yg=~InLJQA{l=c)S zoYlm;U}w9#_v}Te!Ml6<`-{HV_i;jaBVEq4?tvW~Cf#sWbnz_0!u#v!&#}r7=2{pk z$q8!)gUAiW4aP6@#c3I-V&k`(Z@xpQHg3boF%Im$0y%Z{cB`OEpRZk_*z3Q~23!P+ zptj5|m%d$iuL(Rt*RW%rL&30u683ocoCFWg&f`MI=DAr|pjU=?eAIh)@BaPP_r+f0 z*+V$naJTSH;%j`Lf-j^y6O{1ynguc+WThuC=fS)YkUUwd$BynNwi#= zMn7L)T&gN#hI!)0C44snziCNJCfvj|aJfNoD!v4r7&Xgho9jVrp;-_RJDm1*M)I3l zuOFscwB_a1ddzMWB~=$36r9%y2 zLpk{CpI#O^HeWPUFa`wdfbcbX6T&z+ebctJ3G-~ZaY(w`HBl=7=tzf;AAg9iqJY4P ztRvt0j{g^q9+KgradrubXuQ(U&_HsTDyFlle{r9fK?EiFJPhM)Oj7%pnQP$*2InBJ z>*)B&Cg>9UImD$Vh&vFk6xqRpD{WnC7KozV#N)WSxe37L-uCY@(T4ndqp>+T^u;hp zU{m-hGshqm5mV?3!Sth1A^BlvhWFd{vcq#}h4~;p-~x70I1GxU$5B!K#U@9%xgnUT zhZBCB_|#M$p8Y$bqM}H-I5F{`Nkd&9ri$l;n1&QW>c+V_pwmxGV|c3G=KzW=yGhVR z`%4>MorAz?NFr=SI4mk48nTZA%XSsW90jLJO-*)}6H;g<^A(dDxS(YSCgURl0yHFa z4tMU{;k@)V95W+&ku3c5rF<_OY8j#Ef3$+pFfcG6EgdC9|=Wv7Vp0|%=eO98h$A|9u<$G1*0=zCDttCYCVf;oa8oHfb%eH2I;pGb)X!c9vU1h zfrx2;>lP&;WMy8@FVcU+B=r`8;-TG)qC~>+X^($}>J~B{5!Xj)W%=chh>4RiBr!2D z9iIItQ?c6jj~zYQmwCTXsD!5cGEP+j&F1v~kx^{E00RUuJk%NwM&RZQmYSn~yiETR zhz}3%_ArQub5Szhd1Lm^;A%^RVhI0GFV61m?Cb44jh-0%1_=(MlDSP=kF^q_E&|w{ zIPmj0=f!v8T-=7^V4o%IMXwqLak)V?Uf$Qu4ELN6yepyV3zb zpdsu_UvK?YAP#PPaU7w+|B1y)gqTaru`je>2l&%TFeE9Uuts3A-G)J`rnNN+vDG&) zKq-r6r^|Cb7VC8w4qspNDI5Ep@YLfFIR#;_!+DF}`y1)9nU{D&S$Y7D7A+r)GsmE> zgKRW5VzJ*CAK~D{F&XQ&AHGyW&wZH$PK1QBB5KT#z=<}9M3jQUHqQ$Ei$XT00P+># zSMGk39QOj76H^w7jTo>K_O23m34w`ZEvVs9lL`uli{2w9d2u4%8)s_Fp)tYS%WzOx zdEe@$CoHevoyc7rjLsaxmmh>aer#mKl5Gg)w;5*2-B=BC_<}OW(2fzR7rabo;ir*T zMXh4hmU*0nNhWad$#VC+^$Z^;5U@S6D zj_m+aN*2KNh1ALh&(J{xIxa|aF=_~*M z6(DhuL|rBiqjfkb8q!W!L*{gGdCLEx=wv$1CaKY?H{P4K^4sUEPzRZ04o#o?t`j$9s5*>_U!{&F0;V zSM6B%57NpW(}I&n9=n{t#jn6cn4W%iYYsZWsZN+!Hue+Y2OMKgqZRIK$ zkOB_D>WQjzOMmCBYw0>=Wo0lki~TwCvm>+m^4m%&azj3rBsuE@r9drthB}%q$ z-wxXpD;4^stmDQ5pl$FlsJt;P89-Q*6qMB~|I)lE9pa^~r|aOT&`6G{THGXLj2CDRN*>T?AUB$fA(JGbxhCNpQXC|Z12JWc8?g_E7JOck zB%DEgfkpu&bH>K|e+}2e0qX-E!fRzp@vcUMH3l{m$d^aj2wuWLh}Vc?HSp|{V@8Q_ z5?4-yC^BW+bYv67Lrjdd(Th;RiLwlNd+&h**V>rG9XW#~r~RNlIbe_ZPvR)gbkSZl z5^;pbqAJqZ?nS5-=u#r18RO^+tb7bU2>Zs**R@fh_G2n&3W1#PFr(QdwV=c7@|by8 z_(u5&toIpCV|xEpO5i&P>pao00c6|aEO|{}e?G>~H7|gV{7$1f8-`jOz5tR&r#}x6+sLFS>d;M-$!0qY5KX+a zpn5+xjlTwrbqc{uHf?c$>9Ns>7Qi9(GWw7E_;#qaIaCX8bkbo*mK#TEQ%=Mh*XMb< zlVA)%N7u;NqKd)|Vl{3tU4HE|&4B~T|2uED;iyff$%Z5USUTa?LUXyP0KO(QYwOfP z|A43Px#FW#%~7)vR+j>~;!>QVB(jMO zVeHQZ$#@%zUTbD4zS9a%g(@^u1UIXXbNh1)=k0vjlXX<$B%@+t81HJ(+GLgJWW^=H z!===T+80gA5g{R35{_T!W!)g6IhP0z5$l!{Z4Y;#Rbk`es_2%JkKO>OZ*D>|>nnmJ zDyi8GM?S{aLA+i2tD_asYP7-U(T7Zm)%{9{QbZYop!$K%(WVVH88C&vp~@|y)Jd8| z^woWHcP2G7Hm2+Fm|0pLjCp%?ah1NZtIH72C5gY7Zh!(QfoPfjW0N*6<#(AhYU``q zeMr0r2(?pH^Hb`TZ_kLcP}!!bU|KrRSj)FT1QYXEI6*?#Zzaz5h=wSw!H8xBcN=lM zGA8zB{uteHJzy%#)0a+e)QyJTs}ZQX_WiGzo1B~kB5hpu=H#`XepkM^kv)!xD28*k ztf~qQ{`3vF2b$s(0t+|y4j=6+uJ>_RlQ`rjjeuUb5heh9@EoKMkTNcl2}Bc(zRQ%! zVdo$rJOB}DcEfc?U_IXK1F926UO3mK3NRIOFoSB~225#rOI(lL=TlG}OG)7j!+mZ+ z!M%aS#Ntc8N>1JjaqhB8p7;714))gK!g+wQN{aJDC%7O|w#X?Soeu@wa`!io1V0m0 z2I&IIRh%z}{W`=Q{cO^}pFhfgOfWDc)X^20JC)BS6Zy$&ZP5~>24(*h1sdqsIYDxX zqOjR(q+Ckb50oT#h`)W1xc}DdMCEhmewd_hv_B%Yov;LNN@?1@VGyi-CWPA5!5hup ztlRAHDHsMf&g^7Z)(VSWEY$m8bbIWg3qY&AgE%<}ww-kT*~uOdgeV2eRxuBaP*<|Y z#+$)gIZbrh*uA|&c$+=(^LcRmlcmM|@&SULbb%yvDa4`o%rSfe0e1CHm3|jus}Q5g zLOFzEde&`T@Y%i5`}`I#z^F)hp?@9U(Gvlbq##gf14UU%pGmnB_Bbb^HAeYGnE=@e zbUHoO)t)%^8H|HXSja3X3TK?Dfy&PiQ^B9NzUB@->^~5Ya2hqjMk2vh`+%raA(hy1 zQJ2=+l0w#}!3hiCWK5fri;F1Q;LYq`y+Hwgu?Z5wmL)>sab%>Di_4b{K!u4F2Rm3E z5y!YCQ1$mlS;modqp$;VHf64yu|Em_5=v8_c783W6)2I_9d+Mn!R(ujuOTGij5rVE zAmXG-A9l{lBMjZNBn!g*&16;28A5iw+bysw(P`|C2NCn zvhTYv_H8iFb@#l!-#_B}`uYVgbB}xO&;5BX*ZaDzo6H3TQkgQME7pa;&xe~cMCz0l zVxVf}f?!#5F9_*c*essy8*ZZP^=N9^@o0|YgmtT#fGHYus276^ef|7Uxx2GHN3ERO zvE`udcAQ)P3q*Ga_vtxGfMF1>JSyC1SO;W*FK7ZcOLUTqiYbw(CE9X;>Vl-HxtDlV zo5;Qj*o>e=Cr)}2Cq3~JN+>XkIWVI;14S14svH_?FxqxE0d+$%gUT+e!_Eq~bu}6r zqQ!cRXpGWU>+D$$z@?tp!w4CP-T8Y+za`2MZWJo3v%CaI1|BoWzC`UVEFuC7aM7CC z>1yxE18LAAcxyy+KHUegs2N_!c5-F1G*@Z6ZsGyl`Bj`!Qc{S@kfbGo5vHo40qd#} z#R;p+>?fTjVu*W`sG@+9a@vP`aBbOAR#QVzP9H%ld_V{oKt7r(BGLnVqu((kfxUkYfA|fh*BLaY|RT4@_=Xy?LuByt)k0u#UAu#+6 z<5Y|K=U&9=#)o*0fKGQ}HSd_^|A?z_Z@OO#IpLo)W7;}5mEc|*kP}wW!m<&QFC?ULq{Gh$ zy;ZMq`x9Jm2#@|iPZY=8)zAMMZlEzj(L+FpzY(5ETwEpP<>j~$h+{HBV5k6|^L|jD z@WDIm;vXLN1dpEB!}~GOe)<&6I)(vnFDCdPD*A7PnEn9<3uOd&g^>}V|4dEIO?&e! zp69Nf-Y)c;*NR+25m4K7C0&+?sjGmg(tNWi-tev2?c1I6kyX{z1wX6^obhT6LCt)P z?7x9@Dbb)_!BcqQ6Dmuv)gYdzz=iy|1vKHlDI(&HzJi@_h=88A4&vu?D_$IB6++#O zRlEi%-`fK9Gxe|K4&W&D5h}#y_m_jul zk_H-n%na3v)J}Twy%7s z@I4svEEE3h9}sYBEYD6*o)W<=Rdgz-N#kO+UM!AiG4{AQ@I)M(QPCjTJC#{)FO4*3 zByenh{A`QDqkX+>hK7c4Q;9>*7d$dZr-fDgsvuXgABGuM#tS}7Y3&XR{b84OfgkIS zX6AQwb)VCLQo7C3($c$?DRP93Ygmf!z+(e-cfrA@)0`KIQcswkdNoruWR>Ci>=j^P zyt%URi9p{7FFKOrYixt-?)hSX$ZvO-IgNbvNI$K9Uc&rQrbG1sOXnu@GqZYa@mEvy zj!Ooatx;{K(C6@G-`)xsI*+lyD}Dsx)Py$UwGzlgDy(eXDreGW3t!irTS>KbcDhlg zxYi+7^K!~!{=ifC=^CDl*AXiUO0(4{UNlKE(wXNG_jBM&uXF?Z=9PDv6g5b&XME|b z#q?zXs^9{MP4A+Vc5ahOQ(1xZhF5B(F1c}bzQ?$fb*3$693~;-hrM)<5G;P+KX%iz z7M)k~Vm5xc+Ocq~a8~GC(ZMe^%uK4)KRK&39B#z9dj8R8-s^1?U*pe@it3yr*|+=X`&Hle1XL7ysRo}agI>#Jt&o~mNnJL+H|x8)Xg`W&i++%+ zr31395|-ewLkjynaUW&2LF3(3zS1|{zfePIS9L=|s^}GSZubR_-|W}G$g(&Fpdj`3 zzr?kPH1P>OzaPRQnkz{_F3BHNT+35ZGhFL z+>Z73P|(Vs8ynI2Lj61ae$6iG0MEVF3{y^obz*{x;6N43bfa>| zHv;L+mGs$LsxF_kA}V??{f^}?MLt0A{+FuSZ5 zyYgn>n7eMlQ|qwqwX9)lA16y|CL=t4;qF9#+7?D*)K2n*dquD5(JLX5kyW64kfL<@!_aoT zeED)WfTINU0F3Rzva+&NI#{si5+jpCe2$WskySP2Po565-zo8}AcQ5fcJg+^Nl%2$SQJ|qz`UAgbTR5F!Y-&<_A4kv0eOSD-)|_t zFdeKYE%gSPIC}E?Zcy8(G~40ko6n{vpRe&AJ!Jfr%RETvR^N2pp@E*NC75N9A8CJMFafStY{_&<9*q4s|gf zxVSXDIL!$vz~uaV@i+rAZ&im{1#GR&{R$tMp^?G#5#zvmVCD%4zB>pTVnqy4e4fn8 zxGSZ{FY9Fesz4WtSsM6NTuTdo_&j{bWF3_0XuCnoSRVG+wB+L)5*2H{r{5Fn=x z8r+#MPqVwb;H37RZSS%j-}R)k-`*LL|M%?RVe%D&i5yDC6PvWHQo153==YAN`Ia^1 z_Ql5q@Z{@bK>r%kVVAh^!jSfo;hMqFvy(rVO{X60(R4R6zm;)oK=-FtR(FV-sy~NY z#pC9Y6ps~eNcASa6v&=jFxi&S*F4tw-YZ0ddupV;MO`C!dr3{rX4n+qGEU#mVbpz? z`>sNGiKyIJ_17b<3Pwz>ja?He&%Y$LSivWOPo+B?^R8gQsLW<<%}CC9Om4r`aX!CH zPeh58)lkXH$=8C%+j96x8vgmX-|t}<)0%6`NYAXYZp-eYl*lR@7N=^)Y^bHvZ&OYf z?_oM;+88})uv6uVor*sdY%&a!l)kaF3WHrX#}v5Ol5gt_7_2BOJG0yp5;Ql}ry40j z)l6~~|D>X_=xI8|G>|oqDh+f|3Db@&vlR=RfoB9iNv-T(*ewgsam6VsQx)%`$N@&t z-vy!uUX!jG9+!_{E@qFCdQV6D=WIjor#sMDzvhseLVdv`Nc7BS#`x32a?Qt zpFEPWT)Ow=jVQm@J9*tV%BhaFw)&Svd*tSVXO z@#@V#mbYg3&bm0=(20_{QyG{>18LYK0d84ii_2DfROWXxxW}pnrNVYqn;&$nI@KvO z%aw8^=LR#!8aBAD3LJ-e*)S+491MYU@5!e4d+~PlHGDo#T2mGa5;SX|b((kOD(;3= zI1K9Y3i*mOzWTMFcXd^OpQ9OCO&Pak`HgFg!VUKP5&1y^qJ5lI6`9_B7o zT9Bq)0@+iTyBp(b>`(MeqGAIZc^@p1$2}_Uf@Dh-WPNQR*HRv=#_B?T7;K{lkKR)uyG!X7+lNww#HOZ29aDo$hFYcM z3m9UD_1~6ISu0|veYP}&D66^y8cg&A3zm3D$M$@)O&}d zdF0YA{SznNOOv(EYYn#h^~K0L{@E2MG*A-x4e4jHWOFQZ;Zg)U6BAi=4@2P%#B(+< zz7!S-pZrH(pps4>?Aash(tlCNvN8E*yJuKX>!D1p(pqus-EHnJU)|EDk?%Y&L$KqV zAUZ8}8)?m!z)+ibH#H1rHTPo(ec<3hA7JM^9^Gurg^GLgwIeEH`bDl=i69KTm9VS9 zlOtZ730;Y2=MfhN`LP74*j|M^#R>cSq1-O|+D+Q1tR+wk(>*7uS8EY=hhH5Erl5^H zrU^6yH48d>Frt0HT?Nq)j4tu_aId!$L?FjkNQ2QwKoY_SF&4l#6KU+F|Nr&>{?(Xa bu^;#T+^nJ-`n*UT(|27x7Vxkd^{hI`{RC|=W!h8aoz*fR8CNDWZp6oUIx~-{`tD%Dlg|eZOot3SV)ny|N7ZV4^%eFTAg$@Yq z7vwN^atH5adtade7ujH^c+ru9g4U4yta>K*^fCp7oz_W(!{^)* zhC5xI&JAp@>e0Wl#bdOXPnqL}+EHGHpC(5#PSGjE@o{nqqqY1XMGuKD)n=k1Chme#rBZj!7rOYe{R`}s9J zSLcm8aCyQ-EU?00qZ6I``}cPQetvpND{vu|L$|<*Vl&geE4`IL>X`ia?NFr6bJ zvqFf2;|i7{+v(@om!@?VD;~2Woo)G!yz6LKzb(#BT6GoO71AvT=U3->ZPoVn;jti! zJoiZ+cAvRj_ze!n@3pn@5@EAlp0s9WW})nIG)&s_))p=9BMYs3J!Q9cYOm7FcVuCY z=CfYuik)8xKcFH#GuquSTDqbVFK#{5eaL-+OIB7kc*p+lcS?=l-q>(4&u&+t>!@kv zt!-1knm1i(%QjQbGCDRh{IzP^GJEkjXCj=o)$l>^U>{gyoC+>?)o#LD@~ zUP!rvJtHe6vCJB>=UmdlGyTg`iNh|1j2%&vJUxdTzbmmxyS=$D<4HCIo^_X`WbDMi zhivyrQ&E%m3fZQ0LxnV)BIG9SM+#mPjozzW6(+a*?&IUr?o)$wDk>_ERPM!LxnCNT zQ7%~C=21Q+FaIWpb|!=CWTe_dg$;kEei~cdIaHcQbvz`J&8snCri-YTo?fPJPnp z;N&V%&WT{9yP{c_YUp2RWYl9}%s)M$rrOBBfjt_v=luKS0-Bu%)t;Z_p6IWc{J729 z%}vteeN2 zCQB<#Gws6S($f4$;pkv%Mq-w8iS^3<+_d7T+gqddY#zV2JHtGJN$IK(CmjzL*9~eG z@o&S!b=Rmi<#|l+!OQ2d>B!?!iVfd+$R!-B-B-EX+EbC=D(CinYD}+1qf~_}nxvjX z8#Zn)$byHLDF zC|qjirIYMgrB`mQCSPs2Vf}i8pC2FNtI1v{51{2g_bl9-TknDV)mGZ^ANj8AHeF)J zpH_veuDN~W#Y*8V@81{rbpOoD3DbYzZ#>rTXVYC$hwMhazxl=aHB?k*QZ+>uPAx9Y zcKfFEAyq_4Iey<~-&^r?MAtXz0SA-xm$~lVO0~in?c$7^yVY?M>goEW^;oq`t+Z4G zZDXUFw6rwt|A5t(a8@aYqEF+(`Xx#|Z~gc$zT^sG6!s}TztmsTn0{|uQknTnF0H7E z$J2uftRdLdNUUbdi}P-tp4s+&$0_!ldv>MLDCzL^wU=%^7~4!s`&28(g7u)&&83Ce z+v3*kW_pe@Ll-@!2FsB7YvLs`#*f8QGatC(w<+Yu9f9%}=f@&L9XYc?4ps(Moc&RM z&v`Y*=H2^-VhqoM%=E(wTh8G)&db4c)QdR9d2Tl}%?s zM;Pt* ziN}Y?c+Py$PG>vh68z}o?Xyo+cCMvnR+#?Poa}VqS)FOJc#%|cYb%$G6~l8QzI{p0E^x*L7qN1W_YDsSkGyJ=o#`~(V-8UicKfai4O6U4* zsLk;08uN}XZp&?E$II_lYg7hR9NFj;!NkSIwT7LYePQf2Dscq&>Fu7$F-W3YB;q>W zZ)0Fk00OCr;@^tQd}~g^{PX&QPW!Gcm8~{!sU74p`>1l`W*g$ONk>g>ONvIuYg)N{ z?*(y$!XxM3EpG1aXNug$8ENH2&UBY}OSz44e0^=b8wopNlBaZOZApn;|4n=Qj#mBh zv7U%YJQ(;!n2~r|<1r%BjE^gvYz3Tj)|JyLbtabOSH4r>87@*HQB?nY&Q&B?>EYXMSgtzVw*3 zxR9oGtib8#!;z4C3Bjv`($l|<(pt8>5iXS9^Tz2 zLLZSF;B;lU=iVXLkGZz`q+laoC6`<|aM_@0^Vrk@t#Y5qkS6BW3W3iuj#aEV7$8J{ zvi`n|yxb z<2v(D;q#00LBgerk#S;{$7{y6?pIEfy@&L(&$w!{!;gAv7pZSUi;u*Hiao3Pel>?| z8c<-3MWW~muQN49g`T;Co2ot;Ew}^OrtHIqpkK`?xAz$y$^H;b&#RK~z`W@pNyDYf ze*}(%&ev;?gw@^Kq#Vy2ww2evvv8N{{q@h!a2@=(QMX_0MnFI|G8F;_5gWPZ{GMN} z84Wk-c8^U>9k8AYym;;U^~)`(J9da(G632!jhRg4Q8t*ih&}N0XG^AOBK?*?F2o(< z`c0dR5nFh`<>lo^s)@_bdw9otE4xaMbbC!w1FM?-Zb@sJef9QT#Bs|n#?`^wJi1G& zhOIbh_-2+Zxh7b5?b?;9U)m+R*pH-nsV36zcnGs$mgd;l*iG?r)!J7M1E+lE2N=mu zM`vf9(2q)bUh%4wXu%C-Wn;fHa8X*h1BIdy>z_If(*Kt6n0kj@i8tL*;vJ9hXyc7N z*4o2snvWU}#8w3sV)7yS*j%FWjeAE|GP->OMmj@~WOg7@F5QeZ4pP{vm2^6F3fLY? z^Z0a3dq5%*6ID>EIncMo;K=AJ4>-T}ahD43LJW znwF9(i{h_Jvx*UB=|NWT8ux3v6R5yMRUr9FJJ%-5yoodQLW=j?Ni6OTNjnapmtcFc zK9;RQCCh&-OXhkv0gu_ZNZATmYsJd$d~rbxF|s6f?iod8P`vJ4#T$)MPWF--8G1Ri zau-W|WDE@rQ5@F>RURq#r>=?K8{fuVCAn(VDpZuH{+ip_SSH2cwT%2EMr`%xe)9I& zk91(U2R-hTyklwHsLT2m%M&YM%LbeaCezd3-*1OInrbskv>$lC4G6{5$FkK`%sjk_ z*=4~+()m48@j>gjw)25S`>6^lG|lQ0vRo~ZN?Gdb>(4zu>nFFecpI@6!K2KaecEaL ze$!e5EHnu{pp)()hpv0s`)lu0AG^hrX2@<^o@-&^V!}D9a8*d;eU@?c(5@2CSsS3p zEdu_Du>+rQ!+{Imdd>=t6Y^K5_K@%q-ao_h3f0Ph)!IL9K`=|;OEKwn^ucO6F zCOD%aaI1RCg}o(zehFB#q$0tetQGpSOU7n6PS)F_DtL#nixgeP#r?@*Ls9&8D<$Jz zlcqWTcbHCJ6>18tGc9juXegnVv+rF~bDQ_6%Dsb|*`y^eP|JyY%I)^~Kw$n$lT9_O z&iCg=OIddLEJ_Zwo7A3NnK#Q$p?4S9=oGm9ZFzayYwLLLxte^(ABsr9)4yBI`rk!> zY*sA>Wf_H^Pq{EY*&sKGAN7t1+ux@mE6l02UqoSnzwApEv&ykB)!><^Vi+`v11`e` zo}c{DH#({c6mQ=6VAb{@?iN(B4*=KZodsgJ+GFeo)0nOE9UTUPYJ+W`+`0;KnwZ6T z#Omn|UllqdC@DFIfR?c7;IM2-Jz(*9Jps8fLTNp`JRTkGV$#wHmp?tJOlV0Tec|ca z=k@2MiQV*`SJsxV0z>wemP)R{5*M5ZW6QE=-h;b2;rW?l|F!{zVyB&zt$_hlec*g0(J`U*`(^<6U-ste>MTvc{`z}g zhv)~yoQB)C`TF_-uUT8fp4imwOZ&UEJanhs#3K<8=U?Z@o9Ct~D9Qrp5cOU5!WtpF zypP`dp+Rm%iNs}`SV|lBdzM%+%kAn8^54c0jf&nP`rY@tJRQRW-s-K7gB4Mk7yj&;5`{&)g zujbSXk`;$s#YfJ!hTc{%-st3>gx~vGm}A{tvJ=9dSDKhxS~b!Px!Z9c>Y;2h7PR94py3>cDP`qR%>Z>Oor>2&(m&dj=9BfQlocg31C3x}Uki)}_M<+whq&z-- zRPm<$bm7yd_A0tuaZT2iS)_)xrt6}HB0f*vmzDyys{}+y(-Om#3|cevpW5}jWf0U1 zzayY=ywJw(N%!j+>GFW`KJmOAqR2U)9`DcPiC9VA<{?PO##Y~wrafG)TAwIq%kCp; z@tJRrMtW)wZ`Ku{Y5>+7{{B_zBrZ-g zSReQhQxm>xH8MH@EG1s<)N+9)J}XPEgyR7j)x?SK}R1upB6uRlr$*l;wwD(3& zi#=yQ7P{JkNF4@`#U}WEGLh|x@^t`?AH|+W=O?!4s%!%8cN{c@9GJaqH_UUxPi|r9 zbImSK9>uu192!O@CUc-sw{fG9j{I`Z(PA^(d@X>`&Paw2GEiq+U0vyUl-|9z{`$~a zBG25NW~tO;R{Z;u)%`WAeSE5Poat^~_G4>iqbe)ut6C|2S666vh(h)q_47!%S?<}< z?p&0p0w;d_-&6Uklq86dcQ$U@^JoiWA>!Pz=Pgx^OUU}`>sZnZU5BsrRVQgn#7egf zy-;8nwA};A5u9fA6{IE+ql)!-Pbc0-@h7@llW36fI6$>&`+<@zY&7dsiuTnCxUAd| z$hGNZ6=q8^H2lo3e*bW37>8lpxuN!)AP9r%MQ-+3K_syrkg!BqZ&2O-4>7_YeQX2s zzt`XU09q9*?Jnv*`CY6qAy(MOtM7uighZZiH&dZj&Wk3u;}r@A@BWD3j3;Ym`fA0H%?$-hVQU zDmQ{d9xd^j&-0uWqCj;AFAHjHY&7$E;*_%|FUR)qhq7*ZR{DvLvx-q1tBgISOrJL# zw9(7I6&6OjiBYH@?80lVCx8|F5pOe6Ktt#|sGPi}CezM?PK4EbPScKwut>9U215s9musl`YN0(-D+PwL_o7d?5rad#;d^3)5-lkllrdqS6vB=#qT1fX4 z=wjejUYZaViSJMr*S`7sH6A2Y+WF8I{1ub96W?#29d-8u_t)Iv-@i4w)_1^@TRAFL zXUBd=hgm&}goK25k=&ao$T}gpkW}om^kX-`W$QtRz1Sbrm1F=Ia@F5*Mz3 zu60+&Q@rN3+=|v__Y=ldOexM+hQAuVp>X^ip{aaz*&j;ejre#LAdpPoGz2p+2=x_g z1|Z$|r#_~@EJJd3S3V~CC`Gu`%~zZ4H4|DWZCQXG-Z%4lMZM6)8Vsc7-XRIsk&aac zs3He!I+%EQc_)4}sG?kTPvl0$+ARHR|maTEx zw=1*?_(rHJLs(+4xy~RlK;k{MFf&|pM}QG9&=}#3IyQTkgBnsvO8~p*WA9lBkBkLc zc8Bk`vQ4R`YV+;e(-NW74>S|gQdacZmA{NpCohvx+V zAKG65K4b-77_{AW@#Q5!?bpHVzKan+d6ZRqict(-d3dP|%c1_){ZWpWbY0p*G0WER zqjuo5uy@#-2PeG5C(M3%MDd<)QOY6$Rd&6#$8F1=u6Z5Vn>*;zJHjk=v!T`jhFqFqru)Qu(6)$6(5}ZURMsX z14z{bxy(!tL{W=JDfY_1q~032&0L|kx0ZUh1SRa)FE^=`vC4ZWH?4WE`u(ekE@(xp z>RVi@X7{a4J`r~RP}OH#2CyeW&esR@yLuhF*MqFsEJ)DCnni9RP^);Lo zuo~MGqzLE~u00*YoUBpkyuVO1@YrX5p=)zPWit~UIUBynhLp^f9V zNb_Y753l)w7*;u-1aO%%kXr<|Z)#4_;05)&(qzX2Oqn3#xm{IN6>59>c`d;#+iuxY z(SkL+iC&;cyTJs~jxDIz3uhZqeST&r9m?LFrr`B@$+fStX)A+|J^V)&b($S$p58mBA5C0F!)#n^t-S-$dDUi7d|IM(Gy z*}0i9gE?vWrQ9FX7~4>dP%~+uSn_iIBZlE^K~MlyF7o-r64-RmW#}E`xADozpmAk? zBd-VR)?E(>pzEg?ZZE3{{NBQqb&ax9@Nk*kz}h)|3ICicbX`BycW4itq%R)d)o@>i z2=5RYQNR2EYI=VD41_?4@P5>MK9}ZaqVIANIz&ndk`XS$?RRzS4+V{1rLpV1(ZoDc zwz_XVL8|dlV7^#jx%z_>>kJLI*j#tBPi)uoWsDKhHG=Sn;wWy@v0mP9<2E8-nm5Wb zDoNdhB-Zom*C~iwkhwySI$d|XDZkG6^RK@93^kEuUB%)1pFZafG**95O$j(*jCjU% zTGDk-BPk+QUWaMa-Ipl@YSUg%P5t?Fd>jPrn8B#8d%lzDL#@ulF&b1Jh zvbMI4f(pZ*vQwI*{p2**cy*h=1-s#Pu_sD*j{xrd{F*B)< zT^%i12p#^KyWg@!FkpjYKyUvV-^Eq=4m%oht*;-xUYmB3HSWS-mZrQs#pxKKN{gJA zR&Anxm7`&SSxTynk`>$2cTbFuCpiqfCn<>37chY&R#U&_FQGfto@~D1&%CSDW$(Ec zmt4;GUSSxdd;_WKVwMpV_+DiYUf?I@-mvD3n{7^@A^}-h@u5T)MSJ?_`U%I#=OEpuml@I zl~HbvySe4H4OD4iPvia4F)_VEr-@alc4rHtzWkj%RmQ%)b92T(RO_G0$Cv@BtAV}o zsNSzd#9hp>*apeS7z{E>NH>lkAoSV9t-i=>e#yT5jcX!!=b>mQ0!T9qqGmp?oii2G zfv_}+jEg_xzc5t`Oqo#rYIj*NT*)djYiUX8|}!%L!@I$jP!*!+sFEPxR|ex~e{}d4pCV z^0-NRUEKws(kFp7Z-x>8YLEr;i?FKz+Ig=2lm@bC^0A=pq`il0#_8Gw&(8lyM8j_f z>UUqGA)CPB)a|BYG~Wi#fcABGR2cF#4&0NHk^;)9qLo{G6S4b*B$Uo#kLliTW!Irw zete=F6cfV;wdgyP4bvEwK5YA{F!lzdEq=8JSK0>N6*}09XqCz8-BFFDSXnf-QSROH zYCtIB7s$hm^*j{Ap5ERgITp=WKEMWza$~(7kgmLfg0qiLZChSm7}d1@{h-`7UryY4 zkJnVhxTL!Sz?8FflHoH%oql}|L{O1t)$uU4 zkkZo9w#UaeK@TuRp{$J)6KJ{No{G>iu9n?F$h+6FD|F)FdxCA& zy%y9lPta#{U)}By!^F$ScN2{VAT`o9&b8^}1X{yJK{|k%S-X(xG4}27Ek@z`6YSm< zKq7`NQcnW!kl51Qm}AL;*fRK`!guanM;up`+Jn=<+v(}wBCDWY)F#R$f>K9HIhuO< z&Xec9Y5n`n8+lxe<_+NA$=H2KHQVm;URZZfK8$Uj!=v#$`Bl3=Z{-%v;R@Vg)Fpbn zUk(WF`Ps)CjjKZk5cO7HGFJsvzD3{b835E>QIp==ss9mAyb9XvWt6^1{JM^iWi(`-**-mjwl{bcfLUOvTlE62m*F4L+>8I&}7pI zcG6Y7cI{fNP^%5f6Uk5z3e{jm$o@c=ou9{)`%*^lP8d7wg%t9dAMACtcSCMOZE4qT zWRvlTA}t<(Pt>FDH{XHAVw9t0d<^*{a2hM9eBVlEm?oUl&t5?L zwbheouBLcOU88$Q@L$Wl(c~a~P)OA1Og=lGvK^XBP~^e4Z{Lz<#}gXjHy)wsbE-?C zK>fkW2h;1Obp~*0xVOE`^eNUVf4}MS2V4zRW^6dO`=#rs9$E@zS5~c-^j(%l{PN<- zfnoxXs2s4B71R0x*nJEDBx)0+)D49i92~CM_i>z{>C4Z^XgaCVPlaaId@Ho9L}s?F z5;i(u+E(mrw-JBqJ%!-}K;!TY(b%B9>>kPsl^2*=$#xcq5!`?Yws*R0Mm0OB}oYo#tO_ofr*n{+*&=8%2M$zr&77Q@} zaBR(*HTzKO{PK(LXOvt!btkx*QTWKhj0LqogW7|jq9Z6$ml1%Vl|P_w5XBRk^LU*^ zcldrY70BN6z|2xUi*o{DV(5RRUJw8b;EGSzjBec~A*7VJe97R$;yh8+S5O%uav8R4 zdGpfb0|J3ycyu1f7V_NGj@>Kk%+j88G=T3yDihg$;K@7}*orTISmNF;>|fvgrOVXz_zlV1u&vlfIly^NnJ**kwG6)dT06?$xN#`uvR=!4k z5OF54_il@2>yAH5DSYq%7qL5h_%J%fEwa+zkutcDL{O1P+0}YwPPaRtT45X29|38P zHQcA)E-zJ0*5BK;opv&UcPitS;u=SL`y}*3mEsNr3TUM7GjHUeq@+}YafI}#05ga* zfVLmDX04EhQQVph2K5QNDHB=7A&$T3f1~Bi*#t3%Ny>qX^eRystvd1|&|%23>p8OL z{0jw$x<9{U?Z&l(Tgr{O;%XAvp}f>gx(t7NOEvi`!u+uI2xkPBpx|aec9?x?O1u{o zm*zH_1b=OH8R-c8rx6?vwd^)JLukeX0G^_AOQ3Ycue#*Dv#po158vh)Ymlp&bQlPJ zvR}kNCsTn2%{a~)Y@G^}hP!ApsvFXL>+c6z=Vm(S#K)_8{}QmT*G!ukAQAB$MS}1k z9Q|{1C1}~C_x+RzH?OPNu)MhSrJ2Ni+x9hbiv~8zMtjI*%dp1J)siT^7iIH9bgNp@weh*PRD+F&(+rJwQ57hzfoqF?WpR>rD~}S#LZ4$i9TzeeG2)>2U=L_U z6f?jp(l17OehAzh%q(^b==a#*!l}($B!p^X$1fQKHE-O?6RUk&LCQKmNFf}w=o{n~ zl>2#T>d8aiwjFt8&^(YHQZHuvhlg)LnlrII9FO|Rm%`0y{$XjSpw9Z~-z;HUxvuCI z2HQB$3!u@*`3C%w4~7SbqY#chylP1Y^*2P~B*i>cvkd=i=jfQ7`vB=LgWtJ$1J$2H ze}?um?XPmvdA7x>JG~_{>jpY~oal=d6H^j!mUxb;C%VPvZ7;bee>D6+f2{W2p%_%( zL_*8G<|ob|tk-U4dINUdWahq3%qkYlY8}m+82vcyFohjd1@8`Nfz|?+_QvS@lr=Xu z4>=5>t8t{SD&+1VS0PBAW@Xo?;5-olp(WVjHZLvOT4IGR!)NmjMc&wuXhVI-G&pOU zFpVk#VU#p#0oQub?!_V{GRH9MQmtF}HK1BhGxG|h@JJa?7v$2Lhyo!}*EQc#DDhZ6j6-#%e_>NMr97t%|QZ4$UhMMg=&<9Om|cB_x1= z5zR1wW@j(-aj>=LKv7H92-rUhDTo(_4}Apd2lUEsWTmFans4mM3#yavWt557)h$N z@u@01%zkeZq#PN(XY4xaznL@)0Z8r8y~M35LOPxA4HA9_A^?kv5mI7;tatm+S>r@~ zUvJS&lNF!A&aWLFTyK#8^hm4+vr0u8miwQw;u=p zl62@_4;^tg5P)e+eYKxO>5EB#g zv)q{VeVX>SUmF>PnHzlPR{fa~%jI#m{G+{Vf)(0RvVN%#Fz^XOwn{dM-}5tHZSx_2 z!^-m*#Ghn6z!}hj?bvf~QGOt-h~>9437y{qXBC^T{I72I*EauLP%9~DG4Zcs3cvj2 z)n)b6!L^L{iUwcjptXi@wy-_yxxDC3ba9Z|v5AR?;0G{-bXUAL&b+$Xu#uzBer71s zHAAbsN}gP#)w5fde{CHBT@0=XgKyt3(x!v?2Ei^L^g z9A^`BRKSVIvIXFE0EAgNbWI;hVSxx02~$Zx;9gc!uPYLm)*|Gx(X@XHL^H4@f}2aA_HWFbPq^+mv(=N zrjgcYJO2m*5UlFI`f%U}@Q>^QuZ&R3xt^&7Cy84EUj(8pdoy^1qT2( z-oUyELust;+0<+gH+X@*qxXSFK4CZ_Pv{uRQ4Ith!UswhCpM8r4{8AXBlm&INLvx4+Q{X3 zQ}tL6q=j*}ZrQ<4)g2!FIsA>>EvWlDb{`KmfUb|ybyqi3Ari&<q$zrKNLE~QiikdGgI^z0s%t2OifW7+weGq4m zz5@#)j;%f;V?B(-CaCplJ*p9~$p#vlC%|aHzF0tH$0<{P7t4fw;v=NE{E(s*MywtNW z8d5Fg`1ZccgN6Czo$D4dRQd<3#983=`c5!ToY-kYAzMMv9m0$^Y~`_=pD-a!JoG!} z7e-6@HPTt3%zpo*DrbU*Pw0N>C%(R8WBb?=rIK4Ro1#Eu@1R#hq*1_YM$Zhr==EEL z^`x=0Di8|jj&lO4Jb|H55PnzuEu3p>+jDIj&=J5Z7BB3`WfW$sjhnu7Ue=6eaXKbn ztY$yLE2|2s20xqusL=4o0Za8$JzR)h_?_8iH8(%sR`~gzr2RG2NI--CCHot`yO3tc6R$981ry&P(U?_$dOo zkI@<9JNIl0^hzS(u|gjJdvTcPKM5#JDCcwiQdtxwu(v~|F$)&3GKP&-cW19FS#JOA z(7yqqMG>@Un5;@gFTLCHkNfI`Q9cxTV#!-vT$J?wbD-OIMFt*{$55IcosJ2`-HBfQ z$OR|0q094z7(Tk%`%73xqcwusrZ&oyh&0v?5HdSw=g07>Vf{ak+weNbhrS+IE)dcy zdiO6gCnQbMz8C&)DnuI03mmAMrZID`nv#<&HTvw^UlAYD1!KWv-_8m{zkmSr_w0coP*v%7FZPQP11kb%_Gb)tP%D{i-;TpM>#r;5Jq8W<3ys^^rHE*KDEWgF**QT7n?g_n&btcmuP$7MmVfy(H zA+bd}w?n@g^371WF^am1fdL1)I#B$m*cwE_PW^7Z{`6^+Igg(7m!ch~qHg{<2(MEp zFSd(>gv8k=N;Sw%f$VZ6ZQM01Y7a{9gXoivZ&7hEQrHIMR9@fZ#Th$SXXlWD<%y*~ zWwdfkVU7c$={~B_f)-ucL%1!Pr(j4r#U6Ly+Z3p+G~`xEV1mwt9hC30bP$OK69V+X zY%hi2A3wPtu3WxO3|C{u;GbAfoFwHZ~R9_m^T%2?8lmQA}gF z=;W`mc>`Dbqj7DRqt#a6EC7!mY-~hOMAkvca32t1^YhR8J+U)gX0y-8Y@g)e`u;$^ zD4`wp4}X=ouX`MJjNW(&KrmG^>lzHLs0kArQJu*g8G*bbBlS0`_t)ujLXX6#QP5uP z*LLH*$NXv8Nf=>XsP1wO-WRSEa3}7OS3VW^p30yoUQE>ET*bgy$YWH2_NAcuxQt zE1`<7V!#8D0?Hxz-^JJuQH){V@)}M=lV^XT_skB^QsUIcqLVsQ;5w=Tv5{ZpAwZ7mM6byznLB5`*-2oWOM#D14Wt;nH0FnXh zd`I4u2QcR`X z_!@SEJkBn8r{txu35FMkzGHX~n`>5d-)Iyz%o zpHKrWrIP#rwU8Pj(&C#DfEp~0fa%4pBi-BlAXODm=cbnLk+BEz||;X zH_EQBTV2%{i&n-22UnDWu=~o{W{WKMc}^9!jt{)o{o6}ReEN7$BR9}r5pm1!rrdOXTgJlbLgZrXAov>`rUuWT8Q_m>39gcaZG0}}!f;L)V<(a9Nh7f- z-_Z=p>|tyRlE06C#c&$pXY~W$m1W{yhYT_S4GI>HOTL{c1=T3O*)W35jC6iL8U)Iw zglF7sfXaqD#phj-+==nS;~!O({Wkg5gmIsmdKtD}^$>6aiZVK17@V9{$A$sfP`oS3 zjhVy;M7LuSxh4!lb57WfPT>9Hu(A=fhH=Sg?DXBgs*c=}d;oLOSS6$W7)+q6suHGA z*;k{)e3m$P0R(pr^Gw4Ha7}F*d#~LX`B+IgMXy_}_+tFi61`WK_)#uSpu0xeZNQXK zZb9?EV2uLDxdGFLJ+cTy%hhjSJ|cPoNZMvr$ws}5-Hp+O73*=wW)Nq|WaXu}Y{7{t zIN**#3BpbC0PPV80hD!BBMf%P&gE!JEL6FMcr6U)I*oSSgKD;wp8gtUci=7J$a0j{ zbKa_Da{7~5$%Uq51`TGhx1F6kVHASTgJ{#kKNj?3pa7ut!3&fREAVv?VM;s5o$ar! zPXkdSBlh7tJd^v5n^_3%Zt6nCB62F44v(R?n#SyoPzo_IivH^%2R6v}T`5^I%89>P zW+mx684|ipE_ADy!&6=x*5NnB)PRw%aQ|Xjxi-pBW>|me#3(AcO#eEMPOmCfRxwdl z2I`{-uKgH3jG2W-b>3jr7i;QmojMZu=>=-LucGR-Z^Xh86QrLXfl$+z8AY1@n#F-> z=l=ZZh1v}_-aOtDL7~w2yuO>AGCft}KPi#;Rp?a<4V?+h-~E+G<9%l&?~SMhD&e+V!1k-KLPOcH$GD8(BLlo15*P>WiIjGC09Yyq zf`5)84LaoYyH6jE61YRpVzd^$rq2?bw{S~Z#MA~g&JbqDe@(&)tZ-0Bq7J~I6OU31 z1HTkTz?9)UBP$Oa798HTJ}e-S^sazj)eYJFNTU~}AdZ-=AlYFLPyS-x5)reJn%V^A zhJdYx#4w}}MEQfiVC&p7$gOlNt5N&`U#Kz9ai7QmgINOuxZGZ}NQu=C-&}{4o_?;^ zzZa@8>8}x}3MX{v5t;TGP~dixkrpB**d~myR@)(YUx6}$ zIUX+6`yE3L3Pw?XJ?7XDfULd9p)g>_qY9GiAw+gB9i0HZH18^sf|&LQnJnUu-h|gi zCy`F{+wdgoNn*i2k^R8bgS0ECU&4xEH`o*3BjVw2pg`}0xP|lVdicKn#OS-z(3c2^ zy6BVmukWskX-$@M7HNiBbGiA&Hc*@ki7pWu#C3T(TCfcM8vt|YZ2V^*t=IRS-UcEE z7#M%H6)y_D4Bt6ah#I(t_{DBg>MEgqGB=nUwtmBgGnN_=jCt;pPv8>maLTCvCiMwfjIWI}K8OyST#2$U30*DEHXI_YiT4gH^t z=9E?W3)rj?knsbUk20(CH&!yBrVRiNJ;HyH{y$*3m0Xb`3FL+yA6o*-V*pADu|P8) zFqg-yL9NjE4)TG1DP^uA{97_KiV23)P6BP%ZswTe9)#)tp zK1Aj~(zNbC6+R0$fCddlCs2pURwX8Opjbp1Ut{GO7{`AglY(?V&q=8`h_A^BnCt7| z#aw%jHU=E7V|%iDPtl%uv5bpbGTl(0xyX4%9b2U&NRuJ%~$UeZfehH&9lYOXKzcWlRFEL3AzcMn- zZO9sbn=$AW(R>mchG0XS`*64J!=O7D=nuQ#m5*Fn+875S0f5r}1X2~&YeEI{Ul((2 zc4BdegXFK8i(9(}4-gWSOCHZjSPxWX=WmeGf>?%MqE6`KePrv1U(j7%S+zxCS4=c( z=tH4dE6ORsWk;bhq`T zWW`H)$hvs6Y6KKiG~!>pN=Y@?lEwn^!m#JuyQHIwfPbOmKm|?dx`%MTMlMnl^vD_n zaTp>MK+d}fun>=X66h@UjDeHwYe1s3$JBZ-Trx?85v|n1W>I)kVD^m^v%CPu2K4QT zjkpK{c5@#&0RjR5G92bG6!ZoW30R^ne>K7l8tTmj7a0mf%YN# zucIN%Vorx!E!&YkNS%N>4G;`kR)nUp!p*-nNitrZ<8nvQ4E?rz$EV)hKEFOA z6)PS_;w0H0aQo9Vi|wGjr3OY90KP8ag>PpVoT!I}1gf!*G}YMH*sw4(doc6_vI*Bx z;tn5C(^@7dhzxxJiLsTY*#tYo2U&wyZ*CX!#}Le+e4Mv|Uw?!U^jey3C0F1%a3BiP z9$x|y2`hx95femU6ZMAVJ)_{_c!PN0-M_7Y+()GwCR*_5&^mWRFa}n7mXo4z6TRs- zk|7wN`G8G?`8^h(5#o}Dmrkk!lchW1L54$S47MUt$Pw+X-%wbrOc{5Hd;)|!3=^y- ziZ7OZKP+iwqzi=8Q~;Dy_TBFz9~8G>jvCt#^YN>|f&rH+h9diS z!Z(kEuX{CY)_z~2895T)2g^sW8#pt<9{USr7Xg@rNc>l&Um1Q>|;9^v`>*Y~J+z!_nM zr2FqnUHtPq176}QAaJp|MyW&~!S)8EN!Kboh=IOps>TcN+2y^ zc1IC$HHe`Jc$;{DSaA;x_M=@g#DoILAF6M0+khfE+aCn1A=Z*bTeW(v+H0$eSZF>| zgjud_qD%!lt=x0nLUC}Qy{OGem>#15>-;-9eRi+IPKfn-XrXJ9rvS5=faM9PO@S`H zt_q%$pMW>E9V<5>kkKJav1kVWi{MWHaWS$UTsffzV2vGLQwwuVH&vGmU z(d(S~Ja!vAF&w>bGTjXDiRp((f0qh*3`>85%0^^seDzzrS$h7)0YCCufspQ^xq>Yr zhGkxZC5Ea&Vih7O+T$`}iwf-hM(G&$!(to<+WFihvK zO>2;CJLWbQ2;&dPJ2BoCtt>A9deQ;dV%Wf0;Nf)=wWNuLpCFIkY7{&7;~0CFbpFKv ze0t8Zm1zhD5r9Dklqf8+8{!us{s=S{C2He#!Dm}s)&6Sug#6$c$lcK4ZcNZwCoV+P z)U*G%5F;d}x_fv@>k9P|G7NcPBm!^qhP82@;@Sk-2RjZ0X>cC&rVj#G8v#(mka8%J z>KLXRNa1<{G?9rTYk<~KN4YUDgbw*+IjvkHn)VLgYcIP5()%3`W-3FV!*A}_K3pZb z(P>q%b~Mo?5FmFY?H|52O3q)QksBW$U-bZKbTb5dd__1MpN^Xt)XDG`VkQnU!ZpMV zs=a~;RRIMK{E^E$N^_BpRmz1Bgp(RNK;Coog$=R` z!7!O*{-b4uJZ2co>OkZ4GH3{j$<*&wV9+(j|GZsn5%3H$%TL5J2n=ZVMEfVcgG>-x z_UiH{atmQT8RNc=@BMyG&C2V?yC9!Pd)E$x`6>xVm&6% z5YI*cB&M*)xjO$=!e-3wtKOG}O?(69|KsE1jaxOS&-BQ@*yn;HNahC?6_iMW_KC{9_W;t)S|{`rF%%1w1LeLSJOwSl zGikbsePndN#u`ZSZDnPp?BXK=K$Y%(9HQrrCNko^gU%1}b?{uYBZo78DjlP-0=>h6 z%aJpUV53CUen^FK@^5j&fn8uf3V=#K(f)>>#fesgX$(IlQ%E35=O7GBhg?#HOz&Wl z`p`4HDsnp8L8n1^(6L&f>T}>c*vMawE~1zaD=X=2flHC;X0b03=FcH5VAhZY=o@%b z1J`%}cG?8S>(KwM3}Ijj4?9#vUr-@(hz>+gyrUm~578;eRD75NRcasXkv@NZ^1_G- z=0U%juW_f^Ut1uK&C%K6)mr4J-qb0bxM8i;nWq(O4Yz+ zK|X&JpRYyi5E6~Yc>9kJkW*JtaXq*O!UdA|Zm?RM9HLgP%5|KSQR}bdU?)6+#6x*k z4j{$eAb{A+Otyvi_0 zV*nUN+*d$DWOO9^gF7#gfKf()=*U4ecqjxWVcGzeV;I@Mc>s!!2n>P|;+&<1yXD3y zrV*%1{~L>T7ieJdK|6K_d1WBn&z?y3j)BXTL)(E3=ikX-*1#l&K@pO+A+h6Z5*Bv$ zL?-9c(U>_Yw*7;sScOB6D9Kz3X?KHB@o4bT|I=8&WZ)5~ESJB&PD7Awej*=MhS9LM zu#jN`sRT3ixTE*<6wnGMw;^Be^I3F5#XA8WQ73eU>y+PL@$K=cN=zU)Dc>yGO69TH z8Et?9m*Gfz;Ffs(vaZfR<(+~U}3uu;?=dkTE` z8JHSr%%C3Lmb5p@{*Xm02hRw0l*8hjJ-lAW5!*~)zp&ASo!@JIOmE2;CzseehSKpN-3G|dM0gL^sq*WZ|Z%odrPSZu` z685{h|5`S5A@W%?+L3$qBT3@>A^qsBIVZ#!b`S3c2>)ZAy)iisge(Pib`{1k-=S|z zj=Mku9ZI*(|KXS^6b~+XzyHVsfC0|!r#SCW$}q3rKwE9P`iG>7>XKgu0tyN4+%vVF zkT7?&Ogy`%08Uq_K{bb_a}sWXcNqM=(Jai_Ac4sONF8O^VkaXw{eZHrt3QbEKV!~> zMrZ#}XTTbN|J7SsYXVbi=)(n$8J*?Y_qw&4s}>o`(st_Q{~S4mB1g9se1QPXF%+P_ zo*q)4H}N$p+fB5rrqL-47+xu1GtIW2vEeWqT^q@LnX+U5BMzH{7~3WpHlJRcNQmlZ zZ*Sj&D_lYllMqayq}xi2R5-hfcw(?~aS{#v=|NK?4rD;vDG!W5pxxQ^t2nf~pkevP zjrpZQS9AUPy5+@0-y+z3_`zZ*5UT!U4glUFoHR$yAH~J`>*8ZT&91@`H8BvQ?|`{3 z;+=rj!|lo!edH-4kI%dPYR1~4Z)4Pw( zu%><~*m?!S8RSH%iSKo%$$*%M(HiVK;?kYjg0lgoflUX{v)U~wDf!+Ct)LSXu*ED zu$>)x7oKj70hTOk&&6vEzt0;gWTw)N5Bpil?;f4?MD8r*;|WG{T4| zE-fQNG!$4OcfnB5QQ#Z|@sfbC1rhY&h@cF_j-f?Hatwg_GqqjdP4A%nQ}lTiqCp3h zU>AflxHQ+q53kHpEA%Uqn}rP^0UV%qc~+I{1z+Qe2~PRLk*VZZEO_GxS;f+hLwqBo zk#tZ&g@?c5IM7j3h;Eq93kQ~V#KOg}l_qKI_Fv2n?%C8D&Z&Ixb*koKt>px~dUJYm zM~)r=rs%s)|F|vJl2?LlZ8iiJyy^-_i{(&P+R(y98YTE$b!RdZaWcIKQHt2%0U#CF}t>`v2Oy@^7fy{$ENIahnKbxkJ%nnN}oiNTpONQpr}5O130h zD*KiQAw$uENRo-cokX%Pk(#pa8cVWf=6PNB_j%59?(cu_J?Hy_c3E<4)wmOGk=ExtO{5pHJK5uA?20w3W+pKG`=fQze z4efx;3oQOBscl*z4DJsRvZ8D&{j8y3A?VO{puKC(v6Tis(T;PD#P@5ld+GRY-ov>D`p}~bD;4ubuGFM_ODI8M;6VZdSADr3?AmB4i(wH$u z8?1R33Y0ka-Rxnfg@-Ru;}bUT8no`TQ(Uwoz6c4sD)E@G=jm_=O>U9ZjA8PNLumL$ z>myuTL4iXgwg@$wL>^+&fMr-e^-378BSg|rMTP?J$GL?O4c2@21YaMYc9?icG!bSu z%nlDRD(Xe6c+Fo(Q2~ZO<86;1IKW@6$)(EyoPr5^43vNThs%wf^LR#`9>utQOeGStZOjuE-t1nXd90Qv2b*6Cb6V%UJXbc#v>>K<9Qubr ztPuMIe1r<9B2c;$Q8em7!IX4_pN1?@RTRiOh;C*7{;3b`h=E$O`BZWxPLQxcy=7Y*y0`-0PoD9oBzWo-&m}E9fM7I34`+R= zz3|3S%L#}KYL%4U^7s8B(_nEyD889(eEA`ArS-16C7!bbe{`s;jd-LK>leIm8mLdi z7s$VSLGr$xuP@f*Z@u_szPhLqrH>qPP*7B3+d-zOSUfFq{iv%LrQ|W+7MDLpM{9xy zI<=lvtlmre+|_4$>J8V=o?D+5X=+vr4vqCC?wn`QWs)gVTwlpgaVWkmGL2#jIps?D zAP{AG@LQ{#@u7s+KNU6x$!-~PV4M7z*rv}J**aJJF8$7Srz0~rB1LoU<}Fp^vb8nJ zS`c5K=5zE}g2}ewQ7(P`D|Rm9n`CNr9R(ec2LIlikhw&@yiS=OsV$eXy5@i|MXKt( zYbYGeI|TXp$-k+psS#G_$vFi-EuLKCkF_iH&d2S}FciFb%j}!FMOT68TqeVsu}a|s z?~Ha}5MOV~QEE}X$u`~C#)eVthk;n)b|4H$wNQyVzxsH~>!kz5p|){bX{xn!V~-!k zlVb)S?zENJ?AjgdFf6Gqb|&MLcuCM)PtTwIOR3F36vek*T}PUGX}4iQ(r84zW^xz3 z3wCAZ=LbKZ;uDQ`4-Q{)?V8xy37^F)T*seg7?^wazV7k>mjhcC$!q};*S|o%Hj?Xf z{JE^R>8EvGxVpZ3W>D>UI@7%5`IV)7j0uy5Mg;*yb?)m3qJSEr9pXv?2x(>?Lgr&+ zo(3#~0iwPucDEKU{G2CRFuRoPd9xw?bj=e%21k>gTLhy~;_eb2E+L+gf8%7(Fg?R3 z)?e%B;=U(T^TeB>Z!^D}IxA-^yG)Y&rpwEh2P&;~ME!>YcL%^saTU`W)=qv5C7|37 z>YoH($uTyY8Sg1vWmWaWx3sv{=MKZzk#`J3EYaG7>odY|Fw&rT!hFsw-&$LFL#4^l z{hwbiuA=#d$tIq9^Te>zs)~e#_SNb8lwM>$ZKG12Lmh#EoWK|NsTMv(r_A~BYI$iV zU_F&ho1HZqH0m%J=Ln?H9T$3VB-b3hp?5#QK;9^SdTO>uTW{lk4YcqP0L~iy0vT*r zPj{s}@(6^#hx(Sn?&3RVaj5^V3a0&b$6hiMl0+{6p_})$oa{UeP0|Hs{*2|diqS4* zDJg@z@$fdPKSkU9fw_7X*ES%y#K8_u7n9$KD4jP3cl z`FG`9Mq^wjOdHq9*3>^n?4@ay1TU{j#%2FaB>sXprqKxtcT;5Xdi^W+j>@HFobmPM zOLVf49g}vQtofW`+gQOnk?Yi!QP?_u2}{j48@5)oE6AaJ2U%VMRvJSDFFrN`C-SEY z{GmuhYHlhHr|9tk9eQ;v zPn7cZnHW{O1UHvQVFzw4DEai0(xH7e!56`=Kp8+360|?}Es_xwo&Dq6-{0DI&vfiO z{hE-Qd!m(ohsStn(Yv>$Jeo87>#cm&pEaGlqUv1r>gCFFQ+-cpu;?rS%6TYyf6x<= z+~Rc{Nhyo$qO$O6&j)!k;Y(i)6-sAs`nc6UMPwQ<60x?DWKlHl0k0;6{MUe$eRFX$ zI@-N-Y4x$+O(JW?lDL2HNIxxf+bAmH8b*dz)4Th@*DZ(XLyz1zz9sg4I~>e0DxN zqF>lOX$NDt#ePjJ+jhRsxt~;}l{1R~=1=|)oqDtAltjSs-u6i)la1*SImW?jduS6h zx9*CX7m1nn$|uK>`a(&Taq#v)w*@|oC`Vxa39YdRj6MK=K>4TCl5MQxsdm*f2pUe_ zZ^i7moGE7bW$V^GPWLj6ExD)vVLA=ex}dmDK<6Zjl9!|}NOR*#Jucp+>9W2dg?pr9 zyGv!Z&2SIxP=4;nG*XtPYk0Wt8|E;wKq)v3ex?Gic%&lgo3tb9^IE5Vc{BGP%POMH zHa?xQl^*(`|d(*{hcpsW@fp z3Ozjwrn;A7K7xx;CXBcnht_CFyuRdGm(0?BXSOfOqwePBJs}E;)K&g|iWBHa|6}>Y zTnT}=IX4{I-;c$qwzkbJWG_N#t9nrLq&jQ28Qg2?^<5R#jwv&J@{b%IXes>L-RaOH z0G#|t^!~I&Sm|{S9z2v5E!0>V@|HbYQ&>n9?k>DK=FX#O!>}qBQ--%TKqP_ncGOFp(yhhBDh01YDR4|%_s>VuLN zX+MT19^seV!nfrJ3y{7)EI^MhOU80`&hZvFEtK8DGo(Y;LX4rR#n2AQh5-K<{ zF#VceTDnjg*=&`|5=WooB7!ZRo*m;k$V&LyrhawfdBlSmgDhMq3>_sRu`-~yYJCR@OyJNUZ^7a2ZBs(bGumoFjHRmu_iMTG0(NfQjY3O zym=qkHtiIxRGVEpcedu)?QK znzh|(5@rMy5T#!3;Kkd&2Ag&0%Et3Aec2HptZ%YJjQ3~v&cLNQ^rrMnL0bGtk$_zGum!-t4I(!iMgy3pHD zHhJB9k;;XmLCd6m(z6F3Fo3r3bg$~UL#gnZ+tI@E?XDk%- z4PK5TxTEn+U2ri0jVp#;(cquRQnafjjf>UBhI?zap;q zef!;-BWKX3!R|mrw|YqE+&4h+XJMCS-m6^TDQ*Pm#jZkO*7m;SSL-Ps#0<=jY{2l>3%y2sk@WC`d~Egz^q2j~JdV zNbQpm`5C%;*kxf>57aD}4URHQ5)37F6IckKe~AGit@UNbuh^2@ zAoFH_lquT{U8Hrm9rYWhJYwOpjVi}kT_44BO7ow&PPBEOwwOdl*&UhHN&DCh`!8;e z&3)_7AXh4xv}D_m62CU>q!n|)1g9>E%CegnUC(ksK)FaMW1(nz5e5(sWiLL}SL5|HI5_UgZ-W3(e3>wMQdXabh0Y0avpjaW>NY)LL0UEVn4sa_B+xup_ zE6X5}qFH?~jdM7|hz@ZXZH-?iE`9V_5wg;`wy+q7Ra@u|zUuDR4}JbS%*GzkN*K}i zU`k%dnUKi`sE&+&yE$mlwK0^EB?Pj9Iqj@)09__=?*jtBe57Q~G1bx=UmEo=K=)!K z;2m7yL44js=|K<@1l!!G?fQZK2`tlHLCwh<_^R(bzk12%+O<1tT9&yt+G zmcdcO_bpr(_wK&wsr)c+Vt8&B-|~rA!MJJpu0?s7^jZ0eZBBQ9^pfaqlJJKKo2aM& zw?)JbD}U+^aeYdnd+*iyh; z0vOvRgqD!IM1m{g)WR{By|Aj50>HZm)Y+gHtG(Ua^E7}rY?coAWN^^>5Ht`XW&o7D zi(JYb+U$Z-nbIwRCV*jqwtobrSVr5vow!I_TBISu13AxO?uKZz_s92>axwL4*kiJU z7DD;^@AWj5Q3aZ~{0J%}GV#MZcs|ZSzjw5bHsyJiPsFS-M&ypF5Qe4*g~MDbH}lb{ z5V#G%#~cEOE1jYf39;$e4IE{?Cx1Vdq2g8pEtCD{&nqY?DG@mepyI>8`A9%11Og`0 z4$z-=R?}z@auI1ELYnzjhZl}nv0MInEjiMh7h80opNeWipF literal 26637 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 z'yf9Qc*%Di>9ziNF=+1$dyxaiEm!lo={1`cNRf5sk!9*ooGkt&DwXAdACTDi! zOLus_c`4h@JJkEBxyI3}B4A9X>Irsj11dXFM@{o`F8y!f*4Mk7Qtg#+l~f z;9@WMCPZh{+pvdd)4-V#ekJ^R`ucT&WE9qpj@N+S9F8P9WcOBto_v&NMwXRD)6dV( zr0Wsj)2_(iuIdiz{C=+g&hqs3!}m3$5;9M}ji0EStHw=?NlV*;l9fp}B@wS2#Z6(~ zOxnA*dUd(Fz@|EgBCumpLq{nxD32Q7Iyot+D||e6b$P*VtUcQdXa{Ho3+8!i8=2Q- zvZF_B^C_?KtVMXr zoqXxmZ2B}4TAdL!HI1fd+e7=jqjg5v*toe9hL)yFN)!mXwDXR^hwyuei4m%zk=tZt zS^bt~gF-_oKjmBHKex%7Q}Q4meory{j%?@7kmU#A;S{O9C>~i&JfljuhTY&;ICW

    _+GO2wf&}`q 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

    9a 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 Q&kuFywz6FAEyEZ817w~z6951J literal 36485 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png index 551d858ccd9fdded438742b1690c0039977a0af4..c9883a651e68b79db0fc3509035925de187dd523 100644 GIT binary patch literal 24565 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png index 6763b66929d395f778bb8fb7bc36772b8869dd3a..33fa772b2dfe4aa8da5819da407060178cb44a0f 100644 GIT binary patch literal 24177 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 literal 24552 zcmeFZc{r7A^ftT^q9TQoDQp>%G88f<#go4M5!AYS|7SRm! z=oAXeN(zP9Y(5+Q&($+$o$-g-sV!!wb~_z9tgTMgtHVn;oDKH5QYhTklPqeNBss6N{9$-$ibiOR^n7Sh-;IcG5(;* z*!mmb4?_VKJ^Vqh{QrOY|M4<4Tw{-v8zMMJ1B3% z^?DX_?ba5NQWue09kr65bC(e3LrtMW91otRQO9$+PSpGV()4oaQtMvl+@{m~%t^F< zuOuyl2d5(BT5u#)=JT3^&trPu+)|ou5BBJd-Fu<5LuhG;vy0qTsg>Q2BW~*S9Mk$B zRit~Z=W)dB`Ij2(eHY7n-)Agksnt#iU|}D+=j0Q*v*(9a0@YNW93)HY+C;T5QI&9Z z5%0*mJ1=Mz6}cxq4&eVbrg0!(mJ-1|dPh9&LeW?>eepP&3B?B?9}u$)c# z64l3bX89IITAfjfR?@G7&j(6UBV42gHqkh=C340ns;utv{2h`jCj+@v+s8TtG(DAH zxb<^6%hEQw-^V}|Eod~3&F2@kPyEPou#$e2vXtZMJk7USF_dWklh+qZB|9_EdJk;k z(j2M3R?bLcu_3={et++Pfct1u-dN+dmPmtvV+Awvdp3EojyWnDrde-J_Usby9O>a1 z!8)|U_UL7@^737Yk88jF?oR0*Gz;5(R-}h=m$~+$p4q2sOj(7$`A;-wb9ho|&1;jH zqNw(1?i#iB+LHoxbytd0W976cS6ODmOK(3svh>!U-k0YW37!?9F-AjS-IWGp>|eb4 zza{IP-5n^>wNjW<;~>4HEPb2WWSG*&rzZ~7OVAoWD8eBKbf?TtNu4`)u4SJ0+8*nI z>s&?A50^h~^$50{{l0fogapm9N@*n{E$oqPIoC$Fo+6$*dxsD6d2;0OLN@+))ir0o?@9%P8D9uvvW-&bP?;otH z&UNh-99hZNmt8kA(f7EHZDTMswv@afNI>ZjCB-k$!gM{8=ay8B;cBH#5#qE-JF=N2 zVFF4$JeL}kdp6OpIng+jW~TeEl}D!e%&nRAH+|8l-Sj0R%Viok%%1pa4!Udf?4tJi z!F#5KJvd#(f0SKQ@8VnLB_Z?F&-Bgr^mnsSm>B)BY($!oy<=_^ zLY_U>PaS@9K67T&yN-$DS{50O$)V%tW2yFupI^A`HZgfs9j_F>{usY&cWt_ARNM8P z7X+7Zd}q_NV$GG}y>YBOJo|W)BIbM~g`DNso#y7%?4sU9clSNMf?o}H)!2Txe=z<2 zkInaO>T2KB4X4e!ZTbvB~vjtso?=(zW6{yAOC$vOl2VlssE z2RNWzH3@Mo^e0xu%!Y=Bm3alU=v5`eo0MSQE-fo7&L0}<;q&I^_UMNVclNHmy5YqB zt|x9SC)wjHebxL}ea)F3-)i=5du0%`o1LpOAXtPG=WoK0Ec2Se_SP(aNHjougm>WtL~u@bvP_=bpYs#AC2?5dKJX%K@gFdu+hVrl3KTnfE^;tuX$dZH&CuE(smG-d4&?W#+z`8lW>m)5zj zFn(W=M}u_2v3FlBG16y+(?752Gt#CH!R#tapP&9=$XZ?*ySgfGgAmu7>zjk^oKN+C zN!ob&dzy1|b2*|$jg#-@j;}V3 z;iamA261k0t}HNL#xKe4NdcjQ z&rebc9g~2ONUwdnU`)B6QNOWA9%cKO>_2j zj5+)0yNgHO-1O;q;ZLLQ#8xc{(K~Bjbvbr_`^W4fyW>CXy|d@1-&qNDb@g*gZ`E#F zoBt}OAvJ!mWP#9<5a;&}tHp2aF6h=X^xqp$?%&%WEqXbozF@oH`3RBig}&3vH=a7| zl5n8v@){XAIb~g{DLMA`*AS-|lG_*$6}(1|YmIkCD`w#wZ2bKE^fosATgFMRD=Q7# zUln`x=l^l|$W=jp}tnkw^EU#=7_}5w_ zw$Rr*)Cy@$kG#Q9_B~z&54VF&zdT$xx^@17%X0flY$G(wY$G&EJ~BDP*;a;k(A{18y!kWiro^IC{(*bH4@`-8EMd8$`$-) zJkK&bGXK-V70QQqHdsEQ#tOpFGOwA*m6e=Z5WQN+wX53tlS3=Df7{RIC(*^kp8&A! zpe~`czlz-}9%VH>@tc>APf{C(`s)3f1JYlfgnm8v;=&>OsDt-bygT;x+KCruIy*Zf zqoX%t^zf~}nWkS@yg0KaH#c|dg*3w|N>rMx75pc8OQ7wqmfXIN4^yjuV4b!_h-fla z3*o~`sw8c#o)nv;`L z{X-YAA4Qu#>@bC4iiXSsg@4T+5*}l~PW0RJaUZ+ba`DWN-Bw5fPxtLpL)s$oKrs zoNUA}gg=mBeR{m9q_62Qc39MROw96kxf9~J;XUWE@DI(RtM}fw!x=sP@d1?BUs#7IO(bdNYo4hS2er z90dVEC5KwO@u6>UW}N2^!_#H7IVXfwzJc3Vu6%g0po-(XYd({syu7^2#TboefiKvt zai%KTNK9V6=dSc{v$LwvR~N9v&6*dp|yu*nP`*y}u-DCC=bl8gsrR@GK1%W)D||1RNnEA_u5HgP zqhBgdSw4F7sHY{@)#Y63u@Co6vMe;uE#1a`sOgb?XIIxFkKscU7Z;Z+8&AtVIrf3; z%sQF?aAC|zATIc$ZDnO-Lk^gXrsK^0j|&x>^K;u;TjC_rFkGW}#nSmvF)nNu(qz|) zL_EfG^wmNs-a|Av#w?2@cz4ObR6J;BZ=ddLlVKx=R4Oko&o1cHua8gF_37z})x#68#W(q0e-Q3^>H`d@jFOOat2Ou)zSn7J6(@i2iiXD{9&s5-@_S?C zCtJ2`sZg0tPa>iB{w_)LzD_k#k8}JygBcznuzaLw!h@orfO>!ngkgo zYs6n&e~e8dJ}t8v>wMP{FuDc&a>Qo=^W~iEpcexoEePB^!3HO&=j-dM zsQVl#;j56Pmlo6bO7LlyPtTkj;Mywq!dVyaFAgmQ&O?k#e`>P+MDyFW$jT<{u6~4w zQKD)TkkLFcWH2En?N1#)S0<{tGKwEMx9ff#bca`Q`l6Bhd=A$sA3>Z?uYQ8RV&fJ$ z9%PWY6UV~k8G1LS>?CgVUF4asrEiua*>ikGKrW#_n(vBY-D9437W<8aa(!D2f!@%;0H6Fer-< zbqX?&U4{>{JU!V_W_P^$>iSR;t_i5Raqz_%tgncs=T5}lw~JQyUXwF>;9nfbF4g*W zc;F?s!_?RyF_X3ms_7ZLBkT8Ixu}$_E&SVEvxhgTkG*VP_w&;;gg#=z2c9`%1SS?* zV{I&$arNlWPfR!;w=49$==xIazKRG0wt*O6is^VPmy zkXWwmtMM+=bb-4fEjE@(+&%{o=KH%l+gQtSnyd1(R$RKw8IFA)w_u|4k;OjGC44n3 zQX)cwf$0f|F}N<`S6A>WAin5N8HZ}FmX?e9ng0bozgpA)d|sS6J$WuBAZ#)18`8E+ z@`<5uRj@R8#D~>C9zTBEi;pR)Zgl(Ar?Q+uxdMaO9L!~p<3$nj8EFU;R=?cW*XJ)4 zZ4$qHC7o|+MESnwr;aFYI0Q_Jd;td+n^Mu%^X|?vH8nL~C9w=65~u-bG0Cngw#$_c zh50!eG&`|fFsUe=LloxlPz9lb1#fTf3jFo?h16bEtk8w6sWORXbbA$G4a~E$Hc1@| z+8CgqlV-SzKlI_@h8sYPf3&72>38<50TmFnFq}(x z`6|}R{e=^a#%93x#J-9@+4H-MNPcA3z>J) zYOnOGaOW%b?dwE+then9e100IcJ*|fRszAZ$Q%5`XIT$CJubsXFhu)aHhlsiSoKr4 zUZShsqnhTe)qfo#mHZmJ3_s}4L{EoFpPi%iqV(O{OP4i)-{EPH&fjL(v#`^9w1Ic* zx%WpdIp&N0=Ze&e-bBqmV5`vlBxyP#m3Gxjy~PG4vxAP+$# z1kK>oBdTUsAKQF=F~I4z`;H?$4S@(ow~p_j8A>@7PH(^(7;b%CA(c{He|__vz8~k( zrfvOAY(%{Wn3hTzwe|bWs&ALz8QNwz#<6oPYh4n>g8gRDOAV2THxCc0BUP!9j5DYA zTAFF$sC9lX1JoPqNsXwSOE3$3CjTawh@Lm$)D4}S@_+Lqj2dr!Epsce1YcBg{B7RY zy)e@7FkrH|+s`LcI1NWcLe^!c1y%Wf2L~y?PM+7sQ+(6ph7&p8o_ttLPrE z4-nA)Cz*4uS6KZ_8p3Nu+wH&TDXp@*if1UP-#b`r^ZDgs^z({3vhfZnK9^Ib27-@I zj@hm%voU8gS>SoQE|0r2_@&0u2-kP9d+DktRsg;)^t?+4)&b!~E2tVns6n>3J^q8f zI1ju-jCp$x*vMv|?FT(V2u9m_qX|K zzu)ezsH;=aOl(mmOu7>@8A~lC}fRA}7jqb;vZ`7PnrKmg)J$y<<^XxbQZB9g5Gyh}hb-b@QVX zFEBB>zJg1bYGcUjO`k5iB*rHTxhc!$Y1VHV z;~g`mmV9Shg8HXSrcYtJx(0J27g`R6N|UK@zf4o?7R)c-|qeIKLl-o5Lj97yd= z@cQ}W17f7NqAua%fOan}mSI`G^2pr>4qE1!Eus8K;J~zlLwZvEIp!UR>q&E(j0S_^yxkYo8d zZZl0}V%$7beWm!wt)#N~R^Ih5V*m%?WXoFjO zzf6Xf*=gZBZokSn@k&_an;qIoSoB)$)^u6y!DhG`sknn@1e_@4Y??-DhLrr5)_by# zmcoCK*p8i?ODp|u61@4br|Gd2Vv)S-Z#{;INB-1MmC==T0qz=HI?XOkz zxK3+Zik8n=5q(C?Awu)4+L4@S&Y||>?&C3#RJK6|ra^_#Z>qu6=(WlUiBhB}>r1S^ z`26{NO+Sj7e!btjTYaH`B2_?$6q5>Pr~3yTZqnab`KQGvm6nby^1Q&gXOXIadspwR zK#?tsn46w|e$@cPM)M41`At`0VDnk1H9{*cHA?h|f%(>`ty)_+73)^SpxQs(y+iYf zNstEI=u|tm-#Xni!&(YWNqA|9>~MjorDU+?9Zj$UoM5}@E7XZwsH)nw^)(?^);w#m z2{MSi!o)aq)O2uI)a%_uUltJPqElQn`h@z=>^CGk{~~#EVx)I!Fv3q6@2;fmS~+@u zXzZ&PtyvUVt>oIZYX!t2v?ipVeet}LB|(?8!>mpSxP%tx{}3TbAbHuhhG$N#^wnY! z8bkB_Cf=lkEzV$6g!P|U9aVaLar{7ekIhQ;72iN|a*$z45-REbi(k*}f;6TEUbdY1 zbYklTlMtBbAyXR1aG;1dYcj_0>-;ug zuq9ZCrUvP{d765xtJy5(pX>Ql=r{L#1|oMLx7KS^N*u8S{#XKIjrMuT9Hu`72Md^v zhnDw#dX`!E?FKbNJn3YafH|B-MLD;|0A==%-z*%{5wge*i9Q>Ybj9|tX&SITXFuF> zjY(hVq~6>Ia+T^dqL1CrT{S*7GuhuAuKo)pawjtHxGz)H=&`Qc zH|u*J*EcBa}ipiBgiQmev>kz>`^X9>n(-}OG-+P^faF9 z3SBmQT*KIO+;;fLHEl1)c=sETx-+$I%*-4?4)RdV8ENyT{nV7Dt)*$+IC#0()f+MO^Oo?%=(x?t#Wh8(G1d%WT#ddM!bY zr;*kS{#_m6JCaI~V$5SRXa+`aKRaC8(F6}@IjEW+h+5upmV#xRgWgY$YWxA8>ecsf zQv{V(xegieI-KBRLxbsY7M0w7V=wWJPX4>f%PwslFUL-Bw2pK6Y!-8zC%aieo;f^J z&;9!T^&*~~JRO@EycdS+v{Ni+hT<@X=^vK4SOLtQ!9?eHdv{;7REqD_W9*B*Zfu*{ zdExgaZqxJgylU?X@r69NbNbj9@5vJrfBHp7%ou44&lIyR8wjkMW z7GFcjpx$VZMm><&Lms_Q>$3#UFDApYB7F<^nU@9WnsYA98MFD~*{=!2#E(}|Pqv?1 z=2FVHmnu5@ZLMFs=(4nU*k|+LOF*+N=-z-{RU~brN=MGQG6Gk;yUM^ zZ@u|f;jHhk@lUO{fs6ci(-|>ctvHjJVg1voK>Fu6mx^k3~~fv&pev{OJ0$<6xU*gY=JWhKIdh zizT{#@mMINIu{JVGMIk+05QfE9EX`=7-qaT2#E}9f0JFnd+nC96U*L+dIYIh`X&8N z*dRIk>`;TWaK}lmkn#*RJEoIX%eq4CMh~Q6j#`Jc7gnS$CU)52-qOd%9-axBAG%~WR~MBmU8?{ z^~DG+8x%h`N$UlN3#(=CQ`-N`al5gx@lYzNx@^JJjLHd@Aah`cM8BEw;zd-`lWYd( zy#|WebALYlL|Lw2Gw)WSi(%1H$WlE2w77C(4c&$w@`#%X^`DJxFKMrvU5W&Z$yl65 zcZPL|4t9vns*aDnKj8GOL0@!{^R_<3o=g@ z{PP*5misBk328uNw}Y( zK+&m{$VGw^U3g}=MrHWb(jD_uV@=j$DQnljOnx3fUCaUX`_{=Xe;9>l z-fUMH?2O*QhG)hF{yh`B27_s`k2~40WtpVk&oV(L1VX1GN`7S7oz{mOLjK~q^>&IJoR zMw=W0g^e=jkyYiFqcON@zswg{XGIzC2&zVHzpWx|o&q1sPcWw}i5m?ao&abI$_|u%zg}21pXZ`gpFxsRD6MA72ps zk_7T}al5atLbhHAVqy$>OP!)IWXrzH@BNS^N&&`49yV0DItv6PuN+1+ZrsD5nkHgM zr#~Fj2c}1qvHqqmzFAzeW3w zzb1U5Tfwj}g1k7Pa=ErT*9emrer-J=2SrT^?E8UVEn?A-}1?qVCmVaGe(9-7o*yr_40! z1PV5<<`+!=bYgjM?1MabstV{RSdxt)($>|7Z8P$7zfkz^2v8m^O z+t>S}iszAQw=vyPph5|NDm_{VkNe__0h0dSmi8~80UDX9kR4k0%w5_)sKqacTs$b6{j&-(g~mxT$u zB;K|tTv&ZMC^95)SfeAe|Jjvn9C;{QxN4WaFsrwS7$OCZ;E`FfyQpMm48d;nMLeh! z!qoTFU*CE`mK6uwL(l>Sa0}s00oA8l? zF9tmwhyz+lT*KVy&oxD52JG?4vG!nMdMFW|6*iI$WV&G&M8u1x#t6}b3a^;o^z?*a zAUpR4-I&V@7fU{~_F#i=sXW$iXaIWP-}@2Uu*R}AlqeDnOnKHHeQSjugM?!7M_#Gu zK41kdaXHqnd*Nc@G)%?FBXd^Wc$rCjZcL>(ui$}M26}I$%>81`eqI##n8b?Y_@@~ZvoGZB7v1eMU;8t==-}BX|(7bFoCcnZ%l}3$4#R{{?fUusN_;JzRRrE zMg1C{rP74$!Ua8Xe+TlrOsrrj`CViB0t)B{F>UP>$!(Y6M-(9`A|Aey0;in&Nwh|BT^SM*s`O0!*`;8|+6c%*uQ!ih=@J+?aNhORL^y>^{<3ph-cAld7T;$G3V9rkg4L_YJhS_YTCJJ1K(-SIX1_~_V2!svy+hxqNHC*cTbju zaGzD?TO7H)I!i*pYy&~4bw+MR-T4|wcQ|GUK6WYU6a~WJ_xcIDycXl-=O;xo3P?MB ztT~afxhtA(WxK#Q@Sx}f(8H0|(X9rcgehi!tNo~}ZfL78XM=g} z0VdRp_@GAc28O~CpR)IVO~6mDpn~qHmH*!EV|z(ZIaLIOMUS|Jj45G=-muOtJ=cTbJgGQ`*bG*U__K%nUw;|^ z80Kt%BnH&E9ouBuGnAA|C;V&DDWWKDDMKr7r;cIj`ZN0cn|#UHA5H03S+4DFp`J@WRar zC7Kljd(*RQ{9nI-<)-O8ar}H0dWU~yeo`wKXe%~%Z$H-p^$(Kij^oYQ$vdS(4`;Ky zaC4jI;y?dEGytvI^?KKsn7fhy!y^slE&#*M$S-$7Jm6or(Py7@dvZdU+vLw@uCvpB zSO8yD>VXpcrLb=ChyTd~AWqbpa^?_J@ikIzPG&F`_y-g{8~dJ;lEt1(<-KYwJu(lB zk+{mA{rB@n_rs?pF|syU)+zlpr}T4#%mc~&#q-Ar)Sc!{MKc(zMJ8?T1-`?^wrybE zgG0)fJ+`mn27VF${6e($fK$F{L&q`gzrLN`2Bq4j)`Dr0_5^?gboCGY__*e~RW`+O zl}O6Vi+qdJX2zC!v<0wNp0E(sVA0bPPnj({qn`{Z{u2gciTv{(8w=0g^-Dq={ELOW z-M#m*+dPcBP+Hr~uALLqo$Pf#Q7elJ@rSs3`n9d7azH-5Nn?gm|AIOB`ihWOmLcU{ zu25e;vMIgD>CW|Y?Z30kdZ>aS$;)db5w)Bt(KMhgX1j*3c4_H)1bTN?t%!nfCh^t_ zI~i2gLsMfMIua{UQP~s0U_5Mbt^166^GepbTac&D89na>NWDgSXK$o+mh0T()%>wz ze(;@PBsDjC#z*Y`#uEm!g4-|i4UXpQiI+~k>f^a}5}^UtZW9s+hT$>Lfk%UbvJtg|~Oq>5QbaKJc|cTD1p6Av43 z1iGBvH;v}aj5O(Q84oh(JibEZe%(NO!BWr2e>2><*V1Qw;mq$Wj&t|fX6Q_H0}AZ} zO>gh!LSvlV1u8Pbzq@`$QKysSn!LA>G;LS;{K`J=Alp>m9KFR-xcErobZ>N=Bh$nb$$hxTBm=x>52bY!uf=46(vQe)4@B*IY--Bwp{o_ z_@7q4;Eo9Gf+@E5o0N2j!Z|Jb0VFhsY7;AD_Ir8ke1OV0s=!2a9Z0?kUsG zXLVn++*r9;ST#9Zc&~G-&!54sp>+-5ecpQWOzcPF!p;GL8_7Cs`uNCx0aWMKDC$6i zkhI%a?Hn-2TxHbr@J5g}N~l&{-?^co$C|oikpWdaNcV-mJ*=Gdn&W4-M6X{>=FY{` zTCK_Bt%Dkiu>HRU-w;45^9}*G3=#=5$XOnA*P1~nrhM#u7-S{{Y0XKzXh6cDvM zg{VNdV1)2xudc}I-=|fOxFxd~;ut$HiclwW`$H$7aQeGREA_#}{{V#xs>|5M^YKa! z%sXG4IdRh{UKe^EB)b1W5xU{eFZl_B9p%Gd!zepZr6bP-a|t7$WxzGhea7DA;qqvy z9bK1HzEG~=Geo;WSVxU`dMSkmY|Z$exuNq(@`vs+Gb8!tLLE#K#j{keKfg$9_;(yK zol)USaC{y@)a{Y6v87iOY*hiL$=49*$dYF0g7I|B{l*VXyB~|!8OyNc3TJJ@)mF7t z@XmvmAPB&eh%(R_;2`4Fr(jk0M;MZdZ;-zM2C$aSMd62Laz!+ln(6R|!kJiTzZZWT z*3<`Bm?L<0%NYEN#(ZB%BLe=}u2s-=^;i#b0{^8l!pr9{FgaoHq*uI=*)MYi(L7HzipcKg9Gs8s+We6vI8GIxdAn2m zw6rIi>I{8S!~&SaNAm>gE#?-S{rm3^mJW?+vw6vm@$to7TIgr9`kKBtK4=7Gq>JcFkY?|q<2MjE`{Dg<(2{7`nK@ARi z0+KFLj5P-JkUN_nJ@zbn?LYs?MKT%!$hYSc0XzjNZ!73R36rl8FT3;~#H>4V&PXHFOyaJn`orX4x*a4 z4kivoAd?QDr3^?QQn$gppl*T+j$u-HE5)}Ga0Y@N846(Ib%1!Nvsl%yWRinSpqnHh z$|b0RiG+)}9x`=MQEDjMASX9H$0Y9bay5-XLCVQ4u{8{G6)nm&$VwrgtcL;wgEobq zCl(q49g+e>F4#{N9e5Rj<-vH8ECSjxf~6~+i7SBE2)(Xxrg( z7Pm*fSk%qlun0S!d6^VHT0DQ;t0*V6V%V=QyviE^jD&mfTuy#^3RSIkQcoBfM4?7P zzF_Pti2sF)eags&ny#tSp4IqZ>E|;vxMkVFSO01`qw93$<-h@^Wp>8ywXged zaQxEX^=upe`OYLOj{OXFXE}%(G@h}wsiWirO3$#MY+G;1tT^l35Gs#<$@3t-8E22l zxr9Rs*3i}|xM&;lAf7g|+Ol`fEm%e<9-vL8B876Hmk+F8LWc%I?q>p%c+uQMw{E*E zXAQ|76w-_QA?QrRDTq!=BD7f(7M-}cj7R&RCX4?YP$*C}<8Q)7IgEsz9B@=l$$&($G=x92pG&ck^T6OK zMEVWtmQV!b8Erg6QW8TqLKT45fNx-`e`LRnBqM({*BjTdU7!#r5>rcb*RXy<7*GzQ zJVc-Y!a4Xb7KeY!+w2uPtut-qmLFm9n z%pa9}&`w;CCC{y5dP0)An={!qITC0M(+((a6C11f4CGewYNEYhJau?FZN@<}{q zx{y4^w|H*RSHNF44spbaHa+@L%xkny<#W~C$-N6dl0txUMLGF* zZ)>3+DvKGm*jtbuX(k@%yU3j${S+PHHyCQU4!SlNIH+u%HiD$-?L>}p`G6x$Yo=m{ zZ^^l37R&L8@7ResDwpqPyhC#P%>+l(kvkdNa`4YtK?BYU|JhC2GE46$)HNjiUb~SJ zCyGRD8nL`sjK3Bxos~bj0-(*fpnz-nI)4<~Z@lH6O*8t>!ui_oJ^NyVFp6!Ypzd1t zZm;DDZ|PKg-_WVJc``VSigr_w$Rf67Vb+l3Qbu~;1f!^M^DXyuno(yzg^4h3Cdr67 zFJWlX^73qLY0<`D(6Zi6I@01R|4p>AigezAvu?_Dm7<`XNeJLpNh_@mi#a#bZ`ROM zFBIMw1Fa8>^V?ne3ShNwG#th$>3vDz(aA`uoO3uV&rbEy&o2}x!3km_dRPpMNak@c zN64(mqB|j-BrstZi%Y40a%?X|%R6v55uXgTvAJ{QntNxs&WdQ#RzSu?c95ht>_;(?&Troy9;#VEL7}k*EFjS> zlV@u14B;F%E>2K!Is{q)Iy+8(=y`YV+)3>7Z>ec9QvnYO|C7f+pez*8xI!!zroEeZ z0l+A{C^qole*cUBQcwVn0^_<+2c-cL;?X}y3_#@HsU0~DM_UXZi^f1^0!FU?WwC(M zO>(i?1e6pI;je(23l)%st(_1S9?901-i3UgxYNcssL>!2supz0W1904swc(atGM7LT>f+2Yf%9L^))n9 zwU&i=3Fz#5zT|t6>8D`&gdG~aSl%&(qB*u)fI{jRhpLx{BXPi|GTHuqYDr%ct8>+w zX9I6{?;zovRCCLPT#fJ=(_p;DO*f7zgN8aVGsD2COkNg(NOLMdsEQ)iyu%3^NUE2l zP5iK&tz_ZWp!9hhtgfl~7PH%!!(EnCWalDpOw-KFpF&sI#VS!t*P8VsKR>Ayg`{PY zLxGq_?*fe%JXU2n!|?Y0{cf*oSG)t8YLv;7zh?Dcsq4GO=ttYB-W`61S~I9#))MhZ ziw>Rb0-L7)St0>{Xv2zz7%QT%`}iOL$I(Q%Iq_tJc2#YiXaH{7kdo)6XrzqH0#&kaI2whunC1twLA^pregG`k1_+kyH zq%8xL>h6cZqFqoCFkL&nhhOdCaP$S+%CduR-3qCgo0*H8yrK_k;&s}E5yN9uSjbo8SuwX-iC{if) zUpYTF@UOKr{%H_2GpNe4grj!e3g4G?mdtsa8f-=pTgM-y1?_)#N2#sFRY38SG#VbJ z$}9s>Z~TVfVucEB#c(*(s~ZZ(Yn;NkWzH>(lqC{^DQsqU*^xINpPpW=eX%^3(nGrG zE=E$iSl$GDO5JriCdTd zIs>Rj2<;zJP}NI%L#vYSlzWjI>i$dt&C#zI+$Sy=5JpOf}5O8S}=}y>#tp z;>A4*wgl-m+*UDcbPKgm;R?LG<=1}ER-wnKR@l!7NxI>uF61k`^SjESs5Ycp3Cb<$qf}@ zslOf@#a|O~P!Sz(cN<^tnf^1bFSm8}8hi7OAO8L4Ugn8}45T=utOp+9bNoMAs-XQY zMuOtwdQfH&X7vhCMa`{Sz=lq4rXn}$eN-yLqXnEjw017JF_m06$G}^iR zRFB2ySyb#Cc4r^v!Na8Kn=Uzum`K_x8`HNj5sn|(h32Id>p9V!HrdH(u)+&0L_E}! zMj1APOzY;|7K~8x{`i0hH%)EG4uU_UmFWXABlN7(N>lFQG`Na;JcL|d@#u9|xBoT^ z+gZi@~#l9^z~IR#(`ktCAH^|w~aLP1Z%>qROpBx6QQZrpp4mAZWmbUbc{YVF+l zE^+%;`QL1iCdliroDs70bvCaq*mTG@La7uHhc@|=LfcKYxIFmfTTahN&iBjQoksgQ z*DQtKm;Jvc$c)hhCdPRp7C-~Leyf>W&o0@PBPoz(hY1AKiqQ=HpeQ6L0=l^c{(ute z&`7rNOdqN~3@&IZ&XXqITc4f{|GdUd3+U2GxGM+3DSu893!bVBxWNOlg6a02dn=Z% zGP;I-LY&K99Y_WbBR`n%jvE8gEJuiC`TU=9t4ec?8YYg<<1dIs8&PA9)f!C553(Gh6p(1QbnUXbpA zne0>*y1Ap!S3@vlo~GeBFa8TbFAHuPFc@?BdBNl_w>u8nB%&AmCx^4}knB!$H3n9fb-JzxwTkEb=`0j|!C45- zFqsRDtmCs|ujf4sIkr^NsU;xCZo!R^Hh+{|7IU6EE3%6bqdN;>&)DaF-#Bk?B8eI- zHT`Y6v(lW+V8xH&r2YpJ@Ak%<(sh-4tYwRMtyG;`2FrJouFKg2@B_U-u!@GH2%x;5 zZ+49Vg90_wESi+Bcuyh8i3D4yToghz%10(5bo%YC7KVYdJzT@%(>lSG8z5YVAb?1x}`^teX%&o5jHNf8oJslYTq zT$0D0w)CfFnCBt43lr7W5)ehzM}F_Y)3JkMrq*l*R}bX6ND6;?)-Cno%wYMoU>PYV zW~m@uqcw7*-FPx@6&hNR&f7&oB9id?#|OV}-6y`}<#rnoZ9fERM0f+Mq9l5B#hU|X z%`~kcVm(P`a8oYtO!q1*g0BBZtUiykH&ypmYD8D=GRrj3T9eat_o25JppqszlsvuP z`4uEfM5T?)^+>^!bdG*{W2}A&?0<>1Q@xDoX}nYcfs&-Mnnm2?I+}ZI;SpOi8tw~c z(WE5}Ei#v2Y~SJzmVI{n zTw1tE0nJTMuyx5Zk8@9urk&NlA^-t8mF;0C!U>Db6&c0bz6Kv<>sO~ zah|JBPE<)mXd9!AmpQ3BwA+9*A0kW?4o&2D8;ouZ!M60aksd7cd;^g&7lE#bBll3#K}(s*2r}Wvvhptz;vM55qCTKxYek@PkI*_&vXfy_KY-Kj7s&cfrI znMSQb)O;2jg<7WP%=_5KbC(vaXxlfcSN^xpj_cUxtNp&SlfZYAe7o#$tMe&a*b z2?3u-E_NXwK~*9%Z8TY;Nsv0}8r~VYi8zE-J+$$I0nS6$QBm@}>jd&*Mac4gM&mBu zLo7e(o?Xb8R?~;I$Ibb-#u<{0^YRWL1!N-GIFWKevxZ}wxe%ke*zEPsXz3o%LjR}F zolD9=%ZB5&228+YAG&4FfBf&!#sENyxm*kBHv7sYA?wiL_m7xMt9(U?QoI5a`k4ji ziE>)mW^T=Sef!o6Yk8|edE!DoeH`S)+=g6M@6U_&o9Ymy1nG*Q8igy=e3+9B>Gmia z%SPiZOhmoW0#{N|4$k_9-|P&8-WhaUEbx<@iumpTc9AwHhFymSvwVNAX5$h9@5YdY zdZNcw#joii_=KuCPUXFTrbl**=KYgCnx8}$u%Y1z5^`2X!!w4mqxT*F?8%|<0s_T zud&2fN(zyln4c`=n@Nr~L6wjefZaNnL7W$F*ar)*ORx=|&{E2BsFDjO-erYxV-)1F z1Ck@79>gHKp7Avw%`ssjnj6Qx?qTjk=8HaRvL){zG-|ZKnZu0+25j)@XdFgMjuL_& zm|>=#H@CPUvAHj2n7J73`G!(|ubh}W6dT=1IECJzuO)Y>f3)$&5YpK!%8>z#Q&;b^Y-*DpUtfnDn5V$RN8MMtq$%EnC19pi=Y=i)djiffY z?dJu7qzHpYw2{=R3Tq9a&iS43_1o(-EWKkszB(4bx77CYI=VJIbw*60!3n1-)G0?AR=-(K6 zN_4&u>w>H1)`4%k0udAd!lG01v}ST2k8+3F65+e(qbC|2$dwoApv{?FUjuiAuhCM- z6*4v0yvbBV8JxgD1O=8kod9Ych@x> zPJ<9+$g0&v**$gFFov3IuISg))I|CrCBjw3;l_@Tiw85$a*YbnfNfDINa!{wAmkVF z<$n?i!~xt?ApX>`spNi=decF3Bjpv6FFa2leS4Rd@bm<^LCZJW@v~>)?C0{1ljM>< zqVb@hX9!w^jw`m|8L!vwVifRTFp5RX>Y@nx1T!{w9h+~z8Y3Sz#K?N;K4?Qq`{dFk zxSN;A-B=bgHy^TZxSkf|88WX)hkr54#efqSY$6DAdZYd$ z6$1@@W(dQ%NGH}CQO^sx3;1`g5xU9k?4n^TwUS+R;q8KdZ8}<$V`~TOs3m1)VO?l0 zs`cnrK!}|f{kaXR@{j5)V&SHE&CHVMM5GVryzhat$2v0r>~@PswW01{)pvVW9!iM(~6TOORgb2QfT*Gje(%;GQPvF67ABJ4S0jCLaj~Rc=*aZ?l2Y+ zCax17BVRy^M+7nT%8XNOm{H@VjPKnBDDFJ_d`2+ve*Wb{0CeW`5`lTkL@YN5=4=o; zv{j?_-QI&++Ov|~n4xR(-jxd7=`E-JFLH_6De4_33*s6bv{n0Ay7g0!XBUfQ%p$(5qk~5}G%&QI8lg|8qH1qw8hJ)cW z+L$EKl<%d&Ql}Oiht~ULwhG~LadlVs3kF2r*!5J{Q#xzS$Id7lrWz-?55C)*F$Z&?FUEvqP6$`4F*b9l zQ9W+^_|-)bZu%=JZdSC7KDn3#;pgS|zB*)k9l$g8T#Gt@C zoTxxg9sYD#N#(@X`@GfvtDST4Y4Qrgc!9}93rL4DD9`|9YXt*XOV*}#jC(h^3?U-8 zVlfCZZku2WTSMK{ifiboI&dpkr3frANmyVMVT6|JDlLp{aau$xqFh@+%ALIjm;Db* z_78mD`M&R*@4WAGp67RCAJ@DbIH8+#IPy8J)knsG;hgouC{!t^`bYZ-l;}`hb*QI- z`~o`9Vaox~Sk>7eRdn;Dd&$!FTRj3VFNaK6OLsbr;Ykn25+z+==Sm1jVZb^8?R;6! zXSV}baf~-hz37b-eQ1={8+^4+KW}ZWp^P0$WWIr@m;2`a>1t3nI~j>$a7%l962FU- zPvC986;dF>eRfU_G)@#dMyEtq&%r=x^E1sfuF^8cwn(;f(SFIbAqD)yke}WKf|{r6 zA_fu(NjgQr=|38rKMBmL8*P24Bk-AP(~y(KKX;Y<1fE*JooW~hSkCw;qFqJ_l+_bPgWxMc(8LbayXm?wB-(MvH%CvU-G11TezN;53n( zfbP~yKQkWWUK+Zs&_JQ)Y$&vod&^US?C<=KoWe>>j$!3?BB+%2SA>9;QOv`@+yAy zYgaD=4h9`$r`?5J2z96PU|m}~w+r&K_(Y6!cZqhT;w0}`+az)t0JL^{EwO?iPA?&> z3xouoU`wT!;ueFfIC~I9p;2k4pZGJS7Jhk1mfljr40u5S1JaX*&5gq8iSk0vy?T|* zijMISP`n%h12a|AxgBBPLEWb34j_LV|2D`R3{i!BlEsihO>ahzS6-(eIZ6vq zN?`I3S*sEd6?5(y!`%TP%x*X;o-4C1-m#sqWn((sO8m*Lr$&L1yfM?<`Jhey0dn%! zW1WuYnKe(|)2qxZmTj~&mkGa_V};hi<`rgAT!|Kci90)p2W&LFCglH!@@83qFA310 z=>Km8ZW<7|#B7M+Y6Q{4q*jaMBL_ol432qm#O~8wEpxg;h!pYCpB+Zsg=3Tlgqo0p zJ0AlIe$RQMzR++}*uV3_a|^7fk7kv@F4ZiM4F~<*c%C@U5#Qd{Qu^g#h~)G-r-OVq zXuMA(7r=Cs*mVQeu7b&@{{|x{PvKvC-8k2(QlAFBtR@=@>YJQNtKEIckNq`fJ;rwr zDe^hvJDd>7x|BXeQijCUq{IAKw9N)vIy5ShzS}XAm0-JhF?da-{}huM;hAqOtalP$ zaT8yujEuzr9ow$?kYj2v#>aEW;RZ{8+jD;muhI};q1W9}V8XK7G^&XJO i`yYY+pCZMtzc=L8L0m93eht)p3@a=;^vB>6U;Yh)P{Zl~ diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png index 41279222155db204ff509001afff978525b6a811..fafa8fe0bb65f752e3c7b29d231208a8caddff4a 100644 GIT binary patch literal 25533 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 From a67eb194c15fb441139e716694d76807ec3ea4a0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 12 Dec 2021 11:26:45 +0100 Subject: [PATCH 0764/1892] doc: emphasize that the Configuration object is supposed to be used as a singleton --- src/igraph/__init__.py | 4 ++++ src/igraph/configuration.py | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 7f616ef1f..e4432f571 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -5289,4 +5289,8 @@ def write(graph, filename, *args, **kwds): config = init_configuration() +"""The main configuration object of igraph. Use this object to modify igraph's +behaviour, typically when used in interactive mode. +""" + del construct_graph_from_formula diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index e81a1dfa4..8e28835c3 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -88,6 +88,14 @@ def get_platform_image_viewer(): class Configuration: """Class representing igraph configuration details. + Note that there is one primary instance of this class, which is used by + igraph itself to retrieve configuration parameters when needed. You can + access this instance with the L{instance()} method. You I{may} construct + other instances by invoking the constructor directly, but these instances + will I{not} affect igraph's behaviour. If you are interested in configuring + igraph, use L{igraph.config} to get hold of the singleton instance and then + modify it. + General ideas ============= From 387b8c299b20a9532b3130760e840aed763dabc0 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 12 Dec 2021 23:36:00 +1100 Subject: [PATCH 0765/1892] Remove ax.set_aspect(1) from all scripts --- .../assets/bipartite_matching.py | 2 -- .../bipartite_matching/bipartite_matching.rst | 1 - .../assets/bipartite_matching_maxflow.py | 1 - .../bipartite_matching_maxflow.rst | 1 - .../erdos_renyi/assets/erdos_renyi.py | 4 ---- .../tutorials/erdos_renyi/erdos_renyi.rst | 4 ---- .../tutorials/quickstart/assets/quickstart.py | 7 +++---- .../quickstart/figures/social_network.png | Bin 28909 -> 65370 bytes .../tutorials/quickstart/quickstart.rst | 7 +++---- .../ring_animation/assets/ring_animation.py | 1 - 10 files changed, 6 insertions(+), 22 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py index c92c64800..d675d5dc7 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py @@ -29,8 +29,6 @@ vertex_color="lightblue", edge_width=[2.5 if e.target == matching.match_of(e.source) else 1.0 for e in g.es] ) -ax.set_aspect(1) - plt.show() # Matching is: diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index d2bd96527..9eb753699 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -52,7 +52,6 @@ And finally display the bipartite graph with matchings highlighted. vertex_color="lightblue", edge_width=[2.5 if e.target == matching.match_of(e.source) else 1.0 for e in g.es] ) - ax.set_aspect(1) plt.show() The received output is diff --git a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py index 6b7624dfb..c49327db9 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py +++ b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py @@ -42,5 +42,4 @@ vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] ) -ax.set_aspect(1) plt.show() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index a53a1b42a..78fd976fc 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -67,7 +67,6 @@ And finally, display the original flow graph nicely with the matchings added vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] ) - ax.set_aspect(1) plt.show() The received output is: diff --git a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py index b546d0dfd..1b8127965 100644 --- a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py +++ b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py @@ -26,14 +26,12 @@ layout="circle", vertex_color="lightblue" ) -axs[0].set_aspect(1) ig.plot( g2, target=axs[1], layout="circle", vertex_color="lightblue" ) -axs[1].set_aspect(1) plt.show() fig, axs = plt.subplots(1, 2, figsize=(10, 5)) @@ -44,7 +42,6 @@ vertex_color="lightblue", vertex_size=0.15 ) -axs[0].set_aspect(1) ig.plot( g4, target=axs[1], @@ -52,7 +49,6 @@ vertex_color="lightblue", vertex_size=0.15 ) -axs[1].set_aspect(1) plt.show() # IGRAPH U--- 15 18 -- diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index d4a451e5f..59e2ad0f1 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -43,14 +43,12 @@ We generate two graphs of each, so we can confirm that our graph generator is tr layout="circle", vertex_color="lightblue" ) - axs[0].set_aspect(1) ig.plot( g2, target=axs[1], layout="circle", vertex_color="lightblue" ) - axs[1].set_aspect(1) plt.show() fig, axs = plt.subplots(1, 2, figsize=(10, 5)) @@ -61,7 +59,6 @@ We generate two graphs of each, so we can confirm that our graph generator is tr vertex_color="lightblue", vertex_size=0.15 ) - axs[0].set_aspect(1) ig.plot( g4, target=axs[1], @@ -69,7 +66,6 @@ We generate two graphs of each, so we can confirm that our graph generator is tr vertex_color="lightblue", vertex_size=0.15 ) - axs[1].set_aspect(1) plt.show() The received output is: diff --git a/doc/source/tutorials/quickstart/assets/quickstart.py b/doc/source/tutorials/quickstart/assets/quickstart.py index 927e9046f..52edfab77 100644 --- a/doc/source/tutorials/quickstart/assets/quickstart.py +++ b/doc/source/tutorials/quickstart/assets/quickstart.py @@ -24,15 +24,14 @@ target=ax, layout="circle", # print nodes in a circular layout vertex_size=0.1, - vertex_color=["lightblue" if gender == "M" else "pink" for gender in g.vs["gender"]], - vertex_frame_width=2.0, + vertex_color=["steelblue" if gender == "M" else "salmon" for gender in g.vs["gender"]], + vertex_frame_width=4.0, vertex_frame_color="white", vertex_label=g.vs["name"], vertex_label_size=7.0, edge_width=[2 if married else 1 for married in g.es["married"]], - edge_color=["#F00" if married else "#000" for married in g.es["married"]], + edge_color=["#7142cf" if married else "#AAA" for married in g.es["married"]] ) -ax.set_aspect(1) plt.show() diff --git a/doc/source/tutorials/quickstart/figures/social_network.png b/doc/source/tutorials/quickstart/figures/social_network.png index c9e901addd02eda2199681acfa788d27008c97ea..f528c450abd21668dbea3e4a1e7d2eef2e1e39db 100644 GIT binary patch literal 65370 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%0Ao@8SF>iJ!=AXDhWCGOBDQO)#uM=_9nE0PW_j? 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
  • pHIR53IAi*J;V6W35P~R} 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 diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 74ba5c7e9..7237998aa 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -43,15 +43,14 @@ Check out our in-depth tutorial TODO LINK and our gallery TODO LINK for more. target=ax, layout="circle", # print nodes in a circular layout vertex_size=0.1, - vertex_color=["lightblue" if gender == "M" else "pink" for gender in g.vs["gender"]], - vertex_frame_width=2.0, + vertex_color=["steelblue" if gender == "M" else "salmon" for gender in g.vs["gender"]], + vertex_frame_width=4.0, vertex_frame_color="white", vertex_label=g.vs["name"], vertex_label_size=7.0, edge_width=[2 if married else 1 for married in g.es["married"]], - edge_color=["#F00" if married else "#000" for married in g.es["married"]], + edge_color=["#7142cf" if married else "#AAA" for married in g.es["married"]] ) - ax.set_aspect(1) plt.show() diff --git a/doc/source/tutorials/ring_animation/assets/ring_animation.py b/doc/source/tutorials/ring_animation/assets/ring_animation.py index 02e028ec5..55d080643 100644 --- a/doc/source/tutorials/ring_animation/assets/ring_animation.py +++ b/doc/source/tutorials/ring_animation/assets/ring_animation.py @@ -9,7 +9,6 @@ # Create canvas fig, ax = plt.subplots() -ax.set_aspect(1) # Prepare interactive backend for autoupdate plt.ion() From bd82befc11adf2f67ff4f64e34cb1236ba00a4db Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 12 Dec 2021 23:45:38 +1100 Subject: [PATCH 0766/1892] Fix figure captions --- .../bipartite_matching_maxflow.rst | 2 +- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 16 +++++++--------- doc/source/tutorials/quickstart/quickstart.rst | 1 + 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 78fd976fc..c8aed55f5 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -8,7 +8,7 @@ Maximum Bipartite Matching by Maximum Flow This example presents how to visualise bipartite matching using maximum flow. -.. note:: :meth:`maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching<>`_. +.. note:: :meth:`maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching <>`_. .. TODO: add link to Maximum Bipartite Matching diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 59e2ad0f1..e5c3132df 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -6,7 +6,7 @@ Erdős-Rényi Graph ================= -This example demonstrates how to generate `Erdős-Rényi Graphs`_. There are two variants of graphs: +This example demonstrates how to generate `Erdős-Rényi Graphs `_. There are two variants of graphs: - :meth:`Erdos_Renyi(n, m)` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. - :meth:`Erdos_Renyi(n, p)` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. @@ -78,18 +78,16 @@ The received output is: IGRAPH U--- 20 35 -- .. figure:: ./figures/erdos_renyi_p.png + :alt: The visual representation of a randomly generated Erdos Renyi graph + :align: center - :alt: The visual representation of a randomly generated Erdos Renyi graph - :align: center - - Erdos Renyi random graphs with probability ``p`` = 0.2 + Erdos Renyi random graphs with probability ``p`` = 0.2 .. figure:: ./figures/erdos_renyi_m.png + :alt: The second visual representation of a randomly generated Erdos Renyi graph + :align: center - :alt: The second visual representation of a randomly generated Erdos Renyi graph - :align: center - - Erdos Renyi random graphs with ``m`` = 35 edges + Erdos Renyi random graphs with ``m`` = 35 edges .. note:: diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 7237998aa..7b3256ce8 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -69,4 +69,5 @@ The output of the code is pictured below .. figure:: ./figures/social_network.png :alt: The visual representation of a small friendship group :align: center + The Output Graph From a1d1eb78c5d0888df3fa39ec82971f4e65e3c0f1 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 12 Dec 2021 23:56:21 +1100 Subject: [PATCH 0767/1892] Fix gallery links --- doc/source/gallery.rst | 2 +- .../tutorials/bipartite_matching/bipartite_matching.rst | 4 ++-- .../bipartite_matching_maxflow.rst | 4 ++-- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 4 ++-- doc/source/tutorials/maxflow/maxflow.rst | 4 ++-- doc/source/tutorials/quickstart/quickstart.rst | 6 +++--- doc/source/tutorials/shortest_paths/shortest_paths.rst | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 517727fdc..69fff1990 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -1,6 +1,6 @@ .. include:: include/global.rst -.. gallery +.. _gallery: ======== Gallery diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 9eb753699..b421189a8 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-bipartite-matching +.. _tutorials-bipartite-matching: ========================== Maximum Bipartite Matching diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index c8aed55f5..11abe3029 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-bipartite-matching-maxflow +.. _tutorials-bipartite-matching-maxflow: ========================================== Maximum Bipartite Matching by Maximum Flow diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index e5c3132df..f702da660 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-random +.. _tutorials-random: ================= Erdős-Rényi Graph diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index 5a078f296..d7371b196 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-maxflow +.. _tutorials-maxflow: ============ Maximum Flow diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 7b3256ce8..56b926b22 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-quickstart +.. _tutorials-quickstart: =========== Quick Start @@ -69,5 +69,5 @@ The output of the code is pictured below .. figure:: ./figures/social_network.png :alt: The visual representation of a small friendship group :align: center - + The Output Graph diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index c7623fc0c..4f8f14700 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -1,6 +1,6 @@ -.. include:: include/global.rst +.. include:: ../../include/global.rst -.. tutorials-shortest-paths +.. _tutorials-shortest-paths: ============== Shortest Paths From 3109fe451aba0270367bbb29cd526b62d4011e85 Mon Sep 17 00:00:00 2001 From: h5jam Date: Sun, 12 Dec 2021 22:30:43 +0900 Subject: [PATCH 0768/1892] doc: fix topological_sort.rst --- .../tutorials/topological_sort/topological_sort.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index 09e92fc2e..bbe53eecf 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -6,7 +6,10 @@ Topological Sort ================ -To get a topological sort of directed acyclic graph(DAG), we can use :meth:`topological_sortng`. +This example demonstrates how to get a topological sorting list on a directed acyclic graph (DAG). +Topological sort of a directed graph is a linear ordering based on the precedence implied by the directed edges and it exists iff the graph doesn't have any directed cycle. + +We can use :meth:`topological_sortng` to get a topological ordering. .. code-block:: python @@ -25,7 +28,7 @@ To get a topological sort of directed acyclic graph(DAG), we can use :meth:`topo results = g.topological_sorting(mode='in') # results = [5, 3, 1, 4, 2, 0] print('Topological sort of graph g on 'in' mode:', *results) -There are two modes of :meth:`topological_sorting`. Default mode is 'out', it starts a topological sorting from the node with indegree 0. The other mode is 'in', it starts a topological sorting from the node that has maximum indegree. +There are two modes of :meth:topological_sorting. 'out' is the default mode which start from a node with indegree equal to 0. The other mode is 'in', and it similarly starts from a node with outdegree equal to 0. The output of the code above is: @@ -35,7 +38,7 @@ The output of the code above is: Topological sort of graph g on 'in' mode: 5 3 1 4 2 0 -For finding indegree of each node, we can use :meth:`indegree()`. +We can use :meth:`indegree()` to find the indegree of the node. .. code-block:: python @@ -64,4 +67,5 @@ For finding indegree of each node, we can use :meth:`indegree()`. The graph `g` -- Note that :meth:`topological_sorting` returns a list of vertice ID paths and we can set two modes. +- :meth:`topological_sorting` returns a list of node IDs. +- We can set two modes as a parameter. From 3fc0f22b5605da8eaf237d812cd9b2a7ef6a54cc Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Mon, 13 Dec 2021 00:36:41 +1100 Subject: [PATCH 0769/1892] Add links to external sites --- doc/source/gallery.rst | 1 + .../bipartite_matching/bipartite_matching.rst | 5 ++++- .../bipartite_matching_maxflow.rst | 11 +++++++---- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 10 +++++++--- doc/source/tutorials/maxflow/maxflow.rst | 5 ++++- .../tutorials/ring_animation/ring_animation.rst | 9 ++++++--- .../tutorials/shortest_paths/shortest_paths.rst | 11 ++++++++--- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 69fff1990..f3782f6ea 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -12,5 +12,6 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-bipartite-matching` - :ref:`tutorials-bipartite-matching-maxflow` - :ref:`tutorials-random` + - :ref:`tutorials-ring-animation` - :ref:`tutorials-maxflow` - :ref:`tutorials-shortest-paths` diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index b421189a8..eaf28f320 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -6,7 +6,10 @@ Maximum Bipartite Matching ========================== -This example demonstrates an efficient way to find and visualise a maximum biparite matching. First construct a bipartite graph +.. _maximum_bipartite_matching: https://igraph.org/python/doc/api/igraph.Graph.html#maximum_bipartite_matching +.. |maximum_bipartite_matching| replace:: :meth:`maximum_bipartite_matching` + +This example demonstrates an efficient way to find and visualise a maximum biparite matching using |maximum_bipartite_matching|_. First construct a bipartite graph .. code-block:: python diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 11abe3029..83ed53426 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -6,11 +6,14 @@ Maximum Bipartite Matching by Maximum Flow ========================================== -This example presents how to visualise bipartite matching using maximum flow. +.. _maximum_bipartite_matching: https://igraph.org/python/doc/api/igraph.Graph.html#maximum_bipartite_matching +.. |maximum_bipartite_matching| replace:: :meth:`maximum_bipartite_matching` +.. _maxflow: https://igraph.org/python/doc/api/igraph.Graph.html#maxflow +.. |maxflow| replace:: :meth:`maxflow` -.. note:: :meth:`maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching <>`_. +This example presents how to visualise bipartite matching using maximum flow (see |maxflow|_). -.. TODO: add link to Maximum Bipartite Matching +.. note:: |maximum_bipartite_matching|_ is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out :ref:`tutorials-bipartite-matching`. .. code-block:: python @@ -35,7 +38,7 @@ This example presents how to visualise bipartite matching using maximum flow. flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1.0 print("Size of maximum matching (maxflow) is:", flow.value) -Let's compare the output against :meth:`maximum_bipartite_matching` +Let's compare the output against |maximum_bipartite_matching|_ .. code-block:: python diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index f702da660..64b31c4e0 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -6,10 +6,14 @@ Erdős-Rényi Graph ================= -This example demonstrates how to generate `Erdős-Rényi Graphs `_. There are two variants of graphs: +.. _Erdos_Renyi: https://igraph.org/python/doc/api/igraph.Graph.html#Erdos_Renyi +.. |Erdos_Renyi| replace:: :meth:`Erdos_Renyi` -- :meth:`Erdos_Renyi(n, m)` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. -- :meth:`Erdos_Renyi(n, p)` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. + +This example demonstrates how to generate `Erdős-Rényi Graphs `_ using |Erdos_Renyi|_. There are two variants of graphs: + +- ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. +- ``Erdos_Renyi(n, p)`` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. We generate two graphs of each, so we can confirm that our graph generator is truly random. diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index d7371b196..7e8b999e1 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -6,7 +6,10 @@ Maximum Flow ============ -This example shows how to construct a max flow on a directed graph with edge capacities. +.. _maxflow: https://igraph.org/python/doc/api/igraph.Graph.html#maxflow +.. |maxflow| replace:: :meth:`maxflow` + +This example shows how to construct a max flow on a directed graph with edge capacities using |maxflow|_. .. code-block:: python diff --git a/doc/source/tutorials/ring_animation/ring_animation.rst b/doc/source/tutorials/ring_animation/ring_animation.rst index 9add9a945..8fbe53cc5 100644 --- a/doc/source/tutorials/ring_animation/ring_animation.rst +++ b/doc/source/tutorials/ring_animation/ring_animation.rst @@ -1,12 +1,12 @@ .. include:: ../../include/global.rst -.. tutorials-ring-animation +.. _tutorials-ring-animation: ==================== Ring Graph Animation ==================== -This example demonstrates how to use Matplotlib's `animation features `_ in order to animate a ring graph sequentially being revealed. +This example demonstrates how to use `Matplotlib's animation features `_ in order to animate a ring graph sequentially being revealed. .. code-block:: python @@ -53,6 +53,9 @@ The received output is: :caption: Sequentially animated ring graph. +.. _induced_subgraph: https://igraph.org/python/api/latest/igraph._igraph.GraphBase.html#induced_subgraph +.. |induced_subgraph| replace:: :meth:`induced_subgraph` + .. note:: - We use *igraph*'s :meth:`Graph.subgraph()` (a.k.a `Graph.induced_subgraph()``_) in order to obtain a section of the ring graph at a time for each frame. + We use *igraph*'s :meth:`Graph.subgraph()` (see |induced_subgraph|_) in order to obtain a section of the ring graph at a time for each frame. diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 4f8f14700..28a75253f 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -6,9 +6,14 @@ Shortest Paths ============== +.. _get_shortest_paths: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#get_shortest_paths +.. |get_shortest_paths| replace:: :meth:`get_shortest_paths` +.. _get_all_shortest_paths: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#get_all_shortest_paths +.. |get_all_shortest_paths| replace:: :meth:`get_all_shortest_paths` + This example will demonstrate how to find the shortest distance between two vertices on a weighted and unweighted graph. -To find the shortest path or distance between two nodes, we can use :meth:`get_shortest_paths()`. If we're only interested in counting the unweighted distance, then +To find the shortest path or distance between two nodes, we can use |get_shortest_paths|_. If we're only interested in counting the unweighted distance, then we can do the following: .. code-block:: python @@ -67,8 +72,8 @@ The output of these these two shortest paths are: .. note:: - - :meth:`get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. - - If you're interested in finding *all* shortest paths, take a look at :meth:`get_all_shortest_paths`. + - |get_shortest_paths|_ returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. + - If you're interested in finding *all* shortest paths, take a look at |get_all_shortest_paths|_. From 30b4c6955309b80e2bb0f8fa868a9dc9765546aa Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Mon, 13 Dec 2021 00:38:31 +1100 Subject: [PATCH 0770/1892] Make tutorial captions more consistent I.e. capitalise all captions --- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 4 ++-- doc/source/tutorials/maxflow/maxflow.rst | 2 +- doc/source/tutorials/ring_animation/ring_animation.rst | 4 ++-- doc/source/tutorials/shortest_paths/shortest_paths.rst | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 64b31c4e0..f980f7ee9 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -85,13 +85,13 @@ The received output is: :alt: The visual representation of a randomly generated Erdos Renyi graph :align: center - Erdos Renyi random graphs with probability ``p`` = 0.2 + Erdos Renyi Random Graphs With Probability ``p`` = 0.2 .. figure:: ./figures/erdos_renyi_m.png :alt: The second visual representation of a randomly generated Erdos Renyi graph :align: center - Erdos Renyi random graphs with ``m`` = 35 edges + Erdos Renyi Random Graphs With Number of Edges ``m`` = 35 .. note:: diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index 7e8b999e1..0e93ec577 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -41,4 +41,4 @@ The received output is: :alt: A visual representation of the flow graph :align: center - The flow graph + The Flow Graph diff --git a/doc/source/tutorials/ring_animation/ring_animation.rst b/doc/source/tutorials/ring_animation/ring_animation.rst index 8fbe53cc5..455913572 100644 --- a/doc/source/tutorials/ring_animation/ring_animation.rst +++ b/doc/source/tutorials/ring_animation/ring_animation.rst @@ -47,10 +47,10 @@ This example demonstrates how to use `Matplotlib's animation features Date: Mon, 13 Dec 2021 00:43:38 +1100 Subject: [PATCH 0771/1892] Fix shortest_path.rst figure aspect ratio --- .../tutorials/quickstart/quickstart.rst | 2 +- .../shortest_paths/figures/shortest_path.png | Bin 30009 -> 27685 bytes .../shortest_paths/shortest_paths.rst | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 56b926b22..384f68b87 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -13,7 +13,7 @@ For the eager folks out there, this intro will give you a quick overview of the - Save the plot as an image - Export and import a graph as a ``.gml`` file -Check out our in-depth tutorial TODO LINK and our gallery TODO LINK for more. +To find out more features that |igraph| has to offer, check out the :ref:`gallery`! .. code-block:: python diff --git a/doc/source/tutorials/shortest_paths/figures/shortest_path.png b/doc/source/tutorials/shortest_paths/figures/shortest_path.png index b48156a38a4b5aa190729a4cfef443bc940b9924..7c77c04e0cecda3ffc3d1b06626701efffed84b5 100644 GIT binary patch literal 27685 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 N?AO%Oc&ug}@GtrOV|f4o literal 30009 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 Date: Sun, 12 Dec 2021 22:46:05 +0900 Subject: [PATCH 0772/1892] doc: fix topological_sort.rst and codes --- .../assets/topological_sort.py | 11 +++++---- .../topological_sort/topological_sort.rst | 24 +++++++++---------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/source/tutorials/topological_sort/assets/topological_sort.py b/doc/source/tutorials/topological_sort/assets/topological_sort.py index 02b384b5e..eebc7de3a 100644 --- a/doc/source/tutorials/topological_sort/assets/topological_sort.py +++ b/doc/source/tutorials/topological_sort/assets/topological_sort.py @@ -1,17 +1,18 @@ import igraph as ig -# generate directed acyclic graph +# generate a directed acyclic graph (DAG) g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], directed=True) assert g.is_dag -# topological sorting +# g.topological_sorting() returns a list of node IDs. +# If the given graph is not DAG, the error will occur. results = g.topological_sorting(mode='out') -print('Topological sorting result (out):', *results) +print('Topological sort of graph g (out):', *results) results = g.topological_sorting(mode='in') -print('Topological sorting result (in):', *results) +print('Topological sort of graph g (in):', *results) -# print indegree of each node +# g.vs[i].indegree() returns the indegree of the node (which is g.vs[i]). for i in range(g.vcount()): print('degree of {}: {}'.format(i, g.vs[i].indegree())) \ No newline at end of file diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index bbe53eecf..8c69edbd8 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -15,18 +15,18 @@ We can use :meth:`topological_sortng` to get a topological ordering. import igraph as ig - # generate directed acyclic graph(DAG) + # generate a directed acyclic graph (DAG) g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], directed=True) assert g.is_dag - - # g.topological_sorting() returns a list of vertex ID paths. - # If the given graph is not DAG, error will be returned. - results = g.topological_sorting(mode='out') # results = [0, 1, 2, 4, 3, 5] - print('Topological sort of graph g on 'out' mode:', *results) - results = g.topological_sorting(mode='in') # results = [5, 3, 1, 4, 2, 0] - print('Topological sort of graph g on 'in' mode:', *results) + # g.topological_sorting() returns a list of node IDs + # If the given graph is not DAG, the error will occur. + results = g.topological_sorting(mode='out') + print('Topological sort of graph g (out):', *results) + + results = g.topological_sorting(mode='in') + print('Topological sort of graph g (in):', *results) There are two modes of :meth:topological_sorting. 'out' is the default mode which start from a node with indegree equal to 0. The other mode is 'in', and it similarly starts from a node with outdegree equal to 0. @@ -34,8 +34,8 @@ The output of the code above is: .. code-block:: - Topological sort of graph g on 'out' mode: 0 1 2 4 3 5 - Topological sort of graph g on 'in' mode: 5 3 1 4 2 0 + Topological sort of graph g (out): 0 1 2 4 3 5 + Topological sort of graph g (in): 5 3 1 4 2 0 We can use :meth:`indegree()` to find the indegree of the node. @@ -44,11 +44,11 @@ We can use :meth:`indegree()` to find the indegree of the node. import igraph as ig - # generate directed acyclic graph(DAG) + # generate directed acyclic graph (DAG) g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], directed=True) - # g.vs[i].indegree() returns the indegree of each vertex(which is g.vs[i]). + # g.vs[i].indegree() returns the indegree of the node (which is g.vs[i]). for i in range(g.vcount()): print('degree of {}: {}'.format(i, g.vs[i].indegree())) From 3a17830763951f21c99bfa6c4c88bc4cd759de77 Mon Sep 17 00:00:00 2001 From: h5jam Date: Sun, 12 Dec 2021 23:14:54 +0900 Subject: [PATCH 0773/1892] chore: ignore .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 44657c996..5495ecd24 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ result_images/ .vscode/ vendor/build/ vendor/install/ +.DS_Store From 036c1eafd1f354a9cb25325845b5df65d3de4ce0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 13 Dec 2021 08:00:29 +1100 Subject: [PATCH 0774/1892] fix: Edge labels --- src/igraph/drawing/baseclasses.py | 6 ++++-- src/igraph/drawing/cairo/graph.py | 2 +- src/igraph/drawing/matplotlib/graph.py | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index da1042085..4051fc432 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -150,9 +150,11 @@ def get_label_position(self, edge, src_vertex, dest_vertex): angle = None # Determine the midpoint - if edge['curved']: + if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge['curved']) + aux1, aux2 = get_bezier_control_points_for_curved_edge( + x1, y1, x2, y2, edge.curved, + ) pos = bezier_cubic(x1, y1, *aux1, *aux2, x2, y2, 0.5) else: pos = ( diff --git a/src/igraph/drawing/cairo/graph.py b/src/igraph/drawing/cairo/graph.py index 44bbef880..191701786 100644 --- a/src/igraph/drawing/cairo/graph.py +++ b/src/igraph/drawing/cairo/graph.py @@ -400,7 +400,7 @@ def draw(self, graph, *args, **kwds): src, dest = edge.tuple src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] (x, y), (halign, valign) = edge_drawer.get_label_position( - edge, src_vertex, dest_vertex + visual_edge, src_vertex, dest_vertex ) # Measure the text diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 28c2eb8a4..5037e4f2d 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -290,7 +290,7 @@ def draw(self, graph, *args, **kwds): src, dest = edge.tuple src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] (x, y), (halign, valign) = edge_drawer.get_label_position( - edge, + visual_edge, src_vertex, dest_vertex, ) @@ -301,8 +301,8 @@ def draw(self, graph, *args, **kwds): label, fontsize=visual_edge.label_size, color=visual_edge.label_color, - ha=halign, - va=valign, + ha=halign.value, + va=valign.value, # TODO: offset, etc. ) From bcaa869a29573b9e0b23070c265b297ac76bed37 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 13 Dec 2021 08:17:52 +1100 Subject: [PATCH 0775/1892] fix: plot multigraphs in Cairo and mpl --- src/igraph/drawing/baseclasses.py | 3 ++- src/igraph/drawing/cairo/edge.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index 4051fc432..720404ac9 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -6,6 +6,7 @@ from math import atan2, pi from .text import TextAlignment +from .utils import get_bezier_control_points_for_curved_edge, evaluate_cubic_bezier ##################################################################### @@ -155,7 +156,7 @@ def get_label_position(self, edge, src_vertex, dest_vertex): aux1, aux2 = get_bezier_control_points_for_curved_edge( x1, y1, x2, y2, edge.curved, ) - pos = bezier_cubic(x1, y1, *aux1, *aux2, x2, y2, 0.5) + pos = evaluate_cubic_bezier(x1, y1, *aux1, *aux2, x2, y2, 0.5) else: pos = ( (src_vertex.position[0] + dest_vertex.position[0]) / 2.0, diff --git a/src/igraph/drawing/cairo/edge.py b/src/igraph/drawing/cairo/edge.py index 78de321fa..bf07ed316 100644 --- a/src/igraph/drawing/cairo/edge.py +++ b/src/igraph/drawing/cairo/edge.py @@ -104,7 +104,9 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge['curved']) + aux1, aux2 = get_bezier_control_points_for_curved_edge( + x1, y1, x2, y2, edge.curved, + ) ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], *dest_vertex.position) else: ctx.line_to(*dest_vertex.position) From e3fc166028b995856553023bda618758d963e803 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 13 Dec 2021 13:11:37 +0100 Subject: [PATCH 0776/1892] doc: added information in the documentation about the MSVC redistributables --- doc/source/install.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 665339bf7..56137e69d 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -73,6 +73,11 @@ Precompiled Windows wheels for |igraph|'s Python interface are available on the `_ (see `Installing igraph from the Python Package Index`_). +.. TIP:: If you get DLL import errors while trying to import |igraph|, the most common reason + is that you do not have the Visual C++ Redistributable library installed on your machine. + Python's own installer is supposed to install it, but in case it was not installed on + your system, you can `download it from Microsoft`_. + Graph plotting in |igraph| is implemented using a third-party package called `Cairo `_. If you want to create publication-quality plots in |igraph| on Windows, you must also install Cairo and its Python bindings. The Cairo project does not @@ -90,7 +95,7 @@ After running the installer, you can launch Python again and check if it worked: >>> ig.plot(g) If PyCairo was successfully installed, this will display a Petersen graph. - + |igraph| on macOS ----------------- From 8a4a6d5dfcee0d84ce41b3a84d0368a1c91dd0f3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 16 Dec 2021 07:55:52 +1100 Subject: [PATCH 0777/1892] Extend mkdoc.sh to make tutorials, fix TOC and some hyperlinks --- doc/source/gallery.rst | 13 +++++++ doc/source/index.rst | 7 ---- .../tutorials/erdos_renyi/erdos_renyi.rst | 2 +- scripts/mkdoc.sh | 39 +++++++++++++++++-- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index f3782f6ea..483092ace 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -15,3 +15,16 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-ring-animation` - :ref:`tutorials-maxflow` - :ref:`tutorials-shortest-paths` + + +.. toctree:: + :maxdepth: 2 + :hidden: + + tutorials/quickstart/quickstart + tutorials/bipartite_matching/bipartite_matching + tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow + tutorials/erdos_renyi/erdos_renyi + tutorials/maxflow/maxflow + tutorials/ring_animation/ring_animation + tutorials/shortest_paths/shortest_paths diff --git a/doc/source/index.rst b/doc/source/index.rst index e2295739c..145bc4c82 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -16,13 +16,6 @@ Contents: install tutorial gallery - tutorials/quickstart/quickstart - tutorials/bipartite_matching/bipartite_matching - tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow - tutorials/erdos_renyi/erdos_renyi - tutorials/maxflow/maxflow - tutorials/ring_animation/ring_animation - tutorials/shortest_paths/shortest_paths generation analysis visualisation diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index f980f7ee9..116551bf3 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -6,7 +6,7 @@ Erdős-Rényi Graph ================= -.. _Erdos_Renyi: https://igraph.org/python/doc/api/igraph.Graph.html#Erdos_Renyi +.. _Erdos_Renyi: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#Erdos_Renyi .. |Erdos_Renyi| replace:: :meth:`Erdos_Renyi` diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 3c64a5ad1..984fed38b 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -2,22 +2,55 @@ # # Creates the API documentation for igraph's Python interface using PyDoctor # -# Usage: ./mkdoc.sh +# Usage: ./mkdoc.sh (makes API docs) +# ./mkdoc.sh -t (makes tutorials) + + +DOC_TYYPE=api + +while getopts ":t::" OPTION; do + case $OPTION in + t) + DOC_TYPE=tutorial + ;; + \?) + echo "Usage: $0 [-t]" + ;; + esac +done + SCRIPTS_FOLDER=`dirname $0` cd ${SCRIPTS_FOLDER}/.. ROOT_FOLDER=`pwd` +DOC_SOURCE_FOLDER=${ROOT_FOLDER}/doc/source DOC_API_FOLDER=${ROOT_FOLDER}/doc/api +DOC_TUTORIAL_FOLDER=${ROOT_FOLDER}/doc/tutorial cd ${ROOT_FOLDER} +# Create a virtual environment if [ ! -d ".venv" ]; then - # Create a virtual environment for pydoctor python3 -m venv .venv - .venv/bin/pip install -U pydoctor wheel fi +# Make tutorial only if requested +if [ ${DOC_TYPE}=="tutorial" ]; then + + # Install pydoctor into the venv + .venv/bin/pip install sphinx sphinxbootstrap4theme + + # Make sphinx tutorials + .venv/bin/python -m sphinx.cmd.build ${DOC_SOURCE_FOLDER} ${DOC_TUTORIAL_FOLDER} + exit $? +fi + +echo "shouldnt be here" +exit 0 + +# Install pydoctor into the venv +.venv/bin/pip install -U pydoctor wheel PYDOCTOR=.venv/bin/pydoctor if [ ! -f ${PYDOCTOR} ]; then echo "PyDoctor not installed in the virtualenv of the project, exiting..." From 514613a90fbfd872238e4d5e33a55aa947168f77 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 16 Dec 2021 08:17:59 +1100 Subject: [PATCH 0778/1892] Visualize_cliques tutorial --- doc/source/gallery.rst | 2 + .../tutorials/maxflow/assets/maxflow.py | 1 - .../assets/visualize_cliques.py | 21 ++++ .../assets/visualize_cliques_with_edges.py | 30 ++++++ .../visualize_cliques/figures/cliques.png | Bin 0 -> 99882 bytes .../figures/cliques_with_edges.png | Bin 0 -> 106100 bytes .../visualize_cliques/visualize_cliques.rst | 91 ++++++++++++++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py create mode 100644 doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py create mode 100644 doc/source/tutorials/visualize_cliques/figures/cliques.png create mode 100644 doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png create mode 100644 doc/source/tutorials/visualize_cliques/visualize_cliques.rst diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 483092ace..16cb26f8c 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -15,6 +15,7 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-ring-animation` - :ref:`tutorials-maxflow` - :ref:`tutorials-shortest-paths` + - :ref:`tutorials-cliques` .. toctree:: @@ -28,3 +29,4 @@ This page contains short examples showcasing the functionality of |igraph|: tutorials/maxflow/maxflow tutorials/ring_animation/ring_animation tutorials/shortest_paths/shortest_paths + tutorials/visualize_cliques/visualize_cliques diff --git a/doc/source/tutorials/maxflow/assets/maxflow.py b/doc/source/tutorials/maxflow/assets/maxflow.py index 643e135b7..b28b81bfc 100644 --- a/doc/source/tutorials/maxflow/assets/maxflow.py +++ b/doc/source/tutorials/maxflow/assets/maxflow.py @@ -22,7 +22,6 @@ vertex_label=range(g.vcount()), vertex_color="lightblue" ) -ax.set_aspect(1) plt.show() # Output: diff --git a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py new file mode 100644 index 000000000..cd8cdf6c9 --- /dev/null +++ b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py @@ -0,0 +1,21 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph.Famous('Zachary') + +# Compute cliques +cliques = g.cliques(4, 4) + +# Plot each clique highlighted in a separate axes +fig, axs = plt.subplots(3, 4) +axs = axs.ravel() +for clique, ax in zip(cliques, axs): + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, palette=ig.RainbowPalette(), + edge_width=0.5, + target=ax, + ) + +plt.axis('off') +plt.show() diff --git a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py new file mode 100644 index 000000000..faf3b9f11 --- /dev/null +++ b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py @@ -0,0 +1,30 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph.Famous('Zachary') +cliques = g.cliques(4, 4) + +fig, axs = plt.subplots(3, 4) +axs = axs.ravel() +for clique, ax in zip(cliques, axs): + # Color vertices yellow/red based on whether they are in this clique + g.vs['color'] = 'yellow' + g.vs[clique]['color'] = 'red' + + # Color edges black/red based on whether they are in this clique + # also increase thickness of clique edges + clique_edges = g.es.select(_within=clique) + g.es['color'] = 'black' + clique_edges['color'] = 'red' + g.es['width'] = 0.3 + clique_edges['width'] = 1 + + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, + palette=ig.RainbowPalette(), + target=ax, + ) + +plt.axis('off') +plt.show() diff --git a/doc/source/tutorials/visualize_cliques/figures/cliques.png b/doc/source/tutorials/visualize_cliques/figures/cliques.png new file mode 100644 index 0000000000000000000000000000000000000000..a6e9d626f172f8347c0454974c1148cb2cbddbbd GIT binary patch literal 99882 zcmeEu_dk_?{P(eyvO{JzDI|MSR&lHlGD221*?S~}jIuK$J0W|7NOs8Hd+)vO*ZF+E zkNZ!!f4YD8JU-!^>s;r$UhmiIx!zZZ3R3Rob;|1q1mdQG{9`o)0^JvZK%2(JhTrh@ zjnBjXgq&oaJE_~6I=Q@bc!f}U>11bR>ttnNbjSIXgQJD5%|lLJ&WHEzm^(SyISO-e zS^wV`aN0VUadm!v+ye)>W+$)hh(Hj$ME!^MRU*d%frdaRJeGRqn!KL!CjQ0Xgzr=d z&B%ndOGmY>G;#8DQP3^)UPZf@?leH%?pwL-LB9&;4_NU0^FKw8tJdy5qJhy{EEuodH znCJLTXh#^<*4CtCWSgUJ6`b#`u(LmljC9N;e38{}zi=?*xRm0uxoWE5%pfr3`S1vi z85z`ku95lD+EX;sfswm-d3`-AEzLI-@vBkUFHYY*L>(#gioC+A=dmS%xrVf60>4qA zktiubh&n>=A8mWL9IoHQjA002GJm!7<{pqK3o@<)d_X_)zHbc+TZb>EZLN zYtO$wy-h)3XlUr`bGer~zp!9G6GU#rp9Ftq5+Q1sQhxLZW9?sIW@%|mX}9oG8}!B7 z(zrT0Iuuk?b6?{0jZ(c1XZHJ*^>wV<uituC z=jm|KIy*Zpbm$~c{kj>g_^J4ltP}sS`X}Qp;*=&_G5&t=ZSMnmnn`f!tKPOxsJB4v z80z%4E&g8aIq{p?%E`}v-M#E{`=V;;Vcdy?{|f?VT9{Gmc0X>M4ii_+jqN4eUp97} zrx@M~nfDz3bYgJow>i@J>N4`ql7C9DXFroj?1;bkkH?$GhgLsWmolj_JouAxPUDr< z7!&BMKJVFc&cFEIbAVf!5FZ~;v|qx^bL!ahN*BJA!%%}6$%8A~`-8#z7!#!l9LvT} z|9itr*J#_10+X%*P?dgVWxPo76O+S94_oaOLymS)@;>x?6lD-S0Uwc2n+N|-&Ra|x#SPQmHQmjvo!bZRR_i9 zIupL@>6VY#MQgb38#F}K@s`E7+fvH;Zd`*&6tZn@h8vmVm~`N^KrviuZfmXcsHiaOo18?d z>r(Z+Z5{|}cD?YP^trmQ)@LQZ5)0G1Jm5m&{0nMM#;83l_Oafhv^X6rJ>G66uy?Do zx)JO~Pn}&?la!sEjao&f05s4W%~HKuf8x;o77rueJKyW^$@G|CTIwgq-+Mj%pzzav zEGZ==uC zV~I~rPJY>oT}c*v(wyZeV@%DIBcASSH-%8MwoKO{^t zzD#GQKlOZ`YGP?2&VcMTJ3GTaBcdUFk3w@RD^g^Ry3?CC{~a+qo8^JHIA_z$x8vOo zE*WjrsCWDcEzAnSr=*XPvE+drGA zZ!v$`XlQVSp%pk`L;mQ|ql}^=q}6z(>i*FYUc(eut$wlKS?5EU_apc6{``6D<#mC- zoG`zpqN>K=@J8643|CV0V!wZCS=?pZKKPr?Jq9r$ZPDZDfQ+0RxnV2*zR}UU|B4N` zM#sj2nr8?@Gv1kfc9YFwWep1)er|ttapcn>7Tt*gn?_xUeCUMvlEVUZ+mT|2@uzhe zY_sXXw8S~d4xyDZZ>gT4*>LjPjI)u-5Y5;<9~c@6`}tFfK9CT8xP?vUef$#bU56C) zmpOC?g_fx84@b;w9Rs*|co?v; zu>%R!n?SA!hrO9Hk=kxr(Y56D^i%&v!d! z%leTd66Z4ngC|~`qobpN9Sg*89bsO=(&U7z5t@NpGlBX`%UW>*=e|y%AXW=jQtQO( zV7?1n1nKL(#PlsKErF=JzW{$#$s}@5L8ep&5za=*(GvLzn#7nckC*mLu3qprXsVL- zjgQ}RcX!WD+3S5oa80sOsS^qpyoK8mK5K zi9_t|GgNX&ehH_%3kxB-xVUhfd~I$nf8*xO+*DQ;mX^0SsUF`UREa#f@J4%gCKV`f zpI1xo&0xezvPsP`G=d<_Orl_4w!fA#?hfDWs$Q%fk$?87=e8`L{h+k94*l`l;F+~J zIc9)V$;)PJsCn^?WIWDF$!BX$(r7yzgbz&jD#qB`hfGy9KK|}qX}OlS8l9 zQkUQTfB!Ow(ng+ERa9u97N?zH0j+M8!$NE?PKHnalqWO- zXT>F^yMI??rKP3Ow`#A%@gjt;H%sBzUttg^J{>rj^w_fZm2D1g>>&+0n)LRl*(&Ta zXXE5#p~ml@oGd!^qPA}#iVv5~dn4RExWcCM&9|wk$+pTYy12QnBW^E~qu9i*;i7VW zx8vmUsG-=q!u!IVW!+i-TCf`e5Icw|tIr9tlP1jfn zuLu1|;6i?%`~Bz7>=i#2#&vpF`fXPHB;@3%_a55CcldFY>HH-oQIMC9-_tMc!h*p@ zaRYmGZ7uif*G9|o-QlUL?!6v~$PBh*&)xR1PMW(XWW(jx<=Zzy$2R`!Q0Xf2u66qM zJ2K=U@3WXndS-uRWM&%Y582opjzrJQyo6!LidxJGgpA_SJh+BOQmUk?1_oR#tgJAH zYPXy4GPt>v=S@vRB?wY=CN^cl5uDijjxu&dmOvhoNM$@ zFS?kyoECiYBI^UpIx&9xc3`08q5 zK;+y>U9O_Er)OvOH4_5^1Dy%gUvhGA@&})IdY%_d;RHziE6{#~MB?Xb6=ydzq|QZ% zL}X+ztgf!I-Mbe{={xc6^Jm&Jo%^sL8V5vZX=s$BrJIsRQw_Q0b#QE53Ze zO6qz$Vzqd2G{q_*ks5;(4uL5KCj?|vBugT?II?XHg{JfJ?gA5naSY`J2ALh{D zpsK3sgQXWU4pq+^yv1Z>WNJ@W^Wg>E!fW^7u3K1HW##2Pu?%n_{EMT)!wQ|FrM2~M ze?Nxe$uEh z5qv(78(sl{eA6o6I+m8Jyb?wC6S~$*g=iy#v$B|MYG<&!1?O%Q)tp*>S}!Mu+XhQI zmqogLQwlBzb&iYg#{N;LkYYu)HTU)sJ|*W`tj;f9j8#X@EGF5q zJbV~q$o(4%rec!3U7*>hr%Be-$Wxcly6!YTNLnqeIaiF?8&;nb;c`dQFp)}!Qh zo9Qk;a1>YiUwq>HwRRAlnyL(iSwK-9fFc|DCa+%2?41DTR42b$U$;6vJ+1G%Sa%jd zz#TL-w|bAHcO`Q@t2;8cwq_O+qoHrn48m*g{$;{b0wggpDXDM836ux8fVXLBKlj@@ zz7A_3^al**;OOXfd9qY>E1uMUS<;vFv#bBtuWZ-x@GLAXqrKB>u0aC>istU&0dO@> zmW7}HQ+s>6cJat3gdjJ!q>c_Hhi1VYUEE~p?T6FpIJAhguV3G#r>7TQCy!2fYGlL! zjc)(&5SS)_I3U-#PyCC+rnbx+9HRUBRH6Is34bFp-&mgq^1;l>83Fe~SVRQ1IJ5uz z-j6d}aj>y*gPWl?h)GE71*r{mACYJu@9piC=oBJquX%o7Ig>AYDJ6vlf{S2Ew`~b) z^i|;Tu`4k#F@SGXmwjkNFuJ?kFaMEU0iTA>$(^A1IH{`uYZ7~XW}EjX10SCTR2m~x z$*Whd%F4>VQu!5HpjGf=qx&JCb-*1mF4svgw7fB3$@^IM9$ZLR8&FVX<>f@Un9f#9 zOk+x#nq>OL9O`oixjK%YShRoT3>hvvz6KdsC3QBFS* z71dMF4B}omTywz~LSORP@*pKA@BjN(`VL_l$VJe~b4iasMZuS^c^4YWz{(n&o=#6H zLr+hSmeViv2v0DsSk`2wr?ZoZ5VyCl?STP2Nd|s$YjgJEoO8Cv2 zaK|5T^R^_IeO6FXx(V$zoJt^%69;aE$QPezYZBG#kNMGAVy*@J{5FA}n8B9E2NNeT zG4U8ycOw85=+&Y-^D)n!J^S$aGZH2Z3| zwr9(9WCH72Nl6JBElN_fYpg$0Q`hfKy*gh?>DO*gW@2Gs2sAV|$F0*>_Vg5m+tA;g z&;=5U0AXa?BRM%7SVk1#vd~2|hCax**vrUZ85%bh5j!uA%X({^_UfJ~_IL-<+E}@@U%)zA%TxPnR?GHZjtN)*evY09gyD zk-WTo!b^1$P)6D5Jhy*VOqE=rgLHU&JQoRrxu%T9z3y{M%VQ0Zq>mo~ z`CXN{sH?`_c7!{ljw=Nt114?%-Eb>~7R*{`{@HF`jeza}&|g78!SQo(pSiq}(wFM$ z#L-b5@14EW7=43C(+hW`=w_u}J?EtWBUa-?GVns**(Paxv3->%VWB8K?xL*=$4*yy z2XK~KNGPPsG$|cxTy2jrP^H`luw&MjFI@>#HcxM0V?a%tEIXakRI;Nq6OTA9ZxJdO zmFXRy?5F*3plX|YY^yEeegJ+q=A~@!?92j`5F1MhU@RNjE;SC(m2$;c7f9oP3&uXK zsb=;O;$p@-30JABy87iRyl#GbQzXr-M&M}5M*`X~HC)^TdKc9oaiiyIB&p&?f z-+lU2X#T?^HqN`VCrX3D&deae=c(Nh5O7JV_obnsAtfd49U98fLHmJ|f)rSAyoafb zal~<*vseo|^a4j7%}!uxX~;l1e5yzIPRGXLzpIl}y?>v6`=j{O{rg|?^YLQZ1KZ|Q zF))54@8jU$fRbtoy&kX}Or;+uE--I^Zh~YH)zl=7-TX2F+veZO^XJ+^Tf~?Wdz}wG z>rHRkqBS5ktIuqppq;fn7{YvD{X;*1$;R{Wp;;L_k3Iul!=NSLz2NWPzZYiX_~qL3 zK6oGn&4x2Bte}jyXkbN9F%vEP?Zx4kZSaAu3lqf+hl%o`U5xCEMGs+N*W;OB7dW!9 zB=9RWHEDPwEWrLUU)^r3sBl9^$36Z+1W~O%m!6&;>Qoc!4revO-)G+ z8T;-LgXWbg`OHG}e$mmZpWvv7_;a zTX}&n$9W}%KU9vC=*ci$kxSaxa6;3|%FgD2%LTHvaEi_7NlHqJiK*#dSV1x}zus># z;?je613-Rm$Ms!gq}fk@ENDlQ2366iQ%)qv-~jTXN~6hZzM&a}nxwM{lsN9;rWLm_ zqA-8Lj9_ABegGg|M`yIG>J9@TsOiy(iPah$l6MFVO-up-V!oGUgpxy<5TGZ;#K-^6 z`^Zt{xuUjNITt}Q*)tKY!WI~n`+yLyM&|qeyBaxw0Wi%`WjQe+mPz@nW}^ONe$X%esM$h)>c)pQ%uO1O+yNFdF?Iw5&rL_<2K#u z%3{A{$o1vrRk*pz0Hju{HW`S9F*wNn)0!| z{?yA@96C=z-+`9L`d)iVpkZ(6{Uwu8H8(d;1J)q+Z*1(TAT>B0C3Z8?*f=;L05aIw zLts`D)6j&snPDgF(-7IV`V&d3Z6&4Q?cP z5|JQ!6j*2Oa%QtqFcmh?ZTupiQ&ji~_~z&=XYeq*b{>RS;C29SfA{pnah*`((o@jT zEL?o#&;}tM=4>)(zW`!Yo}&ZHA3lWrLAfTU(oQIbNo- z@!qfimqbd>Z)i*&bd(*u7^PFB>`PAE7N#z|MfjcISu zS{o{L-q1lrh#fu$ZGfGNi}mhZ%bW^!9`eVSlBFYxun3_ATI#tJYUW$MK?C0|r%=zP zA_p3b+_Fe;OXuLph2&(ACdulIU)T#$b z%BViCa$v@xb)7B~0@!Hz`t>zTbPyI`HbBn-!%tmbA73#XwY))!&083mH2iQ9O6Y%j z>h9p+FpzgUJUkp)0f;rg0#nqR>zh?bS0_DVDuL!jh*O4!4iv+pyA3x6=rNQ)d6xOB zSInlRw;QHbk_u{6+17@0%`o`GXt;&4{|VrD!Oir5 zr+=LutjWm91>4n3h_;zO3^laq z9!+u}cAgR*StXKQ9wj@r3{%!{Cawy!;|!d*PI0k#}C@I;zpB64p1yLCpor zVe1YjW_rKnFYuS3oZ_e&Z6$qt8oggL=l&*2b#T0t5>4Ou{V@ChM*%>}WC z32<$%A5zlLyfQJtgi7fUv0;t!%m?A^VSU)~6WMe7o7fm1KYj#+!6PbK`)G`BrwI>{ z+&%CD(d+$J;XR1n`-fv?KYkG32pXmmq~w0h3pXFU?tp-RVXGf{l)pF=q}|6hjRFY) zTjK~);~$Q`<^nTmm7|my6d?et@Iy5lkUVJ6Al5Mfe*}tV+YnV)n2b42Nu%_+EkFyG zO!JxDetPh1-%2mywv5a(QgX*WJR}k&%KCMp61N0UmWK$>4uZpC$FFo zLa87`C7T&#$Srt(Fm%vT!*TZ(Ir$bh-57W|zF-Z$H7O*k$=I$_M@nV(K?QJA+&~#A zqL)Jr(KAlO*bzdf<}k(K*On)Ok!=BlDCO-9?YoeWk!iWKQ3Q zsMwZz*3a);%yGZuqKsbDhZeb=Sr_3L-6KN^&S3IV-oy?-tC{GA;SD1irtak>AwvD)fJ`#jWf80ml^V{I+Pyn&(=x}VbFFnHGg-GeCv*Vbx-Bum1=sCAb!E-5_C)ZDcf=J28)s0HH@#FpY?%(GX;OiS2 z{1rt0qH&Uhq%ze#)KAxjzPv1Uf8PldHaMNQj-auP)&+-|qcaUZ!@Us6{6Un4Ff(j? zVz}@GUPB;p&JFZ>rDCi>uMr@!;-pjIzU|+ftWXJ)zOv2R2Gw??W7% zoMLBYW@yNiZsTGe4;FhvD>57T{>sG6Eat-pU;Sb^RZ@_ssRV4Y;NpjdUO$}j@d3iR z0-9S+KPUyk?IzNyq+lcqvO`tiaH^69HRFrN4^4VHE(zCe z8N#cAX`KjP|0~3p{>m6J9bPdxnwK`#-~UKavGe_%G|4-X#>R{w?x@Hs@*NLs`r~=psEk`z?rNV0jESev$u39@p{ZG7J|Jk}xzl zM1E-yQewmx3hbWLpEWjig9w+qqX`!}Edwt;#7;?x=YBgY$`x?)20^Z{ zFdY0Pi?(0c$sVB@fM2#Zu(ig0Bwo1C7%PjnuSAMAWkeHOl5sNei6mXmzvZG!)w*cf ziWKxyu0OpFJl*?jqYVWQWi!(&D#*cO0F@kc4Lia2V;h=77^ywMgy=Etyw+m9YX`XW zm5_Wm*)zCAZ`6=DyM4rIz!@M{Pp^g;4}vihos`rerkJ2aj^X3EOkXtoB)mgDcA_Z= z&&-oGFs-hRCg3Nqw9SfLwc`u#*3Fto`>-HG8LTcbvE+}b1k&4a<*(WAaj~`;z5F}( zGOIBBJdu(Y1LOUvCllC?Z@Pu-Cf#lrxX^%*2s&ZRr%(Ku*3!5dcfg~~liUX9)^Ul( zW&6gq@OGJISeMOI=57m(hAVLn(jYuuN|yY*W6QbLLVbX7NN^DfEDWJ(PE1Tp z=~&{vdPt&whp^G6q7+yMC{^GTK(qmrt$``v-%%j1foX)&J4HmO@&`k~1K=T$m4TuX zcs&N8t7^i^7o7e-??8{iAQ1H3BMqAKbL69>b={WoKA)qzYV#V?bA@P{Am{)mh-HK~ zqCl_aQynzs?$=OdAi9)lN~27XY7M}d4~2z8Cv4i5_FnQQ<>uuzZ5^RtH!OD0L_jKp znodYgZZYR2zIE%1?A>5#dT{@kBI#|3t33(NlhyolKI%m+ zo%@%e*Z*x`mzOjs%^DdU7mallHeL$Tb#3|RY|st983}$cis(#TT^?0YZKGB2e0iYv-K5=TyyD~? zFWQzg10|&hcWW%`#_!*_V4SVu3-a?jCq8+RKM2vaofFT84oeoil(523!T|t-nzcfk zke(%=g71NV1MqK8NqOe%q+;+w(TXjQz`WmF(5<-6b)~e&a7G#&m$ulr{+qE`*}Lsa zsp_gKl3O3OqK}4+P0lZmKm&Wg&D{w30Psl}goNC5+=Rk@flr%Yy66RD>VaiBbrIWp zg!0|%;;FWg#E1iI3~xiyZS990sX$~E&`f-=Fpmjx%qKx zE`faD2gw081HW2N+;qi;7ra zsDcIp=ib%T1vCPH{==?y@>{oLo;@4j{b>k*}4MuQdR-5YT?%EjX4ED8;}|ap@tirs8!g;3rB92ZDuK0A0!XgO(xT;VJw-f(SvD zQM(ny=-a??J)b6`cp_(lrcOUHEZ3e86Lfg!%`GN8xyE;lXhJ@G_|P~%pOqNzK5TT@HW#5i+h06xCn>3m5D2+7&B0*QL zUyKUf_85Kf?O_yUqh6}}XgBxCQTuhRv>5SzpDiB}oPEcLi;2EU0j)5w z`Q^TQT{R&zFKdlQ^Lr=emX@QNfqme1zybke3MdL3fV=~5M)1}8CMLqcsumGR0*RG9 zc*{`b7BQ$zPe0vz32+x+%`c;uMn?X#v$GaHwm?(g3YkBJ+X%Hf?%r{~_WTcrxnD~l z=Dz|xk>;DT4GCbK?zB-i*U)()8VNY-;~UNoiu3q80RlJ)Yq*5Gv*!Caj*XfR(3Y&y_-GQi7<>yQD*2z*<>NuJ_#U}Q6~vgT9f0nb253fImd zD+?$c1Xu9WOKsK}nr1z=>e?c~fQ7+@*lf7+_CD=T^=@XZ_t*uwelLLT93i9nyZ!g{ zT#q=TfB<=FPfi3{#aQ9#AY2mgH!0}oataEpy3f4z{;NRfCp$a#&~ZUpg3r!uSo+K! zmqu8(J&Nm|pRDA3|IjG#__}Wm8Y~f$iRw4W zZi@+ymaq8*qGbOpfO`%C&$Ih|pG2DBv;ZoDBV2nt8wP=wJus(KytEmRCy-qR463o5 zbhwKZV8}Cb`HSlqAe_QYZ0*F@K=c7LZ9jyMLHYG?+2$yi_-$6%#9ud7r8E1!35unh zw#w!ONI4A|NE9lAz%eI39tho^%DK*Q>(<)i8ACjgdnPyTTp;` zd4C`B*2MV15IniV%>3$KOKoVz_Mnyl(G6_vYA1Hc833@zu=@MwZm6`A6EDok`NhR( zaNi);4ZayDWgn80MVk%o?|K{^p)}X8|A-GyJYkV%3|eY`GeiR{;{yX2C5Zi1VBLu7 zo`P=&#nwMI)}d{dQa&i08+CIQLTQQSLf@s{V-8yBd*uKUf}R4>AoxCLV234p9gaX` zJrFhI;p_)JzGP)}Cd9jd`v32rW?p{2f}&!}+QDClTSE`Uz`%f2$oHq>`}b%NY9N$z zEl3(tj6Ia|iwEv2o13z@Qt&cBeG`}w5fK2JP*yvn)Qv$BffnZ2LL}!IrtEW+4#S~G z;wrfrUqrDmuar3{NuJSB3S>dve5n>&PXCUD48VV2L49^xyp7{WZn z8!RM@4QDhbuUMC7&tkR<=p2}R~IP94c34z8R;>> z2hcyHJv>CfXBZQUUjto`lT(vsi_sg>frNliI5C0xQ9JZXnWLkPhc>+orfxEz^SDtn z0V$bez2&hReg9ggHMAZ$jl6O~A{{(+D6_w^QTi%QPrO-s9-E>R{i`W;s9>h{;?Vf7 z2?IODd?8oE{OrY%*?9xs0RC@mBs+vvT_ z%YX08hk1B-p50IHUjfSmsv}2c__NdbjwhIpEvrs}nHjDZT>{|gfKZa3SYN1N46+e8 z#xn=*?Z1ED;o?#*oJdSaXa}Z+N~7@deq}L+A^{9uRz_N=DUy%P=0E&wm-G9}kjMO6 z3fY$%uTW@8OUpLylgFNKT2~?VXQgr@0rKltJCQzi;8T(m5Axi`cf5eD8Y^GoW*w@4 zC7>LS;o)JSD;q&-&};GFB4x1M)2oh!@Q#<47%H~#?b;UBcYS=G74r zf_~rCi?EJ>)DF-HfE0q%EI{k`_xHt~%r%HXuTSqYU-U%k{v8=n06UQ^>{Y%dM)6Pw z+Sz*Z_VgX}-|bxskT1Uj*QS4EKxwqV(boF@zySA7@1wF?w{{kB=b*vR zb~6p3@beCV*D1Rkr%s?$PV?!0|9cvH%&=||f*zK_{TF>*M0l!?&&>IgU=jKikdj?-^p(@#5oUU$$`-%f|%j=jPT(8wt zONdzf(6O5UYhkMY(XbJ{5OwRT(w7mT85r`I=lD3thSb?uQsT_a5uZMW%W`)v*t}&mf1)qCQ2`9=rMm9et;$k+cIb)aT=zsZhoHi5daajc&KJ#NzT&; zT+*GL9blB8)*?ZZ1`junP!n?6XLMdIbbfwz6m?TQp|?2L?%vG+7q+0FK!|nd-Qicb z=3x41j4e9}-=?O{s;rFP+_c%<+Z)8XBly zmX>$nnt=&mQ%)KOdz60s_*7XbIH;`tUtocajja*3RDAf5c4|v`1N(oHX~tISpCx_4 zrH3CEJ2fc!XcHA#Af+-OnRe1Tq(=ai1f~ij1UsR#@9yrxMgb7N-_Fh&9i(_IeAHUr z+%o%^v7MXI`)?4XtU@v{EhEDpPEtrr@>sujgBi#d+!5`Dhm_&ahfp&nmrab`72Wj~_woS@gKol8z{XPz+tOrOT6?A7 zE&(zCvGn)W2J=$tRSOYSSlf)DZ?2v`_P2~5pJMX!20WNr+8jM)uzap&@j^+1V&f_P zonEk=ZOF}JM*i&|7PRJxG$#dR8+bql^zhwX2Z&aH*#D)Z#C|l4PJ#Se4)KFF>*C(b zLCe0i159+k+fyq}!hn+C9Y%c_G7z_&M101i4wd%yzAUJhygF;R>Huu%I4~2u2eP=D zu5K9A!T0aPz^^s)Wpesan;W#XZ^O0ciJp(mtcTfWxNmZ37Md!XU zMyf@5)|Z@~yd99#=Z=jdU#(=wjQd<&K>+kD(V7>Wn zfO1kj1ovR1Y)lWK&>i5EwbWp3wtjE*1-GM|trnX;EM%=x2Eku~b zwb7mLZ&>k*Jgk7; zPBJkNDF3uMhwZr{i(t|4gjZdU}1qV=QbBE07>~f!2d`<<9{ud zf5oE6(m$j#yr^?70LEKr8|3|5GBYaC1$P2Tj%NsbAUOr8id4GuX`HMgUAZkeI{T&v zZKwnz7~+)S*fkSHi{u>a>=1zgtzDvvt_Ru;up0;g!-xhw7*59g^=lNHhJ=y^#=Jun zT*GG5QrNgB1Kwlx14vY%nxmdx_|O_^zCrQWFModpMH?NJ_y_jX{FvxjX$UFiK-lQt zHhq15I@G{Y_w56ouU{bMz5^M5-1t0w9)E(Hq$7%1%jJU%`yQ<`2R>Vl*l%mgSsumG~_>pvIQpN2Lm z_05IlPgiB}9RH#K|u61yZHU7iU?n=^lj#RO4qE*1S3o!>7G=WKn>l2)^(hKA&1Wm|bSq(EXbnlKMLW=y-_o3P%ob%@667IXRc`f_aKbC9Pa zL*leNqV)yT-|l%B*DhpYO6z}U4q{tJfV&G@z6@Z?D~3G8aO&Loz?n>TYPv=`KfgWK z!D$R?GGxZUi={lFq9;DN2~Z?*Y=edL`VM6BcUN*!LARm=1p(##fC&d5(LIc5gThXb zVuK8cV;A3$T~vl0qaB=nsl&pb4R6gWrN=TdU3n9!VE}S8#_IXHC9XWdusm7Lj66Ol z_7PhXGVnUMg@f?H@ut96*D_GY#vBz%Eu1`MQwE2Ue>Agm3rxpCbB=-3OlU$<(@jIaP{)B5ZxKybU@_R>uP z0+g)U^}v(=P;46Ud41FLg{te*%$d<<{JD*asl^#(iG?TA0Y#iBT@xv~ufifqOSVxb z;DwFBlAY{RCrPSab%U=_Dkv!V>TGIn;B_(D2a}TR-U%1=2mEivIg#Pp*Mp>C#sG5% zns{;bd+D9ebXN1vYtnYt?1GVPy}i9dK8;sckZR!;7e_vM^2a&ls>kOt2Cqkg&WHQA z#ncIYkJ#1u`#Z2DI}mVBTAF0|VT#i9D6}42+@B?q!ALoz-lV= z=iAMIQoc=jpFv_>{>hW3wSzoyUD&SG_0)_f0aRCNkNGG;{_r~3eE6v!DH1*~@Qkk~ zE`!bS^3qRI@|Go(|L;EYW3=8vHc>&IT{^L~iI49N%{*>XQqFevBQxu(65bCy)A!ix z(q?S;aCiUR(b2qh)T15D2jk~&leEp|>gG@3x*n&sfa!uVMuMxG`&@on*;ExHpQ zU)Ydfn8)IVZzr(6U0qQV`rFjbBY+Ne4bg7a?jaF2H5>dk^(TwBm%s(o;AkihUj(tg zLy4>Y_wB|SVVaJ6WbUhLRV&Q|LNU3?Uz9~pn9Ne`(CtG)Fnz^UhA_}5j*r|`5)=PC zrSs{0B{21#0aG^o?bMVjC8xb^4uAXPd8ujmU4*HrDJ&1jk-~-LYlw%sa|tj@eM2T7enj2S zzgB_=tpJa!(s#~ZDgv{}bA_4K=X~e(;si(_gAz}Rhvp94 z%?5u^JN%}m@mY5LH+fv$KcUwG^6 z!n^)>7VqG519+DqJ7*T?HfWdUzZp@HALu6_v%rpNNFtp^%b?$YT7dZhRE6*EaVSU8 z^l+R3i+Zsc6Y1YYjprwt?V)I81H-Gl~ecxMUA*JIxVkMi?57gD*Yk8JBNO$3WV2r%se8*JXuy!~m z^rP@*o$Mo7BZgoa=V1ZQKQ*Y7E?CmqB%-z;xchXcxJ=7di17tI2Y&kUTDhWj~s0l>R&iB?G&vyjT(fD@iIu_Joe#=c> z$y;&+{7loK;;dii@jmG=*!`j3W5?EF3_KxKbkz->O9B;ZWCR-baM52S(2yU$E`O26 zM&TESj)vM^!^U=plM_GSXCt^1@PLLf4fNkjd-hXaN4ef22szm2-+*!0Z*Go#$aViq zLsddz!M!K^NxY=|3S5okT*2cKCY*5upVfocV!AGqQOb^O^FUvG80C;zj{Xt6C$|4C0H!lJ#s_VSqMWPF&u&D#I zXw{&BcX%BTyo11*mH;LZ-Jn!L-F{^^*z^uDtQQXL%wvW3uWT8k)g3*6E@4fJHe!t96c{vo2Dh5;_|J+H%1g5( zWkfS6wV?14r;|7v=>eHPMfgKp8(J9IOThh&D!Akyh{)RrV6PNpD8BR8z#i36(x7-d z3U$Hv5)@e$=I;!-->GM&>*9|4j+irvJtPVE)zrb&(0MTQBA{dKRq?9jr1#ZDVNn3+ zpgrttY=$85Q#W>1Igb~8e5M{NDo-9P|5cl@j3g@I~xrOi8*(bL* zj>iRQ1Tg!+2LwP2`Zp636U3T>;r7-mfwVXwLC ze4E5#>7+g(iUCnm;obfi6StSe*P%5rV>c*pA~9apMEzX#`RBN#StE-$Z} zjKDtAhzvXKZN}^j<)eA5i?!bWvXp(ASVr-u6A^;z+z{1gG%C{}&5Y7W^+AGgfgg+! z*_QdKD-6>CC?h<9;NfeA1$q2>xX=gB?+{MIjdh>A+Dwg4T(p`%M+FGu3)w(lGi zDY?F96sT2`u5&lN_cQ72MYz$%JDx@KgBM?X)q5z(AVgd7tEB}K1@)QytChJJD~w#U@o>m9j=f(EVwZYAjlVb3Mz?pmRt%e+1Yuth#0FQ3 zyj)!&=^FOaF#glCQkY+Wnk>p+S@TnA=D$hYUUIIv{W*C)^k{OfS4;n;wJ~Gr{=VHR zSxi*Nmf0H@fqWbs_OQsM-dQ6a{_>ede{`~Ennv!+^iP^zR_-CGlcHna-U@2=RrlrK zql5@Vlp;~zrIkK`3qSZ7Cv(jNd$6$`_Q5x0$b=1GHUT7negyeNP+!58hX)|!YQ{k3 z*b*sl?830vMNUPJ2|gyZ>$D%WT_YOYE7WE=QQ98f87{S@^5SBGuwT+ZdjYKHEuI8K zN|*wOhYWReY-|fWcL#=YPP0^f#x~6~mdwilYK*(kNycuCz-AK^<0!0{Li35*h(HQ*W?Cd;iCkQDcus@0D=#-tD%JOz-C@54Wuoxci3SI)`UCb}8hka=u zVfx+nSIA0~V`BG$0CJw5`*D<<;OuWk)V2x8z(WZ^5-ag^^;tG=;87DlM&crga7qL` zZD=s-SQ=MWR@QYc#pQX45f(&*j3dP~3v+1|NT)!pQB=GE;|WaWbhhg-=ixyy1)BM% z0xN_a19Cq|9 z&F9_aJvi9z7O8b}EmRsbX(1t@Rm@_xP#rPJoPLlsprx&v#gG1^3YQ&RVw@#`b{pPhnpsx%tgsr= zt*F$m(coQ{qN=wIdR~0AaQvrFPmoGo&(MdXh%{Z^5ZwsYj*pY`G-V0Wxo^{GTslKb z*|c^v_q&TZy(nV&RmV3ghhsj<@MMR-3blu=R1~m1sz9^;MTJdd-o|MvYI{q^!l-GX zS#UFu@{(%Tqy2qDo`iuAiRdscBL+u7YA}P0E5;zj4Uh97xq+==@DyxuDJehq2H1JR z7dhSlj}rj}Q4pRUAvEoa0jmbY2^0k$+W^55wZ8zAVc0JS{wRcGE`BmF<1wDh0Ak~+ z+b0Gz$-)wjU7Ya^bcmwr)jXOryZ^)9d%ttp|9`*;iEL3)5>ZC>mK91u_FiQtl&rFf zGAc?D*&~HeB-tb>qY`pSLRPZL%DNwCpYL)11^174$MHF?&vj*-@AEuguh;YWSkJ9n z|HUss7*80$AgJcQi&7ByqTy63c5T9B+cxk0_3PKX4-MS420VA(W9Oh@J8C$_35L@6 z0#vu7oB$^9pX^~Q-~&M7Dbot(8E-(|r})ORT%w|k_{z;&&RNV%Or4@Yknc1N*#X}J zdB((gU0qW0nR&JOSD!w$w+}cIC(6{QR6s%Eg}1l2f7(PaHir+N(YhriA%P~iC}?_O z;y9s`5@x+cftx79Vcc;BTE(Y(*uyf<1b15vms>i=3k?;r+1P&``T69b<(oI!6WYte zJZauOIuuln4t5_u*k$y`jNKCUEGr$1jDBZe9bH}V=rued(s#D~6IBed)vi!LTq^BY z5P#RWr4sZlmVZ@4+DyO+(4c!z7Iyf|BxN0@2C4(S&nM5Fa5Cd62qPeP)w!RI9j)Tn z0I)<+c6SaXJ?s|)<0vxVQwjM+ePD<7LL3?>GrOO0U2%?>y>~(kuN2Gvi{x&DP7o3j`7JMc+>(R-j_a@V-u`Ew z?tLa{K!PP%Y9rBbx@d)hwG_xQ`YV#4q$AD@AYKFZG zu8wl(l>A4_$4H1A29y2(=Gy+E_@vO>5MnC;#Oqk%|0uot^Jft!my#Hz%>=NjdT?AJ zfM=`VSi`Yv5Q~EfaV!Yjcck7}UtdgUmL{k9)ZYL_yiGVfiHL+pj-&Yn1&ywyI?RF) zT9%X;w5jZ&3rF*h1&wcBfe}u2B>O&9m@2{vQvK#Ni4-AZQ2frGSy&~m-dQ5=926l> zuRlf(h%{dk)JV;6mfWbf9RRZP-Bm7Ol~8?J7x_N&SQ;g$*6s->H`YFPX>_mPInf@$ z)S0~W@x*sY2w=MWdG(nqa&vb;HU)HF^6u9ssRwh*6CFxR-6nsN4ZH?S^oT|{`=Wi= z_m>jQmoAAUw8`|jD`YUd@b)&XsEpLnTUbQ_n}e6Z=Yy zY-~T2g+n{!sK$TY?Fb1qm$QotXf%hfPeo8!en56nQx4Ua7U9a<;hg^V-xi5`>}r+O zP5=xpF1e51WPxYPYKQ0haBxDh;l344lK8EKwB*f=881JFL+$Le?LPAH%l#)fcgD^x z^}a1Ft)FXZh%wAM zP+gQEwn>mK+@C^5i)y-RN@{a+vPAq{2sWzX;!9so9lvqoM#+*m_8^>bfA=arK9&^m z0g}P1S4ka9SY8;?T0GrJ+;nW7(CUEE!Gb{J zzX$GP6a6=#kOtZK-{?9`v0=5oI+pBRPr*^)wx>OVp&jplbzoeA?cFm$iiw8~%_jBN z<*f4kbd}f(DRYOe(ngXZ?}vZVi9OiR#OKW;wHr$cj3=JSJBN&=UX3nH-CslYgDhz7 zS5|UxJq0*N970HGdONm&2&68mIw(e9>YF%vQxzFGoM`J%0x&7;zpnbZ(eMXfwN4Z1 zQML-{{xEu_unM_|sLZjNwfE)~EIJB|QoYr^m6b<+Jdm}XUyN`bkm}yV8pEw{va+>n z_8r??n;A17*j}f|&Hdf$(=ki`k+|O;`#$8CAvk972VHn5+H;&Uol%^?e+XRLkHg-T zo5bL8)+-6^Z)lruForjXj%5q?$T8Y{Zll1Zo`&v$(3_SPSj)NuzuJeF9Oxpwg@ZvHVyb>Nro&&@ZUYZd?G3IAu_xdX9uPhY)a zUGa4(h29M%3WF*d5~y2_r`e}u!PL$(%3e7lIIAqm@MtK77sHh>phlF z^19l;l}9|1ha!gIBI$>ZAAkH-&FgaAAu7qXl90ER^5{{N&J)6IPeo2Z;h?*~GD^}Y zL!1Z23OGL8ShSx;l4ZU>0;QYw`}3^5?t8oYj)Ld-zmtCjlbG>JJ~?7h zeE#m^0iWY9%?lpU6qc3we!Wa%F;6gO)vm5GJ6~^my;(6~$gF2*$b$PP*|>wN^XzXt zHLQB{TSw4Xzj}JB`IPlW?bf-G&9#Mhi`@%*W5Pd76g}~3pnNM(RJS_DJ^Fe2z2=tE zxrNgk`(sWl?)Yvlk>2h+Tv$2%lhIb`0JnTn+Qy_4G?B1Nqevt6#l@T4-j;U!c`|Zx zSIqxh6xltDP?57Bsub2HO9E!+nh5sF#6-F+YZpr6+u;Y*a9_zIZa zWI2?-)kjgoN;?%B5wsv&!wL3&#habtfvbcRmU zQPf?8Ty6(na!BLZdYrpKHTTL7Fli<~dX!f|B(-QKH3a(hw;c~&+iNpfh9Yo8c=f72 zljUVb?U@>_6_eWQRSLGQAOF+u%|A@78X+rP6l)dQNiyw-Q~Anb z04E*EtxlsEFM!NA7&fpB81rRcN}J>T`{A_4@@pBEsy$ma}uw!!d>H{APYnW-Rl1Gukl*WD*7?_f)wh{H#Y z?0_W?lrpr=M1C9mVT8o(E^vA6YN_JLo>aBr*u-a+<*|DUt68-!OR#MWZ0894)7~5R z=QYgZH{)4hy$Wx0976nG+QpBfZ;sp8a3Xi(%v0Hal%kqaOV!kmEn8I@R0~wzV=L- zd0?DBvV}lKLQz)zVVBdl(V&uYC_R4qR3hR)HNWdicenI8ZiKRcw|l@DB%{}~U+ePm zZ5b9Ghnj3{;qOJ{56Xjv(uG_e_#H&k}DQ< zwlQj#&6**`=j|CMkt2E7`Pk*sVbM+U`3$_T$Z8p#Q< z2j9*F@x2wS?XWx?b&x=>+u@+!zZbT#>gwu)3{(;L1?|W%oAjxiT@5%3;bO--t>JYd zC#eL!Ln&iq5faus#;mR=bws|r-Rn`65#&+Qqvqr^ChbQR3z>|aXyRL@0%PQ&g~{@t z0)rbkwT9k068BVB{?)}H4Y(Ge1qX<83tKP#1y%o9JhE@)$ebdKf*_O@|AQjs1``z( zbhfIF;Xm$5CUv8itF5|xj5V&P>%|0di zlj7Rs`F=hm^^}x&z4OJgfH4tA4;T|X%TFikVZXi!ja+8-ZT1{LZZ)JovDJ0QnE)5Kz4VQ)@V*q2GM6%A^5B*JWQ{5LXSzN}&w3(^xIQ z(*=?LB*1?o$ZtyWbiT<@(X%k_m@o)whX(EPB-y`G)qlDsy?DiMD^O-akW7*DN_9~F z=&29ipKVTx2eHsCC_KNN`>5824IMg^+~%Z|Ip;~ZkCNO|8?^Y#su2(_O|Sg@(lJv$l`>e%C9mnObtgY zT1vHQ4YyNkb`tF9_6Rif#}CCJ2au$MzP;>28u#@s*G9(@!u)^yc<7Zj-H=KN_RKa% z$+Mj^%PkSL9?jc1pY!mA8?n=lZ43VDeDZzs&#!6gVGoPSZ@w5F&h5m0bH<9cc2lym zyFqYV0X;g*G=G+L8zwz-;E`Mwak0u)Zb4sp>bvXAG4G;MY;X`C8+C# zLu${LvW$(s5f0ulQx&=~6f?p*pk({u$JGUsl<0+Px)SV=Qi5Hhg&x-{C+g9ilN1D0 zvA+XH7)e56qU?mm8MkI-ocWvN4xICH@Jb*u30Ad#9EYM};a`)s8$E7Bk`)5tT$+yU zr-w%Pe};J(?o-k~7k16DMXt~Qqyt_Y^=S-12H{o@TI=nfchzT_8XsR@u-VcN)F2M$ z1CnujWAB$wPnMWHyx(B07606I_0mVn;xLFuP9PYpW};{;Yp=)K#KavC#u^%_nCUdaG1q*)D5KZcM#0GFnct$3j>4RpWabu{tIX2U zUEvKcwCzNG{#W~$6$K6m*JEDX&LtTNi!4)Hf7#SeaMC&@lb-)7;`44#74ZpGHFp%5 z6|CHkoefuA|M}fZcKKXF5JiRtm#)(4?xpm-tPC!)* zRgP&9n|08h%{hAPjujsj_ukhDKP&b^Q8;EvIppmxXI2M?dr1lJJMP>`*a*_Gdd)DA zbF$r5rnO&j?RE>Dob&G(h}7H^rX=!&s|_E8Y#m1t1NVPvYeZX~%=qFJWOhMB2CV}Y znIkO|>|%uI1<{zeaDbza0igr^Lw4Zp@Vo?N6)FFI#DS>5R94w0$#ic;+f?KYwQ@) zRPgmenWpoSPYZ9p5PjYw@~(-QDqJs2xzdGH=(J9bh-@O1T)vMUoe8s55WUw#CqvRv z>>x->e%Pjjaszfocz{ec_hvyJ=jq!ppd77%I;`7cBTKNIUo|nMEecC2Bt@3;Gxq` z91Tr^F$oVHFH&7+CdV#n#{HapOK+J6@9UDBVLh6?`tAHGkL0eR4$YjdX3%rdeJorR zFKW|j1DEzZc5vWGN&Ptb*D6#e{2;lVy2_I-CiB+}Q}3zRW41eLGV=5UL3Pp9%qikf zgR&2m?+sMjglELH6y-Lof{=n9pA{c?fY%P!4Ua4zjL23{c}~JC?$%VhCy5c()AG67|qXuCK2fkU2k8w zmtFlT=6#P%5!=13$l;WlE#`weO6BEj=gx{fGrq||Csrns>(tcb)gH7a`t$OI->-{Ejz4+)cq+k3;uB(np48R`-=tJ8>PEij z3D{-vM(5q#jlB#{6gDd;zeiulbA7`DgK6|i_nVE%$Z^*PN;We90 zm~c%<16{8y{dsywhI8F_C3$@NKa0|#LnuvuO-wYnNfE(A*eQ38D1*G8saZRkZ(Q&O z5v~Y@eTYW~=~Yyw2+qbfNABG_@f75R0&g>1$G$`u+XMyGin>3sJHrp9>*Vx=pX6ga z+nM642M{a9az`U8-YKcg-#DwCa0?>23P&CA-g6MH9ywA!G)I7!hgr@p{_e6wf|UKl zgYg<>AfrsGQ>)?zX;RHud3zszkZ zr9Y(t9!4UlqnY7-`SMMY-CUAV@eA=s9li_=R>Q#j-94IL=+H;E(U#Qx))uet4hJre zj3EKPZ%}z#)%;+1)uqKQ@)#v+p*6tds^`uPNeq4h|AJ)J5B3o5n_Cfap7pk#kG7n7 z%02(75>bsf>`L%J_lYpLl!Y~+f^ASWW8=9O8+#oD77%QtRqE{k3P#{!sYm|Km+NwEx!WD&B`8UyTFM%_+d zZ{^aW>;BD-G(MDxy{di!T@4++8_U=;9CX}aAZ4{W`h%}q)9>14Kz6`@w|`07v9jQv?F-Mp z)>r4MtCw>eE!x=G3yr+uB z<{escE~p+P8;BP?c{FHd zwZWow^}S#XZkoKj_j)Yvl64dd^0OT7e_dicka_=>+@j&6zrUMhIg_a9HKjv05D@q@ zdc4)bKy)jFWwf$XH@s}ZXz!%j-4RtmgRgcMnV-|!pYt4vEPNp!Z~5o9Z_n&!I{}<#Vr^}XBGmHrOpWW^rqN%Cd6GgQ zZ6{7Xu#P!MuA;7z)s) zZ<`@?B(ghB0?naJ>$f$s{%rN?Am3u&bom64S5;fSu@wApCO`L@Q`!yB-IwL`&z>7!@Dn+4 zBL8}7T5h8WO#+FyEh*Ct+fK)G-cEenN7+VPTLF@e)sG$ zT3=u4U7ed1Y4rDB9~i!`DVj9*?(G>f^HYX0r*)n9W+bIzZKcjh?Dm_^FFILf{^9m5 zZtp7 z7WQJd^Fwqyc03}b2GM7dxxr`}u)NVuXeZGeoZfe@Z6KZu4bKP^N+%E%ggo}pwAA6G zgB^8~WbWl7tkV@kbULiprAy6qlx7sBg9ome@%g~95786MoPp)i%LPoT18{(`vtzC2 z>hwdw30xB=4GKL7_Hb4sbbyH5 z(r)S|EfDb`P{3<{Cstx)$XXpa_S2s_psW|5;FuG3jJrcpm@X{_*-4%BwD)$gH3iYI z-rdC+!~Bb+HA>aWgl*Bv%Ki{v$$Cck(_X_p1K+u0hUfDO50*doG}oV6tN{o zC6JSw)TW`SxdX3!Ud->U^-o(w#xbeqn-@*KP2u4w}tG)vl1E7 z75yjNPbwZQEB65>D<0Pwdc?Yf~vI-_>toUhztUQYpnMfoRJ-d0_w zKY(^|6q7j`nW${7D;_*eTPJVh3b$Rpvf3XfAnOa~d2cHVGj(|GK8|6OX)oDn*M>** z?xhyGI$J8spP`f>oeNQ++HdvZdM_SzEm>e)QAo^r*Z2Ob4)6GQfp>tbZT;QE7lz*8 zsXzbm3`}kL+~5D{17BJzt+J%2;w%=y#jj>gQ_r1V^D$hITF^?1u_3v2S#BQgEyM|V ze!D5mw781-HxOv3p;eWr|2A?7!;-=v+hJQjc>v=K2w!^Yqo@txV6N#nlilTi^sD^+ zITll9p4T?im)7}8vPa9!pLEBtGL6J9lZQkk9UaBL|Gln4+2?+x&t27BS|^R3RAK2) z$FGV?|C3Zf&$?pmO6Q}EX|l4ukSlD*Xpvn4`>#YqpNR+$5x9oV6+NJn+h4@Tj{o|F zyi33BKAZpY$_C_#3s3Gv|u^~d;#zj6;wLnL(S-PZquU!p+smz7?2kkxH0joM7 zU9(Mb0;|_DXLVDe8{!2aQ^`wQ1u#jZB|d(9gPZ=?gKPH~zr^16-zX@1|M4Rt%+$PB zK7RN>n!_6s5$^~`7Pf*%J~$YGRwHjq!ChKY_4)3TMl2Q5E_4%hjN>;)~#(sq~9WC3!WJ2!V{=`GgZ0vS9Q!5uO4 z`;F&k70XQ|Cr`qEOzYX($mUfa$v3~s%j{vKK{+O9rh2PqQw9AL9N+9Y zXp%|tLIR~yN=n}wePFq@{Oy)f&>V%(pvc|^I~}Vk)5Vlx^8(<*aLl#90xUDuDn3U^ zCRms|c*pmLp1}%ILjc}`+S1z~P0`^)M#c2>^pX3UZ^_SX=e(WuoS}%}7v=W3wT)ph zNxDo)b_MGh!|R@0p9QEx&4qwZzdIB0TA8Fe^YrTc4$`RW#(E;}8eiDn&%b_#W&iS; zCiC^cghw`2QhODalVKcrV|{h1aU+AFf16_a_+jD0$`DuJ%|_J%e7W#0--Y|Y~Y8faa>~N1awJI#1co%ZQwafX!xwG5NT~)DkjT8*UC_KabNO6dP+LXW@LxU+kN`@3Ql`ny)U=*Rd*%vB}GAg9>8~u z(n`n;q^S%Xr-w)~hJoy1OCzuyh#rVB37bawuXXiatK=WL0>k#w$`BG%y68o&!yU@c ze=6{WmzNi#Dn5=HoQXtc3~H<|TEcS+dp&rv4+B0*_4~O4)~fYA7jRk+e z#wmmx^}p|}4H&4C1~`!)RIg6zCi%I~1r9^qik zzkR;<*{CxpHc68kJKq#hY|iB6%LJ~@?^{}5A`fFA=DR6u{pqkD8J=xAu^(n-Y&ZZ3 z@mqm1F8{bH{7Gq322n}DUz|AL+PcU%5?e;z*Vhm|5NZAv7DW67 zXW$=3ll5OGWEA$36xMEDfrTk`&xJp08@L68zC=@#OGrq&Z-AbT4x#s2a2d1SB5%bzl#O5|qc$b*{{2WV z8Ie0Nx{2LV8w)oYBm!ryKIpr+J?9>yLQl`1RBzTEk6P_1p|ZRG_1=1S)=ow-H3sGv z&(k|k?DuB5iYU@#b_*_Y04|VnVC4dz9of!i^|qy`>N+TBh!2P15;_3$B1ZfXA$xFF zWzQ}P!OP<&amiccy^wOQPSXo~NA>a#eDdVMZM^?ROhUsWnP3Zn1j>;weSK|^o`N0k z?Cxq`?{WG=M_24Ts2bn+E|!H_`|-gq#%ShI_^a)g8h4q@{!ZIEZ6MQHbZvWP=5CJt#*&^E zHMQt&VfHP}G*B~e7E2@~YtNtGMbCkrD=m0a7S9+=LI4IbCWx&?-@c6!@fqdzRKLj= z5-(peurW8Z6xB3yAy5RDT~swsjjxAN(cAdp!4HLmj8yc~v1JaZz>b<95G4QS!dGXr zl9(t*X!7s3h3(Ers06dSA2XEn^_g&UQ8^0E9`k)hBDQJ>{*B8>{)0devGG@e5MaPHKLu=@Xo7TC>*+Gw<#rERfA6 zp#Ep$Em=PrW~(riKLC&aH$e#l1CXVP9xRWUuv)27A&vqjYGbcc>P+vB!hMu)UU~9E zMtZ+)Zl))br-#h#3zsf!U$jgwGTK;3r}cknXf z_`mu03KqYp2h$(SrrA9{nO*!e0z#?(jeE>MJLWy{6}f-F6CgY8KtLA8i#YCL10vAw ztoEecGm2sNwI(Tb=2N7eO>^N&>(?N@M2*%U+QcCqch-Rw!U3d$c7)Y}jE%j2AJXbN z=*$3(VpoaEL_-0@Pp>5eWKWy_4AnjD$HEK)Bm+DsNcswS8e=^^etE35>e?swBWUdc z{Lip{)re2{BMb{!LLkMucsAfO2bmyg?hCmEb|#qfAIIOoG!V4DU!Z3LV+8M-AD|>hd^)RzikMiX|Kx@YYShx09kiu z7UaH7`4}+}b~!FCm9BMT5Y-~PF|P*22GS)^K%m4$SW+wI=)M}y_W~PmX{{(&d+9B? z3YX0EuPi5)`ws&uan9=;TkI@IB_0A`HK2lkd;m)#upJU18183hY*WBr0fJ&sh3LHv zIoMD%zzTA~WRdb#;~OHIlomERA#));jjYofFPX8VO~(HA5YawmWtcw~sq^F1C9$SqmOwj6RQ8Wkj@&>JKYvb_^Ou&ALSO|ho*1iw4%zk; z5lBn;>2^}$cH*~UPQW!ZgezM;@-rgkc@?C!zJI4%mws5h@<8f0NrpPZ-5=Q|>MF{Q zu2V%E;6G`ktV}9;xrXEmV=gt%-Bh=k>W4jvJt>M_pO%{(3*~$Icx+>7KLn=n(NBIC z8*4pAjCAjMqY4u!gE6b86l8^FWf!?20VaGimY($#d7;Z39Y{t6niRz8QkY5S3e@BT3jU`w|;Miv&hU<4{+3HUXdXyC-dlMU!j@&p8j8s1U zN=A-N`1b2b2sJ{nfTId!owJ*pp=F5bR#Eo^W=H`q7l$sx-kt}ZU9eSXC7e#rR!L%p z98W$%qu_GPz=?u?_)9MuJ2<8PB?;03DhOaG3LlHs2yAf6iCDF``6C4$;az)j z&=1ZN1veUO1cm5=*aCYS#bA2oO!@u3mvH?|=e zNuOywZ?ZgKvCBjO(+J&uR3$>>hJ_Cv7onwM!J7ex*h~PAqt`vPzbKbm zSiuLhEe=9d%R%HdJY9Qp>>>KKO^l`_%xWDlI$~TjJc4-W=ne1_PR0Ty1_*mVlL=1{ z%w1-?Gw_~MZPWOXxK&Uk;YT)l_`x~?f~9;quUQb&kiob6{~dqg;^FZG(HwXkF}4&% zW=3{4c~*M_!*vkX=+yCs`6;A67xTjQ3yK>3IkePf^myFRLP%W5Wz8=3&7=q_ux8Mp6E$c@>6M%3f1ZV)pyI+3DCRrm3sfwzM4B%;ZP=+?s z6k%;2Ig$ZQS?+8`vC|xomy}R?#e|llmAAJo^`}87wv&q-&(5TIrGD5CEhJ8TsGo7K zse2nM``iy6Jcug7_VQ&GuCRl%yI5EbgeAQATGaf#19-_M4eRVb1*NW1idOLKHe4$} zDZGR?Wv9cXNI^~Gt%Wf+zm+0GI|Ok=K&ZqLAC%XDO9U$efua6Q9fwapn_)vAzOOrq z7sFvLXboo`LNyVPB=$@-qR$<(RVgvw9Fqcm(oo-@<~A>2)r>uP`m|wl(3|W}F8==I zv7u)iX4H0()KU;R;K3;GJjn8|<-C#tO8sQj36n4|+yI>mAX6;=2j6NkG?j+GS1;1g z-&eIm>;_KE$|5g*`PL0cVsk^7O%JqGZG5%B9<43jjNCm@ z@a(R$zx3FcKDcd8~WS@;Cq8_bM1WDMe!gvcU&Hq0WlYCYyoo1vX;MD^KB6lN#otlrZlFK?3s=ydzikFqXgJV+3->u z+$2p01AgHV-g*WImvB5_V2+`|?0yYwi=6Mq}H~(N=R&*Aeo6jIbDD~jEV~b`M9{bkM~gB z{2F@3Uq*Qc)y}wkG>G%O`N3XayZ-8tJdzcmbOdIdFRXdg8zKSZT)b3}iUo-4l&nfz^>#_>6$>@IU>HxKxw7;Ay>w!3I)<|nf(A_U z3|sZDv(I!!VxMt7Ei*NWU~nvu8Hc+d)_KHJ#_^d{x|lD{1QduUjn0t!g~SP%%p*z^ zWm7pqa}anr{!*X`9YChT@DSKh3>TphuJSZ@+z#~aU#%5_l{4Z6tq%s^;5v!XZs2oTmRxExB}`j8(&3ZQAd(lW0=oEKX78 zPWo4&1l;YAc+>VSpF`qek`zXx$V@3<_Qbgx#I(~!8|U*lh}hDC6`f%H?%$a9Eg$`z z@2k#cxQUb{jg?Dn?EC2{U3OANKHwpoays(DyLTQ8OE8|19_EyiWZ((2E^@-~y=1?i zk;&d)%_eJYNl}$l=5X_GF?-ak@`jU2)*n!!_z^gC$7L++JBi~X8UnTE*d`(?rK32f zMzA=nz>N?9T4~T*SiGi3QRg9BzPeiVr0Wv>bL;#=(!#=%D>j?+Y;*|RqWN^pSA(<= zlWNgv-ddZk^f2!n+X!CS#wWVRC4OvS4o0TQis+{S=RndW+;wo@zR9nNNu73;gfyMb zrs6@z|Ka)XB5H`y3`Bw##_v4;gfuF%XIWViB)(+9L4WifCnq$gBAS1vC@YQbDJEZ% zXj_rfEo@Zeua_R3mw|`y_3!x>!0rh?G3fCwF2KaYe)b{!Fng3oWZH(&< zZztPH@`S41!=pBkZAs0c?0{iS7o?z3>Tz*z(z|b+iqzM!k?j2{8m} zHO2y8ugmDis+sAvPftE-KB~NnWSPm{EOn^|+tX2!LDISQ_(qhh=CaW2m)*jC`dVe( zyJaqy>}TanjlgNjP!ctaWcsg^|LT76JEUo!_(JF z7VqBEE3=G@+}Kx(cR5b<`SVQGKJv-IRtZXCOCpUZJwW+NfdDu3WH&K@lS=vJb<@(3 z738<%a1`a{GJcqwBV*tVRjI%@P1$#fWwzgqOFkVG zRC7rIlgKPY-ltuo=h>m9rebB%o3z1v7!#>cC&y5`kH-jA72y&SlX<@}I{4Z*55ug6YL<^(>@qUZ?ig5HUcR+$saKcethIX~nys{~ zc>Fjth>aKkdqhWe)qZYuEKOIQc#UWmF3bCfg(r@rrGE35@Q-ko(Buy{&U^+z$ z1>;!75q_@-%rilLeQwZ_9jfS99_?E!COvCsD3sAF5`W?XcN&f09QyaCI3|NS1T#th z{aM?cNAmRl|BL?*Zi(0!yiZYHA7#UD3D+dV$H$kuM>lhTBUtJA6oi3y$@TEsN_V&E zC30K)4O09Y3=TqJ(r3+5`h)`=z?>0SwFgmmIb!arS6^~9yCxOaXaytx+EF-*1QV3f zENjy)YO3<^>h}{4u}({AZ3pQ~-$k2d8~M^iY~ok-sf?eQ*5fsj?QYZWxr2Q1t%2L( z9|vqTGtIN?#)}=+C$eHjE6n&S?}1Thj*7Y)elvpcx>QQEwviE$ck11-bjpx6y*arU zYM}4d!uj@z4?|V1Y~K#}EMdYicTxkhn_x%#&bqT$pX$_QIYoW8&A@2v_jgrOqT^IO zPl&v4N(+h-Z1L(7jO#mzDKvc>8&$h^&c_K3&8?c2x^`JgpD$9E?xsD{Q?_GjvXJB^ zPb5|7HH^V4zwn^hT|JiP6g7>1ac(53Sq>t#i(_NU-Q%0xbC60>OG&oA(@!`5@#}OF zWO(RJYQZ$g>>_rtvRmsL>ri&yMz8l%kB7K;j7lMNF^al6Iefw~-PXY=2!Z|gbJVEn zkI^eAx2~^NJ-Az^8#K>ch?wC5ArYNR}c&KMW8;Qqnux zBD=T}iVT2&fUH$OX`*dTo8ZlzbPQu4d^D-49|0)?I8f8j_~>1- zoivHzpa-Y@|0aq6=R)rTS$nyAY_mJ>?wwx{;Q{1Pm8xs9G6sZ+Hbh@wwSQYaPdd{t z5hqJb(E&Ia5U_43t?m#FppgL24GqJ1G*L+2))=ys)^d<$`bIT6Jd7?Irn%p{|Jx3n z0s0`+$RQuJF%#|AoZqPO>~>Vr8<80HTxk7M99l8a-;KVn{_KlZ=S>qyk~K=Mf=``y z4m|a$uL)zgj{2-|o%0~>PXRs7G2+{VsJIYVlA5zf>fK!{EGqfyxI;gW{bv6aZYta) zVMgk|REb;1pPsW_CU(b4BI^|$uT$sWr||% zW{LI{-QR>LIZ7YS-?#INTZr5M^y(^{7Fp9POF@p*|Ne4`R&{i%pj45o^Vg^9v?+=} zT;}xgT_i?6M>5i5AYe4xsO;R=|D(-Kh0{Qav`gQJnXE`pvu!3KH7a$LKRRO~x=I(-P zU{0n+@U#^kIR;(;cymPJFwWQusfgBiZYo%r>&;&o3J3vu-S@4nh5<@trHqDIO3RA& zW<(5BLEm4_d6N=&NLs8yXE)bZ?VTLwLG(S1Q(RIZ(j8GPgDx5B zysyhEEbLK9R)dFC`QJ+yW{UE1@cUxI(wOH|(RU|Zj&kWJWZzFxF8y=9j*iZQwy=Ab z9#e47!K{yJl9zbbo*?L*zTML1Q)S(U`U7P@0v3GQ%pQ+fAl~ANiko+)5y>f{#iVuZEblgDm=uuKR$`r{^Y+0)d9sL^v3=C5MH{m17QOwnnrQlV|c~P-oA$M%VhT#>Vhm3Cw~2^8(X-raMj3%Th$?r55o)* z{j5Sl#<1(qp*Mq`FgOD6jof`pz5EkgM2C@7ppL+drzqplG9j!?V63dH?3RT`wGokZ z%nH6uzC??^KLisp)SY=WFK zn97)&JhQyk2%s7fWk0E3*frct>Dd?O0nqm8;no&|)czh+E%s)c-ySv%=5E4_fbPPdJ2@jL< zzdMbqY>xz|q-S9vfNl!IC1YlZOk`O#rkYOcN<7$0n-rxQP+$+mVL|7M%(lIb2PoM6wqE zXp!<>rKP7?p7I=iH*7z|9$H68kfG3Lj$-@vgPGD7ej0JfsKkow_t~AcKBm-sk&7IV z#R;ln7c0F7yx) zsd(&Vm(W}|A`uI+Avf{57HGTCqG2{iE3|VufYlMUfujp+9KQev8BQOWjp6$)u5M}q znmjq#&olC(Amp>^9}G+^k5e*QB4|qT1JfjPKjZtp!6eA;qaZ1&NAf1UBNET+Leg@6 zUY`DDa6o`1hI{Kl6gwi04v0XANF%ryw*H$>0je%vOQ5J3+c^bU(E@2Pj35~JhiKE` zf1TslvyumW$Ztul(AGvsKsw=HDg@SJw8^SUWftG~`SaboJeuEW-)uXm{e+o_N%XPW zZuF{!=nyS_e6Vrz|B3^-c@7cLTDupokVXuz_~8|+Y+KV#p#i+8uC09sQubyi_c9A& z$W7+SEXGZt{yi6@X4a!~C!vE^-c3t+Q87YSS}MD&J67Gnq&u>cV5xN|@~ z(>`m(uCTn-ElXHwYHD(-Ho+qP@5)bXD5Gsjjo3ow%}(yPND>G$aBT2sUJ2&~_-|=-a zKh69R6ZlDC`;jj*;J3Mj#`Vj$_Ie@<{M>l~)I+DvoH%@!Zx7Y6#~1EwGmCFH{Wg|I z55ovxY=m);i#(QRuCssZ<3kN@B{EiIjSy2HkN!?+jz&$ig3a2jHs~0FzldNLuvq*} z+k%u>xlU5tR>dmPY8|jb5sh|oKPUlIRU|}~YpjiV^C9JPhAh5)S7&sl0hWvuLyucf za7Xg|*V(QLZ^Cf8lk(b!a%BO{Y|@LT6~{imNMukAYs2J;XkeT;d@#C$JRP$;h!}=- z_1G05PY8p(er1GDzuBKhlDEUu!I3xsFjAO7H3AS);y-tTTgK5+wJ>UM(e7f#_qF| zU(ZGSFp;PLR`=h7TUmLH^t@dNKf!7iJuROtR`$MF5J|KToXW8ea$VRl9U;Nqh}$kX zQHt;acqv=`TE{O(!AU~>q~i!ak~&I1@G6V|tx*z3W@Kboec_Drc!zfaun;p|S3uwQ zQc??BDY~H`lPW4e8Wzna4K6_)Zuei))2z5yVl#ng3e;v;niU&Ho50`Jp**fp`MMv?yt5llI*= z^G;x3QvNE}GQKpik*=ok9{$c^-yYnH*O#_%K%s&L=GguVSwu= z832rV0P~Evq~eKbTJQh>>9{DvAzvcEzqJiZ2#gL?BS_8~BS^QWSZO79jImVVflByC`633o?}l-Il5No({!;AHVQVqxAx zYHKs#_75mKq_pdL*|*2?Kv<17pmu#k_^q0{U3A0%DhIS-yUgNuiN9$6cmlPzBltuF zC#k}$1zB>nHN7%?7ucWrf2D%R0N)R96VdFIf14RQ6CO(QQ7H{G(upfSf8Jm{)NquD z=tcR86B1H(9J65LK;M77()Lv`!~#=B2Fw4lETEj6rc3=m*w;S!EMJpa|#`|3GcNHWag{h>ox9S)^`Z4n&MFN(RwrQG7tBzn)@-dpgy7j+ZDEnVGy_u^kYkw{4Qz54SL@@m^vt~O!W~jBa;S)i5FAK0 zu4y#T*16Ol=sR|d1R`e8bQl5IV`Qbj`Un~v;z_u>Q}Rmx0a4o9MfUL>;yo^2yoi_L zAPpq)LKe~9zP$oY8|KT;j)+cF?`7TRTutis`5D)D*$o6blXo&+Z+r%!nl$rt9*DrP4Z zuhjUqihjp)_bN?9Ac`V7RSG(z>F3>S}86kil-; z`f7!qmiEXeX!nqOw;6BK@6Xo+Z5_d!J+!>E1M3KzK8zkmFpw%EV{oqvo1qUae48l! z)a8>>Qo!MLzg%$KyNyfwE;@aCGe-zho|(S5eh%6KrSDgTi@;L>KfsVJtV0NP?A+XT zCbhlFugob94SPVA;Y2v0F_KKGgX{v~lq2|X%+lrM^}E#(xJNqITeDexAec}L(>Ay z%X1>4CQ;fW^`|uTeVSmTv?AOIuN)D;AS_HT&j;fNMhjsgDWq6Cv7tyvNr@>cenbFQ zdVIvAbI`P)<2i>G2U{ruFbM6Qz1Wd4l>SJmdimuZ=Fj}k0HB2&K5#^*Z2vRF=lI{` zWa#_Q>)^dXH-+I@hFX*#ffId&`5dPSR@Cj=w-1ws8YCVOz^Ww2sRqd{5o(R)1j()V zML980Z|Aj)31eAQ0fkM8tA4-Qd>E!J!QwM#rtx%FVd>!{8&o2I*+|QUAc)> z4J{2IB5WCGrgOBJxK#D*@WEl|F}JXg4H(xCT4~_Cv_9A5g<5#3`DorG2?U~e)A4<< zaaCI@30=CHbCF?wYbQAwZV3(%v8>tcTiW|m;hVu1DFHtva8zQ%Al-i+N+6Vd%(e_) z=^i$h&rV6vq&fWR6v@u5#jV@0kD%g0is+sjN(q?J+@b5d!cY z1oQKjzfXz-vB1Q{n2-w!`3M&mDPB7(p#j75cN+%N@!Sc#MtTV=8DIwXO~6otZ-=6X z5a{+3;O%JkP|TLO`H47BLsCzAVzd+I)~^$S*3U!Gma)e)i920D@EuxWV*he;Q;X%n z&qF1o_c77s%M5l~0RfuuhI&W_5ggLn^%G--p`$e`zjWx$xIM#)<@sgS+0G9pRJNW1^8ENXK|Q3H3oY0nT|_|pFdxpY1{FI>ZWhtR;oZ9(x$HH=sX9%bo2yn zY_L=S8D_Av+frzfaJa6|#5DT!nG+x4*dL^)MMNA=&3XI$(18bjL>qj&9d9>%+0D$t z0`A3cl1XT+Nb|n0AQ@`f`3z18jx(l!&IF30ECEsc`ukEJNG&PpT%=CN+I8GKQe zlo`WUcJSVYi;K*fpGm;!Z4q@REdE7(-3cQNxo|T-1(WOLlRx}rEe9GK8eW5q6%!M~ zt~xC#ESxY*YGdliR;^-9v&8Go$mU)zZ0ol5Fbgznkip{Bxg>T`vSI%3v`tA(wfLoA zIPt~M(vnEMz;PANAkl>`WE^J3ERU`z8nX+%X=dEH?@RW#+$uP^Z#?VUnsnNA?b^&h zdZuH^m$C16L!dc(eieaR2+ESSiK@m|>gYIoFM~vVr=0hSryYrP9$Qz(=%d(YM@S|I z-mU#P`kj{QKD~r~xb|9`)@@KGvr_O7(7|O3yu_oD&1v7~pS|!NG zO)aH2OE@!0txmJU{3pQ#REtb0F=+|t<9WUcB!)oe@wI~Hg8ZIs(eofW2t_v#l6yV9GfCO+8ReR1 zA&NnG2gGXhU2PA)+!NffV+Uca8x-`hYc((RgY%5BY5xP+RE2YndfoI<-|y|_`p2+- z@~i`zqyNOLEPVZs*JaT5<9-4Ov(Z@%0nexp_96-;Ym?ydqNTzOH1^)eO$PcwthVa+A4tK@ z=Gm;vKAmsj)ju@E%*;?$aaV$73GTm&daL~uZ~XIS%Wm_Y&Vty%L1Q9-S>JtR_f;|0 z1K;LUfl@eCM>uN1e++5yC9P^+4GJophye(r^?f{9ebM;Bg@JxA($I^5`v~^l67D}- zmW0@YVhaVS@hxv0zqP9Y*Iqiut@zDygRR*;E~h0|HaaaZtUw1F$IKiF(v@-pa|=~R zM+eAjVcrA(xf`d^P=Uj4)Oa#^1jBv#h$DE8%Brg0-#rA)(7XsZe9R)sgQw z;){H%KtDRW!VwlcX`{C1_Wq*rje4>dxX+EaXqDQ7&^7k&|SDv+H#I{VPJU# z>iBsZB5xQ>b70Q+v@l|2-Jt#x`@F5TddfW@Gr@CSP1^J4^`>#z^w-$8IUM2*T3Mf) zkGaoB87z+gaps*n&w{lS%)?cel{f<29i7eL8nkJsq@82tgoAE|Hz!@OyR`~di>@Sh!BxE1xy}^%y;{a&8 z-<+hosz5W63Pm>$H`OwYZXmIkUrgXt1jms7C}Hn<+EcDUuf$g}2M0J#wUdash{>H|MtHJK)V0a8f6aY29`3GF*fR@qV;tb&NhB;u5 z6q$z8$;C2;u?}etDQ#^%m%(Rj?!OaijrLs!aj9dZ&MGb4WUE{6n8b=Hi=G21vt3>= z*XAkQ? zjP=-ierr6!Ns&>svZKgtXh)7GNzvy~)+5KhshomE#xj5eXNWBj^Ewo1@?rohYfcFF z(%Wi5=R+p}hZyj@+IIBoacL|{z@`kM2$n1XpNG;C5{Ge!A2Z4Uegas29{51c+&xMF zL8XTk6E6qL=PPh4iHbg6@?!8_o>%9R-q4^cnt5{Z!*%&M{D~N=QTs#%avl#8iv|OO zc&t6Y<@-Ni2H1=1OB+&j?}rEe4|;_avD5qf{Cq136T!DnXG>l&UO2!XKE6;YpqMC^ zw3F#+0Ee^eKJvjjlvDJOM>_w)_AN~Z=kJp3cvlO_u8Jko* zk=eZRL-QJ8$q6jXNm+7<1-7ij3qzM?6fYU8+Wg~3^176e5GUxi@|=u6M{Z_qPC6aj zA^(!+nXMwzElwA^{3}ldZGr^q5)+fxmtt{GnycVLid~$lP!xu&X3f&v46Jn~0igVxJUR%FTbHGT%(k!f@ zQV`GBXruJGZ|T22MZoO~haJm*6-kzsce(;B(0Zfpg4qli-Muf@`k^{B2~sF?(H<4= z56bI>1(VBc|FXn!^b(Og&oaIH?{Z1BnxC61-CnP(QvM;V=DJxI_957I;4sCpEbjtP zg%mGGyOiW)OvY&$89lk0q+CB;rwZoD_j_|5sHW7MpP%l5d&=YOAAi~Y5EGkbb2t$A zruhTNb;Rs~)ylnbo!41IZ^-%&$iI;*RXHyC$`x_xp<8NdY8Ns)2!@iPV$Ct%7xj5v zL7wsC3&HZq`i&?0Hjb4V8||&;7Z{$gh#wjABw>-w=2g4{X}fehL!{r{-0K2poKOj^ zsp1}EJ&7jGJR^`%XZ>8ESi;+VM4cKP#lgy++rKbV6&W0&xU_b^)I3QYcT-dsy@ZD^ z)b>WjRJ#i1=(qCj2~uf~iYgAy1CgGcqkX6EA47PB!`SQS5aB@`?X?e-RT!-{e%|R_ zWB3#kU zs)3?WI=a32%KEiyN|eu<&OrB)wv9p*Jcy4UgTS}e_A zqt5AJT_z^?D-B-!x0cRX|3^9iTcgW5T0icLvAiu|j2JRbo3CpFw<)AsSQ#2=J=3eKI*QfIP!$YkA>~620-=V`PRYxI#f95E z1tLszODKlB-3OxDy|BP>0I|yf?8Gdq)|A-3qK7n~Owvb1MsgmNianSba!`Bpem~)4 zR>gL^{#^%weCX(a91%U^2FM1>qNyK0h#T&sXk+qb;5latLy!142eK+82wp;>M5Z~{Ry>7C#8kY|NYsPs;=Q`blPluV6n z`0wv@uVESm@wd>E^mM!%D;EVC7J1dQLC!i6kbm&X;83cX%KV>=6{2<^cX*2Mk6-Ny z?*+1{mO*fBfHO_u?bST$4|YAL=_UF}RH@$ums@*zeu8b9y1GSyIdnvr(UWSN5IkQ} zQW9&o8+RUhOrq-$+8gsj?5p0Lce)p3Q@LvU7(@!%0Q7FX~4A$Dk=@FEqMIBX)=?%Z^ZF{l$!BiG?O z@dy*)bIzO-Xn|!pg@z`3jXx3#4vflhY}r!p!YT^bBFJXy-`u1QD3%I~$UUi$aEhVJ}0v#410aXsH*C3Nc&lM*yk@I>3fITK&aKdl{ra)D* zGB<`g<_Wbwq+!Je72h#E@_BUj&&!vKPgf%(L%#m8F5FKyOX6THR6V*dk(ai^E9yjv z&^Y&XgjUpzfcI-s$v*$$;3uAOJ4kxpcG+7Xh~Ogy**n5UdHby_7Z;V@TZ}PwS)@RGJ%1ZU-I2D9(&Bu>d(#GF4TZZZdLg)&yVmuTT zkRO8Ngpc@2Uw3`{qqCZ{o>-zHzIV=lE%#7MQxi!sb8(Mc|DuaF#2+X%*(~1z;6J2f zaf*9+s3qzLQ;^67imaM`IWgbX3}~!wW{`> zOIq?2C1v#7bDL{X23H6HEJ_EIre=O zxT?+kY;tvQu_7-e>BEQ1+6*9ZLF7Zk8QhBST{4a8@H$(`MxVg4J;GBc-<=NG%lHFf@w_tsQavObbB>!`AOH&J~5%WX;ql#Vt-f?rEh zlPu&E>=vjkVt-%}f&{!&>^W{}k6!IR=KmzLyj=U?P+)kfPH$92|6 zwkbKfp4m`oH$T>9DRJa@fSUAH%$v^=ro|1(y0W*Fwt110KTYO&w>HJV;SPH~xL^69 zK}MxV;#1T$Sw#F|nGy`iqMWUOlZ}|(Hov-A{Ro;xq+&sXFihkBP-kHLD z(Xlyp@R(7q4hWvuXdos2U6BE9eJoEv`Fb4n+=&9v4A5^(IarF^^t{*jbU;@nPt)+?TF3b!XS-*hOrVqC3{;I zgov1$UmrKH6w}+D|EBF~;U20`ww2f^hX~EOow7HCs-Y*s3M3hM4!0t}Rlde#v7O6Y zjNAvDF%w{bMs8GKR8-9)na!Z?uc!IQNWHr*Z5N^wc=oh^ znVephjMe2q+OZ>Y$*D;N<9zcr?SU@?i;)nKHRFrtGAoM-L5VkSW&|I1w2_;nPgsym zZ+6)25X)oKH2%YybBp{ft@8^=cZb3HPyO~S8XZB<6zofks?4-2$L|pP6Ra~ZOlXJW zqft5)i|)jVz7Mx8S}^pCFv-SW1Aw0rMdww*iQ0*q1Vsb-Vqt z`dj3{)u*V;y>0nJ0ydQA++^l_o&>TS^G-ZC+8D2f?GvB?j0HdyQwoyt8-RO)YmpM= zg(VF1MK}%E(?iyD$obDqmEuK}VOZr6nR$KMGFu1EA`J%8mZ6~lY2%X8$K7{3ZWt96 zF_Iyi*^d+iJU?G7$WSN4ESoa+{bynf9f=}$=vpg9-Ep(|M7l$+= z=Hzi+-xG_tfsC)G;rq*Sh%cCw4hbo*_D?ke#g6={`(CM{{V5X3xr#Zz5+88O%FWY%zwd*SCWuI5(SaI!DI zgED|96VwNsNdl_Ma0f^TuAXG1L84ZIA9+z z;C^c*J1#e}45k_2Tnzdsj;T?Bu+N932X{)^vqW9Hvs=Cf(|(Oro7&o96kcqRQ8gY4 z=U4-GtdIB}UmiG1-JIUcxRNRpboDw7!x_fK0svy5wxEE8dOW!t52`NU2bhA)`tG+M zZe@^3ewX;DNYJ4067x#l&Tl>6Z|3zVKM z#(OomKm9Q47{3Gf98R0;*)tK2Uj7QOH5s6p2yQzy2*8JTHR5fPlO)8NItdja2ei_zGxgLt&+5d)NKr zYbsmlzq9%=ogO{ALzMQ!1JMMYM#)DV6R&ao;eg;#+}&VUZGQ~Hb?hHG84VG#y1xF) zM!V>~=spyKjYjvYnwpi>)lU!3!@2yX=#_8iUEY6U>1$%7j(6PF!tOL}u0lr}6y$e0 zwq99PA^PQWW+C#OvJY;H-U)axH9KVR!DNZXwG-NB&C?4(6*&^Ei{}qWK4kB= zbypqfu|t8`$KT5ZCR`Md6cDD%Sg1A_9-feUbI?~I2`;J8IA zeTq`;wDr$@|Kfe!@v0Njs@@9c5<68Q+G-=%+1LAv$yX-Urfye6+Z!*h^^H?wVkQiX z@kwpkpq&FwX87@X%0mOo3#`n{=g`;6(P00$bXs)k1@I$mG&%?75dV%wkfwFlW43YB zFg&DK3Ycn-jz-%J(ggTSk#-bpo-SHxu>U;Yq70{ro_n;%;u#DsP&Ysqk}P1d>k&mp zxU5jMD2BV$N0ch^3c;j2Q4MT)4qWyR7j|n2+)(bb%E78sogENcV^MiAxE#!C zMcun6+{q8H9vFRu{c+pLJ|1D=TRQ%|88}!lmO#o&caz6GQ;PA*{VO8eUa!i|Dk^Qu z)Vg*{$&6QInm3R^!t-;t-rJM*=4TbC9+z-707kB;;^1a~@HeLrNOudYGC&Sz68u`{ zs5@EW-R{M{lZ00hNx+0m0JIWDyA#9)dUOb=@Bt(vzwdGUN0ddt1IiJ{ctLykW@W9!t_%q;d$59K5PNKD+Y!_te-t<#y+LLkdTfm1%VZlChZ1 z%`8&Y)9d!TuZlGrVB&(y4SmZ@iKActDe|$L)e5)|1`Aq9cq^3Fl?#UVi*2x4bPnXaCJ#I`+lI zf&5()^V3;Z6f9-P%9uu~;Ad%&Lh6q^BN+e?h_P^$68eZur4Kre(DO zdO1P35E3eWM7jNXj^)n(vscy|Jq7y23727Mp=_i7G%-e=2e~e+!j}bYJGwOQ-9v8H2S?CJkQO} zDL(TxVY}Gv`0$Rcz=hDz>A^p3q17V%H8oeo7GOb|(kpXQO-S)k|w3fe4oJ9v4 z+318?iVF?L1S&&QUlMB%h~wzgt~@P5#HH>TV<3TotED3meqKAU25 z`P=r3xE1cnGTd}UK1op!=xGDbcU#_e+`H)V3^vhr4Xob{@*`gfs2gZi z4I=WuheP3FaIl~Ft`AqiAO`uCX~j$=3LZOTd>g$`(x3<&M3SMRj&yJd6gzU2zH!;el*>MQ96JHw(BC#HoU`f=_2c~R$%*me;SON*Aj z%uHN2WbZqQP-9}7U0o0m+q?I!#G8|Q8NFX`Jl(9*&P?XH1ABPBJPY*#f6OH$Ae!NLaz_$WQE z@|`%h)8pQq&`X{q^oj@11@8^viP07RkZ{Qmduc48L6YRBEwk9R_YdecAX$uoDZvj2 zTXJ3UVKhc^(NVb=|3H$Wf-gkA-XWQzzUNM`(l=XHH+~=O=SPa*JN<%}wa>R5%b%7D zhbdsD`-Tm!myyh(7sBE!-*|+L@><_D2R4{CY3&J-j_1lRZa#mW!Zd0}Pmi8kHP;XA zjC?0BSpmi7V4V4WfrB#sxGj+(e(C)A$AcYb)QbZJ>ek_EFiOCOFvfXzWUt#f4US@| zro=kfGRiQnU?HM&_8aqdJR#Z!-V1UDQJNMBQf2!(Sq zGQ|IY5MBENdNWXZf2LUX{kuo(U3NzpeAhav6)dQjQ!PR`Tf&ZNn0`yMj|FrYI4t)J z;3LG+hDa-`>uYQF0qli4~|ahg4&gwrDaHhp8!@*w?&Y9AjKqB!56rcF+t z0Nn{8W476ePXy`+D<{IziOsp+Q_pQ>q_tNHd0rL91LFNxU&$p6{ED_8J-PO;Dxz;o zIv)C+nnSVP-z|szO63wS@omCPQqQI7Y-HZDHN9vQhghtl(FZ8yJAeLcEz5tt?W(P~ zvD>=IA5^Ny#Dl1M)eQ~2M~+xWKg{X+hiUv)`*`ZmfdiE!&h_SRC;ohjlGx}{0=*9e z49UM#VAp5b#(k=IdBVmShh@g4p!-%8yJ(y{4E8^|RczCw^3vPk8W$|5tF`CTdEaFj zuDz!huR{v|#i3KA#Y3O3Zzb*R<0G$v75!)DCfctAg+JjFW!6>Rev_L!#y-3GZJY7T z+CHf{m0(d3#BB78?p<7Q1vpUY6kTOdRZ#(Rh48TRlr?OpXa=|??Ei#C+gvaBVw2_a*wIXf zxH3=oAqCg{;tu64uh;uO54~|Z4K%DJUw`=9ltNkZZRhIvbN|`Y*Ft_)VGkNubI{Hg zk}IZevmxS~b(nFadkiW&xwOC_J#8CuTRz8XSV0N$q>YF zM<+QN-j-8hEI=g3_wDUh=GUDk&v_3%&o>Azd~0j=rI5}72I*?WDvrjp`p2IM3+KCRZRD?GV>7!pPQ6Ljon^h7 zS^xMY&7-_QL1I$NoSp+lKbfRbIwqhBfF&NDr_bYKG8Z~}8nmKOf95)2JxWq#QH&Ui(Qr zj`9VS$lrUK=(MWh9ms-9WMlOMl3P6$yr8`HXizz}zB9Ny<(JN8w#$hQGW)N3-ShLU zXWXYt%CV!utpQ92NAczHBp$`uxsHj2=QhQX#T*`5z)Z8U^CnC6y%dtJ9L&$FVpcm- zvg2fTv0O&Dme#vh>DeJNGOLz9PbK_@enp9ZOB=Ss%l7k@CpGcN-rx2{fPX-N>Mv_o{hTvF`a^CIo*%bf43kM`W~e%H!XCxR0Ql@7Kp07LNRbtENMm>qUZr)Vl;DGtO? zY1_-)M>TN=t`H1l0IUTKiyK23c@k6avX>va%Z$Z86o*lN+r72)OHv3-do9C@< zhD7-ux|nhbo@R9tx>#9G;c3XY74FVl!g){ITqWsjyY-e(HbynXCU`5eZs< z!MU;b=nSt!`?K(!_z+fB_FpgIzCKfX3OiuLY9sm0_*h)SAVBV_bo+elxp-lO34Fg7 zR9TWSU2qC#zMqxr_6i@I+92lHBEv&KiEXY3f({;p5|zqvbZ4BVG#= ziq8Wq+Mev7Lon_$i`WX@F8-ONypg(%oWCIjluMpRRaXTXa3IzXP(iD z)0TV|Ubu!RN|AMkiuM_*NHJ1AvU4h{k76B`2fC*_Ed;`N-g@^>|Gb_b6@|qJ zVReELyYZ_3lfJ?ks(AjfIECbl&1#k_Smf5oYRyzf>cF=yX#v z3w01q1?sR^f;I0Yw7Bp`qu{IRux%cdqk+~$0^#0=D82mmC#3oqzzY44%q&f+-;3bA zyDO5kZk$glE8*8&5!n8U>J8(gPt8{fZSAWlcofdxN@;zjO>@w*V*8#!an@Tp8F~vL z@qvHl2EurxAsJ7*Y1?hS8sdBG>r?#4GLwUvFT~0xDgJg|eMO$Am0R0ICZK6=-yVVE zDOy~1q4Z0SFQ(m7g$*uK6(1r`*k=WCC+84$-7fxm7W`}fmgm_r`KT(rjG4(m( z`gi;B2e6Ao@AIuhN{(jo!Sq?Tt?0gK@3vZAoFAmPX9`Rwh!{iTjt`Hw)cMmcqGk`@ zG*cQ6c-nsfc?kiJUqPlQv7VOtyF2IEy5KL89G#|#ok&0GFi;Z`2|nxPIlM5z-qj;juV(;?)O^i?MmpgFxX3uuA#TL_g~y0 zZ^Do(<>UJo4>U6fPTWYN42U%e!TZIM&%aGeyD~}wCCd;Wm^*$@C~jFlZqKZW4)j?3 zP-c00*>LjV*2C{mKo)j?4hpfD=4D@WeuFIT5KmG^d_^hA-liGhAwEx*@83NUl&&>b z@3wZUxZ&gwRowm2eK7|Z;z>7(2M3Hm^&@;1KXok?JY@4;&Eu9+g}5iL=idGR&>ct^ zdT;q$y;eK5WP&tC*rxoucXa1MFb{v2dkRz5Z(H`jpDY}WecQKNZH*jX$@&tt9f^j1 z#u2?e7CamggBcJiqO(?9@8oayT!4`QU<}V7JzllDif$o~=` zzdJcZs<7#6lqc-m`4lj+AWIICavRK*YHP25G~bbD*Q_Vl`*yywP(@z8{NBXUliCOH z8kx-ukR~%UHI-L9wA&>Pgc`6ipxDJ`6C^2wJ%OHZHke0%MfsfYGVf*_TgEZ@0-Spc4t=)a(R>b5%x((w5aP%tWD z03EsEd%p4|8Z zjRQj;8d z<2hJ$|LF)Fr8nl)-!IPueC)E-LuNM&tEBvNGM=Z&0BY4s3IdS#q;Tuu=}#I7$Y#SM zbw=|jK*wlJ_r(DBb?(KF!g1?MMQM5;JPrZjjNR0A)9u{(4|%GGTneOZ=fWYD2M7A9 zqABQAXd2Ha?b-GQY8Gftn8Cu-crpIx&()S={A2_9_mc}ZPj4n3RQ zX3^fgt|^?dsLcAcz=^PsJ%Wg#zwl=~;bU%?hkn4FQrgJi;8)4spWhrtdO+FwnX!iG z|7Mn0-P!trb!@Cxgr_FF^+?T`N#Ley2?Ol>e7*aXz$zdy!1*R}tp61F2*^V~0W0iI zTO#5b2XtV;B}^Ea3>6%4IU0-_jB-M!�`FG0gowi&!Jzy&$N>#c##5RQPIl^)x(* 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png b/doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png new file mode 100644 index 0000000000000000000000000000000000000000..49e4abf1ca037631a0b229576b7602f1867ff837 GIT binary patch literal 106100 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 H<_G^DFGyWo literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/visualize_cliques/visualize_cliques.rst b/doc/source/tutorials/visualize_cliques/visualize_cliques.rst new file mode 100644 index 000000000..b2ac037fd --- /dev/null +++ b/doc/source/tutorials/visualize_cliques/visualize_cliques.rst @@ -0,0 +1,91 @@ +.. include:: ../../include/global.rst + +.. _tutorials-cliques: + +============ +Cliques +============ + +.. _cliques: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#cliques +.. |cliques| replace:: :meth:`cliques` + +This example shows how to compute and visualize cliques of a graph using |cliques|_. + + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + g = ig.Graph.Famous('Zachary') + + # Compute cliques + cliques = g.cliques(4, 4) + + # Plot each clique highlighted in a separate axes + fig, axs = plt.subplots(3, 4) + axs = axs.ravel() + for clique, ax in zip(cliques, axs): + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, palette=ig.RainbowPalette(), + edge_width=0.5, + target=ax, + ) + + plt.axis('off') + plt.show() + +The plot looks like this: + +.. figure:: ./figures/cliques.png + :alt: A visual representation of the cliques in the graph + :align: center + + Each clique of the graph is highlighted in one of the panels + +Advanced: improving plotting style +---------------------------------- +If you want a little more style, you can color the vertices/edges within each clique to make them stand out: + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + g = ig.Graph.Famous('Zachary') + cliques = g.cliques(4, 4) + + fig, axs = plt.subplots(3, 4) + axs = axs.ravel() + for clique, ax in zip(cliques, axs): + # Color vertices yellow/red based on whether they are in this clique + g.vs['color'] = 'yellow' + g.vs[clique]['color'] = 'red' + + # Color edges black/red based on whether they are in this clique + clique_edges = g.es.select(_within=clique) + g.es['color'] = 'black' + clique_edges['color'] = 'red' + # also increase thickness of clique edges + g.es['width'] = 0.3 + clique_edges['width'] = 1 + + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, + palette=ig.RainbowPalette(), + target=ax, + ) + + plt.axis('off') + plt.show() + +Lo and behold: + +.. figure:: ./figures/cliques_with_edges.png + :alt: A visual representation of the cliques in the graph + :align: center + + Each clique of the graph is highlighted in one of the panels, with vertices and edges highlighted as well. + From 2fb246e2ed915c39ea9da02ecc1077667d947f1f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 16 Dec 2021 08:23:09 +1100 Subject: [PATCH 0779/1892] forgot to adapt one of the scripts --- .../visualize_cliques/assets/visualize_cliques_with_edges.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py index faf3b9f11..f677371fc 100644 --- a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py +++ b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py @@ -12,10 +12,10 @@ g.vs[clique]['color'] = 'red' # Color edges black/red based on whether they are in this clique - # also increase thickness of clique edges clique_edges = g.es.select(_within=clique) g.es['color'] = 'black' clique_edges['color'] = 'red' + # also increase thickness of clique edges g.es['width'] = 0.3 clique_edges['width'] = 1 From a53bfdc49ad6ff817fe96dce8b31ab9bb9c7adc5 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 16 Dec 2021 17:27:23 +1100 Subject: [PATCH 0780/1892] fix: few grammar plus edge width --- .../tutorials/erdos_renyi/erdos_renyi.rst | 8 ++--- .../shortest_paths/assets/shortest_path.py | 2 +- .../shortest_paths/figures/shortest_path.png | Bin 27685 -> 29371 bytes .../shortest_paths/shortest_paths.rst | 33 ++++++++++++++++-- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 116551bf3..d38c299d6 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -82,16 +82,16 @@ The received output is: IGRAPH U--- 20 35 -- .. figure:: ./figures/erdos_renyi_p.png - :alt: The visual representation of a randomly generated Erdos Renyi graph + :alt: The visual representation of a randomly generated Erdős-Rényi graph :align: center - Erdos Renyi Random Graphs With Probability ``p`` = 0.2 + Erdős-Rényi Random Graphs With Probability ``p`` = 0.2 .. figure:: ./figures/erdos_renyi_m.png - :alt: The second visual representation of a randomly generated Erdos Renyi graph + :alt: The second visual representation of a randomly generated Erdős-Rényi graph :align: center - Erdos Renyi Random Graphs With Number of Edges ``m`` = 35 + Erdős-Rényi Random Graphs With Number of Edges ``m`` = 35 .. note:: diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path.py b/doc/source/tutorials/shortest_paths/assets/shortest_path.py index e79b63315..9144c7881 100644 --- a/doc/source/tutorials/shortest_paths/assets/shortest_path.py +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path.py @@ -12,7 +12,7 @@ if len(results[0]) > 0: # The distance is the number of vertices in the shortest path minus one. - print("Shortest distance is: ", len(results[0])-1) + print("Shortest distance is: ", len(results[0]) - 1) else: print("End node could not be reached!") diff --git a/doc/source/tutorials/shortest_paths/figures/shortest_path.png b/doc/source/tutorials/shortest_paths/figures/shortest_path.png index 7c77c04e0cecda3ffc3d1b06626701efffed84b5..b77a93f2200756688757df66162235802ccc2d82 100644 GIT binary patch literal 29371 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 N?AO%Oc&ug}@GtrOV|f4o diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 1cff2be95..1f7103a57 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -65,9 +65,7 @@ The output of these these two shortest paths are: :alt: The visual representation of a weighted network for finding shortest paths :align: center - The Graph `g` - -.. TODO: Add in edge weights as labels when possible! Matplotlib does not support displaying edge weights (and the develop branch implementation is bugged). + The graph `g` with the shortest path from vertex 0 to vertex 5 highlighted. .. note:: @@ -76,4 +74,33 @@ The output of these these two shortest paths are: - If you're interested in finding *all* shortest paths, take a look at |get_all_shortest_paths|_. +In case you are wondering how the visualization figure was done, here's the code: + +.. code-block:: python + import igraph as ig + import matplotlib.pyplot as plt + + # Find the shortest path on an unweighted graph + g = ig.Graph( + 6, + [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] + ) + g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] + + # g.get_shortest_paths() returns a list of edge ID paths + results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] + + fig, ax = plt.subplots() + g.es['width'] = 1 + for edge in g.es: + if set([edge.source, edge.target]) in [set([0, 1]), set([1, 3]), set([3, 5])]: + edge['width'] = 4 + ig.plot( + g, + target=ax, + layout='circle', + vertex_color='steelblue', + vertex_label=['0', '1', '2', '3', '4', '5'], + edge_width=g.es['width'], + ) From fbd654ebbf66b6639f7d3f48f0214953756e6604 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 17 Dec 2021 19:40:21 +1100 Subject: [PATCH 0781/1892] Tutorial on online user actions --- doc/source/gallery.rst | 2 + .../assets/online_users.py | 63 ++++++++++ .../figures/online_users.png | Bin 0 -> 48823 bytes .../figures/online_users_simple.png | Bin 0 -> 47195 bytes .../online_user_actions.rst | 113 ++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 doc/source/tutorials/online_user_actions/assets/online_users.py create mode 100644 doc/source/tutorials/online_user_actions/figures/online_users.png create mode 100644 doc/source/tutorials/online_user_actions/figures/online_users_simple.png create mode 100644 doc/source/tutorials/online_user_actions/online_user_actions.rst diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 16cb26f8c..d29d7d2c4 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -16,6 +16,7 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-maxflow` - :ref:`tutorials-shortest-paths` - :ref:`tutorials-cliques` + - :ref:`tutorials-online-user-actions` .. toctree:: @@ -30,3 +31,4 @@ This page contains short examples showcasing the functionality of |igraph|: tutorials/ring_animation/ring_animation tutorials/shortest_paths/shortest_paths tutorials/visualize_cliques/visualize_cliques + tutorials/online_user_actions/online_user_actions diff --git a/doc/source/tutorials/online_user_actions/assets/online_users.py b/doc/source/tutorials/online_user_actions/assets/online_users.py new file mode 100644 index 000000000..12dec7210 --- /dev/null +++ b/doc/source/tutorials/online_user_actions/assets/online_users.py @@ -0,0 +1,63 @@ +import igraph as ig +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +# User data (usually would come with time stamp) +action_dataframe = pd.DataFrame([ + ['dsj3239asadsa3', 'createPage', 'greatProject'], + ['2r09ej221sk2k5', 'editPage', 'greatProject'], + ['dsj3239asadsa3', 'editPage', 'greatProject'], + ['789dsadafj32jj', 'editPage', 'greatProject'], + ['oi32ncwosap399', 'editPage', 'greatProject'], + ['4r4320dkqpdokk', 'createPage', 'miniProject'], + ['320eljl3lk3239', 'editPage', 'miniProject'], + ['dsj3239asadsa3', 'editPage', 'miniProject'], + ['3203ejew332323', 'createPage', 'private'], + ['3203ejew332323', 'editPage', 'private'], + ['40m11919332msa', 'createPage', 'private2'], + ['40m11919332msa', 'editPage', 'private2'], + ['dsj3239asadsa3', 'createPage', 'anotherGreatProject'], + ['2r09ej221sk2k5', 'editPage', 'anotherGreatProject'], + ], + columns=['userid', 'action', 'project'], +) + +# Make a graph with vertices as users, and edges connecting two users who +# worked on the same project +users = action_dataframe['userid'].unique() +adjacency_matrix = pd.DataFrame( + np.zeros((len(users), len(users)), np.int32), + index=users, + columns=users, +) +for project, project_data in action_dataframe.groupby('project'): + project_users = project_data['userid'].values + for i1, user1 in enumerate(project_users): + for user2 in project_users[:i1]: + adjacency_matrix.at[user1, user2] += 1 + +g = ig.Graph.Weighted_Adjacency(adjacency_matrix, mode='plus') + +# Plot the graph +# Make a layout first +layout = g.layout('circle') + +# Make vertex size based on their closeness to other vertices +vertex_size = g.closeness() +vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] + +# Make mpl axes +fig, ax = plt.subplots() + +# Plot graph in that axes +ig.plot( + g, + target=ax, + layout=layout, + vertex_label=g.vs['name'], + vertex_color="lightblue", + vertex_size=vertex_size, + edge_width=g.es["weight"], +) +plt.show() diff --git a/doc/source/tutorials/online_user_actions/figures/online_users.png b/doc/source/tutorials/online_user_actions/figures/online_users.png new file mode 100644 index 0000000000000000000000000000000000000000..2f0a09d6835654ee7b65cf4c021d4b47d78bb880 GIT binary patch literal 48823 zcmeFZ_dnPF`!C~Rc3>`6$d4T(Rb@5K_#NJt7jTIDD%MQ`q2Y^KBrSppNKu1+?|q?npZ)Wl<$<5mFMJ~lE?YL_i?vo z8zVbEWuvW^*OXDq^8MYrrd>skh&uiK#q-zGP@P|NFQ(_k#$)X^xnf7~KN5km%^6EG#T%xw%VAOYa9Am&1Pt z^upM@Y0QEUdy*gaGBDH(*1i&On`1YvU$&dAaJ*q;w9iWCYax3G!%3ACZN82yi$`&B zHz_qv;!VK_b-&an2w98P)C`+GarG2^gn~#RN8-Up%;PU)ivSesZL6#E`GeV9gtazjd!0nwsQF zKlsqFj0fYK$=IGdcW!NMw*Hh}-V0erx*rx@ydVG8gcz?Ec`b&91XtSJ`gtc{FWf3KZI`No`YaB#5N zj)B=*#)8NMD)N?=rx=Bt2BJ>u9O5>m2pQp*Uog^N6sdjphVi{}ilBMcj*5zkYEOB* zW89eK7PF*Z_*p};SNv8tdgqoo_HK~KswLM}^-oXr&3h2!_{ z@+WE^)E=J@S#8MPOs5swc%xvU$?bH(eQ_f0(u3_Bo_BCr1>#16^o)&JLpawjDjCzN zZceYH1{U^k^7DsIcXv!J3?EBfTCV0~L2gnwL%NeWs5@EfQ;yp>rw7|+T=3M6=(IG& zsK-36^DBIBrJpul*^N}CO{6MT0TB_Aif4>Fzdl`gJ-gV`Y}K+oKPWDE{H6UP>UYlF zOrq^460Ahk^xQHmm+gKPxF@t9VPvdLH!Q0P<6>G_S>ZKn-1@_lvHDNRgB?S|!x`p3 zIcu{sj4Ho%`H1@(A177vRA(9XP7GV(L&Fz+p;*!lvudCt>1*BI*6} zr@Y5&Q{m@_YZ)0C%)GoWtU9x8=Z2IIaOum}zY!sI+1wBb=P`|!4dKkm%?;!+y?XVH za5Yvc5lgaz`bcwRpDL}7uP^zo-Mgz_aO|UTmgW`|)IO1RK%A8xr~I7+KJ_iWvwQ^a zV|>!VvA0+7=8TnQn%$Do1$}eCyKyvix z(YvuyPkxV$)nr?Bin^~Yk+dZ!GTHt4CRN1oDX}T@+RT@>%|$-asmAFt|H)sWPY!aa zWLs*Dw4{8;k2&~74W{!aPCWG6e{%1UBXv*d&)?0t#D#EptDR-8ZB-e-RR8jvQQPO+ zO!K3yncl9dVb4`ii!bF;~k{7i+w&mK7l907VIo=ladAoOscA?wb^ek z2dETzdMGSysS0MJzIyeli<{fb#=3j$0@h>uZaVL*EIzDVMR&K}=&6oe`@baYY9DD& zo(PD?sko(=cT_Ja#6N`bK*LeYZb8&Znn~?A* zAb?sUP5-AZznH@i&D70B5|eK)9wTn27shpJ`HvlYyS0xx+N>#_M7PLO?~}p=DXsX> z{d=i9X~bDm-oIzxSpLiO;aZY($^C7lXZiTzu$al(S$_B@^E0H1FVEf^YyV_%Mo(P# z{pwko3LKPU+}uGYHBy!0WcQP}%?*|0IgZ|HO=U!E_4k%M$jQqyf73rYDmR$i-d5-! zny@eytGt@pb|B;LdgsN|)i))ZzZl0DzLD58>L^IM9NOLKP{E?(G_j;tY|%}rFShe~ zRpjvqQLZCGU;Q`440UqY$GsRYO?6%zTo?6a$em?<@7mgNQ|-g3yuvk}*tfA4CbEJL zZ*iYljpb|WXt)1c$Jmmp_x;_KU?QYd6C4XMcCTvx|#My8EKF z_Gjz$_NdxVru8K0A3v^G>L7n!1(K67T^MUG8*NQ9>nSW~S#TU}X~=W55Of%dZZ|PC zt(@+!%=q-F$?~Ln@}Y#QuUSrmVcScMey^)#fi0T z?NhC4`l9od9Tof&jx~{zEetL4UFln9Yi#Y81=K#2E=^eRS^ch^7mfdE`gTF@a7Qxp z$Thk2lh+<1gMM-tRtY_=BONavp84yQ;$dNzvp6K%f5(TJwIm;&9jsj)n~hg^B^`Q7 z>sIsohJ%bK)j>~m$qul*ZcjJd^6=rqO!GL8dcDD#a9bOjXk@Ro)ybk$n(23Os3UmI zN|EAt$5-Zt%Tjbc5B(|-YE9Ma{}yu6VWj!-UEu!G(%)yQ-CSKsSvB>odW-KxY!yE7`_qM`I*b0w|3T)DP^@R`oIx7S*2bJzmPQVSoW@>BhI(=d!PL6D)J2JP|!9n zWxCita<%OM$4a$mPm#Oa(CSgy3+jWv_{1zJ_YZD7SY=B2tGbVR^l#UOZ z@vy3@N>S8wW}tekrzk2>H6aKY{)O(}rUXS(WNVTOf`Z(ZZD&s?M0or7 zY$Ks&5=EAXD)rfE@pGz=y>DvD#$R53_<{rL>_h5z8jP0_=Snf^dXW*Ctj>jG5!qZ( zE1!lZ4@b_ne_wUJowc%SH&sg}X_aca(*4#qpOp+J^yZs7oa#)ObPm?`mCPqeN=e_! z9vvPww7juWtNM|aOFt4gV9Sq0Rkq02uay(kB1Js}8{8N9Z~v;P3OqK9%@EsMn?28{ ziY*O_B&B6xY|k*-0nA8oX7h-Eoj1;H@5DrER`;)8Z}uLSwOL!TO&Je9q40Zo_Ai5o z+l%jET=olNTEL2=?ApA2;n@L?pFWjBf*g6;rIkL(+I{&dt9za9m~O`NOV*ATyatZa zoDXuk^O-+V>`T-Mk(H^=wf+A38IL_xO)OTHwOi|6o0vzPIdu5&Y}3o?wG3m%w;GnQ z@j9xsQkN7BqF%mynKp6$+-dF1UL={WJjatI*vy3nd_7$~J*~`J%0Uc@q^VQ2k`{p;pq(A+w@sZ0vlao1Gn%|mss4WS&^ z%>vEVjViNia+TB;KWV)J3@);SSx0rXzS%k5{7df;9X*fv^7dU%{rNgQHo6%W^NyA7 zV;q|~{hRBFS56*z@o-auSw|+vvuDqMJjEiGw*ut14(y7i8UBjpZ7=c?Q+UN+UQ;7) zVX&r^kDtw~#Jo0y&)@#_4p}>D%pFHGQp7#<-j*G)X-tb5d&HjiO%`pomkEfRO~tX9ZPenEJ2xvM1$uWEC*5Tm$gEqgZe1_Z|KbvOT}Mrg)}kf3q`CP8 zdJ6MwgCb8x4Gj&-1E+iw5=?`96p$t9%Cy9xPEyYidU4C}fbIk=ITOD|82eRgkKi@)fa&pdIFD6mQN5N^xw$eFp zO0ziMdGft_3f&GWhTgi@LJ|DW_MiNCXI|S)@LIIrC;Dwq!oGg3iTutMU{g8C^4jYO z{r}g4erw}KYfpGr(y?Qmd@B_2`TL?YB)r#++l62;T= zX9k*yD;(m!4lzJgvcPpALqkK7i;o^Y4INOV8#udckj6^C+y;!g4O-9o~Eehiw2u; zx>B}rJe01G)z4>g+E`bv>Zt4DWRJ$(fQ{jJakNK4I@^gJg1EKK#{z5}dsB^1m- zwW!q`D(}dT9Z0RnxVl9z?5*wO$jyiR&V54-Z?zW%JlRj2*uG`UmJ{+Xi;?_-Q$m*( zZ;f|kMYxh*eo9yVff7uZoM?Jq#38BwHW#9a;H6ED? zYhNB!7nonZQAt5g{`{x7H%+xHh#M9ygtz@z+c`_CSv&KzgZH@JjOMW(wGJA7(8;fy zev$MUgFw*G);gWf)^RBJ=vlnm5g{7VxDF5-}`MS>ep*&uaXX71LU2c(wa9+F7k!hA`)ftMW z*u3s5=`MPHe-z)3cb4r^IIM%Tf!tkZ2Y2Jj%=p8A{BGM{(Kj&g6+KyOCPhU>;2{Ya8C`Y`Pm zIdY_{(Bl;%p?_q=51n0d=SgpwFrt?&>_8AGC;eo&U~?B(^@B#*v;2Iao8Mk6-^%Iy zcynipcGmA!t(}R#mMUpe52Z$mmb|Px{gTI&3jOout^8N#Z~yM=y9b0!l4bsr=;u)M zhEC<6uT~-2{3Vvaz(58er(IZ^RQ&>3Y^aT+W1R9^X#?RKSvQl^$J+A)C`O&1r&Wce zajX^SZxc2&&S&DVHt?1Z6^-~QFM6Dv-B-kYAzD2Np%ZP>SDKTbubOa`QR}A!dEg*H z72at?xtgAv``X$0>htX$mBKr&YMlG8C8@8EWLY76ZS6kPHXY&dLA{;sFB#17Ts|3mz-HCMG7lw|$VzRjEe9u>BPHt- z+d;v4zzs>(*4}<~;>RqKRit_A;Gfa+{HDuS(Nt#D@qz$y-`hZ{g1L?`^yFbaR}>1+8}M zD$ANxydpTFu1rg{k^lIoYGqJaV^Cw9EHV}8SB0zVBFr>FgLXOpa{=xPQp&trn5Y;9 zx84m7-p3ijskKAY`{6@wy8#)K`Zo$0cKerI8|5v>$BOcMG)NUSh20MQ4OsaRCwGu& zq-A8tB_8hTLpHhC=w0l>MCJR~-@kd6FNaQc@-DhP;_tNa^{b-yzFPTOTl@6kZu~O%6C3knOBE;FFwr4S9mL0T3AXs$F+~aoj-MO;D{pne$6~%iqzE92>y+Y zjp_qrecuzl?h*HGzK9%fSl&Ex?E)HRK8u#KUK?boy3@yQ$CRoi>oEyE;-+l`!=2?we3G69~I>l4~pjT!?ppcd(&BZg?F@gII;oA zTHdvRTA>5A!m`Ep@#DVcL{&5mM_AzfyD^U^^%t1u*<+ zDBD5uG9uh4kniL}X=zC*sXcTIk}@`DN%;9)6V(go#O8-CfocUL3}1U!9L2nVI<`C;Ni^o@`ucbv1{=*5|;( z=;gj6|BzEronT=hJ9g~YsZ*!euYI5eqr&Pu(PhwmTlV2aqBQ_x@K`%#5NO!=d#J*` zVta(qsY+ULUqx`Z0DAzzAb^Yv4P!=U zRF3QUT)dl}e)i6tJ5y6ry`W~WggbCffcC2aXFf6+kOyYqRI)rJ7zy*N2;_-p?&C-S z`}Xa#)6`PU5O?KNPxgKL_SnxP4aKamULd!7VPOaL_4T)I-%cOw&?ykRa| za^L6ufTr?n{z4hG*pTH2Gc&g!#a$LXx7CHyK#GQVz3YoB_+Re8p29;uvY{2(Hp>3B zH9uPGCDkM^+}0QF|8-4lLa(4^HQE`G+mIo#1Kp!U`^TG(>ngrapZ-C}ATEgbdHk4S zHyv*=4)OhMJ4f=qI2`BmDRvMuafuwGZ$7rW{6FP9Hd}{nanz zr0e3s>G;9HwvbZ_F+n%e>nxrG2A-p&++%3CRXC@zASuknWpul8VBi3k(%mTc#duWh zftqmDRxT;uT~cJxG8(^%yz1X8zt#L=Oo6JPmfGXHlG362Mf|wGf@nc#N-Vpu``q2P zZ#vsI>jm}2yrdB`pndp(^Eu`yH}-*W2kVJiCG0xmE$&0vH!*RwJJ0bP50Bim8@FHc zAu?v`^}e!4)Nj?3ay{1tTUuHo<{zCteOmR)8~XFsz`_?7Cb}g;$3mN}er-=+(z&72 zw(;q0_*<4^x$b{hRzF+z=7jBF&&a&p^9C(OFhDh}+ct4y%e^F0d42u;60O$VE*opx zCc534qOa{ZW$&@hU`qn79^GbTw$CS5mr=o@^#yv+Sru(<7ak{F9coF@!MfwHAOXc7 z&mt`QdwY*AD#txE>O5}cIje^kI}3}rz0=={r}UaS zI{kx#()iFSw0uEKig)zQsfm*+v~enZ~tSpxtHnILhZ>aCU2^R zJi`vPW*z7IaLshlnoH}1qA%+SY}A#_ja4obtc0Ey?agK#oKgXd3`-B073h^x)i`j7 zW~*OK?3e08H%gQn27&v9g`$ol&6f}y$(k9o$=Y|)G7pjUi?~dY5b$=q^D?M%AhMsy z2WE4x|ID>F&9>?(@gHBUGJD14!}-jT9Is;;n&!o!7py}enC`J zw48cx3}@AcjE%>ZkL?I={{b$&y`Q_JHI@o;(Sc)a*?9PV(^kHl(tSN=XMW*lNR%2LQ_OcS}F5>!eCXxj-R zF_)>kNVn&p?mXOec&2-uB2c@EgJN2%^YiTl!?K5MZEe>rE&WqcP7^#6cuMVY{UXoW zx#1>4+dviuT6v0Ul8)VFO}g0-D`i|4%9z0PicKr3=bNzo0rT@#z<1}lXUU3YA@?4bJE(sIDa$O!1E1m$esxN}dTNAr8-EocHin$};1 zlI1ehTjKmPq5)Nx+o)n!?T7t~6WvB_>4sn27q2FDqdgvOO=F^>qI&u2Rj`qpC8jKyc@_E(U@hb z*g0dBgyE?y*o!q%J|1`71bCzIM+T{-7)j!TM*??S&q z%_{>FaQM7+m-Ej9bab-%Iy#XNSussNlzY~-gT;%>R_81_Fm~8VBKC?+OLrU_DJLe zuGQ2@s3EVP`)zMZrUM}npxmte<8gGOeOPzo+W?$o`;lf29Jl#)BVEvGAc9n4B`Mq% z#vY?U@tD*^Uwth&_NzdrX#xdMElr;g7#or_xWKq-rC%pS8tAJD=P}?Lx&_Eel=^9l zY?Vx1sa;QhOD9I5lFx03up1urMq7C`{tQ&xqGq4$#=TeH|9-JbJRU@3#w`QDw6qP&MQR1ETB zR$rpaY8MJmJUEwRozG_)ME6TE3kx$q>H~7GDSvV>*S7zm2}#4po8Om)6QbHanNru) z)sY}^+06`GvF<5M5#TvYLvs;{!q&;jq%+&fU@ZbXP1*31u<#6{q81V7`gNw5gapO9 zFWK5z&qg~U=>OJ#9BIBLzv1gv~6bW^h$`gV7CmbbH~(Cu-e z&$fya@uwI!g?`biA1A*%*;DW*L3{s8VKbHoJE%8qjT_LBP%{d?=;aSXNBRS$Dy2lv zfS%-!N`}nIfxR}{?fXi%p}muYx|5!s9u3ARQqWQM)8>yD3E+9#p&v1d3&AKeH8nMv zXToSX)!0iu>q6Rxup=%hxfLm?$&yLP=@j%uv<#2V=;b{>t;7G(q*fN^lVbO71)DGE z+|JqbUc`|;)DpYrm=N!u-x)b{8dnd?{ryIDXGzbb-COLIe%C_~(Pr5N9`iwiC9WdTe^221enL)`Ls{K#6Wv(5p-<-_X zeJU6!;{MRUYdxefP7W>JrT-+WJz;0`8b{bR*1NyB@)T`u2;n$abagSH&>Ru-T&rGO zGn!ll{JWRql_}O7uRsr;sXdoxVx|j_2=oOVIQO5FtT(@h#z7mj3m>8P7_qYfoX`Aa zLE`T2&cMKs-)O1$-Y?xffc|YCg13 zWrE*K+;UX$jqn8lfxhA4@ZO+l=%ep7Gg#u|<2ALl8*w|eJth5>ib~niR)bFuNlxZ% zrYr@1=Py!UdXUpI%{0Qt%E^8IZvc~d_Q5ozD<{`T+h{Y783e{I^%SIJiM$HoLx4oN zgq5&Z@cV_Ht_QY4SO24{w0CHz3e<<_a@QkjCY5(Gdyt08|4AhUl>(l-e^Yz$KUSvo z0d&4$Z2T4L_UgJ9x@q(}QDYM1dchI}#>yBtJ8doRLfht2Sk;RapTj@e|b;R^%Qg1a^tA2EHf z>qp}X&5dTyo)Yvn#NM?eYwcnbq($zEjErcL9oGJa`!-n)xth^eMrsDg;FnW|s^4nnnJ64ElAVlSPqSO)F1bjyw>YwT> zi@M_pLOREl=ZvwIrsi4jc6rW|8`Xayi#)_hQvPJ30MRx0y4Ui|AFaYWxr5W7oA85x z*Tym%35X)YwWVpo19bcL?MP3{dlm^fay-+fYknI3LK3#Mi@c~#Y^)c2FMqaHYHtr2 z{ktKQ?}~pup!F#@O{Rm&1501COv7Z=-5E`z%F${mZR3USZ4JBva6B&8TK zEZU9X#yEIWHj{oW-YECm17{hO<4kFpim1bPW(Fuou&*ox!!G8jo3sf|%znIsPoc9b zH`qBmZH`lPYlQ*TGwOSrLV_+}-iZDm(7-}u6B-s;p{8_0iP~&nBQn;Nd>EUK)Yc#R zy>SF-*$;4}wx_A8N=D&=-=_Q2RG$Q-oHCf4vL>jlAl9Sang0Izn1uGswb0qicSKk7 z9`tOtyFR)dO8CZDru^mR&6z=05~~%j&f|@XlfTGpAC!m+H!Yt7CL&V*K<%qA9M0$X zqnN!3HIne|00zrAcsV%mG735rmz8Y+_g(wPnZ(1x1Kcs8TmlIH0hK|7CLlM6pnFM4 zqhUo#%qn*yNo$Ux_ixL0=2D2@ZHSQPL#oTPXnkf>`D_m@?Oe5}daCZ@&!5llJaCFI zUVzBMYR)z+z;;BS8FWwFhy}^cxruI_QCk28*Y%aG_)z%fXz1zXh!R6hop3Q@Z$$R= z;)$DCHJ6|@=?c*wT(FK5d*T@{&pW)q15`6G{2)iJ9!Wzr_QvtrS;A4lKN{I=V--8x zRQ%(41!MlcBXp%dKe64*X(;S7jL{VhToUn&KX9Opmi--tGI0DC&vm+;J9iR56)0t& zZ~|C+?R}Hkw;Jwa17Vm7i5~y^YZ0I%kk3LLIlKbWG$1^wTYRH9%1`CnTXxO#;s5e$!S+mum z!FRRPCqX-c_WcBGB@tJty1C*wdgSEfKSoAjr2_94ic~s1^7CYE6iTwu?c4PPx4_54 zrcqc=tqlV0X59}@@2%S!j0V0cX3rNnzq;A)m7tmH*K9pwm9#ie#dy%W|G{(uoOIjR z*w`TDR&A`WiqUWITecO?{P|8eM39Oo7A}Ks_;^!JSVUxcW~PzSiv%kJ9#RCGMIRzt zewTC$@0KJ{$NE^BJRo=;-!LwNy>xUDLo&sXRj_}n?e0H5sHc2b-sHFHP>Pk*J@o3F zk#y|1*Ycl(UkVDKbUrotIi z$ZW&hb_%_Su}S=>XEmGEQ;TK?s}HVq-xD?lIF#5+w$^6*jPtFM>UKEx zd4G<0ES6Qtt#RbrwKS4_IhENhj6Zx)P#!FLu5&Vef>%dMCUN1m@AL28o zC922W_rVdJ{|RV>G*`H{iK+N=BJjG`T9 zrvB_au{h$bHCVGN{1a~j&#*yhiYj&85#OC!XiJJA*(21I;YHkPb&YdB65b7LJdBrj zKK6hyBp^J5?kW_ny;eLoztIw8DFU|0<(V2d?>wjRZ}|Gti;I;lEeo@Xds%!4{LkvX zFxH%+6NY}7jgF)eT{~Famx7L*IPPn=#F$ne^?L0{xGW__YHK>QS2gxG^;plxH>Lqh z6|aZwll@_UJkF{9dnLC?bFfAMc8=o=C%uN{nyVtp{0?_6+D^AIpJABqD-C?Wu;$E@ z=`jcsh*Wy5YzcqcY%`_`>A^V{qt)_888KoihpI5pY4ac){Jp60ya%DXq? z6cm&}R7D!zUl_-?+jdF}qMFRqwXc*i+&CF&9gS0fXX z_}s8D3FNVhusR`1r;#zZCU|fR8eVmw6RdB`Fgkp}CVFsJ^Jh-ooU_REAYGN24r?7` z8au-zR?1i;$Ge`$M038^s6L+0xIUbI9}iCoeP@c5CBaGK_q9z)qq_3nwlmfLsPdI{ ze4VJ)8V+_K^cj80uUZSU2GgTZMt`q&eg+RLn0BdEi7K?UTqaH^Jy9S*zs<>k}?~Qs37>H#S#=&1Uj`}?+?6naI*3E9{ z2eY_@1fS{4jYWU8*Mg4epFb;3@$9CeiidqcEmb!hOp;kP5+s!In}iV=SVv4t0v4F+ z*FxuE78b|q00)`XksL%%b!io;^OH$gh2lc4`?@TD{j0}1f1`MdEFM4hCpZ08|Jrq> z_lS|YWlNXWYDz3i|8{Qd7WKh{2f>ICkpxTDjjz6Yv|}uxl)yak19n&tJ@WZZ<9p|v zk#KZ%b*sX8*r51C39D+tis`mE@$}Uzdbr(;LAn^s-Q?JiPpiq`P=P)7uq3>IHfUA} zgEZ(eoI*0&&5KrT>G$weZYl6g$ACU!)%^JzTtB4tqa{OML9aFyd3kkwzFiOSSeQQn z)7w<%?V^ku<&-4%$$D-raQMaM%7=XC7Yogu0od?{ys=sw= zAIA{~Re+X!-|x;3H|;?6CCuMw`B8&bhh}kd6p;PVOfZ1V`U^C3%Ahb3Voj}wF^Oqi zWDM{T>dOP9lMG~)6i=kFcs`OpaX z4J_28?>0(|8%x!nA4BhW<>7ilVUyi&z z)RA=(9^|t6`T*1$ueo_`ZEcme(z}V;gk~*V#GPNtkG3x%%5!C8k+HbC`Y}Pyp-o0Z zTmfyE@C$?d)9$;C-L&k?ehU7TAW#97mJvfl&8>Yk>gifAX96NOg2VIvg9q?@5Z-lE zf1`EWU|FN*=&VJdmg>-6RVGtw&+~Kc*{QE{mKJdNgd;`gZurY)C1Mx=5#l;1){m#2E z=a@XNLu$R?H1=}P6)+(d!zYh7gb80Txbkn8^S#+5D0mTVRB-*ZLcE7(;)Os>8F>O-leua$+TM}j+K8qk@mYQ@9oF2A*q|4PZPeqze!Jf zakwSrRS=rI^5$l>ME!z)q~SkboSmKQ)CORP^5Jtgyo12N5x-&U=y;7FG3O(S<~%fL zr7)QC{D!G%!XbM4laMB4k?&t%4Nu&1UYRqCLmMEAbH5(|B+jz^<2Q&lFCcFOtcUFB zDXFd=4ldeJy(Av2MtfneqsYOaWIXF1@&xeTqhZC{`W%S%DZk@#LcOf^d zjFOi1hJ=>W6bs)_dpR?3URyWrr1q+;NcpwW;6xSjVWagg^|k$=R*zqP#^8rauL956 zP2lKn_)@%SCo}3pfBaA)mWS9W0Hru~znSU|(Y4nFUYmtv?C@Q;x@{tLN0WSe&Mbj1 z_F^|ZKRb?>N^(lde&n$7Z{K9mvnKu?9bMh#rRpu?`jIwLhKFFUJ~+~A4%n-=#@$+W zp4Jr(t^aFvy_bzEOT0_=C{zSPaLP=tE#%)BMCk}!$V%tZ-nGi~Vc%YcuPILoYkJ(p zTaS}Yxm%p)3^`Mc;{negjoF);E$of{NDR~5y%f%Ax-E_z+E>SCV`r$v?(nZsOv92h zq+*qzy|glRY^r?rwtm*J!~#l}QmdjTu#n2N#*qh}sVdTBskO1SE#Ws1U9i+%U#{R7 zc-C`#LO=H_O35KmuUO=-6%`|Srvm-rd}uU3TkGiy&;K214}Ot4Grebk!>lKC{$=

    569=ny6zm{M3m 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 NJkJFlhuuO`{toAlnvVbg literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/online_user_actions/figures/online_users_simple.png b/doc/source/tutorials/online_user_actions/figures/online_users_simple.png new file mode 100644 index 0000000000000000000000000000000000000000..eee2ee4e8f237edfae277bdf6404e29d16ce0aac GIT binary patch literal 47195 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/online_user_actions/online_user_actions.rst b/doc/source/tutorials/online_user_actions/online_user_actions.rst new file mode 100644 index 000000000..d938de141 --- /dev/null +++ b/doc/source/tutorials/online_user_actions/online_user_actions.rst @@ -0,0 +1,113 @@ +.. include:: ../../include/global.rst + +.. _tutorials-online-user-actions: + +=================== +Online user actions +=================== + +This example reproduces a typical data science situation in an internet company. We start from a pandas DataFrame with online user actions, for instance for an online text editor: the user can create a page, edit it, or delete it. We want to construct and visualize a graph of the users highlighting collaborations on the same page/project. + +.. code-block:: python + + import igraph as ig + import numpy as np + import pandas as pd + import matplotlib.pyplot as plt + + # User data (usually would come with time stamp) + action_dataframe = pd.DataFrame([ + ['dsj3239asadsa3', 'createPage', 'greatProject'], + ['2r09ej221sk2k5', 'editPage', 'greatProject'], + ['dsj3239asadsa3', 'editPage', 'greatProject'], + ['789dsadafj32jj', 'editPage', 'greatProject'], + ['oi32ncwosap399', 'editPage', 'greatProject'], + ['4r4320dkqpdokk', 'createPage', 'miniProject'], + ['320eljl3lk3239', 'editPage', 'miniProject'], + ['dsj3239asadsa3', 'editPage', 'miniProject'], + ['3203ejew332323', 'createPage', 'private'], + ['3203ejew332323', 'editPage', 'private'], + ['40m11919332msa', 'createPage', 'private2'], + ['40m11919332msa', 'editPage', 'private2'], + ['dsj3239asadsa3', 'createPage', 'anotherGreatProject'], + ['2r09ej221sk2k5', 'editPage', 'anotherGreatProject'], + ], + columns=['userid', 'action', 'project'], + ) + +This block just introduces the toy data: a DataFrame with three columns, namely the user id, the action, and the page or project that was being actioned upon. Now we need to check when two users worked on the same page. We choose to use a weighted adjacency matrix for this, i.e. a table with rows and columns indexes by the users that has nonzero entries whenever folks collaborate. First, let's get the users and prepare an empty matrix: + +.. code-block:: python + + users = action_dataframe['userid'].unique() + adjacency_matrix = pd.DataFrame( + np.zeros((len(users), len(users)), np.int32), + index=users, + columns=users, + ) + +Then, let's iterate over all projects one by one, and add all collaborations: + +.. code-block:: python + + for project, project_data in action_dataframe.groupby('project'): + project_users = project_data['userid'].values + for i1, user1 in enumerate(project_users): + for user2 in project_users[:i1]: + adjacency_matrix.at[user1, user2] += 1 + +There are many ways to achieve the above matrix, so don't be surprised if you came up with another algorithm ;-) + +Now it's time to make the graph: + +.. code-block:: python + + g = ig.Graph.Weighted_Adjacency(adjacency_matrix, mode='plus') + +And finally, let's plot a layout of the graph, for instance a circle: + +.. code-block:: python + + # Make a layout first + layout = g.layout('circle') + + # Make vertex size based on their closeness to other vertices + vertex_size = g.closeness() + vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] + + # Make mpl axes + fig, ax = plt.subplots() + + # Plot graph in that axes + ig.plot( + g, + target=ax, + layout=layout, + vertex_label=g.vs['name'], + vertex_color="lightblue", + vertex_size=vertex_size, + edge_width=g.es["weight"], + ) + plt.show() + +We added a few fancy features to this plot to show off igraph's capabilities. The result is shown below. + +.. figure:: ./figures/online_users.png + :alt: A visual representation of the collaboratoin graph + :align: center + + The collaboration graph: thicker edges mean multiple collaborations, and larger vertices indicate users with higher closeness to the rest of the network. + +Loops indicate "self-collaborations", which are not very meaningful. To filter out loops without losing the edge weights, we can use: + +.. code-block:: python + + g = g.simplify(combine_edges='first') + +and then repeat the plotting code verbatim. The result is shown below. + +.. figure:: ./figures/online_users_simple.png + :alt: A visual representation of the collaboratoin graph + :align: center + + Simplified graph after loops are filtered out. From 9ea92c3854ef0248da486267c8c5ec09a97f5a41 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 17 Dec 2021 20:06:21 +1100 Subject: [PATCH 0782/1892] Tutorial on community visualization from usability benchmarks --- doc/source/gallery.rst | 2 + .../assets/visualize_communities.py | 48 ++++++++++ .../figures/visualize_communities.png | Bin 0 -> 57542 bytes .../visualize_communities.rst | 83 ++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 doc/source/tutorials/visualize_communities/assets/visualize_communities.py create mode 100644 doc/source/tutorials/visualize_communities/figures/visualize_communities.png create mode 100644 doc/source/tutorials/visualize_communities/visualize_communities.rst diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index d29d7d2c4..45f49e62b 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -17,6 +17,7 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-shortest-paths` - :ref:`tutorials-cliques` - :ref:`tutorials-online-user-actions` + - :ref:`tutorials-visualize-communities` .. toctree:: @@ -32,3 +33,4 @@ This page contains short examples showcasing the functionality of |igraph|: tutorials/shortest_paths/shortest_paths tutorials/visualize_cliques/visualize_cliques tutorials/online_user_actions/online_user_actions + tutorials/visualize_communities/visualize_communities diff --git a/doc/source/tutorials/visualize_communities/assets/visualize_communities.py b/doc/source/tutorials/visualize_communities/assets/visualize_communities.py new file mode 100644 index 000000000..614bb612d --- /dev/null +++ b/doc/source/tutorials/visualize_communities/assets/visualize_communities.py @@ -0,0 +1,48 @@ +import igraph as ig +import matplotlib.pyplot as plt + +g = ig.Graph.Famous("Zachary") + +# Use edge betweenness to detect communities +# and covert into a VertexClustering +communities = g.community_edge_betweenness() +communities = communities.as_clustering() + +# Color each vertex and edge based on its community membership +num_communities = len(communities) +palette = ig.RainbowPalette(n=num_communities) +for i, community in enumerate(communities): + g.vs[community]["color"] = i + community_edges = g.es.select(_within=community) + community_edges["color"] = i + + +# Plot with only vertex and edge coloring +fig, ax = plt.subplots() +ig.plot( + communities, + palette=palette, + edge_width=1, + target=ax, + vertex_size=0.3, +) + +# Create a custom color legend +legend_handles = [] +for i in range(num_communities): + handle = ax.scatter( + [], [], + s=100, + facecolor=palette.get(i), + edgecolor="k", + label=i, + ) + legend_handles.append(handle) +ax.legend( + handles=legend_handles, + title='Community:', + bbox_to_anchor=(0, 1.0), + bbox_transform=ax.transAxes, +) + +plt.show() diff --git a/doc/source/tutorials/visualize_communities/figures/visualize_communities.png b/doc/source/tutorials/visualize_communities/figures/visualize_communities.png new file mode 100644 index 0000000000000000000000000000000000000000..209720200914ce3df784b6348a62e62d6e11ae1b GIT binary patch literal 57542 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

    _ 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 Date: Sat, 18 Dec 2021 00:30:13 +1100 Subject: [PATCH 0783/1892] Corrected shortest path visualisation Added edge labels and fixed the path to reflect the one found in g.get_shortest_path() --- .../shortest_paths/figures/shortest_path.png | Bin 29371 -> 30185 bytes .../shortest_paths/shortest_paths.rst | 24 ++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/source/tutorials/shortest_paths/figures/shortest_path.png b/doc/source/tutorials/shortest_paths/figures/shortest_path.png index b77a93f2200756688757df66162235802ccc2d82..cbfacff6e3fc6a1b30caf954375ee8dc6ef93927 100644 GIT binary patch literal 30185 zcmeFZg;!N;*FL-n>F#c&5fPMbBt)c3Bn1hPRzM`ATO>q6TDp`LNdW~(DFI0-X$fh5 zbDi_N&-?xj-}oHkjALx}Uh7`>ob#%Chihsm6XMa~p-?D7RTV{T6bjuRg+iOf!GgaL z8JzkB|HE{XSJlOVUp_bw!r;%i&MHQ3C={^;@*i4(OuilbrI@>tp}UTgjr&szS8J4` zg}d`3C-+BomMl-KUES=Q9i@n#z{&OD)pY#g92ANLrK%{W z>zTIx^PwTd!v&G;4|@U;+2iz;1}#bB4v#9cu;}q4C_0i9xwBt{4N{2U;h>F@@x~I< zS;dObk+#xd@{W_B$zdinocPZ6O7A$S=k^Ia^Br3ZWgLH_@P3`iX0zTY&P3pKU>N)w z4hb1RLw-}>U5O$iB_%DSrIKZXUn1@3DvFAVxi*HVaO8Ca_$=_RaVZvP9PqE&*ZKV6 zUlr{`F1>_*Rq3tx|9|-Z(+hU%_6kZ-_eo)4p^CbCkSiE6B5;hE*-u{RtiGJVgE<-6FmC1BI=u<-KYOFUU``5Mnj z>Lx;URr~G5#@{z1rP%ZiyaWuQB$kyl`@ctumvR*^cKU3;X3-Z?Zz7xcB$*OjGoo)EgFEeHogDhW_Hc z60LO>4m39(5wh>v3=9ooqY@|<*>7&(zR#HHN?rcD!?Q{yj2hRd>1exzZ*FD9zD_J} zzu29~J6>l;ey}x3ET&lSvynZDz9vMqeN?by3^QfI8|6PQ&+Te@Wue#1v{qcaA^F;K zx~ZQ(2P>_V1N_LcQz9?DRKcaBplBHzqjqRMr}OTtwitXaN_USiw9F-)*xT2_^v2t+ z^tRpcoG)Kh0#Z}yN6YTxv$N;$XlVTAYjx_&XYIFFZ~9IbBXyRIoxc)%fD`yo&@Cw9PhN}gu85?|9gwA@mWkH`qoMhn*e+?bU%)A_f!jspD6brEz zzOloT)FiaD;X4am2EWf$r5Ht>Q8hI+1v6P!#nlaUH$RMQ>6j$P-g}1e^6Ze9LB^Nh z?Bs9x@ELg_FSNGH&KKv;-8V)Fj|uq(NBXeoj3@M58R|v+{Ytqzlou$Mq{W%FV?kJNEeJ4%e>r*RGM48dn#MTE*Kx+nz<6sIm*BI+IcE zLDMPTAAd@O&AKs4EBX8njg5`Xi1(xHlpx*!5?n4eHgqK=C0mi%U1Hz9wTDl4PAAGe z_gAQLjS2^@3CfjrIu3Ym6VQx0?zNuSjXq>}Ya$(1dau^1}xhH zmmiNgcm!Uut1byrUVi#P-kn^vNAWuCSgc-?beaMRN*ju|3K9!hkWp& z>voGGdfe9s*&yjPm$gbwf5R6g8e?b zPIB!9O=>Ns{FV4b2WG|3=qen^A0GCziLH{-O-Av3-%a^T8|xd{KKNwV1o^}yjCXCF zI}Ts0FRL_=7`=NgQgcLMWb`I1B7*1puF7**usIL?D=FhX#!Jh;>Bi(Pu0GA2d4=O6 zJe4&?o3cj}oU2Uia`8uqw=qrY?qoZP6SAMe z#<`*T=D-^MaAoO^^XgEZkW}pOSVttah2=CRmJMOgsR<#!;|kqanRAHooeBA|may`B z*?8t?9AsZciYosZn0Zo0QZ8Ox(~w&0^Ji z!t3I7-}-L~I)t72aGQSe)|=zg{b2pzK_-hC-kF;5S}hyFH@f+w5Bam|Hj0ZdZaMs4 zyg*0!ha_oq9PC~pcaboVyWLN6|D9)o1Ghl$MMl6=^zY3_yCT^}tz(YXhr3Ug`)4k* z@z6sXK(n<^q7tcZJpFD+vAE3kxC@VBc{%$eN^jsg_e^e`kkQwBZ^EYYg-mM`mCi5B zYK@K4`jQGHk!#N^EhThhWTd$5*0X>5DqG&<BQ(8}Q% z4hL3NUPEPa$tcfq$h!D4xx2d?p~Abvp?$J!OjLKJ4l7&xzBSQ*k$TeHxyFgRB4kag zo?26^8IwjGI{=eT{mvcUD(0di_`gW(4J5LvcX`5j^kRk!Wa&NsD9(-l1}LK|Cmx}WdW)bO|wY2Upus$ZA3 zojKL-$8dH%BCr07pN{u;E#rAgibf4=l<=wu)`WKmb5%woHSvJeUg%X;Wkn||*fwF+ z)goxiza3s>i?eO80|sP1F=YNGK8yqx#=ZDn}x-s_`7MO`(H zWvM;I7b+SWw<4+d2OdY!)7^_D;b`xXcFf61?`s?kM4#J3i3dxJuFDCL6pF{db*p@^=@oPx=8|mo)~%@j_V&IMxG2ASm7!{S zvRF(7eG^^BuEd@PVKQ~N$H!Q8?yF=;0{0`7V}qJM#OtxikxZZbxF~WA17i?4!bQLNHqmM*_e>m z(IFozyC3-B!*$=oIqU}y9~#^v(&n$Pug4)I>?phck>tGyP5G(BZ zQ4hx}pVJEqAMPmWlBVz)l$mh5jB43`{WyTI+we?sy=%m8jd|-RMQr`yKHW28`jn)&j6EO=4_Ar&+abe%p^SVy1KfS z?g%%`q7Rd`PF7tpj4MAs-t3H`-5q@u0PC(sKWEp0n83d(SHCs-5^tN*fk_g)aySpH_rthp%Kn|L2aI znle#O7A573VOEZRn`0q1%w#O?O*xTYQins_w<-6>DXyZjvNevqIa4EDeCzByCR&m+N#k^Z~`eKg#)@+O4IR*wsAl^oN*m)={&etywgi7vz zr0RLDFFRI8#1|^j(&%{A);7s;j;UTfWbdTX)6<^b_4?b^hexh__iEMy1v0)q5JG@_ zR#w)RFJCkt-4qcC&dFg9A*Aoz2@r{b+5^b9-E+0s{Pb`Kd2EVogV-|71qC<`V`ahR z8O#K|bXkipjS40w@Un%PG#*^;@OJhG;pFpdJbb@E$!M<}J99q@gBlh(XD-+><#6odeKCr4&MbJWte zHyCbiyLcNJL2+;1;D#%rzfs4kG(3$}!0472c+D;@PInI-qw;CLDFr1Z00o*(!h5YP zCAh*>9%!h`!P>v_q&ia*u(`hV2Q~$u+4Lo&QBza9{~pF=Vq)6<^T&JZP=Sp{20_2R+HIL`WR<) zRKMc=d--zHPdpp#r{#~Q>H=C?hC~c6a*K;2xpm&PjE+)ydsEVvtBmASRFG(CY1IM8 zvFS|-zTsH3ROXiH?lTL8cH68LNTTOofn05FVPWCSawmUyf^8E;dmfX3*=oC|HzsRc zmcG$`%aCdA{zLjN9dP|U%6Z&OiPQ>E7qUe{P}Tvf4?JBE-<0#6wN;{5Cb%rI#Us?%P^L;$(|jo zYfZUKethbbm*M~8%NLx!zCP&rO0i5*6q6T+3&h`2ZxYY=p70A@zkW$wMRs){fd5{N z`QOc-&Mq#kB}N~Br(bn1A+~w^nCSNH+o$IzTk^`RMOsKD$*QU09c;}IXS(-&g5tnS zTWJ@u8^Sz4KR5j3Es`S4eIFNg(8747RYh%W7f?zd-CWLU`#Rd%FBC$FT4!dM&yM%o z-&^-+Hv5hUTsPEvWT_wc7A@SR?e-tmH-Uo z!mlAP?a4wXVaFa12m}=$K9GxQ9oacJSj~S92Oo?sdEV|TfKZeam~n3$M@lM_Gf z{gRrhYCv;&rG15e4AbS34YHB1jH1H@_ zRt(vbjIWD`bU>|<($E}^Vh&eURyw=7wk7f3dzqfjZ{C)2`RY|-3kwV6MqsUHfBn*B zH&yn#OcrkL=OF;_)skL z!&uGE&W0a~g@w(^%~hODD7t+me(rNPxnZT{CGn@51kB9L!jGp6R}A$!hla@L=;%PL zp%BN5>qg)kAgaE553iftzwhwNJD)8M=lRKjlA$5Z`o;!jyi&8*E|$#cHbz={Iw>_Z zr?c7!IWsfy)vH%w5VEnbpl;l_A+KCSb#QPnUgJpL6;Gz8*?UsOs!b~KbW>M7SJJ%2 zpRTzKehIw0lNy4|ep(^LN-1t`Tpr^#Wdc|fgKZ4)@kG0Xc;X)n5nn$#qvCQQO zyGr_r6V(nmu*#xtOHl(_VY+m%&L}1s->8BDE>vEJZC{!gI%knI{A9;a-t9`4gl2W-4)?B{`~oasa}wVhljWQ{jQ9~_jh-ah3&{dmC-8J=g+djwVbMR5%u2V z%GEAJK7b1OfER&*lvXqE)Zd`Hxw!?9>or5iuv+MhKKxx=PO(NsO-X41f)+_+hp5Xu z<^!QOE!@GJuX|iJr^Gy;Jl459tJmGL9; z^Yh!=m^8SYh51Wq?)k`7s4*03@xwtr@df#qN%_HgsP7l9pk>y!jS3vxue4ZMvqf;T<%j5hf#tnSFY5-l)krn zhitHUfmSx#{?(f|;fxYbP+U^a=6?U~?(y0hEWLLV^U|f(pFbJl5kh{M~};pGP)ZBCi3Pv@}ywQxlEQ z1C{7B;`c=~^z;kyccoiFZVHZ(&(%H@P|zjZoN10_SB^n(F>Wo*&aybOjaWQ-L;x58 z#%@b@w_4>H2t&>u9vy&hUcPz5ZQl0h>({Sxnwlg}HmAa&kIM5=DVUj=tr+syL7NeM zc2F`;%*S^86ckcDb(qM4f|@R0U61!x3+{icX(`mb3lxTggajocBO`1-j3c}1H)-a3 zbP1|4EGkM-ODnF0`{KT;DlQSTGy%M3Z}mGiEK&uGOYtN%c-7pmUqLG?wgEa# zGtu-nXIEEo<5Ys+ks=rfy23SpTOojJ0Rt(9vY`P|(sACKrr$cjLj;l8I{dYJYs<$YkAFyRtBd7%g1kw)jA`Fd<=Ra;W1=iNygsq32>0a^^#y--JfpHqF z39|~lA;{NAe-Rr?JW=Zu3!CZvsa|})%mu^A!G?m1OC|J%1ZZqpl(_i#3ckM5D06_6 zwxcC)TEgvbz=}fcvr9@cTz}Z7t4;-D)8Wxn9VxWbI%s!^%PJ}={_xQNL!yzTf7t(4 z&sY7J8IU;v{S5-3SY*)YwV~4&q3`VM9PW>qp`oCLlEvKKwS*6czJ1GN^DQ|5xC#NC zuuA3GTzlx@eB{;HwYA8EgakF2$KKxJqvd9?z?lCj|L&N(i^EON zpZ!{1UVvK#T%fH6)s@Kg?=+6+LLTa-0S*>%%IA2E4RJ7tyRVd9 zWFV5Jt{nibBE!fhfR0RN^e!118Ck52mO8t+=}Z;GXJo{}Fc%dUp9hG86bYcOsHi9e zeN{Qln9dICQZ+O*&|J46U}I-TI;1Xgtw`w!m^R{|3Uu;`kXaKzJ{UR#eF(NPG~w+Z z4>RNxa`qf|K(9ogE%Zqis>o}P#sxdZRH|X>QNtF#@bt=1`MLcws^A5JxF{%c5yXW9 z8y<~Z%PToK*?hXu>u~eqmignyW#i}I7V#NZ;n3fF{CRDx9DwfP|HW8rd984(a?PiI z@L#=pg+e(_RJFpQ1Q9AOY6DhMvJ*EnZt(o(%V}av!W{p<=7EU&dFm`JhH$DU<7UN?8v3waICQGh^SpcJH3f4IV|k#++5b-#eEZ#s4rhs#wRBi zzQnO}adQ_I9qQu#J0l_i?chL5(1e0rbUylH4M+kF^?R&5RyF<#Zd%y+9ZO5L#>U2% zadBt}NP=!`(o+ji8af*eK<#Ad=i)%iQ79uLqeB=bb4yDhK+yG{_!KEhdGEC>bj2cQ z6#7{!%)&%~M5G83j7?8Vt7Awedj_gV)7im21~FGmn6j6Fu~6ofvhD5fUvn7c1E6Hp z;*S=wLChrC^6K*K3h#aU+;{Kv4@GrF7#J8xn3x3I3I6lOy1EnykVCBu7m^*Iz}eZk zrN(hmbXpx3pl&@xbTd6*`Z zaG@~5^p9L5JbnlDrrxv~%vJ&%bxG4$9y%Q^Ha0fm>ABW7cDoIProtM6s@UO@nwx}d z9~Kx)K*v!2aqP-X9-W~F{MbQKx z_y+C~;e-0HjhJWq?aa;_gKk=N5_DKglW7200yZ_fwH1qofn^T%iBstUZ&hbBeS3dD zG4OD?_$zlPChw++qE#A3!G6rFsL*T)$}KF!m5`9=7$9QvfK}f^1EDPx#6}D*MoH-> z>xKd3TG06$75MTcNnJxj8_;vv)d$1KF1`Mc2<*nsI|1mw zhw|`&oX4f5@c|pO2XABVDyW*IWMtW%l7M?{0XHS9e1gj$@b&c#i;nI9hAL?J87I-u z&*=7TeAv*TifpZba4Fto$oRz|^c8N&b8iKJ;mGTM1%sd%IbFwui~I2^<^Xw>jg9I2 zhpvmkdjdfA?(XeX0^HZu)`s-qhkXn*baZ%(#oz2liY~!m0!W?(LR`eg|52Dbj)!!g z(+S)9FZHH^gk%iJZ{)?Lmn+PTK1XCA(O=RO*Z=b4hY^f$WuU1b5g1n6Q^JEL`Y%nT z9DQ$nyX0Oi5zJTHflM_2p^W{3ECpz}%1}BHk&%})3Qd8Yy?{;u(iARZa6xw^>ea;V z-@l|;@vIFHqp@6k10Ou=~cx(Le`N<7<1TSH9!6SfihRax}4c!45E3ocR zN19Xhr%S!`kAA$r1X>BKC#7iKG4$uIFj974F0IXH-ay^pz5rE;w+sxBK%$`I*VlL# z=;-zuYPv3LV#-YMbkC0WxWO*P0O$s<<$b(|QtRmg{RWj_S`)9r5rKBv{ov@&;`Z(? zx%jO-@1sALLAOD~>o?aQwtfDrxS}$`CMCr%Bw*H5GJKPb^vsOUKX>$tUEH7y1FugZ2%ensU4 zfXo&|x_J3AbNpRiUNA2Cm6pCfjmurqMXx|xW{`M70F~wAaFTcXwYj6?*{Jaltce1^ zUO_+=8kZG#f?xZqI;O+0ii?W_2c%uXOu}V8DEqYf(GRi=-(x$EE*)ODGk~uhkX;xo z(&H^Lu2ysGVMYO?r$VMTv@8o78!Qx;fB;hbupwR6$FG6r9H2950;ovI#pN0>u#3?H z>F39ddgrJX5IY#f-CKa*6kTW23WhCW%)`yydU~{b?b*R2P>EJc%NIe%;Nw%@86O#; z1nq5vQOj}a<5S}4>1ofM`Aer~XUM27D<_auP{2?KA&>*b50rBX9b#)6oB2tn=8i_M z-D$e_vWd5WyRpTcuAN4~Z2*rffT1sPnZ1a?SRR{&Oy1d95D13L@8QCyO*MeT9#~tW zp`iIkLapmQm8=Fn_^$#R0@#PQ&wX$b1`D9JYf#RB6cCt&Qj6S$Z6xSCD+}Q9UZK8h zA?~+t-w-a2pa94-_-*|?+xvdk^I)CU=lS#EYm8bQVDcBHM@11F9v+&*rYkTgpT1{? z>`)>GQ50%mbTlMBKAwcsp(;C@ZGEPh8Tw@xOy0@|U&)f1iOnr6(4Z`Rc6)Ey{&=5f zc>-H>79cLLa~2sHvz8!{{vcd(=fiD_4t3Op0Rm&ErUpQA{FWk8obsJi4+3I^i~v7C z*TDv5&2QO(m6bK3ehe9&yC1YVz-BgS@}Whj`}OOAAhSW?u)Fgme$Ts24UUE7Tw8E~ zUNIFaGcywf4K);cR^MBx9_vM(@R%4PgvP-|U!<3Rf{mYZD_R~R3jmtGTCnB18lqH7 zkw*z1==}6)7kqkLLPAh(E(e1BVFrjkKNbc_!raCtq);axkFmBBq_EB+y<*tqC}81$ z8p0M%d1PUB!8^ZzMhe`Aa*-VbSw!b-^sJn}a-}F4)LR;mRU$_GQL`|s4`Kb|5)*>~ z4rPH}hkk{FhnY%Nn->J5K=mtuA3sWf$C7nO4FIYumU#h$D$m1hR-68}gwLNp&sr!- z08v_=gY0ah8Nhp6M+ZXYPq&Q20bI|nuSdbS7#|-;aecaXINKVCI3ffD1T19XfS!X0 zi`u{*xwnS744w|mMI`?L%s&d$EBv&V1wNkSIE9HZj1u$B7iU`%lRtm{j04pz7PNMx zN}Y$bg7+XZMZ2wV5PID4w}^@_G0bRqrUqot8Rsy|ip!w}al zq=14Gym>Pen6a?1r)y&)-Oa~Qh)4J3B`fk7UAOdd-by_KR|Vl>qCSU$fXST~yD8J8 zo>93ieQQNbH5m4$zE?wGV_HIsMus5FyKTUJPp|mCm44nJyBgLVbLr*qG=LUxerJm~})f7fG`CA>0OdllME(Bq#CxQs@Qchbcvp16KfKBqted#dM0-!Q*DGfG|$-6d23_wE>Vqidoa*~f%kYE!mDWaJr z?GZ!nE)dks`J>(CwDVwHx~pjM#yos{iq6gz^E>eDXN-QOPbY%Y`hS$;E9%LaTz-D} z@K=ZHANrla*@2;_Yo&cG0faR9h9g~Dd;2xdZS#%;Xazp|BL;@`u9sn7fl5sGU!b0i z2Z`2d_t_S-4($5?ZgzIMnDNt8>OsAl&Cl>{13-8U1{+c=!^3-lZzpqA$$?w5-Mm>F zp)(X(WKhlo<1z$Pv8HOe9_Z+ED=T3Y6@tGO7jcs{>qQ<<(JU=3g+)e^i{ok4BiQBZ zmoF{g#-mUm&%;)mtD@Or1x@+<)a!pW<>wBJ6U0D16;@VPTfclMh|t#ds&<-T0yfq5 z+RQgx+~YTj>wdAijOG z!AjU(|8f2B4S(+48c)QHo=i}gPp|A!2#_b%MfaVGXGuk1PDFwL))iEZm7K7Q7J@&7W6y! z87|UWOJAm;p+R&dU>Ki4m2}yeS3>1AU&p87Yk?k#jQVNr3+na|!od7|P9P*Ga&q#l z1(L*YmA;lPpGQ{i{f7@)VEz#>Nz#A{E(?U1H!W7$WOu0-VEbvU*|WVB(v+J{=jA8x zv=u<=1(|_ja&K=>(BrqRdWtYE?8?Lh{b~rn;V<`Rgr=sZ0{iJks;qPMdp;?syP57A z!w{l4UtlaL$`-<#1>LQ}@4^?6_dteQS~NyS!4{u|sf|1ufPWN|@KlI7IrIG(sWJr+ zu^$GUuV&>HZ7QGFoYj!RC8eV)@&p`X!rpDBB<1x7vsk~h4FoDQWbQGFCoINN2#bhZ zv-w5?N!uv;n;JV4DtGP#1EKq`G_LIl>MMNUtUU|J-x_!AEw-jVsocGbjRNA0555pO zCz(FrP@vG2&rhB}SCji6bvrj#U0r<^*f&fwz~S6AGjQ|3PGNIlz*ELl=i-B1P-Q=Y z2OcVwINl((65~+QQChmX9L{PMNLRxqVvx14$b$8j#=&P9@dP<8;^rbq z`Z+M9;PRo$|53G}*CM2CV?u95B^Q7IsrUZx;DG^6xTn^Z78L4bYHB1rpti4HabY^5 z=a=|Ghev<_DJ3PyquIo5=qe%;067qg2<2Z`$PL=w73b{Vf5DPRX6kE!`!7Jly%ozu z_>Zz37x8^?5TVLo0|RT#s-yh{dtv+FAOvYk&P$Yge58l zTN;sEx*#qc5(40($P}h5SvY2EYb&CDK(xU8(IY;0z9I|zv9jpPx0B3a(yWYE=2$)h zW&`p*V&SBvF@Q6~9H)Z$?AbGT{#iLBXAqJtszl;D*u+dIlyU9jXc%+&X$9VZzthA$ z@DQdpR>r7bW)hAF=!}u}qTm_({Qdb9kr_acMN13bnT1@Dy<6v)z`OzN5hYIm75c$p8M+1B?Rx=*u1k8iTn0VJx$aFT~$@} za3v?!e*GmTptT1N9!5G6Of4<=m;P+k&u$2!A{Py(hG-R zlBk3PGW{(plW&*BX*U2Jg^xyfR>uvn0>>vNEP)+}xDs{4YdyWZS^hqxCLRk%>c$kc$X@{Z=g-CQ1IZh*P~L?`>{)^x-M2u}!2Lj>`T_t8Zf z9AwZuzyvV?HDPOjOdO?UE#|&L@>bFd9knu$g@HxHz~!9X4Ju1ihTl0YR3U&sED*C< z+&QxG9H#270Utu5CV-j1*2h4BOAwCO5q*6`kVX#zBe6x5_Z`@ff;Vn-LM;yz>Ttr0 z;0CNUf&+Ttc++zU|DooF`(TrQwjP9J6!;p51OS?l#ZeAj7hq-}e8JGZ=gVfno&-Ix z9cB`>fQjbOsxD%&AT+c?GAvhIl#pNq2VUHPG+Y!2wW1J4V|UJu@B&(PfI=L`gqCJ;EU(x&@Ioib?P!h`>5P9v}RcO3>mcnn{WdE>8}0cGylRK*165J&TBP ztbPRp1+E35$M0cMQN16DFrEMxB0^6|X(_mS(IEIjlTaan;%ON(^NWT&ODoid?5eO3 zAnNN7K5&6%K|xIo9_%Az6v4DypQyeK&mRTEuH)=r(h14?pfZ7ELEfsdCA@nRhX3~7 z9{8T5(EA5IJ$stPPKpbAC+lv8^dTTP0AU4nIWlmNLQYN&(irmU>QOD+J?}sTf$7!( z#v?ctV0{!7gF}k&)GoK>KD|N-EVCw`aG+!JuqB}(wSi_;??XR$k(HAZ2$L1m8+63# zd*t`$7p|m~RHe_6Ya);Czvg5DdVT7J_U(T~cQu)x5up47Ys`0DpeeKgB%DYA-4-qx)dFQT00b|9{OkjK zP+LzAJ_xznfB!1O@K0>2Amio*A}SY%#R|GG!Uze@zI1oD{hjfPh1!~f2ZWyQBZGL8 zv_hDn#LO_<3$Fn^7DEaixC#wYNaRj2vRdSXj6Q!aG7JBmR=JjuaaZBNh%Qf8a?XNB?x?!IDJMVgDm9wS=p^ zc9QViW4DH6TS=5I*=_aXw3+gN*DJa6DB4-yG~C}kK`^o zI+U&%?Pav90elaH0f_sARv&sJ@Jb||hbbmq$O&)jjR+pW_|zyA)OkpHdb+t0V$nco z0+QvHaPW)fnq`o7v;s%=-|s_1Z6JCfp%L#r@QD+AF{S;^8ITMNJkvgVjI`__4^ zQ4M|nehJzF>kpZOPn@0o0|Ml#myrksNJn8X14sd_0cOxTzMLPnvh^k<#j^Fq zC3v+wY$1xth530z_+j=vL~O;86xDxbp_?&H(G7Tx!!b-!5l~3zC_a9EFiI=zrJB^Q zv;&5%bX`;f$V!PIGr&dFHZ0jigNUwf*35+b-9Nhe%n_2to1SI@vumWG#02O|7HF5c zPq}q^!P8e;1JL>}A_LpkYyb!|Y;foPm$H7~>DK~|=)N{en145; z?2lEPH$)xs5+EW8+z6fPlS1F%U}bl#k*20U3}8zn|0U@q^l$#Flt)H@lsgt&^?3-d zw*eX%sByg4aWLa|!3Z+kEpR?u-Q0?W+rgf82CX^oUQ>)c6+BKgn6-LQpWX;rt0nf8 z|DWuaQX~~ZM!>x*TK81UJ%#vMD3A!`?X^o55OWheU4Sx3GV&m$p>2C5QhMHa9HY+?EHHZ#KP1%Ri4B0UQsH>51o zwLCzlF==qe{Wme@n0Gb^TEX??l$3cGd``UvD!R0uST7T9!Nr0Pj+VJsZf0OGruLD6 z_jL~`BO{U)LL_DoX8HUSbp_x^B63g?oDGERqw;RXInFdO!bFBl)uX&S3qsG2-2qM% z8!xkS?6<(8fOO9SG93zW&#FKl(>_T3Ps$dc6%s`NB|)q&HjGCRk%N_ELqHCOCO~mp z9_$b#&KgO5wG(pwJU$E%eer>?ohbNz!GD$Z4A{gTrsk?8#l;1HxCh;Yjg=J*h|bHN zMX;8Xfqz+8TVLYk<%I;7iq>avFo=Q4fG7btOcwIw;I>kB?|>}@p&$$ZULl5j`rr1< zz9SHyO^p%qh30zC!F2==5&*5406kP(~;XdaSI5gRa;poQx+&PYRe z1(+cuyMQLzPS%vppN)R|Rw6IMJR-^GugeXo$qFzj9!-;l(T|m*q1^Wf%ypY-g{$__ zNLj85D4HH$SDAT$j!F@6LNlO#2u2Z%nty_0YEGvGU(%bQ--){Z!tp)XxQXCED7~^n z;)2g$87BZ_?E+ecWE5$72vDH%Ak-8dbADZXT}hc)b4<_ctL@M^peMjF31!V~eGX13 z!1?rJA#y)&k=U)GTxIn+lr-#x@OE#P7rC!a5biG5&+YchP(P6J(3XZ9V1=6l2+>KL zdXs&*mwx!<3)a5GK`QVXh9F6UZR{7)mV1bV>$V8KX+O>w(6sS#UslXUXLFm z#J;J?SIJLT+X62Bar4EwgiYW3uAE#B;niz&(a)lSlx8eWR)A^w;UZtUenTxya zwPa82|6~EWDWw7V^0_4?Bv2sC8N&;^3G7)i-~BSvR$O=T+YR)ooE_JIx?bve zLw6N%k(eQ>@Y^p}Bnn?)Kf*I?{~-Ly0##dqX*}M>2Nq6z+)xbU#3ks`$RU@qvdw1c zyO1dXvf>H+1`=8+!i9!JdeDk;r;x-Xg3Sb}Gu>aUR$6r-A{$UJ-z_(MJUql{f=bSk z3ymGLNx*lHR_9IN$P!91wfULna9hiSR<^XW|1Pnw&;7oMjQR;N7R@3hwWx((Y8QN8w? zj;X6N1oGds`;La0ITn<4CSY+0ku-k0e^LyoKXYL3Q0Ccw;Pdi`QBt4<=ani5`+G}j*TsXH}barEBw57T~s|niAp3>{5{=#xB0)T z6DXqnaP1ej-=t6Zh+bBJ6UH0K_rARSn~$Go%9baOwfXF&rSto*FC>qpw|YHRJ^MdO z_OE`2M!^rK_fV2vG25lJGo5icE-Mliq$O#;52j{imPjK9i*)X;(7dtQ3L(+e(?fJ) z`_zmSY0!?Uk>Lx^*4bx-nh`7Nam6l8^1b%)PPF`UM({mfv<6~hppdQur~)zVVD~D| zG(Bh4w?cC)gRYT644MogECSI|hTP!hl-D0BC-@Cwa6!ftK{`O{!c3UMr?;L5j1oPk z=Zh`8Pp#s02sUrQZgr%wWM8}!AUp!_EMyFIU{Lh%F*_PQkk9OYHI20imTxY} zmgt@AYc7gt=Q2ceGV@-U`*PE1-ef%V%iWKAcQ z6)ksk%t|g#h*!AL#$;oEE#T`e-8XqsR-RpziwPK8n;Sz!hR=Ub9Yj?@LAy(V`bCaA z2l*+#)pTD|W}UiFZKnSSKdn-%dcRdV#9+zqm^>~9NF_^y)|d?RC?r;XwQ(C={K-0( zI|G|`4p@rtiX!*gOQ?tsLly%QM8@7&ccU-7=<7v!;X$mX)&>Nq@^XMho)D123`O@a z;;xE+T(m-Z>|L>n^NWll^6vjy^3AW)zSR2__8OLr{Bu*JMB}A(-$CbgXu6LcGs;I78Np73+Yd%NyYI< z3$;K=b9G~CJ)nG+7@K&z_~M`_%kZ}H(MgeD&1Tf?*D-}@fhp9;t?=;h1;xbKrN`c^ zdK5aEe$rCYuUY4_P5EFXv94;BzM$c}u4XQt0HA_L-_TTIQj#SYN1k9d)@$-=;p-S0 z;-Chu>7MQCmy}|7^_n#s_Ba$JHkacuD(Fx+Y(Ff0XO5Qpu&6Ljo+C-}f_PM$ep!yI zPesYA$$o7t{31T9!MNJ#J^xq0rbh=?weT+|N^?7V95s%J*asI4y=acQ@LH>_S*tx) z<%p9ln%7gX_ccVVzNzwXXMH_V;3)m33J;~JWAtvw#c%q?=*WoPy`&`@z~+KNLT#Y% z0FPI+KUjWv@4mECwBx$g+l+ve?mzjRkxbG*O#43Hs-EorL&xpzzOUOS*NczOA{8H; zcbO;hkFIoCQPuWUD_0{zp{reTC8hWZJqJ9!21aSbC^&JUD|Y)fVwHeTHyeF(8hCK) zE-_2C4RV46rD;@hyzH2|8JPL9C&T!GnJK%{QeL~D<0Pf`yQ1fh^{JNINKL7paiA%h&Y@r$l zf+D3SyJ5XQK*-V5(P^J-R^(53^M-cf>3Y!oH{rx5_t8-wp4=boJW|SK3Rm(lVkI!1 zWZNCm(xq6+JTV;kd%)kT*532DjE7nI-#boCR~lQa|kcNQ0nBOovaCIcRLkzo9iio87Ed>nSW&M4pN zS>qAw(EJUy-R^5}KWznfl=srNFB^NTXAMc>)iYc+s-0Upd7SR5xeNKi{$UVNboCOl zIo58dKXPbh%DmIxTCpl-$WNP_XwB8FuF&i|ZU3fROdL*-43LHu1nh6kFiSi+BeJum zt=iX}47rnC8dz3-oVivkz2B{w=0QI~X}tmx$fu>Ocd`A@mb`#9bdC}c&;P|uVqJ4( zpm3#~ezqmmDnvpmQuTNG88My_;rp`BxJh#sr@rG8)xn{mq2{y&E*0>zfZHvM%~4GE zPcVk?Mh>?1u!H3Tq7FZKTCF2M=f?3-co2w+9r+3d^yjq`d;xRQFS?s8*m%yZ=N&*2! zK~@$y>jkdClr1fU_Txbhz4hr_T>GF@$-`^m`6%VXyoJrLX4|W$M-ZBRT($ek8NjbT zlE-l0_#KogVNmR0vGTCK`YOQ$+a*&71w)Sp>V_OuL4;zcPc5DAqGIsgkt!VWo`y74 zO0H8A)YDwc31ccQZU!W2X$=;j&_%mykTHSD69EV1Zk#eizDj#mxARPp!qqGA?bhZh zMs@T#b;4hDJCm*{?Y(Ga?!yGyW2 z?)etU-~NrxQVdcgKp_Y@Q}6)y)_;%#K7j1qE$`#_$pM4}0lym>8k&XdJ#g&mhjv7e zEec^(2*F_t3>$`^nQ1{$QCr!#x$PQ#dzGU>b%p}#>$#=3)n6LjF(J?wl%JnJ(Jyz0 z8Z_Em$o(Nc&W+$wdAkEf7(#^MG2RDJ397{}UAgFLV;$QdXIBBq%zUbh8-jvJT4@$e z$H6H>maAJ|lT;C313V^8EiE)oPR{5PtR8fgVIe{Y`+)l~e&!}<&(mW*U5WjfY`-!6 zo}O{o+Qm6(>?;ix9v(a}fOLBrhkd}m=ms@35VVf@+Gwr1XOD^9?@YFQQLFy+{K8=F zEVb_akpsm$v(D~B8AMjSsM`(8%e!p)Y(oUL^*m@U1qB8Ez-}Q1<^l)Z;EY)N^t5SS z`t6kKRI=Ggpxjx&*)!yfT1>{++~B^BV2z9a+d`#JOT8N6!NsY~A$8d(kd|6MZn=&T z-{H{4sT?P%#(_|gJct>H?tyfj>U>-dIG=rPGZ3J6wipa<&TAPMj2mbs^w779(4;^8~ii%~BM>zQB$ zYUOX~*Xcp6@i6rfhOhpDBSA>kRcE2R@edwy@RFCe*!!a74kaANv?(Yol=Jiy)xT7F z%h(=Iy;LIGW9(e8(!)Qz6vO=vUqY}Z>+2jqFcH^vw9?`trc(2@Op`+)zdgSYyF3Sz zW+3?^$KGF%(jAfX69~MP7p)4Oo)=91oF_W=Yb$abWI68|$cBEaq5OmMC?&C)qkxn) z{^{nmKVfNbUBrV>dE(Uw)ZJ-wUvRXq!SVIQ)X)6Lw>#NraZy09qa8Fv=hIm7FFn0z zC|h{P+sedv!3^+@UvfuK{xusC=D!@u*#reifQgU_iHorE`46)|mKzDHfFYUF*vJ65 z|M>VALe8OZY6Nsa`t`|tka9u$1A*&oIC~Hb9B^8?K#96HeA5iLYHyw<7vx66!PJ0b zLpkuo0mXx!0@l`x$Vhx}>G|E&?O#C4>OgX@@R*S^K;YOfdcvL(bes?dms_dD{r5j# zQdcxDKQL@bOHU8S3`roU1))iU7|zR=Eubb4;|Pc*raFB49|r-Ito;shl+CI6jOun0 zpBz|{Xp;4guHe{#Z+*5%XvxNwodlsf;al+45~ScAflJngBqcOWO_8s~I6OL~ zrVDa37S8wO`OtE(vtuBqERcvN5W>5&2_OIy!Z)Z1zpAenL$rKw z!k{bZh`mit#)0D=i1rVv69g{V*z83?M;(MTR|SaRK06)M-5uGBu3~V?5*Jt<(w*;q zl2cby943RB?<5abq>=O#L~{R&i+Lt|4e%93Adn)*6TsBK)KGysvX8|1iIH>F3=C07h!moD=qT`d9{p^f1g~Ed{B8L9x)yHuqD5U0arOxQ zOVK(HcNVfrO9@f`96l>C3;<{A|Fw7K?^LdR8()M%WhNpl4N6E+=2>Y(LW4pQX_6so zlavgZvQ3eamC96UAVkJe6qTW(kRj59l%eQ7zv?-jU*3P?kSK7CMDyaPjP1k(w;Xr;=DycUCmA&OGp7GQUA@VE@7^%< zyWT;fw+cHst`pP$Q(#eG&=;7Qx#%4`uBnk7Zz%;E6?;%hfCuJ>M?|nO;^N{+_yv;y zbWzIocjFx&lh9TUS%Dj6MqRfUKv?##Z#hxXjIYegFqao5y$s|&{h+W77RB)- z|BFcl1oPKWFoOrczf8kAn*?;st*uF2PJLQ1R$}V&1O)bI;^Vn4VuI`4dSt4Kii*$Y z+?Qyuz_$~jM9j`NfE1d;U)%n?dJ(;P*MS3(gv%09eE6_+WK~sF1>O?PZIeBFGLCbH zhL{RLuBgV2DLUwN9uR295g-`)&^fgIo>+k|o8w$JXA)T#6o^KWKi73Gda!63V!~CP zwmRlwRu(UVtZu-s(tWTka5tfqPn#rEA`vPrxI%|~O*kIRcwA*DMk`@sWp)JCS$MJ1y580DGwI0TL<<2H1vN2$i zvHW1`bO76=a)NmxeR#vakVC1l0VBFm{6hk{Mt`l=SAFP97^J13h7}Pn?(Vl}t)^e5 zt1<-8@vf&Qm<0c`mgs97`}ThQlVlAcbaq$m*l~ewRr)-7;fdzF{bArEJE5S(o|1~~ z#4sxe>kqw+6McQIw5KdQ=5Lf2=1Dc;f3BC6kx_;?&p&(iPn?KNO-(ef0Lp$GEYq~J zSk+1J@nY>}VGF}?0n^MnOJ(@joVABE21l#d5-9-zwFS6GPoJP8#V;Xo8ed7F3SCJY zJEtG6;v)DssiNf&LzbBdh^2N($eOpEPA7oF?_0BT+HjX4_<((6yp+p)2+kcHVvXkRe$DbdUs)AP@Pm;DndR;(M9k zdnpn^NFyF1Ai)dUM5btY&qSkt8pOdcjhno63o(;-H7Gp%nGP7=AFrJu>1Oor5>F(0 z7p6hX~x(YOFeoKNo;KW3*U8#Y8vE^~Q$VKUNdQ6<|DH1k;)Ygc3F7*)~IG8;Gk z&+)2AwirRZjag#EZ$ZLRj=pqhjMFZ{wQw9lzn7|;Ww;#_8x8z0^##lh$w2@t`D5&>o;n8L)y>T1E)xA%fE@gTI1n*WeY zurWyd?c}+E=S{1(sc9?|}`h2Woo@FA_6T3~x!(i>Ddsu&F1hMsgzVQ1$T73E@J z2J3_AJRPc_&vKox-N)#=A3cqdmjHJPonPK=(>R9g1A`kGEH!{y=uX2@g~S{*^CsBq z@viTM5r~t0RSMWK$%Qu<6DyE%k{TO)2gcFWhcNA;`+cKiqHu71hkwV14}`jr9)%g5 zZs3k%&eaEQz!T9}foqkE1HqX9Xf`r4<71dZU<(42CPzp`>yjrE05C7;ze>n0{S$Ts zbP}NRX!ZZ?XS`~aBO1!p16UY4!6lIy2b7)zcdI4}YD_V|zO-u|lhuP@!Pgwrfp zf{^T;G#Yr6x?wsfK@ux>_objPxaH*JQXPc^p8MmtusDxF7-mJ1%J)Z@ zbbw)nYWwsv5c2ZTuEkjO+1-P7m^<=fRSIY-2?&e>X<%lG0VX7U&R@YfPN9^saSUy7 zbTXhkV4sHv`1^q~Bh-}I@BQ5gcF@j>m??_-VJJ<1h<*YV>f|9Z4jaLchD;Tdm>4Ccy>w=8W^0WMce*iStR|FqQ?IJ<$at7dqPW zU;!vtzp%xAZ?H$$hno#??0_W~R>7BH3FfH8rpU|7^WzAM-i-u+#YGH@@6XS7Nj440 zn6}6PB!W~C|0zc}kyE8%jue`1LF53M6DR&uubj^Y!t}jDsW_s_{s=a$YBGq zR$jh#EdpS!ED{S6lbX(DX8^&ZN^As8V*)7yECmH}_u;$ForZ;v6JCrI_OEYWb=Stw z73Bs&EUQq1SfPH=S<;z(m@&A7en)l3kDZyGIaf`X4VyX$Ri0 z(%L$H^7Fay`L6Ep8YJ1fEY#nCfT{M)R24$qA2OXh z!O;G4US%1a42ZE9JTMrsad8fm=OVFCvdx#F*E&qTHtlb+2)gvY$s*L=lxe};3_D$) z(xq~`2cp*yTZt9Mm^&P2ib9pLZ9e(5kgOFg3Ch7-eX&y01pX7oCq{cvHgGVI9{$3V zfWB^P@jsB|Og=1i>=si;8UdgzrEC#mG$LatTQtNi0K5_er^act2;!2 z*lf_S4-h6M(L6vj)dQFWQnrC6hl!V0E^Vnkl$;^G;(&VySs_{yvT6o;LIH?6>k^l8 zVv5u8Ex@?p6MeQ$aD2QdwIBiWhGV3{*C@0|Bq_%cJMn`xVbqpz$OEA$+l- zkOC2p0A<~TALV{TVEY|3Ph~JfnDiR~b98;>>Apb`FqgS;3P>BmQT}4Qv7JOTBIy8S zWnpbSpI-PI)unM7G{YOf;*?X_3Qlth!`0Ol4itw`(L3PqMlL{+fN%oiwB0yikgc0| zda7a~#sI^_fRIA=*spEi9$n&1v zu+!@vK@$&E?DTBg0>LP0JyC3f++C9|gmOZP;v*`Ki=Y!23}i%rFiWu((FifZT0}0L zewl)XD?7Qwq2U27Q#oMq$^Hl4n9KxFR=mSnOasMdY`i`YYq8b$+j=?)8`3SXEEvZj zIv{--2}z(Z-|k?9^NNm5cvdAQIv{JLXa*=Fwi9S^B_^ma1~}2tu@g0ug$F&S24f9% zb>bmPkx+-CqGvF`Z2&0ZL>B~UNLWj?fW>**3u+E1LzRn%1Zg2cMl-n(p<#fbEBvL7 zBU`5OnrbU1Yqvh4o6!7q`gr=lxUWc-Kxg{CE+q;vhX-~OINDh6p%#DXRt=03{ry4Ac%3uvj(^s%Ru)ln}x;2oh#4 z2Ara1(YhhyAY|3N^ks?WVC}9&+X=>9@WZMMQ@)=rX|{TG85sux$&g*K!Uo&6p@Hr| zE z`Z(=*?#2>y5T$d{^3yr0O3M$uQ~kxq1`nmg#GJ&!X}=VuYq)hQRb8fZW*ipGA%0q3FX0bPUG0;W;Md7pwcn~<#4GxBQq2KgN^=T`}VgkJ@Z&sLxqd@ z^c%Vs3iIIDATgM!>AK2OBOKaA{$Dfn9QQl&daqc4yp8ZmdeX+sX#LQPg{Z96{U@}s zOFLrpAYx>cgz=?r&oofAhBeecx%! z?8}}$jqpDhD#3;(k&rbSe2`Bt)pyNMvMZb>r8DL1D_A8IE(_0YHezM*G0s@oq%Iz2 zTXVbK{NE$9t-9yAed-HLTz16~&~kN8Y47g`5dSS-E{Z&?0y)_8La)7)2BXawKmybO ziC8#hVy*(OzlT>vBl2$FHbQS49HGq(LF-MM0%0a4gAd<$V4e{ottL%w*y$aml&@pTH={%2Bf}PV~{JFJww&ky1(dWKR zi;p~z<1w2%Oi779bY7kIhE(&5?X_y!;ca2b=X&h-?F>KDZVwnaz{Yx_2Cb+Fpev35 zZmH~rIFR-v_=98=@o2X2YwkR$0IPp&9W*Wa8`jFg+?6s7NL4Pr@I|+Qw4C9I%Pcn9 zvV#D4*5oJrMC-fnmo}YKwn0S=VUJ8-1;2^q*t|8@plfVe(ZtwCud&x5y|0lSB%Out zIS`TAn5`VYd`YV?awyn9;hg4Et1ZdF4Mr-D3Xe+Oh?*18pR?rEtA_p8aT@YkUA z%6y&!LnkhTnw%eu)vGnEo^b1WbGmA(^twtjy=y@Q1xL=mM=+wh8u$hcQ=_1nMk|}- zJdZr(%kv9L@6Oy_`}B5xuD4?NcQ1bLp=s!dHlE3I8vABKeeHl4RVAFSNJ(TCFaDHa za%nx3gNP=Rr2FX4tU7$XS(^LQ*DT6>=GCCO*=u%symn$j=b582?1z`{cU$}=z1n8( zAKPR#0h}@wrD9yEX=@^Ng~Tc@#^rA9xv@yGv^&DiV3Wo1m<1bLDit?aVGogj8Xh13 z{VqN`#9@IQ4iLi;Cz4t5_5;u#U_OAhWlx5lKelEOy2rv}?|Z+My?my&@oQY+VAbpV zA_v)ZLvz(V#)Q|(L?_{hQDcM0kDHgrstpd}wnYgBb!lEFlUHrEIKB2J??pLT3cV;+OIXXe*3i_3jV*dGVd@3 z96b65dB<}Oe%*0@)}S;%p5C?+Jv@U$gI$mPi{57JfnJr`WQf|`XMq^E9{s4eujL2t z2D|)e!x;w8)LdU}w4PAs6)S(=KJHy5i=RC)s56=DS90VXY}18X8&9pHb6M?!+ZMHn z|9oUu+CN4f0!VLNV?CBTp@~2V5Xu>B>ZvF(QsvYZB4a`?&~VeHSoi0>2!q&8Q~VbA za@Jh`67g@RLx=2}SKoz5A%JDDyjml4E84S6HY;muR*awXqwxLDoXc4&izO0?JL6}I8YTTl;e4fTc_<; z&hy$Ept_E9GELXqc3UvM9HL!`&u@$sXWTs@C-@ANZ1nj!?y8r+`m82i{C*W=WOqNZ zUbf!VZ=IOg!Po>FG{CRa_U!+%NI^jbLV>ijG<(3ei~Z}s|4dd~fQ!!5h`0@9k9+(Z z_0{%4s3z?g9-aHf9R;}b?rrRAy0(-oVW zjzm_ow9`^XI0dB|uLl8-Da-sR6PV5Y0P0v-(Y;N>22j3uxA}>YsS1&-Zua8|O3%^O zm7Kl&zzMIYgubCSc0buJIqV!B+Mtk`?Xkz@xv1z&KLNp8Tqs`ys(Ti&7T{#za3`}Z zJM}2tuZrm}wHHp6b7;y_5a!XytO>Ky%-ddKk)Jc+NFCz~7b3p>af6Ze5(V)g#<{(7-3w%Km~#KGNC$qt`??JQpU3gFe~wYCnZHQ{LCjb_`6 zO$dtY8^WJJ7&rVe?j)}mo;*XnjTko6~n*MaLfSB0TL!5-8GcN2a zxC@THes&)}Fj zySc?^aYl=t5l&gWyM0dwcjt1ckE-+>QoWoj7tC$=F!KHrF2!(_OMHirpuNl6g4(+5 z9c?!yZuRkmRPH>R>mAgYrMo2eBMbOcsOY+VntR?HP&DpK+rl@_uO{2mDP-@m->#=q zy7KEPCkrLXpbgnJGaXxMVXea<#&NL+gGAGHMbm_~O^u5ZS$oH!ahy{bk1IH zWP9(dq$Y*1XsfBhVj>`_N_KoRuSq~5*1;;*94}Ve+cv}Rq5n)RF|*AY-&b8ts7ftq z<2!B|*idnEQJu3(9SP?LJO*}HClyi&0{NF+Wb9>Z<~@C zIED(}FNAH))B7EnKK5`_PsL?Fufo*{AK#uu!tRM{s@B~3j^6~Zu(Z4szt}h_2u7OR z7j_kRtpg}-Nda+4hjd>n zi}}|AH!ltXP0@Ude~%y?E~vacKQ)M7E*Q4bZF-bh(RN+x>`~7t$SCl>e10OLO^P)I zd_tDXB3frgx>f;c!uFT1@w+&9v(d@K|HzKqxmr>Mca=(6VG72JK+wl~NT1i#QtkT@ zYCJhf)*l=8s3=>OV5PgE>Y1?h+lj)x4~lQ!GoSJ6^H-g;SCc6YD9s zzp&&uo25OTXv9{FAm&x`tSw*TKBUHYo&Sl8MCP9RN3;IQ_8tKL) z^qq$G1b~|q&a62tG5*VGRQ%EUVi<5;Sus`+x>axojIqs4OgJ?U-Wk2G%ng@s~!F( z_F+rZif=Cjx~|NXarfhZTvG?-G50<&>LcwZLrryZ=3t%9ICj797V}N>ZLSI(9r%^k zxA$C%e~iW<{`JsaGt*0Nc$AbMt?Vl^g>ao4-T9*@Q=-x@cPiSm=98C_-*(%9{5uj# ztu+_-?rW9liMEb^xA7CZi|`^1v@Qd5gx7cVjl;ne&DHEx9g!?FS6xll8Z%I-#E^xl__Ez(Vd>JT%7~O3 zPd&IBL!`_#JZFxobKx;{8ntYO^Guz3jJEw1gy}2MNaLd%5o{6`X zkGda~_;HI5{EUuqX9F;>(%5HKt50Xd$~9(bTc`%eL9GEITU?Jbxc%r0wO)x?6|eG8 zd`a0iT$ysm^TOg&vN6_^1=!Mh^CZ97BJ)n=eEoEs3NR#mz6VZASfQ@m>F6jRd5i1A z-TI3M_i@R6tX-1lbv)HcYx1yHYmAfk^W?kydXN0$qKM2vLG|I@&@J!<8y{}NZ<<7x z>Tz4tKs?wm9Yb5HdsanC8WO!uB?^lf;6m)OGqH(1%HS+4*Vgz z{F58fkh-IPoB9WZq5lq+MN>3-CH2CX%oj_F^gt9Cr#awW0T59A`}>ta)U2WZo0<{E z#u9&jzp{cF13(34Apqc?8PwkU|3AhZiT=NO!$$QypMCtX=FY-?2L4%XvcdSeq5X;f E0UiHjHvj+t literal 29371 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 Date: Sat, 18 Dec 2021 00:50:13 +1100 Subject: [PATCH 0784/1892] Add shortest_path_visualisation.py to assets --- .../assets/shortest_path_visualisation.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py b/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py new file mode 100644 index 000000000..485326035 --- /dev/null +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py @@ -0,0 +1,31 @@ +import igraph as ig +import matplotlib.pyplot as plt + +import igraph as ig +import matplotlib.pyplot as plt + +# Construct the graph +g = ig.Graph( + 6, + [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] +) +g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] + +# Get a shortest path along edges +results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] + +# Plot graph +g.es['width'] = 0.5 +g.es[results[0]]['width'] = 2 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout='circle', + vertex_color='steelblue', + vertex_label=range(g.vcount()), + edge_width=g.es['width'], + edge_label=g.es["weight"] +) +fig.savefig('../figures/shortest_path.png', dpi=100) From 533d51277864813487a6a4c7a6df127c06228c3a Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 01:31:32 +1100 Subject: [PATCH 0785/1892] Add "Visualizing Betweenness" tutorial Documents how to visualize both vertex and edge betweenness --- doc/source/gallery.rst | 2 + .../betweenness/assets/betweenness.py | 39 +++++++++++ .../tutorials/betweenness/betweenness.rst | 63 ++++++++++++++++++ .../betweenness/figures/betweenness.png | Bin 0 -> 380066 bytes 4 files changed, 104 insertions(+) create mode 100644 doc/source/tutorials/betweenness/assets/betweenness.py create mode 100644 doc/source/tutorials/betweenness/betweenness.rst create mode 100644 doc/source/tutorials/betweenness/figures/betweenness.png diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 45f49e62b..e669406cc 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -9,6 +9,7 @@ Gallery This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-quickstart` + - :ref:`tutorials-betweenness` - :ref:`tutorials-bipartite-matching` - :ref:`tutorials-bipartite-matching-maxflow` - :ref:`tutorials-random` @@ -25,6 +26,7 @@ This page contains short examples showcasing the functionality of |igraph|: :hidden: tutorials/quickstart/quickstart + tutorials/betweenness/betweenness tutorials/bipartite_matching/bipartite_matching tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow tutorials/erdos_renyi/erdos_renyi diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py new file mode 100644 index 000000000..af8c749ad --- /dev/null +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -0,0 +1,39 @@ +import igraph as ig +import matplotlib.pyplot as plt +import math +import random + +# Generate graph +random.seed(1) +g = ig.Graph.Barabasi(n=200, m=2) + +# Calculate vertex betweenness and scale it to be between 0.0 and 1.0 +vertex_betweenness = g.betweenness() +vertex_betweenness = [math.pow(i, 1/3) for i in vertex_betweenness] # scale values so transition is smoother +min_vertex_betweenness = min(vertex_betweenness) +max_vertex_betweenness = max(vertex_betweenness) +vertex_betweenness = [(i - min_vertex_betweenness) / (max_vertex_betweenness - min_vertex_betweenness) for i in vertex_betweenness] + +# Calculate edge betweenness and scale it to be between 0.0 and 1.0 +edge_betweenness = g.edge_betweenness() +edge_betweenness = [math.pow(i, 1/2) for i in edge_betweenness] # scale values so transition is smoother +min_edge_betweenness = min(edge_betweenness) +max_edge_betweenness = max(edge_betweenness) +edge_betweenness = [(i - min_edge_betweenness) / (max_edge_betweenness - min_edge_betweenness) for i in edge_betweenness] + +# Plot the graph +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout="fruchterman_reingold", + palette=ig.GradientPalette("white", "midnightblue"), + vertex_color=[int(betweenness * 255) for betweenness in vertex_betweenness], # colors are integers between 0 and 255 + edge_color=[int(betweenness * 255) for betweenness in edge_betweenness], + vertex_size=[betweenness*0.5+0.1 for betweenness in vertex_betweenness], # vertex_size is between 0.1 and 0.6 + edge_width=[betweenness*0.5+0.5 for betweenness in edge_betweenness], # edge_width is between 0.5 and 1 + vertex_frame_width=0.2, +) +plt.show() + +# fig.savefig("../figures/betweenness.png", dpi=200) diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst new file mode 100644 index 000000000..0edc7fd36 --- /dev/null +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -0,0 +1,63 @@ +.. include:: ../../include/global.rst + +.. _tutorials-betweenness: + +======================= +Visualizing Betweenness +======================= + +.. _betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#betweenness +.. |betweenness| replace:: :meth:`betweenness` +.. _edge_betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#edge_betweenness +.. |edge_betweenness| replace:: :meth:`edge_betweenness` + +This example will demonstrate how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively. + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import math + import random + + # Generate graph + random.seed(1) + g = ig.Graph.Barabasi(n=200, m=2) + + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 + vertex_betweenness = g.betweenness() + vertex_betweenness = [math.pow(i, 1/3) for i in vertex_betweenness] + min_vertex_betweenness = min(vertex_betweenness) + max_vertex_betweenness = max(vertex_betweenness) + vertex_betweenness = [(i - min_vertex_betweenness) / (max_vertex_betweenness - min_vertex_betweenness) for i in vertex_betweenness] + + # Calculate edge betweenness and scale it to be between 0.0 and 1.0 + edge_betweenness = g.edge_betweenness() + edge_betweenness = [math.pow(i, 1/2) for i in edge_betweenness] + min_edge_betweenness = min(edge_betweenness) + max_edge_betweenness = max(edge_betweenness) + edge_betweenness = [(i - min_edge_betweenness) / (max_edge_betweenness - min_edge_betweenness) for i in edge_betweenness] + + # Plot the graph + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout="fruchterman_reingold", + palette=ig.GradientPalette("white", "midnightblue"), # define a new color palette + vertex_color=[int(betweenness * 255) for betweenness in vertex_betweenness], # colors are integers between 0 and 255 + edge_color=[int(betweenness * 255) for betweenness in edge_betweenness], + vertex_size=[betweenness*0.5+0.1 for betweenness in vertex_betweenness], # vertex_size is between 0.1 and 0.6 + edge_width=[betweenness*0.5+0.5 for betweenness in edge_betweenness], # edge_width is between 0.5 and 1 + vertex_frame_width=0.2, + ) + plt.show() + +Note that we scale the betweennesses for the vertices and edges by the cube root and square root respectively. The choice of scaling is arbitrary, but is used to give a smoother, more linear transition in the sizes and colors of nodes and edges. The final output graph is here: + +.. figure:: ./figures/betweenness.png + :alt: A graph visualizing the betweenness of each vertex and edge. + :align: center + + A graph visualizing edge betweenness. White indicates a low betweenness centrality, whereas dark blue indicates a high betweenness centrality. + diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png new file mode 100644 index 0000000000000000000000000000000000000000..1d61677bcda8f5b94013038b2cbe2c016dba5779 GIT binary patch literal 380066 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

  • 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 z%0D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 z zvDUZXJHc7ocSmhBzD}%IJf&E#?I2ie%AC$Asa8CWJp10lS5aRhZv(p0HAQ08{Lnjh zdVeY9??uPSM|ANO5%<*9)g5nLo;#m#UoJg30W$^K%M+=~Tg=1D{JMt+D(Y-nlr&KZ zgDK=3+QRO?u9h~q`pyh$Y2A!hD7Nj}_#AqjF`l0*CG>{8=&1M`9Wq2$SFXLM(G0gZ zJ>2`P_xT)3w8CG3@uGtWG@Oq$>e0rnNF2#nI)OqNW%=q=IL!3I(i~wdr$$C_7Dk2_ z_`%*33VI9zbVJG*QD$bdbz(go=`!8r$}y+J9#R`8&vJ8l^Nq4XG?%=^Q}U>I>uiZ| z5SP314!{mf%QjlWJdIH4yX?=^w1j;tNWPX>g3z`=bDrJA$3yG1DAqN-Uq3n+_VlK6 zeo(66Aib}w+6g;f)IkFeHd@gu@E}FQwpK zQno;P2tH_NCCN{T)Lcuqn^MHP<5Cl2+3_cFOh!x-<$g7FBWZkxi( zxcY(M-?acEE{x_`)q5c%@am}hc_is?CiaxBbxzvwzZrHk_V#0aY33{XWaz!Q9UH7_ zGWeQT;kKd*29VTfXaR147hso7;k`e!XjsEjQ5fI+()5z(DzEMxml9atdAD09@)j4aVOwc7i%Y#GC=5IJ~h`xURiE0Y(7ec+hzPKhE zTUV^D*&K~?G$>HEBdb&U?H24RuQcczf112K2dVm(&9j-AN5(#u!RbQz;WFPK3Buol z)6`jJKJ{zWwq>zwz!oQkDFPf#F4G4CHk-eGHI>d++JQqHg_Lbajn!9j)~Kk!?!dfd z)M&Y3fv_d*;qO1COLgFSNw_n-z=ljbcfqJ1{5MbNVu)rw?Y9EOMYk31TMeJx6JpE| zCzZRWG>Wx`^Set#_w#Thvy`q;7`K>8$yJo zc1WZY`O`{beu`u!-<lJ%=~rMz_Ar~6Yod_5OonwK<0k!}X=O?%n|cVf-tK5VdbDpJQ9-IAGB}a;|~ZhtU&HjU{Wd5?KD-h zaT?v_a}>NG zt><9^*R8r@F6Z!FhloN!fO0|UP|Y*A8z0m5${@2Jo&IsiXWOFFrTkK@QL_?cK;P&eo`xV z!G8759gbfiVs38wLNQ(IZu`uVbahSCh2Z7u`%m`up2B}LqvD2h#@M+gK2Zr z64Y4r3@9pQ^9HTkR?5wJi#HB@)wWN5E34eZ4tw~0Oe|au7S1Mn)Mk#s7P1tB>Zf@4 zp|F8rYG2L*`Dz+OuHI-tCZDSxi1d}q^Ecgw&5}Jy?B+$HgN2{>@8jY@ zOh!ZF>;AOto-UD9OI*l!?L#1KO@2OoSer8IOMRE`V=Lvbtror@Zls2NUa50rd^|RD zVpgua7==4U@_lx0gkCiK4~UkoXoWfltn>2mu@8E2q_E==U`BNCj&Cr_$wB>;B%;a# zZi?O?>4Jxb6jW&aSM!8kWf<02`UraQAq0j-?F3%4x^4sjvgb8x}|MN3QQjN0UuYCcBwlr&os3vH8B z7c#Ry4I})QR#f+WL;v`)cz6(4=z*crZ4s*3{e-7%aOuzgFclVBR;(W26uk7zZF*r( zxEV<)I=v8t^XmWyk{nQsFy{Tpg-5}8izhXjx!b5o{Bxf&EL?}3;}peHk`sPbhc?**6Qjs58IjR83N3P(NSA5p{~XL zSJys#2z9N6io+B~XO}tjP7TKF2M79cQ?5|jDY`u=w(#%Ys&<1jEtw72U)RarJ-FFl zVrUXsBl}1m>^mIyH!*M9aJ5WTGnCL6<_|}6D9JFcsyu$`E3Td8{RRtgPDmI~xtG3w z@p^5}AOg+BSM)A_8uZn$W3ei_j%`o2B}qh-j({&t{M(({58tN5#J4Kl>x-f8UfB6v zm#IraqF!R0c}LwMmUdNlzwSvr>YVSOk8HfpC7+8E+@E`SvMGaBxOjMd zFM7$~p%7!&*l%)YI|mYEFeyUz#cVlPClNpW{X}f`!S1Aeh!VYlpuwHwn@oykuDqS_ zj4O{`n({=vQQ#M>1F?N-7sHknJms}DTBX3(+g3T1Be1TJiC9F_!|mBc($^oq<j}((Zk_7EN6Guhi42$2n2$~MRl{XzQ|1dqU+h*w|RJCIF#VB z=(^2Mdmy+nP=x)^y>C+DiF$6}Y(wFqK>V!DR-B$4i=cv259cGjl~@BkvxQ#gM%9bK z6z%D!^%~$4?d&(@=^%Im-X2tcy4vV9>j*=AkTv5%u98u=@bz62YM&6%LB}iAMgLJ% zOaK>;KkbpJsnyJ)R=l?hPlZ*P0HrcK>qw^7))2>D@(-j@X$sY8m~$OSnB?^LT`)Fp zHI0OL@$G4IHoWWA_MYUGDpMeBB06v#(vfb}mtT>0hBE18|yDaYd57z^eL?J_UjMVoUo--ea&bfHKvq!3+>^7*M*dgC@S$hvF_8nv=uB z-RvJQa6lUI*4|Q>j_yJP)sppX?I5}Rj5cX1{KF`}Ht3df86=)F*;>+H9>-DG_vQ`z zJP*4Eg>rjQ=?rRxTdNh{H^{VKa}LweKdP}dE-A63r5Qr|&Ka~DSc|YWdGPo2afJOB zJ{XsQ?+)Fxza&jzAu%3vYL==)xH%IZ6R(#%|$u{;wBB~mpLl?|``S6aG zmT|xVd4vo>qw%}?dU`Fb)%Em+FG;s|Ph$GTKg4>Y5*pELTP-67K->dKnh>Ibw|H+) zV!+#BTwHthTPRcvaR~}PAsrl_<3`@fc*90J^;7OscDX{pGpr~U0UWWLD(BLhs-jrY{>Ys6yD<6zP=U9Gs)zHJeQ5I znH(ZesPt-6xDg?>WHx@$h=O>@73Y!JE^XfWRBvzHn!otfM}BDpGBiFhje22871wqD z+FYlD;0xttN;o6RB{S-L!Z6~?32}PGa$Bn_h?D%D%6@H%+2f^~*AP(3!!#PHUNSU> z^~`dw`Z4JPDv}(h*4}GY2rd-qun2OH6tVR=Xb!JyU+*P$st%RTX?TCb`Nq%}c2Qf$ zgM?l(5uZ=aS=Y)muPEec>tw zO}+^axi@kR8hLmKiT&gdj`koT7l|IO)ix4Q1s}Q2-JyZF{K?B1cgZ!6xs!`YaE9*E zNcfVlf)EGrA`pLrBC;34PkoGQE%_mL0`WCaFJg&7X1vYSCBnk@sod-+3atHge)yB^kCu{ zDkOuQesi`Yb8q43*4GhexDo_W^_QlH*xS2|a%@R3{}+fLpm)el5n@&(=H#S@|L%f= zjdK$;M=mO<4o476n%(g1d%f$ky~WeB(S&K>VY|Feg31$fcGes$F)NuZ^3_2=07s?*a4IS!ZiVx`aXA=68iyKH8utR6aS25$Y5UsLL+W z>4E~Ya$PW;b9+xJsNryChw#!RFc!C*n!!|Xa4_hDRU~sFF2k?^e*N^bG5ex`U#?Py z!E(8=@0eNO)$Qzb3<)@0jTWH?f1eYyI3zua-kzqKrK#LnXKLQquH|0VdE7}Kr% zIf$^FvP}UqD)ZLN`hQvg4UWJ$BjBD#q;QoW|75%?_ByyE$;5)T-vIm5OEhq_L2v1h z>8WNMIU6x6lM&6#KB}JtGmr{e<=dDX$m%`sA3}FTq?iDajbEs~Y$E#YFa}gb?PjSM zxcL7{N_!Q``V>3NIbXV9sOTXsm+4~0b$!XXN7q}IXQB6|xF3wPHgt=Thz&q9HC#j= z*zQX>puV1VlFok^E+Z%fkrD1|fFBxsa^Dp%;r5NGRt&n}yad5NxL=1KHvj5Aw)#X( z1UrgA1_*Ex?Ac6pGlq}`C;!V54iMR)SGBZiT`i-b?}E*i5Q|68429ZIUa79Yt_v8e zpbhTtre%yLE)S1a`NcpC6q*rXF3=MS6P3k0Zg{a9r{Ie)F{A*v=$<)z#adXw>&2yvN z_5G$d!*D;A41n+XHPZVdk_cjCpqw-QcVy9m-*g}Qds5R>(w6+IcTDPs23C|{Ht$9+ zG18uytrJ;4-b8R^qm0i=^#j-(aO2g zh30pNj({2^>qayNsuMK85fS4V+G|h@QPRbj@~(=wzBM<(pr^@1p^USJmP#S-4Fs5? zn0@_XIgnUhgX_5iX2@rQ&My=!YJu5;ZtZnMZI1;3^s(0Y*?_}>4OB=hfs|*x?Tlah z6EsJNgd04DgMiyZ14-XCCkqZEvzJ zYA~8!n`;{OHJtl%&@(wmCi||qUq0{6=(88Ct=FLAhwe5`VzhS7X59{2$X^Fvo>wr1 zNh>~o{u%H|os?!lGlPzes@?Ao&xCiXXIoD)cdwLS&Ree43&L&t;K^0`do5o6wlUMcQx?baR zdAZNHbzOh)#eeslkPJ++fGlvWWjsG0W+%7T)%SFlYvTfQ52+c^P(l1$8;KC( z?4eUKCSkv;HIjy?nb`pH6l#n|Jih?k=`tIVIdrX+W_|e+A|N2*rJTGebd=jKpsHz^1CX7TjN9?Ypb3$`z z&$yutJ@orhFX+f#rA0cgHvQ#DU9O?u`I~s?)qwTfsQUJG?!(f3A8~Dsg1o)zQ9e|| zzsygzVTpoLRDLp573lB4F+L0UTpntV=or}=mq#`ojMDN@A>b288j1u9rV}+97g$zJ z11-T0kew#*7u}C{Ef_+jBdP?q(tc#7_uQ8SE%x9{V?R85P~WCNEDwx_eJ47{u)u^2 zES05lnlGuVoiO5=RQ6r#$7Y=j`!5X!u^$8E#!C#hz^sfCwtd`FX99}Huu*hib@;qt zr&AbuOHC~j{%n6&F+es@L9-G9ty+faURrG1dgaheNiCC~Usya7QW-)S$%vA6wV?u` z>w&-l`@u=dk~nDY3JagL^>BKj%+R3))=07vA)C6b0zO?t-rgygHb%X%v7b zTxgx>X@FQ(-up-hiPzy)RaA3xXbK97`fS#6e;pt1?2V>JCaRHVqV5x)hBoYq!Q4$-Ig1C6t|Hgd(Rj9;s`+vfZH-UKkw!kNjF9y`a2 zg2WLVW2Fy>3G(gC2K5191Nq%mXbxQ9TR>aj)o4#q?PQC3s?wuN+HVbWyBs&h(4T>^v0MA#8D|0*PAS)A{+kCB}_akGd+d zFz4)Itwl5QHPit?1RsQZ{An;cBzHfJ@XBEUPKuUbFCkVmQ}rF>HB}bq zS^y1;s?=T>aosi*LsG#|$3l+`%^r&W;$d9i_v&ADS~^qbHr0V&Z&Q1KkOT55X_Ub% zVrKMR%pf5?=b14Zvc9Y4`fvX>hhph3E+?MVu~?>IBIWf=UEKmOg_syF5KaIszq14W zfXm%_PQM*IF-;{+7P_Q1a}Bj8YRe;%$p@Fkb1pU-=DU6?)d|*(6lg*wgxC3L z;&Z0@5&%N@YE;xXw?(NRnK5?ur{_|}9Nxs>3u}|jd0`F^*LAb*`@FCi=_YwE4-ZfO zM0quo!f%-k3k&bt7li?N0p>Phj*c@oGwY6^+EK{g`w!mF$EVnIzA-lDZd_UAyM4L= zzj4Ofoc3#{9|~_ODhLyrJXL?xpW7Kc7UyzBP=F*tHt&r_fkPwiN73gQJ*3Mo7m>x> zool>*+u&>7h@O9C8(hnp_uY^9*KBND5>zSda-RXUuKKjKJz=Ue7Qr6b2U8e{swuQmEnGBTn` z;;e<T^OlLp@}m()uPtx?JPja! zuj1Ui5~?8(Ry_0`XdKuKI=N=#g=tZV_r7eXXEDxe2X;e}wZqQmv(uodQLdB9 z(saO3!L?qwg`ML5O9$s8h^N35IqP2JAz3y0!2i{F3XsSlzyntBQ8$^uHH8TbtHL|X zKxa*vJtzl?RG=?=E$^x?(_FynyCv6DIFXR-0PyUJ^Wqc{Y?$~D7z_RH>*k=eCr_xL zZ-Ro`RFDQ<8?T5@W>XV1Y9}hdR>Bf8d7s~9xrF{iPrA&3%2#Ddm~ln<2vqgnGHGF9 zj051{070ol+uQGHuxWvC05)eFl{p&FL7l5O`ZvNqL`1r{xx{T?7pJ9U=!{fVd+Co{?tV=vHQ?M~xwP z_v7i5s;aRi{l&E!y~S}JNS)JA;(5_U&TsRBnAmyGp!q;inYo!2RS&gv3~0TluC=cD zx;+h+TcyBKLm0L+W0aFL`D{a4?T3p^unPFle%cb)Z z$WA!Z(AOT(oU}=u1=%=G_mezmpb2Tc!<91sy&wpde<5WK+_%$(q^eztAy}$rt`${Y z<9=RPcvQ2fz3{r8{R`*MlHQd{4&F@Fk{EBUidk=QC5~j2maS^@O6qu~<%q}S7_}$T z)BZ!7GfOukJg&%1ILr?yaD!=w(0fgX-&0=ht(MI@G0lrQK?f8(lxNBhSbnV*$Dp&o+>82zDTPeLD zIMX?q9Bb-pKK05T-(D%#2F(Z*<$NMk=BB349|WvbAODiSq%(G&{$R<`u$MW=BPrQe zdilqB2VBvEravt{)FRWe%)%BLyD6j-J-ki^)e`hMQL$f3R?H{Xbe*+qhS$M10HO{7 zQeyZaI#v!`d>p2@rV1UFs+*yGS;#Rs(- z#CTvqq319x;Sr~0PVIYy)R7z&+nFe-7ifmdXs|}|TW9RgwF<&rN#Ty$eQ>!iDs@^O zrgPKP30P0aEQ)!%;A#%oIe+su?&YJQB_Iqlx6a1ksg1$*8Y%GWB0-&F1k+DoZSoS9 zK}OTxy*n!NvAWuR3;?!p$EmZ=dAE@K+?M}*^E++m5-3wOstnnji68Tu_AY|%58nQ~3r?bnc=9GaVP_^2nCGA68Er0w9(8Dx6c#9aLhg?(?cyCa$V`ADL$~!9*UT)N51t zahYz3Q8VDV%T|NWWBuiFslHf}HP1@QYrbTP06#+_!2YY9v7pE?hN+lb_P|SM8-YL( z@hHr;A1nFx<45IhQGERVv+b};#2v=?yaL;ek}pD#=p_NS>#`Fdj(EFsGMaL)R>P1B zS2aHsLI8i7&uiKlWWcJC`iJ&oJ=0|C+IFD~xtmjDe;}PvSSV2T*=pFeo=Fh|t>E-K zyD(uLWI5!K9r))S2#15ZwqVs$@y47`d}+`*4N|RP>(VHzYixw12A!;!dw`ns7ALQ(ry2E7W`6{73of0v1&SnzMJt`IrSjM2 z*rKF_PSrOs&=7q*ALuRtb-s=u>a z;T1FtqSMoigj!mPOs)b$-07U7^llJxcV+RbH7(7B zZ>Y3BO898FIE7v^Ot~EHR+cuxlJx|D2fJa;*}X$n1ojv{KK$(nx^w!$FEf6H9W8)E z0)Yy}fX#R4z3FS*mIBRqe!=Ymfv`U2FS%Ojl-$PYuBF~w&|UmDUH|X2zb<5hCh1M# z*WqEFQcL%n7UdoKM0W-DO7EBHezwpTzrlUgW(gF;s-VfX6L8SAnvi?Zzs!@K;>lNQ zNH3kk1Hu;OPC)$Ra-9^hrd>Bh71Opp7_bL6XReP4u#8!e#JmH<0Gu;yoR7erbEItR z%cu3Rzt}^%jxp8TXfYLNEdbr09!q!?%9D;?QEktN)LB*uI;)`XpKf^F7uA3!-PU#o z$lpiMApx;nCCE@VKD|6+*H+4;=-ns?b+K_Ne#rc0r5fwY7fj3HVL%Wm@yxz=Ii!$SU*0*stnfOY2nj!G;u@f95I5!JQy_|Xi)6=JsnwxRmm!Jt4+rK3H z8}xm=T`ua7Wa^VS&c1dTa0-d)GS6!YoZsnNdLMha=DsVw5?835?6BTvp+Oq8-AS{E z0OScWbJ2+K%DT3Qj@9s2HF;M4n8E5AK3fNe@OxpN;D^*pPCo%_?)IUbhL$8x!zVVp zA|95L{yEK$XL5X7ohG7vUPp{_6|`=Qif6HmlP!%bYDr{4izE3F2)UW=%7+n#nY%^W zXlfOUAX11a!4L_aT`-6mIdXH=n@*>T#LxFP$s!yfgj7{+zy@s-Sbw)=PW}c2F~|>&epPW&U_0$S)T#LH8U`46Yxw?zf| zGp#zNi$Q9jBdXMOd#(&)EZ}6xc}J;v|1n@=0GIQoibEIWEiPs)lBgIrV%K7Jd$cL7 z|Bp(e`lZn2a>_}c^+hycpvw-?vX03)1?;-MY_RS6s1B@LXD1FI?JB*f!?b=&BGQyU zJP;*TOp_3wekMwQA4kh~%?uE)f~VvZ+6t4tGWz#bQcqtg%1zOACx8WPn{SJ))FK|~&a zeJ-rf4aGxq3Q>ess>#2^1oU=`Ws9yOw|QKENHU7zI^FG^og=)M6S_@Z45eVSoQh3a zOkp7@&QjX7_vh>bCtEU%_1*LpLw+iF-?`VA{lB*V$^-hiua5}<&>9goN7lXC_=;*j zKnZyGNy-0;f*U%B{woeXN`(cOP%}(bjQ}Dy+K@ScajhIEX*+rBG; z^#lZmBsei(oG5;KWd(E$%J0-j(2Gpk=K1Gc>Z(8>;$`^ME%a{4BlFHPeFKBXwS54A zfq$Q*@YYVbbr4WEM#7l}eA?CY;`B7;=0hs%XxNyQkG1Qkfw?xkYgI|m!Ul?7mhA5t z!62GsxU7j=?5fw!;I7vC!H#O@)XM=n-~qRkp;gkgwcqgNZY6yIEP^Lp$FrXd$MTL_ zm#T6*HfADp9x&8F8Iyj>axlF!o0Q21c<#)}K&Jmuy$&Q-a!6Q4^{7!?CIEx4C;?CG zvsOR|1le{Gt%47cra{3_;vipY*uYl|lI%y9_``aknpsh~mLCrpH-`XyAKIh)|rSUtW ze+RqhSHDpiad2mKOrvW{rnE zrd~4C7u+UZZnG$PIT*L)Tt=#jbxNKlC^r;s$cK8*IeH5Mnkiw5PlTl?;xA{rcyv+qD_YpG0Vp!eu$Fpd|aTrooP=+1#ckw8Wmz;C#%- z_wek;;5lvczLFH0n%gU8;#vU-ZoOm(s!EYPT8~{z578Q*ETMr6&8XphK-2*W)2ioPO{#-5`lo)zvY^)VT>b<@a zGU4zzi|3Vs#Y)TxRZLylHQj!4{&ajL$soPtlU%7kXv7idv&WrMJfgl&mX{Ghr`16b z9iQCqc837j(q<=+pkQI|<4W_SuyFtA!R+INKNKF7w<0U-uuRDsjlo@n%h=EHML~hL z3VMS{EF;t@%$3VCFf$|Qr-SY)+7CAZ>a^lwaA73z@bH0V6WMMAoTkALF5Dwq+n#=^ zB;#nqk~;y7XtME-Mf>4i*_C|hf47F%Kh@FUab1uRg7^wd)$y_r_s%>agAvcYkAEgp z`!PYuTN@bgRKjnjABvin1qDPJ1*D$!VeC3@K(r0dEs`;JxCeMijRM0BYnqrh-N7l~HQJK%78P6cxyNjCm1vOA8n#EqLd6BM`KUE|Cc~qMls1X=RG4|UKFVK8?etNX% zS)XF!LwDNX>G*VLh^O9DKteNj7+G$9 z&Z&8qZOAfFG`_zLV!F(4W)46JR8VAKFyGq<0ua!CA~P>FIYVf&WvWI&g~jzg=ydvq za{mVwDLT@QFP3pN?_#PIyl-DjoqWIdd)YXyD{|1fYh^giuY3X(z;ijd&jLgr8>f4r z83S$!@_cy5D6b2k`#9J1WXMXl@w*Fmig-5*kUmckXYdsw~ofm28#ATc!+9U^d=`NTZW zG|{*##AWVIrG#gy`LBm>MTu&F*`_WB_bQX&mkw{CIJN5c=`MM1(qID2)ioR@9tO+6 zv~6u|4Q9?vUY88?!ZLaWAz4kq)O}#Bkd%@LRW=3TU%^i`=05;b^2Pln0Gl51u)2G2 zg3&55TM~}c*?ipbrk4qG;w^9#$pn&1HS;7?EBK!lU@cceeWI~G_1(Kux3+v%UL>!n z>sqGEnAyaRH$#Svd&h3z5AG7Kq|HszqSnPSz%j2APf()pq;v8JQ%dJ2u5M;Y{Six_ zki9mtr4#jc9_2ZF4LJRv@)q%}aO>X~>4jDvMhu=wLsLQueWj@;DOK}q?5uMa3>naL zjPRnI;V?n{Im`_?9Q;asY1I7ZMG*SrWHU42|(N0mn>vu`C3^K!}T5{ zM)bo}iXziy9HNF8IwjMu?R6dRmx%@_u(#^2=w!+3lHsn1LTQDx?iLE#OY#3Re0e40 zu3uxe?-~ot2=Sc(YlV^h=ex7h@g5c@g)2$Y4Us|5J0)a))o<@K)RCA>RkWEWQMYd=;-;e6 z(Ix^4cqn^>At8qmR64)XuE{u zBg_#hrGQB%&hW(Qjrdn^-@9|;ss>2Lp{Iq5q^SjazCpkXUtyAY#O@+{tp4yDCCt&4 z57N&;cgX>X_F^^Lc;$R6s6xjR&JKEQ;bM1dST=+1M$!KHk z2<8@Inh4R@`)?T5RLGpB^m1m(gIXN`tv!Em9WICn(gLfTPHU;tVu5S#Y_}3G2S^>`Ymj@{66*%x~K4OSx;+ERuYZhEtsrO=Fq{au^wMz_> z(@Bcz@5L4LOskvt$G>$y-_Mg~=94nvA@BXJuTTV206w2z3s#-XHDLNS5P0dwf zK(RwoPeZG6kvp0Zto` zFBsaKHtNb#%7s(EcwiUGmQZoX_#*6zZ2WD=je_zi_m^ZbKEq%|%N;4$BguzbvhGsT zZB?G0V9(Y|?C5ChG?M{bQQtr&JA3nAVl@4KYS&O;9FUEaWrRGvtzkLOK?uXy3va`v z9u@|Z?Z?$qU4!R8N_STuToOSoWm2;8VoU532VjLOFVllPb0w-HbWhXz-(iPYmvT>2 z-4Gl&siU8F1Yj3{Xxbs0v_F43_)e3-Q0O){G054E5qtw2+yEhzb)*ogKUjKEdgb%OfFRD z?dv0-@T{$fVdw&AA1G!)s-cg&t(_&56nUR1K{`1Pzef)b{RebuPDq*s)J>H6!+oIl zKz95CMoBQjhL5ibGA*R_3bc!;ldP-Itni6aTh2D2T9u=utB_PE<>81cnJ$F7=eahD_+0C*jf#{Nos5_p|}$@Gy> z0uPz=W%kyN!c33eF5j0Y-&BVYAkuZ>}*1*T(qZKY>^&!&LbU3|O~ zkTTKIX35Trb4Tds;qDxIG6358qmIl1!WU=|5$`l=@o(|_^6h~s;WLwqr3W9)yPVwX z>Z{FCxH4Db<$VRUUY6^}2+aHWik4YCdVyqFX8ivb3XoG80!g4FE)kRGNWArCjGH@Q zf1h@te)gOmLIQ*S*abbgRUFZvr?M6s8_?CN^9rJwEcAoKafAI_e5w0;&+eA{n0JLw zJFzFcjY%y*ilkGO!Pb_=>F7)5qmhL;SD*76Ek_zUD|77;PRMyWgK8^QawRbC!Mr1$ zRSge5gXt{?g^b`zWkG)@l!VUBez`7|AgA_!awEyws%x3zHIxV_j z-}BM)6Iz^`DBGuFLKlAAaKNs{StEsEV2I$6mM-BfzIOxzO#nRrP+05hks;48GTByN zx3-BL%m|j+y+v+e{bhM0}YTeoe$Wped7Xk71b~wuG_o>2$3KQ@-$Xm1ooF-pwz7I{TW*_-A zGQc5bMd)F}D1Mii=L=;k;921UUcdTki+I#9cmvsuA}7EAYEmbq3Trc@A*82^`QCnL zu{+O&I>C0hH9H8~EK(pr;?29fnmuiteV3E-Na=8T{12w@ zcm&S@DMm*v@es4H(0iwGtJr43#XItbJVB{_kh7J$s7jxU@Nz5>1wcZM?UM>+%mkPr zJtFJe{Bj?LIk|~JYXf2nU@$s6lVWUA?j!Lil;XR-mF77#dZ?eimf7|<-U6F4kk4qc zJ&-hka0dhSXw_47H*bvg-Znt*Tfx=km^>~TT}aC})E-*hBtyVdd_`VYvpU8#+#FV3 zse^}cyLsG=up+yWZ+S}eLGQ$`1DFhfkY1Q1@9uSZ`Fq;uWv-V8^TkSl$;N33 z+elO0)O4pO&BvHl^k_6ZbLly(E2png@eHtE+(ttqfW3Q|pPBA4qu;|`zcVgPiT5lx zbNrQQC;PNxz0ql5g65>x>U3bx`=Ywu5d$s7Jhp>9k*@qWEqy1>;^eHlS--aM4p*QS z7oXD*NRx&}nGq?J!@BPE60tqJG3^8`Y&wj|hK%PKh8UBC6Ca z)9pC(CuUB3HZJnoohiH22}iQes*Ng^C|%G!@Q=S|U;oW&Qp7+Xe{9j=!O5Jve$`p6fZr8`;&<1Q z*i1bt!yT$B9=SQ|q|hiSQISRov@iNZ$38!lIj#nA8Y8XeqsO=L?_O0a>Um*FR#^DR z_Euv-y+$(GE9Gw`oT{uzcJDRUAZl{1f8$NZulcj~2pq2xSxF0zn=g-UH|!?qI37zz zya@--qn5@a$xwOvRFIX%5GN?9b^l`z8Z_ zmN$M4nJoTUFAZhd>G$Tteu^j>L5DqXgoKzi%@S7tQ>Qc4sx#9j7-{T*o_dmPS5@EXieR&32MX=Vf zeXAi0t9j5%>YesKOsRXp+*0Q^jXxGT*$Ay9RnHR?c$zYdSqCxAg@t#uJjNaBMJ}C- zPfKgNf(GA~4u*Af@RO5&J3blAZizDSw`tq^(i$@Dz1^y3QEmw>G+?fhC+GO{L-G`$ zs505I;Uq0onb1`(Ui35=qnLfG(P4B#b%XKEVWLz0M%C1$5js4e{7AWSUHvaDFlXt` zU$LkP`#&N{ShTMxlJ6gc?f~^g#~A-ew>W>srPr12X!_{JD`iXnU-uYHz2u`J%yP}Y z&hvoQ>jtT7PW4#SrW0Xn$wAR3sL1 ze>Ad=LmwoLV}wP(5c>h^p+V)RgpM^k`hbAInrRA8(f~&{XJ~Pt*efqrwBWV;ZifRe z-q){@l4kw$oGHS%^xWd(#BpjO6H#NM@lRJW3*MU?+}1<{^;P_PAIY?JaFJih^ePla zPiMDa-Bsuto3H$IY47fhmC;*_*zsCfX+t<0n%$aBqR!7JQOH-Kq{FY|S2NI6$T8M& z8PN)Pm8E(up7jnX#{OXzPAZK#mOBTh<%?b|*oBM!^jgc(C!`S6uq3)kl7Tms_qQh> z#gpG8Wx51)1hDC(`es&mxS%-}@&rb~hi7J4yef-=Mc}^08b0hn2S0|3Yl|&yp1276 za9j<8&b5wzTT6x2Zy5(OQC;tixluS~a#?@ue7PZY`^^4EuKLq1^Qo)Pf7Qk6tLSZ! z8X6B=%PxgKuMJC_YZ`l)TCMCIt_`fPtC5n0gaiVQy!9H)i;e+rCVu!3_XQJQ;5HhD zgv52QJ>8OZcHVlozFrq=Sn|~3)6l9;@fXCX;L+q&Y<_YdLxmSCii{;qzLas2qH&?2 z{IISKbJwh_kBGEzhw&F zxZ1oJZF@gYpjfSdKX4Ov;z>7_%x%_Zx0ePA!0c#b2-c1DvHIVijK$Bk#gT8zP&v1G z7G@8?X#*xkb`DfWhwG(nx7Jp77JdyOU+s3Z_5SACpdf@gtnAf@@Nj)#elcZ-czB7Q z^;=CI!m$7Ii3zQ@!#7_k6L)rgb`hrDoAvec+bMVuK#KrQ3VPVVpg`IJ%~gxwvc}vu z->Km(n%#yWqR(4c07=pN+7JXb(}Ap7g(jkWg7?$J!|LpGrR(&AZB_a)rFeS84ZKoP=OhEz8ksA*t6RL%8gzbPi5RZzLL4 z-J{AZ5oJ=@ouApL$tip+)up>C)5cc3R6J7I&p3+ULbc9+1m5U6#D@GX-0ZWUWT?K%ax>0u!i_ zuP5Hh(TEpvk6f#ZO-=1Q3Uc6xb{Ve>^l2<{7?)`{v@X*{Q`2pZOG?5J&dkB*V|-xE zn>sY+bp?F=uw0I}m$1W(urV`T>K&&pY9(N&mrKu0Bc4_MW z*4G!?$QZL1tL>?M>QL1;5hEi*7fTl`BO{|C$X6a|@hLouez2;l(k?CbQ0f#bQBDTpobV)2l$syM4LUP0zNVdJ|Jv> z)t40ewqDt`T48E=GfbBQOPzG?Xe#}pX33Rqc=$^9r$~i%x7MIIWo9%WQM7fUUS(&u zRW}`w!4mrB&t~xu!3-yNO9x3F$f&c8KpJ_QXOIYi1}*@0s3FZ~IYnYfSM5J7Xlo5I zdV8s0(ivZo7*s8fe~%MGih<#NmTLXcACC~Hg$F~(q zygHXbiOX>C^1ppCM>rE~;C#*lVuhLGP9azflzB-|r8w;VRwHJ6X2sr-V!D8!rQaOG zL69%-@+c01HS)m+{mD1~>H*LnnYnq)N)^eq-7@=*cjR#%>FeKOL$$kKjbQ%)ve_w3UW|Hp1Dk zprbA0x{a>!2$%6tFy6$I%Y{8$==44o^l4RlS9y}y%sd6J+_ixX=c?fs-yc4>p8a4^ zV(X+7JM=S8YG2JxXUamqb0F4c%_50d$&LdAa#GolG5e6#uahZjN%zg`_g3YDAFLdS zZSSU-Tu~=Q2J(O-6$GNB&JKZq|1+8WBgQiq(!+E&c?AEF;073L!Ig*!Vt+HFT;B^N zF}WE+0Uig_kPZ2S1BPUFK!EX7D10+GY#G8tA%$xY8BM)~Ynr~B*N=+20&=6W@!`!f zu`JOWR&Z@@LRwdHyIh{fz1A$eLF>6ugVwix@Oj2njub(!n6$g*P7@l(Y*HF z$?uwrKaat47}DBK`fT4FE!Z*ec3sr0j5ax$m!+QNfn(oHVX6O;y?4L;OwH=<#l>Bj z+%m`Ml~4s{8a`St^XD_QqKGl5tf641#YBkjf2D=ZAF{{(1bBp4IqRY@MmmIH!=tdC zZh;$$V<%ACG4ik+j{ubadnvLqGMO=d>wl8}zxp!SR=+2!e*13*#Du2w69UC!R#OUv;F+p zR*9oCn{(lh9Al4X1Eks>1n%Mk3ZDIAXYu#TUdxVyu{flfmb`a<_QDb8Q$uC$dR>XR z?X3_9Nl_i)Wo6q{Vm2tR)w3`0;DahiWI6_tu zJqL#O^QdDPOpIrnypLTTJjA*XT6PT`UC(XI*C?0+zeRevjJaN#8+Y;N!J=wty@YBp- z{oTIURsL6{Y_X=ia(ZPdhFrEdH>>c|5FpmLW~om@h>lg#;jBKj|Az1v-OscYp`pen zMm*PZxAs;MZUWIU8Jko^Y}i2v3SlCPMUHY9E9h6fe=mLJZ2Zmt)Seqi5%y>Z=8u0H zbd^R;LBH?0IhI6u#GE+I~x2tNh5ig4b1k!c@8ixFws{!%HVj z*1=sqe+p8ga^Q>YK%XFPaQ;)3-`BW{GP0R4{0+?XJpQXoeHta!wJj~8HcOpK;_-25 zPXv*!&MYN~Bwl=Nvs`2A&sa)2)b0&72T=i#4z+Lxi<&`<2I6!t_O6R9MnmFdU!~Di zx7@atQ@aQ6uiQvS%qCf{b1H&LWNeY+uMlElQR{ zj*!=WL%rgvo_6hz^JmP2<7K14YvkC>FD-tlQ@yq=)qitT)ZELtre;l^y(&u`&AlJ4 z$mqr@avpl|VxyxgL)rbelG96AV4y1)m)$x@tZhf^fzsfRwxlfn6%E{CI+itxz zLG99V{Yvt2u50uC{*F=v_&;-*SoI2;5Diz$ZT;B{qT~*mm-E`&5!dtlYPf;Z@Q#j2 zvfPP`-j)(hOAzPYMNe~Bg4J3&Ki12;1X(Co?5L6K1qXUi7$+%l?ZvuM(ol5-@0hZj z;%D#Ap>%Mz=XS?LMC|h-){QwbhlE_66Xta<%FowPe|uW=a&v=iz=oB&)x~{h&Zbt- zaW1pDm;GM%a{e=?`?xBs;GG^vVPY_DF~McD$MG@-x$g7I+Jrv3E*PB{7*^Nz<=p{A z9~RZc%GiE1+gu{9T5mmKoq9n@DM8aVHE+Av!}P5BGe_kFGcvt4q%`{+AhhGgXP+k= zq$3zg@12?eP4n=HV7L3G_ai#b>PH{^Jp{60AvKW!50e~9iC(RWT93f(@Iro$uQvG! zS(u(1)MCem+!)1;sVpyEofvn$bomNoU3fM1!|&X(uQthYG4~5i`yD{nZYwCa%QCtY z-;~S1I#pBuzS3=7ND2*Q*sS6=p4kzQX2|#Bx4)J1dF7pB6LaaNF0Pisf~+YUY2Bx% z&7@6&Npu0__GWhro_Z53Wvr$N)}W5xu-SML58mv##ynG!j;7m~ zCH}Lguy?#GsH8eHJgY#C>WkAY^)bb3bNUza!E>2P6QP>CbvJg3rFvYuhOw^|XIv&t zn=iyka934n5Wd%sOO%ojF_GU4%y;(Bb#xK`Y1_Y<w?1af7a|4e&-TWYkXk@3%krQKS8D?a{L z3!p3*EK#_c+TGg9MW5Chx255GeaEyH(Khwdu#eRN`DMBwcqmP=sAH0^2YxI~E%8}j zng2W@p%^d4$}hr+1%`xzV5ci)Ctq@zO+845>7f*>-2En%GP@lqtIKp_)0|IzX@n0H z(I+%KR~_{_FHfUyuhbE+d*7EaS_jXgS|2SsSKY6{ql+BLh(sFvtV^GtpV@Ws-Vmx(}6qEN)I}f&zR5}_= zk1IEGoCL9}Omnigt0^IA&rC|m@74EP{Tq+%D910cFL~o_y}i|^lF0j23#9Smf?*I**rAPvu}LW$Al7|Z8@v23tpflpww^F}1<*%C@Sd>(m(|Xz^4oz2G^k<{3%tNo(pGlxIQ;D5;E|*fTqb41WDO-x=qM9|G2YLt zz4!jkBkNRCg$ACX)qxNj+jfFECrwQ4g|MKVeWy>-y0hKo$Zur`7>ef~0^e zTUPpzdrCnN%AFt*U0YiY7aQFli*K_HaJuB zGNH~SI_$CVU*SkDD6Uef|JKn`?BFWEgWwjwf^u6vIV=;UObf=9a-R~jzQLDGRBbE2 zInzkS)5L`{rPoh?ve|k>ytb|i2dr5(Y+$jzcv^&=kwx;v7WxOt`lp<>(>**_jRR9d zeJhjPPf2$XxWjyMn@oKOv_V~NhYVsjtd6ewGpMc1N~8bSlTXtAWn4VNd-+ACPldnc zR7kn-3INsq;{F0vKD@|Z+o*1H6p81W+qAp5Kjc^@J5XePzT9Sx3*?3_MdT5N^%3wp z$i^8NmnUT-njV@z6_1muaJ&sP$NzDP4%QA#i!5>X!Pk*TWyfiQ)`|63SFbNy9xe}l zLQ6;YC|oB26Yu*fCyV<)9CH@Es@2Qj&`@tsPS|sw9Y1C;un;h<&o3xwTdpEVtj0)2 zf#{guGf&SFKi{g$91+~iZU-DtQX&BpPQP-48dxomF99w?5%_hE_v3^#P5|oY2yRka zAmirON6><>XD2K?{3rXmxeRBBhL%Ar6C+(!`Cm-Ri#nEh&EYw7YF?1tv)x_IuoBOf zSWH+kI5*cgttIiHI3UR~HxiQ;gaR?&LC4qEx4{{l|EDMHQ8izlPYt6Vck@i9((6sC zww_hPafd~EmwGvees!r)bShmtFS72R+ho7{lhmSFZf`S6S z)g`qc-?BO4V!f`rZnp6?Db}oZlb=8R&Vk4i;$ERqH;Cmk&EbCQFz{fLp3?$&+v-y# z@dK%RjEBxHzbDEFb`@=^vwr;8%qZvWgvjNY%D(={9VvxkK!gPy!ATwg6m5FB6Xww- z((1QaDX#9qoMh8BrO-f^?>;??;8D^93vG8*hoXbt9Bz@{|w9yCX7p) zJ1+dOJ?&^z%qQpS8Bg@~If)=hY^NdMTzD)pa;216#Q{&HyLSh(z)(&oS>^BrsjMsx z@e8Xi>>k-c^4kb8N@~&f3;!AUHoc(16@(&&u?dw3dZADCM#ujwk4{%3dp)`6A2al9 z%NF~^5Vgfa@0-=o%jWaQH%og533?4K_+hQrq!;7|Q8tCr_NTY9X#j+B9+N!o($Nft z84dV+1k&J4-vET_>oZ-EOJjzBcGTd6p5c$nSPY!3bu$%i42w{E2cZj(O-1(L!G zHjhnnG~2Z?-o*8&^TUzn=Fwx{&L6sK^7N@g7mA|7=x*9`Xms=hYOH>rasosa zy658e*aV(CCtOuUhYqSZf()V*jOG1f0ufrmM~^yDav^8wtG|Csn3_I6EXf9!m}NT5 z_N~d;o2lQ#j2Qa%tvwhn%&H4J6h?YuAG`DUl3%L16+vDp!TG{g;BMmDTNM-*t{jT> z@E^Lg(6bsnseY2J$b+XbR;QVdk=_U1j-w|f2;Yl+-lpIir2zT^Y?^X6;o47bF0X)vD`CN}WfL`$5 z%F!@sa$KY2>|29?^q!2u+oXxbj^-O%l6DULZZ4SXlD;@5h>xla^=csc|p7vF-#^08SZ>( z@FilX%nn3KsdpppXbhrRVhvNTLivFsj6pJrH$?K}HP2Ps|tViYL ze3&WAbW(nHe-!L^4LS(wx6L47Z}$6^eMDvYV*5aS+?GjMCo|~5W?Bvv09N*2Y$pGw zXV@Azq~^zYB+2RIF0}IMp1PH#4Z^`AkQ|QGGVKtzpNgV!4)*uc3h;$PPVO+6KX2s> ziK_)RW`?ruqLG_8X;^6O6a?*%ss<(=W8{y4=Cs>q-{Rs>><}21ocd8VxuizF-njt2 zcI!D;c6NI3;FXkWqJA6xEfko@#rE=Evh6|^=1|f24{hqJg@9>gJ~cHWV%xcPVqXo$ z*pzo!3vqL!_(1{u^x8(VRU)da_(1!4UiNgKt52L!ih5{c29O5LLnm=PRaSxWj-23D zL{l~P>peX)PbZWER_5wXD(Jl&NsQa$!=d^&`KlCalBPy{_Ux(w=lbTePTOOEhz15k z-=EnM@Tbil)>uE9gZvCx7B#WwRGD!(cKo>5W{!c{O&-@;>kXd?Vd+Uq0lR;FE-n)S zqK(tB*|PP-#Y+tz$m-+X0k4r!gUGBxYvu&o-oB|@%85^$QBpx5 zxTbmhdLSQ5SXD4;)6fgtOR=e0^n01D>(Q)hWGofQNbX^$NF2O}>b!}F-J6sd+cn>4 zYV>*q-jX1NT{YljY5sYUf%Z6ftf!=nVDBmEGx!Jb+FDIu3ktKh3;NJN*5*r}_o9_l zb?c)!F!(FXyDqiP&E75U?tZeXp)B1=8IP1X-l8!1HTCi8c~twxrc7t@Rxj~D;;F0TwNZ6+|E_9-z&{85F^sA% zsc*S<F33ZFuoxeQ#gJIm!nVw zzL(+uY5@$qacWycWhj3TSZK8huK3)mfpvKy63I(nep>n!?bdR!AuRlqEj`0|V*Rz+ zd>4&)Bd9)b3YVu)0UvckM_xx;URV zU6Z=}R%Gu&lsc+Sl@wqd{y8Qllsk5G_g>z!gf9;NXBt1>*#%RIfR9B$kB?_TjKtD5 zlQuJ`+A{U~M5HrEX?OEDkQh$KxL2M?4*BiR3&QP=^c#023}dcv^{KGiw`3JRJKF#~ zN_S`usr1hSF`FH=Ngf=n)tL;Q2IYUVk*HFTZ7Tn;R!x zpZ<99P(P?r)Qz>PY4e+iB=^gigz29gDjF3j>xO;eMVS{d_a^+9WQeZtMf!G|%llP- zrdcf(iivmXQq7=M83i7YE$}^<6fpEHC#;M3q3rR5GO#Jwd=xO31DN_0HekEdA7=i& zOuKR8KhOet?z1FcSu$p_yIlOO)AbC>S%A0TNUbkVo`lrT_TZ@7M!vJ2bB%d$%OT54 zZ8|o2d`jJ(hsX`0;^}U7<(%dg*$1QvbK=f)q~PN(MEM;S zbsxh&qk`MwZFfqX!{n3YA3t&rjh}3#o&E14@)qc@#LpPQjpOIh?It_|J9b>y=f5bo zy2ABeXd~W@ElrJUsKz@Y^X5r6# z&;#s@+&V)gd`{mPlN#xvt#U1**KS4lEAGdUf%wCcLz_ru*|*P)Ca1n(Qk}8wG~SLp z_-sE#%OKwAfFe06#{iozzuuB%H0!!~JmF@eDdZL{pN0q9Z#FsGRm8d$1>d=|84l%D z?}$g3>8ILEo5yV*elGQLP-P4G&u(f;o1h6xLO&{XyC`*!H;%>w^M8z_zT!e?jMN)B zJ3H%>a15v@k6MXH*T*{HQQ)e8Zo{>j4n9m(eCME7@9++tG=Tf|EI+ycUEk2q$;}5# z!@;wVUOg`#CtiAdW3|Y4rEeS!T9Ig?ppAmHEZLQ3V?!7AMRor}HjXel$rDSlJ2rsA zq7|l*1U;dT?eN8%p8)ljT65vJSBEQwPr(^r&=cX}Rcgv=NGnzX)IdBVk1QoA&94~j zBy=3Onux(+jL8#q!*#Wq1R!R1Ygx`JHA)GYS~Ao+`>}62?5)Jf(_5oX<#$e<{}t+A z2JsMcK}Qe(npWJd!m&5=KmGd8Tin#U^Q_d;@!OT@33V zWM23Pi-X#%xt^zos_a-aQq-!dm>UnWv$c|PI+oy=vB$yuBB#AoonY}|uS;_AEs0ZS z&hUP6o-6W9{YL0Mpc{1c1TiSFD4)&qynOFZ*~7TiC;{91&{ecr#N1Hqjc$G~@leVc z7bL@6KqW`(Tn~J)2W$y=#;hkdA|ggY?JgJ6aS>oj_+{f>+@J(y6BtUYGscNG5n}oF zlqqk;Wed*llNp=(1ypcRVp`_iurk(Bj$aF9Vt)2UVy`-1s$C0BdEZsY=7xulL3z1L zmd2u>h}+x*!>LX;iQpQ}G*rOhb^LL;z-Zj780=+W?VJD6S#1B_nCo?JJw45qEgH}* zAz16*ue8XnhqOg9K8=M}F}2P|v|CtT|l(DB^d|9#E(XXyScL3ky!XHSGrLYpF@hhU>-n*vzSg|C_n-(=FI zPWh`q=peamL)W+KImVxr2@5ODIn8H7P~DegUgT|C?%I#51sP05l^Yh;S?~ zxb9iMvYreq)1=GV^9LhPFaGtp-QcbD=)O-vK@NcOkMqAA7Dt17+}(YTc*R9%sX(Lz zn*pV7RXQ2)jX*Ehyf*6Q4!RHZEE&ZflT6Lb{pbDEVl5l%c(V z0W;NJybpdPb1j`_>=!)Z>_zi=f)(T(-W2vPq_&f?6s1?+ntAg*h4>D(?5BbT5+A0{ zTOMyyK;_}%1V-9#vzB$CT=!mwYjyo$uEb0aC)wWYEfq_T=(zTMVz_r)Ns*SW;^W7f zxhN*Qzcc^7zhk$m+j^sYf5~%E)PW<0IooHJggnUtD@IEwSku#T@UWW5>`Y#jDkDu~ z89P8I5T5>wjaMHypD-w9wV#CvRt0(Twp3A0ULR=5xAfC zfF^$D`11BDsfO?6!W=Gps<|vfP0A3^+Tmd->79I=h=lRcQ%0f{^y4(<1M( zGfn-xMFTf?k?VWJwIQTki2lly4@SvXz<`KdrYzH z%x_lqD<0wF#F^y7)gjI%wcXtvXi&h#!1imkW2uz{b5rOg820RSWv0>2D zWoE7i*P`FvF)b9N{)mkW>Pi@8l-W-q#IvTSqTegnM4Wqjxplxz#@JwD3uZ(XZ~8Sm;i%8L`4mBlWI|FLeK+QepfFV z<;`cH1A>xA-~fd3;bZUDkX2Dk%-$O`1_pI$PG|eHO3h9eoCes#1_XWLEE+&2<@ftEupy?92!QBEH3e)4NDJR1TKcEu4pZ_)C5Rq)U;g}1 zMIeA{$TsNVc-(fiL6-cqk#`D}XgEZjeDlyXY6eh7xVd+Q^0tl0vu3>rfG_N~Y{BjX zPj^jby0P)W9X*P$`j$lc<2t%WaRVaWDZ|5<+g>z3!%5IGswVe(vr#w^H~Z6#8`zcc z%{K$J$146R1O#E>h-;hUMu)2;h}1MG!I6<$sLI4Uo9HMch9LKlQU>oVAV9!_%5pDrqoi?qQt?Ur$tN4d=)Qzc9sWS zNKXUiq{89UqHeN_t1CMQDMg}9uBoU`%Z^pM7M3HoxY(7kJ#d-M*Ygqru#!uPf%D7CU}R*x*_gTez=48*`=kj<<$iD^Y4y+& ztBX7(=`YOZ<;OXR4J`_}jV2WLM+`1Y2+%gb%UtUG>cGyarVuEKbkhAh(@ z&wZOwUxg!1CQaPCZ-Ju$@aRsE)^vMTRr*lmT`#uHGRxr+_Qte2RbB!cUtY!nQ_U@iXX?^PD0ZMpY0 z;|cjd{85v=T8{)Evhn=F5Ee2ZVzdoymhgfRUtDzdK{irzg4tmDw$no`ZZ-A@LB- z)^K@NOcqVO8(MF)RMKM#mjvR>F%cqPE%H%HRJlOiq(*Ik+Bj7fcWmR$#=BO3%pr6D zFn2b=k=d|1dzbMc=zg9nvUyJOdmgCeMA|j!O*PQ0aV;aHixXsmH&GWfX@)pXZopR* zf6othoc=*cA8{({eU>S&%+8E|ci$W8CbonWof#P^l@eF@yMphlq=1fuKJxUUt{3-) z8Xdm=&bf+et<9yR;u2{%o!22$cv^VvlQSgdoZ#_&dYQK-wNqK>rZ*QYk3hIrr_1BVh%QJ2Q^&gGXoqG0BgA^qZrPhMwm$!&RPXnt- z&D+i9S$r3d%00=n_N=FIbvR?B6Q}aKZ%iAsdn2Exgrmu|aHRF331Z&qV$|gEv`GE` zec&~&#*$JPy+QJ(nR>NpTl{tqyl8-tmeVkFd!m3qU}-<1rD5DS6C190Q-ZtlA)9dQ zy3*b+%*gw+)_!{pBhz1yh5%8w^$Okk3>2;YEoS;6WQi;9LBarK2?5j`PNuk#DE7T} zkjv<(0Q-7isGjO=v#*h z94u0|XNgPCT3e8VYaxM@j{?o~!XXoHWHU3y5Y^sG;^}jOT`k+Kqp*=`C#7R=u#8<}$U4W=FJ=G0!5sypM?hj-B6& z=y3s#O^X~`ZV5=0P8{}1^lT^EUT>8;$xwTrb(MI37Q+*xb(`NC_rr9s{u|?U^ z;-&m+%5-pjKm*i@RV!)DkCM^y6Jpi}v-XU1qbuA-6ZAyBOB8 zeE(!uXEvO+Ku1rvtnhGINhVGoIs$|WH&3gMa)BIJa~_j|8eB7xX0J9wa%qOqGX%rz z+q2^afjpR+B~ny_l}URdCv`u4@M8u*lSmt&p7> zwLrQ{Nks@pQSBTPpAY&4tm+2@-i` zkgxBBFd`4S$#r%0hCnPH<@Pihc3w!`RqlisuD z_3&0$!#IShXNPo^h{CaT{qvVP4Y9bbQ`GVdei2`2!t3v+7i)G+Y0COO=`t|l>ApC+ z`UdLc)Gl)YShdSJ7G`_{6%PgUOh-+&oKCL7L0&Aic`$Z$anf&OPin{12fQfD>r`Kj zAM`>$6dvuXZR4)K+wm)Q)=}L*egroja*mNgI8gr>F|Fl!ln2)OSo!ZGQU1zXj=IX! zzt9qj{`bQ8i~sowr98g&=l|n3_H(t^o=Kj7KOxJx)3dxf1cE&+7v;Ze=|w3Y(Jbne z5B?27ln*&c0u4UwjzQo@AXMBV(BmU$Hw`mB{^yJT^K$;5?i{w*>)f4c84s^eHrEmD L<60z5yWsx?ZXCTT literal 0 HcmV?d00001 From d1977f071d2986179e7d7a69199b806244c5f4b6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 18 Dec 2021 11:17:53 +1100 Subject: [PATCH 0786/1892] Edge label background box and alignment to edge --- doc/source/tutorial.rst | 19 ++++++++++++++-- src/igraph/drawing/baseclasses.py | 31 ++++++++++++++++++++------ src/igraph/drawing/matplotlib/edge.py | 2 ++ src/igraph/drawing/matplotlib/graph.py | 22 ++++++++++++++++-- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index bd961f4ec..1c8148fed 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -113,9 +113,13 @@ user-friendly output, we can try to print the graph using Python's This summary consists of `IGRAPH`, followed by a four-character long code, the number of vertices, the number of edges, two dashes (`--`) and the name of the graph (i.e. the contents of the `name` attribute, if any) This is not too exciting so far; a graph with no vertices and no edges is not really useful -for us. Let's add some vertices first! +for us. Of course, there are dozens of ways to create a graph with vertices and edges, depending on your exact situation. In general, if you know the number of vertices and already have a list of edges connecting them, you can just use:: -:: + >>> g = ig.Graph(n=10, edges=[[0, 1], [0, 5]]) + +This creates a graph with 10 vertices, numbered 0 to 9, and two edges connecting vertex 0 with vertex 1, and vertex 0 (again) with vertex 5. See :ref:`generation` for a detailed overview of all the possible ways to create graphs in |igraph|. + +A less common situation, which we'll follow here as an example, is to add vertices and edges to an existing graph, which in this case is the empty graph. First, to add vertices:: >>> g.add_vertices(3) @@ -918,6 +922,17 @@ Attribute name Keyword argument Purpose graph is directed, relative to 10 pixels. --------------- ---------------------- ------------------------------------------ ``width`` ``edge_width`` Width of the edge in pixels +--------------- ---------------------- ------------------------------------------ +``label`` ``edge_label`` If specified, it adds a label to the edge. +--------------- ---------------------- ------------------------------------------ +``background`` ``edge_background`` If specified, it adds a rectangular box + around the edge label, of the specified + color (matplotlib only). +--------------- ---------------------- ------------------------------------------ +``align_label`` ``edge_align_label`` If True, rotate the edge label such that + it aligns with the edge direction. Labels + that would be upside-down are flipped + (matplotlib only). =============== ====================== ========================================== diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index 720404ac9..6a983225a 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -121,21 +121,21 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): raise NotImplementedError def get_label_position(self, edge, src_vertex, dest_vertex): - """Returns the position where the label of an edge should be drawn. The + """returns the position where the label of an edge should be drawn. the default implementation returns the midpoint of the edge and an alignment that tries to avoid overlapping the label with the edge. - @param edge: the edge to be drawn. Visual properties of the edge + @param edge: the edge to be drawn. visual properties of the edge are defined by the attributes of this object. - @param src_vertex: the source vertex. Visual properties are given + @param src_vertex: the source vertex. visual properties are given again as attributes. - @param dest_vertex: the target vertex. Visual properties are given + @param dest_vertex: the target vertex. visual properties are given again as attributes. @return: a tuple containing two more tuples: the desired position of the label and the desired alignment of the label, where the position is - given as C{(x, y)} and the alignment is given as C{(horizontal, vertical)}. - Members of the alignment tuple are taken from constants in the - L{TextAlignment} class. + given as c{(x, y)} and the alignment is given as c{(horizontal, vertical)}. + members of the alignment tuple are taken from constants in the + l{textalignment} class. """ # TODO: curved edges don't play terribly well with this function, # we could try to get the mid point of the actual curved arrow @@ -192,6 +192,23 @@ def get_label_position(self, edge, src_vertex, dest_vertex): return pos, (halign, valign) + def get_label_rotation(self, edge, src_vertex, dest_vertex): + """Get the rotation angle of the label to align with the edge. + + @param edge: the edge to be drawn. visual properties of the edge + are defined by the attributes of this object. + @param src_vertex: the source vertex. visual properties are given + again as attributes. + @param dest_vertex: the target vertex. visual properties are given + again as attributes. + @return: a float with the desired angle, in degrees (out of 360). + """ + (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position + rotation = (360 + 180. / pi * atan2(y2 - y1, x2 - x1)) % 360 + # Try to keep text on its head + if 90 < rotation <= 270: + rotation = (180 + rotation) % 360 + return rotation ##################################################################### diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 1e13e3cc3..adbdfab89 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -49,6 +49,8 @@ class VisualEdgeBuilder(AttributeCollectorBase): label_size = 12.0 font = "sans-serif" width = 2.0 + background = None + align_label = False return VisualEdgeBuilder diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 5037e4f2d..7dc824b8a 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -295,14 +295,32 @@ def draw(self, graph, *args, **kwds): dest_vertex, ) + text_kwargs = {} + text_kwargs['ha'] = halign.value + text_kwargs['va'] = halign.value + + if visual_edge.background is not None: + text_kwargs['bbox'] = dict( + facecolor=visual_edge.background, + edgecolor='none', + ) + text_kwargs['ha'] = 'center' + text_kwargs['va'] = 'center' + + if visual_edge.align_label: + # Rotate the text to align with the edge + rotation = edge_drawer.get_label_rotation( + visual_edge, src_vertex, dest_vertex, + ) + text_kwargs['rotation'] = rotation + ax.text( x, y, label, fontsize=visual_edge.label_size, color=visual_edge.label_color, - ha=halign.value, - va=valign.value, + **text_kwargs, # TODO: offset, etc. ) From 3801725ee9bbc216d02368f8637a265cbc0431c2 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 00:16:41 +1100 Subject: [PATCH 0787/1892] Add tutorial for configuration and visual style --- doc/source/gallery.rst | 8 ++- .../configuration/assets/configuration.py | 25 +++++++ .../tutorials/configuration/configuration.rst | 62 ++++++++++++++++++ .../configuration/figures/configuration.png | Bin 0 -> 44598 bytes .../visual_style/assets/visual_style.py | 30 +++++++++ .../visual_style/figures/visual_style.png | Bin 0 -> 63457 bytes .../tutorials/visual_style/visual_style.rst | 52 +++++++++++++++ 7 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 doc/source/tutorials/configuration/assets/configuration.py create mode 100644 doc/source/tutorials/configuration/configuration.rst create mode 100644 doc/source/tutorials/configuration/figures/configuration.png create mode 100644 doc/source/tutorials/visual_style/assets/visual_style.py create mode 100644 doc/source/tutorials/visual_style/figures/visual_style.png create mode 100644 doc/source/tutorials/visual_style/visual_style.rst diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst index 45f49e62b..78d8b35c9 100644 --- a/doc/source/gallery.rst +++ b/doc/source/gallery.rst @@ -2,9 +2,9 @@ .. _gallery: -======== +======= Gallery -======== +======= This page contains short examples showcasing the functionality of |igraph|: @@ -16,6 +16,8 @@ This page contains short examples showcasing the functionality of |igraph|: - :ref:`tutorials-maxflow` - :ref:`tutorials-shortest-paths` - :ref:`tutorials-cliques` + - :ref:`tutorials-configuration` + - :ref:`tutorials-visual-style` - :ref:`tutorials-online-user-actions` - :ref:`tutorials-visualize-communities` @@ -32,5 +34,7 @@ This page contains short examples showcasing the functionality of |igraph|: tutorials/ring_animation/ring_animation tutorials/shortest_paths/shortest_paths tutorials/visualize_cliques/visualize_cliques + tutorials/configuration/configuration + tutorials/visual_style/visual_style tutorials/online_user_actions/online_user_actions tutorials/visualize_communities/visualize_communities diff --git a/doc/source/tutorials/configuration/assets/configuration.py b/doc/source/tutorials/configuration/assets/configuration.py new file mode 100644 index 000000000..ad8424221 --- /dev/null +++ b/doc/source/tutorials/configuration/assets/configuration.py @@ -0,0 +1,25 @@ +import igraph as ig +import matplotlib.pyplot as plt +import math +import random + +# Get the configuration instance +config = ig.Configuration().instance() + +# Set configuration variables +config["general.verbose"] = True +config["plotting.backend"] = "matplotlib" +config["plotting.layout"] = "fruchterman_reingold" +config["plotting.palette"] = "heat" + +# Generate a graph +random.seed(1) +g = ig.Graph.Barabasi(n=100, m=1) + +# Calculate colors between 0-255 for all nodes +betweenness = g.betweenness() +colors = [math.floor(i * 255 / max(betweenness)) for i in betweenness] + +# Plot the graph +ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) +plt.show() diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst new file mode 100644 index 000000000..31b423136 --- /dev/null +++ b/doc/source/tutorials/configuration/configuration.rst @@ -0,0 +1,62 @@ +.. include:: ../../include/global.rst + +.. _tutorials-configuration: + +====================== +Configuration Instance +====================== + +This example shows how to use |igraph|'s `configuration instance `_ to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. + +First we define the default plotting backend, layout, and color palette, and save them. By default, ``config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``C:\Documents and Settings\username\.igraphrc`` for Windows systems. + +.. code-block:: python + + import igraph as ig + + # Get the configuration instance + config = ig.Configuration().instance() + + # Set configuration variables + config["general.verbose"] = True + config["plotting.backend"] = "matplotlib" + config["plotting.layout"] = "fruchterman_reingold" + config["plotting.palette"] = "rainbow" + + # Save configuration to ~/.igraphrc + config.save() + +This script only needs to be run once, and can then be deleted. Afterwards any time you use |igraph|, it will read the config from the saved file and use them as the defaults. For example: + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import random + + # Generate a graph + random.seed(1) + g = ig.Graph.Barabasi(n=100, m=1) + + # Calculate a color value between 0-200 for all nodes + betweenness = g.betweenness() + colors = [int(i * 200 / max(betweenness)) for i in betweenness] + + # Plot the graph + ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) + plt.show() + +Note that we do not never explicitly state the backend, layout or palette, yet the final plots look like this: + +.. figure:: ./figures/configuration.png + :alt: A 100 node graph colored to show betweenness + :align: center + + Graph colored based on each node's betweenness centrality measure. + +The full list of config settings can be found `here `_. + +.. note:: + + - Note that you can specify your own location by passing in a filepath to ``config.save``, e.g. ``config.save("./path/to/config/file")``. You can then load it later using ``ig.Configuration().instance().load("./path/to/config/file")`` + - If you want an efficient way to set the visual style between individual graphs (such as vertex sizes, colors, layout etc.) check out :ref:`tutorials-visual-style`. diff --git a/doc/source/tutorials/configuration/figures/configuration.png b/doc/source/tutorials/configuration/figures/configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..73339f27684a14a68d01adc91aa37f2d65fff518 GIT binary patch literal 44598 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 d_`_. A quick example on how to use it can be found here: :ref:`tutorials-configuration` From 38978c2ec5841f7138c6a82c338a9fbec1d33058 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 13:08:35 +1100 Subject: [PATCH 0788/1892] Switch to `ig.config` in tutorial --- .../configuration/assets/configuration.py | 25 ------------------- .../configuration/assets/configuration1.py | 12 +++++++++ .../configuration/assets/configuration2.py | 15 +++++++++++ .../tutorials/configuration/configuration.rst | 17 ++++++------- 4 files changed, 34 insertions(+), 35 deletions(-) delete mode 100644 doc/source/tutorials/configuration/assets/configuration.py create mode 100644 doc/source/tutorials/configuration/assets/configuration1.py create mode 100644 doc/source/tutorials/configuration/assets/configuration2.py diff --git a/doc/source/tutorials/configuration/assets/configuration.py b/doc/source/tutorials/configuration/assets/configuration.py deleted file mode 100644 index ad8424221..000000000 --- a/doc/source/tutorials/configuration/assets/configuration.py +++ /dev/null @@ -1,25 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt -import math -import random - -# Get the configuration instance -config = ig.Configuration().instance() - -# Set configuration variables -config["general.verbose"] = True -config["plotting.backend"] = "matplotlib" -config["plotting.layout"] = "fruchterman_reingold" -config["plotting.palette"] = "heat" - -# Generate a graph -random.seed(1) -g = ig.Graph.Barabasi(n=100, m=1) - -# Calculate colors between 0-255 for all nodes -betweenness = g.betweenness() -colors = [math.floor(i * 255 / max(betweenness)) for i in betweenness] - -# Plot the graph -ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) -plt.show() diff --git a/doc/source/tutorials/configuration/assets/configuration1.py b/doc/source/tutorials/configuration/assets/configuration1.py new file mode 100644 index 000000000..a10d4e601 --- /dev/null +++ b/doc/source/tutorials/configuration/assets/configuration1.py @@ -0,0 +1,12 @@ +import igraph as ig + +# Set configuration variables +ig.config["general.verbose"] = True +ig.config["plotting.backend"] = "matplotlib" +ig.config["plotting.layout"] = "fruchterman_reingold" +ig.config["plotting.palette"] = "rainbow" + +# Save configuration to ~/.igraphrc +ig.config.save() + + diff --git a/doc/source/tutorials/configuration/assets/configuration2.py b/doc/source/tutorials/configuration/assets/configuration2.py new file mode 100644 index 000000000..7c32aec8a --- /dev/null +++ b/doc/source/tutorials/configuration/assets/configuration2.py @@ -0,0 +1,15 @@ +import igraph as ig +import matplotlib.pyplot as plt +import random + +# Generate a graph +random.seed(1) +g = ig.Graph.Barabasi(n=100, m=1) + +# Calculate a color value between 0-200 for all nodes +betweenness = g.betweenness() +colors = [int(i * 200 / max(betweenness)) for i in betweenness] + +# Plot the graph +ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) +plt.show() diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst index 31b423136..f3c5db155 100644 --- a/doc/source/tutorials/configuration/configuration.rst +++ b/doc/source/tutorials/configuration/configuration.rst @@ -8,23 +8,20 @@ Configuration Instance This example shows how to use |igraph|'s `configuration instance `_ to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. -First we define the default plotting backend, layout, and color palette, and save them. By default, ``config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``C:\Documents and Settings\username\.igraphrc`` for Windows systems. +First we define the default plotting backend, layout, and color palette, and save them. By default, ``ig.config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``C:\Documents and Settings\username\.igraphrc`` for Windows systems. .. code-block:: python import igraph as ig - # Get the configuration instance - config = ig.Configuration().instance() - # Set configuration variables - config["general.verbose"] = True - config["plotting.backend"] = "matplotlib" - config["plotting.layout"] = "fruchterman_reingold" - config["plotting.palette"] = "rainbow" + ig.config["general.verbose"] = True + ig.config["plotting.backend"] = "matplotlib" + ig.config["plotting.layout"] = "fruchterman_reingold" + ig.config["plotting.palette"] = "rainbow" # Save configuration to ~/.igraphrc - config.save() + ig.config.save() This script only needs to be run once, and can then be deleted. Afterwards any time you use |igraph|, it will read the config from the saved file and use them as the defaults. For example: @@ -58,5 +55,5 @@ The full list of config settings can be found `here Date: Sat, 18 Dec 2021 13:13:52 +1100 Subject: [PATCH 0789/1892] Remove general.verbose from example When running as a library, which is what the example intends to show, general.verbose does nothing. --- doc/source/tutorials/configuration/assets/configuration1.py | 1 - doc/source/tutorials/configuration/configuration.rst | 1 - 2 files changed, 2 deletions(-) diff --git a/doc/source/tutorials/configuration/assets/configuration1.py b/doc/source/tutorials/configuration/assets/configuration1.py index a10d4e601..cd3862e0e 100644 --- a/doc/source/tutorials/configuration/assets/configuration1.py +++ b/doc/source/tutorials/configuration/assets/configuration1.py @@ -1,7 +1,6 @@ import igraph as ig # Set configuration variables -ig.config["general.verbose"] = True ig.config["plotting.backend"] = "matplotlib" ig.config["plotting.layout"] = "fruchterman_reingold" ig.config["plotting.palette"] = "rainbow" diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst index f3c5db155..24d5188f0 100644 --- a/doc/source/tutorials/configuration/configuration.rst +++ b/doc/source/tutorials/configuration/configuration.rst @@ -15,7 +15,6 @@ First we define the default plotting backend, layout, and color palette, and sav import igraph as ig # Set configuration variables - ig.config["general.verbose"] = True ig.config["plotting.backend"] = "matplotlib" ig.config["plotting.layout"] = "fruchterman_reingold" ig.config["plotting.palette"] = "rainbow" From e5fc828621a54216a2c89940dbd5fcebe8fe2320 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 13:34:00 +1100 Subject: [PATCH 0790/1892] Update edge labels to be aligned and have backgrounds --- .../assets/shortest_path_visualisation.py | 8 +++++--- .../shortest_paths/figures/shortest_path.png | Bin 30185 -> 29787 bytes .../shortest_paths/shortest_paths.rst | 14 +++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py b/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py index 485326035..47eff84f6 100644 --- a/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py @@ -16,7 +16,7 @@ # Plot graph g.es['width'] = 0.5 -g.es[results[0]]['width'] = 2 +g.es[results[0]]['width'] = 2.5 fig, ax = plt.subplots() ig.plot( @@ -26,6 +26,8 @@ vertex_color='steelblue', vertex_label=range(g.vcount()), edge_width=g.es['width'], - edge_label=g.es["weight"] + edge_label=g.es["weight"], + edge_color='#666', + edge_align_label=True, + edge_background='white' ) -fig.savefig('../figures/shortest_path.png', dpi=100) diff --git a/doc/source/tutorials/shortest_paths/figures/shortest_path.png b/doc/source/tutorials/shortest_paths/figures/shortest_path.png index cbfacff6e3fc6a1b30caf954375ee8dc6ef93927..d6cd6a60d4e88dfa7eed414aec3f9c805b5dddee 100644 GIT binary patch literal 29787 zcmeFZbyQXB*FUd$098&zzr{D^laG5)nQvJ_>~*Qc*^0p->kBP$-Nk zJRJBx!aZYu;9oag6!cy0Ia;~6n?HSsQZsjPvU7B?v$kMzd-&AZ+R;IfSD06To9VHO zi<7fBAD{hyy@1#8=_9@&^Q{JWlZ#Hu_nlEF5_9Aqj6CUFYZS`)iwas++vD}>_#=Jo z!3pdQVfl5YcLC3^sWd5bM$64)DM=M9$?x5{6aDz9z?Wu3Q?-lh3^jQa$hHoM6bjhg)Eg@uLVmD!M2eEcZ*$#t0>erynq5wDDy^y0-#C!>FROE7LiYEtyr>y@Sx zDO);24^J<%lY>ogU^Cnr93!ymB2Nf;F^v~E1ZCpg!!8lVZuPutY4B8h>)RXgg5U5+{8ceRL%5vUm&2iuly*?=O<~ z#@@1elXxg5$2L9U@Xby-_x7y+zy0gWpe>5%+UENS zzi!f0}#bbSFD=+gEs-oNF0iF(?Op>a|SS6!pb zeO+2HtxUvh z&URMAYui!E*&?wFx1L?U_r7)P34hpkU!qS(VfG_Ua=dNp@bZbA*`X?XIypJHkqZCb zyAp0I&984d|FYkpA$+@AN*$+rPJiE*hgZ=jU`wKjRm4rYBZhA9{V9bt7nCUB_=JQ& z^S1D|FD24p-KH1wOHAsFlr+9Pc{1v+k>p05d-qL9ZtkNxqworOEiH1z*elp+fsIZ? zz8A^!@4_o5G~)VACuG%3aDJpqg!`QyRd%^XR9wVlO87#FkKGYVAKqU$IDNWu>6b9S z!{qW;+W4Jrt}?;F&O_(xug%nXwDk1C&D+Kk3{6OWhNf4HhQBy|;QCwnV9T?nR&08x zCo8_n$&Zt;A}Bd1>IH}p!VNVK-Lb_l~QdUFYv3r6pyM>7T+ zpZpOWlRV<;?d_fV^QS*!kiFaO^vG3ALL%#DP57@tN0V@q<8N0Zk!os|D__htZ(VbxSliiuXG3(FDX#07TpNV$yWPrG!m-i#y;vrVZq7*CJMcMyAXw+flf3cnseJR#q=76hQTv4GrEIvZwxgx z$(C$v&H5F+PpiVpD=|NOTnplQNmdD1Bmr+}X$ghWGCm#Hy{8$Jl&&i~_zTOy+0?d2 z*GT-lFi`zMpLFfHL}uT&$lySg-iJZf{6-w(nh7*fnPtX%K|`rk9u3ufD8jB6iC$})F`7BgmWZ*z|Q-HMYfN2QH)y5=t%L|pNn$Tcu`mVn0TC*k9J!! z&vC=8-sIfXOGpePd&|H%C_D1Cs}J*0iHYOpq5F@uu%h?)l~nr-;+)F2WsL7Lqu%AN z6E0kSB~+NcG`74!Y>hBe2ZsEl>E`;gMXN^&a+^* zF4A}(Lqk_D_(Q$K#?FrR;St&;4m~BfgU+n+Jr+6IS;S1aeEV0Ma{-6&AJdz`+f9v8 zfBrnEsjG|9!nA$?|LNi7WifO@wIKdWDT#KCeYNxVEjp*!4x*i<-?x)!BZTPZ;f!YM zm73tCO3@Fi9HR}pRvat{B^&B5pXCipN=i;mFNPMi(`c6P;a&JZZb{1TE8fPa$psiT zlEddKd6Jc>(&Fl*#K}l9_DhcM%7NPfXJ5LzS2vau{~FLXVqp(H*UXuj=(ErGv$xLC zRU5c*^|tuQ2>K1u03z7c-x5}vwk-Seo9uY6U23AyKPPHK5-C8pKaXA)@t-6tHe1Eia?9FENB!Nm0ze< zw^Q1TAz1Zm*m_M@3H)-=VW-k z{ZF_23?V_Hc|W7T@+>6_(>sJaJ3AwD;^>hO*xPE_Iyx=>Ta;{9bIp{8o(}Cej(&c5 zTd>b*I>r50t{%x12`}{Zekf&Eq?TdRoKYjYNvA^HhpMTH%@#CTQ!U;#5 zyu6Cq+LY1J(fpPj(M{u=Wo2cgmYs*wf8W&69R2zxa=xME!E^Z%t8_?ixCAjnL};YS zHuW?1Ok7J8n-;5%j!r5S?K8~s@`XkEh_gh-@DjgexfHp9fMq4WwpEJJskyn()YOKB z-kdH|KSxi`n{KNkp^4YjMee`qXl=dl(W*PBx>|JJ)YW2lcQ+y?M#0L8Jt!#XSA+My zzhrJr4GjiHUqWhX#Dt|))_RR+{8E)e(p@-$wz$3G*qMGOWt#i zd?`Wv&uRM}N~v_?sTLnAdInl8LiNk@}fw?sd1t}8`! zd2jfQggcPQK)4O;_P$3uEn~ILJ-O z3=BrU1LleQ4Yce7<2~-ZmSv0c7?IBysVSdc-YR`7+Yz|VRC>L$lhHR~W5daBfyu@a z`j^f7`uZzexaV%Mxr%!KGIZnnxvteItY;454crh?1=izO?J6f#Oj+2Tm zEZ(8Iqx)(^HiG>%X)1N zRnUb$y|xzUf4Yny(0;`Us-d2n!$C-i*#5v;J7(-dlN zeKIZ#XRZ>Th>(!qbxHf+_}JN^5$BVCmnkV07B+TEYip+35fv83qn~d-9}&@!ZW?0I z(k_{s+2IJ{UZXMG57GXKLNS$=%DT4DYyUA)^0gO^j*cmx>QO59*t8(Ld;<%iPxsVs z?N)D-MCQ$b4$%JvR(Rv=cwO{I({fK1?u5rIk#de!QcB9~%J4_!yLT0}p5EX!ZG86X zl@0vQwt)faADB4JeSMe=3=A8)yQia`empuxM$zy#EX>RqDruFK!d5@u#!R<`S998F zbpo7}@$r%D?dub;>>%7(8?PHLL0&KT=*QS`gPN+MftNVcHKt@$^9K*2WrJ~A`(`KB zi{s)*zIS)i{p|koMaIH{g~4kf!>uq**$}W={zX~Rjr8*qCF_atD85F#NAtMSI<hF&?Q4F`dT=Z}C`vfsfwT2QzL`AhN^khxX&E@O` zo{l;;eNMW5@6|3pKAAA%qu=EDk=fa7IUDn9YiDuO>V&69yKT0m4Pn>>)EqGbC>bv= z@d@93W29>46%|qD%N=nI4-X$~b@4qp-m~Yv{{d@aV#0>;48$hthu{i5eZs3(&w#&08WU^g zwvYi8BBi5?f}`1C2~;{}$hYmw7d)sZt%i;b*ictkce-b!BH+}u=SkYmYw0TqP&{*xyH7M7NDaXj4I$POjr z(lQ<_G2R?={y80b$s`~+I9SWj!GU+6#5l@zd4QRZPdyvIvMZTOugt2Oc42ABV)(hsl)m7@WR5vp{uSD@7^(?m6V+C(`4$-@R+fX!H=0ZISV$2nwwG3?PsX^ zf57#Pjg9d?{>21pfaUr`LtbH_t)2SayB$zB`8~HD+w@cI{eDRd27B4{WG| zKZ)vMg9Q8319#zafKHn^I>v!g^VszObB!lS%DR^=XD%^9Ss2<9z1{KNYJAsROy|c( zKf?ewM^HuPy01@o%q8m~$3*}B{p*#+Ad4~jY+zK`4QE!~_J3eyWdUX5%g>*ky*am` zb^OrmIlp}40p5oXAH>{~{{6O?#*IFg^Yim#I)D85K_lf;18=O(lF&RlN(ZeJX$Nr7 zk_QwdeUF5+w6sV`NdqD&uGuK)m*nNiKqGr_<1&NiAF|?9hIa+WU9D&Z1@r0FP>U4# z>?d%N#3PJ&l^#5JFk6mhk=56yQF1x!gtZm4`rZsg7s?AU+tsVWRUl-U&;NKM_GAVN zYBrImX!YI0b@s%sP6r$2Mzv3|;q?ni>Y>$FadB}|U%g@hK>`zpkhJa!OH8X_Gn)R- zP`TxouV1Yt83e7O2Y${SaSaR%cpNR}ZbCiGf;OdUkByBzRP%&Y>iop{!NZ4<+UCbK z9-Ax!MfWiU1qDOG!v#--@0pn~Sy))mUZT5}`8NU2=uTwbxQ?!_#ph>Kc_k${C>lDt zS*TTkFJIm-JT__ayY+(me(#cBe*&llK#^hVg+6leAbu6nfDEpv3WMpLp!@r`8@e?|xc+4`1%e?p3IyP{}=qevaZ43^pT2@H)2B~2K3_65 zgE|8{^HP2*?(N&R+u)m`P+c#0f2nYzs zpd>guJ0lDNFhA7H>)5!smT;Ur_J$uJ@4gDnyfQH?499N#Q{|>UG{YaSZ?fq2*Dfq9 zn85+x*xN%OTP(fAfLJeQO4pOAW(*JnaavkhXap>qfU?aS+8Bgg~C<# z@#FFaZAD~pF%KN;u-hrTEx&*3KymJ;b;O{kOoU!TNlh)np#EBnZ2XfeMS13rul@a$ z+w(s=(;ORz|Gcn)we&lf#`W1~!Ts{(%R<>J5dYv?1ryPUG=KeiG3pYZ)xk1T-+Q&T zKup{uw^8QI_i)@sWbfax zS}xTzG8!v!9jo`GSRN>rfB5h!NX!F&GN^1!!@|OlYXh~21(wz(raA!L9C!#wBeZeQ zUVmHg8a%p|pv>=c;8gSJ)6B07`JrmZ^xpIE_I5NP5Z`-$rv>oLyVBB0t3h5K9tHSi zD6<;}vvF->WA)uf?7snanyrph!tMS0^fuZb**-CFHwZu?wUJyK{&)?<(d!lpBTDM( zB*>LUkg+0X44RZ^m9UVI+0VDP5QZoxFF(DwI9y;qM@viVwD5}=aR+2&W!2pHGGebK ztCG>sL_mwOJUcl=%F+v@Miap{jflX@DGdz`jodeFi^_(XlnBOO!TeC%tcUMI4d7McrX=ABGpVHeG;&>wPm&IzQ1N% zWZJ}V^X5%F5|Z%naHT>;vV30v+UC%Vrebr^YMZeA>GBH;+o1o`#qI9wkkZm}S}5!& zY2{M_zn~GZqk$@o?8`3?ZlLxRw?Wv81UUl>3k%u6zxw)YdzD~$GqbV~_!rLTN29B& zOMhw^k6%<&^b3g8YYBJawY4?m2I-1jQ0`ZR_tP{m81ayV7OM}NTaWbgs=T~B@~wUs z=%~p7U*&OI847ft@Wh4op}LIU@%i&K?A}0t%nTsJhDj3%KnFwM91#(bMT%UuF5899 zj!1*zygWR|hF#s+wCJ3is}r8{^oYA~Tsc^3igdqU&I&v`@Nt)G}AfO z2O`({{{4GZ`xHLYj-S%!(a8EO{K_Eor~NiQPA}>(ra_x=t=G**nAIi+K9=p;HBknM zn>Sm!x^A~WQ`Uhy42ADAltKZAu^Lc>z{+?=#pU$p3)vcfMj*(XvzW|i7ZOY+O)d^f ze897uzJN-j)kAEUplBu~QT~~mn=bEUu>Fu?2dLTabXTwbc&)DH=^XOzw|7^DDS-9Y zcy7N(HW4-`dAa~VC~pV~(#1i!kDO@mhMQmcrP6i~0k2=?o^l&j5wa@9wnI}VV_=wg zaQ=5?#m?vKa2{!JfJM;-sRkC%2_j-+!{joMJJj>!GEF9RL4H0QVeQ#+5Q~C>gB1$H zwe>)@&&%V0o;tIbn;sS!8L4#~&n!PRGZO@#fSfQe;;ii?{LdtLjX#B`B(j^2R9N#1 z39T$_selw=T8!Z zEtZ+L(Tu1RZYDp=!-lRvcIncfhn=l$6o8Ru`eef4OnA!Rs2%Mt_td#NN*=F#Bq8+o zf8gK{tHj`mTog zl5#xJ0JP4!-mohBjzLYb9V}6>w!Z#?*Z5h6e0bG@`J1=5yl0?~wPz|sz2e^ST^``^ zfdX>yH_cH)ORHBm=N_H2tE&QZe|!Q0R%*MOcZ44@0k|`;ecX?Kh=y zVQ4lG4-r2z!PBap(CqjANbKDL5b=SXMteRzrXwDnS3}gq(Z*Gy=A!a zyg~~cGQcVt`uY(-rT`|YtvuI$54aeRZA)Jt1wh)C1Xd;5bQv8EN<=If{`iQDk}?Ef zvn{%8mD|qFZfap6A}Hv>(8$O$5FP3g@%-yc70~{L@7|#$s^NjgaUoVLlgp!b`tKz(8 zix<>fNvmSZk9t1Pw{yu?4KJYSbdQdZhzPz>c5jpG|3xmYy7!}w5)0!JpGo^bu^}Qa zXM?&-pOKMKR$hMC*$CvDA6g>JrJ+f8;^;hW_v8<=koiV8~|Sr@NV*lyZjk6 zme60nG-v=PROV)9PeEgrb(Ss!7J_Ve1no^W`X&#QWLGgKenrF!bHE86=coJ0RTyl& zl&>+B4QxS;sPWq6H1Ru}>u4~b!pELBt_%bjyndsV0I75QZY%mLW3?2}DeMN`)<8oZ zYV?%=HKM{Mh0562_zuW6fKG-gZ7%^H8KyY`ZZ}?(a1RI<>_F&Vq6Fjfyzxl&1*EYvb`pK=LS^K zB7;hNzWR*|chuAl9Y@0cJiY1S;-Uecpq3^w4c|c#Kp*UL4mWFbcSiIY+19gU+s|dy*VhOAjs|)_M~bQ6 za8C|dB|avTbq*+rQ^?obUmHgxRnUWGp%kaybY}l&wG=!}{ZDtBeB=_(-qzOMH1XZl zp`@ak1}Q`gXuM(^1CgnzY4l}59N_#2EkGp0^4mJz;BDQn?ml0D&q8QsYg?OuS#y9} zLD6<$aWVEUA+gDG4G({*LdfKN`}U0~rAwj;;0iSTVqyCcq14n=CLmywe#bmWump;S z&*|$R@Nvhavx=uD*Vxi@k&9p}%`6uM- zgJiVX5=UK7SSSxXL%@B_sDA4k*OwnZ6k)p}ToZ6nCR9?uC6IVRO1O#F;#D|Uk;Wnk zsz4G9ZYwF_f(C$ezxV3tv2Ecbvl-zGa&Ts#3v7P9mfrmPHx-031V9}Aed8owke;4C zno-(h(RSZafGjuM!5+hkZKdDb{tDK6Fw8h}sz&YL6+zf;>a<-j*-V92Aoa7cB z@D$WWOWcba{QS)YI)!CV=TyI^OEdcU`OyIO2=G2%6Lp*jVZzJH%L@R7FtL&@QV0W% zim)u{uToQKEF2sJt%andTml&`mRUXwIah#GJ3uSA*-}Sz;we-B&f3w@5d^*{OF4+B zFJF!Xu^mZ_A(98&`wduwR?x*zDZSRkmrOh`=tS(A5s3xRvcvc%Sy(l7^*EA2jofAx zwd~((O|p$Uy|?$dE3g2Iyka?2n6WVj;kf`=a(REpW35B4&Klao_( z7hh8}!6jZM*g3NuG55U6=ap5LjqBWqnohO|CVaNl>Nh*+kOOJ;~&yM`4OE@L)Hi;L5O1`FL`)_&4WTUU3l+P2ph)IjCi zx9=Sp0I4CPrta{x_YZcyp8pZ5SFe)=Rx_QbgBg@lCs)_d^mN8~MQfBSX*@U@pnPY7 z=c-Z%cpRh#kacQiN*0l7pszuNQ>rtG8!-jB2bh-AQhz?XJxCaML`0#m!yWz4V!(KMS5k5}>n{Pt zDcPg5=L0vPOoHB^p`#ND&4CJ+gn_b-t@0|Er-_N>01BaFS^lGIya@>n#b)qc5vboA zv0WIgF4Zyw=F@oimkyDQYFw9Jh+!ApgmnPPFx)oec?VMewM(BhWB{)RToaY~FT8ho)9n zK{*y}@93C;MhAZ1V>@Xe(r|g81tOxgoVvPtyUp)^*bXphNMdffh6oWWp;T-^Du>EQ z5z~oy8E|(Mij*7RKp;m9X=flrMRqcHM^CGFfmUG#rv`z#fcTR}KoBbf>VyD^`Jd^y zxpA1F7$BSq3Ohpk9ufv*Q-LLnMu+sK>FVpJDoUU90FC?R=9(S@*Hm)YeYt=f1T#$g&dnf0L;x2LaWCeVMzn zL6{(JiORlPoSltzyua=!Syfin3|IqQq$~;PVx(iC{xPEdk((3PKYaWs@8KZ^>w*um zcuv*p*H?TtKVKRuGsgscs!*VD1sVg*EiWNZ;$ckKQbKy3=P=5;PK0SjYvI8zLCNfx!i7J;ojcGbDS$e)n|*P&*pvH2T(^n_FA0 zpcaFa0-`km2=-n~I5JBWC8kZWAt50hvw%_BIy;rxpNZ=l8`C2uJyaj~iO}U@W*Z)8 zt#?38mXeYJ*{1_;9xY=C_(h0;gYSkW{BnSIh`Y#`b?|Gfjg+iZ^#BURm%Ox&e0 z|CsDbfY%VePih3oW?*qLAi!Jt_@&^ZGC09ItD~3xQJk~f9)ghw3dC%;=%n3^N`yR0 zpKM@C9ZX?@%M+n(-nsa@@DgeYbV?RIxgE1N=i~7ey|7V|O#*y{$RW}!eo3rri) z2Y?5a0f=Hx+>IQ$7sqgGqtySD;HTs^A;A3Pk+refV0EcOET~qMz4G_p^qgwS@Dj)` zMOO#p_vIHCe+I-u8wXpIjGUasLSeNO`gWb$Y7p#IL~Kn>ON%llx4s^UzTocej)V?? z$G3vN4ZwYH=q*H6fVf(IOS+zV;~_p2ZH1yLU#R7PcQHV03`$8!8JYvlGqO33qyH<= zoO_F3C&8}-Ni{-W^Vs_FyNptN$eG&BOLC;jMdyd-RH;3)xBYt0N)vD9c|zA* zM0B*Bt}uK+>+3>pQf`gv69g7@aF9zRC(1H>%@_N)XRu%#jNXe56F z0*obuxM;*(@)XbML5XP|8lnNLD-U|wXQ(}7ju`iHk>JpSM~_4q;(!l93!^O0tlB(Y zZ<>WnM?gXX8PtSt8%l4U#l#SSCw{s9U?vJ0M7WkApjMzc0Z_&{PVH?oFAG|kfjtee zHAG8^z=#(z0WJz%iY_h&!dtK<$hd48KvY1I${@laQML+;OW3_82nm~w5#88mBM}`g z*w~uuLdr6nMd;O6wL*(6Ei5iTV*^oC71oy)%mC|p=u=z`0)T1}oYDTwpaeDwIEV@m zjIio{h5ZjoVp$^nSG^7e=z>_;u%Sd_Q?FCvgO!fNY7o8%;uV^Cj_-IeDAp}Pdy&Gujf9c&Ct{|s!aB|9-n7jqd zfZU-Hz`;}BlDT3!OG-)r)KQhQ{HDBg$r6qyzkomskiqc>YZPP{@?nI5QBefMj8f6C z`0pUUP`(QC-zm)~a5vi&#L7Y^14Y=|c_?H9);+f~^U&0!-VVn4EE z5Z$WuGy4W~2fo7roWr!S8TKXRrDLe0C`iA6S?VasAnhl)va*6MT1W>6D)+0zQbxn}CR>b_Y!zKfE^q7ZI`mL2*(?c;K#p*ZTJ&9-a(*y+2QDhjQYn zAxjf;&%~reC}9MUNMK+fi|)=(hsnkm2+d?b>jZ2PnwFNP$mejIjUCM9df+qq6_3gO zsn0-pLP4LQK>!k*I&{HC3+Q3f%gcp3C^}80Sst@qF^HzCZU=xQWCkB zXh@U|0lIu+Ix@t#~X=o*fOn?lcuYCSo^!XpF!rG2BdfI-aTlM zJdo(1or7+p8kN5Xq#8_b>hjE{0g#Rk4m`4Rb1ea@E&MJ_8M;d5stP?EQJfGo2d$e4 zVq*Wh+Fc^Tx(=%e_X6pouoIwARFFDiBzA!43e+?vu?fQrT9b|Nv>_>0_WSo1U|}M< z5^T=PXA$B7$;niRis65LJgIi}_t~>&WuDtsC;Lt3P)Oe^Q;E#|`4jT#lQfnWRO|S7()!cAQMFbbP=Ko(#-AY`B8a7wxy|RB z`};}|(*q|LT^w9NfXS5KFf(HTm|ldz(7?a~hz^S`77__D_1VORu3e7c2ixal2}fm> zm7l>`*=!}?6T0s$2xDZRa<;*4Nk~iMQuRgfn}i!TL^9E}Qr6dSWVF2DG;16^xI#{T z0TM%+HrF{gnxVrYi3e_zdK#deT7}^n5ew_JH8oR!ciQDiZuLJ{{tSl#u|T0SpjA5>NdI#hvY2%bYWdoStGPGL?C=^&m zCYTeD(r5!6OMGPn-7f%A*ak!pXKUx*A}SJ~HZVTarB5l-MC|3v&CSF61^)$`5c0Bd z2Mf$5A37C~Q#(l!etsEH;=_&Vpwd90;0I*~NMWrSh2}L#7EJy98wTbtGl*xvnpH>D z-h+${KmR}Fqa7*%=4%7lRY5U+q8-CRi-w;9{ral%rmzrCCCm^H{AM z1mK(9uWMlN3{mV6MGVB9Vcx+(2-r6@HT7=kq3vTZ;`@I$(Q8|Y6Onx%xG_1nHm77Du!?ng$N}POrO0b<^*C0D;tvV%ASrBj-km42)qRY$6 zA?vMUkg@|AL^1cZEAQ3P!odBl91hn3T@&yY;#fk9wM&$WJOi-PANJotFC?5j>Vk&5 zIlVF6h9E|en-Cwn`u-%k-*a(!8L{+egl#AxK#)-(Wes!&Q8Az`f;Cjvy~c*9=ik2* z0!pIcHZu^s+175Ifk!{C3=Iuc6iBmVN|F0R7O-90c%kO^DpyOEI>!QdD= z@UpeHA7_^qbY&n9?25TZ2Z^^1KzKo}%c4xXCpS?6jTr)W>UM*)f8xcXf{GY^hu+W2 z=fFViEREy-9~Favf3H0hu@33n9H2cU5y)zas9wR-4aj(x1r)$uwls~{K6s7p9n zkC7CmAWy`(?U2>DH-T#lQ!(X2J{KXL&74E3G6K`F202h?5bQZnVi^AI8U7IQhMef2 z0ROras>67N`LIteKZpsLFq<15jQ8Iq+~TFj#ln7lv=<5>4aN)*VyfGq+|k|+A#)07 z21~zugFnM&$u>cJP$c7avwNQiXe9tY>z=nW>3&DoLFy>8?7Yi?a&e{)F2VFQU;D*~ z^LIe)eHF~c7DPE~yiJa+zul=3{}xNo**S#oeh^}yg22mjN|sMyhRUXvfZ9VXxhLi@ z@hSA}MBu_SJ<5_xBKat2Q{N@)xpPyJEt#Vz~<@Wk}Uwcsa-QdFT!rB^%ucdRcO#$!M z&*LF957<{^(XGtd81_$+Wr1G}SP;AL?%wX4ALeDE(m|%oS(B}TCM}ip7Uk{bG3UX=cRb;5#z z@&Hr-i5*tEa{+VQ0LgR)B&)#jDNU!hjWjs#UlbSS!wg@hl+yhH;riVHL;Z3KY{uw5 zIS|y~*#bz{u>|PlM0?JE6ipOd5$e2qR#xG)QMi7+c=Gdss$y zqoh0Nl^kzpwI ztL;~@^KA)_<>F-h+NW1h@1VaTpc~9FD8$1LR(b3{!}Z?>kOg8{IOL)GfB(K-3Dwpd zhDada(0;t`A7BoXhid+DZpHI3Xr~-^iZpFBm<)9$QT@1>Ov1Negc9cyVNk5ADWUH| z3~{YaJlQ_0L;6^(V6Hl=v@|1Jvkb_!UVC=qKJqLqu86G)-3(a?RZ~80ZkQRS^oqME z-xL{F;Y|;vX?M^)gX2?Vp&qYuw+v6u;oz5dBIPcNH?*~Xn@vT}i`%_bo_w-xX3>W! z7#svTd<>+;_)o|*a{*@rf*W?Fv|*3-Xm6EZYU1QCt5RIc(0kmY*tAh*S7kQxn(z8S z&kAg~4flM)jS|~C$z+a{zp zCd{@niYMw{RBlCwy;4neTaG!SU<`F_n(khkb$H6nyKeB0*$7CD=TJa7*a<8CtOts+ z`2#C#7_Nk&=l4R4A3o8F5vD~1_PupDVe>vq`CXG%(KLLj@4|>$mXa@X8y8PrW@qW8 z1cMG{Jvg{I0>E{L17Z_o+IVFeb>E`*x zbD_FYTihn4mc!F8-Cv>QM1GUTv?h*4^_b7*S3B zvAlHS0#1h&Br|LaZJAiK^nhpw2bN#{M67M^9$P=DF2|Cb89v|NQM$OWm{nIN{q06+ zW>wLgIZXx?0J3 z#gE4~J}lu_Zu3H4*UiW2mHcFJNoI*h;QGb)d#46Ien)4e=l(y^(a#)$6`LO(StK6| zRJzMq^p;Z(%A&K^VAR=M{FnON_7Z25xtY!HKg&2)#%q;&l%jQfAX-v*Ut`h*4W{+_wbVD;zueOfZCxXy{tjAUbECxxH>a3B`(hYBI5;!*b6sed@-%(n#TOAQY z=vI+!9`84;Maji;o4iuJ)kM2TOn4U{W!Y1szXG--LY$M5k|K<0$tn}V!n`p`u9jBg zyf@a+8{XNSIxC($t`17OotYJkL#0Hd^3OUiF4D;`r&Qke-wN|SHu+{#s4c#JW^aj! z87xw$kccR6NPZI(D<@!ih+hv5r4lqEgoT1_S$>->Q@7@PWZ?Orq2O^Ne7m5cDuc!4 zhwgnCGIOKf@b6>p5E1H>1PcK(y%ir*%wyAquOn4j@}c7EAdD4$_}M96@CZd=sFZwE z$isI51<9lWquYL46&kCqAFJx|L=27$3e~`dycM4kj(gXr zrew<#`a^J06|HWAvALN;%+WLQKSp9f1+8^7{12I3h@!QZN+p+Ry>=G~2%=v6R9fM7 zadk!F(Eu7@TooC?IDqM#O&I2xg_ML$wZnM)n>RdeFVWc-0AYyjtp#tb5GK1BUqE%e z{jnh8Ayh(t!~hfi{8er;d$nTyNq;Rh%9gy3b^ksvE6NT3HlJWMjR!X>Hy4-lX-T1E zL4UU^AyWd2pa71Zn`3ivACSK4ma;>xU*6gg-(0olOv2+*a=*>Hy0Npfd;CdIDs!Ba z0&y16Vr4*F{mdH`VbI*!MWIt$;6H_f8obZf`UFk-;U3AX&3ASV${U3K9#=o@xas6G z%4WzY{BZT~;zzl;UBSr4-P+ugHCDR{U!!d-<8T>cgyb^rG4t$5b{I_RCp~=BJbD}{ zvRL}@LwUI@I6(l*!RJ9ftP@wlT_G!@3g0WNz`pH$RxZi>b@f)yZ;8bP8ItqjOST0F zQ7rINK84^P1E_Q)d&J`jFKJi}h;Gi$GIRX#SjY%R7s}p=yR}F2`t|E}-r$IlVbBt= zWO?Q9+SET59#b2`4PU!8H9vpNfT&-921+ul%jVe3qXhR&4q6-S(Y9(H2#3{O^cJvR z5)u;=b2-@k-Qqs!iwm>_uym%|->InpAY~7(ty0XHmq5q)V=Vq`o?4o~*m#0zWd+`n z@fO5G1Ku^S_SL~a`Jvw3tPdN!Y~)NgZjgf|b?!q>mJnv};lagk+iOhc-xi6R_TZH$ z*+7`GayzKZpA|s$N`p(*wxwtKxp+1q?~DD}`MI zVRhb2xfRrJ)z2?!z1eHJ<@99v8pl`V_LX1v`9WW@K_){%D4tqb8C!EDC3DRNA-IN+ z7Aw)DP2j;^*Q(#G&?1aT)25I$-43yo=Y+n#zpG+dyW7cRY^XuwIXP(C&->C8)74|k zT(ONeR-7o2;JnEp;&?<3RObd{Pzw6}AdT+>S%IMnYYKb<9aFJNK?o2w3|%GFq5s>vhgnqP><)Eyxt75~D9A3dtY-GyT24rZcj~ef28#C0?Td$XP&C5?@~4!4!>t zwVt5F(6Zii9t)-nsTRGl*wK&2+wi2FnqI>PiR+zYv#17`#>xoc6*_RXa5CGzykT9Kh0lluR`h-Xk>w6n#V0FiAtn2TDEnQh8Z} z3yr6HhQ-EKx6_^wGgT^sx&XPCi~T}h1enYOR*aOY3z~W*^qj7G5!u|{+JK1HG%^Z^ zW;q;PZ*ra|2EzlMozs(D44PT0ggY-huA#5smC)z^=8Tzc&>xVj3PgUN(ipe~-~P2- zwsNyf$M>&^c;HTI41aH5%L|@KbKs8l+C0|eI5IZnKtm8Y5729fnyIME{##7KWR~VAb%FfPKsVgnz133tiSNY%K za{ifWYXUK47Bc-xPgQSxBBG69n7}Ao5-7fO)V;kZ`d;s`MUgy{a&$r(Y}vfmOc zq=OjvDih@Cp^N(L9bWoU^MaV5ZlcU>FR)f#8a^yIuvX2IiINgu`_lY7$z$4YA4@W( zzNu)ZP`3`cW0`o)Jw(i92}!MaU`zIYfgK@!%id>(=5dK?jIq&lE%ixK@<_@LM+QRu zlimSs9aUT>9WjUqD*$0s5l?1LUS4=$kwkoI>QHv~$OtX)unv$$B*vqVv2{0?X9Hj3 zpONK13j&nXe=t!yJ46|Uj(D;f?=l*xx5B(oG9;bwtPOE&(0Mvw1OQ$1x*r~eQ5lt) z$pULL1rY`iDqzY1aq1B04{2|xj}?ZbT`;hXMq`0e-Lei8jLcEj8WB%TT>A?XB=D4*i(o2jY;OnO z6=XDGW?@+(L^5;CPdQG(mA;ab5Cy)Ge|}tRU7gzP_Aagehh=WJ8^mipgM>}n>Ro)`&$X}`9q zmS7m$_z&L{t^zM(7W7<%mA}9964Btv3a_%T*wFvLU^~Ku;c1wcq$<=a?SLqL(g={% zGWT^8Lc{ zXqMe%BYjRzj@k$^Spy9d41X7&Cm?dLu>6Li)guiFPtfbb($eVuGf*W2f2z`99tHF} zm^W&MyOaTbhD9aJC!I&L2B5)q;cNxnHsST_vFvWJ?~nmqFwJ_8f>tBp=jd!sgq5E%Lcw+S_K#i$WR8N`PB`!{I5l{!3L=ULTtzgGNc$aY!X4}1Iq%2Ju%>+Qf`HT z$O93zKR+~!Fpz~IMezF(pZMhTlsWnAJUt0AGmwiegQvA2P338=QM)QUUh#|(9?vzR z0dpwGz&acw5o>2?V=%vnR63D{|D(Mtf2VqF_X~xJLYt&imZ?-|Koo@~N-|`qC^Ts) zQ-zYDGN+QH0V&faL?uzlEWJ%zD^e(AjHINHa6UJ6-uGPB`47(dt-Z@yU(fe>?&&i; za`@{I0}Gsq?nX>d3Dp4kDpD1IGlsFVKpu38+y{Z=_!c)^N&L9~z)K;my0!R!s4f}U zaKa1mBAv=0c<%wq3 z#vXrH$&EJvG!Lt;Y7x{es_a?I z_Xcol@?<0Z$ZrKPPK0!vd!T$~@6k#HLQBeZNu+V~qfdDv8W z|N7yE!W>9c31TTE%+h9oSnf&CjVw3WxN$1p9MH2?IVZqb`cQilb6#inpMP>gEJpelj!bFwI$;nyo^jjqc{DBwp!w3bORCj67 z2MojsaI8TJCu%l^otCw#1m6Hqr#a!qt6J}Ny+@2<%b#J0u=7^;OgMl}mE0!q1x5wA z2oPg62CbqjHg_~8c^p^29MM<^$-t%D9D!LF7q9K7Zw!Gf|;K2jVFKy(5d|CjTgWQci0PFRUynw{NOL77s3G5eL&{pg2v#`IGVUJ5}jAHOJ z0RK6>h%E+4Yzh#6Y?FEQ?WIlj>{-SQL!3dCV(hW4YY{D49!LE4_n^M>&mQyrwE}yL z-Z|1iM`!Qu6CtVDw8erpxlj1=52ni`hJ&8BU>*D>-U*3`!GW^I(j0lGlMK&Fb5t4c zJzJlMVr7|-%B+h4+YP6O2YS6xxumkKug&@>{BKst>ML>WULzf^^NE^l{x#YlJDYt zjA;X~#h^uc^GQo-dwvK+T9SZaim(qMM>>615zMO*@X3WW&jK_-dLTzE_=6BRX&jXycW(|YT8`1{j5&R(xK03nBV)d=2!XS#cYX3$TColk? zu5oq!!t>A2w?jL@=pj`+^b9Ny4^>pwwduQ<%%9V77)--pW;P`&zjrd;JQzk3F$>`H zEo3pd7=*PT`#F0vSaOlY!1=dq*&;L{{_9XkNa`@k9MiCIgivMXyP=ik<>f0t(1`Qu zTtGS&{M;B`1juGX^zzWA@Q_r0`jK=MwLJHaoQdR1!7C^cK&Tw5K0@osGekb_aKe>z z8D_!|Hh=271%I7<#K$7tphMgdUOEP#h^RW%PM|7gp$wCw=*=GxQfmalIDqCl@e$yc z6SR-T$4h~8bP7cw;!N#-4L>Cn)u_K;6dqygSTTk)WBxOEK=_k0U@bZXz7BX44XupGsdyZ&;GVv1tUNAK};+K;Q}OAEwi^@U1sAjH(5Xp0N7y znk{70Jd7)vmMXK7e&8>>!7K$^00QIL7$-w*&iEWyiXbe7a|z&)@Gn>oure=&7(5&c z8|+eq4N*Yqkho!Zi-(2yhv>}DpP&B56B;tYOAq_%5#z8ee3tOAu22TZIe}z`NDTJ_ zfBq=cm1oc9jDm;wP35_qht|#Hyp`=iZ%=;K{!#NqHPUQDj0FB)Keh_KG-1a6}&}-9v?Zf z6nvGGveu#MoJF2jUVsOxpww-`P4{u*pFk}5a&{NESY!#& z)Ku)$8j`wcEU^n5b3zE6MeJGVIimltX9J;vu9$(RoI3uLc6Fw39Yj>491U4^GI_a} zCaxtJN?ThS)53sNrMiOeY)FS6`bFB0Sk#?F;)5#?%By2Xr-ego%ndRKzkom)s8jLj zPcND)ua6`rsL;;W;(zwmwHLc%%7mc_pf1;9Sti6SQT z#ton|z}PJN2W@P?{K; zU};mW>r{b4iPgOZ&PRazNkI!K1z8b{_kVDEfhv{EZYT-RkEY8qol1YN*Kif0v!H%EwHhsGZ&6K76aXXi=vgKb4GUTh3_ zg5vP^_PY{>at_}mgmMlxZe!&fc9$K7c9_(PAwzTu zvGH4CiR~$#czhDijgn3fLxU9&)XZR3W zNUo@%VJ;Qw7|MiHi$usZjz7S)9}5;PB()zzRSSL%%GPr@BEL;A={XCjZ^G`+slhW+ zcZKYy#_p=iRiZtIukiG?M^gG7^gKWeLk1X2V(ZsO-w79A!cF!-5E|k!&8#TgCKV%t zVb0ow30IP^drDvH*E@3d z?A+;3FKIk|-I-0<3-Xu31F)aNoMPUxW!dXuAmF5D#BmP8xwsC`V0zmIe)oeFZ2n&@{lKgl_uPLxX_N^qk_KW8?1v7CuPC0(M2}kI%+HhC93ui>yFSo3_ZxC zuqSk@q6*4E(k#(9N6%TUl^l%?+|kuT)zeM5E9* z>cw}`r4I?5VlaAtYM6`eN?5AKBl@<+)N0#tt`|H+ECNT40sjkF@0-aNj*hIP2LhHO z=R}bLJpyRyxnljcU^sx>CydY6_o}rJ7mq1^Ry^r%k71$_X#DJ7o8IcKlKQOBKdrut zI0o>=3=;IL;CzuKRWZho);2uCn&McX=-P)z)#ALogeUiYvs+m-{hcO{-Kz#kk&pf^ zuMo%1#msP1b5rWgiamb$-ptoGwuJ$%yCl7^$^c0Lt@#`LG<3aDwNSIu?ty5f=<(y! zw?1$#g_>+;li|gLgnaI8+q_?v?$gNlDKJ>kps6jT-<0#$F4^*H^E4;j-S(g0H)u~7pj@MU;9O%G=J<8o)|T! z6Ayi!{!Dmr9lSd762agn(y0{%u@J0E@V-ztYu&sGiXF&EGe5n3IO~V*aHU^wv-0v> zwy9Bdxw=6^?#w}UC_#XbB+R&Z`?jO0Evv5v=c?*4)>_&AgUqhhmiW=ClqTiPK%OpaXjy0t_wwbDlKPTTd+B4>Eq{RaM1Deje=T zT$)h*9W%mD-@fME9bI@Rw`$nk&x0o2|D8obS1in4Uc8T%?FSn++bS6h{tO%CYgQd|XkMuyxb$vl&iWz5NdE zQL+a0ecX@E^sRmN{-L*Wz=$QJpfn*voF7x1uJHJ^LeZvxH_JgQ`1tkR4_=#rRuN#N zWH(Z;KJfWLPwn@utlGxnY%er-=ZE-@FLja{5}xb|ht#}?kQg=RqT2gD&gz@mQ8rL!B<8=G+Kj>xF|Io8 z#72#-@~P>dVa1Mqbm}l~Yiv8+MfOHF_f2siC~RZ#q^hz||J! zJbhPx?aKZ~so)3~K5nGdFZr@nOf|5u;$v)MX*Ky-m~QU-7_P&jtdyGX|xFhD$9Cmq}Ja6v}wrU?zTD zJcb@hZK$m4{;o@6DvKj&@V!Qg^W zz3id&gZ2|+GX!1RHoUqQ%BouBT`n*3FDL*bF1dvEkF9H#iW zEIuk2X7&wDs0FZ_e`MF4j)u{>fq z9o}JaJoY=-Vepg_tEs#UCr=$*mGW^P+2#UwaKnfyBF#(*lLzHncLH%Mz~axkmR5p+ zHt#=tbGq^{KHZ_H!8*aRa=6_^D&fc3*jRys4+_q9-ud*83GVK2@449VS!?E=cV4-v z(}*M1rg}~%yJAq5RGK=o_TV0=a z{fy$X?xA_=>i6_igoII!u@0&(!O!?ud;9MBpjCB2^jbrizO_a0W&i0I%*1@+G3@^Z zmyE|xo|NPt`BtW=cL)?Yb@gPuSAt0zUL6{HWq5g4owomGb*&*l-}JKItk8!1lfAKB z3jGc{+5@sD{c6;yGQ*lNk!#hm9Ey_CcZR*l%2KTOK5+G=XT42SyYcX4cFp$rN(=Qc zM^FFx@f2iQCt-zsNCt(6X+W)G|y zp1X!woa3LCrO)P63#(ZLJ)E zktlcWX!tae*4tB5UvjRlxamE!0{tR&vCx`9Dg}pT$MQ#yc-z{E7fBHO!~21h)2SFNfaTsygu4A6+zieeE8g%9ml{VW~*aIW>zHfT~We>AW8fJe}i z_P^KqPLSN@vsvT*nuaoN+xU8`&0Ya?ta^i(+VuMfYWFm^%og{+$ivMATQcmh9*a$S}lT;*@@c^KHmKFHh(aJ zQTfzU&TH_+{z!?*uck|-XEpaMHeF~iK}$zZM#5OhrGCLCyMe@X*1eJB?$JQ!k4E+R zZjxrA?RF6!=bpB9bX84TnqJ^~<$J<>mDnLSS+6af%q2}3^K0Zg1qMzU%OoT>8Jf5* zo@t@CMbfwXXWG)1VPEbh!?>ML#J@ssb*^1Zx~G47YL-IRmo6*O-SLfECtnEi97)Lx zt({JB#(dKz|MxyWxi4rosru~>)(ZK0w5omn0}nAZm-@zDrKEEuB|3edU-4bwS!?I| z<(s6(Hfu-=iilgTdUdceWNmy7LW;OVn)r%D?DW(HN8&vt%bPEQ3vL z>PA)43=h-|dwsXqZBUmzXCzX-8Ezo^`@2lr?|{HEU>tYqj%Jrei>0gkI>pR#Uw{3% z+m00#6^&o?U|qy=Bx-Z%J53XtEz|ntwE~V`w!l3P;A*uO`0?ET-fFOJqYmLFtr|&^ zKwg_ZH%+=+pdPgP$DBR^BV5(sE-Gs<=&XMKQfITx`lT5ewe3Cr1~D{N5`>Jo$<=%I zhQ0|hez~(%WRE!cp2p(G4vh%TSC}H?*)gwlZVq{gxOFsg;s3aP9#X5_Epzj4nQ03e z76*sM9Yg&n;KyGOi7 zO4jmLi@ZD7R5EcxY)g2j*Th(!i$$;BrdLzl9y>+f)v0068~2>zrhygU#-s?Q$uf`O ztaf9dCbeqSYyu_k3-*;CLrl2+sWzdYQ(?Vpcca*@tKp?p>{nmDTiM1#|Kwz|MEES4 z?36fPiJ|^(|I(YdlV`VmfDp)@#sgBOj9%gV&}6%23_*{y#l*#rI}DDI9fIy!O$ z48z2(YY`nEMHx@G`;UJ0G{$8QhlXe07U`E-t;x0R{^sWN=P?*LbF{0cvuBJoY|xV1 z`VLOq_d2t*=b~as(Hnt1Q#UH-bn(4%et0e2&t-wY5nai&$xBUf&DxXtE+|s;Y*TzU z<0ch)fOaF(V1)$>iZSU7&*^&I{OG%Y_~k7nRWBydeQnf}dGRtBpaYYR7p#gC9|SlRqmN zq!AcCkmnEjT!Rhk*V=0raQfe@JQRE}MShj0Ci%aiNI8%coytR_+*AxvQ0J_PH$kJu z50KTnS%$df810#C+Qb8>69@F#c&5fPMbBt)c3Bn1hPRzM`ATO>q6TDp`LNdW~(DFI0-X$fh5 zbDi_N&-?xj-}oHkjALx}Uh7`>ob#%Chihsm6XMa~p-?D7RTV{T6bjuRg+iOf!GgaL z8JzkB|HE{XSJlOVUp_bw!r;%i&MHQ3C={^;@*i4(OuilbrI@>tp}UTgjr&szS8J4` zg}d`3C-+BomMl-KUES=Q9i@n#z{&OD)pY#g92ANLrK%{W z>zTIx^PwTd!v&G;4|@U;+2iz;1}#bB4v#9cu;}q4C_0i9xwBt{4N{2U;h>F@@x~I< zS;dObk+#xd@{W_B$zdinocPZ6O7A$S=k^Ia^Br3ZWgLH_@P3`iX0zTY&P3pKU>N)w z4hb1RLw-}>U5O$iB_%DSrIKZXUn1@3DvFAVxi*HVaO8Ca_$=_RaVZvP9PqE&*ZKV6 zUlr{`F1>_*Rq3tx|9|-Z(+hU%_6kZ-_eo)4p^CbCkSiE6B5;hE*-u{RtiGJVgE<-6FmC1BI=u<-KYOFUU``5Mnj z>Lx;URr~G5#@{z1rP%ZiyaWuQB$kyl`@ctumvR*^cKU3;X3-Z?Zz7xcB$*OjGoo)EgFEeHogDhW_Hc z60LO>4m39(5wh>v3=9ooqY@|<*>7&(zR#HHN?rcD!?Q{yj2hRd>1exzZ*FD9zD_J} zzu29~J6>l;ey}x3ET&lSvynZDz9vMqeN?by3^QfI8|6PQ&+Te@Wue#1v{qcaA^F;K zx~ZQ(2P>_V1N_LcQz9?DRKcaBplBHzqjqRMr}OTtwitXaN_USiw9F-)*xT2_^v2t+ z^tRpcoG)Kh0#Z}yN6YTxv$N;$XlVTAYjx_&XYIFFZ~9IbBXyRIoxc)%fD`yo&@Cw9PhN}gu85?|9gwA@mWkH`qoMhn*e+?bU%)A_f!jspD6brEz zzOloT)FiaD;X4am2EWf$r5Ht>Q8hI+1v6P!#nlaUH$RMQ>6j$P-g}1e^6Ze9LB^Nh z?Bs9x@ELg_FSNGH&KKv;-8V)Fj|uq(NBXeoj3@M58R|v+{Ytqzlou$Mq{W%FV?kJNEeJ4%e>r*RGM48dn#MTE*Kx+nz<6sIm*BI+IcE zLDMPTAAd@O&AKs4EBX8njg5`Xi1(xHlpx*!5?n4eHgqK=C0mi%U1Hz9wTDl4PAAGe z_gAQLjS2^@3CfjrIu3Ym6VQx0?zNuSjXq>}Ya$(1dau^1}xhH zmmiNgcm!Uut1byrUVi#P-kn^vNAWuCSgc-?beaMRN*ju|3K9!hkWp& z>voGGdfe9s*&yjPm$gbwf5R6g8e?b zPIB!9O=>Ns{FV4b2WG|3=qen^A0GCziLH{-O-Av3-%a^T8|xd{KKNwV1o^}yjCXCF zI}Ts0FRL_=7`=NgQgcLMWb`I1B7*1puF7**usIL?D=FhX#!Jh;>Bi(Pu0GA2d4=O6 zJe4&?o3cj}oU2Uia`8uqw=qrY?qoZP6SAMe z#<`*T=D-^MaAoO^^XgEZkW}pOSVttah2=CRmJMOgsR<#!;|kqanRAHooeBA|may`B z*?8t?9AsZciYosZn0Zo0QZ8Ox(~w&0^Ji z!t3I7-}-L~I)t72aGQSe)|=zg{b2pzK_-hC-kF;5S}hyFH@f+w5Bam|Hj0ZdZaMs4 zyg*0!ha_oq9PC~pcaboVyWLN6|D9)o1Ghl$MMl6=^zY3_yCT^}tz(YXhr3Ug`)4k* z@z6sXK(n<^q7tcZJpFD+vAE3kxC@VBc{%$eN^jsg_e^e`kkQwBZ^EYYg-mM`mCi5B zYK@K4`jQGHk!#N^EhThhWTd$5*0X>5DqG&<BQ(8}Q% z4hL3NUPEPa$tcfq$h!D4xx2d?p~Abvp?$J!OjLKJ4l7&xzBSQ*k$TeHxyFgRB4kag zo?26^8IwjGI{=eT{mvcUD(0di_`gW(4J5LvcX`5j^kRk!Wa&NsD9(-l1}LK|Cmx}WdW)bO|wY2Upus$ZA3 zojKL-$8dH%BCr07pN{u;E#rAgibf4=l<=wu)`WKmb5%woHSvJeUg%X;Wkn||*fwF+ z)goxiza3s>i?eO80|sP1F=YNGK8yqx#=ZDn}x-s_`7MO`(H zWvM;I7b+SWw<4+d2OdY!)7^_D;b`xXcFf61?`s?kM4#J3i3dxJuFDCL6pF{db*p@^=@oPx=8|mo)~%@j_V&IMxG2ASm7!{S zvRF(7eG^^BuEd@PVKQ~N$H!Q8?yF=;0{0`7V}qJM#OtxikxZZbxF~WA17i?4!bQLNHqmM*_e>m z(IFozyC3-B!*$=oIqU}y9~#^v(&n$Pug4)I>?phck>tGyP5G(BZ zQ4hx}pVJEqAMPmWlBVz)l$mh5jB43`{WyTI+we?sy=%m8jd|-RMQr`yKHW28`jn)&j6EO=4_Ar&+abe%p^SVy1KfS z?g%%`q7Rd`PF7tpj4MAs-t3H`-5q@u0PC(sKWEp0n83d(SHCs-5^tN*fk_g)aySpH_rthp%Kn|L2aI znle#O7A573VOEZRn`0q1%w#O?O*xTYQins_w<-6>DXyZjvNevqIa4EDeCzByCR&m+N#k^Z~`eKg#)@+O4IR*wsAl^oN*m)={&etywgi7vz zr0RLDFFRI8#1|^j(&%{A);7s;j;UTfWbdTX)6<^b_4?b^hexh__iEMy1v0)q5JG@_ zR#w)RFJCkt-4qcC&dFg9A*Aoz2@r{b+5^b9-E+0s{Pb`Kd2EVogV-|71qC<`V`ahR z8O#K|bXkipjS40w@Un%PG#*^;@OJhG;pFpdJbb@E$!M<}J99q@gBlh(XD-+><#6odeKCr4&MbJWte zHyCbiyLcNJL2+;1;D#%rzfs4kG(3$}!0472c+D;@PInI-qw;CLDFr1Z00o*(!h5YP zCAh*>9%!h`!P>v_q&ia*u(`hV2Q~$u+4Lo&QBza9{~pF=Vq)6<^T&JZP=Sp{20_2R+HIL`WR<) zRKMc=d--zHPdpp#r{#~Q>H=C?hC~c6a*K;2xpm&PjE+)ydsEVvtBmASRFG(CY1IM8 zvFS|-zTsH3ROXiH?lTL8cH68LNTTOofn05FVPWCSawmUyf^8E;dmfX3*=oC|HzsRc zmcG$`%aCdA{zLjN9dP|U%6Z&OiPQ>E7qUe{P}Tvf4?JBE-<0#6wN;{5Cb%rI#Us?%P^L;$(|jo zYfZUKethbbm*M~8%NLx!zCP&rO0i5*6q6T+3&h`2ZxYY=p70A@zkW$wMRs){fd5{N z`QOc-&Mq#kB}N~Br(bn1A+~w^nCSNH+o$IzTk^`RMOsKD$*QU09c;}IXS(-&g5tnS zTWJ@u8^Sz4KR5j3Es`S4eIFNg(8747RYh%W7f?zd-CWLU`#Rd%FBC$FT4!dM&yM%o z-&^-+Hv5hUTsPEvWT_wc7A@SR?e-tmH-Uo z!mlAP?a4wXVaFa12m}=$K9GxQ9oacJSj~S92Oo?sdEV|TfKZeam~n3$M@lM_Gf z{gRrhYCv;&rG15e4AbS34YHB1jH1H@_ zRt(vbjIWD`bU>|<($E}^Vh&eURyw=7wk7f3dzqfjZ{C)2`RY|-3kwV6MqsUHfBn*B zH&yn#OcrkL=OF;_)skL z!&uGE&W0a~g@w(^%~hODD7t+me(rNPxnZT{CGn@51kB9L!jGp6R}A$!hla@L=;%PL zp%BN5>qg)kAgaE553iftzwhwNJD)8M=lRKjlA$5Z`o;!jyi&8*E|$#cHbz={Iw>_Z zr?c7!IWsfy)vH%w5VEnbpl;l_A+KCSb#QPnUgJpL6;Gz8*?UsOs!b~KbW>M7SJJ%2 zpRTzKehIw0lNy4|ep(^LN-1t`Tpr^#Wdc|fgKZ4)@kG0Xc;X)n5nn$#qvCQQO zyGr_r6V(nmu*#xtOHl(_VY+m%&L}1s->8BDE>vEJZC{!gI%knI{A9;a-t9`4gl2W-4)?B{`~oasa}wVhljWQ{jQ9~_jh-ah3&{dmC-8J=g+djwVbMR5%u2V z%GEAJK7b1OfER&*lvXqE)Zd`Hxw!?9>or5iuv+MhKKxx=PO(NsO-X41f)+_+hp5Xu z<^!QOE!@GJuX|iJr^Gy;Jl459tJmGL9; z^Yh!=m^8SYh51Wq?)k`7s4*03@xwtr@df#qN%_HgsP7l9pk>y!jS3vxue4ZMvqf;T<%j5hf#tnSFY5-l)krn zhitHUfmSx#{?(f|;fxYbP+U^a=6?U~?(y0hEWLLV^U|f(pFbJl5kh{M~};pGP)ZBCi3Pv@}ywQxlEQ z1C{7B;`c=~^z;kyccoiFZVHZ(&(%H@P|zjZoN10_SB^n(F>Wo*&aybOjaWQ-L;x58 z#%@b@w_4>H2t&>u9vy&hUcPz5ZQl0h>({Sxnwlg}HmAa&kIM5=DVUj=tr+syL7NeM zc2F`;%*S^86ckcDb(qM4f|@R0U61!x3+{icX(`mb3lxTggajocBO`1-j3c}1H)-a3 zbP1|4EGkM-ODnF0`{KT;DlQSTGy%M3Z}mGiEK&uGOYtN%c-7pmUqLG?wgEa# zGtu-nXIEEo<5Ys+ks=rfy23SpTOojJ0Rt(9vY`P|(sACKrr$cjLj;l8I{dYJYs<$YkAFyRtBd7%g1kw)jA`Fd<=Ra;W1=iNygsq32>0a^^#y--JfpHqF z39|~lA;{NAe-Rr?JW=Zu3!CZvsa|})%mu^A!G?m1OC|J%1ZZqpl(_i#3ckM5D06_6 zwxcC)TEgvbz=}fcvr9@cTz}Z7t4;-D)8Wxn9VxWbI%s!^%PJ}={_xQNL!yzTf7t(4 z&sY7J8IU;v{S5-3SY*)YwV~4&q3`VM9PW>qp`oCLlEvKKwS*6czJ1GN^DQ|5xC#NC zuuA3GTzlx@eB{;HwYA8EgakF2$KKxJqvd9?z?lCj|L&N(i^EON zpZ!{1UVvK#T%fH6)s@Kg?=+6+LLTa-0S*>%%IA2E4RJ7tyRVd9 zWFV5Jt{nibBE!fhfR0RN^e!118Ck52mO8t+=}Z;GXJo{}Fc%dUp9hG86bYcOsHi9e zeN{Qln9dICQZ+O*&|J46U}I-TI;1Xgtw`w!m^R{|3Uu;`kXaKzJ{UR#eF(NPG~w+Z z4>RNxa`qf|K(9ogE%Zqis>o}P#sxdZRH|X>QNtF#@bt=1`MLcws^A5JxF{%c5yXW9 z8y<~Z%PToK*?hXu>u~eqmignyW#i}I7V#NZ;n3fF{CRDx9DwfP|HW8rd984(a?PiI z@L#=pg+e(_RJFpQ1Q9AOY6DhMvJ*EnZt(o(%V}av!W{p<=7EU&dFm`JhH$DU<7UN?8v3waICQGh^SpcJH3f4IV|k#++5b-#eEZ#s4rhs#wRBi zzQnO}adQ_I9qQu#J0l_i?chL5(1e0rbUylH4M+kF^?R&5RyF<#Zd%y+9ZO5L#>U2% zadBt}NP=!`(o+ji8af*eK<#Ad=i)%iQ79uLqeB=bb4yDhK+yG{_!KEhdGEC>bj2cQ z6#7{!%)&%~M5G83j7?8Vt7Awedj_gV)7im21~FGmn6j6Fu~6ofvhD5fUvn7c1E6Hp z;*S=wLChrC^6K*K3h#aU+;{Kv4@GrF7#J8xn3x3I3I6lOy1EnykVCBu7m^*Iz}eZk zrN(hmbXpx3pl&@xbTd6*`Z zaG@~5^p9L5JbnlDrrxv~%vJ&%bxG4$9y%Q^Ha0fm>ABW7cDoIProtM6s@UO@nwx}d z9~Kx)K*v!2aqP-X9-W~F{MbQKx z_y+C~;e-0HjhJWq?aa;_gKk=N5_DKglW7200yZ_fwH1qofn^T%iBstUZ&hbBeS3dD zG4OD?_$zlPChw++qE#A3!G6rFsL*T)$}KF!m5`9=7$9QvfK}f^1EDPx#6}D*MoH-> z>xKd3TG06$75MTcNnJxj8_;vv)d$1KF1`Mc2<*nsI|1mw zhw|`&oX4f5@c|pO2XABVDyW*IWMtW%l7M?{0XHS9e1gj$@b&c#i;nI9hAL?J87I-u z&*=7TeAv*TifpZba4Fto$oRz|^c8N&b8iKJ;mGTM1%sd%IbFwui~I2^<^Xw>jg9I2 zhpvmkdjdfA?(XeX0^HZu)`s-qhkXn*baZ%(#oz2liY~!m0!W?(LR`eg|52Dbj)!!g z(+S)9FZHH^gk%iJZ{)?Lmn+PTK1XCA(O=RO*Z=b4hY^f$WuU1b5g1n6Q^JEL`Y%nT z9DQ$nyX0Oi5zJTHflM_2p^W{3ECpz}%1}BHk&%})3Qd8Yy?{;u(iARZa6xw^>ea;V z-@l|;@vIFHqp@6k10Ou=~cx(Le`N<7<1TSH9!6SfihRax}4c!45E3ocR zN19Xhr%S!`kAA$r1X>BKC#7iKG4$uIFj974F0IXH-ay^pz5rE;w+sxBK%$`I*VlL# z=;-zuYPv3LV#-YMbkC0WxWO*P0O$s<<$b(|QtRmg{RWj_S`)9r5rKBv{ov@&;`Z(? zx%jO-@1sALLAOD~>o?aQwtfDrxS}$`CMCr%Bw*H5GJKPb^vsOUKX>$tUEH7y1FugZ2%ensU4 zfXo&|x_J3AbNpRiUNA2Cm6pCfjmurqMXx|xW{`M70F~wAaFTcXwYj6?*{Jaltce1^ zUO_+=8kZG#f?xZqI;O+0ii?W_2c%uXOu}V8DEqYf(GRi=-(x$EE*)ODGk~uhkX;xo z(&H^Lu2ysGVMYO?r$VMTv@8o78!Qx;fB;hbupwR6$FG6r9H2950;ovI#pN0>u#3?H z>F39ddgrJX5IY#f-CKa*6kTW23WhCW%)`yydU~{b?b*R2P>EJc%NIe%;Nw%@86O#; z1nq5vQOj}a<5S}4>1ofM`Aer~XUM27D<_auP{2?KA&>*b50rBX9b#)6oB2tn=8i_M z-D$e_vWd5WyRpTcuAN4~Z2*rffT1sPnZ1a?SRR{&Oy1d95D13L@8QCyO*MeT9#~tW zp`iIkLapmQm8=Fn_^$#R0@#PQ&wX$b1`D9JYf#RB6cCt&Qj6S$Z6xSCD+}Q9UZK8h zA?~+t-w-a2pa94-_-*|?+xvdk^I)CU=lS#EYm8bQVDcBHM@11F9v+&*rYkTgpT1{? z>`)>GQ50%mbTlMBKAwcsp(;C@ZGEPh8Tw@xOy0@|U&)f1iOnr6(4Z`Rc6)Ey{&=5f zc>-H>79cLLa~2sHvz8!{{vcd(=fiD_4t3Op0Rm&ErUpQA{FWk8obsJi4+3I^i~v7C z*TDv5&2QO(m6bK3ehe9&yC1YVz-BgS@}Whj`}OOAAhSW?u)Fgme$Ts24UUE7Tw8E~ zUNIFaGcywf4K);cR^MBx9_vM(@R%4PgvP-|U!<3Rf{mYZD_R~R3jmtGTCnB18lqH7 zkw*z1==}6)7kqkLLPAh(E(e1BVFrjkKNbc_!raCtq);axkFmBBq_EB+y<*tqC}81$ z8p0M%d1PUB!8^ZzMhe`Aa*-VbSw!b-^sJn}a-}F4)LR;mRU$_GQL`|s4`Kb|5)*>~ z4rPH}hkk{FhnY%Nn->J5K=mtuA3sWf$C7nO4FIYumU#h$D$m1hR-68}gwLNp&sr!- z08v_=gY0ah8Nhp6M+ZXYPq&Q20bI|nuSdbS7#|-;aecaXINKVCI3ffD1T19XfS!X0 zi`u{*xwnS744w|mMI`?L%s&d$EBv&V1wNkSIE9HZj1u$B7iU`%lRtm{j04pz7PNMx zN}Y$bg7+XZMZ2wV5PID4w}^@_G0bRqrUqot8Rsy|ip!w}al zq=14Gym>Pen6a?1r)y&)-Oa~Qh)4J3B`fk7UAOdd-by_KR|Vl>qCSU$fXST~yD8J8 zo>93ieQQNbH5m4$zE?wGV_HIsMus5FyKTUJPp|mCm44nJyBgLVbLr*qG=LUxerJm~})f7fG`CA>0OdllME(Bq#CxQs@Qchbcvp16KfKBqted#dM0-!Q*DGfG|$-6d23_wE>Vqidoa*~f%kYE!mDWaJr z?GZ!nE)dks`J>(CwDVwHx~pjM#yos{iq6gz^E>eDXN-QOPbY%Y`hS$;E9%LaTz-D} z@K=ZHANrla*@2;_Yo&cG0faR9h9g~Dd;2xdZS#%;Xazp|BL;@`u9sn7fl5sGU!b0i z2Z`2d_t_S-4($5?ZgzIMnDNt8>OsAl&Cl>{13-8U1{+c=!^3-lZzpqA$$?w5-Mm>F zp)(X(WKhlo<1z$Pv8HOe9_Z+ED=T3Y6@tGO7jcs{>qQ<<(JU=3g+)e^i{ok4BiQBZ zmoF{g#-mUm&%;)mtD@Or1x@+<)a!pW<>wBJ6U0D16;@VPTfclMh|t#ds&<-T0yfq5 z+RQgx+~YTj>wdAijOG z!AjU(|8f2B4S(+48c)QHo=i}gPp|A!2#_b%MfaVGXGuk1PDFwL))iEZm7K7Q7J@&7W6y! z87|UWOJAm;p+R&dU>Ki4m2}yeS3>1AU&p87Yk?k#jQVNr3+na|!od7|P9P*Ga&q#l z1(L*YmA;lPpGQ{i{f7@)VEz#>Nz#A{E(?U1H!W7$WOu0-VEbvU*|WVB(v+J{=jA8x zv=u<=1(|_ja&K=>(BrqRdWtYE?8?Lh{b~rn;V<`Rgr=sZ0{iJks;qPMdp;?syP57A z!w{l4UtlaL$`-<#1>LQ}@4^?6_dteQS~NyS!4{u|sf|1ufPWN|@KlI7IrIG(sWJr+ zu^$GUuV&>HZ7QGFoYj!RC8eV)@&p`X!rpDBB<1x7vsk~h4FoDQWbQGFCoINN2#bhZ zv-w5?N!uv;n;JV4DtGP#1EKq`G_LIl>MMNUtUU|J-x_!AEw-jVsocGbjRNA0555pO zCz(FrP@vG2&rhB}SCji6bvrj#U0r<^*f&fwz~S6AGjQ|3PGNIlz*ELl=i-B1P-Q=Y z2OcVwINl((65~+QQChmX9L{PMNLRxqVvx14$b$8j#=&P9@dP<8;^rbq z`Z+M9;PRo$|53G}*CM2CV?u95B^Q7IsrUZx;DG^6xTn^Z78L4bYHB1rpti4HabY^5 z=a=|Ghev<_DJ3PyquIo5=qe%;067qg2<2Z`$PL=w73b{Vf5DPRX6kE!`!7Jly%ozu z_>Zz37x8^?5TVLo0|RT#s-yh{dtv+FAOvYk&P$Yge58l zTN;sEx*#qc5(40($P}h5SvY2EYb&CDK(xU8(IY;0z9I|zv9jpPx0B3a(yWYE=2$)h zW&`p*V&SBvF@Q6~9H)Z$?AbGT{#iLBXAqJtszl;D*u+dIlyU9jXc%+&X$9VZzthA$ z@DQdpR>r7bW)hAF=!}u}qTm_({Qdb9kr_acMN13bnT1@Dy<6v)z`OzN5hYIm75c$p8M+1B?Rx=*u1k8iTn0VJx$aFT~$@} za3v?!e*GmTptT1N9!5G6Of4<=m;P+k&u$2!A{Py(hG-R zlBk3PGW{(plW&*BX*U2Jg^xyfR>uvn0>>vNEP)+}xDs{4YdyWZS^hqxCLRk%>c$kc$X@{Z=g-CQ1IZh*P~L?`>{)^x-M2u}!2Lj>`T_t8Zf z9AwZuzyvV?HDPOjOdO?UE#|&L@>bFd9knu$g@HxHz~!9X4Ju1ihTl0YR3U&sED*C< z+&QxG9H#270Utu5CV-j1*2h4BOAwCO5q*6`kVX#zBe6x5_Z`@ff;Vn-LM;yz>Ttr0 z;0CNUf&+Ttc++zU|DooF`(TrQwjP9J6!;p51OS?l#ZeAj7hq-}e8JGZ=gVfno&-Ix z9cB`>fQjbOsxD%&AT+c?GAvhIl#pNq2VUHPG+Y!2wW1J4V|UJu@B&(PfI=L`gqCJ;EU(x&@Ioib?P!h`>5P9v}RcO3>mcnn{WdE>8}0cGylRK*165J&TBP ztbPRp1+E35$M0cMQN16DFrEMxB0^6|X(_mS(IEIjlTaan;%ON(^NWT&ODoid?5eO3 zAnNN7K5&6%K|xIo9_%Az6v4DypQyeK&mRTEuH)=r(h14?pfZ7ELEfsdCA@nRhX3~7 z9{8T5(EA5IJ$stPPKpbAC+lv8^dTTP0AU4nIWlmNLQYN&(irmU>QOD+J?}sTf$7!( z#v?ctV0{!7gF}k&)GoK>KD|N-EVCw`aG+!JuqB}(wSi_;??XR$k(HAZ2$L1m8+63# zd*t`$7p|m~RHe_6Ya);Czvg5DdVT7J_U(T~cQu)x5up47Ys`0DpeeKgB%DYA-4-qx)dFQT00b|9{OkjK zP+LzAJ_xznfB!1O@K0>2Amio*A}SY%#R|GG!Uze@zI1oD{hjfPh1!~f2ZWyQBZGL8 zv_hDn#LO_<3$Fn^7DEaixC#wYNaRj2vRdSXj6Q!aG7JBmR=JjuaaZBNh%Qf8a?XNB?x?!IDJMVgDm9wS=p^ zc9QViW4DH6TS=5I*=_aXw3+gN*DJa6DB4-yG~C}kK`^o zI+U&%?Pav90elaH0f_sARv&sJ@Jb||hbbmq$O&)jjR+pW_|zyA)OkpHdb+t0V$nco z0+QvHaPW)fnq`o7v;s%=-|s_1Z6JCfp%L#r@QD+AF{S;^8ITMNJkvgVjI`__4^ zQ4M|nehJzF>kpZOPn@0o0|Ml#myrksNJn8X14sd_0cOxTzMLPnvh^k<#j^Fq zC3v+wY$1xth530z_+j=vL~O;86xDxbp_?&H(G7Tx!!b-!5l~3zC_a9EFiI=zrJB^Q zv;&5%bX`;f$V!PIGr&dFHZ0jigNUwf*35+b-9Nhe%n_2to1SI@vumWG#02O|7HF5c zPq}q^!P8e;1JL>}A_LpkYyb!|Y;foPm$H7~>DK~|=)N{en145; z?2lEPH$)xs5+EW8+z6fPlS1F%U}bl#k*20U3}8zn|0U@q^l$#Flt)H@lsgt&^?3-d zw*eX%sByg4aWLa|!3Z+kEpR?u-Q0?W+rgf82CX^oUQ>)c6+BKgn6-LQpWX;rt0nf8 z|DWuaQX~~ZM!>x*TK81UJ%#vMD3A!`?X^o55OWheU4Sx3GV&m$p>2C5QhMHa9HY+?EHHZ#KP1%Ri4B0UQsH>51o zwLCzlF==qe{Wme@n0Gb^TEX??l$3cGd``UvD!R0uST7T9!Nr0Pj+VJsZf0OGruLD6 z_jL~`BO{U)LL_DoX8HUSbp_x^B63g?oDGERqw;RXInFdO!bFBl)uX&S3qsG2-2qM% z8!xkS?6<(8fOO9SG93zW&#FKl(>_T3Ps$dc6%s`NB|)q&HjGCRk%N_ELqHCOCO~mp z9_$b#&KgO5wG(pwJU$E%eer>?ohbNz!GD$Z4A{gTrsk?8#l;1HxCh;Yjg=J*h|bHN zMX;8Xfqz+8TVLYk<%I;7iq>avFo=Q4fG7btOcwIw;I>kB?|>}@p&$$ZULl5j`rr1< zz9SHyO^p%qh30zC!F2==5&*5406kP(~;XdaSI5gRa;poQx+&PYRe z1(+cuyMQLzPS%vppN)R|Rw6IMJR-^GugeXo$qFzj9!-;l(T|m*q1^Wf%ypY-g{$__ zNLj85D4HH$SDAT$j!F@6LNlO#2u2Z%nty_0YEGvGU(%bQ--){Z!tp)XxQXCED7~^n z;)2g$87BZ_?E+ecWE5$72vDH%Ak-8dbADZXT}hc)b4<_ctL@M^peMjF31!V~eGX13 z!1?rJA#y)&k=U)GTxIn+lr-#x@OE#P7rC!a5biG5&+YchP(P6J(3XZ9V1=6l2+>KL zdXs&*mwx!<3)a5GK`QVXh9F6UZR{7)mV1bV>$V8KX+O>w(6sS#UslXUXLFm z#J;J?SIJLT+X62Bar4EwgiYW3uAE#B;niz&(a)lSlx8eWR)A^w;UZtUenTxya zwPa82|6~EWDWw7V^0_4?Bv2sC8N&;^3G7)i-~BSvR$O=T+YR)ooE_JIx?bve zLw6N%k(eQ>@Y^p}Bnn?)Kf*I?{~-Ly0##dqX*}M>2Nq6z+)xbU#3ks`$RU@qvdw1c zyO1dXvf>H+1`=8+!i9!JdeDk;r;x-Xg3Sb}Gu>aUR$6r-A{$UJ-z_(MJUql{f=bSk z3ymGLNx*lHR_9IN$P!91wfULna9hiSR<^XW|1Pnw&;7oMjQR;N7R@3hwWx((Y8QN8w? zj;X6N1oGds`;La0ITn<4CSY+0ku-k0e^LyoKXYL3Q0Ccw;Pdi`QBt4<=ani5`+G}j*TsXH}barEBw57T~s|niAp3>{5{=#xB0)T z6DXqnaP1ej-=t6Zh+bBJ6UH0K_rARSn~$Go%9baOwfXF&rSto*FC>qpw|YHRJ^MdO z_OE`2M!^rK_fV2vG25lJGo5icE-Mliq$O#;52j{imPjK9i*)X;(7dtQ3L(+e(?fJ) z`_zmSY0!?Uk>Lx^*4bx-nh`7Nam6l8^1b%)PPF`UM({mfv<6~hppdQur~)zVVD~D| zG(Bh4w?cC)gRYT644MogECSI|hTP!hl-D0BC-@Cwa6!ftK{`O{!c3UMr?;L5j1oPk z=Zh`8Pp#s02sUrQZgr%wWM8}!AUp!_EMyFIU{Lh%F*_PQkk9OYHI20imTxY} zmgt@AYc7gt=Q2ceGV@-U`*PE1-ef%V%iWKAcQ z6)ksk%t|g#h*!AL#$;oEE#T`e-8XqsR-RpziwPK8n;Sz!hR=Ub9Yj?@LAy(V`bCaA z2l*+#)pTD|W}UiFZKnSSKdn-%dcRdV#9+zqm^>~9NF_^y)|d?RC?r;XwQ(C={K-0( zI|G|`4p@rtiX!*gOQ?tsLly%QM8@7&ccU-7=<7v!;X$mX)&>Nq@^XMho)D123`O@a z;;xE+T(m-Z>|L>n^NWll^6vjy^3AW)zSR2__8OLr{Bu*JMB}A(-$CbgXu6LcGs;I78Np73+Yd%NyYI< z3$;K=b9G~CJ)nG+7@K&z_~M`_%kZ}H(MgeD&1Tf?*D-}@fhp9;t?=;h1;xbKrN`c^ zdK5aEe$rCYuUY4_P5EFXv94;BzM$c}u4XQt0HA_L-_TTIQj#SYN1k9d)@$-=;p-S0 z;-Chu>7MQCmy}|7^_n#s_Ba$JHkacuD(Fx+Y(Ff0XO5Qpu&6Ljo+C-}f_PM$ep!yI zPesYA$$o7t{31T9!MNJ#J^xq0rbh=?weT+|N^?7V95s%J*asI4y=acQ@LH>_S*tx) z<%p9ln%7gX_ccVVzNzwXXMH_V;3)m33J;~JWAtvw#c%q?=*WoPy`&`@z~+KNLT#Y% z0FPI+KUjWv@4mECwBx$g+l+ve?mzjRkxbG*O#43Hs-EorL&xpzzOUOS*NczOA{8H; zcbO;hkFIoCQPuWUD_0{zp{reTC8hWZJqJ9!21aSbC^&JUD|Y)fVwHeTHyeF(8hCK) zE-_2C4RV46rD;@hyzH2|8JPL9C&T!GnJK%{QeL~D<0Pf`yQ1fh^{JNINKL7paiA%h&Y@r$l zf+D3SyJ5XQK*-V5(P^J-R^(53^M-cf>3Y!oH{rx5_t8-wp4=boJW|SK3Rm(lVkI!1 zWZNCm(xq6+JTV;kd%)kT*532DjE7nI-#boCR~lQa|kcNQ0nBOovaCIcRLkzo9iio87Ed>nSW&M4pN zS>qAw(EJUy-R^5}KWznfl=srNFB^NTXAMc>)iYc+s-0Upd7SR5xeNKi{$UVNboCOl zIo58dKXPbh%DmIxTCpl-$WNP_XwB8FuF&i|ZU3fROdL*-43LHu1nh6kFiSi+BeJum zt=iX}47rnC8dz3-oVivkz2B{w=0QI~X}tmx$fu>Ocd`A@mb`#9bdC}c&;P|uVqJ4( zpm3#~ezqmmDnvpmQuTNG88My_;rp`BxJh#sr@rG8)xn{mq2{y&E*0>zfZHvM%~4GE zPcVk?Mh>?1u!H3Tq7FZKTCF2M=f?3-co2w+9r+3d^yjq`d;xRQFS?s8*m%yZ=N&*2! zK~@$y>jkdClr1fU_Txbhz4hr_T>GF@$-`^m`6%VXyoJrLX4|W$M-ZBRT($ek8NjbT zlE-l0_#KogVNmR0vGTCK`YOQ$+a*&71w)Sp>V_OuL4;zcPc5DAqGIsgkt!VWo`y74 zO0H8A)YDwc31ccQZU!W2X$=;j&_%mykTHSD69EV1Zk#eizDj#mxARPp!qqGA?bhZh zMs@T#b;4hDJCm*{?Y(Ga?!yGyW2 z?)etU-~NrxQVdcgKp_Y@Q}6)y)_;%#K7j1qE$`#_$pM4}0lym>8k&XdJ#g&mhjv7e zEec^(2*F_t3>$`^nQ1{$QCr!#x$PQ#dzGU>b%p}#>$#=3)n6LjF(J?wl%JnJ(Jyz0 z8Z_Em$o(Nc&W+$wdAkEf7(#^MG2RDJ397{}UAgFLV;$QdXIBBq%zUbh8-jvJT4@$e z$H6H>maAJ|lT;C313V^8EiE)oPR{5PtR8fgVIe{Y`+)l~e&!}<&(mW*U5WjfY`-!6 zo}O{o+Qm6(>?;ix9v(a}fOLBrhkd}m=ms@35VVf@+Gwr1XOD^9?@YFQQLFy+{K8=F zEVb_akpsm$v(D~B8AMjSsM`(8%e!p)Y(oUL^*m@U1qB8Ez-}Q1<^l)Z;EY)N^t5SS z`t6kKRI=Ggpxjx&*)!yfT1>{++~B^BV2z9a+d`#JOT8N6!NsY~A$8d(kd|6MZn=&T z-{H{4sT?P%#(_|gJct>H?tyfj>U>-dIG=rPGZ3J6wipa<&TAPMj2mbs^w779(4;^8~ii%~BM>zQB$ zYUOX~*Xcp6@i6rfhOhpDBSA>kRcE2R@edwy@RFCe*!!a74kaANv?(Yol=Jiy)xT7F z%h(=Iy;LIGW9(e8(!)Qz6vO=vUqY}Z>+2jqFcH^vw9?`trc(2@Op`+)zdgSYyF3Sz zW+3?^$KGF%(jAfX69~MP7p)4Oo)=91oF_W=Yb$abWI68|$cBEaq5OmMC?&C)qkxn) z{^{nmKVfNbUBrV>dE(Uw)ZJ-wUvRXq!SVIQ)X)6Lw>#NraZy09qa8Fv=hIm7FFn0z zC|h{P+sedv!3^+@UvfuK{xusC=D!@u*#reifQgU_iHorE`46)|mKzDHfFYUF*vJ65 z|M>VALe8OZY6Nsa`t`|tka9u$1A*&oIC~Hb9B^8?K#96HeA5iLYHyw<7vx66!PJ0b zLpkuo0mXx!0@l`x$Vhx}>G|E&?O#C4>OgX@@R*S^K;YOfdcvL(bes?dms_dD{r5j# zQdcxDKQL@bOHU8S3`roU1))iU7|zR=Eubb4;|Pc*raFB49|r-Ito;shl+CI6jOun0 zpBz|{Xp;4guHe{#Z+*5%XvxNwodlsf;al+45~ScAflJngBqcOWO_8s~I6OL~ zrVDa37S8wO`OtE(vtuBqERcvN5W>5&2_OIy!Z)Z1zpAenL$rKw z!k{bZh`mit#)0D=i1rVv69g{V*z83?M;(MTR|SaRK06)M-5uGBu3~V?5*Jt<(w*;q zl2cby943RB?<5abq>=O#L~{R&i+Lt|4e%93Adn)*6TsBK)KGysvX8|1iIH>F3=C07h!moD=qT`d9{p^f1g~Ed{B8L9x)yHuqD5U0arOxQ zOVK(HcNVfrO9@f`96l>C3;<{A|Fw7K?^LdR8()M%WhNpl4N6E+=2>Y(LW4pQX_6so zlavgZvQ3eamC96UAVkJe6qTW(kRj59l%eQ7zv?-jU*3P?kSK7CMDyaPjP1k(w;Xr;=DycUCmA&OGp7GQUA@VE@7^%< zyWT;fw+cHst`pP$Q(#eG&=;7Qx#%4`uBnk7Zz%;E6?;%hfCuJ>M?|nO;^N{+_yv;y zbWzIocjFx&lh9TUS%Dj6MqRfUKv?##Z#hxXjIYegFqao5y$s|&{h+W77RB)- z|BFcl1oPKWFoOrczf8kAn*?;st*uF2PJLQ1R$}V&1O)bI;^Vn4VuI`4dSt4Kii*$Y z+?Qyuz_$~jM9j`NfE1d;U)%n?dJ(;P*MS3(gv%09eE6_+WK~sF1>O?PZIeBFGLCbH zhL{RLuBgV2DLUwN9uR295g-`)&^fgIo>+k|o8w$JXA)T#6o^KWKi73Gda!63V!~CP zwmRlwRu(UVtZu-s(tWTka5tfqPn#rEA`vPrxI%|~O*kIRcwA*DMk`@sWp)JCS$MJ1y580DGwI0TL<<2H1vN2$i zvHW1`bO76=a)NmxeR#vakVC1l0VBFm{6hk{Mt`l=SAFP97^J13h7}Pn?(Vl}t)^e5 zt1<-8@vf&Qm<0c`mgs97`}ThQlVlAcbaq$m*l~ewRr)-7;fdzF{bArEJE5S(o|1~~ z#4sxe>kqw+6McQIw5KdQ=5Lf2=1Dc;f3BC6kx_;?&p&(iPn?KNO-(ef0Lp$GEYq~J zSk+1J@nY>}VGF}?0n^MnOJ(@joVABE21l#d5-9-zwFS6GPoJP8#V;Xo8ed7F3SCJY zJEtG6;v)DssiNf&LzbBdh^2N($eOpEPA7oF?_0BT+HjX4_<((6yp+p)2+kcHVvXkRe$DbdUs)AP@Pm;DndR;(M9k zdnpn^NFyF1Ai)dUM5btY&qSkt8pOdcjhno63o(;-H7Gp%nGP7=AFrJu>1Oor5>F(0 z7p6hX~x(YOFeoKNo;KW3*U8#Y8vE^~Q$VKUNdQ6<|DH1k;)Ygc3F7*)~IG8;Gk z&+)2AwirRZjag#EZ$ZLRj=pqhjMFZ{wQw9lzn7|;Ww;#_8x8z0^##lh$w2@t`D5&>o;n8L)y>T1E)xA%fE@gTI1n*WeY zurWyd?c}+E=S{1(sc9?|}`h2Woo@FA_6T3~x!(i>Ddsu&F1hMsgzVQ1$T73E@J z2J3_AJRPc_&vKox-N)#=A3cqdmjHJPonPK=(>R9g1A`kGEH!{y=uX2@g~S{*^CsBq z@viTM5r~t0RSMWK$%Qu<6DyE%k{TO)2gcFWhcNA;`+cKiqHu71hkwV14}`jr9)%g5 zZs3k%&eaEQz!T9}foqkE1HqX9Xf`r4<71dZU<(42CPzp`>yjrE05C7;ze>n0{S$Ts zbP}NRX!ZZ?XS`~aBO1!p16UY4!6lIy2b7)zcdI4}YD_V|zO-u|lhuP@!Pgwrfp zf{^T;G#Yr6x?wsfK@ux>_objPxaH*JQXPc^p8MmtusDxF7-mJ1%J)Z@ zbbw)nYWwsv5c2ZTuEkjO+1-P7m^<=fRSIY-2?&e>X<%lG0VX7U&R@YfPN9^saSUy7 zbTXhkV4sHv`1^q~Bh-}I@BQ5gcF@j>m??_-VJJ<1h<*YV>f|9Z4jaLchD;Tdm>4Ccy>w=8W^0WMce*iStR|FqQ?IJ<$at7dqPW zU;!vtzp%xAZ?H$$hno#??0_W~R>7BH3FfH8rpU|7^WzAM-i-u+#YGH@@6XS7Nj440 zn6}6PB!W~C|0zc}kyE8%jue`1LF53M6DR&uubj^Y!t}jDsW_s_{s=a$YBGq zR$jh#EdpS!ED{S6lbX(DX8^&ZN^As8V*)7yECmH}_u;$ForZ;v6JCrI_OEYWb=Stw z73Bs&EUQq1SfPH=S<;z(m@&A7en)l3kDZyGIaf`X4VyX$Ri0 z(%L$H^7Fay`L6Ep8YJ1fEY#nCfT{M)R24$qA2OXh z!O;G4US%1a42ZE9JTMrsad8fm=OVFCvdx#F*E&qTHtlb+2)gvY$s*L=lxe};3_D$) z(xq~`2cp*yTZt9Mm^&P2ib9pLZ9e(5kgOFg3Ch7-eX&y01pX7oCq{cvHgGVI9{$3V zfWB^P@jsB|Og=1i>=si;8UdgzrEC#mG$LatTQtNi0K5_er^act2;!2 z*lf_S4-h6M(L6vj)dQFWQnrC6hl!V0E^Vnkl$;^G;(&VySs_{yvT6o;LIH?6>k^l8 zVv5u8Ex@?p6MeQ$aD2QdwIBiWhGV3{*C@0|Bq_%cJMn`xVbqpz$OEA$+l- zkOC2p0A<~TALV{TVEY|3Ph~JfnDiR~b98;>>Apb`FqgS;3P>BmQT}4Qv7JOTBIy8S zWnpbSpI-PI)unM7G{YOf;*?X_3Qlth!`0Ol4itw`(L3PqMlL{+fN%oiwB0yikgc0| zda7a~#sI^_fRIA=*spEi9$n&1v zu+!@vK@$&E?DTBg0>LP0JyC3f++C9|gmOZP;v*`Ki=Y!23}i%rFiWu((FifZT0}0L zewl)XD?7Qwq2U27Q#oMq$^Hl4n9KxFR=mSnOasMdY`i`YYq8b$+j=?)8`3SXEEvZj zIv{--2}z(Z-|k?9^NNm5cvdAQIv{JLXa*=Fwi9S^B_^ma1~}2tu@g0ug$F&S24f9% zb>bmPkx+-CqGvF`Z2&0ZL>B~UNLWj?fW>**3u+E1LzRn%1Zg2cMl-n(p<#fbEBvL7 zBU`5OnrbU1Yqvh4o6!7q`gr=lxUWc-Kxg{CE+q;vhX-~OINDh6p%#DXRt=03{ry4Ac%3uvj(^s%Ru)ln}x;2oh#4 z2Ara1(YhhyAY|3N^ks?WVC}9&+X=>9@WZMMQ@)=rX|{TG85sux$&g*K!Uo&6p@Hr| zE z`Z(=*?#2>y5T$d{^3yr0O3M$uQ~kxq1`nmg#GJ&!X}=VuYq)hQRb8fZW*ipGA%0q3FX0bPUG0;W;Md7pwcn~<#4GxBQq2KgN^=T`}VgkJ@Z&sLxqd@ z^c%Vs3iIIDATgM!>AK2OBOKaA{$Dfn9QQl&daqc4yp8ZmdeX+sX#LQPg{Z96{U@}s zOFLrpAYx>cgz=?r&oofAhBeecx%! z?8}}$jqpDhD#3;(k&rbSe2`Bt)pyNMvMZb>r8DL1D_A8IE(_0YHezM*G0s@oq%Iz2 zTXVbK{NE$9t-9yAed-HLTz16~&~kN8Y47g`5dSS-E{Z&?0y)_8La)7)2BXawKmybO ziC8#hVy*(OzlT>vBl2$FHbQS49HGq(LF-MM0%0a4gAd<$V4e{ottL%w*y$aml&@pTH={%2Bf}PV~{JFJww&ky1(dWKR zi;p~z<1w2%Oi779bY7kIhE(&5?X_y!;ca2b=X&h-?F>KDZVwnaz{Yx_2Cb+Fpev35 zZmH~rIFR-v_=98=@o2X2YwkR$0IPp&9W*Wa8`jFg+?6s7NL4Pr@I|+Qw4C9I%Pcn9 zvV#D4*5oJrMC-fnmo}YKwn0S=VUJ8-1;2^q*t|8@plfVe(ZtwCud&x5y|0lSB%Out zIS`TAn5`VYd`YV?awyn9;hg4Et1ZdF4Mr-D3Xe+Oh?*18pR?rEtA_p8aT@YkUA z%6y&!LnkhTnw%eu)vGnEo^b1WbGmA(^twtjy=y@Q1xL=mM=+wh8u$hcQ=_1nMk|}- zJdZr(%kv9L@6Oy_`}B5xuD4?NcQ1bLp=s!dHlE3I8vABKeeHl4RVAFSNJ(TCFaDHa za%nx3gNP=Rr2FX4tU7$XS(^LQ*DT6>=GCCO*=u%symn$j=b582?1z`{cU$}=z1n8( zAKPR#0h}@wrD9yEX=@^Ng~Tc@#^rA9xv@yGv^&DiV3Wo1m<1bLDit?aVGogj8Xh13 z{VqN`#9@IQ4iLi;Cz4t5_5;u#U_OAhWlx5lKelEOy2rv}?|Z+My?my&@oQY+VAbpV zA_v)ZLvz(V#)Q|(L?_{hQDcM0kDHgrstpd}wnYgBb!lEFlUHrEIKB2J??pLT3cV;+OIXXe*3i_3jV*dGVd@3 z96b65dB<}Oe%*0@)}S;%p5C?+Jv@U$gI$mPi{57JfnJr`WQf|`XMq^E9{s4eujL2t z2D|)e!x;w8)LdU}w4PAs6)S(=KJHy5i=RC)s56=DS90VXY}18X8&9pHb6M?!+ZMHn z|9oUu+CN4f0!VLNV?CBTp@~2V5Xu>B>ZvF(QsvYZB4a`?&~VeHSoi0>2!q&8Q~VbA za@Jh`67g@RLx=2}SKoz5A%JDDyjml4E84S6HY;muR*awXqwxLDoXc4&izO0?JL6}I8YTTl;e4fTc_<; z&hy$Ept_E9GELXqc3UvM9HL!`&u@$sXWTs@C-@ANZ1nj!?y8r+`m82i{C*W=WOqNZ zUbf!VZ=IOg!Po>FG{CRa_U!+%NI^jbLV>ijG<(3ei~Z}s|4dd~fQ!!5h`0@9k9+(Z z_0{%4s3z?g9-aHf9R;}b?rrRAy0(-oVW zjzm_ow9`^XI0dB|uLl8-Da-sR6PV5Y0P0v-(Y;N>22j3uxA}>YsS1&-Zua8|O3%^O zm7Kl&zzMIYgubCSc0buJIqV!B+Mtk`?Xkz@xv1z&KLNp8Tqs`ys(Ti&7T{#za3`}Z zJM}2tuZrm}wHHp6b7;y_5a!XytO>Ky%-ddKk)Jc+NFCz~7b3p>af6Ze5(V)g#<{(7-3w%Km~#KGNC$qt`??JQpU3gFe~wYCnZHQ{LCjb_`6 zO$dtY8^WJJ7&rVe?j)}mo;*XnjTko6~n*MaLfSB0TL!5-8GcN2a zxC@THes&)}Fj zySc?^aYl=t5l&gWyM0dwcjt1ckE-+>QoWoj7tC$=F!KHrF2!(_OMHirpuNl6g4(+5 z9c?!yZuRkmRPH>R>mAgYrMo2eBMbOcsOY+VntR?HP&DpK+rl@_uO{2mDP-@m->#=q zy7KEPCkrLXpbgnJGaXxMVXea<#&NL+gGAGHMbm_~O^u5ZS$oH!ahy{bk1IH zWP9(dq$Y*1XsfBhVj>`_N_KoRuSq~5*1;;*94}Ve+cv}Rq5n)RF|*AY-&b8ts7ftq z<2!B|*idnEQJu3(9SP?LJO*}HClyi&0{NF+Wb9>Z<~@C zIED(}FNAH))B7EnKK5`_PsL?Fufo*{AK#uu!tRM{s@B~3j^6~Zu(Z4szt}h_2u7OR z7j_kRtpg}-Nda+4hjd>n zi}}|AH!ltXP0@Ude~%y?E~vacKQ)M7E*Q4bZF-bh(RN+x>`~7t$SCl>e10OLO^P)I zd_tDXB3frgx>f;c!uFT1@w+&9v(d@K|HzKqxmr>Mca=(6VG72JK+wl~NT1i#QtkT@ zYCJhf)*l=8s3=>OV5PgE>Y1?h+lj)x4~lQ!GoSJ6^H-g;SCc6YD9s zzp&&uo25OTXv9{FAm&x`tSw*TKBUHYo&Sl8MCP9RN3;IQ_8tKL) z^qq$G1b~|q&a62tG5*VGRQ%EUVi<5;Sus`+x>axojIqs4OgJ?U-Wk2G%ng@s~!F( z_F+rZif=Cjx~|NXarfhZTvG?-G50<&>LcwZLrryZ=3t%9ICj797V}N>ZLSI(9r%^k zxA$C%e~iW<{`JsaGt*0Nc$AbMt?Vl^g>ao4-T9*@Q=-x@cPiSm=98C_-*(%9{5uj# ztu+_-?rW9liMEb^xA7CZi|`^1v@Qd5gx7cVjl;ne&DHEx9g!?FS6xll8Z%I-#E^xl__Ez(Vd>JT%7~O3 zPd&IBL!`_#JZFxobKx;{8ntYO^Guz3jJEw1gy}2MNaLd%5o{6`X zkGda~_;HI5{EUuqX9F;>(%5HKt50Xd$~9(bTc`%eL9GEITU?Jbxc%r0wO)x?6|eG8 zd`a0iT$ysm^TOg&vN6_^1=!Mh^CZ97BJ)n=eEoEs3NR#mz6VZASfQ@m>F6jRd5i1A z-TI3M_i@R6tX-1lbv)HcYx1yHYmAfk^W?kydXN0$qKM2vLG|I@&@J!<8y{}NZ<<7x z>Tz4tKs?wm9Yb5HdsanC8WO!uB?^lf;6m)OGqH(1%HS+4*Vgz z{F58fkh-IPoB9WZq5lq+MN>3-CH2CX%oj_F^gt9Cr#awW0T59A`}>ta)U2WZo0<{E z#u9&jzp{cF13(34Apqc?8PwkU|3AhZiT=NO!$$QypMCtX=FY-?2L4%XvcdSeq5X;f E0UiHjHvj+t diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 34a99a707..d045204c2 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -81,9 +81,6 @@ In case you are wondering how the visualization figure was done, here's the code import igraph as ig import matplotlib.pyplot as plt - import igraph as ig - import matplotlib.pyplot as plt - # Construct the graph g = ig.Graph( 6, @@ -91,12 +88,12 @@ In case you are wondering how the visualization figure was done, here's the code ) g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - # Get the shortest paths along edges + # Get a shortest path along edges results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] - # Plot the graph + # Plot graph g.es['width'] = 0.5 - g.es[results[0]]['width'] = 2 + g.es[results[0]]['width'] = 2.5 fig, ax = plt.subplots() ig.plot( @@ -106,5 +103,8 @@ In case you are wondering how the visualization figure was done, here's the code vertex_color='steelblue', vertex_label=range(g.vcount()), edge_width=g.es['width'], - edge_label=g.es["weight"] + edge_label=g.es["weight"], + edge_color='#666', + edge_align_label=True, + edge_background='white' ) From 5f48a5c2adda405b920f6d1548d617324a585d03 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 13:48:54 +1100 Subject: [PATCH 0791/1892] Update tutorial to use `ig.rescale()` --- .../betweenness/assets/betweenness.py | 27 ++++++---------- .../tutorials/betweenness/betweenness.rst | 29 ++++++++---------- .../betweenness/figures/betweenness.png | Bin 380066 -> 371944 bytes 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py index af8c749ad..f8409704c 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -8,18 +8,10 @@ g = ig.Graph.Barabasi(n=200, m=2) # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 -vertex_betweenness = g.betweenness() -vertex_betweenness = [math.pow(i, 1/3) for i in vertex_betweenness] # scale values so transition is smoother -min_vertex_betweenness = min(vertex_betweenness) -max_vertex_betweenness = max(vertex_betweenness) -vertex_betweenness = [(i - min_vertex_betweenness) / (max_vertex_betweenness - min_vertex_betweenness) for i in vertex_betweenness] - -# Calculate edge betweenness and scale it to be between 0.0 and 1.0 -edge_betweenness = g.edge_betweenness() -edge_betweenness = [math.pow(i, 1/2) for i in edge_betweenness] # scale values so transition is smoother -min_edge_betweenness = min(edge_betweenness) -max_edge_betweenness = max(edge_betweenness) -edge_betweenness = [(i - min_edge_betweenness) / (max_edge_betweenness - min_edge_betweenness) for i in edge_betweenness] +vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/3)) +edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/2)) # Plot the graph fig, ax = plt.subplots() @@ -28,12 +20,13 @@ target=ax, layout="fruchterman_reingold", palette=ig.GradientPalette("white", "midnightblue"), - vertex_color=[int(betweenness * 255) for betweenness in vertex_betweenness], # colors are integers between 0 and 255 - edge_color=[int(betweenness * 255) for betweenness in edge_betweenness], - vertex_size=[betweenness*0.5+0.1 for betweenness in vertex_betweenness], # vertex_size is between 0.1 and 0.6 - edge_width=[betweenness*0.5+0.5 for betweenness in edge_betweenness], # edge_width is between 0.5 and 1 + vertex_color=list(map(int, + ig.rescale(vertex_betweenness, (0, 255), clamp=True))), + edge_color=list(map(int, + ig.rescale(edge_betweenness, (0, 255), clamp=True))), + vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), + edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), vertex_frame_width=0.2, ) plt.show() -# fig.savefig("../figures/betweenness.png", dpi=200) diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index 0edc7fd36..63a8b48fd 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -25,18 +25,10 @@ This example will demonstrate how to visualize both vertex and edge betweenness g = ig.Graph.Barabasi(n=200, m=2) # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = g.betweenness() - vertex_betweenness = [math.pow(i, 1/3) for i in vertex_betweenness] - min_vertex_betweenness = min(vertex_betweenness) - max_vertex_betweenness = max(vertex_betweenness) - vertex_betweenness = [(i - min_vertex_betweenness) / (max_vertex_betweenness - min_vertex_betweenness) for i in vertex_betweenness] - - # Calculate edge betweenness and scale it to be between 0.0 and 1.0 - edge_betweenness = g.edge_betweenness() - edge_betweenness = [math.pow(i, 1/2) for i in edge_betweenness] - min_edge_betweenness = min(edge_betweenness) - max_edge_betweenness = max(edge_betweenness) - edge_betweenness = [(i - min_edge_betweenness) / (max_edge_betweenness - min_edge_betweenness) for i in edge_betweenness] + vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/3)) + edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/2)) # Plot the graph fig, ax = plt.subplots() @@ -44,15 +36,18 @@ This example will demonstrate how to visualize both vertex and edge betweenness g, target=ax, layout="fruchterman_reingold", - palette=ig.GradientPalette("white", "midnightblue"), # define a new color palette - vertex_color=[int(betweenness * 255) for betweenness in vertex_betweenness], # colors are integers between 0 and 255 - edge_color=[int(betweenness * 255) for betweenness in edge_betweenness], - vertex_size=[betweenness*0.5+0.1 for betweenness in vertex_betweenness], # vertex_size is between 0.1 and 0.6 - edge_width=[betweenness*0.5+0.5 for betweenness in edge_betweenness], # edge_width is between 0.5 and 1 + palette=ig.GradientPalette("white", "midnightblue"), + vertex_color=list(map(int, + ig.rescale(vertex_betweenness, (0, 255), clamp=True))), + edge_color=list(map(int, + ig.rescale(edge_betweenness, (0, 255), clamp=True))), + vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), + edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), vertex_frame_width=0.2, ) plt.show() + Note that we scale the betweennesses for the vertices and edges by the cube root and square root respectively. The choice of scaling is arbitrary, but is used to give a smoother, more linear transition in the sizes and colors of nodes and edges. The final output graph is here: .. figure:: ./figures/betweenness.png diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png index 1d61677bcda8f5b94013038b2cbe2c016dba5779..a10c9fb2ec89bb70f46710e49067cad68e7fb3f9 100644 GIT binary patch literal 371944 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
    $%kJYVUUr}+CqEp>kRXmIFGff{ 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%0DkK!~jVz__6-z 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 |sTa=1G+5S8`tl&oU0%vH)XZ{(9eu!j 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 z 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 literal 380066 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
  • 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 z%0D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 z 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 L<60z5yWsx?ZXCTT From a75ede3727812f6125f1c3f6c7db36a2203edd19 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sat, 18 Dec 2021 14:06:08 +1100 Subject: [PATCH 0792/1892] Added Krackhardt Kite example --- .../betweenness/assets/betweenness.py | 50 ++++++++------- .../tutorials/betweenness/betweenness.rst | 60 ++++++++++-------- .../betweenness/figures/betweenness.png | Bin 371944 -> 167428 bytes 3 files changed, 62 insertions(+), 48 deletions(-) diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py index f8409704c..8ede3ec46 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -3,30 +3,36 @@ import math import random -# Generate graph -random.seed(1) -g = ig.Graph.Barabasi(n=200, m=2) +def plot_betweenness(g, ax): + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 + vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/3)) + edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/2)) + + ig.plot( + g, + target=ax, + layout="fruchterman_reingold", + palette=ig.GradientPalette("white", "midnightblue"), + vertex_color=list(map(int, + ig.rescale(vertex_betweenness, (0, 255), clamp=True))), + edge_color=list(map(int, + ig.rescale(edge_betweenness, (0, 255), clamp=True))), + vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), + edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), + vertex_frame_width=0.2, + ) -# Calculate vertex betweenness and scale it to be between 0.0 and 1.0 -vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/3)) -edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/2)) +# Generate Krackhardt Kite Graphs and Barabasi graphs +random.seed(1) +g1 = ig.Graph.Famous("Krackhardt_Kite") +g2 = ig.Graph.Barabasi(n=200, m=2) # Plot the graph -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - layout="fruchterman_reingold", - palette=ig.GradientPalette("white", "midnightblue"), - vertex_color=list(map(int, - ig.rescale(vertex_betweenness, (0, 255), clamp=True))), - edge_color=list(map(int, - ig.rescale(edge_betweenness, (0, 255), clamp=True))), - vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), - edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), - vertex_frame_width=0.2, -) +fig, axs = plt.subplots(2, 1) +plot_betweenness(g1, axs[0]) +plot_betweenness(g2, axs[1]) + plt.show() diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index 63a8b48fd..a4c686fe7 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -11,7 +11,7 @@ Visualizing Betweenness .. _edge_betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#edge_betweenness .. |edge_betweenness| replace:: :meth:`edge_betweenness` -This example will demonstrate how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively. +This example will demonstrate how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Barabási-Albert `_ random graph. .. code-block:: python @@ -20,39 +20,47 @@ This example will demonstrate how to visualize both vertex and edge betweenness import math import random - # Generate graph - random.seed(1) - g = ig.Graph.Barabasi(n=200, m=2) + def plot_betweenness(g, ax): + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 + vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/3)) + edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, + scale=lambda x : math.pow(x, 1/2)) + + ig.plot( + g, + target=ax, + layout="fruchterman_reingold", + palette=ig.GradientPalette("white", "midnightblue"), + vertex_color=list(map(int, + ig.rescale(vertex_betweenness, (0, 255), clamp=True))), + edge_color=list(map(int, + ig.rescale(edge_betweenness, (0, 255), clamp=True))), + vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), + edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), + vertex_frame_width=0.2, + ) - # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/3)) - edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/2)) + # Generate Krackhardt Kite Graphs and Barabasi graphs + random.seed(1) + g1 = ig.Graph.Famous("Krackhardt_Kite") + g2 = ig.Graph.Barabasi(n=200, m=2) # Plot the graph - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout="fruchterman_reingold", - palette=ig.GradientPalette("white", "midnightblue"), - vertex_color=list(map(int, - ig.rescale(vertex_betweenness, (0, 255), clamp=True))), - edge_color=list(map(int, - ig.rescale(edge_betweenness, (0, 255), clamp=True))), - vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), - edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), - vertex_frame_width=0.2, - ) - plt.show() + fig, axs = plt.subplots(2, 1) + plot_betweenness(g1, axs[0]) + plot_betweenness(g2, axs[1]) + plt.show() -Note that we scale the betweennesses for the vertices and edges by the cube root and square root respectively. The choice of scaling is arbitrary, but is used to give a smoother, more linear transition in the sizes and colors of nodes and edges. The final output graph is here: +.. _rescale: https://igraph.org/python/doc/api/igraph.utils.html#rescale +.. |rescale| replace:: :meth:`rescale` + +Here we use |rescale|_ as a great way to linearly scale all data into ranges we can work with. Note that we scale the betweennesses for the vertices and edges by the cube root and square root respectively. The choice of scaling is arbitrary, but is used to give a smoother, more linear transition in the sizes and colors of nodes and edges. The final output graphs are as follows: .. figure:: ./figures/betweenness.png :alt: A graph visualizing the betweenness of each vertex and edge. :align: center - A graph visualizing edge betweenness. White indicates a low betweenness centrality, whereas dark blue indicates a high betweenness centrality. + A graph visualizing edge betweenness in a Krackhardt Kite graph (left) and a 200 node Barabási-Albert graph (right). White indicates a low betweenness centrality, whereas dark blue indicates a high betweenness centrality. diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png index a10c9fb2ec89bb70f46710e49067cad68e7fb3f9..10e4375c5a7bf525c059c2c9e087c39f5d19e5a9 100644 GIT binary patch literal 167428 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
  • `N>>h^2d*>pcI_#+l>rrqB^*$E-y)In$OUYb9X%X zzRBUkMW|ZXFajie2oLx(l%Vn@gSiZ>eB$R%*|V)%R+gu#Y-8efoajln=h{T4phTXV zTifI_PqOk8nKZ~s;290wzQ*W0Ms?%v{LDzaG{x>mV!WmHLbx(#-rohOnyA};XkcIf zSb%=lu3bPMbsZh16S1!Q?8*69UW6yh?DaB#A>lkPVN_LFvMaW?zaj39nVH#Hey19U94V3O61>$1Z z0?K(!_mO>id^{LJO`7Y_8y*GcEg(g*mw%likPV}ej!KD=W)Wk_p(s7sv5A|gmqmK@Pt9$CFx&h@b_DHAMrs&bi$pzSz= zoA#U!!6_wa`1-2+`1B;|ndg<|(Hbr1(IL7W3pG5y-p1$}d!AF=X7P~Yldm!bwHEpG z%7G0ltE+7f4hgKF^AggM+Uo3KugjNf08f=KO^`?cuXY_d#%DWnSWoTTh`le$V_~Tf zl96HAb>>|)3V9o}r^2RKH8;0(b!m$ei(MZMFYYrn;2FJB-_&FWR!LCu^Pe8mYH4ZB zj(0L!T3V6<(SS1{ipa?Mmlv?Ivj=BKaStv!Ik@!N?f7xR|4P8i1;5#fH@D=pdVZw# z4QD^nIH5$UZf|Ep!>xsu)HgB`4hGvFF5pihq1;i+%F32p`nicq+Va};^t9mO<}JBi zOS9XT7N%kVQmy-ILv3R+)$i_Rjqdo^7{eX?CGsj6g=!o?XC1EO$rp}oE4|bGb%p0X zh?1&-1Nw)DZdH8q`QesC)I{@!!qI&X-@nt#df?=E@0huqW#*2yiN=)~}EGtStc zwmh-xrSBg$5(@`Mi2v#mAst=cEWaPE{@0%)H#@SigjfgNg9jTRFI;v@9*{fR`t{@^ zQ4z4Y^`n0xuCgi58eF?}t-y22(tWg*Y>&gIkn(b6>><6KogG10TwGkHD9@o)noJiU~?#)YsSd^6{~o z=qiNDs+Fqd$Fg~I)ZSpKiiK|6hr!eU)mEQgiD!%6Ta*lVulpDqf3Ccknp&y#o0Y;^ z_58MnM<0iHe5j;W%gy+c>j#~AdS<2u@Fq4TWiF@UP^#KCt4ftk@)xh&*=3(`?!*0U zCtp~XH^)9BG%2kxhP}XOGd-T)B2}3_=1EQnKag`1WntO!MM2oF+f0-j7i0#t&hA?! zbJ7IYDsMzdTrs!Y?hRj_kq+=czogh@-&_v?jfIml^uTTLbesxQx6$@&`giZ%O)t$k zB;LC>2+3u%t57J=Rp}R%YKoyaltQAQCU1%!D$y4<_Mf4tDCoJop*!GL|Hv&FuG*KiO$qOu zdSB*#u2bEzg#;u%KR7@X$xsVFg!tf?UGB)UhaeUPDN0K!!4BB*=2E|*Ne~mwYH3`Yv)F#p^gNZhIdQT= zgDg8>w=i&8pGwSUY0f5;VCxey}Cr8Z)lcqwdDW7Svlt*f5dq-@gwyT?586y*Ois-bK_% z!XY?j+p(>eeAvge|S5Lv+L z9QTV0U#XaxnRj38Hk)wSR?NTDE|$k_3fbi+Db#=O$58+c=n!x}H+MqE(&go*!R#sNh z{t2?$Iy!Z=wVEHwJtw>GRFud2tgR?IIyxFXKYt_%t>f#3E7_Xu*a=VD&59;o=4H&P-_Hojd$4n15^dxC3s0x7FC=|DC7+&c6C}7d09^z81@UPd2=3X<@b~bFV=Q zA(&^Bs$t=cm7C>X-rozn&N%(!_Vmn;kF|ask-tEr1nPS&d}H`kuRMRghj5I9bfQP! zGavS5A0-ty2~2-HRy)Wh68PZ(nU4=HY;v8(19Rf3P;$~t#R)|l`*utG2pyPTn1N{U zqenX){<_Z|D!ykACva$q+Xz#0s(K8{U6iUxVcR1O>JUczcxi6_&d1xk>$6Qnh!3r0 zN_KsZ3(UmCbliIZrFC%VZ36xqgl{21LCpyl5gULT8d};KG@3c_cXREvp@Es1(~C6} z)~{H$2x;L&JdkPK{_RI+ehdm>Kl*pX)vH$?JP><$^vTuKfVGW8<3g2@^;>cW|9R;d z;JH)+{lWInuOYLir)VLvieZsE4%{MLn%wZvlvPd5_505Y$0A*W^e0V6+1S|$-VYyh ztOut!Dce)pqU>3h-TCLRmTCdH@$`+jzQP_KZg;nri+Ju)S5MRD?jP;0CQZ+fDS5E@ zh_}P`7B~6PYvIR!=UqiPC@WUItGr4GXd4f%tE*f6xyau5#YB@+(T;uIn?YGmLF%iu zqo+?lly6Kt1bS1Xr){wwHo&euX@crNM?6o(GW4Cf zJkKhamAt&XGN)d#5U>l1n^J|E<}rGD_GaHhdaP;yn_YtO+crZ#P`cyei7FToL6dm* z?wQiwimOWo){zlWQNh=*GrqaCJs89Z|Iby`o1;9V>%T`*tL4AZ#Js)5da?9NS`c9K zQQNe*Pv!orWy4uzaK1=^!NC;Zs;73|XaZ3)-ndjx%JeQjA<{8-+#Qn!&aV?7iU6dq4K z*MAm&D{%Uz=Ga{lYhySC!E0@8^Vx2*#l?1!{)prz+gT?5^tk3Xxt^XL9-#)JA0m5+ zHUbo%xbrj}lvPLoCqi{br%Em{p6%J>^?U!~Vrl@%)00?8C@^}uhYq#4R`?7P%US+n zZW1N7;OSG%)up-qkr8UZr9z!{afVsPi7qk*-fb#U$Js!v9zRCMc}7K%EUed4{wUv* zx_5pOY9ZrhIS!A?*;#iub(C=GYH*{BE4)37N80u?%<>u}k{%xyQpr2Xt>DSD&B_ur zQ5h&ze5>SjYP-(@)< zu4Q*}ggjJ@N?lK1lBXCT-Vmd3SFfMhZ5>_?2Q{n-+%L}c(GKi zE$#4MojazWsL1(eIkx_m1T82oq#1!79Mw-xqbi=jwaY3-S;R??jg8&cTTWOy(86GN z@!=ORF#g%)VOa8gjWwK^LQ1N(tu&U^c}1Z$J-F*|Yy>3Tb@q)LX|ql4WD_Oz$*}jr zmHElnuU|X6yKCbsqKO%&YlhbHoP5eNS}J4DBok0MU2v4b9 ze&Tijc@v7*^oK+0r^kANuUz@{vHZ}Tos`_tmi53t8;4C5utcL>#$LRfB1vSa@uHIk z!keg+jO8Ah=3as7yNQrcdn;he1Gm0AJXLw&tK4IYa;`^5pIo_q{h+KbWfu3fYax8! z)&6KNc73x_I4@R#>YkzUD%W!gcnjy++}yl(yeHqX;wk{b;G_J?+WQCZp}}uypDhd3 zpS;Y%L!+Qrp{jIDJoIb+O-pzuoEoQ2Wr=nN2M3eA{Mj?)swg2T*;eM^z_W2<|GPW8 zAPll!w(Y6WXvyT<5xD(uNYl_;ivE6$WTlK~?S`lzLsQ)pH9tBhCns3+yvmmtA|oTW z9lp;1fvLb{a6iF#_CpSg$=$^>dO6F44E^3`o<`v0NqU{h>;sX?+?<;)jcSK}@9FiM z9c_z!Bm;g8kGi&}hmV?xSHspeqigVH2M-S^B}HR(skW)Vzq6JKVuJ8r7m@bgDQitwBMgNq3xJIo|EBqoL#tI>+Wd$8o| z*RSJ0FS;_!l5g5WH$Bb5FYibLH|+GA2xWH8?W-#ZS8^gG%nC@T`3=}X^-aSh0$yC> zRb;~nZ%I{e0*LDG>m#A+KD+Rh3%AC8%J5IodCt~{x2F|$nv{4d#e5UKPV9@XpP#IK zGcPug8b|8=?-96;n{e$@Qc}EreW&&D6z4g7IQ@|HF~h~KxAbNeC%W(C=(@a4&S6pU zU1Wj6PyneCOo(pv*E1Ag?C-YQ2MC>_x_XQLl% z0Q9_yQj-%15v3pG9=BacMTPhFj$=~o3x^jbe~kBJe<|P9O5b*EV|9CW?ck<85Sh)) zh!s%kS`ClgB=g5mb1`(Z?taZ~OZCj3%a>&YZbF){~i$;SB8q$OkF`kYp$d-xg8P`&}bK zk~WSE6Wz3?PsDvE1}Rp4MV0I_P9MCfY^+AKPZ(iDs^!vTcdm!Lh4J4ivvuoMrOtA< z*A+BL3S{m-Hk>*|qx_ank=%VuaNg8ZmvD)0+_-^t__9S&aU*C5*w*7NAwQ!_6+Uoz zaVDR=@U&0kjt!*`nyTXFKlTu=!XAgKczU{@OH88eWavuYAhcZUeHjUzz`-w(VrpR$ zffp?z0#Q+(oh`Ee`X)-;xcNyFc{kD4%<$>Ozee#Ek$u=gBjhN4y@LL=S^i@Ew}AEQ zgs!h@m~!XNopk$_6u>3y=>U>QNL8GklJY>qZoIDX^Gj{h)~&V2r?Ye%S$SzZNa(t+%q`crvoxj=n+x;~y%-m;6!PSz7<{e`8a zEWa2xV6JS5Hf&#dF!j-nn zpsiXVP5D+7z{*a&I7dU9VYzXGlTraY0MTW@2!^FH(NVDsUcm~Y3Xi3tvpit#1BzE#-qW9K*tV0c;5lb>JDJUP|Jk!H_8BUOIr?dsnsPjT{J6EiMr(0tsTMZb zMC`K@rlz-sy*;h0tPrvxvMqPxe*9|3b%^@hoLn79R%^%3zGWLtK_RQB=o@w%Y9{!F zt)*`ENJ{oW@yt2;QLeY-F6UtS?n@yiQj4h}ZliX^jVx?L90&-f{lNBKaYg1{q)I1=2#b3ObcChVM? zw}-qJzJEWp`&|15kZQ9ke^pde=%YL46PJcYjp6Bp7WFVPlBug#zt)?`9Tmc5yF)A^ z${W&6WhB9(XM%o(ICc0dP2o3*yF**c%t zemg~qH(Nki)VDi5*g30thw3w~PPWK3dl2)*@%*akCV>E%ch3W3V_8YoFu_XvSC#V2 zORoUI4+3`bsQD@o%md(=w`z5MGw%HMU(eW1o!a2oL)VeB)z|k2$8;StfQ~@Dkh>rW z9#mLGg(`|!Fltye0PRHVY;U;X)qi#MV@0|5u6yVkzq`Y0*?1**lOJT$0xJa?0BYQl zB+S~yMK2j&jk{0JbJ#=wFazVr7X34HLAD+>y&ZGI3j3B$O!b~;FSOPC&|L5k9<^Af#K9?Yy64<{E55uy6=ptn!Acs zaI&!x0R?Mh6wL~4L%RlBmFax!?o4CnY5n*f!A3PoA$@ zXEHlZ8{^bX+8@pFB2vT{J$v>|pzl!t@a3fLFs+w+_`f!bad_AZqQ7kl7|6MmfOLsLD(Et)*PkwtOS$2fGb$R+2RL!_DIU^dp3ewU=kj`kFqkicD+ zL^sjXyNceixVAhs(^o^muvtz*f65=xk-{d)6ICnZzH6n^i~U;2j`cT6nNIMG3STb2 z^s|<54}AZ)LfP9t;i7Ac%v$TSbBBEa8x-7z8DR5WLjtq*-8%+km1^x%{lZ|y*dR(t z!^pUA|NgKpA#N!bkpmQOiQjrNRLx#g9JTHlIjYA>BbF;!I`Rof+humt zm|z27aMG491GBSF$B*~u$4hLVPZZ$dXL@#lURaD?V5*C3c1jvw2+^gRY@0XJu_`dh= zwE6VkfZLyvIQfDBT%#Hl0*k4L(AZf>N%6geoG!CxPXiz+5&!)8qlb|pPzn8W z*5?vfCQKn%Wc^N2xlB$t&uDps^9=gpBP_mwVRi++vX+KM;F)ulJ>~Yj_LW^e3l`-e z`dy^z`VBM;9GWR~oD|9KCr+H$q~!4<1dC2!?2jE^58Z6GOXE%|^E{Sn%FV?kYB{y` zvltp4S>K04p}YE@&xNS*H83T+fB8=!3~~548^c*90@vuMmG@Tci{fhdP%eG^7s@n< z{>6*6a)qX6@m-4$^d<}@`~hM`QKYlxz!hcByyGD#^si{C1Vq63O=gAo49v8x+gURNyU_;}8> zuRtxkn&+v0iDC515rwZktt``Xl$DDa&Xy-zkiHrDuht(GRYxdd2zC|fWC&JkaEHUW zgfh5C>|?Ia0y@FjNw#Bsy{jXsL8<<1{K(X-t&ygRjjU0}6zv+X)u8dSqGuq=01t$d zm8$HL7rG5nge06Jb#?VDgk%uZ0#t+C`>RqjK9dLsW4YOk(_DnrT(32Dx7soDTRhcy2*~W>T@CNUhoScLnTZ@lHV(na^ zj^NEKbb&$O-V*OQaTMNgsORj+{w$A1$RCwn7rrj65aKMyBt@3Dn zdRl)4R<;+yUBka^<4k6DZ(V*nc;5FDsYa)Qj5IbjR&sep<=xvO8eMS-rAsFe`XZ9S z7;qT=@y7&W)sy1$AH^rWJg46*=LpSVu7N*XSDFYwfY>xawjv{e2trZ~1dLT%UvVS6 zv_R+YH{rq4CgQ}MLq#W&f<#P+RQ>In0Jzg=Z-p|x2Q`9? zSkjSTs}WRhf^y-P*nWO`niL{HMPOG%Pl>Y&H0>9(t`G$^zz{zYtNpPO~ zafGA+2(GqHg{(~SvrqUeA|c-O`Lhjvil|JUJ5zV@!9*pfF24LL{N-AE5<)sLlHxo6 z+1?Al(kFj#aF7B-dga$!X;L64Ro|PQWdXl+ISX?ZFSE#d3DVZ@UKW?Xq1><`1JT}X zM;>y(;S2?55|of&7Di1iAZx3I0F?73w8UnLsyK& z!}!?PAViw`@P~+5AAS|DKv%9KYD;VL$>lavW$LZZo@>Rk+w4+vb~$R|61M+KEJh*2H261t%_~^(8^Fr| zvq>1AAZ;-}m$7Eq4Jw;r`A9!O%Ix|1+rxthVWoxiH|3jdKbg)JW|(|EkD}-4iht3k z`L1$L>6>wJtk?pKI@L8dOC8!pR_if0JUk3NL;_1h0}4#ifX2FW=T2ht2;hof+pFIW zQG}-JL4-R9Lk1Uqm(rz)ZSxA+-h|zA_TxiNBvq}?pTCL;k#lm+cV+FU2$=$QUIu)y z%icW#0V}MS(a?lp3=5nP^(6j$5IUAR-tANEQ`K2{UDaf1{^NuRHe3aApT&oTk)z;i zZJ7BWE-Mao7)~@4=_u`sI06E+rI9`J>5~s zixNVND6Q=iQl3CRN$LUod(L+R9>~7Zl5CF(pEA|#g`iuvIEc9}$VDGinvkYo6u&#@>)zYECI9@HyFR7&TrL*FD? zKG0H*Y3@xRIAbYbLh~|rT5w<7TmnmjbrQ8n!lI00=N$$-m;co7AGf5hcWysd!n!Pa zZ0c}jmh6dR(pDvP`ZPENwXn?!QTHBORw!AC6|)%6m`n}jRfaF2S{dIr*yxKG)Z+YC zC&2jy^PfY#FAp3~yvNi3<#(sT~;fg~FC^6LppP$E;f z?R#NB86oKS_+)Xkyv5e`oquED1B)|*ch!7rLue5=fLPhwxo|;KlblP+Jc2j^;J7j} zG8!JgO>!=#eCTzVm1S^eyZ)cN=E9@}W|V6GdfpMUDgOZs`eR7vAuvEBv!NML`lr&e zi&|q=gh$1z;LPt$;yhGJk!R3zyPlq=e{r$rDynOQDpPFl0mJ~YBYVW2_msL(^cPeMuIol)>{EO>^z?v-XKsBCA z)_e9W1E12fRx7Jij3S9&B9JsZFT!ww|HS=TeN)zQNufc%&&p!q@Y3`IB{Yz-?PA%S5jb!v=92aH#xkShB`_MzZ1=40VrAT(zYZqLrn zwm}{Vmgrxv>Se@?Q^M8m|3?ZFHJ<1pyU==wK>TD~xyN`Io+$%4w+xIh?18Ed!=DZs z$6q;aP#2=s)eb20f72&ekm%^>zxeoB1#^oe8jOT_2@8U?jU%Z6Qu7MlL3~P_cm8Jx z^XTm5Eall;En=#N0G^?mkh!Y}_Yzs)g9Czo^Vs+N)755t)aq8}v2 z4aj^M<(VrMHf?3I7$#;f27tPhh&VqKW0ya_PH&*3Fy1BH#TTm<;?oq=8WP9>0>MEIEsxm={q~;|J0Ri;Sct9`G-=Y}Z%Oe4q(g zTgLUfu8Q9h2Sy$2663OPJhsZn7`d689R6Ed(28TV|4nHDo_b+_np0HY%5bw%B-1tg zuef4{<^pcKL}z%F*9S61CpFjtKBf|N2!+%(B5yLN*!cc<}-Vc<&NrDZm}H z&^%BLa#~d`|Js1^jlXfc(6m2A;iThB%Xs`SC1yiMKRk%(8XQ%v<+F;5#QQ1>U$#YU-Uf~w4 zviqANd_fG}Z9+W4Nc{GS&W)?udzEJ=mYlV;>aZ07z}&)MC29ot<6J&aqde>pl8gks%<|sJ&z%1|*O;BQyXQ3izQ=B+$jMV|B=& zv+(fb$Zxj4amiNXJyks*8k0A~v?F2K78UJUp4KG%@g!9rF2Yp|4TT(OB!`c1 zK)kdXf41<_&l7-(S5=wD3Nd0xpm!XJiMpt2oRtFCp##L+ZeakU*)YvlNzcFcbNiV=4k zVCJ*kC52ssH#Vr^*h7HEn5k&_aD6qDD9tKWh4ce)s=&b ziwb7LHGb7i0V^}%_#ACSFwM&^9dzSB+2-Tp!aro>D&^ka!Rk~SqsQ-wxW?|?9l9<5Hx{ad)uo*&$E`0QH z1cm~R@+yVsPtK-b=obnl119De+};!eR-RpQM%5?!DTZ9Y&+AYph$-N((D>KzitpXq zjLD%$+}Yn%G0`?@AAGnZPlSNR4z{Lic>CnB4OIfRum4F)KZlZZJ>5Nkq91Jc3$&Z6w_D}jlgpDzs)y(?V5 z^*_QDG3|lHMM7L0XNu5{%)lwD3WQjelL^K_k|y$ZGyAgr1(Bz&*s|{j#&_ z&U5X;7-^!!QX$*>5+!A;P1^YOe^D%3tCnRC~{|s?scB&)a%4$MZ zZv*kJ1AqbIR{clw5~M2QF9WY^j1geQZ^GO?p@gyh8z@D153~65{kIyRkNlku#`_X* zho2L_VX$$hw5j6QeCP#aS9Y;CIMD14k8t!Iyrxwj{ z2WlQ%N{*VEnr%cxPRMxcAZr=Fajq$ktnCK$DreBBu+r!^dCUm$$}T&iyb@-QM{3SI*!6~7I$$1I*0D68r1P4QD0(*KWj1S9mHbwpbCNGSPFxC$bS78Va; zR3Q4=qvdIwbz8*CiE$EzT%&iX>H?LOm4tspFf1Hy+iH!30#J(q^xg(&2MA=~aC`6g zR~FE;=KD>v{x{V&Mcz%n1K6E-WyqzUU-qUOIe&hUC?YJ3Ib6(2-v2u$4dprOn4gz_ zfmTZ@nm`>oFkTse)XVTfC4WC_*#^w2X98*BEfBoOL)1Hs+OqNSF`_cU9l#7O5;4B3 zbDe)@VRB#n&q>5T>-SP@()3%QaXJGe0(ByXMTe;1xjXsH%uGzp?cr}v?c9B~Rbzrx zFXsQ8NesWbk;1|jixURYJAh~v@>AEl26YXwxWH1o#hzPK`ST&gO!&EL2$djv6zr!E zX$uSpX@isSBf;*`Tv=sWMZTj=^We=BVN85iQHY~dqfedc3_q4@LWy}>VghT~nau*& zxx1%F7Ngp}zu(KF_6qjvxv6t2b z=nRETw|1v+Bq)RM2Ei zN!*EAPylr9*i*)N5JMt9ylhy$rqHl3TUgeKnA8HKMeOy&p?{Na3eJ5MYAWnH8q!l9yHK@;hLqiQR0Xmobyby!`93Izr8V}BwR1B(*y0DIu9N^AbQE&xGx=kUO3vAv&?ZnnFJz+_)vAOap}Bskwo zsc_aIdsE|eQ0Si(%>h$~+w9UDWC1sc0a!pVZGhT0@sc~{buY)45``9;thIpQE&BgO zbor_^I&D$&yGmSyh>?Drn@Cl|JP}dRGymR70fl?MUt6H?{~RrBXJv4g^jKTDOuQ5Z zgBp!MZw>q-nJ{GkH9q;Xtt3b;e+yis>lo59V70uJYfBD@!6L4%8}4kkQF8XzkUoJv zF~z@Ux%V?F=&lYbR1LF^E05%3y}`gesN-aCqRi(x2YeD2PjjhKQh9D7u&f`fxHgZHly$~6?|E5MJ$d``}Z=MTH=*v5phTzK!r0B$8Q zK8)Bd8survocoGDo*aG<-8J~VD|}(JjRK=wnm9k7!`V5n-~!m9%Ml7M>LSWQ7Dkg# zd`Fa?K$3VZkTRw}uF8e~?QYoqy^!RVoihYEcz7c4(gSO-)zOcS5^&q1ZNu|K2oVQw z$iQGv?Oze6VY%oNB3n=YLSMX#1LO~6(e&|emNEVCHOwNysK~_4Q}AC=_$QrbW#Zu} z0oIB4WRR)>JFbenbNf*TGW$*~DJPK_;rs9TGsJMWVB2H}4F{=qya!7M(W$Ewe!zQ@ z5)#NzT_qe&1jG^rz1Fs=Nx9lv)N(^b>RZLB2MRZ7x;O@{`hf8JPD^{ax@+rAjLp`FukUtCxh%<=M zW(?|vC;iYR1u@8<9kzDeRwj}n%YWCVlIfvAt9Z6kT;<$rn&8o@+e z}U`rJy#k^Jn@mpQvBD%R0iJefFhM*lS=*C$(u~ZJzgKQ`sGV+By&aona0N3WDGZe+2I(B3kEE zoIw@^5IPkwE5oMUH0Vj3KD;-#yiSluWw`8J38fRzJT8BMF2+0Zm1FISN4I`SadEq^ z@2@nr)T6l(;Vw=j5-`&uEFdx(KQCQf8iEWFt{F6uL`64I&<-L3X@|FIO)o4op`H>( zL6~AJlNaWvycZ^~A5vfCz?&H4tDJImb=6v<-on)_*_@F0Gxbiw4(6h#r)OsSDM%XM zL)~)L&hbtBV&3oSO@+IQ9B&|OxEc(0;)cULA|fJ$$q8O(OPD~Q`Bm#{Q6LKgEA0_E zr2i(|c9_}2JH5DZ7PeK;xD#csYLyFF1uf_feHcN(%j(A12o8sry*xYrkq$MSa!Yq@ z0c?S@#2ACYos7%L?{t=ljezw=Mk3~^%APqzZU1FxCOfw|EBk(>yjJj0xrmp}TqNh^ zA0qC23cQ`osSP~|v_y0aO_-INn;K&e#AzpNJoFBN8NF|I`JZpN`#VwE_VThDF<%c# zMM(lI;Rc5dLH8!c5^?l{kBPBG4&rvy0<;ml1eQGdf?lHKh9#6!=ikEz2_K6Pn!y2x zaQVd^B|&f%A77zAE{o*>p;{Ltb zr{!GN8>&v}B&`$Y#dq#(Z|i6#!~d##lHlY#KXJV4>sPy(fd)e6!?0pBd|Vr>>Tydu zgvo$q{`0~+G|><=BO*ns;4?4r!s%Ny?g$ynQW=!&0hGmv=;-|#8XEm8r`e42Ao}!w zb*gFzp=Fn`t|sB~M}CNk8z6`X02AKqlL3fL>7oy%eRsO3+$efTgu-1Dz zFUVv0uWO22ksJNwe)GLQ!wy;>FPGx~ zR&o8Syi>-3j}M7ZKGIa`L?R#bMHg4SqGFZ0DzBhG#(kp8*lkRo7(8WRA(fg(qZ(%* zn@S=fn?h_BY{8ZmD*@J_Iux-sbb8`QL5u;d z{|WEs{iUCzp8L7)>%Ok<^c;>zj>BPjf>wc;Epbsm5+*@evV}MBt_Pj3oujO_X?2L& z`XfjF+5L?l_xz96shyh-cNl$IRBpMo>b<%1-7UES$)-W!)oGTy*;T^f?3|P#ek4O- zHsmg6WncglC&U&URj+xHX$SVBU@<7`&((NMxsG=AGYpYQC#c;WLCYik_Ip1RKJ8rAbHxD9nm-ks>As!?zFx zhDu`3hT0biGJl|-F%i|Q7sLfxfi5Wj=oi-zM8%+V2Ei(r459*_)DQ4!SbY$7{fy>Sp6GVaT!*`8biVgOPEYi3YAMA7NVPSGi-jUPMQ>o!*C9j9ns?!8Pw zofUX~@BO_(l+VS5&l}G0>z>p}Q@%RKD*N5fxBQZ@a-;qk4-Oe3R+Nnif)qq3+gM+A z3ObkBqz3_BcA~A|0ORiX0al-r- zrl((l=L-~1Dj@IXq5}$*H=>g=V%g`m?ccQYq;i?Xk)Y?cDced4MHJ0$Q$EtUg#jOh zQ=Oi*?t6zMI-}!G)Z;2C{jsm13@bX&u3cle zf3uyZ2=hUJ78{%J9QN49;`UGy{)xeTc%Bd|Dr2Wl$HtJk+cmOPJub+SLAis#j11#bn7)@HUldLN(nr!6c zpu9d5-<|7GJstS_9qM}Ck=5+mGN3uWy|H(pJe2CiqzSEx1v)Ws7w2G)h&G+ur~4{- zp5~s@r^8PPULc}mK?dxwJguWiSzpV@5_GW|CKg(3$8%BzYiT|ZYmfN}KuLqDq| zD^+)Ha@&kBUVFUup_plVe@5xN*s4EcWc$nU3w@#}kg zi#2Pz8cW^o3Kx=>Fx>J#fD^cRasPT_P)L75zVBPc`QE0)jS{tce}OF|C`dvr5c1-M z@JAf=VP%jc%T1N2b9Qna(%D%Sq`ku62N$X&)MX1Gk}#IscnqXKa8qvi9DZtQe=xs3 zvwd_>Tf4tatG!Tz-O$ibm$_b+V196B*a8ExNsR1W`@mscNmHtT4#QYV>Y_h4`68vi zT{33Dw<5Y{(Qgm>#F-K(HYp_G@(1K(fA8UpptPOU324x|Fq0yz&7R*0-vo_@J#5!#oYs0E3el^)V`EjReIgb!$>68 zUdHRMq# z*b>a|sy>lu_$)Co;3`A}(2aln+PN0!%o%S7MD{qef8CdR?``xVHdv^?IoX(xBsU)RN{t&fVTc|N z7V8Y{zvj2TnJyAhY?Z{p@gW?(X{W7Htv&zkaT+jAnnPX+t6^1z~o2c-k6oTJC@C0 zFvuSMfvxns`K7UG@mw(|&)p6N(e(?8n@S7lD_m`8y^<q@-=v>y_fn z3&@6>MNMpoQPfh*F%O#_-KC2(0OxE`%{oX!^?jR5zeJ&BQ^Qz=U>0%zONz>AG7P(e z!Tir}3$}CLa9EE;C#ej~yWm|VUGKS{MO#Fxh_G&nJmGLzR$AIBZ`lkPom$+ZA)2J=q#p~br#`N^$A%jC4z}`{O^I)=y zPJmK)NrX&)b7{{y%lKBbosxhPf&X`M%V)GtikvOPJGy1ml|?ty3wmE#?SnsL)!Ck9 zAtF%iUS8p;jG1i7v%3;@lJK29<#nHz`YakL#naV&XP&#Kp;+_nyB1N+mcA2H!VlMF zT7l&z4iSV6ks02`NP{`bjt!HGDr8=lV;5-Vg)#<%=)u@qC3*Yb>7lUvG*Sn_5^de` zYv$Y_dM589G9(UGFafn)`qDP!9})UrF0GByj&>Oya0az#8_OH{Sy1Vo?IbZ_eUC@k@~N$P7R|ofl?FXSR9`W=dtP5Z z1+h+LZEdW#L(n-q!=}{1wzre7al8`~QCC?zo_$DJ8Gj@=VsKz!j+>hsi7tVLb;uK|Pfw;VNbwiT$X4^bm()W>&$R zd=W$+u|K+MRXTrAMQj+U(uMn)B%nejC=Uwo!ivk*EvJ->nT^-43$TJj$kq&6){X0DeG+KGo3_jAfr4c7p{yO=^%5@66@o zB<2}-#;_(q80bQ#K-4aCa6pSUAu)uZw2OR_g1W^N~Lx;02DVAW1x1+R!6pEt)OR9JmiLF1wQvs`Xd z8}CS5HqaVtvQ)RkQ&gGbq?U0^vpKA_XNuPkp+F+7tShmCIsW3>WlBQR?AIlY4#V1m z6&BXxJG{LGT99{iWa-&+Q;fmLzy}@CJ(4 zPjW1?bwfJc7i!QR99Obir}ZKCf*l{b^p@W(Vz;t1Is&)JHDlT>w-sN8_Pz~L7|YL% z@C;-o2%E$#z07F6uV7X6|tGH_skU4DMiUe~}Gi9L+a35m?# zB4j$YYdo?%GvAdGUZU_<8e_=SNQW+QEP1#R!y^I(ykQqbpA|6JDo2=4Y%TKoZ#!r2 zXfINL?=lhGDFBW%dSlqMMaZPY~BX=P@!{x*M!*kFrzassSUq}jKBuu zq5yp0D=PugIU#j)Kc9CJa;SRehOb|rFsxh4;}4{AlZ&Y}pGB)j@H+D+GgK%GJL>91l_O*)-iX$xz*YWh2gHIlkci~@_c%a*y%1V#*p^goBqa$@`5Tb=cDvhjVsv0z zK-g;JmtxC~7h#x$@Xz!1a+wld4b|Q<1WBcX}d#&NVzm#5S zjhj3f2wU^?Ha*%O=B=6U?K7Q_-#~;x{yNF>f$ok(H@+*IWtgR^<$VVK&M0PGmz=FM zs9;Gn`_PSJmnTyo=|rv*iO)Jdwp_lfGc7RG@kMt|UJak>^jsWPfzx2BDXPsVP+~s` zWdRBaXoJ7B19%f99Q-EqW}n7Q&jyg_ZXSf+bATQ^1#NJ6Vt5ZODMgY7iJEIR7D(dz z(Q(&-F^o}MDSF}9XkaL}q|&x>h8MQGuIv{QX@~Xm81fYo7PmmqJ=Eb8#1k)WF7ej{ zmKOm`8}Tc@Hhhz@pJRAcHQfYF)QnE()Nw5Jy#7dh=|NxiM2yL_e&a0(r~CE6R;#zf*C&=Zl9&OcHtt-l_r?(M>o*@he!Hz?=EmOn?@o_Heoy?u7@TP# z+GooB#j- diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 71792d7ee..9befdfd75 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -48,6 +48,7 @@ This example is aimed at those with some familiarity with python and/or graphing edge_width=[2 if married else 1 for married in g.es["married"]], edge_color=["#F00" if married else "#000" for married in g.es["married"]], ) + ax.set_aspect(1) plt.show() From 9137698cf984667d041f33978f022371d0c6002a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 30 Nov 2021 15:51:50 +1100 Subject: [PATCH 0745/1892] Gallery page, links, TOC entries, and adaptations --- doc/source/gallery.rst | 16 ++++++++++++++++ doc/source/index.rst | 7 +++++++ doc/source/tutorial.rst | 2 ++ .../bipartite_matching/bipartite_matching.rst | 4 ++++ .../bipartite_matching_maxflow.rst | 4 ++++ doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 4 ++++ doc/source/tutorials/maxflow/maxflow.rst | 4 ++++ doc/source/tutorials/quickstart/quickstart.rst | 4 ++++ .../tutorials/shortest_paths/shortest_paths.rst | 4 ++++ 9 files changed, 49 insertions(+) create mode 100644 doc/source/gallery.rst diff --git a/doc/source/gallery.rst b/doc/source/gallery.rst new file mode 100644 index 000000000..517727fdc --- /dev/null +++ b/doc/source/gallery.rst @@ -0,0 +1,16 @@ +.. include:: include/global.rst + +.. gallery + +======== +Gallery +======== + +This page contains short examples showcasing the functionality of |igraph|: + + - :ref:`tutorials-quickstart` + - :ref:`tutorials-bipartite-matching` + - :ref:`tutorials-bipartite-matching-maxflow` + - :ref:`tutorials-random` + - :ref:`tutorials-maxflow` + - :ref:`tutorials-shortest-paths` diff --git a/doc/source/index.rst b/doc/source/index.rst index 3203cf801..1fd485c8d 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -15,6 +15,13 @@ Contents: intro install tutorial + gallery + tutorials/quickstart/quickstart + tutorials/bipartite_matching/bipartite_matching + tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow + tutorials/erdos_renyi/erdos_renyi + tutorials/maxflow/maxflow + tutorials/shortest_paths/shortest_paths generation analysis visualisation diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 20c05bf4f..0c75b552a 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -16,6 +16,8 @@ start out. If you already have a stable programming background in other language a quick overview of Python, `Learn Python in 10 minutes `_ is probably your best bet. +.. note:: + For the impatient reader, see the :ref:`gallery` page for short, self-contained examples. Starting |igraph| ================= diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 45f2b7cbf..ade2200d1 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-bipartite-matching + ========================== Maximum Bipartite Matching ========================== diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 3d00abd36..38e61cfaa 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-bipartite-matching-maxflow + ========================================== Maximum Bipartite Matching by Maximum Flow ========================================== diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 41da76d88..73ade4332 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-random + ================= Erdős-Rényi Graph ================= diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index bf2bdefcb..5a078f296 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-maxflow + ============ Maximum Flow ============ diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 9befdfd75..6f05a7184 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-quickstart + =========== Quick Start =========== diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 21834b3d1..6b80609a2 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -1,3 +1,7 @@ +.. include:: include/global.rst + +.. tutorials-shortest-paths + ============== Shortest Paths ============== From 523f97ad1de7587db8afcc174228931208620e55 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 1 Dec 2021 06:39:14 +1100 Subject: [PATCH 0746/1892] Review changes --- .../assets/bipartite_matching.py | 6 +++--- .../bipartite_matching/bipartite_matching.rst | 6 +++--- .../assets/bipartite_matching_maxflow.py | 21 +++++++------------ .../bipartite_matching_maxflow.rst | 19 +++++++---------- .../tutorials/quickstart/quickstart.rst | 13 ++++++------ .../shortest_paths/assets/shortest_path.py | 6 ++---- 6 files changed, 30 insertions(+), 41 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py index c4d487f69..0b7483e8d 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py @@ -6,7 +6,7 @@ [0, 0, 0, 0, 0, 1, 1, 1, 1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) -assert(g.is_bipartite()) +assert g.is_bipartite() matching = g.maximum_bipartite_matching() @@ -15,7 +15,7 @@ print("Matching is:") for i in range(5): print(f"{i} - {matching.match_of(i)}") - if matching.match_of(i): + if matching.match_of(i) is not None: matching_size += 1 print("Size of Maximum Matching is:", matching_size) @@ -27,7 +27,7 @@ vertex_size=0.4, vertex_label=range(g.vcount()), vertex_color="lightblue", - edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] + edge_width=[2.5 if e.target == matching.match_of(e.source) else 1.0 for e in g.es] ) ax.set_aspect(1) diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index ade2200d1..c7b606454 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -18,7 +18,7 @@ This example demonstrates an efficient way to find and visualise a maximum bipar [0, 0, 0, 0, 0, 1, 1, 1, 1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) - assert(g.is_bipartite()) + assert g.is_bipartite() matching = g.maximum_bipartite_matching() @@ -33,7 +33,7 @@ Then run the maximum matching, print("Matching is:") for i in range(5): print(f"{i} - {matching.match_of(i)}") - if matching.match_of(i): + if matching.match_of(i) is not None: matching_size += 1 print("Size of Maximum Matching is:", matching_size) @@ -50,7 +50,7 @@ And finally display the bipartite graph with matchings highlighted. vertex_size=0.4, vertex_label=range(g.vcount()), vertex_color="lightblue", - edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] + edge_width=[2.5 if e.target == matching.match_of(e.source) else 1.0 for e in g.es] ) ax.set_aspect(1) plt.show() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py index d75ec7c14..6b7624dfb 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py +++ b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py @@ -8,29 +8,24 @@ ) # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side -for i in range(4): - g.vs[i]["type"] = True -for i in range(4, 9): - g.vs[i]["type"] = False +g.vs[range(4)]["type"] = True +g.vs[range(4, 9)]["type"] = False # Add source and sink as nodes 9 and 10 g.add_vertices(2) -g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side -g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other +g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side +g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other flow = g.maxflow(9, 10) -print("Size of Maximum Matching (maxflow) is:", flow.value) +print("Size of maximum matching (maxflow) is:", flow.value) # Compare this to the "maximum_bipartite_matching()" function g2 = g.copy() -g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded for this function. +g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded for this function. matching = g2.maximum_bipartite_matching() -matching_size = 0 -for i in range(4): - if matching.match_of(i): - matching_size += 1 -print("Size of Maximum Matching (maximum_bipartite_matching) is:", matching_size) +matching_size = sum(1 for i in range(4) if matching.is_matched(i)) +print("Size of maximum matching (maximum_bipartite_matching) is:", matching_size) # Manually set the position of source and sink to display nicely layout = g.layout_bipartite() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 38e61cfaa..b82c4980d 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -6,7 +6,9 @@ Maximum Bipartite Matching by Maximum Flow ========================================== -This example presents how to visualise bipartite matching using maximum flow. Please note that the *igraph* already has :meth:`maximum_bipartite_matching` which is better suited for finding the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching<>`_. This particular example is purely for demonstrative purposes. +This example presents how to visualise bipartite matching using maximum flow. + +.. note:: :meth:`maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out `Maximum Bipartite Matching<>`_. .. TODO: add link to Maximum Bipartite Matching @@ -23,17 +25,15 @@ This example presents how to visualise bipartite matching using maximum flow. Pl ) # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side - for i in range(4): - g.vs[i]["type"] = True - for i in range(4, 9): - g.vs[i]["type"] = False + g.vs[range(4)]["type"] = True + g.vs[range(4, 9)]["type"] = False g.add_vertices(2) g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1.0 - print("Size of Maximum Matching (maxflow) is:", flow.value) + print("Size of maximum matching (maxflow) is:", flow.value) Let's compare the output against :meth:`maximum_bipartite_matching` @@ -45,11 +45,8 @@ Let's compare the output against :meth:`maximum_bipartite_matching` matching = g2.maximum_bipartite_matching() - matching_size = 0 - for i in range(4): - if matching.match_of(i): - matching_size += 1 - print("Size of Maximum Matching (maximum_bipartite_matching) is:", matching_size) + matching_size = sum(1 for i in range(4) if matching.is_matched(i)) + print("Size of maximum matching (maximum_bipartite_matching) is:", matching_size) And finally, display the original flow graph nicely with the matchings added diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index 6f05a7184..74ba5c7e9 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -5,16 +5,15 @@ =========== Quick Start =========== +For the eager folks out there, this intro will give you a quick overview of the following operations: -This quick start will demonstrate the following: - -- Construct a *igraph* graph from scratch -- Set the attributes of nodes and edges -- Plot out a graph using matplotlib -- Save a graph as an image +- Construct a graph +- Set attributes of nodes and edges +- Plot a graph using matplotlib +- Save the plot as an image - Export and import a graph as a ``.gml`` file -This example is aimed at those with some familiarity with python and/or graphing packages, who would like to get some code up and running as fast as possible. +Check out our in-depth tutorial TODO LINK and our gallery TODO LINK for more. .. code-block:: python diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path.py b/doc/source/tutorials/shortest_paths/assets/shortest_path.py index 1234c1e14..607854ed1 100644 --- a/doc/source/tutorials/shortest_paths/assets/shortest_path.py +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path.py @@ -24,13 +24,11 @@ if len(results[0]) > 0: # Add up the weights across all edges on the shortest path - distance = 0 - for e in results[0]: - distance += g.es[e]["weight"] + distance = sum(g.es[e]["weight"] for e in results[0]) print("Shortest weighted distance is: ", distance) else: print("End node could not be reached!") # Output: # Shortest distance is: 3 -# Shortest weighted distance is: 8 \ No newline at end of file +# Shortest weighted distance is: 8 From 85b884126b6ba02263ebbf37723979c27f779205 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 1 Dec 2021 07:29:07 +1100 Subject: [PATCH 0747/1892] Stub for ring animation tutorial --- .../ring_animation/assets/ring_animation.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 doc/source/tutorials/ring_animation/assets/ring_animation.py diff --git a/doc/source/tutorials/ring_animation/assets/ring_animation.py b/doc/source/tutorials/ring_animation/assets/ring_animation.py new file mode 100644 index 000000000..a4dc0062d --- /dev/null +++ b/doc/source/tutorials/ring_animation/assets/ring_animation.py @@ -0,0 +1,27 @@ +import igraph as ig +import matplotlib.pyplot as plt + +# Animate a directed ring graph +g = ig.Graph.Ring(10, directed=True) + +# Make 2D ring layout +layout = g.layout_circle() + +# Create canvas +fig, ax = plt.subplots() + + +# Prepare interactive backend for autoupdate +plt.ion() +plt.show() + +# Animate, one vertex at a time +for frame in range(11): + ax.clear() + # Fix limits (unless you want a zoom-out effect) + ax.set_xlim(-1.5, 1.5) + ax.set_ylim(-1.5, 1.5) + gd = g.subgraph(range(frame)) + ig.plot(gd, target=ax, layout=layout[:frame]) + fig.canvas.draw_idle() + fig.canvas.start_event_loop(0.5) From 2f3b4b6495c73480c02eda6ba5d5fa68a6827f00 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 1 Dec 2021 07:32:39 +1100 Subject: [PATCH 0748/1892] Better line comments in ring tutorial --- .../tutorials/ring_animation/assets/ring_animation.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/source/tutorials/ring_animation/assets/ring_animation.py b/doc/source/tutorials/ring_animation/assets/ring_animation.py index a4dc0062d..951337ff6 100644 --- a/doc/source/tutorials/ring_animation/assets/ring_animation.py +++ b/doc/source/tutorials/ring_animation/assets/ring_animation.py @@ -10,18 +10,23 @@ # Create canvas fig, ax = plt.subplots() - # Prepare interactive backend for autoupdate plt.ion() plt.show() # Animate, one vertex at a time for frame in range(11): + # Remove previous plot elements ax.clear() + # Fix limits (unless you want a zoom-out effect) ax.set_xlim(-1.5, 1.5) ax.set_ylim(-1.5, 1.5) + + # Plot subgraph gd = g.subgraph(range(frame)) ig.plot(gd, target=ax, layout=layout[:frame]) + + # matplotlib animation infrastructure fig.canvas.draw_idle() fig.canvas.start_event_loop(0.5) From 6191662c37012953bb4e8112a3860ef804024578 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 1 Dec 2021 14:31:17 +0100 Subject: [PATCH 0749/1892] style: nitpicking --- .../bipartite_matching/assets/bipartite_matching.py | 6 +++--- .../tutorials/bipartite_matching/bipartite_matching.rst | 6 +++--- .../bipartite_matching_maxflow.rst | 4 ++-- doc/source/tutorials/shortest_paths/assets/shortest_path.py | 4 ++-- doc/source/tutorials/shortest_paths/shortest_paths.rst | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py index 0b7483e8d..c92c64800 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py @@ -15,9 +15,9 @@ print("Matching is:") for i in range(5): print(f"{i} - {matching.match_of(i)}") - if matching.match_of(i) is not None: + if matching.is_matched(i): matching_size += 1 -print("Size of Maximum Matching is:", matching_size) +print("Size of maximum matching is:", matching_size) fig, ax = plt.subplots(figsize=(7, 3)) ig.plot( @@ -39,4 +39,4 @@ # 2 - 8 # 3 - 6 # 4 - None -# Size of Maximum Matching is: 4 +# Size of maximum matching is: 4 diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index c7b606454..d2bd96527 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -33,9 +33,9 @@ Then run the maximum matching, print("Matching is:") for i in range(5): print(f"{i} - {matching.match_of(i)}") - if matching.match_of(i) is not None: + if matching.is_matched(i): matching_size += 1 - print("Size of Maximum Matching is:", matching_size) + print("Size of maximum matching is:", matching_size) And finally display the bipartite graph with matchings highlighted. @@ -65,7 +65,7 @@ The received output is 2 - 8 3 - 6 4 - None - Size of Maximum Matching is: 4 + Size of maximum matching is: 4 .. figure:: ./figures/bipartite.png :alt: The visual representation of maximal bipartite matching diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index b82c4980d..a88f209b4 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -74,8 +74,8 @@ The received output is: .. code-block:: - Size of Maximum Matching (maxflow) is: 4.0 - Size of Maximum Matching (maximum_bipartite_matching) is: 4 + Size of maximum matching (maxflow) is: 4.0 + Size of maximum matching (maximum_bipartite_matching) is: 4 .. figure:: ./figures/bipartite_matching_maxflow.png :alt: The visual representation of maximal bipartite matching diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path.py b/doc/source/tutorials/shortest_paths/assets/shortest_path.py index 607854ed1..e79b63315 100644 --- a/doc/source/tutorials/shortest_paths/assets/shortest_path.py +++ b/doc/source/tutorials/shortest_paths/assets/shortest_path.py @@ -8,7 +8,7 @@ ) # g.get_shortest_paths() returns a list of vertex ID paths -results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] +results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] if len(results[0]) > 0: # The distance is the number of vertices in the shortest path minus one. @@ -20,7 +20,7 @@ g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] # g.get_shortest_paths() returns a list of edge ID paths -results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] +results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] if len(results[0]) > 0: # Add up the weights across all edges on the shortest path diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index 6b80609a2..dc83871c4 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -22,7 +22,7 @@ To find the shortest path or distance between two nodes, we can use :meth:`get_s ) # g.get_shortest_paths() returns a list of vertex ID paths - results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] + results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] if len(results[0]) > 0: # The distance is the number of vertices in the shortest path minus one. @@ -38,7 +38,7 @@ If the edges have associated distances or weights, we pass them in as an argumen g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] # g.get_shortest_paths() returns a list of edge ID paths - results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] + results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] if len(results[0]) > 0: # Add up the weights across all edges on the shortest path From 43157403d814ba1ac2554fd4164f7ba40a5f6299 Mon Sep 17 00:00:00 2001 From: h5jam Date: Thu, 2 Dec 2021 21:48:57 +0900 Subject: [PATCH 0750/1892] add: topological sort example --- .../assets/topological_sort.py | 17 +++++ .../figures/topological_sort.png | Bin 0 -> 19017 bytes .../topological_sort/topological_sort.rst | 59 ++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 doc/source/tutorials/topological_sort/assets/topological_sort.py create mode 100644 doc/source/tutorials/topological_sort/figures/topological_sort.png create mode 100644 doc/source/tutorials/topological_sort/topological_sort.rst diff --git a/doc/source/tutorials/topological_sort/assets/topological_sort.py b/doc/source/tutorials/topological_sort/assets/topological_sort.py new file mode 100644 index 000000000..02b384b5e --- /dev/null +++ b/doc/source/tutorials/topological_sort/assets/topological_sort.py @@ -0,0 +1,17 @@ +import igraph as ig + +# generate directed acyclic graph +g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], + directed=True) +assert g.is_dag + +# topological sorting +results = g.topological_sorting(mode='out') +print('Topological sorting result (out):', *results) + +results = g.topological_sorting(mode='in') +print('Topological sorting result (in):', *results) + +# print indegree of each node +for i in range(g.vcount()): + print('degree of {}: {}'.format(i, g.vs[i].indegree())) \ No newline at end of file diff --git a/doc/source/tutorials/topological_sort/figures/topological_sort.png b/doc/source/tutorials/topological_sort/figures/topological_sort.png new file mode 100644 index 0000000000000000000000000000000000000000..24ca49711547068bf574cec820a06ecf723532cb GIT binary patch literal 19017 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 aJ^9s}$EoRX8h+LZrJ Date: Thu, 2 Dec 2021 22:18:56 +0900 Subject: [PATCH 0751/1892] fix: topological_sort.rst --- doc/source/tutorials/topological_sort/topological_sort.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index 11c881d58..6861f7a67 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -26,7 +26,7 @@ To get topological sorted list, we can use :meth:`topological_sorting`. If given results = g.topological_sorting(mode='in') print('Topological sorting result (in):', *results) -Default mode is `out`, start from the first node with in-degree as 0. And mode is `in`, start from the first node with in-degree as maximum of all degrees. +Default mode is 'out', start from the first node with in-degree as 0. And mode is 'in', start from the first node with in-degree as maximum of all degrees. .. code-block:: python From 47412e7a0531055b111262dd6c1153d5dd353aef Mon Sep 17 00:00:00 2001 From: ah00ee Date: Fri, 3 Dec 2021 02:43:09 +0900 Subject: [PATCH 0752/1892] Add topological_sort.rst --- doc/source/tutorials/topological_sort/topological_sort.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index 6861f7a67..60f5e6178 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -6,7 +6,7 @@ Topological Sort ================ -This example show how to sort topological order with directed acyclic graph (DAG). +This example show how to sort by topological order with directed acyclic graph(DAG). To get topological sorted list, we can use :meth:`topological_sorting`. If given graph is not DAG, error will be returned. @@ -26,7 +26,7 @@ To get topological sorted list, we can use :meth:`topological_sorting`. If given results = g.topological_sorting(mode='in') print('Topological sorting result (in):', *results) -Default mode is 'out', start from the first node with in-degree as 0. And mode is 'in', start from the first node with in-degree as maximum of all degrees. +There are two modes for :meth:`topological_sorting`. Default mode is 'out', which starts from the node with zero in-degree to sort nodes by topological order. The other mode, 'in', starts from the node with maximum in-degree. .. code-block:: python @@ -56,4 +56,4 @@ The output of two sorted list following as: The graph `g` -- Note that :meth:`topological_sorting` returns topological sorted list and we can set a mode of two. \ No newline at end of file +- Note that :meth:`topological_sorting` returns topological sorted list and we can set a mode of two. From 858ca8a8738ac36cd26dc13126d9a23d89fa2f64 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 2 Dec 2021 19:31:44 +0100 Subject: [PATCH 0753/1892] test_atlas: skip more graphs. --- tests/test_atlas.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/test_atlas.py b/tests/test_atlas.py index 546a28300..5041795dc 100644 --- a/tests/test_atlas.py +++ b/tests/test_atlas.py @@ -38,9 +38,6 @@ def testEigenvectorCentrality(self): try: for idx, g in enumerate(self.__class__.graphs): - if idx in self.__class__.skip_graphs: - # Skip this graph; it causes lots of problems and I don't know why - continue try: ec, eval = g.evcent(return_eigenvalue=True) @@ -156,14 +153,18 @@ def testAuthorityScore(self): class GraphAtlasTests(unittest.TestCase, AtlasTestBase): graphs = [Graph.Atlas(i) for i in range(1253)] - skip_graphs = set([180]) +# Skip some problematic graphs +GraphAtlasTests.graphs = [g for idx, g in enumerate(GraphAtlasTests.graphs) if idx not in set([70, 180])] +print(len(GraphAtlasTests.graphs)) class IsoclassTests(unittest.TestCase, AtlasTestBase): graphs = [Graph.Isoclass(3, i, directed=True) for i in range(16)] + [ Graph.Isoclass(4, i, directed=True) for i in range(218) ] - skip_graphs = set([136]) + +# Skip some problematic graphs +IsoclassTests.graphs = [g for idx, g in enumerate(IsoclassTests.graphs) if idx not in set([136])] def suite(): From ceba21dce391d046b8b862df82fd0c4db475370b Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 3 Dec 2021 14:04:47 +1100 Subject: [PATCH 0754/1892] Fix spacing in erdos_renyi.rst --- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 73ade4332..bdcee6db8 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -82,18 +82,17 @@ The received output is: IGRAPH U--- 20 35 -- .. figure:: ./figures/erdos_renyi_p.png + :alt: The visual representation of a randomly generated Erdos Renyi graph :align: center Erdos Renyi random graphs with probability ``p`` = 0.2 .. figure:: ./figures/erdos_renyi_m.png + :alt: The second visual representation of a randomly generated Erdos Renyi graph :align: center Erdos Renyi random graphs with ``m`` = 35 edges Note that even when using the same random seed, results can still differ depending on the machine the code is being run from. - - - From 60db6f2214565b582ad3d039eae5cdc35ca395e9 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 3 Dec 2021 14:05:21 +1100 Subject: [PATCH 0755/1892] Add ring_animation.rst --- doc/source/index.rst | 1 + .../ring_animation/assets/ring_animation.py | 5 +- .../ring_animation/figures/ring_animation.gif | Bin 0 -> 39803 bytes .../ring_animation/ring_animation.rst | 55 ++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 doc/source/tutorials/ring_animation/figures/ring_animation.gif create mode 100644 doc/source/tutorials/ring_animation/ring_animation.rst diff --git a/doc/source/index.rst b/doc/source/index.rst index 1fd485c8d..e2295739c 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -21,6 +21,7 @@ Contents: tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow tutorials/erdos_renyi/erdos_renyi tutorials/maxflow/maxflow + tutorials/ring_animation/ring_animation tutorials/shortest_paths/shortest_paths generation analysis diff --git a/doc/source/tutorials/ring_animation/assets/ring_animation.py b/doc/source/tutorials/ring_animation/assets/ring_animation.py index 951337ff6..02e028ec5 100644 --- a/doc/source/tutorials/ring_animation/assets/ring_animation.py +++ b/doc/source/tutorials/ring_animation/assets/ring_animation.py @@ -9,6 +9,7 @@ # Create canvas fig, ax = plt.subplots() +ax.set_aspect(1) # Prepare interactive backend for autoupdate plt.ion() @@ -16,7 +17,7 @@ # Animate, one vertex at a time for frame in range(11): - # Remove previous plot elements + # Remove plot elements from the previous frame ax.clear() # Fix limits (unless you want a zoom-out effect) @@ -25,7 +26,7 @@ # Plot subgraph gd = g.subgraph(range(frame)) - ig.plot(gd, target=ax, layout=layout[:frame]) + ig.plot(gd, target=ax, layout=layout[:frame], vertex_color="yellow") # matplotlib animation infrastructure fig.canvas.draw_idle() diff --git a/doc/source/tutorials/ring_animation/figures/ring_animation.gif b/doc/source/tutorials/ring_animation/figures/ring_animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..613dcfaac38c459042276ca9cabb0b862b779656 GIT binary patch literal 39803 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/ring_animation/ring_animation.rst b/doc/source/tutorials/ring_animation/ring_animation.rst new file mode 100644 index 000000000..92646a9d0 --- /dev/null +++ b/doc/source/tutorials/ring_animation/ring_animation.rst @@ -0,0 +1,55 @@ +.. include:: ../../include/global.rst + +.. tutorials-ring-animation + +==================== +Ring Graph Animation +==================== + +This example demonstrates how to use Matplotlib's `animation features `_ in order to animate a ring graph sequentially being revealed. + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + # Animate a directed ring graph + g = ig.Graph.Ring(10, directed=True) + + # Make 2D ring layout + layout = g.layout_circle() + + # Create canvas + fig, ax = plt.subplots() + ax.set_aspect(1) + + # Prepare interactive backend for autoupdate + plt.ion() + plt.show() + + # Animate, one vertex at a time + for frame in range(11): + # Remove plot elements from the previous frame + ax.clear() + + # Fix limits (unless you want a zoom-out effect) + ax.set_xlim(-1.5, 1.5) + ax.set_ylim(-1.5, 1.5) + + # Plot subgraph + gd = g.subgraph(range(frame)) + ig.plot(gd, target=ax, layout=layout[:frame], vertex_color="yellow") + + # matplotlib animation infrastructure + fig.canvas.draw_idle() + fig.canvas.start_event_loop(0.5) + +The received output is: + +.. figure:: ./figures/ring_animation.gif + + :alt: The visualisation of a animated ring graph + :align: center + :caption: Sequentially animated ring graph. + +Note that we use *igraph*'s :meth:`Graph.subgraph()` (a.k.a `:meth:`Graph.induced_subgraph()``_) in order to obtain a section of the ring graph at a time for each frame. From 0093ea53f441b1655dae06bc4fb70c8794050cfa Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 3 Dec 2021 16:02:18 +1100 Subject: [PATCH 0756/1892] Use ".. note" across all tutorials --- .../bipartite_matching_maxflow.rst | 4 +++- doc/source/tutorials/erdos_renyi/erdos_renyi.rst | 5 ++++- doc/source/tutorials/ring_animation/ring_animation.rst | 5 ++++- doc/source/tutorials/shortest_paths/shortest_paths.rst | 7 +++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index a88f209b4..a53a1b42a 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -83,4 +83,6 @@ The received output is: Maximal Bipartite Matching -Note that maximum flow will represent the capacities as real values, which is why our result is ``4.0`` instead of ``4``. +.. note:: + + Maximum flow will represent the capacities as real values, which is why our result is ``4.0`` instead of ``4``. diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index bdcee6db8..d4a451e5f 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -95,4 +95,7 @@ The received output is: Erdos Renyi random graphs with ``m`` = 35 edges -Note that even when using the same random seed, results can still differ depending on the machine the code is being run from. + +.. note:: + + Even when using the same random seed, results can still differ depending on the machine the code is being run from. diff --git a/doc/source/tutorials/ring_animation/ring_animation.rst b/doc/source/tutorials/ring_animation/ring_animation.rst index 92646a9d0..9add9a945 100644 --- a/doc/source/tutorials/ring_animation/ring_animation.rst +++ b/doc/source/tutorials/ring_animation/ring_animation.rst @@ -52,4 +52,7 @@ The received output is: :align: center :caption: Sequentially animated ring graph. -Note that we use *igraph*'s :meth:`Graph.subgraph()` (a.k.a `:meth:`Graph.induced_subgraph()``_) in order to obtain a section of the ring graph at a time for each frame. + +.. note:: + + We use *igraph*'s :meth:`Graph.subgraph()` (a.k.a `Graph.induced_subgraph()``_) in order to obtain a section of the ring graph at a time for each frame. diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index dc83871c4..c7623fc0c 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -64,8 +64,11 @@ The output of these these two shortest paths are: .. TODO: Add in edge weights when possible! Matplotlib does not support displaying edge weights (and the develop branch implementation is bugged). -- Note that :meth:`get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. -- If you're interested in finding *all* shortest paths, take a look at :meth:`get_all_shortest_paths`. + +.. note:: + + - :meth:`get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. + - If you're interested in finding *all* shortest paths, take a look at :meth:`get_all_shortest_paths`. From 096168d58067e403fbf6227129e25601e0acace9 Mon Sep 17 00:00:00 2001 From: ah00ee Date: Fri, 3 Dec 2021 14:42:58 +0900 Subject: [PATCH 0757/1892] doc: fix: grammer in topological_sort.rst --- .../topological_sort/topological_sort.rst | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index 60f5e6178..09e92fc2e 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -6,54 +6,62 @@ Topological Sort ================ -This example show how to sort by topological order with directed acyclic graph(DAG). - -To get topological sorted list, we can use :meth:`topological_sorting`. If given graph is not DAG, error will be returned. +To get a topological sort of directed acyclic graph(DAG), we can use :meth:`topological_sortng`. .. code-block:: python import igraph as ig - # generate directed acyclic graph + # generate directed acyclic graph(DAG) g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], directed=True) assert g.is_dag - # topological sorting - results = g.topological_sorting(mode='out') - print('Topological sorting result (out):', *results) + # g.topological_sorting() returns a list of vertex ID paths. + # If the given graph is not DAG, error will be returned. + results = g.topological_sorting(mode='out') # results = [0, 1, 2, 4, 3, 5] + print('Topological sort of graph g on 'out' mode:', *results) + + results = g.topological_sorting(mode='in') # results = [5, 3, 1, 4, 2, 0] + print('Topological sort of graph g on 'in' mode:', *results) + +There are two modes of :meth:`topological_sorting`. Default mode is 'out', it starts a topological sorting from the node with indegree 0. The other mode is 'in', it starts a topological sorting from the node that has maximum indegree. + +The output of the code above is: + +.. code-block:: - results = g.topological_sorting(mode='in') - print('Topological sorting result (in):', *results) + Topological sort of graph g on 'out' mode: 0 1 2 4 3 5 + Topological sort of graph g on 'in' mode: 5 3 1 4 2 0 -There are two modes for :meth:`topological_sorting`. Default mode is 'out', which starts from the node with zero in-degree to sort nodes by topological order. The other mode, 'in', starts from the node with maximum in-degree. +For finding indegree of each node, we can use :meth:`indegree()`. .. code-block:: python import igraph as ig - # generate directed acyclic graph + # generate directed acyclic graph(DAG) g = ig.Graph(edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], directed=True) - # print indegree of each node + # g.vs[i].indegree() returns the indegree of each vertex(which is g.vs[i]). for i in range(g.vcount()): print('degree of {}: {}'.format(i, g.vs[i].indegree())) -We can use :meth:`indegree()` to compute indegree of a node. - -The output of two sorted list following as: - -.. code-block:: - - Topological sorting is (out): 0 1 2 4 3 5 - Topological sorting is (in): 5 3 1 4 2 0 + ''' + degree of 0: 0 + degree of 1: 1 + degree of 2: 2 + degree of 3: 3 + degree of 4: 4 + degree of 5: 5 + ''' .. figure:: ./figures/topological_sort.png - :alt: The visual representation of a directed acyclic graph for topological sorting + :alt: The visual representation of a directed acyclic graph(DAG) for topological sorting :align: center The graph `g` -- Note that :meth:`topological_sorting` returns topological sorted list and we can set a mode of two. +- Note that :meth:`topological_sorting` returns a list of vertice ID paths and we can set two modes. From dc25f5714c9d38c5f3dcdc80ba8e90aed8457129 Mon Sep 17 00:00:00 2001 From: "Yesung(Isaac) Lee" <49810053+Isaac-Lee@users.noreply.github.com> Date: Fri, 3 Dec 2021 15:03:25 +0900 Subject: [PATCH 0758/1892] add graph_traversal.rst --- .../tutorials/topological_sort/graph_traversal.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 doc/source/tutorials/topological_sort/graph_traversal.rst diff --git a/doc/source/tutorials/topological_sort/graph_traversal.rst b/doc/source/tutorials/topological_sort/graph_traversal.rst new file mode 100644 index 000000000..40fd31a78 --- /dev/null +++ b/doc/source/tutorials/topological_sort/graph_traversal.rst @@ -0,0 +1,13 @@ +.. include:: include/global.rst + +.. tutorials-graph-graversal + +================ +Graph Traversal +================ + +To get a topological sort of directed acyclic graph(DAG), we can use :meth:`topological_sortng`. + +.. code-block:: python + + import igraph as ig From 9f3f3a578a8b605d1535883d999904de1aca7d84 Mon Sep 17 00:00:00 2001 From: "Yesung(Isaac) Lee" <49810053+Isaac-Lee@users.noreply.github.com> Date: Fri, 3 Dec 2021 15:07:40 +0900 Subject: [PATCH 0759/1892] doc: fix: graph_traversal.rst --- doc/source/tutorials/topological_sort/graph_traversal.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/source/tutorials/topological_sort/graph_traversal.rst b/doc/source/tutorials/topological_sort/graph_traversal.rst index 40fd31a78..d96f4822a 100644 --- a/doc/source/tutorials/topological_sort/graph_traversal.rst +++ b/doc/source/tutorials/topological_sort/graph_traversal.rst @@ -5,9 +5,3 @@ ================ Graph Traversal ================ - -To get a topological sort of directed acyclic graph(DAG), we can use :meth:`topological_sortng`. - -.. code-block:: python - - import igraph as ig From 9b41460b487b847cfa96fdc6dd70328979b546ed Mon Sep 17 00:00:00 2001 From: "Yesung(Isaac) Lee" <49810053+Isaac-Lee@users.noreply.github.com> Date: Fri, 3 Dec 2021 15:08:07 +0900 Subject: [PATCH 0760/1892] doc: fix: graph_traversal.rst From 41523d9c8479af132bf75c7fbb8ee5c7889ad5c9 Mon Sep 17 00:00:00 2001 From: isaac_lee Date: Fri, 3 Dec 2021 15:12:04 +0900 Subject: [PATCH 0761/1892] delete file --- doc/source/tutorials/topological_sort/graph_traversal.rst | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 doc/source/tutorials/topological_sort/graph_traversal.rst diff --git a/doc/source/tutorials/topological_sort/graph_traversal.rst b/doc/source/tutorials/topological_sort/graph_traversal.rst deleted file mode 100644 index d96f4822a..000000000 --- a/doc/source/tutorials/topological_sort/graph_traversal.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. include:: include/global.rst - -.. tutorials-graph-graversal - -================ -Graph Traversal -================ From 9dbabbd50aac195ec1ac4eb317cea5e12433e2a9 Mon Sep 17 00:00:00 2001 From: h5jam Date: Sun, 12 Dec 2021 15:24:21 +0900 Subject: [PATCH 0762/1892] doc: fix a figure of topological sort --- .../figures/topological_sort.png | Bin 19017 -> 23883 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/source/tutorials/topological_sort/figures/topological_sort.png b/doc/source/tutorials/topological_sort/figures/topological_sort.png index 24ca49711547068bf574cec820a06ecf723532cb..db31031e7bfb36722696d15303bb98baf2781587 100644 GIT binary patch literal 23883 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 ZI+pyvSUy8X55eXnN84RCrB=St{{^I4rYisd literal 19017 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 aJ^9s}$EoRX8h+LZrJ Date: Sun, 12 Dec 2021 21:14:21 +1100 Subject: [PATCH 0763/1892] fix: Aspect ratio in matplotlib plotting --- src/igraph/drawing/matplotlib/graph.py | 4 ++++ .../test_graph/clustering_directed.png | Bin 36485 -> 35633 bytes .../test_graph/clustering_directed_large.png | Bin 67108 -> 60787 bytes .../test_graph/graph_basic.png | Bin 25084 -> 24565 bytes .../test_graph/graph_directed.png | Bin 26545 -> 25533 bytes .../test_graph/graph_edit_children.png | Bin 24552 -> 24177 bytes .../test_graph/graph_mark_groups_directed.png | Bin 26545 -> 25533 bytes 7 files changed, 4 insertions(+) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 3c7742efc..28c2eb8a4 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -316,4 +316,8 @@ def draw(self, graph, *args, **kwds): ax.set_xticks([]) ax.set_yticks([]) + # Set equal aspect to get actual circles + ax.set_aspect(1) + + # Autoscale for x/y axis limits ax.autoscale_view() diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index b8ae42ae5db3d7741064b11b0f2c36dff606091d..c2dd4cc65ced7ca3d0e2eedd132c68521ab32fab 100644 GIT binary patch literal 35633 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

  • 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 literal 26448 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 diff --git a/doc/source/tutorials/quickstart/quickstart.rst b/doc/source/tutorials/quickstart/quickstart.rst index c8a57c355..71792d7ee 100644 --- a/doc/source/tutorials/quickstart/quickstart.rst +++ b/doc/source/tutorials/quickstart/quickstart.rst @@ -46,6 +46,7 @@ This example is aimed at those with some familiarity with python and/or graphing vertex_label=g.vs["name"], vertex_label_size=7.0, edge_width=[2 if married else 1 for married in g.es["married"]], + edge_color=["#F00" if married else "#000" for married in g.es["married"]], ) plt.show() From d5cdc3fbfd2f0b1f51fc932325e72bcfb31ff974 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 30 Nov 2021 15:37:22 +1100 Subject: [PATCH 0744/1892] Fix aspect ratio of tutorials to 1.0 for the sake of beauty --- ...rtite_mathing.py => bipartite_matching.py} | 4 +++- .../bipartite_matching/bipartite_matching.rst | 3 ++- .../bipartite_matching/figures/bipartite.png | Bin 33545 -> 21819 bytes .../assets/bipartite_matching_maxflow.py | 1 + .../bipartite_matching_maxflow.rst | 1 + .../figures/bipartite_matching_maxflow.png | Bin 50120 -> 26165 bytes .../erdos_renyi/assets/erdos_renyi.py | 4 ++++ .../tutorials/erdos_renyi/erdos_renyi.rst | 4 ++++ .../erdos_renyi/figures/erdos_renyi_m.png | Bin 153627 -> 135643 bytes .../erdos_renyi/figures/erdos_renyi_p.png | Bin 100941 -> 99833 bytes .../tutorials/maxflow/assets/maxflow.py | 1 + .../tutorials/maxflow/figures/maxflow.png | Bin 27217 -> 27330 bytes doc/source/tutorials/maxflow/maxflow.rst | 2 +- .../tutorials/quickstart/assets/quickstart.py | 1 + .../quickstart/figures/social_network.png | Bin 26637 -> 28909 bytes .../tutorials/quickstart/quickstart.rst | 1 + 16 files changed, 19 insertions(+), 3 deletions(-) rename doc/source/tutorials/bipartite_matching/assets/{bipartite_mathing.py => bipartite_matching.py} (94%) diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py similarity index 94% rename from doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py rename to doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py index 65c5d83dc..c4d487f69 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_mathing.py +++ b/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py @@ -3,7 +3,7 @@ # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side g = ig.Graph.Bipartite( - [0,0,0,0,0,1,1,1,1], + [0, 0, 0, 0, 0, 1, 1, 1, 1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) assert(g.is_bipartite()) @@ -29,6 +29,8 @@ vertex_color="lightblue", edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] ) +ax.set_aspect(1) + plt.show() # Matching is: diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 59c636a52..45f2b7cbf 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -11,7 +11,7 @@ This example demonstrates an efficient way to find and visualise a maximum bipar # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side g = ig.Graph.Bipartite( - [0,0,0,0,0,1,1,1,1], + [0, 0, 0, 0, 0, 1, 1, 1, 1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) assert(g.is_bipartite()) @@ -48,6 +48,7 @@ And finally display the bipartite graph with matchings highlighted. vertex_color="lightblue", edge_width=[2.5 if e.target==matching.match_of(e.source) else 1.0 for e in g.es] ) + ax.set_aspect(1) plt.show() The received output is diff --git a/doc/source/tutorials/bipartite_matching/figures/bipartite.png b/doc/source/tutorials/bipartite_matching/figures/bipartite.png index 3565aba619105e82297afe4aa60406949e319645..1d14a849d820c783e05869e03bc9ed1a85d0bfd9 100644 GIT binary patch literal 21819 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 Qqhc_2*3MQ97Jf;80lOo^CIA2c literal 33545 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 diff --git a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py index 5fa0c3e82..d75ec7c14 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py +++ b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py @@ -47,4 +47,5 @@ vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] ) +ax.set_aspect(1) plt.show() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 97b36c08d..3d00abd36 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -66,6 +66,7 @@ And finally, display the original flow graph nicely with the matchings added vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] ) + ax.set_aspect(1) plt.show() The received output is: diff --git a/doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png b/doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png index 86a6fb1bbbcdfc709431df4f216d7f8cd1433c27..29a7e5ca98cc2e90dd0dcaaa57eb36472d817227 100644 GIT binary patch literal 26165 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

  • {%- endblock %} diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 2656940f3..979a75848 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -6,15 +6,19 @@ # ./mkdoc.sh -s (makes standalone docs that require no further processing) STANDALONE=0 - -while getopts ":s" OPTION; do - case $OPTION in - s) - STANDALONE=1 - ;; - \?) - echo "Usage: $0 [-s]" - ;; +SERVE=0 + +while getopts ":s:j" OPTION; do + case $OPTION in + s) + STANDALONE=1 + ;; + j) + SERVE=1 + ;; + \?) + echo "Usage: $0 [-sj]" + ;; esac done shift $((OPTIND -1)) @@ -68,8 +72,27 @@ if [ "x$STANDALONE" = "x1" ]; then ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} else .venv/bin/sphinx-build ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} + + if [ "x$SERVE" = "x1" ]; then + cd doc/html + + # Copy jekyll build environment + cp -r ../jekyll_tools/* ./ + + # Install jekyll infra + bundle config set --local path 'vendor/bundle' + bundle install + + # TODO: copy back? + + # Build website via templates + bundle exec jekyll serve + + fi fi + + #PWD=`pwd` #DOC_API_FOLDER=${ROOT_FOLDER}/doc/api #DOC2DASH=`which doc2dash 2>/dev/null || true` From 8994aa6e0ea4f5753dd5e1662423f3dceabbd20a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Jan 2022 08:43:01 +0100 Subject: [PATCH 0835/1892] chore: updated vendored igraph to nearly-0.9.6 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 8bb3224ab..ee7875fd0 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 8bb3224ab3cfb71bacb0621412d3d43b61a5d676 +Subproject commit ee7875fd026600d8a47dbb6c456f0195e5e9a260 From 83dc1949e738a648554dd15e0db4d33330955013 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Wed, 5 Jan 2022 19:40:40 +1100 Subject: [PATCH 0836/1892] Add spanning tree tutorials --- .../assets/minimum_spanning_trees.py | 35 +++++++++ .../figures/minimum_spanning_trees.png | Bin 0 -> 21573 bytes .../minimum_spanning_trees.rst | 74 ++++++++++++++++++ .../spanning_trees/assets/spanning_trees.py | 38 +++++++++ .../spanning_trees/figures/spanning_trees.png | Bin 0 -> 21803 bytes .../spanning_trees/spanning_trees.rst | 73 +++++++++++++++++ 6 files changed, 220 insertions(+) create mode 100644 doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py create mode 100644 doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png create mode 100644 doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst create mode 100644 doc/source/tutorials/spanning_trees/assets/spanning_trees.py create mode 100644 doc/source/tutorials/spanning_trees/figures/spanning_trees.png create mode 100644 doc/source/tutorials/spanning_trees/spanning_trees.rst diff --git a/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py b/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py new file mode 100644 index 000000000..9b1191460 --- /dev/null +++ b/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py @@ -0,0 +1,35 @@ +import igraph as ig +import matplotlib.pyplot as plt +import numpy as np + +# Generate grid graph with random weights +np.random.seed(0) + +g = ig.Graph.Lattice([5, 5], circular=False) +g.es["weight"] = np.random.randint(1, 20, g.ecount()).tolist() + +# Generate minimum spanning tree +mst_edges = g.spanning_tree(weights=g.es["weight"], return_tree=False) + +# Plot graph +g.es["color"] = "lightgray" +g.es[mst_edges]["color"] = "midnightblue" +g.es["width"] = 1.0 +g.es[mst_edges]["width"] = 3.0 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout="grid", + vertex_color="lightblue", + edge_width=g.es["width"], + edge_label=g.es["weight"], + edge_background="white", +) +plt.show() + +# Print out minimum edge weight sum +print("Minimum edge weight sum:", sum(g.es[mst_edges]["weight"])) + +# Minimum edge weight sum: 136 diff --git a/doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png b/doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7179457bfb1159501f5c2d75ee28eb4bbcd06b GIT binary patch literal 21573 zcmeIa2{@K(+b@2L3}uK0GAp7G5=o|HR+J)So-}HquT|GRIPF{d+#_j(NDA7 zEr*Mjw?IpSEuvTdnR=Rr|DAzS|0BHGq*PQ?i+xsEWZ_LFdFj&cv#@=yB<^YZ`uXkm zsb+N&jj?lfKCCK<%m0#R9+FhzdsPl2-D!)>=XkRsf5lIZl+9YimZr6blsW%q=w%|F!5Gy770SFonGHY4`r@#BQVJ_IqM&JT); z&e0q^2$$^F6wY}w%lOQTws-2>V)%_QItfpaz5*-1q$GChzI-y=)@tqg5QZv9&UiIl zX_g8ZbQ`0nYiKwoCdTMPLe=m>&^+5^R-2suEU7*QSJ36SXK5x&Sl?@tLtWkO^wsfjmg{xbTZ0bJ2g$+ZG)*imp&VU9KVDLAeZ&jduS$~C6j9fzV2!oZ6FNNdklse*iXSndhn|0UeZeGM&B_%EA zYkNC2vasALd24m^S)ab5A{i|7(8$O~@c3Bt@2wstred~UW>lJ0J^h76(SLr=i6)&A zhrQctbM^Uei`qYC&XpzTF8?59-lY+iYi&%uK0Z9z8()1?M>mGPd=>}Kyr#GJXsg8b z%)K6NE`Fhn^SQZac<1;81rNe+Vr@sP>^$3d7_s~Io|>FdB-?#+q}GoB>Fw>+@VIk+ z22+sQEU_7d-Pt?clSN`@&PBR^f9+IP+I(3M$F{Z&z431NJM5#U#uzmgY?3u2qIkyM z-rmm6sjh>~aCNY7Xo25a`$!OHoF`d^w)o&Mx!l+`#o(Hrk&%(za1}wiRvvN2t)j~L zQgM&d)(gvrXjx<(J^YB**C(HFJPruBbmPViA3@D`s&Nu-GdYdf*1c!k+}(|atL}?< ztnrwAdgcG4B|0%bztggn*AJH^?A*%3_e7h ze16_BSv@W-H@9sR|0zz=w*BeqwsH|gj^nsW;88(hKJ3mJ?+fesEio5pck%03d;HGk z_8lw5wdL_vZkOHZ?hJ-f=V@XD-Sha3M#*FB>_n2dmGCQr&Xi|A;W>-OdLro)v2ZQg zY)4b~!cw{n%RpP?tfzNdfi+p)ruOj@xgU#$yaN0WavFWfHq@3fm)H9bAFu<92U7QEx)hVB&= zuzTp~>4o?1LWNoUz@5b^Bvi1KTUwx1y4#d0dGc(-qSYCpIn&!}v~ZV>nwy(Pn3)K> zZI9MSTNJDXJ%2mmwKd5Z$atP6L}H7p&~}Kj%>8Re$5m~c{m<{5-68+bGJ0%f0YfJt zArbWa-H7MCdn41+`wxlvzWVg?^^U^nsqNNIam*t9~F(E94K?eju%GG zSQX?r?S?lm-n!{9oi(+=VaernkW?`_JNp20Y^oxk3-|EAHYyKECjQ9V@o<{x}yOUn7*w&{wYluS5$Q*7%ZXG$;Gwy==d|59K;_ zN*e2h8=jo>hsSNy9LX!$J8Z(a9e%!M8^t%xuB&q`;ax|6@*-`*ZZ6vAE#+t9nr z4*0pcV*E5R`a5q&kJe0YG(WDU6FQc^mB^o7-`u=EicddtHD_hT3GuErC>~!6KXFCc z)3aPCf#9ka1{TockdQ_a7EfGmrZb$2VSnFmCTk@&XH`+M!&*nT9GiGSEA1Qj2nY$dj-wg+8b#J zYZ_k1jK`=Jw>E#08Kv!i`oe{P%5^^2hKy{YH!r2m|NBFn)}!BFq3lGVm!G$o*)I%V zq?T~c&(6y`h!7!$=H{F=@*zh^sF)9#?y$%|cGih~+XI=y zL>giuM;4U}8w9=Cm0?Yml$0o_s>;s~ReYr7KXY%?{y!p{J^P|jI zll@|6{<|S{J1LuQC)-b)@8U-MZ$fs(29q;}?Fq7^l$4JG0`{M!rx+a@o7c8o`qtED zan=>*G~L~@7JvA4X2m<*d+wsp2OjwNjC}h>L`zG1`8huU7QdBdL)d&-cUxISr6F#2 z$9!jm3L^!(9qzt0i$-e=`I5|v z3UT2(Up0+i=w%f-NSnS>&9csCx;aj6)!qCoYBs=Fzg>b zbFBwoxwE8f{k537!hIEmY--o9+c4ayh95m}@Ssm5?=2;!hc8*t!U{F;+qZ93EiDv{ zAuRF+2E*b#1$lY30eqDfwN4+@Ru-$5lQau2#PvS5h0}e_SFcsiur78 zxLuBu7>LX24R8l zdwu=-b*kLU)Rg1NlPBrV-`;*}n`Noq6N_R!=>9jUFbKcN`vV)Bn}*Osy92qboM*G{ zZLhUWIteRu<}->qkzR0_se+Bq>U_vDK?Dgq_O<-(!B3w)LAkTDx37l2ZgA#BQn2h5 z9TykjrKP2XiNuh>Rn4nc52(BnVY_(Ba_ST}H%xZ-Q?I8an778NHO8NK66LM9_H|%D zz;;k^!`q~G3_YaSbK6w0?6kSk_g5F6A&@(bKGmBkjU!vEM zR=RS_`Q%0sv_AO8nmkOW1=^M=7=(v?s3g4GEzr1}pZl?p3(H{^M%z*60KbF@By%~#6KE?cHafmbew{vk9I zwqJ0N2=QDWaD^YPx5}zGVJ~W_w1dOtSoLIJDr7Xh|>4+A09Rcq!W?l-}mzUdZE`8T# zQHGKVDyvl8zv{}5J5C#Ra~YHn^Wyl?U@QyjO{ z%=i3)>uIlz5t4k1_B{YCYRl#;0{~m}^JnaIzQNYj$)JF_+j(n!zBTJqx(@*%F{`8` zONwe-r06~&wm&Eg+dXXmb?(B8mcL2k_U)6OKYtz`8zYQS;dExK=i=gzH*b9?6!|8J z=TTZ(xQu^<|8|_|7ya6W4UStQNB`R?m6;?;sTB{{xG5?z(y;Rb<&IxIaS(d{>#n8s zXQlknEnIx9KD|1`NSh^-fp9d3${WV7yFWYmSd_KgfhM$2Jq`*wOl)gQ@VX%c26l7h~zHp8e1P+Mzb**bYfV zn;stB-J1T|JDrIabzRH7i&+nQ`SMgl;L+n^;^GfgQV!~txg55wSdHX5c{22D)Ymm^ zA3G;!fL5NF|J*>?etCKM_8en*0rwRPK=XGM9m(PY@xE_|>}`~l&U>X!w!s?XB~eM} zoB5JMc#u;?M%I*Li`dWL>KD!Y={9QQY1A|Sd8~reXM9CA%#6|JY~|eCin|0&VS^j+ zzlKJ$u(l>=WOQtFbd>+@(l`3)4DEt_p`oF4!q#+;s91sl^3^pqj(uwi|5D<}SyNM! z9;+UV>pB7Z6zwW{S&cAxpk)UJe)z`YXU`rgbDfW5k5b#(Pes)jdR(3#u6<>yYyZtG zy?WTChG$;btxR0o*xptSQ$C3!aF)!pQB=fTJ9uoBNa+v@3*TA#Ah)R!>QQub|K!-9 zjX|e*vDL4n&^POnuSBQErlqG}hIR$Nx`@ln7xC6Z8(UjXs;Z<6g`?A=28!)3iJU+0 z56CWUJi-bCql8l`!m1J{p=-QZ=YMc7Vn5p_6m71ihLI0uq=pLmE{8`*Nc~HHf575c zqjDHr4B55yu|AE6ZWbY?a+0U)&mtmxp+OkgZHSaFY0TW4Klu6AKwmr9PJKQ3^8KtV zzOA)cs{-q_wKY3OM~`85Sy|bIfQC3ZIVYS%)4mga8_>6bW``g!4QAy) zmtoS*06r%_`!@5N)%CiAs$UB}!iXg9zJl@qHZS*H)x$^)gjn6WYJ}-@TFBJ-yXoHl z@27hzVS_4UW(dmyl!dgM9Py`^3x2SeMjC<`o(q}>tH<5CjiaFBM-YC~4~KTvvAeQn zW+%`Qv%sq7*qJjlytfMT(QCQMz((ZY=(yN+iK=&}Bw8AyW`tqqh$UeE&!&EPcrQ_x z8H@S|s=n&0p8&f0e5T8M3aQ?}@uT9j)sJzI$xYJ~cYBCSArp?%OxH+r!6 zhtHqW6_=D4!nLk{&4kJq^fIq_gX?Ag1+Gl&&^yuouSK@{mtUTpteno3Y<{01SyGM< zb+AX^-j%yiKk~!HTUD7#{+{xo@m$l^?i(f#vJV*q)($51`F>8rb=OkX11m;2kd` zy@Yq~G-GIVbU=Q7KJhM7q?dKW8|A2M%&wR9m+bfk2dHmitDV8<&1|9A6_3A44avon|qJ{uH#e0cbdmn!)j=Fmf_gBbF@&aORQj|K97iHXEh{s z6?#v~)wW70wzD7+&z`XX6_T2o3WyCUb)CPnOz!Ql9ll?AyG%=m=wA^4#co^dW))&h zQ!E7zlF-iYYoyh~j#>aZ;|Au?WetrZ=n_kbb)Ty2zZE9V&wn6}gZ*qVHqbF8$7Hep zxv-6#k6>q1TpUZ~<`0IXsFdO?)ZP53xHuC%Iu>chI1&x1w`8=dwYTIbS#i1ETXV`j1t(9J2V(>20_Bql#lt)-_PK&K2!Z{+5CVI8~I83kWTj_ zmq_nNB+8@z|02~q$F-HYa^pTu>&YK;d<4v=CL^7x*Xb_YVf++(-X~b1lJ0;o@vPXq zXU#o5mlHJDFONRv?{_QqaJ5!ekZO$;=TPC{gHrhWD}vdFsG>U<@C9F3JcA&IzXNI3r8^2{n~6MYs76QEMvhDQH+Ff`7Aw2sxj9Q zSeSod1(bSdK`Q~qU@!BF|85b@!uNpm)B*HUO)iKL{+kLPJE$Ak7VXD~NJwhy>-W+J z5rfiDkm<2DqlNxeQxh4CNiYTM@xra%>?hWEy1O$jNlHQS5Lg37CZ>`3`4B3}ovTxt zxoUB^R%>D7*}ejFVtU;%IXpG>zpfd0}THD{soy)&z?Q>!fjp5 z>N$Sm1o4S*GH#7@DJ7+SVd3GxW$f=Kjw%6WjF^p$4V{Z>9_|Om!Z$zvEc91JrYjm# zrMm=G&3xEEfB^=hb^g!AJ%p8%lrw7JKFvD zcr+a_BX(zLekW^N`L@9U-&54$|@nj3~jB*)LM)C)TtVPYy#F__)&bT&8xaJq^!G+ z1@L6tk$h!iG=PsEG!urDh^*3;sPJ%~^+6A+gC{Om0Ue(fwY|9s6VD!x^*LDug~zFg|W8Gg=!M?#ylZpZPNb7#Kfj3bfQ-=F`+RrL7BQ` zHL%Kn)&Tzh1PEA3!6_mDFcnl(TrqM>miG$k&puD<04{fheE{g>kQkhsQ1X@HfCdyiQ2ib6hU4D&pkz zg|&X$;{pQID6lj%WCI~bF!lH;C2ehb-vbH?3f?g>Odxv3_e|$Fd{+Wu;|N?ZkY|yi z$=3fs+4;J;H)O8x&VZ;+rRPx+O2(%!su}`}>sC@$CV1UV&{|y`@6JT&?Fy4PO6mxj zeSGWHV+(lg&QN90>U7U>QBnHJ%1WA)8-4Ey=xm_rge51KXj!(B@X^*wup# z%2n)E>QTY(PIKTix;R>f^!3#8-kkQxXv{tl%`E}0Mh|H)i7+Mr%w;S z=$4p}ApOqmNj5AcbXTI93^_3&D7yFRZN8LACLQM>h<^*23!Q!{}%RfL6ofaUNYjHr*Dkt`%nIIGe5}2nyJ{Pz&C6YS|br}YNfz^&gc`B!=PO>tW*&0~pNpK0i zppYj~UYsg$U$s1R6%c!FWE-x@ zmtQeQy>8@eFe$^o&B0>q=xvwQaTY{v< zbVg7x6h_X$3J>KSeYTj=m2<#I0Z1JQm1n*P2o|=@lW*TlP< z0H(M)BS?>tInRC7Lf)=&ii=mcS3o@tki;*B)U>x>%fBwtKx1tYA0MH?&VK0La1FWxF+ zKx0jCogYkqLZ1Nc1fzxF>e20aY?N?u&C2|c{>nuAr7613x&`uI?wN%jhyUy58npGb z&mTVYye)6MhQ3)%?MQ7`mtumuPa&Hi~x|`GoG#v-xJ%zgBdTM0t1k#B0~I{41;3=ne@VnH6;+LcW=r zj&AeOJk7`O&Ab$^%iFr~zGPdyHR?d2bs>1x} z6Vxr@AuoUV#hJZOJ5lMCqGOLA6^opm9lwsQZdw!w4T+dtJUU_loB8V1E9*%4Pq^Ox z{@Rw7jKThaQs?~_T<2tV@woQ*OC;Rv+mct}u_z*f)kSySfgMU9G}rcAQ{}YpTfFDj zUHK>m_%bf~On#B z;Nakw%6ny9ar%=u#UNZLI_a=Ge*bWIroW7~BVkZZu&i|ciAziLakm}iFLdH8z}@fgnY;Lk-|?B0}DO`cyeyxOZ=|T+54R&u-ge;4w@9 z@JjrV+X)(%fvv6W>h>$tAySG3qzh8))2GOV3m57d8i1@t*Av|Z7aqV`)QpVQ&&D-I z7p=&cv7MbT{51i8R9)Rpt?K97<ujv&5=Xw}s$1fZGxS5)abpaAIZnXw z$7S@vp;~^gbpudWPs76r5ioC6j2EJwlFnE4_44gs2ji=8_ezb(U`rl2e7Ngv3D30~ zH+(U;X??f3lJT}uXR9=cs5jejj9Y>)=Eyk!mx#Epa4~z#2q01x7F^IIBYCup3J9+H zH)e6T?WkQxT?vkhqq20&Ykrvo>)eyCUJZ9;kYv6pGkj>WE^ORDZenI;1nL8<>4V5{ zyF5#M`Q7DgfU(hoyEnD8EbKABDPiZ^wyLlxk`bC3k>^<^kOGLqN7(2%bQV+@xx*< zK1CTV@DN}3Obd8!EQn^F_Bgp6KDF^I zph3hd?GtiP2t^cud3l0Lf@c`Y@7Wu&3uMb z{Skkq-(|IL&0X*GnNKkdVfD7gefdW&4aMcrI+z?p(;TiYhY|)SgX2KC> zMVI-(Aec4>T;n2gB}*8w&Kx~sQE%fnuCTJdsHu^5b8{cvyq!lavE1cuv%UFpJ;!5g zDAf4u;PO(W5URDdx3_PA{zVFG52LvIA!z<+-^m65;4x@rN})7?POtyaULq4T?zPe` z9|{xN$B&nzJ#DS8Px1jLM?gTp|Kc(#Zvp27juJn36*#SUcuS2YaFoowk=TAyz*Qn? zNe{~^31y{pJ=RAC28QC*r-hySl8YBa@n?+q<$_4-0T*Yy%1(wIzO&hiX@FhH0wiy( z0l&fLBt`TiP+7c#$9re{?9Wz4IrbJk1Q`k=*#f>+GwmNSM@cAi z1U!`k`jf-sV0pP+pbco09tK6>O@*h)a*6FyiS|!L9~u2}#w@IcSl{CM%Ozg)^xV;%z6Z;GVhAhQS7b{CQ#Bnqarw$; z<@fL3XWum|i59zi<}7`SI3_nQ?@cflgY&@dT-R+-q^w!A*`TZJvVxihKh#d6JHh^N94h1I4r&u;2fKV`dQ$#YQJ0L00KrKJZcDJe2d z-%>KSSrE|1jK>;+gd!(b-MKk$B>$%rQr@n*R)OW=Oq~)VoL$mBRGL94`KG4(Fo}X^ zAh@ckO1tM4G;!VLSPcHI*w#cM>M_QzV|IJ`t{qOa9YWEMZICJI8@w}E?vKiH5lXQr zIfb$edY+5249VA%6B3SHekDSUD&oOR7eLxQ)=|-EzDwv09Rgf5V?pNzr2q&Asi|FW zNDTjj#l-yeUtjtG%fLoTw{?uJ= zu*$)$UIbH-iSpiv0Z`5?^IC2Y~K8JmI9!!6P08u#;+gDZM%z~UgWuNx{+EU$oF%-;7c^-jSaMzSTNL2w1!@l^`r-N2_VnBwjrc&r!V(e@ zaR|Qu5=^#r3pD&E8(=(HgbOo*k$Gchxpfho+lJ74U}EKkHw2fY@kCoZSm2+Ds)R3r zP5xq9*C_mqntbTt7!?wP?%W-npzrGIaVI!9dd0%S0L+YJVQ}2|aSWaWE-nHk24UTX zg3bg&mN$^03QV$vc<3uj16YlOU&JlAQ52bEHQq^trGh6(D6$AZ2x5oZat3WV_b|7{ zFg$lUK{N6*XU;qg4ZVi57wyT?mj_7}2rOQECACwqY&74zc?0H@N1XyDRxrZYIXFmL zSiJ4L_VU%}s1eu=5^eem;i{iWf_DtD>mdn-Ndz&_Uv&c9tb_Gp0-YEPk?>Uo0}=)D z*x&y?{5P2D*;N#k>It5jWI))UJC7JlI$#c~P7IMab@9~Z_G*v5J=mU6-)wMjuv+7_ zbddR>TMiX?E{@h8kY*JT(R^@YN!>YX66jJL<4xebP+bz7B??cKN{$^rj(TzEC4YLc z#~CbLX8ZO+?g0IzD#?7=f72!!acp0p2(5AigC&WStqo>B)TIp9ECs(SYQ`)s76Ahr zk52K`4;#4!HvPijvtC%5Cls^TE%U;O?%A`4A4I~bEU#^7#Eajf^pAm140PmEo-)S0 zL`1{zHx1zFegMlC_y!hWz<(|WkZ7L`^(|kZ>f7B~ne>skx7GP2c}lkmRn@_wW7}NZ zS@%l{NCE{(uh?_bAtU5XN($6MLO}4ffbxJ4yZ`yK8t`uh@1L@1W*ZPl_Rle+7yyX) zYH;p=rmof)nn5y)fek1J4%%R5@qG|KfMFU4l)dQmiL%Ww0r!jK>^zH#Liu=rO#Jjg z6JJXN&01bQ1X)ad$|869H7={LrzkLx9J&K)I?BT0OP?KtqV+pnvl!ni_nQAaAap}I#hR~Tr(|GH!7|5sG1 z0h*W$)?7H+eyZ~%N)%e0tuZ;n27X>`UW|U~et;TFOJdJkOc5lb8$hqt=#3B6zx=mw z!ACE$AA|;YOjuZhuDoKeH@zhIcXHtAqJf;-4T|9>2A<6pNrGQ4%rtE(%h5cm%)xnX zh9dwE(`r4K1!bV6K19PeUvd)Z#NG2nF!=J{=^4_{|J1g##eMqpk!#nk8A0Jm03X{P zZ-@<~IS;`8^>1YMxD3mDWOVcxfK*N>3+9m7;Tl^Fd3hx0fb`g+45;OUp|`Se+odM6rW=g$68Ge`?n?Kr|myJpE<` z0yDwK<%11?e4FS>qs`Q-c+!=2v)1Iy2u#ll>+4adHK+OGN0}_W3UsW35fNx#){`g6 zK-L1;svc}d98DaJc&J+d8`?l!0$l+m{$ce#7rW~aw5pMz{qX&J1=LUgksNuTkbzOL z2Xo}i*OG&VhK3rgryB7Jd)b+#{AIwU4R+bl)N#4Ts$Q3=FSH)D!fk$QJha&9cpT+S zAOsaA>QVsjvmY^<{QM?N3>&s}!QtCuP%$)uOhJ>c864C@`O2`%N>jG*9eccid2kB) z4sNGINF9uR*0GA2IFNMwfj4LKJpiGmvhkx*`uh4nKmd$&T+L-TcZU@85o&sR%hgv7 zvmq}f1_>3yU`nk4rBy)0lTq(3_gdw8$%L+sfO-9p;rztolh>20z=#8ty}+=q4{d26 z{9(2_;;ivsm8R$YIb(~hUV!fhbm~P&s=D zlqtYoDEJRlQu4GVqy~Y7X)IIvI~L|!`rolIgZe1{YdaLo8SAzOYL_s^>&-gJ*Am}Y zuxt1+yTAX@n(|d*)q7q7V!jL*n>Y zXR71E%1qna63F>XmCyC)V}ih956=sKe;T|yJpRs6;MS^NCqZr%T3-aQ3t0a7vRKA# zbP2+vVi4-VfsASleFwT%b*#9@yD04Dk7&(Y6aN+mB*<~6uN2$o37RM?ew2hKNQ8*ZyX&S+$>@)c9?r~IIJtE z$)pDMp@7rG)#B39zMV~O?)`@chF~M3S|}6~R1R%(4d`=E!aDe%~o%o}4=$<)b z9Uvel3SRH__}Uo3BG`{G=(zzJMtiBpTtHCF^3LXR*m@7$`a}@3I6dh9KihOJ^>I0L z$pg4Y4Ph>=HoQ%PbU0lIAy&7l)&bFUT}|!55lRXSLC+s)pm%X7`vv(tvzXJn+Tf`C z?d~zfoV)Y2Dz8-{0Eh)f2~Rpm@d>vY+{XOkcLrB;q#{d)$tdCtx4d7B(BLlSFU-$&Gh~{ePR(hT_Gx)zQVMg!k%S^ zQ2V*Fkvv`u9my@(YBe5z!(|NTD1)8F0wTh4i?0bE`2b{15ow>r{&CG zMVa2Y-sTK!K#HnScXN0;{u&z=BriX7G=riEP&-Wz-)kNR&^G~`m+M~(a~z3(M~hb1 zJ^rOlsUm0V-?b9Cu|U!Xg+S=@0f`%yD}m|S`czt$5s<5JdsA0~1ovK3RYxZf@{p*)IE2|1hZbx8%vxz80>4&-9f1W3S~Ci{lN7`G zAtUgmYivx0-skIo;FbPtO~R%g1K$^@vZ%C@@ltgT%01vac4zolBI3Q(Ep2<3dvJuJ zDchJwI{%Zzk=nEtD;p7-I07QcBssQzP~2lBW!mFkhAn2uOupx28Y_y%zk>a>4O{j zdiP0^JT*~-H4PC97?B@oG~ZI6R{k4rWWW0}iT!`RyU0p78eRBk+78k#=w^9+(Fe_+ zp!OPICc)NKH8i9@#r4E~q-HPbwgBbX8)Agug?ltHVF8wj>o8lW#f`cCGfNQy;}Sr# z0z8npH>TV=>%J&5d3SPyXBUXxiO$r6?(1{F1k`zCZiBw_hr$M-o}k|f8<;5z_owp% zoQBSQ5k|TI+AA_b*>K%8Q|?At0c6on?C8PA_gZFxavR3m+L7839)^ zCEyJo(2qwz8>j{ZVbkBX4}~f~6wx>Eb%TEDM z)QA!z^|bm1pi&E~r0T%Imd{{q(Z@!XYPIQIT_R+Xc)7 zYS0~ET0^tvE8wAqU;7L=!I7WNouOSkEj*Yng*FV`nYsah-St$mQUDAQAWovXLEnJ{ z03im0@BQ&2V)#vz-UFbh7#SJ)!72kcT4ze3lW38KzX@`^|I+J|o_?!{65^T-z-T1} zCx`$a3da}-K+rlH@>NscQFH+s)-l5~rc-?d+{iH4rl61;tS-R_K!^Yn3d6@uaKu-= zy_UG})v+^$r;S>>wzSYW$(^FMjTNp!V#+59l9uGAbp76U`-oWqB0VI;5_ot*v>$y)yFC zY$OX~^l>1&T6#n+Z=lw$ze!}$f0M|b5jB0|1RDhSNr7_Vrz7u@ghV=!AJ@Uab%2S9 z*ZHy*3cpNEzw1IKs+quh{zJYu%w4fwTerc3KLQ*nP|GNHofQ0r6n=k5VG@E+nG`I2 zg)}QVbOtpAf%&)&jjfx<-X*Szp^6`<@HmJ1mf`e{M#LMabs(^udzQeG^}4v24!+wr zBqW5WDWVn(fJ2_k6mU6KuVS`&@QKUMSr;+)%h8iJASI|Own&5?+W}TB10d8b z2FuUGDHRLADJwIDzNERx9uGm1{YU{GWS*N@QIU}+Wel9h04n_y*v;MqpSa+B-fL`hR0e)OS!f-olcf&O zLp_`}!DnOlLc7G_4fGKjP(M&ns<^ByfL7o0nohCZ#VHG@Mt?Yp9_{&GQf; znF3Pp&~Skg4Fn0xeN9KxSWD@HQE{oLVuZqrUvX#DynOio5N_;mh|3HD;y@?|eEFhj z2nW(2mODU^)&F)BwJZVo8}Rlm7dmi)=Y@el3a06Sg26`=3^I`BmjQ2_Ou!Ld->9f4 zpn!5A8(sv5(%`eOU`v`qnKZs=u#-5?c6EO%-0kWD{{s;MZcHjg$M+f7tr>IkPp_!a zz#NQWhtSX*It_qal82sbN5l<~m+8-1xQ_v6n@`TE($4@>etx!-_zs}CF=!rj$ zu<~&q9KwWpC*eE{d(w{z+YSao%}q1^@cum@aVe0yhG%C{*#a)x5E9x#-P<6a1%kAI zrh35!Me(_#1062nLEYh0jfImr{JQc!j)RH%f}3R!?Z)zqzh|*H+Z!_!puot>?u%po;e+qaf24 z8r59*);Cn4`8iDpY&Aplf@XnWUwjJsA=bnkLC<|z&x1C!4^o$>A&yuv16s{tqz+ZS zW3OkT1d<1$s0LW#xv29gV!x1DZrl37bqThL0PY{@8y9Anm;@m71!1`akk~Yu&3=(m ze-XqAo;qUIjTEzjuK45B&qKTe0(SR-X+yhI7`ek-R_1muR01$#*nwv<)x8%AFIY?c zP)9a!?HbKoj2t37#=^Q{> z;PR?@*P6A0SLprsyhMJ)=76Lv7YecCa6ARTAKWgs=P--c23zdiA1}7=T)%2yxv&hB zfYPA84Sin6P;OFMA6E(Xf5f?^Vs;0Uzr?-S)`s*qQZ+Du%WMQtiY5xbg8d5Oe+75= zRu`jRyzmD}QdopAl>w03WgQ(rQ%s9a3Yrx~v**Ofqa$UGLj;0 zYrWb-M4yP4Ov)%mZ)1zK%Ip7${i7&0Tg3Zadv-1XsG9X6wvj@;@Z;L}FBj2X~2pp1t zoz4O0B08VJ`9!~SVtPZ5{S|E7$e#Zj2gQu|sNcAOq75jAsX1cj&mTQ`^5jNG9NuYY z_PW}Ua~mb+tQV?k-fljb%aY)kd?&0l(>gT70)@ELY7>(FDC_Zz`({mJV@kJ8um0@s z{Ct<&rFz$)dwy`?<#1NO`hdoVvGvi(@aL;bNyL(p)L4+`u4`(NLb^mu(nh$(yiz;M zMpA!S!o_yyf43=o((4hLk-YynW8(xR`c|GRNv;vQ`gigGd>Jx$k zPcazhfmW~0@3bh0My&>55V~(z`)CC0=CWY8|Ib;P%$xt3rTO1*91KJ5a;{+LM!m2} zvTjxFK$-C^=?6*r7!LX0@h>1){*nNLOc#2J8N!N?g5?oC8s;w%u%EOL$_)MO`_ from an input graph using |spanning_tree|_. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. + +We start by generating a grid graph with random weights + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import numpy as np + + # Generate grid graph with random weights + np.random.seed(0) + + g = ig.Graph.Lattice([5, 5], circular=False) + g.es["weight"] = np.random.randint(1, 20, g.ecount()).tolist() + +We then call |spanning_tree|_, making sure to pass in the randomly generated weights. + +.. code-block:: python + + # Generate spanning tree + spanning_tree = g.spanning_tree(weights=None, return_tree=False) + +Finally, we generate the plot the graph and visualise the spanning tree. We also print out the sum of the edges in the MST. + +.. code-block:: python + + # Plot graph + g.es["color"] = "lightgray" + g.es[spanning_tree]["color"] = "midnightblue" + g.es["width"] = 0.5 + g.es[spanning_tree]["width"] = 3.0 + + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + layout=layout, + vertex_color="lightblue", + edge_width=g.es["width"] + ) + plt.show() + + # Print out minimum edge weight sum + print("Minimum edge weight sum:", sum(g.es[mst_edges]["weight"])) + +The final plot looks like this: + +.. figure:: ./figures/minimum_spanning_trees.png + :alt: A visual representation of the spanning tree generated from a grid graph + :align: center + + Minimum spanning tree edges are bolded. + +... and the output looks like this: + +.. code-block:: + + Minimum edge weight sum: 136 + +.. note:: + + The randomised weights may vary depending on the machine that you run this code on. diff --git a/doc/source/tutorials/spanning_trees/assets/spanning_trees.py b/doc/source/tutorials/spanning_trees/assets/spanning_trees.py new file mode 100644 index 000000000..abb99f9d8 --- /dev/null +++ b/doc/source/tutorials/spanning_trees/assets/spanning_trees.py @@ -0,0 +1,38 @@ +import igraph as ig +import matplotlib.pyplot as plt +import numpy as np + +g = ig.Graph.Lattice([6, 6], circular=False) + +# Optional: Rearrange the vertex ids to get a more interesting spanning tree +layout = g.layout("grid") + +np.random.seed(0) +permutation = np.random.permutation(36) +g = g.permute_vertices(permutation.tolist()) + +new_layout = g.layout("grid") +for i in range(36): + new_layout[permutation[i]] = layout[i] +layout = new_layout + +# Generate spanning tree +spanning_tree = g.spanning_tree(weights=None, return_tree=False) + +# Plot graph +g.es["color"] = "lightgray" +g.es[spanning_tree]["color"] = "midnightblue" +g.es["width"] = 0.5 +g.es[spanning_tree]["width"] = 3.0 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_color="lightblue", + edge_width=g.es["width"] +) +plt.show() + + diff --git a/doc/source/tutorials/spanning_trees/figures/spanning_trees.png b/doc/source/tutorials/spanning_trees/figures/spanning_trees.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c530ae5003d1e2ce862b263101bd64992e3fb3 GIT binary patch literal 21803 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 Date: Wed, 5 Jan 2022 10:30:50 +0100 Subject: [PATCH 0837/1892] fix: speed up VertexSeq.select() and EdgeSeq.select() for the whole-graph case, fixes performance problem outlined in #494 --- src/_igraph/edgeseqobject.c | 142 +++++++++++++++++++++----------- src/_igraph/vertexseqobject.c | 151 ++++++++++++++++++++++------------ 2 files changed, 195 insertions(+), 98 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index c2cef6a0f..5a91137fd 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -331,15 +331,19 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values_mapping(igraphmodule_EdgeSeq } /* Handle strings according to the mapping protocol */ - if (PyBaseString_Check(o)) + if (PyBaseString_Check(o)) { return igraphmodule_EdgeSeq_get_attribute_values(self, o); + } /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; args = Py_BuildValue("(O)", o); - if (!args) + + if (!args) { return NULL; + } + result = igraphmodule_EdgeSeq_select(self, args); Py_DECREF(args); return result; @@ -559,23 +563,25 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject igraphmodule_EdgeSeqObject *result; igraphmodule_GraphObject *gr; igraph_integer_t igraph_idx; + igraph_bool_t working_on_whole_graph = igraph_es_is_all(&self->es); + igraph_vector_t v, v2; long i, j, n, m; - gr=self->gref; - result=igraphmodule_EdgeSeq_copy(self); + gr = self->gref; + result = igraphmodule_EdgeSeq_copy(self); if (result == 0) return NULL; /* First, filter by positional arguments */ n = PyTuple_Size(args); - for (i=0; ies); igraph_es_none(&result->es); /* We can simply bail out here */ - return (PyObject*)result; + return (PyObject*) result; } else if (PyCallable_Check(item)) { /* Call the callable for every edge in the current sequence to * determine what's up */ @@ -588,7 +594,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } m = PySequence_Size((PyObject*)result); - for (j=0; jg, self->es, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); - igraphmodule_handle_igraph_error(); - return 0; + + if (!working_on_whole_graph) { + /* Extract the current vertex sequence into a vector */ + if (igraph_vector_init(&v2, 0)) { + igraph_vector_destroy(&v); + igraphmodule_handle_igraph_error(); + return 0; + } + if (igraph_es_as_vector(&gr->g, self->es, &v2)) { + igraph_vector_destroy(&v); + igraph_vector_destroy(&v2); + igraphmodule_handle_igraph_error(); + return 0; + } + m = igraph_vector_size(&v2); + } else { + /* v2 left uninitialized, we are not going to use it as it would + * simply contain integers from 0 to ecount(g)-1 */ + m = igraph_ecount(&gr->g); } - m = igraph_vector_size(&v2); - for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_push_back(&v, working_on_whole_graph ? idx : VECTOR(v2)[idx])) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } } - igraph_vector_destroy(&v2); + + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } + igraph_es_destroy(&result->es); + if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return NULL; } + igraph_vector_destroy(&v); } else { /* Iterators and everything that was not handled directly */ PyObject *iter, *item2; - igraph_vector_t v, v2; /* Allocate stuff */ if (igraph_vector_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } - if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); - igraphmodule_handle_igraph_error(); - return 0; - } - if (igraph_es_as_vector(&gr->g, self->es, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); - igraphmodule_handle_igraph_error(); - return 0; + if (!working_on_whole_graph) { + /* Extract the current vertex sequence into a vector */ + if (igraph_vector_init(&v2, 0)) { + igraph_vector_destroy(&v); + igraphmodule_handle_igraph_error(); + return 0; + } + if (igraph_es_as_vector(&gr->g, self->es, &v2)) { + igraph_vector_destroy(&v); + igraph_vector_destroy(&v2); + igraphmodule_handle_igraph_error(); + return 0; + } + m = igraph_vector_size(&v2); + } else { + /* v2 left uninitialized, we are not going to use it as it would + * simply contain integers from 0 to ecount(g)-1 */ + m = igraph_ecount(&gr->g); } - m = igraph_vector_size(&v2); /* Create an appropriate iterator */ if (PySlice_Check(item)) { @@ -708,7 +742,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject PyObject* range; igraph_bool_t ok; - ok = (PySlice_GetIndicesEx(item, igraph_vector_size(&v2), &start, &stop, &step, &sl) == 0); + ok = (PySlice_GetIndicesEx(item, m, &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); ok = (range != 0); @@ -720,7 +754,9 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } if (!ok) { igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator"); Py_DECREF(result); return 0; @@ -733,13 +769,15 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject /* Did we manage to get an iterator? */ if (iter == 0) { igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } PyErr_SetString(PyExc_TypeError, "invalid edge filter among positional arguments"); Py_DECREF(result); return 0; } /* Do the iteration */ - while ((item2=PyIter_Next(iter)) != 0) { + while ((item2 = PyIter_Next(iter)) != 0) { if (igraphmodule_PyObject_to_integer_t(item2, &igraph_idx)) { /* We simply ignore elements that we don't know */ Py_DECREF(item2); @@ -750,28 +788,38 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject Py_DECREF(result); Py_DECREF(iter); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_push_back(&v, working_on_whole_graph ? igraph_idx : VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } } } + /* Deallocate stuff */ - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } + Py_DECREF(iter); if (PyErr_Occurred()) { igraph_vector_destroy(&v); Py_DECREF(result); return 0; } + igraph_es_destroy(&result->es); + if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 32709b64d..af88b4b1a 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -317,16 +317,19 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values_mapping(igraphmodule_Verte } /* Handle strings according to the mapping protocol */ - if (PyBaseString_Check(o)) + if (PyBaseString_Check(o)) { return igraphmodule_VertexSeq_get_attribute_values(self, o); + } /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; args = Py_BuildValue("(O)", o); - if (!args) + if (!args) { return NULL; + } + result = igraphmodule_VertexSeq_select(self, args); Py_DECREF(args); return result; @@ -585,17 +588,18 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, igraphmodule_VertexSeqObject *result; igraphmodule_GraphObject *gr; igraph_integer_t igraph_idx; + igraph_bool_t working_on_whole_graph = igraph_vs_is_all(&self->vs); + igraph_vector_t v, v2; long i, j, n, m; - gr=self->gref; - result=igraphmodule_VertexSeq_copy(self); - if (result==0) + gr = self->gref; + result = igraphmodule_VertexSeq_copy(self); + if (result == 0) return NULL; /* First, filter by positional arguments */ n = PyTuple_Size(args); - - for (i=0; ivs); igraph_vs_none(&result->vs); /* We can simply bail out here */ - return (PyObject*)result; + return (PyObject*) result; } else if (PyCallable_Check(item)) { /* Call the callable for every vertex in the current sequence to * determine what's up */ @@ -616,7 +620,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } m = PySequence_Size((PyObject*)result); - for (j=0; jg, self->vs, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); - igraphmodule_handle_igraph_error(); - return 0; + + if (!working_on_whole_graph) { + /* Extract the current vertex sequence into a vector */ + if (igraph_vector_init(&v2, 0)) { + igraph_vector_destroy(&v); + igraphmodule_handle_igraph_error(); + return 0; + } + if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) { + igraph_vector_destroy(&v); + igraph_vector_destroy(&v2); + igraphmodule_handle_igraph_error(); + return 0; + } + m = igraph_vector_size(&v2); + } else { + /* v2 left uninitialized, we are not going to use it as it would + * simply contain integers from 0 to vcount(g)-1 */ + m = igraph_vcount(&gr->g); } - m = igraph_vector_size(&v2); - for (; i= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { + if (igraph_vector_push_back(&v, working_on_whole_graph ? idx : VECTOR(v2)[idx])) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } } - igraph_vector_destroy(&v2); + + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } + igraph_vs_destroy(&result->vs); + if (igraph_vs_vector_copy(&result->vs, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return NULL; } + igraph_vector_destroy(&v); } else { /* Iterators, slices and everything that was not handled directly */ PyObject *iter=0, *item2; - igraph_vector_t v, v2; /* Allocate stuff */ if (igraph_vector_init(&v, 0)) { @@ -717,20 +742,28 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, Py_DECREF(result); return 0; } - if (igraph_vector_init(&v2, 0)) { - igraph_vector_destroy(&v); - Py_DECREF(result); - igraphmodule_handle_igraph_error(); - return 0; - } - if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) { - igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); - Py_DECREF(result); - igraphmodule_handle_igraph_error(); - return 0; + + if (!working_on_whole_graph) { + /* Extract the current vertex sequence into a vector */ + if (igraph_vector_init(&v2, 0)) { + igraph_vector_destroy(&v); + Py_DECREF(result); + igraphmodule_handle_igraph_error(); + return 0; + } + if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) { + igraph_vector_destroy(&v); + igraph_vector_destroy(&v2); + Py_DECREF(result); + igraphmodule_handle_igraph_error(); + return 0; + } + m = igraph_vector_size(&v2); + } else { + /* v2 left uninitialized, we are not going to use it as it would + * simply contain integers from 0 to vcount(g)-1 */ + m = igraph_vcount(&gr->g); } - m = igraph_vector_size(&v2); /* Create an appropriate iterator */ if (PySlice_Check(item)) { @@ -739,7 +772,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, PyObject* range; igraph_bool_t ok; - ok = (PySlice_GetIndicesEx(item, igraph_vector_size(&v2), &start, &stop, &step, &sl) == 0); + ok = (PySlice_GetIndicesEx(item, m, &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); ok = (range != 0); @@ -751,7 +784,9 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } if (!ok) { igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator"); Py_DECREF(result); return 0; @@ -764,13 +799,16 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, /* Did we manage to get an iterator? */ if (iter == 0) { igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } PyErr_SetString(PyExc_TypeError, "invalid vertex filter among positional arguments"); Py_DECREF(result); return 0; } + /* Do the iteration */ - while ((item2=PyIter_Next(iter)) != 0) { + while ((item2 = PyIter_Next(iter)) != 0) { if (igraphmodule_PyObject_to_integer_t(item2, &igraph_idx)) { /* We simply ignore elements that we don't know */ Py_DECREF(item2); @@ -781,34 +819,45 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, Py_DECREF(result); Py_DECREF(iter); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } - if (igraph_vector_push_back(&v, VECTOR(v2)[(long int) igraph_idx])) { + if (igraph_vector_push_back(&v, working_on_whole_graph ? igraph_idx : VECTOR(v2)[(long int) igraph_idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } return NULL; } } } + /* Deallocate stuff */ - igraph_vector_destroy(&v2); + if (!working_on_whole_graph) { + igraph_vector_destroy(&v2); + } + Py_DECREF(iter); if (PyErr_Occurred()) { igraph_vector_destroy(&v); Py_DECREF(result); return 0; } + igraph_vs_destroy(&result->vs); + if (igraph_vs_vector_copy(&result->vs, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return NULL; } + igraph_vector_destroy(&v); } } From e003ffbf56e18afcc62afb2aeb9dfc987348a055 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Jan 2022 10:39:37 +0100 Subject: [PATCH 0838/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ced031e44..a599e1f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,17 @@ ## [Unreleased] +### Changed + +- Vendored igraph was updated to version 0.9.6. + ### Fixed +- Fixed a performance bottleneck in `VertexSeq.select()` and `EdgeSeq.select()` + for the case when the `VertexSeq` or the `EdgeSeq` represents the whole + graph. See [#494](https://github.com/igraph/python-igraph/issues/494) for + more details. + - Edge labels now take the curvature of the edge into account, thanks to [@Sriram-Pattabiraman](https://github.com/Sriram-Pattabiraman). ([#457](https://github.com/igraph/python-igraph/pull/457)) From 44da93d935b2a77a72071d97335bfdb330f5243b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 5 Jan 2022 10:57:20 +0100 Subject: [PATCH 0839/1892] fix: do not use Py_BuildValue() for simpler cases --- src/_igraph/edgeseqobject.c | 2 +- src/_igraph/graphobject.c | 59 ++++++++++++++++------------------- src/_igraph/vertexseqobject.c | 2 +- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 5a91137fd..08857503e 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -338,7 +338,7 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values_mapping(igraphmodule_EdgeSeq /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; - args = Py_BuildValue("(O)", o); + args = PyTuple_Pack(1, o); if (!args) { return NULL; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 0de916250..68c2c0eab 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -385,9 +385,7 @@ PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject * self) */ PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) { - PyObject *result; - result = Py_BuildValue("l", (long)igraph_vcount(&self->g)); - return result; + return PyLong_FromLong(igraph_vcount(&self->g)); } /** \ingroup python_interface_graph @@ -397,9 +395,7 @@ PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) */ PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject * self) { - PyObject *result; - result = Py_BuildValue("l", (long)igraph_ecount(&self->g)); - return result; + return PyLong_FromLong(igraph_ecount(&self->g)); } /** \ingroup python_interface_graph @@ -938,7 +934,7 @@ PyObject *igraphmodule_Graph_density(igraphmodule_GraphObject * self, return NULL; } - return Py_BuildValue("d", (double)result); + return PyFloat_FromDouble(result); } /** \ingroup python_interface_graph @@ -1319,7 +1315,7 @@ PyObject *igraphmodule_Graph_reciprocity(igraphmodule_GraphObject * self, return NULL; } - return Py_BuildValue("d", (double)result); + return PyFloat_FromDouble(result); } /** \ingroup python_interface_graph @@ -1483,7 +1479,7 @@ PyObject *igraphmodule_Graph_get_eid(igraphmodule_GraphObject * self, PyObject_IsTrue(directed), PyObject_IsTrue(error))) return igraphmodule_handle_igraph_error(); - return Py_BuildValue("l", (long)result); + return PyLong_FromLong(result); } /** \ingroup python_interface_graph @@ -3700,7 +3696,7 @@ PyObject *igraphmodule_Graph_assortativity_nominal(igraphmodule_GraphObject *sel return NULL; } - return Py_BuildValue("d", (double)(res)); + return PyFloat_FromDouble(res); } /** \ingroup python_interface_graph @@ -3735,7 +3731,7 @@ PyObject *igraphmodule_Graph_assortativity(igraphmodule_GraphObject *self, PyObj return NULL; } - return Py_BuildValue("d", (double)(res)); + return PyFloat_FromDouble(res); } /** \ingroup python_interface_graph @@ -3756,7 +3752,7 @@ PyObject *igraphmodule_Graph_assortativity_degree(igraphmodule_GraphObject *self return NULL; } - return Py_BuildValue("d", (double)(res)); + return PyFloat_FromDouble(res); } /** \ingroup python_interface_graph @@ -4820,7 +4816,7 @@ PyObject *igraphmodule_Graph_edge_connectivity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "source", "target", "checks", NULL }; PyObject *checks = Py_True; - long int source = -1, target = -1, result; + long int source = -1, target = -1; igraph_integer_t res; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|llO", kwlist, @@ -4840,12 +4836,10 @@ PyObject *igraphmodule_Graph_edge_connectivity(igraphmodule_GraphObject *self, } } else { PyErr_SetString(PyExc_ValueError, "if source or target is given, the other one must also be specified"); - return NULL; + return NULL; } - result = res; - - return Py_BuildValue("l", result); + return PyLong_FromLong(res); } /** \ingroup python_interface_graph @@ -6235,7 +6229,7 @@ PyObject *igraphmodule_Graph_transitivity_undirected(igraphmodule_GraphObject { static char *kwlist[] = { "mode", NULL }; igraph_real_t res; - PyObject *r, *mode_o = Py_None; + PyObject *mode_o = Py_None; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) @@ -6250,8 +6244,7 @@ PyObject *igraphmodule_Graph_transitivity_undirected(igraphmodule_GraphObject return NULL; } - r = Py_BuildValue("d", (double)(res)); - return r; + return PyFloat_FromDouble(res); } /** \ingroup python_interface_graph @@ -6264,7 +6257,7 @@ PyObject *igraphmodule_Graph_transitivity_avglocal_undirected(igraphmodule_Graph { static char *kwlist[] = { "mode", NULL }; igraph_real_t res; - PyObject *r, *mode_o = Py_None; + PyObject *mode_o = Py_None; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) @@ -6278,8 +6271,7 @@ PyObject *igraphmodule_Graph_transitivity_avglocal_undirected(igraphmodule_Graph return NULL; } - r = Py_BuildValue("d", (double)(res)); - return r; + return PyFloat_FromDouble(res); } /** \ingroup python_interface_graph @@ -6409,7 +6401,7 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "source", "target", "checks", "neighbors", NULL }; PyObject *checks = Py_True, *neis = Py_None; - long int source = -1, target = -1, result; + long int source = -1, target = -1; igraph_integer_t res; igraph_vconn_nei_t neighbors = IGRAPH_VCONN_NEI_ERROR; @@ -6435,10 +6427,11 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, return NULL; } - if (!IGRAPH_FINITE(res)) return Py_BuildValue("d", (double)res); + if (!IGRAPH_FINITE(res)) { + return PyFloat_FromDouble(res); + } - result = (long)res; - return Py_BuildValue("l", result); + return PyLong_FromLong(res); } /********************************************************************** @@ -9303,7 +9296,7 @@ PyObject *igraphmodule_Graph_count_isomorphisms_vf2(igraphmodule_GraphObject *se if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } if (edge_color2) { igraph_vector_int_destroy(edge_color2); free(edge_color2); } - return Py_BuildValue("l", (long)result); + return PyLong_FromLong(result); } /** \ingroup python_interface_graph @@ -9640,7 +9633,7 @@ PyObject *igraphmodule_Graph_count_subisomorphisms_vf2(igraphmodule_GraphObject if (edge_color1) { igraph_vector_int_destroy(edge_color1); free(edge_color1); } if (edge_color2) { igraph_vector_int_destroy(edge_color2); free(edge_color2); } - return Py_BuildValue("l", (long)result); + return PyLong_FromLong(result); } /** \ingroup python_interface_graph @@ -10334,7 +10327,8 @@ PyObject *igraphmodule_Graph_maxflow_value(igraphmodule_GraphObject * self, } igraph_vector_destroy(&capacity_vector); - return Py_BuildValue("d", (double)result); + + return PyFloat_FromDouble(result); } /** \ingroup python_interface_graph @@ -10614,7 +10608,8 @@ PyObject *igraphmodule_Graph_mincut_value(igraphmodule_GraphObject * self, } igraph_vector_destroy(&capacity_vector); - return Py_BuildValue("d", (double)result); + + return PyFloat_FromDouble(result); } /** \ingroup python_interface_graph @@ -11515,7 +11510,7 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, igraph_vector_destroy(weights); free(weights); } - return Py_BuildValue("d", (double)modularity); + return PyFloat_FromDouble(modularity); } /** diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index af88b4b1a..7b90aeab3 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -324,7 +324,7 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values_mapping(igraphmodule_Verte /* Handle iterables and slices by calling the select() method */ if (PySlice_Check(o) || PyObject_HasAttrString(o, "__iter__")) { PyObject *result, *args; - args = Py_BuildValue("(O)", o); + args = PyTuple_Pack(1, o); if (!args) { return NULL; From bb19ba3914cd011923e472c560a89a0119750eb5 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Wed, 5 Jan 2022 21:49:36 +1100 Subject: [PATCH 0840/1892] Remove numpy dependency --- .../figures/minimum_spanning_trees.png | Bin 21573 -> 21579 bytes .../minimum_spanning_trees.rst | 6 +++--- .../spanning_trees/assets/spanning_trees.py | 11 +++++------ .../spanning_trees/figures/spanning_trees.png | Bin 21803 -> 21739 bytes .../spanning_trees/spanning_trees.rst | 9 +++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png b/doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png index 4d7179457bfb1159501f5c2d75ee28eb4bbcd06b..2c62fb7f234d3c35732204500f83eb8f39e9a8b5 100644 GIT binary patch literal 21579 zcmeIa2UL^U+Aoee>ey#QR8T-iLb^+o;2X&TYiI&Z`qgcSHX7_n!3Kizmz;rnRyzz+k5(4yl%&L{-Wnq7k5t= z$4k4s?XG(`y1U6qD@e;8+;zp%^QwokjEw7Fen8s&x`Ryn#hEgAku_J(ntSl^ZMum5 zUY4ej>d41uSg3jOxRG!4cz2N1Gq3Wc>G@svcip-b*)JS#?-!;R(@?u-0 zqMeDo6WwI^>(*F>9D~lo-3GYv1Xu4?igHiuHBpOVzxB&~7L$iI+)wCQb1~t>iEi&rMXHtDz@e(`%lP=-9^qtcgp1=NC-5!j<7;2P z@(1{){r(&9ts^IveaFZ5T5#>{1cE@-o ztNE~vqn=K^@{O% zVjJj#HEx(_9-kn@?L7glbScWV9k-Rjj*yHDJGK`dw2(#+IlNngKS zmJ4EgwiJ0d@Ne02xg*!nw(7C4^W&XLmmH;S18uQsmOHDq4@`uvv8ubfVTb&+{*%@R zWlVc7$_njVyb)R8wnwwJuKtsQXqIt*zSIoSRCls$KDNKVzbp2Dnwqt~zP?juer7^q zVxBWqdasz+m6@+K5#x$}GnX^1OH3xq7bomGPnjcb=HMPI7^`d7M&|1?CE%IGnK6vop*|TR!S=J>Mp>?K1_mrz>tJY>%SeaD@>eGZz(nFNaXd9el`5S(<99>bv@aLNF~+Gu70*UsF>fTeUqbH1s+}?#6~4 zM?3>!C8wDzW4qdC2ha~bdbD0qob$Axktk7dZ@6`0>cYb`O-j$I{A!7K^1Uj~%;Vk$XjdoLg5{=f&gr-TCF0La7!q zC7ESyU}1p|-l6F91pSu;fmT;YYS}OZsr)Er}sqKsxW@V>W#kgA;bovMAi1ep&`6uONt0? ztoV?|f^;L_`@{QmV_Vy#Eaeq=0u%<3XE00ZTeV@w((9fW#WRa@!X^Y01r6;jA`|S- zq0gl(X+^`ahD4jPub#?zuAN89xO1IsHl2u8Aqz7|8lN4FjQCJrzdm9(;_1^@M_fBv zkKR_vFwZ%?Y}qn5Qe(}IHjHsrzPO4PEh#BUEIcBDU{mHFnzU}4^hliy>6w_Fot^cx znQ5Dav6C&=&mU`So?{=Jot-W3-cw4L7!GDIs)l6(SFilxx#rokdbi_ub^pj8&|ST8 zyC8u=Y-k~3nXiQuip#15vvYdWrr$)A&eTdqa2YE$sm4Qx(IhQ#C-W{=tWukLyTVj8 z-?CtvGpF#*9nIq1@yCOQ=Xw1sEqK|$z`$U+)_jlQ#?gTgjkc-23QFNM+XD6HiWwxl zmFszR*4MDeBd(Dt=UyfZ#|G%=q#81Y$)-9wkHyjp3l|<#7iYKO`)TZ)OIQt`g{h0@ zvpR78|fE#8egcmOAT_laP{?1?h^?!GdXT& zhl+c7a|JUDM$2Pim9Dw%gM%xj$&(+S?vap|&YI55ckL?F-@A7&1guvePEMvQ^y+ttM!m6b5V~{suG80#PbnQxBK`dQ)QfmF zSeBg{qh5|Z6y?4}NC@xNUF-wlsI1P&Ye3@`%QD~8{igUu}ovn z{2>QD?0(f$X=``=#kp~3S>uMmuV1eWH^xM&`eiR)j-OwmgpWyC<{Pys-g6Et4W|<| z!^CO5BwVG&Wc!;FnU)1@4T`;EZ`NmJX%L1?4Ga=qyx5+clHyeTSeVvTlv6EtHjlyC z;M$wDmH(aF{u{5)!FHJCMJgyWtYahPow3%{u{CwZ?7kI|OU;sz%FH#2drR{}LpO(q zho|c&o{n(EjV4E2e$@2(VnvoehsTwnEW9zzdi3exw1<-_DRFgq+w2)}V^)@dWCoOS zom56~50|br2c?^?LCs>0GWTiH+cFKcv>t4gu?eL3g#LB44Gs2i!VZs9s~eJ=habJ>0PC**OA2LbTW$Xp5)Z zy0zTS!GRv*)1&X=lHor$c0e;y*7hzuvBX%l0NT6Nq8UdQXXZ&u)^UL|_n~{GglO>E zU3>e?w++p=RF{wEcRmXXON7E55;&PIQ$IPZzQplph*H#@@A3$FUr`Yb?c$eTzS|&p z_@rgNOA$?_(K$+{adI>@t}S%0_7;Br#KlPxshPV;ZT3lZ_Ch~LuRsrqc)DRKEm6vn z$xhLwq+JVh5;ioudYZH&C}LuVnwF$V##QI?j~~y*9KDuMyZBgCBdaQShjY~})EDm;C_JT&WnVql4xiTe_G?Z(v})Z#a$W7GtWDGdd&Vuhn~QSVGOY=)1*p^qy198L!d*?LcOIY#TGQe?}vGCUfR zS(U-U&KxdRa%gyR(!Iaxu^pEBmSa`H*cMwQc+5AZCG}xz9(~>66r<3uSHBy1dy|zn zQKQip893B-#fNn(yn4fSmyY24$T5ibHLlxI|AaLWZ($I>&ClyU^Y1`EwvWlw6 zWL;>uCTGw7dPY4oCF>$KtB$yX=t$-A^4TDf|)#CD|F^2zy~5L~TcVofVk_PpQXmSeQA|bmHdCn`<|1qJDXIo5`eN0*=Vj zwyfP%YGQAnvh|=@JZxMG;Y!KD;bG^VQa@$SktfAIlQx;Q&!w&LVf%E8m0r60j^|Nx zuMM2;_M%!_WM9575-=tk#A6N9D1?ZOJCEwU!N6;+TE9I$@l1%*yIU*$hh93&PFIUM ze|)mL_-fy+J4-9u@DpsyV$XEgjHxN-qi7UU4CSFrc^d3A)Fs$c6`Ryvw3k?s8S_ui zh&0u|lw&@`aDLW~kTwnsEbYj5C6tz`Zc08CbD2*@!L944obS{HIRIEK(BKFIzA;c( z!@|OBAIXaE-CKF~Ff<9%E)7LR>MwWiM*1;^1U2oO5>AO|(PHMtKHCB`lIeUN8R@iq z`SSXO=>f_7^HE0{zFV~_l7F9$kxOTJP|4HFCK+aZZ%TVois?k#>c=TQlRZ_Vo+d6T z0dpA$aweV*o-wi_8g{dwRWzPGEQ(!tb&o$GYheAZ(&phfToz#15$GVf$`7b(zyDtE z;Z`Yp*%E1Kkwh>|)$t#Bb+7A1t`HPNiLSqRw(dUgq1zhE_K3PQn>#0EI_OL zOP$?5y_pEK(5b|Epd5zXOrMD^B?b2$tBv;(FImE-xOMwBK)sR1Uu`mr8H)p=OKIvs z>?`#zWC6h|<9Ma3o8N8Re`87+`U0xpB0;nI016stN4*gg!%mWYsIM5MRWoS}#^iE9!0M(M?o!NHU zK}+0u2`MRK0O@Bu*r7o8v{@`xq>@L9ePi?iO?3V0+*w2Bcqg^rvqwrw>U`C9M2L7i zo<-r+S3jRPf#?rHe{0vQK^-{b@fy)nP&<`^*tz`!1I+%1GI)TTCe`WuCYct=+{Jlk z*qbJ2rkx@h&%w)@hKZjK6%*LDP1_)RCGq&}RRW88e8hwM_n!rpWB`2`JwAc0TWP_H zJ$leR5jWTD2pm zYuBx7c_b*8@z`Krw2F@oS!1a*HfYWq8hRD&s0|%RmyqnGU(hE391AQ;H&h}^Us6gc z)AO9BW{urqyc4Y2a1x1>@ABE;jqB`46Afqwc4@KKxx3hFYYM|HqRqs}$mkR+Ea}Ua z3zZ)}i~!H0RzBP|I7ud6x6&}#P+C>cizS3hn$ln$8+m(sSI+&0Ul8@&y?ZxYV$Pvt zck@!;H;7liaosD|=@_?qY$IzqZmKK2@f7Bms_`&=7+?aVcfI5l&`#()|m!NN7 z>rIZp%9L&47%C|#!3zzH^&0PlUfG%N+EN=XDbp#kb!!TbyXXvfaO+;ihKRO)xRqw3 zs8kh!@zEOxX45)u+5+%Q;HvVox?+-u`&u3PcL zUu(k9H391~kR_{36rKppz3^^1^zl)sid$22b%23hx^(GTWF#K8Gad?eM0YRVSW>~c z?Hu%{OivfsDE_k}eXo+r4=5^{Hix*6v5TOVTbKGawLA^fI(hOJpo_0EGBUL00W}d| zNjSBpJzZI&x9#exA8ZnxsaZfgLnK^reRsAQnVF^S)qb7^WMHcp!&=Uvu@$&Cy)GX% z=qS`pDqOCD|LhgGK6C!YOMegNB+GaA0k3a?;v4?-ss8j~c4{0J-`Z-#ohu+QFJF#p z0eAzu!4V#_KWDmHvgc;(%a`fhB|Ze)5^w9iSuAX`764eeL5to9do_oM{#54JBECUH z)eMV`u0G!ITjP66SuZ4i7G5bLNM!{!*X8qJfh}A1tEgB`mNFh+vbCk;IOu9N!y3g0 zI`02XjDTD4G}doOQ1{H7kgf(d_xV9{1e;Mm3!fm(`rQ{46r_F5NdZ%U^iQ_i#xv!!U-0NUQ@n zRzgCedF(R+uK2;a2+2KrPTaqLpTgU^D}J-K#$BPbRpo2G)^_AMJBS(ksbD$2;nh1e zu+i?zWi_%0k_{8X8bX_P9=!nMNCYV~aAhu4A)@X&G0JxO*C+L3n5HHs_RtHR;OSq4 zLVNz|)z?LgMwJGKxFCC1Um3mbVRs9QNI^OKN6>U+q1W0^eR(IYr1ZJ?OB(;t72m`| zD^)-d|CWaMP2QTA9sS9RKG$#8IX8*Z?CX2Cb?=N+J<)s1wr#NE&yRN&m|nOLPq`Mj zkwFlQB~5Ml*Kp;3PucuKbi-#H)YWmgFIGb)-UPr=nI5>B;St<2+6o%Vv+(fbu`w6e zg6X<(>NAXi$wAtMZ@?`?_C~}|t4*ZN(9G-#6yb(X zuTGqYI{Qd0?8y_o!E#t7awN{6%z4=NYu2rkTd`{WAh}CauvQg5oeZ-onlWE9xY(d2B5fsWd zwCdslkVoJx@z2In3+n67)n)s2GPZfeRcyCa{Umpj08II|xK4E1!@)tC%E8mOZAJAM zZLVUPelG>tV-yJW8*OP#qn)w?tVn1F>7WHNp`%7Gdu28 zTm+ObK4%3|gZRFE)!S{)X=&98kl%WawKvU9bax(&X?)-cn^EE2yLa}jY5H#D(K-gK zO$87N(>=#Tc~h(R)VTDPcaJLt`C+TJdw}}DsMw^j-S*K-kg=-CeExI}-g$na`*f%u zYcN8}FAx(a8n}(h_uc?5-hZ~~jF)NGZGX77Kqh?f=+W%Lz#^OTr4wpM zU9_s7fn|Y9Q|p4M5t+o+Zd$s#L*9i`;qTM4)9&)+G{CQJ=lopV%b3qWD^l1IoP7B;YG)c=%32h3EKZuA}4cHRx``+I{@CR0F0EMd)Cyk%By=-sa zdY|ba;BJO9E{auPA$Fgt8`lOPnOH=Wbk3B>&@c;L{(T*2<7vnBo=p5cE<53<|* zHnQo@Ki`6V+x;Yqee2dO_;~yB+`29HoOujt<*Odwfen>aRZj4TX`f!*wiKaKSeaPY zSS*upkCN6juF&`-h6}1rS?J1jTdx2bM$$7-n*qW^XJ+R^1#I;D_hQ{Ye0n=fjWaI2 z$Tc4HZ~MAhG%$XLTjBBfUfhzxyq8_3@g3%Bfp_xklA=43Ah zHcb(2I_omIuFk^|`@8s7RZY!@O7GnN;XXos&t)(ZbJZTob*;Phr&U!4RIok5W2n72 zE)_R=PZXQhR!5r9+d(I$rFmnX-z@{-ME_FB&mhU9XSi>qE-bviwVcIT3BT7dI~aj+0$zbgK`xf-&%#tI z=qn5kn_^BmIAd4U?r4i6jFs}*GRzYJQw9qu)P`0QgPGep%B`iuZ*`-K0G)S~tKjT8 zRHCZj*v2V-tQHnQ_+9NXXCJn>w^8`(@Ng>d6NH3_3;SO{9Uku~vjhxILN{fyyQF~U zG2S6Wmf=nMF$@y)fdWKt$nc2hLWzP@CQB!xQ>viR(66x*2@F!r} z3SiC5|FXFBS7l5)6rgniT-`Si)S6)~r#AC(kN^4z8TH81NjV7_AC>3**=j%DYh z@BAI+z2acvt=q{6RE6ZbQ0P(W#)(zu@m}XHz7yoS%~}_`&+gAOd-Fb%1x>*VKE1>w zfTTk7AJhG(q%h@HI36QTQo0s!dx1^h^r>#Y;TX4uVLBr$DJ?BcQbfbCSu7J=9^oc2 z7LNnJ2OdC{WLD126|3RetljE{#~CG|u+o5j*w!{Snw0r757z8rO>p!Sk(viACEX`Z z-RVclagXOq#y8)YE=iUYrk!0E`y$@3Iz(cxl6g~86JqXvW94OhP`vrp0KVUm?U$n? zqLj9<=1oUjZfdPewqn&4T(d}}?yttDX}euNm%bFmUczR<7l=j|v9C8f@bwAI0iRth z5~z1?qli(|oUp=v@94+^_B8(lBl~bJy~3;Z?4n75=R}5=GZhaAW9z;->3Xul?_Zmq zAG#57RXN5Uv}AF&F|z?szQhDIt9pBTKY$wcSB0!CnFTwb>gZ0a0K?-br#?;J_C>G4 zZ#vr)W79W!Z*<0z7AI>ob=QyXq;=#GDEg&ZUU4Mw4gF_o_I*=}6uYk8-nsGK zaE1RXI*SDoBePLuGVM%=$lCSmjnE5k63HNvcpW*f^ivlsh56>f*4y6M?qxF=P z06;Sy#DeBT0sTqg(ueQM*ffH~fdfr=V}d*odSteM)fl^BVg=|7=^({p@-w08Y)ziF ze);mH#p??#A8yc6+RM8t5>+cXd4CO}^b2lafbl*N_Fp0e<@b$gK(27k=6t9$++XLX3` z%&!)CPRT(14fzOHtA%~`OG`I`UOM^GA+~9}pf_t~<~oRamcrEpqj{E!Yll3ylf;c$ zzG4M>OMSj260H$Qh!$o3dFq_06TyOVRTT&HBc?YWI>`US5ApEMRvsi^!s&2_BFa3s zY~GvzMSbO}RmE}%x*$ikLZ`@l+?Rt?eb@Ha$KA_WDezDX;Grn?`0gRMNErEGahw5B z3W!JW>ZidUgH||yOu2p8${%cyV2(N;0>ZPip2F&ZW-Y0@)XzB%K)MeS2K=n+FAAF(o!oq`}$9bA?nCMG8bNb1O!#3z5DhNK%4l*I$Lz~`0uGjXUPY6ms}U?12Cm`aThAqA~#*RCNT&*U)3&LE0_ zV6y>$mC=%U3g0cK_|*z=P_wSYOZXY~a@vQBT4w)(Ps#(4pl zOy2cDEd)BvZ!Yy? zfXEm1>#x5eDHh17@n|{FQ-v#^jzN{q-X%y|-ngTJ;5G8;I22Zk0=F0u=*AC1Zq?M+ zw?gxykZ`z%{QeODAF`UgoH00V-Vyhn3}jVev781U1?v)T${EohBge&cGNtk05=oh7 zp9H{GuuE_Z>hv`voaejuW-2Zm(v1`(PK-VOOVveGm5}Gzo0U{c>`K zq4Ks>>yZM5_IgjyyfxC_9|Q**BRGv+bOkI+XAQ>{94@B{g53u@n?l5BAYpj*CXrT9 z(Lk?BGQ|W@XudW?0Ih5$5ohhVm`q-tK~q;LX=5ltkYJxq^e4;`+f)<3a5RC%7}gF2 ztt52~zqr|xE)^pOED|2upgu27l<0z3Zvr?3pl23HUs7hT-_|Znd98Y_2bJ?tl7xG8 zh^S)KcEdjxOmabag^e!CzjdoUSV!lf&^4Ucq;|QSJ7-BqWaR>Ih?KT2HWRL(8x6Bc zpa4luAf;cMVVSASkgIwDTMqXBcK*$qFTqD{fPH!%#5u2b`umV><>AE-?Z{-H9~6#% zE3eg8a-%Qr!NZ5)&!49NP>?)y=o9Uz`oKSxU;q>ly`h&+fZO$NzTN*UQC8JU<9kbn zr40*87qm_Uq=0p>XGiyFXz*;(Hv*2x&Q?{5*&8aRL0Sb;=+@L3;olGo0EX)AZ?yqc zN8MSsEi!H7%AV0|OC!%*b5QGQ$m9a$l+PtTL_q+ejv!egbK}I_^|F{CW;o@I#1MeE z%gL-f=WV0YEGV*3qb;dXjWH_U6cz{y$pMe@00&2FQAE}E)3+d$OZz8z$L0^Jv!70g z%gB&z&4Z`QSs;f0W4fwHhCzshV9JZa!lV2G0(S5`&qJRs8hETy4??e0gWaP^4(CL7 zA4K;;j_Aa%-EqX_6Esb)H>FlV_bRVk9b4hlQyeUIKt}FFTu`CO{m%T4BpWrvXyFOw zhz$c=mf_M&Nd{3zT!BxA)Qx)5pf|PwVI)E}%Zt`p6Kd6Slmzb&*`YH~Eh(7=J$P_v z96x8AuGLfF=8#Y*rU>;TM+ zY6Rx8>b5O5R8@R7?%~Z;Vo{h1q?&pVfTe1b0~fABS}m-Ox0&47cm&F`_>m)Rq33#( zNl<)WG&eWbR}vcKRn`tKhN0d$HCOlZWs>~W9+T476hv1c8@(F`~UX(ZiH?DRv-*-##fjMEBr zE1f>QVdv4;&F4@u2skwo0^I8QB^jNtLjC6_tOwCm6{9FdQql-W3?e~Y#fLQ(#Iq#s zB-;dyE95W_&kdVnk`HdRDIgQ>kXW)5i=TZx+R>ug_HdHWefi0JiDBHQq2W>%yzY zk#mtGirbB;8ErY07bzzvS24)?UE;}$q&p#Q4P6e!C_*7#u}9Mh7HV=3V(XKnB^$Uh za2wN@2YY}H=C|Q1D6FDvac2lou~`8%lh}C`V0%9|ha^h?KZVj;LX%a+=~EFi2We8_ z`?bx&vTvwCV>h0@vEX*7!rs|L&`<1iRxtIR+hJNd2`RHyXy-_FQ-c@>@?11<*h(3Q zB=$>+Af+ZRGUxRnO~voz)22B+7*!0Y;txVXh!iW+>wlkt65~#m;wAQP5Ry-8uNGeU zX-8WxrOm>tP+7yYEr~!UKNz0ei%bM~Y9Q zwLtspJ}=Q7+jnMsj4B!V+6T!gZ#yJ)9zJ|H_e#@GnKoq>q3EHGLU64GB4%Sv^d(Sm ztYUkg?m3fXVL@a~ruPp{;iHwkwDz2Sqz7&8h)cWPwYk~mX}G81j}II;P&8y)7|I11 zR=t2HF?jVFHY+Wd=|JJQm9y--0~rmWN#JPGVgn}h&z*Zz&Y95$f)jE%?XRgS5EzC4 z>f?Lkhe*-OcN}@v!U}@;QfveUYmUMw<*cC{5Sv1r6X95~(Ud5+8MBS4Ip;Rqy5$rY zc#4;H1%JpD%3({v&4wEy72F}%Z) zRZT1~i!l0Rs#Q#!B;>4m4w1CswxWtC2}wy?(Ltjf4prI#z#R zVBNa4&^Tf-Zd3@o@Pjx->W}joYkvg-i)pm+)OQ*rwuG`JLvFvumRQ4xtODd|<-MR? zhh+^oQQyf455Vvh^b3qPj$o3BR1(1P14tGv4d2tu0m4D`&ILJyP#)&K#EWoZUi*iDRnhd`_t$}U>Oe(4|v+#;f_3Y63^;ooTPIzh3Qbqfr8Om${IAU ztF4`dr*YuWq1Vl#`!xnL$(Z<*g`LODQUKZgm}xOeHHYAIV^mC;!f4Q;7#eO zvywov!ll1{tp|`iQr*1Itpp{^+L2)Kv3|&eU>p55G!+7W66ARev%6Cgp#Je zhugo6^a;F4NM-L2v40xq4oPdE)va%At6NKSMe}~8#Vge<;omx!KFt3&)uuDX-1Cj@B}O%ZRVb!!F<0?*iV@DO-nFA}w z{mcbBn0?B2NkIflWuLaWfNev=Lcf2l)&}TyG)5=KV_1h@(K};$eqJ&3 zkr)!4Aa11qQ44vU)E3$c8;D6ker%|jgJN1cHFl; zCafTaa}L7NAR2*MVjR9GZJB?rpzHcWi2k&K!QT+8W{E@zmkTlwzD6Rwy83WWae9n&h zPMDLqk#7+asz7ELtq}0?n(P6(IF7$g!YvlyTHfDT2V5={9B~v!uz;8p>I7WwByQg2 zii|-wiwip_GuIW=AGGz6SFM;jYeR|oBX{-blOC|KV<4{~$zpD@7lB(KgS|QLg3kV3 z&Wm0;*Wuie;}8O42n4{Q#%Pa2U1%kk%0SIF-eTV-+EvB3722IFSngHZZQ-+hb6~H2 zRtIv5WX^Lh4)tY^!)H|pMJQcOfJz6VXnGhh0kRNJpT4_;-@gFVB`B!kK%b%^ig~FM zfM2j!&ZWw=x|K{#h#<(_UcKoEV1IcCzP(X?YziAcYIC=Xzu?$re39O1fY?b=W=E+cMf)>j-e|JU4o0Ytr^1sK@a#JZJ?=WER~M_bMy z8nrUL6yxVtWMBW{6;cR5q|Z@)Og>b#ACe@XLWO@|-wr_HhO!q;OcNds*{&0$EUD3I z(I zsy6c9A(EqciTke1m;d`x3zSc;!|)7)XGE zFtG3loS52C&zYG?uVPTGa{ZZ3zw?ODB*4{1P@UN0?l|Xb%9G7`&Za@&v4`iAAbKVN z+Ae6AU=IeY3-yZw9r>>SDU3ZgZaIjB&-@TV5g8koEuz_(%lQ|F-t{jncZQ7{(dFIgT3b`252b^{Im(hT zcE|o%Qt18XR;TUqSDt{??e*pDGT6AmAmmzTKR=jWn8F$s@gLcZmVMAc-Y%zhtG^Sc zAWCup@~v)2rx#Lix;#-#mu7r+h%?{Or42<4k_iBI_SDqJs&y8>wn-~ys9gPW1MX|U zIk>TofUX2Ju%${~v}a!Lg4XwbXYl#$%@xGLIV_LxlDXRF%lciY1x_hLYWUxrAN;00 zp-%-J!BV(#A8NFuNTs0Svp@bwDjV}=dp@PS3ET+V>-4`gT>kgQ8&T8ZME`eTo^TZA z0Z$Ehzl3C6Sc~~jnllXNU8yaO*Ccx1vHx6hnm3CDfs|iV)cx*8VJ85Em&Aa6{!%x0 zKt@Ip2&1^TcvUV`@b6ZxdN}1+GtVW&ZxK!Qst@=g{5<6kz}&4+`T$$3C!o_i@NXXSJhr zH^|1#$Y%ipi3f{B>)g3kkYp49I|t2ub^yTPMy3Tb2wImeC4dYg-D&@*iCpJMd|1YXiIq zkPu$Hr@?u5_Hbu`yH9|Qdkn@4{PfPVhd~|B-WxKh%_#9)MR&(7M(qv32mtQHM2gb3 zW-a?A83st05L%>V6|QD3h;FrEDo1>JeYL@Yvv1{hD;;4l4@F9$Akgz&V6MxlDWTGM zJ{?0UhvsVPxcEZW76CAD7|wzXR#5VjKa+!}gYEvLqVJPCma!v5BVUG01Y!VPb!NU` zqWUO=$7INx%0mcR7t>8K0p~LlR7Tzu5l!enIcR8Ts2!O%K6NsW>b!27|E`M-h^mKn z@j^q1WFnLnh)1Jb4-fUf|S?K=NG=s29=qAcGLVsQdU)5A;bV zg>7TE!Ph>FTc{Aty*hmHso2kym=B8dSE7q{nlQ+zy8{5qUf|2=Gr7Ads8)*$kgW$Z==Mdi*bh(NloCw zqWPSusVTw)y*2}Hux)6cCg>^O6wqZWR$YO0Z`u{YGHx&(o^Ox0VHY^WK^Q+UbLdtO zf@B`EBl@Sho0-M91xu=Hq-d?U&Ia*vU@|M0;Jm8 z()1G#qO4l4E}HZKElcm}>wqlB%(bwT35>;8Q_rYV&vaaThk1OVmc558ir_z~;TPXun34R8= zhBm;8iS6y}4}8`(LQWqHGFo%;Lzu@zDQZv(XxRf$Tqg6$w3$0B>l)w_$htyyAUt5^ z!hm+U5(yv?cqu4KW5^h4@S6H^9KkJQ*+ZG}s*@`4J-80-|He&T>tM_;QrQcy-jQug zbY~j{3n`|z$=+G%Fk8~(Gg{u1m18oN91e%{gU>}CsnD`bs%I@Ch7_Gzw+~!h zFs>)}P04|Adl9C$*d80`WCfu8LV#(*A=C?sqZeo48ltQloTnUF-d+GfioJu5S3T1T z-T9bL_~@Zt*WLiDZEtu^kD0^DZKA3-$uLR*;LH$cp1|hK*D2(opDEyF?0me+q4nINxpoAwbE#j7llsBb~%nS_x@dye7tk;8F zHcUDyz_b#I_Qq})Kb7TxMXU?Wg+WLGVlV)NkM{=6$2hDA5Ns38I1TbE%5b{(sG`;h z<`A(>7RWZGCTw4KbiEIkj#)BT;&CDMD%%jFVmduN%?48)kzQe?>mR`Dg=A#!o)Fap zAQH4~q=h>uVF3plz%-Ew4D^U-(Sz_RB*?98*na33s`s~6uA8lwBafgV=O?>Qc=o+t zxk-FZ8j_xk|5OO5oaoIAjE-M37FIe&kmM=uAK@>3-n-1kD+>fxFu*5OIX;IK4V~wY}&fI7T1Dq zlhJY*$QmIK%d>ZdPhQ}@i$U1h>Y?mu6l8&nYb&s3$ckGE*EoYE3GSPwgp7a}YMJL0 zj&vfB$IOH)>1ew3A4l1V3#Y8CtX!`B+TygTh4KfE{C$JWhjlmG0RK8wfQ*G$03_2ISBD-iV)% zOoMS7fu&NIa6>U@(6)2#qzCH$HYlV&m=^|W8j3a{7JB?}FVvd9P8(saUq4LlbVe%$ zq)y@y$a5ol9?=a$iMut?1iLzWWDgn-if%4}g|7p0oj-dtb#S=akmrxsI?(41;O~|B z;8wbJRpLQE(;M z7R`2nm~-mk)=@~CO?zG@&i%Q2!BrYvGNhQ}V7L&e14x?#mS0`iG4sbp8!mv zU=!1C1>C1KP6D4F0t-(TEaDW9&+Iu1(?j4hx2>Gt3Apw}44=(*38GH*el7F1)L=!i!E3Zub2K+(_#j~}-|4)xiSC-KmOG5Nia z<4A{j-{T7~sUOyO z6w-~!u0WKGBBZT7M?UQaXAVp~1#28^PBiv}`Z#R#lHH$|@DCYb@XFaZF8j7t4#`vUBKw19PSF1Oh^n&XLhsdPDXQe@s@wpgE%DDyA!|67E ziFSl&cw4{dB?m!R7|o$Vx#;GZc{yTLaTgWQaVI*ls_B`Q`B$7clK5c^H+ckCu|env z?_!yX`{TKBl?;D8(iH5o6y1yf{p4YIUV9hee+K$< zxzRG}xDXLF+TF{q*R2KF1`cDQxa%=6H~!{S8Zeg#V1HY{DM6jsn@3~poPOA11aX4s z-oIDu=RTfs%L!a;O3SEx||bdGHpDh47|5sVCpco{n2TBQfm%Q8;B)IL%sth z@Jb?1y|qD^Y!HARw8%ja_%4(5M^UsBZ2fzOM3GhQIj1WpdoUgL7 z5`709!T^TUtNs;s-Iblg^By28Hf!*vLnM19M@7%{sFR#CN!oNeq=SlqHo)AY3yMs* zHOv}9XfBrYS`L;jqHN5GmNQZb%2yg^ND_w@XmNC7E2E^9y5~Nn51a`PjYg^UO?#O- ze=~1lg6?xVd>^J+%=d-tG~)bXHm=)YIB34h_R-wFaeer2yCjk3=M7P;zI{W(5`RPo zB*7Q5xd;a;_ktx_N5x_fC4H(C^UXBKR!RH7k7AfToY8T2S5q4p2B9`t&l&?RK@lK_f75D29b_i}P=JfN#Ss ze^Cwq{_h*DCa;_QP$ER%{5P2f-T2>*Q^A=4iu!*CF#g|g{v>0G@8a4!G{SIt1Uxf7 O%~LujvwpsC>wf`eFWZ~| literal 21573 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

    U7wH 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 literal 21803 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 Date: Thu, 6 Jan 2022 08:37:40 +0100 Subject: [PATCH 0841/1892] chore: updated vendored igraph to 0.9.6 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index ee7875fd0..2fe864088 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit ee7875fd026600d8a47dbb6c456f0195e5e9a260 +Subproject commit 2fe8640888d19c146e4c8970478a3485a3e485e3 From e9f83e8af08f24ea025596e745917197d8b44d94 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 6 Jan 2022 09:16:39 +0100 Subject: [PATCH 0842/1892] fix: interfaces/ folder should not be pruned from the source tarball any more --- MANIFEST.in | 1 - 1 file changed, 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 65b187f3e..1a25d4486 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,5 +4,4 @@ include scripts/mkdoc.sh include tests/*.py graft vendor/source/igraph -prune vendor/source/igraph/interfaces From 789c89adf336694c5a90d44752d6ae218499a429 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Jan 2022 19:37:20 +1100 Subject: [PATCH 0843/1892] Postprocess API for Jekyll if needed --- doc/source/conf.py | 7 +- doc/source/sphinxext/postprocess_api.py | 56 +++++++++ ...2.2.patch => 0001-Old-patch-renewed.patch} | 115 ++++++------------ scripts/mkdoc.sh | 11 +- scripts/patch-pydoctor.sh | 21 ++-- scripts/pydoctor-21.2.2_sphinx_ext.patch | 26 ---- 6 files changed, 121 insertions(+), 115 deletions(-) create mode 100644 doc/source/sphinxext/postprocess_api.py rename scripts/{pydoctor-21.2.2.patch => 0001-Old-patch-renewed.patch} (56%) delete mode 100644 scripts/pydoctor-21.2.2_sphinx_ext.patch diff --git a/doc/source/conf.py b/doc/source/conf.py index 0aa896561..88a279d59 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -79,19 +79,20 @@ def get_igraph_version(): 'sphinx.ext.intersphinx', 'gallery_generator', 'pydoctor.sphinx_ext.build_apidocs', + 'postprocess_api', #'sphinx_panels', ] pydoctor_args = [ '--project-name="igraph"', - #'--project-version=YOUR-PUBLIC-VERSION', + '--project-version=' + get_igraph_version(), '--project-url=https://igraph.org/python', '--introspect-c-modules', '--docformat=epytext', #'--intersphinx='+get_root_dir()+'/doc/tutorial/objects.inv', - '--html-output='+get_root_dir()+'/doc/html/api', + '--html-output=' + op.join(get_root_dir(), 'doc', 'html', 'api'), #'--html-viewsource-base=https://github.com/igraph/python-igraph/tree/default', - '--project-base-dir='+get_igraphdir(), + '--project-base-dir=' + get_igraphdir(), get_igraphdir(), ] diff --git a/doc/source/sphinxext/postprocess_api.py b/doc/source/sphinxext/postprocess_api.py new file mode 100644 index 000000000..53ab71ce0 --- /dev/null +++ b/doc/source/sphinxext/postprocess_api.py @@ -0,0 +1,56 @@ +""" +Sphinx plugin to run example scripts and create a gallery page. + +Lightly modified from the seaborn project (Michael Waskom). +Originally, lightly modified from the mpld3 project. + +""" +import os.path as op +import glob +from sphinx.application import Sphinx + + +def on_build_finished(app: Sphinx, exception: Exception) -> None: + html_dir = op.abspath(app.builder.outdir) + api_dir = op.join(html_dir, 'api') + + # Check if the index has Jekyll template marks + has_jekyll_marks = False + index_html = op.join(html_dir, 'index.html') + with open(index_html, 'rt') as f: + lines = f.readlines() + if sum(line == '---\n' for line in lines) == 2: + has_jekyll_marks = True + mark_start = lines.index('---\n') + mark_end = lines[mark_start + 1:].index('---\n') + mark_start + 2 + lines_mark = lines[mark_start: mark_end] + + if not has_jekyll_marks: + return + + # Write individual example files + for filename in sorted(glob.glob(op.join(api_dir, "*.html"))): + # Open file + with open(filename, 'rt') as f: + content = f.read() + start = content.find('') + len('') + end = content[start:].find('') + start + head, content = content[start:end], content[end:] + + start = content.find('') + len('') + end = content[start:].find('') + start + body, _ = content[start:end], content[end:] + + # Exclude title from head + start = head.find('') + end = head.find('') + len('') + head = head[:start] + head[end:] + + # Patch-up conent for Jekyll + content = ''.join(lines_mark[:-1]) + head + lines_mark[-1] + body + with open(filename, 'wt') as f: + f.write(content) + + +def setup(app): + app.connect('build-finished', on_build_finished, priority=900) diff --git a/scripts/pydoctor-21.2.2.patch b/scripts/0001-Old-patch-renewed.patch similarity index 56% rename from scripts/pydoctor-21.2.2.patch rename to scripts/0001-Old-patch-renewed.patch index 15a23623f..c3dc88f29 100644 --- a/scripts/pydoctor-21.2.2.patch +++ b/scripts/0001-Old-patch-renewed.patch @@ -1,21 +1,33 @@ +From 284115bf7275d86e245f5ce20cd4c1f0a97745c8 Mon Sep 17 00:00:00 2001 +From: Fabio Zanini +Date: Wed, 5 Jan 2022 17:39:23 +1100 +Subject: [PATCH] update_patch + +--- + pydoctor/astbuilder.py | 2 +- + pydoctor/epydoc2stan.py | 7 +++++- + pydoctor/model.py | 27 +++++++++++++++++------ + pydoctor/templatewriter/pages/__init__.py | 4 +++- + 4 files changed, 30 insertions(+), 10 deletions(-) + diff --git a/pydoctor/astbuilder.py b/pydoctor/astbuilder.py -index 6b274c9..393ddab 100644 +index 831643f5..8895ebd3 100644 --- a/pydoctor/astbuilder.py +++ b/pydoctor/astbuilder.py -@@ -188,7 +188,7 @@ class ModuleVistor(ast.NodeVisitor): +@@ -221,7 +221,7 @@ class ModuleVistor(ast.NodeVisitor): self.newAttr = None def visit_Module(self, node: ast.Module) -> None: - assert self.module.docstring is None -+ # assert self.module.docstring is None ++ #assert self.module.docstring is None self.builder.push(self.module, 0) if len(node.body) > 0 and isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Str): diff --git a/pydoctor/epydoc2stan.py b/pydoctor/epydoc2stan.py -index 1b418ae..841c773 100644 +index ed72e01d..77a76c1e 100644 --- a/pydoctor/epydoc2stan.py +++ b/pydoctor/epydoc2stan.py -@@ -191,6 +191,11 @@ class _EpydocLinker(DocstringLinker): +@@ -189,6 +189,11 @@ class _EpydocLinker(DocstringLinker): target = src.resolveName(identifier) if target is not None: return target @@ -27,17 +39,17 @@ index 1b418ae..841c773 100644 src = src.parent # Walk up the object tree again and see if 'identifier' refers to an -@@ -528,7 +533,7 @@ class FieldHandler: +@@ -592,7 +597,7 @@ class FieldHandler: def handleUnknownField(self, field: Field) -> None: name = field.tag - field.report(f"Unknown field '{name}'" ) -+ # field.report(f"Unknown field '{name}'" ) ++ #field.report(f"Unknown field '{name}'" ) self.unknowns[name].append(FieldDesc(name=field.arg, body=field.format())) def handle(self, field: Field) -> None: diff --git a/pydoctor/model.py b/pydoctor/model.py -index d233639..a14a4df 100644 +index 07fa858a..82cc55c7 100644 --- a/pydoctor/model.py +++ b/pydoctor/model.py @@ -14,7 +14,7 @@ import platform @@ -45,11 +57,11 @@ index d233639..a14a4df 100644 import types from enum import Enum -from inspect import Signature -+from inspect import signature, Signature ++from inspect import Signature, signature from optparse import Values from pathlib import Path from typing import ( -@@ -514,7 +514,8 @@ class Function(Inheritable): +@@ -513,7 +513,8 @@ class Function(Inheritable): is_async: bool annotations: Mapping[str, Optional[ast.expr]] decorators: Optional[Sequence[ast.expr]] @@ -59,17 +71,19 @@ index d233639..a14a4df 100644 def setup(self) -> None: super().setup() -@@ -776,15 +777,24 @@ class System: +@@ -780,15 +781,26 @@ class System: def _introspectThing(self, thing: object, parent: Documentable, parentMod: _ModuleT) -> None: for k, v in thing.__dict__.items(): - if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType)) +- # In PyPy 7.3.1, functions from extensions are not + # TODO(ntamas): MethodDescriptorType and ClassMethodDescriptorType are Python 3.7 only. + if (isinstance(v, (types.BuiltinFunctionType, types.FunctionType, types.MethodDescriptorType, types.ClassMethodDescriptorType)) - # In PyPy 7.3.1, functions from extensions are not # instances of the above abstract types. - or v.__class__.__name__ == 'builtin_function_or_method'): + or (hasattr(v, "__class__") and v.__class__.__name__ == 'builtin_function_or_method')): ++ ++ f = self.Function(self, k, parent) f.parentMod = parentMod f.docstring = v.__doc__ @@ -84,10 +98,11 @@ index d233639..a14a4df 100644 + f.annotations = { + name: None for name in (f.signature.parameters if f.signature else {}) + } ++ self.addObject(f) elif isinstance(v, type): c = self.Class(self, k, parent) -@@ -912,7 +922,8 @@ class System: +@@ -916,7 +928,8 @@ class System: mod.state = ProcessingState.PROCESSED head = self.processing_modules.pop() assert head == mod.fullName() @@ -98,70 +113,20 @@ index d233639..a14a4df 100644 'process', self.module_count - len(self.unprocessed_modules), diff --git a/pydoctor/templatewriter/pages/__init__.py b/pydoctor/templatewriter/pages/__init__.py -index e5f4050..3d326b3 100644 +index d032d495..dab775cf 100644 --- a/pydoctor/templatewriter/pages/__init__.py +++ b/pydoctor/templatewriter/pages/__init__.py -@@ -49,7 +49,7 @@ def format_decorators(obj: Union[model.Function, model.Attribute]) -> Iterator[A - - def signature(function: model.Function) -> str: - """Return a nicely-formatted source-like function signature.""" -- return str(function.signature) -+ return str(function.signature) if function.signature else function.text_signature or "(...)" +@@ -60,7 +60,9 @@ def format_signature(function: model.Function) -> "Flattenable": + Return a stan representation of a nicely-formatted source-like function signature for the given L{Function}. + Arguments default values are linked to the appropriate objects when possible. + """ +- return html2stan(str(function.signature)) ++ return html2stan( ++ str(function.signature) if function.signature else function.text_signature or "(...)", ++ ) class DocGetter: """L{epydoc2stan} bridge.""" -diff --git a/pydoctor/templates/common.html b/pydoctor/templates/common.html -index e5f4050..3d326b3 100644 ---- a/pydoctor/templates/common.html -+++ b/pydoctor/templates/common.html -@@ -63,7 +63,7 @@ -

    -
    - API Documentation for Some -- Project, generated by pydoctor at some time. -+ Project, generated by pydoctor . -
    - -
    -diff --git a/pydoctor/templatewriter/summary.py b/pydoctor/templatewriter/summary.py -index e5f4050..3d326b3 100644 ---- a/pydoctor/templatewriter/summary.py -+++ b/pydoctor/templatewriter/summary.py -@@ -22,7 +22,7 @@ - return r - ul = tags.ul() - for m in sorted(contents, key=lambda m:m.fullName()): -- ul(moduleSummary(m, page_url)) -+ ul(moduleSummary(m, page_url), "\n") - return r(ul) - - def _lckey(x): -@@ -45,6 +45,7 @@ - r = [] - for o in self.system.rootobjects: - r.append(moduleSummary(o, self.filename)) -+ r.append("\n") - return tag.clear()(r) - @renderer - def heading(self, request, tag): -@@ -105,7 +106,7 @@ - if len(scs) > 0: - ul = tags.ul() - for sc in sorted(scs, key=_lckey): -- ul(subclassesFrom(hostsystem, sc, anchors, page_url)) -+ ul(subclassesFrom(hostsystem, sc, anchors, page_url), "\n") - r(ul) - return r - -@@ -136,9 +137,10 @@ - if o: - ul = tags.ul() - for sc in sorted(o, key=_lckey): -- ul(subclassesFrom(self.system, sc, anchors, self.filename)) -+ ul(subclassesFrom(self.system, sc, anchors, self.filename), "\n") - item(ul) - t(item) -+ t("\n") - return t - - @renderer +-- +2.34.1 + diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 979a75848..0eaa3eaf8 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -8,7 +8,7 @@ STANDALONE=0 SERVE=0 -while getopts ":s:j" OPTION; do +while getopts ":sj" OPTION; do case $OPTION in s) STANDALONE=1 @@ -37,14 +37,17 @@ if [ ! -d ".venv" ]; then python3 -m venv .venv # Install sphinx, matplotlib, wheel, and pydoctor into the venv - .venv/bin/pip install sphinx sphinxbootstrap4theme matplotlib - .venv/bin/pip install -U pydoctor wheel + .venv/bin/pip install -U sphinx sphinxbootstrap4theme matplotlib wheel echo "Patching PyDoctor..." + .venv/bin/pip install -U pydoctor $SCRIPTS_FOLDER/patch-pydoctor.sh ${ROOT_FOLDER} ${SCRIPTS_FOLDER} fi +#echo "Set PyDoctor theme" +#$SCRIPTS_FOLDER/set-pydoctor-theme.sh ${ROOT_FOLDER} ${STANDALONE} + echo "Removing existing igraph and python-igraph eggs from virtualenv..." SITE_PACKAGES_DIR=`.venv/bin/python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'` rm -rf "${SITE_PACKAGES_DIR}"/igraph*.egg @@ -66,11 +69,13 @@ rm -rf "${DOC_HTML_FOLDER}" # Make sphinx echo "Generating HTML documentation..." if [ "x$STANDALONE" = "x1" ]; then + echo "Build standalone docs" .venv/bin/sphinx-build \ -Dtemplates_path='' \ -Dhtml_theme='alabaster' \ ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} else + echo "Build Jekyll-style docs" .venv/bin/sphinx-build ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} if [ "x$SERVE" = "x1" ]; then diff --git a/scripts/patch-pydoctor.sh b/scripts/patch-pydoctor.sh index 36342d956..6b0c62daa 100755 --- a/scripts/patch-pydoctor.sh +++ b/scripts/patch-pydoctor.sh @@ -12,16 +12,21 @@ set -e ROOT_FOLDER=$1 PATCH_FOLDER=$(realpath $2) ${ROOT_FOLDER}/.venv/bin/pip uninstall -y pydoctor -${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.2.2 +#${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.2.2 +${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.12.0 PYDOCTOR_DIR=`.venv/bin/python -c 'import os,pydoctor;print(os.path.dirname(pydoctor.__file__))'` cd "${PYDOCTOR_DIR}" -# patch is confirmed to work with pydoctor 21.2.2 -echo "First patch" -patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2.patch 2>/dev/null -rm -f deleteme.rej +## patch is confirmed to work with pydoctor 21.2.2 +#echo "First patch" +#patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2.patch 2>/dev/null +#rm -f deleteme.rej +# +## patch sphinx extension +#echo "Second patch" +#patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2_sphinx_ext.patch 2>/dev/null +#rm -f deleteme.rej -# patch sphinx extension -echo "Second patch" -patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2_sphinx_ext.patch 2>/dev/null +echo "New patch against 21.12.0" +patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/0001-Old-patch-renewed.patch 2>/dev/null rm -f deleteme.rej diff --git a/scripts/pydoctor-21.2.2_sphinx_ext.patch b/scripts/pydoctor-21.2.2_sphinx_ext.patch deleted file mode 100644 index 9987779d6..000000000 --- a/scripts/pydoctor-21.2.2_sphinx_ext.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 439299fc32e7f67d338f85fc919cd42ec293e639 Mon Sep 17 00:00:00 2001 -From: Fabio Zanini -Date: Sun, 26 Dec 2021 08:40:16 +1100 -Subject: [PATCH] Sphinx ext: skip temp dir renaming if absent - ---- - pydoctor/sphinx_ext/build_apidocs.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/pydoctor/sphinx_ext/build_apidocs.py b/pydoctor/sphinx_ext/build_apidocs.py -index 06da7cef..a6204c20 100644 ---- a/pydoctor/sphinx_ext/build_apidocs.py -+++ b/pydoctor/sphinx_ext/build_apidocs.py -@@ -64,7 +64,8 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: - - temp_path = output_path.with_suffix('.pydoctor_temp') - shutil.rmtree(sphinx_files, ignore_errors=True) -- output_path.rename(sphinx_files) -+ if os.path.isdir(output_path): -+ output_path.rename(sphinx_files) - temp_path.rename(output_path) - - --- -2.34.1 - From db95061fd9f766fb4805d3efa38b784a049e810c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Jan 2022 09:39:06 +1100 Subject: [PATCH 0844/1892] Include first ntamas reviews, add FAQ re other libraries --- doc/Makefile | 130 ------------------------ doc/source/faq.rst | 49 +++++++-- doc/source/index.rst | 9 +- doc/source/sphinxext/postprocess_api.py | 25 +++-- 4 files changed, 58 insertions(+), 155 deletions(-) delete mode 100644 doc/Makefile diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index aa1a6dbf8..000000000 --- a/doc/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/igraph.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/igraph.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/igraph" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/igraph" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/source/faq.rst b/doc/source/faq.rst index 55f4f7667..37bcf9cad 100644 --- a/doc/source/faq.rst +++ b/doc/source/faq.rst @@ -22,19 +22,20 @@ more examples in our :doc:`gallery `, read detailed instructions on gra I thought |igraph| was an R package, is this the same package? -------------------------------------------------------------- -|igraph| is a software library written in C with interfaces in R, Python, and -Mathematica. Many functions will have similar names and functionality across -languages, but the matching is not perfect, so you will occasionally find -functions that are supported in one language but not another. See the FAQ below -for instructions about how to request a feature. +|igraph| is a software library written in C with interfaces in various programming +languages such as R, Python, and Mathematica. Many functions will have similar names +and functionality across languages, but the matching is not perfect, so you will +occasionally find functions that are supported in one language but not another. +See the FAQ below for instructions about how to request a feature. I would like to use |igraph| but don't know Python, what to do? --------------------------------------------------------------- -|igraph| can be used via four programming languages: C, R, Python, and Mathematica. -While the exact function names differ a bit, most functionality is shared, so if -you can code any of them you can use |igraph|: just refer to the installation -instructions for the appropriate language on our `homepage `_. +|igraph| can be used from multiple programming languages such as C, R, Python, +and Mathematica. While the exact function names differ a bit, most functionality +is shared, so if you can code any of them you can use |igraph|: just refer to +the installation instructions for the appropriate language on our +`homepage `_. If you are not familiar with programming at all, or if you don't know any Python but would still like to use the Python interface for |igraph|, you should start by @@ -58,6 +59,30 @@ or specific piece of code, you can directly open a instead.) +What's the difference between |igraph| and similar packages (networkx, graph-tool)? +----------------------------------------------------------------------------------- +All those packages focus on graph/network analysis. + +**Differences:** + + - |igraph| supports **multiple programming languages** (e.g. C, Python, R, Mathematica). `networkx`_ and `graph-tool`_ are Python only. + - |igraph|'s core library is written in C, which makes it often faster than `networkx`_. `graph-tool`_ is written in heavily templated C++, so it can be as fast as |igraph| but supports fewer architectures. Compiling `graph-tool` can take much longer than |igraph| (hours versus around a minute). + - |igraph| vertices are *ordered with contiguous numerical IDs, from 0 upwards*, and an *optional* "vertex name". `networkx`_ nodes are *defined* by their name and not ordered. + - Same holds for edges, ordered with integer IDs in |igraph|, not so in `networkx`_. + - |igraph| can plot graphs using :mod:`matplotlib` and has experimental support for `plotly`_, so it can produce animations, notebook widgets, and interactive plots (e.g. zoom, panning). `networkx`_ has excellent :mod:`matplotlib` support but no `plotly`_ support. `graph-tool`_ only supports static images via Cairo and GTK+. + - |igraph| and `networkx`_ are maintained by teams of developers. `graph-tool`_ is developed by a single (very active) person. + - In terms of design, |igraph| really shines when you have a relatively static network that you want to analyse, while it can struggle with very dynamic networks that gain and lose vertices and edges all the time. This might change in the near future as we improve |igraph|'s core C library. At the moment, `networkx`_ is probably better suited for simulating such highly dynamic graphs. + +**Similarities:** + + - Many tasks can be achieved equally well with |igraph|, `graph-tool`_, and `networkx`_. + - All can read and write a number of graph file formats. + - All can visualize graphs, with different strengths and weaknesses. + +.. note:: + |igraph| includes conversion functions from/to `networkx`_, so you can crate and manipulate a network with |igraph| and later on convert it to `networkx`_ or `graph-tool`_ if you need. Vice versa, you can load a graph in `networkx`_ or `graph-tool`_ and convert the graph into an |igraph| object if you need more speed, a specific algorithm, matplotlib animations, etc. You can even use |igraph| to convert graphs from `networkx`_ to `graph-tool`_ and vice versa! + + I would like to contribute to |igraph|, where do I start? --------------------------------------------------------- @@ -72,9 +97,15 @@ you find one that sounds easy enough and sparks your interest, and write a message saying you're interested in taking it on. We'll reply ASAP and guide you as of your next steps. +The C core library also has various `"theory issues" `_ which require knowledge of graphs but not programming, take a +look if you are interested. + If none of those look feasible, or if you have a specific idea, or still if you would like to contribute in other ways than pure programming, reach out on our `forum `_ and we'll come up with some ideas! +.. _networkx: https://networkx.org/documentation/stable/ +.. _graph-tool: https://graph-tool.skewed.de/ +.. _plotly: https://plotly.com/python/ diff --git a/doc/source/index.rst b/doc/source/index.rst index ce9532d9c..20edc1e1c 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -13,20 +13,21 @@ padding-left: 0; padding-right: 0; display: flex; - gap: 20px; } div.twocol > div { flex-grow: 1; padding: 0; - margin: 0; + margin-right: 20px; } python-igraph |release| ======================= -|igraph| is a fast open source tool to manipulate, analyze, and plot graphs or networks written in C, and `python-igraph` is |igraph|'s interface for the Python programming language. +|igraph| is a fast open source tool to manipulate and analyze graphs or networks. It is primarily written in C. `python-igraph` is |igraph|'s interface for the Python programming language. + +`python-graph` includes functionality for graph plotting and conversion from/to `networkx`_. Installation @@ -113,3 +114,5 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` + +.. _networkx: https://networkx.org/documentation/stable/ diff --git a/doc/source/sphinxext/postprocess_api.py b/doc/source/sphinxext/postprocess_api.py index 53ab71ce0..2522a00e8 100644 --- a/doc/source/sphinxext/postprocess_api.py +++ b/doc/source/sphinxext/postprocess_api.py @@ -15,18 +15,15 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: api_dir = op.join(html_dir, 'api') # Check if the index has Jekyll template marks - has_jekyll_marks = False index_html = op.join(html_dir, 'index.html') with open(index_html, 'rt') as f: lines = f.readlines() - if sum(line == '---\n' for line in lines) == 2: - has_jekyll_marks = True - mark_start = lines.index('---\n') - mark_end = lines[mark_start + 1:].index('---\n') + mark_start + 2 - lines_mark = lines[mark_start: mark_end] - - if not has_jekyll_marks: - return + # The Jekyll template starts with a --- line + # Nontemplated HTML starts with some kind of XML tag + if lines[0] != '---\n': + return + mark_end = lines.index('---\n', 1) + 1 + lines_mark = lines[: mark_end] # Write individual example files for filename in sorted(glob.glob(op.join(api_dir, "*.html"))): @@ -34,18 +31,20 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: with open(filename, 'rt') as f: content = f.read() start = content.find('') + len('') - end = content[start:].find('') + start - head, content = content[start:end], content[end:] + end = content.find('', start) + head, content = content[start: end], content[end:] start = content.find('') + len('') - end = content[start:].find('') + start - body, _ = content[start:end], content[end:] + end = content.find('', start) + body, _ = content[start: end], content[end:] # Exclude title from head start = head.find('') end = head.find('') + len('') head = head[:start] + head[end:] + # FIXME: fix CSS includes to match navbar appearance + # Patch-up conent for Jekyll content = ''.join(lines_mark[:-1]) + head + lines_mark[-1] + body with open(filename, 'wt') as f: From 8a00991b34a509342cd98d7da135bd3b14d2f7df Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Jan 2022 09:42:31 +1100 Subject: [PATCH 0845/1892] Rename pydoctor patch file --- scripts/patch-pydoctor.sh | 2 +- .../{0001-Old-patch-renewed.patch => pydoctor-21.12.0.patch} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/{0001-Old-patch-renewed.patch => pydoctor-21.12.0.patch} (100%) diff --git a/scripts/patch-pydoctor.sh b/scripts/patch-pydoctor.sh index 6b0c62daa..aad33b27e 100755 --- a/scripts/patch-pydoctor.sh +++ b/scripts/patch-pydoctor.sh @@ -28,5 +28,5 @@ cd "${PYDOCTOR_DIR}" #rm -f deleteme.rej echo "New patch against 21.12.0" -patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/0001-Old-patch-renewed.patch 2>/dev/null +patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.12.0.patch 2>/dev/null rm -f deleteme.rej diff --git a/scripts/0001-Old-patch-renewed.patch b/scripts/pydoctor-21.12.0.patch similarity index 100% rename from scripts/0001-Old-patch-renewed.patch rename to scripts/pydoctor-21.12.0.patch From afe615ebd416b09e3480355129d8df35fabb8f67 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Jan 2022 09:47:25 +1100 Subject: [PATCH 0846/1892] Rephrasing of FAQ as requested by szhorvat --- doc/source/faq.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/source/faq.rst b/doc/source/faq.rst index 37bcf9cad..1855a635e 100644 --- a/doc/source/faq.rst +++ b/doc/source/faq.rst @@ -97,13 +97,15 @@ you find one that sounds easy enough and sparks your interest, and write a message saying you're interested in taking it on. We'll reply ASAP and guide you as of your next steps. -The C core library also has various `"theory issues" `_ which require knowledge of graphs but not programming, take a -look if you are interested. +The C core library also has various `"theory issues" `_. You can contribute to these issues without any programming +knowledge by researching graph literature or finding the solution to a graph +problem. Once the theory obstacle has been overcome, others can move on to the +coding part: a real team effort! If none of those look feasible, or if you have a specific idea, or still if you would like to contribute in other ways than pure programming, reach out on our `forum `_ and we'll come up with -some ideas! +some ideas. .. _networkx: https://networkx.org/documentation/stable/ From 937c00be41d1970ef06f4f0e629eef3f4094278c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Jan 2022 09:52:51 +1100 Subject: [PATCH 0847/1892] Use pathlib where possible --- doc/source/sphinxext/postprocess_api.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/source/sphinxext/postprocess_api.py b/doc/source/sphinxext/postprocess_api.py index 2522a00e8..21ad9677c 100644 --- a/doc/source/sphinxext/postprocess_api.py +++ b/doc/source/sphinxext/postprocess_api.py @@ -6,16 +6,17 @@ """ import os.path as op +from pathlib import Path import glob from sphinx.application import Sphinx def on_build_finished(app: Sphinx, exception: Exception) -> None: - html_dir = op.abspath(app.builder.outdir) - api_dir = op.join(html_dir, 'api') + html_dir = Path(app.builder.outdir) + api_dir = html_dir / 'api' # Check if the index has Jekyll template marks - index_html = op.join(html_dir, 'index.html') + index_html = html_dir / 'index.html' with open(index_html, 'rt') as f: lines = f.readlines() # The Jekyll template starts with a --- line From b87cb1fc7a45f39644e9d01d58411be922f89e85 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 7 Jan 2022 19:12:20 +1100 Subject: [PATCH 0848/1892] Add complement tutorial --- .../tutorials/complement/assets/complement.py | 27 +++++++++ .../tutorials/complement/complement.rst | 53 ++++++++++++++++++ .../complement/figures/complement.png | Bin 0 -> 59999 bytes 3 files changed, 80 insertions(+) create mode 100644 doc/source/tutorials/complement/assets/complement.py create mode 100644 doc/source/tutorials/complement/complement.rst create mode 100644 doc/source/tutorials/complement/figures/complement.png diff --git a/doc/source/tutorials/complement/assets/complement.py b/doc/source/tutorials/complement/assets/complement.py new file mode 100644 index 000000000..bec1e5d16 --- /dev/null +++ b/doc/source/tutorials/complement/assets/complement.py @@ -0,0 +1,27 @@ +import igraph as ig +import matplotlib.pyplot as plt +import random + +# Create a random graph +random.seed(0) +g1 = ig.Graph.Erdos_Renyi(n=10, p=0.5) + +# Generate complement +g2 = g1.complementer(loops=False) + +# Plot graph +fig, axs = plt.subplots(1, 2) +ig.plot( + g1, + target=axs[0], + layout="circle", + vertex_color="lightblue", +) +ig.plot( + g2, + target=axs[1], + layout="circle", + vertex_color="lightblue", +) +plt.show() + diff --git a/doc/source/tutorials/complement/complement.rst b/doc/source/tutorials/complement/complement.rst new file mode 100644 index 000000000..8e337be47 --- /dev/null +++ b/doc/source/tutorials/complement/complement.rst @@ -0,0 +1,53 @@ +.. include:: ../../include/global.rst + +.. _tutorials-complement: + +================ +Complement +================ + +.. _complementer: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#complementer +.. |complementer| replace:: :meth:`complementer` + +This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using |complementer|_. First we generate a random graph + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import random + + # Create a random graph + random.seed(0) + g1 = ig.Graph.Erdos_Renyi(n=10, p=0.5) + +We can then generate the complement, and plot out the graph. + +.. code-block:: python + + # Generate complement + g2 = g1.complementer(loops=False) + + # Plot graph + fig, axs = plt.subplots(1, 2) + ig.plot( + g1, + target=axs[0], + layout="circle", + vertex_color="lightblue", + ) + ig.plot( + g2, + target=axs[1], + layout="circle", + vertex_color="lightblue", + ) + plt.show() + +The two graphs compared side by side look like this: + +.. figure:: ./figures/complement.png + :alt: Two complement graphs side by side + :align: center + + The original graph (left) and its complement (right). diff --git a/doc/source/tutorials/complement/figures/complement.png b/doc/source/tutorials/complement/figures/complement.png new file mode 100644 index 0000000000000000000000000000000000000000..0f7bf86c53a7fe88159c211326e1bdc36353f3e8 GIT binary patch literal 59999 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�S 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 F{68ROOBetE literal 0 HcmV?d00001 From 2dac6ada5888a79dea3794726395b222a1cce609 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 7 Jan 2022 19:12:27 +1100 Subject: [PATCH 0849/1892] Add isomorphism tutorial --- .../isomorphism/assets/isomorphism.py | 51 +++++++++++ .../isomorphism/figures/isomorphism.png | Bin 0 -> 33330 bytes .../tutorials/isomorphism/isomorphism.rst | 83 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 doc/source/tutorials/isomorphism/assets/isomorphism.py create mode 100644 doc/source/tutorials/isomorphism/figures/isomorphism.png create mode 100644 doc/source/tutorials/isomorphism/isomorphism.rst diff --git a/doc/source/tutorials/isomorphism/assets/isomorphism.py b/doc/source/tutorials/isomorphism/assets/isomorphism.py new file mode 100644 index 000000000..8719c14b5 --- /dev/null +++ b/doc/source/tutorials/isomorphism/assets/isomorphism.py @@ -0,0 +1,51 @@ +import igraph as ig +import matplotlib.pyplot as plt + +# Create Graphs +g1 = ig.Graph([(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]) +g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) +g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) + +# Plot graphs +visual_style = { + "vertex_color": "lightblue", + "vertex_label": [0, 1, 2, 3, 4], + "vertex_size": 0.4, +} + +fig, axs = plt.subplots(1, 3) +ig.plot( + g1, + layout=g1.layout("circle"), + target=axs[0], + **visual_style, +) +ig.plot( + g2, + layout=g1.layout("circle"), + target=axs[1], + **visual_style, +) +ig.plot( + g3, + layout=g1.layout("circle"), + target=axs[2], + **visual_style, +) +plt.show() + +# Check isomorphism +print("Are the graphs g1 and g2 isomorphic?") +print(g1.isomorphic(g2)) +print("Are the graphs g1 and g3 isomorphic?") +print(g1.isomorphic(g3)) +print("Are the graphs g2 and g3 isomorphic?") +print(g2.isomorphic(g3)) + +# Output: +# Are the graphs g1 and g2 isomorphic? +# True +# Are the graphs g1 and g3 isomorphic? +# False +# Are the graphs g2 and g3 isomorphic? +# False diff --git a/doc/source/tutorials/isomorphism/figures/isomorphism.png b/doc/source/tutorials/isomorphism/figures/isomorphism.png new file mode 100644 index 0000000000000000000000000000000000000000..ef1ee4140e7397edb0fcd77d1c5df7371f9996f1 GIT binary patch literal 33330 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst new file mode 100644 index 000000000..3fd206a1a --- /dev/null +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -0,0 +1,83 @@ +.. include:: ../../include/global.rst + +.. _tutorials-isomorphism: + +==================== +Checking Isomorphism +==================== + +.. _isomorphic: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#isomorphic +.. |isomorphic| replace:: :meth:`isomorphic` + +This example shows how to check `isomorphism `_ for small graphs using |isomorphic|_. First we generate three different graphs to compare between and plot them. + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + # Create Graphs + g1 = ig.Graph([(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]) + g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) + g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) + + # Plot graphs + visual_style = { + "vertex_color": "lightblue", + "vertex_label": [0, 1, 2, 3, 4], + "vertex_size": 0.4, + } + + fig, axs = plt.subplots(1, 3) + ig.plot( + g1, + layout=g1.layout("circle"), + target=axs[0], + **visual_style, + ) + ig.plot( + g2, + layout=g1.layout("circle"), + target=axs[1], + **visual_style, + ) + ig.plot( + g3, + layout=g1.layout("circle"), + target=axs[2], + **visual_style, + ) + plt.show() + +The three graphs should now look like this: + +.. figure:: ./figures/isomorphism.png + :alt: A visual representation of three different graphs + :align: center + + Three graphs to be compared for isomorphism + +We then have some code to compare the isomoprhism between all three graphs. + +.. code-block:: python + + # Check isomorphism + print("Are the graphs g1 and g2 isomorphic?") + print(g1.isomorphic(g2)) + print("Are the graphs g1 and g3 isomorphic?") + print(g1.isomorphic(g3)) + print("Are the graphs g2 and g3 isomorphic?") + print(g2.isomorphic(g3)) + +The final output is: + +.. code-block:: + + Are the graphs g1 and g2 isomorphic? + True + Are the graphs g1 and g3 isomorphic? + False + Are the graphs g2 and g3 isomorphic? + False + + From e25343a2f1aa0b4f4faf0af698be32c07719e834 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Fri, 7 Jan 2022 19:12:32 +1100 Subject: [PATCH 0850/1892] Add simplify tutorial --- .../tutorials/simplify/assets/simplify.py | 32 +++++++++ .../tutorials/simplify/figures/simplify.png | Bin 0 -> 31685 bytes doc/source/tutorials/simplify/simplify.rst | 62 ++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 doc/source/tutorials/simplify/assets/simplify.py create mode 100644 doc/source/tutorials/simplify/figures/simplify.png create mode 100644 doc/source/tutorials/simplify/simplify.rst diff --git a/doc/source/tutorials/simplify/assets/simplify.py b/doc/source/tutorials/simplify/assets/simplify.py new file mode 100644 index 000000000..ab75337d1 --- /dev/null +++ b/doc/source/tutorials/simplify/assets/simplify.py @@ -0,0 +1,32 @@ +import igraph as ig +import matplotlib.pyplot as plt + +# Generate graph with multiple edges and loops +g1 = ig.Graph([(0, 1), (1, 2), (2, 3), (3, 4), (4, 0), (0, 0), + (1, 4), (1, 4), (0, 2), (2, 4), (2, 4), (2, 4), (3, 3)]) + +# Generate simplified version of graph +g2 = g1.copy() +g2.simplify() + +# Plot graphs +visual_style = { + "vertex_color": "lightblue", + "vertex_size": 0.4, + "vertex_label": [0, 1, 2, 3, 4], +} + +fig, axs = plt.subplots(1, 2) +ig.plot( + g1, + layout="circle", + target=axs[0], + **visual_style, +) +ig.plot( + g2, + layout="circle", + target=axs[1], + **visual_style, +) +plt.show() diff --git a/doc/source/tutorials/simplify/figures/simplify.png b/doc/source/tutorials/simplify/figures/simplify.png new file mode 100644 index 0000000000000000000000000000000000000000..03e0619a4104ce7325d4c58665a86cccbe714764 GIT binary patch literal 31685 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst new file mode 100644 index 000000000..7b534f8e7 --- /dev/null +++ b/doc/source/tutorials/simplify/simplify.rst @@ -0,0 +1,62 @@ +.. include:: ../../include/global.rst + +.. _tutorials-simplify: + +======== +Simplify +======== + +.. _simplify: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#simplify +.. |simplify| replace:: :meth:`simplify` + +This example shows how to remove self loops and multiple edges using |simplify|_. First we plot the graph + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + + # Generate graph with multiple edges and loops + g1 = ig.Graph([(0, 1), (1, 2), (2, 3), (3, 4), (4, 0), (0, 0), + (1, 4), (1, 4), (0, 2), (2, 4), (2, 4), (2, 4), (3, 3)]) + +Then we make a copy of the original graph and simplify it in place: + +.. code-block:: python + + # Generate simplified version of graph + g2 = g1.copy() + g2.simplify() + +Finally, we plot the graph: + +.. code-block::python + + # Plot graphs + visual_style = { + "vertex_color": "lightblue", + "vertex_size": 0.4, + "vertex_label": [0, 1, 2, 3, 4], + } + + fig, axs = plt.subplots(1, 2) + ig.plot( + g1, + layout="circle", + target=axs[0], + **visual_style, + ) + ig.plot( + g2, + layout="circle", + target=axs[1], + **visual_style, + ) + plt.show() + + +.. figure:: ./figures/simplify.png + :alt: Two graphs before and after removing self loops and edges + :align: center + + The original graph (left) versus the simplified graph (right). From ac81d5331eda770d198a60ea76bd2b5109e543d6 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 00:00:55 +1100 Subject: [PATCH 0851/1892] Add Delaunay Triangulation Tutorial --- .../assets/delaunay-triangulation.py | 30 +++++ .../assets/delaunay-triangulation2.py | 45 ++++++++ .../delaunay-triangulation.rst | 104 ++++++++++++++++++ .../figures/delaunay-triangulation.png | Bin 0 -> 56427 bytes .../figures/delaunay-triangulation2.png | Bin 0 -> 41620 bytes 5 files changed, 179 insertions(+) create mode 100644 doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py create mode 100644 doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py create mode 100644 doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst create mode 100644 doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png create mode 100644 doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py new file mode 100644 index 000000000..a2b70335b --- /dev/null +++ b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py @@ -0,0 +1,30 @@ +import igraph as ig +import matplotlib.pyplot as plt +import random +from scipy.spatial import Delaunay + +# Generate a random geometric graph +random.seed(0) +g = ig.Graph.GRG(30, 0) + +# Calculate the delaunay triangulation, and add the edges into the original graph +coords = g.layout_auto().coords +delaunay = Delaunay(coords) +for tri in delaunay.simplices: + g.add_edges([ + (tri[0], tri[1]), + (tri[1], tri[2]), + (tri[0], tri[2]), + ]) +g.simplify() + +# Plot the graph +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + vertex_size=0.04, + vertex_color="lightblue", + edge_width=0.8 +) +plt.show() diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py new file mode 100644 index 000000000..fc1e5bf00 --- /dev/null +++ b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py @@ -0,0 +1,45 @@ +import igraph as ig +import matplotlib.pyplot as plt +import random +from scipy.spatial import Delaunay + +# Generate a random geometric graph +random.seed(0) +g = ig.Graph.GRG(30, 0) + +# Calculate the delaunay triangulation, and add the edges into the original graph +coords = g.layout_auto().coords +delaunay = Delaunay(coords) +for tri in delaunay.simplices: + g.add_edges([ + (tri[0], tri[1]), + (tri[1], tri[2]), + (tri[0], tri[2]), + ]) +g.simplify() + +# Plot the triangles +fig, ax = plt.subplots() + +palette = ig.GradientPalette("midnightblue", "lightblue", 100) +for tri in delaunay.simplices: + # get the points of the triangle + tri_points = [delaunay.points[tri[i]] for i in range(3)] + + # calculate the vertical center of the triangle + center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 + + # draw triangle onto axes + poly = plt.Polygon(tri_points, color=palette.get(int(center*100))) + ax.add_patch(poly) + +# Plot the graph on top +ig.plot( + g, + target=ax, + vertex_size=0.0, + edge_width=0.2, + edge_color="white", +) +plt.show() + diff --git a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst new file mode 100644 index 000000000..9c441fc8b --- /dev/null +++ b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst @@ -0,0 +1,104 @@ +.. include:: ../../include/global.rst + +.. _tutorials-delaunay-triangulation: + +====================== +Delaunay Triangulation +====================== + +.. _GRG: https://igraph.org/python/doc/api/igraph.Graph.html#GRG +.. |GRG| replace:: :meth:`GRG` + +This example demonstrates how to calculate the `Delaunay triangulation `_ of an input graph. We start by generating a set of points on a 2D grid using |GRG|_ with radius zero, so that there are initially no edges in the graph. + +.. code-block:: python + + import igraph as ig + import matplotlib.pyplot as plt + import random + from scipy.spatial import Delaunay + + # Generate a random geometric graph + random.seed(0) + g = ig.Graph.GRG(30, 0) + +We then use `SciPy's Delaunay function `_ to generate the triangles, and then loop through them to add them back into our original graph. We make sure to simplify the graph afterwards to remove multiple edges caused by triangles sharing a side. + +.. code-block:: python + + # Calculate the delaunay triangulation, and add the edges into the original graph + coords = g.layout_auto().coords + delaunay = Delaunay(coords) + for tri in delaunay.simplices: + g.add_edges([ + (tri[0], tri[1]), + (tri[1], tri[2]), + (tri[0], tri[2]), + ]) + g.simplify() + +Finally, we display the graph: + +.. code-block:: python + + # Plot the graph + fig, ax = plt.subplots() + ig.plot( + g, + target=ax, + vertex_size=0.04, + vertex_color="lightblue", + edge_width=0.8 + ) + plt.show() + +Our output looks like this: + +.. figure:: ./figures/delaunay-triangulation.png + :alt: The visual representation of a Delaunay triangulation + :align: center + + The Delaunay triangulation + +Advanced: Improving plotting style +---------------------------------- +Sometimes, we would like to emphasise the actual triangles generated by the Delaunay triangulation. We'll add in some triangles and color them according to their y coordinate. + +.. code-block:: python + + # Plot the triangles + fig, ax = plt.subplots() + + palette = ig.GradientPalette("midnightblue", "lightblue", 100) + for tri in delaunay.simplices: + # get the points of the triangle + tri_points = [delaunay.points[tri[i]] for i in range(3)] + + # calculate the vertical center of the triangle + center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 + + # draw triangle onto axes + poly = plt.Polygon(tri_points, color=palette.get(int(center*100))) + ax.add_patch(poly) + +We then plot the original graph edges on top: + +.. code-block:: python + + # Plot the graph on top + ig.plot( + g, + target=ax, + vertex_size=0.0, + edge_width=0.2, + edge_color="white", + ) + plt.show() + +The final output looks like this: + +.. figure:: ./figures/delaunay-triangulation2.png + :alt: The visual representation of a Delaunay triangulation + :align: center + + The Delaunay triangulation, with colored triangles. diff --git a/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png b/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png new file mode 100644 index 0000000000000000000000000000000000000000..4c25e005d698ded4f0a5541ac7df0c6b300a29a4 GIT binary patch literal 56427 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

  • fun|_2e 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 literal 0 HcmV?d00001 diff --git a/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png b/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png new file mode 100644 index 0000000000000000000000000000000000000000..986a7e53f04a41fc2c90539141f4524485bfa730 GIT binary patch literal 41620 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 literal 0 HcmV?d00001 From 91c4f338629d5ad425d8c611d8a004fc53dfe707 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 9 Jan 2022 13:36:14 +1100 Subject: [PATCH 0852/1892] Use numpy for coordinates, fix some styling --- .../assets/delaunay-triangulation.py | 18 +++++++------ .../assets/delaunay-triangulation2.py | 25 +++++++++++-------- .../delaunay-triangulation.rst | 13 ++++++---- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py index a2b70335b..6b1bc5b67 100644 --- a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py +++ b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py @@ -1,19 +1,23 @@ +import numpy as np +from scipy.spatial import Delaunay import igraph as ig import matplotlib.pyplot as plt -import random -from scipy.spatial import Delaunay -# Generate a random geometric graph -random.seed(0) -g = ig.Graph.GRG(30, 0) + +# Generate a random graph in the 2D unit cube +np.random.seed(0) # To ensure reproducibility +x, y = np.random.rand(2, 30) +g = ig.Graph(30) +g.vs['x'] = x +g.vs['y'] = y # Calculate the delaunay triangulation, and add the edges into the original graph coords = g.layout_auto().coords delaunay = Delaunay(coords) for tri in delaunay.simplices: g.add_edges([ - (tri[0], tri[1]), - (tri[1], tri[2]), + (tri[0], tri[1]), + (tri[1], tri[2]), (tri[0], tri[2]), ]) g.simplify() diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py index fc1e5bf00..7bac09e9b 100644 --- a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py +++ b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py @@ -1,19 +1,23 @@ +import numpy as np +from scipy.spatial import Delaunay import igraph as ig import matplotlib.pyplot as plt -import random -from scipy.spatial import Delaunay -# Generate a random geometric graph -random.seed(0) -g = ig.Graph.GRG(30, 0) + +# Generate a random graph in the 2D unit cube +np.random.seed(0) # To ensure reproducibility +x, y = np.random.rand(2, 30) +g = ig.Graph(30) +g.vs['x'] = x +g.vs['y'] = y # Calculate the delaunay triangulation, and add the edges into the original graph coords = g.layout_auto().coords delaunay = Delaunay(coords) for tri in delaunay.simplices: g.add_edges([ - (tri[0], tri[1]), - (tri[1], tri[2]), + (tri[0], tri[1]), + (tri[1], tri[2]), (tri[0], tri[2]), ]) g.simplify() @@ -27,12 +31,12 @@ tri_points = [delaunay.points[tri[i]] for i in range(3)] # calculate the vertical center of the triangle - center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 + center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 # draw triangle onto axes - poly = plt.Polygon(tri_points, color=palette.get(int(center*100))) + poly = plt.Polygon(tri_points, color=palette.get(int(center * 100))) ax.add_patch(poly) - + # Plot the graph on top ig.plot( g, @@ -42,4 +46,3 @@ edge_color="white", ) plt.show() - diff --git a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst index 9c441fc8b..5860a3fae 100644 --- a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst +++ b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst @@ -13,14 +13,17 @@ This example demonstrates how to calculate the `Delaunay triangulation `_ to generate the triangles, and then loop through them to add them back into our original graph. We make sure to simplify the graph afterwards to remove multiple edges caused by triangles sharing a side. From 4b70c2cb153b167e1dca0cf24544d62da06339be Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 9 Jan 2022 13:38:29 +1100 Subject: [PATCH 0853/1892] No need for GRG tricks --- .../delaunay-triangulation/delaunay-triangulation.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst index 5860a3fae..b2fc98f77 100644 --- a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst +++ b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst @@ -6,10 +6,7 @@ Delaunay Triangulation ====================== -.. _GRG: https://igraph.org/python/doc/api/igraph.Graph.html#GRG -.. |GRG| replace:: :meth:`GRG` - -This example demonstrates how to calculate the `Delaunay triangulation `_ of an input graph. We start by generating a set of points on a 2D grid using |GRG|_ with radius zero, so that there are initially no edges in the graph. +This example demonstrates how to calculate the `Delaunay triangulation `_ of an input graph. We start by generating a set of points on a 2D grid using random ``numpy`` arrays and a graph with those vertex coordinates and no edges. .. code-block:: python From ccde7ed8a7eea860e1cb2b24d15373cef2471e0b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 9 Jan 2022 13:47:17 +1100 Subject: [PATCH 0854/1892] Forsake numpy as requested by Tamas --- .../assets/minimum_spanning_trees.py | 7 +++---- .../minimum_spanning_trees/minimum_spanning_trees.rst | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py b/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py index 9b1191460..bb2bd66c0 100644 --- a/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py +++ b/doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py @@ -1,12 +1,11 @@ +import random import igraph as ig import matplotlib.pyplot as plt -import numpy as np # Generate grid graph with random weights -np.random.seed(0) - +random.seed(0) g = ig.Graph.Lattice([5, 5], circular=False) -g.es["weight"] = np.random.randint(1, 20, g.ecount()).tolist() +g.es["weight"] = [random.randint(1, 20) for _ in g.es] # Generate minimum spanning tree mst_edges = g.spanning_tree(weights=g.es["weight"], return_tree=False) diff --git a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst b/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst index 39afbbda0..8978eb30d 100644 --- a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst +++ b/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst @@ -11,13 +11,13 @@ Minimum Spanning Trees This example shows how to generate a `minimum spanning tree `_ from an input graph using |spanning_tree|_. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. -We start by generating a grid graph with random weights +We start by generating a grid graph with random integer weights between 1 and 20: .. code-block:: python + import random import igraph as ig import matplotlib.pyplot as plt - import random # Generate grid graph with random weights random.seed(0) From 97874eb1d4737720b43b1e1039a4ad0e66b8ad29 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:14:33 +1100 Subject: [PATCH 0855/1892] Add colorbars to betweenness tutorial --- .../tutorials/betweenness/betweenness.rst | 78 +++++++++++++----- .../betweenness/figures/betweenness.png | Bin 30970 -> 241654 bytes 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index d85da5daa..cf53cbaa9 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -11,43 +11,70 @@ Betweenness .. _edge_betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#edge_betweenness .. |edge_betweenness| replace:: :meth:`edge_betweenness` -This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Barabási-Albert `_ random graph. +This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. First we import the relevant libraries .. code-block:: python import igraph as ig import matplotlib.pyplot as plt - import math + from matplotlib.cm import ScalarMappable + from matplotlib.colors import LinearSegmentedColormap, Normalize import random +.. _rescale: https://igraph.org/python/doc/api/igraph.utils.html#rescale +.. |rescale| replace:: :meth:`rescale` + +Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s |rescale|_ as a great way to linearly scale all data into ranges we can work with. + +.. code-block:: python + def plot_betweenness(g, ax): + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/3)) - edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/2)) + vertex_betweenness = g.betweenness() + edge_betweenness = g.edge_betweenness() + scaled_vertex_betweenness = ig.rescale(vertex_betweenness, clamp=True) + scaled_edge_betweenness = ig.rescale(edge_betweenness, clamp=True) + print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") + print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") + + # Define color bars + cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["mediumpurple", "indigo"]) + cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) + + norm1 = Normalize() + norm1.autoscale(vertex_betweenness) + norm2 = Normalize() + norm2.autoscale(edge_betweenness) + + plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), ax=ax) + plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), ax=ax) + + # Plot graph + g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] + g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) + g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] + g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) ig.plot( g, target=ax, layout="fruchterman_reingold", - palette=ig.GradientPalette("white", "midnightblue"), - vertex_color=list(map(int, - ig.rescale(vertex_betweenness, (0, 255), clamp=True))), - edge_color=list(map(int, - ig.rescale(edge_betweenness, (0, 255), clamp=True))), - vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), - edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), vertex_frame_width=0.2, ) - # Generate Krackhardt Kite Graphs and Barabasi graphs - random.seed(1) + +Finally, we call our function with the two graphs: + +.. code-block:: python + + # Generate Krackhardt Kite Graphs and Watts Strogatz graphs + random.seed(0) g1 = ig.Graph.Famous("Krackhardt_Kite") - g2 = ig.Graph.Barabasi(n=200, m=2) + g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) # Plot the graph - fig, axs = plt.subplots(1, 2, figsize=(6, 3)) + fig, axs = plt.subplots(1, 2, figsize=(10, 5)) plot_betweenness(g1, axs[0]) plot_betweenness(g2, axs[1]) @@ -57,14 +84,21 @@ This example demonstrates how to visualize both vertex and edge betweenness with plt.show() -.. _rescale: https://igraph.org/python/doc/api/igraph.utils.html#rescale -.. |rescale| replace:: :meth:`rescale` - -Here we use |rescale|_ as a great way to linearly scale all data into ranges we can work with. Note that we scale the betweennesses for the vertices and edges by the cube root and square root respectively. The choice of scaling is arbitrary, but is used to give a smoother, more linear transition in the sizes and colors of nodes and edges. The final output graphs are as follows: + + +The final output graphs are as follows: .. figure:: ./figures/betweenness.png :alt: A graph visualizing the betweenness of each vertex and edge. :align: center - Graph visualizing edge betweenness (a) in a Krackhardt Kite graph and (b) in a 200 node Barabási-Albert graph. Color legend: white to dark blue means low to high betweenness centrality. + Graph visualizing edge betweenness (a) in a Krackhardt Kite graph and (b) in a 150 node Watts-Strogatz graph. The edge betweenness is shown in blue, and the vertex betweenness is shown in purple. + +and the output for betweennesss is as follows: + +.. code-block:: + vertices: 0.0 - 14.0 + edges: 1.5 - 16.0 + vertices: 0.0 - 1314.629277155593 + edges: 1.0 - 628.2537443550603 diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png index 465482dad02dbe342c5e7829e7b90092a9e31740..6151da29d63ab78b3cbeefa776d6aac2785927bb 100644 GIT binary patch literal 241654 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Ě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 y#(i);?PtUjz^YK2qZ<< z{jG=O%h5=JJW}o6MLxYZxfR5bowA?O5WtO^Inz}((pJ{{(M6GwUO!S5H#TH5(&K(u z{U&dMuI&Z?Pn6R)ZzSYI!nZh|?qxcGn9BiLp^&dEdN#gKB_N9ximTRr+YkV^quR(2 zR3wV$8oq>R+&5P?yD#GJjA0{Re}7HW?VFz9PqOcb@298B@RpcU)tNb$;CnK?o^9gF zRfV}u6nB^+n?+d}8*N;*X?(_2{d0q6p6s75u`bZ0S`D;KdV1m(cTeNL&`?-uC%&JI zK-8K^?*6k+SFqdQvP*qb{s6%yS*-qae%TT@n1lzb>z`Hb zHPja0WyfxlkkaK4|5BDcEV zZCLdOf$Y!ePQKdXxfOYsP`IQ>_>|(+bL%3@50kja*jg4fw{Pw_OLeGNeyu%jMaRk7 zgOR3O^|t>s3wr#q=^eb-ry>b7a@PcbAnHm}8KNV1=a|Ju`O{&Jay!*^2V(2=5jP;S zJd(pew;Tc+bfR+i*{++YyIn>?oDHd#Cw*#@LiMzTBh{SAQ${H_3OsBaeU(@p)2Z8IEsaz)!pB2IJ=VnN9VT*$LhugXG<7((9>G4C4&e3E}?Cb_zP9X zBC)B0XalB~&yFRGKU!y)a1Y z0a~3LI$q1ghQoXfRmzq&-v*5~!AU=Q_ryH=d- z{yX=`7!c_u{QAW}es#i<5x3v>4mABA=nD8)UlX_LOOF{%3Ol7wH_)L)&h(vRh&>Ae zt#<=27a( zaBB}Sn$A~xu)4|-LnYQ)7@froKG);19BVnR4fCv{ejJj25~F{*5ek^DqJtpRFt%-E zM9&@);3VqZ)0!Mmw^pZW`NU^`(8{8KeE~VCszHC{Di3AOq3XPo{E=?Aal|Z&-%$>} zmo>5$W1El*Y~AJEm9|qv?Q#7HxDZ_WBb@OOAu}V@5TQ^X_zFT-&^B_#;{Et_K9>|_zHG9G$z$PJ= zRyv0hO_PwAc=K5M82BRwW89={H^lw$WVqtArg;Bxo5*3XIo5)?{}sk+ClIs@a{RPT zo0~@dc_AIiq4D!$;kSXiixjj9C6N_T7m(k)7gC*-^5`Z*N?$bSfEzMdI?W*w>?sz0 z;aCiLs|$VU0X)&KeEnqSN1pGW5>+$3S3*xyn)?Eu2f(pEHpkuP^{_(LkL!0*JzSh{ z+%;ZoHF#0he?Jo)KJNlEzy1n`N7*4KL@Rf;Di+fUw#LqfcW zh>1Ni{XyO43%U_~1KWt&P0VVV9_+s;0+R_Nz_W54xAwTZ_UvZUr~iahUDTZu0Dg+& zM>;@`>rcL#Afs7ULv?DSQb%}_4S5qCqjlrzyXPQVK(5(mT0q#N(w*!pUaDseY^OHQ zD>}%iDG!MIsh)cfz1VJ>JSJoy5@RT}+i-I>2N#uW+F=z7-3_~z?8Kxul^lG0UU%Bi z!_-eyVv?Qhg{|rsbu#HF9p(vVpAyrcC}qpFuzR(iKH=*AxGnUw++g&8^1X9=wZDRR zF9X)h=ENAEMcaa=wBZq=TC}&b7rNfV{E5Su7F(}I1O>nV-F8!T(oh6Kkpg1Ye2)|o zG|`XK89gUsL2mh8a3&s4%B+2$q5+tZ|MaerDX`mzuhTxfN#;dK*s<+8Ex zCIh#a;3)}^8*Wx@CYgf2C9pJ5{ZCE29q1g@H$zhI0O*#Qo^VN?&!iLueQ{v6>2!Zx3}1 z@V^K*tKzQ>pX{O)RGVR9z33Ix5|vw`8E&zOs*acEuhOTrDuJ|YfgQTF2Z@y(?9I^< zEI!baG{O!Lq|L4>@Bu#}(*vS)ARL{evhJ8E#P)edcQED^FUF(xc1&C=GU+AW*>ClQ@U9W@z!R2^{>Xe=j zu;`9|H^92*-Za$y3WI?6f7IS()-M9>7G! z)M{2(%9$*WEL>Gg&usW-;gs(nvpR5NR`N1T)E@f}8yc)4fL z)@iK5eC`cJbaCk{|SmZ(d|SIiM-s&ceKxuZnwdCXW?TA75xbY zaIUtXXlUjzX=_agbS#%)SX*{J$sNWpxa{V}uD_2+AIvZ^5#pJVoy=N`Qg6DcG zo@co$3g|>BL~JWue;!Hd8qHplaE>i?_PH%E$9+h5$qJa>>}hiOI9m^FtlMKYJ2lrC0=olA%~R2WM34A?>=4oRq2A!IpN) z&375|)tgo03Mz&{r$W_Aet-R3Gg>C=XP@j8b|DcslwfsRK=kqdEvZY$57=+@$;?ZK z1!LhnH3Sz%0J3_0uPOcf!z)O1b$L8+Z#ju)n9sqd1BG71G!#%ET!eD{V^Vb4jwI6G zw59+iuT=@btgAn-T@I3RaS#CIY#P8BbY*i+eUuqffFip}9l$;RSA@Ju-`sqplbvn?;}6+&c5l8<;^@6G znhdxT>tnWpCZlA6nv(SF1_c|_Xel|8j?X(i`QyzvxdzIDn>nddvK^8sqq z^Q;Fj=iz5-tB_eWL9(p)w{INJ!>5i~?wC^DPmusEfZOP^w@omQc8iCt6k?z1?r`&~ zJVmLND)!_a9p-ng{w^yAFHorZLm(>$D{Wg=a=NBbq-uDa!Bd@QcT)HPWLH zQLk1ywFTRJ8e>-8DQRhfc`bdED^Nr|B`xbJ#tE)GW8=YU`B3;ZS$?Z_s&RRrB`iK6 zQVq;SH{DuMa5Djx(_oO%NXW}&U)(G#j!>DW5)^YCei!!f8oHHh5OTF9OdkEb^ z`_-^LCk}>UZA;CzQ_ffizp5&r`%NUny4Ks>jqVhmlXAt~?4{cg@C8VqU9CJiAk`W; zAAX&ZIeQqan;Ez|e0A#wTZWkMle zH|g2wxb0NTSCE|%DU?r7Oyjr(4CP)Xi?p|_iMNZoW{m+mB&_7nS|tRZ9Py=(5QSkfQ4n@$tq-WV z{zjtGlCz@?Ls!vJzKf24&U6{I^be3RNG;kt9+85i<{6pvIClcFz{_m0z(wXze}A7m zH`%grKIH0;GW`-T(FGqLuWFfxoZY#l%(uvjlYLA$>2N7EJfiRYpqde$IoWrDc&_lM z`@^N;g-R9nit|x8s6$6*o8?mQ;)4cMuobqpbz|-V&s(4DpT!vH_ELV{eAd!NofQ&V zkLpa_vJ+pxefsn;(zrj{@N;-yB}mC_?}1mXl0QM1x`4LOEH~F0R@=JvpQHTw4_fx6 zGv~wS(Nvh=eTywxdz`AE%Qit}OO8oaxRR|f;`&?@OY zkqD~&r+>5XTmSa<U?f=uR=jX79;>og}1=Ry{n4|4s}PI)2VqQCF2yhB31%Bi%* z1`*v#Lnstnwz0RoGvm@{Ct*7UOl$06UXh+vRp()Pv47Na$=T-v$eJPT)tazw4K@ue zgx1aUl!G23w=Oo_8D%G@r&AwG6~?UVzQMVQcaw=j6z#4}DC=*)(CSP2%iu8N-`&H> z30+#)Qb>{!DvfM0Zigz0+mASg=&l_@;2ggIr_v zX?;yUdYtp(i|SnUvg=G(LUB~}h5e}oma*K#h?)~Q&((?J2D?*kcm{2U zq#|5d$-K3xedwE%&6M;s14Lkp7e9jZGnTWwJu}FoJtqrHw1&xwXcT}wjX@N zydMNgo%!Dl1gx*?eEZ;vT`^EL;;ogtQj@ieU;I~@9>+o!P1nm5S)6`OUJCP9%VFME zsn7KC1yR$Mj{g23`-@JvPUv`I{xU>@3qAF_R=55EraOlpe?)|qLtkru9c|9{ipqh8 z!B1brR(8s8kY76}&{cQssOtMB*JW0%@U7vO074M2V^h$N!xj1(TZf4(t3U=1V+Telz>Z&C0?VIJk zCFFk!K$6dY3IL&OrqapZ62l^OjQ+FIlw}PULS8@ABqr096*u@PE}TS z_o|4#S*CZ50Z7O8ss9gKTsF&ECu-K8WO;JmOAv#!*~)^_l|*#I(quyFuu;HJ?T5KV z6e&S9=CR%yjQTbymmZfYug3K6%L!Y1!OLPoOmMSH9qx$bTCGv^vlTyNVgo;6Nk;Oi zx9e=TCmJ+(l)Km{zjG>*6Dd}bbtP&J$n?7T4eQYet#&7FgMQKmN}@NCb@h#9yqwqo zKcp`!26AeYlu=<)YCIY9um?0+7pmY#B%=w(Sd|PPJOyo*zHOQI4d0DE`pFQU462| zV=Mdi3)%n{4G~#E2t~)xw(9NtHOzetqwgGtZ#Q)e;E$oz#(*q_ooIqP- zYV1UFXu(5p_`*L`@`WYY51Me$ITlIBu}LTtMpJab*_9MU|I&R+fXDe#m8!PNFWNNy z+Ih&5_o}m(9K?eEPV#nii_^Q9DBmWfSm#(c#?O{~2vWbz%Rk7-Nc&OKh5W}QtrY?N zP|A3$0d{;0G5q2X0@dv04b`mw_jflXW1XquYyXhE1&(W}T-j z&V50(K!)~;s8@ou9;|fH5v2kZK~4~5Hj@gy+PNKz!?$#-;mKDP!o{;6%#RT7fX6>l zxqmVn<6C@DoTa1pH#0QcTAkV%B%7(#oMg{x@1YWM2oWfj%BAeicFR;Olr7dsS347` zPx#9`SZO8y#KM;228Xt`BoFUddQaX^H0X>~rUkPQ|H~EGl5Q9O9JMX=i);0Z6NtrvN2@d$~3|%Pahv zxrdRS(zY2_6RQcPj=W=>SpR`8JpVf~H=`*eEmZKOyE0fF?;W8LAW;faqD9LbCFb**PLs2cq;Ch74+GpE#{WzWe5GB*jz;xp4nGM|0X)hDTSB3G_wsDjMi zmG>`im27PPVcU0%ze;qYrL$ToA2z@sTg&y!NTHnJmA2J7@efA0iCbWSg|r&j~C#iT^~q;wpQje{S_-qR$6kfy4BkF zZQ`c3rQyc~)>r8~i$nc!14Gd-#}3gkt-pXQgHOP^k~xKeCHU}HJOA@5!j8$#d(UJQA019n1)xPCRgc znV|jDX2w+lS*ur;`@A&X|Jc5fL}#&F9uNa2febW78zoAcSLj`Df99=56{vDR!6c$_ zP5a*{2Yq@eX`&VNhHWpwbWrD#%ta3cA7P)`%A%@;2B9jPi^xi%ywFLr#%{GC)ob^l zDcQ-Ys|lV+_VFFIm0P`_*LPlf7z452-l0PMv4rbaGs7vq2siZ~1N_7{eh^FlC!FKTmmcO&t?=WJ{09y!NocV07ytBq z+sl*FcBRGLwj1~<)jRIQ>A|R$A`N~Qs6;kg=lD>_?@@ztTX7{6YZ5wrFIiOWdbgb< z*?EVNf|)ux2s&C!`I8M?Z84;A1!MJb;Rk%3mDvX11u94 z7di55PEBC(Bw2`t#KzL6rdS!6{QXHGStRk&=t6X3By#ly*r!JF?qoDLfI(^WR4x@H zrLNk{3eDXN`Ll=tZi3I&$^^6UHWLNMQ+!GjVUPq~mjZvVUH`p`KD6Vkot`-ux8K5Y zmB{J17;&f_bkyozFqtJFh!Ins?=`wy)~0@$;<+d|J8OU!Gd(1E!!?cEJlB@DXjC)J zBT)0si)v$TIQXB!ZM7Y**FU4U#QOUr0=H?t%A!9c<$SBkx~Jz*KN=+@P9h9dN5Qot zgc@o7OVWSHz{qE0piN0Rs7LSr>zwisXMg!KRBT!_6tvpenzH&;7sgmx{YFU0J@&4K zd9&ppSiaC2f*Auy2)kgm!&9B_|5$zh7RztH(*s>{t?Rpn;WLvYb-NIuFbnm8R4`>~ zE;S}Yo?bNuh_5vyBupZ{uI&7{X<@G!L49qzs)2paH0+F+_i-!!5`=V>@Yql zXKIL$9~fDxm(1v>nv-rEw;Ch(4gvK%1a3

    |4OP<^ML!Hd*wuzGV5H|3MTQFj3mX zI|t*6fkxqH)6@V{{pHW*_~&scIFO<_{qxIC4Gi|pKcrw3v{Bo7O~iEya&!rN@U~79 z$9~Du`G-Uqs}}4Lu=&4Q&Q&crPzWWs;!cQ>;}kH7pj~A=xSt-*1;B^ioN#)%vyZ=- zi5@Jej_)It{d;QAub>9HNQn@d0LQvny<;U4XMJ-*mrHwQn4haF6?G3FjXmDv(~`%Y zv!{l{%KB*f3mws}mwE~KEil29fd#sBySrXEG|bm}%kL3%dODPqRY06MBURRlkUsU< zkCCkdIaEy&uxOfLGOs_K2qd5i!?WMnnak5sJk!(-BfjigHn%r96ukuAx?53Q204@l z+QOaZbF^(x_Mg$rd+hYgcI(c|i_Zn9GAqoy03~)-dlkgvSm56+)SA#qi?xKUZZZjw z2LGl{Tw>v_az2-?|6b6WGdty{T|1`fXZ#Ud=kB?Ge`f8h)EkM(C>=^5ZG2Ne&!nOU zN9)>32E0wwk~T>@0=WKcn(Wk|UBR4*;pSiBM`=GmA5zIkwDRc_mQvy;k?#l~7tuYe z(Ea_-KtSiDpH7> zkMbN^B}s*c>ycCT<#9!8`e2sdDB$$idb}Z=q<+QfqqVqo;e-lp1F#g1jr_%mTU+rA zTv7xLBaNnkXlgtYv!}u8P(7a#RjYrTMM=T2t_VhfqD66OFo+VPQlLY6df#!eKVKJE zH~>NPMKcxJzWMC!j9UeKqNdT^smYhOTaIjyf7{Dm{C^*^Uya~T#=4H-8ODA-#p5*CcoQFPpmhwi&-7u|9%rI5xpPaMGkkGFxrY5$~*L%WBlw>tlj%O3PrClWG3*y;qp3z~j%}kEZHEIF>MRMO^-T z@cA@(x#i_f?uh_R@%(9{@#QNCl2UWW3P#K(IvCLO|LSZ)#y=Cd`kRunl+kg05AXlj z6WXtT&C{4r;7_uf;1-CM$RAQ-wZGz5d&(MDBm!_BV|zTBQ=yA8?OmcP9q@bIKB~>K z?UUo51sSZKYudTdwx5B=!iDm>fVoh(s{@oeI@f>`Tla*AtAF%yL z61pd|&WElRr~yt}m0*PuPEl7_S@JJN`sOR}F74f4)FL}yKUsD1{f=ajBL*AQ-&A`o zhU*&`&!w7xS*D}J3lbVbiZw70s0X!9@mt;(=l&_Y=zqhK%yX)Z<3!~>8Gt|c=c)OOmRPiRJU{ebX zcf68<>D2)RWrDG=lsg$lx)w*xIWW?}Y1avzHH6)akqXLqh@w8y1_!q4<2g2l)Vsym z=bD*XG`vdc7QH(;ZpLTO#^p7hA_ktrX1A*q;&tyK&HfBB0kCfkEgvXgT_e~&OfaHz zGZv1$<%v-4{;^Nj@;HNoMbem7u{rtoSgggc-nM`dB2i1;%OpQtnH%Zu;O-nJ{F8l_P(a&Da0gImwGMRz`--WPhN&v%C94X*NTrN@tN*dJrnryqHC%9 zAR!EkbO-spqVSaks^v$V!Dj5Q4$Gxewr;NLIAOrg*IS`fA+2URQ2+)(y!f#=1v&-K z@12*`!<{L-gDU2 z)lALh(tauJ_AA-}rzVkCZn%f_W>~-$QaSYfUgX?$r`(~wsMvUt?Ce9g*ELg6glo{_ zsZbQ&SCD_U&uD-F*~iHa1XXAi(Z@u~;WG5+$T6)0elUvI7=a;9- zk8wopmL|$*oWKu&?6P%JXF3x>6x2y|wi#$929HuT>3Fis?A0gcr0hD}GPwQM&%R6K z&UWikG^^+*xuqh54CBKz0t!kZLsPth@Ye6`kXB|;nLa)2(Y8ER0+A2y!;Kif@y$4Rrl2`O9apo_YU{ zgO0LMsWZK0f2-drmiP1Ydq+w7#X~j0T3S`#t>+J66Zwk%FDPbw;l$I!>-05Ws7klH z7&-|CR1^Xv(P}R#n62QHbqutm?Qh6i@Gp4!sNoTuN5R}!M=Roym6m_*qLM_8%VAZX zF%_#9m_rIMe`D{Cca~`D&nKO|s$hnUT5* z|5fq(#|gtvAYr4{-mPA z-`z67VU5U(C2HdZGuql?BNP2ye5C6pE=a_o2T28H)I9S6d|y76&T20X&xHb}-8vrk z*-oIDU@beb&3T&V*?ZQlT{pzQQ((M*wSUlMDcy#YvPlQ_oD~{r{&KsVbbgTu!VE?q zf=gWm6=Sk!eeSly)k?`h;dGtgj~+zrQ#vqGu>qP{^-XQwkBm0>dvE?gDYTVjg=!0J zT*GLwYvT5-yh1 z5wQ6AQ&UtQioakIZ^|eNqfej;OcD2JgNdKz)VTze6GJ76w$6=>8YkC_Nor=Zw@8<^ zYrs5#Z1%>--uC}5xc2iu1qx33D19xExfGO=Jiu{JF=+X)|4`?Pbpv2rzi^5qQX3SGnf14V4+w!`(B!D~sIxW#(RFZhQdLIZk19PY z6xRH8L{H@t>9mp`)+e0SRt|!CEr^+?4tH`42Ul&-@VIPPS|M&-N`b?0p<7Q()#+C1Jgf`GnyQN(nZ)R>&iN^EajgKUD2%~U%en=M zDz7lI>UMa}>DG*~Y5#JV-MD#1>D{~PNn1TNBl&z>X!Ux3 zTd}CgXl$RE;(c_$bR|u+`V#-w@3;$3PwAhMOTNFKT;Kmi_FImvO~OnVzzr7p}hnu}pOzd5%tP@m61O9ZxT%}&)(;H?PGdYo&fIV)^K`}YphNc;y;n!_2# zM!_DbbbxJ$htrzq_vm#I9=U;4dL`VB4xC(d*_lZ`tE?cA@Qt6=OVx_22y6`o1ogM^<$A zy%xFEVpaYWilv-}?cbIM?~c!TVUGP?hyDyO@)lUS+AA^cM20Tdu4Tcl`^X49PZMUI z|H3Uzf?dFl4YPR( z??n^v$rX*t-^0o_`~6uVhJZsJ54@l;#-y_cOm}HZz*2Wa2JMgxK1wBUSa+2PC;DgF zj~oY!<2NGVil?WUjAv(i3_uCd6b(7sU8@arLKJR=rHY5$btsV32o@{&VPt($jLXD1gahW- zEiOMZQPA+K{#a*bS@=pzv#k`$TU`guimM>nUWA@ZpHc~jU`%KGms2^diBfe8{rvx{ z~XZCTC=*r^+#p3zN?rGT!NoHZL3)1$K1a?zP-Wce6i50BCbH$ykHTg|4U!MJC zA@>+mo>)8hn%POVC>}&dz8~rb`)RC~vJ2xPLwcks>D3`4ANET2|?S_YtPZ*FmmRv9{pD(Zp0~tyBRGWF(Y^Q#-pqgHe<%87eZRx zw#SUJXl3*F*Gd|j-v=KZ4NQ+84U#`4lw?CYTN_S>%>B?`-i5Kx76~ge zx4^o;BYIU@{2B#2e>=U^2`4=ze=GGBsUQig+>2^l3Vo-^XM^L`&IPK`=kT`htCNUp z2r<4@N|)6YJC9J$$-$FW9 zH|C8P>QisiiY#=7TZv5VVF$;F5|Q1^dtdzP^ICcT1MOT70TpwIQbs}oakWJ{{A{z9 zo602QVUK=anVCGT$s)=7{?q)L`rE49#+MhlaZ+$%*k6Al)Q^k*58I*hk%rv{_@EGfgrRUq4;3tTp>Sy?_nb!63+GZ2@}D+HDJQkV&`>6MNgY;GK)Efq9eL&&;vtm#79 zXdIr?OV;wakooD{3I<$@$&^`fbs5AZ zbsp2St^TN-^E^L8uYxhi4G-etLfvL+Z!Bm{SS zm3N$%<(y)G!FqQ4w)v*b?SNNlC@80YW2!DvbxuHDi${-Rs=6jMZ8MdZGG#$A2gL*W z)pyaTlgR?``FUXjEYy6?6qpK7G-B8s{y?UD0;Gg=Y{(fK-Z^NpU13aKE@_rT%-#%$ zf5)TiXd=cUN3Gd2IFWj1aA)W6!9zwM0@qjTa1mZ(WkdP&R|O#^l-8qcp?gA6)QZSf&;?~w%^I2>>x*k3*yy~M~3yi_ssg#%WW=yuCj6#jhAp9NnZ@sZW5b?#d8=ad`z9iJz=RyZ$o0Nm6M2blJ*~iDLZ|LD zeVH#@EQ^ec7e%Koc3O%W=m)r1+%!CX{m|MDLn7MorHE)?8BY_5*8K?Em8W`VDkvCE zBUd_XC6z_Qh{^8!;U2bpE;VNJ`-GM7{`sy^Evb4t~(}MJo1SUD7rK(T6 zmpla&{c7(zN}=MmqbijO2Rw6JDe{GIMa$~^7t$?B$y;6PhrFy@bN?`>Pj~-I1jK!M zjHN0GUDf@O&8O}BSGZK9bs1pQaXFUfL4o;GI_v4(%5qtb2A3!*3yti`N*-fX z@BU3~k$o%Z$;kX+J?_bQA6%L6$Eto_zta*Iek-2Wt+t!vc38hV*{4#d9AnJ|MdcU8 zHDSK-oOXvv?S3-RdU#+Di&vt5&{EQOjuy;N15bLPXEOu8o2j*6z^Nmr%`YG93x|}dw%)71>}yE_1t#3JYn7t zI1fv|2b?g)mDh23{#hKvU6LX2D--lplvE}}9T~kq);4Z^6UrBHycI8_yxyzr(Zu9g zc^he1=c?MUbyiWZVIt5WhJN(Hg1$<&vthUJJ+tv<#{Ky>>PRRZ2PDF@Z3slCDq3#- zXR@&90anu+R|=`T=#T?3sN4|idwVD_-f=AVs@ziu8b}tE#G1Rc5s8nbN5mioQ9cDF zSUBgmzC-!Zx3|#pC9kn;7um`2Tl7z6{`Hf-W$6`>@BiWq9eQhKe@;6CFaau!Th?3! zINkONWuw~1nW*^9HZak09i!(b;gQen12>x{VU`&Rh= zVSRZal3JI&psSAQSJ~Nv>D&2JUHcdYlU2s?T;Z%MyR1%gk?q{f+FmI$a|9^Hx9>P- zBj7me-FTJ?rn)5XN6n?Hcb_(6AGKHwWY7+6 zGQM>PjjE;F_pD1VHqC769Vx!~trZG`1rKq&Y%6~JL3?=FzYgg-g!b5daPx z)P2J5Gq`Z2TG^FC=CpNoH{QH#xv*6=b8W1PD9lA9dc|FDE_{%$I1F#_L3~?MM-NXE zQ)f5jZO^pIYksW%cKtuP5=&we3^28+cJEy(yEgI$-{m4c-5luaXA4;`A5NT{j%$ux z4yR!YSt+C4hsT`$#+wLOiu)&>^P2x=kI}Ai-cC9Mo}{cgFlbMKchTAVUQw#GgZh4N z=irC~F9saA?p}xC5y96+lUUz866^c}b~$45HA_xMx8;Dv=bOiDsT9wNxApk!cOWzxW6CsL<)}sXf+^&l|uyV3}?`S&R0)<<|-VX2K5l8U!(3|C6T>nP1_JI0V zd9#t=^+K$ikh~mhKMJqJ&$CY5+LP0xmr0UKBqBHErefJx1!RAt!}7QP@Qc=pNh;_% zO}<2qiC<2)hmRX6#d^8c0&(GA z8Bp&k(IP*F@61w1k25-9aj>duMNBGBD;VIcxjGd}iKiX=>%1F=Emtzjf9Q$kc7M5!<^#*EVXggX zwAsV6Fb>gNDaH3%S$?QQ#o!t?npja(@KQ3`sJy3taG+OL;G!-| z`@DhWwgh5~$Ut&msku-|gjN+-y}K+s5{=j%{5*AtKB8iSxBl}d3rp`hjbR=(_2KmC z=cI2Ui=OwaPT#FAYuXO(Jz5mH531kP9?|P>d!gdrPQMdqS-LZK;7ql(z5X+9w2N7c z$(B$)hwCQ4MjA>MB2w(u-dLyMQ%LXwY_bQA3M2S!2&gH;Ho%pK$8NF?Wav&g^t1Z+WfpWCHV90#16XeQbsY629>ah!^Oo|)*br|{P+-v{zUPlF2o86^{4+MydExs}KOAXy21VfS z$@*Gg{I}J%?3l?9<9@xqdBFK?$b*mFx1c3?W|^-q>`{o@bw*;X^f&rbE5tk`_>#OW z->cKdfyf{vwIY)ANWuPQsC>tdEX=Q(2VJ7#B}UmhBPVj_`w0=hY~@js z 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

    &`<~j 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

    T-kc`*R^_n;zWcB z95TCT&vNKoQ4KMEJVK5n6!kjjFam;N#2|x<`gZMhNA*YWq62EsQ zA!c=MV0!Id_k5!vv-g?dnAe-&tBIM@OgIz?`wMXelv^ut@(04(**tcasa)d*vA3HS zTMG&*m)9!CFmPzk|IIm|*MXH0Vgp68SifDvX2$BBGsCY@q#eLHiZ$ zJDOew!zhu?i{dx_Ir=o@g*J+UOA>dZSeNK(N^I;>x@>K2Lc*>@t0x)KM<*hAq953= z^i%e8zwTo)?ThOYaBZ`%)Agm};1^wW9OG9@h>I1zZg3bn7@+|ykRB?qA|%v-1l2}& zmyq)T#x!V~c^SrFEu_2;_cm@jo%G*N58uG%CNByCH9%jDw4@H?5=@k9W zx%!-2lI|ylrLIT+p!ovhjSJ8p-uOGpi#q!99;;(Zp)Vc?olf|q1Ldc7#M;g8pVIfi ziW&3+tqA)4d`w?)oQ=SzA{B%}!KF<`vSZ9G83EgIxR4|iB4;ug7y6qA`fcs!ds575 z_C0d-r!EHe?mr`A-OXi^DSCAC2}~J5x*Lv(LzI2{*1fji%Qj1U@Ny^|o^HzV;PpiT z5dsfUkRZ)7#reOwf$ zb>hosi|S67m^b&8Pb=Q*TOI3KdiUdtz?_oY#4fI``C$Gat)Zx^xr-%-%(}QwM;L4l zKWieaR~N*^s1>w%A+3MxqD1uKjWYfymCA;pX}=-K+2y^JJ>M7n&Nn1)){wo}p=ikF zvHR!wmcFHu4AzNje=FDd{rq|U;>e3!%iS?a=NX;8B#SY;+zYUC3l6>}L}Gb)iOJT{PXrk2=ku#4m|Fjxt;ZO@{hiXr=uUW(5k-9tXUy@;isP~D@+pi z6Pex?vhp!KJM%j7-bD1fE566g@;2yBeYmf9aHrRI8-JBWQJNcD?(MQsKWF8m^Du8= zBEF~5>Z?bW;wI{+9;y@Y(3{ut;&1jSO@6Pb=wVAblEi7a=p3o|tK>i{?eG!U0UH20 zPc0U1xS;o@kH4?udayLEm!oNl^M+518jE$_vK zjRC*fJ38Xcip%2voT+rLo%NC$)kb_6{;QU@-8<|jdaHDl=;Spi2a)-6r{Gs<)ZlGi ztKr*|X1-^PTNKA z?S$GmuxI{zGxhyg(X(gxcRg0~)|>o24(C31JSQrqeEh@HMQ!6-P>4IePmdZJlzP*$ z?5i>wEfcp?(_Y{^s(+;DWS_;5^h%v5yGR8gCSLLSS8j&(bunGu_RYr?i-$fbn0;q^ zXwU#e+S}fsaSLU;UZvksfpyhSPp7V^3y0Xs?pT%n?ecW4+ARmUIdodZ7O!bu7~+6L zB5guOyVc!KgHONgG3{DzcdZ$ad!M)Ex##jC&a#W69=CKU2k!x$vIjPGq;M+5=UbEi zJ135g#rlzMXU{_qcI|RR2l+*I^;=gIKXHaW{ofMYf1D_sY#2PZF3pKL`h2-Szu?qy z*I%WxUpM+MPJWSPrB@B#fqAV!7o~gV<_U zBt;&nnTJ-xD_65_j2~cAx^eZyz3Asj)NhLm&-jPmFN}B0q#c`n=pTc*Id>PvD^*Yl zANTV2P+YMuU-HFpYPWlj@8^y(p~4LMLQFDoT6^jQ4k1gsvcWB{G*z4={t70_w z8S5>&NI#8G=7z_&#Xh_>N*X<3b*J*~PUX_CH45L(x4(NAtutP!XqBxZ+-2pn7rN$_ z`Jtp9ExAy4VaoQ-?+rIUys*(|d7Rl$_Tbd>bFYR9{C>{vDIcX~NjWvd` z$vSlS@JB@z=C^{7$h^n?D{S4XXlCi@5WDC8}4trrR)^ah|m{8OqvL|Z7}`jfksRQB4M)c=YC0m=Oa6xE^Q$M3@^*!eZYavP+ literal 31685 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 diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst index 7b534f8e7..faf595603 100644 --- a/doc/source/tutorials/simplify/simplify.rst +++ b/doc/source/tutorials/simplify/simplify.rst @@ -28,7 +28,7 @@ Then we make a copy of the original graph and simplify it in place: g2 = g1.copy() g2.simplify() -Finally, we plot the graph: +Finally, we plot the graphs: .. code-block::python @@ -39,7 +39,9 @@ Finally, we plot the graph: "vertex_label": [0, 1, 2, 3, 4], } - fig, axs = plt.subplots(1, 2) + # Make twin axes + fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) + # Plot graphs ig.plot( g1, layout="circle", @@ -52,6 +54,16 @@ Finally, we plot the graph: target=axs[1], **visual_style, ) + # Draw rectangles around axes + axs[0].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[0].transAxes, + )) + axs[1].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[1].transAxes, + )) + # Set titles + axs[0].set_title('Multigraph...') + axs[1].set_title('...simplified') plt.show() From b2d770b6201ee8fa986843fcad7975a3c1ee7ad3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 06:52:08 +1100 Subject: [PATCH 0863/1892] Typo --- doc/source/tutorials/simplify/simplify.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst index faf595603..0c45497e9 100644 --- a/doc/source/tutorials/simplify/simplify.rst +++ b/doc/source/tutorials/simplify/simplify.rst @@ -30,7 +30,7 @@ Then we make a copy of the original graph and simplify it in place: Finally, we plot the graphs: -.. code-block::python +.. code-block:: python # Plot graphs visual_style = { From 1edfb1ef8a55415046e95ed43da5ac6b6c9717ab Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 07:03:29 +1100 Subject: [PATCH 0864/1892] Further explanation for isomorphism --- .../tutorials/isomorphism/isomorphism.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst index 3fd206a1a..8c94a2f46 100644 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -2,14 +2,16 @@ .. _tutorials-isomorphism: -==================== -Checking Isomorphism -==================== +=========== +Isomorphism +=========== .. _isomorphic: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#isomorphic .. |isomorphic| replace:: :meth:`isomorphic` -This example shows how to check `isomorphism `_ for small graphs using |isomorphic|_. First we generate three different graphs to compare between and plot them. +This example shows how to check for `isomorphism `_ between small graphs using |isomorphic|_. + +First we generate three different graphs to compare between and plot them. .. code-block:: python @@ -49,15 +51,13 @@ This example shows how to check `isomorphism `_ is an equivalence + relationship, i.e. if `g1 ~ g2` and `g2 ~ g3`, then automatically `g1 ~ g3`. Therefore, + we could have skipped the last check in our example. From e40d37e46f105775aa14f22e2d20510e0104246c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 07:26:34 +1100 Subject: [PATCH 0865/1892] Typo as found by szhorvat --- doc/source/tutorials/isomorphism/isomorphism.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst index 8c94a2f46..f21b7d35f 100644 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -57,7 +57,7 @@ First we generate three different graphs to compare between and plot them. Three graphs to be compared for isomorphism -To compare the isomoprhism between all three graphs, we run: +To compare the isomorphism between all three graphs, we run: .. code-block:: python From 0c7f904284be949ca48a9fdfaf4b1c5b517478cd Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 09:02:24 +1100 Subject: [PATCH 0866/1892] Better isomorphism tutorial figure --- .../isomorphism/assets/isomorphism.py | 35 ++++++---- .../isomorphism/figures/isomorphism.png | Bin 33330 -> 33861 bytes .../tutorials/isomorphism/isomorphism.rst | 64 ++++++++++-------- 3 files changed, 55 insertions(+), 44 deletions(-) diff --git a/doc/source/tutorials/isomorphism/assets/isomorphism.py b/doc/source/tutorials/isomorphism/assets/isomorphism.py index 8719c14b5..b9544f62e 100644 --- a/doc/source/tutorials/isomorphism/assets/isomorphism.py +++ b/doc/source/tutorials/isomorphism/assets/isomorphism.py @@ -6,6 +6,23 @@ g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) +# Check isomorphism +print("Are the graphs g1 and g2 isomorphic?") +print(g1.isomorphic(g2)) +print("Are the graphs g1 and g3 isomorphic?") +print(g1.isomorphic(g3)) +print("Are the graphs g2 and g3 isomorphic?") +print(g2.isomorphic(g3)) + +# Output: +# Are the graphs g1 and g2 isomorphic? +# True +# Are the graphs g1 and g3 isomorphic? +# False +# Are the graphs g2 and g3 isomorphic? +# False + + # Plot graphs visual_style = { "vertex_color": "lightblue", @@ -32,20 +49,8 @@ target=axs[2], **visual_style, ) -plt.show() +fig.text(0.38, 0.5, '$\simeq$' if g1.isomorphic(g2) else '$\\neq$', fontsize=15, ha='center', va='center') +fig.text(0.65, 0.5, '$\simeq$' if g2.isomorphic(g3) else '$\\neq$', fontsize=15, ha='center', va='center') -# Check isomorphism -print("Are the graphs g1 and g2 isomorphic?") -print(g1.isomorphic(g2)) -print("Are the graphs g1 and g3 isomorphic?") -print(g1.isomorphic(g3)) -print("Are the graphs g2 and g3 isomorphic?") -print(g2.isomorphic(g3)) +plt.show() -# Output: -# Are the graphs g1 and g2 isomorphic? -# True -# Are the graphs g1 and g3 isomorphic? -# False -# Are the graphs g2 and g3 isomorphic? -# False diff --git a/doc/source/tutorials/isomorphism/figures/isomorphism.png b/doc/source/tutorials/isomorphism/figures/isomorphism.png index ef1ee4140e7397edb0fcd77d1c5df7371f9996f1..d96f2d2d22500795b5a55060f186f106530a0886 100644 GIT binary patch literal 33861 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 F{ug#u?q~o2 literal 33330 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 diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst index f21b7d35f..2acf7dcfc 100644 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -11,7 +11,7 @@ Isomorphism This example shows how to check for `isomorphism `_ between small graphs using |isomorphic|_. -First we generate three different graphs to compare between and plot them. +First we generate three different graphs to compare between: .. code-block:: python @@ -23,6 +23,38 @@ First we generate three different graphs to compare between and plot them. g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) +To compare the isomorphism between all three graphs, we run: + +.. code-block:: python + + # Check isomorphism + print("Are the graphs g1 and g2 isomorphic?") + print(g1.isomorphic(g2)) + print("Are the graphs g1 and g3 isomorphic?") + print(g1.isomorphic(g3)) + print("Are the graphs g2 and g3 isomorphic?") + print(g2.isomorphic(g3)) + +The final output is: + +.. code-block:: + + Are the graphs g1 and g2 isomorphic? + True + Are the graphs g1 and g3 isomorphic? + False + Are the graphs g2 and g3 isomorphic? + False + +.. note:: + `Graph isomorphism `_ is an equivalence + relationship, i.e. if `g1 ~ g2` and `g2 ~ g3`, then automatically `g1 ~ g3`. Therefore, + we could have skipped the last check in our example. + +We can plot the graphs to get an idea about the problem: + +.. code-block:: python + # Plot graphs visual_style = { "vertex_color": "lightblue", @@ -49,6 +81,8 @@ First we generate three different graphs to compare between and plot them. target=axs[2], **visual_style, ) + fig.text(0.38, 0.5, '$\simeq$' if g1.isomorphic(g2) else '$\\neq$', fontsize=15, ha='center', va='center') + fig.text(0.65, 0.5, '$\simeq$' if g2.isomorphic(g3) else '$\\neq$', fontsize=15, ha='center', va='center') plt.show() .. figure:: ./figures/isomorphism.png @@ -56,31 +90,3 @@ First we generate three different graphs to compare between and plot them. :align: center Three graphs to be compared for isomorphism - -To compare the isomorphism between all three graphs, we run: - -.. code-block:: python - - # Check isomorphism - print("Are the graphs g1 and g2 isomorphic?") - print(g1.isomorphic(g2)) - print("Are the graphs g1 and g3 isomorphic?") - print(g1.isomorphic(g3)) - print("Are the graphs g2 and g3 isomorphic?") - print(g2.isomorphic(g3)) - -The final output is: - -.. code-block:: - - Are the graphs g1 and g2 isomorphic? - True - Are the graphs g1 and g3 isomorphic? - False - Are the graphs g2 and g3 isomorphic? - False - -.. note:: - `Graph isomorphism `_ is an equivalence - relationship, i.e. if `g1 ~ g2` and `g2 ~ g3`, then automatically `g1 ~ g3`. Therefore, - we could have skipped the last check in our example. From 5a1399514563c3e8fda8720819e073265eefd178 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 15:46:45 +1100 Subject: [PATCH 0867/1892] Better wording in simplify tutorial --- doc/source/tutorials/simplify/simplify.rst | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst index 0c45497e9..3721f56b4 100644 --- a/doc/source/tutorials/simplify/simplify.rst +++ b/doc/source/tutorials/simplify/simplify.rst @@ -9,7 +9,9 @@ Simplify .. _simplify: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#simplify .. |simplify| replace:: :meth:`simplify` -This example shows how to remove self loops and multiple edges using |simplify|_. First we plot the graph +This example shows how to remove self loops and multiple edges using |simplify|_. + +We start with a graph that includes loops and multiedges: .. code-block:: python @@ -17,10 +19,23 @@ This example shows how to remove self loops and multiple edges using |simplify|_ import matplotlib.pyplot as plt # Generate graph with multiple edges and loops - g1 = ig.Graph([(0, 1), (1, 2), (2, 3), (3, 4), (4, 0), (0, 0), - (1, 4), (1, 4), (0, 2), (2, 4), (2, 4), (2, 4), (3, 3)]) + g1 = ig.Graph([ + (0, 1), + (1, 2), + (2, 3), + (3, 4), + (4, 0), + (0, 0), + (1, 4), + (1, 4), + (0, 2), + (2, 4), + (2, 4), + (2, 4), + (3, 3)], + ) -Then we make a copy of the original graph and simplify it in place: +To get rid of both loops and multiedges, we make a copy of the graph and simplify it in place: .. code-block:: python @@ -28,7 +43,7 @@ Then we make a copy of the original graph and simplify it in place: g2 = g1.copy() g2.simplify() -Finally, we plot the graphs: +Finally, we check what happened by plotting both graphs: .. code-block:: python From 40af0e6d8d36bfbffe9184ccebff66285af64c13 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 15:48:49 +1100 Subject: [PATCH 0868/1892] Better wording in isomorphism tutorial --- doc/source/tutorials/isomorphism/isomorphism.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst index 2acf7dcfc..e0b8b8a30 100644 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -11,7 +11,7 @@ Isomorphism This example shows how to check for `isomorphism `_ between small graphs using |isomorphic|_. -First we generate three different graphs to compare between: +First we generate three different graphs: .. code-block:: python @@ -23,7 +23,7 @@ First we generate three different graphs to compare between: g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) -To compare the isomorphism between all three graphs, we run: +To check if they are isomorphic, we run: .. code-block:: python From 25819023924bb0c7d688134b7a9cc5c96ab4df76 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 16:00:44 +1100 Subject: [PATCH 0869/1892] A little more flesh in the complement example --- .../tutorials/complement/assets/complement.py | 34 ++++++++-- .../tutorials/complement/complement.rst | 59 +++++++++++++----- .../complement/figures/complement.png | Bin 60007 -> 85235 bytes 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/doc/source/tutorials/complement/assets/complement.py b/doc/source/tutorials/complement/assets/complement.py index 22ffcee3e..399cdc35a 100644 --- a/doc/source/tutorials/complement/assets/complement.py +++ b/doc/source/tutorials/complement/assets/complement.py @@ -9,20 +9,42 @@ # Generate complement g2 = g1.complementer(loops=False) -# Plot graph -fig, axs = plt.subplots(1, 2) +# Union graph +g_full = g1 | g2 + +# Complement of union +g_empty = g_full.complementer(loops=False) + +# Plot graphs +fig, axs = plt.subplots(2, 2) ig.plot( g1, - target=axs[0], + target=axs[0, 0], layout="circle", vertex_color="black", ) -axs[0].set_title('Original graph') +axs[0, 0].set_title('Original graph') ig.plot( g2, - target=axs[1], + target=axs[0, 1], + layout="circle", + vertex_color="black", +) +axs[0, 1].set_title('Complement graph') + +ig.plot( + g_full, + target=axs[1, 0], + layout="circle", + vertex_color="black", +) +axs[1, 0].set_title('Union graph') +ig.plot( + g_empty, + target=axs[1, 1], layout="circle", vertex_color="black", ) -axs[1].set_title('Complement graph') +axs[1, 1].set_title('Complement of union graph') + plt.show() diff --git a/doc/source/tutorials/complement/complement.rst b/doc/source/tutorials/complement/complement.rst index 1ecbaea7d..3b887ba41 100644 --- a/doc/source/tutorials/complement/complement.rst +++ b/doc/source/tutorials/complement/complement.rst @@ -9,7 +9,9 @@ Complement .. _complementer: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#complementer .. |complementer| replace:: :meth:`complementer` -This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using |complementer|_. First we generate a random graph +This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using |complementer|_. + +First we generate a random graph .. code-block:: python @@ -21,35 +23,64 @@ This example shows how to generate the `complement graph r(l85A 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⋘h@$B)GdH)kYC(|+ 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 A6aWAK literal 60007 zcmeFZ_dD0^|3CgjvNDp<5VA*<7RpM=s8lFK*(F;fWQQ`cLW-0^G|W=U9vN9lnPpQ^ zR#rxz+j+g;$LBxz{_;IOuj9Cm*HstK=i_lc&hvi1t@|V7q_#RU<7P$*g~F_>0xU$-Al^$?Ue()hX`XJ*RH;JCT3pFsIh@bY;J9b%8#2_9q-0$ci0+I z<<5UQca7=?e^kRnWRik1H5D}j|7GRTqS3GGZr9yTXz1~%FII>clw(t+-xe5k`MOCL zGk+lYgK!wN%K!Xb@c;XlsLTIv5wJV{-y;0~X%Tb;;jH&U+Ga^ zCn*}!vy=UY!nYpadS&xD;O*P}Hea4IY}v9!!D}JsW#SR~Q!#gTm{c@1u>=PPx3skQ zB`5PXG&bg%Rjy45hkdV0UtuVsIJc@ZY>GE(;W^Q)JM1`b}!3+s>GkxrvT#nQ*MI#3q( z7JDtS55B*3JtbwE^trcz5~rW$loq~yThZD|{<^aG+PtZ?b;78#j*ia57cZDOIXN>j zIDUIzX=;hhE zb!woRiAUL|h{H%DG)zNC^~jO6d-m+ndMBP5dySJDkdi2^E3VYUojqhk-Ul(2{INZbIsKZ3=A|@q~5)Jx#!KBHxDll*SCEBT-{fG zeX76mhOvvMWh2#dlTxMCg+bQCYHBHmZm^ICfEz5Z?-rTe?Ck8Epm=Q`){0^4)~(-v z{7CWrxBBMVyhF5d;&z2w-j}T8z4=%7Yuu#>E{j4j zDzH0<3p)AA=5)rhXO*?J^xL*=D?ESna`^6xO%IPJ?jzqA9lf4q>wckpdu89%s)oC} zPo-&bTHD%MbmW*V%>6Qo?v-3DesR8db6s6sN0CRq-lXWqj8lS{yk*ayZ{KcG!o$2} zUm!Nt&-QHA6DLkAFE8r;^oW`GRUO9Nd9~E)L;M@}DFMpVchwK^QYk4Z{%*gz`saRi z>omW9^(rVLg5`X%XHbdvlB$u>mc6!Ls`9KplsOywPmERGU`^O_iT&y6XKSxqx$@Hb zBen0!?433x?j7gXMAlT|S8`l`=(IgO&Gh!|+l?~jYuMS@Cuc@aG$hE-oPKtOe6)ym zQo@)wby>vL11(wS4p`gRRFsub9;-*be|L2vb?(QP7hA$_-J1ITQP6eb+t#yZ&t{x{ z7T>lwGf*A2bMIbS%CRK5^$NTvvOMZynhg#eqQRXWHZVwNn30OCxqkch2DjfmAzV^t zRnDE;`b7IaHRbuacU%`PT*%PNWZ$!Q??-$kkDL>KyRDV-kx%KzJ4<`hj^42>kWy0O zEhs3+IGIBIXLeQw=O;BiePqc;gJFO^I^{y+J>!+Xvol|x_^kXj#?$Q_#7eqQd@;BAjhuVI9yO++-sK{NW+YzhHL-{>B z)^2B1>^b`;{dnT#&reSeDkv%zmX)bw;q>xE)(rA0xR=en^I6&7o?~{%;df7=v4O$H z*LIz|vd+9Xn^aPwG~ZuISI~>YB2Vdwmol36Zl35Z9bLC>-5aeq31^(q;V)U|KH$NH zzdCSn%a*-1Ri~dDL?<4&D$TulbN#tDPX2>(5xe*99k#Q#mseI+mgeX88~gNxmClc8 z-MUy$T-s0PYSHUA_F|!u;D!wwveYAaja5`AvbJBg zYxA=?ojG%6u|!nI2R9V9d(WQOYyTKFh&WN+tQS1ubnxK8o`tDFTy9Isp|rW%%SyIw z8Rb%jd4V%CGlMptpH~0){@v+-+jt*p&WFW?1t%pXC32_j*wor$99qQ@!NF_W-#A-1 zU}=p_P5I|*_077k0p5@6d34qosM;c;^gDwV^_+= zEsdYvXW!*?|G?Fe<&_nAZf@>~nn7pmyOHrPhIMBDcOS})f_Fi)PJ^bO0$Lh77w^zb+_4P+_I-AMOO6q3~kTWABJu#Gp-kR^#ypO84=EhP=GJ3sD{LJr*?)!~27C zb7jbdIdtY(_26i}AAq=u!3r^%F5_efK()qbuz1lpp5*4FH z#a}0^q?Alk#=L2lQ16P6=;x}c!x4k4|I{7r?eE+6CQ4Y|IZjD(9pt|707PCLPo}hVcHSMFav!g%bLQdR zvgO03jT?tL-|Ifn9^S8QV`GzLkABm5MJAqS5Cz!INL7_u|M3y#rmCty``cbeunh+e z3#{+{Ju>p1VGXr3wnXo|TK$8-z%_+FqwH6I_w-YobkmPTcPU+)vtyxLU0wDlI6hsB zuC%M$?eCvUER-jinRUh9OY!!sOiY86oJ7HhrGF})a8>pjLJs$o`P0bn-Mja9_iIPH zYuH0Wb+-#Q@3nD4qrPJ^`u*c$d2es;x$fI*{NBHRZ;YnX-Q3l64>x4|Z*?Utxwp{e zVipSJ_*9~-qny7=*$d-B9h=gn`3V;Z2??F|l%wY2mFGjDlcpxHEkTjY3*=W32wB{}+av)?qP9&a;^IjW<>PEpa< zm&GIXJ#p+sRL}m57i~A8!A9*DFcVK=7b4y=}id4>79@&aLtE^xUZIqu|h6a;y1)^3h)h z?7Q}4rto0_=z~;?yq5}2PTXEz6)Noxz{3^QPNGm6lH_%5mYy5tQ~2AB52Dn%{_eS} z_`4%lkn#}4C&TEq1HRVxHM_R9_IRmqW#pz!n-;LbmIcv+ay$y|Y}eN^Q`a~ztgakb zGU+Yxj*g0o8oR3Ov+SPn^r_aX8-sGk?(NaEDMcq5`16~H3HEF`Q_v`W}B48?>~t8q4~SL{@d?y?!6&JUH98BuHU-#7Fw2|h=@pg zQUWgM``Fmgtp`TEl0}Z+qp*$cc#iGaojkKU(;!!XqTwwPNEz6|@UXA9FmOmVapoPK z=M}w-liS*lA8DF+G<4wH6YZ^cyIp+L7rlJ4XfJe@&gXe8%`s0+O?A9+7TgB}?D7ED z!c}-*Aex?mfq}H&WMyBLh`|ueTSM1H4xLa$dT0 zX;-sikRspK18(b3g3GYyQb*+L>%U5jt?awhx+XI-6A&n|XH>9mJ~Eb4D0hAvs?Q!D(ces6YMxp9H!!1?p%4c<6y!<`1A09OKTcq#GizR=*OAtW)k zum11$^Cey($%@w=8RlP@oSjv>zyHd^^z>j9@v`RT6De+WGk4jjZ_eew{AJ zGr5T2>&#ziuFECMHfvdsyYrWl=N~bj)#VUD^$3lx+eUeI)%(~*45msKH76_5@SnHW)Ht;=Rl`S~ zo4L8U<(%C`(Zxn3-&Gz|{)^qEUW)+>3+`#7KR7}TyU+gQ9Gj(KT>Yk>sY45hht2!_ z^RqiT-M4isgPF^nc{cB{=Kp*|jU)Z64uAllWy<8@cT{&^+Oi*?o}{2*6gYO~sg10n z2sFR?)tP^>rM0y_P9|Wv%bEpPz9~r_2s-fo{jKH}7HO+o+}w26u3fXfbjb|=MQwkH z<#~XuoVGbXKfgzN(;KWt^{<(60gOWv56ffB~_@e6bjAS zbrcHdzd4xXYx6AsmU{oSJUQ{8SHQ&9Lsil5a5}Jx1qw+{ zZtg(A#amDpwzp1ozp}ld{BL;!Fr&Ji-S+)geg^vf zTe zP|%e7U#oVUd;9X_L|m*AidpiJ2%ZoSj`HsAL|X4SiPNgM&Hf)h7%VI-f+9-oyZ7m3 zpWh0u^uE{k-z}VSvx#rT+siX{xqEsF2n*AaMg3NM?PGzx5m^V9(I%q)Unj6W8{#@y`5HsP%Gkau0zh3eWIT511jnHRZ)ss$zkdC~(nKlw=!QgD)-diJXFT7np{CNlzn_+ljt;DX4y$eemIUq=J23+o z8w@gS21qOC`kf8P`c$TlFd>}J&b-jE*)rO6KMeI8^*NGO1)%@n110aB?vs70d?!dz zeeF<<=V|Kb7zsZ79}TDE0Ikb;ObcCTPQC@&@Ce^*P++%-SJ@|A^h9#)>^()#KV>*L z{ey$oH|@TFExp#@l?~^&A`ijclyN|s{a1g7gDVa|Nx2SsE+8Oqx$%WisS>YxzD(VY zA)J_F(GLp?UYL~fqGthkiwAMliC%n%&5#R1 z0X3tAXQQe{NWF)W=jyV&c9NXG!`HWQ+SfJi9z0Z*+J?5iS=RB}VeFxlM~?z-i=G$& z%uU#5e>RK9xHJYA{TPd7{jEqIwJ!i=M^Hv)J$B0WU+L>r>o*-bbO`6L0uK;{RZT;K zzOAjT@AvQXUB?AW<*->ZWp?kbL=DgNTD&YID*71TZIEZlFw*?Mr0e*Hc0Vc_r@k^O zyPh|o?5sqb!UFsLIDb^Nb|TZH)Tg8Pnk+iaI%o;NcAKy@Jw!4@4hM`-*ol}PyL%5^ z6j9exlTs-Epa07#@n37%V&dY0Q2zuW2VlJcu!xpZJ~*ZI?vhqqRFogOmY}@+rv3Z( zlZpm{e6p)iAhjVhGO`AmU5DdSaIcp3_8q@2h{tINRor0Zn;fiRy?IywKS}k^&4uv&HG*jC1eyp>0yYsb4yL-Hel?_V~!H9G?}>s+yWRZo4@voOz_r z7u}2&RDYzCre*!*`KGSdj*%!4Dfr{YeRdo16zL)cwcce0#xn5K^!F6H;BONedfRHF z1*axT|HUu%wxQFIkKE(XvyprQ`i7agdB9rc%@3jd7?gO)D|!Fb>uMCT+N7?*a8yg{ zKPC*?6#+&sw) zmx;&g`FU&Nrn-f6(g`F)_j!-w0l+=%$pWbrz{PoC(hPbSw+mC81)x28pudJt0PviX zuhIin-pCs_Z_-0xEm(6_L!&bfCxysHJT-MIi32l>9j|P;QDqIOrSy!ov>1a~ww}#6 zMTO>zQO-_~Qs?sW@)&20l^#R_Zw&hWTjEr^yrRfO0%JvW9z8OFLV0K|o6UI~m<1XZby+IA@P&oz8CsX(6dzt0_ep&NnH zv~JU`HBhNyB+DAL)zoNToPAY+5>wxBe3!U4G+p+=pFcyPBNbj-y*x1GZt&V+D^@?Y zXVCo&A1Wj^8J8^XAR&|5gIgK|YaE1RJY>Fa!;7f)<@pd5*UDCWfzF*rF? zx8bn5y5zSEb0G5PFN=JrsHn8$Sr%6S!$a@m{0`Pc#$BG5;$U zIrJIO4plx{?Tz8$we zY4OJ=Q3E3*$zSgE(=Y(iwuUv2;v4w14)AWXI_2f1u!h=Sr-_f+zwge$*he@! zY03P50TnWIpG34u8vsO~tarvb#V&4P1M+Rpe$X1BuLrDjb>f?vo*u`e$B)+o<=fla zgFznew|JJ3VG2!E%UW2RRc!qp@%7Qs(cfFs!gM0692{7VA3vUHk8A(lQ@DG(loX1X zj!p4(h>rwba5B1{*3)Y#_4VbEzkC?mE!7T{l}$TYA+zOHTxcj`Fe_gKs)o;u*`EX~)=w>O6qepeS7>7Z(&{f5T4Tk2AQ1OeeCx<3CH@D(;&X#?4^xy$K zMIIX<;iyAY&hiE#Hr&|(0>{3UWpTdO_u~sA*`P=ls868w>Qigi>%70OQ6Wx%}(#)2EEOy1FmzySd;2R6Wzr=J0F`<&-3B6WT($ zYR$G`8Wf`rXtz|r@HJ4JoB;a-_-@n;ra(orZh1&G0!Rc!c>t{XW_WlNnvG?XOj}C} zLB(d5E`>lb9QrA*w+|G&_}W#t8=RRns{CwaZEYMMKYr9Y>U&VbP=r0i^umSUEwTQEgI9orc}PDG_> z6fqPP79QT8g}r&~*fG;fml$^M-VJR=@^5^a7jB4#j-?8I0hLPDJI{0H&aKBOn@pwdaO3 z%inOrV@A~?I}5%WG{rJVFfhI3uFY*PuyTL@+nho5C(ZLuYOr%J1K;@4B!p zdMSYeGD9UK91GN2{DIopvzwvh2Li;`ANwN#Gm(SwRH=`*-ix!GpxCG}3p35iW{!^8 zvHRGj51@P=ba$5ntq4RbS8x;{L=GI2n4?-_RAIMnsi9d22nsq+d{ewzmkBONkHsQ8 z4?tNu6E_m02x)EL@w_2vl;b?(M#0%`5l{BZ7cLaR1X)MkvDq=O+xQ(O5jb8I zA3iXF37Kbq2ECNqzkkG|f}1hO{m=LHxWVP_hTFuVola>ULL1I0 zD0mN$7!?~E2x*ERdx)rNMz5uzZTX=I^kEx1xw&09ID^8}l53$JbUrbv_anY^CvY2R z^)`@C7_JvfGXZQ5>g#h8c@nA`$L~er6+C+Mhz*Ywh`4@T)l`rJcvVNIgIMiV={=uKVVCLE?^QWM*#LvxkF@ zm3Iw4Z#+FCV?Aevp^?!bK85(lZWG@c3u>yX%VEMp)1>%8yCUAJhNh-}X{jU@}YKbI#9@MW%U(u)Orq%H58(GqcV!NmvBnxsaRWo-*M+n zd{k?JW3LiW5e-G;L~=L;{(KPo0%kl0Itm_}IW*-UrB$p|$MFHQQmfy(FhnR6_7|f3%g{cY`RNWe~{H z)6*$_=u7710ko8=%Jl$B)>w}$i(yU*bs6^NPTy58w{^b0zI$xi=s`lj0kBfO(Ki(2 zA}Ud|JMXVTaT0Y=2BmcU(Mrq3#g(C-ooxJ|83KPt{phVNvX4Ny7Yi&tK2jsknKG5c z@95}wmid^*KHQt#Z{x#<*AT04bq?w$(PbztZ?D+G-aV6L0pmIT>$;J+&@?bmJIjYS zX_p@uP2Xex^zN!7WuUL6x;kj(>xU0v_YdTM@bQ79B^be{%tA4EX}umOV#cl#w~%w8 zakCrEeHW^&;-%O(YVqxdFR-$*y3KFivV{pEq}z1eM3zD+g-xZT_$I*D4Qx(m+D&s4 zEh#i34R>|FZ)3GOw~i?Oc%p}d*i%5Q7RItm8H=oigoI4HUS4`GdZj*AeB)jly_BvK zwG%(_z&Gx`u#PgtYzPm#tyeyxvMOW)v`o6mMX&#KmWfh1$G<}4GjWCWN$k34dz1mQ zer(A6ML<0_-6)Z5|&VPu2FE#*^fIAF(woCub*OFs8Ugu++P4N&xG8@H`lx@IXco zP*C7Gk*pAXPtbL7+G^jao{9?9EM6LzYz;7(f4#H%z?Df!jGEpqArZRr`ne4^K<;dC z$YBBF60f@}w{X^cmN%jrChRn$=HcPV0WdHwH_5-yxYMehgJ^xi;!AVPXhk1ZQOVh;4H@;McZ=2-Tdx%S9hQdtx@r!?t-OJ^5YES zPpUOliry?NEOu{TMlKezC!a6%IVUkWH02IUDd5G67pjMNgYL7HSk$m^d99_TP0_q9 za=G-2iSJ6a(sfdGg@jT&rn%U4&cOTH0ER(FA%ZG2#KJj`zkkG&l9DJl)rGLsM&?YV zLwDH)o%<_j-90?0*jSlv1O{r*-jE+wP=+hH`C@Z2EoHk=!8(ZG@y~9>(7FQ1T6X{a z^MgiIRJ4ARK@*_-(A@H(%X8yGc0MI9({9hXaRwj(bZyOFOQ1$1v;mk7Y+m}%oZH;QAAaiHYo`w;e)&Es*lX8L&383Qv#a7a>>o0 zwXEfDN=Ycb7!@@wA}!4V=Y4IBGe`mp5>(q~=A%%hWGvnf8M)=j=_q@n@qPRDO-FH# zbb)v8u4N7S{{6#1wk&7(yLSf?HzeFi8m)nIZrWcFMDc^-S^4$rx!(opsj2*sE1?fs zbfa1X!CK8f#WlV3m=eXIA;g{=(hw8)1Y`!SEZ(D43-$c^bs8f>TYGz{_LkrxD*hVh z$*C!`L)_59Ze(XWW>Jm`vG>El_%CMD1XET2&-agqN@RE3s1ON4-IUTheVR$Z;gmFc z;Br<3uOcIAAf*gxBhqH(UXR!H!cPdVs;V+>-qAEPA@8!334+s_s!33ai_}29hf90@ z#S`xC?i}tecV?CoqNDvG^$6_U%Lzu;fj*w1E+-^U^QpDf;N26T2y~WDjThuq;N7k;%tvaEfnej{!ib&@jg)YT^qF&5Oq$I#Y3ZBHR#5T z(N3Ce&$jEGC#n+QGj)_>!p*4OxEnX<#y+w#FdPKVc3Sy+1r%Y}aCJS~eAx+9Tl{4} zL_~y6ckI1;p#Wn0IGBbMg^xVS_;kSXK3{QBk-;!4>h((qg)I{YzfkW7d?&IlP{8&- zQyQHI!&Eeq9ljMY95`?wv(Is;Hrk-nr?{bym9n}x%Ez?~ozo0rYjuo`3iNdV0Xx+h zQ0tlJGCh!|0|Nse!k@P5zPtM(z!(3OR^7EoU?tqWyA5)j-{)`;+<*`-$y?VS63v@)6!TgQix-#I%RG~SCU{MAk_HXxFQx%du z)|N@5qQE+nUAn4s)(8T%u&Ah@fH~c@g2Mw5z%y7 zNB2AgivKzfc1~9kijyhUfu5E1Nn%qkhn2sOj*`~`g%Fi%bK&;3y(Nl0U%$?5WdYC* zMBhCiK0nsJqy1;kfT@*L5ZdS52@<3M36K7Gp9_#9Q6 z9R@Lc1RD})>v~&YUy;bJQ4TJyU=Tw}?YlOkgN(cBcD_SYqocDk_nWeZmWtJd3wf^0 zBpiUvMThm!&v3hVCq6zH`)~j{7|FQJjd$L@Xn#`0_`w3s*v-&TRae)Sdg6)<5I4c+ zf!^=X-tmYF6G(j?`hN-1jIm+!=!}eM8HE5isE-npulFLZiMs))qXBfjb1(Fi0c6}V z?1{9IIjz>CoG&wuZnEN?*{=+w#EXhf@k8z*heIwjYWu?_U?YRc7eMo9JAcMIb^8Zz zo6s;*Z9w+U9QHBUI^`y4HJwFK0Rg2DKJxpBy@O*WeDB0lsNV^@FS1-KavnTVgwRj# zC~_TywocB?T`2ac-#AUy6V^8aWv8rc^E@@}%~7gX&{#lJ$!T9+UfzjV6!fm3Uyv)E zAn|1;R|6?OH^^1ZJk%Z-`w|g`0URw<^R>@kyjai1=6B%gZw>EkVV6aUDcmooD_4S` z6&ROFfwofyGPydh{bD?{OZWmRnU1cxP)HmT<0?rP-~s2=KpZ$@b87+?QQkfjSMlMb zveB7NFGtO66B`=|FE1~kub&FsJyCf}>jEkdCtJDEBTZ0wy z=q}|+a1N_E>ow=~>l#oEL+bAFe@g7c1MbMRka3?h1??C)uqN$hYO0WNu_q^3 z6kPud#6*B+uj4^;e;A97nS~aCO-hG!jh_m?pT9rVez$QkPIvK7gv8AMMbX?fpNW_Z z(d?irA+I2~fB$C6^a~Hku%IAX7*|v(JUpCpi(rBr7lQ0S^3P-$*Exv&gRkxiz<$zR z>}Em1KJ4ckC}I5j_HhAA`jbN&A!Vp?$2)BXq;CqcYQqEN(z2mBw8rK2I_2@DJqw`w*&_>UYkFwG&{ascgRFJ= zcxJ8m?%f+8iNanCj*sV>o9Jal&aE(c32~*e-d+S{u;0*Gl&Q6a7q zB>O@WIRY&3F;2;mCDFKB5dCBj~~~=QaqFKlkpS} zt)CS~jWeABv|R)B;J(xm!yHp8Rq_%{SUG4@t(pB$f{i~1v+&{TH)O#kNMyC8&)>&v#Zt0se5~g z$h;)o{a+pgh;?0IH-B`oW!LoZhmV=MPrT-#uB#y!OJGgG3$fF?@?M|YB(E@YKpEky ziu!s+oNE-fO60A>hSSHP*`e>p{48uN(U@$@)Fp8aV`H9obF~$tGv%W*u>M2P#9Npx z#ZxFb>)1mMC&)Pqpr?q;y9iyihLlr*RFT1bV+v>`2MHqSUttU(TF~duadDnAQ&R`K z3+#t|O19V2WBdx=Kx`z+)Ffo?jj-88=4ZlUdN{?FgO02>G&FQ_aj~#^^5@SV%QMQ9 zs=5op+?{Y5hp*+WAV&B0%2+Tl%kS%`!mYw8k?8{LgVPJLhqM|1iHNc+BqB1hX<=B1 zjlSi%;cnw1_w{&sO)kpO8bW*R59%<8J;4X&PFNh2O(IwXIE0D!_wS;JwJB6h4c1s76?1w1Df=*4w|j`~GdYE#TdzT;A^-&nc!H_;Ck_TD4%oPm zJUZF2WQD@oU(qMeP+)Ok7k31acz#JqNl^0D%fEZ%7nYVjocmUXX9!g>h}TBqX;Rt% zE)E7U8z*NF)FhQJC*C19fqruXh~Vr?>us}lp?;^pWdAQjS?(XG!ml!1ABSWi^HaU) zFi#*oV&_6n;NEYNg#WlS_lvN)Ocf0=jsbvuNK1#IP!fq_tPo_3)aslZzo4L?o=P7a zcoMTGX4*ZSZOzWHhWm8HILx6&5Ydl96jg|X$rZ)MSTU5u2&i~8C%?(dD|hOv`Qp2q z4=+!Xk%ngz+FC3@JyuYm!&PDCC3joFA4Y6TAWeaRp5F9-h_+e9nxL-7cDM?}=S;&m zpbG|~r*Qw3gAf;6|MLMz99kW~%WnO*@#vNO;^GW`?$VadbiRIXE;eIJDt>!=MH0<{ zSSi4tbZB14O++)EDfM0ohRbV#Gzrln!P=cbdTie343k1kh9v(xs2?3!CP-Q#|ZdUPxe!eIZQCWV<1DT5`!%$*!v`GI zdGT%kp}rVil(qQATd*Jko;P>vZCU6?>kl{hP5^A}e?`n~%xDZxtvh?2yqQ_oh1)O!M){qq=5f~KvGa<AKluCfbDcr32gF8kT%6Vz?Su161J^$)&OfCIKwQM#;)6G)i zx53-51h?m0&BX(ZkA1lltN_tJ%3KGgk_?U(i`PRx*3W!XG*UOL4rquxxPN3M>(L?} zKE7s8X4uq*_ZY8SnHAu))DOgT2-6!v;SdhUEFBvgdyEVU5m8Bp#Q$J19G%rE@maYy zYbp^?Gq_Db!MJ~rZJ3djRbOj|9zxa7a~gS{WoDN5^pIp#H7HLGMCU(a?I-&CPUvvb zvGrQtOGprNRRH_VjJX7+2{YmPlP97~t9T$}ArXk<7GF53p+V%PF%M+wrFJsk$+KdO z&3}?Ap^Z@q#^&A+_4O6F&`E^&gkOc$UZ*bGWr@0=r8$jkDcgn(m0WDKhje}(-z5ad z#+Md*M#2I8-uhEIGi8eU27C)n59?F}p0I7>B+3g&oUXe&KkQ~^=A{sk^0iezY!K0D zmOhKmw2)_ZY5n-|AY2W?ng2Hjrt;e1>vU3%i2+U)oEj~8u2abFLRr=s+Mg>AD~ti$ zr80n)Y5KYIiwqp}99j-21Ul|oL6~!TCleMKd84>k@#uM03OqR#xGB-xdColK(zf9Q z`?)8-ii?X=wU-VZFH}D&K!MRA1F!DU%Q2l(=|7_$Jx0m)m>LMu*<>NsmBdm!)UB}s`T zXQ5KV)2B}(4rf{&%E_3Pv;XoCePU&Lb~fwPtMfXBpU-0OB7V(Zz;eVdymL#=n`Lby z2~T%iJnVGFxv}Hl1U$5k9n-VEWTjvW95bh*TTcc)Wnv6n*z@2=Uonw7Wb*km|nWXNcd%igSvKix+ZjB5nx+ekb2t{s^wX#>MrXxB2dF(Oy^i z>c)zS04ddw@bK+lTrzi+G6_WA{Okgpj9qsa$2-$s4bvLYBgU4^+YERP3!KVrrWMbc zkBW{i5BAqGf(DS;m?@qaGLdRJ9qYQiad6lbOTk5-aPJ=U!9yv7ijY%Ll?v14-@JV* z!Lyw9ryPTg4-K70xTl3o*f@)3v3 z%>@n=WGbNyo;`aec}3%{*b$gin0L@xns3B;19pqeYt`qnV*VG3`rBK| zhitZ4sRs}OoKy;1Hsy?~v!=DRm}Dck_@T^88`IK2wydEjgWE=cSr5W3*UIj0bmk#N z2JuDl*#y1KS(c|L2EoXChsJT~=t0hO21WH6<=~Zb@?*BwL;4-MwVKve!5x~9bTL;E z#C~vev=kx3$BzY3zu={^V5A*1nHZ(-Nt{>bLgHxvV_P0n-C+Q%CjV>0Q)%^uJl$^YLd1vP)@biSy$H=D(5fwl3ycK$!Ntts}tAjLp&Q4&ipvXf* z>R~GNYzSYW0819J1vZaX*42sk4nq1_2h;pQq#|x^?}DT_sz)_)6`dBq4hV+5(x@S! zMl;JqXm97nw49kC6{3vBLuzy;C0_nm&THe}zuyF6=K5h!odR8ayflAQ zcl&k>)(~6-joRXUcsb^(NR-Cy8^(%Ywq{kxdckFeIYt;CVjn?=s7yBvj*mZg+E1tS z;K77IL|dC46#JNSJ27b(swXp~{~5f>^;Z`s1zFQ|j*b%o-szn;o(hQ?!^#JsmDg`7 zg9t8&kvwK)PFWN)82Ncj$gN*=hT^6$kNKcL6be<*%Sg^`*l?S@`ML(<1&C5`H^g4< zibKK#BS3_1Au}hw_c@^P@7~hLzCKf2{94fF4&-f8J~4^MEXxZD(%_>Ea!md897K}mWYRh98DGG9{Z6NfDMyZc-f(~4DcS9sJ_*Oh{renrp&P5NEG8gb5v-C+? zT0eF#30h(GtfVhsD91D;;nr1mY<*q;iK~hEqL=p!~z5$J&%sWHs4t(~^Hus4ViFSfiO-&7|lcWM@ zXwcoeo3KBoAlMc3BA`t|^4LTVA-mYsik7Mz@O}8m zk-Rn2esc0;W-7I@P%&C}y|C6LaN%O0h zFDku08hC4MGXq*Lly4Z$g3SEYe12 zlC}h0BkIhI097ACqc?Bf^urz@pMsk1raC(14sYZzP%0@msMslRYpT0^9vKtKBr$Od zyvb0QvGi-GGXqC>YEp1OzJGluio*lAfM<5gHrIfh3h*^QZ;xbn(mx2?0VZNp&zKSu%M2h3rwj7zV_Cp`u_U z$#1yv1LRNx3@6FR$je+K5-f#mXOe^dISbR29t8{*1vT6JBTeat)rLwEOPVCeL=R)aVCN!_Hm10k?^do|N93;CbP$;sOJ3*SMaVWu5Hh88qiG(RsIDMIoH zfY}M7mZ*hT2m_f9qbdd`w~ehm!VBeuJS~bTq%qi&ZplkfaAI#o;7u0Wwr_u4^~{@N zWO)G-3$Q2p;of?D@ydpgnkrO|-0|X=;2{LO&}UUBd#YIH-~5Zeef=6G(TLF7iFCKks$!Jn?k#4Eu(M zgK#DeLHdHI52cL@c=#mJ$&ZSoy^O)|^_hn-y=e~gz4*<4X3>k7gU~C_cqVE<<+)Xj zGy=#3O1HXQ*Go-_vf9;&U&!90s`UZX6DZ3Z z%w2BWWl0~rZW9@qBwG#``3>%A%nWaWs6Z$PWc3u%ot2ofL)9bU2co_&&DpytU^Wet zQP~{2DH}OC<1Vti#SRt}5(-qrj&RG2_x$hyVz%42|3$*^KCC#+JUl z9{2e^efrctJX{@o90fcSh=%*eY-lA~e-2W1at97rAjv|{!tx&HEiIsQTy_R`7yx#K zWa$g1$r|{yFN|tN7!wl`%IfPSdKW*!ntrZ`2EFUXW6io0%B1XFjT)J|!ek|3QRCG2 zFhfMk#D!69gZ?CcQkgMU35Bwu0L{h>y>8qY*y);b>ay5)02B7av4oveehU>7gM*b0 zVq_c=W=Uq*cPN-hut@KmW#Z3jLQdkq+ zNZeIhJ%Z=pv198fDkdg;Kr3WglZ2CR(s+TqWsXj|E6gcELM_L!i2cH= z%p5*?4aAt#RUgdlWb!>jpeMKK;L>N1*Z*$%kqcBDW6@()e^!Uv&>{ZA<%ugR^Sw^a z&Su>2D^Tn2k@jLD$B-FWdr3UESr zMjiq?c~{Pv=LY@=+nM5}OJsDkqk_X@xSeSu0$MB~MpT-L+S z&CRW?YpE+B3|W8#5tRT#Qyt6@J!P3zHq}kz-AkEUhEO@kONex~GDAk$b#2q|4-aAC z$IIt`eF!NE_D6IlVsg@HuH)<1mDggk=^0R-hm9n(qqS%kKeo5mppf=`|6VKokc=z? zXG2*KFLWtDc*6oXU~*>0;!p>+-Jz2w+19f1HU#@(4R2yw(y;BYVPIs`>AJS9v;d4e zznUAA^YZ8;3HiheuHvJ zs4nfy;Yd-D3^Ll3D#8Pbq9_K4MUx52BM8-ifDXcWdVXVikQ`R2~QtrEKK7q=2I0RyatO zm9Js=S!@y+Dm;itz2Z@+4O_RqaI%uramD@{0T-k}c;-yxxYxwy1U^if=+<)PTv2UNOpLC%ZyV?jhmgKl|QD$--zV1ifj?;Z~ z6;?Au)j@POyKW>z)^FUHV0$nuRWC`%>OClrGhRoMR>C)JThHrcmAy%lwJtzB1b&LK z<^xPDBO4qDAd+W~v5*~bkPK;=Lx8|@lb<7eMxK@lY}1rxzBwAM<%v@H7^U*b)2H<##(+lyFgOvcHXp8qF4LfMk4=U* zl9(GLr%xeD%Z~RpUK&Nx``~;- zcWYlEQ>!y8D{I$r@_W~dR69*=?F&refTd?sX-!af-s25JR5!21B0O-{)+ZMkt_uwb z{$LY%TUu~RO!1Lq`fO|#Oq|RlLNHF1__U5kjt#x5FgTOU4?!3p*+y?s}yf;%GW@a*=qH0x%Uq|4et-c0IfrhY?bQ6V*?O*qs z!a~h+Do{GtVX?8sVdqp}t*u2|>`dbtwg=;t6%|7^1iF7j>=1AH2pm_e9Gb`UY2~Un z)9&TOPdKQCC+Cng2n-Ic?;%$Q8$k_5Gv(&>JWxPV=7b_2VsV}97q&aQ8KJRI5bemEC8rMJ<7%pi$Vs{Gr* z8apOV7?K1Q(udGkSRe((bRHFllU(9`4fjPx-3{_D+%jg!nu&2ydSm(fsu|uWK#O-g zjpyP^xBR4Ie4Uell05zvML=pdpOCmuEL{$dHR=N5SJCnDBA>th9v?UEYdPp~!Okum zg@qVvNGTAnpYjm<=yE&DX+3gSAR@V6yG9rX{&Pp36%(q~0J_cNxZF~P5{u8udcZNLwyBRp-%n-A-p znDJOEe}HjN%YFcPh^kN9id5}1Q?ko+AP zp3_4N$qF6;=n@+@Z${}Q7N!o9B-DatYJD}lcxVF||3>JIyxT*2^yKN&YJjf<&7+!V zHoEAM$)F@TXKFt=1IdQc(vxC=@THdK@glA*f9HOESWS+Lt3I;^k-kT`#6{i{XpoRo z)Byva!B4__G?on3oPuA&gEv83M?-Jx$-yG&TsD!17Di%ub{h02pO2=B330b1XiGbJwsGVPCEHK^awABa&R5LpY z=o2q1s!!Lp6lJ5|2}2s{(^}*QDsVh5OELD(ERsY$BGS)d*=@nm@wyyU>?4xKC9lxI zgH;7#GBT!C`B^HA$`p>7Chz^YlMRSE<_C0IHUCW=9#JuHwCu=&YB|nUbkAlr%h{Gb!yP z(J(d}78X{C0Md`tIUdsy}UT%BDD{*t601;Ky0m{ z11P{!=v$ld9u9Q9=uPV&_D7%Y+=%EGl2>SY*NtaBBlAm;65*|6J^&#YBs!(yYR}>L zpfUkEN#?*Z#Z&@;MZ!M3(&GbRcrhA=h(e1;F|3F=N-oAAaBoD~?}#}b2^p6R0;mZ^ z(6(+?;gQ0gHOq-`Kx^>HsRhEq!u_ZrjI$f#M8PR^M7=dL-@w07kmMB8g{KUKF;$zu zwCjb1@^GRfkw-1^oMl9~FG0zBKSVVB)NMA<=J7v-JhuVgl2{-CWd#(%Mc;sYZM0yy*6=ja>`;41N=p9xePBd=pP-u0foA( zvGMp1mp;qI#TikO=cm0wY!(#w&N+y?q|1>vaKOF(?{$r~wu3;hn1)YoP+JFM4LKBA zB6{Lhz4WW&W6=k57yDvp4|==`8zaH1=l?vxU@3^|3+sEwt>#rT~ z)kH6z&Ka8KcPq!XYQcMsXSs0z-Q-*|KcGejjfS&`=8NRjedb@SNad8k7pIKy5ik*g<*(Eps@2p?^J`Cm`(hc)=N!A0zfiI z-+Q(7EVc45l2Or1ouCV#Xy z8Y;z_q)Q}avBbnIdA&_&`dK{Y6zyk0sc`Zwjd|o`9x(b|5^oW?{2!a4^p=}P+KqVb z0m-cFMWd~EEx^iKMLl=JI{^&*eEo|iD;2K#fGq5~$*rf6^Nv0G#yw;k*`TP`RX7Bb z>Bol+9=wBgRdQ|H7A&jDl#%UK!PG%b@D1&reW53V+=3eew5S-xMBebW= zeNbTM59x;x+p$ujt@$xy(Un8Y&3wP4}~CKc#Bz+^WvX zW;NiNs>UX_j6IS#vmDy4jVq|tp4;Z)=mQo*oePt;mIVj0s$=J8!AgdlkXsPrAyTTI zgKkZ6i{Fn?99=uRL*AfwRMuOS zE&T%b`^C-?g%SHv%`Jis`Ys-9ma9|y^8^$-&=kQ(9DjMw7pme1Z@>>tHZf5#9cPB_V=&RD&j$i< za6bKebQM^0o=Z%$r)Rz09wQZJK1f+(;Mitle0i~EIggL%{`0R14c{lVG(g7!P_5;e z`rS1~4jncu1?o-GujF@;IO{(*$qzpe+fEFuym&7V9^wpkli=t5dZ%Xjhd+dZ;&f5$ zDzL3GTQy=$mz0yb5K3iQdPc|$^U{i_i(*IK3;xL&bL=`$hOSNT(5HuM_u0>!*>c5; z%Szq*>Guv@Io>6G{-8mn$(sPnL(SHp@zO01t^|IBir@WcY6F)a@6>&$FX&U&&NC!= z?k_w*q2JY%-@_reeg8+v@c5_Z zDKQuS+UDF$P%uuuef6@iv1&{F!@G+(a=7h^dBbXm_^k`aImQvBNQO1u@w^G$f z=f$C{zR^9k!5&n33&7_EVvx9IgcJuq`J+Glk48ohWssf}xT7p2m!eKW^SDU4k7Bn- z1g3h~yYCpStMaZ8xdSmUd1cF|jr(;4FqpzY*vlgP@B8;BFAlw0*2nx;Oo{&Q6ET;r zZ-8h^rXEz<)xTe!saERtx7Y02(^U+SW|7P!^WmyK#SM;b*;OLhFnpil%#IJ=ek&|0 zy89t)EZ#+KLaU4Of{S0?+I%SD!6zv#gZ15hSLq{UTm#)5j}WJUfK*W%z=?t2jZdsv zRD0e9PC64$Myk+n)RbYnw|BeIsPV1l)Vyn1NPG<#a$nZ1auNAvPGYrSFX(LJ^#so z=;eZ*iI;cH$w9_ZOJ~3cE%1LP@DDre`q(ULD!q9()X-X7ni>fo1zd0!C?(Kx*$hzX zh%P~Ph8*sy@^!~~*hR*hnA|sZTZcJY-@<2K%?;nRKdt^sb`{zkF#4Q5Jf65C|Z? z9?3zYHRP?v@P{C6n|SO(JVG=E~&x9lQlOyo|TrDHzKQBG&k<3YQg|#yisYBD8XH+L)MHfO-tc;dqaI+ zt??TiN8ppAIb(5dG-}kysAQRWJNyAWTmlOZbgkza5_Kq8U8YZ2`IG;gWvx!tY;kut zS>K|q_TgE57b%@SdbATUAEz%n5>Fu^Rq`{({H+o_wxDEvvwvKjL+MGShK-|>28|eT zM0pO7oc9cWGx@(8H(m&Jw)_}+I|@Z|M^%B<1etU zGpD&QqniPN^afp|q|c3C(HVrOXJGy+d~SlUSA}W%9p9SQ|FpO94QD5(`#yWgr3^KH z+5a=EMQCQPyH?EFWzz0?=n3)|3)8b@3X z%-Ec9a#!BHd*_lmNBAA?eedlz2?oUCSA+p?q0%V|m>dtb(p|deyhJB1ocT95p82|p z4ynIY|1y3pCiy)LPU-57+IIHOWo7_x(SM1gRJLhH2+P^;(rz4&tC7iwGU72Ot2flZv;0|YXw@meN=cEIM}_R?x*v)4fkp|&Z`56H&l_KEGUGP2X=rgV2{9i`EDkBnD(*#lnkxAo zC{peLhX+#@awE&o0-?@;4s!2?uqab2ZE%d9RL(#a*6*PAOxmD(oQti&e7PN`9Wj`^ zcU4b56D>3X2oOONv6-Pvo$ z`MvC`(7V?wG&EG4)`_tqRXj_ty6SIZn z);lKKa|@+NYUR-prsw&1Gb2m2O+nQLkV7uJ3v!%J?xDqu&m2F31>4!#IXF6Qhp9n` zVgLC|5l_gp)>XN|_}k&J{{}>ieFE)}eyNq2`Q;A5|H={Zz|=c7qkp@o02sXPkXFG+CFK?Mw* zbcezn2d6T0fL)@;ys$ozaOHAhM=yJ-!_mC&iq?n`9r+~pKnJZ`Ug;IHX~B7$8Xa{V zQ6kU-$6faYKtlPvH|KgC>sSOEQpAHjIdaxR1zVoHQ;6Cm*yNT{k(b%Y?<4PDkKPq& z%*37~gAc$H5`6o=zJyegSt+Nx*{-C3(a)S^WwoSZMafh6W)V-P;A?cKe}z3*v$RUL zA4n%?Pv8x&-db8Q>S>#_UY&pl!6fvD;mrem2M@lS{9>BQ`M=b<#`^i2u5Gj{i#ZGV$91?;x%(+~EbnDn@Mk^fG?ID{&%r$yXNY$Ouy2SF@1HY(1uxXu40 zUMYOA=E2&lOIEGwZ#AZ%jAJ@!<-0|J({%N*wS$hTg1heopS}xr7PjFlXd~*m4jj1R zl%-2EF0ltV=_BsC^A{J5>z4ZDW6+omme0OMO~PQ6yX`ReOu$Bul zEX%lm#?{xvJ)V3`>D#h509J1}AT}aUk=#hOp>_hHZ(>BcvFq%#HK1C(jZ*K4+KQA4yY@4sf&z+RHBWVO8z~W%G|^|lGeZ7$_nTg& z*42G%qS4xEQVHM(4%O&EK@AwJK5|?MfWLLiYp4$BQ(~Arp)iE%s{8$AoG3uxQv$1N zh*d}eYY1GP?i?_YzK%jo%t0V#SstETGhI@)zP&b~wyu}f6Z*f_r1EeyNQ{~HrjPec zAUe5Grc!4fJbwJI!-qSFFak)X>;=ZcU4YkbxS~ifp1`g=c=+(cx_P8^d!bl}Q?CO8 zq}8xH83nSk#IpT$ux7K+N(fqx&@W-grdXmfAYqXHG>^2jzPq7kNHp9lzIos^ zw4X}inqRi5VNt+Po{D3MKI{kog(@1#!K+?(@f!a1Q1FI>A*YLfrWsZ!Ok0SQldd@3 zXFB+x->a>i;c5b>C{`@+JOopG~pdYb=e{)c6JEWPK?qW*%JO!86^e(9E& zpuYb2aR~T_v*jOvYsDHjmHz#s>=$3WbW`WU^uHEe90Ceww%hu z|HNr>=wk_yvkNp3#R^hZ_m6kpdH)-;Vy&~_8dAT&72P+l9>$ZAC{3fNCcD~uN~zy{ z1+1YMJ!KgL4th*J5VdIF$0=HyQzieQWW==Ea5F2bodB9tQ}^DLH8^l|5Lpe{fmhej z5)TK9kDTvvGNwBHLefnImYd_0) zWUEwVb3}}gD2}&IK)>ji_ir})Br8S&eH$tS9t1nA{@fp6jY|U@eW&sa_ya+@{Qc*g znbMvQCBkQzQAQs~lrmj#zzY)i?qF)dLnyo=HGf_Kwtw5=m&gH(r;jHM+J|01@$Ke4 z@QSl+MMd)X``noW01vL8*Q;r9t`|qa;-we4eYSDkI|BP744oDE#RyY4;IJIq$OJ?z zMZkgn!8i6zJ2mdt5rDn5)NLE=|6?Jt-v#`=fBMK(M@P3UC3wf48p1em)=@xGoaMpg z3kh=#%{JjPC&Nzfc|T9BB?2E2TFf)#DfHt#{%fTg-sy(+Chv}C{d@H(h;iJR^LR0M zc**?XnuK8fzl?R@%g9!a>mCp}PF&nQUXae^7UaH z6%-YPeymA2bHMnAMU^Nu7~2dyu!T9|G!BQhl9e%+{X(g3?v z>aZgA5WjGjs4YrO$B;C|w^oi-zLS7elc8N)Lc-7)9Ojvt?(!gp4qxQd%niE2!D5Ju zOTpO}aOBi1^yZj;Ky3B$$Gf-~gfBgA<>Fq=uzj_7wv-_DeoRdZ}<31MPTj)I_ z6O(P&5fOjy<`_B$sL#CExpp%`sD2 zRq%LzY;0xqyg}Pfu7C!TV#u8!NSu>CZsBaC(t-P3Ygd_@CRy&f$|4<9s7yqXO#muo zk_YRV6^X=OmdDpt6R?ro4{hH@Ly&WBS>+_yL?8f^6{357%x1ccP{)8XNJIK!n%!7B|i zazDGbF~ zO{wXuJ|ELo@@sYxRdMIBGH6a?tot7{vXTwNjoC;BENHavXP3lxm34qKAolI*E<0ID z=XjEE8h41_Pz$r3tw9ctBNYXAeF}Qb(`V1#z3oYv$#+2IC=*5mx(mGU2~C>hUF7Vj z=bJ7>t7tIp2gR^mf~%?sGF?9%&CoCaSr*|fk?P}74d$9WDVw7MlzXi0u|x3EcOE?O zd74Jt)D*0XTMKr=uL~#VwegKvRj;yYZvHzI(K1bp4ce1aL!!=r{6r1P*=1TA`RLIj zq`XO)>WmdjteKw90?OMoodOgLK!3odtKxdAN2IV91A^q$A%@a!rf^1d_O#*$k57Ib zr`|--;gQuy%{v%V^TSiv=UreuZE(WRM6cnTkQBz%cy+)#@##G0_ zS|)wf$N^A?EyKB+diCLOR11`FoMD7iinc7|*}Mz}nzF{*QDA$cAf|n=3O;V{D<*8Z zyx9QV0Er37^XXKcOJa}W+q_s<_}?-dZ>gGwr@WyS=o_rTSKhFwOuG~&898#X}t1)#*-(*D)8j1N04Q|;Eg^~rEcpdrLz z(^hCnbR$Pfo{GjDCyK(5TL2I4oWkFzq7LJF?;P}*$WG!W50rY3A$u0mr$P76TQW}G zxHv%C2$4Q2`zgd_#93;)Oy?oX)@H;_9-QTmgkTX%b4E+qT~LB@sbuc8Z@fCo{@1zZ zt+9an`S}e%Xojjx0!X;7Q#hX_1{0e6S^BX#h!Y$ZEKuU*64f^Cb3C>ZnHDh|Dlnlj zPepb8|Dw4~Z{1vMGjXlL^Z+U6*h-E?`PqN%lh>_P6u~#;A!enuB>`LBZ`pKg?Ln*8 zm+_ZLD&U7W=^q((wnwc-si-e$;(ecOmPuA*=bk(z|Yx(Nn3nmR;p<%Rd*;rAhBb zhZa8|h4zZd4J%hNWqd0H^%UE88PGv=g4vy4A`FIN0icV1jS@S@oD%@Y?;CvdtGbyz8)}bLO0}M zlK6(PT01_q#OZH(P}u;;=-PeQtl3lznc%8;Lx~`j;hbE};91+K3LUsa(0Qgm&0pf+ z;Kid@K=~-3kdU_UzDBBVODk_o)}L%eN(VW7{$nUqgF3}FPA>4LzKOAThwfD6P&44c zdk9Enjsu}$*v{p6rp+Mg$LajCZ0TZtRXQt*+_&Vd8r}>C>EjU7_KNyb+oMi zPF(6gY7421NiHzkv%A+;8;%HqlVo%$rb^SWwmaSq=h+pe1?qaYC`Lfft|rlO_Qle` z4TBrmO~7Bj7q65~7rYT)63d!|E%(z%BWRaPp@^ry+{wYX@7^AT97~Qx$-5O^RC!V% zf+U++i~??AHbrF4n;-BBRKGE=6FGDpQ5Ktw@>q(C zr}e|aM8~T(eBps^gi*@1h@C-rHIAY3(e34e%g^u3mE1r3z+6}bzXi#6=K_e^UPR;D z7rud>MshwCyPhOaP?ua^me^N{DW1z4py%bs7#G4P-6_)99$Da;c(F~FM%lL7l)0Z? z<^d;%(yr|<=)flY_-k>u+ryY60+d2q-jtqM4&Nk;BFR#d9ANrv>+0*raf;Y%`G-s< zoD2!GRy^9x*Z~>=t+5!`X18=`+O%0S|KB_P+w)aH?6pHDUzY?7g(j8&Oz^t#&wp7g zO7xH7&_#V3;_`dCI7L^Eb2@OzJ)rp!64XMb1^DWc4CX6oAR5o|FzS@lZQD4!N;2a5 z{%n}sUS?nlq=U{pK&6gau_+{o%(?K|xRuECH3v)Qs1H4JLyuc@`Q-OvI@i!>LCTzg zre*`Lp9{xr_-q%_*wbtH#qSg>&=+|lep74;ePOb zrNA69?(6TLxvAQ4iRXTSC&o{uRhFg8@78rUOEU#wSin`PSYG02)6$K}Ga+fy)Gff^ z)3?~1#6Y5(m80j41@5b;?yqs>Nn#J{0GG{x^&iYbY7&&vnkux`XKLMh#5R6__B7b# z#omsCe6;#l4Fz}L7u{oSP2h-WNaaxqk-xX<)XA3zR`M&K%ezEJ%c>1>=6mff5y7TRk7NE% z!H^||kx^0m0X1}TrZoLOzzTDT1Xuy!gXNvAozmC~f6ehRn=O~7{5~;TBdN_-CMz&b z;q7qQ$Ig%Dr@op4lt|_0UurVW$^ViXVlu}uj`u+~T(2HKK_AMl*{MC}yxPZ)OZup( z{Lj&dwQCoGsOV8|V|$@rr+4G&8TC5r-Mv-TY>Q{Aj2O8~g`7KU)tbK3v`20d9TJ?A zq)_DT^$rTMj5J$y-x!bqkY5z14H`BKS?N1*!h~qjAj}?(|G~}S8kby3%AnrLMT;6C zOQ)o5r~ty9rFZJ8Bobz1IG{>Jo|iUll)2jd5hhim!?Z=+7e|I4}Kutwq%B1R(W)*GeLDX$0{7Duf z3cX+PaPVot0!FfhQbu2=bGw%?b5L`eD(%)oF4#LtdZ1 zJL}o2gh@;7W_b>Qnm6gXST8f{J1b@*W`D(LU{sT)+57=65seeqy>G*PVW~N1uuB+N zCi*oQAnoetPUj~X(G=SR^cnBIG8w5#dF}tun7wBEP9Wo4-**1XTi?>`9uofd&&wWt z_yUHr+XlRIVo^q4xnl8Q;93zINRAg?H^kHuLuYN@@@M_vCVuN0rUh`G5bVDY4DGs4 z4nkm2qlVm`KbvYoOeOsL?QBg{kj4F0SRC!OdpmQ!%pKNu-UJjwF+Zzmgl<0Y^bRTy zZLOKX)ZWlSl6B88B%Ak6KYaaau6KvJct9b|1+jx`jbtF?Ld02KHaBU)`L}@TLU5;i z8I*@WkeCUXgf{ENwxcynMe_|@m_x?Fhv=U)^&#!dqSB5Z8AqjZ zfy}L{nnZp|UHA3Q0z_NL>L0v9kaJ2dnx3{V;vcMAZYmJo4CI%_Xb}k z79;jUYtao;upR-~yTpNq=KX#OyzB zzX5Xl`tzHkqUiM@L`b?h&xr7(iSrqAk`C*?EMLnuGWB}+mS2}AM9nd$-`DHoz&*rD zv;L9~$p>h*pB7pz-Fa=7CQu_oOI?9bOm6Ka&Sc@*esQH`x|#bFoHCfm#%pU|4OkPQ z-~XREIz55t+%V~F`(Mlx&+ek8N-HPu34{Vzkoi{?bS3CYr|l4BhXZadAQn2+%W=?qr8 zPo&*H|5$6@`!jJQ#RSBRA_DQ>$2e`N+jEnvIqZcYqdyJ&{WCAF zP2U&4HHj*RA$&F{FLX{HaVaWhMa&%nD-^S3`?hUg3q0$!zq?K5Shs$Be@z$R3VBIL zWI8F5n;iyPjt0_NX!EdwZcR~S@K@UH-Xh9*w5p6g=i_QPZr^On>eBCZwVQ`Fv1<(+ zbbsua4;vnznN%?-?RK9UEZuHZ*l|>^W$rIvDqneTCATUt9*<4BVYQ-D?$Q%+| zWY;M7YcT8Gs$~RfiQZ4~ZPQwgIkRC)fmH8%DK%8=+SwcW)@J!uV-J@Z{!59JK`{N8 z(I)Y=R9CCltxHD26;O4<@8me_;t+QB?<>k<>uq_Eflu|xJanq>m&T|vY|pAqnlwp% z@IYsDr?&0dS(fPrc}gL6TE@wMSk@P_jd zA9LbN*m9Da5sDY})TQ>Nyf>=SsknUb5c{BESxAkD$migQCLek2dP^^3ni3NSpTp!+ z1@>u~rlODuHQv1ofh&hwg$}dP9oe-@msxbSiXyW$yhojK=XMr2QFCu501U`fIdBUR zitxQ{9Kcpb$+O@*RC#2RkvGaR$81$~YZdQH!>rKXq8~L=x@9n`0Se*5PoMTm>wKEi zEOPQ~5x$>!ojBpFB6Zwks#rS9P@RBCnVFp=K@K?T0d z*J2iqjIj+i_Ww7DKRj8lpx$)k0K=U5y7p3 zjH%GKw}Hzbq3#p+HDGCWFB%wSG?y%{!Odo$r_Y$123*hH`4+EXBvjx% zzEQH0;B=0sY4BtAoH-K_HVJsd&PvQ_5Lk5M_nh-0?Spfq7I(}Sp)3gm#Yg|@XM9Xi za}*UfLMSDujE0J;6WYuAGwOOH-hMa+;W9-q!_S!wS*UaxrKC)^r9r_<*|>A(W10~Q zSFynb7NhsIY(BORf+ZQjD%s7PS9^vSud%UWk5OZ{lYa+h?qvDT!Crc=Ng!<8yn}+T zhhC$rJYo*Roahponm5J8JGg93yG|r)3US0_0!F1N!ZA2_#S8Ogr{GSduRy&bi!6VB zP62_j9QO^w3;&w|JGP)y3ZrEqKiO#}?sv>Ro-C4}AP#R+rxjw*0SY4DF=E24OskGFIQ9D37ja8kBI3(UyaHANzNg?wl4KOHV)XGc$vGO} z%x;caFAA_ms2|;bec$a?=esK<@af%iiA_0-DnD3=VTiW-@zbaGX}cxRip3|2ML?5~ zXSbPmE5!~RidFAXJ}7I6(D{SS}y^B1&hN1 z^_86=cLMSm!c@$cb$wi3jPyfL42)?ES5O8@U;IB!WE`G-(a|*X6PL4D)3-O!j)So-yVC%Ab4tG-0kJEMHxCdyT z08E`bl=DQ-I$GiNbKj-G4Gk%uWG)-)_MX&iB)lMExS8{!r)28DhMPXx!?D|ycUN(| zkvogVwLB&|x^G(0rw@9;kW+nt-jHP5h>e)?%;__hjav4l;Ux3NF`? zhUfaWafS8mr{&=~LaxQvf54`bCXxYdeW|6H`PXHPn;Om%*_v>ELC)hq5=GPw3@I@j zKzvA2*PyPa)_+&+p;b{Fn^o`Me6wyoO|Et2e(?(x&dm1U01|H`#EPgcbKK2SHM^!( zA428<9xe$&a5FM?XRHMSwq|4n^o?9@r! zT7SL3x}ioQM@6?l-63s;xvd|IY%AZPL93_+-ytf0&F66yvKpk|B~Y#K&6};9T*k_t z1Sd#j3ovL5wp$sayS=fhPJCg@S)V`5GTX?#y|Ci3q#8k_DT==LAcaQnmdb(OnkP;n z+>*9Tuf0Zhjrd2ek5y6-bRlk)6d;lQ2^Y-WXA+V7i2MYQ&^%2qa2NGo3rW`4j|(IA z^=UA|AphuI50B|f!VU1I@Gi|xvRNB2i0C*emCx&FhHwZhzj*oD6U`E<6dQx~ty*1Z z>h|;N8M_p6!VDSMgV8N7UOo=HjgHnE{XT_Ja9Zv4YuEbfpBbIntx{39ji98*RMGsY z8sMJdY|7~I$WH{hsI+M~**Xi+$%JHAp8VhF4{n8^72!aKj1*e?Xm*|(Zq-M%^%CyG2bSedS??{(V(rbzmNET)W%sqK z4>^+nr^)zAp{SDi)gZSGVfOH+Pk;#%>%Hs28F<%F#SY}Ob>F<{|M;Vdu(efwJjloU zPol*y)yrj!?Opz;HNUG=vynOO|>@gWa)5*WT@&2Xd&T+fSS);cR`pRJH3Am^{l{Xxm1oP+=ILbhG5!Hp%D85zq)zkYcqAck9G}Fv^DDY&y zTtN9rqdOOyd~IK;tACs6pA)(Aly;S#bE+SIC;*q?0zSIg9ee&uihMJNuT5$^^-T@C zJk|+cyx5rjJefPuIv-&6--*?*F8_@)asA{=`Up*8Ly_;$y;&69p;xNi35=y^l~ox^ zR?hC*V_Szax&&Ei?prDjqd*;G853nb)#IZ7ge%;gT3K(?j+&i0cWyfy-0}ZR1<|wi zf^#(~2{Zj~3=5c@(9&KT53fQBq!QQ=fUQfq|1WUQHoEFqc&(EHkOlB>)qWl)k4>{z zuSRr7i}Dc;H{{YDja!wP%<hiBP{^?A%*d1)t4&X3%}drWrgK{{0Vv=E zSv4D;gj@A*x7;Yqe9_EO7}FBF_O%?aL`06wD%d=}{x+4#^_7#Du%sPlH3Lo-rUy$GU5bh}LbDzVg}FI~JisPyX`}Y0c3QA+n?6TX%bVnj56h(g*R`_t34qd(j8dg5um7 zM44YK(FZ7J&(7LZ5oQ(D&qAkP_wHU=-u-7lI_X94-Mw4e+^LOmrlGOfFOj}yo@Xyp za?bMD9#@@M^?B6k)Q`Wr{T$VF&a6hmeCIYZS#x&V+2mhOU%aStJkh;f_{HwsO*8nUnC?Aw;li^Sm!3dB5n-39;te4kV_*Pl67hF=u~gjIrzxLq*H+mQ z{yAlF!$a1354f^qB93rvd=McY^F!ta@-2jVQ*?^7IDX@X+ljg7*O%qCX1eCZ0l%xL zQ@n@SNBGdUEa~zFAR@JGm^<$ zLhMX+bsdWQmyvlh?5?feI_5kF8d%ZA?;8*lX;@yipL_L6Xh5-B!Q+{?TFbCN>G2e3 zgg2E&2K?H%!t<@%vRhw2^D<-G!PAL?vJ zizQYx;;=92+Zh`-#lVsGJLRHmPp{wTCc6 zh3R*`AmtL1fu>#nvhs+O`%Y_Ql%uhtV<-@{3FysrO`R#SqdsmxfL&co+5|-tX7cL0)^0vPBcEZlC= z%+i0ucGQw+BPHUG+gW@!u5Z(xpj;8_C~llwT4JyI#?I6~R@cV90!_1?y_#wrCj3@* z3Xmd@OKkiOxNOH$r^?^=5yX;XTeiWvkI(jQ@j%wy08t@$qGS+w1zXrre%(^;!rdlG zreeYr(Gnltuj%UWSk_wn@|R&2x=2LM^7?XdU`g$poo&``R#4XcOW_0^xQ=08O$H4M z+cKltZ&7wgCCi+t$)_y#T+Cqc=N4oFE4^O2Y0w0oHCZI;=}}C0TX7(^vBm5vJu!C3 z>qC#@+Kq@5v?3sc=A|K9HwT6R4-^6e3pf) z)%^MxCH@LUYT6Vu`ggbX+@Ioj${%RpNR}~^V_x0kmllGIh+UO>{T~JW-B zwp=T1*0EPfbg3y^bc&j*dXX0{kn^17cJ$CGT5` zZ`Bn145!xjzt}9sIz#0UrFCroZNJPcEhVd5dIae*c{Lw3iMLja&!iIjqdurkVv2wJ`L*#ji6Tg8*5Y;~dIY4U_U; zudIAmQWCN{eAp&gLNqXph>;K-Udc8#PKG0rz+HmU@_@y^lb2n_1O6DYKQaK7>F;W^ zkFhV3etvTL24ib(ZFb0VY~RF$dQQOYq{eW*+FYox_#T(Gri({)Nqa~Diw?;Y54I~` zC6xzv_E8vn?=;PPB=t6Y{p|OK(0*}VBSwrM2QHaj zIZrv4BMv={NtC^n{h-;*Pmrb!lmhi*6ZVV@u020Vnf=IlFY}8aAA9QP2r(%_?m$QF2gk6 zk>bM;R%P$d<>piW9(;sc0(AoM6y2MC1@KUt+iq1}tXBRf`?+&{scm~=mkqR-9iVw^ zT=4y*^g}&>PU?1Yu?+p_MnhuatPgCXNvit1ws^oppW60>9cufSpvY$lLqU_ltvoN3 z&dDF0MD0R8)RD@T%1IwyX|EmH{6L0*$stcdp$5R9j_ewB?OF#?sqat|J8(GyMna~| zI&TyKBF9lN5Lk=--hK4wn-jLg{rc{@Qtl}AWu_t1F4yFL7rSBa0h>v~pB6qm^y(ZP z7VRIrf7xT$^2*l0vTVcTD#e>iV>AuKD*T5qxG?`&5us-T}$ z`Kxf1DwAI7-Max6|Ky=NjQ5YVvzfg+n0tRV}Ap@~p4BvP{L^+`Q32qaCo-=*DE$E8ek-(;^x5(D>u(Xy@ns z1OcPYeEKdq=MW60j1MYv1$VtQcLu^t$ zKA-?sEJv*by|Q^-MJ=UM{9e6%`<}yxAMU!DPi3HVSu^M9QwYyp61tfreY5Sn(0;XV zIp8iOt*icc{rmCSni@E##_eu$W_5<^Fc@#YKGYcX3AIZ?#ul}jA^p@8LtB?LOuDi1 z_N>P5cbp{x>yDvY$Q+{$TIcdy! z`d91yDfgC~+Tuejhsst@r0Ri3e^|9gO)0%#LIgSQh!&0TC@CEXjurI= zzbX8{?d&rXn^Yy-rkg#c-KbYwI570`_lMkShR%@3!oA^x0Z>s$srCSiV#SQC3pf7m zma^t&<#T(%UtPR_W28_7!cSY#B2uqQO3d0K0#XbX83pe5#Oy2NG)%n=D-i3xQ7^xa zwIBcaN3@mlRX~QkLHXP{rd8vEE!t8IB92`WQN-5SNj3HS_s3_KPwOqUdz~4`@z(j+ z->^xJiS|T2nZwP z2w@zemUG*L)ht;LrSemT)NyUN|9G{b?3Q?>D6Uh66}Zn?8a{4Q+qQs*Y;wImWR2AE z6wS>4xX~1Hak8x?b3gYp85E98Oc482UBWXxnx>=yhBQ0WwWd z{i??5Z3N$qkBfw$cRA$9_>0|C%d|ENEmvk7wR8pGpA<3pDKd&D}y77 zf>lccBTk?8stjB~wc;JyCHTF}GLeW2dMrHP=o?47ecu)0M$LXYJMS}BwiFI!@pP^# zDk@)z@DQlp)zy{KW$vxuEjc?l>ZAjpwv?f+@^BG!4qWuG72cS_yWY*n@{^$sACqRA znQaryjvlYoAB|*U8!@=d0@P{#XCV} zMLKgM@bA7lIupn#myFamZ|-<35tM3>JCcpUifW7%2U7K~#>e|GgWyW29`525Lvb%j zeiheO%F*^lwzr;^zUyYTd2qwr9fQw1IcV%p$-Hps(qC6>6BuDi|KzkS5r!>&UZ=4B zf$E+f2%!Yo;jWFZ?xn9kz4uS%mnT`-Z}CP2FL{b^z*~t|@mHw}=012h_kJLk)$rlh zUeCRMV#HdXlCCzkwsTfx^`2&Hd#oh-77VU5UwO)N^UCBQgDT#2X#&Y7(++|@Fv^z3 zrZGVd*N;u>$Z>K9goC_lkIj0rR%967~)o*VjKLW*~4m9v_8a?1E*K;CkyDD2}}!#A;;9 zxfpdYu7JT?HoS7_Qgi76X&o7QhwW()$F=4DS#u{{uW3Bo-oC&s{ovDQ&wLQukO99R z^;HpyWnqLRYLW2NXs0a-1B(WXxANsQ!?1c~O4JgZbJ)G3J378MT#XPS@Vv@_2XAVt z&(CR%aL2LU<9VFd7`N{Zw|bHX2=tM$Eph+YUw=^hsh+H=e&c&Ca8SB6k8Yka#IC(og!>g`*%p8eiOn`y;h zM|TjMvu39-g1-06lX_Un4rJ`W?|X+O^yyMiV^0cogbf#;clk3Eoy^0Wk8StdXEth( zZKq|BOT5sCHD8-N%v@(uaDn%6#m%|F>!?+u)E^&CyJNH@R}tN72{Im959-RWJB#~_ z*mn;&?Hd-yH20;q=G{HRiad-s3~{F1<3zGGf*M+ z7cRVI`#N5q%jYmjT@hTA^##@W;y0+27pJ>rk2VOsYI_SGj0*J1rSBUFlNEoL;Az}5 zf~Vo+=NXCsiD%W>-H_R9`ynwPIq~i<;NJM>$%U35<7ao}C2?oTs7=XD6xk*l2j#5g zAIqa4r8&8|i|@R6(TSUg&szEGq?F)`Gdh5*pP$fH$=Ug%igK*;2XI7#h}UE5emX9z zd^YKEbBDI(hb)(;eTCCPduh=@yJF)_w^y|`mX;5Ktmy82#D~Gf@3K9SQ*t3X4hdL% zZtoe9edkmFZpLFrHf_GTc!lw(V1-}a4p7u*)rW(>!3Fzi>$o#-S)a}G2S0MhT6|2jG?Uq9?-m7av15BrAv zZ0EeN@bI|fQAI@yA^9vrqqN)YS@W%Ea`OHA2vJU|bBkSf=TzBg#;kD;vZ4L8Q0 zAL#dPvGJilHwwH-5$0LiHX-HypoZLv3d1kf5P)dx=84^?C)e1JuD9oseXdT@M8Q7 z&81!XDwc2K6ihpx%d*Js9&wvWLX_#Sb3xA+Ql;_-O7~p0rX+oGj$|&Fn%?{Wb+^e4 z{_Acb1EK0U8B7)z8=D?1XHQNHjVSuF`bVv0U4`DGdfmQ#lL)E@rOK=m3hYYQz|hFZ z7RXT1S4Hn_OJ1xG5D4UMp)y`vkH%*t(Z9KAMzd$P7FQCT z6yQVO@15i_;rvxHay2y_)|X~BcBEJE8j^&X!rZ7_T{uTjAvs&=ksW?)VL$EKvu8U; zdq!pwr$Vf%(vaD9b{R*bON)zToSDRi*tGC-?Ji9Lm!05pGHV&jMhaZNOl4Ih?d;}Z z6z6FnrH??&hUIaQE5fg_%xkFD6}{s2ROY?dKlmoqTMgm=3I*33vro@(tt)zIH_Fa> z$H6cV$==9YGB%J?FSkGo4G|9oxoYRji%)}?&=loviV}`J)d`0+r5y5cQ(xV z{`uwr{*pAsN6zyLr<9d`lH$s8?j$;FSLex-C%dFKe>ms%BR^EgL%iy4tGLC<2guAebu-%HoP>gsA~ zqGSy^{Mz1ftRXf4uvM)M7j9EWN*q9(`>7KrRDl?l7u=rrIqAUL;V2GbGY3EeifDoA zI%DOBUpgaa2JCF(dbBSPG$9ijta~9%cslA~FC#BPa`e>HoN(Ur0?nZ4SM&@wan5rt zHtt?sB%kZ$+jeSdg$O!~rcaM>iC+yk!d-lMu*6f zM}Fn%<8OHutSa~2Om0eC(F3nVUoT|DN<0~?gF!XBzMZWw`AZgD0GLKEqQ)ufkt7(YuoF&+!-5x32 zMbSawbKw0uiIf~#5d|PNNFn14T67ui#irwouR780SMR6isGY-Nx#U)(l@McO;eMo9 zz`mR~F5AZ$8mI(R9c6&n<&0g`f`O3VLpXV(|6w2#dbLSy$N#^Mn7odjad_JmJp{x6A9R zt1E-!Y};MEd^sTWjCI|Ob*LM>UDHgKv_KIqNYS&sAvMh}ty8D^)Yp@M>urSjv$M%# z+RBC3E?Qi~(!<(EQKDgeyUQK^Xg(3W4VgN){6amq9%CYsPYxoZ=E%#tKGsJx)0ofL z_I#Pkfcy9Fb395+qjkgYv?M(+xl#LD?E5bI`hG9BZEHX^5|jv=wVe-O@ketcv%CA> z{@DO@2?xi8m(7lA0#c^l_WHAT*kT#8x40IKAgtnr#}$m@$hcj`P|edJAr|%*j9x2k ziu2?s{&&cCYWCT6_a*=DXLaeRK#vx5Hun&%7M7N#G~OoRjl6b`U+*utX&*704jwd-D*Bf$PHd2fcu~!L!7#0 z1DNRE+-!Q%ldN&N1%vAj^hwe)P}Rkk4=KdBlh-1?yo3{}`2g24Yd!nh$F(-uT3hFY zb|0u;|Lo*ti{pd6M!6L4now<-^ZQ3_mFtX8^yV^9N#S=SbX8()JBczLh+Naye@0kANc_Z!*(zDSu616i%;dfd*!U*Yo5U&JgWo2eg;ZWtmVtl;TkAd`L z_qa%6NMT=|AFs+~^H2WOC^MIx^TAa9#l^}B{XfU|^!>;H$!X!&X!0ztSHuDoDF2at zBCoi%hyJw|MkX^LRTiMvEUO(a7y2n5c#Led_yv3hSx=WTCUO?faEKTaK$apuSN2R<=%|p>zgsxyl_n zM^m@#L{aVlBrd5by%{hAUY5EAe_JoU*8x92%{itP8el**U+=XfN;`aY1VM{|Enak< zljvqPMC19a=}nDq$&4MYLm8ex%Jw-L1flKOsGuG##g0Zh>Ys24m6x-4$tn9rB}CCq z!M%qW9Dsvfq@Np>meO&o`*7?r%m+OCIQBDIaMA1{v7Fm`>2;mNn(}5yB$O0XBSE8d zw4S~l-U77df9zeE3q**Ei;J*=Vm3kcwbNS9hbziu?OK@&CQ4s|xHhFMnJFPuwg8yP zl59+aJ3+7AM9yd&bK;nnc_S>EXAM?zsI!TdWcBaY&xbak^XNKK_x!cbnRSDU*U?Mi z7R8l5UOPfnck?4Ic7>l)Hnk@z-R_(oiFLnpz3RsfvQVGMm^xM6lb@I#o;9xC?#)_s zv7wK(oH%6}0pP=Fm{Cg&&xayg@lZx(?FvY{OBRcrKINmmq4Bw(Qhf&%k=XBTK3_G5 zREH(q!F|zV)TqvoeNF{!MaKXHk9{I!@8AYNf(y{NP5Iy4h~gk^5*Q}3nM9*6*&XD{ z%}3pFzPtJ(IQp=W$||E|9-|}WRX3F5AR^_{_TFka3?cU zd4rlgd#+|}sUnK(uHNWIH0k<(QA?mAlJ;;Q3fu_%+f?jd!!a}1%jv=SE z7{;#Y1>f)}R@=6^Fan(?<%QGsEO0!EEP$Q=Gjn`}E2yiJ*21V+WgXQ530imWMJi*hc zFxr*~lu4J;fpv8#Z{U17T8+h7C#C8M%lp-0wjy^DNhD1{c(soOhWdVQAoe%{uG-31 z7Bb~_4jjXqPoMM$t_Ho=S6EIRGeAI`=ptiMLDeltOK=l6qU@V;H5~(n70~ z-+$!6I?C|eY$eO;BO9q9A#KjEWYWe|U&R2qfcwOt>qPYQjsIu;GkYIp1+YpT8oRBc z#M48jGY(uh=?b%VTVMp2#6aM9js>#?RgpJAEFNF786=zs?`2_}2Q3SbnJ_ILm}b098|=QnQ08+pQ~ar`MvqFl z_ZL4n@|j9ccuRejHWK_A&2jlto;#rh^)Xlb9HT)pE_bSC?Zx&G&7p=tK{QK{XMkb!uWG|6+&;*wG zS+<_8?w(H@EuIxD!Y@AUiZY~2*RGE&HPybkre7{UrYpAxeJNTF?=9^@v}~4TFN>kr zc-o1y?d_C=SF(`TtD?1*w5GU|8LKu6G4Uy1L;y%7-tupMmZ$f3a!GYI(QDTeR-9oQ zjuHFEFWbp-AqylqIXS0#IQT5NOg~Ew*)MVpG~P1;DpufnMi$&VWbdJU^}K}zaTf%~ zv{1%|G;AZ9q1Om1|c$YH;4zxptJWX}!o(aV`4 z^5!j<&NH33Yu64x3af(~6^-B0L9AYJW}=Utc2#wx?8Y;e%5O?>%iLjcQimc^p zr^Dt&FMiZX_z-$>gM>>$lcDL+1Ub@vPvXbGN&_21ov8&!r$6lGStE1ipI1-BPsxDR zMlsgSQ6+=-)4+G9)0SyH@Uj0-duRU8bKZabPZ24Z82ge!smPK&R6-jisVI>wQDFvU zU$SJKHZ8;$6Gc0sj5V^Pl15}{!L&?MmQq62@8dbw_rCA{;Qr~lez{CipU?aATF&#F z^E^+N>Z@5zWgT`$ZHe?nIKuJFW@OuJ9BClj&_HHW-DQvSZ<4 zH9p;1zGR6^^T4GSU3MTUY9|jf?^XBIJ!xsi5=EqU(*9ytD+L7KR)OvtFE>m{6VL^I zlAP6yGsmE02rs=2#`0;}u;EhZ`C}4}NJ!}F5{9@-SE(q*jCPP0%q>8i)J_`V@Y3*( zVk7Ee*-b?W<|7lvs3{JI@+4eb7bMDG6P3FUqryhaSaNd&S?($7##B{x{fH}V-JP6n zTIR#Qgy!Vvq@N{SJ+9yDeYfUgF+Ui!wMTmvKQyxb>kqT9&JG>NZjxyE^aT*1?X2ELn?<33pKjn0c1mq9`JiqlKeT%CCYKd5UpH8lwi7Big7ib9h^KRvEVnu>(A z$gSopYx&i8nZ(Dsbvv2Z{2xN7A} zy5}Nndw*a{rv0N39pH^j6RnchwfQKQ}V{xr2_qy+r^nW&> z{BA|RlyY4DfgHkyug7(iq408*aTF~5^B~+8c603^Lrxc#XIGV>mf{k8mBEGdx#Twp zI(S@3?ECfCo~($rTuv#gZ6XS)j{}_U6cjApz5w3=DC@7Y1*S<4_SZ^ZMatENtzQ1n za+3tay8<`g=6T5|S;-=2ZLUEp?jTA~j zy>iAp9*AqNhge|pjKUYro2S6*%&S#a><*MwG_Gpc)6l>ocl7cN|I%#4Kqkd|;x zqPFa(gfRh*&uD?6LzsP=m6erv`Ly-et-Ld*;x?5qZ8FtYkrSMWT%-T>SLge1vCyHx zCL#Z<8>fZ(Tbt5a^pk1BQ3?N+bRKg*5ipg$zx2Z|ct zy%qdnNy=tq6L%U=*}ld{>}BRO^p|pIOB22j`E3rw!8{-TSA7z=k+`?rq1m{wr7`$E^yZ&68*f!Bv@TVlFs-r`J3z?5z0Vl&HwjB}|y&S^P zGcIabeCj{mc15e#^hhX1cZ$gPwQ-QwTI-_NuZv$M;;Y88JYu~)I9R5AEN3RTSQKr? z94)3{U9?@OO~Z$60SNtZE{kDLBI?FxKX?%C-y`8J&)jqVd}VVc3t`b!fJ1_W-lkq1 z_z_Ln%F(fdOa}bz)GzaF!^#V)uw6tJ`7EV>5zthX8edsmU4axNj&^Lf!r)UYZ)4A6 zqP2Am^uB*A@b0~3j^AOjEd=vhS!J6XSOv5fS=KcdU*vU8QHjon8Wd+n>vlckS2-?k z-sdpq{73GYwDJ>lj7D}IpgUqQxwZ&4kD4t~6B73PbhX*?-wXTjPgfIGz3D~6EA^!q zvc@5r4|o-f-w46vv^9PI=gRPD_4sIeCQLZy{uFJEBDCrxllMfWamS0 zDm`|dbn3m@#H14$dZFkyLdDm3Lowx2bhmoyo;33`s7)bi0Qj@^4CF-1cy;*b(GZG- zN1v|XwNa&@YoXxwleGCr(~&@W_|c_nJ_4BjWMC*Ha7W(6PO_@_5t?YUY@Fyhm4(4N zg5iLn4zp&dE?f56hhQ3N2P&69 zQ!o(EI?Tor8!IQEC6O{TB*V~bg_24$Zn4+FW%?4sZ|<4Gu&`cExO7>$)m(Zfb?`=N z-TOsf7+?$*Gn2GA(mc5b{cAgw;fUrOOnXr+JD=jhXVbVv^xH4!HR_rDnV};_q^x*d z#Qo@UFy|A42Nsz`L@-=-$osmBu{rwdH$`Ne3SX^ObN_g28c?Ol3CIt~;i(Y6EJXotTmNK|9%T@G6JD&MC?`_yvCKX~P)r(L93*@WJGg>aHF4Tb9QozzJSd zX`LFdKpVRZ@$yhWm4E+Temul93(wLS$^~J)36@KBhbHE&w%h(i~&;??iMeJ}PwB){-6@4+SiN-!oSS%fl4k;hjC4D1WH zkXHTdj}^yVrsPN)koS#;4o&LLK{!jf9|XCcjw{WzYy#gi>i8hx%-_B=PKzF{TsT_% zbl4vL)=t9^WZ&rVopZ{IGjOY$CIV%l#n zrFlW*{J*}Ik=BW$IrM31!|KydQ)Z8nNJBn(nJCK+Q9>tsKW7D6(&({c&t|OQ3C%b$ zbpo?buYPHmg7Ookax`*Nf1A2GBJH36j-S)8js2UWEK2}58u|;8mp_*88*J!)SE#2q zZ-SvDqyaE_P^4cDQ{vrE*cGBOGWK9M@=0`sA4$*8H#TbgKOfAL6Yk2|24<%h<#py` zx<(g^^yWjoKUF!KdNyE0S(&9zNI~@iY`q)@x7oT?8O6hljV(xy&@$Wni!9G6ZFC&X z{QUfIAN@i^CXrCIsuFkLYVtQ&bMO2f5lH23rRu}3LFTY^12?|@1_f2um=oo*8zHtKWs zik`F2toZro00QJnqc-B}xkhWP*nHr@JV}-5l50R#-zHP2>GX&vS{1!mj6RKTOS z=}ou{@Z^fS#fJHvDUBE))w*LEldtuq z_vv6_?#@@u@J8Zi80JNVcN-DG!PDR?fJ!b^_+*ag?euRst)05)v6VuaKJjjG?nY=sK7{lDTuW zcnt^Ee$mfnxt99Tg2f*Q z=T6Vs@42YUAFTGXNBkjI@dPI{ZP48@T#Fk@+yIIfqGK;znp_xlsMGXWvvvcSPxs6u zs}i68g{%tcgqmb!b@r(lG3>D28DYu_@#F!6o%FAM!L%xeR@EYWT|_UYX8CeIm9ric z0jwV9Cqo>cHjxfrpKc-KVImuvmv`SZ8&y}6r8xkue&ynY}4 zv7)hAdh-c@DZST&kjZV}(@QKvpXjH<6An2|(f2s-FLwNI4UcDeKkkeHD>~nG@459@ zVk7_tCZ8XR--dTB@>It!SNbn$6?%t$_(>KP+oswF`{hhr|2An4YSY<_2|smdA6a<+ z{#JUx=o8w`ot5*;&v@~mS>J+#$rQPbzu6|^ z5b`POcZcDFxoYa_;*Xa0E#nW&Pn9W=`0)}Onh*@%B9AJCww%G@H$MCn>oa{B`>3_? zrOro)GTs_R;1fSv3H%hFkdV{sU{XTDbs{v_j6``!bUtzK1s69_DABzdpR0HS4nUlr zOdsZ@y2b)C#zqfVc6CF6gTlIU|M|+lUc6Auo?YTry}47zj+~QQjRKu4`NRc&o;xQw zw6os&(&IzH_pmm-jZV;G96o@r7UqtF392bt!c}+W$}>%3&bikY}S_O9=IM8K)@mDD48`;@be-DN1$)-kBSS$1ECvr=4 z=APT~<*ij@oei^a*b@hG&XjsLLGD61ojL z;c{wKK=$ zg`W>ZFew1)Nrl;$`iU)7RC3B(HLTaSymawm+M*)fXl~1yl1oi9q{8~*UU4{BIJYu) zd~lyw8mx$t3ZS@#h(gc$tD!WETxSfGgNutW+StY3)fP>8vu->Q1)$V{A6trDiM=e7 z(pMgxc*rzYsb3_CYvUO}32q$xKrdlq{?*5Ft zcT)&Wqd0R_??bUEs&PGTNb4DV#^XF+LJ#(+Z0Tj<7qDyBuF@BSM~ylVd3%4WE#Mg| zz_K`YxHm*)LOD+MdcoI)1%Vu!wcL3J(Fo#*EyI0c$ueYBOWs;^X(nc?=oi!02aBzV z7evg~A`|1t0v*C^BBv&uhq-s@{^f}2rtWYi13${V55myE5h`2i#vD@Wr*;7w4#mHi z@mG8JPtj^1EfbsG1>HHZmrC8vE!paMW9MJIvq`Mxzy;Q0rwM(~%fxAU`3RlZnhQwE zvRS-RcuG=X#Pu@6ae;3|K_9qkONy1i()UYo)-c7~94vIHfFT&eyzb7sK3DoHC&C4Z z*K_rA3Rgj_YKx|g4xWhNTJk8(jStUsa_YC{!*VcIJxlTi{!enP31n5t3rkJ*YfEYo zQ5foa=mbGx%s6Oggx6ITC+y;C5701vun?A>Vf}-CcD?cy9Rj7P8V`Vk_I-FwS~Oyw zahEH#kUAsP;SdaGY;mw<^Uj?+*Lbo;p2wuT+}u#6xc+YyNR+fxfzG?yTUb{JGviV? zso3xhm!j>M)!bb?$|rYAS^l)D!juW<=Ob~gKZ);^))2{|UtZtZ+GL6NAi=>4KYS&s z9`jk4O$-!{0a&i@+3V$?EaU4Q&D~FOCvV3A!Ug2v8P$NTaQ?7xS`fZ&X^y@r`Pt8( zXIj*M;Pa8l3%!p$;95a&`X6WLjCi@y&gqa}&H`9BQRmQ&-#ojb&b0-+Y0aVJ5&VQqVPV?$2=mA(7tw^j~7>;&aw45AC6g?isUQ8bJB{uH{CaUF*dJ*keTnAnp`t0`3>a|3}K(wt}8Rs8n;$*gjZ*V zgoI3uS8v|Dv8zD8NwXd>^+Xs82eNsouoo&$d|I&JhLHocS%xp%okG z|0(5Omgwymu1P^l894IC_xPi8{mSEm;MvaS!cV8QuQKrxC~`ghPFI8vZ;dAJ=HxmduWw zfOqiJ*&{iO2?@)&z`q+IhI?8pw`CIdr9Eg+JC99GoybJm4YM>L(rBHu8kO92hf(?G z&lp9&b^3)`zg9UHeI~Bye`g{6tD%0xF|OB0`^+0&p$0CQg;xgEm0oDP*Q4M^i^NCt zSVVU)0Mw*w-JzJ7dE(kR0EF~in|H8gnzS|~y>lPt_1r{r_gt{x_|G{5_>k!9cr;)W zv3$mJEMh5eC5wcDPtx5uh3VsItzFZ#0~AznMdE7>_p1Tls0prDHxgFrBd&IZj5AFLG@D&q6cSw>42GvM*1H*t`DjFI`Oc%^%1!fm*%txb+43?d+gXtwt1uf*HEX> zPDsl{Gmmz$l4$L|f77;Nc=^}Qbo)O#`bSz-XRgkSsihF5-J3fUTBl$i!W`RDyPIDs zLA92L?*Tp}F9CC+vI579Dh0jb8g^ZX%7MdfjKu!^$E8boe)r-zov5T+U3wPrJZ$!F z#54msbY|50fR?0rno^Yrkam*cS0=_His>CpnO5Ye-Qh-Cm>Pmi{SmaGq~OWWqLj7f z`6gPpCK_qHg0Ri_>3J~v@0oEEk@caJ?!4-*m$*mS{8&dZYjc45TDP+v84QhQzC54H z)KMZGuyaCLXTfs}L1UM69!T#y`S~i^2}zL$56((jwVpHR(r6DdJ>J~)ptFD0kR@JT zE`$BEpWR;3Q{~7G{okp@xS*E4|4H5kj-dKKa!qGo^-E3)qyGY#TT~j+hACx_kO6{H zjQb`nx3T@cTM{%zinQa58CCZh=!lTOReYWRFEKgb28Dc-_OmnDP?j37!T->8DtM7o zMU-=bd%+OD#$A_f$H6^NF%UG0dLtJVrvXd59O_r`E$P4~yhD_m;x&IYVgo7)8#DT{ z`LT=oihj0zu~@Ea^kN!(WY9>)4lAL!M3>!g6o?H45e7j|^TH$lNp^M`JRw>lwgI)K z>`tZXnEL`^m_9W6>h_oJR~I`no=j{A_bF@RRJKcM7B!<#Lfp+5A}z=i$J}y|011qN zHeD847_RvKZIf7BbPJ@vQ&<5ZKG2@~py_TpK`c^BhQZL@(t>q<3xl50m&dhsR#vTf zfeV^fDTKxcs<>Rtg?ti=KV=Yo_WL#L^9Fbv@*#_5>7EPY*lsVbDIpo9eK^KItC4@| z(w30F0zPghky#A-5L*Uz^51{|UC}dp0@*!OVlpe_#MJ0*LRe`3#0ep+U_Fxmzb%LQ zm5t2+2pJx_z3oby2j)uJ(=YN+_*C4z{Mpgw|5pRNO;4h{Z zH&<0v$~E_{noh$gYFJ+qxZMR#CCHcU9J0cudkQ6FeB()sb49gAKFsrqK% zGR}!sEWH)A4-GCfS)+z9Md#i&Q&3mnvpf`=_H5wr2czK+`E2NI*2Ie~m>(g18_tq5 zzA@t{cPHW6^`!2BW)kX<`Z-&obry(lhb~V+V-?fbH*q_s?O<8acmrqT#-W$iH#OZt z6AIy|F!bwLbE^O$i;Fb<%|!QTvE*^NTcCB~F00I#L#=e3AuZ(14CO;q>ouiPfST#o zcQd$}b2WxM*V9y`rE?cPrW;vV$6V?HLqBxNmUBgNG9298692Ruq!rRy6w@(dVn_lP zIpwn%1+A19^zgo7$i>$##6|O2IA@$Zclxx%KezfpYv7Etr}QvV;+EaPM-g2Hzc!Xc zQW*`x6G^%MR?=W$cO)EhXyL!!X$(}-^-ifxLgc*vPMRrFUgOlX4;XFu{tnYdiLmSSj&}m zbN-pEQ-gWSG(q!u4oLs3q+?eGAB@H@4^)4`@^L%fEmW7}!*mKiPgERk5M~~SptK>? z2;;|RnDTCz*^)oCRRgnZ%^K5nJM6)_$;OZiOfO(YM|2DB+xq)fy_ujj0Tjrp`S|?% zH>>8`v5s`#uV2H)r38IJU&=LL{YyVCuGOCO-r1U*&5b;&F?!Rd;d#>rPUD}-an1ux zPEMAgT==z-$$DXjSIhr$#SRu7Xu#!~YB4Nm$K^U6cRd~7<#aEN=bFB6ot8x!~Pr4)uh)+DD$=;Vxk0fP>E~6s>BRfgX#tnNQ=MQ0ID)O-(fkv1neFJL zi-^UN41-p$!fig#HEoi&jE3LN^a(|1{O~aAmW)}berlG0A9ev)FKGD!nW*=&C$_E$ z-aMF2hx@C=C_*1zq7y;Cs$5TZS@gq$R3uA$d@Nuo4C)xKaK~u$l--5|lMn>yV5_)O z@m5M^WYjrr7N2m(DehQ&2DuagC*EP~*ki@qb4~V7U0Vf>@SPA{?d<$^riD{rnpq1K z6%|G?TyP9YXq&h)s9%t}N-%mC`DMZ2$Kql)gLMHsppTi~Kbz?uiC)ufSlIAgA%oz>widB^+@fg6`OT0NaZ8oEag$bkZy$L1^XqAo zbYTJXm;Jc=(xpos?pZhE#MJJn_R`(f!mZV9nlWq^TUtL@h^ZS0#e-rC(cboqyIiw{U2mtLjHt_fH@DJKw7rU{vjD z4xdWGv+j|w2Afm9{u+KIIHMumY*96zt&v3*lbRY#?8D=lu8^Ws|1%4_6@?IXA^oH2 zzo~Sj2_3A9?i#VtYsYXq8cg`_hGS>O88=*U&cWFyr{$LC3nP zDQvcbqPJo?OR>6u<0Z&+2-8=EoQ+9Jnq4t?AT%VDNKd?vFrZC-J9i8>;t!H!fw$GC zDO#=y##44bmp*%$#B2br)7KATm*eh%EKI39+ox`r{2H8yPlyTR9PYR|czEQU^) z8rZ`fyLK%A9Fh8}qPU=R>YXWNDZg?arx-4=C4a8cwd>uatXDS`QCFsK!CDFqk!kT% zAp#%C7ZLrwZnDjG-nFDXVVT7BtOwGFNlDS5ERg14k#QSab+d5dsGfEj52KVWc%EMk zD?+Hnoiv{|!JxEf9(IgDrQUy`yVP65-$$5&?y4n4efa5(uO`ztK`N9`>lrgSo$k+^bGKaE|=<`$|tJ2X2@T$Q~;lRp~n{J&pO(&jHLcJJlf zkiVI93pP@|_ZXdO{p6dc5ACSvApbm`Mb<{X*{Q8cz<+OFaAx From fbe25df9ea7f55c2afd2232ddaaaaaa92077281e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 14:49:11 +0100 Subject: [PATCH 0870/1892] chore: bumped version to 0.9.9 --- CHANGELOG.md | 6 ++++-- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a599e1f21..51401e81e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.9.9] ### Changed @@ -234,7 +234,9 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[unreleased]: https://github.com/igraph/python-igraph/compare/0.9.7..master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.9..master +[0.9.9]: https://github.com/igraph/python-igraph/compare/0.9.8...0.9.9 +[0.9.8]: https://github.com/igraph/python-igraph/compare/0.9.7...0.9.8 [0.9.7]: https://github.com/igraph/python-igraph/compare/0.9.6...0.9.7 [0.9.6]: https://github.com/igraph/python-igraph/compare/0.9.5...0.9.6 [0.9.5]: https://github.com/igraph/python-igraph/compare/0.9.4...0.9.5 diff --git a/doc/source/conf.py b/doc/source/conf.py index 4aa58a76e..9d9b333a2 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.8' +version = '0.9.9' # The full version, including alpha/beta/rc tags. -release = '0.9.8' +release = '0.9.9' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index 543a50026..fbe3a4a5e 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 8) +__version_info__ = (0, 9, 9) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 70e076dbe3704a4d6692f318e4968c31e8a328c0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 15:33:38 +0100 Subject: [PATCH 0871/1892] fix: fix Github Actions spec to ensure aarch64 builds are triggered for tag pushes --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de9259cf0..4073c03e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,10 @@ jobs: build_wheel_linux_aarch64: name: Build wheels on Linux (aarch64) - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + on: + push: + tags: + - * runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 From 157336344ee33cba5e424a5ef61e665372a31bb2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 15:35:00 +0100 Subject: [PATCH 0872/1892] fix: fix Github Actions spec to ensure aarch64 builds are triggered for tag pushes (YAML syntax) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4073c03e1..1b1a2f470 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,7 @@ jobs: on: push: tags: - - * + - '*' runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 From 58d3c922e0d7cf56b78c4d74ea473d8227c2fe43 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 15:38:01 +0100 Subject: [PATCH 0873/1892] fix: another attempt at fixing aarch64 wheel build trigger --- .github/workflows/build.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1b1a2f470..8ae4a6fb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,11 +45,8 @@ jobs: build_wheel_linux_aarch64: name: Build wheels on Linux (aarch64) - on: - push: - tags: - - '*' runs-on: ubuntu-20.04 + if: startsWith(github.ref, 'refs/tags/') steps: - uses: actions/checkout@v2 with: From 581fb65ab635e8fc1fe86dfd9e2aeb9f59b32925 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 15:42:49 +0100 Subject: [PATCH 0874/1892] fix: another attempt at fixing aarch64 wheel build trigger (2) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ae4a6fb2..9388bac43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: build_wheel_linux_aarch64: name: Build wheels on Linux (aarch64) runs-on: ubuntu-20.04 - if: startsWith(github.ref, 'refs/tags/') + if: github.event_name == 'create' && startsWith(github.ref, 'refs/tags/') steps: - uses: actions/checkout@v2 with: From 3b45e58f9e866faea6c29857f7c8f676154d8708 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jan 2022 17:08:59 +0100 Subject: [PATCH 0875/1892] fix: looks like the original build trigger worked, I was just looking at the wrong place [ci skip] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9388bac43..4026bf0e7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: build_wheel_linux_aarch64: name: Build wheels on Linux (aarch64) runs-on: ubuntu-20.04 - if: github.event_name == 'create' && startsWith(github.ref, 'refs/tags/') + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') steps: - uses: actions/checkout@v2 with: From 15473f5e8a1b984f3f09166fd521f6967320a11c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 11 Jan 2022 11:12:26 +1100 Subject: [PATCH 0876/1892] Make pydoctor CSS compatible with outer igraph --- .gitignore | 2 ++ doc/jekyll_tools/_layouts/default.html | 8 ++++---- doc/jekyll_tools/css/other.css | 4 +--- doc/source/sphinxext/postprocess_api.py | 27 ++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 2e57cd068..8bf34132f 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ vendor/install/ doc/source/gallery.rst doc/api/ doc/html/ +doc/jekyll_tools/Gemfile.lock +doc/jekyll_tools/vendor diff --git a/doc/jekyll_tools/_layouts/default.html b/doc/jekyll_tools/_layouts/default.html index c554844ba..a88d03a06 100644 --- a/doc/jekyll_tools/_layouts/default.html +++ b/doc/jekyll_tools/_layouts/default.html @@ -121,9 +121,7 @@

    {{ page.mainheader | default: layout.mainheader }}

    {{content}} -

    7O%LXH%dU3`;r)z?YFvI5Ta3SfmxF0M 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 literal 30970 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 Nyt0N;mZFKz{{aL%cJTlJ From aee3be0d17c74b92fbb785167af377e51f68ea8e Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:19:04 +1100 Subject: [PATCH 0856/1892] Update script assets --- .../betweenness/assets/betweenness.py | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py index 7f9b7e6d4..d7b59350f 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -1,39 +1,56 @@ import igraph as ig import matplotlib.pyplot as plt -import math +from matplotlib.cm import ScalarMappable +from matplotlib.colors import LinearSegmentedColormap, Normalize import random def plot_betweenness(g, ax): + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = ig.rescale(g.betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/3)) - edge_betweenness = ig.rescale(g.edge_betweenness(), clamp=True, - scale=lambda x : math.pow(x, 1/2)) + vertex_betweenness = g.betweenness() + edge_betweenness = g.edge_betweenness() + scaled_vertex_betweenness = ig.rescale(vertex_betweenness, clamp=True) + scaled_edge_betweenness = ig.rescale(edge_betweenness, clamp=True) + print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") + print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") + + # Define color bars + cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) + cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) + + norm1 = Normalize() + norm1.autoscale(vertex_betweenness) + norm2 = Normalize() + norm2.autoscale(edge_betweenness) + + plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), ax=ax) + plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), ax=ax) + + # Plot graph + g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] + g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) + g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] + g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) ig.plot( g, target=ax, layout="fruchterman_reingold", - palette=ig.GradientPalette("white", "midnightblue"), - vertex_color=list(map(int, - ig.rescale(vertex_betweenness, (0, 255), clamp=True))), - edge_color=list(map(int, - ig.rescale(edge_betweenness, (0, 255), clamp=True))), - vertex_size=ig.rescale(vertex_betweenness, (0.1, 0.6)), - edge_width=ig.rescale(edge_betweenness, (0.5, 1.0)), vertex_frame_width=0.2, ) -# Generate Krackhardt Kite Graphs and Barabasi graphs -random.seed(1) +# Generate Krackhardt Kite Graphs and Watts Strogatz graphs +random.seed(0) g1 = ig.Graph.Famous("Krackhardt_Kite") -g2 = ig.Graph.Barabasi(n=200, m=2) +g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) # Plot the graph -fig, axs = plt.subplots(1, 2, figsize=(6, 3)) +fig, axs = plt.subplots(1, 2, figsize=(10, 5)) plot_betweenness(g1, axs[0]) plot_betweenness(g2, axs[1]) # Add "a" and "b" labels for panels fig.text(0.05, 0.9, 'a', va='top') fig.text(0.55, 0.9, 'b', va='top') + +plt.show() From 767cf4c6af04d7df8517a1f2a4c468fc752a8365 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:20:59 +1100 Subject: [PATCH 0857/1892] Fix typo in topological sort --- doc/source/tutorials/topological_sort/topological_sort.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index e397d1d75..d3d1b052b 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -31,7 +31,7 @@ This example demonstrates how to get a topological sorting on a directed acyclic results = g.topological_sorting(mode='in') print('Topological sort of g (in):', *results) -There are two modes o |topological_sorting|_. ``'out'`` is the default mode which starts from a node with indegree equal to 0. Vice versa, the mode ``'in'`` starts from a node with outdegree equal to 0. +There are two modes of |topological_sorting|_. ``'out'`` is the default mode which starts from a node with indegree equal to 0. Vice versa, the mode ``'in'`` starts from a node with outdegree equal to 0. The output of the code above is: From 7a6dfd5fd496fefeb2d76059605c5dddcaafad42 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:24:24 +1100 Subject: [PATCH 0858/1892] Update assets script to match rst file --- .../visual_style/assets/visual_style.py | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/doc/source/tutorials/visual_style/assets/visual_style.py b/doc/source/tutorials/visual_style/assets/visual_style.py index 7388db94e..fbdbc5c45 100644 --- a/doc/source/tutorials/visual_style/assets/visual_style.py +++ b/doc/source/tutorials/visual_style/assets/visual_style.py @@ -1,30 +1,26 @@ import igraph as ig import matplotlib.pyplot as plt -import math import random -# Configure visual style +# Configure visual style for use in both graphs visual_style = { "edge_width": 0.3, - "vertex_size": 1, + "vertex_size": 1.5, "palette": "heat", "layout": "fruchterman_reingold" } -# Generate graphs +# Generate four random graphs random.seed(1) -g1 = ig.Graph.Barabasi(n=100, m=1) -g2 = ig.Graph.Barabasi(n=100, m=1) +gs = [ig.Graph.Barabasi(n=30, m=1) for i in range(4)] # Calculate colors between 0-255 for all nodes -betweenness1 = g1.betweenness() -betweenness2 = g2.betweenness() -colors1 = [int(i * 255 / max(betweenness1)) for i in betweenness1] -colors2 = [int(i * 255 / max(betweenness2)) for i in betweenness2] +betweenness = [g.betweenness() for g in gs] +colors = [[int(i * 255 / max(btw)) for i in btw] for btw in betweenness] -# Plot the graphs -fig, axs = plt.subplots(1, 2) -ig.plot(g1, target=axs[0], vertex_color=colors1, **visual_style) -ig.plot(g2, target=axs[1], vertex_color=colors2, **visual_style) +# Plot the graphs, using the same predefined visual style for both +fig, axs = plt.subplots(2, 2) +axs = axs.ravel() +for g, color, ax in zip(gs, colors, axs): + ig.plot(g, target=ax, vertex_color=color, **visual_style) plt.show() - From 70e69ec033d72982726e74ec7a83ff3f61bd1b23 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:24:32 +1100 Subject: [PATCH 0859/1892] Update figure caption to match figure --- doc/source/tutorials/visual_style/visual_style.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/visual_style/visual_style.rst b/doc/source/tutorials/visual_style/visual_style.rst index f83afa362..dc9b8ffc4 100644 --- a/doc/source/tutorials/visual_style/visual_style.rst +++ b/doc/source/tutorials/visual_style/visual_style.rst @@ -44,7 +44,7 @@ The plots looks like this: :alt: Four graphs plotted using the same palette and layout algorithm :align: center - Two graphs using the same palette and layout algorithm. + Four graphs using the same palette and layout algorithm. .. note:: If you would like to set global defaults, for example, always using the Matplotlib plotting backend, or using a particular color palette by default, you can use |igraph|'s `configuration instance `_. A quick example on how to use it can be found here: :ref:`tutorials-configuration` From a72b6174f8e021ce913bfb64650eb127340158b2 Mon Sep 17 00:00:00 2001 From: Gomango999 Date: Sun, 9 Jan 2022 19:27:04 +1100 Subject: [PATCH 0860/1892] Update comment in visual style tutorial --- doc/source/tutorials/visual_style/assets/visual_style.py | 2 +- doc/source/tutorials/visual_style/visual_style.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorials/visual_style/assets/visual_style.py b/doc/source/tutorials/visual_style/assets/visual_style.py index fbdbc5c45..8ae1b5452 100644 --- a/doc/source/tutorials/visual_style/assets/visual_style.py +++ b/doc/source/tutorials/visual_style/assets/visual_style.py @@ -2,7 +2,7 @@ import matplotlib.pyplot as plt import random -# Configure visual style for use in both graphs +# Configure visual style visual_style = { "edge_width": 0.3, "vertex_size": 1.5, diff --git a/doc/source/tutorials/visual_style/visual_style.rst b/doc/source/tutorials/visual_style/visual_style.rst index dc9b8ffc4..ec554aad3 100644 --- a/doc/source/tutorials/visual_style/visual_style.rst +++ b/doc/source/tutorials/visual_style/visual_style.rst @@ -15,7 +15,7 @@ This example shows how to use dictionary unpacking in order to easily use the sa import math import random - # Configure visual style for use in both graphs + # Configure visual style visual_style = { "edge_width": 0.3, "vertex_size": 1.5, From fa065d0885594cdc5e40902b897060caa1efa1e7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 06:37:30 +1100 Subject: [PATCH 0861/1892] Add titles to complement tutorial figures --- .../tutorials/complement/assets/complement.py | 7 ++++--- .../tutorials/complement/complement.rst | 2 ++ .../complement/figures/complement.png | Bin 59999 -> 60007 bytes 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorials/complement/assets/complement.py b/doc/source/tutorials/complement/assets/complement.py index bec1e5d16..22ffcee3e 100644 --- a/doc/source/tutorials/complement/assets/complement.py +++ b/doc/source/tutorials/complement/assets/complement.py @@ -15,13 +15,14 @@ g1, target=axs[0], layout="circle", - vertex_color="lightblue", + vertex_color="black", ) +axs[0].set_title('Original graph') ig.plot( g2, target=axs[1], layout="circle", - vertex_color="lightblue", + vertex_color="black", ) +axs[1].set_title('Complement graph') plt.show() - diff --git a/doc/source/tutorials/complement/complement.rst b/doc/source/tutorials/complement/complement.rst index 8e337be47..1ecbaea7d 100644 --- a/doc/source/tutorials/complement/complement.rst +++ b/doc/source/tutorials/complement/complement.rst @@ -36,12 +36,14 @@ We can then generate the complement, and plot out the graph. layout="circle", vertex_color="lightblue", ) + axs[0].set_title('Original graph') ig.plot( g2, target=axs[1], layout="circle", vertex_color="lightblue", ) + axs[1].set_title('Complement graph') plt.show() The two graphs compared side by side look like this: diff --git a/doc/source/tutorials/complement/figures/complement.png b/doc/source/tutorials/complement/figures/complement.png index 0f7bf86c53a7fe88159c211326e1bdc36353f3e8..3ead9296e101d412de61a8347d58705afc05738f 100644 GIT binary patch literal 60007 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 literal 59999 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�S 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 F{68ROOBetE From ee525c8c0b09aac6d731cac2be5508f719ced726 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jan 2022 06:49:11 +1100 Subject: [PATCH 0862/1892] A little more figure variety --- .../tutorials/simplify/assets/simplify.py | 16 ++++++++++++++-- .../tutorials/simplify/figures/simplify.png | Bin 31685 -> 39750 bytes doc/source/tutorials/simplify/simplify.rst | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/doc/source/tutorials/simplify/assets/simplify.py b/doc/source/tutorials/simplify/assets/simplify.py index ab75337d1..194b74995 100644 --- a/doc/source/tutorials/simplify/assets/simplify.py +++ b/doc/source/tutorials/simplify/assets/simplify.py @@ -9,14 +9,16 @@ g2 = g1.copy() g2.simplify() -# Plot graphs +# Choose a consistent visual style visual_style = { "vertex_color": "lightblue", "vertex_size": 0.4, "vertex_label": [0, 1, 2, 3, 4], } -fig, axs = plt.subplots(1, 2) +# Make twin axes +fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) +# Plot graphs ig.plot( g1, layout="circle", @@ -29,4 +31,14 @@ target=axs[1], **visual_style, ) +# Draw rectangles around axes +axs[0].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[0].transAxes, + )) +axs[1].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[1].transAxes, + )) +# Set titles +axs[0].set_title('Multigraph...') +axs[1].set_title('...simplified') plt.show() diff --git a/doc/source/tutorials/simplify/figures/simplify.png b/doc/source/tutorials/simplify/figures/simplify.png index 03e0619a4104ce7325d4c58665a86cccbe714764..381e8debce3b957da82c5a6a8a790e3a05a327cf 100644 GIT binary patch literal 39750 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%0D9jFvcbrd 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

  • - - + +
    diff --git a/doc/jekyll_tools/css/other.css b/doc/jekyll_tools/css/other.css index e0f7bf402..a764417be 100644 --- a/doc/jekyll_tools/css/other.css +++ b/doc/jekyll_tools/css/other.css @@ -31,10 +31,8 @@ span.type { padding: 57px 0 0 0; } -#footer { +.footer { padding-top: 5px; -} -#footer p.credit { text-align: center; } diff --git a/doc/source/sphinxext/postprocess_api.py b/doc/source/sphinxext/postprocess_api.py index 21ad9677c..52ca4392f 100644 --- a/doc/source/sphinxext/postprocess_api.py +++ b/doc/source/sphinxext/postprocess_api.py @@ -26,6 +26,15 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: mark_end = lines.index('---\n', 1) + 1 lines_mark = lines[: mark_end] + # Relative links to stylesheets break, repair them + for i, line in enumerate(lines_mark): + pattern = 'href="_static/' + j = line.find(pattern) + if j == -1: + continue + line = line[:j] + 'href="../_static/' + line[j + len(pattern):] + lines_mark[i] = line + # Write individual example files for filename in sorted(glob.glob(op.join(api_dir, "*.html"))): # Open file @@ -44,7 +53,23 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: end = head.find('') + len('') head = head[:start] + head[end:] - # FIXME: fix CSS includes to match navbar appearance + # Bootstrap from Jekyll and pydoctor conflict, remove the pydoctor one + headlines = head.split('\n') + for i, line in enumerate(headlines): + + if 'bootstrap.min.css' in line: + break + head = '\n'.join(headlines[:i] + headlines[i+1:]) + + # Repair footer that conflicts with igraph footer + # NOTE: this is not the prettiest thing, but it works okay + bodylines = body.split('\n') + for i, line in enumerate(bodylines): + if ' Date: Tue, 11 Jan 2022 18:33:53 +1100 Subject: [PATCH 0877/1892] Add labels and improved sizing --- .../betweenness/assets/betweenness.py | 23 +++++++++---- .../tutorials/betweenness/betweenness.rst | 31 +++++++++++------- .../betweenness/figures/betweenness.png | Bin 241654 -> 240448 bytes 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py index d7b59350f..2a941acc4 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -4,7 +4,7 @@ from matplotlib.colors import LinearSegmentedColormap, Normalize import random -def plot_betweenness(g, ax): +def plot_betweenness(g, fig, ax): # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 vertex_betweenness = g.betweenness() @@ -18,13 +18,23 @@ def plot_betweenness(g, ax): cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) + # Create normalising objects to scale the color bars correctly norm1 = Normalize() norm1.autoscale(vertex_betweenness) norm2 = Normalize() norm2.autoscale(edge_betweenness) - plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), ax=ax) - plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), ax=ax) + # Create new axes for color bars + cax1 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.05, ax.get_position().width, 0.03], in_layout=True) + cax2 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.20, ax.get_position().width, 0.03], in_layout=True) + + plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), cax=cax1, orientation="horizontal") + plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), cax=cax2, orientation="horizontal") + + # Add labels for color bars + mid = (ax.get_position().x0 + ax.get_position().x1) / 2 + fig.text(mid, 0.3, 'Vertex Betweenness', ha='center') + fig.text(mid, 0.15, 'Edge Betweenness', ha='center') # Plot graph g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] @@ -45,9 +55,10 @@ def plot_betweenness(g, ax): g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) # Plot the graph -fig, axs = plt.subplots(1, 2, figsize=(10, 5)) -plot_betweenness(g1, axs[0]) -plot_betweenness(g2, axs[1]) +fig, axs = plt.subplots(1, 2, figsize=(10, 8)) +plt.subplots_adjust(bottom=0.3) +plot_betweenness(g1, fig, axs[0]) +plot_betweenness(g2, fig, axs[1]) # Add "a" and "b" labels for panels fig.text(0.05, 0.9, 'a', va='top') diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index cf53cbaa9..f1dd65ec0 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -28,8 +28,8 @@ Next we define a function for drawing a graph on an Matplotlib axis. We set the .. code-block:: python - def plot_betweenness(g, ax): - + def plot_betweenness(g, fig, ax): + # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 vertex_betweenness = g.betweenness() edge_betweenness = g.edge_betweenness() @@ -39,16 +39,26 @@ Next we define a function for drawing a graph on an Matplotlib axis. We set the print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") # Define color bars - cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["mediumpurple", "indigo"]) + cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) + # Create normalising objects to scale the color bars correctly norm1 = Normalize() norm1.autoscale(vertex_betweenness) norm2 = Normalize() norm2.autoscale(edge_betweenness) - plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), ax=ax) - plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), ax=ax) + # Create new axes for color bars + cax1 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.05, ax.get_position().width, 0.03], in_layout=True) + cax2 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.20, ax.get_position().width, 0.03], in_layout=True) + + plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), cax=cax1, orientation="horizontal") + plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), cax=cax2, orientation="horizontal") + + # Add labels for color bars + mid = (ax.get_position().x0 + ax.get_position().x1) / 2 + fig.text(mid, 0.3, 'Vertex Betweenness', ha='center') + fig.text(mid, 0.15, 'Edge Betweenness', ha='center') # Plot graph g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] @@ -74,18 +84,17 @@ Finally, we call our function with the two graphs: g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) # Plot the graph - fig, axs = plt.subplots(1, 2, figsize=(10, 5)) - plot_betweenness(g1, axs[0]) - plot_betweenness(g2, axs[1]) + fig, axs = plt.subplots(1, 2, figsize=(10, 8)) + plt.subplots_adjust(bottom=0.3) + plot_betweenness(g1, fig, axs[0]) + plot_betweenness(g2, fig, axs[1]) # Add "a" and "b" labels for panels fig.text(0.05, 0.9, 'a', va='top') fig.text(0.55, 0.9, 'b', va='top') - + plt.show() - - The final output graphs are as follows: .. figure:: ./figures/betweenness.png diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png index 6151da29d63ab78b3cbeefa776d6aac2785927bb..612c2843d3d9203347f2248b2807d524ab181cc5 100644 GIT binary patch literal 240448 zcmeFZ1y@`_*EQIjpE)F*KE;gS`$lc7GoIlyyak6l;urrZcy0|zv^Ru$r{?7|o z?42xFmyLgS18;)h@a}^%2!w|T{s&=^Kc@ zlio$Hw3sooesCjRs#xW7%s#u_cPqOqJ$jeja`etmf&WY)d!0)**_>|bBBq8}*PHcB z2tqMnx$kYSi0EvRlq@woCg{Pl*T74bGQhd#GyV2v@WGQ{5Vb63#Q$7L2|u3dRBstfia6X5RmvkH4rl{dJj0tOH+8lp64M7#J#up4|q2&dy(0qN1V-W-XPqw8E!- z&z#Yv*w@}uQBoE$QN2r|X1*nFZ*PZ(4c6{-V@51&dY|BKubl7XwJFn|tYoBU-(W8h-{@{|uNYNl1dPXa`Os z=zy>=SYkd05NbFSXl8acFr3T}KR7tpUtg-R#sQH?w%;3D5+%!fS33iuXVV#`8+r=DE=FiY{!Rw%f=sUJUnirr)p|y_1a7` zR?QiCd13M+nF+wCUHqelNkx;WeNIft1`mYq-u`5+x_$#qL4+>!Q*+N?G^?$W(b#-%NxxM&1fhi{4-QCW9KaX!roSZOq zYH)F*%{=j>fS-M^p2dm5!omUt3=9ki*gZ|T_cSgKVu9aOB?{O(TYZ60?mmBXHy&|8 zMo+h=2@`u0-Aq70jjKkZ;#XBwL4XYZY~$IlBKn>zv-|9G=6^WZ`a9W{2;dvqmb2E;Dg2Khqb9r5zjD!RfEG(?UpL@qYTVyX3 z!cRY@i#~sbURzsxqr(9n4+hQ7KK7CAY6}HsWIq2SQrp)a=3{P7K+ zR+i?v)xo2qd{bd0=zYtS=lA$2CN6G!ROE%dw5;s%{PpF$`d>;I7qx08ghL}8LSpR- zNTyTTj^$k!RZ+nJfATh?;e%X9x(s-R%z+vDJB#2iO9Y%KP(;K& zD{1`B#OobW1}XkP+BV{$x|JTu;jl7SME=7to{EY_>KP5@-;_4X050yTmCYqMBF|qZ z&`llb7p(+u0xeY3)l<&QYVeb&x6WU#r!Ti3ZRuV1embrm7`{N{JvPS|RF={zF#h}O zqQx)>DvXk$#fkLGojQM_RA~WH!(JG~cE~MDXpy&fsIUXVT^HHCVRK*RTv$1eyMGUo z6@KIhX*R=gUT2ZTeA&7o+xCB5+hDpH2iM7n2+QW}1UyQerp7YGt&64J_>CVA*thmR zAVkli?kb&%0l1da0sHgiczeH>*P`wk=1Im$ze$VfHEumY$~b7yUnTwZ7=k##2vYA36Tqnoe(9zy5)#x8zqb!^e^e*`W-YGqvOo@iRp4R)cU+fSqCAk~v=H`h57@>!({~<#_b-!R%iC->@V2 zq_QG#kKi_5P=)I+`=8d8(4kK%biz%;<2Sd~I@5gg@2F%kx06EJpogRow!dvi$%^X@ zb^51$&Rn$+rd{{>`E6A4Na$|ZJ1&)Pv}Uw}0An0llm$KkL44c&!}fV2Su#T7o$OB* z(Ht33qS)aA<=>+Me-{#i8LbDBrbz0jb2hAuY=yV($*#J5xR=b&n#U-`4q@*M_i&By z*QDP`i>O0w!g-pg1J7>f^QCi`4+n%3L}Q>KDV;=Tcv@r7z`{vbCeT=Kpu=(-@OaIh#iTv zo{r@h@0DYwgYII!9O{_4c#kercROUidZ^FQ^=6Oneg9VL<$hpy~7KSOSf<$q9_~fZ2Rt-?Wnk;`IE-NkL?qVl?F?wRNZp2nT- zHnhRRFpB^Cb^2I*HcXYdm7fNGnmplqZ!hC_HrD+}NF;on*Ux=q7=_(WKz?`euS*@X0@J~twNhDl6nw&ENsp&Q{G_8&V z`|lJ$<_O<-7G9Y$4C7}Bo;T`KpFzvllbr34jmQkz( z^-_`cd@Hev9WfB!mO1>}e=3g-h9nr1s}Zar>2)Z5vSUR4F@H zWs_zEIYL`?!s=P3gTlvi-A|tmP)3bZ*FF$4CnI<`sl6HTrO2@%)%itZfg_vbVCw)G z4!pSeTjXR(oIqInPlXsE{Qs=oWE+qg&fc&@@%<2r3j7MX)jXhF`rLi++`UE5lqJAO z1kv{y*z7379uM+(QMuCCZ)4v#>{e4oVJf#su=&-%F0M zhk>T3^LMzZ$MXm}ZLrFTp_<2r1I9a>M4rh8*T>Rdkc{8cmM>S@?Vza|)LD3sLrfjJ zJWbJq)gT0$Yc2b?C=)U$nbRBKsQ%r02^#R$S@ZS05n8o3gGCzKksV#$iX1(%N!0h0 z>=|dy8*9gih3aD$^GHJ4HNhvoh4cpPb7(3_7YiMf8O@cS=>(VXF>F`=rp1!)bCpVeCRrzzUvgav^Yu= z>AhWK-7?K~6RVruw(q^jzn|}Y##X=ctPz*|Y7C^IMiWO2x(*rk6O`@5EWurTZX~ZR zUgBVtnj9_iOw(E8(JUY0o|SmWPKaAin_dHil{JH|`J<6AN`deDy89&SQ#34c3Dgcz zT;TaN3+1$6-7buB1qH0#DBNdLg_Eb$1k0n7V8o(P58oy z1<1j|2c6uSe*4p2+Cm6drzaUXAKK6c`Fh^RozgB}{-(ZY$T%ctX;$*hAW+CbpdJV8 z@Kx!81cc?@Qc%ZRTCt5+d}pPEp6pUYypA>DE~geG){|=e*;Egpvioe{*P*&GC02FbT_CS9Qr zKS>k!x%GsW0sr9DR0ZrGqs>?BL{}F++}Jp^ z@Q$AaM9;Sy3LY9q0=4WRe%?R>Q7|arS=V}t#G7=3=x8M0?^k?ces<%>gScU-99yFP z#wW7Dv|oB4(Ta%>)pUeeZDM^pRvlQ{i{g2bnab4ism21@4ajiWiTXr(1Z4b3O?Ge$ zdmyI6($<$O$1$XTQW?DpEp|A%LGp?*C?48Tpz%18gp<>!O*zQIYYvmg`j-Qfpn*{G zFc@^&XQch|uQ}tGzjuL`sY5X`8i+6DpySbKb10cdX;%$iDP5mwT>*1{cBWb+alaM z1TXHzJ*s)orm)o)J*n6;7RF&jYMDl3fJI*C+X%+HTj($NaL>*$+a?mzYKJ^vr@XUO z`7`BCZWs3xIB$$|C2A8}tjIVtOaxPgW00+=KuyRiyVsiG!zf}wPyTsqp<@Ix)jUrS z%AR8RIp=~@m8y|`B-F7S@dYfEB~gy##3r<2GYZvck%U4IjD{!fVUkC#L{k=<5w%We zS0O!WD~d!(g6ZoDq-ARKs|tE#H2kO}e$wF@JP2*^pxA#Qd}-QsryY)=(N9+#$i?Bh z;mYY2{Uat%Nj}02ZO{P#qyVmxd}>)sqO74yqTqyykIPHyQ5@-?Zuvbv{)~r+M?>Sn z?cYITJ<_qej-?`wHI{f7sH9fV!Qs(tt8W+xRk25}k%+7uF--wDL=A=`> znhb=Xnq`<5A?UkALWAg;hqqSH1 zQGY@qiCT{=Yp8vl-G2F}S0-q*Ri)QqZBLV(!T;IJ5!LQa8 zUOE@iJQ=s=ozK_r;6x78`9y za;iZ(KFF{uqTl+MPPAq^@6p6U=4rl`l*fvTM*&JO^K7R3JI*o(t~fQ@!M2~Az*HiT zd9}fsujTq86*us)w01U>2$Lmdz&BeRF@Un+Mz+vKXVeq3NaKUZ$u~-6dKBVGZeR|H zZVJsDAVs=|WEUh`fzWP3l-#CVKXWntN!GvP`cTg**0>$22xOdQ8aJ2DZjT!qUg54P z9_tn|p!5*i5sbL-MLi!!8GWxz`;)`25+u&D6N(HT8#5!g-m(R@W``GOj$K@ra-{H` z3$y)}o~9R1#OG1p+tw>1%A)BQ!7GuxF_EY+mGz<>Hyg-JE{CH7rVAb%!Ce(b(BS;1 z@wLHUp+89|^Jzc@JEJLDIF20N!^M}q$E}gN$)!_M4A{E!s$!2hQhxIt#2O)MKPOtvcnQy;)scYWUQ7(5ud$3nMqf- zCdvumMeiRO&!KtyQo{$Vnj3f=_3H>Cz?>A1e-c+qw3Th0^P*y3C@BcS0C6$Er!1i-<*Wc!w#pfDdXvIvTMkvz>Yp5N92sZbm6L!Yr#(U*qgz>SDW@x^$J}53tA3^V z5ViDZ6wlgKK_k zUd`IX@~L&Z}FDI+COb-;5xnV0ve+L2E{sJv4Uu znX>14zG_)BJ3Kb^EfaY`^>9EU{RFTHqo1)XNizq6_Y_l>(|U`h@Z$PwbvtU{7hyE3 zUA@6bx2vrTb%hJsd*_91y@MS-Tr8GEqg~m&4@<RDjEc|lfj&0{H7xB6UWAav^QL}2$v~oz#S~o64lE**!15cC z#CU5?f_MsRQ!y@|0#^B3i`}1o#oK^{1;Rq6kAySmol`Chn%}Ip(PTg(v;MYP^qy8{qrN z1KB7Y`fUCC{0X{6omw`Cl~~~j`ly{A$4Rig0(nDlE{Jih*pl9v<>(<`=)ld_67#@o zw7&aWWF_%cQob{ViDTry5TG|3DGgHIT`1_O#L#I+&OJl_#fa;d(?-7~e#}P5ps&3C zo1X?dR)Q8wwS}l0fDnNVpSs#QS!hN(i455|I``WBZ3tf+kj--urQD$0>fVS3t|ct6 zREc*&cxnnwxwKu5bx;a^SC6{cV2Mbljr;szp&1v?EuQE5 zaVq9pOArh5y-9Q7q1bT@8bW7y4o?3qE{R+9*U_!2XZm^~BVOh;0WYB5N~RMD0rj?; zg{*zQq-I85S{_?%oje;H)0%b8HG?zODaw^N<;?ZlC$SWQJ?$qg2@b;iup?VYlIG!^ zKV6*r-d7s*0(nQ;EDt6QyO#w%%oHDANuB-{h!F<#K!Y05!nFX~#dctsRC#K=tj$mj z_}3y)N)(r43EPiKfVMXY1K$cE5`5`{_-(5ix^T3uiG0?(pqK(%3>tlR-)8X;1SsS1Y8koI(&G9MAPQkQ32)9BFV1>JosWD@hS-^yN=oxS`u5CSs4fbYbEYkOHfPg zMhLJhVRTT9x_L6Ckji5p$6Ak6a_xr=Iw4S#&3{DEw`lHf3ec^vbKrIt-x6%BiE_3dDF6(4xJ?W#0Yt%ifOHN;%VFq@o3*%U6(GK+EH`f7Al29a^URS#FUL185LVmp>7@FbSRl<+Sj@X5 zXnSfz)2z}gA@%(D7ZoxCk)_xJ(sKD~_oRVs=J)^sl$NoQ=65Mm2 z3APx1oJvI7w&l~zwUKJ|v4+xx!1p9}g7qz%Jxi-=63H1Cp%;Prp3du}Q6t8g7BstS zF(v&PvonM*X#xzDy>c$7+b zIN4I1eE2>Z@{a(sY$yUc4A&SVYhQ?u92B#3mua@&VpCai?1}m}54jL?M!ZRn^(NSy zs=amv_E9@9h4AsT`aLRL@k3Fem|(d9YJrU{E#vkCN!oaU0a&8V!WBX66_go^!{hSK zAL?fV{$%!2t)t-_OWon^<*81BUA5@P zATUV2IUdL|mEi8hb^?u-R|6m`!lpug;Y!l*F;75*nx=a^hGC=ZS(r$Z!mvV%T*4pLfXk&xQ0^-qM%L zX}>!)H$scpEt9*>P-S*3N%3Wl`=Eh7qQ~a~wu#{_7)n$+6wa6j$d--&su_Td#k7vL z;ae0AQY~{d$d6tu=zk(Bm%JOpM%Di{nC|C=qigNd@Mh5P{oHu6Z(TXia`3d`m3fcO zXd4Y@={b*xy!9GvFv}(P<+Xl)a_HuL`Rj+BkB8Q&FA+)n!yvfp$${l2tsS3SNr?NW zFE?p}!JCF8hUF((&~BQ>w;b<1<>~On(?tE*2BZ0g+Xi zSxy{DK^F1iq~eB!K*}-0BM|Teggg!& zLA5UNCI=nj>Ui2(KbImnunaRX%>sZjFPRQ^092Ar20E(n_HV;@iiWSlx(Go5GD~<= zEOLAv?dN%SrzH6!Ra%eAM*tR4F!&DZl0@w|hV-|693KlIdnP60`QEi^MNb^N!5(3z z-;PxHj+ohZ$C*?H2ta!hY2OMcotvMlNi?!@@`*j~`|$B-kQMG7OMRh5_!a|SJ+251 z-Y%issiW_`H5Y8@!7rjWF;siQlhV1#X4SaOJum)A1Cc9j*|B3SwvC?oumJ%0rE++F zdzY^C)7(3IYPt8fv$$<^Q16>`irh;?2*`Ez{+s-E_Y|L!Tz5dGA>i_+As!(!2 z)u5TOpP{U4*?H>rmqx|}8k_p=pP`jc*IZv+im1gPzwnTQ)rg{NfejAiMuXTWpW~BJ zOpUNs85r|!LNiZuy)y?>g^HcHo$K~){9NSCBe=>luUbpJ5P(GerY<9w6ry5i*#hMB zpYa*=17_a~$L#vj#))@zTpE`;?F|kCC#of6(+o$aM;}$;YHwqUJslve*RMLvg`2Ek zNPj2?jX2SPx84$}-e?C09I1{PNFTR*{qqSpm;j#(1@R{`u{_!6(~`Jqq-dW+ZE1D3 zb#)_NBcPD|htJ>7v?cw&0H#_{ySZ(aR)>$Yyb)vb}fWi9}=pGczs zp;XP>QruUW-?)~@i#~GG!!FqTaP~~1g_$ZI2e5HdZfz>b7P6078=t;!S-7hg11)5D z-F0!vD+6iy#ONa;-7ZH@T*1P4&c^^t9H7l)wqu>Ti7l>}30omn`!1w1vP}s&%O_93 zLu~e6Z7Bf#9Lvq%1K%Ml)i4Ihc5={G0ssLdN-5Q2L|zYAct;$Vu0vz zs|9fFBxp?#5qGL3w$FT_NN_3Vq%7O@JMIsM3JYwlr;!G~xXRfFOlSxV7|oQuEXP`3 z=+QcqP1SU`PNFE~mZ+Y*rfUvHU~9r`7eyqm72{_h8`-v3)=ASMA>UMKe3_@nk<){t^C9d?##`0(MB&GV=3feivdEM&3aIZ z+?n>>^zdgj)A#zM{AG}A^f(^XwMJ4vC(aB()ye~QsLev6#44CNxDXOmIom&ZP!qy| zEK{5f4|p|qja(Qa*0&J!gnUTjzY9V)PDQ{m@``d(Zri_HnGtu*#f$Pqg<--OEUUyC zuIPu45=JMQ&WaVQGVxIhuAYT`D3jLcp{bbW&R)dTE>s-@7L3Vkl*>|MxwQhBY(+oX zh&rsU%M&G>^^Sr#w&aAkiQmkeU$hAl1t5r4go7ZXQCH>FKeC+M@63W|D~|Lz6Fv+l}hmMyAZdn9|4YMya&;G(%L9iT|T=E z=v~kJO#_+%>9s!t^vnaNcLoc@VsX1+&4USPg9(!Z;Xh|Y92r4-#X1>?nUWI^r;?(P zeq#Edu^7$!)eN#leSdT8My#6oOUX62Lf&Kmp4;NK^afv?!O>{*I{S&XT0nCN>X_!% zQWmbgS@$;WIN(Iv8i~NedmL@37>lz?ca#zYN|eej{=$*Lh%I1pdst@&Gpx10^ma3w z?jN_zyF3fwlr>qLhRYHv;hJ!Qq66=WW8Mlh85FwuyPaVK2YWYPz(x7rNs+ zd@4Yju1+_Pcl5eoco`*o=8-IC+e0(9;*XiF0P(}pZX$(H(5#b_1P=Mt|*1?%-?lhh$S5`CXHWjLpGOHyx=oD<5;f{i{ayowvfI)|bxEXd+ z-`92MFvEvqx!pDiC+Z}MR@vn$z1C~`4T#S=;sD8m1%%Zt?BzQJQYTGidn7~ZFu7)m zwTTRz=xDwb9^`2ke5G2(AYb#K>lX#H`;kOky(3a7iA>JPD*0R>X_Hg0FaGsbWYtyW zk`4_Cgm;1>5v4=rGkmdhlc<|qy)IS)k3F7T@Bm!Jq$%{x)7)p*-yd7#{_=eS9E2?M z=B1$rBAQ)!&Q*@1%25A%U;JD|Bilrh^&_^@Qi+V;;p|69g%%!&2LAZl-&jaM2@_`Z z`}l=P0rtI~wk?=*K8*~jbzv%Xv7uW>f#a)31XNaUT!TTMYCfbbw}l;Doxlr@41ghm%{k+ z6yoEQi5w&!Fkd>_fw+`&he3nzVg#)=Z|qSv*tWt8+sX@Hrh@>WXFyOe@b_?|Lj%D> z8ZA^9b@MFJ;oP3qNVq<9_8UorB8hmGq0IM><%sR+0p*bCt~@Lm0WyZ48+eF+ z$46bm?~7{=wd^v(OQM#A4=Dn6f<-0yAnKPJ&p1lS-EBSWikHA@WktA0YA z%uoBH*H-0cbM72i@SGYktoi37kE#OSI!bC7nB1~1w%5J%jtGY@t)bdhgrdTiaEe-H zT8dT_Rjhz$kfZp&iE3}w-s@mSBFtS`f9p!|8ZC4D?23QmiOYqvdfq`QhJGQbhS1}7 z2n#Mcd0|Cn2A_TbZ1ry(^pwBb;Ws#?Wy=Q7>0OFZ zT3cd#gxO2jyYIN-kVx!os=mIrI!GjkpRq~-9%IcL-4;IdnD5oa9tSU`u7kVUg*xqr zqN_+Kpa&aPNsBeV+8;wate-9epp&rKI%R$)FM-AEzD!T3#l`iG_2tkRzn;4i1m-?BUkRWF0=+a4M2YV457DYo0%>m z(J3G&=#o?{QMVE?0s3d=e8l`I)pBd$$NqRj1JY{og9~g_!?VHk^|m0}<_F74 zmrGX!2qPdZT0$j55Fa}f|1|CcIF65u)f?M-U5WUJlM^CLG{n(6$`j~7zmNx@7+KC< zKh{>Sa$&OPV&N{oTB2zo<;+{#^{-%O9B^gTIq*dl<9T7+hF+BA`w@VYHEl+Fx?Mdy zbZHhiJCmo-Vx~KL4ISeUaDxfc1%BS4;M2&8(-Vg83qzQ4(Qf+yUZwLnUElVK6em6= zemV`;?)KrEC`qD_`!pC(T+WK0C~}N|7tm1iWF7l)WxY-swB_eX&x_i zqI9{?D&f@M_-&qL1=eb|) zYb#X&=8geTYHNIkx)xQ@#JU0s$NdQ6%N#(TY{;XH?CqjRU+e=+-6G|MSO!zRBN^Qns)&^E5wD6F9NCJ#T%CLHAM2zW7UWd1=a7B=>Dx1cNDQF zybRU-H@X+X{Fi~(R^t3$OzrYvlZ)-;tSvkD%@AEKMI_7{S5&m=1pG!om@_w znq~V`k$2=7L(m`{?MbM#u!gHpdwW~7H%9Gy7+{xJ<_J;kgjgNdi>}3NCg5J~u0@Aq zxhWbm9vi0}W>5UbKpZLpE!FQEh%T>9{we*FV0zhdVDre)ZeHd4kX5I38a{;`w8uV_ zh9Tm`8JtP1_CZ^1a3<`v>_}rlX>i>g_TvMHWR)i<7U!)p%?J5}id`oHCTSF=yTfey zD9qB}#2+9ho|v2;d28pl0|F${{?256ZcEaj0G)~;>;#8qcWh5hC>z+DFPa#?xa9*4AETjSq6<9H-k&An_M%;f!-H_V?LSLO( ze`ov7iYRj+k_8RWIaKm3WPf-rr7h3y+=4Az_ZPJ~Nm? z7;!XeJFbuuGe6KVPhei}Y2VyG}r9S@u2PW)X^@|N|(2Yiqe^~nMNlSH-4+MV{+I~y^a7*Uhu z2}U~pO*E-a(z zPFfr6e1%FSRAS^|*#wV9fsUHRr2_+tM*I5Lk9zi{%J8*<4@onCr*#4MhjOCDNalA8 z;-0zq=v>m1PfX$s)@OYwnz#UqeFf-XEGY7uj~Cc2>2Fnd;@^B?Oa)9+vfWK0{6&r! zqbp(T{3IhUu2S{Pv$!s?a)E$Ix-BrOqmpGRZd+(8JJpD7;)tMw!`ky#Mk%&rio>$# z07G6&J9j9M9AeFKYbz<5eO-tf?O`&Y0|T;m={JN^-zaFHN&=<=o%VX`=MGE(1Ch1J zDt%IL<+~E*h3ooh%R6_|;}}Be$d$Sw0x}X~cb(yeNNf3=s*q)1Yo1v~{gU zXBnZuT#ovlZoRWU22q zIp&})FDwOopBjqP46~!Gf8bg`4R^c8u?g$%YOjpO&-vyiQP;n!3cv)A&ZP8c>E#Hx zIr>bXwvN8*1c7Gz2FUw29-V;YM4#ach?kn5Yg0XrRGwqd{BvVHTCd;dD@7 zrwGuH$W~=lILO=7xn*!AusRidmMt4m)17GO8Hkiff4tb^tus;6KyCTHU(-gKoznN( zEqTXA5V5Je3Xg0B18Cy!yqqrOzNBD%9tEi3Do=QpVpstN=QLZSibL+27sVG$uur9Q-M`)qxjb$qOYhL>hgB~?SjKum?zr9~WsXg*_}0H`mX$y1ey1bIl7y@^E;CH~CT>saaIXjLEFKr&)f{d&H0s8)Z-*{u)%jSnNWa#$#QV`$^Sn8Ak zHwaG#y6!G6n=2Fco1F22Vg8Su)0=9qzvGc~tUuKf(B>inKwzvn73ib*`0p<8RgxS! zT=7v#;!^D9^-*#-#m){x{MR9NyuU&N3KlN#u(k-h4k>DoWF5_{SzLM?L63}NvrOUa zCdSgO%B4N+GK>dO$*~+sIZOTa$1C!6zNKKYUN`)ntIne^PTh`3P|34c||Ptq(dbx6k-3Iosgm znOMw+HSNGiu%lO7eyHMV&EuxeRnMLP7KFX8TW_x<*+^YDm{HyuxMX}j#Ltj)ojo1Il1SuZIzMs+PG=}K zBb(|+QXQSPR{gMn*=h5aou-0^w1Gtd9=|MJ^r>d~q)Q<=pNXL?2{J?hfT>s_8mAH7 z1#B3WM%?kYD={Bp3HfUHhlcrfIo^)^q42q}M5?^1DIaenpDx;IIbup_ugi-}`{6+z zGiXc2X05*5OPe2Saj>ai{5lNy)q!01Wogo zF(nMN|1w@FlOuG0?vJ+2|6IRAqNRlb0KUzJdX%sCaYG9a>yh>B+18sF&tQ+&xL=*? z7JYa_!-;SBT&)B(&jxN^Z`l8=#*j)gq58^7o!8f zg|UW1ObKpR2Kb-=!^hl>frFPvGIn;HApl9i(zwEa4UX^21PZknRZ^{`HS%B-lW9#2 zlV?wXeGYL*m^}i3qF>IFmQ3}(;g<9C4iq<``QY4EKJ$#0D!x#Z2ffa zUJ>YVwubKdC+jaC0DH2Z#|125tBrWxU_=KbV^AXgN_g1}4_748T5&5j{`)E0sW;2$`2 z^4`is?9=!-Yz-)m+Z+^2Ny`S^En{J>!*2IM7)@wOg|3!}7W_W}vkus`%rO1Uh#v|( z7mV1kJC>vHL5X~M)vN)TA_c$+1G$X2Av|ue4%?52bRB}r+BP!2c{Ih0QrQf8hi*?7 z<3Cus>Kl2A2Lxr4%uC-{oGrzJK^EpC;NE@=B;o^fmY_oV1qK+>RgGvMa+GyGDm^@~ zv~*IWBWP>AoGB9fQ-@tqsliK{ENdEts<~UxWXRKsR%tR-2B{RQ7PKsf0ciV2fJzc| z2<5qAV$X+eZ7s{rVpb~V7=VN;*{2vX+4e1qD$6E^XZxf9Jj(M3#Bw;kea&4P^)(D3<3Yi4)OK$IqLP!c}U5#8c|+CEkFH__2pCK9d0u z6!6UL_>>Vjssu^ZN!Ln+hnWy9$iV=cjK#&%q1qEYln1Kv_qXyf_Kn%&rBWmj$MxX+>Th_F_K~_s{hON{j+DIY0;lk|3}3HIWOfl%J5yUk%CS2jykPAPA8 zlYhsx$H7M-rB~sB-9SP&?M8)*XUt)B@l!3Tm(kqYL8N zqYDI`a)1x`j-(m}L2nHOnA=aho0Yi2Macucew96R;n!wL6R<;*HszZ;lLkDt$<~NQ z;{gfut3WAP#+@m1a^VkwnhbUzXkJ#yOjZ#>#`{(H=yM(ac=6b7CwM1nwo+wa!HC~@ zZ!HIGg_KkAE&8~;!#<#v6nC;>BrK?RfWZdovL5Unhuz|zb$@@Pc`dK{rNnqv|5p*^ z?w7jy&LN0oFXKAzCPJ95my4pMdF8F4RjsF4c0Pz$X@pF2(KqQ^>c?z=9m?V3Ci<|= z$JRq~_(;SN8#B&Nz`hbs`3wWIW%kxQWslk|BeE!@;Rs!t779P_!qk!@K-M4MHaHnL zln^4%B9SK*jl}AUGNKGU9|5=`Uze1t8ZF%Qc>wP1!|9AJoWtWL#-S|SuEnASKu5;4pqK*MByhIx6WT8B zdy4d}uYhU;NK`qt?xxNfiaJYIc6}LZhFSm`E3)BY6AWDfT9*DDTX<+H<%(T^khT(R zC?mxwiEFB^IM87P_&i?F=GLs3`nUuVDqf(Z1E*lief_xc_rgBop*>Vy!b;~tm2q}K z4AH;#xoZ9E%Qs>y>HX&4&0JxM7e7nsrEFe>8!I}kcFEKBeVQBiG-qP#XyTwsk2!ep z5d^g}e|UNCaHPY@@R47z@tFO(BmCkwnt#lJ-Kzgd2IH`(^C?U;&6QYiTGe~&Q=sbol1dy5(6fGoU9A6mAjZ;jSPH{}^>(Wn zYRU0v1q32rG8?#>w&}|YuQZZ(77>%J8ri(3|6T3YD;zEpt&&-4XuMO7G-DnPCM-Q;Rg3so3$a~b|W@sM| z^uBzh0QF@~@!0shT&CnkW8$-^YCgvMzlba+s|8m6X{USI|B-tiJn9Ea_PXldm+yZ@ zrffMm71ny>a5O;kXE$3!)P(^$_;ZkgX&Ali;bmNr2AycW^$48*o)k7N?)q&T*tJqd z)V<>;XkZwSgVT0uY#T`;WXEbCv>J;pF{*@qJRPI4e z9uzSU4>vBjk*hY;ZQGU5-LEp4e!ARC?}_aT!Sl}dB_&jF5{uO=mSiIirk0InnJQ;h zfR53ZNKOzFU5daX^Jz0z8T~Bqw%W_(CcbQUgNdYiWaxMV!5-f1;k^fG70&t7BHGSt z*EM2Tiss2=opwiZjViG4$MQ-_RD5hfmHOFdo+8bvp@u&m$!mLjp+l8U4NDiz>LMc% ze9qKf1A;POp5C{LrMY{1G@I?;DO1PP`TyD|U~b(iCVL{G$3_e(b_6Vl;%tPY^C(hm zwKJsYLFAi>H^cWUh33RvKf~#G(n`%p*x6_Esnu94!QMnoOrTb-Z1sbY=qYDz#IPhj zaIW*|BNXX|emHR%@E2gZ6h<$oy`-P-lSQ8K0e4lAtr6u>y=<8#B`zLDY-F?_r+$@Y z--ah?UGEC)SU_bssc3C8a8e7H2wSfZD#!aj7#YYvmec^<1FRVG$a+<9@z{!*&cphg zYa^i={u*T6&-lWTGN}%p3ZL`d-pIR}4dJ?{TIPzrUSe+;B{rk3vi)P;i+uk(|I43Q zGKDH@PqMPbs-}i(s2*LW_lCVM-uKVF&qz6>8DU~ILocqO%8YYri>=@t_+N)R?$&vF z046K(84rB#s!YU@TgzXEX40ne*g>LZnOIM^-?#di_mrzR&i9xlrr1)jbB ziBz5jTBDz5{umZunUDb=!z~#|SdHdIUGEDtt;x6z2M&lfJoPi2tm?*BI$3n2yDI@U zbPOyhLFM#i-7Jgw!Ov=i?e>Bd0V=$WSa0y-`oD~^sHH3BjbfQ)TfDw}d6kZz>AJCu}^?(XhJy1To(;oSWG z`<&T(zc@4c!f}St=lguuz1F&}>vO}i&itPnsXG=+RYMS91WgbpP}2Pef!?@kuTeLS zEb&$Y3DU#R6Y}~v&%6K6aytD5^ETqT#seIY6^*}3&OETtfko-)B1Zt>0sP5NKb}3y zd>sus!4JaZSl*K9l0`EdZ`36mV004x>B>O$rxp=iW{CE-bycMP?45u6_&}RkH@POL zsBA0z`!!WWeGp`et9OQjaen9iP@rtfEB8Z~oPiWA9;EAndPGImNpm{O6Cwdg=wulS zodT|nK0WLGK*Fg_iS|h|y*kaE$Kw;RZe=|dyz}`2aWW-O2S-U}YwJryJ0op^H06Iz zwE1>JkZ11jy^@;!eai=|`TxZYd z{skvqSo1bX;Nf3Jq*U#MiSnpfEKW+_ve%gDxDGdpAUU3PjbI{W^Q#T#?7I35_{_5` zymlmk;jCh~WoJ3^ug480Z~d9~!?L68Jgk&FLy_8)&+vy3G|~)Ce10(_pMG^u8F9Uz z%am{A`ux;s$WPu=#-8NoG~Joi7g913aQPbzI?~^BHqzFvtH0dYyB&@QwA_js{J%k% z*w-KouKeb=)PR-O96oH*t2<~&-Bnf3co5hRfF)%z7BwAv4+4`GvefT;unCypeISa}5~AS6l7<5K7$0e#_f}ebvHz}weD&PS{Kc42 z=6yV@J7we!O$H%->(f_GZ)^4Z*1UAEHyep#xC&{bogI46VL3MB4Vgho;yj+4(f*(l z81D8~f4~hMfr@3e`Bau1(Sw56 ztS;kxF*8&ku|?3nk({1&c)fttAnFL9Oo?))%jwFr%BPNBvp2uZrwc+ALpa$mj1#Gw2@K$}Qw;0cd!+E1)%m!s9OP}g&NZi>?v01e@#?ShP3je#& z+a4P$?9&mJN@A!xQ11)y47 zHt9D3|0%S)!u$Z3-XxtfTx`fBb2}wr5EBy;ELT7O@q#w2W))62MXic%qi|1wV*jXz!8 zoSsGzo9wHgTlSbR;BkqTwYb*CA2 zZ`G<a2KP=KJ2@Omn9Q`T#6Rqw`uyG{2$}_V8H(Ktw&;8CqNBwH-q!<{M`Ojt~;t*!0pg6CcC?ajyw?LQl?)TK+3Fm65(`7ZVNkqiS{sObQD zoT)gFLG?-|r_7`00F8C=FX0rCsUI3qmIxG?Cv(GuK|M^k4b3l`>K_@_q1D|7rvGME zX6EL?noSphgixhFP%~Z~N!w%p<4Bqtm&O0_KmYp$(0GTcKAhdR<8!*^V@E-89>MTl zba5ZL*TG;-bO_Z*v-7U?ZXL_>HWsg^&iLLrK!&MdCO-6>{&Ln;4&$zV+m4~c)U!c) z4?`&@zu$K+$1%~&BQYQ87Ee7?_?%`*Kd5y+wrd+aM3uBn=FSO_sqPFmV}@R(E^RA6aDCRbr|oD9qk3I zKM9;1+*=Hm&$V8Tg$?H1ee3zI8Q3JBF}h<285clyh8NiMJ5?X#bvW8u{IJXa$2J$k zbcDRoRt}Eo|4&&w()5)H7yVV5#$g~T-{CFQoHtOLcFFHfW@Q;|DWR8CrBd9rX=ltV z1r6~&+zBE6z_537mG2&<_1j1GhD4%=y&4!p$^UII;46R%Caf3xmdmF>ECOoE2toJub+zR zm#r8`RtYh5vM$g7CD6mI0loZozqrh`v>4f3xG?vlL2nX zv9??7O~Hd4_*!JgOfkZHY&KII+#X9k!vr2TkzXx-n>&Bb)QO$pwC^8b&uEF~Tl6}+ zfkW|x4SC(Wffwiae14}Ho&W}?T9WN1oN-s90pm*Na4!i0LWPL|GE@SgUZd|`VjR7N zgj_;$@U9S{sIL~^dec^0ZMYS!EIG6y@gs`2W?{n)ltHniw^6O?y1KafE9YXiwmgRK zGsNc3j=uCcD2~7rPJ-20`_(a{!$hcl5H3lpnWlC4|4Qh%o*dEk|4&v@O@NVPgfpBJJ#kXHztJ2NB^V0t7k_IBcpKJX}9{bSpMox%9`V51g}=537u zNQnDp3w-G2SlBE&8m24>5P_n9r!d1lMZ=8!XVC0ntKvY1deev(dK&J_G0M6wDk1A& z$^P{tC>c|W&rHb|w`=-ig=fzen76}cDoyVCD9BSIFYg>EXw}rc&w?dp!{S52i2`z~kuEIfLBz@6D$bS%S5dO&1nFEa9Y|3?~J$FQ}`AV3f#pvPa*jdu% zbH>+G!T1WKkK;>`*Ix&`Z6QVx37@5cPT0RoLE?_nZHdsr1d7?cN1`C};9)7w{sZB# zQ&as%Z~ZiCn5%Eu(9fhQ+2YR{F<|wVu0lzSdkMTJTTGuzleD`j=p#A{M)u*w4*uQj z_;JLvyRr@;XS}n2|~Wp%UfDCqN9@P)q^) zMJfJ04*bXU(ib%TXEWkX@lU+5m&_ewa4rV=w^zkUZy=`Xu>g9(F7keK?Rw2^gz6B6 zeISK0h9{h9=%cwH+2xO94cGw#pZs`WQ?|uMf}GIGgBqS=_fBv1O*`zj1Ov< zliO@lI%j_GL2w3?X$)OwbFRji=jl(N0x{3qFw` z%G%<1CFAyZ;c2tbTMZ(k=f!!0wH?F}8G{?bfxUsOnnZPBcrlG=x|v!j^8+o?|3}=X zvAmuJe2F7|{+GNcX5w?-c-5W=_{JjSIAOxYf?ov}tFMG1@I`xCTJykn08D4S5#)|K zOARtEEpIX{x382*F#NmIB=(z{pMsx5DHe&E%?VTp^_Wo=TTqI&?~t$hG4QJ2s#U)Q z!@b(fTE%V|2t<*^KgcQT3=Nch(gd^ov@L9h^)A-(j+J{o`mzpGY4Tpj1y8~6%8(k> z#Z5#}>pBA*8~F}EbzzH8+v0Ru#kf|oNV#EN*CSYIy{F_qZ}ouuw6MfTaA`_0jWu6Z zGYX?kd1#C1tKKU}=Okhj)+Ct*h08&fvm=4CJ|V*p~&E zCQX)$b)=_>xKyiSivf9B^md{{!YupPQBD2be*ZPtetnrE7eZA>95y-|P16+^o`34U_6TahE!V`_KDpVD zg8p8SFGIN`@ukTJZyJ_n{fGtl7Q;A@IrQ~t;DF41Eo0zhYehIcxm|vOi^k)R1guHm zJ9{r0VCRoSc8Ny;+J-WBqS#-i*#tfiP#t4gBXbjf;c%pIm>80PlYKFAUqL)kHJTtv zBGkr;YH84`J53BY5F)hqdK1xjVrX}-_7q-g0ua8O-s%?F<3+nPfsH>{a<6#i623mH z5dn?LJV)qCK@i%=am6^YWF*S7PVaDjP%5%Ow(Jd%k-6Q+ZVg*5G+K>GkUOICpD+(3 z58lNm6j~5r^x5acBbpCtb$uqrwm&l(%O6!*Zwt`lp?uV}b8@SjWewOU?xd>1m0M$b z1@y2C(q2Icwvio#o>dDEfg}?$z=COBGV8xGxI}12znFdWco;JR+D!EAar?yVWF3sN z;ZcZXenld%Kbs8+gRd82GWW`>*^%As?2+|9;ciy3YC=ETm@rvnB@dZ+Ub%L+O_>s1 zj>ovQjx7YV^h1Q0(wrWQJbx&fp1f{Dg?jVJ z7Y6)Fk|e}QK}zpD>fB>Mj;KM(oK1zp4>b=cdb%0Q!+7Otwfro?%;ut;WT?PKeC-Iv zfIt+AgBEkUu3ow}(1()hd5@cXbl!#?(vc-kI+G!s`aM*m5=ksP3eyr-5-@M~ULIjx zO6)#Id1bI?JDtsV;EK!It%Ad8jDzzXL|*A|H?T_1Hk8N23jPFQ1gC8_u?!}c^}nCz z7f+KIlr<7xWdpaTROJg*$Ti!kfc$sgBOhbs&ns2BQu$jg+p9lqcwb^19Ku?joMiA| z!A}9qFKe6Of<>j)!$<-djr!o_>pw#7%vPnpUsotpSOq|g*RHzBrUe$zWi)NDi&B8E zb7D;_0oZ+5)iX}SQJ^p|FjkFHJ&_=+YX*J$Ka+2*t!wPq<5gSZRnMv&cLi|-A=P4A z0g@UeQf8OsXa7OJw}nLKbY?Z`|9jAif6w9$IGGtFziZC{^~NrmT*9fbGdz(0axf?$ zCms3iR{ba5brxN2g6>l#l+Nfk8vFRYzvFa);c_!^1(AThp<5eW!PISQp*yza~ zCz~nV0K2hUNBsQR?+JUN&E$2u&4kh!$MzwEG^8*u=jiUt z)JGJtU@mq6>whlnsY_bHR>WrAX9vEs%p-fI2@I3~NyHxFFtVtgfi0A)qNBs|t7B^E zF9}>9`@t`>XZOp zhL_mLfP!%2_ybmwVS~Qtr?uYE#&Kv8XpI{IB6Lsdq-W9pkswP2kn%rHLp!`43xNJ&I9^J3%8 zVOevAG!DJZ?O|{@%J5u7YU*CK!#6tm_QwT@OTXTO#?BrX)5>+AlFsSCQ;!f0%>5L< z1`rK8*ERkkm$GqurPpz&V% zc5LlzedyKH1{K2gQI@E!+;4icBVe`W2 zcHPm>aRxlZEMR#AC$jzr&W{;4OotSu2LP+Q)2S~bq~G}0uC!(>2ImrKCZ%>8;(`>x zsx9LH@a273GfPP_4K=SDJx-nZWCB(NXXLqewmx?EoW(BEu%vJS8Kb5ZR#K(T+lU!I zT5sZngzM3B)dOrEO$Dy4ioe|0vfzPfl3TwW?otw(jrw>-A=RvBxrdaXZW7j4te*Vq z{-CadR8^-}arVUmn!5mZH5!QYMUiLowM7p?VJsk0)!?IqhVJ6uWKL{!o2lNX$@j@0 zvw&&9r!!CDL2XBGJpXJrK(EO*2cesREQA07U+L1at?#vA9I!<9W{LnoXx9XE!(ue_ zb~pkT_855FL`g!<6}}L_#NhjTF$sTnX#eKd?$+)#3^N<<=aX5sVf%2PR3;}JO*$JA zCQ~B1;*KbS5H5IPA|yV+pP`~zJtMkAca`D)R7*OEKN*`42DqBzmDO9j=Mi2x$3l2H zeB~%eG@W?-{v(o>FB9hq<_y7gAa3(kR2JRN6#A9maK#UX^l-E%B5j2oU113NQ5Ng1*0^h0JTU7z;4*!CWv!_=xt@94*$HkfeP%Muk?(*m|fxGpM3 zqO<>7;PV|LX1n6n=2KUEsQn%Z`rcFTK(p5>8OtT{W{kHU5_NL8NvauxsAw<{@TZW! zI;`%1?vDcDo=*DJW6c5uK|P1|qy?VHTL@3iIQcgl#WA+HG+=USkcR7B-^IOpJ%6)X znE%)p%$1E*h+vx|R0Hj<#iI@v#DQNc)efOo&w4OXSmBdDn8^(ofm^W39m=p69^a5A zS?o!d)3Sa$Y7okt#(q8J8g+6@Jx$VfCq#%+IF$mG{B1D5cjg4E_r?#185l|wOi@n6 zL=pc?(LjPqtbI)Gxo=VAP?=|Q1zkyk>pz&_Kl^+y^bsxenMf0?9)v2Cg-(%Vc1>Z~ zLRj0qvuyfVj@@qkeu~0@_hnXXGLFmeM4x6U=t>m-G zVuaz~i?=0j=bVC7uNy7+}Z&c6!6W^050(>*m~#8ln;J;_rK`^R3<|4Jx2F zfUU3wB|Z3s7kY?7@eci&2^^C+sqh)q25{gjdYWY+s4VM9GoxGsouH+Gv7oaw9*0LVcRt(!JSc!Px#|)woh65S9u6 zO4o8%wr(M`VlR2f9QQqE-mrxv+UuG$-3;heuXU!ky!z8g$<0JQCis{9HYV7Ic6&j7 zFH1@kFQ?FVG`6S1l9#SDz|39V1j((~Z#cdx+51JTYNtUNFa!+h4GCH%Ly=F4NAju- zLJnPXvXm{@P`s5h{cMB(I$_%4F4tBQtng2V5dYn8`-!Y%pfS=2=I?wUmvh@v~8>`qakC@ZhbLkGJv{AP|l34Ft^5J`Xc??)^J{BMJnhifZR3eIt(c(;o$2wDOw;b1AlvaK1C4=8pA9v|4~l7{-++AzLY~Bp-%r4Etu&2xY89FPu91q0?pw`>H`rG3FSek_+DGcC zDi2%CFnAji{B|O!;VLl-If9u*#M9Wt?e)d6!)oScbPXq=Pi9ACprxiVs$;X-nO`~$%ye=(I@fHR`ez=U zdLF3TBE>_Ma&Op%<3Hte57i5BP33R;68z5!LIv)o%_p)a%T5T9S|=u}|#k zQ)b65T1+0_skM50tGK?l7rk zUy1+0w|c(xQ@d^Mc;bsHG8Bz{dV`S6n5AM|rZVPtYfbR?KDM=U`i5gI-s6G{7d-?W zb!>k-vdg;80_Omsh^lJwnSAFgPQ>_N*}g^yoE;k#9vHt`?B4O8v`KYSnlwAM1*MAT$)@D~|Id-*>N%=5LmnPJx=$ zH(1?PpxEvfU%DdX*TI|&JPBkw4NPl@A4W{1-&^Jn{+*E}l8>=&UJ9SL{kVx+bMaA8 z2D; z7vR=ym}y@am+_de8l+9MhEj-tjKtXDf~(rVXG~{QeO>&zvVs%YfD;j&tr~n_5PR+0 zYhu;{|Lfb!KFA0F(hh2F1MjQnS2&i7Nc2-Te~iZ33sgbC$Z6-+=FdOFBF$Q)&w8#Gc2pt3I-51`hL`0q z;1eJU8Bocw7A}pG=a!TAIRrkse<0vl39n_mCS_x-+u9-04op<&^${9>UZcK!)Gf;Y zC$V?0Qqie;zs6)bCfCrUIgCD$RczcM-j=5@@B!Tqy7tTdUef2(L8$6PdEo}mBA1{H zzjszBNC$5Vu~@uRioMh*di^;59B2RQ*BgCJMfaAzPivWdlTG>{w3yxTauvhQ>&-;K zJ!Q^%x}_AS54wLng1T9ROcnnDE{2Hs@gF2UoyEc+T6|@;(xUe#(UbGPz>@WaZ6s zXe~$c>-kGnqcthopld1mWd!t(_bnkuG6}`1Q5Cn#|d} zibC1LSWZv6f41RnL0DQg^D_zW3%pnt8RVz zgvW-j*mMt-q7Z263Hf}g`U3ZIU+oz{C$qu>PG1*I;?#~bj-cFWjA3U)bZiP~D6*R( z9Vm$2e>yc_;mzApVw@kBgl6hb(Cq*TP6CKvlVM8$5oQe6?aeuY^AoT z=QE9!;^(@}N%B=kN<9|(84qh3`xe=XuDcWegul+9rKGy?_YPZ!;dHifHLWUe_M`(k zADv@|fyBs6A!jdCI1RIm%g>=jWiSSywL@#XtQ@v}Q+w@yHk03B@}YZ7W;@gOS0q&7 zs<*>I0BK3x^ul_*hXjvSW0X!G`9->?^sNE3MAYhapnUAMqYmKK`2Mdkz?a8Nr+%dS zRIh8DRMx?HG$jW#q}i&pC=uPL=-pNR$$O-5Z*7OTHxun=wGw>O`$a@M*0u!!CA%{S zth=4DmYQhIGsmd-Uv^%6uJ$dY>g|kUxi=%@*0rD4w9gueUs5Reuz^Nb3_}T7H!2X( zYkHC1I_S`U_8A8}I_|Bf+9yje67U#tgF)-FC6@oUSJ%4=pU0KwBMbNutwAlp5YLyT zFBsXwTL<(GJF8fT%e94A3;3aFGJ+?qpP770T5JyIRDSzRmAHLW4*-r1qC6Sxt!NEO zVS7Qnq|2qZVkv6gZEszet}kucq$tbO?NFe8T#=gqFn}5B)JcNrPZ^@&+VEAdk2^G_ zlLZt1TW}J>w|sez2BDbf>I{+?y@?@bzK-+%{caC5OVjjWmw_SWoaBab#;X-+jkny^ zO!&+hhk77^oj{V-Rv_-J90^-!%gnSU9@rboQHuEa13Ji9_=R&(9`V&Sx?Pt(qhhYP zz!hY#py^L>T0gCdR`E{wBsL^c2!Lw^#z0(y48+9M*1Zmh(2d0*Q914Qoh?w=50vtT zDp&1t@xPWb_BRL`8fJxjMZ?<;3O+XH*8aWB@WLQoVE=SO=5fVJo^kI@Dqd)GvneMq@q9U>ZvQ$yMk} zj~P^PBkuA4_20T=Rx>FQWHq}$O9iHWrz>0H7Uu%Uk33?lXD}Zm#w{Yvtjxq;csiN# z{|(kmbIXuD-zmN{nD3C0W=zqdflNGb1`~)WE#=m(=Lx(I^mv}(mZ3m$a{F*;U}G>0 z*ieZNADNol_L>j?)MTv}M1!!kIsJ$UO~oRXyjEO1Sf6*vkaaH-ePRMaA*_ps5Mvc0 zLiAvyZh%MTRd`764BCIZv?62ZXBGq`vurE9;e~3`EuYud>+9!Y1rj6N!k;FVvPt}d zv^dpZY*Bo+Ziu)2dO)keWUS=$u>ZLsJ_;2ikiNGQ!jY-|Qw#1*e8;H8Qc)eiC@` z$2&?i&;(mfxw`5)+dcSc_7e5!pRaAy2T8OD`#P|0E32RNSa|?kw>+ESmqhVW6+O*# zM5Bg9&>OI>5AFEV3^KPDsjlhe!Xi)QI)omk@i5nIEryHW$LBP-9WHAG_&h*0hl1^W zNo{0W&c8PXAs;nL*=8Pkn1Q1M_##2;)-P@FAZ5<$)*mUd`=7pr!e6hXTAl8+tFC zl)k8d&{%KPhZ59<64s-uzKYV?L(1cpPQ|^r+)c-B0aSNjpip%YLk;f6cIO2KRdCCM z=fkndW2b7whU5aAg9T0J-gI7;|Rz--AsIIygjCFIY}I#oU3+v$_Z$iSE3F;SxH+o85l6lZxF(lUBu}C zL??49?b|D|UpR}l>CSMlBX)YDN50*8?W~Qa<@BPy>e~lu4{#7^sc$y;2wV9fz|R>{ zc2t4SQ3Q~4py2@o->j1R!@M0H^xL)Frh?UmhaR+E{g>{r)iO#L-EdhboxYA`FQ7I7 zzu(5P9Qb-^`;h3U3Zu5TXF)?|@?-okE+4h+TO{{24&XrvVDqFidCpX|dBaLuZQnthu04g{R%);KFR2g2gA1s<4vxsI=Ps@1F9%(g%~?44!wdQJ zXD8%h&Y$B$DdGp^*jZ)nn}K3P{tiz3MB8Lx;_vQ8-@EaIwe6Q)^W#oqb`$2`(3oKm za*1YQ5)tnJU}$N~)04fw=&z;7PwNL(E7wccVtSibvL5i6`?otkqWpdDcXqzT4`f>> zZGC3RqX2_%TkCsZlH=Mmkk1jHcp(3qOW$?ody-|3__~OI%48-mCG1J$MUXVVXw9kT z66D4O4WG8hNAMPb(w9MISK0)h)*KTO?W#n7EOT>Y5BS{OY!)4k_gFsa_}iip3v)NSGt zY{>fcMxWAJtx`azDuL~LxhUSBd_8kIq1N8O2kr0joN&K5JPSOB{O-EZD7v%X?5-$o&pRrbcOcu~OWo6vtl5)NIjmW|cPr@5yN z0X}0YU;L_(==x$KTV#NiTii+8<67Y z4nH2VW7Js z2mg|H9K?z>*68Y&=K~n^vY-22s*8+1*)pgkV>K;RtU8GQ^g3e413vW|76qf$BG$DYAu_}yuX_5&tPRYD^f$jqcyw1sRhFF^JrVTQGzHq+vC0?2?^PMNOe zT2x8&Ho!`77T?pA>P(X2M1Yzpm^mD=yT2Ad`q-++>#G%Ypb*0=q8v44u7Z^r6h@XmvuG*d;BuopoiHi14rUmo{vfeTlwZ#} zD*wide}EVhSIeWnr?0!t+f3MHpAVeyo@@cubo`~uiXi4?E5#EQ(%q{2eT}6(Pi1}l zpI5NCK69Qtz#i8laX^q@VcTraL-1e3ZrpY_4(t3d#~V2;>DGRnwgeU1Ld-uD{0vYI z3#16;=t-%x@|T^DWFCi?Z#GT@PCu{_dyp*+)|bwc;@>Y<%BW@k5@tX@Uhr*p)Oj1# zbu^aHV>0od4>;_hLO+QOVm1tqO@-6uP||a{=H%OZesnpppRgU@4y0eMBSG$9%gMo& zqQyB2x-@l9#3BJbw~-f!$%Ma*Z1SsQv%MgIvu@aon|w*OSVg$&Dd`6z`*$oQD0EbL z!;6O;d3n`P?{a31eS*(zQND80e$o(Z@LW~!Tx`HKtLAThJ%U&N{_o4Cc7~Ek&(xY$ z(OuzJ5&;2$J$ukW4{b3tITsU~Ar#df5%psM`TTbJw_%f85vEberM@Y*-`n_ijQmqU zSM1Ivd&Qi@WPtmf^j_y?`rM9@Vgo3XA3SjspG};aqRZ-8JP|yemfAh0o1i`z-5(=Wp~Z*3iy^UVnVwpq_O(nu?R^q@kEuOMx{+Qh`uPR)M-42-QY0 z8<1g9H$4Y3i2=ARfJKFqvI9G~y=15bK@?2(xwSECALCt^=hk{k5}S&O)tX|ZQP84) zk=>kh3OOoJVf-=~CuX9pejNJ>uKc~AZGDn=yF+*h@S29GE=OS(qX+RcaElF;zKx%r z4OC|EN-miV=!?N0!oIrb1`VA4gGAP~V)7#PxS@EATzT5fm{#~P(P=Wd>IU!-1;foR zkSu+E96_w$-!Qr-X0-rkI+zSvc^Ds3Uym~xm#KY!1PqdJi$&ol_J#c`)M_cFjr*sh_!jD)8C7JS@Yq=wq(SW_BA0Z8!Azkg(>f|~^tjyt|G zT&Jb?!6?GqG&JUWc7=8taoe;w!@cz?P=L*O({wxOvdcbqwtZiHjXDc(JDe&#?3Og( zbpiLnjDnkRka@qs&P2=HmS)oL;->V>XZ*8zP*VKSDP>jLP8>4qLA*aH2_~c9BJb8z1s@qswkuX&7}`Tr<73Ce(0O#Ug{g^5sCoeXAJF!{+?*>2y{?3G+y2n`3Ja7z zD@hrUa|Z=F2>hwJ0KNG@Wj+gRBpYRkqiogtr3+_S6sX63qh}aRhc{fV#DR12e&{o> zXH$?fqwK(qhzI6zjJfxm3tJNRI8xxMAvQYh!zK}#P$u~+jSFLfem;1^(yqCmwoO7G$UVawz~A=SuR zfkD{p<@T`G&a|5^un9cQ;}#o??eA$n5VFJ8s{l$9-J7kH+*u_W2K_q@Q$Z{|Z&?lm zP|d9l%o@gl#2dDS^kc>=9-KPhYOdrxqVC~+4Rh+BLJa6-Ib9J))y_^w8XPdaITOwQ zL?`mUx7Xn;I9RpIr3qN+f`QE>IS!{r-a<3+SIR(YH z_9WHYs3Y>`q@+{(aU0MeDzUIKVORv)0&G7rIEItrNqM$zKbU}L#71fBdPzTQUuV-Y z==+2(^;-b_5aP3Q#Ji`B2{>`qmzAq&lW`7{sR36c=Y(YVjspa+SAeNVsQ#73c@ML= zrzJUVPDxK$VIF!ZgHNLg?sVYvuqRoP`u+*za>(v7nZdoGbl)pPe=HLBd}X-lzz?I$ z5m~TYp{XdQ#IE-L^mwWSOUZJW;h26|@NlD>-st++-^*M;EIU}=Sd8 z8k;&eqpqv@hKMA{nUC?y0Nx^0{N+oNgtVRp`5QRS8Lpk)x$|jf?0F$+?x+q(sv>nl zO)sR}q)3M8v)UD|cE;tF0EMXALo)o^Q0s|%M(*>>v5HYAYT3hS$me+=7h{52F<;Aesm4-9)T+ZqwHU#3Nz&VT^7#{0j zJYcJq?s#6ZvTYG7T-?(>cAva3Ti(n+yvHU;%k`Y~9;vlO*FnfupqZ^^2v~0@VdvUz zM#*TSDw14sz)puj3{lpCOCSjLD9lRuLqdjZ(5sW0K}92h_Q27FYRP=MU!TaXnZ|0| zE3D<`FHeP$wfS+~n(-x1sJb#t`{8^i{>cMc5XH|`TskN?x8~!-JWt1OA8w6GjCbMO z>?4OmX@x7pTLVa`3(><*2OD*2GegJ%RGAIco?3;X=N9Qzmyx6VWwvDAPr^uAFL^$# z&nFuMT+S(ZOsv{2hOF98i%91znK?54DuozDwf?r*HD*0Xqf==`IiXo~D0XH{)e9>F ziLP8fo5LXwHom|i)NMS#OOSq`^SUpome-LE`a=*+qKr{RC(7?$nz8OBMVsD=RZ-)&|vPZ5iE^`Sf3e5{!6ClWhx3FWm`#hff%93r~1d zgC#>;WUi&h+UHNfs8|siMO(3zQ^LxIH4m z6CI7>`$O3X3=U@A?d|ep&UK%ixYS%_T4y(PG%|h5}T z1x9+rRq^sok3~!6%RPm8|IWn+4{mIU6UW$8R6)-WT+eRxsP7TtX4YHn3Hh$T#s9Z8Ka7d!pCsXYbjx2`6yy4kWnj@uLLA5T zQ`?YjZ%mL?>l0;{pP$GD9yL=|FU-U&dsp5>xK^%EoUVD|yPTdl{xBHC>7;8}cv{8} z6yeCGA!m0z2*Dp|87p*ZI=`zUy84L$(sz z&G79r=$d{LqDu>E-b6KzG@ve?cTTt&vD6u?^tRJuRa&;!rX*pAiN8=CxjP6DmA}L& zJL)kX1SRSb+-i-DvUfGACe5Z|NjPZq6~(JkV|E25=Bo>vj28qmn{;;JJSw3}Yn4WB z*SuNR_w9~2QT{Qxx4oNfNO~;L^%CdV7bzvM?xSkBlG=5}yFHaJ68G(sZkEnC3Po?2Tna8#a4H`IT~)#)&80 zD`jgxSFM@6Xt_*>sVB0n>w8Ys1&M<;Dpy6apcMU?btNHs7ow%8zQP?-I40x1uitsd zDDkr2W(##3U;b;XqX|2x=HZfG>i_9^4cm0Cx~b0_L!f}dRpaC|6&6m-J55szV;bv|)%Teu>7mR&5<5z~chL`O*Q#Day_dwY zRu$A!Ql#8KZKBe)wezUd+K60_4JJwdu3GJuE}k8;+m1Cv&^yT%llSP67_PHVg6e8r zw~K2(uJ0&6#}_tnK=Gxt-E>lq-MAc&eRpb5TL>O$w0I76PeT3!<+z>?r~IO{kl$8` z`x6FXSVzGG`#!08Y`FLePOyWElb!owMo4J%x)3C18FQ+lL9tTx^}`xfJQ&__s%gYD z%{cN5DW)8dFDymzsdWvB`enBMw!GY6+%eEeeAMs#h981R^n7{Xd3dvc1qF_8DeP?Wb76O+%5p;yO-hM(VKn2*G=C z71bG83q@kt+W3F2b}xFattpxD__I2dQGeN5QO|DWSS=$XYo4d(5?mTD>vZtAVH1k{ zWviv^Sp?Ofnu?J08IT#1^K|}gecD^nhw&Ub) z4Y1yH!Y!p~~EB;-Tqm2`PS$BLnIib711|J5LZaD^g@Do=#4jWAb#-y!|Fz?=k9iI%P z)XVNHdqisK+87~qt)1&P$V=X8*4Tm?4_OVf^o;DtrSHr?dIJ}2>x*_tB-QTgmY2V( zTz0^d(5LtkFy`g%y6{8^kqWSe@Fk%IRSjF!uDgjsi-8*?nVweSjuNZT zo_8@Ey%r5EhI(3Yo@|NCnA$X)H!*Y{Ms=S;6lFF4CJ7B&NYb3?M5~B`o*!z8&Ey(* z%{%hsbtm(J5b#d8Z*JW#!y9(XdG>H{Gpl~0l+vNIjBVlQO`_$=pI)4JU}r1z?|44c z%H6JQN?CiQ&c{_x{9;Y{1;KZK-pQ#vE~I9DTIA_ly?gu+?8ja_vL;rlq9aEO?tig% zZb~lNUzJou1~qN&M^OMj~GCG=SqF`YUg9FoWLg&$1^MC_)AR)m( zNQ=BiGBDY9)p|Y?ckyFM_RktLwaj79el^l5iqxAD^*H$3N)i$Zj^&O5pbqh{WXvX@ z4mFB~V@%o0xXvX-XOF~J%Q~x@jJ3Nxd(%xX2;HrklC^T$q(me&bSghYL}CGaf&Y|GH2a^@oNsJzs251j;Wj@)+nEWyj3e{YF9e z6KrkB36E1dImNNUn2shu?JEh(gO22&^jFV2!Ba!$nVq7ckdXIQs=3UZDXkF0F#h`e3+mrme(rR@3W1O>Z`Yg4z4ab7)t z)ECjizrAgGbougJZ18$|(`aVOcD$dD<$v!Y-ot5IjN52tOYX9#Fh(x1{(NO40)^{* zo2Q&ol8tky4_Fa{-ES*s95?r|igy*ko*BW_2*Zabvh zw>sOFd@LMiP;g&JrL0N1sY~{9F<#q0+<(3C^#eHI;hv+DFnYYh&ypFewid5yOhW0Y zncENleu*nFPjtzW&Qz#irA^dc`s**7xo*@;>vSU78J?k`CPIQ28#Nv*)F;hL#E30L z>7%a2kmYC{(|a-Jt#yj4y8AlUq8)s^<~5MfY@$yn%!NGs zrAb~++$}GGFLaU51Oc&)e>=x4Jj^xcwOiuyvrN2s4j*#&`z~{%(eBJ{?t<*Q=(L&uHW z<(E$Y5epe)fB4nOmrJ`C_~6bYG^aIb%u?;Vt-TcLJZ0LIZZ1M!710}-g?CkW%8rQg zqmzU8yCfCcb^ka%F~qe#)Rt~obKdT~JclKk#m<6Ts}TEf_^>9U@ctflQgD@<1&qO( znGoWoGqw%fv|P=Q&lL@xM!&YO9qT{3pfVL{xm@y7<#Pkwxyq?>ZXIo<3^A4)?*CjVZ@!?+!w26=Hjh3)MP#qYnrZ}mMFCn^m=uQ>MAn&>RYCAyLm~K zkA>B{oA(V}4IaVD_#s>&MxwUBOe6d=loBHstxmzvIMJDD_!G-d(252vraNW*09ab} z?=;iBu;Y6N=jIvaVa4Z?uq4b!$L;B5!D90KcA7j@K)HWR3X!*g%Vvu5A8vJquMMTv zUui*ol{DyYA=poF3qVcx96oRwPmREvS);W%(;-8cq6(7K&BA9hChjo*}MDM5In!d)VDA zLD?M8TT3x9&)RYJ|FCq`QBgi$UqwM$kxuFEP6d$;36Wg7yBn00mhSHEF3APy?(Xic zcliF^bM_qnT3zRv=g$4qorulvjj8&4>s`$zVV2|}4SY>%BO+l7z3KbgZ!oZO(a_O_ zArQjGqq(k2g1O%Qe&J%mCnyywd(!8i6x-O{t|j4juLYGAGQ6bus`-5{f5|~wm4j>p z3Dj80C1t;6E0)po2M&Gu-R5#br zbs_US_0_oVj!YB_MO0z$`ijkXygpr|o`0YkQ#HBc)GR==+t4G0qE=1$_rVyzii>ua zS4be7hhBmy?oU+B%|xX%Msf44*tD0744h$8P*cMK zqoc~R{S+i27-U5Ul$DcSJ&{3=S6ZeHNSKwOj)PMS+mHGxIW3Mpq}lZ6vl@I+IA0-V zJt0FUCfPcZQ#&``sK~tfU2YE}UXgx=NN~A?1Xe2SV?+9cf5|DcH;8KVEjCku6Y&5B zpWd99xU=)i3^R5$tt)IBZravyjIac*OTA(xPi!l06%C(&GX!z$=#55)E7otlGN|tSP5x&0pbMeR`(tM4*O@& z?@!82v9C|fX&_Y4ot=5!VAjkU9A5dJT58_FExK(WzranT;Klx;bo%ay8^FM+q3>g( zto@a)EN@X+ST-+hsTxXs5QyqTK3n*w%bm8?hr{yO-QFj_}tX{y9{T zz|6#B?_P0cR?gHry9J!ic-{VwyY*0cy-1EFg=dy6m&g3YmM@`(lIHa zf-7A*b=5!P-o5WnUod_hrzD_m#UYZMa31%uq)2Pm$XOZ-?N2zm-w@^5YM961(URkz zlnPuImmHL3m7pXGMp1@|%s*r(Ta;-k8OhrLD=)_#OCDdXi5_{1RWK$Uh~vGjROXIq zi9NGS?%cZ=ogVd9Ehb~()5=CYOIf+N;j(G*+bkhYnTZta?39_!h!FsILC1SjfIB)~ zs|(Y3W%>pebbCR+7)rw=2b%F|ElE4`Hb(Zb(S)QF9NY?{5n4GjUccGiA!=|%uzoSa zLEH9{M<%+e=sf*8D^)z`MZ;NDmQd^b9B;*yG)T|gbMA@D7 z%r{m;)4rdrU!sHLBV$T_hGC#ZbUm5mk_FVgk!wuVE_1J3w+zl!G3^tod+!E?-^iq4 zZt+kH$(5$kn7Er6QwU%i8I8M3SWi~tBhhQCPqfV$4`4EBZPXvvFRz{UZ1@RF`!f^K zhGpKrU1to?#%%DzN4g{Kb)?pyrz4@~+leWSCx>x&cW0|P|A0l{WAkQGZ6U}_AikDi zTz-l9@7PuL2ln?4qlS+1WBi?)PJ2xP-eM7*ZRWjTSc6S{hWl(E;Gh;dx$K^{*SYMN zc5xmLO|nOi-gGa&;D6`{Z8RZ>5+b(Nl%d0rZni5LHf?MT_yME+eVfq!ea2Lp`f4%* zfMSaRf9JC4$&{t>`vcqZG@4aJ6BRmogArFkg6z*xN=ss_yhZGX9GPa52^aH?47J9) z(u=T3D9{F#yo89$-6KO<9_46Ed4KG4{Rg?20g4PWmm#5{Y$y83o z@7^;k*iP#3uUKBzI=mYnyWddzv?coWNZ#~th1T=LGj{bjR!ZzAp_=mFKs)A|^WZcT z=J&}TzRab0-`Bl+T(NwN+x`MKbF-&OOilOOQBsY|quG3*h4b9W9lv?>XUE1$`2hU3 z;oIJ0f2~N&Ai>IAXx5Rd7HTXo4c(}=@_7ZL+~oybW0!kca|32VlyOpiY<5VYaV#K3 zdFNvv3l^TM7-H?ax}V>5N74;Avi#0gvSGV(oDMI;8k|}ylELOa)%Bi9b=l%NR~)B# za%6&q1Ho6f;G)xvdpB~?H)t4U>uOJz1SwA^vL{ZHo2J`j&y~TqM2<3Dl8^A<)QKB1 z(>AdwaHy$IIx-ec7I0^)6M(>RI$N*0uj_b7rb;bx;56LVT%g<2Hd2B4>cWJuKe)XL z0bzodGbBtr^}X)sbB}?WBTwT*H6&u9_^uR^mtJxV@zasEcYFb61PFF0Davj zj{6UxxcZ;>zGUU@x|jmd2~LIa&@;0-J^@I*x~RD1QbIz`@vR#^t%;u1c&~0ETC6@% zBbhjvU-2XJ&iz0l)dlj2%?KR&q{f=(U{gC~%Q0IBiJ;3&Pep%uI}eT8t&@!-Zn-v5 zSQh8`4316R^tC-kkY$ty4(DOPE-?>e#Z!m1sQuMI26(Lx=W zZY$@Qj55MAj~MVGW5@!!BTG*ejo5ZFVIMd4mXvqCsG>hFb`o8m-He70POJr=3qVKx zYa8VN8kM$(Z|_i{qxo}?r;SlP!z6~G64`b(o8%b>6-En1OxH5_-LG3M(iLSk-Aq~=Z3tIX2@wxat2E?g z`M!t@B}=rYMs*eM@`-y}xlOIw&L9#tBx--fWEov;lhYEUm5FI+OH@3?+tYI3n5#td z8=h@=m={bJUiqxV)~G;AZMnBqo#DsM%yDqm+w@~zYG@ccbvo&{bNnRxOENz-qrKWS z<*uXLJ=I(Ip81YNM)y#XW_WIWA~i>|%yef!?4V=EM$q*&DJaW2>!QjYN{|ZNulX2( zhGQcK!qM$VXY#}7r(ECQg>@36aXLU_4Jq28Q8i4H?@!5F9iC{!Et+qQGvgYRbrzZfP7uGBNNwwZVJQt z;Ya;&C^}zxUgq`;P~>W=#18ucR~`zb)mzNp{FckzjCYT(q>#M2oG~^zFmzW!4fmmSlJ>Pge5hXC$rTCC5|W&gcd6&Ny;`PF!_1AA4#dr{w*aBm}ImV zVynae&r;$Whv_Q1J~!o2DYevOSu>fx6~Wq(FIF)5U5W$!4ku>1wj=cy zdF+#iKf=H{Zk27d6bJM0vDG3EPmiMhM(NHb>ti|6ut=*)PXvqIfvH`;ahH7n17dCw zUk1kJ+vg9|iGm=xo4G_$w$;_C($>WDskp!Nf4#Zt^~(AbnPsnv0h@eVA`ton)AzX?P z20uKkguV3IYtFUU+q!dSQ~4`ihpq)-Zy?2dk=o9egwarG_!mjk=>IDp3))|VsNihP zlZuVD?40-LkA8s;lrtiGC|V|&PD7C=Ww_p2qrU?GNM0fUL8w&Dx;P!mSUY9vXj4-X zG$om^gJ)mPN*pX&ks%Jxo+(ddWVQ!Aw2F+z=h(Pd^OE9Hhqzec&M8r2tj`n`x|pfP z=*vV^j}G(qgM#sv1sFyfdYN|`zVlGHU%2oNB!9u5jrNnz|Hw-I>gQS(5A_R@UM|DS8PN^^{k8L)U!j+M?BCK|L z=t`w#f1u6ir=uKP|J1UJl|xhs`+v8Wbq2L!bztI2DLTEtV&GgpSyTA}m`FioapMs| zz8dauQ)K=o&3QY?avE}qxQ82#P%P4N7rR}f5AvcBQ1nGA8OgoGf*xbqg;WNvxf~2^uA^$Rm8gHCuzXvxHN+lL z)EzS~)Oud{L3PXA0`s4uXCKN+w8S)ZlwS-qlNK7h86^YM)tq4gz?BrN%;-OZqnOCx zB}!|@W(BCaGh=_#_2DyGtlHSag_+9|I|n`l#wNG~AhMuYK(2Lv#ORw)cBjJ;FbGuB z`fh(?J<`nUs_hYp!6OLvpkr#eYu~%y$Q(L>L-mN5Mf`z-r`Fhr%?}|u!eF;KbiqU2 zoShEGk+w787@?jCdR!=FdoJ5iplpZnz_Z>Ok_pD>|C_z#R+<%(H+q3;@U?VTXIQ9H zb$~ApZz%qhgNEWVwdghQ7Ikc>oH2T_f+sq9`7-o}V+0;ve~r&Dxh#)n5!hfW?)((W|i2>nZLXjjq-R=9zcwaylmqk?7@7dmC%oXrK{q zd)o=W{!ht+-4^cY_QG;>*wRo}>RqZbmZXy2$61_qVi6Gywwg;>UP69qhUwo6JL#5w zc6$>n9ParwK^eCeC>yiC5g<44lt50y#IzEXzm>qP;N^xW%R&s$M{1j&2E^bEjr8u1 z=y>mYWCj)=-|Bl-Q~#^<73>@{W3dR&3f8c@u2;8)*V9pjho2m zx@LitM#kixfT@p-ePEKbks^ZM)U{6!4*tzwUW}oVr#{PsNnj(rL?L4VhOnynhFwtgc3j z%m+EyKI^b=3+2jGpsc(KIQGs?H|iH5p{UvNZIM?Yl#;D>ZhR^(HcvVhmkSD7uczbQ z{YzUAf1ta&o1L2#e;Xp4uZUJOb^lQY%-qV&+bS28cwv_ z9PZUEiC()hfaj1cvOj6VevH7z{H!~~1Xe@YW}e)T&4m+DDjot(Dn{w zP+>z5DrE+KZ)>6Z`0lB$JDm@Zj`TY2fMx`A7yto{5Q{)~H5>OCML^1bxB!exBnU1B zOsU4CM4ieI%ue|B)b^S&H0QMl0YgcQbn`Lfnd+Ei0h%~43dm8TKWp2+0uH%5ge&Z> zmZ>b0OIJ+95h=X=);se*m6d)6R94lt7Q>XofKxqXibvp-Y0yp36hw=QFMN_4{Uv4e zgk8p1o>;;c;$8#xkzv-0xbp)g9kYh2{MgFq1AJwoAoFPHY*6O_G@)<4oMCM0oNe%@ zrZUx*Z9(osr<@*BXt%r%(aoJkrlRZj4djrCtvVjw6rLpak#UY^u8n<$Cu>6AXf`3; zJJr0-SD;LoKbQs7RxpA~E-h~Fy#Xkko9wd6sS8NQX^1df8+w%qW>HC~(8l*_$K59_ zl#T1DOKs|Uv+HA8uWC? zT-G%B(D(^_g;s}iUW2QgOH)f#6lw2-utD31r4my=IXM)NAOn8bv`%Hot$PsbOu0(1 zI3n1tj-1URT_5Hm%CW1T*S4hXM5b=|GmPxMM0Qb0qMVky(s`4>pHhr^aqX(h(BY9! z?%ERB@+YF2Pq=b$sk&P*sL!v;m&_6s%ek${{Jb3!erEIybPbu>AVdz9Rl6}x|2dGH z>0{&20A`im)Bl-O%#E80f2rnwoHWTPG1VW-(pT9mR)~&6R=r%G%V`SkD*8e!P8E&7 z=Amp&{#j6;mohNXiRsg?i-56G(z@AE(cf~C>cjIQca+fdr9v~x_M)|sBJ5SK%@`E- zrEaHj8uBBo@qwGIx@53>)t2?_zn}s_J+VUf!N#?(YwhC1LXLE+wAPkssQWTFkJ|Ie zAr>xE#8;dau*YRu?z#-YCKwGk4y{s#He|C07bn~NEMRr3C3-1qD3~`dPnEPEDh?}{ zO}+;&z99&G&4xgXs0LZ^!@g2{P!8dHQs+xf#UxlIT=M~ zXCF8Yc5s%Ylkq=Dxs?Uvb$-*y-Fd6J2h0hpLIdjY*+F3Zmdano1;tsffPbPTkoOR+|Yd0}HEihz4D{(V&xIRXf6xN%RvBHln2Ja9;F! z*4OKe%NTF>{((NjLgS>jw&JNIWn10)$%Im>K(TonG^+22W|E|NwMtJqqWu!Tr^!(y z!w|?#&Y&GQcyJJ)vPc+n3j72#;{Czu2NJGrs}lzmTA8pg(F&cig!@RN7To>msK0Sz z9nq%rwC+@3>w1;xMIpRF-I(q94Zm3(R6SmW`eJxwR8;ovMKyni-Fb0I6vVSv5+Sp} z{Ab%pyeJNgw5p$o29O%UfmU->!ZCR5QEo@_)uHBRY$CZ&obfgRWccozc*JkicoQ?1 zl_OTX20y3Lx_AQPa6Q@gapeiqLIYe2gggMSZyYoU5LqS{kn!|OK@7&LVoi+*Wf^`@ zkVh7VNBh(<1NBVaq~x&wW`{VyMlwiP`&whUp?bBiDw>4~W9Pz-^Bs^0YJs zi?w?p;q(4zOxvpZCrdhN5f+;f$YC=|GEx#g^swNa$>&*sR(dqa6uUE>Yyo1k*x{Hy zUE8?!?+xNynV~zErz;l$;oJRG9NmkqfRBUc*mE+IM8gvPAgE?_4(9i6w_ zIyhCzpo1k83lnyX4RLWxqG&!of&H&7Mg-+q)&VI|frQJYKE)JyL7mq0EBhw#Kac7L& znK@z3up?U*l6A)}5OEVNfSpNMjxV?a1g5-4N2mWa0TgTKeT z2a!D_jLJ?`^2wPGbO>_&T|-!sK+{G}2M;D`{0&(e6fkQeYe` zV-98AFdw%^TC`Sy#w9jv3b1UAG{60zI~r4;Ek0zx41k5ZLny>p3n0iF@v}P|rP1rS z^W_R@5@{Q*g(k-qzoIOr2wlU&b2B3xMkYVs1nN>Wf?z~B`K1BC06CNf>6><+FJ!y` zO@O3yvso~_2yd4vvr0_pc+G2&&f_4am}bI6w=GIEZ%sA;XmW@TO=s)R^z@6q_x zQ_-2Xr71*~|4Z!yl+Cvb>$tx3d)^N9oW_)ejW)J$66B&Cc)@2pAq>nWpNnxX=n!jx zhEi3W>L{Tmj*LY*VjGV6p}(ZaXt8lrcns}GgxO>g0+$I)eopq3_WY#y{l7^@OjH4z zB+tu9zHH-MuRh;2>i-}8(?jNv^$Gfn%XHP_+n=jU$jL*- z9C6+xRGrTyb9!9%Pro~j=y1A|=XdYWtyQndC_zl6i)4pB1aV5niA7%e`vyxpqJ*Aq zX1i4A2u&xjJgsSp!)w1p;+{WWyu4C2A;K76v2x+6qP3swyXDy%}a0<2DJiN>eXy=lWlYI=%rvyx7tkOZ|m)N{P~#9 zt)G4Awku( zcAsLV?9%0E#UXze+v~JGc%xuFRPOsEh1G{jUmqMoeYthtxhx^NuKhlt<3!F)ay8{3W{!*F2e5m#>MeIH7wKVnDrmua(>ppyG@qp_qlML$!|BchfS_66 zKR_T4)-{Mse19N-xZ7lN;*1@Mab%EqO_(#^9odeV<1*wJ98uP7u!piib$gfeGEiJI zGE(v+T5|entnv?FL=0$M1KWt>bdr*%r{{s5~Fz&`03C(=*Jn?2)k>C6f@6kk{;-%evk~GLI0bGF&nZit9@fStgYlD5#P(+UjhbUpLK;_ z!1Xt$gsN2?KVJmSfXk=QFGG5oEy(cK+wvVrrI||9nEWK}`B}c7D?`_>CvZl`*}49m z<(7aJmCsQV_kAV$POeVsbSu|Q9MhiSbN6}%yump3cW+a4R`TikqN-#`$~CztVZkT0KH zQ`ODZ{eNYUEHTRXV!hUY-425ckgspb3Nxhn+ZP#mY&=i_)}$shqUnmi)AoiUu1J_q zMUgIxB;x|B*UyK^L7`-kE?u<`#(M-SX3lu#8Xf1T+&!wDPUZBS>#_X73iZxrs{FH} zOW7tVb54JTHu;4M7QS-9nAX(2U30~D740^VesksTSMxHkkY~D;9exepi;4mUva0I^ zkIeiYR|m}%dn>J>I+b(qdt@wH+v0__t&5uj61Nc!Ho0d;P@Q3CFE569R5fY^KXFtu z^?T0C3wpRrNJok~o-c;E-Q~=dU2>NL6Utn&dg&eoBd@`C4~IgFz0|k1%%|sric+>t zDAHYrr&{A~_qA+0kFLZcH1;BekT#8aF(!7tI78B!~k4 z^BUI|erRmxklE)#WZ7{t5JdnCVC>LTnW;NnII*K<#kpT6)2&FiQIZZ^Et&Xh+-juY z`T8Zs&Z4b!K0M!vB7vBf8h9ZQ4cISIEE*h&u+QnlmMB{+r%NZ3aZf!Vs}n!T#dv!YzaQ3T zgJ#dnFo#TTWJ(I*EZl)(u&5&nD0lNdQVD|?$Xy<98+@G$`N~*8BHj0tL=pJya|7**rfqq)3U)7vIwN2s>C=y%yR#O4Y|K>mQRSa z?w?+IMh|MM{J~w{3E1qBPLBu2xx=P8WXQyzvY6NkBrmA2T(NT%fjC-dSkP1Bd-^%W zd@#9sLgNe90t6hvq7rIWb?$r-?93?qlAm|wpWV3A5yJMiL=(2k%;`!rR<4)=fOuy~(vg}yu?oh|AQ=Vw+xPdp5Om&Uxv)h+J&6z_82FBHQ2H)H^5T5R1JqJ)9 zZ}FP0mX@~GTc2ndpY}c}D15iqCA(dyP#Ptn!|w@3BOQ_aI9;?>UM#L|xwEE|?dg~e zJjDBjMc(DW#i6@lPUaUk9gF)*$=-5bEvYwj0N$yY1uLjCt_tjJtE&R@ZEdGc@k4ZC z1fGyU0Qhv-_ngk;`2q6TCbXOX-aG0nuFZB8Jk0K72-aH86$;kc#*8?4CYj3KWIyQs zr)gzEzNQy{Fy|ijX~vul7?t=)RmzdPCh2*h?{V;9t~{*%rfsh4emxltmj^cH96Lrx zr_ML@*9gv71y;ww$?0W04O)hGj|@uU*#&OG-CKALorJgI{ZbfU(ShTxhc=hCH@Mcu zN}+weJA;?!8v5x8_vt3YQ~1)kZjqgh8HFHJrO|C|n6+1`Oed(yYF~&RveZv$Fiz9u zCA)ZzGM#UFsH@=6U!da5#Im`W&H5eue}et%h2d^C9Dv5R$V0-vd%7CGan-0AAQ4)Y zCE#?2&Hpvq?c(uEZ4=kEo516i=qJ%~4^}~O9I)gR?HQVFq|J9<{o{Zj+O6h$5r>Rh zf%ylC3nNpcI*XL)jJe*jyutK$vbc69z1GO#f{AHK$kF3IpCQ8TbStfWHY&(l3cic! zoQODi2*S(3DO4y#=c}L&M-9Zg$*c0!*wek)wt<=a%+EX3#jusm5K#6Rrd;X650eJ2 zIK##b*IyI_QcQyobFCZd|WiPCRVIHw=Jj(AR?kA7U282fVV348%dqLD==PpfTy2_{X*l5 z9`yFp{Hl~3>BARYx65Ha?k8ZBvEXU&>uKKMMk6$#;2QoIk!3kH&)(UWOCufxzmhH; zVEah$wC>pgJvwmvBiNWsUTm6DD;$kgVG_Ob&Wnjo9GinSw*RR?J!t!hpk0kh$5&7nl8so$k3&=a5Fh|b%y*A!TDH%fxE9EY`4be?PU@?*wA^1K%QBy zzE+ffMaEa_6ONY#1l;j*QA$;;OzX-!9q+-z@FBO(u6mQK^z{}gSq0<(ej%Sc^P>4J zi5I;qNmM2cpz7F0w&$7c8D7^sMEs(lCq=oc()g;+u8|jokTRDl{`5OCEHDvkekOk^ z?|0dDY*vt5jQ%3u4{wp;zc6}TZ9QL1#L>I2C#&*5o{d=!e>^(U}pq0_2}R`H$&p=Z*qe2AMz<_DW**BveNB<+$`d zrDDb9NGRUt&BC%Q-@2a9?LXQc?{~pL!lm$4u`E2-fsU_Vp9YeO3WAtBIq)*k@?cPn zdZqYi;h7xmJO<=(X6UAW(47^s`J?7&^}1ZQ&rbMNaO+OL_}h&EFP?^6?9_Nh@E)vE zk2YVPxCfa4bAM$9yt)_bhNE|KA{vmEfJ6nXHqY#_*AjAAu$;ouKtnLqcx90&*dz<_ zBWBV;Svju1>)!S`Rh*+`6ERY%DZgl=Aoyy(Q0vBTrBh{Jz-$aShQdQKa)H;TY2l(A zl;0-D`>Op?-Vlij{SNRWzjlWd8D*B+{_)BC*!~LHN2an-BZ4dI-h?9-W<`-M!G-pX9HJ5Eb)ESyz?GKqR1mNIn#IvWcHrdN8>``YLl z!NZfh?Lm|!k?-F3tQ7ZFVq&>hNCBz6G?q6+$*QKRQ z=fR21sl-@SY&?>Hwd*G5?%X81u-epcpnu~${$>R=d6GXC4rtQlrmoNC(wgndrn3}+ zKua?}xH#s|&Scfyr`J7alvkvl0)zJRgj3CRvg;k5$!7IgwPVsk3Zu7D$ijw7Ij1q8 zfu8+~62Q7ly<)Ukmv;-PBIiVjmS~$13jd!>;$8xd;l4k-P}H0VvT|zfqzAm!9Xwm@ zQB$Xt>si?t;BlDGVv@jfwV?i{LV*~pKql^ZF}p*6O-`%tRthPa=wD1y4%IZxsW;Tt zravL3xIK{ZyT88M->k0A!m^eLKg#T8~P`A>i@~$`hH{7!+}AE@sl8%yI1f2) z4?tM$fN`?B1NO}tkZNGC%r4UXsa1{8xX`;Y?}YNn?&k#_2i=e$qY$telptHHQ<5paaw#?xd7NeTPEVdB}O;HPl9q+KLqm~S^EREL)G zSERh~j)@J`+-lWq6%yCL5?I=$W}_j4S2KEX;UN_%;L?B=3F%n8_i@&&O|J*~4GGWb zWchC1TSQ<9JuPsp^)9bm8f27Je5cEPHhmd?6$89U*JTCXto93JzH#O87mBsW$HU!D zBvaEaxdb5ja$)jJp=?}X$!kRc?Hd@q=89g!7WE@kzxNNq8d4k?j88;R_HZhQ{2;F*}YSkCYQ8!nZqh_%%Vk5)D+C+@GxP4ADrSwb-<6~0Xfx^FFK zDD3;>=YK~KC})QU!eHVXdnc^x9EnmTl9!o-8*?4NBK7Q^x+I1JB|iW@$%Rd%ZY*>l zpob-?k*opx*@xHYKSXI;T@)P$YGBdX(p)q?P7h@*c_zEb_I9Q1y4gj+zF8tIKums} z-vW0VEX7@u8N?fkaw4^YQhv{QIJ(;EyyY@nMMEhk6Xk;y=~ z5Z->VDF6gurX8%961)$%U`(;z$sU;Djh41G5gC0ywHHfWvZK!K+YP+CxUPN=^7|!b z+bb?#P~jZ2(vmaMm_Gokl-VIE1mPPeU>dp>#Su#t{nU;6N*qa@73epW_n!$^~LI z@OwNH(t?e)(ycpc^hm1gvSyMQrdCk^A24h?(uj{%z&4);{}&iZmgwyOfst*@%kEQ1 zwX-`uZngaX%Qn%sIS^R??&&&<6j!CbmF_i-sU!5cII6XSO(f$RSG9AyM zZ#}YhVO?CD3hdQ&O#;tunNJ)(nf?NBce>?mgsh#geaoiv?JVSd6o-#~By zL~2G_dF+Lppx#&2PO+ZQG_wmS7z^}h}m-wRDG<0w1>yt)M-k#>KDh4E2Aa&yqc z{B)BRg$3dHr}m^GohB%|n`6&+5pVclo!2LlD;JJI^ql-0)$RV#`#Pbj>T} zahTS9R}*JcOfK#M46)S_@%W+EI550GCDi#22ZXyydj1Id{P%sA;FUao$Nx1pOC`5^ z<#P4pR%yN3kog&w%ZGisL!$h2{m0Ye3Rwq?UOxR} zzs~a~=%g~Lf{sK&DAQZL=bLD?bf=Ej|u~A@@E)gXgVgpQsv@NfUIL;p4JD{ zjTxuHvgbo&-#O(yhtc=xSS#V#y+~@a-SqUS!Nn-6j2v-9^i6}UoYxHM7RzSZ{Ha`Z z7XOcOFpKl5-V}>`HIV4s$4dE{CfAo)AI{e7l+1X@gYX_zuNDB zgv0bV7}#LFwr^CUBm(?v$UvrVL%KOj~L3g}WZrkGcTE=lJfPDz| zbb6#i;@FetpW#23$_Q|)Gv;w|Z36gTkIRAvPD(B4mY!D?y~FMvROF2|i^)+ufAB+x zE}v(U*T+bJw{n+G;*5ywtm?B-Yo|mZW=to7-FQRQlLEX)=$z%`+`;?C9;v1w^elgh zI=?M~oD3~9ddThC64VVLIQoJgX)d`hf$-qu)~Plxydm@@;Y`$LiSf|`wWPoW?u*}5 za-5IV+PR4zy&Y7-jLV;&vdz^&YwF$QlB}pG9B^>2`}k^Ct75sif^eDMDENePl-qre z(HH5S=j0)1gd;##a%9=JB7P}oK%iZVL1=$A|H-CSG6Y2@tYZM~2Ojgz#Pp_h&UoH; z)&^nH(M$$ZN>iQ_Cw&zCuez9|BSA5-AA)2GLAVLLyelP4I*#(+=LWiyu*XfF(0}r% zCQhRz+N`ynna8WwIT;UNVAI3WQ_KBQFWJFmWJ;)Va%bs4;e6?L!jOKNz!0$}G(2=l zNXt(VcPI!4GPlS13&uYE%sy?HI;%qNoE^G{&aGjM@(bejrk_%sKOzE(@;EOj=TJLk zHlF1!8jH9yW2;;ve}C~^U%V-O(+}mLc+&y1p-^H*`qLPafAWE->}w1sBa@bt1}_yT zp@@4p_I2Dq#%O~w#eXCq;qo*JNZzYp;fSd!zxbCJ*q-bS{2Jpuu!+$jtmtP`889GE@&ut;ma_hEXMym3 zRO+?iKv#Bz0pNl5j2J*D3Iu<(iEPi#2eX%Iop@DZprTpqjslvB2yb9RBEp#g z|L$W9E(&<}zMPE_8+bz|O_}!C$wb_eEI2k#=jH9_On2A%#qe0PCQaWq<}YI#jOdQ% zAMKRS&95{0;WL0Pa4lXV-)C@`8iZ{wE-sR|J!0Cu5JYYXnvBOu#1YVG;C0J>A*)SQ znr}_M!HR11gL0{iiPxz>fmsdDSg(E6sG8<<3Tl&+mJ(V*OoGYmK>CcwXb)7K@dQ*1 zbT8Yl7#A7X*`pm@G%27lD1YzteS7M;gX{TB56SEyHe5rg1zE1cf`5$Nq-=);M1Bf> zk!?*LTzp?+9-KI4e$W$~Vc64#hqdQ)*iyy)zyM4dD=&F)T||{R!-OYO+T;Z4=Ko$6 z8Lf6emzI98U1?7i1|YK!-8f*9_7rU$hoU=_hHXfRBN9O@mcbu$6&W*8?*o*YtHR!d zNQf6r2y09YHz5Xt(JL|<7Fwn z?(>2)Ii8He+b_G+_jXES#4q zJ|&%m(M-)ZIJJ^lRu)zJwC2thF5!Sb-~C}oAXI|=t}m3X512G;^Xp?nm<9EGg4}~1 zYjhPz00+gbpga`mKUw>#3C0F3px-LvSG`tlEPwTFy4V6D~zd z%;WNKV-XsCxKic&;-)(I<=;yP+sZ3uw`V5`R>THdHSanX=fz5_@U{?_-A?Hk8m8_ zrPHBb8pphaB8H{Mkj)_gCjxFExNU0Er3)a+gOHoqP^V{NaRt}$p_V>3Gj$BO z-jIPAFCI``o~1ZCz>v_G6Vveh{Qd0-^MS*1p?$M>jdWz;!QpYw_mv9|+|A6LzFA+O z0Z6g3SN{A220YXv?9GG|ii5WrmGrZ-G$m$a=(aQ2jLC!q;ao)L86_>Z#^OJBTPlQU zAu08uBW=BY{#=W6g{g!c0=r{V)KXFI6W&8yt6^Tg?iG4O#Gn)Z7nw2MY7x`*3^BI) z^hwmlo9ZfvY9MW&fDz&mC_LRI@fLAeScO)@JCr-jn!_IHn_YAAmqvMJ98AKvkxAyC z(6vMkL6-=64(w(b_aBGa_||pTT_-lc^OQQ9_)DZXtHv;{5Hwrk|I}WoTX61MS%Zfw zCkT6~_jRcnTxFK5)YT%*vB;+}P-8zL><^okvi93f+Za)#*{`2`_wd}MnF<|&L9xa* zy~6uoC)^Cu%@mvepYdd(3JR`S!?Af5mx{zASC}SW@Jsom_Ez*S=k1C7kpk`VZp}*( z%0Uib6cISILmJkt-X5VlTiwdeP@=i+jQKC@3y^7Nq5pMi>k~uopp?z|4PwKaDI?ZX+!q22g_I^d;TwQ7%OQ7)qzE3%`);;~JrrQeUR8zqZVgKI zd=LvNGlbB)pQG|jJB%%sX1~MLTjxye2iTrQ*rBdY9iU_ANB>&#fjW7EYO%Mde|5&K zfP?aLWa!H~Y{Iaxe+?EkSl_PS0@sXFWC&0m(Lfu;YO(njAyY{@&e=_h$2EqbyE{~H zFuM8_IQ@j^h*FIhEO*KIhMBe&!X$h3hOM*|NO*y#FTE%Pal>4l%2ZcDglw)NlX>?( z)~gVZpGYiV$OK#Nt4t6Haju8}7C>H(e)Ds89%TB57o9`$T8cF2S(N^^#Tm%CW8Mx4 zcHyF+6EPQfZ>$^)AG4hb`Ihc`b&mdJbM=|n|gphVjlK%zRh=m{I2s(xH_Hr z#&o@^$H54)?XH$xa6NVLuHK$s9UkR}dwnyr;MTiV&tED^a-3YBM@dsRPc&xw2>+*o zuOTH586+o6K91<~kv!G$rrdayy#{%X;XLx;yylIsJp!98BRkXl+i7_+f8ru_xZ9IutWAwN6XX;V?tw=xFO-$(*+)95`ErQJd~s4{|j)FMm%=dpoZW2$lJnr zMu8NlBZOLbOEFy@`+B4?dtZe})WhVu;7}%lETAciNhZ2FoKQbK+t4Q=2a;rQlmyMR zjD2UJZK#BPq-jplQ$%XxN8rx1*rohQ^4G}9xz)NlJ2kVQnbgfSK%DV=^zLTjLF&Wh z3}A#($AdFRjiIP*dQ(WyMlrf#Rd_09@8y2nS9{b&IxtRWG)ACifcQmbRzoCEdj)Kb z9x@b4@hr*2h8Ecq;&Elny=A_lfmb|B&3CA4m zcx8}efM@Fp9wT9s&82%-`Jt1&&jK`-wJk22<;j}c?ywfm4Dtn zTE_*C9W-Z;l~-hk*-kIhyv?Ez{UV-Vzz zh_B)6%`AV9*>bE*_;fc*ZfAl4Iuvfmys)|2CxAW{${StS#lzq?)xYv)GBCoB%KS6s z2`3YiRdvcR_pss8@J0d7m9;Tf0~E|qlHzk|2)yq3Y$K1U#MPqmMS<}}x$Sgvyz>}g_k^OBUE=~(v;_JY)hTz9 zMan0+Uvq1uwEPi~fYkF(m@z<1b}(Ed1CtC!XhZVQ5eOk|1fI0y-2XF3HGYF`HgWM) z28&_ERK3FnKrDt~yZ*G71?+~T`q3U&L(`cm)BB5o4TlkP$1(o(k9HV#f^*3h{j7F8 ziFPL4^N@MSQUU_cGqrRKQ>+R+XHvlzYuP@)7PPn$cE!WtfNEV|^C9fVGch}|gKacg zQZRXQ73ThVg|RfktVcOwE|x4Hq@nnJ;K)4^#`EM32xuWzXa8EKmn6aIpmu8J=F||_ z9rMVYoc!OAq=|Mg6{4ahGATGuUz{*G3j0In7U4n<>QbGTYVrD*D=U{ne#%j+Z3x`i zho0jxIDJnAYK$UTqzw}dPLx>x)617=I$q4XSP=ARvH%#oRp%8ua!W|jT7EM17^b3> zDtkHwK}a*Ho-}iYvg(qwvo7P%Vc%aTwe*Ujd@QxPHysFB&4d16Si#jTSB;*C^^Obg zmV{cp`pjT=fROGoQde92>uq))*lo}lCY1kms;LWTA%;u!;DRzzhT^H+2E1j}jqA`Q zV;&4t%FNKgIMAl!^GsP|Z2I@dH2Bjkw3YIs)~!Y+q%>CZemnR43N=G!)=N@eHv~yI zCd(K`-C_$M&BnZEx|EWGe4c%;a&vFFhOFg5o;Wuwwc`L+TVbD6xp6zMBknB z%2FC~zO~#I&OC_4Ze5c1E9FrRcw$rU&vTs)GGpK7DKXJG&pgd&ZdFTOOcxoPe)wYO z#z0^FKG(koXVO$E#RrGb_Cr(82lPI1bnG|U0YGyBUX|K?iId(nZI%V^&;Sdl+&_wL z1u#!%^2I{P$9SfoU+*d{z7D#C1P33td$#n8EKHI&6NyJm8%z&Qq~6DA&RvyCx@fkK zJD5o#35+tMLuW7h!aTnLw&esPNS1)h!0^X1UtxmJ?4uxkDvCKJW~{5NmM&*xL!`|o!MxJBM+=hunOGv2*b&zY0oR@(ns$NaZDxJiPu$cPF9CBH+N(|)ze*3 zyP0XYkO7g_5OL4>@PzMw5uYNQui0yNSe%2zT~5?`l>TS^-ZS^7$!L(9vLr(ybx|9| zk04!r>g_1uq-Tm|t^Fun11UmXa={zhkZ*}{_ykFft%Z0-n(ki_ zDKY}vfU013-AtVIMSbHqFz~vU^1YI+)w=x?JwASql!-{!`oS1*v!ThF}y%sIBdZE$XL;qLu=LP1v8n7ul*) zt^L$q>+i`kEpOx}7s@vu0(QjmH;wByk8;T1osag}@Mrn{$qaIo;{T4`eA4&oLm%~m zNR(=(qo)McpjuwMlb`i+x<-tWwLHC8piqG{r~!7m>^QX!;bD=WG96S#4pKPa6r?3e z0xG_{t!J55JEmY)#_5ajXqve=!v0cc<|0$%#XDEI3%ddDHw6hago8_?MFQ^T<4|JX z{-K~h%=Dfc*rU(9A+XPKebxmMOttu=pcT~0Y>2m<>N7%~Coq}5RAvJTabY`pN;v^) z!zXscAZDbo=Jd&iuUR-#no0d=P+Jsr5u$3E=|#ikbo`9;xm+>4`&U+}WysZ8U90}V zKHj>QJ*($ASd?eprqjs_p+{jN_kAou-MKgn!YEVN^l5$clqZ;D#0{+_uP_OtFvazNYsfN1+n7IsiAS8Ld!XkP-R(V4MStnsSK0yIiJMDS-=E@Dx5kP1Y;r$8Fk(R}-(E$9n=N#7HcHqDAO>g?T^u zB<8QGbrI^pnwQ``UmQz3bi4XWRx&TI3XBwI>$2-TZCmm_rRFC+wVpWha8RBehaQ0I z7wiAMe!tof{Hj|WY4^sVUGZ*Xqx_J+IH;XZGj5T&W6 zCiHH1rKHw)>74$BS`ux-T3~d7>r&!g#vT1_(iL6CJYGZte4p$|X6D1S$c&@NyOb zwMhS&wJR&gZlu*w4+C5MvxgL?;0Hd?5xPB$zoUH?lzo*YnO>Z^UG7uyE+?CH?wy}L z2WnO0VnWxF$6HsS0o6eXe9hy(7NzUrXmSBIL(!KERj55X_oc5Yn*`k6q)*?wvz*4la7vp0~!D1!p>cQn=B_!m`2?LD`yo5wF(*w>Kz|~_ki?Ya)o%i${4BC+wUC!A6 zsWw<=&vfDE9vF!+j=!};-H z^+lj$38pGm4U;~&2fWXRJBS@Hbn7N#*X9Y!TI?4Izdz&w4p%zfRtgY zl<%%kL1K$6Fg624%3T;aKP>HbB~4v26!tYGHndq>$FUg)LVjT6B4MS#20?gOIq`dN z%G_bEVG|v&)ZL)s5qwu-ZX+=;wSe4K&6wi2ii@jvIN9?I!jItQtCIf z3;&@3923;U-w7lQE@&7&uw5!ljdhYXoYj5zSh2K7^KidlcK-bitLOT!D+^o_o;OUHymprVoj0Xkln)j1Vu_`Fuou*cX{u ziLz%4rZ0GgBouQJMx!u+&bkS8m+|OW9gX#0+J5^3Z~*r17=bxxB%zW5j!N+-$v7C6 zJ@6$FPAIFRaBMPVE?piW@+tIN66aa9z5@T*E)bz zc}|ZEhrYg2)uY(CEE_^ePuKze{)a);_3?mw7vO>!<<;#$ zKg_xg)8DyL#(eQj=2Aw`Jk!-k>$lNvP!+I(o1F}X&=%G_Z821ToH zbxK#kXVAJQ^&x>2jw3_sfUv>9W=yP`Sm7JOA{tF|CAOo`XKtDwH^(m>E~a$L>Om|5xt26rTz5K?Zp zJ$U^hMc2#>a87dyvI(jb2lJ6i%sg$D2%QPqsRr~u2;3vBrTgr2xVEYE6dS1uw zl^Gz2Hs~z|BIHsAolmtpZ{>=Y_8qHA#sL>WXx)#31KbS|MahS~t;z#qFwuDrzFt@z zG9c%1IpL+%(4-R*F+|VWb`Sri0M1Ff=om8CD!l;BGUBtm+*0P`U9s`A&UR*vcJwYa zBkXRdSrI>bs9cIbLqv9mXQg+UzNUi_O&0%UJmiULwZIoYS1zF~*d+#Q|t$GV`H&(&vkU<7sF)Inq`dE$*R6Rs2SY&EUqVni%CMlhM>Njl^Q(l&em z`6}t~D1PgqL?NUbB$kn&=K6(cFC>kaueP}`y6+3AV4kPhrAizbiaZ~(BtBQo>F3Kprj<|x#N5m%=mYvvZy=nfxdk5Bs`dHz^ z$UJXmahp23E8-K=>59d(VmRw*6QNzmax!;}<->;I@@c^RXCUl>0j}M`YA9_P6iS8} z`)3REP8Z6z6!g$8d6lFbga;T88tNTeE0f>L-&k5cMh%Vn;RxjPgYR-ajej{ zjAQ-}vNN9eD#dL$P}BEA?P(hS$rTehc(mQ^Dm`A1SS(F=vJW)fhog~{Tr@E`Af~nR zkmE1Ji9E7U8XQzx#966X;CWy>HYOLNe`4bfp$|Y>X;}LFiy6`KTU6c1^sm`Jp&_t& z6|UbS`u_5i?q1y$SnV}gcIfVaWlIwqLO>LnS6h=Auby_>&qGdil!1`WJGdKnEKE$T zQHH;ES+TpmSK`z15(qj-6BepKOr=w{*L84lS5xIs3XGY<%bmP2c)pvK87-ubqv22y z5skN3loz3)up2FZkgh2Lv(h(1ukK5U`Dv`zTZg{JnNdZpMpC@f0mr0!E+virz=*4v z(P(Ds98`aRDEcEvuQIOF{lp5>I{@kaJ;A5y%lK6Mk*FoNncrf+bbd>o0mv{LOH8gE zeB#kNox+p6`if*7Z7Op`KS!TO8C?5D$*B>&bTtVyv68S@W)5P@EfHWffb+Ktm~E+q z5_^-`TUQBfhrC$96$@U%wv|D~>)!&H0DuVT&|9|yV-dH*mCs*w8ceU9^{dCVNZQB8 zBSZcd4F+=#@|Oh?I$X4>EH+dpLGh@$EV7CS{&O^Pf_UFs@zt`N~4 z24f*71a7;lo_(;i+9MsyrnEyc zN>}c$H%H!-`U(!Efg~=9| zi7{~R_7as-W?CcL@_2zPckz_Wn59Pj8qL>l_?x`txy5RCStDr3%03TES#4{1h^kLD?A&z_t!r z1>L&>vC?kkp+wF0sXI~a+O3R$jn7W2&smR@q17L~O8fg)rS}YS;d4wXKYxjWUc;s6 z$3RHJe7ryJ?atbc?rpZ82g|2>OV;TzJ|)ymLto zwmf=g6@@6q7JPPeObjhv_9=z{OGvL{AaI5*zqA##^~Uh+>is&7$G!O7RMyqwo$ZN< zu0>ZdrON`aiSK1tKF+r_cSh?s$*lgRN^>-PD-nhW;9CZhjdR<#%t`55gzDV${JAoDnae83%`p}V&?2P_Oc+6KY?q~a@y-Gl=u0e8{+wn+m#ED&cvLiFG7`FPVSnVj_}wMntwdq5F#|71 zEMVsP)&P42>HHb-oY2tJ4MMz+GNq=8v;c06e^}5b$6| z`O*WxCSGK0FlFHHlbFMIS-6UfINRBNuS5bdpM=)B-;{@CX*|`6JGE=eOg>c2rT=`c|DH32a|;=)y}O3i~01Y%LuyZtcU;ZT)P13DVP#k*B4=< zfVqhcv$kL5#=yoG5>;)tE=AgQmU>hmB3=kS*yU238H5A0JQDJ-;$`~lzsE0(rz~$H zv{+K{XL>Ge(HadmhSy%R`yB3t^_A|Qdr`b zpZJYQxwSCwhl^e)oeVWuncTpg>$mJB;et7>JcA0{HF3j|2F2lsJK#b-(X*tODmGG9 z!d65tySWa9*wm4Yk{GOPrXUR1P}K$>a-keyJNNV|eY;Sndad~u-`TL`wp05bmm$mj zHDQ>=?5}u|4r?jeMSIU?OHHrkVL6g49jq4AbFvT=Mo_CV|f z8$OqQ=NyJ7+!L`S5J1eMMM^FLI<9+Z(2yJLJo@Hu05QoGgFf5o=EgvS#QpT?Dk@s? zCOTq##f(xK$W)~ZRnGhKi71I*-m;m4{NEw4^Ib*TV>MP*@N zw(SYEtW{r3CpS>wF7n|vQGQEKTL<6KozwHT-^)!Kmc?qfe}LNCgXCtD+9XXy1MGDXym`G7tXrBtv`a@hk?!@1@HS@PV43GyMDq{tKfy9k%#O^%b-X~W?usZxTHl?3ehT9t< zZ=ylA0JP*dJR49;B3nx~E9Qa(9@r?D_SoX}m+O+f?wav9Qj$ZgHE#T`TR|l{~F=R6`V}r}{X*4h${$yknzrxDfkR-4Js;&uI=lk8Y6_)kMe?&%7Tzxj9>k~ZM-@ixGYf7JcW8a z@BW5py%`|)IVhCHzWPDUXc=A(lq1`x$G_kI6!6Iy-itld!wRrSLMma2iC+S z^Z_|e^Sy3vNyl8TJ7n?2i)KjaYai-fa zBv#w)NWB|A3IKC1c4LtWR>q$Rw+#aF;=MYbY7pNjEG~(=>@U{@*t46q1o5RRdKpiB zVg4bZ_Q$R65`wVIcBVH)D2~Z|8i8k7BmWw1L!TSO{ z>epA#_hS72FQ3ct;X?YYBnXUUM;XGG4}0uyJ)jAieGC1L0AnCn8=#3a%hmz48!U0z zD`*^9eL50Q_Sr_m3CAC9QP&vaejnWH20%Nn9DhA?jZ14JB(8r%PIMl;9!j7?6VPc? z?R?wz;4(3NaOCxH7oHM{i*z#D^>qpj^Zd+5Ik~s@H^4__2aJu3@$FvUg0mfhfWLqp zeb2Bc%+IpF@!M7EcG1>X#M~JR`ABNpw$)33=fbKE1M8Jg{yRF8fOh`wk0 z`n><$yw~OnZyy$as{9{%C%v-HZp3v%vLC+UV83IyADu=y!jdPGdY<#S-{( zK$*F%AxjzgE~hF=y6iXEUekdlDIkIJ-FF#q)5$unz^@|!(ZUhX%k<7&A?(&I1DuzzV^~+ZH9b z(z=K3CoR+aEkd!E2uaTte&E~=oX$3Ll{<_`j)Y@3AS@8(*8f{&z-4@OdAh^syO+FK zzbFg*$5v_^IS_ZJUi5k=8`ssc$NJUX_xaMCV0YOjxble@3pPPSCgx{}S$!FDxj$ks z6dJC>7z$f>fMxy~S|cOiasrUqYD;}7i-YUDcv@G>tUU+UZtgESh`v`ZEu*2~&Q=4V z>t$_T0>L*XOL0hi+&de_f&{C#BlfL#Ps$icpQ?yS!(J}#biIzGZyaB0jb-3vY8dIP ziK#xzt2uBYmORxj-OQNrXVP7$2@+KF?|E$swD!+FudX^W@%TL!e57d%zAI==TTz^? zp5>5*Y$=BN@1mv$p-um3QQ((hv76?xJTRa~U>JrhcM!cSgY@&_V$RIX4>L(zMB|Ml zSgx*T-N7ZS9{6999SooofUFBloPdqwlZb&n1V;Ivl^@;+_*B7+(uF_Li_rspSUcDW zB&TP&liXV--_&bgS~)>+!*p*Zb3avM3Z@^twWLtn_+m0V(q(7H&w5U{^f$k^Cp2{a zzb9|9_ICv1J{Vu;2UQoNitwcI-*8_cmkH&Lw^U{4wtnNg@$OdvEU&x&5OHE3udC9S z|4n^zK|~|^V7KW&(1`>XHy}p-sNEa^|MEnORT%h!hO4slx4zz5*gJk3v^+^h#lq~% z1S>6lwkx9F=>T11ZDDd|vrnqP(@ayd-63uzf;@pvufStwz~la=J6Ufa-5*OYJL8Cf zdzyia{&Rq!HQ@aPTvMU zM&71Cf;6<_Fy?|93qZ~FIaeZ1E@P|m&dyPM?ISouS7rdvc|=g5D`u(5Uai7U zPtM>>0{WfZ-mtr&tSjYX;WRP;2AUw13@Ja|xx)opKVgw~C}VKi%Ci-~6ap^rl{+Du z5s*%6xt%o}s$upIyD3%udbu)Z^eC+%UK!hr`QY^4_%MfoJy#s{gVk0`6`R#asP5^* zZqUv=54J7?7GX4WfWdWJS$8oh1C;&CJ)T))K_V9vOxS*U~RitQe%nl zw0V3!Lc+odPvZh9%=NJWm>J&9j~@C?xORrq^rl-HOQTpg-% z*QBfa@Mf2GfwP(mwP<_f8*w06EUqERN_Kv+Ws0jMw7W`2_qjn^pQ!J3Rg;233=BSA}LsPF`|$9d)}ra!?|1yZ@Gq1$r;t zHv?`v?T0w%nr}ff(d!uW9Lv}ox4aP9te^1vs+Lg;Snx9BWaEaVWOX^@@}Z9)0)&7j zX@yf;R!Rm1kCJsO7O&B0%%v=dAs*jqy}Jh}0rR4{ziN`wZ1fk9ux!n}Wd9^1B>{y%hI*Ci5vWNWA=J zdd(y*)p0rHQJBoRgm2pnobKb(JRJu_Nsd6c{cREA^_>053Vt1^(!9#eP|*$6=Ywaf z%ykj&$!SV~R}{s74ISM^Fpdl~WeQrwubGe*GVtk(jf4%UQteqY-%R{T*b;+^!?4=2 z=>2%brn~hW8U_7VFE2Am%anoS^T*eBC?gq1_Pj38)}Hx%oVi|jb=wkO;d020m)XD5 zpznR%GYb@O&^M;#iasdJ_%juSf`e76W7)HA zmovLcVCMYa3IP)qJF87yoiC7mqYy*^bxn$;pU`b$Ee8St541?SH7s%~% zDhCS`X>xeQEEz-9FnjB1v$^XL`72K--G#qALd#{+W*-E; z@c%5!FnkNhh5BA3nTLyEbCDSVU4c+wo#3(yrL(sSQl6OHodz(J z!cS+YxFVct_&~JhO=phq#K$UP^~$L_RF)I|7HS9TVfQcMEZikO44UG@!EV8p2??_k z7*HmIKIeR@87Tvcog};(*eZ&v^}yA9vpHLtaEk&G7+}-R{z>d)R&oK@{tXJ!zZ834 z$u+G%Me|Kvy!kg4_AIvPXxa@GnN8M6RJ_ZjvF;WPXyMLMT5!gD>nm} zPJ&&2kLZSh0#qG z_OT%I`0da9nxS{53=YP0ithdjU``GO+D`Q2kQ!_Ig^BR%IoX8G|pZ zzQ14Ms%=!O2T*^Esf&?9DX`b2)+%KCbOnLVltA@rb2&_%b^*kYjcf?_<5dU?DZ8#tF?VY@@q>K#4`nux@ioVT%Sxp4kjCS*~byNTR&$;y~`9-Wt0UtH! zuI=oypWosr@#`eU2tB@^2{>BS{_o5WYf8Ivtwh}&8XT%+Ne$HjoanZE;FsQf)HmCasGrRBe*?A*@1o}(+&FH;V`e`6&Ik<4>nrQFo? z=)qYwaV6l%8;@mdPJ%d}XyKeJX{@;ex?i?l8iFT(smx*3esab{cIR$)OrP0wAN%kC zn$1xIyUR`wx~I0H3s+PH7zAoNp%`#PE>X%yz^QXwuhc;GoagD4&bXZQ6HseJzzZmX zl~QC-xC#xtkZJEi;1D`&>K@J{o@|{39D(khZGv_3ZbbT}8?Ow1y(@OoZSkXIW{?=y zMQfbFF3Obyo1mnr&sBJ)q405#`*N9B$;N!I!+Z;QC_um9Q;yC$G}Nb#@}`bH>zY%2 z;4~#3k_FXqL;_5hly-SEH*=T`#H$zz2UFJRuT^v5yB)n#z<5k&Kt9PR6UVylyvR$7RlLfHwWI zOM#zPIZ`XAk1OJ2urdNL>!!Bf^V1bjvhaT6OG7(-Ys3ILd%?uP;lObU{;;lyg`4q% zgK>JbKJq^3Cmun}W=1Sne@dwJAl4TF+p~8*Ho@bNqpVb>RTc zN+KQC!P$2*+#MwpfABorLaH&jYJX3$ZmqQpB3emDliA0L>IP4C7MT^n3@i@T$+bxL zG&+I)(UapZX_5afdDcLo_Dy+j|K7}d$Qrhq=I0JnE$uYya;iW!hH+^gt1J zz1#0lZysgSHqbut|9C5@C%!(Y|^(`-N` z5~PDAd)A9@qOCx;JILloaWza-W?>#^9o=%Z)^V%PNNNA4cNHh zy-EUy@pfCA4)u(g4{Y|nK-T+OqV+OPoj=dx@;}T?JuK}1c(`4chSF)75Xscdvn~&y z8tnDN!@K`cP(Ik~ng{3jJ@Ee607!fAY!5hD%~cMi5w;x`-w;i?RPeEWMmasDTYOSY@;Z-ugII#scmum@SDyYW**bQzYM9_3g;x8)Ry#TXjiuio|Z6_&0=HV)+n|G}DS|!Sf!+(KCipiyYd6y8`LK&Gd#i-3IIB7Wt*U>}4f6G`#$meqQWG z>Js7FdFWHB8?T-or%U9DpW-DqThj&lTr8gaC9i8aLtsbT2Qt|6%44r1xzIW#(B&QR?;GYsBPkk+t6M>Njj# zN@rM+OQJQ^QN%Ve1ZB2)q~6Hsfqf3o?}Lf@Hul6h7&PzaTWqvjBTrs7Ab^S$n0G;~ zq`_`emppNBluH(9$iD1Ja0&M3^gmSDHMBIJ3*z9`#6@1riPHbyb<$#Ax+xtqD_`8E z*&ph%!xUw|iW;+&$=M(Cb<96csl{ZmEKaVC_1qtDPtuzi;3BGE(zE|!WB)R9l%s>1 z{lV4D@sv~}1eTLNZf#2^=vsnh2ic&bkhA)vEZ24i;hcD-f!Xdf*n$9QDLK3VQVVv& zWxY!{D9?#Jz1UnOsyTcD5$nv1O+>yevG-`ciyA(r`?n+Y=ldg?@DU7k$(b$Ai5mk* z*EVu%<1IL>6n~od^Z-VnJSZgw6YhLN=(yg?=!R+b$HQDafw0SAuX!t2jur&oY*SF- ztk6;anbT$wA{)Y8#N(v~>>C3?u?J@NyL68T!S6pfoTMi4)ON!;ni3CM8PR zj5mqf5OOn?=f-2r85i<*`Ss@Qn>Ugof-1#vpJg)X92<%QRkZ&_GG(Xz?$YLRZ1C%; z_2W8$(>($)V|fq}>`Nn@Pv_h;a$(N^GW8muj?k4{?j@FcX+_~XG2oncrnr`n*PBz`MqSMj%o z)SwN=-ROCId;g9{i4)ASHn9$FyPjnj)N3yui;@fJY~SH*7zW${fuB`>O_qYh;llmy z<;~6H*w|-7Lz4ILspEm%ywsJn#Z+k|9AlEI*A(8kVzBQit{{aLs>Ygz&iWPZnRnG=-C1aJ^LB*jNgwnd zKe-@GOfgG%FTM%fwtfT9Y8#|v_LO3_Lpz%%LM*G-|Oon({c+JJrI9H#HqFMKH0ht`ec(62qc|Ts?5+=hGVz!NjD_HV4Y{#Rbk{zUK+w zq2wV=m>7^7!Kf{_zslfX6eU9o6{-7~U0HY+?)Vk46}{hBiE#DD(CR9GFZ>DCMgNhx z2$ZMJLl9QXU~aKIEX9)i;DZ_N-6FJ!)i50CmcQD-+GkgM0t}TI9nbN>_6`aeQ`$xL z9>xK@A?=wiJF@(r-r_~>JE7a~J}<6t>Yyq59-Y1EDf`>t>}2ZJS0bQywIi$hnO7(< zS&l*weI!N7N`6}@zyW?OEm0(2PPs&Xsh0T|E73O;^{b&efa4}PUVmYPlBn+^*_Ry? zer|D0ypCqhN&dcy9iJqq#!V(wRV=LS;j^XpK|#ItX$EHsFEM@sElH#0D}9tF(xlV_ zyOjq+xeaC*(9q<}E2Z^3dP_f-Sy@I_vOgq!{}*!Znp5nU(&NMTK0NUw2c=q|=jKuN zPbBghYH2$dgnY-T5D^l=d}on-XEN(Q4s&0s#}@d62B!ob91bexp%UP5{PY+gALP_H z-+MIuQqtkFz`@2|1E7DL0A~*sG0LF<`%lC)t+xW1s^0xPmYb?WD0lBhr_l z2iNAmP9PobGFWFfO$Ve9*XOb1A&7^yN+GPxYPQj2BS z5N}oLkQ8)Q2TN7Q>**%W>)zKQ{hOT zpyE6+GY0+HxSle4C0WkHVU6wGdQYpO!+sMgWM9;2ULFuUv5gxeL7(-kD7C&c30r9r z3`ZfJQJH@2cUI`rAjrxftI=fvQSJTa6$qm#FZhe+_7 zuP0e}440SfEZA52FPCgRt|8!^2f8O*+L^Pfp>an~8hObrCr`{;K6&3TY&WLqi}^Gh zji;Dt^H9H_q*VcBMb^*1#)$@=Wj~XS4YZoXIdvCCV*O2X(O~%rI^W(p*tF7oS} z1J+SVwbX+xS0!Grfo%7EBK({Z#}rk~^*R&GUPA@yZ7&OP8ebpM%(gb~sQi=BkAFRn zr7x$XxNaDtKXw3ms=w)vCh>YRO-Ma0@eM;SF7*XD6IqUVX~tExKSXuqH&*ZZ*Y&#S z98Q}|WD&O6mht&j2fba%>GzG6ORJUJ56V}*s}OJ68L&QFCr^%Z;?OnLbFbw&?&QBX zA`cX)Ol8b+GxePPV8BqKj^!`yx;KX%H^2Rr{jQ{mboF81RL`v_rbWDnOMRxDl2C%u zg2t*TMuo&6wCsbcIC;JnbjXbZF}p)$OpjL}8Jl3!T-TVMkhi%rCa+Da`te0yU9Rnd+aSnz>pXlE94Co56Z_Mr zmM-fRQR8xG+DReFu(ON``X@Ej<++iio~mkA0Yk88CS~ zORU;TtgRxU-}-Yi&1JkM;Y^8}2oWhI*rQ_i?^i+<`AR18z+&Mc(YAD^M*DoWnx02l zO6KDp)j^V|-HUE$ftiK~>ehZpkyQI$?c1d(DPAY6Q3GDZxuG;@TA1tE^Hg1&ulQv; zXD-x&C;&|os6s-_FqUDE6By*fcg2?jX5gFqxrV}qZ@4L^)BTBl%Y@|!^@NQ3@8a)9 zNt2^BFSEHdS@xwbknpmYHWrjL(zJ!Dh8@xZVM3Gch-+Ips{Bo$cDfVkc5+>o(tu>W zSh(lbRAph~&hsMsm!XpV+!o)6-r4T#AHDtrMZ+U2&0@HXVsj0=ai@j9?p<6SMApFv z;*&H`*i#;luD!I@1f;+)BK<7bhF|pxFv>qbgzQG`Yy!)qWGU zXK_r)JQGdiy-DbEE^t#xM*QtN6_FQT2A5kSVbjyVsGp};B!2PX=X^yYtS{EZtD=KS z`1wLTdM%-oh%I!|h&#bAt%23w-ymg{?xwZP$=_jqsIUKnS&V$qK?75~kUB6{AGoea zdV*iL5gC9;Xar&B|= zi&Zm%{pIF{BXwz^MPjms-#N6aNatfPLKb|kV0t7Ao2@%V2fruA?c2l|d6nJqbO;}W zG!?ybrhmur&k4S$!R&kbfE;_?`^`P>3(n9YX3gS5eobl1vY)|f;;X3ZB>xMT0Z`EO zX8~ol+ZROoe#;D}X>A#6i!Tpvk90dZ9=_I*Q;L%p!oF3RzF}fAuAlEk4HY37C$Q+S z$N^zB1ciWM=#q-baa?a?E1um^CS8DUqnd@gJAL`ny4iE42yKR@5+w?9o-qQmw=*l5BUQE^ z9LUOIr}whF48`};AuQ9D<#bP|8f3i-(x<5KF+@BX>}-YJcn28ObJNUMlKpGkxd#z4 zC^FfX(2>oc#-6<_H1pX@!1d&o9+~eM3%BXMRO@u@A9LNWD>Wsx#ejK3a-*cg-B@Do zeQoGcT%Xl2vEJcBu0;u@0!mo0#>g>?sP6Q9+(N9Ep0|iGD39XuZ>}_{5C%Bu-gY>zWz{#HQ zcR%|~E&NJYXI9|&G;&T59pfF@U;#foF4+I4nCY6RD6166;c<4JyfLtc&{bRz9siUE z{_&^a)`os7Aq)5A%aV|q1rsd5Jg=~m5`VjiQmJ@RA?Rmr#ZtXQ#2Gqdw4@wc4(;LR zJ1~5*Ya6(UsnTjsa`U}Ts&iCZ7@a^N*b9Bz736s~@Y7HZ^OLgLd(umJt1axLiLuvbhfpf{;z4>1xQfR2@;F-(LU`i z-b6-R^z>`ttHKfL5QN9ypN~V-u~zsilA(E%)pHizbx^9GKfN@=6ER}BoKUY1u6l%L z7q$;(&x3#_RG45-Q+8%b^k04AT5xfJrEFuD;>>gIFnc;x`l+Xf9%Q2sJ+iav&g99G zl86_%TgLR_`o6Iyf0$fEi#G~W=o%eY+o<7P*~_8?N!CdaT{CMbnZR<oAz;s&Nhz2v6ycMR8kHmzOnXym6&m z2u2`-_CR3?-&etcCfDA0_jP|(d5q=TM;J~nn!BlhRIe-LB2XtiJ_k;|en;q_lp-QT zUo7~+y_sU6Zv28QSBvnacA@lE!{Y*yoIto)ccEu}f#L9TbJ+*zn)J`&m=2+k;5}V` zs9`avs-maI-i8?3pZbFtflXgUSTZ%qGho>Sf4hXGZ+Ntmd2wai+zX{Hwb@JHV&y9nEe!zgx@|0YUF_ zTtQ_fsz*}P?cb92D1X=^ukP*C$fwtn*VgK6pHDf;vt)R2v_Z5<|hy=IuwnLj7-8OPF88dAjZAe(09@hC=5+qth zU6|>M@~{+spDK*p2p#A5dMQeCH`2!mmY-Fg9vjTLp=)2AO*C`G0%;llh(*}og695_ z&~QksaHO|Lk+sTJrosF`;@4&8YJ{k9CML1f6j%W)=p@K`^nW`c!wjc_vRHd>2{F`N zQUC1?wNJPp?7+I1e$W2dop(5Ir$}243$ck_3o?9o|IfPKjJ@(x4woW`iK;}knMGj! zs4iMz>imf|S=^4MEVivBC4AnBoRuwwk+0>wt1D&eO@5s@w>Mmgir!KJ&iA6KAB{;qGYp9OU6b??`?Z2_2c94?K|8|7dNW;(47#&o zh7im1>4Xlt^pABc|5Xx1Tp-ug)sF8ULD(*P;TD$jK^NUV;%#J&9JVw%p3}dDHxV_( zZU`LS+Ty6VD9ugt#(zyOmjwY+)!dwjgojn-@xcwr-@C@k&=bzr^8kOe#W70$NJf}> zREj}9gY_pNu9oFxL~74?0RavNUIn%7N@i~o8#9KglifdKdgPU=t-K5)=J`VxT#u^+ zXM_ojRcRx8JZt54Lp2W=WUxoqFla_u-HfedHifZNjanlEb)YrA2K0IyN-ZHXOe--L zEU+{Pj(B!WsE*}m*t_ql+OprJst7rJ<6*ipy#!ZjzYNkA5ja%6X@Q(vMdOVHcT1g` z7$53@%n;bgiNNiv;*5MY_;R!AWpHKcbFRNie1@+7d3Q&qUaoWBjuD>$<`!-NdW@?O z#?E;yV?~jd@6*3tnZqHNZu=nmnG5nn2|GpE5d&T#Can^eurO^dkL;jLN{hXJ_|K=7 z>&IRDn6brrnB5aY{S8^b#P+x~3r$^e*wwGt-{$Q@fHx~s`+e3GX}#cL7t8k^wRDzw zW=%~=VI>NrHd%hhRjrZW_Gi%$cQ#`5|2SkxJQ~STz)@LN9{PKnUu4Lhc(9?75DBX; z4s&xb4Dv<${-RmW@GliwD1W6FIDtLM>~Y$2L#z7ygZld1o#W};KiyfHl&o| zAry+X{`Sm zJDAIJgHU~@er}xpisY9^*GSwwd^QL5YQ~n%&AD7Ogb%bgCPC|m<)`6_Is^$$h`0rG zUw7t0wd8iDn7Qu_et(rHhqlb4!9?E_u!65$gj%`#by@jGbQvm~Hw@1M_GWs8d3_^f zMZ{WJ0Ayv13;g_evF(Hy33Zdx`MslqCb4pE-gIhsCtK`mn>$@$xAQN{WH1nv0}K5{ zd#2t}D21pi;cf%k0oY7oBH7WOLPa{xFBOuy9xl!ocW>A1F!f*BJ*_mc21$98>>ZlD zIU49cBr3`E#C??eX`NeT1}Si|Xhc=@S~A#piz;7WB@eBOrvDSJF!;&qp^o;lpxrS@ zlyLrUS@Pl!WMuU9wwoMZkqfV6xI0ACyp)Y9k#xM!t}c!{9~l~~_Ke6yo%%Va?pW6k z6I6~z1bFMNuUXkfAqziIFPBMGK+Ukg9U=ljn;djDHu6cxR1tB9yT;txY3O_K%wE{6 za#13gNg(SV4pfw#zw>!M?A;HW9vSQD`Bgt6D}3+^4nNZ*0&`3^1I!_pUgtV1BAJ*+ z6*v8NtQGEFc-st88kJxWE@YJjYYq7T(54eB`43##WTA*~A?d zgHsFb>JoiAD1e_@s`c2>R$|t<|1TWtAR_haA>sOSq9VMkBB(Wj=^nsZkWZ`Us zq_>j-@>Mr>UIW;Jy1u-`Q4_*9jt`pDde03Wv&YI(T^s41(gid~O{JR)j zIJE=h$>pFw)gao3iI zM*s>8rjl*KMh4A)zc!-rw;kSgk6YM_?3Tqz9?dF!FHidvl(5gPJLUSfOI|01%QTc{ z&+MEO{r%{Fp%)Tl+K`1Fjh;|6E0;@%zJQxvM(ypR?CJcEj35RgRh|GHYs=GHm0!?~ zEmIt#oHzn=x3_;oX+qc4O4TQB%0#wkt5_YcJxw51VfF?Y+v%YSd*Q9;jyumbt^gd? z&>S?}$CQ$E1hmEk?l8ek&;k_sS{)~7HPP?4{@W|w5s6^OzUmuhk+8gYR46yVW}VT_$mzUwfdiV zqgUD)R5|_Y4Z~V>N1{c*EjJgL*$I!qVeLaaX3Jl7v5K&-A)QC)NN|``9XAzlg(_o( zXS(S`VBG&hx=0#)B&fDa?5t=c;n(YxN3E$!1L-{uXpdLphOUPLDULJh`7Uw*{+om~ z1p3$lr$5Z)gHg;A*p4EN&OXN4z1n!}_Kj*L!Km!+f#v|GI;@X17#`vz{)4Lp^^Yh( z{m+H1G4Qi0$xYVXRh>)1tq&k?tq3j3a(uBweF#%rMSGpyZJb?W7!x!?Xv)fU{rZg) zxv`NM{uip)GHu0=z+TzCYWO^Dx=;ieV$Z(@_6_G~-$s--{bqaJg4tOVd129MBTLPk z1}ot%1)l3x8g8YKn+bts?0jCG+pP8KThEL#1eUAIOcZ#`15EOA#yV z)M*xHy0an%EfxCb>zP9kN2<#nBzROE;6Du@33i`*e{!#Xx5{w zmY0sSrRCWEicnB{6> zOQpwM!)q^V;Jxyv>nGUp0!!M|5BikTH3l0FDbk*1e`q)#;Pj4yE7vH4f#GQ{jkyj% zhaoayJ5!O-vt6BB|NW(}vw8VVxBy~_)Q-0pKph@!82U7XMlE~}F3xWkkEXc2*HNoN z1dj^ilC0zTUP11=A?{@sJrd|B%?Y8^HjK1d5e%yWh6~8p z)Xpi}@U@Hx!pm^0b0btU+|E8dIo98S>+MIB?hS>9EG!QxG_r#tx#~;$%c<=$fw~IgWWhZ~_s~I9%aA@ubA=P*2 zz|-jp7Gk*HLcYW1!gR4~`x`&~r8*n^sVHeoc2N-ZknpxV<>++3JHs@NvQA9%c%^4Y zW$n1Ll0Z!?mkRH0{G6m&P<*(*!r@ctEk|M5+Gf)(pZnSG6eJ4!TnvbgBt=;tzdgF5 z6z~ZdO}`Tgi5rCIsaK%Y$j{I8pZko6161Ny!(gVk+dlHSZOpVu_Gon5nnKP780B{& zkm2gt>=X*>|FIZis-mKPZySb1T4DF#bR_Qlhy0KD!}&+qcPikU8ONa!J>898UGD$x zBJOnIE%&@@h+k&!1S!p%;8}DbTy*&KMYP!E3EHO z-{SBXn?n_=KGo<6>!g*H)8`??e(4EP8Ij@U^Di%zMoj7##2Q3?>@V6|`>a76ZYuGu zib-=AO#fS`wbpBn@Zrnx_VOc^q))nJ16+P!*WNrT?y;Kc^YliwwGAbR7oD%5i-SIv zY&Z>~bbnv28fT1!aGihF%5_3m@FQW+&z)M|@k($a>K z(kP*Any8=v{b;irf}t?!%e4{O3LaK5D_0uT+mm#&wr>9ZCu$=4LiQNZoUX5qvZ~YF z4lNCdO%tpd^YR^t9v(iD)I{_39Iw5n!=^+7OC`kI-RMOLIf-1=IOON8y8j6BBN>_g z*_{jQpV_TA58EG%5yLD}a%Gp6&1XPixn{r`Td-)$=*;DK`cL7)(Rh%*tI5!VL*YTWEIu6~N+r?#YzB!3eUL;R!|% z=PRKv+{|_1(x=zSyL*Rt{B-fwH-7BLt%k4~!BvOt(<*MVZ*{fB`QY80YslW}phJc! zIYgo!2aYOC|1hm1_v9_X;Z_Gf#hw3sUhsD(HxG{2ymYQR&u{>AnzBQ%X)1=V>=x3= zCs!9@vfkd_^xepErJy>=XsJ(EOw=Y3dN?1geK+q>5od#n+eHsgOw{K+ajfyBDTUHx zU-%&ZmrGw;#T?=;>w>AhnAjqReU@J~x$zGZ?35OXgFkHpU{O;?9j*Wv?ao|9p(6EO zf^p9A9@b902e+7tJ~`r-6`aLP$H1%p&TEf9Li7-wvL|ae8C5 z&Gl05i(-g%+gs%Hcy@;qwl#GI3MnjtW$S!z<9Y>C2fJfdTuKw!zrR8>-jtf0v`GpT z5-dO!dD_+kNrS>_k6-vXCn6fh?W$f!DopH)*U}I3<6c^Y-a03UQ17T;A{N#I3-cZ| zp3n_L)R{!gCmI^9LL;YghA>WQsPr>&0wpT|{m^aW}t3M&zhdfCk%r?b)C{bO7Z zfnRPW&wXR@ow4X$?ZNt=;#?0)oS#uOuc^5F>$xbAgkw`2f>mKIY{_Pnx!l~qo7HnD z^876HdY6i8mzz%-uu6Qgo$X6d$V5$!=PMsCdtmL;3$uSqOIs(959&Ty%JdiP zp=0Yjoi=Cu=A|>X_A}5oV}oUAsjKHa?GD$ER-Wj&ut?2bv;9lm#~|SjX1NuZVs9Ba zaaq^HAqtZUhbh?rSmkd!Lw-i?kioo2TNj+x7T^vhZXl$pVpTH zID5cewmEc|+R?B1>r9xHcxd>#}UPu{x{)~(!?>!l5HI_dIEv*3rh+>6}7#Mi1 zCH4mgnQW?aHZ`8NNVuYz%J|cSFc2K5sar~R6=WQiGd5T!w*M{EHYAZE-s(yXe zaLxYtrq|>){G_>)2OGulbcK}dDfJSYlD7x?ckmkyr%-Nt%>~?xU!s4@D_hvGdET$A z=!nk_OUveuYOUe#0I5UlK+15Y!9agR4W0!u`i|Z7VpsRA_32mmS5UxUL=h`8SHT>z zdmSe?za;(0q7gvvr~iYn>G7HaAlL?O_FM2rBn+y>AlY4hnZ@f19qGbgV$Fg^n%g!K zkDD`4H7wSWSg+RTahuD?WKFY=jWK=}>_zJS{l-)jrfpfYyFCa&;T`56aTC2uSRB@F zFPA?qM}oYtv)4;;dZ&t+y~e`#FWQ3S)N3*vaR2bJ6|AItOs0hSvOhZtS#B{v;*mBNH?+C}G&e3{w^LyX zL?!1N?7R#9H;78FJ{csfJ+ADWz5+R5%Nz-_A`)fLjQgRf9Jva8-&%=+YOiBum6ipq zQ&y`jY*YPuhhrSz#>a|!1+s~VySx|95!~-aCokbcz|T4Fg(y`Anf_-Qo>>ETfs z(J=G+SOq22Kkxkuy8@VHHq(Ya0a*f*pM_P6s;RxFw_+*)RC^~?Le=O{0$29UtSNr+v&##{O=$>`(Q7o8 zWzqjltn#)#=r1?Fj}AE$+KWy;o^7t;5iyYlNb@E6jy&yHeEDuVkD2-RVgBDjo04h~ zE|sdAoNMI%(HaxKmCd)cNw$q|g?5AKCI@9BFZHa!ilGI@{&l-SuVs71`=65HowuFX zZ?}}~qwG*r7ukwKz!_%LLoTJ}wb$9h2Ai{d_mp1kAr4=-H7Mt8;V@yY$I1Y^Z{s`s zxJFNofx(!e)IVQMo0#fAo^97$KKNqFiak9&olySazPwZ!NDdx*CxfO=4nyt?` zr4_$)?xF}*_>_j9R1XO?Bu%Le@xo_02 zd=HQrE%7g}@T90VvRx^P{$#b(;}^Ik^bj)Lp$fpUBA&V{qSOAyACZsg&oQzaDb_^q z6rj#x|F+^Om)&9K*|`)}qV0a>PYkjTGp*#-*MI2@msC0V2EY2;4FbHppU)|=#YiU(&${tQmX14QM|3jU6&hnyG(%P`RT?i&E zcLgg{DfXjK$I<71K#S39FvizdNa;B_Q+T-C!8r;3j#08dAG`ioQxe`GA(b~V=N&tUc)u;Y9-R={`MmJMx&FKH+ni!BPPvc`{n8QlXvGPdp;_+D7}Xt}60{5BCxeZzW^B|%&1X$L^)X@`CXAhPHpNMCBidf2 zNX)f2A*Z{u7v=9G($KzG9T1dz9)km=ffqPvc{H%Ly<~Iqn&TttXRo`2oONp#@8%sm zdW=1!7apJ;^DJTbIaJzrPV!Py^6EH)%)JwN{HgMdG1o$ya}FE00zo!llU+@u%Y=ZH zg8J%BI$*&^pmQE|jb}C{s*qYPFR?g>(1hqaqA)!;0GDNttf6HEy(g@{0RHk9EA#h^HP`GzU2@&%a_<>n#g>bC*yM zJraQ1M3}jVor$l8pY(DeSH~@SmV|%v&unGAtCnaY-viLiSz|VLlx%$IgvlhED zm|}6M-ofe6bhMbsS~_1F9^$ThXCwFXY6kT)E5I70=SlZa~1EXBr$oAnOw#+})- z?d?BDv=J9&pC#{ZBu#xr^z-Yvo7a>c)0`F1RUwBx?mVpXK!25!>Y=;&#^hTg=Y5t_ zkjn+ON-G^g<4TvOyxkP@wbjeADBRpplT~io5vFz>`-qwNrBl2Tt^3(NOR*-Z?^hyi zQyAlitBVHBr#jz;5kh;KMw>!(?Ft^%-!aih^<}}5yeXaRZ4xQNGsziNifF>qrY^son;$9*_SKHMN!A>Vy94}9sJf>=> z!<&s0{lwujRz70EM{Avg=PlSNx zJ#~W-Cac1G#j||S{AA;oj+5Lg4j_2zxufl4ov#mo8UOGhYqM(}3a^PAvlp{)ACg~d zh?xPG>{{~4Ws2QX0RsFZISpC((?;@R81FBIYEG7fj>el^T}G3cLmza8&AP^A`*|G5 zBjYgrRFE*36O8izbg^p-5Jqq8{OVX1Wx2B$-fG2-Jr{hB_m)3Ho@zH7`dWr>&R=+p zbA;s*8E;#_VD3NB=q<1MQpZCc_9@)ddcIN_)p+_XLAaBf z)G+N64wuHDC$XY}qU7^Zr(VGFk1FfBUq3%=VuX7*W8WOBI?eAcOfZQFRUz(2@&X{^ zJbd=TX?^(122nFi@QvY3qVusRV)vx}HOS~xqBY3zKkd$&RjW!7KFH9TGfGqrP@9+v z26FI6FZh*OuF7sPka7UHQyD5W`&_+@aB3>w5HO0wk-eqca~s`~0hYT-$Qz4*h7Fwg zo)YbqVKaiR-q_#boh6*(;WAiQ|OE~P!J7QPPI?K7fI5Z&3H(4Q9IU2~#(1hOP#Q*wbdaGC@76pvB}za=Z{hWmzV!0}TUf zz5ATqL%{|n2DCMOR9qYm)!|ItXCB#>cMOU)8`8ox#2NGVKh z52is~k@ZNRKuTAi`9nLM9?_fWjYd+f@W~0f4ZfN$%62+1edCblhx94<&%ocV`usqw zprENy?MP@C3(-iRRW>&^lnK9RP%A$%CoEPsi_5~BUtEKI;S(An=qN8j7LAMsTIxZY z*Xm7(;D3urFb#VfII-wD@hg*%A+<}}st z;80Dam=)@h498BYE5~1kgI#Da^PQ>v>rhqC5tY#JnaHlsh_-YHb?g*$@50H7?SqmY zD1TtL31l0%731FlMf#r;glv4K%`DlAE$>9rMU3!GMO6#j80*Ja>qq*0XB5cS-cD4G z%n6t{OtO_70g4yk5CvmOxZF6mh#jx zquGT+0tX__S$y@~w8cYk+o>te5?()xgt|LTbk7p>6*Kyo+vgw25P+m@tAJBTIAk)u zzJV(;5p!T>_)L!;UYIa`oX2!+xQUEvgtdZ<#i+;fLq?9nN8wnU<+r;sefoz>F`u1v zUU_)Xre{M_2TH?kEI$gd(!!E$yc;byln0Ny;Hy`#YI{IGW8Tm55?ze!d9exHnpfo+ zO}Ib{xW}Q;Kk`>wstDg4vL{)`NiQX6J9^6QAEf#%a*b~j%?R*T^2^-?=LkxqP!X6% zHo~ZWH2+}*S=fMuE3;B$PNd|2yr^~!ODox>UUd(CI2PMz`7KI;zLt8JOv`1%s5R7Y zf&3rsp{^(@%TUT&n>@3@TEpwOI?Njeb9y~?n)onrH+kHj7&5w)4u}s=2{J(-l&6Yk zC}dk_>fU*^X~+RwvcaQG}iCz^9uN3L#&6f zA5%UqobnT_Kdr#&?3oXnq`{6mI!_fa#*IRb+h1vCV6kOe=nmCzZHBeUzzVSun8QiBj$WCVob;qZvbT-7sE7NL-6)6FX zu+0O(?zJF1&)54#^>WT*d%aJp`S}Ohf~tL4cGQAU>FJ$w()UCPqDeGLEB(L8yB2+O z#^YNxfUeU&Se3%;a2Fth$aHsj$m+{SFF{HGLNF&T89{JemoNI3jN6~C$vtdxf@*Va zN}TRwiYbn4esWz_Mt}&A$39x4oyl+mLKMT8eb zwSMtvg3~<6E@Hkp=r`HxHm&}!dnBfBg}wT8APQ)>Dmnz$^KqJE4Savq-wCsKrC>B% z`;*@_Eh`$3cX8QkX74GR?c2^UX*;be-5En;YBbu#?lcPrL@$nhVf_C#z6^VUfiqHF*$DLH3ELo`dTDaVNnB8E)475+CZwD z)=wTST5lo=2Y5y9+Qy%`15$tlbiL!(DYHoIh|_E2;xO^g|A zk~K(0TaKJXXV!KEykoejl~~Hc+o;sTYAMrthCbF{8kh+q^m<&TYiM%OOJM?+PD2s{ zrZ^^LX4<7+BE83%J(Fi5d+l?|oz!WJr#B#jXNjW4auO zM7-wzIXf~#94i(fLLx$vVXLHVRIO9H7&%hWV5&9MH$K6t>T;C;XCQQcwRc4((GwV4 zVp#h=M%mVKO$1dqY^0l7`)Q=9E4EQ1uZe^a)`&MRlbnBORo_M6m2hemw-z()3T7_v2Xl5=^`+dV)m;d z*F{P(7~NWt`bUa(@O|t@w#&8kjn5e)cMHlbp+H8mnQ2F2nr1;TB#;~a<#sAMV36%lhGh14k)g8Q7{B%*rcWKBrJ{vqt0RM_68=I z-wR0^;e5pCCI2K&z{rx&nx0>;l^KHNK#n>>MM?j1rMZPq)&5C~p9(rKJ}HBxC@?H6 zw^bJ=M`9ozU$cjAm2Sh*{Ec`t1cyV3ubV$LN36WZIJe;MWE7Rbj=2U(&*CAOkCiF7 zuw!#vVxl&DH@|!{5(__u2A}U7x#_b@&dE@2{RL2Ln)t-(L*iCsmza&!48D~yp#YS& zLH`5E*SphXbel7nvo_j^U{VCJ=ZlL219i~ie|tkT|A0tV|7;(+wxm-n3kI~pt~M@X z^VL&u#}_b!2EugryQm+2Z9Z*IgQ+wn)!=5=oz@KKTw-b~2}v>VZ-QH)h2RYA(~AX> zAo0GV2iv0&)*Bhr?pVly0qq{U9L}LxE`KCT7qcy>v!utH2bu03 zFI41dwB(aac;4N8=y*@uFISZ>WCW+@*WIt^(X+g`=Nxihdk>F9v`eI~bk)rVsZq6e zs)UYodv2}ucT?kGvAnzMXv)OeIsuW6Yp7-sxS{80@Mwk;Ovb-*U3^@kyp0aAvkj-Zu4A+sE`@~P(SD&QjqJ=^Tue?8$RX#0Z7jmTXGto2r|+g8U_Mbpuot6Qzr(H<&O=TnP4_0^}wt z4?=_}DEM^OurSt!(*qR8^C_Q)xZ^e8u!nGfDdC3?+cP?ieNf=35K*Lz`s|?cY`0Ze zVKne80MIi%rFGBk=uh{1b#{~S(qZqeLy?bEZ(YJ?Ennik0@euPgdjdMLKKrldd)sG zF({Vy4Gcurs=?@bX--+zo7a8cx~}&why=LT*r#d{B9IRpmT%Yq{M%d!-v#9y;o3iu znznAW!mbh=oE`O`^mXK57=GN}Jbg7EY+Sa`fDxt{h0z!F;-hc23v&}LyuH6!-7L8( z=dK{OTM_87@B@syhErZZRFKp}bSXFeKTSNoWcqV$-t8v6`)DKissLHMmgV(U+SX9A z8_hTzGI5hkwUUiTN6mgX>0I{RGNSu1;`6CIRF8ywurgT@3iKrz0N8sZQDSCqqCRd* zR;6Qu_N|txAc9_h{-bk%g6hEecG<+KtLK(+Wo|S$?++jp!M4bK>-g?KStvW9H+MU^ z-=H>HepbM%6)Xp#m7)It>1o;iwmQsuwV-|)t;&VS#kV?iM%qt3@ht*+%0$L@-NcT+ zkSW)%^@5~Rb6MEE$kR)HRkv6;r)7PmB4lk(4>i%PGtqrS-K89v@tGcJiBf`CVxg(m zv+@IqoNp0aigrAJ$Ykxhx5}vSenLI6g$s$q+GlAjjUFE1auL7l9W*TaW;$7kM$78S zW__^7D0P~;inA4nTR@^FqwPYA90>VawY_ZIdit+uAPCDj0C7gL)^U~cd~osX!n%Fc zyK)H%Fhd$$br-lM-6cj{bI&mM6Q(ts(5Qv|)|D@2GQd+e;ndWL>y16+cDcMp0EJf6sb zbfE4!p30~HlDCQL1-hz^2ht|jjF3_f)9x&2nXGzBDk`E8j;*Zl{$Gsui%J=f2ZOnij~k5 zcAmc)dAXV5lYgO)ba%vs&0v%Ml)>gnAfq_;Ra6SszVTy<^PnZMOIH z?xy|z;cn}08qTTvmBW^31qwl58S4*sHZC-8N4IaB?lv`?)1%|#9pH6QAipf7-exqV zPH7=RHL#@)$va8YEPmY?SDkW2e zNNDAL3*~~eb|h9-`##(2r|VR}jHs^;p7)Fg+H|Hm1UOeKy&BMT-l>fcOpqc=81iA2wP)*DXyvtPdiKx4}blyER9F?0R5ch_bB_YmLR4$mQ<>ToN-EMJ}- zW2U-Z{iTzdcr1=Q$Desid>|X5m8XLAJA&j0pB0G#o|zRK8Y1aOz{w`eN*BKNq&uBL zW3F#E5X&|jgqBVK6M{vayGs&R70zJV;#%MBGc2U3h>qrsnLHh~Os9no8DsytJ{tKU z0X8s?iPM8ks6nV~@vSNA>&8!Z>W#SkuNs%bhUp0Ad<(**SHhR+hAbOQq9uIocIVCP zdoB&$1us(2m?z)NZW~xzIp{ofCT=w;e;GWty!75|dOQ#i$?XtJZH>$Mj*J8;Q~2@m z3_tI7Isvo(OArD6*Og5OWlYMvC=TSU%ypMmcb}n486ZmXc1H1Vb$Niv zpo#=(X(glaX;T)gZSRzYrxguR;%eb1rt)^5bF`I z)5WCBb@2~$Tn$sC-G5APRD{U1+)f!U(I-~t%k?>$O2WCkPnMe)?mY)WMEmo8Hq;F_EXVVE1wB~ZKqJ^QB9)^6>yMPwLa9qs8b|5ql z!KS@9-YPu7Au7#HcB$;JN>9?I0@9o6WgL1lL#Gt{!OchWV2H3q-`hgzzpIxl*nz<1 zp~zUQ4n7SYaUiJIyiaFyT1z8cYUEgtOS7mWVv0durPu;+-kdcb#q4$9SUIVsoae`Q%RivdFZOex|`gIoJ_dgbH^Z5`nSHc9oD}E0?7}{prte{?t31 z)EGyn#*Ggf{3hyez16t50|PG!T~xX*Uk=o8zhP|-F8Wi=$6@yLbbU6p=jz->c$*8FDr!~=iy|;%? zOxWlBp)yvtdbv3Cyg7fOxY;H_^KpGZF*rVI@RzAL;(lg;N*3eg%ifh$x1ZA{@#{M~ z_OajTLi&(!@l%R(TI_!QGFs(Wb$1-jx5@GQLcIDO1ohqcL4(?Jb z`mFl@aFvGc`bLiPlhI=R0+b{;o*8j(-^LB-nHD%c4zB=H|b->`S}o^Wg?G_f!UygS1~fzMiyl+ zlaO=@MH(GCMd5ruf@~d;Z>xa(8D+Z;zChwjXFy=Q!^?eAcs)&fdQ%Vr!Vb&XY0oW3 zx)Y;F6hXA77vib{aB4))P6<27>rlOAby%?Q+&+b@(MuJS# zVZN%59h)i;Q-z3(x+|_Y3$rNiW!18^+o@H4E@VaRxkC4?XZRMXj#wn;myqMxl)4pn z9ftGXXkMs&B&oYI@Wi27DT!I5f6{x+lX2`=uD zq+g$#s={1l#z)Q?%$0=iK#c>!osq8q3?o~?7tX;!fFZ z!c?&`vrBxtKgW$LFGdofxKpN!rQRhx&;4I_uqEFSQHtt+c)M+~h$zgO^6Fwg_DTHd zHMIWY=;(C?D_2xFPlRXig`%^jIRw5mI?)%qk3iVYD4l`ERsob-k$Vu?P)sH03QWFt zKLQbMvZ`{EYpP@*cI#M_m_?BwFLML;yQ!bD$?kX%CQ69U63%2rSkE`3rGs!^Lxho%c0Bl0rUlCdsuh6>N*6;Hg%9N1dSSi z?jJ!~gY2}VWcQXtYsM=!y!phQ^P#bQv<1ncY!1hYIJe%SyQS#)*{eFX!Gs@PUUBXl zuGKMB@a3couXZsDU1Ayc^{DH{y~MJ6IL+6izoS^DJDX#~{OP{cW)dqf?&;khpE_MG zeZH*-=gLPdmOxxz+jnkwxV%-<{u=&;u6wZiHGO<=(MyN{^+~Epk4`1Z+WObUHVo3= zZ-CE)LT@6t5SRSrHyP`IKNyJj4lxD!80wvtRt3D($n8^cOes3q! zo?nV!P7KOnUQUUf)<`Xn+ES4FQb#Xq7jd*0FeZb^FzxvRG2-vAv}p5BV+mbFCHB!4%cN`$yDjwE^KxiLfaE!e!&8imz--^;y1o-%>}wHN5CkuUNYy8y zo}oHUbsR_TCc-rQYPi$$XU3N6E^8~g8J4+22mz=`+km-JHbAaur=8_w4P^-VXQUW^F zJZ$GPYx|5W-GpLG=|_Wv1H;NiO7lJaG8ahUYKVfb9hNtzwskP4S0^uACM)g%u}OCM z`cmjTLZuC1>Y7UddAmcuvkodcIGk%Dz4HznbzJ_W@cL)Pxr1_mNcX^l5U8X&|G0$Y(fgXfZK{C9=t(0gfCU9_T*-;ZP4ZWlb3u_gcf11u=P= zH?OdpS`=<(JtM{@<5%eK#i)JLW5bs-td_frCvHmzWRr>x`ui2@)CH0wJJBKs-PupT z`p~akxoGcJgo(jy$($F~NpAAv1P6-XlMd{|0m8Yc1HOVa=?*N@$;|F~c)I(!Un(`@ zx8C+iJB(oz_MwVznN9WS6S=&2-!OeEvylNk3&`@svUw+4^+Q2E>@45^)JL}1?@p)B zmrIws|F#Gh+VE9Ahah4OJMODnYp*xvp)(<1*-HbAg1nRDe-ma_Fqk4Boz>NH@~vbl z7>Q$u^A0%VS4Jwj+LCP>l8b6<2UpHem608*~ zW!PA?jSdHHY5k>Q*o#o#qm9KW*}abVcn}=#4;3pWB`7&tY)<|Eh|OI04h_@hk04mo zJ8?K>C8q0@RR1_5L3*Ad;Ub<$=eh)_m`TnewkS;I%+A`lpf9hkRu_M zpT|_*vJgxMJghy(AHw3Rnapc8vg}BxJCccW%tFE>-8EBI`=0&zQuJhyJ2l)8te(x; zVa0w~p9W2w=Zy03D_u`erwJTvd^V6HFcep>BF*mFQlexod`X;xqrYKfkcaMA9tDRU@ zQFOLT%`6hi zdUyTA^})g`^1sUk*JyrwNbt@%`eriI7s~v-wI`Hnn!xi!yXk>c9aqOJ4s!?>_EszL!G&^8L5kQoL=>wEEss>gkm=Kk%*Nt_%JUBzJCx z-BnR|;|pDfg1I-+-Xx^s#Z#gpNC^W$`$qSWZ}GF02Fek9GYrI6Kd1B45d}thgS1G8 zf?wbGT$@ukYzxDVl96T9vQZzEw3EuLax)Rhb8zYz(`i^flXzlS)#3k`l0q2Sn;n>#xk zPL)Am4!E14M=Z0E=T24<%2cGzKW5T+ybJqhMe~f6y>NfT28bTG?hIlY<5241F?wiU zk#yZwxa)r$WD=lvZaLoB>FEjgz#^~qQY?38wnI3(aR{DwtBZnW>yh@K3nr!M!wrP| zqk3P8`6-FKxXC3q?Q<&Apw5%g$>fEB6mHA0l&K~f1J8+aRo(wk2%8Zs)byvhcQXdU z=ey`q7c$|;!8KNg0vd7^LP+Fy1)*YPg7%dblDoGI+8Cs?oH(hKZ}3JgOsrb) zh_i)M7yQ39a_ewz1qEN{RAogEESSgT`VReZXVv#R^JjZUk^e{MN7D;x=`5G=*3*)+ zwe-xy{1oD6g*xCj3GYJPw~n6Fg)gwYvt)R^PR5fGZs=i*?mS5y5|G~2b7 zo$M60F@5XE8U1k+ocA%PDGq7)gWZFog#8fo9d_b}2tvz!$jJNV>y3l_16NBq4fhuI zX=DU6+^xZMmw;+&GPbYS?*!NtQlu|FQdVL= zL1R7xWn@uFC^8PIZPj7-Vqrz@Tx=02gFgyMpul*2dcq(LZ8l0(@KM_h8SiHPWVF^- zz=@DvoSAK6y%`>#$8=*ZrL{aj;o4NfePIuRR6Gh7n5RZVp=Wx}2HM|MjTqO^oZGlS z$9jF%q_v}cQf^KofH|Z#>M=%{OTrW~>qP<{2oka}a5sgJ?eS(uIPpJ+94--ANAk;4 z`u~wgX0PIqP_raR^G5la$DI(+R{>S=4szctFO*c`^X%%{ClkJRjA^*Z1P_c$xXc1v{q^1^;`zyS$-n+_deRh>sWR zXtTE%_^+r;4DdhQI~s`up068eGxbNV#4Dk5$4`Z=p&ert{$F)gcDs*c@BXGQwii8!Lr=z?14rK5Z%3gQ%r?F5(ah zk0ZhKU^zOlN^fQQ>a%B?d)4$6&7V?E+q;1b2-@sLLU|__lbW|Uf`Wo1#?>Jr%v)^N6H82A z1Xd})F)$cu^bT7roR2oaTmUpZ9C)|e>}9aRKH1icnfZ8QIBUIU%VXgx(=+;F8xz6K z=hxY6X(Pv^T`9jXC9D*(N_*3+U-OLvSh&|wsz1g%07z$wisL{@s9anB;~7KCY|1hn z3`FOq!4loAdg{mh;l6}KMC${q>3o$qjI#W6VZ8`wV6bNRUYuVd^IQGftbp6@r|^={ z%tE`Lo!!6nx^F9pw9Qxjvkv~(M4%%Fa}MXCMC^qqJlyu-3`eSE)W+L^8@b-a4W|OT zX?{fgK*Ti$5yTaRU=A6XXU{YLMKDxxh~-~r2k#6VRU=viYA$kx{iA@s&f1tD69@IXv%Wg{0UKP}qxl)klzy-`}fd?!Tl`w!UBknpdx zU35%i5Rv=0vf}H%rGF4p5uhgz{yv|;p(1Hi_08$UmIp+NjW2V;d-7g*_XE21gtB=KmDx~&wjdFUCN&(RgGrmJs?baZltfwHU&8kp z5t`3xQk2m;<@0Bjvf0)$){l-XFOR!FUe$0%gca4kXV9)p_i!pG`|LmjB2lbsJndB0 znQD^bYY@gJ@(gDuKE<5ZyPc?p&J<~sw8z%$*fTORnGsXI|btV$L6OZb+hRrbJvN>9Y1{f~Es<{F^lGIrufft+g%WoCp98NcZ2hH7) zQmC=bXIe@pz+5W*M2BM)!tM4eE%~VH97HO{!Qg%DIL#E+eOs@nA81_~3f{T=t zX<+pLB#{CfZM6R1N4@L`LJl5V=}ier^L<-eZ2df%l6uGg$~3pEv&>KZ8Uc?uVA8|Ka!>W_}a$Cmv7%N80UvQv`PQA4qrA#R@6_N>h;qT%k!Qg zTOd6oi8B9?WRuFQx|R_{5AB|^(>_IKX8q{!OP`5k=c8@MOA1EQ0<6r(nVSkL(J|T& zbPGoi`qRr_{r=Dy2T!vXz#v%W<+k_-!Y&pYVmGiCd`tWIS?UK@0Yl4HOx5}E%EZ1F z1Bki;3rZA5ZP~O|vXXG+$v2k2HqVLIy6*D$LcyU%7U-^OQ%w#vkqcpjIuJ{9kE7p(yZ?oSI;&ubjA=Ic1r=V_zSb4 zjT?_YFc~d#3lRB#ev*d&z=>X^e8-uVr_fhNPV3{HV+Q1%o@PG?ZySJlWVCqa&P_js zLwyvO(-M9XAWq18nco-BC8}mL^Q8XOr&LoDl`cTIv2;ScXDommCd~x7EZQdaB*eM~ z8XVu+^J?>uwkp|aH$L#=iTnh-@*sqe_Ybd|5oV_r^;TkD3ZRQ#uH43=Hh z*CJszyOF5{BwZTM?7*D0D`Bkj>WAo+Z^_g|XN5tZ>NsT>0zV|$4Z9k~Z z>H_jXd{G4MoWK>0a1w+@$l9TU*P_ZUoFMXZ*MwdJV(n&j(p?I&2XSD3pmMV&2rh9> zn6+imeOSXV*?3ezUXz;bW5059zK*F~Kh7uWm`p@M99E>J)n}wkj)%0WD2#SE$C{5q zmI#P{FFyI@^u2Z7t?e7YePIZNfB-LKY%ASPlgjRaL@xs{J>=9i0m#2vY~(&x7Knre zT`#M@XO!yqX$c*$Ur2zvejNhXo41Qxf{!*9lpqDv&)k@7?~Apq%*M&lm*uHFp9|pd zNNW;`vBngNj$K)|`sc6b-U$gp8#y|wt@`^kcZT_YujwKhR5+_ZdbqDMKZGmV?5HuN zI~q}f90^+E#Y6&_6n5K~uoO3DR)Iu@kEBvR-@I$8KYY@7{prjfWgdj1ozN^WB|8iKjeHoN9rD@DSzJ} z$0b)4AW{Mj8R@0eu5>_d)$@>oh-9oJ6@`EiMc{~(_Z|L5W;(f;A+2mX#_`E7*gGnd zfhoK=Sa5fvY%QEN3Hv`YWOxAZy}93Ne&=wlh(ovEy(ntM+3hP(O>=hTaDTrvqgAbX zcZcXcxPLP^7SFk%o%n(#^A>^Pz7t~w+JnNt>CRLys1}A6Q@kaD~UDkR1C2Lq4 zQ+4%^NFZI-Y~Cx*#wt0iXUTrx7HC|*lPRmnO;*2gy*(Qrmj(C85D@TN#`sjmy52Xw z-!n}%^_3ER*ETQf>yYsP4~za9sJme=C#?Zk1ay~88x;ZA`!{@#ZxMS={f&ly0z>{%bNiTIh`lEBKwC{Lyv({ zk85FjJ_iit#COql5bAYtCr_)&fq}tklN|bTlqw%qd?XZ^YOce}Sy%A!m4$WO)PRFe zzfCJQQ+o959xsNGa-Gw#gC})7pUwhW3h|~xmU36biR z()>g3D65?6a(6V>gXb=3OR@UZqdAB6K&Wb&&tO-4>JUlc98_wb?ZUuh+l!w3y%Svr4l#2OP7A z#lhPS^y%x>-rKJ0>p5({J4OxA_ptEt^tBijaB9DuO>!b{a&btXO>pQ}Do&00w==f~ zy+t4`=>?H&ZZ>=>=v5sWeY1;i*_5HFiW&h*HWDV~ezmNbffKERVoKqLt8%l3()1`r zi3<|27NY(?p3X9=3TW%vh;)d6bcvL7O1E@McSuWjhtl2M($d}C-JR0ioqn5p@B59R zfB3`ToW1s5G3T@R37hEC3asg=QXZV|b)m11eT1NBJSFSFyFQd`@^Ue$W_yvMnn2L7 z7vVxnmEz8+2^Bc$5{0_MT6Uiz(Gc7AyaDn2tbbMO@OwIu-L=+#o}modLL+V|ZEKP4e`XgbB(|{6|npVhw`L@(|<^b90Z}Jn2E08UK$#JM6jE=Q!w?aEU z$7IfczF*X`bIq+u;Bs+d@bWOqq0OV(p|634b!8sslE25^nDCFs4I(TbS3``HcmT(_ zk+YJ7Ya@A+6&P>tD2PF>N+h6;1>1VHKU1uM+EYcJx&z!U94@s{`Gh(mw#!d2`x+(6 zt+zUSB)dAu1x;OYmCmxRvFw5Zq-!2$F7kx)VOXoANwK3SG;F%H2W*@Q0H)eL9fcER1VfXgf$sWBz&7`kRJ zW=CC6aNJ>uWn>=VKhRD`*PD=96$Zqs7nfEqu_M|=Q7%%RJV-`w*B%C)Y~XdI!J$d7 z=kp01M`0W3_1}ZLaQyyn0jBe5rPS@sfVn|_z{Leu53nNwQ!6T43r5Qvga3-9C?|$q zm};N3ZL$vZ;rUyP52*zm;uB$o8>ADB5Tn)j6wmv8m>2yJ2KoNhXXbBn)4GZSuX{8O z#l9|m+%4p!EZy(aP37M#AY~^0SqOLL{ZAmU0d`VGOpVpY?2_;Zp%17-d zH5hE7Bgmu0u0A6GZe54-7tlhaz67yMOo$8U0ocRJfNcpziZ-KX_*ZV0jX1H>=tjJlI6*Ki_qzI5fA`#p)a5{V6zHKR>24Acq}&cmjhNt+}rC zn3{wd{xTh$p2|=^i(jp{z`6%C{gRpUR=L z8ui{ayVArjFc#lp7&FtkhoLGtfFjSJ&=d!?Fo!W7hix&$itkO9DK|wN`tMR1_s4)H zxD;ZkcrjA*QG{LkSNZ1LSBdG3ItglE)G!o1JNbn`W!fYj*m|*BJAaV;uxA&%8Stq6 zsdp}9XZ?Gv$3~P3G!qY?*PWuQf>z}$8OQm#;Sz)@W`nQFP4n1|g&Ee>k$jSGIlI>b z`1<0U&SqET{jWj6gd+~h?B07+jH6#toVS1T3u|FTVW9=ySPJ>?7nmJnH>pIF-9FWR z)ahSa34%@VkI|UxO1YQL@!u1JKX2aKT@WXum{<#g;-hVGMZbP_eW&QKkrR!+zAqR# z>*v2tM_#PV8Q?0{prsjfyqCG9-!ut`e;W;K2zOJUK2um8jNwu!duVR7(hbedKVS!G z#poYQ6C!$J$JMmqMU1GBSx_>OY+^zz8*z+6lCQDXI~lT^rWObs78^MnT-WVpEI9dN zSPs!W%rmup7>(a1N#LnGI9AtRDbTBH?VM#{ zv;&?m;FG$&Q?doHgWJ*|wQ^=Kx5(^}vipZk`_>h>xa+z8z)k$&c4D%LIcc0!vr@s_7QBlbgZpo3HJhu zfXfsyxJx0Mw3*DR3LC=@;8#|jnp{gGVn4$4-fip1W;)z%aIO6#;7uQOx2}z9ydfqp zuI2C`0Fo;+9k;Nk?fSB%?T#$^Mw!uwa|D@cWTwCz#kpJTlU=YTxKN@eIsqyZY4(ZQL(=xx4iC1%;h$xall(Ydj7C zDM7du%gOHVl7Zquq_h_;Jthqfh4F518BEcRzcYmfxj_}^tJ_TQvegWN)~QHI(xEh%cE0+4q7U6K+bzpGknRgdbel>aF=*fY7rcSWz#+Tu)mj;p`b7TnGN|^d z;s8@x?q?y^?;V89t9dmwU?JZ>n2TT&(&c7MXn6UpIJu`jAHMZDD~}k!f_Gb|{7*ZC znaKzyaRzf=vLx_!*W3j*KUhOG8T)5l-xF3V5bS7?Y)-`m!-QbysEB5{Yr@}*|1H*D z_Iu;~(Hiuw;B-{HTQJGF)jp>ISGMmxLag4 zJHJfVtgNHrh@9-@y(nz#mqALrer|a%B@B3{l=W@U`L0M~pX=-sW)XC*=D_$ooc!D& z5fS*Cvg#W{Ityh)N*uY}HKTB7eIM%Or^fqkYAT#*+Ee=goEdn?>I()+wxSf2T57^P ziU$$eP9EF7MUE!HR&@^iIo<(cJpiQ>Lr8Wps}m$A>zwif?J|)t%o_~VpfzW{(sR#L zGa^#KT_%0J3JJ>Hb+`D)DExjt?Xg`D^MF`97(A^DbZhJ`d2h1!y)pNc<_ZOC{BC|>4Fo@$=y~~1`sQF)OI}ZRklnwl& zqTjbmT48{|!1#Cn?6lBG93D`Yzw!5MJtqC-#WQ{3T!)QElUvpsO4#Cqj_29qli{f> z90Ee~|ByRmBFGAFHo3Ly2Xo{dOT%}ptUi=KeuK_%W3ZFK;Elh$`~cf)f`|Y0{YLnJk8a$*^KmESUZrCj7Fdfm*faPZrHzN?EpjAt|U8Je0I4m^rlIy z=kw93g`=mN2K>b)(YxucBvQ?Cfu#kxo=H_c+rcIAunS<@zhqxp3b>oCTZR0)_D>&i zQ5VJ0bJOhUR;4upo#{!?!Tqss?u9vVp#F#VWck><(SdN^@LzM*XPF+#mwOfK%AvL3fQACdpn1@11Vg!rHZ&Bz4SAyRj?6r4^~n z7gf?iiL2oO=rCXuI$C61fIR*(l&iuvS>C~Ycn_3d5~Ry@bnz25%>N!TL-QT;z_5$W zmj-x7C9npY%*4*_trui__{k2_HTlY_f-n>Q>yZG`;BbjomFDZDEFb7~S33}F5t8q& zNYntS4yeS>W@KMbJ_s+Pt#7!Xk@iz(-9^Z{2dJPtU+1A%W4%I`dPI=O6(w*AT}Ho! zp3R`)>`OZ+Vdd8Fkc#TGJX;QP3z)s$>-zTZ@T|Y}gE^Bb)?q-#tc|waMrp!;-nM}- z#eUT4C4xGZhPV=zXMUJI z{SoI7`V)uBlC+E(7v5wUA@|a;^;XHX9ZoPy+coTKCk;x6WrpT=4p!gp_D&xT8{IFw3LXq8`XBSaaw zL~Lu@603wy-|uYtOB5NbWFOAkj>WrVNLM@mPn)Om0eI8%*P4OssK{l1M9}jlfFy?u zdPC3R_hlsHHSOJ8AQYt!h1UIcgx8qLzsEJp8=F_bj{UC*#!Cl3Q?wx8G;mY^cE*aR z=o7i3lbouHXZnW0;UzWzqAjN>Lb;iUq0IcADzJJ;ku^4Lj2a>}5TSd~i)pA-EmnNh zA#J)%IL-nXo3>k-FS;>aqy%ZP4yyQW=C8b+fdi%@7hA$b_u7wKf8vTI;5V#2nbpo; zoQJ;;EW3lcwzfEE9pxYQNDwo!xpuotx{B>zA=&_$nW%W|_OG`zN#~rVxv59p5aF0L zk*J4GGZ`^nFPAJ7va?yr)OXiqM8b5hMhD72N2K$zk`5MZn+nHuD*9DRe=KnRY8q1H zI`AaY&JJwj{~!kSgk&(=io#g;m^fxL6qQ$<=s0f{snzbAn=q|WSQ-}< zDxi?)3E&%x`koFDag*~*{L7!{AZ@=5F2rJsX^p|LypOjVK3qU=ginf6JeBSj>g zO?jw>H&j&13(W?Crdn0R1*qiYRND2*$`b`p3%}5lQ@f#!pSe8_@28^ z!L_9t573h~h>~n8JzicvHXYJLtM4pZRQ&(bc*yO~kq1x`eKk`!FRyJRQJMJ3)>~|W z-s%*OYHE4e`ik4J`y=Oqpzf4744eD&lf1-b*?Lz^xOxE4z`?a zsBewNG)ESur~7W({t-f~-Sx6|=25*sH4#+Jh)5Msd~r~D2R0vOHrOS04$1_ZHDcq{ z{oTs^$TJ!-t;#3(c9||&I8kHDZ`EY|S8?FbDB)H<8ToLGzDt<7CgCsJ^tb_lZ34$< z|J5v$Uubfe{DAdE*LUDA$Dn9P#w_5Mq%}L%{yO?hl;u$~WhG&c9Qx+3lenRd)jw=e z*%@0fBhzZhhHyS$5hA_YBrGHu9t+czHQtiIc~xgC_eG-Zj@dOKI-7ZMK<6I2U;IK6 zgxujPvL;RsArkGCm2rmRJ*UF>3ncl662b)d{v;QRZfLP`C#Cx8QF zoU137I-|DQ#;b2y8>rArM7mU3A86xwZg3!%Q^gP`Q1?m&Jl+CpOZ-PTd|I=eR>E$f_nG?u6!0qcd&HO58q!zn)~uhUazYK4#7G* zuN13j#@{_XB@@FI=MW&cFIB&k@Q^@B)AFg&*fxYBQ)kaVds31qrR8)#(hqJ{+asMn z?%It5NcwHQa<;P8^L8DOQA$fNoTinMP_Gh|Nyg{Tn>)5XZ6`3|(i#|xo(0JkLy))C zh4#WX+v6^45kwB;Od$f}(h**6d1Xx20UeBJ=w}S3=ua);Vb>&_LILLfosVj|#dClKDH%5+(eZ4Ah#YSNw& zZggdPv;Qn^B1IcnZ0P(XGB#k-i2U*p`7xJIbmSMxyQ=#W0N|gTHd!DMKC=y2pmStGD3+)E0I7|%@9yF$#qWqmd8Fau z9q&0mr`+#!wk^A~fwOuX;~G7IrCJim<%Jqn|2Y(u-!laZ&f?fSmeprnYxsbYl|hh# z?(FP_aC$=DXI@e1@O7E?kxRk8LgODs)@!TS636TQzRen6E7j>9%O`swMdjtG^uNLy z+IG__W}|AFe!Z9oubUq)Pi<{EHE!5rhIo`k$HdnN8WC2|=&W3QAoB*F>C_C^5@jsn zAnjp)6Z&Z$8f-eurw+siy!zY2`w_(a3aRau#<0JB5v}eH*wKn9**5c};Sk`9mLn>% z-pHxW_(282UHtt$@|#rj@h^KwE-PkHm`6{EuPaB)d*|yaNm4Y{lE5viCPa3X1#uC* z_F_Jj#NyWC!b9TzHRKVbHoQ+=+#J@;{=bOdHbNJ8rXzyIE4MjNc6p5_`P%s5TSdKvB%-*tZ~PN#V^h=l zdBe5;{wq;eG|1Dv^7zEnm;tiBvGF2<@9rIWNE~0QPUre0>qZxk9HrG$$oazO;?oYj z8nDyv)`)1E31ktob@{TolkI(I<8D9?ULU0cY6b4 zf3g}=(lpAfd?kc_a-qJl#P2sF<($`_sB^bc!y6fB76F^3b`((PwIUy@m!My+1nH!~ zZlGF{xM|-8XiJEw7fUFx)oDwUnP@3GaK?03QpXj(YGH7(M$UX0n^$Xsjm0#lx;ACp znx2o{X{8ByFb3(;R?C${#Q)Z2PRA74IH+A6>0b3 ztC~h!jBVGad5&*YtY@BpY(!!G(_?@4%P!@~5 zOLbC816BUyke?X+Yn6ZSc%5o-A{yE0gJNuZB1Ix9GY5$I1HknkgYBW8(e)0G#v~2X z*zq{ITGzi%s@bj?6N>`FlMvVQEafXp9r8tct-(pg1A)Biq=ZvOx&_{*l|(;PGSUCI zsl`v{SYBTz?GKd$G=mDM1J|DJ)I6^atyYe*0Rm$}bg_TB+*4(wQ>nKg&K3Y#^mJ^f z%ZSR>&%@vm9oG$h7%rcLw9>B!s~J#kxgn8Ogsd?mT7_AN0$ie}&r+dU2zSP&VUo(M`v zELzX(!AB}xTsZyXKXm3>N_S13+J38Q;do%$^t#}a==iJX>1PC8>E30m6%4jpu#Ua= zS+dKxB@n=aD!;2il^xOM7XFT?hbvR#(^guUe(LE@D$>c$i=PJqs!DDigV|dyBG68h zn;KaMwCb%d;C-bRKQjho1c0$O*G3ipvGg&1@SU>IeOBYBOBvle3Hi4?s{dcPU~kh( zb8DMN+LomAbPOdK^Soci?p@*bA?JM(>QGf6WSP^e>pzy5cxC5mOtLzi_Rn9%g=H>B zc>TdW?6DPwi&^S@E_nVsJ+gYT_#*wBB{wHkXdWP(_IahTN>%YoqhDxVksf zqY&?Q_I(8i1Qb!k6!GvYk(U17M}Tep^k7B7;n?`gVh+a$A9yF+0;t3TZ`KDMr^=|! zk*{otsm9Y#Z1L`9%5L74^9m2-$Dcy9>wy(?eD|~h3rpuSKg7o1g!eOr^eUJbOojNk zd3XDcu< z&dVbzGh+)jX05ci{v1-zjKHef;5PV3JsI#>hgOt|%lX=z$4u`T?!vmYmqar~@l%J+ zq3{3H0&jRuwCO&8Q+;#!?{CPT!*PEZWfYZ!FK0K0Ru!AS(&nD)6Mz_C-G+G)8g8jf zh#c%2Q)cJ;r$Wd68GtMAv#cw!-F)o~!Mbu7n!P>9i4BeAWIG@cL|Z`}He&WE@lWvx zb-}Z!V`N~ku8R22#O((dlf@z|WI>5EDGTd=k+#k(fc6=v{Cmr%WAW^2%IU9~@FDOD zQ&oO^s%%%qi>Kq(%OP^~1ofneIx54r0(sgJ6BHT?^xykSqZ$E2Y=+v zaM%Y1ch;HJVO#GBerwyI1jQlXm?iitOijy5_Kg=?si-Z5CCK=UuKeg70veF0-<-*d zFo}ufBlnsrdMwh`pln&Yn;_(Uj!SUa4-*u*CTA@RTQ^>7OyGMy_2I7PF?4O!Q)wey z`}5Cnu3#aFP$V@2?@>aXLwhEur_tJ2f!d(^!DJzhaInqG9C}?HwpxY=#)5HmJ$46^ zc79Wz!pQaURH?Owq*lz}5g#M?d z&5PcUC+8$cdWOo-kcvRemrY+!C(y9E5r6fgk(f>E_Rfgcd|u)wAc!pnrZ!b2iYD3F z^KSq86v92=2@#cC3WB%p^1_t-h&fe1!PLNbulhx~DD5cpJz*;wG)mpTxBO~XCTywT z>)fo;fVSrJfTr0fdfrz2lA)S}$!_V9@5R86^jvsf1Fh4qlx?J@2azwiG!S~Ja|RmT zVD&L5R(Il@fU)VWDtvpwNFRhgLt=88~`*%3= z&&!mtrqGfA;qb zzRWAOh zfB=&KfV4!KOn^Fn?OuGhqReP^f=5SZ4NooX>6=QL&S@9s@G&|6?-VnrbiaQ!hFu-g zDP>d7w%cbp+wZ>>EZan2M{|LIoQOA{OB}(~p>%5Lfr0Sy#^`BN{N#@3D}6+pgj-Dt zNCos8uA5u)eJ2>1!AVY^kCW*pJ6_CH(gK(1IGg!jBC8J@oBP99ggW7uH2<1Eb#lvn zHb7MFfP2-4`^{*9tqvRis+{H~EC?L&`r1^aY7LBx`hvPbktw8Y40}sf8Yi(EO9)yH zl~)@rshREYjKG>E#=OLZN-{O~H9jQdMB?$)F%FI&7W)Sh@dSqxD0CSaoO*r71H#Pc z_j^S&%2uOz_U-dV4rjMmtef_Ypb>|OhRw^l*<~~ve z!XPeA%7;m-`PQmTn2?p88D_Mo0e`~bLkB7&>0raD^iK!4U=eVuEMRt#N^> zswQ8~&x*X#IO!$Ch4PZ0ix1(Ldx76b5O>L|bd}M5J*OI{jEIAO&L}100-axX zjRzzWSG$J$I_9SkG$=_)!uN=BaW1Jo#-wSC;1LmIHaGh5^YPrSu=?$z>yH+Ew5XY< zEHU}S!x5Xn%g%2A>{u%dZ=XMoYUIYoq`sGu@dS6o+h;ha0o*um=or0wTTx=>UJ*3T zV5Ll$mgEJ6&H4IG_FN3>0Y0^jTI&1?BJ)6;k8MJX2Z zT7;pT7~jbWaO7U9Ynwioeo>e*S@*$WB?yk3|Wrd!h#izE~xuCQm zsq{5jzk*^tr8RmU-PCL|b8WTMOGlj zYOUB-To5xn?kEqPj(!*SNGx`$nQXslzS#c0qr_sfzY&UxxCxH8z}Omopg%cc1aCup zqX?qY8bg|2RZJ5f7P`^Kf$)BF4QI-rw>ltyBJPsj+OQ1VOCVssDzzueW_um$f4&v@ zSqt;nzzYr1ta}+|4Sdpf4D~pLfx0^6q)>Lnl}YqBan_f@KXys~E+uLBiR9|)b+#vH zg~k@DGh2DOM}8Hh296KS7E^9&%$%$PGH%Xf6`#+7;)cwWK^@C(EB4jN9d)AN;_%z5 z+Fu&{YNQASQ*30(^ZhCgO`y$gKG+Ne52JDzS;ddY8g7Pf7B8fZ-CCtioNf!tZS^?a zMyn|HVGQ-ASFF$P-+Ws!&jz8aR28OPg`vJj`Hy*&t8)par^-UI`h~{n`}i`H2Sp%YMD7I;30p+{OMcv|dqICJx?$M>7`u z1Wgyp*Z&%bW)q(c>xYkvSGBrli)|&SlkYl^nFFpo+!`@cVt(?r8hw?Un@6Q%Wl_6( z31e1cU_K8WG9ZPDK_zIfXdyEQ59wwIo;iu0Ab}1A2jJ6wLLbM~@7-O*Tex>H2_SD9 z`0LEAO~Xnd^1LT|sl~}0L{etnXJLK0-HKM4oEG{-Q@c1*Gv813<8SnjbCSwE{Y)BV zSR&7~o`(`>XW^)OX0-Z)4XLMxKUwN^*$_WteLs3ScZCwuuZznf`^ch1#i%gry~)-j z*B_X6Ue$IA-Nca2#{DMhpM)KQHaPlBrs=c~uyBgjm>8~Iroy*G8Td|Knw-vGE;m%FCEWZp z$qMmu9%07d0OM7~^l8C1CzbNgcXK{_$XvnE>WZk9-R$TgYZoEztiU|GldOTv?=M^I zbV)ISYSM_JAqVX0iesy(RQ9-J9da*F_oia-%wc=_4bIAFZk2-z)%l5%SU1fDU8Z*5 zlqb4l&nMm%l1c@m=uL%hRwpho;>e~Usw>P5_F6!j&ufcmsUX@XM)}#vt1?hmtYPlG zD1K3eBl^n-1lCmwoq>oK-xVw|43RA~S;)QlGhU37-U-EKgn!+Z)?_4xX_4s(NV)iI zReS!JKYO;hwDTU7skvl`Rv8w)YZ=O`GWmg((9M)KY=rfs#Sqgj|C*O6tGb>Lq6lt5 z*dde$)@oeLU-bWie%)M&TgO=o>%{{g^P&-zQbvN{?r=rgsD$(7Ds5$$h%AQ%zV*+i zD-1M;_P>;|Lkh_mC^$khcC>Z}ygT)K;cwv4p0%R>+f`OszL=Ur;b*;x5fd18z!$1f zmmRrD7Iud{z3enaqbPA7IhJh}V?PQv`W;Fv1euhxJK>94a8Se<-pn@7&`!QBO`AV5 z7ea&k!n`(p-Qzc$Qx6;8Kx_1KoT%p7FB!FtSn6@jRh$z-^%?2>Iu=g#$JfEJvvoGb z%~6#wh#<S3oXW)Asrf9+W$}->Fs+h*NV=>zpv&6xX@zb|YJ#+(UZ}bJkc@+9Y zr@+0hZ^ejLi)qbb*fh zOHH-innhL87qZg1q1oBGiqmm;CiyOGX4dH2x!u3n3aDJ2UcIpFupjn_^@(v=@_|LJ0yeoTC)ldbi2FG92pfk3}d0D(2vHmjiyvBjS5v<&> z!P=vkpsfDi*>TPH0|JF+8u0Ke*0;#aiQIIRYfG5IQDt?QXAA!Nfm!{XYT{i8SZ~}t zScHTV`>Bh2HqSp1{ayniBHjHfsF%lm;_wf%OusYyK6WvFmx3bx1v6_wt2>ir{~=8v z1^k7h%Q6ljVMpG$ti`;+>P4h3dMp6OP6^-Pn{<_URmg0tS<5x>$K+F87Eb<>qJ1c=raK#QEuq9# z6a>W2r+Sw{)4yF(U#VF(++9U;JfhRFY4+rEe?--`)82oMSD`lVtKMt5bYpRfQvs0DXoE7 z7k`9y@-@LrpcmUss&kA&HPsvGV1f)=lvC3l@7ca7zcwL5NB2HE&2Mq6A1nf^{IcH~ z>?&nXQ8lbz1kog=c-un!n*}Gs7|%|vDLeAL*IUf0G+ zS~igYY#el~ZhsFlgKk*lrp{6}rlj_0mp{$d`vS8kl)d!*0S7TV6bD;Oj+TR8|HNK~ zxY2#0B+u;Iv{$6AwJmP`)1+=AA;>U5p+uc-IhCim>a33iAB54j! zpTRbnt-bJa#xJba-;OVX7~gaYKU935v)Pdi6SY~yYXK=sfuik(s|%8>GPuuYwff%7 z*VbX@uLv8|2l?4?*7C#NMQB4P&FH?twhpnE)r0h?cXfs2LNLA4wPI92_r}2@VAwKU z7ULtp7*X!EZ~YOCPtZOx)OX%{V7?Lk^#B{hoAXSQ>6c=0}%AGw15${sh`o}o~ojCn%)_izd)pH~eCKMthzxRCD?Q!0rI=X>`WwRor z=j34ZWVtw!(cuS-uo0e|1P6G|^GKmKi{#Gcc3C&9>+cs(Ft4!b9F?ed6j?S8^3~4` zXlYpqJ@2$2PMYoLnB5BQ-uBa*wJ(~&X2%CVuzvE9DJfJKFl2AmHeh;_CL;d$*|7ZePM^@rW0)2Bz}40`9wmz`BOnu zf%mFR)InIQD?_bEwnnKRm^id75hM@9rIGf((A3s&Ei}~mUN0fA&n`fg%>4OAwatA~ zwVgxe7wQ_vz^|l_NAB|w>v;8h{4)j(KDxN(H)@T`!q0!KwzIC_LchX|etN#bXP*e1 zI^KU*yh-v@Z@A5_{m7Xz9ST<&p>)wiF$dmuBXoijw#-dOi%7!JP1mf-q`q|ZfSQ#7 zAEz;W38Q~&MN5uY6Gjf!3l|kDabuie(HiulTlXj^XNw7H%PtF0(-M@eoNMAb#IIp~ zMa@F@(-yzKo}marSjanTY?OxP_2;Pr<~F+cJBV|?RavQ{NT9z|r!3hNVVIAW>Q2A~ zD2!KNfB$!`ju{al!h?WuNtX~XlX7`yFe0~jOxK(1XY=~t<9E9=m8onU(?^tFe#5!U z>#nf%q`G}M_?j0QL1<5HXf?^zHIv$GN~ghSDHOgy)?T1*>dLNx630mS0VbZ($gIK+MV{!r-5Eb69_wz!)4CyPFU-cdv&%-C#^*B2^&7Li=%@?n zl-fROc}Mk{jcLz94B6X$5+Vf!eR5vjK%FN&!?J`W$8w}>ZDFxU6ufuwwwKYN3a$CE z2snfhfz8ai)eC79Y555?qJ!{fGYn)E|IXOD*Z2e5e)%bEn3z;JD6(SCop<=-8!-Ly z731qAhl(M@@@-8x9^91ggo9@&x7@YKGZY~?OyzTK&UsU}B>C{;_(Z#`f1=rx)qI36 z7ur?c=mRLS?6L}zWasd|=JQlxcvLI0srpY7uB6=Q>U2tR*6t{szodW4qwr@SpY-~6 z+gBi`_l@!oQysdSyrH2~LC})2(Zzv^T4>t)uP+q{gdRo&PTI_2`_GD~f_-BZ>xy9Y z2g`Y1{v0ST&tp!-PLM{`K!JVoSXiZl7?cz2$G8}eF z-T%BHZFysf-k**z3b^NtnOF$hjCN>~JxXN(wO_2YN}cu{q*SAw?UDl1r+K?-@8d_w zBsS(KhXC34=F@27T_Fp>gSdd`W&iBYHd#Sio@U{*Gc zZ=7B3v!C%tON@G&KPV3$vyT-ohu2P3kYF<)c=NkTd~Uh{EH+(YQj;yJHi#=+3_A*; zs_#0KQ+-13b-6D&lr%JkjK|u#F%*n0r(nHC5~(fwsDq*IP2ex5qHxzm6Eog{IZIfR zFZ3f5FON4*z+fN}TZN<98+7JR^{z_f!Zk+WacnkO9fFake~U0=XXj1UjrrV&eiFS{ z6URKL`c^#a;()Hzfc~fPf)Av^cNOQlIPmM9D{;R-J0W5&L~~WHLv_s@`eR#RQfjaf zT?TG|W1{3Y5SznE@4Hgr853!5!dVYCIC+<%$BZ>Dg5a5>qTWl12)-Bbfk|qKUz8@A z!b}b-n7o{ajgZTYCB~jCD7IWri+E>E)26>3qMfgI-)RprPI5}#z0lMAQek>OvTGWS zl0^%a#FBUB@7UJABCR}tx$?ko@=j^j+AXE?)$~tBWC77=M!4f+QJ?vEG!V?rf;Vt} z*{Eis)ah`itF&?p8VJ4zX?g2vs;HVF^X)1N`kHq9aP>TX=nOJ%JuQ{lUs>6*zWtlC zDmQw)<&UhEUJbmkKjT7ruUwO26Zz@V5<2@*E*WsAHCY;NEvBRGB>z`<())D$WR&;2 zgha-^MkW082}b1@OgTxTqx5Sz10%5K@ynxTE6&KmjMrABHLBwJ`QK)oQm;R_P<}=5 zli4|UT}agu5RroTO;WvI-O$t9ltE;)w5n&|-F^Z6N3+$P#-DiD)UJW&>GatHpSF0r z(r=$8eMat@BKVV}#LI}>1r%y2pJtwO~_!l&EmUccuz;>q~G0+{Pi(@%w(yJgt9 zeA-{TkhbI?R(f{0DQG9PvIN7V@bCt9o^z!nkvc#D@^S_*B!@q1gMu-mU(=MB#`{D& z{4PHwqIGoRwwiVUHA{T}d!-!8eatE&zv4fQ$(gh13>TTHX5 z<0PI0tQrImKI)t?I*NT6>1q*u z)E6N{wD^kkaOJKFgoF|OgFX9i8=tZ$ZKR~&x3foFKE$&jAJmc>2Yg_V0Fwg)e$S_& zCTst6_PKmU6IKO|+o!8|I}cp&Jzu05R&ao#q1O(Z0g@&q&R2rc_;^&1E*(u)zz|U_ z7x^o1`pk)*ljj#^g{}!?lAmX;!nNQ6SQq8n^r5eUgJ(KBe8fCITe*bivY0yMui?^s zx*XBkN|?6mDm)*~!1Ws3t-26t1)~=|&G(?FOC4RpMotPM_J!F~YiTOzd%rVzXhr&C zJ4`Bt<(ExIYq1y{IT^of$xO$bu)|S_Y2N6;-g#pQD+S)Wxbr?QO9+AX!}I8){LSPf zaRVV(q^1Lm%)H)VE6+<*2o&D>*a{Dtt~2N6BX)Q1E8oA&y-34Dp`DW_Tl~g}MMuTD ziv0#AGZLwEC@8xnokr#vOm^$m}|;ZhD0rAw&b zDocJmO%%;+`}ME2DqxOxIb!L!wMOS(JjNtYk=70}d)EBr@LsK9))M@Sq?Ab+GL{snJb2 z4=Z&YE)WP_FpRdaQN?-Z`07f?vV5=Mcx>x@-){gZnNMb&RU5ZV=uPgjDvsCP`s>O{yd+|KDPbue{$yNm4^nq3r!ih<#bRv(qzAe0bla`8JE z76-*z%F%V-#GgMQvhsS$+n&Un_%*El>~3z1EW3=AeC0H<&moe?P3?@HNb8!{tI&69 zga@tFPzvV#X-!U!@Zm)MSwofbb5-bf3A?dFCQ1m9$fkoSk6tk#5^SzJ?LT;jV)5~a z8RYQc?61epuw*f~C1PjvE?>bXJeIr_ID zC9#lrO=b%|EH^WugQa!bLnPI==;aclg#S&<2Y%AFIm71-U8pXw68<84C z(hh?+^p=-zSeEcHRSR}7k(D^P&&v*ePMh;hn(~*}rsv>yCDT0v{~>BK1m;;bs82-ngP% zI0|DHS+>FE+M4j8fX@P+@y&<$>CNNKLoQ9@*K`S_lfH@kt!!V?$%}lPZt-`8Hvd?3 z$ay}TaD;-7VsKHp62Wx7x-JoAj&QT>^mMcA-_qdNONBpQTe;uG1^MvEvH6OQL{*P~ zqR_|OFyz3jz`4WR%9=PV730f|1DaZblFYn?#pkMXYZB4krF|~pDYA8J8#FB z6vBY|OtS(u{<44Vgz$pC{B^X4gJV?mR;T5mS*;cW!_>f3gcR=RY_sf*-Vo6 zF=CF<5W=n-gmBjHnzRsDb~dDT@N789GM;*PCdMmsolm?hJ8y3h*I?e{RP^*Rm!0O! z=Y&V`o>D|nT(k-$F0lO33?L(vOp~) z!KUBTK%zVdrFEE?htgN0EP3+T9r=Qdfs8rWLv-+uRrPz8?)HJh>x=QPR{AxZiA-eS zO{eK|rw+9QG+*=OZkiaKOikGzFA4|fiiLCK|K_VO^Rh;UEg_Vrcm15utGMhi4uC_F z+{*aZl;*R5f&Xt!xi{~Y*Ut81^oDmom$s-L^oL*=&-N|*U>F?u3 zs#W=ci$-{Cw0M#~8pCyX9}z5ADVSBXM`!F5K9^XKl{H6cH7MO3C>DSzS=o?4w(`Z& zBNqCSr0_Andjs8Tr36#EoXbZ10%NJk8=t_(Hw=qs*WfD0S$Vm&mULQZ_iyD@nGuaB zv2#~3+(PMR;bq28o1VdplQxg-WyoNMC3ZaVnm3mw(S~1U@jMs|8B;`gfbF=oTQ-Me z=&Ff0BaK~#zW4hlfub`OyR7#Ba6LV-)@$QEwSk1-P{hqk@!lw}_NTmvnc7 zba%IOi3mu8bf0d{RZFpRABZ$catQolBfac0 z`bzp7dxJ)`mSX=>A&)e*#9q1L2{akL4jFslqsLEI7rH9=irhb!Q+wEC5);GhU3mp= z6l9?}!h`K&8u7qb4tFgXS9=aE$$$;^pE9JLr{a{oL5>re8+R8{LjXni-KVjd;WDIV z_Ahr*Yc#TF5;0`5<(+$P#*-Y(Iue(vb*m`o&Kw($TU9!LYE8LSS--Q*RioV;ltkX# zZRHP9Vi?8W9XWvag-u&P>Om6_2%p;9xGT;#0N|0zD8{FPOO=MX%sg;3FLQC3)HpMi z;21~8##a`t3dU@5e|Jycx_Mo%=$_j|x#{VF5grEP+0!&3DD0S6>tU@*5?`fczA6RR zMirfEt4D5^)<}397Jn?$PigmCxua%msS92TmN)S6Lc3mK32QK>u(Yu?zr1?cqT&3e zK}Y=TJB^d|kUKVu(KjD>zLkl^`QchVu`UQ~Gvgpa_y3=WD_&K*c;&|m@ zoB@c_X%4f+B*ismNq$R&x!#KZz~Lr@bLc%)NBPJAXU%M3AxD+F{P>S_5&NFJpg*oE zq?FWzQsG3mrYzv*K>;$HKdi;ye(z%3>`g5>Gs7#lYdGZi=Nw1_WK7`piTC0!tM-%% z=C>aq7seCA@5*#yxOU179Ub}n9-!MW4_9@?KZx3(mFJRN@0jRVJq7DdPs5(qB#g~5 zR*iG!#{2z9{a(H-Fy@hXkvp}u3e*AFV>AtS;~|2OEkl9agwd?Ezy&Zu9AIIZOx7Ej z135IxQx=BHH>`O3Z-UjaEp4kNEbNZopf6b3RF0X{j+xjMG}NTWQnUA(zVz*htYD&` zg?%1g9o@;zUbLYspB|hogb@`AYF_GZ3ZH#3;-E^qxmdv#;5JPH9b%u;X|#BAz4$4% zz7S^lah)lOw;|}>E<>)kdstncta~PFtG#jC_|l!W&}OUi5UvoLWxZ1tfIb*xR>DgP z=%^L0GW>RRi2w!(*HHB`Q>LM}MV&ri=-9|L^z1qLU_vQE{a?ui0b7I4aOTsaGilSo zvm#Eq{xLRpPS|Z{tbl0lSlYhIzvV|Hp&zfz{cOrcJOLJA+X61rZkU4k!`HALvD2$* z-j;d&ejHY;5sMmY8|!UFN0I?*NcQK8r+3TKM;p+oxsv6yCGIt1sMo%8{DlaQbC6WI-SixPS;9Xd*-n1_h>hZyrhiRE6=#DjbU7X z9=hF1e$;~;Uj3mfPIHtZ$M?B=_Q}t#A@Pch`1&3T#`m>;N@P+DT>I&n`1-p?gj3Ee zLO~cdW&WoJ1faRGE>HVDR@l8bFK=3toUF1QMDp=A^$YCHF6~Exbh&Z4QdeSmw6y@6 zU_3Dl>&DoggtFC&$5gAX1lJU;1qBazq?bwF)v!s`@5SL)?I*#l?ef5Eb$U5=F@Khd zzNuhk0z>5dVeV|cRcdN)&cJ?cChD0Wz|dg3^mA{6oz&}N``)$E8c4mTA@{&`0VdWO zL_mL`T|Z;x>%wNcMEQCQd?M!9EvuQ66OCG97*ur#TaDvg^{qgROAUY^Wr2l zm5nqiu^iB{#)_=wo)1~13r~aT=yGA*!`ll;OnXy#5oaUBQX~KCu0&XT<~s#K2D^Cs(vz0e?(f zc^QK#Af{PNgB&$knPpVJ7X$U1xjH(j!CNlyWlq8B5V?_V2QWsBnmI-jlXXR?%MzZw z``!`Fw2`JJ5}DL=92r*0U31c{aH-0s$3CHHn_=U%52@U>M*#^S4gG|a2)bibG3e=)3Qj*Y6gJf0^4z%b6TmXh3Gymb}0UoSRdJdP;4 z;lUtzfa?j7W3&a9rz329a;>D_G&{Q+b1Az)F%JP|ku?Irs^?=cf z@t6ER-*w8}+*yeGjL9VSSsEU2YqihwbuU&_Q;Z(izRslyZF*SdcS5p8j6gJKzxeJO zRj%Bx`H3evO5NO)muoj!EbfEiNvMPC)E|1YGfIm2 z(|*gq6w9(*y!us>ZG&vjHEv#Z+`x^43IkVQjrUzQ#zQ#a_)n3!Oxtqw|l&+{-WJ`!`GJBUytAqOJ+gmKdkXZx=d?1`-`M zYZ5c27C;yjrqs${x(uTC<@WJxC{9%@*L=gtW`Zh~WaNplaBg5ZY8;TluvJ^ZY5$?? z4M%?0>%RA~ub=Rr!t-k~X z0t7~{tojTsXC8Gqg*NqKqs>Qw?%gv7&FviI^n9e?2|1hkklEM{X(eoCZQ><=W0%~( z{yPp-yvZ*krIXfiE3lFNBz|alLw}o>`n)oUMSuNt9>Q7q*wsf{C{&<|$r^sxNiD-| zi3&A%*^`0$o2|CmZBU5UG6ty)KAyfX?(ArK^9I51fhVBT|D!S&5s22P^Ls{);=9M4 zuy2Zhn_&H5a9%S(9V!liYngRqHo>A9Npse-u1Jr@TBWZfMH7fExGHuPJg=QsAse`=l3E z`0;|`i7Fh#;^gB%Z?1#k-8aK1yq`m*@T<*-RpY}^|Az=v45jf!aMtp+D;(dwQr*Y4 zI50Oq3elbWPVqZ!`p#kbIWLW_jMn7pV2n(M@n7HJ&#cX@SCUzd6Al9u9i~-3Z`_R; zZhxWVb-iZcr1-XHMyG$kNX{_}AH2{R9{a6Yq-qeNeRQ?3v&O9+TV8sF0!fkox_j6KF`!*PHV2s$C_toO1Qeh z`TBB``aSHufTsnw##*sDYgwk;05#$Kthx@QACdXS^)*dI>0wtUTbN3*l96-$NPXE` zgd}e^@X5=V>^Q!1w*=fjd=z^Gu9NiMT(au2Bj1k3xRdfPW67`nFuAo}N1Fxu=7x5* z+g^#XZLQ8ng-dHW^(8Tb%ot0FL}m3fen5uY&Y7 zsFdt3G}U&6n_%fk=HWNfh)**QQ!6%|PxC^no7ppYqRyFdTOlz7q4Ng>;MOT*CTxeisjp31YFjN%3bs#wG> z*n3Q@1DU5aESSOM6kHuqy@Ht-)>E7os*ANBVz&i&+xGQM9U+uh z!+Q^7$1MNbD?bnr5!Y%)p1KDZo7#C4N<{R~d90?w-|3|}cI!NKYA&9y3b?QO*WIoL zJU*<#m;dp+1aa4qgN@MtAPyNo%HJR>=oVS*eaGr!gY6ZicG8!xL)v1A3v$!K3cAkk z@^!3INm9^2!NOBcm|GsS<2!FBq3mh?OGRD}iL+0g@k13F{pNbIaqS`bOB zfy8X^1LWu?e~5clUm;ow@>dsfigvoWjsry(1F9k#nj*+P&WJ@+Sy53=ZEZqcUfv5v zDlU&0X_GjzUsGnwkKDyo@eRjfAEcNc8I{3?tYii6V@S5h9Y2pc(5;!elrB9V7pO8* zGbB-ION`!V%2W0U@#nq1BxWmHP-}Z$o|m(TMiXeXMU?;z6F5tCK;arvnb!q>x+5Y3 z1cf9`*P9s90Gi#Ow|qrdXHdyK`={zhp#v6YNv|k6ETQ%S=xy?|{)7ZTtjCJ5-v_zb zhxCnMX(uzyDuLqg3bfEUuKu`XFjUtNo7N41U4CZ0wSy#;07iDe^XVDQd;C&RDsp26eWO6YB}Ur(>!(?<52_KkurGvPiM#IKTd)#L64N@SojUrZ zhc=wHv&|C|molG&twbx-lK1*HYwr!=jLk6gm)kWa?!f>B8bkX^p0U!`7lArGL64O6 zi+Z?nA)OcDNVxgc< zQ%eo#=r=?9kb3JbK@RSL8$~Qo33ml2E2352F>z1!vWG!Vw)SiQ-Q8Bi)wk`#z8Cm^ z^u)Tbu<*?_&vRB~Wz6=|mB3Z`NO#I%*f4wb^scK1MG7;$tX6cdPwRt#u&}%jyiT#| z>3UdQrOh0ciMjeon10g;0GJpbG5>)o+Zx4Fj(T>{M^Yvg{(t1i-hL96LY8blbg8o6 zr>5zFJqdJ!lW@Z!hqr4o!j##f%EfQfsal(NtO&1b{UqxhCvdGJKyrwlSVc@OCjILzGyji=4sM&nVe-ISkxCOQUM@-$z)8ju;E6UabqhQ-27(7NbCEBqmkCQg zG1#m)z+hr^VLlNw(GBXgRi;%(Ya|jl~=FgI|7g>2`Ypnc|wV-37X29#=mrk5M zrP$kW>80``>|%Qg?fU#4$Q~bw%$N*iMWePiPd#s~d{DVd|IBPv5HKe>Lyo za)N>|t@o{&&`ZzTi%!PbKb~kP)Prnsbz^$JMJ-PyLh>8q=fj9NQPcj4Ph!Y_%kf4G zKQrv<(DXk3JD^14`D{+dGMXXU+M4MI&8de*Hkj|1{o}jy;LXCIO&P83 zfBg7Pd0DZOZ*IR-^U!Tdn+3_4>R*u~Jw`J5_PE<=C2vJQrW zmqoNo1Dbo<3oj4|J7%2szFRClmu$IRKW6yRUeptlR*O^mBR+XoR^kYap4~ua&__Fa zmX<+)c+S$A*-_W>tLU^)Dx@OqdLt{|lnLRyplR0!AGU(QPm@-0?oIFH6U{Y7GW~Ci z4wX{0Z9Z!A0_#ZxWUo!4ya$R?SsQPBGLJ)2i?t3mAnZr#@Yb)~8{AznftY^z0`^^}EbslEYlgQYT_WSq>UcMSc{MrNU{Myp zGgW1J-dK=F%9onx=%7Q_zd6+NV$W17f`+??f?C5XEAEFN*-wfGQ2lg%YU3<73ymMUWJQp9bhT}72d3$DrE z_I4eF<;VW~`OPLepv`W<>_B~Ak=~8KUIC+429DkFqWD3X%>Ff1U?xBj*aLT?2dGGIRZ8Ic$!e4tH&ZE zagaCb|5fn)Y;8L_R^NFVbn;(e_&8EypS>$GJGoRp0&!JNEN(mSV4aK=jiR!+V~K%d zc7v~aoPaTz5jlIy@f(?D1={wOj>7mBHi2OXf0DV5>>~yFc+|;i1|DRxrnZW{JjKIu z4fe7^wlI6jSK5nhRF~PRsxb(M2?%lfgut zZTTk}!_PGVC-Oa6DU#6F1mBlE3=4I56@Y`nFcintR(WAz~+YSVt;rjSXIxXZlM2I!oMlhS8{G@)^CBDvgW9 z#Szr{32;xXtLEe*%87C;|T7B{#Q^J|WS*A^-eRRl{_l)tV$X zdT(*Ub0(1a(u!oG4HaoMnJFXDT(L0;4Bql_8+;iS!oIbV;n%kvGWXWPuhV7rm>od< zP&CArx{xfuXZU^C$zfcDJ0WsoBfXg`9OlEXmtd5A)l~cJg@axF!KCI77qf-v`P}Eb z#)8@BOkCN>dRG1dLAg*jD%;>Nu8M2)*nCu*CnF(EiW)h!gc13p({td+We-+}#2&|`78!%;LUzz&D>mL-S>S)f{{g9$E9

    %hL-)nC_& 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

    |4OP<^ML!Hd*wuzGV5H|3MTQFj3mX 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 z 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

    &`<~j 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

    7O%LXH%dU3`;r)z?YFvI5Ta3SfmxF0M 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 From cba406e7e88d7e50e840503a8609886b120fd124 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Jan 2022 11:01:03 +0100 Subject: [PATCH 0878/1892] chore: bumped C core --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 2fe864088..f5745c3ac 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2fe8640888d19c146e4c8970478a3485a3e485e3 +Subproject commit f5745c3ac8f9ef031b575af3a6d256dd7f4cf44f From 6e077ea14d67f78c034c76e679ae76ba108b76b0 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 07:43:36 +1100 Subject: [PATCH 0879/1892] Coding and wording styles --- .../betweenness/assets/betweenness.py | 68 ++++++++------- .../tutorials/betweenness/betweenness.rst | 80 +++++++++--------- .../betweenness/figures/betweenness.png | Bin 240448 -> 114355 bytes 3 files changed, 71 insertions(+), 77 deletions(-) diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/source/tutorials/betweenness/assets/betweenness.py index 2a941acc4..fc2cd8c99 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/source/tutorials/betweenness/assets/betweenness.py @@ -1,11 +1,20 @@ -import igraph as ig +import random import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable from matplotlib.colors import LinearSegmentedColormap, Normalize -import random +import igraph as ig + + +def plot_betweenness(g, ax, cax1, cax2): + '''Plot vertex/edge betweenness, with colorbars + + Args: + g: the graph to plot. + ax: the Axes for the graph + cax1: the Axes for the vertex betweenness colorbar + cax2: the Axes for the edge betweenness colorbar + ''' -def plot_betweenness(g, fig, ax): - # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 vertex_betweenness = g.betweenness() edge_betweenness = g.edge_betweenness() @@ -14,54 +23,43 @@ def plot_betweenness(g, fig, ax): print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") - # Define color bars + # Define mappings betweenness -> color cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) - # Create normalising objects to scale the color bars correctly - norm1 = Normalize() - norm1.autoscale(vertex_betweenness) - norm2 = Normalize() - norm2.autoscale(edge_betweenness) - - # Create new axes for color bars - cax1 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.05, ax.get_position().width, 0.03], in_layout=True) - cax2 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.20, ax.get_position().width, 0.03], in_layout=True) - - plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), cax=cax1, orientation="horizontal") - plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), cax=cax2, orientation="horizontal") - - # Add labels for color bars - mid = (ax.get_position().x0 + ax.get_position().x1) / 2 - fig.text(mid, 0.3, 'Vertex Betweenness', ha='center') - fig.text(mid, 0.15, 'Edge Betweenness', ha='center') - # Plot graph g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) - ig.plot( - g, - target=ax, + g, + target=ax, layout="fruchterman_reingold", vertex_frame_width=0.2, ) + # Color bars + norm1 = ScalarMappable(norm=Normalize(0, max(vertex_betweenness)), cmap=cmap1) + norm2 = ScalarMappable(norm=Normalize(0, max(edge_betweenness)), cmap=cmap2) + plt.colorbar(norm1, cax=cax1, orientation="horizontal", label='Vertex Betweenness') + plt.colorbar(norm2, cax=cax2, orientation="horizontal", label='Edge Betweenness') + + # Generate Krackhardt Kite Graphs and Watts Strogatz graphs random.seed(0) g1 = ig.Graph.Famous("Krackhardt_Kite") g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) -# Plot the graph -fig, axs = plt.subplots(1, 2, figsize=(10, 8)) -plt.subplots_adjust(bottom=0.3) -plot_betweenness(g1, fig, axs[0]) -plot_betweenness(g2, fig, axs[1]) - -# Add "a" and "b" labels for panels -fig.text(0.05, 0.9, 'a', va='top') -fig.text(0.55, 0.9, 'b', va='top') +# Plot the graphs, each with two colorbars for vertex/edge betweenness +fig, axs = plt.subplots( + 3, 2, + figsize=(7, 6), + gridspec_kw=dict(height_ratios=(20, 1, 1)), + ) +#plt.subplots_adjust(bottom=0.3) +plot_betweenness(g1, *axs[:, 0]) +plot_betweenness(g2, *axs[:, 1]) +fig.tight_layout(h_pad=1) plt.show() diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index f1dd65ec0..9f76e8dc9 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -11,24 +11,34 @@ Betweenness .. _edge_betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#edge_betweenness .. |edge_betweenness| replace:: :meth:`edge_betweenness` -This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. First we import the relevant libraries +This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. + +First we import |igraph| and some libraries for plotting et al: .. code-block:: python - import igraph as ig + import random import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable from matplotlib.colors import LinearSegmentedColormap, Normalize - import random + import igraph as ig .. _rescale: https://igraph.org/python/doc/api/igraph.utils.html#rescale .. |rescale| replace:: :meth:`rescale` -Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s |rescale|_ as a great way to linearly scale all data into ranges we can work with. +Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s |rescale|_ to rescale the betweennesses in the interval ``[0, 1]``: .. code-block:: python - def plot_betweenness(g, fig, ax): + def plot_betweenness(g, ax, cax1, cax2): + '''Plot vertex/edge betweenness, with colorbars + + Args: + g: the graph to plot. + ax: the Axes for the graph + cax1: the Axes for the vertex betweenness colorbar + cax2: the Axes for the edge betweenness colorbar + ''' # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 vertex_betweenness = g.betweenness() @@ -37,43 +47,29 @@ Next we define a function for drawing a graph on an Matplotlib axis. We set the scaled_edge_betweenness = ig.rescale(edge_betweenness, clamp=True) print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") - - # Define color bars + + # Define mappings betweenness -> color cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) - - # Create normalising objects to scale the color bars correctly - norm1 = Normalize() - norm1.autoscale(vertex_betweenness) - norm2 = Normalize() - norm2.autoscale(edge_betweenness) - - # Create new axes for color bars - cax1 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.05, ax.get_position().width, 0.03], in_layout=True) - cax2 = fig.add_axes([ax.get_position().x0, ax.get_position().y0-0.20, ax.get_position().width, 0.03], in_layout=True) - - plt.colorbar(ScalarMappable(norm=norm1, cmap=cmap1), cax=cax1, orientation="horizontal") - plt.colorbar(ScalarMappable(norm=norm2, cmap=cmap2), cax=cax2, orientation="horizontal") - - # Add labels for color bars - mid = (ax.get_position().x0 + ax.get_position().x1) / 2 - fig.text(mid, 0.3, 'Vertex Betweenness', ha='center') - fig.text(mid, 0.15, 'Edge Betweenness', ha='center') - + # Plot graph g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) - ig.plot( - g, - target=ax, + g, + target=ax, layout="fruchterman_reingold", vertex_frame_width=0.2, ) - + # Color bars + norm1 = ScalarMappable(norm=Normalize(0, max(vertex_betweenness)), cmap=cmap1) + norm2 = ScalarMappable(norm=Normalize(0, max(edge_betweenness)), cmap=cmap2) + plt.colorbar(norm1, cax=cax1, orientation="horizontal", label='Vertex Betweenness') + plt.colorbar(norm2, cax=cax2, orientation="horizontal", label='Edge Betweenness') + Finally, we call our function with the two graphs: .. code-block:: python @@ -82,17 +78,17 @@ Finally, we call our function with the two graphs: random.seed(0) g1 = ig.Graph.Famous("Krackhardt_Kite") g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) - - # Plot the graph - fig, axs = plt.subplots(1, 2, figsize=(10, 8)) - plt.subplots_adjust(bottom=0.3) - plot_betweenness(g1, fig, axs[0]) - plot_betweenness(g2, fig, axs[1]) - - # Add "a" and "b" labels for panels - fig.text(0.05, 0.9, 'a', va='top') - fig.text(0.55, 0.9, 'b', va='top') - + + # Plot the graphs, each with two colorbars for vertex/edge betweenness + fig, axs = plt.subplots( + 3, 2, + figsize=(7, 6), + gridspec_kw=dict(height_ratios=(15, 1, 1)), + ) + #plt.subplots_adjust(bottom=0.3) + plot_betweenness(g1, fig, *axs[:, 0]) + plot_betweenness(g2, fig, *axs[:, 1]) + fig.tight_layout(h_pad=1) plt.show() The final output graphs are as follows: @@ -101,7 +97,7 @@ The final output graphs are as follows: :alt: A graph visualizing the betweenness of each vertex and edge. :align: center - Graph visualizing edge betweenness (a) in a Krackhardt Kite graph and (b) in a 150 node Watts-Strogatz graph. The edge betweenness is shown in blue, and the vertex betweenness is shown in purple. + Vertex and edge betweenness in a Krackhardt Kite graph (left) and in a 150 node Watts-Strogatz graph (right). Edge betweenness is shown in shades of blue and vertex betweenness in shades of purple. and the output for betweennesss is as follows: diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png index 612c2843d3d9203347f2248b2807d524ab181cc5..b411178047762446780ffbe7d96b19a558572a12 100644 GIT binary patch literal 114355 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

    G(Y$#Y@6|420Iyra#?}6rWQ+%zShZ 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 z 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 literal 240448 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

    %hL-)nC_& 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 Date: Wed, 12 Jan 2022 08:14:43 +1100 Subject: [PATCH 0880/1892] Typo in edge label alignment in some matplotlib cases --- src/igraph/drawing/matplotlib/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 7dc824b8a..6673929ff 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -297,7 +297,7 @@ def draw(self, graph, *args, **kwds): text_kwargs = {} text_kwargs['ha'] = halign.value - text_kwargs['va'] = halign.value + text_kwargs['va'] = valign.value if visual_edge.background is not None: text_kwargs['bbox'] = dict( From 978656087ef3024626f5a0b1da96f83da8de5ae7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:13:31 +1100 Subject: [PATCH 0881/1892] Add Gemfile.lock --- .gitignore | 1 - doc/jekyll_tools/Gemfile.lock | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 doc/jekyll_tools/Gemfile.lock diff --git a/.gitignore b/.gitignore index 8bf34132f..ef7ad00fd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,4 @@ vendor/install/ doc/source/gallery.rst doc/api/ doc/html/ -doc/jekyll_tools/Gemfile.lock doc/jekyll_tools/vendor diff --git a/doc/jekyll_tools/Gemfile.lock b/doc/jekyll_tools/Gemfile.lock new file mode 100644 index 000000000..710e3df51 --- /dev/null +++ b/doc/jekyll_tools/Gemfile.lock @@ -0,0 +1,74 @@ +GEM + remote: http://rubygems.org/ + specs: + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) + colorator (1.1.0) + concurrent-ruby (1.1.9) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.15.4) + forwardable-extended (2.6.0) + http_parser.rb (0.8.0) + i18n (1.8.11) + concurrent-ruby (~> 1.0) + jekyll (4.2.1) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (~> 2.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (~> 0.4.0) + pathutil (~> 0.9) + rouge (~> 3.0) + safe_yaml (~> 1.0) + terminal-table (~> 2.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-sass-converter (2.1.0) + sassc (> 2.0.1, < 3.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + kramdown (2.3.1) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.3) + listen (3.7.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.6) + rb-fsevent (0.11.0) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.5) + rouge (3.27.0) + safe_yaml (1.0.5) + sassc (2.4.0) + ffi (~> 1.9) + terminal-table (2.0.0) + unicode-display_width (~> 1.1, >= 1.1.1) + unicode-display_width (1.8.0) + webrick (1.7.0) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + jekyll-redirect-from + jekyll-sitemap + webrick (~> 1.7) + +BUNDLED WITH + 2.2.26 From cf057da4848349045ffa1272508a7d1d2f054d89 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:21:21 +1100 Subject: [PATCH 0882/1892] Remove useless fonts and CSS --- doc/jekyll_tools/_layouts/default.html | 1 - doc/jekyll_tools/css/epydoc.css | 291 ---- doc/jekyll_tools/css/manual.css | 75 - .../fonts/font-mfizz/font-mfizz.css | 318 ---- .../fonts/font-mfizz/font-mfizz.eot | Bin 43154 -> 0 bytes .../fonts/font-mfizz/font-mfizz.svg | 1344 ----------------- .../fonts/font-mfizz/font-mfizz.ttf | Bin 45324 -> 0 bytes .../fonts/font-mfizz/font-mfizz.woff | Bin 29056 -> 0 bytes 8 files changed, 2029 deletions(-) delete mode 100644 doc/jekyll_tools/css/epydoc.css delete mode 100644 doc/jekyll_tools/css/manual.css delete mode 100644 doc/jekyll_tools/fonts/font-mfizz/font-mfizz.css delete mode 100644 doc/jekyll_tools/fonts/font-mfizz/font-mfizz.eot delete mode 100644 doc/jekyll_tools/fonts/font-mfizz/font-mfizz.svg delete mode 100644 doc/jekyll_tools/fonts/font-mfizz/font-mfizz.ttf delete mode 100644 doc/jekyll_tools/fonts/font-mfizz/font-mfizz.woff diff --git a/doc/jekyll_tools/_layouts/default.html b/doc/jekyll_tools/_layouts/default.html index a88d03a06..ad0de6836 100644 --- a/doc/jekyll_tools/_layouts/default.html +++ b/doc/jekyll_tools/_layouts/default.html @@ -21,7 +21,6 @@ - diff --git a/doc/jekyll_tools/css/epydoc.css b/doc/jekyll_tools/css/epydoc.css deleted file mode 100644 index 41c59516e..000000000 --- a/doc/jekyll_tools/css/epydoc.css +++ /dev/null @@ -1,291 +0,0 @@ - -/* Page Header & Footer - * - The standard page header consists of a navigation bar (with - * pointers to standard pages such as 'home' and 'trees'); a - * breadcrumbs list, which can be used to navigate to containing - * classes or modules; options links, to show/hide private - * variables and to show/hide frames; and a page title (using - *

    ). The page title may be followed by a link to the - * corresponding source code (using 'span.codelink'). - * - The footer consists of a navigation bar, a timestamp, and a - * pointer to epydoc's homepage. - */ -h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; - margin-top:30px; } -h2.epydoc { font-size: +130%; font-weight: bold; } -h3.epydoc { font-size: +115%; font-weight: bold; - margin-top: 0.2em; } -td h3.epydoc { font-size: +115%; font-weight: bold; - margin-bottom: 0; } -table.epynavbar { background: #a0c0ff; color: #000000; - border: 2px groove #c0d0d0; } -table.epynavbar table { color: #000000; } -th.navbar-select { background: #70b0ff; - color: #000000; } -table.epynavbar a { text-decoration: none; } -table.epynavbar a:link { color: #0000ff; } -table.epynavbar a:visited { color: #204080; } -span.breadcrumbs { font-size: 85%; font-weight: bold; } -span.options { font-size: 70%; } -span.codelink { font-size: 85%; } -td.footer { font-size: 85%; } - -/* Table Headers - * - Each summary table and details section begins with a 'header' - * row. This row contains a section title (marked by - * 'span.table-header') as well as a show/hide private link - * (marked by 'span.options', defined above). - * - Summary tables that contain user-defined groups mark those - * groups using 'group header' rows. - */ -td.table-header { background: #70b0ff; color: #000000; - border: 1px solid #608090; } -td.table-header table { color: #000000; } -td.table-header table a:link { color: #0000ff; } -td.table-header table a:visited { color: #204080; } -span.table-header { font-size: 120%; font-weight: bold; } -th.group-header { background: #c0e0f8; color: #000000; - text-align: left; font-style: italic; - font-size: 115%; - border: 1px solid #608090; } - -/* Summary Tables (functions, variables, etc) - * - Each object is described by a single row of the table with - * two cells. The left cell gives the object's type, and is - * marked with 'code.summary-type'. The right cell gives the - * object's name and a summary description. - * - CSS styles for the table's header and group headers are - * defined above, under 'Table Headers' - */ -table.summary { border-collapse: collapse; - background: #e8f0f8; color: #000000; - border: 1px solid #608090; - margin-bottom: 0.5em; } -td.summary { border: 1px solid #608090; } -code.summary-type { font-size: 85%; } -table.summary a:link { color: #0000ff; } -table.summary a:visited { color: #204080; } - - -/* Details Tables (functions, variables, etc) - * - Each object is described in its own div. - * - A single-row summary table w/ table-header is used as - * a header for each details section (CSS style for table-header - * is defined above, under 'Table Headers'). - */ -table.details { border-collapse: collapse; - background: #e8f0f8; color: #000000; - border: 1px solid #608090; - margin: .2em 0 0 0; } -table.details table { color: #000000; } -table.details a:link { color: #0000ff; } -table.details a:visited { color: #204080; } - -/* Fields */ -dl.fields { margin-left: 2em; margin-top: 1em; - margin-bottom: 1em; } -dl.fields dd ul { margin-left: 0em; padding-left: 0em; } -dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; } -div.fields { margin-left: 2em; } -div.fields p { margin-bottom: 0.5em; } - -/* Index tables (identifier index, term index, etc) - * - link-index is used for indices containing lists of links - * (namely, the identifier index & term index). - * - index-where is used in link indices for the text indicating - * the container/source for each link. - * - metadata-index is used for indices containing metadata - * extracted from fields (namely, the bug index & todo index). - */ -table.link-index { border-collapse: collapse; - background: #e8f0f8; color: #000000; - border: 1px solid #608090; } -td.link-index { border-width: 0px; } -table.link-index a:link { color: #0000ff; } -table.link-index a:visited { color: #204080; } -span.index-where { font-size: 70%; } -table.metadata-index { border-collapse: collapse; - background: #e8f0f8; color: #000000; - border: 1px solid #608090; - margin: .2em 0 0 0; } -td.metadata-index { border-width: 1px; border-style: solid; } -table.metadata-index a:link { color: #0000ff; } -table.metadata-index a:visited { color: #204080; } - -/* Function signatures - * - sig* is used for the signature in the details section. - * - .summary-sig* is used for the signature in the summary - * table, and when listing property accessor functions. - * */ -.sig-name { color: #006080; } -.sig-arg { color: #008060; } -.sig-default { color: #602000; } -.summary-sig { font-family: monospace; } -.summary-sig-name { color: #006080; font-weight: bold; } -table.summary a.summary-sig-name:link - { color: #006080; font-weight: bold; } -table.summary a.summary-sig-name:visited - { color: #006080; font-weight: bold; } -.summary-sig-arg { color: #006040; } -.summary-sig-default { color: #501800; } - -/* Subclass list - */ -ul.subclass-list { display: inline; } -ul.subclass-list li { display: inline; } - -/* To render variables, classes etc. like functions */ -table.summary .summary-name { color: #006080; font-weight: bold; - font-family: monospace; } -table.summary - a.summary-name:link { color: #006080; font-weight: bold; - font-family: monospace; } -table.summary - a.summary-name:visited { color: #006080; font-weight: bold; - font-family: monospace; } - -/* Variable values - * - In the 'variable details' sections, each varaible's value is - * listed in a 'pre.variable' box. The width of this box is - * restricted to 80 chars; if the value's repr is longer than - * this it will be wrapped, using a backslash marked with - * class 'variable-linewrap'. If the value's repr is longer - * than 3 lines, the rest will be ellided; and an ellipsis - * marker ('...' marked with 'variable-ellipsis') will be used. - * - If the value is a string, its quote marks will be marked - * with 'variable-quote'. - * - If the variable is a regexp, it is syntax-highlighted using - * the re* CSS classes. - */ -pre.variable { padding: .5em; margin: 0; - background: #dce4ec; color: #000000; - border: 1px solid #708890; } -.variable-linewrap { color: #604000; font-weight: bold; } -.variable-ellipsis { color: #604000; font-weight: bold; } -.variable-quote { color: #604000; font-weight: bold; } -.variable-group { color: #008000; font-weight: bold; } -.variable-op { color: #604000; font-weight: bold; } -.variable-string { color: #006030; } -.variable-unknown { color: #a00000; font-weight: bold; } -.re { color: #000000; } -.re-char { color: #006030; } -.re-op { color: #600000; } -.re-group { color: #003060; } -.re-ref { color: #404040; } - -/* Base tree - * - Used by class pages to display the base class hierarchy. - */ -pre.base-tree { font-size: 80%; margin: 0; } - -/* Frames-based table of contents headers - * - Consists of two frames: one for selecting modules; and - * the other listing the contents of the selected module. - * - h1.toc is used for each frame's heading - * - h2.toc is used for subheadings within each frame. - */ -h1.toc { text-align: center; font-size: 105%; - margin: 0; font-weight: bold; - padding: 0; } -h2.toc { font-size: 100%; font-weight: bold; - margin: 0.5em 0 0 -0.3em; } - -/* Syntax Highlighting for Source Code - * - doctest examples are displayed in a 'pre.py-doctest' block. - * If the example is in a details table entry, then it will use - * the colors specified by the 'table pre.py-doctest' line. - * - Source code listings are displayed in a 'pre.py-src' block. - * Each line is marked with 'span.py-line' (used to draw a line - * down the left margin, separating the code from the line - * numbers). Line numbers are displayed with 'span.py-lineno'. - * The expand/collapse block toggle button is displayed with - * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not - * modify the font size of the text.) - * - If a source code page is opened with an anchor, then the - * corresponding code block will be highlighted. The code - * block's header is highlighted with 'py-highlight-hdr'; and - * the code block's body is highlighted with 'py-highlight'. - * - The remaining py-* classes are used to perform syntax - * highlighting (py-string for string literals, py-name for names, - * etc.) - */ -pre.py-doctest { padding: .5em; margin: 1em; - background: #e8f0f8; color: #000000; - border: 1px solid #708890; } -table pre.py-doctest { background: #dce4ec; - color: #000000; } -pre.py-src { border: 2px solid #000000; - background: #f0f0f0; color: #000000; } -.py-line { border-left: 2px solid #000000; - margin-left: .2em; padding-left: .4em; } -.py-lineno { font-style: italic; font-size: 90%; - padding-left: .5em; } -a.py-toggle { text-decoration: none; } -div.py-highlight-hdr { border-top: 2px solid #000000; - border-bottom: 2px solid #000000; - background: #d8e8e8; } -div.py-highlight { border-bottom: 2px solid #000000; - background: #d0e0e0; } -.py-prompt { color: #005050; font-weight: bold;} -.py-more { color: #005050; font-weight: bold;} -.py-string { color: #006030; } -.py-comment { color: #003060; } -.py-keyword { color: #600000; } -.py-output { color: #404040; } -.py-name { color: #000050; } -.py-name:link { color: #000050 !important; } -.py-name:visited { color: #000050 !important; } -.py-number { color: #005000; } -.py-defname { color: #000060; font-weight: bold; } -.py-def-name { color: #000060; font-weight: bold; } -.py-base-class { color: #000060; } -.py-param { color: #000060; } -.py-docstring { color: #006030; } -.py-decorator { color: #804020; } -/* Use this if you don't want links to names underlined: */ -/*a.py-name { text-decoration: none; }*/ - -/* Graphs & Diagrams - * - These CSS styles are used for graphs & diagrams generated using - * Graphviz dot. 'img.graph-without-title' is used for bare - * diagrams (to remove the border created by making the image - * clickable). - */ -img.graph-without-title { border: none; } -img.graph-with-title { border: 1px solid #000000; } -span.graph-title { font-weight: bold; } -span.graph-caption { } - -/* General-purpose classes - * - 'p.indent-wrapped-lines' defines a paragraph whose first line - * is not indented, but whose subsequent lines are. - * - The 'nomargin-top' class is used to remove the top margin (e.g. - * from lists). The 'nomargin' class is used to remove both the - * top and bottom margin (but not the left or right margin -- - * for lists, that would cause the bullets to disappear.) - */ -p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em; - margin: 0; } -.nomargin-top { margin-top: 0; } -.nomargin { margin-top: 0; margin-bottom: 0; } - -/* HTML Log */ -div.log-block { padding: 0; margin: .5em 0 .5em 0; - background: #e8f0f8; color: #000000; - border: 1px solid #000000; } -div.log-error { padding: .1em .3em .1em .3em; margin: 4px; - background: #ffb0b0; color: #000000; - border: 1px solid #000000; } -div.log-warning { padding: .1em .3em .1em .3em; margin: 4px; - background: #ffffb0; color: #000000; - border: 1px solid #000000; } -div.log-info { padding: .1em .3em .1em .3em; margin: 4px; - background: #b0ffb0; color: #000000; - border: 1px solid #000000; } -h2.log-hdr { background: #70b0ff; color: #000000; - margin: 0; padding: 0em 0.5em 0em 0.5em; - border-bottom: 1px solid #000000; font-size: 110%; } -p.log { font-weight: bold; margin: .5em 0 .5em 0; } -tr.opt-changed { color: #000000; font-weight: bold; } -tr.opt-default { color: #606060; } -pre.log { margin: 0; padding: 0; padding-left: 1em; } diff --git a/doc/jekyll_tools/css/manual.css b/doc/jekyll_tools/css/manual.css deleted file mode 100644 index 4717f7547..000000000 --- a/doc/jekyll_tools/css/manual.css +++ /dev/null @@ -1,75 +0,0 @@ -.search-box-container { - position: relative; - z-index: 15; /* jumbotron is at 10 so we need this higher */ -} -.search-box-container > .row:first-child { - position: absolute; - width: 480px; - top: 0; -} -.search-box-container .search-label { - transform: translateY(3px); -} -.gsc-results-wrapper-overlay { - top: 80px !important; -} - -/* offset the documentation title page from the search bar */ -.titlepage { - margin-top: 80px; -} - -div.example-contents { - display: none; -} -.example p.title { - color: blue; -} -.example p.title b:before { - content: '\25B6\00a0'; -} -.example p.title:hover { - color: #00f; - text-decoration: underline; - cursor: hand; -} - -code { - background: transparent; - color: inherit; - - /* undoing break-word setting from Bootstrap; it messes up the layout of - * argument lists in the R manual */ - word-break: normal !important; -} - -.navigation-header { - text-align: right; -} - -.navigation-footer { - margin: 50px 0; -} - -div.variablelist td { - display: table-cell; - vertical-align: top; -} - -div.variablelist span.term { - padding-right: 10px; -} - -div.authorgroup { - margin-bottom: 50px; -} - -.warning { - background-color: #ffc; - padding: 0.2em 1em; - border: 1px solid #f80; -} -.warning .title { - color: #f80; -} - diff --git a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.css b/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.css deleted file mode 100644 index d7cd91765..000000000 --- a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.css +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Font Mfizz v1.2 - * Copyright 2013 Mfizz Inc, Joe Lauer - * MIT License - * - * Project: http://mfizz.com/oss/font-mfizz - * - * The font designed for technology and software geeks representing programming - * languages, operating systems, software engineering, and technology. - * - * Mfizz Inc - * Web: http://mfizz.com/ - * Twitter: http://twitter.com/mfizz_inc - * - * Joe Lauer - * Web: http://lauer.bz/ - * Twitter: http://twitter.com/jjlauer - */ - -@font-face { - font-family: "FontMfizz"; - src: url("font-mfizz.eot"); - src: url("font-mfizz.eot?#iefix") format("embedded-opentype"), - url("font-mfizz.woff") format("woff"), - url("font-mfizz.ttf") format("truetype"), - url("font-mfizz.svg#font-mfizz") format("svg"); - font-weight: normal; - font-style: normal; -} - -.icon-microscope:before, -.icon-cplusplus:before, -.icon-wireless:before, -.icon-fire-alt:before, -.icon-mobile-device:before, -.icon-objc:before, -.icon-redhat:before, -.icon-freebsd:before, -.icon-heroku:before, -.icon-python:before, -.icon-java:before, -.icon-satellite:before, -.icon-debian:before, -.icon-grails:before, -.icon-c:before, -.icon-postgres:before, -.icon-database-alt2:before, -.icon-raspberrypi:before, -.icon-nginx:before, -.icon-ruby-on-rails:before, -.icon-redis:before, -.icon-scala:before, -.icon-gnome:before, -.icon-perl:before, -.icon-mysql:before, -.icon-fedora:before, -.icon-ghost:before, -.icon-google:before, -.icon-netbsd:before, -.icon-aws:before, -.icon-bomb:before, -.icon-looking:before, -.icon-ruby:before, -.icon-mysql-alt:before, -.icon-playframework-alt:before, -.icon-osx:before, -.icon-database:before, -.icon-database-alt:before, -.icon-shell:before, -.icon-script:before, -.icon-antenna:before, -.icon-coffee-bean:before, -.icon-scala-alt:before, -.icon-platter:before, -.icon-java-duke:before, -.icon-iphone:before, -.icon-script-alt:before, -.icon-google-alt:before, -.icon-haskell:before, -.icon-mariadb:before, -.icon-phone-retro:before, -.icon-phone-alt:before, -.icon-csharp:before, -.icon-php:before, -.icon-postgres-alt:before, -.icon-html:before, -.icon-mfizz:before, -.icon-apache:before, -.icon-hadoop:before, -.icon-ruby-on-rails-alt:before, -.icon-mobile-phone-broadcast:before, -.icon-css:before, -.icon-playframework:before, -.icon-clojure:before, -.icon-mobile-phone-alt:before, -.icon-suse:before, -.icon-java-bold:before, -.icon-nginx-alt:before, -.icon-nginx-alt2:before, -.icon-linux-mint:before, -.icon-dreamhost:before, -.icon-blackberry:before, -.icon-javascript:before, -.icon-ubuntu:before, -.icon-php-alt:before, -.icon-centos:before, -.icon-nodejs:before, -.icon-splatter:before, -.icon-3dprint:before, -.icon-line-graph:before, -.icon-cassandra:before, -.icon-solaris:before, -.icon-jetty:before, -.icon-tomcat:before, -.icon-oracle:before, -.icon-oracle-alt:before, -.icon-mssql:before, -.icon-google-developers:before, -.icon-google-code:before, -.icon-kde:before, -.icon-grails-alt:before { - font-family: "FontMfizz"; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - display: inline-block; - text-decoration: inherit; -} - -.icon-microscope:before { content: "\f100"; } -.icon-cplusplus:before { content: "\f101"; } -.icon-wireless:before { content: "\f102"; } -.icon-fire-alt:before { content: "\f103"; } -.icon-mobile-device:before { content: "\f104"; } -.icon-objc:before { content: "\f105"; } -.icon-redhat:before { content: "\f106"; } -.icon-freebsd:before { content: "\f107"; } -.icon-heroku:before { content: "\f108"; } -.icon-python:before { content: "\f109"; } -.icon-java:before { content: "\f10a"; } -.icon-satellite:before { content: "\f10b"; } -.icon-debian:before { content: "\f10c"; } -.icon-grails:before { content: "\f10d"; } -.icon-c:before { content: "\f10e"; } -.icon-postgres:before { content: "\f10f"; } -.icon-database-alt2:before { content: "\f110"; } -.icon-raspberrypi:before { content: "\f111"; } -.icon-nginx:before { content: "\f112"; } -.icon-ruby-on-rails:before { content: "\f113"; } -.icon-redis:before { content: "\f114"; } -.icon-scala:before { content: "\f115"; } -.icon-gnome:before { content: "\f116"; } -.icon-perl:before { content: "\f117"; } -.icon-mysql:before { content: "\f118"; } -.icon-fedora:before { content: "\f119"; } -.icon-ghost:before { content: "\f11a"; } -.icon-google:before { content: "\f11b"; } -.icon-netbsd:before { content: "\f11c"; } -.icon-aws:before { content: "\f11d"; } -.icon-bomb:before { content: "\f11e"; } -.icon-looking:before { content: "\f11f"; } -.icon-ruby:before { content: "\f120"; } -.icon-mysql-alt:before { content: "\f121"; } -.icon-playframework-alt:before { content: "\f122"; } -.icon-osx:before { content: "\f123"; } -.icon-database:before { content: "\f124"; } -.icon-database-alt:before { content: "\f125"; } -.icon-shell:before { content: "\f126"; } -.icon-script:before { content: "\f127"; } -.icon-antenna:before { content: "\f128"; } -.icon-coffee-bean:before { content: "\f129"; } -.icon-scala-alt:before { content: "\f12a"; } -.icon-platter:before { content: "\f12b"; } -.icon-java-duke:before { content: "\f12c"; } -.icon-iphone:before { content: "\f12d"; } -.icon-script-alt:before { content: "\f12e"; } -.icon-google-alt:before { content: "\f12f"; } -.icon-haskell:before { content: "\f130"; } -.icon-mariadb:before { content: "\f131"; } -.icon-phone-retro:before { content: "\f132"; } -.icon-phone-alt:before { content: "\f133"; } -.icon-csharp:before { content: "\f134"; } -.icon-php:before { content: "\f135"; } -.icon-postgres-alt:before { content: "\f136"; } -.icon-html:before { content: "\f137"; } -.icon-mfizz:before { content: "\f138"; } -.icon-apache:before { content: "\f139"; } -.icon-hadoop:before { content: "\f13a"; } -.icon-ruby-on-rails-alt:before { content: "\f13b"; } -.icon-mobile-phone-broadcast:before { content: "\f13c"; } -.icon-css:before { content: "\f13d"; } -.icon-playframework:before { content: "\f13e"; } -.icon-clojure:before { content: "\f13f"; } -.icon-mobile-phone-alt:before { content: "\f140"; } -.icon-suse:before { content: "\f141"; } -.icon-java-bold:before { content: "\f142"; } -.icon-nginx-alt:before { content: "\f143"; } -.icon-nginx-alt2:before { content: "\f144"; } -.icon-linux-mint:before { content: "\f145"; } -.icon-dreamhost:before { content: "\f146"; } -.icon-blackberry:before { content: "\f147"; } -.icon-javascript:before { content: "\f148"; } -.icon-ubuntu:before { content: "\f149"; } -.icon-php-alt:before { content: "\f14a"; } -.icon-centos:before { content: "\f14b"; } -.icon-nodejs:before { content: "\f14c"; } -.icon-splatter:before { content: "\f14d"; } -.icon-3dprint:before { content: "\f14e"; } -.icon-line-graph:before { content: "\f14f"; } -.icon-cassandra:before { content: "\f150"; } -.icon-solaris:before { content: "\f151"; } -.icon-jetty:before { content: "\f152"; } -.icon-tomcat:before { content: "\f153"; } -.icon-oracle:before { content: "\f154"; } -.icon-oracle-alt:before { content: "\f155"; } -.icon-mssql:before { content: "\f156"; } -.icon-google-developers:before { content: "\f157"; } -.icon-google-code:before { content: "\f158"; } -.icon-kde:before { content: "\f159"; } -.icon-grails-alt:before { content: "\f15a"; } - -/* These classes only added to fix FontFamily to display FontMfizz during debug/inspection */ -.icon-osx, -.icon-bomb, -.icon-mobile-phone-broadcast, -.icon-objc, -.icon-nginx-alt2, -.icon-mysql, -.icon-phone-retro, -.icon-netbsd, -.icon-mobile-device, -.icon-ruby-on-rails, -.icon-phone-alt, -.icon-line-graph, -.icon-postgres, -.icon-playframework, -.icon-python, -.icon-ruby-on-rails-alt, -.icon-nginx, -.icon-database-alt2, -.icon-google-alt, -.icon-microscope, -.icon-blackberry, -.icon-dreamhost, -.icon-google, -.icon-centos, -.icon-kde, -.icon-csharp, -.icon-scala, -.icon-redis, -.icon-looking, -.icon-database-alt, -.icon-javascript, -.icon-postgres-alt, -.icon-linux-mint, -.icon-ubuntu, -.icon-apache, -.icon-script-alt, -.icon-mssql, -.icon-c, -.icon-gnome, -.icon-java-duke, -.icon-scala-alt, -.icon-clojure, -.icon-oracle-alt, -.icon-redhat, -.icon-haskell, -.icon-3dprint, -.icon-mariadb, -.icon-java, -.icon-script, -.icon-cplusplus, -.icon-jetty, -.icon-perl, -.icon-heroku, -.icon-nginx-alt, -.icon-iphone, -.icon-splatter, -.icon-shell, -.icon-mysql-alt, -.icon-wireless, -.icon-ruby, -.icon-playframework-alt, -.icon-raspberrypi, -.icon-suse, -.icon-nodejs, -.icon-java-bold, -.icon-google-developers, -.icon-mobile-phone-alt, -.icon-grails-alt, -.icon-coffee-bean, -.icon-cassandra, -.icon-google-code, -.icon-fedora, -.icon-antenna, -.icon-hadoop, -.icon-solaris, -.icon-html, -.icon-css, -.icon-satellite, -.icon-aws, -.icon-mfizz, -.icon-php, -.icon-debian, -.icon-ghost, -.icon-php-alt, -.icon-tomcat, -.icon-database, -.icon-grails, -.icon-freebsd, -.icon-oracle, -.icon-fire-alt, -.icon-platter{ - font-family: "FontMfizz"; -} diff --git a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.eot b/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.eot deleted file mode 100644 index b2a7d6b91168e2831275edb6f25052d8dc1594ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43154 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 H>H7Zz>X%B= diff --git a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.svg b/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.svg deleted file mode 100644 index da46bf402..000000000 --- a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.svg +++ /dev/null @@ -1,1344 +0,0 @@ - - - - - -Created by FontForge 20110222 at Tue Jul 23 15:25:00 2013 - By Joe Lauer,,, -Created by Joe Lauer,,, with FontForge 2.0 (http://fontforge.sf.net) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.ttf b/doc/jekyll_tools/fonts/font-mfizz/font-mfizz.ttf deleted file mode 100644 index cc7ca4bc985fccc26fbbeb55b2230b2d3a0c410e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45324 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 Pn+M)^TokYn_jvv6o2c| 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 B Date: Wed, 12 Jan 2022 17:22:15 +1100 Subject: [PATCH 0883/1892] Remove R logo --- doc/jekyll_tools/fonts/rlogo.eot | Bin 1480 -> 0 bytes doc/jekyll_tools/fonts/rlogo.svg | 29 ----------------------------- doc/jekyll_tools/fonts/rlogo.ttf | Bin 1324 -> 0 bytes doc/jekyll_tools/fonts/rlogo.woff | Bin 1400 -> 0 bytes 4 files changed, 29 deletions(-) delete mode 100755 doc/jekyll_tools/fonts/rlogo.eot delete mode 100755 doc/jekyll_tools/fonts/rlogo.svg delete mode 100755 doc/jekyll_tools/fonts/rlogo.ttf delete mode 100755 doc/jekyll_tools/fonts/rlogo.woff diff --git a/doc/jekyll_tools/fonts/rlogo.eot b/doc/jekyll_tools/fonts/rlogo.eot deleted file mode 100755 index 25ebdaf2306b93c2cc59c0ba3b688ccf82eddf8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1480 zcmaJ>T})eb6hG&F^pjq=qaW1P(m_XQi-on&ZbB+1WUi5qiHRl~A}wGcwrc|j+wj3m z;}$alnk8mSln`Hx4?f_F4?Zl*G=61!A$!*>i^<+hOe7iB-@ms`AjWg^zvp*8|M&d= z=brCXqAn~Zi4GFe1`EybnS*-aYtXgpYeR=^L^fKWB9*CtMWoR<%>us#T@Dr^H@yPQ z0xi-!JkC>)dMJ){I1&o6k)7TlnR>=v?oMdiatxYpu%@O#%% zc?#T8C|-Oc_Q}-`AkSevn48Vb@K^5^iR59}Q*%&QK2-jM{2t`cTxsco{YR=o{v2{s zu{@ol$8;0&*N|97TSvNR8q9j{|-#%h|_CXq?;6s*gRq@ETXb{GK4qf;K#jAExHwPUo9 zrDj8h>RuHUAr}c${pBgC?h7S|iD7T7MH?D4LHcBED}_v?Dj&9;?dIJ>ociaArdaqcdE$AX+b zpQlmp47&IcKhvKunVn9r!`B;avshKNxv4SG+1v5g#+}P{mu6$OX)gO^mRASn*T+ZK z-W(Kse0_f4qgXbdO6RlDXf~ft<+HID_X>SuXOBr{S4%LPiH=T=t5%!Yq$;}anAej` z_B1znb?a5z5x2d;t=m^|SQ714e^Bnp+tfwR5;g1UfZXRcD(_Q!4_6*mRZl7)xtut{ zaNjORd|e$Om%smbD^Hzzb;RuO2Scvt$n(dw2CK#Ib;tY9r1y3>a$9e8I~?v-{kFXQ zxP^Ia<;n?G?5&~h%4^TzK$g}oSsc36X0o(IPK1w+4xfIyCFFB3|HQ0&+w>zrzs8If z7MF@Ow08a4>x~0{kX@Unxp++a`dKvm)9V@^u)Uk?TVyk0x zD@E(rMxFGM=yb&jjmT+WBd39loCY>>8raBbU=w1y>#;`8e@EMY53wiqg<`o--Zu#k mPQfQ`C}kEiP|U*|ErHLV&^%qlJ4@4;k0V%OO5!X2m;MGKGTSi# diff --git a/doc/jekyll_tools/fonts/rlogo.svg b/doc/jekyll_tools/fonts/rlogo.svg deleted file mode 100755 index 7f0d09e09..000000000 --- a/doc/jekyll_tools/fonts/rlogo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - -{ - "fontFamily": "rlogo", - "fontURL": "", - "designer": "Gabor Csardi", - "designerURL": "", - "license": "CC-BY-SA", - "licenseURL": "", - "version": "Version 0.0", - "fontId": "rlogo", - "psName": "rlogo", - "subFamily": "Regular", - "fullName": "rlogo", - "description": "Generated by IcoMoon" -} - - - - diff --git a/doc/jekyll_tools/fonts/rlogo.ttf b/doc/jekyll_tools/fonts/rlogo.ttf deleted file mode 100755 index 0242e4970de8dd59de33edda0e3d8f0bbb998326..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1324 zcmaJ>T})eL7=GXLozq`>;EeuIi=`_ar7afLLc0m6m@L~G2Ph_*Y>2c_3$a}rK-h*C zW*WB`7v^GOW}<}b#(3cc-gx1~vP=_yvfYr~YnH`icP1v14D0i8I-FkkHsAT4=lyxU zpYxs)6OohNAwdHZFZZYPEs=odTa206YN7t1oh}h^C-|{)VX2O}4SWW(tz0?(M&h%} zAArwe+@CKM=J@M(D@5WH;+c6kY#*tAg1-kInXfLNbN)yT@GrpIDz(`HJ)%#+zX5kt z3+L)&r!x3$@X*;pwe;PY*l*zXp&zZ+mX@(knARfWBvj(7q!B6Cm7n2RH)noGX|~I} zCycS}f7>X99os$*@mBtL7}nRz=?oJqQ);z zDa~9sVN8s8>t40#L0$If-cl-ANK-!%YtW6+D>R4nu&!8xBAv=9(M(e5_N9V~PZ!}B)DQT-nhci8yXetwAUr=KQo-NSlw>F zD=-)j+w7Xw-qsrI9qjq*>g|h8kM3Z0=pN@q7HcC5>yzVG-W-+lf4ye^lw%eW=B9(6EJtX?|8s&68M%(;0Y*+a5}q@hOkA^N%x%&OjfqFZE~&~-4Gu6|AyWbH^!4tzVmW0vcx zR5G*nRb|Fw)9I_GCZo!%kb*iLZTbcLp(a*=Pc*ScUNE@=$!?{16FaDvUXq=z+ToF! zCN?!qY-*a=)HJcFX<`d%`F@f%H~K>@macS^wpdsT?IxsRvfvtpDkjrxh-(=ZV!IMRV8g4K zxW%|I%@W-bCB!>pyg)C!ToyI)Cz}^!_ZqX9?9ON+$*?}}_kA)n#?zelJm;L}ocDX* zo_D1*I!a6sb(P$P?G@{PN$L5%3=un!J0n!vl2g<5@;qX*@Q(|<*G8AB`eJAk^DaLIidX78?{*k5&HptOsL}><&W9=(kf!V!EY7n z{+61x#x!_}0^eom1G-T!uVP_=se25ri-?@-6#%qb`5U*h(QAsmgou8u}*aB;jT`s!8^+ zoXr%ZcrGn<1u|hNpvhg)w3P2INLjm_jpn*@@k}nvfw0__MIxS-;{`ci;4}kv9SUSo zWcO=Qiu2O=%J$|Y^W^6C%JSWfDdwq-yUWGNkKZgYpLqSF$y1xlqs)c+_0zZcYZl@S zg#s;lPsGRf`LUsl&F=LEJ)wbQ)ZtXsw$_$#&p`K|SHHaI_GvC=m*#U{WO;3PZhd0> z%Bv&7POQ%jzndyna`{RznJiZFxk@qh^lo*qbn38V_q9igh2;3ugz9wJZK|S&4hI9- zY=2v8P@ zZ#`&dF0EWT%8I)));Iss6S$D2^$QMx%T$UEyKT)TZ}r`fwd!iyrLWQE36nMg=S3FURS~RTQvIA>dD62GsX{0jgDDy8S#jP72u~Vtdbv| z$;Y%((!wt4q36V;D^5hjdp5Dz)5K;^6PrCvZ1yy<4Yhq%t=V&dYSf@A^d!!-K#Md7 zd=6jNPig30excT=HXgb(0eY2QLwOm|JsOTOgL2WTOiQq5(W*k{u@-3>t;e8Z1AN8* F%3mCE&n^G} From c65b3e6ef02d303902debd55675723b280210a3b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:33:14 +1100 Subject: [PATCH 0884/1892] Cleanup img folder --- doc/jekyll_tools/img/igraph2.svg | 185 --------------- doc/jekyll_tools/img/igraph3.png | Bin 656 -> 0 bytes doc/jekyll_tools/img/igraph3.svg | 295 ------------------------ doc/jekyll_tools/img/igraph4.svg | 192 ---------------- doc/jekyll_tools/img/igraph5.png | Bin 2673 -> 0 bytes doc/jekyll_tools/img/python.svg | 372 ------------------------------- 6 files changed, 1044 deletions(-) delete mode 100644 doc/jekyll_tools/img/igraph2.svg delete mode 100644 doc/jekyll_tools/img/igraph3.png delete mode 100644 doc/jekyll_tools/img/igraph3.svg delete mode 100644 doc/jekyll_tools/img/igraph4.svg delete mode 100644 doc/jekyll_tools/img/igraph5.png delete mode 100644 doc/jekyll_tools/img/python.svg diff --git a/doc/jekyll_tools/img/igraph2.svg b/doc/jekyll_tools/img/igraph2.svg deleted file mode 100644 index 7ec4054dd..000000000 --- a/doc/jekyll_tools/img/igraph2.svg +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/jekyll_tools/img/igraph3.png b/doc/jekyll_tools/img/igraph3.png deleted file mode 100644 index 8bb38a9419455bed41718140d1b32073ae71cf9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmV;B0&o3^P)Fnyhd?o`G-TVhY}@xGD1 zblu*9gY}yp8^@3KA3wN0{Cv;T`;&v?CF7qz|FiP*PoryO`umUN#pf?VKY#t^4tV!f zWZ&P*3_FF7J~XmizHF`Zjq6+Z-@aAH7C209zViZZ+%;EYW@B5z`tM&l|EpK=4ht9Z zDqgt2>Nb74DBIVsMKHzFCQoLZHhHoF0|NsCBXV@i>g#hfU%O_9>dBLAFtJ0iF(2+3 znFKR1Fzgo=e0oYw>W19o=Nj9Ykgb3I`SZaChKBbT7#SHD7#JA-u(2_G5|g;}|Nnmu z21dpX3DF1Amc|>!*x9}rF;1N{iII!*llPxLY_C6jVZ0*n@81&MSFaTL-@N8~FClsV zr=Va#LV5XR1_lO(l}jonv$K7-`T2`$62sC3wfWc2n14OK&+qMwDgDc)O`9h8|Nno6 z?(S~x|Ns9p;KEEyOn($4#qV)RirwYmO&<>;=3* - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/jekyll_tools/img/igraph4.svg b/doc/jekyll_tools/img/igraph4.svg deleted file mode 100644 index 8c5dda4db..000000000 --- a/doc/jekyll_tools/img/igraph4.svg +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/jekyll_tools/img/igraph5.png b/doc/jekyll_tools/img/igraph5.png deleted file mode 100644 index 12f4c2bc70d14316bf8e7d99cf0fd768d7651af4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2673 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 - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8b1df1f38d245102d6e07953f625f4d691453727 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:37:00 +1100 Subject: [PATCH 0885/1892] Remove animated jumbotron --- doc/jekyll_tools/_layouts/default.html | 2 +- doc/jekyll_tools/js/jumbotron.js | 276 ------------------------- 2 files changed, 1 insertion(+), 277 deletions(-) delete mode 100644 doc/jekyll_tools/js/jumbotron.js diff --git a/doc/jekyll_tools/_layouts/default.html b/doc/jekyll_tools/_layouts/default.html index ad0de6836..6257c0e1d 100644 --- a/doc/jekyll_tools/_layouts/default.html +++ b/doc/jekyll_tools/_layouts/default.html @@ -141,9 +141,9 @@

    {{ page.mainheader | default: layout.mainheader }}

    - {% if page.animated_header or layout.animated_header %} + diff --git a/doc/jekyll_tools/js/jumbotron.js b/doc/jekyll_tools/js/jumbotron.js deleted file mode 100644 index 62e74c25e..000000000 --- a/doc/jekyll_tools/js/jumbotron.js +++ /dev/null @@ -1,276 +0,0 @@ -var startAnimation = function(){ -// Background animation for the jumbotron. -// Taken from https://codepen.io/jkiss/pen/OVEeqK - -var canvas = document.getElementById('jumbotron-anim'), - can_w = parseInt(canvas.getAttribute('width')), - can_h = parseInt(canvas.getAttribute('height')), - ctx = canvas.getContext('2d'); - -var ball = { - x: 0, - y: 0, - vx: 0, - vy: 0, - r: 0, - alpha: 1, - phase: 0 - }, - ball_color = { - r: 52, - g: 58, - b: 64 - }, - R = 4, - balls = [], - -// Line - link_line_width = 0.8, - dis_limit = 260, - add_mouse_point = true, - mouse_in = false, - mouse_ball = { - x: 0, - y: 0, - vx: 0, - vy: 0, - r: R, - type: 'mouse' - }; - -// Random speed -function getRandomSpeed(pos){ - var min = -1, - max = 1; - switch(pos){ - case 'top': - return [randomNumFrom(min, max), randomNumFrom(0.1, max)]; - break; - case 'right': - return [randomNumFrom(min, -0.1), randomNumFrom(min, max)]; - break; - case 'bottom': - return [randomNumFrom(min, max), randomNumFrom(min, -0.1)]; - break; - case 'left': - return [randomNumFrom(0.1, max), randomNumFrom(min, max)]; - break; - default: - return; - break; - } -} -function randomArrayItem(arr){ - return arr[Math.floor(Math.random() * arr.length)]; -} -function randomNumFrom(min, max){ - return Math.random()*(max - min) + min; -} -// Random Ball -function getRandomBall(){ - var pos = randomArrayItem(['top', 'right', 'bottom', 'left']); - switch(pos){ - case 'top': - return { - x: randomSidePos(can_w), - y: -R, - vx: getRandomSpeed('top')[0], - vy: getRandomSpeed('top')[1], - r: R, - alpha: 0.5, - phase: randomNumFrom(0, 10) - } - break; - case 'right': - return { - x: can_w + R, - y: randomSidePos(can_h), - vx: getRandomSpeed('right')[0], - vy: getRandomSpeed('right')[1], - r: R, - alpha: 0.5, - phase: randomNumFrom(0, 10) - } - break; - case 'bottom': - return { - x: randomSidePos(can_w), - y: can_h + R, - vx: getRandomSpeed('bottom')[0], - vy: getRandomSpeed('bottom')[1], - r: R, - alpha: 0.5, - phase: randomNumFrom(0, 10) - } - break; - case 'left': - return { - x: -R, - y: randomSidePos(can_h), - vx: getRandomSpeed('left')[0], - vy: getRandomSpeed('left')[1], - r: R, - alpha: 0.5, - phase: randomNumFrom(0, 10) - } - break; - } -} -function randomSidePos(length){ - return Math.ceil(Math.random() * length); -} - -// Draw Ball -function renderBalls(){ - Array.prototype.forEach.call(balls, function(b){ - ctx.fillStyle = 'rgba('+ball_color.r+','+ball_color.g+','+ball_color.b+','+b.alpha+')'; - ctx.beginPath(); - ctx.arc(b.x, b.y, R, 0, Math.PI*2, true); - ctx.closePath(); - ctx.fill(); - }); -} - -// Update balls -function updateBalls(){ - var new_balls = []; - Array.prototype.forEach.call(balls, function(b){ - b.x += b.vx; - b.y += b.vy; - - if(b.x > -(50) && b.x < (can_w+50) && b.y > -(50) && b.y < (can_h+50)){ - new_balls.push(b); - } - }); - - balls = new_balls.slice(0); -} - -// Draw lines -function renderLines(){ - var fraction, alpha; - for (var i = 0; i < balls.length; i++) { - for (var j = i + 1; j < balls.length; j++) { - - fraction = getDisOf(balls[i], balls[j]) / dis_limit; - - if(fraction < 1){ - alpha = (1 - fraction).toString(); - - ctx.strokeStyle = 'rgba(150,150,150,'+alpha+')'; - ctx.lineWidth = link_line_width; - - ctx.beginPath(); - ctx.moveTo(balls[i].x, balls[i].y); - ctx.lineTo(balls[j].x, balls[j].y); - ctx.stroke(); - ctx.closePath(); - } - } - } -} - -// calculate distance between two points -function getDisOf(b1, b2){ - var delta_x = Math.abs(b1.x - b2.x), - delta_y = Math.abs(b1.y - b2.y); - - return Math.sqrt(delta_x*delta_x + delta_y*delta_y); -} - -// add balls if there a little balls -function addBallIfy(){ - if(balls.length < 20){ - balls.push(getRandomBall()); - } -} - -// Render -function render(){ - if (Date.now() - lastCanvasSizeUpdate > 1000) { - updateCanvasSize(); - } - - if (balls.length == 0) { - initBalls(30); - } - - ctx.clearRect(0, 0, can_w, can_h); - - renderBalls(); - - renderLines(); - - updateBalls(); - - addBallIfy(); - - window.requestAnimationFrame(render); -} - -// Init Balls -function initBalls(num){ - for(var i = 0; i < num; i++){ - balls.push({ - x: randomSidePos(can_w), - y: randomSidePos(can_h), - vx: getRandomSpeed('top')[0], - vy: getRandomSpeed('top')[1], - r: R, - alpha: 0.5, - phase: randomNumFrom(0, 10) - }); - } -} - -var lastCanvasSizeUpdate = 0; - -function updateCanvasSize() { - can_w = canvas.width = canvas.offsetWidth; - can_h = canvas.height = canvas.offsetHeight; - lastCanvasSizeUpdate = Date.now(); -} - -// Init Canvas -function initCanvas(){ -} - -window.addEventListener('resize', function(e){ - updateCanvasSize(); -}); - -function startCanvasAnimation(){ - initCanvas(); - window.requestAnimationFrame(render); -} - -// Mouse effect -canvas.addEventListener('mouseenter', function(){ - mouse_in = true; - balls.push(mouse_ball); -}); -canvas.addEventListener('mouseleave', function(){ - mouse_in = false; - var new_balls = []; - Array.prototype.forEach.call(balls, function(b){ - if(!b.hasOwnProperty('type')){ - new_balls.push(b); - } - }); - balls = new_balls.slice(0); -}); -canvas.addEventListener('mousemove', function(e){ - var e = e || window.event; - var rect = canvas.getBoundingClientRect(); - - mouse_ball.x = e.clientX - rect.left; - mouse_ball.y = e.clientY - rect.top; -}); - -function startAnimation() { - window.addEventListener('DOMContentLoaded', startCanvasAnimation); -} - -return startAnimation; - -}(); From 11c7a2175c865cb99d3b1968278829cf6c923c49 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:44:51 +1100 Subject: [PATCH 0886/1892] Wording in FAQs --- doc/source/faq.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/faq.rst b/doc/source/faq.rst index 1855a635e..900cc10d6 100644 --- a/doc/source/faq.rst +++ b/doc/source/faq.rst @@ -63,6 +63,9 @@ What's the difference between |igraph| and similar packages (networkx, graph-too ----------------------------------------------------------------------------------- All those packages focus on graph/network analysis. +.. warning:: + The following differences and similarities are considered correct as of the time of writing (Jan 2022). If you identify incorrect or outdated information, please open a `Github issue `_ and we'll update it. + **Differences:** - |igraph| supports **multiple programming languages** (e.g. C, Python, R, Mathematica). `networkx`_ and `graph-tool`_ are Python only. @@ -70,7 +73,6 @@ All those packages focus on graph/network analysis. - |igraph| vertices are *ordered with contiguous numerical IDs, from 0 upwards*, and an *optional* "vertex name". `networkx`_ nodes are *defined* by their name and not ordered. - Same holds for edges, ordered with integer IDs in |igraph|, not so in `networkx`_. - |igraph| can plot graphs using :mod:`matplotlib` and has experimental support for `plotly`_, so it can produce animations, notebook widgets, and interactive plots (e.g. zoom, panning). `networkx`_ has excellent :mod:`matplotlib` support but no `plotly`_ support. `graph-tool`_ only supports static images via Cairo and GTK+. - - |igraph| and `networkx`_ are maintained by teams of developers. `graph-tool`_ is developed by a single (very active) person. - In terms of design, |igraph| really shines when you have a relatively static network that you want to analyse, while it can struggle with very dynamic networks that gain and lose vertices and edges all the time. This might change in the near future as we improve |igraph|'s core C library. At the moment, `networkx`_ is probably better suited for simulating such highly dynamic graphs. **Similarities:** @@ -80,7 +82,7 @@ All those packages focus on graph/network analysis. - All can visualize graphs, with different strengths and weaknesses. .. note:: - |igraph| includes conversion functions from/to `networkx`_, so you can crate and manipulate a network with |igraph| and later on convert it to `networkx`_ or `graph-tool`_ if you need. Vice versa, you can load a graph in `networkx`_ or `graph-tool`_ and convert the graph into an |igraph| object if you need more speed, a specific algorithm, matplotlib animations, etc. You can even use |igraph| to convert graphs from `networkx`_ to `graph-tool`_ and vice versa! + |igraph| includes conversion functions from/to `networkx`_, so you can create and manipulate a network with |igraph| and later on convert it to `networkx`_ or `graph-tool`_ if you need. Vice versa, you can load a graph in `networkx`_ or `graph-tool`_ and convert the graph into an |igraph| object if you need more speed, a specific algorithm, matplotlib animations, etc. You can even use |igraph| to convert graphs from `networkx`_ to `graph-tool`_ and vice versa! From 2bbb58735b68df66c35f68624dbe147cb1a31a67 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 17:46:06 +1100 Subject: [PATCH 0887/1892] Remove commented old pydoctor patching lines --- scripts/patch-pydoctor.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/scripts/patch-pydoctor.sh b/scripts/patch-pydoctor.sh index aad33b27e..de94288fa 100755 --- a/scripts/patch-pydoctor.sh +++ b/scripts/patch-pydoctor.sh @@ -12,21 +12,10 @@ set -e ROOT_FOLDER=$1 PATCH_FOLDER=$(realpath $2) ${ROOT_FOLDER}/.venv/bin/pip uninstall -y pydoctor -#${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.2.2 ${ROOT_FOLDER}/.venv/bin/pip install pydoctor==21.12.0 PYDOCTOR_DIR=`.venv/bin/python -c 'import os,pydoctor;print(os.path.dirname(pydoctor.__file__))'` cd "${PYDOCTOR_DIR}" -## patch is confirmed to work with pydoctor 21.2.2 -#echo "First patch" -#patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2.patch 2>/dev/null -#rm -f deleteme.rej -# -## patch sphinx extension -#echo "Second patch" -#patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.2.2_sphinx_ext.patch 2>/dev/null -#rm -f deleteme.rej - -echo "New patch against 21.12.0" +echo "Patch against 21.12.0 to fix a bug with C extensions" patch -r deleteme.rej -N -p2 <${PATCH_FOLDER}/pydoctor-21.12.0.patch 2>/dev/null rm -f deleteme.rej From 86b1291bac1428074d1d99d44102e3ce4a1354a7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 18:10:26 +1100 Subject: [PATCH 0888/1892] Annotate a few types in function headers --- src/igraph/io/libraries.py | 8 ++-- src/igraph/io/objects.py | 81 ++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/igraph/io/libraries.py b/src/igraph/io/libraries.py index 057ca1014..d4b02115b 100644 --- a/src/igraph/io/libraries.py +++ b/src/igraph/io/libraries.py @@ -1,5 +1,5 @@ def _export_graph_to_networkx( - graph, create_using=None, vertex_attr_hashable="_nx_name" + graph, create_using=None, vertex_attr_hashable: str = "_nx_name", ): """Converts the graph to networkx format. @@ -11,7 +11,7 @@ def _export_graph_to_networkx( constructing the graph. C{None} means to let igraph infer the most appropriate class based on whether the graph is directed and whether it has multi-edges. - @param vertex_attr_hashable: (str) vertex attribute used to name vertices + @param vertex_attr_hashable: vertex attribute used to name vertices in the exported network. The default "_nx_name" ensures round trip conversions to/from networkx are lossless. """ @@ -68,7 +68,7 @@ def _export_graph_to_networkx( return g -def _construct_graph_from_networkx(cls, g, vertex_attr_hashable="_nx_name"): +def _construct_graph_from_networkx(cls, g, vertex_attr_hashable : str = "_nx_name"): """Converts the graph from networkx Vertex names will be stored as a vertex_attr_hashable attribute (usually @@ -78,7 +78,7 @@ def _construct_graph_from_networkx(cls, g, vertex_attr_hashable="_nx_name"): distinguish edges that connect the same two vertices. @param g: networkx Graph or DiGraph - @param vertex_attr_hashable: (str) attribute used to store the Python + @param vertex_attr_hashable: attribute used to store the Python hashable used by networkx to identify each vertex. The default value '_nx_name' ensures lossless round trip conversions to/from networkx. An alternative choice is 'name': in that case, using strings for vertex diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 104d1277e..8de718f0e 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -1,3 +1,4 @@ +from typing import Union, Sequence from collections import defaultdict from itertools import repeat from warnings import warn @@ -9,10 +10,10 @@ def _construct_graph_from_dict_list( cls, vertices, edges, - directed=False, - vertex_name_attr="name", + directed: bool = False, + vertex_name_attr: str = "name", edge_foreign_keys=("source", "target"), - iterative=False, + iterative: bool = False, ): """Constructs a graph from a list-of-dictionaries representation. @@ -147,8 +148,8 @@ def create_list_from_indices(indices, n): def _construct_graph_from_tuple_list( cls, edges, - directed=False, - vertex_name_attr="name", + directed: bool = False, + vertex_name_attr: str = "name", edge_attrs=None, weights=False, ): @@ -238,8 +239,8 @@ def _construct_graph_from_tuple_list( def _construct_graph_from_list_dict( cls, edges, - directed=False, - vertex_name_attr="name", + directed: bool = False, + vertex_name_attr: str = "name", ): """Constructs a graph from a dict-of-lists representation. @@ -256,8 +257,8 @@ def _construct_graph_from_list_dict( vertex will be given the vertex_name_attr attribute. @param edges: the dict of sequences describing the edges - @param directed: (bool) whether to create a directed graph - @vertex_name_attr: (str) vertex attribute that will store the names + @param directed: whether to create a directed graph + @vertex_name_attr: vertex attribute that will store the names @returns: a Graph object @@ -299,8 +300,8 @@ def _construct_graph_from_list_dict( def _construct_graph_from_dict_dict( cls, edges, - directed=False, - vertex_name_attr="name", + directed: bool = False, + vertex_name_attr: str = "name", ): """Constructs a graph from a dict-of-dicts representation. @@ -323,8 +324,8 @@ def _construct_graph_from_dict_dict( @param edges: the dict of dict of dicts specifying the edges and their attributes - @param directed: (bool) whether to create a directed graph - @vertex_name_attr: (str) vertex attribute that will store the names + @param directed: whether to create a directed graph + @vertex_name_attr: vertex attribute that will store the names @returns: a Graph object """ @@ -370,9 +371,9 @@ def _construct_graph_from_dict_dict( def _construct_graph_from_dataframe( cls, edges, - directed=True, + directed: bool = True, vertices=None, - use_vids=True, + use_vids: bool = True, ): """Generates a graph from one or two dataframes. @@ -381,7 +382,7 @@ def _construct_graph_from_dataframe( for each edge. These indicate the vertex IDs as nonnegative integers rather than vertex names unless `use_vids` is False. Further columns may contain edge attributes. - @param directed: bool setting whether the graph is directed + @param directed: whether the graph is directed @param vertices: None (default) or pandas DataFrame containing vertex metadata. The DataFrame's index must contain the vertex IDs as a sequence of intergers from `0` to `len(vertices) - 1`. If `use_vids` @@ -502,7 +503,10 @@ def _construct_graph_from_dataframe( def _export_graph_to_dict_list( - graph, use_vids=True, skip_none=False, vertex_name_attr="name" + graph, + use_vids: bool = True, + skip_none: bool = False, + vertex_name_attr: str = "name", ): """Export graph as two lists of dictionaries, for vertices and edges. @@ -524,14 +528,14 @@ def _export_graph_to_dict_list( [{"source": "apple", "target": "pear", "name": "first_edge"}, {"source" "apple", "target": "peach", name": "second"}]) - @param use_vids: (bool) whether to label vertices in the output data + @param use_vids: whether to label vertices in the output data structure by their ids or their vertex_name_attr attribute. If use_vids=False but vertices lack a vertex_name_attr attribute, an AttributeError is raised. - @param skip_none: (bool) whether to skip, for each edge, attributes that + @param skip_none: whether to skip, for each edge, attributes that have a value of None. This is useful if only some edges are expected to possess an attribute. - @vertex_name_attr: (str) only used with use_vids=False to choose what + @vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -571,7 +575,10 @@ def _export_graph_to_dict_list( def _export_graph_to_tuple_list( - graph, use_vids=True, edge_attrs=None, vertex_name_attr="name" + graph, + use_vids: bool = True, + edge_attrs: Union[str, Sequence[str]] = None, + vertex_name_attr: str = "name", ): """Export graph to a list of edge tuples @@ -591,16 +598,16 @@ def _export_graph_to_tuple_list( >>> g.to_tuple_list(use_vids=False) [("apple", "pear"), ("apple", "peach"), ("pear", "peach")] - @param use_vids: (bool) whether to label vertices in the output data + @param use_vids: whether to label vertices in the output data structure by their ids or their vertex_name_attr attribute. If use_vids=False but vertices lack a vertex_name_attr attribute, an AttributeError is raised. - @param edge_attrs: (str or list of str) list of edge attributes to export + @param edge_attrs: list of edge attributes to export in addition to source and target vertex, which are always the first two elements of each tuple. None (default) is equivalent to an empty list. A string is acceptable to signify a single attribute and will be wrapped in a list internally. - @vertex_name_attr: (str) only used with use_vids=False to choose what + @vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -637,9 +644,9 @@ def _export_graph_to_tuple_list( def _export_graph_to_list_dict( graph, - use_vids=True, - sequence_constructor=list, - vertex_name_attr="name", + use_vids: bool = True, + sequence_constructor: callable = list, + vertex_name_attr: str = "name", ): """Export graph to a dictionary of lists (or other sequences). @@ -654,15 +661,15 @@ def _export_graph_to_list_dict( >>> g.to_sequence_dict(use_vids=False) {'apple': ['pear', 'peach'], 'pear': ['peach']} - @param use_vids: (bool) whether to label vertices in the output data + @param use_vids: whether to label vertices in the output data structure by their ids or their vertex_name_attr attribute. If use_vids=False but vertices lack a vertex_name_attr attribute, an AttributeError is raised. - @param sequence_constructor: (function) constructor for the data structure + @param sequence_constructor: constructor for the data structure to be used as values of the dictionary. The default (list) makes a dict of lists, with each list representing the neighbors of the vertex specified in the respective dictionary key. - @vertex_name_attr: (str) only used with use_vids=False to choose what + @vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -691,7 +698,11 @@ def _export_graph_to_list_dict( def _export_graph_to_dict_dict( - graph, use_vids=True, edge_attrs=None, skip_none=False, vertex_name_attr="name" + graph, + use_vids: bool = True, + edge_attrs: Union[str, Sequence[str]] = None, + skip_none: bool = False, + vertex_name_attr: str = "name", ): """Export graph to dictionary of dicts of edge attributes @@ -704,18 +715,18 @@ def _export_graph_to_dict_dict( >>> g.to_dict_dict() {0: {1: {'name': 'first_edge'}, 2: {'name': 'second'}}, 1: {2: {'name': 'third'}}} - @param use_vids: (bool) whether to label vertices in the output data + @param use_vids: whether to label vertices in the output data structure by their ids or their vertex_name_attr attribute. If use_vids=False but vertices lack a vertex_name_attr attribute, an AttributeError is raised. - @param edge_attrs: (str or list of str) list of edge attributes to export. + @param edge_attrs: list of edge attributes to export. None (default) signified all attributes (unlike Graph.to_tuple_list). A string is acceptable to signify a single attribute and will be wrapped in a list internally. - @param skip_none: (bool) whether to skip, for each edge, attributes that + @param skip_none: whether to skip, for each edge, attributes that have a value of None. This is useful if only some edges are expected to possess an attribute. - @vertex_name_attr: (str) only used with use_vids=False to choose what + @vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. From 4e43383e04e60d7c0624e77cc809161412421139 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jan 2022 18:27:18 +1100 Subject: [PATCH 0889/1892] Restore doc2dash guessing the paths --- scripts/mkdoc.sh | 52 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 0eaa3eaf8..3bdd417f1 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -96,30 +96,32 @@ else fi fi - +echo "HTML documentation generated in ${DOC_HTML_FOLDER}" + + +# doc2dash (tamas please check this) +PWD=`pwd` +# Output folder of sphinx (before Jekyll if requested) +DOC_API_FOLDER=${ROOT_FOLDER}/doc/html/api +DOC2DASH=`which doc2dash 2>/dev/null || true` +if [ "x$DOC2DASH" != x ]; then + echo "Generating Dash docset..." + "$DOC2DASH" \ + --online-redirect-url "https://igraph.org/python/api" \ + --name "python-igraph" \ + -d "${DOC_API_FOLDER}" \ + -f \ + "${DOC_API_FOLDER}/doc2dash" + DASH_READY=1 +else + echo "WARNING: doc2dash not installed, skipping Dash docset generation." + DASH_READY=0 +fi -#PWD=`pwd` -#DOC_API_FOLDER=${ROOT_FOLDER}/doc/api -#DOC2DASH=`which doc2dash 2>/dev/null || true` -#if [ "x$DOC2DASH" != x ]; then -# echo "Generating Dash docset..." -# "$DOC2DASH" \ -# --online-redirect-url "https://igraph.org/python/doc/api" \ -# --name "python-igraph" \ -# -d "${DOC_API_FOLDER}" \ -# -f \ -# "${DOC_API_FOLDER}/html" -# DASH_READY=1 -#else -# echo "WARNING: doc2dash not installed, skipping Dash docset generation." -# DASH_READY=0 -#fi -# -#echo "" -#echo "HTML documentation generated in ${DOC_HTML_FOLDER}/html" -#if [ "x${DASH_READY}" = x1 ]; then -# echo "Dash docset generated in ${DOC_API_FOLDER}/python-igraph.docset" -#fi -# -#cd "$PWD" +echo "" +if [ "x${DASH_READY}" = x1 ]; then + echo "Dash docset generated in ${DOC_API_FOLDER}/python-igraph.docset" +fi + +cd "$PWD" From 8b7c9a6b0636c0adb53cd3c582ef4948c828ebac Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 12 Jan 2022 14:30:12 +0100 Subject: [PATCH 0890/1892] doc: clarify that we now support graphs of size 5 or 6 for isomorphism / motif calculations if the graph is undirected --- src/_igraph/graphobject.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 68c2c0eab..6e99886b4 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2668,12 +2668,6 @@ PyObject *igraphmodule_Graph_Isoclass(PyTypeObject * type, &n, &isoclass, &directed)) return NULL; - if (n < 3 || n > 4) { - PyErr_SetString(PyExc_ValueError, - "Only graphs with 3 or 4 vertices are supported"); - return NULL; - } - if (igraph_isoclass_create(&g, (igraph_integer_t) n, (igraph_integer_t) isoclass, PyObject_IsTrue(directed))) { igraphmodule_handle_igraph_error(); @@ -8817,11 +8811,6 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, return NULL; n = vids ? PyList_Size(vids) : igraph_vcount(&self->g); - if (n < 3 || n > 4) { - PyErr_SetString(PyExc_ValueError, - "Graph or subgraph must have 3 or 4 vertices."); - return NULL; - } if (vids) { igraph_vector_t vidsvec; @@ -13118,7 +13107,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Isoclass(n, cls, directed=False)\n--\n\n" "Generates a graph with a given isomorphism class.\n\n" - "@param n: the number of vertices in the graph (3 or 4)\n" + "Currently we support directed graphs of size 3 and 4, and undirected graphs\n" + "of size 3, 4, 5 or 6. Use the L{isoclass()} instance method to find the\n" + "isomorphism class of a given graph.\n\n" + "@param n: the number of vertices in the graph\n" "@param cls: the isomorphism class\n" "@param directed: whether the graph should be directed.\n"}, @@ -14526,9 +14518,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "argued that the motif profile (ie. the number of different motifs in\n" "the graph) is characteristic for different types of networks and\n" "network function is related to the motifs in the graph.\n\n" - "This function is able to find the different motifs of size three\n" - "and four (ie. the number of different subgraphs with three and four\n" - "vertices) in the network.\n\n" + "Currently we support motifs of size 3 and 4 for directed graphs, and\n" + "motifs of size 3, 4, 5 or 6 for undirected graphs.\n\n" "In a big network the total number of motifs can be very large, so\n" "it takes a lot of time to find all of them. In such cases, a sampling\n" "method can be used. This function is capable of doing sampling via\n" @@ -14537,7 +14528,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@newfield ref: Reference\n" "@ref: S. Wernicke and F. Rasche: FANMOD: a tool for fast network\n" " motif detection, Bioinformatics 22(9), 1152--1153, 2006.\n\n" - "@param size: the size of the motifs (3 or 4).\n" + "@param size: the size of the motifs\n" "@param cut_prob: the cut probabilities for different levels of the search\n" " tree. This must be a list of length I{size} or C{None} to find all\n" " motifs.\n" @@ -14556,10 +14547,12 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Motifs are small subgraphs of a given structure in a graph.\n" "This function counts the total number of motifs in a graph without\n" "assigning isomorphism classes to them.\n\n" + "Currently we support motifs of size 3 and 4 for directed graphs, and\n" + "motifs of size 3, 4, 5 or 6 for undirected graphs.\n\n" "@newfield ref: Reference\n" "@ref: S. Wernicke and F. Rasche: FANMOD: a tool for fast network\n" " motif detection, Bioinformatics 22(9), 1152--1153, 2006.\n\n" - "@param size: the size of the motifs (3 or 4).\n" + "@param size: the size of the motifs\n" "@param cut_prob: the cut probabilities for different levels of the search\n" " tree. This must be a list of length I{size} or C{None} to find all\n" " motifs.\n" @@ -14574,10 +14567,12 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "This function estimates the total number of motifs in a graph without\n" "assigning isomorphism classes to them by extrapolating from a random\n" "sample of vertices.\n\n" + "Currently we support motifs of size 3 and 4 for directed graphs, and\n" + "motifs of size 3, 4, 5 or 6 for undirected graphs.\n\n" "@newfield ref: Reference\n" "@ref: S. Wernicke and F. Rasche: FANMOD: a tool for fast network\n" " motif detection, Bioinformatics 22(9), 1152--1153, 2006.\n\n" - "@param size: the size of the motifs (3 or 4).\n" + "@param size: the size of the motifs\n" "@param cut_prob: the cut probabilities for different levels of the search\n" " tree. This must be a list of length I{size} or C{None} to find all\n" " motifs.\n" @@ -15381,8 +15376,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "isoclass(vertices)\n--\n\n" "Returns the isomorphism class of the graph or its subgraph.\n\n" - "Isomorphy class calculations are implemented only for graphs with\n" - "3 or 4 vertices.\n\n" + "Isomorphism class calculations are implemented only for directed graphs\n" + "with 3 or 4 vertices, or undirected graphs with 3, 4, 5 or 6 vertices..\n\n" "@param vertices: a list of vertices if we want to calculate the\n" " isomorphism class for only a subset of vertices. C{None} means to\n" " use the full graph.\n" From 554d7462c23f03fba9fd724af5389d376bb0365b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 13 Jan 2022 10:31:34 +1100 Subject: [PATCH 0891/1892] Acceptable double footer --- doc/jekyll_tools/_layouts/default.html | 9 +++++--- doc/jekyll_tools/css/other.css | 11 ++++++---- doc/source/sphinxext/postprocess_api.py | 29 +++++++++++++++---------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/doc/jekyll_tools/_layouts/default.html b/doc/jekyll_tools/_layouts/default.html index 6257c0e1d..d74c2b8b1 100644 --- a/doc/jekyll_tools/_layouts/default.html +++ b/doc/jekyll_tools/_layouts/default.html @@ -120,7 +120,9 @@

    {{ page.mainheader | default: layout.mainheader }}

    {{content}} -
    + + + < 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 l+ww`H3IY{DQ8_Iiu=#kWLfG}!dEvmnH diff --git a/tests/drawing/cairo/baseline_images/graph_basic.png b/tests/drawing/cairo/baseline_images/graph_basic.png index d7fa29c1d90b5dfd7c9efd2b7caf8d51cc7501f9..2eee93d865310740adc91b867062b5b2ec6a5205 100644 GIT binary patch literal 16701 zcmZvE1yoh**7gDcHz2YVX(S|-RHPdTk+eujrE8;vG!hCTq9CBsAl)J%k_t!(QqrMx z2m;de&&9d-{&(E*amE?vxLJFxcg=UkGoSgqhG=OhlabJoAP7RHa#i65g5c|-|6=gr zlZyo8q3|CfGgV~;X7uyCSG=Qn=N5*Nwb?|2}u3%Ys9TB;>?};N9yyohK;oAacS_ zw)dSj*~!m;#&vity>XX1G>^{tDi%I!xOpeB!`xDUh7CdNqN-+LP1q1-0;K=4KNd0R z#>gXn>Z}+%L^$k!K74S-5J5tnHWmlGcQ>Y{r?s`UORYLnZ2R)7JU2_rW@<7_2Nuiq zh-80fXJ3M^6hbd0%5m!N~gOA5|vdWyTHgGd@S5OG)@{`dfIbaa7)yMRH&(MhXsBK8gy1qgtk{la<36 zc79DPGCqFo$w}|S;tsXjTqgJgEGC~O_lBxG-4qoSO-xL1IIx<`o&7$% zgM)A;$*qlVu`YWbQX?+cjz}%^WC`0pOAsR@V8-CZK3MtH0P6`14D9Oas`lO`I)2=3 zd31j{HDNVv$d;5OA@hr+5$v7Y=D>2zVF$I5fZ{j5Ic%U`Ub*vJ*JzbzWMt&p>Z(n1 zjX_#QhKv+${8dCmpG}qXf^ohcOW)OXmRDMjEt|3g_BbzTklr$pAT%jIG6p#&Wnp7oD6hA zm*lqnnmbS7|HvvV#C0S{g@lCE93FhCsqwvfH8?RbG2lv-h4I0y+qc&nW)k@mE>3K& z%>=~94@JjFEUd@eF(e-xFf1uM?Bgz|q^Ic4yq?-;?7QF0ndr6J%t?7@iKq6InIQMt z_3PI?JUp&lYYCy?+}qoemzVe0T>3qm*;btRV5a@|Sj}O$%t2;mrq#fE^D>7KFK_Rh z*jCjTzN&+rh2^SEBUl*aws@^1M!uHr3^jE|T3Xt>cMQ^A<(3@@r%s)E^ytyGDdQ3I zd-r&B3r)6HrxFqpEDmgHtzaMPu3fvfu{2^3?+g3Bzq4-3_P4A;JysZQz@zuRzM(G0yJiK@5aZ)aTI1VQu#9z z@F;H7Y8KmX@};xmi4Z zsd{&bl$e-Sz(lq?z47-qAqpZ(6FH2$Y#Jn(=S(sQuU@^1i{qIwwz9G+w)m#dcU$Mp zn>TAS9hNwvd1WmA{JEJ#FG8zWVSBJ4{Ja%$$N=<1NT4CE;|MHqC7$LrReV0 z8#iu5L`Kq!I55D^sZ*U5F1DR6Lcx-v6SK2hOP`jX<`b5)`eU&?5QG;mUSwxiOzk8% ze*DRkCkEXcMDDohqOXkfk`D`K_5Fq*dtS83MHa_uYGPtyW>eJs>u56>Dy)RacMFK{kF5iAYKgTdXZ>!yV({-7fZW z?fR_$$QXsFm{o;6wbMw!X`Z&pUaX+u)Gvv32YZ`?TEcu7$~_tkrjj*gur zwdtn3m&1dDF=S*eZf?|uF(sz(g0fhA-|bzJ;e-9%u?HPeDGTo{;N3+1 zv4z=`e$iaQ!aqhweSX!4q>w%eJBKm-l&ym-4VJWacMG07cTQBa|I3#v&W6IujB&K0 zxbbdH8Qu!2{&W6V;hAM_T%H|a61y3W2>(=IA&Z!pn2L&u%>LiVPoF$-IGnDo?og?{ zB6X0=S;>b2e0+S;($%+fv{P&!*|T6w_w6hR^V4=WYYz94pT6Qjb=;N7m7D1u+LkOz!P&&m^vU zcwfERRQu@IP?;k?Ttx4V+9?5>FL?&QkQ;FG~h8S#)D9CeT zQAJHH*XU6z30vmz06{A-RGHiUj!V2oOhm-}y)CCzavRuWx?tvd->f2h0q}fg=Gx|F z6=y?P`{#^O;(^O-?IIP&f7i=mQ&YvHE1jCIp{aETSQt@C$1JWvi|M&D}Zk!$- zW}y)G^K(l}i%KL%2p<8}W9AQvkVd+@x|X2Ufh$5NM*0>yQ&LhoR&QGz9_%N2Z|FfB zM_>bm11ZZ3Jz#e*1j*~*zvX}pOYMiiJAQ=K(e_ZwS(W^EfcnGLry$C9SH3dQ#>t&M z75F1v{1C2CQc(Dl*jOkOO2wOVY%fM$ zm3?L`-|*7~Zti2pjzMgQyDjllaLF1zKPw^pU|NmHQcJ@B`{y_*Phl}Jcc^nyQ&Vzs za=EpHHk{<`JO-uDVk2;z1j*+AiQyuA>dY9$P^zey7|jGpJ!clJ^Zr`B**fD1GQQQ0 zW7R)@{+v8=VRWT*hSgr%F~&YB8XEaVc(XGzGvnjT6@0ZfVE^^8ffsJvy7damGt{~G z_>l}vCT#?tB;vSbG>=|ax;j0)fgwhIMfVZu>#u+$s_uS03F|#3$EEh4EIo`NeBG0x z82U6c6wqdiy8KlK;KEulz0K6&;+1yv@YoD~PW z<*i>WQQQ-aVWH2TTi}Q;`G5ZaZ}J`=t3^&^iR1SF&IXkj8j#Zz6gg`JzJ~{!!w+iu3J`%r+G;w%xy5vIIZRzM3E4B=;#P93q;6HaRMW?`MlF8&I>OyxLpB;tX z-J5n&7`;cNd7?8ARh7{bhR6vfMV+_>HKg|83D5x39d&(w>ineP!YBdHff z?@HtfU~+Vj^t3dWxh{4|$+*2^CV`GM`y0E<;v7v z8?fD_^^>1(W@va6*sHxS!9ux?;#4*DP~&sdjyJb?qJ=Hi{K6HB(bNE6Bso z&o3l&+X%0}%yA3~+bX%=j`!w>8vuPFSWBvg9L@G>>l0zeQSBRD**{_oU%X>kT9W?q zI1hSFeIxBE{1{3NzZxSc+MS`9=zFl1m|`n;WrQ8mktj2kqZ+d>;xKGHqq(OZu~Yu>Y)gAI zQxdqeVMaIF9?1CISvqWzLA3qqXmgxmn4fvgv4^Y2PT#uKvv7q|Ov0E^+__(sf20Cm z0AN)^Lz-zXzTZ;;(Yt4DNYQHX_?r~)g?_o3o{ny?%+Xj!r;kXR z7@7aOzd7bOQsL6@loI@lZ&&{yIy(ACb7yC;r{vJp8zOF-asfn&3JNd$k=%X?P07ww za}X_3NGK>ahyc_^iED zf$r|^ye%!yc89gi&8hi~E-zIfCUOjC&t|B-Ssig3gElcVpRh5L7b8TcUKAPWlxQ$H z+4D|?Vq%mOiB1C-yP2-0_rdDAgG2tTzLsMNp(zw7UlG^#H8;x{sAY7UMo6J3xzyk9 zH3#bj=WnJ1RJr2Jo0&M6t^}=UMX952QRVQ*1SWkxl{|VOardRTj10?T3&#-B_t3L~ zV>!eX@szj(^6Gz>9ZhQ`UqAf*JEAAmR_6xRFOOEjl_x-uDx;M772Dj1*aMDFpZaX? z-{M!fDfCvw$%*VdDZ+CqKrniiPj0K8Li5AgM#9pa@F%G^p~>9clHBOOOU8Wy;kkiA zdNVUB9$nnhuvlkFlE#wH+{RRE%s!LPLwO&cd$)THWgJSX_EV^MyTTdQ|NPO)lt&6B zAxT5C^sA9J6c_VcE8?B!a+Qc_N5Vt?g1$S3p-X%3L^m2Txe;KZQ2uJHA!aE>Bh)?Ttc2_0J|%bc!22m1Q&U^Z8OYAu5tE%C=Ef}( zy2%bAGrgs z&flcsyYp~k5pbB_b1b4T`y+2?wlmeT?RDMwGaM`@7^(^UFCB1W%+Dl6i=8HvI)jcF zzrdHrEnOG;;g_;xXQO{|u^^WfpqZYex1@?tA#XS@4ZHVbUO&-}wll~)eESVpH%T1*;P^bAtP4%tMNV;fM2nTkvh6YOkWur) z9|c9)U*n;dQ!+A+=IHPfS*ktd{(;E$Ha??;DziFZnHa)XZv*^{Uv_hVAh;2fCxvn| zGNdP8uh>G+vi(_jct>;dDZ^086jlO+^n2D#PPj=R+`kpe$hb5yA?UVrhsg4kBCN52 zM$n=S=sW5Czc)LBbSWL8@sLm!^7cho2z39>ygvfKI6NU<6K$(gt+a91NnmMI=^nWB z@^W4Htsi<<3b^aSLTi}d({T%0r0^=hf%Ck)`;(EH3e;vRvlzVEb7G>RYHu#Fv#>m> zdqeaKz3LW#DDnV7GG#C?RW5|n%a<=tv|ony8;R!S;mHMx?7?(fR(AGj!%)RvvQmg{ zWm6NhWY-+xE^2^dw70j9jv5v8ao;9GYB48Io`hSdU%Lii1w%$6ACi%ZB%K7z^+wp9 zEG999Ai9)9mh(Bua!qeM5G_g|I5HA_%y8+?(M1mm zh~DHUaSq&5!XP%?MR%3q(qOPg?oD0Y*NKT^ivz{9aaqvrBigoqXFENr5^k%P04q{! z18)oEb#HI2<3xK8@Ir`f<9M4P>N&Y_Kng(g5m`EfqPH@JTh-La1PGQjJn}#aiC4$l z9+S~4P^XB4Pnl2vvtanim7S9_G+)tBREr!bm1m68D>5U5FQA)Ce~!Ezo^*ziG9+J- z7f9_wUQ<(3;J%8AicYjQp&y7rfhjF6-rbrASENoMfhg%`@buhmj^uZp4luKv0s75Q&8zOr#YexOkjl}#b_hd18OSy*M8_>*DYc34I+K(4V(H>ofO+?| zhRju&J=gXIy7P+^kX-&4!v&C8si>%)<~J~iO5-7!*0p|k013lFLyLos9$0H%xig=$ zv9SS+%gb4LwdY_)96kIQ65TZwm4PbHvRQpK*wTM8PC?%SWfl>V#0ZuJke}y?OHY>L zT5&#uFMcl<7Z*7+;;iNZ1mU*GgkIhF3CJu68Tdup>x*CHk6VH#BV@e* z(_XxIA@*Qe_g8`|m^#VtaDVL31yFB&9c{kuF@#GN5<3(*DiP5u5RqDsl~Rk~SLmfQ zstiXPc5NOCi6L51%LhySE#Xbab4XH5Cq4p4TSwCm)??fW^t?k zb_qc!pbG?|HfQi3SF^Uh{1#GN)#1VJ{69>U*ah7d{nqc#pX+D|{l7!O#3U;4j-!>P2vcs)< zxZ&z#^YN1m0z?0}!~C!5X<;D$!M5X*&5;&c;%MZ~KXi9jR95bIE0mLzRNFHK^#JMN z5)cpoW(bN+I^)rtuOS& zI^Z5dsY0?X=KtBS!8gwTd_pxo6=VFv>T+*@ATZwmz^)fmb`>axYw#Ml+6=rm4reR~ zV|er8h1OW%2SJ(>WCf0W`G#PTNKQ?MEoD3eX8@?42LAn?d`0!zHIABt3T3C27r%b_ zWoK(gu&Hzrs$45B8%yuJV?8X&C+!2omdl>5xxavrkkG}8P5`RO4!ICyX%d<he(uF``iUV`yPnD2UTehlC5PY+10MV#SK zv2JMCjuj!_{VD@=z|u|;>amy9-UuYKN$roBn=iR}rYS{KS30FyEst7LaE`9uB?c=K zZguz`6#MjM7hJm*H^1S*sj{=$7*@iqJ?t_i1^Zu!2tw}{|CA(rr?TN@#Atrz>+Pja zB{gkDEatb-31#|CefKX6{0oGxwpn(;MG>}yAyyW@^CXNLHa?G3Bl zKmdw}+9J$_tAX4c+W0b1cXzhB2X2Tu_m}j6Pjo@H`h9_%ah9sNa&1Fqh zRfA%Sun_6Q2?_*Rzre+%`@yO+keGr_#KA75V7!wHkxiRiI~_nowz{z)JW_^k{w*8m z4uQ`9@`PMuuI$Kz!eGQDeYm#<6z~3iW#IdVmq`$YnYBbLqN%!|ksTVs$PQ!bb zyy#GsJlL9miIK=q%+V+P@6BO=6Oz@T+LP4p7zoo`K=c|K?K;NZC0^V2Jv|%VeyD)q zG!m?1WF!sTFo4HsUW2#WIZ-F%(d_4>U0}379zYH(e(j!d-el@^^wU!}Zr&6W6jU!W zPH{!!A=r7UC2DJH3x<>xA3qYGNAWJ^t^mz6uniCYj6Y%YxO$5WO@Xfqs&}$eQho(d z8)0>i>Ez-e^-X|KE8W+gQgXL>8Kn@Rw@1v)&7GW_VD>pJ!+-r)s5>5lpQ~SzZBXU_ z1TM89CR_;*v50y5)?@a2a&L}KD4#;aQ86oSjp64vC{-JG524!%gK{QK6krN>?~q(m zgPu;IZ&FUp}&uTnSou)ca?oRghhuTclq<(81}gr@N`YPNgl zCC?Hf!yz8+sy#4)LfTA$w1B3jkPbdbx`)003XqinR5`KxlUMKEdp9fZfHngr`rF&v zK>h>Xy3q{F0ifbX+`P-4;Jq;bS>kE_)W(^UN5SN<-au_UyS@Vm@hRWr^D`3CEa(;= z3<1UilA-ke)V163F`05dO;Mb|%+1RSFppls)eabOg}xi~KCpeS>!I(cs;asoFRws- zpBgo_`}yfQT)^b4yT~3?CIh0G(U~; z$hjL~oB<(9NkhX`@nQ!Buq0PiRGQn{wP$=n1|d5A9s@&a{PF%2R9M41ci;sa?-UUs zR@f>d8O!!K(=U&qtH18d+lYGQ<)+3kdU_$7%lDeFok27qXf#d$Ct$a`@jFMSpfqXi zw9pY+y2{SZ4)gG{GCp2FcPRFmNun|I>4oUL)>#+~AktgI#qsdo}cb0JZp*VDB8-x%e!@~(a zJJy{+TvwWvQyDUkBROu+*ub)M|H4M2NYdr@oja0lOT&QQLZ!ijp$cT?KzsnPoTtrQ zfn`Sxuf+)!9$uMN>^?ZnnZ^}jq;>?PH2DA_#KE^}A!pSZHqEdbd95fei2ie%@=!8* zVXMn;>jI94^3}7UHqZP95YBaJ*jjyt-A3y@t1}KKKyw0SY$QG$h-}iYU%!CKsshgV zhcoOjdw^ETc>-kNG!qlknKL~wN9YWCjfDl4SHT;^0rmwPcgir>`usM1a{YB^ji^3; z{J79pU|eYOXdV3U5jeLNgid&9sOMZ-48T;p&XU(K(MB@oQp2Tfy52PdVaHN|eW10~ z$ps%rFEzbn1$6{um!cnFUo=-9oJ)*(xR6)&R>+p4f=ckH(b21Lwg&oVZ+~Br+Dy9T zILpmc#3UKGdLK|3onloA=Bv+rB_oXz4bfa8BAf6qeOMDP%d`4zPhoqIx#@4QkT(E3 z76!qCxEKP_-BJAu6u-yAhkFxDhgid4gdq_@4BWQ<{DeGNU{s~=%wqNj62G0klhX=l zK~PQ}D8#4viYFl4><0Y_N#(Cx@%HjkpgxE8Zlw#rnRj$__=0jkk^0=}8lV`$U{W;v zmC3jAUh`>X<)Gr)_wbT_yxF!r#wu0e;#P&!T<20!GPhGsDm zn)--{_ZHviI)gINe!D;V^XJbnq11RSkPM@@6x-{BXyZU{CO|{QtAB=(@t}z{JQ#Xe zv;lwY1(b3Ozp)SO2DHTIj@}PdW@$=q2mWJknCEn;qHS6n>>p%;*gr5|FSG8R?o?)? zGz^|c-#>Tk(Xr$3tzy^T`ml^sXxsl0mI31{byx<}Q&Z2cK}9C-s|(d)W%-domuA7_8bFIw&yfV(m_UXr^5L>_-69nQT5OY0E)Q0yc{^) zGTS~4XWneIIu~j{b+ZRNtDq1#E8p`RLfs^2V|gqwI=ay({ZwGvK<^q4`r3T1gQMgafICB$R}@_OmL<_I7SY%kNn*BQZqcw)Vb zenAfaG{UD@eI8JBA<_0Qp@)PO7b8H2dJkc1bMy9mPC+!kv4dlQ*WJ6UYL|psARPz< ztgfy?E2pTWRBAVH!PKP%8 zJRMQoI=?0+I5pyCr>7yvLcc<DjotZ>mBWIQ$AxCT;Fa}V! zTil7elc5}}|Edh6MbmR;AHW4hpDojN)z@d>-7|amYxeF>Hoa_Wx(e$T1H1Qd{ioQ$ zx3Z2H#Z{jWV2w+`(SVNhL32az_ODQWNcFH_a1x4s;8N!A&-Y|O+0DE2F=FlXbRGDn z)=QA2fyV+t4I)Q*XWmkj><_2=FS$Vr)75^7w5RI7sF1vQ5=;Gwp-HCN{ zbUI7=sn951ncP1Ov%`tX!0q!)fk2!P1te!@Uqk)UwgkA?fVw}!pm5}?r#kQJCBIXX zkqU~F^er4xc!^UpVQ)ItQ9Dl`WILP{R0j7Vu3Xqt!yqnfi7~;?pKtvAd&V#n#4mWV z?*MZ`KynKRXgRZ#hQfMHVSWep9N=e(&hkgyTI&-i%D_uB5+vV*kQ6~KkwyNe3YVg| z0S^E{KM2%Vt~?IrBS;sMt^*n{vjMdR%&Cd^~UD%~HzL^?w4 zOyJ@)p`S!Zc=+b#COHNJ%>ID_Wbo<8*RQt#&p)RVy5`KX6-r#7E7-t!%x|g!1P6d^ zXF3u)+=*|ayZ!)_GiYs>_Ie0ZltQ2XA+*<^3;stKH?F|%C z_{a^VrL!iFDzQV?I~8ztL3HCH(ImR{D-`}L2H_wO@?WKxz^x9#E2)xI`8klnk!z=^ z&^mcW8*l)0hX9?9J_2I~fjR|k0MS7Osa!nJRY~ul@PhKOa3ciYhD9*eI`d=^cM^c4_IOt81iX8;z93GZ52!sUZa-u)JLK(xp|v zQ?R+zhNScAkC=HbT%bGn+wHqJCR0!@`pcDH^nwb-$cV3F@BBi&0%QEKLg`}54scY4 zBVcOs?D2upLvU1C$K~Cwu8k2ELUt7o-H2-b^C4}`#PhuiFuEYyQ-T%$9x6+e@^q~a zJ_Q1=mvmRRNzb%^#%-m?HE$~_%B@WxNr^?Dv)j8K(xX^gb2F??D(PC5)5-4t545B|jtoyj-)lnzhgu_Hd#*Dr(GoJ*snz6!}a^ zO$`mx;qS6Bhrth7v-;n)8jt^MPE}^QIA4@q#uhK`J36~ei2Q_E9+r-7eqw^P0?Spq z#a!vUeP1#$<^6Eoh$` z8=nK82`WQpUae;_#d|K#HK9^Lw;PqOA0oR^GE` z&j5Vn=@q9RVW3A5bk1|G<=VS4yBk$E5;dD5-f_l?9Cmzsu(Y%k!3L!Rq!Y8w6>zW0 zN=eWYGBG9k`S}4Rq&K8Qxbh1N1;ANh?(04IQdyx7KS+oRL(U*7Aj-z}yD@Bceq)C| zqDM28_LJQJbi>=b#sCiAzI@5@BxRUm2jp3vp2e+LKV7I@po%~#P42Q?H){awfY$^jU&FERN* zpK|Q@$tL?05Swb}tgo!hfr$CgjlhHv1ijvXs6h_&`CVqo4T~%LrFjNpG(s1WK3oPW z&F9ct^y1A3X&0yMwoWHAwYFFa4jQSG4{T$%0J#2L9Jra&yR*9sy_|5R4^o~77!4Bq zN!m-3M;MV*P4Nvn(Eaei`CCg=?2m$u_Gb6m2B6}eF8=oA=KhqSSIoj+Dd6)tkcxL{ z=kJGnP%Mz26@LYD{e*=4POA_4dD=N?>I6yU0DeJytr;t<(%@e>2sH?#@PLu~ zfZ72)3?NgbfsUG}VGd9UgJvaO?17R4#s1#jnG=SH@B(O+KsjXe$<-djND!?QH>5F& zFNYMw&Ok#sDO>~sbr7qks2($M2gD(f%ZbUMJ@FWH5Um;OAj29+Q>D(+rl+Clf1l-oXP0h{ju)`p59?Um{rn#2Ejti3m zWEIFKu4Z(@dvx7BK7TQ!Zm;WA`U#kQ`Icb(@(%=d;(P${&(XIIV>J(VJ(V0{f_) zLx#a5sT1UW0Wt}uHYK2TY*+1P_AeaG9#V+c(9zZ98e5>kVv{>KX;$4sz?g8{ zLfe@a>&I+|{iyz`xizpv-ySq!))aWEzy)1|$uxjNX&xRmxF~@67RbmOpoy4Lcojq3 z8WVrXlPL3!mzS5RDGR(Utz2d$cnPGO?;QB^FxaVv2jm%kicS=U-&x6fR2|fZP#l@{ z)s;?E8f=Zc1B-$*UH#3aG|1MV`MgSy{N@f2x!`f2KnHm=3MlCTEg1sYT$~lou(ISBG;=t$rQkik$r8~_odLt=sArJ|%<2UHKeqcIdIR{!sB zf#8wL=!Wa&g*(4~%>Xc&vVh-a0|!pP3*y~IPZ?rvJ!Sqtyn4wrUZc!y*+?Y_`l-F#2dy243v~YFy9A7Ed<8AB6g4u z9J-+JBS`8C3JMsW@>m4807*l^p$75i{xgUg>Jf}FSX2)CIJDu$HYIp?cppLvt-!e& zKxB)?tvhkgb5zxP?mTA@5jZ+R$&9n zC8~^kf7KI%KKRWWy(%?PX67WIgTUwxS9}U^skq#q4+x{r$kQIcGgNX)kU0~{ zVF>>fGxxcGcCjka2dXKW_)8lQ=5RO+^n9pnQB@u*ukzoead#qIW-|FE$euMdH9OPl zc2IpIOy|Zc3FbqY1GCPYIRocbbWbV{D!d*9Y7{DE6}aO+4OyW80gIZ31H}}#9R$mj zSWE+?S;!Anpgmz>LFL<1pw!m}1vRt~5m!2a2gvEQDH&vx@(>jh3*jT9vI7kch$TSe z2mCVHre6d!48#7Z?w!?WuA_RyaZZM-)D51S-{^4n@7x0znLXwEHhl+ZX%G|wExr6bIRF+3r+CKsV9W>I1kV!`09KxRD%>dv z^abdcY3b;8+5|g-^9i+~*`L4m-?f809+2IGx#Bsmy_K)PApj|99!w19HSim`j;e+h zoWt_)s8C9M8E*QW;{w`q!GIHTu^OEFqAVMJC?0Dx$=i$~MWZc%D;n1Yg$y#lK%Z)GUA$pjCNPFw)L>R7s1Ai}Ua-{_DsQp&SOI z1>P4GmG(bDB_blynMS+;JaK}ww+CbpSik@*z~uh|Uj(ASGyzWvPll5|cqLri+!Am? zN+V+k_~iKbczAd9k`O>N;B4z~v4 zDmk+hiota@aH;_2Hmz-K!w~LHPDMurgDyc*_#1CR#H*| zq2>pDds$gO$`9y+2}!9W|I{9Xtj7yfQ0vVR6h}|b%(V9T9w#8sHH&=+LlQV^1B9>i z_GBbnhf+qZ+DF&HF%W&}*nT*{scKCjvo#(75}mdLsi7MrkJrJ_+_*n+(X~EF7}>f!5ovLqkJ#b#l(uzAu44fpdum2M6#- z^jxuRdf$R(oG65dgZ)2^(UaM(cLT+i(1rk!1Jrz>3!FscM#t*owRrIwZhyw>fc4_7$M&0Egg(|2y@PMJ@9qE%l!Bo?bdH_f{i=(_L zs#t_1Deb*83^nAb*8wPtE!7h$-CLuN$H!HSRt~(+U3^@;re`^0+|v39Z1AqUT$$1R z9^^yFxpt7W&y8Wwyxaf5-`^iVPHXZkl*58xo2#+qcAY5$H#3w#rmw9xFkf?ci$!IK z{k&3YmQ~li=@iAoy%`yLBbo205L0ERM))FR5nkTk@Di&73P;7SL)^z7&h>fCrFk2a z`54}~(Q0wNicQ@W*Z*tos$w<6lAgE;w-xEK7RPG|&%tR$5TE7ZF(w`E( z_`z*C=8~Xt&&(KSP()9|x8F1SyG$OlERna#hC%$7Gz#dptGhdAs2*AZzOWFn2NO!( z;R_wkI4&9~kCm1vj;zy}^!`}Cm4E8q83|9`T`7>X1bi~t`q$-}GNFwsdpe;Vz!tA^ zi849;v9ebNhKA_(DMIT^OzXm zzK5NTRYD4>=d*?uboz%fN*$_RNSG(#gM3By!T1a*{7nIa=-&%K3k_>qEB^uv1+;Ih z*2WvV-i!b)&dz$&3zQnr#|jvG*PaDpU+Xa(6?#iXuhgFKdwE)TU|@Us_=OgB>rl4! z9;@e8C3DK*5&l}lKxUGl@XMlRbF@ap5qPS8^#VsdeUC2#VqXWuN-8TY%N!`~-evM! zyx1v(?+a<*bv>|=5K%BJD}!K%5n+kr7?7%e0G3f2Qfr}7-a>0s6Iy7EDuCc%CxXN( l!Tj8g?&w$l^Wos(@yn(oe^Xjzu<(|MilT->zPyS5{{u5>fa(AM literal 17231 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 diff --git a/tests/drawing/cairo/baseline_images/graph_directed.png b/tests/drawing/cairo/baseline_images/graph_directed.png index c85c3b668ad66ff9355f7e9d467ecfa5019c9c6a..83d6e37647f1b6fe90f88f080974afea8573013d 100644 GIT binary patch literal 17353 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 z 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 mMB}CUMZX3{Qm%)pbLxu literal 17911 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 diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png index c85c3b668ad66ff9355f7e9d467ecfa5019c9c6a..83d6e37647f1b6fe90f88f080974afea8573013d 100644 GIT binary patch literal 17353 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 z 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 mMB}CUMZX3{Qm%)pbLxu literal 17911 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 diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png index 51608e9245d547b872aedea2c1cbae494eaaeab4..c5372745cb597e2bbd728fcaa117abd639f956cb 100644 GIT binary patch literal 14924 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 literal 15413 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 H*&F`{ Date: Thu, 12 May 2022 14:20:12 +0200 Subject: [PATCH 0968/1892] feat: added safe_locale() context manager --- src/_igraph/igraphmodule.c | 60 ++++++++++++++++++++++++++++++++++++++ src/igraph/io/utils.py | 23 +++++++++++++++ vendor/source/igraph | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/igraph/io/utils.py diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 028cfea79..2c67c5bd6 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -623,6 +623,54 @@ PyObject* igraphmodule_split_join_distance(PyObject *self, return Py_BuildValue("nn", (Py_ssize_t)distance12, (Py_ssize_t)distance21); } +#define LOCALE_CAPSULE_TYPE "igraph._igraph.locale_capsule" + +void igraphmodule__destroy_locale_capsule(PyObject *capsule) { + igraph_safelocale_t* loc = (igraph_safelocale_t*) PyCapsule_GetPointer(capsule, LOCALE_CAPSULE_TYPE); + if (loc) { + PyMem_Free(loc); + } +} + +PyObject* igraphmodule__enter_safelocale(PyObject* self) { + igraph_safelocale_t* loc; + PyObject* capsule; + + loc = PyMem_Malloc(sizeof(loc)); + if (loc == NULL) { + PyErr_NoMemory(); + return NULL; + } + + capsule = PyCapsule_New(loc, LOCALE_CAPSULE_TYPE, igraphmodule__destroy_locale_capsule); + if (capsule == NULL) { + return NULL; + } + + if (igraph_enter_safelocale(loc)) { + Py_DECREF(capsule); + igraphmodule_handle_igraph_error(); + } + + return capsule; +} + +PyObject* igraphmodule__exit_safelocale(PyObject *self, PyObject *capsule) { + igraph_safelocale_t* loc; + + if (!PyCapsule_IsValid(capsule, LOCALE_CAPSULE_TYPE)) { + PyErr_SetString(PyExc_TypeError, "expected locale capsule"); + return NULL; + } + + loc = (igraph_safelocale_t*) PyCapsule_GetPointer(capsule, LOCALE_CAPSULE_TYPE); + if (loc != NULL) { + igraph_exit_safelocale(loc); + } + + Py_RETURN_NONE; +} + /** \ingroup python_interface * \brief Method table for the igraph Python module */ @@ -751,6 +799,18 @@ static PyMethodDef igraphmodule_methods[] = METH_VARARGS | METH_KEYWORDS, "_intersection(graphs, edgemaps)\n--\n\n" }, + {"_enter_safelocale", (PyCFunction)igraphmodule__enter_safelocale, + METH_NOARGS, + "_enter_safelocale() -> object\n--\n\n" + "Helper function for the L{safe_locale()} context manager. Do not use\n" + "directly in your own code." + }, + {"_exit_safelocale", (PyCFunction)igraphmodule__exit_safelocale, + METH_O, + "_exit_safelocale(locale: object) -> None\n--\n\n" + "Helper function for the L{safe_locale()} context manager. Do not use\n" + "directly in your own code." + }, {NULL, NULL, 0, NULL} }; diff --git a/src/igraph/io/utils.py b/src/igraph/io/utils.py new file mode 100644 index 000000000..ae56a1281 --- /dev/null +++ b/src/igraph/io/utils.py @@ -0,0 +1,23 @@ +from contextlib import contextmanager +from typing import Iterator + +__all__ = ("safe_locale", ) + + +@contextmanager +def safe_locale() -> Iterator[None]: + """Helper function that establishes a context that temporarily switches the + current locale to use decimal dots when printing numbers. + + This can be used to establish an execution context within which it is safe + to call functions that read or write graphs from/to the disk and ensure that + they use decimal dots for interoperability with systems that are running + with another locale. + """ + from igraph._igraph import _enter_safelocale, _exit_safelocale + + locale = _enter_safelocale() + try: + yield + finally: + _exit_safelocale(locale) diff --git a/vendor/source/igraph b/vendor/source/igraph index 136601826..186ac9359 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 136601826532906269dd5d09540d9f7f6c1fe682 +Subproject commit 186ac935906ef23ff86cbf81f2909c2009afa588 From 1331d143ecf0dbd3aad30371ea382d5ef8a2d884 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 25 May 2022 11:41:19 +0200 Subject: [PATCH 0969/1892] test: extended community_label_propagation() unit test to decide whether #541 is a bug or not --- tests/test_decomposition.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 21e25e6f8..788fe08b2 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -266,11 +266,11 @@ def testInfomap(self): cl = g.community_infomap(edge_weights=e_weights, vertex_weights=v_weights) def testLabelPropagation(self): - # Nothing to test there really, since the algorithm - # is pretty nondeterministic. We just do a quick smoke - # test. + # Nothing to test there really, since the algorithm is pretty + # nondeterministic. We just do a few quick smoke tests. g = Graph.GRG(100, 0.2) cl = g.community_label_propagation() + g = Graph([(0, 1), (1, 2), (2, 3)]) g.es["weight"] = [2, 1, 2] g.vs["initial"] = [0, -1, -1, 1] @@ -283,6 +283,22 @@ def testLabelPropagation(self): or cl.membership == [0, 0, 0, 1] ) + g = Graph.GRG(100, 0.2) + g.vs["initial"] = [ + 0 if i == 0 else 1 if i == 99 else 2 if i == 49 else random.randint(0, 50) + for i in range(g.vcount()) + ] + g.vs["dont_move"] = [i in (0, 49, 99) for i in range(g.vcount())] + cl = g.community_label_propagation(initial="initial", fixed="dont_move") + + # igraph is free to reorder the clusters so only co-membership will be + # preserved, hence the next assertion + self.assertTrue( + cl.membership[0] != cl.membership[49] and + cl.membership[49] != cl.membership[99] + ) + self.assertTrue(x >= 0 and x <= 5 for x in cl.membership) + def testMultilevel(self): # Example graph from the paper g = Graph(16) From 3595ff82e6f434458973dbd432b034cbe3c7031b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 25 May 2022 11:45:11 +0200 Subject: [PATCH 0970/1892] doc: document that community_label_propagation() preserves co-community membership constraints only --- src/igraph/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index b61a6b71f..0e1fe0c33 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1292,10 +1292,21 @@ def community_label_propagation(self, weights=None, initial=None, fixed=None): iteration. Ties are broken randomly and the order in which the vertices are updated is randomized before every iteration. The algorithm ends when vertices reach a consensus. + Note that since ties are broken randomly, there is no guarantee that the algorithm returns the same community structure after each run. In fact, they frequently differ. See the paper of Raghavan et al on how to come up with an aggregated community structure. + + Also note that the community _labels_ (numbers) have no semantic meaning + and igraph is free to re-number communities. If you use fixed labels, + igraph may still re-number the communities, but co-community membership + constraints will be respected: if you had two vertices with fixed labels + that belonged to the same community, they will still be in the same + community at the end. Similarly, if you had two vertices with fixed + labels that belonged to different communities, they will still be in + different communities at the end. + @param weights: name of an edge attribute or a list containing edge weights @param initial: name of a vertex attribute or a list containing From 53b03c59802e1fe59d4a555227ad555bc6a257e0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 4 May 2022 22:26:53 +0200 Subject: [PATCH 0971/1892] fix: edge drawing with labels now works again, closes #535 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b47a6f91..4512056b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,12 @@ ## [Unreleased] +### Fixed + +- Fixed a bug in the Cairo and Matplotlib backends that prevented edges with + labels from being drawn properly; see + [#535](https://github.com/igraph/python-igraph/issues/535) for details. + ## [0.9.10] ### Changed From b06fd851f37bee996d4de0cbc5d78aebee3971db Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 25 May 2022 11:45:11 +0200 Subject: [PATCH 0972/1892] doc: document that community_label_propagation() preserves co-community membership constraints only --- src/igraph/community.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/igraph/community.py b/src/igraph/community.py index aebce6142..84d52edf9 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -151,10 +151,21 @@ def _community_label_propagation(graph, weights=None, initial=None, fixed=None): iteration. Ties are broken randomly and the order in which the vertices are updated is randomized before every iteration. The algorithm ends when vertices reach a consensus. + Note that since ties are broken randomly, there is no guarantee that the algorithm returns the same community structure after each run. In fact, they frequently differ. See the paper of Raghavan et al on how to come up with an aggregated community structure. + + Also note that the community _labels_ (numbers) have no semantic meaning + and igraph is free to re-number communities. If you use fixed labels, + igraph may still re-number the communities, but co-community membership + constraints will be respected: if you had two vertices with fixed labels + that belonged to the same community, they will still be in the same + community at the end. Similarly, if you had two vertices with fixed + labels that belonged to different communities, they will still be in + different communities at the end. + @param weights: name of an edge attribute or a list containing edge weights @param initial: name of a vertex attribute or a list containing From 07275849265ae25f114ac7d42aa09fb8e7932f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Thu, 26 May 2022 12:46:06 +0200 Subject: [PATCH 0973/1892] fix: union and intersection by name now verifies that there are no duplicate names --- src/igraph/operators/functions.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/igraph/operators/functions.py b/src/igraph/operators/functions.py index 8c54443b3..94cff35d8 100644 --- a/src/igraph/operators/functions.py +++ b/src/igraph/operators/functions.py @@ -9,6 +9,13 @@ from warnings import warn +def name_set(names): + """Convert a list of names to a set of name while checking for duplicates.""" + nameset = set(names) + if (len(nameset) != len(names)): + raise AttributeError("Graph contains duplicate vertex names") + return nameset + def disjoint_union(graphs): """Graph disjoint union. @@ -135,7 +142,7 @@ def union(graphs, byname="auto"): if byname: allnames = [g.vs["name"] for g in graphs] - uninames = list(set.union(*(set(vns) for vns in allnames))) + uninames = list(set.union(*(name_set(vns) for vns in allnames))) permutation_map = {x: i for i, x in enumerate(uninames)} nve = len(uninames) newgraphs = [] @@ -319,9 +326,9 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): allnames = [g.vs["name"] for g in graphs] if keep_all_vertices: - uninames = list(set.union(*(set(vns) for vns in allnames))) + uninames = list(set.union(*(name_set(vns) for vns in allnames))) else: - uninames = list(set.intersection(*(set(vns) for vns in allnames))) + uninames = list(set.intersection(*(name_set(vns) for vns in allnames))) permutation_map = {x: i for i, x in enumerate(uninames)} nv = len(uninames) From c3ce00209dc93e8dc2a394cf546f53f282b87df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Thu, 26 May 2022 12:46:06 +0200 Subject: [PATCH 0974/1892] fix: union and intersection by name now verifies that there are no duplicate names --- src/igraph/operators.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 94c47fce4..7ffb7f3c6 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -9,6 +9,13 @@ from warnings import warn +def name_set(names): + """Convert a list of names to a set of name while checking for duplicates.""" + nameset = set(names) + if (len(nameset) != len(names)): + raise AttributeError("Graph contains duplicate vertex names") + return nameset + def disjoint_union(graphs): """Graph disjoint union. @@ -135,7 +142,7 @@ def union(graphs, byname="auto"): if byname: allnames = [g.vs["name"] for g in graphs] - uninames = list(set.union(*(set(vns) for vns in allnames))) + uninames = list(set.union(*(name_set(vns) for vns in allnames))) permutation_map = {x: i for i, x in enumerate(uninames)} nve = len(uninames) newgraphs = [] @@ -319,9 +326,9 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): allnames = [g.vs["name"] for g in graphs] if keep_all_vertices: - uninames = list(set.union(*(set(vns) for vns in allnames))) + uninames = list(set.union(*(name_set(vns) for vns in allnames))) else: - uninames = list(set.intersection(*(set(vns) for vns in allnames))) + uninames = list(set.intersection(*(name_set(vns) for vns in allnames))) permutation_map = {x: i for i, x in enumerate(uninames)} nv = len(uninames) From 2df9981e45a1140405c87e8b6c3a5a6f64ce1bfa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 May 2022 13:53:37 +0200 Subject: [PATCH 0975/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 23fa0e1d0..a40735082 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 23fa0e1d09ab64f14f343710a35c8f5832828ca8 +Subproject commit a4073508210db885e8e129bed628f6b091a52404 From b7e22dea20d0a5dd800b5abb01cab9e3f8544a84 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Jun 2022 11:41:24 +0200 Subject: [PATCH 0976/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index a40735082..b4fb32758 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit a4073508210db885e8e129bed628f6b091a52404 +Subproject commit b4fb3275822ed7608712022bfaf41b301cb7636b From c633aa2d2cd2c96b029d4b20d8887425b53c7db8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 11:58:51 +0200 Subject: [PATCH 0977/1892] chore: updated vendored igraph to 0.9.9 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b4fb32758..2f79050fc 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b4fb3275822ed7608712022bfaf41b301cb7636b +Subproject commit 2f79050fc219f045a23d2e42f72ebd18854a2e0e From bc9164237a95f52c7adc0f1ffc91976139566c91 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 11:59:09 +0200 Subject: [PATCH 0978/1892] doc: fix quite a few broken cross-references in the docstrings --- src/igraph/__init__.py | 67 +++++++++++++++++------------------ src/igraph/app/shell.py | 9 +++-- src/igraph/drawing/text.py | 15 ++++---- src/igraph/operators.py | 71 ++++++++++++++++++++++++++------------ src/igraph/remote/gephi.py | 28 ++++++++------- src/igraph/utils.py | 31 ++++++++--------- 6 files changed, 127 insertions(+), 94 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 0e1fe0c33..37030e87c 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -447,7 +447,7 @@ def add_vertices(self, n, attributes=None): def as_directed(self, *args, **kwds): """Returns a directed copy of this graph. Arguments are passed on - to L{to_directed()} that is invoked on the copy. + to L{GraphBase.to_directed()} that is invoked on the copy. """ copy = self.copy() copy.to_directed(*args, **kwds) @@ -455,7 +455,7 @@ def as_directed(self, *args, **kwds): def as_undirected(self, *args, **kwds): """Returns an undirected copy of this graph. Arguments are passed on - to L{to_undirected()} that is invoked on the copy. + to L{GraphBase.to_undirected()} that is invoked on the copy. """ copy = self.copy() copy.to_undirected(*args, **kwds) @@ -494,7 +494,7 @@ def delete_edges(self, *args, **kwds): def indegree(self, *args, **kwds): """Returns the in-degrees in a list. - See L{degree} for possible arguments. + See L{GraphBase.degree()} for possible arguments. """ kwds["mode"] = IN return self.degree(*args, **kwds) @@ -502,7 +502,7 @@ def indegree(self, *args, **kwds): def outdegree(self, *args, **kwds): """Returns the out-degrees in a list. - See L{degree} for possible arguments. + See L{GraphBase.degree()} for possible arguments. """ kwds["mode"] = OUT return self.degree(*args, **kwds) @@ -586,7 +586,7 @@ def biconnected_components(self, return_articulation_points=False): def clear(self): """Clears the graph, deleting all vertices, edges, and attributes. - @see: L{delete_vertices} and L{delete_edges}. + @see: L{GraphBase.delete_vertices} and L{delete_edges}. """ self.delete_vertices() for attr in self.attributes(): @@ -1065,8 +1065,8 @@ def transitivity_avglocal_undirected(self, mode="nan", weights=None): to the formula of Barrat et al (see the references). Note that this measure is different from the global transitivity - measure (see L{transitivity_undirected()}) as it simply takes the - average local transitivity across the whole network. + measure (see L{GraphBase.transitivity_undirected()}) as it simply takes + the average local transitivity across the whole network. @param mode: defines how to treat vertices with degree less than two. If C{TRANSITIVITY_ZERO} or C{"zero"}, these vertices will have zero @@ -1075,7 +1075,8 @@ def transitivity_avglocal_undirected(self, mode="nan", weights=None): @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. - @see: L{transitivity_undirected()}, L{transitivity_local_undirected()} + @see: L{GraphBase.transitivity_undirected()}, + L{GraphBase.transitivity_local_undirected()} @newfield ref: Reference @ref: Watts DJ and Strogatz S: I{Collective dynamics of small-world networks}. Nature 393(6884):440-442, 1998. @@ -1630,57 +1631,57 @@ def layout(self, layout=None, *args, **kwds): - C{auto}, C{automatic}: automatic layout (see L{layout_auto}) - - C{bipartite}: bipartite layout (see L{layout_bipartite}) + - C{bipartite}: bipartite layout (see L{GraphBase.layout_bipartite}) - C{circle}, C{circular}: circular layout - (see L{layout_circle}) + (see L{GraphBase.layout_circle}) - C{dh}, C{davidson_harel}: Davidson-Harel layout (see - L{layout_davidson_harel}) + L{GraphBase.layout_davidson_harel}) - - C{drl}: DrL layout for large graphs (see L{layout_drl}) + - C{drl}: DrL layout for large graphs (see L{GraphBase.layout_drl}) - C{drl_3d}: 3D DrL layout for large graphs - (see L{layout_drl}) + (see L{GraphBase.layout_drl}) - C{fr}, C{fruchterman_reingold}: Fruchterman-Reingold layout - (see L{layout_fruchterman_reingold}). + (see L{GraphBase.layout_fruchterman_reingold}). - C{fr_3d}, C{fr3d}, C{fruchterman_reingold_3d}: 3D Fruchterman- - Reingold layout (see L{layout_fruchterman_reingold}). + Reingold layout (see L{GraphBase.layout_fruchterman_reingold}). - - C{grid}: regular grid layout in 2D (see L{layout_grid}) + - C{grid}: regular grid layout in 2D (see L{GraphBase.layout_grid}) - - C{grid_3d}: regular grid layout in 3D (see L{layout_grid_3d}) + - C{grid_3d}: regular grid layout in 3D (see L{GraphBase.layout_grid_3d}) - - C{graphopt}: the graphopt algorithm (see L{layout_graphopt}) + - C{graphopt}: the graphopt algorithm (see L{GraphBase.layout_graphopt}) - C{kk}, C{kamada_kawai}: Kamada-Kawai layout - (see L{layout_kamada_kawai}) + (see L{GraphBase.layout_kamada_kawai}) - C{kk_3d}, C{kk3d}, C{kamada_kawai_3d}: 3D Kamada-Kawai layout - (see L{layout_kamada_kawai}) + (see L{GraphBase.layout_kamada_kawai}) - C{lgl}, C{large}, C{large_graph}: Large Graph Layout - (see L{layout_lgl}) + (see L{GraphBase.layout_lgl}) - - C{mds}: multidimensional scaling layout (see L{layout_mds}) + - C{mds}: multidimensional scaling layout (see L{GraphBase.layout_mds}) - - C{random}: random layout (see L{layout_random}) + - C{random}: random layout (see L{GraphBase.layout_random}) - - C{random_3d}: random 3D layout (see L{layout_random}) + - C{random_3d}: random 3D layout (see L{GraphBase.layout_random}) - C{rt}, C{tree}, C{reingold_tilford}: Reingold-Tilford tree - layout (see L{layout_reingold_tilford}) + layout (see L{GraphBase.layout_reingold_tilford}) - C{rt_circular}, C{reingold_tilford_circular}: circular Reingold-Tilford tree layout - (see L{layout_reingold_tilford_circular}) + (see L{GraphBase.layout_reingold_tilford_circular}) - C{sphere}, C{spherical}, C{circle_3d}, C{circular_3d}: spherical - layout (see L{layout_circle}) + layout (see L{GraphBase.layout_circle}) - - C{star}: star layout (see L{layout_star}) + - C{star}: star layout (see L{GraphBase.layout_star}) - C{sugiyama}: Sugiyama layout (see L{layout_sugiyama}) @@ -1730,14 +1731,14 @@ def layout_auto(self, *args, **kwds): 3. Otherwise, if the graph is connected and has at most 100 vertices, the Kamada-Kawai layout will be used (see - L{layout_kamada_kawai()}). + L{GraphBase.layout_kamada_kawai()}). 4. Otherwise, if the graph has at most 1000 vertices, the Fruchterman-Reingold layout will be used (see - L{layout_fruchterman_reingold()}). + L{GraphBase.layout_fruchterman_reingold()}). 5. If everything else above failed, the DrL layout algorithm - will be used (see L{layout_drl()}). + will be used (see L{GraphBase.layout_drl()}). All the arguments of this function except C{dim} are passed on to the chosen layout function (in case we have to call some layout @@ -3431,7 +3432,7 @@ def DataFrame(cls, edges, directed=True, vertices=None, use_vids=False): contain the vertex IDs as a sequence of intergers from 0 to C{len(vertices) - 1}. All other columns will be added as vertex attributes by column name. - @use_vids: whether to interpret the first two columns of the C{edges} + @param use_vids: whether to interpret the first two columns of the C{edges} argument as vertex ids (0-based integers) instead of vertex names. If this argument is set to True and the first two columns of C{edges} are not integers, an error is thrown. @@ -4031,7 +4032,7 @@ def __plot__(self, context, bbox, palette, *args, **kwds): L{Layout}, it will be passed to L{layout} to calculate the layout. Note that if you want a deterministic layout that does not change with every plot, you must either use a - deterministic layout function (like L{layout_circle}) or + deterministic layout function (like L{GraphBase.layout_circle}) or calculate the layout in advance and pass a L{Layout} object here. - C{margin}: the top, right, bottom, left margins as a 4-tuple. diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index 987507d4f..bc3b66272 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -202,7 +202,9 @@ def _render_sub(self, match): class ProgressBar: """ - A 2-line progress bar, which looks like:: + A 2-line progress bar. + + The progress bar looks roughly like this in the console:: Header 20% [===========----------------------------------] @@ -325,9 +327,10 @@ class IDLEShell(Shell): """IDLE embedded shell interface. This class allows igraph to be embedded in IDLE (the Tk Python IDE). + """ - @todo: no progress bar support yet. Shell/Restart Shell command should - re-import igraph again.""" + # TODO: no progress bar support yet. Shell/Restart Shell command should + # re-import igraph again. def __init__(self): """Constructor. diff --git a/src/igraph/drawing/text.py b/src/igraph/drawing/text.py index 2895d9061..ff55a7ea3 100644 --- a/src/igraph/drawing/text.py +++ b/src/igraph/drawing/text.py @@ -34,8 +34,9 @@ class TextDrawer(AbstractCairoDrawer): TOP, BOTTOM = "top", "bottom" def __init__(self, context, text="", halign="center", valign="center"): - """Constructs a new instance that will draw the given `text` on - the given Cairo `context`.""" + """Constructs a new instance that will draw the given ``text`` on + the given Cairo ``context``. + """ super().__init__(context, (0, 0)) self.text = text self.halign = halign @@ -78,7 +79,7 @@ def draw(self, wrap=False): ctx.new_path() def get_text_layout(self, x=None, y=None, width=None, wrap=False): - """Calculates the layout of the current text. `x` and `y` denote the + """Calculates the layout of the current text. ``x`` and ``y`` denote the coordinates where the drawing should start. If they are both ``None``, the current position of the context will be used. @@ -92,7 +93,7 @@ def get_text_layout(self, x=None, y=None, width=None, wrap=False): @param width: The width of the box in which the text will be fitted. It matters only when the text is right-aligned or centered. The text will overflow the box if any of the lines is longer than the box - width and `wrap` is ``False``. + width and ``wrap`` is ``False``. @param wrap: whether to allow re-wrapping of the text if it does not fit within the given width. @@ -144,7 +145,7 @@ def get_text_layout(self, x=None, y=None, width=None, wrap=False): def draw_at(self, x=None, y=None, width=None, wrap=False): """Draws the text by setting up an appropriate path on the Cairo - context and filling it. `x` and `y` denote the coordinates where the + context and filling it. ``x`` and ``y`` denote the coordinates where the drawing should start. If they are both ``None``, the current position of the context will be used. @@ -158,7 +159,7 @@ def draw_at(self, x=None, y=None, width=None, wrap=False): @param width: The width of the box in which the text will be fitted. It matters only when the text is right-aligned or centered. The text will overflow the box if any of the lines is longer than the box - width and `wrap` is ``False``. + width and ``wrap`` is ``False``. @param wrap: whether to allow re-wrapping of the text if it does not fit within the given width. """ @@ -229,7 +230,7 @@ def text(self): def text(self, text): """Sets the text that will be drawn. - If `text` is ``None``, it will be mapped to an empty string; otherwise, + If ``text`` is ``None``, it will be mapped to an empty string; otherwise, it will be converted to a string.""" if text is None: self._text = "" diff --git a/src/igraph/operators.py b/src/igraph/operators.py index 7ffb7f3c6..ea74c7c7e 100644 --- a/src/igraph/operators.py +++ b/src/igraph/operators.py @@ -3,17 +3,27 @@ """Implementation of union, disjoint union and intersection operators.""" __all__ = ("disjoint_union", "union", "intersection") -__docformat__ = "restructuredtext en" +__docformat__ = "google en" from igraph._igraph import GraphBase, _union, _intersection, _disjoint_union from warnings import warn def name_set(names): - """Convert a list of names to a set of name while checking for duplicates.""" + """Converts a list of names to a set of names while checking for duplicates. + + Parameters: + names: the list of names to convert + + Returns: + the set of unique names appearing in the list + + Raises: + RuntimeError: if the input name list has duplicates + """ nameset = set(names) if (len(nameset) != len(names)): - raise AttributeError("Graph contains duplicate vertex names") + raise RuntimeError("Graph contains duplicate vertex names") return nameset @@ -30,8 +40,11 @@ def disjoint_union(graphs): An error is generated if some input graphs are directed and others are undirected. - @param graphs: list of graphs. A lazy sequence is not acceptable. - @return: the disjoint union graph + Parameters: + graphs: list of graphs. A lazy sequence is not acceptable. + + Returns: + the disjoint union graph """ if any(not isinstance(g, GraphBase) for g in graphs): raise TypeError("Not all elements are graphs") @@ -108,13 +121,20 @@ def union(graphs, byname="auto"): An error is generated if some input graphs are directed and others are undirected. - @param graphs: list of graphs. A lazy sequence is not acceptable. - @param byname: bool or 'auto' specifying the function behaviour with - respect to names vertices (i.e. vertices with the 'name' attribute). If - False, ignore vertex names. If True, merge vertices based on names. If - 'auto', use True if all graphs have named vertices and False otherwise - (in the latter case, a warning is generated too). - @return: the union graph + Parameters: + graphs: list of graphs. A lazy sequence is not acceptable. + byname: bool or 'auto' specifying the function behaviour with + respect to names vertices (i.e. vertices with the 'name' attribute). If + False, ignore vertex names. If True, merge vertices based on names. If + 'auto', use True if all graphs have named vertices and False otherwise + (in the latter case, a warning is generated too). + + Returns: + the union graph + + Raises: + RuntimeError: if 'byname' is set to True and some graphs are not named or + the set of names is not unique in one of the graphs """ if any(not isinstance(g, GraphBase) for g in graphs): @@ -130,7 +150,7 @@ def union(graphs, byname="auto"): if n_named not in (0, ngr): warn("Some, but not all graphs are named, not using vertex names") elif byname and (n_named != ngr): - raise AttributeError("Some graphs are not named") + raise RuntimeError("Some graphs are not named") # Now we know that byname is only used is all graphs are named # Trivial cases @@ -288,15 +308,22 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): An error is generated if some input graphs are directed and others are undirected. - @param graphs: list of graphs. A lazy sequence is not acceptable. - @param byname: bool or 'auto' specifying the function behaviour with - respect to names vertices (i.e. vertices with the 'name' attribute). If - False, ignore vertex names. If True, merge vertices based on names. If - 'auto', use True if all graphs have named vertices and False otherwise - (in the latter case, a warning is generated too). - @param keep_all_vertices: bool specifying if vertices that are not present - in all graphs should be kept in the intersection. - @return: the intersection graph + Parameters: + graphs: list of graphs. A lazy sequence is not acceptable. + byname: bool or 'auto' specifying the function behaviour with + respect to names vertices (i.e. vertices with the 'name' attribute). If + False, ignore vertex names. If True, merge vertices based on names. If + 'auto', use True if all graphs have named vertices and False otherwise + (in the latter case, a warning is generated too). + keep_all_vertices: bool specifying if vertices that are not present + in all graphs should be kept in the intersection. + + Returns: + the intersection graph + + Raises: + RuntimeError: if 'byname' is set to True and some graphs are not named or + the set of names is not unique in one of the graphs """ if any(not isinstance(g, GraphBase) for g in graphs): diff --git a/src/igraph/remote/gephi.py b/src/igraph/remote/gephi.py index aa3075cfb..e1338b92d 100644 --- a/src/igraph/remote/gephi.py +++ b/src/igraph/remote/gephi.py @@ -18,11 +18,11 @@ def __init__(self, url=None, host="127.0.0.1", port=8080, workspace=1): """Constructs a connection to a Gephi master server. The connection object can be constructed either by specifying the `url` - directly, or by specifying the `host`, `port` and `workspace` arguments. - The latter three are evaluated only if `url` is None; otherwise the - `url` will take precedence. + directly, or by specifying the ``host``, ``port`` and ``workspace`` + arguments. The latter three are evaluated only if `url` is None; + otherwise the ``url`` will take precedence. - The `url` argument does not have to include the operation (e.g., + The ``url`` argument does not have to include the operation (e.g., ``?operation=updateGraph``); the connection will take care of it. E.g., if you wish to connect to workspace 2 in a local Gephi instance on port 7341, the correct form to use for the `url` is as follows:: @@ -233,10 +233,11 @@ def iterjsonobj(self, graph): def post(self, graph, destination, encoder=None): """Posts the given graph to the destination of the streamer using the - given JSON encoder. When `encoder` is ``None``, it falls back to the default - JSON encoder of the streamer in the `encoder` property. + given JSON encoder. When ``encoder`` is ``None``, it falls back to the + default JSON encoder of the streamer in the `encoder` property. - `destination` must be a file-like object or an instance of `GephiConnection`. + ``destination`` must be a file-like object or an instance of + `GephiConnection`. """ encoder = encoder or self.encoder for jsonobj in self.iterjsonobj(graph): @@ -245,14 +246,15 @@ def post(self, graph, destination, encoder=None): def send_event(self, event, destination, encoder=None, flush=True): """Sends a single JSON event to the given destination using the given - JSON encoder. When `encoder` is ``None``, it falls back to the default - JSON encoder of the streamer in the `encoder` property. + JSON encoder. When ``encoder`` is ``None``, it falls back to the + default JSON encoder of the streamer in the `encoder` property. - `destination` must be a file-like object or an instance of `GephiConnection`. + ``destination`` must be a file-like object or an instance of + `GephiConnection`. - The method flushes the destination after sending the event. If you want to - avoid this (e.g., because you are sending many events), set `flush` to - ``False``. + The method flushes the destination after sending the event. If you want + to avoid this (e.g., because you are sending many events), set `flush` + to ``False``. """ encoder = encoder or self.encoder destination.write(encoder.encode(event).encode("utf-8")) diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 4b86e5dd6..35469626b 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -75,27 +75,27 @@ def numpy_to_contiguous_memoryview(obj): def rescale(values, out_range=(0.0, 1.0), in_range=None, clamp=False, scale=None): """Rescales a list of numbers into a given range. - `out_range` gives the range of the output values; by default, the minimum + ``out_range`` gives the range of the output values; by default, the minimum of the original numbers in the list will be mapped to the first element in the output range and the maximum will be mapped to the second element. Elements between the minimum and maximum values in the input list will be interpolated linearly between the first and second values of the output range. - `in_range` may be used to override which numbers are mapped to the first + ``in_range`` may be used to override which numbers are mapped to the first and second values of the output range. This must also be a tuple, where the first element will be mapped to the first element of the output range and the second element to the second. - If `clamp` is ``True``, elements which are outside the given `out_range` + If ``clamp`` is ``True``, elements which are outside the given ``out_range`` after rescaling are clamped to the output range to ensure that no number - will be outside `out_range` in the result. + will be outside ``out_range`` in the result. - If `scale` is not ``None``, it will be called for every element of `values` + If ``scale`` is not ``None``, it will be called for every element of ``values`` and the rescaling will take place on the results instead. This can be used, for instance, to transform the logarithm of the original values instead of the actual values. A typical use-case is to map a range of values to color - identifiers on a logarithmic scale. Scaling also applies to the `in_range` + identifiers on a logarithmic scale. Scaling also applies to the ``in_range`` parameter if present. Examples: @@ -191,7 +191,7 @@ def str_to_orientation(value, reversed_horizontal=False, reversed_vertical=False def consecutive_pairs(iterable, circular=False): """Returns consecutive pairs of items from the given iterable. - When `circular` is ``True``, the pair consisting of the last + When ``circular`` is ``True``, the pair consisting of the last and first elements is also returned. Example: @@ -251,15 +251,14 @@ def __init__(self, *args, **kwds): self.update(kwds) def __contains__(self, key): - """Returns whether there are any items associated to the given - `key`.""" + """Returns whether there are any items associated to the given key.""" try: return len(self._dict[key]) > 0 except KeyError: return False def __delitem__(self, key): - """Removes all the items associated to the given `key`.""" + """Removes all the items associated to the given key.""" del self._dict[key] def __getitem__(self, key): @@ -286,8 +285,8 @@ def __len__(self): return len(self._dict) def __setitem__(self, key, value): - """Sets the item associated to the given `key`. Any values associated to the - key will be erased and replaced by `value`. + """Sets the item associated to the given key. Any values associated to the + key will be erased and replaced by ``value``. Example: @@ -299,7 +298,7 @@ def __setitem__(self, key, value): self._dict[key] = [value] def add(self, key, value): - """Adds `value` to the list of items associated to `key`. + """Adds ``value`` to the list of items associated to ``key``. Example: @@ -321,8 +320,8 @@ def clear(self): self._dict.clear() def get(self, key, default=None): - """Returns an arbitrary item associated to the given `key`. If `key` - does not exist or has zero associated items, `default` will be + """Returns an arbitrary item associated to the given ``key``. If ``key`` + does not exist or has zero associated items, ``default`` will be returned.""" try: items = self._dict[key] @@ -331,7 +330,7 @@ def get(self, key, default=None): return default def getlist(self, key): - """Returns the list of values for the given `key`. An empty list will + """Returns the list of values for the given ``key``. An empty list will be returned if there is no such key.""" try: return self._dict[key] From 2954aa6c1bb3244180d128e157b704b187168f82 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:02:17 +0200 Subject: [PATCH 0979/1892] chore: updated changelog --- CHANGELOG.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c632f8de0..7306a001e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,19 @@ # igraph Python interface changelog -## [Unreleased] +## [0.9.11] + +### Changed + +- Vendored igraph was updated to version 0.9.9. ### Fixed +- Graph union and intersection (by name) operators now verify that there are no + duplicate names within the individual graphs. + +- Fixed a memory leak in `Graph.union()` when edge maps were used; see + [#534](https://github.com/igraph/python-igraph/issues/534) for details. + - Fixed a bug in the Cairo and Matplotlib backends that prevented edges with labels from being drawn properly; see [#535](https://github.com/igraph/python-igraph/issues/535) for details. @@ -274,7 +284,9 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.9..master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.11..master +[0.9.11]: https://github.com/igraph/python-igraph/compare/0.9.10...0.9.11 +[0.9.10]: https://github.com/igraph/python-igraph/compare/0.9.9...0.9.10 [0.9.9]: https://github.com/igraph/python-igraph/compare/0.9.8...0.9.9 [0.9.8]: https://github.com/igraph/python-igraph/compare/0.9.7...0.9.8 [0.9.7]: https://github.com/igraph/python-igraph/compare/0.9.6...0.9.7 From 48e78b2f2c89057cc35b4cb95e86fee5bac988f1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:10:20 +0200 Subject: [PATCH 0980/1892] chore: bumped version to 0.9.11 --- doc/source/conf.py | 4 ++-- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 0a6a3ceee..927fa1f81 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.9.10' +version = '0.9.11' # The full version, including alpha/beta/rc tags. -release = '0.9.10' +release = '0.9.11' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/igraph/version.py b/src/igraph/version.py index a93fdc77e..ca101d47f 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 10) +__version_info__ = (0, 9, 11) __version__ = ".".join("{0}".format(x) for x in __version_info__) From ca286bc47c5c4fc07765ced5160479685fc1337c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:10:33 +0200 Subject: [PATCH 0981/1892] ci: trying to build wheels for musllinux (i.e. Alpine) --- .github/workflows/build.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7d490e39..214f288b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,6 @@ on: [push, pull_request] env: CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" CIBW_TEST_EXTRAS: "test" - CIBW_SKIP: "*musllinux*" CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" @@ -31,10 +30,10 @@ jobs: python-version: '3.8' - name: Build wheels - uses: joerick/cibuildwheel@v2.4.0 + uses: joerick/cibuildwheel@v2.6.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" - CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" + CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }} *-musllinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit # wheel for Linux yet CIBW_TEST_SKIP: "cp310-manylinux_i686" @@ -58,11 +57,11 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Build wheels - uses: joerick/cibuildwheel@v2.4.0 + uses: joerick/cibuildwheel@v2.6.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 - CIBW_BUILD: "*-manylinux_aarch64" + CIBW_BUILD: "*-manylinux_aarch64 *-musllinux_aarch64" - uses: actions/upload-artifact@v2 with: @@ -104,7 +103,7 @@ jobs: brew install ninja autoconf automake libtool cmake - name: Build wheels - uses: joerick/cibuildwheel@v2.4.0 + uses: joerick/cibuildwheel@v2.6.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -162,7 +161,7 @@ jobs: shell: cmd - name: Build wheels - uses: joerick/cibuildwheel@v2.4.0 + uses: joerick/cibuildwheel@v2.6.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 4f12d08991af4562f2f57c32d5b2d8cd52bd5aa4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:25:55 +0200 Subject: [PATCH 0982/1892] doc: fix one more broken link --- src/igraph/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 35469626b..100fb09f1 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -233,7 +233,7 @@ class multidict(MutableMapping): values for the same key. Each value in this dictionary will be a list. Methods which emulate - the methods of a standard Python `dict` object will return or manipulate + the methods of a standard Python ``dict`` object will return or manipulate the first items of the lists only. Special methods are provided to deal with keys having multiple values. """ From f9e44be7d6afffa011e0848a9dd9d4bc2de9fe46 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:33:09 +0200 Subject: [PATCH 0983/1892] ci: in musllinux images, use apk instead of yum --- .github/workflows/build.yml | 23 +++++++++++++++++++---- setup.py | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 214f288b4..0a3e8facc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,15 +29,22 @@ jobs: with: python-version: '3.8' - - name: Build wheels + - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" - CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }} *-musllinux_${{ matrix.wheel_arch }}" + CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit # wheel for Linux yet CIBW_TEST_SKIP: "cp310-manylinux_i686" + - name: Build wheels (musllinux) + uses: joerick/cibuildwheel@v2.6.1 + env: + CIBW_BEFORE_BUILD: "apk install -y flex bison libxml2-dev zlib-dev* && pip install cmake && python setup.py build_c_core" + CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" + CIBW_TEST_EXTRAS: "test-musl" + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl @@ -56,12 +63,20 @@ jobs: id: qemu uses: docker/setup-qemu-action@v1 - - name: Build wheels + - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 - CIBW_BUILD: "*-manylinux_aarch64 *-musllinux_aarch64" + CIBW_BUILD: "*-manylinux_aarch64" + + - name: Build wheels (musllinux) + uses: joerick/cibuildwheel@v2.6.1 + env: + CIBW_BEFORE_BUILD: "apk install -y flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" + CIBW_ARCHS_LINUX: aarch64 + CIBW_BUILD: "*-musllinux_aarch64" + CIBW_TEST_EXTRAS: "test-musl" - uses: actions/upload-artifact@v2 with: diff --git a/setup.py b/setup.py index 3aef163d5..b5bc598e7 100644 --- a/setup.py +++ b/setup.py @@ -834,14 +834,27 @@ def use_educated_guess(self) -> None: scripts=["scripts/igraph"], install_requires=["texttable>=1.6.2"], extras_require={ + # Dependencies needed for plotting with Cairo "plotting": ["cairocffi>=1.2.0"], + + # Dependencies needed for testing only "test": [ "networkx>=2.5", - "pytest>=6.2.5", + "pytest>=7.1.2", "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", ], + + # Dependencies needed for testing on musllinux; only those that are either + # pure Python or have musllinux wheels as we don't want to compile wheels + # in CI + "test-musl": [ + "networkx>=2.5", + "pytest>=7.1.2", + ], + + # Dependencies needed for building the documentation "doc": [ "Sphinx>=4.2.0", "sphinxbootstrap4theme>=0.6.0" From a05be743898ee8a7fede73673e31f20126695f59 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 12:38:35 +0200 Subject: [PATCH 0984/1892] ci: relax pytest version --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b5bc598e7..594901e8e 100644 --- a/setup.py +++ b/setup.py @@ -840,7 +840,7 @@ def use_educated_guess(self) -> None: # Dependencies needed for testing only "test": [ "networkx>=2.5", - "pytest>=7.1.2", + "pytest>=7.0.1", "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", @@ -851,7 +851,7 @@ def use_educated_guess(self) -> None: # in CI "test-musl": [ "networkx>=2.5", - "pytest>=7.1.2", + "pytest>=7.0.1", ], # Dependencies needed for building the documentation From 75bcf2218b6236b8689edc7be72569c246cf469f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 13:01:58 +0200 Subject: [PATCH 0985/1892] ci: fix APK invocation syntax --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a3e8facc..f037ac434 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk install -y flex bison libxml2-dev zlib-dev* && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev* && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_EXTRAS: "test-musl" @@ -73,7 +73,7 @@ jobs: - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk install -y flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_EXTRAS: "test-musl" From 395b849a63ce96ec9436167f28d4808e0cb92470 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Jun 2022 13:57:37 +0200 Subject: [PATCH 0986/1892] ci: fix typo in zlib-dev package name --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f037ac434..cf8f492c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev* && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_EXTRAS: "test-musl" From 304aa852b0024744bcce2bcfb9792e178bf784da Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 8 Jun 2022 22:54:34 +0200 Subject: [PATCH 0987/1892] chore: final touches to changelog [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7306a001e..76a6ece03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [0.9.11] +### Added + +- We now publish `musllinux` wheels on PyPI. + ### Changed - Vendored igraph was updated to version 0.9.9. From 4866e4d4ab4343f217b4ce7b25124c6775ed2e6a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 9 Jun 2022 00:34:02 +0200 Subject: [PATCH 0988/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 186ac9359..9cfaafe2b 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 186ac935906ef23ff86cbf81f2909c2009afa588 +Subproject commit 9cfaafe2b94f293bdaf10c46157db9dd31b465b9 From eb1931c4f5e840cd34e3478600efd1fd2dee173f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 15 Jun 2022 11:43:41 +0200 Subject: [PATCH 0989/1892] chore: sync up with development branch of igraph --- CHANGELOG.md | 9 ++ src/_igraph/convert.c | 47 ++++++++ src/_igraph/convert.h | 2 + src/_igraph/graphobject.c | 211 ++++++++++++++++++++-------------- src/_igraph/random.c | 46 ++++---- src/_igraph/vertexobject.c | 1 + src/_igraph/vertexseqobject.c | 2 +- src/igraph/__init__.py | 6 +- src/igraph/io/adjacency.py | 4 +- src/igraph/io/files.py | 4 +- src/igraph/seq.py | 1 + src/igraph/structural.py | 8 ++ test.sh | 4 +- tests/test_attributes.py | 2 +- tests/test_decomposition.py | 8 +- tests/test_layouts.py | 4 +- tests/test_spectral.py | 30 +++++ tests/test_structural.py | 8 +- tests/test_vertexseq.py | 7 +- vendor/source/igraph | 2 +- 20 files changed, 273 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4512056b0..e26eca6c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ data structures. See PR [#434](https://github.com/igraph/python-igraph/pull/434) for more details. +- `Graph.get_adjacency()` now allows the user to specify whether loop edges + should be counted once or twice, or not at all. + +- `Graph.get_laplacian()` now supports left-, right- and symmetric normalization. + ### Changed - Changed default value of the `use_vids=...` argument of `Graph.DataFrame()` @@ -25,11 +30,15 @@ - Removed deprecated `show()` method of `Plot` instances as well as the feature that automatically shows the plot when `plot()` is called with no target. +- Removed the `eids` keyword argument of `get_adjacency()`. + ### Deprecated - `Graph.clusters()` is now deprecated; use `Graph.connected_components()` or its already existing shorter alias, `Graph.components()`. +- `Graph.shortest_paths()` is now deprecated; use `Graph.distances()` instead. + ## [Unreleased] ### Fixed diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 5257db133..937c74b9d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -570,6 +570,31 @@ int igraphmodule_PyObject_to_get_adjacency_t(PyObject *o, return igraphmodule_PyObject_to_enum(o, get_adjacency_tt, (int*)result); } +/** + * \brief Converts a Python object to an igraph \c igraph_laplacian_normalization_t + */ +int igraphmodule_PyObject_to_laplacian_normalization_t( + PyObject *o, igraph_laplacian_normalization_t *result +) { + static igraphmodule_enum_translation_table_entry_t laplacian_normalization_tt[] = { + {"unnormalized", IGRAPH_LAPLACIAN_UNNORMALIZED}, + {"symmetric", IGRAPH_LAPLACIAN_SYMMETRIC}, + {"left", IGRAPH_LAPLACIAN_LEFT}, + {"right", IGRAPH_LAPLACIAN_RIGHT}, + {0,0} + }; + + if (o == Py_True) { + *result = IGRAPH_LAPLACIAN_SYMMETRIC; + return 0; + } else if (o == Py_False) { + *result = IGRAPH_LAPLACIAN_UNNORMALIZED; + return 0; + } else { + return igraphmodule_PyObject_to_enum(o, laplacian_normalization_tt, (int*)result); + } +} + /** * \brief Converts a Python object to an igraph \c igraph_layout_grid_t */ @@ -592,6 +617,28 @@ int igraphmodule_PyObject_to_layout_grid_t(PyObject *o, igraph_layout_grid_t *re } } +/** + * \brief Converts a Python object to an igraph \c igraph_loops_t + */ +int igraphmodule_PyObject_to_loops_t(PyObject *o, igraph_loops_t *result) { + static igraphmodule_enum_translation_table_entry_t loops_tt[] = { + {"ignore", IGRAPH_NO_LOOPS}, + {"once", IGRAPH_LOOPS_ONCE}, + {"twice", IGRAPH_LOOPS_TWICE}, + {0,0} + }; + + if (o == Py_True) { + *result = IGRAPH_LOOPS_TWICE; + return 0; + } else if (o == Py_False) { + *result = IGRAPH_NO_LOOPS; + return 0; + } else { + return igraphmodule_PyObject_to_enum(o, loops_tt, (int*)result); + } +} + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_random_walk_stuck_t diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 82f5875c3..a56e2e0df 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -64,7 +64,9 @@ int igraphmodule_PyObject_to_connectedness_t(PyObject *o, igraph_connectedness_t 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_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); +int igraphmodule_PyObject_to_loops_t(PyObject *o, igraph_loops_t *result); int igraphmodule_PyObject_to_neimode_t(PyObject *o, igraph_neimode_t *result); int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t *result); int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index cf6587cce..292391628 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1944,15 +1944,21 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, igraphmodule_GraphObject *self; igraph_t g; igraph_matrix_t m; - PyObject *matrix, *mode_o = Py_None; + PyObject *matrix, *mode_o = Py_None, *loops_o = Py_None; igraph_adjacency_t mode = IGRAPH_ADJ_DIRECTED; + igraph_loops_t loops = IGRAPH_LOOPS_ONCE; + + static char *kwlist[] = { "matrix", "mode", "loops", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OO", kwlist, + &PyList_Type, &matrix, &mode_o, &loops_o)) + return NULL; - static char *kwlist[] = { "matrix", "mode", NULL }; + if (igraphmodule_PyObject_to_adjacency_t(mode_o, &mode)) + return NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, - &PyList_Type, &matrix, &mode_o)) + if (igraphmodule_PyObject_to_loops_t(loops_o, &loops)) return NULL; - if (igraphmodule_PyObject_to_adjacency_t(mode_o, &mode)) return NULL; if (igraphmodule_PyList_to_matrix_t(matrix, &m)) { PyErr_SetString(PyExc_TypeError, @@ -1960,7 +1966,7 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, return NULL; } - if (igraph_adjacency(&g, &m, mode)) { + if (igraph_adjacency(&g, &m, mode, loops)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&m); return NULL; @@ -3571,54 +3577,60 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, igraphmodule_GraphObject *self; igraph_t g; igraph_matrix_t m; - PyObject *matrix, *mode_o = Py_None, *attr_o = Py_None, *s = 0; - PyObject *loops = Py_True; - char* attr = 0; + PyObject *matrix, *mode_o = Py_None; + PyObject *loops_o = Py_None, *weights_o; igraph_adjacency_t mode = IGRAPH_ADJ_DIRECTED; + igraph_loops_t loops = IGRAPH_LOOPS_ONCE; + igraph_vector_t weights; - static char *kwlist[] = { "matrix", "mode", "attr", "loops", NULL }; + static char *kwlist[] = { "matrix", "mode", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OOO", kwlist, - &PyList_Type, &matrix, &mode_o, &attr_o, - &loops)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OO", kwlist, + &PyList_Type, &matrix, &mode_o, &loops_o)) return NULL; if (igraphmodule_PyObject_to_adjacency_t(mode_o, &mode)) return NULL; - if (attr_o != Py_None) { - s = PyObject_Str(attr_o); - if (s) { - attr = PyUnicode_CopyAsString(s); - if (attr == 0) - return NULL; - } else return NULL; - } + /* mapping of Py_True is different from what igraphmodule_PyObject_to_loops_t + * assumes so we handle it separately */ + if (loops_o == Py_True) { + loops = IGRAPH_LOOPS_ONCE; + } else if (igraphmodule_PyObject_to_loops_t(loops_o, &loops)) + return NULL; if (igraphmodule_PyList_to_matrix_t(matrix, &m)) { - if (attr != 0) - free(attr); PyErr_SetString(PyExc_TypeError, "Error while converting adjacency matrix"); return NULL; } - if (igraph_weighted_adjacency(&g, &m, mode, attr ? attr : "weight", - PyObject_IsTrue(loops))) { + if (igraph_vector_init(&weights, 0)) { igraphmodule_handle_igraph_error(); - if (attr != 0) - free(attr); igraph_matrix_destroy(&m); return NULL; } - if (attr != 0) - free(attr); + if (igraph_weighted_adjacency(&g, &m, mode, &weights, loops)) { + igraphmodule_handle_igraph_error(); + igraph_matrix_destroy(&m); + igraph_vector_destroy(&weights); + return NULL; + } + igraph_matrix_destroy(&m); CREATE_GRAPH_FROM_TYPE(self, g, type); + weights_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); + if (!weights_o) { + Py_DECREF(self); + igraph_vector_destroy(&weights); + return NULL; + } - return (PyObject *) self; + igraph_vector_destroy(&weights); + + return Py_BuildValue("NN", (PyObject *) self, weights_o); } /********************************************************************** @@ -5696,14 +5708,15 @@ PyObject *igraphmodule_Graph_rewire_edges(igraphmodule_GraphObject * self, } /** \ingroup python_interface_graph - * \brief Calculates shortest paths in a graph. + * \brief Calculates shortest path lengths in a graph. * \return the shortest path lengths for the given vertices * \sa igraph_shortest_paths, igraph_shortest_paths_dijkstra, * igraph_shortest_paths_bellman_ford, igraph_shortest_paths_johnson */ -PyObject *igraphmodule_Graph_shortest_paths(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) -{ +PyObject *igraphmodule_Graph_distances( + igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds +) { static char *kwlist[] = { "source", "target", "weights", "mode", NULL }; PyObject *from_o = NULL, *to_o = NULL, *mode_o = NULL, *weights_o = Py_None; PyObject *list = NULL; @@ -5745,7 +5758,7 @@ PyObject *igraphmodule_Graph_shortest_paths(igraphmodule_GraphObject * self, if (weights && igraph_vector_size(weights) > 0) { if (igraph_vector_min(weights) > 0) { /* Only positive weights, use Dijkstra's algorithm */ - e = igraph_shortest_paths_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode); + e = igraph_distances_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode); } else { /* There are negative weights. For a small number of sources, use Bellman-Ford. * Otherwise, use Johnson's algorithm */ @@ -5753,15 +5766,15 @@ PyObject *igraphmodule_Graph_shortest_paths(igraphmodule_GraphObject * self, e = igraph_vs_size(&self->g, &from_vs, &vs_size); if (!e) { if (vs_size <= 100 || mode != IGRAPH_OUT) { - e = igraph_shortest_paths_bellman_ford(&self->g, &res, from_vs, to_vs, weights, mode); + e = igraph_distances_bellman_ford(&self->g, &res, from_vs, to_vs, weights, mode); } else { - e = igraph_shortest_paths_johnson(&self->g, &res, from_vs, to_vs, weights); + e = igraph_distances_johnson(&self->g, &res, from_vs, to_vs, weights); } } } } else { /* No weights or empty weight vector, use a simple BFS */ - e = igraph_shortest_paths(&self->g, &res, from_vs, to_vs, mode); + e = igraph_distances(&self->g, &res, from_vs, to_vs, mode); } if (e) { @@ -7908,23 +7921,26 @@ PyObject *igraphmodule_Graph_layout_bipartite( PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "type", NULL }; + static char *kwlist[] = { "type", "loops", NULL }; igraph_get_adjacency_t mode = IGRAPH_GET_ADJACENCY_BOTH; igraph_matrix_t m; - PyObject *result_o, *mode_o = Py_None; + igraph_loops_t loops = IGRAPH_LOOPS_TWICE; + PyObject *result_o, *mode_o = Py_None, *loops_o = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &loops_o)) return NULL; if (igraphmodule_PyObject_to_get_adjacency_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_loops_t(loops_o, &loops)) return NULL; + if (igraph_matrix_init (&m, igraph_vcount(&self->g), igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); return NULL; } - if (igraph_get_adjacency(&self->g, &m, mode)) { + if (igraph_get_adjacency(&self->g, &m, mode, /* weights = */ 0, loops)) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&m); return NULL; @@ -8004,20 +8020,29 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "weights", "normalized", NULL }; + static char *kwlist[] = { "weights", "normalized", "mode", NULL }; igraph_matrix_t m; PyObject *result_o; PyObject *weights_o = Py_None; - PyObject *normalized = Py_False; + PyObject *normalized_o = Py_False; + PyObject *mode_o = Py_None; + igraph_laplacian_normalization_t normalize = IGRAPH_LAPLACIAN_UNNORMALIZED; + igraph_neimode_t mode = IGRAPH_OUT; igraph_vector_t *weights = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, - &weights_o, &normalized)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, + &weights_o, &normalized_o, &mode_o)) return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; + if (igraphmodule_PyObject_to_laplacian_normalization_t(normalized_o, &normalize)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + return NULL; + if (igraph_matrix_init (&m, igraph_vcount(&self->g), igraph_vcount(&self->g))) { igraphmodule_handle_igraph_error(); @@ -8025,20 +8050,14 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, return NULL; } - if (igraph_laplacian(&self->g, &m, /*sparseres=*/ 0, - PyObject_IsTrue(normalized), weights)) { + if (igraph_get_laplacian(&self->g, &m, mode, normalize, weights)) { igraphmodule_handle_igraph_error(); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_matrix_destroy(&m); return NULL; } - if (PyObject_IsTrue(normalized) || weights) { - result_o = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); - } - else { - result_o = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_INT); - } + result_o = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_matrix_destroy(&m); @@ -8156,7 +8175,7 @@ PyObject *igraphmodule_Graph_to_directed(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Reads a DIMACS file and creates a graph from it. * \return the graph - * \sa igraph_read_graph_dimacs + * \sa igraph_read_graph_dimacs_flow */ PyObject *igraphmodule_Graph_Read_DIMACS(PyTypeObject * type, PyObject * args, PyObject * kwds) @@ -8183,9 +8202,10 @@ PyObject *igraphmodule_Graph_Read_DIMACS(PyTypeObject * type, return NULL; } - if (igraph_read_graph_dimacs(&g, igraphmodule_filehandle_get(&fobj), - 0, 0, &source, &target, - &capacity, PyObject_IsTrue(directed))) { + if (igraph_read_graph_dimacs_flow( + &g, igraphmodule_filehandle_get(&fobj), 0, 0, &source, &target, + &capacity, PyObject_IsTrue(directed) + )) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&capacity); igraphmodule_filehandle_destroy(&fobj); @@ -8503,7 +8523,7 @@ PyObject *igraphmodule_Graph_Read_GraphML(PyTypeObject * type, /** \ingroup python_interface_graph * \brief Writes the graph as a DIMACS file * \return none - * \sa igraph_write_graph_dimacs + * \sa igraph_write_graph_dimacs_flow */ PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) @@ -8547,7 +8567,7 @@ PyObject *igraphmodule_Graph_write_dimacs(igraphmodule_GraphObject * self, Py_DECREF(capacity_obj); - if (igraph_write_graph_dimacs(&self->g, igraphmodule_filehandle_get(&fobj), + if (igraph_write_graph_dimacs_flow(&self->g, igraphmodule_filehandle_get(&fobj), source, target, capacity)) { igraphmodule_handle_igraph_error(); if (capacity) { @@ -8673,7 +8693,7 @@ PyObject *igraphmodule_Graph_write_gml(igraphmodule_GraphObject * self, } if (igraph_write_graph_gml(&self->g, igraphmodule_filehandle_get(&fobj), - idvecptr, creator_str)) { + IGRAPH_WRITE_GML_DEFAULT_SW, idvecptr, creator_str)) { if (idvecptr) { igraph_vector_destroy(idvecptr); } if (creator_str) free(creator_str); @@ -12729,7 +12749,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_adjacency */ {"Adjacency", (PyCFunction) igraphmodule_Graph_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Adjacency(matrix, mode=\"directed\")\n--\n\n" + "Adjacency(matrix, mode=\"directed\", loops=\"once\")\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" @@ -12745,6 +12765,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " the matrix (including the diagonal)\n" " - C{\"lower\"} - undirected graph with the lower left triangle of\n" " the matrix (including the diagonal)\n" + "\n" + "@param loops: specifies how the diagonal of the matrix should be handled:\n" + "\n" + " - C{\"ignore\"} - ignore loop edges in the diagonal\n" + " - C{\"once\"} - treat the diagonal entries as loop edge counts\n" + " - C{\"twice\"} - treat the diagonal entries as I{twice} the number\n" + " of loop edges\n" }, /* interface to igraph_asymmetric_preference_game */ @@ -13294,9 +13321,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " small world networks}, Nature 393, 440-442, 1998\n"}, /* interface to igraph_weighted_adjacency */ - {"Weighted_Adjacency", (PyCFunction) igraphmodule_Graph_Weighted_Adjacency, + {"_Weighted_Adjacency", (PyCFunction) igraphmodule_Graph_Weighted_Adjacency, METH_CLASS | METH_VARARGS | METH_KEYWORDS, - "Weighted_Adjacency(matrix, mode=\"directed\", attr=\"weight\", loops=True)\n--\n\n" + "_Weighted_Adjacency(matrix, mode=\"directed\", loops=\"once\")\n--\n\n" "Generates a graph from its adjacency matrix.\n\n" "@param matrix: the adjacency matrix\n" "@param mode: the mode to be used. Possible values are:\n" @@ -13312,10 +13339,12 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " the matrix (including the diagonal)\n" " - C{\"lower\"} - undirected graph with the lower left triangle of\n" " the matrix (including the diagonal)\n" - "@param attr: the name of the edge attribute that stores the edge\n" - " weights.\n" - "@param loops: whether to include loop edges. When C{False}, the diagonal\n" - " of the adjacency matrix will be ignored.\n" + "@param loops: specifies how to handle loop edges. When C{False} or C{\"ignore\"},\n" + " the diagonal of the adjacency matrix will be ignored. When C{True} or\n" + " C{\"once\"}, the diagonal is assumed to contain the weight of the\n" + " corresponding loop edge. When C{\"twice\"}, the diagonal is assumed to\n" + " contain I{twice} the weight of the corresponding loop edge.\n" + "@return: a pair consisting of the graph itself and its edge weight vector\n" }, ///////////////////////////////////// @@ -14305,10 +14334,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param multiple: whether the algorithm is allowed to create multiple\n" " edges.\n"}, - /* interface to igraph_shortest_paths */ - {"shortest_paths", (PyCFunction) igraphmodule_Graph_shortest_paths, + /* interface to igraph_distances */ + {"distances", (PyCFunction) igraphmodule_Graph_distances, METH_VARARGS | METH_KEYWORDS, - "shortest_paths(source=None, target=None, weights=None, mode=\"out\")\n--\n\n" + "distances(source=None, target=None, weights=None, mode=\"out\")\n--\n\n" "Calculates shortest path lengths for given vertices in a graph.\n\n" "The algorithm used for the calculations is selected automatically:\n" "a simple BFS is used for unweighted graphs, Dijkstra's algorithm is\n" @@ -15221,16 +15250,15 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { // interface to igraph_get_adjacency {"get_adjacency", (PyCFunction) igraphmodule_Graph_get_adjacency, METH_VARARGS | METH_KEYWORDS, - "get_adjacency(type=\"both\", eids=False)\n--\n\n" + "get_adjacency(type=\"both\", loops=\"twice\")\n--\n\n" "Returns the adjacency matrix of a graph.\n\n" "@param type: one of C{\"lower\"} (uses the lower triangle of the matrix),\n" " C{\"upper\"} (uses the upper triangle) or C{\"both\"} (uses both parts).\n" " Ignored for directed graphs.\n" - "@param eids: if C{True}, the result matrix will contain\n" - " zeros for non-edges and the ID of the edge plus one\n" - " for edges in the appropriate cell. If C{False}, the\n" - " result matrix will contain the number of edges for\n" - " each vertex pair.\n" + "@param loops: specifies how loop edges should be handled. C{False} or\n" + " C{\"ignore\"} ignores loop edges. C{\"once\"} counts each loop edge once\n" + " in the diagonal. C{\"twice\"} counts each loop edge twice (i.e. it counts\n" + " the I{endpoints} of the loop edges, not the edges themselves).\n" "@return: the adjacency matrix.\n"}, // interface to igraph_get_edgelist @@ -15278,27 +15306,36 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_laplacian */ {"laplacian", (PyCFunction) igraphmodule_Graph_laplacian, METH_VARARGS | METH_KEYWORDS, - "laplacian(weights=None, normalized=False)\n--\n\n" + "laplacian(weights=None, normalized=\"unnormalized\", mode=\"out\")\n--\n\n" "Returns the Laplacian matrix of a graph.\n\n" "The Laplacian matrix is similar to the adjacency matrix, but the edges\n" "are denoted with -1 and the diagonal contains the node degrees.\n\n" - "Normalized Laplacian matrices have 1 or 0 in their diagonals (0 for vertices\n" - "with no edges), edges are denoted by 1 / sqrt(d_i * d_j) where d_i is the\n" - "degree of node i.\n\n" - "Multiple edges and self-loops are silently ignored. Although it is\n" - "possible to calculate the Laplacian matrix of a directed graph, it does\n" - "not make much sense.\n\n" + "Symmetric normalized Laplacian matrices have 1 or 0 in their diagonals\n" + "(0 for vertices with no edges), edges are denoted by 1 / sqrt(d_i * d_j)\n" + "where d_i is the degree of node i.\n\n" + "Left-normalized and right-normalized Laplacian matrices are derived from\n" + "the unnormalized Laplacian by scaling the row or the column sums to be\n" + "equal to 1.\n\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name. When edge weights are used, the degree\n" - " of a node is considered to be the weight of its incident edges.\n" + " of a node is considered to be the sum of the weights of its incident\n" + " edges.\n" "@param normalized: whether to return the normalized Laplacian matrix.\n" + " C{False} or C{\"unnormalized\"} returns the unnormalized Laplacian matrix.\n" + " C{True} or C{\"symmetric\"} returns the symmetric normalization of the\n" + " Laplacian matrix. C{\"left\"} returns the left-, C{\"right\"} returns the\n" + " right-normalized Laplacian matrix.\n" + "@param mode: for directed graphs, specifies whether to use out- or in-degrees\n" + " in the Laplacian matrix. C{\"all\"} means that the edge directions must be\n" + " ignored, C{\"out\"} means that the out-degrees should be used, C{\"in\"}\n" + " means that the in-degrees should be used. Ignored for undirected graphs.\n" "@return: the Laplacian matrix.\n"}, /////////////////////////////// // LOADING AND SAVING GRAPHS // /////////////////////////////// - // interface to igraph_read_graph_dimacs + // interface to igraph_read_graph_dimacs_flow {"Read_DIMACS", (PyCFunction) igraphmodule_Graph_Read_DIMACS, METH_VARARGS | METH_KEYWORDS | METH_CLASS, "Read_DIMACS(f, directed=False)\n--\n\n" @@ -15417,7 +15454,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Reads a file in the Pajek format and creates a graph based on it.\n" "Only Pajek network files (.net extension) are supported, not project files (.paj).\n\n" "@param f: the name of the file or a Python file handle\n"}, - /* interface to igraph_write_graph_dimacs */ + /* interface to igraph_write_graph_dimacs_flow */ {"write_dimacs", (PyCFunction) igraphmodule_Graph_write_dimacs, METH_VARARGS | METH_KEYWORDS, "write_dimacs(f, source, target, capacity=None)\n--\n\n" diff --git a/src/_igraph/random.c b/src/_igraph/random.c index 966acfb35..b059042d7 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -43,18 +43,14 @@ typedef struct { PyObject* rng_max_as_pyobject; } igraph_i_rng_Python_state_t; -/* igraph_rng_get_int31() is potentially faster if the max value of the RNG - * is 0x7FFFFFFF; however, in case of Python, it is actually _slower_ because - * Python long integers are not terribly efficient. We are better off with using - * any other value here */ -#define RNG_MAX 0xFFFFFFFF - -/* This must be consistent with the value of RNG_MAX above */ #define RNG_BITS 32 +#define RNG_MAX ((((size_t) 1) << RNG_BITS) - 1) -static igraph_i_rng_Python_state_t igraph_rng_Python_state = {0, 0, 0}; -static igraph_rng_t igraph_rng_Python = {0, 0, 0}; -static igraph_rng_t igraph_rng_default_saved = {0, 0, 0}; +static igraph_i_rng_Python_state_t igraph_rng_Python_state = {0}; +static igraph_rng_t igraph_rng_Python = { + /* type = */ 0, /* state = */ 0, /* is_seeded = */ 1 +}; +static igraph_rng_t igraph_rng_default_saved = {0}; igraph_error_t igraph_rng_Python_init(void **state) { IGRAPH_ERROR("Python RNG error, unsupported function called", @@ -111,7 +107,7 @@ PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object) { GET_FUNC("random"); new_state.random_func = func; GET_FUNC("gauss"); new_state.gauss_func = func; - /* construct the arguments of getrandbits(RNG_BITS) and randint(0, RNG_MAX) + /* construct the arguments of getrandbits(RNG_BITS) and randint(0, 2 ^ RNG_BITS-1) * in advance */ new_state.rng_bits_as_pyobject = PyLong_FromLong(RNG_BITS); if (new_state.rng_bits_as_pyobject == 0) { @@ -125,7 +121,7 @@ PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object) { if (new_state.one_as_pyobject == 0) { return 0; } - new_state.rng_max_as_pyobject = PyLong_FromUnsignedLong(RNG_MAX); + new_state.rng_max_as_pyobject = PyLong_FromSize_t(RNG_MAX); if (new_state.rng_max_as_pyobject == 0) { return 0; } @@ -153,7 +149,7 @@ PyObject* igraph_rng_Python_set_generator(PyObject* self, PyObject* object) { * \ingroup python_interface_rng * \brief Sets the seed of the random generator. */ -igraph_error_t igraph_rng_Python_seed(void *state, unsigned long int seed) { +igraph_error_t igraph_rng_Python_seed(void *state, igraph_uint_t seed) { IGRAPH_ERROR("Python RNG error, unsupported function called", IGRAPH_EINTERNAL); return IGRAPH_SUCCESS; @@ -163,10 +159,10 @@ igraph_error_t igraph_rng_Python_seed(void *state, unsigned long int seed) { * \ingroup python_interface_rng * \brief Generates an unsigned long integer using the Python random number generator. */ -unsigned long int igraph_rng_Python_get(void *state) { +igraph_uint_t igraph_rng_Python_get(void *state) { PyObject* result; PyObject* exc_type; - unsigned long int retval; + igraph_uint_t retval; if (igraph_rng_Python_state.getrandbits_func) { /* This is the preferred code path if the random module given by the user @@ -198,7 +194,7 @@ unsigned long int igraph_rng_Python_get(void *state) { PyErr_WriteUnraisable(exc_type); PyErr_Clear(); } - /* Fallback to the C random generator */ + /* Fallback to the C random generator -- this should not happen */ return rand() * RNG_MAX; } else { retval = PyLong_AsUnsignedLong(result); @@ -226,7 +222,7 @@ igraph_real_t igraph_rng_Python_get_real(void *state) { PyErr_WriteUnraisable(exc_type); PyErr_Clear(); } - /* Fallback to the C random generator */ + /* Fallback to the C random generator -- this should not happen */ return rand(); } else { retval = PyFloat_AsDouble(result); @@ -260,7 +256,7 @@ igraph_real_t igraph_rng_Python_get_norm(void *state) { PyErr_WriteUnraisable(exc_type); PyErr_Clear(); } - /* Fallback to the C random generator */ + /* Fallback -- this should not happen */ return 0; } else { retval = PyFloat_AsDouble(result); @@ -276,16 +272,19 @@ igraph_real_t igraph_rng_Python_get_norm(void *state) { */ igraph_rng_type_t igraph_rngtype_Python = { /* name= */ "Python random generator", - /* min= */ 0, - /* max= */ RNG_MAX, + /* bits= */ RNG_BITS, /* init= */ igraph_rng_Python_init, /* destroy= */ igraph_rng_Python_destroy, /* seed= */ igraph_rng_Python_seed, /* get= */ igraph_rng_Python_get, - /* get_real */ igraph_rng_Python_get_real, + /* get_int= */ 0, + /* get_real= */ igraph_rng_Python_get_real, /* get_norm= */ igraph_rng_Python_get_norm, /* get_geom= */ 0, - /* get_binom= */ 0 + /* get_binom= */ 0, + /* get_exp= */ 0, + /* get_gamma= */ 0, + /* get_pois= */ 0, }; void igraphmodule_init_rng(PyObject* igraph_module) { @@ -295,8 +294,9 @@ void igraphmodule_init_rng(PyObject* igraph_module) { igraph_rng_default_saved = *igraph_rng_default(); } - if (igraph_rng_Python.state != 0) + if (igraph_rng_Python.state != 0) { return; + } random_module = PyImport_ImportModule("random"); if (random_module == 0) { diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 2a7e14576..03c3dc0f0 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -738,6 +738,7 @@ GRAPH_PROXY_METHOD(constraint, "constraint"); GRAPH_PROXY_METHOD(degree, "degree"); GRAPH_PROXY_METHOD(delete, "delete_vertices"); GRAPH_PROXY_METHOD(diversity, "diversity"); +GRAPH_PROXY_METHOD(distances, "distances"); GRAPH_PROXY_METHOD(eccentricity, "eccentricity"); GRAPH_PROXY_METHOD(get_shortest_paths, "get_shortest_paths"); GRAPH_PROXY_METHOD_PP(incident, "incident", _convert_to_edge_list); diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 81073bb12..11d05403a 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -65,7 +65,7 @@ igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) { if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) { igraph_vector_int_t v; - if (igraph_vector_int_copy(&v, o->vs.data.vecptr)) { + if (igraph_vector_int_init_copy(&v, o->vs.data.vecptr)) { igraphmodule_handle_igraph_error(); return 0; } diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index c9618a177..a4f2c0af4 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -129,6 +129,7 @@ _biconnected_components, _cohesive_blocks, _connected_components, + _clusters, ) from igraph.cut import ( Cut, @@ -255,6 +256,7 @@ _outdegree, _degree_distribution, _pagerank, + _shortest_paths ) from igraph.summary import GraphSummary, summary from igraph.utils import ( @@ -353,7 +355,8 @@ class Graph(GraphBase): adhesion = GraphBase.edge_connectivity # Compatibility aliases - shortest_paths_dijkstra = GraphBase.shortest_paths + shortest_paths = _shortest_paths + shortest_paths_dijkstra = shortest_paths subgraph = GraphBase.induced_subgraph def __init__(self, *args, **kwds): @@ -650,6 +653,7 @@ def es(self): ############################################# # Connected components biconnected_components = _biconnected_components + clusters = _clusters cohesive_blocks = _cohesive_blocks connected_components = _connected_components blocks = biconnected_components diff --git a/src/igraph/io/adjacency.py b/src/igraph/io/adjacency.py index 0cb81688e..940402869 100644 --- a/src/igraph/io/adjacency.py +++ b/src/igraph/io/adjacency.py @@ -132,12 +132,12 @@ def _construct_graph_from_weighted_adjacency( if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() - graph = super(Graph, cls).Weighted_Adjacency( + graph, weights = super(Graph, cls)._Weighted_Adjacency( matrix, mode=mode, - attr=attr, loops=loops, ) + graph.es[attr] = weights # Add vertex names if present if vertex_names is not None: diff --git a/src/igraph/io/files.py b/src/igraph/io/files.py index 1bf7542af..bea7bb076 100644 --- a/src/igraph/io/files.py +++ b/src/igraph/io/files.py @@ -134,8 +134,8 @@ def _construct_graph_from_adjacency_file( if attribute is None: graph = cls.Adjacency(matrix, *args, **kwds) else: - kwds["attr"] = attribute - graph = cls.Weighted_Adjacency(matrix, *args, **kwds) + graph, weights = cls._Weighted_Adjacency(matrix, *args, **kwds) + graph.es[attribute] = weights return graph diff --git a/src/igraph/seq.py b/src/igraph/seq.py index 6530def6c..0f0dc2168 100644 --- a/src/igraph/seq.py +++ b/src/igraph/seq.py @@ -759,6 +759,7 @@ def _add_proxy_methods(): "closeness", "cocitation", "constraint", + "distances", "diversity", "eccentricity", "get_shortest_paths", diff --git a/src/igraph/structural.py b/src/igraph/structural.py index ef6b3b440..a55d9ba9d 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -93,3 +93,11 @@ def _pagerank( niter, eps, ) + + +def _shortest_paths(graph, *args, **kwds): + """Deprecated alias to L{Graph.distances()}.""" + from igraph import deprecated + + deprecated("Graph.shortest_paths() is deprecated; use Graph.distances() instead") + return graph.distances(*args, **kwds) diff --git a/test.sh b/test.sh index 2a41882b6..49fb2ad10 100755 --- a/test.sh +++ b/test.sh @@ -7,7 +7,6 @@ PYTHON=python3 set -e CLEAN=0 -PYTEST_ARGS= VENV_DIR=.venv while getopts ":ce:k:" OPTION; do @@ -39,6 +38,7 @@ if [ x$CLEAN = x1 ]; then rm -rf vendor/build vendor/install fi -$VENV_DIR/bin/pip install .[plotting,test] +# pip install is called in verbose mode so we can see the compiler warnings +$VENV_DIR/bin/pip install -v .[plotting,test] $VENV_DIR/bin/pytest tests ${PYTEST_ARGS} diff --git a/tests/test_attributes.py b/tests/test_attributes.py index e7f0d6786..c7d3e6515 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -274,7 +274,7 @@ def suite(): attribute_suite, attribute_combination_suite, unicode_attributes_suite, - ]) + ]) def test(): diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 788fe08b2..fb130cd2b 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -294,8 +294,8 @@ def testLabelPropagation(self): # igraph is free to reorder the clusters so only co-membership will be # preserved, hence the next assertion self.assertTrue( - cl.membership[0] != cl.membership[49] and - cl.membership[49] != cl.membership[99] + cl.membership[0] != cl.membership[49] + and cl.membership[49] != cl.membership[99] ) self.assertTrue(x >= 0 and x <= 5 for x in cl.membership) @@ -473,7 +473,7 @@ def testLeiden(self): import random - random.seed(0) + random.seed(42) set_random_number_generator(random) # We don't find the optimal partition if we are greedy cl = G.community_leiden( @@ -481,7 +481,7 @@ def testLeiden(self): ) self.assertMembershipsEqual(cl, [0, 0, 1, 1, 1, 2, 2, 2]) - random.seed(0) + random.seed(42) set_random_number_generator(random) # We can find the optimal partition if we allow for non-decreasing moves # (The randomness is only present in the refinement, which is why we diff --git a/tests/test_layouts.py b/tests/test_layouts.py index cabdef5b6..142a5de5d 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -243,7 +243,7 @@ def testMDS(self): lo = g.layout("mds") self.assertTrue(isinstance(lo, Layout)) - dists = g.shortest_paths() + dists = g.distances() lo = g.layout("mds", dists) self.assertTrue(isinstance(lo, Layout)) @@ -334,7 +334,7 @@ def testReingoldTilford(self): lo = g.layout("rt") ys = [coord[1] for coord in lo] root = ys.index(0.0) - self.assertEqual(ys, g.shortest_paths(root)[0]) + self.assertEqual(ys, g.distances(root)[0]) g = Graph.Barabasi(100) + Graph.Barabasi(50) lo = g.layout("rt", root=[0, 100]) self.assertEqual(lo[100][1] - lo[0][1], 0) diff --git a/tests/test_spectral.py b/tests/test_spectral.py index 6d879ccfb..14689a93e 100644 --- a/tests/test_spectral.py +++ b/tests/test_spectral.py @@ -18,6 +18,18 @@ def testLaplacian(self): g.laplacian(normalized=True), [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]], ) + self.assertAlmostEqualMatrix( + g.laplacian(normalized="symmetric"), + [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]], + ) + self.assertAlmostEqualMatrix( + g.laplacian(normalized="left"), + [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]], + ) + self.assertAlmostEqualMatrix( + g.laplacian(normalized="right"), + [[1, -0.5, -0.5], [-0.5, 1, -0.5], [-0.5, -0.5, 1]], + ) mx0 = [ [1.0, -1 / (12 ** 0.5), -2 / (15 ** 0.5)], @@ -40,6 +52,24 @@ def testLaplacian(self): ] ) + g = Graph.Formula("A --> B --> C --> D --> E --> A, A --> C") + self.assertAlmostEqualMatrix( + g.laplacian(mode="out"), + [[2, -1, -1, 0, 0], [0, 1, -1, 0, 0], [0, 0, 1, -1, 0], [0, 0, 0, 1, -1], [-1, 0, 0, 0, 1]] + ) + self.assertAlmostEqualMatrix( + g.laplacian(mode="in"), + [[1, -1, -1, 0, 0], [0, 1, -1, 0, 0], [0, 0, 2, -1, 0], [0, 0, 0, 1, -1], [-1, 0, 0, 0, 1]] + ) + self.assertAlmostEqualMatrix( + g.laplacian(mode="out", normalized="left"), + [[1, -0.5, -0.5, 0, 0], [0, 1, -1, 0, 0], [0, 0, 1, -1, 0], [0, 0, 0, 1, -1], [-1, 0, 0, 0, 1]] + ) + self.assertAlmostEqualMatrix( + g.laplacian(mode="in", normalized="right"), + [[1, -1, -0.5, 0, 0], [0, 1, -0.5, 0, 0], [0, 0, 1, -1, 0], [0, 0, 0, 1, -1], [-1, 0, 0, 0, 1]] + ) + def suite(): spectral_suite = unittest.makeSuite(SpectralTests) diff --git a/tests/test_structural.py b/tests/test_structural.py index 62e134201..d6c665da6 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -734,7 +734,7 @@ def testMaximumCardinalitySearch(self): class PathTests(unittest.TestCase): - def testShortestPaths(self): + def testDistances(self): g = Graph( 10, [ @@ -775,10 +775,10 @@ def testShortestPaths(self): [inf, inf, inf, inf, inf, inf, inf, inf, 0, 4], [inf, inf, inf, inf, inf, inf, inf, inf, inf, 0], ] - self.assertTrue(g.shortest_paths(weights=ws) == expected) - self.assertTrue(g.shortest_paths(weights="weight") == expected) + self.assertTrue(g.distances(weights=ws) == expected) + self.assertTrue(g.distances(weights="weight") == expected) self.assertTrue( - g.shortest_paths(weights="weight", target=[2, 3]) + g.distances(weights="weight", target=[2, 3]) == [row[2:4] for row in expected] ) diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 08e92bc31..8cb612e66 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -102,7 +102,7 @@ def testNeighbors(self): @unittest.skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") def testProxyMethods(self): # We only test with connected graphs because disconnected graphs might - # print a warning when shortest_paths() is invoked on them and we want + # print a warning when distances() is invoked on them and we want # to avoid that in the test output. while True: g = Graph.GRG(10, 0.6) @@ -119,15 +119,16 @@ def testProxyMethods(self): # edge indices. # - pagerank() and personalized_pagerank() are ignored because of numerical # inaccuracies + # - shortest_paths() is ignored because it's a deprecated alias # - delete() is ignored because it mutates the graph ignore = ( "neighbors predecessors successors pagerank personalized_pagerank" - " delete incident all_edges in_edges out_edges" + " delete incident all_edges in_edges out_edges shortest_paths" ) ignore = set(ignore.split()) # Methods not listed here are expected to return an int or a float - return_types = {"get_shortest_paths": list, "shortest_paths": list} + return_types = {"distances": list, "get_shortest_paths": list} for name in Vertex.__dict__: if name in ignore: diff --git a/vendor/source/igraph b/vendor/source/igraph index 9cfaafe2b..0963e56ff 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 9cfaafe2b94f293bdaf10c46157db9dd31b465b9 +Subproject commit 0963e56ff287725dc2297b96679be624352cf7f2 From 227e021324391f7e09f03ab01d9e8ffb16f35002 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 17 Jun 2022 18:39:55 +0200 Subject: [PATCH 0990/1892] ci: set MACOSX_DEPLOYMENT_TARGET to 10.9 to make sure that wheels are usable on older versions of macOS --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf8f492c8..eec7e5f19 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" + MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: build_wheel_linux: From 56d15c542a5e6aedc1c3518050a9a5356d51ee15 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 20 Jun 2022 10:21:53 +0200 Subject: [PATCH 0991/1892] fix: trying to fix cross-compilation in CI for macOS arm64 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 0963e56ff..e4a0df242 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 0963e56ff287725dc2297b96679be624352cf7f2 +Subproject commit e4a0df2421b94fcb0e3c294eab1ef2cbe0c61a16 From f60b6f62b831f33405f363607daee5bc025af4b4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 20 Jun 2022 12:31:38 +0200 Subject: [PATCH 0992/1892] ci: skip IEEE754 endianness check when cross-compiling for Apple Silicon --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 260e36efe..34ae2eafe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,7 +77,7 @@ jobs: - cmake_arch: x86_64 wheel_arch: x86_64 - cmake_arch: arm64 - cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h + cmake_extra_args: -DF2C_EXTERNAL_ARITH_HEADER=../../../etc/arith_apple_m1.h -DIEEE754_DOUBLE_ENDIANNESS_MATCHES=ON wheel_arch: arm64 steps: From 2267304303df346d9ee7a1237bc40a022db1adf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 20 Jun 2022 09:40:34 +0200 Subject: [PATCH 0993/1892] =?UTF-8?q?ci:=20build=20libomp=20instead=20of?= =?UTF-8?q?=20using=20Homebrew=E2=80=99s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eec7e5f19..cd77366b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" + CIBW_BUILD_VERBOSITY: "3" MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: @@ -86,6 +87,8 @@ jobs: build_wheel_macos: name: Build wheels on macOS (${{ matrix.wheel_arch }}) runs-on: macos-10.15 + env: + LLVM_VERSION: "14.0.5" strategy: matrix: include: @@ -106,7 +109,14 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + + - name: Cache C core dependencies + id: cache-openmp-lib + uses: actions/cache@v2 + with: + path: ~/local + key: deps-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }} - uses: actions/setup-python@v2 name: Install Python @@ -114,16 +124,28 @@ jobs: python-version: '3.8' - name: Install OS dependencies - if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core + if: steps.cache-c-core.outputs.cache-hit != 'true' || steps.cache-openmp-lib.outputs.cache-hit != 'true' # Only needed when building the C core or libomp run: brew install ninja autoconf automake libtool cmake + - name: Install OpenMP library + if: steps.cache-openmp-lib.outputs.cache-hit != 'true' + run: | + wget https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/openmp-$LLVM_VERSION.src.tar.xz + tar xf openmp-$LLVM_VERSION.src.tar.xz + cd openmp-$LLVM_VERSION.src + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/local -DLIBOMP_ENABLE_SHARED=OFF -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} + cmake --build . + cmake --install . + - name: Build wheels uses: joerick/cibuildwheel@v2.6.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" - IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} + CIBW_ENVIRONMENT: "LDFLAGS=-L$HOME/local/lib" + IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} -DCMAKE_PREFIX_PATH=$HOME/local - uses: actions/upload-artifact@v2 with: From 63a2210d84af090777847415b8c0e1e944cd16d5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 21 Jun 2022 17:31:17 +0200 Subject: [PATCH 0994/1892] fix: revert cibuildwheel verbosity, rename cache-openmp-lib to cache-deps --- .github/workflows/build.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd77366b9..3f631fab3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,6 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" - CIBW_BUILD_VERBOSITY: "3" MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: @@ -112,7 +111,7 @@ jobs: key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - name: Cache C core dependencies - id: cache-openmp-lib + id: cache-c-deps uses: actions/cache@v2 with: path: ~/local @@ -124,12 +123,12 @@ jobs: python-version: '3.8' - name: Install OS dependencies - if: steps.cache-c-core.outputs.cache-hit != 'true' || steps.cache-openmp-lib.outputs.cache-hit != 'true' # Only needed when building the C core or libomp + if: steps.cache-c-core.outputs.cache-hit != 'true' || steps.cache-c-deps.outputs.cache-hit != 'true' # Only needed when building the C core or libomp run: brew install ninja autoconf automake libtool cmake - name: Install OpenMP library - if: steps.cache-openmp-lib.outputs.cache-hit != 'true' + if: steps.cache-c-deps.outputs.cache-hit != 'true' run: | wget https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/openmp-$LLVM_VERSION.src.tar.xz tar xf openmp-$LLVM_VERSION.src.tar.xz From 367d915d8f290a2e7e86799708b9bbc09f7e1c21 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 23 Jun 2022 15:45:13 +0200 Subject: [PATCH 0995/1892] fix: allow edge color and width to vary edge-by-edge for the Matplotlib backend --- CHANGELOG.md | 7 +++++++ src/igraph/drawing/graph.py | 18 +++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a6ece03..a683e29ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- The Matplotlib backend now allows `edge_color` and `edge_width` to be set + on an edge-by-edge basis. + ## [0.9.11] ### Added diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index 809039ca3..747a825d5 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -1194,11 +1194,11 @@ def callback_edge_offset(event): # Edge properties ne = graph.ecount() - ec = kwds.get("edge_color", "black") + edge_color = kwds.get("edge_color", "black") edge_width = kwds.get("edge_width", 1) arrow_width = kwds.get("edge_arrow_width", 2) arrow_length = kwds.get("edge_arrow_size", 4) - ealpha = kwds.get("edge_alpha", 1.0) + edge_alpha = kwds.get("edge_alpha", 1.0) ezorder = kwds.get("edge_order", 1.0) try: ezorder = float(ezorder) @@ -1206,6 +1206,14 @@ def callback_edge_offset(event): except TypeError: pass + # Expand edge_width and edge_color to a list if needed + if isinstance(edge_width, (int, float)): + edge_width = [edge_width] * ne + if isinstance(edge_color, (str, int, float)): + edge_color = [edge_color] * ne + if isinstance(edge_alpha, (int, float)): + edge_alpha = [edge_alpha] * ne + # Decide whether we need to calculate the curvature of edges # automatically -- and calculate them if needed. autocurve = kwds.get("autocurve", None) @@ -1345,9 +1353,9 @@ def callback_edge_offset(event): arrow = FancyArrowPatch( path=path, arrowstyle=arrowstyle, - lw=edge_width, - color=ec, - alpha=ealpha, + lw=edge_width[ie], + color=edge_color[ie], + alpha=edge_alpha[ie], zorder=ezorder[ie], ) ax.add_artist(arrow) From ce527fd3f540d53543da8cba92eff88af8a3f15f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 26 Jun 2022 12:51:19 +0200 Subject: [PATCH 0996/1892] refactor: deprecate Graph.clusters() in favour of Graph.components() and document blocks() alias for biconnected_components() --- CHANGELOG.md | 4 ++++ src/_igraph/graphobject.c | 4 ++-- src/igraph/__init__.py | 34 +++++++++++++++++++++++++++------- src/igraph/formula.py | 2 +- tests/test_games.py | 6 +++--- tests/test_generators.py | 2 +- tests/test_operators.py | 36 ++++++++++++++++++------------------ 7 files changed, 56 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a683e29ba..cf5cd4c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - The Matplotlib backend now allows `edge_color` and `edge_width` to be set on an edge-by-edge basis. +### Deprecated + +- `Graph.clusters()` is now deprecated, use `Graph.components()` instead. + ## [0.9.11] ### Added diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 556429405..5baed3887 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13477,9 +13477,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the calculated harmonic centralities in a list\n"}, /* interface to igraph_clusters */ - {"clusters", (PyCFunction) igraphmodule_Graph_clusters, + {"_clusters", (PyCFunction) igraphmodule_Graph_clusters, METH_VARARGS | METH_KEYWORDS, - "clusters(mode=\"strong\")\n--\n\n" + "_clusters(mode=\"strong\")\n--\n\n" "Calculates the (strong or weak) clusters for a given graph.\n\n" "@attention: this function has a more convenient interface in class\n" " L{Graph} which wraps the result in a L{VertexClustering} object.\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 37030e87c..549b7ae34 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -552,8 +552,9 @@ def all_st_mincuts(self, source, target, capacity=None): ] def biconnected_components(self, return_articulation_points=False): - """\ - Calculates the biconnected components of the graph. + """Calculates the biconnected components of the graph. + + This function is also aliased to ``blocks()``. @param return_articulation_points: whether to return the articulation points as well @@ -611,15 +612,34 @@ def cohesive_blocks(self): return CohesiveBlocks(self, *GraphBase.cohesive_blocks(self)) def clusters(self, mode="strong"): - """Calculates the (strong or weak) clusters (connected components) for - a given graph. + """Calculates the strongly or weakly connected components for a given + graph (deprecated name). + + This function is deprecated; use `components()` instead as the original + name was misleading. @param mode: must be either C{"strong"} or C{"weak"}, depending on the clusters being sought. Optional, defaults to C{"strong"}. - @return: a L{VertexClustering} object""" - return VertexClustering(self, GraphBase.clusters(self, mode)) + @return: a L{VertexClustering} object + """ + deprecated( + "Graph.clusters() is deprecated since igraph 0.9.12, use " + "Graph.components() instead" + ) + return self.components(mode=mode) - components = clusters + def components(self, mode="strong"): + """Calculates the strongly or weakly connected components for a given + graph. + + This function is also aliased to ``clusters()`` for backwards + compatibility. + + @param mode: must be either C{"strong"} or C{"weak"}, depending on the + clusters being sought. Optional, defaults to C{"strong"}. + @return: a L{VertexClustering} object + """ + return VertexClustering(self, GraphBase._clusters(self, mode)) def degree_distribution(self, bin_width=1, *args, **kwds): """Calculates the degree distribution of the graph. diff --git a/src/igraph/formula.py b/src/igraph/formula.py index 65b7596d7..1213f8c73 100644 --- a/src/igraph/formula.py +++ b/src/igraph/formula.py @@ -160,7 +160,7 @@ def construct_graph_from_formula(cls, formula=None, attr="name", simplify=True): >>> g = Graph.Formula("A--B, C--D, E--F, G--H, I, J, K") >>> print(", ".join(g.vs["name"])) A, B, C, D, E, F, G, H, I, J, K - >>> g.clusters().membership + >>> g.components().membership [0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6] The colon (C{:}) operator can be used to specify vertex sets. diff --git a/tests/test_games.py b/tests/test_games.py index 486573298..8a29be5e7 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -25,7 +25,7 @@ def testRecentDegree(self): def testPreference(self): g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) + self.assertTrue(isinstance(g, Graph) and len(g.components()) == 2) g = Graph.Preference(100, [1, 1], [[1, 0], [0, 1]], attribute="type") types = g.vs.get_attribute_values("type") @@ -33,7 +33,7 @@ def testPreference(self): def testAsymmetricPreference(self): g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[0, 1], [1, 0]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 2) + self.assertTrue(isinstance(g, Graph) and len(g.components()) == 2) g = Graph.Asymmetric_Preference( 100, [[0, 1], [1, 0]], [[1, 0], [0, 1]], attribute="type" @@ -44,7 +44,7 @@ def testAsymmetricPreference(self): self.assertTrue(min(types1) == 0 and max(types1) == 1 and min(types2) == 0 and max(types2) == 1) g = Graph.Asymmetric_Preference(100, [[0, 1], [1, 0]], [[1, 0], [0, 1]]) - self.assertTrue(isinstance(g, Graph) and len(g.clusters()) == 1) + self.assertTrue(isinstance(g, Graph) and len(g.components()) == 1) def testTreeGame(self): # Prufer algorithm diff --git a/tests/test_generators.py b/tests/test_generators.py index 576ca5b98..b3df8d64d 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -213,7 +213,7 @@ def testSBM(self): # Simple smoke tests for the expected structure of the graph self.assertTrue(g.is_simple()) self.assertFalse(g.is_directed()) - self.assertEqual([0] * 20 + [1] * 40, g.clusters().membership) + self.assertEqual([0] * 20 + [1] * 40, g.components().membership) g2 = g.subgraph(list(range(20, 60))) self.assertTrue(not any(e.source // 20 == e.target // 20 for e in g2.es)) diff --git a/tests/test_operators.py b/tests/test_operators.py index f2ae015bc..449c62320 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -45,7 +45,7 @@ def testMultiplication(self): self.assertTrue( g.vcount() == 9 and g.ecount() == 9 - and g.clusters().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2] + and g.components().membership == [0, 0, 0, 1, 1, 1, 2, 2, 2] ) def testDifference(self): @@ -252,7 +252,7 @@ def testInPlaceAddition(self): self.assertTrue( g.vcount() == 5 and g.ecount() == 3 - and g.clusters().membership == [0, 0, 0, 1, 2] + and g.components().membership == [0, 0, 0, 1, 2] ) # Adding a vertex by name @@ -260,7 +260,7 @@ def testInPlaceAddition(self): self.assertTrue( g.vcount() == 6 and g.ecount() == 3 - and g.clusters().membership == [0, 0, 0, 1, 2, 3] + and g.components().membership == [0, 0, 0, 1, 2, 3] ) # Adding a single edge @@ -268,13 +268,13 @@ def testInPlaceAddition(self): self.assertTrue( g.vcount() == 6 and g.ecount() == 4 - and g.clusters().membership == [0, 0, 0, 0, 1, 2] + and g.components().membership == [0, 0, 0, 0, 1, 2] ) # Adding two edges g += [(3, 4), (2, 4), (4, 5)] self.assertTrue( - g.vcount() == 6 and g.ecount() == 7 and g.clusters().membership == [0] * 6 + g.vcount() == 6 and g.ecount() == 7 and g.components().membership == [0] * 6 ) # Adding two more vertices @@ -293,7 +293,7 @@ def testInPlaceAddition(self): self.assertTrue( g.vcount() == 11 and g.ecount() == 10 - and g.clusters().membership == [0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3] + and g.components().membership == [0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3] ) # Adding two graphs @@ -301,7 +301,7 @@ def testInPlaceAddition(self): self.assertTrue( g.vcount() == 16 and g.ecount() == 14 - and g.clusters().membership + and g.components().membership == [0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5] ) @@ -313,7 +313,7 @@ def testAddition(self): self.assertTrue( g.vcount() == 5 and g.ecount() == 3 - and g.clusters().membership == [0, 0, 0, 1, 2] + and g.components().membership == [0, 0, 0, 1, 2] ) g0 = g @@ -322,7 +322,7 @@ def testAddition(self): self.assertTrue( g.vcount() == 6 and g.ecount() == 3 - and g.clusters().membership == [0, 0, 0, 1, 2, 3] + and g.components().membership == [0, 0, 0, 1, 2, 3] ) g0 = g @@ -331,14 +331,14 @@ def testAddition(self): self.assertTrue( g.vcount() == 6 and g.ecount() == 4 - and g.clusters().membership == [0, 0, 0, 0, 1, 2] + and g.components().membership == [0, 0, 0, 0, 1, 2] ) g0 = g # Adding two edges g = g0 + [(3, 4), (2, 4), (4, 5)] self.assertTrue( - g.vcount() == 6 and g.ecount() == 7 and g.clusters().membership == [0] * 6 + g.vcount() == 6 and g.ecount() == 7 and g.components().membership == [0] * 6 ) g0 = g @@ -347,7 +347,7 @@ def testAddition(self): self.assertTrue( g.vcount() == 9 and g.ecount() == 10 - and g.clusters().membership == [0, 0, 0, 0, 0, 0, 1, 1, 1] + and g.components().membership == [0, 0, 0, 0, 0, 0, 1, 1, 1] ) def testInPlaceSubtraction(self): @@ -359,7 +359,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 7 and g.ecount() == 21 - and g.clusters().membership == [0, 0, 0, 0, 0, 0, 0] + and g.components().membership == [0, 0, 0, 0, 0, 0, 0] ) # Deleting a vertex @@ -367,7 +367,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 6 and g.ecount() == 15 - and g.clusters().membership == [0, 0, 0, 0, 0, 0] + and g.components().membership == [0, 0, 0, 0, 0, 0] ) # Deleting two vertices @@ -375,7 +375,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 4 and g.ecount() == 6 - and g.clusters().membership == [0, 0, 0, 0] + and g.components().membership == [0, 0, 0, 0] ) # Deleting an edge @@ -383,7 +383,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 4 and g.ecount() == 5 - and g.clusters().membership == [0, 0, 0, 0] + and g.components().membership == [0, 0, 0, 0] ) # Deleting three more edges @@ -391,7 +391,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 4 and g.ecount() == 2 - and g.clusters().membership == [0, 0, 1, 1] + and g.components().membership == [0, 0, 1, 1] ) # Did we really use the original graph so far? @@ -403,7 +403,7 @@ def testInPlaceSubtraction(self): self.assertTrue( g.vcount() == 4 and g.ecount() == 1 - and g.clusters().membership == [0, 1, 2, 2] + and g.components().membership == [0, 1, 2, 2] ) def testNonzero(self): From da7484807f5152a2c18c55dd4154653de2c7f5f7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 26 Jun 2022 12:52:59 +0200 Subject: [PATCH 0997/1892] fix: removed return_alpha_only kwarg of power_law_fit() that was deprecated a long time ago --- src/igraph/statistics.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 68350b86a..5d09c7cad 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -529,7 +529,7 @@ def percentile(xs, p=(25, 50, 75), sort=True): return quantile(xs, p / 100.0, sort) -def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): +def power_law_fit(data, xmin=None, method="auto"): """Fitting a power-law distribution to empirical data @param data: the data to fit, a list containing integer values @@ -566,7 +566,8 @@ def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): @ref: MEJ Newman: Power laws, Pareto distributions and Zipf's law. Contemporary Physics 46, 323-351 (2005) @ref: A Clauset, CR Shalizi, MEJ Newman: Power-law distributions - in empirical data. E-print (2007). arXiv:0706.1062""" + in empirical data. E-print (2007). arXiv:0706.1062 + """ from igraph._igraph import _power_law_fit if xmin is None or xmin < 0: @@ -577,17 +578,7 @@ def power_law_fit(data, xmin=None, method="auto", return_alpha_only=False): raise ValueError("unknown method: %s" % method) force_continuous = method in ("continuous", "hill") - fit = FittedPowerLaw(*_power_law_fit(data, xmin, force_continuous)) - if return_alpha_only: - from igraph import deprecated - - deprecated( - "The return_alpha_only keyword argument of power_law_fit is " - "deprecated from igraph 0.7 and will be removed in igraph 0.8" - ) - return fit.alpha - else: - return fit + return FittedPowerLaw(*_power_law_fit(data, xmin, force_continuous)) def quantile(xs, q=(0.25, 0.5, 0.75), sort=True): From e86e58917fa04bd7594679b1bf0b609a433829c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 4 Jul 2022 13:42:18 +0200 Subject: [PATCH 0998/1892] docs: better explain the characteristics of methods in Graph.Degree_Sequence --- src/_igraph/graphobject.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 5baed3887..f00b569c8 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13121,9 +13121,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " If omitted, the generated graph will be undirected.\n" "@param method: the generation method to be used. One of the following:\n" " \n" - " - C{\"simple\"} -- simple generator that sometimes generates\n" - " loop edges and multiple edges. The generated graph is not\n" - " guaranteed to be connected.\n" + " - C{\"simple\"} -- simple generator that implements the stub-matching\n" + " configuration model. It may generate self-loops and multiple edges.\n" + " This method does not sample multigraphs uniformly, but it can be\n" + " used to implement uniform sampling for simple graphs by rejecting\n" + " any result that is non-simple (i.e. contains loops or multi-edges).\n" " - C{\"no_multiple\"} -- similar to C{\"simple\"} but avoids the\n" " generation of multiple and loop edges at the expense of increased\n" " time complexity. The method will re-start the generation every time\n" @@ -13132,9 +13134,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " is no upper bound on the number of iterations, but it will succeed\n" " eventually if the input degree sequence is graphical and throw an\n" " exception if the input degree sequence is not graphical.\n" + " This method does not sample simple graphs uniformly.\n" " - C{\"vl\"} -- a more sophisticated generator that can sample\n" - " undirected, connected simple graphs uniformly. It uses\n" - " Monte-Carlo methods to randomize the graphs.\n" + " undirected, connected simple graphs approximately uniformly. It uses\n" + " edge-switching Monte-Carlo methods to randomize the graphs.\n" " This generator should be favoured if undirected and connected\n" " graphs are to be generated and execution time is not a concern.\n" " igraph uses the original implementation of Fabien Viger; see the\n" From b8e0c2117fec32e72cf253653fc20987bf0a33a6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Jul 2022 14:01:58 +0200 Subject: [PATCH 0999/1892] feat: IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM now exposed --- CHANGELOG.md | 11 +++++++++++ src/_igraph/convert.c | 1 + src/_igraph/graphobject.c | 9 +++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf5cd4c83..ebc3fa378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## [Unreleased] +### Added + +- `Graph.Degree_Sequence()` now supports the `"no_multiple_uniform"` generation + method, which generates simple graphs, sampled uniformly, using rejection + sampling. + +### Changed + +- `Graph.Degree_Sequence()` now accepts all sorts of sequences as inputs, not + only lists. + ### Fixed - The Matplotlib backend now allows `edge_color` and `edge_width` to be set diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 7710c9ed9..a314433df 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -514,6 +514,7 @@ int igraphmodule_PyObject_to_degseq_t(PyObject *o, {"no_multiple", IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE}, {"vl", IGRAPH_DEGSEQ_VL}, {"viger-latapy", IGRAPH_DEGSEQ_VL}, + {"no_multiple_uniform", IGRAPH_DEGSEQ_SIMPLE_NO_MULTIPLE_UNIFORM}, {0,0} }; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f00b569c8..65cab4ffd 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2205,10 +2205,8 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, static char *kwlist[] = { "out", "in_", "method", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!O", kwlist, - &PyList_Type, &outdeg, - &PyList_Type, &indeg, - &method)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, + &outdeg, &indeg, &method)) return NULL; if (igraphmodule_PyObject_to_degseq_t(method, &meth)) return NULL; @@ -13135,6 +13133,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " eventually if the input degree sequence is graphical and throw an\n" " exception if the input degree sequence is not graphical.\n" " This method does not sample simple graphs uniformly.\n" + " - C{\"no_multiple_uniform\"} -- similar to C{\"simple\"} but rejects\n" + " generated graphs if they are not simple. This method samples simple\n" + " graphs uniformly.\n" " - C{\"vl\"} -- a more sophisticated generator that can sample\n" " undirected, connected simple graphs approximately uniformly. It uses\n" " edge-switching Monte-Carlo methods to randomize the graphs.\n" From 2bd774f622de7f23ba116bd4ce96b12606cebc35 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Jul 2022 15:28:33 +0200 Subject: [PATCH 1000/1892] feat: exposed IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE and updated documentation of Graph.Degree_Sequence() with the new names --- src/_igraph/convert.c | 9 ++++++++- src/_igraph/graphobject.c | 29 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 937c74b9d..006468fdc 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -526,10 +526,17 @@ int igraphmodule_PyObject_to_community_comparison_t(PyObject *o, int igraphmodule_PyObject_to_degseq_t(PyObject *o, igraph_degseq_t *result) { static igraphmodule_enum_translation_table_entry_t degseq_tt[] = { + /* legacy names before 0.10 */ {"simple", IGRAPH_DEGSEQ_CONFIGURATION}, {"no_multiple", IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE}, - {"vl", IGRAPH_DEGSEQ_VL}, {"viger-latapy", IGRAPH_DEGSEQ_VL}, + /* up-to-date names as of igraph 0.10 */ + {"configuration", IGRAPH_DEGSEQ_CONFIGURATION}, + {"vl", IGRAPH_DEGSEQ_VL}, + {"viger_latapy", IGRAPH_DEGSEQ_VL}, + {"fast_heur_simple", IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE}, + {"configuration_simple", IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE}, + {"edge_switching_simple", IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE}, {0,0} }; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 292391628..37449f3aa 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13242,7 +13242,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_degree_sequence_game */ {"Degree_Sequence", (PyCFunction) igraphmodule_Graph_Degree_Sequence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "Degree_Sequence(out, in_=None, method=\"simple\")\n--\n\n" + "Degree_Sequence(out, in_=None, method=\"configuration\")\n--\n\n" "Generates a graph with a given degree sequence.\n\n" "@param out: the out-degree sequence for a directed graph. If the\n" " in-degree sequence is omitted, the generated graph\n" @@ -13252,17 +13252,27 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " If omitted, the generated graph will be undirected.\n" "@param method: the generation method to be used. One of the following:\n" " \n" - " - C{\"simple\"} -- simple generator that sometimes generates\n" - " loop edges and multiple edges. The generated graph is not\n" - " guaranteed to be connected.\n" - " - C{\"no_multiple\"} -- similar to C{\"simple\"} but avoids the\n" - " generation of multiple and loop edges at the expense of increased\n" + " - C{\"configuration\"} -- simple generator that implements the stub-matching\n" + " configuration model. It may generate self-loops and multiple edges.\n" + " This method does not sample multigraphs uniformly, but it can be\n" + " used to implement uniform sampling for simple graphs by rejecting\n" + " any result that is non-simple (i.e. contains loops or multi-edges).\n" + " - C{\"fast_heur_simple\"} -- similar to C{\"configuration\"} but avoids\n" + " the generation of multiple and loop edges at the expense of increased\n" " time complexity. The method will re-start the generation every time\n" " it gets stuck in a configuration where it is not possible to insert\n" " any more edges without creating loops or multiple edges, and there\n" " is no upper bound on the number of iterations, but it will succeed\n" " eventually if the input degree sequence is graphical and throw an\n" " exception if the input degree sequence is not graphical.\n" + " This method does not sample simple graphs uniformly.\n" + " - C{\"configuration_simple\"} -- similar to C{\"configuration\"} but\n" + " rejects generated graphs if they are not simple. This method samples\n" + " simple graphs uniformly.\n" + " - C{\"edge_switching_simple\"} -- an MCMC sampler based on degree-preserving\n" + " edge switches. It generates simple undirected or directed graphs. The\n" + " algorithm uses L{Graph.Realize_Degree_Sequence()} to construct an\n" + " initial graph, then rewires it using L{Graph.rewire()}.\n" " - C{\"vl\"} -- a more sophisticated generator that can sample\n" " undirected, connected simple graphs uniformly. It uses\n" " Monte-Carlo methods to randomize the graphs.\n" @@ -13271,6 +13281,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " igraph uses the original implementation of Fabien Viger; see the\n" " following URL and the paper cited on it for the details of the\n" " algorithm: U{https://www-complexnetworks.lip6.fr/~latapy/FV/generation.html}.\n" + " \n" + " Legacy names that were valid before igraph 0.10 are also supported, but\n" + " these may be removed without further notice:\n" + " \n" + " - C{\"simple\"} -- equivalent to C{\"configuration\"}" + " - C{\"no_multiple\"} -- equivalent to C{\"fast_heur_simple\"}" + " - C{\"no_multiple_uniform\"} -- equivalent to C{\"configuration_simple\"}\n" }, /* interface to igraph_isoclass_create */ From 78a41975b70b4a69b8fbbdd78d515d8fda8c6368 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Jul 2022 00:00:02 +0200 Subject: [PATCH 1001/1892] feat: added Graph.reverse_edges() --- CHANGELOG.md | 2 ++ src/_igraph/graphobject.c | 55 +++++++++++++++++++++++++++++++++++++-- tests/test_operators.py | 22 ++++++++++++++++ vendor/source/igraph | 2 +- 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebc3fa378..35bee4a8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ method, which generates simple graphs, sampled uniformly, using rejection sampling. +- `Graph.reverse_edges()` reverses some or all edges of a graph. + ### Changed - `Graph.Degree_Sequence()` now accepts all sorts of sequences as inputs, not diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 65cab4ffd..833cf72ec 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -716,14 +716,14 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, /* no arguments means delete all. */ - /*Py_None also means all for now, but it is deprecated */ + /* Py_None also means all for now, but it is deprecated */ if (list == Py_None) { PyErr_Warn(PyExc_DeprecationWarning, "Graph.delete_vertices(None) is " "deprecated since igraph 0.8.3, please use " "Graph.delete_vertices() instead"); } - /* this already converts no arguments and Py_None to all vertices */ + /* this already converts no arguments and Py_None to all edges */ if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { /* something bad happened during conversion, return immediately */ return NULL; @@ -10124,6 +10124,43 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, return (PyObject *) result; } + +/** \ingroup python_interface_graph + * \brief Reverses some edges in an \c igraph.Graph + * \return the modified \c igraph.Graph object + * \sa igraph_reverse_edges + */ +PyObject *igraphmodule_Graph_reverse_edges(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + PyObject *list = 0; + igraph_es_t es; + static char *kwlist[] = { "edges", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &list)) + return NULL; + + /* no arguments means reverse all; Py_None means reverse _nothing_ */ + if (list == Py_None) { + Py_RETURN_NONE; + } + + /* this one converts no arguments to all edges */ + if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { + /* something bad happened during conversion, return immediately */ + return NULL; + } + + if (igraph_reverse_edges(&self->g, es)) { + igraphmodule_handle_igraph_error(); + igraph_es_destroy(&es); + return NULL; + } + + igraph_es_destroy(&es); + Py_RETURN_NONE; +} + /********************************************************************** * Graph traversal algorithms * **********************************************************************/ @@ -15799,21 +15836,35 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /////////////// // OPERATORS // /////////////// + {"complementer", (PyCFunction) igraphmodule_Graph_complementer, METH_VARARGS | METH_KEYWORDS, "complementer(loops=False)\n--\n\n" "Returns the complementer of the graph\n\n" "@param loops: whether to include loop edges in the complementer.\n" "@return: the complementer of the graph\n"}, + {"compose", (PyCFunction) igraphmodule_Graph_compose, METH_O, "compose(other)\n--\n\nReturns the composition of two graphs."}, + {"difference", (PyCFunction) igraphmodule_Graph_difference, METH_O, "difference(other)\n--\n\nSubtracts the given graph from the original"}, + /* interface to igraph_delete_edges */ + {"reverse_edges", (PyCFunction) igraphmodule_Graph_reverse_edges, + METH_VARARGS | METH_KEYWORDS, + "reverse_edges(es)\n--\n\n" + "Reverses the direction of some edges in the graph.\n\n" + "This function is a no-op for undirected graphs.\n\n" + "@param es: the list of edges to be reversed. Edges are identifed by\n" + " edge IDs. L{EdgeSeq} objects are also accepted here. When omitted,\n" + " all edges will be reversed.\n"}, + /**********************/ /* DOMINATORS */ /**********************/ + {"dominator", (PyCFunction) igraphmodule_Graph_dominator, METH_VARARGS | METH_KEYWORDS, "dominator(vid, mode=\"out\")\n--\n\n" diff --git a/tests/test_operators.py b/tests/test_operators.py index 449c62320..283aff151 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -518,6 +518,28 @@ def testContractVerticesWithNumPyIntegers(self): ], ) + def testReverseEdges(self): + g = Graph.Tree(10, 3, mode="out") + g.reverse_edges([0, 1, 2]) + self.assertEqual( + g.get_edgelist(), + [ + (1, 0), + (2, 0), + (3, 0), + (1, 4), + (1, 5), + (1, 6), + (2, 7), + (2, 8), + (2, 9) + ] + ) + + g = Graph.Tree(13, 3, mode="in") + g.reverse_edges() + self.assertTrue(g.isomorphic(Graph.Tree(13, 3, mode="out"))) + def suite(): operator_suite = unittest.makeSuite(OperatorTests) diff --git a/vendor/source/igraph b/vendor/source/igraph index 2f79050fc..fbb4ff098 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2f79050fc219f045a23d2e42f72ebd18854a2e0e +Subproject commit fbb4ff098960aeee6180277dad8bf1979f026ce5 From bfedb1e02c8c8ec7329783747784ab0e5e66fccc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Jul 2022 00:00:02 +0200 Subject: [PATCH 1002/1892] feat: added Graph.reverse_edges() --- CHANGELOG.md | 4 +++ src/_igraph/graphobject.c | 53 ++++++++++++++++++++++++++++++++++++++- tests/test_operators.py | 22 ++++++++++++++++ vendor/source/igraph | 2 +- 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e26eca6c8..8d8889614 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,10 @@ ## [Unreleased] +### Added + +- `Graph.reverse_edges()` reverses some or all edges of a graph. + ### Fixed - Fixed a bug in the Cairo and Matplotlib backends that prevented edges with diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 37449f3aa..797e6be58 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -719,7 +719,7 @@ PyObject *igraphmodule_Graph_delete_edges(igraphmodule_GraphObject * self, Py_RETURN_NONE; } - /* this already converts no arguments and Py_None to all vertices */ + /* this already converts no arguments and Py_None to all edges */ if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { /* something bad happened during conversion, return immediately */ return NULL; @@ -10215,6 +10215,43 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, return (PyObject *) result_o; } + +/** \ingroup python_interface_graph + * \brief Reverses some edges in an \c igraph.Graph + * \return the modified \c igraph.Graph object + * \sa igraph_reverse_edges + */ +PyObject *igraphmodule_Graph_reverse_edges(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) +{ + PyObject *list = 0; + igraph_es_t es; + static char *kwlist[] = { "edges", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &list)) + return NULL; + + /* no arguments means reverse all; Py_None means reverse _nothing_ */ + if (list == Py_None) { + Py_RETURN_NONE; + } + + /* this one converts no arguments to all edges */ + if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { + /* something bad happened during conversion, return immediately */ + return NULL; + } + + if (igraph_reverse_edges(&self->g, es)) { + igraphmodule_handle_igraph_error(); + igraph_es_destroy(&es); + return NULL; + } + + igraph_es_destroy(&es); + Py_RETURN_NONE; +} + /********************************************************************** * Graph traversal algorithms * **********************************************************************/ @@ -15990,21 +16027,35 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /////////////// // OPERATORS // /////////////// + {"complementer", (PyCFunction) igraphmodule_Graph_complementer, METH_VARARGS | METH_KEYWORDS, "complementer(loops=False)\n--\n\n" "Returns the complementer of the graph\n\n" "@param loops: whether to include loop edges in the complementer.\n" "@return: the complementer of the graph\n"}, + {"compose", (PyCFunction) igraphmodule_Graph_compose, METH_O, "compose(other)\n--\n\nReturns the composition of two graphs."}, + {"difference", (PyCFunction) igraphmodule_Graph_difference, METH_O, "difference(other)\n--\n\nSubtracts the given graph from the original"}, + /* interface to igraph_delete_edges */ + {"reverse_edges", (PyCFunction) igraphmodule_Graph_reverse_edges, + METH_VARARGS | METH_KEYWORDS, + "reverse_edges(es)\n--\n\n" + "Reverses the direction of some edges in the graph.\n\n" + "This function is a no-op for undirected graphs.\n\n" + "@param es: the list of edges to be reversed. Edges are identifed by\n" + " edge IDs. L{EdgeSeq} objects are also accepted here. When omitted,\n" + " all edges will be reversed.\n"}, + /**********************/ /* DOMINATORS */ /**********************/ + {"dominator", (PyCFunction) igraphmodule_Graph_dominator, METH_VARARGS | METH_KEYWORDS, "dominator(vid, mode=\"out\")\n--\n\n" diff --git a/tests/test_operators.py b/tests/test_operators.py index 85bc97598..a87c585ab 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -518,6 +518,28 @@ def testContractVerticesWithNumPyIntegers(self): ], ) + def testReverseEdges(self): + g = Graph.Tree(10, 3, mode="out") + g.reverse_edges([0, 1, 2]) + self.assertEqual( + g.get_edgelist(), + [ + (1, 0), + (2, 0), + (3, 0), + (1, 4), + (1, 5), + (1, 6), + (2, 7), + (2, 8), + (2, 9) + ] + ) + + g = Graph.Tree(13, 3, mode="in") + g.reverse_edges() + self.assertTrue(g.isomorphic(Graph.Tree(13, 3, mode="out"))) + def suite(): operator_suite = unittest.makeSuite(OperatorTests) diff --git a/vendor/source/igraph b/vendor/source/igraph index e4a0df242..3aa446401 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit e4a0df2421b94fcb0e3c294eab1ef2cbe0c61a16 +Subproject commit 3aa446401881f9455af0c89ad7e02d8ed12654f1 From 91080a4fab0863a1f21a85e2eecf2bc110f57d87 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 9 Jul 2022 21:02:47 +0200 Subject: [PATCH 1003/1892] ci: cache based on the hashes of .git/modules/**/HEAD instead of .gitmodules --- .github/workflows/build.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f631fab3..c84c5a893 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -108,7 +108,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/**/HEAD') }} - name: Cache C core dependencies id: cache-c-deps @@ -179,7 +179,7 @@ jobs: uses: actions/cache@v2 with: path: vendor/install - key: C-core-build-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.gitmodules') }}- + key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/**/HEAD') }} - name: Cache VCPKG uses: actions/cache@v2 @@ -230,9 +230,8 @@ jobs: uses: actions/cache@v2 with: path: | - vendor/build vendor/install - key: C-core-${{ runner.os }}-${{ hashFiles('.gitmodules') }}-4 + key: C-core-cache-${{ runner.os }}-${{ hashFiles('.git/modules/**/HEAD') }} - name: Install OS dependencies if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core From 5bd535de3758f2aebc67e8cadb3435955a8be90f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 10 Jul 2022 13:02:27 +0200 Subject: [PATCH 1004/1892] fix: fix a duplicate function introduced during the merge --- src/_igraph/graphobject.c | 38 -------------------------------------- tests/test_iterators.py | 2 +- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index ad0f46d52..b8f9e8639 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -10213,44 +10213,6 @@ PyObject *igraphmodule_Graph_compose(igraphmodule_GraphObject * self, return (PyObject *) result_o; } - -/** \ingroup python_interface_graph - * \brief Reverses some edges in an \c igraph.Graph - * \return the modified \c igraph.Graph object - * \sa igraph_reverse_edges - */ -PyObject *igraphmodule_Graph_reverse_edges(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) -{ - PyObject *list = 0; - igraph_es_t es; - static char *kwlist[] = { "edges", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &list)) - return NULL; - - /* no arguments means reverse all; Py_None means reverse _nothing_ */ - if (list == Py_None) { - Py_RETURN_NONE; - } - - /* this one converts no arguments to all edges */ - if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) { - /* something bad happened during conversion, return immediately */ - return NULL; - } - - if (igraph_reverse_edges(&self->g, es)) { - igraphmodule_handle_igraph_error(); - igraph_es_destroy(&es); - return NULL; - } - - igraph_es_destroy(&es); - Py_RETURN_NONE; -} - - /** \ingroup python_interface_graph * \brief Reverses some edges in an \c igraph.Graph * \return the modified \c igraph.Graph object diff --git a/tests/test_iterators.py b/tests/test_iterators.py index ddf5e44f0..e1ab34984 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -8,7 +8,7 @@ def testBFS(self): g = Graph.Tree(10, 2) vs, layers, ps = g.bfs(0) self.assertEqual(vs, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - self.assertEqual(ps, [0, 0, 0, 1, 1, 2, 2, 3, 3, 4]) + self.assertEqual(ps, [-1, 0, 0, 1, 1, 2, 2, 3, 3, 4]) def testBFSIter(self): g = Graph.Tree(10, 2) From 8f56a48071e4aea4df4ac519eb9f4664dbaff15e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 10 Jul 2022 13:13:45 +0200 Subject: [PATCH 1005/1892] fix: changed Graph.dfs() to be consistent with Graph.bfs() when returning the parent of the root --- src/igraph/__init__.py | 2 +- tests/test_iterators.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a4f2c0af4..3c130baa4 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -772,7 +772,7 @@ def dfs(self, vid, mode=OUT): # ok start from vid stack.append((vid, self.neighbors(vid, mode=mode))) vids.append(vid) - parents.append(vid) + parents.append(-1) added[vid] = True # go down the rabbit hole diff --git a/tests/test_iterators.py b/tests/test_iterators.py index e1ab34984..9ce63aabb 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -35,7 +35,7 @@ def testDFS(self): g = Graph.Tree(10, 2) vs, ps = g.dfs(0) self.assertEqual(vs, [0, 2, 6, 5, 1, 4, 9, 3, 8, 7]) - self.assertEqual(ps, [0, 0, 2, 2, 0, 1, 4, 1, 3, 3]) + self.assertEqual(ps, [-1, 0, 2, 2, 0, 1, 4, 1, 3, 3]) def testDFSIter(self): g = Graph.Tree(10, 2) From e522e243a56fa7faee6155786f0b43c4943b1f9c Mon Sep 17 00:00:00 2001 From: tristanlatr <19967168+tristanlatr@users.noreply.github.com> Date: Tue, 12 Jul 2022 16:19:33 -0400 Subject: [PATCH 1006/1892] Don't generate the pydoctor sidebar The API documentation is currently not optimal, the sidebar is shown inline the main contents because the CSS is customized and integrated in a smaller div. Skipping the sidebar generation is probably the best --- scripts/mkdoc.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 5bbab7145..fb4d9ab33 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -44,11 +44,16 @@ rm -f dist/*.whl && .venv/bin/pip install . IGRAPHDIR=`.venv/bin/python3 -c 'import igraph, os; print(os.path.dirname(igraph.__file__))'` echo "Generating HTML documentation..." + +# Using --no-sidebar option to skip the sidebar whole together not to generate noise in the HTML. +# Because the pydoctor output is integrated in a smaller div with a custom CSS it's not optimal to include the sidebar. + "$PYDOCTOR" \ --project-name "igraph" \ --project-url "https://igraph.org/python" \ --introspect-c-modules \ --make-html \ + --no-sidebar \ --html-output "${DOC_API_FOLDER}/html" \ ${IGRAPHDIR} From 5c1aa56f52a18e1f469c4856b1be74d5c0ef60d9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 28 Jul 2022 14:06:17 +0200 Subject: [PATCH 1007/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 25849d584..aeb9ecba4 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 25849d58453884676b2221778951c23f08bd8cd5 +Subproject commit aeb9ecba4e707ad146588daeefc7e5848a7a1828 From f5006bbef640897b6a9112bc3dde61b83aac66b7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 29 Jul 2022 12:05:21 +0200 Subject: [PATCH 1008/1892] fix: fix code for newer igraph develop branch --- src/_igraph/edgeseqobject.c | 14 +++++++------- src/_igraph/graphobject.c | 11 +++++++---- src/_igraph/vertexseqobject.c | 14 +++++++------- tests/test_edgeseq.py | 5 ++++- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 5d6fdc50a..7c8702a67 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -226,12 +226,12 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, } break; - case IGRAPH_ES_SEQ: + case IGRAPH_ES_RANGE: if (i < 0) { - i = self->es.data.seq.to - self->es.data.seq.from + i; + i = self->es.data.range.end - self->es.data.range.start + i; } - if (i >= 0 && i < self->es.data.seq.to - self->es.data.seq.from) { - idx = self->es.data.seq.from + i; + if (i >= 0 && i < self->es.data.range.end - self->es.data.range.start) { + idx = self->es.data.range.start + i; } break; @@ -342,15 +342,15 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* } break; - case IGRAPH_ES_SEQ: - n = self->es.data.seq.to - self->es.data.seq.from; + case IGRAPH_ES_RANGE: + n = self->es.data.range.end - self->es.data.range.start; result = PyList_New(n); if (!result) { return 0; } for (i = 0; i < n; i++) { - item = PyList_GetItem(values, self->es.data.seq.from + i); + item = PyList_GetItem(values, self->es.data.range.start + i); if (!item) { Py_DECREF(result); return 0; diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index b8f9e8639..3b16533fa 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1107,10 +1107,11 @@ PyObject *igraphmodule_Graph_is_mutual(igraphmodule_GraphObject *self, igraph_vector_bool_t res; igraph_es_t es; igraph_bool_t return_single = 0; + PyObject* loops_o = Py_True; - static char *kwlist[] = { "edges", NULL }; + static char *kwlist[] = { "edges", "loops", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &list)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &list, &loops_o)) return NULL; if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, &return_single)) { @@ -1124,7 +1125,7 @@ PyObject *igraphmodule_Graph_is_mutual(igraphmodule_GraphObject *self, return NULL; } - if (igraph_is_mutual(&self->g, &res, es)) { + if (igraph_is_mutual(&self->g, &res, es, PyObject_IsTrue(loops_o))) { igraphmodule_handle_igraph_error(); igraph_es_destroy(&es); igraph_vector_bool_destroy(&res); @@ -12676,7 +12677,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_is_mutual */ {"is_mutual", (PyCFunction) igraphmodule_Graph_is_mutual, METH_VARARGS | METH_KEYWORDS, - "is_mutual(edges=None)\n--\n\n" + "is_mutual(edges=None, loops=True)\n--\n\n" "Checks whether an edge has an opposite pair.\n\n" "Also works for a set of edges -- in this case, every edge is checked\n" "one by one. The result will be a list of booleans (or a single boolean\n" @@ -12690,6 +12691,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "of edges do not matter.\n\n" "@param edges: edge indices which we want to check. If C{None}, all\n" " edges are checked.\n" + "@param loops: specifies whether loop edges should be treated as mutual\n" + " in a directed graph.\n" "@return: a list of booleans, one for every edge given\n"}, /* interface to igraph_count_multiple */ diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 11d05403a..643077076 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -223,12 +223,12 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, break; case IGRAPH_VS_NONE: break; - case IGRAPH_VS_SEQ: + case IGRAPH_VS_RANGE: if (i < 0) { - i = self->vs.data.seq.to - self->vs.data.seq.from + i; + i = self->vs.data.range.end - self->vs.data.range.start + i; } - if (i >= 0 && i < self->vs.data.seq.to - self->vs.data.seq.from) { - idx = self->vs.data.seq.from + i; + if (i >= 0 && i < self->vs.data.range.end - self->vs.data.range.start) { + idx = self->vs.data.range.start + i; } break; /* TODO: IGRAPH_VS_ADJ, IGRAPH_VS_NONADJ - someday :) They are unused @@ -328,13 +328,13 @@ PyObject* igraphmodule_VertexSeq_get_attribute_values(igraphmodule_VertexSeqObje break; - case IGRAPH_VS_SEQ: - n = self->vs.data.seq.to - self->vs.data.seq.from; + case IGRAPH_VS_RANGE: + n = self->vs.data.range.end - self->vs.data.range.start; result = PyList_New(n); if (!result) return 0; for (i = 0; i < n; i++) { - item = PyList_GetItem(values, self->vs.data.seq.from + i); + item = PyList_GetItem(values, self->vs.data.range.start + i); if (!item) { Py_DECREF(result); return 0; diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index bf8fd51e3..ae5e40ae8 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -401,13 +401,16 @@ def testGraphMethodProxying(self): self.assertEqual([ebs[i] for i in idxs], es.edge_betweenness()) idxs = [1, 3] - g = Graph([(0, 1), (1, 2), (2, 0), (1, 0)], directed=True) + g = Graph([(0, 1), (1, 2), (2, 0), (1, 0), (2, 2)], directed=True) es = g.es(*idxs) mutual = g.is_mutual(es) self.assertEqual(mutual, es.is_mutual()) for e, m in zip(es, mutual): self.assertEqual(e.is_mutual(), m) + self.assertTrue(g.es[4].is_mutual()) + self.assertFalse(g.es[4].is_mutual(loops=False)) + def testIsAll(self): g = Graph.Full(5) self.assertTrue(g.es.is_all()) From 3018b0d038cb77d78f2ff85232818e83f209e887 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 2 Aug 2022 13:04:45 +0200 Subject: [PATCH 1009/1892] chore: updated vendored igraph --- src/_igraph/graphobject.c | 17 +++++++++-------- vendor/source/igraph | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3b16533fa..7ae3d748d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4280,7 +4280,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; igraph_vector_t res, *weights = 0; igraph_neimode_t mode = IGRAPH_ALL; - int return_single = 0; + igraph_bool_t return_single = 0; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, @@ -4360,7 +4360,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; igraph_vector_t res, *weights = 0; igraph_neimode_t mode = IGRAPH_ALL; - int return_single = 0; + igraph_bool_t return_single = 0; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, @@ -4539,7 +4539,7 @@ PyObject *igraphmodule_Graph_cocitation(igraphmodule_GraphObject * self, char *kwlist[] = { "vertices", NULL }; PyObject *vobj = NULL, *list = NULL; igraph_matrix_t res; - int return_single = 0; + igraph_bool_t return_single = 0; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &vobj)) @@ -4678,7 +4678,7 @@ PyObject *igraphmodule_Graph_eccentricity(igraphmodule_GraphObject* self, PyObject *vobj = Py_None, *list = NULL, *mode_o = Py_None; igraph_vector_t res; igraph_neimode_t mode = IGRAPH_OUT; - int return_single = 0; + igraph_bool_t return_single = 0; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &vobj, &mode_o)) @@ -5722,7 +5722,8 @@ PyObject *igraphmodule_Graph_distances( igraph_matrix_t res; igraph_vector_t *weights=0; igraph_neimode_t mode = IGRAPH_OUT; - int return_single_from = 0, return_single_to = 0, e = 0; + igraph_bool_t return_single_from = 0, return_single_to = 0; + igraph_error_t e = 0; igraph_vs_t from_vs, to_vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, @@ -5830,7 +5831,7 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, /* Case #1: vertices, returning matrix */ igraph_matrix_t res; igraph_vs_t vs; - int return_single = 0; + igraph_bool_t return_single = 0; if (igraphmodule_PyObject_to_vs_t(vertices_o, &vs, &self->g, &return_single, 0)) return NULL; @@ -5916,7 +5917,7 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, /* Case #1: vertices, returning matrix */ igraph_matrix_t res; igraph_vs_t vs; - int return_single = 0; + igraph_bool_t return_single = 0; if (igraphmodule_PyObject_to_vs_t(vertices_o, &vs, &self->g, &return_single, 0)) return NULL; @@ -5987,7 +5988,7 @@ PyObject *igraphmodule_Graph_similarity_inverse_log_weighted( PyObject *vobj = NULL, *list = NULL, *mode_o = Py_None; igraph_matrix_t res; igraph_neimode_t mode = IGRAPH_ALL; - int return_single = 0; + igraph_bool_t return_single = 0; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &vobj, &mode_o)) diff --git a/vendor/source/igraph b/vendor/source/igraph index aeb9ecba4..4d2a03c30 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit aeb9ecba4e707ad146588daeefc7e5848a7a1828 +Subproject commit 4d2a03c30d303f6e6b9a64c7bf0c334b856c3c8c From 950d61a1c4dec3d0793c3b5327f154d64009f536 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Aug 2022 11:11:39 +0200 Subject: [PATCH 1010/1892] doc: remove occurrences of the now-removed 'power' implementation of PageRank, fixes #558 --- src/igraph/__init__.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 549b7ae34..43f67f5d6 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -1023,16 +1023,12 @@ def pagerank( implementation in igraph 0.7 - C{"arpack"}: use the ARPACK library. This implementation was used from version 0.5, until version 0.7. - - C{"power"}: use a simple power method. This is the - implementation that was used before igraph version 0.5. - @param niter: The number of iterations to use in the power method - implementation. It is ignored in the other implementations - @param eps: The power method implementation will consider the - calculation as complete if the difference of PageRank values between - iterations change less than this value for every node. It is - ignored by the other implementations. - @return: a list with the Google PageRank values of the specified - vertices.""" + @param niter: unused, kept for sake of backwards compatibility. It will + be removed in igraph 0.10. + @param eps: unused, kept for sake of backwards compatibility. It will + be removed in igraph 0.10. + @return: a list with the PageRank values of the specified vertices. + """ if arpack_options is None: arpack_options = default_arpack_options return self.personalized_pagerank( From bb58b4db67a8ff386ca3061e599bd14bfcc1e135 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Aug 2022 11:37:11 +0200 Subject: [PATCH 1011/1892] fix: remove unused niter and eps arguments --- src/igraph/structural.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/igraph/structural.py b/src/igraph/structural.py index 0fe4da239..2aa0283ab 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -80,8 +80,6 @@ def _pagerank( weights, arpack_options, implementation, - niter, - eps, ) From ff0ea6ab2d80a6205f69a87988d128508f97ef8d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Aug 2022 14:06:38 +0200 Subject: [PATCH 1012/1892] chore: updated vendored igraph --- src/_igraph/convert.c | 2 +- src/_igraph/graphobject.c | 4 ++-- vendor/source/igraph | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 006468fdc..1b6120806 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1382,7 +1382,7 @@ PyObject* igraphmodule_real_t_to_PyObject(igraph_real_t value, igraphmodule_conv } else if (type == IGRAPHMODULE_TYPE_FLOAT) { return PyFloat_FromDouble(value); } else if (type == IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT) { - if (ceil(value) != value) { + if (!isfinite(value) || isnan(value) || ceil(value) != value) { return PyFloat_FromDouble(value); } else { return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 7ae3d748d..bad0057d1 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1724,7 +1724,7 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, { PyObject *sc = Py_False; static char *kwlist[] = { "return_shortest_circle", NULL }; - igraph_integer_t girth; + igraph_real_t girth; igraph_vector_int_t vids; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sc)) { @@ -1749,7 +1749,7 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, return o; } - return igraphmodule_integer_t_to_PyObject(girth); + return igraphmodule_real_t_to_PyObject(girth, IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT); } /** diff --git a/vendor/source/igraph b/vendor/source/igraph index 4d2a03c30..0f0db77be 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 4d2a03c30d303f6e6b9a64c7bf0c334b856c3c8c +Subproject commit 0f0db77be002ab6ce5e6aa993a075e4e9398ceed From ed2be69d1d948c78982ea00358a047e28584d475 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Aug 2022 14:40:15 +0200 Subject: [PATCH 1013/1892] fix: rmeove occurrence of power method from C glue code as well, refs #558 --- src/_igraph/graphobject.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 833cf72ec..0c15de70d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14131,14 +14131,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " implementation in igraph 0.7\n\n" " - C{\"arpack\"}: use the ARPACK library. This implementation\n" " was used from version 0.5, until version 0.7.\n\n" - " - C{\"power\"}: use a simple power method. This is the\n" - " implementation that was used before igraph version 0.5.\n\n" - "@param niter: The number of iterations to use in the power method\n" - " implementation. It is ignored in the other implementations.\n" - "@param eps: The power method implementation will consider the\n" - " calculation as complete if the difference of PageRank values between\n" - " iterations change less than this value for every node. It is \n" - " ignored by the other implementations.\n" + "@param niter: unused, kept for sake of backwards compatibility. It will\n" + " be removed in igraph 0.10.\n" + "@param eps: unused, kept for sake of backwards compatibility. It will\n" + " be removed in igraph 0.10.\n" "@return: a list with the personalized PageRank values of the specified\n" " vertices.\n"}, From b4fb8accb008155b513543290e41a25acc1dce76 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 Aug 2022 17:17:55 +0200 Subject: [PATCH 1014/1892] fix: remove niter and eps arguments from Graph.personalized_pagerank() --- src/_igraph/graphobject.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index ddd547551..caa5d0d36 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5480,7 +5480,7 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel { static char *kwlist[] = { "vertices", "directed", "damping", "reset", "reset_vertices", "weights", - "arpack_options", "implementation", "niter", "eps", NULL }; + "arpack_options", "implementation", NULL }; PyObject *directed = Py_True; PyObject *vobj = Py_None, *wobj = Py_None, *robj = Py_None, *rvsobj = Py_None; PyObject *list; @@ -5494,22 +5494,18 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel igraph_vs_t vs, reset_vs; igraph_pagerank_algo_t algo=IGRAPH_PAGERANK_ALGO_PRPACK; PyObject *algo_o = Py_None; - Py_ssize_t niter = 1000; - float eps=0.001f; void *opts; igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!Onf", kwlist, &vobj, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOOOO!O", kwlist, &vobj, &directed, &damping, &robj, &rvsobj, &wobj, igraphmodule_ARPACKOptionsType, - &arpack_options_o, &algo_o, &niter, &eps)) + &arpack_options_o, &algo_o)) return NULL; - CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); - if (robj != Py_None && rvsobj != Py_None) { PyErr_SetString(PyExc_ValueError, "only reset or reset_vs can be defined, not both"); return NULL; From eb2b49c23cc1935e9d20578e91f6ae705b83cdec Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 13 Aug 2022 11:58:00 +0200 Subject: [PATCH 1015/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 0f0db77be..8d84c9f3a 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 0f0db77be002ab6ce5e6aa993a075e4e9398ceed +Subproject commit 8d84c9f3a9f7526adc46520215b67a219a008f1e From 4f5cad4646bbdfcfceafc053fd7fa5b934dd6f4e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 13 Aug 2022 19:14:10 +0200 Subject: [PATCH 1016/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index fbb4ff098..d15e21eda 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit fbb4ff098960aeee6180277dad8bf1979f026ce5 +Subproject commit d15e21eda4decdbd43a4c01c19b28d0188c8ad7f From dc805a7f2444b6a6ba84f063aa9654fb08b26c03 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 14 Aug 2022 14:45:50 +0200 Subject: [PATCH 1017/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index d15e21eda..04b9fd82f 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit d15e21eda4decdbd43a4c01c19b28d0188c8ad7f +Subproject commit 04b9fd82f56960c3c2760f10ab292dd8db86f89b From fb46ae36fa7a978c4c6ac1fbf1cb95f566147ab6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 14 Aug 2022 14:52:06 +0200 Subject: [PATCH 1018/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 8d84c9f3a..9bb1eaa78 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 8d84c9f3a9f7526adc46520215b67a219a008f1e +Subproject commit 9bb1eaa78c6151c5a74cdcbfcd91a7d35df2dcf0 From 0cc31e9809933212698f9fb6e503585c069a04ad Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 14 Aug 2022 16:39:49 +0200 Subject: [PATCH 1019/1892] fix: fix conversion from igraph_real_t to PyObject when integers are needed but igraph_integer_t is 32-bit --- src/_igraph/convert.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 1b6120806..405060de0 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1373,19 +1373,19 @@ PyObject* igraphmodule_integer_t_to_PyObject(igraph_integer_t value) { * error occurred */ PyObject* igraphmodule_real_t_to_PyObject(igraph_real_t value, igraphmodule_conv_t type) { - if (!igraph_finite(value)) { + if (!igraph_finite(value) || igraph_is_nan(value)) { return PyFloat_FromDouble(value); } if (type == IGRAPHMODULE_TYPE_INT) { - return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); + return PyLong_FromDouble(value); } else if (type == IGRAPHMODULE_TYPE_FLOAT) { return PyFloat_FromDouble(value); } else if (type == IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT) { - if (!isfinite(value) || isnan(value) || ceil(value) != value) { + if (ceil(value) != value) { return PyFloat_FromDouble(value); } else { - return igraphmodule_integer_t_to_PyObject((igraph_integer_t)value); + return PyLong_FromDouble(value); } } else { Py_RETURN_NONE; From 7f028d68b11341d1936bb51df297a8613189d9ed Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 14 Aug 2022 16:40:09 +0200 Subject: [PATCH 1020/1892] fix: follow up changed types in igraph_dyad_census() --- src/_igraph/graphobject.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index caa5d0d36..17afba88e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6480,13 +6480,32 @@ PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, * \sa igraph_dyad_census */ PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { - igraph_integer_t mut, asym, nul; + igraph_real_t mut, asym, nul; + PyObject *mut_o, *asym_o, *nul_o; if (igraph_dyad_census(&self->g, &mut, &asym, &nul)) { return igraphmodule_handle_igraph_error(); } - return Py_BuildValue("nnn", (Py_ssize_t)mut, (Py_ssize_t)asym, (Py_ssize_t)nul); + mut_o = igraphmodule_real_t_to_PyObject(mut, IGRAPHMODULE_TYPE_INT); + if (!mut_o) { + return NULL; + } + + asym_o = igraphmodule_real_t_to_PyObject(asym, IGRAPHMODULE_TYPE_INT); + if (!asym_o) { + Py_DECREF(mut_o); + return NULL; + } + + nul_o = igraphmodule_real_t_to_PyObject(nul, IGRAPHMODULE_TYPE_INT); + if (!nul_o) { + Py_DECREF(mut_o); + Py_DECREF(asym_o); + return NULL; + } + + return Py_BuildValue("NNN", mut_o, asym_o, nul_o); } typedef struct { From 4b4c3fea633fb2958a531c95836e388fb5fe41df Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Aug 2022 13:40:47 +0200 Subject: [PATCH 1021/1892] chore: bumped vendored igraph to 0.10.0-rc.2 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 9bb1eaa78..2b1ad04b0 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 9bb1eaa78c6151c5a74cdcbfcd91a7d35df2dcf0 +Subproject commit 2b1ad04b0a5982a22bde933183b8a485b7083a06 From 29aea1b5fab850f76b826b61041cdd0acc962815 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Aug 2022 15:47:45 +0200 Subject: [PATCH 1022/1892] feat: added Graph.list_triangles() --- src/_igraph/convert.c | 67 +++++++++++++++++++------------------- src/_igraph/convert.h | 3 +- src/_igraph/graphobject.c | 39 ++++++++++++++++++---- test.sh | 4 +-- tests/test_cliques.py | 38 ++-------------------- tests/test_motifs.py | 68 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 77 deletions(-) create mode 100644 tests/test_motifs.py diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 405060de0..5bc77a65d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1602,55 +1602,56 @@ PyObject* igraphmodule_vector_int_t_to_PyTuple(const igraph_vector_int_t *v) { /** * \ingroup python_interface_conversion - * \brief Converts an igraph \c igraph_vector_int_t to a Python list of integer pairs + * \brief Converts an igraph \c igraph_vector_int_t to a Python list of fixed-length tuples * * \param v the \c igraph_vector_t containing the vector to be converted * \return the Python integer pair list as a \c PyObject*, or \c NULL if an error occurred */ -PyObject* igraphmodule_vector_int_t_to_PyList_pairs(const igraph_vector_int_t *v) { - PyObject *list, *pair, *first, *second; - Py_ssize_t n, i, j; +PyObject* igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples( + const igraph_vector_int_t *v, Py_ssize_t tuple_len +) { + PyObject *list, *tuple, *item; + Py_ssize_t n, i, j, k; + + if (tuple_len < 1) { + PyErr_SetString(PyExc_SystemError, + "invalid invocation of igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(), " + "tuple length must be positive" + ); + } n = igraph_vector_int_size(v); - if (n < 0 || n % 2 != 0) { - return igraphmodule_handle_igraph_error(); + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "igraph vector has negative length"); + return NULL; + } + if (n % tuple_len != 0) { + PyErr_Format(PyExc_ValueError, "igraph vector length must be divisible by %zd", tuple_len); + return NULL; } /* create a new Python list */ - n >>= 1; + n /= tuple_len; list = PyList_New(n); if (!list) { return NULL; } /* populate the list with data */ - for (i = 0, j = 0; i < n; i++, j += 2) { - first = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[j]); - if (!first) { - Py_DECREF(list); - return NULL; - } - - second = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[j + 1]); - if (!second) { - Py_DECREF(first); - Py_DECREF(list); - return NULL; - } - - pair = PyTuple_Pack(2, first, second); - if (pair == NULL) { - Py_DECREF(second); - Py_DECREF(first); - Py_DECREF(list); - return NULL; + for (i = 0, k = 0; i < n; i++) { + tuple = PyTuple_New(tuple_len); + for (j = 0; j < tuple_len; k++, j++) { + item = igraphmodule_integer_t_to_PyObject(VECTOR(*v)[k]); + if (!item) { + Py_DECREF(tuple); + Py_DECREF(list); + return NULL; + } + PyTuple_SetItem(tuple, j, item); /* will not fail */ + /* reference to 'item' is now owned by 'tuple' */ } - - Py_DECREF(first); - Py_DECREF(second); - first = second = 0; - - PyList_SetItem(list, i, pair); /* will not fail */ + PyList_SetItem(list, i, tuple); /* will not fail */ + /* reference to 'tuple' is now owned by 'list' */ } return list; diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index a56e2e0df..f24eaf517 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -159,7 +159,8 @@ PyObject* igraphmodule_vector_t_to_PyTuple(const igraph_vector_t *v, igraphmodu PyObject* igraphmodule_vector_int_t_to_PyTuple(const igraph_vector_int_t *v); PyObject* igraphmodule_vector_int_t_pair_to_PyList(const igraph_vector_int_t *v1, const igraph_vector_int_t *v2); -PyObject* igraphmodule_vector_int_t_to_PyList_pairs(const igraph_vector_int_t *v); +PyObject* igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples( + const igraph_vector_int_t *v, Py_ssize_t tuple_len); PyObject* igraphmodule_vector_int_t_to_PyList_with_nan(const igraph_vector_int_t *v, const igraph_integer_t nanvalue); PyObject* igraphmodule_vector_ptr_t_to_PyList(const igraph_vector_ptr_t *v, igraphmodule_conv_t type); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 17afba88e..e1ba260ca 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4260,7 +4260,7 @@ PyObject *igraphmodule_Graph_chordal_completion( igraph_vector_int_destroy(alpham1_ptr); } - res_o = igraphmodule_vector_int_t_to_PyList_pairs(&edges); + res_o = igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(&edges, 2); igraph_vector_int_destroy(&edges); return res_o; @@ -6471,7 +6471,7 @@ PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, } /********************************************************************** - * Motifs, dyad and triad census * + * Motifs, triangles, dyad and triad census * **********************************************************************/ /** \ingroup python_interface_graph @@ -6508,6 +6508,26 @@ PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { return Py_BuildValue("NNN", mut_o, asym_o, nul_o); } +/** \ingroup python_interface_graph + * \brief Lists the triangles of the graph + * \return the triangles of the graph as a list of triplets with vertex IDs + * \sa igraph_list_triangles + */ +PyObject *igraphmodule_Graph_list_triangles(igraphmodule_GraphObject *self) { + igraph_vector_int_t res; + + if (igraph_vector_int_init(&res, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_list_triangles(&self->g, &res)) { + return igraphmodule_handle_igraph_error(); + } + + return igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(&res, 3); +} + typedef struct { PyObject* func; PyObject* graph; @@ -8098,7 +8118,7 @@ PyObject *igraphmodule_Graph_get_edgelist(igraphmodule_GraphObject * self, return NULL; } - result_o = igraphmodule_vector_int_t_to_PyList_pairs(&edgelist); + result_o = igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(&edgelist, 2); igraph_vector_int_destroy(&edgelist); return (PyObject *) result_o; @@ -14752,9 +14772,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " if C{pairs} is not C{None}.\n" }, - /******************/ - /* MOTIF COUNTING */ - /******************/ + /*****************************/ + /* MOTIF COUNTING, TRIANGLES */ + /*****************************/ {"motifs_randesu", (PyCFunction) igraphmodule_Graph_motifs_randesu, METH_VARARGS | METH_KEYWORDS, "motifs_randesu(size=3, cut_prob=None, callback=None)\n--\n\n" @@ -14853,6 +14873,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " It is advised to use that. The name of the triplet classes are\n" " also documented there.\n\n" }, + {"list_triangles", (PyCFunction) igraphmodule_Graph_list_triangles, + METH_NOARGS, + "list_triangles()\n--\n\n" + "Lists the triangles of the graph\n\n" + "@return: the list of triangles in the graph; each triangle is represented\n" + " by a tuple of length 3, containing the corresponding vertex IDs." + }, /********************/ /* LAYOUT FUNCTIONS */ diff --git a/test.sh b/test.sh index 49fb2ad10..215dd5e97 100755 --- a/test.sh +++ b/test.sh @@ -10,7 +10,6 @@ CLEAN=0 VENV_DIR=.venv while getopts ":ce:k:" OPTION; do - echo "$OPTION" case $OPTION in c) CLEAN=1 @@ -22,7 +21,8 @@ while getopts ":ce:k:" OPTION; do PYTEST_ARGS="${PYTEST_ARGS} -k $OPTARG" ;; \?) - echo "Usage: $0 [-c]" + echo "Usage: $0 [-c] [-e VIRTUALENV]" + exit 1 ;; esac done diff --git a/tests/test_cliques.py b/tests/test_cliques.py index bb36832de..573bd6181 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -158,37 +158,6 @@ def testIndependenceNumber(self): self.assertEqual(self.g2.alpha(), 6) -class MotifTests(unittest.TestCase): - def setUp(self): - self.g = Graph.Erdos_Renyi(100, 0.2, directed=True) - - def testDyads(self): - # @note: this test is not exhaustive, it only checks whether the - # L{DyadCensus} objects "understand" attribute and item accessors - dc = self.g.dyad_census() - accessors = ["mut", "mutual", "asym", "asymm", "asymmetric", "null"] - for a in accessors: - self.assertTrue(isinstance(getattr(dc, a), int)) - self.assertTrue(isinstance(dc[a], int)) - self.assertTrue(isinstance(list(dc), list)) - self.assertTrue(isinstance(tuple(dc), tuple)) - self.assertTrue(len(list(dc)) == 3) - self.assertTrue(len(tuple(dc)) == 3) - - def testTriads(self): - # @note: this test is not exhaustive, it only checks whether the - # L{TriadCensus} objects "understand" attribute and item accessors - tc = self.g.triad_census() - accessors = ["003", "012", "021d", "030C"] - for a in accessors: - self.assertTrue(isinstance(getattr(tc, "t" + a), int)) - self.assertTrue(isinstance(tc[a], int)) - self.assertTrue(isinstance(list(tc), list)) - self.assertTrue(isinstance(tuple(tc), tuple)) - self.assertTrue(len(list(tc)) == 16) - self.assertTrue(len(tuple(tc)) == 16) - - class CliqueBenchmark: """This is a benchmark, not a real test case. You can run it using: @@ -219,7 +188,7 @@ def printIntro(self): def timeit(self, g): start = self.time() - omega = g.clique_number() + g.clique_number() mid = self.time() cl = g.maximal_cliques() end = self.time() @@ -252,7 +221,7 @@ def testMoonMoser(self): print("Moon-Moser graphs") print(" n exp_clqs #cliques t1 t2") for n in ns: - n3 = n / 3 + n3 = n // 3 types = list(range(n3)) * 3 el = [ (i, j) @@ -282,8 +251,7 @@ def testGRG(self): def suite(): clique_suite = unittest.makeSuite(CliqueTests) indvset_suite = unittest.makeSuite(IndependentVertexSetTests) - motif_suite = unittest.makeSuite(MotifTests) - return unittest.TestSuite([clique_suite, indvset_suite, motif_suite]) + return unittest.TestSuite([clique_suite, indvset_suite]) def test(): diff --git a/tests/test_motifs.py b/tests/test_motifs.py new file mode 100644 index 000000000..f19e96b4c --- /dev/null +++ b/tests/test_motifs.py @@ -0,0 +1,68 @@ +import unittest + +from igraph import Graph + + +class MotifTests(unittest.TestCase): + def setUp(self): + self.g = Graph.Erdos_Renyi(100, 0.2, directed=True) + + def testDyads(self): + # @note: this test is not exhaustive, it only checks whether the + # L{DyadCensus} objects "understand" attribute and item accessors + dc = self.g.dyad_census() + accessors = ["mut", "mutual", "asym", "asymm", "asymmetric", "null"] + for a in accessors: + self.assertTrue(isinstance(getattr(dc, a), int)) + self.assertTrue(isinstance(dc[a], int)) + self.assertTrue(isinstance(list(dc), list)) + self.assertTrue(isinstance(tuple(dc), tuple)) + self.assertTrue(len(list(dc)) == 3) + self.assertTrue(len(tuple(dc)) == 3) + + def testTriads(self): + # @note: this test is not exhaustive, it only checks whether the + # L{TriadCensus} objects "understand" attribute and item accessors + tc = self.g.triad_census() + accessors = ["003", "012", "021d", "030C"] + for a in accessors: + self.assertTrue(isinstance(getattr(tc, "t" + a), int)) + self.assertTrue(isinstance(tc[a], int)) + self.assertTrue(isinstance(list(tc), list)) + self.assertTrue(isinstance(tuple(tc), tuple)) + self.assertTrue(len(list(tc)) == 16) + self.assertTrue(len(tuple(tc)) == 16) + + +class TrianglesTests(unittest.TestCase): + def testListTriangles(self): + g = Graph.Famous("petersen") + self.assertEqual([], g.list_triangles()) + + g = Graph([(0, 1), (1, 2), (2, 0), (1, 3), (3, 2), (4, 2), (4, 3)]) + observed = g.list_triangles() + self.assertTrue(all(isinstance(x, tuple) for x in observed)) + observed = sorted(sorted(tri) for tri in observed) + expected = [[0, 1, 2], [1, 2, 3], [2, 3, 4]] + self.assertEqual(observed, expected) + + g = Graph.GRG(100, 0.2) + tri = Graph.Full(3) + observed = sorted(sorted(tri) for tri in g.list_triangles()) + expected = sorted(x for x in g.get_subisomorphisms_vf2(tri) if x == sorted(x)) + self.assertEqual(observed, expected) + + +def suite(): + motif_suite = unittest.makeSuite(MotifTests) + triangles_suite = unittest.makeSuite(TrianglesTests) + return unittest.TestSuite([motif_suite, triangles_suite]) + + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + + +if __name__ == "__main__": + test() From f9a718c80c8c871259ab78d026a47112027e3c54 Mon Sep 17 00:00:00 2001 From: flange-ipb <34936695+flange-ipb@users.noreply.github.com> Date: Wed, 17 Aug 2022 15:49:03 +0200 Subject: [PATCH 1023/1892] invoke Emscripten's emcmake when cross-compiling to wasm --- setup.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/setup.py b/setup.py index 7cfe397c0..e34bfa72b 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,11 @@ def building_on_windows_msvc() -> bool: return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" +def building_to_wasm() -> bool: + """Returns True when building to WebAssembly""" + return "PYODIDE" in os.environ + + def exclude_from_list(items: Iterable[T], items_to_exclude: Iterable[T]) -> List[T]: """Excludes certain items from a list, keeping the original order of the remaining items.""" @@ -229,6 +234,18 @@ def _compile_in( print("Configuring build...") args = [cmake] + # Build to wasm requires invocation of the Emscripten SDK + if building_to_wasm(): + emcmake = which("emcmake") + if not emcmake: + print( + "You need to install emcmake from the Emscripten SDK before " + "compiling igraph." + ) + return False + args.insert(0, emcmake) + args.append("-DIGRAPH_WARNINGS_AS_ERRORS:BOOL=OFF") + # Build the Python interface with vendored libraries for deps in "ARPACK BLAS GLPK GMP LAPACK".split(): args.append("-DIGRAPH_USE_INTERNAL_" + deps + "=ON") From 6267d2e1359f1bd8a3da9d225440c47c5740ab1c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 17 Aug 2022 16:31:07 +0200 Subject: [PATCH 1024/1892] feat: Graph.Lattice() now supports per-dimension periodicity control --- src/_igraph/graphobject.c | 33 +++++++-- tests/test_generators.py | 148 +++++++++++++++++++++++++++++++++----- 2 files changed, 157 insertions(+), 24 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e1ba260ca..79d926c02 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2745,10 +2745,10 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, PyObject * args, PyObject * kwds) { igraph_vector_int_t dimvector; + igraph_vector_bool_t circular; Py_ssize_t nei = 1; igraph_bool_t directed; igraph_bool_t mutual; - igraph_bool_t circular; PyObject *o_directed = Py_False, *o_mutual = Py_True, *o_circular = Py_True; PyObject *o_dimvector = Py_None; igraphmodule_GraphObject *self; @@ -2763,19 +2763,35 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, directed = PyObject_IsTrue(o_directed); mutual = PyObject_IsTrue(o_mutual); - circular = PyObject_IsTrue(o_circular); if (igraphmodule_PyObject_to_vector_int_t(o_dimvector, &dimvector)) return NULL; + if (PyBool_Check(o_circular) || PyNumber_Check(o_circular) || PyBaseString_Check(o_circular)) { + if (igraph_vector_bool_init(&circular, igraph_vector_int_size(&dimvector))) { + igraph_vector_int_destroy(&dimvector); + igraphmodule_handle_igraph_error(); + return NULL; + } + + igraph_vector_bool_fill(&circular, PyObject_IsTrue(o_circular)); + } else { + if (igraphmodule_PyObject_to_vector_bool_t(o_circular, &circular)) { + igraph_vector_int_destroy(&dimvector); + return NULL; + } + } + CHECK_SSIZE_T_RANGE_POSITIVE(nei, "number of neighbors"); - if (igraph_lattice(&g, &dimvector, nei, directed, mutual, circular)) { + if (igraph_square_lattice(&g, &dimvector, nei, directed, mutual, &circular)) { igraphmodule_handle_igraph_error(); + igraph_vector_bool_destroy(&circular); igraph_vector_int_destroy(&dimvector); return NULL; } + igraph_vector_bool_destroy(&circular); igraph_vector_int_destroy(&dimvector); CREATE_GRAPH_FROM_TYPE(self, g, type); @@ -6515,6 +6531,7 @@ PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { */ PyObject *igraphmodule_Graph_list_triangles(igraphmodule_GraphObject *self) { igraph_vector_int_t res; + PyObject *res_o; if (igraph_vector_int_init(&res, 0)) { igraphmodule_handle_igraph_error(); @@ -6525,7 +6542,11 @@ PyObject *igraphmodule_Graph_list_triangles(igraphmodule_GraphObject *self) { return igraphmodule_handle_igraph_error(); } - return igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(&res, 3); + res_o = igraphmodule_vector_int_t_to_PyList_of_fixed_length_tuples(&res, 3); + + igraph_vector_int_destroy(&res); + + return res_o; } typedef struct { @@ -13183,7 +13204,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param directed: whether to create a directed graph.\n" "@param mutual: whether to create all connections as mutual\n" " in case of a directed graph.\n" - "@param circular: whether the generated lattice is periodic.\n"}, + "@param circular: whether the generated lattice is periodic. May also be an\n" + " iterable; in this case, the iterator is assumed to yield booleans that\n" + " specify whether the lattice is periodic along each dimension.\n"}, /* interface to igraph_lcf */ {"LCF", (PyCFunction) igraphmodule_Graph_LCF, diff --git a/tests/test_generators.py b/tests/test_generators.py index 5583e5031..fe79b738f 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -138,31 +138,47 @@ def testLCF(self): def testRealizeDegreeSequence(self): # Test case insensitivity of options too g = Graph.Realize_Degree_Sequence( - [1, 1], None, "simPLE", "smallest", + [1, 1], + None, + "simPLE", + "smallest", ) self.assertFalse(g.is_directed()) self.assertTrue(g.degree() == [1, 1]) # Not implemented, should fail self.assertRaises( - NotImplementedError, Graph.Realize_Degree_Sequence, - [1, 1], None, "loops", "largest" + NotImplementedError, + Graph.Realize_Degree_Sequence, + [1, 1], + None, + "loops", + "largest", ) g = Graph.Realize_Degree_Sequence( - [1, 1], None, "all", "largest", + [1, 1], + None, + "all", + "largest", ) self.assertFalse(g.is_directed()) self.assertTrue(g.degree() == [1, 1]) g = Graph.Realize_Degree_Sequence( - [1, 1], None, "multi", "index", + [1, 1], + None, + "multi", + "index", ) self.assertFalse(g.is_directed()) self.assertTrue(g.degree() == [1, 1]) g = Graph.Realize_Degree_Sequence( - [1, 1], [1, 1], "simple", "largest", + [1, 1], + [1, 1], + "simple", + "largest", ) self.assertTrue(g.is_directed()) self.assertTrue(g.indegree() == [1, 1]) @@ -170,17 +186,29 @@ def testRealizeDegreeSequence(self): # Not implemented, should fail self.assertRaises( - NotImplementedError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "multi", "largest" + NotImplementedError, + Graph.Realize_Degree_Sequence, + [1, 1], + [1, 1], + "multi", + "largest", ) self.assertRaises( - ValueError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "should_fail", "index" + ValueError, + Graph.Realize_Degree_Sequence, + [1, 1], + [1, 1], + "should_fail", + "index", ) self.assertRaises( - ValueError, Graph.Realize_Degree_Sequence, - [1, 1], [1, 1], "multi", "should_fail" + ValueError, + Graph.Realize_Degree_Sequence, + [1, 1], + [1, 1], + "multi", + "should_fail", ) # Degree sequence of Zachary karate club, using optional arguments @@ -204,6 +232,90 @@ def testDeBruijn(self): # This is not a proper test, but should spot most errors self.assertTrue(g.is_directed() and deg_in == [2] * 8 and deg_out == [2] * 8) + def testLattice(self): + g = Graph.Lattice([4, 3], circular=False) + self.assertEqual( + sorted(sorted(x) for x in g.get_edgelist()), + [ + [0, 1], + [0, 4], + [1, 2], + [1, 5], + [2, 3], + [2, 6], + [3, 7], + [4, 5], + [4, 8], + [5, 6], + [5, 9], + [6, 7], + [6, 10], + [7, 11], + [8, 9], + [9, 10], + [10, 11], + ], + ) + + g = Graph.Lattice([4, 3], circular=True) + self.assertEqual( + sorted(sorted(x) for x in g.get_edgelist()), + [ + [0, 1], + [0, 3], + [0, 4], + [0, 8], + [1, 2], + [1, 5], + [1, 9], + [2, 3], + [2, 6], + [2, 10], + [3, 7], + [3, 11], + [4, 5], + [4, 7], + [4, 8], + [5, 6], + [5, 9], + [6, 7], + [6, 10], + [7, 11], + [8, 9], + [8, 11], + [9, 10], + [10, 11], + ], + ) + + g = Graph.Lattice([4, 3], circular=(False, 1)) + self.assertEqual( + sorted(sorted(x) for x in g.get_edgelist()), + [ + [0, 1], + [0, 4], + [0, 8], + [1, 2], + [1, 5], + [1, 9], + [2, 3], + [2, 6], + [2, 10], + [3, 7], + [3, 11], + [4, 5], + [4, 8], + [5, 6], + [5, 9], + [6, 7], + [6, 10], + [7, 11], + [8, 9], + [9, 10], + [10, 11], + ], + ) + def testSBM(self): pref_matrix = [[0.5, 0, 0], [0, 0, 0.5], [0, 0.5, 0]] n = 60 @@ -380,12 +492,7 @@ def testDataFrame(self): vertices = pd.DataFrame( {"node": [1, 2, 3, 4, 5, 6], "label": ["1", "2", "3", "4", "5", "6"]} )[["node", "label"]] - g = Graph.DataFrame( - edges, - directed=True, - vertices=vertices, - use_vids=False - ) + g = Graph.DataFrame(edges, directed=True, vertices=vertices, use_vids=False) self.assertTrue(g.vs["name"] == [1, 2, 3, 4, 5, 6]) self.assertTrue(g.vs["label"] == ["1", "2", "3", "4", "5", "6"]) @@ -437,7 +544,10 @@ def testDataFrame(self): Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(TypeError, "integers"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) - vertices = pd.DataFrame({0: [1, 2, 3]}, index=pd.MultiIndex.from_tuples([(1, 1), (2, 2), (3, 3)])) + vertices = pd.DataFrame( + {0: [1, 2, 3]}, + index=pd.MultiIndex.from_tuples([(1, 1), (2, 2), (3, 3)]), + ) Graph.DataFrame(edges, vertices=vertices) with self.assertRaisesRegex(ValueError, "unique"): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) From e6536766e7a8b0dbaa8eff9f3dab907f7d1599b0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 18 Aug 2022 20:53:31 +0200 Subject: [PATCH 1025/1892] fix: make tests work again when matplotlib is not installed --- src/igraph/drawing/shapes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 79a274043..d4ca9fc49 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -94,7 +94,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): or filling it. @see: ShapeDrawer.draw_path""" height = height or width - if isinstance(ctx, plt.Axes): + if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Rectangle( (center_x - width / 2, center_y - height / 2), width, height, **kwargs ) @@ -162,7 +162,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): Height is ignored, it is the width that determines the diameter of the circle. @see: ShapeDrawer.draw_path""" - if isinstance(ctx, plt.Axes): + if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Circle((center_x, center_y), width / 2, **kwargs) else: ctx.arc(center_x, center_y, width / 2, 0, 2 * pi) @@ -191,7 +191,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): @see: ShapeDrawer.draw_path""" height = height or width - if isinstance(ctx, plt.Axes): + if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): vertices = [ [center_x - 0.5 * width, center_y - 0.333 * height], [center_x + 0.5 * width, center_y - 0.333 * height], @@ -228,7 +228,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): @see: ShapeDrawer.draw_path""" height = height or width - if isinstance(ctx, plt.Axes): + if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): vertices = [ [center_x - 0.5 * width, center_y + 0.333 * height], [center_x + 0.5 * width, center_y + 0.333 * height], @@ -266,7 +266,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): @see: ShapeDrawer.draw_path""" height = height or width - if isinstance(ctx, plt.Axes): + if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): vertices = [ [center_x - 0.5 * width, center_y], [center_x, center_y - 0.5 * height], From 9dd5fceb453c3476858daaa685ae7d03398f3ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 24 Aug 2022 15:58:46 +0200 Subject: [PATCH 1026/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 04b9fd82f..7107c2f3d 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 04b9fd82f56960c3c2760f10ab292dd8db86f89b +Subproject commit 7107c2f3d89d550d332f4b550d953b9546be3256 From ec42454bdf40d88237c0b5f338d1dcb2c8899837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 24 Aug 2022 16:00:51 +0200 Subject: [PATCH 1027/1892] chore: bumped vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 2b1ad04b0..67f4f1514 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2b1ad04b0a5982a22bde933183b8a485b7083a06 +Subproject commit 67f4f15143992e6736a3ee317dfc773460a08caf From e3275c4f9ce78bab08bc66b7614e47318ce56a2a Mon Sep 17 00:00:00 2001 From: flange-ipb <34936695+flange-ipb@users.noreply.github.com> Date: Mon, 29 Aug 2022 13:02:37 +0200 Subject: [PATCH 1028/1892] add workflow to build a WASM wheel --- .github/workflows/build.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c56fa0085..48aa932fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -150,6 +150,34 @@ jobs: with: path: ./wheelhouse/*.whl + build_wheel_wasm: + name: Build wheels for WebAssembly + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.10.2' + + - uses: mymindstorm/setup-emsdk@v11 + with: + version: '3.1.14' + + - name: Build wheel + run: | + pip install pyodide-build==0.21.0 + pyodide build + + - uses: actions/upload-artifact@v2 + with: + path: ./dist/*.whl + build_wheel_win: name: Build wheels on Windows (${{ matrix.cmake_arch }}) runs-on: windows-2019 From a28f7dc8696e7fd272035f7d44491e2b97808e33 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Sep 2022 12:16:43 +0200 Subject: [PATCH 1029/1892] chore: updated vendored igraph, added ierative scheme to community_leiden --- src/_igraph/graphobject.c | 5 ++++- vendor/source/igraph | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 79d926c02..9ea452fae 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -16718,7 +16718,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " will try to improve this provided membership. If no argument is\n" " provided, the aglorithm simply starts from the singleton partition.\n" "@param n_iterations: the number of iterations to iterate the Leiden\n" - " algorithm. Each iteration may improve the partition further.\n" + " algorithm. Each iteration may improve the partition further. You can\n" + " also set this parameter to a negative number, which means that the\n" + " algorithm will be iterated until an iteration does not change the\n" + " current membership vector any more.\n" "@return: the community membership vector.\n" }, {"community_walktrap", diff --git a/vendor/source/igraph b/vendor/source/igraph index 67f4f1514..540d5009e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 67f4f15143992e6736a3ee317dfc773460a08caf +Subproject commit 540d5009ed2e0341f95c678c98947df2d8e7144a From 4df9a09c8dcffb4a8712d0c8dd0637351af4aaaa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Sep 2022 13:21:40 +0200 Subject: [PATCH 1030/1892] fix: iterative scheme of the Leiden algorithm is now handled in igraph_community_leiden() --- src/_igraph/graphobject.c | 25 +++++-------------------- tests/test_decomposition.py | 1 + 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9ea452fae..5d71ab3fc 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12313,26 +12313,11 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, /* Run actual Leiden algorithm for several iterations. */ if (!error) { - if (n_iterations >= 0) { - for (i = 0; !error && i < n_iterations; i++) { - error = igraph_community_leiden(&self->g, - edge_weights, node_weights, - resolution_parameter, beta, - start, membership, - &nb_clusters, &quality); - start = 1; - } - } else { - while (!error && prev_quality < quality) { - prev_quality = quality; - error = igraph_community_leiden(&self->g, - edge_weights, node_weights, - resolution_parameter, beta, - start, membership, - &nb_clusters, &quality); - start = 1; - } - } + error = igraph_community_leiden(&self->g, + edge_weights, node_weights, + resolution_parameter, beta, + start, n_iterations, membership, + &nb_clusters, &quality); } if (edge_weights != 0) { diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index fb130cd2b..f2b37dfc4 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -301,6 +301,7 @@ def testLabelPropagation(self): def testMultilevel(self): # Example graph from the paper + random.seed(42) g = Graph(16) g += [ (0, 2), From 33bde29fc92d8710802aa618e732a0a8b26dc52a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 14:44:54 +0200 Subject: [PATCH 1031/1892] chore: updated vendored igraph to 0.10.0 --- src/_igraph/graphobject.c | 4 ++-- src/_igraph/pyhelpers.c | 2 ++ vendor/source/igraph | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 5d71ab3fc..8119f6e68 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12238,7 +12238,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, PyObject *normalize_resolution = Py_False; PyObject *res = Py_None; - int error = 0, i; + int error = 0; Py_ssize_t n_iterations = 2; double resolution_parameter = 1.0; double beta = 0.01; @@ -12246,7 +12246,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, igraph_vector_int_t *membership = NULL; igraph_bool_t start = 1; igraph_integer_t nb_clusters = 0; - igraph_real_t quality = 0.0, prev_quality = -IGRAPH_INFINITY; + igraph_real_t quality = 0.0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOdOn", kwlist, &edge_weights_o, &node_weights_o, &resolution_parameter, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) diff --git a/src/_igraph/pyhelpers.c b/src/_igraph/pyhelpers.c index af961c0c1..98bd09e40 100644 --- a/src/_igraph/pyhelpers.c +++ b/src/_igraph/pyhelpers.c @@ -271,7 +271,9 @@ int igraphmodule_helpers_init() { called = 1; success = 1; +#if defined(PY_IGRAPH_PROVIDES_PY_NONE) || defined(PY_IGRAPH_PROVIDES_BOOL_CONSTANTS) cleanup: +#endif if (!success) { #ifdef PY_IGRAPH_PROVIDES_PY_NONE Py_XDECREF(Py_None); diff --git a/vendor/source/igraph b/vendor/source/igraph index 540d5009e..83714d331 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 540d5009ed2e0341f95c678c98947df2d8e7144a +Subproject commit 83714d331f5f279eb4a5aa11be054a1710e220c4 From d54ae8f8d2b2e8fe6bdee7f1133a43591d86c52d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 17:00:22 +0200 Subject: [PATCH 1032/1892] chore: consolidated changelog [ci skip] --- CHANGELOG.md | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a956ce49..bae718dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Development branch] +## [Unreleased] ### Added @@ -13,6 +13,16 @@ data structures. See PR [#434](https://github.com/igraph/python-igraph/pull/434) for more details. +- `Graph.list_triangles()` lists all triangles in a graph. + +- `Graph.reverse_edges()` reverses some or all edges of a graph. + +- `Graph.Degree_Sequence()` now supports the `"no_multiple_uniform"` generation + method, which generates simple graphs, sampled uniformly, using rejection + sampling. + +- `Graph.Lattice()` now supports per-dimension periodicity control. + - `Graph.get_adjacency()` now allows the user to specify whether loop edges should be counted once or twice, or not at all. @@ -20,9 +30,19 @@ ### Changed +- The C core of igraph was updated to version 0.10.0. + - Changed default value of the `use_vids=...` argument of `Graph.DataFrame()` to `True`, thanks to [@fwitter](https://github.com/user/fwitter). +- `Graph.Degree_Sequence()` now accepts all sorts of sequences as inputs, not + only lists. + +### Fixed + +- The Matplotlib backend now allows `edge_color` and `edge_width` to be set + on an edge-by-edge basis. + ### Removed - Removed deprecated `UbiGraphDrawer`. @@ -39,32 +59,6 @@ - `Graph.shortest_paths()` is now deprecated; use `Graph.distances()` instead. -## [Unreleased] - -### Added - -- `Graph.reverse_edges()` reverses some or all edges of a graph. - -- `Graph.Degree_Sequence()` now supports the `"no_multiple_uniform"` generation - method, which generates simple graphs, sampled uniformly, using rejection - sampling. - -- `Graph.reverse_edges()` reverses some or all edges of a graph. - -### Changed - -- `Graph.Degree_Sequence()` now accepts all sorts of sequences as inputs, not - only lists. - -### Fixed - -- The Matplotlib backend now allows `edge_color` and `edge_width` to be set - on an edge-by-edge basis. - -### Deprecated - -- `Graph.clusters()` is now deprecated, use `Graph.components()` instead. - ## [0.9.11] ### Added @@ -351,7 +345,6 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Development branch]: https://github.com/igraph/python-igraph/compare/0.9.11..develop [Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.11..master [0.9.11]: https://github.com/igraph/python-igraph/compare/0.9.10...0.9.11 [0.9.10]: https://github.com/igraph/python-igraph/compare/0.9.9...0.9.10 From 6c5811cee0182ec0393a7afabb11c91355c8a8d1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 18:00:03 +0200 Subject: [PATCH 1033/1892] build: dropping support for Python 3.6, setting up proper tags for abi3 wheels --- .github/workflows/build.yml | 3 ++- CHANGELOG.md | 11 +++++++++-- README.md | 8 ++++---- pyproject.toml | 3 +++ setup.py | 21 +++++++++++++++++---- src/igraph/version.py | 2 +- tox.ini | 4 ++-- 7 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 pyproject.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c56fa0085..9b4707c27 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" + CIBW_SKIP: "cp36-*" MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: @@ -85,7 +86,7 @@ jobs: build_wheel_macos: name: Build wheels on macOS (${{ matrix.wheel_arch }}) - runs-on: macos-10.15 + runs-on: macos-latest env: LLVM_VERSION: "14.0.5" strategy: diff --git a/CHANGELOG.md b/CHANGELOG.md index bae718dcb..c0060fa2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.0] - 2022-09-05 ### Added @@ -32,6 +32,10 @@ - The C core of igraph was updated to version 0.10.0. +- We now publish `abi3` wheels on PyPI, making it possible to use an + already-built Python wheel with newer minor Python releases (and also + reducing the number of wheels we actually need to publish). + - Changed default value of the `use_vids=...` argument of `Graph.DataFrame()` to `True`, thanks to [@fwitter](https://github.com/user/fwitter). @@ -45,6 +49,8 @@ ### Removed +- Dropped support for Python 3.6. + - Removed deprecated `UbiGraphDrawer`. - Removed deprecated `show()` method of `Plot` instances as well as the feature @@ -345,7 +351,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.9.11..master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.0...master +[0.10.0]: https://github.com/igraph/python-igraph/compare/0.9.11...0.10.0 [0.9.11]: https://github.com/igraph/python-igraph/compare/0.9.10...0.9.11 [0.9.10]: https://github.com/igraph/python-igraph/compare/0.9.9...0.9.10 [0.9.9]: https://github.com/igraph/python-igraph/compare/0.9.8...0.9.9 diff --git a/README.md b/README.md index 1f2643bfb..cc1ac190e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) -[![PyPI pyversions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/igraph) +[![PyPI pyversions](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/igraph.svg)](https://pypi.python.org/pypi/igraph) Python interface for the igraph library @@ -49,8 +49,8 @@ automatically. ### Installation from source on Windows It is now also possible to compile `igraph` from source under Windows for -Python 3.6 and later. Make sure that you have Microsoft Visual Studio 2015 or -later installed, and of course Python 3.6 or later. First extract the source to +Python 3.7 and later. Make sure that you have Microsoft Visual Studio 2015 or +later installed, and of course Python 3.7 or later. First extract the source to a suitable directory. If you launch the Developer command prompt and navigate to the directory where you extracted the source code, you should be able to build and install igraph using `python setup.py install` @@ -235,7 +235,7 @@ faster than the first one as the C core does not need to be recompiled. We aim to keep up with the development cycle of Python and support all official Python versions that have not reached their end of life yet. Currently this -means that we support Python 3.6 to 3.9, inclusive. Please refer to [this +means that we support Python 3.7 to 3.10, inclusive. Please refer to [this page](https://devguide.python.org/#branchstatus) for the status of Python branches and let us know if you encounter problems with `igraph` on any of the non-EOL Python versions. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..9787c3bdf --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 7cfe397c0..5e0ad85cc 100644 --- a/setup.py +++ b/setup.py @@ -7,13 +7,14 @@ ########################################################################### # Check Python's version info and exit early if it is too old -if sys.version_info < (3, 6): - print("This module requires Python >= 3.6") +if sys.version_info < (3, 7): + print("This module requires Python >= 3.7") sys.exit(0) ########################################################################### from setuptools import find_packages, setup, Command, Extension +from wheel.bdist_wheel import bdist_wheel import glob import shlex @@ -777,6 +778,18 @@ def use_educated_guess(self) -> None: self.library_dirs = LIBIGRAPH_FALLBACK_LIBRARY_DIRS[:] +########################################################################### + +class bdist_wheel_abi3(bdist_wheel): + def get_tag(self): + python, abi, plat = super().get_tag() + if python.startswith("cp"): + # on CPython, our wheels are abi3 and compatible back to 3.7 + return "cp37", "abi3", plat + + return python, abi, plat + + ########################################################################### # Import version number from version.py so we only need to change it in @@ -876,7 +889,7 @@ def use_educated_guess(self) -> None: "sphinxbootstrap4theme>=0.6.0" ] }, - python_requires=">=3.6", + python_requires=">=3.7", headers=headers, platforms="ALL", keywords=[ @@ -894,7 +907,6 @@ def use_educated_guess(self) -> None: "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -911,6 +923,7 @@ def use_educated_guess(self) -> None: "build_c_core": buildcfg.build_c_core, # used by CI "build_ext": buildcfg.build_ext, "sdist": buildcfg.sdist, + "bdist_wheel": bdist_wheel_abi3, }, ) diff --git a/src/igraph/version.py b/src/igraph/version.py index ca101d47f..e51845b97 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 9, 11) +__version_info__ = (0, 10, 0) __version__ = ".".join("{0}".format(x) for x in __version_info__) diff --git a/tox.ini b/tox.ini index 1ec3997ed..e23856d30 100644 --- a/tox.ini +++ b/tox.ini @@ -4,14 +4,14 @@ # and then run "tox" from this directory. [tox] -envlist = py36, py37, py38, py39, pypy3 +envlist = py37, py38, py39, py310, pypy3 [gh-actions] python = - 3.6: py36 3.7: py37 3.8: py38 3.9: py39 + 3.10: py310 pypy-3.7: pypy3 [testenv] From ec4ee3cfc7451ef59e2d40aea125dcc648a3a668 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 18:09:31 +0200 Subject: [PATCH 1034/1892] fix: make sure that setup.py still works without the 'wheel' module --- .github/workflows/build.yml | 8 ++++---- setup.py | 39 ++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b4707c27..7a5220ce7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit # wheel for Linux yet @@ -43,7 +43,7 @@ jobs: - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_EXTRAS: "test-musl" @@ -68,14 +68,14 @@ jobs: - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_EXTRAS: "test-musl" diff --git a/setup.py b/setup.py index 5e0ad85cc..1a3c2fcc2 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,11 @@ ########################################################################### from setuptools import find_packages, setup, Command, Extension -from wheel.bdist_wheel import bdist_wheel + +try: + from wheel.bdist_wheel import bdist_wheel +except ImportError: + bdist_wheel = None import glob import shlex @@ -780,14 +784,17 @@ def use_educated_guess(self) -> None: ########################################################################### -class bdist_wheel_abi3(bdist_wheel): - def get_tag(self): - python, abi, plat = super().get_tag() - if python.startswith("cp"): - # on CPython, our wheels are abi3 and compatible back to 3.7 - return "cp37", "abi3", plat +if bdist_wheel is not None: + class bdist_wheel_abi3(bdist_wheel): + def get_tag(self): + python, abi, plat = super().get_tag() + if python.startswith("cp"): + # on CPython, our wheels are abi3 and compatible back to 3.7 + return "cp37", "abi3", plat - return python, abi, plat + return python, abi, plat +else: + bdist_wheel_abi3 = None ########################################################################### @@ -820,6 +827,15 @@ def get_tag(self): headers = ["src/_igraph/igraphmodule_api.h"] if not SKIP_HEADER_INSTALL else [] +cmdclass = { + "build_c_core": buildcfg.build_c_core, # used by CI + "build_ext": buildcfg.build_ext, + "sdist": buildcfg.sdist, +} + +if bdist_wheel_abi3 is not None: + cmdclass["bdist_wheel"] = bdist_wheel_abi3 + options = dict( name="igraph", version=__version__, @@ -919,12 +935,7 @@ def get_tag(self): "Topic :: Scientific/Engineering :: Bio-Informatics", "Topic :: Software Development :: Libraries :: Python Modules", ], - cmdclass={ - "build_c_core": buildcfg.build_c_core, # used by CI - "build_ext": buildcfg.build_ext, - "sdist": buildcfg.sdist, - "bdist_wheel": bdist_wheel_abi3, - }, + cmdclass=cmdclass, ) setup(**options) From da476e473528279008d0fa7eb3d417567ec63685 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 18:50:30 +0200 Subject: [PATCH 1035/1892] ci: try building abi3 wheels on Python 3.8 to see if the leak problem persists --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a5220ce7..22b2577e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,9 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" - CIBW_SKIP: "cp36-*" + # Build wheels on Python 3.8 because apparently abi3 wheels built on Python + # 3.7 have a strange memory leak problem when loaded in 3.8 or later + CIBW_SKIP: "cp36-* cp37-*" MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: From 4b0b745da76163081bf593eeb02ca10faf1569fd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 20:37:10 +0200 Subject: [PATCH 1036/1892] ci: build abi3 wheels only for CPython >= 3.9, use version-specific wheels for the rest --- .github/workflows/build.yml | 4 +--- CHANGELOG.md | 9 ++++++--- setup.py | 21 +++++++++++++++++++-- src/_igraph/preamble.h | 4 +++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 22b2577e9..7a5220ce7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,9 +8,7 @@ env: CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" - # Build wheels on Python 3.8 because apparently abi3 wheels built on Python - # 3.7 have a strange memory leak problem when loaded in 3.8 or later - CIBW_SKIP: "cp36-* cp37-*" + CIBW_SKIP: "cp36-*" MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index c0060fa2b..6744db8fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,9 +32,12 @@ - The C core of igraph was updated to version 0.10.0. -- We now publish `abi3` wheels on PyPI, making it possible to use an - already-built Python wheel with newer minor Python releases (and also - reducing the number of wheels we actually need to publish). +- We now publish `abi3` wheels on PyPI from CPython 3.9 onwards, making it + possible to use an already-built Python wheel with newer minor Python + releases (and also reducing the number of wheels we actually need to + publish). Releases for CPython 3.7 and 3.8 still use version-specific wheels + because the code of the C part of the extension contains conditional macros + for CPython 3.7 and 3.8. - Changed default value of the `use_vids=...` argument of `Graph.DataFrame()` to `True`, thanks to [@fwitter](https://github.com/user/fwitter). diff --git a/setup.py b/setup.py index 1a3c2fcc2..732599a80 100644 --- a/setup.py +++ b/setup.py @@ -796,6 +796,15 @@ def get_tag(self): else: bdist_wheel_abi3 = None +# We are going to build an abi3 wheel if we are at least on CPython 3.9. +# This is because the C code contains conditionals for CPython 3.7 and +# 3.8 so we cannot use an abi3 wheel built with CPython 3.7 or 3.8 on +# CPython 3.9 +should_build_abi3_wheel = ( + bdist_wheel_abi3 and + platform.python_implementation() == "CPython" and + sys.version_info >= (3, 9) +) ########################################################################### @@ -811,7 +820,15 @@ def get_tag(self): # Define the extension sources = glob.glob(os.path.join("src", "_igraph", "*.c")) sources.append(os.path.join("src", "_igraph", "force_cpp_linker.cpp")) -igraph_extension = Extension("igraph._igraph", sources, py_limited_api=True) +macros = [] +if should_build_abi3_wheel: + macros.append(("Py_LIMITED_API", "0x03090000")) +igraph_extension = Extension( + "igraph._igraph", + sources=sources, + py_limited_api=should_build_abi3_wheel, + define_macros=macros, +) description = """Python interface to the igraph high performance graph library, primarily aimed at complex network research and analysis. @@ -833,7 +850,7 @@ def get_tag(self): "sdist": buildcfg.sdist, } -if bdist_wheel_abi3 is not None: +if should_build_abi3_wheel: cmdclass["bdist_wheel"] = bdist_wheel_abi3 options = dict( diff --git a/src/_igraph/preamble.h b/src/_igraph/preamble.h index fa427ccac..b1c9596b9 100644 --- a/src/_igraph/preamble.h +++ b/src/_igraph/preamble.h @@ -24,7 +24,9 @@ #define PYTHON_IGRAPH_PREAMBLE_H #ifndef PY_IGRAPH_ALLOW_ENTIRE_PYTHON_API -# define Py_LIMITED_API 0x03060100 +# ifndef Py_LIMITED_API +# define Py_LIMITED_API 0x03090000 +# endif #endif #define PY_SSIZE_T_CLEAN From 20ead614a5a6404d611b746dd36c7f53ae8b7d40 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 5 Sep 2022 20:38:34 +0200 Subject: [PATCH 1037/1892] fix: fix version tag of abi3 wheels --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 732599a80..7a27c0525 100644 --- a/setup.py +++ b/setup.py @@ -789,8 +789,8 @@ class bdist_wheel_abi3(bdist_wheel): def get_tag(self): python, abi, plat = super().get_tag() if python.startswith("cp"): - # on CPython, our wheels are abi3 and compatible back to 3.7 - return "cp37", "abi3", plat + # on CPython, our wheels are abi3 and compatible back to 3.9 + return "cp39", "abi3", plat return python, abi, plat else: From ef8a5be5fe3deee73e465442c93bc5a31510e1ba Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 6 Sep 2022 08:50:20 +0200 Subject: [PATCH 1038/1892] fix: Layout class can now be constructed from numpy arrays, fixes #564 --- src/igraph/layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/layout.py b/src/igraph/layout.py index 09efcaffc..211f162b0 100644 --- a/src/igraph/layout.py +++ b/src/igraph/layout.py @@ -69,7 +69,7 @@ def __init__(self, coords=None, dim=None): length of the coordinate list is zero, otherwise it should be left as is. """ - if coords: + if coords is not None: self._coords = [list(coord) for coord in coords] else: self._coords = [] From e99e084030df18b5668b7a984350cc31a05f116e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Sep 2022 10:06:29 +0200 Subject: [PATCH 1039/1892] fix: make sure that everything is exported from __all__ that used to be exported intentionally in 0.9, refs #565 --- src/igraph/__init__.py | 78 ++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 3c130baa4..026f9a149 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -41,7 +41,6 @@ BLISS_FSM, DFSIter, Edge, - EdgeSeq as _EdgeSeq, GET_ADJACENCY_BOTH, GET_ADJACENCY_LOWER, GET_ADJACENCY_UPPER, @@ -62,7 +61,6 @@ TREE_OUT, TREE_UNDIRECTED, Vertex, - VertexSeq as _VertexSeq, WEAK, arpack_options as default_arpack_options, community_to_membership, @@ -260,13 +258,8 @@ ) from igraph.summary import GraphSummary, summary from igraph.utils import ( - dbl_epsilon, - multidict, - named_temporary_file, numpy_to_contiguous_memoryview, rescale, - safemin, - safemax, ) from igraph.version import __version__, __version_info__ @@ -1126,37 +1119,86 @@ def write(graph, filename, *args, **kwds): # except for the objects mentioned down here. __all__ = ( 'config', + 'AdvancedGradientPalette', + 'BoundingBox', + 'CairoGraphDrawer', + 'ClusterColoringPalette', + 'Clustering', + 'CohesiveBlocks', + 'Configuration', + 'Cover', 'Cut', - 'Graph', - 'GraphBase', + 'DefaultGraphDrawer', + 'Dendrogram', + 'DyadCensus', 'Edge', - 'Vertex', 'EdgeSeq', - 'VertexSeq', - 'Matching', - 'AdvancedGradientPalette', + 'FittedPowerLaw', + 'Flow', 'GradientPalette', + 'Graph', + 'GraphBase', + 'GraphSummary', + 'Histogram', 'InternalError', 'Layout', - 'default_arpack_options', + 'Matching', + 'MatplotlibGraphDrawer', + 'Matrix', + 'Palette', + 'Plot', + 'Point', + 'PrecalculatedPalette', + 'RainbowPalette', + 'Rectangle', + 'RunningMean', + 'TriadCensus', + 'UniqueIdGenerator', + 'Vertex', + 'VertexClustering', + 'VertexCover', + 'VertexDendrogram', + 'VertexSeq', + 'autocurve', + 'color_name_to_rgb', + 'color_name_to_rgba', 'community_to_membership', + 'compare_communities', 'convex_hull', - 'is_degree_sequence', - 'is_graphical_degree_sequence', + 'default_arpack_options', + 'disjoint_union', + 'get_include', 'hsla_to_rgba', 'hsl_to_rgb', 'hsva_to_rgba', 'hsv_to_rgb', + 'is_degree_sequence', + 'is_graphical', + 'is_graphical_degree_sequence', + 'intersection', + 'known_colors', + 'load', + 'mean', + 'median', + 'palettes', + 'percentile', + 'plot', + 'power_law_fit', + 'quantile', + 'read', + 'rescale', 'rgba_to_hsla', 'rgb_to_hsl', 'rgba_to_hsva', 'rgb_to_hsv', + 'save', 'set_progress_handler', 'set_random_number_generator', 'set_status_handler', + 'split_join_distance', + 'summary', 'union', - 'intersection', - 'disjoint_union', + 'write', # enums and stuff 'ADJ_DIRECTED', From 749503dccab99618678e2deb65f8c4b11f958a43 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Sep 2022 10:53:54 +0200 Subject: [PATCH 1040/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 83714d331..96c2cc751 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 83714d331f5f279eb4a5aa11be054a1710e220c4 +Subproject commit 96c2cc751063bf3ba7e920e99793956013cef6b5 From cbd5341e166ca20071726872b134b8dec13973af Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Sep 2022 16:56:56 +0200 Subject: [PATCH 1041/1892] chore: updated vendored igraph to 0.10.1 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 96c2cc751..b5ebda267 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 96c2cc751063bf3ba7e920e99793956013cef6b5 +Subproject commit b5ebda26702efbd510d91d7ccc1b38deea1e8ed1 From 47501ad4ac229f99455950bff6ede69b10c474cd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 8 Sep 2022 17:34:50 +0200 Subject: [PATCH 1042/1892] fix: remove unneeded unrolling of dict.items() in several parts of the code --- src/igraph/basic.py | 8 ++++---- src/igraph/io/libraries.py | 8 ++++---- src/igraph/utils.py | 2 +- tests/test_basic.py | 2 +- tests/test_cliques.py | 4 ++-- tests/test_vertexseq.py | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/igraph/basic.py b/src/igraph/basic.py index 5e443a26c..416a9949a 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -41,7 +41,7 @@ def _add_edges(graph, es, attributes=None): res = GraphBase.add_edges(graph, es) n = graph.ecount() - eid if (attributes is not None) and (n > 0): - for key, val in list(attributes.items()): + for key, val in attributes.items(): graph.es[eid:][key] = val return res @@ -90,7 +90,7 @@ def _add_vertices(graph, n, attributes=None): result = GraphBase.add_vertices(graph, 1) graph.vs[m]["name"] = n if attributes is not None: - for key, val in list(attributes.items()): + for key, val in attributes.items(): graph.vs[m][key] = val elif hasattr(n, "__iter__"): m = graph.vcount() @@ -102,13 +102,13 @@ def _add_vertices(graph, n, attributes=None): if len(names) > 0: graph.vs[m:]["name"] = names if attributes is not None: - for key, val in list(attributes.items()): + for key, val in attributes.items(): graph.vs[m:][key] = val else: result = GraphBase.add_vertices(graph, n) if (attributes is not None) and (n > 0): m = graph.vcount() - n - for key, val in list(attributes.items()): + for key, val in attributes.items(): graph.vs[m:][key] = val return result diff --git a/src/igraph/io/libraries.py b/src/igraph/io/libraries.py index d4b02115b..1269a6d28 100644 --- a/src/igraph/io/libraries.py +++ b/src/igraph/io/libraries.py @@ -201,7 +201,7 @@ def _export_graph_to_graph_tool( # Graph attributes if graph_attributes is not None: - for x, dtype in list(graph_attributes.items()): + for x, dtype in graph_attributes.items(): # Strange syntax for setting internal properties gprop = g.new_graph_property(str(dtype)) g.graph_properties[x] = gprop @@ -209,7 +209,7 @@ def _export_graph_to_graph_tool( # Vertex attributes if vertex_attributes is not None: - for x, dtype in list(vertex_attributes.items()): + for x, dtype in vertex_attributes.items(): # Create a new vertex property g.vertex_properties[x] = g.new_vertex_property(str(dtype)) # Fill the values from the igraph.Graph @@ -218,12 +218,12 @@ def _export_graph_to_graph_tool( # Edges and edge attributes if edge_attributes is not None: - for x, dtype in list(edge_attributes.items()): + for x, dtype in edge_attributes.items(): g.edge_properties[x] = g.new_edge_property(str(dtype)) for edge in graph.es: e = g.add_edge(edge.source, edge.target) if edge_attributes is not None: - for x, dtype in list(edge_attributes.items()): + for x, dtype in edge_attributes.items(): prop = edge.attributes().get(x, None) g.edge_properties[x][e] = prop diff --git a/src/igraph/utils.py b/src/igraph/utils.py index d8a52516e..48f226774 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -313,7 +313,7 @@ def lists(self): def update(self, arg, **kwds): if hasattr(arg, "keys") and callable(arg.keys): - for key in list(arg.keys()): + for key in arg.keys(): self.add(key, arg[key]) else: for key, value in arg: diff --git a/tests/test_basic.py b/tests/test_basic.py index b21342f2f..bf4710e07 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -321,7 +321,7 @@ def testGraphGetEid(self): g = Graph.Famous("petersen") g.vs["name"] = list("ABCDEFGHIJ") edges_to_ids = dict((v, k) for k, v in enumerate(g.get_edgelist())) - for (source, target), edge_id in list(edges_to_ids.items()): + for (source, target), edge_id in edges_to_ids.items(): source_name, target_name = g.vs[(source, target)]["name"] self.assertEqual(edge_id, g.get_eid(source, target)) self.assertEqual(edge_id, g.get_eid(source_name, target_name)) diff --git a/tests/test_cliques.py b/tests/test_cliques.py index 573bd6181..cb952d220 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -59,7 +59,7 @@ def testCliques(self): [1, 2, 4, 5], ], } - for (lo, hi), exp in list(tests.items()): + for (lo, hi), exp in tests.items(): self.assertEqual(sorted(exp), sorted(map(sorted, self.g.cliques(lo, hi)))) def testLargestCliques(self): @@ -129,7 +129,7 @@ def testIndependentVertexSets(self): (2, 3, 4), ], } - for (lo, hi), exp in list(tests.items()): + for (lo, hi), exp in tests.items(): self.assertEqual(exp, self.g1.independent_vertex_sets(lo, hi)) def testLargestIndependentVertexSets(self): diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index 8cb612e66..a2587ebfd 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -77,7 +77,7 @@ def testIncident(self): for i in range(g.vcount()): vertex = g.vs[i] - for mode, method_name in list(method_table.items()): + for mode, method_name in method_table.items(): method = getattr(vertex, method_name) self.assertEqual( g.incident(i, mode=mode), From 3db29fcefadaa8687286f08c3c80e80b25aa9bdc Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 9 Sep 2022 09:38:57 +0200 Subject: [PATCH 1043/1892] networkx g.nodes is not a list but is iterable (#567) * networkx g.nodes is not a list but is iterable * Add test * fix: fix check for _igraph_index in NetworkX nodes * fix: remove an unneeded unrolling of dict.items() in the nx converter Co-authored-by: Tamas Nepusz --- src/igraph/io/libraries.py | 4 ++-- tests/test_foreign.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/igraph/io/libraries.py b/src/igraph/io/libraries.py index 1269a6d28..7331d9d25 100644 --- a/src/igraph/io/libraries.py +++ b/src/igraph/io/libraries.py @@ -98,7 +98,7 @@ def _construct_graph_from_networkx(cls, g, vertex_attr_hashable : str = "_nx_nam vcount = len(vnames) # Dictionary connecting networkx hashables with igraph indices - if len(g) and "_igraph_index" in g.nodes[0]: + if len(g) and "_igraph_index" in next(iter(g.nodes.values())): # Collect _igraph_index and fill gaps idx = [x["_igraph_index"] for v, x in g.nodes.data()] idx.sort() @@ -118,7 +118,7 @@ def _construct_graph_from_networkx(cls, g, vertex_attr_hashable : str = "_nx_nam # Vertex attributes for v, datum in g.nodes.data(): - for key, val in list(datum.items()): + for key, val in datum.items(): # Get rid of _igraph_index (we used it already) if key == "_igraph_index": continue diff --git a/tests/test_foreign.py b/tests/test_foreign.py index 5e117179a..a6890927d 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -690,6 +690,19 @@ def testGraphNetworkx(self): self.assertEqual(g.vcount(), g2.vcount()) self.assertEqual(sorted(g.get_edgelist()), sorted(g2.get_edgelist())) + # Test networkx with custom node hashables + # In this case each node is a tuple of ints + g_nx = nx.DiGraph() + inf = float("inf") + g_nx.add_edges_from(( + ((0, 0), (1, 1), {"weight": 3.0}), + ((0, 0), (1, 0), {"weight": inf}), + )) + g = Graph.from_networkx(g_nx) + self.assertTrue(g.is_directed()) + self.assertEqual(g.vcount(), 3) + self.assertTrue(g.es["weight"] == [3.0, inf] or g.es["weight"] == [inf, 3.0]) + @unittest.skipIf(nx is None, "test case depends on networkx") def testMultigraphNetworkx(self): # Undirected From d0e90788d532a95e2f49788b2f540677ee5a9425 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 11 Sep 2022 12:33:54 +0200 Subject: [PATCH 1044/1892] feat: added Graph.minimum_cycle_basis() and Graph.fundamental_cycles() --- src/_igraph/graphobject.c | 197 ++++++++++++++++++++++++++++++++------ tests/test_cycles.py | 183 +++++++++++++++++++++++++++++++++++ tests/test_structural.py | 12 --- 3 files changed, 349 insertions(+), 43 deletions(-) create mode 100644 tests/test_cycles.py diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8119f6e68..eb34b7178 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -429,25 +429,6 @@ PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject * self) return igraphmodule_integer_t_to_PyObject(igraph_ecount(&self->g)); } -/** \ingroup python_interface_graph - * \brief Checks whether an \c igraph.Graph object is a DAG. - * \return \c True if the graph is directed, \c False otherwise. - * \sa igraph_is_dag - */ -PyObject *igraphmodule_Graph_is_dag(igraphmodule_GraphObject * self) -{ - igraph_bool_t res; - - if (igraph_is_dag(&self->g, &res)) { - igraphmodule_handle_igraph_error(); - return NULL; - } - - if (res) - Py_RETURN_TRUE; - Py_RETURN_FALSE; -} - /** \ingroup python_interface_graph * \brief Checks whether an \c igraph.Graph object is directed. * \return \c True if the graph is directed, \c False otherwise. @@ -2756,9 +2737,8 @@ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, static char *kwlist[] = { "dim", "nei", "directed", "mutual", "circular", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|nOOO", kwlist, - &PyList_Type, &o_dimvector, - &nei, &o_directed, &o_mutual, &o_circular)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nOOO", kwlist, + &o_dimvector, &nei, &o_directed, &o_mutual, &o_circular)) return NULL; directed = PyObject_IsTrue(o_directed); @@ -6781,6 +6761,115 @@ PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self) { return list; } +/********************************************************************** + * Cycles and cycle bases * + **********************************************************************/ + +PyObject *igraphmodule_Graph_is_acyclic(igraphmodule_GraphObject *self) { + igraph_bool_t res; + + if (igraph_is_acyclic(&self->g, &res)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (res) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +PyObject *igraphmodule_Graph_is_dag(igraphmodule_GraphObject * self) { + igraph_bool_t res; + + if (igraph_is_dag(&self->g, &res)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (res) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +PyObject *igraphmodule_Graph_fundamental_cycles( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + PyObject *cutoff_o = Py_None; + PyObject *start_vid_o = Py_None; + PyObject *result_o; + igraph_integer_t cutoff = -1, start_vid = -1; + igraph_vector_int_list_t result; + + static char *kwlist[] = { "start_vid", "cutoff", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &start_vid_o, &cutoff_o)) + return NULL; + + if (start_vid_o != Py_None && igraphmodule_PyObject_to_vid(start_vid_o, &start_vid, &self->g)) + return NULL; + + if (cutoff_o != Py_None && igraphmodule_PyObject_to_integer_t(cutoff_o, &cutoff)) + return NULL; + + if (igraph_vector_int_list_init(&result, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_fundamental_cycles(&self->g, &result, start_vid, cutoff, /* weights = */ NULL)) { + igraph_vector_int_list_destroy(&result); + igraphmodule_handle_igraph_error(); + return NULL; + } + + result_o = igraphmodule_vector_int_list_t_to_PyList_of_tuples(&result); + igraph_vector_int_list_destroy(&result); + + return result_o; +} + +PyObject *igraphmodule_Graph_minimum_cycle_basis( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + PyObject *cutoff_o = Py_None; + PyObject *complete_o = Py_True; + PyObject *use_cycle_order_o = Py_True; + PyObject *result_o; + igraph_integer_t cutoff = -1; + igraph_vector_int_list_t result; + + static char *kwlist[] = { "cutoff", "complete", "use_cycle_order", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &cutoff_o, &complete_o, &use_cycle_order_o)) + return NULL; + + if (cutoff_o != Py_None && igraphmodule_PyObject_to_integer_t(cutoff_o, &cutoff)) + return NULL; + + if (igraph_vector_int_list_init(&result, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_minimum_cycle_basis( + &self->g, &result, cutoff, PyObject_IsTrue(complete_o), + PyObject_IsTrue(use_cycle_order_o), /* weights = */ NULL + )) { + igraph_vector_int_list_destroy(&result); + igraphmodule_handle_igraph_error(); + return NULL; + } + + result_o = igraphmodule_vector_int_list_t_to_PyList_of_tuples(&result); + igraph_vector_int_list_destroy(&result); + + return result_o; +} + /********************************************************************** * Graph layout algorithms * **********************************************************************/ @@ -12570,15 +12659,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the number of edges in the graph.\n" "@rtype: integer\n"}, - // interface to igraph_is_dag - {"is_dag", (PyCFunction) igraphmodule_Graph_is_dag, - METH_NOARGS, - "is_dag()\n--\n\n" - "Checks whether the graph is a DAG (directed acyclic graph).\n\n" - "A DAG is a directed graph with no directed cycles.\n\n" - "@return: C{True} if it is a DAG, C{False} otherwise.\n" - "@rtype: boolean"}, - // interface to igraph_is_directed {"is_directed", (PyCFunction) igraphmodule_Graph_is_directed, METH_NOARGS, @@ -14889,6 +14969,61 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " by a tuple of length 3, containing the corresponding vertex IDs." }, + /***********************/ + /* CYCLES, CYCLE BASES */ + /***********************/ + + {"is_acyclic", (PyCFunction) igraphmodule_Graph_is_acyclic, + METH_NOARGS, + "is_acyclic()\n--\n\n" + "Returns whether the graph is acyclic (i.e. contains no cycles).\n\n" + "@return: C{True} if the graph is acyclic, C{False} otherwise.\n" + "@rtype: boolean" + }, + + {"is_dag", (PyCFunction) igraphmodule_Graph_is_dag, + METH_NOARGS, + "is_dag()\n--\n\n" + "Checks whether the graph is a DAG (directed acyclic graph).\n\n" + "A DAG is a directed graph with no directed cycles.\n\n" + "@return: C{True} if it is a DAG, C{False} otherwise.\n" + "@rtype: boolean" + }, + + {"fundamental_cycles", (PyCFunction) igraphmodule_Graph_fundamental_cycles, + METH_VARARGS | METH_KEYWORDS, + "fundamental_cycles(start_vid=None, cutoff=None)\n--\n\n" + "Finds a single fundamental cycle basis of the graph\n\n" + "@param start_vid: when C{None} or negative, a complete fundamental cycle basis is\n" + " returned. When it is a vertex or a vertex ID, the fundamental cycles\n" + " associated with the BFS tree rooted in that vertex will be returned,\n" + " only for the weakly connected component containing that vertex\n" + "@param cutoff: when C{None} or negative, a complete cycle basis is returned. Otherwise\n" + " the BFS is stopped after this many steps, so the result will effectively\n" + " include cycles of length M{2 * cutoff + 1} or shorter only.\n" + "@return: the cycle basis as a list of tuples containing edge IDs" + }, + {"minimum_cycle_basis", (PyCFunction) igraphmodule_Graph_minimum_cycle_basis, + METH_VARARGS | METH_KEYWORDS, + "minimum_cycle_basis(cutoff=None, complete=True, use_cycle_order=True)\n--\n\n" + "Computes a minimum cycle basis of the graph\n\n" + "@param cutoff: when C{None} or negative, a complete minimum cycle basis is returned.\n" + " Otherwise only those cycles in the result will be part of some minimum\n" + " cycle basis that are of length M{2 * cutoff + 1} or shorter. Cycles\n" + " longer than this limit may not be of the smallest possible size. This\n" + " parameter effectively limits the depth of the BFS tree when computing\n" + " candidate cycles and may speed up the computation substantially.\n" + "@param complete: used only when a cutoff is specified, and in this case it\n" + " specifies whether a complete basis is returned (C{True}) or the result\n" + " will be limited to cycles of length M{2 * cutoff + 1} or shorter only.\n" + " This limits computation time, but the result may not span the entire\n" + " cycle space.\n" + "@param use_cycle_order: if C{True}, every cycle is returned in natural\n" + " order: the edge IDs will appear ordered along the cycle. If C{False},\n" + " no guarantees are given about the ordering of edge IDs within cycles.\n" + "@return: the cycle basis as a list of tuples containing edge IDs" + }, + /********************/ /* LAYOUT FUNCTIONS */ /********************/ diff --git a/tests/test_cycles.py b/tests/test_cycles.py new file mode 100644 index 000000000..8d8260a41 --- /dev/null +++ b/tests/test_cycles.py @@ -0,0 +1,183 @@ +import random +import unittest + +from igraph import Graph + + +class CycleTests(unittest.TestCase): + def setUp(self): + random.seed(42) + + def test_is_acyclic(self): + g = Graph.Tree(121, 3, mode="out") + self.assertTrue(g.is_acyclic()) + + g = Graph() + self.assertTrue(g.is_acyclic()) + + g = Graph.Ring(5) + self.assertFalse(g.is_acyclic()) + + def test_is_dag(self): + g = Graph(5, [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], directed=True) + self.assertTrue(g.is_dag()) + g.to_undirected() + self.assertFalse(g.is_dag()) + g = Graph.Barabasi(1000, 2, directed=True) + self.assertTrue(g.is_dag()) + g = Graph.GRG(100, 0.2) + self.assertFalse(g.is_dag()) + g = Graph.Ring(10, directed=True, mutual=False) + self.assertFalse(g.is_dag()) + + def test_fundamental_cycles(self): + g = Graph( + [ + (1, 2), + (2, 3), + (3, 1), + (4, 5), + (5, 4), + (4, 5), + (6, 7), + (7, 8), + (8, 9), + (9, 6), + (6, 8), + (10, 10), + (10, 11), + (12, 12), + ] + ) + cycles = [sorted(cycle) for cycle in g.fundamental_cycles()] + assert cycles == [[0, 1, 2], [4, 5], [3, 5], [6, 7, 10], [8, 9, 10], [11], [13]] + + cycles = [sorted(cycle) for cycle in g.fundamental_cycles(start_vid=6)] + assert cycles == [[6, 7, 10], [8, 9, 10]] + + cycles = [ + sorted(cycle) for cycle in g.fundamental_cycles(start_vid=6, cutoff=1) + ] + assert cycles == [[6, 7, 10], [8, 9, 10]] + + def test_minimum_cycle_basis(self): + g = Graph( + [ + (1, 2), + (2, 3), + (3, 1), + (4, 5), + (5, 4), + (4, 5), + (6, 7), + (7, 8), + (8, 9), + (9, 6), + (6, 8), + (10, 10), + (10, 11), + (12, 12), + ] + ) + cycles = g.minimum_cycle_basis() + assert cycles == [ + (11,), + (13,), + (3, 5), + (4, 5), + (0, 1, 2), + (6, 7, 10), + (8, 9, 10), + ] + + g = Graph.Lattice((5, 6), circular=True) + cycles = g.minimum_cycle_basis() + expected = [ + (0, 1, 10, 3), + (0, 51, 50, 53), + (1, 8, 9, 18), + (2, 3, 12, 5), + (2, 53, 52, 55), + (4, 5, 14, 7), + (4, 55, 54, 57), + (6, 7, 16, 9), + (6, 57, 56, 59), + (8, 59, 58, 51), + (10, 11, 20, 13), + (11, 18, 19, 28), + (12, 13, 22, 15), + (14, 15, 24, 17), + (16, 17, 26, 19), + (20, 21, 30, 23), + (21, 28, 29, 38), + (22, 23, 32, 25), + (24, 25, 34, 27), + (26, 27, 36, 29), + (30, 31, 40, 33), + (31, 38, 39, 48), + (32, 33, 42, 35), + (34, 35, 44, 37), + (36, 37, 46, 39), + (40, 41, 50, 43), + (41, 48, 49, 58), + (42, 43, 52, 45), + (44, 45, 54, 47), + (0, 8, 6, 4, 2), + (1, 51, 41, 31, 21, 11), + ] + assert len(cycles) == len(expected) + for expected_cycle, observed_cycle in zip(expected, cycles): + assert expected_cycle == observed_cycle or expected_cycle == (observed_cycle[0], ) + tuple(reversed(observed_cycle[1:])) + + g = Graph.Lattice((5, 6), circular=True) + cycles = g.minimum_cycle_basis(cutoff=2, complete=False) + expected = [ + (0, 1, 10, 3), + (0, 51, 50, 53), + (1, 8, 9, 18), + (2, 3, 12, 5), + (2, 53, 52, 55), + (4, 5, 14, 7), + (4, 55, 54, 57), + (6, 7, 16, 9), + (6, 57, 56, 59), + (8, 59, 58, 51), + (10, 11, 20, 13), + (11, 18, 19, 28), + (12, 13, 22, 15), + (14, 15, 24, 17), + (16, 17, 26, 19), + (20, 21, 30, 23), + (21, 28, 29, 38), + (22, 23, 32, 25), + (24, 25, 34, 27), + (26, 27, 36, 29), + (30, 31, 40, 33), + (31, 38, 39, 48), + (32, 33, 42, 35), + (34, 35, 44, 37), + (36, 37, 46, 39), + (40, 41, 50, 43), + (41, 48, 49, 58), + (42, 43, 52, 45), + (44, 45, 54, 47), + (0, 8, 6, 4, 2), + (1, 51, 41, 31, 21, 11), + ] + assert len(cycles) == len(expected) - 1 + for expected_cycle, observed_cycle in zip(expected[:-1], cycles): + assert expected_cycle == observed_cycle or expected_cycle == (observed_cycle[0], ) + tuple(reversed(observed_cycle[1:])) + + +def suite(): + cycle_suite = unittest.makeSuite(CycleTests) + return unittest.TestSuite([cycle_suite]) + + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + + +if __name__ == "__main__": + test() diff --git a/tests/test_structural.py b/tests/test_structural.py index d6c665da6..b39f948a7 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -614,18 +614,6 @@ def testTopologicalSorting(self): g.to_undirected() self.assertRaises(InternalError, g.topological_sorting) - def testIsDAG(self): - g = Graph(5, [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], directed=True) - self.assertTrue(g.is_dag()) - g.to_undirected() - self.assertFalse(g.is_dag()) - g = Graph.Barabasi(1000, 2, directed=True) - self.assertTrue(g.is_dag()) - g = Graph.GRG(100, 0.2) - self.assertFalse(g.is_dag()) - g = Graph.Ring(10, directed=True, mutual=False) - self.assertFalse(g.is_dag()) - def testIsTree(self): g = Graph() self.assertFalse(g.is_tree()) From 742d3b58d6d29beb45a946ce97cf82aa7dc7bc9b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 11 Sep 2022 12:34:49 +0200 Subject: [PATCH 1045/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6744db8fe..af3641458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # igraph Python interface changelog +## [Unreleased] + +### Added + +- Added `Graph.minimum_cycle_basis()` and `Graph.fundamental_cycles()` + +### Fixed + +- Restored missing exports from `igraph.__all__` that used to be in the main + `igraph` package before 0.10.0. + ## [0.10.0] - 2022-09-05 ### Added From 562c05fb4462c5bb1b2d1dd965002fad481ba89c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 11 Sep 2022 15:24:16 +0200 Subject: [PATCH 1046/1892] feat: Graph.average_path_length() now supports weights --- CHANGELOG.md | 5 +++++ src/_igraph/graphobject.c | 29 +++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af3641458..c10c1e249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - Added `Graph.minimum_cycle_basis()` and `Graph.fundamental_cycles()` +- `Graph.average_path_length()` now supports edge weights. + ### Fixed - Restored missing exports from `igraph.__all__` that used to be in the main @@ -39,6 +41,9 @@ - `Graph.get_laplacian()` now supports left-, right- and symmetric normalization. +- `Graph.modularity()` now supports setting the resolution with the + `resolution=...` parameter. + ### Changed - The C core of igraph was updated to version 0.10.0. diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index eb34b7178..e95da47d9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3809,16 +3809,31 @@ PyObject *igraphmodule_Graph_average_path_length(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "directed", "unconn", NULL }; + static char *kwlist[] = { "directed", "unconn", "weights", NULL }; + PyObject *weights_o = Py_None; PyObject *directed = Py_True, *unconn = Py_True; igraph_real_t res; + igraph_vector_t *weights = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &directed, &unconn)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &directed, &unconn, &weights_o)) return NULL; - if (igraph_average_path_length(&self->g, &res, 0, PyObject_IsTrue(directed), PyObject_IsTrue(unconn))) { - igraphmodule_handle_igraph_error(); - return NULL; + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, + ATTRIBUTE_TYPE_EDGE)) return NULL; + + if (weights) { + if (igraph_average_path_length_dijkstra(&self->g, &res, 0, weights, PyObject_IsTrue(directed), PyObject_IsTrue(unconn))) { + igraph_vector_destroy(weights); free(weights); + igraphmodule_handle_igraph_error(); + return NULL; + } + + igraph_vector_destroy(weights); free(weights); + } else { + if (igraph_average_path_length(&self->g, &res, 0, PyObject_IsTrue(directed), PyObject_IsTrue(unconn))) { + igraphmodule_handle_igraph_error(); + return NULL; + } } return PyFloat_FromDouble(res); @@ -13623,7 +13638,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"average_path_length", (PyCFunction) igraphmodule_Graph_average_path_length, METH_VARARGS | METH_KEYWORDS, - "average_path_length(directed=True, unconn=True)\n--\n\n" + "average_path_length(directed=True, unconn=True, weights=None)\n--\n\n" "Calculates the average path length in a graph.\n\n" "@param directed: whether to consider directed paths in case of a\n" " directed graph. Ignored for undirected graphs.\n" @@ -13631,6 +13646,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " the average of the geodesic lengths in the components is\n" " calculated. Otherwise for all unconnected vertex pairs,\n" " a path length equal to the number of vertices is used.\n" + "@param weights: edge weights to be used. Can be a sequence or iterable or\n" + " even an edge attribute name.\n" "@return: the average path length in the graph\n"}, /* interface to igraph_authority_score */ From 1d5a31017920b51dbd7c73edd8e3e12b4b1de36f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 11 Sep 2022 17:45:39 +0200 Subject: [PATCH 1047/1892] refactor: simplifying attribute handler code and improving resilience to errors [WIP] --- src/_igraph/attributes.c | 329 ++++++++++++++++++++++++--------------- src/_igraph/attributes.h | 2 - 2 files changed, 201 insertions(+), 130 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 9fe211822..0fafbe573 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -38,26 +38,43 @@ static INLINE int PyObject_allowed_in_string_attribute(PyObject* o) { return o == Py_None || (o != 0 && PyBaseString_Check(o)); } +static INLINE void igraphmodule_i_attribute_struct_invalidate_vertex_name_index( + igraphmodule_i_attribute_struct *attrs +); + int igraphmodule_i_attribute_struct_init(igraphmodule_i_attribute_struct *attrs) { - int i; - for (i=0; i<3; i++) { + int i, j; + + for (i = 0; i < 3; i++) { attrs->attrs[i] = PyDict_New(); - if (PyErr_Occurred()) + if (PyErr_Occurred()) { + for (j = 0; j < i; j++) { + RC_DEALLOC("dict", attrs->attrs[j]); + Py_DECREF(attrs->attrs[j]); + attrs->attrs[j] = NULL; + } return 1; + } + RC_ALLOC("dict", attrs->attrs[i]); } - attrs->vertex_name_index = 0; + + attrs->vertex_name_index = NULL; + return 0; } void igraphmodule_i_attribute_struct_destroy(igraphmodule_i_attribute_struct *attrs) { int i; - for (i=0; i<3; i++) { + + for (i = 0; i < 3; i++) { if (attrs->attrs[i]) { RC_DEALLOC("dict", attrs->attrs[i]); Py_DECREF(attrs->attrs[i]); + attrs->attrs[i] = NULL; } } + if (attrs->vertex_name_index) { RC_DEALLOC("dict", attrs->vertex_name_index); Py_DECREF(attrs->vertex_name_index); @@ -68,32 +85,37 @@ int igraphmodule_i_attribute_struct_index_vertex_names( igraphmodule_i_attribute_struct *attrs, igraph_bool_t force) { Py_ssize_t n = 0; PyObject *name_list, *key, *value; + igraph_bool_t success = 0; - if (attrs->vertex_name_index && !force) + if (attrs->vertex_name_index && !force) { return 0; + } if (attrs->vertex_name_index == 0) { attrs->vertex_name_index = PyDict_New(); if (attrs->vertex_name_index == 0) { - return 1; + goto cleanup; } - } else - PyDict_Clear(attrs->vertex_name_index); + } - name_list = PyDict_GetItemString(attrs->attrs[1], "name"); - if (name_list == 0) - return 0; /* no name attribute */ + PyDict_Clear(attrs->vertex_name_index); + + name_list = PyDict_GetItemString(attrs->attrs[ATTRHASH_IDX_VERTEX], "name"); + if (name_list == 0) { + success = 1; + goto cleanup; + } n = PyList_Size(name_list) - 1; while (n >= 0) { key = PyList_GetItem(name_list, n); /* we don't own a reference to key */ if (key == 0) { - return 1; + goto cleanup; } value = PyLong_FromLong(n); /* we do own a reference to value */ if (value == 0) { - return 1; + goto cleanup; } if (PyDict_SetItem(attrs->vertex_name_index, key, value)) { @@ -108,7 +130,10 @@ int igraphmodule_i_attribute_struct_index_vertex_names( ); } - return 1; + /* Drop reference to value because we still own it */ + Py_DECREF(value); + + goto cleanup; } /* PyDict_SetItem did an INCREF for both the key and a value, therefore we @@ -118,16 +143,24 @@ int igraphmodule_i_attribute_struct_index_vertex_names( n--; } - return 0; -} + success = 1; -void igraphmodule_i_attribute_struct_invalidate_vertex_name_index( - igraphmodule_i_attribute_struct *attrs) { - if (attrs->vertex_name_index == 0) - return; +cleanup: + if (!success) { + igraphmodule_i_attribute_struct_invalidate_vertex_name_index(attrs); + } - Py_DECREF(attrs->vertex_name_index); - attrs->vertex_name_index = 0; + return success ? 0 : 1; +} + +static void igraphmodule_i_attribute_struct_invalidate_vertex_name_index( + igraphmodule_i_attribute_struct *attrs +) { + if (attrs->vertex_name_index) { + RC_DEALLOC("dict", attrs->vertex_name_index); + Py_DECREF(attrs->vertex_name_index); + attrs->vertex_name_index = NULL; + } } void igraphmodule_invalidate_vertex_name_index(igraph_t *graph) { @@ -224,15 +257,19 @@ igraph_bool_t igraphmodule_has_edge_attribute(const igraph_t *graph, const char* * attribute exists already (no exception set). The returned * reference is borrowed. */ -PyObject* igraphmodule_create_edge_attribute(const igraph_t* graph, +PyObject* igraphmodule_i_create_edge_attribute(const igraph_t* graph, const char* name) { PyObject *dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; PyObject *values; Py_ssize_t i, n; - if (dict == 0) { + if (dict == NULL) { dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE] = PyDict_New(); + if (dict == NULL) { + return NULL; + } } + if (PyDict_GetItemString(dict, name)) return 0; @@ -295,12 +332,16 @@ PyObject* igraphmodule_get_edge_attribute_values(const igraph_t* graph, PyObject* igraphmodule_create_or_get_edge_attribute_values(const igraph_t* graph, const char* name) { PyObject *dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE], *result; - if (dict == 0) + if (dict == NULL) { return 0; + } + result = PyDict_GetItemString(dict, name); - if (result != 0) + if (result != NULL) { return result; - return igraphmodule_create_edge_attribute(graph, name); + } + + return igraphmodule_i_create_edge_attribute(graph, name); } /* Attribute handlers for the Python interface */ @@ -314,28 +355,37 @@ static igraph_error_t igraphmodule_i_attribute_init(igraph_t *graph, igraph_vect if (!attrs) { IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); } + IGRAPH_FINALLY(free, attrs); + if (igraphmodule_i_attribute_struct_init(attrs)) { PyErr_PrintEx(0); - free(attrs); IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); } - graph->attr = (void*)attrs; + IGRAPH_FINALLY(igraphmodule_i_attribute_struct_destroy, attrs); /* See if we have graph attributes */ if (attr) { PyObject *dict = attrs->attrs[0], *value; const char *s; + n = igraph_vector_ptr_size(attr); for (i = 0; i < n; i++) { igraph_attribute_record_t *attr_rec; attr_rec = VECTOR(*attr)[i]; + switch (attr_rec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: value = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]); + if (!value) { + PyErr_PrintEx(0); + } break; case IGRAPH_ATTRIBUTE_STRING: s = igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0); value = PyUnicode_FromString(s ? s : ""); + if (!value) { + PyErr_PrintEx(0); + } break; case IGRAPH_ATTRIBUTE_BOOLEAN: value = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[0] ? Py_True : Py_False; @@ -343,23 +393,29 @@ static igraph_error_t igraphmodule_i_attribute_init(igraph_t *graph, igraph_vect break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - value = 0; + value = NULL; break; } + if (value) { if (PyDict_SetItemString(dict, attr_rec->name, value)) { Py_DECREF(value); - igraphmodule_i_attribute_struct_destroy(attrs); - free(graph->attr); graph->attr = 0; - IGRAPH_ERROR("failed to add attributes to graph attribute hash", - IGRAPH_FAILURE); + value = NULL; /* set value to NULL to indicate an error */ + } else { + Py_DECREF(value); } - Py_DECREF(value); - value = 0; + } + + if (!value) { + /* there was an error above, bail out */ + IGRAPH_ERROR("failed to add attributes to graph attribute hash", IGRAPH_FAILURE); } } } + graph->attr = (void*)attrs; + IGRAPH_FINALLY_CLEAN(2); + return IGRAPH_SUCCESS; } @@ -370,6 +426,7 @@ static void igraphmodule_i_attribute_destroy(igraph_t *graph) { /* printf("Destroying attribute table\n"); */ if (graph->attr) { attrs = (igraphmodule_i_attribute_struct*)graph->attr; + graph->attr = NULL; igraphmodule_i_attribute_struct_destroy(attrs); free(attrs); } @@ -382,50 +439,78 @@ static igraph_error_t igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t PyObject *key, *value, *newval, *o=NULL; igraph_bool_t copy_attrs[3] = { ga, va, ea }; int i; - Py_ssize_t j, pos = 0; + Py_ssize_t j, pos = 0, list_len; if (from->attr) { - fromattrs=ATTR_STRUCT(from); - /* what to do with the original value of toattrs? */ - toattrs=(igraphmodule_i_attribute_struct*)calloc(1, sizeof(igraphmodule_i_attribute_struct)); - if (!toattrs) + fromattrs = ATTR_STRUCT(from); + + toattrs = (igraphmodule_i_attribute_struct*) calloc(1, sizeof(igraphmodule_i_attribute_struct)); + if (!toattrs) { IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); + } + IGRAPH_FINALLY(free, toattrs); + if (igraphmodule_i_attribute_struct_init(toattrs)) { PyErr_PrintEx(0); - free(toattrs); IGRAPH_ERROR("not enough memory to allocate attribute hashes", IGRAPH_ENOMEM); } - to->attr=toattrs; + IGRAPH_FINALLY(igraphmodule_i_attribute_struct_destroy, toattrs); for (i = 0; i < 3; i++) { - if (!copy_attrs[i]) + if (!copy_attrs[i]) { continue; + } if (!PyDict_Check(fromattrs->attrs[i])) { - toattrs->attrs[i]=fromattrs->attrs[i]; - Py_XINCREF(fromattrs->attrs[i]); - continue; + IGRAPH_ERRORF("expected dict in attribute hash at index %d", IGRAPH_EINVAL, i); } - - pos = 0; - while (PyDict_Next(fromattrs->attrs[i], &pos, &key, &value)) { - /* value is only borrowed, so copy it */ - if (i > 0) { - newval = PyList_New(PyList_Size(value)); - for (j = 0; j < PyList_Size(value); j++) { + + /* graph attributes are easy to copy because the dict is a key-value map */ + if (i == ATTRHASH_IDX_GRAPH) { + Py_XDECREF(toattrs->attrs[i]); /* we already had a pre-constructed dict there */ + toattrs->attrs[i] = PyDict_Copy(fromattrs->attrs[i]); + if (!toattrs->attrs[i]) { + PyErr_PrintEx(0); + IGRAPH_ERROR("cannot copy attribute hashes", IGRAPH_FAILURE); + } + } else { + /* vertex and edge attributes have to be copied in a way that values + * are also copied */ + pos = 0; + while (PyDict_Next(fromattrs->attrs[i], &pos, &key, &value)) { + /* value is only borrowed, so copy it */ + if (!PyList_Check(value)) { + IGRAPH_ERRORF("expected list in attribute hash at index %d", IGRAPH_EINVAL, i); + } + + list_len = PyList_Size(value); + newval = PyList_New(list_len); + for (j = 0; j < list_len; j++) { o = PyList_GetItem(value, j); Py_INCREF(o); PyList_SetItem(newval, j, o); } - } else { - newval = value; - Py_INCREF(newval); + + if (!newval) { + PyErr_PrintEx(0); + IGRAPH_ERROR("cannot copy attribute hashes", IGRAPH_FAILURE); + } + + if (PyDict_SetItem(toattrs->attrs[i], key, newval)) { + PyErr_PrintEx(0); + Py_DECREF(newval); + IGRAPH_ERROR("cannot copy attribute hashes", IGRAPH_FAILURE); + } + + Py_DECREF(newval); /* compensate for PyDict_SetItem */ } - PyDict_SetItem(toattrs->attrs[i], key, newval); - Py_DECREF(newval); /* compensate for PyDict_SetItem */ } } + + to->attr = toattrs; + IGRAPH_FINALLY_CLEAN(2); } + return IGRAPH_SUCCESS; } @@ -433,9 +518,9 @@ static igraph_error_t igraphmodule_i_attribute_copy(igraph_t *to, const igraph_t static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, igraph_vector_ptr_t *attr) { /* Extend the end of every value in the vertex hash with nv pieces of None */ PyObject *key, *value, *dict; - igraph_integer_t i, j, k, l; + igraph_integer_t i, j, k, num_attr_entries; igraph_attribute_record_t *attr_rec; - igraph_bool_t *added_attrs=0; + igraph_vector_bool_t added_attrs; Py_ssize_t pos = 0; if (!graph->attr) { @@ -446,14 +531,8 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr return IGRAPH_SUCCESS; } - if (attr) { - added_attrs = (igraph_bool_t*)calloc((size_t)igraph_vector_ptr_size(attr), - sizeof(igraph_bool_t)); - if (!added_attrs) { - IGRAPH_ERROR("can't add vertex attributes", IGRAPH_ENOMEM); - } - IGRAPH_FINALLY(free, added_attrs); - } + num_attr_entries = attr ? igraph_vector_ptr_size(attr) : 0; + IGRAPH_VECTOR_BOOL_INIT_FINALLY(&added_attrs, num_attr_entries); dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; if (!PyDict_Check(dict)) { @@ -467,16 +546,13 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr /* Check if we have specific values for the given attribute */ attr_rec = 0; - if (attr) { - j = igraph_vector_ptr_size(attr); - for (i = 0; i < j; i++) { - attr_rec = VECTOR(*attr)[i]; - if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { - added_attrs[i] = 1; - break; - } - attr_rec = 0; + for (i = 0; i < num_attr_entries; i++) { + attr_rec = VECTOR(*attr)[i]; + if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { + VECTOR(added_attrs)[i] = 1; + break; } + attr_rec = 0; } /* If we have specific values for the given attribute, attr_rec contains @@ -526,64 +602,61 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr /* Okay, now we added the new attribute values for the already existing * attribute keys. Let's see if we have something left */ - if (attr) { - l = igraph_vector_ptr_size(attr); - j = igraph_vcount(graph) - nv; - /* j contains the number of vertices EXCLUDING the new ones! */ - for (k = 0; k < l; k++) { - if (added_attrs[k]) { - continue; - } - attr_rec = (igraph_attribute_record_t*)VECTOR(*attr)[k]; + j = igraph_vcount(graph) - nv; + /* j contains the number of vertices EXCLUDING the new ones! */ + for (k = 0; k < num_attr_entries; k++) { + if (VECTOR(added_attrs)[k]) { + continue; + } + attr_rec = (igraph_attribute_record_t*)VECTOR(*attr)[k]; - value = PyList_New(j + nv); - if (!value) { - IGRAPH_ERROR("can't add attributes", IGRAPH_ENOMEM); - } + value = PyList_New(j + nv); + if (!value) { + IGRAPH_ERROR("can't add attributes", IGRAPH_ENOMEM); + } - for (i = 0; i < j; i++) { - Py_INCREF(Py_None); - PyList_SetItem(value, i, Py_None); - } + for (i = 0; i < j; i++) { + Py_INCREF(Py_None); + PyList_SetItem(value, i, Py_None); + } - for (i = 0; i < nv; i++) { - const char *s; - PyObject *o; - switch (attr_rec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); - break; - case IGRAPH_ATTRIBUTE_STRING: - s = igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i); - o = PyUnicode_FromString(s); - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; - Py_INCREF(o); - break; - default: - IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o = 0; - break; - } - if (o) { - PyList_SetItem(value, i + j, o); - } + for (i = 0; i < nv; i++) { + const char *s; + PyObject *o; + switch (attr_rec->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + break; + case IGRAPH_ATTRIBUTE_STRING: + s = igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i); + o = PyUnicode_FromString(s); + break; + case IGRAPH_ATTRIBUTE_BOOLEAN: + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + Py_INCREF(o); + break; + default: + IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); + o = 0; + break; } - - /* Invalidate the vertex name index if needed */ - if (!strcmp(attr_rec->name, "name")) { - igraphmodule_i_attribute_struct_invalidate_vertex_name_index(ATTR_STRUCT(graph)); + if (o) { + PyList_SetItem(value, i + j, o); } + } - PyDict_SetItemString(dict, attr_rec->name, value); - Py_DECREF(value); /* compensate for PyDict_SetItemString */ + /* Invalidate the vertex name index if needed */ + if (!strcmp(attr_rec->name, "name")) { + igraphmodule_i_attribute_struct_invalidate_vertex_name_index(ATTR_STRUCT(graph)); } - free(added_attrs); - IGRAPH_FINALLY_CLEAN(1); + PyDict_SetItemString(dict, attr_rec->name, value); + Py_DECREF(value); /* compensate for PyDict_SetItemString */ } + igraph_vector_bool_destroy(&added_attrs); + IGRAPH_FINALLY_CLEAN(1); + return IGRAPH_SUCCESS; } @@ -1594,7 +1667,7 @@ igraph_error_t igraphmodule_i_attribute_get_type(const igraph_t *graph, } /* Basic type check */ - if (!PyList_Check(o)) { + if (attrnum != ATTRHASH_IDX_GRAPH && !PyList_Check(o)) { IGRAPH_ERROR("attribute hash type mismatch", IGRAPH_EINVAL); } diff --git a/src/_igraph/attributes.h b/src/_igraph/attributes.h index e24a90c74..010ca4b63 100644 --- a/src/_igraph/attributes.h +++ b/src/_igraph/attributes.h @@ -85,8 +85,6 @@ void igraphmodule_index_vertex_names(igraph_t *graph, igraph_bool_t force); void igraphmodule_invalidate_vertex_name_index(igraph_t *graph); int igraphmodule_get_vertex_id_by_name(igraph_t *graph, PyObject* o, igraph_integer_t* id); -PyObject* igraphmodule_create_edge_attribute(const igraph_t* graph, - const char* name); PyObject* igraphmodule_create_or_get_edge_attribute_values(const igraph_t* graph, const char* name); PyObject* igraphmodule_get_edge_attribute_values(const igraph_t* graph, From ecfebc0179894ac3aaf0ef2536b33ef56fb91ed7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 09:14:52 +0200 Subject: [PATCH 1048/1892] refactor: more cleanup in attribute handling code [WIP] --- src/_igraph/attributes.c | 223 ++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 95 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 0fafbe573..cbbdca690 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -545,14 +545,14 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr } /* Check if we have specific values for the given attribute */ - attr_rec = 0; + attr_rec = NULL; for (i = 0; i < num_attr_entries; i++) { attr_rec = VECTOR(*attr)[i]; if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { VECTOR(added_attrs)[i] = 1; break; } - attr_rec = 0; + attr_rec = NULL; } /* If we have specific values for the given attribute, attr_rec contains @@ -560,7 +560,8 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr if (attr_rec) { for (i = 0; i < nv; i++) { const char *s; - PyObject *o; + PyObject *o = NULL; + switch (attr_rec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); @@ -575,16 +576,24 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o = 0; + o = Py_None; + Py_INCREF(o); break; } + if (o) { - if (PyList_Append(value, o) == -1) { - IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); + if (PyList_Append(value, o)) { + Py_DECREF(o); /* append failed */ + o = NULL; /* indicate error */ } else { - Py_DECREF(o); + Py_DECREF(o); /* drop reference, the list has it now */ } } + + if (!o) { + PyErr_PrintEx(0); + IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); + } } /* Invalidate the vertex name index if needed */ @@ -593,7 +602,8 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr } } else { for (i = 0; i < nv; i++) { - if (PyList_Append(value, Py_None) == -1) { + if (PyList_Append(value, Py_None)) { + PyErr_PrintEx(0); IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); } } @@ -603,11 +613,13 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr /* Okay, now we added the new attribute values for the already existing * attribute keys. Let's see if we have something left */ j = igraph_vcount(graph) - nv; + /* j contains the number of vertices EXCLUDING the new ones! */ for (k = 0; k < num_attr_entries; k++) { if (VECTOR(added_attrs)[k]) { continue; } + attr_rec = (igraph_attribute_record_t*)VECTOR(*attr)[k]; value = PyList_New(j + nv); @@ -622,7 +634,7 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr for (i = 0; i < nv; i++) { const char *s; - PyObject *o; + PyObject *o = NULL; switch (attr_rec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); @@ -637,11 +649,23 @@ static igraph_error_t igraphmodule_i_attribute_add_vertices(igraph_t *graph, igr break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o = 0; + o = Py_None; + Py_INCREF(o); break; } + if (o) { - PyList_SetItem(value, i + j, o); + if (PyList_SetItem(value, i + j, o)) { + Py_DECREF(o); /* append failed */ + o = NULL; /* indicate error */ + } else { + /* reference stolen by the list */ + } + } + + if (!o) { + PyErr_PrintEx(0); + IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); } } @@ -669,12 +693,12 @@ static igraph_error_t igraphmodule_i_attribute_permute_vertices(const igraph_t * dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_VERTEX]; if (!PyDict_Check(dict)) { - return 1; + IGRAPH_ERROR("vertex attribute hash type mismatch", IGRAPH_EINVAL); } newdict = PyDict_New(); if (!newdict) { - return 1; + IGRAPH_ERROR("cannot allocate new dict for vertex permutation", IGRAPH_ENOMEM); } n = igraph_vector_int_size(idx); @@ -685,17 +709,19 @@ static igraph_error_t igraphmodule_i_attribute_permute_vertices(const igraph_t * for (i = 0; i < n; i++) { o = PyList_GetItem(value, VECTOR(*idx)[i]); if (!o) { + PyErr_PrintEx(0); Py_DECREF(newlist); Py_DECREF(newdict); PyErr_Clear(); - return 1; + IGRAPH_ERROR("", IGRAPH_FAILURE); } Py_INCREF(o); if (PyList_SetItem(newlist, i, o)) { + PyErr_PrintEx(0); Py_DECREF(o); Py_DECREF(newlist); Py_DECREF(newdict); - return 1; + IGRAPH_ERROR("", IGRAPH_FAILURE); } } PyDict_SetItem(newdict, key, newlist); @@ -709,7 +735,7 @@ static igraph_error_t igraphmodule_i_attribute_permute_vertices(const igraph_t * /* Invalidate the vertex name index */ igraphmodule_i_attribute_struct_invalidate_vertex_name_index(ATTR_STRUCT(newgraph)); - return 0; + return IGRAPH_SUCCESS; } /* Adding edges */ @@ -717,8 +743,8 @@ static igraph_error_t igraphmodule_i_attribute_add_edges(igraph_t *graph, const /* Extend the end of every value in the edge hash with ne pieces of None */ PyObject *key, *value, *dict; Py_ssize_t pos = 0; - igraph_integer_t i, j, k, l, ne; - igraph_bool_t *added_attrs=0; + igraph_integer_t i, j, k, ne, num_attr_entries; + igraph_vector_bool_t added_attrs; igraph_attribute_record_t *attr_rec; if (!graph->attr) { @@ -730,14 +756,8 @@ static igraph_error_t igraphmodule_i_attribute_add_edges(igraph_t *graph, const return IGRAPH_SUCCESS; } - if (attr) { - added_attrs = (igraph_bool_t*)calloc((size_t)igraph_vector_ptr_size(attr), - sizeof(igraph_bool_t)); - if (!added_attrs) { - IGRAPH_ERROR("can't add vertex attributes", IGRAPH_ENOMEM); - } - IGRAPH_FINALLY(free, added_attrs); - } + num_attr_entries = attr ? igraph_vector_ptr_size(attr) : 0; + IGRAPH_VECTOR_BOOL_INIT_FINALLY(&added_attrs, num_attr_entries); dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; if (!PyDict_Check(dict)) { @@ -750,18 +770,16 @@ static igraph_error_t igraphmodule_i_attribute_add_edges(igraph_t *graph, const } /* Check if we have specific values for the given attribute */ - attr_rec = 0; - if (attr) { - j = igraph_vector_ptr_size(attr); - for (i = 0; i < j; i++) { - attr_rec = VECTOR(*attr)[i]; - if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { - added_attrs[i] = 1; - break; - } - attr_rec = 0; + attr_rec = NULL; + for (i = 0; i < num_attr_entries; i++) { + attr_rec = VECTOR(*attr)[i]; + if (igraphmodule_PyObject_matches_attribute_record(key, attr_rec)) { + VECTOR(added_attrs)[i] = 1; + break; } + attr_rec = NULL; } + /* If we have specific values for the given attribute, attr_rec contains * the appropriate vector. If not, it is null. */ if (attr_rec) { @@ -782,86 +800,99 @@ static igraph_error_t igraphmodule_i_attribute_add_edges(igraph_t *graph, const break; default: IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o = 0; + o = Py_None; + Py_INCREF(o); break; } + if (o) { - if (PyList_Append(value, o) == -1) { - IGRAPH_ERROR("can't extend an edge attribute hash member", IGRAPH_FAILURE); + if (PyList_Append(value, o)) { + Py_DECREF(o); /* append failed */ + o = NULL; /* indicate error */ } else { - Py_DECREF(o); + Py_DECREF(o); /* drop reference, the list has it now */ } } + + if (!o) { + PyErr_PrintEx(0); + IGRAPH_ERROR("can't extend an edge attribute hash member", IGRAPH_FAILURE); + } } } else { for (i = 0; i < ne; i++) { - if (PyList_Append(value, Py_None) == -1) { + if (PyList_Append(value, Py_None)) { + PyErr_PrintEx(0); IGRAPH_ERROR("can't extend an edge attribute hash member", IGRAPH_FAILURE); } } } } - /*pos=0; - while (PyDict_Next(dict, &pos, &key, &value)) { - printf("key: "); PyObject_Print(key, stdout, Py_PRINT_RAW); printf("\n"); - printf("value: "); PyObject_Print(value, stdout, Py_PRINT_RAW); printf("\n"); - }*/ - /* Okay, now we added the new attribute values for the already existing * attribute keys. Let's see if we have something left */ - if (attr) { - l = igraph_vector_ptr_size(attr); - j = igraph_ecount(graph) - ne; - /* j contains the number of edges EXCLUDING the new ones! */ - for (k = 0; k < l; k++) { - if (added_attrs[k]) { - continue; - } - attr_rec=(igraph_attribute_record_t*)VECTOR(*attr)[k]; + j = igraph_ecount(graph) - ne; + /* j contains the number of edges EXCLUDING the new ones! */ + for (k = 0; k < num_attr_entries; k++) { + if (VECTOR(added_attrs)[k]) { + continue; + } + attr_rec=(igraph_attribute_record_t*)VECTOR(*attr)[k]; - value = PyList_New(j + ne); - if (!value) { - IGRAPH_ERROR("can't add attributes", IGRAPH_ENOMEM); - } + value = PyList_New(j + ne); + if (!value) { + IGRAPH_ERROR("can't add attributes", IGRAPH_ENOMEM); + } - for (i = 0; i < j; i++) { - Py_INCREF(Py_None); - PyList_SetItem(value, i, Py_None); + for (i = 0; i < j; i++) { + Py_INCREF(Py_None); + PyList_SetItem(value, i, Py_None); + } + + for (i = 0; i < ne; i++) { + const char *s; + PyObject *o; + switch (attr_rec->type) { + case IGRAPH_ATTRIBUTE_NUMERIC: + o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); + break; + case IGRAPH_ATTRIBUTE_STRING: + s = igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i); + o = PyUnicode_FromString(s); + break; + case IGRAPH_ATTRIBUTE_BOOLEAN: + o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; + Py_INCREF(o); + break; + default: + IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); + o = Py_None; + Py_INCREF(o); + break; } - for (i = 0; i < ne; i++) { - const char *s; - PyObject *o; - switch (attr_rec->type) { - case IGRAPH_ATTRIBUTE_NUMERIC: - o = PyFloat_FromDouble((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]); - break; - case IGRAPH_ATTRIBUTE_STRING: - s = igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i); - o = PyUnicode_FromString(s); - break; - case IGRAPH_ATTRIBUTE_BOOLEAN: - o = VECTOR(*(igraph_vector_bool_t*)attr_rec->value)[i] ? Py_True : Py_False; - Py_INCREF(o); - break; - default: - IGRAPH_WARNING("unsupported attribute type (not string, numeric or Boolean)"); - o = 0; - break; - } - if (o) { - PyList_SetItem(value, i + j, o); + if (o) { + if (PyList_SetItem(value, i + j, o)) { + Py_DECREF(o); /* append failed */ + o = NULL; /* indicate error */ + } else { + /* reference stolen by the list */ } } - PyDict_SetItemString(dict, attr_rec->name, value); - Py_DECREF(value); /* compensate for PyDict_SetItemString */ + if (!o) { + PyErr_PrintEx(0); + IGRAPH_ERROR("can't extend a vertex attribute hash member", IGRAPH_FAILURE); + } } - free(added_attrs); - IGRAPH_FINALLY_CLEAN(1); + + PyDict_SetItemString(dict, attr_rec->name, value); + Py_DECREF(value); /* compensate for PyDict_SetItemString */ } + igraph_vector_bool_destroy(&added_attrs); + IGRAPH_FINALLY_CLEAN(1); + return IGRAPH_SUCCESS; } @@ -874,12 +905,12 @@ static igraph_error_t igraphmodule_i_attribute_permute_edges(const igraph_t *gra dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; if (!PyDict_Check(dict)) { - return 1; + IGRAPH_ERROR("edge attribute hash type mismatch", IGRAPH_EINVAL); } newdict = PyDict_New(); if (!newdict) { - return 1; + IGRAPH_ERROR("cannot allocate new dict for edge permutation", IGRAPH_ENOMEM); } n = igraph_vector_int_size(idx); @@ -888,19 +919,21 @@ static igraph_error_t igraphmodule_i_attribute_permute_edges(const igraph_t *gra while (PyDict_Next(dict, &pos, &key, &value)) { newlist = PyList_New(n); for (i = 0; i < n; i++) { - o=PyList_GetItem(value, VECTOR(*idx)[i]); + o = PyList_GetItem(value, VECTOR(*idx)[i]); if (!o) { + PyErr_PrintEx(0); Py_DECREF(newlist); Py_DECREF(newdict); PyErr_Clear(); - return 1; + IGRAPH_ERROR("", IGRAPH_FAILURE); } Py_INCREF(o); if (PyList_SetItem(newlist, i, o)) { + PyErr_PrintEx(0); Py_DECREF(o); Py_DECREF(newlist); Py_DECREF(newdict); - return 1; + IGRAPH_ERROR("", IGRAPH_FAILURE); } } PyDict_SetItem(newdict, key, newlist); @@ -911,7 +944,7 @@ static igraph_error_t igraphmodule_i_attribute_permute_edges(const igraph_t *gra ATTR_STRUCT_DICT(newgraph)[ATTRHASH_IDX_EDGE]=newdict; Py_DECREF(dict); - return 0; + return IGRAPH_SUCCESS; } /* Auxiliary function for combining vertices/edges. Given a merge list From a30ca7c19f38da2d995016d3c5d61e13c9955d33 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 15:42:41 +0200 Subject: [PATCH 1049/1892] refactor: finalized error checking improviements in attributes.c --- src/_igraph/attributes.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index cbbdca690..b5ba31af8 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1417,23 +1417,24 @@ static igraph_error_t igraphmodule_i_attribute_combine_dicts(PyObject *dict, /* Allocate memory for the attribute_combination_records */ n = PyDict_Size(dict); todo = (igraph_attribute_combination_record_t*)calloc( - n+1, sizeof(igraph_attribute_combination_record_t) + n + 1, sizeof(igraph_attribute_combination_record_t) ); if (todo == 0) { IGRAPH_ERROR("cannot allocate memory for attribute combination", IGRAPH_ENOMEM); } - for (i = 0; i < n+1; i++) + for (i = 0; i < n + 1; i++) { todo[i].name = 0; /* sentinel elements */ + } IGRAPH_FINALLY(igraphmodule_i_free_attribute_combination_records, todo); /* Collect what to do for each attribute in the source dict */ pos = 0; i = 0; while (PyDict_Next(dict, &pos, &key, &value)) { todo[i].name = PyUnicode_CopyAsString(key); - if (todo[i].name == 0) + if (todo[i].name == 0) { IGRAPH_ERROR("PyUnicode_CopyAsString failed", IGRAPH_FAILURE); - igraph_attribute_combination_query(comb, todo[i].name, - &todo[i].type, &todo[i].func); + } + IGRAPH_CHECK(igraph_attribute_combination_query(comb, todo[i].name, &todo[i].type, &todo[i].func)); i++; } @@ -1564,8 +1565,8 @@ static igraph_error_t igraphmodule_i_attribute_combine_edges(const igraph_t *gra PyObject *dict, *newdict; /* Get the attribute dicts */ - dict=ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; - newdict=ATTR_STRUCT_DICT(newgraph)[ATTRHASH_IDX_EDGE]; + dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_EDGE]; + newdict = ATTR_STRUCT_DICT(newgraph)[ATTRHASH_IDX_EDGE]; return igraphmodule_i_attribute_combine_dicts(dict, newdict, merges, comb); @@ -1599,13 +1600,13 @@ static igraph_error_t igraphmodule_i_attribute_get_info(const igraph_t *graph, if (n) { retval = igraphmodule_PyList_to_existing_strvector_t(keys, n); if (retval) { - return retval ? IGRAPH_FAILURE : IGRAPH_SUCCESS; + IGRAPH_ERROR("Cannot convert Python list to existing igraph_strvector_t", IGRAPH_FAILURE); } } if (t) { k = PyList_Size(keys); - igraph_vector_int_resize(t, k); + IGRAPH_CHECK(igraph_vector_int_resize(t, k)); for (j = 0; j < k; j++) { int is_numeric = 1; int is_string = 1; @@ -1763,8 +1764,9 @@ igraph_error_t igraphmodule_i_get_boolean_graph_attr(const igraph_t *graph, /* No error checking, if we get here, the type has already been checked by previous attribute handler calls... hopefully :) Same applies for the other handlers. */ o = PyDict_GetItemString(dict, name); - if (!o) + if (!o) { IGRAPH_ERROR("No such attribute", IGRAPH_EINVAL); + } IGRAPH_CHECK(igraph_vector_bool_resize(value, 1)); VECTOR(*value)[0] = PyObject_IsTrue(o); return IGRAPH_SUCCESS; @@ -1778,7 +1780,9 @@ igraph_error_t igraphmodule_i_get_numeric_graph_attr(const igraph_t *graph, /* No error checking, if we get here, the type has already been checked by previous attribute handler calls... hopefully :) Same applies for the other handlers. */ o = PyDict_GetItemString(dict, name); - if (!o) IGRAPH_ERROR("No such attribute", IGRAPH_EINVAL); + if (!o) { + IGRAPH_ERROR("No such attribute", IGRAPH_EINVAL); + } IGRAPH_CHECK(igraph_vector_resize(value, 1)); if (o == Py_None) { VECTOR(*value)[0] = IGRAPH_NAN; @@ -1801,8 +1805,9 @@ igraph_error_t igraphmodule_i_get_string_graph_attr(const igraph_t *graph, dict = ATTR_STRUCT_DICT(graph)[ATTRHASH_IDX_GRAPH]; o = PyDict_GetItemString(dict, name); - if (!o) + if (!o) { IGRAPH_ERROR("No such attribute", IGRAPH_EINVAL); + } IGRAPH_CHECK(igraph_strvector_resize(value, 1)); /* For Python 3.x, we simply call PyObject_Str, which produces a @@ -1815,8 +1820,9 @@ igraph_error_t igraphmodule_i_get_string_graph_attr(const igraph_t *graph, Py_INCREF(str); } else { PyObject* unicode = PyObject_Str(o); - if (unicode == 0) + if (unicode == 0) { IGRAPH_ERROR("Internal error in PyObject_Str", IGRAPH_EINVAL); + } str = PyUnicode_AsEncodedString(unicode, "utf-8", "xmlcharrefreplace"); Py_DECREF(unicode); } From 70d66c41eddab5cee614a0a2cc6f681c8a5f12bb Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 15:46:29 +0200 Subject: [PATCH 1050/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 2 +- src/igraph/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c10c1e249..a840c3526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.1] - 2022-09-12 ### Added diff --git a/src/igraph/version.py b/src/igraph/version.py index e51845b97..619ee99bb 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 0) +__version_info__ = (0, 10, 1) __version__ = ".".join("{0}".format(x) for x in __version_info__) From c3df47ef9e0908975c1d8a401786f15f7cdbe8f3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 16:37:07 +0200 Subject: [PATCH 1051/1892] chore: trigger build From 7d05b17e0fa7f0ca6d81142a5f3b77bd6eb5e111 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 19:52:59 +0200 Subject: [PATCH 1052/1892] fix: make sure that Clustering.sizes() handles None items in membership vector gracefully, closes #550 --- src/igraph/clustering.py | 3 ++- tests/test_decomposition.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index fe438f22e..33a4a7bd0 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -140,7 +140,8 @@ def sizes(self, *args): """ counts = [0] * len(self) for x in self._membership: - counts[x] += 1 + if x is not None: + counts[x] += 1 if args: return [counts[idx] for idx in args] diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index f2b37dfc4..8a217c99c 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -140,6 +140,10 @@ def testClusterGraph(self): self.assertTrue(clg.vs["string"] == ["aaa", "bbc", "ccab"]) self.assertTrue(clg.vs["int"] == [41, 64, 47]) + def testSizesWithNone(self): + cl = VertexClustering(self.graph, [0, 0, 0, None, 1, 1, 2, None, 2, None]) + self.assertTrue(cl.sizes() == [3, 2, 2]) + class CoverTests(unittest.TestCase): def setUp(self): From 5283d4cd240b01019f63d9926ce17276557f6c34 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 19:56:18 +0200 Subject: [PATCH 1053/1892] refactor: get rid of old Python 2.x-style calling convention for superclass constructors --- src/igraph/__init__.py | 4 ++-- src/igraph/app/shell.py | 2 +- src/igraph/clustering.py | 10 +++++----- src/igraph/cut.py | 2 +- src/igraph/drawing/cairo/dendrogram.py | 2 +- src/igraph/drawing/cairo/graph.py | 2 +- src/igraph/drawing/colors.py | 10 +++++----- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 026f9a149..9c545f8ed 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -436,9 +436,9 @@ def __init__(self, *args, **kwds): # Initialize the graph if ptr: - GraphBase.__init__(self, __ptr=ptr) + super().__init__(__ptr=ptr) else: - GraphBase.__init__(self, nverts, edges, directed) + super().__init__(nverts, edges, directed) # Set the graph attributes for key, value in graph_attrs.items(): diff --git a/src/igraph/app/shell.py b/src/igraph/app/shell.py index 40c41f74c..866eb7800 100644 --- a/src/igraph/app/shell.py +++ b/src/igraph/app/shell.py @@ -336,7 +336,7 @@ def __init__(self): Imports IDLE's embedded shell. The implementation of this method is ripped from idlelib.PyShell.main() after removing the unnecessary parts.""" - Shell.__init__(self) + super().__init__() import idlelib.PyShell diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 33a4a7bd0..b9859ae29 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -234,11 +234,11 @@ def __init__( containing a C{weight} key with the appropriate value here. """ if membership is None: - Clustering.__init__(self, [0] * graph.vcount(), params) + super().__init__([0] * graph.vcount(), params) else: if len(membership) != graph.vcount(): raise ValueError("membership list has invalid length") - Clustering.__init__(self, membership, params) + super().__init__(membership, params) self._graph = graph self._modularity = modularity @@ -805,7 +805,7 @@ def __init__( original graph was weighted, you should pass a dictionary containing a C{weight} key with the appropriate value here. """ - Dendrogram.__init__(self, merges) + super().__init__(merges) self._graph = graph self._optimal_count = optimal_count if modularity_params is None: @@ -1082,7 +1082,7 @@ def __init__(self, graph, clusters=None): if clusters is None: clusters = [range(graph.vcount())] - Cover.__init__(self, clusters, n=graph.vcount()) + super().__init__(clusters, n=graph.vcount()) if self._n > graph.vcount(): raise ValueError( "cluster list contains vertex ID larger than the " @@ -1247,7 +1247,7 @@ def __init__(self, graph, blocks=None, cohesion=None, parent=None): if blocks is None or cohesion is None or parent is None: blocks, cohesion, parent = graph.cohesive_blocks() - VertexCover.__init__(self, graph, blocks) + super().__init__(graph, blocks) self._cohesion = cohesion self._parent = parent diff --git a/src/igraph/cut.py b/src/igraph/cut.py index 4cf62d937..cca6e6093 100644 --- a/src/igraph/cut.py +++ b/src/igraph/cut.py @@ -63,7 +63,7 @@ def __init__(self, graph, value=None, cut=None, partition=None, partition2=None) membership = [1] * graph.vcount() for vid in partition: membership[vid] = 0 - VertexClustering.__init__(self, graph, membership) + super().__init__(graph, membership) if value is None: # Value of the cut not given, count the number of edges diff --git a/src/igraph/drawing/cairo/dendrogram.py b/src/igraph/drawing/cairo/dendrogram.py index 27c225ea9..c1dc06db8 100644 --- a/src/igraph/drawing/cairo/dendrogram.py +++ b/src/igraph/drawing/cairo/dendrogram.py @@ -23,7 +23,7 @@ def __init__(self, context, bbox, palette): @param palette: the palette that can be used to map integer color indices to colors when drawing vertices """ - AbstractCairoDrawer.__init__(self, context, bbox) + super().__init__(context, bbox) self.palette = palette @staticmethod diff --git a/src/igraph/drawing/cairo/graph.py b/src/igraph/drawing/cairo/graph.py index 123aee230..3605bbda2 100644 --- a/src/igraph/drawing/cairo/graph.py +++ b/src/igraph/drawing/cairo/graph.py @@ -108,7 +108,7 @@ def __init__( Cairo context. The default label drawer is L{CairoTextDrawer}. """ - AbstractCairoGraphDrawer.__init__(self, context, bbox) + super().__init__(context, bbox) self.vertex_drawer_factory = vertex_drawer_factory self.edge_drawer_factory = edge_drawer_factory self.label_drawer_factory = label_drawer_factory diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 72813dc4b..67d226d97 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -195,7 +195,7 @@ def __init__(self, color1, color2, n=256): @param color2: the color where the gradient ends. @param n: the number of colors in the palette. """ - Palette.__init__(self, n) + super().__init__(n) self._color1 = color_name_to_rgba(color1) self._color2 = color_name_to_rgba(color2) @@ -230,7 +230,7 @@ def __init__(self, colors, indices=None, n=256): C{None}, the colors are distributed equidistantly @param n: the total number of colors in the palette """ - Palette.__init__(self, n) + super().__init__(n) if indices is None: diff = float(n - 1) / (len(colors) - 1) @@ -306,7 +306,7 @@ def __init__(self, n=256, s=1, v=1, start=0, end=1, alpha=1): @param end: the hue at which the rainbow ends (between 0 and 1). @param alpha: the alpha component of the colors in the palette. """ - Palette.__init__(self, n) + super().__init__(n) self._s = float(clamp(s, 0, 1)) self._v = float(clamp(v, 0, 1)) self._alpha = float(clamp(alpha, 0, 1)) @@ -331,7 +331,7 @@ def __init__(self, items): RGBA quadruplets or color names, which will be resolved first by L{color_name_to_rgba()}. Anything that is understood by L{color_name_to_rgba()} is OK here.""" - Palette.__init__(self, len(items)) + super().__init__(len(items)) for idx, color in enumerate(items): if isinstance(color, str): color = color_name_to_rgba(color) @@ -381,7 +381,7 @@ def __init__(self, n): adding_darker = not adding_darker colors = colors[0:n] - PrecalculatedPalette.__init__(self, colors) + super().__init__(colors) def clamp(value, min_value, max_value): From 1b7649896ed9c34503a99b2b211337e0145f53e6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Sep 2022 19:56:59 +0200 Subject: [PATCH 1054/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a840c3526..7c4199d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- `Clustering.sizes()` now works correctly even if the membership vector + contains `None` items. + ## [0.10.1] - 2022-09-12 ### Added @@ -370,7 +377,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.0...master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.1...master +[0.10.1]: https://github.com/igraph/python-igraph/compare/0.10.0...0.10.1 [0.10.0]: https://github.com/igraph/python-igraph/compare/0.9.11...0.10.0 [0.9.11]: https://github.com/igraph/python-igraph/compare/0.9.10...0.9.11 [0.9.10]: https://github.com/igraph/python-igraph/compare/0.9.9...0.9.10 From c6dbbd95bb75e45c3f709bb7dd2b00b27d4daa67 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 14 Sep 2022 15:00:57 +0200 Subject: [PATCH 1055/1892] doc: update docstring of personalized_pagerank() so it no longer mentions niter and eps, fixes #568 --- src/_igraph/graphobject.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e95da47d9..f937f5267 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13457,13 +13457,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " igraph uses the original implementation of Fabien Viger; see the\n" " following URL and the paper cited on it for the details of the\n" " algorithm: U{https://www-complexnetworks.lip6.fr/~latapy/FV/generation.html}.\n" - " \n" - " Legacy names that were valid before igraph 0.10 are also supported, but\n" - " these may be removed without further notice:\n" - " \n" - " - C{\"simple\"} -- equivalent to C{\"configuration\"}" - " - C{\"no_multiple\"} -- equivalent to C{\"fast_heur_simple\"}" - " - C{\"no_multiple_uniform\"} -- equivalent to C{\"configuration_simple\"}\n" }, /* interface to igraph_isoclass_create */ @@ -14388,8 +14381,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "personalized_pagerank(vertices=None, directed=True, damping=0.85,\n" " reset=None, reset_vertices=None, weights=None, \n" - " arpack_options=None, implementation=\"prpack\", niter=1000,\n" - " eps=0.001)\n--\n\n" + " arpack_options=None, implementation=\"prpack\")\n--\n\n" "Calculates the personalized PageRank values of a graph.\n\n" "The personalized PageRank calculation is similar to the PageRank\n" "calculation, but the random walk is reset to a non-uniform distribution\n" @@ -14424,10 +14416,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " implementation in igraph 0.7\n\n" " - C{\"arpack\"}: use the ARPACK library. This implementation\n" " was used from version 0.5, until version 0.7.\n\n" - "@param niter: unused, kept for sake of backwards compatibility. It will\n" - " be removed in igraph 0.10.\n" - "@param eps: unused, kept for sake of backwards compatibility. It will\n" - " be removed in igraph 0.10.\n" "@return: a list with the personalized PageRank values of the specified\n" " vertices.\n"}, From 73676b3f19c26e993c78ed36e0fd8d0bce424993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Thu, 15 Sep 2022 15:01:53 +0200 Subject: [PATCH 1056/1892] docs: fix redirect URL for Dash docset --- scripts/mkdoc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 9ef7e52ee..878f81192 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -117,7 +117,7 @@ if [ "x$DOC2DASH" = "x1" ]; then if [ "x$DOC2DASH" != x ]; then echo "Generating Dash docset..." "$DOC2DASH" \ - --online-redirect-url "https://igraph.org/python/api" \ + --online-redirect-url "https://igraph.org/python/api/latest" \ --name "python-igraph" \ -d "${DASH_FOLDER}" \ -f \ From 408e4c3a6306d1ac5cf2995cba18982a5d199e58 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 15 Sep 2022 20:41:15 +0200 Subject: [PATCH 1057/1892] feat: scripts/mkdoc.sh now installs doc2dash if needed [ci skip] --- scripts/mkdoc.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 878f81192..0636e9de7 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -46,12 +46,16 @@ cd ${ROOT_FOLDER} if [ ! -d ".venv" ]; then python3 -m venv .venv - # Install sphinx, matplotlib, wheel, and pydoctor into the venv + # Install sphinx, matplotlib, wheel and pydoctor into the venv. + # doc2dash is optional; it will be installed when -d is given .venv/bin/pip install -U pip sphinx sphinxbootstrap4theme matplotlib wheel pydoctor fi -# Make sure that Sphinx and PyDoctor are up-to-date in the virtualenv +# Make sure that Sphinx, PyDoctor (and maybe doc2dash) are up-to-date in the virtualenv .venv/bin/pip install -U sphinx pydoctor +if [ x$DOC2DASH = x1 ]; then + .venv/bin/pip install -U doc2dash +fi #echo "Set PyDoctor theme" #$SCRIPTS_FOLDER/set-pydoctor-theme.sh ${ROOT_FOLDER} ${STANDALONE} From d300379aa92894b3a90840532e3eaab87051b9ad Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 15 Sep 2022 20:41:26 +0200 Subject: [PATCH 1058/1892] chore: added doc/dash/ to .gitignore [ci skip] --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ef7ad00fd..af835ecb6 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,6 @@ vendor/install/ doc/source/gallery.rst doc/api/ +doc/dash/ doc/html/ doc/jekyll_tools/vendor From 6e770af67d290482c2e48cacd7c36eeaad316625 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 18 Sep 2022 19:19:00 +0200 Subject: [PATCH 1059/1892] fix: fix ownership transfer in igraphmodule_graph_list_t_to_PyList(), closes #570 --- src/_igraph/convert.c | 42 ++++++++++++++++++++++--------------- src/_igraph/convert.h | 2 +- tests/test_decomposition.py | 23 ++++++++++++++++++++ 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 5bc77a65d..90f76275a 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2495,41 +2495,49 @@ PyObject* igraphmodule_vector_int_list_t_to_PyList_of_tuples(const igraph_vector * will destroy each graph inside, which in turns destroys the vertices and edges * data structures that are now supposedly managed by Python. * - * \param v the \c igraph_graph_list_t containing the list to be converted + * \param v the \c igraph_graph_list_t containing the list to be converted; the + * list will become empty after executing this function * \param type the GraphBase subclass you want your graphs to use. When called from * a GraphBase method, this is typically Py_TYPE(self) * \return the Python list as a \c PyObject*, or \c NULL if an error occurred */ -PyObject* igraphmodule_graph_list_t_to_PyList(const igraph_graph_list_t *v, PyTypeObject* type) { +PyObject* igraphmodule_graph_list_t_to_PyList(igraph_graph_list_t *v, PyTypeObject* type) { PyObject *list; Py_ssize_t n, i; - igraph_t *g; + igraph_t g; igraphmodule_GraphObject *o; /* We have to create a Python igraph object for every graph returned */ n = igraph_graph_list_size(v); list = PyList_New(n); - for (i = 0; i < n; i++) { - /* Python takes ownership of vertices and nodes here */ - g = igraph_graph_list_get_ptr(v, i); - o = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t(type, g); + for (i = n - 1; i >= 0; i--) { + /* Remove the last graph from the list and take ownership of it temporarily */ + if (igraph_graph_list_remove(v, i, &g)) { + igraphmodule_handle_igraph_error(); + Py_DECREF(list); + return NULL; + } + + /* Transfer ownership of the graph to Python */ + o = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t(type, &g); + if (o == NULL) { + igraph_destroy(&g); + Py_DECREF(list); + return NULL; + } + /* Put the graph into the result list; the list will take ownership */ if (PyList_SetItem(list, i, (PyObject *) o)) { Py_DECREF(o); Py_DECREF(list); - return 0; + return NULL; } } - /* Now we know the function went fine, so we can free pointers without worrying - * that we won't be able to find them again */ - - /* reference has been transferred by PyList_SetItem, no need to DECREF. - * - * we mustn't call igraph_destroy here, because it would free the vertices - * and the edges as well, but we need them in o->g. So just call free */ - for (i = 0; i < n; i++) { - free(igraph_graph_list_get_ptr(v, i)); + if (!igraph_graph_list_empty(v)) { + PyErr_SetString(PyExc_RuntimeError, "expected empty graph list after conversion"); + Py_DECREF(list); + return NULL; } return list; diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index f24eaf517..7f240e0e7 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -168,7 +168,7 @@ PyObject* igraphmodule_vector_int_ptr_t_to_PyList(const igraph_vector_ptr_t *v); PyObject* igraphmodule_vector_list_t_to_PyList(const igraph_vector_list_t *v); PyObject* igraphmodule_vector_int_list_t_to_PyList(const igraph_vector_int_list_t *v); PyObject* igraphmodule_vector_int_list_t_to_PyList_of_tuples(const igraph_vector_int_list_t *v); -PyObject* igraphmodule_graph_list_t_to_PyList(const igraph_graph_list_t *v, PyTypeObject *type); +PyObject* igraphmodule_graph_list_t_to_PyList(igraph_graph_list_t *v, PyTypeObject *type); PyObject* igraphmodule_vector_int_t_to_PyList(const igraph_vector_int_t *v); PyObject* igraphmodule_matrix_t_to_PyList(const igraph_matrix_t *m, igraphmodule_conv_t type); diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 8a217c99c..b3e864699 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -44,6 +44,29 @@ def testSubgraphEdges(self): class DecompositionTests(unittest.TestCase): + def testDecomposeUndirected(self): + g = Graph([(0, 1), (1, 2), (2, 3)], n=4, directed=False) + components = g.decompose() + + assert len(components) == 1 + assert components[0].isomorphic(g) + + g = Graph.Full(5) + Graph.Full(3) + components = g.decompose() + + assert len(components) == 2 + assert components[0].isomorphic(Graph.Full(5)) + assert components[1].isomorphic(Graph.Full(3)) + + def testDecomposeDirected(self): + g = Graph([(0, 1), (1, 2), (2, 3)], n=4, directed=True) + components = g.decompose() + + g1 = Graph(1, directed=True) + assert len(components) == 4 + for component in components: + assert component.isomorphic(g1) + def testKCores(self): g = Graph( 11, From c085cec54bfcebb4f8725521984f0c64f2333ccd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 18 Sep 2022 19:19:49 +0200 Subject: [PATCH 1060/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c4199d88..c370ac90d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Fixed +- Fixed a crash in `Graph.decompose()` that was accidentally introduced in + 0.10.0 during the transition to `igraph_graph_list_t` in the C core. + - `Clustering.sizes()` now works correctly even if the membership vector contains `None` items. From 17d28aa2fc4ad09cdf5f8e9f0c21bfebc41f3729 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 19 Sep 2022 08:51:14 +0200 Subject: [PATCH 1061/1892] ci: pinning Matplotlib temporarily to 3.5 to see if it resolves CI failures --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7a27c0525..792f47a6a 100644 --- a/setup.py +++ b/setup.py @@ -899,7 +899,7 @@ def get_tag(self): "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", - "matplotlib>=3.3.4; platform_python_implementation != 'PyPy'", + "matplotlib>=3.3.4,<3.6; platform_python_implementation != 'PyPy'", "plotly>=5.3.0", # matplotlib requires Pillow; however, Pillow >= 8.4 does not # provide manylinux2010 wheels any more, but we need those in From 749cebeacc6288d294efbdf6bf31a13b57e8c9a1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 20 Sep 2022 23:12:03 +0200 Subject: [PATCH 1062/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b5ebda267..53f79ce3f 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b5ebda26702efbd510d91d7ccc1b38deea1e8ed1 +Subproject commit 53f79ce3fd3cca903eb6d4402f26cd9357576f9a From a2460c1b16348d9590a7961bb6fea5a637076fca Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 21 Sep 2022 10:25:56 +0200 Subject: [PATCH 1063/1892] fix: fix linking to libxml2 with new igraph.pc format --- setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 792f47a6a..3699ecef2 100644 --- a/setup.py +++ b/setup.py @@ -306,7 +306,12 @@ def _parse_pkgconfig_file(self, filename: Path) -> List[str]: libraries.extend( word[2:] for word in words if word.startswith("-l") ) - + # Remap known library names in Requires and Requires.private with + # prior knowledge -- we don't want to rebuild pkg-config in Python + if line.startswith("Requires: ") or line.startswith("Requires.private: "): + for word in line.strip().split(): + if word.startswith("libxml-"): + libraries.append("xml2") if not libraries: # Educated guess libraries = ["igraph"] From d98fb7dd25cfe4fddb7e05661ff726e52a5ad792 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 24 Sep 2022 19:57:11 +0200 Subject: [PATCH 1064/1892] doc: fix broken API referenc link from tutorial to API on the homepage --- doc/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/index.rst b/doc/source/index.rst index 20edc1e1c..0b1226cb1 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -82,7 +82,7 @@ Documentation **Reference** - - :doc:`api/index` + - :doc:`../../api/latest/index` - `Source code `_ .. container:: From e2c0b264a867fb59e9b3bd15d2eb79b138cc85e7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 24 Sep 2022 19:57:29 +0200 Subject: [PATCH 1065/1892] fix: looks like the tests work again with Matplotlib 3.6 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3699ecef2..ca516ecd5 100644 --- a/setup.py +++ b/setup.py @@ -904,7 +904,7 @@ def get_tag(self): "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", - "matplotlib>=3.3.4,<3.6; platform_python_implementation != 'PyPy'", + "matplotlib>=3.3.4; platform_python_implementation != 'PyPy'", "plotly>=5.3.0", # matplotlib requires Pillow; however, Pillow >= 8.4 does not # provide manylinux2010 wheels any more, but we need those in From c3aaafd89dd0b8a6639a5be6f9fab17360969970 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 24 Sep 2022 20:01:27 +0200 Subject: [PATCH 1066/1892] doc: fix more broken links [ci skip] --- doc/source/analysis.rst | 2 +- doc/source/generation.rst | 2 +- doc/source/visualisation.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 2782fb663..d9e23869e 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -443,4 +443,4 @@ Flow and cuts are closely related, therefore you might find the following functi - :meth:`Graph.edge_connectivity` or :meth:`Graph.edge_disjoint_paths` or :meth:`Graph.adhesion` - :meth:`Graph.vertex_connectivity` or :meth:`Graph.cohesion` -.. _API documentation: https://igraph.org/python/doc/igraph-module.html +.. _API documentation: https://igraph.org/python/api/latest/ diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 3fdef2d5d..34cb8d64e 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -209,4 +209,4 @@ Finally, there are some ways of generating graphs that are not covered by the pr - small graphs of any "isomorphism class" :meth:`Graph.Isoclass` - graphs with a specified degree sequence :meth:`Graph.Realize_Degree_Sequence` -.. _API documentation: https://igraph.org/python/doc/igraph-module.html +.. _API documentation: https://igraph.org/python/api/latest/ diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index de7e8de6f..e766a1cd3 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -223,7 +223,7 @@ You can also specify vertex and edge color, size, and labels - and more - via ad See the `tutorial`_ for examples and a full list of options. -.. _API documentation: https://igraph.org/python/doc/igraph-module.html +.. _API documentation: https://igraph.org/python/api/latest/ .. _matplotlib: https://matplotlib.org .. _Jupyter: https://jupyter.org/ .. _tutorial: https://igraph.org/python/doc/tutorial/tutorial.html#layouts-and-plotting From 6b3113fdbe6dcb2dc4963877f4a817ab7d53eea3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 25 Sep 2022 11:10:42 +0200 Subject: [PATCH 1067/1892] test: update Matplotlib testing utils for Matplotlib 3.6.0 --- setup.py | 4 ++-- tests/drawing/matplotlib/utils.py | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index ca516ecd5..5767e6e82 100644 --- a/setup.py +++ b/setup.py @@ -889,7 +889,7 @@ def get_tag(self): "cairo": ["cairocffi>=1.2.0"], # Dependencies needed for plotting with Matplotlib - "matplotlib": ["matplotlib>=3.3.0; platform_python_implementation != 'PyPy'"], + "matplotlib": ["matplotlib>=3.6.0; platform_python_implementation != 'PyPy'"], # Dependencies needed for plotting with Plotly "plotly": ["plotly>=5.3.0"], @@ -904,7 +904,7 @@ def get_tag(self): "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", - "matplotlib>=3.3.4; platform_python_implementation != 'PyPy'", + "matplotlib>=3.6.0; platform_python_implementation != 'PyPy'", "plotly>=5.3.0", # matplotlib requires Pillow; however, Pillow >= 8.4 does not # provide manylinux2010 wheels any more, but we need those in diff --git a/tests/drawing/matplotlib/utils.py b/tests/drawing/matplotlib/utils.py index c9872a2fd..f9f195940 100644 --- a/tests/drawing/matplotlib/utils.py +++ b/tests/drawing/matplotlib/utils.py @@ -7,7 +7,7 @@ try: import matplotlib - from matplotlib.testing.decorators import _ImageComparisonBase + from matplotlib.testing.decorators import _collect_new_figures, _ImageComparisonBase from matplotlib.testing.compare import comparable_formats import matplotlib.pyplot as plt except ImportError: @@ -53,15 +53,16 @@ def wrapper(*args, **kwargs): ) matplotlib.testing.set_font_settings_for_testing() - func(*args, **kwargs) + with _collect_new_figures() as figs: + func(*args, **kwargs) - assert len(plt.get_fignums()) == len( + assert len(figs) == len( baseline_images ), "Test generated {} images but there are {} baseline images".format( - len(plt.get_fignums()), len(baseline_images) + len(figs), len(baseline_images) ) - for idx, baseline in enumerate(baseline_images): - img.compare(idx, baseline, _default_extension, _lock=False) + for fig, baseline in zip(figs, baseline_images): + img.compare(fig, baseline, _default_extension, _lock=False) parameters = list(old_sig.parameters.values()) new_sig = old_sig.replace(parameters=parameters) From df6f08450dc895ecb46b2d74d74ad4446211e490 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 25 Sep 2022 11:11:04 +0200 Subject: [PATCH 1068/1892] test: update expected images for Matplotlib 3.6.0 --- .../test_graph/clustering_directed.png | Bin 35633 -> 36425 bytes .../test_graph/clustering_directed_large.png | Bin 60787 -> 60676 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index c2dd4cc65ced7ca3d0e2eedd132c68521ab32fab..bd2235aa56e1f2decda6b0d4907ddc8817eaed1f 100644 GIT binary patch literal 36425 zcmeFZhf|bW^DR7NkvJ$hI-n>ys6+`m2!fy@IR{BfW=N7nk_d=Ii6U7*qU1aXC`rjm z8gh<9j^BRpocI3Ty0^Z6;9jdv9m|?|p1pf_uU@^n_k=uFkte&za1jQBkv&jAs={D+ zY%mzE)&)ZFF9|NM?7{!UP;y$Rr*`HjS7S#rn6fd--r5djZDqpdV&>>%WoIkQcbiXu zhs_d&vUd{a=ePOK2l(t9E%@(zdP)W!LTs;~?F55S7(@TzU+ zu5M~(g!om8 z2ETp1VULy9ia#hFA-j4t$on!a+7Iusf%n4cuU|il*|!&P?gh#yzBzCTBFEU{pZ4$| zs9rGz8q;Y6QNrQ5>fTbGr(&H+#7=WEPvD}-KfiKsFPYHYRNV4@yj&=kgN zdK+#ZeSGKyaSwO=Q|?^h`f(;kita4&t~)SA6JqD@cyvyz|Gv~MPSP!TDUhu1Vo0z8 zbFMFV$d0$JI4R!yDC1F4(K)){u&?5iR}K#51`AVt0s}~lC!`b<1VY ze@%t7^Lbcsa99p_rvheXmf1j@Df}KcvuUeLN2~^?wJ2Jk!t!LFokt6%Tagen^+=qU zukNyn*f+@r1fsY7e5pPI8sdZ$Qe|~Nx-+LEtVhgaBM-1$CcSkMqmCqcE+52fl#m&b zsyJ{se4?Z4j+*#fkBCy+yDLG8@}V>uoTT{!d6Ux-U1z*HWxmT_{Fe)Zc2^5jt|6%G zxd0SQF^Y)=DYivOe@6A2&#Pd4(hKWfy}4Mqao0)x8Ac{AD&(KwxT&W?{xH=$2UV$O zzDOsb0oKAKY83m9Ubu7M(^D0{Hdc`~($L`7qSVl_r?SU{J4_pGTgHSR=H$O-_4c*u z>l}zw;tvR7d6mHdJ$63~GAYwocQSbYD}tc7aMN(Vxvl~gOFL@njc>FYgSwAZaYe>2 zxK1!v6K%_7Jb4QC82M*)*dYgXyd9-2uBu92fXYGb8$5|TXxNiyl`S>j7 zd$OOdjZ{>`M9O3MeSUo-m225Oe`NZKHMaUPk&?U?9Vw%^O5yWond!Z&bET=?QwQ|I z`%>(9zOgEtHyU9PLFO{}j|o=@dXrUR@xHN8@MT8{-;bE97VgFjH~Bm4o96ZV;caYn zZ2YzmFvhLLl9$;mAI-zz#FSu*k*x^s<;RO!m6XkB3d6;XdCmjboU+=aGtd1i{GIW# zyW@3l9mT79r;T}j66~jQO%e+Ei8U(m(Y_e9eaXqOF@)`&K2s4R$d=Z)(c5dZq!t|P zyEpE?Iqh}Egh1eY#6=*eemv)9Mh60y@6WlfDNe3a;=&u1tzu^CayyF5f7y42P%0Lu zlPJYibiZAIuCI`_aLh|&>=Kn{Y{j3ou{n+Wx1??uoXU9?r;en5g5h<->Ig+lxLl~3 z`19-B{PXK}wN01S8+wd_{6!>L4v#iA=W#VF^=3qqC0%v~j%PcCy&4#%ToR{WPIz8Y zk)oH{hnbjo9)T5lXFw~wSZ*VsCQieDTd8eh68NWB$&%laJg`ANHVSR9T;1Y=vx-dIov>(yr`FR`xz3Urz(Chk_) z*87md;jECm7DpB6f_+|9QWIbLm|vR|wO;9;$*n0gGHt8{OZB*BAC7LCx%6mecEoP4 zCpw>50`sNjV_84X6@Q|mQ!ymcQ-J`9t8s8rvcx^Am1|aro$?O(&!(56pA&Zx)(N z6sP;7$Rk^nAlPU!>4*h5rWAKK>RM1C2*Q3PD|a#f!pc{360TcOZPRgh^Umt9ZP%)W z)TGX#N0O7N1zJX5d`I2bZ`#>@dA(p%9gKekicoHwanBr7M&^giX^di9Fr16oz-_-v z%=HzH?x^_AoJ8{X(tVvl!cIeB-bOa^+V#7QY+zJN8fy~j) z(7jC4-$Gb2ldhQXoa=d){usE+5hR};TXc_BM9}7wKSd+6qoxe%_7@4Hvww8n)V#}A zLwdR=eI^wbtZ+xW3c-u$b?esju~}ahSjxc`z!c0bR}6Urz0Y(Q zU7n_J&vdc)4`VJr6+YVR6cp82-HyhY)Cc3n>4-!N+1}nxRp86`5PW!AO}F05WWO`U z!_0m^K9l{HdL}!p#B~+1IqKxjSlPZL@U@cFjZ5hLEB=O-MbzQmcK|^NFFHx6`E)X{ zYzV5$Wdusd7F~HRW(rB8l-0+J7jiN`e1OI3Vbl3qaVg?rOQg6%$4^;e7^w;N#)yUt zDJsSYd+y9n%wK}%;z0%t94?xCyx86@pw!kLX}+kSJiysSqo~`Ea+{Af#I|DK$@3W1 z9VZ?0tTU1eGJ9)tTb^9g)0Xvr0K}2f@a>(b8LHHdM zbasM+m{lxAy=AhB4ewXOn)p$by-`%MvULtlw+#=htwBF+9G42FgaCS^uP$%RQBiCJPLW;y&o*<13cmy$rdm*L99k3F%97+Eg# z?9}lW{Q?q7Mv}czQ z%bls*Z=r&u?APTt*Ko^g#z6YBvUwMM*$FW?aY|^~)|~TXa1I`M{~olCwn)XcZ?x#2 zX@+?@lBZ%Hi&ek>soy%!*C@}h5@ z%rqSnj|soOB%@7F|NA%3NPY6GZaD@v2RpNHF4FO&XlZTv`Sl)AUb=6G*%x0u_e|~k z=A8nC^nl371GAg(6DhR?u_j0h33v4hKEJH@GPkM#nVJ4X^s&bMml`x3B_&#^aY5Nj zo$}ArE;C2HcN63eJtHY`Vl!)8=A(^Eazlh0xu>(TQn-%dfT-ZFg$)_nIV0f24&>+y zC7KrS$O$1*>>nl~P4VZk;hWRy;tY|^y{b-`(;}JaS;GsKl1F>kg%18wd^(!_c=>H| zd%+^xKQ~`GuUI-Kq3>WxJrAz(7?6Jdu8|Foq|5?7*7RMVGw&TM5A*U+Vy5Y~C7p;$ zW;*-^5AW5w=N2!-0JJb>T;cOg0kqkJLS3$<{L?#rm;be>-wM)@T@@|y_H?G3K z4t8o>o{Us{9uyQL&E;Zd*8O@o7MsN>eHc7q;N~ZX-^SH`)JV`s`!w6}M|-43TkhEI zs{PKu#=JDT%<6m#nP3Zp;#%V5DT~9En~xXiq*($zr-?YYs2M{_OLU%M3ZOTG)&aWV7! z`A~NEv!I)6@A2nmW)!)LoeSy)>EJ=r2F33v(jV2x z+bB;V*(f&Ms{QUG&N%>oG*iMpewh)oERUdi4uHJHhdef%Li%PXc=FFr-_nGcL0q)f zzkk0Z%*=?zMx0wtVY>v?KjTs(cGg66;Ms&LB|>`baOTPK95qG}^M!g?-$P7zFkcD|C zCgtoTf}Dk-uxjk>&g8Vu1-*6DRLGmDCBSBzNccHMXSXJWwLTV6eyP4F?izT2y~TDH zSqsIRvuhEGNwTllEYw}WdD~KSSF02?e9{%$|3FrKQLEldB5@1rUk!?(dm1!x(udcj z3$)QzrPNLmvLs5x(L_cj{V8N+7k6!4v~Eu) z3IR1&Rw5=`0`Td)zTn_4P|3Bk3X^J8Z~xr=T%g+pNE}Fp=})d-=lf!?xW98DlfC{k zij=&$cT?B4B2lFNAkaeUFqm4mqPJ^yO0gnQP)3OIglLZ!7K`KLtEtcDIA+^QM%QTA zb0@Cvenjh}{l-s`iFc(w(y-M;k@;;uJo@1@|I{-z@9njkjUU__s}%x*@8l2UIQoIb z+t=v{kGDF~R@HSY?&fLy6H(55%<2~6;`r{1Ibp_hJbHBrwC3G2)9%>odHF5G+YVK9 z7?(cMVAv0VQ2Ccybd22GIF>B*-@kDtH9BXfsx|B<|N^4=N|Bkuw@PK%hn)+r)@JH>3 zq$f4b?3osiRA269XsS|uVLz_f_da&kD_@L6V| z7Cqu(Y`GA;7^q+hrsi}-&%UR{gxid;-QNAF2ncd|@g88MyQ|059&dT?e z@w$+bj@P-G27Y@JBH1Qk3}(&@@M3yu%E(rX(V}Q&9T#^850Dh%Gff*|AbFZRauDpO zu(QzCph-OY2s!&NgG@9xh4;y=s(=9JYMZ`m%A&=OSX*6|?`svEd7x@03w;7!;VL{5 zF?hv)DStVZ?fj55duP4pXE?LJN20Fn z7k96BrV#;;r2LG!xe&5);QP^Tl0}xk(t0D4$qIBqUKv}?i87}fox&Tl zadU58IF<}pAzKImEUzpWE$(mJ+uxr?Ly+^cFjY~Wy|^YP*leVtRFYdMll?+Wbez*j z=Lh*a!3K%fjE$3|pIyjJmN*iRwTp>E8=jh+zWgm@`KSMnB!X%idSdgmU#ib-O)*d_ zpB%lo=ELq#gyQM=VX_QYl)oEFGhiWZ?OG5*iQOx#HyQH7+o^s8YN&_wV(<6OyN;uO zw3XWhpV4P2L*R~IC6I>)Kx4xVlbuQ)6P_%QrksdA2j75WJR)!=thp$Ta%=57 zLPNLh^cejzGzyl~Wm=uryS4oZ;kMc8of#ZXT!a0&_Q#v{Ae(YhMX~_^q_X}SbB>N6 z)^fpmv*O!Ms4?MB!OOqp+ zGBKh1S?>j-I{2k5()8!6{aV#r+IG7_-lY%)%3gX(cpk_DM%ZLmOx<2*@2~PzpxRUv zf^&Hi*BjYia@9W%%KXDh4g<2=e?*zc56f&i{*3C8VrJ^S#J>8R`Oaah!Wg?EYtQz4 zHjc3nePGJ~Q6l41GuiiOaM7(|G_?&B!k9K)$OMukBaOg{>#Yp+K^~m6-GO3?+5_%rIk|#GG z#=|U9tRRjkq=N$|j_y@;!z#N?5o0ek&pdN7dHDSE{khvz?g0UiGaT%$TJvAe*|`mP zD&(@3NmlJ{2lJ_bDyg41r|!G)DJf^V571=V4dzdls^`Hh;q>3{L|yyU**y|RipSyx z6B6oVO%~TqRzSWA1_;_fA6V736fV(eqXCGx`}~JIW~!~NizIoP;w9ma#l>0l7D4H! zJ&~{9VZp6Ag%aI=dUpD7X^b%l{p93`1&ygXz-q@OlE^f;tX8^o(k0!pHI)bm0M*pb zD&fvlipj}y#{sc7^++kMnM|bdlib|xycwx#}IQt1cd!hf?5GQ=4@UBBV?J!-P757o+!oL!qR^hyq2@j7~5r<^@J zyyQQ_#jHvzteI~#SnUie3lEu03Aq#^uINDgoF(GGuQQgn$b_Kmg#|d&;&`yi!szJu ziD#+qgn?wj6--RVc>%+kfE&((M}^{*hldc`-z}D?XhZvW@B4MtxZ(+L+z7eBexJ$3 zyv1dAMX<-8gA<*vov_P!F6r*yy-x_LE3vVq&v~82QHO+#LXNxZg;IUR(-h}GM#y>X zGb(tcNj%G;v03`XwLjmFi{Q<0+Hm4vq6UrT4Xu3zgt}`0-vS4Ndk|FLz;l;Rozo)50$( zLxloPa5K6M50t;h)2wsf%57`N5^ffY$G92K*Lw|&+3I^`v1?@BJ6<^{ zyE$j~2VdrBuB*za86VMX?MY@_!FYP8dHuTYHVS(;AJMx2J+{RU&;I+>IqI&$TB>eo z)|Fc68u-)2cSahMF4&eNv4N<8`_7Ba-_U{Dj6Za%s^&BX&Qr;+7ugEzfc&c(O1LyW z;QTOuXRVI*eprckWPe|{*U@MBIhL;|j;nA+W@gN5M9|FIM2~5y#ZwJ!;>KC_`vUo< z@}W=Nt(tHv*QMNcwVfVT1>fWXJb$OynVZQqsS0;%A${(aR0|CNLo;pd8KyK8%4RI# z%7X_Sknt5BYnPdk*zsxO$~@Deb5%}K7%}hSQJKxONb%!uc>OKZIhiB!{(S;u#+SiD zk&Yna#)h*3?OoY!0aBO2cmwB*-e0_Y;Z5ozc{;f$1xgRoO_Nybv5WDvUu$9O^ggkQw?8x4H>Z$dbvdBKD&@>Zau8>o4o@3{td!rugS>)C>*H;7f@Z z^5XQ~Hy2rs)+DybnP8a8lsjT=YurR573cv?wAg%OqMc6i{c|;7#!^Vg=-AD2goee3 zNvFIF811pX_-74qkekS%;M|ejisfQ9c{;MUHX9=5l(X#ytK5w@rTdxY|1Gz6d(2h9 znd@O9VVuEpKsAVgycQ{4;x7D_iI`U>e&kD;9NTreK-pd38bgbss*4LWv~8Hr%c!!q zZ!UU1hD*oS7~`?>8IsF9MB?u~On7z{Q`^QG#OiaCUt>5g4obm2V7KAVhWMPC)gOe2 z9AIKoOn5D59o)8|dmpb*q8Rl0I$B_VqDMLk5DA&RN>N(|X_mM?D+eL| z=;+2>G~PwU>*uF zNMYX6rKYxD%AHF(TiU>x zkiT5N16n_or!SqZ)$Qx)E6GPNjN~PZ9Q5f$!iN73c>ZFrF-)X+wE~?U0Xd)NLjoke zQ3nm(%?p9#0SzZ)E60n*?*vKxS3UML44DKPau!@G97LJ6t@{F-xR?=SCD%BE=I45d z8W-*DM;zLIRXM)^al2Tzhw(Y{w`&M^5S0&3Knel^ZQ|+H50?rJynkm89fEYca_qTF zOZ`OSiL9Fz-4i$*^)`Z2lBd(6=c(b<+1Z=K6ni7L$K`b-dV+(RNejX>5p{j%#v^pw zd2BX2>sj}VICL=oip`jKuaNL>-CNg6v)YRU2%T3I6;q{1R|i6+!x-fBLTL={xaw2K z#%`?~A0$b*35<=DZT_BS2y7Yzl%qm1NI|CR4$CPPO<_G=$LM<{Bm^))s-R>|)ZW^y zfAWRV{EOsZg3|5#T~}ta%E7`wZMk z4vDmWM1W){^g8NvVpUFT?tA3lp}ro}K2{o(nCcZvG2fM*i*7Pwp%{XBEpO7*_zwBe z>hqOXj*%|^@~5?}i%FA`LRN#9WY2dOjFS%_xZdPur|7Jgn9>pI?yU&&ljrnap+d!4 zm~C$LNaIniIXbj$wnhCc$^4pDyR(!x_u-v87IYV(+B!~6CS$XD-y~kFPjc^9y;t4Z zb2`FxpR+qY?pqJ^u3nX#*|ZnLbS=U~Hh4EgvZJU2o04e_+E3yP6fd!^Om>eoq-KNl ze$1FDI`i%*ZX2{>j5VgS{#}~=GSl=C@5m1zlg+ds6K-2gIoram;wfTzO~+fqU}Z1H zlc0vDrcxb<11dY*uZtn6$8_hJQWqD z;lW4-`CE|TO(bXdUc?AujDht-LOekqYJ0givne7@{c&R{c1}HFA>Ya~f(7`GeZgMd zi^YY3a^8FI-_u3E`v}a#!8K}|5-%JC@D27~ITVt@SBf{jb0%n9H!)k&-%ya+f z&~l;Fw;%oG6|PFc`f-_6`C6c$IES76+}p-Czw?Cb}JA)E@Ux~XCMS-dr_*wF}S zRXqcP<@JiUZ>Ay{Mv9hn#9y|x30FP`LVS>d{SRQeHuIjW{1PhP4*9o6T5aJFw|GS` z7hsa=MFV6=a6SrnxxNb1Q=5%~ZHIJ{QoGeI{5NhP1KPXQ1^s&=-M@9#wD=35|Mqz zj{W%2LGL;pX8otg?|_BE>o{)1l^k{{S!GaOu6Q9cZXq(>t^X*0yejJK~fjz7(>Jf{0ixx#gzHXcJghxb!u9_4~ z2gj~*j7O&;JUi==^wcVi-Pn&j657EkPuL1S@71d}LX-l@rc<+1yLU|6gi4fXV<;ji z;q)xs(Qx()dDX!adyKb>Oxnl+Uf&Re+t&Zq8%Vj`wR97q`Utq3=*&!`X+#sfh0NW% z$?FpO z`t}%{TU7sNYKwtkm&3vLSHGt0mBfTxnryi=S-s3A+y}jh0(#S^kF;p=+``yPx7iN< z@15Oq&JjUI@gL79*qQ_?j{v7#Y3S+hoT)3j$xxl@2vm_jVK=D$K!x(h≦)ess8d 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 literal 35633 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

    _+GO2wf&}`q z1AP2b!!sxSWYPH2Ze>uY&IFSgtEc{Ae)E6+<;K|UbPN^_@|-D~$%cmBGi@_lU1*QA!JO^JS zT#;R^MYO^ZlR4xa3JSM&hJ))~Rn2D2^kWqK(c%KhuN5{LCj7E;) zqfQV-f8rDHXhjle|31drZSpjU5|NA7anHZ7vhdo$$N?Aye3Fh zFsh`WLz!V}`tJQZBC0ztOvbZ1w6e3i6`x6L*3$zooH_gZ)w*!9MD;n^r~x6Za6>`; z6L};^b}iVTm{67cv;q+Ihelhc?BSNiBib?z9pT51PfXgwsFdWo{Q((yE_`9S7sFmt zZ9YIO(Y9vC_07>tWn(ya)lmDXvQnVPwx8#=zgY^mNGNj54-YW0gLZn2jD_Qw&_Pvi z&uA#i#eAkIt?g86jzz^GZ(=hsa!F>S>6b079QaCHY3GFBwi#UK4BHvRip63^pwI3#yu)ovmSEL-a(?uN`A#GQAY8^;RwJN} z4(EKeP&0wnxkak}Ic!PpAuW3Xf1ap({@|Pe=hX!dwaa$y!Ah&F%-*O;_yZyCq7gF{ z3`;<+MCDV(xlFKcY=|+#jDag1PZ~zL2kD~MMUWEcc)U(=fZbLgua_9 zMTcSUx9%@>>zC(Gr_Km)gi*_e6u!aLDZ8~@OMZ3w%haapN-IDE+PG)bj*eIgc|%I%0>efbql6`%ip3l2G8VAs8VR!EuQhZ~p> zQ`&2%CnDA0tF_!U1UY;{OHa=|;zB;d#LyUqNpeSBSb2HRt-`bOuHw}8OK-2Y>UT$P zQOhC>&!of!$n&cS!X)VGPO<;aBqD$Ng952R`;a!(*XH77b=eP)hG4g-(g%%9ezMT! z!S3huI+dD#9W=Vf*`3hZ_NqGU%sx=qY4+3N>y7ZaybjxX$`wf_m3I?1Jirxi5L-9i zDY{cIN)hF0n33kORxyt!ucEnDSmfQ>ny#6&rX8E;*)kZJ6eo`Z_O1AKU>=FZ_a9j|DNStzs*iST3Le>i@Xbp(Sp*A7eoAd4apjhzS^I9+ytp{zT&h=` zTKq(EMGC%{1s;ykv+y<3Udvx?m(CSi3pcgr$rWn`j33EP=;|K|t-6cKr% z0**|H2m8RIA7~L$%Wh<41zufNP3m18c5%AZ>eCS5xF);7UYVFYRouYo6EmyHDt5}= zJA4XX|jKXMG6a)Z$Y{X{l(69G_uNHy z>rss$jqDWE-02lnW2NISDbLDs@Eo2~luOKdh^?LkUSLiGursce!=h0XT{z+c;G%UV zIB4xM(o+jiJy`saGy8M28^A2G3=G)da|efzCT?%xBp+ctPxh9UxManP z*S4y}U95`jK~P|}z~|G_0*?`j7SBCDesr@ubHYw`ysdZHz#!**UU$99iW8wdt^O{M*s9s z3r$aj`8br4L{A`1Yvr&Bb(w0v%+5DF=JE*kA{0cW#MX>$cZ=@|?SkED?eP<*((&vT z91xV&V1;PW1bdB(q^xn3F6@R$Bp$n;)sQzwl<H3=byetAWM474;Ln`mXEW8U!suLThVqHg&?BfYTIr>dSeCqo zEZzspjpu=1wMTjbFj5k@1Lun$qj6C4A{T^R`Gukh#m~DbTJ{#gxoncgE#NIM;7VSH zd+m0I!~H*VigtvwkF5osRI_Rdhp7wy;j`6u|1O;&jbQ{5ur0ebnj|Rnfy}AO=Y~_A zYkL%GXaaBjqFKLsdzO%VKw?2Vo?puhwas5>qnx<)M7l?XQO^F06I<6W!-f1;d_KzO z%RQ{NjN$kr^cRd--Zf4v2mCfS7&wFz&YuZ?=uZpz`!iR}bGB;Z%QN~oZfTQWGC;OZ z*RRoEFmB9D4Pwpb@>z?v@9LbWPhFyS@jQGl&Wr( zdCO|Hqn{El6!o~A+Rq9>Xl7{qts~oOw^w9$K#t2SjQhcJI2Ai^xhlKr(7YQvb@;B+ z7Rt4Ey0V_GA%ny6Y2qj9+z-&0?`9{?@Y^glXDFfHB*ZmpV#(|me$=_Bez@pDt*ha> z6+p`RMS~TxngTch%dQQ+ZSg`PV$*#)iuwSFR?g{Xjy?r1TCKQnF&U z`+&B_fid(+KO{sql1s@ioW$>&m8WhoHo3%&jq=QC|$_h5so z;3$8$Srs()2vD;!kQ=;pNs!Iv&$urxT(z$(ryEUB6q)DlE{Zzns}Q3@v!UesINc~Z zcoeNQJ7H_oh(RIP4*?lN;I(oG!&-J%r*_+wvbX~={(eHwg#lA5UgFBQe~;92JeMNj&3aZ9;}o+5~21>=eMr7JXx^E-Wbiu zWviIO7TjPvnZ>NFxIc&lo22ROjOMbu>$HLWOe{kQo4UU@AfPik>^|VEX2O56oaFCo zJb%%oHk4VCnRU~T$K!apbh`E_Fqclr><8u$;##d&rY=;(KtUmjOn5tijfpLJu)I5{ zL_}%f0-MNwx+Wj;!AP<-o*%I>I?4qn5I_9S!M> zpQ1id{H_(T&(p=(#6f~=^gUm{r}Far{IbYOO<0)bA?=3`E!Z19y)dRfYU(Y()N0RP zU^KX2p7SuVbS$cigNBdWsp-i)zTl211Q#)1pc4xjqI~34f{Guz9S(cY3v;q^u1uUB zxI1^=_0ccF@cXX9jOho|{_lR653wK961+%KahS3}^Jr;z92z%sJgu;A;hiO1I#*J1 zUm7(SFSQ~^x&E;zJ!*CYCMt07)L2%%2HN$anery(!psOQpG#7-*rASElQui$LL2Hs zk2%y;A4ONSmypx?Ye=bL0KSeh=|rNO@R|+fx~aYLY{o#ZJ2=(17xi8F9*}xv1(Wrb z_PA(P2`UH<-1QkqwDG*w?YJm!S`WTcY7bkA+*?@dFS8ayN%8?u+3maBo5zN0cDU9& z=0SHcsjn&=L!ak#U2}={>N{99xg57%q8X=sbGt4;xZFY-Vx)H|$m^JxnrhsMa)B~0 z1OphIE9R;Gx%FMEI6YG_1RzUHi@f)ROhN&Ia%rNzN#=siPCwTu#C{n(#_HuZZ`PW95!GwmRYFnv`=Vg|El*reV_dPz3-W;+(gh% zF^T$phlbo*PpgZ#Fm_!{eS$GXlVBMPOEW3-XFYLJ_Bxbk5L`p{CPM+*C(fgpmiaWW z{-PD+qIt7N41*Q!q97btH5+torJS7dB>3tJBkILZ7=l4W;TFVJ3tsTE8YpAtJ67)U zTD675>VI<;JCd>O>sy&|TvpfDcgZR_J2HJ69+)#!c5wml;`k$4SWG#{u;pZIXbb>m zHAX%A?oC_wUFTyvCJ9qR(CxO2!mWu!z(y{BxItA;Zt%`?=lx15LMqVm(&F^}`y{W? zSLwE64eH?t;@cF&hSXfWYm7Xw00SnK^k=mC7srkvaG4nrtsEs?Qq@RnP^ z0&b?JQsp*we=O`a@_t^G&JVu0a@eU&2NBsvM~F$yW$aw-&#l5dk-%pHP^>(J#wofUEx(oFizkg^f#fQZ}CeV1P-|JZNMx)M;tJu+uBfB}6 zHKqjMV8?K7+Kos#2>JN{fgyAh2q2>d%{cTF0=pxFfwnb`U8z2uefqY61zt3kI9!uU z-=2=dCpuaCx^ATnX6HwJt6F^w`YL(=G8?>Fqq$5QYb+^-kA{@;EY?k}lL1 z(26JdfB3+Zx!;(s09u&4U7TE&pCNEVs4kgqulV%6KjvK7#O!8?)ul!7;Gp34h^~9n z#?sdyC0F=?ziNY{!1S+La((TEcA)glh0gfoT%f1(1Ms5)mzQ5!@?%frKYV6Lj9c-4 zRP-A=aN+WaIOI>OSbP0~f2w&nc;()n$J}C+(WQsmxpmgk)he(uw!Y)-$nkNuT{kXA ztwXT})~5*(XGar%SNrF__?Cf(*R^rDzx_>yZM=$g=9fA8P^4-#&8d@umrUvfnvgeyaL##uFhL0uDtLrm}gg_dV|JUgzgKz<^S3 z*+h5IypCxvRwUkJ5);#B`^hi7(6>>prQ$*hA}lz}bQh(AWT@a8eGdV{nm?9!%DZlH zWp3Qm#l>hR&du1<2BkN{34;^50IGR=AIA93D(H6e5^vpbpI&v$u#gaRO1pD*)9z3g z@ohYGN;ptt)|@iszQPxnQqO#Fks8BhG!#ZVIq5gBzW#)vZEewa#=E`yr`0Lr11y7M zHJgqu6Rq3iq#xz&*87Vem>qBFo?dwdlhYrGfB6EOzCW8p&klWa!VDDVY-Um-3sJyt zirPbhajKnjhBE7fP4O`GID+_}m!2Wf@{ioyHYRN2qf%7jQr}#1cKzDzT0kQCLbgXj z#Ys)7@f8)_TnAvHhm+qes`{V1{Z$<+yKPf5AUMPflWO10+l2Y^SbXA^S=#T~_-pYX zBjcjfiKVZ4N_%T;fwUo5Mka}Zyj`KA9r5#_%1dpU&>Q>67X8hhvWU&*>P>~|}x z2rX(l5##CuOt2S-bMOz%gaP08(JKiW^3XMswh(J+Z+_+4Nb-yVQzpNv6R_qNa=>bW zpJSWxIU8`9CD}Q4b8LpcKmA-e74z~^@C!N7n$ssRy8vDc@BuL?nJj{g-SXn(ad~xd zk~-%j9H08kEMyPqM4?kxCDI#w#{RI-sOI9Dd4B(%F_8C^8gvvAX!CqjggXRr95(W} z-ctPC1fYgE8xxq6rtS=n-#P$?KKCH=d+w`X{M8kdy0{}crr+nke}V3S?2-Y%&U_+Q zClockaQMkUeX)E?4`xgY_^eQ^7H6G7Es*lM(%<991F)xRWb{TZCw0Omu#|T}^w)eV z5wQ{UrU%LB#ODVdbK_>9$@l5g`o$W{+S*^2%EI;Xve)5=&!xQeqA^2r4Bsu(U{9nk z_uXK|?7nN`Q2_LzjR7!m9!ySBI_m!((L949*chSIErv6i1Jrlf6OY*y+blyqyfMV% zviU`c*5)o@X})Az{;N0bM3D@$PQsNAtNooC;WLg7akVzdfC2!onsmUgxf1r;dkVJ9w4$@Q;U6>;Bv!WN$qOJ+~d)~H#-8NV3AU=_x{B07&VbM-o6YD7s$ zPFF*Cz~F@meCPX95MPlmLHosXqIy&i#ciXPynUGkG$;~+i|pJKHF$2C>-kaAWUUCA zO*q1pj3YfOw;SRQb`4Xm(y!Bt25CW!zn*K_+$!n&Qu@2%JS_#*)XZ{Z!syG|B&fIT zP}v;@gGnvgw$mvA)`0$t{o!m>hEm}1`;e@MZi~bwk3pXy5vb8&Kz!ZYN_I8;MPxoz zHBC5>ufbaO@&s|7Cpod)(-U?NCiVS8SL<+d5Hax`jE2FGTR!;9?8;)EO+QDQ4*HtI zC7>2Tm?U_L)z(Yx(wkTNF0w@SKfA+Ys*1=AhHRT!B@tnJpWpKU0lQqsX&zRH^b)${1^@|eqx z;l!;&6SO+*g=yIKz4@b;X7!x*=GM8+j#APXT z(AbX{jGtAzHrv*p)|{dD^NJ>^w$pXBt8834pHi4pQFYqadM47!zyq|+qnPw~yad0J zu1qakPs%IG1_8g}GW09Dy;0OYJ8A%-dqm;%Gj-V2?$EQg!D@QEn+;FRl3QuQ+h0r+ zcKVIJ;^3ebiCN8hSh4_gQLC96A@W-k&rh%9lwylZz5pRgyz0UMOy6xC3JM`lh! z!0;vLyX#g0@R4C*%fblE5(7C;V(sO_{rSA|gd{k8lS%ZSI-y~|ZLR4cT)(mym(+>V zjA(XWY4kppQv3*x;RY#DQ5xoq;f0>0@wabo3s>i-9UDuu_2Ldw>FB<$f)(ch_!J{K zu^$xRE&0NwZ#%}l&o%2%SM#l#L$H0$ z&|3Z`{pIBj{KT#P17Nd2wQ3`zQ&xuGK-+L|Jhktkic&je5U1O&qZYrSnD!n8mJCh6 zLyq+Y-HwPGGbE%ZA#DwbHDF5DU=4Gv)E+hLQ_mne$!Tt+i4C?*@lX^<4VIVuH=%=v zqk(K5S!aTPJn_w~Bp0el57rxw@po_?fLlxG==4`P2a3z+ZH#oE?)X~#$){}>O7-&jEvF23F!28*vPpm!8ACr1_91bTK;p2}PV(m?Iuhj=OfJ-TS0ME6Xu&7 zB?Y~$bXCC5&c`cBUjDS)%~U{!E{$sG8!Z+ZCE@5T+7%9khZ|svqBDxnd~R*$IhH^f zIsH^>g2OSEIK?~%YoAi19g&glfn#$E1c1j)@Zxf(&_`_2ITrW;)dOJOOl*DhY_Eh> zb0&$s8}t(UH+d5HGXOO!k<2Fy*SY0&^OlRS`{dkgof5~rrMz;A{=7urC&9?ykwa^X zAHPa}_#x}2f&n-C*E^(|Bu1dD#9Ozck25n zP1^UhqnH>4X+m&(u<CI9dF0#XmR?Rmtf;tOt{Df^Q%@#rigi`;--y^mW>C(uz(yDiDYUpCs^gW zYN!Z?Tkpr$7-R8_QU(4p`9Jtz!)*Zyl420khL?`W8m|4=if(k=h9p3v;chzHb~` z*W16e!1I6bv#_q_>R^`7*d*b&Zwmo(&I^P}V+jHrucLVGr559TJbd@p>*{Er1!lKp z-yWYN4^Q8A0n;OYLnuLK8r^Q~i&V(!^-Dt!u%D4_;2w?f{mA&=Zc2gK}CV2DyjfLk6;*hhV}8 zqDaFT_-LR9Vaus4Y2jYkk-grr2IdgCru98oDyBeVtO&>?Ma;ohb_U*vQa+N8$lueI zmuJM}w6`Tye8dgDe@~$PMb6F5WrWe4jQ>mwl6rL2fQ#(Ab*ntTp9e;XlHc)LH1Rbf zNY)+Dxoj6?Up#&cscBc2q1M{r5(M>Emf$-RAS67CR|$`yIgV-zD6JFFX#Xdz^9wNO z{65+1&m`3I;@$ z!zIL>OPFi67Ye0kf0L0}@+eO34*|VR$V%;wxV!??<;;VsjEcCX9bz`#I54o=46p1j<*Bk#4@0g9lai) z-_9xUb7Mj|nAsgEB4Z@u#yDvE4XRbRMkV1scX8v}vc)_>3n%d?Qj zSRWyT|p-XNO?68u%ctCA4>`-P^rqz-he}u7TupplPB(LqMrRLy$C~k{l8p zAu#R7S;qyELI1ULn4@RcVJVqOf>~rFm?rpmPx{de%47IZ+2T@s+%LJzRDv|QW&pRY zfg`RW^cGDqOsH{6O!C)eCIu+DI1O8SyGH?7ccWtxfFejkVDd<_K=qh{nyTy%y9_XB4F-0{`I=>Y56ZNlfWP5@at0I0OUzse1zhWXis z35hM{XL-Y_51Oft}mA%JDN<(&z#0ScoRS+Tb?2Ud^pUft4nIOx78c+u93|$Kt?77TTp} z>g@Jf3$36M#Rl$CY<4u|;8Qh&c~XjzqWgg&PH0~$YLb9N^hH#=Pqjj?O*6OY324tM z`O@FvPK1^eUB7FEAA`JU_*S77LRDE0(aN@`d;WLy&ds2}i6Bj{&(RG(rfv5lQvKiP zwV3DiVT_MX>HT3yXCdMx2#WEfuS9w}sA(;qu06Qs+Jj*@8~xv~{$b339F>3u62wYC z!$pa_Vix09p8$Bn(sjJMW2Jxd%klxkl0rqg0%vWl=+CuZcBab&?`oe|of5x)*Kj|) z0RW$cP>)81MIs=7G7V6I@z6(r$97>8GBLq0{G2N*m32$nfK`#} zS*|mL&+ujg8QaswJH$fT>e>{b3#wW9;zIf*)tZP46p1En4QrXrdF4-DLVm>t@q&&f ziOCHz@S5fgD(WuET2IV2e7-0$_HSR(Tfl274mHguMg$38sJ{kjR|%q5#SZ8L6#C#S zsYcUqrY1_!4MD4Mhf|-XCa3Lx$8HgXF`4mg8-*F<>!Uv+c?C0vI-;c!cSy;w8+L?* zE|OAgKwk+6zPaye_OSoqfy!WT40x_qrxP|9OI`hT|6k5mumAHS5LO_11NN{wV7K+N z&^`@pLm9L{!52s)FhM$nFaGiYlJLWEf(#z#e^rz#rH2oT()IXXNQtFW6R zU>=};_O7t$jJYT zq5&jcX!IY7#yINwhd_H`L@-DRL^zA8_ZbzKLXV;6C48u#ChA-O8?^h@<02^0|t8!d2&tUuw7TtB<5z8cw?+^m4*C%1JBSP=h@5-@_Vo!^ zyoJ;RC+;=$RR+Izd!l^*5|o@beOH%|Q#p@H#d3h$9+7Gby&?^~!ekFPRW4-SGnLJe z&^mj2w7W4eP~%XP%!ha#`Q*uLq@3Zo3s4Hboai&Xpoca?CV_cHSU@KB z5(N{ZUS}*d2VuZyRM%E+#g{+iu6cA1Op^!W;V*z{@W@~`zU84P}Pr24tW@ceG1M%-`4J> zjI09~hytZHGC}db<(1vJ|HN+k^uOCyf=r9f!*I|4|BhW60=HT8g{^3DSL3P&a-#T05RoU^ui-`92@eCo)n}(bMAO)rC|K}YhZZdF;N1!8- zPbr@CJQm;YG?Bl^X+slmT*F<%lMREpNI3=ph~qj#TFtd-9gr?PiH>s({$LYeLZA{0 z3-b42Eo#m(v3=yY0(>1@r`c>@$4dXRlb84c-r^JFy!mUEfEMi`2j>bT1-Vv3DU_Sr z?sTb*eJwj1cwsil|1d0)1q|1aGcyk{J;L+Lt9Cu;`Jn*`(>i8S;Er57ZOm02v%|yx zc3bGyLjxYb$?J2?P^G<*a9wF>Ehf@&C+#o+HE>*p*yG55wvFhQfh!OHudqG74qK2! z`zv`wQ8i#2mJn37l zl82D^r6A47bU+4J6Y&rb@geab`1@0I?bO6B!p1Yq3k7DN;@9j3KyLt7CBPe48HC?) zz>IMt0Y2t)df5B1plfI(_a0D~0i=?aznSDn04BWN&e(uNk_OWBIqrAq)$bYL1%CNO zMM=}uK8M{Wh9s z@JBb_jys}_M~9W}jugUo#V`6d8DVlz^&?ScWoSIQtpaZeN>X9gBA`_S)gKMa^PdQb zO#zM5Zoi|@i6vLp%;nBC1Op4=VPIN@z{LPDv7V5V`O>*TfnLWlq^S-!@6Lg4dlD9L z5f`)=Xc_Wie=SGD)T#g^UO3$UFGx(#)MWS@I#OztxM6xB0kLY2mU@cBZ*Zg24GegI1gE7F(!X zz921-wXqo)x&ANAJJ{gQWkq&FN#DW=y2;zJLlgEz2mSgsSpLD;vDrdz^6RZBC5W!F z8T4ihYs&s$W#u&cZ)ShbY()iJLa-C0d53rx0hF4Kf0_M@JGEdqdCB2a;$*gQce@(Q z4$!zJq38`-Ky$%ZqR|Pvr3Ktxb9jA^gM9QBeJ>Bso9F8;JibFrRpr)QUkGR)NieYr z#Dc3;OQE)P_ssg}k|a4}gI|{?4*A^-@xL$A&^A>aUulF{5EHwACEV8LumGCxhuN8T zs7V&;XQ!&AfxL4B0I>F_>*9@TQ$Ef@kmG?~-$1UnS<;>X9 zc1HJSDIouq(fH#TdZl!9ZO@V#d2em+|0EDN0ff_~!-TN?E;BOp#Oz_-1yvtS>o42t zYxRr8==3pVF`ioOx%K#QH&jc;jCMuY2=Mq`#hVmV1SkxBKQ;5TDYt3MTZNGULHURT ze(Yy{s{n~Sgj#G=f)Nq>4t3{eR^NM*Iu4hXaviEGvCOxdP0BI0u{5ivk~Gv?hJnPk zMkp%ToByiry^3Oh^9F;&OnE!81sZe?9I-#40_E55f?6;69J;N z_I6wUBG|rIMAci$`!;p)w{>(5eH(11LdvtV#mz|e1Rz(>nZcaze+s<4@pbFjVUk-r ztrNJ>`aqwvU0~KRnSjly8h89>uxj~qXWQoHnb`C8Fe0iS7_b;wh{Y%&r5=ZE+Z{?H?hwr`u42-l7EZh_J>zg8on{!dCup$?z*?n?ZwpnI@sat*~ zmWaHr=>b`O+Ct#^qltk1{%ap4rG;1JA`Gnb2x07#)QKJee6rn+Tped$G!XSNfEZnB zU)};23GXlxx{6Ff1U%1SRW zTe{%R#FMzwj#7V@kJNEK|36ii%I!ZQJ5D z#1r5YsHEtf4o1@rz?L?(%OR{Y*%;H&7~Fm;y2 z))8?X*(Q1N1l;^T+O{4uyuOGBPM1Y{7$5mQ_!F@4=T9kNBoyW@5mdMG-4cskthXdO z<~chR7OwqZk6rtE&##~!oI|C#CHPzmrnMdixCvl|QXunHRiOgi)*|}g`afw

    9a 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 Q&kuFywz6FAEyEZ817w~z6951J diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png index c1e4d8e56469e89e29aeeb2be77ef3bef09797a5..6d7f5f038171bf243b89e7e0d67581e0921c7df5 100644 GIT binary patch literal 60676 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 Q;K8M?qODwd%Od!H02y`u>i_@% literal 60787 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 Date: Sun, 25 Sep 2022 11:24:08 +0200 Subject: [PATCH 1069/1892] test: don't install Matplotlib in test environment for Python 3.7 as it does not have wheels for that version --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5767e6e82..d0cfe399d 100644 --- a/setup.py +++ b/setup.py @@ -904,7 +904,8 @@ def get_tag(self): "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", - "matplotlib>=3.6.0; platform_python_implementation != 'PyPy'", + # Matplotlib 3.6.0 does not support Python 3.7 any more + "matplotlib>=3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", "plotly>=5.3.0", # matplotlib requires Pillow; however, Pillow >= 8.4 does not # provide manylinux2010 wheels any more, but we need those in From a926562e2e8b415b9c72940a898ebb53128acdc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Sun, 25 Sep 2022 21:08:06 +0200 Subject: [PATCH 1070/1892] chore: fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc1ac190e..42225e01b 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ the packaged igraph library instead of bringing its own copy. It is also useful on macOS if you want to link to the igraph library installed from Homebrew. -Due to the lack of support of `pkg-config` on Window, it is currently not +Due to the lack of support of `pkg-config` on Windows, it is currently not possible to build against an external library on Windows. ## Compiling the development version From 3de81122d75ca5439fa233de417eaccdcb90f267 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 26 Sep 2022 14:37:29 +0200 Subject: [PATCH 1071/1892] test: add pytest-timeout and try to track down the failure in i686 --- .github/workflows/build.yml | 5 +++-- setup.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a5220ce7..4276da505 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,7 @@ env: CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" CIBW_SKIP: "cp36-*" + PYTEST_TIMEOUT: 60 MACOSX_DEPLOYMENT_TARGET: "10.9" jobs: @@ -252,7 +253,7 @@ jobs: - name: Test run: | - pip install numpy scipy pandas networkx pytest + pip install numpy scipy pandas networkx pytest pytest-timeout python -m pytest tests - uses: actions/upload-artifact@v2 @@ -310,7 +311,7 @@ jobs: - name: Install test dependencies run: | - pip install pytest numpy scipy pandas networkx + pip install pytest pytest-timeout numpy scipy pandas networkx # Only pytest, and nothing else should be run in this section due to the presence of LD_PRELOAD. # The ASan/UBSan library versions need to be updated when switching to a newer Ubuntu/GCC. diff --git a/setup.py b/setup.py index d0cfe399d..384c0bd0d 100644 --- a/setup.py +++ b/setup.py @@ -901,6 +901,7 @@ def get_tag(self): "test": [ "networkx>=2.5", "pytest>=7.0.1", + "pytest-timeout>=2.1.0", "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", @@ -920,6 +921,7 @@ def get_tag(self): "test-musl": [ "networkx>=2.5", "pytest>=7.0.1", + "pytest-timeout>=2.1.0", ], # Dependencies needed for building the documentation From dd28a89e02fe17e5b0b957fce5510d306a4c2923 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 26 Sep 2022 22:46:40 +0200 Subject: [PATCH 1072/1892] ci: force Matplotlib to use the Agg backend in an attempt to get rid of the hang in the CI environment --- tests/drawing/matplotlib/test_graph.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index e3f125aff..eefb92033 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -13,6 +13,7 @@ try: import matplotlib as mpl + mpl.use("agg") import matplotlib.pyplot as plt except ImportError: mpl = None From 5e5d74bc81a7f716d8f0327108ee1c1893b19fa0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 08:59:55 +0200 Subject: [PATCH 1073/1892] ci: prefer binary packages in CI, run pytest in more verbose mode --- .github/workflows/build.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4276da505..ebdda20e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,7 @@ jobs: - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit # wheel for Linux yet @@ -44,7 +44,7 @@ jobs: - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_EXTRAS: "test-musl" @@ -69,14 +69,14 @@ jobs: - name: Build wheels (manylinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install cmake wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) uses: joerick/cibuildwheel@v2.6.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install cmake wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_EXTRAS: "test-musl" @@ -253,8 +253,8 @@ jobs: - name: Test run: | - pip install numpy scipy pandas networkx pytest pytest-timeout - python -m pytest tests + pip install --prefer-binary numpy scipy pandas networkx pytest pytest-timeout + python -m pytest -v tests - uses: actions/upload-artifact@v2 with: @@ -311,7 +311,7 @@ jobs: - name: Install test dependencies run: | - pip install pytest pytest-timeout numpy scipy pandas networkx + pip install --prefer-binary pytest pytest-timeout numpy scipy pandas networkx # Only pytest, and nothing else should be run in this section due to the presence of LD_PRELOAD. # The ASan/UBSan library versions need to be updated when switching to a newer Ubuntu/GCC. From 1554293b726da88530d9563a60d943a116ab4bbb Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 09:28:00 +0200 Subject: [PATCH 1074/1892] ci: also run pytest in verbose mode within cibuildwheel --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ebdda20e9..4f3e1513a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: - CIBW_TEST_COMMAND: "cd {project} && python -m pytest tests" + CIBW_TEST_COMMAND: "cd {project} && python -m pytest -v tests" CIBW_TEST_EXTRAS: "test" CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" From a7da66ecbf524604e3c8c116f4263dced0d3e87d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 10:55:36 +0200 Subject: [PATCH 1075/1892] ci: temporarily disable a test that seems to cause the CI to hang --- tests/test_vertexseq.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index a2587ebfd..d7b2ee41d 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -277,6 +277,7 @@ def testIntegerFilteringFind(self): self.assertEqual(self.g.vs.select(2, 3, 4, 2).find(3).index, 2) self.assertRaises(IndexError, self.g.vs.find, 17) + """ def testIntegerFilteringSelect(self): subset = self.g.vs.select(2, 3, 4, 2) self.assertEqual(len(subset), 4) @@ -286,6 +287,7 @@ def testIntegerFilteringSelect(self): subset = self.g.vs[2, 3, 4, 2] self.assertTrue(len(subset) == 4) self.assertTrue(subset["test"] == [2, 3, 4, 2]) + """ def testStringFilteringFind(self): self.assertEqual(self.g.vs.find("D").index, 3) From 600d4a03b0c3aadb4c6a316f9793417fe578d504 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 14:49:20 +0200 Subject: [PATCH 1076/1892] ci: pass PYTEST_TIMEOUT envvar to the cibuildwheel container --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f3e1513a..935d8617c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: + CIBW_ENVIRONMENT_PASS_LINUX: PYTEST_TIMEOUT CIBW_TEST_COMMAND: "cd {project} && python -m pytest -v tests" CIBW_TEST_EXTRAS: "test" CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" From c1e4c1098b7120b1469c845cb3a6fad79829e898 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 16:14:53 +0200 Subject: [PATCH 1077/1892] Revert "ci: temporarily disable a test that seems to cause the CI to hang" This reverts commit a7da66ecbf524604e3c8c116f4263dced0d3e87d. --- tests/test_vertexseq.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index d7b2ee41d..a2587ebfd 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -277,7 +277,6 @@ def testIntegerFilteringFind(self): self.assertEqual(self.g.vs.select(2, 3, 4, 2).find(3).index, 2) self.assertRaises(IndexError, self.g.vs.find, 17) - """ def testIntegerFilteringSelect(self): subset = self.g.vs.select(2, 3, 4, 2) self.assertEqual(len(subset), 4) @@ -287,7 +286,6 @@ def testIntegerFilteringSelect(self): subset = self.g.vs[2, 3, 4, 2] self.assertTrue(len(subset) == 4) self.assertTrue(subset["test"] == [2, 3, 4, 2]) - """ def testStringFilteringFind(self): self.assertEqual(self.g.vs.find("D").index, 3) From 55be30b648b789d86e7b05be4e7372b037a0fdf8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 27 Sep 2022 16:27:40 +0200 Subject: [PATCH 1078/1892] ci: temporarily revert to Matplotlib 3.5 to see if it resolves the infinite loop --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 384c0bd0d..a92bf5897 100644 --- a/setup.py +++ b/setup.py @@ -889,7 +889,7 @@ def get_tag(self): "cairo": ["cairocffi>=1.2.0"], # Dependencies needed for plotting with Matplotlib - "matplotlib": ["matplotlib>=3.6.0; platform_python_implementation != 'PyPy'"], + "matplotlib": ["matplotlib>=3.5.0,<3.6.0; platform_python_implementation != 'PyPy'"], # Dependencies needed for plotting with Plotly "plotly": ["plotly>=5.3.0"], @@ -906,7 +906,7 @@ def get_tag(self): "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", # Matplotlib 3.6.0 does not support Python 3.7 any more - "matplotlib>=3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", + "matplotlib>=3.5.0,<3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", "plotly>=5.3.0", # matplotlib requires Pillow; however, Pillow >= 8.4 does not # provide manylinux2010 wheels any more, but we need those in From a3d8f48f925c92eb402cf9b66628d029abd3d0ab Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Fri, 30 Sep 2022 14:37:48 +0200 Subject: [PATCH 1079/1892] doc: Corrected name of argument. (#578) --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f937f5267..2c84edf5f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13411,7 +13411,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Generates a tree in which almost all vertices have the same number of children.\n\n" "@param n: the number of vertices in the graph\n" "@param children: the number of children of a vertex in the graph\n" - "@param type: determines whether the tree should be directed, and if\n" + "@param mode: determines whether the tree should be directed, and if\n" " this is the case, also its orientation. Must be one of\n" " C{\"in\"}, C{\"out\"} and C{\"undirected\"}.\n"}, From 08b33723322412860a7f5b4759e8bf43b47e84cf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Sep 2022 21:04:05 +0200 Subject: [PATCH 1080/1892] fix: replace deprecated unittest.makeSuite() --- tests/drawing/cairo/test_graph.py | 4 ++-- tests/drawing/matplotlib/test_graph.py | 4 ++-- tests/drawing/plotly/test_graph.py | 4 ++-- tests/test_atlas.py | 4 ++-- tests/test_attributes.py | 6 +++--- tests/test_basic.py | 18 +++++++++--------- tests/test_bipartite.py | 2 +- tests/test_cliques.py | 4 ++-- tests/test_colortests.py | 4 ++-- tests/test_conversion.py | 4 ++-- tests/test_cycles.py | 2 +- tests/test_decomposition.py | 14 +++++++------- tests/test_edgeseq.py | 4 ++-- tests/test_flow.py | 6 +++--- tests/test_foreign.py | 2 +- tests/test_games.py | 2 +- tests/test_generators.py | 2 +- tests/test_homepage.py | 2 +- tests/test_indexing.py | 2 +- tests/test_isomorphism.py | 6 +++--- tests/test_iterators.py | 2 +- tests/test_layouts.py | 4 ++-- tests/test_matching.py | 4 ++-- tests/test_motifs.py | 4 ++-- tests/test_operators.py | 2 +- tests/test_rng.py | 2 +- tests/test_separators.py | 2 +- tests/test_spectral.py | 2 +- tests/test_structural.py | 18 +++++++++--------- tests/test_unicode_issues.py | 2 +- tests/test_vertexseq.py | 4 ++-- tests/test_walks.py | 2 +- 32 files changed, 72 insertions(+), 72 deletions(-) diff --git a/tests/drawing/cairo/test_graph.py b/tests/drawing/cairo/test_graph.py index 7ffdea110..eacec226d 100644 --- a/tests/drawing/cairo/test_graph.py +++ b/tests/drawing/cairo/test_graph.py @@ -89,8 +89,8 @@ def test_clustering_directed_large(self): def suite(): - graph = unittest.makeSuite(GraphTestRunner) - clustering = unittest.makeSuite(ClusteringTestRunner) + graph = unittest.defaultTestLoader.loadTestsFromTestCase(GraphTestRunner) + clustering = unittest.defaultTestLoader.loadTestsFromTestCase(ClusteringTestRunner) return unittest.TestSuite([ graph, clustering, diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index eefb92033..1bfda8e1f 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -172,8 +172,8 @@ def test_clustering_directed_large(self): def suite(): - graph = unittest.makeSuite(GraphTestRunner) - clustering = unittest.makeSuite(ClusteringTestRunner) + graph = unittest.defaultTestLoader.loadTestsFromTestCase(GraphTestRunner) + clustering = unittest.defaultTestLoader.loadTestsFromTestCase(ClusteringTestRunner) return unittest.TestSuite([graph, clustering]) diff --git a/tests/drawing/plotly/test_graph.py b/tests/drawing/plotly/test_graph.py index 6f628380c..22ca84b9b 100644 --- a/tests/drawing/plotly/test_graph.py +++ b/tests/drawing/plotly/test_graph.py @@ -177,8 +177,8 @@ def test_clustering_directed_large(self): def suite(): - graph = unittest.makeSuite(GraphTestRunner) - clustering = unittest.makeSuite(ClusteringTestRunner) + graph = unittest.defaultTestLoader.loadTestsFromTestCase(GraphTestRunner) + clustering = unittest.defaultTestLoader.loadTestsFromTestCase(ClusteringTestRunner) return unittest.TestSuite([ graph, clustering, diff --git a/tests/test_atlas.py b/tests/test_atlas.py index d1b96b7c5..6e040f727 100644 --- a/tests/test_atlas.py +++ b/tests/test_atlas.py @@ -173,8 +173,8 @@ class IsoclassTests(unittest.TestCase, AtlasTestBase): def suite(): - atlas_suite = unittest.makeSuite(GraphAtlasTests) - isoclass_suite = unittest.makeSuite(IsoclassTests) + atlas_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphAtlasTests) + isoclass_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IsoclassTests) return unittest.TestSuite([atlas_suite, isoclass_suite]) diff --git a/tests/test_attributes.py b/tests/test_attributes.py index c7d3e6515..a1af53ce1 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -267,9 +267,9 @@ def testUnicodeAttributeNameCombination(self): def suite(): - attribute_suite = unittest.makeSuite(AttributeTests) - attribute_combination_suite = unittest.makeSuite(AttributeCombinationTests) - unicode_attributes_suite = unittest.makeSuite(UnicodeAttributeTests) + attribute_suite = unittest.defaultTestLoader.loadTestsFromTestCase(AttributeTests) + attribute_combination_suite = unittest.defaultTestLoader.loadTestsFromTestCase(AttributeCombinationTests) + unicode_attributes_suite = unittest.defaultTestLoader.loadTestsFromTestCase(UnicodeAttributeTests) return unittest.TestSuite([ attribute_suite, attribute_combination_suite, diff --git a/tests/test_basic.py b/tests/test_basic.py index bf4710e07..a342d84fa 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -943,15 +943,15 @@ def testVertexSeqReferenceCounting(self): def suite(): - basic_suite = unittest.makeSuite(BasicTests) - datatype_suite = unittest.makeSuite(DatatypeTests) - graph_dict_list_suite = unittest.makeSuite(GraphDictListTests) - graph_tuple_list_suite = unittest.makeSuite(GraphTupleListTests) - graph_list_dict_suite = unittest.makeSuite(GraphListDictTests) - graph_dict_dict_suite = unittest.makeSuite(GraphDictDictTests) - degree_sequence_suite = unittest.makeSuite(DegreeSequenceTests) - inheritance_suite = unittest.makeSuite(InheritanceTests) - refcount_suite = unittest.makeSuite(ReferenceCountTests) + basic_suite = unittest.defaultTestLoader.loadTestsFromTestCase(BasicTests) + datatype_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DatatypeTests) + graph_dict_list_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphDictListTests) + graph_tuple_list_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphTupleListTests) + graph_list_dict_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphListDictTests) + graph_dict_dict_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphDictDictTests) + degree_sequence_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DegreeSequenceTests) + inheritance_suite = unittest.defaultTestLoader.loadTestsFromTestCase(InheritanceTests) + refcount_suite = unittest.defaultTestLoader.loadTestsFromTestCase(ReferenceCountTests) return unittest.TestSuite( [ basic_suite, diff --git a/tests/test_bipartite.py b/tests/test_bipartite.py index a5ed90029..23ec6554f 100644 --- a/tests/test_bipartite.py +++ b/tests/test_bipartite.py @@ -216,7 +216,7 @@ def testIsBipartite(self): def suite(): - bipartite_suite = unittest.makeSuite(BipartiteTests) + bipartite_suite = unittest.defaultTestLoader.loadTestsFromTestCase(BipartiteTests) return unittest.TestSuite([bipartite_suite]) diff --git a/tests/test_cliques.py b/tests/test_cliques.py index cb952d220..2b7e6692a 100644 --- a/tests/test_cliques.py +++ b/tests/test_cliques.py @@ -249,8 +249,8 @@ def testGRG(self): def suite(): - clique_suite = unittest.makeSuite(CliqueTests) - indvset_suite = unittest.makeSuite(IndependentVertexSetTests) + clique_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CliqueTests) + indvset_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IndependentVertexSetTests) return unittest.TestSuite([clique_suite, indvset_suite]) diff --git a/tests/test_colortests.py b/tests/test_colortests.py index e254e4656..ffedf5a33 100644 --- a/tests/test_colortests.py +++ b/tests/test_colortests.py @@ -104,8 +104,8 @@ def testAdvancedGradientPalette(self): def suite(): - color_suite = unittest.makeSuite(ColorTests) - palette_suite = unittest.makeSuite(PaletteTests) + color_suite = unittest.defaultTestLoader.loadTestsFromTestCase(ColorTests) + palette_suite = unittest.defaultTestLoader.loadTestsFromTestCase(PaletteTests) return unittest.TestSuite([color_suite, palette_suite]) diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 5bfd443bb..55817a02e 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -174,8 +174,8 @@ def testGetSparseAdjacency(self): def suite(): - direction_suite = unittest.makeSuite(DirectedUndirectedTests) - representation_suite = unittest.makeSuite(GraphRepresentationTests) + direction_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DirectedUndirectedTests) + representation_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphRepresentationTests) return unittest.TestSuite([direction_suite, representation_suite]) diff --git a/tests/test_cycles.py b/tests/test_cycles.py index 8d8260a41..325a9ca9d 100644 --- a/tests/test_cycles.py +++ b/tests/test_cycles.py @@ -170,7 +170,7 @@ def test_minimum_cycle_basis(self): def suite(): - cycle_suite = unittest.makeSuite(CycleTests) + cycle_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CycleTests) return unittest.TestSuite([cycle_suite]) diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index b3e864699..19be7ecf9 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -649,13 +649,13 @@ def testRemoveNone(self): def suite(): - decomposition_suite = unittest.makeSuite(DecompositionTests) - clustering_suite = unittest.makeSuite(ClusteringTests) - vertex_clustering_suite = unittest.makeSuite(VertexClusteringTests) - cover_suite = unittest.makeSuite(CoverTests) - community_suite = unittest.makeSuite(CommunityTests) - cohesive_blocks_suite = unittest.makeSuite(CohesiveBlocksTests) - comparison_suite = unittest.makeSuite(ComparisonTests) + decomposition_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DecompositionTests) + clustering_suite = unittest.defaultTestLoader.loadTestsFromTestCase(ClusteringTests) + vertex_clustering_suite = unittest.defaultTestLoader.loadTestsFromTestCase(VertexClusteringTests) + cover_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CoverTests) + community_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CommunityTests) + cohesive_blocks_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CohesiveBlocksTests) + comparison_suite = unittest.defaultTestLoader.loadTestsFromTestCase(ComparisonTests) return unittest.TestSuite( [ decomposition_suite, diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index ae5e40ae8..df14bd490 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -419,8 +419,8 @@ def testIsAll(self): def suite(): - edge_suite = unittest.makeSuite(EdgeTests) - es_suite = unittest.makeSuite(EdgeSeqTests) + edge_suite = unittest.defaultTestLoader.loadTestsFromTestCase(EdgeTests) + es_suite = unittest.defaultTestLoader.loadTestsFromTestCase(EdgeSeqTests) return unittest.TestSuite([edge_suite, es_suite]) diff --git a/tests/test_flow.py b/tests/test_flow.py index 188b8b188..239046ac7 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -249,9 +249,9 @@ def validate_gomory_hu_tree(self, g, t): def suite(): - flow_suite = unittest.makeSuite(MaxFlowTests) - cut_suite = unittest.makeSuite(CutTests) - gomory_hu_suite = unittest.makeSuite(GomoryHuTests) + flow_suite = unittest.defaultTestLoader.loadTestsFromTestCase(MaxFlowTests) + cut_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CutTests) + gomory_hu_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GomoryHuTests) return unittest.TestSuite([flow_suite, cut_suite, gomory_hu_suite]) diff --git a/tests/test_foreign.py b/tests/test_foreign.py index a6890927d..192ee8959 100644 --- a/tests/test_foreign.py +++ b/tests/test_foreign.py @@ -884,7 +884,7 @@ def testMultigraphGraphTool(self): def suite(): - foreign_suite = unittest.makeSuite(ForeignTests) + foreign_suite = unittest.defaultTestLoader.loadTestsFromTestCase(ForeignTests) return unittest.TestSuite([foreign_suite]) diff --git a/tests/test_games.py b/tests/test_games.py index 447196dde..c93a00742 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -187,7 +187,7 @@ def testRewire(self): def suite(): - game_suite = unittest.makeSuite(GameTests) + game_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GameTests) return unittest.TestSuite([game_suite]) diff --git a/tests/test_generators.py b/tests/test_generators.py index fe79b738f..88b319610 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -564,7 +564,7 @@ def testDataFrame(self): def suite(): - generator_suite = unittest.makeSuite(GeneratorTests) + generator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GeneratorTests) return unittest.TestSuite([generator_suite]) diff --git a/tests/test_homepage.py b/tests/test_homepage.py index b8a61eb5b..84eed6581 100644 --- a/tests/test_homepage.py +++ b/tests/test_homepage.py @@ -38,7 +38,7 @@ def distance(p1, p2): def suite(): - homepage_example_suite = unittest.makeSuite(HomepageExampleTests) + homepage_example_suite = unittest.defaultTestLoader.loadTestsFromTestCase(HomepageExampleTests) return unittest.TestSuite([homepage_example_suite]) diff --git a/tests/test_indexing.py b/tests/test_indexing.py index 97f5897fa..2a6423550 100644 --- a/tests/test_indexing.py +++ b/tests/test_indexing.py @@ -41,7 +41,7 @@ def testSingleEdgeRetrievalAttrName(self): def suite(): - adjacency_suite = unittest.makeSuite(GraphAdjacencyMatrixLikeIndexingTests) + adjacency_suite = unittest.defaultTestLoader.loadTestsFromTestCase(GraphAdjacencyMatrixLikeIndexingTests) return unittest.TestSuite([adjacency_suite]) diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index 48efff370..a0ecb509e 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -407,9 +407,9 @@ def testPermuteVertices(self): def suite(): - isomorphism_suite = unittest.makeSuite(IsomorphismTests) - subisomorphism_suite = unittest.makeSuite(SubisomorphismTests) - permutation_suite = unittest.makeSuite(PermutationTests) + isomorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IsomorphismTests) + subisomorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(SubisomorphismTests) + permutation_suite = unittest.defaultTestLoader.loadTestsFromTestCase(PermutationTests) return unittest.TestSuite([ isomorphism_suite, subisomorphism_suite, diff --git a/tests/test_iterators.py b/tests/test_iterators.py index 9ce63aabb..cc9e5e2a6 100644 --- a/tests/test_iterators.py +++ b/tests/test_iterators.py @@ -60,7 +60,7 @@ def testDFSIter(self): def suite(): - iterator_suite = unittest.makeSuite(IteratorTests) + iterator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IteratorTests) return unittest.TestSuite([iterator_suite]) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 142a5de5d..e97f397f6 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -368,8 +368,8 @@ def testDRL(self): def suite(): - layout_suite = unittest.makeSuite(LayoutTests) - layout_algorithm_suite = unittest.makeSuite(LayoutAlgorithmTests) + layout_suite = unittest.defaultTestLoader.loadTestsFromTestCase(LayoutTests) + layout_algorithm_suite = unittest.defaultTestLoader.loadTestsFromTestCase(LayoutAlgorithmTests) return unittest.TestSuite([layout_suite, layout_algorithm_suite]) diff --git a/tests/test_matching.py b/tests/test_matching.py index 3ef3a1e92..384df76e4 100644 --- a/tests/test_matching.py +++ b/tests/test_matching.py @@ -89,8 +89,8 @@ def testBipartiteMatchingErrors(self): def suite(): - matching_suite = unittest.makeSuite(MatchingTests) - bipartite_unweighted_suite = unittest.makeSuite(MaximumBipartiteMatchingTests) + matching_suite = unittest.defaultTestLoader.loadTestsFromTestCase(MatchingTests) + bipartite_unweighted_suite = unittest.defaultTestLoader.loadTestsFromTestCase(MaximumBipartiteMatchingTests) return unittest.TestSuite([matching_suite, bipartite_unweighted_suite]) diff --git a/tests/test_motifs.py b/tests/test_motifs.py index f19e96b4c..d0f9131fa 100644 --- a/tests/test_motifs.py +++ b/tests/test_motifs.py @@ -54,8 +54,8 @@ def testListTriangles(self): def suite(): - motif_suite = unittest.makeSuite(MotifTests) - triangles_suite = unittest.makeSuite(TrianglesTests) + motif_suite = unittest.defaultTestLoader.loadTestsFromTestCase(MotifTests) + triangles_suite = unittest.defaultTestLoader.loadTestsFromTestCase(TrianglesTests) return unittest.TestSuite([motif_suite, triangles_suite]) diff --git a/tests/test_operators.py b/tests/test_operators.py index 2f75560ab..ecc9f73c5 100644 --- a/tests/test_operators.py +++ b/tests/test_operators.py @@ -543,7 +543,7 @@ def testReverseEdges(self): def suite(): - operator_suite = unittest.makeSuite(OperatorTests) + operator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(OperatorTests) return unittest.TestSuite([operator_suite]) diff --git a/tests/test_rng.py b/tests/test_rng.py index 5e078eada..e32490214 100644 --- a/tests/test_rng.py +++ b/tests/test_rng.py @@ -43,7 +43,7 @@ def testSeeding(self): def suite(): - random_suite = unittest.makeSuite(RandomNumberGeneratorTests) + random_suite = unittest.defaultTestLoader.loadTestsFromTestCase(RandomNumberGeneratorTests) return unittest.TestSuite([random_suite]) diff --git a/tests/test_separators.py b/tests/test_separators.py index c5d144b9c..29a63ebb8 100644 --- a/tests/test_separators.py +++ b/tests/test_separators.py @@ -60,7 +60,7 @@ def testMinimumSizeSeparators(self): def suite(): - is_separator_suite = unittest.makeSuite(IsSeparatorTests) + is_separator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IsSeparatorTests) return unittest.TestSuite([is_separator_suite]) diff --git a/tests/test_spectral.py b/tests/test_spectral.py index 14689a93e..5a959bf79 100644 --- a/tests/test_spectral.py +++ b/tests/test_spectral.py @@ -72,7 +72,7 @@ def testLaplacian(self): def suite(): - spectral_suite = unittest.makeSuite(SpectralTests) + spectral_suite = unittest.defaultTestLoader.loadTestsFromTestCase(SpectralTests) return unittest.TestSuite([spectral_suite]) diff --git a/tests/test_structural.py b/tests/test_structural.py index b39f948a7..610319139 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -1034,15 +1034,15 @@ def testDominators(self): def suite(): - simple_suite = unittest.makeSuite(SimplePropertiesTests) - degree_suite = unittest.makeSuite(DegreeTests) - local_transitivity_suite = unittest.makeSuite(LocalTransitivityTests) - biconnected_suite = unittest.makeSuite(BiconnectedComponentTests) - centrality_suite = unittest.makeSuite(CentralityTests) - neighborhood_suite = unittest.makeSuite(NeighborhoodTests) - path_suite = unittest.makeSuite(PathTests) - misc_suite = unittest.makeSuite(MiscTests) - dominator_suite = unittest.makeSuite(DominatorTests) + simple_suite = unittest.defaultTestLoader.loadTestsFromTestCase(SimplePropertiesTests) + degree_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DegreeTests) + local_transitivity_suite = unittest.defaultTestLoader.loadTestsFromTestCase(LocalTransitivityTests) + biconnected_suite = unittest.defaultTestLoader.loadTestsFromTestCase(BiconnectedComponentTests) + centrality_suite = unittest.defaultTestLoader.loadTestsFromTestCase(CentralityTests) + neighborhood_suite = unittest.defaultTestLoader.loadTestsFromTestCase(NeighborhoodTests) + path_suite = unittest.defaultTestLoader.loadTestsFromTestCase(PathTests) + misc_suite = unittest.defaultTestLoader.loadTestsFromTestCase(MiscTests) + dominator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(DominatorTests) return unittest.TestSuite( [ simple_suite, diff --git a/tests/test_unicode_issues.py b/tests/test_unicode_issues.py index 543f871e5..1c782adbd 100644 --- a/tests/test_unicode_issues.py +++ b/tests/test_unicode_issues.py @@ -14,7 +14,7 @@ def testBug128(self): def suite(): - generator_suite = unittest.makeSuite(UnicodeTests) + generator_suite = unittest.defaultTestLoader.loadTestsFromTestCase(UnicodeTests) return unittest.TestSuite([generator_suite]) diff --git a/tests/test_vertexseq.py b/tests/test_vertexseq.py index a2587ebfd..fb804cc6a 100644 --- a/tests/test_vertexseq.py +++ b/tests/test_vertexseq.py @@ -361,8 +361,8 @@ def testBug367(self): def suite(): - vertex_suite = unittest.makeSuite(VertexTests) - vs_suite = unittest.makeSuite(VertexSeqTests) + vertex_suite = unittest.defaultTestLoader.loadTestsFromTestCase(VertexTests) + vs_suite = unittest.defaultTestLoader.loadTestsFromTestCase(VertexSeqTests) return unittest.TestSuite([vertex_suite, vs_suite]) diff --git a/tests/test_walks.py b/tests/test_walks.py index ac887d507..760a3937c 100644 --- a/tests/test_walks.py +++ b/tests/test_walks.py @@ -110,7 +110,7 @@ def testRandomWalkUndirectedWeighted(self): def suite(): - random_walk_suite = unittest.makeSuite(RandomWalkTests) + random_walk_suite = unittest.defaultTestLoader.loadTestsFromTestCase(RandomWalkTests) return unittest.TestSuite([random_walk_suite]) From ed5fdd4865d2cc5af558ddb2e9c4b81f07a6c7f2 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Mon, 3 Oct 2022 15:06:02 +0200 Subject: [PATCH 1081/1892] Update cibuildwheel, add dependabot. (#579) * doc: Corrected name of argument. * CI: Update cibuildwheel, add dependabot. * ci: skip tests for Python 3.11 because SciPy does not have wheels yet * ci: also skip tests of Python 3.11 on macOS * CI: Use Python 3.11 for ASan tests. * CI: Update to 3.11.0-rc.2 for ASan tests. * CI: Remove extra test dependencies for Python 3.11 * Accidentally reverted submodule. * Simplify build setup. Co-authored-by: Tamas Nepusz --- .github/dependabot.yml | 6 ++++++ .github/workflows/build.yml | 32 ++++++++++++++++---------------- 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 935d8617c..5e1aad3f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,10 +5,6 @@ env: CIBW_ENVIRONMENT_PASS_LINUX: PYTEST_TIMEOUT CIBW_TEST_COMMAND: "cd {project} && python -m pytest -v tests" CIBW_TEST_EXTRAS: "test" - CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" - CIBW_MANYLINUX_I686_IMAGE: "manylinux2014" - CIBW_MANYLINUX_PYPY_X86_64_IMAGE: "manylinux2014" - CIBW_MANYLINUX_PYPY_I686_IMAGE: "manylinux2014" CIBW_SKIP: "cp36-*" PYTEST_TIMEOUT: 60 MACOSX_DEPLOYMENT_TARGET: "10.9" @@ -34,16 +30,17 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit - # wheel for Linux yet - CIBW_TEST_SKIP: "cp310-manylinux_i686" + # wheel for Linux yet, and for Python 3.11 because SciPy does not + # have wheels for 3.11 at all + CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-*" - name: Build wheels (musllinux) - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -68,14 +65,14 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Build wheels (manylinux) - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -142,12 +139,14 @@ jobs: cmake --install . - name: Build wheels - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_ENVIRONMENT: "LDFLAGS=-L$HOME/local/lib" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} -DCMAKE_PREFIX_PATH=$HOME/local + # Skip tests for Python 3.11 because SciPy does not have wheels for 3.11 at all + CIBW_TEST_SKIP: "cp311-*" - uses: actions/upload-artifact@v2 with: @@ -201,13 +200,14 @@ jobs: shell: cmd - name: Build wheels - uses: joerick/cibuildwheel@v2.6.1 + uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 because SciPy does not have a 32-bit - # wheel for Python 3.10 yet - CIBW_TEST_SKIP: "cp310-win32" + # wheel for Python 3.10 yet, and for Python 3.11 because SciPy does + # not have wheels for Python 3.11 at all yet + CIBW_TEST_SKIP: "cp310-win32 cp311-*" CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ @@ -299,7 +299,7 @@ jobs: - uses: actions/setup-python@v2 name: Install Python with: - python-version: '3.10' + python-version: '3.11.0-rc.2' - name: Build C core run: | @@ -312,7 +312,7 @@ jobs: - name: Install test dependencies run: | - pip install --prefer-binary pytest pytest-timeout numpy scipy pandas networkx + pip install --prefer-binary pytest pytest-timeout # Only pytest, and nothing else should be run in this section due to the presence of LD_PRELOAD. # The ASan/UBSan library versions need to be updated when switching to a newer Ubuntu/GCC. From c048d99642f8f04b51a705f51d900833d7d0894f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Oct 2022 15:28:07 +0200 Subject: [PATCH 1082/1892] fix: eliminate unit test warnings in Python 3.11 --- src/igraph/io/objects.py | 4 ++-- tests/drawing/cairo/utils.py | 2 -- tests/drawing/plotly/utils.py | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 181fcaaff..bc22c9559 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -476,8 +476,8 @@ def _construct_graph_from_dataframe( # Map source and target names in 'edges' to IDs vid_map = pd.Series(vertices.index, index=vertices.iloc[:, 0]) edges = edges.copy() - edges.iloc[:, 0] = edges.iloc[:, 0].map(vid_map) - edges.iloc[:, 1] = edges.iloc[:, 1].map(vid_map) + edges[edges.columns[0]] = edges.iloc[:, 0].map(vid_map) + edges[edges.columns[1]] = edges.iloc[:, 1].map(vid_map) # Create graph if vertices is None: diff --git a/tests/drawing/cairo/utils.py b/tests/drawing/cairo/utils.py index 382253051..443aa1e2d 100644 --- a/tests/drawing/cairo/utils.py +++ b/tests/drawing/cairo/utils.py @@ -130,8 +130,6 @@ def wrapper(*args, **kwargs): res = compare_image(baseline, fig, tol) self.assertLessEqual(res, tol) - return figs - parameters = list(old_sig.parameters.values()) new_sig = old_sig.replace(parameters=parameters) wrapper.__signature__ = new_sig diff --git a/tests/drawing/plotly/utils.py b/tests/drawing/plotly/utils.py index eaf54dca9..76d96e346 100644 --- a/tests/drawing/plotly/utils.py +++ b/tests/drawing/plotly/utils.py @@ -220,8 +220,6 @@ def wrapper(*args, **kwargs): res = compare_image(baseline, fig, tol) assert res, f"Image {i} does not match the corresponding baseline" - return figs - parameters = list(old_sig.parameters.values()) new_sig = old_sig.replace(parameters=parameters) wrapper.__signature__ = new_sig From 67eab78397c8e44d714d18455bf78c411cf83895 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Oct 2022 17:58:18 +0200 Subject: [PATCH 1083/1892] fix: Graph.is_chordal() is not dropping a reference to True/False any more --- src/_igraph/graphobject.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 2c84edf5f..ec7f4bb13 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5302,7 +5302,11 @@ PyObject *igraphmodule_Graph_is_chordal( igraph_vector_int_destroy(alpham1_ptr); } - return res ? Py_True : Py_False; + if (res) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } } /** \ingroup python_interface_graph From 04950e50604a6a923253a4e85aad8ccd6ee5d763 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:12:08 +0200 Subject: [PATCH 1084/1892] build(deps): bump actions/setup-python from 2 to 4 (#586) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 4. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e1aad3f6..240e4a1df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: submodules: true fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.8' @@ -117,7 +117,7 @@ jobs: path: ~/local key: deps-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }} - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.8' @@ -171,7 +171,7 @@ jobs: submodules: true fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.8' @@ -241,7 +241,7 @@ jobs: run: sudo apt install ninja-build cmake flex bison - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.8' @@ -296,7 +296,7 @@ jobs: run: sudo apt install ninja-build cmake flex bison - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.11.0-rc.2' From d3e4d6aa98a3f6e3309b0fa2fe9845b4eb5e49b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:12:26 +0200 Subject: [PATCH 1085/1892] build(deps): bump actions/upload-artifact from 2 to 3 (#585) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 240e4a1df..f761db9d0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_EXTRAS: "test-musl" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl @@ -79,7 +79,7 @@ jobs: CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_EXTRAS: "test-musl" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl @@ -148,7 +148,7 @@ jobs: # Skip tests for Python 3.11 because SciPy does not have wheels for 3.11 at all CIBW_TEST_SKIP: "cp311-*" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl @@ -215,7 +215,7 @@ jobs: IGRAPH_EXTRA_LIBRARIES: libxml2,lzma,zlib,iconv,charset IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl @@ -257,7 +257,7 @@ jobs: pip install --prefer-binary numpy scipy pandas networkx pytest pytest-timeout python -m pytest -v tests - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: dist/*.tar.gz From f232cf1ae3a010de7a5dc3edd17507b198f3fc63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:12:42 +0200 Subject: [PATCH 1086/1892] build(deps): bump actions/checkout from 2 to 3 (#584) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f761db9d0..c9b257b74 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: wheel_arch: [x86_64, i686] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -55,7 +55,7 @@ jobs: runs-on: ubuntu-20.04 if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -98,7 +98,7 @@ jobs: wheel_arch: arm64 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -166,7 +166,7 @@ jobs: vcpkg_arch: x64 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -223,7 +223,7 @@ jobs: name: Build sdist and test extra dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -277,7 +277,7 @@ jobs: CXXFLAGS: "-g -Og -fno-omit-frame-pointer -fdiagnostics-color" IGRAPH_CMAKE_EXTRA_ARGS: -DUSE_SANITIZER="Address;Undefined" -DCMAKE_BUILD_TYPE=Debug -DFLEX_KEEP_LINE_NUMBERS=ON -DFORCE_COLORED_OUTPUT=ON -DCMAKE_C_FLAGS="-DNDEBUG" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 From 8275fc830451c6dca7ccbc216b44fb4358fba48b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:12:52 +0200 Subject: [PATCH 1087/1892] build(deps): bump actions/cache from 2 to 3 (#583) Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9b257b74..8abaa7d3a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -105,14 +105,14 @@ jobs: - name: Cache installed C core id: cache-c-core - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: vendor/install key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }}-${{ hashFiles('.git/modules/**/HEAD') }} - name: Cache C core dependencies id: cache-c-deps - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/local key: deps-cache-v2-${{ runner.os }}-${{ matrix.cmake_arch }}-llvm${{ env.LLVM_VERSION }} @@ -178,13 +178,13 @@ jobs: - name: Cache installed C core id: cache-c-core - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: vendor/install key: C-core-cache-${{ runner.os }}-${{ matrix.cmake_arch }}-${{ hashFiles('.git/modules/**/HEAD') }} - name: Cache VCPKG - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: C:/vcpkg/installed/ key: vcpkg-${{ runner.os }}-${{ matrix.vcpkg_arch }} @@ -230,7 +230,7 @@ jobs: - name: Cache installed C core id: cache-c-core - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | vendor/install @@ -284,7 +284,7 @@ jobs: - name: Cache installed C core id: cache-c-core - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | vendor/build From 810629cbb2e3f5fc2954f55542b2a7ae0f91cf89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:13:01 +0200 Subject: [PATCH 1088/1892] build(deps): bump docker/setup-qemu-action from 1 to 2 (#582) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1 to 2. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v1...v2) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8abaa7d3a..2873fb875 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: - name: Set up QEMU id: qemu - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) uses: pypa/cibuildwheel@v2.10.2 From 63b287a86639feb253d5eeddab7202408204ef8a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Oct 2022 23:22:41 +0200 Subject: [PATCH 1089/1892] doc: fix documentation of Graph.get_eids() as the path=... argument was removed from the C core, fixes #581 --- src/_igraph/graphobject.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index ec7f4bb13..b2c0d7966 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12885,23 +12885,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_eids */ {"get_eids", (PyCFunction) igraphmodule_Graph_get_eids, METH_VARARGS | METH_KEYWORDS, - "get_eids(pairs=None, path=None, directed=True, error=True)\n--\n\n" + "get_eids(pairs=None, directed=True, error=True)\n--\n\n" "Returns the edge IDs of some edges between some vertices.\n\n" - "This method can operate in two different modes, depending on which\n" - "of the keyword arguments C{pairs} and C{path} are given.\n\n" "The method does not consider multiple edges; if there are multiple\n" "edges between a pair of vertices, only the ID of one of the edges\n" "is returned.\n\n" "@param pairs: a list of integer pairs. Each integer pair is considered\n" " as a source-target vertex pair; the corresponding edge is looked up\n" " in the graph and the edge ID is returned for each pair.\n" - "@param path: a list of vertex IDs. The list is considered as a\n" - " continuous path from the first vertex to the last, passing\n" - " through the intermediate vertices. The corresponding edge IDs\n" - " between the first and the second, the second and the third and\n" - " so on are looked up in the graph and the edge IDs are returned.\n" - " If both C{path} and C{pairs} are given, the two lists are\n" - " concatenated.\n" "@param directed: whether edge directions should be considered in\n" " directed graphs. The default is C{True}. Ignored for undirected\n" " graphs.\n" From 885662dd623ef1362f9e0ca43208a5cf81d40a93 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Oct 2022 23:57:53 +0200 Subject: [PATCH 1090/1892] fix: Graph.modularity() and Graph.community_multilevel() now correctly exposes the resolution parameter, fixes #553 --- src/_igraph/graphobject.c | 5 ++--- src/igraph/community.py | 38 +++++++++++++++++++++++++++---------- tests/conftest.py | 22 +++++++++++++++++++++ tests/test_decomposition.py | 8 ++++++++ 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 tests/conftest.py diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index b2c0d7966..395e22ab4 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -16575,8 +16575,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " C{True} will use the directed variant of the modularity measure where the\n" " in- and out-degrees of nodes are treated separately; C{False} will treat\n" " directed graphs as undirected.\n" - "@return: the modularity score. Score larger than 0.3 usually indicates\n" - " strong community structure.\n" + "@return: the modularity score.\n" "@newfield ref: Reference\n" "@ref: MEJ Newman and M Girvan: Finding and evaluating community structure\n" " in networks. Phys Rev E 69 026113, 2004.\n" @@ -16702,7 +16701,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"community_multilevel", (PyCFunction) igraphmodule_Graph_community_multilevel, METH_VARARGS | METH_KEYWORDS, - "community_multilevel(weights=None, return_levels=True, resolution=1)\n--\n\n" + "community_multilevel(weights=None, return_levels=False, resolution=1)\n--\n\n" "Finds the community structure of the graph according to the multilevel\n" "algorithm of Blondel et al. This is a bottom-up algorithm: initially\n" "every vertex belongs to a separate community, and vertices are moved\n" diff --git a/src/igraph/community.py b/src/igraph/community.py index 84d52edf9..a7628a358 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -192,7 +192,7 @@ def _community_label_propagation(graph, weights=None, initial=None, fixed=None): return VertexClustering(graph, cl, modularity_params=dict(weights=weights)) -def _community_multilevel(graph, weights=None, return_levels=False): +def _community_multilevel(graph, weights=None, return_levels=False, resolution=1): """Community structure based on the multilevel algorithm of Blondel et al. @@ -202,7 +202,7 @@ def _community_multilevel(graph, weights=None, return_levels=False): to the overall modularity score. When a consensus is reached (i.e. no single move would increase the modularity score), every community in the original graph is shrank to a single vertex (while keeping the - total weight of the adjacent edges) and the process continues on the + total weight of the incident edges) and the process continues on the next level. The algorithm stops when it is not possible to increase the modularity any more after shrinking the communities to vertices. @@ -213,6 +213,10 @@ def _community_multilevel(graph, weights=None, return_levels=False): @param return_levels: if C{True}, the communities at each level are returned in a list. If C{False}, only the community structure with the best modularity is returned. + @param resolution: the resolution parameter to use in the modularity + measure. Smaller values result in a smaller number of larger clusters, + while higher values yield a large number of small clusters. The classical + modularity measure assumes a resolution parameter of 1. @return: a list of L{VertexClustering} objects, one corresponding to each level (if C{return_levels} is C{True}), or a L{VertexClustering} corresponding to the best modularity. @@ -225,20 +229,26 @@ def _community_multilevel(graph, weights=None, return_levels=False): if graph.is_directed(): raise ValueError("input graph must be undirected") + modularity_params = dict(weights=weights, resolution=resolution) if return_levels: - levels, qs = GraphBase.community_multilevel(graph, weights, True) + levels, qs = GraphBase.community_multilevel( + graph, weights, return_levels=True, resolution=resolution + ) result = [] for level, q in zip(levels, qs): result.append( VertexClustering( - graph, level, q, modularity_params=dict(weights=weights) + graph, level, q, modularity_params=modularity_params ) ) else: - membership = GraphBase.community_multilevel(graph, weights, False) + membership = GraphBase.community_multilevel( + graph, weights, return_levels=False, resolution=resolution + ) result = VertexClustering( - graph, membership, modularity_params=dict(weights=weights) + graph, membership, modularity_params=modularity_params ) + return result @@ -485,18 +495,19 @@ def _community_leiden( return VertexClustering(graph, membership, modularity_params=modularity_params) -def _modularity(self, membership, weights=None): +def _modularity(self, membership, weights=None, resolution=1, directed=True): """Calculates the modularity score of the graph with respect to a given clustering. The modularity of a graph w.r.t. some division measures how good the division is, or how separated are the different vertex types from each - other. It's defined as M{Q=1/(2m)*sum(Aij-ki*kj/(2m)delta(ci,cj),i,j)}. + other. It's defined as M{Q=1/(2m)*sum(Aij-gamma*ki*kj/(2m)delta(ci,cj),i,j)}. M{m} is the number of edges, M{Aij} is the element of the M{A} adjacency matrix in row M{i} and column M{j}, M{ki} is the degree of node M{i}, M{kj} is the degree of node M{j}, and M{Ci} and C{cj} are - the types of the two vertices (M{i} and M{j}). M{delta(x,y)} is one iff - M{x=y}, 0 otherwise. + the types of the two vertices (M{i} and M{j}), and M{gamma} is a resolution + parameter that defaults to 1 for the classical definition of modularity. + M{delta(x,y)} is one iff M{x=y}, 0 otherwise. If edge weights are given, the definition of modularity is modified as follows: M{Aij} becomes the weight of the corresponding edge, M{ki} @@ -507,6 +518,13 @@ def _modularity(self, membership, weights=None): @param membership: a membership list or a L{VertexClustering} object @param weights: optional edge weights or C{None} if all edges are weighed equally. Attribute names are also allowed. + @param resolution: the resolution parameter I{gamma} in the formula above. + The classical definition of modularity is retrieved when the resolution + parameter is set to 1. + @param directed: whether to consider edge directions if the graph is directed. + C{True} will use the directed variant of the modularity measure where the + in- and out-degrees of nodes are treated separately; C{False} will treat + directed graphs as undirected. @return: the modularity score @newfield ref: Reference diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..9d0f7c610 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,22 @@ +import gc +import sys + +from pytest import fixture + + +@fixture(autouse=True) +def check_refcounts(): + objs = [True, False] + gc.collect() + refs = {} + for obj in objs: + refs[obj] = sys.getrefcount(obj) + gc.collect() + + yield + + gc.collect() + for obj in objs: + current = sys.getrefcount(obj) + if refs[obj] - current > 7: + raise RuntimeError(f"reference count of {obj} decreased from {refs[obj]} to {current}") diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 19be7ecf9..43be061a4 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -360,6 +360,7 @@ def testMultilevel(self): (10, 14), (11, 13), ] + cls = g.community_multilevel(return_levels=True) self.assertTrue(len(cls) == 2) self.assertMembershipsEqual( @@ -371,6 +372,13 @@ def testMultilevel(self): self.assertAlmostEqual(cls[0].q, 0.346301, places=5) self.assertAlmostEqual(cls[1].q, 0.392219, places=5) + cls = g.community_multilevel() + self.assertTrue(len(cls.membership) == g.vcount()) + self.assertMembershipsEqual( + cls, [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] + ) + self.assertAlmostEqual(cls.q, 0.392219, places=5) + def testOptimalModularity(self): try: g = Graph.Famous("bull") From 49931e0c5cb9370e5fe30c5d05b956a3c31b50d8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Oct 2022 00:40:51 +0200 Subject: [PATCH 1091/1892] fix: restored proper behaviour of power_law_fit(), p-values are now calculated again, fixes #580 --- src/_igraph/igraphmodule.c | 19 +++++++++++++------ tests/conftest.py | 22 ---------------------- 2 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 tests/conftest.py diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 2c67c5bd6..834a499fc 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -563,14 +563,15 @@ PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kw PyObject* igraphmodule_power_law_fit(PyObject *self, PyObject *args, PyObject *kwds) { - static char* kwlist[] = { "data", "xmin", "force_continuous", NULL }; + static char* kwlist[] = { "data", "xmin", "force_continuous", "p_precision", NULL }; PyObject *data_o, *force_continuous_o = Py_False; igraph_vector_t data; igraph_plfit_result_t result; - double xmin = -1; + double xmin = -1, p_precision = 0.01; + igraph_real_t p; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|dO", kwlist, &data_o, - &xmin, &force_continuous_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|dOd", kwlist, &data_o, + &xmin, &force_continuous_o, &p_precision)) return NULL; if (igraphmodule_PyObject_float_to_vector_t(data_o, &data)) @@ -582,10 +583,16 @@ PyObject* igraphmodule_power_law_fit(PyObject *self, PyObject *args, PyObject *k return NULL; } + if (igraph_plfit_result_calculate_p_value(&result, &p, p_precision)) { + igraphmodule_handle_igraph_error(); + igraph_vector_destroy(&data); + return NULL; + } + igraph_vector_destroy(&data); - return Py_BuildValue("Odddd", result.continuous ? Py_True : Py_False, - result.alpha, result.xmin, result.L, result.D); + return Py_BuildValue("Oddddd", result.continuous ? Py_True : Py_False, + result.alpha, result.xmin, result.L, result.D, (double) p); } PyObject* igraphmodule_split_join_distance(PyObject *self, diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 9d0f7c610..000000000 --- a/tests/conftest.py +++ /dev/null @@ -1,22 +0,0 @@ -import gc -import sys - -from pytest import fixture - - -@fixture(autouse=True) -def check_refcounts(): - objs = [True, False] - gc.collect() - refs = {} - for obj in objs: - refs[obj] = sys.getrefcount(obj) - gc.collect() - - yield - - gc.collect() - for obj in objs: - current = sys.getrefcount(obj) - if refs[obj] - current > 7: - raise RuntimeError(f"reference count of {obj} decreased from {refs[obj]} to {current}") From 383d43ba4efaf46b341ae79cdf58f0c900d9aa18 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Oct 2022 00:45:02 +0200 Subject: [PATCH 1092/1892] doc: documented p_precision parameter of power_law_fit() --- src/_igraph/igraphmodule.c | 2 +- src/igraph/statistics.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 834a499fc..06455e323 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -693,7 +693,7 @@ static PyMethodDef igraphmodule_methods[] = }, {"_power_law_fit", (PyCFunction)igraphmodule_power_law_fit, METH_VARARGS | METH_KEYWORDS, - "_power_law_fit(data, xmin=-1, force_continuous=False)\n--\n\n" + "_power_law_fit(data, xmin=-1, force_continuous=False, p_precision=0.01)\n--\n\n" }, {"convex_hull", (PyCFunction)igraphmodule_convex_hull, METH_VARARGS | METH_KEYWORDS, diff --git a/src/igraph/statistics.py b/src/igraph/statistics.py index 700e8d848..ca655eb54 100644 --- a/src/igraph/statistics.py +++ b/src/igraph/statistics.py @@ -502,7 +502,7 @@ def percentile(xs, p=(25, 50, 75), sort=True): return quantile(xs, p / 100.0, sort) -def power_law_fit(data, xmin=None, method="auto"): +def power_law_fit(data, xmin=None, method="auto", p_precision=0.01): """Fitting a power-law distribution to empirical data @param data: the data to fit, a list containing integer values @@ -530,6 +530,11 @@ def power_law_fit(data, xmin=None, method="auto"): method is used if the input vector contains at least one fractional value and the discrete method is used if the input vector contains integers only. + @param p_precision: desired precision of the p-value calculation. The + precision ultimately depends on the number of resampling attempts. The + number of resampling trials is determined by 0.25 divided by the square + of the required precision. For instance, a required precision of 0.01 + means that 2500 samples will be drawn. @return: a L{FittedPowerLaw} object. The fitted C{xmin} value and the power-law exponent can be queried from the C{xmin} and C{alpha} @@ -551,7 +556,7 @@ def power_law_fit(data, xmin=None, method="auto"): raise ValueError("unknown method: %s" % method) force_continuous = method in ("continuous", "hill") - return FittedPowerLaw(*_power_law_fit(data, xmin, force_continuous)) + return FittedPowerLaw(*_power_law_fit(data, xmin, force_continuous, p_precision)) def quantile(xs, q=(0.25, 0.5, 0.75), sort=True): From becc5884ee901655ca09f4e1856037787c3e353e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Oct 2022 08:53:37 +0200 Subject: [PATCH 1093/1892] doc: document that --use-pkg-config needed for both setup.py build and install, refs #574 [ci skip] --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 42225e01b..e3f08d811 100644 --- a/README.md +++ b/README.md @@ -127,9 +127,14 @@ Alternatively, if you have already downloaded and extracted the source code of igraph, you can run `setup.py` directly: ```bash +python setup.py build --use-pkg-config python setup.py install --use-pkg-config ``` +(Note that you need `--use-pkg-config` for both invocations, otherwise the call +to `setup.py install` would still build the vendored C core instead of linking +to an existing installation). + This option is primarily intended for package maintainers in Linux distributions so they can ensure that the packaged Python interface links to the packaged igraph library instead of bringing its own copy. From a452cd2e7674f79b7e06ad24a5983b11b54a5295 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 4 Oct 2022 08:57:02 +0200 Subject: [PATCH 1094/1892] doc: document that one needs SETUPTOOLS_USE_DISTUTILS=stdlib for MSYS2 [ci skip] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e3f08d811..7f5cb06be 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,9 @@ set IGRAPH_CMAKE_EXTRA_ARGS=-A [arch] ``` where `[arch]` is either `Win32` for 32-bit builds or `x64` for 64-bit builds. +Also, when building in MSYS2, you need to set the `SETUPTOOLS_USE_DISTUTILS` +environment variable to `stdlib`; this is because MSYS2 uses a patched version +of `distutils` that conflicts with `setuptools >= 60.0`. #### Enabling GraphML From 62a2501805454af4ed80de83915f1df620e2e80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Thu, 6 Oct 2022 11:38:14 +0200 Subject: [PATCH 1095/1892] docs: add references for Realize_Degree_Sequence --- src/_igraph/graphobject.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 395e22ab4..88bb5d08e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13331,6 +13331,26 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - C{smallest}: The vertex with smallest remaining degree first.\n" " - C{largest}: The vertex with the largest remaining degree first.\n" " - C{index}: The vertices are selected in order of their index.\n" + "\n" + "In the undirected case, C{smallest} is guaranteed to produce a connected graph.\n" + "See Horvát and Modes (2021) for details.\n" + "\n" + "@newfield ref: Reference\n" + "@ref: V. Havel,\n" + "Poznámka o existenci konečných grafů (A remark on the existence of finite graphs),\n" + "Časopis pro pěstování matematiky 80, 477-480 (1955).\n" + "http://eudml.org/doc/19050\n" + "@ref: S. L. Hakimi,\n" + "On Realizability of a Set of Integers as Degrees of the Vertices of a Linear Graph,\n" + "Journal of the SIAM 10, 3 (1962).\n" + "https://www.jstor.org/stable/2098770\n" + "@ref: D. J. Kleitman and D. L. Wang,\n" + "Algorithms for Constructing Graphs and Digraphs with Given Valences and Factors,\n" + "Discrete Mathematics 6, 1 (1973).\n" + "https://doi.org/10.1016/0012-365X%2873%2990037-X\n" + "@ref: Sz. Horvát and C. D. Modes,\n" + "Connectedness matters: construction and exact random sampling of connected networks (2021).\n" + "https://doi.org/10.1088/2632-072X/abced5\n" }, // interface to igraph_ring From 2a2f7a5354ce5655b13b51ac5257730826f47836 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 6 Oct 2022 15:01:00 +0200 Subject: [PATCH 1096/1892] doc: fix a few PyDoctor warnings while building the documentation --- src/_igraph/graphobject.c | 114 ++++++++++---------- src/_igraph/igraphmodule.c | 4 +- src/igraph/basic.py | 6 +- src/igraph/drawing/matplotlib/dendrogram.py | 4 +- src/igraph/io/objects.py | 12 +-- 5 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 88bb5d08e..f3881e802 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13332,25 +13332,25 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - C{largest}: The vertex with the largest remaining degree first.\n" " - C{index}: The vertices are selected in order of their index.\n" "\n" - "In the undirected case, C{smallest} is guaranteed to produce a connected graph.\n" - "See Horvát and Modes (2021) for details.\n" + " In the undirected case, C{smallest} is guaranteed to produce a connected graph.\n" + " See Horvát and Modes (2021) for details.\n" "\n" "@newfield ref: Reference\n" "@ref: V. Havel,\n" - "Poznámka o existenci konečných grafů (A remark on the existence of finite graphs),\n" - "Časopis pro pěstování matematiky 80, 477-480 (1955).\n" - "http://eudml.org/doc/19050\n" + " Poznámka o existenci konečných grafů (A remark on the existence of finite graphs),\n" + " Časopis pro pěstování matematiky 80, 477-480 (1955).\n" + " U{http://eudml.org/doc/19050}\n" "@ref: S. L. Hakimi,\n" - "On Realizability of a Set of Integers as Degrees of the Vertices of a Linear Graph,\n" - "Journal of the SIAM 10, 3 (1962).\n" - "https://www.jstor.org/stable/2098770\n" + " On Realizability of a Set of Integers as Degrees of the Vertices of a Linear Graph,\n" + " Journal of the SIAM 10, 3 (1962).\n" + " U{https://www.jstor.org/stable/2098770}\n" "@ref: D. J. Kleitman and D. L. Wang,\n" - "Algorithms for Constructing Graphs and Digraphs with Given Valences and Factors,\n" - "Discrete Mathematics 6, 1 (1973).\n" - "https://doi.org/10.1016/0012-365X%2873%2990037-X\n" + " Algorithms for Constructing Graphs and Digraphs with Given Valences and Factors,\n" + " Discrete Mathematics 6, 1 (1973).\n" + " U{https://doi.org/10.1016/0012-365X%2873%2990037-X}\n" "@ref: Sz. Horvát and C. D. Modes,\n" - "Connectedness matters: construction and exact random sampling of connected networks (2021).\n" - "https://doi.org/10.1088/2632-072X/abced5\n" + " Connectedness matters: construction and exact random sampling of connected networks (2021).\n" + " U{https://doi.org/10.1088/2632-072X/abced5}\n" }, // interface to igraph_ring @@ -13574,7 +13574,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_assortativity */ {"assortativity", (PyCFunction)igraphmodule_Graph_assortativity, METH_VARARGS | METH_KEYWORDS, - "assortativity(types1, types2=None, directed=True)\n--\n\n" + "assortativity(types1, types2=None, directed=True, normalized=True)\n--\n\n" "Returns the assortativity of the graph based on numeric properties\n" "of the vertices.\n\n" "This coefficient is basically the correlation between the actual\n" @@ -13823,9 +13823,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "connected_components(mode=\"strong\")\n--\n\n" "Calculates the (strong or weak) connected components for a given graph.\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{VertexClustering} object.\n" - " It is advised to use that.\n" + "Atttention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{VertexClustering} object.\n" + "It is advised to use that.\n" "@param mode: must be either C{\"strong\"} or C{\"weak\"}, depending on\n" " the clusters being sought. Optional, defaults to C{\"strong\"}.\n" "@return: the component index for every node in the graph.\n"}, @@ -14439,8 +14439,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "path_length_hist(directed=True)\n--\n\n" "Calculates the path length histogram of the graph\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param directed: whether to consider directed paths\n" "@return: a tuple. The first item of the tuple is a list of path lengths,\n" " the M{i}th element of the list contains the number of paths with length\n" @@ -14962,9 +14962,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "I{b} and also from I{b} to I{a}; asymmetric, there is an edge\n" "either from I{a} to I{b} or from I{b} to I{a} but not the other way\n" "and null, no edges between I{a} and I{b}.\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{DyadCensus} object.\n" - " It is advised to use that.\n\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{DyadCensus} object.\n" + "It is advised to use that.\n\n" "@return: the number of mutual, asymmetric and null connections in a\n" " 3-tuple." }, @@ -14976,10 +14976,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "vertices in a directed graph. A triplet can be in one of 16 states,\n" "these are listed in the documentation of the C interface of igraph.\n" "\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{TriadCensus} object.\n" - " It is advised to use that. The name of the triplet classes are\n" - " also documented there.\n\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{TriadCensus} object.\n" + "It is advised to use that. The name of the triplet classes are\n" + "also documented there.\n\n" }, {"list_triangles", (PyCFunction) igraphmodule_Graph_list_triangles, METH_NOARGS, @@ -16285,9 +16285,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_VARARGS | METH_KEYWORDS, "maxflow(source, target, capacity=None)\n--\n\n" "Returns the maximum flow between the source and target vertices.\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{Flow} object. It is advised\n" - " to use that.\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{Flow} object. It is advised\n" + "to use that.\n" "@param source: the source vertex ID\n" "@param target: the target vertex ID\n" "@param capacity: the capacity of the edges. It must be a list or a valid\n" @@ -16312,11 +16312,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "directed graph.\n\n" "This function lists all edge-cuts between a source and a target vertex.\n" "Every cut is listed exactly once.\n\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a list of L{Cut} objects. It is\n" + "advised to use that.\n" "@param source: the source vertex ID\n" "@param target: the target vertex ID\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a list of L{Cut} objects. It is\n" - " advised to use that.\n" "@return: a tuple where the first element is a list of lists of edge IDs\n" " representing a cut and the second element is a list of lists of vertex\n" " IDs representing the sets of vertices that were separated by the cuts.\n" @@ -16326,11 +16326,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "all_st_mincuts(source, target)\n--\n\n" "Returns all minimum cuts between the source and target vertices in a\n" "directed graph.\n\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a list of L{Cut} objects. It is\n" + "advised to use that.\n\n" "@param source: the source vertex ID\n" "@param target: the target vertex ID\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a list of L{Cut} objects. It is\n" - " advised to use that.\n" }, {"mincut_value", (PyCFunction) igraphmodule_Graph_mincut_value, METH_VARARGS | METH_KEYWORDS, @@ -16359,9 +16359,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "For undirected graphs and no source and target, the method uses the Stoer-Wagner\n" "algorithm. For a given source and target, the method uses the push-relabel\n" "algorithm; see the references below.\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{Cut} object. It is advised\n" - " to use that.\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{Cut} object. It is advised\n" + "to use that.\n\n" "@param source: the source vertex ID. If C{None}, target must also be\n" " {None} and the calculation will be done for the entire graph (i.e. all\n" " possible vertex pairs).\n" @@ -16386,6 +16386,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "st_mincut(source, target, capacity=None)\n--\n\n" "Calculates the minimum cut between the source and target vertices in a\n" "graph.\n\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a list of L{Cut} objects. It is\n" + "advised to use that.\n\n" "@param source: the source vertex ID\n" "@param target: the target vertex ID\n" "@param capacity: the capacity of the edges. It must be a list or a valid\n" @@ -16394,9 +16397,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the value of the minimum cut, the IDs of vertices in the\n" " first and second partition, and the IDs of edges in the cut,\n" " packed in a 4-tuple\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a list of L{Cut} objects. It is\n" - " advised to use that.\n" }, {"gomory_hu_tree", (PyCFunction) igraphmodule_Graph_gomory_hu_tree, @@ -16460,9 +16460,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { METH_NOARGS, "cohesive_blocks()\n--\n\n" "Calculates the cohesive block structure of the graph.\n\n" - "@attention: this function has a more convenient interface in class\n" - " L{Graph} which wraps the result in a L{CohesiveBlocks} object.\n" - " It is advised to use that.\n" + "Attention: this function has a more convenient interface in class\n" + "L{Graph}, which wraps the result in a L{CohesiveBlocks} object.\n" + "It is advised to use that.\n" }, /********************************/ @@ -16581,9 +16581,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "is the total weight of edges incident on vertex M{i}, M{kj} is the\n" "total weight of edges incident on vertex M{j} and M{m} is the total\n" "edge weight in the graph.\n\n" - "@attention: method overridden in L{Graph} to allow L{VertexClustering}\n" - " objects as a parameter. This method is not strictly necessary, since\n" - " the L{VertexClustering} class provides a variable called C{modularity}.\n" + "Attention: method overridden in L{Graph} to allow L{VertexClustering}\n" + "objects as a parameter. This method is not strictly necessary, since\n" + "the L{VertexClustering} class provides a variable called C{modularity}.\n\n" "@param membership: the membership vector, e.g. the vertex type index for\n" " each vertex.\n" "@param weights: optional edge weights or C{None} if all edges are weighed\n" @@ -16625,8 +16625,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "community, and communities are merged one by one. In every step, the two\n" "communities being merged are the ones which result in the maximal increase\n" "in modularity.\n\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param weights: name of an edge attribute or a list containing\n" " edge weights\n" "@return: a tuple with the following elements:\n" @@ -16701,8 +16701,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "A proper implementation of Newman's eigenvector community structure\n" "detection. Each split is done by maximizing the modularity regarding\n" "the original network. See the reference for details.\n\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param n: the desired number of communities. If negative, the algorithm\n" " tries to do as many splits as possible. Note that the algorithm\n" " won't split a community further if the signs of the leading eigenvector\n" @@ -16732,8 +16732,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "keeping the total weight of the incident edges) and the process continues\n" "on the next level. The algorithm stops when it is not possible to increase\n" "the modularity any more after shrinking the communities to vertices.\n\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param weights: name of an edge attribute or a list containing\n" " edge weights\n" "@param return_levels: if C{True}, returns the multilevel result. If\n" @@ -16766,8 +16766,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "is typically high. So we gradually remove the edge with the highest\n" "betweenness from the network and recalculate edge betweenness after every\n" "removal, as long as all edges are removed.\n\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param directed: whether to take into account the directedness of the edges\n" " when we calculate the betweenness values.\n" "@param weights: name of an edge attribute or a list containing\n" @@ -16871,8 +16871,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "method of Latapy & Pons.\n\n" "The basic idea of the algorithm is that short random walks tend to stay\n" "in the same community. The method provides a dendrogram.\n\n" - "@attention: this function is wrapped in a more convenient syntax in the\n" - " derived class L{Graph}. It is advised to use that instead of this version.\n\n" + "Attention: this function is wrapped in a more convenient syntax in the\n" + "derived class L{Graph}. It is advised to use that instead of this version.\n\n" "@param weights: name of an edge attribute or a list containing\n" " edge weights\n" "@return: a tuple with the list of merges and the modularity scores corresponding\n" diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 06455e323..c9133546d 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -808,13 +808,13 @@ static PyMethodDef igraphmodule_methods[] = }, {"_enter_safelocale", (PyCFunction)igraphmodule__enter_safelocale, METH_NOARGS, - "_enter_safelocale() -> object\n--\n\n" + "_enter_safelocale()\n--\n\n" "Helper function for the L{safe_locale()} context manager. Do not use\n" "directly in your own code." }, {"_exit_safelocale", (PyCFunction)igraphmodule__exit_safelocale, METH_O, - "_exit_safelocale(locale: object) -> None\n--\n\n" + "_exit_safelocale(locale)\n--\n\n" "Helper function for the L{safe_locale()} context manager. Do not use\n" "directly in your own code." }, diff --git a/src/igraph/basic.py b/src/igraph/basic.py index 416a9949a..0f35f89bf 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -124,15 +124,15 @@ def _delete_edges(graph, *args, **kwds): arguments. Edges in the derived edge sequence will be removed. Otherwise the first positional argument is considered as follows: + Deprecation notice: C{delete_edges(None)} has been replaced by + C{delete_edges()} - with no arguments - since igraph 0.8.3. + - C{None} - deletes all edges (deprecated since 0.8.3) - a single integer - deletes the edge with the given ID - a list of integers - deletes the edges denoted by the given IDs - a list of 2-tuples - deletes the edges denoted by the given source-target vertex pairs. When multiple edges are present between a given source-target vertex pair, only one is removed. - - @deprecated: C{delete_edges(None)} has been replaced by - C{delete_edges()} - with no arguments - since igraph 0.8.3. """ if len(args) == 0 and len(kwds) == 0: return GraphBase.delete_edges(graph) diff --git a/src/igraph/drawing/matplotlib/dendrogram.py b/src/igraph/drawing/matplotlib/dendrogram.py index 4f4a22e8d..9e87b835b 100644 --- a/src/igraph/drawing/matplotlib/dendrogram.py +++ b/src/igraph/drawing/matplotlib/dendrogram.py @@ -63,8 +63,8 @@ def draw(self, dendro, orientation="lr", **kwds): Other keyword arguments are passed to mpl.patches.Polygon. @param dendro: the igraph.Dendrogram to plot. - @orientation: the direction of the plot. Accepted values are "lr" (root - on the right), "rl" (root on the left), "tb" (root at the bottom), + @param orientation: the direction of the plot. Accepted values are "lr" + (root on the right), "rl" (root on the left), "tb" (root at the bottom), and "bt" (root at the top). A few aliases are available (see L{utils.str_to_orientation}). """ diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index bc22c9559..0646263de 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -258,7 +258,7 @@ def _construct_graph_from_list_dict( @param edges: the dict of sequences describing the edges @param directed: whether to create a directed graph - @vertex_name_attr: vertex attribute that will store the names + @param vertex_name_attr: vertex attribute that will store the names @returns: a Graph object @@ -325,7 +325,7 @@ def _construct_graph_from_dict_dict( @param edges: the dict of dict of dicts specifying the edges and their attributes @param directed: whether to create a directed graph - @vertex_name_attr: vertex attribute that will store the names + @param vertex_name_attr: vertex attribute that will store the names @returns: a Graph object """ @@ -535,7 +535,7 @@ def _export_graph_to_dict_list( @param skip_none: whether to skip, for each edge, attributes that have a value of None. This is useful if only some edges are expected to possess an attribute. - @vertex_name_attr: only used with use_vids=False to choose what + @param vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -607,7 +607,7 @@ def _export_graph_to_tuple_list( elements of each tuple. None (default) is equivalent to an empty list. A string is acceptable to signify a single attribute and will be wrapped in a list internally. - @vertex_name_attr: only used with use_vids=False to choose what + @param vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -669,7 +669,7 @@ def _export_graph_to_list_dict( to be used as values of the dictionary. The default (list) makes a dict of lists, with each list representing the neighbors of the vertex specified in the respective dictionary key. - @vertex_name_attr: only used with use_vids=False to choose what + @param vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. @@ -726,7 +726,7 @@ def _export_graph_to_dict_dict( @param skip_none: whether to skip, for each edge, attributes that have a value of None. This is useful if only some edges are expected to possess an attribute. - @vertex_name_attr: only used with use_vids=False to choose what + @param vertex_name_attr: only used with use_vids=False to choose what vertex attribute to use to name your vertices in the output data structure. From a058f957005cfa61ac7ed0b04683383898234cf3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Oct 2022 00:24:45 +1100 Subject: [PATCH 1097/1892] Fix #587 via better docs and logic and add test (#589) --- src/igraph/drawing/__init__.py | 38 ++++++++++++++++++++------ tests/drawing/matplotlib/test_graph.py | 11 +++++++- tests/utils.py | 12 ++++++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 7764bacde..eab1907eb 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -138,17 +138,24 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): backend, and you can use interactive backends and matplotlib functions to save to file as well. - - C{string} -- a file with the given name will be created and an - appropriate Cairo surface will be attached to it. The supported image - formats are: PNG, PDF, SVG and PostScript. + - C{string} -- a file with the given name will be created and the plot + will be stored there. If you are using the Cairo backend, an + appropriate Cairo surface will be attached to the file. If you are + using the matplotlib backend, the Figure will be saved to that file + using Figure.savefig with default parameters. The supported image + formats for Cairo are: PNG, PDF, SVG and PostScript; matplotlib might + support additional formats. - C{cairo.Surface} -- the given Cairo surface will be used. This can refer to a PNG image, an arbitrary window, an SVG file, anything that Cairo can handle. - - C{None} -- no plotting will be performed; igraph simply returns a - CairoPlot_ object that you can use to manipulate the plot and save it - to a file later. + - C{None} -- If you are using the Cairo backend, no plotting will be + performed; igraph simply returns a CairoPlot_ object that you can use + to manipulate the plot and save it to a file later. If you are using + the matplotlib backend, a Figure objet and an Axes are created and + the Axes is returned so you can manipulate it further. Similarly, if + you are using the plotly backend, a Figure object is returned. @param bbox: the bounding box of the plot. It must be a tuple with either two or four integers, or a L{BoundingBox} object. If this is a tuple @@ -185,8 +192,9 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): argument has an effect only if igraph is run inside IPython and C{target} is C{None}. - @return: an appropriate L{CairoPlot} object for the Cairo backend or the - Matplotlib C{Axes} object for the Matplotlib backend + @return: an appropriate L{CairoPlot} object for the Cairo backend, the + Matplotlib C{Axes} object for the Matplotlib backend, and the C{Figure} + object for the plotly backend. @see: Graph.__plot__ """ @@ -227,11 +235,16 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): if palette is not None and not isinstance(palette, Palette): palette = palettes[palette] + if isinstance(target, (str, Path)): + save_path = str(target) + target = None + else: + save_path = None + if target is None: if backend == "matplotlib": # Create a new axes if needed _, target = plt.subplots() - elif backend == "plotly": # Create a new figure if needed target = plotly.graph_objects.Figure() @@ -249,6 +262,13 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): *args, **kwds, ) + + if save_path is not None: + if backend == "matplotlib": + target.figure.savefig(save_path) + elif backend == "plotly": + target.write_image(save_path) + return target # Cairo backend diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index 1bfda8e1f..0cec58830 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -2,7 +2,9 @@ import unittest -from igraph import Graph, InternalError, plot, VertexClustering +from igraph import Graph, InternalError, plot, VertexClustering, config + +from ...utils import overridden_configuration # FIXME: find a better way to do this that works for both direct call and module # import e.g. tox @@ -80,6 +82,13 @@ def test_mark_groups_squares(self): dot.set_facecolor("blue") dot.radius *= 0.5 + @image_comparison(baseline_images=["graph_basic"], remove_text=True) + def test_gh_587(self): + plt.close("all") + g = Graph.Ring(5) + with overridden_configuration('plotting.backend', 'matplotlib'): + plot(g, target="graph_basic.png", layout=self.layout_small_ring) + class ClusteringTestRunner(unittest.TestCase): def setUp(self): diff --git a/tests/utils.py b/tests/utils.py index c4158416b..0d0a8067e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -10,6 +10,18 @@ __all__ = ("temporary_file", ) +@contextmanager +def overridden_configuration(key, value): + from igraph import config + + old_value = config[key] + config[key] = value + try: + yield + finally: + config[key] = old_value + + @contextmanager def temporary_file(content=None, mode=None, binary=False): tmpf, tmpfname = tempfile.mkstemp() From 05b4d228e751542295fdc9f80f07360b6c0ae60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Fri, 7 Oct 2022 20:50:07 +0200 Subject: [PATCH 1098/1892] docs: universal way to refer to igraph config file location on Windows (#590) * docs: universal way to refer to igraph config file location on Windows * docs: universal way to refer to user directory on Windows systems --- doc/source/tutorials/configuration/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst index 408bf55a6..4a9a172ce 100644 --- a/doc/source/tutorials/configuration/configuration.rst +++ b/doc/source/tutorials/configuration/configuration.rst @@ -8,7 +8,7 @@ Configuration Instance This example shows how to use |igraph|'s `configuration instance `_ to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. -First we define the default plotting backend, layout, and color palette, and save them. By default, ``ig.config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``C:\Documents and Settings\username\.igraphrc`` for Windows systems. +First we define the default plotting backend, layout, and color palette, and save them. By default, ``ig.config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``%USERPROFILE%\.igraphrc`` for Windows systems. .. code-block:: python From 82002d83159fb2c63abf01dbcba27c0552c8afb6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 8 Oct 2022 00:55:17 +0200 Subject: [PATCH 1099/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 53f79ce3f..63d1a6f99 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 53f79ce3fd3cca903eb6d4402f26cd9357576f9a +Subproject commit 63d1a6f9951394c7121c4c0000c6f725df14fa4b From 0021e563c9b6d072583a613bb80d4fc57907bdb8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 8 Oct 2022 01:42:49 +0200 Subject: [PATCH 1100/1892] refactor: moved conversion of output='vpath' or output='epath' to a separate function --- src/_igraph/convert.c | 22 ++++++++++++++++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 9 +-------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 90f76275a..a68af33f7 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3647,6 +3647,28 @@ int igraphmodule_PyObject_to_attribute_values(PyObject *o, return 0; } +int igraphmodule_PyObject_to_vpath_or_epath(PyObject *object, igraph_bool_t *use_edges) { + if (object == 0 || object == Py_None) { + *use_edges = 0; + return 0; + } + + if (!PyUnicode_Check(object)) { + PyErr_SetString(PyExc_ValueError, "output argument must be \"vpath\" or \"epath\""); + return 1; + } + + if (PyUnicode_IsEqualToASCIIString(object, "vpath")) { + *use_edges = 0; + return 0; + } else if (PyUnicode_IsEqualToASCIIString(object, "epath")) { + *use_edges = 1; + return 0; + } else { + PyErr_SetString(PyExc_ValueError, "output argument must be \"vpath\" or \"epath\""); + return 1; + } +} int igraphmodule_PyObject_to_drl_options_t(PyObject *obj, igraph_layout_drl_options_t *options) { diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 7f240e0e7..39cc02eb5 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -138,6 +138,7 @@ int igraphmodule_PyObject_to_eigen_algorithm_t(PyObject *object, igraph_eigen_algorithm_t *a); int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, igraph_eigen_which_t *w); +int igraphmodule_PyObject_to_vpath_or_epath(PyObject *object, igraph_bool_t *use_edges); /* Conversion from attributes to igraph types */ diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f3881e802..d55122b5a 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5005,15 +5005,8 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) return NULL; - if (output_o == 0 || output_o == Py_None || - PyUnicode_IsEqualToASCIIString(output_o, "vpath")) { - use_edges = 0; - } else if (PyUnicode_IsEqualToASCIIString(output_o, "epath")) { - use_edges = 1; - } else { - PyErr_SetString(PyExc_ValueError, "output argument must be \"vpath\" or \"epath\""); + if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) return NULL; - } if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) return NULL; From 26d74e649a420cb9155733070e396ff3d36c3efd Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 9 Oct 2022 12:57:57 +0200 Subject: [PATCH 1101/1892] ci: trying to increase coverage of test matrix by preferring binary wheels over source --- .github/workflows/build.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2873fb875..6613a87a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: CIBW_ENVIRONMENT_PASS_LINUX: PYTEST_TIMEOUT - CIBW_TEST_COMMAND: "cd {project} && python -m pytest -v tests" - CIBW_TEST_EXTRAS: "test" + CIBW_TEST_COMMAND: "cd {project} && pip install -E test --prefer-binary . && python -m pytest -v tests" CIBW_SKIP: "cp36-*" PYTEST_TIMEOUT: 60 MACOSX_DEPLOYMENT_TARGET: "10.9" @@ -34,17 +33,13 @@ jobs: env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" - # Skip tests for Python 3.10 because SciPy does not have a 32-bit - # wheel for Linux yet, and for Python 3.11 because SciPy does not - # have wheels for 3.11 at all - CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-*" - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.10.2 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" - CIBW_TEST_EXTRAS: "test-musl" + CIBW_TEST_COMMAND: "cd {project} && pip install -E test-musl --prefer-binary . && python -m pytest -v tests" - uses: actions/upload-artifact@v3 with: @@ -77,7 +72,7 @@ jobs: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" - CIBW_TEST_EXTRAS: "test-musl" + CIBW_TEST_COMMAND: "cd {project} && pip install -E test-musl --prefer-binary . && python -m pytest -v tests" - uses: actions/upload-artifact@v3 with: @@ -145,8 +140,6 @@ jobs: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_ENVIRONMENT: "LDFLAGS=-L$HOME/local/lib" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} -DCMAKE_PREFIX_PATH=$HOME/local - # Skip tests for Python 3.11 because SciPy does not have wheels for 3.11 at all - CIBW_TEST_SKIP: "cp311-*" - uses: actions/upload-artifact@v3 with: @@ -204,11 +197,7 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" - # Skip tests for Python 3.10 because SciPy does not have a 32-bit - # wheel for Python 3.10 yet, and for Python 3.11 because SciPy does - # not have wheels for Python 3.11 at all yet - CIBW_TEST_SKIP: "cp310-win32 cp311-*" - CIBW_TEST_COMMAND: "cd /d {project} && python -m pytest tests" + CIBW_TEST_COMMAND: "cd /d {project} && pip install -E test --prefer-binary . && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True From 3d12dc3a95bc3295016ec099c3d8e5c43f9e132b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 9 Oct 2022 13:13:24 +0200 Subject: [PATCH 1102/1892] ci: fix pip install syntax when installing with extras --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6613a87a8..f28304cde 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,7 @@ name: Build and test, upload to PyPI on release on: [push, pull_request] env: CIBW_ENVIRONMENT_PASS_LINUX: PYTEST_TIMEOUT - CIBW_TEST_COMMAND: "cd {project} && pip install -E test --prefer-binary . && python -m pytest -v tests" + CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test]' && python -m pytest -v tests" CIBW_SKIP: "cp36-*" PYTEST_TIMEOUT: 60 MACOSX_DEPLOYMENT_TARGET: "10.9" @@ -39,7 +39,7 @@ jobs: env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" - CIBW_TEST_COMMAND: "cd {project} && pip install -E test-musl --prefer-binary . && python -m pytest -v tests" + CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test-musl]' && python -m pytest -v tests" - uses: actions/upload-artifact@v3 with: @@ -72,7 +72,7 @@ jobs: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" - CIBW_TEST_COMMAND: "cd {project} && pip install -E test-musl --prefer-binary . && python -m pytest -v tests" + CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test-musl]' && python -m pytest -v tests" - uses: actions/upload-artifact@v3 with: @@ -197,7 +197,7 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" - CIBW_TEST_COMMAND: "cd /d {project} && pip install -E test --prefer-binary . && python -m pytest tests" + CIBW_TEST_COMMAND: "cd /d {project} && pip install --prefer-binary '.[test]' && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True From a2a3d7fcfe101b57fa1a71f6689b4d4e6b34b04d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 9 Oct 2022 22:22:39 +0200 Subject: [PATCH 1103/1892] ci: bump Pillow version --- setup.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setup.py b/setup.py index a92bf5897..9232d6f06 100644 --- a/setup.py +++ b/setup.py @@ -908,11 +908,7 @@ def get_tag(self): # Matplotlib 3.6.0 does not support Python 3.7 any more "matplotlib>=3.5.0,<3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", "plotly>=5.3.0", - # matplotlib requires Pillow; however, Pillow >= 8.4 does not - # provide manylinux2010 wheels any more, but we need those in - # cibuildwheel for Linux so we need to restrict Pillow's version - # range - "Pillow>=8,<8.4; platform_python_implementation != 'PyPy'", + "Pillow>=9; platform_python_implementation != 'PyPy'", ], # Dependencies needed for testing on musllinux; only those that are either From 222ebde9eecb92e5cf03f1fa8dc4b338cd4ec2c4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 9 Oct 2022 23:54:00 +0200 Subject: [PATCH 1104/1892] ci: more CI tweaks --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f28304cde..2b47b03c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,6 +33,9 @@ jobs: env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" + # Skip tests for Python 3.10 and 3.11 because SciPy does not have + # 32-bit wheels for Linux + CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.10.2 @@ -197,7 +200,7 @@ jobs: env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" - CIBW_TEST_COMMAND: "cd /d {project} && pip install --prefer-binary '.[test]' && python -m pytest tests" + CIBW_TEST_COMMAND: "cd /d {project} && pip install --prefer-binary \".[test]\" && python -m pytest tests" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True From 44c84a2fdb617a194c62dbdcd7e06fb4cc652162 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Oct 2022 00:57:57 +0200 Subject: [PATCH 1105/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 63d1a6f99..1f7f21ee9 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 63d1a6f9951394c7121c4c0000c6f725df14fa4b +Subproject commit 1f7f21ee9066f51a4d72a3b6f9c1fa50a19f9877 From 9822a392e26d06fc185c59a2d62048ad680e44d5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Oct 2022 06:51:41 +0200 Subject: [PATCH 1106/1892] ci: skip tests for Win32 above Python 3.10 because SciPy does not publish 32-bit wheels any more --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b47b03c3..696222403 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -201,6 +201,9 @@ jobs: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" CIBW_TEST_COMMAND: "cd /d {project} && pip install --prefer-binary \".[test]\" && python -m pytest tests" + # Skip tests for Python 3.10 and 3.11 because SciPy does not have + # 32-bit wheels for Windows + CIBW_TEST_SKIP: "cp310-win32 cp311-win32" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True From 1f76f4f5e822b43a13858f618b1816136e6ae2d2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Oct 2022 23:56:49 +0200 Subject: [PATCH 1107/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 1f7f21ee9..17e828a49 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 1f7f21ee9066f51a4d72a3b6f9c1fa50a19f9877 +Subproject commit 17e828a4970e4301ed98315550566f9c3fb53960 From 9eb3f21c0df2bf2a7559b0ac9e6531800d9fb4f9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Oct 2022 00:26:52 +0200 Subject: [PATCH 1108/1892] ci: try to install Matplotlib 3.6 for testing purposes because we need it for Python 3.11 --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9232d6f06..c39a63eac 100644 --- a/setup.py +++ b/setup.py @@ -905,8 +905,9 @@ def get_tag(self): "numpy>=1.19.0; platform_python_implementation != 'PyPy'", "pandas>=1.1.0; platform_python_implementation != 'PyPy'", "scipy>=1.5.0; platform_python_implementation != 'PyPy'", - # Matplotlib 3.6.0 does not support Python 3.7 any more - "matplotlib>=3.5.0,<3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", + # Matplotlib 3.6.0 does not support Python 3.7 any more, but we need + # it because Python 3.11 support came in Matplotlib 3.6.0 first + "matplotlib>=3.6.0; platform_python_implementation != 'PyPy' and python_version >= '3.8'", "plotly>=5.3.0", "Pillow>=9; platform_python_implementation != 'PyPy'", ], From cf8370be903df02d3aa08c1af560139265b3b401 Mon Sep 17 00:00:00 2001 From: sombreslames Date: Tue, 11 Oct 2022 08:34:08 +0200 Subject: [PATCH 1109/1892] Integrating igraph_get_k_shortest_paths with python-igraph (#577) * Adding C wrapper and test for get_k_shortest_paths * Used of k_O? PyLong_AsInt used for python object to get integer K * igraphmodule_PyObject_to_integer_t instead of PyLong_AsInt * igraph_integer_t cast for from,to and k; Update doc and naming of function parameter * Erasing one test with multiple target vertex. Correcting call to get_k_shortest_paths * igraphmodule_PyObject_to_vid to handle vertex or vertex id No more use of igraph_vs_destroy since to is not a vector * Coding style * Removing last igraph_vs_destroy * Updat the PyArg_ParseTupleAndKeywords for igraphmodule_Graph_get_k_shortest_paths * Reanming arg from "fromm" to "v" for the source vertex. * test: get_k_shortest_paths() result checks in unit tests should not be sensitive to the order * Adding output parameter to get_k_shortest_path Changing order of arg of get_k_shortest_path(v,to,k,weights,mode,output) * Correcting order for PyArg_ParseTupleAndKeywords of igraphmodule_Graph_get_k_shortest_paths * style: nitpicking * fix: make sure that unit tests pass with the new argument parsing Co-authored-by: lferrari Co-authored-by: Tamas Nepusz --- src/_igraph/graphobject.c | 93 +++++++++++++++++++++++++++++++++++++++ tests/test_structural.py | 45 +++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index d55122b5a..e98257173 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5123,6 +5123,73 @@ PyObject *igraphmodule_Graph_get_all_shortest_paths(igraphmodule_GraphObject * igraph_vector_int_list_destroy(&res); return list ? list : NULL; } +/** \ingroup python_interface_graph + * \brief Calculates the k-shortest paths from/to a given node in the graph + * \return a list containing the k-shortest paths from/to the given node + * \sa TODO I don't know what to write here : igraph_get_shortest_paths + */ +PyObject *igraphmodule_Graph_get_k_shortest_paths( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "v", "to", "k", "weights", "mode", "output", NULL }; + igraph_vector_int_list_t res; + igraph_vector_t *weights = 0; + igraph_neimode_t mode = IGRAPH_OUT; + igraph_integer_t from; + igraph_integer_t to; + igraph_integer_t k = 1; + PyObject *list, *from_o, *to_o; + PyObject *output_o = Py_None, *mode_o = Py_None, *weights_o = Py_None, *k_o = NULL; + igraph_bool_t use_edges = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOO", kwlist, &from_o, + &to_o, &k_o, &weights_o, &mode_o, &output_o)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + return NULL; + + if (k_o != NULL && igraphmodule_PyObject_to_integer_t(k_o, &k)) + return NULL; + + if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_vid(to_o, &to, &self->g)) + return NULL; + + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) + return NULL; + + if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) + return NULL; + + if (igraph_vector_int_list_init(&res, 0)) { + igraphmodule_handle_igraph_error(); + if (weights) { igraph_vector_destroy(weights); free(weights); } + return NULL; + } + + if (igraph_get_k_shortest_paths(&self->g, + weights, + /* vertices, edges */ + use_edges ? 0 : &res, + use_edges ? &res : 0, + k, from, to, mode) + ) { + igraphmodule_handle_igraph_error(); + igraph_vector_int_list_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } + return NULL; + } + + if (weights) { igraph_vector_destroy(weights); free(weights); } + + list = igraphmodule_vector_int_list_t_to_PyList(&res); + igraph_vector_int_list_destroy(&res); + + return list ? list : NULL; +} /** \ingroup python_interface_graph * \brief Calculates all the simple paths from a single source to other nodes @@ -14139,6 +14206,32 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " reachable node in the graph in a list. Note that in case of mode=C{\"in\"},\n" " the vertices in a path are returned in reversed order!"}, + /* interface to igraph_get_k_shortest_paths */ + {"get_k_shortest_paths", + (PyCFunction) igraphmodule_Graph_get_k_shortest_paths, + METH_VARARGS | METH_KEYWORDS, + "get_k_shortest_paths(v, to, k=1, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "Calculates the k shortest paths from/to a given node in a graph.\n\n" + "@param v: the ID or name of the vertex from which the paths are calculated.\n" + "@param to: the ID or name of the vertex to which the paths are calculated.\n" + "@param k: the desired number of shortest path\n" + "@param weights: edge weights in a list or the name of an edge attribute\n" + " holding edge weights. If C{None}, all edges are assumed to have\n" + " equal weight.\n" + "@param mode: the directionality of the paths. C{\"in\"} means to\n" + " calculate incoming paths, C{\"out\"} means to calculate outgoing\n" + " paths, C{\"all\"} means to calculate both ones.\n" + "@param output: determines what should be returned. If this is\n" + " C{\"vpath\"}, a list of vertex IDs will be returned, one path\n" + " for each target vertex. For unconnected graphs, some of the list\n" + " elements may be empty. Note that in case of mode=C{\"in\"}, the vertices\n" + " in a path are returned in reversed order. If C{output=\"epath\"},\n" + " edge IDs are returned instead of vertex IDs.\n" + "@return: the k shortest paths from the given source node to the given target node\n" + " in a list of vertex or edge IDs (depending on the value of the C{output}\n" + " argument). Note that in case of mode=C{\"in\"},\n" + " the vertices in a path are returned in reversed order!"}, + /* interface to igraph_get_all_simple_paths */ {"_get_all_simple_paths", (PyCFunction) igraphmodule_Graph_get_all_simple_paths, diff --git a/tests/test_structural.py b/tests/test_structural.py index 610319139..b9b1d0b54 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -841,6 +841,51 @@ def testGetAllShortestPaths(self): self.assertEqual(4, sum(1 for path in sps if path[-1] == 12)) self.assertEqual(12, sum(1 for path in sps if path[-1] == 15)) + def testGetKShortestPaths(self): + g = Graph(4, [(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)], directed=True) + + sps = sorted(g.get_k_shortest_paths(0, 0)) + expected = [[0]] + self.assertEqual(expected, sps) + + sps = sorted(g.get_k_shortest_paths(0, 5, 2)) + expected = [[0, 1, 2, 4, 5], [0, 1, 3, 4, 5]] + self.assertEqual(expected, sps) + + sps = sorted(g.get_k_shortest_paths(1, 4, 2)) + expected = [[1, 2, 4], [1, 3, 4]] + self.assertEqual(expected, sps) + + g = Graph.Lattice([5, 5], circular=False) + + sps = sorted(g.get_k_shortest_paths(0, 12, 6)) + expected = [ + [0, 1, 2, 7, 12], + [0, 1, 6, 7, 12], + [0, 1, 6, 11, 12], + [0, 5, 6, 7, 12], + [0, 5, 6, 11, 12], + [0, 5, 10, 11, 12], + ] + self.assertEqual(expected, sps) + + g = Graph.Lattice([100, 100], circular=False) + sps = sorted(g.get_k_shortest_paths(0, 202, 6)) + expected = [ + [0, 1, 2, 102, 202], + [0, 1, 101, 102, 202], + [0, 1, 101, 201, 202], + [0, 100, 101, 102, 202], + [0, 100, 101, 201, 202], + [0, 100, 200, 201, 202], + ] + self.assertEqual(expected, sps) + + g = Graph([(0, 1), (1, 2), (0, 2)]) + g.es["weight"] = [0.5, 0.5, 1] + sps = sorted(g.get_k_shortest_paths(0, 2, 2, weights="weight")) + self.assertEqual(sorted([[0, 2], [0, 1, 2]]), sorted(sps)) + def testGetAllSimplePaths(self): g = Graph.Ring(20) sps = sorted(g.get_all_simple_paths(0, 10)) From f52191439392d04707c3020b6163ccc7f035b35c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Oct 2022 10:45:17 +0200 Subject: [PATCH 1110/1892] doc: update set_random_number_generator() docs --- src/_igraph/igraphmodule.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index c9133546d..35cda299d 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -772,12 +772,15 @@ static PyMethodDef igraphmodule_methods[] = " with at least three attributes: C{random}, C{randint} and C{gauss}.\n" " Each of them must be callable and their signature and behaviour\n" " must be identical to C{random.random}, C{random.randint} and\n" - " C{random.gauss}. By default, igraph uses the C{random} module for\n" - " random number generation, but you can supply your alternative\n" - " implementation here. If the given generator is C{None}, igraph\n" - " reverts to the default Mersenne twister generator implemented in the\n" - " C layer, which might be slightly faster than calling back to Python\n" - " for random numbers, but you cannot set its seed or save its state.\n" + " C{random.gauss}. Optionally, the object can provide a function named\n" + " C{getrandbits} with a signature identical to C{randpm.getrandbits}\n" + " that provides a given number of random bits on demand. By default,\n" + " igraph uses the C{random} module for random number generation, but\n" + " you can supply your alternative implementation here. If the given\n" + " generator is C{None}, igraph reverts to the default PCG32 generator\n" + " implemented in the C layer, which might be slightly faster than\n" + " calling back to Python for random numbers, but you cannot set its\n" + " seed or save its state.\n" }, {"set_status_handler", igraphmodule_set_status_handler, METH_O, "set_status_handler(handler)\n--\n\n" From fe3ef23b6b08946096bc627f6caea0596904a54c Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 11 Oct 2022 20:23:08 +1100 Subject: [PATCH 1111/1892] Readthedocs (#591) * Fix a bunch of links from tutorials * RTD config file and requirements empty file * Add some deps in the requirements * Typo in RTD config * Grab doc version slug from RTD * Add pydoctor to requirements * Some OS devs * Pre-build command * Playing with pre-build hook * More playing with pre-build hook, not pre-create-env * Try a different install method * Tell RTD to build the C core explicitely * Git submodule in RTD conf * Update OS to Ubuntu 22.04, hoping it has cmake 3.18 * Switch in conf.py for RTD and pydoctor * Install using wheel+pip, no egg file please * Indent typo in RTD conf * Try setting output folder for pydoctor on RTD * Simplify catching html output folder * Try patching pydoctor re race condition with RTD extension * Make RTD prebuild script * RTD uses python 3.9 * conf.py and other streamlining, try to use native RTD theme * Change pydoctor output UI * Tidy up conf.py * Try out RTD theme for pydoctor * Theme fix and umap double space * Corrected absolute links to github pages and API objects * Improve home page * Add link checker * Better wording on homepage * Fix broken links and HTTPS redirects * Fix a few more redirects * Fix https errors in linkcheck * Require recent requests package for linkcheck * Ignore linkcheck output folder * Skip linkcheck for now * Introspection is cool Co-authored-by: Tamas Nepusz --- .gitignore | 1 + .readthedocs.yaml | 49 +++++ doc/source/analysis.rst | 6 +- doc/source/conf.py | 194 ++++++++++-------- doc/source/generation.rst | 6 +- doc/source/index.rst | 22 +- doc/source/install.rst | 10 +- doc/source/requirements.txt | 10 + doc/source/sphinxext/postprocess_api.py | 27 ++- doc/source/tutorial.rst | 18 +- .../articulation_points.rst | 5 +- .../tutorials/betweenness/betweenness.rst | 13 +- .../bipartite_matching/bipartite_matching.rst | 5 +- .../bipartite_matching_maxflow.rst | 11 +- doc/source/tutorials/bridges/bridges.rst | 5 +- .../tutorials/cluster_graph/cluster_graph.rst | 16 +- .../tutorials/complement/complement.rst | 5 +- .../tutorials/configuration/configuration.rst | 4 +- .../connected_components.rst | 7 +- .../tutorials/erdos_renyi/erdos_renyi.rst | 6 +- .../tutorials/isomorphism/isomorphism.rst | 5 +- doc/source/tutorials/maxflow/maxflow.rst | 5 +- .../minimum_spanning_trees.rst | 7 +- .../ring_animation/ring_animation.rst | 5 +- .../shortest_paths/shortest_paths.rst | 11 +- doc/source/tutorials/simplify/simplify.rst | 5 +- .../spanning_trees/spanning_trees.rst | 10 +- .../topological_sort/topological_sort.rst | 8 +- .../tutorials/visual_style/visual_style.rst | 2 +- .../visualize_cliques/visualize_cliques.rst | 6 +- doc/source/visualisation.rst | 6 +- scripts/mkdoc.sh | 27 ++- scripts/rtd_prebuild.sh | 13 ++ src/_igraph/graphobject.c | 20 +- 34 files changed, 298 insertions(+), 252 deletions(-) create mode 100644 .readthedocs.yaml create mode 100644 doc/source/requirements.txt create mode 100755 scripts/rtd_prebuild.sh diff --git a/.gitignore b/.gitignore index af835ecb6..f0a852ea0 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ vendor/install/ .DS_Store doc/source/gallery.rst +doc/linkcheck doc/api/ doc/dash/ doc/html/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..7af56aadb --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,49 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +submodules: + include: + - vendor/source/igraph + recursive: true + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + apt_packages: + - cmake + - flex + - bison + - libxml2-dev + - zlib1g-dev + + tools: + python: "3.9" + # You can also specify other tool versions: + # nodejs: "16" + # rust: "1.55" + # golang: "1.17" + + jobs: + pre_build: + - bash ./scripts/rtd_prebuild.sh + # One website complains about legacy SSL renegotiation (?), skip for now + #- python -m sphinx -b linkcheck doc/source/ _build/linkcheck + + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: doc/source/conf.py + +# If using Sphinx, optionally build your docs in additional formats such as PDF +# formats: +# - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: doc/source/requirements.txt + diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index d9e23869e..1be2277df 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -6,7 +6,7 @@ Graph analysis ============== -|igraph| enables analysis of graphs/networks from simple operations such as adding and removing nodes to complex theoretical constructs such as community detection. Read the `API documentation`_ for details on each function and class. +|igraph| enables analysis of graphs/networks from simple operations such as adding and removing nodes to complex theoretical constructs such as community detection. Read the :doc:`api/index` for details on each function and class. The context for the following examples will be to import |igraph| (commonly as `ig`), have the :class:`Graph` class and to have one or more graphs available:: @@ -51,7 +51,7 @@ You can index and slice vertices and edges like indexing and slicing a list:: >>> g.vs[0, 2, 4] >>> g.es[3] -.. note:: The `vs` and `es` attributes are special sequences with their own useful methods. See `API documentation`_ for a full list. +.. note:: The `vs` and `es` attributes are special sequences with their own useful methods. See the :doc:`api/index` for a full list. If you prefer a vanilla edge list, you can use :meth:`Graph.get_edge_list`. @@ -442,5 +442,3 @@ Flow and cuts are closely related, therefore you might find the following functi - :meth:`Graph.all_st_mincuts` - :meth:`Graph.edge_connectivity` or :meth:`Graph.edge_disjoint_paths` or :meth:`Graph.adhesion` - :meth:`Graph.vertex_connectivity` or :meth:`Graph.cohesion` - -.. _API documentation: https://igraph.org/python/api/latest/ diff --git a/doc/source/conf.py b/doc/source/conf.py index 28fb072c1..2e2356231 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -15,58 +15,52 @@ import sys import os -import os.path as op +import importlib +from pathlib import Path import sphinxbootstrap4theme +# Check if we are inside readthedocs, the conf is quite different there +is_inside_rtd = os.getenv("READTHEDOCS", "") == "True" +rtd_version = os.getenv("READTHEDOCS_VERSION", "") + + # Utility functions # NOTE: these could be improved, esp by importing igraph, but that -# currently generates a conflict with pydoctor +# currently generates a conflict with pydoctor. It is funny because pydoctor's +# docs indeed import itself... perhaps there's a decent way to solve this. def get_root_dir(): '''Get project root folder''' - root_folder = op.abspath('../..') - return root_folder + return str(Path('.').absolute().parent.parent) def get_igraphdir(): '''Get igraph folder''' - vmaj, vmin = sys.version_info[:2] - root_folder = get_root_dir() - ig_folder = op.join( - root_folder, - '.venv', - 'lib', - f'python{vmaj}.{vmin}', - 'site-packages', - 'igraph', - ) - return ig_folder + return Path(importlib.util.find_spec('igraph').origin).parent def get_igraph_version(): '''Get igraph version''' - version_file = op.join( - get_igraphdir(), - 'version.py', - ) + if is_inside_rtd: + return rtd_version + + version_file = get_igraphdir() / 'version.py' with open(version_file, 'rt') as f: version_info = (f.readline() .rstrip('\n') .split('=')[1] .strip()[1:-1] .split(', ')) - version = '.'.join(version_info) - + version = '.'.join(version_info) + return version -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.append(os.path.abspath('.')) - # -- General configuration ----------------------------------------------------- +_igraph_dir = str(get_igraphdir()) +_igraph_version = get_igraph_version() + # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' @@ -78,32 +72,14 @@ def get_igraph_version(): 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx', 'gallery_generator', - 'pydoctor.sphinx_ext.build_apidocs', - 'postprocess_api', #'sphinx_panels', + 'pydoctor.sphinx_ext.build_apidocs', ] -# Using --no-sidebar option to skip the sidebar whole together not to generate noise in the HTML. -# Because the pydoctor output is integrated in a smaller div with a custom CSS it's not optimal to include the sidebar. -pydoctor_args = [ - '--project-name="igraph"', - '--project-version=' + get_igraph_version(), - '--project-url=https://igraph.org/python', - '--introspect-c-modules', - '--no-sidebar', - '--docformat=epytext', - #'--intersphinx='+get_root_dir()+'/doc/tutorial/objects.inv', - '--html-output=' + op.join(get_root_dir(), 'doc', 'html', 'api'), - #'--html-viewsource-base=https://github.com/igraph/python-igraph/tree/default', - '--project-base-dir=' + get_igraphdir(), - get_igraphdir(), -] - -# API docs relative to the rest of the docs -# NOTE: there is a bug in pydoctor that requires this to be a subfolder -# of the main docs. Although we patch pydoctor to work anyway, links might -# be broken if that constraint is not satisfied -pydoctor_url_path = 'api/' +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) # The suffix of source filenames. source_suffix = '.rst' @@ -123,7 +99,7 @@ def get_igraph_version(): # built documents. # # The short X.Y version. -version = get_igraph_version() +version = _igraph_version # The full version, including alpha/beta/rc tags. release = version @@ -164,26 +140,50 @@ def get_igraph_version(): # -- Options for HTML output --------------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'sphinxbootstrap4theme' -#html_theme = 'alabaster' +# The theme to use for HTML and HTML Help pages. RTD overloads this with their +# standard theme if the variable 'html_theme' is not set +if not is_inside_rtd: + html_theme = 'sphinxbootstrap4theme' -# Add any paths that contain templates here, relative to this directory. -templates_path = [ - '_templates', -] + # Add any paths that contain templates here, relative to this directory. + templates_path = [ + '_templates', + ] -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "navbar_style": "full", - "navbar_color_class": "dark", -} + # Theme options are theme-specific and customize the look and feel of a theme + # further. For a list of options available for each theme, see the + # documentation. + html_theme_options = { + "navbar_style": "full", + "navbar_color_class": "dark", + } + + # Add any paths that contain custom themes here, relative to this directory. + html_theme_path = [sphinxbootstrap4theme.get_path()] + + # Add any paths that contain custom static files (such as style sheets) here, + # relative to this directory. They are copied after the builtin static files, + # so a file named "default.css" will overwrite the builtin "default.css". + html_static_path = ['_static'] + + # If false, no module index is generated. + html_domain_indices = False + + # If false, no index is generated. + html_use_index = False + + # If true, the index is split into individual pages for each letter. + #html_split_index = False + + # If true, links to the reST sources are added to the pages. + html_show_sourcelink = False -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [sphinxbootstrap4theme.get_path()] +else: + + # Inspired by pydoctor's RTD page itself + # https://github.com/twisted/pydoctor/blob/master/docs/source/conf.py + html_theme = "sphinx_rtd_theme" + html_static_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". @@ -201,11 +201,6 @@ def get_igraph_version(): # pixels large. #html_favicon = None -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' @@ -221,18 +216,6 @@ def get_igraph_version(): # template names. #html_additional_pages = {} -# If false, no module index is generated. -html_domain_indices = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True @@ -251,6 +234,49 @@ def get_igraph_version(): htmlhelp_basename = 'igraphdoc' +# -- Options for pydoctor ------------------------------------------------------ + +def get_pydoctor_html_outputdir(pydoctor_url_path): + '''Get HTML output dir for pydoctor''' + # NOTE: obviously this is a little tricky, but it does work for both + # the sphinx-build script and the python -m sphinx module calls. It works + # locally, on github pages, and on RTD. + return str(Path(sys.argv[-1]) / pydoctor_url_path.strip('/')) + + +# API docs relative to the rest of the docs, needed for pydoctor to play nicely +# with intersphinx (https://pypi.org/project/pydoctor/#pydoctor-21-2-0) +# NOTE: As of 2022 AD, pydoctor requires this to be a subfolder of the docs. +pydoctor_url_path = 'api/' + +pydoctor_args = [ + '--project-name="igraph"', + '--project-version=' + version, + '--project-url=https://igraph.readthedocs.io', + '--introspect-c-modules', + '--docformat=epytext', + #'--intersphinx='+get_root_dir()+'/doc/tutorial/objects.inv', + '--html-output=' + get_pydoctor_html_outputdir(pydoctor_url_path), + #'--html-viewsource-base=https://github.com/igraph/python-igraph/tree/default', + '--project-base-dir=' + _igraph_dir, + ] + +# Using --no-sidebar option to skip the sidebar because the pydoctor output is +# integrated in a smaller div with a custom CSS. +if not is_inside_rtd: + pydoctor_args.extend([ + '--no-sidebar', + ]) +else: + pydoctor_args.extend([ + '--theme=readthedocs', + ]) +pydoctor_args.append(_igraph_dir) + +# RTD needs no postprocessing for pydoctor, while Jekyll does +if not is_inside_rtd: + extensions.append('postprocess_api') + # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 34cb8d64e..674d971c3 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -7,7 +7,7 @@ Graph generation ================ -The first step of most |igraph| applications is to generate a graph. This section will explain a number of ways to do that. Read the `API documentation`_ for details on each function and class. +The first step of most |igraph| applications is to generate a graph. This section will explain a number of ways to do that. Read the :doc:`api/index` for details on each function and class. The :class:`Graph` class is the main object used to generate graphs:: @@ -55,7 +55,7 @@ a representation that uses Python builtin data structures: - :meth:`Graph.to_list_dict` - :meth:`Graph.to_dict_dict` -See the `API documentation`_ of each function for details and examples. +See the :doc:`api/index` of each function for details and examples. From matrices +++++++++++++ @@ -208,5 +208,3 @@ Finally, there are some ways of generating graphs that are not covered by the pr - graphs from LCF notation :meth:`Graph.LCF` - small graphs of any "isomorphism class" :meth:`Graph.Isoclass` - graphs with a specified degree sequence :meth:`Graph.Realize_Degree_Sequence` - -.. _API documentation: https://igraph.org/python/api/latest/ diff --git a/doc/source/index.rst b/doc/source/index.rst index 0b1226cb1..60b1d987c 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -25,9 +25,11 @@ python-igraph |release| ======================= -|igraph| is a fast open source tool to manipulate and analyze graphs or networks. It is primarily written in C. `python-igraph` is |igraph|'s interface for the Python programming language. +Python interface of `igraph`_, a fast and open source C library to manipulate and analyze graphs (aka networks). It can be used to: -`python-graph` includes functionality for graph plotting and conversion from/to `networkx`_. + - Create, manipulate, and analyze networks. + - Convert graphs from/to `networkx`_, `graph-tool`_ and many file formats. + - Plot networks using `Cairo`_, `matplotlib`_, and `plotly`_. Installation @@ -63,9 +65,9 @@ Documentation **Tutorials** - - :doc:`tutorials/quickstart/quickstart` - - :doc:`Gallery ` - - :doc:`tutorial` + - :doc:`Quick Start ` + - :doc:`Example Gallery ` + - :doc:`Extended tutorial ` .. container:: @@ -74,7 +76,7 @@ Documentation - :doc:`Generation ` - :doc:`Analysis ` - :doc:`Visualization ` - - :doc:`configuration` + - :doc:`Configuration ` .. container:: twocol @@ -82,7 +84,7 @@ Documentation **Reference** - - :doc:`../../api/latest/index` + - :doc:`api/index` - `Source code `_ .. container:: @@ -92,6 +94,7 @@ Documentation - :doc:`FAQs ` - `Forum `_ +Documentation for `python-igraph <= 0.10.1` is available on our `old website `_. .. toctree:: :maxdepth: 1 @@ -115,4 +118,9 @@ Indices and tables * :ref:`modindex` +.. _igraph: https://igraph.org .. _networkx: https://networkx.org/documentation/stable/ +.. _graph-tool: https://graph-tool.skewed.de/ +.. _Cairo: https://www.cairographics.org +.. _matplotlib: https://matplotlib.org +.. _plotly: https://plotly.com/python/ diff --git a/doc/source/install.rst b/doc/source/install.rst index f6caa73d8..899d930b7 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -10,7 +10,7 @@ Installing |igraph| Binary package (recommended) ============================ -It is recommended to install a binary package that includes both C core and Python interface. You can choose either of `PyPI `_ or `Conda `_. Linux users can also use their package manager. +It is recommended to install a binary package that includes both C core and Python interface. You can choose either of `PyPI `_ or `Conda `_. Linux users can also use their package manager. PyPI ---- @@ -22,7 +22,7 @@ To install the Python interface of |igraph| globally, use the following command $ pip install igraph If you prefer to install |igraph| in a user folder using a `virtual environment -`_, use the following commands instead:: +`_, use the following commands instead:: $ python -m venv my_environment $ source my_environment/bin/activate @@ -145,11 +145,11 @@ Q: I am trying to install |igraph| on Windows but am getting DLL import errors A: The most common reason for this error is that you do not have the Visual C++ Redistributable library installed on your machine. Python's own installer is supposed to install it, but in case it was not installed on your system, you can -`download it from Microsoft `_. +`download it from Microsoft `_. Q: I am trying to use |igraph| but get errors about something called Cairo ---------------------------------------------------------------------------------- -A: |igraph| by default uses a third-party called `Cairo `_ for plotting. +A: |igraph| by default uses a third-party called `Cairo `_ for plotting. If Cairo is not installed on your computer, you might get an import error. This error is most commonly encountered on Windows machines. @@ -165,7 +165,7 @@ you need to install Cairo headers using your package manager (Linux) or `homebre The Cairo project does not provide pre-compiled binaries for Windows, but Christoph Gohlke maintains a site containing unofficial Windows binaries for several Python extension packages, including Cairo. Therefore, the easiest way to install Cairo on Windows along with its Python bindings -is simply to download it from `Christoph's site `_. +is simply to download it from `Christoph's site `_. Make sure you use an installer that is suitable for your Windows platform (32-bit or 64-bit) and the version of Python you are using. diff --git a/doc/source/requirements.txt b/doc/source/requirements.txt new file mode 100644 index 000000000..342477ba6 --- /dev/null +++ b/doc/source/requirements.txt @@ -0,0 +1,10 @@ +pip +wheel +requests>=2.28.1 + +sphinxbootstrap4theme +pydoctor + +numpy +pandas +matplotlib diff --git a/doc/source/sphinxext/postprocess_api.py b/doc/source/sphinxext/postprocess_api.py index 7af0d35fb..8a059d84f 100644 --- a/doc/source/sphinxext/postprocess_api.py +++ b/doc/source/sphinxext/postprocess_api.py @@ -1,9 +1,9 @@ """ -Sphinx plugin to run example scripts and create a gallery page. - -Lightly modified from the seaborn project (Michael Waskom). -Originally, lightly modified from the mpld3 project. +Sphinx extension to postprocess pydoctor API output. +- If this is released via Jekyll (e.g. GitHub pages), we need to ensure Jekyll + headers are present everywhere and consistent. +- If this is released via readthedocs (RTD), we can skip this step, see conf.py """ from pathlib import Path @@ -18,8 +18,8 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: # Check if the index has Jekyll template marks. If it does, extract the # YAML frontmatter into a separate variable index_html = html_dir / 'index.html' - with open(index_html, 'rt') as f: - lines = f.readlines() + with open(index_html, 'rt') as handle: + lines = handle.readlines() # The Jekyll template starts with a --- line # Nontemplated HTML starts with some kind of XML tag if lines[0] != '---\n': @@ -78,14 +78,13 @@ def on_build_finished(app: Sphinx, exception: Exception) -> None: footer = footer.replace('"container"', '"container-fluid text-muted credit"').strip() # Patch-up content for Jekyll - content = (''.join(lines_mark[:-1]) + - indent(head, " ") + "\n" + - 'extrafoot: |\n' + - indent(footer, " ") + - indent(rest, " ") + - '\n' + - lines_mark[-1] + - body) + content = (''.join(lines_mark[:-1]) + + indent(head, " ") + "\n" + + 'extrafoot: |\n' + + indent(footer, " ") + + indent(rest, " ") + '\n' + + lines_mark[-1] + + body) # Write the patched content back to the file path.write_text(content) diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index c3089a033..0844d2156 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -573,6 +573,8 @@ The adjacency matrix for the example graph is For example, Claire (``[1, 0, 0, 1, 1, 1, 0]``) is directly connected to Alice (who has vertex index 0), Dennis (index 3), Esther (index 4), and Frank (index 5), but not to Bob (index 1) nor George (index 6). +.. _tutorial-layouts-plotting: + Layouts and plotting ==================== @@ -582,7 +584,7 @@ mapping from vertices to coordinates in two- or three-dimensional space first, preferably in a way that is pleasing for the eye. A separate branch of graph theory, namely graph drawing, tries to solve this problem via several graph layout algorithms. |igraph| implements quite a few layout algorithms and is also able to draw them onto -the screen or to a PDF, PNG or SVG file using the `Cairo library `_. +the screen or to a PDF, PNG or SVG file using the `Cairo library `_. .. important:: To follow the examples of this subsection, you need the Python bindings of the @@ -636,7 +638,7 @@ Method name Short name Algorithm description ==================================== =============== ============================================= .. _Distributed Recursive Layout: https://www.osti.gov/doecode/biblio/54626 -.. _Large Graph Layout: http://sourceforge.net/projects/lgl/ +.. _Large Graph Layout: https://sourceforge.net/projects/lgl/ Layout algorithms can either be called directly or using the common layout method called :meth:`~Graph.layout`:: @@ -874,7 +876,7 @@ Specifying colors in plots color (e.g., edge, vertex or label colors in the respective attributes): X11 color names - See the `list of X11 color names `_ + See the `list of X11 color names `_ in Wikipedia for the complete list. Alternatively you can see the keys of the igraph.drawing.colors.known_colors dictionary. Color names are case insensitive in igraph so "DarkBlue" can be written as @@ -962,13 +964,13 @@ Labeled edgelist ``ncol`` :meth:`Graph.Read_Ncol` :meth:`Graph.write_n Pickled graph ``pickle`` :meth:`Graph.Read_Pickle` :meth:`Graph.write_pickle` ================ ============= ============================ ============================= -.. _GraphViz: http://www.graphviz.org -.. _LGL: http://lgl.sourceforge.net/#FileFormat -.. _NCOL: http://lgl.sourceforge.net/#FileFormat -.. _Pajek: http://pajek.imfm.si/doku.php +.. _GraphViz: https://www.graphviz.org +.. _LGL: https://lgl.sourceforge.net/#FileFormat +.. _NCOL: https://lgl.sourceforge.net/#FileFormat +.. _Pajek: http://mrvar.fdv.uni-lj.si/pajek/ As an exercise, download the graph representation of the well-known -`Zachary karate club study `_ +`Zachary karate club study `_ from :download:`this file `, unzip it and try to load it into |igraph|. Since it is a GraphML file, you must use the GraphML reader method from the table above (make sure you use the appropriate path to the downloaded file):: diff --git a/doc/source/tutorials/articulation_points/articulation_points.rst b/doc/source/tutorials/articulation_points/articulation_points.rst index 5c05a7c6a..85ea30810 100644 --- a/doc/source/tutorials/articulation_points/articulation_points.rst +++ b/doc/source/tutorials/articulation_points/articulation_points.rst @@ -6,10 +6,7 @@ Articulation Points =================== -.. _articulation_points: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#articulation_points -.. |articulation_points| replace:: :meth:`articulation_points` - -This example shows how to compute and visualize the `articulation points `_ in a graph using |articulation_points|_. For an example on bridges instead, see :ref:`tutorials-bridges`. +This example shows how to compute and visualize the `articulation points `_ in a graph using :meth:`igraph.GraphBase.articulation_points`. For an example on bridges instead, see :ref:`tutorials-bridges`. .. code-block:: python diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index 9f76e8dc9..1fc476f1d 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -6,12 +6,7 @@ Betweenness ======================= -.. _betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#betweenness -.. |betweenness| replace:: :meth:`betweenness` -.. _edge_betweenness: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#edge_betweenness -.. |edge_betweenness| replace:: :meth:`edge_betweenness` - -This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods |betweenness|_ and |edge_betweenness|_ respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. +This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods :meth:`igraph.GraphBase.betweenness` and :meth:`igraph.GraphBase.edge_betweenness` respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. First we import |igraph| and some libraries for plotting et al: @@ -23,10 +18,7 @@ First we import |igraph| and some libraries for plotting et al: from matplotlib.colors import LinearSegmentedColormap, Normalize import igraph as ig -.. _rescale: https://igraph.org/python/doc/api/igraph.utils.html#rescale -.. |rescale| replace:: :meth:`rescale` - -Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s |rescale|_ to rescale the betweennesses in the interval ``[0, 1]``: +Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s :meth:`igraph.utils.rescale` to rescale the betweennesses in the interval ``[0, 1]``: .. code-block:: python @@ -85,7 +77,6 @@ Finally, we call our function with the two graphs: figsize=(7, 6), gridspec_kw=dict(height_ratios=(15, 1, 1)), ) - #plt.subplots_adjust(bottom=0.3) plot_betweenness(g1, fig, *axs[:, 0]) plot_betweenness(g2, fig, *axs[:, 1]) fig.tight_layout(h_pad=1) diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst index 8334f77c7..0464a7e48 100644 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst @@ -6,10 +6,7 @@ Maximum Bipartite Matching ========================== -.. _maximum_bipartite_matching: https://igraph.org/python/doc/api/igraph.Graph.html#maximum_bipartite_matching -.. |maximum_bipartite_matching| replace:: :meth:`maximum_bipartite_matching` - -This example demonstrates an efficient way to find and visualise a maximum biparite matching using |maximum_bipartite_matching|_. First construct a bipartite graph +This example demonstrates an efficient way to find and visualise a maximum biparite matching using :meth:`igraph.Graph.maximum_bipartite_matching`. First construct a bipartite graph .. code-block:: python diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst index 83ed53426..5034878cb 100644 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst @@ -6,14 +6,9 @@ Maximum Bipartite Matching by Maximum Flow ========================================== -.. _maximum_bipartite_matching: https://igraph.org/python/doc/api/igraph.Graph.html#maximum_bipartite_matching -.. |maximum_bipartite_matching| replace:: :meth:`maximum_bipartite_matching` -.. _maxflow: https://igraph.org/python/doc/api/igraph.Graph.html#maxflow -.. |maxflow| replace:: :meth:`maxflow` +This example presents how to visualise bipartite matching using maximum flow (see :meth:`igraph.Graph.maxflow`). -This example presents how to visualise bipartite matching using maximum flow (see |maxflow|_). - -.. note:: |maximum_bipartite_matching|_ is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out :ref:`tutorials-bipartite-matching`. +.. note:: :meth:`igraph.Graph.maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out :ref:`tutorials-bipartite-matching`. .. code-block:: python @@ -38,7 +33,7 @@ This example presents how to visualise bipartite matching using maximum flow (se flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1.0 print("Size of maximum matching (maxflow) is:", flow.value) -Let's compare the output against |maximum_bipartite_matching|_ +Let's compare the output against :meth:`igraph.Graph.maximum_bipartite_matching`: .. code-block:: python diff --git a/doc/source/tutorials/bridges/bridges.rst b/doc/source/tutorials/bridges/bridges.rst index 13838b2a1..3505864d8 100644 --- a/doc/source/tutorials/bridges/bridges.rst +++ b/doc/source/tutorials/bridges/bridges.rst @@ -6,10 +6,7 @@ Bridges ======== -.. _bridges_method: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#bridges -.. |bridges_method| replace:: :meth:`bridges_method` - -This example shows how to compute and visualize the `bridges `_ in a graph using |bridges_method|_. For an example on articulation points instead, see :ref:`tutorials-articulation-points`. +This example shows how to compute and visualize the `bridges `_ in a graph using :meth:`igraph.GraphBase.bridges`. For an example on articulation points instead, see :ref:`tutorials-articulation-points`. .. code-block:: python diff --git a/doc/source/tutorials/cluster_graph/cluster_graph.rst b/doc/source/tutorials/cluster_graph/cluster_graph.rst index 5e5e61921..4915984c7 100644 --- a/doc/source/tutorials/cluster_graph/cluster_graph.rst +++ b/doc/source/tutorials/cluster_graph/cluster_graph.rst @@ -6,12 +6,7 @@ Generating Cluster Graphs =========================== -.. _cluster_graph: https://igraph.org/python/doc/api/igraph.clustering.VertexClustering.html#cluster_graph -.. |cluster_graph| replace:: :meth:`cluster_graph` -.. _community_edge_betweenness: https://igraph.org/python/doc/api/igraph.Graph.html#community_edge_betweenness -.. |community_edge_betweenness| replace:: :meth:`community_edge_betweenness` - -This example shows how to find the communities in a graph, then contract each community into a single node using |cluster_graph|_. For this tutorial, we'll use the *Donald Knuth's Les Miserables Network*, which shows the coapperances of characters in the novel *Les Miserables*. The network can be obtained `here `_. +This example shows how to find the communities in a graph, then contract each community into a single node using :class:`igraph.clustering.VertexClustering`. For this tutorial, we'll use the *Donald Knuth's Les Miserables Network*, which shows the coapperances of characters in the novel *Les Miserables*. The network can be obtained `here `_. .. code-block:: python @@ -21,7 +16,7 @@ This example shows how to find the communities in a graph, then contract each co # Load the graph g = ig.load("./lesmis/lesmis.gml") -First, let's visualise the original communities, using |community_edge_betweenness|_ to separate out vertices into clusters. (For a more focused tutorial on just visualising communities, check out :ref:`tutorials-visualize-communities`). +First, let's visualise the original communities, using :meth:`igraph.Graph.community_edge_betweenness` to separate out vertices into clusters. (For a more focused tutorial on just visualising communities, check out :ref:`tutorials-visualize-communities`). .. code-block:: python @@ -69,7 +64,7 @@ Now let's try and contract the information down, using only a single vertex to r g.vs["size"] = 1 g.es["size"] = 1 -This is so we can define how each of these attributes get combined together when we call |cluster_graph|_. +This is so we can define how each of these attributes get combined together when we call :meth:`igraph.VertexClustering.cluster_graph`. .. code-block:: python @@ -88,12 +83,9 @@ This is so we can define how each of these attributes get combined together when Here, we take the mean of x and y values so that the nodes in the cluster graph are placed at the center of the original cluster's position. -.. _contract_vertices: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#contract_vertices -.. |contract_vertices| replace:: :meth:`contract_vertices` - .. note:: - ``mean``, ``first``, and ``sum`` are all built-in collapsing functions, along with ``prod``, ``median``, ``max``, ``min``, ``last``, ``random``. You can also define your own custom collapsing functions, which take in a list and return a single element representing the combined attribute value. For more details on |igraph| contraction, see |contract_vertices|_ + ``mean``, ``first``, and ``sum`` are all built-in collapsing functions, along with ``prod``, ``median``, ``max``, ``min``, ``last``, ``random``. You can also define your own custom collapsing functions, which take in a list and return a single element representing the combined attribute value. For more details on |igraph| contraction, see :meth:`igraph.GraphBase.contract_vertices` Finally we plot out the graph using our calculated attributes: diff --git a/doc/source/tutorials/complement/complement.rst b/doc/source/tutorials/complement/complement.rst index 3b887ba41..cd51bcf61 100644 --- a/doc/source/tutorials/complement/complement.rst +++ b/doc/source/tutorials/complement/complement.rst @@ -6,10 +6,7 @@ Complement ================ -.. _complementer: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#complementer -.. |complementer| replace:: :meth:`complementer` - -This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using |complementer|_. +This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using :meth:`igraph.GraphBase.complementer`. First we generate a random graph diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst index 4a9a172ce..558f07fae 100644 --- a/doc/source/tutorials/configuration/configuration.rst +++ b/doc/source/tutorials/configuration/configuration.rst @@ -6,7 +6,7 @@ Configuration Instance ====================== -This example shows how to use |igraph|'s `configuration instance `_ to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. +This example shows how to use |igraph|'s :class:`configuration instance ` to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. First we define the default plotting backend, layout, and color palette, and save them. By default, ``ig.config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``%USERPROFILE%\.igraphrc`` for Windows systems. @@ -50,7 +50,7 @@ Note that we do not never explicitly state the backend, layout or palette, yet t Graph colored based on each node's betweenness centrality measure. -The full list of config settings can be found `here `_. +The full list of config settings can be found at :class:`igraph.Configuration`. .. note:: diff --git a/doc/source/tutorials/connected_components/connected_components.rst b/doc/source/tutorials/connected_components/connected_components.rst index 505af1494..d8a8578c3 100644 --- a/doc/source/tutorials/connected_components/connected_components.rst +++ b/doc/source/tutorials/connected_components/connected_components.rst @@ -6,10 +6,7 @@ Connected Components ===================== -.. _connected_components: https://igraph.org/python/doc/api/igraph.Graph.html#connected_components -.. |connected_components| replace:: :meth:`connected_components` - -This example demonstrates how to visualise the connected components in a graph using |connected_components|_. +This example demonstrates how to visualise the connected components in a graph using :meth:`igraph.GraphBase.connected_components`. .. code-block:: python @@ -47,4 +44,4 @@ The plotting results are: .. note:: - We use the integers from 0 to 200 instead of 0 to 255 in our vertex colors, since 255 in the `rainbow palette `_ corresponds to looping back to red. + We use the integers from 0 to 200 instead of 0 to 255 in our vertex colors, since 255 in the :class:`igraph.drawing.colors.RainbowPalette` corresponds to looping back to red. diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst index 4ba1c3c31..dc0349652 100644 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst @@ -6,11 +6,7 @@ Erdős-Rényi Graph ================= -.. _Erdos_Renyi: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#Erdos_Renyi -.. |Erdos_Renyi| replace:: :meth:`Erdos_Renyi` - - -This example demonstrates how to generate `Erdős-Rényi Graphs `_ using |Erdos_Renyi|_. There are two variants of graphs: +This example demonstrates how to generate `Erdős-Rényi Graphs `_ using :meth:`igraph.GraphBase.Erdos_Renyi`. There are two variants of graphs: - ``Erdos_Renyi(n, p)`` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. - ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst index e0b8b8a30..1d4175623 100644 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ b/doc/source/tutorials/isomorphism/isomorphism.rst @@ -6,10 +6,7 @@ Isomorphism =========== -.. _isomorphic: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#isomorphic -.. |isomorphic| replace:: :meth:`isomorphic` - -This example shows how to check for `isomorphism `_ between small graphs using |isomorphic|_. +This example shows how to check for `isomorphism `_ between small graphs using :meth:`igraph.GraphBase.isomorphic`. First we generate three different graphs: diff --git a/doc/source/tutorials/maxflow/maxflow.rst b/doc/source/tutorials/maxflow/maxflow.rst index 0e93ec577..85cb8a4ca 100644 --- a/doc/source/tutorials/maxflow/maxflow.rst +++ b/doc/source/tutorials/maxflow/maxflow.rst @@ -6,10 +6,7 @@ Maximum Flow ============ -.. _maxflow: https://igraph.org/python/doc/api/igraph.Graph.html#maxflow -.. |maxflow| replace:: :meth:`maxflow` - -This example shows how to construct a max flow on a directed graph with edge capacities using |maxflow|_. +This example shows how to construct a max flow on a directed graph with edge capacities using :meth:`igraph.Graph.maxflow`. .. code-block:: python diff --git a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst b/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst index 8978eb30d..c24e67e3b 100644 --- a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst +++ b/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst @@ -6,10 +6,7 @@ Minimum Spanning Trees ====================== -.. _spanning_tree: https://igraph.org/python/doc/api/igraph.Graph.html#spanning_tree -.. |spanning_tree| replace:: :meth:`spanning_tree` - -This example shows how to generate a `minimum spanning tree `_ from an input graph using |spanning_tree|_. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. +This example shows how to generate a `minimum spanning tree `_ from an input graph using :meth:`igraph.Graph.spanning_tree`. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. We start by generating a grid graph with random integer weights between 1 and 20: @@ -25,7 +22,7 @@ We start by generating a grid graph with random integer weights between 1 and 20 g = ig.Graph.Lattice([5, 5], circular=False) g.es["weight"] = [random.randint(1, 20) for _ in g.es] -We then call |spanning_tree|_, making sure to pass in the randomly generated weights. +We then call :meth:`igraph.Graph.spanning_tree`, making sure to pass in the randomly generated weights. .. code-block:: python diff --git a/doc/source/tutorials/ring_animation/ring_animation.rst b/doc/source/tutorials/ring_animation/ring_animation.rst index 455913572..e18411058 100644 --- a/doc/source/tutorials/ring_animation/ring_animation.rst +++ b/doc/source/tutorials/ring_animation/ring_animation.rst @@ -53,9 +53,6 @@ The received output is: Sequentially Animated Ring Graph -.. _induced_subgraph: https://igraph.org/python/api/latest/igraph._igraph.GraphBase.html#induced_subgraph -.. |induced_subgraph| replace:: :meth:`induced_subgraph` - .. note:: - We use *igraph*'s :meth:`Graph.subgraph()` (see |induced_subgraph|_) in order to obtain a section of the ring graph at a time for each frame. + We use *igraph*'s :meth:`Graph.subgraph()` (see :meth:`igraph.GraphBase.induced_subgraph`) in order to obtain a section of the ring graph at a time for each frame. diff --git a/doc/source/tutorials/shortest_paths/shortest_paths.rst b/doc/source/tutorials/shortest_paths/shortest_paths.rst index a8fe6c8e6..fab61b0cf 100644 --- a/doc/source/tutorials/shortest_paths/shortest_paths.rst +++ b/doc/source/tutorials/shortest_paths/shortest_paths.rst @@ -6,14 +6,9 @@ Shortest Paths ============== -.. _get_shortest_paths: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#get_shortest_paths -.. |get_shortest_paths| replace:: :meth:`get_shortest_paths` -.. _get_all_shortest_paths: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#get_all_shortest_paths -.. |get_all_shortest_paths| replace:: :meth:`get_all_shortest_paths` - This example demonstrates how to find the shortest distance between two vertices on a weighted and unweighted graph. -To find the shortest path or distance between two nodes, we can use |get_shortest_paths|_. If we're only interested in counting the unweighted distance, then we can do the following: +To find the shortest path or distance between two nodes, we can use :meth:`igraph.GraphBase.get_shortest_paths`. If we're only interested in counting the unweighted distance, then we can do the following: .. code-block:: python @@ -76,8 +71,8 @@ The output of these these two shortest paths are: .. note:: - - |get_shortest_paths|_ returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. - - If you're interested in finding *all* shortest paths, take a look at |get_all_shortest_paths|_. + - :meth:`igraph.GraphBase.get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. + - If you're interested in finding *all* shortest paths, take a look at :meth:`igraph.GraphBase.get_all_shortest_paths`. In case you are wondering how the visualization figure was done, here's the code: diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst index 3721f56b4..8012d5958 100644 --- a/doc/source/tutorials/simplify/simplify.rst +++ b/doc/source/tutorials/simplify/simplify.rst @@ -6,10 +6,7 @@ Simplify ======== -.. _simplify: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#simplify -.. |simplify| replace:: :meth:`simplify` - -This example shows how to remove self loops and multiple edges using |simplify|_. +This example shows how to remove self loops and multiple edges using :meth:`igraph.GraphBase.simplify`. We start with a graph that includes loops and multiedges: diff --git a/doc/source/tutorials/spanning_trees/spanning_trees.rst b/doc/source/tutorials/spanning_trees/spanning_trees.rst index d60b58c95..cbc704269 100644 --- a/doc/source/tutorials/spanning_trees/spanning_trees.rst +++ b/doc/source/tutorials/spanning_trees/spanning_trees.rst @@ -6,10 +6,7 @@ Spanning Trees ============== -.. _spanning_tree: https://igraph.org/python/doc/api/igraph.Graph.html#spanning_tree -.. |spanning_tree| replace:: :meth:`spanning_tree` - -This example shows how to generate a spanning tree from an input graph using |spanning_tree|_. For the related idea of finding a *minimum spanning tree*, see :ref:`tutorials-minimum-spanning-trees`. +This example shows how to generate a spanning tree from an input graph using :meth:`igraph.Graph.spanning_tree`. For the related idea of finding a *minimum spanning tree*, see :ref:`tutorials-minimum-spanning-trees`. First we create a 6 by 6 lattice graph. @@ -21,10 +18,7 @@ First we create a 6 by 6 lattice graph. g = ig.Graph.Lattice([6, 6], circular=False) -.. _permute_vertices: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#permute_vertices -.. |permute_vertices| replace:: :meth:`permute_vertices` - -As an optional step, we randomly rearrange some of the vertex IDs with |permute_vertices|_ in order to generate a more interesting spanning tree. +As an optional step, we randomly rearrange some of the vertex IDs with :meth:`igraph.GraphBase.permute_vertices` in order to generate a more interesting spanning tree. .. code-block:: python diff --git a/doc/source/tutorials/topological_sort/topological_sort.rst b/doc/source/tutorials/topological_sort/topological_sort.rst index d3d1b052b..451d72f5e 100644 --- a/doc/source/tutorials/topological_sort/topological_sort.rst +++ b/doc/source/tutorials/topological_sort/topological_sort.rst @@ -6,11 +6,7 @@ Topological sorting =================== -.. _topological_sorting: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#topological_sorting -.. |topological_sorting| replace:: :meth:`topological_sorting` - - -This example demonstrates how to get a topological sorting on a directed acyclic graph (DAG). A topological sorting of a directed graph is a linear ordering based on the precedence implied by the directed edges. It exists iff the graph doesn't have any cycle. In ``igraph``, we can use |topological_sorting|_ to get a topological ordering of the vertices. +This example demonstrates how to get a topological sorting on a directed acyclic graph (DAG). A topological sorting of a directed graph is a linear ordering based on the precedence implied by the directed edges. It exists iff the graph doesn't have any cycle. In ``igraph``, we can use :meth:`igraph.GraphBase.topological_sorting` to get a topological ordering of the vertices. .. code-block:: python @@ -31,7 +27,7 @@ This example demonstrates how to get a topological sorting on a directed acyclic results = g.topological_sorting(mode='in') print('Topological sort of g (in):', *results) -There are two modes of |topological_sorting|_. ``'out'`` is the default mode which starts from a node with indegree equal to 0. Vice versa, the mode ``'in'`` starts from a node with outdegree equal to 0. +There are two modes of :meth:`igraph.GraphBase.topological_sorting`. ``'out'`` is the default mode which starts from a node with indegree equal to 0. Vice versa, the mode ``'in'`` starts from a node with outdegree equal to 0. The output of the code above is: diff --git a/doc/source/tutorials/visual_style/visual_style.rst b/doc/source/tutorials/visual_style/visual_style.rst index ec554aad3..095c043eb 100644 --- a/doc/source/tutorials/visual_style/visual_style.rst +++ b/doc/source/tutorials/visual_style/visual_style.rst @@ -47,4 +47,4 @@ The plots looks like this: Four graphs using the same palette and layout algorithm. .. note:: - If you would like to set global defaults, for example, always using the Matplotlib plotting backend, or using a particular color palette by default, you can use |igraph|'s `configuration instance `_. A quick example on how to use it can be found here: :ref:`tutorials-configuration` + If you would like to set global defaults, for example, always using the Matplotlib plotting backend, or using a particular color palette by default, you can use |igraph|'s `configuration instance :class:`igraph.configuration.Configuration`. A quick example on how to use it can be found here: :ref:`tutorials-configuration` diff --git a/doc/source/tutorials/visualize_cliques/visualize_cliques.rst b/doc/source/tutorials/visualize_cliques/visualize_cliques.rst index b2ac037fd..55b3c9dce 100644 --- a/doc/source/tutorials/visualize_cliques/visualize_cliques.rst +++ b/doc/source/tutorials/visualize_cliques/visualize_cliques.rst @@ -6,11 +6,7 @@ Cliques ============ -.. _cliques: https://igraph.org/python/doc/api/igraph._igraph.GraphBase.html#cliques -.. |cliques| replace:: :meth:`cliques` - -This example shows how to compute and visualize cliques of a graph using |cliques|_. - +This example shows how to compute and visualize cliques of a graph using :meth:`igraph.GraphBase.cliques`. .. code-block:: python diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index e766a1cd3..8d2274cff 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -11,7 +11,7 @@ In the following examples, we will assume |igraph| is imported as `ig` and a >>> import igraph as ig >>> g = ig.Graph(edges=[[0, 1], [2, 3]]) -Read the `API documentation`_ for details on each function and class. The `tutorial`_ contains examples to get started. +Read the :doc:`api/index` for details on each function and class. See the :ref:`tutorial ` and the :doc:`gallery` for examples. Graph layouts ============= @@ -221,12 +221,10 @@ You can also specify vertex and edge color, size, and labels - and more - via ad ... edge_color=['black', 'grey'], ... ) -See the `tutorial`_ for examples and a full list of options. +See the :ref:`tutorial ` for examples and a full list of options. -.. _API documentation: https://igraph.org/python/api/latest/ .. _matplotlib: https://matplotlib.org .. _Jupyter: https://jupyter.org/ -.. _tutorial: https://igraph.org/python/doc/tutorial/tutorial.html#layouts-and-plotting .. _Cairo: https://www.cairographics.org .. _graphviz: http://www.graphviz.org .. _networkx: https://networkx.org/ diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 0636e9de7..ef820ae95 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -12,8 +12,9 @@ set -e STANDALONE=0 SERVE=0 DOC2DASH=0 +LINKCHECK=0 -while getopts ":sjd" OPTION; do +while getopts ":sjdl" OPTION; do case $OPTION in s) STANDALONE=1 @@ -24,6 +25,9 @@ while getopts ":sjd" OPTION; do d) DOC2DASH=1 ;; + l) + LINKCHECK=1 + ;; \?) echo "Usage: $0 [-sjd]" exit 1 @@ -38,6 +42,7 @@ cd ${SCRIPTS_FOLDER}/.. ROOT_FOLDER=`pwd` DOC_SOURCE_FOLDER=${ROOT_FOLDER}/doc/source DOC_HTML_FOLDER=${ROOT_FOLDER}/doc/html +DOC_LINKCHECK_FOLDER=${ROOT_FOLDER}/doc/linkcheck SCRIPTS_FOLDER=${ROOT_FOLDER}/scripts cd ${ROOT_FOLDER} @@ -52,7 +57,7 @@ if [ ! -d ".venv" ]; then fi # Make sure that Sphinx, PyDoctor (and maybe doc2dash) are up-to-date in the virtualenv -.venv/bin/pip install -U sphinx pydoctor +.venv/bin/pip install -U sphinx pydoctor sphinxbootstrap4theme if [ x$DOC2DASH = x1 ]; then .venv/bin/pip install -U doc2dash fi @@ -74,15 +79,27 @@ echo "Patching modularized Graph methods" .venv/bin/python3 ${SCRIPTS_FOLDER}/patch_modularized_graph_methods.py -# Remove previous docs +echo "Clean previous docs" rm -rf "${DOC_HTML_FOLDER}" -# Make sphinx +if [ "x$LINKCHECK" = "x1" ]; then + echo "Check for broken links" + .venv/bin/python -m sphinx \ + -T \ + -b linkcheck \ + -Dtemplates_path='' \ + -Dhtml_theme='alabaster' \ + ${DOC_SOURCE_FOLDER} ${DOC_LINKCHECK_FOLDER} +fi + + echo "Generating HTML documentation..." if [ "x$STANDALONE" = "x1" ]; then echo "Build standalone docs" - .venv/bin/sphinx-build \ + .venv/bin/python -m sphinx \ + -T \ + -b html \ -Dtemplates_path='' \ -Dhtml_theme='alabaster' \ ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} diff --git a/scripts/rtd_prebuild.sh b/scripts/rtd_prebuild.sh new file mode 100755 index 000000000..b35e22f0a --- /dev/null +++ b/scripts/rtd_prebuild.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo "Compile and install igraph into venv. This might take a few minutes..." +/home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/bin/pip wheel -q -w dist . +/home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/bin/pip install -q --force-reinstall dist/*.whl + +echo "Modularize pure Python modules" +/home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/bin/python3 scripts/patch_modularized_graph_methods.py + +echo "NOTE: Patch pydoctor to trigger build-finished before RTD extension" +# see https://www.sphinx-doc.org/en/master/extdev/appapi.html#sphinx.application.Sphinx.connect +# see also https://github.com/readthedocs/readthedocs.org/pull/4054 - might or might not be exactly what we are seeing here +sed -i 's/on_build_finished)/on_build_finished, priority=490)/' /home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/lib/python3.9/site-packages/pydoctor/sphinx_ext/build_apidocs.py diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index e98257173..756055222 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -7979,13 +7979,13 @@ PyObject *igraphmodule_Graph_layout_sugiyama( return (PyObject *) result_o; } - /** \ingroup python_interface_graph - * \brief Places the vertices of a graph using Uniform Manifold Approximation and Projection (UMAP) +/** \ingroup python_interface_graph + * \brief Uniform Manifold Approximation and Projection (UMAP) * \return the calculated coordinates as a Python list of lists * \sa igraph_layout_umap */ -PyObject *igraphmodule_Graph_layout_umap(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) +PyObject *igraphmodule_Graph_layout_umap( + igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "dist", "dim", "seed", "min_dist", "epochs", "sampling_prob", NULL }; @@ -15522,7 +15522,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_umap", (PyCFunction) igraphmodule_Graph_layout_umap, METH_VARARGS | METH_KEYWORDS, - "layout_umap(dist=None, dim=2, seed=None, min_dist=0.01, epochs=500, sampling_prob=0.3)\n--\n\n" + "layout_umap(\n" + " dist=None, dim=2, seed=None, min_dist=0.01,\n" + " epochs=500, sampling_prob=0.3)\n--\n\n" "Uniform Manifold Approximation and Projection (UMAP).\n\n" "This layout is a probabilistic algorithm that places vertices that are connected\n" "and have a short distance close by in the embedded space.\n\n" @@ -15536,16 +15538,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param min_dist: the minimal distance in the embedded space beyond which the\n" " probability of being located closeby decreases.\n" "@param epochs: the number of epochs (iterations) the algorithm will iterate\n" - " over. Accuracy increases with more epochs, at the cost of longer\n " - " runtimes. Values between 50 and 1000 are typical.\n" - " Notice that UMAP does not technically converge for symmetry reasons, but a \n" + " over. Accuracy increases with more epochs, at the cost of longer runtimes.\n" + " Values between 50 and 1000 are typical.\n" + " Notice that UMAP does not technically converge for symmetry reasons, but a\n" " larger number of epochs should generally give an equivalent or better layout.\n" "@param sampling_prob: the probability of sampling each vertex for repulsion at\n" " each epoch or iteration. A higher probability will give better results but\n" " also require more computations.\n" "@return: the calculated layout.\n\n" "@newfield ref: Reference\n" - "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation \n" + "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation\n" " and Projection for Dimension Reduction. arXiv:1802.03426."}, //////////////////////////// From 07d717fe5e14f366f994273e9e82bfa37d478302 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Oct 2022 17:03:15 +1100 Subject: [PATCH 1112/1892] Typo in tutorials (#569) --- doc/source/tutorials/betweenness/betweenness.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/tutorials/betweenness/betweenness.rst b/doc/source/tutorials/betweenness/betweenness.rst index 1fc476f1d..5ac6d3bd3 100644 --- a/doc/source/tutorials/betweenness/betweenness.rst +++ b/doc/source/tutorials/betweenness/betweenness.rst @@ -77,8 +77,8 @@ Finally, we call our function with the two graphs: figsize=(7, 6), gridspec_kw=dict(height_ratios=(15, 1, 1)), ) - plot_betweenness(g1, fig, *axs[:, 0]) - plot_betweenness(g2, fig, *axs[:, 1]) + plot_betweenness(g1, *axs[:, 0]) + plot_betweenness(g2, *axs[:, 1]) fig.tight_layout(h_pad=1) plt.show() From 37726ad3600640d1119bb7a17548edb39d3064fa Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 13:17:37 +0200 Subject: [PATCH 1113/1892] feat: added Graph.modularity_matrix() --- CHANGELOG.md | 5 ++++ src/_igraph/graphobject.c | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c370ac90d..df2869de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +### Added + +- Added `Graph.modularity_matrix()` to calculate the modularity matrix of + a graph. + ### Fixed - Fixed a crash in `Graph.decompose()` that was accidentally introduced in diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 756055222..52fd1a4ec 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11807,6 +11807,52 @@ PyObject *igraphmodule_Graph_modularity(igraphmodule_GraphObject *self, return igraphmodule_real_t_to_PyObject(modularity, IGRAPHMODULE_TYPE_FLOAT); } +/** + * Modularity matrix calculation + */ +PyObject *igraphmodule_Graph_modularity_matrix(igraphmodule_GraphObject *self, + PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"weights", "resolution", "directed", 0}; + igraph_vector_t *weights=0; + double resolution = 1; + igraph_real_t modularity; + igraph_matrix_t result; + PyObject *wvec = Py_None; + PyObject *directed = Py_True; + PyObject *result_o; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OdO", kwlist, &wvec, &resolution, &directed)) + return NULL; + + if (igraphmodule_attrib_to_vector_t(wvec, self, &weights, ATTRIBUTE_TYPE_EDGE)) + return NULL; + + if (igraph_matrix_init(&result, 0, 0)) { + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + return NULL; + } + + if (igraph_modularity_matrix(&self->g, weights, resolution, &result, PyObject_IsTrue(directed))) { + igraph_matrix_destroy(&result); + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + return NULL; + } + + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + + result_o = igraphmodule_matrix_t_to_PyList(&result, IGRAPHMODULE_TYPE_FLOAT); + + igraph_matrix_destroy(&result); + + return result_o; +} + /** * Newman's edge betweenness method */ @@ -16651,6 +16697,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /*********************************/ /* COMMUNITIES AND DECOMPOSITION */ /*********************************/ + {"modularity", (PyCFunction) igraphmodule_Graph_modularity, METH_VARARGS | METH_KEYWORDS, "modularity(membership, weights=None, resolution=1, directed=True)\n--\n\n" @@ -16688,6 +16735,21 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@ref: MEJ Newman and M Girvan: Finding and evaluating community structure\n" " in networks. Phys Rev E 69 026113, 2004.\n" }, + {"modularity_matrix", (PyCFunction) igraphmodule_Graph_modularity_matrix, + METH_VARARGS | METH_KEYWORDS, + "modularity_matrix(weights=None, resolution=1, directed=True)\n--\n\n" + "Calculates the modularity matrix of the graph.\n\n" + "@param weights: optional edge weights or C{None} if all edges are weighed\n" + " equally.\n" + "@param resolution: the resolution parameter I{gamma} of the modularity formula\n." + " The classical definition of modularity is retrieved when the resolution\n" + " parameter is set to 1.\n" + "@param directed: whether to consider edge directions if the graph is directed.\n" + " C{True} will use the directed variant of the modularity measure where the\n" + " in- and out-degrees of nodes are treated separately; C{False} will treat\n" + " directed graphs as undirected.\n" + "@return: the modularity matrix as a list of lists.\n" + }, {"coreness", (PyCFunction) igraphmodule_Graph_coreness, METH_VARARGS | METH_KEYWORDS, "coreness(mode=\"all\")\n--\n\n" From 49aed354a0a89fa441991154feb76678d401534b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 16:14:49 +0200 Subject: [PATCH 1114/1892] fix: remove unused variable --- src/_igraph/graphobject.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 52fd1a4ec..afc97ae1f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11815,7 +11815,6 @@ PyObject *igraphmodule_Graph_modularity_matrix(igraphmodule_GraphObject *self, static char *kwlist[] = {"weights", "resolution", "directed", 0}; igraph_vector_t *weights=0; double resolution = 1; - igraph_real_t modularity; igraph_matrix_t result; PyObject *wvec = Py_None; PyObject *directed = Py_True; From c9cbbce94598419c63a1884d5552bec9783d66be Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 16:15:26 +0200 Subject: [PATCH 1115/1892] refactor: setup.py arguments can now be replaced with envvars, refs #592 --- setup.py | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index c39a63eac..9938feaaf 100644 --- a/setup.py +++ b/setup.py @@ -63,6 +63,12 @@ def exclude_from_list(items: Iterable[T], items_to_exclude: Iterable[T]) -> List return [item for item in items if item not in itemset] +def fail(message: str, code: int = 1) -> None: + """Fails the build with the given error message and exit code.""" + print(message) + sys.exit(code) + + def find_static_library(library_name: str, library_path: List[str]) -> Optional[str]: """Given the raw name of a library in `library_name`, tries to find a static library with this name in the given `library_path`. `library_path` @@ -335,6 +341,7 @@ def __init__(self): self.static_extension = False self.use_pkgconfig = False self.c_core_built = False + self.allow_educated_guess = True self._has_pkgconfig = None self.excluded_include_dirs = [] self.excluded_library_dirs = [] @@ -396,8 +403,7 @@ def run(self): # Bail out if we don't have the Python include files include_dir = sysconfig.get_path('include') if not os.path.isfile(os.path.join(include_dir, "Python.h")): - print("You will need the Python headers to compile this extension.") - sys.exit(1) + fail("You will need the Python headers to compile this extension.") # Check whether the user asked us to discover a pre-built igraph # with pkg-config @@ -405,17 +411,19 @@ def run(self): if buildcfg.use_pkgconfig: detected = buildcfg.detect_from_pkgconfig() if not detected: - print( + fail( "Cannot find the C core of igraph on this system using pkg-config." ) - sys.exit(1) else: # Build the C core from the vendored igraph source self.run_command("build_c_core") if not buildcfg.c_core_built: # Fall back to an educated guess if everything else failed if not detected: - buildcfg.use_educated_guess() + if buildcfg.allow_educated_guess: + buildcfg.use_educated_guess() + else: + fail("Cannot build the C core of igraph.") # Add any extra library paths if needed; this is needed for the # Appveyor CI build @@ -618,9 +626,7 @@ def compile_igraph_from_vendor_source(self) -> bool: ) if libraries is False: - print("Build failed for the C core of igraph.") - print("") - sys.exit(1) + fail("Build failed for the C core of igraph.") assert not isinstance(libraries, bool) @@ -686,7 +692,8 @@ def print_build_info(self) -> None: def process_args_from_command_line(self): """Preprocesses the command line options before they are passed to - setup.py and sets up the build configuration.""" + setup.py and sets up the build configuration. + """ # Yes, this is ugly, but we don't want to interfere with setup.py's own # option handling opts_to_remove = [] @@ -709,6 +716,34 @@ def process_args_from_command_line(self): for idx in reversed(opts_to_remove): sys.argv[idx : (idx + 1)] = [] + def process_environment_variables(self): + """Processes environment variables that serve as replacements for the + command line options. This is typically useful in CI environments where + it is easier to set up a few environment variables permanently than to + pass the same options to ``setup.py build`` and ``setup.py install`` + at the same time. + """ + def process_envvar(name, attr, value): + name = "IGRAPH_" + name.upper() + if name in os.environ: + value = str(os.environ[name]).lower() + if value in ("on", "true", "yes"): + value = True + elif value in ("off", "false", "no"): + value = False + else: + try: + value = bool(int(value)) + except Exception: + return + + setattr(self, attr, value) + + process_envvar("static", "static_extension", True) + process_envvar("no_pkg_config", "use_pkgconfig", False) + process_envvar("no_wait", "wait", False) + process_envvar("use_pkg_config", "use_pkgconfig", True) + def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static versions if the static version is to be found on the library path.""" @@ -820,6 +855,7 @@ def get_tag(self): # Process command line options buildcfg = BuildConfiguration() +buildcfg.process_environment_variables() buildcfg.process_args_from_command_line() # Define the extension From 59b7922764fcbf76cca294ce6ed7043f39a0d5f0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 16:20:09 +0200 Subject: [PATCH 1116/1892] chore: updated README so it now refers to the environment variables and not the command line options --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7f5cb06be..252e2289c 100644 --- a/README.md +++ b/README.md @@ -120,23 +120,25 @@ pkg-config --cflags --libs igraph If `pkg-config` responds with a set of compiler and linker flags and not an error message, you are probably okay. You can then proceed with the -installation using pip: +installation using pip after setting the environment variable named +`IGRAPH_USE_PKG_CONFIG` to `1` to indicate that you want to use an +igraph instance discoverable with `pkg-config`: ```bash -pip install igraph --install-option="--use-pkg-config" +IGRAPH_USE_PKG_CONFIG=1 pip install igraph ``` Alternatively, if you have already downloaded and extracted the source code of igraph, you can run `setup.py` directly: ```bash -python setup.py build --use-pkg-config -python setup.py install --use-pkg-config +IGRAPH_USE_PKG_CONFIG=1 python setup.py build +IGRAPH_USE_PKG_CONFIG=1 python setup.py install ``` -(Note that you need `--use-pkg-config` for both invocations, otherwise the call -to `setup.py install` would still build the vendored C core instead of linking -to an existing installation). +(Note that you need the `IGRAPH_USE_PKG_CONFIG=1` environment variable +for both invocations, otherwise the call to `setup.py install` would still +build the vendored C core instead of linking to an existing installation). This option is primarily intended for package maintainers in Linux distributions so they can ensure that the packaged Python interface links to From ee25f6393f8861d71d3e17b1a77e9e72c793c6db Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 16:40:57 +0200 Subject: [PATCH 1117/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 17e828a49..2c0cebbaa 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 17e828a4970e4301ed98315550566f9c3fb53960 +Subproject commit 2c0cebbaa6e8179f1c2ed79f9d189eb22dc08f38 From 15df26f0b700d7d952fb3752e13840769025ff9f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 18:19:23 +0200 Subject: [PATCH 1118/1892] chore: updated vendored igraph to 0.10.2 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 2c0cebbaa..bc7c16000 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 2c0cebbaa6e8179f1c2ed79f9d189eb22dc08f38 +Subproject commit bc7c160008ffe3d8dbc352c77add1571e282b519 From 734c69ce928e71e6dfe35933802b0ef6aaa3f3bc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 19:13:10 +0200 Subject: [PATCH 1119/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df2869de8..c22ab84cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,32 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.2] - 2022-10-14 ### Added +- `python-igraph` is now tested in Python 3.11. + - Added `Graph.modularity_matrix()` to calculate the modularity matrix of a graph. +- Added `Graph.get_k_shortest_paths()`, thanks to + [@sombreslames](https://github.com/user/sombreslames). See PR + [#577](https://github.com/igraph/python-igraph/pull/577) for details. + +- The `setup.py` script now also accepts environment variables instead of + command line arguments to configure several aspects of the build process + (i.e. whether a fully static extension is being built, or whether it is + allowed to use `pkg-config` to retrieve the compiler and linker flags for + an external `igraph` library instead of the vendored one). The environment + variables are named similarly to the command line arguments but in + uppercase, dashes replaced with underscores, and they are prefixed with + `IGRAPH_` (i.e. `--use-pkg-config` becomes `IGRAPH_USE_PKG_CONFIG`). + +### Changed + +- The C core of igraph was updated to version 0.10.2, fixing a range of bugs + originating from the C core. + ### Fixed - Fixed a crash in `Graph.decompose()` that was accidentally introduced in @@ -15,6 +35,14 @@ - `Clustering.sizes()` now works correctly even if the membership vector contains `None` items. +- `Graph.modularity()` and `Graph.community_multilevel()` now correctly expose + the `resolution` parameter. + +- Fixed a reference leak in `Graph.is_chordal()` that decreased the reference + count of Python's built-in `True` and `False` constants unnecessarily. + +- Unit tests updated to get rid of deprecation warnings in Python 3.11. + ## [0.10.1] - 2022-09-12 ### Added From 10a5fb0f940aff3f716499b2772d592147dc3062 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 19:50:00 +0200 Subject: [PATCH 1120/1892] fix: gotten rid of unsafe casts of pointers-to-enums to pointers-to-ints, refs #594 --- src/_igraph/convert.c | 177 +++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 88 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index a68af33f7..aa4b15096 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -77,7 +77,7 @@ int PyLong_AsInt(PyObject* obj, int* result) { * \param result the result is returned here. The default value must be * passed in before calling this function, since this value is * returned untouched if the given Python object is Py_None. - * \return 0 if everything is OK, 1 otherwise. An appropriate exception + * \return 0 if everything is OK, -1 otherwise. An appropriate exception * is raised in this case. */ int igraphmodule_PyObject_to_enum(PyObject *o, @@ -203,20 +203,34 @@ int igraphmodule_PyObject_to_enum_strict(PyObject *o, return -1; } +#define TRANSLATE_ENUM_WITH(translation_table) \ + int result_int = *result, retval; \ + retval = igraphmodule_PyObject_to_enum(o, translation_table, &result_int); \ + if (retval == 0) { \ + *result = result_int; \ + } \ + return retval; + +#define TRANSLATE_ENUM_STRICTLY_WITH(translation_table) \ + int result_int = *result, retval; \ + retval = igraphmodule_PyObject_to_enum_strict(o, translation_table, &result_int); \ + if (retval == 0) { \ + *result = result_int; \ + } \ + return retval; + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_neimode_t */ -int igraphmodule_PyObject_to_neimode_t(PyObject *o, - igraph_neimode_t *result) { +int igraphmodule_PyObject_to_neimode_t(PyObject *o, igraph_neimode_t *result) { static igraphmodule_enum_translation_table_entry_t neimode_tt[] = { {"in", IGRAPH_IN}, {"out", IGRAPH_OUT}, {"all", IGRAPH_ALL}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, neimode_tt, (int*)result); + TRANSLATE_ENUM_WITH(neimode_tt); } /** @@ -245,7 +259,7 @@ int igraphmodule_PyObject_to_add_weights_t(PyObject *o, return 0; } - return igraphmodule_PyObject_to_enum(o, add_weights_tt, (int*)result); + TRANSLATE_ENUM_WITH(add_weights_tt); } /** @@ -266,8 +280,7 @@ int igraphmodule_PyObject_to_adjacency_t(PyObject *o, {"plus", IGRAPH_ADJ_PLUS}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, adjacency_tt, (int*)result); + TRANSLATE_ENUM_WITH(adjacency_tt); } int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, @@ -299,11 +312,11 @@ int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, return 0; } - return igraphmodule_PyObject_to_enum(o, attribute_combination_type_tt, (int*)result); + TRANSLATE_ENUM_WITH(attribute_combination_type_tt); } -int igraphmodule_PyObject_to_eigen_algorithm_t(PyObject *object, - igraph_eigen_algorithm_t *a) { +int igraphmodule_PyObject_to_eigen_algorithm_t(PyObject *o, + igraph_eigen_algorithm_t *result) { static igraphmodule_enum_translation_table_entry_t eigen_algorithm_tt[] = { {"auto", IGRAPH_EIGEN_AUTO}, @@ -315,19 +328,19 @@ int igraphmodule_PyObject_to_eigen_algorithm_t(PyObject *object, {0,0} }; - if (object == Py_None) { - *a = IGRAPH_EIGEN_ARPACK; + if (o == Py_None) { + *result = IGRAPH_EIGEN_ARPACK; return 0; - } else { - return igraphmodule_PyObject_to_enum(object, eigen_algorithm_tt, - (int*)a); } + + TRANSLATE_ENUM_WITH(eigen_algorithm_tt); } -int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, - igraph_eigen_which_t *w) { +int igraphmodule_PyObject_to_eigen_which_t(PyObject *o, + igraph_eigen_which_t *result) { PyObject *key, *value; Py_ssize_t pos = 0; + igraph_eigen_which_t *w = result; static igraphmodule_enum_translation_table_entry_t eigen_which_position_tt[] = { @@ -361,13 +374,13 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, w->vestimate = 0; w->balance = IGRAPH_LAPACK_DGEEVX_BALANCE_NONE; - if (object != Py_None && !PyDict_Check(object)) { + if (o != Py_None && !PyDict_Check(o)) { PyErr_SetString(PyExc_TypeError, "Python dictionary expected"); return -1; } - if (object != Py_None) { - while (PyDict_Next(object, &pos, &key, &value)) { + if (o != Py_None) { + while (PyDict_Next(o, &pos, &key, &value)) { char *kv; PyObject *temp_bytes; if (!PyUnicode_Check(key)) { @@ -390,8 +403,11 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, } Py_DECREF(temp_bytes); if (!strcasecmp(kv, "pos")) { - igraphmodule_PyObject_to_enum(value, eigen_which_position_tt, - (int*) &w->pos); + int w_pos_int = w->pos; + if (igraphmodule_PyObject_to_enum(value, eigen_which_position_tt, &w_pos_int)) { + return -1; + } + w->pos = w_pos_int; } else if (!strcasecmp(kv, "howmany")) { if (PyLong_AsInt(value, &w->howmany)) { return -1; @@ -413,8 +429,11 @@ int igraphmodule_PyObject_to_eigen_which_t(PyObject *object, return -1; } } else if (!strcasecmp(kv, "balance")) { - igraphmodule_PyObject_to_enum(value, lapack_dgeevc_balance_tt, - (int*) &w->balance); + int w_balance_as_int = w->balance; + if (igraphmodule_PyObject_to_enum(value, lapack_dgeevc_balance_tt, &w_balance_as_int)) { + return -1; + } + w->balance = w_balance_as_int; } else { PyErr_SetString(PyExc_TypeError, "Unknown eigen parameter"); if (kv != 0) { @@ -442,8 +461,7 @@ int igraphmodule_PyObject_to_barabasi_algorithm_t(PyObject *o, {"psumtree_multiple", IGRAPH_BARABASI_PSUMTREE_MULTIPLE}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, barabasi_algorithm_tt, (int*)result); + TRANSLATE_ENUM_WITH(barabasi_algorithm_tt); } /** @@ -457,8 +475,7 @@ int igraphmodule_PyObject_to_connectedness_t(PyObject *o, {"strong", IGRAPH_STRONG}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, connectedness_tt, (int*)result); + TRANSLATE_ENUM_WITH(connectedness_tt); } /** @@ -475,8 +492,7 @@ int igraphmodule_PyObject_to_vconn_nei_t(PyObject *o, {"ignore", IGRAPH_VCONN_NEI_IGNORE}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, vconn_nei_tt, (int*)result); + TRANSLATE_ENUM_WITH(vconn_nei_tt); } /** @@ -494,8 +510,7 @@ int igraphmodule_PyObject_to_bliss_sh_t(PyObject *o, {"fsm", IGRAPH_BLISS_FSM}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, bliss_sh_tt, (int*)result); + TRANSLATE_ENUM_WITH(bliss_sh_tt); } /** @@ -515,8 +530,7 @@ int igraphmodule_PyObject_to_community_comparison_t(PyObject *o, {"adjusted_rand", IGRAPH_COMMCMP_ADJUSTED_RAND}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, commcmp_tt, (int*)result); + TRANSLATE_ENUM_WITH(commcmp_tt); } /** @@ -539,8 +553,7 @@ int igraphmodule_PyObject_to_degseq_t(PyObject *o, {"edge_switching_simple", IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, degseq_tt, (int*)result); + TRANSLATE_ENUM_WITH(degseq_tt); } /** @@ -557,8 +570,7 @@ int igraphmodule_PyObject_to_fas_algorithm_t(PyObject *o, {"ip", IGRAPH_FAS_EXACT_IP}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, fas_algorithm_tt, (int*)result); + TRANSLATE_ENUM_WITH(fas_algorithm_tt); } /** @@ -573,8 +585,7 @@ int igraphmodule_PyObject_to_get_adjacency_t(PyObject *o, {"both", IGRAPH_GET_ADJACENCY_BOTH}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, get_adjacency_tt, (int*)result); + TRANSLATE_ENUM_WITH(get_adjacency_tt); } /** @@ -594,12 +605,14 @@ int igraphmodule_PyObject_to_laplacian_normalization_t( if (o == Py_True) { *result = IGRAPH_LAPLACIAN_SYMMETRIC; return 0; - } else if (o == Py_False) { + } + + if (o == Py_False) { *result = IGRAPH_LAPLACIAN_UNNORMALIZED; return 0; - } else { - return igraphmodule_PyObject_to_enum(o, laplacian_normalization_tt, (int*)result); } + + TRANSLATE_ENUM_WITH(laplacian_normalization_tt); } /** @@ -616,12 +629,14 @@ int igraphmodule_PyObject_to_layout_grid_t(PyObject *o, igraph_layout_grid_t *re if (o == Py_True) { *result = IGRAPH_LAYOUT_GRID; return 0; - } else if (o == Py_False) { + } + + if (o == Py_False) { *result = IGRAPH_LAYOUT_NOGRID; return 0; - } else { - return igraphmodule_PyObject_to_enum(o, layout_grid_tt, (int*)result); } + + TRANSLATE_ENUM_WITH(layout_grid_tt); } /** @@ -638,12 +653,14 @@ int igraphmodule_PyObject_to_loops_t(PyObject *o, igraph_loops_t *result) { if (o == Py_True) { *result = IGRAPH_LOOPS_TWICE; return 0; - } else if (o == Py_False) { + } + + if (o == Py_False) { *result = IGRAPH_NO_LOOPS; return 0; - } else { - return igraphmodule_PyObject_to_enum(o, loops_tt, (int*)result); } + + TRANSLATE_ENUM_WITH(loops_tt); } /** @@ -657,8 +674,7 @@ int igraphmodule_PyObject_to_random_walk_stuck_t(PyObject *o, {"error", IGRAPH_RANDOM_WALK_STUCK_ERROR}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, random_walk_stuck_tt, (int*)result); + TRANSLATE_ENUM_WITH(random_walk_stuck_tt); } /** @@ -670,8 +686,7 @@ int igraphmodule_PyObject_to_reciprocity_t(PyObject *o, igraph_reciprocity_t *re {"ratio", IGRAPH_RECIPROCITY_RATIO}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, reciprocity_tt, (int*)result); + TRANSLATE_ENUM_WITH(reciprocity_tt); } /** @@ -684,8 +699,7 @@ int igraphmodule_PyObject_to_rewiring_t(PyObject *o, igraph_rewiring_t *result) {"loops", IGRAPH_REWIRING_SIMPLE_LOOPS}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, rewiring_tt, (int*)result); + TRANSLATE_ENUM_WITH(rewiring_tt); } /** @@ -697,8 +711,7 @@ int igraphmodule_PyObject_to_spinglass_implementation_t(PyObject *o, igraph_spin {"negative", IGRAPH_SPINCOMM_IMP_NEG}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, spinglass_implementation_tt, (int*)result); + TRANSLATE_ENUM_WITH(spinglass_implementation_tt); } /** @@ -710,8 +723,7 @@ int igraphmodule_PyObject_to_spincomm_update_t(PyObject *o, igraph_spincomm_upda {"config", IGRAPH_SPINCOMM_UPDATE_CONFIG}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, spincomm_update_tt, (int*)result); + TRANSLATE_ENUM_WITH(spincomm_update_tt); } /** @@ -727,8 +739,7 @@ int igraphmodule_PyObject_to_star_mode_t(PyObject *o, {"undirected", IGRAPH_STAR_UNDIRECTED}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, star_mode_tt, (int*)result); + TRANSLATE_ENUM_WITH(star_mode_tt); } /** @@ -745,8 +756,7 @@ int igraphmodule_PyObject_to_subgraph_implementation_t(PyObject *o, {"new", IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, subgraph_impl_tt, (int*)result); + TRANSLATE_ENUM_WITH(subgraph_impl_tt); } /** @@ -766,12 +776,14 @@ int igraphmodule_PyObject_to_to_directed_t(PyObject *o, if (o == Py_True) { *result = IGRAPH_TO_DIRECTED_MUTUAL; return 0; - } else if (o == Py_False) { + } + + if (o == Py_False) { *result = IGRAPH_TO_DIRECTED_ARBITRARY; return 0; } - return igraphmodule_PyObject_to_enum(o, to_directed_tt, (int*)result); + TRANSLATE_ENUM_WITH(to_directed_tt); } /** @@ -790,12 +802,14 @@ int igraphmodule_PyObject_to_to_undirected_t(PyObject *o, if (o == Py_True) { *result = IGRAPH_TO_UNDIRECTED_COLLAPSE; return 0; - } else if (o == Py_False) { + } + + if (o == Py_False) { *result = IGRAPH_TO_UNDIRECTED_EACH; return 0; } - return igraphmodule_PyObject_to_enum(o, to_undirected_tt, (int*)result); + TRANSLATE_ENUM_WITH(to_undirected_tt); } /** @@ -811,7 +825,7 @@ int igraphmodule_PyObject_to_transitivity_mode_t(PyObject *o, {0,0} }; - return igraphmodule_PyObject_to_enum(o, transitivity_mode_tt, (int*)result); + TRANSLATE_ENUM_WITH(transitivity_mode_tt); } /** @@ -831,7 +845,7 @@ int igraphmodule_PyObject_to_tree_mode_t(PyObject *o, {0,0} }; - return igraphmodule_PyObject_to_enum(o, tree_mode_tt, (int*)result); + TRANSLATE_ENUM_WITH(tree_mode_tt); } /** @@ -1373,7 +1387,7 @@ PyObject* igraphmodule_integer_t_to_PyObject(igraph_integer_t value) { * error occurred */ PyObject* igraphmodule_real_t_to_PyObject(igraph_real_t value, igraphmodule_conv_t type) { - if (!igraph_finite(value) || igraph_is_nan(value)) { + if (!isfinite(value) || isnan(value)) { return PyFloat_FromDouble(value); } @@ -3852,8 +3866,7 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t {"arpack", IGRAPH_PAGERANK_ALGO_ARPACK}, {0,0} }; - - return igraphmodule_PyObject_to_enum(o, pagerank_algo_tt, (int*)result); + TRANSLATE_ENUM_WITH(pagerank_algo_tt); } /** @@ -3861,8 +3874,6 @@ int igraphmodule_PyObject_to_pagerank_algo_t(PyObject *o, igraph_pagerank_algo_t * \brief Converts a Python object to an igraph \c igraph_edge_type_sw_t */ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t *result) { - int result_int = *result; - int retval; static igraphmodule_enum_translation_table_entry_t edge_type_sw_tt[] = { {"simple", IGRAPH_SIMPLE_SW}, {"loops", IGRAPH_LOOPS_SW}, @@ -3870,15 +3881,7 @@ int igraphmodule_PyObject_to_edge_type_sw_t(PyObject *o, igraph_edge_type_sw_t * {"all", IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW}, {0,0} }; - - retval = igraphmodule_PyObject_to_enum_strict(o, edge_type_sw_tt, &result_int); - - if (retval) { - return retval; - } - - *result = result_int; - return 0; + TRANSLATE_ENUM_STRICTLY_WITH(edge_type_sw_tt); } /** @@ -3892,8 +3895,7 @@ int igraphmodule_PyObject_to_realize_degseq_t(PyObject *o, igraph_realize_degseq {"index", IGRAPH_REALIZE_DEGSEQ_INDEX}, {0,0} }; - - return igraphmodule_PyObject_to_enum_strict(o, realize_degseq_tt, (int*)result); + TRANSLATE_ENUM_STRICTLY_WITH(realize_degseq_tt); } /** @@ -3906,6 +3908,5 @@ int igraphmodule_PyObject_to_random_tree_t(PyObject *o, igraph_random_tree_t *re {"lerw", IGRAPH_RANDOM_TREE_LERW}, {0,0} }; - - return igraphmodule_PyObject_to_enum_strict(o, random_tree_tt, (int*)result); + TRANSLATE_ENUM_STRICTLY_WITH(random_tree_tt); } From 648a2bb5710f4fe515172d3494b42b5985136168 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Oct 2022 22:27:39 +0200 Subject: [PATCH 1121/1892] fix: fix a null pointer dereference in igraphmodule_i_Graph_isomorphic_vf2_callback_fn() --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index afc97ae1f..446c0b2b3 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -9326,7 +9326,7 @@ igraph_error_t igraphmodule_i_Graph_isomorphic_vf2_callback_fn( if (map21_o == NULL) { /* Error in conversion, return an error code */ PyErr_WriteUnraisable(data->callback_fn); - Py_DECREF(map21_o); + Py_DECREF(map12_o); return IGRAPH_FAILURE; } From cbdc10df4a0f759d65015e570ae823fad0c70b55 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 16 Oct 2022 12:00:56 +1100 Subject: [PATCH 1122/1892] Move documentation examples to sphinx-gallery (#593) * Try out sphinx-gallery, work-ish locally * RTD + sphinx-gallery needs scipy for one example * Start polishing examples * Improve more examples * More examples polished * Annotated all examples * Remove old gallery system * Vertex size in one example * Vertex size in one example, again * Vertex size in one example, again (3x) * Close small leftover bugs here and there --- .gitignore | 2 + doc/examples_sphinx-gallery/README.rst | 10 + .../articulation_points.py | 38 + .../betweenness.py | 48 +- .../bipartite_matching.py | 33 +- .../bipartite_matching_maxflow.py | 67 + doc/examples_sphinx-gallery/bridges.py | 81 + .../cluster_contraction.py | 141 ++ doc/examples_sphinx-gallery/complement.py | 75 + doc/examples_sphinx-gallery/configuration.py | 60 + .../connected_components.py | 44 + .../delaunay-triangulation.py | 98 + doc/examples_sphinx-gallery/erdos_renyi.py | 86 + .../isomorphism.py | 25 +- doc/examples_sphinx-gallery/lesmis/lesmis.gml | 1913 +++++++++++++++++ doc/examples_sphinx-gallery/lesmis/lesmis.txt | 7 + .../maxflow.py | 28 +- .../minimum_spanning_trees.py | 53 + .../online_user_actions.py | 104 + .../quickstart.py | 17 + doc/examples_sphinx-gallery/ring_animation.py | 89 + .../shortest_path_visualisation.py | 79 + doc/examples_sphinx-gallery/simplify.py | 71 + doc/examples_sphinx-gallery/spanning_trees.py | 57 + .../topological_sort.py | 59 + doc/examples_sphinx-gallery/visual_style.py | 49 + .../visualize_cliques.py | 66 + .../visualize_communities.py | 29 +- .../gallery_thumbnails}/ring_animation.gif | Bin .../gallery_thumbnails}/ring_animation.png | Bin doc/source/conf.py | 15 +- doc/source/faq.rst | 4 +- doc/source/index.rst | 6 +- doc/source/requirements.txt | 2 + doc/source/sphinxext/gallery_generator.py | 281 --- doc/source/tutorial.rst | 4 +- .../articulation_points.rst | 48 - .../assets/articulation_points.py | 24 - .../figures/articulation_points.png | Bin 22137 -> 0 bytes .../tutorials/betweenness/betweenness.rst | 100 - .../betweenness/figures/betweenness.png | Bin 114355 -> 0 bytes .../bipartite_matching/bipartite_matching.rst | 74 - .../bipartite_matching/figures/bipartite.png | Bin 21719 -> 0 bytes .../figures/bipartite_matching.png | Bin 13959 -> 0 bytes .../assets/bipartite_matching_maxflow.py | 45 - .../bipartite_matching_maxflow.rst | 85 - .../figures/bipartite_matching_maxflow.png | Bin 18396 -> 0 bytes .../tutorials/bridges/assets/bridges1.py | 25 - .../tutorials/bridges/assets/bridges2.py | 32 - doc/source/tutorials/bridges/bridges.rst | 84 - .../tutorials/bridges/figures/bridge1.png | Bin 31005 -> 0 bytes .../tutorials/bridges/figures/bridge2.png | Bin 31782 -> 0 bytes .../assets/cluster_contraction.py | 94 - .../tutorials/cluster_graph/assets/lesmis.zip | Bin 2517 -> 0 bytes .../tutorials/cluster_graph/cluster_graph.rst | 236 -- .../cluster_graph/figures/cluster_graph.png | Bin 101457 -> 0 bytes .../cluster_graph/figures/communities.png | Bin 1623454 -> 0 bytes .../tutorials/complement/assets/complement.py | 50 - .../tutorials/complement/complement.rst | 83 - .../complement/figures/complement.png | Bin 85235 -> 0 bytes .../configuration/assets/configuration1.py | 11 - .../configuration/assets/configuration2.py | 15 - .../tutorials/configuration/configuration.rst | 62 - .../configuration/figures/configuration.png | Bin 44598 -> 0 bytes .../assets/connected_components.py | 23 - .../connected_components.rst | 47 - .../figures/connected_components.png | Bin 42512 -> 0 bytes .../assets/delaunay-triangulation.py | 34 - .../assets/delaunay-triangulation2.py | 48 - .../delaunay-triangulation.rst | 104 - .../figures/delaunay-triangulation.png | Bin 56427 -> 0 bytes .../figures/delaunay-triangulation2.png | Bin 41620 -> 0 bytes .../erdos_renyi/assets/erdos_renyi.py | 59 - .../tutorials/erdos_renyi/erdos_renyi.rst | 89 - .../erdos_renyi/figures/erdos_renyi.png | Bin 91293 -> 0 bytes .../isomorphism/figures/isomorphism.png | Bin 33861 -> 0 bytes .../tutorials/isomorphism/isomorphism.rst | 89 - .../tutorials/maxflow/figures/maxflow.png | Bin 17642 -> 0 bytes doc/source/tutorials/maxflow/maxflow.rst | 41 - .../assets/minimum_spanning_trees.py | 34 - .../figures/minimum_spanning_trees.png | Bin 21579 -> 0 bytes .../minimum_spanning_trees.rst | 71 - .../assets/online_user_actions.py | 63 - .../figures/online_user_actions.png | Bin 31455 -> 0 bytes .../figures/online_users_simple.png | Bin 47195 -> 0 bytes .../online_user_actions.rst | 113 - .../quickstart/figures/quickstart.png | Bin 16277 -> 0 bytes .../quickstart/figures/social_network.png | Bin 65370 -> 0 bytes .../tutorials/quickstart/quickstart.rst | 73 - .../ring_animation/assets/ring_animation.py | 32 - .../ring_animation/ring_animation.rst | 58 - .../assets/shortest_path_visualisation.py | 33 - .../shortest_paths/assets/shortest_paths.py | 34 - .../shortest_paths/figures/shortest_paths.png | Bin 29787 -> 0 bytes .../shortest_paths/shortest_paths.rst | 117 - .../tutorials/simplify/assets/simplify.py | 44 - .../tutorials/simplify/figures/simplify.png | Bin 39750 -> 0 bytes doc/source/tutorials/simplify/simplify.rst | 86 - .../spanning_trees/assets/spanning_trees.py | 37 - .../spanning_trees/figures/spanning_trees.png | Bin 21739 -> 0 bytes .../spanning_trees/spanning_trees.rst | 68 - .../assets/topological_sort.py | 35 - .../figures/topological_sort.png | Bin 27783 -> 0 bytes .../topological_sort/topological_sort.rst | 94 - .../visual_style/assets/visual_style.py | 26 - .../visual_style/figures/visual_style.png | Bin 47738 -> 0 bytes .../tutorials/visual_style/visual_style.rst | 50 - .../assets/visualize_cliques.py | 21 - .../assets/visualize_cliques_with_edges.py | 30 - .../visualize_cliques/figures/cliques.png | Bin 99882 -> 0 bytes .../figures/cliques_with_edges.png | Bin 106100 -> 0 bytes .../figures/visualize_cliques.png | Bin 61106 -> 0 bytes .../figures/visualize_cliques_with_edges.png | Bin 66521 -> 0 bytes .../visualize_cliques/visualize_cliques.rst | 87 - .../figures/visualize_communities.png | Bin 37030 -> 0 bytes .../visualize_communities.rst | 85 - doc/source/visualisation.rst | 3 +- scripts/mkdoc.sh | 2 +- scripts/patch_modularized_graph_methods.py | 23 +- src/_igraph/graphobject.c | 6 +- src/igraph/__init__.py | 4 +- 121 files changed, 3439 insertions(+), 3233 deletions(-) create mode 100644 doc/examples_sphinx-gallery/README.rst create mode 100644 doc/examples_sphinx-gallery/articulation_points.py rename doc/{source/tutorials/betweenness/assets => examples_sphinx-gallery}/betweenness.py (52%) rename doc/{source/tutorials/bipartite_matching/assets => examples_sphinx-gallery}/bipartite_matching.py (55%) create mode 100644 doc/examples_sphinx-gallery/bipartite_matching_maxflow.py create mode 100644 doc/examples_sphinx-gallery/bridges.py create mode 100644 doc/examples_sphinx-gallery/cluster_contraction.py create mode 100644 doc/examples_sphinx-gallery/complement.py create mode 100644 doc/examples_sphinx-gallery/configuration.py create mode 100644 doc/examples_sphinx-gallery/connected_components.py create mode 100644 doc/examples_sphinx-gallery/delaunay-triangulation.py create mode 100644 doc/examples_sphinx-gallery/erdos_renyi.py rename doc/{source/tutorials/isomorphism/assets => examples_sphinx-gallery}/isomorphism.py (66%) create mode 100644 doc/examples_sphinx-gallery/lesmis/lesmis.gml create mode 100644 doc/examples_sphinx-gallery/lesmis/lesmis.txt rename doc/{source/tutorials/maxflow/assets => examples_sphinx-gallery}/maxflow.py (54%) create mode 100644 doc/examples_sphinx-gallery/minimum_spanning_trees.py create mode 100644 doc/examples_sphinx-gallery/online_user_actions.py rename doc/{source/tutorials/quickstart/assets => examples_sphinx-gallery}/quickstart.py (78%) create mode 100644 doc/examples_sphinx-gallery/ring_animation.py create mode 100644 doc/examples_sphinx-gallery/shortest_path_visualisation.py create mode 100644 doc/examples_sphinx-gallery/simplify.py create mode 100644 doc/examples_sphinx-gallery/spanning_trees.py create mode 100644 doc/examples_sphinx-gallery/topological_sort.py create mode 100644 doc/examples_sphinx-gallery/visual_style.py create mode 100644 doc/examples_sphinx-gallery/visualize_cliques.py rename doc/{source/tutorials/visualize_communities/assets => examples_sphinx-gallery}/visualize_communities.py (53%) rename doc/source/{tutorials/ring_animation/figures => _static/gallery_thumbnails}/ring_animation.gif (100%) rename doc/source/{tutorials/ring_animation/figures => _static/gallery_thumbnails}/ring_animation.png (100%) delete mode 100644 doc/source/sphinxext/gallery_generator.py delete mode 100644 doc/source/tutorials/articulation_points/articulation_points.rst delete mode 100644 doc/source/tutorials/articulation_points/assets/articulation_points.py delete mode 100644 doc/source/tutorials/articulation_points/figures/articulation_points.png delete mode 100644 doc/source/tutorials/betweenness/betweenness.rst delete mode 100644 doc/source/tutorials/betweenness/figures/betweenness.png delete mode 100644 doc/source/tutorials/bipartite_matching/bipartite_matching.rst delete mode 100644 doc/source/tutorials/bipartite_matching/figures/bipartite.png delete mode 100644 doc/source/tutorials/bipartite_matching/figures/bipartite_matching.png delete mode 100644 doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py delete mode 100644 doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst delete mode 100644 doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png delete mode 100644 doc/source/tutorials/bridges/assets/bridges1.py delete mode 100644 doc/source/tutorials/bridges/assets/bridges2.py delete mode 100644 doc/source/tutorials/bridges/bridges.rst delete mode 100644 doc/source/tutorials/bridges/figures/bridge1.png delete mode 100644 doc/source/tutorials/bridges/figures/bridge2.png delete mode 100644 doc/source/tutorials/cluster_graph/assets/cluster_contraction.py delete mode 100644 doc/source/tutorials/cluster_graph/assets/lesmis.zip delete mode 100644 doc/source/tutorials/cluster_graph/cluster_graph.rst delete mode 100644 doc/source/tutorials/cluster_graph/figures/cluster_graph.png delete mode 100644 doc/source/tutorials/cluster_graph/figures/communities.png delete mode 100644 doc/source/tutorials/complement/assets/complement.py delete mode 100644 doc/source/tutorials/complement/complement.rst delete mode 100644 doc/source/tutorials/complement/figures/complement.png delete mode 100644 doc/source/tutorials/configuration/assets/configuration1.py delete mode 100644 doc/source/tutorials/configuration/assets/configuration2.py delete mode 100644 doc/source/tutorials/configuration/configuration.rst delete mode 100644 doc/source/tutorials/configuration/figures/configuration.png delete mode 100644 doc/source/tutorials/connected_components/assets/connected_components.py delete mode 100644 doc/source/tutorials/connected_components/connected_components.rst delete mode 100644 doc/source/tutorials/connected_components/figures/connected_components.png delete mode 100644 doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py delete mode 100644 doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py delete mode 100644 doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst delete mode 100644 doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png delete mode 100644 doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png delete mode 100644 doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py delete mode 100644 doc/source/tutorials/erdos_renyi/erdos_renyi.rst delete mode 100644 doc/source/tutorials/erdos_renyi/figures/erdos_renyi.png delete mode 100644 doc/source/tutorials/isomorphism/figures/isomorphism.png delete mode 100644 doc/source/tutorials/isomorphism/isomorphism.rst delete mode 100644 doc/source/tutorials/maxflow/figures/maxflow.png delete mode 100644 doc/source/tutorials/maxflow/maxflow.rst delete mode 100644 doc/source/tutorials/minimum_spanning_trees/assets/minimum_spanning_trees.py delete mode 100644 doc/source/tutorials/minimum_spanning_trees/figures/minimum_spanning_trees.png delete mode 100644 doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst delete mode 100644 doc/source/tutorials/online_user_actions/assets/online_user_actions.py delete mode 100644 doc/source/tutorials/online_user_actions/figures/online_user_actions.png delete mode 100644 doc/source/tutorials/online_user_actions/figures/online_users_simple.png delete mode 100644 doc/source/tutorials/online_user_actions/online_user_actions.rst delete mode 100644 doc/source/tutorials/quickstart/figures/quickstart.png delete mode 100644 doc/source/tutorials/quickstart/figures/social_network.png delete mode 100644 doc/source/tutorials/quickstart/quickstart.rst delete mode 100644 doc/source/tutorials/ring_animation/assets/ring_animation.py delete mode 100644 doc/source/tutorials/ring_animation/ring_animation.rst delete mode 100644 doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py delete mode 100644 doc/source/tutorials/shortest_paths/assets/shortest_paths.py delete mode 100644 doc/source/tutorials/shortest_paths/figures/shortest_paths.png delete mode 100644 doc/source/tutorials/shortest_paths/shortest_paths.rst delete mode 100644 doc/source/tutorials/simplify/assets/simplify.py delete mode 100644 doc/source/tutorials/simplify/figures/simplify.png delete mode 100644 doc/source/tutorials/simplify/simplify.rst delete mode 100644 doc/source/tutorials/spanning_trees/assets/spanning_trees.py delete mode 100644 doc/source/tutorials/spanning_trees/figures/spanning_trees.png delete mode 100644 doc/source/tutorials/spanning_trees/spanning_trees.rst delete mode 100644 doc/source/tutorials/topological_sort/assets/topological_sort.py delete mode 100644 doc/source/tutorials/topological_sort/figures/topological_sort.png delete mode 100644 doc/source/tutorials/topological_sort/topological_sort.rst delete mode 100644 doc/source/tutorials/visual_style/assets/visual_style.py delete mode 100644 doc/source/tutorials/visual_style/figures/visual_style.png delete mode 100644 doc/source/tutorials/visual_style/visual_style.rst delete mode 100644 doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py delete mode 100644 doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py delete mode 100644 doc/source/tutorials/visualize_cliques/figures/cliques.png delete mode 100644 doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png delete mode 100644 doc/source/tutorials/visualize_cliques/figures/visualize_cliques.png delete mode 100644 doc/source/tutorials/visualize_cliques/figures/visualize_cliques_with_edges.png delete mode 100644 doc/source/tutorials/visualize_cliques/visualize_cliques.rst delete mode 100644 doc/source/tutorials/visualize_communities/figures/visualize_communities.png delete mode 100644 doc/source/tutorials/visualize_communities/visualize_communities.rst diff --git a/.gitignore b/.gitignore index f0a852ea0..46689eff9 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,10 @@ vendor/install/ .DS_Store doc/source/gallery.rst +doc/source/tutorials doc/linkcheck doc/api/ doc/dash/ doc/html/ doc/jekyll_tools/vendor +doc/examples_sphinx-gallery/social_network.* diff --git a/doc/examples_sphinx-gallery/README.rst b/doc/examples_sphinx-gallery/README.rst new file mode 100644 index 000000000..6fe17a0c1 --- /dev/null +++ b/doc/examples_sphinx-gallery/README.rst @@ -0,0 +1,10 @@ +.. _gallery-of-examples: + +Gallery of Examples +=================== + +Gallery of examples for `python-igraph` illustrating graph generation, analysis, and plotting. + +Impatient? Check out the :ref:`tutorials-quickstart`. + +Too little detail? Read the :doc:`extended tutorial <../tutorial>`. diff --git a/doc/examples_sphinx-gallery/articulation_points.py b/doc/examples_sphinx-gallery/articulation_points.py new file mode 100644 index 000000000..2b92b3704 --- /dev/null +++ b/doc/examples_sphinx-gallery/articulation_points.py @@ -0,0 +1,38 @@ +""" +.. _tutorials-articulation-points: + +=================== +Articulation Points +=================== + +This example shows how to compute and visualize the `articulation points `_ in a graph using :meth:`igraph.GraphBase.articulation_points`. For an example on bridges instead, see :ref:`tutorials-bridges`. + +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# First, we construct a graph. This example shows usage of graph formulae: +g = ig.Graph.Formula( + "0-1-2-0, 3:4:5:6 - 3:4:5:6, 2-3-7-8", +) + +# %% +# Now we are aready to find the articulation points as a vertex sequence +articulation_points = g.vs[g.articulation_points()] + +# %% +# Finally, we can plot the graph +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + vertex_size=0.3, + vertex_color="lightblue", + vertex_label=range(g.vcount()), + vertex_frame_color = ["red" if v in articulation_points else "black" for v in g.vs], + vertex_frame_width = [3 if v in articulation_points else 1 for v in g.vs], + edge_width=0.8, + edge_color='gray' +) +plt.show() diff --git a/doc/source/tutorials/betweenness/assets/betweenness.py b/doc/examples_sphinx-gallery/betweenness.py similarity index 52% rename from doc/source/tutorials/betweenness/assets/betweenness.py rename to doc/examples_sphinx-gallery/betweenness.py index fc2cd8c99..a9e568e70 100644 --- a/doc/source/tutorials/betweenness/assets/betweenness.py +++ b/doc/examples_sphinx-gallery/betweenness.py @@ -1,3 +1,13 @@ +""" +.. _tutorials-betweenness: + +======================= +Betweenness +======================= + +This example demonstrates how to visualize both vertex and edge betweenness with a custom defined color palette. We use the methods :meth:`igraph.GraphBase.betweenness` and :meth:`igraph.GraphBase.edge_betweenness` respectively, and demonstrate the effects on a standard `Krackhardt Kite `_ graph, as well as a `Watts-Strogatz `_ random graph. + +""" import random import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable @@ -5,7 +15,15 @@ import igraph as ig -def plot_betweenness(g, ax, cax1, cax2): +# %% +# We define a function that plots the graph on a Matplotlib axis, along with +# its vertex and edge betweenness values. The function also generates some +# color bars on the sides to see how they translate to each other. We use +# `Matplotlib's Normalize class `_ +# to ensure that our color bar ranges are correct, as well as *igraph*'s +# :meth:`igraph.utils.rescale` to rescale the betweennesses in the interval +# ``[0, 1]``. +def plot_betweenness(g, vertex_betweenness, edge_betweenness, ax, cax1, cax2): '''Plot vertex/edge betweenness, with colorbars Args: @@ -15,9 +33,7 @@ def plot_betweenness(g, ax, cax1, cax2): cax2: the Axes for the edge betweenness colorbar ''' - # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = g.betweenness() - edge_betweenness = g.edge_betweenness() + # Rescale betweenness to be between 0.0 and 1.0 scaled_vertex_betweenness = ig.rescale(vertex_betweenness, clamp=True) scaled_edge_betweenness = ig.rescale(edge_betweenness, clamp=True) print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") @@ -46,20 +62,30 @@ def plot_betweenness(g, ax, cax1, cax2): plt.colorbar(norm2, cax=cax2, orientation="horizontal", label='Edge Betweenness') -# Generate Krackhardt Kite Graphs and Watts Strogatz graphs +# %% +# First, generate a graph, e.g. the Krackhardt Kite Graph: random.seed(0) g1 = ig.Graph.Famous("Krackhardt_Kite") + +# %% +# Then we can compute vertex and edge betweenness: +vertex_betweenness1 = g1.betweenness() +edge_betweenness1 = g1.edge_betweenness() + +# %% As a second example, we generate and analyze a Watts Strogatz graph: g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) +vertex_betweenness2 = g2.betweenness() +edge_betweenness2 = g2.edge_betweenness() -# Plot the graphs, each with two colorbars for vertex/edge betweenness +# %% +# Finally, we plot the two graphs, each with two colorbars for vertex/edge +# betweenness fig, axs = plt.subplots( 3, 2, figsize=(7, 6), gridspec_kw=dict(height_ratios=(20, 1, 1)), - ) -#plt.subplots_adjust(bottom=0.3) -plot_betweenness(g1, *axs[:, 0]) -plot_betweenness(g2, *axs[:, 1]) +) +plot_betweenness(g1, vertex_betweenness1, edge_betweenness1, *axs[:, 0]) +plot_betweenness(g2, vertex_betweenness2, edge_betweenness2, *axs[:, 1]) fig.tight_layout(h_pad=1) - plt.show() diff --git a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py b/doc/examples_sphinx-gallery/bipartite_matching.py similarity index 55% rename from doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py rename to doc/examples_sphinx-gallery/bipartite_matching.py index fdb400eae..dd7885b07 100644 --- a/doc/source/tutorials/bipartite_matching/assets/bipartite_matching.py +++ b/doc/examples_sphinx-gallery/bipartite_matching.py @@ -1,16 +1,34 @@ +""" +.. _tutorials-bipartite-matching: + +========================== +Maximum Bipartite Matching +========================== + +This example demonstrates an efficient way to find and visualise a maximum biparite matching using :meth:`igraph.Graph.maximum_bipartite_matching`. +""" import igraph as ig import matplotlib.pyplot as plt -# Assign nodes 0-4 to one side, and the nodes 5-8 to the other side +# %% +# First, we construct a bipartite graph, assigning: +# - nodes 0-4 to one side +# - nodes 5-8 to the other side g = ig.Graph.Bipartite( [0, 0, 0, 0, 0, 1, 1, 1, 1], [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] ) + +# %% +# We can easily check that the graph is indeed bipartite: assert g.is_bipartite() +# %% +# Now can can compute the maximum bipartite matching: matching = g.maximum_bipartite_matching() -# Print pairings for each node on one side +# %% +# It's easy to print matching pairs of vertices matching_size = 0 print("Matching is:") for i in range(5): @@ -19,6 +37,9 @@ matching_size += 1 print("Size of maximum matching is:", matching_size) +# %% +# Finally, we can plot the bipartite graph, highlighting the edges connecting +# maximal matches by a red color: fig, ax = plt.subplots(figsize=(7, 3)) ig.plot( g, @@ -30,11 +51,3 @@ edge_width=[3 if e.target == matching.match_of(e.source) else 1.0 for e in g.es], edge_color=["red" if e.target == matching.match_of(e.source) else "black" for e in g.es] ) - -# Matching is: -# 0 - 5 -# 1 - 7 -# 2 - 8 -# 3 - 6 -# 4 - None -# Size of maximum matching is: 4 diff --git a/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py b/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py new file mode 100644 index 000000000..6164e0e47 --- /dev/null +++ b/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py @@ -0,0 +1,67 @@ +""" +.. _tutorials-bipartite-matching-maxflow: + +========================================== +Maximum Bipartite Matching by Maximum Flow +========================================== + +This example presents how to visualise bipartite matching using maximum flow (see :meth:`igraph.Graph.maxflow`). + +.. note:: :meth:`igraph.Graph.maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out :ref:`tutorials-bipartite-matching`. +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# We start by creating the bipartite directed graph. +g = ig.Graph( + 9, + [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], + directed=True +) + +# %% +# We assign: +# - nodes 0-3 to one side +# - nodes 4-8 to the other side +g.vs[range(4)]["type"] = True +g.vs[range(4, 9)]["type"] = False + +# %% +# Then we add a source (vertex 9) and a sink (vertex 10) +g.add_vertices(2) +g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side +g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other + +flow = g.maxflow(9, 10) +print("Size of maximum matching (maxflow) is:", flow.value) + +# %% +# Let's compare the output against :meth:`igraph.Graph.maximum_bipartite_matching`: + +# delete the source and sink, which are unneeded for this function. +g2 = g.copy() +g2.delete_vertices([9, 10]) +matching = g2.maximum_bipartite_matching() +matching_size = sum(1 for i in range(4) if matching.is_matched(i)) +print("Size of maximum matching (maximum_bipartite_matching) is:", matching_size) + +# %% +# Last, we can display the original flow graph nicely with the matchings added. +# To achieve a pleasant visual effect, we set the positions of source and sink +# manually: +layout = g.layout_bipartite() +layout[9] = (2, -1) +layout[10] = (2, 2) + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_size=0.4, + vertex_label=range(g.vcount()), + vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], + edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] +) +plt.show() diff --git a/doc/examples_sphinx-gallery/bridges.py b/doc/examples_sphinx-gallery/bridges.py new file mode 100644 index 000000000..ba821e88b --- /dev/null +++ b/doc/examples_sphinx-gallery/bridges.py @@ -0,0 +1,81 @@ +""" +.. _tutorials-bridges: + +======== +Bridges +======== + +This example shows how to compute and visualize the `bridges `_ in a graph using :meth:`igraph.GraphBase.bridges`. For an example on articulation points instead, see :ref:`tutorials-articulation-points`. +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# Let's start with a simple example. We begin by constructing a graph that +# includes a few bridges: +g = ig.Graph(14, [(0, 1), (1, 2), (2, 3), (0, 3), (0, 2), (1, 3), (3, 4), + (4, 5), (5, 6), (6, 4), (6, 7), (7, 8), (7, 9), (9, 10), (10 ,11), + (11 ,7), (7, 10), (8, 9), (8, 10), (5, 12), (12, 13)]) + +# %% +# Then we can use a function to actually find the bridges, i.e. the edges that +# connect different parts of the graph: +bridges = g.bridges() + +# %% +# We set a separate color for those edges, to emphasize then in a plot: +g.es["color"] = "gray" +g.es[bridges]["color"] = "red" +g.es["width"] = 0.8 +g.es[bridges]["width"] = 1.2 + +# %% +# Finally, we plot the graph using that emphasis: +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + vertex_size=0.3, + vertex_color="lightblue", + vertex_label=range(g.vcount()) +) +plt.show() + +# %% +# Advanced: Cutting Effect +# -------------------------- +# Bridges are edges that when removed, will separate the graph into more components then they started with. To emphasise the removal of edges from the graph, we can add small "x" effect to each of the bridges by using edge labels. + +# %% +# As before, we begin by constructing the graph: +g = ig.Graph(14, [(0, 1), (1, 2), (2, 3), (0, 3), (0, 2), (1, 3), (3, 4), + (4, 5), (5, 6), (6, 4), (6, 7), (7, 8), (7, 9), (9, 10), (10 ,11), + (11 ,7), (7, 10), (8, 9), (8, 10), (5, 12), (12, 13)]) + +# %% +# We then find and set the color for the bridges, but this time we also set a +# label for those edges: +bridges = g.bridges() +g.es["color"] = "gray" +g.es[bridges]["color"] = "red" +g.es["width"] = 0.8 +g.es[bridges]["width"] = 1.2 +g.es["label"] = "" +g.es[bridges]["label"] = "x" + +# %% +# Finally, we can plot the graph: +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + vertex_size=0.3, + vertex_color="lightblue", + vertex_label=range(g.vcount()), + edge_background="#FFF0", # transparent background color + edge_align_label=True, # make sure labels are aligned with the edge + edge_label=g.es["label"], + edge_label_color="red" +) +plt.show() + diff --git a/doc/examples_sphinx-gallery/cluster_contraction.py b/doc/examples_sphinx-gallery/cluster_contraction.py new file mode 100644 index 000000000..f39e71d5d --- /dev/null +++ b/doc/examples_sphinx-gallery/cluster_contraction.py @@ -0,0 +1,141 @@ +""" +.. _tutorials-cluster-graph: + +=========================== +Generating Cluster Graphs +=========================== + +This example shows how to find the communities in a graph, then contract each community into a single node using :class:`igraph.clustering.VertexClustering`. For this tutorial, we'll use the *Donald Knuth's Les Miserables Network*, which shows the coapperances of characters in the novel *Les Miserables*. +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# We begin by load the graph from file. The file containing this network can be +# downloaded `here `_. +g = ig.load("./lesmis/lesmis.gml") + +# %% +# Now that we have a graph in memory, we can generate communities using +# :meth:`igraph.Graph.community_edge_betweenness` to separate out vertices into +# clusters. (For a more focused tutorial on just visualising communities, check +# out :ref:`tutorials-visualize-communities`). +communities = g.community_edge_betweenness() + +# %% +# For plots, it is convenient to convert the communities into a VertexClustering: +communities = communities.as_clustering() + +# %% +# We can also easily print out who belongs to each community: +for i, community in enumerate(communities): + print(f"Community {i}:") + for v in community: + print(f"\t{g.vs[v]['label']}") + +# %% +# Finally we can proceed to plotting the graph. In order to make each community +# stand out, we set "community colors" using an igraph palette: +num_communities = len(communities) +palette1 = ig.RainbowPalette(n=num_communities) +for i, community in enumerate(communities): + g.vs[community]["color"] = i + community_edges = g.es.select(_within=community) + community_edges["color"] = i + +# %% +# We can use a dirty hack to move the labels below the vertices ;-) +g.vs["label"] = ["\n\n" + label for label in g.vs["label"]] + +# %% +# Finally, we can plot the communities: +fig1, ax1 = plt.subplots() +ig.plot( + communities, + target=ax1, + mark_groups=True, + palette=palette1, + vertex_size=0.1, + edge_width=0.5, +) +fig1.set_size_inches(20, 20) + + +# %% +# Now let's try and contract the information down, using only a single vertex +# to represent each community. We start by defining x, y, and size attributes +# for each node in the original graph: +layout = g.layout_kamada_kawai() +g.vs["x"], g.vs["y"] = list(zip(*layout)) +g.vs["size"] = 1 +g.es["size"] = 1 + +# %% +# Then we can generate the cluster graph that compresses each community into a +# single, "composite" vertex using +# :meth:`igraph.VertexClustering.cluster_graph`: +cluster_graph = communities.cluster_graph( + combine_vertices={ + "x": "mean", + "y": "mean", + "color": "first", + "size": "sum", + }, + combine_edges={ + "size": "sum", + }, +) + +# %% +# .. note:: +# +# We took the mean of x and y values so that the nodes in the cluster +# graph are placed at the centroid of the original cluster. +# +# .. note:: +# +# ``mean``, ``first``, and ``sum`` are all built-in collapsing functions, +# along with ``prod``, ``median``, ``max``, ``min``, ``last``, ``random``. +# You can also define your own custom collapsing functions, which take in a +# list and return a single element representing the combined attribute +# value. For more details on igraph contraction, see +# :meth:`igraph.GraphBase.contract_vertices`. + + +# %% +# Finally, we can assign colors to the clusters and plot the cluster graph, +# including a legend to make things clear: +palette2 = ig.GradientPalette("gainsboro", "black") +g.es["color"] = [palette2.get(int(i)) for i in ig.rescale(cluster_graph.es["size"], (0, 255), clamp=True)] + +fig2, ax2 = plt.subplots() +ig.plot( + cluster_graph, + target=ax2, + palette=palette1, + # set a minimum size on vertex_size, otherwise vertices are too small + vertex_size=[max(0.2, size / 20) for size in cluster_graph.vs["size"]], + edge_color=g.es["color"], + edge_width=0.8, +) + +# Add a legend +legend_handles = [] +for i in range(num_communities): + handle = ax2.scatter( + [], [], + s=100, + facecolor=palette1.get(i), + edgecolor="k", + label=i, + ) + legend_handles.append(handle) + +ax2.legend( + handles=legend_handles, + title='Community:', + bbox_to_anchor=(0, 1.0), + bbox_transform=ax2.transAxes, +) + +fig2.set_size_inches(10, 10) diff --git a/doc/examples_sphinx-gallery/complement.py b/doc/examples_sphinx-gallery/complement.py new file mode 100644 index 000000000..4436ae372 --- /dev/null +++ b/doc/examples_sphinx-gallery/complement.py @@ -0,0 +1,75 @@ +""" +.. _tutorials-complement: + +================ +Complement +================ + +This example shows how to generate the `complement graph `_ of a graph (sometimes known as the anti-graph) using :meth:`igraph.GraphBase.complementer`. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# First, we generate a random graph +random.seed(0) +g1 = ig.Graph.Erdos_Renyi(n=10, p=0.5) + +# %% +# .. note:: +# We set the random seed to ensure the graph comes out exactly the same +# each time in the gallery. You don't need to do that if you're exploring +# really random graphs ;-) + +# %% +# Then we generate the complement graph: +g2 = g1.complementer(loops=False) + +# %% +# The union graph of the two is of course the full graph, i.e. a graph with +# edges connecting all vertices to all other vertices. Because we decided to +# ignore loops (aka self-edges) in the complementer, the full graph does not +# include loops either. +g_full = g1 | g2 + +# %% +# In case there was any doubt, the complement of the full graph is an +# empty graph, with the same vertices but no edges: +g_empty = g_full.complementer(loops=False) + +# %% +# To demonstrate these concepts more clearly, here's a layout of each of the +# four graphs we discussed (input, complement, union/full, complement of +# union/empty): +fig, axs = plt.subplots(2, 2) +ig.plot( + g1, + target=axs[0, 0], + layout="circle", + vertex_color="black", +) +axs[0, 0].set_title('Original graph') +ig.plot( + g2, + target=axs[0, 1], + layout="circle", + vertex_color="black", +) +axs[0, 1].set_title('Complement graph') + +ig.plot( + g_full, + target=axs[1, 0], + layout="circle", + vertex_color="black", +) +axs[1, 0].set_title('Union graph') +ig.plot( + g_empty, + target=axs[1, 1], + layout="circle", + vertex_color="black", +) +axs[1, 1].set_title('Complement of union graph') +plt.show() diff --git a/doc/examples_sphinx-gallery/configuration.py b/doc/examples_sphinx-gallery/configuration.py new file mode 100644 index 000000000..fb0c07483 --- /dev/null +++ b/doc/examples_sphinx-gallery/configuration.py @@ -0,0 +1,60 @@ +""" +.. _tutorials-configuration: + +====================== +Configuration Instance +====================== + +This example shows how to use igraph's :class:`configuration instance ` to set default igraph settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every igraph project you work on. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# First we define the default plotting backend, layout, and color palette. +ig.config["plotting.backend"] = "matplotlib" +ig.config["plotting.layout"] = "fruchterman_reingold" +ig.config["plotting.palette"] = "rainbow" + +# %% +# Then, we save them. By default, ``ig.config.save()`` will save files to +# ``~/.igraphrc`` on Linux and Max OS X systems, or in +# ``%USERPROFILE%\.igraphrc`` for Windows systems: +ig.config.save() + +# %% +# The code above only needs to be run once (to store the new config options +# into the ``.igraphrc`` file). Whenever you use igraph and this file exists, +# igraph will read its content and use those options as defaults. For +# example, let's create and plot a new graph to demonstrate: +random.seed(1) +g = ig.Graph.Barabasi(n=100, m=1) + +# %% +# We now calculate a color value between 0-200 for all nodes, for instance by +# computing the vertex betweenness: +betweenness = g.betweenness() +colors = [int(i * 200 / max(betweenness)) for i in betweenness] + +# %% +# Finally, we can plot the graph. You will notice that even though we did not +# create a dedicated figure and axes, matplotlib is now used by default: +ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) +plt.show() + +# %% +# The full list of config settings can be found at +# :class:`igraph.Configuration`. +# +# .. note:: +# +# You can have multiple config files: specify each location via +# ``ig.config.save("./path/to/config/file")``. To load a specific config, +# import igraph and then call ``ig.config.load("./path/to/config/file")`` +# +# +# .. note:: +# +# To use a consistent style between individual plots (e.g. vertex sizes, +# colors, layout etc.) check out :ref:`tutorials-visual-style`. diff --git a/doc/examples_sphinx-gallery/connected_components.py b/doc/examples_sphinx-gallery/connected_components.py new file mode 100644 index 000000000..e85869cd5 --- /dev/null +++ b/doc/examples_sphinx-gallery/connected_components.py @@ -0,0 +1,44 @@ +""" +.. _tutorials-connected-components: + +===================== +Connected Components +===================== + +This example demonstrates how to visualise the connected components in a graph using :meth:`igraph.GraphBase.connected_components`. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# First, we generate a randomized geometric graph with random vertex sizes. The +# seed is set to the example is reproducible in our manual: you don't really +# need it to understand the concepts. +random.seed(0) +g = ig.Graph.GRG(50, 0.15) + +# %% +# Now we can cluster the graph into weakly connected components, i.e. subgraphs +# that have no edges connecting them to one another: +components = g.connected_components(mode='weak') + +# %% +# Finally, we can visualize the distinct connected components of the graph: +fig, ax = plt.subplots() +ig.plot( + components, + target=ax, + palette=ig.RainbowPalette(), + vertex_size=0.07, + vertex_color=list(map(int, ig.rescale(components.membership, (0, 200), clamp=True))), + edge_width=0.7 +) +plt.show() + +# %% +# .. note:: +# +# We use the integers from 0 to 200 instead of 0 to 255 in our vertex +# colors, since 255 in the :class:`igraph.drawing.colors.RainbowPalette` +# corresponds to looping back to red. This gives us nicely distinct hues. diff --git a/doc/examples_sphinx-gallery/delaunay-triangulation.py b/doc/examples_sphinx-gallery/delaunay-triangulation.py new file mode 100644 index 000000000..8f95b6e75 --- /dev/null +++ b/doc/examples_sphinx-gallery/delaunay-triangulation.py @@ -0,0 +1,98 @@ +""" +.. _tutorials-delaunay-triangulation: + +====================== +Delaunay Triangulation +====================== + +This example demonstrates how to calculate the `Delaunay triangulation `_ of an input graph. We start by generating a set of points on a 2D grid using random ``numpy`` arrays and a graph with those vertex coordinates and no edges. + +""" +import numpy as np +from scipy.spatial import Delaunay +import igraph as ig +import matplotlib.pyplot as plt + + +# %% +# We start by generating a random graph in the 2D unit cube, fixing the random +# seed to ensure reproducibility. +np.random.seed(0) +x, y = np.random.rand(2, 30) +g = ig.Graph(30) +g.vs['x'] = x +g.vs['y'] = y + +# %% +# Because we already set the `x` and `y` vertex attributes, we can use +# :meth:`igraph.Graph.layout_auto` to wrap them into a :class:`igraph.Layout` +# object. +layout = g.layout_auto() + +# %% +# Now we can calculate the delaunay triangulation using `scipy`'s :class:`scipy:scipy.spatial.Delaunay` class: +delaunay = Delaunay(layout.coords) + +# %% +# Given the triangulation, we can add the edges into the original graph: +for tri in delaunay.simplices: + g.add_edges([ + (tri[0], tri[1]), + (tri[1], tri[2]), + (tri[0], tri[2]), + ]) + +# %% +# Because adjacent triangles share an edge/side, the graph now contains some +# edges more than once. It's useful to simplify the graph to get rid of those +# multiedges, keeping each side only once: +g.simplify() + +# %% +# Finally, plotting the graph gives a good idea of what the triangulation looks +# like: +fig, ax = plt.subplots() +ig.plot( + g, + layout=layout, + target=ax, + vertex_size=0.04, + vertex_color="lightblue", + edge_width=0.8 +) +plt.show() + +# %% +# Alternative plotting style +# -------------------------- +# We can use :doc:`matplotlib ` to plot the faces of the +# triangles instead of the edges. First, we create a hue gradient for the +# triangle faces: +palette = ig.GradientPalette("midnightblue", "lightblue", 100) + +# %% +# Then we can "plot" the triangles using +# :class:`matplotlib:matplotlib.patches.Polygon` and the graph using +# :func:`igraph.plot() `: +fig, ax = plt.subplots() +for tri in delaunay.simplices: + # get the points of the triangle + tri_points = [delaunay.points[tri[i]] for i in range(3)] + + # calculate the vertical center of the triangle + center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 + + # draw triangle onto axes + poly = plt.Polygon(tri_points, color=palette.get(int(center * 100))) + ax.add_patch(poly) + +ig.plot( + g, + layout=layout, + target=ax, + vertex_size=0.0, + edge_width=0.2, + edge_color="white", +) +ax.set(xlim=(0, 1), ylim=(0, 1)) +plt.show() diff --git a/doc/examples_sphinx-gallery/erdos_renyi.py b/doc/examples_sphinx-gallery/erdos_renyi.py new file mode 100644 index 000000000..7f0e3b67a --- /dev/null +++ b/doc/examples_sphinx-gallery/erdos_renyi.py @@ -0,0 +1,86 @@ +""" +.. _tutorials-random: + +================= +Erdős-Rényi Graph +================= + +This example demonstrates how to generate `Erdős-Rényi Graphs `_ using :meth:`igraph.GraphBase.Erdos_Renyi`. There are two variants of graphs: + +- ``Erdos_Renyi(n, p)`` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. +- ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. + +We generate two graphs of each, so we can confirm that our graph generator is truly random. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# First, we set a random seed for reproducibility +random.seed(0) + +# %% +# Then, we generate two Erdos Renyi graphs with identical parameters: +g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) +g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) + +# %% +# For comparison, we also generate two Erdos Renyi graphs with a fixed number +# of edges: +g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) +g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) + +# %% +# We can print out summaries of each graph to verify their randomness +ig.summary(g1) +ig.summary(g2) +ig.summary(g3) +ig.summary(g4) + +# IGRAPH U--- 15 18 -- +# IGRAPH U--- 15 21 -- +# IGRAPH U--- 20 35 -- +# IGRAPH U--- 20 35 -- + +# %% +# Finally, we can plot the graphs to illustrate their structures and +# differences: +fig, axs = plt.subplots(2, 2) +# Probability +ig.plot( + g1, + target=axs[0, 0], + layout="circle", + vertex_color="lightblue" +) +ig.plot( + g2, + target=axs[0, 1], + layout="circle", + vertex_color="lightblue" +) +axs[0, 0].set_ylabel('Probability') +# N edges +ig.plot( + g3, + target=axs[1, 0], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 +) +ig.plot( + g4, + target=axs[1, 1], + layout="circle", + vertex_color="lightblue", + vertex_size=0.15 +) +axs[1, 0].set_ylabel('N. edges') +plt.show() + +# %% +# .. note:: +# +# Even when using the same random seed, results can still differ depending +# on the machine the code is being run from. diff --git a/doc/source/tutorials/isomorphism/assets/isomorphism.py b/doc/examples_sphinx-gallery/isomorphism.py similarity index 66% rename from doc/source/tutorials/isomorphism/assets/isomorphism.py rename to doc/examples_sphinx-gallery/isomorphism.py index b9544f62e..dd1e130b8 100644 --- a/doc/source/tutorials/isomorphism/assets/isomorphism.py +++ b/doc/examples_sphinx-gallery/isomorphism.py @@ -1,12 +1,23 @@ +""" +.. _tutorials-isomorphism: + +=========== +Isomorphism +=========== + +This example shows how to check for `isomorphism `_ between small graphs using :meth:`igraph.GraphBase.isomorphic`. +""" import igraph as ig import matplotlib.pyplot as plt -# Create Graphs +# %% +# First we generate three different graphs: g1 = ig.Graph([(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]) g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) -# Check isomorphism +# %% +# To check whether they are isomorphic, we can use a simple method: print("Are the graphs g1 and g2 isomorphic?") print(g1.isomorphic(g2)) print("Are the graphs g1 and g3 isomorphic?") @@ -22,8 +33,14 @@ # Are the graphs g2 and g3 isomorphic? # False +# %% +# .. note:: +# `Graph isomorphism `_ is an equivalence +# relationship, i.e. if `g1 ~ g2` and `g2 ~ g3`, then automatically `g1 ~ g3`. Therefore, +# we could have skipped the last check. -# Plot graphs +# %% +# We can plot the graphs to get an idea about the problem: visual_style = { "vertex_color": "lightblue", "vertex_label": [0, 1, 2, 3, 4], @@ -51,6 +68,4 @@ ) fig.text(0.38, 0.5, '$\simeq$' if g1.isomorphic(g2) else '$\\neq$', fontsize=15, ha='center', va='center') fig.text(0.65, 0.5, '$\simeq$' if g2.isomorphic(g3) else '$\\neq$', fontsize=15, ha='center', va='center') - plt.show() - diff --git a/doc/examples_sphinx-gallery/lesmis/lesmis.gml b/doc/examples_sphinx-gallery/lesmis/lesmis.gml new file mode 100644 index 000000000..3c0751191 --- /dev/null +++ b/doc/examples_sphinx-gallery/lesmis/lesmis.gml @@ -0,0 +1,1913 @@ +Creator "Mark Newman on Fri Jul 21 12:44:53 2006" +graph +[ + node + [ + id 0 + label "Myriel" + ] + node + [ + id 1 + label "Napoleon" + ] + node + [ + id 2 + label "MlleBaptistine" + ] + node + [ + id 3 + label "MmeMagloire" + ] + node + [ + id 4 + label "CountessDeLo" + ] + node + [ + id 5 + label "Geborand" + ] + node + [ + id 6 + label "Champtercier" + ] + node + [ + id 7 + label "Cravatte" + ] + node + [ + id 8 + label "Count" + ] + node + [ + id 9 + label "OldMan" + ] + node + [ + id 10 + label "Labarre" + ] + node + [ + id 11 + label "Valjean" + ] + node + [ + id 12 + label "Marguerite" + ] + node + [ + id 13 + label "MmeDeR" + ] + node + [ + id 14 + label "Isabeau" + ] + node + [ + id 15 + label "Gervais" + ] + node + [ + id 16 + label "Tholomyes" + ] + node + [ + id 17 + label "Listolier" + ] + node + [ + id 18 + label "Fameuil" + ] + node + [ + id 19 + label "Blacheville" + ] + node + [ + id 20 + label "Favourite" + ] + node + [ + id 21 + label "Dahlia" + ] + node + [ + id 22 + label "Zephine" + ] + node + [ + id 23 + label "Fantine" + ] + node + [ + id 24 + label "MmeThenardier" + ] + node + [ + id 25 + label "Thenardier" + ] + node + [ + id 26 + label "Cosette" + ] + node + [ + id 27 + label "Javert" + ] + node + [ + id 28 + label "Fauchelevent" + ] + node + [ + id 29 + label "Bamatabois" + ] + node + [ + id 30 + label "Perpetue" + ] + node + [ + id 31 + label "Simplice" + ] + node + [ + id 32 + label "Scaufflaire" + ] + node + [ + id 33 + label "Woman1" + ] + node + [ + id 34 + label "Judge" + ] + node + [ + id 35 + label "Champmathieu" + ] + node + [ + id 36 + label "Brevet" + ] + node + [ + id 37 + label "Chenildieu" + ] + node + [ + id 38 + label "Cochepaille" + ] + node + [ + id 39 + label "Pontmercy" + ] + node + [ + id 40 + label "Boulatruelle" + ] + node + [ + id 41 + label "Eponine" + ] + node + [ + id 42 + label "Anzelma" + ] + node + [ + id 43 + label "Woman2" + ] + node + [ + id 44 + label "MotherInnocent" + ] + node + [ + id 45 + label "Gribier" + ] + node + [ + id 46 + label "Jondrette" + ] + node + [ + id 47 + label "MmeBurgon" + ] + node + [ + id 48 + label "Gavroche" + ] + node + [ + id 49 + label "Gillenormand" + ] + node + [ + id 50 + label "Magnon" + ] + node + [ + id 51 + label "MlleGillenormand" + ] + node + [ + id 52 + label "MmePontmercy" + ] + node + [ + id 53 + label "MlleVaubois" + ] + node + [ + id 54 + label "LtGillenormand" + ] + node + [ + id 55 + label "Marius" + ] + node + [ + id 56 + label "BaronessT" + ] + node + [ + id 57 + label "Mabeuf" + ] + node + [ + id 58 + label "Enjolras" + ] + node + [ + id 59 + label "Combeferre" + ] + node + [ + id 60 + label "Prouvaire" + ] + node + [ + id 61 + label "Feuilly" + ] + node + [ + id 62 + label "Courfeyrac" + ] + node + [ + id 63 + label "Bahorel" + ] + node + [ + id 64 + label "Bossuet" + ] + node + [ + id 65 + label "Joly" + ] + node + [ + id 66 + label "Grantaire" + ] + node + [ + id 67 + label "MotherPlutarch" + ] + node + [ + id 68 + label "Gueulemer" + ] + node + [ + id 69 + label "Babet" + ] + node + [ + id 70 + label "Claquesous" + ] + node + [ + id 71 + label "Montparnasse" + ] + node + [ + id 72 + label "Toussaint" + ] + node + [ + id 73 + label "Child1" + ] + node + [ + id 74 + label "Child2" + ] + node + [ + id 75 + label "Brujon" + ] + node + [ + id 76 + label "MmeHucheloup" + ] + edge + [ + source 1 + target 0 + value 1 + ] + edge + [ + source 2 + target 0 + value 8 + ] + edge + [ + source 3 + target 0 + value 10 + ] + edge + [ + source 3 + target 2 + value 6 + ] + edge + [ + source 4 + target 0 + value 1 + ] + edge + [ + source 5 + target 0 + value 1 + ] + edge + [ + source 6 + target 0 + value 1 + ] + edge + [ + source 7 + target 0 + value 1 + ] + edge + [ + source 8 + target 0 + value 2 + ] + edge + [ + source 9 + target 0 + value 1 + ] + edge + [ + source 11 + target 10 + value 1 + ] + edge + [ + source 11 + target 3 + value 3 + ] + edge + [ + source 11 + target 2 + value 3 + ] + edge + [ + source 11 + target 0 + value 5 + ] + edge + [ + source 12 + target 11 + value 1 + ] + edge + [ + source 13 + target 11 + value 1 + ] + edge + [ + source 14 + target 11 + value 1 + ] + edge + [ + source 15 + target 11 + value 1 + ] + edge + [ + source 17 + target 16 + value 4 + ] + edge + [ + source 18 + target 16 + value 4 + ] + edge + [ + source 18 + target 17 + value 4 + ] + edge + [ + source 19 + target 16 + value 4 + ] + edge + [ + source 19 + target 17 + value 4 + ] + edge + [ + source 19 + target 18 + value 4 + ] + edge + [ + source 20 + target 16 + value 3 + ] + edge + [ + source 20 + target 17 + value 3 + ] + edge + [ + source 20 + target 18 + value 3 + ] + edge + [ + source 20 + target 19 + value 4 + ] + edge + [ + source 21 + target 16 + value 3 + ] + edge + [ + source 21 + target 17 + value 3 + ] + edge + [ + source 21 + target 18 + value 3 + ] + edge + [ + source 21 + target 19 + value 3 + ] + edge + [ + source 21 + target 20 + value 5 + ] + edge + [ + source 22 + target 16 + value 3 + ] + edge + [ + source 22 + target 17 + value 3 + ] + edge + [ + source 22 + target 18 + value 3 + ] + edge + [ + source 22 + target 19 + value 3 + ] + edge + [ + source 22 + target 20 + value 4 + ] + edge + [ + source 22 + target 21 + value 4 + ] + edge + [ + source 23 + target 16 + value 3 + ] + edge + [ + source 23 + target 17 + value 3 + ] + edge + [ + source 23 + target 18 + value 3 + ] + edge + [ + source 23 + target 19 + value 3 + ] + edge + [ + source 23 + target 20 + value 4 + ] + edge + [ + source 23 + target 21 + value 4 + ] + edge + [ + source 23 + target 22 + value 4 + ] + edge + [ + source 23 + target 12 + value 2 + ] + edge + [ + source 23 + target 11 + value 9 + ] + edge + [ + source 24 + target 23 + value 2 + ] + edge + [ + source 24 + target 11 + value 7 + ] + edge + [ + source 25 + target 24 + value 13 + ] + edge + [ + source 25 + target 23 + value 1 + ] + edge + [ + source 25 + target 11 + value 12 + ] + edge + [ + source 26 + target 24 + value 4 + ] + edge + [ + source 26 + target 11 + value 31 + ] + edge + [ + source 26 + target 16 + value 1 + ] + edge + [ + source 26 + target 25 + value 1 + ] + edge + [ + source 27 + target 11 + value 17 + ] + edge + [ + source 27 + target 23 + value 5 + ] + edge + [ + source 27 + target 25 + value 5 + ] + edge + [ + source 27 + target 24 + value 1 + ] + edge + [ + source 27 + target 26 + value 1 + ] + edge + [ + source 28 + target 11 + value 8 + ] + edge + [ + source 28 + target 27 + value 1 + ] + edge + [ + source 29 + target 23 + value 1 + ] + edge + [ + source 29 + target 27 + value 1 + ] + edge + [ + source 29 + target 11 + value 2 + ] + edge + [ + source 30 + target 23 + value 1 + ] + edge + [ + source 31 + target 30 + value 2 + ] + edge + [ + source 31 + target 11 + value 3 + ] + edge + [ + source 31 + target 23 + value 2 + ] + edge + [ + source 31 + target 27 + value 1 + ] + edge + [ + source 32 + target 11 + value 1 + ] + edge + [ + source 33 + target 11 + value 2 + ] + edge + [ + source 33 + target 27 + value 1 + ] + edge + [ + source 34 + target 11 + value 3 + ] + edge + [ + source 34 + target 29 + value 2 + ] + edge + [ + source 35 + target 11 + value 3 + ] + edge + [ + source 35 + target 34 + value 3 + ] + edge + [ + source 35 + target 29 + value 2 + ] + edge + [ + source 36 + target 34 + value 2 + ] + edge + [ + source 36 + target 35 + value 2 + ] + edge + [ + source 36 + target 11 + value 2 + ] + edge + [ + source 36 + target 29 + value 1 + ] + edge + [ + source 37 + target 34 + value 2 + ] + edge + [ + source 37 + target 35 + value 2 + ] + edge + [ + source 37 + target 36 + value 2 + ] + edge + [ + source 37 + target 11 + value 2 + ] + edge + [ + source 37 + target 29 + value 1 + ] + edge + [ + source 38 + target 34 + value 2 + ] + edge + [ + source 38 + target 35 + value 2 + ] + edge + [ + source 38 + target 36 + value 2 + ] + edge + [ + source 38 + target 37 + value 2 + ] + edge + [ + source 38 + target 11 + value 2 + ] + edge + [ + source 38 + target 29 + value 1 + ] + edge + [ + source 39 + target 25 + value 1 + ] + edge + [ + source 40 + target 25 + value 1 + ] + edge + [ + source 41 + target 24 + value 2 + ] + edge + [ + source 41 + target 25 + value 3 + ] + edge + [ + source 42 + target 41 + value 2 + ] + edge + [ + source 42 + target 25 + value 2 + ] + edge + [ + source 42 + target 24 + value 1 + ] + edge + [ + source 43 + target 11 + value 3 + ] + edge + [ + source 43 + target 26 + value 1 + ] + edge + [ + source 43 + target 27 + value 1 + ] + edge + [ + source 44 + target 28 + value 3 + ] + edge + [ + source 44 + target 11 + value 1 + ] + edge + [ + source 45 + target 28 + value 2 + ] + edge + [ + source 47 + target 46 + value 1 + ] + edge + [ + source 48 + target 47 + value 2 + ] + edge + [ + source 48 + target 25 + value 1 + ] + edge + [ + source 48 + target 27 + value 1 + ] + edge + [ + source 48 + target 11 + value 1 + ] + edge + [ + source 49 + target 26 + value 3 + ] + edge + [ + source 49 + target 11 + value 2 + ] + edge + [ + source 50 + target 49 + value 1 + ] + edge + [ + source 50 + target 24 + value 1 + ] + edge + [ + source 51 + target 49 + value 9 + ] + edge + [ + source 51 + target 26 + value 2 + ] + edge + [ + source 51 + target 11 + value 2 + ] + edge + [ + source 52 + target 51 + value 1 + ] + edge + [ + source 52 + target 39 + value 1 + ] + edge + [ + source 53 + target 51 + value 1 + ] + edge + [ + source 54 + target 51 + value 2 + ] + edge + [ + source 54 + target 49 + value 1 + ] + edge + [ + source 54 + target 26 + value 1 + ] + edge + [ + source 55 + target 51 + value 6 + ] + edge + [ + source 55 + target 49 + value 12 + ] + edge + [ + source 55 + target 39 + value 1 + ] + edge + [ + source 55 + target 54 + value 1 + ] + edge + [ + source 55 + target 26 + value 21 + ] + edge + [ + source 55 + target 11 + value 19 + ] + edge + [ + source 55 + target 16 + value 1 + ] + edge + [ + source 55 + target 25 + value 2 + ] + edge + [ + source 55 + target 41 + value 5 + ] + edge + [ + source 55 + target 48 + value 4 + ] + edge + [ + source 56 + target 49 + value 1 + ] + edge + [ + source 56 + target 55 + value 1 + ] + edge + [ + source 57 + target 55 + value 1 + ] + edge + [ + source 57 + target 41 + value 1 + ] + edge + [ + source 57 + target 48 + value 1 + ] + edge + [ + source 58 + target 55 + value 7 + ] + edge + [ + source 58 + target 48 + value 7 + ] + edge + [ + source 58 + target 27 + value 6 + ] + edge + [ + source 58 + target 57 + value 1 + ] + edge + [ + source 58 + target 11 + value 4 + ] + edge + [ + source 59 + target 58 + value 15 + ] + edge + [ + source 59 + target 55 + value 5 + ] + edge + [ + source 59 + target 48 + value 6 + ] + edge + [ + source 59 + target 57 + value 2 + ] + edge + [ + source 60 + target 48 + value 1 + ] + edge + [ + source 60 + target 58 + value 4 + ] + edge + [ + source 60 + target 59 + value 2 + ] + edge + [ + source 61 + target 48 + value 2 + ] + edge + [ + source 61 + target 58 + value 6 + ] + edge + [ + source 61 + target 60 + value 2 + ] + edge + [ + source 61 + target 59 + value 5 + ] + edge + [ + source 61 + target 57 + value 1 + ] + edge + [ + source 61 + target 55 + value 1 + ] + edge + [ + source 62 + target 55 + value 9 + ] + edge + [ + source 62 + target 58 + value 17 + ] + edge + [ + source 62 + target 59 + value 13 + ] + edge + [ + source 62 + target 48 + value 7 + ] + edge + [ + source 62 + target 57 + value 2 + ] + edge + [ + source 62 + target 41 + value 1 + ] + edge + [ + source 62 + target 61 + value 6 + ] + edge + [ + source 62 + target 60 + value 3 + ] + edge + [ + source 63 + target 59 + value 5 + ] + edge + [ + source 63 + target 48 + value 5 + ] + edge + [ + source 63 + target 62 + value 6 + ] + edge + [ + source 63 + target 57 + value 2 + ] + edge + [ + source 63 + target 58 + value 4 + ] + edge + [ + source 63 + target 61 + value 3 + ] + edge + [ + source 63 + target 60 + value 2 + ] + edge + [ + source 63 + target 55 + value 1 + ] + edge + [ + source 64 + target 55 + value 5 + ] + edge + [ + source 64 + target 62 + value 12 + ] + edge + [ + source 64 + target 48 + value 5 + ] + edge + [ + source 64 + target 63 + value 4 + ] + edge + [ + source 64 + target 58 + value 10 + ] + edge + [ + source 64 + target 61 + value 6 + ] + edge + [ + source 64 + target 60 + value 2 + ] + edge + [ + source 64 + target 59 + value 9 + ] + edge + [ + source 64 + target 57 + value 1 + ] + edge + [ + source 64 + target 11 + value 1 + ] + edge + [ + source 65 + target 63 + value 5 + ] + edge + [ + source 65 + target 64 + value 7 + ] + edge + [ + source 65 + target 48 + value 3 + ] + edge + [ + source 65 + target 62 + value 5 + ] + edge + [ + source 65 + target 58 + value 5 + ] + edge + [ + source 65 + target 61 + value 5 + ] + edge + [ + source 65 + target 60 + value 2 + ] + edge + [ + source 65 + target 59 + value 5 + ] + edge + [ + source 65 + target 57 + value 1 + ] + edge + [ + source 65 + target 55 + value 2 + ] + edge + [ + source 66 + target 64 + value 3 + ] + edge + [ + source 66 + target 58 + value 3 + ] + edge + [ + source 66 + target 59 + value 1 + ] + edge + [ + source 66 + target 62 + value 2 + ] + edge + [ + source 66 + target 65 + value 2 + ] + edge + [ + source 66 + target 48 + value 1 + ] + edge + [ + source 66 + target 63 + value 1 + ] + edge + [ + source 66 + target 61 + value 1 + ] + edge + [ + source 66 + target 60 + value 1 + ] + edge + [ + source 67 + target 57 + value 3 + ] + edge + [ + source 68 + target 25 + value 5 + ] + edge + [ + source 68 + target 11 + value 1 + ] + edge + [ + source 68 + target 24 + value 1 + ] + edge + [ + source 68 + target 27 + value 1 + ] + edge + [ + source 68 + target 48 + value 1 + ] + edge + [ + source 68 + target 41 + value 1 + ] + edge + [ + source 69 + target 25 + value 6 + ] + edge + [ + source 69 + target 68 + value 6 + ] + edge + [ + source 69 + target 11 + value 1 + ] + edge + [ + source 69 + target 24 + value 1 + ] + edge + [ + source 69 + target 27 + value 2 + ] + edge + [ + source 69 + target 48 + value 1 + ] + edge + [ + source 69 + target 41 + value 1 + ] + edge + [ + source 70 + target 25 + value 4 + ] + edge + [ + source 70 + target 69 + value 4 + ] + edge + [ + source 70 + target 68 + value 4 + ] + edge + [ + source 70 + target 11 + value 1 + ] + edge + [ + source 70 + target 24 + value 1 + ] + edge + [ + source 70 + target 27 + value 1 + ] + edge + [ + source 70 + target 41 + value 1 + ] + edge + [ + source 70 + target 58 + value 1 + ] + edge + [ + source 71 + target 27 + value 1 + ] + edge + [ + source 71 + target 69 + value 2 + ] + edge + [ + source 71 + target 68 + value 2 + ] + edge + [ + source 71 + target 70 + value 2 + ] + edge + [ + source 71 + target 11 + value 1 + ] + edge + [ + source 71 + target 48 + value 1 + ] + edge + [ + source 71 + target 41 + value 1 + ] + edge + [ + source 71 + target 25 + value 1 + ] + edge + [ + source 72 + target 26 + value 2 + ] + edge + [ + source 72 + target 27 + value 1 + ] + edge + [ + source 72 + target 11 + value 1 + ] + edge + [ + source 73 + target 48 + value 2 + ] + edge + [ + source 74 + target 48 + value 2 + ] + edge + [ + source 74 + target 73 + value 3 + ] + edge + [ + source 75 + target 69 + value 3 + ] + edge + [ + source 75 + target 68 + value 3 + ] + edge + [ + source 75 + target 25 + value 3 + ] + edge + [ + source 75 + target 48 + value 1 + ] + edge + [ + source 75 + target 41 + value 1 + ] + edge + [ + source 75 + target 70 + value 1 + ] + edge + [ + source 75 + target 71 + value 1 + ] + edge + [ + source 76 + target 64 + value 1 + ] + edge + [ + source 76 + target 65 + value 1 + ] + edge + [ + source 76 + target 66 + value 1 + ] + edge + [ + source 76 + target 63 + value 1 + ] + edge + [ + source 76 + target 62 + value 1 + ] + edge + [ + source 76 + target 48 + value 1 + ] + edge + [ + source 76 + target 58 + value 1 + ] +] diff --git a/doc/examples_sphinx-gallery/lesmis/lesmis.txt b/doc/examples_sphinx-gallery/lesmis/lesmis.txt new file mode 100644 index 000000000..8772c84b0 --- /dev/null +++ b/doc/examples_sphinx-gallery/lesmis/lesmis.txt @@ -0,0 +1,7 @@ +The file lesmis.gml contains the weighted network of coappearances of +characters in Victor Hugo's novel "Les Miserables". Nodes represent +characters as indicated by the labels and edges connect any pair of +characters that appear in the same chapter of the book. The values on the +edges are the number of such coappearances. The data on coappearances were +taken from D. E. Knuth, The Stanford GraphBase: A Platform for +Combinatorial Computing, Addison-Wesley, Reading, MA (1993). diff --git a/doc/source/tutorials/maxflow/assets/maxflow.py b/doc/examples_sphinx-gallery/maxflow.py similarity index 54% rename from doc/source/tutorials/maxflow/assets/maxflow.py rename to doc/examples_sphinx-gallery/maxflow.py index b28b81bfc..246d4c451 100644 --- a/doc/source/tutorials/maxflow/assets/maxflow.py +++ b/doc/examples_sphinx-gallery/maxflow.py @@ -1,19 +1,38 @@ +""" +.. _tutorials-maxflow: + +============ +Maximum Flow +============ + +This example shows how to construct a max flow on a directed graph with edge capacities using :meth:`igraph.Graph.maxflow`. + +""" import igraph as ig import matplotlib.pyplot as plt +# %% +# First, we generate a graph and assign a "capacity" to each edge: g = ig.Graph( 6, [(3, 2), (3, 4), (2, 1), (4,1), (4, 5), (1, 0), (5, 0)], directed=True ) -g.es["capacity"] = [7, 8, 1, 2, 3, 4, 5] # capacity of each edge +g.es["capacity"] = [7, 8, 1, 2, 3, 4, 5] -# Runs max flow, and returns a Flow object +# %% +# To find the max flow, we can simply run: flow = g.maxflow(3, 0, capacity=g.es["capacity"]) print("Max flow:", flow.value) print("Edge assignments:", flow.flow) +# Output: +# Max flow: 6.0 +# Edge assignments [1.0, 5.0, 1.0, 2.0, 3.0, 3.0, 3.0] + +# %% +# Finally, we can plot the directed graph to look at the situation: fig, ax = plt.subplots() ig.plot( g, @@ -23,8 +42,3 @@ vertex_color="lightblue" ) plt.show() - -# Output: -# Max flow: 6.0 -# Edge assignments [1.0, 5.0, 1.0, 2.0, 3.0, 3.0, 3.0] - diff --git a/doc/examples_sphinx-gallery/minimum_spanning_trees.py b/doc/examples_sphinx-gallery/minimum_spanning_trees.py new file mode 100644 index 000000000..50a3d668a --- /dev/null +++ b/doc/examples_sphinx-gallery/minimum_spanning_trees.py @@ -0,0 +1,53 @@ +""" +.. _tutorials-minimum-spanning-trees: + +====================== +Minimum Spanning Trees +====================== + +This example shows how to generate a `minimum spanning tree `_ from an input graph using :meth:`igraph.Graph.spanning_tree`. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. + +""" +import random +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# We start by generating a grid graph with random integer weights between 1 and +# 20: +random.seed(0) +g = ig.Graph.Lattice([5, 5], circular=False) +g.es["weight"] = [random.randint(1, 20) for _ in g.es] + +# %% +# We can then compute a minimum spanning tree using +# :meth:`igraph.Graph.spanning_tree`, making sure to pass in the randomly +# generated weights. +mst_edges = g.spanning_tree(weights=g.es["weight"], return_tree=False) + +# %% +# We can print out the minimum edge weight sum +print("Minimum edge weight sum:", sum(g.es[mst_edges]["weight"])) + +# Minimum edge weight sum: 136 + +# %% +# Finally, we can plot the graph, highlighting the edges that are part of the +# minimum spanning tree. +g.es["color"] = "lightgray" +g.es[mst_edges]["color"] = "midnightblue" +g.es["width"] = 1.0 +g.es[mst_edges]["width"] = 3.0 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout="grid", + vertex_color="lightblue", + edge_width=g.es["width"], + edge_label=g.es["weight"], + edge_background="white", +) +plt.show() + diff --git a/doc/examples_sphinx-gallery/online_user_actions.py b/doc/examples_sphinx-gallery/online_user_actions.py new file mode 100644 index 000000000..8ad9142d6 --- /dev/null +++ b/doc/examples_sphinx-gallery/online_user_actions.py @@ -0,0 +1,104 @@ +""" +.. _tutorials-online-user-actions: + +=================== +Online user actions +=================== + +This example reproduces a typical data science situation in an internet company. We start from a pandas DataFrame with online user actions, for instance for an online text editor: the user can create a page, edit it, or delete it. We want to construct and visualize a graph of the users highlighting collaborations on the same page/project. +""" + +import igraph as ig +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +# %% +# Let's start by preparing some toy data representing online users. Each row +# indicates a certain action taken by a user (e.g. click on a button within a +# website). Actual user data usually come with time stamp, but that's not +# essential for this example. +action_dataframe = pd.DataFrame([ + ['dsj3239asadsa3', 'createPage', 'greatProject'], + ['2r09ej221sk2k5', 'editPage', 'greatProject'], + ['dsj3239asadsa3', 'editPage', 'greatProject'], + ['789dsadafj32jj', 'editPage', 'greatProject'], + ['oi32ncwosap399', 'editPage', 'greatProject'], + ['4r4320dkqpdokk', 'createPage', 'miniProject'], + ['320eljl3lk3239', 'editPage', 'miniProject'], + ['dsj3239asadsa3', 'editPage', 'miniProject'], + ['3203ejew332323', 'createPage', 'private'], + ['3203ejew332323', 'editPage', 'private'], + ['40m11919332msa', 'createPage', 'private2'], + ['40m11919332msa', 'editPage', 'private2'], + ['dsj3239asadsa3', 'createPage', 'anotherGreatProject'], + ['2r09ej221sk2k5', 'editPage', 'anotherGreatProject'], + ], + columns=['userid', 'action', 'project'], +) + +# %% +# The goal of this example is to check when two users worked on the same page. +# We choose to use a weighted adjacency matrix for this, i.e. a table with rows +# and columns indexes by the users that has nonzero entries whenever folks +# collaborate. First, let's get the users and prepare an empty matrix: +users = action_dataframe['userid'].unique() +adjacency_matrix = pd.DataFrame( + np.zeros((len(users), len(users)), np.int32), + index=users, + columns=users, +) + +# %% +# Then, let's iterate over all projects one by one, and add all collaborations: +for project, project_data in action_dataframe.groupby('project'): + project_users = project_data['userid'].values + for i1, user1 in enumerate(project_users): + for user2 in project_users[:i1]: + adjacency_matrix.at[user1, user2] += 1 + +# %% +# There are many ways to achieve the above matrix, so don't be surprised if you +# came up with another algorithm ;-) Now it's time to make the graph: +g = ig.Graph.Weighted_Adjacency(adjacency_matrix, mode='plus') + +# %% +# We can take a look at the graph via plotting functions. We can first make a +# layout: +layout = g.layout('circle') + +# %% +# Then we can prepare vertex sizes based on their closeness to other vertices +vertex_size = g.closeness() +vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] + +# %% +# Finally, we can plot the graph: +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_label=g.vs['name'], + vertex_color="lightblue", + vertex_size=vertex_size, + edge_width=g.es["weight"], +) +plt.show() + +# %% +# Loops indicate "self-collaborations", which are not very meaningful. To +# filter out loops without losing the edge weights, we can use: +g = g.simplify(combine_edges='first') + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_label=g.vs['name'], + vertex_color="lightblue", + vertex_size=vertex_size, + edge_width=g.es["weight"], +) +plt.show() diff --git a/doc/source/tutorials/quickstart/assets/quickstart.py b/doc/examples_sphinx-gallery/quickstart.py similarity index 78% rename from doc/source/tutorials/quickstart/assets/quickstart.py rename to doc/examples_sphinx-gallery/quickstart.py index 52edfab77..8edf0c9d3 100644 --- a/doc/source/tutorials/quickstart/assets/quickstart.py +++ b/doc/examples_sphinx-gallery/quickstart.py @@ -1,3 +1,20 @@ +""" +.. _tutorials-quickstart: + +=========== +Quick Start +=========== +For the eager folks out there, this intro will give you a quick overview of the following operations: + +- Construct a graph +- Set attributes of nodes and edges +- Plot a graph using matplotlib +- Save the plot as an image +- Export and import a graph as a ``.gml`` file + +To find out more features that igraph has to offer, check out the :ref:`gallery`! + +""" import igraph as ig import matplotlib.pyplot as plt diff --git a/doc/examples_sphinx-gallery/ring_animation.py b/doc/examples_sphinx-gallery/ring_animation.py new file mode 100644 index 000000000..25daa2918 --- /dev/null +++ b/doc/examples_sphinx-gallery/ring_animation.py @@ -0,0 +1,89 @@ +""" +.. _tutorials-ring-animation: + +==================== +Ring Graph Animation +==================== + +This example demonstrates how to use :doc:`matplotlib:api/animation_api` in +order to animate a ring graph sequentially being revealed. + +""" +import igraph as ig +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +# sphinx_gallery_thumbnail_path = '_static/gallery_thumbnails/ring_animation.gif' + +# %% +# Create a ring graph, which we will then animate +g = ig.Graph.Ring(10, directed=True) + +# %% +# Compute a 2D ring layout that looks like an actual ring +layout = g.layout_circle() + +# %% +# Prepare an update function. This "callback" function will be run at every +# frame and takes as a single argument the frame number. For simplicity, at +# each frame we compute a subgraph with only a fraction of the vertices and +# edges. As time passes, the graph becomes more and more complete until the +# whole ring is closed. +# +# .. note:: +# The beginning and end of the animation are a little tricky because only +# a vertex or edge is added, not both. Don't worry if you cannot understand +# all details immediately. +def _update_graph(frame): + # Remove plot elements from the previous frame + ax.clear() + + # Fix limits (unless you want a zoom-out effect) + ax.set_xlim(-1.5, 1.5) + ax.set_ylim(-1.5, 1.5) + + if frame < 10: + # Plot subgraph + gd = g.subgraph(range(frame)) + elif frame == 10: + # In the second-to-last frame, plot all vertices but skip the last + # edge, which will only be shown in the last frame + gd = g.copy() + gd.delete_edges(9) + else: + # Last frame + gd = g + + ig.plot(gd, target=ax, layout=layout[:frame], vertex_color="yellow") + + # Capture handles for blitting + if frame == 0: + nhandles = 0 + elif frame == 1: + nhandles = 1 + elif frame < 11: + # vertex, 2 for each edge + nhandles = 3 * frame + else: + # The final edge closing the circle + nhandles = 3 * (frame - 1) + 2 + + handles = ax.get_children()[:nhandles] + return handles + +# %% +# Run the animation +fig, ax = plt.subplots() +ani = animation.FuncAnimation(fig, _update_graph, 12, interval=500, blit=True) +plt.ion() +plt.show() + +# %% +# .. note:: +# +# We use *igraph*'s :meth:`Graph.subgraph()` (see +# :meth:`igraph.GraphBase.induced_subgraph`) in order to obtain a section of +# the ring graph at a time for each frame. While sufficient for an easy +# example, this approach is not very efficient. Thinking of more efficient +# approaches, e.g. vertices with zero radius, is a useful exercise to learn +# the combination of igraph and matplotlib. diff --git a/doc/examples_sphinx-gallery/shortest_path_visualisation.py b/doc/examples_sphinx-gallery/shortest_path_visualisation.py new file mode 100644 index 000000000..de17c0d0d --- /dev/null +++ b/doc/examples_sphinx-gallery/shortest_path_visualisation.py @@ -0,0 +1,79 @@ +""" +.. _tutorials-shortest-paths: + +============== +Shortest Paths +============== + +This example demonstrates how to find the shortest distance between two vertices +of a weighted or an unweighted graph. +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# To find the shortest path or distance between two nodes, we can use :meth:`igraph.GraphBase.get_shortest_paths`. If we're only interested in counting the unweighted distance, then we can do the following: +g = ig.Graph( + 6, + [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] +) +results = g.get_shortest_paths(1, to=4, output="vpath") + +# results = [[1, 0, 2, 4]] + +# %% +# We can print the result of the computation: +if len(results[0]) > 0: + # The distance is the number of vertices in the shortest path minus one. + print("Shortest distance is: ", len(results[0])-1) +else: + print("End node could not be reached!") + +# %% +# If the edges have weights, things are a little different. First, let's add +# weights to our graph edges: +g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] + +# %% +# To get the shortest paths on a weighted graph, we pass the weights as an +# argument. For a change, we choose the output format as ``"epath"`` to +# receive the path as an edge list, which can be used to calculate the length +# of the path. +results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") + +# results = [[1, 3, 5]] + +if len(results[0]) > 0: + # Add up the weights across all edges on the shortest path + distance = 0 + for e in results[0]: + distance += g.es[e]["weight"] + print("Shortest weighted distance is: ", distance) +else: + print("End node could not be reached!") + +# %% +# .. note:: +# +# - :meth:`igraph.GraphBase.get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. +# - If you're interested in finding *all* shortest paths, take a look at :meth:`igraph.GraphBase.get_all_shortest_paths`. + +# %% +# In case you are wondering how the visualization figure was done, here's the code: +g.es['width'] = 0.5 +g.es[results[0]]['width'] = 2.5 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout='circle', + vertex_color='steelblue', + vertex_label=range(g.vcount()), + edge_width=g.es['width'], + edge_label=g.es["weight"], + edge_color='#666', + edge_align_label=True, + edge_background='white' +) +plt.show() diff --git a/doc/examples_sphinx-gallery/simplify.py b/doc/examples_sphinx-gallery/simplify.py new file mode 100644 index 000000000..6d626fc71 --- /dev/null +++ b/doc/examples_sphinx-gallery/simplify.py @@ -0,0 +1,71 @@ +""" +======== +Simplify +======== + +This example shows how to remove self loops and multiple edges using :meth:`igraph.GraphBase.simplify`. +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# We start with a graph that includes loops and multiedges: +g1 = ig.Graph([ + (0, 1), + (1, 2), + (2, 3), + (3, 4), + (4, 0), + (0, 0), + (1, 4), + (1, 4), + (0, 2), + (2, 4), + (2, 4), + (2, 4), + (3, 3)], +) + +# %% +# To simplify the graph, we must remember that the function operates in place, +# i.e. directly changes the graph that it is run on. So we need to first make a +# copy of our graph, and then simplify that copy to keep the original graph +# untouched: +g2 = g1.copy() +g2.simplify() + +# %% +# We can then proceed to plot both graphs to see the difference. First, let's +# choose a consistent visual style: +visual_style = { + "vertex_color": "lightblue", + "vertex_size": 0.4, + "vertex_label": [0, 1, 2, 3, 4], +} + +# %% +# And finally, let's plot them in twin axes, with rectangular frames around +# each plot: +fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) +ig.plot( + g1, + layout="circle", + target=axs[0], + **visual_style, +) +ig.plot( + g2, + layout="circle", + target=axs[1], + **visual_style, +) +axs[0].set_title('Multigraph...') +axs[1].set_title('...simplified') +# Draw rectangles around axes +axs[0].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[0].transAxes, + )) +axs[1].add_patch(plt.Rectangle( + (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[1].transAxes, + )) +plt.show() diff --git a/doc/examples_sphinx-gallery/spanning_trees.py b/doc/examples_sphinx-gallery/spanning_trees.py new file mode 100644 index 000000000..e9b083f60 --- /dev/null +++ b/doc/examples_sphinx-gallery/spanning_trees.py @@ -0,0 +1,57 @@ +""" +.. _tutorials-spanning-trees: + +============== +Spanning Trees +============== + +This example shows how to generate a spanning tree from an input graph using :meth:`igraph.Graph.spanning_tree`. For the related idea of finding a *minimum spanning tree*, see :ref:`tutorials-minimum-spanning-trees`. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# First we create a two-dimensional, 6 by 6 lattice graph: +g = ig.Graph.Lattice([6, 6], circular=False) + +# %% +# We can compute the 2D layout of the graph: +layout = g.layout("grid") + +# %% +# To spice things up a little, we rearrange the vertex ids and compute a new +# layout. While not terribly useful in this context, it does make for a more +# interesting-looking spanning tree ;-) +random.seed(0) +permutation = list(range(g.vcount())) +random.shuffle(permutation) +g = g.permute_vertices(permutation) +new_layout = g.layout("grid") +for i in range(36): + new_layout[permutation[i]] = layout[i] +layout = new_layout + +# %% +# We can now generate a spanning tree: +spanning_tree = g.spanning_tree(weights=None, return_tree=False) + +# %% +# Finally, we can plot the graph with a highlight color for the spanning tree. +# We follow the usual recipe: first we set a few aesthetic options and then we +# leverage :func:`igraph.plot() ` and matplotlib for the +# heavy lifting: +g.es["color"] = "lightgray" +g.es[spanning_tree]["color"] = "midnightblue" +g.es["width"] = 0.5 +g.es[spanning_tree]["width"] = 3.0 + +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + layout=layout, + vertex_color="lightblue", + edge_width=g.es["width"] +) +plt.show() diff --git a/doc/examples_sphinx-gallery/topological_sort.py b/doc/examples_sphinx-gallery/topological_sort.py new file mode 100644 index 000000000..04971131b --- /dev/null +++ b/doc/examples_sphinx-gallery/topological_sort.py @@ -0,0 +1,59 @@ +""" +.. _tutorials-topological-sort: + +=================== +Topological sorting +=================== + +This example demonstrates how to get a topological sorting on a directed acyclic graph (DAG). A topological sorting of a directed graph is a linear ordering based on the precedence implied by the directed edges. It exists iff the graph doesn't have any cycle. In ``igraph``, we can use :meth:`igraph.GraphBase.topological_sorting` to get a topological ordering of the vertices. +""" +import igraph as ig +import matplotlib.pyplot as plt + + +# %% +# First off, we generate a directed acyclic graph (DAG): +g = ig.Graph( + edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], + directed=True, +) + +# %% +# We can verify immediately that this is actually a DAG: +assert g.is_dag + +# %% +# A topological sorting can be computed quite easily by calling +# :meth:`igraph.GraphBase.topological_sorting`, which returns a list of vertex IDs. +# If the given graph is not DAG, the error will occur. +results = g.topological_sorting(mode='out') +print('Topological sort of g (out):', *results) + +# %% +# In fact, there are two modes of :meth:`igraph.GraphBase.topological_sorting`, +# ``'out'`` ``'in'``. ``'out'`` is the default and starts from a node with +# indegree equal to 0. Vice versa, ``'in'`` starts from a node with outdegree +# equal to 0. To call the other mode, we can simply use: +results = g.topological_sorting(mode='in') +print('Topological sort of g (in):', *results) + +# %% +# We can use :meth:`igraph.Vertex.indegree` to find the indegree of the node. +for i in range(g.vcount()): + print('degree of {}: {}'.format(i, g.vs[i].indegree())) + +# % +# Finally, we can plot the graph to make the situation a little clearer. +# Just to change things up a bit, we use the matplotlib visualization mode +# inspired by `xkcd _: +with plt.xkcd(): + fig, ax = plt.subplots(figsize=(5, 5)) + ig.plot( + g, + target=ax, + layout='kk', + vertex_size=0.3, + edge_width=4, + vertex_label=range(g.vcount()), + vertex_color="white", + ) diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py new file mode 100644 index 000000000..8273edfd6 --- /dev/null +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -0,0 +1,49 @@ +""" +.. _tutorials-visual-style: + +Visual styling +=========================== + +This example shows how to change the visual style of network plots. +""" +import igraph as ig +import matplotlib.pyplot as plt +import random + +# %% +# To configure the visual style of a plot, we can create a dictionary with the +# various setting we want to customize: +visual_style = { + "edge_width": 0.3, + "vertex_size": 1.5, + "palette": "heat", + "layout": "fruchterman_reingold" +} + +# %% +# Let's see it in action! First, we generate four random graphs: +random.seed(1) +gs = [ig.Graph.Barabasi(n=30, m=1) for i in range(4)] + +# %% +# Then, we calculate a color colors between 0-255 for all nodes, e.g. using +# betweenness just as an example: +betweenness = [g.betweenness() for g in gs] +colors = [[int(i * 255 / max(btw)) for i in btw] for btw in betweenness] + +# %% +# Finally, we can plot the graphs using the same visual style for all graphs: +fig, axs = plt.subplots(2, 2) +axs = axs.ravel() +for g, color, ax in zip(gs, colors, axs): + ig.plot(g, target=ax, vertex_color=color, **visual_style) +plt.show() + + +# %% +# .. note:: +# If you would like to set global defaults, for example, always using the +# Matplotlib plotting backend, or using a particular color palette by +# default, you can use igraph's `configuration instance +# :class:`igraph.configuration.Configuration`. A quick example on how to use +# it can be found here: :ref:`tutorials-configuration`. diff --git a/doc/examples_sphinx-gallery/visualize_cliques.py b/doc/examples_sphinx-gallery/visualize_cliques.py new file mode 100644 index 000000000..44f0ff713 --- /dev/null +++ b/doc/examples_sphinx-gallery/visualize_cliques.py @@ -0,0 +1,66 @@ +""" +.. _tutorials-cliques: + +============ +Cliques +============ + +This example shows how to compute and visualize cliques of a graph using :meth:`igraph.GraphBase.cliques`. + +""" +import igraph as ig +import matplotlib.pyplot as plt + +# %% +# First, let's create a graph, for instance the famous karate club graph: +g = ig.Graph.Famous('Zachary') + +# %% +# Computing cliques can be done as follows: +cliques = g.cliques(4, 4) + +# %% +# We can plot the result of the computation. To make things a little more +# interesting, we plot each clique highlighted in a separate axes: +fig, axs = plt.subplots(3, 4) +axs = axs.ravel() +for clique, ax in zip(cliques, axs): + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, palette=ig.RainbowPalette(), + edge_width=0.5, + target=ax, + ) +plt.axis('off') +plt.show() + + +# %% +# Advanced: improving plotting style +# ---------------------------------- +# If you want a little more style, you can color the vertices/edges within each +# clique to make them stand out: +fig, axs = plt.subplots(3, 4) +axs = axs.ravel() +for clique, ax in zip(cliques, axs): + # Color vertices yellow/red based on whether they are in this clique + g.vs['color'] = 'yellow' + g.vs[clique]['color'] = 'red' + + # Color edges black/red based on whether they are in this clique + clique_edges = g.es.select(_within=clique) + g.es['color'] = 'black' + clique_edges['color'] = 'red' + # also increase thickness of clique edges + g.es['width'] = 0.3 + clique_edges['width'] = 1 + + ig.plot( + ig.VertexCover(g, [clique]), + mark_groups=True, + palette=ig.RainbowPalette(), + target=ax, + ) +plt.axis('off') +plt.show() + diff --git a/doc/source/tutorials/visualize_communities/assets/visualize_communities.py b/doc/examples_sphinx-gallery/visualize_communities.py similarity index 53% rename from doc/source/tutorials/visualize_communities/assets/visualize_communities.py rename to doc/examples_sphinx-gallery/visualize_communities.py index 614bb612d..7cfd90746 100644 --- a/doc/source/tutorials/visualize_communities/assets/visualize_communities.py +++ b/doc/examples_sphinx-gallery/visualize_communities.py @@ -1,14 +1,27 @@ +""" +.. _tutorials-visualize-communities: + +===================== +Communities +===================== + +This example shows how to visualize communities or clusters of a graph. +""" import igraph as ig import matplotlib.pyplot as plt +# %% +# First, we generate a graph. We use a famous graph here for simplicity: g = ig.Graph.Famous("Zachary") -# Use edge betweenness to detect communities -# and covert into a VertexClustering +# %% +# Edge betweenness is a standard way to detect communities. We then covert into +# a :class:`igraph.VertexClustering` object for subsequent ease of use: communities = g.community_edge_betweenness() communities = communities.as_clustering() -# Color each vertex and edge based on its community membership +# %% +# Next, we color each vertex and edge based on its community membership: num_communities = len(communities) palette = ig.RainbowPalette(n=num_communities) for i, community in enumerate(communities): @@ -17,7 +30,10 @@ community_edges["color"] = i -# Plot with only vertex and edge coloring +# %% +# Last, we plot the graph. We use a fancy technique called proxy artists to +# make a legend. You can find more about that in matplotlib's +# :doc:`matplotlib:tutorials/intermediate/legend_guide`: fig, ax = plt.subplots() ig.plot( communities, @@ -44,5 +60,8 @@ bbox_to_anchor=(0, 1.0), bbox_transform=ax.transAxes, ) - plt.show() + +# %% +# For an example on how to generate the cluster graph from a vertex cluster, +# check out :ref:`tutorials-cluster-graph`. diff --git a/doc/source/tutorials/ring_animation/figures/ring_animation.gif b/doc/source/_static/gallery_thumbnails/ring_animation.gif similarity index 100% rename from doc/source/tutorials/ring_animation/figures/ring_animation.gif rename to doc/source/_static/gallery_thumbnails/ring_animation.gif diff --git a/doc/source/tutorials/ring_animation/figures/ring_animation.png b/doc/source/_static/gallery_thumbnails/ring_animation.png similarity index 100% rename from doc/source/tutorials/ring_animation/figures/ring_animation.png rename to doc/source/_static/gallery_thumbnails/ring_animation.png diff --git a/doc/source/conf.py b/doc/source/conf.py index 2e2356231..1e8b6d682 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -71,7 +71,7 @@ def get_igraph_version(): 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx', - 'gallery_generator', + 'sphinx_gallery.gen_gallery', #'sphinx_panels', 'pydoctor.sphinx_ext.build_apidocs', ] @@ -277,6 +277,17 @@ def get_pydoctor_html_outputdir(pydoctor_url_path): if not is_inside_rtd: extensions.append('postprocess_api') + +# -- Options for sphinx-gallery ------------------------------------------------ + +sphinx_gallery_conf = { + 'examples_dirs': '../examples_sphinx-gallery', # path to your example scripts + 'gallery_dirs': 'tutorials', # path to where to save gallery generated output + 'filename_pattern': '/', + 'matplotlib_animations': True, + 'remove_config_comments': True, +} + # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). @@ -367,7 +378,7 @@ def get_pydoctor_html_outputdir(pydoctor_url_path): intersphinx_mapping = { 'numpy': ('https://numpy.org/doc/stable/', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/', None), 'matplotlib': ('https://matplotlib.org/stable', None), 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), 'networkx': ('https://networkx.org/documentation/stable/', None), diff --git a/doc/source/faq.rst b/doc/source/faq.rst index 900cc10d6..040a9fa58 100644 --- a/doc/source/faq.rst +++ b/doc/source/faq.rst @@ -16,8 +16,8 @@ help you! I've just installed |igraph|. What do I do now? ----------------------------------------------- -Take a peek at the :doc:`tutorials/quickstart/quickstart`! You can then go through a few -more examples in our :doc:`gallery `, read detailed instructions on graph :doc:`generation `, :doc:`analysis ` and :doc:`visualisation `, and check out the full :doc:`API documentation `. +Take a peek at the :doc:`tutorials/quickstart`! You can then go through a few +more examples in our :ref:`gallery `, read detailed instructions on graph :doc:`generation `, :doc:`analysis ` and :doc:`visualisation `, and check out the full :doc:`API documentation `. I thought |igraph| was an R package, is this the same package? diff --git a/doc/source/index.rst b/doc/source/index.rst index 60b1d987c..040b4c5c5 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -65,8 +65,8 @@ Documentation **Tutorials** - - :doc:`Quick Start ` - - :doc:`Example Gallery ` + - :doc:`Quick start ` + - :doc:`Gallery of examples ` - :doc:`Extended tutorial ` .. container:: @@ -101,7 +101,7 @@ Documentation for `python-igraph <= 0.10.1` is available on our `old website =2.28.1 sphinxbootstrap4theme +sphinx-gallery pydoctor numpy +scipy pandas matplotlib diff --git a/doc/source/sphinxext/gallery_generator.py b/doc/source/sphinxext/gallery_generator.py deleted file mode 100644 index 111f60eeb..000000000 --- a/doc/source/sphinxext/gallery_generator.py +++ /dev/null @@ -1,281 +0,0 @@ -""" -Sphinx plugin to run example scripts and create a gallery page. - -Lightly modified from the seaborn project (Michael Waskom). -Originally, lightly modified from the mpld3 project. - -""" -import os -import os.path as op -import re -import glob -import token -import tokenize -import shutil -import warnings - -import matplotlib -matplotlib.use('Agg') -import matplotlib.pyplot as plt # noqa: E402 - - -INDEX_TEMPLATE = """ - -.. raw:: html - - - -.. _{sphinx_tag}: - -Gallery -======= - -{toctree} - -{contents} - -.. raw:: html - -
    -""" - - -def create_thumbnail(infile, thumbfile, - size=275, - #width=275, height=275, - #cx=0.5, cy=0.5, border=4, - ): - '''Store a thumbnail from a PNG figure. - - For nonsquare images, pad them with the background color as estimated from - the top left corner of the image. - ''' - import numpy as np - - baseout, extout = op.splitext(thumbfile) - - im = matplotlib.image.imread(infile) - rows, cols, ncolors = im.shape - - if rows > cols: - tmp = np.empty((rows, rows, ncolors), dtype=im.dtype) - tmp[:] = im[0, 0] - diff = (rows - cols) // 2 - tmp[:, diff:diff + cols] = im - im = tmp - elif cols > rows: - tmp = np.empty((cols, cols, ncolors), dtype=im.dtype) - tmp[:] = im[0, 0] - diff = (cols - rows) // 2 - tmp[diff:diff + rows] = im - im = tmp - - #x0 = int(cx * cols - .5 * width) - #y0 = int(cy * rows - .5 * height) - #xslice = slice(x0, x0 + width) - #yslice = slice(y0, y0 + height) - #thumb = im[yslice, xslice] - #thumb[:border, :, :3] = thumb[-border:, :, :3] = 0 - #thumb[:, :border, :3] = thumb[:, -border:, :3] = 0 - - dpi = 100 - fig = plt.figure(figsize=(size / dpi, size / dpi), dpi=dpi) - - ax = fig.add_axes([0, 0, 1, 1], aspect='auto', - frameon=False, xticks=[], yticks=[]) - ax.imshow(im, aspect='auto', resample=True, - interpolation='bilinear') - fig.savefig(thumbfile, dpi=dpi) - plt.close(fig) - - -def indent(s, N=4): - """indent a string""" - return s.replace('\n', '\n' + N * ' ') - - -class TutorialGenerator(object): - """Tools for generating an example page from a file""" - def __init__(self, dirname, thumbs_dir): - self.dirname = dirname - self.thumbs_dir = thumbs_dir - - @property - def modulename(self): - return op.split(self.dirname)[-1] - - @property - def rstfilename(self): - return op.join(self.dirname, self.modulename + ".rst") - - @property - def htmlfilename(self): - return 'tutorials/{0}/{0}.html'.format(self.modulename) - - @property - def sphinxtag(self): - return self.modulename - - @property - def pagetitle(self): - return self.docstring.strip().split('\n')[0].strip() - - def create_thumbnail_if_needed(self): - '''Create a thumbnail except for animated GIFs''' - - # Make thumbnail for PNG images, for GIFs just pass through - animated_giffiles = glob.glob( - op.join(self.dirname, "figures", "*.gif") - ) - if len(animated_giffiles): - thumbfile = animated_giffiles[0] - else: - imagefile = glob.glob(op.join(self.dirname, "figures", "*.png"))[0] - thumbfile = op.join(self.thumbs_dir, self.modulename + '_thumb.png') - create_thumbnail(imagefile, thumbfile) - - # Thumbnail/GIF file without path - self.thumbfilename = op.split(thumbfile)[1] - - def extract_title(self): - '''Extract title from RST file''' - with open(self.rstfilename, 'rt') as f: - for line in f: - if set(line.rstrip('\n')) == set('='): - break - else: - raise IOError('Title not found') - title = next(f).rstrip('\n') - self.title = title - - def toctree_entry(self): - return " ./{:}\n\n".format(op.splitext(self.htmlfilename)[0]) - - def contents_entry(self): - return (".. raw:: html\n\n" - " \n\n" - "\n\n" - "".format(self.thumbfilename, - self.modulename, - self.title, - )) - - -def main(app): - source_dir = op.abspath(op.join(app.builder.srcdir, 'tutorials')) - thumbs_dir = op.join(app.builder.outdir, "_images") - - if not op.isdir(thumbs_dir): - os.makedirs(thumbs_dir, exist_ok=True) - - toctree = ("\n\n" - ".. toctree::\n" - " :hidden:\n\n") - content_dict = {} - - # Write individual example files - for filename in sorted(glob.glob(op.join(source_dir, "*", "*.rst"))): - print(filename) - - # Folder for this tutorial - dirname = op.dirname(filename) - - # Extract title for thumbnail alt/subtitle - ex = TutorialGenerator(dirname, thumbs_dir) - - # Extract title - ex.extract_title() - - # Make thumbnail if needed - ex.create_thumbnail_if_needed() - - # Generate toctree and content raw html code - toctree += ex.toctree_entry() - content_dict[ex.title] = ex.contents_entry() - - # Sort - content_list = ["\n\n"] + [content_dict.pop('Quick Start')] - for title in sorted(content_dict): - content_list.append(content_dict[title]) - contents = ''.join(content_list) - - # write index file - index_file = op.join(source_dir, '..', 'gallery.rst') - with open(index_file, 'w') as index: - index.write(INDEX_TEMPLATE.format(sphinx_tag="gallery", - toctree=toctree, - contents=contents)) - - -def setup(app): - app.connect('builder-inited', main) - diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 0844d2156..bb0c6b0b6 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -8,10 +8,10 @@ Tutorial ======== -This page is a detailed tutorial of |igraph|'s Python capabilities. To get an quick impression of what |igraph| can do, check out the :doc:`tutorials/quickstart/quickstart`. If you have not installed |igraph| yet, follow the :doc:`install`. +This page is a detailed tutorial of |igraph|'s Python capabilities. To get an quick impression of what |igraph| can do, check out the :doc:`tutorials/quickstart`. If you have not installed |igraph| yet, follow the :doc:`install`. .. note:: - For the impatient reader, see the :doc:`gallery` page for short, self-contained examples. + For the impatient reader, see the :doc:`tutorials/index` page for short, self-contained examples. Starting |igraph| ================= diff --git a/doc/source/tutorials/articulation_points/articulation_points.rst b/doc/source/tutorials/articulation_points/articulation_points.rst deleted file mode 100644 index 85ea30810..000000000 --- a/doc/source/tutorials/articulation_points/articulation_points.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-articulation-points: - -=================== -Articulation Points -=================== - -This example shows how to compute and visualize the `articulation points `_ in a graph using :meth:`igraph.GraphBase.articulation_points`. For an example on bridges instead, see :ref:`tutorials-bridges`. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Construct graph - g = ig.Graph.Formula( - "0-1-2-0, 3:4:5:6 - 3:4:5:6, 2-3-7-8", - ) - - - # Find the set of articulation points as a vertex sequence - articulation_points = g.vs[g.articulation_points()] - - # Plot graph - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()), - vertex_frame_color = ["red" if v in articulation_points else "black" for v in g.vs], - vertex_frame_width = [3 if v in articulation_points else 1 for v in g.vs], - edge_width=0.8, - edge_color='gray' - ) - plt.show() - - -The plot looks like this: - -.. figure:: ./figures/articulation_points.png - :alt: A visual representation of the articulation points in a graph - :align: center - - Articulation points are marked with a red border. - diff --git a/doc/source/tutorials/articulation_points/assets/articulation_points.py b/doc/source/tutorials/articulation_points/assets/articulation_points.py deleted file mode 100644 index 7839778b0..000000000 --- a/doc/source/tutorials/articulation_points/assets/articulation_points.py +++ /dev/null @@ -1,24 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -# Construct graph -g = ig.Graph.Formula( - "0-1-2-0, 3:4:5:6 - 3:4:5:6, 2-3-7-8", -) -# Find the set of articulation points as a vertex sequence -articulation_points = g.vs[g.articulation_points()] - -# Plot graph -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()), - vertex_frame_color = ["red" if v in articulation_points else "black" for v in g.vs], - vertex_frame_width = [3 if v in articulation_points else 1 for v in g.vs], - edge_width=0.8, - edge_color='gray' -) -plt.show() diff --git a/doc/source/tutorials/articulation_points/figures/articulation_points.png b/doc/source/tutorials/articulation_points/figures/articulation_points.png deleted file mode 100644 index 9e39177be782a38396c155536d87c30e0cc26f67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22137 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 graph, as well as a `Watts-Strogatz `_ random graph. - -First we import |igraph| and some libraries for plotting et al: - -.. code-block:: python - - import random - import matplotlib.pyplot as plt - from matplotlib.cm import ScalarMappable - from matplotlib.colors import LinearSegmentedColormap, Normalize - import igraph as ig - -Next we define a function for drawing a graph on an Matplotlib axis. We set the color and size of each vertex and edge based on the betweenness value, and also generate some color bars on the sides to see how they translate to each other. We use `Matplotlib's Normalize class `_ to ensure that our color bar ranges are correct, as well as *igraph*'s :meth:`igraph.utils.rescale` to rescale the betweennesses in the interval ``[0, 1]``: - -.. code-block:: python - - def plot_betweenness(g, ax, cax1, cax2): - '''Plot vertex/edge betweenness, with colorbars - - Args: - g: the graph to plot. - ax: the Axes for the graph - cax1: the Axes for the vertex betweenness colorbar - cax2: the Axes for the edge betweenness colorbar - ''' - - # Calculate vertex betweenness and scale it to be between 0.0 and 1.0 - vertex_betweenness = g.betweenness() - edge_betweenness = g.edge_betweenness() - scaled_vertex_betweenness = ig.rescale(vertex_betweenness, clamp=True) - scaled_edge_betweenness = ig.rescale(edge_betweenness, clamp=True) - print(f"vertices: {min(vertex_betweenness)} - {max(vertex_betweenness)}") - print(f"edges: {min(edge_betweenness)} - {max(edge_betweenness)}") - - # Define mappings betweenness -> color - cmap1 = LinearSegmentedColormap.from_list("vertex_cmap", ["pink", "indigo"]) - cmap2 = LinearSegmentedColormap.from_list("edge_cmap", ["lightblue", "midnightblue"]) - - # Plot graph - g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] - g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) - g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] - g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) - ig.plot( - g, - target=ax, - layout="fruchterman_reingold", - vertex_frame_width=0.2, - ) - - # Color bars - norm1 = ScalarMappable(norm=Normalize(0, max(vertex_betweenness)), cmap=cmap1) - norm2 = ScalarMappable(norm=Normalize(0, max(edge_betweenness)), cmap=cmap2) - plt.colorbar(norm1, cax=cax1, orientation="horizontal", label='Vertex Betweenness') - plt.colorbar(norm2, cax=cax2, orientation="horizontal", label='Edge Betweenness') - -Finally, we call our function with the two graphs: - -.. code-block:: python - - # Generate Krackhardt Kite Graphs and Watts Strogatz graphs - random.seed(0) - g1 = ig.Graph.Famous("Krackhardt_Kite") - g2 = ig.Graph.Watts_Strogatz(dim=1, size=150, nei=2, p=0.1) - - # Plot the graphs, each with two colorbars for vertex/edge betweenness - fig, axs = plt.subplots( - 3, 2, - figsize=(7, 6), - gridspec_kw=dict(height_ratios=(15, 1, 1)), - ) - plot_betweenness(g1, *axs[:, 0]) - plot_betweenness(g2, *axs[:, 1]) - fig.tight_layout(h_pad=1) - plt.show() - -The final output graphs are as follows: - -.. figure:: ./figures/betweenness.png - :alt: A graph visualizing the betweenness of each vertex and edge. - :align: center - - Vertex and edge betweenness in a Krackhardt Kite graph (left) and in a 150 node Watts-Strogatz graph (right). Edge betweenness is shown in shades of blue and vertex betweenness in shades of purple. - -and the output for betweennesss is as follows: - -.. code-block:: - - vertices: 0.0 - 14.0 - edges: 1.5 - 16.0 - vertices: 0.0 - 1314.629277155593 - edges: 1.0 - 628.2537443550603 diff --git a/doc/source/tutorials/betweenness/figures/betweenness.png b/doc/source/tutorials/betweenness/figures/betweenness.png deleted file mode 100644 index b411178047762446780ffbe7d96b19a558572a12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114355 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

    G(Y$#Y@6|420Iyra#?}6rWQ+%zShZ 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 z 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 diff --git a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst b/doc/source/tutorials/bipartite_matching/bipartite_matching.rst deleted file mode 100644 index 0464a7e48..000000000 --- a/doc/source/tutorials/bipartite_matching/bipartite_matching.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-bipartite-matching: - -========================== -Maximum Bipartite Matching -========================== - -This example demonstrates an efficient way to find and visualise a maximum biparite matching using :meth:`igraph.Graph.maximum_bipartite_matching`. First construct a bipartite graph - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Assign nodes 0-4 to one side, and the nodes 5-8 to the other side - g = ig.Graph.Bipartite( - [0, 0, 0, 0, 0, 1, 1, 1, 1], - [(0, 5), (1, 6), (1, 7), (2, 5), (2, 8), (3, 6), (4, 5), (4, 6)] - ) - assert g.is_bipartite() - - matching = g.maximum_bipartite_matching() - -Then run the maximum matching, - -.. code-block:: python - - matching = g.maximum_bipartite_matching() - - # Print pairings for each node on one side - matching_size = 0 - print("Matching is:") - for i in range(5): - print(f"{i} - {matching.match_of(i)}") - if matching.is_matched(i): - matching_size += 1 - print("Size of maximum matching is:", matching_size) - - -And finally display the bipartite graph with matchings highlighted. - -.. code-block:: python - - fig, ax = plt.subplots(figsize=(7, 3)) - ig.plot( - g, - target=ax, - layout=g.layout_bipartite(), - vertex_size=0.4, - vertex_label=range(g.vcount()), - vertex_color="lightblue", - edge_width=[3 if e.target == matching.match_of(e.source) else 1.0 for e in g.es], - edge_color=["red" if e.target == matching.match_of(e.source) else "black" for e in g.es] - ) - plt.show() - -The received output is - -.. code-block:: - - Matching is: - 0 - 5 - 1 - 7 - 2 - 8 - 3 - 6 - 4 - None - Size of maximum matching is: 4 - -.. figure:: ./figures/bipartite.png - :alt: The visual representation of maximal bipartite matching - :align: center - - Maximum Bipartite Matching diff --git a/doc/source/tutorials/bipartite_matching/figures/bipartite.png b/doc/source/tutorials/bipartite_matching/figures/bipartite.png deleted file mode 100644 index d5660dc5e740a788e91fd1713db983883624c35d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21719 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 Xf(EW9CJ#p-WRzrYz2BHGrx@HmTWIIGy1 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 diff --git a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py b/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py deleted file mode 100644 index c49327db9..000000000 --- a/doc/source/tutorials/bipartite_matching_maxflow/assets/bipartite_matching_maxflow.py +++ /dev/null @@ -1,45 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -g = ig.Graph( - 9, - [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], - directed=True -) - -# Assign nodes 0-3 to one side, and the nodes 4-8 to the other side -g.vs[range(4)]["type"] = True -g.vs[range(4, 9)]["type"] = False - -# Add source and sink as nodes 9 and 10 -g.add_vertices(2) -g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side -g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other - -flow = g.maxflow(9, 10) -print("Size of maximum matching (maxflow) is:", flow.value) - -# Compare this to the "maximum_bipartite_matching()" function -g2 = g.copy() -g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded for this function. -matching = g2.maximum_bipartite_matching() - -matching_size = sum(1 for i in range(4) if matching.is_matched(i)) -print("Size of maximum matching (maximum_bipartite_matching) is:", matching_size) - -# Manually set the position of source and sink to display nicely -layout = g.layout_bipartite() -layout[9] = (2, -1) -layout[10] = (2, 2) - -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - layout=layout, - vertex_size=0.4, - vertex_label=range(g.vcount()), - vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], - edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] -) -plt.show() diff --git a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst b/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst deleted file mode 100644 index 5034878cb..000000000 --- a/doc/source/tutorials/bipartite_matching_maxflow/bipartite_matching_maxflow.rst +++ /dev/null @@ -1,85 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-bipartite-matching-maxflow: - -========================================== -Maximum Bipartite Matching by Maximum Flow -========================================== - -This example presents how to visualise bipartite matching using maximum flow (see :meth:`igraph.Graph.maxflow`). - -.. note:: :meth:`igraph.Graph.maximum_bipartite_matching` is usually a better way to find the maximum bipartite matching. For a demonstration on how to use that method instead, check out :ref:`tutorials-bipartite-matching`. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Generate the graph - g = ig.Graph( - 9, - [(0, 4), (0, 5), (1, 4), (1, 6), (1, 7), (2, 5), (2, 7), (2, 8), (3, 6), (3, 7)], - directed=True - ) - - # Assign nodes 0-3 to one side, and the nodes 4-8 to the other side - g.vs[range(4)]["type"] = True - g.vs[range(4, 9)]["type"] = False - - g.add_vertices(2) - g.add_edges([(9, 0), (9, 1), (9, 2), (9, 3)]) # connect source to one side - g.add_edges([(4, 10), (5, 10), (6, 10), (7, 10), (8, 10)]) # ... and sinks to the other - - flow = g.maxflow(9, 10) # not setting capacities means that all edges have capacity 1.0 - print("Size of maximum matching (maxflow) is:", flow.value) - -Let's compare the output against :meth:`igraph.Graph.maximum_bipartite_matching`: - -.. code-block:: python - - # Compare this to the "maximum_bipartite_matching()" function - g2 = g.copy() - g2.delete_vertices([9, 10]) # delete the source and sink, which are unneeded - - matching = g2.maximum_bipartite_matching() - - matching_size = sum(1 for i in range(4) if matching.is_matched(i)) - print("Size of maximum matching (maximum_bipartite_matching) is:", matching_size) - -And finally, display the original flow graph nicely with the matchings added - -.. code-block:: python - - # Manually set the position of source and sink to display nicely - layout = g.layout_bipartite() - layout[9] = (2, -1) - layout[10] = (2, 2) - - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout=layout, - vertex_size=0.4, - vertex_label=range(g.vcount()), - vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], - edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] - ) - plt.show() - -The received output is: - -.. code-block:: - - Size of maximum matching (maxflow) is: 4.0 - Size of maximum matching (maximum_bipartite_matching) is: 4 - -.. figure:: ./figures/bipartite_matching_maxflow.png - :alt: The visual representation of maximal bipartite matching - :align: center - - Maximal Bipartite Matching - -.. note:: - - Maximum flow will represent the capacities as real values, which is why our result is ``4.0`` instead of ``4``. diff --git a/doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png b/doc/source/tutorials/bipartite_matching_maxflow/figures/bipartite_matching_maxflow.png deleted file mode 100644 index d70f1389f79e33fd11fbf36f1721190188f34d85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18396 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 Jmvv4FO#m;HoF4!H diff --git a/doc/source/tutorials/bridges/assets/bridges1.py b/doc/source/tutorials/bridges/assets/bridges1.py deleted file mode 100644 index 50c2c19f7..000000000 --- a/doc/source/tutorials/bridges/assets/bridges1.py +++ /dev/null @@ -1,25 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -# Construct graph -g = ig.Graph(14, [(0, 1), (1, 2), (2, 3), (0, 3), (0, 2), (1, 3), (3, 4), - (4, 5), (5, 6), (6, 4), (6, 7), (7, 8), (7, 9), (9, 10), (10 ,11), - (11 ,7), (7, 10), (8, 9), (8, 10), (5, 12), (12, 13)]) - -# Find and color bridges -bridges = g.bridges() -g.es["color"] = "gray" -g.es[bridges]["color"] = "red" -g.es["width"] = 0.8 -g.es[bridges]["width"] = 1.2 - -# Plot graph -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()) -) -plt.show() diff --git a/doc/source/tutorials/bridges/assets/bridges2.py b/doc/source/tutorials/bridges/assets/bridges2.py deleted file mode 100644 index be4160f31..000000000 --- a/doc/source/tutorials/bridges/assets/bridges2.py +++ /dev/null @@ -1,32 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -# Construct graph -g = ig.Graph(14, [(0, 1), (1, 2), (2, 3), (0, 3), (0, 2), (1, 3), (3, 4), - (4, 5), (5, 6), (6, 4), (6, 7), (7, 8), (7, 9), (9, 10), (10 ,11), - (11 ,7), (7, 10), (8, 9), (8, 10), (5, 12), (12, 13)]) - -# Find and color bridges -bridges = g.bridges() -g.es["color"] = "gray" -g.es[bridges]["color"] = "red" -g.es["width"] = 0.8 -g.es[bridges]["width"] = 1.2 - -g.es["label"] = "" -g.es[bridges]["label"] = "x" - -# Plot graph -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()), - edge_background="#FFF0", # transparent background color - edge_align_label=True, # make sure labels are aligned with the edge - edge_label=g.es["label"], - edge_label_color="red" -) -plt.show() diff --git a/doc/source/tutorials/bridges/bridges.rst b/doc/source/tutorials/bridges/bridges.rst deleted file mode 100644 index 3505864d8..000000000 --- a/doc/source/tutorials/bridges/bridges.rst +++ /dev/null @@ -1,84 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-bridges: - -======== -Bridges -======== - -This example shows how to compute and visualize the `bridges `_ in a graph using :meth:`igraph.GraphBase.bridges`. For an example on articulation points instead, see :ref:`tutorials-articulation-points`. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Construct graph - g = ig.Graph(14, [(0, 1), (1, 2), (2, 3), (0, 3), (0, 2), (1, 3), (3, 4), - (4, 5), (5, 6), (6, 4), (6, 7), (7, 8), (7, 9), (9, 10), (10 ,11), - (11 ,7), (7, 10), (8, 9), (8, 10), (5, 12), (12, 13)]) - - # Find and color bridges - bridges = g.bridges() - g.es["color"] = "gray" - g.es[bridges]["color"] = "red" - g.es["width"] = 0.8 - g.es[bridges]["width"] = 1.2 - - # Plot graph - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()) - ) - plt.show() - - -The plot looks like this: - -.. figure:: ./figures/bridge1.png - :alt: A visual representation of the bridges in a graph - :align: center - - Bridge edges are marked in red. - -Advanced: Cutting Effect --------------------------- -Bridges are edges that when removed, will separate the graph into more components then they started with. To emphasise the removal of edges from the graph, we can add small "x" effect to each of the bridges by using edge labels. We add the following code to define the edge labels only for bridges: - -.. code-block:: python - - g.es["label"] = "" - g.es[bridges]["label"] = "x" - -And then when we plot... - -.. code-block:: python - - # Plot graph - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - vertex_size=0.3, - vertex_color="lightblue", - vertex_label=range(g.vcount()), - edge_background="#FFF0", # transparent background color - edge_align_label=True, # make sure labels are aligned with the edge - edge_label=g.es["label"], - edge_label_color="red" - ) - plt.show() - - -As a result, we get: - -.. figure:: ./figures/bridge2.png - :alt: A visual representation of the bridges in the graph - :align: center - - Bridges marked with an additional "x" effect. - diff --git a/doc/source/tutorials/bridges/figures/bridge1.png b/doc/source/tutorials/bridges/figures/bridge1.png deleted file mode 100644 index 506ca03a1591d1a29a4ea4df95ac0462e126b15f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31005 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 TyIX;yiYbQMcheqjvk(7&J=@5$ diff --git a/doc/source/tutorials/bridges/figures/bridge2.png b/doc/source/tutorials/bridges/figures/bridge2.png deleted file mode 100644 index 5099207cfd158db7d05123dd8c14aa0bdb896da4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31782 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 WPxAf&*(LaM20!m4@NR99pWR`_. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Load the graph - g = ig.load("./lesmis/lesmis.gml") - -First, let's visualise the original communities, using :meth:`igraph.Graph.community_edge_betweenness` to separate out vertices into clusters. (For a more focused tutorial on just visualising communities, check out :ref:`tutorials-visualize-communities`). - -.. code-block:: python - - # Generate communities - communities = g.community_edge_betweenness() - communities = communities.as_clustering() # Convert into a VertexClustering for plotting - - # Print them out - for i, community in enumerate(communities): - print(f"Community {i}:") - for v in community: - print(f"\t{g.vs[v]['label']}") - - # Set community colors - num_communities = len(communities) - palette1 = ig.RainbowPalette(n=num_communities) - for i, community in enumerate(communities): - g.vs[community]["color"] = i - community_edges = g.es.select(_within=community) - community_edges["color"] = i - - g.vs["label"] = ["\n\n" + label for label in g.vs["label"]] # Move the labels below the vertices - - # Plot the communities - fig1, ax1 = plt.subplots() - ig.plot( - communities, - target=ax1, - mark_groups=True, - palette=palette1, - vertex_size=0.1, - edge_width=0.5, - ) - fig1.set_size_inches(20, 20) - fig1.savefig("../figures/communities.png", dpi=200) - - -Now let's try and contract the information down, using only a single vertex to represent each community. We start by defining attribute values for each of the nodes in the original graph. - -.. code-block:: python - - # Assign x, y, and sizes for each node - layout = g.layout_kamada_kawai() - g.vs["x"], g.vs["y"] = list(zip(*layout)) - g.vs["size"] = 1 - g.es["size"] = 1 - -This is so we can define how each of these attributes get combined together when we call :meth:`igraph.VertexClustering.cluster_graph`. - -.. code-block:: python - - # Generate cluster graph - cluster_graph = communities.cluster_graph( - combine_vertices={ - "x": "mean", - "y": "mean", - "color": "first", - "size": "sum", - }, - combine_edges={ - "size": "sum", - }, - ) - -Here, we take the mean of x and y values so that the nodes in the cluster graph are placed at the center of the original cluster's position. - -.. note:: - - ``mean``, ``first``, and ``sum`` are all built-in collapsing functions, along with ``prod``, ``median``, ``max``, ``min``, ``last``, ``random``. You can also define your own custom collapsing functions, which take in a list and return a single element representing the combined attribute value. For more details on |igraph| contraction, see :meth:`igraph.GraphBase.contract_vertices` - -Finally we plot out the graph using our calculated attributes: - -.. code-block:: python - - # Plot the cluster graph - palette2 = ig.GradientPalette("gainsboro", "black") - g.es["color"] = [palette2.get(int(i)) for i in ig.rescale(cluster_graph.es["size"], (0, 255), clamp=True)] - - fig2, ax2 = plt.subplots() - ig.plot( - cluster_graph, - target=ax2, - palette=palette1, - # set a minimum size on vertex_size, otherwise vertices are too small - vertex_size=[max(0.2, size / 20) for size in cluster_graph.vs["size"]], - edge_color=g.es["color"], - edge_width=0.8, - ) - - # Add a legend - legend_handles = [] - for i in range(num_communities): - handle = ax2.scatter( - [], [], - s=100, - facecolor=palette1.get(i), - edgecolor="k", - label=i, - ) - legend_handles.append(handle) - - ax2.legend( - handles=legend_handles, - title='Community:', - bbox_to_anchor=(0, 1.0), - bbox_transform=ax2.transAxes, - ) - - fig2.set_size_inches(10, 10) - fig2.savefig("../figures/cluster_graph.png", dpi=150) - -The two figures are shown side by side here: - - -|pic1| |pic2| - - -.. |pic1| image:: ./figures/communities.png - :width: 45% - -.. |pic2| image:: ./figures/cluster_graph.png - :width: 45% - -... and the final output of the communities we printed out are displayed below: - -.. code-block:: - - Community 0: - Myriel - Napoleon - MlleBaptistine - MmeMagloire - CountessDeLo - Geborand - Champtercier - Cravatte - Count - OldMan - Community 1: - Labarre - Valjean - MmeDeR - Isabeau - Gervais - Bamatabois - Simplice - Scaufflaire - Woman1 - Judge - Champmathieu - Brevet - Chenildieu - Cochepaille - Community 2: - Marguerite - Tholomyes - Listolier - Fameuil - Blacheville - Favourite - Dahlia - Zephine - Fantine - Perpetue - Community 3: - MmeThenardier - Thenardier - Javert - Pontmercy - Eponine - Anzelma - Gueulemer - Babet - Claquesous - Montparnasse - Brujon - Community 4: - Cosette - Woman2 - Gillenormand - Magnon - MlleGillenormand - MmePontmercy - MlleVaubois - LtGillenormand - BaronessT - Toussaint - Community 5: - Fauchelevent - MotherInnocent - Gribier - Community 6: - Boulatruelle - Community 7: - Jondrette - MmeBurgon - Community 8: - Gavroche - Marius - Mabeuf - Enjolras - Combeferre - Prouvaire - Feuilly - Courfeyrac - Bahorel - Bossuet - Joly - Grantaire - MmeHucheloup - Community 9: - MotherPlutarch - Community 10: - Child1 - Child2 - - diff --git a/doc/source/tutorials/cluster_graph/figures/cluster_graph.png b/doc/source/tutorials/cluster_graph/figures/cluster_graph.png deleted file mode 100644 index 13614fa1a98b8f9c99592d9ca6003a84b4eb5de6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101457 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"O4u;@a!woLiR8S42=?xS(5md4 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

  • Ihm-h)cmh^4 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

    DxF3qNu za{)WL*HbT_85W#EbaCHFVJKsOMhARzRMW~C-VsE#ZA5RyYAL*s|2+N^I};Nt4!V4m zwIlM)hjC|KQG7IAw-I_7bBmPtbP<)+AD!Gh|FqM({eLsOAKRwTO9;O=%dZh&GEJ7s z$VkJ6QcZzhuVGf3=QO2z`SCB^mO8*0<^1&YMTraw#)Q4a=X=oeE^z=6;p`Du3Zt~j z=^Io%pvS?(@zUm{dGxcbv%DLfT=!hYy&j!DFBx`+td)R-;Ji63$GYlUu{$r!4A$P> z2XUg2qa#R$3)R1_yjaxXfE0p5p6d{bu-hY?T>Kb3rYCg_4ezkxD6{T zzsCFDyS}h=-``^jZ0%IipPkiP9TdUUtsHyJ5bNshm$r5{KArs*-?&nJVgM5s2H2$)(!&Hs2xVxc-^{g};z?2o1q3X@UI6ggZmC5Cb_ z<&A_WMZu2 z)8lTDe*(?4|3Cd+rp}6fLV<2impL{eI&x5F$t?;Xgf&xHWA(v0A?rJV zyN)LQ@cTP2_fnWTN>WhIxPKf=%KZ3rzVZ~~6+l$m2c8b$Rx}`Zj~rPk_r*5@-Tr3+fR|y+K*!9iAhaAiHdr)x!{e_oj}1GM4}yg zL)F1hWPk#AxAYO29h^5(K$ziK>Q)%v>EexNQ&GW z=fieP2x#i~&>4uJwWNQ>QM&YGZQ(aLCPR*xl?@nFOwR9V>sFlH# zX~h+k$X(q9irp`+#&=C#Op}xu*9o0ucOfeu1r3=l=ASHR1Yb6*tlM`u8Hn-<3~e4C zf*no!=Or?SKRP8g<_pgzg8@^9|12{i-nqWv^Hkt=9z@?{JIN;F4WMtC4EFGQ7N^dumzUS|ls=0;9rYcxy$QiXWt$<#><3E}!L zi*}a3EeJ~mLPHWdpx0C;BCL(?FgT`68;iuoC{^*{y-z3|B;(`1teV%SgG6GHw|#9! zhE9%q0*3|O|4rO;t9~I%wq8cQRHM_jT#7cHJcN0NZ-jEebmGAqnG`_RGyJ^B zT~I5g4lmv*zmk<);3pYhB25KG^Juct(Q*Zr-jBtFGyC>tc0h$~y;keWu(3|c-4aNF z_Uaz^z9xLRv_NWNLNvF|+;BP2o{ujq&elXqM1*8i=PU=0@S3i5zz}SU(4@|{Ts|x3 zKaUStW=`ap8tGM{4j5gA9J(E}o$+w}lSXvax0~7u{uCa!?RoN3LD!yyK?9#E=!BPI z;)l9-!Lgon%#ky_tKMTi*v9O06{ny_u`D1Wrvf;AOH42xXMB*7frEC^|3}ta21L0< z`@@9Np&%hKfRsv0cPSl;N=bttf^;|1(jWp7BZm^nA*4G7BnCkV=^T(8a)1He%{kX| z|M$G}0S5Jh%-+x5YyE1aT4Xfz6m5(F5ZDiVjVmkjA^(NOC(fZCqx|Njp41V6i{iD4D`#Y9T>-|CVMfQ07 zs~Tmyy@%ym+S9vMCO1SPS+H z_?$RSJGhEym#AgVcVJcCc=BQA6j`hC3_RDl}OKi@A`rAQEKJKd-w-MCzRsX3C^g5_DRX?@w}B!LsO9W@(1iASKAuPmE)f3Fp#uV1a4-ggjm3VJk9aR)mFHAB^qk| zUv@Lmu$P}mV)tV~dXt0-*TH8C^Iddkj)%KkdBECCn$H$0tC!^!Vry)8S0%IcP#v3TiR?v!iQRZXOMh4sDV);-?8CRma9?Qq#e z61xT74h9=!ffgvmIxTb;I4mL(hW24M>QzmIKAGHjHs{VT&(vWbu3xT%MNj=3j`Led zD9vPd3|N}#Ja)=#@pO%h;$k}u4v++8&3+D>)6YdacMID-FK;pW5%@_EJJiw2c#~r; zuxQ8wg3{G9e-!Vqrc62WGv}0N#A;nLFj_!y$amP^8IX93iH#>0m<*Pe-t#6QP*OI8 z4bu{90v#f?RxI8?hItMP-cjgu{H;j0EJS-H`SoE<1@s9Hc{vUTpb0}R1y<|tku(Cw zYmO7luCj8k_uDtim3K8w0_JqhXON+(9oe>kv*%4uPeE6OY!ckDSzrpJ@eY`2C~Z1i z74_S_AOZ2w=2~JfNtO?So<|(K^k~YBaZR2F0Y7Coyg}dVWiwLick%Ns*qC|KHL{sf zAuld=yhR+QO*W0TO*hbIEJ`#k)7NP+POaVwvfpo(T&@eR`t!{*a2s+LmOD(_wm z=RYTg?kqaBrKu)99yzeBcs$cG_+`OK)5gcEN!GGV zRN6bem{laS-#0u7W=mBSX)|GxBTo*C&;upAu3_@f{)AX{Z(7JNk)?FxW&9{UL~*o$ zJ55G|@_e00qfSu!7gJrD&dGv{#!miDA3%pxb+51Y4n@s^UbJJ0(1b$VOO@f@|* zb|5|1hs$XAlI3!ws6jPa(#3VYWkK<_$G8~-nXf%&guR${ct-?0^Fsxil3wNq5!0@h z2^8b!7mfAP-c#yn1yP;m$lwUxg~4`mDBf8Y#%W9fa-ozdUS zcQeuddk8DS`Zo=<>bIk8RbY5AA|iFR)Q8}_*1+jx@_IazH%85{=CzJ}W^mOzs{h6L zoBxAZ6tT=SxaayFZ$HW=j_BN+u1}V|K!@b3r{YxDj&cl1?Q0Zhq<36i9JgA%H#ASY zQ9_?Qo#!UUIb>(}SzSUqu~T!|h09hdIz`FZ*i!q3l>pvt{a4wbf+p0ZOYS)F@}|MZ zwV?i4GY`Sd`-YZ6 z2}>76TbCMq&6;5D(VW?Yaft1&YHUS5>H2ALNsrfqsdF-_g&v9%bDO2yV?7%b2*X%>@A9o^)#i5BI3TlLi1^Y7Hg#buEQ61vD_d47} zj3VfGF3ZFMOPYbqwNn^DL8jc$pzU)kqs8Q9A9d(1Q$jl0;`?zs!uapaasIPt+W9z4 z$nHZODeuFFuXCBz3F{;FJJ>jFj)hTPI2z})L*fu6?MQp6XHORRHE4-h9q_depfQEn z0YZAlu0Byqntm|LkoOeuf1mnIyZ_(fb3*+dbViW#fgAzZ^R5#l6cKoNu6*~_;_u>e z>z`kqPi!6OluuG_5`B6a!Z;k|@mc-h+Du14-oBeqXaMngOpn5$q6H`plJz*JZ$}Un z^Ich74B39%k4ot<^YaUfpaEEtLJ1J^8yN+M`KT86w^7en2i9rkWPiG#?}-C~H>QQE?qKh!+Lo6|(!hX_7QGiqdCd8HQu?nj zV45P^n)otc$3P|t{PgZc$askcR(!}rLg3}hHMx**JkJ?pAN)PRAt|zmB|=cGfMY;i zODiC;>^BxP@JKN5{DcXsFw0q^2%KSb!e8K|qFIB@p0TVq2*CWV(faiduKi6)53Nki zEf$fkd)^Q({O`3$Ck}0cL2;Yu2>8-ct-)|1<+Ky0ksFoJL~BgF2HI9a>hK2ULDl@p z1*eDQNaL|3?ETSxq3r4GhvC@we`hqOS$waT6tvrfig9yzs+vFhO+E7(sm_%eOvwfGQ6)bFIK0C;)*prZ#=hVfuqJvdjrH{v zv;Xn-`gL>n5E7D@I~y980VbPXyD!adNgKbpchBkQ(eAgZ8wA%*R*>D99;X7KeJlh2 zh=VDu8G$rnoZiYThfw#U#S%ZaP;}UUdIR*W-j#Q!rz<`(; zUj2wWNM`;Au9Jk?j>CqFxGex1`cq5Wg*1WALcb*3_Gw@=BUBcRelR|p?>X0L3716} zUil>n%oaJJHmH4eEiHJrJMF}JpaO1z|M4wFUa!!f#Uk^45l@ag1zA7M-E(@VEq1`) zTSA<}TyjBAJruS+I$uupXuNLkQwYiDGn2XHU^J?=m|4Xs({)b}Olm`P% zRr^2i7}UI`!ctG=ExnHICYq4uu>7(-<869d*@iA%V$bNZ6RY^Nngqfu$Dw1a_#Vpz zP7}bGzyU4p;bXqUzvqpU{HE@1}#571x>BHP`Vwh`Yx;IxppzzS)ACDdna!-9aI;`z24 z14U0!n(2Rf<&Uj_mD5)s9*?h@}gick56|Tppg9_I-<`f(QM-xkuOlv*63-K0a zrMnE^x?A0rG+8L-3k1VefjYDFMb$S(VE;{O-M*z;>(I`D#VEn>WE<^sNYrCvgQSwY zoZ?frgfj)Aab*WExzplRRYa>Nj$5lPa8N950e4CKLa6?uzjaf0kiL+~;Cf=yrEE#l zg%uiEu(UYXXcx8RQmMfgLW}u&j=4K1n8*;Zg}m)dj~;e>@=JWp+FUxH;6ZpbOVyjyG z^KEd52#wEqQ9F2k=a*w+czZ9e zV6yFx&!1Q~Ruq|*2BS=|`L_=x>%7)f*@uz|!c60-`t>T@iSzQN4RXd67vXJf-9ML| zgsDH87ur;+e-Qu#Qu=oUG(?R7IKr%yqq2S|maw!jQ1ksF3i?U3MOhu809Tm&u@YS( zCeBLtz%e|91Ewju*r#UK_6TTyaMomGSfJm<)|Bse@*fmJYQj~?Ub?rG^Ss5V%7Ag6 zB1f6Aiub8xE>DZ+#Lo_VQ71SlhLWP3td5t`%fwwGd6NXi<1p2YO=ZE#a}?px={1 zNFOuQPP-82JVwnw)77OmFfb_5hrK1F+sJ5ARy!ZxlLB&{rJH%e281 zKRwx-;lvR(Zcj4K$K{|WY7WOV!yVPe1Wp^k@H2NNIIa(ebi(f?ES=hI_e}33o zJiNhzqO#&OyJ5}6F(q*K($&G#+^qYP4E66+iJoL%mWsG)Hx<>#PuEXLiQ@KMKQ1hG zba6k645p%IB&fVWd+lLEk8gTtDoRY8m}cCI9R!l%g zae~|P!gxF-f0vs&cd`9sWb;D0rc$AOQ8ptga+6p?!>v;2G6I~6SEd|#egDz|Y&S4GJ``nI8E`HlbF%n^`@`GE zg`?~91Fk*-0n;>CP5WcDZd)GGwo-uO}^ z>%Q&uXK{JQexhawg{=A4#RW}rf6hf=A4@|YvABe* zafjZ(%j+f+Q&IA5aX@^byG`6Cl^RQa=wZI=y>z|qa&scVHv!o zmGxqOhCH{g_inSDx7PKBY`qVCLv=$)kHW6)^;++8r-=o2&uz`Tj*O$o$RBtd-peR4 z>;SefVpa3IcvMrjtd1N57g6Z-sd7rqk7K!=IXp|cdO?#gOHSXO)}?dZSm zAl_@FhBXcy^p11twcA_KnU_v`B%muK2$o9#XvM-zZR<)$wDz^Ow&!`cr=h5)mgXBV zB%<-M?xZxN;x`+c*UBH+Xh0G9G_h6yt@4xJ^2`p{lXjpN`P`eGJhF>n7G9xv7hZjsX(|5$xVygp&pdPwMefsrKetyT^-x ze`et&4$DOk-0I3AA-b@9Kvyik$fe;?x)B6fcD$mi?ra{gr`T0IZZ&ibxSVO4Kp7vK zJhMhK%mak?ON|MT#l~#-or#vv5Px!f>C_)0?@L7#y;+B-8rm3|D!R|7HUi-v9UYy7x!X)B20k zjp!z0->n)Wr}pb^n-huKGmQYXea%cE0~NB>sTpeoC-&99QYVGtf+6csj;-e(lw#?y zcNe4idKwCL9DaO$f;q9tWA(PS=BTnBv>5&*uOIU^XthkPZfa{0(|+#t62tfscx3QD z>+xmn1kf6D`;j>T33dHNPnAXdoGcS9QqFU-CZmZ&WRBvFIlD&%n<7 zeMdxLcG^r{+zz$H17}**BPQgXEw}h9Mp#6?-YJiGW}1+XKB1#YHD@8kFEm?W-t*=i zLm7S>KiL(5Ej`+&tm^4dIJ5p?r3dJ2EG}=UaOjS+Yk3ENcV=^qH^od23vBXw;y{WM zuP0{l(Ph_5O_XU&f%dklv(7ssT_121u5O2MF1Z|1vY5vMTMTio`5^3mKIm`aD zhP|`@nZJ`r_rUkaz9;7P)8#jt6R@W9qbY6^20}hzhv~F<*^9JznbXK0KYqAa$HWf| zXn;qOpe>w~UcbT37A7DAjTf-&>4L}}O;|Gc?Y3jl-rBY@Jel9CXyp5(nmlqj9N3$W zYXNt);frUa0k^F==9$O#!1Z~cW-9cJuas1)b)3s2j(8|h}o zH&K$wEwPMKue2qANkzPVT6y9CH9IxeJw)D6!PKYwYvZQXO=!pqNlw)v}5svA^v!B|G0}^+~IUj_T)k6*kyS2%K(M3){wY$yD%0MHf$_n3`mBf7!i@WJ^+w^fTdzUzk{z$Fl^M zrhMed34A5AlLLNmzs20Z{W=ijZZ3z`A^84Wl{)_&eN~A+Sz(TAljTlLW9)WQ(ql7n zswqR%adlK%b_E4zLJmppEQixO+#QMXAIcPm!HB83?|Ph3npYF6);neJLU4-mC>p3J@g=H@#Vt}{-+R#P=?DXeaqUOEZdjXU6ddXnqIFjuY~Hm037ViM0B4f_u3 zvis&Mo%b8#ry03YR|mnh+w`Vq1YtAeO9aUoT|{>ApbLk;j>QypPL<0u-J)eDAp5|v0wkIy=IYX)4}4c54;A(CmoL-zE(-gT7E#nw6nBG z2eik*#cHmamjQ%XZt~fyo5_&&$db)rL#X z?}y&CKpBR~`8Q)<&>C65FH2{1HvP_y2CurPG}#?(7guRNiI>z! za^5uu2PFT9SK2WrX|%NG_NNy8(lHCypVdhw$d@Wc z@g=j~WqCTY2Ust>yi;V98cJlB3K}}6-|NbPpoyBS#-4=|&=^5lPvEh5j&9{q(R{aq zri^PoJ$o5Cp~72hzS!NJ;zg^Nrm6obZMTNqSwkUh*AG__%SClgyn!zc{jp zuiP#zU`rot`-+XWW<=P2G?IFCjVbWr?%+q^$XG%=MJd@+#qIi~mzi3UGNzfH3pZ{? zg)sN`tzfrl1FJH!;y$9rU0o!arfi|-#U)McsRwGG%3K6%{!^<6*1z(s$=Lsr3acKC z>%%#?j1q2U;NCk}`yK*T9cI->;ZVOqZ4!8Xcz^Khr=F?v>3ZSP{>goJV=XN$7*gcT zuUnE10DDYy{ka~Loo)c*_3-eO|15cf;L*6d`67$x_|wl^5;1{?(P}@jDlC;zzTqk~ z2PgX%*XFZoTX-ns@CnW&P~G@ik$4OE#`>`Bji_fA8v>lCx((p2E0Q8l=I>)oDOQtm z%)#d61^HWI;@7!&UVm*fTx+~#Pkm4jdDE@HfXy>~@CdKK?II9pUIZ*+^UFnmUZZ>k7)P?2EI#2w$nMaCR z%aes1`^axKSG+;}E4KJ}zi3dtCMPYLfw~)nUEu_QA4e~{9HfMQ&(xJLTHNM%Q866r zg*S|Sr6NSaX9q~fr4;YpS_P=c(uQs8=taURuvoo2AQ8>>)UG5k(=kppU|W%MBG*fT@Zu&K)dr7{*J4xvA^O;rb*&AFn^BpJHEK;mBjyR z7P{i0aWpeTR)X;%k3<1vfq1*FLi+ABvbcdgGv>U?fo`)e@NvDKCT%@pME zpjtn*)jjd)$S{o&fXQlBJjN%+zhU)6Vf;gvU>{x^vvgm|!%%%q&nC)VURC{@gz zIy!;nqA(<0#y1o+sa@GGK-awk3T#J>G-_ffllwuA257E~cx|S~js$T-&iOyn*NPK2 zZoaz|ILzR*b$u*|1z118K{g!^9XFls+5F8fUv5p`k(Ff_$+_;nk%Dpl-VA4nVf3`y zv>}g&!&6N$-|Wi$hLo8GtoBzKg&dlgpc?)q`uOfQ6RjSglHtkA`)p)dce1|!B!l7( zq_u=@OOtnOX+?6YhiBloDixU49#J#g}jKlw@AU@*f%=WU_6r&}1;JT^- z?&c=7K>>$pvC7IythMQSL0QZ$?(N(8p5{D78{X!C6O%8Rp8g9P*}*tmWQBk5TeZC_ zWNPdF-e%7hRHxR#4<|5|?q@ErMf&akw13-vBY7@ksAilzCMytG>SzfM;oXdet_Nj3 zbAYRi1kC3*Lne(vQgEGIJ#~KnqVe{+Nqnf1vxzXp#pf;KjBh052LTUbkHc!lpXNHw zpE)97=A9w|=Qnv}sCojgtv`Py((KJj0>R=+Rf2emRkM4}c|P$Yp4AMR1Zk%tAp2B> zJ4|G+;`J|$-*nJE|3F6|z%@devy**-eKf~8z7!CoA{5{u}oYZWM`0NP&)Ac?8lgrSH+Ox8E z%SV5Rz3nyTY!vXb=tnuUZ{RjDg@^W?N}Kh$Gme0?6Xhc0=!nr~ttlR(WNiWXWR1K~ zgjUuCDH1ZXz(<&hPk<6FBI)c4svBrLnk&VeBbA2e-Q0{;r`QL`q?)Mwtyp4}|IZ%y zZ$T}svD6bAEoD+=t(lKR1BTcFemv{zn7*+8uH<`#x%~0!^I}~palI_EwVyZFgCNXR zam0nAaR?e)<0j{&qq^(E*m$NBP{)>!q-~%Gj=Da4rAGvxN$d{`S|hLalsfSwDJ2{c z5a}E8y4tJ!FA4XNcg+y@-@gc84;;*I+%pZDyoSCldTjX^gb7PZ!@lE^^H~&1;-NOM znnb_65X~Z&@lK;Wn^kcrgEF;-%rY*dkI&ZyP-S!qEhHZ=Y;W9Q9A>Fp?^?dc>Lfuq zPW21nwnrP4RaWQyX#yS*8wcE7{PmCCuIn_iHR3izsRrF%-oL{kp2z?G)=;S~eBaSp z>P6|t2M?x68aHslXWZq}m$vC;-e1WYkJ4_a3rxPtnr)KEp}bPdbkyh`nUv~s;Ua!_ zw^jK(|J^WBEt_{8@PxkUmOh6vBv6n>A;4oObl;Pt?c2{C-7hjXC#!(dkCc8D5m`?_Vi7vj^CbdT!9GvWy4ex1p&hTA5V9zU%SRc#XjFr6K-~TYu zL1S^z#oq0%bEf$%%!?tR!MZW#KZmsr{eLvSl@WaizF+yH7DaxXTR;f{j{`Nh{_4cz zyIp__e72ef>aw1=z>^gkDF`{QUf!t30@<21sfQdN!5g2ov1aM203+I>ox<*F$2lp7 zjZB$cS^yIOeg$(e_2A;dm$CGP=t?fRb&tX<95NmSA}|Pqy4d7oa``Kk7Q^#Ghdl$O ze^onP3xz#7g1_yG0HV7dvs}TeJO(=4kY{DA8S1D#2wTwJhwOTz^7dxE@aTZ%Vwkcz|=!VnP~}AU*niJlB;??`D2E0ZYctb0PjakRt7e zUv1NjX?##UK?n(V7hf7*{=PsMzn!zQf4&HFg$owAHT$PRC*QXb*|jnUCiY7MRUK>V zkZ&x29pbYxE~rSPaml^~CHr>7rnXhs&4;rLUq<%sj~nX?`30;_Hltr|_k;d9n6PNP ztE-c3&l``^CgGbgdpH7{Td4gLM4p;GkGkkKhq#xe;xAn|qpIzpt-gOUTk`K-s2@+LVSt~r)Yy(JU_0lN8rUOG=s zN&nSJT&+MaWHsF;JBpD$Tz;;_pG#V~7+{xhXuzp$(b8A@$&NwMIiqbqt-@rx@@A1E zbe!b2S@%1tL^@)3xk5bLHGtVl?;Kp}`q`Jsh7JniV4tL378YsbYDp)DY4Ovr` zCVT^Dq_Y`Vj!oB+=Yk&Xv)s6wRtzvt@3V7!FPlB5qq$ZGh2O%2OAC*hnv{qXot+ia zq0xAFA`&1_N#S?mNAo0O%Nc~G24;XQItPtTxW&sBG7fXKiY;m7B!XQ_E)`o#-qZn7 zg@JY4_?I0oj=La$cQ6TXRx=tWK=Dl)sRvEgc@xm+nVH3I&|wL-m@3TpI7oQJ&EXkh zQ{R}kVXj<=&v>yUQv3JzzgmDV2aiK-5DyjGTz)PO`=xW=K7|iG$hq|NN zzZkqAkoeYtnycDeDfTz^?l|<)`E1bA!gx#@fG6PArE25|3$Clf13IXcSPLYj?eX|h z6uzj_c><3!0216FJ(MSFP1S1S^m!n`4`+a_4TGkxr6H)wGID?eeP%pdq^&}q`|4ET zKC`0$^<2z8-eJCbMnQL3tv)xnO2k9>YZXO`}^6uqNjzGe|P;zB=QPG4LCp4lY(e(o?Joa2cz10 zwxukJ;k!ScYQtPs)cj4(pa>$H$V-t5vet5x6twlE+l8kqNWd;(G$Iff7 zx5@^M+7^08E7i^L;ta5-P7zd55N}aDE033g+-Y+J$;J3^J+$E;k8S=}!sJ+apN>^g z)Z$ADlUaC2K%MtBd}Vg~=3ial0A+G=VhHzfjqH{AjC{hVkA}}-m7LlD1=iKclR;U4 z+8TF7BX!j`jAWaL{y?TL8Abq+Gp=DC~`QpS^Iz!|Q=PjZtTe!`SBFf3?;y2Oz22~uD0%QMp z?N~qXU8Y_!+qI^Mg}Fe{g?&8z3Ny&Y*m=J&XaL^e>E0}`-2=$n6@t@xQTcu_!()Em zd$L?UQpCP67NfNyQ#BNkPhShgH-hc-`O~6vAzJ@y6 za~#j+<>c2l^pqSLX1}U!xlLO#d0u=?NJ>&j=FnUlEhJAhav?MZ$Al;34~Luh?*AeF zuOP3y@PTaUjL9k+y;qyIg;_oQe60f)XFI0(HJMtRQ2(RbxOgP%;pQblK zIQ_K5*Rrrh{A`Yi9KDJ;9y>q)jv^ohKbzWAuk> zgm`(c;asz;BbIn*5+6b~(`76gIM{R8b$FQYmxhLvRD2k&vx`#A>Vt}eZ=}mkq%tz> zVZo?-mDGZ$^^j8Eu(Wh}8kkL%I7UW<7%=%JIa%o$6{E@ftEP*4`u;zIrdzyW>{Ek)XojXal z+&8H0gOakcOqY$s7_7T?38l`ve7%}4?jS+ybQPcof7|-E5K>~(58{Qk--}fyctB30 zx3DZlqDE$U2@YId$N@hFX{%J+Er1SoM=V9Fe*y=W-ELkDA~&#&(* zLp84!=8Qy^1upb=^az1ns(92Ch9ymrkR+}3rr zyr;gt>BpSx-xjncVe&t?$)#J;wsSoC`3b9p$7b(*dx-e)v@6Vzi$=s@wn<#jW@s5) zLza8XeHipoe92tJ`%HTkcX}bm*(5Nt;$_=C>61CzsLdWa!cRNDgIfA0kw*(ZM&nn( zv;|}a7?@{sMD*2RQq`dhzjo?Ta>1eP_=Q}Y%vVa_v|=5bESFMt6HoKl%Bb?2{5aui zlQl)(*o-l4Ea1PzC5uyhKfu@7cH`4@MKz3B0m z=B=7y;2^`+swd~$uRgYi5LSZ9w{F>OYQ?~OWY#V3h|z#||8(9;Vz9=qpO#M}&D(#N zg0l>=7~PnA@0dNFex3Z$GAS&q$2m)|OJWcBgImpW@olBTQVM`r)N$Sh5AP5*!g5t$ zvvmV+1#D?R!*f#%L|C+YlcP`(vVi~oRV`!OSX&qnqOs>9{dZ>pPMCJHNVsxK_bCq( zYMF~{gf=W|jSL{B-;Q5NST zpF})3t8H~Ipv9bz2Lc2Ntd9BcWar6Rm9p4E*LMEUAvoooR*Q}kva;}lW*l6(}Eg7b}ek5mqK&t-+|6Wh*12?A^no=Nu-Lx8J3V<)KujS4pdq?RmSjOsA(QYQ60!DUzo9QJmP)-!mPybk=n`h;6K0LxcOK^B zHTBi>^YSL<+p)-j@Rq@czUO;@fXZICn4LP@;eSltL7nED zv?QoCNkhF@3-&YP8S56o?VPVwCi-y1<;UJABhcyBGCBCx?IlOve8d zYq(gC&w3#3$+j?+fh7iwGV+*wDaW>Z0g4*|tKJ)%9=?grqlMbYzoL09fc_dw>H@t) zLN8J>P4_RyqLw@N`2RG7DmAzBu+0{W+J)Z)H7kvmkm2Iej4v*e?0M5MjZ(B&ryZtk ze%8UaE)wJ0xoIuQTNb;~MEyIVgB^X6$sE|@zWuACzZjjacE59xP6ofig@BrlV*add zfW|^td>SiM6+?Th=fCHPk)e!sO#zxp*?5Gc}yGBxYHUrRvLX-LSaoT zJ{=0>6VE}sIgo|XV*z!mc{`?3R8dXUncwBd^OUlB&@WEAZPa4{Ey~IHxa|5&;k=y} zcq;48E}|{L@U5elFn-Jj9!YQCky;pvl_~zm%|%l`Kca^h&A(S!uu62f;-&UfHcxA3 zeTqli$KPKaajr-$tg_}KL!X1SC#&eAttmn99AJUczo*(ZYVJVe&%Qr0`D#V;FKG4m zBGk;4k*&>lca^jcm6REdV*AtJ5*JP5Tn@FA;V`m-_spN zm_FC0bbma#{|)+tn)95pawxk8uIELoP86cLFdbUD^odVqmbF)E)2(=f0edx}-(TNW z5lnGNfTaE+F#_JgD;v3?(dv89^x_6R35&me6<6BcKSc|&JjFcXp2GKu_z9Pg_`r7k zSexwTq&i@k>0i`ZQ+e~++3;2cnhu!;Ug#~KJkd7o2RUF&jSi{%_{Ur#j#p!PZkTaq zeV=%xz0)#z1%6`%e5{G=jDPjwweh*un%Yc5%4Lh^#rzT=U$8JzcGtmWw{*&&V>JN$ z2CksT1c8PnrmZPdTw^0;Gr_R^xj;#pR#~jJbsLDf+B;kl1%Rj}GA{Lhe) zXH#Gi%y48r=a7}+-K*gZB5PDw>*Oa)f)m_fImlgV(Msr^Sf@DlX1~*>fTMARwy9`N zNO&}uA;mx_Q%Ejl!&o+R8{e`Z5k9WU!d__E%N1sBh9Kw;n8bW6m@Eb9QKA{4g&c4H z0EokUMBUK6C>xM^o}a`x4DvZ;5R}$}_cGOqXe{Q{9!B}*Ge-+deyGqi25GR@uJn&X zn=3ElRJFBNioTBvE+=7QfnKH?$~BHN?=<0!ZjTC6$_Pbg04o166TLA%nhyPOMSZ+W z>AcoMJ>3rSJ^#ST$H0fd;D!kFZJi&(8UIy zx&=I%=AtupJf34f7Y9QUB!B-NCZhe2eXPO~PPVtV2Xw#e+1drB0VnJpm~UL={LYJA z50sQK$ENK{*X+j2G*yiMJzO0BQ(8X!Qpy}e#*tkY!LM#Q9u`%rH1bCY?%(4HiADpRM8Ei?iN8v#*{Y<|)-;|YT|nwr9*xhPspDz6zlx>+O=@-|3O6R(3+{`l8z zxd>yH1K&PNvHEFsy7-<_OYa1g-3}#q-2msKlar(yfr&%3B;16i2sKt6+R)TmXMQZM zK?~&RaZ41F^~IBQ@z(4Ml4c(!YWV$P&aV3)y9N}^t1=`d!j%qStKfl=hwTC@aiRjC zcQ!HU?vpbzf>y+1(?{SWB5d&CoK~b!t^5X9w0WuGLtXKy$EXK{A#Px-RF(puuFSgu6+8?JQjd^WSR^9WJ%Fdj7bhxQQa^v3U zEsE7PnuSzNGiWEe8W?y#H*Bmh;|GCLi#%Lh#lKuPqmKWb!dVmXAIe_mO_=1Tkis9% zD6shqLN?gn1~ZD1gY$9Oh1^yuJgf7Iv}3{}{a2x3ct81c-Vr26N9cixlwavKt1~*7 zL8e1zbe=$E&sZrTi%3!@Flw;HD)WCfj4Zl;mEXjL(clvWT_eC{{hG9i6v4Q?(C{#x zANh&cyZpQSGOj)yV@c?%t@h-18dhsE!ZmaSVI^(yme^X>70P%d z=HS_WoC=hV8vxI+p*x3j`ZB=ZSg zB~TEb{>s!A;Y$me8dCY;L7EDHu?;9# zSj5v2s|qiE|Eq(I-pSI8$Afo(WACF2*1DKv%{$HY9UpPnI+abW48E>k7)NZ%NpZ189U^C9X*;~Jw4e@T88@i%B($R zl`Gl$ClF1C$46646uI_jk9>k~0MbB#|STRhN0w2yH= zvd^mW*x6Jh9%0vcViC=wq^O8%Y&^q$e(!04zFaDsY7(2Oj4GMK6UwuLIH^)8!odaCXG#&fNr2aeynORXlNX%G3F zI43_`%NXu^SzU1tyC^+w=OC8PwZrlFvv1jTsu6ifWy%qG!PFa;Q7SHMw;#pX-QDBA zr-X2k%9F$Ae7by-PWU138#r<>P<8kgW8%!(mOUBX~1jIdp<_Khpkv%=ypPB$Jp-!lfr#coIE_x%h}65 zPUyfs2G|A$_A`0DPP_$p5>pU9lV8H&*uE0i)d$6<`i1Fo?9o4O!PgN5V(VW)CI}oK zy59}X&0ldISc!*-6^{%hzV~_=T=sO)`_m%c!F^)F_2mZ^-0HZp@7NUO6W$vhB7E;1&uv3#^UBI#ky|_S@Gif{2g_0Qy+;tv{(J5-c}2lR3S8KO&4_3z zRW9G;B||#2h+wu!!-0yoeu8E2VN{m z$29xmya;e-99drmpU2Xm=M!GNpzR0e5*sB#qbNoX3`NvKh9Ef87yfmF-U?B|aGqyh z-6Uqt>h!sX_A$?O4Z@h$F6vrNe-~HR)*=out(X<5u&t)Shoj&nS5Ovq>_hM>FI_MSc4v!0K7AZ{M#s)UF{}~u{B?rU_vgzu z)ugn-ajhq%OthVKbAxvhmpJbGF&M;!-P9=v8NDlz$X%FdHu#w}(L(4EB)0?kGKc7? z?GpdDCIvxcl2tze@^PkWtTp8Cb!dn!}7Crw| zOZKE-7U{cr9y^;PvoX7W5>VV}0>9q}HmxIFNMuG^t?b^8j?ynOTSW<^So@Tm@sP6j>x?T0V zD=zg2r20Rfrl}RS@jvgt*Aa#2*SHc^1o+?a4%Trht;92E`-gjOzW26kF)_8kAq=NP z>vcS*)M19dWShujGmVuXvpr&FeiTxH$mA3IcAPo$^(R^)UIkMOOYN>+?i%9>@AGxYXxn!uO)n1=TKn^C8ihpU)w zh|Q22cel!?hlyv{cLl>#9U)yK?OfdSZWR|_3I~rqI<|=CAAhtfZ&2TvV)8S?IlEkB z2rqA>S0_KACT+hF}d*{B`Pq@A&~ zp`QQ1bLK?MciTt8bk+*`aYch|v1#ucm()Sq(`WZn(&L(UJ6`x%MzEgjb{1iAH*PLs z_9~bLk0jukA8aO98kuA-jly_p(PW;p-be;y%l?q$mHxe?YDfZef(Xn8*_Gk`E%N8( zf#-J6St#`4pb%;!u}TZ^nh!P@I@t-l>>qDAsxf$XP<7Sh@z%}1okenHxlvqgJ)n?3 zvPY12CS09exa3j^DS9U9Mh;FhC7S?VuIi)e+ zo2{n3J*#Xl%p;M@k%p?Qbfg5)v=*zf^VX&R*b5Q5nwbLb+G&a^|H1Ua^I$=(<|w}w z{?RE}jMM$A4Go9*2k#GEP;z2C$m7ILIrq=Zv6y>w*d`)zELAIH-Z0e5jo-WVj^U_Z z9X<2BmT!2YIA5p8>6>FY661Oy)ekRyeD{I-YkGvt{{2)FH{uAU8e-0@22be!N7r}9 zQ{Db?+agrmkI3GV?Csd=*z>tgxBLFx zJjr>kyUcG;a(duVH zdA&Aj_A#FCuVh{%K4t@U`yl*kSYiPTaMU%;rYB^%JrkS!S)uZ!*0=8w9 zzOXXN)NmSQ0+7(->=h9agMs2Gtzn{ms+1M_&YLR;V2HFRSjHol#ckuxX-Fx zmA}&$x+{_gtcBI9UnWq)j=|S5#U2gMQ=?vU>sLG<8z}pVYDHaUeBL>znYhi3GJD#K z<0qpR{vjsJe%`{8Pb;1cc3AcE+8fiK59OG|d_Bd+>`9~BB#Np}$V!YRi6?kTOhZqv z9Nnnb+&K0pbW*C1E=`&2@0S=ryH#}doK3ckz3A|(abb}1;1-*-l#PGz;?ngs$s0a9 z_?Q-@o+V_L>Msl|5IQig*W_DMbYv0~wK%698jeqnJfMzXWc2)WyQtL*z>bvN50R{D zr-}%>r6~xrwlEFC;&j65_SMa*m8eHCT|XCMDT?fte~1wWv0jlE33{!f4e^3 z{JPkv)nMV%p?P&HvtPN!Kqg{yy@?LB;tNeFg|tmkevfdZRV3{9sIRPV2=#vzJ2DQ`7A4linDkQ{7bBQ{8@uI!QEVs$1bho$jEd zcc^>Mk8(;<{3fuQX16A0@z*(8vP6o7NmsuiLtJi6R}5j>KUPPBZztO!dcK$7Doj=U zeAJ4wyK2$m!2`LvCFLhi2;VSzTsz-?Q-xJN_pPpESFG_6T+5ug5v5vhsSpISO{#dC z>(M#1GU<(CE37dIg86mZjFgf22Xxg9J0Eu)^mS(*#p;eL zs(WlbcQesZNK%P>A9ML_srrvTf*QCG{yN)tGQ6F&1+r)nqo6&{0qt&Rr z8c*RBsj*L-x$FM8>h@;i74%TuS={k@RTO3<+;jOJc?g~ce+A@8!C%y%YDtfjt0K}3OpVic%% z8G5OTy1!Os!{^zO)pybFh~F3G$~)I+*f{@g974`cwge9{BO2srS8- zu}jVFFWY3NgJ$vChLI=7sM~)R#hWS2B#pP0ul{eh5`1BeLUTXF>aE|mpMzI+-rT%; zow4PrbD~v)W%0*N7AHnxJP~&mL0fZbXVe`@VE!PX>+3sD^a0KF-Iet2lBaUg1KEF-PFGe5+qCEK)ty9Fiyig|$8}(T zyJej^=>P4Ziyv0~+PQRC(b}(5zxSq3t=I$|IDU^+_mDLP#zCF_o?-(FN*0M6I*+1pr#=2rL|HNF%jMvmEN3_e&b zMHyqQRvt&5tRGpuh@vWwBGYEiK+y8`f6J;qT%i1ETu`-H)6Ubey`3D8WV08J!V(e7 z_TE{_H}+YJTR0M|d43}7>-6IhmZP*K+d6%~v}4bcOL78%0p!kV@dKzAXgndnqwEQzsTS0M6TE#3;z5RDx<_nqdVsF?*BzSs~xZr_jmWpYbE_}MSAdqp;yVxGnp=qwgW!z zJ0cM%Mz+EIzQ?5U3K6&9OM=>Ky6p|@NJY+st9G7xzQW5A?vz&E8C9^erdfe)@C7KC z&*@Au+CYIx2-5MqwodfE`IZiteWx(FCRIA@Zip6UFlxcR8- zWpx=HY0hZt%k+}bFxp47+oc>1G~HT>~KHqFkVW*XJKzh4JUcdaj z)-F-zPzeiE7@{wu{-wr+qW-J;HBrxxniGtjE7)x%?Nl%{bLiQ~tANR~t62MyKG`|| zqy#`(21Pbag~GAjJlt6Do3Tf`(YxklX#T%={e#MMr*F=D5^Hfk+fP^ZVcOUpFb+E{ z6?WU<81rnI#gaLw$Gg1fepN3!>|vX$EH)9nWGJO{w}%o8E{28k;6rEy^b)uJl)s*D z1Z;TnonkaW70#7`HU~UFq!W5}QLoP)FNSLH_pb2xs(=s0O8aiVkg^$)h|UHb)-GfjCf;(o)4QC(UUY-&qcElH zT#LME5?@Zw=I%(%b-&8g0HGu=-=D9}g>~vijt_Vr?ykAN$S)#WxtSq<`h(Y9Rvb^N zBAWk9Gie-Js@l_XQzN>F?=H4%qGsopcjmH!>YDGY8dhU;vbWkhVqUHnY~`eRD5V!3 z&7fVtXJguJzjE?tT2OBGOWjWQ4r@93C~5+Uh||>%d3JD zdpkpVNFj$jT8zR2=`BZ9?Ihw75AJ$9<4Iw)7SjNYWk;0#?}Fd;=gt(HCD=KNZ=fk4 zT^#ssT#*y#PrJsb7LR_5SmVwv)ON(8x_gu_BTmt;9(*Eqa?L5#U1sn19y~ic?!w~5sQS8ps1s1z=vai_Qcd5L zGqZ`aIgWi2XCN=X5hEEpm%}TJ;GbY`Y(O4PYqkJL`#L7~R+f%?&O_fVTk;U&j-5er zJ16iaUT$>m9mMX-ulbp9QC4h!9$oNhw$mS_7MaMnH?8kxqWn@iq?EtQfV!D56?L2S$FPf)PnN@95!5gx$zYOz6 z*VJtpqt09JH}_LTX7Vz&Y;mqn9FM5mbSLvZKLejJY;G@i)=i%7D}t`sIzQe}1+?iI z*3X9lRAR#(Yr|$aHK*vJmFDanAh>;K&eq(R{ZbJ-huvPS!Pe5PCr1eV%nr}4Z}dx& zHsy#(Dng^~zj_q=?pDhzXv6|L;d;5%y+gDlitTe1afZ(_TiHb1@VZRIhPJ);S4Ln{ zm&I*$MT26w-I&x=$gkc3g6MK~Q+`>Ayp0)iN22w?A&fU2cMcsC^ujOl32Z(6J~-(T z9rsx-IuBC74fl^)xD&gkm_6vp;9dOISs|UjA<0_u4dDI}Y#(nW;`!XU{-nOcl^r__ zVVeLj@K-$Z58vuq(V*YS4Y>yZT=-6`02f9o{@}IGdez(bc*z7?l))mwCGKd`b;U2^ za?Rz^JhAFFXGbVkMz76%pWhPXzFgYCo;%EO4=vnF1*OF|@HTAVjWUH?%U{H7>L)Vfu)#Og% z5OhmR=;Rfx($UTc+z=;;=piW;RC`DubmEKJPHI`B*vT?=}Ip+QweOzdJ4ZC~IldY^5qfMs45RhyMjbZ;nPW zSyzfy;ti&~=GUuv^-0rf^S7mi}<<54us=EL3 zCEMJ4$ke&(1x+OD&S)w9n3qTCGem@+Sw)A&}{gP zjf~v3Lw)dekHj~4#B)7GnZXJs(Pg4S@n*lmcfv1X9jEefPCa0Us=hZy7ug+dUE=O* z`|jZ;#jVocnT7iW+>mfyBXG;I>5K2daNQCyxELj`WB2ec7AiNB;bWPO+?oJ_iw$+p zkGl7wn1PaJpser(r7J6*L8xGh7zaJz)vnrS_N%>Z%7K(0B1M>kVwdLh$VoWcK7O3# zD;AOG%m`w<-?>}8KY5JY-y&$dpS)5r@0R$6DaCJzju`@J$)c=C;D|&KPM%9@X*pp1 zCcr*xrdVfZUwxLAd2oumzA${=Ztv*cN@8&NY`Zb5dLv0>$ag^Yq!&deKI{QhYAU&m z2=o3Q{XdVt=*T&wuKX44*d0beeKAgOX#k}EBjlsUp`*u z9{4VAZzCQm0|h9$(*|PXf?YVMuAo7xM_d_D5IUw4eN9##7ur8%FikOXNM#D7t2h0v zeRw-X=~@dz2PHATJkW!5LP*zI^M}@aHfA`?4Nv=5&DOjwc9pHgf8<>~gFB_z*Kzti z(}$T14q$l6dNYzz5(v2E4+KF9|Cw6Q*VbFM3N#G3Le{?$Sod}3+9cCx!u-zU7Nn{c zUUUUa>|yC=`%1OUdOIV-M(yYB>N#rY>j!W6x~xph2AnjG%buSfitVJI_`a#=W|Vv} zFwt^;+{5O3F#V$(A3Da(qr+1UF?k+ezpu?p!em*$s6Q$#|C;IJH%Iq$V-q=~f zVp!9XN8Y|`i4kkVEp-|37IfWNLD7y}?eccO50O!eyEEP+5-@FkNZXgPr$DWF13SPm z6+m|3ydaJ93WoPUNvDznp?c=A?-Y2C^%ne+D&PdQ(is7A`0uvQ?5a0Uq=8h};9Dn# zREV71mFsa^$2m8<`FEepb>Yjn(8a;~%M0xh&q!E#;7``dw~fC8XS6Zn`2NLOGKf{D zzkxe2_CutY#l3ebX)DkzQu0rt8#Fua++R4m2|V1E80D`RKJ*I$&wqqca)0rwqO6>GYrZEJwyosoIX9+I!|E&rp}yR~=R-S?Zj z_9xE+tJZyeBZp3U>X;U~0|G>b!gq`3qSF%+C;j%V$VqZK8SdGquN}U*Q7gRVwJ%S2 z*ix|XKD&Fqg8o!7Zf#MVdnZIl0-DE67_N=OFIQgtBHJ1~)yg!bldn#@TwI2a4_1Yp7tU>eY0Hfd=+t!Xv60zq&s}kNtlr~RT`wV3 z@s_|Jnv~w<;aIgMZdEZKk2N)Te`30|k$+`e;w-|&sSVCDY+NXwX~fs;V7ESSe9{xZ z*nxeVqTzGgIcYvJA~kH+Q(C^ZvAJ+;zIxJLiCJsU_r)%HjgMb$6#a^1{xN$gng4i>fmN7 z#D2~mXQnTBwMD&Jh30F_qX0|38=fh7YQMFnP=j>mG=31}YkOY#c7?%HeRRDTOKFX@;V}!Bo@b|;T z#va<|J^I3N{Vj|~Y_(gs_9$9%$2;*cM6EkFwaATz;!=#(Vos`SZ5|t;+NSFF!66IaQt#O@~O6&*qVNz?5}5= zKa-g-O5Eb&Vr@uE_~=i??pCi zKF;1V4K}}PEhFi#N&)`t(|eZhlP>ZR8@{Ks6JDpXSZ2P{H^EmyV)y8Be&a!7dO+hw z(c$xrQ667S>6RFafiwoj&NKIw9Qn!GuQ0jsXpJw$14DIVsQu{=8dn~HV>lJA@A4r( zANueiC#Fu8rX*X7Q}XQKYs|0tH=O;$i8)4m zf_v+nc2YT6Ss_mfr9&gcO?`sDQXi*OBs~Ly<{5xGfB>T|HNt&bWE*Q{vCI|^nHZmL z?%VNX5ZbI+fBwk6Pz0TSbB51QW9}6>IdcF68WmvbCH;_(AtkK3Rk%GEy?MgCC?j$_5}h2 zLxK}+E#VP=b1Y!AZE#dLr?TGap?f)h)q^H=3Q|KI!mlt_euewi90ektg_+~rjsWpLjA5BkbzRb z_uGOM)%8nPb!w1=98@i`~_qaCA-AuHgi6n#r z_0LfUAQQZ;fOv<$lXsb0e@;%%cVMywLQ2m&%;d&%b1_Jt=Thi zw1MuPSGp~KVMp~@c9RC+N?j(3uZCR&)@S5B+{j2z;3R~`6D!yHm3gZuFbwjVXG#*N z?Co-RBK@7;-Ny_kXsF~qLvo(?VLb=do~jPmBZuQx>&y!n+r zKH<1fz`#n~ZQCgN)5GD9r7^(}% zR7g(#i*bA^J1ypM^llLypztx59cHluJp0s^BJqU6 zN||^}DZ1;4kd;4PlUgx0JBP~ktjSBccc&uLk{v1Ao-zX?G9&U_gab)c3^Q|LVFzRY zcQWs&iye|X0sbu^irkLNxSO@R_aocjz1({XFMZ4{-lU3gP_G>CZ?evEp;@trf@5r> z=-DrpP=xdK{+GmmpEY{q%u;JKW0$W5%GK^dYF;7YU>EUdwpZ+6yr;|`}0mQtcp6_1^!usJH z$k(hqVbPYsex-5tnjhj$xzJ?5eoxvE5Sr}SuE2?sIUr|KaZXbD1r>!#WS?J+qL6&7d_-u zZ71NE<6lhXaQB@n?hB)R(#7$teb~M6g*`%cj%e#r{1;9N3c;r^@>G*c5c{d*!SJDt zz%mfZ({t3Zl>6Fzg+uKNM}w`08{JJuvC*Pr{xjvYCu*gHq`u;>VoQ0p$k!OP>Mcdw z$pqsIeS#@7+uUy|-{APZSlM&_0k4s3Tj7V`@`vMF`#qT7)q0BqVQ7Meu~gqBEx))D{BJ7CMs7*ZNP0J8v}ic~4XpBgHsy^k=zW`&gSy|{j3^3Ynlsvwap0P5 zD-{XZRZHA=up+^49%wBQ5wb<_rGNeMY-Py~;mudN=6* zh11l%1F})eUp;H&xdgE--V-n0stNSJ#9gb+X{T%9C_1w%jnSANLeZtI?H#9TDFzNx zgmdK%+1qZ2oTaII(c#RE@BDR-_%^ZD7?oe`IxNUol7xupg!WN-$HMoZ?h5+^9tS7K z4Ho(fq$85C+S;5APlKQ0I`}Ip2rb)}8oVDQT{O5i!>#y0P3U(zlM@6NBTk8yG7>c$ zEZ%%%Q(kB|HiwWXeYsI$mfkI}&8WOi$lSaw;(F)i?8QD@#{ItlDb5SOj;XK(f*o++ zN*oQ^e_#vJA5sA~7O3buvGN2l+Wef&LdapsWv)||q;Vo>%FBhLKpBOc>!jt-ZQ z63rid3p~g;*uqCE5_w5mr+0NAsGKGlB2sFT=Hq| z_^umGBPE$kIf)FRIO-}g4bM_51}>S(b^OJNS8_(gi!9)GLJ{LjGfc?gFlv9*XaVKx z1v-l28TYlIA*}l`mJsaQKU^UWk%}WrQ{r(<9FnR4RdlX)% zjKMD5?vL*U_q-BRn#+}+iz!Nd>?MkYmQn}?-$}{Q!V|0SF}=0oIX1x4U*QWc!MB4&!7=lh(ZnKBOqJ#$5=m!S;3`A8sJe}blnVnR)& z1{RD3j8KJ8+d|gw@w%$Z;+QH(ZEhUaoE_|)Hi}6rf_7c2f-C(~>YsKk_umv+?&EBl z-j#<08~kE?>I}Uan#>uAwD~{gjiKmCRM~rC}lTS3RINT6A;bu!GCc*iB4h#DGZ!;BThHqNL8 zPB$&wY>s%5D0shm<8P9s9uSrd$SRW#}pc>j2>lI1Nq@2XY%-pbvZJ;2476UFNAt%D( z`h)V9Bvs__P^l4|<7${3WCnt39+Gp(fvxQ=rZ;QyXlA9dEzY=DOS}bGjG4molmGmL zYmEKl#};UT0>K`4^cWOMh~=;cY1@3z@=xPp`r~XREiv>qRyr%Zfq9JEsjwq8L)0L& zhG=7KQc%+Hp7eL?#(L#02f11ff4pA92_RTiRY?mh3u!*5o-o|OYTV`T{fD`xkp8zzHFDGXH z-V7g&XIYR~4QzcsIq1Fxqo5&ccXdZt^gRLgw469UZZx%VH)mJWrAr?o2a7<=4cGw( z%VI0hn(PZNoDja_ zhmja}GdH)FxkK2^3OdGuu95e*u{Rk<5Y$qDvdGyoNLe1k5y{dj{0<-u6LmDb6#6!%p>wkUB-0_v?y1Nhup3x8reR=$@`NrHKuYAE)+v=GMlzgaS$c30r8CID|xeXBGasT3Ic-IP;$Gq$}SRn z){bF7a-T(JbTW7**D!~UDJ80b{Q~pCtfEW+GE6>Z+CtA!exL*fiD1+WvEy=c=_-v) z)C4A%OqYq~hsgAS!DvfL8#8354`ShMDF-~e$sMuqE>&owx4X~dDJzj-PS8qQu{3rr zctV39F=iqpaMLs5yh7p6qJPVJ*Yq-C+!yC?=npsmP7cok>*z8r{fu0LKhfq_FmKOp zHEWOVoIe(D(AZReu>Dh84*#3k*Bk6KQYf+m30Ea(tuy+=Js|D<%=hsYR*C0BUA5vK zkw_788S?Zu51Lz?U@XE^n z@?oK()d`P#Tl(UMF68D+yXN}{LCW$sAijrCx&&3Zo>=KbY*1@_iK%DM4l zC@|)BHggU`hEYbov-NHaWTp9uvUT{cySI)PA2+L@Ik8^Keo~f^~DX9 zXe;OK69nABT7nrM67`paKv2;04HNO{-W?+$Bo_j!`AIFFwWqiF5wI?7`B|I$MHBU} zVAFwTM!167*%17jqxLg`-hCq@PPP@z3Fso&o0j=d_rV9PA|SdFDVTAwHy_L;Q04+* zrP)8Q4A__=#a2HMM>Tfo{xLmrD;7`85i(WrBKl>N*n zC1K#{6nwNIy)@gRZ3%)o#S0HQy0%i_IFg0yeiMFH`ChU!7Z3LU>ksPI70%F``vlvs z4>;d5lFZEAW8#;8J_u(A>qRso8BWZkl4MuOc>n6HKoNN$E!64G7>r0p;xY6#x%%-R zA`j`Xm0Deu2S0mk$peED@(>^-9QyocYh3JyNLWn%mulFlQt~l7} z@Kmc&QAXQ#yzzxP%TV^@XH<||)U?q}sfz6O}IMHGC0P~bqlE+Gg6 z-ozEz16DRw7lo^xhbpS3C#l3tSn!!A&hZzqt|Q4mi{`>_!8R=yU2P9M#+1R3u6sLC zD&biU3%*#O!c)mbis&G6Kyrd^kDZyqA^z+`r%#zXrK=%x2R9z_=wt*&60xd-IOg7N zQnYKspvf>w^PCWh1zwE+8aQj47$vO+l=e|1iR;fiAMBd?#Zk zjLcGWd38pIPypru@ft)Co%!mpyJri$B|M&kK`Y&Rgu<7|&<2A{SS_hg*zsudGqhv{0FG)V^Q zKO&}*%Nq^{C&L*TC(E@(taTEP8Mgx!l<|_{$XjCta|;ZkX>T$T1sIw7+PHj22k+{m=M)6KSZe7BicsMM)QV0W_KENhZpe%~-ooN8;j)UH<;xd|_UqE3TC1 zI4teu?OJTVBg5GhvTd%L zUvQk^`+9dsqnLx#H;i#e|IxDV{NfZP@kz2uBx~3C!;g%orV1&PY+Sb@;p*0sC*F$amG^{ZNE4pYwYR%q)gtp>3Snt6-cEV%ss2yfe)K1z)OAvLvy(9i zGqVJ-ZuaJWUDd<_iTvKqihBpecE`_rOcxd^(%|HD{<;a?r^X=ZqW!)p%vv&4BLDt; zB_>g;0^EH;)yQX&nXO79uH>Y?H9V3>Rgg@gL%2{3YsXb9A^`A1LJVr06S>RW!JAPE zw{e($KtDY6*(_>(-#%4D|ViYY7<8HRD?uipimT)HN5K?io zIQE3cX=__RQFN2X5{%D8u&vPPTy!$UKUB%bw)`1GKDaLsaJ_NcpASPqAir)c)4EgH zd1B&Z&mCrI6{Vg?6?HOrY+VsrRS9Q*ER|n}nd|fomAMl?3C`nS;dQG^4tpQ!1Gu+l zOfb+Kgs7U()}VwuynjFj{UE-6=E0cEmjNR*F#3zT>>vQ{@{uaW!r3vOp?g8B++=bq-05 zSi;|-Rbtf^+6<)R+GOTdIjUgKwN)hcc*>ueq5)=mI)j>wfcAu;yV;3*l3GMGBZ|511(9^@U1v0>05?6iQwA9&t)!|H--cb`z-og{?6P zgxo53Kyza@01B=|AkOptR$UQST7WsNNQw6&Q=1aL7{xe>$##_d-L})_8F6NI!~Z#T zEPsM!VHW@;>3oj}b{ZZiq$?;03mS$BO(3x+)NSAxEOJhaYV1_T9xA?wk7 zh5ql?=gMCZ_$wx*K9S;WYsO4q=Myb0`uT+1x1UW=z`bdrm=gCSDN{bIR7}t?qyAT` z5MT`TGa!p-UUZo|8Wp8!^&F_hA+v36a;}E?y8R8A{SOsfLL}Pi^{oNt*+OgTX@Rz8 zxW{hI11vRM^C+qQjIDL)^v(8;4Uj!1D3zT6I=}%I4ESJqeHZhG(U8GE{clWngZo}b zWv|GUrU8qn;pr>vz5CT_Vyqnwv0h2wUUj5V+{(h?WuSs1aP!@2Ugotn0)G#vdBJ|m zLZ#rvFF{(gWa-kfA{yV8@Bt1GZnGSnSx0;cT5?@^J%3q?W^7G?K+{b6kCY!Br{UBMD5KJ$F_uegQuzX_ULI!!O(BzQ(4 zb`FGv(GOi}XmnSr8xJ@ful0$z1%B-E_})oN1`1@@PWBo(g*^%q?Wo4~W~kr?g%w@@ z2@um&(gJ$BbshY9ZvXHfl-&%4YT{n-9L&r<8K+Xn15t_Wf zv{`zbe(PTap+to7LN2}CCE#c0&}L>f8#;72W5PCeGl9Ok+3H4s9pTy4oBrK6f;L~* z+R>U0gm5Ui(Cv;2rG`oa>JuM4i)#k?HYFOmbdz%#*N86>_Li-dm2awlfd=oSP zf)F8>f%cb_-YFc~9F20G=aLS(o6EfVUi+y!mh1p7 z*070~2hpF>Mq8^cFTMuie+ZF6G$u@C^B(yN0Jn@*FCZ?$+kMS5n;^tvK*GKXFSy-) zR@6y3A`wd45j`)0L%*E%J}iJ-h!jTf46=BdG~~gpqCeG8Iq}v?#q}p%zwD&Et>K)* zgF}4D!t9qWz2724igB@TpS~s|rxMTT`3lFuzrp$)V`9*Q|3ZhC5UUq}t6v;5cU}+G z0C4roQp>TdEw7ZZ!&P)=%rP&7?X7TG?exWFGl=-37K+x;noN=|E>-q?N+73z7Efew z9cI(srfAWda+Z<|s8wGCej3n~o**o9=(AVrek(IXP{jOdWx^&fp-$2m6A&}!2n%-r z6`}77B?(?pX2N8YZ$w)AE2QA9^xRV@0+X;Qiqdtg%o@V?`&wx&!xp<3^SD9c@5q;D zTcY=ND8@AusSk<;O6K*GV2JsLppKAIH-PR7z$^~Pqm`_+?uNA3ouP8rIqv?Z(;955 zD*w<;y*S7RGUf}66%BEC3h?aQK&3O=#zb`*qX(FoQN+a1U4Q`wK89NriU1ZS^X*`z zqcZP``cx3yvE}DrHhY6S)qoNL;{{3xYE(G;vP_*OCyoA8I*3w=$iMG=SoT>QxZ%O+ zL!vqXGjOiYl9xQPHIajN@O9#Nu7_N^3qX2@ODL_#)IkaD?#`LfOTHqgB~nN+0OrtKMIzXW&HbKTgOgdb%8`@T`px#8 zc6&_~dfagfR+U?iMK-VZuPTQxRNB$40yqp}G(C#MlwNN|q(P3bAIort9g{=M1|;UXuX2M$4~N!7lw@crIamiV40 zNJZY4_&ajE+qAuEzti6$3Z7d`BeY8OGi6Wznnz1)8(oreJ(75nz)VOQpbb1jS_ zFK4*eaP*reMZW)ej%Bn~9aRRF$PWi++pE;QoLB8cEw4H16uuFeBvhX(Pg&Pm^yzfd zPJF&NL*2is4m!|vK|L0hRFfb2XL2DBhCxsNAVa|QZ6-iYzx3vFeCxL2E2$}3h>d9L z#!B1O9xyfhij@0SJP0Cmbi##9$J8TNh@e-kBxgw28b&-5>$r%yaZ;&!QA!A(kP>=V z002Uf*c?a&&IG-wXL`OdD*kE;Jj+I5;hZ-DA|fOCRl@1T21cvOBZ&1uN)R_!>U50l zqMm;l`>*7YhY1$497=U-4SAZ$0?EY^PV-{mT|97W)E@+f{*5*SO-$iskZV45v$ zh3lzw1fzCn!HQJXx0W(jE~<(5iD*=%vB>wxCgTJ~8VbEatM)U2@Am34w}Tu+)4}w- z)2c>fhg!+?n`6-E0&d}wg;E+D7AGt`=Y)+II6tw>;-0%2y5O5C_-^=TKvU~&x)$HF z;&}2)4Mg-lf2wZRt8oDtNg457naiziWY`U>0vDCRLE#ViChry97tbNgZ8ii1;Ia&2 z{ai4|0LDP{+#USYlVn@nZ+f5gAMde7>CQa@EJ#5qkZ47q=jL2R2+47Oz4)?JRcBS1 zU@-hyQbi!%O84#wj5gvVTBt~OYSL3(@)l&6dU4{wgctDZ*TN0}Mgi|3Bc$@W zKpiG#8gxASz>lPYy<_M-Mz+o>fFq7P)SIJwFq}Y~-rM=Vk$FRR*Ixk*>*&W3DCT2uYGk zAm?Ws9mDZGY$E=v5HLZRn3ZsNvR}nGgk^)3B=Jf@iR~YPoJ;)&ILd=LZp;F)h6yNb z6ppl>;g!UfT8rhmYt;~2V2}mx3CR9B|8MZpEndj=CY9H_XOWPG5fS$@9I9$y#0HNq z&OB4EesBuMy%+5S!^2-UU3_A25Kh*e9r5}lZI_8UNPc?G`eG)BihD~%eZbndL`tZg z-=A}3R{h;~fAqv9YVs0-93+5c5v!^SGN3ek0;x*xg|#j8Yy z{~Kqa|MNIu@;W3RNEcZo+p9HSJ!tekt3#($)zQ<%UflR%aZ^RC%>{YCP1!V@55&jof8p1vKof!e!ds;`hfOaTZp+Wv zaD?`C0+}T5RQMi#T9M>s2mGYvBT?zQRJ5u<$^)oD7qV-GQGsz`LN`sOwRn$S9&h-) zG~%1eAN_P0Y(&ocJ2xrz%C~7ImR7z<;)rp`tf9&E!gCqodT4rlG zPZr|=M%29=>m2~*JZA7mB;c3<2(jNgEvF~hqN*om`+p^1^;$upBJj@4Zx&vK98ChA!9Lmbg`V072GmZ+uvYG#I!(5f> z)6W;E4_x5FlMLXh?B(g#b{N!(CqnVCNnMEjlp3GlN!Q#m1iQ|mH_=MnrfmJeUqs5-h3slarDiXBKXbG z({_F@w1OPw%7byvS-R;(+_{Ow-fawnjEaRTU~FyF=+hTnra^`{Uu(Pd5iPKk0+FSfL;8* zgC2Qw;u%AwS8u=z-KT4w{ml)PSBpHt!ZVxjK(0vP6-*+6Q7O6r+-(smL+;s>N8Hxe zEf`pam}j))Gsvj`14|%M+Ey$Ov1+~>eLooY(qTAo9hN-_^I#-uUp}<{@=jyWdmlFH z0A_u{IU8w{D%@VSqsB{d$w@Ms0`XteEb#x9bkX-LWLyn7yW0Vz{m~Qa6(qKo)2RV2 zViJ)r@tueo1Ln|@N3=kI%}uOI&~Z0#;g&vntCTkX%vOk&*`Gea{};@viPGFD!>;k^ za7%-$1ImXu_r^QDS5q89}y%NlSJL z$^w6r#QU|CWJ{W%!~?DF`aOLxK9pA}*58lhaJBRgMDdDFEJJ^YbTKha)zmZD`0~Fz zv9cY_35Kg5of}8uL+oe7A-`fVN}%xW6(eO98!3s`xP8{^%l5Na84AKQ15JHRMjv=etLoALg;X~v z%;^czWV6NgD-4w(o>LQK1zhnc1e3Xda@rv*r9p$2=up0{VZPbC!X$LK7DXrd7#C~% z&tDe^`CS z&#WBngi&{|!r;U}_cMH!RWA$7Pus%6BT}xJPee%WEfa&H{Pm&&Od4nB3DB;)>6?tX zG0*lATz}U52>6E}6coYu8w(~y09C%PKN?*0Vwl-kh3Ulz(2FC4k}i6&)E_!%-Uprx zok^G+EyxP|e25H{06IZNqKJI*iuXACjy|-Q--%Hv1ho=d{9=0yO7pd^6|mzk{KCAx ziVSb=J`(BzTdZqYh=#e1i`)^)nLw`hX>{z2=Q|gVW_BlUtXHB~b8lM(Xz$PO9ByQm{)|(FMV>z~8q~bQE_ge_Y^2%l6+U6@*{Vj|uf>1q(=ah&r#HqLX z&2p6NzTJgFX68T~3>#oY_iBfWs3NkV@efi(+`1=6);8q2UOx%DLB2=Xn_qQWF3-D7 zqTC$w$Q*|rfGr8Ic5G(jgWbPayJwx|mesFg5C#XbcQGS|un05S3o-E(<-c z1jYln!H?f`?7`6RsqU+;OZM+$+`$%9bo-rvW^X1JO{-x6(>Z#%ODW1~P?}yFY(M_r zTM$Tk)DA2x-e)R+GG;_MOtYE$)y$$1q74^QIt|aLBCl)&pYpY zd>)tk<8*dr-uT5k$Cq6{SH(ThYB99h=A_XFa$1ggr`MItsL~eeM2g2-z~?1&Dj7sW zip&gph7xV~_>I*ON2z?86b%NQW5MqLDQ$gE^3o!LtJHGl+h>5ysQbktexRd1kJ z=|xLck2A<6bjM2sryGnw0Pu^FW*IASHYfqxMtP3;AJVI4CV=oH+M)nCtaWf@Odb*@ zUjD+0QprjM3OHG#F;9JUT;N^z|J5Sy{lNk8xZ8fUQG3}+C?AFq5~lMJH9*YgDx0`U zQbg1JX?3`}7I+w1DDeBx4UTcCLGvs?7AzA>$m9oQ2Esu>F6w&{O1)35nyGPPLvy`e zO@x}np}7cIl260uxKND#qiXQjaHOs{BT%|CR{S$tbsCI11Hi|5m3<3c&UiPVQ$=zT zU01|RLc}YsE0*`NrlSWNQBB`fGm1)Zbx^2KCCJaVH<`|z9Cd{rg;S=)~KVX&wPzi+)VpCl9u+W|8j z>7G_jben2-9E|nop_G9EE$4ZWj*~8dKGgg4AUq&^sUUh{<%?#ZA}$fz-6T`y0c)wt z$l(9rc)5FKC}OlpfbSd*r6VU{8{z_! zhCrt8mS#X&6FM~x=*iP$Ze|G=?x%T z84c1V8jGpjUL|F|t=YBk2gt~U0XzY(-I&t_?uVT#(o!*)bRw~I zTE{<}U(poVi?SGVAL?4Q0-!1GOWlE?)eh0s6|9pAo0Z)=PjL}oLTXlOBIxm@?@w#X zjAZR_%)Zwn=lt@zKpR7a-)uEA!Nz%TR}2AC@pX)r5*0-fSMgu<#V4nKnu}kAS&P=~ zfX9zU2^YX%iFPvL&*&kbUd|_V2)=x3_o9K$L90lLDe?K#S|*hTFUkQD8w*6r&6jU# z5CIjUoD~1Ps8ZKWP4soK($0!356!F@Pzh#y22M0nO`K9ob>44R) zi6qnI&xNhdSg)s+EPQLdRlf$jF!c~qjlH8ZS)>FBx*xH{4RC|?DN7XR>dylLU6{YwwKN}e(6 z=hQ=&dz!4BVsnz17=R9Zu zhwYGN)d0?4@DYcfGiSA`%+tFQ?*Pvz$vYovjZ-r-8UGV2v3GMATaQsyNSDZq4auc zNj0Os_;@cL9`?wB;F0<5#=0u-XY1{lUN2%Icd$Sy8U(>i4?dJ+xjHut%x3&cvRvLs z3IMu#?aXE|UFipy1Hcx;vL8??Llf6#p;(@V3W@)}U6=142zk;2!|d}>J5gT>$R!X$ zl!FeQPy>_Vqy}mIb0e4N{xSdU%@7>&dUDwJhB>9vwv5Wd)T z5c4BK&CE4s0G(yxpoZi8mMx3VzE>ic&)U=>@b3jm-~(H$r#Ay4%ImJIpLI>r*DGI3 z0t-_EvKosNlvVDM166&)j{jwPbq(=RHgPne6qysxaBq<`(hU6^^6T)y^DQ< z2c^*$)ck?pK6p&g5kq*Jym)OJ^HYZHB@jvD5N$sGFK%9$9(oG!Lf6k=)XmjTuWU@V z|vw< zFjGYDMj6|SD|W39<jB>Ddo?2)8TBcSOMP03U1rCNcM#%3rQjFB- zPPR@`D+l)zQmuGQ_v|f?u^uIvk*oV0SXdu`Y465rclF{!p81k&vc?%u5UQgJ!WTtT z5Ar2>pZBGY`iW4=r%F%hDl6kJkBbJ@0JB6ZFP|ll&6@@2C+~9|;j%E8_I_9fUaKT( zT<(`(S>$A7v(AtU0{ms2l1E9c${<0T8WsZi1T(%Y(3^lSD=!?t|@;4nUp4;1^f6O_>dTUMt{IG~C7#rq@-JZK20|SyL#&eaO0B zqNr(ir@?H~6qlkrmonE}-Vxr`HC$iS70K9WGl6#4al(u{+KC4 z|AXsf^=jY@+DV`rnU?3;L$6f##h5<*TmoGnL8)TF5e)smQPr9SoX*)}DL&UGuyD`! z2Ab4-mg=aXV@A2X;C0xZPa#o!8hUrWUA5nNdE#>Y*PX(M`6F0Rzrgm#1{+UC9trh% z2_`1Ii1W|dxSW*=MW`E&03x@gWX5>+`y_h)w9aqWMu1+*CpE^qX>3WY(xAUe9dZ}v z<$>s-27zpF9qCqEDEn@nG5|6M=v3DITT0YRw%o-#)f%C6Kq##(tA@i#ZdBAbpC6p? z%d3$T>6n(K3@mOtl35<=d95y8%>%aC>+XXV<@EU^Mh)N2flmI*b0BFtBXA8@N2xu> zyCw{TlgSKD@`~K~n3bYG!72n|GsOGQzow$jT7X-~0JhdA!#in2a5m(n>ctoieHQV= z2qKG|+-J9fY?oa;nkR9fS-_}$IpD8La}oQ;-bnaCdc)}ufc?b)IGW~yu_6;-weRyD z^9O&|E-EK+SghTcfFiaXr3!)Gs=qFbU)Jmth1ymW!d%Fv&0AB0y?_q~2oCg0bQM)5 zoj>6KcMh#ep~UX`=dLOKV}4*fB??zbHFZVlJPqg5gOf8AH8a2MiHiURUzfSssJ$>o zOOw|Y64sSLug3WH%rZ|jBR41w6iI{7mJ)yo zU#HDTVJ(98Z)1%~fXGd^22l5jW^h95mnPy2QN1G372X$Q9EX1O zD2Bi9u&mB5pu2X=2U&$S@@(Z)KhR4kC7|pY%JLsT?dM!|8?+4h z89O1MnvTby?o6u!MwDZp(=fdqilB_EpP@)#>?Yu|G)R63+DhqLUSI^;poqz7HUBYL zJ@H`36Jpo!0P1N6!GVvrQd)p3uazIA1WvBTA_4ALowuu^VEB$mKAB5gtwUYBvhp>Z z{Nvr;@s_PxZqX6_&-ZwK)v(SjH!k!Z{dF3%s=H8@Lpg$7pom0T(y*7YO}Pz%HbJ3D zPe71;Ap;7&4iN(|pJ}j>+Z)u}nwpZ&4>QOZN^}d&5WXBfS08G@Kcp|w`uotO(W}Ro zYg~(mYo`t&nsBhZY6f|Me5>%wjU97<&C~GCJo^aJ2tvs&45hZicBiJRV zMOj8uHs{|`$8B;QadEeo>tGng8My9v156X>Ei-|){SCG0b+r#$oiz#-pIRxdr+YyM zUK?usTGSl!4^;&?fr`j^AFnQ#ZAI=1189G|;YjU$0Q|?bBLtoMC`61s4A?XPd+BRA zdtI5hZWBrpkRj8Z&!v`;q^PEf$+*v5#Usr zLtD6P;|?Y<(y9Q=hqilqp7%%)gz++kjO`J^wGbnZB>{p!pdi@}25R#BV9)}u$?=3* z<_Ci)K?eaUm|ben9Zz+k#@Ye&j|+_adHAz7s)&1l{Q_BC)D6C9euX$rM$4jy8ZI|* zpV0mt{4&}f{sPRv2{Z`+qRyII;P|=l7recmfMdMKIr1?ogYY)czeE9v0B{0z#0m=- zuhW9eo4oHX-1w{pD5p`bh2jtOWkN4h>cW>m|i;S|1_Ke{l7^|h zszIL{3TL3oK(zMt#VEgt!D)c(uuZYZa!(JR+u;H1feF zzKP6XGx6g;(x>x3Q4>8($J>lA{OE!)rhkAz8bJ^+{3-}&_pWJDgKLerDmSzkRR<<7 z`qATwS0ruVC1yJlUp~bHN(tmc0=cT&$GfD17NySo%)?}+n(`f3)vlXp;6`L>xJWUA zcRHAEI1vLDn4B|XOLo1U3|tUg%}jfD{8V;m{aMe4k1CYfy7$lO`@!MYq-$2|0fP!z zDm1e^QC1KlltUHs=)6p{I~zDuMM2?4$|VFmtmp>^9l47)HZFn37TDSJe_f0^g+I6% z4)mf(Fl4k_qOs;(S3sB&sNNJsnjw~1rTob9+5eIIFbb3P1$)cdYblG z8h~dNN$g(jX$lqLXLBFBO}Y%3Cq)i%2>}HNc1nhRMa$?-MFA9;%=Z6NNB7I5N^hah zIq*SFf!E!T9Jt&l(L%raU#m?;NTYZ*kzvfA-BC>5{=@Q&c@oGe@Jj6uHn72U5I4a+IS z?5o-khh}QFfGPPJzk9ogoi}cOg$6L|E(w{^6RgY=zt^9722fb*t z$sMIA{bi2;%7D}%m)q92@WKcIY9o~pNx`lDW$i0Vu-D$=^aYzRz2NFiX%a9)B71!a zP|x)9q|;!&b(Z}%rRKx)6m&8utyZQ_?ECA-UxfMvfeJ8#6@n<5x=bi9P(hp|spXF^ zi%Ic+F3p+5h;_si=(m9OjxB*a18~=@6krs~i(cdph1*{kwoOVO`<&mN&DM&qT);AH zX0G6WsfIQDsQuF;i6#slaSBRaDw95Jo(0PBYcCtRKQs_cHY{AZ^1d=LI!BA+(`Lz+ zbXxT*V>#I+j@#cY^XG?H5Xarz&gw27j(g-f>AK&yuv1b}J_yeJ{eCa**RjXHe?Wbp zh*$FOe4tB;yhI)LF2s2A3}17js%FXX8gztnvzBARl}2?L{@hXAg3K~`NMMjAE&tQi zZ=o2(q*I)IZ)&%I70YTMG=<_;#x_K`M7Kc1ME+(Jy~wB##^{=z+^a(prO$4;TgOi5 zCnM|BM-x1!76BhMXpcfI4qC6pIAQr4(7lca+2CX(3itcwv&^Uk%5_9D^MwkM**a z72{nJz4`6*Z@f@@tK4F)82v!Y8)7X@vWW?M!ioIirNJx7BqwBE3~Qu3hY74i+FpFi zu1A2snAb{wov8SlZ;wu7xR(ZLW(Y@XtsO~lIP=(KtfX%FZCom`>fny=W2?Q0+vG{A z3&A_3R+GOU!eiZ1!t(#UHq;01#4U*m>Q)l#b|BbqJ1!b?#N=jBHkX-LFnMoOK0bfH0h1f87W~!^K?M~)v#h&C`21|6Ec(MYMLcw8 zW&4e=?T<)F`8mcsV`&rfy`Z!SXl30x2@Zk;5DV1cOpI#P5s{E2nR_0%6>wu8jR0M2ge$W!x`X7s9@*;9-t^ zd8+dJ1-t5?v3D|%-#?;0RD0BSKzf7XysKg*DwY;LVV&H|Ez?O-i>CNOYAX=xe@jL` z`)+4G?8p5#j!)cMooP;MSB1~tYetWQqlH$C38n*WU{t2ED&}U-ETz&j84lD{cN8;! zGeSV4-^WBnMdjnFAVd;iKLTak`mt)CISX+xQJ=%Wz7-~=Ssk>FmFiu>&h-rJ_J(r@ zEn*YD>tIl;)@wy%IErd{v5ZCyc3=^^cQfc{tCj^j20i}HGuR_lBYg9|GTs$gw$0)(8!NT4&!v~Qtu-sFUciF6 zSfkcTcy8j&F8`Rb|E^=9e#!CZF`v-zx(jE5Q9A?GQ^WB`P)Xt#E};*s&lZCc8xCZd zp51L5T65x+tvATqi!R@);uIG%pWr*S*qUajfHb#;z)fgYk5!xjMGG14j^2YfEGNK%q({fe6f%eEb2M{I7$T*>VTH>-YM8 zMu^yEOV_pzI)sYaO2=yo4iN~3z!JDs7Dwmcrr`O6E_yCZ955N_GLH(yO3r2$VnZq| z)AGIMeA$D;*@rz($4-#*eB!~gvO`AL84lQ_z{DyU>hWZ3K30mMSk#q~$9{HQL=bnn zoc?(;g7O5$v;raKD5p3ndD+JSPbgRtvdrAlW3B=JtQ6lKjS{5=Xrd2}(&s>#tQ?wb z$Uoy+*-v`chA!bXf(AaOMQP;hD3CR&awv zKWT0bGRK=dg{m20LN5>Y2^pnHozZB^Sdh1d@ZOOrm@drO9)&9*g%VetTEEgcjqaJx z*-lUG(=>p8uE5f&9RmnGq~YC((1G~{NtTd7=&_vBs5r@gKEHJ!uHFQriN zfv2j!_zM;O-jEzR%4xNK-lS^gki(#;#$pW3w?`$GAkjxgzQ{UJ7?)&CS67~S zF(N`=-QyiMHcdDH^6%RbiH;Y!I@ zN58}MYpE)KuKCU`n{8<2(!9`c#`rbea{1Ex_jw2hI_ZRx{#uddJJgx|=P!yuFrOo( zGqXojqC#Ma#}bZpLTKP1l#c5n-KEr%aWug>plxN3zsDWS}Z-TFv*5 zT}o}=Lm1XA70a0DWm?4q3$;p=sykxPZW|#6Fs0C{u- zC`-`WJ+NQR=DOgp;gUF=;7h37s3R1(GA@R>Yk)OxOLA?^hghgGb*MtlXNnV<4llK8 zfKeHbrwvNc9guG5^GG6_(Qn3zG@qu4rppL7QUov32&{}6Sxx)N*2g7W5t=Quv z9~}9|z9;kobmW`fASINY!Ke7yA)lcmOAB*UsBL=$2@~@mi%e6R*ymEq-MGZ85%~mE z6|SH1Rx~*WjANx@@cG?O&#yX~&dNsX(MOVSuI>oTy?l8D-rjNl*7^I~iKhHFM}f98 z(dpm~f%Fh>Z)1{PvaH|1%m7GF_D50{)+`eUxaR|YXfX^AbZWAdsl(&(U~QT{oUR|( z2DM_P2plficzv19q>->AVeSt$KVR3(^R*KOoSLQ(kwRFVBbgG>v%c#Y$InV4l~O6l z351_g%z2hgWo=DHmu*yW20!5sn(4J%oI`8tytFHIZ~ZO~qjV=oz@{RFdY58Gj~NWT zSO-aIXuL+U$nsqnY0Dly#V6gmhGrdc5up3L+U99^gVW!~^62h=k0sX0x)&Sqi*gHT zPzNqX#-*2m%@U<6hPH1w8Kcwh29}7mAdJTY3PQDW-W@b|I{0O$atu6=l`0m*xNL=a z+$1jKg)KWM#gu{tcjR%R(y4VK^qInB9%eA{hA_UOJh6`HC9Ee0+s|0v~Wr^55?F^eF_B<0Q_6d>K9m-VmA>ON>KUCON1 z1<806a;5()XptszZ_h2{)1F$5epm4C%}W$5{m<@U&%`rPw-S2gI6}fWu!Us(ePpz& zoPu*@%SoMY^gq5TbGHE&K__Kh6U}?j`cTDBWX>1M!uoEs4xZ1AY?mPO1TF~&2Qn8L zsuX&}RX2|#$DpXoATeJionjxx4D}bd7LOJ&FfIj14*2UJIdX3cLW~~?b)A^EF%_aq*`XwS- zz69ZcRapsmzM3;PEp2T{?6|1jWUj?kmRZ3dU(v;-?oq!d#K2&ZGgY*~O1X?i$YZ5% zBrA1qwWJVv$T4Oa9C|C}?`;I1a!R)dc00h-i~^SixE^CR@?hrqK37`awvdM#uE@eZmwV2( z>#VG9!E?Npr)(m8ROCCMN1=MD&8Lf=bGgapL+=Sikg>nQ{XslcJq`Q!|==e{@3jILS|( z>M7~g)zA}fNB+qCslg7slsISyNlL6kYYJkRbwFoMFp@qSPb7zioZ+I^ElIEjU7Y)a zpNzH==59Jd!~FbelgQrdM&Zq~7H|-Gi;Kh`Uz`Up8$`;X(wf`CLiHIAUi`*gI-w8G zMyNmt5q9`1Q`@d$tk#r=uOA~7YQQOc81(xT&f?cb^8fw`^#RL)1Z(ep#ZYT~r1fRG zX+3B3@E#{4n6?mU%;#9i;eD2C)l*!y&)||OkQADY!)A-|nD0^f z4XU&$Lr7=`ZgKU73q=-!dQd7GDzWBb2Fk`n6`_MJhKErJ;Qy5b6L1h7*_VVLx5})t zkLQ4kc9)K1aPxU|sbPbM+rf0;V}x^Ibb49P?k4EKuJ&_i@tI|=dnwbaN z1Cs?FOZU3EisZw-lHkWJCv*MYw1<)Zj+BBQJQQo5$nJ+jR)!k{D!%y3j9p&b)bho# z4q2@k+n0Qhvm--h8J#~_x2jDT%2!sn5w=b^pyE=woSg6oEH6aY+Ncz)PIABGJC+N&PsMWusQ^O)AcIzR@#fo_tyBXTq$us|yxVk_MG zg7WnG7{_a8{9UQnXh)a}Ajh&g35<)n(Gb#@2uGoHcQR;=nHOm^)j^mC@lMZl1{`c6 zF2wwHrtaRq@2^n)yK~7rs`z)3n*b)r3?8?n8D>ke>v#FK?OHov_`9^$ed{u;gq{l( z=5DZXmML$-m#kx4gx8+D5E?fDi%s`T62c}H!pRbcr+-lGgkJLro&W~RIdvjxE2 z)EZuO;d~{OM3Rs{`S_|rM8AQJ(Q=&LEI6J=&v9_Gcvq?XndF)+l82VT@q~NiJuXBK z$>ToVO-gtKVv5n@J+A{liAR=6<)yWb=+@GphaNNk)kCZ1xSIv_fX(~7ztnp1d5Kz~ z3ptvX`>rAc@%mReHl2)uZ-s|s9k(<+=2n*PNSrMVUBEziigH9 zXYxRwK!m1P(v>klCb^36+38{&>;;z0z=(Kc&G#_fyyhh8PwJFj&4~_2^5I`m^@)cC zjJ@AmSXQZk1$6G%cA%;()bSA*|K82>ESPtBx~~PsVNf=~c>8@6a>tMR&flw}`p@cU zRO!MkCzONgJQO9)Fa@j*VPC#oNuHHWOj9c`UWT_AiF1=#rs|b&Ib7>Wn;+&Fs)BYF zGDmPe!zEnieS3OFVA#MiLg?0sP4_&PUR<2k`c6E=F(^(jrgoF@++#YE5=(cd&2=khpGlY6u2PFA9lMF$eweu0Ti9`BF+LKgV&z_scQaI4@)tpp@2 z*KJgJF@I)qxE_(F{gt19v)e` zH#*?LWJo4?MpHAh*4H8LW_oXbu^;)nzPvhm(OCIspZefMo4dIs+;3}(5#lS!%nLg&k53*Acl?`ool33-73DXE;}Mkjr-0L zRMS_+M}MR;o=bvs>xk-Rp#VF!(lbJqk)_R`ad728*JLZvV&dRHy-5geT|vUoO{_v2 zFOPLJnn6o_BXcUTf}Zqp6xhhk3yQDKB&Y*!6S0ujz<@MJd{p@%=(5b@uH1>fgmm{(mCpI50A%bY;q#Y#x7~s251g@rB5Z`0L6;pB2)a zuE1NPyY#l&vmJOSEtAWiws~9UU2A}XB1tfs@!&`{NikvJ@zeM-vljF^yNATgLXRlaF8N z)m#=RE_)1e-0@oSRk#V*6e$6AHO^bzF?qQEGWZF5eMCzH%*#S z)5~~(@yr~*4Lp^lc8Npe;5iBkVh8x}BssJLO`w=;gFn>cZ6M6m3APS!?=|URbHY^0 zvTR+B;CBz(ci%jXXx{jHNxb*|li&cjz`cika>Wq&jjfm>czd-f!JYQ%h&{xWk$n_E zJ_|rQI4WESZ71FQf$L+L;*3H&{hG`*bCy7DeJ5v#)G>m!L?^yR%jZ@r!LYcvg|!1W z2I7F#PXA8U?ZeiXfg~N9L~sRuZDn`{SfU;!P-6Vs?V)#XTQkN_6I9Au7G$OA_LB=?75X5E5~6?jWDy-2MS1>`=i-*)+98F96; zk4b(k*z)$NBcK=O;45QJumwde1I;O(pKrEx`HoE1ay&xgbTJ0kWz}v4{Vrb^V`Z#V z8q@*L*BkK~TFD)HGHA=!VzNGoEfj->GT2S#i_bEQu3q{LIW zSklFTgnhW91-!OQzV7|3M87CO>(IN(+94Z?P<4}}OuwuTuu|fP$)Bi{O_)h~aI8I%XVu34xi$Oa-c9%osaHdL) zeNVZmSyPx%;5vz|4FFzim!Kg+*5d4ArZlI;a=asi>m}(4X-PhGj4uNP>u!V6JuzF$ zPr;SZX6x9)qea&lbuQ^y^sBSJ9kv>iKF<@!5Fm}u+R!;4u&yGcR~8*7KlSr72ZYUKv>mesQ2)-IRLhxXo&Po zg*9fl5D5+E>q@=02XwB(bQ#yYz!#T!e~WuY;{m4&Po9jvKDW5bHG!uHLNi2Onf}SM z4M2e*JPSf2%U5vyI6zm(?p}911F*}?b?fsJzHbj-T0b5h2yv_%Mt+7PzszJ)d~tBF zZ(F-5)|}M7_p`iQph7hhtVTw#JfrbP1)++dOZFATjz`_S)@Ci?J8RNora@N^4|g8T zTRS8$1Xfse2M#6wy^Wr#uAv%Hzn6{r(5B6p4=k8AvX4{DLu@#ZW{Q`YH_!r>VmB-k)AUk>9>89Ts>kQoZn>Sm*UxdkZUxRD2`A|$m(j9PJauGO zM0?h<-lZB_p>nROMBlWr9d{CE5^;-J+1fK6u^;oS9fjb#OpC=$|8wxzVg2LnmCp1|k)HOw?Pn)&i*6 z`5%oP+p7ScFoAg3aTE*nsxW3HRU0n=yYM}3&bU;-iR`jL&KYLeWK;iiZN`XEhpWkbQE0MktW7XwW zes*FGoUk!tld8ubFhfD+^ZS~!*bAGQKDPz}a%N~w&Au*k8{Y$s-9o^;Rmwl`lvf!q zznR|pBY^spuFYcmSJ`27$zb_2UC%eclSEny%jzXMTsJuhOit5^elU7`$XxO|edB(a;dp@X3k08UdlNF@#t?BzuSMDD*>M zTZ`i==d;3sP))e2*NAIo7ah4t=GG+-VbmqV$S!oUnY)Qse3_7E1->Skau?jHpS-nC z=@9xlNShJlb~KchwZ+|M5VO%;)cL{hIgCP)aQ8=RY)wR|`&tgE6)PZ#eL`n7t<+$oh{NTbZ6Ns8@{Q*XHkq`24pvV z`92^*b(#y_f!KJ(Y!BH6WV{XEdk2so_&G^^%;4#Oi>CrC5SEh*+^}K$SPcBsLx^BYcf(I>nV4o<# zDfrMg@|oQbrhCjqTgEZ5_(^T?UTYnD|IlVo0@pm5qdy<|>(6Cp~fT6$Hj7 zx;HU2K}p`E;h!t=9w3hLmVCyI3PhUCRf|Rd>&0p<4NxqL`wU=ZGOKkF@u0Fb4#?IW&p^Fp45f+B*8^QmsK-92w;Ybnb>m(38lzP^y>gL{U@3@f&ejpe z+pAx`rI26wy}VcS|K<{H2?+^#BG#EA z)TsG=^I2?ww`qu>VY?gm4?PGA4+sz|l@6%XNM{^M{Kv}v)6rZ3K$nCdF7+qflp*tp zAq`|@X{R*zhmk%|WmryTZm76*QYnPtiL_Z1FC3pMUQ&so7aHDh@Y{*WOO!p<6pX&c zKQy3j;>%>G-_P7OJb(GL&K4>klDTT+8)_6g_%K1K05@h-D2-kOP~#rfF9AESS@8bU z<5x=xNAd>*szBtneaT#$3X{|K+YT*Wm2}bd5@PG}6#fhj^=!WfKy$HjIy4GyJ* zUbgG=doxcXB4ioEzSaEB%M|eM#MQrlLVci^131?ZEM^|hf!YW3Z8d1@h5#{%hW%h2 z)Ox_zL?J&yPi7gP?pe2*aA;`9(vI!LWQOkgAcRIbjAc zqQqtSdylZGbOg_?3|)6MMhS|_!Iy^oY~sslE$$tmm|5W`T?0YJ$hw%^=hhYc=TMG|SEvvbhms=sK4AN28yqz8GfGqLPvnB|=qtl0&NABHur+$jhR6R* z$E7lLu)F$sbAqR2?v=V|NcDvVi z2Axo_DJQ_s*+-SYz2nJUPm_3E0qAcU^SpGdxLK!^zU=<=~0w$d3k_*G|EX?wI(2gP32 zAKWD1>B!=8IGA0W@gw9(6uwOSE_)UIDD>U#`AgUYccfDCw`KUO2dGIm*6*Z|P;-VOt^=s8++)vKC{5I) zvVH2nK$l)w=C+T~vRY(JlJ{fx>&pb}Bi%rQHWV67uU`;_#kX)fk<5t@Z;EqD(0+Lj z5XE9g({K{bY-C$xV(%KChTr)|EBj{|V{}8O zcI}e9J&#Di*tZE=@!+EeVS1Mi-tma%y+-<>sU|hCEj95jwea>XWS8QR`%3m|jz0v_ zHc2|fyQxc*o+^z9T|)byU89`is~pJCSy`n-w!;>s8DzUq-Im)?s9I`s&|-B`W4o4* z1T7=yAYQDbYua_@@uVREXlD%la{zZ5Hh3O=H1rFug^ro8m$X~rg$-1eSWQLK>*nQa z3YXDr2p)7W)M@>nTIt!o0a+OsrZKS>ZcU?{b}tGrPBY3yb@wAGw^4^9c1W4bQmsrN z(VG!Mo;kStNtpvsy?9XzVMkEPV`_06GiC=9N5b1S9KTPIz#Wanec#Ws z%^IOZa_iXsF@i67yf#-wvkOmm*W8rEhExf8@O&(1kdHwx9Z&y}%!xw&vFrM~V`yg_ zOn`h_SDD_rqI$?Bn{B|jI*29)A4q@{E>f(ckEhFMBuIBG*Ma+Q>7d2hP$Y*AL%=RR zYgM+TM?0f;1wQ8(eqU2KS@xLW+p)Od!3=qJA$)?Dno2Baae1Ex-ejJN7*Ul(Ay`P_SBFcGE7CMJJh1p*6!IbkZes z0QSTgl42$q0VDPy&pws8=uFIBD73~pdz361r_{DKGW0r9pLD7f;c!H2hfQ%_Z;Ci% zk-A4_hl#ybSzf;G)pGu`*3#Dtd8h{yFWyB{2*M;+yNWOC4=&m$zOHk2)n&ApM|G>~>b(ts z^8sB$84-gtg>c#L^sX86_|R1GA5C2*dUJE(FyV(a*YAi25wEU#**0<0&7^pFjOU$H z(lHd7TOX~m=q3uXNYBDO7gE{wn6CG+Iv-wYJZ3R2R3aj$D|V^dwz&Uxgotnl`uVQG zO#6N^tTlA)F?cHg*MZt@Bc!Y`QdB;K>byR;8Iipn*yEuR`IPeFT=WO?0C}v`1H{e} zRLh%|quj7x4D-}I%7`j|2t8|A30`-)tCo|A(lf!(Wc^u(CkLf!!pXlr3^HHZH)rR2 zW}7FRK|xGzmjRONAaiuN6~ahwbPZkFar77{JOe$v>ROrsm{If-%s3@rd0egQUjrPN+U8j%SJh#wC-{ca_27gC+3PHX&s1rYBA@0iUs6PA*ou?<_f-ltu7J2BU?8I+J=k^kmB|=^+3`82n3-{fZ=8qT6aN|be$h3p-Wds(U)DlqS$U8 zi@J<&z-5FZj>&ZsHuYV1e&!?%h4zLS<%>)y4=<1_^hv zzs^$T(W;M3!`l98A;6i|`1u~0tJ z5k)}LH(bATu)sO77Np)Jh2tahgV|z^Z*KM_Dy$#G9lQZj`MU>C>LXoAxK1r191T^H zzu`3r$Uo-UTeNu1jL^fB%pl>Ec>9RzDcOz(AT5UZ9#)2yZD6=brcrz$*+c{ED)a4J z%d=2g0XmWmXAid|KgiXKG#$q+W%{^;M}VIee~datNPfjw06$EM9&9+c>&gdsICHnw zLHbato4j!$1~i54&Jxu@TA);&vh`>&@vRx#F>3Mft?qaLz_1&H=O7}36bDQI1i%E~ z9^Ufz*P-%fU+Y@UJ|~#ke6lL|-PGnaWT8l}Gxd2;a&rk{#@}h+#gx{td*PQ!gNf2( zIfC$Wtnn85N!mUnDz7m-<6+{rF=Wa-`^mR^Tgl;m#r;7L#L8B zx8#%-OdP1QuX&LtaC{FzC!p)Hr(m-&PFpT=Yl@gx*4ogbe|zbs7INjW(+^`J=Zl61 z0!9q;b-})h0PQLpL8(zYDq~Qe~ln}Iq zSTLJski!7czmSU_Qg#z@AZw>TpfXZf>V8Ct$3HY8ZsJXg{hFiaGXc;fD&4kE?N_Nm z=ir0U0S+i*U5QXxwW9#-cK-X}W7EUgI2wl}KStm{cF?uR*;!e2kqABE7}`I5o2Jya zubDlk>ir`rR?oKx##?@f!sNwmy zaD9YX-~-c)RNQt{c(bx|D9J{Zf=daYvA`L8-?0IY`v)f5V)SR$tXGHA?+C}s1Xr%@ zpr1;`he;)e;WgfybKBM}>)H}3>)gkqn!4UJw)5iU+|l72@oCT=j;!>aQsC2psGXXO1X7laaAX`?wey}9)-pX))~axiKg-yq zps|k8!VNaSx(pFxO2v|JZg6kRKF-%m63)ZiA>XmLPaS4n53J8}uq9c8xk=^{{(ufP zgVI%$sTbe_8joVIPCU_wIYgFpAuB2qTTs4i2k9%fM6fb_osPsFSw;cgUjhg*+S!uo z4U07B@5pOueVE4XmoyqngG*I5Jom_tP}>uk0P5@G?cN2BnH>e%W@4Fpx4r)ADwbA zQ%WO|>v^`kF5%V*$K0{IqLiAXD%o8>zB7KhtDYmYc?QSKr}*^dh3~o(c{IItazeBD zr%5O6v?wNp?(Dm-n$tgGQwA*(W*aaRnvLyg$1vV__RX4m4D@=vhd>y`#X6a_7BMJA z9)l~yaX*ybi3J%dENc}(2^|Ya3*X-L*|oJ!wN*4CCflb>KXIZ&WQp4yA$X#e>#y z`p!(_(R8S^NHfkdjUbX@rAx_Yo8%1r!veq+7Zhq&uY%P!L3vZjgq< zp#>$R;ZTwXP#V4)pXcL@&u^{YS~F`g{xNH2^WJ;k_jSLnYqM{=Nh&8{Oprw#Bh$Ag zR2c36QJ~!OT`zO&JytMgQO_7KCV?`L<(7g5I-|cEh~$aU%&qjDR6yecllYO_|1FX! zd7s}r{|-=A3AatfQvI&;9fE&8%13_<36T$>`#h4)FoRt>$X0|SS;s`?^YNqa>qBbh zNRrg}zA@h*@jEiRgDbn!(6Wd4XT`U9Y}dj_Hd>$QwwrAP)NU6_X9xsE{gO;|so;Az z^Q%)VLe?Ye3%IpD%ECk8vx_DdgY`BYmyXgyiJvYDJQE58QlOzr~Gj za6h^KXFU@%tzR3E{9(kvpIa5Urz0-1x{R$M6Tt*&t?v$OI#Z??q%LD$#MaaHeVC(? zDnoB-5#J=X@(BpQF3~2^pTn0J^G!M~wD;-fmbJ6oD}Be_jv=1ag1Vho7yNjwHf1Jr!QiynaukNfEBwT3PkAVI~;qDJcHS0|B0 z%Qsb|*m`d_*?jLApUkfdBPYA=2m=glZd0TnMb!Icuf;3^jBx&!*H;(V_erfyjwVxX zj~neVRY!M@5hz};v^IN8CbBG*AsXol)$yA!))Z0@v1aLyl#1wFqVYv&ue`s3JevL8|m*%Jt=&ohBu%TtiWbd(kf+?T-D9bb5Q-yN z!EevfcxuL<3A4(67m9}T$h=NTyhM0KS5&>-8_m2u9=~+Qy1vFnd92HLo~eBjc^t{b z3)bz+wI@dVnI@T2zjeM|Yce0_iLb9*9jCx%&LRH2nQwN10YYV`I3+L5m7#BK!Hp{c z3ZQOi4rJa8uN~idWTUvac+xU2W^K%NK(ynZg=5F~d*K4etq2!rS1O4E^ljRNv*hG_ zU%IO5H*IK}w>)k+caDNgSCe??Xw^+i;n&&?J9zfZ)AaCg)={RtY%4if6yaHP<9S0g zB@C+x7R#$k<=N~rELq_6yR8gmH*n1?mHqjw3uM|zRz9K`wxDo5tw(TGoW=1K&NJ!k z?vG4ANbx5z5<_#d{rbYD;;R#Z_JwM2)OE-EFCRAz! zavOdh9lX(f^9AVfbOsmim6#ix%y;134drr2J*+_z$0B9S`HI&j^L?m(hFCS;HQPrIw9Ryz=p;YM*9H9X8(#e z3;&X-3nLJ)8@FhF-i&$&>>){$_o-C_q%a58$TMNo*@ah|GwAv%$<^lEa;r)t&E>rj z&DeLT=v1k^)`uES-~*fo47k%I)$%ajw-;a~5z(eUJCw3Cs#&D@^2!-)W>Hkdob>nH z>nSH(vXeSmHImAmc;4Plfz*lu2)Xpub+P;uK?Sz_r6nciQQS3#c`+hR68}jA}(0Jt2v(0;~L}bYM zK+3Z|&44=*4oun?a*?QpFFj6yw2@&1N-2n)C@_I9>HC5Q%W zt~d0;!`yh-IDPN^Vr>US0$^%Vq44Gfg~53V5hH1NN8YFn(Ke;2eQ&gx(34Cl z^4011C7NN|y)>WDxa`=$=jkx%#D$z-G2qK4-_5dD;=9J6tI@U`^ZlBgK$w^XI@1*g z*Nxe?iUBsAelFN_Y07EN;Xr|$nTdV+G>}#?trD^OaAdle)a#D4feyfkTZUG%47d&cagCOsgvF(p!EjJ3j;eOy z&EvK`agcPdn5C4cySx9}chVyI!IIaXV)0RX*1Zh4;yw^8mF3d}%d}N8{OjntHh+3u1Vp2F&ddaOGF1vSDlA?E0zrifBzN<5!n4mg_+pLq)j%8;kT6b#XSAo zBnNK-k{+%bJDuP0K$KDI@?xTai!;}|7bHtwsl?AyCf~VM@B;;*T2D4$25ez{5g>>w zMomuSrvcO0@&|L@SeRKaxsMb><4$v9(!Z{`jQ_dj9{ZW2DewdF1fn*7*X_--%GKi_ zKUnq&Z#`GPB#GlPMFxR1zCuTcB-}{10_T}Pnvz~$+d)?xQ2;HJXcsmk{z_IXO!T;C zCRf8D`$ptI*HnNVx#54DK0xL9Qr}n1X*m-SXNwxGy=!qrI|D5e%pU2$m;=8Q_$H2y zIo0Kj9%bw(h)_`L7XX7n5wu^sv#$8I?#5IiF`RVqKB&Ah*sj({hBoY8;|*oYcfAk& z8D(Qdbzpt1adDsckE@p3l>7gy83|F~@uw^Ori{>9jY)7q6Be}F@mbr$17{2s@+X{{ zULx4;&ZvSvvmVO=O{Cj*E4H^^gy+bW|Cufi|0P}~h;(!!EqRQk@X*!<#_*Bz6axod zpIz2xtGA8aZjNAnSG#E2!TerwM})JV8ncRN!-<}4S4`B2_LPiuWOo8jvNp!Sf#85x3DErsE(pLhEc(MG{J~c*%EV?$X5N2Y6AU@inV#N6FZYD}7uhb{**f zsF&hpvpZn+02-S9{i{*br|qRWIoe&>^c!Zs?=|O90T~Dy1fq2R-jm;VTw4Fz(0f31 zr>gzxujh8LPeUR)k@iRFRn6XCijx+w7^J=0aMAyuA|p2cv*8@sm%xApGFE_|>L{U) z-K8U4bU_a)6Y}&xKKYy{xD$w_>xm0{Ap7uwj-_C3SF+OS1nvmqZ;g zgV_=hr&w<0QNCc3lQRRXpOrvDgrzI8v|pLxO#fjg6U_f+6}|_rruSRYW3)!47E`Hs z8^`v~mKf~J@opO+d-`wqWQL5BLOxD;-Wi)RMPD7dU2&Z$)|7#M$t%>E`L%ZGLixkv zNHo1}bK0IyFquH4HB_ly3uG3eaM!Sy6huoh`!VpFY?dbarIj5ST)kgCbn~f+QB9oc zK}p=udzrH}wtEHxFyTO6FttqDsB%fLl}W_$!{=xH9F@{>o^n|h3aFY87wLp&S2iehN5oM65UnM5(f!Rm_XVj*S0MG=LW z*57&MvQwlnPXf#$OMNmUHp!AX>?4SAAyJrQQ5?VY#|oel72a?*o2n@)DFKENDU6_d z*kqA^v~QuDzvQuzAHD;6SWccDKMi9IX+)fD{90~Z%F8vLY$e9=zC0$h-==RN-fUo? z7h8LTpI6nJ!@U59`)zik>kSBJ)wk#L>8&`^o2<1r>mgoqnU+T>y?YmZL!?aN*>!{c z`a!$@n4|D&)W?vV6-_GPWI)$L9b3^e_C?*Nk`I`9da9Sn1&-R3)Cj&TVg-rp!gs*1 zH#o^c9g{<6dF9NAeL1vcX**ak;u?UiB#^;X+CYcU1jfalm-!yoqpnS7bu-bAwZq*^ z)2A1;ujE8>ASWt5l>p95U?7TyBEYS;V9;^er1%E;J542BCYS`UG*@XV_i0lXfqfTp z-I2@B&1Ni%x8*F6!T&4)bbf6ALJF$F|6Z~W?-ZS>I<%B&1N=5yjW*ZUsNX1tpQ}lf zZ8O_;P)onGl@#=mC++6OXk9%lzhuXj6s+y^*e#=(63mXOk6GB1DGh~Fl)oyjj~d+U zdsMP2>F2~>B$Nt9c(1vdGC@i~cI<#|c8qEy%41C>UY0f|=Z~}a@@7T8q6545Y<^$@ z#^ewR#%+|qh!9)EZ-?G{r3*rKY@fQO0~^ae@DWw(JxpN-+fg$-iGMeKQ6ISPo(6EJ zNV(+S-pONw3eqWRN^n{8;X261%K*()T9RVZoSnHi3E)$4L;QAZJ^G+&VF!d6Vt44I zm{Gmt#jlUxQ2$M0&X2;wJc->-L!$s7UBWN3%~dm{)nh(}=LsHc>ks;5)^LG2OlfQEMRxUbsOb7o7i z1ofL#S)NPl2ZaL1@gyBzk3e--B`{ws7ADS~%svqjrs|xI{bEUh*R#*=chW#7_nnF+ ziaZY3*qdzRKs7Zn4devOq?O-*qw{WsQsoMA-}7q9+2VJ;>-BjMll;%BSuy=3z~p~x z$g!x;S%q9DF=UYq2ZfI|Sg`qN$*{`{vck*j54o%^THkq!&Fda%C35WFLGT63;edau&5Emgq~}ZaUl5{U&B#gRk33S1YOoZKkt?H>@fc zPP>Tyo&^B?FdNhWq zFR@|Q9rKsWe67TR!GWi3$PQq?wDyg32w_0?^c4Vo0)$azCGQOrGDyb1Yq(lFh^40P z@CNQ0NH(&pYM=oF>QVUC?UB$4miNoJBhw1uOA!LN52??+Z;d>G<|Hi(L-5Dm20qBR z^J1kx{S16*Ku(w|`d8l<`?n6Q^DgcvOR&Cq;lu}PIGF&?%Y3fm5V>PPukN0J9ea!x zIuP`P49~)TtX<8ZeM1Ry<|qBx>nC%no#)FM+E0BtSzTXXgO+MY;_uwgOfQJ+HM*=e z`yF8&#mLl8QK^YbV*qq1GqK3{kKFflQQQC33XTm0nR$4gv#NQ*yfVnO3dZAqy3e`@ zlP0ye9S^I*H=>)kRxPR?9--v`A^Gh9En*2?MC2h1VB^K31Ko)q_f zUZOoK`elvSgAKF)LI<3v;pWMGeeW&dF#~_!npv+G*dzapMZ|zq@aNM5QnPEyqYfkd zTdFg^c7xX8`kNZBD#K!Fy3q>HKX12V+38=O8hm+5anFfB?jY{5!}qwdsc}9wyt|Fn zQ_fw|@<#7epsytpSfzP6EH5<1VsE31hl4=~7>E4SYFsEkJc{n1l6NOu*3V{=9qY=k z5a`C0t24H{OEiAj102UpH95LxG8z8Fi`Sb7XK&vcatDkcZ|38+gi4GNt+Zv3O&};3^Afolly1SItKsGRWLD;)pNtABMxHI14|(h#Okm!|G}k8F(rOa5fM9hvwC6)A9QDyoY(J=TSAXtE zH(_09OLf_OXVXo~0BcqRgVP>0FHUxR+?NyiYlB^m36u*r;vDEwoo;4UsCSq+A7zhH zA)uS^nCT&nMILDKa(y)#oy<>*nvVx|Nz6l8f#kzUDxHkV;Y+lcRv-f-)TE38^a5Wm zr9P^}#(~K({TOSv80_PcR_sbI2xJ;$Mcno|$fqMBSp?#Qok9{61T8IF1Cq0i^;1FG z^b-;+qa@}o7I25Wx`*lK#`M57%HnuUF1xf$Ng}@gxd={cH{*)iD|rMET8lBbFfEeU zfa8lgBBw;OP&c{MdD7w4yvB>x0&bgKVd@fHh&f;l|` z@82$ce0Yd~Zwn&)|g*#F<+@+TkG z2Rjms-x5pysnu5vdtS5MTep75w=jb}d6*yc{{2U-t$op{8k*H<{;XU65~)LBY+65x zpD&;y3Dsj6oH<^5yDlU8*ia~cb8-Q{Nj|=b2>R*vkZHtqw^d#$D#+LPd3kz6vR_Ls zCFX>4^)xjE&LA9SVHlv&=~SJ&^LpYS;|r8IlaUZ_aUnsuz^L*FGBYmvG5uv{!Lu+O z9{AAU{rcJRYhds(VOsRtW(Q+ZE4Z?M=DkSo)W%}EvMH!uVbV43w~~n!7LDiF)7U*>hK;pyiOaLAJB<-(!;jlT9WvC48?5=06 z;tPu;#sS%@WU!jG9e-O}?knOJNRMj&8ag><4Q)aGz$M@ZwWD-Q+Aaq!uHU`Bo5y2E zXWMEM_nPnJl9aRF?9#r%sp5iC7KlJrq%*WlF`j2e^xf1i-AC%$wVwp;CHn6}<8}os zoHubRuPs0nqG8$oao#UeyQNfpj0k*Vx5A9xAEA{AXF3U6?4s{`CSL9u%rb{5rO+Pk z3LWm@U&6EXI+ZpRf#I!&ozu>Q`vS{FN6SkzJtB^tig0#Gvah9QUzmT}!L&p*7UNm` zDz@=-U~0_M<7uHwmM%IBv4HEVM)S6)F6tcR#ONI4d_omkz7)}cHk&Ef{QPMu_l{hEt568sqq?k9O={gUBrw~lU$g+ zCg8&@3dn&pf?`SMO#@9=)BQx0$GZHh;@x2cD3;`s7t2HA@R(xThSaz-4p%bm69>%K z$4hh2*Z+tH_p|BWDDsw#WY#1*7yKY93%i;7i=xk(&|)l zWI+4Xt#C*&RQZ3=0W`biT^!jKNh@eq)SSt6=ZqKrm$n-DY4<}5cgyJ2?Q9$q6qIxB zVXDg~8B*c!yl>HNhuXn808h1Bj?TW_ITZVIC*~cntZVCcE$V_H?4~#{bS&PpQHd6~ z7$c9mnd^hQ=IUSg7Jy-jWD}-JPMlz57B347npl3dCK2SCKp;M{IM)ogou>n<1m{8a z9q)=ki4AZi{%HjjnZ(?^{r*)HkfcT%!ba23TEDx@3#h?$R}8SkUvY3m>=E;p95{CH zO`Hec5qFp{@;TT!JYLm|OH?(B%Bnc{r0R|3C>G~@tI(N>&T4#jf_&COdeG22c9G$X zhHSJe-!|wTCd3V|HbGRit_vjX{0^y=O=lcnv8f0a|J((}rW(^~u|-cD*!?alB3GBe z|Be+sw4aeVYg_ra$u8;#d5Qptl_fT2Or9>?^Q2j10(gnXnqrm_GJV4>|1CdXI3IbG zf#QDtl;cGwoRF%sM`Na4{LV|4^HYoCiU{;KiH+*54BBVP*+ajL?jyZd&0r;B?pC50ewFuZC{s7TibNo5=&Iw>&8#oHObX=G{c_*T7af_6@S)D*$W%)MU55~iBbcq_WjlJ@K%Yf@Qj=KoS)SmTdZ&}ST zI}C&oM%{}RTTNO8Xwr?C)IkjKXrVac@>bx)=i6PfAgWO5?za0y3sQ0K{$98u_ROu- zdA6&BLFP}2vDBT^!2=q`(`xa)AaZaKH;K1rj|149)Z4--hO#7FIYN!ffKlzQZ|u$A zt)bZlr=KBXs;C~(%Jmu}K}s_54Tzh?^RY$0Y~8JWkvXdeu?*fE4_0{>-#Bj@qnhR- z$;$9Ccbyr%cNxbWZpcnp*AKYP?U7kH-g!O|_o6Ne;EFnfW7d;cE|CprbolMVfmeeq zFuqe%`VOLXw>-2`8N;eQ^g~yb_8FPfn1Dk>3|urMNRQXJCCoh++)}kgHW~nMxT)5* z2rN3xz11GtrEA*xE*@)lqci!gCm2$Bt~AmWS+?W1GO8qk*udi?$a#61LiSMRosKJ! zR96md<}sG2$nPea`w+a{bZlb-LIDF8JSGFF$WUJfz&Te^R<6W<<#SHjJ@0C%2#JwgKs;5pgZFpU|fqaEYc^R|}jdT{6 zQZ*g9=-MB2#R`Gwpj)LhWBZia=5Fm#2&{5<6vT6m;7)wi=t~B_0w75*W5KGNB~!v* z05Mtn(((HPQ6MIx`g8m*(kCk|KtcX(QTv~ZH{|aL*Qj2=T4a_fgDJ;)*%C3ArKN^O)VF| z(VkU5awr`Y0+5WToNz}xzl)K#f|(pcaV&M=IwhU(f+u^7MpzORO8Pn=z$Dy>EFL&z zxcrVtweZY_Ye=jZ>eyS)sW8obw4X|MQUz`ocQU zVMKSsA-AYyg5&#&a66*H9*ey?Oz#T&SpSIL>RFp(-orN=1|q9Pob(HM{w)TpBWcSH5{krQWtOmaZ_Q@PWjUPV%q}xOV>zB+4HpGJ~3Z#h9NCi3fM&JGc#*kE!5+ z2dgXC_Sa}YuKDARhHw^9RX{0^;!9Dr{6y&HNiLjVpp>Iw+0 ziu5mIN~peA>_xX4=h^AVgjWAE(ozT5Ml1?RRQXY;$X`J97snHf9P5{6zdIw2mbaW!W6A&sYVqUp= zw5B}<8jYLyz$#*r?4*KzcI28zWQ7&Q3f}Iy3X}@QEzw(FrC_#I&+s=KpQD0y@*hni z60Rto)b1KWIdY1oDAAr=T?|YDJtiaU(>SA!H z`NF2wK23!h4X>v8(ZbHIn_uk6W;ZMvRTQbbOsbJGlA#^c2f`uGim8ZEP$=Adp8x;? znT`-q!3eQxuyDR0NXmX&es9HU7R%*7=Hya}*LDKnBO_jUWo|!G{hnzsWMTpY5?Qc@ z^l;fH%**)L+ylDdaI;)JO$Ssq5*v71xtj9=UxYiM15fYKKjV-8&qC^Z zt+P__>Nm9y#Vp*@H^hY`1F}r^`n*N=6Eof4CQOAuCxbCvh4VGeApS(SihQr-rUEmtBxJNq`~l}8SnH&aaD zuyRPsq%9EhiKeEwz(3MV{{KvF6G70LJEUTgD^B{tqhsjd!X0@&dI);Z6%6nZv(+E^ zd3v{rXQq*Y-xlR+@%W^S4s1uLd6Isk)s9`3!>CoKfAPYbO18bJINQ7`gX{FL&EA^m zCFX8tet)yZP&mjYkk~c?+5vva5{;h=uO*H^IFGyL<~6U;tBoAy`b_7@?ju)eqJ@aj zV0-Hna(pU{rS5~D>^gzR`dQ&>zGntY-t{ux8+sAs8X#!xs@0fC9oiJDU6k78DAYMS&EM)>OvJZ};NMsu=U91O%n2=M6|u>=VBB z^2yTAziw`PtW@i`JS6^e53{@et#u*9PS)~Jr{@rr3?ZC=9PQRGdch%>tti^o!Jkt? zFJ6!~p{AceMCR=9M7HYd@rt50$O)G%DE4^u?e|`cPx+v$-4vxNorBA+svrxsrO6qM zrbdDW>SHTC0*WV7TNaCXsR|K%FWJ_+@6ir8NSW63DLv@8N;H4Q@`+Pk)B^papTbW1 zVdA3Q*+Ey!bPVpzORp#vQR6){^^!LDn7_v~wCg;-?lq$V$wHuc@-$5j+k;4@uMW&m z1C2IKkaM0IgXdNd9=F|Dhn6&?zt` zi^BYSAD1R5nL#Ej=Fz%{HUmp+dgdn5m6{X_s9BrbHrx#7KLu$uIk4 zlUaraw17CrI|^l#Mu8A5EnuBJ!c(Xe4Fab^S^0CdjqEG`w0n}{C_t<8djt#RFb_a$ zMaI@Y4{fO_fjIwPR>}fVoNj(yj1UpoiVHJ-cdMn_m@ooGD4caa1JJF}Zm|0S&6sx{ zn^H5}0oM{#P{~2AnCDFxb>IL9&RlULhcvmg^_iO%*?}784r1R7@#+UnpE3KR49o*C zsoNJvyNbH(y&Fpe@=`>iBKWfzPk{?IpJmyDEGZ6cx5BehD$F36TF{(04nFBTbcZgJ z{ZBouVfjBUDK7ig0JNsvc05Ryz&h=0!wL{mzr1`PPO#&2IDWp9?~gYB({plv!Z+>b zufiCKr6}r3&&!sb-E|s<{qv9Z+GiWa{Wh^$Vag&CHnKGvbD2R{=L{Qe`lU*fg|MF- zm#+_ao6qL)Qh4-a8rA65DtS*ajSi9NFp%Xx5n1z5mB&cENU_;hrj-Z%ih!M zM{;S^qMMy==U$cLIHzBHSLt8Sj?PUKEx?nu8V24=`=IXds(54^UhIps44z}g!8^R3 zk6WakpE@ARmMm-CPP4DU1F~1yMqqN`ARnOWkn}xgsf9-d-zstLC2rg#=-aWJ zRG8W^G1#XG!~hG{MThjDW0)c{BiC;r--IP-qAKasOIX{kTi0jcmb6=j%0$H^qeT7b4RZ~K02H>L3Nl4K~m>o*rb?<|hUSx&>n*sUy{QqK>b zoG|rBBzIpj@dnmwqAh@0Y9!jIXiR?tao9lAgReXTc}ECn=5Y0kXYhY*DRP~SQ|pg^ zgd<>|s}3TR2nUAXG7psTtd}XS-scP+QL}o`v(v&z0>%yl3mr zC@u~-1@(PXQ+GVG6E2&Y)u}Jn8nx#fzAdEgo^RSeJ39W(@Z!DSS<4gY3j-`YM-H|a zm~RZo0JV}Zc}Uas_PFKK(F-k7wsMw1_Z;62XLndvHhjAS^H5LuHmSACASG04U~6?& zhNp7T{JXu>apcwCsoS2hUrMLDQzTvN5Bi;M z0=EHIK5o*b#ZGfx-t8$q!b@}A3Ivq=9x*Y7dj5x8#RQ5?0zA1Vk&(D=MI4%3hO(HA zxdFF-6oya8kr8v^-VSHXWmF`~X93BQw$0L{l*}*5-Q2HDkBetlR_+g;PSYTu@vwa^ zrgZhXwMPX$UHqt|K3${$dJuUcbx2Zdh6hiIlhaN5?nN_}N!VS1TMy2}eQzt}vv~sg zV0Cvl;G3hv2o3`;$vlnTD?g{=7zwI;QqxJMv4CtGmef8Px})^4B*9)6S%|nm8Zv(1 z7Dn1b=4S~#u3^ik?-Z+$C^RDx$UIVo^kVDjthjR^nc#uI1 zO1N-|!oW$jV#z$(C^BbYN*i_VN_jIkRd^u= zO&9FCV|Kyh|%kT9Iy~_CpvJ zlz8Ah#C*svNl#De@Fhe|@4oj+Ww_{3@VAfHh6EeyL+H^f;@k7qSi>=q`8ru*H6ODA zvU!OVIlc(rOIgUp!K%?1$14km7~Bwor<_3vA%4v)VQh-Ico7HeE<7p}`rAyM3?5XJ zmGXlS>G+QO?KaStC3WjD>g{oviXX+T2cYTe$f=IVi_qRXgES#(hDOlOWGG5G!i$^6Z8;VWxF7}7r(CZaazczYPy6<0{4b;6 zCwHiuM5A$gLpE1@~qNRatHPk%UAv<=QsGmBMZ3NP44y1b*{x{ z=6g6%+Gwp$FBbHn04Q>W66fuE$@mVxYch}D}^)mIaXd~ zKBQgyP77VgrB;(j{_!31pl1aws|r3~8*96CRruVKNdmezt;puXl4 z5%hSMk3!NlPhSCPST9CKbx-6FoiLF~qaai6m4%wb;`|*akBlb;hVxZIaZy4(O?T5i z3J9A?T1LiMrD60f-$%U-Ms(f|6Ai`TV{ll=cP)Rh+_PkXHW>|ekH*^gGA>C{}% z;*Wnp&zhTLUiclGv(t>*KypnEE0u-boEo^_k&J#yS;bv(OxtQ#>#RQ)MI~T{0cpD% zFFrKH;bc2Ds50xbS>1#BNko`?np=z~oP+-L{j($m>DP+Y5^&<4eef{+UB;my&BKG` zZd5IWwG{T6?y&%=fi#-8li%a-1=1oF#tVDQhv`yo0#f#b5aA7mzPudONTD2bAvMYL z;%OHGv} zZ$fWDJR}%Mm=*dd7a*#!dOO`k5V@JxEn!Z^;1m2?WzYbG*v|s<~ z1&>5x=giUZE86VN&MFCwC)8AR^)Y-jh^6PnOY?7U5i_?23Ovub^vlrQz3{T+LvW-L ztof}hR^g$cdR)>4%0FZpy4%l?=OJQ^OiKb-E&e$KqY=Blcy z-fwgMsU}H@tpELXSAx^hi6=W*q%w2>(0zkh_&}ZK84+Yoqm+uezmlIj#T|x@;vh^?lHl$1&1^u z{jBFUgHd)(ua+`jm(A_3{%VFa-fDT{)?x3T_nSUm@Ciwe5NEWP+rwS_P%IXoTt<|D9$UNCb=Iz;G|SZL=f zv^O{Et`h#$pwWh4!NDVE!#}(B_FmoNxXLm~TI`SGZ(giwsJ_6q^hKp(Hx+PNBsf@y z^q^8)GY_@*`$QkyN*d>UQlyv}HMQm5lDF}6^?L-m*hT)*ts!oNR@L0k%O4Y;_R)se z-myGhI?{op6(Gi>Ysni|6W&6! z^K^>#XzR8`nx?~2+a})M=ip7~IHMX)<*s z*K=X+F>c@F`dN*oMk@sCygBS{a;xhHRR~5JHp_f|^*8nWtm_q#T;O3OYZy$1`Hm|Y zbpk2w9*y71HN!{grlAU-<-NQlxOJ*>HQp(!&*}ati&(}8&vYOC*;L>MM{*X7yOa`+ zaXCMX_D<$A`b z_{)x$JsJ05o8JEDkDjGa3n6y5oX-6FKSYY)_R=M{9ml*>HyC!CGVklqearGZ!$Cfb zzAP1f;1>mxDl%I#rdfU*SE9J%C|bc{3xO0>;c>NsWgJ5npB~cZB`R3pq_UdA%mF>Jhncp=plLom_TL zpYRAz#j{JCB+YGT?&(z-`>UZmk`}Rdlt!D~s&+@Cj`xG;2NLn=^t2-nDW^>%mxz`y z-l9*swR?TMEqpF(!+)J|ycvJF^_F{;zAl?LpgVvA4RSq9#^>UDVQaS4TBwnOTPdD$ zb*)tf%xC5tHtlW`kvVjkoRnNSFUP2-zt$vnH8DxO70&ypcy z-O%y#DK|O#XT^^{-*Dp4|=Z7|R;Hh+?cbP+ogY7UF+VLwiE91U{zjB&(&!waui zy_^(yIvTa`b=4TUcXM*{bhX0AS@zzjky1umo^GwF>W-0!Q3V20r%7WS;h1d^=$1z z-|Eb0e@6VPM{n`%9%>W`Fj)RLYN6e<+8i{ULo7<|WJAr|oe)s-3-=j|A>UR?USB;V z{7t_2I~P5%`T)W7Uajp_iks@ZPIh-P>w^^DcN|AAh}Tr^LnMXtVN$_5{$7_PdFDljR>4j$>7%^V^ovS_4?>IjRh;AfBwBsDWek$ zKhA~4$#Dn&F|4I6Wxuvv@4t{A~W{ zn^}Lj@@vy-WUvpxsUAALIUzDrvNGhGJ=M5A^Q`^k^11sjRm#1Y%jU(;VV4TSrR&Qm z(~j=+tlrV-jwJkL{0#ZQ^A4WvB~NQ-`dYzkSDPw6D+E7$;K6apSG31OOB&w>dKNJt3l5|Y>p05 z`<~cp228kaTRIm*(5Gk*elRc*;i!ny*PDHR`voo^IBjfP!#pHnCs_caV8z|~Td+@2LW9`AB$*Bgr46Xqz}xxq5S zFk4&aP1Q_c?tCHqS*n~in9|$(34JW)8aYw*q29la1s`Qov7n=}1MCdrwH9&KVn1h` zMJ4rR1|MUKil$nAj-y2FQzNG7th7XNmP|el04sxRWp;p_^gPlv}*D$eU^ zq^n(9HCj{Xbiz=~=fyebgjXU3rmog}1*+n6lxD7tg-)cVvj7^^aY;-0c!RfD949J! zE!ZG`a9GxcrISO?rAi`FtF@CQwRTtFx+FZIH%iRX(v>SgHZdYquRuQbvBz0%%MOpS zygU||i)8totp9Z#>mN*E{yB=6nMvKzt{oWO);%tqsOBEDMySJ|upj76@ob@<+@5q< z^tYX>;@+$KrR3@$Mu)A}0(1v{)%}1MKXROmk*LU>RLV@Iq13+b27bJ5Gi{1Y>4>H% zME2&-hqlC?O->7?!7^`*54A4_Mr6imLhp4Ds@7YdRoiG+Mm)oArka`8;Q0Bz>+`{q zaJQrQYo$)iyWzy8C=#~O7`(cW<1?+bAsNrz9gKrSp&*6S#)*PMK1rNPG;r)!nSizr z_$ceHNmfTb&*@Xy^B@zgU1Yw5-h|$(@QjCt^bjmVc5ROm>IU~#D-<3;StNS z-72q~en>96W7ZpSrnDA0o4#t3RZaA zH^c8$tl?0q+~wsZSVLPu#}O0n_;H)m0xDHe&%iL0a90!ti;RhU3MUme{cndjd<(i$ zTws-$kZ`Zj4fu3ltIrwyIdoX`zy5XWI=b^FX|)3rAU`jo)O}$N@+V% zKs^|IhP4c?-MyJG0|tjU@EjXksSmNZl<-zn&(imSA0wv`nLPuMa|hOwEk9_xY!8qG z^lx}m<9oAd1bzCSxgfoCMx)%11Nn^blD1Jh7%n{>`A3;d_e)EzehvPGdnqp0ya;&> zvU)|^U$p>BE}9 zErPY>r4_oXj_wAQU2&cwZOBoSiXF7ookcK|<;29WRwAW`iL?KylV{_6j~wojv4%xg zWa_mj8#{27?R3QHIl;@97sSdd=ta#m0x5KHuu=NXZ}*O>ShD-o`6_<6iFGo}S44 zcPh`lG~X)|e0CMAEKyEE&1;(u0dLl8e#=Z}g>rI0ZA zS!aFlT8!~z;axw+{2QXwT`VGJnma|^>Iu$smC=3Finn-7a4UN{?2Se~(+r~-d&`El zyOKq{4xl%s7WrV5XI*}ZsVyJiGCjSUGhW3jZIINlR96>%zXY8zI+ZJw7-<2E?vM*h zY)NCTFm=2omE9$0adj3^8m__HoPzu8Wm@PcDdRix%&gOR?D6&L>O&Z#KmkP4+sPx# z%=0~EeaR}1L*#>k-I2OJm=w`adCyFAaWILH8VmDCXw%6p_6&`ijxbzL=&i*5=^Gf1 z+~>!{z2JG(xiwKllOzF@k|#wPAzO0k6}~E1%p- zSlK&Q`lR>L4&7Tm)}Y~(de+Ygy5O*&G^#shYYe2+O0)k**LR0g{r>;kvR77)eH@W+ z>@Bhm2k(#&vPUGx3dx??PWG%sGBOe(n{!U~3Z=}*$d;Yo?fw0J>(l4De*d_fe~!!Z zb>GkN7|++2MJ#mNWCdeiW=*(bdeN_9|7BpkA_C9Vq&DyA(${8vhCuL@KZ?K3Oor%d z+Q22>r zsi1D!O*Lk|u8&z5DqoGHmncZLJ8D2gLtxg$_`>~)GoSF3(S0U4Z}?*5;i4CIXe`&c zdi@PDg3(Mb`~>K%eUkcotLt-51QG_4do3okuKqMj=8Xu6hmy?A303>iD({phcn#*f z=~mGRPzYniu=!o=PtwTn4mY{I;=(SWNCYczw4M=Q9w{R1C8bAsM2_8nQX^Fld^24& zW(s9X6rytH&j)NQ#qarTJzh80D(P@%X{5>)BX-&t@%yQ0`OQ_z{pT)A2&>2DP-ffeHhE_nA;YIdE<5pcikiB`v`dT#mrvxS;Hw!avv$-&<;JbIZ{V8ovi-pDpiG}mW z^^12QcPR45F~h{lRgdPUlOJ8Gy{mer>2~Et-vdtHu(BVSIjF8oxSy_p95nUVI#tvtK$jqi;gp1FPf@ z55s9o5wpvLdaN|nBqANC!3;YMD=Yp^7#Phv^~v>9OG63bpr9K?fPaCQcryENI!-%*`KStDKC21{IfGc%^zuM1su3NF|6CK-`mr((P+SGSPh z7-{ujL7#_$B=kh$J{@PviPFy3qnseA`xu9sp@&Aw70t!>V}5$^)%)&_#N=f8m@PE? zU^|1I#t$60Z$A`5oWWZTn{>sy`~6u)BzRX-4AHTl!~`pr45TVk^$%d%=4OdCepWwu zjb0hE2LB`4nG&ZSAakfVJbh61&yJtjfT!)Shf|#<#ygHVVm}n|6$1g@zfSm(qMG0Wvpnz* z#wOzGW!OmL_Zx*H+)+I!0NIYv{5M0E9GVxh zkocrDkn-QdI#A*>nXxYyOqA#n+)C90*Fol_UT+6#K(X+cAd>sjm64Iv`SLBzVB@_NtmGI08= z%G(1)KkBE*j7m&X7oCeyzr54k+e@glYl}fbWoY(Ii>q7Qp4?3|sdeHrl@}}d=LJtK z8wY0ceg9HfX@AG8S5hr+&7gOcLH?)0p%mxdSy!{!cCu@$v7fd+Wtj%-ZXXBix7{kc z{fo4*ZsWrl%jnAw0=Z`An1Pd*2HIduXY~O`$;~U9%i^3#wTft+NT04*kM6k_2v*5w z9JUP+d#{=0sQbT<&A+zAw$nH1AmE z#^uj{rD0~au@c$h;4#RE;S}K|+ZN~G=*HoUH3e%TCzvU`nrcG3*D`(L^6TVKVY8JGnJbr?CF#;#_$QiL3X^5jT)%_O!xQy7 z*KRmfC3$g2*h}tN_CWfhJ;TDolkc{rU2hH{1x#Zy`Qn*vQO6Q2m=6d?sl^q|3dhgy z%8@Or#A0V(8PnexoVRX4@3vrx?u6-vF{9W9FD4IRLZ`OWrZx-_nMV2gSBAkp8NF*! zYQ3ic92wyksv)GhH1*f12W;k@=$D)GAD#HJ>SdG{ZeH*KrXXft)&w+@uWz9d$SlT5 zU409iP`yvdAH3-6)c|5dDsbk&V2c`L5!t7;YZy!Z(AzaR;T)cb$OxY^``nrkn{a?@ zg_^$tb)66UI^)L45xuUp7+kAL;(Bz;g(?zecA-A*Dmn*w(;DDo*ND+ z@rfnL^A|Z1O?PCk0ce&#*DED!;P>#oQ2CVPKmD{ZF{0K-qM@~}L^IG8kDb6QsYD|D zpkT*!e;$vi!&jd326Z&d$=8L!o^atkyt|SW*Ejg@^CU6Pq<+qKT;YsaGm}Z z3jhA5DB-fYZbCxN?RIT{4{3f6vVm<_^W`aQ0a#KK;1-v3XZ-zi+ z*Yvyt9!bTc{_Jq4Tal)kWfnOM7SCO?ZC?Q5`X40eu*3rVhz?)}Hr zNN8w}$3P*BNI@Yui~(!IqGD{uUV@}_g`(KFKc--E>c<}pk)eMOnHs-Z-JZVhNw)RS zHIyBSM#jB&>$M?P-U(LA(cJ9IroM$A2t%_`xS8x2we{KCj9(^9Qo7B5=gE!$kHvO|qG}+gX@ZIkO9Ua}-$=lR^+)K)pY6oyUX1!R$u5Jdx?wz3? zPb}_(@b(E9ksYl*^_~2jC&!!0gT9-Zk`$hNWss?}+<7~o+pP&zLiW##pF_KkUMb^J z6`K6VW6N$ED6#e0(J<=?7ZHy52E%uY@iFTC<@UUFo3!3CiKM>C>}$fFx$O+C^V0ZV zWLk-KPr4EOK6*miO<;9?UYCkzPL64(9~uIqoncF14aH z^N+-qb%Xr?nRYP`qcU&s-k45+l~9_a+j>c+iIN+8x0E+ECJgP4Qfg>YJ>dG9-_x#V zOPK(><}dJC9^XCn9ZHb{i9}Wl-M>a7O2c0c*LounrIr|j5WYWe&*gI${eeQp$qt|s z9R}wU`@fVM3-gFS1(OgLgnH!Z^{9-GzsCW(82-PoIIU6p%A{EZs^E||ceesLP177f zpI_!x37W5if^|ysdiu&M=AT+V_p@pB<*4_Ej!XW)?e$g6rN0g$X%(e(%a)10TU&~` zI(^gpT860jp^Td(zCxAU%JW_LbxC&W|dbbC@Rp-51lEc*sN zPvErjo=Po=C23B!rWtJ9|3>7sX>GIaDU217ajKst`{vin(+f+fuf>wRXh3!kXhPu^ z`5kA@aUZ_qRg|Z=23epG+k$j;eFOwHQ%F^UTBcHFj!5|VwwiN~L zd#A24S6pKHyxDkbWGt{@CL&&59B*)Ur&meq7PT<_Mu6|iBvlYKaV>fpH8fOBNpAsD z^6;hQ97t+q^!0_XrIv$EeqtNWx=DBrq?WLa_ygEE$K!(l#CvoWEExZt96c6p{B>m2 z#$dk|wIk_Zl-ERrpYiDm=`nJKC@5cPK8t7&S90jzsX3V2(>Fct*~oAR>?j4T!+w8# z;?C>$G8GMiDXI_pXDx;&yZh@u>S<{g9235G9$vQl%C^rm-F#@jFwgxhJ4D6v()Q&C zTRhLTp7Xs8U0ihyP-vrEL2*A~#l3zK(0&Rs>HK6cbxbg>CI0e5u?!;9$F|BFhSoka zwsK@%0@WzK^g8S}?7}b4#c7`W_FGBXMq_Lc(L-)LHZk={)x-ZTQegJW2zh zo*74_q-eCbP!HD-gAK3g)Z_fu2nQ%)s*J5Sy7Ql;n+KT`!7BDCtQ;f$pX=@~0p)*@ zVX+>(ocDKJ>F@syDZC`3Eg-#qn9Ys{=y89BX$O}pasKo8>j6HObNzF4PYv}7@0LGD zxbr8?=oNt9oB@zeq7Xn)vud5v`=pU?Q z?vq8eqXxL`9}v{C;^Lb=T=#m)Ae@6oL?#w5E3xPyJnPf!fT()Nm>0YrYr6Po^<8Wk zs{;c}9yM5oT@65Xx2o_w+Luko6d(8|5c#LH^4W>gEAMDIK*`KKS`}c{+XqQV|Jfyq zsVP-*k+}lrNy~z0$VIjiUth|w$9C`}+8|T*l2Q8li)^)9aDfWlFFty$8dpyW(^uq3 z`$Q)Z8S!v!W2sp!LVw~OF`|qpv=j@}Bu(X6$3UGOiUAgA;K#)5Y^+HyTXxP*2?KuW zqLg6Q8wY?^Qb&dP{P@)MCgFEl)oPOcuj-!oFavvwnCj)tlFkc9*2)CyQMViX8Q)QU z*G|W`C{L)qgR5`I+VM*^^;$B&>)~a-3Q$K(vm@G!FI6Ab$L;bEX0g5;BHqS24)Jim z`%kKTLza?xZ)2f&wpTS4f9BERj?#{Ej{xPonQ)=vTOOse{k-4=KC15##TBHcBrFro zO#_lDfgJ<<^$qN7B@z9^2WjW@&mow;M6Q!nU!tLzUDzdbAgg{1$>ZsK4Mq*=Q^_s! zLP+I}kc%9=v5i<8E&+vzT-&mQn>HlWDfLt!4{Q<(_dhnYAY{(P+A|@hB0@^l#$}y| zScps`bIq!#Ov#P)uhCTH(YBzqICWNZyfVUZ_HqDWMzEzcEGbVD#%Ku<9VBom<6ABH zPEkht^~J?en$_M__wex8iv3;j)u_3n&h7{N@nl46nfK0layZK2QLn{4Rb~{rJC*#* z`zb@J);GqlHA2^SV*3kLGh7Z%F=I_iYxW*uo=w0kD?eo0#CW7p68B2flVeyody$;?6IEY~{_F7yp)uIoIV zat6L9!F@~C)!12qYL?&_8XEnS-uLI?3{6)fSOf;{K5Nfq{T38;qntOb2zd`*?uw17 zL&Mw}vdYTNaTec7!`Cw!T;DJ)RNv3uZ)r6hWYW~5hKEy*JT}|yX1`f_Wa{yZqkB)m zSH=*cX_fL4ArF1)JEheHO7~XBYy9`_p7RkSa=-5}kMTc$BQE!RMGUILgU-DH$t%xh;)qCJjBu#0-ABT z(deAxRORnIS_w<4c{4Ygh|$CQZmmZf65A$XT0$=y?i0QXD>^RQ-;w1`n_o1hTuWZM zUe?v~UdHJfkMztpJ<#<;6q6SnuJ=HZ9QjFz``ZVU(x-@T>Nz=(u3MLRhHRdb3n1~h zVnf0w9Z=7PLFIvEE{O5EN&bLD<@z7sE}v(-v=I_7Hmg49XS^Nv;Y(peIx9VGWYv*E zM+|ef6yh*_k}OAiLdo@;JNVWg2|=|YGw0aJI_EC=_)y)fj-5^aVYzNv=7;==7>~z4 z9-CmpCbpB}+NG-vaT2kHVE?!NZE&;FGw(SkWKku)7(kzr5qBWp&-=YCo3wN0kd@Jc zhjA5jaOe7^NEU4G) zHj3Q8S|eb~9FMm%beQUFK)Duidi-7sl4%Ft7_ur-SzrZ>k`$&_!+VK zCm{cIgq~!^;QACg#f%C6$zGu>s^g=QHxQ$SnCmb%&pM{KpUUYsu~ICckiRXvz02s~HkQ@)lw|GSEvY18mvZNpO}qeMzW@DmogL^CYm7~m|#UOOchcM>KCin zWZpVke1*W{U*unXE0L(CZ>Tq;;x=!;K5zcX3PXKO*bn)Fyxh4pKKvl2WiAC1-6Z`Z zvzP6E!SRI#+HBl6UHS&GVFfT4rCVp%p|O&7;!N^;TC-%XM#4szPH5u5gf6&W7k~ok zgI!Jz{c8GU9=KI8Oh6$4=hj3CLl%uCYj<+dNfTb!q{44b)X|lftn{Q09M%blkAF4s zQZLCKjx?5onX(j`7|6FOn7?V`YD+mX@VEZe)^ly!ms9#dQstC?+Ge$^* zmUV#nN>OpKVTl2sp3>pM9CPgN+6M{!ng#vzKTd4!8-G2}AyIxWF8zCnj_&%RoTVegLN>cIw5Uv!WFw`O zRpCQ~f+k6+O~CbVqSk`}qFwuAr1Jh2goIJ6kRJ~g*c1otgwcQ3pk{C%hR`Hh%?Nni zi&h3anrvK0n}Cs(T+D83D_zGpA5WD-v6O&*z8& z6PcL2N=yzb`c{Uo$iT)pXDQw3uX+-KPC&iBYR_QDnmMHvty{QB6l4B4#QOXcB_s+2 za|T1*I`qC|j8g(#Y_@b_0=v9T-Dg|NKj)~E{79Gd&*(rWQ2X!Tzrc8svj4*CnYg1# zj<)u5#y+RsE##tw*&ue?fi?R}Kk)+#4ec@V-iP1B#p-^{P2CphF1oX*>)YEud_KI^`73HGPyFto_7uR3h%Yx|y{mNBW{?(n*Rcf-It|GIk zoI>AH{EKW%rmE|H&g84B{G+%#oK|prrlekX%Bc)6(W-==s1jIUzww#psMBAkkW9@6 znMBa9w_W3^f_xra`5@HY>8*}rf z5D8f3(8NpE^ROEHZ!gOSdfD`M%4a9y@;+-^SFc_b-uq2Vs+AS|g$f9y{s$@`7QD_> zoH8sX`W^Fas_VIs75qn!N==zH%bSg{%+Xhj2j62R?d}aMRL|a;LwcFA>pr^-#EmF& z=4}{j;igjUgenJK?8G&F%cn{=8)79YX1(Z9Y40=~9HhjHg1RXNnlT?3gMKZo9fh9# zl8n&HO?MyZV;=dH;w-}+j~ZqLjYJ+#D?yGIPhuUS;EEfG)kO(Rb_UTwC?u}~N-BM- zRd7XvRV-HPaH&9vgM%+t#kYZth9*5Wa+$EoFp=mT7%GJOySs0|%N?H!QfJLB#TrNy zNE5dc9oCvpHFZE4!ba=I_rz(K@4*N66~AR7gaO<)FcrE%;U?&1c!@5ClYxPAfDnd< zi)+_-Q9r7uuV1VYe@Vh=kn67yx^LPN{)s4X1#DkDATc9x zX-BMvjP9+RUZ=oPuEzfH!>aY-=}fpC`DA00v1ZC;&%qobWIr!@>1C^8PREu}OwOGS zDYsc&y#*x>d*Q~dRNoERjYsNehKH!}dknEoN+M?6%&`sIkB?Y~|TC;SaWo+ zV?!7?MY><)#Y%(i&_@MDzcr?rCvWHQ^5g#{Qz zI(Fm5Vv89I1T%Fu7{-jo$uJTEMM$$L<>!m_P zJp5*%A%8-)e@zEMwyDtw7POEn%I(^|IE_|2qNo02Y6``sqUlt4OrlX~RN=*IKZ(Z)Q&Q?Zmr8UO zK!4YePgt7v3pHJUhj?9b=RD2C-FLnE=8juMevdFmf827udY=3-57vadrX?IdtU#Ak z=AE3;E6Uot9h1!MgU2(g(=&UCv*D44&>3{iE-PsHdk?RTp_|483zbQ=|@;w zshC~9Q~?=TMGj6eIswNViH?piqQgwrZmYDK*H6#B%@M5ST%%?HEk$}PBO4>i{nB}{ z)eR&(@<6JBTC0GDaK));o39>aCdNvkT=Jfzhy(G>CCl|T6+;7GeEGd|ma}tbhx`Bf zTDrPV=irEYI~h<@%ezVb8IJxt@fio>DYAT+Uc&ga zHnZaZQsy4Mh z$mx}NCms<|)*+#LWPXZwr}vZ&?*TnBhh${wT1QdWQspGq4~2|I7B`OSr9-m)hnY%S z1VD;nqi9Kj?mLxn(gMIv?8S@W}j1SeWj`?mCNNbS=Zy`uVR7lM8c978^vl=9XskN^ zZQ$|{Qc6HVq^OWU*Wi8A)!xx@=gWiXp%TO5`q4kzB&t&WcDtDDizdG|A!r>kav(ab zT*XjE#mkM(K+JXoIcIo*pzK)dRZ_2HqU8Xp_~R0IDZ};%M%j!V@vK#42RqNzaDmp0^hAd6n+wNhj+n>x>ZFr<=K5?T6ha`${?o1a1A@7`t{~ zTeF_7%wR%gRz9=)OKPp^pl9p53Au7<@U)jS#ofby>aO;d>WK>A=&C8fEMG(u`Rf<2 zf$+jM2}~Yet3Y1ZtgHOztvip@MOg}MF$t*BKju>###6ihNc(EkPE7ebG9&ozR*n*< zCD$Hzl|Vlo4Mqr6XLd0gYYL=@52=q2-9oJp7jMmmn+C|9dLl>O$fZGuNaHJSkOgz~ zh)&i{*QO#C{XcD9dbF&`CWw9#WMdnA^TFvw)BQCUcmM3Lp0N$7`sIofjGrGq$?hqO zf|Nfs zo5bt3IosgU?6a#HZMw#t{(;S0=-Z-NToFsC?y82HYSco#(+k_iZOIHY^K)j(fTDEh z%eql}cdY*7pEtf$h5mIW>{^U>_{YWMJOacOozxU57!YMfOP2wTeSee8)b2KWv6fV0 z?vC4rD#m5Nx~+6MKxWpW{pt4S1%6V88EA+Oc|!Yv=|5|dxccvUo<$>3jane}GObY) z4wg&jjPuD&t_RYtNMnPV?4IJ%^CkYV1t?WgtPfNiqI@T*g9zCUSgDkF!TM$0b4k}d zq)WqhwdmCF36p1g)LBeZNuBT5dOIHy_(yw(n?`|Fv;_QJdT5j*a2lDv;f-*tG#ptm z;i+ckG{jTJLrg{TCY&h&Wdt=))A0`v56>C@u>p2!|2@#~e4CjkCrOTB4hH%Nfm|Uy zzA7&&W_l==E#R*AlT$Iuu(!9o7v`Q?m`Xi>-;d7~3tg%9fm?3wC zT&LE@NIXY>yk-+qTmXzsIK6g0SChmDQPYJW3+*@^Mdh6kFxW7q`&S16h}9k_^kTC= zBjz~bWKLyilT*m5$(23vMPI6kb}IT(mS+0CREqh z6Rbtw!$pPkU{yw$S?(gX7%WJXM>CUp^+(00hV<-BRr_mBDb*_jfcW=u86E;z1}OVVw6=LpxT&PHht z9m$n6al>@|UCBNq|@jD&pV`DuKgQ?vG53A0tWS_dci)`fHotjWE&4P(}^Ih4<|4z+iwl zWqM%qT&|=kI;;q&5tDg{4u7{|^y5ct(r$L&KBS&&L24_0PnyxGe@~hbLJq`ra3v3g zaHY|wkr6S_JO$_wddD~a(A6P(4E6Zt`#`EAr7_ONj{Z0D`Hu6CsX*y7@c4(5v>1>wKOVa>w1mrkXw&qFo-1NFcz_aqsh6C=AwJ`}Y6)2=T(nMzUwiY#H#VN-%iuZs%y1&A>uj z>XRA**baC8`PyKJu3wp5mHD;H;CI~2D)ejSAvmN0GS2VEf$VZ~$FFMqz;h>i6s=g* zllr7-31w-yrMtz$bC#;55Aa*_qE4@2U(<#LlCX;b3Y;~UgoiKG#L$*Lwpisl>*rKS z>k=9W$w1u&sCAlX&|INyuM5H&pD9H>2w9Dob*7j3yrRY9fd`vB$hai?b5n*y!(9C2 z*YSqyL}dujYyOpRvi?dqM8Q#h5i|$%!A1&ki?AFSkX?-%qJKjAZZ!3}mOg)yA>M}j z#_K;kmtq`nGWzg*%tzK7IG5Te5{B8WhllP%l$XN~kAuf$a(wW%J#5o^^6QqWdS2jO z@)$_D`2$qwz&FJFE11f-Nf7l7F?c&lxUD%`l4B0Rzu?#du-VP(S|Ry+1Ad zm6E?^AgmQPukR)7eIoWYDx>+!v4%0JIWpgS_`s}v#ni<+hrVX=UXJIEdf^v$jyo+% zi8LIKqW%#D{Hg%Hyth`NX4{P<^RL}@XVSDU{ax+xr0$28^-kEC)!GcqXVt#yE{cwZ z(9wf;o%+wrvulj_?z?>u|E~u z{6D#=mML2qHbrB9ovXZKh$^_E__6c6rM&7aEI=M${R^775ALM8Bl0bsjb9azR&aL; zA_L&KYGoKVvWcaz`;8t@Q<^5mCIFuAP_>K?jZbtKW5?0nSIctbEs%UY^#35Lwk^~^ zrR${F+xydcW@ctnE`I<#6J6ySe;zcQY$)-C!LX+%ebjh*#qjs_*f}Eu%ZVzKV){03 zOLcgvF-D*k=3G3u^R(I3yejV&>3g-0%J56*t2b$){~mY&WpFZCI(uA4)~k&)9KJy9qcT8JHy4h@B%57I|?6g z_!$;Arl$dg|7vb2mfp^pJe;hWXGNB}vy&o&1)dl8gCE=zNDkA8T*_Hh|AIp+f?QXdn>^Hj7>TE5B%HUKPeO}-I`n8oJ%0VjFX^v zPT<7uJmF*yu(%)~poFrgpz{;u_k8^oQM|H^O~^(-5WGGEnZbaP`JVd_2_705fb4)a z4ZM4so~s@DnXEP2kh}4_(w^AyEZc#%bDK&jv|qLvu2|A@Y-GdSlF}jLGZO!0moF;j z;PA2N*YA%3n+1uKxmWu@08*9I+~qkni2!IC z_8_D-DM8P(O!Tfv!?(ma`5kR$;!JaSbAfO-k2kwY#`(J7fK_o3kSG;~Bas0Lq{KmI zNC&8tAVx82dczTHoC0eB=sHB_EdMC|JMSJ*iTybR$-JZT0sTal#H}H@K+d5W$FKC^ zDWp~)fw1m8Di=com=DdYi-DBO z6_If6s4goL0^PDu$shf_jpSeD7!qP!mEgk4DBGOLAyJqY5mTt(qQa~94O+A*Jj(;S z!AWia44bdXq;J%^d0TQyMWo)jS|^tR3CRaa{vTe2B#b;Ri#73{2bm+-St^nl8_+#>YEW$-(29gjbamOm zGt4ddvG=?5P8pMVqe60_k+X%0lW|=Gb;g~KHB06YW(ISrDs-v@!4OB|p{z?M+flWTx zFG3Kci&(zStd|ZlNurt8)-Da|B0<^2WwOZF8q90i+oWJ1)%6T)V_M&cb8-MoO(#I8 z%t^nfj|aXuq#|tri^I)+zTfh~kpJ}dALbg;@K?v`K?H}hwuTAWO5%CTM7HgIw7Vu? z%)2s_W|;BeArYAwdvPyBm^A&%=P+^M`#p{WP5MAfA=(kOXtd9(LXbW?mlMjXtYp~@ zEgsCevLTyDQp`!(TGUd|lUaFiJUlL@>uW1${!oC3;Bdgg$I(%5eS)hRNQQonE;+y3 z5w&pYuS)g|nzxtWG{}cj&MUrkzZm1y(IF$att5bihE!y%bz?^ChNHgha%FEVz|%#~ zo+!PEhHRhfQtA1xZi69geqZehCgAi+Qj}YzdJtB`}6$@L)o+~uUXc2BOwfxVC9Q1ZeCy! zMQ_^>GH%kwL@2s>Nb3J)cyfmOlS)oJ9$2`0O79~X zr^xh&WR;^UTEKLNU{Z2W^S&eRU3G(5d70GQai(3RLq@v5(I$z$=9I7((;61G2roqy zl2t{3wG#u(P?R)cs$_YaC#ur?YpWeU9+_8%x=T-WVR7+DA%fx6%~IgY`;)~>S&N*r zjHCW+!lO%`xZU~s%~R>XZO!9^1&v`RXAs6wg-$!Bn$U3;P1QJ9c=yQbopiCK*)x^7)c2R?pp2x-KUXRUamwwImac%NaO3Kq!N%yZW z2Fr+z1X!Z)W>p4W6*|Oscu$fabYXTg&wpupFyV9ld-BE(%elDhiN4Q5v*N}x{6^oW z)FrG%9fz{ssavu+Fsm>zSix1&XdM`=I`jy0Brqxz5Q&6IBTG5~PNc_{hlq-CO1mx4 z>N#_8j$rLcN}57*&2CIR02G3Tx`XwMQtP{PETFA6^~_;2iS@T))<<>+yPh}DWRGdk(t?#bd!r(;*w#H@R1$?~(8)E8&I%rRYMdSCO=cILC z{jV_J38>;@{oNj_eIWe%Wa9f&W;2=NHk;zoFf*MU84!jtQ)e+s6iQ?C9#Lw4H$F>uYKS#N+G))3+-q4S2uMtCMA(z~+|?-m^~;wv7AI_wLA&=ptc*LBZBvwk z-%;(+8E*_A@5Hy@#H3fX9Au<+-)Cc=3TJN}99|5Du0O^-L?QYz#iJbaAEil82cXFr zcYpn9zchva4&h>ZctiN-!z5xni9!y2pi!ibMdO~XkU5AZa{9)je6^~9@!j=yU8?kY zE_rJz&EAU@)L0o6RGqv!ONhieg*Z4@j#&451pjxpgL@PkN{7VxEl2DPlYZ*=Zfd2P zrOKQgiBImiB-!efsg9F=V)yz8ISJ_WaM)t_j1%^%pc`XVbMzl1aD?kFz^p+ZjeQnM zwyaFpz*0Cfa}gqeK~T7kKJE#(qKi>PyH>NPX0&XI;*;)O?U`HBsb-CjigF*8yL;>) zhR1eu)BP-PJbbG$4s%_sg1NUKnFyvU-0s`t5vmwsZTeUU%$&qtVm?%+Yk) z#aQZgCWaHT>AN>F zjdVUyxzkK1T@P(rp00-dcsahE@p6HRmM83HQ$ zUjxSH?ygLr+)KWUJ(ClU1`OZkrtj!K&C>_3ba4FT^f5l<02>1+RcG`x7GtT#3*gg4BK@_7W$s<;6AO-zhfR~ zTaWu{G$sn0u1SzK?R@Pj;8j77pe$gQ9?5$}>eMMDCax5EVm_GEoI%?{X!V>L5Gn=4 zdU{G$Va3r;^sU9VJeaM0QrgiICHD{sv@WI^b<5`Z>; z!|F_Xl=;4nx5lH5p(ybZWD!9Pkc%6 zZPzPKA7yj9cjtJ3E^QXdNTVo|zMp~lXduzULB6I(Y7y!E+`G=F_tE-wrJ!HDz3vk$ zCfl4oD@pBYYok|uVb_Gkao;47+vMe^b@=b0uRfMz1(?|fq{Y+bzs$yZtOV%3Y&$jY zq}W{$x@0ACP*t9YH&7GYt#IvrQPmsDz9K2XS)O=162p*j#5c*5dJ48N?EIr9N;~HC zq%K;IOhnSOD4F^(5UV|zc&P=HSnlYqYpSkQP)(jkaIIEM?2XSO>X%fQ=p4oa$7P&I zu7Py`#&wrrDqN&tPcCn`oMSTmovn0Z?`a-b`^?&3@H?TACe(7cNOJcAqioK>VYFxv zu+cD*dDTh`0I`~Bog2Hevvba#m>=Ym~=l{hG~{=pY%A$JM)t z^^}+PFEOgIqxz2L_|rMA&&{^2r{`JLe#?r-#p|-!&bxDBdN4YEJnr@;oDJB+FFYr^ zSape^1}V8V$`um3Df*bamnS0K-ILu4gYl~VKHw(Y(c`r3n@Ag!+K?9A85#ef5I~32 zO_b2yX(qePnMD#{>eBN1%9i_vl&dwJ^yO_vwy|f%oM+>@Up|kuSyYemz{to50)cp{9?SH1xOTH0{*+su zsLZ;|9)@1L{~hO_6w5xwt4A!{6<%Oywtlb9U~2ngSLe287dEf#$bndV!;komu`A3* zXOb0~)XSB^N|zaT$>GYRf(i%c+&~YH%WY~#9k2sTPq*Mpt**(>WjU#{x4gzfya})f z{5Q5F@0a^njkw?*Zo*e&(~D)%WKBK#;TO^y5<;j*_Yj5h0&&GWo}1@eI1+Gr9vNz| z_Y-}opc?vtmk28l`Nr^gB)J;#MUY*~5F#<%ZdjgESj*9(MvIcM?*@XiS|A%ZOjF;l zGEy&D@cG$PFb5Z5m=Q!G5yY!TK?xfBxe9d=Pzz{7&|~qylX}=P)`+;k3PvYe=REh{ znBTIOS=Jx!q_F9~Du5m1YJI{`@_hEP%Jmh~3@z#h>4PDHMhlD%x7qm|^zM#_mvS`c zwT!#Xj)jOM9qtRC7gYN1NI?;srGrpMf`h}HtJ(Q@1qOYcr+3W5(IPK3$NU)&<}&#* zW)F}=`d#3?uKlIEv&Nqc@4e2BI>Gu^EHGwm(Hb5^Duj|+3;?U9L;W(?GzZ!_%uW_<8kcpb(VIJxu&-eiS9t7gpI_pDS*2()5t1<+v)Qfnwd&E=G1y23DkXf# z6P9DJ6R>{!<3W5_QMgG2V$F@fHicO20l~YNnEXQ-Sq4JQ(VvRunFqK zBrorR@ir#p4^V2FMLIKnC&+&FV>w`CfQSB1*_`^Xpz)A$-V%)#s>TOKiu7UJoRLSp z=WHQOI%wle`}|AiJA12iR|WxZv3Y!QuC)DS`OsG{KzVesL|t$oMN9g!)6dVf0%tj; z-F7Fv7$NKVw|#EUclwH}ox7Azj=J*U+U9T6a?Dl5i-uz#%0&4CvC(ZHHd_2wY&7rb zqglm0!bQekt~JMGkf}=Skld>U0mzcHop`7PK$dQAZi(Rsws&&Y9sy65yrh;j0nD$RlZRG7w&HZ+&i)EXHqcv1M+=``kxvBS{U|mSVf)kSs*0-z1s<@Qnifx-`n{q zFRD~D2;Iega2N-TOzFKwX?~8UvutgNC6NLobf%!WHY6CxZ(kXgYolShWeI;Sq=DOC zl9&ZiD;u$3(!&TzywO<}k`Xq-jyXFIs7(4th>mxWXwS-J_|0?A6%cYD7!{E%JH#Ka z9)4NT;uCA$c;qE!HjHz^@f#{v%Jm0Y_?f3`^;vQ}k znUqV9R>UJ8W_B#HNId=YGCWoyg%wHckn+I=ied&nmPA?KhFA-8Ri^7$dzeb#m7lhP zJfs79d-B2pJ^a2E>{rjWA#_d(IjwZrDGe@EuNAER&=-P%1C$Ro001(A7_>f@hAmTdbMI1R76=8z=p6w;BJ|4J@VH6 zJ?|z5{g(@abc64!wcG|_k`}=}98Wq13}(C$?DFF%f&DE79aD92J+Pv&w-A!5{Tg%M z>f^+Crr(B7-*9{pVQoyQ>?))|_!8$zkarDIoJ4$?!~mPcp3 zRw`4~7=G%EMfM2QLkGg$A{$w_323|2qLpl&i5 zboC?GGn*-pmAbp)@UPsL8c1209?aTb1}e-De&O1CkcjNB2fi^x!tHwR!#)kDUz(iK zkJgGS^>M6SHEFaGlp%k4(j;=wl0i@E;&dM;1a z12vlx#Xi}PPe9k&8yXqfaZ}ZR;0xz>-Fdyf48?Wb=0~eK$eqo=zNl&oHc#1C8ny<0 zWXwPC9T##C!YXMgJ=wkuiLTvfj4QBOLWAb~BJSeetPKToPMdc1$8Y6|nLk0l?7rOZ zNPf#xDc+sw1Us%Doqm|+prA%mv`HA$Euk5B-RTkivK~2&VX~~R?_(lizFumN3@zAu zY$5-o0+Pd%tcJHJQ!POPfEu&#_7ioc2ev5;b)U%0L*la*Hg{EmzC0Mdq}8e4ecsq; zCw;j(c+CyJ3q3? zRBWg9Io1j|)xcTGEHie2qBUxHW}0Q~yJO^qExTlypM5-i&M2xTdwkB83PI72rAcLN6`wt%VlU2^7y2A-wDvuPVG+8)RnlS?e1Sck< zds25Y$`2;Vdr5PE&7YJX<-gBh`V&F0JaE>_xS#Jl=`wlysvwHld3TZ0VMlypheGxM z4$tf}aHx4gJ?cp7h@$523LtL?Vc_p`AEuNZw@JC4luuTf!4AzGUx*Iqnc1mrM5OgT(Q>g%-(qg)R$*w> zjFyyf`e)JXm;uJX`}lmjk!{lBFvIiM^Zd^$WT_O^*jS(Q!B0k%EV;uodH&?}Eixw9 zhozmvgQL~g4ci~Cz~d$YTZDe+VUL%8ISsMgg2;@ol#cA#ct8t8GWZ45FQ|NOx5T^} zOgwhPIWE3h(w0+@vZG+Wb}7lMmLMOQb^YT{7VZD)*h~fWR)GxvLz^=j@C=~rgh$cdMe(lPhkqco;k@B--pj^9HDHJEgf0~X8e z%Ni0DH8(uEv_J_qv|v1CWC_DM#Wub@W0(Yzdb73BFH23iB*AE|9-HA{w-m-&5-$b@ zWnj#q=GEJ1h$2^}z&a>My-NAu2}VzEC|wMLGAG@lKG)f*CIM;lp>b2d{+9;}i;F2~ zX%60hUhJFfv9$TCobz|mrc3Ua@U>jL&V=_5KF#yxM8o|&MhaFIfSi4-3^^16xX+YC z%Xi9m3C)qyK_*?R9hTkcnYP|gflALEYEfOmjj`ZnX^`M9%@s+PDCnv?%v(zc3%6>d zs=BP!-qDYDXha0LF*b(rf{lrwz3e1G_WCyE5Ng9h)+HR}9@WR{jXtwkm@<$Wj=JUC zNvP11zA%&cP>C%SH3YVWCVfB}WU9~utqMSHqQGjeEjf!l$M`di1Q~WVlj#dU7xuCiK z5Eymt_Oj&3z9A!<`#-ZIT_*s=UjzCD*;){QWYY)SrFBOn#IqM}tobKm0uTP4g)SV0 zZm{CSuLX{5TyO&nCQwljWqA;kJ9S^_g{fgzWKf^{GIee4675V!)C|K$2xK2|EqwNYqD z?3QRGd6N#g$n2t7YhR@MZK=7X(qc7&lDB(t0=~XUTwsH?5|RM^+PN4O z($* z-QC@T(x89>qJ$tYh;&E|0wNtl4J9yu((t=^-tT=LUGMtV(&axaTzsY|K4%|6 zp_!DFtcu-rM|tc@2t=Icf^oZRw{K_xXk~D9Wz8La`vfQen{^J6V^Ql@A>PaM*Ivl!E>0_8osedtKD# zLovA{3V|=5=(XmG%vQbxFEYpno`tks9Ps|&w;bC0`B}}K>(LvB$J$%dk@Z1^I;Em{ zN>}18XI`RUt=#Uk;*imopYp%X=Bht@WAJY3L+2KV!V7bFPCzDRQAxpZD+ z-P;xeg+pb;kOKju7zaOb2u@GePmDjEO8UB-;rMy7a(#07+S^q4aDqS*wR${TklvV5 z_E53Q8VX)o>O~5MbjPk+)_K(@lxG&II5Le;MoCXJKc-J+4duIllY0eNFW-QiJha*R zLINEVEKYQ2d1><`(83>1>IFRS_Gf^HoHW^%D*N*LYA%KUEcLl;I~Kg0^Xzo3{n8Ru z_w&i&f%v}XgIUFLG$|ac?VX776r|afCfTrLUQa8(J^(T&GB_3L-3Tgk&_- zo4Eg$Do1!qX&jqezfeeMlPB7Ssu63VW1hWWPQt4Nv~Kh+fU%0&fHwq8ZPCUV~uSq_{f!#eQYFPC#>s#HyjhO{Nq_ThyOP2QyJcu=5H&&pxb1*gmZ%(ofjnkN%LKE z(e2moJwNaq2W)fR_Kg5;gI_62Yu;KUkpqLbUt271tTd;BPQ7|(?~l4&?6?7TL&?XI z@}+<$l^I~^*}L}(_|X2lv2oLN>&5p+aSktmJ6Gp=1|AOG2=i{+Hp6ZgE9fcfsc4O* zC2kw8B5sXTkgWN3By+Ra32*nSUAeIIU(GOd_IX18bg}~2!Ok%&Dan<6Yg_>QH*?5e zfT?Q`Rp_Cd;lct={=!D52MtsfE;;`iY@N!E+ee>Fnw-5-P z43{-q7~RFp7t^CdxqY&)1RvLqC@;TQ)Gt?i9L`EsKRzfBm?vG6An(mB8GV-31TuUQf-qgXE4r)a7B1=GAsSJ zpJHf)k$g#k7%l1!26X>Ka0fGQ+0#dH&9d^Waa?s?vfRm?D&oLEL_Ah-E8$w$Xi*P8 zq{8j_t1o~w=e1o~t_Muc{RN#h{^kLr30KwIHn>3VbaR8Y;_l>sdaab`&Tqcit+pYQ zR$cJir=a=J;2|Qf|6F({Lek&sR7`-uTWSO@047&xa+~d2u6JDrHglj1G+zVGWEBQi zcSV}^Z9LA??Dl`73x(|3ZHv9rFiE?*Y1atz5+JsaOLV`B89w4#zLm?RUmwaJYylpk zy6n02_PI4vnEB{SPCj1T`y$8vQ4ONf6m0)n^d^bnvz&UtY$eu()|4l8sEh*s6 ze?2eTcF7zCH7zt*`Ev7IzDZ_R%sKzY#M8^uIP;oKrfCnf{0lX)DOD?(q+r%J2c0@Z zCYm>snTtISLx21a^4GQaiZF$QuXzOz8tblckM+euy=zIZX%vYoTMz@+%$ z3w=E7NSC?Be9MV&=Vh?8V(Xtfu1Jz zTv95o+135_8;7m&H-xkzJ%7cYmwz=O5|O%zW^?7Bg=5H+Zs}mjQk9c&oAAH$karY` zB8G(nYdH%CrsD9kWg_-$YY?SeORHC^i=59)IiCmm-bJzR83Fqj@Bya{xwv0%frt~s znd!JUJ(A;kQp?WJ z3BurT)->cFy23D8A(N z&GiH}Q|md$^|=qhWfnn{WOu#zS&k*}$GO+T4CVD;WB3{$l-57;%q?Z3^=S02$Q(G# zW#vQe7K1teZ*unM27StoX5M{0?8BUqe5@Td09|Zmfko!=O-zJk0ge)W-bTrtX66mr zW6Adjk7CE}+db+4#w_OsRyYrHv{=oD8q%O*hdB@8*C9?VqXB?KQQI8PI|K*BJbG>% zSeknH8N``-BH?J=_;%n`D_)#kI0sXpK{_+usHdl=-)n6Ng_}tmky85p&Zq2vqYZ?& zwDVl!hreo5{;O#7e~}V^jcOBp%=$OKqWI0!|Di<7{6m`K89W2>VNX=+qDNejT@l%1 z)qai}Uk+(+OCtzHqnQ5Rdp^_v&r8ypB^?{j(9+}ozdav3--C&)>Ss3P51yVY_y(=P zPKpBZN1jQ(?;|F(AOu(uv0n9c_2{AyHhKnF z*7l&)kP;y!&*zW&?i|zjF5WI7=`Z%=OA8T>e>iz)34MO3&2zJ!TyT@>Luh>Pbj`nm zG5co|VDn}1g>GK%l1`wdc_ehICo&?UFpu3GkE!obgr7P>dHxuyqhIV}bH;*MY_>2~ z$_IL3g1pyCM1BHr)&!Q*Gh8s#=G<|q6Ay4uHG50u;7EJol&DB~S+;)?oO367#)m|m zKy(1T<5id9PjVYdYl+noTM9kKK=ex`pzmt~td~=<;g!K=mL7vi;7VgtE}%aD)T5+p zd}6|R@*U;Ct!3IDRY%ibRfitj9@$jPyNU?&OOK^OT!$QQ~9XF~{$}F61m>v$_o}?xPePF908fAV2#I z)CLk@+?imMI#{FfJJ&wFjE0_OtC#c+KrE5>_wc37{09(ke98y8w-n6FdwdJ!8U(CU z_7PL6aJTa-!O((>kUDW!hA@J?NbJj-hY!^^k_iZO)MU&1&+Ig>3EKtTihoV+Fg$=t zoJ|C2P1s$f-BDlX<`KamK7n@hPFJWPLsNm3C^|FB;W4KR_ReHlXgY|Yr~kW6vuSxqP`?C%2>TI(k0=eP*zSa zQG*IZ7v0Yv(xh3ab_(js8*0Cd zYUam5+Z1_4=}7DnGI+snDIOcq^c$Ob`HuV6Zp-`t>^n#OEBURZk}F9ben%^{3F|rwYbm)f$}Y|^#uSlxMX!W>#zdSX91rxe zqN_dj%*g?aXeeC!;j~Ie(nNHoK(WPVx5AZD*@?`Mjp$6EXEnA5ygY$4nzHyM$n;Oe zz(^nM4?8k7VFw$LRAABj2hjJ|(oLcaQM*Y3%8B_^&FLUC`ITo?rAF@_FZmJ%I?>2X zxvWRYEOGJ+Pi8U{3d++PZdN8Kz+D#Zp8DUwL%0fVj*tom4h*~{X+T}7QI6UL#)8f* z{5%fM@_MU0$)%irmAvTeXB6DMfA)@2CnN&QV^Bd7-11v&CpJ3f+g1tr=R|Og#SwOA zzc}4@n*)q)53V<;2~~}HM$0DStL4?OMC9}6)fE@k<`f$Fl}yr_Rd>dn#I_Ytg#o-9 zidgJ}dU9d{_0@p3;ES1MGr5|l%4#_~(Z8My-!w7TPd#ST4iLO?n%r4p?MxYJ^b$x3 zC}fe7M-F!;55W%?-4+m3t1I4jw=+m^yD)bE=cYTL!O$W#NK?lr*if zL)-*271pVYK3@M*j=8-fRt|IAD_mPy+F(s-H%b%ImK2)%Fe>6BRGpNLSMz4f0BP|1 z5r^x+=?cA9Sep*DAUPheSB}4NBGi>;nt;co&T)nFMV!0n3leP7fr;t6zV0jy~Y!87K@t>qK?diN-dcHZTi0-t}4mYohV=IL6*G&#mJIAgPROoQF z+}AwtFd0vXIW(ODwy{h%KhWPzow)g0XFT=NxLQ){sBB?K$6+V0Ju)rd*V$thrMj}h zZCQsNM-0Zc8rs&UzW>9;h(7M<`w1E4g`0=X!du5j)g}Sb#L{t=4mWC5Z9lb7gH^I` zn(|$J!5SD*_%HH2euo$F`_k|2qw>^KvOnE-;G56P#tDU`* zBI)IA7f{rCw}|@#wMWVqa`H{(5bb)}d%`v(5lQgoO~QNOn8EM+hMu-ws$qjMe0RnA z)ae--dKJkD3w~fzbAw(JVzxHt;zRIkm0rImzaJ(WtV}0J)~i7S+fA`5CzW`&YE7y= zTjai|cy#~nJxQVX;Uk7n334k1fj|nQ>J|7X;3gjq!il#M5oiIn#3?1BkxRNR;>oA2 z&Dea3D00rbrS`qxQaIT=J$DNKNcNUI_o)8}{%=EViS18ytB!)9ztNM>sEO!E+E3iw;cx0gWqw{=8V+W>FKjR6 zRr0(r?G6Y$6$`dd*!|tLh9PtYDpI3&^PTT9T~H`J>HQf{Hc8p=_DS_rLte^ZGq4yM zX=6iXB`E&{VJ}V_tSG&Y_8Q_u%BQCAO-q)EmKYnEa-v80>ld)%vSbj$7zZ5l~v z7p82m1}+kL7>Ggrj*zZ|4$t!euCfsAdKYDQ! zl=OjDdm;BT^LpcszwbQv4Hb8s^4j}@{r1)I%n5CgLxY{`xk?!^oE@eadL0VPNvjTy-~yeCVMnSNL-0d$Ts4O2symZmK`vSNzP=E6derX& zAOe0C_P+KIS*oWc7qygnZ)0Uuj?Hq+l{wIJK&#uTO)~{To7ZH^9b@<8=GNql5=4<3 z+Uy$+RzIp{%_1#3qS_i3$Px!!s?~|-TO-t;R@eBA5kM(g3z~BQW+@yDrYB(L##HNJ zmL8qT2jXTV)b)(VMi5W)vN<5%V6R`Dp0YSejS7v3@g$^IkzL0qk4q+rioYcI?6ARU ztn1I(thY$|&;2bFqG;%Zs}{a>)ZuTxJMtLt206eITh9)qZ(6ew^sS%s%cYJ4rhn6 zrv+*m}NUyUq7!l8#%!MdZMWq_GMO|D!!aP|nS7GrCW51mPhv zD@OI3MraOdMz|q0q3LR@c^#*e!@C?1MNZ zr_j-?RZq8tR+(s?doysWP8gkZTVBFkc*FQElK9)Nv^w&Q8`=g(wu>}i2c?V+uo9`J ziTsF$9*f8mCCOUED;6R;vO%li;rn6WD%8h3u_7Gw>59mx#$3j6Q`^$k$uVVZ-Yi5o zj-);s*K0z)1Mx0e4c4jU4Y@Ab{HkX^3nEfl{EefN1dQP`6;X=p@;?w|T5Vo=?A9bN zkULi{tQ}}(-lKjmSNQI+R>~%(J&yK}V z+~UpsCGc05tKb6tf6l$}6w#R%6QO^+AiZsmMF)8Wbdm?`P?{+HpuvZD)R9Su`P^s!96`vmbkN&nLm zfocco5&tYnqgeV;ZX`eVEfud!GetTwlw~VGDw_zcPxE<&1V;6e*;O(DP;!O^6|1sM zvK#7P&eDx`$8xn`j}jyZzC-^Qcb!M%6jLD#c^*jp<=}vvbIUjtJjYN%D}T+GUcfm( z)3bIKNUR|o->W!;KA_KVHho{j7FD0CR>Ydc!XrDnQYo<)`kii1F@?=JRT%Qxue=YAN>;=(at zd1Fmx5-Y@UO{A>=Lx6hY6detuLKT`?7}?)=^SzJ++p1jUWgX{$|JfbMeP|a(8H#~+ zxWC_5)AQsLH7R4CG8-K6Mw#3r*3LD{bDFrFfwyH5ZtdzobSEI4>nyhP&3l?TW^`(E zTqLJWjtU`|94boJk^A4ZB{nKzXlhkEz7$Y)JhmgQ1P26rO=5xP1ho}aQ+)LjK}|T`)pzo zgh(hl0TUM_6nWiHTG?BvgrACmGv$e=Q2+9mOTDyqoiz=%dChibub&wlOkgPNIDX+j z-`iyCT`$1z9@`9p1a9IEA+Nj#Q4#mTu_mthOI#PK%!__JpQs8sKpmbbc&%A=srNG_ zXfU&}MfoUv7&&QyjfM0CxCz8M3D4c{$^pka8^c~*>kByhIKgdQQN(;`~|YWl7Y zb}_W;1H&7I0ZsP8nbYaS+%q}L9-jWhZ*E=63giCx#7mS1mjYeQXkgxt{Ok&pfScO{ zE^(4J1o?_~xz7@`&xH;Iyu$Kl{{*~(p=CFS$6oF{KuSR54zW@y733ME5TLAU8 zih_sj!C6UK8zOfsZADvsNJM~N>IHFeZfC?5PGoml)Ec{ zI>vLMRnN?iL9M`?r-E0D`!^bJ*amMtFfij;gb$1sw(|A%O3~!jxV?$UUQ)LqL?a^U zC5Uzx#@?plW1TrV5J&R``k~oa2tP`EQ@^dyV(-xF)jMeYr6AD|Rbl*__u}KTe7sI$ zkpW;3jxVS1OBzhk>8=zF6B0-wAB#V=HM;^R}9<@gJuLr^XkAq1+#SEg$WBLqsT{X_Vz?|Z}y>rnk5 z`mkfG`k;z2|2yKN=Y{b`7&UXs_swwW!yfh^@i39i*SWm7ctf)sP1x%+I>fPK5u;~? zf@e?)5zuL-Pw;>={H;6yQ`_v<#5(~yj3@sf9_!4=>?KqkonRG82n>?><^Bzu>$&?k zvZ#ZJVZKa1Y~L;zJvq2iHomhPvSq;RHCOon7egHxa(^=_<)KsyT*V&f!RfZS4^bGB z!WkK`LgRFhw~!o16Ks^Fcy%$O7LEboZrK-(8R%h;(s381#Nm%$Msw*g0hqN!;r}h! zb8XJ#1vofj0D}f0&o#BbZo}Qb>h-#B4!)j@(8y6YJ0VBi(Jm#{n9&X^ifoaH^0SOd z@6r#G8Ht6Sk8NqMFO4?lZv^(2P*mBAl0DmMT$?`Y0ny6QhsPDFQl89c?W3areP&ee zKbc?~cZ^7F+UusI%iQ;I3pgVhG~^!*O4IDlN3Z~|ycl`y-UR_>E8}r$klUYC*Mdgo zrAxIi=zO1dmFTpM{Q5-s?s1t{d%f}Rv+?CR0#)?l`U`_f+z&8Sb}WnIc!gH_)^(Rhi@)Ghl6MRtLfl@eYM z+6w9;9Z+^0V9*8=PS<%+Y0s{_xTrJU&h10EtK<%@)MSmpiC+^gXy8qUbvI)Z zFRgC)ur>?!Pf2aXqVy*ltIyQQpr zk`#2YyW-JhXu}k2Nh-MZm;Ofk5yw!wNgw>zoVsio8rGaoqY=C!#u^9+?VDj{y%4 zO?*O{&59a@TU0vOOPhU@n(}Jcn@QcGcdXw%dc#+ILQbE3quzDxuLsq`yF<*;_%Pt9 zWc7my0shVDCW1RA;?(%JC4H4AiclH&gSo4?bp*oa3a;Ipfou8f7EVkM9A@ z>V_Cwy@)WXmV$cWVesq5Vu)UIG3Ww##%6EINLo&^d|mA*XR;Xh-pdWvQMO*6d1*AYpz>#4O(RsW|`;D3>Yz4vrc&` zI!swg>2`pZ=PE5xbJRmyfj&AdmR!KI9-d90EsRx9Dbky${RI?CVJ@{%~qkIKy#8+!3Wn zNMwQ|Q#M!W>SMr-(3CB6Czk&~-m8x_zBR{wPec-3zQmuuzjtn6J|kcxi?1I_lTg^F z+8dnOVWVS~=VoWjlSA)a6cj880ElcJ@XFq%GO#-PrSjf_%Z_o9}U zpz0`)=z`HIn4;|3sNs0jawt^LfzK)!@RhYSFFMM}W&HMB3ArtOtM2fpmjv_XV7iN@ z7y!keMV1Rc}bwz|7D#{FEecHCWVy~noowa>@-E(H% zTMLJgcJ!oVS6+UlzwDuG*zgUUh|EOQal2p(06nql&$?(5)E_$doj>+BX5>5kq)&|V z++!RYhhG@C9su!#!9xRNt^ z4(QfTlX3UDmBB7O4z%>kLQF4#ORd+OEoRZ%ee%7pyRcx0FjhGIWwhPihdr(i%_n0; z<;^)$MuSwt!{~RV`k2Y6&G8&%g*CZirJ}uvfw*ps$2~uyE5MnHYR*kf^T{~{RLkBR zMH*dz0XHdg$B}Pb4}uG+*sib@I!n>Hv5|2x9@O3)LWN1EU!02SNTIXalB6iY+Z|75 z;s+Fgl6WHT$zk0KyS^1iwhUQCng@@A1z2G#wjA=I7#%9+U9f@Mi|shdbbY=f7zk{` z{^PV?sx-bhulj5rKAJ_Fi)%&tSBp*;_cEQ9qKbNu!+P- z>Z4@Dp?IPWwMw_prq^mO!>mvGW6Np?;u0u(`)~iQDf)RmpXg-oM0hjjeOumi zn^pr`Y%sh%kZLDqezbP-gbWzk#6^;JD%s>Hi|v#3Y0+e{Md_$J1Uo36o0o~wgH45h z)n(lX#j|IY*XqVlT*nm`p5=|I1avjW5^iiXzgkchymaXqZCl-_OitkeGF~|YX97U| z@>a)j&}8*1*2{iyenHsAk(&?vj>IYValmGURj&)M&$WGe5I~V;%W$&zzS+3dUl@S^ z24KDq{8guBTIaoOjQS%gbEBsnV4ob}gM^h1If)-79NzXVF8XK$QN~ z%B(;Ovg-Avh*A^K{2pQ#BUaG6V3biLw-$nUS)H=u{@8#jo3Nfe(dKK~E2dTbc~2TH zy~DTHdZb;o`fosp&r;j|i^0Kcvy~z~-~nM{p9q`uB3b)s2bE6`grT?YJi<0S*|w)y z!Upe5V~F>H^RmS0AXFY z=1QVelcE@78n<8BkhS@RlRR_m2`e3_cfAw>g@g$nqe$`1iJ9954+?pH0E!*0zc z-M@O}(y>OO-GU6{=f#ZY%ANbVtkIQw590Uk)J*BHrza)fFLE?3MDT7=FA`+h=wdxu zB=>(vl$VVmf8I>HAV>$vURMvM73P(*sy?8dQ3$RlAVlEnz#cMOYh7!? zfEAMsd8s%Zrt|b8w_VlG8q%hWLn5jtjA#?=je)4SWj0ocOt08qD;JV&Z%33FEA(!R zRJVFJ@ROjF;9G9VrkwM&Sz-dU;LbrEI&eShle(iyDy^uPHIa$Z`}tUjau%;) z>W>dzCn1Xesms@Ih&KNNWvnq@ld=`(JFQbe-!dEs*MTAU1PYxf7zl@Gag@(JtH7hV zfUwn1h!NY@8Zl(~aq|OKPDJ=*9bX0j!yfU;yuxSz79*`cGgt$XRTluBS1E$9wapq> z3hH_eB!q`qB4s?rFrq4kg}>2B5`TpD&pc4o6B3aOR%b1AJS~cq{R(mT7!yUcs5M~6 zMn>&O4)?do(I)i5MY`^ab##;IH7AvtX^J#0J7CNIuwJQ`Zlpk?r;J~b>d?k-B42(~ zgv4J}(M(N;tClnFlwpuW#P#;uSN@|%tp`4bvL`bD{5jsTHJ(6=wVkWKE<M{K`e=tI7kJ#^D%e&t_1{tT7XC%*;g1!{ zjtX89-I98ex1=6Y`6Hz|oNR!75GAGCdY^{P{TpWO zSUTa}8c47S}IK>NAfhq{Kujio(9ARDkm zrKvl}s&46s_+`Ldf?c}HTwLRIsirHG*hkSrGhu}wR6t(8w$FW7rnke2;}Um2U9-D~ z1QV65!!_-#LTJoH@D1u^7QW|*!5QZ<&Nj6}K?wysJqaZRNxSZ`22jzj1AFCIISTUq z!o5KNNsi-aLcb~Y)m`+xS}q}=TPA7#cx#3`EkKa^SPoifQWC6Oq> z52<>rKCQbh*o!hbDGKjxH@=8|Rnuyc*2{PpFQW;7f0|fppDgIRr8X8v->1WVZow&% z3xHE4*-%F;lr!4n&RFYxDS56;_2x|tew*fq2b%WO7?Ar$4rmQ{!F_=(hYUzhu;mdy z+T}k-2ME^^uL+qmuxx;No7l@HlRZC2oX z_Z9NW1Mb7{qiE(^183_50!ghTLmM&Eq?}UIe&xVUMW5T)WJdGH{X-`|LcM z`)ffBn8Otfi2AS(ZtHlVL`2Q3zp=K6t?&SIo}v5L&@Hfe*c^~zJ9l~y^TfKe%CN@f3-^nE^RSvaK)vvA{`Y$Iy53~=+0U!sJA(=|RL>{6XCJY0s42AQ z=Hj<@BY`uh+irN@FFu;qS-9(Pep(4&#Exw>WmW)}uRo)>K|eke=lO;huf7!7!675A z*o3`e+!+qRwl-6z7}bLc()1}Uz805Ue#3L)TXaKCU8-I}Su7kgwu=m$Z%xQv5>Dea z%AOZ>N0i+G2#vhTo&zjkJp?rM^b~5q#F~M|E}SR!c4ggAbN)&HOWBY5`FD#r?#Xh` zD~4y8jUvjph)mM^hRQFG9G5%P{aX1t+0$Xb1Y<&)kCeqIJGWQcgx|fBdM0Rh^Jebq zSyH4rNKzC~9~l~$6Q^qRM*-&wy@&qB5ot^RN>E!L%wU<{zZ(Sp8dv#aS=ZT{za(6A zI~$Rgsz${#A$0BEA5&*R z=3CcB=d$u-#GEhVi8euih^X#lN3+z9`ZTHgP%i3`nK$c8)8_J$T$4nwMoLlYhW7$y4i+f?Kxe z*Y;$ob|HXs|CQ=Uxlw<=%5V!uqJ2@~aH0GD>GZg4J;1;b$0*FZglID0LJZ5v^Xb?N z8yboAz;|L5@Hq1FI#gT%^~MV^)f0|z=YI~01;KJm=YvKcb_z9bcWaW?&Rr?NMhd4& z<_y+rzGD0og(P!7pm^-8VavoETX^}9PG8LiH-V5V1>nROpxy-gue@t@6G+ZUIv09` z@|_$=`tH#5q<1o8(vIq$L%SBrL~#`6goOb}SB`jvmLaPZzQFEfSp9ic#_1mJmAhyZ z2(O%GiXke|-zaN+x-Nyl^S95T4qD4kF|18aG}+7WBv+c=wJ9K#u;tdB8tJg7k@p?g zK(&+};t&(y+PPwHyux5HbM`2i(9qJdKRa9p44>xyEH~anhMu$k_ar&;64cRyPN8ly zJ$k;ii6JhW5s+~;_VD(vA20g?T@jVbM>4RNvj+SheCV>3UTCgP5^1yZ^}y z?6;YLpd{zvT|?WI&XIg};Y=j~wwSm9tD=^1YFnU@W6)fCiIXYk*n2!gF>(*Fk>h1Wn zUf=&<<5GWYwj((`kKae53aco8zz#3&FUAKeZW8T3OsC|@mJsE#g5z74SD1Ul;k8+| zS{VH;94_`2$8ijb?cEnq-{IBkl{It*W@-hQ^}&u`nMc&H>Aft_dPb+8-E^9j4g0J_ zAxB|IlpUq9N2g@)hNi7hI<4$M!ZA|_TI`48UBeJ|0VdUWXa#<`06U*HVSb9dq{VPU zzJ>kB<%@2LW)l+sy;gq+CBe#?f$|*OA));(y_U?F&#uinhy7HAN0kT=Gv=?Zut>(14Dl)F=svb5xYX zbbK8IcG;~+Ug95Vx5plHk+7yqXeQP2Lxs@VOqFhwysH-i;hpmk2+Zj0KQ&5%HcmTZ z0}L@>>QHXZbx&j&^S+K0yxWG5$EMsl^^ls19PDZVl;VKzFJeB{BX5_LH6R1dr%49F zwPqH8*FkjQx8mQ%NWMPI)BZ2H2S3(1Z#MCd>5RlLAubN`qX*>sE8S3JKo_^F7rdO3 zdMvU{NmqDj1|4&=eRQ740bqrA-d|oiwgvbw zX|+fqS7ZeG5j>1Fk1g9zv4XDWdp9Nf0NgLrRkkr0gQi8lhKIL_nL^3*+=fCYcnWT59E85w?5y@;_E?X?OBvHxPiV73YQ{ zk2h$djSCD~-?PMgcK?>A#x&?b+LBOg*9X!r@yBAzS9s3Jscx1MC82bn0Llco;rhr? zz&eLeBu7I^UP?I?lt9>}Oxy+IR-GYu5RR!AKmy*uTUEJF^C~4ksq7IZM3c2U+`B^& z>&NP=*OPVHJ6|){2$^Ja^4;2UL$A(_8CCzi!DR+_8QZn~3k|Gqepp`i1Q$7oTiON5 zC)2zePapi=-O&+6Pwd*7d!u7ToUlurs4b<*3_}{~ zN$sg@tQx1V3IOr3%J{XMv}_kQM5QOt=hO$~IFPf%oA(W3oaDoTCAje>npZksN2|QN zWF2AiK=u5nu<}Wk-3l-VOI)3DDYRZNBA31|0jJ$VHsV8Qg-Z<>>g0AeF%0iwp7U~F zK4jNwPDg#W2hD}QVc`9aj=StA7y1JV_a-b6O)5#FEStl(I?DeDS78U%%k<8GFd@;| zlcz>0ar*;SRLdQT&|#vj=XDb_5B5hB3!p!g4sp5XHF$_gJJ%ROmmHhAuoqSDVm{BZ4ZciJmlX(HbAop*uj&A0;XMj{_iytb z`B?SNVYz(@`_5g>uayA4fX}>z0wBSDe8~SRoZRvGqvJTkhC8>rwNv~Oe#zJWApR9r zNTrqr@CEMj6gE1^W?b#s@Xr|!5IsrPe%QEbQ>mySP)2#>^w8~oJmfii-$)zWXJcby zbs$FWqya5hs)z@=sT)1m(ty?nNSZd#q9^Wq1B1>Gx2hV%+{IRqj@%qvf1jEqC`cTX z$GMO{@$7qoaw13Pp_IaHwV53F(}Aa0cXAtY2$l~H9>oV5+CNX{ubXMTbLTbmyaQDH zc(i;yqp?u9eK`}+>}nYXQQmqpTf!1OdPSJwYqy*Ugd{( z(TK=;3Ah-ceM$bO88i;|b1`3pa&znsq+Bh4_E{w%JbDhVQc6;8+S?2{7M`F;NI7F- zBLSyX2$dBU7M8s{=>7{pi2ns3df~pIs~iGsMeR}jB^7Ex0_7akqb#1JJ`Z$G| zKF`LF1>L*Dz6DScx{0WlW=gyQB_hAHY3k!J8a5shd0~d{&~yl$uS?~}7tDvW4il~9 z0E+nc&c+UgMW1wFVxDW6Sm?Bll%w%r28lv_?}cs#4S|5Zxy5Zrz{<(F|LQq)!aJIg zNu87)Ap;sy1}xm#0)^9ftjmEPfYL==(53a>MQCFguUuJR*Ef! zbTMJ%_Q?rgg)n&I>TXn5Z%o{EMEW z`%|mWu<7ox!*fG1Ng}#2?m_B~g;Z@#_2YiEyINnpYmc9UfouBXfbm0>g?D1l=h8PA z=_bmwy3MF}8STSrX|CLUU`}1tJQaHjT>oC>0(C?5d&DY-1nn5#GB#xUMy3;+MN8C- z>!KhkBDtopyzApyY3<5PhT@+0L5}X;mgw0EkgS#u+op`%Q$#l*=~JrmqriBEZuxow zeQXwmY1qQ>`wIv684Sa*(*lPl{TUNR{ZtMg(~FJs*ZuFZm<@4Urah}r)zS?1Kcgfj z02&(rO8w)F@RyWrz_cNX2;!Wg=#N-ZqqWV9NK^Qq28w!Gp*mf;X~qS`XD&TPjGqh+ zYoiUA`jo+4Fg8{5-i1~j>4}65#@+AmjZ1*ofqDifD&AFvkx|Qi@ zX%Wg5W16tS!9cO_>|=3A*&!&@mmK~x+T9}K13#;Mb~a_15Gjb>r{XIo;eCGX7oy=Q5N(oRlgB;#7e_~Xkss|ShFxu zky+iSJNPcYqSc;VeTCt>ZJYi%#dqx(oqg5zIY9aIpzmT6-lpIDf6{Nos}Ha24)~pA zQd(B2#Ko39Ab42;p+upM%`ug$Hn1r)2AWj4$!;=YD$m{D1PHX7mba_y8>Y?sBWps z*egYhy|xS2za9n8-;V-eyXPp7hFPo{JP|Xha@`vt7w08sIGOjt|MaKK=4^Qgpk3xL z*vOcQCXKC5hpU6a3wsXOd_Y1%FcPl9&HEVA`Z3r%MC5=x%CJVa=SYD;JB$ScexFMV z@X_1gz81HsZx`on-mRA|gr#<^MOWtoA}=*BUdpr=nAwOFYjzcNx5}Sm!P{E6kc2<& zeHaE}qS%Gv+|ClgYFunXu%pc$rRq{@#*ctevoH#U!$g(ddB2qpqjd)E_K1n=rwGCL zoOP)g%c9l{^|*%Ckf@3oS|g2(McB3UbcH~ zLfM+=Wk+aRn%#;xtj*N)x-o6l@woS}kJMIaK@1J$vO`HOt0|YWjnC2(@vjS9e294 zyf5YMZu}#lro{u~Cl^Le6eqVtJE3NW!+Vws4#>r9&23L!$a(Ocl^Y_EnE1Vv?apQo zZA0%H*IZVtr}+Ez(Jz8KR+Y$HeG2sY#k6jZzgWTK{smg0l;5uM^loqa>Dmr;yVYp% zXPT=%|Ef}o`2D5JyrniHc(WfTi8-ub(t|xaQw>4z@_>8ED{GApIXfPmU^evTxDTGN zuY+E;Y%fg9*U^oB>7p>egAFK)WfqY@tpg(hGcy?`k{ncntC~E;gFKt*a+UCGj9jP#`8fGEgDgJj~Z(L z5!VMDk>cXg0#!&8>HT(cc+goPg)2v5HZaW{CK*V_$z65`u?XeNB8?V#-$N0as0OU2 z;mokk>A@fwB5sECuNX+3Y~;IrwCY3$HrB;-zaFvv7nLgEXZ}g~_UHu}jYfI1M;V~Y zPkZ`=JQ-f3lC}Iq-4H@F*d%*phS%Qx?xyp4|60!XnsOoFy!(Qn0#`1oQ?~!fZ;Wp_ zxOpBqO1~Xs7E__K4P|JBl{#F5`oK3+8f@uiu)ljE6fbYq52{+tGO232d=Vo!`bKx^ z|MB$}Kvl18_wWX!k=k@ONSAbXmw>so7FOvbLWG!&d=(iMDFvb!-^KUs z@~^d2NJo?o;EohyiLtLT+nhc06HebWMtX538R_=$H#*}+i5p-xM@3jwL%8Dj;tDmb za8u^4`+7_b>sR{`_ zK7+fd;QWF2xa12>UiY^R&+tD~rl`adnn=qV5Y@r2_A$0&k=Z#Ceq#;z;kLi7# zLn6WY&B9qyR0)otmWbaaF0^ZG_cA8h3O0&0m4hvXhV%$lHiI%0Aw|7?@ZfKfrA}$PNZLSlcaTS((KtWh8A0RRr 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 z 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

    PJ5T~ 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 z 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

    oeqyZ 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

    UARSk=<9Hs3dBNJX5jo_GSXme9BN(p;Zek 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

    k3M7#P+Ll;4wkBM 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

    @)PWp#%q{N^j17*)``R$uTgE!Xw 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%0AgihxYjNV5ZDZ6H1waZc67 z`_W+1q{Wjpa7n`l{h?2WzlKCcQ8|Oi8YnVe)>p&-6b>QMa%uGU8zNac*}?=2PZ z%gQJ?P&pnWGq1NZc?6I$@ffz(ZSN$yCZXa?+tvl?E^X(2O{XKkZ>{jh2+voRPhf;v ziBEY7c|jqhB`72Aii)yr?Xv_zw?!!)F&%0A>^U?M!MRV5{{T+*O8}m0%tMYQC_$XE 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

    pKAiM#wfN4qM>yfW&#k%qor&lpS&Xpc^)bXXs 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�IdC*-_*=gRt3Q$@e}Lf8vXwi0tUz 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 of a graph (sometimes known as the anti-graph) using :meth:`igraph.GraphBase.complementer`. - -First we generate a random graph - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - import random - - # Create a random graph - random.seed(0) - g1 = ig.Graph.Erdos_Renyi(n=10, p=0.5) - -To compute the complement graph: - -.. code-block:: python - - # Generate complement - g2 = g1.complementer(loops=False) - -Of course, the union of the original graph and its complement creates the full graph: - -.. code-block:: python - - g_full = g1 | g2 - -And the complement is a graph with the same number of vertices and no edges: - -.. code-block:: python - - g_empty = g_full.complementer(loops=False) - -To appreciate these results, we can easily plot the four graphs: - -.. code-block:: python - - fig, axs = plt.subplots(2, 2) - ig.plot( - g1, - target=axs[0, 0], - layout="circle", - vertex_color="black", - ) - axs[0, 0].set_title('Original graph') - ig.plot( - g2, - target=axs[0, 1], - layout="circle", - vertex_color="black", - ) - axs[0, 1].set_title('Complement graph') - - ig.plot( - g_full, - target=axs[1, 0], - layout="circle", - vertex_color="black", - ) - axs[1, 0].set_title('Union graph') - ig.plot( - g_empty, - target=axs[1, 1], - layout="circle", - vertex_color="black", - ) - axs[1, 1].set_title('Complement of union graph') - plt.show() - -.. figure:: ./figures/complement.png - :alt: Complement graphs - :align: center - - The original graph (top left), its complement (top right), - their union (bottom left) and its complement (bottom right). diff --git a/doc/source/tutorials/complement/figures/complement.png b/doc/source/tutorials/complement/figures/complement.png deleted file mode 100644 index 8c980a3a98e9f3d2aad77f5ec2fe139f50f1a38f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85235 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⋘h@$B)GdH)kYC(|+ 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 A6aWAK diff --git a/doc/source/tutorials/configuration/assets/configuration1.py b/doc/source/tutorials/configuration/assets/configuration1.py deleted file mode 100644 index cd3862e0e..000000000 --- a/doc/source/tutorials/configuration/assets/configuration1.py +++ /dev/null @@ -1,11 +0,0 @@ -import igraph as ig - -# Set configuration variables -ig.config["plotting.backend"] = "matplotlib" -ig.config["plotting.layout"] = "fruchterman_reingold" -ig.config["plotting.palette"] = "rainbow" - -# Save configuration to ~/.igraphrc -ig.config.save() - - diff --git a/doc/source/tutorials/configuration/assets/configuration2.py b/doc/source/tutorials/configuration/assets/configuration2.py deleted file mode 100644 index 7c32aec8a..000000000 --- a/doc/source/tutorials/configuration/assets/configuration2.py +++ /dev/null @@ -1,15 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt -import random - -# Generate a graph -random.seed(1) -g = ig.Graph.Barabasi(n=100, m=1) - -# Calculate a color value between 0-200 for all nodes -betweenness = g.betweenness() -colors = [int(i * 200 / max(betweenness)) for i in betweenness] - -# Plot the graph -ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) -plt.show() diff --git a/doc/source/tutorials/configuration/configuration.rst b/doc/source/tutorials/configuration/configuration.rst deleted file mode 100644 index 558f07fae..000000000 --- a/doc/source/tutorials/configuration/configuration.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-configuration: - -====================== -Configuration Instance -====================== - -This example shows how to use |igraph|'s :class:`configuration instance ` to set default |igraph| settings. This is useful for setting global settings so that they don't need to be explicitly stated at the beginning of every |igraph| project you work on. - -First we define the default plotting backend, layout, and color palette, and save them. By default, ``ig.config.save()`` will save files to ``~/.igraphrc`` on Linux and Max OS X systems, or in ``%USERPROFILE%\.igraphrc`` for Windows systems. - -.. code-block:: python - - import igraph as ig - - # Set configuration variables - ig.config["plotting.backend"] = "matplotlib" - ig.config["plotting.layout"] = "fruchterman_reingold" - ig.config["plotting.palette"] = "rainbow" - - # Save configuration to ~/.igraphrc - ig.config.save() - -This script only needs to be run once (to store the new config options into the ``.igraphrc`` file). Whenever you use |igraph| and this file exists, |igraph| will read its content and use those options as defaults. For example: - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - import random - - # Generate a graph - random.seed(1) - g = ig.Graph.Barabasi(n=100, m=1) - - # Calculate a color value between 0-200 for all nodes - betweenness = g.betweenness() - colors = [int(i * 200 / max(betweenness)) for i in betweenness] - - # Plot the graph - ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) - plt.show() - -Note that we do not never explicitly state the backend, layout or palette, yet the final plots look like this: - -.. figure:: ./figures/configuration.png - :alt: A 100 node graph colored to show betweenness - :align: center - - Graph colored based on each node's betweenness centrality measure. - -The full list of config settings can be found at :class:`igraph.Configuration`. - -.. note:: - - You can have multiple config files: specify each location via ``ig.config.save("./path/to/config/file")``. To load a specific config, import igraph and then call ``ig.config.load("./path/to/config/file")`` - - -.. note:: - - To use a consistent style between individual plots (e.g. vertex sizes, colors, layout etc.) check out :ref:`tutorials-visual-style`. diff --git a/doc/source/tutorials/configuration/figures/configuration.png b/doc/source/tutorials/configuration/figures/configuration.png deleted file mode 100644 index 73339f27684a14a68d01adc91aa37f2d65fff518..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44598 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 F{{e2Ixhenv diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py deleted file mode 100644 index 6b1bc5b67..000000000 --- a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation.py +++ /dev/null @@ -1,34 +0,0 @@ -import numpy as np -from scipy.spatial import Delaunay -import igraph as ig -import matplotlib.pyplot as plt - - -# Generate a random graph in the 2D unit cube -np.random.seed(0) # To ensure reproducibility -x, y = np.random.rand(2, 30) -g = ig.Graph(30) -g.vs['x'] = x -g.vs['y'] = y - -# Calculate the delaunay triangulation, and add the edges into the original graph -coords = g.layout_auto().coords -delaunay = Delaunay(coords) -for tri in delaunay.simplices: - g.add_edges([ - (tri[0], tri[1]), - (tri[1], tri[2]), - (tri[0], tri[2]), - ]) -g.simplify() - -# Plot the graph -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - vertex_size=0.04, - vertex_color="lightblue", - edge_width=0.8 -) -plt.show() diff --git a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py b/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py deleted file mode 100644 index 7bac09e9b..000000000 --- a/doc/source/tutorials/delaunay-triangulation/assets/delaunay-triangulation2.py +++ /dev/null @@ -1,48 +0,0 @@ -import numpy as np -from scipy.spatial import Delaunay -import igraph as ig -import matplotlib.pyplot as plt - - -# Generate a random graph in the 2D unit cube -np.random.seed(0) # To ensure reproducibility -x, y = np.random.rand(2, 30) -g = ig.Graph(30) -g.vs['x'] = x -g.vs['y'] = y - -# Calculate the delaunay triangulation, and add the edges into the original graph -coords = g.layout_auto().coords -delaunay = Delaunay(coords) -for tri in delaunay.simplices: - g.add_edges([ - (tri[0], tri[1]), - (tri[1], tri[2]), - (tri[0], tri[2]), - ]) -g.simplify() - -# Plot the triangles -fig, ax = plt.subplots() - -palette = ig.GradientPalette("midnightblue", "lightblue", 100) -for tri in delaunay.simplices: - # get the points of the triangle - tri_points = [delaunay.points[tri[i]] for i in range(3)] - - # calculate the vertical center of the triangle - center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 - - # draw triangle onto axes - poly = plt.Polygon(tri_points, color=palette.get(int(center * 100))) - ax.add_patch(poly) - -# Plot the graph on top -ig.plot( - g, - target=ax, - vertex_size=0.0, - edge_width=0.2, - edge_color="white", -) -plt.show() diff --git a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst b/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst deleted file mode 100644 index b2fc98f77..000000000 --- a/doc/source/tutorials/delaunay-triangulation/delaunay-triangulation.rst +++ /dev/null @@ -1,104 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-delaunay-triangulation: - -====================== -Delaunay Triangulation -====================== - -This example demonstrates how to calculate the `Delaunay triangulation `_ of an input graph. We start by generating a set of points on a 2D grid using random ``numpy`` arrays and a graph with those vertex coordinates and no edges. - -.. code-block:: python - - import numpy as np - from scipy.spatial import Delaunay - import igraph as ig - import matplotlib.pyplot as plt - - # Generate a random graph in the 2D unit cube - np.random.seed(0) # To ensure reproducibility - x, y = np.random.rand(2, 30) - g = ig.Graph(30) - g.vs['x'] = x - g.vs['y'] = y - -We then use `SciPy's Delaunay function `_ to generate the triangles, and then loop through them to add them back into our original graph. We make sure to simplify the graph afterwards to remove multiple edges caused by triangles sharing a side. - -.. code-block:: python - - # Calculate the delaunay triangulation, and add the edges into the original graph - coords = g.layout_auto().coords - delaunay = Delaunay(coords) - for tri in delaunay.simplices: - g.add_edges([ - (tri[0], tri[1]), - (tri[1], tri[2]), - (tri[0], tri[2]), - ]) - g.simplify() - -Finally, we display the graph: - -.. code-block:: python - - # Plot the graph - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - vertex_size=0.04, - vertex_color="lightblue", - edge_width=0.8 - ) - plt.show() - -Our output looks like this: - -.. figure:: ./figures/delaunay-triangulation.png - :alt: The visual representation of a Delaunay triangulation - :align: center - - The Delaunay triangulation - -Advanced: Improving plotting style ----------------------------------- -Sometimes, we would like to emphasise the actual triangles generated by the Delaunay triangulation. We'll add in some triangles and color them according to their y coordinate. - -.. code-block:: python - - # Plot the triangles - fig, ax = plt.subplots() - - palette = ig.GradientPalette("midnightblue", "lightblue", 100) - for tri in delaunay.simplices: - # get the points of the triangle - tri_points = [delaunay.points[tri[i]] for i in range(3)] - - # calculate the vertical center of the triangle - center = (tri_points[0][1] + tri_points[1][1] + tri_points[2][1]) / 3 - - # draw triangle onto axes - poly = plt.Polygon(tri_points, color=palette.get(int(center*100))) - ax.add_patch(poly) - -We then plot the original graph edges on top: - -.. code-block:: python - - # Plot the graph on top - ig.plot( - g, - target=ax, - vertex_size=0.0, - edge_width=0.2, - edge_color="white", - ) - plt.show() - -The final output looks like this: - -.. figure:: ./figures/delaunay-triangulation2.png - :alt: The visual representation of a Delaunay triangulation - :align: center - - The Delaunay triangulation, with colored triangles. diff --git a/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png b/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation.png deleted file mode 100644 index 4c25e005d698ded4f0a5541ac7df0c6b300a29a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56427 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

    aphD3#f8>3zYJgAZIQ&=LN74+_h2 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%0AeZ^Qto>dWKMExJVp@tN~`9B9} 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�?&jaGMpa^2K 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%0AL^;8BCWS=&&%W4ZsZY{bIK zmWo`!R(R_VM=_nQUA}Q$Y(FC{hXfJyC6I?Y9mZ=FwdQI)9w zUer)%pS%r)b>p%D8{;3n%R+kf=!q*Dnx{Ja`LoOcwp6%SaVBa%h(D>f=)OXU%et2) zkaqhMxKn`Cx5i?4U$$p>Z7!O4*s}p@mtK6%`dmPh5{5&MZ!INdo1qw4kltQrpUTTYv{K z-U}5~h8ky)H&C9KyZBiqPW+)c%ifiHL&uYpx}`PDbJuK!d4+c0o`;xN@0l{l3k{Rg z2$QX*@QUF{M_W~4&E`1`?u!cUcyDjuD;TYDz<3*(3~YWB4j z(Axz#GX|a{IO6U`K-c=CDbXP>_FTHhNwKB9H^CUzd(o{FkBqe^96UI8WRh6gUwf26 z467q153+AnoHkyKH?(};oi{(iP)r@BGXsm!c?E6rD9%+AxoK0dT|QLgtq72laWMoU za?L&hzC%KE32mU;d1X;tZK%m?Bj^TnPhudC&n>3z`2DiblDMWCV!JZ5&eNo$p;?4T z311)HrNQLf!tk!!T=iobi94*P<2}|qW(wio+n;$6RMOUu_E@0yx?c+ih&uMC)9jT^ z&!aOP9TXv=s(*m%dkROZ$pZxn>-$?`@5<%~>P+@&2ud!)X<08Nuf}F;Tdt}ycmTGL zOsFj-?ugJocgID+8l+fz=On#ceY?PxGz?v@uZ+y+*ANnmchd6HE9=$IE7K#X=tQsU z@>Xvs>-8KF?0w=x+IIZ4pEfWHD0t009>T+?+4pIDs8ujVC~aa^#4a( z&v(+GVFrh8`xWM5b?-`Mv*`=z+dxgYhw>=CoTQu`HcucIot$Z}^W1aabq(yT8LVnR|K6{2EZ1@HiT zC)ToMFqfRS)v5AwH(^6%_{AoA#9ZeAEt}i;pF^azrgS(}KlDO2t^@FPg6Yr@fW_2!Z+x%c{_N_!g;+dRnAA1v^4VSXc zmlm%wg-nI3rwl$%VkNHrkaR4AL}dc3;O~NYVRs8Xc$q}Pj+k~LGZL=ir43P_lS^FI z6@GV0KPIlH88MMynvj?G-Cg4VaxCZB9uon6wBM!%5!PH$L6oOXJ6|0v17POuN2u+fwTV`&^Op8#Z1HykpS=q?^Efk7 zn67?MIr@ErQjJ}s_VZ0&GN<0>KG^ryqI=oHSG^W8_tqjH+m}wA&8YeaUSAHKjVO~b zw$%Kzfto{y-?WHau^MB^$Mm9vh4Q%|h26 z2=s4M$MIDut=`fNlht{;(&JfQyK=~P&r!7I-~lpPa39L^n*#JKkiC=PhG-H^z2PDv z)IW1FQNtA;)TaL=47@2FzK0bTx3E_aNFald#>k&}P53@-DYf2+00|=)Jhx1kMz`da z3~+=Nc9#9ydt%d@_plLRA{B!7hf@d6tz-muxO;{y}_%n!~jyL1~+nrFSqIWl|Z{qz7_YNyN6REXn2E86RC_F$j;tq_M> z#z0|6gX4I|xag^n;}{Swhx_L^CF3sQ+;EQa?jLa`{V@FbN36V+qePN zJYHFLJk|Sx8`sdLdQ-4JTpFA#ynpn)cHF0fEg@!MNQR0SN^b9y+?Bw_pj3^v4Y5u~ zbQWk)PF|TaX9$B4e8JaED;_!MbRx`qgm&{B(;sbD*=JkBe%k*fpE>2HjMFa3w1G{- z+3{tT!}dS`;58v-uSyRQ<$dUW=`K+&O?cCD_w3lsQ*yd<`0ky8^22!jZ$NEp84B7v zZHs%_eh2e0Bvo&UhgDLbj>fe~q=1tL2wnzcWF4jIZS>kGQ$nZUCT?-OvV zwwEbn5LsBTQ<@KA^!;B}&b`FFZ|eCENG+*DC2^_i4N>MHTO2l$J)+-kT;<;Kk^+%Vj3HwH z0DnW#Ku$a#g8(=1f>GcUFm#(WxA9-X?@24&yQA35M2cxXJ7 z`Z0U#8WX_h7*J#vg6;0>A$Ts2J28OKW*;S6Hm2RUWL{KvNC@-fHzO2uG{3IY+ zD5d6W;g)@Rh|KJBoIkUXOWI;H0pa-I=mC0boz2Q zBB$?)2Dmy**NlGP8!d&lH6c|YUYrVEw!os*v$p>Kk@FPQde^Dcj50h47XT%_ZW zVr69>iQpEFT|W4JbKC0peV&(sxyaV$zD5TXH_Y1l`7+$Dc=0xU-N72mxzJ7+YaR56j(DLJ{RoHD-Eih^-?4Z^A@|6By+;4UANb z4M%_-E=x@xeJ|6Y+86(?MOff`PCzK zWbI5sfM{Z3_~r9>eU6>|N#tr@XCuy*w7D$#WlJ7*!E5hHEoY;3vix=gB5bDBmmET! zt^BeE+L94wiVU|c31Y}R)JlU4#D zRnUR}DRV{Y>0fvaa`$fj_8W$_jbDWM1T@^Aqe zT#6-ox_$a2Kk=y3P30QXH(T)gjVYkh@w4*J^l_EWE10dVS6HER_KS4PKs(zsw|TcTx` zpyYy>=R+$I1lDGJ_uWi}yTAWGg0O*~d2ec&d1sNkeWU92J{_dvf);L8ln(TTe7uj{ zy)6JeP3(b(_9WRJ-KS3xGVl#1Jz}I!AFZBN2WC-U_$KM%cHQHH8*k&apyo#LF5yfY z^vWvQKb5=3^Fc4AEaXf5lh!t5?#>tR2o_KrIqqzbY4?7QP;5j2!46Hw#KKkyV!PEN z+pbR0Jd-?GtLI2&zXGa;$nv4(eAm@EJtF=)0v}NQpIFD=e697D&I^GX%M*R+U*J8; zjSx)BTZfV$U5PWKXFZ&`Bo$Lrw-OQ>1`0HtFBga{L6lrix82g z44gxBj0jx$)*aVKOC*7|jBlaEDjYM}+vSu(Lr7Bxcf~R6z_bM5&a2$j@qe=zzmq#y zV)ZefxQRMzN-N@~S24{~O-Z>^W#fEIAM~CLsr3>)OJ5K@l21%F91UcupuUAse9MWr z#LvjF3c`#~HU%Ew1w$(prIxix3@Mg}anzu%-Pmiv>XyhSTZi;4qck4DuV%3ZU^B4XV_9g!d@bB4dn_3?48k>@ud zae|#=fpZ&%m|x;HC~2L$2ocC6RGZd%35N%UWfz2WI!&A2)j0w+Ro=zuplKVD9A{dP ztfZ3e);}I5Xcssne<`YPCMllc!Ve(6tN|@{`R!*WIIG0Wm=^SP58E6ad#?82ehxbs zy|AMF-5SKK_`zDDXeEwa)@7LKI~qrvHHk`7odU>DQa1mJeL`BnFxmLfn%=m!Pa*!# z7Du4pv3c5s7_odo>&PT@bui#I2lOkW?rA6K$2%)D?}jMAc^4^~lYMo~1JKiyo7KAb zhTD5OYsv4?o`3)NS+3(BKY(Hm`r?H?rK2nBJ$XGtc0;~fU{jplEJVhoKL6)3uL`gL z%C%Y2(}1${8q930Xw4p(FQ#vD<}86+@$i_0USloYf?**K~jd7Bv}|7&#`y;~8QHvgZVlkd0SoA~=3<$fJf$%|`g+La`BK4ufbs+!Cu zDop-Ps7oow{w!5e^6+TsJ*Iy{RKIYF_t%Vce#H5;hVv$$6Nc=yMPX74p*)kJuSW3W z(x^{MF{5r9{-bVX%Bso+Hihr@D;F#VqTq1a5c*2ZjafW&dXAtw)NoW_gp~lT95GBz zs51h7M_Tl1V3Eo7XG2n44PW%16&$)*8Gkd_xQ7;O?|2`jQutMc6$NCk`}(cDAjpq@ z9HhRJOOv8YNz04Zv#yL4rkH!w>_7rUtEd;4gnxywjA-F*$r7z%Ed(q_KHu(qSd2D& zTW}{u!9eDLo+vRk3+{mHC}ubN8mAxKB_GP6A%PC#5Ju{qMl{Ie!!f;7t5D1&_Sm2X zGNUeAYO~0S*oP}xQnG}POtNqBhc~iZnc)TB zdP>mi78a@dh8Stv^VgG(b5R`>&zG0+TaNl#hx^SJMLJ59m>RPD7mQ7{&RDnaYaQG0 zmv;;lPw77<)=S(1dJnfJJx*>N<8M=4*14t8zIg#2urT`IblDHsm8YJW6{s^XX%Q7- zHt_i!$cX9zlI7ld{|~cHpRL2t<#Dm8%MiItr5yEmf=YATo-d8Og=I5)5SMC{vE_9` z)uy#`5@CURHXZkV&{ew&+D+Fq4A{o5UO!E)yf_CM!{qL{{B8NBn0LIA)$<~ z?+d-1%6}$p0}hP;BQR@_==}BIGu#hH;iprw=bn#|r02y}mL?%PgHe7w?PhSfs>>=m zRorRrJ`0LM1HaLzvZ!+|l5be^i+`=+{57wuE=fLlt^DF@!bw;A08}(a|n&IAr1&cWIQ3W5xR#3a6V9lJ-zLDT^>j z+1krv#x^em9ii16tsb~SNjsZys`Dl(OWl~RJ`bpTcxHt~(%?=rt7s3#(IW_9~v6 zwo>?zF?hf6K7x>ysI(3iimd^|tLyH*zilH{N{ZN@5Q$fklv_xVv$-SXpmZ&M=gchI z*Osv*p{*EE+xbAd)@1DWnJKgwGD-fP@+XUjI#W0^9?rm8yct!1bj$bZWAbl5)~484 z`&c6MEz6`_J)Q$d_Ux@pr}O4rtXS)aDX9rTsebU51O^V@W)mT|;o!Cp;UI08wtWtm zLY0=A_TQ-jx&2R2NcyYnM8P^TE9zP-TBOP zahVq+k$(2i1x&;filtTf`Rq{@k&`Epq6Acxf=c;{OcrFxDE+LC@ad1ozkcKkfq^JX0NsJ{>Ls=9NcZDH!tmbX6Lb zj2}Y-$F&hfAZuJAe$d+RuUqciDJ!1alW+pJ8+YvCsmHsM5g@hf?xm0AEE>`9phtcE z=)|!(geoFt=x>|Hr7+Wd(6M`_aXUiVoL~Rv+N`me`vELZcbxHS>e|NJC!IT42}PLL zt*3=%`hbWL{^bdl2b0Hphbh^O{k@oTHmXhYOki8Ps2nsUg07 zqH@d%tuKobsai{o4hOBu_p8t9J)BB_?Yl!1uqOZ%>JC-zqyC`9&}DmI%|K=iwPG4fqUf)k;O!Lv>2JHHIFs?8 z@!CnD2qNX=sypk6=GS=qYwJofnqOM@<6kp;Eg|O#jk;m?JE_R)4S!?x!iTw`uFGGJ z9wxLbO)HQ^bh`M7GA|IMDLWq$5D^d6K zPs69A?fjJ>J9|&M`g|~Tj^DARMw%C<7Nw?+rIg#V75r~w5-H?j<1h~L^aqr7W{_n)xpGzhWD zvdd;$#*tJ;3E|@Hsy3CcXo<{rIt*>ig{RG8KlO~_$Y{x!*+Uw-i$<4x*^m_bmC5F& zmOYJT6Odh}DZMI5x((j_A&JZGPtY#FWA)B3o4^FJ<`9(bqyq)Mk^vSts^0H5R(q4Bk*a$% zSgx4}LP@)>+T$$DKO<1Jt5e6!o%xnh(*S`Bj_PWB9ABp;q}{Q;z@R~E%Jzk+)KBeQ z<;0Pr$3ZOP4Y&=yfgDVu=g3S*>(gKZOc{L$?1M|KBu*;GUG!n%6Uh;)b?n3zwzfIu zuNX+TB)Jvs80vP4n7E@ftn_G+zRtB7{KRNlmjAZ>?yF5N0Z3;lZF}CNKqe@>fmVV{ z@m+tfb8V^>s>0LRHV9EJ0^q|d*B(`hN$5P^XO~66P1=m5`nrl|5eA9cif|_tSEDGy zGy};NKJj9cGf?S15~lA$bCkvvbl&&w1g^i`ll^x|v~c+kT8@I|-Ph+}Yw)fFJLts& zxsLaG)Yq6#MCEY}sa(7(adeYS$b>S4CtUBHV_qmog%xx7ZI3Yww!Sg?+~ggJ#{FqAD5YTE{?I`aOL-=C_4sKV%2Nd>wd`tK zPJxBYTjH0fx@b%x4N>!EDW9mcBi9qM7J+U`nAvLB0E#Mec6dhFqR>rn^3g)5hc zv$|;zh^6{@T+{UpxnBO z3_N}PA*U)|QC%^Wh7l%QhA}3aH`j|VkpNupou$Y2FgCNkBRf)+IIH^zGSNvkr62SA zqWyv6$7HYj45-m4KQb_kdv6b5>pkuK?_$)~q!;}1-xmT6;_Kkb2ZkGZXg`-nb`QX< zkBLD>pIZZ$f0#p+4w$SfuKzx=TZSF8NPS~zU)?D~ZeQe-ZE^XzDop>i_K_^lHZN6YQ2E(L z*h)@C8>vPkOlpVM0bZ+>f!ZzJ_MoF%fmnDA*HX^K6riSB+``w~ZV2~-^di3IeLvYO z@VqE>-oYQc8XYfq%El z9rqf<-*oErQ4{;fgDxg)0`T&Zw(st3n3kw3tHu0ir%2h=fzfhfusuJfo52KxY;2!n zk#lrgcdEJ#AUGG;2~=Y2Vt5c|h9y`^HCAA%0P&2Ow|TsZlEX&SJogI<9?LhbaB%vK z@sByQK+f%NSnl?PMCZ~DO)_C7SqW(;AK(fQJUK}`$`AtAV16ormlEpZ>C90T0-08o0 z4X|xkcK4%OhCV%WdqfX>AQlSQ-(fD+edHzxteQ|o3V&x2;f`$Kih=aSu)zc(_Ku#B zZoT7HP{zdr&IKn?m)Y&|{38#|&t$|QIUQEKkXf14ai2SUTth)Zh3ye-Wy_tlG=K;? zSrF@gU;?xulOqqaoUd-rx3N^xs-}DKO%4q5-#CG-Dh9t9A#>&lNz(i_o-&YNwv)n3 zmw@!NW%Rzup5o-kOHm!$6l8j7(b5-S#C3GTdzfE^t}2-UJ?g#O&%^hr{9es@M>#=r z({oW&(&nfz$Vi`NFr`*rsoezpZ0(4fvIF{SNSwmh>)}am)Nnral*oVm>e86{&l%}^FpPh;%O?A1j{HXy&hIHo7F35MvABV9q zJiQE54#=xw_@e5$K$O|`88y-jc1@TR^O1ulcP`zABqK*ofzw3+7SW_vO$MVD8+%s1 zNMubQVeZ+ft1p_qL0+UO&AK=)wEOpl1^Sn!g!DI#{F7wP*AD`MF^CORTimM%J0F7K zNq7LgDGEW?%t4SD<;ho2gPP!r^{Y8n%JQ_sxxLA1WVn=G`p>h+n4 z*FrNeI(l<@pt75P=GGbgFrk*a;k<86=%bw?n%V1#0F55cw_2)K^sh!+kaf(}rL9p2 z4LkgNCRsRF#Z#t^jYUr>*`2YgphIyT$DR0w-Y*4*C(UQQD%Uu;nwAVdvh>L{`;ebpK`QRoWh^ByuI_d?@-xvEaawZLOPH%CM5W#^de zH+6JeEJDyrfa+kO#8 zcC?!&2*fFAbK_Xn$cIUL&IiUXEd+1Gt|{$?5XXxYtrz>RLO0o`X4t^QPdG^{cL<~} zD-%%Gy011#P|bktPHoO9JD*K9dZKpMR~J393?_0)Le}ARDf(kosp(!uPAw6_3r60+ z0v7<Ebi&_n%O-gx2*J!k6AU|prdab8H!u|+2U^tizAbJ%X<{1 zK$wY6YjL;exG9;I6=$xZ-fs1DT_F>H#-Qb@2qphlO6bp0Om2=>VscK*_?sx@w2a{zNWm72`56s(lY1YsxDs& zsWpgb=Ql~VUM?udy!#E#G`a;Jzd;MEunhJJZTs@d{0N}EEn#BpqNIwkm}l-0RI**> zY^eR}O`g%+hG0=))!8=^aCgrR6i3Nrv497A$Ax1K_4#QHO)(XdL}H$*;(o|SGN>xm zGKcG%-tAMd$;QBOwM*!Tzm7*-WU5drQ_po;$ByODZ5GBb`vWN>DEJ>+xED~x=jM4E z;TzXMFQbUcYBgjCxZcvot|?y&j2~cBG@e7QpYD>F7$5dD_jM4~P&DH;NBTp2MU5tZ z@Ar8$!lMa6Y7$D0K87S(?|JT`dh%0B2SvG8_P+`Az&Uy8O#S=4Rk#SVBp;VCO9T~R|4 z1SuL~J9wekAE^8VGi+&Wy5n~Feui9_ebnB}oS11lW0jmz35BD}UjIPVD+S4FQNyt`}YUyPg5dCffy|<>26Y%j8={`wPO%>Z}qf z#MJO1P;F#ML%Xy`n}BkODD;R*f`Gd;ic!Bj)C6pkjn*13+e#%&%F|`Vgvaa1H4iW% zEh`8Om5`&9_*s1L=n6gMVq`>-=3{?p_>UCj&x)V-*irr8Ilr6Wcrw+97Ml{tFw^KV zM7o(*=DT67NcM=Yx`Sbuy!pULARXdrH(;6wV^+eBmn}MR(lKZwL?8X@3O_LFCs~Ms zT_x91SmeT-}p+U@TKW$&l%MvFV>%E<1%VO3s3T*9yNoK`xyl}j|$0Y#Yn5l z!e%s);cN9H%K{J;v1`sRq<|#w>DP&nrwK?{du6KMedM!cIGIHp?Dc`?o2 zn<)o1i-B87nT~D86{I7_q&uff*Gb*$FB=*J;7|)pNdM6Il!4;;hH=g%L$OLUZ2dnQ z_lc2~a^`BtK(WD3HuhuC{gD@=Uxr)AhudWtQI^s}H?P)hzY8+mA*!ptbne_vzE0ODO>}(wwapt}CwjnOLCt1lr8T z2lu$VN)~O z5Jf{XKw9DZw7yr6KC7mo#VG07ezY)q|6GS9y1x}{EN6)V%NAnDWjG)QXK}|~vFzw6Ftwo|xTyPXUq;p3 z{)E#nQv|VZ=C?mV0HHn{>Vm@uXVIF*zyOrhp6{1M_anmT>SUcURk?$C$-u=OamM#O z*nDTdABAhDdVSkZ?>s2nat-fRh53)rJ~t4XE)S&9fwX?=JCi3pnZU9A#SE^U_2B`Q zDj{>HX3th-tPQp7TR)rRnw)6}S5jVs`DvNLSzc~1Dl;o}Zll-MF{u2#^7<_Xh3JX7 zAhl|nw0G5JVrcQ>VF%~W+1G(UZiMO{nPP7{i+#m-(NxiC*aug0KJY)w$E1Xwubrhh|pp@Q$@BVx~SVVE3qerng2h`l}FrX<2KEe+c2x zGQ!omVg;ScW-t!Dm!l627}s+O@?U?14l-w0sR(!zk@I(5$?nrtToEU&&N618Z zBb5woOS`=sM~ZpWDk@~;4+tr#%j9dZ4<@~|-*S07gCZLPH5MM8N#&S?8j~Mv^;ImW zf%u+H&Kw-ul5U-{Tt2|N!}78k2|;gF;$1wKvp6=F;)d0d>^rt^2J+JY-Af#}3n2v@ z#EI1O?1yMZ$;^9|ip6CEn0)zs>)Qn%FBx|F=!EYP4=$WSzzv_<+PvG^Euq3aKTog3 zRDjx|2LJ(}fxS!)kQ&Q|@MUfyfquIPxfQRBnm=y~H;-4mMU4yET37`N>dI|f#QGc%E zNF2m4|8gsR)lYlQXc?tI{#+J-&E27R01`ZBAE!O}DV+XvEQN{P9wRQ>Of)s|8o`{6 zqr`gh1P26z-<^fw4UUZ;EEFQqb~pK(+x7>X(}6Kw;_a0Ne4{S(9X;@f#*&Xw%b8l> z55Y;l&q_xYpAWbJry=Y4^yPWv2?~BKcb)xJQ5OA@8$NKfVT+k3t&^=jrtgm|g#O9ORV^qM(-srgfm* z6wf2eRFeP>I&x&g#L0(=E_;C0=tOo5`+S=TCuK7fEwmTQE|lnS#4|};f94VL;-(hw zyl2z#o!$Ws*d$*kS(JBxv07ehvSxrVA9Ijo$ArP2tk?VWqlpNFqU<^Ju@2+CxIvnz zGv>5A_M}|m9M|QX^#~A_haaO5O@>=BWxPhEu>Aa4%y@oYTQ$2>w)hyn?e>Q%hnQE^ zUu)}q3lsz@te14gB=Fw!hJwCw$LE|~{}X-T+Kx+!>zUbWK!WhTGr-*+p0gg)66(FE zZx-N$=hZpmlvjqEfyDphJbWMdx14Gs$A~q>h|zDT?!&_+;=UZ?ZQ8$of%8p^`q* zXbM8Ds`&VsGZ>jnBY5?GhGzc5xVKD;K*@BVhXJvtB|n_xCq$yZK5+@-@K?WVlQMqN zM1LsPf;rhC0Cs8AfQfq%QCK@B!_OUE?X@!Uf7X?Wt!p2FTeNN)&+#kV&@v7<-Dt)g?l$emUY!?%l40Zm^cZ%^H+fS=Kg!9X87TXW2kzgc#W$D=r(8m zZ65@z6L>uE!Yx?oDh~n+q(=|DR7LinMZ!5kb?k-`3)nHnu>5WIf1^G}+4U2v%iLWC zEbU&O6&ZQ$Y&+cI@rlMK^xH?fLe=1dE@1cyD+~W@Iq!C@blTou6~5Tz6*N_| z`<+-0%uPE%>FyX0@D5HN|5?TNXH-4e2jh=f88T?)W$67Rd+Y<-V!1jIAY`GDtGco2 zwMT!|RhD^~qTDts!otOg7KH;Cp}~8d39ddjlEZO9w}b3kA^>WK%W6>pu7sUOCn>pU zDDIXC9r=>u-&R-ju6_;kLLZyx8C$K)HVkK=E{jw>b(JVdJWE>??>=QXd#i2cNmOBR z5NH29EQC6;jF1eVKmxZL#2tl=>MJQ@GGFZUsnXujf|2z~n1CpaF7^VPNZARBb$#{% zq)o8;8@dUc<^s@7lc%k>?PW8Qwwt)(9JsAyWiP_ZkRe|GQ>W3 zv@MHtOZ<_UB9mU7xsOR0?Y$;YhI#qlw%;pym)(wM#u z%2dp$;b!KOF+os(gxpq=(vQSz?%TT3T2P249oMt`zfvrw=80&zw?g4D0AFLaQnm}B z2CyUswv(qqYIWf_+VQSZ{qto1um~r|OaiiaIt|?Hua=2L_h9qb(G=IgJgTH#YdbxG zLP^)MHx$=y^hZwvq>%1Nah9kfClcv6p0gVRw03Y{@+D=;T}uK5DtwueBTkLG|HPsw zUyT(0ADd`c9IeeJBsassbwR?RH(8yRBEN$DfRAu8S|yhzmWa0(%-i|@arM!(j|}clY7$?phoQw0(O&zdzpld6Fhg)AmZPra9+) zKN?6lUL}qrw!9l5tX^i$&82Jo5t+L^l0Z>Hb&UK%TV)pLl?H#Zxs9SVKT3Yv8oe5t zd+_I%?glmd(S^s{@*nkDI`nyAE=v0!AHBi)aul{^InKB}G*~oLxI#4_v-~_@^GDKn zHv|q|Sz9t!UpJLJDmTPj4LIuNaa*s0Ef5B=m`8=@bk8z@H3uq2MOpU+s1uT&wwg7g}b}sl-of;ogxR$7tmz37)(9pyrPQ_#@h3 z$%>MFwh1@J=jaK2w`2)GI(j0-QeXwkY??&I66NEJ6{7sUbRFmU)w+hiVDk-S!E&^vKn%4Q<(ixh5-*6; z%Snibwzf9;W@d35W9lekaqmdKdcQ%r*Ppn8?Tf(d)AEHvXg6 zwMNM&xI#{0iM@H)52!wV55^9vS&{j;C4nPw8w#hZ=i?wtiW1q?KyP5yXyypm65IL( z&8D*_pSdZR3jR=uX;Y~v_qEzTG7cZjDb6mk3$!h*9P)wF)KSX?YKBT4Hk=%eE`fQz zd7W;3e8Pr(*IF9f1nnAm&>lCJ(8r-nstesJnVM7@4R=2Xyi!^zYHCfewz`c8*8qKK z(Sp2nu=-hXy>~UkXQl*U-(W{Tiz6xjQydAI#n+2Lg9eh|0GLM{m2ioVuX(1HJhrRX`ngA?u~_6rfdBD*AR3# zg0FixmX?6L&=n7P!ZGahy^IYs5%t`kmCIda8)wnb#tq!u&;7n~cZ7pYM_e7`G5UghbVUi;vjOjgP1Ghs2(e>x&|c7z7cbb6)D z@UU~@=Q8irJZ|E)%_T6!(5HW(ut;D6O=^nW#^;4rLyCJ>x~~nLO>FEDP0;5mDYa~+vU-cVSH8er)L8NwRXdr5FVs?P-Ua{wb?q3HdKXaf3Y5jCGQ0JD!(5!xQ z_sx4~rY7Nr;^0KC*vtw7R2Qq>4)&->EB>2_t2=oJSn}X?Dqpf@gNkQ~h$Xyi*sHq@ zTYY?gFU9N2bZ{RnaWyLW;B}EAY-a6ao?unLEwZ@aFlaG89=*2{c{<6~A5!Cb-nKZM za?xeb`_Z;@pjcR_$jg8I5tgYMq$_mv_8HnMv;s^JBn*vxj(@mv*NL3$n`XKAsL%Npe^z+#W({cc2;mnJg!FyFizPNDb6&h;+=BD$~Xgu2(0jkX!n8$GrL|W zpkgSX(bE^B?pTF!XeYNC@#nkwClo>A;+)zG zk;dgF^`?SY=L!QLr6ZFMwxCcTquAVe2G_pFSDuErIE0;Gldu2?*2SM$pwHLzEazeS z(dKQnZH0e?vmmH&_EIx>O3w0c5eKyPjHuopgRWz8D%a7Y_Vm*IGoI6<5=R6F`y z5DO-Yu^nKZz_^2NBrabNiWXzV=kM-*hYhZetWCp`J7|wqqTal{hBj5M)#s5gpGvo? zox4;bg2bZ?z!lJAJ8xLPVtB)h4QFSw3;g8=k`{fgJOYZ=%zq4A9l1V{bXT3(Cn}J6 z!3Buo*1qvoj7l2;Ru`=BCU!0=>k;2|4r}Yjb~$(xbV@ha)XT)s6Fmq7vyhmZO-9!240*!6gj`UqyshUZgC*rD+jr^$w zWbf(_C=hx31}&3R*3CZ!a_Iv>wBMHtu=@l*4%Yoe^$29^=R@$!; zRrZ$~PJjl#`-ceTHc<{F%X|JTQFYxUu#p zxt;%tYlF*J=oh=^(c(*onYiz?fADZ)-CIG+Fvdt(lh7cV3y;>F4L`bGELF&ky!SuPx0Pv?o(hybU-B;_(kv zS&8GhBUEiV4HsHRhMwFuO-SNlDWMTh`C#n_dOFW;&|6}w>p1Uop)fK5LZX{DJv$LX zo{IcTsqSq$5%0C?y9$;BDwm((f8^z7k=&=<1qU@tsU3g(=%k^o^tN%MR5G>HddD^p zLizhN*eh~;d?QkUmhNluYiOWcS7c%xXISjRR$wJ!d4$LPgd-de^nwh9BzM=kaOd!+ z?GD}c@sh>V{ASx@rt4&Bcen-Gp9jS#Ju1I{7kXn*58`XZa(5!baPa9q___OemMd(Y zM0WxGVd3g=MD;g(0tS>nfpm2r1SW>iZbSm@uSApI!iqjr zolyC<;%{z;DY%g*`p7`C^cZM(yI>~Q?2&q6D6;V-5ZM%z*tj#N zM9pMsyPr0Wqn)LHD8C!(8R`gsCW?R&j_tFYD2z10;MylKm9o0OT-3aacha^meIOIw z(XKAX&gajJ=*R0;+F0x&6yc^=3d-FEzIvXqSR+usnkn%HglKWe)g>xHUPeTG<62EV z|ID@l`}r|7Z2gK?{yx7xsd{eyuy0GhrrO{7Duv74ba~WL&68edcZeQfE=b_w*UU|f zVuA4F66CltVx^HRheq(5t-NgXJMme>fcOcZKD4EsCajt+>|=zQEW?mpLA*;NsdvvK zB^;vemp>4yAcsGh8&pf~JEr&@88X6+jl!RIJle2Cd{%O{!RKW zm0D+T!w706#ou~0A`Yjz~Sbo%pBH=5!3wWDXH*$J1O2t&{U zuh1%Cfbe3OX&r!>p*N@fvQ(2w`o-jAj4Hzq_~S%T@CjVdatN3{?2s0gPTomQuim=E)yX9J0xD5}D0? zj_}on#xbA`A#z|$kznee$d~yjSgYr#`dH}rCTrTlDKFO_K-Kuk>$8G4W;B;K$tFv|sre%(#j9+VjZu1Mu=L`B>!5dJC1vC&n@C36k0Q$enLh6O=7% zJRz=m2^ohmLjzYT{B08Gs*~ zeNTC5!v=^oc;#pVv^|xUHNCfcwCW!XMtC6^WBg(?Uflt)Kq?+=Ss^ww zDYHh&L(T%7=Hbbk{~`)Cj9k=|*3~2@X$A}&x}>D(jsCfFFdKISBomU%Ry&iU>X9)n*%y@#@|W$I)%c0Y`Qcej5l+hzY)&={T7T!Xp^Yb(aPvY*`^Ndj zs39Cpo->)+dAzWO!_U|yCF16Ybb@g&o(`MEGjjcM zw@wS1B7JlHoTJs)rkFlHd0|Uo`4B<&&!yvt6x_U657QR^x%A(1VrtpFa$m!b^vuZz ztun=iPRP8#Awqvl1yata+8vl^IY#Zr+zfj~K{b_&ta28=E>I8>uKc~+F`dfh{bJNj+N3+VQfDSBBa>fU9luzim6DT#+51~ErgcA_ z|DSPZt&=cUi+48+7X=fu2>S6Vy_S00WoGEz3}6dW3k&CM2fS7d zae4iV)(G4BpYcYlWqcFyrx?KH{+-IBi>$Z-CSK9N3iVoGt5d1D{4T^M_OC{GvLGK6r@#d4j2pN0`AD zcB|v6v4w4iZX?dCa5|8iv4dOmro|6jRffYW)+H*b>57JzHZWg_1PkMDXS`|ct=EzslY%cI z!Nlu)hn9?yr|m1w@6&6{h^7eO20S1&jZOBx-mUr>QJ?1hN~#dNZ!3uU#levDWEgP& zOTA5b{E=>;E}fpp$rCoI;maiXGU<@W7cV1Hxv@_n(DCe(y3BVmd+0;NJLQgMxge-L zcWpBul__p8_cEqIBS!yx*g`c_Ls%pu?61DG*NGc5N|P!{in3)7nH_O!Qd(VJN2{w4!0taqB!O`vKO5}k(gKjOVo&}WfR_~dTKHgX6f|Ywsba8a&soF3 zP|)6*dX~(t?*SO3WytxkZOkExT1TC2Jj}fk>!<>Q25p$>J+*@Yslc}%*!fVXJ@Yv0 z`2gaQ8LqF9?x(sUG>(@Od&&~oJY!F)O&+2@aea~wZ)?k7(xue;oAEq@`lZvGmyrS- zLsX+6S>)IW(3Q7;yXm#DL9@-^bNo~w?$cejN!jt>r>UPqh`A)7MaO`m7UHCxs|BOU?%Ca`@s z1=*lc$>+>CX*n)G!3-`j5nN@-2PW{&YnPElxHi8V1P3t4ZoDrtW zue(OAEvqo?VS^*mjd{~{UXH@Hd+!2t>wY}&&lB=fw~bk3sl1BZ^40?6Ph5pgbg`O2 zS=qey)Wl8E>B2zFj`<<7^qhWIPs7nd$AA%kmcXIV<(#3F0(xoRUl0R!qOka|#P=$# zTO<-j-jUovTM%{>;sv06)@vxxx%6)YXxpo$>j~WvMG$zg<&E*|MJHUBW?|||ueua0 zTI>KMG0@9s0SVZ!|JpMin%q(Wk3yU`rif4Kec_KReDgcIcQ-V*BdV}(A|?uHeIZZs z7i#LDGfaNspVHW;^FzTc7u6-({f91hd!fs&~U>ep~kYOCckJ#*Dgb;;IV10Y?^!0fR7)yQ-;ou!#~xToc+ z&%u-3!z)n8_b_0ukYxLO_3T35XGEYIWRDM%(D}x8-h5%Xp8ItwlP$OH9Lt;>44!?{(w`28^wwKFtj`o5MuCj!PtO%2Df^G2#-xnu0|ded{| z(!+8xbI2FaB`qPb|4W~l;Azv7f~E5s4hGP9hxN4Kid|P%N47SyEA)0f5OLi$`~6^u z!02F3o<;H@0Wb`H-p6L{em1?mz142~{{EjYLSDBad|gKW-cG7<{@aOJuuf(pj2y*} zw)&@Y^P~62ms*7gI7Dn$rsZpdq0}TvA>mtOD~_(^VH(+d**p|Kc#*YWCWEcwzsqsa z!yiQyztMa{ZiM-zmg)Fmd`!mv(XD7Jl(sjVv&I#f{%7SwL1@u$MQTH};ph9ijGh+) z81OTQe^`k>JPo}^y5E=8e|vO(_Ozqq8!PyYy&h_)whb1RP5(*eoC~$#czPfvaWI(& z;EF7@z#hDvN%wECLuZsmesd=8e80%}&LLVfE#O`=Jqn@jc(3m*YK}&n+HzfD(8zxA z$8#8vwBpswVSA`PDj44W8M`sbPm&%hCcB>L!Q?)z+uWZZNdK@eur@9~sp*&W(hlzV zcgL|gwn-gEy7Md;_8wG`;zX1jeaRa>ire((_k0CN2BSSah~PYGZu1H3onC2CLfmu0 z8wI5Si4T)MjA1&o(L_))a>y5PDrAy?@R%v8MYRVtc~m+)&Fz7fLMz!45*ZF;=M?pWOF zgvE);$;pkbXUSQ=h=!!>opQJfh~BUjV9Wch~ zB_x%RQ4{FyvxJTKiUPSn@#ffs`Y zWos1rgr{oOM>dmF2q*F`c3r^-hEr#cvg|(Up9@)W29&l6&SC+Hhb12=o4j%kJ`;^L z{j-}~2V(3=!C7|**3w9s-q3{;qm3Ra@A2Rd39pTVWIkqD$ap30VltQA3`sJP>yN5_ zqO6N0!=U|XtT1_r7S#Tik6p_=rH&^iI##YRfOt-8!`$_D9J2UUYaw!>3`h@j;g8w~yuxmS6^~%Jmq>#2?nn6Q-k; zNu};x0%ke{JeNxU>^tX2HDc!#$FZ+dMUd1!Nc3`>ICVl~8U>5lr4}O*t367|hVuux zhZ|1o*csmg2ZH3^H#3DM>bNW23@P`Q;nbLdE^0{Wx(W5ja3`bY8exw^HO58_R*9p8sF)CN(6I|YQwP6iT(B7y6e!<2@jv{Hu`Hs;#u$A6tGEz|MW87+a353&uAkZov=7tDe!xGEL5a5x#0%hp2|NZvEGPn zIAAkEwxmp)c?Do{U;sn&bcXe2hjnhhuiDdUIH7h7rt-6%L*pD zsv93ga*i-WN8t!D=K~EaFs+f0Z<}*AbkITTEwY;4sVZ@Btgjla{kY|Oq%@r8j}EiV z^p@h8*LEI-iipK)|DvswCDgoFHzXN(GmfmxvDaw3TE`vA5}-ePhpivkGq&6jLW5ra z!8`pMQhxK|Wz(=j3x`QRLI4o5a-jzykBcK z)8gXdhWBv}OzEP{&o4UtC$oiF2A+RY>Ax7XrC~|Lx83w*7EYbXb zDSv-Y%>UGlZ#pc`4IdW17nxp#jexm^NGC<08s+XFIhc|w=~tRC&W5p<$5j2eOuLc% z7_q>SH10UC@9b>+q={90Nkv0((p=701;Q(K_#!Ea+oYB>*JbUYQz|@$-Y; zh3%cj0SjAF%V1QMN*wcs=o|1bEKeg`sPQn-K~E07-g(7dV({tmo~u1(?SRrwj?+ZF zylZ5HTti)VJ3jX%IK$r&v5<|QWNmhGpsG~ys!;F(%bDNY9C9N4LJ-_~elR#u{Sh3( zz95DD&6>DbfN(6+){N*yMkrX^_oISyY&|~X>Wv%EA-~(8k&4vZVbSRNbBs8Q>Iti9 zVYG{j)2@UpfE4D6qc-GVd0DNEFZJ!|CD9r38P4(mCjc0*(C02)dG0()LcDMp&KJ!{ zil@a>hj->&g)NmAsNGSw5z1FOMIwXU^c%I|H`Wbvg}D7B(gICO?8Hdq?w6&cw_#$9 zfOx7YEg}tVzq!OSk}oN3ADBcpJ@iU%s4_@ar^I12eDx>Vfj*7hLeiDTl?~hx6C_}k zfy;ZLz_JIvSV~JVwLLbZtQ$HJ>dE%*F53Fiv?-XjzZxs8Se(8O8yQx>Kay+q1Hv??nbgVz`5-Rg`RIcBC1A z2P%KPzhZv#(kF*vTZwhlF&jO1Nn_>`v8ZO(hwvyA@1yls32DcM`00~{m743L2rW%{ zzS!j|Q6hZ}+gm<8UpE9^P$4^_7sCe9dYCrTLk09JZb40VT1j10DZQm1mAY)P;ES=O z3itwYrKx32Ax0fKk5hn!R4oplDX-zloLJow-Zk-a&Bryq0G}fgtjg`_g$gV7qij@2 zxf3W*9`LqxKu$;Qz3-b*>lG+w23oEE)b#{+A|k0xA;z&(P+l=y_F&Hg%DX&H(6!{u z*fC!UqwE9&Kgltcv%Zp8&j&Ulk{O@P-@EO+)ict{&CaZ*EYG`_5#bpY`Uw7NzQ}QDnNjqm zfnSj(AoZ=`yC2g&6fGkRR?wm!Ta2vqOIYc&CxPwHjxz#RcmPN-kM7&2dJ>Iq%X==I z0glI37j0v6NRK}px%>h~gHm~E%WD#@|Psx9#WJ@ZDB@+r-B=PvFU!q=;Gjj&E zU?-{(^l*(?*I>Z!d|a8t$lUeM>-HJIdMvR@NuGK6^NvN>&n)HI+jSpd=DUV~=XMj5 zgYCv>utYd=N{W$!dt93T=_*t6Y)hnE(Lp~)NrM@nV_}u-t;yNS%*p@wb!*kI?^R&X zH)jjGm$9aEj@mCEN`ZDC%57Nf568jSt<)B*KCJCSk)c2J^*BK!4y^@4(2f`X*T+NX zk^eBqbE}}TGFCF?1Do&Tg%ZH%UjYFHjPZFrC;w&38bOpMyU;r{c*G3pEmVom=py@# zJZpFE!d|!0HzY7F4dXYC)6a@4`8^@N%qu5&0ecdo{ZDN2-u$!cEH?Cq)w{bo++7xu zcKrS-B9ky84n6ow^$c6$rPYvdN`=7T(lZMNtzVjgGV@N-{W$9_v>S{$634POfUq9K^D2--a@o*#2e zs|axyx$w*T(=2qyR>D}|6XiWg3#RH4RHu2!<0sQ;rsG~@(F-5S*a=5?nYQw<9cRu_ z^PT#?^xCKLTc)`9{P&;l9r|gtaM=oBAi>QJ)^O9~E0MZ|1Ec|VoYQ~JcSz2AxtByY zc=21w*cm)dK5u@{H!lqClnnTo!b-F3J#a#0dvk7O%hBl9=(Um9GAgk~XL(^E_er^o z`eu*4Q8Z5Rcv#~9=#G6T-N6{0dLHv5NBySeyPuPlFBgHPArNyf}~gzMh*)Jdj-aTNPX#xyEX=$RMPpp7FzhfkvYoCexfMO>8JyKob+$aAfyd zO!rbu#VGDn!v?CLGkZ%@z< z`RskLYgW-3KU^EBkt<9$bU}ZmHWgT~xtjN_+8jaaSd1v+XMkA@lW#R7Tv zc^*=GqiL>@+)W)bafn=}wT3ElYxV3d9+iU=x3uu)d!_#ur9WMvTQo+vZh~*`4IVF9 z}GDiX~l=Nn=pKK{bTq_yI z7)-~qdJ>zMLI>IWf4xrNBS>T>Jl3`wNCpsX3*8cZ8~QNiy9aHSDXPG5 zX*2M`vK2`mGsnpKFb$w^7*^Ab8QXZyt&@g7DcC|?dqaCt$64pW-D?kQ%*%7I<%8W# zodtOxpIdw}YzReHCfh!Ev!t24L2~?usc<}d!RLurAl!?@Ea?gIz%13^K%uag06t7r)$0}%fg+$VuMX3g~^+##X`R#v>XhaDGjA0qQq z?%bZ^UeW6IV?-h4)Vp1K+#lo5h?PUE5AKfN!P=DG`De!dGk!HKha1U=GFx27LEVX7 zmi`^y6fly$kBTB> zf%FUlMO;XEfm;9ohb!6|M!uG=&9m=0xkrhms-|^8@lwRd{Iigyk&nl~ZS$t}7L3m+ z^Qh6j;4B>}j@5h`jE|q6z(541t$R*^cqG>sD+>#EAEO=!*mvM|qs?{QJ)=y$jF_TbGf{Vw9wAX{s zIZk%8$gVH%-X~$9LGC5b2A$9Q=oVBOXVT9wFuQMZ97U0Tx%?#!cz$DoPP!KxRhT8p zg05Ub=$8jf_vg(p?MoM*&NR?snj{vixGgmNbp3 zE5vkBt5Z)Hp`>zZO%r`O#^oy@4sZ4qhXH21qQuFHZH2~3Z;BTDWKF0wB{wOWexO-M zW1!zWu$P_&uO{42PeK=dxJX^Lgi4z4=1ecwQ``fd1hOH&h5cngy$bg65w-N+s0|E5 zD9eF$Wr_|`0_oyszM>bt9AV`eOz>BqFCMpF>v}EH8jc@~Z$ALv^OZ$|J@I~XHG{o? zB{E2f!+bDuV`qynFO=*>5;Ho;s66xuziamCUuc8pj0#aZo?(tS>Juw6A)7?{KD5X2 zW@=a3>J}>NlUNGT5ksm5&72tAQ z;W;leF&E@OaF2p6<(Tfj@ZC%CB~|c&*2u7|$sySG+%E2^@hWdb61;k!`F;&Va|??V zsN~{WlGY!h9Q z=WbxAWt-UjJX07`;qYXk9w`X|pVUQil8@{fB!|awYql}a3G$G>L8VL?%_*-g;PNY97aq$6J zhY{7WR*rsA=*QC{Kd1fEQ|n@{G%ECHVGL?=0&I-O9UMF(!=FjUq$33oPOf&bp;HnUF-(td)fn*mad7lYtF&5j7IsAu=qN%L99IK?YK3yPmfPLWiGObUKN$!C4^p^T zQnIqvYqL{Q=1=|6|0Ni8OZ#6K!)7^o_^|aoQ_Zsa?W0##OkreW_m-l*2=VF#Whh!X zFwCeez9DJ83;BiD_Q1}Y6|QP^DE}2Lajb8fbRtK&d(8F8P`;@sBqUoQ7r6Zm;g`6~ z3I97Ibr^^An6q*;7j|qFwZ!$kM+oF(vfeH*V5&Q;$Q^}!jT+WDBzT+`8Jx8FazpOU9YdLv=6X=fN5z3;-EX^ap#y{h zE&}UIkX5HlwF1k%SdPyrIxCQFBI&fwf!*bwg9a*6k2SPd;2r7y@Js%WhSt|R%ga*V z+9TFNw*n(R^ZPq8pEWzZ3G-gM;~iVD9S!md)`N2YaCSsxTT{9e59vL-iO7#hIezp9 zoKs#nkIzK%6R*v}N9wL;W8`JxJ65Jw2+#xO4|9$6$1r1>`41+tU+wj~Ec7(bd87pddMh9!o$74BeRup+fZ zd`oF*`_T+diuJD*;qVESo+(oxatgRtCdAU}o!hYJ1>#GD6O@`wU>bU$t3kA$wx+#vA)3y|FY16^!wH+5)+ z&#myMIF-VYI@HCa(Mx4S7whs zKk8DVr zU4pad!jcHa1#jZuQIoC?u6B8;?r<5i5)y#fgwJ_Tv<=No6VAI%9VI8TRlaT&v@`0= zNTXmLK6HW#eo_eCm$dQh5fbC2ld0=~=?`DL@3c%K2VIv!3G(j*eWtC&xX+4!Z39s_TtFs`<#$)D$e;ClVPy9!W%Hq9LdE=PH|wrM=@MdNEjQs%=)ldcWTVk@M&W z18aA6R)7Vb^%2kNqKj|Gicr1JKkAd+zYmxt2HZ%w{D^*fW9cvFCRZwe9*Z)k!r1lgElIW(=&rcF`|=p8>b>HsFTLz| z%16e`*Xf@ECn+8F^-Fqc6L~cNcz)>MkyF)y#cF?*qoKVfj7q+fqmge+mb%n4jQpoJ zXnc3Nhp#awkUc}ezPeD2Qz?Jf&EtwcD>IY0yn>|W?iJ9py=$+bq2Xq;{ja4FWpj7? zi9qdNgdxIi=~`1`fGAR(V0xCV>J-)tao>iNNhKOhg0mo$BgEHm4hnsnvQesX{Ca_v zOyX$VAU3wr(x5^_JkW^hk92#mzI}Ujhh6VGz73O_{z0|7{V?=U0c|0o#c|o=IP%w7LikmXt?tFzz`)@q| z?@tk^=vd?;w_Yd-fcdKROM7Cv9H%|!X@-X{-k{?{; zgMROCZW#v|2t#6H!US~jB)rkbiin!pu1PCJp$gac*z1+TmwbM3imGO^X~_B2;qgv@ zF0}LMB^mhabib{E<9tc(7uhI88Qxc9rFO+bdlXMI@0QqPLZXA$k{#|mPN=e$UI#3c zsf;aT-jq1nA7G86|8yH6IEt4a=KvPD>az9hg@0HF1V7%1`$gGnYo57(^4mg^_P@*0 z-TndN12WprwEdj#=L-W110yRTsv)BF>}ABb`5(z5H&_1p-MUcXTjGMz+-#P+MDDvS z+<`N;a66Gu;Q(q69}?z{7|y#TXbfzgY6}Jxuu;P9kn6)%W9+wt>fJ#Cy21t0F5!;c z30ANvi&1SRKTp+U{&k&#**((Cf`1J&db7YpATpzN#TOJw5n6y-_n za%^CERjJ7Uw(aWM-8PiuLsFvni+Zd`%{sTSXAy7F)`4CBJZVHPkT}wNDxTr8h~Wnx zXK!@PbKudg{dQDi2eOARv`jEt$klW5usi+8_319}Zi37;gExRx$Oluo=Z*@y>k%_yg9kaMcz>G> zRZyn-n(OC?LS*Go?Jsk$z%G! zpXXOW>F1y_&_Xa!i4}0kDM;k8iAoTF*mD6JIX|hhEHn`>N%4*Zf34|!9!Kxg#N@6^ zrH*3513>TxEc=e{F9{d+1#$!{A7{+A>O0)`VlSeA!QZ}E<_{|Y=9_N56J3X6P+>z& zLT<$re+E&CR5B@nWbG<;j%KL-6-dnau-#sP7vcdUpthc3=;0Q->7IjCvTVK9lqd_KS= zjKK46*>0>nmyq;)KMl!!_U9Ziwe}YadUR?stB3p7G8mTo>Azh@Vl8!eqK{kvm+v?y z>&!_f9;@q=HXkq1$}>@SRI87%4143U4(&chvm&KzFqz4MSfi5TkfbKY?YU}+@QC}M zUSf%}tEx()wqO4IT&kLCGWPEHXyI@ag%kxzY=d-9Ry(84_ay9S;lEF{e4sjOtF(}S zF;E+DqUjAhIievEpe$>`oJ{@x9bSLXt{Lx5EP7O|y`Wza_7l>sjqA6n>gD99j1O}{ z=+yh;B1oHhGiCOq?B){^8VsCDC7uf6rp%V}T}iP%Y*{ z7*f#hoE-Vvy~FUU+Rl-;7R@XE8PaF-r2I@TF?>IzLt$M5KH8OE->ok6bnJZDLohw1 zXOGuRO{dFv4C6V3LaJoO9!mzwR?4VM9Eg6Tr+JLr33F1(wLJyK&SNfR$`pI zEt!XAk=re30P*^WDY2f+^Wy8w&{Ct14iWnvQ{5nijU@K!aQii8C+C59KL_qF_9u9^ zq{Ts@R(u_jHs*}_n{KAUV=?3Ufz0D^*IWAOF=?}zf~9j+n}sfqk5@Op{ zyDWxtk{JU|hBZ%Z@8vQ$V)&EzkVi#GM$iS@DM8dl+oy=v4`x{rJ{t zPl=qNslSns-=DgYWfS6UQFhMZ+!TE51mqoz`nFl@O*gs<6V~>n;*!yS^`5^?an%#b z@rSyOd`vU^p-(^JP{*D9p&!NXha~}^_J=pMGx>W3I~;0_eAAEI3z0KM01Xtu>^k#X zbmp_sL+oUpl3f9H5H(WKlK%oTTS_-I`Vh#aJQ|%on{=v;PLYPK&NjHptvN-3w=X*a zsfYHsL{)}5`1@(wMQ~v5i5XP!kBMRX zsS}rjh2LL5qB4yXNwUFqI!OWAFq=Vhs_4lJRH6#;(N=)5bT4TR-mu2tt)5 zmYW@;Lsg%8gBU+P@bg@EaVL`V-+ z`nS%J^-RA-!Rdzk7=m`N(B@@O^ulnjH_)*5gYWb_vbcy5-~rVel8={sraRy912_n%E z>epT?v%7W%GDe|rHryPyprWJNIfKqJ2LiM>fhuW-23RDRvQ`f}G97t+P6va5hlhvH zudh!pJOa7RbO!&Tj6}c3|L;_6`BV>`iVL0I+Q(smzQ%KDmpv07liPA#y+VO7enWt; zcOsvexU~fD|CZQ0v>1o85E&sQyBM&E7G^rO2~xK~RFYq@?IHOP(Zlm$oqbID_WFSg zz8z7iE;s9n^fsX>sT~zYkOQ;Oo?E!47|Fq4X30?#aD08^$^B_+zuos38hs)0=6!hK z%lKEZ=r<&FD^V)%ukyZP?zvXo*c^q)ANF zCO#Oz5Z%F#0yia~3V^{}gDukrAKycZD;k07=^i0MnZNMDyq2<;BQZ+ZzgV@d5{ky)C0!^5c(;jUie$QD&sgEam6>a<0(6%OWmss9+4M z41in*sCxIMOc!bETa=hDG*zCz4EpNa?w<-ewuUJmHAW1kfA>e(+_a zZP|%e_nTPUE=&Zt`eH1r!?*G ztV5e#SPc#LJBQLpd|!PWc{V#PKt@$h%!~`=fuK7zEw~f*qNh55Lp5xdP|#KN)y5!8 zP63)-C&fDYnx{YePs?3rADQgMv9F`5YEy>U3-9_%l?=Mu^CR$|YKB$!cLoV)&8}Pz zU~hwE!LePwcolj2kw)1+V2__J<4rvOvhERzd^M`i1WObMDM2v4q>RlFE-ri{1Nv3a z{o36ahwZiyHd5&ecyVEqi|@pyKq~<3C^p~miMJvKs;zYeA`*Yfko(Y+JYuuQgGr++ z;DAk&WkWfZUR9B<{@{W3zHmSVh@|FGj+rBnDAE2w=xL`oEbp`Q2(=|whZ0}-eL;*# zttL-hLk0y&K<<=cDa4tC!0JQ&)w%F0XauWKNO#zfHRF9rf~b|iV+ix*u1o96^MEe+ z#S~GlDLKVaIHr#yfFM}mBUTKsF z2=Em=3|~YDd)ZSvPn0J=U`8hY_7ursU?aE)%l3?aahNg-#4HiE$yl^`1ya(*lZ{5A zgN;|)4JL%@asXrtLR%j%bEiKZ`prN(Xk%<^o=e{uzHLjs0m4~Y@7kulud30B*0_Hj z1G*DmjWVWlru~PZQ*-YHz_&4y;j45($l!ce)d^8g{}#*6j+&!N=k}2CiD_u75K4qT zHi$XoK5w@dZuA*nYXzaY-BWqMW;%Bc2<4y|5TOwU7+&vP7)*efOn&XgZ0Wh1Z@v|l zvN#JL#DKZbh0cQ5OFv&FG!RWfF}Sz;-3-9!sWp$!<8z*03t>=bn`Gr?V+>S-n>V=s z9V*n4AGj@YwQM97LIynWZkZnwv~=Mlx~}*f!I&vymds;83^qN6R;wbWVX=gl zOoKUkTaSqCGKc5Z-@mk6EaPw$l~0a0dSw3;niI8GI@ZH4RH~u|$vdLI1a+YCcjX8N z7|qlQcrV#42(jL-k}hq(SA-sz7HA2)(Lt;~ueHN!7- z-xms1czia2&@dcipba!)eY}?$5Ooch8ugIozy}(56xYXsJNPJ&ffY#pPC2*|wH}(5a2QbEIC;Z1u&w3y+rm3P1k&6hrAhCi~Y$C>~GP|1ai9t2Q#sbu2yLi%YUFP3eIi>5p})hPn5dzS`u8BAqiIp8If=z>bI? zb10Q+cmp;ZSw3+I5CyNT-ih(#}Q>oecq5f%JdyZM`-B!T$pVhnl$3km69G|N@>!$Bxp?mmIG*0f9l zg)-oGSm{E8JGaZ4{)QppegcIKARE+M`*Qj6HsUAi_l{^3ZxWnMpLj4Q=9i58t3Cx~ zr{zbBMxQqQ{Q1LlpfL`PcR+*Ql+OGo=3101MsyBLOYh_kfW8AW;rJ#j4i{T*e1UO5 zYJdCWL#N1G!XMNgJ&)HtN(7%L!JHmQ-y=tqZbnzCjViu(6*!YTk9MO8@jIMdKFbYX z+xP2_#js35`NBXF!HoD}c#5F`LtNSne!z2+;K$19zF;^nqioTX{)z?B!;!!|B+$Gw0t-=h;I?L;nd3sDGk)A%%;m zt`QtG?dNm@+KBelo}g{;Mt#F1ejVdY8*0M1e|hgS?;8e-LtA2HbZlT|p9{ztB1+rs z%{uL}{eC}n?JY%SZ^Yt}`ShPqZ+l<0`=Wle=Q_$J#-<&4`bWgDKmlKIHPUWKRd&mM)vtPN6_6bLit$01pZa8@nOzpakZM)TF~Kr zHeE$>gIks+9|Fr>d7>H<$*hz?gZb+Ms4UK1rP{>;nJl5@iM{ za-1A!eg`mW4eVx3PAD$x-${SeA&%&wUg`qoj%QJv$or$KqE|mJw^B3sOOYjKwboZt zTO>4O+Iweyx4a2yV3Nrn!3t66Dn~Fhp2EcV{-I|ydZD#jjuFl?9s05lu~z*uuVcRTr#g!+-XaOvyd#K-7+!TX@dp)kI8-`F#7b`&mCJDRMoD!iaX+LJOY{MIC*pE>g66DzyX|6_gE#67k5M{=}ZYh&|gOhnG-KxL{22Ihq<2 zgvK#pARiX&AJmkJ|86JfOwxWESb>j|vgodOpys+*#uPJiM&7mV4aTBeU8X(m6T-`c zxIns~rfGiJ)Q#;AyjE0PwE`*qsCZis0UhbptE(%eYlH!#Ol$rhn|`HgekscDvRg3N z>?L0A*h3F=2tPad=9mJq5-FPgoa)+&rlFoge)|naaK1&5YLnXv>A+^aA)-E2Fuj=_iMp}&JX>M%s>X;;zc_r$zp=?rIgpgXq5Fh{qjf^ z$hYIM_o_z*sQ8G*u2j;DT2@*&_@~8%rM5|dYVL;4#U=K zKd=QhURI-mzdlU2-z)y2#R4Y?srFlwwYi|pMpC2ku%!gy)hwWQFHk?VZpNNGE?kP` zlPKvm4b3RY!w9H|Vp17r>QO_T7s`Y?)dc_hhz-BkPXa-sWRKnuu!Ce-_2PlW#Z${9 z0c*dsYCi3IWQZv(78_N-k+h#&b91^b`Q%AbBeKQyG#U9R0*Px0bflEf4>B-#?#jtw zC_e9j%<`CD?7!WC6!yH4r;!1CTXl9{1LZ$hh#9!UcLJ>GPIrDG5P;v-YkQD>|F)aw z9ky5(2U+BNf;e?qQe<)t^}bNP_paJUyuf`8j>>p-u^fsm`>Y3!T^*H3P2}AH&+eDR zcAs8=S+(2L!a%`2GD3H+H`K=H-FrIjHPp((KuUJB{*vXnqGCn5ODM^SHRbaMC7&_i zK_%~8cOt!|-a8l{U4Hw` zy^^d`Cs@8Oyti=E^I1q$SJxTNA%VDxlzy~4Tp}irQP8Tj!~udaJz}ACjbmpsvh^q2 z6BpMz%px8}rbOha4R5Y>?)yIMw(Iw?DrQXfYiPw5be05}guX8$f z_Pfa%E?j~n1O&^~K*_aUeZHcsY&+G!=Wy!34{1D{bAu&L{(p=dup8ds-COehcD4}m z;c9cfHcFV;g$_Wj?QOC?r;+qL>t1YDV=RTLt#DNFu;470T*Py|7;RJ0vX*;=_!(>x0EXloRLGbESO^8G6 z@@R3DK=kw`AFj>KPWnS8flkUdA6xOZI8ZY|K`EVjV#|c+2wpM~v59j?$ch*h08Fq~ zrMZl*BH#Uk{tT=6__U{af-Tm-W^yc&jo9Ad*LXc7<;@soqabRSWgszB*L#XgzHfF0 zBE$|>Uw6?t^$nJVX}@&w+CBxwY)p&1_#?6%kH?`nR8z;3zw8yv3+1P5Rk@tZhzXc~ z1#Qg)co-*9-gJ?t3PH7(zDhSu^+5}cL!M><5qEJbaj#~imL!?XRP)SNO@xSOe4ZQM zF`*Vh?mPR@S;CDZW6!F}lK2^f8M*z&9u0E3i%nOUON$;zh{V(4^HT~2NxJ_< zImX%B_#H#PmpFj6>f!zOk(hdoy|$-|hzD1fA+_L=8AzRMEXUmP*>WKNAVMy?B{@B+ z2lqMC)$JxH?eA4xPPSr-H1GRiC&B*ZkIQ zgcuV8yZggiegjcvcmrydWP-uc&R^>;5PY}$-()Ang<*&cjQ*h4Z}-X56mUB=L3I?> zZq|K$&t*S*nw+jsJu=KsyeT%fy=^6^1XF85Pw2;FYP_tK6&$0v8L%}S-yn~4 z(0B9ER64DW4MxP*_7QhChA-PsBpRpT*_+i|54(@&?^(n|hRm_XCY9IQ`Nxhj*Y-fp ztat6q_L22y;tO2)8(*?Ffg>JUF0e*GY%lWcqmy8D%iQaayfBXMzyB1VlbHxA&r{i< zdH5^CdXI$$O>Y9VATW~YE6ioFC$-LmbNguflrrdwO$So)Q_$gPhuCq#vBCuq6m5Td z{@SOFwC3VyjzkJ&62)Qh>)Y~Ehn>@YyXq?rc-?vbdOM*5Uw9N}ogbx6yVr7hSwp4c zhc6Y*$}==jCOVk}5_L{)psR72d50&p{ckP5mQVLGJPmp_IqOA+M&l{Mbx1q|bJl$S zF5cVOHe~7$ySHubUy{R4Q8PDlgf1{hJXfYv?3SlvWay1sm2CsR)!IY6Ba+Nw0*(43 z47-o*(D3l_FaNu^A60EB?$>)tT3UlCUv=D0YWm%7CMA}g7pJC_pI=^-Xkxs4@cBHP zKvw{wM%vQy%Xi0Xj38d1kC~K`;^OiAUsmdK!~ab71x$SXzuV>{puaVe+2LgUG}>=K zlSf5yK)S!8MMp=_5~0Yup{&$PU4Q!iDcRF0%HvCmO2vA1(UtRdxw7G6mDu67ILX>t z;9&*|(E&Lj&?{LO#P4U?1aJ%7~s`+@jqW#N_V@KQWTkI1Uf7CXB(q6xl`?cxP zbQE~Frta+NE%|bB;UOo*wX06xQikQq3L8hqcI5l7?9EXt^f!NN<=k-`-BPsucuiPhLjd2A@LM&4a6>9 z67^2N#*Bl-luTQFc>`FdC`+`?(o}r>F~J;Px5xYESx(c#X;j-t3@7vUc>6AqWftX- zUs@JMyuVpQSn=$E;HxM5gy4!#h?rpV9i31!+ssB0ThzZ6w*ODLkhYW~a@5{E-4Hg#f1 z)9ZGTUXUhCH8diK|3gGIsf2|#W1iu49Z|iy)<|T0PFK;%`XM^Iy5loGHnD`frh6eMSsNBfP3BZYUEl+Tp zJR7!a{fjvs%Z$;VAA>Vfg^}dPx$^?&06ErAOph1cZwy;Nv}6Zhy_m0MwoF$jNHFV z-`D4mw6BV=pRb@eiVF`ltyMSq!k2hA`xd{U<40%Mt$QS4j5UXEO~G3`y8xATG6r5p z{QK3PWZsF!8M@*L6zr!9;{-X+o%;gxpzTX0^SK^kqWv!_{Xg%g?Z~Cjfr?_Eoyt(OlK58!V;Ayw6? zj;G#?e~l|#Szyy;`&vCK`L#uCW-X@`Hlh`LAT|=uu~|vEVwNkj97RjGztY7HpLvCR zZ9z7i_)$_f=c~bx3To`nv}R>sKyK5IoweHC=nAx6X^f92m$)0cJ)}t->;W)ZBfF^v z$ekv!eB$4~Qz`IXLQhW0Q6mDtm3Oii&|tr~>?cvt)s2cBj~~|}mx!StBlEwxaRP9W zjT-?74||z*7x(ven*COFR|Dj+7u^Vqxsw*v%Q`s+a{pyu`g@ z!Tk@T--yJL1VTI)Asz)u7eM2{7Zqriyb3{VQ$5bzyng?ak-PC z)T9ymrKr-oVyL3rBmm1<@fLM*_QJfR9!&-T%4QK7omb5 zaU6+{GL0os&y-XSKG)7p78w7ytMtktsNU5&EB8^!l~crv!-*vY{Bj zXT2W4{}7_7bmYN+%Ag`RGz&!ajusxRagS}Mm`=iZZ;T|0{lEAEW`qGe@Ofi&GrS0m zc(%G<`3Xk37hW(wiN5=Adi&{ybB7b&87Q$YTqAK_-LB=jw-bB%Lk_OFZIsbgBRji& z%_zZ-Du|d2(oqVX`|NJY34gmVC97(O)RSUac*1esHSZ7zrI3y892R|1c9(yy5=_;K ztwjerJsgLofhD4=hG_mfyE`Sp*lHbLp35w$HXXjcHfR2D*k;v%fN+CPS`$`KQWg`A z$Xf8+621sMdlDzRhVSJFKvN+jlz0Mcac~Y%o%%@~`=1DDd(F0CVvT7y<0S3q2Bo%k zH9Zv)O@UU+Rc#}oJf-bRw>VcOqP!B{?8|=_iW*>U`&(lOqSkvmi9BNSbnIBY7~Scc zTMSYgBN&IetOtxt7{nMec`F(d9I343%G*_Wj$?y0(Y~ob#5OBbAn|vox-duG(+L#b zYfjFRt-T!S3han{RE1kiB==BUuDN`#p!W+-e#6mwL^eRKPM+P0;Knd2oow;3Um*@= z$v`LK3x~pgL);UuzlK?MkM@}(DABF_Y$AnS^faXO^d~$MU+!6|2AblL<9W{q357#t(hL#Fw-#*4tfUe+8s=ceX!*tz0Wp|gDXklco3v)hYR*^ z)VF%Z2gbNsy2x|lrw_^Mqh?il5}pkJp>i{p*=!fr|lxb%%SbVrH9>np<~Ki{K?#u)&cHqQVQdGL9fv zA&zsI;AAdssjXCGbO{1P?rB_&x`hx=HBi@?^7-r3LvideoU@0HmlNl)@3Vk>%axDI z>39!-oLan>c|3V4>JblNDY4`I?u%g?8`_=VP=6{_P_i>{uIPJye~{L^?9DNZfKJBCR5XD&%FC04m+%Wjz93-Ie^fcYz7|L-f0<(4Es(dx-Lb|sZUcjddq zw(|j#gJ39(uGoH((!~N5%1swf!0B~74*&jozsP?c3z z4`JMO=)uiTB7*>cC#s6q=om#g7-33K6*ip1?IGxb#(QL07f1Bb|}9)3G}+jH84ei(%+TQjNf~RGZ<}5HlIeuo^w`;Oc~+4Q}#(QLi^UD_1vx!_`R{G3caC15$ z9u9N7#6w2Wi6J)8r*R^vZ&XNkv^)tEbx&N<3QXh=B(R#DKJA48-Z#7GNp2#HEDaGG zHv5Wr5B$r41_j2wOaZdqX%`c4qA_q1dA1pfH)H`2Fp6Wu4iABtW3ZjEqEipS_+X|e zG}FKEu(R3lx#m{{$n=Q2F0T|QY|)dUa}vA0^gHDT zH0`g*3l=u%+&g~L{90H3Z1F|McU@9Z78Qrzm9jZ;ob6jX-20daG?A!~S|y@uBdM5qtm z;rQi#PW|VHO%~Vbf^|8TcJ5s;qz1qrS$IP#^hU815WXUmVW=PQBA7Td*cN0p5@u$>{dU zF-cKwV^mH`x#iy&VY2CCaCPLb_c} zM+%Yw5q1)L!?X75&9p+TaW6bD=W4Voyxv~!C9+5`FdRpqCm@M^pY34~aXU{N*5!SC z_yMh9G?SwiPzPhRR8RCuyXHbIsQjE*ol{b0A{J2ZD3LoCN{lhXJ0fy%X!3q zDWMlR|2tKfN~F1MLjoH{F!@7FM`B&nE$csTBs;SBGQlT|ghPXXjMLW926o3rjMUekCgOK?+q{8~3k;zIc*AV6bLC z3By&Ni#9N{b;LVJoH}3e&Q|c!%}{DK4(x+kMBvR-w1E34%)Ym21BJ+w0YM_f6*vcGLW6M zUJ?7gmM;{TJ*jMR(qbYubL3nk{)riKWEVuOv0ySRPI35azb!r)6Cpf^6oank-S}MX z=kA@@)bjhXNoMm{5aSFfnElK>tePji33CPabdX#b?2qmZBlbdtRPm=h-P>d{8j&$BU22 z@KxT%wkfSfa6xzp<=$%rwCrd>RWZt<45OLO9(7|)O;lpq7|Zjau81L4DgCynt{V!j z!kn&np$oU-TInfKRgx8!bRB$~!Lq-zRKm}B*tvPHXEy&yv@{IkpU(yF57<(a8l8CF zx3m!*0-$s0E_#AwFNuA#2)eZBD zqWW~( zLFn>S8@ccYnmTSs?xwXtobn32FxUDtMoc^PpN(Z zb)ObMWUx|Eg`6%oT=x;!Rhtf?E32rKR#x`yI@GzP7o4s*j_*dXjv2l_Kho>BrUCRK zWo2byIXNVlK>x6?PvE=L;UG8+PN3ZJ0)qZjsc+CX*4^(r#nv0ZeZex)gpNnXX5KMh;r#q!nPK?;=v zvk-Zw)s7B7J3G_AzS!J!R6I^R_qC8K9Z�xcS}7Q%|0-6NBe87J)W0`t@w-hNDF{ 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%0Ab;08}LDOaz?Q@u9iRt?0kd7;i71ZmQ=$^Piq8 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

  • fun|_2e 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 diff --git a/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png b/doc/source/tutorials/delaunay-triangulation/figures/delaunay-triangulation2.png deleted file mode 100644 index 986a7e53f04a41fc2c90539141f4524485bfa730..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41620 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 diff --git a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py b/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py deleted file mode 100644 index 6715ff6f6..000000000 --- a/doc/source/tutorials/erdos_renyi/assets/erdos_renyi.py +++ /dev/null @@ -1,59 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt -import random - -# Set a random seed for reproducibility -random.seed(0) - -# Generate two Erdos Renyi graphs based on probability -g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) -g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) - -# Generate two Erdos Renyi graphs based on number of edges -g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) -g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) - -# Print out summaries of each graph -ig.summary(g1) -ig.summary(g2) -ig.summary(g3) -ig.summary(g4) - -# IGRAPH U--- 15 18 -- -# IGRAPH U--- 15 21 -- -# IGRAPH U--- 20 35 -- -# IGRAPH U--- 20 35 -- - - -fig, axs = plt.subplots(2, 2) -# Probability -ig.plot( - g1, - target=axs[0, 0], - layout="circle", - vertex_color="lightblue" -) -ig.plot( - g2, - target=axs[0, 1], - layout="circle", - vertex_color="lightblue" -) -axs[0, 0].set_ylabel('Probability') -# N edges -ig.plot( - g3, - target=axs[1, 0], - layout="circle", - vertex_color="lightblue", - vertex_size=0.15 -) -ig.plot( - g4, - target=axs[1, 1], - layout="circle", - vertex_color="lightblue", - vertex_size=0.15 -) -axs[1, 0].set_ylabel('N. edges') -plt.show() diff --git a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst b/doc/source/tutorials/erdos_renyi/erdos_renyi.rst deleted file mode 100644 index dc0349652..000000000 --- a/doc/source/tutorials/erdos_renyi/erdos_renyi.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-random: - -================= -Erdős-Rényi Graph -================= - -This example demonstrates how to generate `Erdős-Rényi Graphs `_ using :meth:`igraph.GraphBase.Erdos_Renyi`. There are two variants of graphs: - -- ``Erdos_Renyi(n, p)`` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. -- ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. - -We generate two graphs of each, so we can confirm that our graph generator is truly random. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - import random - - # Set a random seed for reproducibility - random.seed(0) - - # Generate two Erdos Renyi graphs based on probability - g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) - g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) - - # Generate two Erdos Renyi graphs based on number of edges - g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) - g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) - - # Print out summaries of each graph - ig.summary(g1) - ig.summary(g2) - ig.summary(g3) - ig.summary(g4) - - fig, axs = plt.subplots(2, 2) - # Probability - ig.plot( - g1, - target=axs[0, 0], - layout="circle", - vertex_color="lightblue" - ) - ig.plot( - g2, - target=axs[0, 1], - layout="circle", - vertex_color="lightblue" - ) - axs[0, 0].set_ylabel('Probability') - # N edges - ig.plot( - g3, - target=axs[1, 0], - layout="circle", - vertex_color="lightblue", - vertex_size=0.15 - ) - ig.plot( - g4, - target=axs[1, 1], - layout="circle", - vertex_color="lightblue", - vertex_size=0.15 - ) - axs[1, 0].set_ylabel('N. edges') - plt.show() - -The received output is: - -.. code-block:: - - IGRAPH U--- 15 18 -- - IGRAPH U--- 15 21 -- - IGRAPH U--- 20 35 -- - IGRAPH U--- 20 35 -- - -.. figure:: ./figures/erdos_renyi.png - :alt: The visual representation of a randomly generated Erdős-Rényi graph - :align: center - - Erdős-Rényi random graphs With probability ``p`` = 0.2 (top) and with number of edges ``m`` = 35 (bottom). - -.. note:: - - Even when using the same random seed, results can still differ depending on the machine the code is being run from. diff --git a/doc/source/tutorials/erdos_renyi/figures/erdos_renyi.png b/doc/source/tutorials/erdos_renyi/figures/erdos_renyi.png deleted file mode 100644 index da0fcbc7f895794be5efc296b10497b93fbd0eda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91293 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

    L>(P6~T@W7%OJ$G`=m*MmL@ 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 diff --git a/doc/source/tutorials/isomorphism/figures/isomorphism.png b/doc/source/tutorials/isomorphism/figures/isomorphism.png deleted file mode 100644 index d96f2d2d22500795b5a55060f186f106530a0886..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33861 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
  • pHIR53IAi*J;V6W35P~R} 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 in order to animate a ring graph sequentially being revealed. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Animate a directed ring graph - g = ig.Graph.Ring(10, directed=True) - - # Make 2D ring layout - layout = g.layout_circle() - - # Create canvas - fig, ax = plt.subplots() - ax.set_aspect(1) - - # Prepare interactive backend for autoupdate - plt.ion() - plt.show() - - # Animate, one vertex at a time - for frame in range(11): - # Remove plot elements from the previous frame - ax.clear() - - # Fix limits (unless you want a zoom-out effect) - ax.set_xlim(-1.5, 1.5) - ax.set_ylim(-1.5, 1.5) - - # Plot subgraph - gd = g.subgraph(range(frame)) - ig.plot(gd, target=ax, layout=layout[:frame], vertex_color="yellow") - - # matplotlib animation infrastructure - fig.canvas.draw_idle() - fig.canvas.start_event_loop(0.5) - -The received output is: - -.. figure:: ./figures/ring_animation.gif - :alt: The visualisation of a animated ring graph - :align: center - - Sequentially Animated Ring Graph - - -.. note:: - - We use *igraph*'s :meth:`Graph.subgraph()` (see :meth:`igraph.GraphBase.induced_subgraph`) in order to obtain a section of the ring graph at a time for each frame. diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py b/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py deleted file mode 100644 index 47eff84f6..000000000 --- a/doc/source/tutorials/shortest_paths/assets/shortest_path_visualisation.py +++ /dev/null @@ -1,33 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -import igraph as ig -import matplotlib.pyplot as plt - -# Construct the graph -g = ig.Graph( - 6, - [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] -) -g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - -# Get a shortest path along edges -results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] - -# Plot graph -g.es['width'] = 0.5 -g.es[results[0]]['width'] = 2.5 - -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - layout='circle', - vertex_color='steelblue', - vertex_label=range(g.vcount()), - edge_width=g.es['width'], - edge_label=g.es["weight"], - edge_color='#666', - edge_align_label=True, - edge_background='white' -) diff --git a/doc/source/tutorials/shortest_paths/assets/shortest_paths.py b/doc/source/tutorials/shortest_paths/assets/shortest_paths.py deleted file mode 100644 index 9144c7881..000000000 --- a/doc/source/tutorials/shortest_paths/assets/shortest_paths.py +++ /dev/null @@ -1,34 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -# Find the shortest path on an unweighted graph -g = ig.Graph( - 6, - [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] -) - -# g.get_shortest_paths() returns a list of vertex ID paths -results = g.get_shortest_paths(1, to=4, output="vpath") # results = [[1, 0, 2, 4]] - -if len(results[0]) > 0: - # The distance is the number of vertices in the shortest path minus one. - print("Shortest distance is: ", len(results[0]) - 1) -else: - print("End node could not be reached!") - -# Find the shortest path on a weighted graph -g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - -# g.get_shortest_paths() returns a list of edge ID paths -results = g.get_shortest_paths(0, to=5, weights=g.es["weight"], output="epath") # results = [[1, 3, 5]] - -if len(results[0]) > 0: - # Add up the weights across all edges on the shortest path - distance = sum(g.es[e]["weight"] for e in results[0]) - print("Shortest weighted distance is: ", distance) -else: - print("End node could not be reached!") - -# Output: -# Shortest distance is: 3 -# Shortest weighted distance is: 8 diff --git a/doc/source/tutorials/shortest_paths/figures/shortest_paths.png b/doc/source/tutorials/shortest_paths/figures/shortest_paths.png deleted file mode 100644 index d6cd6a60d4e88dfa7eed414aec3f9c805b5dddee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29787 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 0: - # The distance is the number of vertices in the shortest path minus one. - print("Shortest distance is: ", len(results[0])-1) - else: - print("End node could not be reached!") - -If the edges have weights, we pass them in as an argument. Note that we specify the output format as ``"epath"``, in order to receive the path as an edge list. This is used to calculate the length of the path. - -.. code-block:: python - - # Find the shortest path on a weighted graph - g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - - # g.get_shortest_paths() returns a list of edge ID paths - results = g.get_shortest_paths( - 0, - to=5, - weights=g.es["weight"], - output="epath", - ) - # results = [[1, 3, 5]] - - if len(results[0]) > 0: - # Add up the weights across all edges on the shortest path - distance = 0 - for e in results[0]: - distance += g.es[e]["weight"] - print("Shortest weighted distance is: ", distance) - else: - print("End node could not be reached!") - -The output of these these two shortest paths are: - -.. code-block:: - - Shortest distance is: 3 - Shortest weighted distance is: 8 - -.. figure:: ./figures/shortest_paths.png - :alt: The visual representation of a weighted network for finding shortest paths - :align: center - - The graph `g` with the shortest path from vertex 0 to vertex 5 highlighted. - - -.. note:: - - - :meth:`igraph.GraphBase.get_shortest_paths` returns a list of lists becuase the `to` argument can also accept a list of vertex IDs. In that case, the shortest path to all each vertex is found and stored in the results array. - - If you're interested in finding *all* shortest paths, take a look at :meth:`igraph.GraphBase.get_all_shortest_paths`. - - -In case you are wondering how the visualization figure was done, here's the code: - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Construct the graph - g = ig.Graph( - 6, - [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)] - ) - g.es["weight"] = [2, 1, 5, 4, 7, 3, 2] - - # Get a shortest path along edges - results = g.get_shortest_paths( - 0, - to=5, - weights=g.es["weight"], - output="epath", - ) - # results = [[1, 3, 5]] - - # Plot graph - g.es['width'] = 0.5 - g.es[results[0]]['width'] = 2.5 - - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout='circle', - vertex_color='steelblue', - vertex_label=range(g.vcount()), - edge_width=g.es['width'], - edge_label=g.es["weight"], - edge_color='#666', - edge_align_label=True, - edge_background='white' - ) diff --git a/doc/source/tutorials/simplify/assets/simplify.py b/doc/source/tutorials/simplify/assets/simplify.py deleted file mode 100644 index 194b74995..000000000 --- a/doc/source/tutorials/simplify/assets/simplify.py +++ /dev/null @@ -1,44 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -# Generate graph with multiple edges and loops -g1 = ig.Graph([(0, 1), (1, 2), (2, 3), (3, 4), (4, 0), (0, 0), - (1, 4), (1, 4), (0, 2), (2, 4), (2, 4), (2, 4), (3, 3)]) - -# Generate simplified version of graph -g2 = g1.copy() -g2.simplify() - -# Choose a consistent visual style -visual_style = { - "vertex_color": "lightblue", - "vertex_size": 0.4, - "vertex_label": [0, 1, 2, 3, 4], -} - -# Make twin axes -fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) -# Plot graphs -ig.plot( - g1, - layout="circle", - target=axs[0], - **visual_style, -) -ig.plot( - g2, - layout="circle", - target=axs[1], - **visual_style, -) -# Draw rectangles around axes -axs[0].add_patch(plt.Rectangle( - (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[0].transAxes, - )) -axs[1].add_patch(plt.Rectangle( - (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[1].transAxes, - )) -# Set titles -axs[0].set_title('Multigraph...') -axs[1].set_title('...simplified') -plt.show() diff --git a/doc/source/tutorials/simplify/figures/simplify.png b/doc/source/tutorials/simplify/figures/simplify.png deleted file mode 100644 index 381e8debce3b957da82c5a6a8a790e3a05a327cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39750 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%0D9jFvcbrd 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

    T-kc`*R^_n;zWcB z95TCT&vNKoQ4KMEJVK5n6!kjjFam;N#2|x<`gZMhNA*YWq62EsQ zA!c=MV0!Id_k5!vv-g?dnAe-&tBIM@OgIz?`wMXelv^ut@(04(**tcasa)d*vA3HS zTMG&*m)9!CFmPzk|IIm|*MXH0Vgp68SifDvX2$BBGsCY@q#eLHiZ$ zJDOew!zhu?i{dx_Ir=o@g*J+UOA>dZSeNK(N^I;>x@>K2Lc*>@t0x)KM<*hAq953= z^i%e8zwTo)?ThOYaBZ`%)Agm};1^wW9OG9@h>I1zZg3bn7@+|ykRB?qA|%v-1l2}& zmyq)T#x!V~c^SrFEu_2;_cm@jo%G*N58uG%CNByCH9%jDw4@H?5=@k9W zx%!-2lI|ylrLIT+p!ovhjSJ8p-uOGpi#q!99;;(Zp)Vc?olf|q1Ldc7#M;g8pVIfi ziW&3+tqA)4d`w?)oQ=SzA{B%}!KF<`vSZ9G83EgIxR4|iB4;ug7y6qA`fcs!ds575 z_C0d-r!EHe?mr`A-OXi^DSCAC2}~J5x*Lv(LzI2{*1fji%Qj1U@Ny^|o^HzV;PpiT z5dsfUkRZ)7#reOwf$ zb>hosi|S67m^b&8Pb=Q*TOI3KdiUdtz?_oY#4fI``C$Gat)Zx^xr-%-%(}QwM;L4l zKWieaR~N*^s1>w%A+3MxqD1uKjWYfymCA;pX}=-K+2y^JJ>M7n&Nn1)){wo}p=ikF zvHR!wmcFHu4AzNje=FDd{rq|U;>e3!%iS?a=NX;8B#SY;+zYUC3l6>}L}Gb)iOJT{PXrk2=ku#4m|Fjxt;ZO@{hiXr=uUW(5k-9tXUy@;isP~D@+pi z6Pex?vhp!KJM%j7-bD1fE566g@;2yBeYmf9aHrRI8-JBWQJNcD?(MQsKWF8m^Du8= zBEF~5>Z?bW;wI{+9;y@Y(3{ut;&1jSO@6Pb=wVAblEi7a=p3o|tK>i{?eG!U0UH20 zPc0U1xS;o@kH4?udayLEm!oNl^M+518jE$_vK zjRC*fJ38Xcip%2voT+rLo%NC$)kb_6{;QU@-8<|jdaHDl=;Spi2a)-6r{Gs<)ZlGi ztKr*|X1-^PTNKA z?S$GmuxI{zGxhyg(X(gxcRg0~)|>o24(C31JSQrqeEh@HMQ!6-P>4IePmdZJlzP*$ z?5i>wEfcp?(_Y{^s(+;DWS_;5^h%v5yGR8gCSLLSS8j&(bunGu_RYr?i-$fbn0;q^ zXwU#e+S}fsaSLU;UZvksfpyhSPp7V^3y0Xs?pT%n?ecW4+ARmUIdodZ7O!bu7~+6L zB5guOyVc!KgHONgG3{DzcdZ$ad!M)Ex##jC&a#W69=CKU2k!x$vIjPGq;M+5=UbEi zJ135g#rlzMXU{_qcI|RR2l+*I^;=gIKXHaW{ofMYf1D_sY#2PZF3pKL`h2-Szu?qy z*I%WxUpM+MPJWSPrB@B#fqAV!7o~gV<_U zBt;&nnTJ-xD_65_j2~cAx^eZyz3Asj)NhLm&-jPmFN}B0q#c`n=pTc*Id>PvD^*Yl zANTV2P+YMuU-HFpYPWlj@8^y(p~4LMLQFDoT6^jQ4k1gsvcWB{G*z4={t70_w z8S5>&NI#8G=7z_&#Xh_>N*X<3b*J*~PUX_CH45L(x4(NAtutP!XqBxZ+-2pn7rN$_ z`Jtp9ExAy4VaoQ-?+rIUys*(|d7Rl$_Tbd>bFYR9{C>{vDIcX~NjWvd` z$vSlS@JB@z=C^{7$h^n?D{S4XXlCi@5WDC8}4trrR)^ah|m{8OqvL|Z7}`jfksRQB4M)c=YC0m=Oa6xE^Q$M3@^*!eZYavP+ diff --git a/doc/source/tutorials/simplify/simplify.rst b/doc/source/tutorials/simplify/simplify.rst deleted file mode 100644 index 8012d5958..000000000 --- a/doc/source/tutorials/simplify/simplify.rst +++ /dev/null @@ -1,86 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-simplify: - -======== -Simplify -======== - -This example shows how to remove self loops and multiple edges using :meth:`igraph.GraphBase.simplify`. - -We start with a graph that includes loops and multiedges: - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Generate graph with multiple edges and loops - g1 = ig.Graph([ - (0, 1), - (1, 2), - (2, 3), - (3, 4), - (4, 0), - (0, 0), - (1, 4), - (1, 4), - (0, 2), - (2, 4), - (2, 4), - (2, 4), - (3, 3)], - ) - -To get rid of both loops and multiedges, we make a copy of the graph and simplify it in place: - -.. code-block:: python - - # Generate simplified version of graph - g2 = g1.copy() - g2.simplify() - -Finally, we check what happened by plotting both graphs: - -.. code-block:: python - - # Plot graphs - visual_style = { - "vertex_color": "lightblue", - "vertex_size": 0.4, - "vertex_label": [0, 1, 2, 3, 4], - } - - # Make twin axes - fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) - # Plot graphs - ig.plot( - g1, - layout="circle", - target=axs[0], - **visual_style, - ) - ig.plot( - g2, - layout="circle", - target=axs[1], - **visual_style, - ) - # Draw rectangles around axes - axs[0].add_patch(plt.Rectangle( - (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[0].transAxes, - )) - axs[1].add_patch(plt.Rectangle( - (0, 0), 1, 1, fc='none', ec='k', lw=4, transform=axs[1].transAxes, - )) - # Set titles - axs[0].set_title('Multigraph...') - axs[1].set_title('...simplified') - plt.show() - - -.. figure:: ./figures/simplify.png - :alt: Two graphs before and after removing self loops and edges - :align: center - - The original graph (left) versus the simplified graph (right). diff --git a/doc/source/tutorials/spanning_trees/assets/spanning_trees.py b/doc/source/tutorials/spanning_trees/assets/spanning_trees.py deleted file mode 100644 index 23cd4a019..000000000 --- a/doc/source/tutorials/spanning_trees/assets/spanning_trees.py +++ /dev/null @@ -1,37 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt -import random - -g = ig.Graph.Lattice([6, 6], circular=False) - -# Optional: Rearrange the vertex ids to get a more interesting spanning tree -layout = g.layout("grid") - -random.seed(0) -permutation = list(range(g.vcount())) -random.shuffle(permutation) -g = g.permute_vertices(permutation) - -new_layout = g.layout("grid") -for i in range(36): - new_layout[permutation[i]] = layout[i] -layout = new_layout - -# Generate spanning tree -spanning_tree = g.spanning_tree(weights=None, return_tree=False) - -# Plot graph -g.es["color"] = "lightgray" -g.es[spanning_tree]["color"] = "midnightblue" -g.es["width"] = 0.5 -g.es[spanning_tree]["width"] = 3.0 - -fig, ax = plt.subplots() -ig.plot( - g, - target=ax, - layout=layout, - vertex_color="lightblue", - edge_width=g.es["width"] -) -plt.show() diff --git a/doc/source/tutorials/spanning_trees/figures/spanning_trees.png b/doc/source/tutorials/spanning_trees/figures/spanning_trees.png deleted file mode 100644 index b19a6155ebb200df7d93b4c93e206c1664e0d14a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21739 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 diff --git a/doc/source/tutorials/visualize_cliques/figures/visualize_cliques_with_edges.png b/doc/source/tutorials/visualize_cliques/figures/visualize_cliques_with_edges.png deleted file mode 100644 index cad960acdf8fa830d11f54b28896b968b9f71379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66521 zcmX_IWmHvL*Y+BK5`r`ch)8!R4bq(=A|NT<-Q6u65+WcV(%m4^B^^={(%t>d^Zxkm z7>=vx*=L`<)|&IFc|sKBCD0!cJ-Tz}4!V@2sPdgV|GB}h7br;ZlYxKHwD3P}doeZp zH&%xBPP(=RcjR>Kt}Y|9`+_WoyLT zmo7R87kOwc`QGl%9n=uSum3o^dkgRUcju0jsE~?t>QaYMvy_na6{3-X6hpm~#?0Z*AFxnQd?)ilgE^wL0(A{fPW`MGMf+Zc1ot!y z#!}l(YhC_e-`pxcrDG%ae;q~2?|Q^H)@7z~2Y$0Q^yY9aq7m`4(f^J*v=D#0amQ7^ zSOR|MaHp|!B1hs1E#%a(O|m4LQ8r$X`$|}mW;A88_TO#MWrVjsgAKR zF~;*+{dR--lCq=3$^q6emcoRLDtv$}F`8uY<SQ&K)W$s^!&HeG7{ZhzE7DGb;mogoTrnnw=e6LZWjTFMj|F7gy}^WV^Jgii)5A zI+~D(-wTt3BqAsX`Q+pzJ2zLb4Bs-1lDoUbYY`Dxo=1yp6Xh}uI4}<&-yoqA%+?txCR~FNEKBc8a z`1!R_m|W&_o+KwHXMg*)xV`=1&)3oSJ2SOyV+HTl;TK{r(lRhCZ%vgS?antN_F`N@ zg6+|oQXm@PbBhtvN*bI{iQ$_!7F%!WaCx0}KK3QC^87i@x{wG`FQnq)N(#ZI-Y}oo zTo}q6Gu=Nt)ZZA*hrj1>wnrhKtaG3r`6f3qbwlH@r$T)B{lS#r{BIsS3Dp7>#;y%? zneD%;tDV0>u#cIFDkT*aG4(sbYmGJzl%~Jts$M!VcWva8oNWJ*INg~oEh)*fP}*R4 zi(2;T)vHQI>9iGCikkX*eJd;N0$aYf^dDDNR+g8SKgGufG&VL4_?qKhD0%dMRnG4k z7@*?h#DDYVjpm0BW*XT%5@KQx-oJm3gNwV)(6!-WpEqX8#?DU5%$%E-7Yv6ScA-L4 z>0nRKSBWT$nYwtnDAEsH)(dKtow#^-8?#Ji!80?OuE!g{D$O|8Cri$<-_PrLxE!|#OdWV0JRo}VB&No*@#0FMwzl>qY5Hx&o|A+1 z$=3U_@>p7i(ND=PvAu}}3RP;Vswa}U$z(G6Ui*t;M4VNfKY!jAY~FrsFAp1z%S%h9 zSgV7>LOmmm*J*Kgcd*uOHCstmNeSySr`5lKG~SoAH*bW5h41#KaO)Zx{tQIlBwb5| z;}8>ff3}`@Y0bE;)ere03d+K0{+k#KX&ITR65V^;+}!_rowW2LOUnpWR@TKtZB>Ea z+!oUnUt30Qrl{&k;L=_Yi z94botyf!nXrl#>Z7^;uJ*EzoAhMNm|z1F+6lco2D8fvpD8f$9QeyCSUZ_UTH9{o8eX{o>ZY>VPdAH-%(IdFmG;dzFN&Qef_|zuWMxFK5w>` z{}D=_-VB$%%>~ELpFh>6wY0RD#tSv5g+)XHR0|qc8;*|b)8>VQgnVioHWN_L&~V@) zdR?Cce)jf?PW~Yd^Y-?Z7*6aQp1i#}l>WP@N5|v9_9T`nBChK4%pOZX;M>o+IZ^0O z1=DtZzP|pL!g2BOQjhB}h2hwc$C6vlyhbClWbnM&?@Zb4!tU#cAQsCK|Mu1F9R;hq zv$o0Q-d_)~Vy$mKhlZA$9-CNOmtcN9Kvp{b@(y+l4U@LGY`Qs3)5S&s(RN#`ypGNn zYkLkXemA0rWElg)CsMKE!IrbKh%4%~1)`6oYvlNahCV8FJvOyj9Uw8u@be4ca(KjQ zm9E)vdvp16I*2-r-|Ym&%?6&M!4$9J>Yd#3kSIN2Gtgjp4K^Pw8kZ-L9LLoV)@i%@@{o2by?ii?ZG$<^DP zV@qIq`GSfnFjFLG&dxGkusS5<;o-l2{iTkGa1vfTUS3`}9zrAEG>m_@#NpEK@V^@* z>q~iw3V$&?GJ+)xJ0mbZpO%#sf3hqm++lP1*RNEgpZ*U|8v~=Gu?|-Uji6?tk?`P1 zNJyl+7zz|>+=ezbK9os7^YZ6+Js=SDiGmLEb^tRbN0S; z{>!Eb78Vwro2&D)i;KmjB@wu>^Fc4IFB;VblaonhX7BoqG~8nd`J7oiJ$a#zbpHPR zsiA?-+`@v}>xN^uNuwwKjrGkH?LxcTKw+7fZEY&I-M@v^Rf&nB4<^$Uw1Wcm!9Mrq zJBNq;7Z!%1zOhFw#~&~&(#7j-Pge>TjD=b?f1p~nO*S6wlF!b`dF$pr7X0l|p(=fq z`P6geH*eYzd&JYT3Gs^Kjj=IL&-GgTcxlSnVr|d&v}kC{uvgSI>m3WHmkLH&VFAQ! zZObN0bp2>(Xg-NwLp8)YTIiN2R1Jd$h8iJG@yc9{8Vwy6Hma~@qif~#((R9XFDT8)h=@H!F{L}s#C%r{WInrb8@vBprNA^@;WlW!Q;E!LVYUW9v4qP!Dp@V z173Kr+-*KvhihkN=Xt(@@3=eHzuX-=)pXs8x3J0cD8LusN2$l9qv2qBZ>=5c)zx8L zGj1}Ua>S^WWr_Ic$y-#a*onQN^-aOmnzg<+a`ai z7?B^7HmufM8YnX`Fl4{Um1j_|@Q$TUWN|xj9>@?>fD^=RzxF$8?I*TEqwBHpY~4#} zTU=aR3;+Igl+p*$su1jftYuCDfmlWB9PYkT|qy0H6R(wvX@)z)%*T%H(o zMv_ea`SYe&i@!*-_Mm08V9XSD@cTyB2lbAPy^HOGB`$}C0AhsI)YQXM(IpL3W`eu7WG{xnO4u7Gipn3QxN7>hzuroLap>g~cx&dOqYScU1>Bl7z; zHa1b;i4{2B#y48dH_2&fk@ly&q~PX$ze+$ZTA9@kdqzBpw7*c}eZz(60}`IRTIc=e zMMXtPDJi!5i|rD_LDVGg-o5MV>ywm`p+XJtkB={(%B7@lE6CbGN{27=p-1nEG+W!+?!kXl zaw#pJ$f=Auv_=cwMUn72{?1h(W74d7t)(@Wwbg?yGvDMPB_;J2K&L%m8EAYPTg=SN zon2j$MjE!ZYy$%W1Vlt^x<5a5L~*VRq$P0i@?zuRiC0_BO3KQPUU~>V1M0H?FaKy{ zG}7eZ2G`yb9F&rg$0GF845=R)N)SwrSW-WB5^U`bar#YMoMTOat>%nf_K00|ZW$2=z|7n)8?Or(BJLE#WtJnWN^ zkdS9UU!Ps45uK#Mj+$G%WKq zJ6rTuXJ^<*uEOTl<>6h6c#NNIZHNjv&=eE%q}1ZiD;r>sr8Z0ASj5Ei7*DzO6!8bi zHoBThNmX40Va-+fFdMBfAa>RXqteTaxJo2P~bG}Ch=LOt8L8Re9G%Y3%W5>hqUE|S2u(XB z8%Rq`Obn65k|jxnSKP$|@>8PFI+4m<;>F zVhuOCA)4fi!`01yT3#_Uw6vKuH8mZ7p!CBX;d63w0*B7oUQ`%KHX2CHgd+Bo+twd; zza;LT?=0->`aN;9&d$!C;^IV4cSzos=-|A`72vDx3o_iADAe$4Y$QP^8Z8)dq0Vby zovnAesrY6?>^Q*w*GZGb5|zA_fJ*U~3vzJ?mfs z=TEg&+uU5j#qsv{4=tWafL%wLy}Y1&@9ph<8t2~`7kdAmu-a;#>gCILBy^(RU&X>M zwTi{U@PJX4>G-5DYV=H2(tj0SDW(NbXJcIg{IIG6pC28%ihw&8IXQWS*@S$`K&=Kc z5aiKO6)2;AIXRSt>Xmi7$0@HYq@f6p)%02Iah@4x>5VY3_mMrpbnNZMaQPv$*6CrWIlI{O z&n`a?=SGnq{^NhMbTDzh`Kl~+P~gq};h?GK#d-me)!@KDB(##~l$4%Ivxz$&Nc@9> zme$v$R8{c+d;T~f0^)W5!2{s75+Ef^RS$*_q(vlg?%w=o=am?QCj>tDPQwuGHm`S@STs*6FW+v5a zqKG`UyQ`;1@638ua_Z+#VW679(m8;)qTy^wIdDltK9z#@2;0}~#etytboK5)Zbo{} zSK(g&hf(6lK+|+@Z>}e&rl41Io12@1fCOqr8q_nub%1ex3~)oEddlaFnWG#6G+Z7x z=Wkn3Y+|C*ph{b;aAzd{`>HL>M*%v&pG8Rw8}=qJ=I{_fCvSuG)YsRywY7y4OwP(0 z-5pE4nfgXuy$47nEiG*;JaVNhajE>~Aavr6?LXCIru-<$n74DW&A{0g7Ic0T7S>w- zy(=IffH+@;8r4DMSxmy12V3Rgv(=B4l`&gf=>(ND>+CaU6Sd0#;Ss$weGza#A1@7$ zK+?vBb$opMX#3A8X;d_I+VHS)mBkx*MJbxEj{c!N`^h`{opo3=A(dmIKVLsPDNKH*0NhUY| zeFZ*Fe(CdhfRQ}M@z5_3#}j(x>r6#}jUj+;fVSSH3rl&*V;>B#ysy81eWIA`+qZ8o zpKDlTsusL&_T-25i}-8MUO<$y8~n1XyKh7S#|fTv=O=QJ8oN~t5c}F&TD*a_KacGO zl?-5K66iNNrl!)(p4XsF6=O}^^fkXafpZ1Ok=1IB59iSXxGRKEH#w;WdyWuPkG2?G zZ_vlitwis$=PDR2B(dt~cuQyfoz3u~;(mpft5I#tZSaV>NJGNjo?~ii3i0@hwFMa% z8OgpgM4_q|CLk_uH1HG+4GowrHLTDJO3LW;^nnuHHd0eJcuB+c$sgHtzV~%i>V^M6 z#f2vn0`kh=jg6ko;^u+VOo0{x^f_!rCbNbkVL4Od1NBlNL!k1_*S-0=L)a=xAT&vN&DYvVJms=} zjY9qlSW7|w<9&spok?=OWm{J1OiV{4q{ZL94}{%sYB4jsm@YU>Uj%wvCv^Y1d+#3B z-mKGU%{hM|@PxO^D=Si7fb?YY%|NsD&&Ze;aiHFwEX^T!)u+hCwPr|0BG6F0Hm^;U z!kHL0Rc;jG?S01vc52Z0&QdrC5uk=8+%PdS5OG_q2?kEFY-B#$T$*lSv^F2#SBpcg*q<))DAu-%tblmz< zokoJ+(;G6_wZQvK4Mll->(lo9V1R0&@yIuHbRv$k2@Am@U}p$8vKF4y-``I;A&9`= z{ryulHWYBWTo+P>Peo8##|pZy_Cy|#dFHi)&|6l<21N`gFhhnX9ha@B^^*7_wq(Rn z@W%wQu$Mp93dLyu;NWL#tI)LJ$B+KfId|zOn1av38p7N*Ol^6{}VC5O=Bq|Y$yG6peiZt22jIaq2 z>go@T>PXmu*Ow+Uc{D`{iRHp5cR7fDs#mm_PO?}wUad0x8$aCi9|fKR%qFw1ToVZt@T3$Ae{)F{VWV0s=)P zC7;Ypa#$RltFwKCo(CWB?Pujhq3G_93?J&^{<}BVGBkvt@#hKfau!zBOpR)vhW!qv zzJ9s$t@7KfA3xB5eOS&lbVFlsAUyz{I`sW5J;{52Oen6&n-j%{Gj@YYP}sZ}jO3u} z^#U&rEwu3Hh|16`l*s~#CMPE+DLGjQ_~JL&6KB%_T(D9*X zm)Wl?gACpakb#iX@+qg~Ov~&nNu|0R0Ayew|Dbt-p2TXs@VeXCtWq6xR z*(~0_xe@%G=@9M#v^Q{Y|yN z!Ia_ZgFoi4j*cf}WP`AsVFj5(A|nmKZwMz7OplAh0d)A=v=W*D3v@6Lx5YuY23Qaq zUXAGsEYkY?z@VqMH)k_L&?_D4;7ECH$}iD(18HvVhvJo%v#CD!-f&sBc;joGrLSf* zPZ+4@tCU&I3jh|Tv=}kwFrTgn0oQ33d-?PkN=^(t2FA?#pTs#VEX@z4zT)#9ou@?T zMRK2Q`Clcd_9l@3D5Pa#GCbLu0&^?{+8u~ae&ywMD-QlZw0npuoshG%fRB)QU4{R5 zkB-ak8~Ofz{_VofOz%9=6g;pvY22bB9ZROA7N2{d;$|w+7>|929~E`2*rukX?RF>Y znVQn!mJx88qijAW^^r!`trY|YJ3)y_V* zd5t1uV#3X+?j0Y$@H+Ljd zyTG`(9+PAY5*~!e1W*Sgjx3XrZ_pP@?N;SMCX)j&2dZM*(2!E74xVs{*R3bON&+5x znyRWQs9RU06HOvP7$ED160%n?sM{}P&Q%A&t7zfb=-&f#w|#i{3EV<`JufH|G&qld z%Iwg(Tj}VuG`JihJS`BrT)!x3jLE#><|c&N`}viH@q82i`uaK;P&!st3UElKD$Ve* zspUlhIernk2bTc53YkJ8G8^7NR7?!qz;=L&rPbBBaQ7S*(<-@zP&pUY-?yf66B+i^ zoMY}zwt<)DZ`gmos>&BGB{@=QX=$k}z<`a7ot8+bBEQ?0%#Q2@$JS}*>NV3hVH75< z21#&a7Ds6to<3cpi1i70aLz_J(Gj&;7(skaMIVMoO4=oOjgyE@{HeAM^r4?{8um|4 z{()_cpvC{)Lt0o{lY~~XPC}*L zaa%ZFg-!1l$~t>pcDDcCp7ouk^MBZEY-MNXtH+=W9n8;85xwB!O9giYm$~=^x+$)R zhzPATGb<|=v_Z^xLGNUCqs8@gmnaMnL5(MhNZiR zJbo;J(i)1Z4YE|v>HKZauaH>Me)MZ(#QAWV{}3D&Mz2wIAHj*mvk;UAy2-ke_2RFG zR0`>`z!7(of1;tHw)OW%!1J8Tx<`H=ApHs;jjoSu)74hR?62Q9y1sn)@FC(B&CJYz z$aLLYUlPJj4+#l@?n&$)5TI*jR)C#eJZ8E}c=bBxkFm2e7vOzu&-0X;8qox%Yd{+R zMvn@wIuZ1MbKafQ%}wI!>L)8FC%DTopo(Z}rmD-3R-^Caq>TI3K0brmp0zLE zZSr1?oqh8u{sa(sxi}-P&}^QnLVroO_Gv>BM!ja z>}e7J69k6`#UT;{N;uRKbO81ZhXc=*mCMeq4x`rQy@HQown4nCY&D=(NdMR#itB!J zzRJbJv$(k_1I87?(gAA%(ch7gk-_Q0rjpeGbPAwF#C0yycCXy+)DryLoS|K4z!_Z4 zZshktu=HA2P0q+rfDHw8b+{rE(-*|dThhY1D1cr*+1VNmkjDupWS4U7t}>gz;N+|p zWKz{ci;PV5*yW#Qet)+uD9dG?@)g+LxnZagsE>@V#@^jWC-7d}c*~KHAj@atE7#N{ zo6IJ*YLGQ#jEK5Cc<=zkd_`sDpKv2)eY-bgwGY(P)o%u0hyZ$^5)eoSLM;8qA2T~U zy96XIa8tU2vCd`F9+ew5f_-9hdjHN_k0#*fPqsE?9#d1>#>V`H`r@^Qd5DhorQsi|VUrJK)HB~G?$wum7kyeBx z-k-^n!f7=CWZT}oApjHV2%^n{NF+9x?!ut{fk0rd3rY4`^ss~H#Os^`TwxUg?eXRAT;2K@Vi$B_dQg#Mwa zcgo7o-QDX@l4YsB$&*lntm%JoJR!EV_xJfg%j>hIqZk@=47{InTEPar{#?$A_dTvk zF$ejnMcV?OJ1vTq_VmicF{nMmI9aF2!Hx(E!-h&XEXACXk-=PLIZFr2O36VKFktFBBYyFjRad6mow_DXIS%CW*}23Db16v{WeAue0;$NMt0*vS9J{V=F7vjD77LLc3EQ>}oD)Yl?L_DtXCnHu%SvXILjwM$eh~G|R-MPv`M}POIZEXi#ZYls&1&XMBRsr1@$1S#C}a;=xGq zU@Xxa@R+sw;%F&QP~Bqxwq1_@ zVsu%Cw9pf`cl-dOu&+bwLav0ifXaTNXA%|I_PfKfZ2BdWoI z1&`N@m7TcD=U%77Nqa|!Eu5a=;rpef)W0=rg_EMO!tUOk)K(9*%auK5>r3_(eAchTT2*u*Xix({V9cXE2Ns!A!Fgc%l$Ypx%kB~67 z+FSjsM#_zH-SCocAKr4+wSg=ST{q49yI{H1ygUR^WL%H-s9t<5jV9ZP z1iachJRAe5q&R6xP`t9imJ|z1mtaaPw=?2ubUSUIno5Qc9>fTm@w@mOl#YBG&%l%B;YGMM|;?w6?k>mpU zZ+=Kv9xIQS&F8{ZGrz1RY7bvG-{#nq8=jq=eTt2xSpSljCnu6J$>Dqt8(bRl1*Kvl_^kuL2dq?MtyX2 zv|L!7pkrat-xIG7$zG1g6W{2pg-){j8`qbt85j>(u z;F!?dy-iOcE-~l2`9VG%2acZ@LLY*KyrVK8golHpV`iqY-CzXR(B*XYF+?vH{#Z$T z`t<2_qw6E_aBnhC%okKt!xbiP)@R`O+Ca9Djg1Wv#1%DP9Z`76#cSq#drfe0Obk#2 zd9uFxAV(0^0+P@+Q5c|Ew0$BETK`QRsUYzFK#kb-4k&vFn>w-M=6FI|e}V}&!;7?Y zy3)+$u%FYX2Vc|C@fEnnV;f(<0bD=4!dftuGjY&s5xHF@3Mpb+C zQ~uq?(}$4M8N7THXEv@A6WfNOgZ}&Gz~GxPhnj(*unV`CG$jVOV$*f;WucG8AGO-G zSVsh!w4l_cLXEUO+tZbmlLM_AX>M)~_TX9tFPMJvX`w&IjyaeckG4b}vRrj`G|`pM zU$eY?**-KBs36El#i}F%4+dZo&_PhTe?dqKq^hyG1z3`ydM7J*(D%HP)g$zI`aT=C zoNn_adu}7SpHp6u{^!I>8{+eNX(adWBx?#6cWF%pPJreBLv8A}**Y8DK~fCT8PGJ4 z8jiHz)7BeL#i3C zT-38-OFLbKD3Lr48^68?`FZyQHN7vF?@O}r;hb|O1u-7F6)lO^_Vi0=B65I+K|9G) zS#iHuk4j3SNn+8(kxStq2VG%r58c^~-gzZ{NmOE3<`RACnfp2EmxM6J?FW&!p`!mA9+3# zMI}d6swc*_I_MV^Bt6^;4Dban1iu*@-3t%_UtnPIr0)veWtCNT*2@v6b2~*EX;eJ3 z9DY$ZvmLLdEPS5MkJjjj{`D)%ckPUIPRj*UG>(@!K8g68@zRh|nwlhJa)yS6KprjC zZ9@Y0ETEu(9^4Bcjgt8`0hsrTwFf=x1O2;K!W+|2?N(KZE`BgfHWE*K!j$dr*FCd# zzHv#fF3q%FS5{Bu3+e7l&SPMJ&y%A-#u!T#e>iOx;zfHIyXP&40xW<*yD4UQ`J;M8 z*UGHZe7siC+kA4^gQBjkJO!$SdM)1n0oDPbCpbJjjxXOI6RKW`*@RF6!+YV~IRVHq z37O_@TmghxT3QkT8kNN7!WJ2cZamk(4L)a{3LVt#^|=pwSBG?l{n9rwQyF+9h@{11 zLCp^E{!GT`f+%I^npMBse@aZ0fB+C|A5aWZAilEj_pgs86DTG8JX*3~=~HvqbAlks z3et1o(fLgp^f$yoPT?^5>HXh5*fzwFZR(htBL#sS93n&t9CW2fl9h%7=?86rIafKX zF6#E5l9IYUTX{-?Jer>V-u-AuA_jFCXu489U4)mqIuSVQ2BUdO&aSS{6MLtii;=z8 zKRn#;9qiood(1-2o3Kg3^QGt_rE4&#(M`$U|M&a+9~EM|&4a-sx#ukWY2y8#_4j+| zY0%L@;r#~g5kx3`s+}(QZ?2sVSsWB8I&L72hAFCZrE(r&&Id^ zWJycD26p?aJ=(}H@Unh)@n)j{Vd3V;;EPAp_4z(nzd9Ou{Bmf!Gqk3L3rg+_zqGWp zet2^Nkiw8Lp6dJx#u_cwCL_NOs2lVH@NZBsFupZ3qyk(ddSxyN0}Wt9J_cRPs6XZH z*5uzHSRU9RFmVv%>wEVp35kuPW5@V-0`LpFizAae5MQAnWCoEF8b)iL5`K~Ze}GkU z;kmSWr5x;X7;#9PIeYZz(PX0=Cs5-B5HHc5aw$Gan=q{eLGGFVGY$?M&}cyAGyeVM zKhRI8fSLYx52*xFCqLV&m9(_v!6*XyMh3Asu4k#_=eDJtY2^ivZ`sc7K6R3ejpKL{8vn?m$-|j(6DhSnye5@44lv<#={Z zsU(Ux%!5F`W!)Hkh=d`U9xpbY|3-GQnM_|oBI#8`xK(p|_wP@yoC>KC+Qi{1*{#?_ zb69?Uew=whC|GaUWMsu}R5HQR^$$cU*J(vVL>51OG~hu6y)_`9eK#v&91-e*m{iCB_BO|dO zaUk9prjyjFElEH{f*eT5prCeN3?(iA3P!L7?Kj8KWn^R^e+Mc^CiwTm<%pa%)H-=7 zNl0!-k`~UfuStCa)orHEK_)lJ6`C*bTEw`^@GD5~%4Z1ln-%j11q5&-V_f~sd~^I2 z@?9;E2>Vd)xIgE%n>l2>cYI7)Uh=8e#)g60AvDUHvNQ584!*=S(}z#}>FDo@V;Y>8 z2dm9P&SNM+Mm43NScY6?slG%$3FscrDa@+mogA*{_2*&e2h{l-qGDJB%_jHr^k8Aw z?|`=^>)-WiSm7Q(5*ZP~fDa5*J-XpP5cLpo5XgB$MT`a24h|)^zMe1bZ-Tr}-2~?c zy-68dO6TI0m6UlNZsFBdLGvqI#8^uD@g}640QX_KEHV4yD@<5{^K_B^#8?;winm|0 z*8^>Lr53Z|#ttC0`FVNIsHl)2k1bdJ)*!EMaF80nSkZ@iTX4z3BMdk!(S%!KC}r#$ zqya$KH++{*=X05N{j5Ozw!P`{coSKr$O%!{)<<&Z?Y2513P91<^Soq?f+(C+b38Wn zO;W~~F~?J0M>GiEfEElZ1^HROU%y1r&@*k8dK?lU+wty#&0Cse=6YDrVPn)|b3niX zCO!gzV|P!kuC5}a%zWvIS>SS^3Ierquf0p2 zh?Fns^UV#7{}Dd;yS_X{C8tA8gAXYQ`LKuN{*YwDh4KxSMkwgU zQmX~FcI}e%^h4rI_%i){qB_?X!k0Vs!Vo5*_=i;xL||Sz)sDyyVTZ7iUMBGB`sr>hznRz@LIDU1TmrlhLM5cm*6j;`0_G%~DyM=#_S}77Y>@Wxg zLHQC8@*s=);)5B4#oTYN6~I5d+S&fs1=W~Pz?p?y@alB{CX3#EK3(oWQY5Hc{(*tY zfcAjOLl&~x>H^v8HtlM!?R0rL^&?DtjFHABB#0wuHVTT)OpQ$p>RzkwT>(KaQaR-( zVg?2^=%jst+kXhv)w)Q%yvoYU&3;7Prg$BG1HXi>BU}lEmsg||s3S7ZDxga|kPn^+ zqeREYQ-XOR1{x)(@WqI@G=xlk(`JDX`VvN{gvdo#@=V}Og@bz(5AYa?LP`0<{Uahu zVJ0mJrhUxF+1L)|?Kivs&TtQjWnxkYjUr=>=0;)a>cTM5^@<6^Rm$xZ!otGZ=NjF_ zV6!1qP0)v)K)!QCiWcHaj8e@okO4VMI6%!?z!{k89A7?hbo6pBjgO0yG{D-t3;P+% z51BYP5YnOGJ;Q7mLSYRKMuEFaR2u8L0dw*>g!U1qPnwn79}|*iJg5AVg9^bUy#9te znnUlI@Y94Q{ZPuQ@fUxS!vLA6q-0my?v{Q}SM;^$?M>iUDQuBa+m#+<9_nY$UW3ge zcfrfWr3SZ!h+~JzBr=5n5?Ie>@9OQ172k34QUcR`sNfy-P*Y=Rp7y+2-8bEY6A-<}&C^zRS9SNkB*_r7g2~>Rs{uB_`9a5;(NUj zhvDt-{{oLmWh5(z2u$WQVVqMK&m`QMYb4HV=(MeUiXer0dfq(_MR53~J9j5b{jfYP zg>{~Rul{==ukJTWSNlvjyceXB7Y$27Mpk9&H!E2&p1n z@A*4~Oa~=lQ*?+ElHE{+bqox|w6xOYdHjC=R_tE?yTe=!$ry;Zt2H&GKEzf5!8KX+ z8Y+<&;o5QDd1r?fNJ#GI%7N(YnH8fEkRdr7;N9K3K80p7S$c`YtwIJLerG40UIH}VSNba4!?pN1UUEbS(ICdRTA{KLBi#D2`uARseb2VlLs$2BYMNx z@6kvZ+6D(x&kt`O=ehqkOMNOekz|!45Vr`H8qU^)IyASh+6{Y zkc@|(&v{;2Kplcw`uAX^*Zul2JLviVE<1ldm<3Glud00!GQN>3_jPwYP zO!*RYkFkVxH#(QU4;1sieBf1Udiu)TTccWMmWRt8MOKdfgHg)M0@(*?DUa?UwZzc| zM^n5%n{#tN=%z-1KSXwCW0bb(a);N%^8hqfxWOmzKrLtTemq@SUx#dzTON!*fEC&@ zGxIb@83fOoWd%|koTJ3^_6*e>&l8AM%R=N8oY$JVy5S%1*+J{bW`B+&Tw?uK7%~aO zFtpI!+q(q05BJOYTfG`P>a)vOGTinY*WSL ztUnRY@CbDO^9lunYOjxwN_3u>@}|PB8e?&Bk;`@&1^NcO9sI$!y84uVla{&Z>^Z_C z1k)E1J&4(@1ZHg}$}@UeT3vvri0qobe^0PJNG`PeN5E0QOUMCo1~W_RPJ1;|U%g0F zj#r5%^50M+v>Gs`5W`ELqf;>zl||-MS95}73>g^kskv>l%LdHe8aK&OWq~gZM-=QG zNnlcY2M1pPh=WJ;1PeEv~EtBqriRBtiLlXmf(T_d}J{ zJSoh9z?jNCWDLY`zp<@t7vM~J8ykWmE%g4+e!@Qan(_)FA`oFXSn*s!x;j7|C*iR+ zzp!_`*1Gre*GTz6FC#r_VJ>x9y?B8`Jk&eH;5}q#TOpiW>$sf~Cl2GZGT)!Rguy&O zGw3Q8|G<^RgVLJM@V&U08Ri0h!R#g2)5>6kL45(OJgcHYftV%cQ=H(aU}Iu>LyeKniGh#-nAp_*nBe!K zR;u?y_6G8lh*>HSHr=KX2$(;BEZuavDj-LOUc#+VUC5l_>`Y~+ygFz#BWQhup5ols z7vf1Q9R4+2*0x`heg5+s{~>hGeYoyrH)!BGhEyv=2pJYe;Dk_Gf%U`4j{y(@*b%hV zlDKb2Fo8*AL7Y13MvD&#gaero-M5Ghy0IY*Vi2gU2xboo_}#mA!3Rw;G}yliWBz(~ z4#Eb+Z{B?B6)IQ>ETGrxKudAlR6TD$*{+Tsv6o5EnaR9274-Oas7Cldi|LjCR87nA z@bR3Sc}qt6=?ip*zKTJP zO-c~PDIh2Fx{MP>9LOOp4oji;@uU6VZp+V~zTl~X-*P?a@=zeo{RC29FQ`;AtiAyt zgpf-FsE9V#7Y>j%w{dV-8Bv(monm98e`k7rJh6h9B7{o~L%#su&Dz!$CdUz$K6n?*MXy99C)S!kLNn2C#obMc0rKP8&`W7FOWnk0w;0tL!{oWBFW&9_B z8T-lEoyj{tq-1~XPiQ9_o5{clgN_AA(;Cce_+|%x*xraQO0dG~0RRR=UNWw(7mbvZ zn<$VpiB=Z7N(T5N?SKvWE*KE~l2bsR(R9UDeAnl-q$LxZot^VKrSu$R;7NFgE8b8~ zHW0!Xq4IpeyS8gz`{_!*B!VZyBQ|EUL>mhn@=$AY7V-o^A?X5(Z+)(j7Y3_f@zpC$ z+jBEKf3Xj$lo&leyC~}D=?Q&^O~nGqEEo(!jDkXT3SkMtLtuq^;AT3dsua&D`0ACa zkif{(<>+pH?UzB94!rhuYDkI#Q529pqQa3Q_1#-Ny-l!S;^0(4>JtX?fBR*vqz zucc*)SZeqx2cX+>fH+;CUzk9K5wa8YMyCG;k($3>=aN9?|NL+jF`FSTFCX8%K=jH# zE>2qiwwHOh)L>;rQ$}Ic)sPDJZ2$=oM~mx~bISI-!eI#uQtwBG2Mpe%uU9>x9K5lgzm?< zYHBStHou$rY2xFxZLhG_Y1d)UKRDRC=tH!NOKUWR^}Fxhxev(igZJGsFtC%((+$yL z2(w6g!T6yJPYo|`J`9jUYWCTS7xzU(uwPjym$+4bvC+o|rrixlsn&Mo5qJ!c4&nvL zE(4ws6sW8bt+yVl-}8Ix|9H&|+X?R7-OiSx2#FMU?NaNzw#KepHwrZE>zFBg9|PBH zox?r45j$1JV3_^{lchVFLIP75p;5p9^<=Y`AT(CdOhqt|WHe{q`+KMJBmZ4o{0Sp% zh>;Wo^qI+nLJV#Rm;>UGPia@21t7b7dp^hk_oraIHkbRV#b{@Sc54b-{C#qGUYq{T6T8Bc3Q(E zM1HJXq&lLM^;gi)5T|R!o}M9ly`cD@=W_RrqGAiQxtx?X$i>%cLKk3#JZH>74I;w} zS{{t<$Vql-!3eb3zWmrzXs~ELK234)tvj>Ph-iV@|FdHG#nm6mpkaVB2V*n!?-;xAWdJ(@G-nI`SniK@E^nQ0N>RgE?VT zh%^u7$3BLh-T+^@0C^2-7=;4SD<`o^mZ}Z(A<(pCiaG#|!8hPMg6NIT!cJ!o#fDFK zBLo0ooT!4M^>C2>Q?JDSPgLfGogH}yiYd|Hz+Czu!d`^19eH9ei0IU8Y%x$(LET-S zt>=Uo9+=#aekmy}jeh=0@M=#k5M73X6W?-Xt;g%;@ClrH$m0(|ZeqQV_J89_;4s=k z7Scq1Yc(UW)LK_SNh#3Tt+`)<%tN`{sW1Tm%)cuaTr!Ur)SONz%*|J9q*z#7MuvJN z*5tHcgJz=>ygu!YRWh!$zH-j-5p=?+a}3B7$&|t0!ND!P{Y|ckhQ>li({eCOIVa!{ zibRBdH<K3}TcG z8mXR+&TAo||3I^^N#hZN#`p1bckm!fV!x;F7hW(sn_hi2=M*I+)LJ55E}gwgO@W*o zMHPPp2IGeCird zAcl^%HW4CCOURld#!F$&8#>t#2x*Y`gi{E;avh)*%rQZ>s~mUqI*|lQ@MNx(oWxK73o}_;DfvI4^T=fzgq$*BY^#JfBaas-+bjw`{v)X*lt7| z9p(pt_DW^;A-)Nzvoi=}CtVYh5U{g|BA!t`_&?g-I~>dQj~{PJDWi-i3E8qrg+wZa zP*y@#WG6dW4TO>;JELT0Wu-)9gv@NIP-a$US-;o$e7^tv{{4QR<9Lqad5ZhK?(06U z^L)Qw>m3jP9gUla$tPNpdjz92Ey#2THIz7ARaI5#xB2|M$3~y$|MaPxy#sbs?e@0k~$Vq&&Ab3`FM3jKwA8W zt^CY*VJC2LlgNi^hYsbnx9`^0d2!_M&m{SKjOLlmB2$rOyUlG?v3sD%kw<1hzSX7F zXS$%jn#>PBp?036{yA7L^|dG={>r=L%UeQrivoF!p#r2L(*csNtCeWFHsc4223Q(YW>K^#eD?v?#1Pu0J_(Z}R#8fM_fq zcn1S~d^SU=2ALQGTC1fg3cD*xi6}v)r+Up6HdYw`>NUuGgP{ih8T+84Wp)ZA0B()(>7pgy^m3IeVDVev*ecpa+D|5mK~_sR=sU{YIAba1s9F4 zT_ZkNE>@&@A-@S1kpOxWI11Pic{R12q}t#c;Rk&5BO$2d>FCL?y;UIIpkX9V|2IWN zqNcUxd-wkSJKtjfQTfn4nr~%IO@2Wq{`KcXsjYUL)V#pFPsaQ)jaX#ZW~$h$BWk_n z^k>eTft#B+QUQYrT*|D#Qvs=@q~owG)aIb~0c<+}7lRrjVd;8)a)Uv;?*P>E zJmI=?#&-vwCa?LDTYx^KOV}c?a3$N^S3d(qgdTzS%DXDNrGoWyqxJnmaUCc6Rb)J| z4x19r@_54%pCSt6{EC^Et80;o33kZK`IZd6_#W7ApkqK~)8Y^Z26<_+G%Muw;&q&o zl|O4ZExP_}U|`s0`1`83=>=V&wIEA+)GuC?Ut8Tcy%5yYWpMFg89KR$LuS-yU+@n4 zQ9UkbF;Gha)(2Zn3OY#P+wBI5qjA6{sj}S<`NH@4^A7|NZQ4BUN#DDC_Befq5&~C{ zjUnMG7M4}=PsPjtbvB3~)LBI>ACZOi0fjA`+)45Aw{bGrFU{LLd-jaz`S%>Leq*Z( zdjyv91ugF6Vm;qGWeKT&{%EUb?X#g_<(U2|@xtq`4_naQ)Y&>AfqP>ed@?s~AG}8) zdi40-xx1Se!=64iHK};TWKdDj`V{N|+JQ4@3`rwD)~>uwER`A#5xg6(fO@<}?c7O? zQuUDy&uW7?hqT{0r#FzK3}P08xaD>&of+I$4uhYGehek4nCl->iQO5WoX9GLh1jFV z5-<^*(NDt#cm+0&*XD#D*nVH7*Iq0}kH*h|9;H zS0F!|%*lzot9K%HvgF-b-QS#ed3%e1TKWonY0<~LR*O5|*d;(e&Ll_4w=#s?7_R0x z+83{f7^D6q(J69%GLG36U${rU z0~sV*W#5YFTxoPKFk&L@IzK18_h6Ksu6NCZTLtii~iqAdTq) zn$rv9C$K;IkuVk@ffwgxT6|@;9?uJwmPN8cql`?D#g{6;ka6)Bcu^{lWH4-C4YATn z!0R9#Dg1et+tWa77`--lX}uD6X0(+=H3yPuU(!vdyLe&!TNdjfpdL&JIfW#_9ZeLi7rQhPa+eG0Tj0U!`)@Ip#oOv0;+-lk2>^qKVcL4 zJN1zUnPl49pRfs-x4&X05t3M7#195|VdQfi1k%wE86apN2hl5tBywNqb;<9DZ{C0{)k5+$ZY{k3gwcTXF+$vm(ZFlP z>EOcf_n8ZUEBDz}!&@~B1O>}Gb3O(^=`{LNK|xUw_aEgSUy;z2QqLG-`vqJDK)$B2 zaSMOQt}E|vh34hu-RJ99Z^VPw5Gt@I)j;OihYz)tAKtx>HokflR+}^2AwYqs;_aW; zG&ch;*@NG|$RD~6K2UG$ntWg4Vz&%nZysn(Z98o7`rbiZ&#Ndi5Rs$Q?FE#W$Qj^3 zMR^AOyn;nZ{pZiT!ouMkjj%-#%U4cYVtJE;0pT_|IK7^m*7d%+JhRbZsG%~M-GM*e(M`3RDOLIzT34+FMUHO4<;A$x0WN|% z?TzEe6AeEd?hreySx|yJtUMF;)cgsKBLfh4S99ZXiIbs<2V_*14Q4? zwd=yttu@3o^>X_0+4;Du*H1)^bu1wWE&Am+0Bi7LArQ^}x|J!nte?1rq{*m#b4+=4 zUfj6CuT+n&BcV=eviR&hih&~cB4Mj`>yUyWV97|6LKu~FzN!E}|4X)eg@uJGYEpoH zVBaoZ_}*c+&|X?5kX0NI-9xVuH&I^|c&B9^_YHKxr}}!+(K!2d@D%6%-Unq;iAF5Z z11%1zpc0klsQPGX9U7(2F3o?Da7^LRE%ZItGcz-@m4=2#Sa@(?ue*vL-c;k(>z z2H$774;5_ajr;tU#mi2K&!bqf?xvSDANKtE_3Ju_Y9>KYtZ$TA+YYyD6Z1F~yQBO= zpooa}8h&Vq=k6rpC$Og+5Eq{_3Ru!GHZ`s6&e!$#JLU&0Z=F^9tMZ!E6ObqF;o(Vk z)8m?KzmuDL2pMIP2~kkhfPW=oCP+D453JmLLdvKPgQM9FLq?LzvCmsNT&Pr3<`6%? zk3HIpdC|<)HVDu6AG(vKN2<|ffw~1mtrNJ=r%+u{;f?6IY`2Ar7J2*j?nSK5MnGpk zY?e)b#G%~BEt1?^(UWI!4;?VLj1L3r-TmNznBR_!v z)!}jsI1eQg+)|!N&Cg#CN;ab^`71B;_U}88=wi#uhl`goeIGxTkzbOdY-wq6dTyzFTai`f_mMNnD&)&@_B_*tw}BdvHY7 z3^$(|ZhFq}fKmF=fS8PiWp}Sx+1;-4-rn=A>1G^7I^YeOvkWe+_k#deX~F|C31pGT z=b88MYGtjCXIg!xn=B22QnDFAwo#0KQwJcvr_ap1h7^d?D9N-aFOINCSw{q|tN2m& z{=mWs=ot`56=weJ>&fNCfrS=veUCZQ>3?H>K+5W)rP>u`VokyXU3HOo6+p4$dN9nbn(LNluM1;;K>w_Rs#G82l_RR z1DlLYUJ?LJTDajYSU@t9M9$tuzL*=#2%Ia$KOaIiHeLjElTY`9)aob@17ocW4A!zgN)?8Y4 zzWC0~n<J?ixPfOHJSgX&T6QuQtV>lf;IjzuffyOY!Uf&tAr< zp%c#U6RV3J(6h@T56k9(Iu911``=$?aBMz;Dx{;}nA1-7P2b&fAC7#f-pR^(rKi93 zvKE3E^DM4HAN^{&VDwpz0X)E~t92Hwync2AzU}095Ix+UvGi=P{uFMUh@9Vl8RB$w zWi&GGx5F>-LMwq-zz!0a4g)IMcBCLtUY#B8dm0wjZtjLF3l9x7x}N#m?kez@bQ`2TAXN32_>E186_RniFvq_fzla*sA0b@cQ+fnqxer2yh#fFtXZ-1PrJJkMPwzoC$9 z!IMNjGpU#2;@I#s?nlFh@W?h?CpAh>5)cHR8~8k<;ijlKwai1DZV(2_%C19of>bhA z9H!(2*u4!w`Vt}!rXwhlwaHr{z@_(XD5QpCP8S{^Cszz{QV0QOi=-ZXm;*7E6kbDK zC|q4n?_px1DG8dNT39eccnttqJhyf?Zlu@*kM2eG7ZPzZX zB;yzGIx*r7L%WHV^L$3lR4a=c^hyxg<9aj65C1QmeM0|no4Omhljs=Q(xRu;t$u^| zu0poU>`Zz7Ia%4;dHd6oo!_{f)KVQs#iH_WVKT_yUm>H`=t6pijLG$H#R>>FMf>Ck zFrs_&Wp?iqe#sO7(1xIyUWa{5k?OUVeAc}vP5}YpK1I{y$Y`?mP=AZ~S)_v!j2MyH zV8~&9PnVv!IQk=1bRN4G49|!%ILOT%=;yDHGXDmJ+7iot>9t3=C6Z2-I80bF+GCZ% zGd11xOjA6^AKAxhLEVlR4+dvvMMb5IH@CzSy9e@gGQM?o(4vWQ{5|X+s=0OZW^S}o z10~fbYR~+sc78-I3!=R(*aM~q@@$0>x`M>01IR;4msVjr_vZ)n*698hKUBv_I8a== zba1FK+-_Wl1((>iFFZK-`NE{9EI#@vclYIudwe1ycK;sN#I7x`qVi}qbk2;}0D~NE z%0f}-|KNd}A+bSh-gwU#fuf18Uirb!rQxOrEiA&#Xw+Lvf94#XhbaF8^5v;nb#fd> zhG-lc;Bz>4{&2F-6qLNl}rYRo$&uJUtLm?1zGu$F4ya~ zuoW-K4xx#--&2^8U3lroNY`Cpad64Xnw#_Dj;w>(WEx=x4$F&n@5jEc{eaE~y`DEf ztUrU%!ZJ+~P(GhYu=~)ibuxsz0r=KN=*ZyD1=+Kne~X$@m|*kRkM)S~K^D9aQf419 z=|`-|4#6I>-pb0%+J>Puedruy*5LFZmko}I*`c8_1HHBZ^q2F)Pn!IzADhL+2z>Km z%W*sU!pVxs!VNK~+IhogroX7lKv?S5=n6KWA4K&|r0|if>3&o*L~V=1$qyo}2fjOO zDnCcsH^<-c??g4r`MWu!+A8bdPB?3h-J)-Pb=kwh4cY6kV~1BjTr6;yrCxdnibFs2 zN82Dng$kMn%jPt2Kb(i9fJAm>X6~qX%4gsA+nOKTHJfR8>@oOWIAYyYgc{<`wr1IK z*?_2E$|@~6C#X9gibTyfL&ey3AuLpcH9-gr{{bAY2p8Ll0=&GjQT67nw|>(Dzg}EE zqz>Ss>TFjc&m(~JYM-M_d3WxlMTOEb4`^+AFgnX0bmjS{;o;vMV%1XV@paKdHi_p` z6C{=&ur#~jCU)df@<=+~U`mkZ^M3cvA1doOHU)!yN>|x-?&Nrt5$KbU5UibTn3>mG zmmaxTx)$<)@!7!6P!vBrLTIjxZ0`x_UF7&|Oh?3iT?DlZi7j39D;IYIFAU9K^o9$m{LtQTiO2KpPvIwDA7E%a|c_Lj7PHTTTcFsMGCxwEOU< zb42|m-sQtXgn(4!m*3>%AjK~w@4bPHt*A}Z9rKQc)A*r3mW>&ZEX%=G0@vQkqvLHJmfY+dZV{C8d2D-aT)ck_5#S%1}72aDZUMMl`B0r?zHqk3dxpgZY zF|n^YJ6Q1^v6ej_!_S1s{cFnpSs$+!$x2=Oyj$g&A3Mx#D4bw5x(|Q&<;xO~E&l2j z4@9hj49ILeg9k)J9z)*twYS&xSLme((W?xAA>rGYqMIA6F+q41@Jr&+#tBnXTT9|L zU%j$s6l{7NlE5t`H71;eSk4GZCw@db84O%2qyl^{l0fi)T8_k&W7s&d0tG`Rd% z02w+V(a}m^0Du&7WB-{RXw%T3#1dK^a^gN8@d4X5$-xD2R=oPpO;Bfc>!U~1#S5_| zw;K%z#VVxdhm&Ow=spL?S^z7_J3BM(;z<(~Z+jA|x$^HvFJe1TIN(=*=w`jE9ax60V{;_)3b2A{AwPRzq3+f<-m3#af|lEIukDxrauQTxB)O18 zo@j-O(n6Se6#Yu-^HEPArw_neQ(d}rwmB!^J{tCn`9&BA-3rFPml_c4Zs>tEM2JW` zep&U?vzvq=ql{r7HGl8>=Scc10xFm`-#O~JDGiPc#0R< z*%!zQ)tG>$^nM7fkW@%R^3x}zt6CBTikvfUF%68Oe%=C!77n7R z&xZ~nJ&qMh-BW;1OVk){M@BLug-y7^$lMV@i0G@`X>kzPPxl^a09IPxWy8}JyB{yrQRS*c@N&N;Z?v~CTTMR8| zB-vOX{V};5S)A}MmrU^s0HtAdqd9H}CI&S5o%(1mC=kLumP&>I))C_k6xbQ^rd}KmrDc&> zb;HpS081z!Afisf2JQF=LWHa%+C++rCW$Rk%_n+KM6?xvl;_|TiHHZHQkk^t$D998 z_I)rs&WLwMDg6Vuv1IjEVQn+0c#w#?Jy8u^u%SijAoeU0m4iJTz3Otx+v(Hl$P^@5 z2$c_*081hf^*YV+vi#}OBKAMeAsx=*o1URf#vot|Oa~ywI+&d=d~A_nMMPlV_;@{( zw1hFmlp^GUNjDXtJ4eFF?LXWIAbfOS@K%4ZB^LI^%64JD2 z<%q8vU^?QczH}M%QZ3*Vcl_N+2RY&F$V^xEbMe^NUBd{V)h)1oj>Z*@KDFOR%pt!MF|o`0CK`2?#lH&b+w5i?UOaj&3~rHA}-o=3Kz@hajWIZJ&%?-}bIuzo0ff6=TUHfu|)-F0actVE|8U*vu zL*VC#iOZlFTBGu%X01hzf+8MKU=oA>LrgcnS@213Hh+U~SEQdC0!k-&NfA+=>A7Cm z4G}4i>Q2IKUXW}EvC?}S9A?gbE9BXXW*NLawz9-aS^5YrSIReOL-d(r675~o^P&!e z=dtO0z|sv${3T{ls+DdEWF6Z*NogboZd?H{@vxE~jRv3VU2y*NJA^->OhkyHJlramk#txoJIySboY#~RpBT3{uzRutR9&YXc*fe7X&euP310}B17X-G-N z$RQC&^f;kk>@XF9#g>Pc_uLq9WA^63|uJXttSw8x% zzZfoN#mdc2+HxSnmFKZN^oqtL|IoKd_2 zCh@F7fxT_d9v@U0r%`E6Jg@oJlw=1}VClo%&3kMo3lM61{8gRS1G(qKHiIPPFPT@Q zEF^~}f&m*-KxRzrs@Tw%e^FuyL!1A4_feJl7iUcMig&A%ly{|Y&xRjmy(3+@oFyf? zmU#!^PWo?>hldm-cSK&^#M*@r;4KJ*g=h{tcC|s6L3(SM4Pd6J!D#YAy5xnR=9XUh z=L+b+3=MU@d{5dRjr2cFsX7aUbZ`VyL)<^0QW9~%W8eBw(sAhU;h!jMx3e73F4nH8 ze9$KRL1qGMl`l9XQA62FC2OnE2zkd`5Tv3Y?YA5oVi(|>c&i7XLK2rHfmJWm-`;8n zs2i(rxJ{|5noXeSrszaT_3D*<-G^1oQ`n%TMhD~ko09D5G-E9b(Cc70TLOxF;M|X6 zV^!eR0j;9OK8*__G)-}FahkGwQnNWyj8LagL2MW%_%}i!q#@VYX8oQcf*GP+R!^Fm zGM1MeBvMmp_m#wqd@*a))`c(+hDR{pL}35|;lK1McHBIkKo;>A*u5Zz{pzp-bOhwr zMBE19+S=-ZG`F&3S$jqy$oDSkYMHIx_iYEpvYx1~miZv~Q3Uj)#|$ z9WD10YCLE+?Ci?Q%U^W2Jd>j&Nq-1<5XEd2xKzzXTR(1R^Lzjcd78Xw79ae>Gc`QF zv~@qeb<(|@H=NI6(}?weruhaEaj@G1{gJ#E3pp!J+Pl~tF`8oGnXvZ{ln$t6aJXr| zxxxM=d9u2i$H%m8pWxBXds9shJxV=4MvDDHR$|$GwgOk}@D(M@U%%C&|PhZv0Kn>J!H~m-c0$; zJ@@0}I#jg+3(s~AK7|;v2k0GbeZ?J&j6%uoj(TKH! z8vf}#7gz7C7fwxule~;V$M4bJWzrv>J=g8%?2O8F55g}sG)PuM8EyjF4SYUYx#8AW zpW00Znwhy+8;Nj}wUne^Qjaxfot=~kDExlHj}}(Dx5u9xVP$2tXnwI7r#y*kh704W zv9TP!ayd#Y%SpcaNE}TNe4xa_>Q)-lUzd}kKyzgaO=aizV%Lz>l`S(6Av(Z-2B$cC zk!u^J%ftsiI$CB0HaE9r2m50g8vX4lbjbfd_B6r|RtBtX3Vtg6OBpv%yTn4F)4R~3 zI=YdB@l-#$f@Ab5kRPPLhr_9i0(oI-PhI2v@1FO%a-XO8P1sAYi!l%7>qtV6WZTR! zzj3^~F#O>s6ye95M(NkV)Z)tT^ca=-%wVQoal{9R(!6M7X8_46h<}5WUy=lrBBIj| zP%Y#fWN1KNANvk-G`usifY8LnWv$L^;CbDWEzb&EpB1Q65=#Ns^O21h&~PPs)%1Fm zzqZHT*~aZQG3V8C9NwST*C)64IB#BXaQ`pStEZW^Y!N;8oHp8XMH3<_{|_HzNwWwp zbf)RoO=vU(cHxu{{RjIPA2L->W1tG+ufBX7ca!(^vuQcK{dEpq9giww6i7nW;zKr3 zQ`ehhw~L7FES(?ax^8BsBnh73r+Nkw6uBgJfLlQ6Q-Npg%(ZJtq{2sp3{5^}sT~u& znH>a*Q`IqZ1xLjTfZM~iHU~>$j{g@#79YQ#TozCOEt{m4H`Yi3CvybS}qtL8unLh@}G&yXYT3&@go*lamkO_exKxj)pqc|JHC{$I|FHSqL z&8Jh$@b=4l`g5cHW+xrPYbs9f+GS@r-G6^|qubupT2>95UnDG8ZQBsZi^Itqv$Dph z+L%N}mQDQ;qXUbcPc#zD3JNdcii#q3ykPTdmX|mFE;V`lc(2SL0>b{6K@T@#-{hpQ zcS@cTD!yAciz49fyz(DHaiJT-B6X?xa zW=`?(ip(qY>oV5w3G`ilxIMu3n@P0~)k`KuV;XI$lVLHeu12I?$w8^K7MVD!0O4H( z?0;hw*I=0A`wjp%@u$HR&2vNFVV(6(P6i-#2D?mnL(J8&Y@?T9;p#Nm6tBmB^HNgo zM{q1oFAV(rd!gHNF9_je)a8<)aTBo=qL>x~q>coCV~)b|5{1j}_@>T?u-gf=CJ|Bg zu1)(3JpOD2wcpvb)!KTKghU|*YnosIk}4-a`A>mlUP z9Ba9`pw!XY`V=%697P|{Vy?M+ibsIbGc7#l5g?RY}@8{ z_4UmxEU$k?n(+ob_*m2M2t^p$hyA^4cx^d3IigpXRoeg|2rLF;P>}!23Hpgfis#DP zJd@7s5;guH859AW(lh^uiqFo@UJCoXECq5PMz}QZRI2qEOT}$n@c$%e{0Ti@#kX-| z0K>L#ZW9u3qaPP<|2Zmm-m3t*67P6hIjMCxqpCFV&8Sm_oXw;kfics z2pxwAZF5>^4v@g~`8U{!$S|fD8_o3>7L>O9D@Av}z)r>Jcg)T0x!4iLT4}e6fN=et zA#Ss@sRadcyLbD=%LjU|&5yS%JHedViQ*W=%H4*1TuKF6S~!yZ$P7n_oQ(g?roK2! zb85OpNepe|T#$)7J!)VhOG{pN54!Q5J^qLk0J?qgVzYGH8(=kPu;0DGz9?fUwf27D zw01{k|If}Gj?9ak7a8{n+4p{}cn!rzjS;g2*v**SD$ajx%gK8;F~aD@)sB6_M|^Wp^yY7N3Fh@Kdt4buebLF%%a0f zubH{wnC?S&iq;ZVZ|1N_e<-%QeRpgjq55<0L_!dhYBZ=Et z3%be9#bpS=K%}>a;q3VFvf!oEv3EBW`<^J z>O<+6n9jn5ctPS8_H%Jkzm=Ew$6BDCt3uP_@8=i)^5xHc;h#p~WG9kp?8}Dly=3mW z&3@ozzoV3)Lw9SG{$Q-D@6i*>v@+`If)qP8hWF)LO)b8h9|`8V#7gK=IBklhfy zIIaX+4&vsKh|**iDDA!|!p*HS+U8d5w9XLjb8Bl+2?=}5|2n`5TM-~rxGfr8xco?=4Dn+4^*69{ql0_#c-i!`^s&9Wd3@ieFj@xgCmZZ#8BWtOxlER z5B)oowy--X+Ei9oD@k5R-KXDuHImlLcEbqFcK{)_pb?68`M#2scO_MW1Pp>c+xh`L z5UKuAe?Es{QF6u%eb~qL_Apei1SiHx|8fQOE(v+Z{(y?)EI3{M8F%x1L))OFyr*OP z_8tB=DsVph;Jv)VN4~$gb20kJ*JqNUka$9|w-0<}ib3fKw1{f&5HAGA^A2u96G+SW z*OabsKx11#;`XnX$=`q0346K6vl-bSljoyZ-20$+ZdNB&W)F>g1K#TZ?+B6W(%uD! zh)LASsA&NLoe^5Q+AajG0jx{#*r|Z;(bv~+ahmX~>F(@=TP3bm9410Unew_WTq$rF zt@!Cfm7`s>b3Aa*)5Ju&FQqbDY^-lKwlN&B9duk)oETlp8bI2b+o(k)#rl}wg+s!byH ziLVLUX5Zi-&K<+WF57%AEAIjcASoH37o+q1uJyb$mmW`5Dg;MZcKA*-}gDGJ!8aqhI=kd zC^7z}cg34yZ!{ zDjpMny=1N{3XHkfy$d*=e?dfrEvgBa4d0#C5N`zPb8y_nJA7S;08UK?YeL_g_=7rS zZ{NFj??}v;zUN5tsD z?#zGS7kOx;;}vriCQ@~YUOjic^Kt5TuORn1OZTDrtL~Qk+$t)PuVaqc-38%KBF4aP z0myIMHPmy^dp{~tJf`0lB2d9Yj|W36DHL0H)&D0=g`=bV?q&zru-Q+^V-S_#2v-l} z5pJ*FY-0x=&olc#c#%UQ@*k%>x=O=q6j!VNI9c!sJ$eKXSackD@{8j~3)YqoaY`Q- zG02r4(g8g53ko<0ATggnVQqCK?ij1=FP3(L5m`(i!BdT+!VeSV6PnL0L7fVzlqo!F zyLT_kxD7Egw&jceaPfV<@Zxq#{A~`#Y(pem>R-Jj&Z7R%Um??Ckb96jry`}fQ(%9J z-;UF%0UHA1DL1r8wT%6q+|uX%$T0J0j@0DL)V^bq>Z6Q2#~97V$4BCxdLx!j zY_``02ZGk$R}i}pcN9N=c}yq99yQlyLCuz zg45_G;rALKdPQ9Sobdc-@xGQ7u0D8z>7lz&P*LHYy3ZET{+jD`^ig)HJ&*SJ&~g44 zzG#Bya|q*1&z&;_I}S-tI1vo%f^h%Oag-7xp#DO0)N8}@u=`j!Et}o z^eOHZdlCRKkQsh3tMMJ;ZLQglgnBRzhdgdEOqK`?e_z{Qy88CanKCGKf|1??TmVeX zqPRu5hO+YYo=!tL=B*&%-dHmHxw~POl~qE@igCqxGO72qskOzoXUxx^pSSoPdkFD?0_%A+u0CptarcKi%YEbZ8Zt6Tf_k4~fyOV4Wlas4;kAL0V+$tZ5Fiu4nb~Y^8JrBjhczud z-Ok=#O_YsXz%FpH(}-JRDX>nhYH0~)m7-2F(aV4-5D2%LS~QmZ7&F2IlUzSC_2@zSVQtD0 z;Ur1|J18x3@Tf5ue8oB>8SB_H1qd1g^8UcLn*&_XqA$6G4+h)Gh{5OZL)u^p*$q@1 zH!3&hrOFjA_6vprfxh#hb#l4@5-H<}j|LPF#G(KO z_5tWJB!=FCKvg)+M8rd_h>aQb$k#*P_T!W6-fg~BK)?rtcCn(aon6jwQ<*+4#ou}S zH&O_~FWhqVj|LpF#D21IdX~4yQ6}R#O9cu|9@T(ArSO2-Uv-tSVFxP%W27nr z+cPS=kSZldNrKvOq$a8@;8M0h=|;4p!O(~!UY|qXYvl~4{Xc)=UduqWw4)osB24sf0%I2)=k+bV#TjYH zQQ`vZ((eO4ecJtG=gylW6IDbPHmBMcx6neydpE~ELBn#ug{-_*L8=brh zIj6q7mnvR4!g4mqIQ-e?%zk6V4I7Ea5@#z$e2QAN3o?XXK}&$?e$a48%B;-pGVsXX zeWmvx&de$QELDNR$AnJ5!_SH^y0D#|sx~af;fuIrsi{qe~Wi1tTMSr;wBA;g)&Rbs9Pd zV;h@#KqxSBgl0nSx}D`Pj$*UdnC=b#pZLSTLJ{lEbqpP!dFX6x#@8$@2w91H3uf(z zxr3vlNn6^QhGul>)`l`6m~$D*D+3=CzsTvqmKypwL1&t2jg17&!H%nHJr!6If1;24;P zoS@*U;m=R(Ysck%y&mtW2D}0y%Zy|(bIJy8 z1nrZ4G;m4%WAX<;pBrnTipUkYA={-yz6OWGZY3Le$hpj{RhuQI^|a(B3*l z(ZtW|_looEjl5jW@m9VIyyrgEa*WQ~=;-LYZftlY%)!}=Xv;5(Tm##vQZ;xnPNE8< z6;Xp7<-Z4xGU|xWxA%P=1`j|K@ejV|*#U18z6QtDQRTK^|M}}PQ7x_EwpQGtN2R4}(i@8bu^}G%OES$X{VU(% zch`obM+0^;?o5t%o;huYbZ-SS#_0^bR?yAiI`B<(Xf{5 zsfVyqP*{i7*&%57TKC}w_Z4v;m-jRX$Dw4$Y|g5R(}?dwYMEw>QomREcddC6*?;DY zD57lTdk~S=^}Z*hr_ktkr#qPbGBgf&B(T(9BqsX!`pPHBEHWO{nW{gUZs+Jorp;{f zoTU>NV>XrBA6_#|%M$Roj?bVtLeWRATXgf5E$CwFzrFXG`a2|UZq+e05Ht;6A?nlV z8L3B^nT&BB^ML{3D$GEZN+6^enpiX?myZJ_D% zy7<|vXM6b(jcb3I+0EYJ^0vH`4Aaf=83`ZTI<=RVRpJv8&<2)hd32N#&7R?(>#6H!W)X;ho9D2sdlK;|!fMZX?t9xV% zqgcMx)|8nHU&z!eeN?)pkeBxpDbPcKw_*aJl`1bkf8y_f$Mw-N=`*sfcR}HBad7kt zhob2iJLaWdqbd{n`g*Tq`>V^GXC#=AJ$LPzFOs`cHPWoz;THb;GbD>psgMc$+_Whk z`fOP~lVMAXW^97zckD<_Nt0XGCN8e`@BxAz6{uq*KFS%McM_)x2=H@ozNVwM*LDx{ z#lv1FCRhFmNbBE9ExTDAxaX{q5qDi!%-~Smcdz}E^lJsLj~+U-ROhF?apT7B0-KYi zo)QPRwtn*}4g9%f4*-%kb_0Z9UN)T6`vFY=$*g$aX_KrW2Hl}ba`M2$p!{0;C8OWk z+HdJoX856$U5PWQy@n}IX82d?_QUUkkhsFH`1b;f)9JDYs)z~;=X{nv(B?IG= z_;|NbTZwd^on1x6Uej6gver~4|3KyIBG+teY|y{1edri90vM&ik+Ua3DSZBX#EqDz zPj!x5|Bd0~;ZHvn1Mx>+W%OS_$DIHRE_C{MAP zI5z9f;k50YQh0X8tJCd;!U=cprle;4`rh7tI8MwbC4>iVuiA&qirnWZ z2ir4zEd&pXi+AN&RBybJd|zSZ`eN1%r}0k@nS);@cf5ACp;4ef%?!9F6tY5?C1H=f z)O8#p)@F=WPyHItaWwpLRhaeK+b8)kdxJ43cY(U&Q}O5X&ocEZM;7hQDH`7l7urru zeJxO}#%1MSpPE+H^HEEcp`Rj5yJuPt1uVE;^VNeD#Q`0;LNgfa3IECWaYls|+hs_253~4?TPO z`{N53S7+GZpC>ISASW_S8o^K?hEp;!5;4yMA~ZNQ@jquMxs;QI)NpmH&{u(+tH>7$nV5*)`f%)EqvA3wo6-VbzEQCmCWz&-3fkL2ZFi%Q1? zA;w)pH@Yt@>~Zu1=zw@R?|rnem^~z7`0CDjowhdK^fcbQ?0DCXO!NAvGs?<4ChNfn7hVD^tpqwkzFsftnp#Xe# z5Vf6)HL1P5?)cnnC*&KvD=X}%t%Nptc)W3Ec6ZPIvj9|R^oSe-!|e2eS)$yX`p4|% z4YA6Jv;-}zXUMyL1%cOH>M@0@o?Cb9FvZL|UO~YFP(b}JnarEksmu+GejoS~2nUc| zu7yS&$tzUIKX@kTMC{ueoRUU1?%VfjkH}+;yF8X>uJGl0uPmjX|9T9RRgJ4^YR*xi zn4fpVP_R5T{}|fC3M#&>8j6liqWl6MPg2%;%U;&$mhF<+zAxaljKkn|?9+fBTj1J3 zmm+~V!mtMP17*g{Bx*c6aMStg300$A;@5+<{_M4D+^Dk%Jofl8ZIZ6;%q_$HW#Zz3 zd;(WLrDrKhaE?-m<7fibx1+Up1db{!qo>PH$-Lw}wiCX(2`ml$H+?q8<=PHUhw8)Jo^N%34BCX@p6!DVc4}ysVb1`JW zE~xbMw0GC6cFBe~nHl>+On5rT#+LTZv2QqTrOrgmFUYLF$5u&oJKQ8c>W|iSmaef# zIWI3qXbqNej=ruwav=)-df8K_?jiqigVUaHoP3Ay?j+nBoG7Mm5P2w&CM@UO7_Wm7 z)BV74VfiNKF9OOhJqd}lw5of3Q1_UY`bR3vHov5?X=aEsE$vNPp|BLj&wD6rU0yzP zOp0@l#FOr>T;|f7IVK29y|#U_SiP#iCK%IORt_Z$?>ST^8^h*iYRa{dV*9$$BSOGm zNkl49l3_Xsn*80!W1M|@9D!@3#)j(!yfgMy#5YDHAbI1j|#i z`99fc-WIS|O6pZz?daaK+qZvcpjP*}%WczrJL4cG+#V7SZ4$WDc|o@>HrzmdI(}Qg z8q;d<>yGyJ>r;ycLzT}Tq^GAleujlqIl5gGL5J2h(PU5@5xS_Ql6XV(lHfUaix{qh zU7wilai_8|9Xc&7?dDSX=DQ&wf7eH7XjX3H?53@a zC@7(go`IfST~m|D+4%VRjq$`R{=05EP-V%j@)fUGL_d*{kbtqdxdGeJ-jS%vT9;Gk z!emxE7tXc+x=2Kl_=}tp&Kti0D*{4GDgM&Z-j3`>cNxGN9OdUB_$v_u-RHhE!~|pS?w_^zJvSGbXR`Hk z43(A^cratyeVN7%xWyO;J|1LkvyWkZe*SB*t9n4K?_1tB;H*fa5Mov5rQft^5e?b- z^U8BusY`ez9<@dTSIrv+@Q+mXoSG{@O(9aJa4fYP3KijeW zL)rS@zds2ctnB_)(vT8|VNmYJJ3>P2J~dD#;)zGl236);ccNgKZ&|eP3@1F zKBW!tpXQDZGgxo+FzqC6tYa(1Ed91HkNL;|4%Kt#E{sg#=3--+h&w-?is@D=K0F! z>;qu5_xR!#cJ}zh#2Tc8z3e}6Ic{HkEP$FVjDssLzaXRzwaEcfHf&uG&qM8DePiPJ zsePwUe<=JO_GctHPLcaAcA=4x__VYD#HuJ(CL<1nxzL)KSv@IRIrV_IWaZ)1w1A|t zG7&TCSGs5Ic}Ewt6@2Q9V&?XkU+ltjY_BpDH92|KJ+ZD8)|?q%@pCY z_Ja*EJnyUTzRkz%Q!d2xrPL`ujgGFX@ZZIE?!3uBLyY&jHZkUZRE)B&5(l^;)jkmV zw5ce5o!%9r{?kH~Cl@Xz#5;|h&8J@&j5{_02#qhE9kLg=So>p#iryB`y?3+Pdg_!i z-vv&L@WUwu_?U+M^c7kyC#QUndFop~@z>Qe*d9CP7YyQ)6Cv#2Z_ceJ1{t-Sr?)0} zKJ{OI;aP%QAM&HG(-|Lh+asp)s*p-aG3oswW0kh7kHkDK zW@sTEK$v?GBs%h1g<{l09`FBV(WCXSwS#Fw+AToYw)9}Y+V+QP{Gly#bMUE6-Kn3n zi1%E@%kKVX2 zHMO%fCxKV*t%e_9qc@&cZhp-lRDH62wYlL0c!PW^uOH<;7j7*~xHR_WAs4Svm>#bQ zVIX_axn7H_>91bFF^>rvIDmd6N_`DJ9>g{@6tNp=T0}`L0-Xqyy~iXaflS}9W#(w}&s4#w?gJbbu`DXZ+@J%HExgkOoD5(Hi zs?5#>LRl@h@!i~vENG|F)qiXoHm;0x<~*o%S-9>zc>>lUDU4tX99)1b0(&)vrGU`8 ziWWz$CwQRx^0ZmJIYc&?LTCv3;c(&W@~agY0b zEd25Qy&X>2K<^{x*pF7u578WS^z<0ze4H#ONaSs36}=Ew_@5vALT_cqoGpjG=Vfkd zYsbXK^GZr?hJBT)8|UZiD_RmMd3X-y03}&^JBV1uC&fhHjJgV%yZgs(&8DEzqK8e6 z7NKA*f1%b6wSWHo{R7*!TD8w{!n>TE-?o@x44NNyCFvBt6Vr~PCc@ub&vFBwp)ZBQ z$>YiZ&|FXGPS{WPx*)z(orKC0vkBaORA2?6AL5JgLR_oe#8-)tWhs~GhK2&;!Sh8o z99x4+HbPh6_4nz*t7b&QPj_31^$jNRl^_fUSBtN}7&##=Yxvg5a-ek-Yt_v(rxXq)$G%xsSASlP07tT)DCmuId^T<(0P?_p18azU|weBCI_c zzrA*=9+S)QJgk5Gf-^ra59|pCgib_MS@0t*jUT8OmzNu`c{E?Zjy?c*`TCWETX|<^ z7rW*f0-;~bQunz+5H-p1ODu6iyvdbd@$qq7tQJyRtR4v{o-)7m1r5*gQY42*u-VN!{s?XR(VX)z#D#)3r9Jf6>7{Fqz(R z`F-_$wbZ93O=xt$-4L(F<=ks64^AP28}gf{G5M=!j5ReGJUu-jQ9N|*;gcgamR!ux zv96Z<$&(R4!D(zIAaW=j%?GF6d(Mpc_XMK@ET--sLh=O(e~%6vi~7tnDt72})Logl zz2o1$je?O2GUf(9I>l!(R_BzIHjfIjsj8*TmfBPSWcl6Y@L0G+J0KxJI$g`75jQXO z)hjX_5mpj$mN_nHaDgX*yGF3p4&;iWI)=&;{6wc{kO5Vip@=(tEVOfkm1 z?T^v6tGD03--uYN^`qBmU9RnLZ|};lLnOv!fYMwtYsJ1`B@r6!ivUEFg64-qULq{u z=ci!u-Gbr7HUvNANnPD&z-yt!J-C1;+cEeB$wY{O^#)9iwT}TWn(k9&F50?BL(bcR zwpcrsw`5`5Q?L;rhVJkP^J}Az+_0s{!bu7Z0x`?Lt1X`u4Nn^4jjkb015!F9i=x8B z_?riKloW?pksk?CbE8w_xiQlV7cZU!Bx>M3ZHrRK3N7nR#73`&-bu6O-Je&vt~2|> zggkIx%GkWDt1%UaObYJrm%~zmLt8f3m-PrX?oeSKBy#L~N>LvfBC8&=6|vcl_uNW(=3 zBZs|P(txrIQAPDIh(Rd{lIAWkzJjwkH-rWI_{kGFc;Usx#i49%#>`a`-wptz2E7m0 z(iG&Dgd6gfz+Pbl@{%7u?!vV*=uFUKxc%> zU}(_gbanSAD=Uu#&p<;3!KXd;LXzEs4Y|3s^#Dc%A)por0tPjnNf6$E{2k5m`nXGo zwL_K-Bcz{DHIb(TYSY9QyWy)pt*%aDyZ=D8`#d$(A2J3LZak)(AlISc5rdQr;bFdE zVT>qVKJ@m&OpvT}J#wyfk{N*qv5R{AK^st&k#|I(6m&NLd59dAp>p@J8~eMvyP@^C zFI>936R?M)qa(?i$ADrr5$rSwF%2f4Eh9r2`v$gV%z^Pi3Q1^q&YW0EW~S$hUE$LF z=w85-QJ|6{SFW$$0Ga}S8FoY#eFChQV+f#3exgtW5)LqHs^vFaAhVS7D~(isn3hm( zivraI-_Si=r=6(ww?abTIIXDx8?F7&OGFGuf`P%oftLpDKmxX5D`{+i!IUU*rt0vp`fB3pyRW zqMgWO;ujF;!hm)n1;P{>+1`*#S65_g3;LyCqaZ_EKgy_IKXpZ<2V_=CS{jgjCIlB? zd@-8*WE9)Dm7wJrqM|_1TO&@Ssj2BhZS6L|_#}@KB(|cHlQ{9UlTPC#y2^wVL>V2w zSkQmgA2FYpAQRz0 zky!8!tIMt+E>iJfdfbF%mg7yvbuiA0wc^t!KTIJ6J#;5OUmPP`Hc?R6W5Q<=h*-YI zRTE)zE8$^bX&Mo(u{RtXIFBDMZYDMeTzCae(;^sCkiWL3PO+q2q*l|Oq4qd5D~Hs41()$UW2JKGznhJ@#^0pKw4G5G&gp#85#6^fz`c0%|tzyZ<2S6JXnV> z-+ggE+98ukeXe8`)?mvRti~6qsS4O%p>HPUNML<~!dB&||3aY1y{|hyy!F3H({FA( zZ$5%YxaturQDpmL7`e%fpMJ1NUwIH7z7s=jhet*bo+Kmb{QDfvWJvi*?lUSm5(Gmb zlE3I0Jr(A*`SEP+dx z6;Bh11{fSHC|=OtDHaJ4MhT?pn0T@t&qx4{!=;7EWJn9)=UORcyq_|;b{V4^H(|Gj zsw2@|U=IFD%+B53+QpA7d@O-5jhVcCSW~!*a3oc=w)!#%WU_}-`O-`(19ZgtBJ;~2 z3Iv66V9se_XdVBb_ql6kkx0LVwL1sXk}kaK1kM3wEncW{p;s*BXf99;WC49fcz}p# zj!7H8gnbdbdJ`xF2PP&mIqqTa`+}yHLhQ|w|G$RSI8!_-P;FLscfUOu;Dj}ss;!3Y z2#70`rQ%KOc&3mlPRqn}KRB4rs{IpkrSC-RGJ&vyL|{J&=Yyd}P$!R4SGPz0sFX|c z!=l_Zp8AIl--XRF3D`U7+J@$4Md!)+4hCIAm{#R!1JrU_lv z?A#nPc58^cpl~L-AUrH+1~?DTZjXxEh6F!lcto`eteL^@k%J%FXFgr-R?X1Kwsa=M zrprD5|ET-!f3DyC|4N|}ij)SCkr5(E86nw(A`P;#l0w;3RvD2^B1B}BO4%iQCRFww zA%v3sxnJ+|{U^RZoZIP~o7Z|ipVxIg9{2S)iyPvu@9rd}787-A(ViNqlXPb9SVZJ} z<`N5+F|CoWt|6Wqw_J72mcC&%&XVPvO~CP?1>uxuftVXANF3fD;Vj1e{?E8{^M8`c zhq<}OJgMloa3%yU^fP)IX11z7X?Qg&P{YP@CEP6W&&%QLq_in; ztj7@0hAmnK9J$O#&FN9;z~qC2zY*S@rsn2@{B`j&Gs=s9_bZcIQtT>@>Jp>okSL@E zWyaA6z_NHL86%9Zid_fssDJ~vJ=*tssdnE|P|T9nUqni%scjOwLEY^rcQ5zvA*2ui zEA)SUS9)negbX+!Glai?=f-WoeF3gQg7IxnW2+60iQx^W!e(OJ`cea8zw0?~*bY1s zu_^kq9hp|22HQntPt>uSWtxvI+e?$J9d6>;0skHTAbV9E|voIK68+tjpKgZ_d? z5AiUUBCL^<^B@JnL92pnumz?j7 zH-?@8gM;f`mwvs+ZgC~#6S6#fBcuwin{ zDg&cJ!FSZ+>&DcjD;ZaoC@84(U%0va>!Y&5n0hnd8l+e2?$+mQ+kXlJh*8lHOFOhi z5|Zy{$I?+$mcFw}!r6aFW6QiL31cUD0zW!DFs@?f3yti9$h)Nr%I6OOjBPYK+FQ6(us#*4avdd8}puyMH6Q=S-}`!d|dVz!9h+xWPe+NC=Hvb__@owUJsFmpV5i9Ej@y>;4{($P|=+Iz2eRU%Rpp}WjC3FB7WOad~MZX=au{_akut(#8DVx z{fN^7P=K+p5$k--;@+C1O(PS5!)mu zNAY*!cLfd;^hdzyKHf)~dEGKU-Gjv~Rt}A~kYxgBCo1z2-|P3;e2FGjR(#@ar=E%; zHQyK1qjGsTZYr7uE=WXCZs32A{&{b`T^J_#B1UUaR1`5YZ{NLZ%WL+8^O4A(aD|DP zcuTolI^7@X*;Dsl!VggW1r(D~wGrIB81b=}_ZQ+B0FLNy5h8o7`HESM2AUv15ga`W zINfwIF5GIQt^-VvZ*TEAQQqS8>8hrd%T`<+=u0@GLM<&VV4i(|EdjSF zTw7fVdDwSjOzWY8VM{9Jmz=uXso2>SB{-ZvUxMJI8>#c?x+0)_uaJHH>Ia;ainNb%P)XfZO|sj~d<*I7e}u9YOvF zA|Gxx7K0UoUIJjd)pn*7@62Be!Q6|Rp8GvJ{?86rzoS`w4ujEY1#W4>vwhni5@k7w1I<;NQ&6I)Fyp3gQR`5nmL!Ac`}=H%@FV4*ns ziOLeyu+}PRdXztj&%=IIgeVdoBxc1Vt4O<^)pi`SP^CmZH_50bDdup11Hyd$>eW>M zRWRqEY^y?B^U%+)6jph(^CS=jYjyql_45-}D~p*l%roM%!Rt33)r9tvH+rnT6s4-f2o)XXHi_X&#U}yd4CO zX66)^(H60)-!frb#U06f!r(bm(ehUx}mKDdB#!0~N___!5Xusn}YfuZgx?dZU-+Kb{9 z(_vEJ<$|2Z#r1ESnTFe|UJ5t=JHWjuX-0kg{V70x$O%LeCJ)`MACMjrg8>v{-|?Gw z@gOLd??KTD(bYjDc42cvcY_?VV>qVaVD)L@Uuw0cajl|?u3zT4T~V+|oB$qJ$lpth@Ei@9~@Mm54` z{A3eInSuHV$G9Rs7pEMkgxK{Il+XUXNqI+q9}UtiXi^XXh?3-LbqHsp7Y$2l&f4O5 z1yX{&as6uX`G#=&-<(D+JdeP-}8%kzj@E*Huv}13y|vV$ExkvxZj} zR+nsEzb&k)73AK&d$e|WVfMW22!gt+8yZp|+mCwk1ThfLC!%n5unQ|L6yeE7BQnsL z$336i99o6EYbwbip>DT%CZt#qjQFi(tFmPYpj%)_Xug$7g3y4Xd;{F~JU3S-fBi{u zaYJNZ1H@ygy&R{5&GD3)8hvd)E%R{kky0!3&@Gqay2jks6J!`BGZ5T z{53Iw*spCs51do|_u-93G z(f4uSfk4b5{gdq>nXe=aXPEn^T#($e1bcFrjz; z0i0}J!v|8~3BV4O57Ba;ri!S3O?Xl25C$=(1t5)kIc_qU&L zn5=_7s0{(F1c&}N-PdUUu|ZlMOAJGGP7VDqi$9FPwW5r>bisw{gg<*z5Ng$`Ao+b) z5hWRDf)puIhGJGE#7qmSR1?eEM~@zLobM{RNWA-^&&-S^YLLhhnq?6op;HNG zgAs?6yoF>}VR9FmaWc^huTE>wTiXRzq}zGiI@}oOVp*ht`|=B`30;pg1r%z@VF&+Q zJBzlE%vIHZ6BH5`=$gEgm49@u1%CiM zT-adT7(ctGfRe6y-=i}<geH25AcBwQq^cvoTnG;IZG zKSSx`ERLIJ3t*fKFa3B*d-tBP2XMF|pBpDuX?Jn7dHXpw>}v8b6@k=6Z3}|MEFqb5 z7pvtO&ZcIL=TL_doV68#^Bv95l$5Yyp@z5-n?^zGv?TN zYVH>ii7;{F|AgXTw^U*FmzFSpY_G&|gAYZhC^3U?*g&6o>5^1#ofVM?R=5lNG{?Ey^%eC5oq>SHm}sQwCxPsw7X(rY%#P$RTB~uFZ%!TL9z?kclGsA ztEePZ9*cYt4!m)dhe8b$`3-y;1SyHSg1ZbY(&&#J8)oO@Q^EJLw$8-Fo*eSM^xkm! zp~1&rLL8eJC3#7^tb(0}<}GW-Fh4P*g8tGLumc|_FtBTENC zo6~c1i~<6S>;kk2X*`ikQW!C^oB8J!YwK-zx?>cM44OT9{+xrb%_|=$Q7jve*@EB(fl}j^%ss+A+Gr_y3k?o;z0t1Q=o`Pi3!bFxCUO0a2h=E~Z!S z2~gS##Rv|i^E(=^z~+nPf#P?qEL_Ls8v$F9xr>Vyey9!JMs)M#shUY~ZR{KxTd?$q zhZ*wvRE{-&K-M7U5y7XFRjnZsq}G;>S|czvF6&eQ%2;^%n^?`FD4!)w=;KlsjGHnOx-K63_9&7Ns#edNO*Lfz8VChFw{ zM+gi0#vm6(OBUhAr#Uv@;SQcDR6J8*4y@$AuZ{@h`_-Wa+*0nxD<3VOgkqTwjysu= zk%7=Sgw4_ompv4*G+oj>OOH?R#L)M4;lI559Aqc*rV}RU%1B0YDO@ zG5)?q_cQO{$&*hY|7iF^90Og?}o%!H9(+R(TIzFL=%d=7u z!D4{8QDjR^CZsy4N;KCc`Fm{(X?r+LBqqKq9oJc-4CX$Pdf>**L2) zgQ}O-vq3>HNU8{$v`X|yXxs3EN`(}Lop68{`=F*)PdNhMn>|uGbp8YPeE{ZY?1T_` z3T*~2dC?x|a?6mlN_5MJ@cp_~Pqb02F(8NFa@ePm45T@?Z$AT@r+;8vWN4@y_&CII2n|Bcn4(Bj z(~FwpMB;uNzJa}mQ2V*Le~TMPCH||uTCXVIuchTO#uWFYstHRxTmar6TIZh4s<-pBNaPtt?17J-@Tc1X+tCBuJs+?{G@XeWf{FEyEglcl*$ z#EZl!nwD67SLagSSNb(s1i{;_OZnH3k#BB(yl;ZvtiKF}f6GmD=SbYG!UIh&OV7wy zhS@E3!}TSwJhIO4$K3$i!z}5%t~Ro9cqnpjPeKn-TAP0@^FC%hhzFVx4-v>W!eA3= zHnj|@%Ip%UpdOE&n>}KWN5Y9m+1{L0YRy#u%~*c66(!B?yGh1$`}Pgajen;D*rh~? zUK{0sfI)Fxskg|F{6Av1b8AO7|K2#$Znd?1X6QkZ!uI_qekfPs7MH&=EGmPPgC9)T zo}zDET~}}d0f{($`Eo4k7ckYxnQ}KYd48~Xg{g1wIrkmVk6%W9ADu-R?dQ-VA1m$& znNgbkG8!tQf79Llt-2%rP&}Q<{sYUfEOp<|5GP@byy)4F9MMGQdg`dPd#i5)3YCLD9nYN$+by0G54f+nTMFZq3fQ@f6K=HS`Ag_O8Qqn`u~C zWF7yhAG7K19DVmk&;T5_GAc|EAFyeO0NXm{b8mgs(7UlKLmq~cotv)rWHr7rw5(#z9~R$+EW1qxA84mXHwf$-@|FqK;0? zUkcu14RR@0?h=T_WbqM2mDygH{;bH4fqymz_z#v45ielIlZ=WAh{CgnT7(_r9NEL& z;4xLwXvF09NEuI`kfngrlR=;mhoeB*CUU)4QvXJ24? z`nX(Nd9xbSlu9bKc)4$N=nFE<{h2ytdHKAcXM&us)|D&uSf}g%O@D4Y?)qWt-@gZ8 zadAntb8JVx7Th}g!ooRvAEwX48F%jlb68l_A-)1>W}4kX>p(lANLr8aXN}^w68Y+5 z0-wQjM|YdnGHxGM2i>z5FMM%!z(&9g8n(aRsI$urBLes`FK#P-@xH!`ya#XyU_`)2 zaFuTUo&0m)*s%z>MtvpxU+hK84L)r*_`v_k)?PVei}m$M9ub?W#H8U{2JzsQ1<~n? zV-7A(!jZaY|B0R{c>oUp0_dEWG{ivmqmw87Ce(DGn66dQ(is^qB__9e0!;gm-ALR# zIDQ}#1`l@Jjw=?_ClCs-7d3Km-Z9+wxOLiki23mc5NOH`A$nY+^C0^x zfIyhE7dSi8*o>kZv+0g8aH)R8(BYNcF7ZH__T#7=hXo6Km!UIvcy zOOeY-{Hq4bo@g@{Is4p*mIu76A2K<{zgZiW`w4EQr7fNsfBN)kbyXD^UdSRD3#xM; z4waAam*R|qYE)EXgNAp`cVHy#Z!IP|-qQih0yqX$fz3^Qa9K%u%Vci_TnQ29LH}Kq zw-#pDP)w9#+b0QkNl~TRK@ivBKHxy4!mIxm>yS4Uyo7a+kjYOeYF3y9V8y|?AE3fv zA{atLkR~@jMS*4*FCx-h^q6Q1f!0iQyy1sw8K3alW&YZ5y+7o98_@+CLui4&RXFTv z7W+cBje>~Iid-DPGReZg3)m2YMNbdKLbOEbG*%uz>5gNl^2^ysKHUT8esI7O)*dDc z$W2_rw4E%|46f;L+FWN$k3z^;Fq7Rvn+a$_3u0j|?J^*MizuwG|ygWO{siN~>2ScIuI}1Z-UY=9Z zH8#<07D$)D5H;LO|I z1waY?O?@#-MyPog6-lCBL3A)W^z57ho9n(TjEu+{E%a`lZTp36+%D+N030$|HvM;FnkQo4>EN4 z(xuwTu9IMC27y;-E9_d`gh?zwWgj3(1nKYmJa*=epATdBIrKwPZi{5ziPXPditwi; zc#v^=^#Z)dqtV%gaoGAbzO3%DNYG(f=!|0mMYrwx?fu{if1-^1<>_mMdJ>7LP1DIa`xFR>feKfZODWn4f z1IVY`i6$>(vEWh@DSY5*A`d=P!F%eLze6~L>ae^zwDR}7ft-2+m%gK6yWIY@&xz3R zA{U{*ukZI4(=V{WVP7KQB4~8wDIL0R78MqfvJVBf2^jo9t^_-z2jc0D6(4APZ7i*Q zxiA_A6^WML()>`h6NMNwJ07E&?bt^kZ-ohy7zn~H4&ERJ01>E`01Fcp!Z}7aNqq1% zyelFx>_)$Mq`qt~#kfkAv45=+7g?fmJO%=HU3fFB#&kHQ+GpE1YfI&^nx}#eO^r{kbtI!x$10g5t3R*O(bEbsD0%L%gch^e2HhV;`7x`a4%f;L8^ThFYdGz(3 zxKf)EQ5Lq9=SWts*=rM~skhmzQEJ(N9s|&D9@-67ZO68OBAZwExZC1UG+1*JZ43xX zr~D50GZ`U+ZVs#&#zsa&8Z?-F_Su+w-RZ-VW1>M3R4Egcfltbp7kZwhr=vLAPcJJ` zcz?4j29;k(N$J1&hgVEnd-H>bGH*0k?XO#t4hNqKj6ChRhyW%9^z_8n)F_iV2VR>Q z&aqgyxo+4q{wocRc|Bm8=Rq^zw9cZ_rSvdLIooSwQuc1nUOi5N3_Hipjc1S2TNb$o zZ4`V14y}ngBBGbezwfR?&#!x0X|AJx7;t)y;$cSt z1&Jm}2mwb2TAEn$CMMwS4sFPWTm#<@HW!e}yCt39`UUoMUHSF&FaOM`uoZCY%*U=D z=hJcZ0Rx5U8zjdKtliWnkEU#W?_`yP#0?j7pC`q!=y7tMHo5i{0*W;E@xubT*>dhu>QL0~++~+wszTH4NHOqxVDpwOC}I2FT6aVM#zJSHf(HT(5Hwk%(fp~z zxChfmo?Afx_HAKU5s}|gLpGJbHOJt$H@aeA&w{e%_3Ip2g#;3T4H0rM*lSq0YQcIV zC|(9yV`!bhm`|Urd_KH+ApV*bFw;=s3DmVEB_*g>m=IpaggF6)W_M~zw#W0kzf?U|%dK9hAtUL{)f zZFB3+0*47Q<-`cY86Z?S_=Kgt9Fed9=?nqN9i=q`*w@JDUjUqBx-bSXE}vS0rkMd8 z1|trF?cjvJ{?6uBXS{Qu{r-=m_NgCkV)QYF1|hhOBnZ*j(^$p{z;G#uIVUKocETQW zLg)N>PBchB;ed!d0OU;|t+gbXZ`vY;_rHYKmebN_+2;M|P79?!sIUd-^39fSOja@h zlt;=d&OHB+w^{Sj(y2wa5bPUdPO;8o8K9G4V|g!MDgzhQ8yp&v3|)4W`ZW!K5F`}yor7x+USUs>1xo=rEbM>)@J`6uFd~bJ3=HVRxUhe%#8~! zNF>fpl*YuwXcaT#DARZSEf2b-8sNcN^i)25m3rK1gG*1WhK4$Ic#nMf%3fOL^{?Z7 z+D6%X93R^|W1kJ09PM%6>qA=(GdfYh7#YpXFL`X(F8d0nJ=pJbb_z&d@>VP?EoU(N zlE@n|eoO;Q%$jCAGUnwdDEe>oq@1Fr@#^(U<9WSl6JzaAELH#d0k4hs=O>2}lMb!} znToLatCp6FL5m(c+TK|K2yE0jqE}-gti%N*h*-41uChWkiWRsLv~*PH%Sc7w<(!L7&_Z(plnGVW9yiVO;kFTvW2tN72JzVQ zy#4(T5{l<&`AZO_cx-O(uNuNeK-4Hm>{?w_w6hK73;*Z3D*ox?0d8&|1$o1BdP;@` zcM7i>%G`S=8j3j2<_gO454R5G+L(bQf<;@McS>i?0k{t$7};Vf zFTzT#sspE$OuO>q;Sz;PXBgVD14(6EIG z-5xVPap!uny5a8tHirJyBpYHV7ZN&fjA^*>dw=;Zk70!U+sqXLo5iq_OxtBxKOkLN zYs?$;roa3n$9oWRPrEM%=2n(>=Q{`%xUW4uqVOo#`kK$LUmg2gX4M$O!vi`BnWYvV z^xKV0S2tFgmv4b4Eg@$XMO;5FAzZx-$y(KjlRC>wC*pYX@ZMuTZ2wq(T{~K#Ade#( zVd`GKTbTsEnJoXa(SsVtlf07TvjI`zt<-pW!W$I?z^S{{U4W!R}$a_7|E2IBsuB_~9ND{brLo5H!nU^kHZ$CG3 zB*$d)!uYpag(*JJm~!#~#CgzDrCC3c*L|2$7EtWOFf+?0u`f)SdRy`j3+P z;^iGuYq9-uzQ-e;67xNAP#-l!8e#46o4wpV+tQI$!Bkepu`*k(HG6tmn#UzoC3F!H z&CN)+MYZwbs}A}rh^@#>aBpwKx9MWYIc9GVhhIoYAetJaDFUkoT1MIm=$L`p0TM#` zi2`IFFv6{&*KgIOXRh{%+D)ma*L1CX%Q6s%hkopRa~ApS9mf0i2M)hH?`Ucwv{1U~ z5bu2%&#U7)4<53;`LG+O(#72CJYCoED`C(wL}7EiEhicjo7BInd44wkLeF5=L(qRR zgjw6-GEg3Ta9t2almSVYpxuAss)-500G~pulgB}VV9`}z>^h0;K;H{(`oS&}xEYb; zM63HdYx5@d`>t+HPQOGaYIS$*#U-Cm|8ft-DSo zU@P~<>LPJx5HCTyK|E8SWnpT9{^q2jYQRX*yp&enLrDu%A35$T&VVNtdMR2rutV2D zh$3|B&?;dzDbfC;%=(&Rs-i>*&j9zaV@we00RbY)BNTA+h1K2FxN&Ia`jfRrlXev@C`!n5IoG~qCJx(7O&S&`V<_FtNKD3(z1t0jamn7Z?6p()19TgDCE{3Ra z;N!g&>?Yyz{t^AXz0>AQ=j!D~Jaqn^oga0;Kol<34-Ts#ot>8nxIyF!aC8vI_7kYF zNO;DJ_+qf>Y8e^%(=)aHh-o5y!rr}4DB~Sm8um#Di!>=IUj4Sba60$8l9SB(qTfJ$k_F zV{`MHdk=fn;f4g3bd3awl2zDhm%Wywm-%5j;XD}w=E(;^-2yi0jCfeJAH}KS4C|;Iq&uu*|mm~_|mH0Z; zl-5T#>tWIl*`fLQ1E7-hi#4rPq}^g@oZVPNM5OJ#4UsJoaU$A%$sgsKv!{Q*FTBOL#d}V6L?6(JqRdf;?|B(G zqCVbptBW~bUl-k47tQebt;Ngg%CYo4+gK!EN7*e5h4|Q8i;epErvVFFh>Hj0*>BFj z(yLK73_R4lBbZLGdeGEHeirNb$Q}Q&GtWfK>I??QlDW9>Mj^K! z`nA!PwB{Z?zsic0(-kP9v_Nm5TLPHED{2584xx(}xLRf=3tDORemhHv9TPfq5oC=( zaiavv3~(l?N}x%xMOl%5=a(N~E=;Rdr`!E;di=ZLvg2__diRxg>YqyHS&*=%8nv#W z0b3vR{>(&}MXXQTwk5+N364f$`nGc?6p;j=g7OGgJ{g;U)+L-~!1#=R2z?Uk3F{kk z&b(I*k~)2Q(D`9~kxR1#hgV{baK+qM`4MU9 zPW7jy?h7;dPk!kdw5|lQY8W=gVcrPY|L}w<;o?A|M_f#rf{$Yq%6tB_Wy}w(@_{r- z?RRnIhMabLMMb`>fWq=zGaaurKyFah8Xxk0K8!g0jNAhnM7moh1@`+0J zdXIotaWTEi{1!Au5;|Fo?_Oy5t4);%-dOwl%I1i{2e&ld&!t|(J$T3YTDL5Jwu=MyIV!8l--FW*8OQy6=)u3wV z0Yt!&%9oUt{V=4CUeaaE|60B3|C_CjP5vQTPvze`VdD+X`VB0MEg-;4NQmBO;sTq! zz1L`u!Gld(y&w@em!I$Fx%BrT2;gJ?^x?@RUDZPn;@CZ{Fa)ikA6CS*0Y3@nNd-y( znDaE(Rg{$p$-gCU-|uQ}*3`GA@ZPJaFf^q{7Mr)XoQ3{U2Wkv^`?mm|S<8`6 zF*3R57AmgapQ!v#m$+xmi%N@XP^~Gp^<*BM0%~xEj6G!+7tfQq1nBfQJj)kyOq4ux z@z6hDk(`rP+ANz8{4lU&m3MKRy)J;!C^;+Q(DYxXLmjzbwO_VRa+hJyXy-e!hLCwEI zk@NcykwQ;)3flvJQSgc=1I#NpU zr3S%eZp#9=`}yNDW=hJI_N3)?%h%3i;C!G2^FgB^4Txl@YAB1ULmM7g!87af=&?);Ni54 zu+TW#ix>TTw;?R|iGBOVLhmzaffSJ;G_&rdgCYG?7X@KBM9w!WT{j?8+| zckeDdiGCav*N`_#eXZyjcJbm_LXLI^fAgeT{q+KyG zN}QfqT%HoBKS;*j0q5)1Zo>?noA5nGM^E?rUqoqrZzrD)(R~u_>d~Xu-v)1LXtUDa0 zoV$}Lq&1DAVkB2l0b8Mj7hK$@J zZ31}k!-o*B1npdgG87M)F1lIF^YsH3J2)>eS)+vZH>32|-5C2y^jI@GCsxcNs_ zkICb<7(S~uJ3P2^r=g)y>9=`lvqjz7rgMjWEcI1Z+1cqeWiSs_SJ!2|>>qk|pueW3 zH!D>EMgX0Rf8TqqgeVX<0Q%th>$-;+@i0>;RH|SV{T>LKx(R6pVxrIwB?9@@;>ibG z8_xd#ur4Ol>xJAy+Y7v36e5djQ{6)ts*o;`24!tiuJt9Nl(G8iCGF}Obs65x!?i{q z>G0o~U(V{ocV^ThW&SPTM)M1i(&kVszU3okv{x7yHWxUDKYz*FU0rV)r+P-_^u`=E zxpNhKq16|12HkpBs0uDvvhdMmQvQN51AJ8S+qYr35yXvyZk6~(#>dGpV04OAb#*4F zqM-6_dalGkMm1t_41NlYk8k`_8@cezOhY1Q|7YWUfbv9(+i|VKeE_8hmW-8@=rS_*2J=XaTzot$E+;|i z-rDrAAV&rjB-9!~Sj5b z-|YHB2*pooX0n>r4znj>FXSzFmRC1f%IxU!M%} zq?7k60jm5xH&=%F7_dI-yDyl+1_;A52_Yo8h?pyo^X5%kuJv9tfJkkB2H`rOlp>?CnXsW;b_MIiODD?MV5HZg4I~uMMVzvkVjBNXd@HUbN3W)L10Ltm=Mk0m= z7rYiK89Wv!MC4{FLC=ZpK9)hZy2^&|j2O_15HQHVGz&l#6ex}x3>-#GFyi)AsC0F? zJm&YKxk7Mpfb`9~t?%BISy}cY{5#0Wn}y%u$<=k3F{=)$fz!k3Bn^kSy_)e&`wNztnk^Vt$p!B{CUNYJI>Aag8t;dR}#HUZ5mMr`z^)NsT z1DmiE6YT3MD}8Y^t$Gad-EI@~STNnGr1breV5A6c2%PPZ`0w7c$9CzjHE?o9NtA;Z z&_fdYKCBdVw3`#2zX~3|D|d#H)w=URw5MFxuJ&?o73&V+t5x(>4L)V36O$5!>S{K4 ztmQw|D7a&OXQGPRrfAd3V(Y@N^g-hB1+4;GMY1t+sR8qS<89lCbWQkmBBG*H!opjN z?%uw0=Sz5kT=HMBB$ediv9sMncmS+xomyUSI8B| z4L&X|t_eL1268`NMYn~J4sDDO9DarAAL+WYhML<)$7By~o{Q6gSP@h7LX_#xA$w9s zM+YR4&Izu_+O~puI)Tf_6)e)8K_a4c{T_mjTbwEr@LkXfBV*|~b`?BYE#eZYPb$J= z_UyR#h?CP5UW=zZnetn|eCPgJ^j9q48z`!S0==y}J~nN~ zIB*}p>fLVd1ulMRP|x`#?QcKU@(^1iPh}01LvWsbY-`gSl3?4oe!U?F7q4E<=}`Eu zL=ch*h1~;;(@II9L?#qkO6X89&@m(|tPC@G;E<+5*6nkb`6T{}&oO4>Nu<8>PeJW7 zV3VSWT=BY)uyb&;2Rl&*!5tEkL$_^P_{=~j^h)=Efl1R>RC(s-&)AU-CIBRYpc5Ym#qDL-?NTf zZ#neOUv|nejuiyddw^Pp4pHAlAP}TQ$b2*QoF&o`u^WeewLeWxlx@hrJ*D(_37;Gi z8CeOM^#^caF3&O1pr5< zOv?&a9+H%FixVA-4_F774189^w_i8FJ(S*EPj%?<&REHUbEal=x8sBWxeRtW^l-vO z2HsJ~e)R0R7@B=me&6*6&L~owoq06)fu05f$0E84k{CBczZX-DJ@n`NPKIXlMJv%p z?ltpT7dQzg;5omXxj>u5W2tya*{fcC}T#>NGkxb2O5;5y_tD1PwT*cY;w zHN3OKq&-HPAAoa?Thgty7Wx24SRe}^LSKv^31@6YNl2`-u$%irkco3pkR)A@LC_Dj zyZxT)oR5r?X%q%^+!w0Rjl)F-Q6yd3O%y=#pBh)nVk)^zk_KcY=dp96eL(GF*uTG~ zqq#Yh)9U+7UJ%_-DA$p-p0#01cc~6gPGt{@!HI=Jz~n2cCaQ7LLu`)<=6txhS-&=> zLf?A$H4xUN{D#U(1t75U=+duUOQEKvWx~cy2-ZZ(GmilpA zoB+x}mKMf%$BBs;KT#`sIiEvi7_I4M@Ey3YCgvMniJ`~L5c2J4S*7?%GA8^gST(-N z)@{(5KY*7*aSdt`olO4nk@$nof4**qB{7LUF^g-mIe116x)0W06M=!S5#Ep8$B74* zgf43-mAa5XC}6EPPymDv+UCvecAfZf1O(OL=#9{A1F_*26r=+%P82Vat4Jma ziHJA@I^gb_m>3AFP%JWJ>9(GtL>0DXcPs1#GXsNhmVS6>oB$bmOgyK0Bl;v40*o~x z|9Ps3tC=Llz<`1s$a^)O#TW|~Vctof=JTaotnh3qa~=wZ8426xZ7mT|-eqf3!O-gC zck1FZGJdMY{@a66gBx1+AaH3Yc9aBT_ZZ{kB7F5?2+R~PIjcb3JdrjvN2*`3iYFTc0=3FY<2Nu z^P$R$3T5HrV5eZdo@g78HyOMdBf1x{*oEs`l9P^|bLmXY^YoazpNkk7H6C{GZ7Jh{M&UOTU*1) zh;oEh5elR&1xuJ`fn7QXr#&phH}K37Q!tcQM68E~pU{gWWeJQU@Bx&~`uSP7!`C}< z1L0uC9)N-qKGWHDt8Aqaq9up?5f^qH9557s@ZgTw0r=Txnb}Dk{Q~scdovZ5C9c}o zG^VI^z-oL7RU<;L3D`lhwV{0>v3aNsVTtwum#H)u{`LFEjRW;yNHy&F{u70t10MSY8_%E;waFrP$dz60FrHR zZ^(G_t^zS|%_OgsY>Q}YniJ%xNFRfO2}!pIl4f9L2F#}NT$T$7aD-mrREfZ}$sY3_ zFc|Z7t+NuS1wX;8LoZA6`H&#>zxYc8umP*2LOIeKuB&g@lqe5yxp!hh6`?OA;Q?&| zdI%iYjsJUhw3(a;K7l?S?uTyk9{A=weugX*qE>+*Xg6}BFr?htbz^6}>hZxVEI~p-( zuK=qgNyWp@&$##w{&N{94?*}s4WuY6i1n8`myIj|TtKWAld=cf{|lFclXu%p2U=bz zBxzbQ^`IcaBa5FyMwr58gthOBrH#A@PQiom1r6xWC{?b|Zxev2$PXxXbHR9WqK?CauTqRz8y*gR z+VunpNqB#-h$PvGgyTV-fxkn2z8g$-B4YX0ZR_4j^rYw>fg88$XQ!;EJKg3m{w)x? z_Ma+_+%T>}Afbt-5>zbZku6V|BTt?v!4ShlNGjoY8Nm&-L}&JUl#hMz)^(2|!R?T^+#G z4rI!pVSVu6c;i;Vmaj=v{Q9n&biZSIR}94SirAcxm=4tFAdYk*1d9|VU?OfN858;2 zY>SPk+BP>00=X*>`Zut`ep zS5VN65Y#wB?YJ;>3(bZdHWJXeuX1vbFjSA>^`PhR_?J~zZ^p#F#v>jt=6&(Qk$~J- zm{D*$MWz>3BsqSWPS#2#XXHV2YepjHTvDRGD+=3CrEB>o*gaR*ucHfOJ7B69FG zJ_`My3@qS~6=KJH3V~O`IbJf!7D!!)(Ly|{hVV4x_3Zho-Dd+iI z^qq#nDR~|u->SN?vE&6_t6w1 za4i8`5$X0&P{HBXv?OvV9b**E&AcjJLwft|RVUFvTZ2uN-t@3l2$`Q{DlWbVWA7$} zD{3wz`g(Z@p+~?+fJhE&AA7_8t)+zwvLSll`FRDdP~_1l;75JWuH3=m&XRYz;!8pj zS%au+Qsn)av?$B*`AX{#qKhC2{0I&Bl7HJuCtJVVZ)ZGWoV?==o+&?VG<*1H|1aE% z=)3FGptBmFY^uTL1v@ws6%`e{X&lUqJ9m=L!r}!)O%8Na|0K}LVUkEQ4#0UeJL0*H z8RrbvlvG{Zm0jz&y`Wx*#;h3Z(e$#2&V59GA4SFhjL6v~S*Aa~&SN@N@Ax=(@)yT% z&_*82yi{r1cb}^{nUa+2H1F~~1Vy*SS*TjIWgs+0*)3Dj(e2qqEe%6w=>F!Y8E;-m7WrpLcJ)_McQ z^bt1K(D%7`-nB-1*45VF3lm*OG9%SiSs~W$ixHaA4VGXn~v*nwzc*4X^u3*RIE-AKryjO zJlxT$Ts(q+DymI_qob=q>DK*hR;JyTdUdM1t1%--L#4LgVC^La3|F8}{E5Q|+fu}i zD$Ea!g%u#j{-**p8wm@>g2U4#j5^SQ3ja{X+!BDM5SE~~ulL^So}s5b!v4WRo4uhS zTXFI&&|Pv^hoI^HTv6eJdkEm9fz@OA)1&?4zh|^|?7o13c9-JyOyeUWKAoIu(K^S0 z)6=x~<2?*A*h@j-Dg9mIZdbwkHzw6ofZZ6d*e_n(gZNnZ`DC3>6d?);D}aNGOId9A z=}C`)CpMO^-+E0I7symTvavEtSjP<%-EJ z)F)wBqcWKjt*JK+YV={*>9E=BG+S><+G<$rNv8+Y4*pkC>-6?s`H?fJt~CYg#1=`J>p!MX;$8`$?8I=jKos35iR93u!Br7^ z{B`&z&va&?-UEUqg%4o5#}ubC04QO@pct#Wg(?>aaWt4N5)bp{jR-(-W#i-Xhsq6SIhkMr9r>xJG+gSjB)Cc0bQ6C4-sEKE;-xIZ zokH*{A~$ZqCgbvgU_<;Grp&!um{GA4FnCmnRbO65lHs65N0=uP3Fwg1fIyFrQ2Dmy z-zGD1wBr7pEE)WRPU|Kd4d@0x+~$kckXqR7=5|FrcKQXrAm$cqAW74qcO@~3t!NKx z{1E@;3+4Ugix83B2b|zXLzaGHqZu-m;RHaANgZMgqIu zwv`j!#FulBLEqcn!i6qqHHQ21M@&2$o}Qv10UV`8_%*ML=4KN!&SBkt1?( z==0HsZQa$-TN8c=%3PNe4c#KcZiLbhyaQGPFM31;Rsv?G!2Su0*#bUiRENZXgQ^&T zCu=!TuE-C%@L_t3scG+s7*ZD1B`0`ZI{7&r$o^GdS9jdDES^ty$KFGW1SWd=wEmfl zC-v5?#t<-KE4hyxpdEYn`Xj{^ParN0+0LN7zkrQhaw+7$DUY#1(%+10nf5!+vrHdI znQj4G0u_j0Qvi&eJ;y&M{ zvAon%urNSp)9q~4bTGE5nG_Rv+(@wt9tEy7QYA(Sn{Gixg?jEQtU#zmNmdCAAQhdR z`#|$T5aQI>xUxK({qN@sx8=q3lgNUbW34cK zS3yP+S^QA!VsusVI8IU^r3dhPzU#XLLP-X4=7%}d_*syD( z#l^n%0evC#Q{lFZh!i9H$j&8ax2AdQ9SG`>g(U`UoyA+ayvq%^`_D`FSe{FZl!1;9 zXx4fnc&vMRG7{HKxy_J{RZ10(b_nZ8UMZ?11YIH0_!{hfq@s(7X*Xv@eUB#-$8Bl} zO|DiFCCjV-?Aj3#DabV;%h!t@bcUu@4RnA;Rl#h;CI<21`rCrBc-Bbr6n0m9H_{p6 z!}Z=-w*HqqWp979J|-H&?>?i2J;>vQUKte1^A-k&8Xyk%=O|Lokkp4Aj4iSjZm#)O z;eUI9nowN2q=F1t)Tfciki=}!$M8h&z->EwmL8pwA=*B)?Ar304ww~(4jnzBw<;Gr zP11w#mpM-Q&7?X_BP$7BaJs@71x=T!$Bay?<91rCD{4;$2zU<*TUMc$Hqy%+3-^JY1N;uEl6? zm4RL1rc<+VoJ3+(Jyrn;8VfQN(BK0*@$m7%+2eOql}teunC_|##L12bhc5AN4M@OuCgiFKUgpJ{rA#T!Mzh}|FDQuhVNG7XnlLKV=`j> zN8osP4p;$kPlHdRiF%ePGrz#gh7LOKHdYR0v?JY`8JC4wQ zDevpwR8OCDQ*OuXuLIl4`@a~`IQKN(nVKt}|Mg7h#Tc|`= zP>ZqzV-;|Gxn787=R?=?Cr=u*lzCnDJ+P{&Ss6{CqSEuajn~}LmLaHe{c&mO%AXnR z`vg7@q#cY_-4LwEF}-A9{O;oJ{rmg>{$;w`)}~Qc2T(dYfuz zr>tXQVz-W8|IqbrVrq&aSUGvxd3>{PZEE)WB#S-kK*f8>W?sl-T3qZ7QGc;MDn8!K zHYebnsQ33vx;gq~v*+esQB{r14$dx=&i?&-%>Dnizc<9|VM&-!_fdw3xVUA@kM|{N zoI0)hVi(^5&;Wt#*&TQJu3f)Af6){1=l`UD-Q))!_b5#b`cV@G?4&XP2VWL!zU-&A zc*Q!s=fGv$4Zucs(?JHHSG2Y5y)GRtF0bc(^wDDLR?(PPp!=nPLxc=(-o1PD{q~78 z(ca#vE{g*n{b_!o2_h diff --git a/doc/source/tutorials/visualize_cliques/visualize_cliques.rst b/doc/source/tutorials/visualize_cliques/visualize_cliques.rst deleted file mode 100644 index 55b3c9dce..000000000 --- a/doc/source/tutorials/visualize_cliques/visualize_cliques.rst +++ /dev/null @@ -1,87 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-cliques: - -============ -Cliques -============ - -This example shows how to compute and visualize cliques of a graph using :meth:`igraph.GraphBase.cliques`. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - g = ig.Graph.Famous('Zachary') - - # Compute cliques - cliques = g.cliques(4, 4) - - # Plot each clique highlighted in a separate axes - fig, axs = plt.subplots(3, 4) - axs = axs.ravel() - for clique, ax in zip(cliques, axs): - ig.plot( - ig.VertexCover(g, [clique]), - mark_groups=True, palette=ig.RainbowPalette(), - edge_width=0.5, - target=ax, - ) - - plt.axis('off') - plt.show() - -The plot looks like this: - -.. figure:: ./figures/cliques.png - :alt: A visual representation of the cliques in the graph - :align: center - - Each clique of the graph is highlighted in one of the panels - -Advanced: improving plotting style ----------------------------------- -If you want a little more style, you can color the vertices/edges within each clique to make them stand out: - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - g = ig.Graph.Famous('Zachary') - cliques = g.cliques(4, 4) - - fig, axs = plt.subplots(3, 4) - axs = axs.ravel() - for clique, ax in zip(cliques, axs): - # Color vertices yellow/red based on whether they are in this clique - g.vs['color'] = 'yellow' - g.vs[clique]['color'] = 'red' - - # Color edges black/red based on whether they are in this clique - clique_edges = g.es.select(_within=clique) - g.es['color'] = 'black' - clique_edges['color'] = 'red' - # also increase thickness of clique edges - g.es['width'] = 0.3 - clique_edges['width'] = 1 - - ig.plot( - ig.VertexCover(g, [clique]), - mark_groups=True, - palette=ig.RainbowPalette(), - target=ax, - ) - - plt.axis('off') - plt.show() - -Lo and behold: - -.. figure:: ./figures/cliques_with_edges.png - :alt: A visual representation of the cliques in the graph - :align: center - - Each clique of the graph is highlighted in one of the panels, with vertices and edges highlighted as well. - diff --git a/doc/source/tutorials/visualize_communities/figures/visualize_communities.png b/doc/source/tutorials/visualize_communities/figures/visualize_communities.png deleted file mode 100644 index 80c110331511a4f946b9ef8c04e361cb39065d75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37030 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 diff --git a/doc/source/tutorials/visualize_communities/visualize_communities.rst b/doc/source/tutorials/visualize_communities/visualize_communities.rst deleted file mode 100644 index 6d9a98c5a..000000000 --- a/doc/source/tutorials/visualize_communities/visualize_communities.rst +++ /dev/null @@ -1,85 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-visualize-communities: - -===================== -Communities -===================== - -This example shows how to visualize communities or clusters of a graph. First, make the graph: we just use a famous graph here for simplicity. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - g = ig.Graph.Famous("Zachary") - -Second, define the clusters. - -.. code-block:: python - - # Use edge betweenness to detect communities - communities = g.community_edge_betweenness() - # ... and convert into a VertexClustering for plotting - communities = communities.as_clustering() - -Third, prepare colors for the various communities: - -.. code-block:: python - - # Color each vertex and edge based on its community membership - num_communities = len(communities) - palette = ig.RainbowPalette(n=num_communities) - for i, community in enumerate(communities): - g.vs[community]["color"] = i - community_edges = g.es.select(_within=community) - community_edges["color"] = i - -Finally, plot the graph: - -.. code-block:: python - - # Plot with only vertex and edge coloring - fig, ax = plt.subplots() - ig.plot( - communities, - palette=palette, - edge_width=1, - target=ax, - vertex_size=0.3, - ) - -... and add a fancy legend via `proxy artists`_: - -.. _`proxy artists`: https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html - -.. code-block:: python - - legend_handles = [] - for i in range(num_communities): - handle = ax.scatter( - [], [], - s=100, - facecolor=palette.get(i), - edgecolor="k", - label=i, - ) - legend_handles.append(handle) - - ax.legend( - handles=legend_handles, - title='Community:', - bbox_to_anchor=(0, 1.0), - bbox_transform=ax.transAxes, - ) - -The resulting figure is shown below. - -.. figure:: ./figures/visualize_communities.png - :alt: A visual representation of the graph and its communities - :align: center - - The graph with its communities highlighted by color. - -For an example on how to generate the cluster graph from a vertex cluster, check out :ref:`tutorials-cluster-graph`. diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index 8d2274cff..e8121551c 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -11,7 +11,8 @@ In the following examples, we will assume |igraph| is imported as `ig` and a >>> import igraph as ig >>> g = ig.Graph(edges=[[0, 1], [2, 3]]) -Read the :doc:`api/index` for details on each function and class. See the :ref:`tutorial ` and the :doc:`gallery` for examples. +Read the :doc:`api/index` for details on each function and class. See the :ref:`tutorial ` and +the :doc:`tutorials/index` for examples. Graph layouts ============= diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index ef820ae95..360716803 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -57,7 +57,7 @@ if [ ! -d ".venv" ]; then fi # Make sure that Sphinx, PyDoctor (and maybe doc2dash) are up-to-date in the virtualenv -.venv/bin/pip install -U sphinx pydoctor sphinxbootstrap4theme +.venv/bin/pip install -U sphinx pydoctor sphinxbootstrap4theme sphinx-gallery if [ x$DOC2DASH = x1 ]; then .venv/bin/pip install -U doc2dash fi diff --git a/scripts/patch_modularized_graph_methods.py b/scripts/patch_modularized_graph_methods.py index 3b871b275..0ad893737 100644 --- a/scripts/patch_modularized_graph_methods.py +++ b/scripts/patch_modularized_graph_methods.py @@ -5,6 +5,13 @@ import igraph +# FIXME: there must be a better way to do this +auxiliary_imports = [ + ('typing', '*'), + ('igraph.io.files', '_identify_format'), +] + + def main(): # Get instance and classmethods @@ -14,7 +21,7 @@ def main(): # Get the source code for each method and replace the method name # in the signature methodsources = {} - underscore_functions= set() + underscore_functions = set() for mname, method in methods: # Source code of the function that uses the method source = inspect.getsourcelines(method)[0] @@ -27,7 +34,6 @@ def main(): # Make new source code, which is the same but with the name swapped newsource = [source[0].replace(fname, mname)] + source[1:] - methodsources[mname] = newsource # Prepare to delete the import for underscore functions @@ -36,18 +42,23 @@ def main(): newmodule = igraph.__file__ + '.new' with open(newmodule, 'wt') as fout: + # FIXME: whitelisting all cases is not great, try to improve + for (origin, value) in auxiliary_imports: + fout.write(f'from {origin} import {value}\n') + with open(igraph.__file__, 'rt') as f: # Swap in the method sources for line in f: mtype = None + for mname in methodsources: # Class methods (constructors) - if mname + ' = classmethod(_' in line: + if ' ' + mname + ' = classmethod(_' in line: mtype = 'class' break # Instance methods (excluding factories e.g. 3d layouts) - if (mname + ' = _' in line) and ('(' not in line): + if (' ' + mname + ' = _' in line) and ('(' not in line): mtype = 'instance' break @@ -55,7 +66,7 @@ def main(): fout.write(line) continue - # Method found, substitute + # Method found, substitute and remove from dict fout.write('\n') if mtype == 'class': fout.write(' @classmethod\n') @@ -63,6 +74,8 @@ def main(): # Correct indentation fout.write(' ' + mline) + del methodsources[mname] + # Move the new file back with open(igraph.__file__, 'wt') as fout: with open(newmodule, 'rt') as f: diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 446c0b2b3..11895f788 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -16740,9 +16740,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Calculates the modularity matrix of the graph.\n\n" "@param weights: optional edge weights or C{None} if all edges are weighed\n" " equally.\n" - "@param resolution: the resolution parameter I{gamma} of the modularity formula\n." - " The classical definition of modularity is retrieved when the resolution\n" - " parameter is set to 1.\n" + "@param resolution: the resolution parameter I{gamma} of the modularity\n" + " formula. The classical definition of modularity is retrieved when the\n" + " resolution parameter is set to 1.\n" "@param directed: whether to consider edge directions if the graph is directed.\n" " C{True} will use the directed variant of the modularity measure where the\n" " in- and out-degrees of nodes are treated separately; C{False} will treat\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 9c545f8ed..fa15e680d 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -649,8 +649,8 @@ def es(self): clusters = _clusters cohesive_blocks = _cohesive_blocks connected_components = _connected_components - blocks = biconnected_components - components = connected_components + blocks = _biconnected_components + components = _connected_components ############################################# # Community detection/clustering From e2d76cd888b0f26883fe4855d107ae26ca9d187e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 16 Oct 2022 15:31:53 +0200 Subject: [PATCH 1123/1892] fix: better error handling for cases when CREATE_GRAPH() fails --- src/_igraph/graphobject.c | 59 +++++++++++++++++++++++++++++++++++---- src/_igraph/operators.c | 36 ++++++++++++++---------- 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 11895f788..8359c0020 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -42,12 +42,14 @@ PyTypeObject* igraphmodule_GraphType; py_graph = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( \ py_type, &c_graph \ ); \ + if (py_graph == NULL) { igraph_destroy(&c_graph); } \ } #define CREATE_GRAPH(py_graph, c_graph) { \ py_graph = (igraphmodule_GraphObject*) igraphmodule_Graph_subclass_from_igraph_t( \ Py_TYPE(self), &c_graph \ ); \ + if (py_graph == NULL) { igraph_destroy(&c_graph); } \ } /********************************************************************** @@ -2442,10 +2444,17 @@ PyObject *igraphmodule_Graph_Full_Bipartite(PyTypeObject * type, } CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + igraph_vector_bool_destroy(&vertex_types); + return NULL; + } vertex_types_o = igraphmodule_vector_bool_t_to_PyList(&vertex_types); igraph_vector_bool_destroy(&vertex_types); - if (vertex_types_o == 0) return NULL; + if (vertex_types_o == 0) { + return NULL; + } + return Py_BuildValue("NN", (PyObject *) self, vertex_types_o); } @@ -2536,6 +2545,11 @@ PyObject *igraphmodule_Graph_GRG(PyTypeObject * type, } CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + Py_DECREF(o_xs); + Py_DECREF(o_ys); + return NULL; + } return Py_BuildValue("NNN", (PyObject*)self, o_xs, o_ys); } @@ -2617,6 +2631,9 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, igraph_matrix_destroy(&matrix); CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + return NULL; + } vertex_types_o = igraphmodule_vector_bool_t_to_PyList(&vertex_types); igraph_vector_bool_destroy(&vertex_types); @@ -2943,7 +2960,7 @@ NULL }; CREATE_GRAPH_FROM_TYPE(self, g, type); - if (store_attribs) { + if (self != NULL && store_attribs) { type_vec_o = igraphmodule_vector_int_t_to_PyList(&type_vec); if (type_vec_o == 0) { igraph_matrix_destroy(&pm); @@ -3045,7 +3062,7 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, CREATE_GRAPH_FROM_TYPE(self, g, type); - if (store_attribs) { + if (self != NULL && store_attribs) { type_vec_o = igraphmodule_vector_int_t_pair_to_PyList(&in_type_vec, &out_type_vec); if (type_vec_o == NULL) { @@ -3134,6 +3151,9 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, } CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + return NULL; + } vertex_types_o = igraphmodule_vector_bool_t_to_PyList(&vertex_types); igraph_vector_bool_destroy(&vertex_types); @@ -3386,6 +3406,7 @@ PyObject *igraphmodule_Graph_Static_Fitness(PyTypeObject *type, igraph_vector_destroy(&fitness_in); CREATE_GRAPH_FROM_TYPE(self, g, type); + return (PyObject *) self; } @@ -3616,6 +3637,10 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, igraph_matrix_destroy(&m); CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + return NULL; + } + weights_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); if (!weights_o) { Py_DECREF(self); @@ -4098,9 +4123,17 @@ PyObject *igraphmodule_Graph_bipartite_projection(igraphmodule_GraphObject * sel if (p_g1) { CREATE_GRAPH(result1, g1); + if (result1 == NULL) { + return NULL; + } } + if (p_g2) { CREATE_GRAPH(result2, g2); + if (result2 == NULL) { + Py_XDECREF(result1); + return NULL; + } } if (PyObject_IsTrue(multiplicity_o)) { @@ -7967,10 +8000,19 @@ PyObject *igraphmodule_Graph_layout_sugiyama( if (weights != 0) { igraph_vector_destroy(weights); free(weights); } result_o = igraphmodule_matrix_t_to_PyList(&m, IGRAPHMODULE_TYPE_FLOAT); + if (result_o == NULL) { + igraph_vector_int_destroy(&extd_to_orig_eids); + igraph_matrix_destroy(&m); + return NULL; + } + igraph_matrix_destroy(&m); if (PyObject_IsTrue(return_extended_graph)) { CREATE_GRAPH(graph_o, extd_graph); + if (graph_o == NULL) { + Py_DECREF(result_o); + } extd_to_orig_eids_o = igraphmodule_vector_int_t_to_PyList(&extd_to_orig_eids); result_o = Py_BuildValue("NNN", result_o, graph_o, extd_to_orig_eids_o); } @@ -8444,6 +8486,10 @@ PyObject *igraphmodule_Graph_Read_DIMACS(PyTypeObject * type, return NULL; CREATE_GRAPH_FROM_TYPE(self, g, type); + if (self == NULL) { + Py_DECREF(capacity_obj); + return NULL; + } return Py_BuildValue("NnnN", (PyObject *) self, (Py_ssize_t)source, (Py_ssize_t)target, capacity_obj); @@ -10616,6 +10662,10 @@ PyObject *igraphmodule_Graph_unfold_tree(igraphmodule_GraphObject * self, } CREATE_GRAPH(result_o, res); + if (!result_o) { + Py_DECREF(mapping_o); + return NULL; + } return Py_BuildValue("NN", result_o, mapping_o); } @@ -11155,8 +11205,7 @@ PyObject *igraphmodule_Graph_gomory_hu_tree(igraphmodule_GraphObject * self, CREATE_GRAPH(tree_o, tree); if (!tree_o) { - igraph_destroy(&tree); - return 0; + return NULL; } return Py_BuildValue("NN", tree_o, flow_o); diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 1463daa03..add8449aa 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -197,13 +197,17 @@ PyObject *igraphmodule__union(PyObject *self, o = (igraphmodule_GraphObject*) igraphmodule_Graph_from_igraph_t(&g); } - if (with_edgemaps) { - /* wrap in a dictionary */ - result = PyDict_New(); - PyDict_SetItemString(result, "graph", (PyObject *) o); - Py_DECREF(o); - PyDict_SetItemString(result, "edgemaps", em_list); - Py_DECREF(em_list); + if (o != NULL) { + if (with_edgemaps) { + /* wrap in a dictionary */ + result = PyDict_New(); + PyDict_SetItemString(result, "graph", (PyObject *) o); + Py_DECREF(o); + PyDict_SetItemString(result, "edgemaps", em_list); + Py_DECREF(em_list); + } else { + result = (PyObject *) o; + } } else { result = (PyObject *) o; } @@ -319,13 +323,17 @@ PyObject *igraphmodule__intersection(PyObject *self, o = (igraphmodule_GraphObject*) igraphmodule_Graph_from_igraph_t(&g); } - if (with_edgemaps) { - /* wrap in a dictionary */ - result = PyDict_New(); - PyDict_SetItemString(result, "graph", (PyObject *) o); - Py_DECREF(o); - PyDict_SetItemString(result, "edgemaps", em_list); - Py_DECREF(em_list); + if (o != NULL) { + if (with_edgemaps) { + /* wrap in a dictionary */ + result = PyDict_New(); + PyDict_SetItemString(result, "graph", (PyObject *) o); + Py_DECREF(o); + PyDict_SetItemString(result, "edgemaps", em_list); + Py_DECREF(em_list); + } else { + result = (PyObject *) o; + } } else { result = (PyObject *) o; } From 8cc87ea64cecce56474a83e90831e7b7ba13850e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 16 Oct 2022 15:47:38 +0200 Subject: [PATCH 1124/1892] fix: fix two more issues found by static analysids --- src/_igraph/igraphmodule.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 35cda299d..e702035cb 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -200,7 +200,8 @@ PyObject* igraphmodule_set_progress_handler(PyObject* self, PyObject* o) { Py_XDECREF(progress_handler); if (o == Py_None) - o = 0; + o = NULL; + Py_XINCREF(o); GETSTATE(self)->progress_handler=o; @@ -220,9 +221,11 @@ PyObject* igraphmodule_set_status_handler(PyObject* self, PyObject* o) { Py_RETURN_NONE; Py_XDECREF(status_handler); - if (o == Py_None) - o = 0; - Py_INCREF(o); + if (o == Py_None) { + o = NULL; + } + + Py_XINCREF(o); GETSTATE(self)->status_handler = o; Py_RETURN_NONE; @@ -271,6 +274,10 @@ PyObject* igraphmodule_convex_hull(PyObject* self, PyObject* args, PyObject* kwd igraph_matrix_destroy(&mtrx); return NULL; } + } else { + PyErr_SetString(PyExc_TypeError, "convex_hull() must receive a list of indexable sequences"); + igraph_matrix_destroy(&mtrx); + return NULL; } if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) { From e669a4e5d2dd3ea849a529fcb0e1c0dda24b1fd3 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 17 Oct 2022 08:28:00 +1100 Subject: [PATCH 1125/1892] igraph logo in documentation template --- doc/source/_static/logo-black.svg | 1 + doc/source/conf.py | 4 ++-- scripts/mkdoc.sh | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 doc/source/_static/logo-black.svg diff --git a/doc/source/_static/logo-black.svg b/doc/source/_static/logo-black.svg new file mode 100644 index 000000000..410ffa84d --- /dev/null +++ b/doc/source/_static/logo-black.svg @@ -0,0 +1 @@ +logo-black \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index 1e8b6d682..aeced121c 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -41,7 +41,7 @@ def get_igraphdir(): def get_igraph_version(): '''Get igraph version''' - if is_inside_rtd: + if rtd_version != '': return rtd_version version_file = get_igraphdir() / 'version.py' @@ -194,7 +194,7 @@ def get_igraph_version(): # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +html_logo = '_static/logo-black.svg' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 360716803..3e3a659f1 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -97,11 +97,10 @@ fi echo "Generating HTML documentation..." if [ "x$STANDALONE" = "x1" ]; then echo "Build standalone docs" - .venv/bin/python -m sphinx \ + .venv/bin/pip install -U sphinx-rtd-theme + READTHEDOCS="True" .venv/bin/python -m sphinx \ -T \ -b html \ - -Dtemplates_path='' \ - -Dhtml_theme='alabaster' \ ${DOC_SOURCE_FOLDER} ${DOC_HTML_FOLDER} else echo "Build Jekyll-style docs" From 916a83da5cb1e50ac553b4148e8c078105f1f1b3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Oct 2022 10:33:35 +0200 Subject: [PATCH 1126/1892] fix: fix two more issues found by static analysis --- src/_igraph/convert.c | 2 ++ src/_igraph/operators.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index aa4b15096..f6842ee2a 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3829,6 +3829,8 @@ int igraphmodule_PyObject_to_attribute_combination_t(PyObject* object, return 0; } + rec.type = IGRAPH_ATTRIBUTE_COMBINE_IGNORE; + if (PyDict_Check(object)) { /* a full-fledged dict was passed */ PyObject *key, *value; diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index add8449aa..5aaca69b5 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -47,7 +47,6 @@ PyObject *igraphmodule__disjoint_union(PyObject *self, /* Needs to be an iterable */ it = PyObject_GetIter(graphs); if (!it) { - Py_DECREF(it); return igraphmodule_handle_igraph_error(); } @@ -113,7 +112,6 @@ PyObject *igraphmodule__union(PyObject *self, /* Needs to be an iterable */ it = PyObject_GetIter(graphs); if (!it) { - Py_DECREF(it); return igraphmodule_handle_igraph_error(); } @@ -241,7 +239,6 @@ PyObject *igraphmodule__intersection(PyObject *self, /* Needs to be an iterable */ it = PyObject_GetIter(graphs); if (!it) { - Py_DECREF(it); return igraphmodule_handle_igraph_error(); } From 88e3bfc661973494ec824e08cc531374041743e2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Oct 2022 11:06:34 +0200 Subject: [PATCH 1127/1892] chore: updated changelog [ci skip] --- CHANGELOG.md | 3 ++- src/igraph/version.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c22ab84cc..a8cbd22f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -413,7 +413,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.1...master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.2...master +[0.10.2]: https://github.com/igraph/python-igraph/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/igraph/python-igraph/compare/0.10.0...0.10.1 [0.10.0]: https://github.com/igraph/python-igraph/compare/0.9.11...0.10.0 [0.9.11]: https://github.com/igraph/python-igraph/compare/0.9.10...0.9.11 diff --git a/src/igraph/version.py b/src/igraph/version.py index 619ee99bb..cb33a78fc 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 1) +__version_info__ = (0, 10, 2) __version__ = ".".join("{0}".format(x) for x in __version_info__) From bb1cb538d34a131faf1014d86398adaef7210c43 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Oct 2022 11:08:19 +0200 Subject: [PATCH 1128/1892] chore: added contributors file [ci skip] --- .all-contributorsrc | 537 ++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTORS.md | 92 ++++++++ README.md | 3 + 3 files changed, 632 insertions(+) create mode 100644 .all-contributorsrc create mode 100644 CONTRIBUTORS.md diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 000000000..78c931202 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,537 @@ +{ + "projectName": "python-igraph", + "projectOwner": "igraph", + "repoType": "github", + "repoHost": "https://github.com", + "files": [ + "CONTRIBUTORS.md" + ], + "imageSize": 100, + "commit": false, + "commitConvention": "none", + "contributors": [ + { + "login": "ntamas", + "name": "Tamás Nepusz", + "avatar_url": "https://avatars.githubusercontent.com/u/195637?v=4", + "profile": "https://collmot.com/", + "contributions": [ + "code" + ] + }, + { + "login": "iosonofabio", + "name": "Fabio Zanini", + "avatar_url": "https://avatars.githubusercontent.com/u/1200640?v=4", + "profile": "https://fabilab.org/", + "contributions": [ + "code" + ] + }, + { + "login": "Gomango999", + "name": "Kevin Zhu", + "avatar_url": "https://avatars.githubusercontent.com/u/37771462?v=4", + "profile": "https://github.com/Gomango999", + "contributions": [ + "code" + ] + }, + { + "login": "gaborcsardi", + "name": "Gábor Csárdi", + "avatar_url": "https://avatars.githubusercontent.com/u/660288?v=4", + "profile": "https://github.com/gaborcsardi", + "contributions": [ + "code" + ] + }, + { + "login": "szhorvat", + "name": "Szabolcs Horvát", + "avatar_url": "https://avatars.githubusercontent.com/u/1212871?v=4", + "profile": "http://szhorvat.net/", + "contributions": [ + "code" + ] + }, + { + "login": "vtraag", + "name": "Vincent Traag", + "avatar_url": "https://avatars.githubusercontent.com/u/6057804?v=4", + "profile": "http://www.traag.net/", + "contributions": [ + "code" + ] + }, + { + "login": "deeenes", + "name": "deeenes", + "avatar_url": "https://avatars.githubusercontent.com/u/2679889?v=4", + "profile": "https://github.com/deeenes", + "contributions": [ + "code" + ] + }, + { + "login": "h5jam", + "name": "Seungoh Han", + "avatar_url": "https://avatars.githubusercontent.com/u/46439899?v=4", + "profile": "https://h5jam.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "luav", + "name": "Artem V L", + "avatar_url": "https://avatars.githubusercontent.com/u/6162969?v=4", + "profile": "http://linkedin.com/in/artemvl", + "contributions": [ + "code" + ] + }, + { + "login": "Isaac-Lee", + "name": "Yesung(Isaac) Lee", + "avatar_url": "https://avatars.githubusercontent.com/u/49810053?v=4", + "profile": "https://github.com/Isaac-Lee", + "contributions": [ + "code" + ] + }, + { + "login": "jboynyc", + "name": "John Boy", + "avatar_url": "https://avatars.githubusercontent.com/u/2187261?v=4", + "profile": "https://www.jboy.space/", + "contributions": [ + "code" + ] + }, + { + "login": "casperdcl", + "name": "Casper da Costa-Luis", + "avatar_url": "https://avatars.githubusercontent.com/u/10780059?v=4", + "profile": "https://cdcl.ml/", + "contributions": [ + "code" + ] + }, + { + "login": "albertoalcolea", + "name": "Alberto Alcolea", + "avatar_url": "https://avatars.githubusercontent.com/u/1153725?v=4", + "profile": "https://albertoalcolea.com/", + "contributions": [ + "code" + ] + }, + { + "login": "horvatha", + "name": "Árpád Horváth", + "avatar_url": "https://avatars.githubusercontent.com/u/951303?v=4", + "profile": "https://pyedu.hu/arpad/", + "contributions": [ + "code" + ] + }, + { + "login": "ebraminio", + "name": "ebraminio", + "avatar_url": "https://avatars.githubusercontent.com/u/833473?v=4", + "profile": "https://github.com/ebraminio", + "contributions": [ + "code" + ] + }, + { + "login": "fwitter", + "name": "Fabian Witter", + "avatar_url": "https://avatars.githubusercontent.com/u/10985458?v=4", + "profile": "https://github.com/fwitter", + "contributions": [ + "code" + ] + }, + { + "login": "jankatins", + "name": "Jan Katins", + "avatar_url": "https://avatars.githubusercontent.com/u/890156?v=4", + "profile": "http://www.katzien.de/", + "contributions": [ + "code" + ] + }, + { + "login": "nickeubank", + "name": "Nick Eubank", + "avatar_url": "https://avatars.githubusercontent.com/u/9683693?v=4", + "profile": "https://github.com/nickeubank", + "contributions": [ + "code" + ] + }, + { + "login": "PeterScott", + "name": "Peter Scott", + "avatar_url": "https://avatars.githubusercontent.com/u/406445?v=4", + "profile": "http://finger-tree.blogspot.com/", + "contributions": [ + "code" + ] + }, + { + "login": "Sriram-Pattabiraman", + "name": "Sriram-Pattabiraman", + "avatar_url": "https://avatars.githubusercontent.com/u/59712515?v=4", + "profile": "https://github.com/Sriram-Pattabiraman", + "contributions": [ + "code" + ] + }, + { + "login": "iggisv9t", + "name": "Sviatoslav", + "avatar_url": "https://avatars.githubusercontent.com/u/19172517?v=4", + "profile": "https://iggisv9t.xyz/", + "contributions": [ + "code" + ] + }, + { + "login": "ah00ee", + "name": "Ah-Young Nho", + "avatar_url": "https://avatars.githubusercontent.com/u/68725978?v=4", + "profile": "https://github.com/ah00ee", + "contributions": [ + "code" + ] + }, + { + "login": "frederik-h", + "name": "Frederik Harwath", + "avatar_url": "https://avatars.githubusercontent.com/u/22046314?v=4", + "profile": "https://github.com/frederik-h", + "contributions": [ + "code" + ] + }, + { + "login": "naviddianati", + "name": "Navid Dianati", + "avatar_url": "https://avatars.githubusercontent.com/u/5558232?v=4", + "profile": "https://github.com/naviddianati", + "contributions": [ + "code" + ] + }, + { + "login": "abe-winter", + "name": "abe-winter", + "avatar_url": "https://avatars.githubusercontent.com/u/7256523?v=4", + "profile": "https://github.com/abe-winter", + "contributions": [ + "code" + ] + }, + { + "login": "arivero", + "name": "Alejandro Rivero", + "avatar_url": "https://avatars.githubusercontent.com/u/43174?v=4", + "profile": "https://github.com/arivero", + "contributions": [ + "code" + ] + }, + { + "login": "Ariki", + "name": "Ariki", + "avatar_url": "https://avatars.githubusercontent.com/u/519412?v=4", + "profile": "https://github.com/Ariki", + "contributions": [ + "code" + ] + }, + { + "login": "cvanelteren", + "name": "Casper van Elteren", + "avatar_url": "https://avatars.githubusercontent.com/u/19485143?v=4", + "profile": "https://cvanelteren.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "cthoyt", + "name": "Charles Tapley Hoyt", + "avatar_url": "https://avatars.githubusercontent.com/u/5069736?v=4", + "profile": "https://cthoyt.com/", + "contributions": [ + "code" + ] + }, + { + "login": "cgohlke", + "name": "Christoph Gohlke", + "avatar_url": "https://avatars.githubusercontent.com/u/483428?v=4", + "profile": "https://www.cgohlke.com/", + "contributions": [ + "code" + ] + }, + { + "login": "chrisfalter", + "name": "Christopher Falter", + "avatar_url": "https://avatars.githubusercontent.com/u/4177499?v=4", + "profile": "https://github.com/chrisfalter", + "contributions": [ + "code" + ] + }, + { + "login": "ReblochonMasque", + "name": "FredInChina", + "avatar_url": "https://avatars.githubusercontent.com/u/6275531?v=4", + "profile": "https://github.com/ReblochonMasque", + "contributions": [ + "code" + ] + }, + { + "login": "friso", + "name": "Friso van Vollenhoven", + "avatar_url": "https://avatars.githubusercontent.com/u/273638?v=4", + "profile": "https://friso.lol/", + "contributions": [ + "code" + ] + }, + { + "login": "szarnyasg", + "name": "Gabor Szarnyas", + "avatar_url": "https://avatars.githubusercontent.com/u/1402801?v=4", + "profile": "https://szarnyasg.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "GaoFangshu", + "name": "Gao Fangshu", + "avatar_url": "https://avatars.githubusercontent.com/u/11488742?v=4", + "profile": "https://github.com/GaoFangshu", + "contributions": [ + "code" + ] + }, + { + "login": "gchilczuk", + "name": "Grzegorz Chilczuk", + "avatar_url": "https://avatars.githubusercontent.com/u/16257695?v=4", + "profile": "https://github.com/gchilczuk", + "contributions": [ + "code" + ] + }, + { + "login": "limburgher", + "name": "Gwyn Ciesla", + "avatar_url": "https://avatars.githubusercontent.com/u/2363820?v=4", + "profile": "http://cecinestpasunefromage.wordpress.com/", + "contributions": [ + "code" + ] + }, + { + "login": "xuhdev", + "name": "Hong Xu", + "avatar_url": "https://avatars.githubusercontent.com/u/325476?v=4", + "profile": "https://www.topbug.net/", + "contributions": [ + "code" + ] + }, + { + "login": "jhsmith", + "name": "Jay Smith", + "avatar_url": "https://avatars.githubusercontent.com/u/974519?v=4", + "profile": "https://github.com/jhsmith", + "contributions": [ + "code" + ] + }, + { + "login": "MapleCCC", + "name": "MapleCCC", + "avatar_url": "https://avatars.githubusercontent.com/u/25131775?v=4", + "profile": "https://mapleccc.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "theCapypara", + "name": "Marco Köpcke", + "avatar_url": "https://avatars.githubusercontent.com/u/3512122?v=4", + "profile": "https://www.linkedin.com/in/marco-koepcke/", + "contributions": [ + "code" + ] + }, + { + "login": "elfring", + "name": "Markus Elfring", + "avatar_url": "https://avatars.githubusercontent.com/u/660477?v=4", + "profile": "https://github.com/elfring", + "contributions": [ + "code" + ] + }, + { + "login": "MartinoMensio", + "name": "Martino Mensio", + "avatar_url": "https://avatars.githubusercontent.com/u/11597393?v=4", + "profile": "https://martinomensio.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "lauzadis", + "name": "Matas", + "avatar_url": "https://avatars.githubusercontent.com/u/30608308?v=4", + "profile": "https://github.com/lauzadis", + "contributions": [ + "code" + ] + }, + { + "login": "mlissner", + "name": "Mike Lissner", + "avatar_url": "https://avatars.githubusercontent.com/u/236970?v=4", + "profile": "http://www.michaeljaylissner.com/", + "contributions": [ + "code" + ] + }, + { + "login": "flying-sheep", + "name": "Philipp A.", + "avatar_url": "https://avatars.githubusercontent.com/u/291575?v=4", + "profile": "https://phil.red/", + "contributions": [ + "code" + ] + }, + { + "login": "PuneethaPai", + "name": "Puneetha Pai", + "avatar_url": "https://avatars.githubusercontent.com/u/21996583?v=4", + "profile": "https://puneethapai.github.io/", + "contributions": [ + "code" + ] + }, + { + "login": "sr-murthy", + "name": "S Murthy", + "avatar_url": "https://avatars.githubusercontent.com/u/9358070?v=4", + "profile": "https://github.com/sr-murthy", + "contributions": [ + "code" + ] + }, + { + "login": "scottgigante", + "name": "Scott Gigante", + "avatar_url": "https://avatars.githubusercontent.com/u/8499679?v=4", + "profile": "https://github.com/scottgigante", + "contributions": [ + "code" + ] + }, + { + "login": "thierry-FreeBSD", + "name": "Thierry Thomas", + "avatar_url": "https://avatars.githubusercontent.com/u/6819982?v=4", + "profile": "http://people.freebsd.org/~thierry/", + "contributions": [ + "code" + ] + }, + { + "login": "willemvandenboom", + "name": "Willem van den Boom", + "avatar_url": "https://avatars.githubusercontent.com/u/41558513?v=4", + "profile": "https://github.com/willemvandenboom", + "contributions": [ + "code" + ] + }, + { + "login": "remysucre", + "name": "Yisu Remy Wang", + "avatar_url": "https://avatars.githubusercontent.com/u/6758001?v=4", + "profile": "https://github.com/remysucre", + "contributions": [ + "code" + ] + }, + { + "login": "yy", + "name": "YY Ahn", + "avatar_url": "https://avatars.githubusercontent.com/u/24250?v=4", + "profile": "https://yongyeol.com/", + "contributions": [ + "code" + ] + }, + { + "login": "kmankinen", + "name": "kmankinen", + "avatar_url": "https://avatars.githubusercontent.com/u/22212710?v=4", + "profile": "https://github.com/kmankinen", + "contributions": [ + "code" + ] + }, + { + "login": "odidev", + "name": "odidev", + "avatar_url": "https://avatars.githubusercontent.com/u/40816837?v=4", + "profile": "https://github.com/odidev", + "contributions": [ + "code" + ] + }, + { + "login": "sombreslames", + "name": "sombreslames", + "avatar_url": "https://avatars.githubusercontent.com/u/4037102?v=4", + "profile": "https://github.com/sombreslames", + "contributions": [ + "code" + ] + }, + { + "login": "szcf-weiya", + "name": "szcf-weiya", + "avatar_url": "https://avatars.githubusercontent.com/u/13688320?v=4", + "profile": "https://hohoweiya.xyz/", + "contributions": [ + "code" + ] + }, + { + "login": "tristanlatr", + "name": "tristanlatr", + "avatar_url": "https://avatars.githubusercontent.com/u/19967168?v=4", + "profile": "https://github.com/tristanlatr", + "contributions": [ + "code" + ] + } + ], + "contributorsPerLine": 7 +} diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 000000000..75652838e --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,92 @@ +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Tamás Nepusz

    💻

    Fabio Zanini

    💻

    Kevin Zhu

    💻

    Gábor Csárdi

    💻

    Szabolcs Horvát

    💻

    Vincent Traag

    💻

    deeenes

    💻

    Seungoh Han

    💻

    Artem V L

    💻

    Yesung(Isaac) Lee

    💻

    John Boy

    💻

    Casper da Costa-Luis

    💻

    Alberto Alcolea

    💻

    Árpád Horváth

    💻

    ebraminio

    💻

    Fabian Witter

    💻

    Jan Katins

    💻

    Nick Eubank

    💻

    Peter Scott

    💻

    Sriram-Pattabiraman

    💻

    Sviatoslav

    💻

    Ah-Young Nho

    💻

    Frederik Harwath

    💻

    Navid Dianati

    💻

    abe-winter

    💻

    Alejandro Rivero

    💻

    Ariki

    💻

    Casper van Elteren

    💻

    Charles Tapley Hoyt

    💻

    Christoph Gohlke

    💻

    Christopher Falter

    💻

    FredInChina

    💻

    Friso van Vollenhoven

    💻

    Gabor Szarnyas

    💻

    Gao Fangshu

    💻

    Grzegorz Chilczuk

    💻

    Gwyn Ciesla

    💻

    Hong Xu

    💻

    Jay Smith

    💻

    MapleCCC

    💻

    Marco Köpcke

    💻

    Markus Elfring

    💻

    Martino Mensio

    💻

    Matas

    💻

    Mike Lissner

    💻

    Philipp A.

    💻

    Puneetha Pai

    💻

    S Murthy

    💻

    Scott Gigante

    💻

    Thierry Thomas

    💻

    Willem van den Boom

    💻

    Yisu Remy Wang

    💻

    YY Ahn

    💻

    kmankinen

    💻

    odidev

    💻

    sombreslames

    💻

    szcf-weiya

    💻

    tristanlatr

    💻
    + + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file diff --git a/README.md b/README.md index 252e2289c..d5d0164e3 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ igraph. You can learn more about igraph [on our website](http://igraph.org/python/). +igraph is a collaborative work of many people from all around the world — +see the [list of contributors here](./CONTRIBUTORS.md). + ## Installation from PyPI We aim to provide wheels on PyPI for most of the stock Python versions; From ebef7af0e4b66da28288fa781c297fd62885f071 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Oct 2022 11:08:44 +0200 Subject: [PATCH 1129/1892] chore: bumped version number to 0.10.2 From 817e0aa289268d891b570179b6555eeee4fba8f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 21:08:47 +0200 Subject: [PATCH 1130/1892] build(deps): bump pypa/cibuildwheel from 2.10.2 to 2.11.1 (#596) Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.10.2 to 2.11.1. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.10.2...v2.11.1) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 696222403..491497be4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,14 +63,14 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -137,7 +137,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -196,7 +196,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.10.2 + uses: pypa/cibuildwheel@v2.11.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 41b00a5ddeb28bb8ff05f5a8f79a121ba65b0a1e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 18 Oct 2022 09:55:33 +1100 Subject: [PATCH 1131/1892] chore: change docs link in setup.py to use RTD from now on --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9938feaaf..ca25d2c52 100644 --- a/setup.py +++ b/setup.py @@ -907,7 +907,7 @@ def get_tag(self): "Bug Tracker": "https://github.com/igraph/python-igraph/issues", "Changelog": "https://github.com/igraph/python-igraph/blob/master/CHANGELOG.md", "CI": "https://github.com/igraph/python-igraph/actions", - "Documentation": "https://igraph.org/python/doc", + "Documentation": "https://igraph.readthedocs.io", "Source Code": "https://github.com/igraph/python-igraph", }, ext_modules=[igraph_extension], From 00b0291b8b989d4a6ea2dcc0f89996e8de1ed556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Tue, 18 Oct 2022 11:15:16 +0200 Subject: [PATCH 1132/1892] docs: update installation instructions (#598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: update installation instructions * doc: fix typo Co-authored-by: Tamás Nepusz --- doc/source/install.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 899d930b7..5b7b9dd3d 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -46,12 +46,12 @@ Like virtualenv, Conda also offers virtual environments. If you prefer that opti $ conda activate my_environment $ conda install -c conda-forge python-igraph -Linux package managers ----------------------- -|igraph|'s Python interface and its dependencies have been packaged for most popular Linux -distributions, including Arch Linux, Debian, Fedora, GNU Guix, NixOS, and Ubuntu. -|igraph| and its underlying C core are usually in two different packages, but -your package manager should take care of that dependency for you. +Package managers on Linux and other systems +------------------------------------------- +|igraph|'s Python interface and its dependencies are included in several package management +systems, including those of the most popular Linux distributions (Arch Linux, +Debian and Ubuntu, Fedora, GNU Guix, etc.) as well as some cross-platform systems like +NixPkgs or MacPorts. .. note:: |igraph| is updated quite often: if you need a more recent version than your package manager offers, use ``pip`` or ``conda`` as shown above. For bleeding-edge From e74779956c38ab79f40ddfc1cd14cf2561a1f792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Tue, 18 Oct 2022 16:44:34 +0200 Subject: [PATCH 1133/1892] docs: update Erdos-Renyi gallery example (#599) --- doc/examples_sphinx-gallery/erdos_renyi.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/examples_sphinx-gallery/erdos_renyi.py b/doc/examples_sphinx-gallery/erdos_renyi.py index 7f0e3b67a..cb3ddf530 100644 --- a/doc/examples_sphinx-gallery/erdos_renyi.py +++ b/doc/examples_sphinx-gallery/erdos_renyi.py @@ -5,10 +5,10 @@ Erdős-Rényi Graph ================= -This example demonstrates how to generate `Erdős-Rényi Graphs `_ using :meth:`igraph.GraphBase.Erdos_Renyi`. There are two variants of graphs: +This example demonstrates how to generate `Erdős–Rényi graphs `_ using :meth:`igraph.GraphBase.Erdos_Renyi`. There are two variants of graphs: -- ``Erdos_Renyi(n, p)`` will generate a graph where each edge between any two pair of nodes has an independent probability ``p`` of existing. -- ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. +- ``Erdos_Renyi(n, p)`` will generate a graph from the so-called :math:`G(n,p)` model where each edge between any two pair of nodes has an independent probability ``p`` of existing. +- ``Erdos_Renyi(n, m)`` will pick a graph uniformly at random out of all graphs with ``n`` nodes and ``m`` edges. This is referred to as the :math:`G(n,m)` model. We generate two graphs of each, so we can confirm that our graph generator is truly random. """ @@ -21,12 +21,12 @@ random.seed(0) # %% -# Then, we generate two Erdos Renyi graphs with identical parameters: +# Then, we generate two :math:`G(n,p)` Erdős–Rényi graphs with identical parameters: g1 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) g2 = ig.Graph.Erdos_Renyi(n=15, p=0.2, directed=False, loops=False) # %% -# For comparison, we also generate two Erdos Renyi graphs with a fixed number +# For comparison, we also generate two :math:`G(n,m)` Erdős–Rényi graphs with a fixed number # of edges: g3 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) g4 = ig.Graph.Erdos_Renyi(n=20, m=35, directed=False, loops=False) @@ -78,9 +78,3 @@ ) axs[1, 0].set_ylabel('N. edges') plt.show() - -# %% -# .. note:: -# -# Even when using the same random seed, results can still differ depending -# on the machine the code is being run from. From e5ff03ec141d17bb7e48c09cc362fe196b184ac3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 19 Oct 2022 15:08:58 +0200 Subject: [PATCH 1134/1892] fix: Graph.layout_lgl() root argument must be optional, fixes #600 --- src/_igraph/convert.c | 20 ++++++++++++++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 16 +++++++++------- tests/test_layouts.py | 8 ++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index f6842ee2a..d7591bb8e 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3209,6 +3209,26 @@ int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *g return 0; } +/** + * \ingroup python_interface_conversion + * \brief Tries to interpret a Python object as a single vertex ID, leaving + * the input vertex ID unmodified if the Python object is NULL or None + * + * \param o the Python object + * \param vid the vertex ID will be stored here + * \param graph the graph that will be used to interpret vertex names + * if a string was given in o. It may also be a null pointer + * if we don't need name lookups. + * \return 0 if everything was OK, 1 otherwise + */ +int igraphmodule_PyObject_to_optional_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph) { + if (o == 0 || o == Py_None) { + return 0; + } else { + return igraphmodule_PyObject_to_vid(o, vid, graph); + } +} + /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a vertex selector diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 39cc02eb5..def18da8c 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -119,6 +119,7 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t(PyObject *it, int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, igraph_vector_ptr_t *v, PyTypeObject **g_type); int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph); +int igraphmodule_PyObject_to_optional_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph); int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, igraph_t *graph, igraph_bool_t *return_single, igraph_integer_t *single_vid); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8359c0020..9527ebb49 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4886,11 +4886,11 @@ PyObject *igraphmodule_Graph_edge_connectivity(igraphmodule_GraphObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &source_o, &target_o, &checks)) return NULL; - if (source_o != Py_None && igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { + if (igraphmodule_PyObject_to_optional_vid(source_o, &source, &self->g)) { return NULL; } - if (target_o != Py_None && igraphmodule_PyObject_to_vid(target_o, &target, &self->g)) { + if (igraphmodule_PyObject_to_optional_vid(target_o, &target, &self->g)) { return NULL; } @@ -6490,11 +6490,11 @@ PyObject *igraphmodule_Graph_vertex_connectivity(igraphmodule_GraphObject *self, &source_o, &target_o, &checks, &neis)) return NULL; - if (source_o != Py_None && igraphmodule_PyObject_to_vid(source_o, &source, &self->g)) { + if (igraphmodule_PyObject_to_optional_vid(source_o, &source, &self->g)) { return NULL; } - if (target_o != Py_None && igraphmodule_PyObject_to_vid(target_o, &target, &self->g)) { + if (igraphmodule_PyObject_to_optional_vid(target_o, &target, &self->g)) { return NULL; } @@ -6921,7 +6921,7 @@ PyObject *igraphmodule_Graph_fundamental_cycles( if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &start_vid_o, &cutoff_o)) return NULL; - if (start_vid_o != Py_None && igraphmodule_PyObject_to_vid(start_vid_o, &start_vid, &self->g)) + if (igraphmodule_PyObject_to_optional_vid(start_vid_o, &start_vid, &self->g)) return NULL; if (cutoff_o != Py_None && igraphmodule_PyObject_to_integer_t(cutoff_o, &cutoff)) @@ -7170,8 +7170,9 @@ PyObject *igraphmodule_Graph_layout_star(igraphmodule_GraphObject* self, return NULL; } - if (igraphmodule_PyObject_to_vid(center_o, ¢er, &self->g)) + if (igraphmodule_PyObject_to_optional_vid(center_o, ¢er, &self->g)) { return NULL; + } if (order_o != Py_None) { order = (igraph_vector_int_t*)calloc(1, sizeof(igraph_vector_int_t)); @@ -7728,8 +7729,9 @@ PyObject *igraphmodule_Graph_layout_lgl(igraphmodule_GraphObject * self, if (cellsize <= 0) cellsize = sqrt(sqrt(area)); - if (igraphmodule_PyObject_to_vid(root_o, &proot, &self->g)) + if (igraphmodule_PyObject_to_optional_vid(root_o, &proot, &self->g)) { return NULL; + } if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); diff --git a/tests/test_layouts.py b/tests/test_layouts.py index e97f397f6..370a70a19 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -328,6 +328,14 @@ def testUMAP(self): lo_adj = g.layout_umap(dist=dist, epochs=1, sampling_prob=1, seed=lo.coords) self.assertTrue(isinstance(lo_adj, Layout)) + def testLGL(self): + g = Graph.GRG(100, 0.2) + lo = g.layout("lgl") + self.assertTrue(isinstance(lo, Layout)) + + g = Graph.GRG(100, 0.2) + lo = g.layout("lgl", root=5) + self.assertTrue(isinstance(lo, Layout)) def testReingoldTilford(self): g = Graph.Barabasi(100) From c8b4da32b7c964524beeb6b4d613e3891f6793d7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 20 Oct 2022 09:56:31 +0200 Subject: [PATCH 1135/1892] ci: test if removing a warning thrown by the LGL layout will fix the crashes in CI --- tests/test_layouts.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 370a70a19..ab514d84a 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -329,11 +329,10 @@ def testUMAP(self): self.assertTrue(isinstance(lo_adj, Layout)) def testLGL(self): - g = Graph.GRG(100, 0.2) + g = Graph.Barabasi(100) lo = g.layout("lgl") self.assertTrue(isinstance(lo, Layout)) - g = Graph.GRG(100, 0.2) lo = g.layout("lgl", root=5) self.assertTrue(isinstance(lo, Layout)) From 5df12f07bf8ad42f3d2d49d8daaa0f1a4fe9598e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 20 Oct 2022 14:21:57 +0200 Subject: [PATCH 1136/1892] chore: updated vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index bc7c16000..e36289996 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit bc7c160008ffe3d8dbc352c77add1571e282b519 +Subproject commit e362899966254cd8af61b1e64be5d7d8244ead3f From 0f6dd7bc1f96f1698704124babc136554ebe34a7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 21 Oct 2022 08:50:31 +1100 Subject: [PATCH 1137/1892] RTD badge in markdown --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d5d0164e3..5a2c789cb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) [![PyPI pyversions](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/igraph.svg)](https://pypi.python.org/pypi/igraph) +[![Documentation Status](https://readthedocs.org/projects/igraph/badge/?version=latest)](https://igraph.readthedocs.io/) Python interface for the igraph library --------------------------------------- From 03e42aa5d6052576d7d78106086d265cd680c9a2 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 21 Oct 2022 08:54:19 +1100 Subject: [PATCH 1138/1892] Clarify new/old docs --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a2c789cb..a7170229f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,9 @@ analysis of large graphs. This repository contains the source code to the Python interface of igraph. -You can learn more about igraph [on our website](http://igraph.org/python/). +Since version 0.10.2, the documentation is hosted on +[readthedocs](https://igraph.readthedocs.io). Earlier versions are documented +on [our old website](https://igraph.org/python/versions/0.10.1/). igraph is a collaborative work of many people from all around the world — see the [list of contributors here](./CONTRIBUTORS.md). From 8bc5d0aa07a85de4c27c72080e7c288cac850233 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 24 Oct 2022 10:47:12 +0200 Subject: [PATCH 1139/1892] doc: add explanation about potential incompatibilities when linking to different versions of the C core [ci skip] --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index a7170229f..c24867860 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,25 @@ from Homebrew. Due to the lack of support of `pkg-config` on Windows, it is currently not possible to build against an external library on Windows. +**Warning:** the Python interface is guaranteed to work only with the same +version of the C core that is vendored inside the `vendor/source/igraph` +folder. While we try hard not to break API or ABI in the C core of igraph +between minor versions in the 0.x branch and we will keep on doing so for major +versions once 1.0 is released, there are certain functions in the C API that +are marked as _experimental_ (see the documentation of the C core for details), +and we reserve the right to break the APIs of those functions, even if they are +already exposed in a higher-level interface. This is because the easiest way to +test these functions in real-life research scenarios is to expose them in one +of the higher level interfaces. Therefore, if you unbundle the vendored source +code of igraph and link to an external version instead, we can make no +guarantees about stability unless you link to the exact same version as the +one we have vendored in this source tree. + +If you are curious about which version of the Python interface is compatible +with which version of the C core, you can look up the corresponding tag in +Github and check which revision of the C core the repository points to in +the `vendor/source/igraph` submodule. + ## Compiling the development version If you want to install the development version, the easiest way to do so is to From 24fc2a8f03fb4fd897b27e3114540798364592d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Mon, 31 Oct 2022 08:40:25 +0100 Subject: [PATCH 1140/1892] docs: remove mention of betweenness "estimation" --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9527ebb49..efbdd72b2 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -13847,7 +13847,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" - "@return: the (possibly estimated) betweenness of the given vertices in a list\n"}, + "@return: the (possibly cutoff-limited) betweenness of the given vertices in a list\n"}, /* interface to biconnected_components */ {"biconnected_components", (PyCFunction) igraphmodule_Graph_biconnected_components, From f37f6a7416f44c4f9d6bdbebf47301497f1b167e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 13:32:44 +0000 Subject: [PATCH 1141/1892] build(deps): bump pypa/cibuildwheel from 2.11.1 to 2.11.2 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.11.1 to 2.11.2. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.11.1...v2.11.2) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 491497be4..2a8f70609 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,14 +63,14 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -137,7 +137,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -196,7 +196,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From a06d932c38dcf9d98bd86972bbf756af8f13f683 Mon Sep 17 00:00:00 2001 From: Adriankhl Date: Tue, 8 Nov 2022 16:50:15 +0100 Subject: [PATCH 1142/1892] feat: handle pandas nullable integer data type in Graph.DataFrame --- src/igraph/io/objects.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 0646263de..b731783fb 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -417,15 +417,22 @@ def _construct_graph_from_dataframe( raise ValueError("The 'vertices' DataFrame must contain at least one column") if use_vids: - if not ( - str(edges.dtypes[0]).startswith("int") - and str(edges.dtypes[1]).startswith("int") + if ( + str(edges.dtypes[0]).startswith(("int", "Int")) + and str(edges.dtypes[1]).startswith(("int", "Int")) ): + # Check pandas nullable integer data type: + # https://pandas.pydata.org/docs/user_guide/integer_na.html + if (edges.iloc[:, :2].isna()).any(axis=None): + raise ValueError("Source and target IDs must not be null") + + if (edges.iloc[:, :2] < 0).any(axis=None): + raise ValueError("Source and target IDs must not be negative") + else: raise TypeError( f"Source and target IDs must be 0-based integers, found types {edges.dtypes.tolist()[:2]}" ) - elif (edges.iloc[:, :2] < 0).any(axis=None): - raise ValueError("Source and target IDs must not be negative") + if vertices is not None: vertices = vertices.sort_index() if not vertices.index.equals( From ba2dbd1f63cb1844c0364a358ad0f6bc05eb3d8d Mon Sep 17 00:00:00 2001 From: Adriankhl Date: Tue, 8 Nov 2022 21:11:12 +0100 Subject: [PATCH 1143/1892] test: add tests for graph generation from pandas Int64 data type --- tests/test_generators.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_generators.py b/tests/test_generators.py index 88b319610..d9bdc4ed3 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -517,6 +517,11 @@ def testDataFrame(self): self.assertTrue(df_edges.equals(g_clone.get_edge_dataframe())) self.assertTrue(df_vertices.equals(g_clone.get_vertex_dataframe())) + # pandas Int64 data type + edges = pd.DataFrame(np.array([[0, 1], [1, 1], [1, 2]]), dtype="Int64") + g = Graph.DataFrame(edges) + self.assertTrue(g.vcount() == 3) + # Invalid input with self.assertRaisesRegex(ValueError, "two columns"): edges = pd.DataFrame({"source": [1, 2, 3]}) @@ -561,6 +566,9 @@ def testDataFrame(self): edges = pd.DataFrame({"source": [1, 2, 3], "target": [4, 5, 6]}) vertices = pd.DataFrame({0: [1, 2, 3]}, index=[0, 1, 2]) Graph.DataFrame(edges, vertices=vertices) + with self.assertRaisesRegex(ValueError, "null"): + edges = pd.DataFrame(np.array([[0, 1], [1, np.nan], [1, 2]]), dtype="Int64") + Graph.DataFrame(edges) def suite(): From 13f200a1f4bf5b50eed7b5649e5a39d829fa1e16 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 9 Nov 2022 08:43:59 +0100 Subject: [PATCH 1144/1892] chore: updated changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8cbd22f5..df018e649 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- `Graph.Data_Frame()` now handles the `Int64` data type from `pandas`, thanks + to [@Adriankhl](https://github.com/Adriankhl). See PR + [#609](https://github.com/igraph/python-igraph/pull/609) for details. + +- `Graph.layout_lgl()` `root` argument is now optional (as it should have been). + ## [0.10.2] - 2022-10-14 ### Added From 6685a7a63cc2911c48dbfb7b72822aec0a33bd22 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 17 Nov 2022 12:26:23 +0100 Subject: [PATCH 1145/1892] chore: updated vendored igraph, layout_umap() does not have sampling_prob any more --- src/_igraph/graphobject.c | 19 +++++++------------ tests/test_layouts.py | 16 +++------------- vendor/source/igraph | 2 +- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index efbdd72b2..f80d74a81 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8032,20 +8032,19 @@ PyObject *igraphmodule_Graph_layout_umap( igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = - { "dist", "dim", "seed", "min_dist", "epochs", "sampling_prob", NULL }; + { "dist", "dim", "seed", "min_dist", "epochs", NULL }; igraph_matrix_t m; igraph_vector_t *dist = 0; Py_ssize_t dim = 2; double min_dist = 0.01; - double sampling_prob = 0.3; Py_ssize_t epochs = 500; PyObject *dist_o = Py_None; PyObject *seed_o = Py_None; PyObject *result_o; igraph_bool_t use_seed = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOdnd", kwlist, &dist_o, - &dim, &seed_o, &min_dist, &epochs, &sampling_prob)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOdn", kwlist, &dist_o, + &dim, &seed_o, &min_dist, &epochs)) return NULL; CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); @@ -8088,7 +8087,7 @@ PyObject *igraphmodule_Graph_layout_umap( dist, (igraph_real_t)min_dist, (igraph_integer_t)epochs, - (igraph_real_t)sampling_prob)) { + /* distances_are_weights = */ 0)) { if (dist) { igraph_vector_destroy(dist); free(dist); } @@ -8102,7 +8101,7 @@ PyObject *igraphmodule_Graph_layout_umap( dist, (igraph_real_t)min_dist, (igraph_integer_t)epochs, - (igraph_real_t)sampling_prob)) { + /* distances_are_weights = */ 0)) { if (dist) { igraph_vector_destroy(dist); free(dist); } @@ -15618,9 +15617,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_umap", (PyCFunction) igraphmodule_Graph_layout_umap, METH_VARARGS | METH_KEYWORDS, - "layout_umap(\n" - " dist=None, dim=2, seed=None, min_dist=0.01,\n" - " epochs=500, sampling_prob=0.3)\n--\n\n" + "layout_umap(dist=None, dim=2, seed=None, min_dist=0.01, epochs=500)\n" + "--\n\n" "Uniform Manifold Approximation and Projection (UMAP).\n\n" "This layout is a probabilistic algorithm that places vertices that are connected\n" "and have a short distance close by in the embedded space.\n\n" @@ -15638,9 +15636,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " Values between 50 and 1000 are typical.\n" " Notice that UMAP does not technically converge for symmetry reasons, but a\n" " larger number of epochs should generally give an equivalent or better layout.\n" - "@param sampling_prob: the probability of sampling each vertex for repulsion at\n" - " each epoch or iteration. A higher probability will give better results but\n" - " also require more computations.\n" "@return: the calculated layout.\n\n" "@newfield ref: Reference\n" "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation\n" diff --git a/tests/test_layouts.py b/tests/test_layouts.py index ab514d84a..d0d936ac0 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -264,16 +264,6 @@ def testUMAP(self): epochs=-1, ) - self.assertRaises( - InternalError, g.layout_umap, - sampling_prob=-0.01, - ) - - self.assertRaises( - InternalError, g.layout_umap, - sampling_prob=1.01, - ) - self.assertRaises( ValueError, g.layout_umap, dim=1, @@ -303,7 +293,7 @@ def testUMAP(self): 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.08, 0.05, 0.1, 0.08, 0.12, 0.09, 0.11 ] g = Graph(edges) - lo = g.layout_umap(dist=dist, epochs=500, sampling_prob=0.3) + lo = g.layout_umap(dist=dist, epochs=500) self.assertTrue(isinstance(lo, Layout)) # One should get two clusters in this case @@ -321,11 +311,11 @@ def testUMAP(self): self.assertLess(dxy, 0.2 * distmax) # Test single epoch with seed - lo_adj = g.layout_umap(dist=dist, epochs=1, sampling_prob=1, seed=lo) + lo_adj = g.layout_umap(dist=dist, epochs=1, seed=lo) self.assertTrue(isinstance(lo_adj, Layout)) # Same but inputting the coordinates - lo_adj = g.layout_umap(dist=dist, epochs=1, sampling_prob=1, seed=lo.coords) + lo_adj = g.layout_umap(dist=dist, epochs=1, seed=lo.coords) self.assertTrue(isinstance(lo_adj, Layout)) def testLGL(self): diff --git a/vendor/source/igraph b/vendor/source/igraph index e36289996..857a5b7c0 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit e362899966254cd8af61b1e64be5d7d8244ead3f +Subproject commit 857a5b7c03bde9801f1dbbec492c0ce6d92e0845 From eb12fad390ec04955e8faa58f8ba5440d5954ed3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 17 Nov 2022 13:10:48 +0100 Subject: [PATCH 1146/1892] refactor: rewrite PyObject-to-matrix conversion routines to use the existing PyObject-to-real and PyObject-to-integer conversion functions --- src/_igraph/convert.c | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index d7591bb8e..27be5410d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2583,7 +2583,7 @@ int igraphmodule_PyList_to_matrix_t(PyObject* o, igraph_matrix_t *m) { int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igraph_matrix_t *m, int min_cols) { Py_ssize_t nr, nc, n, i, j; PyObject *row, *item; - int was_warned = 0; + igraph_real_t value; /* calculate the matrix dimensions */ if (!PySequence_Check(o) || PyUnicode_Check(o)) { @@ -2613,17 +2613,12 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap n = PySequence_Size(row); for (j = 0; j < n; j++) { item = PySequence_GetItem(row, j); - if (PyLong_Check(item)) { - MATRIX(*m, i, j) = PyLong_AsLong(item); - } else if (PyLong_Check(item)) { - MATRIX(*m, i, j) = PyLong_AsLong(item); - } else if (PyFloat_Check(item)) { - MATRIX(*m, i, j) = PyFloat_AsDouble(item); - } else if (!was_warned) { - PY_IGRAPH_WARN("non-numeric value in matrix ignored"); - was_warned=1; + if (igraphmodule_PyObject_to_real_t(item, &value)) { + Py_DECREF(item); + return 1; } Py_DECREF(item); + MATRIX(*m, i, j) = value; } Py_DECREF(row); } @@ -2656,11 +2651,11 @@ int igraphmodule_PyList_to_matrix_int_t(PyObject* o, igraph_matrix_int_t *m) { int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols) { Py_ssize_t nr, nc, n, i, j; PyObject *row, *item; - int ok, was_warned = 0; + igraph_integer_t value; /* calculate the matrix dimensions */ if (!PySequence_Check(o) || PyUnicode_Check(o)) { - PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + PyErr_SetString(PyExc_TypeError, "integer matrix expected (list of sequences)"); return 1; } @@ -2670,7 +2665,7 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i row = PySequence_GetItem(o, i); if (!PySequence_Check(row)) { Py_DECREF(row); - PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + PyErr_SetString(PyExc_TypeError, "integer matrix expected (list of sequences)"); return 1; } n = PySequence_Size(row); @@ -2686,23 +2681,12 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i n = PySequence_Size(row); for (j = 0; j < n; j++) { item = PySequence_GetItem(row, j); - ok = 1; - if (PyLong_Check(item)) { - if (igraphmodule_PyObject_to_integer_t(item, &MATRIX(*m, i, j))) { - ok = 0; - } - } else if (PyFloat_Check(item)) { - MATRIX(*m, i, j) = (igraph_integer_t)PyFloat_AsDouble(item); - } else { - ok = 0; - } - - if (!ok && !was_warned) { - PY_IGRAPH_WARN("non-numeric value in matrix ignored"); - was_warned = 1; + if (igraphmodule_PyObject_to_integer_t(item, &value)) { + Py_DECREF(item); + return 1; } - Py_DECREF(item); + MATRIX(*m, i, j) = value; } Py_DECREF(row); } From 4c04738810abfb4a44a2ef08c48bd4b08b07a199 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 17 Nov 2022 17:12:57 +0100 Subject: [PATCH 1147/1892] fix: improved error message for matrix conversions, closes #610 --- src/_igraph/convert.c | 58 ++++++++++++++++++++++++++++++------- src/_igraph/convert.h | 8 +++--- src/_igraph/graphobject.c | 59 ++++++++++++++++++++------------------ src/_igraph/igraphmodule.c | 4 ++- 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 27be5410d..708a0493d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2564,10 +2564,14 @@ PyObject* igraphmodule_graph_list_t_to_PyList(igraph_graph_list_t *v, PyTypeObje * * \param o the Python object representing the list of lists * \param m the address of an uninitialized \c igraph_matrix_t + * \param arg_name name of the argument we are attempting to convert, if + * applicable. May be used in error messages. * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. */ -int igraphmodule_PyList_to_matrix_t(PyObject* o, igraph_matrix_t *m) { - return igraphmodule_PyList_to_matrix_t_with_minimum_column_count(o, m, 0); +int igraphmodule_PyList_to_matrix_t( + PyObject* o, igraph_matrix_t *m, const char *arg_name +) { + return igraphmodule_PyList_to_matrix_t_with_minimum_column_count(o, m, 0, arg_name); } /** @@ -2578,16 +2582,24 @@ int igraphmodule_PyList_to_matrix_t(PyObject* o, igraph_matrix_t *m) { * \param o the Python object representing the list of lists * \param m the address of an uninitialized \c igraph_matrix_t * \param num_cols the minimum number of columns in the matrix + * \param arg_name name of the argument we are attempting to convert, if + * applicable. May be used in error messages. * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. */ -int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igraph_matrix_t *m, int min_cols) { +int igraphmodule_PyList_to_matrix_t_with_minimum_column_count( + PyObject *o, igraph_matrix_t *m, int min_cols, const char *arg_name +) { Py_ssize_t nr, nc, n, i, j; PyObject *row, *item; igraph_real_t value; /* calculate the matrix dimensions */ if (!PySequence_Check(o) || PyUnicode_Check(o)) { - PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + if (arg_name) { + PyErr_Format(PyExc_TypeError, "matrix expected in '%s'", arg_name); + } else { + PyErr_SetString(PyExc_TypeError, "matrix expected"); + } return 1; } @@ -2597,7 +2609,11 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap row = PySequence_GetItem(o, i); if (!PySequence_Check(row)) { Py_DECREF(row); - PyErr_SetString(PyExc_TypeError, "matrix expected (list of sequences)"); + if (arg_name) { + PyErr_Format(PyExc_TypeError, "matrix expected in '%s'", arg_name); + } else { + PyErr_SetString(PyExc_TypeError, "matrix expected"); + } return 1; } n = PySequence_Size(row); @@ -2632,10 +2648,14 @@ int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igrap * * \param o the Python object representing the list of lists * \param m the address of an uninitialized \c igraph_matrix_int_t + * \param arg_name name of the argument we are attempting to convert, if + * applicable. May be used in error messages. * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. */ -int igraphmodule_PyList_to_matrix_int_t(PyObject* o, igraph_matrix_int_t *m) { - return igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(o, m, 0); +int igraphmodule_PyList_to_matrix_int_t( + PyObject* o, igraph_matrix_int_t *m, const char* arg_name +) { + return igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(o, m, 0, arg_name); } /** @@ -2646,16 +2666,24 @@ int igraphmodule_PyList_to_matrix_int_t(PyObject* o, igraph_matrix_int_t *m) { * \param o the Python object representing the list of lists * \param m the address of an uninitialized \c igraph_matrix_int_t * \param num_cols the minimum number of columns in the matrix + * \param arg_name name of the argument we are attempting to convert, if + * applicable. May be used in error messages. * \return 0 if everything was OK, 1 otherwise. Sets appropriate exceptions. */ -int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols) { +int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count( + PyObject *o, igraph_matrix_int_t *m, int min_cols, const char* arg_name +) { Py_ssize_t nr, nc, n, i, j; PyObject *row, *item; igraph_integer_t value; /* calculate the matrix dimensions */ if (!PySequence_Check(o) || PyUnicode_Check(o)) { - PyErr_SetString(PyExc_TypeError, "integer matrix expected (list of sequences)"); + if (arg_name) { + PyErr_Format(PyExc_TypeError, "integer matrix expected in '%s'", arg_name); + } else { + PyErr_SetString(PyExc_TypeError, "integer matrix expected"); + } return 1; } @@ -2665,7 +2693,11 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i row = PySequence_GetItem(o, i); if (!PySequence_Check(row)) { Py_DECREF(row); - PyErr_SetString(PyExc_TypeError, "integer matrix expected (list of sequences)"); + if (arg_name) { + PyErr_Format(PyExc_TypeError, "integer matrix expected in '%s'", arg_name); + } else { + PyErr_SetString(PyExc_TypeError, "integer matrix expected"); + } return 1; } n = PySequence_Size(row); @@ -2675,7 +2707,11 @@ int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, i } } - igraph_matrix_int_init(m, nr, nc); + if (igraph_matrix_int_init(m, nr, nc)) { + igraphmodule_handle_igraph_error(); + return 1; + } + for (i = 0; i < nr; i++) { row = PySequence_GetItem(o, i); n = PySequence_Size(row); diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index def18da8c..c4c895458 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -107,10 +107,10 @@ int igraphmodule_PyObject_to_edgelist( igraph_bool_t *list_is_owned ); -int igraphmodule_PyList_to_matrix_t(PyObject *o, igraph_matrix_t *m); -int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igraph_matrix_t *m, int min_cols); -int igraphmodule_PyList_to_matrix_int_t(PyObject *o, igraph_matrix_int_t *m); -int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols); +int igraphmodule_PyList_to_matrix_t(PyObject *o, igraph_matrix_t *m, const char *arg_name); +int igraphmodule_PyList_to_matrix_t_with_minimum_column_count(PyObject *o, igraph_matrix_t *m, int min_cols, const char *arg_name); +int igraphmodule_PyList_to_matrix_int_t(PyObject *o, igraph_matrix_int_t *m, const char *arg_name); +int igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(PyObject *o, igraph_matrix_int_t *m, int min_cols, const char *arg_name); PyObject* igraphmodule_strvector_t_to_PyList(igraph_strvector_t *v); int igraphmodule_PyList_to_strvector_t(PyObject* v, igraph_strvector_t *result); int igraphmodule_PyList_to_existing_strvector_t(PyObject* v, igraph_strvector_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f80d74a81..f0a45b037 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1944,9 +1944,7 @@ PyObject *igraphmodule_Graph_Adjacency(PyTypeObject * type, if (igraphmodule_PyObject_to_loops_t(loops_o, &loops)) return NULL; - if (igraphmodule_PyList_to_matrix_t(matrix, &m)) { - PyErr_SetString(PyExc_TypeError, - "Error while converting adjacency matrix"); + if (igraphmodule_PyList_to_matrix_t(matrix, &m, "matrix")) { return NULL; } @@ -2280,9 +2278,7 @@ PyObject *igraphmodule_Graph_Establishment(PyTypeObject * type, types = PyList_Size(type_dist); - if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) { - PyErr_SetString(PyExc_TypeError, - "Error while converting preference matrix"); + if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm, "pref_matrix")) { return NULL; } if (igraph_matrix_nrow(&pm) != igraph_matrix_ncol(&pm) || @@ -2614,10 +2610,8 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, return NULL; } - if (igraphmodule_PyList_to_matrix_t(matrix_o, &matrix)) { + if (igraphmodule_PyList_to_matrix_t(matrix_o, &matrix, "matrix")) { igraph_vector_bool_destroy(&vertex_types); - PyErr_SetString(PyExc_TypeError, - "Error while converting incidence matrix"); return NULL; } @@ -2932,7 +2926,9 @@ NULL }; CHECK_SSIZE_T_RANGE(n, "vertex count"); types = PyList_Size(type_dist); - if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) return NULL; + if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm, "pref_matrix")) { + return NULL; + } if (igraphmodule_PyObject_float_to_vector_t(type_dist, &td)) { igraph_matrix_destroy(&pm); return NULL; @@ -3022,8 +3018,10 @@ PyObject *igraphmodule_Graph_Asymmetric_Preference(PyTypeObject * type, CHECK_SSIZE_T_RANGE(n, "vertex count"); - if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm)) return NULL; - if (igraphmodule_PyList_to_matrix_t(type_dist_matrix, &td)) { + if (igraphmodule_PyList_to_matrix_t(pref_matrix, &pm, "pref_matrix")) { + return NULL; + } + if (igraphmodule_PyList_to_matrix_t(type_dist_matrix, &td, "type_dist_matrix")) { igraph_matrix_destroy(&pm); return NULL; } @@ -3279,7 +3277,7 @@ PyObject *igraphmodule_Graph_SBM(PyTypeObject * type, CHECK_SSIZE_T_RANGE(n, "vertex count"); - if (igraphmodule_PyList_to_matrix_t(pref_matrix_o, &pref_matrix)) { + if (igraphmodule_PyList_to_matrix_t(pref_matrix_o, &pref_matrix, "pref_matrix")) { return NULL; } @@ -3615,9 +3613,7 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, } else if (igraphmodule_PyObject_to_loops_t(loops_o, &loops)) return NULL; - if (igraphmodule_PyList_to_matrix_t(matrix, &m)) { - PyErr_SetString(PyExc_TypeError, - "Error while converting adjacency matrix"); + if (igraphmodule_PyList_to_matrix_t(matrix, &m, "matrix")) { return NULL; } @@ -7261,8 +7257,10 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * return NULL; } } else { - use_seed=1; - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; + use_seed = 1; + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { + return NULL; + } } /* Convert minimum and maximum x-y-z values */ @@ -7398,10 +7396,10 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel return NULL; } } else { - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) { + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { return NULL; } - use_seed=1; + use_seed = 1; } retval = igraph_layout_davidson_harel(&self->g, &m, use_seed, @@ -7467,10 +7465,10 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, return NULL; } } else { - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) { + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { return NULL; } - use_seed=1; + use_seed = 1; } /* Convert the weight parameter to a vector */ @@ -7566,8 +7564,10 @@ PyObject return NULL; } } else { - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; - use_seed=1; + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { + return NULL; + } + use_seed = 1; } /* Convert the weight parameter to a vector */ @@ -7675,8 +7675,9 @@ PyObject *igraphmodule_Graph_layout_graphopt(igraphmodule_GraphObject *self, } } else { use_seed = 1; - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) - return NULL; + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { + return NULL; + } } if (igraph_layout_graphopt(&self->g, &m, niter, @@ -7783,7 +7784,7 @@ PyObject *igraphmodule_Graph_layout_mds(igraphmodule_GraphObject * self, PyErr_NoMemory(); return NULL; } - if (igraphmodule_PyList_to_matrix_t(dist_o, dist)) { + if (igraphmodule_PyList_to_matrix_t(dist_o, dist, "dist")) { free(dist); return NULL; } @@ -8063,7 +8064,9 @@ PyObject *igraphmodule_Graph_layout_umap( } } else { use_seed = 1; - if (igraphmodule_PyList_to_matrix_t(seed_o, &m)) return NULL; + if (igraphmodule_PyList_to_matrix_t(seed_o, &m, "seed")) { + return NULL; + } } /* Initialize distances */ diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index e702035cb..bcabc487f 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -358,7 +358,9 @@ PyObject* igraphmodule_community_to_membership(PyObject *self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!nn|O", kwlist, &PyList_Type, &merges_o, &nodes, &steps, &return_csize)) return NULL; - if (igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(merges_o, &merges, 2)) return NULL; + if (igraphmodule_PyList_to_matrix_int_t_with_minimum_column_count(merges_o, &merges, 2, "merges")) { + return NULL; + } CHECK_SSIZE_T_RANGE(nodes, "number of nodes"); CHECK_SSIZE_T_RANGE(steps, "number of steps"); From a1a565f758baa6f249b18ca4087886c7e8bcc96a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 20 Nov 2022 09:45:41 +1100 Subject: [PATCH 1148/1892] Adapt docs for new umap API --- src/_igraph/graphobject.c | 51 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f0a45b037..187efd4a6 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -15616,17 +15616,54 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Internal function, undocumented.\n\n" "@see: Graph.layout_sugiyama()\n\n"}, + /* interface to igraph_layout_umap_compute_weights */ + {"layout_umap_compute_weights", + (PyCFunction) igraphmodule_Graph_layout_umap_compute_weights, + METH_VARARGS | METH_KEYWORDS, + "layout_umap_compute_weights(dist)\n" + "--\n\n" + "@param dist: distances associated with the graph edges.\n" + "@return: Symmetrized weights associated with each edge. If the distance\n" + " graph has both directed edges between a pair of vertices, one of the\n" + " returned weights will be set to zero.\n\n" + "Compute undirected UMAP weights from directed distance graph.\n\n" + "UMAP is a layout algorithm that usually takes as input a directed\n" + "distance graph, e.g. a k nearest neighbor graph based on Euclidean\n" + "distance between points in a vector space. The graph is directed\n" + "because vertex v1 might consider vertex v2 a close neighbor, but v2\n" + "itself might have many neighbors that are closer than v1.\n" + "This function computes the symmetrized weights from the distance graph\n" + "using union as the symmetry operator. In simple terms, if either vertex\n" + "considers the other a close neighbor, they will be treated as close\n" + "neighbors.\n\n" + "This function can be used as a separate preprocessing step to\n" + "Graph.layout_umap(). For efficiency reasons, the returned weights have the\n" + "same length as the input distances, however because of the symmetryzation\n" + "some information is lost. Therefore, the weight of one of the edges is set\n" + "to zero whenever edges in opposite directions are found in the input\n" + "distance graph. You can pipe the output of this function directly into\n" + "Graph.layout_umap() as follows:\n" + "C{weights = graph.layout_umap_compute_weights(dist)}\n" + "C{layout = graph.layout_umap(weights=weights)}\n\n" + "@see: Graph.layout_umap()\n\n"}, + /* interface to igraph_layout_umap */ {"layout_umap", (PyCFunction) igraphmodule_Graph_layout_umap, METH_VARARGS | METH_KEYWORDS, - "layout_umap(dist=None, dim=2, seed=None, min_dist=0.01, epochs=500)\n" + "layout_umap(dist=None, weights=None, dim=2, seed=None, min_dist=0.01, epochs=500)\n" "--\n\n" "Uniform Manifold Approximation and Projection (UMAP).\n\n" "This layout is a probabilistic algorithm that places vertices that are connected\n" "and have a short distance close by in the embedded space.\n\n" "@param dist: distances associated with the graph edges. If None, all edges will\n" - " be assumed to convey the same distance between the vertices.\n" + " be assumed to convey the same distance between the vertices. Either this\n" + " argument of the C{weights} argument can be set, but not both. It is fine to\n" + " set neither.\n" + "@param weights: precomputed edge weights if you have them, as an alternative\n" + " to setting the C{dist} argument. Zero weights will be ignored if this\n" + " argument is set, e.g. if you computed the weights via\n" + " Graph.layout_umap_compute_weights().\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" "@param seed: if C{None}, uses a random starting layout for the\n" @@ -15640,9 +15677,17 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " Notice that UMAP does not technically converge for symmetry reasons, but a\n" " larger number of epochs should generally give an equivalent or better layout.\n" "@return: the calculated layout.\n\n" + "Please note that if distances are set, the graph is usually directed, whereas\n" + "if weights are precomputed, the graph will be treated as undirected. A special\n" + "case is when the graph is directed but the precomputed weights are symmetrized\n" + "in a way only one of each pair of opposite edges has nonzero weight, e.g. as\n" + "computed by Graph.layout_umap_compute_weights(). For example:\n" + "C{weights = graph.layout_umap_compute_weights(dist)}\n" + "C{layout = graph.layout_umap(weights=weights)}\n\n" "@newfield ref: Reference\n" "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation\n" - " and Projection for Dimension Reduction. arXiv:1802.03426."}, + " and Projection for Dimension Reduction. arXiv:1802.03426.\n" + "@see: Graph.layout_umap_compute_weights()\n\n"}, //////////////////////////// // VISITOR-LIKE FUNCTIONS // From fa14bf90ebb76ce610c8ee66ea80d16a2efbf099 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 20 Nov 2022 15:18:42 +1100 Subject: [PATCH 1149/1892] Write interface function for weight computation and adapt the layout one --- src/_igraph/graphobject.c | 90 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 187efd4a6..0c448bf2e 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8033,19 +8033,20 @@ PyObject *igraphmodule_Graph_layout_umap( igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = - { "dist", "dim", "seed", "min_dist", "epochs", NULL }; + { "dist", "weights", "dim", "seed", "min_dist", "epochs", NULL }; igraph_matrix_t m; igraph_vector_t *dist = 0; Py_ssize_t dim = 2; double min_dist = 0.01; Py_ssize_t epochs = 500; - PyObject *dist_o = Py_None; + PyObject *dist_o = Py_None, *weights_o = Py_None; PyObject *seed_o = Py_None; PyObject *result_o; igraph_bool_t use_seed = 0; + igraph_bool_t distances_are_weights = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOdn", kwlist, &dist_o, - &dim, &seed_o, &min_dist, &epochs)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOnOdn", kwlist, &dist_o, + &weights_o, &dim, &seed_o, &min_dist, &epochs)) return NULL; CHECK_SSIZE_T_RANGE_POSITIVE(dim, "number of dimensions"); @@ -8056,6 +8057,12 @@ PyObject *igraphmodule_Graph_layout_umap( CHECK_SSIZE_T_RANGE_POSITIVE(epochs, "number of epochs"); + /* Check whether distances and weights are both set, which is not allowed */ + if ((dist_o != Py_None) && (weights_o != Py_None)) { + PyErr_SetString(PyExc_ValueError, "dist and weights cannot be both set"); + return NULL; + } + /* Precomputed starting layout */ if (seed_o == 0 || seed_o == Py_None) { if (igraph_matrix_init(&m, 1, 1)) { @@ -8069,7 +8076,7 @@ PyObject *igraphmodule_Graph_layout_umap( } } - /* Initialize distances */ + /* Initialize distances or weights */ if (dist_o != Py_None) { dist = (igraph_vector_t*)malloc(sizeof(igraph_vector_t)); if (!dist) { @@ -8082,6 +8089,21 @@ PyObject *igraphmodule_Graph_layout_umap( free(dist); return NULL; } + } else if (weights_o != Py_None) { + distances_are_weights = 1; + /* they are actually weights, but let's keep them into the same variable + * for simplicity */ + dist = (igraph_vector_t*)malloc(sizeof(igraph_vector_t)); + if (!dist) { + igraph_matrix_destroy(&m); + PyErr_NoMemory(); + return NULL; + } + if (igraphmodule_PyObject_to_vector_t(weights_o, dist, 0)) { + igraph_matrix_destroy(&m); + free(dist); + return NULL; + } } if (dim == 2) { @@ -8090,7 +8112,7 @@ PyObject *igraphmodule_Graph_layout_umap( dist, (igraph_real_t)min_dist, (igraph_integer_t)epochs, - /* distances_are_weights = */ 0)) { + distances_are_weights)) { if (dist) { igraph_vector_destroy(dist); free(dist); } @@ -8104,7 +8126,7 @@ PyObject *igraphmodule_Graph_layout_umap( dist, (igraph_real_t)min_dist, (igraph_integer_t)epochs, - /* distances_are_weights = */ 0)) { + distances_are_weights)) { if (dist) { igraph_vector_destroy(dist); free(dist); } @@ -8123,6 +8145,60 @@ PyObject *igraphmodule_Graph_layout_umap( return (PyObject *) result_o; } +/** \ingroup python_interface_graph + * \brief Compute weights for Uniform Manifold Approximation and Projection (UMAP) + * \return the weights given that graph + * \sa igraph_layout_umap_compute_weights + */ +PyObject *igraphmodule_Graph_layout_umap( + igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) +{ + static char *kwlist[] = + { "dist", NULL }; + igraph_vector_t *dist = 0; + igraph_vector_t weights; + PyObject *dist_o = Py_None; + PyObject *result_o; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &dist_o)) + return NULL; + + /* Initialize distances */ + if (dist_o != Py_None) { + dist = (igraph_vector_t*)malloc(sizeof(igraph_vector_t)); + if (!dist) { + PyErr_NoMemory(); + return NULL; + } + if (igraphmodule_PyObject_to_vector_t(dist_o, dist, 0)) { + free(dist); + return NULL; + } + + /* Initialize weights */ + if (igraph_vector_init(&weights, 0)) { + igraph_vector_destroy(dist); free(dist); + PyErr_NoMemory(); + return NULL; + } + + /* Call the function */ + if (igraph_layout_umap_compute_weights(graph, dist, &weights)) { + igraph_vector_destroy(&weights); + igraph_vector_destroy(dist); free(dist); + PyErr_NoMemory(); + return NULL; + } + igraph_vector_destroy(dist); free(dist); + + /* Convert output to Python list */ + result_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); + igraph_vector_destroy(&weights); + return (PyObject *) result_o; + +} + + /** \ingroup python_interface_graph * \brief Places the vertices of a bipartite graph according to a simple two-layer * Sugiyama layout. From 0b03d1ea5df5b3dcc39aaa91c2fb54bb98d78290 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 20 Nov 2022 15:23:01 +1100 Subject: [PATCH 1150/1892] Typo in function call --- src/_igraph/graphobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 0c448bf2e..3d715c18b 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8150,7 +8150,7 @@ PyObject *igraphmodule_Graph_layout_umap( * \return the weights given that graph * \sa igraph_layout_umap_compute_weights */ -PyObject *igraphmodule_Graph_layout_umap( +PyObject *igraphmodule_Graph_layout_umap_compute_weights( igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = @@ -8183,7 +8183,7 @@ PyObject *igraphmodule_Graph_layout_umap( } /* Call the function */ - if (igraph_layout_umap_compute_weights(graph, dist, &weights)) { + if (igraph_layout_umap_compute_weights(&self->g, dist, &weights)) { igraph_vector_destroy(&weights); igraph_vector_destroy(dist); free(dist); PyErr_NoMemory(); From 9fc467c75fa426cf4a6408c83e8eac95475763f8 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 22 Nov 2022 10:00:19 +1100 Subject: [PATCH 1151/1892] Compiles locally --- src/_igraph/graphobject.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 3d715c18b..4216d52a3 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8153,8 +8153,7 @@ PyObject *igraphmodule_Graph_layout_umap( PyObject *igraphmodule_Graph_layout_umap_compute_weights( igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = - { "dist", NULL }; + static char *kwlist[] = { "dist", NULL }; igraph_vector_t *dist = 0; igraph_vector_t weights; PyObject *dist_o = Py_None; @@ -8174,6 +8173,7 @@ PyObject *igraphmodule_Graph_layout_umap_compute_weights( free(dist); return NULL; } + } /* Initialize weights */ if (igraph_vector_init(&weights, 0)) { @@ -8195,7 +8195,6 @@ PyObject *igraphmodule_Graph_layout_umap_compute_weights( result_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&weights); return (PyObject *) result_o; - } From 25996e35caf326ee36884e68d4195e05534ce587 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 22 Nov 2022 10:24:35 +1100 Subject: [PATCH 1152/1892] Test for weight computation --- src/igraph/__init__.py | 2 +- tests/test_layouts.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index fa15e680d..2eeedc3e9 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -963,7 +963,7 @@ def __reduce__(self): for name in dir(Graph): if not name.startswith("layout_"): continue - if name in ("layout_auto", "layout_sugiyama"): + if name in ("layout_auto", "layout_sugiyama", "layout_umap_compute_weights"): continue setattr(Graph, name, _layout_method_wrapper(getattr(Graph, name))) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index d0d936ac0..c6e0079bc 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -318,6 +318,17 @@ def testUMAP(self): lo_adj = g.layout_umap(dist=dist, epochs=1, seed=lo.coords) self.assertTrue(isinstance(lo_adj, Layout)) + def testUMAPComputeWeights(self): + edges = [0, 1, 0, 2, 1, 2, 1, 3, 2, 3, 2, 0] + edges = list(zip(edges[::2], edges[1::2])) + dist = [1, 1.5, 1.8, 2.0, 3.4, 0.5] + # NOTE: you need a directed graph to make sense of the symmetryzation + g = Graph(edges, directed=True) + weights = g.layout_umap_compute_weights(dist) + self.assertEqual( + weights, + [1.0, 1.0, 1.0, 1.1253517471925912e-07, 6.14421235332821e-06, 0.0]) + def testLGL(self): g = Graph.Barabasi(100) lo = g.layout("lgl") From f5d82fc5da37e52b2e1d170c07fde81ca35a736a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 22 Nov 2022 12:54:42 +0100 Subject: [PATCH 1153/1892] style: replaced most usages of 0/1 with false/true for booleans --- src/_igraph/attributes.c | 6 +-- src/_igraph/common.h | 2 + src/_igraph/convert.c | 26 +++++------ src/_igraph/dfsiter.c | 2 +- src/_igraph/edgeseqobject.c | 2 +- src/_igraph/graphobject.c | 86 +++++++++++++++++------------------ src/_igraph/igraphmodule.c | 2 +- src/_igraph/indexing.c | 28 ++++++------ src/_igraph/pyhelpers.c | 10 ++-- src/_igraph/vertexobject.c | 20 ++++---- src/_igraph/vertexseqobject.c | 2 +- 11 files changed, 95 insertions(+), 91 deletions(-) diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index b5ba31af8..26bc5ee77 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -85,7 +85,7 @@ int igraphmodule_i_attribute_struct_index_vertex_names( igraphmodule_i_attribute_struct *attrs, igraph_bool_t force) { Py_ssize_t n = 0; PyObject *name_list, *key, *value; - igraph_bool_t success = 0; + igraph_bool_t success = false; if (attrs->vertex_name_index && !force) { return 0; @@ -102,7 +102,7 @@ int igraphmodule_i_attribute_struct_index_vertex_names( name_list = PyDict_GetItemString(attrs->attrs[ATTRHASH_IDX_VERTEX], "name"); if (name_list == 0) { - success = 1; + success = true; goto cleanup; } @@ -143,7 +143,7 @@ int igraphmodule_i_attribute_struct_index_vertex_names( n--; } - success = 1; + success = true; cleanup: if (!success) { diff --git a/src/_igraph/common.h b/src/_igraph/common.h index 31a434353..388591035 100644 --- a/src/_igraph/common.h +++ b/src/_igraph/common.h @@ -23,6 +23,8 @@ #ifndef PYTHON_COMMON_H #define PYTHON_COMMON_H +#include + #include "preamble.h" #ifdef RC_DEBUG diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 708a0493d..1405e989d 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1038,7 +1038,7 @@ int igraphmodule_PyObject_to_vector_t(PyObject *list, igraph_vector_t *v, igraph it = PyObject_GetIter(list); if (it) { while ((item = PyIter_Next(it)) != 0) { - ok = 1; + ok = true; if (igraphmodule_PyObject_to_integer_t(item, &number)) { PyErr_SetString(PyExc_ValueError, "iterable must yield integers"); @@ -1144,7 +1144,7 @@ int igraphmodule_PyObject_float_to_vector_t(PyObject *list, igraph_vector_t *v) it = PyObject_GetIter(list); if (it) { while ((item = PyIter_Next(it)) != 0) { - ok = 1; + ok = true; if (igraphmodule_PyObject_to_real_t(item, &number)) { PyErr_SetString(PyExc_ValueError, "iterable must yield numbers"); @@ -1222,7 +1222,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v while ((item = PyIter_Next(it)) != 0) { if (!PyNumber_Check(item)) { PyErr_SetString(PyExc_TypeError, "iterable must return numbers"); - ok = 0; + ok = false; } else { ok = (igraphmodule_PyObject_to_integer_t(item, &value) == 0); } @@ -1267,7 +1267,7 @@ int igraphmodule_PyObject_to_vector_int_t(PyObject *list, igraph_vector_int_t *v if (item) { if (!PyNumber_Check(item)) { PyErr_SetString(PyExc_TypeError, "sequence elements must be integers"); - ok = 0; + ok = false; } else { ok = (igraphmodule_PyObject_to_integer_t(item, &value) == 0); } @@ -1795,10 +1795,10 @@ int igraphmodule_PyObject_to_edgelist( } while ((item = PyIter_Next(it)) != 0) { - ok = 1; + ok = true; if (!PySequence_Check(item) || PySequence_Size(item) != 2) { PyErr_SetString(PyExc_TypeError, "iterable must return pairs of integers or strings"); - ok = 0; + ok = false; } else { i1 = PySequence_GetItem(item, 0); i2 = i1 ? PySequence_GetItem(item, 1) : 0; @@ -1813,11 +1813,11 @@ int igraphmodule_PyObject_to_edgelist( if (ok) { if (igraph_vector_int_push_back(v, idx1)) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } if (ok && igraph_vector_int_push_back(v, idx2)) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } } @@ -3067,7 +3067,7 @@ int igraphmodule_PyList_to_existing_strvector_t(PyObject* v, igraph_strvector_t for (i = 0; i < n; i++) { PyObject *item = PyList_GetItem(v, i); char* ptr; - igraph_bool_t will_free = 0; + igraph_bool_t will_free = false; if (PyUnicode_Check(item)) { ptr = PyUnicode_CopyAsString(item); @@ -3075,7 +3075,7 @@ int igraphmodule_PyList_to_existing_strvector_t(PyObject* v, igraph_strvector_t igraph_strvector_destroy(result); return 1; } - will_free = 1; + will_free = true; } else { o = PyObject_Str(item); if (o == 0) { @@ -3088,7 +3088,7 @@ int igraphmodule_PyList_to_existing_strvector_t(PyObject* v, igraph_strvector_t igraph_strvector_destroy(result); return 1; } - will_free = 1; + will_free = true; } if (igraph_strvector_set(result, i, ptr)) { @@ -3399,7 +3399,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, /* The object can be converted into a single vertex ID */ if (return_single) - *return_single = 1; + *return_single = true; if (single_vid) *single_vid = vid; @@ -3610,7 +3610,7 @@ int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, /* The object can be converted into a single edge ID */ if (return_single) { - *return_single = 1; + *return_single = true; } /* diff --git a/src/_igraph/dfsiter.c b/src/_igraph/dfsiter.c index b3dd00cc9..a01710daf 100644 --- a/src/_igraph/dfsiter.c +++ b/src/_igraph/dfsiter.c @@ -166,7 +166,7 @@ static PyObject* igraphmodule_DFSIter_iternext(igraphmodule_DFSIterObject* self) /* the design is to return the top of the stack and then proceed until * we have found an unvisited neighbor and push that on top */ igraph_integer_t parent_out, dist_out, vid_out; - igraph_bool_t any = 0; + igraph_bool_t any = false; /* nothing on the stack, end of iterator */ if (igraph_stack_int_empty(&self->stack)) { diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 7c8702a67..b22b641af 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -709,7 +709,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject } else if (PyCallable_Check(item)) { /* Call the callable for every edge in the current sequence to * determine what's up */ - igraph_bool_t was_excluded = 0; + igraph_bool_t was_excluded = false; igraph_vector_int_t v; if (igraph_vector_int_init(&v, 0)) { diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f0a45b037..646caf835 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -200,7 +200,7 @@ int igraphmodule_Graph_init(igraphmodule_GraphObject * self, Py_ssize_t n = 0; igraph_vector_int_t edges_vector; igraph_integer_t vcount; - igraph_bool_t edges_vector_owned = 0; + igraph_bool_t edges_vector_owned = false; int retval = 0; self->destructor = NULL; @@ -653,7 +653,7 @@ PyObject *igraphmodule_Graph_add_edges(igraphmodule_GraphObject * self, { PyObject *list; igraph_vector_int_t v; - igraph_bool_t v_owned = 0; + igraph_bool_t v_owned = false; if (!PyArg_ParseTuple(args, "O", &list)) return NULL; @@ -736,7 +736,7 @@ PyObject *igraphmodule_Graph_degree(igraphmodule_GraphObject * self, igraph_neimode_t dmode = IGRAPH_ALL; igraph_vector_int_t res; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "vertices", "mode", "loops", NULL }; @@ -788,7 +788,7 @@ PyObject *igraphmodule_Graph_diversity(igraphmodule_GraphObject * self, PyObject *weights_o = Py_None; igraph_vector_t res, *weights = 0; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_integer_t no_of_nodes; static char *kwlist[] = { "vertices", "weights", NULL }; @@ -868,7 +868,7 @@ PyObject *igraphmodule_Graph_strength(igraphmodule_GraphObject * self, igraph_neimode_t dmode = IGRAPH_ALL; igraph_vector_t res, *weights = 0; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "vertices", "mode", "loops", "weights", NULL }; @@ -956,7 +956,7 @@ PyObject *igraphmodule_Graph_maxdegree(igraphmodule_GraphObject * self, PyObject *loops = Py_False; igraph_integer_t res; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "vertices", "mode", "loops", NULL }; @@ -993,7 +993,7 @@ PyObject *igraphmodule_Graph_is_loop(igraphmodule_GraphObject *self, PyObject *list = Py_None; igraph_vector_bool_t res; igraph_es_t es; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "edges", NULL }; @@ -1041,7 +1041,7 @@ PyObject *igraphmodule_Graph_is_multiple(igraphmodule_GraphObject *self, PyObject *list = Py_None; igraph_vector_bool_t res; igraph_es_t es; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "edges", NULL }; @@ -1089,7 +1089,7 @@ PyObject *igraphmodule_Graph_is_mutual(igraphmodule_GraphObject *self, PyObject *list = Py_None; igraph_vector_bool_t res; igraph_es_t es; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; PyObject* loops_o = Py_True; static char *kwlist[] = { "edges", "loops", NULL }; @@ -1156,7 +1156,7 @@ PyObject *igraphmodule_Graph_count_multiple(igraphmodule_GraphObject *self, PyObject *list = Py_None; igraph_vector_int_t res; igraph_es_t es; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; static char *kwlist[] = { "edges", NULL }; @@ -1494,7 +1494,7 @@ PyObject *igraphmodule_Graph_get_eids(igraphmodule_GraphObject * self, PyObject *error = Py_True; PyObject *result_o = NULL; igraph_vector_int_t pairs, res; - igraph_bool_t pairs_owned = 0; + igraph_bool_t pairs_owned = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &pairs_o, &directed, &error)) @@ -2078,7 +2078,7 @@ PyObject *igraphmodule_Graph_Bipartite(PyTypeObject * type, igraph_t g; igraph_vector_bool_t types; igraph_vector_int_t edges; - igraph_bool_t edges_owned = 0; + igraph_bool_t edges_owned = false; PyObject *types_o, *edges_o, *directed = Py_False; static char *kwlist[] = { "types", "edges", "directed", NULL }; @@ -2157,7 +2157,7 @@ PyObject *igraphmodule_Graph_Degree_Sequence(PyTypeObject * type, igraph_t g; igraph_vector_int_t outseq, inseq; igraph_degseq_t meth = IGRAPH_DEGSEQ_CONFIGURATION; - igraph_bool_t has_inseq = 0; + igraph_bool_t has_inseq = false; PyObject *outdeg = NULL, *indeg = NULL, *method = NULL; static char *kwlist[] = { "out", "in_", "method", NULL }; @@ -3876,7 +3876,7 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, PyObject *weights_o = Py_None; PyObject *nobigint = Py_True; igraph_vector_t res, *weights = 0; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; /* nobigint is now unused but we kept here for sake of backwards compatibility */ @@ -3960,7 +3960,7 @@ PyObject *igraphmodule_Graph_bibcoupling(igraphmodule_GraphObject * self, PyObject *vobj = NULL, *list; igraph_matrix_t res; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &vobj)) return NULL; @@ -4320,7 +4320,7 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; igraph_vector_t res, *weights = 0; igraph_neimode_t mode = IGRAPH_ALL; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, @@ -4400,7 +4400,7 @@ PyObject *igraphmodule_Graph_harmonic_centrality(igraphmodule_GraphObject * self *mode_o = Py_None, *weights_o = Py_None, *normalized_o = Py_True; igraph_vector_t res, *weights = 0; igraph_neimode_t mode = IGRAPH_ALL; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &vobj, @@ -4522,7 +4522,7 @@ PyObject *igraphmodule_Graph_constraint(igraphmodule_GraphObject * self, PyObject *vids_obj = Py_None, *weight_obj = Py_None, *list; igraph_vector_t res, weights; igraph_vs_t vids; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; if (!PyArg_ParseTupleAndKeywords (args, kwds, "|OO", kwlist, &vids_obj, &weight_obj)) @@ -4579,7 +4579,7 @@ PyObject *igraphmodule_Graph_cocitation(igraphmodule_GraphObject * self, char *kwlist[] = { "vertices", NULL }; PyObject *vobj = NULL, *list = NULL; igraph_matrix_t res; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &vobj)) @@ -4718,7 +4718,7 @@ PyObject *igraphmodule_Graph_eccentricity(igraphmodule_GraphObject* self, PyObject *vobj = Py_None, *list = NULL, *mode_o = Py_None; igraph_vector_t res; igraph_neimode_t mode = IGRAPH_OUT; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &vobj, &mode_o)) @@ -5028,7 +5028,7 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * PyObject *list, *mode_o=Py_None, *weights_o=Py_None, *output_o=Py_None, *from_o = Py_None, *to_o=Py_None; igraph_vector_int_list_t veclist; - igraph_bool_t use_edges = 0; + igraph_bool_t use_edges = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO!", kwlist, &from_o, &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) @@ -5169,7 +5169,7 @@ PyObject *igraphmodule_Graph_get_k_shortest_paths( igraph_integer_t k = 1; PyObject *list, *from_o, *to_o; PyObject *output_o = Py_None, *mode_o = Py_None, *weights_o = Py_None, *k_o = NULL; - igraph_bool_t use_edges = 0; + igraph_bool_t use_edges = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOO", kwlist, &from_o, &to_o, &k_o, &weights_o, &mode_o, &output_o)) @@ -5476,7 +5476,7 @@ PyObject *igraphmodule_Graph_neighborhood(igraphmodule_GraphObject *self, PyObject *result_o; Py_ssize_t order = 1, mindist = 0; igraph_neimode_t mode = IGRAPH_ALL; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; igraph_vector_int_list_t res; @@ -5532,7 +5532,7 @@ PyObject *igraphmodule_Graph_neighborhood_size(igraphmodule_GraphObject *self, PyObject *result_o; Py_ssize_t order = 1, mindist = 0; igraph_neimode_t mode = IGRAPH_ALL; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; igraph_vector_int_t res; @@ -5594,7 +5594,7 @@ PyObject *igraphmodule_Graph_personalized_pagerank(igraphmodule_GraphObject *sel igraph_vector_t res; igraph_vector_t *reset = 0; igraph_vector_t weights; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs, reset_vs; igraph_pagerank_algo_t algo=IGRAPH_PAGERANK_ALGO_PRPACK; PyObject *algo_o = Py_None; @@ -5822,7 +5822,7 @@ PyObject *igraphmodule_Graph_distances( igraph_matrix_t res; igraph_vector_t *weights=0; igraph_neimode_t mode = IGRAPH_OUT; - igraph_bool_t return_single_from = 0, return_single_to = 0; + igraph_bool_t return_single_from = false, return_single_to = 0; igraph_error_t e = 0; igraph_vs_t from_vs, to_vs; @@ -5931,7 +5931,7 @@ PyObject *igraphmodule_Graph_similarity_jaccard(igraphmodule_GraphObject * self, /* Case #1: vertices, returning matrix */ igraph_matrix_t res; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; if (igraphmodule_PyObject_to_vs_t(vertices_o, &vs, &self->g, &return_single, 0)) return NULL; @@ -6017,7 +6017,7 @@ PyObject *igraphmodule_Graph_similarity_dice(igraphmodule_GraphObject * self, /* Case #1: vertices, returning matrix */ igraph_matrix_t res; igraph_vs_t vs; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; if (igraphmodule_PyObject_to_vs_t(vertices_o, &vs, &self->g, &return_single, 0)) return NULL; @@ -6088,7 +6088,7 @@ PyObject *igraphmodule_Graph_similarity_inverse_log_weighted( PyObject *vobj = NULL, *list = NULL, *mode_o = Py_None; igraph_matrix_t res; igraph_neimode_t mode = IGRAPH_ALL; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &vobj, &mode_o)) @@ -6367,7 +6367,7 @@ PyObject PyObject *weights_o = Py_None; igraph_vector_t res; igraph_vector_t *weights = 0; - igraph_bool_t return_single = 0; + igraph_bool_t return_single = false; igraph_vs_t vs; igraph_transitivity_mode_t mode = IGRAPH_TRANSITIVITY_NAN; igraph_error_t retval; @@ -6528,7 +6528,7 @@ PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { PyObject *types_o, *return_types_o = Py_False; igraph_vector_bool_t types; - igraph_bool_t return_types = 0, res; + igraph_bool_t return_types = false, res; static char *kwlist[] = { "return_types", NULL }; @@ -7212,7 +7212,7 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * { "maxiter", "epsilon", "kkconst", "seed", "minx", "maxx", "miny", "maxy", "minz", "maxz", "dim", NULL }; igraph_matrix_t m; - igraph_bool_t use_seed=0; + igraph_bool_t use_seed = false; igraph_error_t ret; Py_ssize_t niter = 1000, dim = 2; double kkconst, epsilon = 0.0; @@ -7339,7 +7339,7 @@ PyObject* igraphmodule_Graph_layout_davidson_harel(igraphmodule_GraphObject *sel "weight_border", "weight_edge_lengths", "weight_edge_crossings", "weight_node_edge_dist", NULL }; igraph_matrix_t m; - igraph_bool_t use_seed=0; + igraph_bool_t use_seed = false; Py_ssize_t maxiter = 10, fineiter = -1; double cool_fact=0.75; double weight_node_dist=1.0; @@ -7428,7 +7428,7 @@ PyObject* igraphmodule_Graph_layout_drl(igraphmodule_GraphObject *self, static char *kwlist[] = { "weights", "seed", "fixed", "options", "dim", NULL }; igraph_matrix_t m; - igraph_bool_t use_seed=0; + igraph_bool_t use_seed = false; igraph_vector_t *weights=0; igraph_layout_drl_options_t options; PyObject *result_o; @@ -7512,7 +7512,7 @@ PyObject "seed", "minx", "maxx", "miny", "maxy", "minz", "maxz", "dim", "grid", NULL }; igraph_matrix_t m; - igraph_bool_t use_seed=0; + igraph_bool_t use_seed = false; igraph_vector_t *weights=0; igraph_vector_t *minx=0, *maxx=0; igraph_vector_t *miny=0, *maxy=0; @@ -7658,7 +7658,7 @@ PyObject *igraphmodule_Graph_layout_graphopt(igraphmodule_GraphObject *self, double node_charge = 0.001, node_mass = 30; double spring_constant = 1, max_sa_movement = 5, spring_length = 0; PyObject *result_o, *seed_o = Py_None; - igraph_bool_t use_seed=0; + igraph_bool_t use_seed = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ndddddO", kwlist, &niter, &node_charge, &node_mass, @@ -8042,7 +8042,7 @@ PyObject *igraphmodule_Graph_layout_umap( PyObject *dist_o = Py_None; PyObject *seed_o = Py_None; PyObject *result_o; - igraph_bool_t use_seed = 0; + igraph_bool_t use_seed = false; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OnOdn", kwlist, &dist_o, &dim, &seed_o, &min_dist, &epochs)) @@ -9235,7 +9235,7 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_isomorphic(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_bool_t res = 0; + igraph_bool_t res = false; PyObject *o = Py_None; igraphmodule_GraphObject *other; static char *kwlist[] = { "other", NULL }; @@ -9266,7 +9266,7 @@ PyObject *igraphmodule_Graph_isomorphic(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_isomorphic_bliss(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_bool_t res = 0; + igraph_bool_t res = false; PyObject *o=Py_None, *return1=Py_False, *return2=Py_False; PyObject *sho1=Py_None, *sho2=Py_None; PyObject *color1_o=Py_None, *color2_o=Py_None; @@ -9457,7 +9457,7 @@ igraph_bool_t igraphmodule_i_Graph_isomorphic_vf2_edge_compat_fn( PyObject *igraphmodule_Graph_isomorphic_vf2(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_bool_t res = 0; + igraph_bool_t res = false; PyObject *o=Py_None, *return1=Py_False, *return2=Py_False; PyObject *color1_o=Py_None, *color2_o=Py_None; PyObject *edge_color1_o=Py_None, *edge_color2_o=Py_None; @@ -9794,7 +9794,7 @@ PyObject *igraphmodule_Graph_get_isomorphisms_vf2(igraphmodule_GraphObject *self PyObject *igraphmodule_Graph_subisomorphic_vf2(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_bool_t res = 0; + igraph_bool_t res = false; PyObject *o, *return1=Py_False, *return2=Py_False; PyObject *color1_o=Py_None, *color2_o=Py_None; PyObject *edge_color1_o=Py_None, *edge_color2_o=Py_None; @@ -10122,7 +10122,7 @@ PyObject *igraphmodule_Graph_get_subisomorphisms_vf2(igraphmodule_GraphObject *s PyObject *igraphmodule_Graph_subisomorphic_lad(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - igraph_bool_t res = 0; + igraph_bool_t res = false; PyObject *o, *return_mapping=Py_False, *domains_o=Py_None, *induced=Py_False; float time_limit = 0; igraphmodule_GraphObject *other; @@ -12510,7 +12510,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, double beta = 0.01; igraph_vector_t *edge_weights = NULL, *node_weights = NULL; igraph_vector_int_t *membership = NULL; - igraph_bool_t start = 1; + igraph_bool_t start = true; igraph_integer_t nb_clusters = 0; igraph_real_t quality = 0.0; diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index bcabc487f..2ba4554fb 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -117,7 +117,7 @@ help(igraph.Graph) /** * Whether the module was initialized already */ -static igraph_bool_t igraphmodule_initialized = 0; +static igraph_bool_t igraphmodule_initialized = false; /** * Module-specific global variables diff --git a/src/_igraph/indexing.c b/src/_igraph/indexing.c index 7dedd2677..6f37b1cae 100644 --- a/src/_igraph/indexing.c +++ b/src/_igraph/indexing.c @@ -269,7 +269,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, PyObject *iter = 0, *item; igraph_vit_t vit; igraph_integer_t v, v1, v2, eid; - igraph_bool_t deleting, ok = 1; + igraph_bool_t deleting, ok = true; /* Check whether new_value is an iterable (and not a string). If not, * every assignment will use the same value (that is, new_value) */ @@ -313,7 +313,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (igraph_vector_int_push_back(&data->to_delete, eid)) { igraphmodule_handle_igraph_error(); igraph_vector_int_clear(&data->to_delete); - ok = 0; + ok = false; break; } } @@ -324,7 +324,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, igraph_vector_int_push_back(&data->to_add, v2)) { igraphmodule_handle_igraph_error(); igraph_vector_int_clear(&data->to_add); - ok = 0; + ok = false; break; } if (values != 0) { @@ -332,7 +332,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (PyList_Append(data->to_add_values, new_value)) { Py_DECREF(new_value); igraph_vector_int_clear(&data->to_add); - ok = 0; + ok = false; break; } } @@ -375,7 +375,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (igraph_vector_int_push_back(&data->to_delete, eid)) { igraphmodule_handle_igraph_error(); igraph_vector_int_clear(&data->to_delete); - ok = 0; + ok = false; break; } } @@ -386,7 +386,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, igraph_vector_int_push_back(&data->to_add, v2)) { igraphmodule_handle_igraph_error(); igraph_vector_int_clear(&data->to_add); - ok = 0; + ok = false; break; } if (values != 0) { @@ -394,7 +394,7 @@ static int igraphmodule_i_Graph_adjmatrix_set_index_row(igraph_t* graph, if (PyList_Append(data->to_add_values, new_value)) { Py_DECREF(new_value); igraph_vector_int_clear(&data->to_add); - ok = 0; + ok = false; break; } } @@ -424,7 +424,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, igraph_vs_t vs1, vs2; igraph_vit_t vit; igraph_integer_t vid1 = -1, vid2 = -1, eid = -1; - igraph_bool_t ok = 1; + igraph_bool_t ok = true; igraphmodule_i_Graph_adjmatrix_set_index_data_t data; char* attr; @@ -451,7 +451,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, /* Deleting the edge between vid1 and vid2 if it is there */ if (igraph_delete_edges(graph, igraph_ess_1(eid))) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } } } else { @@ -460,7 +460,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, eid = igraph_ecount(graph); if (igraph_add_edge(graph, vid1, vid2)) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } } if (ok && values != 0) { @@ -492,13 +492,13 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, /* Complete submatrix */ if (igraph_vit_create(graph, vs1, &vit)) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } else { while (!IGRAPH_VIT_END(vit)) { vid1 = IGRAPH_VIT_GET(vit); if (igraphmodule_i_Graph_adjmatrix_set_index_row( graph, vid1, &vs2, IGRAPH_OUT, values, new_value, &data) == 0) { - ok = 0; + ok = false; break; } IGRAPH_VIT_NEXT(vit); @@ -511,7 +511,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, /* Second phase: do the deletions in one batch */ if (igraph_delete_edges(graph, igraph_ess_vector(&data.to_delete))) { igraphmodule_handle_igraph_error(); - ok = 0; + ok = false; } } @@ -526,7 +526,7 @@ int igraphmodule_Graph_adjmatrix_set_index(igraph_t* graph, if (PyList_Size(values) != igraph_ecount(graph)) { PyErr_SetString(PyExc_ValueError, "hmmm, attribute value list " "length mismatch, this is most likely a bug."); - ok = 0; + ok = false; } } } diff --git a/src/_igraph/pyhelpers.c b/src/_igraph/pyhelpers.c index 98bd09e40..05bdcef53 100644 --- a/src/_igraph/pyhelpers.c +++ b/src/_igraph/pyhelpers.c @@ -23,6 +23,8 @@ #include "pyhelpers.h" +#include + #ifdef PY_IGRAPH_PROVIDES_PY_NONE PyObject* Py_None; #endif @@ -239,8 +241,8 @@ long igraphmodule_Py_HashPointer(void *p) { * in PyPy as part of the limited API. */ int igraphmodule_helpers_init() { - static int called = 0; - int success = 0; + static bool called = false; + bool success = false; if (called) { PyErr_SetString(PyExc_RuntimeError, "igraphmodule_helpers_init() called twice"); @@ -268,8 +270,8 @@ int igraphmodule_helpers_init() { } #endif - called = 1; - success = 1; + called = true; + success = true; #if defined(PY_IGRAPH_PROVIDES_PY_NONE) || defined(PY_IGRAPH_PROVIDES_BOOL_CONSTANTS) cleanup: diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 03c3dc0f0..67cba83bc 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -329,7 +329,7 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, PyObject** pObj; PyObject *key, *value, *it, *item, *keys; - igraph_bool_t ok = 1; + igraph_bool_t ok = true; if (!PyArg_ParseTuple(args, "|O", &items[0])) return NULL; @@ -350,17 +350,17 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, /* Object has a "keys" method, so we iterate over the keys */ keys = PyObject_CallObject(keys_func, 0); if (keys == 0) { - ok = 0; + ok = false; } else { /* Iterate over the keys */ it = PyObject_GetIter(keys); if (it == 0) { - ok = 0; + ok = false; } else { while (ok && ((key = PyIter_Next(it)) != 0)) { value = PyObject_GetItem(obj, key); if (value == 0) { - ok = 0; + ok = false; } else { PyObject_SetItem((PyObject*)self, key, value); Py_DECREF(value); @@ -369,7 +369,7 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, } Py_DECREF(it); if (PyErr_Occurred()) - ok = 0; + ok = false; } Py_DECREF(keys); } @@ -378,20 +378,20 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, * yields tuples when treated as an iterator */ it = PyObject_GetIter(obj); if (!it) { - ok = 0; + ok = false; } else { while (ok && ((item = PyIter_Next(it)) != 0)) { if (!PySequence_Check(item) || PyBaseString_Check(item)) { PyErr_SetString(PyExc_TypeError, "cannot convert update sequence element to a sequence"); - ok = 0; + ok = false; } else { key = PySequence_GetItem(item, 0); if (key == 0) { - ok = 0; + ok = false; } else { value = PySequence_GetItem(item, 1); if (value == 0) { - ok = 0; + ok = false; } else { PyObject_SetItem((PyObject*)self, key, value); Py_DECREF(value); @@ -403,7 +403,7 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, } Py_DECREF(it); if (PyErr_Occurred()) - ok = 0; + ok = false; } } diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 643077076..573c66280 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -710,7 +710,7 @@ PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self, } else if (PyCallable_Check(item)) { /* Call the callable for every vertex in the current sequence to * determine what's up */ - igraph_bool_t was_excluded = 0; + igraph_bool_t was_excluded = false; igraph_vector_int_t v; if (igraph_vector_int_init(&v, 0)) { From 81a4fc9a53c643bf77a323b0c63a45fab8fa5674 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 22 Nov 2022 19:05:12 +0100 Subject: [PATCH 1154/1892] doc: remove incorrect claim about 1-damping being the PageRank of dangling nodes, closes #614 --- src/_igraph/graphobject.c | 2 -- src/igraph/structural.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 646caf835..a5b903bbb 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14590,8 +14590,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " C{None} means all of the vertices.\n" "@param directed: whether to consider directed paths.\n" "@param damping: the damping factor.\n" - " M{1-damping} is the PageRank value for vertices with no\n" - " incoming links.\n" "@param reset: the distribution over the vertices to be used when resetting\n" " the random walk. Can be a sequence, an iterable or a vertex attribute\n" " name as long as they return a list of floats whose length is equal to\n" diff --git a/src/igraph/structural.py b/src/igraph/structural.py index 2aa0283ab..870329bc1 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -51,8 +51,7 @@ def _pagerank( @param vertices: the indices of the vertices being queried. C{None} means all of the vertices. @param directed: whether to consider directed paths. - @param damping: the damping factor. M{1-damping} is the PageRank value - for nodes with no incoming links. It is also the probability of + @param damping: the damping factor. It is also the probability of resetting the random walk to a uniform distribution in each step. @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. From 6a6e82c6a0d80f1c7f4f2c1a4967aa79612f254b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Tue, 22 Nov 2022 22:17:02 +0100 Subject: [PATCH 1155/1892] docs: fix description of damping for PageRank --- src/igraph/structural.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/structural.py b/src/igraph/structural.py index 870329bc1..e5b78ddf0 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -51,7 +51,7 @@ def _pagerank( @param vertices: the indices of the vertices being queried. C{None} means all of the vertices. @param directed: whether to consider directed paths. - @param damping: the damping factor. It is also the probability of + @param damping: the damping factor. M{1-damping} is the probability of resetting the random walk to a uniform distribution in each step. @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. From 7b37dbff6ae3edd427b291a4563713dfa70c25e8 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 23 Nov 2022 15:21:10 +1100 Subject: [PATCH 1156/1892] Move umap compute weights to separate global function --- src/_igraph/graphobject.c | 91 ++------------------------------------ src/_igraph/igraphmodule.c | 88 ++++++++++++++++++++++++++++++++++++ src/igraph/__init__.py | 3 +- tests/test_layouts.py | 3 +- 4 files changed, 96 insertions(+), 89 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index b6405b340..f452bd137 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8145,58 +8145,6 @@ PyObject *igraphmodule_Graph_layout_umap( return (PyObject *) result_o; } -/** \ingroup python_interface_graph - * \brief Compute weights for Uniform Manifold Approximation and Projection (UMAP) - * \return the weights given that graph - * \sa igraph_layout_umap_compute_weights - */ -PyObject *igraphmodule_Graph_layout_umap_compute_weights( - igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) -{ - static char *kwlist[] = { "dist", NULL }; - igraph_vector_t *dist = 0; - igraph_vector_t weights; - PyObject *dist_o = Py_None; - PyObject *result_o; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &dist_o)) - return NULL; - - /* Initialize distances */ - if (dist_o != Py_None) { - dist = (igraph_vector_t*)malloc(sizeof(igraph_vector_t)); - if (!dist) { - PyErr_NoMemory(); - return NULL; - } - if (igraphmodule_PyObject_to_vector_t(dist_o, dist, 0)) { - free(dist); - return NULL; - } - } - - /* Initialize weights */ - if (igraph_vector_init(&weights, 0)) { - igraph_vector_destroy(dist); free(dist); - PyErr_NoMemory(); - return NULL; - } - - /* Call the function */ - if (igraph_layout_umap_compute_weights(&self->g, dist, &weights)) { - igraph_vector_destroy(&weights); - igraph_vector_destroy(dist); free(dist); - PyErr_NoMemory(); - return NULL; - } - igraph_vector_destroy(dist); free(dist); - - /* Convert output to Python list */ - result_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); - igraph_vector_destroy(&weights); - return (PyObject *) result_o; -} - /** \ingroup python_interface_graph * \brief Places the vertices of a bipartite graph according to a simple two-layer @@ -15691,37 +15639,6 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Internal function, undocumented.\n\n" "@see: Graph.layout_sugiyama()\n\n"}, - /* interface to igraph_layout_umap_compute_weights */ - {"layout_umap_compute_weights", - (PyCFunction) igraphmodule_Graph_layout_umap_compute_weights, - METH_VARARGS | METH_KEYWORDS, - "layout_umap_compute_weights(dist)\n" - "--\n\n" - "@param dist: distances associated with the graph edges.\n" - "@return: Symmetrized weights associated with each edge. If the distance\n" - " graph has both directed edges between a pair of vertices, one of the\n" - " returned weights will be set to zero.\n\n" - "Compute undirected UMAP weights from directed distance graph.\n\n" - "UMAP is a layout algorithm that usually takes as input a directed\n" - "distance graph, e.g. a k nearest neighbor graph based on Euclidean\n" - "distance between points in a vector space. The graph is directed\n" - "because vertex v1 might consider vertex v2 a close neighbor, but v2\n" - "itself might have many neighbors that are closer than v1.\n" - "This function computes the symmetrized weights from the distance graph\n" - "using union as the symmetry operator. In simple terms, if either vertex\n" - "considers the other a close neighbor, they will be treated as close\n" - "neighbors.\n\n" - "This function can be used as a separate preprocessing step to\n" - "Graph.layout_umap(). For efficiency reasons, the returned weights have the\n" - "same length as the input distances, however because of the symmetryzation\n" - "some information is lost. Therefore, the weight of one of the edges is set\n" - "to zero whenever edges in opposite directions are found in the input\n" - "distance graph. You can pipe the output of this function directly into\n" - "Graph.layout_umap() as follows:\n" - "C{weights = graph.layout_umap_compute_weights(dist)}\n" - "C{layout = graph.layout_umap(weights=weights)}\n\n" - "@see: Graph.layout_umap()\n\n"}, - /* interface to igraph_layout_umap */ {"layout_umap", (PyCFunction) igraphmodule_Graph_layout_umap, @@ -15738,7 +15655,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param weights: precomputed edge weights if you have them, as an alternative\n" " to setting the C{dist} argument. Zero weights will be ignored if this\n" " argument is set, e.g. if you computed the weights via\n" - " Graph.layout_umap_compute_weights().\n" + " igraph.layout_umap_compute_weights().\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" "@param seed: if C{None}, uses a random starting layout for the\n" @@ -15756,13 +15673,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "if weights are precomputed, the graph will be treated as undirected. A special\n" "case is when the graph is directed but the precomputed weights are symmetrized\n" "in a way only one of each pair of opposite edges has nonzero weight, e.g. as\n" - "computed by Graph.layout_umap_compute_weights(). For example:\n" - "C{weights = graph.layout_umap_compute_weights(dist)}\n" + "computed by igraph.layout_umap_compute_weights(). For example:\n" + "C{weights = igraph.layout_umap_compute_weights(graph, dist)}\n" "C{layout = graph.layout_umap(weights=weights)}\n\n" "@newfield ref: Reference\n" "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation\n" " and Projection for Dimension Reduction. arXiv:1802.03426.\n" - "@see: Graph.layout_umap_compute_weights()\n\n"}, + "@see: igraph.layout_umap_compute_weights()\n\n"}, //////////////////////////// // VISITOR-LIKE FUNCTIONS // diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 2ba4554fb..21d5cb3bd 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -639,6 +639,64 @@ PyObject* igraphmodule_split_join_distance(PyObject *self, return Py_BuildValue("nn", (Py_ssize_t)distance12, (Py_ssize_t)distance21); } + +/** \ingroup python_interface_graph + * \brief Compute weights for Uniform Manifold Approximation and Projection (UMAP) + * \return the weights given that graph + * \sa igraph_umap_compute_weights + */ +PyObject *igraphmodule_umap_compute_weights( + PyObject *self, PyObject * args, PyObject * kwds) +{ + static char *kwlist[] = { "graph", "dist", NULL }; + igraph_vector_t *dist = 0; + igraph_vector_t weights; + PyObject *dist_o = Py_None, *graph_o = Py_None; + PyObject *result_o; + igraphmodule_GraphObject * graph; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &graph_o, &dist_o)) + return NULL; + + /* Initialize distances */ + if (dist_o != Py_None) { + dist = (igraph_vector_t*)malloc(sizeof(igraph_vector_t)); + if (!dist) { + PyErr_NoMemory(); + return NULL; + } + if (igraphmodule_PyObject_to_vector_t(dist_o, dist, 0)) { + free(dist); + return NULL; + } + } + + /* Extract graph from Python object */ + graph = (igraphmodule_GraphObject*)graph_o; + + /* Initialize weights */ + if (igraph_vector_init(&weights, 0)) { + igraph_vector_destroy(dist); free(dist); + PyErr_NoMemory(); + return NULL; + } + + /* Call the function */ + if (igraph_layout_umap_compute_weights(&graph->g, dist, &weights)) { + igraph_vector_destroy(&weights); + igraph_vector_destroy(dist); free(dist); + PyErr_NoMemory(); + return NULL; + } + igraph_vector_destroy(dist); free(dist); + + /* Convert output to Python list */ + result_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); + igraph_vector_destroy(&weights); + return (PyObject *) result_o; +} + + #define LOCALE_CAPSULE_TYPE "igraph._igraph.locale_capsule" void igraphmodule__destroy_locale_capsule(PyObject *capsule) { @@ -766,6 +824,36 @@ static PyMethodDef igraphmodule_methods[] = "@return: C{True} if there exists some simple graph that can realize the given\n" " degree sequence, C{False} otherwise.\n" }, + {"umap_compute_weights", (PyCFunction)igraphmodule_umap_compute_weights, + METH_VARARGS | METH_KEYWORDS, + "layout_umap_compute_weights(graph, dist)\n" + "--\n\n" + "@param graph: directed graph to compute weights for.\n" + "@param dist: distances associated with the graph edges.\n" + "@return: Symmetrized weights associated with each edge. If the distance\n" + " graph has both directed edges between a pair of vertices, one of the\n" + " returned weights will be set to zero.\n\n" + "Compute undirected UMAP weights from directed distance graph.\n\n" + "UMAP is a layout algorithm that usually takes as input a directed\n" + "distance graph, e.g. a k nearest neighbor graph based on Euclidean\n" + "distance between points in a vector space. The graph is directed\n" + "because vertex v1 might consider vertex v2 a close neighbor, but v2\n" + "itself might have many neighbors that are closer than v1.\n" + "This function computes the symmetrized weights from the distance graph\n" + "using union as the symmetry operator. In simple terms, if either vertex\n" + "considers the other a close neighbor, they will be treated as close\n" + "neighbors.\n\n" + "This function can be used as a separate preprocessing step to\n" + "Graph.layout_umap(). For efficiency reasons, the returned weights have the\n" + "same length as the input distances, however because of the symmetryzation\n" + "some information is lost. Therefore, the weight of one of the edges is set\n" + "to zero whenever edges in opposite directions are found in the input\n" + "distance graph. You can pipe the output of this function directly into\n" + "Graph.layout_umap() as follows:\n" + "C{weights = igraph.layout_umap_compute_weights(graph, dist)}\n" + "C{layout = graph.layout_umap(weights=weights)}\n\n" + "@see: Graph.layout_umap()\n" + }, {"set_progress_handler", igraphmodule_set_progress_handler, METH_O, "set_progress_handler(handler)\n--\n\n" "Sets the handler to be called when igraph is performing a long operation.\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 2eeedc3e9..a518843f6 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -71,6 +71,7 @@ set_progress_handler, set_random_number_generator, set_status_handler, + umap_compute_weights, __igraph_version__, ) from igraph.adjacency import ( @@ -963,7 +964,7 @@ def __reduce__(self): for name in dir(Graph): if not name.startswith("layout_"): continue - if name in ("layout_auto", "layout_sugiyama", "layout_umap_compute_weights"): + if name in ("layout_auto", "layout_sugiyama"): continue setattr(Graph, name, _layout_method_wrapper(getattr(Graph, name))) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index c6e0079bc..3f8910bce 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -1,6 +1,7 @@ import unittest from math import hypot from igraph import Graph, Layout, BoundingBox, InternalError +from igraph import umap_compute_weights class LayoutTests(unittest.TestCase): @@ -324,7 +325,7 @@ def testUMAPComputeWeights(self): dist = [1, 1.5, 1.8, 2.0, 3.4, 0.5] # NOTE: you need a directed graph to make sense of the symmetryzation g = Graph(edges, directed=True) - weights = g.layout_umap_compute_weights(dist) + weights = umap_compute_weights(g, dist) self.assertEqual( weights, [1.0, 1.0, 1.0, 1.1253517471925912e-07, 6.14421235332821e-06, 0.0]) From cb1b4e29ef8d0a95ef75f01db0d82181aa9f0f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 23 Nov 2022 10:06:08 +0100 Subject: [PATCH 1157/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 857a5b7c0..4584cfd5e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 857a5b7c03bde9801f1dbbec492c0ce6d92e0845 +Subproject commit 4584cfd5e43912e4bffb34f736d969f6cd68b18d From 2113731e5b3cbaaafb27f932e642ead96f6d34ca Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 24 Nov 2022 12:13:41 +1100 Subject: [PATCH 1158/1892] Changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df018e649..95165e219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## [Unreleased] +### Changed + +- UMAP layout now exposes the computation of the symmetrized edge weights via + `umap_compute_weights()`. The layout function, `Graph.layout_umap()`, can + now be called either on a directed graph with edge distances, or on an + undirected graph with edge weights, typically computed via + `umap_compute_weights()` or precomputed by the user. Moreover, the + `sampling_prob` argument was faulty and has been removed. See PR + [#613](https://github.com/igraph/python-igraph/pull/613) for details. + ### Fixed - `Graph.Data_Frame()` now handles the `Int64` data type from `pandas`, thanks From a45988f0e751da68ca6ebd2aa44915320e02892d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Fri, 25 Nov 2022 09:44:46 +0100 Subject: [PATCH 1159/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 4584cfd5e..b4771e733 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 4584cfd5e43912e4bffb34f736d969f6cd68b18d +Subproject commit b4771e733d8f23648c859a7c487d705a41fbd3c2 From 9ce085a7d111b19aadda20b88af6809dce49737a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Fri, 25 Nov 2022 22:50:53 +0100 Subject: [PATCH 1160/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b4771e733..b58dc67f7 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b4771e733d8f23648c859a7c487d705a41fbd3c2 +Subproject commit b58dc67f71458f5cb273e8ab58526be35de426e3 From bd6d3dc11f52f6254839b7aca6e394799f9c107e Mon Sep 17 00:00:00 2001 From: Adriankhl Date: Fri, 25 Nov 2022 20:39:12 +0100 Subject: [PATCH 1161/1892] fix: Graph.DataFrame() can now process dataframe with non-comparable data types --- src/igraph/io/objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index b731783fb..6cc550a24 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -459,7 +459,7 @@ def _construct_graph_from_dataframe( # Bring DataFrame(s) into same format as with 'use_vids=True' if vertices is None: - vertices = pd.DataFrame({"name": np.unique(edges.values[:, :2])}) + vertices = pd.DataFrame({"name": pd.unique(edges.values[:, :2].ravel())}) if vertices.iloc[:, 0].isna().any(): warn( From ccf4984313d17d9924e9c8f92d3cdbe18c997b53 Mon Sep 17 00:00:00 2001 From: Adriankhl Date: Fri, 25 Nov 2022 20:51:45 +0100 Subject: [PATCH 1162/1892] test: add a test for graph generation from pandas dataframe with both number and string data --- tests/test_generators.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_generators.py b/tests/test_generators.py index d9bdc4ed3..26c8cae61 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -522,6 +522,11 @@ def testDataFrame(self): g = Graph.DataFrame(edges) self.assertTrue(g.vcount() == 3) + # dataframe with both int data and str data + edges = pd.DataFrame({"source": [1, 2, 2], "target": ["A", "B", "A"]}) + g = Graph.DataFrame(edges, use_vids=False) + self.assertTrue(g.vs["name"] == [1, "A", 2, "B"]) + # Invalid input with self.assertRaisesRegex(ValueError, "two columns"): edges = pd.DataFrame({"source": [1, 2, 3]}) From afae3a847f7a0b41d7dc8784e2b33b14cabc6aa8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Dec 2022 19:35:38 +0100 Subject: [PATCH 1163/1892] fix: fix a bug in VertexDendrogram.optimal_count() --- src/igraph/clustering.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index b9859ae29..f2a7cef0e 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -848,13 +848,17 @@ def optimal_count(self): return self._optimal_count n = self._graph.vcount() - max_q, optimal_count = 0, 1 - for step in range(min(n - 1, len(self._merges))): + if n == 0: + return 0 + + max_q, optimal_count = 0, n - len(self._merges) + for step in range(min(n - 1, len(self._merges) + 1)): membs = community_to_membership(self._merges, n, step) q = self._graph.modularity(membs, **self._modularity_params) if q > max_q: optimal_count = n - step max_q = q + self._optimal_count = optimal_count return optimal_count From 00bc09ab15bd8992cbb4ccfc82450d26e7811ed7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 1 Dec 2022 19:48:36 +0100 Subject: [PATCH 1164/1892] fix: VertexClustering now handles partial dendrograms correctly, fixes #17 and #616 --- CHANGELOG.md | 2 ++ src/igraph/community.py | 46 ++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95165e219..9ec077c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ - `Graph.layout_lgl()` `root` argument is now optional (as it should have been). +- The `VertexClustering` class now handles partial dendrograms correctly. + ## [0.10.2] - 2022-10-14 ### Added diff --git a/src/igraph/community.py b/src/igraph/community.py index a7628a358..19d1f15b5 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -1,8 +1,8 @@ from igraph._igraph import GraphBase from igraph.clustering import VertexDendrogram, VertexClustering -from igraph.utils import ( - safemax, -) +from igraph.utils import safemax + +from typing import List, Sequence, Tuple def _community_fastgreedy(graph, weights=None): @@ -24,16 +24,7 @@ def _community_fastgreedy(graph, weights=None): in very large networks. Phys Rev E 70, 066111 (2004). """ merges, qs = GraphBase.community_fastgreedy(graph, weights) - - # qs may be shorter than |V|-1 if we are left with a few separated - # communities in the end; take this into account - diff = graph.vcount() - len(qs) - qs.reverse() - if qs: - optimal_count = qs.index(max(qs)) + diff + 1 - else: - optimal_count = diff - + optimal_count = _optimal_cluster_count_from_merges_and_modularity(graph, merges, qs) return VertexDendrogram( graph, merges, optimal_count, modularity_params=dict(weights=weights) ) @@ -286,7 +277,7 @@ def _community_edge_betweenness(graph, clusters=None, directed=True, weights=Non @param clusters: the number of clusters we would like to see. This practically defines the "level" where we "cut" the dendrogram to get the membership vector of the vertices. If C{None}, the dendrogram - is cut at the level which maximizes the modularity when the graph is + is cut at the level that maximizes the modularity when the graph is unweighted; otherwise the dendrogram is cut at at a single cluster (because cluster count selection based on modularities does not make sense for this method if not all the weights are equal). @@ -298,13 +289,12 @@ def _community_edge_betweenness(graph, clusters=None, directed=True, weights=Non modularity or at the desired number of clusters. """ merges, qs = GraphBase.community_edge_betweenness(graph, directed, weights) - if qs is not None: - qs.reverse() if clusters is None: - if qs: - clusters = qs.index(max(qs)) + 1 + if qs is not None: + clusters = _optimal_cluster_count_from_merges_and_modularity(graph, merges, qs) else: clusters = 1 + return VertexDendrogram( graph, merges, clusters, modularity_params=dict(weights=weights) ) @@ -385,11 +375,7 @@ def _community_walktrap(graph, weights=None, steps=4): networks using random walks, U{http://arxiv.org/abs/physics/0512106}. """ merges, qs = GraphBase.community_walktrap(graph, weights, steps) - qs.reverse() - if qs: - optimal_count = qs.index(max(qs)) + 1 - else: - optimal_count = 1 + optimal_count = _optimal_cluster_count_from_merges_and_modularity(graph, merges, qs) return VertexDendrogram( graph, merges, optimal_count, modularity_params=dict(weights=weights) ) @@ -537,3 +523,17 @@ def _modularity(self, membership, weights=None, resolution=1, directed=True): return GraphBase.modularity(self, membership.membership, weights) else: return GraphBase.modularity(self, membership, weights) + + +def _optimal_cluster_count_from_merges_and_modularity( + graph, merges: Sequence[Tuple[int, int]], qs: List[float] +) -> float: + """Helper function to find the optimal cluster count for a hierarchical + clustering of a graph, given the merge matrix and the list of modularity + values after each merge. + + Reverses the modularity vector as a side effect. + """ + no_of_comps = graph.vcount() - len(merges) + qs.reverse() + return qs.index(max(qs)) + no_of_comps From fbc54d0bfb10b819537f8b20b7e2df5107ec2e8e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Dec 2022 14:06:14 +0100 Subject: [PATCH 1165/1892] refactor: moved deprecated() to igraph.utils --- src/igraph/__init__.py | 9 +-------- src/igraph/clustering.py | 3 +-- src/igraph/structural.py | 3 +-- src/igraph/utils.py | 8 ++++++++ 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a518843f6..f7fbf2999 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -259,6 +259,7 @@ ) from igraph.summary import GraphSummary, summary from igraph.utils import ( + deprecated, numpy_to_contiguous_memoryview, rescale, ) @@ -267,14 +268,6 @@ import os import sys -from warnings import warn - - -def deprecated(message): - """Prints a warning message related to the deprecation of some igraph - feature.""" - warn(message, DeprecationWarning, stacklevel=3) - class Graph(GraphBase): """Generic graph. diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index f2a7cef0e..d54d684f5 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -14,6 +14,7 @@ from igraph.drawing.matplotlib.dendrogram import MatplotlibDendrogramDrawer from igraph.statistics import Histogram from igraph.summary import _get_wrapper_for_width +from igraph.utils import deprecated class Clustering: @@ -1599,7 +1600,5 @@ def _connected_components(graph, mode="strong"): def _clusters(graph, mode="strong"): """Deprecated alias to L{Graph.connected_components()}.""" - from igraph import deprecated - deprecated("Graph.clusters() is deprecated; use Graph.connected_components() instead") return graph.connected_components(mode=mode) diff --git a/src/igraph/structural.py b/src/igraph/structural.py index e5b78ddf0..9f8014271 100644 --- a/src/igraph/structural.py +++ b/src/igraph/structural.py @@ -4,6 +4,7 @@ arpack_options as default_arpack_options, ) from igraph.statistics import Histogram +from igraph.utils import deprecated def _indegree(graph, *args, **kwds): @@ -84,7 +85,5 @@ def _pagerank( def _shortest_paths(graph, *args, **kwds): """Deprecated alias to L{Graph.distances()}.""" - from igraph import deprecated - deprecated("Graph.shortest_paths() is deprecated; use Graph.distances() instead") return graph.distances(*args, **kwds) diff --git a/src/igraph/utils.py b/src/igraph/utils.py index 48f226774..f4f1f7573 100644 --- a/src/igraph/utils.py +++ b/src/igraph/utils.py @@ -6,12 +6,14 @@ from collections.abc import MutableMapping from itertools import chain +from warnings import warn import os import tempfile __all__ = ( "dbl_epsilon", + "deprecated", "multidict", "named_temporary_file", "numpy_to_contiguous_memoryview", @@ -23,6 +25,12 @@ __docformat__ = "restructuredtext en" +def deprecated(message): + """Prints a warning message related to the deprecation of some igraph + feature.""" + warn(message, DeprecationWarning, stacklevel=3) + + def _is_running_in_ipython(): """Internal function that determines whether igraph is running inside IPython or not.""" From 7848bcbc8b81fa248362f56d5593d366836deb1f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Dec 2022 14:09:39 +0100 Subject: [PATCH 1166/1892] refactor: renamed resolution_parameter=... argument of community_leiden() to resolution=..., closes #620 --- CHANGELOG.md | 3 +++ src/_igraph/graphobject.c | 14 +++++++------- src/igraph/community.py | 20 ++++++++++++++------ tests/test_decomposition.py | 4 ++-- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec077c67..7f8f5e9df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ `umap_compute_weights()` or precomputed by the user. Moreover, the `sampling_prob` argument was faulty and has been removed. See PR [#613](https://github.com/igraph/python-igraph/pull/613) for details. +- The `resolution_parameter` argument of `Graph.community_leiden()` was renamed + to `resolution` for sake of consistency. The old variant still works with a + deprecation warning, but will be removed in a future version. ### Fixed diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index be47f20c0..df3ad6bb3 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12518,7 +12518,7 @@ PyObject *igraphmodule_Graph_community_walktrap(igraphmodule_GraphObject * self, PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"edge_weights", "node_weights", "resolution_parameter", + static char *kwlist[] = {"edge_weights", "node_weights", "resolution", "normalize_resolution", "beta", "initial_membership", "n_iterations", NULL}; PyObject *edge_weights_o = Py_None; @@ -12529,7 +12529,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, int error = 0; Py_ssize_t n_iterations = 2; - double resolution_parameter = 1.0; + double resolution = 1.0; double beta = 0.01; igraph_vector_t *edge_weights = NULL, *node_weights = NULL; igraph_vector_int_t *membership = NULL; @@ -12538,7 +12538,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, igraph_real_t quality = 0.0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOdOdOn", kwlist, - &edge_weights_o, &node_weights_o, &resolution_parameter, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) + &edge_weights_o, &node_weights_o, &resolution, &normalize_resolution, &beta, &initial_membership_o, &n_iterations)) return NULL; if (n_iterations >= 0) { @@ -12597,14 +12597,14 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, } } } - resolution_parameter /= igraph_vector_sum(node_weights); + resolution /= igraph_vector_sum(node_weights); } /* Run actual Leiden algorithm for several iterations. */ if (!error) { error = igraph_community_leiden(&self->g, edge_weights, node_weights, - resolution_parameter, beta, + resolution, beta, start, n_iterations, membership, &nb_clusters, &quality); } @@ -17070,14 +17070,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { (PyCFunction) igraphmodule_Graph_community_leiden, METH_VARARGS | METH_KEYWORDS, "community_leiden(edge_weights=None, node_weights=None, " - "resolution_parameter=1.0, normalize_resolution=False, beta=0.01, " + "resolution=1.0, normalize_resolution=False, beta=0.01, " "initial_membership=None, n_iterations=2)\n--\n\n" "Finds the community structure of the graph using the Leiden algorithm of\n" "Traag, van Eck & Waltman.\n\n" "@param edge_weights: edge weights to be used. Can be a sequence or\n" " iterable or even an edge attribute name.\n" "@param node_weights: the node weights used in the Leiden algorithm.\n" - "@param resolution_parameter: the resolution parameter to use.\n" + "@param resolution: the resolution parameter to use.\n" " Higher resolutions lead to more smaller communities, while \n" " lower resolutions lead to fewer larger communities.\n" "@param normalize_resolution: if set to true, the resolution parameter\n" diff --git a/src/igraph/community.py b/src/igraph/community.py index 19d1f15b5..b2121177c 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -1,6 +1,6 @@ from igraph._igraph import GraphBase from igraph.clustering import VertexDendrogram, VertexClustering -from igraph.utils import safemax +from igraph.utils import deprecated, safemax from typing import List, Sequence, Tuple @@ -423,11 +423,12 @@ def _community_leiden( graph, objective_function="CPM", weights=None, - resolution_parameter=1.0, + resolution=1.0, beta=0.01, initial_membership=None, n_iterations=2, node_weights=None, + **kwds ): """Finds the community structure of the graph using the Leiden algorithm of Traag, van Eck & Waltman. @@ -436,9 +437,9 @@ def _community_leiden( Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. - @param resolution_parameter: the resolution parameter to use. - Higher resolutions lead to more smaller communities, while - lower resolutions lead to fewer larger communities. + @param resolution: the resolution parameter to use. Higher resolutions + lead to more smaller communities, while lower resolutions lead to fewer + larger communities. @param beta: parameter affecting the randomness in the Leiden algorithm. This affects only the refinement step of the algorithm. @param initial_membership: if provided, the Leiden algorithm @@ -463,11 +464,18 @@ def _community_leiden( if objective_function.lower() not in ("cpm", "modularity"): raise ValueError('objective_function must be "CPM" or "modularity".') + if "resolution_parameter" in kwds: + deprecated("resolution_parameter keyword argument is deprecated, use resolution=... instead") + resolution = kwds.pop("resolution_parameter") + + if kwds: + raise TypeError('unexpected keyword argument') + membership = GraphBase.community_leiden( graph, edge_weights=weights, node_weights=node_weights, - resolution_parameter=resolution_parameter, + resolution=resolution, normalize_resolution=(objective_function == "modularity"), beta=beta, initial_membership=initial_membership, diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 43be061a4..8fe223a7f 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -513,7 +513,7 @@ def testLeiden(self): set_random_number_generator(random) # We don't find the optimal partition if we are greedy cl = G.community_leiden( - "CPM", resolution_parameter=1, weights="weight", beta=0, n_iterations=-1 + "CPM", resolution=1, weights="weight", beta=0, n_iterations=-1 ) self.assertMembershipsEqual(cl, [0, 0, 1, 1, 1, 2, 2, 2]) @@ -525,7 +525,7 @@ def testLeiden(self): # refined). cl = G.community_leiden( "CPM", - resolution_parameter=1, + resolution=1, weights="weight", beta=5, n_iterations=-1, From e736cd9ec1334e549ab48f433dea6e58820f4c02 Mon Sep 17 00:00:00 2001 From: gruebel Date: Fri, 9 Dec 2022 22:17:59 +0100 Subject: [PATCH 1167/1892] add Python 3.11 classifier to setup.py --- README.md | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c24867860..1c54f5dbb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build and test with tox](https://github.com/igraph/python-igraph/actions/workflows/build.yml/badge.svg)](https://github.com/igraph/python-igraph/actions/workflows/build.yml) -[![PyPI pyversions](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10-blue)](https://pypi.python.org/pypi/igraph) +[![PyPI pyversions](https://img.shields.io/pypi/pyversions/igraph)](https://pypi.python.org/pypi/igraph) [![PyPI wheels](https://img.shields.io/pypi/wheel/igraph.svg)](https://pypi.python.org/pypi/igraph) [![Documentation Status](https://readthedocs.org/projects/igraph/badge/?version=latest)](https://igraph.readthedocs.io/) diff --git a/setup.py b/setup.py index ca25d2c52..0ac08c9ca 100644 --- a/setup.py +++ b/setup.py @@ -985,6 +985,7 @@ def get_tag(self): "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", From 5a11840d3e813ca8fe5e699b203f34ee04534a56 Mon Sep 17 00:00:00 2001 From: gruebel Date: Fri, 9 Dec 2022 22:18:58 +0100 Subject: [PATCH 1168/1892] change Python 3.11 version to GA one in GitHub workflow --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a8f70609..b852fd99b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -294,7 +294,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.11.0-rc.2' + python-version: '3.11' - name: Build C core run: | From 3473422b93510f40c1dd0496bb487889d6fac7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Sat, 10 Dec 2022 20:26:11 +0100 Subject: [PATCH 1169/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b58dc67f7..b51cb8d56 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b58dc67f71458f5cb273e8ab58526be35de426e3 +Subproject commit b51cb8d5657e68bf63fe335416fe4a5a80c57412 From 6949432a0f1c7be898590cd2dbe33b8b597ca498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Sun, 11 Dec 2022 19:08:42 +0100 Subject: [PATCH 1170/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index b51cb8d56..1ec65ac06 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit b51cb8d5657e68bf63fe335416fe4a5a80c57412 +Subproject commit 1ec65ac069da1ab487aea64752a8e518cc748bb7 From 46ce53f75c270762fb021b23bc33369d591730f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 12 Dec 2022 10:44:29 +0100 Subject: [PATCH 1171/1892] doc: improve the documentation of vertex_attrs and edge_attrs in Graph.__init__ --- src/igraph/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index f7fbf2999..a89be5af0 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -362,10 +362,13 @@ def __init__(self, *args, **kwds): @keyword directed: whether the graph should be directed @keyword graph_attrs: the attributes of the graph as a dictionary. @keyword vertex_attrs: the attributes of the vertices as a dictionary. - Every dictionary value must be an iterable with exactly M{n} items. - @keyword edge_attrs: the attributes of the edges as a dictionary. Every - dictionary value must be an iterable with exactly M{m} items where - M{m} is the number of edges. + The keys of the dictionary must be the names of the attributes; the + values must be iterables with exactly M{n} items where M{n} is the + number of vertices. + @keyword edge_attrs: the attributes of the edges as a dictionary. The + keys of the dictionary must be the names of the attributes; the values + must be iterables with exactly M{m} items where M{m} is the number of + edges. """ # Pop the special __ptr keyword argument ptr = kwds.pop("__ptr", None) From 2bdb0fe27bfac43e535423f6767647f14185c499 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:12:23 +0000 Subject: [PATCH 1172/1892] build(deps): bump pypa/cibuildwheel from 2.11.2 to 2.11.3 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.11.2 to 2.11.3. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.11.2...v2.11.3) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b852fd99b..0483306be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,14 +63,14 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -137,7 +137,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -196,7 +196,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.11.3 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From a30cbbba10b6a13533331addaca49bec29f28e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Tue, 13 Dec 2022 16:29:19 +0100 Subject: [PATCH 1173/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 1ec65ac06..678815111 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 1ec65ac069da1ab487aea64752a8e518cc748bb7 +Subproject commit 678815111bc3f4bc243cfc38932b3efbb38f695f From 796f3a93d405ad3e8cc44f3104c06549c50d1652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Thu, 15 Dec 2022 20:00:24 +0100 Subject: [PATCH 1174/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 678815111..3ffeca6dc 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 678815111bc3f4bc243cfc38932b3efbb38f695f +Subproject commit 3ffeca6dc9333768e503f68ceb2d6d6ddea416b4 From a9dc7aa2250257116faf3a3f1bc6bbf29d3f13c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 13:09:31 +0000 Subject: [PATCH 1175/1892] build(deps): bump pypa/cibuildwheel from 2.11.3 to 2.11.4 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.11.3 to 2.11.4. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.11.3...v2.11.4) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0483306be..27b803dd7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,14 +63,14 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -137,7 +137,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -196,7 +196,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.11.3 + uses: pypa/cibuildwheel@v2.11.4 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 143ca3c9e37641a135fd378e45a7b53aa8f1bc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 28 Dec 2022 12:30:46 +0100 Subject: [PATCH 1176/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 3ffeca6dc..a69989656 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 3ffeca6dc9333768e503f68ceb2d6d6ddea416b4 +Subproject commit a6998965612df1d20be08e324838bcab81086092 From 7f808bd8c470d17b7dbe0c3aa0b64c9958f4e5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Thu, 29 Dec 2022 17:28:38 +0100 Subject: [PATCH 1177/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index a69989656..3bfdc13f2 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit a6998965612df1d20be08e324838bcab81086092 +Subproject commit 3bfdc13f28aaa6c6f1aa5f5d092b4ca31a5235f5 From 7772cba53b2b90e679ce851aec574c9dea8115e9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Dec 2022 21:28:57 +0100 Subject: [PATCH 1178/1892] chore: updated to igraph 0.10.3 --- src/_igraph/graphobject.c | 2 +- vendor/source/igraph | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index df3ad6bb3..17cc9b231 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6283,7 +6283,7 @@ PyObject *igraphmodule_Graph_subgraph_edges(igraphmodule_GraphObject * self, if (igraphmodule_PyObject_to_es_t(list, &es, &self->g, 0)) return NULL; - if (igraph_subgraph_edges(&self->g, &sg, es, PyObject_IsTrue(delete_vertices))) { + if (igraph_subgraph_from_edges(&self->g, &sg, es, PyObject_IsTrue(delete_vertices))) { igraphmodule_handle_igraph_error(); igraph_es_destroy(&es); return NULL; diff --git a/vendor/source/igraph b/vendor/source/igraph index 3bfdc13f2..ae908007e 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 3bfdc13f28aaa6c6f1aa5f5d092b4ca31a5235f5 +Subproject commit ae908007efae21623c16ff752780a14a78aa149d From 6a65d16bf9de28b882addc71a6fcdd6734f8af3d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Dec 2022 21:29:37 +0100 Subject: [PATCH 1179/1892] chore: updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f8f5e9df..4768e003a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Changed +- The C core of igraph was updated to version 0.10.3. + - UMAP layout now exposes the computation of the symmetrized edge weights via `umap_compute_weights()`. The layout function, `Graph.layout_umap()`, can now be called either on a directed graph with edge distances, or on an @@ -11,6 +13,7 @@ `umap_compute_weights()` or precomputed by the user. Moreover, the `sampling_prob` argument was faulty and has been removed. See PR [#613](https://github.com/igraph/python-igraph/pull/613) for details. + - The `resolution_parameter` argument of `Graph.community_leiden()` was renamed to `resolution` for sake of consistency. The old variant still works with a deprecation warning, but will be removed in a future version. From b4c04ab78fd6fca96793c6e77bda887968c77620 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Dec 2022 21:29:53 +0100 Subject: [PATCH 1180/1892] fix: test script now builds the C core of igraph for macOS 12.0 --- test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test.sh b/test.sh index 215dd5e97..0e55c78e8 100755 --- a/test.sh +++ b/test.sh @@ -38,6 +38,8 @@ if [ x$CLEAN = x1 ]; then rm -rf vendor/build vendor/install fi +export MACOSX_DEPLOYMENT_TARGET=12.0 + # pip install is called in verbose mode so we can see the compiler warnings $VENV_DIR/bin/pip install -v .[plotting,test] $VENV_DIR/bin/pytest tests ${PYTEST_ARGS} From 2c918471dc44aaa0f8708e979b7df2ce3dea466c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 31 Dec 2022 21:34:14 +0100 Subject: [PATCH 1181/1892] chore: bumped version to 0.10.3 --- CHANGELOG.md | 5 +++-- src/igraph/version.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4768e003a..b3a39147f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.3] - 2022-12-31 ### Changed @@ -441,7 +441,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.2...master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.3...master +[0.10.3]: https://github.com/igraph/python-igraph/compare/0.10.2...0.10.3 [0.10.2]: https://github.com/igraph/python-igraph/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/igraph/python-igraph/compare/0.10.0...0.10.1 [0.10.0]: https://github.com/igraph/python-igraph/compare/0.9.11...0.10.0 diff --git a/src/igraph/version.py b/src/igraph/version.py index cb33a78fc..32f861113 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 2) +__version_info__ = (0, 10, 3) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 502281f752d2ca39adecca24c7781a6a9adc42ee Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jan 2023 11:31:49 +0100 Subject: [PATCH 1182/1892] fix: RTD prebuild script should fail early if needed --- scripts/rtd_prebuild.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/rtd_prebuild.sh b/scripts/rtd_prebuild.sh index b35e22f0a..9b41bab13 100755 --- a/scripts/rtd_prebuild.sh +++ b/scripts/rtd_prebuild.sh @@ -1,5 +1,7 @@ #!/bin/sh +set -e + echo "Compile and install igraph into venv. This might take a few minutes..." /home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/bin/pip wheel -q -w dist . /home/docs/checkouts/readthedocs.org/user_builds/igraph/envs/${READTHEDOCS_VERSION}/bin/pip install -q --force-reinstall dist/*.whl From 8f54f856b4c404c3bc0a4e7a15d9569f3d0d9f1b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jan 2023 11:32:07 +0100 Subject: [PATCH 1183/1892] doc: fix build of gallery examples on RTD --- scripts/patch_modularized_graph_methods.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/patch_modularized_graph_methods.py b/scripts/patch_modularized_graph_methods.py index 0ad893737..085b9f539 100644 --- a/scripts/patch_modularized_graph_methods.py +++ b/scripts/patch_modularized_graph_methods.py @@ -9,6 +9,7 @@ auxiliary_imports = [ ('typing', '*'), ('igraph.io.files', '_identify_format'), + ('igraph.community', '_optimal_cluster_count_from_merges_and_modularity'), ] From f73bbc42f206f1d31b8c7723002e36826672bf98 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jan 2023 11:39:09 +0100 Subject: [PATCH 1184/1892] fix: fix a circular import in RTD patched build --- src/igraph/clustering.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index d54d684f5..47cb58f7d 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -5,8 +5,7 @@ from copy import deepcopy from io import StringIO -from igraph._igraph import GraphBase -from igraph import community_to_membership +from igraph._igraph import GraphBase, community_to_membership from igraph.configuration import Configuration from igraph.datatypes import UniqueIdGenerator from igraph.drawing.colors import ClusterColoringPalette From 94d14b2fc6694825d93298cf11d35efeecba82ba Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jan 2023 12:45:10 +0100 Subject: [PATCH 1185/1892] fix: add sphinxcontrib-jquery to bring back JQuery for newer Sphinx versions --- doc/source/conf.py | 1 + doc/source/requirements.txt | 3 ++- scripts/mkdoc.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index aeced121c..2226aa156 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -68,6 +68,7 @@ def get_igraph_version(): # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. sys.path.insert(0, os.path.abspath('sphinxext')) extensions = [ + 'sphinxcontrib.jquery', 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx', diff --git a/doc/source/requirements.txt b/doc/source/requirements.txt index 88d997594..a5350bfa4 100644 --- a/doc/source/requirements.txt +++ b/doc/source/requirements.txt @@ -2,8 +2,9 @@ pip wheel requests>=2.28.1 -sphinxbootstrap4theme sphinx-gallery +sphinx-rtd-theme +sphinxcontrib-jquery pydoctor numpy diff --git a/scripts/mkdoc.sh b/scripts/mkdoc.sh index 3e3a659f1..82ed81625 100755 --- a/scripts/mkdoc.sh +++ b/scripts/mkdoc.sh @@ -57,7 +57,7 @@ if [ ! -d ".venv" ]; then fi # Make sure that Sphinx, PyDoctor (and maybe doc2dash) are up-to-date in the virtualenv -.venv/bin/pip install -U sphinx pydoctor sphinxbootstrap4theme sphinx-gallery +.venv/bin/pip install -U sphinx pydoctor sphinxbootstrap4theme sphinx-gallery sphinxcontrib-jquery if [ x$DOC2DASH = x1 ]; then .venv/bin/pip install -U doc2dash fi From ee03c3cb08cfb6dbd2fcdf68d377fae8f3c601b6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 1 Jan 2023 12:59:47 +0100 Subject: [PATCH 1186/1892] doc: restore sphinxbootstrap4theme in doc requirements --- doc/source/conf.py | 3 ++- doc/source/requirements.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 2226aa156..bf3853af3 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -17,13 +17,14 @@ import os import importlib from pathlib import Path -import sphinxbootstrap4theme # Check if we are inside readthedocs, the conf is quite different there is_inside_rtd = os.getenv("READTHEDOCS", "") == "True" rtd_version = os.getenv("READTHEDOCS_VERSION", "") +if not is_inside_rtd: + import sphinxbootstrap4theme # Utility functions # NOTE: these could be improved, esp by importing igraph, but that diff --git a/doc/source/requirements.txt b/doc/source/requirements.txt index a5350bfa4..af675f44c 100644 --- a/doc/source/requirements.txt +++ b/doc/source/requirements.txt @@ -2,6 +2,7 @@ pip wheel requests>=2.28.1 +sphinxbootstrap4theme sphinx-gallery sphinx-rtd-theme sphinxcontrib-jquery From 2261de0d020807dee4a168175c96571e865adedb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Wed, 11 Jan 2023 11:05:51 +0100 Subject: [PATCH 1187/1892] doc: fixed vertex count in quickstart example, thanks to @pauljurczak --- doc/examples_sphinx-gallery/quickstart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples_sphinx-gallery/quickstart.py b/doc/examples_sphinx-gallery/quickstart.py index 8edf0c9d3..8fcefb43e 100644 --- a/doc/examples_sphinx-gallery/quickstart.py +++ b/doc/examples_sphinx-gallery/quickstart.py @@ -18,8 +18,8 @@ import igraph as ig import matplotlib.pyplot as plt -# Construct a graph with 3 vertices -n_vertices = 3 +# Construct a graph with 5 vertices +n_vertices = 5 edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (3, 4)] g = ig.Graph(n_vertices, edges) From 79d4b2dc5794d17711392d6073b9bc5c70222271 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 12 Jan 2023 17:44:35 +0100 Subject: [PATCH 1188/1892] doc: fix the documentation of the 'seed' argument of Graph.layout_kamada_kawai(), closes #626 --- src/_igraph/graphobject.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 17cc9b231..111b9284d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -15322,9 +15322,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "An Algorithm for Drawing General Undirected Graphs.\n" "Information Processing Letters, 31/1, 7--15, 1989.\n\n" "@param maxiter: the maximum number of iterations to perform.\n" - "@param seed: if C{None}, uses a random starting layout for the\n" - " algorithm. If a matrix (list of lists), uses the given matrix\n" - " as the starting position.\n" + "@param seed: when C{None}, uses a circular layout as a starting point for the\n" + " algorithm when no bounds are given, or a random layout when bounds are\n" + " specified for the coordinated. When the argument is a matrix (list of\n" + " lists), it uses the given matrix as the initial layout.\n" "@param epsilon: quit if the energy of the system changes less than\n" " epsilon. See the original paper for details.\n" "@param kkconst: the Kamada-Kawai vertex attraction constant.\n" From a09df6f7be4d26de5c69de49798a24ccf4fbfa2d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 12 Jan 2023 18:06:47 +0100 Subject: [PATCH 1189/1892] fix: Kamada-Kawai layout iteration count now scales with the number of vertices; closes #627 --- src/_igraph/graphobject.c | 42 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 111b9284d..791054cf2 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -7214,9 +7214,11 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * igraph_matrix_t m; igraph_bool_t use_seed = false; igraph_error_t ret; - Py_ssize_t niter = 1000, dim = 2; - double kkconst, epsilon = 0.0; - PyObject *result_o, *seed_o=Py_None; + igraph_integer_t maxiter; + Py_ssize_t dim = 2; + igraph_real_t kkconst; + double epsilon = 0.0; + PyObject *result_o, *maxiter_o=Py_None, *seed_o=Py_None, *kkconst_o=Py_None; PyObject *minx_o=Py_None, *maxx_o=Py_None; PyObject *miny_o=Py_None, *maxy_o=Py_None; PyObject *minz_o=Py_None, *maxz_o=Py_None; @@ -7234,10 +7236,11 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * } kkconst = igraph_vcount(&self->g); + maxiter = 50 * igraph_vcount(&self->g); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nddOOOOOOOn", kwlist, - &niter, &epsilon, - &kkconst, &seed_o, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OdOOOOOOOOn", kwlist, + &maxiter_o, &epsilon, + &kkconst_o, &seed_o, &minx_o, &maxx_o, &miny_o, &maxy_o, &minz_o, &maxz_o, &dim)) @@ -7249,8 +7252,22 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * return NULL; } - CHECK_SSIZE_T_RANGE_POSITIVE(niter, "number of iterations"); + /* Convert number of iterations */ + if (maxiter_o != 0 && maxiter_o != Py_None) { + if (igraphmodule_PyObject_to_integer_t(maxiter_o, &maxiter)) { + return NULL; + } + } + CHECK_SSIZE_T_RANGE_POSITIVE(maxiter, "number of iterations"); + + /* Convert Kamada-Kawai constant */ + if (kkconst_o != 0 && kkconst_o != Py_None) { + if (igraphmodule_PyObject_to_real_t(kkconst_o, &kkconst)) { + return NULL; + } + } + /* Handle seed */ if (seed_o == 0 || seed_o == Py_None) { if (igraph_matrix_init(&m, 1, 1)) { igraphmodule_handle_igraph_error(); @@ -7304,11 +7321,11 @@ PyObject *igraphmodule_Graph_layout_kamada_kawai(igraphmodule_GraphObject * } if (dim == 2) ret = igraph_layout_kamada_kawai - (&self->g, &m, use_seed, niter, epsilon, kkconst, + (&self->g, &m, use_seed, maxiter, epsilon, kkconst, /*weights=*/ 0, /*bounds*/ minx, maxx, miny, maxy); else ret = igraph_layout_kamada_kawai_3d - (&self->g, &m, use_seed, niter, epsilon, kkconst, + (&self->g, &m, use_seed, maxiter, epsilon, kkconst, /*weights=*/ 0, /*bounds*/ minx, maxx, miny, maxy, minz, maxz); DESTROY_VECTORS; @@ -15315,13 +15332,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"layout_kamada_kawai", (PyCFunction) igraphmodule_Graph_layout_kamada_kawai, METH_VARARGS | METH_KEYWORDS, - "layout_kamada_kawai(maxiter=1000, epsilon=0, kkconst=None, seed=None, " + "layout_kamada_kawai(maxiter=None, epsilon=0, kkconst=None, seed=None, " "minx=None, maxx=None, miny=None, maxy=None, minz=None, maxz=None, dim=2)\n--\n\n" "Places the vertices on a plane according to the Kamada-Kawai algorithm.\n\n" "This is a force directed layout, see Kamada, T. and Kawai, S.:\n" "An Algorithm for Drawing General Undirected Graphs.\n" "Information Processing Letters, 31/1, 7--15, 1989.\n\n" - "@param maxiter: the maximum number of iterations to perform.\n" + "@param maxiter: the maximum number of iterations to perform. C{None} selects\n" + " a reasonable default based on the number of vertices.\n" "@param seed: when C{None}, uses a circular layout as a starting point for the\n" " algorithm when no bounds are given, or a random layout when bounds are\n" " specified for the coordinated. When the argument is a matrix (list of\n" @@ -15329,7 +15347,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param epsilon: quit if the energy of the system changes less than\n" " epsilon. See the original paper for details.\n" "@param kkconst: the Kamada-Kawai vertex attraction constant.\n" - " C{None} means the square of the number of vertices.\n" + " C{None} means the number of vertices.\n" "@param minx: if not C{None}, it must be a vector with exactly as many\n" " elements as there are vertices in the graph. Each element is a\n" " minimum constraint on the X value of the vertex in the layout.\n" From d6c49d842516236bc07e29976132a9c6af68431c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 12 Jan 2023 19:00:02 +0100 Subject: [PATCH 1190/1892] fix: replace deprecated ConfigParser.readfp() with ConfigParser.read_file() --- src/igraph/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/configuration.py b/src/igraph/configuration.py index aa9922333..708133e50 100644 --- a/src/igraph/configuration.py +++ b/src/igraph/configuration.py @@ -313,7 +313,7 @@ def load(self, stream=None): if isinstance(stream, str): stream = open(stream, "r") file_was_open = True - self._config.readfp(stream) + self._config.read_file(stream) self._filename = getattr(stream, "name", None) if file_was_open: stream.close() From 55d227407571b8dd1146c032a2a6c633808f7a15 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 12 Jan 2023 21:47:58 +0100 Subject: [PATCH 1191/1892] doc: update link to Python branch status in README [ci skip] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c54f5dbb..c22ea7ed8 100644 --- a/README.md +++ b/README.md @@ -270,8 +270,8 @@ faster than the first one as the C core does not need to be recompiled. We aim to keep up with the development cycle of Python and support all official Python versions that have not reached their end of life yet. Currently this -means that we support Python 3.7 to 3.10, inclusive. Please refer to [this -page](https://devguide.python.org/#branchstatus) for the status of Python +means that we support Python 3.7 to 3.11, inclusive. Please refer to [this +page](https://devguide.python.org/versions/) for the status of Python branches and let us know if you encounter problems with `igraph` on any of the non-EOL Python versions. From 6655f668b330a501a9ef3bcfd7f5bcac97cfe497 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 14:42:32 +0000 Subject: [PATCH 1192/1892] build(deps): bump pypa/cibuildwheel from 2.11.4 to 2.12.0 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.11.4 to 2.12.0. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.11.4...v2.12.0) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27b803dd7..d26d4f032 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,14 +63,14 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -137,7 +137,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -196,7 +196,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.11.4 + uses: pypa/cibuildwheel@v2.12.0 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From b17386a683746d45b1556f6bc0658f9c0fc8385e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 19 Jan 2023 16:14:03 +0100 Subject: [PATCH 1193/1892] fix: improve error message for union() and intersection() when not all graphs are named --- src/igraph/operators/functions.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/igraph/operators/functions.py b/src/igraph/operators/functions.py index fe9f34f48..d50cc4fbb 100644 --- a/src/igraph/operators/functions.py +++ b/src/igraph/operators/functions.py @@ -128,7 +128,7 @@ def union(graphs, byname="auto"): False, ignore vertex names. If True, merge vertices based on names. If 'auto', use True if all graphs have named vertices and False otherwise (in the latter case, a warning is generated too). - + Returns: the union graph @@ -148,9 +148,14 @@ def union(graphs, byname="auto"): if byname == "auto": byname = n_named == ngr if n_named not in (0, ngr): - warn("Some, but not all graphs are named, not using vertex names") + warn( + f"Some, but not all graphs are named (got {n_named} named, " + f"{ngr-n_named} unnamed), not using vertex names" + ) elif byname and (n_named != ngr): - raise RuntimeError("Some graphs are not named") + raise RuntimeError( + f"Some graphs are not named (got {n_named} named, {ngr-n_named} unnamed)" + ) # Now we know that byname is only used is all graphs are named # Trivial cases @@ -337,9 +342,14 @@ def intersection(graphs, byname="auto", keep_all_vertices=True): if byname == "auto": byname = n_named == ngr if n_named not in (0, ngr): - warn("Some, but not all graphs are named, not using vertex names") + warn( + f"Some, but not all graphs are named (got {n_named} named, " + f"{ngr-n_named} unnamed), not using vertex names" + ) elif byname and (n_named != ngr): - raise AttributeError("Some graphs are not named") + raise RuntimeError( + f"Some graphs are not named (got {n_named} named, {ngr-n_named} unnamed)" + ) # Now we know that byname is only used is all graphs are named # Trivial cases From 346fb495b7e9435211d521ef5e2545e6838f4415 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 19 Jan 2023 16:26:43 +0100 Subject: [PATCH 1194/1892] fix: fix drawing of VertexDendrogram with the Cairo backend, closes #628 --- src/igraph/drawing/cairo/dendrogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/cairo/dendrogram.py b/src/igraph/drawing/cairo/dendrogram.py index c1dc06db8..9e7b2a7dc 100644 --- a/src/igraph/drawing/cairo/dendrogram.py +++ b/src/igraph/drawing/cairo/dendrogram.py @@ -136,7 +136,7 @@ def draw(self, dendro, **kwds): # Calculate space needed for individual items at the # bottom of the dendrogram item_boxes = [ - dendro._item_box_size(context, horiz, idx) for idx in range(dendro._nitems) + self._item_box_size(dendro, context, horiz, idx) for idx in range(dendro._nitems) ] # Small correction for cases when the right edge of the labels is From 4250b6bf11241de97526cac4e71eee70ce3e0f34 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 19 Jan 2023 16:26:58 +0100 Subject: [PATCH 1195/1892] fix: fix drawing of VertexDendrogram with the Matplotlib backend --- src/igraph/drawing/matplotlib/dendrogram.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/igraph/drawing/matplotlib/dendrogram.py b/src/igraph/drawing/matplotlib/dendrogram.py index 9e87b835b..4354ce143 100644 --- a/src/igraph/drawing/matplotlib/dendrogram.py +++ b/src/igraph/drawing/matplotlib/dendrogram.py @@ -72,6 +72,10 @@ def draw(self, dendro, orientation="lr", **kwds): ax = self.context + # Pop unneeded arguments from kwds that are passed down to us by + # default but cannot be interpreted by Matplotlib + kwds.pop("palette", None) + # Styling defaults kwds["edgecolor"] = kwds.pop("color", "black") if ("lw" not in kwds) and ("linewidth" not in kwds): From cd9cf639d0e908b72720f2de5d8d2f75690296a1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 19 Jan 2023 16:29:17 +0100 Subject: [PATCH 1196/1892] chore: updated changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a39147f..0966c2527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- Fixed the drawing of `VertexDendrogram` instances, both in the Cairo and the + Matplotlib backends. + ## [0.10.3] - 2022-12-31 ### Changed From df5cbf24d64dc2cd960c74ef95cbac1e2491fd02 Mon Sep 17 00:00:00 2001 From: pmp-p Date: Mon, 23 Jan 2023 01:14:26 +0100 Subject: [PATCH 1197/1892] first build try for @skelsec --- src/_igraph/graphobject.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 791054cf2..7a2fc9b62 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1620,7 +1620,7 @@ PyObject *igraphmodule_Graph_get_diameter(igraphmodule_GraphObject * self, } else { if (igraph_diameter(&self->g, 0, /* from, to, vertex_path, edge_path */ - 0, 0, &res, 0, + 0, 0, &res, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; @@ -1657,7 +1657,7 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, if (weights) { if (igraph_diameter_dijkstra(&self->g, weights, &len, - /* from, to, vertex_path, edge_path */ + /* from, to, vertex_path, edge_path */ &from, &to, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); @@ -1673,7 +1673,7 @@ PyObject *igraphmodule_Graph_farthest_points(igraphmodule_GraphObject * self, } else { if (igraph_diameter(&self->g, &len, /* from, to, vertex_path, edge_path */ - &from, &to, 0, 0, + &from, &to, 0, 0, PyObject_IsTrue(dir), PyObject_IsTrue(vcount_if_unconnected))) { igraphmodule_handle_igraph_error(); return NULL; @@ -3636,7 +3636,7 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, if (self == NULL) { return NULL; } - + weights_o = igraphmodule_vector_t_to_PyList(&weights, IGRAPHMODULE_TYPE_FLOAT); if (!weights_o) { Py_DECREF(self); @@ -4258,7 +4258,7 @@ PyObject *igraphmodule_Graph_chordal_completion( alpham1_ptr = &alpham1; } - + if (igraph_vector_int_init(&edges, 0)) { igraphmodule_handle_igraph_error(); if (alpham1_ptr) { @@ -4490,7 +4490,7 @@ PyObject *igraphmodule_Graph_connected_components( igraphmodule_handle_igraph_error(); return NULL; } - + if (igraph_vector_int_init(&res2, 10)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&res1); @@ -5362,7 +5362,7 @@ PyObject *igraphmodule_Graph_is_chordal( alpham1_ptr = &alpham1; } - + if (igraph_is_chordal( &self->g, alpha_ptr, /* alpha */ @@ -5430,7 +5430,7 @@ PyObject *igraphmodule_Graph_maximum_cardinality_search(igraphmodule_GraphObject igraphmodule_handle_igraph_error(); return NULL; } - + if (igraph_vector_int_init(&alpham1, 0)) { igraph_vector_int_destroy(&alpha); igraphmodule_handle_igraph_error(); @@ -6755,7 +6755,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_no(igraphmodule_GraphObject *self, return NULL; CHECK_SSIZE_T_RANGE_POSITIVE(size, "motif size"); - + if (cut_prob_list == Py_None) { if (igraph_vector_init(&cut_prob, size)) { return igraphmodule_handle_igraph_error(); @@ -6795,7 +6795,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s return NULL; CHECK_SSIZE_T_RANGE_POSITIVE(size, "motif size"); - + if (sample == Py_None) { PyErr_SetString(PyExc_TypeError, "sample size must be given"); return NULL; @@ -8381,7 +8381,7 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, * \sa igraph_get_edgelist */ PyObject *igraphmodule_Graph_get_edgelist(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) + PyObject * _null) { igraph_vector_int_t edgelist; PyObject *result_o; @@ -10585,7 +10585,7 @@ PyObject *igraphmodule_Graph_bfs(igraphmodule_GraphObject * self, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &vid_o, &mode_o)) return NULL; - + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; if (igraphmodule_PyObject_to_vid(vid_o, &vid, &self->g)) { @@ -13700,7 +13700,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " graph to uniformly sample its spanning trees (Wilson's algorithm).\n" " This is the default choice as it supports both directed and\n" " undirected graphs.\n" - }, + }, /* interface to igraph_watts_strogatz_game */ {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, @@ -17249,7 +17249,7 @@ int igraphmodule_Graph_register_type() { { Py_mp_subscript, igraphmodule_Graph_mp_subscript }, { Py_mp_ass_subscript, igraphmodule_Graph_mp_assign_subscript }, - + { 0 } }; From 1a6b714821ed0965f2a22e0ebde3ed3ba7f21317 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 23 Jan 2023 19:21:42 +0100 Subject: [PATCH 1198/1892] fix: fix signature of METH_NOARGS Python functions, they should have an extra unused PyObject* argument --- src/_igraph/edgeobject.c | 12 ++--- src/_igraph/edgeseqobject.c | 6 +-- src/_igraph/graphobject.c | 91 +++++++++++++++++------------------ src/_igraph/graphobject.h | 6 +-- src/_igraph/igraphmodule.c | 2 +- src/_igraph/vertexobject.c | 18 +++---- src/_igraph/vertexseqobject.c | 6 +-- 7 files changed, 69 insertions(+), 72 deletions(-) diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index abed303f1..82b8ae9e4 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -37,7 +37,7 @@ PyTypeObject* igraphmodule_EdgeType; -PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self); +PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self, PyObject* _null); /** * \ingroup python_interface_edge @@ -151,7 +151,7 @@ static PyObject* igraphmodule_Edge_repr(igraphmodule_EdgeObject *self) { PyObject *s; PyObject *attrs; - attrs = igraphmodule_Edge_attributes(self); + attrs = igraphmodule_Edge_attributes(self, NULL); if (attrs == 0) return NULL; @@ -256,14 +256,14 @@ Py_ssize_t igraphmodule_Edge_attribute_count(igraphmodule_EdgeObject* self) { /** \ingroup python_interface_edge * \brief Returns the list of attribute names */ -PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self) { - return self->gref ? igraphmodule_Graph_edge_attributes(self->gref) : 0; +PyObject* igraphmodule_Edge_attribute_names(igraphmodule_EdgeObject* self, PyObject* Py_UNUSED(_null)) { + return self->gref ? igraphmodule_Graph_edge_attributes(self->gref, NULL) : NULL; } /** \ingroup python_interface_edge * \brief Returns a dict with attribute names and values */ -PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self) { +PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self, PyObject* Py_UNUSED(_null)) { igraphmodule_GraphObject *o = self->gref; PyObject *names, *dict; Py_ssize_t i, n; @@ -277,7 +277,7 @@ PyObject* igraphmodule_Edge_attributes(igraphmodule_EdgeObject* self) { return NULL; } - names = igraphmodule_Graph_edge_attributes(o); + names = igraphmodule_Graph_edge_attributes(o, NULL); if (!names) { Py_DECREF(dict); return NULL; diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index b22b641af..2ea925fe5 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -259,8 +259,8 @@ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, /** \ingroup python_interface_edgeseq * \brief Returns the list of attribute names */ -PyObject* igraphmodule_EdgeSeq_attribute_names(igraphmodule_EdgeSeqObject* self) { - return igraphmodule_Graph_edge_attributes(self->gref); +PyObject* igraphmodule_EdgeSeq_attribute_names(igraphmodule_EdgeSeqObject* self, PyObject* Py_UNUSED(_null)) { + return igraphmodule_Graph_edge_attributes(self->gref, NULL); } /** \ingroup python_interface_edgeseq @@ -373,7 +373,7 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* return result; } -PyObject* igraphmodule_EdgeSeq_is_all(igraphmodule_EdgeSeqObject* self) { +PyObject* igraphmodule_EdgeSeq_is_all(igraphmodule_EdgeSeqObject* self, PyObject* Py_UNUSED(_null)) { if (igraph_es_is_all(&self->es)) { Py_RETURN_TRUE; } else { diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 7a2fc9b62..4aefc16e9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -392,7 +392,7 @@ PyObject *igraphmodule_Graph_str(igraphmodule_GraphObject * self) * \brief Creates a copy of the graph * \return the copy of the graph */ -PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraphmodule_GraphObject *result_o; igraph_t g; @@ -416,7 +416,7 @@ PyObject *igraphmodule_Graph_copy(igraphmodule_GraphObject * self) * \return the number of vertices as a \c PyObject * \sa igraph_vcount */ -PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { return igraphmodule_integer_t_to_PyObject(igraph_vcount(&self->g)); } @@ -426,7 +426,7 @@ PyObject *igraphmodule_Graph_vcount(igraphmodule_GraphObject * self) * \return the number of edges as a \c PyObject * \sa igraph_ecount */ -PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { return igraphmodule_integer_t_to_PyObject(igraph_ecount(&self->g)); } @@ -436,7 +436,7 @@ PyObject *igraphmodule_Graph_ecount(igraphmodule_GraphObject * self) * \return \c True if the graph is directed, \c False otherwise. * \sa igraph_is_directed */ -PyObject *igraphmodule_Graph_is_directed(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_is_directed(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { if (igraph_is_directed(&self->g)) Py_RETURN_TRUE; @@ -533,7 +533,7 @@ PyObject *igraphmodule_Graph_is_maximal_matching(igraphmodule_GraphObject* self, * \return \c True if the graph is simple, \c False otherwise. * \sa igraph_is_simple */ -PyObject *igraphmodule_Graph_is_simple(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_is_simple(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { igraph_bool_t res; if (igraph_is_simple(&self->g, &res)) { @@ -551,8 +551,8 @@ PyObject *igraphmodule_Graph_is_simple(igraphmodule_GraphObject *self) { * \brief Determines whether a graph is a (directed or undirected) tree * \sa igraph_is_tree */ -PyObject *igraphmodule_Graph_is_tree(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) +PyObject *igraphmodule_Graph_is_tree(igraphmodule_GraphObject* self, + PyObject* args, PyObject* kwds) { static char *kwlist[] = { "mode", NULL }; PyObject *mode_o = Py_None; @@ -1133,7 +1133,7 @@ PyObject *igraphmodule_Graph_is_mutual(igraphmodule_GraphObject *self, * \return \c True if the graph has multiple edges, \c False otherwise. * \sa igraph_has_multiple */ -PyObject *igraphmodule_Graph_has_multiple(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_has_multiple(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { igraph_bool_t res; if (igraph_has_multiple(&self->g, &res)) { @@ -1739,9 +1739,9 @@ PyObject *igraphmodule_Graph_girth(igraphmodule_GraphObject *self, * \ingroup python_interface_graph * \brief Calculates the convergence degree of the edges in a graph */ -PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_t res; - PyObject *o; + PyObject *o; igraph_vector_init(&res, 0); if (igraph_convergence_degree(&self->g, &res, 0, 0)) { @@ -1750,8 +1750,9 @@ PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) return NULL; } - o=igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); + o = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); + return o; } @@ -1759,7 +1760,7 @@ PyObject *igraphmodule_Graph_convergence_degree(igraphmodule_GraphObject *self) * \ingroup python_interface_graph * \brief Calculates the sizes of the convergence fields in a graph */ -PyObject *igraphmodule_Graph_convergence_field_size(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_convergence_field_size(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_t ins, outs; PyObject *o1, *o2; @@ -1772,8 +1773,8 @@ PyObject *igraphmodule_Graph_convergence_field_size(igraphmodule_GraphObject *se return NULL; } - o1=igraphmodule_vector_t_to_PyList(&ins, IGRAPHMODULE_TYPE_INT); - o2=igraphmodule_vector_t_to_PyList(&outs, IGRAPHMODULE_TYPE_INT); + o1 = igraphmodule_vector_t_to_PyList(&ins, IGRAPHMODULE_TYPE_INT); + o2 = igraphmodule_vector_t_to_PyList(&outs, IGRAPHMODULE_TYPE_INT); igraph_vector_destroy(&ins); igraph_vector_destroy(&outs); return Py_BuildValue("NN", o1, o2); @@ -1893,7 +1894,7 @@ PyObject *igraphmodule_Graph_radius(igraphmodule_GraphObject * self, * \return the Prufer sequence as a Python object * \sa igraph_to_prufer */ -PyObject *igraphmodule_Graph_to_prufer(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_to_prufer(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_int_t res; PyObject *list; @@ -3658,7 +3659,7 @@ PyObject *igraphmodule_Graph_Weighted_Adjacency(PyTypeObject * type, * \return the list of articulation points in a PyObject * \sa igraph_articulation_points */ -PyObject *igraphmodule_Graph_articulation_points(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_articulation_points(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { igraph_vector_int_t res; PyObject *o; if (igraph_vector_int_init(&res, 0)) { @@ -4207,7 +4208,7 @@ PyObject *igraphmodule_Graph_bipartite_projection_size(igraphmodule_GraphObject * \return the list of bridges in a PyObject * \sa igraph_bridges */ -PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_bridges(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_int_t res; PyObject *o; if (igraph_vector_int_init(&res, 0)) { @@ -5422,7 +5423,7 @@ PyObject *igraphmodule_Graph_linegraph(igraphmodule_GraphObject * self) { * \brief Conducts a maximum cardinality search on the graph. * \sa igraph_maximum_cardinality_search */ -PyObject *igraphmodule_Graph_maximum_cardinality_search(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_maximum_cardinality_search(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_int_t alpha, alpham1; PyObject *alpha_o, *alpham1_o; @@ -6583,7 +6584,7 @@ PyObject *igraphmodule_Graph_is_bipartite(igraphmodule_GraphObject *self, * \return the dyad census as a 3-tuple * \sa igraph_dyad_census */ -PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_real_t mut, asym, nul; PyObject *mut_o, *asym_o, *nul_o; @@ -6617,7 +6618,7 @@ PyObject *igraphmodule_Graph_dyad_census(igraphmodule_GraphObject *self) { * \return the triangles of the graph as a list of triplets with vertex IDs * \sa igraph_list_triangles */ -PyObject *igraphmodule_Graph_list_triangles(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_list_triangles(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_int_t res; PyObject *res_o; @@ -6850,7 +6851,7 @@ PyObject *igraphmodule_Graph_motifs_randesu_estimate(igraphmodule_GraphObject *s * \return the triad census as a list * \sa igraph_triad_census */ -PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_vector_t res; PyObject *list; @@ -6873,7 +6874,7 @@ PyObject *igraphmodule_Graph_triad_census(igraphmodule_GraphObject *self) { * Cycles and cycle bases * **********************************************************************/ -PyObject *igraphmodule_Graph_is_acyclic(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph_is_acyclic(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_bool_t res; if (igraph_is_acyclic(&self->g, &res)) { @@ -6888,7 +6889,7 @@ PyObject *igraphmodule_Graph_is_acyclic(igraphmodule_GraphObject *self) { } } -PyObject *igraphmodule_Graph_is_dag(igraphmodule_GraphObject * self) { +PyObject *igraphmodule_Graph_is_dag(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_bool_t res; if (igraph_is_dag(&self->g, &res)) { @@ -8381,7 +8382,7 @@ PyObject *igraphmodule_Graph_laplacian(igraphmodule_GraphObject * self, * \sa igraph_get_edgelist */ PyObject *igraphmodule_Graph_get_edgelist(igraphmodule_GraphObject * self, - PyObject * _null) + PyObject* Py_UNUSED(_null)) { igraph_vector_int_t edgelist; PyObject *result_o; @@ -10398,7 +10399,7 @@ int igraphmodule_Graph_mp_assign_subscript(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Returns the attribute list of the graph */ -PyObject *igraphmodule_Graph_attributes(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_attributes(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { return PyDict_Keys(ATTR_STRUCT_DICT(&self->g)[ATTRHASH_IDX_GRAPH]); } @@ -10406,8 +10407,7 @@ PyObject *igraphmodule_Graph_attributes(igraphmodule_GraphObject * self) /** \ingroup python_interface_graph * \brief Returns the attribute list of the graph's vertices */ -PyObject *igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject * - self) +PyObject *igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { return PyDict_Keys(ATTR_STRUCT_DICT(&self->g)[ATTRHASH_IDX_VERTEX]); } @@ -10415,7 +10415,7 @@ PyObject *igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject * /** \ingroup python_interface_graph * \brief Returns the attribute list of the graph's edges */ -PyObject *igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { return PyDict_Keys(ATTR_STRUCT_DICT(&self->g)[ATTRHASH_IDX_EDGE]); } @@ -11346,7 +11346,7 @@ PyObject *igraphmodule_Graph_st_mincut(igraphmodule_GraphObject * self, * \brief Returns all minimal s-t separators of a graph */ PyObject *igraphmodule_Graph_all_minimal_st_separators( - igraphmodule_GraphObject * self) { + igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { PyObject* result_o; igraph_vector_int_list_t res; @@ -11437,7 +11437,7 @@ PyObject *igraphmodule_Graph_is_minimal_separator(igraphmodule_GraphObject * sel * \brief Returns the minimum size separators of the graph */ PyObject *igraphmodule_Graph_minimum_size_separators( - igraphmodule_GraphObject * self) { + igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { PyObject* result_o; igraph_vector_int_list_t res; @@ -11465,8 +11465,7 @@ PyObject *igraphmodule_Graph_minimum_size_separators( /** \ingroup python_interface_graph * \brief Calculates the cohesive block structure of a graph */ -PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, - PyObject *args, PyObject *kwds) { +PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { PyObject *blocks_o, *cohesion_o, *parents_o, *result_o; igraph_vector_int_list_t blocks; igraph_vector_int_t cohesion, parents; @@ -11582,7 +11581,7 @@ PyObject *igraphmodule_Graph_cliques(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Find all largest cliques in a graph */ -PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_largest_cliques(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { PyObject *list; igraph_vector_int_list_t res; @@ -11702,7 +11701,7 @@ PyObject *igraphmodule_Graph_maximal_cliques(igraphmodule_GraphObject * self, /** \ingroup python_interface_graph * \brief Returns the clique number of the graph */ -PyObject *igraphmodule_Graph_clique_number(igraphmodule_GraphObject * self) +PyObject *igraphmodule_Graph_clique_number(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { igraph_integer_t i; @@ -11759,10 +11758,9 @@ PyObject *igraphmodule_Graph_independent_vertex_sets(igraphmodule_GraphObject /** \ingroup python_interface_graph * \brief Find all largest independent_vertex_sets in a graph */ -PyObject - *igraphmodule_Graph_largest_independent_vertex_sets(igraphmodule_GraphObject - * self) -{ +PyObject *igraphmodule_Graph_largest_independent_vertex_sets( + igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null) +) { PyObject *list; igraph_vector_int_list_t res; @@ -11784,10 +11782,9 @@ PyObject /** \ingroup python_interface_graph * \brief Find all maximal independent vertex sets in a graph */ -PyObject - *igraphmodule_Graph_maximal_independent_vertex_sets(igraphmodule_GraphObject - * self) -{ +PyObject *igraphmodule_Graph_maximal_independent_vertex_sets( + igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null) +) { PyObject *list; igraph_vector_int_list_t res; @@ -11809,9 +11806,9 @@ PyObject /** \ingroup python_interface_graph * \brief Returns the independence number of the graph */ -PyObject *igraphmodule_Graph_independence_number(igraphmodule_GraphObject * - self) -{ +PyObject *igraphmodule_Graph_independence_number( + igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null) +) { igraph_integer_t i; if (igraph_independence_number(&self->g, &i)) { @@ -12813,7 +12810,7 @@ PyObject *igraphmodule_Graph___graph_as_capsule__(igraphmodule_GraphObject * * Python integer. This allows us to use igraph graphs with the Python ctypes * module without any additional conversions. */ -PyObject *igraphmodule_Graph__raw_pointer(igraphmodule_GraphObject *self) { +PyObject *igraphmodule_Graph__raw_pointer(igraphmodule_GraphObject *self, PyObject* Py_UNUSED(_null)) { return PyLong_FromVoidPtr(&self->g); } @@ -13920,7 +13917,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@see: Graph.bipartite_projection_size()\n"}, /* interface to igraph_bridges */ - {"bridges", (PyCFunction)igraphmodule_Graph_bridges, + {"bridges", (PyCFunction) igraphmodule_Graph_bridges, METH_NOARGS, "bridges()\n--\n\n" "Returns the list of bridges in the graph.\n\n" diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 164b875cb..29e022239 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -55,8 +55,8 @@ int igraphmodule_Graph_register_type(void); PyObject* igraphmodule_Graph_subclass_from_igraph_t(PyTypeObject* type, igraph_t *graph); PyObject* igraphmodule_Graph_from_igraph_t(igraph_t *graph); -PyObject* igraphmodule_Graph_attributes(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject* self); -PyObject* igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject* self); +PyObject* igraphmodule_Graph_attributes(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)); +PyObject* igraphmodule_Graph_vertex_attributes(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)); +PyObject* igraphmodule_Graph_edge_attributes(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)); #endif diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 21d5cb3bd..6fa7d7f04 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -706,7 +706,7 @@ void igraphmodule__destroy_locale_capsule(PyObject *capsule) { } } -PyObject* igraphmodule__enter_safelocale(PyObject* self) { +PyObject* igraphmodule__enter_safelocale(PyObject* self, PyObject* Py_UNUSED(_null)) { igraph_safelocale_t* loc; PyObject* capsule; diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index 67cba83bc..f2894a36c 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -37,7 +37,7 @@ PyTypeObject* igraphmodule_VertexType; -PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self); +PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self, PyObject* _null); /** * \ingroup python_interface_vertex @@ -151,7 +151,7 @@ static PyObject* igraphmodule_Vertex_repr(igraphmodule_VertexObject *self) { PyObject *s; PyObject *attrs; - attrs = igraphmodule_Vertex_attributes(self); + attrs = igraphmodule_Vertex_attributes(self, NULL); if (attrs == 0) { return NULL; } @@ -257,14 +257,14 @@ Py_ssize_t igraphmodule_Vertex_attribute_count(igraphmodule_VertexObject* self) /** \ingroup python_interface_vertex * \brief Returns the list of attribute names */ -PyObject* igraphmodule_Vertex_attribute_names(igraphmodule_VertexObject* self) { - return self->gref ? igraphmodule_Graph_vertex_attributes(self->gref) : 0; +PyObject* igraphmodule_Vertex_attribute_names(igraphmodule_VertexObject* self, PyObject* Py_UNUSED(_null)) { + return self->gref ? igraphmodule_Graph_vertex_attributes(self->gref, NULL) : NULL; } /** \ingroup python_interface_vertex * \brief Returns a dict with attribue names and values */ -PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self) { +PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self, PyObject* Py_UNUSED(_null)) { igraphmodule_GraphObject *o = self->gref; PyObject *names, *dict; Py_ssize_t i, n; @@ -278,7 +278,7 @@ PyObject* igraphmodule_Vertex_attributes(igraphmodule_VertexObject* self) { return NULL; } - names = igraphmodule_Graph_vertex_attributes(o); + names = igraphmodule_Graph_vertex_attributes(o, NULL); if (!names) { Py_DECREF(dict); return NULL; @@ -425,7 +425,7 @@ PyObject* igraphmodule_Vertex_update_attributes(PyObject* self, PyObject* args, * \param args positional arguments * \param kwds keyword arguments */ -PyObject* igraphmodule_Vertex_all_edges(PyObject* self) { +PyObject* igraphmodule_Vertex_all_edges(PyObject* self, PyObject* Py_UNUSED(_null)) { return PyObject_CallMethod(self, "incident", "i", (int) IGRAPH_ALL); } @@ -437,7 +437,7 @@ PyObject* igraphmodule_Vertex_all_edges(PyObject* self) { * \param args positional arguments * \param kwds keyword arguments */ -PyObject* igraphmodule_Vertex_in_edges(PyObject* self) { +PyObject* igraphmodule_Vertex_in_edges(PyObject* self, PyObject* Py_UNUSED(_null)) { return PyObject_CallMethod(self, "incident", "i", (int) IGRAPH_IN); } @@ -449,7 +449,7 @@ PyObject* igraphmodule_Vertex_in_edges(PyObject* self) { * \param args positional arguments * \param kwds keyword arguments */ -PyObject* igraphmodule_Vertex_out_edges(PyObject* self) { +PyObject* igraphmodule_Vertex_out_edges(PyObject* self, PyObject* Py_UNUSED(_null)) { return PyObject_CallMethod(self, "incident", "i", (int) IGRAPH_OUT); } diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 573c66280..5183510c6 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -250,8 +250,8 @@ PyObject* igraphmodule_VertexSeq_sq_item(igraphmodule_VertexSeqObject* self, /** \ingroup python_interface_vertexseq * \brief Returns the list of attribute names */ -PyObject* igraphmodule_VertexSeq_attribute_names(igraphmodule_VertexSeqObject* self) { - return igraphmodule_Graph_vertex_attributes(self->gref); +PyObject* igraphmodule_VertexSeq_attribute_names(igraphmodule_VertexSeqObject* self, PyObject* Py_UNUSED(_null)) { + return igraphmodule_Graph_vertex_attributes(self->gref, NULL); } /** \ingroup python_interface_vertexseq @@ -1041,7 +1041,7 @@ PyObject* igraphmodule_VertexSeq__name_index(igraphmodule_VertexSeqObject* self, * \ingroup python_interface_vertexseq * Re-creates the dictionary that maps vertex names to vertex IDs. */ -PyObject* igraphmodule_VertexSeq__reindex_names(igraphmodule_VertexSeqObject* self) { +PyObject* igraphmodule_VertexSeq__reindex_names(igraphmodule_VertexSeqObject* self, PyObject* Py_UNUSED(_null)) { igraphmodule_index_vertex_names(&self->gref->g, 1); Py_RETURN_NONE; } From 222efa9d6a866317441e410c7205bc3a8631d614 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 24 Jan 2023 20:41:04 +0100 Subject: [PATCH 1199/1892] feat: skip header installation when building a wasm wheel with emscripten --- setup.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 0ac08c9ca..ab012f516 100644 --- a/setup.py +++ b/setup.py @@ -39,9 +39,12 @@ LIBIGRAPH_FALLBACK_LIBRARIES = ["igraph"] LIBIGRAPH_FALLBACK_LIBRARY_DIRS = [] -# Check whether we are compiling for PyPy. Headers will not be installed -# for PyPy. -SKIP_HEADER_INSTALL = (platform.python_implementation() == "PyPy") or ( +# Check whether we are compiling for PyPy or wasm with emscripten. Headers will +# not be installed in these cases, or when the SKIP_HEADER_INSTALL envvar is +# set explicitly. +SKIP_HEADER_INSTALL = ( + platform.python_implementation() == "PyPy" or + (sysconfig.get_config_var("HOST_GNU_TYPE") or "").endswith("emscripten") or "SKIP_HEADER_INSTALL" in os.environ ) From 8c260e9c8a5305fce0e23b7ada7851aa9e2cc255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 25 Jan 2023 10:11:41 +0100 Subject: [PATCH 1200/1892] fix: closeness_cutoff() broken handloing of cutoff argument --- src/_igraph/graphobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 4aefc16e9..706741407 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4362,8 +4362,8 @@ PyObject *igraphmodule_Graph_closeness(igraphmodule_GraphObject * self, if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } - if (igraph_closeness_cutoff(&self->g, &res, 0, 0, vs, mode, weights, - PyFloat_AsDouble(cutoff_num), PyObject_IsTrue(normalized_o))) { + if (igraph_closeness_cutoff(&self->g, &res, NULL, NULL, vs, mode, weights, + PyObject_IsTrue(normalized_o), PyFloat_AsDouble(cutoff_num))) { igraph_vs_destroy(&vs); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } From 4262c328ec4db5db3baf5733f8c521eaf5288767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Wed, 25 Jan 2023 10:15:52 +0100 Subject: [PATCH 1201/1892] chore: update changelog [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0966c2527..bac663026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Fixed the drawing of `VertexDendrogram` instances, both in the Cairo and the Matplotlib backends. +- The `cutoff` and `normalized` arguments of `Graph.closeness()` did not function correctly. ## [0.10.3] - 2022-12-31 From 6792363425b4716ea550a998697a786f29c560d7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 25 Jan 2023 12:18:26 +0100 Subject: [PATCH 1202/1892] doc: following up the master -> main rename in source files --- CHANGELOG.md | 2 +- README.md | 5 +++-- setup.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bac663026..7dda8a4bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -449,7 +449,7 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.3...master +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.3...main [0.10.3]: https://github.com/igraph/python-igraph/compare/0.10.2...0.10.3 [0.10.2]: https://github.com/igraph/python-igraph/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/igraph/python-igraph/compare/0.10.0...0.10.1 diff --git a/README.md b/README.md index c22ea7ed8..92892f595 100644 --- a/README.md +++ b/README.md @@ -186,8 +186,9 @@ pip install git+https://github.com/igraph/python-igraph This automatically fetches the development version from the repository, builds the package and installs it. By default, this will install the Python interface -from the `master` branch, which is used as the basis for the development of the -current release series. Unstable and breaking changes are being made in the `develop` branch. You can install this similarly by doing +from the `main` branch, which is used as the basis for the development of the +current release series. Unstable and breaking changes are being made in the +`develop` branch. You can install this similarly by doing ```bash pip install git+https://github.com/igraph/python-igraph@develop diff --git a/setup.py b/setup.py index ab012f516..f6918f254 100644 --- a/setup.py +++ b/setup.py @@ -908,7 +908,7 @@ def get_tag(self): author_email="ntamas@gmail.com", project_urls={ "Bug Tracker": "https://github.com/igraph/python-igraph/issues", - "Changelog": "https://github.com/igraph/python-igraph/blob/master/CHANGELOG.md", + "Changelog": "https://github.com/igraph/python-igraph/blob/main/CHANGELOG.md", "CI": "https://github.com/igraph/python-igraph/actions", "Documentation": "https://igraph.readthedocs.io", "Source Code": "https://github.com/igraph/python-igraph", From f3c1e117bf3790476cacd0dfcc5ceafe3ce21b50 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 26 Jan 2023 20:54:19 +0100 Subject: [PATCH 1203/1892] chore: bumped vendored igraph to 0.10.4 --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index ae908007e..c9426b5d9 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit ae908007efae21623c16ff752780a14a78aa149d +Subproject commit c9426b5d9fa841d93a311f46ddef9ed1d97576ac From 3047d7ddcf0e4a0dd3aa17ac2653ad7d5f01d0c0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Jan 2023 16:38:08 +0100 Subject: [PATCH 1204/1892] feat: added support for sources=... and targets=... for betweenness and edge betweenness --- CHANGELOG.md | 6 ++ src/_igraph/graphobject.c | 160 +++++++++++++++++++++++++++++++++----- tests/test_structural.py | 17 ++++ 3 files changed, 163 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dda8a4bb..15bc0d319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +### Added + +- Betweenness and edge betweenness scores can now be calculated for a subset of + the shortest paths originating from or terminating in a certain set of + vertices only. + ### Fixed - Fixed the drawing of `VertexDendrogram` instances, both in the Cairo and the diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 706741407..dac864739 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3870,28 +3870,46 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { static char *kwlist[] = { "vertices", "directed", "cutoff", "weights", - "nobigint", NULL }; + "sources", "targets", NULL }; PyObject *directed = Py_True; PyObject *vobj = Py_None, *list; PyObject *cutoff = Py_None; PyObject *weights_o = Py_None; - PyObject *nobigint = Py_True; + PyObject *sources_o = Py_None; + PyObject *targets_o = Py_None; igraph_vector_t res, *weights = 0; igraph_bool_t return_single = false; - igraph_vs_t vs; - - /* nobigint is now unused but we kept here for sake of backwards compatibility */ + igraph_bool_t is_subsetted = false; + igraph_vs_t vs, sources, targets; + igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO", kwlist, &vobj, &directed, &cutoff, &weights_o, - &nobigint)) { + &sources_o, &targets_o)) { return NULL; } if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; + if (igraphmodule_PyObject_to_vs_t(sources_o, &sources, &self->g, NULL, NULL)) { + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraphmodule_PyObject_to_vs_t(targets_o, &targets, &self->g, NULL, NULL)) { + igraph_vs_destroy(&sources); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + is_subsetted = !igraph_vs_is_all(&sources) || !igraph_vs_is_all(&targets); + if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } igraphmodule_handle_igraph_error(); return NULL; @@ -3899,13 +3917,25 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, if (igraph_vector_init(&res, 0)) { igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } return igraphmodule_handle_igraph_error(); } if (cutoff == Py_None) { - if (igraph_betweenness(&self->g, &res, vs, PyObject_IsTrue(directed), weights)) { + if (is_subsetted) { + retval = igraph_betweenness_subset( + &self->g, &res, vs, PyObject_IsTrue(directed), sources, targets, weights + ); + } else { + retval = igraph_betweenness(&self->g, &res, vs, PyObject_IsTrue(directed), weights); + } + + if (retval) { igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } igraphmodule_handle_igraph_error(); @@ -3915,13 +3945,29 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, PyObject *cutoff_num = PyNumber_Float(cutoff); if (cutoff_num == NULL) { igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; } + + if (is_subsetted) { + igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); + igraph_vector_destroy(&res); + if (weights) { igraph_vector_destroy(weights); free(weights); } + Py_DECREF(cutoff_num); + PyErr_SetString(PyExc_ValueError, "subsetting and cutoffs may not be used at the same time"); + return NULL; + } + if (igraph_betweenness_cutoff(&self->g, &res, vs, PyObject_IsTrue(directed), weights, PyFloat_AsDouble(cutoff_num))) { igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } Py_DECREF(cutoff_num); @@ -3932,6 +3978,8 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, } else { PyErr_SetString(PyExc_TypeError, "cutoff value must be None or integer"); igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } return NULL; @@ -3942,8 +3990,10 @@ PyObject *igraphmodule_Graph_betweenness(igraphmodule_GraphObject * self, else list = PyFloat_FromDouble(VECTOR(res)[0]); - igraph_vector_destroy(&res); igraph_vs_destroy(&vs); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); + igraph_vector_destroy(&res); if (weights) { igraph_vector_destroy(weights); free(weights); } return list; @@ -4819,39 +4869,92 @@ PyObject *igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "directed", "cutoff", "weights", NULL }; + static char *kwlist[] = { "directed", "cutoff", "weights", "sources", "targets", NULL }; igraph_vector_t res, *weights = 0; PyObject *list, *directed = Py_True, *cutoff = Py_None; PyObject *weights_o = Py_None; + PyObject *sources_o = Py_None; + PyObject *targets_o = Py_None; + igraph_vs_t sources; + igraph_vs_t targets; + igraph_error_t retval; + igraph_bool_t is_subsetted = false; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, - &directed, &cutoff, &weights_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, + &directed, &cutoff, &weights_o, &sources_o, &targets_o)) return NULL; if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; - igraph_vector_init(&res, igraph_ecount(&self->g)); + if (igraphmodule_PyObject_to_vs_t(sources_o, &sources, &self->g, NULL, NULL)) { + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraphmodule_PyObject_to_vs_t(targets_o, &targets, &self->g, NULL, NULL)) { + igraph_vs_destroy(&sources); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + is_subsetted = !igraph_vs_is_all(&sources) || !igraph_vs_is_all(&targets); + + if (igraph_vector_init(&res, igraph_ecount(&self->g))) { + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + } if (cutoff == Py_None) { - if (igraph_edge_betweenness(&self->g, &res, PyObject_IsTrue(directed), weights)) { - igraphmodule_handle_igraph_error(); + if (is_subsetted) { + retval = igraph_edge_betweenness_subset( + &self->g, &res, igraph_ess_all(IGRAPH_EDGEORDER_ID), + PyObject_IsTrue(directed), sources, targets, weights + ); + } else { + retval = igraph_edge_betweenness( + &self->g, &res, PyObject_IsTrue(directed), weights + ); + } + if (retval) { + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_vector_destroy(&res); + igraphmodule_handle_igraph_error(); return NULL; } } else if (PyNumber_Check(cutoff)) { PyObject *cutoff_num = PyNumber_Float(cutoff); if (!cutoff_num) { + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_vector_destroy(&res); return NULL; } + + if (is_subsetted) { + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraph_vector_destroy(&res); + Py_DECREF(cutoff_num); + PyErr_SetString(PyExc_ValueError, "subsetting and cutoffs may not be used at the same time"); + return NULL; + } + if (igraph_edge_betweenness_cutoff(&self->g, &res, PyObject_IsTrue(directed), weights, PyFloat_AsDouble(cutoff_num))) { - igraphmodule_handle_igraph_error(); igraph_vector_destroy(&res); + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } Py_DECREF(cutoff_num); + igraphmodule_handle_igraph_error(); return NULL; } Py_DECREF(cutoff_num); @@ -4861,10 +4964,13 @@ PyObject *igraphmodule_Graph_edge_betweenness(igraphmodule_GraphObject * self, return NULL; } + igraph_vs_destroy(&targets); + igraph_vs_destroy(&sources); if (weights) { igraph_vector_destroy(weights); free(weights); } list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); igraph_vector_destroy(&res); + return list; } @@ -13871,11 +13977,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@see: hub_score()\n" }, - /* interface to igraph_betweenness[_estimate] */ + /* interface to igraph_betweenness, igraph_betweenness_cutoff and igraph_betweenness_subset */ {"betweenness", (PyCFunction) igraphmodule_Graph_betweenness, METH_VARARGS | METH_KEYWORDS, - "betweenness(vertices=None, directed=True, cutoff=None, weights=None)\n--\n\n" + "betweenness(vertices=None, directed=True, cutoff=None, weights=None, sources=None, targets=None)\n--\n\n" "Calculates or estimates the betweenness of vertices in a graph.\n\n" + "Also supports calculating betweenness with shortest path length cutoffs or\n" + "considering shortest paths only from certain source vertices or to certain\n" + "target vertices.\n\n" "Keyword arguments:\n" "@param vertices: the vertices for which the betweennesses must be returned.\n" " If C{None}, assumes all of the vertices in the graph.\n" @@ -13886,6 +13995,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" + "@param sources: the set of source vertices to consider when calculating\n" + " shortest paths.\n" + "@param targets: the set of target vertices to consider when calculating\n" + " shortest paths.\n" "@return: the (possibly cutoff-limited) betweenness of the given vertices in a list\n"}, /* interface to biconnected_components */ @@ -14187,11 +14300,14 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: the calculated eccentricities in a list, or a single number if\n" " a single vertex was supplied.\n"}, - /* interface to igraph_edge_betweenness[_estimate] */ + /* interface to igraph_edge_betweenness, igraph_edge_betweenness_cutoff and igraph_edge_betweenness_subset */ {"edge_betweenness", (PyCFunction) igraphmodule_Graph_edge_betweenness, METH_VARARGS | METH_KEYWORDS, - "edge_betweenness(directed=True, cutoff=None, weights=None)\n--\n\n" + "edge_betweenness(directed=True, cutoff=None, weights=None, sources=None, targets=None)\n--\n\n" "Calculates or estimates the edge betweennesses in a graph.\n\n" + "Also supports calculating edge betweenness with shortest path length cutoffs or\n" + "considering shortest paths only from certain source vertices or to certain\n" + "target vertices.\n\n" "@param directed: whether to consider directed paths.\n" "@param cutoff: if it is an integer, only paths less than or equal to this\n" " length are considered, effectively resulting in an estimation of the\n" @@ -14199,6 +14315,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " returned.\n" "@param weights: edge weights to be used. Can be a sequence or iterable or\n" " even an edge attribute name.\n" + "@param sources: the set of source vertices to consider when calculating\n" + " shortest paths.\n" + "@param targets: the set of target vertices to consider when calculating\n" + " shortest paths.\n" "@return: a list with the (exact or estimated) edge betweennesses of all\n" " edges.\n"}, diff --git a/tests/test_structural.py b/tests/test_structural.py index b9b1d0b54..0e3fbab70 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -237,28 +237,45 @@ class CentralityTests(unittest.TestCase): def testBetweennessCentrality(self): g = Graph.Star(5) self.assertTrue(g.betweenness() == [6.0, 0.0, 0.0, 0.0, 0.0]) + g = Graph(5, [(0, 1), (0, 2), (0, 3), (1, 4)]) self.assertTrue(g.betweenness() == [5.0, 3.0, 0.0, 0.0, 0.0]) self.assertTrue(g.betweenness(cutoff=2) == [3.0, 1.0, 0.0, 0.0, 0.0]) self.assertTrue(g.betweenness(cutoff=1) == [0.0, 0.0, 0.0, 0.0, 0.0]) + g = Graph.Lattice([3, 3], circular=False) self.assertTrue( g.betweenness(cutoff=2) == [0.5, 2.0, 0.5, 2.0, 4.0, 2.0, 0.5, 2.0, 0.5] ) + observed = g.betweenness(sources=[0, 8], targets=[0, 8]) + self.assertEquals(len(observed), g.vcount()) + for x, y in zip(observed, [0, 1 / 2, 1 / 6, 1 / 2, 2 / 3, 1 / 2, 1 / 6, 1 / 2, 0]): + self.assertAlmostEquals(x, y) + self.assertRaises(ValueError, g.betweenness, cutoff=2, sources=[0, 8], targets=[0, 8]) + def testEdgeBetweennessCentrality(self): g = Graph.Star(5) self.assertTrue(g.edge_betweenness() == [4.0, 4.0, 4.0, 4.0]) + g = Graph(5, [(0, 1), (0, 2), (0, 3), (1, 4)]) self.assertTrue(g.edge_betweenness() == [6.0, 4.0, 4.0, 4.0]) self.assertTrue(g.edge_betweenness(cutoff=2) == [4.0, 3.0, 3.0, 2.0]) self.assertTrue(g.edge_betweenness(cutoff=1) == [1.0, 1.0, 1.0, 1.0]) + g = Graph.Ring(5) self.assertTrue(g.edge_betweenness() == [3.0, 3.0, 3.0, 3.0, 3.0]) self.assertTrue( g.edge_betweenness(weights=[4, 1, 1, 1, 1]) == [0.5, 3.5, 5.5, 5.5, 3.5] ) + g = Graph.Lattice([3, 3], circular=False) + observed = g.edge_betweenness(sources=[0, 8], targets=[0, 8]) + self.assertEquals(len(observed), g.ecount()) + for x, y in zip(observed, [1 / 2, 1 / 2, 1 / 6, 1 / 3, 1 / 6, 1 / 3, 1 / 6, 1 / 3, 1 / 3, 1 / 2, 1 / 6, 1 / 2]): + self.assertAlmostEquals(x, y) + self.assertRaises(ValueError, g.edge_betweenness, cutoff=2, sources=[0, 8], targets=[0, 8]) + def testClosenessCentrality(self): g = Graph.Star(5) cl = g.closeness() From 06d120aa2c4a7708cff79cd0d86d04e865f885a5 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Jan 2023 17:02:46 +0100 Subject: [PATCH 1205/1892] feat: added Graph.vertex_coloring_greedy() --- CHANGELOG.md | 3 +++ src/_igraph/convert.c | 13 ++++++++++ src/_igraph/convert.h | 1 + src/_igraph/graphobject.c | 51 +++++++++++++++++++++++++++++++++++++++ tests/test_coloring.py | 37 ++++++++++++++++++++++++++++ tests/test_structural.py | 4 +-- 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 tests/test_coloring.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 15bc0d319..5ac08cd3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Added +- Added `Graph.vertex_coloring_greedy()` to calculate a greedy vertex coloring + for the graph. + - Betweenness and edge betweenness scores can now be calculated for a subset of the shortest paths originating from or terminating in a certain set of vertices only. diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 1405e989d..466653296 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -513,6 +513,19 @@ int igraphmodule_PyObject_to_bliss_sh_t(PyObject *o, TRANSLATE_ENUM_WITH(bliss_sh_tt); } +/** + * \ingroup python_interface_conversion + * \brief Converts a Python object to an igraph \c igraph_coloring_greedy_t + */ +int igraphmodule_PyObject_to_coloring_greedy_t(PyObject *o, igraph_coloring_greedy_t *result) { + static igraphmodule_enum_translation_table_entry_t coloring_greedy_tt[] = { + {"colored_neighbors", IGRAPH_COLORING_GREEDY_COLORED_NEIGHBORS}, + {"dsatur", IGRAPH_COLORING_GREEDY_DSATUR}, + {0,0} + }; + TRANSLATE_ENUM_WITH(coloring_greedy_tt); +} + /** * \ingroup python_interface_conversion * \brief Converts a Python object to an igraph \c igraph_community_comparison_t diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index c4c895458..15bf4ead8 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -58,6 +58,7 @@ int igraphmodule_PyObject_to_attribute_combination_type_t(PyObject* o, int igraphmodule_PyObject_to_barabasi_algorithm_t(PyObject *o, igraph_barabasi_algorithm_t *result); int igraphmodule_PyObject_to_bliss_sh_t(PyObject *o, igraph_bliss_sh_t *result); +int igraphmodule_PyObject_to_coloring_greedy_t(PyObject *o, igraph_coloring_greedy_t *result); int igraphmodule_PyObject_to_community_comparison_t(PyObject *obj, igraph_community_comparison_t *result); int igraphmodule_PyObject_to_connectedness_t(PyObject *o, igraph_connectedness_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index dac864739..f35d3db96 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11637,6 +11637,43 @@ PyObject *igraphmodule_Graph_cohesive_blocks(igraphmodule_GraphObject *self, PyO return result_o; } +/********************************************************************** + * Coloring * + **********************************************************************/ + +PyObject *igraphmodule_Graph_vertex_coloring_greedy( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds +) { + static char *kwlist[] = { "method", NULL }; + igraph_vector_int_t result; + igraph_coloring_greedy_t heuristics; + PyObject *heuristics_o = Py_None; + PyObject *result_o; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &heuristics_o)) + return NULL; + + if (igraphmodule_PyObject_to_coloring_greedy_t(heuristics_o, &heuristics)) { + return NULL; + } + + if (igraph_vector_int_init(&result, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraph_vertex_coloring_greedy(&self->g, &result, heuristics)) { + igraph_vector_int_destroy(&result); + igraphmodule_handle_igraph_error(); + return NULL; + } + + result_o = igraphmodule_vector_int_t_to_PyList(&result); + igraph_vector_int_destroy(&result); + + return result_o; +} + /********************************************************************** * Cliques and independent sets * **********************************************************************/ @@ -16818,6 +16855,20 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "It is advised to use that.\n" }, + /************/ + /* COLORING */ + /************/ + {"vertex_coloring_greedy", (PyCFunction) igraphmodule_Graph_vertex_coloring_greedy, + METH_VARARGS | METH_KEYWORDS, + "vertex_coloring_greedy(method=\"colored_neighbors\")\n--\n\n" + "Calculates a greedy vertex coloring for the graph based on some heuristics.\n\n" + "@param method: the heuristics to use. C{colored_neighbors} always picks the\n" + " vertex with the largest number of colored neighbors as the next vertex to\n" + " pick a color for. C{dsatur} picks the vertex with the largest number of\n" + " I{unique} colors in its neighborhood; this is also known as the DSatur\n" + " heuristics (hence the name).\n" + }, + /********************************/ /* CLIQUES AND INDEPENDENT SETS */ /********************************/ diff --git a/tests/test_coloring.py b/tests/test_coloring.py new file mode 100644 index 000000000..a3791384d --- /dev/null +++ b/tests/test_coloring.py @@ -0,0 +1,37 @@ +import unittest +from igraph import Graph + + +def assert_valid_vertex_coloring(graph, coloring): + assert min(coloring) == 0 + for edge in graph.es: + source, target = edge.tuple + assert source == target or coloring[source] != coloring[target] + + +class VertexColoringTests(unittest.TestCase): + def testGreedyVertexColoring(self): + g = Graph.Famous("petersen") + + col = g.vertex_coloring_greedy() + assert_valid_vertex_coloring(g, col) + + col = g.vertex_coloring_greedy("colored_neighbors") + assert_valid_vertex_coloring(g, col) + + col = g.vertex_coloring_greedy("dsatur") + assert_valid_vertex_coloring(g, col) + + +def suite(): + vertex_coloring_suite = unittest.defaultTestLoader.loadTestsFromTestCase(VertexColoringTests) + return unittest.TestSuite([vertex_coloring_suite]) + + +def test(): + runner = unittest.TextTestRunner() + runner.run(suite()) + + +if __name__ == "__main__": + test() diff --git a/tests/test_structural.py b/tests/test_structural.py index 0e3fbab70..9ec5493ed 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -249,9 +249,9 @@ def testBetweennessCentrality(self): ) observed = g.betweenness(sources=[0, 8], targets=[0, 8]) - self.assertEquals(len(observed), g.vcount()) + self.assertEqual(len(observed), g.vcount()) for x, y in zip(observed, [0, 1 / 2, 1 / 6, 1 / 2, 2 / 3, 1 / 2, 1 / 6, 1 / 2, 0]): - self.assertAlmostEquals(x, y) + self.assertAlmostEqual(x, y) self.assertRaises(ValueError, g.betweenness, cutoff=2, sources=[0, 8], targets=[0, 8]) def testEdgeBetweennessCentrality(self): From c710884245bf38924138862ac6369849e08d581b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Jan 2023 17:09:53 +0100 Subject: [PATCH 1206/1892] fix: remove deprecated construct from a unit test --- tests/test_structural.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_structural.py b/tests/test_structural.py index 9ec5493ed..557398859 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -271,9 +271,9 @@ def testEdgeBetweennessCentrality(self): g = Graph.Lattice([3, 3], circular=False) observed = g.edge_betweenness(sources=[0, 8], targets=[0, 8]) - self.assertEquals(len(observed), g.ecount()) + self.assertEqual(len(observed), g.ecount()) for x, y in zip(observed, [1 / 2, 1 / 2, 1 / 6, 1 / 3, 1 / 6, 1 / 3, 1 / 6, 1 / 3, 1 / 3, 1 / 2, 1 / 6, 1 / 2]): - self.assertAlmostEquals(x, y) + self.assertAlmostEqual(x, y) self.assertRaises(ValueError, g.edge_betweenness, cutoff=2, sources=[0, 8], targets=[0, 8]) def testClosenessCentrality(self): From 580cf5dd0e9f2c403cd8622a95b7306ded2d539c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Jan 2023 17:13:48 +0100 Subject: [PATCH 1207/1892] chore: bumped version to 0.10.4 --- CHANGELOG.md | 5 +++-- src/igraph/version.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ac08cd3c..402ea417f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.4] - 2022-01-27 ### Added @@ -458,7 +458,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.3...main +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.4...main +[0.10.4]: https://github.com/igraph/python-igraph/compare/0.10.3...0.10.4 [0.10.3]: https://github.com/igraph/python-igraph/compare/0.10.2...0.10.3 [0.10.2]: https://github.com/igraph/python-igraph/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/igraph/python-igraph/compare/0.10.0...0.10.1 diff --git a/src/igraph/version.py b/src/igraph/version.py index 32f861113..b93074332 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 3) +__version_info__ = (0, 10, 4) __version__ = ".".join("{0}".format(x) for x in __version_info__) From b6ebd8eb277fc1d0e33340a6624629a10c638992 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 27 Jan 2023 17:38:05 +0100 Subject: [PATCH 1208/1892] fix: set up appropriate default for the vertex coloring heuristics --- src/_igraph/graphobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f35d3db96..7ba3e693f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -11646,7 +11646,7 @@ PyObject *igraphmodule_Graph_vertex_coloring_greedy( ) { static char *kwlist[] = { "method", NULL }; igraph_vector_int_t result; - igraph_coloring_greedy_t heuristics; + igraph_coloring_greedy_t heuristics = IGRAPH_COLORING_GREEDY_COLORED_NEIGHBORS; PyObject *heuristics_o = Py_None; PyObject *result_o; From 6a437c93d661a443081cdea0dfc24b645cddba9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Gr=C3=BCbel?= Date: Sun, 29 Jan 2023 22:33:29 +0100 Subject: [PATCH 1209/1892] split aarch64 build into manylinux and musllinux to prevent GHA timeout (#635) * split aarch64 build into manylinux and musllinux to prevent GHA timeout * temporarily disable condition on aarch84 builds to see whether the new configuration works * Revert "temporarily disable condition on aarch84 builds to see whether the new configuration works" This reverts commit d9ca8fc8f963091cbc5d2511a299b966b27304d5. --------- Co-authored-by: Tamas Nepusz --- .github/workflows/build.yml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d26d4f032..f5d6a795d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,8 +48,8 @@ jobs: with: path: ./wheelhouse/*.whl - build_wheel_linux_aarch64: - name: Build wheels on Linux (aarch64) + build_wheel_linux_aarch64_manylinux: + name: Build wheels on Linux (aarch64/manylinux) runs-on: ubuntu-20.04 if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') steps: @@ -69,6 +69,24 @@ jobs: CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" + - uses: actions/upload-artifact@v3 + with: + path: ./wheelhouse/*.whl + + build_wheel_linux_aarch64_musllinux: + name: Build wheels on Linux (aarch64/musllinux) + runs-on: ubuntu-20.04 + if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + steps: + - uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v2 + - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.12.0 env: From ddecc7c57b823d94538cfc860c19a03d02b36e04 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 31 Jan 2023 14:16:06 +0100 Subject: [PATCH 1210/1892] make things more generic by detecting Emscripten and not only pyodide --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index dd7721f49..6be61230b 100644 --- a/setup.py +++ b/setup.py @@ -59,9 +59,9 @@ def building_on_windows_msvc() -> bool: return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" -def building_to_wasm() -> bool: - """Returns True when building to WebAssembly""" - return "PYODIDE" in os.environ +def building_with_emscripten() -> bool: + """Returns True when building with Emscripten to WebAssembly""" + return (sysconfig.get_config_var("HOST_GNU_TYPE") or "").endswith("emscripten") def exclude_from_list(items: Iterable[T], items_to_exclude: Iterable[T]) -> List[T]: @@ -249,7 +249,7 @@ def _compile_in( args = [cmake] # Build to wasm requires invocation of the Emscripten SDK - if building_to_wasm(): + if building_with_emscripten(): emcmake = which("emcmake") if not emcmake: print( From 8b19ce1a670a5c82e5ddce5137be1f503a6dd35b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 31 Jan 2023 21:16:29 +0100 Subject: [PATCH 1211/1892] doc: do not use 'latest' or 'stable' as version numbers in readthedocs --- doc/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index bf3853af3..99028dfe7 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -42,7 +42,7 @@ def get_igraphdir(): def get_igraph_version(): '''Get igraph version''' - if rtd_version != '': + if rtd_version and rtd_version not in ('latest', 'stable'): return rtd_version version_file = get_igraphdir() / 'version.py' From dea8a394c9f866ca5d3a461b9caa6b350fb3dc6d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 31 Jan 2023 21:52:18 +0100 Subject: [PATCH 1212/1892] doc: use version number from READTHEDOCS_VERSION only for tags --- doc/source/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 99028dfe7..a31dba8b7 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -22,6 +22,7 @@ # Check if we are inside readthedocs, the conf is quite different there is_inside_rtd = os.getenv("READTHEDOCS", "") == "True" rtd_version = os.getenv("READTHEDOCS_VERSION", "") +rtd_version_type = os.getenv("READTHEDOCS_VERSION_TYPE", "unknown") if not is_inside_rtd: import sphinxbootstrap4theme @@ -42,7 +43,7 @@ def get_igraphdir(): def get_igraph_version(): '''Get igraph version''' - if rtd_version and rtd_version not in ('latest', 'stable'): + if rtd_version and rtd_version_type == "tag": return rtd_version version_file = get_igraphdir() / 'version.py' From 45b278c1543f9affef8a7dadf618b74005e997f6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Feb 2023 22:28:15 +0100 Subject: [PATCH 1213/1892] fix: remove defunct Graph.community_leading_eigenvector_naive() function, closes #637 --- CHANGELOG.md | 9 +++++++++ doc/source/analysis.rst | 1 - src/igraph/__init__.py | 3 --- src/igraph/community.py | 34 ---------------------------------- 4 files changed, 9 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 402ea417f..ae776db49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # igraph Python interface changelog +## [Unreleased] + +### Removed + +- Removed defunct `Graph.community_leading_eigenvector_naive()` method. Not a + breaking change because it was already removed from the C core a long time + ago so the function in the Python interface did not do anything useful + either. + ## [0.10.4] - 2022-01-27 ### Added diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index 1be2277df..aef415fcf 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -348,7 +348,6 @@ Clustering - :meth:`Graph.community_infomap` - :meth:`Graph.community_label_propagation` - :meth:`Graph.community_leading_eigenvector` -- :meth:`Graph.community_leading_eigenvector_naive` - :meth:`Graph.community_leiden` - :meth:`Graph.community_multilevel` (a version of Louvain) - :meth:`Graph.community_optimal_modularity` (exact solution, < 100 vertices) diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index a89be5af0..4e0136ba5 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -103,7 +103,6 @@ from igraph.community import ( _community_fastgreedy, _community_infomap, - _community_leading_eigenvector_naive, _community_leading_eigenvector, _community_label_propagation, _community_multilevel, @@ -653,7 +652,6 @@ def es(self): # Community detection/clustering community_fastgreedy = _community_fastgreedy community_infomap = _community_infomap - community_leading_eigenvector_naive = _community_leading_eigenvector_naive community_leading_eigenvector = _community_leading_eigenvector community_label_propagation = _community_label_propagation community_multilevel = _community_multilevel @@ -1071,7 +1069,6 @@ def write(graph, filename, *args, **kwds): _export_graph_to_tuple_list, _community_fastgreedy, _community_infomap, - _community_leading_eigenvector_naive, _community_leading_eigenvector, _community_label_propagation, _community_multilevel, diff --git a/src/igraph/community.py b/src/igraph/community.py index b2121177c..74a290a7a 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -64,40 +64,6 @@ def _community_infomap(graph, edge_weights=None, vertex_weights=None, trials=10) ) -def _community_leading_eigenvector_naive(graph, clusters=None, return_merges=False): - """Naive implementation of Newman's eigenvector community structure detection. - - This function splits the network into two components - according to the leading eigenvector of the modularity matrix and - then recursively takes the given number of steps by splitting the - communities as individual networks. This is not the correct way, - however, see the reference for explanation. Consider using the - correct L{Graph.community_leading_eigenvector} method instead. - - @param clusters: the desired number of communities. If C{None}, the - algorithm tries to do as many splits as possible. Note that the - algorithm won't split a community further if the signs of the leading - eigenvector are all the same, so the actual number of discovered - communities can be less than the desired one. - @param return_merges: whether the returned object should be a - dendrogram instead of a single clustering. - @return: an appropriate L{VertexClustering} or L{VertexDendrogram} - object. - - @newfield ref: Reference - @ref: MEJ Newman: Finding community structure in networks using the - eigenvectors of matrices, arXiv:physics/0605087""" - if clusters is None: - clusters = -1 - cl, merges, q = GraphBase.community_leading_eigenvector_naive( - graph, clusters, return_merges - ) - if merges is None: - return VertexClustering(graph, cl, modularity=q) - else: - return VertexDendrogram(graph, merges, safemax(cl) + 1) - - def _community_leading_eigenvector( graph, clusters=None, weights=None, arpack_options=None ): From ff16f5cf451379ea76e5b3a34b4aa99b130cf218 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 7 Feb 2023 22:33:10 +0100 Subject: [PATCH 1214/1892] doc: add more info about how to determine the matching revision of the C core, closes #636 --- doc/source/install.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 5b7b9dd3d..7eef1fa66 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -62,8 +62,14 @@ Compiling |igraph| from source You might want to compile |igraph| to test a recently added feature ahead of release or to install |igraph| on architectures not covered by our continuous development pipeline. -.. note:: In all cases, the Python interface needs to be compiled against a **matching** version of - the |igraph| core C library. +.. note:: In all cases, the Python interface needs to be compiled against + a **matching** version of the |igraph| core C library. If you used ``git`` + to check out the source tree, ``git`` was probably smart enough to check out + the matching version of igraph's C core as a submodule into + ``vendor/source/igraph``. You can use ``git submodule update --init + --recursive`` to check out the submodule manually, or you can run ``git + submodule status`` to print the exact revision of igraph's C core that + should be used with the Python interface. Compiling using pip ------------------- From 0b17fa405ff51b1e6b73168a316066109ba3305d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Mar 2023 10:19:02 +0100 Subject: [PATCH 1215/1892] fix: removed unused 'params' parameter from VertexDendrogram --- src/igraph/clustering.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index 47cb58f7d..c7270a52b 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -62,7 +62,8 @@ def __init__(self, membership, params=None): @param membership: the membership list -- that is, the cluster index in which each element of the set belongs to. @param params: additional parameters to be stored in this - object's dictionary.""" + object's dictionary. + """ self._membership = list(membership) if len(self._membership) > 0: self._len = max(m for m in self._membership if m is not None) + 1 @@ -788,7 +789,7 @@ class VertexDendrogram(Dendrogram): vertex set of a graph.""" def __init__( - self, graph, merges, optimal_count=None, params=None, modularity_params=None + self, graph, merges, optimal_count=None, modularity_params=None ): """Creates a dendrogram object for a given graph. @@ -799,7 +800,6 @@ def __init__( clustering algorithm that produces the dendrogram. C{None} means that such a hint is not available; the optimal count will then be selected based on the modularity in such a case. - @param params: additional parameters to be stored in this object. @param modularity_params: arguments that should be passed to L{Graph.modularity} when the modularity is (re)calculated. If the original graph was weighted, you should pass a dictionary From 423b3217d3dac5d37260debd309a42ff3c2009fc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Mar 2023 10:35:27 +0100 Subject: [PATCH 1216/1892] fix: fix forwarding of resolution parameter to the low-level modularity() method from the Graph class, closes #640 --- src/igraph/community.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/igraph/community.py b/src/igraph/community.py index 74a290a7a..834744707 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -403,7 +403,7 @@ def _community_leiden( Model (CPM) or modularity. Must be either C{"CPM"} or C{"modularity"}. @param weights: edge weights to be used. Can be a sequence or iterable or even an edge attribute name. - @param resolution: the resolution parameter to use. Higher resolutions + @param resolution: the resolution parameter to use. Higher resolutions lead to more smaller communities, while lower resolutions lead to fewer larger communities. @param beta: parameter affecting the randomness in the Leiden @@ -431,7 +431,10 @@ def _community_leiden( raise ValueError('objective_function must be "CPM" or "modularity".') if "resolution_parameter" in kwds: - deprecated("resolution_parameter keyword argument is deprecated, use resolution=... instead") + deprecated( + "resolution_parameter keyword argument is deprecated, use " + "resolution=... instead" + ) resolution = kwds.pop("resolution_parameter") if kwds: @@ -448,10 +451,10 @@ def _community_leiden( n_iterations=n_iterations, ) + modularity_params = {"resolution": resolution} if weights is not None: - modularity_params = dict(weights=weights) - else: - modularity_params = {} + modularity_params["weights"] = weights + return VertexClustering(graph, membership, modularity_params=modularity_params) @@ -494,9 +497,11 @@ def _modularity(self, membership, weights=None, resolution=1, directed=True): if isinstance(membership, VertexClustering): if membership.graph != self: raise ValueError("clustering object belongs to another graph") - return GraphBase.modularity(self, membership.membership, weights) + return GraphBase.modularity( + self, membership.membership, weights, resolution, directed + ) else: - return GraphBase.modularity(self, membership, weights) + return GraphBase.modularity(self, membership, weights, resolution, directed) def _optimal_cluster_count_from_merges_and_modularity( From 18a903e17cf47bdcb45bd003afccd677eba47e65 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Mar 2023 14:25:22 +0100 Subject: [PATCH 1217/1892] feat: VertexClustering returned from Graph.community_leiden() now stores the value of the quality function --- src/_igraph/graphobject.c | 2 +- src/igraph/community.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 7ba3e693f..69f544187 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -12784,7 +12784,7 @@ PyObject *igraphmodule_Graph_community_leiden(igraphmodule_GraphObject *self, free(membership); } - return error ? NULL : res; + return error ? NULL : Py_BuildValue("Nd", res, (double) quality); } /********************************************************************** diff --git a/src/igraph/community.py b/src/igraph/community.py index 834744707..61af2a3b1 100644 --- a/src/igraph/community.py +++ b/src/igraph/community.py @@ -420,7 +420,9 @@ def _community_leiden( If this is not provided, it will be automatically determined on the basis of whether you want to use CPM or modularity. If you do provide this, please make sure that you understand what you are doing. - @return: an appropriate L{VertexClustering} object. + @return: an appropriate L{VertexClustering} object with an extra attribute + called C{quality} that stores the value of the internal quality function + optimized by the algorithm. @newfield ref: Reference @ref: Traag, V. A., Waltman, L., & van Eck, N. J. (2019). From Louvain @@ -440,7 +442,7 @@ def _community_leiden( if kwds: raise TypeError('unexpected keyword argument') - membership = GraphBase.community_leiden( + membership, quality = GraphBase.community_leiden( graph, edge_weights=weights, node_weights=node_weights, @@ -451,11 +453,15 @@ def _community_leiden( n_iterations=n_iterations, ) + params = {"quality": quality} + modularity_params = {"resolution": resolution} if weights is not None: modularity_params["weights"] = weights - return VertexClustering(graph, membership, modularity_params=modularity_params) + return VertexClustering( + graph, membership, params=params, modularity_params=modularity_params + ) def _modularity(self, membership, weights=None, resolution=1, directed=True): From 02f37ab55310dff5826980d4726b0b535957644d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 3 Mar 2023 14:27:01 +0100 Subject: [PATCH 1218/1892] chore: updated changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae776db49..65fa445a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## [Unreleased] +### Added + +- The `VertexClustering` object returned from `Graph.community_leiden()` now + contains an extra property named `quality` that stores the value of the + internal quality function optimized by the algorithm. + +### Fixed + +- `resolution` parameter is now correctly taken into account when calling + `Graph.modularity()` + ### Removed - Removed defunct `Graph.community_leading_eigenvector_naive()` method. Not a From 61111f229dedc131b9a1b5f014b4bbcb884b20fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Sun, 5 Mar 2023 14:05:28 +0100 Subject: [PATCH 1219/1892] chore: update vendored igraph --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index c9426b5d9..df540582b 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit c9426b5d9fa841d93a311f46ddef9ed1d97576ac +Subproject commit df540582b4c2b267e573fc42d7ca654573960072 From bdada6f6c3bbeb170cd56b4ed8c23332433710f4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 10 Mar 2023 18:03:18 +0100 Subject: [PATCH 1220/1892] chore: updated C core --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index df540582b..47c76b691 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit df540582b4c2b267e573fc42d7ca654573960072 +Subproject commit 47c76b691c8158daea48648f3d47129e682d4651 From be0d890307c5e52d971a094e895d599716dca2e9 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 13 Mar 2023 19:40:15 +1100 Subject: [PATCH 1221/1892] Add Spanish tutorial by @adriandiazlab (#642) * Add Spanish tutorial by @adriandiazlab * fix: let's try with all-lowercase filenames * A few corrections in style and language --------- Co-authored-by: Tamas Nepusz --- doc/source/index.rst | 3 +- doc/source/tutorial.es.rst | 815 +++++++++++++++++++++++++++++++++++++ 2 files changed, 817 insertions(+), 1 deletion(-) create mode 100644 doc/source/tutorial.es.rst diff --git a/doc/source/index.rst b/doc/source/index.rst index 040b4c5c5..aca648dfb 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -67,7 +67,7 @@ Documentation - :doc:`Quick start ` - :doc:`Gallery of examples ` - - :doc:`Extended tutorial ` + - :doc:`Extended tutorial ` (:doc:`Español `) .. container:: @@ -103,6 +103,7 @@ Documentation for `python-igraph <= 0.10.1` is available on our `old website `_, o un `IDE `_):: + + $ python + Python 3.9.6 (default, Jun 29 2021, 05:25:02) + [Clang 12.0.5 (clang-1205.0.22.9)] on darwin + Type "help", "copyright", "credits" or "license" for more information. + >>> import igraph as ig + +Para llamar a funciones, es necesario anteponerles el prefijo ``ig`` (o el nombre que hayas elegido):: + + >>> import igraph as ig + >>> print(ig.__version__) + 0.9.8 + +.. note:: + Es posible utilizar *importación con asterisco* para |igraph|:: + + >>> from igraph import * + + pero en general se desaconseja `_. + +Hay una segunda forma de iniciar |igraph|, que consiste en llamar al script :command:`igraph` desde tu terminal:: + + $ igraph + No configuration file, using defaults + igraph 0.9.6 running inside Python 3.9.6 (default, Jun 29 2021, 05:25:02) + Type "copyright", "credits" or "license" for more information. + >>> + +.. note:: + Para los usuarios de Windows encontrarán el script dentro del subdirectorio file:`scripts` + de Python y puede que tengan que añadirlo manualmente a su ruta. + +Este script inicia un intérprete de comandos apropiado (`IPython`_ o `IDLE `_ si se encuentra, de lo contrario un intérprete de comandos Python puro) y utiliza *importación con asterisco* (véase más arriba). Esto es a veces conveniente para usar las funciones de |igraph|. + +.. note:: + Puede especificar qué shell debe utilizar este script a través + :doc:`configuration` de |igraph|. + +Este tutorial asumirá que has importado igraph usando el de nombres ``ig``. + +Creando un grafo +================ + +La forma más sencilla de crear un grafo es con el constructor :class:`Graph`. Para hacer un grafo vacío: + + >>> g = ig.Graph() + +Para hacer un grafo con 10 nodos (numerados ``0`` to ``9``) y dos aristas que conecten los nodos ``0-1`` y ``0-5``:: + + >>> g = ig.Graph(n=10, edges=[[0, 1], [0, 5]]) + +Podemos imprimir el grafo para obtener un resumen de sus nodos y aristas:: + + >>> print(g) + IGRAPH U--- 10 2 -- + + edges: + 0--1 0--5 + +Tenemos entonces: grafo no dirigido (**U**ndirected) con **10** vértices y **2** aristas, que se enlistan en la última parte. Si el grafo tiene un atributo "nombre", también se imprime. + +.. note:: + ``summary`` es similar a ``print`` pero no enlista las aristas, lo cual + es conveniente para grafos grandes con millones de aristas:: + + >>> summary(g) + IGRAPH U--- 10 2 -- + +Añadir y borrar vértices y aristas +================================== + +Empecemos de nuevo con un grafo vacío. Para añadir vértices a un grafo existente, utiliza :meth:`Graph.add_vertices`:: + + >>> g = ig.Graph() + >>> g.add_vertices(3) + +En |igraph|, los vértices se numeran siempre a partir de cero El número de un vértice es el *ID del vértice*. Un vértice puede tener o no un nombre. + +Del mismo modo, para añadir aristas se utiliza :meth:`Graph.add_edges`:: + + >>> g.add_edges([(0, 1), (1, 2)]) + +Las aristas se añaden especificando el vértice origen y el vértice destino de cada arista. Esta llamada añade dos aristas, una que conecta los vértices ``0`` y ``1``, y otra que conecta los vértices ``1`` y ``2``. Las aristas también se numeran a partir de cero (el *ID del arista*) y tienen un nombre opcional. + +.. warning:: + + Crear un grafo vacío y añadir vértices y aristas como se muestra aquí puede ser mucho más lento que crear un grafo con sus vértices y aristas como se ha demostrado anteriormente. Si la velocidad es una preocupación, deberías evitar especialmente añadir vértices y aristas *de uno en uno*. Si necesitas hacerlo de todos modos, puedes usar :meth:`Graph.add_vertex` y :meth:`Graph.add_edge`. + +Si intentas añadir aristas a vértices con IDs no válidos (por ejemplo, intentas añadir una arista al vértice ``5`` cuando el grafo sólo tiene tres vértices), obtienes un error :exc:`igraph.InternalError`:: + + >>> g.add_edges([(5, 4)]) + Traceback (most recent call last): + File "", line 1, in + File "/usr/lib/python3.10/site-packages/igraph/__init__.py", line 376, in add_edges + res = GraphBase.add_edges(self, es) + igraph._igraph.InternalError: Error at src/graph/type_indexededgelist.c:270: cannot add edges. -- Invalid vertex id + +El mensaje intenta explicar qué ha fallado (``cannot add edges. -- Invalid +vertex id``) junto con la línea correspondiente del código fuente en la que se ha producido el error. + +.. note:: + El rastreo completo, incluida la información sobre el código fuente, es útil cuando + se informa de errores en nuestro + `Página de problemas de GitHub `_. Por favor, inclúyalo + completo si crea un nuevo asunto. + +Añadamos más vértices y aristas a nuestro grafo:: + + >>> g.add_edges([(2, 0)]) + >>> g.add_vertices(3) + >>> g.add_edges([(2, 3), (3, 4), (4, 5), (5, 3)]) + >>> print(g) + IGRAPH U---- 6 7 -- + + edges: + 0--1 1--2 0--2 2--3 3--4 4--5 3--5 + +Ahora tenemos un grafo no dirigido con 6 vértices y 7 aristas. Los IDs de los vértices y aristas son siempre *continuos*, por lo que si eliminas un vértice todos los vértices subsiguientes serán renumerados. Cuando se renumera un vértice, las aristas **no** se renumeran, pero sí sus vértices de origen y destino. Utilice :meth:`Graph.delete_vertices` y :meth:`Graph.delete_edges` para realizar estas operaciones. Por ejemplo, para eliminar la arista que conecta los vértices ``2-3``, obten sus IDs y luego eliminalos:: + + >>> g.get_eid(2, 3) + 3 + >>> g.delete_edges(3) + +Generar grafos +============== + +|igraph| incluye generadores de grafos tanto deterministas como estocásticos. Los generadores *deterministas* producen el mismo grafo cada vez que se llama a la función, por ejemplo:: + + >>> g = ig.Graph.Tree(127, 2) + >>> summary(g) + IGRAPH U--- 127 126 -- + +Utiliza :meth:`Graph.Tree` para generar un grafo regular en forma de árbol con 127 vértices, cada vértice con dos hijos (y un padre, por supuesto). No importa cuántas veces llames a :meth:`Graph.Tree`, el grafo generado será siempre el mismo si utilizas los mismos parámetros:: + + >>> g2 = ig.Graph.Tree(127, 2) + >>> g2.get_edgelist() == g.get_edgelist() + True + +El fragmento de código anterior también muestra el método :meth:`~Graph.get_edgelist()`, que devuelve una lista de vértices de origen y destino para todas las aristas, ordenados por el ID de la arista. Si imprimes los 10 primeros elementos, obtienes:: + + >>> g2.get_edgelist()[:10] + [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6), (3, 7), (3, 8), (4, 9), (4, 10)] + +Los generadores *estocásticos* producen un grafo diferente cada vez; por ejemplo, :meth:`Graph.GRG`:: + + >>> g = ig.Graph.GRG(100, 0.2) + >>> summary(g) + IGRAPH U---- 100 516 -- + + attr: x (v), y (v) + +.. note:: + `+ attr`` muestra atributos para vértices (v) y aristas (e), en este caso dos atributos de + vértice y ningún atributo de arista. + +Esto genera un grafo geométrico aleatorio: Se eligen *n* puntos de forma aleatoria y uniforme dentro del cuadrado unitario y los pares de puntos más cercanos entre sí respecto a una distancia predefinida *d* se conectan mediante una arista. Si se generan GRGs con los mismos parámetros, serán diferentes:: + + >>> g2 = ig.Graph.GRG(100, 0.2) + >>> g.get_edgelist() == g2.get_edgelist() + False + +Una forma un poco más relajada de comprobar si los grafos son equivalentes es mediante :meth:`~Graph.isomorphic()`:: + + >>> g.isomorphic(g2) + False + +Comprobar por el isomorfismo puede llevar un tiempo en el caso de grafos grandes (en este caso, la respuesta puede darse rápidamente comprobando las distribuciones de grados de los dos grafos). + +Establecer y recuperar atributos +================================ + +Como se ha mencionado anteriormente, en |igraph| cada vértice y cada arista tienen un ID numérico de ``0`` en adelante. Por lo tanto, la eliminación de vértices o aristas puede causar la reasignación de los ID de vértices y/o aristas. Además de los IDs, los vértices y aristas pueden tener *atributos* como un nombre, coordenadas para graficar, metadatos y pesos. El propio grafo puede tener estos atributos también (por ejemplo, un nombre, que se mostrará en ``print`` o :meth:`Graph.summary`). En cierto sentido, cada :class:`Graph`, vértice y arista pueden utilizarse como un diccionario de Python para almacenar y recuperar estos atributos. + +Para demostrar el uso de los atributos, creemos una red social sencilla:: + + >>> g = ig.Graph([(0,1), (0,2), (2,3), (3,4), (4,2), (2,5), (5,0), (6,3), (5,6)]) + +Cada vértice representa una persona, por lo que queremos almacenar nombres, edades y géneros:: + + >>> g.vs["name"] = ["Alice", "Bob", "Claire", "Dennis", "Esther", "Frank", "George"] + >>> g.vs["age"] = [25, 31, 18, 47, 22, 23, 50] + >>> g.vs["gender"] = ["f", "m", "f", "m", "f", "m", "m"] + >>> g.es["is_formal"] = [False, False, True, True, True, False, True, False, False] + +:attr:`Graph.vs` y :attr:`Graph.es` son la forma estándar de obtener una secuencia de todos los vértices y aristas respectivamente. El valor debe ser una lista con la misma longitud que los vértices (para :attr:`Graph.vs`) o aristas (para :attr:`Graph.es`). Esto asigna un atributo a *todos* los vértices/aristas a la vez. + +Para asignar o modificar un atributo para un solo vértice/borde, puedes hacer lo siguiente:: + + >>> g.es[0]["is_formal"] = True + +De hecho, un solo vértice se representa mediante la clase :class:`Vertex`, y una sola arista mediante :class:`Edge`. Ambos, junto con :class:`Graph`, pueden ser tecleados como un diccionario para establecer atributos, por ejemplo, para añadir una fecha al grafo:: + + >>> g["date"] = "2009-01-10" + >>> print(g["date"]) + 2009-01-10 + +Para recuperar un diccionario de atributos, puedes utilizar :meth:`Graph.attributes`, :meth:`Vertex.attributes` y :meth:`Edge.attributes`. + +Además, cada :class:`Vertex` tiene una propiedad especial, :attr:`Vertex.index`, que se utiliza para averiguar el ID de un vértice. Cada :class:`Edge` tiene :attr:`Edge.index` más dos propiedades adicionales, :attr:`Edge.source` y :attr:`Edge.target`, que se utilizan para encontrar los IDs de los vértices conectados por esta arista. Para obtener ambas propiedades a la vez, puedes utilizar :attr:`Edge.tuple`. + +Para asignar atributos a un subconjunto de vértices o aristas, puedes utilizar el corte:: + + >>> g.es[:1]["is_formal"] = True + +La salida de ``g.es[:1]`` es una instancia de :class:`~seq.EdgeSeq`, mientras que :class:`~seq.VertexSeq` es la clase equivalente que representa subconjuntos de vértices. + +Para eliminar atributos, puedes utilizar ``del``, por ejemplo:: + + >>> g.vs[3]["foo"] = "bar" + >>> g.vs["foo"] + [None, None, None, 'bar', None, None, None] + >>> del g.vs["foo"] + >>> g.vs["foo"] + Traceback (most recent call last): + File "", line 25, in + KeyError: 'Attribute does not exist' + +.. warning:: + Los atributos pueden ser objetos arbitrarios de Python, pero si está guardando grafos en un + archivo, sólo se conservarán los atributos de cadena ("string") y numéricos. Consulte el + módulo :mod:`pickle` de la biblioteca estándar de Python si busca una forma de guardar otros + tipos de atributos. Puede hacer un pickle de sus atributos individualmente, almacenarlos como + cadenas y guardarlos, o puedes hacer un pickle de todo el :class:`Graph` si sabes que quieres + cargar el grafo en Python. + + +Propiedades estructurales de los grafos +======================================= + +Además de las funciones simples de manipulación de grafos y atributos descritas anteriormente, |igraph| proporciona un amplio conjunto de métodos para calcular varias propiedades estructurales de los grafos. Está más allá del alcance de este tutorial documentar todos ellos, por lo que esta sección sólo presentará algunos de ellos con fines ilustrativos. Trabajaremos con la pequeña red social que construimos en la sección anterior. + +Probablemente, la propiedad más sencilla en la que se puede pensar es el "grado del vértice" (:dfn:`vertex degree`). El grado de un vértice es igual al número de aristas incidentes a él. En el caso de los grafos dirigidos, también podemos definir el ``grado de entrada`` (:dfn:`in-degree`, el número de aristas que apuntan hacia el vértice) y el ``grado de salida`` (:dfn:`out-degree`, el número de aristas que se originan en el vértice):: + + >>> g.degree() + [3, 1, 4, 3, 2, 3, 2] + +Si el grafo fuera dirigido, habríamos podido calcular los grados de entrada y salida por separado utilizando ``g.degree(mode="in")`` y ``g.degree(mode="out")``. También puedes usar un único ID de un vértice o una lista de ID de los vértices a :meth:`~Graph.degree` si quieres calcular los grados sólo para un subconjunto de vértices:: + + >>> g.degree(6) + 2 + >>> g.degree([2,3,4]) + [4, 3, 2] + +Este procedimiento se aplica a la mayoría de las propiedades estructurales que |igraph| puede calcular. Para las propiedades de los vértices, los métodos aceptan un ID o una lista de IDs de los vértices (y si se omiten, el valor predeterminado es el conjunto de todos los vértices). Para las propiedades de las aristas, los métodos también aceptan un único ID de o una lista de IDs de aristas. En lugar de una lista de IDs, también puedes proporcionar una instancia :class:`VertexSeq` o una instancia :class:`EdgeSeq` apropiadamente. Más adelante, en el próximo capítulo "consulta de vértices y aristas", aprenderás a restringirlos exactamente a los vértices o aristas que quieras. + +.. note:: + + Para algunos casos, no tiene sentido realizar el calculo sólo para unos pocos vértices o + aristas en lugar de todo el grafo, ya que de todas formas se tardaría el mismo tiempo. En + este caso, los métodos no aceptan IDs de vértices o aristas, pero se puede restringir la + lista resultante más tarde usando operadores estándar de indexación y de corte. Un ejemplo de + ello es la centralidad de los vectores propios (:meth:`Graph.evcent()`) + +Además de los grados, |igraph| incluye rutinas integradas para calcular muchas otras propiedades de centralidad, como la intermediación de vértices y aristas o el PageRank de Google (:meth:`Graph.pagerank`), por nombrar algunas. Aquí sólo ilustramos la interrelación de aristas:: + + >>> g.edge_betweenness() + [6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] + +Ahora también podemos averiguar qué conexiones tienen la mayor centralidad de intermediación +con un poco de magia de Python:: + + >>> ebs = g.edge_betweenness() + >>> max_eb = max(ebs) + >>> [g.es[idx].tuple for idx, eb in enumerate(ebs) if eb == max_eb] + [(0, 1), (0, 2)] + +La mayoría de las propiedades estructurales también pueden ser obtenidas para un subconjunto de vértices o aristas o para un solo vértice o arista llamando al método apropiado de la clase :class:`VertexSeq` o :class:`EdgeSeq` de interés:: + + >>> g.vs.degree() + [3, 1, 4, 3, 2, 3, 2] + >>> g.es.edge_betweenness() + [6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0. 4.0] + >>> g.vs[2].degree() + 4 + +Busqueda de vértices y aristas basada en atributos +================================================== + +Selección de vértices y aristas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Tomando como ejemplo la red social anterirormente creada, te gustaría averiguar quién tiene el mayor grado o centralidad de intermediación. Puedes hacerlo con las herramientas presentadas hasta ahora y conocimientos básicos de Python, pero como es una tarea común seleccionar vértices y aristas basándose en atributos o propiedades estructurales, |igraph| te ofrece una forma más fácil de hacerlo:: + + >>> g.vs.select(_degree=g.maxdegree())["name"] + ['Claire'] + +La sintaxis puede parecer un poco rara a primera vista, así que vamos a tratar de interpretarla paso a paso. meth:`~VertexSeq.select` es un método de :class:`VertexSeq` y su único propósito es filtrar un :class:`VertexSeq` basándose en las propiedades de los vértices individuales. La forma en que filtra los vértices depende de sus argumentos posicionales y de palabras clave. Los argumentos posicionales (los que no tienen un nombre explícito como ``_degree`` siempre se procesan antes que los argumentos de palabra clave de la siguiente manera: + +- Si el primer argumento posicional es ``None``, se devuelve una secuencia vacía (que no contiene vértices):: + + >>> seq = g.vs.select(None) + >>> len(seq) + 0 + +- Si el primer argumento posicional es un objeto invocable (es decir, una función, un método vinculado o cualquier cosa que se comporte como una función), el objeto será llamado para cada vértice que esté actualmente en la secuencia. Si la función devuelve ``True``, el vértice será incluido, en caso contrario será excluido:: + + >>> graph = ig.Graph.Full(10) + >>> only_odd_vertices = graph.vs.select(lambda vertex: vertex.index % 2 == 1) + >>> len(only_odd_vertices) + 5 + +- Si el primer argumento posicional es un iterable (es decir, una lista, un generador o cualquier cosa sobre la que se pueda iterar), *debe* devolver enteros y estos enteros se considerarán como índices del conjunto de vértices actual (que *no* es necesariamente todo el grafo). Sólo se incluirán en el conjunto de vértices filtrados los vértices que coincidan con los índices dados. Los numero flotantes, las cadenas y los ID de vértices no válidos seran omitidos:: + + >>> seq = graph.vs.select([2, 3, 7]) + >>> len(seq) + 3 + >>> [v.index for v in seq] + [2, 3, 7] + >>> seq = seq.select([0, 2]) # filtering an existing vertex set + >>> [v.index for v in seq] + [2, 7] + >>> seq = graph.vs.select([2, 3, 7, "foo", 3.5]) + >>> len(seq) + 3 + +- Si el primer argumento posicional es un número entero, se espera que todos los demás argumentos sean también números enteros y se interpretan como índices del conjunto de vértices actual. Esto solo es "azucar sintáctica", se podría conseguir un efecto equivalente pasando una lista como primer argumento posicional, de esta forma se pueden omitir los corchetes:: + + >>> seq = graph.vs.select(2, 3, 7) + >>> len(seq) + 3 + +Los argumentos clave ("keyword argument") pueden utilizarse para filtrar los vértices en función de sus atributos o sus propiedades estructurales. El nombre de cada argumento clave consiste como máximo de dos partes: el nombre del atributo o propiedad estructural y el operador de filtrado. El operador puede omitirse; en ese caso, automáticamente se asume el operador de igualdad. Las posibilidades son las siguientes (donde *name* indica el nombre del atributo o propiedad): + +================ ================================================================ +Keyword argument Significado +================ ================================================================ +``name_eq`` El valor del atributo/propiedad debe ser *igual* a +---------------- ---------------------------------------------------------------- +``name_ne`` El valor del atributo/propiedad debe *no ser igual* a +---------------- ---------------------------------------------------------------- +``name_lt`` El valor del atributo/propiedad debe ser *menos* que +---------------- ---------------------------------------------------------------- +``name_le`` El valor del atributo/propiedad debe ser *inferior o igual a* +---------------- ---------------------------------------------------------------- +``name_gt`` El valor del atributo/propiedad debe ser *mayor que* +---------------- ---------------------------------------------------------------- +``name_ge`` El valor del atributo/propiedad debe ser *mayor o igual a* +---------------- ---------------------------------------------------------------- +``name_in`` El valor del atributo/propiedad debe estar *incluido en*, el cual tiene que ser + una secuencia en este caso +---------------- ---------------------------------------------------------------- +``name_notin`` El valor del atributo/propiedad debe *no estar incluido en* , + el cual tiene que ser una secuencia en este caso +================ ================================================================ + +Por ejemplo, el siguiente comando te da las personas menores de 30 años en nuestra red social imaginaria:: + + >>> g.vs.select(age_lt=30) + +.. note:: + Debido a las restricciones sintácticas de Python, no se puede utilizar la sintaxis más + sencilla de ``g.vs.select(edad < 30)``, ya que en Python sólo se permite que aparezca el + operador de igualdad en una lista de argumentos. + +Para ahorrarte algo de tecleo, puedes incluso omitir el método :meth:`~VertexSeq.select` si +desea:: + + >>> g.vs(age_lt=30) + +También hay algunas propiedades estructurales especiales para seleccionar los aristas: + +- Utilizando ``_source`` or ``_from`` en función de los vértices de donde se originan las aristas. Por ejemplo, para seleccionar todas las aristas procedentes de Claire (que tiene el índice de vértice 2):: + + >>> g.es.select(_source=2) + +- Usar los filtros ``_target`` o ``_to`` en base a los vértices de destino. Esto es diferente de ``_source`` and ``_from`` si el grafo es dirigido. + +- ``_within`` toma un objeto :class:`VertexSeq` o un set de vértices y selecciona todos los aristas que se originan y terminan en un determinado set de vértices. Por ejemplo, la siguiente expresión selecciona todos los aristas entre Claire (índice 2), Dennis (índice 3) y Esther (índice 4):: + + >>> g.es.select(_within=[2,3,4]) + +- ``_between`` toma una tupla que consiste en dos objetos :class:`VertexSeq` o una listas que contienen los indices de los vértices o un objeto :class:`Vertex` y selecciona todas las aristas que se originan en uno de los conjuntos y terminan en el otro. Por ejemplo, para seleccionar todas las aristas que conectan a los hombres con las mujeres:: + + >>> men = g.vs.select(gender="m") + >>> women = g.vs.select(gender="f") + >>> g.es.select(_between=(men, women)) + +Encontrar un solo vértice o arista con algunas propiedades +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +En muchos casos buscamos un solo vértice o arista de un grafo con algunas propiedades, sin importar cuál de las coincidencias se devuelve, ya sea si éxiste mútliples coincidencias, o bien sabemos de antemano que sólo habrá una coincidencia. Un ejemplo típico es buscar vértices por su nombre en la propiedad ``name``. Los objetos :class:`VertexSeq` y :class:`EdgeSeq` proveen el método :meth:`~VertexSeq.find` para esos casos. Esté método funciona de manera similar a :meth:`~VertexSeq.select`, pero devuelve solo la primer coincidencia si hay multiples resultados, y señala una excepción si no se encuentra ninguna coincidencia. Por ejemplo, para buscar el vértice correspondiente a Claire, se puede hacer lo siguiente:: + + >>> claire = g.vs.find(name="Claire") + >>> type(claire) + igraph.Vertex + >>> claire.index + 2 + +La búsqueda de un nombre desconocido dará lugar a una excepción:: + + >>> g.vs.find(name="Joe") + Traceback (most recent call last): + File "", line 1, in + ValueError: no such vertex + +Búsqueda de vértices por nombres +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Buscar vértices por su nombre es una operación muy común, y normalmente es mucho más fácil recordar los nombres de los vértices de un grafo que sus IDs. Para ello, |igraph| trata el atributo ``name`` de los vértices de forma especial; se indexan de forma que los vértices se pueden buscar por sus nombre. Para hacer las cosas incluso más fácil, |igraph| acepta nombres de vértices (casi) en cualquier lugar dónde se espere especificar un ID de un vérice, e incluso, acepta colecciones (tuplas,listas,etc.) de nombres de vértices dónde sea que se esperé una lista de IDs de vértices. Por ejemplo, puedes buscar el grado (número de conexiones) de Dennis de la siguiente manera:: + + >>> g.degree("Dennis") + 3 + +o alternativamente:: + + >>> g.vs.find("Dennis").degree() + 3 + +El mapeo entre los nombres de los vértices y los IDs es mantenido de forma transparente por |igraph| en segundo plano; cada vez que el grafo cambia, |igraph| también actualiza el mapeo interno. Sin embargo, la singularidad de los nombres de los vértices *no* se impone; puedes crear fácilmente un grafo en el que dos vértices tengan el mismo nombre, pero igraph sólo devolverá uno de ellos cuando los busques por nombres, el otro sólo estará disponible por su índice. + +Tratar un grafo como una matriz de adyacencia +============================================= + +La matriz de adyacencia es otra forma de formar un grafo. En la matriz de adyacencia, las filas y columnas están etiquetadas por los vértices del grafo: los elementos de la matriz indican si los vértices *i* y *j* tienen una arista común (*i, j*). La matriz de adyacencia del grafo de nuestra red social imaginaria es:: + + >>> g.get_adjacency() + Matrix([ + [0, 1, 1, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 1, 1, 1, 0], + [0, 0, 1, 0, 1, 0, 1], + [0, 0, 1, 1, 0, 0, 0], + [1, 0, 1, 0, 0, 0, 1], + [0, 0, 0, 1, 0, 1, 0] + ]) + +Por ejemplo, Claire (``[1, 0, 0, 1, 1, 1, 0]``) está directamente conectada con Alice (que tiene el índice 0), Dennis (índice 3), Esther (índice 4) y Frank (índice 5), pero no con Bob (índice 1) ni con George (índice 6). + +Diseños ("layouts") y graficar +============================== + +Un grafo es un objeto matemático abstracto sin una representación específica en el espacio 2D o 3D. Esto significa que cuando queremos visualizar un grafo, tenemos que encontrar primero un trazado de los vértices a las coordenadas en el espacio bidimensional o tridimensional, preferiblemente de una manera que sea agradable a la vista. Una rama separada de la teoría de grafos, denominada dibujo de grafos, trata de resolver este problema mediante varios algoritmos de disposición de grafos. igraph implementa varios algoritmos de diseño y también es capaz de dibujarlos en la pantalla o en un archivo PDF, PNG o SVG utilizando la `libreria Cairo `_. + +.. important:: + + Para seguir los ejemplos de esta sección, se requieren de la librería Cairo en Python o + matplotlib. + +Algoritmos de diseños ("layouts") +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Los métodos de diseño en |igraph| se encuentran en el objeto :class:`Graph`, y siempre comienzan con ``layout_``. La siguiente tabla los resume: + +==================================== =============== ============================================= +Method name Short name Algorithm description +==================================== =============== ============================================= +``layout_circle`` ``circle``, Disposición determinista que coloca los + ``circular`` vértices en un círculo +------------------------------------ --------------- --------------------------------------------- +``layout_drl`` ``drl`` El algoritmo [Distributed Recursive Layout] + para grafos grandes +------------------------------------ --------------- --------------------------------------------- +``layout_fruchterman_reingold`` ``fr`` El algoritmo dirigido Fruchterman-Reingold +------------------------------------ --------------- --------------------------------------------- +``layout_fruchterman_reingold_3d`` ``fr3d``, El algoritmo dirigido Fruchterman-Reingold + ``fr_3d`` en tres dimensiones +------------------------------------ --------------- --------------------------------------------- +``layout_kamada_kawai`` ``kk`` El algoritmo dirigido Kamada-Kawai +------------------------------------ --------------- --------------------------------------------- +``layout_kamada_kawai_3d`` ``kk3d``, El algoritmo dirigido Kamada-Kawai + ``kk_3d`` en tres dimensiones +------------------------------------ --------------- --------------------------------------------- +``layout_lgl`` ``large``, El algoritmo [Large Graph Layout] para + ``lgl``, grafos grandes + ``large_graph`` +------------------------------------ --------------- --------------------------------------------- +``layout_random`` ``random`` Coloca los vértices de forma totalmente aleatoria +------------------------------------ --------------- --------------------------------------------- +``layout_random_3d`` ``random_3d`` Coloca los vértices de forma totalmente aleatoria en 3D +------------------------------------ --------------- --------------------------------------------- +``layout_reingold_tilford`` ``rt``, Diseño de árbol de Reingold-Tilford, útil + ``tree`` para grafos (casi) arbóreos +------------------------------------ --------------- --------------------------------------------- +``layout_reingold_tilford_circular`` ``rt_circular`` Diseño de árbol de Reingold-Tilford con una + post-transformación de coordenadas polares, + ``tree`` útil para grafos (casi) arbóreos +------------------------------------ --------------- --------------------------------------------- +``layout_sphere`` ``sphere``, Disposición determinista que coloca los vértices + ``spherical``, de manera uniforme en la superficie de una esfera + ``circular_3d`` +==================================== =============== ============================================= + +.. _Distributed Recursive Layout: https://www.osti.gov/doecode/biblio/54626 +.. _Large Graph Layout: https://sourceforge.net/projects/lgl/ + +Los algoritmos de diseño pueden ser llamados directamente o utilizando :meth:`~Graph.layout`:: + + >>> layout = g.layout_kamada_kawai() + >>> layout = g.layout("kamada_kawai") + +El primer argumento del método :meth:`~Graph.layout` debe ser el nombre corto del algoritmo de diseño (mirar la tabla anterior). Todos los demás argumentos posicionales y de palabra clave se pasan intactos al método de diseño elegido. Por ejemplo, las dos llamadas siguientes son completamente equivalentes:: + + >>> layout = g.layout_reingold_tilford(root=[2]) + >>> layout = g.layout("rt", [2]) + +Los métodos de diseño devuelven un objeto :class:`~layout.Layout` que se comporta principalmente como una lista de listas. Cada entrada de la lista en un objeto :class:`~layout.Layout` corresponde a un vértice en el grafo original y contiene las coordenadas del vértice en el espacio 2D o 3D. Los objetos :class:`~layout.Layout` también contienen algunos métodos útiles para traducir, escalar o rotar las coordenadas en un lote. Sin embargo, la principal utilidad de los objetos :class:`~layout.Layout` es que puedes pasarlos a la función :func:`~drawing.plot` junto con el grafo para obtener un dibujo en 2D. + +Dibujar un grafo utilizando un diseño ("layout") +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Por ejemplo, podemos trazar nuestra red social imaginaria con el algoritmo de distribución Kamada-Kawai de la siguiente manera:: + + >>> layout = g.layout("kk") + >>> ig.plot(g, layout=layout) + +Esto debería abrir un visor de imágenes externo que muestre una representación visual de la red, algo parecido a lo que aparece en la siguiente figura (aunque la colocación exacta de los nodos puede ser diferente en su máquina, ya que la disposición no es determinista): + +.. figure:: figures/tutorial_social_network_1.png + :alt: The visual representation of our social network (Cairo backend) + :align: center + +Nuestra red social con el algoritmo de distribución Kamada-Kawai + +Si prefiere utilizar `matplotlib`_ como motor de trazado, cree un eje y utilice el argumento ``target``:: + + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> ig.plot(g, layout=layout, target=ax) + +.. figure:: figures/tutorial_social_network_1_mpl.png + :alt: The visual representation of our social network (matplotlib backend) + :align: center + +Hmm, esto no es demasiado bonito hasta ahora. Una adición trivial sería usar los nombres como etiquetas de los vértices y colorear los vértices según el género. Las etiquetas de los vértices se toman del atributo ``label`` por defecto y los colores de los vértices se determinan por el atributo ``color``:: + + >>> g.vs["label"] = g.vs["name"] + >>> color_dict = {"m": "blue", "f": "pink"} + >>> g.vs["color"] = [color_dict[gender] for gender in g.vs["gender"]] + >>> ig.plot(g, layout=layout, bbox=(300, 300), margin=20) # Cairo backend + >>> ig.plot(g, layout=layout, bbox=(300, 300), margin=20, target=ax) # matplotlib backend + +Tenga en cuenta que aquí simplemente estamos reutilizando el objeto de diseño anterior, pero también hemos especificado que necesitamos un gráfico más pequeño (300 x 300 píxeles) y un margen mayor alrededor del grafo para que quepan las etiquetas (20 píxeles). El resultado es: + +.. figure:: figures/tutorial_social_network_2.png + :alt: The visual representation of our social network - with names and genders + :align: center + +Nuestra red social - con nombres como etiquetas y géneros como colores + +y para matplotlib: + +.. figure:: figures/tutorial_social_network_2_mpl.png + :alt: The visual representation of our social network - with names and genders + :align: center + +En lugar de especificar las propiedades visuales como atributos de vértices y aristas, también puedes darlas como argumentos a :func:`~drawing.plot`:: + + >>> color_dict = {"m": "blue", "f": "pink"} + >>> ig.plot(g, layout=layout, vertex_color=[color_dict[gender] for gender in g.vs["gender"]]) + +Este último enfoque es preferible si quiere mantener las propiedades de la representación visual de su gráfico separadas del propio gráfico. Puedes simplemente crear un diccionario de Python que contenga los argumentos que contenga las palabras clave que pasarias a la función :func:`~drawing.plot` y luego usar el doble asterisco (``**``) para pasar tus atributos de estilo específicos a :func:`~drawing.plot`:: + + >>> visual_style = {} + >>> visual_style["vertex_size"] = 20 + >>> visual_style["vertex_color"] = [color_dict[gender] for gender in g.vs["gender"]] + >>> visual_style["vertex_label"] = g.vs["name"] + >>> visual_style["edge_width"] = [1 + 2 * int(is_formal) for is_formal in g.es["is_formal"]] + >>> visual_style["layout"] = layout + >>> visual_style["bbox"] = (300, 300) + >>> visual_style["margin"] = 20 + >>> ig.plot(g, **visual_style) + +El gráfico final muestra los vínculos formales con líneas gruesas y los informales con líneas finas: + +.. figure:: figures/tutorial_social_network_3.png + :alt: The visual representation of our social network - with names, genders and formal ties + :align: center + + Nuestra red social - también muestra qué vínculos son formales + +Para resumirlo todo: hay propiedades especiales de vértices y aristas que corresponden a la representación visual del grafo. Estos atributos anulan la configuración por defecto de |igraph| (es decir, el color, el peso, el nombre, la forma, el diseño, etc.). Las dos tablas siguientes resumen los atributos visuales más utilizados para los vértices y las aristas, respectivamente: + +Atributos de los vértices que controlan los gráficos +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +=============== ====================== ========================================== +Attribute name Keyword argument Purpose +=============== ====================== ========================================== +``color`` ``vertex_color`` Color del vertice +--------------- ---------------------- ------------------------------------------ +``font`` ``vertex_font`` Familia tipográfica del vértice +--------------- ---------------------- ------------------------------------------ +``label`` ``vertex_label`` Etiqueta del vértice. +--------------- ---------------------- ------------------------------------------ +``label_angle`` ``vertex_label_angle`` Define la posición de las etiquetas de los + vértices, en relación con el centro de los + mismos. Se interpreta como un ángulo en + radianes, cero significa 'a la derecha'. +--------------- ---------------------- ------------------------------------------ +``label_color`` ``vertex_label_color`` Color de la etiqueta del vértice +--------------- ---------------------- ------------------------------------------ +``label_dist`` ``vertex_label_dist`` Distancia de la etiqueta del vértice, + en relación con el tamaño del vértice +--------------- ---------------------- ------------------------------------------ +``label_size`` ``vertex_label_size`` Tamaño de letra de la etiqueta de vértice +--------------- ---------------------- ------------------------------------------ +``order`` ``vertex_order`` Orden de dibujo de los vértices. Vértices + con un parámetro de orden menor se + dibujarán primero. +--------------- ---------------------- ------------------------------------------ +``shape`` ``vertex_shape`` La forma del vértice,. Algunas formas: + ``rectangle``, ``circle``, ``hidden``, + ``triangle-up``, ``triangle-down``. Ver + :data:`drawing.known_shapes`. +--------------- ---------------------- ------------------------------------------ +``size`` ``vertex_size`` El tamaño del vértice en pixels +=============== ====================== ========================================== + +Atributos de las aristas que controlan los gráficos +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +=============== ====================== ========================================== +Attribute name Keyword argument Purpose +=============== ====================== ========================================== +``color`` ``edge_color`` Color de la arista +--------------- ---------------------- ------------------------------------------ +``curved`` ``edge_curved`` la curvatura de la arista. Valores positivos + corresponden a aristas curvadas en sentido + contrario a las manecillas del reloj, valores + negativos lo contrario. Una curvatura cero + representa aristas rectas. ``True`` significa + una curvatura de 0.5, ``False`` es una + curvatura de cero. +--------------- ---------------------- ------------------------------------------ +``font`` ``edge_font`` Familia tipográfica del arista +--------------- ---------------------- ------------------------------------------ +``arrow_size`` ``edge_arrow_size`` Tamaño (longitud) de la punta de flecha del + arista si el grafo es dirigido, relativo a + 15 pixels. +--------------- ---------------------- ------------------------------------------ +``arrow_width`` ``edge_arrow_width`` El ancho de las flechas. Relativo a 10 + pixels. +--------------- ---------------------- ------------------------------------------ +``width`` ``edge_width`` Anchura del borde en píxeles +--------------- ---------------------- ------------------------------------------ +``label`` ``edge_label`` Si se especifica, añade una etiqueta al borde. +--------------- ---------------------- ------------------------------------------ +``background`` ``edge_background`` Si se especifica, añade una caja rectangular + alrededor de la etiqueta de borde (solo en ) + matplotlib) +--------------- ---------------------- ------------------------------------------ +``align_label`` ``edge_align_label`` Si es verdadero, gira la etiqueta de la + arista de forma que se alinee con la + dirección de la arista. Las etiquetas que + estarían al revés se voltean (sólo matplotlib). +=============== ====================== ========================================== + +Argumentos genéricos de ``plot()`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Estos ajustes se pueden especificar como argumentos de palabra clave a la función ``plot`` para controlar la apariencia general del gráfico. + +================ ================================================================ +Keyword argument Purpose +================ ================================================================ +``autocurve`` Determinación automática de la curvatura de las aristas en grafos + con múltiples aristas. El estandar es ``True`` para grafos + con menos de 10000 aristas y ``False`` para el caso contrario. +---------------- ---------------------------------------------------------------- +``bbox`` La caja delimitadora del gráfico. Debe ser una tupla que contenga + la anchura y la altura deseadas del gráfico. Por default el gráfico + tiene 600 pixels de ancho y 600 pixels de largo. +---------------- ---------------------------------------------------------------- +``layout`` El diseño que se va a utilizar. Puede ser una instancia de ``layout`` + una lista de tuplas que contengan coordenadas X-Y, o el nombre + un algoritmo de diseño. El valor por defecto es ``auto``, que + selecciona un algoritmo de diseño automáticamente basado en el tamaño + y la conectividad del grafo. +---------------- ---------------------------------------------------------------- +``margin`` La cantidad de espacio vacío debajo, encima, a la izquierda y + a la derecha del gráfico. +================ ================================================================ + +Especificación de colores en los gráficos +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +|igraph| entiende las siguientes especificaciones de color siempre que espera un color (por ejemplo, colores de aristas, vértices o etiquetas en los respectivos atributos): + +***Nombres de colores X11*** + +Consulta la `lista de nombres de colores X11 `_ en Wikipedia para ver la lista completa. Los nombres de los colores no distinguen entre mayúsculas y minúsculas en |igraph|, por lo que "DarkBLue" puede escribirse también como "darkblue". + +***Especificación del color en la sintaxis CSS*** + +Se trata de una cadena según uno de los siguientes formatos (donde *R*, *G* y *B* denotan los componentes rojo, verde y azul, respectivamente): + +- ``#RRGGBB``, los componentes van de 0 a 255 en formato hexadecimal. Ejemplo: ``"#0088ff"`` +- ``#RGB``, los componentes van de 0 a 15 en formato hexadecimal. Ejemplo: ``"#08f"`` +- ``rgb(R, G, B)``, los componentes van de 0 a 255 o de 0% a 100%. Ejemplo: ``"rgb(0, 127, 255)"`` o ``"rgb(0%, 50%, 100%)"``. + +Guardar gráficos +^^^^^^^^^^^^^^^^ + +|igraph| puede usarse para crear gráficos de calidad de publicación solicitando la función :func:`~drawing.plot` que guarde el gráfico en un archivo en lugar de mostrarlo en pantalla. Para ello, basta con pasar el nombre del archivo destino como argumento adicional después del grafo mismo. El formato preferido se deduce de la extensión. |igraph| puede guardar en cualquier cosa que soporte Cairo, incluyendo archivos SVG, PDF y PNG. Los archivos SVG o PDF pueden ser convertidos posteriormente al formato PostScript (``.ps``) o PostScript encapsulado (``.eps``) si lo prefieres, mientras que los archivos PNG pueden ser convertidos a TIF (``.tif``):: + + >>> ig.plot(g, "social_network.pdf", **visual_style) + +Si estas usando matplotlib, puedes guardar el gŕafico como de costumbre:: + + >>> fig, ax = plt.subplots() + >>> ig.plot(g, **visual_style) + >>> fig.savefig("social_network.pdf") + +Muchos formatos de archivos son admitidos por matplotlib. + +|igraph| y el mundo exterior +============================ + +Ningún módulo de grafos estaría completo sin algún tipo de funcionalidad de importación/exportación que permita al paquete comunicarse con programas y kits de herramientas externos. |igraph| no es una excepción: proporciona funciones para leer los formatos de grafos más comunes y para guardar objetos :class:`Graph` en archivos que obedezcan estas especificaciones de formato. La siguiente tabla resume los formatos que igraph puede leer o escribir: + +================ ============= ============================ ============================= +Format Short name Reader method Writer method +================ ============= ============================ ============================= +Adjacency list ``lgl`` :meth:`Graph.Read_Lgl` :meth:`Graph.write_lgl` +(a.k.a. `LGL`_) +---------------- ------------- ---------------------------- ----------------------------- +Adjacency matrix ``adjacency`` :meth:`Graph.Read_Adjacency` :meth:`Graph.write_adjacency` +---------------- ------------- ---------------------------- ----------------------------- +DIMACS ``dimacs`` :meth:`Graph.Read_DIMACS` :meth:`Graph.write_dimacs` +---------------- ------------- ---------------------------- ----------------------------- +DL ``dl`` :meth:`Graph.Read_DL` not supported yet +---------------- ------------- ---------------------------- ----------------------------- +Edge list ``edgelist``, :meth:`Graph.Read_Edgelist` :meth:`Graph.write_edgelist` + ``edges``, + ``edge`` +---------------- ------------- ---------------------------- ----------------------------- +`GraphViz`_ ``graphviz``, not supported yet :meth:`Graph.write_dot` + ``dot`` +---------------- ------------- ---------------------------- ----------------------------- +GML ``gml`` :meth:`Graph.Read_GML` :meth:`Graph.write_gml` +---------------- ------------- ---------------------------- ----------------------------- +GraphML ``graphml`` :meth:`Graph.Read_GraphML` :meth:`Graph.write_graphml` +---------------- ------------- ---------------------------- ----------------------------- +Gzipped GraphML ``graphmlz`` :meth:`Graph.Read_GraphMLz` :meth:`Graph.write_graphmlz` +---------------- ------------- ---------------------------- ----------------------------- +LEDA ``leda`` not supported yet :meth:`Graph.write_leda` +---------------- ------------- ---------------------------- ----------------------------- +Labeled edgelist ``ncol`` :meth:`Graph.Read_Ncol` :meth:`Graph.write_ncol` +(a.k.a. `NCOL`_) +---------------- ------------- ---------------------------- ----------------------------- +`Pajek`_ format ``pajek``, :meth:`Graph.Read_Pajek` :meth:`Graph.write_pajek` + ``net`` +---------------- ------------- ---------------------------- ----------------------------- +Pickled graph ``pickle`` :meth:`Graph.Read_Pickle` :meth:`Graph.write_pickle` +================ ============= ============================ ============================= + +.. _GraphViz: https://www.graphviz.org +.. _LGL: https://lgl.sourceforge.net/#FileFormat +.. _NCOL: https://lgl.sourceforge.net/#FileFormat +.. _Pajek: http://mrvar.fdv.uni-lj.si/pajek/ + +Como ejercicio, descarga la representación gráfica del conocido `Estudio del club de karate de Zacarías `_ en formato graphml. Dado que se trata de un archivo GraphML, debe utilizar el método de lectura GraphML de la tabla anterior (asegúrese de utilizar la ruta adecuada al archivo descargado):: + + >>> karate = ig.Graph.Read_GraphML("zachary.graphml") + >>> ig.summary(karate) + IGRAPH UNW- 34 78 -- Zachary's karate club network + +Si quieres convertir el mismo grafo a, digamos, el formato de Pajek, puedes hacerlo con el método de la tabla anterior:: + + >>> karate.write_pajek("zachary.net") + +.. note:: + La mayoría de los formatos tienen sus propias limitaciones; por ejemplo, no todos pueden + almacenar atributos. Tu mejor opción es probablemente GraphML o GML si quieres guardar los + grafos de |igraph| en un formato que pueda ser leído desde un paquete externo y quieres + preservar los atributos numéricos y de cadena. La lista de aristas y NCOL también están bien + si no tienes atributos (aunque NCOL soporta nombres de vértices y pesos de aristas). Si no + quieres utilizar grafos fuera de |igraph|, pero quieres almacenarlos para una sesión + posterior, el formato de grafos ``pickled`` te garantza que obtendras exactamente el mismo + grafo. El formato de grafos ``pickled`` usa el modulo ``pickle`` de Python para guardar y + leer grafos. + +También existen dos métodos de ayuda: :func:`read` es un punto de entrada genérico para los métodos de lectura que intenta deducir el formato adecuado a partir de la extensión del archivo. :meth:`Graph.write` es lo contrario de :func:`read`: permite guardar un grafo en el que el formato preferido se deduce de nuevo de la extensión. La detección del formato de :func:`read` y :meth:`Graph.write` se puede anular mediante el argumento ``format`` de la palabra clave ("keyword"), la cual acepta los nombres cortos de los otros formatos de la tabla anterior:: + + >>> karate = ig.load("zachary.graphml") + >>> karate.write("zachary.net") + >>> karate.write("zachary.my_extension", format="gml") + +Dónde ir a continuación +======================= + +Este tutorial sólo ha arañado la superficie de lo que |igraph| puede hacer. Los planes a largo plazo son ampliar este tutorial para convertirlo en una documentación adecuada de estilo manual para igraph en los próximos capítulos. Un buen punto de partida es la documentación de la clase `Graph`. Si te quedas atascado, intenta preguntar primero en nuestro `Discourse group`_ - quizás haya alguien que pueda ayudarte inmediatamente. + +.. _Discourse group: https://igraph.discourse.group +.. _matplotlib: https://matplotlib.org/ +.. _IPython: https://ipython.readthedocs.io/en/stable/ +.. _Jupyter: https://jupyter.org/ + + + + + + + + + + + + From 709c6b1c99f271e21717e9b5f9e5f918d1e69300 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 14:05:47 +0000 Subject: [PATCH 1222/1892] build(deps): bump pypa/cibuildwheel from 2.12.0 to 2.12.1 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.12.0 to 2.12.1. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.12.0...v2.12.1) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f5d6a795d..cf9edebae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -214,7 +214,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.12.0 + uses: pypa/cibuildwheel@v2.12.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 79a7829ffbec5f3ae542b904b2d88217188a2b6e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 14 Mar 2023 23:14:17 +0100 Subject: [PATCH 1223/1892] fix: VertexClustering.giant() now works with null graphs, closes #649 --- src/igraph/clustering.py | 7 +++++-- tests/test_decomposition.py | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index c7270a52b..c4b345a47 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -427,8 +427,11 @@ def giant(self): @return: a copy of the largest cluster. """ ss = self.sizes() - max_size = max(ss) - return self.subgraph(ss.index(max_size)) + if ss: + max_size = max(ss) + return self.subgraph(ss.index(max_size)) + else: + return self._graph.copy() def __plot__(self, backend, context, *args, **kwds): """Plots the clustering to the given Cairo context or matplotlib Axes. diff --git a/tests/test_decomposition.py b/tests/test_decomposition.py index 8fe223a7f..a7ad5bd49 100644 --- a/tests/test_decomposition.py +++ b/tests/test_decomposition.py @@ -167,6 +167,13 @@ def testSizesWithNone(self): cl = VertexClustering(self.graph, [0, 0, 0, None, 1, 1, 2, None, 2, None]) self.assertTrue(cl.sizes() == [3, 2, 2]) + def testClusteringOfNullGraph(self): + null_graph = Graph() + cl = VertexClustering(null_graph, []) + self.assertTrue(cl.sizes() == []) + self.assertTrue(cl.giant().vcount() == 0) + self.assertTrue(cl.giant().ecount() == 0) + class CoverTests(unittest.TestCase): def setUp(self): From abd21c71848c70cd5efb4f1913b1f8a892a2fe80 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 14 Mar 2023 23:15:56 +0100 Subject: [PATCH 1224/1892] chore: updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65fa445a7..7dbf0e0a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ - `resolution` parameter is now correctly taken into account when calling `Graph.modularity()` +- `VertexClustering.giant()` now accepts the null graph. The giant component of + a null graph is the null graph according to our conventions. + ### Removed - Removed defunct `Graph.community_leading_eigenvector_naive()` method. Not a From 3334f535918b2ebd74e93b678c1a140a820bf477 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 15 Mar 2023 14:22:09 +0100 Subject: [PATCH 1225/1892] doc: fix title of Spanish tutorial to make it distinguishable from the English one in the sidebar --- doc/source/tutorial.es.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/source/tutorial.es.rst b/doc/source/tutorial.es.rst index a94945b63..d6e89d39c 100644 --- a/doc/source/tutorial.es.rst +++ b/doc/source/tutorial.es.rst @@ -4,9 +4,9 @@ .. currentmodule:: igraph -======== -Tutorial -======== +================== +Tutorial (Español) +================== Esta página es un tutorial detallado de las capacidades de |igraph| para Python. Para obtener una impresión rápida de lo que |igraph| puede hacer, consulte el :doc:`tutorials/quickstart`. Si aún no ha instalado |igraph|, siga las instrucciones de :doc:`install`. From e4bf36ffa2c7452877afdfb241a15641c13e738f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horv=C3=A1t?= Date: Thu, 16 Mar 2023 15:20:38 +0100 Subject: [PATCH 1226/1892] docs: improve linegraph() docs --- src/_igraph/graphobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 69f544187..5f27d40e3 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14676,7 +14676,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "The line graph of a directed graph is slightly different: two vertices\n" "are connected by a directed edge iff the target of the first vertex's\n" "corresponding edge is the same as the source of the second vertex's\n" - "corresponding edge.\n" + "corresponding edge.\n\n" + "Edge M{i} in the original graph will map to vertex M{i} of the line graph.\n" }, /* interface to igraph_maxdegree */ From 72e427480e58d7813065818bd908b0e08c10cc0f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 18 Mar 2023 22:33:03 +0100 Subject: [PATCH 1227/1892] doc: increase spacing between parameters in parameter lists of the API docs, closes #648 --- doc/source/_pydoctor_templates/extra.css | 7 +++++++ doc/source/conf.py | 7 ++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 doc/source/_pydoctor_templates/extra.css diff --git a/doc/source/_pydoctor_templates/extra.css b/doc/source/_pydoctor_templates/extra.css new file mode 100644 index 000000000..f5a70f56a --- /dev/null +++ b/doc/source/_pydoctor_templates/extra.css @@ -0,0 +1,7 @@ +/* increase spacing between parameters in a parameter list, and make sure + * that parameter names are aligned to the top */ +.fieldTable tr td { + padding: 3px 4px 10px 10px !important; + vertical-align: top; +} + diff --git a/doc/source/conf.py b/doc/source/conf.py index a31dba8b7..212b0a831 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -262,18 +262,19 @@ def get_pydoctor_html_outputdir(pydoctor_url_path): '--html-output=' + get_pydoctor_html_outputdir(pydoctor_url_path), #'--html-viewsource-base=https://github.com/igraph/python-igraph/tree/default', '--project-base-dir=' + _igraph_dir, - ] + '--template-dir=' + get_root_dir() + '/doc/source/_pydoctor_templates' +] # Using --no-sidebar option to skip the sidebar because the pydoctor output is # integrated in a smaller div with a custom CSS. if not is_inside_rtd: pydoctor_args.extend([ '--no-sidebar', - ]) + ]) else: pydoctor_args.extend([ '--theme=readthedocs', - ]) + ]) pydoctor_args.append(_igraph_dir) # RTD needs no postprocessing for pydoctor, while Jekyll does From 3431498a4a80cecc0960da5c2cc0279fd412206e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 23 Mar 2023 09:33:36 +0100 Subject: [PATCH 1228/1892] feat: allow the plotting backend to be defined explicitly in plot() --- CHANGELOG.md | 3 +++ src/igraph/drawing/__init__.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbf0e0a3..4b00f57ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Added +- The `plot()` function now takes a `backend` keyword argument that can be used + to specify the plotting backend explicitly. + - The `VertexClustering` object returned from `Graph.community_leiden()` now contains an extra property named `quality` that stores the value of the internal quality function optimized by the algorithm. diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index eab1907eb..5ae708ccc 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -192,6 +192,10 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): argument has an effect only if igraph is run inside IPython and C{target} is C{None}. + @keyword backend: the plotting backend to use; one of C{"cairo"}, + C{"matplotlib"} or C{"plotly"}. C{None} means to try to decide the backend + from the plotting target and the default igraph configuration object. + @return: an appropriate L{CairoPlot} object for the Cairo backend, the Matplotlib C{Axes} object for the Matplotlib backend, and the C{Figure} object for the plotly backend. @@ -205,8 +209,13 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): cairo = find_cairo() plotly = find_plotly() - # Switch backend based on target (first) and config (second) - if hasattr(plt, "Axes") and isinstance(target, plt.Axes): + backend = kwds.pop("backend", None) + + # Switch backend based on target (first) and config (second) if it was not + # selected explicitly + if backend is not None: + pass + elif hasattr(plt, "Axes") and isinstance(target, plt.Axes): backend = "matplotlib" elif hasattr(plotly, "graph_objects") and isinstance( target, plotly.graph_objects.Figure @@ -218,7 +227,7 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): backend = Configuration.instance()["plotting.backend"] if backend not in VALID_BACKENDS: - raise ValueError("unknown plotting backend: {0!r}".format(backend)) + raise ValueError(f"unknown plotting backend: {backend!r}") if backend in ("matplotlib", "plotly"): # Choose palette From 6aef873764548d2fd614a156e4e9e91368b908b7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 23 Mar 2023 09:34:57 +0100 Subject: [PATCH 1229/1892] fix: specify Cairo backend explicitly in Cairo plotting tests in case the default backend is overridden on the user's machine --- tests/drawing/cairo/test_graph.py | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/drawing/cairo/test_graph.py b/tests/drawing/cairo/test_graph.py index eacec226d..eccd60618 100644 --- a/tests/drawing/cairo/test_graph.py +++ b/tests/drawing/cairo/test_graph.py @@ -15,14 +15,14 @@ cairo = find_cairo() -has_cairo = hasattr(cairo, 'version') +has_cairo = hasattr(cairo, "version") image_comparison = find_image_comparison() class GraphTestRunner(unittest.TestCase): @classmethod - def setUpClass(self): + def setUpClass(cls): if not has_cairo: raise unittest.SkipTest("cairo not found, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) @@ -30,29 +30,30 @@ def setUpClass(self): @image_comparison(baseline_images=["graph_basic"]) def test_basic(self): g = Graph.Ring(5) - plot(g, target=result_image_folder / 'graph_basic.png') + plot(g, target=result_image_folder / "graph_basic.png", backend="cairo") @image_comparison(baseline_images=["graph_directed"]) def test_directed(self): g = Graph.Ring(5, directed=True) - plot(g, target=result_image_folder / 'graph_directed.png') + plot(g, target=result_image_folder / "graph_directed.png", backend="cairo") @image_comparison(baseline_images=["graph_mark_groups_directed"]) def test_mark_groups(self): g = Graph.Ring(5, directed=True) plot( g, - target=result_image_folder / 'graph_mark_groups_directed.png', - mark_groups=True) + target=result_image_folder / "graph_mark_groups_directed.png", + backend="cairo", + mark_groups=True, + ) - @image_comparison( - baseline_images=["graph_mark_groups_squares_directed"] - ) + @image_comparison(baseline_images=["graph_mark_groups_squares_directed"]) def test_mark_groups_squares(self): g = Graph.Ring(5, directed=True) plot( g, - target=result_image_folder / 'graph_mark_groups_squares_directed.png', + target=result_image_folder / "graph_mark_groups_squares_directed.png", + backend="cairo", mark_groups=True, vertex_shape="square", ) @@ -60,7 +61,7 @@ def test_mark_groups_squares(self): class ClusteringTestRunner(unittest.TestCase): @classmethod - def setUpClass(self): + def setUpClass(cls): if not has_cairo: raise unittest.SkipTest("cairo not found, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) @@ -71,7 +72,8 @@ def test_clustering_directed_small(self): clu = VertexClustering(g, [0] * 5) plot( clu, - target=result_image_folder / 'clustering_directed.png', + backend="cairo", + target=result_image_folder / "clustering_directed.png", mark_groups=True, ) @@ -79,11 +81,12 @@ def test_clustering_directed_small(self): def test_clustering_directed_large(self): g = Graph.Ring(50, directed=True) clu = VertexClustering(g, [0] * 3 + [1] * 17 + [2] * 30) - layout = [(x*2.5, y*2.5) for x, y in g.layout("circle")] + layout = [(x * 2.5, y * 2.5) for x, y in g.layout("circle")] plot( clu, + backend="cairo", layout=layout, - target=result_image_folder / 'clustering_directed_large.png', + target=result_image_folder / "clustering_directed_large.png", mark_groups=True, ) @@ -91,10 +94,7 @@ def test_clustering_directed_large(self): def suite(): graph = unittest.defaultTestLoader.loadTestsFromTestCase(GraphTestRunner) clustering = unittest.defaultTestLoader.loadTestsFromTestCase(ClusteringTestRunner) - return unittest.TestSuite([ - graph, - clustering, - ]) + return unittest.TestSuite([graph, clustering]) def test(): From f01cb4202420111a145e9cf97e12263839804344 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 23 Mar 2023 10:44:51 +0100 Subject: [PATCH 1230/1892] test: make Cairo drawing tests deterministic --- .../baseline_images/clustering_directed.png | Bin 31493 -> 33794 bytes .../cairo/baseline_images/graph_basic.png | Bin 16701 -> 18287 bytes .../cairo/baseline_images/graph_directed.png | Bin 17353 -> 19005 bytes .../graph_mark_groups_directed.png | Bin 17353 -> 19005 bytes .../graph_mark_groups_squares_directed.png | Bin 14924 -> 16548 bytes tests/drawing/cairo/test_graph.py | 10 +++++++--- 6 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/drawing/cairo/baseline_images/clustering_directed.png b/tests/drawing/cairo/baseline_images/clustering_directed.png index 712f1b95f8fdc22b4eb1b2683143634a81146a14..3971f801c44b9b241ad55579c2d37825480b32bf 100644 GIT binary patch literal 33794 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

    OH9Qh)~+=xe9%^+}N1@mpJtyPbtu)y+r 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 G=l=)LhSQS( literal 31493 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

    3&d%}xZZW+`g_A~m_IP753kl3u7nInA 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 diff --git a/tests/drawing/cairo/baseline_images/graph_directed.png b/tests/drawing/cairo/baseline_images/graph_directed.png index 83d6e37647f1b6fe90f88f080974afea8573013d..77106eb56d46320be55f68af9f3cc345a7d8513a 100644 GIT binary patch literal 19005 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 Ogs#>>&Bq$HSN=bKBxy4M literal 17353 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 z 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 mMB}CUMZX3{Qm%)pbLxu diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png index 83d6e37647f1b6fe90f88f080974afea8573013d..77106eb56d46320be55f68af9f3cc345a7d8513a 100644 GIT binary patch literal 19005 zcmZv^2|QJ8+cv(4Ol8OvB@!}5sMuu6kf98fDWM5TDP#_J$Q%hNQAiRZQY2GSh9XIb z6v;d#Q^x@j+qfqPOEMADEsOy%)b}e|XwY#@=fsarzcvo5uCsZ{GeqcJ*g$X)kk_ zjAY^R%J;?JyAPeZb!+6^yOBR{=TfWR-FZHD+5fVSN?S>z@x~}^27>VUDL}ze1dW3T zqEwrWni%EPq9^jta%?3kAOGizdd*Zs?W>vy?&!^mEZZPay0biseVXK-+^;B-Uy zHHJhsE&BF6*MY{F;jWU=_enPj3cf6#&FGWXz1`FQthw$?b2#VMefw%OY2HN((u{tR zu2}jgr{L-0KC82K-&W_vW3k@Fr6GoilfT-Za5bzo-+Glp+%DKiPgTm^_27Nw8ai*z--qUevL0lg{Zi&L zK0a<2Moa&SXREEv7G=*1lXKq!BUYweA6xw~^!ep*-^;0jRM^vM-{8QGU0jGlpO~X`t@(pfjM{P<{U=_fY zw%?45jO0D?$VqC2ZbJ9t^_MU2-4kfBrw%&7ztxuespVKzAl)GolgCyiR6;>Y3XG8Sz`5t`*@Df0T0*C-oB@O*?F_$oo!Fgv~-vG zC@Cu5nusRo)!C>`r6nZJwmm*pS67#klHyoIk&*e(+FBHPch|;s+2tz~zp1{FGiSz< z?>y@J>*-xxemCzg>YZL?QC*T3*UKL#AJ5j+c$jemc8Edi;Fksvv=5(`}Wmdhp|W8DE$0)7iLEGocXBvYxQ~e*`hDy zmly3$o!TGE!OF_Y#q}nT;kX>0c)>yb_T|OdbFfr)Yx%D?o0640b{u*TS;F$d_s`U> zv!6MZzSPuY_{@#ts!Oh}a&s4{T+`{P&YE0coNqBy-Gwj6HC6TgXm=jo>NEG%;}Yd- zwVC+ghcdR6#IyG5FW5;=&tkrn;nwVA$|Xhy2C<{ha(*&ac74q7TVA*{{7KQZ|J_NL<;A(qXGKmO1r~*N z8dsCaEqoSnV z@5&BP!vdM2&xOFlN|nvN;#++t$~^GwA$f-%TPg0?G5%-ZE_WiM=z5-IefE4q9v&Vg zkMXX8)B3k$Pk(Zp8Ej5JW@V)r;w=u(G|e`9Y-KUo$!+7ibNhB3o4zEEHL|adU|^M_dhgBy)x*arfU=w zka61Hes%sw^rk)MKMlD#zx;L8GIw@*nuG6==L5sL<2^k)o!axS9E*g35gikE6kT)1 zS*Z6Ti|A56uTC;`cYhWV@-{v1UDBS3sh!bKVNww=(8-wyQJ{5WSrHJ47|^9sbzT;xYE6$m_SAw6t`QRj8*vw8DoUS4qu(vmaLm)e-EFbI1xttU#`lA)#L7x+Cq)gqs-{NMbX zwyz@;Rq-01(ryuvt8^Xv&Wmb%=kM%Uvu4e{efut7zN{5eppFcUNBZ*amRz=JF8S@M z99u_uJA0&@no{;km_0VwzkhOemMfWdo_wRZ`jFbQ>Z9FeHkW5c@+undDBf7U8N(3H zIxCE92_HwcY;0^qiP#syymZOwxOV!*+0l-np`j;Fo=8?{FpFxmGd-(r2sxOUBy(J& zCY%#bE=FNeV|(@a%ztMxF;&%yLzxGws;aE5t<(0Ye{_)N_g}h*e1bG4MPVA{)1pth z^s_!5_8UbQ>)sH-7vi^5$j$ia>FLQyRAGNrQPKTwTnzl-AEp}2goLAg_VBBLHT@bc{bmko$G|nmX?;{aM_KV9I~(pZ{P0Y?fs~AxUy2s%*?Dg)s|N~ zedq4opX=(*AiG$7W71EfKhC%1EAzK>9hMYZ+Z$6;Q*R=9S{@pwQ>|GW+DNUW!KU$f z%lVKt$0B4J?SaPRhB&cp6pnYIa&mHrW-J>%2fJ7s1;u1tIaGPqZy{`Ka<(6d79qTj zg~j>ni=sivd?t>qeLvyQ*e`tGbVC9sA7g?$cKz3nw}vUoCDvu$xXY|@P)r087g-gt zlc-FGvs;nPFI~96%E$O>2?32Hj*RUdFMdSR{-3CH`mKovGnFoUSJTt0hmEgXx$?q& zZ1~3ytnt)VVd2xrEes3{2DG-O99x6L+L=c?YS@4)K&j<+&d)lZGwVpnKy6TxKWhC z&e-6O+^#1($6T-}AS>bnCTbtZ6rAx#2O|mpY zu8b+TkG2C$*frjl_kGfylP6E| z@$q3rt?Bf}$|$8Q>(LhE-X1i{S6Ul*{NsIH@p#8i4~?p1UV+L}CRT5F6tFONal_vA9-EBpBAgZAhpOEkju8L~RcYZ8I5TacfuG+>;?9#x z%gd@ull$aX@7}$ut*woTi9zOxXrvxdWBXDZk{RF>60%&3;(6*+UntwQ zFHg^GgV_l!hr)t_0>IF_ckYaij^>zVE4d9;;x^If&ETm!cJF=$lcW`@jf-k*dhPD1 z7JI)sgry0F1F&sUU41zy8M7<=gZqDh(C(Lt($abVN9v{$M1+qeIhX71-!BT-h|8tJ zKX6%a1{AOsowuUxA+Gb^OqN3@JVoPi55jU<{4lRcoq^Js)pL({o zwrDJYO9dz#0@8?Czy$o<5INvNW)M0TO*YGn|Eo`N3ZY}nY#B;RPe-Xkj3KFPHV*py z+Exb5fuy41pV5v&b#?V)FWj=w0S+1kaDH%*PuGqb{*YRI)VWNU!gMM`@F_E(VP~1o z+=By2hsEP9bD0?#UEJNd_!#p=@J>W%=-{`CRqXW+3R7ROU|i9EX7NhPW97boZWyZY zsQUS0wOB=@QIKqWe0&kIVPD@VQ~(r)jT>usIjapND_j)Zz1w|ZdZ_CJ1B-D`!S6x$ z`F|UPh=VlkaY&uQ_z@Di5WkDjD9FV)pU)344=^!mPxl~j5J0MC2(?qom!h*+-X?zj ziJqRV6sFhd^feL+v`a&ocMdOgl}yO|FD6K=dR)>Cu+j?A_IJVv8!Q2 zfWiHYjHu0uvZzHzvQ2T}y6_K?TRNG)VK>liL@?8Szer|Nq)L)|&s`be0< z79iLGr0?S5;_It?)N^dTmIE(sXV0GVT@PD^x;=j&5snQFiBUKLdM#dh{<l$34d5WQ#yQd=F<)6@U>pITIBOE5yPrtS;*oM&_Q`t@ccfrH5upn>L8 zA}--z<|epBu4U2M^}Iq9CdnW{$!FPSdE@O*0>>r;a_bu#wnM96`fnWq61Pi~4^4ZUlBrvhC<>E*c(lv2+pN&>s zDL!7kHn8dg$~lZsQc{97sByt&ITnR02z_8UMG7VS+M1TaIYD1fou`O8U>y7oKS-nI zj%F>0fnD4*N5Q3UKkn@9ZW)A%2!}#ra{1uFgBLEyV7VLz)0=%!Yx7=C)hkWBM5;4* zHy%FuKbTuvj|dmsyLYd$^3w9$Hx@?54au|*PDyJ$Y;`1I0G#&E)Xz2>|Gh#&_u-Oh z`>66|Zz4BMw-~+!g!;F-$Ud_PLN{|1S*gU;zRGk!CIc3*7kFuTaSkv>*gjtCVY37J_2*u{`_b-Ub7<-4e7w9!AK7x+ z&JJk9eWDxo&~)R9i;3s#0T=ZQ9Ti+o484R%I-({%Hnsp5 z8gb^r?mr^*Bt4F%}N zqNh2VK6h%f1Bpz{axG8G^U|%`_yGwgBv19_HcJEuP`oL?k^b5>0Uu%NmQ2H@#>Nzd zi)n#@frAR7v9aJGllA}tdx1FBjrF~Jc@v1B+L+(QaN0t<_g}zpRXKySm`92_D}Vcc z!TPpdZEE7yhyNRMYMDd|%5Pj}<3H1y#v|8wtoXyb)}q*h+jT##&zPzxDJfcBy6U?y ziMIVF7$;43jPQO>?mdErFn!DPQbKW_rFAh?V0FXPV*BESH}`}#H=z{e-R-)V*4 zJHjo4aOp7n29w#@v4=T1%(3@<`*bXIziih%q`X(|vhU~f-Ak{tL!_-=Dja_mgiYN$ z>kSv%e(=s2=sr$E$A}zbq)6dWM)+}3C@U3=Si4{`RHPO*s5R*9D z7tEBm+qoPi;jM}vSTLX%|L6CFbl(C6)z^z3cPC=9!D+m$sgbfM5Zbj1xk|aZFk-T= z?#9H-;PpH4trHdl*CsYa)pc}C%nn{0{*)CWEdo+TM+c_e?)Tb39<(5b#7@FI7}bO1 zSf={w%<`#aX>e+8-d;brKnrWTF)xi==G6Y@7^V^V2vlXRael!ajy8q>%nT4 zDJQ8bMaJ-a=w5&Q`qi{|?#`g3r|jt-)q|EVi@mkAn~xgB-Y?hwQSURyB_v{9dhrL6 zWUP=_e7)@HdQUI%XYW!?I%tQi6;?vP4B@(8Uq9m7wUk|FxeP;ZWZK_hTd0_P^)cJ* zDCci||LgaoA05{1F4V~|!ADC3=@ki6JbkM;?=8HaeAjUG_DK^cwTuGK3TE4?7S(XfW}bKWWUMLj45=> z(ibI(d|_s0X1ITa=dWIvNXx$J2cyI*U@Eh^_fj2mrgaVa`uY+b_EeR##l^)auBSot zp%QT<)2(@l+-uGXZ15@|uUuPtox`0SKP;#1777emn!y8Xbq&!Jgk&wtf*!l=0M(O42 z6&EXnW@ctpTxZ0a;)nnZ@XAP5N)*a9epTyK(JIqjiErf2zW^90Iq~&{N7q+rjaSG_DKD(dj@-L0{%uPn+V$rbxelsx9z zI|_liZDTJGww-s9lec3;(I8y`qEFq8Yw^e@y59f;KbD_&Gd4S>ySO}B9?85Zd?q}p zlgoY}e&q9|(e~y(F{;X|UtfBmYj=4a%7${zmRz%ivxr_;cL8v^B2n3EC|0vMIoI(v*nHV(x4z;$mWT4Gkk>&%f#9TCw9#u^n?%l^q_kz(@)@@>h~M9M?d zhC>ewNLUBv5bs^g5Z3@_fNm{H`{W~eA|T|ES>6^tzP+HMnYhC}E9~Pmv%-yHh2r&U zWU)qFv<@H>x%l`l4>a;MTR54Xi6GYxx>Y2MnwWpyX6=)U^alQ*qoV^3A%dBb+PF7h zdj9e1F!t@kZWMgV=uE_i&dwwz9jeMM+^!#_FUX6>hVqK+k=kM!gv=f~x)4m*b21iiG);>tOo~^UwF?916&+%fSNL$vsJ^+vyBK5jT`* z;n;eVfl7^og(Vt~IZ?5?GH}-)4=;WZ4``YPPLF;2!N}-n)l0*1gOZ;^1Zjw)MySy{ zPriXoK=q(rNL1Iz61LlJ?{V%1QTOnn=oa>)k~y&47(Ei-x^q^h&-p2*A~%uf=^U~$QNS_7L=7W$!lv$RsuOaQpvlOXy?r^QA8mG7V-Q2 zeh-#Q)pCbT#dEUKRwiyGn;=Ab#>cmCb3aGZiy9x+DCi*~szFCb$HKxg9>7c#Oo5T9 zsi{F@w+s-RR#8Q1Emq=G7APfl5rafv%U~vMP5bN8Fa&8iL+P^Vj|e=p853P4 z+b9tRw;s@!m6gFmVlu(b7NII5l@DC^GCWlvr!o6!O@LF`@@(gU+w!-7P)xHqleOH< z5fh~{Zi63Cm)<4r49uKYxeCLT-ZK(?bB)gj*%UA@yirhEL_$M5oe*%{v111SC7>qe zRyPJEWlt3B(m3zVOiT^@{J9Hp0lJA_;ewhQSBb4WBQaak*0u-TET}-lVdkJ@K_&cd z6yWlb%JOszHuynC2CR{CCj3J~gMNDRWGxGk&qcDjZF%3|-wIJX53q@IFrr0XX`vw` zukvV<|yQcCPP-)(`+vAiqBf9Mr0d+nu&N| zPuALqfUA6rGK{=Gim53o8+WqSx^Pxv^jOs)Ur@iR;H9vjfV%LQ#q(MHw-FwW9t6}F) zhd8`(whiqcpe;rP7z`kGw%)ldt*TT7c0$zvHmCv$OM#1S+Bv zv%dbp!Niyt0ZOQFVh%l;78h67BFo&Ya$tw>z`%Wn4}ZdZzAeWBUeIwXhn|x$7;W43 zV8V8jm6g>4gIfhi>wsRUbJn==UyDhJ$BScU0Gkm>rGt`or|Jby!Qq_VF-gCafiItF zd62B?Z|%nAy7M$!K_E5Z)TA$6#<69K3f{zA1@XWovLyqu3UfeWk)@Ops2puQKyJGRd-gmv~&BSId5Iae<9v&WL)^~5-w0|{0L)01p{9;tK7py+gaaf~?B`ygg6Ylw^ z4$Wzp;2=eRR$-FI6Y$Xzi)@=WFV#!rX=3;K`@kMb z;g;XuB)n`S$^mx#lVcHRiL}BvRwT~=6Jzmsbl_wo;_>bBc8b1kVmW<@`C4K$s}8uNE%;hrGB> z-tm*Dq@<*{_%L=kt&oHBEQB40yvK^#z?buKa>geoOHuT%Cl-_WK@lOZ)Q0v4wFSA~ zII|_Jamq<#2U+TLV?lfvEEW;Oh^$k)3{ovgvXF?V0Z|lqmq?kX4q`OSj~gwS{)WYVrA8Zt@K|U+tX}84$_E3%}E~w}kC7m)WMAtcl8#|5JE!awMBAw%8}gy^4%ncf((bsC+~= zep(S+Fz(;Nv$O{0CYX5S9gG0Z(W~vqejofmTI2kVHH4>Nu*NS8d@!u^$EVT?msrS) z8?ZMh9m-%7TwDqUC0E~CnMKtPKjkI___u7?a$~!pHI@dhQ<4%PbSs@6L&4-bcjS4a z>MD2;VQ5EBoIHt%k6|)Jm=eK*ye+Yn_-^6Y_83goAP9|Ps69>_3OTkmWziAJhp?w` z9ac_GVfPk3askJ$1O{RvheYn`>Z)}b@&`f?Bg8y_T;P%Bkr@r@#BBNwbt*!XF<66* zhbOCTgq@u|n8r2=2_VrV>ki@-8&$qMd$fT+xmlD@Q}*zfLzP7H30|h*RfrvuaZK<) ziVyPldCWIgmnZzCysVH82^V8HF*?MoLz&ja7phLsW#C2GsgL^7>%rkrC=2kZ1jV$H z9SL>s-u1bs69F4MXIjllFOAqe$(+BPK_9P|k)55rj(^`eBA?N@V%eQ+1P|Q4-|G1O zvScAg>T5R+!iWNd{(E}*&d!rpO9mnkKWf)F7;7+ZcK%kr+-hcXYeubKoGem=UR_Pi zX^aq5SLT0!_Ic;Q;mVo%{P`XzlthK&_5P>GR2qcH{NUN@GfYKf42+Cy+O$c@XLeK- z0_wnl5o?lX+}Sv}XZ4a7xBMa5JIf1`u^PVdWs z{^dOY=LUJI>CFl`N8279uNLgijM{}zx>O8KSbH{Te)v%-pIWg9d!z< zvVAZ?N3_Rdk}RPU{ic6_dwJWTsj0_Ha}`MA(o5%H_`gsjIxX)AHDMGgotD;HP#9nH zCp2B?Kz;p!@6!CMZ+4Fb!nLOR_KliW#vZb_jqLNbY^qu5hdXOB(9y zrzD3085$glf^G6obnntYQ8w~cQBi?_OmDU$>G9+8^77!9|B&82j?vJ{1vkkK`_&6> z)4zX9^sWE9!ENAUTq$3pdi`Y%#5Rt&!Lh~r_L9yvj-igX+eCR~T~;ywor%$|k@tJz z>tD_Cljt~~dgopL^4hu~my0Scy0HnO@y!=623Pz|#GIZhe+JS|oGkV6=KA%kv?G>d zxaXIJl@&&mjQ*KC5r8ccpcpb+ZcVTfs1$#Gy?u||I@ojZx5dOuFGL!`EOeZ!u|9wGn-4iyM|AD%>85xUeR^_p#M=exEKHVJzCYe_=J{m zd7=57wA8aJr(Yp>8*_B1h<1ixjpl4aetVYa_-~i@{F)v*?|oVA{P^!!A>EI=bSZtq zFPfX1^Q_DIXqfbJO72$GO6S=5fC1^^5mOHMWFsSeSNufEY@Yd7P0pqwLU8Q z^r-dPhYzqK*ND>lqe0!>-J?iZaVgCXR!D&m{AC%54!7k=>zbfN7`e8|Y{B{2Yllxc zAq3H`oNKCtp%4Tw`(qDd+6TzS?x%>TjUoAd!`t#hC=j$2=RQ5Wex~AEq*;_6fH$Ex zfN}Zp<4_y0TFQZu$HPI)ksOZ(4 zrnNS(rG_lMMd zfM8^1odxZ@oSj#GTjlZ#jno(+G2|9J88frptrNG)=qpytSwXRB#Cb4|D_|gSnhGKNTwE2C)wqW&pnoHZQ(#99k0iz?nb$ zj;7IDh~QCr=YRdk%E|(u<8*Oj;v_qlfbAb0i!isx9MQwom3>11iDCBRV_7KwYH9%w z3A>86hnjGXlwJ%Kz;IbVb+}%+EJ_0daYw zL_knGk$_%6&CaeLyp!OzZSSY!s?rKS{6*r*NYFKTWwVxmfLe4<_Op5W_#DETLcrO3 zfdIv@GmKeKcNE)T4)H-mbTt2Nr^M1yAmrFnw*=iTUIawtje0} zeDfIje84TnKflXCe%rQcS@Px|0_j*1BrP_e+#j~=9Z%7+FOegAFx#fs*jU&F#O2;* z^(}AFP}#b}EmVMCusd3GUepay+9b+byx%qg7%b;DXoO${{0czwtbB=~J~V43;QAw& zr%sXfv~z3hCKtW;%iuqZc7z;kpYyzMqtwQ_xIcK*uF{?8Q^GzAGy$xP72j z1PK}Q+3hh{zwo`1j^9^+Qd>ysj@esAW?&!k$p_w4y)}PK-*JeAaPJM__XAIaZM!`v zparEZQ5kn0xB=AC)!^VTW|PBKl4}T=40L%jsQK{zv_KBdbYno{r2*B|5>U3thnjR^ zYhgd41w&pY?j4Y?c(}N1NY2(<<{GL>I8eCGZ;JxUs%%?&L zqLAV{KM9Vd+i&q)v$|g6N3B{|p*<3l8j!%Dq4f6l_RSW5Unl8^Nb)(RKkB2`XXCqn zSh7reKS+*q#h`VuZGR_?`_GV_tmy9a=8gRPs@Mj68(JGnGAW0jL%WRJM(Pg-1w<IfRgn1TL4U1k42`PQ?0zIiLm(;&KsU0b@Df6DOeCn{35-Mi# z;%^R-AR#^gM`tBm;sO@!`Rqzm;D2SUK}iu(z@8!{EDVk&yVbE--M~hG=~AnwUvzyQ+d(_bk{XbH*uD93|S+`oUL zif^&hxy`=o5D)>GmQV{t@$N!5qDi-NTSjoS4s2Rf3`7W34ahGcN~o8`LL?N}vQQaP zk{e&Wr6o8bnjIjZ^PDJ~tG_7?YSar)#mT4z>ReV%PRiGcPr%%7w!%UaA}Y) z0gcqWeH#)SOpaHfdF_l|cftRS!l;D%Iaz*9vip&4O3BmrQ)QVjceO@3F0 zc=yz)`{-l_B@^BpL9mI5iIK^FX1JA|Pm`e1!gvUy@!!9HOZhtxl@%Ee9&7=vj~OgC zpXNF$vi6dd^^`_l+jb}xgM+=iy+J=+O-!nN5)U>ERQsi$4L6ss4VwgU7ka(yNvEzlkPeb$v9o>0yhHpVuEChPgDCfM=A+s$j^_27dGX4OfM-grwz~9pGr-V8;9UK$gCw z|H~4g+DY1>5P}840gWgvy6b$$wQ5tmiTp$ml4zr%!H)eiDBvRGfNRU{3o*oaWdb?a2Cskp`gL@kZd|u|0XdvHmj3*P zeDtqcG}Jfjq=a@cNRZqET97F1ZQ?+Z`N+5^S=H zjz3Q7s42)?f#SdU;YKH@$nPIwDd`57AW;Twpg=kPev%2BPbDWHqt0?d4>21oX=CMggggfeM93VF=<4KR3UN z^b6t=vvDmq)}sP`Q8DO?@0lY-ndO*+kU)x>pSaK|uo4*qq$-*KLgv!ohg1kk(gNG* ze`(bMq=b)S&WBVx@i$XF+viKNg8_ojQvw&E12}*FJSG;*zs?4MLH&*rYs5ifLeSp; z8`xN}D-j>i*t~x)B`0^tX&n($ft-i)A!3q}23XX#mGEuA8uvsoUs{+QJ4$LQ)SaRv z|AH^kE~t-48R3QvaJcmV$!g;`t3wX^YisvoK#U>^``}vlZUunTApb=B5)JC0yxEUE1G$csmM74XP_N z;xM7gFRj6!KcN`QXdBU@qasRb8ygSm>4ir|9u}{Ww(U^H``^ER9~!C~)28~K3ZOtH zdQ!L-*iQRPOO)(LqRBB2NC{{dKqQyN=>KgBV}*uhz<^2{gy1Q8#>$jrXo3N4*U&L@@V!0=3-Lrz=O0}gm}>ju9!@YM*O0G4yL=-lDZ6Dz z69&>hTH#lglynqQS!|+Bfv85XM$gZmHK+=+sB21~eWPGJQ4YAAv;{aS%*Qvp1PmZ#f$M5|*{m*5_mgWa0CsycnbA6*ON)u=y0Pw$&1s~^lxDW_Z^FQ_xDcn!aZu0` zl8#8sg+acfUCvg$NBQ5Z|KNbrJT-nd3 z=+cMm41F9IAI+-3O+lzXz(kYOXdn?_fj&-HM5N%N(N%mPRtOq2giQORyz&LoSxAWk zA5HWPW70D!O^-o1hMsEQ)pcxqG=>7{BuouBfc$`XU9)!GziLiTYOE5#z{v#eXr0Hx z%#1HK6iFAHo}IOeVhxCbj@lfmzS`^CIut~YV)bw!r>0lIOppzr!QD=wPtn`4=W7DV zErBSV!MGg5rKZ|iBk_2ktqpvPgx)whq}3nMsvty#DfEonis|8Jr5HGaSm2JcF*W^+ zEoJiK;N`^>G~XH>F;W;Gz#DkUK}pfb?}A8!!v$u&RykubO}W zqFH@%-IX?aRKFB=rdb@jI;yY^7hswN-h+brjtiW6r4xp_%N8r7A56{6NZFLXj8P_x z^dLmV@e`DX9}_#X1c1G3Z}X{N+>$A}T&sH_$9@FN5?xNVIub=F1(lVR*y%9lD`~M>Y!n3r z=&eF3qz*kGhcyB+EJWNp%+kQ-|LXRcz*Q$=wAl1wIWV@EvwBSBIlZEb`;uK zm?bGG31(Sa!jY<%;SDaA$?rY&R^seaKv{eKqZA~vKWPpQ0_znSdOqm8Q#roDQ2O3bqFJp zUo8(v33-b{&gfvVP3-xN>&&L6EalI4NlWG!ek)&UVhV7QvVJ)qZ)Tl!^!Z~fa%*t2 z1Ba()l(rns%0%Hnh`98GRAA~tx@zqGW3loLEx-M0!W$|UA7j>)ra@iVa!1)q7U#b} zVB!b~D`as(1@us*HvcSYv?2P zRR&P~RbJ2vZ+Gg0n(l@BAgjyDQoRPrZ9R{A^Og5~=*lv@+d1_DVMK#Td~S3!i+Yvv?C-f4VdRyiKL{be(SNA&wNHd!aJRBLWu5XU@$Q1;o;^V0nF=!u zM1MY5WCWn{OMb4L+mOs|Tz7Q0v!8yR^f;Y_u8G|COh^clws8_1#?TY~3+he8BKRCc zg{ibWhdv5(mz8UWsVsg$Iq_fVc>ND?PXVli<@58$Aj51{x8FdxS`-VDQ#g9-s?N8AAAD+b14p-_DFb_tsvEb0K*TkkB6I^ujd1E_u=Gm#sS|{=O|s^i9=; z!QYCm;q%MjRB;^Hz=$di_&m)zFFG<3A!@gEYNtWnNE^%LiL$(1x9@3uOW2`XrmS55 z?CjhzJ-xb=4-GV&YGKKWt|AnQH>!{Lk&6>d3?l;bRWHf8OXsoDN57{;`uh&Av>9HC zeQJ`LIN1N$f_E0@h1wIkL|KlWNlY39atC-7hsh)9MeMVgGc~+B+<%e$6~S#KK3BKlx^z zw$5$?UpB7V_wT==<;kOCw%Y5lLt3db(|g7{iuclZ*B=azpPOIJJYa;&h-vVgxWd?8LJ9PqTtw;R&gKOuW7C@9FN)AltvI7z&@Ne~QQ$iE99udS&`o^U~TgN@Y? z)nFnAK$z7rdS7P{7dQ%X9~fyxIEZwlf1+C zkr4?BpDhMQQz{FC=@4g(_VMz1s-jgM%gUFqnuN2n!4w zBrOW=1KB~rPlSIMh7t6t9pp(x@$e@x1qE|Au26NhFL5F4pRjq5&uV10;2K6!ii}hS zsc=$MpnHVi)6)h<|Gdh`%w*w}cfcG2C(-{sJYcPS?g}Z#MLmx=NEgb+&5d~=d2S3V z*`VbRjg`a-0b)CYTSO(kbm?#U^fC^f+9^pLp-p zL8ygC0YxF9;pU_1H4gF=7kQX}1jj@dpjYCOwzk4q;bsegEn1;z@R&|pd0w(%H?#K2 zfQMmST%sCrH0+1X^T4-2jl65;&g)TuqH1huPp7??0W6pfa^1S8(T}b~72l6xEm`0j zsY`HZ@PuK~J!l|riXGB+qqLWj$84ZYUdl)CfJcmzg616=(r1z&h%h2N*quS`0$u*;j9I4 z{*329Ti`lz=D4Y<3WdKGf7~Ja*M%$Iz(t=veRBC(zf-+N4jOVltN;`3ERw#Gj1dcG zH4S4B4|l-XJDjga$_M(K(qenXC8J)$o~-QUf+URXn)zFb$u~YLQ`Gl*P2I;7rlLZX z{jk#gmLbHitZiigNx?T#Tcpz;ZvZii=Sopf&pniR4czo#fJ{1aEGZwkcoEWU@+ea~ zo5;i2Z78egVW2zBBai<`#wdlex`#77I=4yA&HxPPzs!p*t*Ax-!=qeMijKApN}#5h zYEi~;R?n^$k%u5?=BB1LBr`X~BquN9JlMfRnN+gzDy*a!1*si}o}%%t>gwdFU(F1T zKvtfwOV+)=CHEGGH0LKV9;kH0RmMBj<15H5yrXatu?}P4wVE`vyhN33u^MkXeG z1B24hGC3fF-T3kce@&ADiBhWh>!?o>XChH)CtuztpQJmnp z_@fl8KkyLv0jmQASK_^d0PXZYlhrKgX=yl!hGc#OowbFhf;!l&Q8b}Yt2ELSg>GPH zU%z%ANT5N1e4Nx2P%vWC;g~D z_hG4EU}iv!b9B+Qs%(FV+W$4LVugal-xzDmi_`D9qrO+X(Ut;SfP;ZpA7VfAJ@_*k zwC)P(QDI>Kgy+HDY0{BL7O6H(KV@))SQE#&2Hiv^p&RpuDqcT9@=4vbkYMAWfT+SU z21oEfIyA*UYtvQg6CqxA}UDXC4Byh$g{ZjSBgrt`MJds(T>XV00|VX(wd=oY-mI8e)_MgN^gZ?}3fR3org3Y2;1 z!*RHO^p*}zQ2L-*8Fd{Hu|It&?*7~Q-?xQ?6_lhukDTo7Rl$*wPyQm`{h@=biAhRY zBu~h=UU8J?MX0>T!NV)x*3!^KZrqs$++?`;1&-O6S5A?abImb5T3ga>p*uX@(|r1S z<&f*Z?I}arMQpEV>RXYAupf88YSFACJGmE$oHZwV#WZ0_R7SZ@;iT zatBlIh~LYuoB8G{X1`oLR;riG5wls7j<5{`{9^huL?T({&GS&N47t6iaqaiLbK_7B zSDet9#J_s!%#4h95h0@hK^of=kT}mFiW&V4&z~QMNbpB*@3Z^&gSh;6{1ntp=G(m6 z`OD#tk(H|)m;6}>j%GYaq;`5{rak2Hj4Klr{>GrQp#6snWXRdYjf&~z%HRG`u_C^n z=S1&xKF;M6>}NX)em+ji?as)^II?5Peevz#g!_Cqcf^ktR;Gi{mU)u)O;0=3C~n?y zZ@SP$f1X4dEqb+$Ha6cjQI6HA`0R`I%|0S`ZcF?2aMl1BB+y2W3&kdBOEiu@q2%T#kDZLt$xQ%lZXO`9OS8da2ba8DE>(A_0qC7j> z`3#xgu8u~jI{7p~Kbv4VhJ)|}TIDrggmoQ<#>-ddzM*|Q+h~=~4bGO;sj5Ey+upgZ zHfF7bkwItO;r<>rxpTZy^oI~T^rkpMd7#uo$IIufq9PCD<$*K0jFXdt(>)=_dwRGS z>69=GVQm5`Z@aPGW0zC=yB607p=BSP8cto_pS>R&t50H|ZC<}+3Z?I?!HA4U_u#>l zoyT8w{2u6hQT#II?!@i8{tfS?TAP18sv^(${Ce^vSotfrC=bjr+6B4=f4l+65n+o7 zB`TOZWL%qZ2zubkIdbOi{#Uwlj8w9@BXkM!uMQBlZ3vWr|MlVu|K6og6_+Ei1^6RO Ogs#>>&Bq$HSN=bKBxy4M literal 17353 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 z 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 mMB}CUMZX3{Qm%)pbLxu diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png index c5372745cb597e2bbd728fcaa117abd639f956cb..d3168068ef58d289d1fff76b692d9bf2b22ae6fb 100644 GIT binary patch literal 16548 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 diff --git a/tests/drawing/cairo/test_graph.py b/tests/drawing/cairo/test_graph.py index eccd60618..31d4fdc11 100644 --- a/tests/drawing/cairo/test_graph.py +++ b/tests/drawing/cairo/test_graph.py @@ -1,9 +1,7 @@ -import os import random import unittest - -from igraph import Graph, InternalError, plot, VertexClustering +from igraph import Graph, plot, VertexClustering from igraph.drawing import find_cairo # FIXME: find a better way to do this that works for both direct call and module @@ -27,6 +25,9 @@ def setUpClass(cls): raise unittest.SkipTest("cairo not found, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) + def setUp(self) -> None: + random.seed(42) + @image_comparison(baseline_images=["graph_basic"]) def test_basic(self): g = Graph.Ring(5) @@ -66,6 +67,9 @@ def setUpClass(cls): raise unittest.SkipTest("cairo not found, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) + def setUp(self) -> None: + random.seed(42) + @image_comparison(baseline_images=["clustering_directed"]) def test_clustering_directed_small(self): g = Graph.Ring(5, directed=True) From ddeb521fab808a2b0a8cc5521e34405db849eea8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 23 Mar 2023 15:26:50 +0100 Subject: [PATCH 1231/1892] feat: added granular loop edge handling for Graph.Adjacency() and Graph.Weighted_Adjacency(), fixes #647 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b00f57ef..a791d6de1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ contains an extra property named `quality` that stores the value of the internal quality function optimized by the algorithm. +- `Graph.Adjacency()` and `Graph.Weighted_Adjacency()` now supports + `loops="once"`, `loops="twice"` and `loops="ignore"` to control how loop + edges are handled in a more granular way. `loops=True` and `loops=False` + keep on working as in earlier versions. + ### Fixed - `resolution` parameter is now correctly taken into account when calling From 79f87354450e7b95b55905ce69e0f7f8c26617f6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 24 Mar 2023 17:57:47 +0100 Subject: [PATCH 1232/1892] feat: added granular loop edge handling for Graph.Adjacency() and Graph.Weighted_Adjacency(), fixes #647 --- src/igraph/io/adjacency.py | 21 +++-- src/igraph/sparse_matrix.py | 108 ++++++++++++++------- tests/test_generators.py | 181 +++++++++++++++++++++++++++++++++++- 3 files changed, 269 insertions(+), 41 deletions(-) diff --git a/src/igraph/io/adjacency.py b/src/igraph/io/adjacency.py index 940402869..5f4c3a5c4 100644 --- a/src/igraph/io/adjacency.py +++ b/src/igraph/io/adjacency.py @@ -4,7 +4,7 @@ ) -def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwargs): +def _construct_graph_from_adjacency(cls, matrix, mode="directed", loops="once"): """Generates a graph from its adjacency matrix. @param matrix: the adjacency matrix. Possible types are: @@ -26,6 +26,11 @@ def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwarg the matrix (including the diagonal) - C{"lower"} - undirected graph with the lower left triangle of the matrix (including the diagonal) + @param loops: specifies how to handle loop edges. When C{False} or + C{"ignore"}, the diagonal of the adjacency matrix will be ignored. When + C{True} or C{"once"}, the diagonal is assumed to contain the multiplicity + of the corresponding loop edge. When C{"twice"}, the diagonal is assumed + to contain I{twice} the multiplicity of the corresponding loop edge. """ # Deferred import to avoid cycles from igraph import Graph @@ -46,7 +51,7 @@ def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwarg pd = None if (sparse is not None) and isinstance(matrix, sparse.spmatrix): - return _graph_from_sparse_matrix(cls, matrix, mode=mode) + return _graph_from_sparse_matrix(cls, matrix, mode=mode, loops=loops) if (pd is not None) and isinstance(matrix, pd.DataFrame): vertex_names = matrix.index.tolist() @@ -57,7 +62,7 @@ def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwarg if (np is not None) and isinstance(matrix, np.ndarray): matrix = matrix.tolist() - graph = super(Graph, cls).Adjacency(matrix, mode=mode) + graph = super(Graph, cls).Adjacency(matrix, mode=mode, loops=loops) # Add vertex names if present if vertex_names is not None: @@ -67,7 +72,7 @@ def _construct_graph_from_adjacency(cls, matrix, mode="directed", *args, **kwarg def _construct_graph_from_weighted_adjacency( - cls, matrix, mode="directed", attr="weight", loops=True + cls, matrix, mode="directed", attr="weight", loops="once" ): """Generates a graph from its weighted adjacency matrix. @@ -92,9 +97,11 @@ def _construct_graph_from_weighted_adjacency( These values can also be given as strings without the C{ADJ} prefix. @param attr: the name of the edge attribute that stores the edge weights. - @param loops: whether to include loop edges. When C{False}, the diagonal - of the adjacency matrix will be ignored. - + @param loops: specifies how to handle loop edges. When C{False} or + C{"ignore"}, the diagonal of the adjacency matrix will be ignored. When + C{True} or C{"once"}, the diagonal is assumed to contain the weight of the + corresponding loop edge. When C{"twice"}, the diagonal is assumed to + contain I{twice} the weight of the corresponding loop edge. """ # Deferred import to avoid cycles from igraph import Graph diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index bcf5436fe..82a7b7120 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -47,10 +47,37 @@ def _convert_mode_argument(mode): return mode +def _maybe_halve_diagonal(m, condition): + """Halves all items in the diagonal of the given SciPy sparse matrix in + coo mode _if_ and _only if_ the given condition is True. + + Returns the row, column and data arrays. + """ + data_array = m.data + if condition: + # We can't do data_array[m.row == m.col] /= 2 here because we would be + # modifying the array in-place and the end user wouldn't like if we + # messed with their matrix. So we make a copy. + data_array = data_array.copy() + idxs, = (m.row == m.col).nonzero() + for i in idxs: + data_array[i] /= 2 + + return m.row, m.col, data_array + + # Logic to get graph from scipy sparse matrix. This would be simple if there # weren't so many modes. -def _graph_from_sparse_matrix(klass, matrix, mode="directed"): - """Construct graph from sparse matrix, unweighted""" +def _graph_from_sparse_matrix(klass, matrix, mode="directed", loops="once"): + """Construct graph from sparse matrix, unweighted. + + @param loops: specifies how the diagonal of the matrix should be handled: + + - C{"ignore"} - ignore loop edges in the diagonal + - C{"once"} - treat the diagonal entries as loop edge counts + - C{"twice"} - treat the diagonal entries as I{twice} the number + of loop edges + """ # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. from scipy import sparse @@ -67,16 +94,21 @@ def _graph_from_sparse_matrix(klass, matrix, mode="directed"): mode = _convert_mode_argument(mode) + keep_loops = (loops == "twice" or loops == "once" or loops is True) + m_row, m_col, m_data = _maybe_halve_diagonal(m, loops == "twice") + if mode == "directed": - edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data)), - [], - ) + edges = [] + for i, j, n in zip(m_row, m_col, m_data): + if i != j or keep_loops: + edges.extend([(i, j)] * n) elif mode in ("max", "plus"): fun = max if mode == "max" else add nedges = {} - for i, j, n in zip(m.row, m.col, m.data): + for i, j, n in zip(m_row, m_col, m_data): + if i == j and not keep_loops: + continue pair = (i, j) if i < j else (j, i) nedges[pair] = fun(nedges.get(pair, 0), n) @@ -86,12 +118,12 @@ def _graph_from_sparse_matrix(klass, matrix, mode="directed"): ) elif mode == "min": - tmp = {(i, j): n for i, j, n in zip(m.row, m.col, m.data)} + tmp = {(i, j): n for i, j, n in zip(m_row, m_col, m_data)} nedges = {} for pair, weight in tmp.items(): i, j = pair - if i == j: + if i == j and keep_loops: nedges[pair] = weight elif i < j: nedges[pair] = min(weight, tmp.get((j, i), 0)) @@ -102,30 +134,36 @@ def _graph_from_sparse_matrix(klass, matrix, mode="directed"): ) elif mode == "upper": - edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j >= i), - [], - ) + edges = [] + for i, j, n in zip(m_row, m_col, m_data): + if j > i or (keep_loops and j == i): + edges.extend([(i, j)] * n) elif mode == "lower": - edges = sum( - ([(i, j)] * n for i, j, n in zip(m.row, m.col, m.data) if j <= i), - [], - ) + edges = [] + for i, j, n in zip(m_row, m_col, m_data): + if j < i or (keep_loops and j == i): + edges.extend([(i, j)] * n) else: - raise ValueError("invalid mode") + raise ValueError(f"invalid mode: {mode!r}") return klass(nvert, edges=edges, directed=(mode == "directed")) def _graph_from_weighted_sparse_matrix( - klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops=True + klass, matrix, mode=ADJ_DIRECTED, attr="weight", loops="once" ): """Construct graph from sparse matrix, weighted NOTE: Of course, you cannot emcompass a fully general weighted multigraph with a single adjacency matrix, so we don't try to do it here either. + + @param loops: specifies how to handle loop edges. When C{False} or + C{"ignore"}, the diagonal of the adjacency matrix will be ignored. When + C{True} or C{"once"}, the diagonal is assumed to contain the weight of the + corresponding loop edge. When C{"twice"}, the diagonal is assumed to + contain I{twice} the weight of the corresponding loop edge. """ # This function assumes there is scipy and the matrix is a scipy sparse # matrix. The caller should make sure those conditions are met. @@ -143,35 +181,39 @@ def _graph_from_weighted_sparse_matrix( mode = _convert_mode_argument(mode) + keep_loops = (loops == "twice" or loops == "once" or loops is True) + m_row, m_col, m_data = _maybe_halve_diagonal(m, loops == "twice") + if mode == "directed": - if not loops: + if not keep_loops: edges, weights = [], [] - for i, j, n in zip(m.row, m.col, m.data): + for i, j, n in zip(m_row, m_col, m_data): if i != j: edges.append((i, j)) weights.append(n) - else: - edges = list(zip(m.row, m.col)) - weights = list(m.data) + else: # loops == "once" or True + edges = list(zip(m_row, m_col)) + weights = list(m_data) elif mode in ("max", "plus"): fun = max if mode == "max" else add nedges = {} - for i, j, n in zip(m.row, m.col, m.data): - if i == j and not loops: + for i, j, n in zip(m_row, m_col, m_data): + if i == j and not keep_loops: continue + pair = (i, j) if i < j else (j, i) nedges[pair] = fun(nedges.get(pair, 0), n) edges, weights = zip(*nedges.items()) elif mode == "min": - tmp = {(i, j): n for i, j, n in zip(m.row, m.col, m.data)} + tmp = {(i, j): n for i, j, n in zip(m_row, m_col, m_data)} nedges = {} for pair, weight in tmp.items(): i, j = pair - if i == j and loops: + if i == j and keep_loops: nedges[pair] = weight elif i < j: nedges[pair] = min(weight, tmp.get((j, i), 0)) @@ -185,20 +227,20 @@ def _graph_from_weighted_sparse_matrix( elif mode == "upper": edges, weights = [], [] - for i, j, n in zip(m.row, m.col, m.data): - if j > i or (loops and j == i): + for i, j, n in zip(m_row, m_col, m_data): + if j > i or (keep_loops and j == i): edges.append((i, j)) weights.append(n) elif mode == "lower": edges, weights = [], [] - for i, j, n in zip(m.row, m.col, m.data): - if j < i or (loops and j == i): + for i, j, n in zip(m_row, m_col, m_data): + if j < i or (keep_loops and j == i): edges.append((i, j)) weights.append(n) else: - raise ValueError("invalid mode") + raise ValueError(f"invalid mode: {mode!r}") return klass( nvert, edges=edges, directed=(mode == "directed"), edge_attrs={attr: weights} diff --git a/tests/test_generators.py b/tests/test_generators.py index 26c8cae61..25bfb56d9 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -362,11 +362,95 @@ def testAdjacencyNumPy(self): el = g.get_edgelist() self.assertTrue(el == [(0, 1), (2, 2), (2, 2)]) + # ADJ MAX + g = Graph.Adjacency(mat, mode="max") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2), (2, 2)]) + # ADJ LOWER g = Graph.Adjacency(mat, mode="lower") el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (2, 2), (2, 2), (1, 3)]) + # ADJ UPPER + g = Graph.Adjacency(mat, mode="upper") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2), (2, 2)]) + + @unittest.skipIf(np is None, "test case depends on NumPy") + def testAdjacencyNumPyLoopHandling(self): + mat = np.array( + [[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 2, 0], [0, 1, 0, 0]], + ) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (2, 2), (3, 1)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min", loops="twice") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (2, 2)]) + + # ADJ MAX + g = Graph.Adjacency(mat, mode="max", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 3), (2, 2)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (2, 2), (1, 3)]) + + # ADJ UPPER + g = Graph.Adjacency(mat, mode="upper", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2)]) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat, loops=False) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min", loops=False) + el = g.get_edgelist() + self.assertTrue(el == [(0, 1)]) + + # ADJ MAX + g = Graph.Adjacency(mat, mode="max", loops=False) + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 3)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower", loops=False) + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (1, 3)]) + + # ADJ UPPER + g = Graph.Adjacency(mat, mode="upper", loops=False) + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2)]) + @unittest.skipIf( (sparse is None) or (np is None), "test case depends on NumPy/SciPy" ) @@ -389,6 +473,13 @@ def testSparseAdjacency(self): self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (2, 2), (2, 2)]) + # ADJ MAX + g = Graph.Adjacency(mat, mode="max") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2), (2, 2), (1, 3)]) + # ADJ LOWER g = Graph.Adjacency(mat, mode="lower") el = g.get_edgelist() @@ -396,6 +487,77 @@ def testSparseAdjacency(self): self.assertEqual(4, g.vcount()) self.assertTrue(el == [(0, 1), (2, 2), (2, 2), (1, 3)]) + # ADJ UPPER + g = Graph.Adjacency(mat, mode="upper") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2), (2, 2)]) + + @unittest.skipIf( + (sparse is None) or (np is None), "test case depends on NumPy/SciPy" + ) + def testSparseAdjacencyLoopHandling(self): + mat = sparse.coo_matrix( + [[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 2, 0], [0, 1, 0, 0]], + ) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat, loops=False) + el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min", loops=False) + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower", loops=False) + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (1, 3)]) + + # ADJ_DIRECTED (default) + g = Graph.Adjacency(mat, loops="twice") + el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + + # ADJ MAX + g = Graph.Adjacency(mat, mode="max", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2), (1, 3)]) + + # ADJ MIN + g = Graph.Adjacency(mat, mode="min", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (2, 2)]) + + # ADJ LOWER + g = Graph.Adjacency(mat, mode="lower", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (2, 2), (1, 3)]) + + # ADJ UPPER + g = Graph.Adjacency(mat, mode="upper", loops="twice") + el = g.get_edgelist() + self.assertFalse(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (2, 2)]) + def testWeightedAdjacency(self): mat = [[0, 1, 2, 0], [2, 0, 0, 0], [0, 0, 2.5, 0], [0, 1, 0, 0]] @@ -414,6 +576,11 @@ def testWeightedAdjacency(self): self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + g = Graph.Weighted_Adjacency(mat, attr="w0", loops="twice") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 1.25, 1]) + @unittest.skipIf(np is None, "test case depends on NumPy") def testWeightedAdjacencyNumPy(self): mat = np.array( @@ -435,10 +602,15 @@ def testWeightedAdjacencyNumPy(self): self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + g = Graph.Weighted_Adjacency(mat, attr="w0", loops="twice") + el = g.get_edgelist() + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 1.25, 1]) + @unittest.skipIf( (sparse is None) or (np is None), "test case depends on NumPy/SciPy" ) - def testSparseWeighedAdjacency(self): + def testSparseWeightedAdjacency(self): mat = sparse.coo_matrix( [[0, 1, 2, 0], [2, 0, 0, 0], [0, 0, 2.5, 0], [0, 1, 0, 0]] ) @@ -471,6 +643,13 @@ def testSparseWeighedAdjacency(self): self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (3, 1)]) self.assertTrue(g.es["w0"] == [1, 2, 2, 1]) + g = Graph.Weighted_Adjacency(mat, attr="w0", loops="twice") + el = g.get_edgelist() + self.assertTrue(g.is_directed()) + self.assertEqual(4, g.vcount()) + self.assertTrue(el == [(0, 1), (0, 2), (1, 0), (2, 2), (3, 1)]) + self.assertTrue(g.es["w0"] == [1, 2, 2, 1.25, 1]) + @unittest.skipIf((np is None) or (pd is None), "test case depends on NumPy/Pandas") def testDataFrame(self): edges = pd.DataFrame( From c8efd805c96dc3364fe8d38bc481765dc1eb687a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 24 Mar 2023 18:12:15 +0100 Subject: [PATCH 1233/1892] feat: added Graph.get_shortest_path() convenience function --- CHANGELOG.md | 3 ++ src/_igraph/graphobject.c | 85 +++++++++++++++++++++++++++++++++++++-- tests/test_structural.py | 8 ++++ 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a791d6de1..06aa43232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ edges are handled in a more granular way. `loops=True` and `loops=False` keep on working as in earlier versions. +- Added `Graph.get_shortest_path()` as a convenience function for cases when + only one shortest path is needed between a given source and target vertices. + ### Fixed - `resolution` parameter is now correctly taken into account when calling diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 5f27d40e3..477b0ae11 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5118,6 +5118,67 @@ PyObject *igraphmodule_Graph_feedback_arc_set( } +/** \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 + * \sa igraph_get_shortest_path + */ +PyObject *igraphmodule_Graph_get_shortest_path( + igraphmodule_GraphObject *self, PyObject *args, PyObject * kwds +) { + static char *kwlist[] = { "v", "to", "weights", "mode", "output", NULL }; + igraph_vector_t *weights=0; + igraph_neimode_t mode = IGRAPH_OUT; + igraph_integer_t from, to; + PyObject *list, *mode_o=Py_None, *weights_o=Py_None, + *output_o=Py_None, *from_o = Py_None, *to_o=Py_None; + igraph_vector_int_t vec; + igraph_bool_t use_edges = false; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO!", kwlist, &from_o, + &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) + return NULL; + + if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) + return NULL; + + if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_vid(to_o, &to, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + return NULL; + + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, + ATTRIBUTE_TYPE_EDGE)) return NULL; + + if (igraph_vector_int_init(&vec, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + /* Call the C function */ + if (igraph_get_shortest_path_dijkstra(&self->g, use_edges ? 0 : &vec, + use_edges ? &vec : 0, from, to, weights, mode)) { + igraph_vector_int_destroy(&vec); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + /* We don't need these anymore, the result is in vec */ + if (weights) { igraph_vector_destroy(weights); free(weights); } + + /* Convert to Python list of paths */ + list = igraphmodule_vector_int_t_to_PyList(&vec); + igraph_vector_int_destroy(&vec); + + return list ? list : NULL; +} + + /** \ingroup python_interface_graph * \brief Calculates the shortest paths from/to a given node in the graph * \return a list containing shortest paths from/to the given node @@ -5194,8 +5255,6 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * list = igraphmodule_vector_int_list_t_to_PyList(&veclist); igraph_vector_int_list_destroy(&veclist); return list ? list : NULL; - - return list; } /** \ingroup python_interface_graph @@ -14453,7 +14512,27 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " feedback arc set problem. In: Proc Inf Process Lett 319-323, 1993.\n" }, - // interface to igraph_get_shortest_paths + /* interface to igraph_get_shortest_path */ + {"get_shortest_path", (PyCFunction) igraphmodule_Graph_get_shortest_path, + METH_VARARGS | METH_KEYWORDS, + "get_shortest_path(v, to, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "Calculates the shortest path from a source vertex to a target vertex in a graph.\n\n" + "@param v: the source vertex of the path\n" + "@param to: the target vertex of the path\n" + "@param weights: edge weights in a list or the name of an edge attribute\n" + " holding edge weights. If C{None}, all edges are assumed to have\n" + " equal weight.\n" + "@param mode: the directionality of the paths. C{\"out\"} means to\n" + " calculate paths from source to target, following edges according to\n" + " their natural direction. C{\"in\"} means to calculate paths from target\n" + " to source, flipping the direction of each edge on-the-fly. C{\"all\"}\n" + " means to ignore edge directions.\n" + "@param output: determines what should be returned. If this is\n" + " C{\"vpath\"}, a list of vertex IDs will be returned. If this is\n" + " C{\"epath\"}, edge IDs are returned instead of vertex IDs.\n" + "@return: see the documentation of the C{output} parameter.\n"}, + + /* interface to igraph_get_shortest_paths */ {"get_shortest_paths", (PyCFunction) igraphmodule_Graph_get_shortest_paths, METH_VARARGS | METH_KEYWORDS, "get_shortest_paths(v, to=None, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" diff --git a/tests/test_structural.py b/tests/test_structural.py index 557398859..67b183398 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -787,6 +787,14 @@ def testDistances(self): == [row[2:4] for row in expected] ) + def testGetShortestPath(self): + g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) + self.assertEqual([0, 1, 3], g.get_shortest_path(0, 3)) + self.assertEqual([0, 1, 3], g.get_shortest_path(0, 3, output="vpath")) + self.assertEqual([0, 2], g.get_shortest_path(0, 3, output="epath")) + self.assertRaises(ValueError, g.get_shortest_path, 0, 3, output="x") + self.assertRaises(TypeError, g.get_shortest_path, 0) + def testGetShortestPaths(self): g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) sps = g.get_shortest_paths(0) From 22484a9fdfae4534745cdf7170499be32c4383db Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 24 Mar 2023 18:39:33 +0100 Subject: [PATCH 1234/1892] feat: added Graph.get_shortest_path_astar() --- src/_igraph/graphobject.c | 139 ++++++++++++++++++++++++++++++++++++++ tests/test_structural.py | 32 ++++++--- 2 files changed, 163 insertions(+), 8 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 477b0ae11..8986018e1 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -5178,6 +5178,118 @@ PyObject *igraphmodule_Graph_get_shortest_path( return list ? list : NULL; } +typedef struct { + PyObject* func; + PyObject* graph; +} igraphmodule_i_Graph_get_shortest_path_astar_callback_data_t; + +igraph_error_t igraphmodule_i_Graph_get_shortest_path_astar_callback( + igraph_real_t *result, igraph_integer_t from, igraph_integer_t to, + void *extra +) { + igraphmodule_i_Graph_get_shortest_path_astar_callback_data_t* data = + (igraphmodule_i_Graph_get_shortest_path_astar_callback_data_t*)extra; + PyObject* from_o; + PyObject* to_o; + PyObject* result_o; + + from_o = igraphmodule_integer_t_to_PyObject(from); + if (from_o == NULL) { + /* Error in conversion, return 1 */ + return IGRAPH_FAILURE; + } + + to_o = igraphmodule_integer_t_to_PyObject(to); + if (to_o == NULL) { + /* Error in conversion, return 1 */ + return IGRAPH_FAILURE; + } + + result_o = PyObject_CallFunction(data->func, "OOO", data->graph, from_o, to_o); + Py_DECREF(from_o); + Py_DECREF(to_o); + + if (result_o == NULL) { + /* Error in callback, return 1 */ + return IGRAPH_FAILURE; + } + + if (igraphmodule_PyObject_to_real_t(result_o, result)) { + /* Error in conversion, return 1 */ + return IGRAPH_FAILURE; + } + + return IGRAPH_SUCCESS; +} + +/** \ingroup python_interface_graph + * \brief Calculates a single shortest path between a source and a target vertex using the A-star algorithm + * \return a list containing a single shortest path from the source to the target + * \sa igraph_get_shortest_path_astar + */ +PyObject *igraphmodule_Graph_get_shortest_path_astar( + igraphmodule_GraphObject *self, PyObject *args, PyObject * kwds +) { + static char *kwlist[] = { "v", "to", "heuristics", "weights", "mode", "output", NULL }; + igraph_vector_t *weights=0; + igraph_neimode_t mode = IGRAPH_OUT; + igraph_integer_t from, to; + PyObject *list, *mode_o=Py_None, *weights_o=Py_None, + *output_o=Py_None, *from_o = Py_None, *to_o=Py_None, + *heuristics_o; + igraph_vector_int_t vec; + igraph_bool_t use_edges = false; + igraphmodule_i_Graph_get_shortest_path_astar_callback_data_t extra; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|OOO!", kwlist, &from_o, + &to_o, &heuristics_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) + return NULL; + + if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) + return NULL; + + if (igraphmodule_PyObject_to_vid(from_o, &from, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_vid(to_o, &to, &self->g)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + return NULL; + + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, + ATTRIBUTE_TYPE_EDGE)) return NULL; + + if (igraph_vector_int_init(&vec, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + extra.func = heuristics_o; + extra.graph = (PyObject*) self; + + /* Call the C function */ + if (igraph_get_shortest_path_astar(&self->g, use_edges ? 0 : &vec, + use_edges ? &vec : 0, from, to, weights, mode, + igraphmodule_i_Graph_get_shortest_path_astar_callback, + &extra + )) { + igraph_vector_int_destroy(&vec); + if (weights) { igraph_vector_destroy(weights); free(weights); } + igraphmodule_handle_igraph_error(); + return NULL; + } + + /* We don't need these anymore, the result is in vec */ + if (weights) { igraph_vector_destroy(weights); free(weights); } + + /* Convert to Python list of paths */ + list = igraphmodule_vector_int_t_to_PyList(&vec); + igraph_vector_int_destroy(&vec); + + return list ? list : NULL; +} + /** \ingroup python_interface_graph * \brief Calculates the shortest paths from/to a given node in the graph @@ -14603,6 +14715,33 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " argument). Note that in case of mode=C{\"in\"},\n" " the vertices in a path are returned in reversed order!"}, + /* interface to igraph_get_shortest_path_astar */ + {"get_shortest_path_astar", (PyCFunction) igraphmodule_Graph_get_shortest_path_astar, + METH_VARARGS | METH_KEYWORDS, + "get_shortest_path(v, to, heuristics, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "Calculates the shortest path from a source vertex to a target vertex in a\n" + "graph using the A-Star algorithm and a heuristic function.\n\n" + "@param v: the source vertex of the path\n" + "@param to: the target vertex of the path\n" + "@param heuristics: a function that will be called with the graph and two\n" + " vertices, and must return an estimate of the cost of the path from the\n" + " first vertex to the second vertex. The A-Star algorithm is guaranteed to\n" + " return an optimal solution if the heuristic is I{admissible}, i.e. if it\n" + " does never overestimate the cost of the shortest path from the given\n" + " source vertex to the given target vertex.\n" + "@param weights: edge weights in a list or the name of an edge attribute\n" + " holding edge weights. If C{None}, all edges are assumed to have\n" + " equal weight.\n" + "@param mode: the directionality of the paths. C{\"out\"} means to\n" + " calculate paths from source to target, following edges according to\n" + " their natural direction. C{\"in\"} means to calculate paths from target\n" + " to source, flipping the direction of each edge on-the-fly. C{\"all\"}\n" + " means to ignore edge directions.\n" + "@param output: determines what should be returned. If this is\n" + " C{\"vpath\"}, a list of vertex IDs will be returned. If this is\n" + " C{\"epath\"}, edge IDs are returned instead of vertex IDs.\n" + "@return: see the documentation of the C{output} parameter.\n"}, + /* interface to igraph_get_all_simple_paths */ {"_get_all_simple_paths", (PyCFunction) igraphmodule_Graph_get_all_simple_paths, diff --git a/tests/test_structural.py b/tests/test_structural.py index 67b183398..afe6413da 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -868,21 +868,21 @@ def testGetAllShortestPaths(self): def testGetKShortestPaths(self): g = Graph(4, [(0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5)], directed=True) - + sps = sorted(g.get_k_shortest_paths(0, 0)) expected = [[0]] self.assertEqual(expected, sps) - + sps = sorted(g.get_k_shortest_paths(0, 5, 2)) expected = [[0, 1, 2, 4, 5], [0, 1, 3, 4, 5]] self.assertEqual(expected, sps) - + sps = sorted(g.get_k_shortest_paths(1, 4, 2)) expected = [[1, 2, 4], [1, 3, 4]] self.assertEqual(expected, sps) - + g = Graph.Lattice([5, 5], circular=False) - + sps = sorted(g.get_k_shortest_paths(0, 12, 6)) expected = [ [0, 1, 2, 7, 12], @@ -893,7 +893,7 @@ def testGetKShortestPaths(self): [0, 5, 10, 11, 12], ] self.assertEqual(expected, sps) - + g = Graph.Lattice([100, 100], circular=False) sps = sorted(g.get_k_shortest_paths(0, 202, 6)) expected = [ @@ -905,12 +905,12 @@ def testGetKShortestPaths(self): [0, 100, 200, 201, 202], ] self.assertEqual(expected, sps) - + g = Graph([(0, 1), (1, 2), (0, 2)]) g.es["weight"] = [0.5, 0.5, 1] sps = sorted(g.get_k_shortest_paths(0, 2, 2, weights="weight")) self.assertEqual(sorted([[0, 2], [0, 1, 2]]), sorted(sps)) - + def testGetAllSimplePaths(self): g = Graph.Ring(20) sps = sorted(g.get_all_simple_paths(0, 10)) @@ -965,6 +965,22 @@ def testPathLengthHist(self): h = g.path_length_hist(False) self.assertTrue(h.unconnected == 20) + def testGetShortestPathsAStar(self): + n = 4 + g = Graph.Lattice((n, n), circular=False) + xs, ys = list(range(n)) * n, sum(([i] * n for i in range(n)), []) + g.vs["coord"] = list(zip(xs, ys)) + + def heuristics(graph, u, v): + ux, uy = graph.vs[u]["coord"] + vx, vy = graph.vs[v]["coord"] + return ((ux - vx) ** 2 + (uy - vy) ** 2) ** 0.5 + + self.assertEqual( + [0, 1, 5, 6, 10, 11], + g.get_shortest_path_astar(0, 11, heuristics) + ) + class DominatorTests(unittest.TestCase): def compareDomTrees(self, alist, blist): From fcde6bdd012701553516ae71ab52f4545b77843b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 24 Mar 2023 18:41:02 +0100 Subject: [PATCH 1235/1892] chore: updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06aa43232..0d15855ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ - Added `Graph.get_shortest_path()` as a convenience function for cases when only one shortest path is needed between a given source and target vertices. +- Added `Graph.get_shortest_path_astar()` to calculate the shortest path + between two vertices using the A-star algorithm and an appropriate + heuristic function. + ### Fixed - `resolution` parameter is now correctly taken into account when calling From f35a35e04ca186cb78191d7a540b4c50bc5f09c2 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 25 Mar 2023 10:38:07 +0100 Subject: [PATCH 1236/1892] feat: VertexCover constructor now accepts vertex names, closes #617 --- CHANGELOG.md | 3 +++ src/igraph/clustering.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d15855ec..a66ffaaef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ between two vertices using the A-star algorithm and an appropriate heuristic function. +- The `VertexCover` constructor now allows referring to vertices by names + instead of IDs. + ### Fixed - `resolution` parameter is now correctly taken into account when calling diff --git a/src/igraph/clustering.py b/src/igraph/clustering.py index c4b345a47..42e224a86 100644 --- a/src/igraph/clustering.py +++ b/src/igraph/clustering.py @@ -1089,6 +1089,8 @@ def __init__(self, graph, clusters=None): if clusters is None: clusters = [range(graph.vcount())] + self._resolve_names_in_clusters(graph, clusters) + super().__init__(clusters, n=graph.vcount()) if self._n > graph.vcount(): raise ValueError( @@ -1216,6 +1218,24 @@ def _formatted_cluster_iterator(self): for cluster in self: yield ", ".join(str(member) for member in cluster) + @staticmethod + def _resolve_names_in_clusters(graph, clusters): + if not graph.is_named(): + return + + names = graph.vs["name"] + name_to_index = dict((k, v) for v, k in enumerate(names)) + + for idx, cluster in enumerate(clusters): + if any(isinstance(item, str) for item in cluster): + new_cluster = [] + for item in cluster: + if isinstance(item, str): + new_cluster.append(name_to_index.get(item, item)) + else: + new_cluster.append(item) + clusters[idx] = new_cluster + class CohesiveBlocks(VertexCover): """The cohesive block structure of a graph. From bbe93df7f2b1c7b7406688e9f806881d18fccb2f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 4 Apr 2023 14:41:29 +1000 Subject: [PATCH 1237/1892] First blobs of code --- src/igraph/drawing/__init__.py | 6 +- src/igraph/drawing/matplotlib/graph.py | 162 ++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 5ae708ccc..ec1a8168f 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -41,7 +41,10 @@ from igraph.drawing.cairo.matrix import CairoMatrixDrawer from igraph.drawing.cairo.histogram import CairoHistogramDrawer from igraph.drawing.cairo.palette import CairoPaletteDrawer -from igraph.drawing.matplotlib.graph import MatplotlibGraphDrawer +from igraph.drawing.matplotlib.graph import ( + MatplotlibGraphDrawer, + GraphArtist, +) from igraph.drawing.matplotlib.matrix import MatplotlibMatrixDrawer from igraph.drawing.matplotlib.histogram import MatplotlibHistogramDrawer from igraph.drawing.matplotlib.palette import MatplotlibPaletteDrawer @@ -54,6 +57,7 @@ "BoundingBox", "CairoGraphDrawer", "MatplotlibGraphDrawer", + "GraphArtist", "DefaultGraphDrawer", "Plot", "Point", diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 6673929ff..a3dd32de7 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -24,13 +24,171 @@ from .utils import find_matplotlib from .vertex import MatplotlibVertexDrawer -__all__ = ("MatplotlibGraphDrawer",) +__all__ = ( + "MatplotlibGraphDrawer", + "GraphArtist", + ) -_, plt = find_matplotlib() +mpl, plt = find_matplotlib() ##################################################################### +# NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py +class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): + """Artist for an igraph.Graph object. + + Arguments: + graph: An igraph.Graph object to plot + layout: A layout object or matrix of coordinates to use for plotting. + Each element or row should describes the coordinates for a vertex. + vertex_style: A dictionary specifying style options for vertices. + edge_style: A dictionary specifying style options for edges. + """ + def __init__( + self, + graph, + layout=None, + vertex_style=None, + edge_style=None, + vertex_label_style=None, + edge_label_style=None, + **kwargs, + ): + + super().__init__() + self.graph = graph + self.layout = self.ensure_layout(layout) + self.vertex_style = vertex_style + self.edge_style = edge_style + self.vertex_label_style = vertex_label_style + self.edge_label_style = edge_label_style + + self._clear_state() + + def _clear_state(self): + self._vertex_artist = None + self._vertex_indx = None + self._edge_artist = None + self._edge_indx = None + self._vertex_labels = None + self._edge_labels = None + + def get_children(self): + artists = [self._vertex_artist, self._edge_artist] + if self._vertex_labels is not None: + artists.extend(self._vertex_labels) + if self._edge_labels is not None: + artists.extend(self._edge_labels) + return tuple(a for a in artists if a is not None) + + def get_datalim(self): + import numpy as np + + mins = np.min(self.layout, axis=0) + maxs = np.max(self.layout, axis=0) + + return (mins, maxs) + + def _reprocess(self, *): + """Process the actual drawing.""" + # nuke old state and mark as stale + self._clear_state() + self.stale = True + + # get local refs to everything (just for less typing) + graph = self.graph + edge_style = self.edge_style + vertex_style = self.vertex_style + edge_label_style = self.edge_label_style + vertex_label_style = self.vertex_label_style + + # get the layout + pos = self.layout.coords + + # handle the edges + edge_style_dict = generate_edge_styles(graph, edge_style) + self._edge_artist, self._edge_indx = ( + _generate_straight_edges(graph.edges(), pos, + edge_style_dict, ax=self.axes)) + + # handle the nodes + vertex_style_dict = generate_node_styles(graph, node_style) + self._vertex_artist, self._vertex_indx = ( + _generate_vertex_artist(pos, vertex_style_dict, ax=self.axes)) + + # TODO handle the text + + # handle the node labels + if vertex_label_style is not None: + vlabel_style_dict = generate_vertex_label_styles( + graph, + vertex_label_style) + self._vertex_label_dict = ( + _generate_vertex_labels(pos, vlabel_style_dict, ax=self.axes)) + + # handle the edge labels + if edge_label_style is not None: + elabel_style_dict = generate_edge_label_styles(graph, + edge_label_style) + self._edge_label_dict = ( + _generate_edge_labels(pos, elabel_style_dict, ax=self.axes)) + + # TODO sort out all of the things that need to be forwarded + for child in self.get_children(): + # set the figure / axes on child, this is needed + # by some internals + child.set_figure(self.figure) + child.axes = self.axes + # forward the clippath/box to the children need this logic + # because mpl exposes some fast-path logic + clip_path = self.get_clip_path() + if clip_path is None: + clip_box = self.get_clip_box() + child.set_clip_box(clip_box) + else: + child.set_clip_path(clip_path) + + @_stale_wrapper + def draw(self, renderer, *args, **kwargs): + """Draw each of the children, with some buffering mechanism.""" + if not self.get_visible(): + return + + if not self.get_children(): + self._reprocess() + + elif self.stale: + self._reprocess(reset_pos=False) + + for art in self.get_children(): + art.draw(renderer, *args, **kwargs) + + def contains(self, mouseevent): + """Track 'contains' event for mouse interactions.""" + props = {} + edge_hit, edge_props = self._edge_artist.contains(mouseevent) + vertex_hit, vertex_props = self._vertex_artist.contains(mouseevent) + props['vertices'] = [self._node_indx[j] + for j in vertex_props.get('ind', [])] + props['edges'] = [self._edge_indx[j] + for j in edge_props.get('ind', [])] + + return edge_hit | node_hit, props + + def pick(self, mouseevent): + """Track 'pick' event for mouse interactions.""" + # Pick self + if self.pickable(): + picker = self.get_picker() + if callable(picker): + inside, prop = picker(self, mouseevent) + else: + inside, prop = self.contains(mouseevent) + if inside: + self.figure.canvas.pick_event(mouseevent, self, **prop) + + class MatplotlibGraphDrawer(AbstractGraphDrawer): """Graph drawer that uses a pyplot.Axes as context""" From df01256a3553fcbf8b0677e02851f9eef1dec3f6 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 4 Apr 2023 14:57:47 +1000 Subject: [PATCH 1238/1892] A bit more logic --- src/igraph/drawing/matplotlib/graph.py | 28 +++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index a3dd32de7..86e0647b5 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -73,6 +73,7 @@ def _clear_state(self): self._edge_indx = None self._vertex_labels = None self._edge_labels = None + self._group_artist = None def get_children(self): artists = [self._vertex_artist, self._edge_artist] @@ -80,8 +81,25 @@ def get_children(self): artists.extend(self._vertex_labels) if self._edge_labels is not None: artists.extend(self._edge_labels) + if self._group_artist is not None: + artists.extend(self._group_artist) return tuple(a for a in artists if a is not None) + def get_vertices(self): + return self._vertex_artist + + def get_edges(seff): + return self._edge_artist + + def get_groups(self): + return self._group_artist + + def get_vertex_labels(self): + return self._vertex_labels + + def get_edge_labels(self): + return self._edge_labels + def get_datalim(self): import numpy as np @@ -91,7 +109,11 @@ def get_datalim(self): return (mins, maxs) def _reprocess(self, *): - """Process the actual drawing.""" + """Prepare artist and children for the actual drawing. + + Children are not drawn here, but the dictionaries of properties are + marshalled to their specific artists. + """ # nuke old state and mark as stale self._clear_state() self.stale = True @@ -106,13 +128,13 @@ def _reprocess(self, *): # get the layout pos = self.layout.coords - # handle the edges + # edges edge_style_dict = generate_edge_styles(graph, edge_style) self._edge_artist, self._edge_indx = ( _generate_straight_edges(graph.edges(), pos, edge_style_dict, ax=self.axes)) - # handle the nodes + # vertices vertex_style_dict = generate_node_styles(graph, node_style) self._vertex_artist, self._vertex_indx = ( _generate_vertex_artist(pos, vertex_style_dict, ax=self.axes)) From bf3a18393088c8b9e6ea3f160c2d57a024213934 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 4 Apr 2023 18:09:23 +1000 Subject: [PATCH 1239/1892] Move more logic to artist --- src/igraph/drawing/matplotlib/graph.py | 114 +++++++++++++++---------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 86e0647b5..562465422 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -53,7 +53,8 @@ def __init__( edge_style=None, vertex_label_style=None, edge_label_style=None, - **kwargs, + mark_groups=False, + **kwds, ): super().__init__() @@ -63,9 +64,36 @@ def __init__( self.edge_style = edge_style self.vertex_label_style = vertex_label_style self.edge_label_style = edge_label_style + self.mark_groups = mark_groups + self.edge_curved = self._set_edge_curve(**kwds) + self.palette = kwds.pop("palette", None) + self.kwds = kwds self._clear_state() + def _set_edge_curve(self, **kwds): + # Decide whether we need to calculate the curvature of edges + # automatically -- and calculate them if needed. + autocurve = kwds.get("autocurve", None) + if autocurve or ( + autocurve is None + and "edge_curved" not in kwds + and "curved" not in self.graph.edge_attributes() + and self.graph.ecount() < 10000 + ): + from igraph import autocurve + + default = kwds.get("edge_curved", 0) + if default is True: + default = 0.5 + default = float(default) + return autocurve( + graph, + attribute=None, + default=default, + ) + return None + def _clear_state(self): self._vertex_artist = None self._vertex_indx = None @@ -124,9 +152,19 @@ def _reprocess(self, *): vertex_style = self.vertex_style edge_label_style = self.edge_label_style vertex_label_style = self.vertex_label_style + layout = self.layout + kwds = self.kwds - # get the layout - pos = self.layout.coords + # Determine the order in which we will draw the vertices and edges + # These methods come from AbstractGraphDrawer + vertex_order = self._determine_vertex_order(graph, kwds) + edge_order = self._determine_edge_order(graph, kwds) + + # FIXME FIXME + # vertices + vertex_style_dict = generate_node_styles(graph, node_style) + self._vertex_artist, self._vertex_indx = ( + _generate_vertex_artist(pos, vertex_style_dict, ax=self.axes)) # edges edge_style_dict = generate_edge_styles(graph, edge_style) @@ -134,10 +172,6 @@ def _reprocess(self, *): _generate_straight_edges(graph.edges(), pos, edge_style_dict, ax=self.axes)) - # vertices - vertex_style_dict = generate_node_styles(graph, node_style) - self._vertex_artist, self._vertex_indx = ( - _generate_vertex_artist(pos, vertex_style_dict, ax=self.axes)) # TODO handle the text @@ -172,7 +206,7 @@ def _reprocess(self, *): child.set_clip_path(clip_path) @_stale_wrapper - def draw(self, renderer, *args, **kwargs): + def draw(self, renderer, *args, **kwds): """Draw each of the children, with some buffering mechanism.""" if not self.get_visible(): return @@ -184,7 +218,7 @@ def draw(self, renderer, *args, **kwargs): self._reprocess(reset_pos=False) for art in self.get_children(): - art.draw(renderer, *args, **kwargs) + art.draw(renderer, *args, **kwds) def contains(self, mouseevent): """Track 'contains' event for mouse interactions.""" @@ -262,32 +296,20 @@ def draw(self, graph, *args, **kwds): directed = graph.is_directed() ax = self.ax - # Palette - palette = kwds.pop("palette", None) - - # Calculate/get the layout of the graph - layout = self.ensure_layout(kwds.get("layout", None), graph) - - # Decide whether we need to calculate the curvature of edges - # automatically -- and calculate them if needed. - autocurve = kwds.get("autocurve", None) - if autocurve or ( - autocurve is None - and "edge_curved" not in kwds - and "curved" not in graph.edge_attributes() - and graph.ecount() < 10000 - ): - from igraph import autocurve - - default = kwds.get("edge_curved", 0) - if default is True: - default = 0.5 - default = float(default) - kwds["edge_curved"] = autocurve( - graph, - attribute=None, - default=default, - ) + # Create artist + art = GraphArtist( + graph, + layout=kwds.get("layout", None), + vertex_style=None, + edge_style=None, + vertex_label_style=None, + edge_label_style=None, + mark_groups=False, + **kwds, + ) + + ax.add_artist(art) + art._reprocess() # Construct the vertex, edge and label drawers vertex_drawer = self.vertex_drawer_factory(ax, palette, layout) @@ -392,9 +414,6 @@ def draw(self, graph, *args, **kwds): legend_info["labels"], ) - # Determine the order in which we will draw the vertices and edges - vertex_order = self._determine_vertex_order(graph, kwds) - edge_order = self._determine_edge_order(graph, kwds) # Construct the iterator that we will use to draw the vertices vs = graph.vs @@ -475,24 +494,24 @@ def draw(self, graph, *args, **kwds): dest_vertex, ) - text_kwargs = {} - text_kwargs['ha'] = halign.value - text_kwargs['va'] = valign.value + text_kwds = {} + text_kwds['ha'] = halign.value + text_kwds['va'] = valign.value if visual_edge.background is not None: - text_kwargs['bbox'] = dict( + text_kwds['bbox'] = dict( facecolor=visual_edge.background, edgecolor='none', ) - text_kwargs['ha'] = 'center' - text_kwargs['va'] = 'center' + text_kwds['ha'] = 'center' + text_kwds['va'] = 'center' if visual_edge.align_label: # Rotate the text to align with the edge rotation = edge_drawer.get_label_rotation( visual_edge, src_vertex, dest_vertex, ) - text_kwargs['rotation'] = rotation + text_kwds['rotation'] = rotation ax.text( x, @@ -500,10 +519,13 @@ def draw(self, graph, *args, **kwds): label, fontsize=visual_edge.label_size, color=visual_edge.label_color, - **text_kwargs, + **text_kwds, # TODO: offset, etc. ) + # Set new data limits + ax.update_datalim(art.get_datalim()) + # Despine ax.spines["right"].set_visible(False) ax.spines["top"].set_visible(False) From 7dc40b3552e8b215302422fc9ce1bb59d6075c53 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 11:50:52 +1000 Subject: [PATCH 1240/1892] Container artist with children creates, but fails to show --- src/igraph/drawing/matplotlib/edge.py | 13 +- src/igraph/drawing/matplotlib/graph.py | 626 +++++++++++++----------- src/igraph/drawing/matplotlib/vertex.py | 5 +- 3 files changed, 338 insertions(+), 306 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index adbdfab89..607f98de9 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -163,7 +163,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): path["codes"].append("LINETO") # Draw the edge - stroke = mpl.patches.PathPatch( + arrowshaft = mpl.patches.PathPatch( mpl.path.Path( path["vertices"], codes=[getattr(mpl.path.Path, x) for x in path["codes"]], @@ -172,7 +172,6 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): facecolor="none", linewidth=edge.width, ) - ax.add_patch(stroke) # Draw the arrow head arrowhead = mpl.patches.Polygon( @@ -185,7 +184,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): facecolor=edge.color, edgecolor="none", ) - ax.add_patch(arrowhead) + return [arrowshaft, arrowhead] def draw_loop_edge(self, edge, vertex): """Draws a loop edge. @@ -201,7 +200,7 @@ def draw_loop_edge(self, edge, vertex): radius = vertex.size * 1.5 center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 - stroke = mpl.patches.Arc( + art = mpl.patches.Arc( (center_x, center_y), radius / 2.0, radius / 2.0, @@ -212,7 +211,7 @@ def draw_loop_edge(self, edge, vertex): edgecolor=edge.color, ) # FIXME: make a PathCollection?? - ax.add_patch(stroke) + return [art] def draw_undirected_edge(self, edge, src_vertex, dest_vertex): """Draws an undirected edge. @@ -247,7 +246,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): path["vertices"].append(dest_vertex.position) path["codes"].append("LINETO") - stroke = mpl.patches.PathPatch( + art = mpl.patches.PathPatch( mpl.path.Path( path["vertices"], codes=[getattr(mpl.path.Path, x) for x in path["codes"]], @@ -257,4 +256,4 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): linewidth=edge.width, ) # FIXME: make a PathCollection?? - ax.add_artist(stroke) + return [art] diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 562465422..576584b7b 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -14,6 +14,7 @@ """ from warnings import warn +from functools import wraps from igraph._igraph import convex_hull, VertexSeq from igraph.drawing.baseclasses import AbstractGraphDrawer @@ -27,7 +28,7 @@ __all__ = ( "MatplotlibGraphDrawer", "GraphArtist", - ) +) mpl, plt = find_matplotlib() @@ -35,6 +36,17 @@ # NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py +def _stale_wrapper(func): + @wraps(func) + def inner(self, *args, **kwargs): + try: + func(self, *args, **kwargs) + finally: + self.stale = False + + return inner + + class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. @@ -45,33 +57,53 @@ class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): vertex_style: A dictionary specifying style options for vertices. edge_style: A dictionary specifying style options for edges. """ + def __init__( self, graph, + vertex_drawer_factory=MatplotlibVertexDrawer, + edge_drawer_factory=MatplotlibEdgeDrawer, layout=None, - vertex_style=None, - edge_style=None, - vertex_label_style=None, - edge_label_style=None, mark_groups=False, + palette=None, **kwds, ): - super().__init__() self.graph = graph - self.layout = self.ensure_layout(layout) - self.vertex_style = vertex_style - self.edge_style = edge_style - self.vertex_label_style = vertex_label_style - self.edge_label_style = edge_label_style + self.layout = self.ensure_layout(layout, graph) + self.vertex_drawer_factory = vertex_drawer_factory + self.edge_drawer_factory = edge_drawer_factory self.mark_groups = mark_groups self.edge_curved = self._set_edge_curve(**kwds) - self.palette = kwds.pop("palette", None) + self.palette = palette self.kwds = kwds self._clear_state() + def _clear_state(self): + self._vertex_artists = [] + self._edge_artists = [] + self._vertex_labels = [] + self._edge_labels = [] + self._group_artists = [] + self._legend_info = {} + + def get_children(self): + artists = sum( + [ + self._vertex_artists, + self._edge_artists, + self._vertex_labels, + self._edge_labels, + self._group_artists, + ], + [], + ) + return tuple(artists) + def _set_edge_curve(self, **kwds): + graph = self.graph + # Decide whether we need to calculate the curvature of edges # automatically -- and calculate them if needed. autocurve = kwds.get("autocurve", None) @@ -94,33 +126,14 @@ def _set_edge_curve(self, **kwds): ) return None - def _clear_state(self): - self._vertex_artist = None - self._vertex_indx = None - self._edge_artist = None - self._edge_indx = None - self._vertex_labels = None - self._edge_labels = None - self._group_artist = None - - def get_children(self): - artists = [self._vertex_artist, self._edge_artist] - if self._vertex_labels is not None: - artists.extend(self._vertex_labels) - if self._edge_labels is not None: - artists.extend(self._edge_labels) - if self._group_artist is not None: - artists.extend(self._group_artist) - return tuple(a for a in artists if a is not None) - def get_vertices(self): - return self._vertex_artist + return self._vertex_artists - def get_edges(seff): - return self._edge_artist + def get_edges(self): + return self._edge_artists def get_groups(self): - return self._group_artist + return self._group_artists def get_vertex_labels(self): return self._vertex_labels @@ -136,7 +149,250 @@ def get_datalim(self): return (mins, maxs) - def _reprocess(self, *): + def _draw_vertex_labels(self): + kwds = self.kwds + layout = self.layout + vertex_builder = self.vertex_builder + vertex_order = self.vertex_order + + # Construct the iterator that we will use to draw the vertex labels + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) + + # Draw the vertex labels + for vertex, coords in vertex_coord_iter: + if vertex.label is None: + continue + + label_size = kwds.get( + "vertex_label_size", + vertex.label_size, + ) + + art = mpl.text.Text( + *coords, + vertex.label, + fontsize=label_size, + ha="center", + va="center", + transform=self.axes.transData, + clip_on=True, + # TODO: overlap, offset, etc. + ) + self._vertex_labels.append(art) + + def _draw_edge_labels(self): + graph = self.graph + kwds = self.kwds + vertex_builder = self.vertex_builder + edge_builder = self.edge_builder + edge_drawer = self.edge_drawer + edge_order = self.edge_order + + labels = kwds.get("edge_label", None) + if labels is None: + return + + edge_label_iter = ( + (labels[i], edge_builder[i], graph.es[i]) for i in range(edge_order) + ) + for label, visual_edge, edge in edge_label_iter: + # Ask the edge drawer to propose an anchor point for the label + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + (x, y), (halign, valign) = edge_drawer.get_label_position( + visual_edge, + src_vertex, + dest_vertex, + ) + + text_kwds = {} + text_kwds["ha"] = halign.value + text_kwds["va"] = valign.value + + if visual_edge.background is not None: + text_kwds["bbox"] = dict( + facecolor=visual_edge.background, + edgecolor="none", + ) + text_kwds["ha"] = "center" + text_kwds["va"] = "center" + + if visual_edge.align_label: + # Rotate the text to align with the edge + rotation = edge_drawer.get_label_rotation( + visual_edge, + src_vertex, + dest_vertex, + ) + text_kwds["rotation"] = rotation + + art = mpl.text.Text( + x, + y, + label, + fontsize=visual_edge.label_size, + color=visual_edge.label_color, + transform=self.axes.transData, + clip_on=True, + **text_kwds, + # TODO: offset, etc. + ) + self._vertex_labels.append(art) + + def _draw_groups(self): + """Draw the highlighted vertex groups, if requested""" + # Deferred import to avoid a cycle in the import graph + from igraph.clustering import VertexClustering, VertexCover + + kwds = self.kwds + palette = self.palette + layout = self.layout + vertex_builder = self.vertex_builder + + if not kwds.get("mark_groups", False): + return + + # Figure out what to do with mark_groups in order to be able to + # iterate over it and get memberlist-color pairs + mark_groups = kwds["mark_groups"] + if isinstance(mark_groups, dict): + # Dictionary mapping vertex indices or tuples of vertex + # indices to colors + group_iter = iter(mark_groups.items()) + elif isinstance(mark_groups, (VertexClustering, VertexCover)): + # Vertex clustering + group_iter = ((group, color) for color, group in enumerate(mark_groups)) + elif hasattr(mark_groups, "__iter__"): + # Lists, tuples, iterators etc + group_iter = iter(mark_groups) + else: + # False + group_iter = iter({}.items()) + + if kwds.get("legend", False): + legend_info = { + "handles": [], + "labels": [], + } + + # Iterate over color-memberlist pairs + for group, color_id in group_iter: + if not group or color_id is None: + continue + + color = palette.get(color_id) + + if isinstance(group, VertexSeq): + group = [vertex.index for vertex in group] + if not hasattr(group, "__iter__"): + raise TypeError("group membership list must be iterable") + + # Get the vertex indices that constitute the convex hull + hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] + + # Calculate the preferred rounding radius for the corners + corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) + + # Construct the polygon + polygon = [layout[idx] for idx in hull] + + if len(polygon) == 2: + # Expand the polygon (which is a flat line otherwise) + a, b = Point(*polygon[0]), Point(*polygon[1]) + c = corner_radius * (a - b).normalized() + n = Point(-c[1], c[0]) + polygon = [a + n, b + n, b - c, b - n, a - n, a + c] + else: + # Expand the polygon around its center of mass + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] + ) + polygon = [ + Point(*point).towards(center, -corner_radius) for point in polygon + ] + + # Draw the hull + # FIXME: defer this to the draw operation! + facecolor = (color[0], color[1], color[2], 0.25 * color[3]) + drawer = MatplotlibPolygonDrawer(self.axes) + drawer.draw( + polygon, + corner_radius=corner_radius, + facecolor=facecolor, + edgecolor=color, + ) + + if kwds.get("legend", False): + legend_info["handles"].append( + plt.Rectangle( + (0, 0), + 0, + 0, + facecolor=facecolor, + edgecolor=color, + ) + ) + legend_info["labels"].append(str(color_id)) + + if kwds.get("legend", False): + self.legend_info = legend_info + + def _draw_vertices(self): + """Draw the vertices""" + graph = self.graph + layout = self.layout + vertex_drawer = self.vertex_drawer + vertex_builder = self.vertex_builder + vertex_order = self.vertex_order + + vs = graph.vs + if vertex_order is None: + # Default vertex order + vertex_coord_iter = zip(vs, vertex_builder, layout) + else: + # Specified vertex order + vertex_coord_iter = ( + (vs[i], vertex_builder[i], layout[i]) for i in vertex_order + ) + for vertex, visual_vertex, coords in vertex_coord_iter: + art = vertex_drawer.draw(visual_vertex, vertex, coords) + self._vertex_artists.append(art) + + def _draw_edges(self): + """Draw the edges""" + graph = self.graph + vertex_builder = self.vertex_builder + edge_drawer = self.edge_drawer + edge_builder = self.edge_builder + edge_order = self.edge_order + + es = graph.es + if edge_order is None: + # Default edge order + edge_coord_iter = zip(es, edge_builder) + else: + # Specified edge order + edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) + + directed = graph.is_directed() + if directed: + # Arrows and the likes + drawer_method = edge_drawer.draw_directed_edge + else: + # Lines + drawer_method = edge_drawer.draw_undirected_edge + for edge, visual_edge in edge_coord_iter: + src, dest = edge.tuple + src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] + arts = drawer_method(visual_edge, src_vertex, dest_vertex) + self._edge_artists.extend(arts) + + def _reprocess(self): """Prepare artist and children for the actual drawing. Children are not drawn here, but the dictionaries of properties are @@ -148,54 +404,38 @@ def _reprocess(self, *): # get local refs to everything (just for less typing) graph = self.graph - edge_style = self.edge_style - vertex_style = self.vertex_style - edge_label_style = self.edge_label_style - vertex_label_style = self.vertex_label_style + palette = self.palette layout = self.layout kwds = self.kwds + # Construct the vertex, edge and label drawers + self.vertex_drawer = self.vertex_drawer_factory(self.axes, palette, layout) + self.edge_drawer = self.edge_drawer_factory(self.axes, palette) + + # Construct the visual vertex/edge builders based on the specifications + # provided by the vertex_drawer and the edge_drawer + self.vertex_builder = self.vertex_drawer.VisualVertexBuilder(graph.vs, kwds) + self.edge_builder = self.edge_drawer.VisualEdgeBuilder(graph.es, kwds) + # Determine the order in which we will draw the vertices and edges # These methods come from AbstractGraphDrawer - vertex_order = self._determine_vertex_order(graph, kwds) - edge_order = self._determine_edge_order(graph, kwds) - - # FIXME FIXME - # vertices - vertex_style_dict = generate_node_styles(graph, node_style) - self._vertex_artist, self._vertex_indx = ( - _generate_vertex_artist(pos, vertex_style_dict, ax=self.axes)) - - # edges - edge_style_dict = generate_edge_styles(graph, edge_style) - self._edge_artist, self._edge_indx = ( - _generate_straight_edges(graph.edges(), pos, - edge_style_dict, ax=self.axes)) - - - # TODO handle the text - - # handle the node labels - if vertex_label_style is not None: - vlabel_style_dict = generate_vertex_label_styles( - graph, - vertex_label_style) - self._vertex_label_dict = ( - _generate_vertex_labels(pos, vlabel_style_dict, ax=self.axes)) - - # handle the edge labels - if edge_label_style is not None: - elabel_style_dict = generate_edge_label_styles(graph, - edge_label_style) - self._edge_label_dict = ( - _generate_edge_labels(pos, elabel_style_dict, ax=self.axes)) + self.vertex_order = self._determine_vertex_order(graph, kwds) + self.edge_order = self._determine_edge_order(graph, kwds) + + self._draw_groups() + self._draw_vertices() + self._draw_edges() + self._draw_vertex_labels() + self._draw_edge_labels() + # Forward mpl properties to children # TODO sort out all of the things that need to be forwarded for child in self.get_children(): - # set the figure / axes on child, this is needed - # by some internals + # set the figure / axes on child, this ensures each primitive + # knows where to draw child.set_figure(self.figure) child.axes = self.axes + # forward the clippath/box to the children need this logic # because mpl exposes some fast-path logic clip_path = self.get_clip_path() @@ -215,7 +455,7 @@ def draw(self, renderer, *args, **kwds): self._reprocess() elif self.stale: - self._reprocess(reset_pos=False) + self._reprocess() for art in self.get_children(): art.draw(renderer, *args, **kwds) @@ -225,12 +465,10 @@ def contains(self, mouseevent): props = {} edge_hit, edge_props = self._edge_artist.contains(mouseevent) vertex_hit, vertex_props = self._vertex_artist.contains(mouseevent) - props['vertices'] = [self._node_indx[j] - for j in vertex_props.get('ind', [])] - props['edges'] = [self._edge_indx[j] - for j in edge_props.get('ind', [])] + props["vertices"] = [self._node_indx[j] for j in vertex_props.get("ind", [])] + props["edges"] = [self._edge_indx[j] for j in edge_props.get("ind", [])] - return edge_hit | node_hit, props + return edge_hit | vertex_hit, props def pick(self, mouseevent): """Track 'pick' event for mouse interactions.""" @@ -293,235 +531,29 @@ def draw(self, graph, *args, **kwds): ) # Some abbreviations for sake of simplicity - directed = graph.is_directed() ax = self.ax # Create artist art = GraphArtist( graph, - layout=kwds.get("layout", None), - vertex_style=None, - edge_style=None, - vertex_label_style=None, - edge_label_style=None, - mark_groups=False, + vertex_drawer_factory=self.vertex_drawer_factory, + edge_drawer_factory=self.edge_drawer_factory, + *args, **kwds, ) + # Bind artist to axes ax.add_artist(art) - art._reprocess() - # Construct the vertex, edge and label drawers - vertex_drawer = self.vertex_drawer_factory(ax, palette, layout) - edge_drawer = self.edge_drawer_factory(ax, palette) - - # Construct the visual vertex/edge builders based on the specifications - # provided by the vertex_drawer and the edge_drawer - vertex_builder = vertex_drawer.VisualVertexBuilder(graph.vs, kwds) - edge_builder = edge_drawer.VisualEdgeBuilder(graph.es, kwds) - - # Draw the highlighted groups (if any) - if "mark_groups" in kwds: - mark_groups = kwds["mark_groups"] - - # Deferred import to avoid a cycle in the import graph - from igraph.clustering import VertexClustering, VertexCover - - # Figure out what to do with mark_groups in order to be able to - # iterate over it and get memberlist-color pairs - if isinstance(mark_groups, dict): - # Dictionary mapping vertex indices or tuples of vertex - # indices to colors - group_iter = iter(mark_groups.items()) - elif isinstance(mark_groups, (VertexClustering, VertexCover)): - # Vertex clustering - group_iter = ((group, color) for color, group in enumerate(mark_groups)) - elif hasattr(mark_groups, "__iter__"): - # Lists, tuples, iterators etc - group_iter = iter(mark_groups) - else: - # False - group_iter = iter({}.items()) - - if kwds.get("legend", False): - legend_info = { - "handles": [], - "labels": [], - } - - # Iterate over color-memberlist pairs - for group, color_id in group_iter: - if not group or color_id is None: - continue - - color = palette.get(color_id) - - if isinstance(group, VertexSeq): - group = [vertex.index for vertex in group] - if not hasattr(group, "__iter__"): - raise TypeError("group membership list must be iterable") - - # Get the vertex indices that constitute the convex hull - hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] - - # Calculate the preferred rounding radius for the corners - corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) - - # Construct the polygon - polygon = [layout[idx] for idx in hull] - - if len(polygon) == 2: - # Expand the polygon (which is a flat line otherwise) - a, b = Point(*polygon[0]), Point(*polygon[1]) - c = corner_radius * (a - b).normalized() - n = Point(-c[1], c[0]) - polygon = [a + n, b + n, b - c, b - n, a - n, a + c] - else: - # Expand the polygon around its center of mass - center = Point( - *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] - ) - polygon = [ - Point(*point).towards(center, -corner_radius) - for point in polygon - ] - - # Draw the hull - facecolor = (color[0], color[1], color[2], 0.25 * color[3]) - drawer = MatplotlibPolygonDrawer(ax) - drawer.draw( - polygon, - corner_radius=corner_radius, - facecolor=facecolor, - edgecolor=color, - ) - - if kwds.get("legend", False): - legend_info["handles"].append( - plt.Rectangle( - (0, 0), - 0, - 0, - facecolor=facecolor, - edgecolor=color, - ) - ) - legend_info["labels"].append(str(color_id)) - - if kwds.get("legend", False): - ax.legend( - legend_info["handles"], - legend_info["labels"], - ) - - - # Construct the iterator that we will use to draw the vertices - vs = graph.vs - if vertex_order is None: - # Default vertex order - vertex_coord_iter = zip(vs, vertex_builder, layout) - else: - # Specified vertex order - vertex_coord_iter = ( - (vs[i], vertex_builder[i], layout[i]) for i in vertex_order - ) - - # Draw the vertices - drawer_method = vertex_drawer.draw - for vertex, visual_vertex, coords in vertex_coord_iter: - drawer_method(visual_vertex, vertex, coords) - - # Construct the iterator that we will use to draw the vertex labels - vs = graph.vs - if vertex_order is None: - # Default vertex order - vertex_coord_iter = zip(vertex_builder, layout) - else: - # Specified vertex order - vertex_coord_iter = ((vertex_builder[i], layout[i]) for i in vertex_order) - - # Draw the vertex labels - for vertex, coords in vertex_coord_iter: - if vertex.label is None: - continue - - label_size = kwds.get( - "vertex_label_size", - vertex.label_size, - ) - - ax.text( - *coords, - vertex.label, - fontsize=label_size, - ha='center', - va='center', - # TODO: overlap, offset, etc. - ) - - # Construct the iterator that we will use to draw the edges - es = graph.es - if edge_order is None: - # Default edge order - edge_coord_iter = zip(es, edge_builder) - else: - # Specified edge order - edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) - - # Draw the edges - if directed: - drawer_method = edge_drawer.draw_directed_edge - else: - drawer_method = edge_drawer.draw_undirected_edge - for edge, visual_edge in edge_coord_iter: - src, dest = edge.tuple - src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - drawer_method(visual_edge, src_vertex, dest_vertex) + # Create children artists (this also binds them to the axes) + art._reprocess() - # Draw the edge labels - labels = kwds.get("edge_label", None) - if labels is not None: - edge_label_iter = ( - (labels[i], edge_builder[i], graph.es[i]) for i in range(graph.ecount()) + # Legend for groups + if ("mark_groups" in kwds) and kwds.get("legend", False): + ax.legend( + art._legend_info["handles"], + art._legend_info["labels"], ) - for label, visual_edge, edge in edge_label_iter: - # Ask the edge drawer to propose an anchor point for the label - src, dest = edge.tuple - src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - (x, y), (halign, valign) = edge_drawer.get_label_position( - visual_edge, - src_vertex, - dest_vertex, - ) - - text_kwds = {} - text_kwds['ha'] = halign.value - text_kwds['va'] = valign.value - - if visual_edge.background is not None: - text_kwds['bbox'] = dict( - facecolor=visual_edge.background, - edgecolor='none', - ) - text_kwds['ha'] = 'center' - text_kwds['va'] = 'center' - - if visual_edge.align_label: - # Rotate the text to align with the edge - rotation = edge_drawer.get_label_rotation( - visual_edge, src_vertex, dest_vertex, - ) - text_kwds['rotation'] = rotation - - ax.text( - x, - y, - label, - fontsize=visual_edge.label_size, - color=visual_edge.label_color, - **text_kwds, - # TODO: offset, etc. - ) # Set new data limits ax.update_datalim(art.get_datalim()) diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py index 3a7db0d90..00270a010 100644 --- a/src/igraph/drawing/matplotlib/vertex.py +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -44,6 +44,7 @@ class VisualVertexBuilder(AttributeCollectorBase): return VisualVertexBuilder def draw(self, visual_vertex, vertex, coords): + """Build the Artist for a vertex and return it.""" ax = self.context width = ( @@ -57,7 +58,7 @@ def draw(self, visual_vertex, vertex, coords): else visual_vertex.size ) - stroke = visual_vertex.shape.draw_path( + art = visual_vertex.shape.draw_path( ax, coords[0], coords[1], @@ -68,4 +69,4 @@ def draw(self, visual_vertex, vertex, coords): linewidth=visual_vertex.frame_width, zorder=visual_vertex.zorder, ) - ax.add_patch(stroke) + return art From e310f201dbb76dfaa761470fbe355efbdc2f2832 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 11:56:05 +1000 Subject: [PATCH 1241/1892] Forwarder as in grave --- src/igraph/drawing/matplotlib/graph.py | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 576584b7b..6fdef7f03 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -14,7 +14,7 @@ """ from warnings import warn -from functools import wraps +from functools import wraps, partial from igraph._igraph import convex_hull, VertexSeq from igraph.drawing.baseclasses import AbstractGraphDrawer @@ -37,6 +37,7 @@ # NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py def _stale_wrapper(func): + """Decorator to manage artist state.""" @wraps(func) def inner(self, *args, **kwargs): try: @@ -47,6 +48,32 @@ def inner(self, *args, **kwargs): return inner +def _forwarder(forwards, cls=None): + """Decorator to forward specific methods to Artist children.""" + if cls is None: + return partial(_forwarder, forwards) + + def make_forward(name): + def method(self, *args, **kwargs): + ret = getattr(cls.mro()[1], name)(self, *args, **kwargs) + for c in self.get_children(): + getattr(c, name)(*args, **kwargs) + return ret + + return method + + for f in forwards: + method = make_forward(f) + method.__name__ = f + method.__doc__ = 'broadcasts {} to children'.format(f) + setattr(cls, f, method) + + return cls + + +@_forwarder(('set_clip_path', 'set_clip_box', 'set_transform', + 'set_snap', 'set_sketch_params', 'set_figure', + 'set_animated', 'set_picker')) class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. From 33e57b590ee109623baca52abaeb5195c6d5382f Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 11:58:01 +1000 Subject: [PATCH 1242/1892] Remove unused import --- src/igraph/drawing/__init__.py | 6 +----- src/igraph/drawing/matplotlib/graph.py | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index ec1a8168f..5ae708ccc 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -41,10 +41,7 @@ from igraph.drawing.cairo.matrix import CairoMatrixDrawer from igraph.drawing.cairo.histogram import CairoHistogramDrawer from igraph.drawing.cairo.palette import CairoPaletteDrawer -from igraph.drawing.matplotlib.graph import ( - MatplotlibGraphDrawer, - GraphArtist, -) +from igraph.drawing.matplotlib.graph import MatplotlibGraphDrawer from igraph.drawing.matplotlib.matrix import MatplotlibMatrixDrawer from igraph.drawing.matplotlib.histogram import MatplotlibHistogramDrawer from igraph.drawing.matplotlib.palette import MatplotlibPaletteDrawer @@ -57,7 +54,6 @@ "BoundingBox", "CairoGraphDrawer", "MatplotlibGraphDrawer", - "GraphArtist", "DefaultGraphDrawer", "Plot", "Point", diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 6fdef7f03..113dac3b5 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -27,7 +27,6 @@ __all__ = ( "MatplotlibGraphDrawer", - "GraphArtist", ) mpl, plt = find_matplotlib() From 794410eb6f944d503dfb34a764c547cc355a5ef4 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 19:32:03 +1000 Subject: [PATCH 1243/1892] Injected axes into builders should be used for transData --- src/igraph/drawing/matplotlib/edge.py | 8 +++++ src/igraph/drawing/matplotlib/graph.py | 41 ++++++++++++++++++-------- src/igraph/drawing/shapes.py | 39 ++++++++++++++++++++---- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 607f98de9..3919f370d 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -171,6 +171,8 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): edgecolor=edge.color, facecolor="none", linewidth=edge.width, + transform=ax.transData, + clip_on=True, ) # Draw the arrow head @@ -183,6 +185,8 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): closed=True, facecolor=edge.color, edgecolor="none", + transform=ax.transData, + clip_on=True, ) return [arrowshaft, arrowhead] @@ -209,6 +213,8 @@ def draw_loop_edge(self, edge, vertex): linewidth=edge.width, facecolor="none", edgecolor=edge.color, + transform=ax.transData, + clip_on=True, ) # FIXME: make a PathCollection?? return [art] @@ -254,6 +260,8 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): edgecolor=edge.color, facecolor="none", linewidth=edge.width, + transform=ax.transData, + clip_on=True, ) # FIXME: make a PathCollection?? return [art] diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 113dac3b5..7146ba8a5 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -25,9 +25,7 @@ from .utils import find_matplotlib from .vertex import MatplotlibVertexDrawer -__all__ = ( - "MatplotlibGraphDrawer", -) +__all__ = ("MatplotlibGraphDrawer",) mpl, plt = find_matplotlib() @@ -37,6 +35,7 @@ # NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py def _stale_wrapper(func): """Decorator to manage artist state.""" + @wraps(func) def inner(self, *args, **kwargs): try: @@ -64,15 +63,24 @@ def method(self, *args, **kwargs): for f in forwards: method = make_forward(f) method.__name__ = f - method.__doc__ = 'broadcasts {} to children'.format(f) + method.__doc__ = "broadcasts {} to children".format(f) setattr(cls, f, method) return cls -@_forwarder(('set_clip_path', 'set_clip_box', 'set_transform', - 'set_snap', 'set_sketch_params', 'set_figure', - 'set_animated', 'set_picker')) +@_forwarder( + ( + "set_clip_path", + "set_clip_box", + "set_transform", + "set_snap", + "set_sketch_params", + "set_figure", + "set_animated", + "set_picker", + ) +) class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. @@ -170,9 +178,21 @@ def get_edge_labels(self): def get_datalim(self): import numpy as np + vertex_builder = self.vertex_builder + mins = np.min(self.layout, axis=0) maxs = np.max(self.layout, axis=0) + # Pad by vertex size, to ensure they fit + if vertex_builder.size is not None: + mins -= vertex_builder.size * 1.1 + maxs += vertex_builder.size * 1.1 + else: + mins[0] -= vertex_builder.width * 0.55 + mins[1] -= vertex_builder.height * 0.55 + maxs[0] += vertex_builder.width * 0.55 + maxs[1] += vertex_builder.height * 0.55 + return (mins, maxs) def _draw_vertex_labels(self): @@ -424,7 +444,7 @@ def _reprocess(self): Children are not drawn here, but the dictionaries of properties are marshalled to their specific artists. """ - # nuke old state and mark as stale + # clear state and mark as stale self._clear_state() self.stale = True @@ -477,10 +497,7 @@ def draw(self, renderer, *args, **kwds): if not self.get_visible(): return - if not self.get_children(): - self._reprocess() - - elif self.stale: + if (not self.get_children()) or self.stale: self._reprocess() for art in self.get_children(): diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index d4ca9fc49..69d39bb4d 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -96,7 +96,12 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): height = height or width if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Rectangle( - (center_x - width / 2, center_y - height / 2), width, height, **kwargs + (center_x - width / 2, center_y - height / 2), + width, + height, + transform=ctx.transData, + clip_on=True, + **kwargs, ) else: ctx.rectangle(center_x - width / 2, center_y - height / 2, width, height) @@ -163,7 +168,13 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): @see: ShapeDrawer.draw_path""" if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): - return mpl.patches.Circle((center_x, center_y), width / 2, **kwargs) + return mpl.patches.Circle( + (center_x, center_y), + width / 2, + transform=ctx.transData, + clip_on=True, + **kwargs, + ) else: ctx.arc(center_x, center_y, width / 2, 0, 2 * pi) @@ -197,7 +208,13 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): [center_x + 0.5 * width, center_y - 0.333 * height], [center_x, center_x + 0.667 * height], ] - return mpl.patches.Polygon(vertices, closed=True, **kwargs) + return mpl.patches.Polygon( + vertices, + closed=True, + transform=ctx.transData, + clip_on=True, + **kwargs, + ) else: ctx.move_to(center_x - width / 2, center_y + height / 2) ctx.line_to(center_x, center_y - height / 2) @@ -234,7 +251,13 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): [center_x + 0.5 * width, center_y + 0.333 * height], [center_x, center_y - 0.667 * height], ] - return mpl.patches.Polygon(vertices, closed=True, **kwargs) + return mpl.patches.Polygon( + vertices, + closed=True, + transform=ctx.transData, + clip_on=True, + **kwargs, + ) else: ctx.move_to(center_x - width / 2, center_y - height / 2) @@ -273,7 +296,13 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): [center_x + 0.5 * width, center_y], [center_x, center_y + 0.5 * height], ] - return mpl.patches.Polygon(vertices, closed=True, **kwargs) + return mpl.patches.Polygon( + vertices, + closed=True, + transform=ctx.transData, + clip_on=True, + **kwargs, + ) else: ctx.move_to(center_x - width / 2, center_y) ctx.line_to(center_x, center_y + height / 2) From 6e24ea651a6c293ee42f5d0b16669a53574b9e7b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 20:52:24 +1000 Subject: [PATCH 1244/1892] Working except for zorder --- src/igraph/drawing/matplotlib/edge.py | 5 +++++ src/igraph/drawing/matplotlib/graph.py | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 3919f370d..04dabf22e 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -51,6 +51,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): width = 2.0 background = None align_label = False + zorder = 1 return VisualEdgeBuilder @@ -171,6 +172,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): edgecolor=edge.color, facecolor="none", linewidth=edge.width, + zorder=edge.zorder, transform=ax.transData, clip_on=True, ) @@ -185,6 +187,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): closed=True, facecolor=edge.color, edgecolor="none", + zorder=edge.zorder, transform=ax.transData, clip_on=True, ) @@ -213,6 +216,7 @@ def draw_loop_edge(self, edge, vertex): linewidth=edge.width, facecolor="none", edgecolor=edge.color, + zorder=edge.zorder, transform=ax.transData, clip_on=True, ) @@ -260,6 +264,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): edgecolor=edge.color, facecolor="none", linewidth=edge.width, + zorder=edge.zorder, transform=ax.transData, clip_on=True, ) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 7146ba8a5..49fd0d9d0 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -237,14 +237,14 @@ def _draw_edge_labels(self): vertex_builder = self.vertex_builder edge_builder = self.edge_builder edge_drawer = self.edge_drawer - edge_order = self.edge_order + edge_order = self.edge_order or range(self.graph.ecount()) labels = kwds.get("edge_label", None) if labels is None: return edge_label_iter = ( - (labels[i], edge_builder[i], graph.es[i]) for i in range(edge_order) + (labels[i], edge_builder[i], graph.es[i]) for i in edge_order ) for label, visual_edge, edge in edge_label_iter: # Ask the edge drawer to propose an anchor point for the label @@ -469,8 +469,8 @@ def _reprocess(self): self.edge_order = self._determine_edge_order(graph, kwds) self._draw_groups() - self._draw_vertices() self._draw_edges() + self._draw_vertices() self._draw_vertex_labels() self._draw_edge_labels() From 9121dbb10b8491927b5d48af20c6df216350d701 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 20:57:57 +1000 Subject: [PATCH 1245/1892] Manual management of zorder --- src/igraph/drawing/matplotlib/graph.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 49fd0d9d0..66e1ab30f 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -125,14 +125,17 @@ def _clear_state(self): def get_children(self): artists = sum( [ - self._vertex_artists, + self._group_artists, self._edge_artists, - self._vertex_labels, + self._vertex_artists, self._edge_labels, - self._group_artists, + self._vertex_labels, ], [], ) + + # NOTE: looks like we have to manage the zorder ourselves + artists.sort(key=lambda x: x.zorder) return tuple(artists) def _set_edge_curve(self, **kwds): From 8e63abd9ccacca5c095b2f8136b73615140f5457 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 21:33:56 +1000 Subject: [PATCH 1246/1892] zorder in the draw function makes children more consistent --- src/igraph/drawing/matplotlib/graph.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 66e1ab30f..ad8098102 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -134,8 +134,6 @@ def get_children(self): [], ) - # NOTE: looks like we have to manage the zorder ourselves - artists.sort(key=lambda x: x.zorder) return tuple(artists) def _set_edge_curve(self, **kwds): @@ -503,7 +501,8 @@ def draw(self, renderer, *args, **kwds): if (not self.get_children()) or self.stale: self._reprocess() - for art in self.get_children(): + # NOTE: looks like we have to manage the zorder ourselves + for art in sorted(self.get_children(), key=lambda x: x.zorder): art.draw(renderer, *args, **kwds) def contains(self, mouseevent): From 9bb39625895355c9de42141c02d09989a3cee4ca Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 21:54:24 +1000 Subject: [PATCH 1247/1892] Return artist in group hull and speed up sorting for zorder --- src/igraph/drawing/matplotlib/graph.py | 7 +++++-- src/igraph/drawing/matplotlib/polygon.py | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index ad8098102..6bcd474ba 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -367,12 +367,13 @@ def _draw_groups(self): # FIXME: defer this to the draw operation! facecolor = (color[0], color[1], color[2], 0.25 * color[3]) drawer = MatplotlibPolygonDrawer(self.axes) - drawer.draw( + art = drawer.draw( polygon, corner_radius=corner_radius, facecolor=facecolor, edgecolor=color, ) + self._group_artists.append(art) if kwds.get("legend", False): legend_info["handles"].append( @@ -502,7 +503,9 @@ def draw(self, renderer, *args, **kwds): self._reprocess() # NOTE: looks like we have to manage the zorder ourselves - for art in sorted(self.get_children(), key=lambda x: x.zorder): + children = list(self.get_children()) + children.sort(key=lambda x: x.zorder) + for art in children: art.draw(renderer, *args, **kwds) def contains(self, mouseevent): diff --git a/src/igraph/drawing/matplotlib/polygon.py b/src/igraph/drawing/matplotlib/polygon.py index 9cbbf6546..0e10fa4c3 100644 --- a/src/igraph/drawing/matplotlib/polygon.py +++ b/src/igraph/drawing/matplotlib/polygon.py @@ -80,8 +80,10 @@ def draw(self, points, corner_radius=0, **kwds): codes.extend([mpl.path.Path.CURVE4] * 3) u = v - stroke = mpl.patches.PathPatch( + art = mpl.patches.PathPatch( mpl.path.Path(path, codes=codes, closed=True), + transform=ax.transData, + clip_on=True, **kwds, ) - ax.add_patch(stroke) + return art From 59e2ce514722345ab3a153e8e9b94ef2f9a4a2fd Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 22:07:24 +1000 Subject: [PATCH 1248/1892] Update a few test baseline images, which were manually verified --- .../test_graph/clustering_directed.png | Bin 36425 -> 23399 bytes .../test_graph/graph_basic.png | Bin 24565 -> 22749 bytes .../test_graph/graph_directed.png | Bin 25533 -> 23715 bytes .../test_graph/graph_mark_groups_directed.png | Bin 25533 -> 23715 bytes tests/drawing/matplotlib/test_graph.py | 3 ++- 5 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index bd2235aa56e1f2decda6b0d4907ddc8817eaed1f..4d3486fe3173ae2f0814632c30485c2efd94a6b2 100644 GIT binary patch literal 23399 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 D<#A&W literal 36425 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≦)ess8d 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png index c9883a651e68b79db0fc3509035925de187dd523..259ec8d487269ad52d4479a18943b895132ddc9e 100644 GIT binary patch literal 22749 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 literal 24565 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 cJT3e4e~E)Lzopr0Io*@?*IS* literal 25533 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 cJT3e4e~E)Lzopr0Io*@?*IS* literal 25533 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 Date: Wed, 5 Apr 2023 22:10:05 +1000 Subject: [PATCH 1249/1892] Remove PathCollection TODOs --- src/igraph/drawing/matplotlib/edge.py | 4 +--- src/igraph/drawing/matplotlib/graph.py | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 04dabf22e..929555ecf 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -56,7 +56,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): return VisualEdgeBuilder def draw_directed_edge(self, edge, src_vertex, dest_vertex): - if src_vertex == dest_vertex: # TODO + if src_vertex == dest_vertex: return self.draw_loop_edge(edge, src_vertex) ax = self.context @@ -220,7 +220,6 @@ def draw_loop_edge(self, edge, vertex): transform=ax.transData, clip_on=True, ) - # FIXME: make a PathCollection?? return [art] def draw_undirected_edge(self, edge, src_vertex, dest_vertex): @@ -268,5 +267,4 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): transform=ax.transData, clip_on=True, ) - # FIXME: make a PathCollection?? return [art] diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 6bcd474ba..5ee0ebbf8 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -364,7 +364,6 @@ def _draw_groups(self): ] # Draw the hull - # FIXME: defer this to the draw operation! facecolor = (color[0], color[1], color[2], 0.25 * color[3]) drawer = MatplotlibPolygonDrawer(self.axes) art = drawer.draw( From 4c10be2063d3b5ddc8865e2c25a03a50a78e8e99 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 22:16:07 +1000 Subject: [PATCH 1250/1892] Check contains --- src/igraph/drawing/matplotlib/graph.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 5ee0ebbf8..5bfda2636 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -509,17 +509,22 @@ def draw(self, renderer, *args, **kwds): def contains(self, mouseevent): """Track 'contains' event for mouse interactions.""" - props = {} - edge_hit, edge_props = self._edge_artist.contains(mouseevent) - vertex_hit, vertex_props = self._vertex_artist.contains(mouseevent) - props["vertices"] = [self._node_indx[j] for j in vertex_props.get("ind", [])] - props["edges"] = [self._edge_indx[j] for j in edge_props.get("ind", [])] + props = {"vertices": [], "edges": []} + hit = False + for i, art in enumerate(self._edge_artists): + edge_hit = art.contains(mouseevent)[0] + hit |= edge_hit + props["edges"].append(i) - return edge_hit | vertex_hit, props + for i, art in enumerate(self._vertex_artists): + vertex_hit = art.contains(mouseevent)[0] + hit |= vertex_hit + props["vertices"].append(i) + + return hit, props def pick(self, mouseevent): """Track 'pick' event for mouse interactions.""" - # Pick self if self.pickable(): picker = self.get_picker() if callable(picker): From 05c7437cdeb90c81f2f975588c2e47380b0df034 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 5 Apr 2023 23:27:33 +1000 Subject: [PATCH 1251/1892] Revert test image --- .../test_graph/clustering_directed.png | Bin 23399 -> 36425 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index 4d3486fe3173ae2f0814632c30485c2efd94a6b2..bd2235aa56e1f2decda6b0d4907ddc8817eaed1f 100644 GIT binary patch literal 36425 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≦)ess8d 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 literal 23399 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 D<#A&W From 9f660d44392ba59478635363f1a4b9f462bbacc2 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 06:43:20 +1000 Subject: [PATCH 1252/1892] mark_groups now works, update baseline test images --- src/igraph/drawing/matplotlib/graph.py | 29 +++++++++++++----- src/igraph/drawing/matplotlib/polygon.py | 1 + .../test_graph/clustering_directed.png | Bin 36425 -> 34606 bytes .../test_graph/clustering_directed_large.png | Bin 60676 -> 60151 bytes 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 5bfda2636..d6942d8ea 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -133,7 +133,6 @@ def get_children(self): ], [], ) - return tuple(artists) def _set_edge_curve(self, **kwds): @@ -162,21 +161,35 @@ def _set_edge_curve(self, **kwds): return None def get_vertices(self): + """Get vertex artists.""" return self._vertex_artists def get_edges(self): + """Get edge artists. + + Note that for directed edges, an edge might have more than one + artist, e.g. arrow shaft and arrowhead. + """ return self._edge_artists def get_groups(self): + """Get group/cluster/cover artists.""" return self._group_artists def get_vertex_labels(self): + """Get vertex label artists.""" return self._vertex_labels def get_edge_labels(self): + """Get edge label artists.""" return self._edge_labels def get_datalim(self): + """Get limits on x/y axes based on the graph layout data. + + There is a small padding based on the size of the vertex marker to + ensure it fits into the canvas. + """ import numpy as np vertex_builder = self.vertex_builder @@ -228,6 +241,7 @@ def _draw_vertex_labels(self): va="center", transform=self.axes.transData, clip_on=True, + zorder=3, # TODO: overlap, offset, etc. ) self._vertex_labels.append(art) @@ -286,6 +300,7 @@ def _draw_edge_labels(self): color=visual_edge.label_color, transform=self.axes.transData, clip_on=True, + zorder=3, **text_kwds, # TODO: offset, etc. ) @@ -299,14 +314,14 @@ def _draw_groups(self): kwds = self.kwds palette = self.palette layout = self.layout + mark_groups = self.mark_groups vertex_builder = self.vertex_builder - if not kwds.get("mark_groups", False): + if not mark_groups: return # Figure out what to do with mark_groups in order to be able to # iterate over it and get memberlist-color pairs - mark_groups = kwds["mark_groups"] if isinstance(mark_groups, dict): # Dictionary mapping vertex indices or tuples of vertex # indices to colors @@ -315,6 +330,10 @@ def _draw_groups(self): # Vertex clustering group_iter = ((group, color) for color, group in enumerate(mark_groups)) elif hasattr(mark_groups, "__iter__"): + # One-off generators: we need to store the actual list for future + # calls (e.g. resizing, recoloring, etc.). If we don't do this, + # the generator is exhausted: we cannot rewind it. + self.mark_groups = mark_groups = list(mark_groups) # Lists, tuples, iterators etc group_iter = iter(mark_groups) else: @@ -571,10 +590,6 @@ def __init__( self.edge_drawer_factory = edge_drawer_factory def draw(self, graph, *args, **kwds): - # Deferred import to avoid a cycle in the import graph - from igraph.clustering import VertexClustering, VertexCover - - # Positional arguments are not used if args: warn( "Positional arguments to plot functions are ignored " diff --git a/src/igraph/drawing/matplotlib/polygon.py b/src/igraph/drawing/matplotlib/polygon.py index 0e10fa4c3..8e429a9b8 100644 --- a/src/igraph/drawing/matplotlib/polygon.py +++ b/src/igraph/drawing/matplotlib/polygon.py @@ -84,6 +84,7 @@ def draw(self, points, corner_radius=0, **kwds): mpl.path.Path(path, codes=codes, closed=True), transform=ax.transData, clip_on=True, + zorder=4, **kwds, ) return art diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index bd2235aa56e1f2decda6b0d4907ddc8817eaed1f..8a8179e05c9997cca1a174bfa5702e803efa1167 100644 GIT binary patch literal 34606 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 literal 36425 zcmeFZhf|bW^DR7NkvJ$hI-n>ys6+`m2!fy@IR{BfW=N7nk_d=Ii6U7*qU1aXC`rjm z8gh<9j^BRpocI3Ty0^Z6;9jdv9m|?|p1pf_uU@^n_k=uFkte&za1jQBkv&jAs={D+ zY%mzE)&)ZFF9|NM?7{!UP;y$Rr*`HjS7S#rn6fd--r5djZDqpdV&>>%WoIkQcbiXu zhs_d&vUd{a=ePOK2l(t9E%@(zdP)W!LTs;~?F55S7(@TzU+ zu5M~(g!om8 z2ETp1VULy9ia#hFA-j4t$on!a+7Iusf%n4cuU|il*|!&P?gh#yzBzCTBFEU{pZ4$| zs9rGz8q;Y6QNrQ5>fTbGr(&H+#7=WEPvD}-KfiKsFPYHYRNV4@yj&=kgN zdK+#ZeSGKyaSwO=Q|?^h`f(;kita4&t~)SA6JqD@cyvyz|Gv~MPSP!TDUhu1Vo0z8 zbFMFV$d0$JI4R!yDC1F4(K)){u&?5iR}K#51`AVt0s}~lC!`b<1VY ze@%t7^Lbcsa99p_rvheXmf1j@Df}KcvuUeLN2~^?wJ2Jk!t!LFokt6%Tagen^+=qU zukNyn*f+@r1fsY7e5pPI8sdZ$Qe|~Nx-+LEtVhgaBM-1$CcSkMqmCqcE+52fl#m&b zsyJ{se4?Z4j+*#fkBCy+yDLG8@}V>uoTT{!d6Ux-U1z*HWxmT_{Fe)Zc2^5jt|6%G zxd0SQF^Y)=DYivOe@6A2&#Pd4(hKWfy}4Mqao0)x8Ac{AD&(KwxT&W?{xH=$2UV$O zzDOsb0oKAKY83m9Ubu7M(^D0{Hdc`~($L`7qSVl_r?SU{J4_pGTgHSR=H$O-_4c*u z>l}zw;tvR7d6mHdJ$63~GAYwocQSbYD}tc7aMN(Vxvl~gOFL@njc>FYgSwAZaYe>2 zxK1!v6K%_7Jb4QC82M*)*dYgXyd9-2uBu92fXYGb8$5|TXxNiyl`S>j7 zd$OOdjZ{>`M9O3MeSUo-m225Oe`NZKHMaUPk&?U?9Vw%^O5yWond!Z&bET=?QwQ|I z`%>(9zOgEtHyU9PLFO{}j|o=@dXrUR@xHN8@MT8{-;bE97VgFjH~Bm4o96ZV;caYn zZ2YzmFvhLLl9$;mAI-zz#FSu*k*x^s<;RO!m6XkB3d6;XdCmjboU+=aGtd1i{GIW# zyW@3l9mT79r;T}j66~jQO%e+Ei8U(m(Y_e9eaXqOF@)`&K2s4R$d=Z)(c5dZq!t|P zyEpE?Iqh}Egh1eY#6=*eemv)9Mh60y@6WlfDNe3a;=&u1tzu^CayyF5f7y42P%0Lu zlPJYibiZAIuCI`_aLh|&>=Kn{Y{j3ou{n+Wx1??uoXU9?r;en5g5h<->Ig+lxLl~3 z`19-B{PXK}wN01S8+wd_{6!>L4v#iA=W#VF^=3qqC0%v~j%PcCy&4#%ToR{WPIz8Y zk)oH{hnbjo9)T5lXFw~wSZ*VsCQieDTd8eh68NWB$&%laJg`ANHVSR9T;1Y=vx-dIov>(yr`FR`xz3Urz(Chk_) z*87md;jECm7DpB6f_+|9QWIbLm|vR|wO;9;$*n0gGHt8{OZB*BAC7LCx%6mecEoP4 zCpw>50`sNjV_84X6@Q|mQ!ymcQ-J`9t8s8rvcx^Am1|aro$?O(&!(56pA&Zx)(N z6sP;7$Rk^nAlPU!>4*h5rWAKK>RM1C2*Q3PD|a#f!pc{360TcOZPRgh^Umt9ZP%)W z)TGX#N0O7N1zJX5d`I2bZ`#>@dA(p%9gKekicoHwanBr7M&^giX^di9Fr16oz-_-v z%=HzH?x^_AoJ8{X(tVvl!cIeB-bOa^+V#7QY+zJN8fy~j) z(7jC4-$Gb2ldhQXoa=d){usE+5hR};TXc_BM9}7wKSd+6qoxe%_7@4Hvww8n)V#}A zLwdR=eI^wbtZ+xW3c-u$b?esju~}ahSjxc`z!c0bR}6Urz0Y(Q zU7n_J&vdc)4`VJr6+YVR6cp82-HyhY)Cc3n>4-!N+1}nxRp86`5PW!AO}F05WWO`U z!_0m^K9l{HdL}!p#B~+1IqKxjSlPZL@U@cFjZ5hLEB=O-MbzQmcK|^NFFHx6`E)X{ zYzV5$Wdusd7F~HRW(rB8l-0+J7jiN`e1OI3Vbl3qaVg?rOQg6%$4^;e7^w;N#)yUt zDJsSYd+y9n%wK}%;z0%t94?xCyx86@pw!kLX}+kSJiysSqo~`Ea+{Af#I|DK$@3W1 z9VZ?0tTU1eGJ9)tTb^9g)0Xvr0K}2f@a>(b8LHHdM zbasM+m{lxAy=AhB4ewXOn)p$by-`%MvULtlw+#=htwBF+9G42FgaCS^uP$%RQBiCJPLW;y&o*<13cmy$rdm*L99k3F%97+Eg# z?9}lW{Q?q7Mv}czQ z%bls*Z=r&u?APTt*Ko^g#z6YBvUwMM*$FW?aY|^~)|~TXa1I`M{~olCwn)XcZ?x#2 zX@+?@lBZ%Hi&ek>soy%!*C@}h5@ z%rqSnj|soOB%@7F|NA%3NPY6GZaD@v2RpNHF4FO&XlZTv`Sl)AUb=6G*%x0u_e|~k z=A8nC^nl371GAg(6DhR?u_j0h33v4hKEJH@GPkM#nVJ4X^s&bMml`x3B_&#^aY5Nj zo$}ArE;C2HcN63eJtHY`Vl!)8=A(^Eazlh0xu>(TQn-%dfT-ZFg$)_nIV0f24&>+y zC7KrS$O$1*>>nl~P4VZk;hWRy;tY|^y{b-`(;}JaS;GsKl1F>kg%18wd^(!_c=>H| zd%+^xKQ~`GuUI-Kq3>WxJrAz(7?6Jdu8|Foq|5?7*7RMVGw&TM5A*U+Vy5Y~C7p;$ zW;*-^5AW5w=N2!-0JJb>T;cOg0kqkJLS3$<{L?#rm;be>-wM)@T@@|y_H?G3K z4t8o>o{Us{9uyQL&E;Zd*8O@o7MsN>eHc7q;N~ZX-^SH`)JV`s`!w6}M|-43TkhEI zs{PKu#=JDT%<6m#nP3Zp;#%V5DT~9En~xXiq*($zr-?YYs2M{_OLU%M3ZOTG)&aWV7! z`A~NEv!I)6@A2nmW)!)LoeSy)>EJ=r2F33v(jV2x z+bB;V*(f&Ms{QUG&N%>oG*iMpewh)oERUdi4uHJHhdef%Li%PXc=FFr-_nGcL0q)f zzkk0Z%*=?zMx0wtVY>v?KjTs(cGg66;Ms&LB|>`baOTPK95qG}^M!g?-$P7zFkcD|C zCgtoTf}Dk-uxjk>&g8Vu1-*6DRLGmDCBSBzNccHMXSXJWwLTV6eyP4F?izT2y~TDH zSqsIRvuhEGNwTllEYw}WdD~KSSF02?e9{%$|3FrKQLEldB5@1rUk!?(dm1!x(udcj z3$)QzrPNLmvLs5x(L_cj{V8N+7k6!4v~Eu) z3IR1&Rw5=`0`Td)zTn_4P|3Bk3X^J8Z~xr=T%g+pNE}Fp=})d-=lf!?xW98DlfC{k zij=&$cT?B4B2lFNAkaeUFqm4mqPJ^yO0gnQP)3OIglLZ!7K`KLtEtcDIA+^QM%QTA zb0@Cvenjh}{l-s`iFc(w(y-M;k@;;uJo@1@|I{-z@9njkjUU__s}%x*@8l2UIQoIb z+t=v{kGDF~R@HSY?&fLy6H(55%<2~6;`r{1Ibp_hJbHBrwC3G2)9%>odHF5G+YVK9 z7?(cMVAv0VQ2Ccybd22GIF>B*-@kDtH9BXfsx|B<|N^4=N|Bkuw@PK%hn)+r)@JH>3 zq$f4b?3osiRA269XsS|uVLz_f_da&kD_@L6V| z7Cqu(Y`GA;7^q+hrsi}-&%UR{gxid;-QNAF2ncd|@g88MyQ|059&dT?e z@w$+bj@P-G27Y@JBH1Qk3}(&@@M3yu%E(rX(V}Q&9T#^850Dh%Gff*|AbFZRauDpO zu(QzCph-OY2s!&NgG@9xh4;y=s(=9JYMZ`m%A&=OSX*6|?`svEd7x@03w;7!;VL{5 zF?hv)DStVZ?fj55duP4pXE?LJN20Fn z7k96BrV#;;r2LG!xe&5);QP^Tl0}xk(t0D4$qIBqUKv}?i87}fox&Tl zadU58IF<}pAzKImEUzpWE$(mJ+uxr?Ly+^cFjY~Wy|^YP*leVtRFYdMll?+Wbez*j z=Lh*a!3K%fjE$3|pIyjJmN*iRwTp>E8=jh+zWgm@`KSMnB!X%idSdgmU#ib-O)*d_ zpB%lo=ELq#gyQM=VX_QYl)oEFGhiWZ?OG5*iQOx#HyQH7+o^s8YN&_wV(<6OyN;uO zw3XWhpV4P2L*R~IC6I>)Kx4xVlbuQ)6P_%QrksdA2j75WJR)!=thp$Ta%=57 zLPNLh^cejzGzyl~Wm=uryS4oZ;kMc8of#ZXT!a0&_Q#v{Ae(YhMX~_^q_X}SbB>N6 z)^fpmv*O!Ms4?MB!OOqp+ zGBKh1S?>j-I{2k5()8!6{aV#r+IG7_-lY%)%3gX(cpk_DM%ZLmOx<2*@2~PzpxRUv zf^&Hi*BjYia@9W%%KXDh4g<2=e?*zc56f&i{*3C8VrJ^S#J>8R`Oaah!Wg?EYtQz4 zHjc3nePGJ~Q6l41GuiiOaM7(|G_?&B!k9K)$OMukBaOg{>#Yp+K^~m6-GO3?+5_%rIk|#GG z#=|U9tRRjkq=N$|j_y@;!z#N?5o0ek&pdN7dHDSE{khvz?g0UiGaT%$TJvAe*|`mP zD&(@3NmlJ{2lJ_bDyg41r|!G)DJf^V571=V4dzdls^`Hh;q>3{L|yyU**y|RipSyx z6B6oVO%~TqRzSWA1_;_fA6V736fV(eqXCGx`}~JIW~!~NizIoP;w9ma#l>0l7D4H! zJ&~{9VZp6Ag%aI=dUpD7X^b%l{p93`1&ygXz-q@OlE^f;tX8^o(k0!pHI)bm0M*pb zD&fvlipj}y#{sc7^++kMnM|bdlib|xycwx#}IQt1cd!hf?5GQ=4@UBBV?J!-P757o+!oL!qR^hyq2@j7~5r<^@J zyyQQ_#jHvzteI~#SnUie3lEu03Aq#^uINDgoF(GGuQQgn$b_Kmg#|d&;&`yi!szJu ziD#+qgn?wj6--RVc>%+kfE&((M}^{*hldc`-z}D?XhZvW@B4MtxZ(+L+z7eBexJ$3 zyv1dAMX<-8gA<*vov_P!F6r*yy-x_LE3vVq&v~82QHO+#LXNxZg;IUR(-h}GM#y>X zGb(tcNj%G;v03`XwLjmFi{Q<0+Hm4vq6UrT4Xu3zgt}`0-vS4Ndk|FLz;l;Rozo)50$( zLxloPa5K6M50t;h)2wsf%57`N5^ffY$G92K*Lw|&+3I^`v1?@BJ6<^{ zyE$j~2VdrBuB*za86VMX?MY@_!FYP8dHuTYHVS(;AJMx2J+{RU&;I+>IqI&$TB>eo z)|Fc68u-)2cSahMF4&eNv4N<8`_7Ba-_U{Dj6Za%s^&BX&Qr;+7ugEzfc&c(O1LyW z;QTOuXRVI*eprckWPe|{*U@MBIhL;|j;nA+W@gN5M9|FIM2~5y#ZwJ!;>KC_`vUo< z@}W=Nt(tHv*QMNcwVfVT1>fWXJb$OynVZQqsS0;%A${(aR0|CNLo;pd8KyK8%4RI# z%7X_Sknt5BYnPdk*zsxO$~@Deb5%}K7%}hSQJKxONb%!uc>OKZIhiB!{(S;u#+SiD zk&Yna#)h*3?OoY!0aBO2cmwB*-e0_Y;Z5ozc{;f$1xgRoO_Nybv5WDvUu$9O^ggkQw?8x4H>Z$dbvdBKD&@>Zau8>o4o@3{td!rugS>)C>*H;7f@Z z^5XQ~Hy2rs)+DybnP8a8lsjT=YurR573cv?wAg%OqMc6i{c|;7#!^Vg=-AD2goee3 zNvFIF811pX_-74qkekS%;M|ejisfQ9c{;MUHX9=5l(X#ytK5w@rTdxY|1Gz6d(2h9 znd@O9VVuEpKsAVgycQ{4;x7D_iI`U>e&kD;9NTreK-pd38bgbss*4LWv~8Hr%c!!q zZ!UU1hD*oS7~`?>8IsF9MB?u~On7z{Q`^QG#OiaCUt>5g4obm2V7KAVhWMPC)gOe2 z9AIKoOn5D59o)8|dmpb*q8Rl0I$B_VqDMLk5DA&RN>N(|X_mM?D+eL| z=;+2>G~PwU>*uF zNMYX6rKYxD%AHF(TiU>x zkiT5N16n_or!SqZ)$Qx)E6GPNjN~PZ9Q5f$!iN73c>ZFrF-)X+wE~?U0Xd)NLjoke zQ3nm(%?p9#0SzZ)E60n*?*vKxS3UML44DKPau!@G97LJ6t@{F-xR?=SCD%BE=I45d z8W-*DM;zLIRXM)^al2Tzhw(Y{w`&M^5S0&3Knel^ZQ|+H50?rJynkm89fEYca_qTF zOZ`OSiL9Fz-4i$*^)`Z2lBd(6=c(b<+1Z=K6ni7L$K`b-dV+(RNejX>5p{j%#v^pw zd2BX2>sj}VICL=oip`jKuaNL>-CNg6v)YRU2%T3I6;q{1R|i6+!x-fBLTL={xaw2K z#%`?~A0$b*35<=DZT_BS2y7Yzl%qm1NI|CR4$CPPO<_G=$LM<{Bm^))s-R>|)ZW^y zfAWRV{EOsZg3|5#T~}ta%E7`wZMk z4vDmWM1W){^g8NvVpUFT?tA3lp}ro}K2{o(nCcZvG2fM*i*7Pwp%{XBEpO7*_zwBe z>hqOXj*%|^@~5?}i%FA`LRN#9WY2dOjFS%_xZdPur|7Jgn9>pI?yU&&ljrnap+d!4 zm~C$LNaIniIXbj$wnhCc$^4pDyR(!x_u-v87IYV(+B!~6CS$XD-y~kFPjc^9y;t4Z zb2`FxpR+qY?pqJ^u3nX#*|ZnLbS=U~Hh4EgvZJU2o04e_+E3yP6fd!^Om>eoq-KNl ze$1FDI`i%*ZX2{>j5VgS{#}~=GSl=C@5m1zlg+ds6K-2gIoram;wfTzO~+fqU}Z1H zlc0vDrcxb<11dY*uZtn6$8_hJQWqD z;lW4-`CE|TO(bXdUc?AujDht-LOekqYJ0givne7@{c&R{c1}HFA>Ya~f(7`GeZgMd zi^YY3a^8FI-_u3E`v}a#!8K}|5-%JC@D27~ITVt@SBf{jb0%n9H!)k&-%ya+f z&~l;Fw;%oG6|PFc`f-_6`C6c$IES76+}p-Czw?Cb}JA)E@Ux~XCMS-dr_*wF}S zRXqcP<@JiUZ>Ay{Mv9hn#9y|x30FP`LVS>d{SRQeHuIjW{1PhP4*9o6T5aJFw|GS` z7hsa=MFV6=a6SrnxxNb1Q=5%~ZHIJ{QoGeI{5NhP1KPXQ1^s&=-M@9#wD=35|Mqz zj{W%2LGL;pX8otg?|_BE>o{)1l^k{{S!GaOu6Q9cZXq(>t^X*0yejJK~fjz7(>Jf{0ixx#gzHXcJghxb!u9_4~ z2gj~*j7O&;JUi==^wcVi-Pn&j657EkPuL1S@71d}LX-l@rc<+1yLU|6gi4fXV<;ji z;q)xs(Qx()dDX!adyKb>Oxnl+Uf&Re+t&Zq8%Vj`wR97q`Utq3=*&!`X+#sfh0NW% z$?FpO z`t}%{TU7sNYKwtkm&3vLSHGt0mBfTxnryi=S-s3A+y}jh0(#S^kF;p=+``yPx7iN< z@15Oq&JjUI@gL79*qQ_?j{v7#Y3S+hoT)3j$xxl@2vm_jVK=D$K!x(h≦)ess8d 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png index 6d7f5f038171bf243b89e7e0d67581e0921c7df5..a6ea8972f330c3b60de970b50a37f014b747aa2f 100644 GIT binary patch literal 60151 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 literal 60676 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 Q;K8M?qODwd%Od!H02y`u>i_@% From 8a7f368db90a1b70114e9bc106913fb1d018eaee Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 13:13:01 +1000 Subject: [PATCH 1253/1892] Vertex label offset --- src/igraph/drawing/matplotlib/graph.py | 32 ++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index d6942d8ea..bb7e24247 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -210,6 +210,8 @@ def get_datalim(self): return (mins, maxs) def _draw_vertex_labels(self): + import numpy as np + kwds = self.kwds layout = self.layout vertex_builder = self.vertex_builder @@ -233,16 +235,34 @@ def _draw_vertex_labels(self): vertex.label_size, ) - art = mpl.text.Text( - *coords, + # Locate text relative to vertex in data units. This is consistent + # with the vertex size being in data units, but might be not fully + # satisfactory when zooming in/out. In that case, revisit this + # section + dist = vertex.label_dist + angle = vertex.label_angle + if vertex.size is not None: + vertex_width = vertex.size + vertex_height = vertex.size + else: + vertex_width = vertex.width + vertex_height = vertex.height + xtext = coords[0] + dist * vertex_width * np.cos(angle) + ytext = coords[1] + dist * vertex_height * np.sin(angle) + xytext = (xtext, ytext) + textcoords = 'data' + + art = mpl.text.Annotation( vertex.label, + coords, + xytext=xytext, + textcoords=textcoords, fontsize=label_size, ha="center", va="center", transform=self.axes.transData, clip_on=True, zorder=3, - # TODO: overlap, offset, etc. ) self._vertex_labels.append(art) @@ -292,17 +312,15 @@ def _draw_edge_labels(self): ) text_kwds["rotation"] = rotation - art = mpl.text.Text( - x, - y, + art = mpl.text.Annotation( label, + (x, y), fontsize=visual_edge.label_size, color=visual_edge.label_color, transform=self.axes.transData, clip_on=True, zorder=3, **text_kwds, - # TODO: offset, etc. ) self._vertex_labels.append(art) From a57011db4ebe2f7b71d8c408a737e51701d573d8 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 14:43:27 +1000 Subject: [PATCH 1254/1892] Correct logic in draw --- src/igraph/drawing/matplotlib/graph.py | 2 +- .../test_graph/graph_edit_children.png | Bin 24177 -> 22431 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index bb7e24247..5b2ed04bd 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -535,7 +535,7 @@ def draw(self, renderer, *args, **kwds): if not self.get_visible(): return - if (not self.get_children()) or self.stale: + if not self.get_children(): self._reprocess() # NOTE: looks like we have to manage the zorder ourselves diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png index 33fa772b2dfe4aa8da5819da407060178cb44a0f..14a9122d80c3d75900e9c77d4a09d04e540763f2 100644 GIT binary patch literal 22431 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%0AL z>@j}_C*BKImZU2!6k~lc0X#}6-On;6j=k+*dcZIc=M)a%P82fF&em+z1Qmse7A9_| z7O&bt)WT;b?`Xz@r5bw!DW~)+CD!NuC6gWucD{_3@5)Y3`K}-7t&{@NkFRD1o!WkI2|5JdHxJy%xCzaRa5lF8n zfWsx8K&E$zpmf9Tzw#2GS^zoK_wci!%WX4>vjg`FI+!*uX;|kkVLImuGH;F4?dZee z7d|CwP9n1}L8N`*s(cHCZT)`I3-HwOt@(?2vc9xnU-CM%4j04`3$5B_cbD%@Ed^fC zck=6RrhdGIOPDTve%_I+ID?jLdFe_Fdr9v-lIqTL_) z{?X@{y8LcX;lHki64#_K_Q=du`#V-rtY0+s%8(W~Wo||98n2M3j*c}4{w{D%#)+idLNOqr}7&p1}WsKO3`ATgS_ws&F~k)LYjsu=?SdUQKs# zGlqaPRaUtH3e<~>Tkh;<`S!?X`?7Fljf;R$4n&DQ8EQnAvA<(*Zl!D1*_9m~9S^vcXg~jjpIh^{D331vhzYof{>apuZInKkBbM)w?P`O+zH=w>o9WMXAvw+E2 z!2X7T4rAK+50?RA-XGcYp6@n4<1S$^sJ0MDCjA>5Yo15<}y5)8J*@-~q z8jH((2Tfbw-gHI(kivPX`{9apJ2sndrq-jqRL_LT9@8^hUtf55#kKH6!My{Q!CeP~ z?Ce5eD!?6n==rA`|7T_pgyU>9>1tmyYku{FGSaHg9i^hAwoUwZcSzT4!K8XnQ#&>w?9!1px7t# zK@fzb9fMbjxsKJDayBLN#635v-o!Mw%wUDw(d<3TIYe8bSDgA}*ET5S!!CLn=Z3k$ zK{TBEM{-C-t#yd7@NrhkX3sH(0o)XXcJNwHyDDjKBj5@kK>Bl7YVL?Pq72&U10DtO z3_s@?2aL??EQe{T+v^_pAK?$o!B|VY_z=?A&ygG;|G)qKdoMYP+W0_L=^*-hF2{z~ zz`d+{F$P2i2a#>M?P|j>muQ0w>YL_wKGP8=mo!Lay&&({8YQUjJ#m_&b)!~xik5A8znMA|A)!2~p!Tpl?9E_J!!XZCg2yWY`_2}Ei zuSPd&5Sh(-UVeOsN&T)dpCYM;IpMCGH%Tq~;*j!o$xC1RwH~w8`KNb=1c%mSI9hGr zxa)=l=C?QO7P8gQ?oj3rBv^s07UN-rL4q3rUe#bvr$&1AW6-CuNxS|C(N)b)ea@#4 z6(w|3q4|n5am+_27+d8{@)a!xNczDoso%Z&Om91Oy*66Q@po&cD9f)~<)1 zC6PNl+6F?zq*(o_4u;hZ9z00=77#rpHS|8Lklb)66T4h9rkAzq0^7$Sqjq>5J-iiskl5nfEp3#j#Tz8trxeR9+@TEhu#NrEdRn_bs<_Ph1FpoAy--+CAD z7W*uka>AfvzIE#sqTCXk?$>YO7?^@QZlHGS7@`ZF;@Th{Y^X$WZj~o~u>(_HO3ZvF zyYK{QP&w&lTAw=a(#$4&ymurAg=|cjGRUunqpDh;uo3ITjg`-rH_GAw`&EzWRz*vV`J$!{)^}@8POEY2pbwt>0RN`A3F8z46FfqsJKJkr|Q9vZ|DkyEr zq>Nk#4<`6xg5l1At;vPbNCJ<+1i@92zBkSE4ALVfKzmif{Jlto3zzzku1-r>fwlU+ zyfk|LY*jcF`2+3FAh+4@V2h8KZvvhI0@`$G^!q^&ZjQEmg7P9KUiy-eDMEUHy_;+r z&*MOj)#AkW2%Q1cB(q(x>YXlQy|o)NEg;u@AEU}a%(}lRmn_ILnqGxz4U(X-ixkpe z$%O9{J0pWvntZ{S?!jOw&K&%wgih|IQI;-Dp?yHnkAp)dJG4o&zL<0+APCyIK(2r< z-;3J&-|y(a4RD|bupku4ZO9qTJXKRqjqZQ~H3pFD3I4U7#5-l1@f1qKHM>NhZX41~cs3Hmw2kg5f`o0j(y5HeOh zN)1nrp`Q(dPOb~H%ty!sI{*V}q6aA88KCu@#I$%ROq=rLM8@_t0&3An2Mdn?P(oKD zT0J<>QBBRa;KVQyI?U3A`_rPL&{KCK1K0##ct)2QN4ZZ45@`>jJ%xxdFsDZ}rwQnr z;%yfAEugvt!7m`$5i%U51fVM*CJE^SkZYg7mnk*G?-lFCuOgl@S<|TkHfZ((h*N{f zWTwjlP)ev{MAI#eQAf+lCjq<0U*v%_%}**u{57_?Vu3LN)wW*IJ?GdIuhw$hyI%Eo zgnl_b``;q8WxueYOW*G2VBC@Rp)zg23mkeBfR!J z+3=r-t_es1k0wp_&mJbAxfEs=axZrDSE#Iq431=1f=5s*qvFC;`7I6HBlf;!E5=e5 zKfv)4-()|!P!!RG>ImSiZ*rWQnS^M*-|xbC+emm76|HL18%)XSj3PrJ52Zt8W83H8s2ucc6L4JAtEk;_FSx-aBB=O*SaSr zGWb zVeix9&j|O{XsfM}4o{BW6?m9mH^rEGUg?=XR6228>E?Cf09?sul<*8ZY6*=*&x}PL z5)b2L_pw38p0o_E`|(j5PQ%u>PcLN@|u~Tz&H`=EJeSXzv`w2}0C@aX|)}5Z(%aA)pZ8 z8wy4ZigB!*@ifgoa{2yex~bRKOPu{%Q}e(-#lf-vQ5>wilXmG6ATt?+q=2|3_0TT3 z3QA)YCY)dbBca|g2Y(l{!(@OQ@e#=Uf8c)x+HuxRZX>Hg4II`ZuP$lH$e$HOZNP#< zSQsZyxC?|2T)CG7G|b=rXN0eTb3|@;doPrLatZS}!?1XU0dxfJK)fLiS6-NUPk4jj zUVwL%XB&0%Tqo74Wijk^%%mN~u#HQz8yWbY>++am_5>ENo1Y!eW>KQO1cr+~zZLt0 zuZ)2o4ivIFUNXeDXjE@N$Xo;0`>>?)B$5Wvc^8BT)Hfq=k`PNw@Dd`C#_mzrXY`>% zz;DlRiexDJo$}}B2EeVirA*S`XT`VJgdq{!A|T+6e$R*4BOAe64@Wd-BP$WKOj@bi zL`2#Fxe|Nd(SmGX*}MeD!UzS0gj&Iq@^JgZ#gGAxeVrcb{=m}~)gEz}KTN?*1|_GW zV5DqlYh9{to^1z9mx-xq&ETE=@A^ObaLZq^##;z%F_hSA{frcdm^xVFiL6J|=IG@` zN5BJUFH=!a{!Wi}T~$Z=+S8ta%zXdsge1~hAtV#~q3mShZIs3PK}<0t}}}>E+06~PPpc*-l6gyjJQFHIP(v2`Ovx*3`ypxBuGx}eOl$LMUsz-0cOuPvM0!W+Mg zEZIR7v#`iNdgmM8eM)C(t|eG}>liZ6!EoCyLX&NO)xv1#JgT*w;W@Kjf8i*tpuFIH zI43**YR=l&l}NQa7M6#%3JCG0@@i?p8|d7sysHTl2!|ud9gT>WHNzNWiO_r71g?DZ z*J%Zi>oc|mlzSne67f0V{n{<*s$M5N?|UKE?R5Jj!XiKNep${HUM+d@eG1fHKsvt9 zEknVx|2`3D0c4Oo86oTFXYA69h-!<_I3#iMFL7$F%ByO|mJ(^{xA!Hxnv-(=!U(f) zj~Xp#5(X8$48bX-b{EDfTmvI!ch@}F$K)s7x$YM_hAh4I$p9xBEB#sBk9^iG@--R% z?A-fI-3zsaPIKb=nzL2yD3KFDVrrZP{X`S0L;@%Rej%=p+9WO~hh*}P2}PjrkKn|V z;P966c5T^2@WP2N9)4;}Te??sO}+xt)Z5dw<~7%yAzT|g!KSKVLe69>X>}n9AA|{z zSb~@i6S#k070v{+-*dk9oPU2RG+2J!wKuOQO#5=IS^CJ`Z~F9u3l4iiQAdzGv#QzP z*K2atW})>%8oOUTCvv#`YhFIO(jWWP>q2S@(efdW{Xt&2 z1E~jXttQ0tkhvhKL*xCW#~F^OYSHiVejjt6z0xz_HhR8?$4{p1N$m~I{467-rQgaw zJ#!xJ%OK6)yN76WAAC#D9^`T~XQ_QpMo|l(BtmS6J%l%v^eQ`yh46L8&9yMQ&b(P( z;Zq{)_F>Xdm%_PN4oEBf;wN45`XM6UpwT~JV}mYzdWSdMI9yUgkwp66U}8GbFdyn= zOfxzdZl^uf(SD~UTT)CtVgq@((n_LM1FfEf*9C${5@qI?5h{jd*5LjW{J$j*G%bk{vzEdQ|3;_+Ik9qetP z+D4VgFn^Wc1x;u`;-y{?Uk(A-454}sGWD$4&pdTq!t3Mg^l+f(T^AdfW(XAZ~;ndfAVgi#i@&={+#`*$ASU4dT~-?|a+D{-%f{Hy4rD zh}}H>;7EB0CdbIU>F*`TqEq$`6DF2e;?eNH{qEI~3vcNnr!8)Xx}>KmU0B^T?z7Q_ za!<3Hi%Pg1^~p=f_RxO>>(QcfcMS}cPbzJF&HV6+dE1r;hbr&Qv~uMCLEd;p9!`^Q z22JtD`*JTGUcuFVp`+lfj;~#{Y&93O0?<%WHG;`I61LBLOmf;G;2jKtFVIUJnyKED zatu^Pr_sneAs_BnrfIIipmWtXE?L{w`gA$&fuxL%f>YAc;Uj@j0~1m6oFdpL9_SFM zT8EH8GaVbG=E4sT**{o8eXv8=r(wy;%<;Tw#+W*jS z?#~Yfe1fTfQ&cTFri@gZ&-gw3rfoEs%Jn62^h|$2o#}ZX7)#`Hl)YQ}#-ai!x zr36(=1Lt&CL-TF%?AT*%k>cgS_ED7uD+{Cx>J+Efdt92aDfi}eBWE99b{vRBrO^8e_iI z;epBnb`NCVPn^gTTbje1vrO(zU||K8b|UTM!25?YU{4%s_tVD6dv!GX@PehwL>{$t zys^YP%9XL;byik;Xz+*C@0eN(4xO}d*i)pdn|QMXsy__ErtG^i@r~6(S%iH#c_U&m z3F`^ZkY33)0u%xZm^6h;C+g&dqoEuCRA=~1FYU*d0KDD_ntTC8#b#3%Wx4{nj=T#r t`y_ca=>NSF^#9&}`v1dgV&@c1V(1kq~YApvVFe$`~7{-Ie(w)I{Ug@dv9y4_wYQg;eOq(`}KrvGclMcASOVe zP-fB$_30D}&q4}?+hQso{^qLpaaa6H%X6cJ=MI;Ho<4is?I>IJdb&Egcse@lTj*`) z?&09#tg5W0tg5u|kf*1shqj7}(|^98?BZ^(Ql6+^g^NscHMI1gP=xl9KU}xR)JV>og@4he?dOWb|3@wV|Nr;@ z6RSZ__*J3NxIAdg_o$uy4n3LBZSwk>b8qZ;dUQ-vqV4OpGf62a{mDN)>)zinke|DF zuE5*ns+aOhrK{#_UHvR(*{r=^ z=dUH=&bF`LrAovnR<^db?&g!oi);Tq>++1%VuCw_1^RP8xwPMmb6&h=&C}8K#`Lr4 zA%={u6B?g=Lydz5#NP*vtM9+DU73F+tFt~XL?K>Cw2YC_BlGl=XWSfp&F>g^;G2o|I}9@eily59Sf)9|%p)W9U6 zR3iqRP8Dt*8>npQt>sfJYTG-8uCqu=SE>g!EZ^dtzIbKOo4?bsWrOF>tm@Y@v+uN!;&V)+Bb9G zpSs*&Mz(;jyiDjw?^A=*f|A^uWoVh9y!wnN`ulsk3~m(($@w>ETc6!DjW_<5Xor|! zb@na|frAx`B?S574H?H<7kgqsa@xA?C@3rLGg>AuO}SDi6FJqRtih^8!bIHg9jzSa*6vT7xoYRA=L#l+w3)X& z*1cJ$*tct;L|EUO4MMz<8yVcKc%A+q$cnCC^K zucwOCCOWtJjntTjMl7ZsbLGPV{LG&iJrZ-@;@Q?vK{~IT{^IgPtvLmgmrTtq*HUS; zvgb(CXO!GWH)hp{xf8f26E-EW4yRP&ibFBq=4wVHyQAQ=@3{y$Y_hNHut*O-k>uFYE zSFXHLvzMXOlyWZpTixlk`Sk-9$Mb7y*Irt(<#@y*+A(684C}0(hAZ<0FU=5AzsDUD z8~yg)uB>axe{UR{kWj(;;l6W+`<0@+;q?BcDw!U7Bq3=9yxDT83IgPfhqX z;d_>m%&r4u)y^;5^>{g4?Q_7umV*^nH@dmGjTNXneU2}UQMOZi;NvDm!;=n{e z^GVKDp4jKCuS{bVKX&{moYXno$WGr4iJlgu+?{Zn;KlnW%CL%swV)SR{hAiiXmoHy7g$^~gAFH)# zXZ&zK{E5dTF2tZ{FQ1^O?Z`#bTg0YWB9B!hA04c?!8}lEKK-DbUF4-pMQ){%^Hn52 z`FCg54u7l)DrpQ+ofDPI3KAOAU3R`|o=O|cd8T#*mA3@zC$O1Ddo?7LR%hAyvZA6j zyCov|NbP-{sEF?3eJd(8$2|{Dv`8x{sn}0mol!9TGtbcz>u2PS9GvJotv5x|fWb{d zpRDPhYq0KmdVYI<{^w7Y-ionbwKmnAXJm#uPt9CyIX$R2n#Wj=9e~LrpCanLoeOxHMkNgZ0$YG0pPP!E?b)T$O8vcAM}AJw5$#=v{Z=af@>w zgGVp5ZeS35IsEc5yT2{YlxhXBd2_BVNc|X|3V{KRLH5ZDd zxMaqA)o$V5#GTxeU8Ip@%=QVGV$3jg!n%31mG3Q!S*COD<4$d?dC_(QNi!#0B046< zebnJr|9f$lzV&Law;ukgsG}j0&7FPt<*c5kL)JE{B7x*3f;#lecRu@P)GTe3v$@H_eZn=&ui+av80{Z2jO;hXg-J91j& zRQnx)j~2BS1{N-Ja5(TTt*SXe`)#({{*rSGh`F&k6&X=t#DNp)^87sVJo5%Bb@VLA z%4~>L-gDTjbJ*t2&U^dbh?w_fwI?R;KdK%2x=c&@gS|%8kVxOc!Lt zvHFK$qVJb!l&fkE&%eI97QFVJn@)ZPxKWjjr0a{y%adzIWPRJnwadIGu*O;!9{yNUnu?{d|p`KWCuH4X1-03R>4Sx z3ukY9K6`z8zrwbV@;=Q*sL(EUPf1$PuRA9u92us&5ROwL>M|UvhYo5hDoUOg*I1&W zazQt6^i7UOdz8GS&Li(`tG0?bgS~qf4YXI?I@E1-R>NuWvSsJXpAOx0cy#c9z5S(x zge|rA_c(lb&@7aQ(0;MG==7ZM;;E;L>OHE~cz*w|Vx8W3YK=ACleJ-$Q{9X5E2@6q z?qyxp@o`R2kyLlW{a62bx1;dAM#k2wYN_lmi)pEqaB+qEiYdvoOH2CIC1WDGc34|i z!Z)jKYz(K6^(h$dc4@e3PER<<70H~7S6Fhe{PMG1E>Ab^-P!A#2> zcUkk@ZoG{_zn4)qoSM;`QEf6^Gn&dvqPxPEPc8-Lt31cHb$)n!v7Q~NIWjU*AN0GM za^S#$<$Iq`!PCugRip`=LS|=t7);sUQ=bzR8{515CLT=!yV%ce_I~h8R4-_?O8)R- z3Ig$gFE7Fl96ZPuZ^RHLv7Xk3dyIc>F%yZ77$5v};qz1f>RVf-wY|R|>b%WsWNf@( z<$MLc{9+=gnE@m2d^5%LX|!n+#Oh?1 z#(b_@4Caf6A%^s2X3^~Q$%)^kwVoE*jG~{N)eCgIl_*!PTv^>$$dhsC?cyd=MwBMm zgpI2lKg?2*#D1nd@RV>Zh9o;5BnYW{R)c zwr$(2q|OhPSYiL@6q#QE2z)aZtfc1e`O%%#Xo7$6_0%>Pqry5R$x$1Xygu$ZOEyy$ zE?pY_>XKYFHaBDkjb1_Cb7tLxy*${We)jD1n|wscX9%Gp0w=i*Sqoq6Tj5+V?kyl7 zK_Cc^20xn$6AbBti|vfbGizunJ`IHYDIKX+gGhMV#Gg#+gY59+qrX+7o(#<$hTgkpIw!*1SE%9iVg6+5O zbxhi&LmwXOC3|!fxT(hB+xvUru@St}=OKp)>JB#zZ$6!}A#7Hdes<53Zx$JcW>cQ} z54B|#jNc0$qNYrleuk-S|C`-E@w<1&+tQ}T?6)xfy2no6&L;^w*RafHh%OI-f6NP6 zwBeL%ox?3&_|0HEuRcBDfpdfQXZYgqW`m8=ffaEY7ph?0rs8ww&UO9dl*M&1GV$%$-`w)xI@Li47L;-~^GI!paVfuaKws#eH*%;hVPChhe|}SNJc_>>}4cX?AC4 zvAwqUPHjQ0uNQkOJPo~SrmN%?V*M#EU%%e>CfG zn(O*h@3Y1GNMOb0QAlJ)WHZo|5Y)UvHAA#lxW4nAm57buMDuCsoth==MP|-$k=<^^ zB6qDa1wxQXVsW?SAGR?}d2xAl=hoNJ{p|j?2GVBa+ucu2PM`1I;8lyLFzw{}b5d)r z_B7=3!@7emVl~gh84fi(@yheeI9#LnY+A~@zIQve5+nb2u7`y?wBub_6}2|Ol7E~S zu-v!v(8q^%$LAQO%KaanNd+F_lDot_3)Ab4Oe>hs)~)XEFO@bY4^?yb-wtYhRKY$e z(3`l?KD?Ss8VWS565*D|{i z5Mz`q*CTs-v{%}V{Ai7eirQvvZGy5Edv*h;1PQzvMN8CV@kEWe4F{Y8)c1GZO5*H7 zjZ~!J2}C>P3F`!;t$|OC6EWN5=en+>jq1&tRpWXJ zH>-sArX7k}{y=u_zCD`d#}7pV7+a~!iI(^G zf5Zj*-dFvLG@Pqrlx0O!=-vAPh7ga|ZHZg;>=b~W#ah#LtejNf&+YdmSDsiFr!nyDP}I7$RSl~f z`I@QWU{YogHX+A+)tAEt+jQ3e}5!Uirh%B8v>9k_OfmcuH1BTzBT0< z;>G58&B*fda_kR-SKq4~K_h#NZ9Gz{H~GpXB=^|(ozD6dO|rJON44X`)S4~~HCEx5 z7IzMA*m>7twu&S$!hP5BKLJ!wyW`pvxhT^;fAE9hSmS7zT;j`_8uhaf)*go37W4yZ z%t1E$n9Dqo+S(dV-%zW-eVdkeMyT$L4;yTv}6CVu_AMZ0%&@qzss=y2|m!$q5bY z)8yCyp3d#XY{YM5>BG5?nP0c>-d*1GEYvbTK#PKOydQxR;EFI7Q4jy&bJ}lb9`Vzf zmptnH+ovI}@WO^gnTl-K8+_8+gSw?0}fe0`PULY=wU8fy~#P+s0LN$~EhQr`7g$yz%` zd5=}IsPSp$Yr?*qlh%_8xqDZMK!@s^I{x24+|8JNhR#M%Tw4${?mHuUVaM`D1+FJ2 zi`2fePhRn8GaZ%RX=X&2sV^x-aZ_p0Va5B#CWZ>+^z@`dOcJzLIM-`FZ`Qvbamln6 zFX;|Da;RpBH0(@kD?SueH!x4|^31O%)^EP783~){>1%`o0kVqPRPXJ)m~m&7bN$Q0 zV>|?0Q^tP}wciL=79cP90xvjFu3F^^kT<~f;E0g6Y>DOdS>bhA?V%TRL20IYcCvjt zEgm~so(#T;^arSVIxlZE-gM1lz*JI*-FPd1ecPG0$p+N`64& zBpFgWf5S?H`%H4G3j$H)$T66F#ee(6TYiDS;!w~c)~LK9%S1P#OuPp6yT-~9@y zCRE7Kkfnex#vk}-xKc;>y6gM9;L?PF8E4CEx)>eJTZn3=qD-Yg0&ynwHMaYqxs}+f zhhYaiY%A(AL9bCMS64Z`MzJQXm#F3-Y#gIBZFwZq6#j1XYV(b58P#J9HkgpKYbtrdeTYa`q&-6v6*n6v|9)%0FS&uC`14ZI z*oiqNnp`2Mb2ddt&{Ds>r<(DQ>srqgyEwz;{Tc3o^@|?*|C|aoviqHx`JRoSXSjyH zKdSQWd&bXWLRAp4SQ|xu;@!!Z%lmbQ?SATdZ|{|PtG3hkL?a%eBd{46h*G6DxmxvL zIf_5#0eh@fXLMXyTxVw#za&$5k{cWefniUP`Q3{}%wJqU{BtIl$#yaARV8-8{Tc84 zK080H%#rb@D{S45YTrt57l0p317&8`g_<|nr}s0(u|7L;d-A5)Vfuiy3YKtuJXiPY zbOY&%7gl5IpK~{j|8VEC@iKd}otkR2{`xGW_hkU53n_4)uRu0Jd)dqewGP%D zUm3C1mTRHkU+`R?)x9h0CTdbbFDjM+623Syn;AI7TXkux?kgY~a>E5A(gcl^*|0Nc zbArSLcqQ%ld%3H)Lr={Jn-q>^9(bF+-$40E$6^Y~6i__ZZ{L;&q-31;S!<*<6FD(I zY>wZmc`a${PJc8}aNVo9xl~Y+6r69|s18|UUFHR6U9P30Y#{8An%GS8u-H{2Z8)9Q zBO5)wlSOw0waa}raY?_}w|cZ)Z%3N-(`zk;Y-gIW@&1lC*Za4q2~3~v2NsSz?iK7C z1B)QEIdQYv((tkki;hn?I}0vfId|WS3Jn6BLaGhfi6DwrY&b0_`?DeW{)N>)roy;L zEIhCm_N0yS`^sQPavo*I-fx3h>nx_kO9)mc8wfe)w8n(c4e7tSK0noIkM|Iyygd|! ztx0!lDIw0vN0M6gR=os;9XFTH&YmZ%JLlo7VcJn`{!EvurD;#wlFb?P*Szz0uSMvh zSRf7~j|!z*Y_l0MG@6GW=MkWVO2=K=bN7ygK}0C2<)Ug*>Y`9SbpfuLPCa3SQY5*VORS-;!De%mMt(m`;DyJ z>B+C{r8b{sX{k3+)7HBd&FpVM{!jPq|3aBVV|6PnWT}o0^;Y>$pXcgYl_*j5p0TZA z>(WX74n|^S#^|q{q0jy!!IL9GAe`>E-7%zhGcH})fHXz{1-Ad|%gDL&=ktpj(eEK- zB(U=X{XdsiwSV^SwX+%@&6s+60e3()f4dUb#1si}!2y|TBX11`CitaYf7O`(ez=b2 zRRWT0Q?7S6#RAD3@N24OB(qL&u1DtOuG=Jx`29E_6|WXnvvK2?yu?i#>iSi0L_YY- z1uOF@@wRcRhUmda&g*M7m+BpCiZ*v2?Yy;XHMNF@C}I2N+PeOa7p`wO{R2^f3d=k! z4p5p0(uWhZ70`++|M*B@*;1LAnu}#Zz3uD{aCbT;bXvs5l;mEYwJ~xkr9x=+MVnu} zRU+oQpY1&@Ij?E!B3fpVxJ%x%%PaO%NB~2N0W8-%0zcv`fa0TKVjj9SuZLYKC@CGl z!j*l$q8hd_`Flci@!L{~qDTWN8i<0Im6hIZIaITz`?)<|5PkWt?aB472MOZ5L0JJM zmf08PC6mR%VQ;XYQoc>cVD|KT=KnkF*)@FaiD{VAH?8kosOP{U)w`E110zQ18yl!n zg=4}(S<93b(q-WtFx(rB$;z}>cYvU0NN6q(3IM_K=x_~-SOe!}e1W!OpKlW?J0n^kq?M515^3ls4=h)NZ?d8oc^v>daH#{j%kPo)nVIx<~lf6_k5- z{;8SbD-lMWohy!?0f#baT ztP@ATl^#`duD^`kFDdxo_chW0TnD+n>{ar)DoCclCqBKETJ7;Xj^n!})ep}_Yjp+! zfj)V^4?EFws%besUHRIMTPBpdyK@*IVM;9zrV64Uk0y;Xmbs?HK}5|1c6MABlai{8 zRi4hp`-ko0id1Yy|CAMk1#SgFct(0_;_55K;q&<~8`5vUMvO>jPF+S$?lcO0E)?)3 zFC%3Xl$8ZnMKQ(f@$>Y1A>=DHy${QjlVKMWumbV@Ev0Bh(zlTH?VGJcV`=^Bs%b%k zVu`BioDcwQRj_5PF&BaRIzX#Vd;RyXJG&u!KJ8riI)|7B#|%G1x7PJ;g?&FPD2>$I_UouEJ|q?S(f@9FojG+Ix-0Oo-uiLhUET1f71*gx8t zLY^O06fV$v9IY{?Eok{Dap&wsL8}ohNns0D{^uK2A=!fZjN`HY3fb>&Z~rG`M}u}S z8lD=1mN}s$yX!J}Y*D|Ve$j1$fxjl6Xz+lVI+$vnCPfG+#1_hCREMxOer$sojCoHJ z*=c`}*2lq-Xa@yMjt@QBSA3R469KG3ST~k|mTBCWAE*U>j!Rxap&7;3HFWk7k%P|o z?1VL*P^M*mLP6*7@u4gQh4aC#cd1-*jGr6++G^&mf7u#g2LIR^yOQ$+*ykD(v?lg8 z6&~wv!4jwc31@W+$Trl%72Gw^wCF@9f&wo;fTV@40N#K-`Qz_SYn@oX2(eiEs`?SW zLPT`mvHnt!zMa8jjk4kI3F5LVBhaMAK z{gBV`=vU2mA64EkxFAKDDlgx76at!p)_-ix@L#s}pXW0l>S^d~EYN%KOEmy*2=KU~$&}uJmWyID_9&{pQg1Q< z5|0^$EVDbJ8qV=a?eq}x@T6JE*o9~|+}BK^8Cn2^f1(*D*yk3)25|HL#mKy3@oX;! z5lxw2qtO*!U?0!576K3%g9v7JwkElKOG32iwE5SK>0Q}B*~Siy`D-X7H;)bXV}rY- z{%%kg=m9ALZ~l8Q^9twHuj3`b?8gxVv)bJrTmA$ynCUZKMwjS+em~NGA-Ei*%G9;! zxRCpE42<5;MD9;a;IPSCdsc^VI+pPrv&MqX3`Hlo@qQgjeykqN{XmD;keV}4Vu6$iq2J1;7 zaUiU_HUw0>!ms~nVc*kBfm{Fij{RD)4fGxVj%P_hSD!zB4tGy|MO<+K!hyK9XGdZ2 ze481L<9X7m2WM>DxDn8U4(gh90-b@b2%Cu?v46uEvTFDDEYk{(7s1E846LlgG#WhT zpwi&7MSo~DihuHR&MF5@UqVYwgZF?FSJLH~cqwz?fon78_C>h;zTdb%z2VKhT^fLk zLXP7<91uzVv9iN`@S_)lN7fQYc+vvg(T<-_u|>>3C$3Rx;Ffau?^3hkNJKj|Q-(ye zg-ULp`cOkx?#-sb(8|>KOt=}lK!Uctk$nzT}u|&Q~s4W zHKU{QIF>AQhT6$CR!Kn@g+d6jKS|RF{Y*|uWOUWsDLpe==4E;L6k9Z%5zE%VNZpb0 za|_jh34AgU$Bx|3S@I{21&sV?;-=9!fe>%cUZpqDe?hC0d5QAh!WiBCZ$5JH2U~js z>^nut^5Kcp9k-A%jg&dDx+;W3S_QNZb~)#qgy@9}VeGG+`Td0jqc*5h4*n;OxwpPX zAbmyFpD1ToFBNXZuLmQ_H9YvqWdT471Yp=eqK)Es8AB0WWzyL>^#1Mw3QC(V>7`QW zpPK&W7&2f9dr)kZ<4ddodcKs^<3FqC&YOqs2kTE-PC~E0GuW%+&9QKme9;fuJ9Ll! zJOs<1@2Z$ONMhwbdrUR^8e1?XyT*TT3h9TPTcBFfxPWa!-h#wR(<>yDp{ggLtPtg- zFK{{hp~ht1EQk5SPBBymdoc~?a?o*KRNF7;j>@B81^6=k{dXN$Ea!$NZwrEhZNJ6t zM3;RZEQY-3eDb1=KreM7?McD9Xu4DXlQxG=XGoHdNy5p6a!VDBxrYxQQsm|3n~2Nc z`u?1JLDX$#q?uap+j73Y1vOhA)E&H+4Owgc3Fg%9i2WDV#Hd!So)hx$;Yz|JK&4Zd z%53@@ZZmR~bG{0Lq!ub9?IgXRfWojppE~OCd_lZr?%AGZy~a6zHE0e*J_?^4Q9@%JItuW385iLOeR8o7gzvJw-0wb^RN?QyHH)0SlYVG64WQ zlJ+zPjh7Py|GnR(DzCCtMof}213c9DP)Teok0V#2eaX4s!<}1$U*j#GKOLHgynFX9 zC5YRhYS=L>V>)6ImI~E~`*8DV)!>QTs2C|@wI{Q(#Sax+(%UYr8E43(Tz-uW-_ZNH z6e^0k6Lv8y#6(V=!0Z}Cli3X-2yUK`+G9J-#x5;tTDdqf0L|0_?2dwS`yD2vy^78L zq-JnHuWNTezg=Nxp}u#o_uc7{FPFl_kP~iq&6KZM{?|ZjI!nY|_O+DEO8+o-@cYj1 zhxVn;Ji@i33{R#^|=4*<{bNl+}MX z_?AO;sKcknPU?v}SX!hQ{17zr3;`f(NVMpxb)jrdy{UR%P9o^|x=`hz>8i3bCvO^Y z3YOF-VEJ@sh^d8SWVjXD*SMC%-8NTw(Hd)GJ+qx5%yAqNJN&y4TyOae9Au{Kp+tRu zcEy?^_4PtzY6LtEAjZo)q_n@_jtfA~oRzi-9{)u+eiB_dd$%eN_Oji|>NQlGuOQW? zkn-S9*Jm!A;UC8{H)gujEvm2%7ikT$x(C4%9SfcSL{2X zB4nD-PSB=}zC5i?@>^|MI|>Ti-Tjp;Sn*Yb`t%Pi(t<_lh!bzu`U10jigAs)JVvzR*0f8IOo;{nN)!GBkF@e5>XER4JmMW}! zT$VPv2#s*``{I6mtL1V1`PRS#sUQ3xtC+KLh%i4lSo=2fBFgZr1uZ}X8~H=I8#q01 zPBH3WkDi~$O_KyMz5MkAh`Sx^Eg)R$5M#m|eW3n*WVVq$efhPzRUJ3*Gx_{n{U z;43&1Ko8>**8aE?XYE;WH#c8-{-d>w>(Hmi%jWO#+z!}5W&>EZpR{L@I;R1Q-wf-Z z5j#p(ZCY!(X z*;+y1gw0b&3RL{C3eI7)1uBRY`%50ULH%%asHXxYqbM+yx}UkM*|G39vI?1N5a;qh zdQ%8O+zo}ZbI#J5S$`kl-7oZ220D^2a8G8nI-}?P;5u_IYHaUgNJ3FokDYSF!}KY` zztVy$p!F5Or8CLR2_u?v69oScI1RV!i`fRQXaP+@brAU3jAqsZyER(ll0UKp0}Faw zs80?+#f4xClEMh8r&Iv~1yb!$PZ8UAy)=yprVH_`>pv^kbw+B$=8LK?pJ^!6wAJSz2&Vyi?Pe|eV zk9Eo33LgJvlLwcke9x@4Cdw;UP4p#GojK1yD2hBXi_nAUG2DM~(FUT3<3?<8BAZJp z=p6mUvwQLeOjfykp0O5$QYT0AzKx3K$8m9!!JrUQ%gbo!T4AZOj zP$Au>s^AILzTjOw5LthQZ$XgHDnv{(Ql89h?eS|*FaTc&o1dn%kge=SUaM#v%8u93 zOSwAUrOrX~TnG&cC$grFaln-|L1&EkE1!Ca=J! zW`%?bYM)t}mbVhzoFZ6e7N=s(U1sqhL@p^nc(`Dh&rscwG(;j6=k|`fc({p6IX!}{ zW7#T)+Xv7-CJX{mo#-GF{<(w>RQOnQ-JNOHGuJ|ftqBLf5_F#ayS0aJ5xoWoz&Rm= z(?^Fqt3LX$7Uv!2lU_lpH}bj4<>h$=Wf*K=b|i-Yl%1% z35)y9Q-7bJ{%{)(1<#4dB&OUoxAr@^K=mNy0rY~dE$20~#h0Z_os>1^1Z>&LhjwL` zSNpk-4Uc|Hvj=r6gw{HlQeoNt{*w~o|A2{N4od3IsDAlJ8^ifdAt;Hk{=OoiM+aUB zQ>-!%7bCby!R2Z=9(lnQI^Z}RALZcRpBgC`H6a084XsMD`*CD_=Ia{KE368F)}W1K zJ~m948>df?$vf`gydxZwrG+X}}}LXUe9QaEw#j8edR(`coLQ3EbC^ zSg?F4nv-6}xi86Ybs?Iw1Buk%0($%yM2w^bLpmsCO&V?t({V)WT~<~CM3mEkyaB7J zQR`*>iFalN0Jj&>=a&fCAhae5{aGbAp71kbwVd`+#TC`l2y;@z@xImEneQl1n})ib zV^JCQ{|7`;h$IHf>FdbM3wNvCNm1*Fx7G6+GX~55jgZh5`-6}e$ALas zgv@oQ0{65mBc*5W-8G# z_0`1ekln$PNQczd?+zNuZOr)=&6Grn<8aegR-Sa&aqD4EoXerO$aUV93qG!0^+xy* zdq1y6u)@)A)g7*#yaW@l>(@1?v6nqM^_(l=|lEM{w7m%Zw&3I8o;;#oVN z=JgzTGkt1X-Q)cEye1QG2MxdJ~k>Z8ZJvAI(Q{%j`G)wM57M> zv3}BajJKgbKmNmAnS14(=K9XU1%>g3CmJ^6C5yFb-yL<6v@U6c(AMspxmzyup6X(c{VUjd<579>5}@O(dCVEiraZ{4 z##*E&Dc4X!!;Mmnh#&$GcWYAKYC)@lM6K4=pIZvmb1ABeXGf?kYmK_JwT%=$g=Vs; zZ5;hJIN|=5XQBMnWZVUkC+In9rV(S38|*gzv?XrXhq}IcinY!hUuCh@D8mzvg8HXV z3?xlb`_Qi+hw-5%wu5<5$b?F~@0T!`W|R^e`bAc2b`QakYNnj%UP_ z-Nx5^EndjC*t)H&UW;r%2-QJ@WgEG9F+uuhhUSzz)jdU|q40@aL4uN6^# z^ITdy+uFBNHZkDGE26heB)U9 ztgwqxp4YnL=LqzV>i+I)mP-QsTx`ySfFKvWU0;;2T$-3<9L6RX9zE(b>KPq115&%! zM=^jl3}xoc_YZ$?E!Ulwe4u3$sR}*k(pU`AjkMMU6d;JJbpzWOSWV&1R%!e}PPlqu#>2EuBqxj9t9EGgv9D zJhrnQeEF8<*O?M~97D1?B4PTXss}gc1xN&s^^bj((<9Q*0|%i~y1LqLWd*ysbH3+A z={F*pt0daceI$dmI$#sFrrSQ_ra)r4mLTo**U6NPtSV7~eoM=Hu2NR^YO1!OY-O0f z??87JBk3QVU8#@w@>fqGYSmhLZ4BK9l+qToX5>Gt~ zt1+4gWbW3U;3Ir~6ITa1fPbJl(-hL6*H`p{btxaY+Hapt4sn&&2cd@>b^0&ae7O*y zZsuCRT`i;;fD#3?bEDi*wtif??7Ylz3^zJ!$EC8YvIotWtUP6KIPNbxA76vzez^re)@!mou23J}%aemoMf9RJ{< za`%-V#N{WP{f%h?7y{pmu9f5Gyagc`$6#lq zHf))`a%Bf*BHpZ^)@%nh`Q4LyA$qAfH>U9HiJXMofM_@4zkhc$+P`8R9|nq7aVJGZ zMFg(Oe-ma7>gFXOj(Cq4{G! zjImb$o^4l;XhNO_vL#iSEIX;8JP*}IXszQp_5=!%Am6xu@TN*Sj7 zXmfkOFiNuO*EFA)qd76$5(?~OGPQUgEyE_&bR#_8t}ELOar=S!o4wwP`8)+qTI4nc zd3M&RPfS+5e*NY0{)j~y8nJj8vFr^oOtC&>vl5@D+Td`nKriawZMI8qg)B$9$!5qJ zAF91CDO9{~w}j{A1YdDYL1K>RQAR~acQ3z*9l|DuLO@Jt6R{_|Vwi{fAWiWAE`{w* z!xSQFD5CWy4{rc-d}uQAv1<6}sAt=z#qUb8jw6b!Nb@?PJN9#jk&%%vUhQR7l|AUH zeuKr2=VQL0>vrOxFA| z{e0lt<_%5{XB?6iSTUIBpN+-NA8Lfknz#=yFK>Cg)+G>Hy?yN)uFsOx_FRZ1LF&G$ z;gWc<9?f&5c|-}9H_{eIfnxe3IFu*I=qDbA$lGmPJlp+()~R2;`DJ52+*gJQ{!9?< ztIkl4S}UUr>&bWR@g#R%%a zR}DUmGadK1tb)!1vRyQTXkHiyQ|K-d(qn$wZs2BSxxj~4vQ1~lF|I=NO-f+=7Oi^o z!;3BQeBJWSDeZZZ@!YNAs=5rGAKL({ZqkTjP%P5-@$&EsGD(RBh9^tHXSY+Fbc`vg z?x-In5t3yOu5Wn7@6KKMa7KrO;J~-(Dqo+Sma0qkxQ8AqdbmFZ21Z~PiW1egwY`_!&8*!ZW6AmxvHlMvKfh9`vL7P@uT)gp--Ni| z_c-48390Hs|65v3OhYXgAE7KE!}%Dse^_+++_@R(cfBerYk~4;{F#?LgYgOUL>U08zS2Al zDkKp1FA~&I!cbusnmb+RQjBBSavHI3SZ145RBi&lg}f%6)q%s763 zMsaa*d4f(XUg=;}Vg)MC+@j0y{wJQD>mjq&($Z2kjHbUtu`LSAC3R~PYNJ-PFF?64 zpFlyZO$LPGK^OG@VyD!LhxLiye(Q5$Y)-b?nuKMRmU$Ct!Ee2CH4^2l0J6Z&OJNL? zEF$=3GtC~9Y!}kR9l$0X-(kd3MigtDoEZAr-p=zT^N2Z-<62o+6~6j2O`-+=-R<$K zX7$7^JvVnNu^q|VS-+QwHBxGMszc_C4z^xDEq&iiV*uPC>Ez}ozmK&EvTV)gWz)nDSoPBgS!vpJsdv%7K4fJLJ?`i)QJ>zYyCHkZ94%QhFB}sIbeP*Kxcw`JtVqNWhy}1-Ut3$>A^>L%MITNl zvQe-I!!fy84c_88IXN&l<~_i=Y7}L|-7djp$<;TvKeU@Z9&#*QG%)0+Vxo*dInNTF zV489A>SgDNgyNi(>dl=MM@@l#12>|>fEb{JS<Gh;OJEkpFS{Ibk)mQ=N`WL~=#f*Jz@ z*7-%3%gZ;DiWp8{ARVZN(CI^=$vP3C-VY3QP~HGlEHR1ih{4A^?Ns?zn!4%byj8H)@aK`sgFm&eq@jR zC~MKF-xD;_N|btJD=AAp|VH{#HCizK&6*=WWVgvDQzIk{M@jq**$B z7kB_z(>3fpnOA?_9Y`40;lX@P5>izSVX_kymMycxJX-&PLM#gzWXX4=7A|VEcf$(|PE3rnbJ}xP$j)`uOvi+KH~J{dC{t9= z^*J62^715I1^n*L(m98Lh-7eGumB>?$A~qLp`w{HJ|=Z{;d|jVsMD!%))?oJ( z((>}+!HHhL_LHL+05%jQe9-qTtv%0~x>ZOyDoC9$(UF{OJ8+|mU zwyfCsADHGX_IWq@qf7xM}z&an`XPG3q~tx8N5+NojM3)M+W94HU4n>GP-d&F! zujAwmlKU&;U%@tgL@&j}Y$7vl;UD7AoLozny>ms?-knHJwiN^gB8KA>FbQGu2x!vM z>PQa@eVi9rLwlYc^*Y&7mw9BqiVQS1w{=7vZoR+1rwo2a`tcM|99D5F!P|;>?NNly zR58rT>Y}X&n=Ok~Npr0Sg}52sLo5)u8v}5%nyH8H98!DT*IYy@2?~-cIk9WrPMQKa zgG1dG#VRlok-Q_>Sv6k<(7u2Zh0w(4V5dy)?ChLol3MpQEqHwCj+>jgu3^@M_#lF* z26$i7ancVcBC}A9pM9P|te^Z=vIMGAC_q%ua_oGY%#YUI)P+27ee?9 z2&qZ*B9oL<**BxVzFommAuU5(Q_|S~;3@uwOzM!fW!vTbn3xt=m@1qC0tLKIvGgaM zZ+9P&T!PjCO`W_57b!yt!Ag)3s9c;_(7SwzgrEnA3>>p#U}7Q&*Rr9|%r2oywIAP!S&R{lZ$a3w28>BFIABN3+|Q0q=MBJQ!W_$F`RpV=%h@r zbFgQ61+nL4^Zp-D{aQ^46US}c4D2J?u;d60E|f(rm=@2}H)74f9z^MrG3CbX-%vW- zbtMPceEIYn(x;kVQ!?LRlBoiu_mn~uXH_Ko{psV~ zs73MqfPaTbcgB#_9SFFOV?$0DQrF|)jqe}QQQxWqBXdqaG~)Vik?_A`Z5$8)19d25Lb8ovtPJvnDjS2Y5q&chYJf2St*U@1WNK2f1m^oT#dtn!0Ah~o zqzgs8=MN7nMJ>d~VF^+7f0J=%bV21oO?mL+hdU^NHNZDlR_y14l;MtRJG!iw%6@sQ~-KOQ3~7{c(*!UkyHvKR{#3; ze)~f|Rg5I4eK?|WRWe{XXmD~S05ChDHWCt-3WvE?Z_yy9cksAEP3Bg%EX(3MwZ;-r zL)a$pmsx;+BV=^+w`r#^)Owmo98m>g4#or+gxk={120g5{T?oBx$x+F?#3^_PZfEF z7atNkPnSN!Rb2S+r|0Jj`ts+C4Uun-v{&w4X-gq8OiN44Mx9V7HYt0p z#M(D5{>k<5*s8+HHU*<&C)Y0OJ1qYqeC@$dzTK{GH_nh+eHjD|NkVQF>a{q|1W(ig zxeYlcA#9|Xni>O;$M8OkR9K$4CJt%tvtPR;I0J9dOUSvTK>btHrJ%ROMQ!l12^x`& zwK=Mg1~OPeL{L>z_`2SMT(iTx%SC*buSuwRD_?8vBZ)N>fgEqj-*ac~CiXF+UcjB0 ziU^C-39Lr>2+`#5@viQZKtw)05-=u$WT@kNfon>ogX53fe{z;DPD52oxVim1&Kfa~ z=Jw&rI=vqF*xmP*2`6QOQ%3jSyxNSa;D@+P%T*E%dtm$QIN~~2rogtQRpg*wY@#!Qmd530Ny*zQHy5gxh3q=^mMA)Mkn(s`_M)K! z2S~L-C{qHMLZ5*CKN5lQdA+LysnF!&3;n^#8d29fpSN~02%d7EhlpZ(a0=WM8+31> z=*97DI5dCVR`O%G%3^M}r%& zO&Sd2H2ITMUT9fpMrZzC5wdC7@0CPGL#Fz|3myCe9^HmVX2FCK<2E?{i% zQ@}RsO5K`xf1e6&cN|{O;3o&NjvT2ci{o|}rbnQKz!^092*L;;{jtO2X^7Zr`N=yW zj$B%A*+mjCX_ZY*39>56@u}HTIKE(k(ysh?^s$#?T0LqTd7^tH2!R_yU_kk@Q}aGd zm7qvOF(fgf5tnGp)kw!FV5-72+b)&@_tje|ZUeo+RhWd9@RXn#$z%T%6#gfwCT9e$ z!F5lLo&F{>dlRqZePJ8| zm@zg|HS(!(QVRU|pWoPF=xKmV>tj1FXoTdi<7d5C-W0|obYKMImpIZ=c*(L33IkGF zl+}*|)84OXQZkF2c^9)Dw{in%bVU+S=tk&VI;~uJNW$}?;>(Gi;OWz+^HeONg^`0D zQ=&#Z+SyO&~^Byqq3VX>q zM4=Om?isBK}T-YK1C(F`}IzK;>JGo%Ny3*T>s*v-MQyX&Sigp?QIT?zkAgiMj zHyIP1zNBNJ*@NzGX(SUpO%nz^jB|77DY(WOD*~N%PL-(3(;`slzaE$U*lE|G%eynR zI5IR$bUA1+>zo`iN)E=8ERy`(FB;%;lAB%ceV%!QuP?|?YyO@9H*$gN>v10LJkO~R zs8-|9CI|4v7bx@jBoE3}&OCY9Ys}L<`J}Dll%PUW!1mVAohB;?9Gq%aUK&j@&ekJFz$x1A3$?)ik z$1xXljuA!2bmi=Y&!$0GgKC*Ux5kkJRb#)>;yt@kvMBgjEcGHPZnST=(>QD`+ zSDd)-E7CF{s$iJPL1GbNKRKwOod1)~N0Gagl753PZD`dSGY6YvO zS01R`m|J{GbNPpZ!0Pu|`|Bd{qH zu{8xaT?<|yUm69>LHxi2f#T;?GFVdQ&MBb@00OW`EC2ui From c8ef8175a62311a255b38cba1cef40b5fdffcab7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 14:48:54 +1000 Subject: [PATCH 1255/1892] Try new conditional import for matplotlib --- src/igraph/drawing/matplotlib/graph.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 5b2ed04bd..0524d052b 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -28,6 +28,10 @@ __all__ = ("MatplotlibGraphDrawer",) mpl, plt = find_matplotlib() +if mpl is not None: + Artist = mpl.artist.Artist +else: + Artist = object ##################################################################### @@ -81,7 +85,7 @@ def method(self, *args, **kwargs): "set_picker", ) ) -class GraphArtist(mpl.artist.Artist, AbstractGraphDrawer): +class Graph(Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. Arguments: @@ -250,7 +254,7 @@ def _draw_vertex_labels(self): xtext = coords[0] + dist * vertex_width * np.cos(angle) ytext = coords[1] + dist * vertex_height * np.sin(angle) xytext = (xtext, ytext) - textcoords = 'data' + textcoords = "data" art = mpl.text.Annotation( vertex.label, @@ -619,7 +623,7 @@ def draw(self, graph, *args, **kwds): ax = self.ax # Create artist - art = GraphArtist( + art = Graph( graph, vertex_drawer_factory=self.vertex_drawer_factory, edge_drawer_factory=self.edge_drawer_factory, From 5659847341eede1383c27714578cae244b00858b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 14:55:08 +1000 Subject: [PATCH 1256/1892] Try again with mpl imports --- src/igraph/drawing/matplotlib/graph.py | 4 ++-- tests/drawing/matplotlib/test_graph.py | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 0524d052b..1d5854f2e 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -28,9 +28,9 @@ __all__ = ("MatplotlibGraphDrawer",) mpl, plt = find_matplotlib() -if mpl is not None: +try: Artist = mpl.artist.Artist -else: +except AttributeError: Artist = object ##################################################################### diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index 594b7489e..bbc7554d2 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -15,6 +15,7 @@ try: import matplotlib as mpl + mpl.use("agg") import matplotlib.pyplot as plt except ImportError: @@ -68,16 +69,20 @@ def test_mark_groups_squares(self): plt.close("all") g = Graph.Ring(5, directed=True) fig, ax = plt.subplots() - plot(g, target=ax, mark_groups=True, vertex_shape="s", - layout=self.layout_small_ring) + plot( + g, + target=ax, + mark_groups=True, + vertex_shape="s", + layout=self.layout_small_ring, + ) @image_comparison(baseline_images=["graph_edit_children"], remove_text=True) def test_mark_groups_squares(self): plt.close("all") g = Graph.Ring(5) fig, ax = plt.subplots() - plot(g, target=ax, vertex_shape="o", - layout=self.layout_small_ring) + plot(g, target=ax, vertex_shape="o", layout=self.layout_small_ring) graph_artist = ax.get_children()[0] dot = graph_artist.get_vertices()[0] dot.set_facecolor("blue") @@ -87,7 +92,7 @@ def test_mark_groups_squares(self): def test_gh_587(self): plt.close("all") g = Graph.Ring(5) - with overridden_configuration('plotting.backend', 'matplotlib'): + with overridden_configuration("plotting.backend", "matplotlib"): plot(g, target="graph_basic.png", layout=self.layout_small_ring) @@ -169,8 +174,7 @@ def test_clustering_directed_small(self): g = Graph.Ring(5, directed=True) clu = VertexClustering(g, [0] * 5) fig, ax = plt.subplots() - plot(clu, target=ax, mark_groups=True, - layout=self.layout_small_ring) + plot(clu, target=ax, mark_groups=True, layout=self.layout_small_ring) @image_comparison(baseline_images=["clustering_directed_large"], remove_text=True) def test_clustering_directed_large(self): From 495ce27a930c7939f9c8d7afe4fd1b21f2629548 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 6 Apr 2023 15:01:04 +1000 Subject: [PATCH 1257/1892] New try for import of Artist --- src/igraph/drawing/matplotlib/graph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 1d5854f2e..f60c354c2 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -18,7 +18,7 @@ from igraph._igraph import convex_hull, VertexSeq from igraph.drawing.baseclasses import AbstractGraphDrawer -from igraph.drawing.utils import Point +from igraph.drawing.utils import Point, FakeModule from .edge import MatplotlibEdgeDrawer from .polygon import MatplotlibPolygonDrawer @@ -31,7 +31,7 @@ try: Artist = mpl.artist.Artist except AttributeError: - Artist = object + Artist = FakeModule ##################################################################### From 3f6bdbbea4af46e9dbdadb30c0e7877008adc738 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 6 Apr 2023 23:43:24 +0200 Subject: [PATCH 1258/1892] fix: allow NumPy integers as colors when plotting, closes #656 --- src/igraph/drawing/colors.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 67d226d97..4c977e04b 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -84,14 +84,14 @@ def get(self, v): return self._cache[v] except KeyError: pass - if isinstance(v, int): + if isinstance(v, str): + result = color_name_to_rgba(v) + else: if v < 0: raise IndexError("color index must be non-negative") if v >= self._length: raise IndexError("color index too large") result = self._get(v) - else: - result = color_name_to_rgba(v) self._cache[v] = result return result @@ -466,7 +466,7 @@ def color_name_to_rgba(color, palette=None): try: components = palette.get(color) except AttributeError: - raise ValueError("palette index used when no palette was given") + raise ValueError("palette index used when no palette was given") from None if len(components) < 4: components += [1.0] * (4 - len(components)) else: From db979528eb1634252b1b89bdcca33907acee64fa Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Fri, 7 Apr 2023 19:26:47 +1000 Subject: [PATCH 1259/1892] matplotlib artist: Graph.set --- src/igraph/drawing/matplotlib/graph.py | 79 ++++++++++++++++++-------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index f60c354c2..bc0607907 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -36,6 +36,14 @@ ##################################################################### +class _Unset: + def __repr__(self): + return "" + + +_UNSET = _Unset() + + # NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py def _stale_wrapper(func): """Decorator to manage artist state.""" @@ -101,26 +109,31 @@ def __init__( graph, vertex_drawer_factory=MatplotlibVertexDrawer, edge_drawer_factory=MatplotlibEdgeDrawer, + mark_groups=None, layout=None, - mark_groups=False, palette=None, **kwds, ): super().__init__() self.graph = graph - self.layout = self.ensure_layout(layout, graph) self.vertex_drawer_factory = vertex_drawer_factory self.edge_drawer_factory = edge_drawer_factory - self.mark_groups = mark_groups - self.edge_curved = self._set_edge_curve(**kwds) - self.palette = palette self.kwds = kwds + self.kwds["mark_groups"] = mark_groups + self.kwds["palette"] = palette + self.kwds["layout"] = layout + self._kwds_post_update() + + def _kwds_post_update(self): + self.kwds["layout"] = self.ensure_layout(self.kwds["layout"], self.graph) + self.edge_curved = self._set_edge_curve(**self.kwds) self._clear_state() + self.stale = True def _clear_state(self): - self._vertex_artists = [] - self._edge_artists = [] + self._vertices = [] + self._edges = [] self._vertex_labels = [] self._edge_labels = [] self._group_artists = [] @@ -130,8 +143,8 @@ def get_children(self): artists = sum( [ self._group_artists, - self._edge_artists, - self._vertex_artists, + self._edges, + self._vertices, self._edge_labels, self._vertex_labels, ], @@ -166,7 +179,7 @@ def _set_edge_curve(self, **kwds): def get_vertices(self): """Get vertex artists.""" - return self._vertex_artists + return self._vertices def get_edges(self): """Get edge artists. @@ -174,7 +187,7 @@ def get_edges(self): Note that for directed edges, an edge might have more than one artist, e.g. arrow shaft and arrowhead. """ - return self._edge_artists + return self._edges def get_groups(self): """Get group/cluster/cover artists.""" @@ -197,9 +210,10 @@ def get_datalim(self): import numpy as np vertex_builder = self.vertex_builder + layout = self.kwds["layout"] - mins = np.min(self.layout, axis=0) - maxs = np.max(self.layout, axis=0) + mins = np.min(layout, axis=0) + maxs = np.max(layout, axis=0) # Pad by vertex size, to ensure they fit if vertex_builder.size is not None: @@ -217,7 +231,7 @@ def _draw_vertex_labels(self): import numpy as np kwds = self.kwds - layout = self.layout + layout = self.kwds["layout"] vertex_builder = self.vertex_builder vertex_order = self.vertex_order @@ -334,9 +348,9 @@ def _draw_groups(self): from igraph.clustering import VertexClustering, VertexCover kwds = self.kwds - palette = self.palette - layout = self.layout - mark_groups = self.mark_groups + palette = self.kwds["palette"] + layout = self.kwds["layout"] + mark_groups = self.kwds["mark_groups"] vertex_builder = self.vertex_builder if not mark_groups: @@ -433,7 +447,7 @@ def _draw_groups(self): def _draw_vertices(self): """Draw the vertices""" graph = self.graph - layout = self.layout + layout = self.kwds["layout"] vertex_drawer = self.vertex_drawer vertex_builder = self.vertex_builder vertex_order = self.vertex_order @@ -449,7 +463,7 @@ def _draw_vertices(self): ) for vertex, visual_vertex, coords in vertex_coord_iter: art = vertex_drawer.draw(visual_vertex, vertex, coords) - self._vertex_artists.append(art) + self._vertices.append(art) def _draw_edges(self): """Draw the edges""" @@ -478,7 +492,7 @@ def _draw_edges(self): src, dest = edge.tuple src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] arts = drawer_method(visual_edge, src_vertex, dest_vertex) - self._edge_artists.extend(arts) + self._edges.extend(arts) def _reprocess(self): """Prepare artist and children for the actual drawing. @@ -487,13 +501,15 @@ def _reprocess(self): marshalled to their specific artists. """ # clear state and mark as stale + # since all children artists are part of the state, clearing it + # will trigger a deletion by the backend at the next draw cycle self._clear_state() self.stale = True # get local refs to everything (just for less typing) graph = self.graph - palette = self.palette - layout = self.layout + palette = self.kwds["palette"] + layout = self.kwds["layout"] kwds = self.kwds # Construct the vertex, edge and label drawers @@ -548,16 +564,31 @@ def draw(self, renderer, *args, **kwds): for art in children: art.draw(renderer, *args, **kwds) + def set( + self, + **kwds, + ): + """Set multiple parameters at once. + + The same options can be used as in the igraph.plot function. + """ + if len(kwds) == 0: + return + + self.kwds.update(kwds) + # NOTE: this also clears the state and sets the stale property + self._kwds_post_update() + def contains(self, mouseevent): """Track 'contains' event for mouse interactions.""" props = {"vertices": [], "edges": []} hit = False - for i, art in enumerate(self._edge_artists): + for i, art in enumerate(self._edges): edge_hit = art.contains(mouseevent)[0] hit |= edge_hit props["edges"].append(i) - for i, art in enumerate(self._vertex_artists): + for i, art in enumerate(self._vertices): vertex_hit = art.contains(mouseevent)[0] hit |= vertex_hit props["vertices"].append(i) From c261f28b0eccb93238177326f70f67dc734f877d Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 8 Apr 2023 14:06:20 +1000 Subject: [PATCH 1260/1892] Add specific set methods via decorator --- src/igraph/drawing/__init__.py | 5 ++- src/igraph/drawing/graph.py | 2 +- src/igraph/drawing/matplotlib/graph.py | 49 +++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 5ae708ccc..06bcda90a 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -264,13 +264,16 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): warn("%s does not support plotting" % (obj,)) return else: - plotter( + result = plotter( backend, target, palette=palette, *args, **kwds, ) + # NOTE: for matplotlib, result is the container Artist. It would be + # good to return this instead of target, like we do for Cairo. + # However, that breaks API so let's wait for a major release if save_path is not None: if backend == "matplotlib": diff --git a/src/igraph/drawing/graph.py b/src/igraph/drawing/graph.py index ce56fe7ad..aa38d0571 100644 --- a/src/igraph/drawing/graph.py +++ b/src/igraph/drawing/graph.py @@ -555,4 +555,4 @@ def __plot__(self, backend, context, *args, **kwds): "drawer_factory", DrawerDirectory.resolve(self, backend)(context), ) - drawer.draw(self, *args, **kwds) + return drawer.draw(self, *args, **kwds) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index bc0607907..ff2c06afa 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -81,6 +81,52 @@ def method(self, *args, **kwargs): return cls +def _additional_set_methods(attributes, cls=None): + """Decorator to add specific set methods for children properties.""" + if cls is None: + return partial(_additional_set_methods, attributes) + + def make_setter(name): + def method(self, value): + self.set(**{name: value}) + return method + + for attr in attributes: + desc = attr.replace('_', ' ') + method = make_setter(attr) + method.__name__ = f"set_{attr}" + method.__doc__ = f"Set {desc}." + setattr(cls, f"set_{attr}", method) + + return cls + + +@_additional_set_methods( + ( + "vertex_color", + "vertex_size", + "vertex_font", + "vertex_label", + "vertex_label_angle", + "vertex_label_color", + "vertex_label_dist", + "vertex_label_size", + "vertex_order", + "vertex_shape", + "vertex_size", + "edge_color", + "edge_curved", + "edge_font", + "edge_arrow_size", + "edge_arrow_width", + "edge_width", + "edge_label", + "edge_background", + "edge_align_label", + "autocurve", + "layout", + ) +) @_forwarder( ( "set_clip_path", @@ -576,7 +622,6 @@ def set( return self.kwds.update(kwds) - # NOTE: this also clears the state and sets the stale property self._kwds_post_update() def contains(self, mouseevent): @@ -693,3 +738,5 @@ def draw(self, graph, *args, **kwds): # Autoscale for x/y axis limits ax.autoscale_view() + + return art From cfdbe4af569c82906db06b53e791db2c96471f77 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 8 Apr 2023 14:25:05 +1000 Subject: [PATCH 1261/1892] Add docs on new feature in example from gallery --- doc/examples_sphinx-gallery/visual_style.py | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py index 8273edfd6..9d33968a1 100644 --- a/doc/examples_sphinx-gallery/visual_style.py +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -47,3 +47,25 @@ # default, you can use igraph's `configuration instance # :class:`igraph.configuration.Configuration`. A quick example on how to use # it can be found here: :ref:`tutorials-configuration`. + +# %% +# In the matplotlib backend, igraph creates a special container +# :class:`igraph.drawing.matplotlib.graph.Graph` which is a matplotlib Artist +# and the first child of the target Axes. That object can be used to customize +# the plot appearance after the initial drawing, e.g.: +g = ig.Graph.Barabasi(n=30, m=1) +fig, ax = plt.subplots() +ig.plot(g, target=ax) +artist = ax.get_children()[0] +# Option 1: +artist.set(vertex_color="blue") +# Option 2: +artist.set_vertex_color("blue") +plt.show() + +# %% +# .. note:: +# The ``artist.set`` method can be used to change multiple properties at +# once and is generally more efficient than multiple calls to specific +# ``artist.set_...` methods. + From c665543e2983fbeabf855ced7e370290a8b50866 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Apr 2023 11:33:35 +0200 Subject: [PATCH 1262/1892] feat: added Graph.Triangular_Lattice() and Graph.Hexagonal_Lattice(), closes #658 --- src/_igraph/graphobject.c | 110 ++++++++++++++++++++++++++++++++++++-- tests/test_generators.py | 35 ++++++++++++ 2 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 8986018e1..dcbb0bd87 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2583,6 +2583,47 @@ PyObject *igraphmodule_Graph_Growing_Random(PyTypeObject * type, return (PyObject *) self; } +/** \ingroup python_interface_graph + * \brief Generates a regular hexagonal lattice + * \return a reference to the newly generated Python igraph object + * \sa igraph_hexagonal_lattice + */ +PyObject *igraphmodule_Graph_Hexagonal_Lattice(PyTypeObject * type, + PyObject * args, PyObject * kwds) +{ + igraph_vector_int_t dimvector; + igraph_bool_t directed; + igraph_bool_t mutual; + PyObject *o_directed = Py_False, *o_mutual = Py_True; + PyObject *o_dimvector = Py_None; + igraphmodule_GraphObject *self; + igraph_t g; + + static char *kwlist[] = { "dim", "directed", "mutual", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, + &o_dimvector, &o_directed, &o_mutual)) + return NULL; + + directed = PyObject_IsTrue(o_directed); + mutual = PyObject_IsTrue(o_mutual); + + if (igraphmodule_PyObject_to_vector_int_t(o_dimvector, &dimvector)) + return NULL; + + if (igraph_hexagonal_lattice(&g, &dimvector, directed, mutual)) { + igraphmodule_handle_igraph_error(); + igraph_vector_int_destroy(&dimvector); + return NULL; + } + + igraph_vector_int_destroy(&dimvector); + + CREATE_GRAPH_FROM_TYPE(self, g, type); + + return (PyObject *) self; +} + /** \ingroup python_interface_graph * \brief Generates a bipartite graph from an incidence matrix * \return a reference to the newly generated Python igraph object @@ -2730,9 +2771,9 @@ PyObject *igraphmodule_Graph_K_Regular(PyTypeObject * type, } /** \ingroup python_interface_graph - * \brief Generates a regular lattice + * \brief Generates a regular square lattice * \return a reference to the newly generated Python igraph object - * \sa igraph_lattice + * \sa igraph_square_lattice */ PyObject *igraphmodule_Graph_Lattice(PyTypeObject * type, PyObject * args, PyObject * kwds) @@ -3547,6 +3588,47 @@ PyObject *igraphmodule_Graph_Tree_Game(PyTypeObject * type, return (PyObject *) self; } +/** \ingroup python_interface_graph + * \brief Generates a regular triangular lattice + * \return a reference to the newly generated Python igraph object + * \sa igraph_triangular_lattice + */ +PyObject *igraphmodule_Graph_Triangular_Lattice(PyTypeObject * type, + PyObject * args, PyObject * kwds) +{ + igraph_vector_int_t dimvector; + igraph_bool_t directed; + igraph_bool_t mutual; + PyObject *o_directed = Py_False, *o_mutual = Py_True; + PyObject *o_dimvector = Py_None; + igraphmodule_GraphObject *self; + igraph_t g; + + static char *kwlist[] = { "dim", "directed", "mutual", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, + &o_dimvector, &o_directed, &o_mutual)) + return NULL; + + directed = PyObject_IsTrue(o_directed); + mutual = PyObject_IsTrue(o_mutual); + + if (igraphmodule_PyObject_to_vector_int_t(o_dimvector, &dimvector)) + return NULL; + + if (igraph_triangular_lattice(&g, &dimvector, directed, mutual)) { + igraphmodule_handle_igraph_error(); + igraph_vector_int_destroy(&dimvector); + return NULL; + } + + igraph_vector_int_destroy(&dimvector); + + CREATE_GRAPH_FROM_TYPE(self, g, type); + + return (PyObject *) self; +} + /** \ingroup python_interface_graph * \brief Generates a graph based on the Watts-Strogatz model * \return a reference to the newly generated Python igraph object @@ -13663,6 +13745,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param citation: whether the new edges should originate from the most\n" " recently added vertex.\n"}, + /* interface to igraph_hexagonal_lattice */ + {"Hexagonal_Lattice", (PyCFunction) igraphmodule_Graph_Hexagonal_Lattice, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "Hexagonal_Lattice(dim, directed=False, mutual=True)\n--\n\n" + "Generates a regular hexagonal lattice.\n\n" + "@param dim: list with the dimensions of the lattice\n" + "@param directed: whether to create a directed graph.\n" + "@param mutual: whether to create all connections as mutual\n" + " in case of a directed graph.\n"}, + /* interface to igraph_incidence */ {"_Incidence", (PyCFunction) igraphmodule_Graph_Incidence, METH_VARARGS | METH_CLASS | METH_KEYWORDS, @@ -13777,11 +13869,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " either \"in\", \"out\", \"mutual\" or \"undirected\"\n" "@param center: Vertex ID for the central vertex in the star.\n"}, - // interface to igraph_lattice + // interface to igraph_square_lattice {"Lattice", (PyCFunction) igraphmodule_Graph_Lattice, METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Lattice(dim, nei=1, directed=False, mutual=True, circular=True)\n--\n\n" - "Generates a regular lattice.\n\n" + "Generates a regular square lattice.\n\n" "@param dim: list with the dimensions of the lattice\n" "@param nei: value giving the distance (number of steps) within which\n" " two vertices will be connected.\n" @@ -14013,6 +14105,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " undirected graphs.\n" }, + /* interface to igraph_triangular_lattice */ + {"Triangular_Lattice", (PyCFunction) igraphmodule_Graph_Triangular_Lattice, + METH_VARARGS | METH_CLASS | METH_KEYWORDS, + "Triangular_Lattice(dim, directed=False, mutual=True)\n--\n\n" + "Generates a regular triangular lattice.\n\n" + "@param dim: list with the dimensions of the lattice\n" + "@param directed: whether to create a directed graph.\n" + "@param mutual: whether to create all connections as mutual\n" + " in case of a directed graph.\n"}, + /* interface to igraph_watts_strogatz_game */ {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, METH_VARARGS | METH_CLASS | METH_KEYWORDS, diff --git a/tests/test_generators.py b/tests/test_generators.py index 25bfb56d9..104f27cf3 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -129,6 +129,24 @@ def testFullCitation(self): self.assertRaises(ValueError, Graph.Full_Citation, -2) + def testHexagonalLattice(self): + el = [ + (0, 1), (0, 6), (1, 2), (2, 3), (2, 8), (3, 4), (4, 10), + (5, 6), (5, 11), (6, 7), (7, 8), (7, 13), (8, 9), (9, 10), + (9, 15), (11, 12), (12, 13), (13, 14), (14, 15) + ] + g = Graph.Hexagonal_Lattice([2, 2]) + self.assertEqual(sorted(g.get_edgelist()), el) + + g = Graph.Hexagonal_Lattice([2, 2], directed=True, mutual=False) + self.assertEqual(sorted(g.get_edgelist()), el) + + g = Graph.Hexagonal_Lattice([2, 2], directed=True, mutual=True) + self.assertEqual( + sorted(g.get_edgelist()), + sorted(el + [(y, x) for x, y in el]) + ) + def testLCF(self): g1 = Graph.LCF(12, (5, -5), 6) g2 = Graph.Famous("Franklin") @@ -346,6 +364,23 @@ def testSBM(self): pref_matrix[0][1] = 0.7 self.assertRaises(InternalError, Graph.SBM, 60, pref_matrix, types) + def testTriangularLattice(self): + g = Graph.Triangular_Lattice([2, 2]) + self.assertEqual( + sorted(g.get_edgelist()), [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3)] + ) + + g = Graph.Triangular_Lattice([2, 2], directed=True, mutual=False) + self.assertEqual( + sorted(g.get_edgelist()), [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3)] + ) + + g = Graph.Triangular_Lattice([2, 2], directed=True, mutual=True) + self.assertEqual( + sorted(g.get_edgelist()), + [(0, 1), (0, 2), (0, 3), (1, 0), (1, 3), (2, 0), (2, 3), (3, 0), (3, 1), (3, 2)] + ) + @unittest.skipIf(np is None, "test case depends on NumPy") def testAdjacencyNumPy(self): mat = np.array( From a633ab24d66e0aff15c424ac759fd795d54f5b8f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Apr 2023 22:07:28 +0200 Subject: [PATCH 1263/1892] doc: fixing a few documentation warnings --- doc/source/tutorial.es.rst | 2 +- src/_igraph/graphobject.c | 5 +++-- src/_igraph/igraphmodule.c | 4 ++-- src/igraph/sparse_matrix.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/source/tutorial.es.rst b/doc/source/tutorial.es.rst index d6e89d39c..ea5727155 100644 --- a/doc/source/tutorial.es.rst +++ b/doc/source/tutorial.es.rst @@ -1,6 +1,6 @@ .. include:: include/global.rst -.. _tutorial: +.. _tutorial_es: .. currentmodule:: igraph diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index dcbb0bd87..9b958d806 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14634,7 +14634,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"eigen_adjacency", (PyCFunction) igraphmodule_Graph_eigen_adjacency, METH_VARARGS | METH_KEYWORDS, - "" }, + "eigen_adjacency(algorithm=None, which=None, arpack_options=None)\n--\n\n" }, /* interface to igraph_[st_]edge_connectivity */ {"edge_connectivity", (PyCFunction) igraphmodule_Graph_edge_connectivity, @@ -14820,7 +14820,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_shortest_path_astar */ {"get_shortest_path_astar", (PyCFunction) igraphmodule_Graph_get_shortest_path_astar, METH_VARARGS | METH_KEYWORDS, - "get_shortest_path(v, to, heuristics, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "get_shortest_path_astar(v, to, heuristics, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" "Calculates the shortest path from a source vertex to a target vertex in a\n" "graph using the A-Star algorithm and a heuristic function.\n\n" "@param v: the source vertex of the path\n" @@ -16128,6 +16128,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"_layout_sugiyama", (PyCFunction) igraphmodule_Graph_layout_sugiyama, METH_VARARGS | METH_KEYWORDS, + "_layout_sugiyama()\n--\n\n" "Internal function, undocumented.\n\n" "@see: Graph.layout_sugiyama()\n\n"}, diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 6fa7d7f04..50e2d7bca 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -826,7 +826,7 @@ static PyMethodDef igraphmodule_methods[] = }, {"umap_compute_weights", (PyCFunction)igraphmodule_umap_compute_weights, METH_VARARGS | METH_KEYWORDS, - "layout_umap_compute_weights(graph, dist)\n" + "umap_compute_weights(graph, dist)\n" "--\n\n" "@param graph: directed graph to compute weights for.\n" "@param dist: distances associated with the graph edges.\n" @@ -850,7 +850,7 @@ static PyMethodDef igraphmodule_methods[] = "to zero whenever edges in opposite directions are found in the input\n" "distance graph. You can pipe the output of this function directly into\n" "Graph.layout_umap() as follows:\n" - "C{weights = igraph.layout_umap_compute_weights(graph, dist)}\n" + "C{weights = igraph.umap_compute_weights(graph, dist)}\n" "C{layout = graph.layout_umap(weights=weights)}\n\n" "@see: Graph.layout_umap()\n" }, diff --git a/src/igraph/sparse_matrix.py b/src/igraph/sparse_matrix.py index 82a7b7120..3b7622828 100644 --- a/src/igraph/sparse_matrix.py +++ b/src/igraph/sparse_matrix.py @@ -49,7 +49,7 @@ def _convert_mode_argument(mode): def _maybe_halve_diagonal(m, condition): """Halves all items in the diagonal of the given SciPy sparse matrix in - coo mode _if_ and _only if_ the given condition is True. + coo mode *if* and *only if* the given condition is True. Returns the row, column and data arrays. """ From 6a1b89d9e904e97d020f7dcba246537c46c40137 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Apr 2023 22:35:41 +0200 Subject: [PATCH 1264/1892] doc: fix documentation build on readthedocs --- src/igraph/drawing/colors.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 4c977e04b..6d2dad274 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -86,6 +86,8 @@ def get(self, v): pass if isinstance(v, str): result = color_name_to_rgba(v) + elif hasattr(v, "__iter__"): # lists, tuples etc + return result # no need to cache else: if v < 0: raise IndexError("color index must be non-negative") From 669fe5b45640b70e1cdc875a4a98bc1dad8d85b8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 14 Apr 2023 22:46:10 +0200 Subject: [PATCH 1265/1892] fix: fix typo in previous commit --- src/igraph/drawing/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/igraph/drawing/colors.py b/src/igraph/drawing/colors.py index 6d2dad274..192abe308 100644 --- a/src/igraph/drawing/colors.py +++ b/src/igraph/drawing/colors.py @@ -87,7 +87,7 @@ def get(self, v): if isinstance(v, str): result = color_name_to_rgba(v) elif hasattr(v, "__iter__"): # lists, tuples etc - return result # no need to cache + return v # no need to cache else: if v < 0: raise IndexError("color index must be non-negative") From 5972fde4fc04f3391d217fa9ce99649f0315425d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 21 Apr 2023 15:11:58 +0200 Subject: [PATCH 1266/1892] fix: remove unused _Unset class and _UNSET instance --- src/igraph/drawing/matplotlib/graph.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index ff2c06afa..31e639104 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -36,14 +36,6 @@ ##################################################################### -class _Unset: - def __repr__(self): - return "" - - -_UNSET = _Unset() - - # NOTE: https://github.com/networkx/grave/blob/main/grave/grave.py def _stale_wrapper(func): """Decorator to manage artist state.""" From e8ab5c578d8c0ce1751426c61d98b5f08baaea42 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 21 Apr 2023 17:53:26 +0200 Subject: [PATCH 1267/1892] refactor: renamed Matplotlib Graph artist to GraphArtist --- doc/examples_sphinx-gallery/visual_style.py | 2 +- src/igraph/drawing/matplotlib/graph.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py index 9d33968a1..232942a11 100644 --- a/doc/examples_sphinx-gallery/visual_style.py +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -50,7 +50,7 @@ # %% # In the matplotlib backend, igraph creates a special container -# :class:`igraph.drawing.matplotlib.graph.Graph` which is a matplotlib Artist +# :class:`igraph.drawing.matplotlib.graph.GraphArtist` which is a matplotlib Artist # and the first child of the target Axes. That object can be used to customize # the plot appearance after the initial drawing, e.g.: g = ig.Graph.Barabasi(n=30, m=1) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 31e639104..4269e5d5e 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -131,7 +131,7 @@ def method(self, value): "set_picker", ) ) -class Graph(Artist, AbstractGraphDrawer): +class GraphArtist(Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. Arguments: @@ -691,7 +691,7 @@ def draw(self, graph, *args, **kwds): ax = self.ax # Create artist - art = Graph( + art = GraphArtist( graph, vertex_drawer_factory=self.vertex_drawer_factory, edge_drawer_factory=self.edge_drawer_factory, From ae4bd3fac0963b6bf0f0a5dd70a2ab4e8afb6361 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 22 Apr 2023 22:40:52 +0200 Subject: [PATCH 1268/1892] fix: don't treat compiler warnings as errors while compiling the C core, refs #654 --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index f6918f254..9b9f97da2 100644 --- a/setup.py +++ b/setup.py @@ -254,6 +254,11 @@ def _compile_in( # No need to build tests args.append("-DBUILD_TESTING=OFF") + # Do not treat compilation warnings as errors in case someone is trying + # to "pip install" igraph in an environment for which we don't provide + # wheels and the compiler complains about harmless things + args.append("-DIGRAPH_WARNINGS_AS_ERRORS=OFF") + # Set install directory during config step instead of install step in order # to avoid having the architecture name in the LIBPATH (e.g. lib/x86_64-linux-gnu) args.append("-DCMAKE_INSTALL_PREFIX=" + str(install_folder)) From 8b0bc042f5e16917c982f9af89da32bc3201e34d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:02:48 +0000 Subject: [PATCH 1269/1892] build(deps): bump pypa/cibuildwheel from 2.12.1 to 2.12.3 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.12.1 to 2.12.3. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.12.1...v2.12.3) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf9edebae..4b79fe8a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -214,7 +214,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From eb29a5a59a5e8477e44a60a77853f102ee0b6e64 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 2 May 2023 09:53:59 +1000 Subject: [PATCH 1270/1892] Fix a few doc errors and warnings (#661) --- doc/examples_sphinx-gallery/visual_style.py | 7 ++- src/_igraph/graphobject.c | 8 ++-- src/_igraph/igraphmodule.c | 17 ++++---- src/igraph/drawing/matplotlib/graph.py | 48 ++++++++++++--------- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py index 232942a11..04f899ef8 100644 --- a/doc/examples_sphinx-gallery/visual_style.py +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -65,7 +65,6 @@ # %% # .. note:: -# The ``artist.set`` method can be used to change multiple properties at -# once and is generally more efficient than multiple calls to specific -# ``artist.set_...` methods. - +# The :meth:`igraph.drawing.matplotlib.graph.GraphArtist.set` method can +# be used to change multiple properties at once and is generally more +# efficient than multiple calls to specific ``artist.set_...`` methods. diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9b958d806..821b91588 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -16148,7 +16148,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param weights: precomputed edge weights if you have them, as an alternative\n" " to setting the C{dist} argument. Zero weights will be ignored if this\n" " argument is set, e.g. if you computed the weights via\n" - " igraph.layout_umap_compute_weights().\n" + " igraph.umap_compute_weights().\n" "@param dim: the desired number of dimensions for the layout. dim=2\n" " means a 2D layout, dim=3 means a 3D layout.\n" "@param seed: if C{None}, uses a random starting layout for the\n" @@ -16166,13 +16166,13 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "if weights are precomputed, the graph will be treated as undirected. A special\n" "case is when the graph is directed but the precomputed weights are symmetrized\n" "in a way only one of each pair of opposite edges has nonzero weight, e.g. as\n" - "computed by igraph.layout_umap_compute_weights(). For example:\n" - "C{weights = igraph.layout_umap_compute_weights(graph, dist)}\n" + "computed by igraph.umap_compute_weights(). For example:\n" + "C{weights = igraph.umap_compute_weights(graph, dist)}\n" "C{layout = graph.layout_umap(weights=weights)}\n\n" "@newfield ref: Reference\n" "@ref: L McInnes, J Healy, J Melville: UMAP: Uniform Manifold Approximation\n" " and Projection for Dimension Reduction. arXiv:1802.03426.\n" - "@see: igraph.layout_umap_compute_weights()\n\n"}, + "@see: igraph.umap_compute_weights()\n\n"}, //////////////////////////// // VISITOR-LIKE FUNCTIONS // diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 50e2d7bca..a7edd9315 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -826,16 +826,10 @@ static PyMethodDef igraphmodule_methods[] = }, {"umap_compute_weights", (PyCFunction)igraphmodule_umap_compute_weights, METH_VARARGS | METH_KEYWORDS, - "umap_compute_weights(graph, dist)\n" - "--\n\n" - "@param graph: directed graph to compute weights for.\n" - "@param dist: distances associated with the graph edges.\n" - "@return: Symmetrized weights associated with each edge. If the distance\n" - " graph has both directed edges between a pair of vertices, one of the\n" - " returned weights will be set to zero.\n\n" - "Compute undirected UMAP weights from directed distance graph.\n\n" + "umap_compute_weights(graph, dist)\n--\n\n" + "Compute undirected UMAP weights from directed distance graph.\n" "UMAP is a layout algorithm that usually takes as input a directed\n" - "distance graph, e.g. a k nearest neighbor graph based on Euclidean\n" + "distance graph, for instance a k nearest neighbor graph based on Euclidean\n" "distance between points in a vector space. The graph is directed\n" "because vertex v1 might consider vertex v2 a close neighbor, but v2\n" "itself might have many neighbors that are closer than v1.\n" @@ -852,6 +846,11 @@ static PyMethodDef igraphmodule_methods[] = "Graph.layout_umap() as follows:\n" "C{weights = igraph.umap_compute_weights(graph, dist)}\n" "C{layout = graph.layout_umap(weights=weights)}\n\n" + "@param graph: directed graph to compute weights for.\n" + "@param dist: distances associated with the graph edges.\n" + "@return: Symmetrized weights associated with each edge. If the distance\n" + " graph has both directed edges between a pair of vertices, one of the\n" + " returned weights will be set to zero.\n\n" "@see: Graph.layout_umap()\n" }, {"set_progress_handler", igraphmodule_set_progress_handler, METH_O, diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 4269e5d5e..34eb62f6e 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -81,10 +81,11 @@ def _additional_set_methods(attributes, cls=None): def make_setter(name): def method(self, value): self.set(**{name: value}) + return method for attr in attributes: - desc = attr.replace('_', ' ') + desc = attr.replace("_", " ") method = make_setter(attr) method.__name__ = f"set_{attr}" method.__doc__ = f"Set {desc}." @@ -134,12 +135,11 @@ def method(self, value): class GraphArtist(Artist, AbstractGraphDrawer): """Artist for an igraph.Graph object. - Arguments: - graph: An igraph.Graph object to plot - layout: A layout object or matrix of coordinates to use for plotting. - Each element or row should describes the coordinates for a vertex. - vertex_style: A dictionary specifying style options for vertices. - edge_style: A dictionary specifying style options for edges. + @param graph: An igraph.Graph object to plot + @param layout: A layout object or matrix of coordinates to use for plotting. + Each element or row should describes the coordinates for a vertex. + @param vertex_style: A dictionary specifying style options for vertices. + @param edge_style: A dictionary specifying style options for edges. """ def __init__( @@ -247,21 +247,25 @@ def get_datalim(self): """ import numpy as np - vertex_builder = self.vertex_builder layout = self.kwds["layout"] - mins = np.min(layout, axis=0) - maxs = np.max(layout, axis=0) - - # Pad by vertex size, to ensure they fit - if vertex_builder.size is not None: - mins -= vertex_builder.size * 1.1 - maxs += vertex_builder.size * 1.1 + if len(layout) == 0: + mins = np.array([0, 0]) + maxs = np.array([1, 1]) else: - mins[0] -= vertex_builder.width * 0.55 - mins[1] -= vertex_builder.height * 0.55 - maxs[0] += vertex_builder.width * 0.55 - maxs[1] += vertex_builder.height * 0.55 + mins = np.min(layout, axis=0) + maxs = np.max(layout, axis=0) + + # Pad by vertex size, to ensure they fit + vertex_builder = self.vertex_builder + if vertex_builder.size is not None: + mins -= vertex_builder.size * 1.1 + maxs += vertex_builder.size * 1.1 + else: + mins[0] -= vertex_builder.width * 0.55 + mins[1] -= vertex_builder.height * 0.55 + maxs[0] += vertex_builder.width * 0.55 + maxs[1] += vertex_builder.height * 0.55 return (mins, maxs) @@ -465,7 +469,8 @@ def _draw_groups(self): facecolor=facecolor, edgecolor=color, ) - self._group_artists.append(art) + if art is not None: + self._group_artists.append(art) if kwds.get("legend", False): legend_info["handles"].append( @@ -575,7 +580,8 @@ def _reprocess(self): for child in self.get_children(): # set the figure / axes on child, this ensures each primitive # knows where to draw - child.set_figure(self.figure) + if hasattr(child, "set_figure"): + child.set_figure(self.figure) child.axes = self.axes # forward the clippath/box to the children need this logic From e4bf5e10a9a8cbc4b2118117039ada865cb5f045 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 May 2023 11:39:17 +0200 Subject: [PATCH 1271/1892] fix: Graph.layout_reingold_tilford() now accepts vertex names as roots, closes #666 --- CHANGELOG.md | 3 ++ src/_igraph/convert.c | 101 ++++++++++++++++++++++++-------------- src/_igraph/convert.h | 8 +-- src/_igraph/graphobject.c | 14 +++--- tests/test_layouts.py | 6 +++ 5 files changed, 85 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a66ffaaef..ebd5c8967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,9 @@ - `VertexClustering.giant()` now accepts the null graph. The giant component of a null graph is the null graph according to our conventions. +- `Graph.layout_reingold_tilford()` now accepts vertex names in the `roots=...` + keyword argument. + ### Removed - Removed defunct `Graph.community_leading_eigenvector_naive()` method. Not a diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 466653296..a8a46ab5b 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -3262,6 +3262,68 @@ int igraphmodule_PyObject_to_optional_vid(PyObject *o, igraph_integer_t *vid, ig } } +/** + * \ingroup python_interface_conversion + * \brief Tries to interpret a Python object as a list of vertex IDs. + * + * \param o the Python object + * \param result the vertex IDs will be stored here + * \param graph the graph that will be used to interpret vertex names + * if a string was given in o. It may also be a null pointer + * if we don't need name lookups. + * \return 0 if everything was OK, 1 otherwise + */ +int igraphmodule_PyObject_to_vid_list(PyObject* o, igraph_vector_int_t* result, igraph_t* graph) { + PyObject *iterator; + PyObject *item; + igraph_integer_t vid; + + if (PyBaseString_Check(o)) { + /* exclude strings; they are iterable but cannot yield meaningful vertex IDs */ + PyErr_SetString(PyExc_TypeError, "cannot convert string to a list of vertex IDs"); + return 1; + } + + iterator = PyObject_GetIter(o); + if (iterator == NULL) { + PyErr_SetString(PyExc_TypeError, "conversion to vertex sequence failed"); + return 1; + } + + if (igraph_vector_int_init(result, 0)) { + Py_DECREF(iterator); + igraphmodule_handle_igraph_error(); + return 1; + } + + while ((item = PyIter_Next(iterator))) { + vid = -1; + + if (igraphmodule_PyObject_to_vid(item, &vid, graph)) { + Py_DECREF(item); + break; + } + + Py_DECREF(item); + + if (igraph_vector_int_push_back(result, vid)) { + igraphmodule_handle_igraph_error(); + /* no need to destroy 'result' here; will be done outside the loop due + * to PyErr_Occurred */ + break; + } + } + + Py_DECREF(iterator); + + if (PyErr_Occurred()) { + igraph_vector_int_destroy(result); + return 1; + } + + return 0; +} + /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a vertex selector @@ -3346,9 +3408,6 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, /* Object cannot be converted to a single vertex ID, * assume it is a sequence or iterable */ - PyObject *iterator; - PyObject *item; - if (PyBaseString_Check(o)) { /* Special case: strings and unicode objects are sequences, but they * will not yield valid vertex IDs */ @@ -3358,40 +3417,7 @@ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, /* Clear the exception set by igraphmodule_PyObject_to_vid */ PyErr_Clear(); - iterator = PyObject_GetIter(o); - if (iterator == NULL) { - PyErr_SetString(PyExc_TypeError, "conversion to vertex sequence failed"); - return 1; - } - - if (igraph_vector_int_init(&vector, 0)) { - Py_DECREF(iterator); - igraphmodule_handle_igraph_error(); - return 1; - } - - while ((item = PyIter_Next(iterator))) { - vid = -1; - - if (igraphmodule_PyObject_to_vid(item, &vid, graph)) { - Py_DECREF(item); - break; - } - - Py_DECREF(item); - - if (igraph_vector_int_push_back(&vector, vid)) { - igraphmodule_handle_igraph_error(); - /* no need to destroy 'vector' here; will be done outside the loop due - * to PyErr_Occurred */ - break; - } - } - - Py_DECREF(iterator); - - if (PyErr_Occurred()) { - igraph_vector_int_destroy(&vector); + if (igraphmodule_PyObject_to_vid_list(o, &vector, graph)) { return 1; } @@ -3522,7 +3548,6 @@ int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *g return 0; } - /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as an edge selector diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index 15bf4ead8..d318ce585 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -121,9 +121,11 @@ int igraphmodule_append_PyIter_of_graphs_to_vector_ptr_t_with_type(PyObject *it, igraph_vector_ptr_t *v, PyTypeObject **g_type); int igraphmodule_PyObject_to_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph); int igraphmodule_PyObject_to_optional_vid(PyObject *o, igraph_integer_t *vid, igraph_t *graph); -int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, - igraph_t *graph, igraph_bool_t *return_single, - igraph_integer_t *single_vid); +int igraphmodule_PyObject_to_vid_list(PyObject *o, igraph_vector_int_t *vids, igraph_t *graph); +int igraphmodule_PyObject_to_vs_t( + PyObject *o, igraph_vs_t *vs, igraph_t *graph, + igraph_bool_t *return_single, igraph_integer_t *single_vid +); int igraphmodule_PyObject_to_eid(PyObject *o, igraph_integer_t *eid, igraph_t *graph); int igraphmodule_PyObject_to_es_t(PyObject *o, igraph_es_t *es, igraph_t *graph, igraph_bool_t *return_single); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 821b91588..6e5763f5d 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -8220,8 +8220,11 @@ PyObject *igraphmodule_Graph_layout_reingold_tilford(igraphmodule_GraphObject if (roots_o != Py_None) { roots_p = &roots; - if (igraphmodule_PyObject_to_vector_int_t(roots_o, roots_p)) return 0; + if (igraphmodule_PyObject_to_vid_list(roots_o, roots_p, &self->g)) { + return 0; + } } + if (rootlevels_o != Py_None) { rootlevels_p = &rootlevels; if (igraphmodule_PyObject_to_vector_int_t(rootlevels_o, rootlevels_p)) { @@ -9607,17 +9610,16 @@ PyObject *igraphmodule_Graph_isoclass(igraphmodule_GraphObject * self, if (vids) { igraph_vector_int_t vidsvec; - if (igraphmodule_PyObject_to_vector_int_t(vids, &vidsvec)) { - PyErr_SetString(PyExc_ValueError, - "Error while converting PyList to igraph_vector_int_t"); + if (igraphmodule_PyObject_to_vid_list(vids, &vidsvec, &self->g)) { return NULL; } if (igraph_isoclass_subgraph(&self->g, &vidsvec, &isoclass)) { + igraph_vector_int_destroy(&vidsvec); igraphmodule_handle_igraph_error(); return NULL; } - } - else { + igraph_vector_int_destroy(&vidsvec); + } else { if (igraph_isoclass(&self->g, &isoclass)) { igraphmodule_handle_igraph_error(); return NULL; diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 3f8910bce..cabc9c5ae 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -350,6 +350,12 @@ def testReingoldTilford(self): lo = g.layout("rt", root=[0, 100], rootlevel=[2, 10]) self.assertEqual(lo[100][1] - lo[0][1], 8) + # test named vertices + g.vs["name"] = [f"v{i}" for i in range(g.vcount())] + lo = g.layout("rt", root=["v0", "v100"]) + self.assertEqual(lo[100][1] - lo[0][1], 0) + + def testBipartite(self): g = Graph.Full_Bipartite(3, 2) From 478e896ecb7470655803b6222fa1574ae9ef59f0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 10 May 2023 13:46:09 +0200 Subject: [PATCH 1272/1892] doc: require PyDoctor >= 23.4.0 because of the search-related fixes --- doc/source/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/requirements.txt b/doc/source/requirements.txt index af675f44c..959667565 100644 --- a/doc/source/requirements.txt +++ b/doc/source/requirements.txt @@ -6,7 +6,7 @@ sphinxbootstrap4theme sphinx-gallery sphinx-rtd-theme sphinxcontrib-jquery -pydoctor +pydoctor>=23.4.0 numpy scipy From c22e1d64ab7be1fbf7e06bff730b4cfb7acc43a7 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 11 May 2023 16:11:33 +1000 Subject: [PATCH 1273/1892] Use graph layout attribute if found (#663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plotting: use graph layout attribute if found --------- Co-authored-by: Tamás Nepusz --- src/igraph/drawing/baseclasses.py | 19 +++++++++++++----- src/igraph/drawing/matplotlib/graph.py | 4 ++-- .../test_graph/graph_layout_attribute.png | Bin 0 -> 8845 bytes tests/drawing/matplotlib/test_graph.py | 10 ++++++++- 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_layout_attribute.png diff --git a/src/igraph/drawing/baseclasses.py b/src/igraph/drawing/baseclasses.py index 6a983225a..60d819f96 100644 --- a/src/igraph/drawing/baseclasses.py +++ b/src/igraph/drawing/baseclasses.py @@ -121,7 +121,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): raise NotImplementedError def get_label_position(self, edge, src_vertex, dest_vertex): - """returns the position where the label of an edge should be drawn. the + """Returns the position where the label of an edge should be drawn. the default implementation returns the midpoint of the edge and an alignment that tries to avoid overlapping the label with the edge. @@ -266,9 +266,13 @@ def ensure_layout(layout, graph=None): C{layout} method of the given I{graph} if I{graph} is not C{None}. - - If I{layout} is C{None}, the C{layout} method of - I{graph} will be invoked with no parameters, which - will call the default layout algorithm. + - If I{layout} is C{None} and I{graph} has a "layout" + attribute, call this same function with the value of that + attribute. + + - If I{layout} is C{None} and I{graph} does not have a "layout" + attribute, the C{layout} method of I{graph} will be invoked + with no parameters, which will call the default layout algorithm. - Otherwise, I{layout} will be passed on to the constructor of L{Layout}. This handles lists of lists, lists of tuples @@ -284,7 +288,12 @@ def ensure_layout(layout, graph=None): if isinstance(layout, Layout): layout = Layout(layout.coords) - elif isinstance(layout, str) or layout is None: + elif isinstance(layout, str): + layout = graph.layout(layout) + elif (layout is None) and hasattr(graph, "attributes") and \ + ('layout' in graph.attributes()): + layout = AbstractGraphDrawer.ensure_layout(graph['layout'], graph=graph) + elif layout is None: layout = graph.layout(layout) else: layout = Layout(layout) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 34eb62f6e..46839f154 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -253,8 +253,8 @@ def get_datalim(self): mins = np.array([0, 0]) maxs = np.array([1, 1]) else: - mins = np.min(layout, axis=0) - maxs = np.max(layout, axis=0) + mins = np.min(layout, axis=0).astype(float) + maxs = np.max(layout, axis=0).astype(float) # Pad by vertex size, to ensure they fit vertex_builder = self.vertex_builder diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_layout_attribute.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_layout_attribute.png new file mode 100644 index 0000000000000000000000000000000000000000..c074d6298e391a5875a827bf43f9d7a9e1b8eb36 GIT binary patch literal 8845 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 Date: Tue, 16 May 2023 00:13:22 +0200 Subject: [PATCH 1274/1892] fix: disallow using integers as vertex names in add_vertex(), refs #664 --- src/igraph/basic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/igraph/basic.py b/src/igraph/basic.py index 0f35f89bf..01b6a0a4e 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -62,6 +62,8 @@ def _add_vertex(graph, name=None, **kwds): vertex = graph.vs[vid] for key, value in kwds.items(): vertex[key] = value + if isinstance(name, int): + raise TypeError("cannot use integers as vertex names; use strings instead") if name is not None: vertex["name"] = name return vertex From 9d537949a9f3b4aded2c18c7609a05bbeeb788d0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 16 May 2023 00:49:21 +0200 Subject: [PATCH 1275/1892] fix: fix failing test --- src/igraph/basic.py | 8 ++++++-- tests/test_basic.py | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/igraph/basic.py b/src/igraph/basic.py index 01b6a0a4e..e672ef7d9 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -57,15 +57,19 @@ def _add_vertex(graph, name=None, **kwds): C{add_vertices(1)} if you don't need the L{Vertex} object and want to avoid the overhead of creating t. """ + if isinstance(name, int): + raise TypeError("cannot use integers as vertex names; use strings instead") + vid = graph.vcount() graph.add_vertices(1) vertex = graph.vs[vid] + for key, value in kwds.items(): vertex[key] = value - if isinstance(name, int): - raise TypeError("cannot use integers as vertex names; use strings instead") + if name is not None: vertex["name"] = name + return vertex diff --git a/tests/test_basic.py b/tests/test_basic.py index a342d84fa..48ce89d1a 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -120,17 +120,20 @@ def testAddVertex(self): self.assertTrue("name" in g.vertex_attributes()) self.assertEqual(g.vs["name"], [None, "foo"]) - vertex = g.add_vertex(3) + self.assertRaises(TypeError, g.add_vertex, 3) + + vertex = g.add_vertex("3") + print(g.vcount(), g.ecount()) self.assertTrue(g.vcount() == 3 and g.ecount() == 0) self.assertEqual(2, vertex.index) self.assertTrue("name" in g.vertex_attributes()) - self.assertEqual(g.vs["name"], [None, "foo", 3]) + self.assertEqual(g.vs["name"], [None, "foo", "3"]) vertex = g.add_vertex(name="bar") self.assertTrue(g.vcount() == 4 and g.ecount() == 0) self.assertEqual(3, vertex.index) self.assertTrue("name" in g.vertex_attributes()) - self.assertEqual(g.vs["name"], [None, "foo", 3, "bar"]) + self.assertEqual(g.vs["name"], [None, "foo", "3", "bar"]) vertex = g.add_vertex(name="frob", spam="cheese", ham=42) self.assertTrue(g.vcount() == 5 and g.ecount() == 0) From 36e62e0d105836a6cfa3cc405c772574765ea2cf Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 18 May 2023 16:16:17 +1000 Subject: [PATCH 1276/1892] Subclass matplotlib collection for edges --- src/igraph/drawing/matplotlib/edge.py | 61 ++++++++++++++++++++++--- src/igraph/drawing/matplotlib/graph.py | 43 ++++++++++++----- src/igraph/drawing/matplotlib/vertex.py | 16 +++++-- src/igraph/drawing/shapes.py | 23 ++++------ 4 files changed, 107 insertions(+), 36 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 929555ecf..5a01ce84e 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -1,6 +1,7 @@ """Drawers for various edge styles in Matplotlib graph plots.""" from math import atan2, cos, pi, sin +from copy import deepcopy from igraph.drawing.baseclasses import AbstractEdgeDrawer from igraph.drawing.metamagic import AttributeCollectorBase @@ -78,9 +79,11 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): # Determine where the edge intersects the circumference of the # vertex shape: Tip of the arrow - x2, y2 = intersect_bezier_curve_and_circle( - x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 - ) + ## FIXME + #x2, y2 = intersect_bezier_curve_and_circle( + # x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 + #) + x2, y2 = x_dest, y_dest # Calculate the arrow head coordinates angle = atan2(y_dest - y2, x_dest - x2) # navid @@ -136,12 +139,14 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): else: # Determine where the edge intersects the circumference of the # vertex shape. - x2, y2 = dest_vertex.shape.intersection_point( - x2, y2, x1, y1, dest_vertex.size - ) + # FIXME + #x2, y2 = dest_vertex.shape.intersection_point( + # x2, y2, x1, y1, dest_vertex.size + #) + x2, y2 = x_dest, y_dest # Draw the arrowhead - angle = atan2(y_dest - y2, x_dest - x2) + angle = atan2(y_dest - y_src, x_dest - x_src) arrow_size = 15.0 * edge.arrow_size arrow_width = 10.0 / edge.arrow_width aux_points = [ @@ -268,3 +273,45 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): clip_on=True, ) return [art] + + +class EdgeCollection(mpl.collections.LineCollection): + def __init__(self, *args, **kwargs): + self._vertex_bboxes = kwargs.pop("vertex_bboxes") + ret = super().__init__(*args, **kwargs) + self._paths_original = deepcopy(self._paths) + return ret + + + def _update_path_from_vertices(self): + # Get actual coordinates of the vertex bbox edges + for p, p_orig, bboxes in zip(self._paths, self._paths_original, self._vertex_bboxes): + coords = p_orig.vertices + + # Start vertex + if coords[0, 0] == coords[1, 0]: + bbox_offsetx = 0 + bbox_offsety = bboxes[0].extents[1 + 2 * int(coords[1, 1] > coords[0, 1])] + else: + ratio = (coords[1, 1] - coords[0, 1]) / (coords[1, 0] - coords[0, 0]) + bbox_offsetx = bboxes[0].extents[2 * int(coords[1, 0] > coords[0, 0])] + bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[1, 1] > coords[0, 1])] * abs(ratio) + voff = np.array([bbox_offsetx, bbox_offsety]) + start = ax.transData.inverted().transform(ax.transData.transform(coords[0]) + voff) + p.vertices[0] = start + + # End vertex + if coords[-2, 0] == coords[-1, 0]: + bbox_offsetx = 0 + bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[-2, 1] > coords[-1, 1])] + else: + ratio = (coords[-1, 1] - coords[-2, 1]) / (coords[-1, 0] - coords[-2, 0]) + bbox_offsetx = bboxes[0].extents[2 * int(coords[-2, 0] > coords[-1, 0])] + bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[-2, 1] > coords[-1, 1])] * abs(ratio) + voff = np.array([bbox_offsetx, bbox_offsety]) + end = ax.transData.inverted().transform(ax.transData.transform(coords[-1]) + voff) + p.vertices[-1] = end + + def draw(self, renderer): + self._update_path_from_vertices() + return super().draw(renderer) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 46839f154..93ab256de 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -30,8 +30,12 @@ mpl, plt = find_matplotlib() try: Artist = mpl.artist.Artist + PatchCollection = mpl.collections.PatchCollection + IdentityTransform = mpl.transforms.IdentityTransform except AttributeError: Artist = FakeModule + PatchCollection = FakeModule + IdentityTransform = FakeModule ##################################################################### @@ -256,16 +260,21 @@ def get_datalim(self): mins = np.min(layout, axis=0).astype(float) maxs = np.max(layout, axis=0).astype(float) - # Pad by vertex size, to ensure they fit - vertex_builder = self.vertex_builder - if vertex_builder.size is not None: - mins -= vertex_builder.size * 1.1 - maxs += vertex_builder.size * 1.1 - else: - mins[0] -= vertex_builder.width * 0.55 - mins[1] -= vertex_builder.height * 0.55 - maxs[0] += vertex_builder.width * 0.55 - maxs[1] += vertex_builder.height * 0.55 + # 5% padding, on each side + pad = (maxs - mins) * 0.05 + mins -= pad + maxs += pad + + ## Pad by vertex size, to ensure they fit + #vertex_builder = self.vertex_builder + #if vertex_builder.size is not None: + # mins -= vertex_builder.size * 1.1 + # maxs += vertex_builder.size * 1.1 + #else: + # mins[0] -= vertex_builder.width * 0.55 + # mins[1] -= vertex_builder.height * 0.55 + # maxs[0] += vertex_builder.width * 0.55 + # maxs[1] += vertex_builder.height * 0.55 return (mins, maxs) @@ -504,9 +513,19 @@ def _draw_vertices(self): vertex_coord_iter = ( (vs[i], vertex_builder[i], layout[i]) for i in vertex_order ) + offsets = [] + patches = [] for vertex, visual_vertex, coords in vertex_coord_iter: art = vertex_drawer.draw(visual_vertex, vertex, coords) - self._vertices.append(art) + patches.append(art) + offsets.append(list(coords)) + art = PatchCollection( + patches, + offsets=offsets, + offset_transform=self.axes.transData, + ) + art.set_transform(IdentityTransform()) + self._vertices.append(art) def _draw_edges(self): """Draw the edges""" @@ -732,7 +751,7 @@ def draw(self, graph, *args, **kwds): ax.set_yticks([]) # Set equal aspect to get actual circles - ax.set_aspect(1) + #ax.set_aspect(1) # Autoscale for x/y axis limits ax.autoscale_view() diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py index 00270a010..2c3143d28 100644 --- a/src/igraph/drawing/matplotlib/vertex.py +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -7,6 +7,15 @@ from igraph.drawing.baseclasses import AbstractVertexDrawer from igraph.drawing.metamagic import AttributeCollectorBase from igraph.drawing.shapes import ShapeDrawerDirectory +from igraph.drawing.matplotlib.utils import find_matplotlib +from igraph.drawing.utils import FakeModule + +mpl, _ = find_matplotlib() +try: + IdentityTransform = mpl.transforms.IdentityTransform +except AttributeError: + IdentityTransform = FakeModule + __all__ = ("MatplotlibVertexDrawer",) @@ -36,7 +45,7 @@ class VisualVertexBuilder(AttributeCollectorBase): # FIXME? mpl.rcParams["font.size"]) position = dict(func=self.layout.__getitem__) shape = ("circle", ShapeDrawerDirectory.resolve_default) - size = 0.2 + size = 30 width = None height = None zorder = 2 @@ -60,13 +69,14 @@ def draw(self, visual_vertex, vertex, coords): art = visual_vertex.shape.draw_path( ax, - coords[0], - coords[1], + 0, #coords[0], # FIXME + 0, #coords[1], width, height, facecolor=visual_vertex.color, edgecolor=visual_vertex.frame_color, linewidth=visual_vertex.frame_width, zorder=visual_vertex.zorder, + transform=IdentityTransform(), ) return art diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 69d39bb4d..6598766d4 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -96,10 +96,9 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): height = height or width if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Rectangle( - (center_x - width / 2, center_y - height / 2), + - width / 2, - height / 2, width, height, - transform=ctx.transData, clip_on=True, **kwargs, ) @@ -169,9 +168,8 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): @see: ShapeDrawer.draw_path""" if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Circle( - (center_x, center_y), + (0, 0), width / 2, - transform=ctx.transData, clip_on=True, **kwargs, ) @@ -211,7 +209,6 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): return mpl.patches.Polygon( vertices, closed=True, - transform=ctx.transData, clip_on=True, **kwargs, ) @@ -247,14 +244,13 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): height = height or width if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): vertices = [ - [center_x - 0.5 * width, center_y + 0.333 * height], - [center_x + 0.5 * width, center_y + 0.333 * height], - [center_x, center_y - 0.667 * height], + [- 0.5 * width, 0.333 * height], + [0.5 * width, 0.333 * height], + [0, -0.667 * height], ] return mpl.patches.Polygon( vertices, closed=True, - transform=ctx.transData, clip_on=True, **kwargs, ) @@ -291,15 +287,14 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): height = height or width if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): vertices = [ - [center_x - 0.5 * width, center_y], - [center_x, center_y - 0.5 * height], - [center_x + 0.5 * width, center_y], - [center_x, center_y + 0.5 * height], + [-0.5 * width, 0], + [0, -0.5 * height], + [0.5 * width, 0], + [0, 0.5 * height], ] return mpl.patches.Polygon( vertices, closed=True, - transform=ctx.transData, clip_on=True, **kwargs, ) From 57714e267188052458340320ee9b271f4e9dc3b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 14:00:34 +0000 Subject: [PATCH 1277/1892] build(deps): bump mymindstorm/setup-emsdk from 11 to 12 Bumps [mymindstorm/setup-emsdk](https://github.com/mymindstorm/setup-emsdk) from 11 to 12. - [Release notes](https://github.com/mymindstorm/setup-emsdk/releases) - [Commits](https://github.com/mymindstorm/setup-emsdk/compare/v11...v12) --- updated-dependencies: - dependency-name: mymindstorm/setup-emsdk dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 05857b88c..36babc937 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -181,7 +181,7 @@ jobs: with: python-version: '3.10.2' - - uses: mymindstorm/setup-emsdk@v11 + - uses: mymindstorm/setup-emsdk@v12 with: version: '3.1.14' From aebf64210e56c2c84f0fa3efbed719c95d66a351 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 28 May 2023 11:09:50 +1000 Subject: [PATCH 1278/1892] PatchCollection for vertices and edges, according to working prototype --- src/igraph/drawing/matplotlib/edge.py | 136 +++++++++++++++---------- src/igraph/drawing/matplotlib/graph.py | 33 +++++- 2 files changed, 113 insertions(+), 56 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 5a01ce84e..595c77086 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -1,6 +1,6 @@ """Drawers for various edge styles in Matplotlib graph plots.""" -from math import atan2, cos, pi, sin +from math import atan2, cos, pi, sin, sqrt from copy import deepcopy from igraph.drawing.baseclasses import AbstractEdgeDrawer @@ -10,11 +10,16 @@ euclidean_distance, get_bezier_control_points_for_curved_edge, intersect_bezier_curve_and_circle, + FakeModule, ) __all__ = ("MatplotlibEdgeDrawer",) mpl, plt = find_matplotlib() +try: + PatchCollection = mpl.collections.PatchCollection +except AttributeError: + PatchCollection = FakeModule class MatplotlibEdgeDrawer(AbstractEdgeDrawer): @@ -168,8 +173,16 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): path["vertices"].append([x_arrow_mid, y_arrow_mid]) path["codes"].append("LINETO") + # Add arrowhead in the path, the exact positions are recomputed within + # EdgeCollection before each draw so they don't matter here. The + # path for an arrowhead is: headbase (current), headleft, tip, + # headright, headbase, so we need to add 4 (degenerate) vertices. + # Assuming the arrowhead uses straight lines, they are all LINETO + path["vertices"].extend([path["vertices"][-1] for x in range(4)]) + path["codes"].extend(["LINETO" for x in range(4)]) + # Draw the edge - arrowshaft = mpl.patches.PathPatch( + arrowpatch = mpl.patches.PathPatch( mpl.path.Path( path["vertices"], codes=[getattr(mpl.path.Path, x) for x in path["codes"]], @@ -182,21 +195,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): clip_on=True, ) - # Draw the arrow head - arrowhead = mpl.patches.Polygon( - [ - [x2, y2], - aux_points[0], - aux_points[1], - ], - closed=True, - facecolor=edge.color, - edgecolor="none", - zorder=edge.zorder, - transform=ax.transData, - clip_on=True, - ) - return [arrowshaft, arrowhead] + return arrowpatch def draw_loop_edge(self, edge, vertex): """Draws a loop edge. @@ -225,7 +224,7 @@ def draw_loop_edge(self, edge, vertex): transform=ax.transData, clip_on=True, ) - return [art] + return art def draw_undirected_edge(self, edge, src_vertex, dest_vertex): """Draws an undirected edge. @@ -272,46 +271,81 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): transform=ax.transData, clip_on=True, ) - return [art] + return art -class EdgeCollection(mpl.collections.LineCollection): +class EdgeCollection(PatchCollection): def __init__(self, *args, **kwargs): - self._vertex_bboxes = kwargs.pop("vertex_bboxes") - ret = super().__init__(*args, **kwargs) + kwargs["match_original"] = True + self._vertex_sizes = kwargs.pop("vertex_sizes", None) + self._directed = kwargs.pop("directed", False) + self._arrow_size = kwargs.pop("arrow_sizes", 0) + self._arrow_width = kwargs.pop("arrow_widths", 0) + super().__init__(*args, **kwargs) self._paths_original = deepcopy(self._paths) - return ret - def _update_path_from_vertices(self): - # Get actual coordinates of the vertex bbox edges - for p, p_orig, bboxes in zip(self._paths, self._paths_original, self._vertex_bboxes): - coords = p_orig.vertices - - # Start vertex - if coords[0, 0] == coords[1, 0]: - bbox_offsetx = 0 - bbox_offsety = bboxes[0].extents[1 + 2 * int(coords[1, 1] > coords[0, 1])] + if self._vertex_sizes is None: + return + + paths_original = self._paths_original + vertex_sizes = self._vertex_sizes + trans = self.axes.transData.transform + trans_inv = ax.transData.inverted().transform + + # Get actual coordinates of the vertex border (rough) + for i, (path_orig, sizes) in enumerate(zip(paths_original, vertex_sizes)): + self._paths[i] = path = deepcopy(path_orig) + coords = path_orig.vertices + coordst = trans(coords) + self._update_path_edge_start(path, coords, coordst, sizes[0], trans, trans_inv) + if self._directed: + self._update_path_edge_end_directed( + path, coords, coordst, sizes[1], trans, trans_inv, + self._arrow_sizes[i], self._arrow_widths[i], + ) else: - ratio = (coords[1, 1] - coords[0, 1]) / (coords[1, 0] - coords[0, 0]) - bbox_offsetx = bboxes[0].extents[2 * int(coords[1, 0] > coords[0, 0])] - bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[1, 1] > coords[0, 1])] * abs(ratio) - voff = np.array([bbox_offsetx, bbox_offsety]) - start = ax.transData.inverted().transform(ax.transData.transform(coords[0]) + voff) - p.vertices[0] = start - - # End vertex - if coords[-2, 0] == coords[-1, 0]: - bbox_offsetx = 0 - bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[-2, 1] > coords[-1, 1])] - else: - ratio = (coords[-1, 1] - coords[-2, 1]) / (coords[-1, 0] - coords[-2, 0]) - bbox_offsetx = bboxes[0].extents[2 * int(coords[-2, 0] > coords[-1, 0])] - bbox_offsety = bboxes[1].extents[1 + 2 * int(coords[-2, 1] > coords[-1, 1])] * abs(ratio) - voff = np.array([bbox_offsetx, bbox_offsety]) - end = ax.transData.inverted().transform(ax.transData.transform(coords[-1]) + voff) - p.vertices[-1] = end - + self._update_path_edge_end_undirected(path, coords, coordst, sizes[1], trans, trans_inv) + + def _update_path_edge_start(self, path, coords, coordst, size, trans, trans_inv): + theta = atan2(*((coordst[1] - coordst[0])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= size + start = trans_inv(trans(coords[0]) + voff) + path.vertices[0] = start + + def _update_path_edge_end_undirected( + elf, path, coords, coordst, size, trans, trans_inv, + ): + theta = atan2(*((coordst[-2] - coordst[-1])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= size + end = trans_inv(trans(coords[-1]) + voff) + path.vertices[-1] = end + + def _update_path_edge_end_directed( + self, path, coords, coordst, size, trans, trans_inv, + arrow_size, arrow_width): + + def dist(a, b): + return sqrt(((a - b)**2).sum()) + + # The path for arrows is start-headmid-headleft-tip-headright-headmid + # So, tip is the 3rd-to-last and headmid the last + theta = atan2(*((coordst[-6] - coordst[-3])[::-1])) + voff_unity = 0 * coordst[0] + voff_unity[:] = [cos(theta), sin(theta)] + voff = voff_unity * size + voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] + + tip = trans_inv(trans(coords[-3]) + voff) + headbase = trans_inv(trans(tip) + arrow_size * voff_unity) + headleft = trans_inv(trans(headbase) + 0.5 * arrow_width * voff_unity_90) + headright = trans_inv(trans(headbase) - 0.5 * arrow_width * voff_unity_90) + path.vertices[-5:] = [headbase, headleft, tip, headright, headbase] + def draw(self, renderer): self._update_path_from_vertices() return super().draw(renderer) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 93ab256de..15e929c0c 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -20,7 +20,7 @@ from igraph.drawing.baseclasses import AbstractGraphDrawer from igraph.drawing.utils import Point, FakeModule -from .edge import MatplotlibEdgeDrawer +from .edge import MatplotlibEdgeDrawer, EdgeCollection from .polygon import MatplotlibPolygonDrawer from .utils import find_matplotlib from .vertex import MatplotlibVertexDrawer @@ -550,11 +550,34 @@ def _draw_edges(self): else: # Lines drawer_method = edge_drawer.draw_undirected_edge + + vertex_sizes = [] + edgepatches = [] + arrow_sizes = [] + arrow_widths = [] for edge, visual_edge in edge_coord_iter: - src, dest = edge.tuple - src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] - arts = drawer_method(visual_edge, src_vertex, dest_vertex) - self._edges.extend(arts) + edge_vertices = [vertex_builder[v] for v in edge.tuple] + edge_vertex_sizes = [] + for visual_vertex in edge_vertices: + if visual_vertex.size is not None: + edge_vertex_sizes.append(visual_vertex.size) + else: + edge_vertex_sizes.append( + max(visual_vertex.width, visual_vertex.height)) + art = drawer_method(visual_edge, *edge_vertices) + edgepatches.append(art) + vertex_sizes.append(edge_vertex_sizes) + arrow_sizes.append(visual_edge.arrow_size) + arrow_widths.append(visual_edge.arrow_width) + + edgecoll = EdgeCollection( + edgepatches, + vertex_sizes=vertex_sizes, + directed=directed, + arrow_sizes=arrow_sizes, + arrow_widths=arrow_widths, + ) + self._edges.append(edgecoll) def _reprocess(self): """Prepare artist and children for the actual drawing. From b7da7d3e99566cc75fa0034b75b9f1aeedd01a6e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 28 May 2023 12:55:08 +1000 Subject: [PATCH 1279/1892] Undirected edges kind of work --- src/igraph/drawing/matplotlib/edge.py | 28 ++++++++++++------------- src/igraph/drawing/matplotlib/graph.py | 7 ++++--- src/igraph/drawing/matplotlib/vertex.py | 4 ++-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 595c77086..b979116d9 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -46,8 +46,8 @@ class VisualEdgeBuilder(AttributeCollectorBase): drawing""" _kwds_prefix = "edge_" - arrow_size = 0.007 - arrow_width = 1.4 + arrow_size = 10 + arrow_width = 10 color = ("#444", self.palette.get) curved = (0.0, self._curvature_to_float) label = None @@ -268,7 +268,7 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): facecolor="none", linewidth=edge.width, zorder=edge.zorder, - transform=ax.transData, + #transform=ax.transData, clip_on=True, ) return art @@ -279,8 +279,8 @@ def __init__(self, *args, **kwargs): kwargs["match_original"] = True self._vertex_sizes = kwargs.pop("vertex_sizes", None) self._directed = kwargs.pop("directed", False) - self._arrow_size = kwargs.pop("arrow_sizes", 0) - self._arrow_width = kwargs.pop("arrow_widths", 0) + self._arrow_sizes = kwargs.pop("arrow_sizes", 0) + self._arrow_widths = kwargs.pop("arrow_widths", 0) super().__init__(*args, **kwargs) self._paths_original = deepcopy(self._paths) @@ -291,7 +291,7 @@ def _update_path_from_vertices(self): paths_original = self._paths_original vertex_sizes = self._vertex_sizes trans = self.axes.transData.transform - trans_inv = ax.transData.inverted().transform + trans_inv = self.axes.transData.inverted().transform # Get actual coordinates of the vertex border (rough) for i, (path_orig, sizes) in enumerate(zip(paths_original, vertex_sizes)): @@ -301,11 +301,13 @@ def _update_path_from_vertices(self): self._update_path_edge_start(path, coords, coordst, sizes[0], trans, trans_inv) if self._directed: self._update_path_edge_end_directed( - path, coords, coordst, sizes[1], trans, trans_inv, - self._arrow_sizes[i], self._arrow_widths[i], - ) + path, coords, coordst, sizes[1], trans, trans_inv, + self._arrow_sizes[i], self._arrow_widths[i], + ) else: - self._update_path_edge_end_undirected(path, coords, coordst, sizes[1], trans, trans_inv) + self._update_path_edge_end_undirected( + path, coords, coordst, sizes[1], trans, trans_inv, + ) def _update_path_edge_start(self, path, coords, coordst, size, trans, trans_inv): theta = atan2(*((coordst[1] - coordst[0])[::-1])) @@ -317,7 +319,7 @@ def _update_path_edge_start(self, path, coords, coordst, size, trans, trans_inv) def _update_path_edge_end_undirected( elf, path, coords, coordst, size, trans, trans_inv, - ): + ): theta = atan2(*((coordst[-2] - coordst[-1])[::-1])) voff = 0 * coordst[0] voff[:] = [cos(theta), sin(theta)] @@ -328,10 +330,6 @@ def _update_path_edge_end_undirected( def _update_path_edge_end_directed( self, path, coords, coordst, size, trans, trans_inv, arrow_size, arrow_width): - - def dist(a, b): - return sqrt(((a - b)**2).sum()) - # The path for arrows is start-headmid-headleft-tip-headright-headmid # So, tip is the 3rd-to-last and headmid the last theta = atan2(*((coordst[-6] - coordst[-3])[::-1])) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 15e929c0c..374dff04b 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -570,14 +570,15 @@ def _draw_edges(self): arrow_sizes.append(visual_edge.arrow_size) arrow_widths.append(visual_edge.arrow_width) - edgecoll = EdgeCollection( + art = EdgeCollection( edgepatches, vertex_sizes=vertex_sizes, directed=directed, arrow_sizes=arrow_sizes, arrow_widths=arrow_widths, + transform=self.axes.transData, ) - self._edges.append(edgecoll) + self._edges.append(art) def _reprocess(self): """Prepare artist and children for the actual drawing. @@ -612,8 +613,8 @@ def _reprocess(self): self.edge_order = self._determine_edge_order(graph, kwds) self._draw_groups() - self._draw_edges() self._draw_vertices() + self._draw_edges() self._draw_vertex_labels() self._draw_edge_labels() diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py index 2c3143d28..e93e31949 100644 --- a/src/igraph/drawing/matplotlib/vertex.py +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -69,8 +69,8 @@ def draw(self, visual_vertex, vertex, coords): art = visual_vertex.shape.draw_path( ax, - 0, #coords[0], # FIXME - 0, #coords[1], + 0, + 0, width, height, facecolor=visual_vertex.color, From 3b8f660cedcc419c3bcbbcbd0d18834ed0bd1ece Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 28 May 2023 14:54:24 +1000 Subject: [PATCH 1280/1892] Edges work, marking groups still buggy --- src/igraph/drawing/matplotlib/edge.py | 45 ++++---------------------- src/igraph/drawing/matplotlib/graph.py | 3 +- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index b979116d9..5e1132fb4 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -46,8 +46,8 @@ class VisualEdgeBuilder(AttributeCollectorBase): drawing""" _kwds_prefix = "edge_" - arrow_size = 10 - arrow_width = 10 + arrow_size = 15 + arrow_width = 15 color = ("#444", self.palette.get) curved = (0.0, self._curvature_to_float) label = None @@ -142,35 +142,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): path["codes"].extend(["CURVE4"] * 3) else: - # Determine where the edge intersects the circumference of the - # vertex shape. - # FIXME - #x2, y2 = dest_vertex.shape.intersection_point( - # x2, y2, x1, y1, dest_vertex.size - #) - x2, y2 = x_dest, y_dest - - # Draw the arrowhead - angle = atan2(y_dest - y_src, x_dest - x_src) - arrow_size = 15.0 * edge.arrow_size - arrow_width = 10.0 / edge.arrow_width - aux_points = [ - ( - x2 - arrow_size * cos(angle - pi / arrow_width), - y2 - arrow_size * sin(angle - pi / arrow_width), - ), - ( - x2 - arrow_size * cos(angle + pi / arrow_width), - y2 - arrow_size * sin(angle + pi / arrow_width), - ), - ] - - # Midpoint of the base of the arrow triangle - x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( - aux_points[0][1] + aux_points[1][1] - ) / 2.0 - # Draw the line - path["vertices"].append([x_arrow_mid, y_arrow_mid]) + path["vertices"].append(dest_vertex.position) path["codes"].append("LINETO") # Add arrowhead in the path, the exact positions are recomputed within @@ -188,10 +160,9 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): codes=[getattr(mpl.path.Path, x) for x in path["codes"]], ), edgecolor=edge.color, - facecolor="none", + facecolor=edge.color, linewidth=edge.width, zorder=edge.zorder, - transform=ax.transData, clip_on=True, ) @@ -221,7 +192,6 @@ def draw_loop_edge(self, edge, vertex): facecolor="none", edgecolor=edge.color, zorder=edge.zorder, - transform=ax.transData, clip_on=True, ) return art @@ -268,7 +238,6 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): facecolor="none", linewidth=edge.width, zorder=edge.zorder, - #transform=ax.transData, clip_on=True, ) return art @@ -313,7 +282,7 @@ def _update_path_edge_start(self, path, coords, coordst, size, trans, trans_inv) theta = atan2(*((coordst[1] - coordst[0])[::-1])) voff = 0 * coordst[0] voff[:] = [cos(theta), sin(theta)] - voff *= size + voff *= size / 2 start = trans_inv(trans(coords[0]) + voff) path.vertices[0] = start @@ -323,7 +292,7 @@ def _update_path_edge_end_undirected( theta = atan2(*((coordst[-2] - coordst[-1])[::-1])) voff = 0 * coordst[0] voff[:] = [cos(theta), sin(theta)] - voff *= size + voff *= size / 2 end = trans_inv(trans(coords[-1]) + voff) path.vertices[-1] = end @@ -335,7 +304,7 @@ def _update_path_edge_end_directed( theta = atan2(*((coordst[-6] - coordst[-3])[::-1])) voff_unity = 0 * coordst[0] voff_unity[:] = [cos(theta), sin(theta)] - voff = voff_unity * size + voff = voff_unity * size / 2 voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] tip = trans_inv(trans(coords[-3]) + voff) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 374dff04b..59fc1089f 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -523,6 +523,7 @@ def _draw_vertices(self): patches, offsets=offsets, offset_transform=self.axes.transData, + match_original=True, ) art.set_transform(IdentityTransform()) self._vertices.append(art) @@ -775,7 +776,7 @@ def draw(self, graph, *args, **kwds): ax.set_yticks([]) # Set equal aspect to get actual circles - #ax.set_aspect(1) + ax.set_aspect(1) # Autoscale for x/y axis limits ax.autoscale_view() From d3e42995072f9893783087bc713ff43f5073fbd4 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sun, 28 May 2023 15:03:12 +1000 Subject: [PATCH 1281/1892] Vertex labels and related offsets are fine, missing group marking --- src/igraph/drawing/matplotlib/graph.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 59fc1089f..c626338cf 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -316,20 +316,18 @@ def _draw_vertex_labels(self): else: vertex_width = vertex.width vertex_height = vertex.height - xtext = coords[0] + dist * vertex_width * np.cos(angle) - ytext = coords[1] + dist * vertex_height * np.sin(angle) + xtext = dist * 0.5 * vertex_width * np.cos(angle) + ytext = dist * 0.5 * vertex_height * np.sin(angle) xytext = (xtext, ytext) - textcoords = "data" art = mpl.text.Annotation( vertex.label, coords, xytext=xytext, - textcoords=textcoords, + textcoords='offset points', fontsize=label_size, ha="center", va="center", - transform=self.axes.transData, clip_on=True, zorder=3, ) From f949f158f389719b6285d3dd31934dd7c3599d2a Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 29 May 2023 18:58:25 +1000 Subject: [PATCH 1282/1892] All works, baseline images unchanged --- src/igraph/drawing/matplotlib/edge.py | 8 +- src/igraph/drawing/matplotlib/graph.py | 127 ++++++++++------------ src/igraph/drawing/matplotlib/polygon.py | 131 +++++++++++++++-------- src/igraph/drawing/shapes.py | 2 +- tests/drawing/matplotlib/test_graph.py | 18 +++- 5 files changed, 159 insertions(+), 127 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 5e1132fb4..f557964af 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -253,10 +253,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._paths_original = deepcopy(self._paths) - def _update_path_from_vertices(self): - if self._vertex_sizes is None: - return - + def _update_paths(self): paths_original = self._paths_original vertex_sizes = self._vertex_sizes trans = self.axes.transData.transform @@ -314,5 +311,6 @@ def _update_path_edge_end_directed( path.vertices[-5:] = [headbase, headleft, tip, headright, headbase] def draw(self, renderer): - self._update_path_from_vertices() + if self._vertex_sizes is not None: + self._update_paths() return super().draw(renderer) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index c626338cf..f1aab7cff 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -18,10 +18,10 @@ from igraph._igraph import convex_hull, VertexSeq from igraph.drawing.baseclasses import AbstractGraphDrawer -from igraph.drawing.utils import Point, FakeModule +from igraph.drawing.utils import FakeModule from .edge import MatplotlibEdgeDrawer, EdgeCollection -from .polygon import MatplotlibPolygonDrawer +from .polygon import HullCollection from .utils import find_matplotlib from .vertex import MatplotlibVertexDrawer @@ -174,24 +174,24 @@ def _kwds_post_update(self): self.stale = True def _clear_state(self): - self._vertices = [] - self._edges = [] + self._vertices = None + self._edges = None self._vertex_labels = [] self._edge_labels = [] - self._group_artists = [] + self._groups = None self._legend_info = {} def get_children(self): - artists = sum( - [ - self._group_artists, - self._edges, - self._vertices, - self._edge_labels, - self._vertex_labels, - ], - [], - ) + artists = [] + if self._groups is not None: + artists.append(self._groups) + # This way vertices are on top of edges, since they are drawn later + if self._edges is not None: + artists.append(self._edges) + if self._vertices is not None: + artists.append(self._vertices) + artists.extend(self._edge_labels) + artists.extend(self._vertex_labels) return tuple(artists) def _set_edge_curve(self, **kwds): @@ -233,7 +233,7 @@ def get_edges(self): def get_groups(self): """Get group/cluster/cover artists.""" - return self._group_artists + return self._groups def get_vertex_labels(self): """Get vertex label artists.""" @@ -256,25 +256,19 @@ def get_datalim(self): if len(layout) == 0: mins = np.array([0, 0]) maxs = np.array([1, 1]) - else: - mins = np.min(layout, axis=0).astype(float) - maxs = np.max(layout, axis=0).astype(float) - - # 5% padding, on each side - pad = (maxs - mins) * 0.05 - mins -= pad - maxs += pad - - ## Pad by vertex size, to ensure they fit - #vertex_builder = self.vertex_builder - #if vertex_builder.size is not None: - # mins -= vertex_builder.size * 1.1 - # maxs += vertex_builder.size * 1.1 - #else: - # mins[0] -= vertex_builder.width * 0.55 - # mins[1] -= vertex_builder.height * 0.55 - # maxs[0] += vertex_builder.width * 0.55 - # maxs[1] += vertex_builder.height * 0.55 + return (mins, maxs) + + # NOTE: Better than this would be to compute bounding boxes explicitely, + # e.g. for vertex labels. However, that needs to be done very carefully + # (e.g. see the note for mpl.artist.Artist.get_window_extent). We + # currently lack the knowledge to ensure that would work well, but + # that might change in the future. + mins = np.min(layout, axis=0).astype(float) + maxs = np.max(layout, axis=0).astype(float) + # 8% padding, on each side + pad = (maxs - mins) * 0.08 + mins -= pad + maxs += pad return (mins, maxs) @@ -396,15 +390,15 @@ def _draw_groups(self): # Deferred import to avoid a cycle in the import graph from igraph.clustering import VertexClustering, VertexCover + mark_groups = self.kwds["mark_groups"] + if not mark_groups: + return + kwds = self.kwds palette = self.kwds["palette"] layout = self.kwds["layout"] - mark_groups = self.kwds["mark_groups"] vertex_builder = self.vertex_builder - if not mark_groups: - return - # Figure out what to do with mark_groups in order to be able to # iterate over it and get memberlist-color pairs if isinstance(mark_groups, dict): @@ -432,6 +426,10 @@ def _draw_groups(self): } # Iterate over color-memberlist pairs + polygons = [] + corner_radii = [] + facecolors = [] + edgecolors = [] for group, color_id in group_iter: if not group or color_id is None: continue @@ -446,38 +444,12 @@ def _draw_groups(self): # Get the vertex indices that constitute the convex hull hull = [group[i] for i in convex_hull([layout[idx] for idx in group])] - # Calculate the preferred rounding radius for the corners - corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) - - # Construct the polygon + # Construct the hull polygon polygon = [layout[idx] for idx in hull] - if len(polygon) == 2: - # Expand the polygon (which is a flat line otherwise) - a, b = Point(*polygon[0]), Point(*polygon[1]) - c = corner_radius * (a - b).normalized() - n = Point(-c[1], c[0]) - polygon = [a + n, b + n, b - c, b - n, a - n, a + c] - else: - # Expand the polygon around its center of mass - center = Point( - *[sum(coords) / float(len(coords)) for coords in zip(*polygon)] - ) - polygon = [ - Point(*point).towards(center, -corner_radius) for point in polygon - ] - - # Draw the hull + # Calculate rounding radius and facecolor + corner_radius = 1.25 * max(vertex_builder[idx].size for idx in hull) facecolor = (color[0], color[1], color[2], 0.25 * color[3]) - drawer = MatplotlibPolygonDrawer(self.axes) - art = drawer.draw( - polygon, - corner_radius=corner_radius, - facecolor=facecolor, - edgecolor=color, - ) - if art is not None: - self._group_artists.append(art) if kwds.get("legend", False): legend_info["handles"].append( @@ -491,6 +463,21 @@ def _draw_groups(self): ) legend_info["labels"].append(str(color_id)) + if len(polygon) >= 1: + polygons.append(mpl.path.Path(polygon)) + corner_radii.append(corner_radius) + facecolors.append(facecolor) + edgecolors.append(color) + + art = HullCollection( + polygons, + corner_radius=corner_radii, + facecolor=facecolors, + edgecolor=edgecolors, + transform=self.axes.transData, + ) + self._groups = art + if kwds.get("legend", False): self.legend_info = legend_info @@ -524,7 +511,7 @@ def _draw_vertices(self): match_original=True, ) art.set_transform(IdentityTransform()) - self._vertices.append(art) + self._vertices = art def _draw_edges(self): """Draw the edges""" @@ -577,7 +564,7 @@ def _draw_edges(self): arrow_widths=arrow_widths, transform=self.axes.transData, ) - self._edges.append(art) + self._edges = art def _reprocess(self): """Prepare artist and children for the actual drawing. diff --git a/src/igraph/drawing/matplotlib/polygon.py b/src/igraph/drawing/matplotlib/polygon.py index 8e429a9b8..c014e9b22 100644 --- a/src/igraph/drawing/matplotlib/polygon.py +++ b/src/igraph/drawing/matplotlib/polygon.py @@ -1,49 +1,52 @@ +from copy import deepcopy + from igraph.drawing.utils import calculate_corner_radii from igraph.utils import consecutive_pairs +from igraph.drawing.utils import Point, FakeModule from .utils import find_matplotlib -__all__ = ("MatplotlibPolygonDrawer",) +__all__ = ("HullCollection",) mpl, plt = find_matplotlib() - - -class MatplotlibPolygonDrawer: - """Class that is used to draw polygons in matplotlib. - - The corner points of the polygon can be set by the C{points} - property of the drawer, or passed at construction time. Most - drawing methods in this class also have an extra C{points} - argument that can be used to override the set of points in the - C{points} property.""" - - def __init__(self, ax): - """Constructs a new polygon drawer that draws on the given - Matplotlib axes. - - @param ax: the matplotlib Axes to draw on - """ - self.context = ax - - def draw(self, points, corner_radius=0, **kwds): - """Draws a polygon to the associated axes. - - @param points: the coordinates of the corners of the polygon, - in clockwise or counter-clockwise order, or C{None} if we are - about to use the C{points} property of the class. - @param corner_radius: if zero, an ordinary polygon will be drawn. - If positive, the corners of the polygon will be rounded with - the given radius. - """ - if len(points) < 2: - # Well, a polygon must have at least two corner points - return - - ax = self.context +try: + PathCollection = mpl.collections.PathCollection +except AttributeError: + PatchCollection = FakeModule + + +class HullCollection(PathCollection): + """Collection for hulls connecting vertex covers/clusters. + + The class takes the normal arguments of a PathCollection, plus one argument + called "corner_radius" that specifies how much to smoothen the polygon + vertices into round corners. This argument can be a float or a sequence + of floats, one for each hull to be drawn. + """ + def __init__(self, *args, **kwargs): + self._corner_radii = kwargs.pop("corner_radius", None) + super().__init__(*args, **kwargs) + self._paths_original = deepcopy(self._paths) + try: + self._corner_radii = list(iter(self._corner_radii)) + except TypeError: + self._corner_radii = [self._corner_radii for x in self._paths] + + def _update_paths(self): + paths_original = self._paths_original + corner_radii = self._corner_radii + trans = self.axes.transData.transform + trans_inv = self.axes.transData.inverted().transform + + for i, (path_orig, radius) in enumerate(zip(paths_original, corner_radii)): + self._paths[i] = self._compute_path_with_corner_radius( + path_orig, radius, trans, trans_inv, + ) + + @staticmethod + def _round_corners(points, corner_radius): if corner_radius <= 0: - # No rounded corners, this is simple - stroke = mpl.patches.Polygon(points, **kwds) - ax.add_patch(stroke) + return (points, None) # Rounded corners. First, we will take each side of the # polygon and find what the corner radius should be on @@ -80,11 +83,47 @@ def draw(self, points, corner_radius=0, **kwds): codes.extend([mpl.path.Path.CURVE4] * 3) u = v - art = mpl.patches.PathPatch( - mpl.path.Path(path, codes=codes, closed=True), - transform=ax.transData, - clip_on=True, - zorder=4, - **kwds, - ) - return art + return (path, codes) + + @staticmethod + def _expand_path(coordst, radius): + if len(coordst) == 1: + # Expand a rectangle around a single vertex + a = Point(*coordst[0]) + c = Point(radius, 0) + n = Point(-c[1], c[0]) + polygon = [a + n, a - c, a - n, a + c] + elif len(coordst) == 2: + # Flat line, make it an actual shape + a, b = Point(*coordst[0]), Point(*coordst[1]) + c = radius * (a - b).normalized() + n = Point(-c[1], c[0]) + polygon = [a + n, b + n, b - c, b - n, a - n, a + c] + else: + # Expand the polygon around its center of mass + center = Point( + *[sum(coords) / float(len(coords)) for coords in zip(*coordst)] + ) + polygon = [ + Point(*point).towards(center, -radius) for point in coordst + ] + return polygon + + def _compute_path_with_corner_radius( + self, path_orig, radius, trans, trans_inv, + ): + # Move to point/canvas coordinates + coordst = trans(path_orig.vertices) + # Expand around vertices + polygon = self._expand_path(coordst, radius) + # Compute round corners + (polygon, codes) = self._round_corners(polygon, radius) + # Return to data coordinates + polygon = [trans_inv(x) for x in polygon] + return mpl.path.Path(polygon, codes) + + def draw(self, renderer): + if self._corner_radii is not None: + self._update_paths() + return super().draw(renderer) + diff --git a/src/igraph/drawing/shapes.py b/src/igraph/drawing/shapes.py index 6598766d4..df4d00c70 100644 --- a/src/igraph/drawing/shapes.py +++ b/src/igraph/drawing/shapes.py @@ -96,7 +96,7 @@ def draw_path(ctx, center_x, center_y, width, height=None, **kwargs): height = height or width if hasattr(plt, "Axes") and isinstance(ctx, plt.Axes): return mpl.patches.Rectangle( - - width / 2, - height / 2, + (- width / 2, - height / 2), width, height, clip_on=True, diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index f40bcdb78..ad7a64dab 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -86,15 +86,15 @@ def test_mark_groups_squares(self): ) @image_comparison(baseline_images=["graph_edit_children"], remove_text=True) - def test_mark_groups_squares(self): + def test_edit_children(self): plt.close("all") g = Graph.Ring(5) fig, ax = plt.subplots() plot(g, target=ax, vertex_shape="o", layout=self.layout_small_ring) graph_artist = ax.get_children()[0] - dot = graph_artist.get_vertices()[0] - dot.set_facecolor("blue") - dot.radius *= 0.5 + dots = graph_artist.get_vertices() + dots.set_facecolor("blue") + dots.radius *= 0.5 @image_comparison(baseline_images=["graph_basic"], remove_text=True) def test_gh_587(self): @@ -190,7 +190,15 @@ def test_clustering_directed_large(self): g = Graph.Ring(50, directed=True) clu = VertexClustering(g, [0] * 3 + [1] * 17 + [2] * 30) fig, ax = plt.subplots() - plot(clu, layout=self.layout_large_ring, target=ax, mark_groups=True) + plot( + clu, + vertex_size=17, + edge_arrow_size=5, + edge_arrow_width=5, + layout=self.layout_large_ring, + target=ax, + mark_groups=True, + ) def suite(): From 682daaea46f0e6a55b9c0c5ca5226075b369ada8 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 29 May 2023 19:07:43 +1000 Subject: [PATCH 1283/1892] Remove fixed aspect ratio --- src/igraph/drawing/matplotlib/graph.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index f1aab7cff..80636b723 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -760,9 +760,6 @@ def draw(self, graph, *args, **kwds): ax.set_xticks([]) ax.set_yticks([]) - # Set equal aspect to get actual circles - ax.set_aspect(1) - # Autoscale for x/y axis limits ax.autoscale_view() From 7c5bb84efd706855b79bc65276fa5e11eb7b8639 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 29 May 2023 22:00:24 +1000 Subject: [PATCH 1284/1892] mpl baseline images, tweak some tests --- src/igraph/drawing/matplotlib/graph.py | 35 ++++++++++++++---- .../test_graph/clustering_directed.png | Bin 34606 -> 36495 bytes .../test_graph/clustering_directed_large.png | Bin 60151 -> 62421 bytes .../test_graph/graph_basic.png | Bin 22749 -> 22683 bytes .../test_graph/graph_directed.png | Bin 23715 -> 23740 bytes .../test_graph/graph_layout_attribute.png | Bin 8845 -> 18111 bytes .../test_graph/graph_mark_groups_directed.png | Bin 23715 -> 23740 bytes .../graph_mark_groups_squares_directed.png | Bin 0 -> 19296 bytes tests/drawing/matplotlib/test_graph.py | 1 - 9 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 80636b723..ea09440f5 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -258,15 +258,36 @@ def get_datalim(self): maxs = np.array([1, 1]) return (mins, maxs) - # NOTE: Better than this would be to compute bounding boxes explicitely, - # e.g. for vertex labels. However, that needs to be done very carefully - # (e.g. see the note for mpl.artist.Artist.get_window_extent). We - # currently lack the knowledge to ensure that would work well, but - # that might change in the future. + # Use the layout as a base, and expand using bboxes from other artists mins = np.min(layout, axis=0).astype(float) maxs = np.max(layout, axis=0).astype(float) - # 8% padding, on each side - pad = (maxs - mins) * 0.08 + + # NOTE: unlike other Collections, the vertices are a vanilla class: + # PatchCollection with an offset transform using transData. Therefore, + # care should be taken if one wants to include it here + if self._vertices is not None: + trans = self.axes.transData.transform + trans_inv = self.axes.transData.inverted().transform + verts = self._vertices + for path, offset in zip(verts.get_paths(), verts._offsets): + bbox = path.get_extents() + mins = np.minimum(mins, trans_inv(bbox.min + trans(offset))) + maxs = np.maximum(maxs, trans_inv(bbox.max + trans(offset))) + + if self._edges is not None: + for path in self._edges.get_paths(): + bbox = path.get_extents() + mins = np.minimum(mins, bbox.min) + maxs = np.maximum(maxs, bbox.max) + + if self._groups is not None: + for path in self._groups.get_paths(): + bbox = path.get_extents() + mins = np.minimum(mins, bbox.min) + maxs = np.maximum(maxs, bbox.max) + + # 5% padding, on each side + pad = (maxs - mins) * 0.05 mins -= pad maxs += pad diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index 8a8179e05c9997cca1a174bfa5702e803efa1167..195b0f379f299c97eef8f1455538eac3fa9bbfef 100644 GIT binary patch literal 36495 zcmeFZ^;eZ&&^8VSP`X1&46bh*yC@4aWwTyxFLwfXc$P7({96deHp0qd2Nm;wR<(jx=}*n8A_;C~Vv zeXPM>y!PVn?G>$z?45LN4H0B@?XAtN?9EN|9yuD?+L>5cva@irurWRQU~g}2$H&TQ z@xLEnv9dL0okT|s1P?*8mQuAtK)}(3{viGk&Ne|n2)%kG_EO0?X=~cyeUi$>@BQ6w z1URBk`}Fkpw_nQDPc3W8EH*4mUu~3IROB~QyVXQnRLo4f!fY(2rcqu=JzDF&yj*NV zpvT46nQ@xC(I8RLdCtBY#r3gjHEC6VrK^}p?CuBFXyJrN4gDy1J@pQPexw@z-#`AJ z5&r)?!Ea0xa+AlZ#9OmCZl@v=0q13Bhg;?!rXDOTJmMO0C-kDkLu84a{u>g+69WSu z?f8iF%ow{n1&iId*#{*e=AO`O>h7lPOJ|;?rLVUdX=%6wNZS)HXX{roFr^)1aQRIXk2HFT!9*+NGj+OCJcp4HI!@8l)SM#F4t&B5n=X!@eAGWMkdoz`jCDO>Qk`ELVdkme z*q*gg7SEFBrb1XvLQ>Jj(r=%rFnvs|fJFF0OpJ!dd|Hjm+I-STnZ4S95qxKS=$Gs8 zllb_(!@j+S+oqMC{xn}S>R8QtJqhEQ$w3`>iU@dkc*YZTljh$Ub{5|^%#eSa%u#$b zw>H$?J^cd*Y=hZ%w;?b`Q8u+}J-a2ZqB#i9QH73L!4TT#0w!>h*RNmAy)SB>n#tE3 zkNTOOvHffCAvU@9tS7s!!J-7uv6Ax^8$pMd7`Ys@x2?!%l%cGquk^ImOd20%maWDI zk;4}H@u;kvzV|L4#=lEwsyAyR|SQ*_yp3;61O)m zCr9TF&)=6=kYOkn7@cRyl6U-RLJ{LM6)QN|emGplNTFWZs7Z#kVobSNO`CO- zM1IRc0PfA%vgzLzBCX7mCCm8mW)yecS7Hj!w*INhO*I9hvqIEshI ziw+%wtvyp0N3eW~`2|mw4BJp$OG^(z-OY6mgJdjAFZqqrSEjCo>r_v@L1|XJ$ke_? zEmkiiQly5AZki@PPW*5Z(NU_LN1Bb+`N@vu6*V$L|cFLoYmu+bJ2U%do05}pJR?THl&X! zq=uzBs6D?LUB$xBcS^%~oAYdkpXX4zb3h?u^)%TP9C)5gv;CYc3=Ck$1Ew?eO+!YlT>b9@nHFzF- zp3PotPp;dw5oyGv_A!>(huSn&V38GH`Qm(tk9#kz(nLLyZJ5M=L(4znZ;On4i6p+uEJA3@cOMr{5^m2-B;^TLB z{?4mNXdI}mnvUih*&rO>7B%aymZEGuvZ3tR4;p3qhfus<4YiJlB74{nE zcC$ZC4)YeHwEGuRLXrb*7&uKM0 z9PS>*nFo>+GC`M5G-DU`?PSd;x$k6dtczrg*DW9SRUgZtN&)Tc=5i^5)}hi|s*4Mg zYC}re$2hGW+xY&-M2t}_3@ozdC$Ymf4&s?J3gAF&o_G0#l1Y~kN*hDwvs#X4voXv@mrA4g)>r$q)<;_=S~Rco)QWYHJU+h2f8viMIBgkYK8D+v zt9KJN?aH{cniySbRsT^@4$T~kT7ea!XJgEqWx)DnWBXyZnp<~;#)amCX z#Zstq8i5tl$3j&s=|76=YM^PHqUTnB> z!e!C@>K%!;xsh#a>)88D?|4MLc2!-=u4ZG=J;d&l`pexwud5dG{mW&N2SQURYGRpk zkcDzA#>Wi3HbXB zQF_{vseoID5w4|EWw<|DZh>UqhVB>Gq95M0UD2X_qo=&>dR$yVifcwhV(a?b-Tgp0#M?784)NQbi3{mI_&zL(AMwpuZ^M;}Hz1rZZjZ%uyzgf5iNK zQQp_y$f60eZ+i`>g}i`n!caJWZ+ErSXRt_{xu_bFJ4COqAhd10V#o)=`K8}A;5U{84d)zhhG z0iGQqBKf-@BHlX*@C;Qhj27^QLQ6={DC9r-%OGJ+;OFkU3-zwn(3Y(++ z)Fvj+Y|__p;<>QY%1djg@z4|?t1t7~pUv(}KWVwWIA;HtA&CRMCe^UW?DppQM}03# zOaIf;%IVV3(Bu1I*l1`Rm{`ZRH{3(nb|=C&O)#Ao%%eg?QZP@Cm4{(YdPArAnzVkc zt#K(4=|t3ck&n|rf`b{IY430RUiwq$V)tjSVWDv#H#XpwH==JQYW)11 zXhwK=G0nqWAQ>NjZ7LIOdvO63Bga|NHf>b;RGKAiJVh|`%zbzys~R@3pId?RrAXleTC*&=}zOFxA^IYO=Il+~<_%lt&(f*tq1?tt+K zb?;kO+t#R-{+rSKGW%%KVw;S0wDmz0&r2*)?sCYQ)WDhw!Uje$6gL(2IaPJeXWF+n zE6}MWT{Vkv85*1+wf{b{Kd75Q-<^HR)cwnn&?3i_h`=}do-%=@=f3#N#R{2c36q4< z<#^`>7Ejx<-c{A=K{FQj@LtL27ZB%>gVz^LeZq+ZCBV5~fau-G+A_Bzx7;77#2}6v z%1z*8L?gexG&@U0S|%negbPkn@o*U%ym|i$$yv$w-c8{EFI(iwz(A$heC1+Nt$46(=W|`*Z8+E^(2rm?Zm7`qJP~!xx()M^=A>i3bKa?W5I--K*jWp4-y6 z-`4TQy%bw|2BIL-vZKqF*X}jQE8T1@w+jn0bAbOMhpqH*hP3EnudH6WagTh@f-LSH zef1&OWGtdrTsOl`k6Jc8-5O=>cKv3{T&`i0WhL)@6T1-AXw%zMKj)7mA8RyO63Ra` zq0yzve8^dG@-_-38)|sRcu`?0-nF*oea#!*kuGkecY#LN7^~e3_qvA{DN64hBxTLO z#F0z-J@9sUDXwnq`Xc(5ZK*|WDRMFRuUVr|4RA6Z@Cqt9}_OZHl z(CX4M+j_K$^Wx?1!%fG-pM8=QkKMz*H#%1&#tTu!rr4rmsg*U`#npeMeft(N31Xhw z00ZrBRb7J}jmlFko>PspGkpq4X6k4Fhmmu0hw=5H3q)Z#iamP`5~1JZQ@=33qu@6^ zOKsT_bnb6RHU$A(!}#Dr<(JFi@0-Q};CT-MQv^;XeNZ&c&lb&J$*+QU?+a12BN3J9 z?;?33YB|)r+CN_#E2ZC^w!?Ysdb%>R+dxoX2_k`pI|_S+c%fHv~5~ zPJlUG^Akp*1EU17s}ldx(sVr2mXLtL&*GhCb=*1m0&0w5WJHWiwYOSF6@NXHKs@4j*t+;o>i-` z<_lk%_fm2O7p8B&PG!}QI+!Svd?)HIhJ3AFw!o@cGjTh+Q!zVN)UI>o?0jyRCloAI z1ze|H&9Q4g8TMlz;&|ly6=$j%hLF;Jt_x-J< zKYyz|+x?I&1y9CI1tmkzcD?4~jpxGn=RVO9iij=AAC;#CjTyINmsG!!sHo&+S^}a2Dq7I&UeC7WWQ$m`2pkiNi8WrIPHIL5@j%doEa&P9_-C$4 z;v~N#M=qI)mPx>^xcInQ*4MoYck}6*(T4A)9%`h#(U{j5ht6wnOz%n7R8~HwyilR4 z(qy?;YTCAxF%|Ha=J}TfoQDc6@7}dkttQ|eG$PUZO}XYy6MYKu1q?xId%OYSXHTTN zxAW8!ncsO`CZ2P0jr1~n{|YOJ?Rog{W?PADaOe-?hUQcGmi{+zWCKaS@y`h1vh%vwL@7cptc9w`19RAJ)O3%C&8*A6hDV`cee7yUB5JzUjrrxg3d!3(y6h$k?@i9XjgEO5^OwLni z6DR(;)_8xzT6&sSa%WpjoVd?Tzl}CeL=Dkcg9R0eJlAg2kIPT19uU{uhh@ZDeWT(?F>ZO+3 z*tCM`RD!5n_qy1WXdVtv8qSbJV92GdAls=O@{4G=`Ah!S?P}jqAZ zkt}eh^>w2ii2|)BL%(Yr|LzF~J_YVl+gU`%nA?0=?F~@eFzYjSxtn$J)gP4*l0)@< zG@HPn@Sty!B}Ovp4KrSo>vgU+w$J=O$EQ~IGE$GyU-}{_GfC>(N!*jaIhjng z3=a>|S%_n6l@#0S>Wp?TvCp|ZmD?PTQgl7RG>DgEWyRU4x<8W7Ics+h=Psc>L&1%_ zFk0>X@;CHPl=%*GS=_+#=$OUb%g+R2^U| z3Zvh%6RGyv7|C;$L3wEZ>|=(P7s%nL1%2%&9+#b%*Im7R1$#GXlsFU%i`O4BG&RU| zCrDN3+)E758VIk|nOWTl`8oWO1~cwwA8!y9^5s5Z?81E7-QjIA)crFzXcz-{hC|QI z^-7@2`n*>RN}gIYa+v3J_uDGHToDkKZl@O&N)}Smk1M{Uc>xEoXG&;-GDLY%k>8K= z2DypU#ID?-ta+Q7D)+TF_|%UXYj<~ZRSuUI+HMNu*9UwR-A*vWhPs}!_n@g(RXy{l zcF_k^K>%1&CpJnElpa^-fRRPfKG6kRW5;}B9vGl_E@AYs%@-NJ^oAV)Ln z>v0%rbUJ)M<*ky$k;90={Sv8bbgyc9r6+16ZyOLT(|A~rRNLddh-Ep3DcH-E*?K62pt{Bxyt&?ICJ`|8RYGb}cFH zy`^H2l!L5lO$;kB%aNCdUWH}SK#h~NUqnx$EUL-uj62TfFvxRrP{6|-OPK5^J=ZgA zh6cN*LQ@2#VUiV=q&LPT0P!wbeoqW5Ia2Yw0nyKGsbSRV{5gy(2H_QWwpT1VoX&pp zcYG7R$Vi?qD1)pjuMRMt{s1hE5f{P_XBS?8|=3`RXr|{B~ew2 zV3rLOVZ8TlF11l{?rifCyys(~naVg(7#3M4_U-2EZ0+RekI3oh5p@vnpfdPE6jsXd z+|HJvwqbHP-Qq6p^xXxpIGMG`jW((s+?5&p$Y;wKjqgjNs@6W(sm2HsB(A@i_=O%K zmHZ7v8QJsa;KAxugHtp09ss;T$tKl|JXQ|R$5P_gamY6Z2Rk~ua`$fFmfYLYSl4DC zuOeA|ihA_S;@VY6v#{~@*haJ3T5h(!2~T9D$JcGwpS{<+PiTlsDUuI#M>A>3dENj| zUuc8sniJ0U1(1{SYK5rOUt?XXr^ZOgy?p6^YK4oh089@EhREL|)|aLi7su`jVBwSB zF;?$Mqs9wSP`cx?RHM##&30qp-F541Ic#lpMt*&1WV6x&WNL8ecOqv=&7f;;?R1 zzwyY55LgCuzb#R)b6O-Ew}QHs7oyG&i@g7sjp`wKVFlpYZWXP#?I_B}D;A}=NX(jv z`+&~1luNDF`^rM#MO)^eYyEL?BUd`$c3nJ|+4kU2H8y5tcXli(^6h$mLtFq>7x|}2 zCWg*))@m`+u^?;;YeXs%{|I_<_)@J7Dx5AAv#M&(>(*GLLlkEm@Eh_cAYPwcleU3e zEg!IC(9z8yDSWby1eyxUP&Ln`>f&M;aAPr9Q81Y11+wYQP3S_JSD4qwC-?|0{PvB@ zw)+JxhlSotWoAW8A%~ZzPB#saC4F3sa2#QCk&a}i3Fs{-D7ZPPOkJ2Y3?3YorVM@o zA_ZF3y}aPCMMSsr%e5u|(9v3NO*J$OUUG*99|VTVefre8A*COQj%7AW8Qaw+X}7AU zYZQP0{D-Bo@t5C}Lo9FgRaPQYKZZrXf`+NoE1*iw!wnoWfgDH!Dy&$yB_9n{4G3i) zvSO3xsH%eE8>RH~r+tv{UQ0cC?b|69*1@(tf%p{-F4VPPg>-Mu(G~R}cduVWq7~SH ziiR%WO}5B{FEV!~>T0&o+b@o@Op5G`AFwqehY5KA^V|dBwc7acOJiir?-}3wAgzJ$ zk~RO;;FSSlIF#e7Oy)$G$tX6-p6*-J_;OD{??cg`E|gI%Gm(yWDlc0Ctmpk9X7DZ( zf!d*crVc8A-|Jdh&CYOyX}ji}bMj5h@NL3Dd4Cv@=5?1iy@Dn+K@bF{I zT8v_Aun>qag_vxP>Z=lyV3Mz0;o2VdWYI0{dU3;-ewA$HzXtWE-3uCLL&IobqYshm z+aJb@x0u4toD(tfyg-~yo@_I&&r3-!>UetkpW+-lui;Yd;*f7IET9gx>PLDfRJgG3 zlKA63qchT6JHmyn3^z+s`9EZztJ$4vC4h1ZwkV>QkEG=e=m`=Li|FZrX~V2`%dPnv zP{F(GYJnmlpp?Uw@!;p>|?I=ZMGUk1cg^jSLA8eNQAL_`G7g zgOoPH^VD6OPRzYfd9yV6Ssrq9oae@lk6T}E7lJIDj4tRp21OeHRL~#nep}flxp;E} z1q4WEP&l*BfgJEYHD*Pa7$i%h@26JyM9UyoDgoXgwvqA;3x0Xp!dwye?70Q0{e}VX zeuZEVTKN`}0Q@J*dwv<&ZyJ@q!+N0892n4nqO{-N;2=&_gG2t~=!Q8x0|01<<=C?q z(ZNB}#Fmr4`Adw>MLQzOEvoGIbXEf+>fCe}#12RscE!H&k#^{&_j=`rlnzE#dfT*Qmatd@{rvzKHd3W^|&kM;lZ zYxRKzDUH^9fEZ%dwzRYw?FGH~zJ>n125*2&$(N^>D%>Mk-y`Fr6z8u6Ex9d1 zvOYV>$z+O(z_7|tvdt1xM)go`Foi8$_Xz-feLu4-S)fCgNot30Au zn2d6aYA1`}Ro|*FF>@znDCkllE`mI$#bM|U+60?J|7AizIJblUy}`r1HsI!yR5a5} zeR73y&q1mWccm;D3&nHf@FCHT80KdtU&aGC4TE`mHO0&`5U2wy+_>GZisGN~+hxV~ zrOkVl?}IXvp7Y2GDl$<}h-MmIN}*B^;IAnSbIfqDguO{-prw{H`E#;e`;Ng6({wt) zMl_I5*w1`ShjggMf!$6dJskig)E|#LICtNhy=|VfO4Jsle87Wy4~MIv+!EBzhzfJZ zPzh+B^IBS8RE_i;q%E@tq-sWM+M96?RvVt-Mt&Nuu*bY#d!ja^G*ic~;qo0=ousU6 z;e{p3=4+I&?aPz5znhv`9P!Gq99~Hn3Tuq`KtBbcSdf19Y&ivBGD;1&1ai@0WUbT%9$wh@&XY!Qd#8X zkO7DvTPP{Y4+T&^m$=nFG=WXAmH+g|8B+*_xae&#T`1KL z(8vgy+@`u1&H1pVU77VcM2e!^c9cbn6&R!RL({uEW4Pb&)}D|G90c*ADTtYd0we3H zKGTKO9^oh1e^E6ZIbRK2K0Y6-wo3K#2d!$;@1nQO0+f89D>N!3q$PSQmN}zZ=Ehwh z3)!JAL?mdjfy(m?UVECNiWSc@uwyE=!GscV(YWeMX6Zeu%{}|3Phe;#m>i;vb`k+z zYqJ-n90%waAj3F+_#td=&q8{!dggQvlnQhGxP!SacKMV-Q{(W~Vj1>}?9^s5t47XI zfXhGnF;d5B=mDg32!ly!t{ldDhF8q^fF2Q2Z0Fmx zVV6N6gz6b!^j4Z?@+aNt5z0*9Y@;hTqj^HX+!O=QZwMaao@7h)e>+^(2EnVesW z>Z+S8eIi}Cu-~p)VMfw2ZJB>~&V&8oZLbHj4*TBYy@d7_g@V|R6#NG>f~WnLPZP(7 zN=jTTF6^J9Q2_Akw=eoVK#b*vbRk3pBWCieeZP6b&MD`ieCN>;mPuT>T@Cl1q zdI~w!ozt>(+X{$k`jDzGo4mj`HdyCJdahrGanAug7wOin7|3YJm^Y~=61H|P7z zOXzCX%X+KGQH4f<4&Z?J>9lb#TfrlDgXJabm1!q-{Xh7WB}}vkl9$`UIL@ffu(Qdr zB6sUPLB9Y$@)MiG3iJ7vD!Xf>TxJ=?Q@)C~aP-Lr-x?%s9%dfA=K!OPx zd8GsNJSCu=s*){xNVPLiXQG%-!RAxQa5YsZ>nU`#NLA?03+i1=DkufNlt;|WKcBzP zb8T;D+wM3(p;8)H`i$@tj=fiw%LjD?&pSD zw;PO}MZZWfsM_igZte-NdkRz}dEKOXHZ*Q7Yagz#S#`y<2&sS`YYN|?3{?1oENBE~ zYvKF<-`UzQV3m07Xq~vWpe30zRW)?vf3#r;*+ClEp`(YhtGUK0v83zq<6HY!6X}=; z4qaFuEXp+J^Q*>9IGo9Kl>+pl7aOiYqOt0ZYYI3zVh{#z?SCD37l6Gj`5-l6+rihX)c**F+r*N+WD_cQ5^2A9~f- zn?GX5jf$40pOfYVTFc4PwLm@)(w=BvE|tHORc0FTfG%pn7qu#$spR;liQ=K03<~RT z#m;!kQd>wB3&K27cVzvjYuy!>8`rsH)d6Bea%x{b7~ADP17d^Bll}cE4p)wO@%w?~ zt{Mf8InD0%31OI+?8P>`kO%-Q7a0pBLg(as^_l)XkWKvpRh%n$8C77`?%y^Ts+B+X zNlI`wzzbw$^WuHL2@g!Px7!`A4crW2j1nh*btqMLMoKr7cD^tfs~zv29!xZ%ewU7b z|0_5giJWbra5a+keMvwJB~A}aiSz~4BV?&OBk%XwV2Z0?RT>h$nw3f8g{rDjiodXi zJ6K0!RCw5Y{vYU*P!+u*Tep%57yOlrU%tYR0~M`n7DV4Q3i_M0RUowu?^ znxWJo_gunhr|KP_%VS3V#4N<8n{Prt*80Ezm`Q{i8C|z+9u_@jk2*FnF_)4z7FARG zKGe-_XDij$OPiKdMGKbCT^1UmFQS0YDwo{ZbmeZRv0G{~_005ZgM6!v>xo}GB|E`T zA3sk01$vTNZcq>53!ec^Cs0xEoi?bf?>MGVJFGw(*K3u%|7{)IZ;5w9K%UzkPg<%e1v|BoDEJ zk;wow)74LRzKh#)?7zFR3l5T+9;D?O`Q?|H2{};!@J#51$>bsdm>(gr#?4Tz>RB)U zw};BqhHKhlg)U2YYhwdR~wmA{K z(*qmlW2L5+8{*@NNsRgugo=UG-5n8|E%$^@cy^_efz9;mc-~&q{guqu$IpYmrXk?V zlw10P>YBYzApOboN6qTO_Dw@K<`~Bx;@&t9#>&hP3K&5AyxkmoPy6|yBCTKT(h;uh z)xPy+-rj_n^=dLYoccTPp(v+W|9e<-m5X6(x}t7JjVM>|`QJrvN*pP9Ge)|2ZTnz|FsxQ6`X!4%5yS4k{7mc6%|8%gMdb<#aesKMefF=lva>l zYGh-R#ApAsz*PWoJRlmUc6;A?{S_Uat6%$0a8Qs^<~tcof-hfu7=c=cMZz1)Hc&CsB2@T4{}tGJhvlH-at&EH-gna!q+SzC0;&egYm=pe806iw0Le*>Uhhty(}o+ti*9Ae*~B-OiV2RYrf*q;u&A z4Ku$g&OJ5OtDLr+sad5|hJ_ECI~dBqid&kUw@1{?_JP3_W{CnLekj0~{J#*PBmTW!(rN^GKPk=Fn0t2 zry<$W*D}BS8G(Z7>r-qvXy+r2somkgbCWN;GAm!C=Pq{vy0#KStJ_do8z-QCoO`Ww zs%eYnCHs28iiJe`?+cSQEfh;+OWs`p7Ji?HPk{RI?|=Yb0@`=cj(U&Uh%X{BilRZ2 z7GcX2LR02{E{;_|j{^0+<58eKQ+KAka+((*LyTBH)1tr zHrzxT{|;|=_&V7Ngot4hhrdI+e))mO3?~5rAwXHVD+I&|-6siLJs{1%UL&@ykL3G* z{!EJT2thY3&E0+0L%^novz8EF#49}TR`1?@<#$4R^!-DN^SOK0Gga4)DRnol{y2De zMdDz95zk?SIq+Si1LM!1UMzT8+RBHSo#~$1h$@J0(&!MrNU|JZDlsmV3@7za3vX|s zAkpe*u9&5*mnM-z;&T%aKx0Dayma)yjYGRa`mnigjo0rr_aeq)4^bt_Hn=$u2)urp z47`@IK^;$t|8w}~4|zvVSyeGQ#|MOP0hq;P^C!CIFHfLkgA26$Ft$Xwu#vLSgzL23 zdUdndLZ%Rq6b?4HXZOy((t}|v{)X+q^kQ03U*NKB(de??J6*WYBQTU@5nQMFo$5kc zXFr@D6vWfLgLL0nh&R5QyyQB%qMO1&R>^Xnx3LiX4ZlP%YeQlfc0SaTfxS!6B%=_)YK4qq@&6nHUo+ooe#^ z3{Fkm#K89a%PalgxL~J_yn=qE=4kT5SU{PMMi+MjcLP=L>F z1o?GH(Z-;|15>^(^ME4;je8fJ>?GLuI7H9&flvM7aUMHbn9ZXEGS(bX{NQr^Xl!_2 zGyuOOxnv+}&>5iSS;VvxiIJlChOl7JhS=&v!`^8YrVJ^W^FM(R?7uN6f;g~Qd~?0; zeG32xg077~L)RT|y;BvD3Jv%FW`QrOAp+HRj?F$Eo(wsA7LA{QVf>^!n${eA{0^?J%P0}@u~2dKpU*X?$4hs2UFCC0uO*96|`LPE1Szl z?@@EU1Una?Jj^ZEfsV4WGJX3!8mN-WK0Kjm$$=ZRqE=p70zu6K;hAy@eCog7!CEGK z09GjELUY^&pyra0fQiEmItiaAxo!*>wKoI#U!qlWUIl}n)EnTK&uc1l?hZ~6ck~Ay zLHp93~i~VL*SXh8F+4tqKx3oK4Pl$NX}dDXJlj zWO(~;;W_sqS4ac17YJfx!4g2hBEW5kZlbEnrJ{@-+hyJciipY!)3YT40FS&(z-3E# zz1Iktpu~|*#$~VohcBHk8LS3?!9xInyq`3ye?bG7Oh&$j+|&jqNK?J=fA%{|7#IQM zRY;)IEQbZgZBve9pD8WM4X%%(Ks+c(fwM{~h3QG7fXF>zz=rpPh;)F_#CZd~qLhOk z>b~<_id*;aQAr<|_JGyU#{%;Z-A6bEaT7F_W#i04@Y+AZgO?ZD0jLHGtBP&?{2GyP zUVw?sgvm3va_|f+uWkgHzW+5#*ZkB8GRVN$xH@;P#dVvw*v zozv&Qu)W*mdH2O+*TA}-qz8*gg{*z}_Tfou4m?v=6kI0wFaWzbAOTkn0N7vMeSCz* z9yoMh5IT;rh{6|PKLcWm_KEFQTzov;tjzY-Mw|AgY6lQ#u&3TUsiBDf9_^)Ei$7S* zURvJQuzk*-^gx8q-kUDf&#-ImXb4URcvEHya9Te8 z3Y{DvToudgqz+aV2^N)7)}rj==k&ARMh_Rp23KIljYYLmp!KJN^;=f(mNkb-GeQnR z9x0)#3pOnVX0YFA{LG#78pL;J_BtLvGep<0MkFK#HTN(9*uiQ9tv#d?$ID58z5xoP zZQxcU3JPN@t+>yv9|@d2y4pkfOlCZpn4-`Cjw3l#@R6wqVB@@e%K;Hf2F3vqx-D}v zZu2F5a}#D3Zi|W=I1sIUzTLHW+KnVsSC1NM76 zl}Ix#_i5#nP$Sg<8rgGEwqQKTeY61qB(E)2OLOIZ1nz;}>tJ@#4v>~JU+pb~fDQ>d zT)_7zud=M)Upj4mz z_*4sVfEWaHWQGd42vDaYSQi54j)X5=9nK$g%~RcaucnmLkmmS8FW6yzFW$faus29a z-uc5*?$4y}0KEn&F6J|4A|qq_>@7Bl7HY*5%&Jz`iBq8+vd=&8eb@%iRD6s2hyLjt z;D=oN%zl*`*2jO1q~_1|K@kq3!2#gi(0Cmz9YRNHP6h#vubYyg>7f4x6z(DP^yapD zs8#zCJnJ--ThGt>ygK@U$XtkySit?F{-!ZRF}rxc1l|g1*M0QEKHBy9&w2rU0vhO;$r(E# z&|kdU7X?nY!ikDDfAKbB4T!A4lBDVBdokc}_=?i6dXJvBb?iolh6ue>J**tMDHBxVe;cNma3^pMR6^Et+O^BYifwvjukk5;}~n|2YRW5@P)3Gf~lw z;hbMiYN%*9+(_u^6#)ct-ruD`67&Hx;~`!e?>kq@bOdo}DVqq3PSie}K9!Y-lpHp>6ZzJ-zLPjUm_;Y`!qp2)Vc?+f--8*`XxM|7eS>g= z4W$vDZE?>MqrI(?h!`VRktD7GO>#+Kkts{J3Y|N?(#i#W;WPNcN)KYksjG{_1jnjB zXtK<&XX|zm^X!X_ffO6u+63OhLemP6E|?0u=LGfGxzgy&+7*mW3uF?1Z%o%%B0)8XgE#mht`#2;<8TiW2t=j&QufC5pIMM5IZ+Z40(XE^m_v7vB^K=G zDxe`~{=fqp^fH{bi-98?ZQjQbL>9hA_PXVFt^b=*sH|=~fSbS;H29BFuK|84yXMfPMe|{1C)Jc8aO;ixkg^ zqX4P8yX0}|{Z$L`?PJJBht5-$`8+ER?vdk*#PBkMx;K9v#bxiM^U6aoULk|>!L;C` zI~Hgo5I)%hW?e1bpbRtzAW~`6zD4JrLfEY{cH)FCWM$j+6En4ex(d(uuyR_1%l@fv zut*S?P~^q4s{-LxPjvKxZPW2+i%E7ov+C^);OVct?^gF;>cm$Pu;gA0z&5l_=^h=ED>e)~w?39+)8?>&$X`|~N1tYJ)A<^U{1?otXR?p-=W z^R%o;l)i_>01hQta8mV-{9M_5m>>)jrc}-cTnSRT$z{_*)F%h=?!!1nV{o{^$0!jg z0~$!1EFMo#JW>FV71FJN_3%Cd`Y&qgmpx!Uvp?5_X*Emv48Bx1UJ~D67y=Fhp8^XI z88{qF4dybvX~1pNJD8;Z@63HtCzlt1`t!kCKELkx76Cf{h)Ny;k%L27)bX+|z!~n{ zo!x)@${`GVx*2?WAPq^!kr${oun)Pc%BzYMpbCqIedx$9GaJCcFz)}x_AsoXtIZ$j z{_|pc)Oh~bDmipGvwHK8d`lR`iv6!{8Gx6hp!k9C^2Z%5*|DwB(0FG3D1*-tMC`fF zj>ZZPnBH2Lkq(XK`9{eH{9*#%F$IMKUyTY>2oQnlDzdsA?7zty(NLr#&~D|K+YqfA z24kKg9Z1ⅈ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 MhMIiAwflkp1D<^8i2wiq literal 34606 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png index a6ea8972f330c3b60de970b50a37f014b747aa2f..ed3c2dd1a223a05a0a29f8d7c22888fa1dc15d27 100644 GIT binary patch literal 62421 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

    }O`wpYJ2qIF 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 JiWRJ${SW^{U!(v4 literal 60151 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_basic.png index 259ec8d487269ad52d4479a18943b895132ddc9e..06cbf300a1ce5eac2143369a17824690984c8e7e 100644 GIT binary patch literal 22683 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 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed.png index 19f703fdeb3a515dde9a07e125aabd2987c05749..89d646b0fcd215ab38e93cc6c0fe6887806e4f89 100644 GIT binary patch literal 23740 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 Ib4q9e0FPl{r~m)} literal 23715 zcmeFZ`9Ia$`#%0Om1xjhN>p2s3>A`yMm8lgnX5w?qS$7!8=WTAj#LyfWll($(s4>9 zL)(S)Xo5Eh^)Y8G8{ zmp(=Dh*1=`DgQM5=8nhdk(OruS*W$LuMS;Jm5xAa}JXKxE`p*+f$T<5PjEn zL$C0zCQmOz+rM6ZJfbBwLr9Eqt=V@5|C&=zF6QKTSYBMHC#E@HS28Cj)h0&resE-@ z;33PZaf=2sp}j{}_Qy%==7^nD9|`WB^T#5Z&Ag56cj^9v?%pqWj(kz6Q@G*%MY{OQ zfKNU*)<6lq-#4B7)b-I-CqGTkbCcf}Zd@Ql{&_QsNq#(>$;XQyOj`*t^3U}FtDxXb`yOjD2+e#mJyq9HI z_fa>vHtEZXt8eI!=x?rPn&>-d{^`-yMrR3EC&dp%?HnlNne)J*Ix((*kCK=Rt7XoU z-n`kQGHzdGiEP0G9*rQ0nvWG!ws|^BxP!rYa?M&i<$9(jJJ%!EX?CE`ASZgp{I!YB zO*zJYPiM{xgilDM*Q8n|`42WmA8W`?dRCjXl2yO3_i2!(k0qNCZ?M$1q~lzumHy&D)KWiK&{Jpc`8lbqg^9omHP)$i=)lQ{qiHk2N=pBbC)K>gh*9C zJh)TMdMU&3f{MCspHF^H-_M4DreaaYOARRwaju#`X1vQ$rG`!;XP+D^uaA6Z=#SJ$=rot$D1PF z;upPw#obl5%+pK7EQEDGIeC4h9wqjH1i$T4?$ztue|qgLR@xs-3vEcbvTXC6Aa06_ zSPs9|^x4ZRPDN`hv{lyJREs=Hf-40e}-SMC?FLz~= zlAF>~kNoS~7fG8*sK^_hdh)JIhi>njeg8i9i5oVQ+$Hi*W~Fx&XT9QfT{9ogP}VLl zg7k3OHMgn$;lVRErOo3$fBr*c>xmsL@15TC`7G2d$$xgU>cgWF!xS@xf47aRYcO`T zv~=m9XO=@XJ24`lrkLft`DTv=hqb7#%cuYO^#2?{_@>yy9Coahj!w;m`D@Fz#yizL z>S)f--N>#~=p5~K&n-SI#u;9u_2#C$O(8|TV(RF*o_BdTj*ko!Tn`cq2`Z6&W^v-g ziJY+?B?}iVihFrwS?4|9@9&K1Dalt)&d!cGpcC($KWtZ>U{HKqnBw32PYlvkerl2G zrlsNIGveL;*+jYQ=8YTC#-(=>%9`^>YFans0*f%2zMpQ>WD7oR(Se$lW` zyv|+y;>X8g^L;};yC%GhJuAz5HDqqi*AizyCI6*i!sD#B0-Emz4B{1htif zT0dkk@Q9n)CnWI<9^V@i-a9uLw!PmlUfX4ya>)0~m^W?K_28o!oYKuLRhFJjZS7Lr z>OIj2P%^J?v(p(I{S?#mzkXoZ4Udl*luM-~wMt|;RXlQ(vW9`TuWu3dq?#)|{Xcgb)7}=KG%v#@)YMINZ9H{LK6!ot# zuu6NW`NAi@UzVo&nbEOJ^Ur3lzI{#pzLAa7=3+|+;aLk_-DaP#i&_1QJ$KO}k21}` zkl0qIS<4g+JI>D6YoYo+&((O#2PbEBQH8?84Q^E`rLrjP=$97E6~dZNEDorX`j7WQVFxzb^9Hm5?C814w);@+SR{ zHRc$lgzKn&bLCjk=kodGX~b)&*wuB7{N1YeLSUi1eTU(!C35QfRR@BNQ!NtSgh+LM z&+V?Up7^nN%U!?6)2YS8HN#hL-aHu2F&YjD>gnl$UEbbkJCi1@lvbN0u6^@pja1s# z=zvLc9eS6O;_jzS9qSX$#T=)5(Cb(~wX{Nl9kLy-l*S!)&Q^YWEGaN>j!8?wNuyMY zEp+y2KEcf6A9u94JJhD8OpK38$;gy-xFBIngCRyXHd@5S#W~bHvNcOTwEKdD$l^yX zE!(86@=P6TlJz>?gw#(|?*HMX(tg(@*GyrzdspIvvb*k0?zIVywW*Kl%I+3s!9P^T z`zza3AA9$G5tg%I)@QqPXLs{Zrx)TIv=TPOw!Xa+^!DxBzA{Oe*P)FYH)b9wUtwzt zyx<|Ve*NC+L?eUJI|`FM=^9s87-8YELxb>wcT6sxs)q-QK3$$kZNGx}6szg%oLZB7 zpmiDNi7w~QpdjO`D^wROTxhgPTjNAWby8@MsG9%tXW0#1IU^lO)oIphMrl?}fBiuT z-2z(B{cB+y-dPqpaucaLmKGF{u=_-SiAb#3!oEfO4b-?#P3=FFq-?sG?27x;M(d~Y((Zt>qb z8O9?KLcVFo=g*&y;)%?17zyOalarJC%C`J+)bzs|&D7#EF)=jNzPFps`CA}NGFna! za_%^$UN8FCvvVV26uguF(3UM*+AlK@ncjrTros09+MK_R7NgWXBd92F4lyB_AFW{u zj&XP(*VQ|z*lC{H+)S|>h+@@ACXVDp@zH$R#dVcQ5+V}@`9AJO$)-+T8u|+%f-I3RGaBzrP(bujv zd0^-HnR-W$K8VogQn$H}_c7m;m2ErXQ+-ZLWAEO}KK);#W{W86D$lg9&$K@!sOjbP zWY6U#QAw#eZ^{!WF*zh|G3FmfjznzA@3^X^Q5+=F#`vM{Yz7P`=+``dze<#{d&kh0 zxfHLAzatm(ARMxQo$fQ>prs+SPLs>N;c<$v{89B`O1GnT*-UDtl7aF~8Oy}r;9#82 zu3dj`A&+`0$vDLr47iv<>Jqj=Oeyn6G7 zjbL*!mPD33Hwh8(1}s6|?aN-(iJ{g+!vy_;_HXagcfy)NOWIhpeYfPcTjqLX$%#|9 zG`P5!tKPhQ+aD72Yjb0@Li_|@ONxj`)OLoH+U0)TBI?(3%C7vLG>0L1chixeMB@~P z-6|A6KWtax?CG09n^uc-)n`RBJ}kFNGuf{;o@tzHx{~hDQjm{=;O~I7l-4YG+1RNJ z?PBg$iijIlAb(K%CfIK&px%I4(Gk%WWS!b%8I%!kA3%44s{AV1mC*#059K}#Yg$? z;o{OwTo}XHwP(*r4MSI1H@wj~`(=8N?mE+NscqHQF&pC@9@upaxq2W8NmX`-9N4{ zERq@F2Q+m!%n-yUdH*plI;)aX)z7J{&hvIFN}vkW5M#8Gv2S-29Q`&2Y&HMmj~E!+ zM=24H+$ME>b)SK1lL1&7orP*Cwl3pHlEqWk^9Ee%y<~ZMB-NJnCt}m^pjG+4o-Ys- zjgpLmXY=xgmc(9Pt>G~Gvx^lYm6oRuuzEz5f2vv%`+8T!n{A?ul1ZDRUZL#O6ZxsN zHRSsBm2}}Pt})I}K2F2pBE9e=ys@W)gA$FBrnXCHJ%NtcB4d`}W2Xc8Ki)_=R79St z)1`DT<3UdE@$tz?VH24;&FcSAA}b{? zUv+#PC9wiF#?|$Wo$k?P_O$8yzkYjvx1iSa(^fhko+t#Y8 zTE2e$`WJTGlxw1=tUIr(E<y}d~Tp><=p03|bvkC(ZD!{KOYY5fS9eYM!Fc?+Vi+7X|H=B)ejy*~MO zr*^pg6Skk3wp532>Wv>f`J_dT#F;3#G>5af!fg>qg*O~J z`{TzC8h!qny}Grjmb2oynfDRe7ribmtwtDg|5~xq_Q;VE=WOhvA;Cq6Xjk$+ZbKQL zXp;6lv|UGAyDx=g)&~bN;?fxMjy0FrTo!)=f8iH)bk?d>tB70RT!pcWb6Ee_-)*j( z8~eAtYmW#>Rgf}qXuT=@X1uGiq$SC;An*SD`&CaJO~wb(0*nBe#_zcR8~S{@u$FuZ zEOTLrTU>1Ha1F!h{limit_7buZ&7_QzuhD=Cb#AQPf3xVLT=+~%05#Ww3>*mzzz`n zCD*S{e!t22{lo16qYW*=AtABP&rI+9+2A7k!%alZztKcl(YaBRLybwmI(mD1m0dso zN#hiZey_|QY<5&yNG(8BC$R>g{l=PoY_)sdduC^wdwQz~Cs)QsM>evyU6(I$u3fz1 zs)KP#;+C}hICJNxvF}~+)n=1J#cIJfZmg!`i9@V>II%laHMVPMq?l#-#YWp##s$xg zyyeuKcOY8h>doTT>rKwJpI_goMh2=(ry>g_#MC#u&-2b0X>z+-bFA?}ah}zc>xRSg zBKkDwtGhhLi(B6{c{ar^m3@}{>eVZ4pR(?PQJonxW)z%DX8n;-M=*+7_<5sS?752< z$0P3QDpP6){+B?WS=Yi|B zfquhnp?8$s9SUB2+)?>3NM!35DUmS6V{Zo2acV!WAVgA*Pnw*sh-@_m&IqNschwt} zZyQ~&7C@cm=Hq?BE1TDIde7ArDcf0b+5!WW?mxA2nm$(4JhB~#DBorPP$w`jG&$C; zc4x!k^D_Od{y*hOv_oarck=CR@+e1~rprcVjt{kVYJ`%BoUiW zor~+@(VySye1<*-D(J9x(I@-`{k7QA9=XP$(n&5iWsE{)_?9_(PmT{Ncz$oZbnkFR zoxE3%jkvftPGlddIs!xXC`*W_+h_s-4)wN*({;nA3D2uo&Ih7Eq z9?Xs9;a5*97)eB|R;9<+9xT15YK}yCnEa;c+P~z*OHc zaOa85Ey;t6WeaR1HTUkVdNwhT#;xX3bbc1LU&hj-&bHwCY^~`+Ll!cjdxDlHAn$3j zQuBUjT@h8g7hy?pq1Io(jy%OPP%}1M|JftyRMgCFdWSTp$+HE3IlpXpD?D-OCcCd{ zlf(O??p4}lNUmJD9a-bk6+xjtX0K3rfXrq4#~+$3^6|@@pFBr&eHBqH+RVNE7;xvE z(T=1$hrsUW%hEmToqW71#O^Ac_-nA;IoljQEyEbTrn5LSB4Fb74=&y)Br%8nukQ+4 z5oGL<{J(H>74FtmXYTMi*kPFEuB`BiAw-w;&R0J1>FlEQregFrpbpQ@nBR}hUpTxa zRNCCwqL(sF_8t75!-)%{(Se)q$Q?Wl5``R8pPo9Cdj#Qopf_M5dZkRL?WHo=xW_RK zw9-2pb^`DEjBw&Zf`b|K@~5^Xi$qj?GEIMQJ#2~4~)NA7n;kv!%X@(1p`vTyopjbK`K zaWq&qD|Vk@s>OlQu+1ij1u|xa6mKBXu4?b!^9%H@zPPm55x^UGhC)ofCbHGzL2T)w zYie>S{-ZgEi)Tk~p?L4b?F(}#WO5a>zP_=f#8YvG4=lkH1+s0opF6_iwt{4V);z&^3*Glaw zK|LA)s?gbpNnqPn0r&*l!8oWLJ9ma0oAXvQRE6%GHh5aFf=g`GsvSU4q2t-L>ANp2 zvWJ^u=@Kd2eIg5mY_MZ-JX~h#v&Vjh9CPEc*o!zyszEwSWyRHb^X3KLylJPnfT=Gj z*P_S86?eEeXk>%z{i+G$9-A||Y~SsTv4xu@`Iw(} zaB&HUt?TF)QLhm$yB=XkS4cGcC{s*LTtfwNYr|m_0OE8uu=l|8>7uu0@kLevF7QwX4xW$qw*UA@0(c-+%o)T!P-nrL)w7pPC$tfhJLh{&XVpVz z%hHV^pEoKm`+ZmaLFLOa=UDzHp2{OjfRhx8ai~d7(2L$P9CV~CJfSJqGfa>-(lC-qos;|H zl~8qxxyc-*<*v)#rdzW$19y71xQ8lxes_|a!L+Fbh;Cw3?qkJ(P9bF!!U{R$*GS(h zgQZM#`WCO(ebkT=I?J|4OZbm$sZ3YfQm;Bg0ZN?i=a(m};6S6-XB@d|S1J(vI*!s> zg}u=P(^S#(u}GoWd9$nawK~>BYp=wKW)+ly!kScMjHE%_<$GSAW`On6Vr?7!wn_TH zqrVY{#X-7AoIZP&H>>NtUhS6U^>!cKTdvC+vU?5|G5Sh3n|s+(;+FY71M-Zox-GpZ zD+t0obAbvrgaPyaRa7)k7ciLwDp<1YV}-I{>Tpg>?lHwC-|l>$6C(`4RQ|}!r$6f* z-BDy{v*1t)CqC_JYik2Ejf{Z-?Ow2SX@Ypm$@pnq4N190QFSa8|0iXV^qsVUP{QJt z28_Gcb&Y-Hmhk@-988c{Xmqu)o-ArVKQ^YpNzqa~!MQfI{)ugq0dQ zJ>~ka1EKK#DW2&gL2LKlOJ1!Jv}7;u)aSj3IZ}SFKJ!@Eo}gv%gR56p?_q~{<$PLATwxgVE5H?f9x9>f(h92mj__>Y*69c=hVw75_#YSq|_Zj9=)Rgcvgd z^_xCOXF_A3ahG+hWKmc1Qv;mBz%s?Ewx%4(b?dbB^z=}wX1xiPJgmHt8v5UmDendW zew%dJf}tH?(?V!hmTcIux!EiF<1Xs>iA#&5*~?t=R&x5kEOYzvRu9y{Wjk)6JX0QS z({JCT8JtP#^!A8tC#yh((b;LwCK6%GuUdPHU$#Giu#?1edGJA*={*^+rV3ghj`*3bMwea6x_D71WfUo7^P=Fyc{AXIoLnTt#4ZMaVS%d4Vk zKiW#PS%hW+hJ6bUdw!Oi+w`)eDRtTs#0&~HiI(2Cw>J^+1vlcIk0-$HFj&;^)37s@AW8j-0Zwbd@624oE%bHj8}6Ovqr{&p z)LKL*r4_*3Zr@Homt~!-Y&jm{)J4x7%oj^QZLr@vDb5nzX5rpZb)D7)J_raG2vj{1 z{NAF&v+y7iDk>KHw++Xj`9z~%S}a=wRteBb=+EC9t(Az%;^>FMQw6O!$*-Vlrp@Q# z-$nNENE#PBP{Q8%Y1^XR8XDRxc4cMAwQFM84aaa2>PS&jCn0|OzmqDGcmJ0#7gU*I z*U%=ow1H1hoxXVP+^F8x;?X^Ri>1wCK)r;`;uEtWFB9ry+Ohh~cjJRCvYdWL%N;vT zv)Syo=edQ1$O>V1k(pncav}TMT?Dz zIokW_1xOh=5JgkxtaannE6poQH@);!acNdL)>6=9vxW|CC292Ob5>Ld%H|aY%Bf54CQr}L&t$(s$^y0bD`f#d zj{pf`gKbbOJzT=at8QI%G8-!fpc^ooSQ!&cHS@)-(|nPcQvV~BOpdvoM4mwYdMNPg`>7b8 zfe!ok4-Xc!hFba1K@M%Y#m_YQy|+}nrEgbOM_oodO>)yF1F{34>0zW};OtE=D~M4& zY5+Y3Q(=Cq$G3{H;l5dGxj(oN`#?vSIXPp_oLaC52_WL>>`yN)Wx2L#0Z|R13rQZI zDyxp6&!4qislrpm`^O(5TU`If<4>Skow6OJ7U}H9`?qc_p|b(@{xvQtV9JYT@l)aD zb{Y1-@`+aYIW$t=`QY)ey&vZMvw|^j#7A)e1=l|jh=#+$@k@C8^Rl30W!#nT&%ndP zTd$t~FDN@Sb$)Q-Cr`GW9C?61$ch0#v;Xn=b)FTsI6qlE4*$a^!0eZomqu%atfR9) z>1BHL9zrFsVA-!gL5-#VU(D;px!;?oD@W`L;gUxGAND1KJpXWsqdFD&fh-MtlopH8 z^I>~_&tHOmUOc>8$fw8IaH&7va#shHpB37Cp)|rtl4=CUBg6N5dj;b6ToDEa3GVhn za|QK8=<{8_UnL*kljGT)8s?lsX9XiM&6vMNLQ1Lx5oGuF-v=OZ2jw8bpeC!ouUrjn zqXXyXb4dvN^ZoCFB@OmWg^!&(#py7>rv<}bmf?ICkVsC>_hKqU8N!NAx4OMX`Z?$x zMPLB}s8Xk_=eT`p{!g=kZ*>MNLfnuLws~_c7Qi>P|A^yH7^pFR!3bhsU@&H`<<`~x z=lHZ2qj$G9!cTwY%9X4bl3Bqp$sxjR{~cVYiyEMHBV9hpI^;IAYZ`y`v4<{ z8j-V+Ua!+g1_irb)2L{IddO z(Mbb~78G15*3X)qB&fwO;h9Q(+AI*#FQU<7?x;x^Jf_l_ zfBqm1;tFdJS1g){ikB{u|0>ZDit99a8D7vM8(*1#2%QA9#fkxTC(Pi6Z~>yVxC~!p zPF6qA+Zny*$`6rp@Eo}wT^kWa$cr{`QqyRXEr-8^iPQf_5YyU>O{QRng~}j-_3?IK z#mO=-5f3;VTmxwg)Bq4{fj4Ygo*gDWqWypWyq() zOPL3<8(l9QI&_Fe2ii1521AeGqoFznRMt!zfko6UTToO!{YOF2Sh6y``|PAGo>UxP z7sY<_RoZcNBF`fqlA5{=iKzzQEGDKgj+d0aB-;{$pRS%h3r(uhdy_f$m>h zpcT~GL>|x^=2Zh0It#2is_MN4aeLnZHTj7yYAfy>K=;@Z5|?VU<%93umA+aW4dnwl zQN(q9q&C0YV_ZakVpI6SKY@!%w#{x(uzR}%Eh$YjJ4hcDJe4faN@sW<8YKNS<}RFk z&t^Rbt&2esDw6cXug4`CokREO2h}DWmI=*c?I;P>8-0AteSF_$dzA8tmbs4yT9ykj zy%zH>DU>m#giKehUajEq&9tSn4=DxxB1JlTj@nq{+|_#?=#<_OmOmc(4V`n)sUy4C z+lkoaXM3Bywbi|#91G=@_P1lsHd-iX?W+zB7~46}QB!T*ooCSEKbjKNEyTZEQT9d! zSBYwW#ZFR~k*cUWV6p-AWuXholz7i(Zw(gFy(k>5P&Zh!-`F;6-<+ow!V(GFS4Q-m zMPX^T4a-d#xR(U*b&+*mtNxQKM}*!oG1}tLbpISU!u(H{XY-=(Wm9;YsCCwZk(4&e)P2)Y zowI)R&LnZw)smS@?lr7Q$c~YA&i=$^6Yx80nR4))Xx$DH0|57!h5a2#X%4Tht<0(I ztTv;Ij32+!!J23ra0rUIz3E8DDgW`IlT7_{mJcbOCv*5grJ%EI4%cJbfa5Hgj9|}Z zb2tY)pAE+W1;*dbu-mXBNdMGanDHJocOQcH+C5I%bf$*e%D%3)PpwU=bNh01Vr+Pk z#&DTn2Md1@h}dc5VN!{-5q)Z_rS{>Yf=v@60Jc03#Vap{H0^knoGrYxT~ z2o3Ia?oG=1A3YYA9O}F8wO#*Q`0`m_TOwL!N%X?Kwp*ozTFX;570vm+1N|)%aT@tn z?h3b}SurM-GADbhO?*J~&RWAYMnc_jJKkM~7VuJg?`-uwB6?Oh3{auu_n#bedLc;J`GIEW_;mci6^_`E8P^#RC9!i_0wU%- z&^<(av}^@J#I5T&uCe!cWRU}9jVJQbKQ13mr#q}V zVZsPD{r5fKD;{aDJFNVQ@2t1Vn>TMZitzLZHuG^!BT~V)0_Qnt&#%p$O6gOfIQij2 zId59q?b)teb&6qN0HH}6o5}+u5*p=t9HX;kAWQorwDd~}f3Q5hhnXSB4^fRxKDv)| z7WavW1RmDUT#Jhr1^!meVQT+#*td*gwH7KoFjy-l`06%f5QLN{lp_Ihsh(x7LrBp< z<(J;Z^hEvi`$(2h`h8eT9s(ej>T@n=TOa{9p??r%iNU3z=CgDpWg=@5;8$aQ;S0C;|+Q?-sR%(F7N4z<4TvCmYxic;h7z1W&Myj zCqeg9ueH)t{u4VM45r&9Z#YiTCtq0db%#k?0Nv++{$DY42M87Z@fehi)Z0rJFS3*C zG87EhHy)*)^;^f03EM~bDzF=N?~J%I!sB?T*ts|kA+Kq(my;H|>d*Iw-&~X5$5L}K z7`hkZ>!di|78lk(vdl$pKp=M7WGv6L@cd~ge5q5d?=(cKlMiIb7ui*Y%nr16*1siV z9~slk^1(MWkJdh0FmK+cKq;5Jr zbk}F=`n})?-km-tC@Cu8PW*|K1cjMki-|tQ485u^vZj$-I|ChJV&Zh-<204c&bGgW zu2=tZQB)^Q;nJ1rFUK0>k5)vwZM()zXhj>Up@&=DW{dZa7($S9@l2DDl%%t&;`S}e z?`LZx73mEYoE*r$CS+-sos<@1LQA>!BmYc}HrtLq87yz8Zy9ees439dY)NX}P-sMv z6wUjtaB=;)`|I!ZeQKuQVsAD`(h5rKh$M0di9DZ9J1GeU6D(Rx8y683z$ zQ?fI?N*1*}wQzm!l-S8wXA!SfU3xRKrOWt>i>Qo(<9pqcE;)4YoW@{Ik|(E~q6jXu zAqNS;Lw7$KOhn|-K5mIHTo$&1F#JTp;WO4-90EuVo?J>n!Dy@JcSAI=fg9kEhS7Uw z?cTjR0rd!==fjQ$E+Y4mW2P+PDh%&_HfeR?!UX`;O1^UY#wWeIBck`--q=x~`pdRGWO!201fgagy=lNz5=s2_=73shm zsk8^^kni?U;p6T3=j(OH0L!QH8u$d6{=;=#f>WYQ>q5|ffIP7ih<8{)i+pPI-3O;&n$Ypv(l z*XXN>(A5EjD=mX3szlgvDT=W&%E|_Y#@LM%#-ZjcD|y9QR6yTuI#|NDi5VJyZ|J?YE75T@7+bleNwy zH5p`zC8NZWvLm^hz^YH_ZtXhxkR2AZ;_)v_d!C}EavGA3MGkc9s)LPgXk6Z)5ycNl zCU~$3Py}+!V_sYz*y3x}IG`$G#h?^V2$-B86*NCdzyvCV+P%2AaAc_UsyH2Gm2HWo z*q;Q=5m>)_5P~8Hcyd82jGtH!wo_szd2X1vuKbFt8tAwZbv2ES9#>B9%Vl6bbeH`0 zJoR^eJJM0-L`e!Qn@}4EM zPB92gQYgM|bEUID5yc|66VhGcH{vK14TCTY;^@V6eb6pMkeP9cTCkKnHQuj#96B6g z<1{+F9sGDW2u9MWG5q&L-$GSgUgzrB^Wk}-d3Gw{B|v+~F-MtHp=h6%3h7oti9ua zqHNHvG&%rZ<;lUOBT93bpQZx%GArs;izhlEB&y9b|IRJGu>15cYv~i&=4Xlm`hK?; zLE_&Ym4LRL;-g5ZS@^Wkd2oyQ_m?kTaB@0RLB=xG$bl0(a|3$tt$%VNnw9{uAw)mC zAsj3OlAp9n1V00Z?ZswjG{Rybng&qH} z|F=C9+HX2iRt1r;I31Nm1&sEv(p)M46b7j=)kmP18EBcDFkvk~wR@uVHrkDjSt znlE-e8%}W;f06XtLv@AoF(E)yYcwKu%Ry=d3rQ%}se{xCb14|!V;wM_MUw>G4Q4XYR&FNSN zit83Jgb#bpQd*Y?v54jiD+b4A|Ft3t9xexhbO|AVSq|Xb3Dlv%LVMKy*(?tHDHhVI z=E0REu&j8%3%Hk

    &4%lmlsPM5rc=Y~XAW7LABhPmc71aZ!(i`A<78DnyCbnOL8U zb$K=p?H$D6Ah~Z!dvXmCV*($fl{h{+*x43p{Zr)X@-6z%t!=)=uO6B1?LEjd^nx9$ zJpicpy0sS_sF8_YFBQnZ-@JZ(9RkoM=g^{$O6_@@Cas_v-xsm%?*7?aynO$y9&}90 zH@>R+^A_S9_Z5f-B4awX@kAoU|m0B_AmYu_tkUXfeuTr8&ur=3K?gVcq^d~%X zh>kSooY(tumD)C_)xeEtZ&<@kP1eEioBca*QcXK<7R$p z8}LzpP7gfuE>;zUSR`MQjtLYwLkFOb5y%f(EhD2tlzIlMkg}}(de1@PxQ0$N#~^x( z>J_NP2ts4YFcFdf1qPOEQ{@$!`SW{I5^C&`APvZ7AO~Bzmse~F&O#7PSPc)~=l+do zC?`WwFbV~<#T^WOL5?7?b*njxF+Nb61cD5nLI$o1xv?gLy?ghbDzoi}>XfLA{D(eH zr?bIN#X;J(Oovy@6rX&l5lZ6#FC7Fa(rpuDQ|j+PK3btGm`a25lCFb*pde}YJcP|G zB9iAE2FLZC+mdlg=qs8v3ifOoV#OSl9wvl3cGzqi(zIcu>s^CyZwe4rSBGkZ^v>M- zzv|KT5p(J`E?19&*9k(2y9Wy8(!p-*Z5g+$;dE*~=~P2zHKiu(M@s9<;ft*Bs;1W8 zY?07Jr|=@9Xb1K14MHXgm?NV>moJ!|%vnY#3bS0xi1IF}NhS|=R=!uYRx<%px zh_|Z9?L72&mu4e~-;t$0aFfx%!Il8)e~{L1@#%Az!4jK{I>N1hStsc{u9Z?R&goj;c_#hIfPy&5d^sf%8 z@>8vOR%ygXfZORT2q+n&UD-s9LVM_4-bm+HPcMO}8%$7q?Y#L}KBdBKU)o;FB-m^I zxhmf(1Y?Mf8Js7jaiTwde7*I5O*HyK zDPu$6KnTGP;aFKrnD=vJG6XnT`{u@{${wH2re-w^EWWCt$5Pf@7g~OJqxi9F!Rt5% zxt0;WDv1l`Moq_%<5iU(e|FTQIDYh`BIO%EmaXs~`Xw*Ack<@}GC2k35l6E@Vh@Di zE_uD@_skZR@io3VlG`LqOR%4N&oMq`7rifBr|qU>bOI(h0qkDcWh`_#N-1fhm4vD_ z4m}WPc?*W^AY3IqSn(N`Do!0Dqbf~aMYB3uo;`C`b=OjR+H@!Je#jiU0}V>u2n(5k zvbQ+bGmK+s*k>Hs-+OKvv*os0KtY-x3PyFF>9gh0ZlxFT^Xtxp0Q7-lT8>uG{I&A6 zZEWkY<5#AJjn?Jv;3FIosg6Wbxg+JZe+vTdHoFc&Ck!Nbg@6_|kebDP#IbcUipK72 zc4qVbww2*VV+Y z_aT8ry1PK0cd*l=e-unwpi-)KLaAO(XbY$qv&Bb zK6NvC>S{|AOom{Ib`$FRSkvQuE(a{O(Gu>*WH&l@H9j>U0)B7|x~y;YS=uPo21L|A z83fOv{9j=Ac#+vEF%A25Mz(pt=3A?`vu`Md-Apr$0$VJ+ms@N}8wO&K^y>3{vuPYq zztsr#Xwd3@f^2Qo*A*fu{TKoGe8h2*wiw}L^?r*Y=+WrYe50tHm-Ch-u+lfm3sXC># z5NaHLc&txf#AKCvsP@XZqOq4NC7avWTV3*F;iBU6D<#q~FBhc;$)x^X|ylK@F z^EY17<{=ew?kgoDhU|fE(tj$C#-|wwkXozBGdY^183z|1R^C%^KhFw^1wlfIqV9xN zx$#N*$Y8e%uq^u`cI+B#?zwejL43&9sP zRpEe`Vsqv;7K;X0AR@{`dkfW8)GqhVI0deeX#rQ7QXiyRVjNe9LSv{O<<78T>`z>!?}!!Kv1Smxf8_CBRgsH+IS9~WXO9sdF{h)0hc zt_teFDs8jw<^e8l9Yn~E+Jxu^Z0z33gJm1F*iP{VCX8zO88 zm6o=2#nlyxB74|=^f`4-BfZ64d}?d;Zxi|?k>>1O#pSsOQ%wDnh6tZ&U zbdsY^9;aS(U=D&P)M<27bd}*-+3uyO&FDI8`Cv!blxre_QVeTW$^}j z0TUV9P&@ZcY{OjvME&II`UsOqQ6QuG%FwqZ`X8kK1@q@e6VbPt67$digd~oC|2Y?J z-bZy#gc(3j+C_O0^_eKApQAjg&e<*4#OMfKv}A0quo$PQ=lHSu93zNQo_&1^!pl6{ z*+^fX#kz3=Qx{Qw<&N(kMx|YrcW%7JS*Fe;DVz*;AbHXC(b(_*aAppfs8|f1dlTW#L=) zM)L~wNQf1RE1_Hc>CmD6&L9!9Pp%2K`Dz;_Is0|u-zYdeuq_Eq0@!^qGDdtKVk(HO zW01x_`yMU=C~5gwKop{;rl#q3pcH0{Zc7G}L3+=u7)&S{)>?Yrh1>TOlkXwrTWZjy z%6Eu?YccCO+H2M+-t>WyxFg?Z#IA1RvjFyOsOnJPNn)x-Qd06wX{l;=IGhG#s3h#w z#Nq^B?ssa@@!TdKgil1GHFP$zIB8sG*a@oZ0tLVL03R7Caj&)S%5nE$cUCLWZ7=o? zTe8;BeISU1Lbtyz)H;#G7q4?_H=#+uL69jPDU(!)e_ndGzwhz@5YXAMVZ%iXsRFA@ zm+}WMB5heKs2}P2_)W;ITd(p@Qly=yyVuptji@M9H=np~rhTW~Ln?8}JvwZfzhM^(!s!RAgoMFH>~Vg$du3wN6FqY4f#0>3Fhp4`jSYPH08`LAv^c3q(31 zV{gbvK;Q}(dlMi71sQ;22`#FFM_X%BIzAr%dNA8OJK^~1Ro<*^Ecu3y74x#qQ$S-Z zb16sw^EV{k7u(~dQeSW~*F_@*wPL$3W@!feY-6Ay+PjeJq8Ri(WLoC<2PTaJs@nLO z|2VQba|ehs|7)1-Mt0NObmVOXJBC(`X`L&-rgfCHlzkuVIrI@Znd0+IiK%I+B_7Pzx zjmU*b9Wp%3CB#5=7lBcP-Pjz1AMDurhxRvI$#9fT*gjh)#WtUO*YTf+P1n$Nbv0z_ zF|Mxg0S$J>-|PkSo_-CZ$lpf8`Hj1F?IJ==93#M=f$jq7!m}8~{t7zx2E%7<&K9>X z4*=;7cZKA1N;Z43YdgVyH|8nT?5$PEO2 zWitc?4S?eoV0@9>Wk3c%t}WnKK~YbJTKvM)fY$e@`u-%2d=X?wp(`fR$)qWZ#R_Jz z?tlCC4IeUNh92I5#be;OPF=rHCA%R7?3p93e_+L609Ol?2EYY%5vsPr2Ur{l=fr4% zouHd4-&zb}9_CT7`y0$z{@Mb$!yo@TXNJm>mVi3;&ZZ-?qt8&Mg&{{Pg!hoAbn$J0 zEcUan71T2@3b^gJ2j}KFVh_kbpi4>9Vk@uhDdyRVFh7|Yc%%9cpZpO}Zdm06#`%Wt znZ)aeSTD7IcmEtTQZMLSlNe&sg(4a=CK7a_U1fCV50cmzidBnA0JjxqN7rED=!a@N zYv0s3 zy8-GvGMJQ}o__J-#f|=hUXgMIBOOwhcc!yB(w_6@&p$BA8~HZ^0>1-Lo!L{@Se#l2 z<`wc+K4Da|jg32|Cr&KyWlsEd%os9$LJ$jx%^G;Rqp zgT1^N%tLuK@(+Sl1UNGtmZ1HPgH4E~Rk;j8gU{ng)4HFGtZ{Em` z+BqGHZPW01;%6hIfDv+&Sk|Lg{c zVz%OD4Froj`yciO{+heugpGLOo&*j!GzGE_Kosg6`i7YYi>8r5Gr%UaU`z|zk*XWB zonsJM7sc{xzw69dx-vL>aL1&As{bE z%};PFD+WC9SBzc7|H&-@sVMc~2obGerkZRX;tZMwcRh7XO>cp3x=+pkeFAh=!cWEY zWD~+1etLsu^gwqzI+d6$x&sVgBaNP%sRST(Brq4Qc`AO3a5r$Yk^z2ckW4&oijWnP9_{m)=9Z zXfGxyV`OD@kK9}U9hByO&k)N&3`cPl;{F+|582`L z0pfH#WHrj{Iz*ua(1A>@q-*4=Htt5K)5zuloV6^t*OG)_aX&hmOuc(_)q~743!gVkhn)i} z4xlTf#Uj0ZG8~A|!8|~&lvouwNA%~h?p&ZAZHL;k|k?W!a!-+h}m=c zU$2cg3Na^3r=?FE&IoT&SSCPmV`PicV!nO57X>;gZD7N=0O5;wJ0#cu#8xC4Bfo=~ zz}+Vz{u9GTRL6RX2t#O${}3qr-P z=E;%TXEZvnS|v{LKp+ow1aeMw$&Wb2%Kd7?Z(hNw07;M>Ne%!cF?;MJ8CZ1iScTY4 zWQp{{#ahZIHAX|N{SRQMZED?uj7aBR4>3LlkDf z1fxa8n3lE&FF_RSG)c@2cs8C0e72fLy#ni^7@%LJaa#>~YG%*;PZl(co(~KheLUEO zUZeH*&*PY(A_Y|!s;ZClHM0(Q5)yx38*k6ghb z;@KDlo;PC9;`jA6Xm5Z*z=ajBP+MP{1Bd*u9Nfqh908_5ce+JK=ZGNCh@oLHDiik? z3r!?et-5cTs%le6Ay#O?x$}@5tk;(h`$7o`^S>nT_;Mz>MaSr_j=M+h!nT2RTKXdN zC{`nDBkfpd@H)wAPSv!l8Y{x~WjA?*tyr;f7j9HQX-0aY3MiK8@fug=&7Z$;=~7PU z7)6F%aC;AAO!}B~LCDK=s9uL}?#Ock%D~gaLoANql>{)kJEsPeCz(2<$9IQq00_r8 z-zWV~5k+7hK!pga*d@8lOs%C4RYAMdYIG)Zzy2(M^;aOmln-a19)d;cpp!1^T7zDh z$()~^@rg2_(B$RhyeelDSkTMqcf=CVoi{6R2)Uzp%UIeMj0kNb+kI4XvDNe5WfMp?(>(GIm# z%p{P1`IpJZqdJmA*D6g@SpV`;!4hdn+?AMyv5u0#mUi=CDl+rO;2jlQ=k@iirlwx9 zWv=nzmzVW0f8JdlxA#uW&)I>~7Mm2Va@D+p+*h1xIRf>@%y=$lA-GCviQ7-JYxm!y z^dwXLATk{=$35~nqg=kKYxbYk<8-PbGPD8mF#)`$X=Q)Ad=^JB2&enS1GQQLfdHERPYY4D=@ZoKU#713sKNoo*bwq zw>=Fs-`|~6-evss&|9wr=TO5^PSs!M1gF05IojTZf0FBVAO&7LHcEgy;5Fc2jrSz3 z@iBnLDnsx5X6^trN|%L^9IB8%yFofI+RJ(VP?f=c$qg&FPq&mQ`R-$- zYppqw5d&250KFpgjhH8h=5UFg1$qUKU0PBVSL`n&{fp6tTGZ`JOS!01V5}*ApQZ6S z38$yH+BcIw6)=HubT-AmfH+EpTU#67xBD+Q4XT%ylx(`gLvf?oLJ9T1Ie$*F7@Vh) zTiA;X&n|8z8x#OO3Ob#dgGX$FPAwnqazx8*?@Nlwgsy|)%?D;X8eP0Plp{8*Io{=n z0^z@2B$Qu6>pNo%247#7fcpSQxx$g4$dnbujI2e2vCc^`WrGM!G+}n&{TvSk5v+ym z9@c^@tjYigd3+owaawzELSB)(_PPwF3;u- zH?d|SjbzS?MrQZ%u34YoI?%zhb7>yy(=o+!hRF{?t-W993jDeZQ2hcs+r_%cwQ`^E zH%7-|p4tdmPK#BV-LsKIn685uHdPVoRZ1%ymzN|s8V2u}Bf{Po`hVtqRd?6B{i=5p zH@`gCE*JFZ&Q9R!Xoe1Usl5a zI#7XuK{X6m!fvVgnzi-KMd$iyCJvW6lWP8%PO`F|I}7OgnZRXm++unm9v&WsaX=@_ zfgNrG9CQROA_!e9U+E(H`IE_^r$P0ep}UaOp)@}=$Uva;M;FM7@IhX9w7bmys+;s>?vkB+?P0s_?pl-P z%PVi{1*|1F7RxaNfR2xHSXm6*f&*GHS{zsDy8HXPsVb&Czy?L!yjLDvQ=d$mqL~Ri zPAg=#ulk)l&r7D^u}eWCN4@6vG=L)kucCoz5!l>jm=Xo-FWLY5u^2S(3T&6G_4T|s zv6+1;aPtDNVRZr6u*$sX6bMYykX^5LZZk9J2?8U40eB?x4OVV24NTZTFnTod=n2wP cJT3e4e~E)Lzopr0Io*@?*IS* diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_layout_attribute.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_layout_attribute.png index c074d6298e391a5875a827bf43f9d7a9e1b8eb36..ed7d14a4f881140a91d880d4c49847dcee35f2b3 100644 GIT binary patch literal 18111 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 F{{ygKr8)or literal 8845 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 Ib4q9e0FPl{r~m)} literal 23715 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 cJT3e4e~E)Lzopr0Io*@?*IS* diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png new file mode 100644 index 0000000000000000000000000000000000000000..f8183bf82dc24f85a5cf4f094489bdab98bedfbd GIT binary patch literal 19296 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 literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index ad7a64dab..b80776d3d 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -94,7 +94,6 @@ def test_edit_children(self): graph_artist = ax.get_children()[0] dots = graph_artist.get_vertices() dots.set_facecolor("blue") - dots.radius *= 0.5 @image_comparison(baseline_images=["graph_basic"], remove_text=True) def test_gh_587(self): From de52768804f3af27face29120b2e8d59d75164b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 14:02:21 +0000 Subject: [PATCH 1285/1892] build(deps): bump pypa/cibuildwheel from 2.12.3 to 2.13.0 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.12.3 to 2.13.0. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.12.3...v2.13.0) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 36babc937..93d6d40fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -242,7 +242,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.12.3 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From d1e21a0b188a44c3d618f1c10c288394c242b420 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 31 May 2023 21:17:19 +1000 Subject: [PATCH 1286/1892] Update edges upon vertex size change --- src/igraph/drawing/matplotlib/edge.py | 2 +- src/igraph/drawing/matplotlib/graph.py | 106 +++++++++++++----- src/igraph/drawing/matplotlib/polygon.py | 2 +- src/igraph/drawing/matplotlib/vertex.py | 84 +++++++++++++- .../test_graph/graph_edit_children.png | Bin 22431 -> 22535 bytes tests/drawing/matplotlib/test_graph.py | 3 +- 6 files changed, 165 insertions(+), 32 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index f557964af..d54bb0935 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -13,7 +13,7 @@ FakeModule, ) -__all__ = ("MatplotlibEdgeDrawer",) +__all__ = ("MatplotlibEdgeDrawer", "EdgeCollection") mpl, plt = find_matplotlib() try: diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index ea09440f5..cc693de37 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -23,18 +23,16 @@ from .edge import MatplotlibEdgeDrawer, EdgeCollection from .polygon import HullCollection from .utils import find_matplotlib -from .vertex import MatplotlibVertexDrawer +from .vertex import MatplotlibVertexDrawer, VertexCollection __all__ = ("MatplotlibGraphDrawer",) mpl, plt = find_matplotlib() try: Artist = mpl.artist.Artist - PatchCollection = mpl.collections.PatchCollection IdentityTransform = mpl.transforms.IdentityTransform except AttributeError: Artist = FakeModule - PatchCollection = FakeModule IdentityTransform = FakeModule ##################################################################### @@ -158,8 +156,8 @@ def __init__( ): super().__init__() self.graph = graph - self.vertex_drawer_factory = vertex_drawer_factory - self.edge_drawer_factory = edge_drawer_factory + self._vertex_drawer_factory = vertex_drawer_factory + self._edge_drawer_factory = edge_drawer_factory self.kwds = kwds self.kwds["mark_groups"] = mark_groups self.kwds["palette"] = palette @@ -262,7 +260,7 @@ def get_datalim(self): mins = np.min(layout, axis=0).astype(float) maxs = np.max(layout, axis=0).astype(float) - # NOTE: unlike other Collections, the vertices are a vanilla class: + # NOTE: unlike other Collections, the vertices are basically a # PatchCollection with an offset transform using transData. Therefore, # care should be taken if one wants to include it here if self._vertices is not None: @@ -298,8 +296,10 @@ def _draw_vertex_labels(self): kwds = self.kwds layout = self.kwds["layout"] - vertex_builder = self.vertex_builder - vertex_order = self.vertex_order + vertex_builder = self._vertex_builder + vertex_order = self._vertex_order + + self._vertex_labels = [] # Construct the iterator that we will use to draw the vertex labels if vertex_order is None: @@ -351,10 +351,12 @@ def _draw_vertex_labels(self): def _draw_edge_labels(self): graph = self.graph kwds = self.kwds - vertex_builder = self.vertex_builder - edge_builder = self.edge_builder - edge_drawer = self.edge_drawer - edge_order = self.edge_order or range(self.graph.ecount()) + vertex_builder = self._vertex_builder + edge_builder = self._edge_builder + edge_drawer = self._edge_drawer + edge_order = self._edge_order or range(self.graph.ecount()) + + self._edge_labels = [] labels = kwds.get("edge_label", None) if labels is None: @@ -404,7 +406,7 @@ def _draw_edge_labels(self): zorder=3, **text_kwds, ) - self._vertex_labels.append(art) + self._edge_labels.append(art) def _draw_groups(self): """Draw the highlighted vertex groups, if requested""" @@ -418,7 +420,7 @@ def _draw_groups(self): kwds = self.kwds palette = self.kwds["palette"] layout = self.kwds["layout"] - vertex_builder = self.vertex_builder + vertex_builder = self._vertex_builder # Figure out what to do with mark_groups in order to be able to # iterate over it and get memberlist-color pairs @@ -506,9 +508,9 @@ def _draw_vertices(self): """Draw the vertices""" graph = self.graph layout = self.kwds["layout"] - vertex_drawer = self.vertex_drawer - vertex_builder = self.vertex_builder - vertex_order = self.vertex_order + vertex_drawer = self._vertex_drawer + vertex_builder = self._vertex_builder + vertex_order = self._vertex_order vs = graph.vs if vertex_order is None: @@ -525,7 +527,8 @@ def _draw_vertices(self): art = vertex_drawer.draw(visual_vertex, vertex, coords) patches.append(art) offsets.append(list(coords)) - art = PatchCollection( + + art = VertexCollection( patches, offsets=offsets, offset_transform=self.axes.transData, @@ -537,10 +540,10 @@ def _draw_vertices(self): def _draw_edges(self): """Draw the edges""" graph = self.graph - vertex_builder = self.vertex_builder - edge_drawer = self.edge_drawer - edge_builder = self.edge_builder - edge_order = self.edge_order + vertex_builder = self._vertex_builder + edge_drawer = self._edge_drawer + edge_builder = self._edge_builder + edge_order = self._edge_order es = graph.es if edge_order is None: @@ -606,18 +609,24 @@ def _reprocess(self): kwds = self.kwds # Construct the vertex, edge and label drawers - self.vertex_drawer = self.vertex_drawer_factory(self.axes, palette, layout) - self.edge_drawer = self.edge_drawer_factory(self.axes, palette) + if not hasattr(self, "_vertex_drawer"): + self._vertex_drawer = self._vertex_drawer_factory(self.axes, palette, layout) + if not hasattr(self, "_edge_drawer"): + self._edge_drawer = self._edge_drawer_factory(self.axes, palette) # Construct the visual vertex/edge builders based on the specifications # provided by the vertex_drawer and the edge_drawer - self.vertex_builder = self.vertex_drawer.VisualVertexBuilder(graph.vs, kwds) - self.edge_builder = self.edge_drawer.VisualEdgeBuilder(graph.es, kwds) + if not hasattr(self, "_vertex_builder"): + self._vertex_builder = self._vertex_drawer.VisualVertexBuilder( + graph.vs, kwds) + if not hasattr(self, "_edge_builder"): + self._edge_builder = self._edge_drawer.VisualEdgeBuilder( + graph.es, kwds) # Determine the order in which we will draw the vertices and edges # These methods come from AbstractGraphDrawer - self.vertex_order = self._determine_vertex_order(graph, kwds) - self.edge_order = self._determine_edge_order(graph, kwds) + self._vertex_order = self._determine_vertex_order(graph, kwds) + self._edge_order = self._determine_edge_order(graph, kwds) self._draw_groups() self._draw_vertices() @@ -625,6 +634,47 @@ def _reprocess(self): self._draw_vertex_labels() self._draw_edge_labels() + # When the vertices change size, one has to redraw the edges to match + # the boundary of the marker. Unless one has granular control over exactly + # what edges to redraw, it's simpler to just redraw the whole thing. That + # requires adapting the vertex_builder (already done in VertexCollection) + # and then redrawing the container artist. + def vertex_size_callback(artist): + sizes = artist.get_sizes() + for size, vb in zip(sizes, self._vertex_builder): + vb.size = size + self._reprocess() + + # Callbacks for other vertex properties, to ensure they are in sync + # with vertex_builder. + # NOTE: no need to reprocess here because it does not affect other + # parts of the container artist (e.g. edges) + def stale_callback(artist): + # If the stale state emerges from other properties, we can salvage + # the other artists but we have to update the vertex builder anyway + # in case a _reprocess is triggered by something else. + prop_pairs = ( + ("edgecolor", "frame_color"), + ("facecolor", "color"), + ("linewidth", "frame_width"), + ("zorder", "zorder"), + ("sizes", "size"), + ) + for mpl_prop, ig_prop in prop_pairs: + values = getattr(artist, "get_" + mpl_prop)() + try: + iter(values) + except TypeError: + values = [values] * len(artist.get_paths()) + for value, visual_vertex in zip(values, self._vertex_builder): + setattr(visual_vertex, ig_prop, value) + + # If the size is stale, one needs to redraw everything + if artist._stale_size: + self._reprocess() + + self._vertices._stale_callback_post = stale_callback + # Forward mpl properties to children # TODO sort out all of the things that need to be forwarded for child in self.get_children(): diff --git a/src/igraph/drawing/matplotlib/polygon.py b/src/igraph/drawing/matplotlib/polygon.py index c014e9b22..b68438ada 100644 --- a/src/igraph/drawing/matplotlib/polygon.py +++ b/src/igraph/drawing/matplotlib/polygon.py @@ -12,7 +12,7 @@ try: PathCollection = mpl.collections.PathCollection except AttributeError: - PatchCollection = FakeModule + PathCollection = FakeModule class HullCollection(PathCollection): diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py index e93e31949..89c874d4a 100644 --- a/src/igraph/drawing/matplotlib/vertex.py +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -13,11 +13,13 @@ mpl, _ = find_matplotlib() try: IdentityTransform = mpl.transforms.IdentityTransform + PatchCollection = mpl.collections.PatchCollection except AttributeError: IdentityTransform = FakeModule + PatchCollection = FakeModule -__all__ = ("MatplotlibVertexDrawer",) +__all__ = ("MatplotlibVertexDrawer", "VertexCollection") class MatplotlibVertexDrawer(AbstractVertexDrawer): @@ -80,3 +82,83 @@ def draw(self, visual_vertex, vertex, coords): transform=IdentityTransform(), ) return art + + +class VertexCollection(PatchCollection): + """Collection of vertex patches for plotting. + + This class takes additional keyword arguments compared to PatchCollection: + + @param vertex_builder: A list of vertex builders to construct the visual + vertices. This is updated if the size of the vertices is changed. + @param size_callback: A function to be triggered after vertex sizes are + changed. Typically this redraws the edges. + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._stale_size = False + + def get_sizes(self): + """Same as get_size.""" + return self.get_size() + + def get_size(self): + """Get vertex sizes. + + If width and height are unequal, get the largest of the two. + + @return: A list of vertex sizes. + """ + import numpy as np + + sizes = [] + for path in self.get_paths(): + bbox = path.get_extents() + mins, maxs = bbox.min, bbox.max + width, height = maxs - mins + size = max(width, height) + sizes.append(size) + return np.array(sizes) + + def set_sizes(self, sizes): + """Set vertex sizes. + + This rescales the current vertex symbol/path linearly, using this + value as the largest of width and height. + + @param sizes: A sequence of vertex sizes or a single size. + """ + paths = self._paths + try: + iter(sizes) + except TypeError: + sizes = [sizes] * len(paths) + + sizes = list(sizes) + current_sizes = self.get_sizes() + for path, cursize in zip(paths, current_sizes): + # Circular use of sizes + size = sizes.pop(0) + sizes.append(size) + # Rescale the path for this vertex + path.vertices *= size / cursize + + self._stale_size = True + self.stale = True + + def set_size(self, size): + """Set vertex size, the same for all vertices. + + @param size: A single vertex size. + """ + self.set_sizes([size] * len(self.get_paths())) + + @property + def stale(self): + return super().stale + + @stale.setter + def stale(self, val): + PatchCollection.stale.fset(self, val) + if val and hasattr(self, "_stale_callback_post"): + self._stale_callback_post(self) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png index 14a9122d80c3d75900e9c77d4a09d04e540763f2..eedbdeb3e6e6a0125b4bb38c61b00824d6ae87e4 100644 GIT binary patch literal 22535 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%0AL z>@j}_C*BKImZU2!6k~lc0X#}6-On;6j=k+*dcZIc=M)a%P82fF&em+z1Qmse7A9_| z7O&bt)WT;b?`Xz@r5bw!DW~)+CD!NuC6gWucD{_3@5)Y3`K}-7t&{@NkFRD1o!WkI2|5JdHxJy%xCzaRa5lF8n zfWsx8K&E$zpmf9Tzw#2GS^zoK_wci!%WX4>vjg`FI+!*uX;|kkVLImuGH;F4?dZee z7d|CwP9n1}L8N`*s(cHCZT)`I3-HwOt@(?2vc9xnU-CM%4j04`3$5B_cbD%@Ed^fC zck=6RrhdGIOPDTve%_I+ID?jLdFe_Fdr9v-lIqTL_) z{?X@{y8LcX;lHki64#_K_Q=du`#V-rtY0+s%8(W~Wo||98n2M3j*c}4{w{D%#)+idLNOqr}7&p1}WsKO3`ATgS_ws&F~k)LYjsu=?SdUQKs# zGlqaPRaUtH3e<~>Tkh;<`S!?X`?7Fljf;R$4n&DQ8EQnAvA<(*Zl!D1*_9m~9S^vcXg~jjpIh^{D331vhzYof{>apuZInKkBbM)w?P`O+zH=w>o9WMXAvw+E2 z!2X7T4rAK+50?RA-XGcYp6@n4<1S$^sJ0MDCjA>5Yo15<}y5)8J*@-~q z8jH((2Tfbw-gHI(kivPX`{9apJ2sndrq-jqRL_LT9@8^hUtf55#kKH6!My{Q!CeP~ z?Ce5eD!?6n==rA`|7T_pgyU>9>1tmyYku{FGSaHg9i^hAwoUwZcSzT4!K8XnQ#&>w?9!1px7t# zK@fzb9fMbjxsKJDayBLN#635v-o!Mw%wUDw(d<3TIYe8bSDgA}*ET5S!!CLn=Z3k$ zK{TBEM{-C-t#yd7@NrhkX3sH(0o)XXcJNwHyDDjKBj5@kK>Bl7YVL?Pq72&U10DtO z3_s@?2aL??EQe{T+v^_pAK?$o!B|VY_z=?A&ygG;|G)qKdoMYP+W0_L=^*-hF2{z~ zz`d+{F$P2i2a#>M?P|j>muQ0w>YL_wKGP8=mo!Lay&&({8YQUjJ#m_&b)!~xik5A8znMA|A)!2~p!Tpl?9E_J!!XZCg2yWY`_2}Ei zuSPd&5Sh(-UVeOsN&T)dpCYM;IpMCGH%Tq~;*j!o$xC1RwH~w8`KNb=1c%mSI9hGr zxa)=l=C?QO7P8gQ?oj3rBv^s07UN-rL4q3rUe#bvr$&1AW6-CuNxS|C(N)b)ea@#4 z6(w|3q4|n5am+_27+d8{@)a!xNczDoso%Z&Om91Oy*66Q@po&cD9f)~<)1 zC6PNl+6F?zq*(o_4u;hZ9z00=77#rpHS|8Lklb)66T4h9rkAzq0^7$Sqjq>5J-iiskl5nfEp3#j#Tz8trxeR9+@TEhu#NrEdRn_bs<_Ph1FpoAy--+CAD z7W*uka>AfvzIE#sqTCXk?$>YO7?^@QZlHGS7@`ZF;@Th{Y^X$WZj~o~u>(_HO3ZvF zyYK{QP&w&lTAw=a(#$4&ymurAg=|cjGRUunqpDh;uo3ITjg`-rH_GAw`&EzWRz*vV`J$!{)^}@8POEY2pbwt>0RN`A3F8z46FfqsJKJkr|Q9vZ|DkyEr zq>Nk#4<`6xg5l1At;vPbNCJ<+1i@92zBkSE4ALVfKzmif{Jlto3zzzku1-r>fwlU+ zyfk|LY*jcF`2+3FAh+4@V2h8KZvvhI0@`$G^!q^&ZjQEmg7P9KUiy-eDMEUHy_;+r z&*MOj)#AkW2%Q1cB(q(x>YXlQy|o)NEg;u@AEU}a%(}lRmn_ILnqGxz4U(X-ixkpe z$%O9{J0pWvntZ{S?!jOw&K&%wgih|IQI;-Dp?yHnkAp)dJG4o&zL<0+APCyIK(2r< z-;3J&-|y(a4RD|bupku4ZO9qTJXKRqjqZQ~H3pFD3I4U7#5-l1@f1qKHM>NhZX41~cs3Hmw2kg5f`o0j(y5HeOh zN)1nrp`Q(dPOb~H%ty!sI{*V}q6aA88KCu@#I$%ROq=rLM8@_t0&3An2Mdn?P(oKD zT0J<>QBBRa;KVQyI?U3A`_rPL&{KCK1K0##ct)2QN4ZZ45@`>jJ%xxdFsDZ}rwQnr z;%yfAEugvt!7m`$5i%U51fVM*CJE^SkZYg7mnk*G?-lFCuOgl@S<|TkHfZ((h*N{f zWTwjlP)ev{MAI#eQAf+lCjq<0U*v%_%}**u{57_?Vu3LN)wW*IJ?GdIuhw$hyI%Eo zgnl_b``;q8WxueYOW*G2VBC@Rp)zg23mkeBfR!J z+3=r-t_es1k0wp_&mJbAxfEs=axZrDSE#Iq431=1f=5s*qvFC;`7I6HBlf;!E5=e5 zKfv)4-()|!P!!RG>ImSiZ*rWQnS^M*-|xbC+emm76|HL18%)XSj3PrJ52Zt8W83H8s2ucc6L4JAtEk;_FSx-aBB=O*SaSr zGWb zVeix9&j|O{XsfM}4o{BW6?m9mH^rEGUg?=XR6228>E?Cf09?sul<*8ZY6*=*&x}PL z5)b2L_pw38p0o_E`|(j5PQ%u>PcLN@|u~Tz&H`=EJeSXzv`w2}0C@aX|)}5Z(%aA)pZ8 z8wy4ZigB!*@ifgoa{2yex~bRKOPu{%Q}e(-#lf-vQ5>wilXmG6ATt?+q=2|3_0TT3 z3QA)YCY)dbBca|g2Y(l{!(@OQ@e#=Uf8c)x+HuxRZX>Hg4II`ZuP$lH$e$HOZNP#< zSQsZyxC?|2T)CG7G|b=rXN0eTb3|@;doPrLatZS}!?1XU0dxfJK)fLiS6-NUPk4jj zUVwL%XB&0%Tqo74Wijk^%%mN~u#HQz8yWbY>++am_5>ENo1Y!eW>KQO1cr+~zZLt0 zuZ)2o4ivIFUNXeDXjE@N$Xo;0`>>?)B$5Wvc^8BT)Hfq=k`PNw@Dd`C#_mzrXY`>% zz;DlRiexDJo$}}B2EeVirA*S`XT`VJgdq{!A|T+6e$R*4BOAe64@Wd-BP$WKOj@bi zL`2#Fxe|Nd(SmGX*}MeD!UzS0gj&Iq@^JgZ#gGAxeVrcb{=m}~)gEz}KTN?*1|_GW zV5DqlYh9{to^1z9mx-xq&ETE=@A^ObaLZq^##;z%F_hSA{frcdm^xVFiL6J|=IG@` zN5BJUFH=!a{!Wi}T~$Z=+S8ta%zXdsge1~hAtV#~q3mShZIs3PK}<0t}}}>E+06~PPpc*-l6gyjJQFHIP(v2`Ovx*3`ypxBuGx}eOl$LMUsz-0cOuPvM0!W+Mg zEZIR7v#`iNdgmM8eM)C(t|eG}>liZ6!EoCyLX&NO)xv1#JgT*w;W@Kjf8i*tpuFIH zI43**YR=l&l}NQa7M6#%3JCG0@@i?p8|d7sysHTl2!|ud9gT>WHNzNWiO_r71g?DZ z*J%Zi>oc|mlzSne67f0V{n{<*s$M5N?|UKE?R5Jj!XiKNep${HUM+d@eG1fHKsvt9 zEknVx|2`3D0c4Oo86oTFXYA69h-!<_I3#iMFL7$F%ByO|mJ(^{xA!Hxnv-(=!U(f) zj~Xp#5(X8$48bX-b{EDfTmvI!ch@}F$K)s7x$YM_hAh4I$p9xBEB#sBk9^iG@--R% z?A-fI-3zsaPIKb=nzL2yD3KFDVrrZP{X`S0L;@%Rej%=p+9WO~hh*}P2}PjrkKn|V z;P966c5T^2@WP2N9)4;}Te??sO}+xt)Z5dw<~7%yAzT|g!KSKVLe69>X>}n9AA|{z zSb~@i6S#k070v{+-*dk9oPU2RG+2J!wKuOQO#5=IS^CJ`Z~F9u3l4iiQAdzGv#QzP z*K2atW})>%8oOUTCvv#`YhFIO(jWWP>q2S@(efdW{Xt&2 z1E~jXttQ0tkhvhKL*xCW#~F^OYSHiVejjt6z0xz_HhR8?$4{p1N$m~I{467-rQgaw zJ#!xJ%OK6)yN76WAAC#D9^`T~XQ_QpMo|l(BtmS6J%l%v^eQ`yh46L8&9yMQ&b(P( z;Zq{)_F>Xdm%_PN4oEBf;wN45`XM6UpwT~JV}mYzdWSdMI9yUgkwp66U}8GbFdyn= zOfxzdZl^uf(SD~UTT)CtVgq@((n_LM1FfEf*9C${5@qI?5h{jd*5LjW{J$j*G%bk{vzEdQ|3;_+Ik9qetP z+D4VgFn^Wc1x;u`;-y{?Uk(A-454}sGWD$4&pdTq!t3Mg^l+f(T^AdfW(XAZ~;ndfAVgi#i@&={+#`*$ASU4dT~-?|a+D{-%f{Hy4rD zh}}H>;7EB0CdbIU>F*`TqEq$`6DF2e;?eNH{qEI~3vcNnr!8)Xx}>KmU0B^T?z7Q_ za!<3Hi%Pg1^~p=f_RxO>>(QcfcMS}cPbzJF&HV6+dE1r;hbr&Qv~uMCLEd;p9!`^Q z22JtD`*JTGUcuFVp`+lfj;~#{Y&93O0?<%WHG;`I61LBLOmf;G;2jKtFVIUJnyKED zatu^Pr_sneAs_BnrfIIipmWtXE?L{w`gA$&fuxL%f>YAc;Uj@j0~1m6oFdpL9_SFM zT8EH8GaVbG=E4sT**{o8eXv8=r(wy;%<;Tw#+W*jS z?#~Yfe1fTfQ&cTFri@gZ&-gw3rfoEs%Jn62^h|$2o#}ZX7)#`Hl)YQ}#-ai!x zr36(=1Lt&CL-TF%?AT*%k>cgS_ED7uD+{Cx>J+Efdt92aDfi}eBWE99b{vRBrO^8e_iI z;epBnb`NCVPn^gTTbje1vrO(zU||K8b|UTM!25?YU{4%s_tVD6dv!GX@PehwL>{$t zys^YP%9XL;byik;Xz+*C@0eN(4xO}d*i)pdn|QMXsy__ErtG^i@r~6(S%iH#c_U&m z3F`^ZkY33)0u%xZm^6h;C+g&dqoEuCRA=~1FYU*d0KDD_ntTC8#b#3%Wx4{nj=T#r t`y_ca=>NSF^#9&}`v1dgV&@c1V Date: Thu, 1 Jun 2023 11:48:04 +1000 Subject: [PATCH 1287/1892] New vertex sizes in docs, remaining bug with loops --- doc/examples_sphinx-gallery/articulation_points.py | 2 +- doc/examples_sphinx-gallery/betweenness.py | 2 +- doc/examples_sphinx-gallery/bipartite_matching.py | 2 +- .../bipartite_matching_maxflow.py | 2 +- doc/examples_sphinx-gallery/bridges.py | 4 ++-- doc/examples_sphinx-gallery/cluster_contraction.py | 8 ++++---- doc/examples_sphinx-gallery/configuration.py | 2 +- doc/examples_sphinx-gallery/connected_components.py | 2 +- doc/examples_sphinx-gallery/delaunay-triangulation.py | 4 ++-- doc/examples_sphinx-gallery/erdos_renyi.py | 4 ++-- doc/examples_sphinx-gallery/isomorphism.py | 2 +- doc/examples_sphinx-gallery/online_user_actions.py | 2 +- doc/examples_sphinx-gallery/quickstart.py | 2 +- doc/examples_sphinx-gallery/simplify.py | 2 +- doc/examples_sphinx-gallery/topological_sort.py | 2 +- doc/examples_sphinx-gallery/visual_style.py | 2 +- doc/examples_sphinx-gallery/visualize_cliques.py | 2 ++ doc/examples_sphinx-gallery/visualize_communities.py | 2 +- src/igraph/drawing/matplotlib/edge.py | 1 + src/igraph/drawing/matplotlib/graph.py | 9 ++++++--- 20 files changed, 32 insertions(+), 26 deletions(-) diff --git a/doc/examples_sphinx-gallery/articulation_points.py b/doc/examples_sphinx-gallery/articulation_points.py index 2b92b3704..89fb3f197 100644 --- a/doc/examples_sphinx-gallery/articulation_points.py +++ b/doc/examples_sphinx-gallery/articulation_points.py @@ -27,7 +27,7 @@ ig.plot( g, target=ax, - vertex_size=0.3, + vertex_size=30, vertex_color="lightblue", vertex_label=range(g.vcount()), vertex_frame_color = ["red" if v in articulation_points else "black" for v in g.vs], diff --git a/doc/examples_sphinx-gallery/betweenness.py b/doc/examples_sphinx-gallery/betweenness.py index a9e568e70..3e2e644a6 100644 --- a/doc/examples_sphinx-gallery/betweenness.py +++ b/doc/examples_sphinx-gallery/betweenness.py @@ -45,7 +45,7 @@ def plot_betweenness(g, vertex_betweenness, edge_betweenness, ax, cax1, cax2): # Plot graph g.vs["color"] = [cmap1(betweenness) for betweenness in scaled_vertex_betweenness] - g.vs["size"] = ig.rescale(vertex_betweenness, (0.1, 0.5)) + g.vs["size"] = ig.rescale(vertex_betweenness, (10, 50)) g.es["color"] = [cmap2(betweenness) for betweenness in scaled_edge_betweenness] g.es["width"] = ig.rescale(edge_betweenness, (0.5, 1.0)) ig.plot( diff --git a/doc/examples_sphinx-gallery/bipartite_matching.py b/doc/examples_sphinx-gallery/bipartite_matching.py index dd7885b07..ad7538fa2 100644 --- a/doc/examples_sphinx-gallery/bipartite_matching.py +++ b/doc/examples_sphinx-gallery/bipartite_matching.py @@ -45,7 +45,7 @@ g, target=ax, layout=g.layout_bipartite(), - vertex_size=0.4, + vertex_size=30, vertex_label=range(g.vcount()), vertex_color="lightblue", edge_width=[3 if e.target == matching.match_of(e.source) else 1.0 for e in g.es], diff --git a/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py b/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py index 6164e0e47..28b06e0b7 100644 --- a/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py +++ b/doc/examples_sphinx-gallery/bipartite_matching_maxflow.py @@ -59,7 +59,7 @@ g, target=ax, layout=layout, - vertex_size=0.4, + vertex_size=30, vertex_label=range(g.vcount()), vertex_color=["lightblue" if i < 9 else "orange" for i in range(11)], edge_width=[1.0 + flow.flow[i] for i in range(g.ecount())] diff --git a/doc/examples_sphinx-gallery/bridges.py b/doc/examples_sphinx-gallery/bridges.py index ba821e88b..fb55c0b42 100644 --- a/doc/examples_sphinx-gallery/bridges.py +++ b/doc/examples_sphinx-gallery/bridges.py @@ -35,7 +35,7 @@ ig.plot( g, target=ax, - vertex_size=0.3, + vertex_size=30, vertex_color="lightblue", vertex_label=range(g.vcount()) ) @@ -69,7 +69,7 @@ ig.plot( g, target=ax, - vertex_size=0.3, + vertex_size=30, vertex_color="lightblue", vertex_label=range(g.vcount()), edge_background="#FFF0", # transparent background color diff --git a/doc/examples_sphinx-gallery/cluster_contraction.py b/doc/examples_sphinx-gallery/cluster_contraction.py index f39e71d5d..aa7cf38a7 100644 --- a/doc/examples_sphinx-gallery/cluster_contraction.py +++ b/doc/examples_sphinx-gallery/cluster_contraction.py @@ -55,7 +55,7 @@ target=ax1, mark_groups=True, palette=palette1, - vertex_size=0.1, + vertex_size=15, edge_width=0.5, ) fig1.set_size_inches(20, 20) @@ -67,8 +67,8 @@ # for each node in the original graph: layout = g.layout_kamada_kawai() g.vs["x"], g.vs["y"] = list(zip(*layout)) -g.vs["size"] = 1 -g.es["size"] = 1 +g.vs["size"] = 15 +g.es["size"] = 15 # %% # Then we can generate the cluster graph that compresses each community into a @@ -114,7 +114,7 @@ target=ax2, palette=palette1, # set a minimum size on vertex_size, otherwise vertices are too small - vertex_size=[max(0.2, size / 20) for size in cluster_graph.vs["size"]], + vertex_size=[max(20, size) for size in cluster_graph.vs["size"]], edge_color=g.es["color"], edge_width=0.8, ) diff --git a/doc/examples_sphinx-gallery/configuration.py b/doc/examples_sphinx-gallery/configuration.py index fb0c07483..ab408886d 100644 --- a/doc/examples_sphinx-gallery/configuration.py +++ b/doc/examples_sphinx-gallery/configuration.py @@ -40,7 +40,7 @@ # %% # Finally, we can plot the graph. You will notice that even though we did not # create a dedicated figure and axes, matplotlib is now used by default: -ig.plot(g, vertex_color=colors, vertex_size=1, edge_width=0.3) +ig.plot(g, vertex_color=colors, vertex_size=15, edge_width=0.3) plt.show() # %% diff --git a/doc/examples_sphinx-gallery/connected_components.py b/doc/examples_sphinx-gallery/connected_components.py index e85869cd5..008f66cec 100644 --- a/doc/examples_sphinx-gallery/connected_components.py +++ b/doc/examples_sphinx-gallery/connected_components.py @@ -30,7 +30,7 @@ components, target=ax, palette=ig.RainbowPalette(), - vertex_size=0.07, + vertex_size=7, vertex_color=list(map(int, ig.rescale(components.membership, (0, 200), clamp=True))), edge_width=0.7 ) diff --git a/doc/examples_sphinx-gallery/delaunay-triangulation.py b/doc/examples_sphinx-gallery/delaunay-triangulation.py index 8f95b6e75..ba6ce5a85 100644 --- a/doc/examples_sphinx-gallery/delaunay-triangulation.py +++ b/doc/examples_sphinx-gallery/delaunay-triangulation.py @@ -56,7 +56,7 @@ g, layout=layout, target=ax, - vertex_size=0.04, + vertex_size=4, vertex_color="lightblue", edge_width=0.8 ) @@ -90,7 +90,7 @@ g, layout=layout, target=ax, - vertex_size=0.0, + vertex_size=0, edge_width=0.2, edge_color="white", ) diff --git a/doc/examples_sphinx-gallery/erdos_renyi.py b/doc/examples_sphinx-gallery/erdos_renyi.py index cb3ddf530..c4f2879f7 100644 --- a/doc/examples_sphinx-gallery/erdos_renyi.py +++ b/doc/examples_sphinx-gallery/erdos_renyi.py @@ -67,14 +67,14 @@ target=axs[1, 0], layout="circle", vertex_color="lightblue", - vertex_size=0.15 + vertex_size=15 ) ig.plot( g4, target=axs[1, 1], layout="circle", vertex_color="lightblue", - vertex_size=0.15 + vertex_size=15 ) axs[1, 0].set_ylabel('N. edges') plt.show() diff --git a/doc/examples_sphinx-gallery/isomorphism.py b/doc/examples_sphinx-gallery/isomorphism.py index dd1e130b8..668b43f16 100644 --- a/doc/examples_sphinx-gallery/isomorphism.py +++ b/doc/examples_sphinx-gallery/isomorphism.py @@ -44,7 +44,7 @@ visual_style = { "vertex_color": "lightblue", "vertex_label": [0, 1, 2, 3, 4], - "vertex_size": 0.4, + "vertex_size": 25, } fig, axs = plt.subplots(1, 3) diff --git a/doc/examples_sphinx-gallery/online_user_actions.py b/doc/examples_sphinx-gallery/online_user_actions.py index 8ad9142d6..969a65b7a 100644 --- a/doc/examples_sphinx-gallery/online_user_actions.py +++ b/doc/examples_sphinx-gallery/online_user_actions.py @@ -70,7 +70,7 @@ # %% # Then we can prepare vertex sizes based on their closeness to other vertices vertex_size = g.closeness() -vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] +vertex_size = [10 * v**2 if not np.isnan(v) else 10 for v in vertex_size] # %% # Finally, we can plot the graph: diff --git a/doc/examples_sphinx-gallery/quickstart.py b/doc/examples_sphinx-gallery/quickstart.py index 8fcefb43e..ec6f7ddb7 100644 --- a/doc/examples_sphinx-gallery/quickstart.py +++ b/doc/examples_sphinx-gallery/quickstart.py @@ -40,7 +40,7 @@ g, target=ax, layout="circle", # print nodes in a circular layout - vertex_size=0.1, + vertex_size=30, vertex_color=["steelblue" if gender == "M" else "salmon" for gender in g.vs["gender"]], vertex_frame_width=4.0, vertex_frame_color="white", diff --git a/doc/examples_sphinx-gallery/simplify.py b/doc/examples_sphinx-gallery/simplify.py index 6d626fc71..46b753a82 100644 --- a/doc/examples_sphinx-gallery/simplify.py +++ b/doc/examples_sphinx-gallery/simplify.py @@ -39,7 +39,7 @@ # choose a consistent visual style: visual_style = { "vertex_color": "lightblue", - "vertex_size": 0.4, + "vertex_size": 20, "vertex_label": [0, 1, 2, 3, 4], } diff --git a/doc/examples_sphinx-gallery/topological_sort.py b/doc/examples_sphinx-gallery/topological_sort.py index 04971131b..7699b54b1 100644 --- a/doc/examples_sphinx-gallery/topological_sort.py +++ b/doc/examples_sphinx-gallery/topological_sort.py @@ -52,7 +52,7 @@ g, target=ax, layout='kk', - vertex_size=0.3, + vertex_size=25, edge_width=4, vertex_label=range(g.vcount()), vertex_color="white", diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py index 04f899ef8..803ed115d 100644 --- a/doc/examples_sphinx-gallery/visual_style.py +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -15,7 +15,7 @@ # various setting we want to customize: visual_style = { "edge_width": 0.3, - "vertex_size": 1.5, + "vertex_size": 15, "palette": "heat", "layout": "fruchterman_reingold" } diff --git a/doc/examples_sphinx-gallery/visualize_cliques.py b/doc/examples_sphinx-gallery/visualize_cliques.py index 44f0ff713..3fee6fb06 100644 --- a/doc/examples_sphinx-gallery/visualize_cliques.py +++ b/doc/examples_sphinx-gallery/visualize_cliques.py @@ -28,6 +28,7 @@ ig.plot( ig.VertexCover(g, [clique]), mark_groups=True, palette=ig.RainbowPalette(), + vetex_size=5, edge_width=0.5, target=ax, ) @@ -59,6 +60,7 @@ ig.VertexCover(g, [clique]), mark_groups=True, palette=ig.RainbowPalette(), + vetex_size=5, target=ax, ) plt.axis('off') diff --git a/doc/examples_sphinx-gallery/visualize_communities.py b/doc/examples_sphinx-gallery/visualize_communities.py index 7cfd90746..df19ebf5e 100644 --- a/doc/examples_sphinx-gallery/visualize_communities.py +++ b/doc/examples_sphinx-gallery/visualize_communities.py @@ -40,7 +40,7 @@ palette=palette, edge_width=1, target=ax, - vertex_size=0.3, + vertex_size=20, ) # Create a custom color legend diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index d54bb0935..c6d64e265 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -250,6 +250,7 @@ def __init__(self, *args, **kwargs): self._directed = kwargs.pop("directed", False) self._arrow_sizes = kwargs.pop("arrow_sizes", 0) self._arrow_widths = kwargs.pop("arrow_widths", 0) + self._curved = kwargs.pop("curved", None) super().__init__(*args, **kwargs) self._paths_original = deepcopy(self._paths) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index cc693de37..1283571f5 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -30,10 +30,10 @@ mpl, plt = find_matplotlib() try: Artist = mpl.artist.Artist - IdentityTransform = mpl.transforms.IdentityTransform + Affine2D = mpl.transforms.Affine2D except AttributeError: Artist = FakeModule - IdentityTransform = FakeModule + Affine2D = FakeModule ##################################################################### @@ -533,8 +533,8 @@ def _draw_vertices(self): offsets=offsets, offset_transform=self.axes.transData, match_original=True, + transform=Affine2D(), ) - art.set_transform(IdentityTransform()) self._vertices = art def _draw_edges(self): @@ -565,6 +565,7 @@ def _draw_edges(self): edgepatches = [] arrow_sizes = [] arrow_widths = [] + curved = [] for edge, visual_edge in edge_coord_iter: edge_vertices = [vertex_builder[v] for v in edge.tuple] edge_vertex_sizes = [] @@ -579,6 +580,7 @@ def _draw_edges(self): vertex_sizes.append(edge_vertex_sizes) arrow_sizes.append(visual_edge.arrow_size) arrow_widths.append(visual_edge.arrow_width) + curved.append(visual_edge.curved) art = EdgeCollection( edgepatches, @@ -586,6 +588,7 @@ def _draw_edges(self): directed=directed, arrow_sizes=arrow_sizes, arrow_widths=arrow_widths, + curved=curved, transform=self.axes.transData, ) self._edges = art From b148b5587f49a7bd76c8891c25ec0cd55c265704 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 1 Jun 2023 15:37:29 +1000 Subject: [PATCH 1288/1892] Solve bug with loops and curved edges and add test --- src/igraph/drawing/matplotlib/edge.py | 438 +++++++++--------- src/igraph/drawing/matplotlib/graph.py | 21 +- .../test_graph/clustering_directed.png | Bin 36495 -> 36628 bytes .../test_graph/clustering_directed_large.png | Bin 62421 -> 62446 bytes .../test_graph/graph_directed.png | Bin 23740 -> 23948 bytes .../graph_directed_curved_loops.png | Bin 0 -> 23883 bytes .../test_graph/graph_mark_groups_directed.png | Bin 23740 -> 23948 bytes .../graph_mark_groups_squares_directed.png | Bin 19296 -> 19476 bytes tests/drawing/matplotlib/test_graph.py | 11 + 9 files changed, 230 insertions(+), 240 deletions(-) create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index c6d64e265..f485f0143 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -61,257 +61,249 @@ class VisualEdgeBuilder(AttributeCollectorBase): return VisualEdgeBuilder - def draw_directed_edge(self, edge, src_vertex, dest_vertex): - if src_vertex == dest_vertex: - return self.draw_loop_edge(edge, src_vertex) - - ax = self.context - (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - (x_src, y_src), (x_dest, y_dest) = src_vertex.position, dest_vertex.position - - # Draw the edge - path = {"vertices": [], "codes": []} - path["vertices"].append([x1, y1]) - path["codes"].append("MOVETO") - - if edge.curved: - # Calculate the curve - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge.curved) - - # Coordinates of the control points of the Bezier curve - xc1, yc1 = aux1 - xc2, yc2 = aux2 - - # Determine where the edge intersects the circumference of the - # vertex shape: Tip of the arrow - ## FIXME - #x2, y2 = intersect_bezier_curve_and_circle( - # x_src, y_src, xc1, yc1, xc2, yc2, x_dest, y_dest, dest_vertex.size / 2.0 - #) - x2, y2 = x_dest, y_dest - - # Calculate the arrow head coordinates - angle = atan2(y_dest - y2, x_dest - x2) # navid - arrow_size = 15.0 * edge.arrow_size - arrow_width = 10.0 / edge.arrow_width - aux_points = [ - ( - x2 - arrow_size * cos(angle - pi / arrow_width), - y2 - arrow_size * sin(angle - pi / arrow_width), - ), - ( - x2 - arrow_size * cos(angle + pi / arrow_width), - y2 - arrow_size * sin(angle + pi / arrow_width), - ), - ] - - # Midpoint of the base of the arrow triangle - x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( - aux_points[0][1] + aux_points[1][1] - ) / 2.0 - - # Vector representing the base of the arrow triangle - x_arrow_base_vec, y_arrow_base_vec = ( - aux_points[0][0] - aux_points[1][0] - ), (aux_points[0][1] - aux_points[1][1]) - - # Recalculate the curve such that it lands on the base of the arrow triangle - aux1, aux2 = get_bezier_control_points_for_curved_edge(x_src, y_src, x_arrow_mid, y_arrow_mid, edge.curved) - - # Offset the second control point (aux2) such that it falls precisely - # on the normal to the arrow base vector. Strictly speaking, - # offset_length is the offset length divided by the length of the - # arrow base vector. - offset_length = (x_arrow_mid - aux2[0]) * x_arrow_base_vec + ( - y_arrow_mid - aux2[1] - ) * y_arrow_base_vec - offset_length /= ( - euclidean_distance(0, 0, x_arrow_base_vec, y_arrow_base_vec) ** 2 - ) - - aux2 = ( - aux2[0] + x_arrow_base_vec * offset_length, - aux2[1] + y_arrow_base_vec * offset_length, - ) - - # Draw the curve from the first vertex to the midpoint of the base - # of the arrow head - path["vertices"].append(aux1) - path["vertices"].append(aux2) - path["vertices"].append([x_arrow_mid, y_arrow_mid]) - path["codes"].extend(["CURVE4"] * 3) - - else: - path["vertices"].append(dest_vertex.position) - path["codes"].append("LINETO") - - # Add arrowhead in the path, the exact positions are recomputed within - # EdgeCollection before each draw so they don't matter here. The - # path for an arrowhead is: headbase (current), headleft, tip, - # headright, headbase, so we need to add 4 (degenerate) vertices. - # Assuming the arrowhead uses straight lines, they are all LINETO - path["vertices"].extend([path["vertices"][-1] for x in range(4)]) - path["codes"].extend(["LINETO" for x in range(4)]) - - # Draw the edge - arrowpatch = mpl.patches.PathPatch( - mpl.path.Path( - path["vertices"], - codes=[getattr(mpl.path.Path, x) for x in path["codes"]], - ), + def build_patch(self, edge, src_vertex, dest_vertex): + art = mpl.patches.PathPatch( + mpl.path.Path([[0, 0]]), edgecolor=edge.color, - facecolor=edge.color, + facecolor=edge.color if src_vertex != dest_vertex else "none", linewidth=edge.width, zorder=edge.zorder, clip_on=True, ) - - return arrowpatch - - def draw_loop_edge(self, edge, vertex): - """Draws a loop edge. - - The default implementation draws a small circle. - - @param edge: the edge to be drawn. Visual properties of the edge - are defined by the attributes of this object. - @param vertex: the vertex to which the edge is attached. Visual - properties are given again as attributes. - """ - ax = self.context - radius = vertex.size * 1.5 - center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0 - center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0 - art = mpl.patches.Arc( - (center_x, center_y), - radius / 2.0, - radius / 2.0, - theta1=0, - theta2=360.0, - linewidth=edge.width, - facecolor="none", - edgecolor=edge.color, - zorder=edge.zorder, - clip_on=True, - ) return art - def draw_undirected_edge(self, edge, src_vertex, dest_vertex): - """Draws an undirected edge. - - The default implementation of this method draws undirected edges - as straight lines. Loop edges are drawn as small circles. - - @param edge: the edge to be drawn. Visual properties of the edge - are defined by the attributes of this object. - @param src_vertex: the source vertex. Visual properties are given - again as attributes. - @param dest_vertex: the target vertex. Visual properties are given - again as attributes. - """ - if src_vertex == dest_vertex: - return self.draw_loop_edge(edge, src_vertex) - - ax = self.context - - path = {"vertices": [], "codes": []} - path["vertices"].append(src_vertex.position) - path["codes"].append("MOVETO") - - if edge.curved: - (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, edge.curved) - path["vertices"].append(aux1) - path["vertices"].append(aux2) - path["vertices"].append(dest_vertex.position) - path["codes"].extend(["CURVE4"] * 3) - else: - path["vertices"].append(dest_vertex.position) - path["codes"].append("LINETO") + # The following two methods are replaced by dummy functions, the rest is + # taken care of in EdgeCollection for efficiency + def draw_directed_edge(self, edge, src_vertex, dest_vertex): + return self.build_patch(edge) - art = mpl.patches.PathPatch( - mpl.path.Path( - path["vertices"], - codes=[getattr(mpl.path.Path, x) for x in path["codes"]], - ), - edgecolor=edge.color, - facecolor="none", - linewidth=edge.width, - zorder=edge.zorder, - clip_on=True, - ) - return art + def draw_undirected_edge(self, edge, src_vertex, dest_vertex): + return self.build_patch(edge) class EdgeCollection(PatchCollection): def __init__(self, *args, **kwargs): kwargs["match_original"] = True - self._vertex_sizes = kwargs.pop("vertex_sizes", None) + self._visual_vertices = kwargs.pop("visual_vertices", None) self._directed = kwargs.pop("directed", False) self._arrow_sizes = kwargs.pop("arrow_sizes", 0) self._arrow_widths = kwargs.pop("arrow_widths", 0) self._curved = kwargs.pop("curved", None) super().__init__(*args, **kwargs) - self._paths_original = deepcopy(self._paths) - def _update_paths(self): - paths_original = self._paths_original - vertex_sizes = self._vertex_sizes - trans = self.axes.transData.transform - trans_inv = self.axes.transData.inverted().transform + @staticmethod + def _get_edge_vertex_sizes(edge_vertices): + sizes = [] + for visual_vertex in edge_vertices: + if visual_vertex.size is not None: + sizes.append(visual_vertex.size) + else: + sizes.append(max(visual_vertex.width, visual_vertex.height)) + return sizes + + def _compute_paths(self, transform=None): + import numpy as np + + visual_vertices = self._visual_vertices + if transform is None: + transform = self.get_transform() + trans = transform.transform + trans_inv = transform.inverted().transform # Get actual coordinates of the vertex border (rough) - for i, (path_orig, sizes) in enumerate(zip(paths_original, vertex_sizes)): - self._paths[i] = path = deepcopy(path_orig) - coords = path_orig.vertices + paths = [] + for i, edge_vertices in enumerate(visual_vertices): + coords = np.vstack( + [ + edge_vertices[0].position, + edge_vertices[1].position, + ] + ) coordst = trans(coords) - self._update_path_edge_start(path, coords, coordst, sizes[0], trans, trans_inv) - if self._directed: - self._update_path_edge_end_directed( - path, coords, coordst, sizes[1], trans, trans_inv, - self._arrow_sizes[i], self._arrow_widths[i], + sizes = self._get_edge_vertex_sizes(edge_vertices) + if self._curved is not None: + curved = self._curved[i] + else: + curved = False + + # Loops require special attention, discard any previous calculations + if edge_vertices[0] == edge_vertices[1]: + path = self._compute_path_loop( + coordst[0], + sizes[0], + trans_inv, + ) + + elif self._directed: + path = self._compute_path_directed( + coordst, + sizes, + trans_inv, + curved, + self._arrow_sizes[i], + self._arrow_widths[i], ) else: - self._update_path_edge_end_undirected( - path, coords, coordst, sizes[1], trans, trans_inv, + path = self._compute_path_undirected( + coordst, + sizes, + trans_inv, + curved, ) - def _update_path_edge_start(self, path, coords, coordst, size, trans, trans_inv): - theta = atan2(*((coordst[1] - coordst[0])[::-1])) - voff = 0 * coordst[0] - voff[:] = [cos(theta), sin(theta)] - voff *= size / 2 - start = trans_inv(trans(coords[0]) + voff) - path.vertices[0] = start + paths.append(path) + return paths + + def _compute_path_loop(self, coordt, size, trans_inv): + # Make arc (class method) + path = mpl.path.Path.arc(-90, 180) + vertices = path.vertices.copy() + codes = path.codes + + # Rescale to be as large as the vertex + vertices *= size / 2 + # Center top right + vertices += size / 2 + # Offset to place and transform to data coordinates + vertices = trans_inv(coordt + vertices) + + path = mpl.path.Path( + vertices, codes=codes, + ) + return path + + def _compute_path_undirected(self, coordst, sizes, trans_inv, curved): + path = {"vertices": [], "codes": []} + path["codes"].append("MOVETO") + if not curved: + path["codes"].append("LINETO") + + # Start + theta = atan2(*((coordst[1] - coordst[0])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[0] / 2 + path["vertices"].append(coordst[0] + voff) + + # End + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[1] / 2 + path["vertices"].append(coordst[1] - voff) + else: + path["codes"].extend(["CURVE4"] * 3) + + aux1, aux2 = get_bezier_control_points_for_curved_edge( + *coordst.ravel(), + curved, + ) + + # Start + theta = atan2(*((aux1 - coordst[0])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[0] / 2 + path["vertices"].append(coordst[0] + voff) + + # Bezier + path["vertices"].append(aux1) + path["vertices"].append(aux2) - def _update_path_edge_end_undirected( - elf, path, coords, coordst, size, trans, trans_inv, + # End + theta = atan2(*((coordst[1] - aux2)[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[1] / 2 + path["vertices"].append(coordst[1] - voff) + + path = mpl.path.Path( + path["vertices"], + codes=[getattr(mpl.path.Path, x) for x in path["codes"]], + ) + path.vertices = trans_inv(path.vertices) + return path + + def _compute_path_directed( + self, coordst, sizes, trans_inv, curved, arrow_size, arrow_width ): - theta = atan2(*((coordst[-2] - coordst[-1])[::-1])) - voff = 0 * coordst[0] - voff[:] = [cos(theta), sin(theta)] - voff *= size / 2 - end = trans_inv(trans(coords[-1]) + voff) - path.vertices[-1] = end - - def _update_path_edge_end_directed( - self, path, coords, coordst, size, trans, trans_inv, - arrow_size, arrow_width): - # The path for arrows is start-headmid-headleft-tip-headright-headmid - # So, tip is the 3rd-to-last and headmid the last - theta = atan2(*((coordst[-6] - coordst[-3])[::-1])) - voff_unity = 0 * coordst[0] - voff_unity[:] = [cos(theta), sin(theta)] - voff = voff_unity * size / 2 - voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] - - tip = trans_inv(trans(coords[-3]) + voff) - headbase = trans_inv(trans(tip) + arrow_size * voff_unity) - headleft = trans_inv(trans(headbase) + 0.5 * arrow_width * voff_unity_90) - headright = trans_inv(trans(headbase) - 0.5 * arrow_width * voff_unity_90) - path.vertices[-5:] = [headbase, headleft, tip, headright, headbase] + path = {"vertices": [], "codes": []} + path["codes"].append("MOVETO") + if not curved: + path["codes"].extend(["LINETO"] * 5) + + # Start + theta = atan2(*((coordst[1] - coordst[0])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[0] / 2 + path["vertices"].append(coordst[0] + voff) + + # End with arrow (base-left-top-right-base) + theta = atan2(*((coordst[1] - coordst[0])[::-1])) + voff_unity = 0 * coordst[0] + voff_unity[:] = [cos(theta), sin(theta)] + voff = voff_unity * sizes[1] / 2 + tip = coordst[1] - voff + + voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] + headbase = tip - arrow_size * voff_unity + headleft = headbase + 0.5 * arrow_width * voff_unity_90 + headright = headbase - 0.5 * arrow_width * voff_unity_90 + path["vertices"].extend( + [ + headbase, + headleft, + tip, + headright, + headbase, + ] + ) + else: + # Bezier + aux1, aux2 = get_bezier_control_points_for_curved_edge( + *coordst.ravel(), + curved, + ) + + # Start + theta = atan2(*((aux1 - coordst[0])[::-1])) + voff = 0 * coordst[0] + voff[:] = [cos(theta), sin(theta)] + voff *= sizes[0] / 2 + start = coordst[0] + voff + + # End with arrow (base-left-top-right-base) + theta = atan2(*((coordst[1] - aux2)[::-1])) + voff_unity = 0 * coordst[0] + voff_unity[:] = [cos(theta), sin(theta)] + voff = voff_unity * sizes[1] / 2 + tip = coordst[1] - voff + + voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] + headbase = tip - arrow_size * voff_unity + headleft = headbase + 0.5 * arrow_width * voff_unity_90 + headright = headbase - 0.5 * arrow_width * voff_unity_90 + + # This is a dirty trick to make the facecolor work + # without making a separate Patch, which would be a little messy + path["codes"].extend(["CURVE4"] * 6 + ["LINETO"] * 4) + path["vertices"].extend([ + headbase, aux2, aux1, + start, aux1, aux2, + headbase, + headleft, + tip, + headright, + headbase, + ]) + + path = mpl.path.Path( + path["vertices"], + codes=[getattr(mpl.path.Path, x) for x in path["codes"]], + ) + path.vertices = trans_inv(path.vertices) + return path def draw(self, renderer): - if self._vertex_sizes is not None: - self._update_paths() + if self._visual_vertices is not None: + self._paths = self._compute_paths() return super().draw(renderer) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 1283571f5..4508fff45 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -554,37 +554,24 @@ def _draw_edges(self): edge_coord_iter = ((es[i], edge_builder[i]) for i in edge_order) directed = graph.is_directed() - if directed: - # Arrows and the likes - drawer_method = edge_drawer.draw_directed_edge - else: - # Lines - drawer_method = edge_drawer.draw_undirected_edge - vertex_sizes = [] + visual_vertices = [] edgepatches = [] arrow_sizes = [] arrow_widths = [] curved = [] for edge, visual_edge in edge_coord_iter: edge_vertices = [vertex_builder[v] for v in edge.tuple] - edge_vertex_sizes = [] - for visual_vertex in edge_vertices: - if visual_vertex.size is not None: - edge_vertex_sizes.append(visual_vertex.size) - else: - edge_vertex_sizes.append( - max(visual_vertex.width, visual_vertex.height)) - art = drawer_method(visual_edge, *edge_vertices) + art = edge_drawer.build_patch(visual_edge, *edge_vertices) edgepatches.append(art) - vertex_sizes.append(edge_vertex_sizes) + visual_vertices.append(edge_vertices) arrow_sizes.append(visual_edge.arrow_size) arrow_widths.append(visual_edge.arrow_width) curved.append(visual_edge.curved) art = EdgeCollection( edgepatches, - vertex_sizes=vertex_sizes, + visual_vertices=visual_vertices, directed=directed, arrow_sizes=arrow_sizes, arrow_widths=arrow_widths, diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index 195b0f379f299c97eef8f1455538eac3fa9bbfef..a50e0e8a68c1981445081258be4b2f0ed4cf2c28 100644 GIT binary patch literal 36628 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 xi9&^2$K#?A|U_( literal 36495 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ⅈ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 MhMIiAwflkp1D<^8i2wiq diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png index ed3c2dd1a223a05a0a29f8d7c22888fa1dc15d27..9a8da6e28a8e55f9b23179f4f2258cddc8e0e972 100644 GIT binary patch literal 62446 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 ~;;^^d5Y(AL_0mUy-C_ODGT*U4|u<*yahse*v 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

    }O`wpYJ2qIF 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 JiWRJ${SW^{U!(v4 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed.png index 89d646b0fcd215ab38e93cc6c0fe6887806e4f89..e4800a3e0da0987575ca8c577748348b3c179417 100644 GIT binary patch literal 23948 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 ZKC#W>Ugg4^C}0X<@O1TaS?83{1OQ@QUZem3 literal 23740 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 Ib4q9e0FPl{r~m)} diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png new file mode 100644 index 0000000000000000000000000000000000000000..e572fa7bc4600268ede2ecfe814ae4a44e87d06b GIT binary patch literal 23883 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 Da5`{Q literal 0 HcmV?d00001 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png index 89d646b0fcd215ab38e93cc6c0fe6887806e4f89..e4800a3e0da0987575ca8c577748348b3c179417 100644 GIT binary patch literal 23948 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 ZKC#W>Ugg4^C}0X<@O1TaS?83{1OQ@QUZem3 literal 23740 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 Ib4q9e0FPl{r~m)} diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png index f8183bf82dc24f85a5cf4f094489bdab98bedfbd..4655ce1c18d701edc6f0e9554ad003658186b9eb 100644 GIT binary patch literal 19476 zcmeIac{r8d`!;-U6pctJ^H@TtP$EMr>!r zC@Q18)l-8D!=M)N-1j3tsiVg!8h&gS<{-akIP>t4-`<@)hZeF7gtW+RwbYFs?{K~<59C~DJM2Kljc z7L5Zx{x^IWVxx^4HSL`kA5&0PuJ!LN+BdkEYB`LE)?+mk`RATFdp0}Z_knry=ezdQ zXETNMxv01I*`IzW4lLjodG_pCeV$i*jSNkXC8)jME|AOJ8dhAb z#pwZZ1+aZT|V)5?-~^x?mcuQ(8%c2 zr%#_QF`2h6U7EX4R`#x2Lk=@x&#Nof)mKnlGs$ID-wqYjrf%Jp>OOb={DPvxGE0_h znl^13dBlbdXHL!*OYZCQ6p)+BU>PtdD&S@7lTgd8Ta#|xlAbqjUQ$+;1@~-G&m)2B z)`c*c%u7*Gsh>aZ#_Py0S@QbnX&PlnR?ng5?aj5enLAHpKHlQskX~PJd$rDR{d#$M zc{={XqiS0o9iJyEy8qKtiXyYduwLcc7q?;K#;`vttFMp1x(!c z#scow5>Ip88SQkCp-@(P>wK5%{;x2Ckqz|4%P>D{rtiDhi@eNSxek)L~u ze!Nul`*PWOu7E)NyLiLyNZ0f&W#MAR*Lf+EljW`MjUp7aQgn7`ZH8m7cSrM^Xf1mO z2~pA1ygUsVjX44WHR<+R0&?y#FJErJqHX>4TgEWlV)yRd7t@V5ZK{rs(5cVor0LDr zJ_P~0dvI_tIXU@&=72|UQ;~88@2puhSl6%{rEP6(^Z5C9G_mC5SFEr?Twp=mYbug5 zGOYLRy;C)zvQ}R|QdEMev5B8iLE>BaL(d^gD=Xm?k%bEvj{I(q#i+!^(?deI+Qh?e zt_>X-y&0UDnRzGR&1Gwcq?Jv+Z6Qq!Db^~tZ{N=DTSvXsBr$R`J>5jnI$h051A)>g zK2n$CW|z2j0+Ts!&g0xG0?YQkz9umJyhD*+Qd}J4#vpBYX7NT!kJ3VDy?pg5+C=E^ z;SR??zk0$F&2J|pII$SCsO3%iB;?cW3tY%F2ANjGXrJb#bV4Z_gEBKWZ^Ie>9)_JY*wb*;usDYq7bh7eq-rqnyCOK!Tf3jevgVhhTFQR)H0%={vBrAV zq*xbd?^(TQQK?O%5uLszLR_0?wt%{vp24{VH}TM%A9%SRc)32Af-@EA3+Bz8ONMvm%$drc6}l?)kuu$JDcs|Rd;W`WTWBpI0OFS0e*p`xb*Q(g z=f}wT^L(>}mOsVRY}&NHcFm!_*+Bd=r%%7DO|uKj5EGMNs_l5p^tu`epY7i7nN z#!g&%()u=mesRflAu5v436&kW4cUH!E{XmcAEQ}~cZ@}zm6eICJjW}hY2j9%waja0 z*2z*go3Msd%;cTX(Eu48Vf(|4KKDQD_xt{^U6!s=*mn&3#l86V-l~058D9~tEa^~Q z39CJOZhP?>Iy)!L7S(9^G4lMm(ZWTGgcU_G#ObqUseA3bwr6y>f26-mV&0rNx8%+5 zEMBzeYhInbe@`}UK7z3>p^wy+jPF^;W2(a0lD2<#=#w3Td=wwgY%$G*d5TsG9uaH= z#yu?5QBZh^rCW1+s#k|Zc=uqPW8H%a9oNDb4X<1755EXXb1|#|d~ugWH9YmOCrm=e zA8PF>+*KBi^#E#*40b0X76s%^s`$5stsHo*TCpI*qp;tg(XTsg9S@a(1gJM7DLws= z=0L{%`;|R6gY63r`DpGbw9arC-N7&SrF>;`b(N{ETVZkQNs$5FiJ!Woho`Vouxy^k zetr8uvIWpTIeEkPpp88>DOaoH+sc|OW@d%tHu-Hd)gHXmKQhvtQP&$h;g7-AVHV>~ zANuyb)q85$$yp*F9hysmgJm?3F{*EGoPTlA`nW&%YKmNJK&7uX*0}LdgBuyA9)n_e zX^75t`*8o6yhgar)mED|Yt{gC&wEw*9yoBnKG(zJ(^JNS+~y!V)7AYU{UiC^=~X?s z%_bq#JyAfr3s3l9cb%5lNbbRQ6XZ{BZbfC~H+jyhk$SK}uxzXchntQVM(B>`^^erM zX4FWG_iG-_yATJLo}R{m&!-d=6~k)6n9Mn2qdzNvn!LQ$J9pmV z7hQXD<`x^9Yo`S`mD-DjnyLV{E`{Q{L51H7f0|$f3o(KqtPvaIW{)WEI z$Z>OhYJiuY$}66VErZ-_Tlc58B*Rer$W!0I!5ZuC^n&lw`qZ^>iq~nd7Mk0)MIv}KbNck@=Xiuxx<`F4=+%+t(n|r$ z@I67&<|Beoq) zmD8uPrXx(wK4|E%&33trnD+9@OioEbZUJ(EuPumpDyHduw?4~x7pRfW#OT2ML^Z#@+jX6fW~ z7jdQ$vrFbPbEERR*zo~5%-UICh*|^Et%ZYw`$sj0|2zD=H@OV*bCi?&K!-%jZ9(O2 zcYptE7vW!i=$no9aLe&^JPbjANM8r*D5rvwlDd@!p=lrwd49D{z}{#t%x-@50|<~yc_iu;{%ETe3>XdErpzj~W9ur+p_*j1Bk>CQXW-BbiR z3{u!tlQMtbG)m|Dd!C0Kx6Tf{UCW#4H?1WBftj_hLL9LLD)RYz?n!J*tto~>-y4mi z1Q}b4N4gZheEz(E|3K@B`3malmw9NOW;}o`x8~wTUrkGp=@t9mxBMDG{41_nwUxvq zVO58}@2^atQhxzz73Jg%4;9!my&p}PzgS5r40m|U!^f&vH3>tVGs6*Q`RoLEeCn(N z`JpnJn)RT%zBfFIe;XWZf1@t_89UwD&rg$|gJe2JEFjFbB&f*T^ILuPt1p9(9z6nL zBYh+Tf)<&~WX%uw(~}#ix-Xnxsy+H}%<|>S5m@C03`*zCBm$iZ`}Aoi@@~bK!5uqx zoQa57`Mvp6M1-}kZywgQ&+@FGQf1VtgXa=k#(w3N)O>z%@icCrj~je_enBQVHC63< zGcarmcJ!<6Cr_S4&mKE__N@6N{Pf9{89aa39+QHk#V18Yo}*}m+wAS5tx|1va2amh zdfmm<6%h%h2(l*hXqj){_VMjh-1@QRiLu!G4<6uAav`|p^`qn5mL!s%WbS-6T}&t7 z{g**R@6sIeg>rJPpdX@wQ{!rs913kdeE3k>YZ`ADQCpp4j&!*b8?jJ~#$ofVJvMlS ziI9qdf*HxT7u);2J1d`o5TF`~)d|!X;AJc<{_|a{JVv|W)Oo_eu{D5KxmcjxU~&iZ zcLWS})sR5?@E{T3wQSikE^aELAC;0TzzAWxNJfugm4j?R;3>_n{ntow;2+KCNAFNE zTwFATA@E@Li#g>{tEx_&Klo;q;q~j+aZ#JJ9z*c6r$!d4uw5reeRX4{$Dt!d<$J5J z0RZm_39>%l-oHZ_#O)Ckk=hp)b%kGQU(As^AoXhyZQ;~33TgrJ#Di}?6%`ad8WLmV#6_4w3&Wn(^l)=Jsg5;~)Kb^9A~jB!;RsCih% ziO|q)@TL71+RJ*IOB}IDN~f14Tc%hzI`;k;0UO4Y`~CX%;$|@A$qWxW4_;;eU~joJ zw&$~HYiP0#mHnzLVN7`Bs)KiaeQ)d@7(|7P@<>6a`1ivs{~>qe5zLyUrRBq-;={d7 zlOzuWw)R^E7nQei|NEuDyv3@j=GocVrPrk%?5kLWo3CTA<~RoQpZM|fXBcNnxTS?f zbprLj^oDyojyH63&s?ybO(ryby1ey&a#E3UnE9Vy%d4`St1Rs7QrHoRmHqbNK@D%%_r3?+H_ z3y2x;#i(Pu>eB6%n*{(BDA9a796^HYemK%Fq4;<1^7-T3yuuOP(c1nwkDokA6X#`2 z%bTW6sWpWZTYPQeyuYcENBv`nj%SM=cD6aDTIp8>?~EC$v&S~l>F*G>zrRkQbZ$Y- zz_3)`*lG?|n_rHOF7IvAqa^h>7&WvXU>aR0M!gE`ljTADE?v9k^s$70{`|7?vsBBI zmoHzc`E*&x=$owiGPnG?YA6qFRFpP{N}YWkWqIu8#UUq8c4bwWs9I@&w!KCuwCoF? zF9jexbL!MR-{n-=34xloUBa<{nzr%t^GD)E(u;oCq8thtrYPM@=g-GYnIX7%`EoPn z0OChpQE?+TuXq;wLh5K;eMxW$N_>yO1r)$TK?Y4Wi7sJnYQLRv0KN#2(A`?lhYv(bV?>=@Y@KfP{nW zf#N(n@Xw*#iKzJwzH7Ao2Asx@(kO>`2znRgOs#x;vSsC$E!%>aQ+2oEZYkh7Pqi4+ z4y@KX^ldXP=U3EBoakmpjy$}x={jCq=M2%P z9Xue;fEHRK|16{{TBW|dByT=|ve$045aTN-7R4}Kpy4TrRiF`Za`+sLbLwJUT}R}` z^Rj8%9#(eJw^D@?4g5*=g0mG*=a4HBCuRk z%SBS;9XrN>w6kRn?hPV|d#47CjmYcjHlI3QdVI!dK9)cD62(eXPY?0#s-`ouP#WJ( zOmuB74iq$<+TzQ;(@*gE?zvLPk6R23rt)+6O0jQsLML$K?!9}PqqPoS0las1cGedh z&d5Ga^PIDDkXmZ`Fg946qKf>7tk$eKT3K01h&xtYUR&G#$dMzZfznj!o`a~}QbP5* z!9XmwZHw9y>xhMU|K8@6js(T$yTbkB-GKq`o{taB&7SP?$8fdyBx$$q-@pHXTMb%i zcV}Yk65D4fA=u-S=Cy1~@6E?i7Yc5LMIRw{K3gLNBp+yt0>RkktU zXL+QWGxM1Mje5HpiQ3B6Rv53v@2(%Zam|{N(e^co98|y-NIRA`Hg_SrY+#binw6#2 z(^S;(=>>ze9`}pqOeijHdQ7J%4KGCP<{dk30&*A836t}>s7d|gm-IwP3I!W8uy9); z`9v+W?>r_&$dtEP`GrvK!@42&W9{#0e+5ar>LVFS5KKiwPfTU?oEIE zSbwnN-CDD?AqjWx0RE=D_2c2o^BxdfQqbt$DoasWh3<{{5WiRm2i3JX9?kCkyBWbU zdM$Gl5f;I9X?82|8)fPl+`t*XDSj%87e1n(bVk+C`-;ImYLwJzjadvjD&-Y1rc9AxI z0-L>HF0ZaAAx?+6Ik=QF@!EWM zLDav^l|qST&0fa-0Dom}uXbDwO0~bpxZ4 zpfOoGK^FGqQCzs(3!IlSgW5+nILd;JE~n0uSE|o?QU8dNV248Pb_kX;fO;%jP&brI zG5k_mhre6c+D0OXoqD!2c!8trSslIQwQx7cE@rf49YW+Z_AzT~=xnh|SFfT1LbP3q zj7**-vchJyP>UAU>#5)p2>xjhegGnMppy&f5bq~rR*fHn*Wl)&7;V_IV_q`5A$?;; ze4+R&d(B2uBYnN0p(4Npr3iCiV@Rr9?i(ybufgAiU=;zfP;`>60W(3{|JPz|?Pwm_ zM@fu!~`frAII+1pMW$n*02yff_C>P%IQcLKM0L9Jvk`}V0@C4VEw!Gy0K*^ zKNln9K&Y zfwsAmO~k032dRD4!LJ(YpQHRb%{Q#{-zRkoq|j=)I`C?P5tL4BSEUGyHjK72w?Qce z`DH>7mwx-UUq+wEN=fF4$q5Nh0hm`X^GampmYPCGxfC6p#xG-FB(2{PivWLS+<|^> z3iM+_YfQ9y)aYiQ+jmT&lfi1q$PqHRdDFxw>ZiKFbAY}wLh+9AjXP*E;bRl=zc0p6 zfBg8dnrrQnM4lI~UswP5@=7UYrp78PDLWc#@!G0yGzcDUiq(ncIcoZE+U{AQ(%t(e zDoM3swRxqAqLl9Va6H~l?&ROKVELh}j$F3uBq@F9m59wtmoMK&pKR-Dp|=6#0ce0w zy?la#q(YMB(jn9Gk&}aB3^{F^Cba56f-F($P;A-edy{!HHpGPF04`hX^`Qj?j(A6d z)G~#ocSC3&X$_UYK5|0i+g+?^%2^&Dgcb;*f~x9IYySHvVDQ$fF?g#s!6m0Hk?jlV zZ5y7iYLAkkYeMP4o6tj8-6Yn$rmXv#xCU+9?BP+R~Ud>tgp$c`>fS*EX?*TO-c#lQUU_ice=gLQ(Y zC-s1ah;dvmi0gqj_P(tr$lx=IM_%IcySUs3S<_vgn_{h;0*zQ*-EzLY_l1O$5(-~G zf9^op3aZV;-a$w#yA1~x$k&Q;@{ac}l2Ostmd2^tkdCbJ@ zNqQ($)4nSK0G27tD^L&=8p=NatBK|Mxq)|&1zJU-F)gtz-RuMX;>;TZ&* zFz0$LndqXlNle^L$tboZgNA^L#4t+xJM$bDA;zGUbGyH-OvKUu^993!CjZ{88uQrS zVCPWQo(CViA+U9!OS-K1S4VtASL5O4Y)^$@&3{kXPTssNT+6%Br%uSx|669+z#FYz z8;yAZ(1~-&U8wi_S2PCw=`rE|G29l>jb1|zZlFMJ0C1&@upAH(Jpy`8%f-A6p7`T9 zBk`CD@Ev=MplB5CU{j7t25q(?^N`iQKVL*oCO1`NI(m#p?V^AwRCw(IDbma9&rXc- z+khCqbHe=5Rm|Ag8*c#>nV41gqCqR;D2;c+^{58Z@Z~3ulUfx2&O4(GbCv()ik)|r z@k+eK*X#RE@%fU4BZx#<3(M@TOrV$6#T@x6R5U))Eod^u19+8&&DWN(74(fNJNUDF zW%t(`9xEJl|9pGk*OOhhB#Ni$+`kbJGX? z9}oJW7m+5y<8YdQB{5<|Ld8Cf%dow>QA=mKOZrChrEoJ2?;W+(H2ES+EaEZ{xpwO}%Ae&WUqjRGk1ArLh%z@RKNzfXX6t zfxTZT+c^jxc7mgn$YhZ8|Nps*k2mA}B*_HvCx}S!;_p+*x=%i9{r~!vxO}g(SF3H2 zH%7A!V$%pzkpYPM9T!b?GW|q-(e#?!25QgX6Crwl(zd+KP^Xt$>4b}}g3jBw;vYzP zK7+OmC3VJpLubOSwNbSp|znhGPy5 zbx&R;Gth#*8HoRyiy6GroQK=K8mFnB=Z5Ae7`S}fKh$N!r#Y4sZ>=*lFmORuG8sCy zd(WOEls!t?^%?76L|L&Sr$(2%95KV*B8+&_6CMG=pb1sKs6-BO=P+6m{@wRqDIXkB zoyswz{Vxo%-k}GXfjS&gS4T)w@S9cbd=gM6C+PtdUQ-rrWZ4CIU5PKIfE^O;(g27^;j&&aSh^*M&gWh z8C2d08PIrKm7^g;l3%iq;jf3^_kU~1HHECQLi`mPJKVVuwXohC2a7Ei=5-+3msF3G zs4JXGk*kl~2cef$|Jcw^kPIDws#E+j;eTQ-$QWw6^%%7Li*nXG7Z(>IZ>2dD*)qWy z<-WAHrx-?vyHwo?gL>x!fEn)!++U(E^WXZroQpVfW;*>}U4>#%s4nEh31^I16NnO) zfv#BBC3BNy{@Z*ZPW=VXN@zEPEJ29bIPzu5c}Vl)UGKLryU3#yaj^~o`vkc-IvYFBXkHG!-xbl>7NL8k+H+zbwDvcve{MP}cU%`Cz)xbe&k-$B(${Ya zo(QDRY93Mr*F5mq2;V9B?>naWPKC~&)TW?6Zurj6#7)<4p+^G_O}eZRq&8tppcm#h z{=0p!RK&x`WjH7nC0_IRuUs-BU0d#poRY%^SeZ63LJ=i9-KX&Q^n; z14J=`oe7!;z`8mv7>X}*Fuk^PP4347XHN*wxOgHNBm@E~Knl|VD{bO$Kxn#i8r)Tb z?(x__JuxK6!0`C}`})o(roY8d=m9K65<&zOhr>Ne#;iatR~CCX9{R9{ zwAfGa`p&}G+1sVL56s8;`^Sf9?K2ZHca?RKezZ=D<-aK`Y-TRps0PQJ*s25T*uBsW z)8LVd{ehx=f}``NO)lnPyPW;k$-Y3~Z)CpF9@+*oioAx#d(;(81duBk7{HK$Ue5HwIJR;J3yC zYcd6BCdtY}!TkOEH}N_W_yK2*JpdnQQ>5)8c0Unn}^sQP; zd;2t^l9WfPGZUa55``SyTk^Qof8S28J1HsY9r6$9W75sg$%B5F0UxC;s&rTaeV-Dg zAuAj$N+f)?=Hgk+77LVmA?c&Nnvc$nEa^^>FF_q7b-De2 zUrNczu|i*SGi({M@(KzY9zJ|1ymUJQua^b|fW3HeU#e?roY7l`IV4t=n2KtSO_`yF zCOO`3lm1^wa}pxi2J#2GvkLSx=gw7Qi6L?CLy>-jj9gn1+^rB{4@JnZIe4N-R(|#B zZL3zTLbE^DcRA67R}&F}adB5}0}-B-Y_p7*)o96;M{8Nbq=JdMM#e-`3D#-iD7m-& zXz}=nE8Ps@2ePy}+Jp!wqLs5zR%033G*hNbvCZ?mDJ!q0W`Uk0*)nNjGw<>JTb8dW z85wn8SjmKlG3UbBhSqWiT2N$6w*SWTm4G_x!$Ale8<^0$*@A~p?N$uR=HH<7s^Fl| z9vi6g>n$3RRS%Geh92=o=g)o&st^ro_Qs2IhWTzB=#QGHiCNvJ?Tt-H47=Db4k3SE zkFgJlCU~sdaS$G}jVKteLs5mIP(d_AGUIIY{xCzOFb#2`W*hPeR|PIR|@eh?kI%gpg`UIqek~sjzXBq*aK}D zb_gEx(ViInS=tT9*IH|PpUc4SrhjkC${0h1SHrgL75C&cc%y^@{}@yI~yJO3D*lUwr)E5~{G>RU;korQISPgL* zG2v5SI{m?j3zPz+rRuqXqD&mnKm0Fabf-RGXAHja=UiEHZyYZ;Bh?8lq4Hpbc4BPs z_*VEa<(CQ%73c4QN>Hv|*AcGued!Kcin48jhehMhJ$8?&0}4 z+t)A$FuSg3Nkg@L2g?-co9E}}FM1YQ-RGT(M4WRuk&BA+Nwv-1K$NjhyN3H(K|L4s z)3P`?xR?o55JeLvgyIdtT#lmOw6rc#-SrY4NQT8!!@h;z#SRULOl&$`e#!H)_HfO0 zy}kKlS_$#@3hM?1yqX1Um_`a*U^c4SjifQIw(pH7+zF6LT1t5MjF{+K!$BJ&5HtZ3 zdOF%?IW6k|nCa+7EJlt(1M{LR{IYOBg@z_mX{Z-=e9ZIe0^&Yso)71vYerGdyhV_% zefHO9(Md-TZZ}zZWo47USq;EAjvYX}!uc?cMvfJ4RDQS)9YpsNr-`}^zOaSlxt{uk zbmHRtS`nLp|AX|*w}6LF<015}nrzp)MUE14<{U7y%f(z&p+`Xa0O-3IF=5+}15ZcK z1MkGAflH>%m{Ilgw7`vkvGw!q6VUF;{zP8s9G(eZnlTpTqAcv$)B8bxC@wbNw3!$W-OS7 zZUh8^xxnn5?bT+`<_hmz)%`uMA_pH%T72AU{fUSJD+YvYb2P%w%ff8B2F+l?F);H^ zyC?g>j8!PrNb>v8Zf#+K_8Y^>99!n~>rL>Q(wTUGCB#H@$stNI;xjqs=m}fv{O7{y zyj#Id#ob2t+z6?8>8E(i$4dyLI+V&f23H(gw*kcyG_$r&-1=Z|C)`7qs_zB*qGl6b z?RyX7&=4m|FQwCsY)4#oLBp-wbTcqF5{_`zbt@`Ll$h3-bJ6>N+6$)l z2#F?dEl`+>CD}N5JRlGTK4!uSw|XaV>J1w|1Pcbj(02HxN}3Q~1*^1eCB&R9OmDe2j=qIyZ}p9U!dU)%pEdfNtjLc@O<@ zZ;%b_0Jc4yV$@+;{UG8FKH`=zVnSdhIM+P-btM2Q?jid{YLHghav#zpc?jqcq2XjQ z_z6ktvn46@_bbN%h<+QGP#9rCRNMP{0g|)lE%q%glgvCmRMMSY=b&1Ag{0gH-R8$h zY{`kDd~eTp4A`PlGJ3y%1mmbiX5HVqj#tZYlZG*o$0DWHx+S=SwW?P#T3YCi+5kJGxRbay+Fer7-HK zGrT31FlxZ|La7V_guAcri&^H-3`I2`Ns-*cl_%2=l{u`xW)raAt8Hgd&(f(TBX2Y^)SCgd z^sL+z>e?5S&9!XvHrQ4-*}32eZ#mys801fo~lUAVo!E*JHvEE>n8|9GqDO;RXs@jBF5!IG8 z%x-87-h_Ad@})~o&(6$)kxo5b3mric&0|o|nF$!-Eb-OvZ5GluZL$DcP93QOG@i#A znE?(B0@$u?h~1}nSrs2d!%DhZhlmFdtvjcrgx0-5=?VNy;wEf;5l|X zvLOfXqV#)+Mvd-#!CZ*`)QV4SaIwkiFensAa**Ue6y8*B-50%(4$OmD>~>X78mu=W zbrP_&+Gsmh<3$q_-C(^qemjU-`VJVVhBC8_+lZKViCuzMl67y2B4hZaV5$I)y=Lur zGBr^W7LJPzL*8(S${S6cC7f`cFH)4UeS$9LWo%cJDRibmnDA|&pm@P-E=dkq#_&Og zC`>B;QQu{fQd2KAy2F1d zZi4UCARy|<*Xu7|zb122nlVmUd~c6!-#|t%OXSXuCnxDla&|DyZr}a}c)i{st%Y^t z->Pge%H%OPle$~IT3e`gV)UU%xHcb|Pd`eP38qqJI6jE;XRmZhV9JDl6lXfk_rsoT zBL?3$4&Ys`O6noaN|0LMogkuA?*AvYfA`)Sf zM_6K{jFk;A$smBjPDB}QvgUD84^{Y# zup>Y*q=*enf=ZB#vOSuckf3}OIk@^bu%N8@#9@Wfxs-Ry$UtX2at-k+ldqtg(x)F| z;-+f_fOLX7)y7;##(9KQUBErJdzsmq5b~dk|a#`;yS-|g!Oy9@N#lyIW^<@OFf{Or>K(=rH&i{zd)2Hi@ z>|0cj?3KE(up;pxi1TJ33P0S%9Vk*SRNp&x{o=)VoOmSPG{ra5()-CQf@g(&9IF)& z66*BUlTOUxOsjCubp_*^6c=!$7}{7(Qeuot&vt5bHaT*GCGwqL(3nnI%dq=GoqiY% z-v~+};v^eJCxP+B;;oIasrp{GdUj-%iC4kKDwnh)+Y1H^VHh^ZgzUr8#Ci@S^?(v2-@V&X zeW*nijzv&7i%& zvp(#LtwF^ul_aGDmGjnLaa)oPY;aT`RVq1uGFP@-J3A1btkvW5gDP+lj==NuE5X(9pzbo zHeEG26Q(FjXb$XrriqjuYG2 z@Y>J)c-P4h5ZMI<0{i?CIVDC8dFfETVjNsl;b!tq1ol1K3wn#IQnxESJwBT_WRMX1OVp_h^phD8lgV~< zbbS*K3=F1hZp=MrdDWCyke4GA@Y3|&|!AP?O} zGUMb7Gs_dWG=!43Q)iBen}=A6bq0~#`%B8?6QgcH%j%P)vCnx^c~6sinsy*hBQsT@ z11U?#34W~NmPu`255`}Lu@?Y+5M5;l$OWaGTyy5kQ9~JsrY5v#Dry1N%hSx{bM-GU zEzLBhjhBl*I2s|-*ssaRbjCrB7;BlEv(g^0I6v4`vT$VbL`Xpwmzt@Wlf{!lUc+l2n#1Mw*i(TdXZY-wBD9d{^bRD zsdraWqV2EW)Z00jTfLN@Ipz()qy2`kSS`pne*C!4#Mn?bWKf?!#prB0KRw0ox5X^r ztZ~~`;*C(U&$mFSv9kXnE$)lgHU%oK23*OQkX(3TR@2{15+l?eCW$$9NVee9?AB*H zLfe{d^0oRGP9rAPA($gp|2RdoDXreZscE_LaR^l>{5 zDm;`lzcLPfV?#RWN;C|K2C~y5j$H(Ng z<%f!ruVlmc(C;LUW2!{}z_w2`+{Vo87C2@^Vh&D`SEHH&^R}?KL|RA%-}7I!wd44f zGtz`faEqKCL?na<73+N~F(=op;g|IgBX17uT-dR8*4w;Jz!ZX-c!+@(AJOGA8#jy$ zP7W4%tI8jf)R0KZYP3W|W#!4-m9aLo)bGK{abP9H`q+}E<6t=|y4`D~Z`J21A z8R}abDX9QOE=sk(Kp9_IXJDY9t=-tQjFN2Wp9`Pc|Hi*46bbhW6rH+De}1>q^jxJe zDNeV@d67zE!C?IDndLX0w0hcTbD=eiLkwm>&O5>Gh!p%q3gd}wl#?@F0{^N!N%#1F r?yu1h+3A1akKFv9+x`zM*#xhr24Bnbum*jyX7u$Y>(ceNAN#)mnGLh= literal 19296 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 diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index 12c1e8db1..7d41676a4 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -63,6 +63,17 @@ def test_directed(self): fig, ax = plt.subplots() plot(g, target=ax, layout=self.layout_small_ring) + @image_comparison(baseline_images=["graph_directed_curved_loops"], remove_text=True) + def test_directed_curved_loops(self): + plt.close("all") + g = Graph.Ring(5, directed=True) + g.add_edge(0, 0) + fig, ax = plt.subplots() + plot( + g, target=ax, layout=self.layout_small_ring, + edge_curved=[0] * 4 + [0.3], + ) + @image_comparison(baseline_images=["graph_mark_groups_directed"], remove_text=True) def test_mark_groups(self): plt.close("all") From 478beb7f0fa8b2dc8cfaee41c90399f01ed8d46e Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 1 Jun 2023 15:53:47 +1000 Subject: [PATCH 1289/1892] Better docs for GraphArtist --- doc/source/visualisation.rst | 12 +++++++----- src/igraph/drawing/matplotlib/graph.py | 14 +++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index e8121551c..24b752e36 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -143,15 +143,17 @@ you might want to change the size and color of the vertices:: >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> ig.plot(g, target=ax) - >>> dot = ax.get_children()[0] # This is a Circle for the first vertex - >>> dot.set_color('tomato') - >>> dot.radius *= 2 # double the default radius + >>> artist = ax.get_children()[0] # This is a GraphArtist + >>> dots = artist.get_vertices() + >>> dot.set_facecolors(['tomato'] * g.vcount()) + >>> dot.set_sizes(dot.get_sizes() * 2) # double the default radius That also helps as a workaround if you cannot figure out how to use the plotting options below: just use the defaults and then customize the appearance of your graph via standard `matplotlib`_ tools. -.. note:: The order of `ax.get_children()` is the following: (i) patches for clustering hulls if requested; - (ii) patches for vertices; (iii) patches for edges: for undirected graphs, there's one patch per edge. For directed graphs, there's a *pair* of patches, associated with the arrow body and head, respectively. +.. note:: The order of `artist.get_children()` is the following: (i) one artist for clustering hulls if requested; + (ii) one artist for edges; (iii) one artist for vertices; (iv) one artist for **each** edge label; (v) one + artist for **each** vertex label. To use `matplotlib_` as your default plotting backend, you can set: diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 4508fff45..053e2f010 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -218,27 +218,23 @@ def _set_edge_curve(self, **kwds): return None def get_vertices(self): - """Get vertex artists.""" + """Get VertexCollection artist.""" return self._vertices def get_edges(self): - """Get edge artists. - - Note that for directed edges, an edge might have more than one - artist, e.g. arrow shaft and arrowhead. - """ + """Get EdgeCollection artist.""" return self._edges def get_groups(self): - """Get group/cluster/cover artists.""" + """Get HullCollection group/cluster/cover artists.""" return self._groups def get_vertex_labels(self): - """Get vertex label artists.""" + """Get list of vertex label artists.""" return self._vertex_labels def get_edge_labels(self): - """Get edge label artists.""" + """Get list of edge label artists.""" return self._edge_labels def get_datalim(self): From 3106e65328b18eae04360d122a66e44d6e431d11 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Sat, 3 Jun 2023 18:17:31 +1000 Subject: [PATCH 1290/1892] Callback and small bugfix for edge editing --- src/igraph/drawing/matplotlib/edge.py | 102 +++++++++++++++++- src/igraph/drawing/matplotlib/graph.py | 38 ++++--- src/igraph/drawing/matplotlib/vertex.py | 17 ++- .../graph_directed_curved_loops.png | Bin 23883 -> 23632 bytes .../test_graph/graph_edit_children.png | Bin 22535 -> 23762 bytes tests/drawing/matplotlib/test_graph.py | 4 + 6 files changed, 134 insertions(+), 27 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index f485f0143..bb77b8ef6 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -86,8 +86,8 @@ def __init__(self, *args, **kwargs): kwargs["match_original"] = True self._visual_vertices = kwargs.pop("visual_vertices", None) self._directed = kwargs.pop("directed", False) - self._arrow_sizes = kwargs.pop("arrow_sizes", 0) - self._arrow_widths = kwargs.pop("arrow_widths", 0) + self._arrow_sizes = kwargs.pop("arrow_sizes", None) + self._arrow_widths = kwargs.pop("arrow_widths", None) self._curved = kwargs.pop("curved", None) super().__init__(*args, **kwargs) @@ -135,13 +135,19 @@ def _compute_paths(self, transform=None): ) elif self._directed: + if (self._arrow_sizes is None) or (self._arrow_widths is None): + arrow_size = 0 + arrow_width = 0 + else: + arrow_size = self._arrow_sizes[i] + arrow_width = self._arrow_widths[i] path = self._compute_path_directed( coordst, sizes, trans_inv, curved, - self._arrow_sizes[i], - self._arrow_widths[i], + arrow_size, + arrow_width, ) else: path = self._compute_path_undirected( @@ -155,6 +161,8 @@ def _compute_paths(self, transform=None): return paths def _compute_path_loop(self, coordt, size, trans_inv): + import numpy as np + # Make arc (class method) path = mpl.path.Path.arc(-90, 180) vertices = path.vertices.copy() @@ -167,6 +175,16 @@ def _compute_path_loop(self, coordt, size, trans_inv): # Offset to place and transform to data coordinates vertices = trans_inv(coordt + vertices) + # Hack used for any curved lines to deal with facecolor + vertices = np.vstack([ + vertices, + vertices[:-1][::-1], + ]) + codes = np.concatenate([ + codes, + codes[1:], + ]) + path = mpl.path.Path( vertices, codes=codes, ) @@ -307,3 +325,79 @@ def draw(self, renderer): if self._visual_vertices is not None: self._paths = self._compute_paths() return super().draw(renderer) + + def get_arrow_sizes(self): + """Same as get_arrow_size.""" + return self.get_arrow_size() + + def get_arrow_size(self): + """Get arrow sizes for the edges (directed only). + + @return: An array of arrow sizes. + """ + import numpy as np + + if self._arrow_sizes is None: + arrow_sizes = [0 for x in self.get_paths()] + else: + arrow_sizes = self._arrow_sizes + return np.array(arrow_sizes) + + def set_arrow_size(self, sizes): + """Set arrow sizes. + + @param sizes: A sequence of arrow sizes or a single size. + """ + try: + iter(sizes) + except TypeError: + sizes = [sizes] * len(self._paths) + self._arrow_sizes = sizes + self.stale = True + + def set_arrow_sizes(self, sizes): + """Same as set_arrow_size""" + return self.set_arrow_size(sizes) + + def get_arrow_widths(self): + """Same as get_arrow_width.""" + return self.get_arrow_width() + + def get_arrow_width(self): + """Get arrow widths for the edges (directed only). + + @return: An array of arrow widths. + """ + import numpy as np + + if self._arrow_widths is None: + arrow_widths = [0 for x in self.get_paths()] + else: + arrow_widths = self._arrow_widths + return np.array(arrow_widths) + + def set_arrow_width(self, widths): + """Set arrow widths. + + @param widths: A sequence of arrow widths or a single width. + """ + try: + iter(widths) + except TypeError: + widths = [widths] * len(self._paths) + self._arrow_widths = widths + self.stale = True + + def set_arrow_widths(self, widths): + """Same as set_arrow_width""" + return self.set_arrow_width(widths) + + @property + def stale(self): + return super().stale + + @stale.setter + def stale(self, val): + PatchCollection.stale.fset(self, val) + if val and hasattr(self, "stale_callback_post"): + self.stale_callback_post(self) diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 053e2f010..42dd70802 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -620,22 +620,11 @@ def _reprocess(self): self._draw_vertex_labels() self._draw_edge_labels() - # When the vertices change size, one has to redraw the edges to match - # the boundary of the marker. Unless one has granular control over exactly - # what edges to redraw, it's simpler to just redraw the whole thing. That - # requires adapting the vertex_builder (already done in VertexCollection) - # and then redrawing the container artist. - def vertex_size_callback(artist): - sizes = artist.get_sizes() - for size, vb in zip(sizes, self._vertex_builder): - vb.size = size - self._reprocess() - # Callbacks for other vertex properties, to ensure they are in sync # with vertex_builder. # NOTE: no need to reprocess here because it does not affect other # parts of the container artist (e.g. edges) - def stale_callback(artist): + def vertex_stale_callback(artist): # If the stale state emerges from other properties, we can salvage # the other artists but we have to update the vertex builder anyway # in case a _reprocess is triggered by something else. @@ -659,7 +648,30 @@ def stale_callback(artist): if artist._stale_size: self._reprocess() - self._vertices._stale_callback_post = stale_callback + # Edge callback, keeps the edge builder in sync with the actual state + # of the artist + def edge_stale_callback(artist): + prop_pairs = ( + ("edgecolor", "color"), + ("linewidth", "width"), + ("zorder", "zorder"), + ("arrow_size", "arrow_size"), + ("arrow_width", "arrow_width"), + ) + for mpl_prop, ig_prop in prop_pairs: + values = getattr(artist, "get_" + mpl_prop)() + try: + iter(values) + except TypeError: + values = [values] * len(artist.get_paths()) + for value, visual_edge in zip(values, self._edge_builder): + setattr(visual_edge, ig_prop, value) + + # Sync facecolor from edgecolor + if mpl_prop == "edgecolor": + artist._facecolors = artist._edgecolors + self._vertices.stale_callback_post = vertex_stale_callback + self._edges.stale_callback_post = edge_stale_callback # Forward mpl properties to children # TODO sort out all of the things that need to be forwarded diff --git a/src/igraph/drawing/matplotlib/vertex.py b/src/igraph/drawing/matplotlib/vertex.py index 89c874d4a..49bd7389b 100644 --- a/src/igraph/drawing/matplotlib/vertex.py +++ b/src/igraph/drawing/matplotlib/vertex.py @@ -107,7 +107,7 @@ def get_size(self): If width and height are unequal, get the largest of the two. - @return: A list of vertex sizes. + @return: An array of vertex sizes. """ import numpy as np @@ -120,7 +120,7 @@ def get_size(self): sizes.append(size) return np.array(sizes) - def set_sizes(self, sizes): + def set_size(self, sizes): """Set vertex sizes. This rescales the current vertex symbol/path linearly, using this @@ -146,12 +146,9 @@ def set_sizes(self, sizes): self._stale_size = True self.stale = True - def set_size(self, size): - """Set vertex size, the same for all vertices. - - @param size: A single vertex size. - """ - self.set_sizes([size] * len(self.get_paths())) + def set_sizes(self, sizes): + """Same as set_size.""" + self.set_size(sizes) @property def stale(self): @@ -160,5 +157,5 @@ def stale(self): @stale.setter def stale(self, val): PatchCollection.stale.fset(self, val) - if val and hasattr(self, "_stale_callback_post"): - self._stale_callback_post(self) + if val and hasattr(self, "stale_callback_post"): + self.stale_callback_post(self) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png index e572fa7bc4600268ede2ecfe814ae4a44e87d06b..9d505b466397c96afaa26cbb855622172a7e6a42 100644 GIT binary patch literal 23632 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 Lu6{1-oD!M<#+|^X literal 23883 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 Da5`{Q diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_edit_children.png index eedbdeb3e6e6a0125b4bb38c61b00824d6ae87e4..21234699ae6300d349c1956a206eeb02da69717b 100644 GIT binary patch literal 23762 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 Q26hTYGPgdGW#$_3U-XbBD*ylh literal 22535 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 svCoHBfQoebvH$ Date: Wed, 7 Jun 2023 16:36:07 +0200 Subject: [PATCH 1291/1892] doc: remove direct references to executing setup.py as it is now deprecated --- README.md | 54 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 92892f595..8ae55c896 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,8 @@ Python 3.7 and later. Make sure that you have Microsoft Visual Studio 2015 or later installed, and of course Python 3.7 or later. First extract the source to a suitable directory. If you launch the Developer command prompt and navigate to the directory where you extracted the source code, you should be able to build -and install igraph using `python setup.py install` +and install igraph using `pip install .`, assuming that you have `pip` +installed in your Python environment. You may need to set the architecture that you are building on explicitly by setting the environment variable @@ -105,17 +106,17 @@ set IGRAPH_EXTRA_LIBRARIES=libxml2,lzma,zlib,iconv,charset set IGRAPH_EXTRA_DYNAMIC_LIBRARIES: wsock32,ws2_32 ``` -You can now build and install `igraph` again by simply running `python -setup.py build`. Please make sure to use a clean source tree, if you built -previously without GraphML, it will not update the build. +You can now build and install `igraph` again by simply running `pip install .`. +Please make sure to use a clean source tree, if you built previously without +GraphML, it will not update the build. ### Linking to an existing igraph installation The source code of the Python package includes the source code of the matching igraph version that the Python interface should compile against. However, if you want to link the Python interface to a custom installation of the C core -that has already been compiled and installed on your system, you can ask -`setup.py` to use the pre-compiled version. This option requires that your +that has already been compiled and installed on your system, you can ask our +build system to use the pre-compiled version. This option requires that your custom installation of igraph is discoverable with `pkg-config`. First, check whether `pkg-config` can tell you the required compiler and linker flags for igraph: @@ -135,15 +136,14 @@ IGRAPH_USE_PKG_CONFIG=1 pip install igraph ``` Alternatively, if you have already downloaded and extracted the source code -of igraph, you can run `setup.py` directly: +of igraph, you can run `pip install` on the source tree directly: ```bash -IGRAPH_USE_PKG_CONFIG=1 python setup.py build -IGRAPH_USE_PKG_CONFIG=1 python setup.py install +IGRAPH_USE_PKG_CONFIG=1 pip install . ``` (Note that you need the `IGRAPH_USE_PKG_CONFIG=1` environment variable -for both invocations, otherwise the call to `setup.py install` would still +for both invocations, otherwise the call to `pip install` would still build the vendored C core instead of linking to an existing installation). This option is primarily intended for package maintainers in Linux @@ -200,7 +200,6 @@ additional dependencies, read further below for details. For more information about installing directly from `git` using `pip` see https://pip.pypa.io/en/stable/topics/vcs-support/#git. - Alternatively, you can clone this repository locally. This repository contains a matching version of the C core of `igraph` as a git submodule. In order to install the development version from source, you need to instruct git to check @@ -220,17 +219,20 @@ sudo apt install bison flex On macOS you can install these from Homebrew or MacPorts. On Windows you can install `winflexbison3` from Chocolatey. -Then, running the setup script should work if you have a C compiler and the -necessary build dependencies (see also the previous section): +Then you can install the package directly with `pip` (see also the previous section): ```bash -python setup.py build +pip install . ``` -You can install it using +If you would like to create a source distribution or a Python wheel instead of +installing the module directly in your Python environment, use a standard build +frontend like [build](https://pypa-build.readthedocs.io/en/stable/). If you +use [pipx](https://pypa.github.io/pipx/) to isolate command-line Python tools +in their own separate virtualenvs, you can simply run: ```bash -python setup.py install +pipx run build ``` ### Running unit tests @@ -242,6 +244,17 @@ with the built-in `unittest` module: python -m unittest ``` +Note that unit tests have additional dependencies like NumPy, PIL or +`matplotlib`. The unit test suite will try to do its best to skip tests +requiring external dependencies, but if you want to make sure that all the unit +tests are executed, either use `tox` (which will take care of installing the +test dependencies in a virtualenv), or install the module with the `test` +extras: + +```bash +pip install '.[test]' +``` + ## Contributing Contributions to `igraph` are welcome! @@ -252,16 +265,17 @@ that you would like to see included in the main tree, open a PR on this repo. To start developing `igraph`, follow the steps above about installing the development version. Make sure that you do so by cloning the repository locally so that you are able to make changes. -For easier development, you can install `igraph` in development mode so your changes in the Python source -code are picked up automatically by Python: +For easier development, you can install `igraph` in "editable" (i.e. +development) mode so your changes in the Python source code are picked up +automatically by Python: ```bash -python setup.py develop +pip install -e . ``` Changes that you make to the Python code do not need any extra action. However, if you adjust the source code of the C extension, you need to rebuild it by running -`python setup.py develop` again. Compilation of the C core of `igraph` is +`pip install -e .` again. Compilation of the C core of `igraph` is cached in ``vendor/build`` and ``vendor/install`` so subsequent builds are much faster than the first one as the C core does not need to be recompiled. From 39f07de21199eb4a3f6c483417070480d028a5b3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Jun 2023 16:41:58 +0200 Subject: [PATCH 1292/1892] doc: stop referring to setup.py in the online docs as well --- doc/source/install.rst | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/source/install.rst b/doc/source/install.rst index 7eef1fa66..5f8fc07ea 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -94,7 +94,11 @@ Compiling step by step ---------------------- This section should be rarely used in practice but explains how to compile and -install |igraph| step by step without ``pip``. +install |igraph| step by step from a local checkout, i.e. _not_ relying on +``pip`` to fetch the sources. (You would still need ``pip`` to install from +source, or a PEP 517-compliant build frontend like +`build `_ to build an installable +Python wheel. First, obtain the bleeding-edge source code from Github:: @@ -122,26 +126,28 @@ Third, if you cloned the source from Github, initialize the ``git`` submodule fo of the C core that is bundled with it (or with the revision that the ``git`` submodule points to). -Fourth, call the standard Python ``setup.py`` script, e.g. for compiling:: +Fourth, call ``pip`` to compile and install the package from source:: - $ python setup.py build + $ pip install . -(press Enter when prompted). That will compile the Python interface in a subfolder called -``build/lib.``, e.g. `build/lib.linux-x86_64-3.8`. You can add -that folder to your ``PYTHONPATH`` if you want to import directly from it, or you can call the ``setup.py`` -script to install it from there:: +Alternatively, you can call ``build`` or another PEP 517-compliant build frontend +to build an installable Python wheel. Here we use `pipx `_ +to invoke ``build`` in a separate virtualenv:: - $ python setup.py install - -.. note:: The ``setup.py`` script takes a number of options to customize the install location. + $ pipx run build Testing your installation ------------------------- -The unit tests are implemented with the standard ``unittest`` module so you can -run them like this from your the source folder:: +Use ``tox`` or another standard test runner tool to run all the unit tests. +Here we use `pipx `_` to invoke ``tox``:: + + $ pipx run tox + +You can also call ``tox`` directly from the root folder of the igraph source +tree if you already installed ``tox`` system-wide:: - $ python -m unittest discover + $ tox Troubleshooting =============== From 6b1e4387a8f5e37a575e0a7c7fdfc52d918f2bd6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 7 Jun 2023 16:42:56 +0200 Subject: [PATCH 1293/1892] test: clarify that you need PIL _and_ NumPy _or_ OpenCV to run Cairo tests --- tests/drawing/cairo/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drawing/cairo/utils.py b/tests/drawing/cairo/utils.py index 443aa1e2d..7a7a297ea 100644 --- a/tests/drawing/cairo/utils.py +++ b/tests/drawing/cairo/utils.py @@ -39,7 +39,7 @@ def fun(filename): except ImportError: pass - raise ImportError('PIL or OpenCV required to run Cairo tests') + raise ImportError('PIL+NumPy or OpenCV required to run Cairo tests') def find_image_comparison(): From 6a258127583819cc39bb9b2a4483dbeb403b9ad7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:03:39 +0000 Subject: [PATCH 1294/1892] build(deps): bump pypa/cibuildwheel from 2.13.0 to 2.13.1 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.13.0 to 2.13.1. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.13.0...v2.13.1) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93d6d40fa..b95a0091d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -242,7 +242,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.13.0 + uses: pypa/cibuildwheel@v2.13.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 9230e603a1e5252b0fe484eda4f01c6b91117a49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:01:47 +0000 Subject: [PATCH 1295/1892] build(deps): bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b95a0091d..6025f8863 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -190,7 +190,7 @@ jobs: pip install pyodide-build==0.21.0 pyodide build - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: ./dist/*.whl From 6fe6ac94b3714a246e610c8377753f6f974fd1ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:02:06 +0000 Subject: [PATCH 1296/1892] build(deps): bump actions/setup-python from 2 to 4 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 4. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b95a0091d..d43b38caa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -176,7 +176,7 @@ jobs: submodules: true fetch-depth: 0 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 name: Install Python with: python-version: '3.10.2' From a02aef943ad7c0c9e45aeae231812283d695ada6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:02:32 +0000 Subject: [PATCH 1297/1892] build(deps): bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b95a0091d..746501758 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -171,7 +171,7 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 From 5204b2e1527c0369a5d3e04ddc8544a6429b1752 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 28 Jun 2023 11:45:04 +0200 Subject: [PATCH 1298/1892] feat: add Graph.count_automorphisms() --- CHANGELOG.md | 3 ++ src/_igraph/graphobject.c | 72 +++++++++++++++++++++++++++++++++++++-- tests/test_isomorphism.py | 11 ++++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebd5c8967..ca0006b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ between two vertices using the A-star algorithm and an appropriate heuristic function. +- Added `Graph.count_automorphisms()` to count the number of automorphisms + of a graph. + - The `VertexCover` constructor now allows referring to vertices by names instead of IDs. diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 6e5763f5d..9b68dd958 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -9593,6 +9593,50 @@ PyObject *igraphmodule_Graph_canonical_permutation( return list; } +/** + * \ingroup python_interface_graph + * \brief Calculates the number of automorphisms of a graph using BLISS + * \sa igraph_count_automorphisms + */ +PyObject *igraphmodule_Graph_count_automorphisms( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { "sh", "color", NULL }; + PyObject *sh_o = Py_None; + PyObject *color_o = Py_None; + PyObject *result; + igraph_bliss_sh_t sh = IGRAPH_BLISS_FL; + igraph_vector_int_t *color = 0; + igraph_error_t retval; + igraph_bliss_info_t info; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) + return NULL; + + if (igraphmodule_PyObject_to_bliss_sh_t(sh_o, &sh)) + return NULL; + + if (igraphmodule_attrib_to_vector_int_t(color_o, self, &color, + ATTRIBUTE_TYPE_VERTEX)) return NULL; + + retval = igraph_count_automorphisms(&self->g, color, sh, &info); + + if (color) { igraph_vector_int_destroy(color); free(color); } + + if (retval) { + igraphmodule_handle_igraph_error(); + igraph_free(info.group_size); + return NULL; + } + + result = PyLong_FromString(info.group_size, NULL, 10); + igraph_free(info.group_size); + if (!result) { + return NULL; + } + + return result; +} + /** \ingroup python_interface_graph * \brief Calculates the isomorphism class of a graph or its subgraph * \sa igraph_isoclass, igraph_isoclass_subgraph @@ -16554,12 +16598,36 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " - C{\"fsm\"}: smallest maximally non-trivially connected\n" " non-singleton cell\n\n" "@param color: optional vector storing a coloring of the vertices\n " - "with respect to which the isomorphism is computed." - "If C{None}, all vertices have the same color.\n" + " with respect to which the isomorphism is computed." + " If C{None}, all vertices have the same color.\n" "@return: a permutation vector containing vertex IDs. Vertex 0 in the original\n" " graph will be mapped to an ID contained in the first element of this\n" " vector; vertex 1 will be mapped to the second and so on.\n" }, + {"count_automorphisms", + (PyCFunction) igraphmodule_Graph_count_automorphisms, + METH_VARARGS | METH_KEYWORDS, + "count_automorphisms(sh=\"fl\", color=None)\n--\n\n" + "Calculates the number of automorphisms of a graph using the BLISS isomorphism\n" + "algorithm.\n\n" + "See U{http://www.tcs.hut.fi/Software/bliss/index.html} for more information\n" + "about the BLISS algorithm and canonical permutations.\n\n" + "@param sh: splitting heuristics for graph as a case-insensitive string,\n" + " with the following possible values:\n\n" + " - C{\"f\"}: first non-singleton cell\n\n" + " - C{\"fl\"}: first largest non-singleton cell\n\n" + " - C{\"fs\"}: first smallest non-singleton cell\n\n" + " - C{\"fm\"}: first maximally non-trivially connected non-singleton\n" + " cell\n\n" + " - C{\"flm\"}: largest maximally non-trivially connected\n" + " non-singleton cell\n\n" + " - C{\"fsm\"}: smallest maximally non-trivially connected\n" + " non-singleton cell\n\n" + "@param color: optional vector storing a coloring of the vertices\n " + " with respect to which the isomorphism is computed." + " If C{None}, all vertices have the same color.\n" + "@return: the number of automorphisms of the graph.\n" + }, {"isoclass", (PyCFunction) igraphmodule_Graph_isoclass, METH_VARARGS | METH_KEYWORDS, "isoclass(vertices)\n--\n\n" diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index a0ecb509e..d6825edcf 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -406,14 +406,25 @@ def testPermuteVertices(self): self.assertTrue(set(g3.get_edgelist()) == set(g1.get_edgelist())) +class AutomorphismTests(unittest.TestCase): + def testCountAutomorphisms(self): + g = Graph.Famous("petersen") + self.assertEqual(120, g.count_automorphisms()) + + g = Graph.Lattice([16, 16]) + self.assertEqual(2048, g.count_automorphisms()) + + def suite(): isomorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IsomorphismTests) subisomorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(SubisomorphismTests) permutation_suite = unittest.defaultTestLoader.loadTestsFromTestCase(PermutationTests) + automorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(AutomorphismTests) return unittest.TestSuite([ isomorphism_suite, subisomorphism_suite, permutation_suite, + automorphism_suite, ]) From 9cbc9558f7ad17a8c6d4723182bddccde2cf642f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 28 Jun 2023 12:39:55 +0200 Subject: [PATCH 1299/1892] feat: add Graph.automorphism_group() --- CHANGELOG.md | 3 +- src/_igraph/graphobject.c | 73 +++++++++++++++++++++++++++++++++++++++ tests/test_isomorphism.py | 13 +++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca0006b79..adf345ba2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,8 @@ heuristic function. - Added `Graph.count_automorphisms()` to count the number of automorphisms - of a graph. + of a graph and `Graph.automorphism_group()` to calculate the generators of + the automorphism group of a graph. - The `VertexCover` constructor now allows referring to vertices by names instead of IDs. diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9b68dd958..f27b74149 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -9547,6 +9547,53 @@ PyObject *igraphmodule_Graph_write_leda(igraphmodule_GraphObject * self, * Routines related to graph isomorphism * **********************************************************************/ +/** + * \ingroup python_interface_graph + * \brief Calculates the automorphism group generators of a graph using BLISS + * \sa igraph_automorphism_group + */ +PyObject *igraphmodule_Graph_automorphism_group( + igraphmodule_GraphObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = { "sh", "color", NULL }; + PyObject *sh_o = Py_None; + PyObject *color_o = Py_None; + PyObject *list; + igraph_bliss_sh_t sh = IGRAPH_BLISS_FL; + igraph_vector_int_list_t generators; + igraph_vector_int_t *color = 0; + igraph_error_t retval; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &sh_o, &color_o)) + return NULL; + + if (igraphmodule_PyObject_to_bliss_sh_t(sh_o, &sh)) + return NULL; + + if (igraph_vector_int_list_init(&generators, 0)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (igraphmodule_attrib_to_vector_int_t(color_o, self, &color, + ATTRIBUTE_TYPE_VERTEX)) return NULL; + + retval = igraph_automorphism_group(&self->g, color, &generators, sh, 0); + + if (color) { igraph_vector_int_destroy(color); free(color); } + + if (retval) { + igraphmodule_handle_igraph_error(); + igraph_vector_int_list_destroy(&generators); + return NULL; + } + + list = igraphmodule_vector_int_list_t_to_PyList(&generators); + + igraph_vector_int_list_destroy(&generators); + + return list; +} + /** * \ingroup python_interface_graph * \brief Calculates the canonical permutation of a graph using BLISS @@ -16576,6 +16623,32 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* ISOMORPHISM */ /***************/ + {"automorphism_group", + (PyCFunction) igraphmodule_Graph_automorphism_group, + METH_VARARGS | METH_KEYWORDS, + "automorphism_group(sh=\"fl\", color=None)\n--\n\n" + "Calculates the generators of the automorphism group of a graph using the\n" + "BLISS isomorphism algorithm.\n\n" + "The generator set may not be minimal and may depend on the splitting\n" + "heuristics. The generators are permutations represented using zero-based\n" + "indexing.\n\n" + "@param sh: splitting heuristics for graph as a case-insensitive string,\n" + " with the following possible values:\n\n" + " - C{\"f\"}: first non-singleton cell\n\n" + " - C{\"fl\"}: first largest non-singleton cell\n\n" + " - C{\"fs\"}: first smallest non-singleton cell\n\n" + " - C{\"fm\"}: first maximally non-trivially connected non-singleton\n" + " cell\n\n" + " - C{\"flm\"}: largest maximally non-trivially connected\n" + " non-singleton cell\n\n" + " - C{\"fsm\"}: smallest maximally non-trivially connected\n" + " non-singleton cell\n\n" + "@param color: optional vector storing a coloring of the vertices\n " + " with respect to which the isomorphism is computed." + " If C{None}, all vertices have the same color.\n" + "@return: a list of integer vectors, each vector representing an automorphism\n" + " group of the graph.\n" + }, {"canonical_permutation", (PyCFunction) igraphmodule_Graph_canonical_permutation, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/test_isomorphism.py b/tests/test_isomorphism.py index d6825edcf..16d848790 100644 --- a/tests/test_isomorphism.py +++ b/tests/test_isomorphism.py @@ -414,6 +414,19 @@ def testCountAutomorphisms(self): g = Graph.Lattice([16, 16]) self.assertEqual(2048, g.count_automorphisms()) + def testAutomorphismGroup(self): + g = Graph.Famous("petersen") + generators = g.automorphism_group() + generators.sort() + self.assertEqual( + generators, + [ + [0, 1, 2, 7, 5, 4, 6, 3, 9, 8], + [0, 4, 3, 8, 5, 1, 9, 2, 6, 7], + [1, 2, 3, 8, 6, 0, 7, 4, 5, 9] + ] + ) + def suite(): isomorphism_suite = unittest.defaultTestLoader.loadTestsFromTestCase(IsomorphismTests) From 82b3e4f89f1622a0470d28323f26cce388bad674 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 12:45:34 +0200 Subject: [PATCH 1300/1892] test: remove debug output from tests --- tests/test_basic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index 48ce89d1a..6d57c5a17 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -123,7 +123,6 @@ def testAddVertex(self): self.assertRaises(TypeError, g.add_vertex, 3) vertex = g.add_vertex("3") - print(g.vcount(), g.ecount()) self.assertTrue(g.vcount() == 3 and g.ecount() == 0) self.assertEqual(2, vertex.index) self.assertTrue("name" in g.vertex_attributes()) From 951c9a790f7a58d04cbf734b2f0a31dbdd776a5d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 13:48:09 +0200 Subject: [PATCH 1301/1892] test: make sure that Cairo tests are executed in tox --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 56f4556a3..7257780d5 100644 --- a/setup.py +++ b/setup.py @@ -960,6 +960,7 @@ def get_tag(self): # Dependencies needed for testing only "test": [ + "cairocffi>=1.2.0", "networkx>=2.5", "pytest>=7.0.1", "pytest-timeout>=2.1.0", From 962af9078cf1c29fb6f4f4ab8b59553c394ddb7d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 17:57:53 +0200 Subject: [PATCH 1302/1892] test: fix Cairo plots one more time --- .../baseline_images/clustering_directed.png | Bin 33794 -> 33682 bytes .../cairo/baseline_images/graph_basic.png | Bin 18287 -> 16701 bytes .../cairo/baseline_images/graph_directed.png | Bin 19005 -> 17353 bytes .../graph_mark_groups_directed.png | Bin 19005 -> 17353 bytes .../graph_mark_groups_squares_directed.png | Bin 16548 -> 14924 bytes tests/drawing/cairo/test_graph.py | 10 ++++++++-- 6 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/drawing/cairo/baseline_images/clustering_directed.png b/tests/drawing/cairo/baseline_images/clustering_directed.png index 3971f801c44b9b241ad55579c2d37825480b32bf..14885e28c4e93b66b41f7ec5884d509c27601dc5 100644 GIT binary patch literal 33682 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 literal 33794 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

    OH9Qh)~+=xe9%^+}N1@mpJtyPbtu)y+r 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 G=l=)LhSQS( diff --git a/tests/drawing/cairo/baseline_images/graph_basic.png b/tests/drawing/cairo/baseline_images/graph_basic.png index 6f17b1502f8f29f4b37438958e8e53c019bcbdc1..2eee93d865310740adc91b867062b5b2ec6a5205 100644 GIT binary patch literal 16701 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 literal 18287 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 diff --git a/tests/drawing/cairo/test_graph.py b/tests/drawing/cairo/test_graph.py index 4b0b92eed..14dca8f8b 100644 --- a/tests/drawing/cairo/test_graph.py +++ b/tests/drawing/cairo/test_graph.py @@ -80,8 +80,10 @@ def setUp(self) -> None: def test_clustering_directed_small(self): g = Graph.Ring(5, directed=True) clu = VertexClustering(g, [0] * 5) + lo = g.layout("auto") plot( clu, + layout=lo, backend="cairo", target=result_image_folder / "clustering_directed.png", mark_groups=True, From fa33d32cddc2cd88bc7d76b513e4ace0cecb1ed1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 18:31:38 +0200 Subject: [PATCH 1306/1892] test: clean up after ourselves when writing graph_basic.png --- tests/drawing/matplotlib/test_graph.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index f40bcdb78..09614cc7a 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -1,3 +1,4 @@ +import os import random import unittest @@ -102,6 +103,7 @@ def test_gh_587(self): g = Graph.Ring(5) with overridden_configuration("plotting.backend", "matplotlib"): plot(g, target="graph_basic.png", layout=self.layout_small_ring) + os.unlink("graph_basic.png") class ClusteringTestRunner(unittest.TestCase): From 354512c2612643b0fcfcdea09af7e6ca5bab8c79 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 20:23:48 +0200 Subject: [PATCH 1307/1892] test: skip Cairo tests if neither PIL+NumPy nor OpenCV are installed --- tests/drawing/cairo/test_graph.py | 18 ++++++++---------- tests/drawing/cairo/utils.py | 12 ++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/drawing/cairo/test_graph.py b/tests/drawing/cairo/test_graph.py index 14dca8f8b..d0e6e124a 100644 --- a/tests/drawing/cairo/test_graph.py +++ b/tests/drawing/cairo/test_graph.py @@ -2,27 +2,24 @@ import unittest from igraph import Graph, plot, VertexClustering -from igraph.drawing import find_cairo # FIXME: find a better way to do this that works for both direct call and module # import e.g. tox try: - from .utils import find_image_comparison, result_image_folder + from .utils import are_tests_supported, find_image_comparison, result_image_folder except ImportError: - from utils import find_image_comparison, result_image_folder + from utils import are_tests_supported, find_image_comparison, result_image_folder -cairo = find_cairo() -has_cairo = hasattr(cairo, "version") - image_comparison = find_image_comparison() class GraphTestRunner(unittest.TestCase): @classmethod def setUpClass(cls): - if not has_cairo: - raise unittest.SkipTest("cairo not found, skipping tests") + supported, msg = are_tests_supported() + if not supported: + raise unittest.SkipTest(f"{msg}, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) def setUp(self) -> None: @@ -69,8 +66,9 @@ def test_mark_groups_squares(self): class ClusteringTestRunner(unittest.TestCase): @classmethod def setUpClass(cls): - if not has_cairo: - raise unittest.SkipTest("cairo not found, skipping tests") + supported, msg = are_tests_supported() + if not supported: + raise unittest.SkipTest(f"{msg}, skipping tests") result_image_folder.mkdir(parents=True, exist_ok=True) def setUp(self) -> None: diff --git a/tests/drawing/cairo/utils.py b/tests/drawing/cairo/utils.py index 7a7a297ea..68091ea10 100644 --- a/tests/drawing/cairo/utils.py +++ b/tests/drawing/cairo/utils.py @@ -51,6 +51,18 @@ def dummy_comparison(*args, **kwargs): return image_comparison +def are_tests_supported(): + if cairo is None: + return False, "cairo not found" + + try: + find_open_image_png_function() + except ImportError: + return False, "PIL+NumPy or OpenCV not found" + + return True, "" + + def _load_image(filename, fmt): if fmt == 'png': return find_open_image_png_function()(filename) From 8e1f8da4bfd3baaeb56314efcbdfd8c77b99ddb0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 20:43:50 +0200 Subject: [PATCH 1308/1892] ci: install Cairo in CI for Windows from vcpkg --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d29e8cdd4..49c6d579c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -238,7 +238,7 @@ jobs: - name: Install VCPKG libraries run: | %VCPKG_INSTALLATION_ROOT%\vcpkg.exe integrate install - %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md cairo:${{ matrix.vcpkg_arch }}-windows-static-md shell: cmd - name: Build wheels From 28647e748cecc57754c9c8236357994b5eb89369 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 21:30:16 +0200 Subject: [PATCH 1309/1892] ci: Cairo in Windows needs a dynamic library --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49c6d579c..82a6ca8c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -238,7 +238,7 @@ jobs: - name: Install VCPKG libraries run: | %VCPKG_INSTALLATION_ROOT%\vcpkg.exe integrate install - %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md cairo:${{ matrix.vcpkg_arch }}-windows-static-md + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md cairo:${{ matrix.vcpkg_arch }}-windows shell: cmd - name: Build wheels From 242953a0e157e63f4c55d63506ce84e9b3bcb31c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 11:14:41 +0200 Subject: [PATCH 1310/1892] ci: give up on testing Cairo on Windows for a while --- .github/workflows/build.yml | 2 +- src/igraph/drawing/cairo/utils.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 82a6ca8c8..d29e8cdd4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -238,7 +238,7 @@ jobs: - name: Install VCPKG libraries run: | %VCPKG_INSTALLATION_ROOT%\vcpkg.exe integrate install - %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md cairo:${{ matrix.vcpkg_arch }}-windows + %VCPKG_INSTALLATION_ROOT%\vcpkg.exe install libxml2:${{ matrix.vcpkg_arch }}-windows-static-md shell: cmd - name: Build wheels diff --git a/src/igraph/drawing/cairo/utils.py b/src/igraph/drawing/cairo/utils.py index 068daa1d2..ad183b229 100644 --- a/src/igraph/drawing/cairo/utils.py +++ b/src/igraph/drawing/cairo/utils.py @@ -18,4 +18,8 @@ def find_cairo() -> Any: break except ImportError: pass + except OSError: + # cairocffi throws an OSError if it is installed but libcairo-2 is + # not present on the system + pass return module From 3245e49d638d74ba819f864ee064e959d833180f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 14:32:13 +0200 Subject: [PATCH 1311/1892] fix: fix plotting of curved directed edges in Cairo, closes #684 --- src/igraph/drawing/cairo/edge.py | 20 ++++++------- src/igraph/drawing/utils.py | 16 +++++------ .../graph_with_curved_edges.png | Bin 0 -> 58459 bytes tests/drawing/cairo/test_graph.py | 27 ++++++++++++++++-- 4 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 tests/drawing/cairo/baseline_images/graph_with_curved_edges.png diff --git a/src/igraph/drawing/cairo/edge.py b/src/igraph/drawing/cairo/edge.py index bf07ed316..7785622dc 100644 --- a/src/igraph/drawing/cairo/edge.py +++ b/src/igraph/drawing/cairo/edge.py @@ -105,8 +105,8 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex): if edge.curved: (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position aux1, aux2 = get_bezier_control_points_for_curved_edge( - x1, y1, x2, y2, edge.curved, - ) + x1, y1, x2, y2, edge.curved, + ) ctx.curve_to(aux1[0], aux1[1], aux2[0], aux2[1], *dest_vertex.position) else: ctx.line_to(*dest_vertex.position) @@ -134,7 +134,9 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): if edge.curved: # Calculate the curve - aux1, aux2 = get_bezier_control_points_for_curved_edge(x1, x2, y1, y2, edge.curved) + aux1, aux2 = get_bezier_control_points_for_curved_edge( + x1, y1, x2, y2, edge.curved + ) # Coordinates of the control points of the Bezier curve xc1, yc1 = aux1 @@ -172,15 +174,8 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): ), (aux_points[0][1] - aux_points[1][1]) # Recalculate the curve such that it lands on the base of the arrow triangle - aux1 = (2 * x_src + x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( - y_arrow_mid - y_src - ), (2 * y_src + y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( - x_arrow_mid - x_src - ) - aux2 = (x_src + 2 * x_arrow_mid) / 3.0 - edge.curved * 0.5 * ( - y_arrow_mid - y_src - ), (y_src + 2 * y_arrow_mid) / 3.0 + edge.curved * 0.5 * ( - x_arrow_mid - x_src + aux1, aux2 = get_bezier_control_points_for_curved_edge( + x1, y1, x_arrow_mid, y_arrow_mid, edge.curved ) # Offset the second control point (aux2) such that it falls precisely @@ -228,6 +223,7 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex): x_arrow_mid, y_arrow_mid = (aux_points[0][0] + aux_points[1][0]) / 2.0, ( aux_points[0][1] + aux_points[1][1] ) / 2.0 + # Draw the line ctx.line_to(x_arrow_mid, y_arrow_mid) diff --git a/src/igraph/drawing/utils.py b/src/igraph/drawing/utils.py index d49c86dcd..7519917f4 100644 --- a/src/igraph/drawing/utils.py +++ b/src/igraph/drawing/utils.py @@ -581,14 +581,14 @@ def get_bezier_control_points_for_curved_edge(x1, y1, x2, y2, curvature): """Helper function that calculates the Bezier control points for a curved edge that goes from (x1, y1) to (x2, y2). """ - aux1 = (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - 2 * y1 + y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) - - aux2 = (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), ( - y1 + 2 * y2 - ) / 3.0 + curvature * 0.5 * (x2 - x1) - + aux1 = ( + (2 * x1 + x2) / 3.0 - curvature * 0.5 * (y2 - y1), + (2 * y1 + y2) / 3.0 + curvature * 0.5 * (x2 - x1) + ) + aux2 = ( + (x1 + 2 * x2) / 3.0 - curvature * 0.5 * (y2 - y1), + (y1 + 2 * y2) / 3.0 + curvature * 0.5 * (x2 - x1) + ) return aux1, aux2 diff --git a/tests/drawing/cairo/baseline_images/graph_with_curved_edges.png b/tests/drawing/cairo/baseline_images/graph_with_curved_edges.png new file mode 100644 index 0000000000000000000000000000000000000000..68846cc94129eddb9bf2f60aed2f88bf9309057a GIT binary patch literal 58459 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

    f} zky5$(VB@`DZuI`0ZyZeI2mpj*Y2GJE#&({a&yW}%9nB>3~fY@8bN*)JO@IrfC@%HWbeB}9k zqn}ghxgLv}fSGY#J6yT!18j&aa{-i%S<70L;Svy)C3|F$iCBg@@0bIAtB}EK5{80K!+%I$9r`wd$08?&jxd%u1+a| zUzJJ=dH{{|X3%>ltbJ=tKUs*_to)trumeDSbUP_*%7*J_!6oF+%*>c|nclWDfCpT< zy~O$XLmD13uW13D53rUTu8PXPdvVEFBGPo!`+t-Ql7pjZHf=)rTb}!Z`C6pO6AO4o zGjnqX{r~LB_zoN>hKUeXxsSK6Nc%Q-0dN7&!cCAQ&y6Xlk;l3nJ0m%2m}_ZmeJR&+ z>mcXg)MhPE{^Adr1ZoM02|qC@!}1EK<9h*N2g*hxQmZT7P}SMlSzrIWZ;(5D2&3j3 zOaE2^G9i{V|9IcbyG?pxoAlN1zCd+yBv%gu>I5=n9WAJ&P)Lo*Adc2~X<7rU`$(x= zkY<@AObTFs2%u};XiVjG{vlRcv88H0dw;~2yRFc({!5CX2qU8&vkvq z+?*?K&GWw9ascAO!WcmIf&<<$@_-aEC|bdZ9I}+6NgL78uY8BL;Kh z;}f1vs46SpsWFAo)|kC1rp6f_@E<^7g!wAiOmc8x&CEP7xH_j};LSNTJIg|~ZXgKC z)I|WVcANJC#E3YGoOcCJOOl0W8DX+#rOONaiN2LnTa3W0M(jV|!PfrD$2>PH%kJ8>L-}MYqtF7<{ATcI z!pH6S93asF?LU%Ld&m&{g3TOKZLq@`BWxdpwpVpY!s;6dFiMc#& zvWK!;8tMJne)3d+*I_4h1O&uLuV%4so@64EONzzJK@bs_tEehiZIVNLQIM8Ypmo*h}OWAn{jAZ^nb|7(VB!E8Ov$gmG0q$*^k^c7?S-gxjX(qUK@p*nATG+eI?6C3XcCO3vfO8E8d z=}Z!_Q_!-7o=Ohui%hfu4hGEUtusrJI!Y`%SXkcwSn|7kCPj7K>Q@lqqvV&8dXt?U zHdZ0-oDM_;MEsl0|J}*-D4PB*$WTiOC_GM%>wwvj~|otTE;I}#S5@h`liGx z@h05u)Y-gKQUsw)GcyZiI%p-(g98IF({y<>V?aKiVIVRF2M6I5Neo+f%$SP?$d~a6 z2>hO&?sH>L+_n1J)X(tT!!%lU0ulm(xc1Hp<1N{k`hS;}zPdPx|GVKepcV0@-b2Rw z&s}4BzrY%eYu8>t$UE|cJbIzuN$xAfb@8Q1NlCEN9q9WyW_W>`e9ym$!sM;Tz(*0q z*DKO{Ua6H8UhCTs>Fb1EB2dXLJCPIA0oFspGhnb+NN5s8vAQbZ&03Q2&(qRs0K{L^ zT)E!hkx9lv49H9=jM-RXh=ZSw4(lCr_G~Qg;GwoYU-nZ@JyEtg^R8aImdr@%y`YSM z-h`iR$tF0p^9(1(o@+@vi8Xzxbub?oup~z+R9+SO?3>bLVX+=8e?Gpu?Br^7$X-5M zh^Q$*Mjjm%b$G|O&6FX%m(fv(!j}y-x4MfLqEm1qY;>2|vr!1?8yc$4O<76ONRL$5 z6RC=yQC!Y$cRt+E+^nA7e0WD)ucrSiO$(J% zcl&=2gU17f)^#ObEHyw<{wfx{ehnIPT#upEgkk6FYmeX_{da_%Tc~GZqT#3Ljd)B@ zBaSaI8#2J@OH=!RTR1%u+C+Y$lAJ zy1Bx!FJApFo3OfrYr&-10tCSoN$mVE%4Mq&F+9t24-dp~V9O0(GBG-@Ym^x;$H_dQ zROF4|BEwhK?nhrAw76LRTw9FrC(MNB&+nX8{DJ)s0p*b%lFzmf5C?_yNdY;Zjf#Ac zzrK|hx=!_G8&y2L^n{$aOaWAQI7l~e|8~jVv113mWW}RB_7J&)m2-@QjTEohz;1!D z%ycw$*F`ufp5!(ON*%=D~JE6~n{BSn&ogk#XZI439vdQecZmsceZ?Hn+2D zFy#sHtsD$|4#XA?N-i!g^{XeI1ImMirB|xcP>413)C;XTQ!)_M_~u8+f{((CLjrk- zvd^fL0sqg{Igme$1UkI7pLSyom6oS-HkLcE_9Rru$NYYlJN(`I_h9+`*YO)r13Ft> z6$2hUNl?oE* zc|M$qB5HR;%@d{Am*^{y$22U%jd_le2gDofp_frH1Sr;4=rn>=zODZqM3^Ys<+c1LkLJ0^!6YL0%g24FJpL*cns7S05-VO>%w9!Mx8x;kkRbmhKCm1-fWh?Q1 zh5_*9`Uf@HtDkj*^^oyN7>-zF6@%!Ho)`xXh{}{aeE7DeCb&m*{BiA06#TlEXY;YI zpnp~Oj9WD22%u8cG{?rI8t>%~ zu_OoYWMXgw-kC7{9$O^Fd05c*oSua~&LvZPzHvdFj>5xG{rTill`fi_}o0uA) zH$)^ieSITG*%%3?8`tJu&OmW|mh-;EpuU#Y(BNRz&w?ExzFQd>gg|*~DgC%kAXf)t zPYT|l1Civ7W?*)p+$nbC$m=mC;iH5FfKWc;C+3lV*xp1>Ro;j#IeWkP%=bq_;spIt z_A_!R!*gJLBHXe*s%^$=h?pCg%?rMIK|`#}b%`>GB(Rx~NP6{31U9Px$TL2WJxD9@ zk{~H|kEm0_W@V?{5|2MjkBMYX44(pqDNoh-j(VJ&%ko*W!e~Z4&${;CanMlVW_n@S zA}JA=qMF8o{xrIZ@kU;uH?#yw0A>T|gqZ;~7Ys-c?Cpe^9@h_`qfkR2UE}SzkE>I3 zR(}0D4@i;#nAq7XDk{)+0*=GYmZDtmP@x22|9Rh}5|t7!Qw6Y&(3Nj*=0{fMIWOwz z{U_U)`XZdcUXf4QT!dz9EV_8P@Yx$rlxpLPi%5MfsS1m`l}4r{8>ii~^bkgxMbaI> z_H0V(_U-FuXR}I{W;Y!y6$n4Ws$s&Ojf!;s(DjYnBO{tE&6~$2Z8mUOJ^sWaN4G=f znEP)FmKD*}`^~IVIjH1yYQ>gHGir75lhom zoP&K^{c%vEq89g{<4$sgKi}U4SB;FsN_p4unm$y@li|8g1g^ak}ol(oGQ9)tq;MWd=wFgTK zg-L0ltX&}5p|Gu-y)m@`YScTa#dV6iO~X^ok888l63RbCi%G!)6Wfg_k5xHl<^0xT zS3culV}t79V%qAT4VxaA2pVD$m8V`e+PcR-Y+tevQooK%sQzHvuJ5}E`S^ob$RuKGswvwOhrz*?2kCJFgsRj zLy|?`6m5~gm`z$J(H*OrI~U+0(fWyT%a-#0|HloRUxwETw`JWwb+fJM5S)aT)X0gg zvMuU|dmlEL8+gr}D0ndT)(T=pk0qzP9P-zU8heS<5zT)8g@xsdnF-~t&3^uGe)fci zX!hf;vJICD9(=B(i#o~uwZLa3;;^<@j(QHYTYH!H;PtgFe-XW$(E6{@d)f{z~fZuE-_eXSP^M$x%2Wx0so+Y$I{H8 zfqU>g^*+QG#CV&TCg74_snZC613(p+f-vJk`;~4G>_JKy9~gK)TS|BYNkt;?j$NMX zLjn#1WgdS(dMGaE4eS6xDxxOA{pbEXQF-gVrsn3PG_=$1;LPkSp~;qb&LjIBKt(K% zqztn8b7T44@b1(3yp@YbMC8@jopb~=p5UOim72`|4!cF7+V*f)?6LKUTgBwhq|L!O72|#BMycfjJb z98kp36k2f1hE4G|5U@-yE9nx{2c+r))4c*~2uKEr0E#%0+Z(+%rmMrJ<mu!#C zBFnGgdayjUi(0Cgr=m|6jKx917)u1V1IUoM)&rzaAd1k?92QP8!4N}=<^};IGM&0@ zUcXzlw9pmOU zMgT{vX|!j!14y1 z)5O(;d|O|6xc<09SF%G;d=eZUB*4>CQJv-7{^&XN>cxxj=EW`KE(Ey1X%-WUs(6QK z3MgiH#yzkvc0&eW6*%?STb$X&pp+mbfvCM=b=T1OH9c)(ZH;7IqHZfq08Kz|g1AYi zhg8KiWC$++k2ErHnL_>w4Aq!p^@}|{`j0Xrp`ytbIo7>o&GCqEgfaRhHVOpDZDD0~ zMI%q!&*X0A;4*P(aq)2*vYdE5>Gmy;eBo@hH=<_l%{VXqJ9H>~+7Z8_IEDf#vTBU5 zBbw*=B7d)C85~R3KvfNZvW=x>@5R-35C^wMl1~-M(*($^X2bi4#0iMcHQSpE5TW)? zOeBVfm#30(Ng)o=H0ZlOE}~}dGEehX?DiTBxGaW-ZoV5u#fA1X1Ncr-A>^mo@XE)> z!4Q6*dQ*wl%EH3%NX!Mo1d-$V+`ZkI7ZjHR2SUwPqx(G6&<8-D`tjpk>PMXJ5t` zd~$=|_0x(gV%R+%IFKZapE$CY`eDl^!BzR~HBs^LJ0rKVAU?Jq{>N)3k80dfO-2R~x* zLIVlD6-k_(La7nV$zezPf(Jc@Pmb3$H|G`>-nUX*IS7v~q;{*^J6}NnPLT@z*eOf@ z!|+BKE0ScW0GO}D50RS`LT7h8L9N5&YtN{qNteEza7YivwSZ03+#OWU*dAr>cOQug=8j>IbQibpmJz zm8)~EKeFMKcNiIAhS(T)Mv}oV!oC@h1Yz=c2Ng0}V*JG+A{ zA#4O_qAJe+_K%wzxB6x%rnU6+%}$~BLi(SvY$~l+UG_*>pT2P-qoC{!d^docEjzW9 zG={Bicjn!yL3;w^K*|78y_`bsFXKCONZ{JkRUrvM!Ub0(kob(cn>*hbAL?2yjYM50 zU9efMqza<~nbF1i(fDkv(!lWW*?v}pS;trL8Aah(r8U=m&9@ZmXQ`%PCdQ~3MGpsp zv=KYz$;Wvku01E$ zF7rnNF7Q+nX#m%Q+GKh(r1tnzoEYMIIwoD%l7>_oKPV@oR}tM^*h2%S9pjZAhLBt zC1CU3t+;fD(hA!Jv<%;rL$8Rir>NH0=;6l{10W6|Jw#RDNZmPQWq8l-%TMgTMymxj z2--ox(qqQ}tS$a608VrB^C0Rv;HhI+w{NetxiBu%9|vv*pb8*$ZOYK0sqJHa&`M%F z!#lcVAS4%h&fBZ0G3U#pxB(s;ItSrBWXC^kw)_X(OL}^Fb&#c45mJi?Z3u&RirYR= zE$()Nxo<_#%eW|2S+;WJ##Azy>&8 zG=VA!w)!q?GRyo>TneTd6gt+tf6oi|W{0(J)$CK3 z0h1rCP^#Q6ki&Tsz$y3WD(mW3-++Y)OkB_@2XZ8U>)h=rIO-QxK=rLs0>+$;GRypRNTl;@)%j-%aOw?{LWm*=WM;_z94I<~I$)f_Uwk zHLnkl;Hm5zteIoq2=-7={Nn883T5a3Ag;T`BZaMJnNk$HN=f$b6< ztB~*DE%JuzfQG^fGJn}-U_PnI;u}(ss?)c=O>PEygYYd2%{*-kJ}8yJX(Ra_4Y^i~ z2Wo)2;?Hp=lx6uNKjiIu&lG^r8}dS3T znFL3UY}ySK7=4gy%2~-v;sy^x*}s)v0~k6hZJp@LKF*GUj+%Y=1nz(vg=5zgefI6G8O?g3Cz- z1)tO9R~n+l#1i?L!4}cj$E>E2%971{Qa-f4TC3yByQ_aARIk+DW|JBFdcw>Jhx^X5 zG{p1Yxw}&GBD`nLWo%S+_wKu(teZJWmU2V!EA!03p;bs3?0|#Y*_Gc{!k}CA3b}65 zIn=*#NuQM|*-fnihJ7f}0H;n=rM06|_yW0}qK#HOckVEIFys8IpLR%fTw%yHo5Z=mh#gDuuH;7tQbcmw8&4G?2HN~5EwK6_g?AXy3c)#ev88Q0; z&)(P9x;wI$clO9s_6BV`@UJj`3yk?2K^zOWmM*@{6cfAn{_bGnbE?dcQ-rN}mo@yN z!Nhx41um`&0GT#zf*@f|eDz&m;Oh3E-*Z+Ly`fafy)dEJQCJS4b=3;i501^SgQ@{p zxUEB6czf1v)91xY?V;PlNjTzL2;}4qGI;AWwJK{*VXjSPFU|Em!xaj-nGI&GMc4R*?ee^)Epu$Ertyf!5}^pL#0E{7w7DDG-{j6+@>#NDdND+ zeu|w|-=CEV6E-8hQ~zkuv87e!B)kHNU=r=o9zpR_wwC_;15&+gRMpa&t3Ns+06Pot z_x-~VP?jFleNy7>rF`*o%#$Z2{x_-i@8MDBSvbL$d(CBKsP-UfFqFS>0V}Mr2s?<( zf5yH>MBKk09y|P8ZQ=KbxB&0v*>45dNo{sUgoQzWcS;T--?djT>2In%6pI+VS6c^Wz7T8}?Z_VRYUxpra~v-`~0cIR#{df+qA1Snen*5WbD{qrM2 z1s-cp`gGGaZ>WIO2~EG{sZjJsXA!KE=CC>vXeWh$zX2%77XSTKt0Fb^4iwaJ3E4+Y z@PfSp9&FV3yWWNY)X01EC)Oe!@h=Wi9Q9{p~lp+!pYErv!4=xS+4zTpZJ8kME(p(`aeuV4a=3J8l$T`wi-a&h!pU_{UaJRD2JCVcUU5;c|K zvi&KXVb1Og{DT0UflG2qUOtxd%Hdd~6Q7ou6lM0jaxJsJdbM%5uK3D}C9lmmc{j!r z_%bl}F&ci4!;>^SO1z3ravz$`DHnqvH?yjvLu=tdk?0x?8=K7eLueccDq0-;q2-29W8^Bi z_-k<)B9ah9&IRa#YitE(jn&{nA%1KkzrUI%!ac_p%3P%lXg$_BEq#c^ zOTl7_WcRV_GVVZ|V+2Jfz{Cr7qzK}kg;#+B*EFtdcDM~A4{Jn%f%fkQMb-8xxa;`>2!)RIi}B^eO3p2eatMu(w-kINrh@EA$Fl`=IFC7o{RpT;4Lwcr5Re0|x!s^z?z zO?n3-fi2W?darO4h2~q+#K&9Hz{?4l4&r|1)w!#03g3F%qvstnIAED<9FakHN(4kb z5T8D2CUvOa-2c<%$SjE@a_eNy9?bPai&~Gq_nVOpr&c5ONC2NOD(X}^Ke_V*B^UtE z>|BDV@bRbBo1#HTs`t{Ax?_{*gz+lf0+lAkbpB~5 zcVNl`U!V`A^+ei(0)t>T2U%l$HlxUoXTe928bS65TcR{Ig_Lwb?fr%*yF%VIoz;gf z*yvq?kG+b8Bn>Y11aWfs{JpmPClfCd?Vau_C@Miv6yWdA%)%ljE45?sR{NRy%NF zlikHIc`yj9UfyGw9)V|}Y1_p`o@#m(3IXYjzza+kn zfKk9nz@y-6hVU3%3zezW?8h-0B{+YmH{6ebng6WW5>#EK6n1_HSxpaXBjJO0#M$)k zP=>+-!a|)a|Kre5R}!__Gqe_vK@0KZ?CqbF#Rbk%!CrA3>F4GRYa=az0-}!qI%x6! zdtyBhz`1wtPWum4FYLZ4PP+SbJDIXUsljaDZ+jG|;DtB437x6&PKFp*mg8~b{DEsFW?``K>NLP!TM zU98;yWX3o-*bA#e&UXgXhtGxC&)|NGhJTWh_y6gYsRQ0360zwniB}K>?Q@e<@<5S=%Dq(o;N>6tGVv71CTS^O~I+qLUE z*e`1ABwDlL6BMMQqWW%N4$naF*nyY*I|xw4_U-%;H3%NwmI9Aw&{qJg+_)Xv#b=U& zh2!xc_(m8IqoC;N=!0UR6dWheA9(jlst0;ewGr@f$cc7?pGNx3@83VP%~5znPVNlq z;-{^g(%goydNqWg7>;F|8YHo80DV!@!9f)1pc6T{xS-Xo=PiKzFnshz5C=K`qtoO& zLqO*>+IA>mQ3c)wI+=MWFlms=yWx5iO*=Z`%)^P26O}m7TGVuU(^A*L(>@hejNT|h zdv;MAV4wmfgI>&)B;+ak^uDa5&TV`J+n#|E2eAkB|RN5_JQnN zv<^;9*h+|+iS9qs=w<$9r=k+h~hW`IV{+|Nw@nvZyoulf}#+7V&F}2 zZ|S#GwoPN?qJqDe`& zcZpn-d0@}Ma2akBu#)lJ`GC^*^xh_=2Qck%z(xirCw`~3OIXyQ+S&8Tm5v@Z6GkWkVlfi>63k_TiTO-m5Z zW(U2*mQZLbYTYIT3Tos!taKEO9x@G#DAfLasg5$StgJ8U11<_LmJj22|1jtzZ`^=C z*xS3L;WPsK;fK`0Cn1*j;YoHKilGSS^`x&Xob+4IJym-a6jX&J!e`!eg}rgThLck+ zBnPO{cId-H9Ile154YYXH8={X;}GzlthZ*8WB~8Y{nHY7N|d!|Ml1B+>hd5 zSSe%nlYTgdOx`!Rz`>|n`vinf=&XqU5+)y&{d8|R2rg51cQ^VT8;-lr7#`LJh#N)i}&%Dmyf$jAaTntA;iijJ$o z`6aAF>sjL9Q*LNTDqkJrXIj4QVv&*Yv9jXNS0yX1>;$@QuU+dW7?qDMe6I@&1+`zk ztE;;m7d*42tD@pjslyP> zJ}kr{S+qQ4K{)Xd5*-+AqSlNJA0Cwqa!`OA+3|c#SdGsK=sT>0#3z+^&ywrevQB7FQv z^-CPlh&MZtlkFAHh_){P$mO`Nhp>GC!Xc7@)1AgB&63%wxp9)0dnA zTwyUhjYeBXT_*v_JQn0E3a)_fs()9h4AjDcW`q&tyRvor_M$K4<%x3IpUlRl)+EcH zeE1@zU(2KqOLotc>vOZ4TpWTxz#q08l{}WJdfKtCXOLw_D@{-RO|sBLXV^Ij<@OS3FqYLmfaj8V)q@3YRrz6Ej<77W-1|$v2lhZ5!xM%g;aJ4YR+)^3~5%Di<5M>dh)INJ-piZf}3Ki)-q- z+=ZV;F#Eg1&MKv-GI&M@$59Mb^LTmvsjG{XwpRBK+Y+p%qgxxIOF8+2ss+3BtI4?p z4Na=#VJb7YBxz_EClc>D3Q1LzI+teB%^J4z?S5Qe_2=)r!>B{ARDuAhweA%Y|MM`J zLM~8F4z7srq)75f;W&ha&m_Qq&ZF6xJ9M_EV&iS5UK$)wvWSt|-hAV{ zjssk4j}5H)5+S=R8etI}9WZKWV9+^Y z-Bt`i&x0e!c^J{iS?Sz4{O`JT>yE_l#p#6Bp$RpzI5bd#V;(1};vlK8F!BC9!5ioD z$c9obBKTd1%LF!)tCA{o<*=ss?Lt?K5J8@q$w5KsL1X)~_Wp?0`MH)`H^1Gw8FSbS z%(V9?Wdh$wK&L5y0N5i?sRR{6;q2LK`|WU1!)!%mWoHM6i0Eh;n84umqHR5TOt(=p zu>=Lx=I1#VTS`+WYoF|;H0YKuU8zrTl<*BYo!y4@OhZt|^y{aW(F)B=-MUKt`rJQ` zb4Q+443d{0{<%Ep4SxnO6Wc4%VMhpD82l$D#>*IdsfGwMSgoI`Szf(5iS!t8m63%- z+qf-|z`oJ1G|kN%roVXn+sE!i283-3kJ+{Bs;EHShYz=`BplW>Y{L$IIM(xR)u8?P zuw9{IltB?zmd2A)TYIO@W@ggdx)rCVr}g&e`4}}m>DSC5Ka`{h;4g0?_7TUI&@&Q*xbAn#b@>}5J zJYE$I?O`?wc-OAMkDpU1{WCeAwWydFAOh&ofK(L5344Jp0?T96CXQ2;Q?by4Obah% zm@)laU<1GfAj3ZlrVv2NkwGJW*viQ{F+Q#jl4qtV*&7ltBC}y%0mpH4JVaMs+dTAd zG6kPzvGu&+lo(o~AaQqIx(%T;(gXAfK^gn2CO!@#`!v|AgNcV%bH|)4H2AqR3}pjIR@AS&)q zCX4v@&G;2KNhBS6^=i~R9b*=J#5_&I%`A505yiz-l$8GVN9-K$I%f2C9guh;q?K~J zr=04r>p0HfYYwNeji4X8xrK5_7cOQZBtj@)b+`e z_aI(XoXa7HCVz)_5urmk4BSSvd6ylHv42*5O6N4Z6*h=AuEMOhO9WD2(FnNVOJgGx zFofn3SU}z* z^~g8!N{=2v8fg+qgl$4)FVfRt1q6Be_~`ET=Qa@fy?#B{ke^h>P747E5-O}*U#gBE zd_=bfOr6u#w~eD=P~=?NnbC;HZ|*d80kSpwr+50T9dUY&2@jDu4TLx!eH{ zslUUY_ipe@MoXQl^LRs89r4z|(}x>V%wrNu(kdZdTb`SG1QVm6tQ$^DbU_i3kuYc8 z!omU=S~&cSz<~pi_wFHv-4K{YC-R!>rNKPHaH6_oWxaX!6=d7%*R6x|L3&!65hIxs ztQO8;_2+>CJ}fDUT_DwxQLk8NC^k~F2*PgU{i%H{}D7zq^$@H3hLT1q$o$+~%X7UDqdLr6To>9cBi0CV z@FuPwLqkX*ZjOC$q@+aJLWiy$NO0CytR^R|*lDF9904HHCMaJD-ZSXsfnR<(=W%Ho z!on5%^0z{#O&!_T67aqLQR*wi4&%CISMZ4eir{`w7kejUjj$WM?u~x}AI7uUllKjP z4p44|=O%viKmY)W2pjxJ>)j;ydQf5f0t6ySKpvp27;m44QWf+eNN3vu`>9X7C<6r& zSv#5|Fb;%+cD7GY5dGS3xS5jIb%I06RW|iASVZ*J6$68V1m6S#g(J7(NI5Em7$8g; zm6*~5RRBv{!bs4vVI#Gkt7>j;^QhB6LmxPQIE{$HfHs_Pn4{VJbxjDCFzp<|a;h;k z-mZ;$Qe|a7P->tz9o0CPB2P;o3d}r+#o$Dp9f}^Bz{Y~coax_~-9!?ejOrHrG?8N( za=3vc4FcRI8k)CKoH=xC!@#ksEWwNc`Rhd}Og1#K^mp#qaeID} zEZB{kkl#Z*ijbi#@FTn^kQF&Q<8~)*tQnC(`VHrI2lQ#K6Q>dt7vILn2*z-Q*y{Yh zD8NFjZcuG(qcgzX4zL*C3*823E3&0F(`2leLs*JLy|2%2%mRzAE;>Pg?Ev?-f9uCZ zEVSqgA%5skxe#wiC77ky8^ILA@{;9;=0YfqgOkaHZsr}?NFK1j3*AJ~Cdmf|nXTv~ z(b1ER2@2GxJkDdgkGM1hTYH2+Ree)h>tTd~j?`hW zL`302npAwjOA%Hb_WwAw| z_$LGUpb3kLq8=8Edo?lHt#Jsb`~hz6dk-GmR+q&^lj0DQL%1pjt#mN58LZI2*+JJh zM15oq?a|Xf!Hl_oAD!`xUSIQr3mM|o7ptvM952FzA~#o5qX|_G#ICSxzNKDPzL6&5 zIcE7~a4GPWF$*klkd28wthbn9uUJPoDrA2B-((l(I(= zCp${U%Oyh`)%xWNOu@c1H=jLo=J$d~9LRU1`ICnSBr-;EKaAE%?q z;Kdb1rrd6Ea3LlX&%Z`Q*01K4-a z*QX0@(H6JdkBh^YIS-r&wFB@slybH+qK7hw@s4OqrKi^kceXb^E6Y_*e39-$ja*pT z3{GWdXCpw^zmZ5hgw%5Rvw8OHLG#9@C9iB`V}Q5OsRYfNjV>m4U0;*_2jM1y4VSTY zQqx972rH!jc|$`(MCMS5Azm-EwKXyd|L?zbIsSOvLaok}EObE~MJ`#7ADfDITsAcY z4rhkJh-ku9DnXc<&ilOKOeA7^K%Zzs1j}LAvI1MFE8$>ejR_BLl0N|zJ!~kU)4R6k z9L{;-OvjcC5ICWra?UYQQ~MIW`!whvxfV^_^^e8WWUmKMB3nbufk6f*w&ALq%<;;E zEChbSw#`@@F>Wg&cVO7la>>vLAWA^-)g_fWQUQSm>CFztH^77=v7KQQ>sc;?9p4do z5xW?4x<7l*oj_+H1X2#iNLlj4CXZVX92x_7^zAett)-Qqt4mjETjtzUB+gK`TMKVQo;w*w>uFXvHio0S#BzIaJ#q zdv>1aI>5v8E}nLyw4BdgAyzOb;2KjOm5xlx%F;QCUcAXrQc_d9pzbvKqXw`@>4V|)j0~x3 zz3XC?P$UbBjviEgdtx13m+{C^nt)%3IWPd>!-P=a?_XcExkr;N{NLV}P`{FX?PAw9 z))95&fz8DTMmb|D^@!7ILjPid<^*U)4Q2 z|C^0g+yCblzW;0N%pYp*zPEo0NhKvJ6d?(v5T%qP5=rKULQ+j~vix?UYi0;j6SVow=IE%P*?oL59d+3uDzVPPM+`#d&{PhRdwrHM&x zZJn%%lo;dWhzxHThyYHFeLb+!*eA0uC;|on85Q&940bhFjg;89y>+mIg3L>$>0N6V z^?x;x({8t3TQOQxjmo}3Ef|7;AV zIV3YAWav_cSR45zz1iFvV_P}L^3q5vyPbXD|HDpdM=jq`xlny!dAZ_fB9nLTS!SlM zu37EPcN%JvzjLSdj?BsYtohQVX9OnksatPn+wFh->Y3hf-hEotyx9lG`{oB6bQXtn zqVE4{v8eI^(SUgbv<-j%?kik2G&25l|Lsle&Gdk=|I220lfKCuOJip0NM&y~uDq1~ z?dJ}TzPEfwfXpJL38E$Y zg(!w6|=^LDTd4J4b|CIP7CS zPR~ObYtJA7@b)>9g@9$#W9}uo6Np)tB_sm<{0ns^x9H@^`5iMm{-vRgTy!ztKd>}@ zW8@*}*Hz`8jt=(gU)5aQ^C_v+Ig3s9fwD(Te>*gwa99(+!Q9pb)Rsqdd5;^Wu=*Ap zjEN#nOYt7#K&M)i{MAN$Kkq`8hUbMB?=b9{DkR7{NJ>RA=$>#sO0 zShYi8!1k3%wXggoQ3rvVqGMv}+ZY#=iyv6)s0DoYPCT=;{xugaBsPONnCUQMMr2)& zAl$M+@7c3A&d#V3 zWlaz-knaKN>T36JK>)DV|0|e`$10FZ4gdi8#K>m|yv56w)i*NYJU*_t*h^Q(qR!@< zn&0)qhwuFU`M2Q1pbWnmg*@7%jW|zx{?SgnS$%f$G6@rxBhT_~sKZnZQ&_3-9#rM) z>s#&GmOGz;vOju8$#eD=Fc@+kahYF^?tRDh?TAu6lb=n&0=)Xso`p+p<=;J^J3P^J z#R}J)ux)GCt{5ftu!n?(!@2V6MH3zlGoUuTBn6pFYub%(IDV8FFyNW$j=cHYsevxIW;nYfL>6>!-WqRQ^137y6PL! zw23bd*o;%oj8HJSVc(}zL_0ehY*J=tWxJ>aRSs8e{j^$BeAEcn#Vh{EPEUK0e?@yz zkrqHimtUrkb1}{9>+HF^la5`wq~~K*{N`zT`S$2Lo-WQbkh{3K4Wn^eLAH3lg8tO0 zn${14Jq#g3_`L*t@Greb#N#z>!m_^W3Ck#?xqnDJaa{mTk~7p;hhc`LrFEC=3#|t; z>ilgUG-|6I^gemO+gLf=#{A0hg8VolWnEiK?5)%^z4^w-dXI;NL8%7W9|QonkOl ztWa`WbMaydzMz%mXQx-Ml#_cqMUbK6xhz^5|1@NUY!G=U30W0S4zgqc9aB zG8GFesTEdseb?|w$>0sVx*i1w4^R_9m`ze``X7&hT3#K_(z^f_3T#4lS{S`rcgvfr zkNv1$($1d@P2N5a*<4z8*ASzu-Wuw$Vu>VZ3>Fz`v|sVIH~A;%2|%PUa3I!JBe$EA zktnfU`y+c8IPe}eO>A5_aSwg{Ym86C0RXOfdJMBZ8$Ko{{R8D+)xQtd%|vvrAAd-azD^AYM8$3%c7z`XK!yw2?-5_ zrObisO;S+MT!r-L{e2yg-cQ8e8)GSWpLL=go#bZwNUFe0Bh_S11uz^@lXi|26CKSW ztw`F=Mnni>FYV{ehIY)TgAh%5eQl@SM;^iFzE6ClBs7LP0rF@!BAar$EQTdfQ){aN zgeJKO(B!VrKDWwr@7^{zCJIwz?**+{K0pbgKQ;7=j>iX2{(;?+$FY8Tw-)$@cpG@) zj}9%*WGu^`(C!p)o4L}%!^4HSY%f|Dnnit|pc#J{6;;XYJY`3*U)Gxdz9wx?Bbt}tWYK|SN@7eL-31wT*0+EKn}tnTz0q?ddsJ$%}sPET8sS$35Vr{V~M}UkIL9n0tIQzb2`t zWNB;bMKVn9C^y`}g9l@OQOeTK=!$HHJmKpjNCFTk;KD}=?wbCB7r?)6p`9EkH$uQeSNNGz@)D%O-)28zV#tk z3Pi+u59gkFVkcx;UcGwt{P{tbR6&l9n~eJ#mK_?0Y3a0zN3~DX*49Jd2LR!_WmL0> zb}Gck5_%v2h-`hm(&Z@TC;|)LvsCu83>BLGBzj3ZR&U!@LzeI$FB}RlEzOG_1|mdq z9?w_G80WiEYVTybni?9s2RS4Agmt#l5-aPK=JM#Mu?in7zXMjtIOj4b2z`YRq3$e4U_Z1+*4g{Y7C80r#+g1(U zu(@jC?*+@(R7nd2ZRp(Z@d2>QVhJC-FNC|)D^>Wc!wN)%g@w^4$+B^U@Rf0O|NWct z$5&$DzZGa62^;(U`xL$nq0Jf0<5KAysg>S~NG(R9SXNdBU~~WVt&hS(Ia%4CzkX3( z_GzUR(pQlrmQe|e(j>M$tA31ziK7O`a^=d%sCLnhBJFm4`$Jn%e&JNH_C%*|u5SDd zXcA|V0RsnO{!r;k6iD|#CnP0?JX$%-=*+$35yB*w zEccaC`aMlNZozP9b#_f4Cp{_!?oSffCob--xmqCbHHOxJcI|Gf(Sl+*v3tp~Wti^h zbA>Vfb;hpAf6~R@s}R6wdggf2aCsMGZt13rw}nt&Jk{Axvhp|a+AMB`u)%co%9T4G zJ|v=-5X(6+@Jx{p2M1F*3u|=m0FYyq3T1viJp6TaJ+%*9CzuN`(9(?@rHJP3k)ak{ zKe?MWAQy~UAlMIvC-e%ZB|DZ)JF&ZGo9v@mdgrQt`~V=(B5lg$vU>Fem+7kIP7kQL zT{LjB&lzzb-cnpz{Y0-pfTqI2ZP}&P?_8 z5xlqS>&a@><_2K%A~j^nF&E{y+#kY9BvRYTz1*C47+GY%Y_+7M5q>b7i&n4RMnFT% z7FmB|$qzmQ%mVUFIG3q!B^6cdjyg3`v1@5+Le?NOLt|P?r9SujDtav-UTB#A?`8Aif8+8`j+Mpc5d5{$Pg2-&0x~SPoWz1=aanW zCk2cBW=e)yJO*^2w_%$J-N`In7lL$2=eWP0{t^|W3o5^TTY^7Q6YH7@URWF7N7(v< zGb#f*uv4O-*EUq9Q9?cT;AKcl!quu3D`VAxI z(Z##m1Kb9IgD2l=u%5Q(m#Vt@W~xIJSj+Psi73Xhg)U=U3-)Se8?iajzOC;%5Xo#H z!sf$W9QHGfqWZWi4p<==j+sImM~Z2=TyD@={F&l@E_2;3m$~`5xeL%l zBEfy84yBh4M<%o+EJ|CpWJz;lqt)WYHS^L*GpO1K_dlZ#`F2iieZ55`JEjjl&OD<* z^74@3+Z-LI)6FeCjEN6)f#WCKy)hj$fmnvJ-)`$THvHLeHqk||t{LL6)+|_*mi;^6 z;3w`e?j@d2sDaz~SA9gMsK*-b18~4I_LY>(`1+Hrfw%VTl1@9We?Sg39km4!!gdT> z&#^SJlLIj5OYBgFP^!LZQ@rg_KK{7(z;gS&w(4Kl9M z&*5fd+HcK^z=SkU<#DQ4U)rho&29YC`ues0`SV`&AOF61b1k+BE@7O7+N5vKk2gJj z9PaUbMQ&I!iwTCHBGwWU!14f$218EjYi2&XI{mll(3vxJBZCauU)>BkE%9h)#>bD36n>J0G?b<=?U%P#q7g(r+SvY5x@alM zBn@ee+?a@duwF|_F(8x^%Q~h_8~UG=@z7jrG=#Dp62m^(jQGhcD$J=~=s60~t)3?5 zDvdqESt($tM*2~%A!>|QQSqMf+^+F}sARJ-e%+Lz4&A4l70gjw@6kbIs=j{RZA@@h z>ERBg$X=?8p4JHWj^Zduf#NE?=Fp(f(7)Wdq*{S|3{EsL*k8Bj3^yL#-t@vkT{X4q z2`RPJn3@|XNt;C#^nLrTRY5_k`uDI{8KsAo!~V;ssN1Z z`H^`=10*V5oFxJ1=TP=&&7wC2tu7HG6K5=)42W#_ASyUGz;NIh$yu{f+h6^K2`1_j zsYvY-S}(;R0@2p?zJFncE#Et~wIW*~V8Z&NH{M3XEVdhdmC{*bS87PeGW%R@#bYcj zf&iinSsq@n(Sf|TyS1&6%YdFerK0BZ>?Z-rCQrsV?BJ+n0=d|tUUphov`+NN3kXzK zGTG$b(SA`vLq0(0j0naOs#V^;9aa#G;`GS~TY$YjJf+}s`%M`+8_`!)DOou$Qo(`R9I9rM=j_> zH|>kH7w-|Si1kv%cNSI2E)~0y5vU+&6PM8NHpCsOq3-P@pDdJf08Kl#2j1_6{g~y} z9HYR6VtQ>6$Auz1ago1rhCyaS1`nom0)>_N>=_>26ylGV3X4=eJK2!^5yU z!9KMnIDG>d=(;u!fj5OoZ#jDV-uU}j-8D*hEZOJ7xeGA-RL^guIFuKYf8_;zU>pAzOr!t|6Y$)o1mDBKMZzD{ zu=<}rA9!#TIWkQWF^POcw)8GnS1!%Ho#2<)S=Sa(#{?$wBIBgBl+UeZ8CLb}n+~VE zOjEm|#{NW%gX8KRd1KrIWb6Vn*WH{uZ+gtlK`k}*-DYYg3D>SkjvZHGvwh2!JzNCD zSB`c`*G{ag_TdejJM0AoHr|x&$$&YIpn<{af0#=6UqQkUL#Z8*MIMc8C8S7?$)Pbr zqCq(?&j~3Y=ECmN9ydIR>wG05kh8KAIidH!(Y7orsBrItTGv6R^qi?IAClhXe!tW^ z1bH24S&Cc|b7X~%co<5z)?@ueoEplcHGfWyoUQxW<<+#BQo+y{?Mtdp*@TnIIDUU zgt*&EN;XzEM?U=Ng!J|Bvu(1nG`Cl6>Ht(Q8qg*R=0iBZjzDti)C5`*X#%6j`b5lE z(A+C1YyaP08=2FGBnnaj0F2l6gZJ%7HVd(M%)WkIw$%N>rOJy_1ca101bG$SejL4|pfy^cUpiNu8I zb;=AhBU7SQojG-R*vShQh5)1$6wI#VqlQO4nD;t2>^2P|Xoe>()qX2n+L)xI_w9L+ z*$P^>ntsl|njZ}HmghF($?^jS_E>zUlc4p1Fkivhi&M)fWXW2;UPh23w0R=qe96=Y zs@Tt-_59vfq)H|wky_5VsV>*){H1zT`0#o`HCvX|YKvPPaqHGrpzpq-I~OiaU6U;@ z1;;Bge(f;(QxOqeoh7<{Cr{t{!9~T{FUc7RTZ2~>i~=4I=TgmFydn##u_?e*aCrYC zI0;PD(W!m00WBR14?v@x;(_fdy1ooOJM>13xctkjby;Ie%Z}F8L<63ylk|WUc6Mvy zg!55^bt{xjM38pFP}F(WkN2;%v~<8ilYF!G(|$pf8$>asG94XPj0+)yWLY_ zOQVtL&}-|gDJKw;mwA6aRg1c!hGf?yL&RqQH1gy~!Q+D&R?`hmU$I_A% z|Mc0jum{)&j4f=#<{uFr6$s@r8ghkA>U2RC{t~%l(1>!OGrWhO4iro8F2e$u=qT0D zu>L6uz1g(-u>_njXX20@r+S)%`+(ZSgLN2bP zgpq1O7cO$S&hQ*BP8Zx%*8lz&v-Aqh9 z4U{42Hy*6(u*NIO7s8%q9?tq`$z6G%xIO`Uku4%ysN2Q!_J? z&zh>LW;cC-YXxZ+`ifdFQJ4ru;>h*yFU_bCOjUVn@|V{I1uisy;R#UpBFJ2%N|J@? z7Z4c89)5({dze?pa8mbA)g5Ne&cC=mCv|D-xN12Zs5ghEw@M+GZLqutQFE%87sBBwL8oe-l z>9KaWq@eC&npaw>^hkpPFQ-+sX)`njwRly?#wp*C`!H)Euf%O$l zfZSQ^Nx_%|^#T8bk3fG0!k_No**86xEw?OYjk#Ko*JB8dnlE3Tb_T<7AjISWy}xVg zxMfRLXHP-8(smsQF-R(35~2BFdN@(m3GY#^`-WpD>EL2pCMGsRI6{!V<778>W0IG* zmTn}N7{K1wO%s{y%;!S~eAP;wK3^+qpBX)7$EII0xrXu7NI29`6Xoku$FA-YKzB8ZyCn$k(2K{1~>aQ#755 ztz&sXpk^{`hB-g&jVz!zP>%$b5#rXLwHb@B)Gxq(<}Yt>(7t1%7Pdl7R&jc zSW`G9mfe7B$$7n<>%8jbpAQMy4MGGTr0xG*d-6ibSbdN65IDX5_7(RpcRFhvp^+PQ&aOH!H0@o<@e9y!!3D41REoNla&Y$uU*?X{c()AK!MnI(2v>>2_}RB zfCFfabr4bo=jq3>tbMVkspr_SBhH_HtM7HEPvm?PlZG>Ah8cQcGF~#vcw%S=n%Pgt ztM1)fYG#I$!=!VSQhR;oUYn?R?4rVHs8R+$*-e&PZe!!H-oatXn*B*PZw5qW@As>n zWvbToyX57B^(dUUrwrFWmvX2dvV8SwA@CVAXzIFW;$-HqszoV1r68z%BCq{34bUGy z9=)jpHTC=7DB9M3B|D}M)L&h3l@bTHI{Sl{QDEvNVV7r%*^dZP};S2E= zYYhP4?43Tn$jV9)5U;CHp1)aVo}66vojV!P(P=sIk)b0-%%+)KTB`Q7Tgf?9ib3FhP7fU}SIvW%6%Lr%*XFy6+k?({LZA`A z!`8v469(#9Qj+7CUTg}H+w2%Dhskv2yD zTh{jt4Sk(#DQ&UWT#$Ma+?$&4;(O!8y3Uz9R~XIUndZ#taCSO8`^rLf`qeShuq9U} z+2c;?STVNZ@hKrI;Cm0`O)E*pC(KI zQ5$yG@AH0Q$5lj0QEk*HZeZG)*Hi3<(N?M(;4MOyt$lTZ;xQ6A(BGqdtub+NJBdp~ zc%Er#n6ZVqIT5L!iTI%mv{k#gf$5j};gmlzMqchINpBZt&W0yvbJ~h+nfw4!YLU>1cHBQUdp{4qg3(=T$N z9}707di4>1`QTx_fzu_xva0GgZYJxF@Niwnp>FS!nSup-#|#6M6LC0S=Fx#v^S!-?%MV6_mJNWo-a1!|zr2!BUXq}MF{Ti3nWhM+2Cu8$p+BGEk@91_32NL{^Z?|Jk7Cgaba zHwaY1Yh@F>Qei*%_a86j{aLdZ6Br@_*8(MSW;INjlt57uW9FSxj~i`ua3F$tvW3mug0sD1{^1y0>d~m)S)Ew5b?Lir5xSp7si?$nEA+`Yw6D-0Ad|(i`^VLeuDQ&uii z8}+(wPhqrp-;A%eYNPS~TH2vC`1t$!wRE!pIJ(Zqu8&*6rL%`N!9|Pu2W5rPflA;p zE{aIGc5M`?6<}4l>~&5K-75^AdXt|&L09)8Ben&$Z*wNeenl)jD3vLlVqNDo;+!jVIm=+*{HJE3##kt0>`u--scBI|c^EdO8z?dH8cGv3FH8qu^Zmu-B z_WN?3f#3UEH)pAhiZh!@(U3ba3x8@0hwa-jl?EY#g1MwvH=V(lC|jDFA4#o>=)64B ztJ6p{-KEX`#Vmo?A^0EZyI+60qc8x3@dD#PVwl}`Y~6cr>M)bKq$PH8Wc~d{H&4;- zy=AlTb!ScTFVb{+U4+va05-xal`4|M^%+<4sf)46WKHn)s1@b0GG@DjjFlQ3)9;2d zwcc?@Hkz$JdoO4YGvUJlB-b~r9fyWDH#fKJ!g|_Ym;_{F)Ab@rw#RO|5*pax z)LEY15ipkO)9wq)$Bb1E{$A0tZp(xokv~G@hgwfNkx?#1WwdYKtPRfiTd<9h3{Z(7 z3O|Uw=*g670u&@$ku7ziF-WEO{9IS@NlDUDQnlIgn>*($Tb6VyIrNB?*6$fwGhXK9 zHFBQL+4mA`?k)WNfpf2MFyhAD;=8!*j6dGx*C)%d?A7IheZ`puezV7p`PpV9uG(KX z7zu<-{!oVufXr8qSdCI*3Ljk>a{&niV?F5{O;Vtce3ASg zJL2%D%4AUb_0x;yt}Xu)aeuy=jMQGwSEB@%6ll*Bq`t7zez>v?g{`x1blstY2P1aJ z9lCh&^B3o5B`K93`mP~blvRrd;n*nk+~2XJTc`!zZz8 z71pgov@`Y8K*1$Vj`L?RwV*9Gu2qDdExe-8=eFz{S$WSh5yH8KH(#|aKr%<~MZ|P3 zBg9(RB1V@Uy$E;LY2@{I!kHhlBRi(uYa1Gg==bJ`5x86xpOM@!aStDX0-N$~ePRch z+WNmcoMe5UAe-c-*~c}U5-@M~;>Cd>6=o`~#xqAw9^Kn=rI@!Q^%3uRsIDHo&i|?D z|K_LDe6wZ0n$nnS7kKCe@{Qg#?Ts7?6lQK@%*a4dKvF*Wb=P(H;#av%Yce2>@rhmNPEz`0R{wCt~m^ zxB5hev!HLEw5o^6^ARINTI;D`y6Ef>2!;?goC2H9PxdDr2s9~gc%C8RzCZTX58pq3 zxH;2MZ(DmcHn~NOX@HCo@7tFn+l3DvyruG;=&v`H_&VskGTtn9N>NrQ+gW98oytDr zGL^oF`3$>x`JzSZ9C!Qg=sL$Dd696mc5kiQd}TK#BJiX0FB+xB#pQ2*b*=>?7X7^$ ziQ&uqln$HT8#T|;_CdPOGZBF@g+oF87KTacZCjRcd->V{M_nreC&(0QsW`1(G_k&7 z9s$MAid>V1L6~Y`a!<|P#%^fJqEp7~A}m-ens z1Czs4jw$hZ3|_xFEL%wqut-EA)P@^2UU|6Ai^(?jlefJ2a{hdVrl$3)ze|TFTA7;S zbr|c_UGX&gfgz)l_*lDr(>9tR(S!?LG3n^JYyeGc&d;{rLa`Afr5`c zd&vtrKf`kOPI3&~^Xr+ZmD3WJ1dZd%7O3o(lRx3OW9jn6E=|89bRBK%cYuu;Ewm8n z1vq8n#>p?Gy$gcRrY*K9E9jfCNT$tt#_*`Cej}&uWd1-lHaT1$CDsfSWpn6Gnp6|J z)YSA@e(Js^Nr~%n;$!E}U+20v`I24I$-E(hUl+gmg?r116VjDT=IH3hQdQ{=kQhY> zhEsiX)zo5iliHe#SI<@{;*`2(ZsX3-Ui>%47!v=!GP-PZ6_wu?tb-MA4GW5iw{d9eI0DX1F2 zW^arogW$vCxH@S-1vIrJmHwv<-+QQVMm@O3|F2*L^9SMC(~FaL9? zl=gk%7ER28zbgB!R5OJ zsD7xmAIgQxMRgv%ix+Nn*mT#aQs_-dH4U9UP!eW$@N~~<(uZzGN2gLOGNHk%3T>aS zo&6HQK^5UX+e119X}}A$pO8CG*mN9uE8v1ce~Mn}p=~(Tp);+ZagJpKwIjN&r~rw1 z8Lb<1D5GVsX}EvJ&%Dsr6qgBOXwA^h!Sq7Bk{nF0$Ca|7yEx@jo?4Ec^yk7^C8}q; zQrxpbyUe@4Nf%7d(Y~y#*yD`PMql}Dk~J5WDBjrkRBf!sgmcfwkUN@VHILss_wsaJ^ZW0o4?bVBuR3#+mUPNx>uBrZ2Y)&riGRzoj`-A6pBeV<(FsWofu+H%{iljA=8UEuia_PgCdV}`WUUnc#c02T<=I&os6lna?Js>H&; zlZ=ENe>UK&-ifcyi$)7N+}y<^RU9?7v;rxY|MMiF!dYCmJEb%yzIJFsbK|rI=j1Z? zP@B7M`r)5!lYd32*V~00efrd~cW+XD&gE{W_L$SESzmuXD0R4BGQXf1@=aO#g~5s) zc>%}h&VOWXI%COb!3J4TdE>62jUT@L#0d2>`2MH+BPbypb0Z^tzCJM2s~8Su#EbH8 zLw8@Y6o~Gs>S`=1amaW3Ug_p!F>~}R>j!(^ef@bSCT0p-NLSZIX*oKXExJ{P__wk* z&|mYaZf#!~vIE$xrzDl}?dniL(Rys(8qTiJ_};QN)uw^|KNT5{2&J0I7hZ$3HYJ2! zufFpN^zppu(VMwiic-I(rEO`gAm=)iv9tc;RMz=e2LjrnmYTG*3iH0os@0En*VSa7 z?Q=k;=i0q{i)&ii_CK~#f2MsbbKTmNN#tAc@l0&4e^C2f*)sa_=JR9_@2Xu@&BxvyazBOf zXzE8VtIs{17$1+7$hx?5D&hxJOp)sA%v~7#VLMklub+EUv7)^D$`dIe435ygOet73 zYwMJ5#UuM4)-9Eid$xS`R}1y#HitF(;nMylo@w2rsO3)XbX76kg3M~e#C)Ck1&KCy zqqdyCtiI8wq*}EJ=74%*V&Z^+%r8IP^^}&a>dobP-h$rSr#qFhi#{Fg85j$RI4alNnx>+9za zTmTWIpDp*npQ)*-5Sc}Z2ifPpgGS%~RQp%%^dpoe0KNMO#^$G=mTTuWM)? zv#&cxY1~?Jt3_!g`DfyL%cz3Ws^+Ivvz;e~;@?gTARG*sh1g~JqYXNPo8tG#3TmZ9 zo12`Si%eH-j~@d(L2t=JDBAmfa>}T5$SXca^rd;N@^E1B-TrS|IYdeed483g;aO zd$RHSs;sLUrWW++@E5bY9&LwJ9*@l05?+5l#qEBwTQ5QES$rk!wA81^q`uRN$n<4ZiMiI}!$A_rmm z^aV0KGqk5%sG}Z}%p3;0asPY{1uK8gh!Hv;2wv*`-@gz(C4u1N#{aK>{H;64Bwxfg SH}t6RJ None: def test_basic(self): g = Graph.Ring(5) lo = g.layout("auto") - plot(g, layout=lo, target=result_image_folder / "graph_basic.png", backend="cairo") + plot( + g, + layout=lo, + target=result_image_folder / "graph_basic.png", + backend="cairo", + ) @image_comparison(baseline_images=["graph_directed"]) def test_directed(self): g = Graph.Ring(5, directed=True) lo = g.layout("auto") - plot(g, layout=lo, target=result_image_folder / "graph_directed.png", backend="cairo") + plot( + g, + layout=lo, + target=result_image_folder / "graph_directed.png", + backend="cairo", + ) @image_comparison(baseline_images=["graph_mark_groups_directed"]) def test_mark_groups(self): @@ -62,6 +72,19 @@ def test_mark_groups_squares(self): vertex_shape="square", ) + @image_comparison(baseline_images=["graph_with_curved_edges"]) + def test_graph_with_curved_edges(self): + g = Graph.Ring(24, directed=True, mutual=True) + lo = g.layout("circle") + plot( + g, + layout=lo, + target=result_image_folder / "graph_with_curved_edges.png", + bbox=(800, 800), + edge_curved=0.25, + backend="cairo", + ) + class ClusteringTestRunner(unittest.TestCase): @classmethod From 00c3011cbe71c1798e73b578502b3acfc0804adf Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 14:37:58 +0200 Subject: [PATCH 1312/1892] chore: updated changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index adf345ba2..b13119595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,13 @@ - `Graph.layout_reingold_tilford()` now accepts vertex names in the `roots=...` keyword argument. +- The plotting of curved directed edges with the Cairo backend is now fixed; + arrowheads were placed at the wrong position before this fix. + +### Changed + +- The C core of igraph was updated to version 0.10.5. + ### Removed - Removed defunct `Graph.community_leading_eigenvector_naive()` method. Not a From edd902a45add3f9d10317dc8e0bdfa4570842766 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 14:44:38 +0200 Subject: [PATCH 1313/1892] chore: updated vendored C core --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 47c76b691..f2c7e65dc 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 47c76b691c8158daea48648f3d47129e682d4651 +Subproject commit f2c7e65dc2d8aa274de9346864aa8edadf86a15a From cd5aaa42b8a455e5b5b07730778698cbba831afc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 14:56:22 +0200 Subject: [PATCH 1314/1892] chore: bump version --- CHANGELOG.md | 7 ++++--- src/igraph/version.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b13119595..06f7f8230 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.5] - 2023-06-30 ### Added @@ -55,7 +55,7 @@ ago so the function in the Python interface did not do anything useful either. -## [0.10.4] - 2022-01-27 +## [0.10.4] - 2023-01-27 ### Added @@ -513,7 +513,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.4...main +[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.5...main +[0.10.5]: https://github.com/igraph/python-igraph/compare/0.10.4...0.10.5 [0.10.4]: https://github.com/igraph/python-igraph/compare/0.10.3...0.10.4 [0.10.3]: https://github.com/igraph/python-igraph/compare/0.10.2...0.10.3 [0.10.2]: https://github.com/igraph/python-igraph/compare/0.10.1...0.10.2 diff --git a/src/igraph/version.py b/src/igraph/version.py index b93074332..2b40ae92e 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 4) +__version_info__ = (0, 10, 5) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 4245a6c5076ed0de9e48d5f2bc156cdbf791cbe8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 15:05:40 +0200 Subject: [PATCH 1315/1892] fix: remove quotes around igraph from API docs, closes #686 --- doc/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 212b0a831..895599cbd 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -253,7 +253,7 @@ def get_pydoctor_html_outputdir(pydoctor_url_path): pydoctor_url_path = 'api/' pydoctor_args = [ - '--project-name="igraph"', + '--project-name=igraph', '--project-version=' + version, '--project-url=https://igraph.readthedocs.io', '--introspect-c-modules', From e5899eda5498c6ec828604711f8389200573fa68 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 30 Jun 2023 15:25:59 +0200 Subject: [PATCH 1316/1892] fix: fix auto-curving of edges with the Matplotlib backend, closes #685 --- src/igraph/drawing/matplotlib/graph.py | 2 +- .../test_graph/graph_with_curved_edges.png | Bin 0 -> 48561 bytes tests/drawing/matplotlib/test_graph.py | 9 +++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/drawing/matplotlib/baseline_images/test_graph/graph_with_curved_edges.png diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 46839f154..841335f1d 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -165,7 +165,7 @@ def __init__( def _kwds_post_update(self): self.kwds["layout"] = self.ensure_layout(self.kwds["layout"], self.graph) - self.edge_curved = self._set_edge_curve(**self.kwds) + self.kwds["edge_curved"] = self._set_edge_curve(**self.kwds) self._clear_state() self.stale = True diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_with_curved_edges.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_with_curved_edges.png new file mode 100644 index 0000000000000000000000000000000000000000..08f10b08cdae3a8a079d5906b3ee20d24f16b245 GIT binary patch literal 48561 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 Date: Mon, 3 Jul 2023 11:56:43 +0200 Subject: [PATCH 1317/1892] fix: fix default size of vertices with the Plotly backend, closes #690 --- CHANGELOG.md | 7 +++++++ src/igraph/drawing/plotly/vertex.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06f7f8230..18e3bd273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # igraph Python interface changelog +## [Unreleased] + +### Fixed + +- The default vertex size of the Plotly backend was fixed so the vertices are + now visible by default without specifying an explicit size for them. + ## [0.10.5] - 2023-06-30 ### Added diff --git a/src/igraph/drawing/plotly/vertex.py b/src/igraph/drawing/plotly/vertex.py index fe39c3a56..f813d696c 100644 --- a/src/igraph/drawing/plotly/vertex.py +++ b/src/igraph/drawing/plotly/vertex.py @@ -36,7 +36,7 @@ class VisualVertexBuilder(AttributeCollectorBase): # FIXME? mpl.rcParams["font.size"]) position = dict(func=self.layout.__getitem__) shape = "circle" - size = 0.2 + size = 20.0 width = None height = None zorder = 2 From 4c5746f2ebbcd7e00d3f48878bea916d976cf2d9 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Jul 2023 12:17:03 +0200 Subject: [PATCH 1318/1892] test: update baseline images for Plotly --- .../baseline_images/clustering_directed.json | 65 +++-- .../clustering_directed_large.json | 251 +++++++++--------- 2 files changed, 157 insertions(+), 159 deletions(-) diff --git a/tests/drawing/plotly/baseline_images/clustering_directed.json b/tests/drawing/plotly/baseline_images/clustering_directed.json index db9b712ef..5ea324abe 100644 --- a/tests/drawing/plotly/baseline_images/clustering_directed.json +++ b/tests/drawing/plotly/baseline_images/clustering_directed.json @@ -6,7 +6,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -24,7 +24,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -42,7 +42,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -60,7 +60,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -78,7 +78,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -183,13 +183,13 @@ "line": { "color": "rgba(255,0,0,255)" }, - "path": "M 1.1197388996537003,-0.16719602520017673L 0.5279328528097523,-0.9934550030368812C 0.45514612062341064,-1.0950773018577296 0.26321850173201045,-1.1588783220760186 0.14407761502695185,-1.1210570434734595L -0.8246194958406551,-0.8135441121460627C -0.9437603825457136,-0.7757228335435037 -1.0637476544979572,-0.6129044204457357 -1.0645940397451423,-0.4879072859505267L -1.0714757322212005,0.5284051354266215C -1.0723221174683857,0.6534022699218305 -0.9545507108608489,0.8178306034288613 -0.8359329190061271,0.8572618024406833L 0.12851107201115136,1.1778644907130693C 0.2471288638658731,1.2172956897248912 0.4399028680044583,1.1560995754479715 0.5140590802883218,1.0554722621592298L 1.1169999394586567,0.23730319901900315C 1.1911561517425202,0.13667588573026146 1.1925256318400421,-0.06557372637932848 1.1197388996537003,-0.16719602520017673 Z", + "path": "M 17.102240893427787,-12.23969476826467L 17.102240893427783,-12.239694768264666C 12.645988843102797,-18.461358578089076 0.8955252694779539,-22.367474687721593 -6.398686253821905,-20.051926987529704L -6.398686253821911,-20.0519269875297C -13.69289777712177,-17.73637928733781 -21.038927892627104,-7.768080596031269 -21.09074648483258,-0.11532960491661903L -21.09074648483258,-0.11532960491661903C -21.142565077038054,7.537421386198031 -13.932197797175824,17.60428489706909 -6.670011925108119,20.018397416825497L -6.670011925108115,20.018397416825497C 0.5921739469595897,22.432509936581905 12.394456112789907,18.685875055099775 16.93455240655252,12.525127653861238L 16.934552406552527,12.525127653861228C 21.47464870031514,6.36438025262269 21.558492943752768,-6.018030958440259 17.102240893427787,-12.23969476826467 Z", "type": "path" }, { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.015318095035966,0.03435580194714975 L 0.1950972580065446,1.0184451153265959", "type": "path" @@ -197,7 +197,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.29010409851547664,1.0184451153265959 L -0.9649307455828062,0.6328259400443561", "type": "path" @@ -205,7 +205,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.8699239050738742,0.6328259400443561 L -0.9566534831822209,-0.5895891303732176", "type": "path" @@ -213,7 +213,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.8616466426732888,-0.5895891303732176 L 0.2084901499044931,-0.9594640169691344", "type": "path" @@ -221,7 +221,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.30349699041342515,-0.9594640169691343 L 0.9203112545270339,0.03435580194714975", "type": "path" @@ -303,7 +303,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -339,7 +339,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -363,7 +363,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -399,7 +399,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -414,7 +414,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -450,7 +450,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -477,7 +477,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -513,7 +513,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -528,7 +528,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -564,7 +564,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -599,11 +599,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -710,7 +709,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -746,7 +745,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -837,7 +836,7 @@ ], "sequential": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -873,13 +872,13 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], "sequentialminus": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -915,7 +914,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ] @@ -1053,4 +1052,4 @@ "visible": false } } -} +} \ No newline at end of file diff --git a/tests/drawing/plotly/baseline_images/clustering_directed_large.json b/tests/drawing/plotly/baseline_images/clustering_directed_large.json index 8f525f7de..5c355cb84 100644 --- a/tests/drawing/plotly/baseline_images/clustering_directed_large.json +++ b/tests/drawing/plotly/baseline_images/clustering_directed_large.json @@ -6,7 +6,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -15,7 +15,7 @@ 2.5 ], "y": [ - 0 + 0.0 ] }, { @@ -24,7 +24,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -42,7 +42,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -60,7 +60,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -78,7 +78,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -96,7 +96,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -114,7 +114,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -132,7 +132,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -150,7 +150,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -168,7 +168,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -186,7 +186,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -204,7 +204,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -222,7 +222,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -240,7 +240,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -258,7 +258,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -276,7 +276,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -294,7 +294,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -312,7 +312,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -330,7 +330,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -348,7 +348,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -366,7 +366,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -384,7 +384,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -402,7 +402,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -420,7 +420,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -438,7 +438,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -456,7 +456,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -474,7 +474,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -492,7 +492,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -510,7 +510,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -528,7 +528,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -546,7 +546,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -564,7 +564,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -582,7 +582,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -600,7 +600,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -618,7 +618,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -636,7 +636,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -654,7 +654,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -672,7 +672,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -690,7 +690,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -708,7 +708,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -726,7 +726,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -744,7 +744,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -762,7 +762,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -780,7 +780,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -798,7 +798,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -816,7 +816,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -834,7 +834,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -852,7 +852,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -870,7 +870,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -888,7 +888,7 @@ "line": { "color": "rgba(0,0,0,255)" }, - "size": 0.2, + "size": 20.0, "symbol": "circle" }, "mode": "markers", @@ -1744,10 +1744,10 @@ 2.5 ], "y": [ - 0, + 0.0, 0.044706825614332625, -0.044706825614332625, - 0 + 0.0 ] } ], @@ -1758,13 +1758,13 @@ "line": { "color": "rgba(0,0,255,255)" }, - "path": "M 0.08467188267459153,-2.7297732924988862L 0.08155152177765243,-2.7299214387141904C -0.009367696129893549,-2.7342380349273507 -0.1909500767190293,-2.7304844316164045 -0.28161323940061905,-2.722414232092298L -0.2847409075439839,-2.722135828987712C -0.3769679042972561,-2.7139264279113124 -0.5593295859951877,-2.684528544914581 -0.6494642709398472,-2.6633400629942487L -0.6518360308590739,-2.6627825196667407C -0.7431565957633468,-2.641315266082655 -0.921699356285265,-2.5853143022647096 -1.0089215519029104,-2.55078059203085L -1.0106573132672392,-2.550093355490123C -1.0978795088848847,-2.5155596452562636 -1.266366877669369,-2.4341616609851098 -1.347632050836208,-2.3872973869478153L -1.3497426540803754,-2.386080237153332C -1.4299525256251309,-2.339824538013279 -1.5830127061525752,-2.236419510991894 -1.6558630151352642,-2.1792701831105616L -1.6583335671282884,-2.1773320940637357C -1.729948600114465,-2.1211518107058165 -1.8648859771397523,-1.999586376639347 -1.9282083211788628,-1.9342012259307966L -1.9303815533160236,-1.9319571979661154C -1.9926172812865535,-1.8676940612399058 -2.1081776870619855,-1.731601158295806 -2.161502364866888,-1.659771392077916L -2.1631196779521384,-1.6575928281259733C -2.215635699214415,-1.5868523438840547 -2.311295509855163,-1.4392954418783066 -2.3544392992336345,-1.3624790241144775L -2.3555105624439965,-1.3605716672622477C -2.398118720217287,-1.2847089279245334 -2.473583896959723,-1.1282792807827042 -2.506440915928869,-1.047712372978589L -2.5070810151735397,-1.0461428204613852C -2.5396179845203504,-0.9663606889158721 -2.5946343855076077,-0.8034009279178234 -2.6171138171480544,-0.7202232984652875L -2.61744961335299,-0.7189807967529462C -2.6397611468909687,-0.6364244181565811 -2.674109931734575,-0.46920125293896836 -2.686147183040202,-0.3845344663177207L -2.6862833838572926,-0.3835764664201169C -2.698252534754375,-0.2993886797476711 -2.711810564600415,-0.1301813690722769 -2.7133994435493722,-0.045161845069328466L -2.713412967029626,-0.04443821545942635C -2.7149950842384567,0.04021949373857103 -2.7078003322721127,0.20909357538870527 -2.699023463096938,0.29330994784084213L -2.698967550250878,0.2938464463318956C -2.690218637498733,0.3777945695385057 -2.662520663182241,0.5439908777104231 -2.643571601617894,0.6262390626757304L -2.643481710215066,0.6266292352814542C -2.6245775943521323,0.7086823339438996 -2.5768702239744856,0.8698584325875697 -2.548066969459773,0.9489814325687944L -2.5479658817830115,0.94925912203067C -2.519213171106679,1.0282432772809569 -2.452251751203909,1.1820960487271361 -2.414043041977471,1.2569646649230286L -2.413944710679318,1.2571573416286943C -2.3757851671019568,1.331929619471754 -2.2905915065957196,1.4762348833329115 -2.2435573896668433,1.5457678693510093L -2.2435573896668433,1.5457678693510093C -2.196523272737967,1.615300855369107 -2.0714375110137118,1.6539310090799837 -1.993385866218333,1.6230281767727623L 2.564155000068931,-0.18142990343059492C 2.6422066448643093,-0.2123327357378162 2.70694608097404,-0.3261200020467362 2.693633872288393,-0.40900443604843495L 2.693633872288393,-0.40900443604843495C 2.680321663602745,-0.4918888700501337 2.6436414186205517,-0.655401953919702 2.620273382324006,-0.7360306037875716L 2.6202131664742097,-0.7362383714668104C 2.5968150222527657,-0.8169709051742993 2.540308327176887,-0.9749629950037181 2.507199776322452,-1.052222551125648L 2.5070833745499557,-1.0524941773080927C 2.4739166228092726,-1.1298895465212448 2.398361167239949,-1.2800398082461453 2.355972463411309,-1.3527947007578938L 2.355770899895785,-1.353140659246398C 2.313281414309383,-1.4260685310023984 2.219703166854112,-1.5661809938114277 2.168614404985243,-1.6333655848644568L 2.168287905206504,-1.6337949504100493C 2.1170358934482656,-1.7011942242358744 2.0066783780538446,-1.8292232783798599 1.947572874417662,-1.88985305869802L 1.9470676576696004,-1.8903713045222426C 1.887709545659387,-1.951260207752514 1.7619957924271628,-2.0653259186720234 1.695640151205152,-2.1185027263612617L 1.6948850690250796,-2.1191078423565233C 1.628151886713033,-2.172587208043392 1.488640566378044,-2.270974288008281 1.4158624283551022,-2.3158820022863016L 1.414767092505202,-2.3165578787338457C 1.34144128655731,-2.361803531235638 1.189782423469918,-2.442934766460868 1.111449366330418,-2.4788203491843053L 1.1099083214293617,-2.479526325642991C 1.0308047418393333,-2.5157648965957717 0.8687095332988997,-2.578137733423335 0.7857179043484942,-2.6042719992981183L 0.783631311463264,-2.6049290724743495C 0.6995963860702434,-2.631391874937248 0.5288537349802286,-2.673472580731123 0.44214600928323433,-2.6890904840620995L 0.43947570913498357,-2.6895714618440083C 0.351432833363864,-2.705429854065939 0.17403092013366794,-2.725530769393378 0.08467188267459153,-2.7297732924988862 Z", + "path": "M 8.413141377617196,-25.896264101676145L 8.155152177765178,-25.9805285854218C 6.833557178763122,-26.41218820673784 4.128701954952482,-26.983613777141827 2.745441730143898,-27.12337972622978L 2.4846737173375413,-27.149727978097353C 0.9710294861257793,-27.302668053119092 -2.0505946108051303,-27.254346482977223 -3.5585744765242784,-27.053084837813618L -3.7543123520242156,-27.02696079747362C -5.360161155493332,-26.81263713214002 -8.472329653542033,-26.001919309518726 -9.97864934812162,-25.405525152231043L -10.117156398738466,-25.35068633147587C -11.623476093318052,-24.754292174188183 -14.447123830844985,-23.214854094068826 -15.764451873792332,-22.27181017123716L -15.925021780439813,-22.156861980872392C -17.16206487006342,-21.271292153223108 -19.397812431581155,-19.238073031125833 -20.396516903475288,-18.090423736677845L -20.568571984283913,-17.892708699193616C -21.48124891577373,-16.84391692348774 -23.06183579517491,-14.575764794341183 -23.729745743086276,-13.356404440900498L -23.860128767511288,-13.118372515724491C -24.462847203210146,-12.018028124871812 -25.445040714149187,-9.721846805970955 -25.824515789389366,-8.526009877922782L -25.899262810803666,-8.290460155948939C -26.241364375336698,-7.212398088887686 -26.734295576952675,-5.013398145996662 -26.885125214035625,-3.8924602701668927L -26.913102784791924,-3.6845361556429297C -27.04994363649672,-2.667560337075141 -27.16404214849462,-0.6246956257750191 -27.141299808787714,0.4011932669573146L -27.137495282725656,0.5728124178221539C -27.11665520604978,1.5128917351220679 -26.94259526292006,3.380714068636491 -26.789375396466216,4.308457084851L -26.76688888882022,4.444612407985373C -26.62491227618937,5.304277762632695 -26.230646745122016,6.997928837870707 -25.978357826685507,7.831914558461397L -25.94644875166113,7.937395659623136C -25.71011437073681,8.718640829632957 -25.144765028541553,10.246844573146316 -24.815750067270613,10.993803146649851L -24.780296766639943,11.074292334019272C -24.46900845568434,11.781006313838098 -23.767936083377943,13.154363712079272 -23.378152022027148,13.821007130501622L -23.342631483495033,13.88175751918912C -22.970607691410294,14.51802574326772 -22.15969179189009,15.746419522342974 -21.72079968445462,16.338545077339628L -21.687138017026985,16.38395927634213C -21.265076743305336,16.953377731837534 -20.363853048610867,18.04507625641636 -19.88469062763805,18.56735632549978L -19.85386256512327,18.60095846522359C -19.390114175407845,19.106437464445104 -18.413939099670152,20.067976195576676 -17.901512413647882,20.52403592748673L -17.873928924555894,20.548585231774698C -17.37529398307962,20.992370311540768 -16.33679664947991,21.82875009256347 -15.796934257356478,22.22134479382011L -15.796934257356478,22.221344793820105C -15.257071865233044,22.613939495076743 -14.096565733835174,22.760803956469676 -13.47592199456074,22.51507371660598L 25.236152912086663,7.187878982388844C 25.856796651361094,6.942148742525145 26.60223357107002,6.040668044025645 26.727026751504514,5.384917585389842L 26.727026751504514,5.384917585389842C 26.851819931939005,4.72916712675404 27.03631054923762,3.4085721615485616 27.09600798610174,2.7437276549788856L 27.099310329081725,2.7069497846985935C 27.16065893743584,2.023716342988772 27.21404138688488,0.6545469509673095 27.206075227979806,-0.03138899934433126L 27.20554567089632,-0.07698716599310718C 27.197314733449506,-0.7857221996291359 27.10695946762353,-2.1984662466468032 27.02483513924437,-2.9024752600284422L 27.01828528025058,-2.958623783359041C 26.932886022374525,-3.690707058405979 26.683124866195204,-5.141277717639568 26.518762967891934,-5.85976510182622L 26.503069823350884,-5.928365711136275C 26.33086135277709,-6.681153399977953 25.90179328536861,-8.162204921041777 25.644933688533918,-8.89046875326392L 25.615679392159933,-8.973412300045215C 25.34419264713825,-9.743147905658006 24.710187131240467,-11.244168747025656 24.347668360364366,-11.975453982780515L 24.298722292456734,-12.07418966127408C 23.91173048762682,-12.854842736275721 23.039753748641374,-14.359354564182366 22.55476881448584,-15.08321331708737L 22.477956040691623,-15.19785934984027C 21.95456471963898,-15.979041119121725 20.80283658467503,-17.459777232178354 20.174499770763724,-18.159331575953534L 20.059791757858704,-18.28704093010392C 19.37410093749489,-19.050449950954288 17.892489575888607,-20.461528429379452 17.09656903464614,-21.10919788695424L 16.933840412443192,-21.241616078234436C 16.056555560099252,-21.955494631449323 14.191905131800675,-23.221061974030174 13.20453955584604,-23.77275076339614L 12.9888064417623,-23.89329126372697C 11.893574308765796,-24.50525030325835 9.605741776693243,-25.506736722232937 8.413141377617196,-25.896264101676145 Z", "type": "path" }, { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.5,0.0 L 2.385279912777263,0.31333308391076065", "type": "path" @@ -1772,7 +1772,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.4802867532861947,0.31333308391076065 L 2.3264510623126458,0.621724717912137", "type": "path" @@ -1780,7 +1780,7 @@ { "line": { "color": "rgb(204,204,204)", - "width": 2 + "width": 2.0 }, "path": "M 2.4214579028215777,0.621724717912137 L 2.229434374211696,0.9203113817116949", "type": "path" @@ -1788,7 +1788,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.324441214720628,0.9203113817116949 L 2.095759859600727,1.2043841852542883", "type": "path" @@ -1796,7 +1796,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.190766700109659,1.2043841852542883 L 1.9275356454284365,1.469463130731183", "type": "path" @@ -1804,7 +1804,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.0225424859373686,1.469463130731183 L 1.7274147280445968,1.7113677648217218", "type": "path" @@ -1812,7 +1812,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.822421568553529,1.7113677648217218 L 1.498553133862792,1.926283106939473", "type": "path" @@ -1820,7 +1820,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.5935599743717241,1.926283106939473 L 1.2445601469385592,2.110819813755038", "type": "path" @@ -1828,7 +1828,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.3395669874474914,2.110819813755038 L 0.9694413884037497,2.262067631165049", "type": "path" @@ -1836,7 +1836,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.0644482289126818,2.262067631165049 L 0.6775356454284366,2.3776412907378837", "type": "path" @@ -1844,7 +1844,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.7725424859373686,2.3776412907378837 L 0.37344644595537924,2.4557181268217216", "type": "path" @@ -1852,7 +1852,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.4684532864643113,2.4557181268217216 L 0.0619694583143512,2.495066821070679", "type": "path" @@ -1860,7 +1860,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.15697629882328326,2.495066821070679 L -0.25198313933221556,2.495066821070679", "type": "path" @@ -1868,7 +1868,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.1569762988232835,2.495066821070679 L -0.5634601269732441,2.4557181268217216", "type": "path" @@ -1876,7 +1876,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.46845328646431206,2.4557181268217216 L -0.8675493264463009,2.3776412907378837", "type": "path" @@ -1884,7 +1884,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.7725424859373689,2.3776412907378837 L -1.159455069421614,2.2620676311650487", "type": "path" @@ -1892,7 +1892,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.0644482289126818,2.2620676311650487 L -1.4345738279564244,2.1108198137550374", "type": "path" @@ -1900,7 +1900,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.3395669874474923,2.1108198137550374 L -1.6885668148806565,1.926283106939473", "type": "path" @@ -1908,7 +1908,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.5935599743717244,1.926283106939473 L -1.9174284090624614,1.7113677648217211", "type": "path" @@ -1916,7 +1916,7 @@ { "line": { "color": "rgb(204,204,204)", - "width": 2 + "width": 2.0 }, "path": "M -1.8224215685535292,1.7113677648217211 L -2.1175493264463,1.4694631307311832", "type": "path" @@ -1924,7 +1924,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.022542485937368,1.4694631307311832 L -2.285773540618591,1.204384185254288", "type": "path" @@ -1932,7 +1932,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.190766700109659,1.204384185254288 L -2.4194480552295605,0.9203113817116944", "type": "path" @@ -1940,7 +1940,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.3244412147206286,0.9203113817116944 L -2.5164647433305096,0.621724717912137", "type": "path" @@ -1948,7 +1948,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.4214579028215777,0.621724717912137 L -2.5752935937951267,0.3133330839107602", "type": "path" @@ -1956,7 +1956,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.4802867532861947,0.3133330839107602 L -2.595006840508932,-8.049116928532385e-16", "type": "path" @@ -1964,7 +1964,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.5,-8.040613248383183e-16 L -2.5752935937951267,-0.3133330839107607", "type": "path" @@ -1972,7 +1972,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.4802867532861947,-0.3133330839107607 L -2.5164647433305096,-0.6217247179121376", "type": "path" @@ -1980,7 +1980,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.4214579028215777,-0.6217247179121376 L -2.41944805522956,-0.9203113817116958", "type": "path" @@ -1988,7 +1988,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.324441214720628,-0.9203113817116958 L -2.2857735406185906,-1.2043841852542885", "type": "path" @@ -1996,7 +1996,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.1907667001096587,-1.2043841852542885 L -2.1175493264463,-1.4694631307311834", "type": "path" @@ -2004,7 +2004,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -2.022542485937368,-1.4694631307311834 L -1.9174284090624611,-1.7113677648217218", "type": "path" @@ -2012,7 +2012,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.822421568553529,-1.7113677648217218 L -1.6885668148806559,-1.9262831069394735", "type": "path" @@ -2020,7 +2020,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.5935599743717237,-1.9262831069394735 L -1.434573827956423,-2.1108198137550382", "type": "path" @@ -2028,7 +2028,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.339566987447491,-2.1108198137550382 L -1.1594550694216126,-2.2620676311650496", "type": "path" @@ -2036,7 +2036,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -1.0644482289126804,-2.2620676311650496 L -0.8675493264463009,-2.3776412907378837", "type": "path" @@ -2044,7 +2044,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.7725424859373689,-2.3776412907378837 L -0.5634601269732437,-2.4557181268217216", "type": "path" @@ -2052,7 +2052,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.46845328646431156,-2.4557181268217216 L -0.25198313933221506,-2.495066821070679", "type": "path" @@ -2060,7 +2060,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M -0.156976298823283,-2.495066821070679 L 0.06196945831435223,-2.495066821070679", "type": "path" @@ -2068,7 +2068,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.1569762988232843,-2.495066821070679 L 0.3734464459553808,-2.4557181268217216", "type": "path" @@ -2076,7 +2076,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.46845328646431283,-2.4557181268217216 L 0.677535645428436,-2.377641290737884", "type": "path" @@ -2084,7 +2084,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 0.7725424859373681,-2.377641290737884 L 0.9694413884037495,-2.262067631165049", "type": "path" @@ -2092,7 +2092,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.0644482289126815,-2.262067631165049 L 1.2445601469385597,-2.1108198137550374", "type": "path" @@ -2100,7 +2100,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.3395669874474918,-2.1108198137550374 L 1.4985531338627929,-1.9262831069394726", "type": "path" @@ -2108,7 +2108,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.593559974371725,-1.9262831069394726 L 1.7274147280445975,-1.7113677648217207", "type": "path" @@ -2116,7 +2116,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 1.8224215685535297,-1.7113677648217207 L 1.9275356454284374,-1.4694631307311814", "type": "path" @@ -2124,7 +2124,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.0225424859373695,-1.4694631307311814 L 2.095759859600727,-1.2043841852542883", "type": "path" @@ -2132,7 +2132,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.190766700109659,-1.2043841852542883 L 2.2294343742116967,-0.9203113817116947", "type": "path" @@ -2140,7 +2140,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.3244412147206286,-0.9203113817116947 L 2.326451062312646,-0.6217247179121362", "type": "path" @@ -2148,7 +2148,7 @@ { "line": { "color": "rgb(51,51,51)", - "width": 2 + "width": 2.0 }, "path": "M 2.421457902821578,-0.6217247179121362 L 2.385279912777263,-0.3133330839107595", "type": "path" @@ -2156,7 +2156,7 @@ { "line": { "color": "rgb(204,204,204)", - "width": 2 + "width": 2.0 }, "path": "M 2.4802867532861947,-0.3133330839107595 L 2.404993159491068,0.0", "type": "path" @@ -2238,7 +2238,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2274,7 +2274,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2298,7 +2298,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2334,7 +2334,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2349,7 +2349,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2385,7 +2385,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2412,7 +2412,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2448,7 +2448,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2463,7 +2463,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2499,7 +2499,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2534,11 +2534,10 @@ ], "scatter": [ { - "marker": { - "colorbar": { - "outlinewidth": 0, - "ticks": "" - } + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 }, "type": "scatter" } @@ -2645,7 +2644,7 @@ }, "colorscale": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2681,7 +2680,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], @@ -2772,7 +2771,7 @@ ], "sequential": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2808,13 +2807,13 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ], "sequentialminus": [ [ - 0, + 0.0, "#0d0887" ], [ @@ -2850,7 +2849,7 @@ "#fdca26" ], [ - 1, + 1.0, "#f0f921" ] ] @@ -2988,4 +2987,4 @@ "visible": false } } -} +} \ No newline at end of file From f49fe96375ef541cb9624fd43522c0ffb68132dc Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Jul 2023 13:05:34 +0200 Subject: [PATCH 1319/1892] refactor: rename Graph.Incidence() to Graph.Biadjacency() and Graph.get_incidence() to Graph.get_biadjacency() --- CHANGELOG.md | 6 ++++ doc/source/analysis.rst | 2 +- doc/source/generation.rst | 4 +-- src/_igraph/graphobject.c | 60 ++++++++++++++++++++------------------ src/igraph/__init__.py | 27 +++++++++++++---- src/igraph/adjacency.py | 19 ++++++------ src/igraph/io/bipartite.py | 16 +++++----- tests/test_bipartite.py | 40 ++++++++++++------------- 8 files changed, 100 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e3bd273..20eb8cd50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +### Changed + +- `Graph.Incidence()` is now deprecated in favour of `Graph.Biadjacency()` as it constructs a bipartite graph from a _bipartite adjacency_ matrix. (The previous name was a mistake). Future versions might re-introduce `Graph.Incidence()` to construct a graph from its incidence matrix. + +- `Graph.get_incidence()` is now deprecated in favour of `Graph.get_biadjacency()` as it returns the _bipartite adjacency_ matrix of a graph and not its incidence matrix. (The previous name was a mistake). Future versions might re-introduce `Graph.get_incidence()` to return the incidence matrix of a graph. + ### Fixed - The default vertex size of the Plotly backend was fixed so the vertices are diff --git a/doc/source/analysis.rst b/doc/source/analysis.rst index aef415fcf..943f719cc 100644 --- a/doc/source/analysis.rst +++ b/doc/source/analysis.rst @@ -75,7 +75,7 @@ The :meth:`Graph.incident` function fulfills the same purpose with a slightly di >>> edges = g.incident(0) -To get the full adjacency/incidence list representation of the graph, use :meth:`Graph.get_adjlist`, :meth:`Graph.g.get_inclist()` or, for a bipartite graph, :meth:`Graph.get_incidence`. +To get the full adjacency/incidence list representation of the graph, use :meth:`Graph.get_adjlist`, :meth:`Graph.g.get_inclist()` or, for a bipartite graph, :meth:`Graph.get_biadjacency`. Neighborhood ++++++++++++ diff --git a/doc/source/generation.rst b/doc/source/generation.rst index 674d971c3..b5a828da6 100644 --- a/doc/source/generation.rst +++ b/doc/source/generation.rst @@ -66,9 +66,9 @@ To create a graph from an adjacency matrix, use :meth:`Graph.Adjacency` or, for This graph is directed and has edges `[0, 1]`, `[0, 2]` and `[2, 2]` (a self-loop). -To create a bipartite graph from an incidence matrix, use :meth:`Graph.Incidence`:: +To create a bipartite graph from a bipartite adjacency matrix, use :meth:`Graph.Biadjacency`:: - >>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) + >>> g = Graph.Biadjacency([[0, 1, 1], [1, 1, 0]]) From files ++++++++++ diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index f27b74149..162d37e75 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -2206,8 +2206,8 @@ PyObject *igraphmodule_Graph_Erdos_Renyi(PyTypeObject * type, igraph_t g; Py_ssize_t n, m = -1; double p = -1.0; - igraph_erdos_renyi_t t; PyObject *loops = Py_False, *directed = Py_False; + int retval; static char *kwlist[] = { "n", "p", "m", "directed", "loops", NULL }; @@ -2231,11 +2231,15 @@ PyObject *igraphmodule_Graph_Erdos_Renyi(PyTypeObject * type, return NULL; } - t = (m == -1) ? IGRAPH_ERDOS_RENYI_GNP : IGRAPH_ERDOS_RENYI_GNM; + if (m == -1) { + /* GNP model */ + retval = igraph_erdos_renyi_game_gnp(&g, n, p, PyObject_IsTrue(directed), PyObject_IsTrue(loops)); + } else { + /* GNM model */ + retval = igraph_erdos_renyi_game_gnm(&g, n, m, PyObject_IsTrue(directed), PyObject_IsTrue(loops)); + } - if (igraph_erdos_renyi_game(&g, t, n, (m == -1 ? p : m), - PyObject_IsTrue(directed), - PyObject_IsTrue(loops))) { + if (retval) { igraphmodule_handle_igraph_error(); return NULL; } @@ -2625,12 +2629,12 @@ PyObject *igraphmodule_Graph_Hexagonal_Lattice(PyTypeObject * type, } /** \ingroup python_interface_graph - * \brief Generates a bipartite graph from an incidence matrix + * \brief Generates a bipartite graph from a bipartite adjacency matrix * \return a reference to the newly generated Python igraph object - * \sa igraph_incidence + * \sa igraph_biadjacency */ -PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, - PyObject * args, PyObject * kwds) { +PyObject *igraphmodule_Graph_Biadjacency(PyTypeObject * type, + PyObject * args, PyObject * kwds) { igraphmodule_GraphObject *self; igraph_matrix_t matrix; igraph_vector_bool_t vertex_types; @@ -2657,7 +2661,7 @@ PyObject *igraphmodule_Graph_Incidence(PyTypeObject * type, return NULL; } - if (igraph_incidence(&g, &vertex_types, &matrix, + if (igraph_biadjacency(&g, &vertex_types, &matrix, PyObject_IsTrue(directed), mode, PyObject_IsTrue(multiple))) { igraphmodule_handle_igraph_error(); igraph_matrix_destroy(&matrix); @@ -8625,12 +8629,12 @@ PyObject *igraphmodule_Graph_get_adjacency(igraphmodule_GraphObject * self, } /** \ingroup python_interface_graph - * \brief Returns the incidence matrix of a bipartite graph. - * \return the incidence matrix as a Python list of lists - * \sa igraph_get_incidence + * \brief Returns the bipartite adjacency matrix of a bipartite graph. + * \return the bipartite adjacency matrix as a Python list of lists + * \sa igraph_get_biadjacency */ -PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, - PyObject * args, PyObject * kwds) +PyObject *igraphmodule_Graph_get_biadjacency(igraphmodule_GraphObject * self, + PyObject * args, PyObject * kwds) { static char *kwlist[] = { "types", NULL }; igraph_matrix_t matrix; @@ -8663,7 +8667,7 @@ PyObject *igraphmodule_Graph_get_incidence(igraphmodule_GraphObject * self, return NULL; } - if (igraph_get_incidence(&self->g, types, &matrix, &row_ids, &col_ids)) { + if (igraph_get_biadjacency(&self->g, types, &matrix, &row_ids, &col_ids)) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&row_ids); igraph_vector_int_destroy(&col_ids); @@ -13848,12 +13852,12 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param mutual: whether to create all connections as mutual\n" " in case of a directed graph.\n"}, - /* interface to igraph_incidence */ - {"_Incidence", (PyCFunction) igraphmodule_Graph_Incidence, + /* interface to igraph_biadjacency */ + {"_Biadjacency", (PyCFunction) igraphmodule_Graph_Biadjacency, METH_VARARGS | METH_CLASS | METH_KEYWORDS, - "_Incidence(matrix, directed=False, mode=\"all\", multiple=False)\n--\n\n" + "_Biadjacency(matrix, directed=False, mode=\"all\", multiple=False)\n--\n\n" "Internal function, undocumented.\n\n" - "@see: Graph.Incidence()\n\n"}, + "@see: Graph.Biadjacency()\n\n"}, /* interface to igraph_kautz */ {"Kautz", (PyCFunction) igraphmodule_Graph_Kautz, @@ -16322,18 +16326,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " the I{endpoints} of the loop edges, not the edges themselves).\n" "@return: the adjacency matrix.\n"}, - // interface to igraph_get_edgelist + /* interface to igraph_get_biadjacency */ + {"get_biadjacency", (PyCFunction) igraphmodule_Graph_get_biadjacency, + METH_VARARGS | METH_KEYWORDS, + "get_biadjacency(types)\n--\n\n" + "Internal function, undocumented.\n\n" + "@see: Graph.get_biadjacency()\n\n"}, + + /* interface to igraph_get_edgelist */ {"get_edgelist", (PyCFunction) igraphmodule_Graph_get_edgelist, METH_NOARGS, "get_edgelist()\n--\n\n" "Returns the edge list of a graph."}, - /* interface to igraph_get_incidence */ - {"get_incidence", (PyCFunction) igraphmodule_Graph_get_incidence, - METH_VARARGS | METH_KEYWORDS, - "get_incidence(types)\n--\n\n" - "Internal function, undocumented.\n\n" - "@see: Graph.get_incidence()\n\n"}, - /* interface to igraph_to_directed */ {"to_directed", (PyCFunction) igraphmodule_Graph_to_directed, METH_VARARGS | METH_KEYWORDS, diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 4e0136ba5..674e20d51 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -78,7 +78,7 @@ _get_adjacency, _get_adjacency_sparse, _get_adjlist, - _get_incidence, + _get_biadjacency, _get_inclist, ) from igraph.automorphisms import ( @@ -217,7 +217,7 @@ ) from igraph.io.bipartite import ( _construct_bipartite_graph, - _construct_incidence_bipartite_graph, + _construct_bipartite_graph_from_adjacency, _construct_full_bipartite_graph, _construct_random_bipartite_graph, ) @@ -512,7 +512,7 @@ def __init__(self, *args, **kwds): # Bipartite graphs Bipartite = classmethod(_construct_bipartite_graph) - Incidence = classmethod(_construct_incidence_bipartite_graph) + Biadjacency = classmethod(_construct_bipartite_graph_from_adjacency) Full_Bipartite = classmethod(_construct_full_bipartite_graph) Random_Bipartite = classmethod(_construct_random_bipartite_graph) @@ -620,7 +620,7 @@ def es(self): get_adjacency = _get_adjacency get_adjacency_sparse = _get_adjacency_sparse get_adjlist = _get_adjlist - get_incidence = _get_incidence + get_biadjacency = _get_biadjacency get_inclist = _get_inclist ############################################# @@ -937,6 +937,23 @@ def __reduce__(self): __iter__ = None # needed for PyPy __hash__ = None # needed for PyPy + ########################### + # Deprecated functions + + @classmethod + def Incidence(cls, *args, **kwds): + """Deprecated alias to L{Graph.Biadjacency()}.""" + deprecated("Graph.Incidence() is deprecated; use Graph.Biadjacency() instead") + return cls.Biadjacency(*args, **kwds) + + def get_incidence(self, *args, **kwds): + """Deprecated alias to L{Graph.get_biadjacency()}.""" + deprecated( + "Graph.get_incidence() is deprecated; use Graph.get_biadjacency() " + "instead" + ) + return self.get_biadjacency(*args, **kwds) + ############################################################## # I/O format mapping @@ -1056,7 +1073,7 @@ def write(graph, filename, *args, **kwds): _construct_graph_from_dataframe, _construct_random_geometric_graph, _construct_bipartite_graph, - _construct_incidence_bipartite_graph, + _construct_bipartite_graph_from_adjacency, _construct_full_bipartite_graph, _construct_random_bipartite_graph, _construct_graph_from_networkx, diff --git a/src/igraph/adjacency.py b/src/igraph/adjacency.py index 48d35fe38..c7b377d3f 100644 --- a/src/igraph/adjacency.py +++ b/src/igraph/adjacency.py @@ -11,7 +11,7 @@ "_get_adjacency", "_get_adjacency_sparse", "_get_adjlist", - "_get_incidence", + "_get_biadjacency", "_get_inclist", ) @@ -133,23 +133,22 @@ def _get_adjlist(self, mode="out"): return [self.neighbors(idx, mode) for idx in range(self.vcount())] -def _get_incidence(graph, types="type", *args, **kwds): - """Returns the incidence matrix of a bipartite graph. The incidence matrix - is an M{n} times M{m} matrix, where M{n} and M{m} are the number of - vertices in the two vertex classes. +def _get_biadjacency(graph, types="type", *args, **kwds): + """Returns the bipartite adjacency matrix of a bipartite graph. The + bipartite adjacency matrix is an M{n} times M{m} matrix, where M{n} and + M{m} are the number of vertices in the two vertex classes. @param types: an igraph vector containing the vertex types, or an attribute name. Anything that evalulates to C{False} corresponds to vertices of the first kind, everything else to the second kind. - @return: the incidence matrix and two lists in a triplet. The first - list defines the mapping between row indices of the matrix and the - original vertex IDs. The second list is the same for the column - indices. + @return: the bipartite adjacency matrix and two lists in a triplet. The + first list defines the mapping between row indices of the matrix and the + original vertex IDs. The second list is the same for the column indices. """ # Deferred import to avoid cycles from igraph import Graph - return super(Graph, graph).get_incidence(types, *args, **kwds) + return super(Graph, graph).get_biadjacency(types, *args, **kwds) def _get_inclist(graph, mode="out"): diff --git a/src/igraph/io/bipartite.py b/src/igraph/io/bipartite.py index aa359b8f1..70fac3750 100644 --- a/src/igraph/io/bipartite.py +++ b/src/igraph/io/bipartite.py @@ -1,4 +1,4 @@ -def _construct_incidence_bipartite_graph( +def _construct_bipartite_graph_from_adjacency( cls, matrix, directed=False, @@ -8,13 +8,13 @@ def _construct_incidence_bipartite_graph( *args, **kwds ): - """Creates a bipartite graph from an incidence matrix. + """Creates a bipartite graph from a bipartite adjacency matrix. Example: - >>> g = Graph.Incidence([[0, 1, 1], [1, 1, 0]]) + >>> g = Graph.Biadjacency([[0, 1, 1], [1, 1, 0]]) - @param matrix: the incidence matrix. + @param matrix: the bipartite adjacency matrix. @param directed: whether to create a directed graph. @param mode: defines the direction of edges in the graph. If C{"out"}, then edges go from vertices of the first kind @@ -28,12 +28,12 @@ def _construct_incidence_bipartite_graph( the nearest integer and this will be the number of multiple edges created. @param weighted: defines whether to create a weighted graph from the - incidence matrix. If it is c{None} then an unweighted graph is created + adjacency matrix. If it is c{None} then an unweighted graph is created and the multiple argument is used to determine the edges of the graph. If it is a string then for every non-zero matrix entry, an edge is created and the value of the entry is added as an edge attribute named by the weighted argument. If it is C{True} then a weighted graph is created and - the name of the edge attribute will be ‘weight’. + the name of the edge attribute will be C{"weight"}. @raise ValueError: if the weighted and multiple are passed together. @@ -43,11 +43,11 @@ def _construct_incidence_bipartite_graph( is_weighted = True if weighted or weighted == "" else False if is_weighted and multiple: raise ValueError("arguments weighted and multiple can not co-exist") - result, types = cls._Incidence(matrix, directed, mode, multiple, *args, **kwds) + result, types = cls._Biadjacency(matrix, directed, mode, multiple, *args, **kwds) result.vs["type"] = types if is_weighted: weight_attr = "weight" if weighted is True else weighted - _, rows, _ = result.get_incidence() + _, rows, _ = result.get_biadjacency() num_vertices_of_first_kind = len(rows) for edge in result.es: source, target = edge.tuple diff --git a/tests/test_bipartite.py b/tests/test_bipartite.py index 23ec6554f..45cca2fc2 100644 --- a/tests/test_bipartite.py +++ b/tests/test_bipartite.py @@ -45,31 +45,31 @@ def testFullBipartite(self): self.assertTrue(sorted(g.get_edgelist()) == expected) self.assertTrue(g.vs["type"] == [False] * 10 + [True] * 5) - def testIncidence(self): - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]]) + def testBiadjacency(self): + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]]) self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, not g.is_directed()))) self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True) + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], multiple=True) self.assertTrue(all((g.vcount() == 5, g.ecount() == 5, not g.is_directed()))) self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual( sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3), (1, 3)] ) - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True) + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], directed=True) self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, mode="in") + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], directed=True, mode="in") self.assertTrue(all((g.vcount() == 5, g.ecount() == 4, g.is_directed()))) self.assertListEqual(g.vs["type"], [False] * 2 + [True] * 3) self.assertListEqual(sorted(g.get_edgelist()), [(2, 1), (3, 0), (3, 1), (4, 0)]) # Create a weighted Graph - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted=True) + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], weighted=True) self.assertTrue( all( (g.vcount() == 5, g.ecount() == 4, not g.is_directed(), g.is_weighted()) @@ -80,7 +80,7 @@ def testIncidence(self): self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Graph is not weighted when weighted=`str` - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="some_attr_name") + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], weighted="some_attr_name") self.assertTrue( all( ( @@ -96,7 +96,7 @@ def testIncidence(self): self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Graph is not weighted when weighted="" - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], weighted="") + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], weighted="") self.assertTrue( all( ( @@ -112,7 +112,7 @@ def testIncidence(self): self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Should work when directed=True and mode=out with weighted - g = Graph.Incidence([[0, 1, 1], [1, 2, 0]], directed=True, weighted=True) + g = Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], directed=True, weighted=True) self.assertTrue( all((g.vcount() == 5, g.ecount() == 4, g.is_directed(), g.is_weighted())) ) @@ -121,7 +121,7 @@ def testIncidence(self): self.assertListEqual(sorted(g.get_edgelist()), [(0, 3), (0, 4), (1, 2), (1, 3)]) # Should work when directed=True and mode=in with weighted - g = Graph.Incidence( + g = Graph.Biadjacency( [[0, 1, 1], [1, 2, 0]], directed=True, mode="in", weighted=True ) self.assertTrue( @@ -132,7 +132,7 @@ def testIncidence(self): self.assertListEqual(sorted(g.get_edgelist()), [(2, 1), (3, 0), (3, 1), (4, 0)]) # Should work when directed=True and mode=all with weighted - g = Graph.Incidence( + g = Graph.Biadjacency( [[0, 1, 1], [1, 2, 0]], directed=True, mode="all", weighted=True ) self.assertTrue( @@ -145,28 +145,28 @@ def testIncidence(self): [(0, 3), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (3, 1), (4, 0)], ) - def testIncidenceError(self): + def testBiadjacencyError(self): msg = "arguments weighted and multiple can not co-exist" with self.assertRaises(ValueError) as e: - Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted=True) + Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], multiple=True, weighted=True) self.assertIn(msg, e.exception.args) with self.assertRaises(ValueError) as e: - Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="string") + Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="string") self.assertIn(msg, e.exception.args) with self.assertRaises(ValueError) as e: - Graph.Incidence([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="") + Graph.Biadjacency([[0, 1, 1], [1, 2, 0]], multiple=True, weighted="") self.assertIn(msg, e.exception.args) - def testGetIncidence(self): + def testGetBiadjacency(self): mat = [[0, 1, 1], [1, 1, 0]] v1, v2 = [0, 1], [2, 3, 4] - g = Graph.Incidence(mat) - self.assertTrue(g.get_incidence() == (mat, v1, v2)) + g = Graph.Biadjacency(mat) + self.assertTrue(g.get_biadjacency() == (mat, v1, v2)) g.vs["type2"] = g.vs["type"] - self.assertTrue(g.get_incidence("type2") == (mat, v1, v2)) - self.assertTrue(g.get_incidence(g.vs["type2"]) == (mat, v1, v2)) + self.assertTrue(g.get_biadjacency("type2") == (mat, v1, v2)) + self.assertTrue(g.get_biadjacency(g.vs["type2"]) == (mat, v1, v2)) def testBipartiteProjection(self): g = Graph.Full_Bipartite(10, 5) From fb4723d57b669648565e672af1cbb277d1291d7a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 3 Jul 2023 13:07:02 +0200 Subject: [PATCH 1320/1892] fix: fix two deprecation warnings --- src/_igraph/graphobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 162d37e75..aaf301838 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3881,7 +3881,7 @@ PyObject *igraphmodule_Graph_authority_score( ATTRIBUTE_TYPE_EDGE)) return NULL; arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; - if (igraph_authority_score(&self->g, &res, &value, PyObject_IsTrue(scale_o), + if (igraph_hub_and_authority_scores(&self->g, NULL, &res, &value, PyObject_IsTrue(scale_o), weights, igraphmodule_ARPACKOptions_get(arpack_options))) { igraphmodule_handle_igraph_error(); if (weights) { igraph_vector_destroy(weights); free(weights); } @@ -5669,7 +5669,7 @@ PyObject *igraphmodule_Graph_hub_score( ATTRIBUTE_TYPE_EDGE)) return NULL; arpack_options = (igraphmodule_ARPACKOptionsObject*)arpack_options_o; - if (igraph_hub_score(&self->g, &res, &value, PyObject_IsTrue(scale_o), + if (igraph_hub_and_authority_scores(&self->g, &res, NULL, &value, PyObject_IsTrue(scale_o), weights, igraphmodule_ARPACKOptions_get(arpack_options))) { igraphmodule_handle_igraph_error(); if (weights) { igraph_vector_destroy(weights); free(weights); } From 458d04780e08270d87332dfc887572986fd439b9 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Wed, 5 Jul 2023 12:22:15 +0200 Subject: [PATCH 1321/1892] fix: Correct shlex on Windows. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 36002acd3..88e351802 100644 --- a/setup.py +++ b/setup.py @@ -282,7 +282,7 @@ def _compile_in( # Add any extra CMake args from environment variables if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: - args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"])) + args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"], posix=not building_on_windows_msvc())) # Finally, add the source folder path args.append(str(build_to_source_folder)) From 72240a9e0dffff19dfc0c89bb49ad4f6d0596d05 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sat, 8 Jul 2023 18:45:51 +0200 Subject: [PATCH 1322/1892] fix: fix a memory management issue in PyUnicode_CopyAsString(); closes #679 --- src/_igraph/pyhelpers.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/_igraph/pyhelpers.c b/src/_igraph/pyhelpers.c index 05bdcef53..65954fddb 100644 --- a/src/_igraph/pyhelpers.c +++ b/src/_igraph/pyhelpers.c @@ -117,21 +117,21 @@ PyObject* igraphmodule_PyList_Zeroes(Py_ssize_t len) { * It is the responsibility of the caller to release the C string. */ char* igraphmodule_PyObject_ConvertToCString(PyObject* string) { - char* result; - - if (string == 0) - return 0; + char* result = NULL; - if (!PyBaseString_Check(string)) { - string = PyObject_Str(string); - if (string == 0) - return 0; + if (string == NULL) { + /* Nothing to do */ + } else if (PyBaseString_Check(string)) { + result = PyUnicode_CopyAsString(string); } else { - Py_INCREF(string); - } + string = PyObject_Str(string); + if (string == NULL) { + return NULL; + } - result = PyUnicode_CopyAsString(string); - Py_DECREF(string); + result = PyUnicode_CopyAsString(string); + Py_DECREF(string); + } return result; } @@ -177,19 +177,19 @@ char* PyUnicode_CopyAsString(PyObject* string) { bytes = PyUnicode_AsUTF8String(string); } - if (bytes == 0) { - return 0; + if (bytes == NULL) { + return NULL; } result = PyBytes_AsString(bytes); - if (result == 0) { + if (result == NULL) { Py_DECREF(bytes); - return 0; + return NULL; } - Py_DECREF(bytes); result = strdup(result); - if (result == 0) { + Py_DECREF(bytes); + if (result == NULL) { PyErr_NoMemory(); } From 9252cf267aa154595bff84151c1a4410fd6cef01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= Date: Sun, 9 Jul 2023 20:45:51 +0200 Subject: [PATCH 1323/1892] fix: fix typo in visualize_cliques.py --- doc/examples_sphinx-gallery/visualize_cliques.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/examples_sphinx-gallery/visualize_cliques.py b/doc/examples_sphinx-gallery/visualize_cliques.py index 3fee6fb06..f223a5b4e 100644 --- a/doc/examples_sphinx-gallery/visualize_cliques.py +++ b/doc/examples_sphinx-gallery/visualize_cliques.py @@ -28,7 +28,7 @@ ig.plot( ig.VertexCover(g, [clique]), mark_groups=True, palette=ig.RainbowPalette(), - vetex_size=5, + vertex_size=5, edge_width=0.5, target=ax, ) @@ -60,7 +60,7 @@ ig.VertexCover(g, [clique]), mark_groups=True, palette=ig.RainbowPalette(), - vetex_size=5, + vertex_size=5, target=ax, ) plt.axis('off') From 8a44fe8e5ae02faca5cf2a2423d09b259349d4c1 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 10 Jul 2023 19:52:50 +1000 Subject: [PATCH 1324/1892] Update one mpl reference image, fix bug in edge_curved --- src/igraph/drawing/matplotlib/edge.py | 3 +++ src/igraph/drawing/matplotlib/graph.py | 9 +++++---- .../test_graph/graph_with_curved_edges.png | Bin 48561 -> 40137 bytes tests/drawing/matplotlib/test_graph.py | 8 +++++++- vendor/source/igraph | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index bb77b8ef6..1fc3d2f6c 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -163,6 +163,9 @@ def _compute_paths(self, transform=None): def _compute_path_loop(self, coordt, size, trans_inv): import numpy as np + # TODO: check out non-loop edges for this vertex and try + # fit the loops in the largest wedge. + # Make arc (class method) path = mpl.path.Path.arc(-90, 180) vertices = path.vertices.copy() diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index f4206cadb..29d08ffa3 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -167,7 +167,7 @@ def __init__( def _kwds_post_update(self): self.kwds["layout"] = self.ensure_layout(self.kwds["layout"], self.graph) - self.kwds["edge_curved"] = self._set_edge_curve(**self.kwds) + self._set_edge_curve() self._clear_state() self.stale = True @@ -192,8 +192,9 @@ def get_children(self): artists.extend(self._vertex_labels) return tuple(artists) - def _set_edge_curve(self, **kwds): + def _set_edge_curve(self): graph = self.graph + kwds = self.kwds # Decide whether we need to calculate the curvature of edges # automatically -- and calculate them if needed. @@ -210,12 +211,11 @@ def _set_edge_curve(self, **kwds): if default is True: default = 0.5 default = float(default) - return autocurve( + self.kwds["edge_curved"] = autocurve( graph, attribute=None, default=default, ) - return None def get_vertices(self): """Get VertexCollection artist.""" @@ -557,6 +557,7 @@ def _draw_edges(self): arrow_widths = [] curved = [] for edge, visual_edge in edge_coord_iter: + print(visual_edge) edge_vertices = [vertex_builder[v] for v in edge.tuple] art = edge_drawer.build_patch(visual_edge, *edge_vertices) edgepatches.append(art) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_with_curved_edges.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_with_curved_edges.png index 08f10b08cdae3a8a079d5906b3ee20d24f16b245..3241471116b8be625204740e06f59b4884ff7713 100644 GIT binary patch literal 40137 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 ZJMmBTKOVc>v&j3UsUB9z+JEB8{{hh8-O&I5 literal 48561 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 Date: Mon, 10 Jul 2023 19:57:28 +1000 Subject: [PATCH 1325/1892] Matplotlib: use gca and return container artist --- src/igraph/drawing/__init__.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/igraph/drawing/__init__.py b/src/igraph/drawing/__init__.py index 06bcda90a..8a2ea2a3c 100644 --- a/src/igraph/drawing/__init__.py +++ b/src/igraph/drawing/__init__.py @@ -252,8 +252,8 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): if target is None: if backend == "matplotlib": - # Create a new axes if needed - _, target = plt.subplots() + # Use get current axes, customary in these cases + target = plt.gca() elif backend == "plotly": # Create a new figure if needed target = plotly.graph_objects.Figure() @@ -271,9 +271,6 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): *args, **kwds, ) - # NOTE: for matplotlib, result is the container Artist. It would be - # good to return this instead of target, like we do for Cairo. - # However, that breaks API so let's wait for a major release if save_path is not None: if backend == "matplotlib": @@ -281,6 +278,12 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds): elif backend == "plotly": target.write_image(save_path) + # For matplotlib, return the container artist, which makes it easier + # to manipulate post-facto. The user can always get the artist with + # plt.gca() - as we do, in fact. + if backend == "matplotlib": + return result + return target # Cairo backend From 005b7081770aaaac96ed2aca862d5d93f2638cf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:05:41 +0000 Subject: [PATCH 1326/1892] build(deps): bump pypa/cibuildwheel from 2.13.1 to 2.14.0 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.13.1 to 2.14.0. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.13.1...v2.14.0) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d29e8cdd4..d1f5a12f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -242,7 +242,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.13.1 + uses: pypa/cibuildwheel@v2.14.0 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 8e2e4d67a180fb505ccf01d6fe6052627b6bec95 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 15:36:09 +0200 Subject: [PATCH 1327/1892] feat: added support for building igraph with sanitizers --- etc/lsan-suppr.txt | 12 ++++++++++++ setup.py | 41 +++++++++++++++++++++++++++++++---------- test.sh | 33 +++++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 etc/lsan-suppr.txt diff --git a/etc/lsan-suppr.txt b/etc/lsan-suppr.txt new file mode 100644 index 000000000..719c01d39 --- /dev/null +++ b/etc/lsan-suppr.txt @@ -0,0 +1,12 @@ +leak:_PyObject_Malloc +leak:_PyObject_Realloc +leak:newlockobject +leak:initumath +leak:uint_arrtype_new +leak:ufunc_generic_fastcall +leak:ffi_call_int +leak:array_empty +leak:array_copy +leak:array_cumsum + + diff --git a/setup.py b/setup.py index 88e351802..48e4e975c 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,14 @@ T = TypeVar("T") +def is_envvar_on(name: str) -> bool: + """Returns whether the given environment variable is set to a truthy value + such as '1', 'on' or 'true'. + """ + value = os.environ.get(name, "") + return value and str(value).lower() in ("1", "on", "true") + + def building_on_windows_msvc() -> bool: """Returns True when using the non-MinGW CPython interpreter on Windows""" return platform.system() == "Windows" and sysconfig.get_platform() != "mingw" @@ -64,6 +72,15 @@ def building_with_emscripten() -> bool: return (sysconfig.get_config_var("HOST_GNU_TYPE") or "").endswith("emscripten") +def building_with_sanitizers() -> bool: + """Returns True when the IGRAPH_USE_SANITIZERS envvar is set, indicating that + we want to build the Python interface with AddressSanitizer and LeakSanitizer + enabled. Currently works on Linux only and the primary use-case is to be able + to test igraph with sanitizers in CI. + """ + return platform.system() == "Linux" and is_envvar_on("IGRAPH_USE_SANITIZERS") + + def exclude_from_list(items: Iterable[T], items_to_exclude: Iterable[T]) -> List[T]: """Excludes certain items from a list, keeping the original order of the remaining items.""" @@ -280,6 +297,10 @@ def _compile_in( # to avoid having the architecture name in the LIBPATH (e.g. lib/x86_64-linux-gnu) args.append("-DCMAKE_INSTALL_PREFIX=" + str(install_folder)) + # Compile the C core with sanitizers if needed + if building_with_sanitizers(): + args.append("-DUSE_SANITIZER=Address;Undefined") + # Add any extra CMake args from environment variables if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: args.extend(shlex.split(os.environ["IGRAPH_CMAKE_EXTRA_ARGS"], posix=not building_on_windows_msvc())) @@ -365,6 +386,7 @@ def __init__(self): self.extra_objects = [] self.static_extension = False self.use_pkgconfig = False + self.use_sanitizers = False self.c_core_built = False self.allow_educated_guess = True self._has_pkgconfig = None @@ -463,16 +485,9 @@ def run(self): extra_libraries = os.environ["IGRAPH_EXTRA_LIBRARIES"].split(",") buildcfg.libraries.extend(extra_libraries) - # Override static specification based on environment variable - if "IGRAPH_STATIC_EXTENSION" in os.environ: - if os.environ["IGRAPH_STATIC_EXTENSION"].lower() in [ - "true", - "1", - "on", - ]: - buildcfg.static_extension = True - else: - buildcfg.static_extension = False + # Override build configuration based on environment variables + buildcfg.static_extension = is_envvar_on("IGRAPH_STATIC_EXTENSION") + buildcfg.use_sanitizers = building_with_sanitizers() # Replaces library names with full paths to static libraries # where possible. libm.a is excluded because it caused problems @@ -484,6 +499,11 @@ def run(self): else: buildcfg.replace_static_libraries(exclusions=["m"]) + # Add sanitizer flags + if buildcfg.use_sanitizers: + buildcfg.extra_link_args += ["-fsanitize=address", "-fsanitize=undefined"] + buildcfg.extra_compile_args += ["-fno-omit-frame-pointer"] + # Add extra libraries that may have been specified if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ: extra_libraries = os.environ[ @@ -768,6 +788,7 @@ def process_envvar(name, attr, value): process_envvar("no_pkg_config", "use_pkgconfig", False) process_envvar("no_wait", "wait", False) process_envvar("use_pkg_config", "use_pkgconfig", True) + process_envvar("use_sanitizers", "use_sanitizers", False) def replace_static_libraries(self, only=None, exclusions=None): """Replaces references to libraries with full paths to their static diff --git a/test.sh b/test.sh index 0e55c78e8..7c74a89c8 100755 --- a/test.sh +++ b/test.sh @@ -9,7 +9,7 @@ set -e CLEAN=0 VENV_DIR=.venv -while getopts ":ce:k:" OPTION; do +while getopts ":ce:k:s" OPTION; do case $OPTION in c) CLEAN=1 @@ -20,14 +20,29 @@ while getopts ":ce:k:" OPTION; do k) PYTEST_ARGS="${PYTEST_ARGS} -k $OPTARG" ;; + s) + USE_SANITIZERS=1 + ;; \?) - echo "Usage: $0 [-c] [-e VIRTUALENV]" + echo "Usage: $0 [-c] [-e VIRTUALENV] [-s]" + echo "" + echo "Options:" + echo " -c: clean igraph's already-built C core before running tests" + echo " -e VIRTUALENV: use the given virtualenv instead of .venv" + echo " -s: compile the C core and the Python module with sanitizers enabled" exit 1 ;; esac done shift $((OPTIND -1)) +if [ "x$USE_SANITIZERS" = x1 ]; then + if [ "`python3 -c 'import platform; print(platform.system())'`" != "Linux" ]; then + echo "Compiling igraph with sanitizers is currently supported on Linux only." + exit 1 + fi +fi + if [ ! -d $VENV_DIR ]; then $PYTHON -m venv $VENV_DIR $VENV_DIR/bin/pip install -U pip wheel @@ -41,6 +56,16 @@ fi export MACOSX_DEPLOYMENT_TARGET=12.0 # pip install is called in verbose mode so we can see the compiler warnings -$VENV_DIR/bin/pip install -v .[plotting,test] -$VENV_DIR/bin/pytest tests ${PYTEST_ARGS} +if [ "x$USE_SANITIZERS" = x1 ]; then + # Do not run plotting tests -- they tend to have lots of false positives in + # the sanitizer output + IGRAPH_USE_SANITIZERS=1 $VENV_DIR/bin/pip install -v .[test] + LD_PRELOAD=$(gcc -print-file-name=libasan.so) \ + LSAN_OPTIONS=suppressions=etc/lsan-suppr.txt \ + ASAN_OPTIONS=detect_stack_use_after_return=1 \ + $VENV_DIR/bin/pytest tests ${PYTEST_ARGS} +else + $VENV_DIR/bin/pip install -v .[plotting,test] + $VENV_DIR/bin/pytest tests ${PYTEST_ARGS} +fi From 2d42876f9f2d7ea95ef8497a51c67686abf10327 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:14:25 +0200 Subject: [PATCH 1328/1892] fix: fix a memory leak in Graph.decompose() --- CHANGELOG.md | 2 ++ src/_igraph/convert.c | 8 +++----- src/_igraph/graphobject.c | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20eb8cd50..61c3f463e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### Fixed +- Fixed a minor memory leak in `Graph.decompose()`. + - The default vertex size of the Plotly backend was fixed so the vertices are now visible by default without specifying an explicit size for them. diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index a8a46ab5b..a3a7f28e0 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -2516,11 +2516,9 @@ PyObject* igraphmodule_vector_int_list_t_to_PyList_of_tuples(const igraph_vector * \ingroup python_interface_conversion * \brief Converts an \c igraph_graph_list_t into a Python list of graphs * - * This function transfers ownership of the graphs to Python and frees the pointers - * to them. If it fails, you can call \c igraph_graph_list_destroy if you have to. - * If successful, do nothing and especially do *not* destroy the list, because that - * will destroy each graph inside, which in turns destroys the vertices and edges - * data structures that are now supposedly managed by Python. + * This function transfers ownership of the graphs to Python and empties the + * graph list in parallel. You can (and should) call \c igraph_graph_list_destroy + * regularly after the conversion is done. * * \param v the \c igraph_graph_list_t containing the list to be converted; the * list will become empty after executing this function diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index aaf301838..5f977cd50 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -4831,16 +4831,17 @@ PyObject *igraphmodule_Graph_decompose(igraphmodule_GraphObject * self, return NULL; } - /* We have to create a Python igraph object for every graph returned */ - /* Pointers to each graph are freed, but the graphs themselves are not - * destroyed because the Python class takes over ownership of them, - * in particular of edges and vertices */ + /* We have to create a Python igraph object for every graph returned. During + * the conversion, the graph list will be emptied as the Python list we return + * from the conversion function takes ownership of all the graphs */ list = igraphmodule_graph_list_t_to_PyList(&components, Py_TYPE(self)); if (!list) { igraph_graph_list_destroy(&components); return 0; } + igraph_graph_list_destroy(&components); + return list; } From f7b74eecbcbfa7194cf9000d15d2ebc793057762 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:25:17 +0200 Subject: [PATCH 1329/1892] chore: removed some unused imports --- tests/drawing/cairo/utils.py | 2 +- tests/drawing/matplotlib/test_graph.py | 2 +- tests/drawing/matplotlib/utils.py | 3 --- tests/drawing/plotly/test_graph.py | 5 ++--- tests/drawing/plotly/utils.py | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/drawing/cairo/utils.py b/tests/drawing/cairo/utils.py index 68091ea10..df34e47f6 100644 --- a/tests/drawing/cairo/utils.py +++ b/tests/drawing/cairo/utils.py @@ -1,7 +1,7 @@ # Functions adapted from matplotlib.testing. Credit for the original functions # goes to the amazing folks over at matplotlib. from pathlib import Path -import os + import sys import inspect import functools diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index 43bb999a0..c657cb4b4 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -3,7 +3,7 @@ import unittest -from igraph import Graph, InternalError, plot, VertexClustering, config, Layout +from igraph import Graph, plot, VertexClustering, Layout from ...utils import overridden_configuration diff --git a/tests/drawing/matplotlib/utils.py b/tests/drawing/matplotlib/utils.py index f9f195940..9bf78966a 100644 --- a/tests/drawing/matplotlib/utils.py +++ b/tests/drawing/matplotlib/utils.py @@ -1,6 +1,5 @@ # Functions adapted from matplotlib.testing. Credit for the original functions # goes to the amazing folks over at matplotlib. -from pathlib import Path import sys import inspect import functools @@ -8,8 +7,6 @@ try: import matplotlib from matplotlib.testing.decorators import _collect_new_figures, _ImageComparisonBase - from matplotlib.testing.compare import comparable_formats - import matplotlib.pyplot as plt except ImportError: matplotlib = None diff --git a/tests/drawing/plotly/test_graph.py b/tests/drawing/plotly/test_graph.py index 22ca84b9b..791e6729c 100644 --- a/tests/drawing/plotly/test_graph.py +++ b/tests/drawing/plotly/test_graph.py @@ -1,8 +1,7 @@ -import random import unittest -from igraph import Graph, InternalError, plot, VertexClustering +from igraph import Graph, plot, VertexClustering # FIXME: find a better way to do this that works for both direct call and module # import e.g. tox @@ -75,7 +74,7 @@ def test_mark_groups_squares(self): return fig @image_comparison(baseline_images=["graph_edit_children"]) - def test_mark_groups_squares(self): + def test_graph_edit_children(self): g = Graph.Ring(5) fig = go.Figure() plot(g, target=fig, vertex_shape="circle", diff --git a/tests/drawing/plotly/utils.py b/tests/drawing/plotly/utils.py index 76d96e346..1c6f51b54 100644 --- a/tests/drawing/plotly/utils.py +++ b/tests/drawing/plotly/utils.py @@ -1,7 +1,7 @@ # Functions adapted from matplotlib.testing. Credit for the original functions # goes to the amazing folks over at matplotlib. from pathlib import Path -import os + import sys import inspect import functools From 40cb48e4a1b63acb0ecd29e235889d4ca6ff02d0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:27:28 +0200 Subject: [PATCH 1330/1892] test: added missing Plotly baseline image --- .../graph_mark_groups_squares_directed.json | 1047 +++++++++++++++++ 1 file changed, 1047 insertions(+) create mode 100644 tests/drawing/plotly/baseline_images/graph_mark_groups_squares_directed.json diff --git a/tests/drawing/plotly/baseline_images/graph_mark_groups_squares_directed.json b/tests/drawing/plotly/baseline_images/graph_mark_groups_squares_directed.json new file mode 100644 index 000000000..48afb5b8b --- /dev/null +++ b/tests/drawing/plotly/baseline_images/graph_mark_groups_squares_directed.json @@ -0,0 +1,1047 @@ +{ + "data": [ + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 20.0, + "symbol": "square" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 1.015318095035966 + ], + "y": [ + 0.03435580194714975 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 20.0, + "symbol": "square" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 20.0, + "symbol": "square" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 20.0, + "symbol": "square" + }, + "mode": "markers", + "type": "scatter", + "x": [ + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176 + ] + }, + { + "marker": { + "color": "rgba(255,0,0,255)", + "line": { + "color": "rgba(0,0,0,255)" + }, + "size": 20.0, + "symbol": "square" + }, + "mode": "markers", + "type": "scatter", + "x": [ + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.29010409851547664, + 0.1950972580065446, + 0.1950972580065446, + 0.29010409851547664 + ], + "y": [ + 1.0184451153265959, + 1.0631519409409285, + 0.9737382897122633, + 1.0184451153265959 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8699239050738742, + -0.9649307455828062, + -0.9649307455828062, + -0.8699239050738742 + ], + "y": [ + 0.6328259400443561, + 0.6775327656586887, + 0.5881191144300235, + 0.6328259400443561 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + -0.8616466426732888, + -0.9566534831822209, + -0.9566534831822209, + -0.8616466426732888 + ], + "y": [ + -0.5895891303732176, + -0.544882304758885, + -0.6342959559875502, + -0.5895891303732176 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 0.30349699041342515, + 0.2084901499044931, + 0.2084901499044931, + 0.30349699041342515 + ], + "y": [ + -0.9594640169691343, + -0.9147571913548017, + -1.004170842583467, + -0.9594640169691343 + ] + }, + { + "fillcolor": "#444", + "mode": "lines", + "type": "scatter", + "x": [ + 1.015318095035966, + 0.9203112545270339, + 0.9203112545270339, + 1.015318095035966 + ], + "y": [ + 0.03435580194714975, + 0.07906262756148238, + -0.010351023667182872, + 0.03435580194714975 + ] + } + ], + "layout": { + "shapes": [ + { + "line": { + "color": "#444", + "width": 2.0 + }, + "path": "M 1.015318095035966,0.03435580194714975 L 0.1950972580065446,1.0184451153265959", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2.0 + }, + "path": "M 0.29010409851547664,1.0184451153265959 L -0.9649307455828062,0.6328259400443561", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2.0 + }, + "path": "M -0.8699239050738742,0.6328259400443561 L -0.9566534831822209,-0.5895891303732176", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2.0 + }, + "path": "M -0.8616466426732888,-0.5895891303732176 L 0.2084901499044931,-0.9594640169691344", + "type": "path" + }, + { + "line": { + "color": "#444", + "width": 2.0 + }, + "path": "M 0.30349699041342515,-0.9594640169691343 L 0.9203112545270339,0.03435580194714975", + "type": "path" + } + ], + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0.0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1.0, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "showticklabels": false, + "visible": false + }, + "yaxis": { + "showticklabels": false, + "visible": false + } + } +} \ No newline at end of file From 485435cf1077041509357fb80664863051261c2f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:30:01 +0200 Subject: [PATCH 1331/1892] fix: do not show suppression stats in sanitizer output --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 7c74a89c8..3b3f7b190 100755 --- a/test.sh +++ b/test.sh @@ -61,7 +61,7 @@ if [ "x$USE_SANITIZERS" = x1 ]; then # the sanitizer output IGRAPH_USE_SANITIZERS=1 $VENV_DIR/bin/pip install -v .[test] LD_PRELOAD=$(gcc -print-file-name=libasan.so) \ - LSAN_OPTIONS=suppressions=etc/lsan-suppr.txt \ + LSAN_OPTIONS=suppressions=etc/lsan-suppr.txt:print_suppressions=false \ ASAN_OPTIONS=detect_stack_use_after_return=1 \ $VENV_DIR/bin/pytest tests ${PYTEST_ARGS} else From 830cd41aed623fc64913b7ee323facce47b5913a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:35:54 +0200 Subject: [PATCH 1332/1892] ci: use sanitizer when building the Python module itself --- .github/workflows/build.yml | 17 +++++++---------- setup.py | 7 +++++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d1f5a12f4..7ddcc1592 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -304,19 +304,11 @@ jobs: # When updating 'runs-on', the ASan/UBSan library paths/versions must also be updated for LD_PRELOAD # for the "Test" step below. - # - # The C core is temporarily compiled with -DCMAKE_C_FLAGS="-DNDEBUG" because the Python test suite - # triggers a bug/assertion in RNG_INTEGER(): https://github.com/igraph/igraph/issues/2031 - # When this bug is fixed, remove NDEBUG and increment the cache version to v1. build_with_sanitizer: name: Build with sanitizers for debugging purposes runs-on: ubuntu-20.04 env: - CC: "gcc -fsanitize=address -fsanitize=undefined" - CXX: "g++ -fsanitize=address -fsanitize=undefined" - CFLAGS: "-g -Og -fno-omit-frame-pointer -fdiagnostics-color" - CXXFLAGS: "-g -Og -fno-omit-frame-pointer -fdiagnostics-color" - IGRAPH_CMAKE_EXTRA_ARGS: -DUSE_SANITIZER="Address;Undefined" -DCMAKE_BUILD_TYPE=Debug -DFLEX_KEEP_LINE_NUMBERS=ON -DFORCE_COLORED_OUTPUT=ON -DCMAKE_C_FLAGS="-DNDEBUG" + IGRAPH_CMAKE_EXTRA_ARGS: -DFORCE_COLORED_OUTPUT=ON steps: - uses: actions/checkout@v3 with: @@ -343,10 +335,14 @@ jobs: python-version: '3.11' - name: Build C core + env: + IGRAPH_USE_SANITIZERS: 1 run: | python setup.py build_c_core - name: Build and install Python extension + env: + IGRAPH_USE_SANITIZERS: 1 run: | # NOTE: install calls "build" first python setup.py install @@ -361,6 +357,7 @@ jobs: - name: Test env: LD_PRELOAD: "/lib/x86_64-linux-gnu/libasan.so.5:/lib/x86_64-linux-gnu/libubsan.so.1" - ASAN_OPTIONS: "detect_leaks=0" + ASAN_OPTIONS: "detect_stack_use_after_return=1" + LSAN_OPTIONS: "suppressions=etc/lsan-suppr.txt:print_suppressions=false" run: | python -m pytest --capture=sys tests diff --git a/setup.py b/setup.py index 48e4e975c..9535eecb6 100644 --- a/setup.py +++ b/setup.py @@ -264,6 +264,7 @@ def _compile_in( print("Configuring build...") args = [cmake] + cmake_build_mode = "Release" # Build to wasm requires invocation of the Emscripten SDK if building_with_emscripten(): @@ -300,6 +301,8 @@ def _compile_in( # Compile the C core with sanitizers if needed if building_with_sanitizers(): args.append("-DUSE_SANITIZER=Address;Undefined") + args.append("-DFLEX_KEEP_LINE_NUMBERS=ON") + cmake_build_mode = "Debug" # Add any extra CMake args from environment variables if "IGRAPH_CMAKE_EXTRA_ARGS" in os.environ: @@ -314,7 +317,7 @@ def _compile_in( print("Running build...") # We are _not_ using a parallel build; this is intentional, see igraph/igraph#1755 - retcode = subprocess.call([cmake, "--build", ".", "--config", "Release"]) + retcode = subprocess.call([cmake, "--build", ".", "--config", cmake_build_mode]) if retcode: return False @@ -502,7 +505,7 @@ def run(self): # Add sanitizer flags if buildcfg.use_sanitizers: buildcfg.extra_link_args += ["-fsanitize=address", "-fsanitize=undefined"] - buildcfg.extra_compile_args += ["-fno-omit-frame-pointer"] + buildcfg.extra_compile_args += ["-g", "-Og", "-fno-omit-frame-pointer", "-fdiagnostics-color"] # Add extra libraries that may have been specified if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ: From 6141ee71a9f773ed385129415af331af1f77e795 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 16:44:36 +0200 Subject: [PATCH 1333/1892] ci: adjust config so we don't run the sanitizer on /bin/bash --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ddcc1592..94450505e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -353,11 +353,11 @@ jobs: # Only pytest, and nothing else should be run in this section due to the presence of LD_PRELOAD. # The ASan/UBSan library versions need to be updated when switching to a newer Ubuntu/GCC. - # Leak detection is disabled because of many false (?) positives in Python itself. + # LD_PRELOAD needs to be specified in the "run" section to ensure that we + # do not pick up memory leaks in the wrapper shell (e.g., /bin/bash) - name: Test env: - LD_PRELOAD: "/lib/x86_64-linux-gnu/libasan.so.5:/lib/x86_64-linux-gnu/libubsan.so.1" ASAN_OPTIONS: "detect_stack_use_after_return=1" LSAN_OPTIONS: "suppressions=etc/lsan-suppr.txt:print_suppressions=false" run: | - python -m pytest --capture=sys tests + LD_PRELOAD=/lib/x86_64-linux-gnu/libasan.so.5:/lib/x86_64-linux-gnu/libubsan.so.1 python -m pytest --capture=sys tests From a2c3b28459d139471dd97bc759e3e9ccd66dcebe Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 17:08:30 +0200 Subject: [PATCH 1334/1892] ci: cache busting for sanitizer job --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 94450505e..2337f7896 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -322,7 +322,7 @@ jobs: path: | vendor/build vendor/install - key: C-core-build-sanitizer-v0-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} + key: C-core-build-sanitizer-v1-${{ runner.os }}-${{ hashFiles('.git/modules/vendor/source/igraph/HEAD') }} - name: Install OS dependencies if: steps.cache-c-core.outputs.cache-hit != 'true' # Only needed when building the C core From 47ec0248c00aa211afc38d8abd67fdb29f9183c4 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 17:40:32 +0200 Subject: [PATCH 1335/1892] fix: fix build on macOS --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9535eecb6..b8d2e7da5 100644 --- a/setup.py +++ b/setup.py @@ -489,7 +489,8 @@ def run(self): buildcfg.libraries.extend(extra_libraries) # Override build configuration based on environment variables - buildcfg.static_extension = is_envvar_on("IGRAPH_STATIC_EXTENSION") + if "IGRAPH_STATIC_EXTENSION" in os.environ: + buildcfg.static_extension = is_envvar_on("IGRAPH_STATIC_EXTENSION") buildcfg.use_sanitizers = building_with_sanitizers() # Replaces library names with full paths to static libraries From 35a4ba43b591b33628c31db92e3b678950752102 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 10 Jul 2023 19:20:28 +0200 Subject: [PATCH 1336/1892] fix: fix edge label plotting in Plotly --- src/igraph/drawing/plotly/graph.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/igraph/drawing/plotly/graph.py b/src/igraph/drawing/plotly/graph.py index e24cc1102..956d954af 100644 --- a/src/igraph/drawing/plotly/graph.py +++ b/src/igraph/drawing/plotly/graph.py @@ -250,7 +250,7 @@ def draw(self, graph, *args, **kwds): "text": [], "x": [], "y": [], - "color": [], + # "textfont_color": [], # FIXME: horizontal/vertical alignment, offset, etc? } for label, visual_edge, edge in edge_label_iter: @@ -258,7 +258,7 @@ def draw(self, graph, *args, **kwds): src, dest = edge.tuple src_vertex, dest_vertex = vertex_builder[src], vertex_builder[dest] (x, y), (halign, valign) = edge_drawer.get_label_position( - edge, + visual_edge, src_vertex, dest_vertex, ) @@ -268,7 +268,9 @@ def draw(self, graph, *args, **kwds): lab_args["text"].append(label) lab_args["x"].append(x) lab_args["y"].append(y) - lab_args["color"].append(visual_edge.label_color) + # FIXME: colors do not work yet; apparently we need to convert + # visual_edge.label_color to Plotly's format + # lab_args["textfont_color"].append(visual_edge.label_color) stroke = plotly.graph_objects.Scatter( mode="text", **lab_args, From 69a90260621121163c437b168cfb79743378dc2b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Jul 2023 09:51:20 +0200 Subject: [PATCH 1337/1892] ci: cache emscripten in wasm build --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2337f7896..9d51dc2e2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -179,15 +179,16 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.10.2' + python-version: '3.11.2' - uses: mymindstorm/setup-emsdk@v12 with: - version: '3.1.14' + version: '3.1.32' + actions-cache-folder: 'emsdk-cache' - name: Build wheel run: | - pip install pyodide-build==0.21.0 + pip install pyodide-build==0.23.4 pyodide build - uses: actions/upload-artifact@v3 From b8ded445da7a53002a86c0592170e0fd2ccbf924 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Jul 2023 13:01:59 +0200 Subject: [PATCH 1338/1892] fix: wasm32 size_t is 32-bit so we need to fix the definition of RNG_MAX --- src/_igraph/random.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/_igraph/random.c b/src/_igraph/random.c index b059042d7..61b67b04e 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -44,7 +44,12 @@ typedef struct { } igraph_i_rng_Python_state_t; #define RNG_BITS 32 -#define RNG_MAX ((((size_t) 1) << RNG_BITS) - 1) +#ifdef __wasm32__ + /* size_t is 32-bit on wasm32 so we cannot use the shift trick */ + #define RNG_MAX 0xFFFFFFFF +#else + #define RNG_MAX ((((size_t) 1) << RNG_BITS) - 1) +#endif static igraph_i_rng_Python_state_t igraph_rng_Python_state = {0}; static igraph_rng_t igraph_rng_Python = { From c7ca7b65c7066c6d70c1067bb019347ce937a2b3 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 11 Jul 2023 13:05:04 +0200 Subject: [PATCH 1339/1892] fix: explicitly turn off libxml2 in wasm builds --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index b8d2e7da5..ffb0a5913 100644 --- a/setup.py +++ b/setup.py @@ -277,6 +277,7 @@ def _compile_in( return False args.insert(0, emcmake) args.append("-DIGRAPH_WARNINGS_AS_ERRORS:BOOL=OFF") + args.append("-DIGRAPH_GRAPHML_SUPPORT:BOOL=OFF") # Build the Python interface with vendored libraries for deps in "ARPACK BLAS GLPK GMP LAPACK".split(): From 97f120c61281bc9a0c5d434f44aa2dba7995f9aa Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jul 2023 06:46:20 +1000 Subject: [PATCH 1340/1892] Loops into largest wedge, with a bit of logic --- src/igraph/drawing/matplotlib/edge.py | 198 ++++++++++++++++++++----- src/igraph/drawing/matplotlib/graph.py | 1 - 2 files changed, 160 insertions(+), 39 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 1fc3d2f6c..71cec9691 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -101,6 +101,36 @@ def _get_edge_vertex_sizes(edge_vertices): sizes.append(max(visual_vertex.width, visual_vertex.height)) return sizes + @staticmethod + def _compute_edge_angles(path, trans, directed, curved): + """Compute edge angles for both starting and ending vertices. + + NOTE: The domain of atan2 is (-pi, pi]. + """ + positions = trans(path.vertices) + + # first angle + if (not directed): + x1, y1 = positions[0] + x2, y2 = positions[1] + elif not curved: + x1, y1 = positions[1] + x2, y2 = positions[0] + else: + x1, y1 = positions[3] + x2, y2 = positions[2] + angle1 = atan2(y2 - y1, x2 - x1) + + # second angle + if not directed: + x1, y1 = positions[-1] + x2, y2 = positions[-2] + else: + x1, y1 = positions[-3] + x2, y2 = positions[-1] + angle2 = atan2(y2 - y1, x2 - x1) + return (angle1, angle2) + def _compute_paths(self, transform=None): import numpy as np @@ -110,9 +140,31 @@ def _compute_paths(self, transform=None): trans = transform.transform trans_inv = transform.inverted().transform + # Loops split the largest wedge left open by other + # edges of that vertex. The algo is: + # (i) Find what vertices each loop belongs to + # (ii) While going through the edges, record the angles + # for vertices with loops + # (iii) Plot each loop based on the recorded angles + loop_vertex_dict = { + } + for i, edge_vertices in enumerate(visual_vertices): + if edge_vertices[0] == edge_vertices[1]: + if edge_vertices[0] not in loop_vertex_dict: + loop_vertex_dict[edge_vertices[0]] = { + 'loops': [], + 'angles': [], + } + loop_vertex_dict[edge_vertices[0]]['loops'].append(i) + # Get actual coordinates of the vertex border (rough) paths = [] for i, edge_vertices in enumerate(visual_vertices): + # Loops are positioned post-facto in the space left by the othter edges + if edge_vertices[0] == edge_vertices[1]: + paths.append(None) + continue + coords = np.vstack( [ edge_vertices[0].position, @@ -126,15 +178,7 @@ def _compute_paths(self, transform=None): else: curved = False - # Loops require special attention, discard any previous calculations - if edge_vertices[0] == edge_vertices[1]: - path = self._compute_path_loop( - coordst[0], - sizes[0], - trans_inv, - ) - - elif self._directed: + if self._directed: if (self._arrow_sizes is None) or (self._arrow_widths is None): arrow_size = 0 arrow_width = 0 @@ -157,36 +201,106 @@ def _compute_paths(self, transform=None): curved, ) + # Collect angles for this vertex, to be used for loops plotting below + angles = self._compute_edge_angles(path, trans, self._directed, curved) + if edge_vertices[0] in loop_vertex_dict: + loop_vertex_dict[edge_vertices[0]]['angles'].append(angles[0]) + if edge_vertices[1] in loop_vertex_dict: + loop_vertex_dict[edge_vertices[1]]['angles'].append(angles[1]) + + # Add the path for this non-loop edge paths.append(path) + + # Deal with loops at the end + for visual_vertex, loops_angles in loop_vertex_dict.items(): + coords = np.vstack([visual_vertex.position] * 2) + coordst = trans(coords) + sizes = self._get_edge_vertex_sizes(edge_vertices) + + edge_angles = loops_angles['angles'] + if edge_angles: + edge_angles.sort() + # Circle around + edge_angles.append(edge_angles[0] + 2 * pi) + wedges = [(a2 - a1) for a1, a2 in zip(edge_angles[:-1], edge_angles[1:])] + # Argsort + imax = max(range(len(wedges)), key=lambda i: wedges[i]) + angle1, angle2 = edge_angles[imax], edge_angles[imax + 1] + else: + angle1, angle2 = -pi, pi + + nloops = len(loops_angles['loops']) + for ii, ipath in enumerate(loops_angles['loops']): + angle1i = angle1 + (angle2 - angle1) * ii / nloops + angle2i = angle1 + (angle2 - angle1) * (ii + 1) / nloops + path = self._compute_path_loop( + coordst[0], + sizes[0], + angle1i, angle2i, + trans_inv, + angle_padding_fraction=0.1, + ) + paths[ipath] = path + + return paths - def _compute_path_loop(self, coordt, size, trans_inv): + def _compute_path_loop(self, coordt, size, angle1, angle2, trans_inv, + angle_padding_fraction=0.1): import numpy as np - # TODO: check out non-loop edges for this vertex and try - # fit the loops in the largest wedge. - - # Make arc (class method) - path = mpl.path.Path.arc(-90, 180) - vertices = path.vertices.copy() - codes = path.codes - - # Rescale to be as large as the vertex - vertices *= size / 2 - # Center top right - vertices += size / 2 - # Offset to place and transform to data coordinates - vertices = trans_inv(coordt + vertices) - - # Hack used for any curved lines to deal with facecolor - vertices = np.vstack([ - vertices, - vertices[:-1][::-1], - ]) - codes = np.concatenate([ - codes, - codes[1:], - ]) + # Pad angles to make a little space for tight arrowheads + angle1, angle2 = ( + angle1 * (1 - angle_padding_fraction) + angle2 * angle_padding_fraction, + angle1 * angle_padding_fraction + angle2 * (1 - angle_padding_fraction), + ) + + # Too large wedges, just use a quarter + if angle2 - angle1 > pi / 2: + angle1 = (angle2 + angle1) * 0.5 - pi / 4 + angle1_deg = 180 * angle1 / pi + + # Make arc (class method) + path = mpl.path.Path.arc(angle1_deg - 90, angle1_deg + 180) + vertices = path.vertices.copy() + codes = path.codes + + # Rescale to be as large as the vertex + vertices *= size / 2 + # Center top right for 0 angle_deg, otherwise in the right place (sqrt2 away from center) + angle_center = pi / 4 + angle1 + xcenter = size / 2 / sqrt(2) * cos(angle_center) + ycenter = size / 2 / sqrt(2) * sin(angle_center) + vertices += [xcenter, ycenter] + # Offset to place and transform to data coordinates + vertices = trans_inv(coordt + vertices) + + # Hack used for any curved lines to deal with facecolor + vertices = np.vstack([ + vertices, + vertices[:-1][::-1], + ]) + codes = np.concatenate([ + codes, + codes[1:], + ]) + + # Smaller than 90 deg wedges, make a Bezier + else: + start = size / 2 * np.array([cos(angle1), sin(angle1)]) + end = size / 2 * np.array([cos(angle2), sin(angle2)]) + amix = 0.2 + aux1 = 1.2 * size * np.array([cos(angle1 * (1 - amix) + angle2 * amix), sin(angle1 * (1 - amix) + angle2 * amix)]) + aux2 = 1.2 * size * np.array([cos(angle1 * amix + angle2 * (1 - amix)), sin(angle1 * amix + angle2 * (1 - amix))]) + vertices = np.vstack([ + start, aux1, aux2, end, + aux2, aux1, start, + ]) + # Offset to place and transform to data coordinates + vertices = trans_inv(coordt + vertices) + + codes = ["MOVETO"] + ["CURVE4"] * 6 + codes=[getattr(mpl.path.Path, x) for x in codes] path = mpl.path.Path( vertices, codes=codes, @@ -249,14 +363,14 @@ def _compute_path_directed( path = {"vertices": [], "codes": []} path["codes"].append("MOVETO") if not curved: - path["codes"].extend(["LINETO"] * 5) + path["codes"].extend(["LINETO"] * 6) # Start theta = atan2(*((coordst[1] - coordst[0])[::-1])) voff = 0 * coordst[0] voff[:] = [cos(theta), sin(theta)] voff *= sizes[0] / 2 - path["vertices"].append(coordst[0] + voff) + start = coordst[0] + voff # End with arrow (base-left-top-right-base) theta = atan2(*((coordst[1] - coordst[0])[::-1])) @@ -269,8 +383,12 @@ def _compute_path_directed( headbase = tip - arrow_size * voff_unity headleft = headbase + 0.5 * arrow_width * voff_unity_90 headright = headbase - 0.5 * arrow_width * voff_unity_90 + # This is a dirty trick to make the facecolor work + # without making a separate Patch, which would be a little messy path["vertices"].extend( [ + headbase, + start, headbase, headleft, tip, @@ -308,8 +426,12 @@ def _compute_path_directed( # without making a separate Patch, which would be a little messy path["codes"].extend(["CURVE4"] * 6 + ["LINETO"] * 4) path["vertices"].extend([ - headbase, aux2, aux1, - start, aux1, aux2, + headbase, + aux2, + aux1, + start, + aux1, + aux2, headbase, headleft, tip, diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 29d08ffa3..003a5b281 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -557,7 +557,6 @@ def _draw_edges(self): arrow_widths = [] curved = [] for edge, visual_edge in edge_coord_iter: - print(visual_edge) edge_vertices = [vertex_builder[v] for v in edge.tuple] art = edge_drawer.build_patch(visual_edge, *edge_vertices) edgepatches.append(art) From 031d071dac823ac530afab2d68012a39b090e043 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jul 2023 09:05:49 +1000 Subject: [PATCH 1341/1892] All loops Bezier, add parameter loop_size (undocumented) --- src/igraph/drawing/matplotlib/edge.py | 91 ++++++++++---------------- src/igraph/drawing/matplotlib/graph.py | 3 + 2 files changed, 39 insertions(+), 55 deletions(-) diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index 71cec9691..af5e69727 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -58,6 +58,7 @@ class VisualEdgeBuilder(AttributeCollectorBase): background = None align_label = False zorder = 1 + loop_size = 30 return VisualEdgeBuilder @@ -88,6 +89,7 @@ def __init__(self, *args, **kwargs): self._directed = kwargs.pop("directed", False) self._arrow_sizes = kwargs.pop("arrow_sizes", None) self._arrow_widths = kwargs.pop("arrow_widths", None) + self._loop_sizes = kwargs.pop("loop_sizes", None) self._curved = kwargs.pop("curved", None) super().__init__(*args, **kwargs) @@ -152,10 +154,11 @@ def _compute_paths(self, transform=None): if edge_vertices[0] == edge_vertices[1]: if edge_vertices[0] not in loop_vertex_dict: loop_vertex_dict[edge_vertices[0]] = { - 'loops': [], - 'angles': [], + 'indices': [], + 'sizes': [], + 'edge_angles': [], } - loop_vertex_dict[edge_vertices[0]]['loops'].append(i) + loop_vertex_dict[edge_vertices[0]]['indices'].append(i) # Get actual coordinates of the vertex border (rough) paths = [] @@ -163,6 +166,9 @@ def _compute_paths(self, transform=None): # Loops are positioned post-facto in the space left by the othter edges if edge_vertices[0] == edge_vertices[1]: paths.append(None) + loop_vertex_dict[edge_vertices[0]]['sizes'].append( + self._loop_sizes[i], + ) continue coords = np.vstack( @@ -204,20 +210,20 @@ def _compute_paths(self, transform=None): # Collect angles for this vertex, to be used for loops plotting below angles = self._compute_edge_angles(path, trans, self._directed, curved) if edge_vertices[0] in loop_vertex_dict: - loop_vertex_dict[edge_vertices[0]]['angles'].append(angles[0]) + loop_vertex_dict[edge_vertices[0]]['edge_angles'].append(angles[0]) if edge_vertices[1] in loop_vertex_dict: - loop_vertex_dict[edge_vertices[1]]['angles'].append(angles[1]) + loop_vertex_dict[edge_vertices[1]]['edge_angles'].append(angles[1]) # Add the path for this non-loop edge paths.append(path) # Deal with loops at the end - for visual_vertex, loops_angles in loop_vertex_dict.items(): + for visual_vertex, ldict in loop_vertex_dict.items(): coords = np.vstack([visual_vertex.position] * 2) coordst = trans(coords) - sizes = self._get_edge_vertex_sizes(edge_vertices) + vertex_size = self._get_edge_vertex_sizes([visual_vertex])[0] - edge_angles = loops_angles['angles'] + edge_angles = ldict['edge_angles'] if edge_angles: edge_angles.sort() # Circle around @@ -227,15 +233,17 @@ def _compute_paths(self, transform=None): imax = max(range(len(wedges)), key=lambda i: wedges[i]) angle1, angle2 = edge_angles[imax], edge_angles[imax + 1] else: + # Isolated vertices with loops angle1, angle2 = -pi, pi - nloops = len(loops_angles['loops']) - for ii, ipath in enumerate(loops_angles['loops']): + nloops = len(ldict['indices']) + for ii, (ipath, loop_size) in enumerate(zip(ldict['indices'], ldict['sizes'])): angle1i = angle1 + (angle2 - angle1) * ii / nloops angle2i = angle1 + (angle2 - angle1) * (ii + 1) / nloops path = self._compute_path_loop( coordst[0], - sizes[0], + vertex_size, + loop_size, angle1i, angle2i, trans_inv, angle_padding_fraction=0.1, @@ -245,7 +253,7 @@ def _compute_paths(self, transform=None): return paths - def _compute_path_loop(self, coordt, size, angle1, angle2, trans_inv, + def _compute_path_loop(self, coordt, vertex_size, loop_size, angle1, angle2, trans_inv, angle_padding_fraction=0.1): import numpy as np @@ -258,49 +266,22 @@ def _compute_path_loop(self, coordt, size, angle1, angle2, trans_inv, # Too large wedges, just use a quarter if angle2 - angle1 > pi / 2: angle1 = (angle2 + angle1) * 0.5 - pi / 4 - angle1_deg = 180 * angle1 / pi - - # Make arc (class method) - path = mpl.path.Path.arc(angle1_deg - 90, angle1_deg + 180) - vertices = path.vertices.copy() - codes = path.codes - - # Rescale to be as large as the vertex - vertices *= size / 2 - # Center top right for 0 angle_deg, otherwise in the right place (sqrt2 away from center) - angle_center = pi / 4 + angle1 - xcenter = size / 2 / sqrt(2) * cos(angle_center) - ycenter = size / 2 / sqrt(2) * sin(angle_center) - vertices += [xcenter, ycenter] - # Offset to place and transform to data coordinates - vertices = trans_inv(coordt + vertices) - - # Hack used for any curved lines to deal with facecolor - vertices = np.vstack([ - vertices, - vertices[:-1][::-1], - ]) - codes = np.concatenate([ - codes, - codes[1:], - ]) - - # Smaller than 90 deg wedges, make a Bezier - else: - start = size / 2 * np.array([cos(angle1), sin(angle1)]) - end = size / 2 * np.array([cos(angle2), sin(angle2)]) - amix = 0.2 - aux1 = 1.2 * size * np.array([cos(angle1 * (1 - amix) + angle2 * amix), sin(angle1 * (1 - amix) + angle2 * amix)]) - aux2 = 1.2 * size * np.array([cos(angle1 * amix + angle2 * (1 - amix)), sin(angle1 * amix + angle2 * (1 - amix))]) - vertices = np.vstack([ - start, aux1, aux2, end, - aux2, aux1, start, - ]) - # Offset to place and transform to data coordinates - vertices = trans_inv(coordt + vertices) - - codes = ["MOVETO"] + ["CURVE4"] * 6 - codes=[getattr(mpl.path.Path, x) for x in codes] + angle2 = angle1 + pi / 2 + + start = vertex_size / 2 * np.array([cos(angle1), sin(angle1)]) + end = vertex_size / 2 * np.array([cos(angle2), sin(angle2)]) + amix = 0.15 + aux1 = loop_size * np.array([cos(angle1 * (1 - amix) + angle2 * amix), sin(angle1 * (1 - amix) + angle2 * amix)]) + aux2 = loop_size * np.array([cos(angle1 * amix + angle2 * (1 - amix)), sin(angle1 * amix + angle2 * (1 - amix))]) + vertices = np.vstack([ + start, aux1, aux2, end, + aux2, aux1, start, + ]) + # Offset to place and transform to data coordinates + vertices = trans_inv(coordt + vertices) + + codes = ["MOVETO"] + ["CURVE4"] * 6 + codes=[getattr(mpl.path.Path, x) for x in codes] path = mpl.path.Path( vertices, codes=codes, diff --git a/src/igraph/drawing/matplotlib/graph.py b/src/igraph/drawing/matplotlib/graph.py index 003a5b281..3a67acbd4 100644 --- a/src/igraph/drawing/matplotlib/graph.py +++ b/src/igraph/drawing/matplotlib/graph.py @@ -555,6 +555,7 @@ def _draw_edges(self): edgepatches = [] arrow_sizes = [] arrow_widths = [] + loop_sizes = [] curved = [] for edge, visual_edge in edge_coord_iter: edge_vertices = [vertex_builder[v] for v in edge.tuple] @@ -563,6 +564,7 @@ def _draw_edges(self): visual_vertices.append(edge_vertices) arrow_sizes.append(visual_edge.arrow_size) arrow_widths.append(visual_edge.arrow_width) + loop_sizes.append(visual_edge.loop_size) curved.append(visual_edge.curved) art = EdgeCollection( @@ -571,6 +573,7 @@ def _draw_edges(self): directed=directed, arrow_sizes=arrow_sizes, arrow_widths=arrow_widths, + loop_sizes=loop_sizes, curved=curved, transform=self.axes.transData, ) From 5b46a90c44044863987447eb337abf6993c0c810 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Wed, 12 Jul 2023 09:35:47 +1000 Subject: [PATCH 1342/1892] Test images (tiny pixel diffs), better test for loop size and docs EN/ES --- doc/examples_sphinx-gallery/visual_style.py | 20 ++++++++++++++++++ doc/source/tutorial.es.rst | 19 +++++++++++------ doc/source/tutorial.rst | 7 +++++- .../test_graph/clustering_directed.png | Bin 36628 -> 34962 bytes .../test_graph/clustering_directed_large.png | Bin 62446 -> 61379 bytes .../test_graph/graph_directed.png | Bin 23948 -> 21974 bytes .../graph_directed_curved_loops.png | Bin 23632 -> 23404 bytes .../test_graph/graph_mark_groups_directed.png | Bin 23948 -> 21974 bytes .../graph_mark_groups_squares_directed.png | Bin 19476 -> 17394 bytes tests/drawing/matplotlib/test_graph.py | 3 +++ 10 files changed, 41 insertions(+), 8 deletions(-) diff --git a/doc/examples_sphinx-gallery/visual_style.py b/doc/examples_sphinx-gallery/visual_style.py index 803ed115d..4ac7d05da 100644 --- a/doc/examples_sphinx-gallery/visual_style.py +++ b/doc/examples_sphinx-gallery/visual_style.py @@ -68,3 +68,23 @@ # The :meth:`igraph.drawing.matplotlib.graph.GraphArtist.set` method can # be used to change multiple properties at once and is generally more # efficient than multiple calls to specific ``artist.set_...`` methods. + +# %% +# In the matplotlib backend, you can also specify the size of self-loops, +# either as a number or a sequence of numbers, e.g.: +g = ig.Graph(n=5) +g.add_edge(2, 3) +g.add_edge(0, 0) +g.add_edge(1, 1) +fig, ax = plt.subplots() +ig.plot( + g, + target=ax, + vertex_size=20, + edge_loop_size=[ + 0, # ignored, the first edge is not a loop + 30, # loop for vertex 0 + 80, # loop for vertex 1 + ], +) +plt.show() diff --git a/doc/source/tutorial.es.rst b/doc/source/tutorial.es.rst index ea5727155..1d2a5af7f 100644 --- a/doc/source/tutorial.es.rst +++ b/doc/source/tutorial.es.rst @@ -628,17 +628,17 @@ Atributos de las aristas que controlan los gráficos =============== ====================== ========================================== Attribute name Keyword argument Purpose =============== ====================== ========================================== -``color`` ``edge_color`` Color de la arista +``color`` ``edge_color`` Color de la arista. --------------- ---------------------- ------------------------------------------ -``curved`` ``edge_curved`` la curvatura de la arista. Valores positivos - corresponden a aristas curvadas en sentido +``curved`` ``edge_curved`` La curvatura de la arista. Valores positivos + corresponden a aristas curvadas en sentido contrario a las manecillas del reloj, valores negativos lo contrario. Una curvatura cero representa aristas rectas. ``True`` significa una curvatura de 0.5, ``False`` es una curvatura de cero. --------------- ---------------------- ------------------------------------------ -``font`` ``edge_font`` Familia tipográfica del arista +``font`` ``edge_font`` Familia tipográfica del arista. --------------- ---------------------- ------------------------------------------ ``arrow_size`` ``edge_arrow_size`` Tamaño (longitud) de la punta de flecha del arista si el grafo es dirigido, relativo a @@ -647,13 +647,18 @@ Attribute name Keyword argument Purpose ``arrow_width`` ``edge_arrow_width`` El ancho de las flechas. Relativo a 10 pixels. --------------- ---------------------- ------------------------------------------ -``width`` ``edge_width`` Anchura del borde en píxeles +``loop_size`` ``edge_loop_size`` Tamaño de los bucles. Este atributo no + es utilizado para otras aristas. Este + atributo sólo existe en el backend + matplotlib. +--------------- ---------------------- ------------------------------------------ +``width`` ``edge_width`` Anchura del borde en píxeles. --------------- ---------------------- ------------------------------------------ ``label`` ``edge_label`` Si se especifica, añade una etiqueta al borde. --------------- ---------------------- ------------------------------------------ ``background`` ``edge_background`` Si se especifica, añade una caja rectangular - alrededor de la etiqueta de borde (solo en ) - matplotlib) + alrededor de la etiqueta de borde (solo en + matplotlib). --------------- ---------------------- ------------------------------------------ ``align_label`` ``edge_align_label`` Si es verdadero, gira la etiqueta de la arista de forma que se alinee con la diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index bb0c6b0b6..50b84deb1 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -824,7 +824,12 @@ Attribute name Keyword argument Purpose ``arrow_width`` ``edge_arrow_width`` Width of the arrowhead on the edge if the graph is directed, relative to 10 pixels. --------------- ---------------------- ------------------------------------------ -``width`` ``edge_width`` Width of the edge in pixels +``loop_size`` ``edge_loop_size`` Size of self-loops. This attribute is + ignored by edges that are not loops. + This argument is available only in the + matplotlib backend. +--------------- ---------------------- ------------------------------------------ +``width`` ``edge_width`` Width of the edge in pixels. --------------- ---------------------- ------------------------------------------ ``label`` ``edge_label`` If specified, it adds a label to the edge. --------------- ---------------------- ------------------------------------------ diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed.png index a50e0e8a68c1981445081258be4b2f0ed4cf2c28..3d87f09802a43b9b661765ca73438141b501f876 100644 GIT binary patch literal 34962 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 xi9&^2$K#?A|U_( diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png b/tests/drawing/matplotlib/baseline_images/test_graph/clustering_directed_large.png index 9a8da6e28a8e55f9b23179f4f2258cddc8e0e972..db95896afff154f1f27febf4faee942ce5321317 100644 GIT binary patch literal 61379 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%0Dwr)yb9Osb_cU1e+oCsv%uMbC= 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 ~;;^^d5Y(AL_0mUy-C_ODGT*U4|u<*yahse*v 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 literal 23948 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 ZKC#W>Ugg4^C}0X<@O1TaS?83{1OQ@QUZem3 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png index 9d505b466397c96afaa26cbb855622172a7e6a42..9108a760ce7b860295020295e347aa16ac2a5595 100644 GIT binary patch literal 23404 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%0Df| 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 Lu6{1-oD!M<#+|^X diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_directed.png index e4800a3e0da0987575ca8c577748348b3c179417..6235d7c166d186084b59df6c5a620bda25f02c89 100644 GIT binary patch literal 21974 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 literal 23948 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 ZKC#W>Ugg4^C}0X<@O1TaS?83{1OQ@QUZem3 diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_mark_groups_squares_directed.png index 4655ce1c18d701edc6f0e9554ad003658186b9eb..73278122736faa76651885cc91e95929fb149415 100644 GIT binary patch literal 17394 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 L+E2G0yYxQ*mC`Kp literal 19476 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 diff --git a/tests/drawing/matplotlib/test_graph.py b/tests/drawing/matplotlib/test_graph.py index 67256cbe6..84d9dd2a7 100644 --- a/tests/drawing/matplotlib/test_graph.py +++ b/tests/drawing/matplotlib/test_graph.py @@ -69,10 +69,13 @@ def test_directed_curved_loops(self): plt.close("all") g = Graph.Ring(5, directed=True) g.add_edge(0, 0) + g.add_edge(0, 0) + g.add_edge(2, 2) fig, ax = plt.subplots() plot( g, target=ax, layout=self.layout_small_ring, edge_curved=[0] * 4 + [0.3], + edge_loop_size=[0] * 5 + [30, 50, 40], ) @image_comparison(baseline_images=["graph_mark_groups_directed"], remove_text=True) From 7131d2ebf6f3c025fcff7722e9f4975c01a7ecb9 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Thu, 13 Jul 2023 09:34:00 +1000 Subject: [PATCH 1343/1892] Add arrows to directed loops --- doc/source/tutorial.es.rst | 4 +- doc/source/tutorial.rst | 8 +- src/igraph/drawing/matplotlib/edge.py | 107 ++++++++++++++++++-------- 3 files changed, 85 insertions(+), 34 deletions(-) diff --git a/doc/source/tutorial.es.rst b/doc/source/tutorial.es.rst index 1d2a5af7f..62c74664c 100644 --- a/doc/source/tutorial.es.rst +++ b/doc/source/tutorial.es.rst @@ -647,7 +647,9 @@ Attribute name Keyword argument Purpose ``arrow_width`` ``edge_arrow_width`` El ancho de las flechas. Relativo a 10 pixels. --------------- ---------------------- ------------------------------------------ -``loop_size`` ``edge_loop_size`` Tamaño de los bucles. Este atributo no +``loop_size`` ``edge_loop_size`` Tamaño de los bucles. Puede ser negativo + para escalar con el tamaño del vertice + correspondiente. Este atributo no es utilizado para otras aristas. Este atributo sólo existe en el backend matplotlib. diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 50b84deb1..015e80b91 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -824,9 +824,13 @@ Attribute name Keyword argument Purpose ``arrow_width`` ``edge_arrow_width`` Width of the arrowhead on the edge if the graph is directed, relative to 10 pixels. --------------- ---------------------- ------------------------------------------ -``loop_size`` ``edge_loop_size`` Size of self-loops. This attribute is +``loop_size`` ``edge_loop_size`` Size of self-loops. It can be set as a + negative number, in which case it scales + with the size of the corresponding vertex + (e.g. -1.0 means the loop has the same size + as the vertex). This attribute is ignored by edges that are not loops. - This argument is available only in the + This attribute is available only in the matplotlib backend. --------------- ---------------------- ------------------------------------------ ``width`` ``edge_width`` Width of the edge in pixels. diff --git a/src/igraph/drawing/matplotlib/edge.py b/src/igraph/drawing/matplotlib/edge.py index af5e69727..9f73eb923 100644 --- a/src/igraph/drawing/matplotlib/edge.py +++ b/src/igraph/drawing/matplotlib/edge.py @@ -158,17 +158,35 @@ def _compute_paths(self, transform=None): 'sizes': [], 'edge_angles': [], } + if self._directed: + loop_vertex_dict[edge_vertices[0]]['arrow_sizes'] = [] + loop_vertex_dict[edge_vertices[0]]['arrow_widths'] = [] loop_vertex_dict[edge_vertices[0]]['indices'].append(i) # Get actual coordinates of the vertex border (rough) paths = [] for i, edge_vertices in enumerate(visual_vertices): + if self._directed: + if (self._arrow_sizes is None) or (self._arrow_widths is None): + arrow_size = 0 + arrow_width = 0 + else: + arrow_size = self._arrow_sizes[i] + arrow_width = self._arrow_widths[i] + # Loops are positioned post-facto in the space left by the othter edges if edge_vertices[0] == edge_vertices[1]: paths.append(None) loop_vertex_dict[edge_vertices[0]]['sizes'].append( self._loop_sizes[i], ) + if self._directed: + loop_vertex_dict[edge_vertices[0]]['arrow_sizes'].append( + arrow_size, + ) + loop_vertex_dict[edge_vertices[0]]['arrow_widths'].append( + arrow_width, + ) continue coords = np.vstack( @@ -185,12 +203,6 @@ def _compute_paths(self, transform=None): curved = False if self._directed: - if (self._arrow_sizes is None) or (self._arrow_widths is None): - arrow_size = 0 - arrow_width = 0 - else: - arrow_size = self._arrow_sizes[i] - arrow_width = self._arrow_widths[i] path = self._compute_path_directed( coordst, sizes, @@ -237,26 +249,41 @@ def _compute_paths(self, transform=None): angle1, angle2 = -pi, pi nloops = len(ldict['indices']) - for ii, (ipath, loop_size) in enumerate(zip(ldict['indices'], ldict['sizes'])): - angle1i = angle1 + (angle2 - angle1) * ii / nloops - angle2i = angle1 + (angle2 - angle1) * (ii + 1) / nloops + for i in range(nloops): + angle1i = angle1 + (angle2 - angle1) * i / nloops + angle2i = angle1 + (angle2 - angle1) * (i + 1) / nloops + if self._directed: + loop_kwargs = { + 'arrow_size': ldict['arrow_sizes'][i], + 'arrow_width': ldict['arrow_widths'][i], + } + else: + loop_kwargs = {} path = self._compute_path_loop( coordst[0], vertex_size, - loop_size, + ldict['sizes'][i], angle1i, angle2i, trans_inv, angle_padding_fraction=0.1, + **loop_kwargs, ) - paths[ipath] = path + paths[ldict['indices'][i]] = path return paths - def _compute_path_loop(self, coordt, vertex_size, loop_size, angle1, angle2, trans_inv, - angle_padding_fraction=0.1): + def _compute_path_loop( + self, coordt, vertex_size, loop_size, angle1, angle2, trans_inv, + angle_padding_fraction=0.1, + arrow_size=None, arrow_width=None, + ): import numpy as np + # Special argument for loop size to scale with vertices + if loop_size < 0: + loop_size = -loop_size * vertex_size + # Pad angles to make a little space for tight arrowheads angle1, angle2 = ( angle1 * (1 - angle_padding_fraction) + angle2 * angle_padding_fraction, @@ -264,25 +291,46 @@ def _compute_path_loop(self, coordt, vertex_size, loop_size, angle1, angle2, tra ) # Too large wedges, just use a quarter - if angle2 - angle1 > pi / 2: - angle1 = (angle2 + angle1) * 0.5 - pi / 4 - angle2 = angle1 + pi / 2 + if angle2 - angle1 > pi / 3: + angle_mid = (angle2 + angle1) * 0.5 + angle1 = angle_mid - pi / 6 + angle2 = angle_mid + pi / 6 start = vertex_size / 2 * np.array([cos(angle1), sin(angle1)]) end = vertex_size / 2 * np.array([cos(angle2), sin(angle2)]) - amix = 0.15 + amix = 0.05 aux1 = loop_size * np.array([cos(angle1 * (1 - amix) + angle2 * amix), sin(angle1 * (1 - amix) + angle2 * amix)]) aux2 = loop_size * np.array([cos(angle1 * amix + angle2 * (1 - amix)), sin(angle1 * amix + angle2 * (1 - amix))]) - vertices = np.vstack([ - start, aux1, aux2, end, - aux2, aux1, start, - ]) + + if not self._directed: + vertices = np.vstack([ + start, aux1, aux2, end, + aux2, aux1, start, + ]) + codes = ["MOVETO"] + ["CURVE4"] * 6 + else: + # Tweak the bezier points + aux1 *= (loop_size + arrow_size) / loop_size + aux2 *= (loop_size + arrow_size) / loop_size + # Angle between end/tip and vertex centre + theta = angle2 + voff_unity = np.array([cos(theta), sin(theta)]) + voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] + headbase = end + arrow_size * voff_unity + headleft = headbase + 0.5 * arrow_width * voff_unity_90 + headright = headbase - 0.5 * arrow_width * voff_unity_90 + vertices = np.vstack([ + start, + aux1, aux2, headbase, + headleft, end, headright, headbase, + aux2, aux1, start, + ]) + codes = ["MOVETO"] + ["CURVE4"] * 3 + ["LINETO"] * 4 + ["CURVE4"] * 3 + + # Offset to place and transform to data coordinates vertices = trans_inv(coordt + vertices) - - codes = ["MOVETO"] + ["CURVE4"] * 6 codes=[getattr(mpl.path.Path, x) for x in codes] - path = mpl.path.Path( vertices, codes=codes, ) @@ -386,19 +434,16 @@ def _compute_path_directed( # Start theta = atan2(*((aux1 - coordst[0])[::-1])) - voff = 0 * coordst[0] - voff[:] = [cos(theta), sin(theta)] - voff *= sizes[0] / 2 - start = coordst[0] + voff + voff_unity = 0 * coordst[0] + voff_unity[:] = [cos(theta), sin(theta)] + start = coordst[0] + voff_unity * sizes[0] / 2 # End with arrow (base-left-top-right-base) theta = atan2(*((coordst[1] - aux2)[::-1])) voff_unity = 0 * coordst[0] voff_unity[:] = [cos(theta), sin(theta)] - voff = voff_unity * sizes[1] / 2 - tip = coordst[1] - voff - voff_unity_90 = voff_unity @ [[0, 1], [-1, 0]] + tip = coordst[1] - voff_unity * sizes[1] / 2 headbase = tip - arrow_size * voff_unity headleft = headbase + 0.5 * arrow_width * voff_unity_90 headright = headbase - 0.5 * arrow_width * voff_unity_90 From 66470fbf1b83cc922908f6daec6c358c6bd62545 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Jul 2023 12:44:52 +0200 Subject: [PATCH 1344/1892] fix: revert the commit that prevented the addition of vertices with integer names, refs #693 --- CHANGELOG.md | 2 ++ src/igraph/basic.py | 10 +++++++++- tests/test_basic.py | 5 +++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61c3f463e..53d1f74a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - `Graph.get_incidence()` is now deprecated in favour of `Graph.get_biadjacency()` as it returns the _bipartite adjacency_ matrix of a graph and not its incidence matrix. (The previous name was a mistake). Future versions might re-introduce `Graph.get_incidence()` to return the incidence matrix of a graph. +- Reverted the change in 0.10.5 that prevented adding vertices with integers as vertex names. Now we show a deprecation warning instead, and the addition of vertices with integer names will be prevented from version 0.11.0 only. + ### Fixed - Fixed a minor memory leak in `Graph.decompose()`. diff --git a/src/igraph/basic.py b/src/igraph/basic.py index e672ef7d9..2944d3f2d 100644 --- a/src/igraph/basic.py +++ b/src/igraph/basic.py @@ -1,5 +1,6 @@ from igraph._igraph import GraphBase from igraph.seq import EdgeSeq +from igraph.utils import deprecated def _add_edge(graph, source, target, **kwds): @@ -58,7 +59,14 @@ def _add_vertex(graph, name=None, **kwds): to avoid the overhead of creating t. """ if isinstance(name, int): - raise TypeError("cannot use integers as vertex names; use strings instead") + # raise TypeError("cannot use integers as vertex names; use strings instead") + deprecated( + "You are using integers as vertex names. This is discouraged because " + "most igraph functions interpret integers as vertex _IDs_ and strings " + "as vertex names. For sake of consistency, convert your vertex " + "names to strings before assigning them. Future versions from igraph " + "0.11.0 will disallow integers as vertex names." + ) vid = graph.vcount() graph.add_vertices(1) diff --git a/tests/test_basic.py b/tests/test_basic.py index 6d57c5a17..cec091474 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -120,8 +120,6 @@ def testAddVertex(self): self.assertTrue("name" in g.vertex_attributes()) self.assertEqual(g.vs["name"], [None, "foo"]) - self.assertRaises(TypeError, g.add_vertex, 3) - vertex = g.add_vertex("3") self.assertTrue(g.vcount() == 3 and g.ecount() == 0) self.assertEqual(2, vertex.index) @@ -141,6 +139,9 @@ def testAddVertex(self): self.assertEqual(g.vs["spam"], [None] * 4 + ["cheese"]) self.assertEqual(g.vs["ham"], [None] * 4 + [42]) + with self.assertWarns(DeprecationWarning, msg="integers as vertex names"): + g.add_vertex(42) + def testAddVertices(self): g = Graph() g.add_vertices(2) From 3a2af150a57429a8dcaf6910c39a92c82457bdbb Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Jul 2023 13:05:17 +0200 Subject: [PATCH 1345/1892] chore: updated vendored C core --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index f2c7e65dc..7686bc9a3 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit f2c7e65dc2d8aa274de9346864aa8edadf86a15a +Subproject commit 7686bc9a3bc9d751f6aca8b0445dae15097fd6d7 From 58fd2e78b6cdf4a72a741d918c8269463b8b14f6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Jul 2023 13:05:42 +0200 Subject: [PATCH 1346/1892] chore: updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d1f74a0..d1398225b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Changed +- The C core of igraph was updated to version 0.10.6. + - `Graph.Incidence()` is now deprecated in favour of `Graph.Biadjacency()` as it constructs a bipartite graph from a _bipartite adjacency_ matrix. (The previous name was a mistake). Future versions might re-introduce `Graph.Incidence()` to construct a graph from its incidence matrix. - `Graph.get_incidence()` is now deprecated in favour of `Graph.get_biadjacency()` as it returns the _bipartite adjacency_ matrix of a graph and not its incidence matrix. (The previous name was a mistake). Future versions might re-introduce `Graph.get_incidence()` to return the incidence matrix of a graph. From 786eaf29d27fe75baa33f79989cc477d0c71028f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 13 Jul 2023 13:48:45 +0200 Subject: [PATCH 1347/1892] chore: bumped version to 0.10.6 --- CHANGELOG.md | 2 +- src/igraph/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1398225b..5f764565a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [Unreleased] +## [0.10.6] - 2023-07-13 ### Changed diff --git a/src/igraph/version.py b/src/igraph/version.py index 2b40ae92e..a9750c7c7 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 5) +__version_info__ = (0, 10, 6) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 5e60acd119788969cab6476c295599774c64dfd1 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 13 Jul 2023 15:38:19 +0200 Subject: [PATCH 1348/1892] README: Add citation and clean up section hierarchy. --- README.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 8ae55c896..49cbf9065 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ [![PyPI wheels](https://img.shields.io/pypi/wheel/igraph.svg)](https://pypi.python.org/pypi/igraph) [![Documentation Status](https://readthedocs.org/projects/igraph/badge/?version=latest)](https://igraph.readthedocs.io/) -Python interface for the igraph library ---------------------------------------- +# Python interface for the igraph library igraph is a library for creating and manipulating graphs. It is intended to be as powerful (ie. fast) as possible to enable the @@ -21,7 +20,13 @@ on [our old website](https://igraph.org/python/versions/0.10.1/). igraph is a collaborative work of many people from all around the world — see the [list of contributors here](./CONTRIBUTORS.md). -## Installation from PyPI +## Citation + +If use use igraph in your research, please cite + +> Csardi, G., & Nepusz, T. (2006). The igraph software package for complex network research. InterJournal, Complex Systems, 1695. + +# Installation We aim to provide wheels on PyPI for most of the stock Python versions; typically at least the three most recent minor releases from Python 3.x. @@ -34,7 +39,7 @@ pip install igraph See details in [Installing Python Modules](https://docs.python.org/3/installing/). -### Installation from source with pip on Debian / Ubuntu and derivatives +## Installation from source with pip on Debian / Ubuntu and derivatives If you need to compile igraph from source for some reason, you need to install some dependencies first: @@ -52,7 +57,7 @@ pip install igraph This should compile the C core of igraph as well as the Python extension automatically. -### Installation from source on Windows +## Installation from source on Windows It is now also possible to compile `igraph` from source under Windows for Python 3.7 and later. Make sure that you have Microsoft Visual Studio 2015 or @@ -73,7 +78,7 @@ Also, when building in MSYS2, you need to set the `SETUPTOOLS_USE_DISTUTILS` environment variable to `stdlib`; this is because MSYS2 uses a patched version of `distutils` that conflicts with `setuptools >= 60.0`. -#### Enabling GraphML +### Enabling GraphML By default, GraphML is disabled, because `libxml2` is not available on Windows in the standard installation. You can install `libxml2` on Windows using @@ -110,7 +115,7 @@ You can now build and install `igraph` again by simply running `pip install .`. Please make sure to use a clean source tree, if you built previously without GraphML, it will not update the build. -### Linking to an existing igraph installation +## Linking to an existing igraph installation The source code of the Python package includes the source code of the matching igraph version that the Python interface should compile against. However, if @@ -255,7 +260,7 @@ extras: pip install '.[test]' ``` -## Contributing +# Contributing Contributions to `igraph` are welcome! @@ -279,9 +284,9 @@ if you adjust the source code of the C extension, you need to rebuild it by runn cached in ``vendor/build`` and ``vendor/install`` so subsequent builds are much faster than the first one as the C core does not need to be recompiled. -## Notes +# Notes -### Supported Python versions +## Supported Python versions We aim to keep up with the development cycle of Python and support all official Python versions that have not reached their end of life yet. Currently this @@ -293,7 +298,7 @@ of the non-EOL Python versions. Continuous integration tests are regularly executed on all non-EOL Python branches. -### PyPy +## PyPy This version of igraph is compatible with [PyPy](http://pypy.org/) and is regularly tested on [PyPy](http://pypy.org/) with ``tox``. However, the From 3ced0af39dc6b2ea4892dec8045890d258945395 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 13 Jul 2023 15:40:47 +0200 Subject: [PATCH 1349/1892] Add CITATION.cff --- CITATION.cff | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..e803bfa79 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,53 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: igraph +message: >- + If you use igraph, please cite it using the + metadata from this file. +type: software +authors: + - given-names: Gábor + family-names: Csárdi + orcid: 'https://orcid.org/0000-0001-7098-9676' + - given-names: Tamás + family-names: Nepusz + orcid: 'https://orcid.org/0000-0002-1451-338X' + - given-names: Szabolcs + family-names: Horvát + orcid: 'https://orcid.org/0000-0002-3100-523X' + - given-names: Vincent Antonio + family-names: Traag + orcid: 'https://orcid.org/0000-0003-3170-3879' + - given-names: Fabio + family-names: Zanini + orcid: 'https://orcid.org/0000-0001-7097-8539' + - given-names: Daniel + family-names: Noom +repository-code: 'https://github.com/igraph/python-igraph' +url: 'https://igraph.org' +abstract: >- + igraph is a C library for complex network analysis and + graph theory, with emphasis on efficiency, portability and + ease of use. +keywords: + - network analysis + - graph theory +license: GPL-2.0-or-later +version: 0.10.5 +date-released: '2023-07-01' +preferred-citation: + type: article + authors: + - given-names: Gábor + family-names: Csárdi + orcid: 'https://orcid.org/0000-0001-7098-9676' + - given-names: Tamás + family-names: Nepusz + orcid: 'https://orcid.org/0000-0002-1451-338X' + journal: "InterJournal, Complex Systems" + start: 1695 # First page number + title: "The igraph software package for complex network research" + year: 2006 + type: article From da47a719661e798bb94fd9a9dce17682661902d5 Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 13 Jul 2023 15:44:08 +0200 Subject: [PATCH 1350/1892] Add citation to documentation --- doc/source/index.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/source/index.rst b/doc/source/index.rst index aca648dfb..94f55b1da 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -125,3 +125,10 @@ Indices and tables .. _Cairo: https://www.cairographics.org .. _matplotlib: https://matplotlib.org .. _plotly: https://plotly.com/python/ + +Citation +======== + +If you use igraph in your research, please cite + + Csardi, G., & Nepusz, T. (2006). The igraph software package for complex network research. InterJournal, Complex Systems, 1695. From 731304708c1be60cac747e49cdccfe11273834ca Mon Sep 17 00:00:00 2001 From: Vincent Traag Date: Thu, 13 Jul 2023 15:44:27 +0200 Subject: [PATCH 1351/1892] fix: Correct typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49cbf9065..7e8c39df3 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ see the [list of contributors here](./CONTRIBUTORS.md). ## Citation -If use use igraph in your research, please cite +If you use igraph in your research, please cite > Csardi, G., & Nepusz, T. (2006). The igraph software package for complex network research. InterJournal, Complex Systems, 1695. From 22de5a24f5fd0330eb32605a9fe235fc6cbd301d Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Jul 2023 11:26:40 +0200 Subject: [PATCH 1352/1892] fix: use Dijkstra's algorithm when there are zero weights but no negative weights --- CHANGELOG.md | 6 ++++++ src/_igraph/graphobject.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f764565a..e6c3bbb62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # igraph Python interface changelog +## [master] + +### Changed + +- `Graph.distances()` now uses Dijkstra's algorithm when there are zero weights but no negative weights. Earlier versions switched to Bellman-Ford or Johnson in the presence of zero weights unnecessarily. + ## [0.10.6] - 2023-07-13 ### Changed diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 5f977cd50..4509fa703 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6221,7 +6221,7 @@ PyObject *igraphmodule_Graph_distances( /* Select the most suitable algorithm */ if (weights && igraph_vector_size(weights) > 0) { - if (igraph_vector_min(weights) > 0) { + if (igraph_vector_min(weights) >= 0) { /* Only positive weights, use Dijkstra's algorithm */ e = igraph_distances_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode); } else { @@ -15330,8 +15330,8 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "Calculates shortest path lengths for given vertices in a graph.\n\n" "The algorithm used for the calculations is selected automatically:\n" "a simple BFS is used for unweighted graphs, Dijkstra's algorithm is\n" - "used when all the weights are positive. Otherwise, the Bellman-Ford\n" - "algorithm is used if the number of requested source vertices is larger\n" + "used when all the weights are non-negative. Otherwise, the Bellman-Ford\n" + "algorithm is used if the number of requested source vertices is smaller\n" "than 100 and Johnson's algorithm is used otherwise.\n\n" "@param source: a list containing the source vertex IDs which should be\n" " included in the result. If C{None}, all vertices will be considered.\n" From 6b986676aa0d313f615f44477cf9681da6635bf1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 13:35:02 +0000 Subject: [PATCH 1353/1892] build(deps): bump pypa/cibuildwheel from 2.14.0 to 2.14.1 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.14.0 to 2.14.1. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.14.0...v2.14.1) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d51dc2e2..c6a4d5aa8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" @@ -38,7 +38,7 @@ jobs: CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -63,7 +63,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -88,7 +88,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -155,7 +155,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -243,7 +243,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.14.0 + uses: pypa/cibuildwheel@v2.14.1 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From 1ce6e3ad4aa7145347f1b250da5d6924baa527c8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Jul 2023 15:41:13 +0200 Subject: [PATCH 1354/1892] refactor: rename header guards so we don't abuse the PYTHON_ namespace --- cairo_layout.pickle | Bin 0 -> 126 bytes docker/emscripten/Dockerfile | 28 ++++++++++++++++++++++++++++ src/_igraph/arpackobject.h | 4 ++-- src/_igraph/bfsiter.h | 4 ++-- src/_igraph/common.h | 4 ++-- src/_igraph/convert.h | 4 ++-- src/_igraph/dfsiter.h | 4 ++-- src/_igraph/edgeobject.h | 4 ++-- src/_igraph/edgeseqobject.h | 4 ++-- src/_igraph/error.h | 4 ++-- src/_igraph/filehandle.h | 4 ++-- src/_igraph/graphobject.h | 4 ++-- src/_igraph/indexing.h | 4 ++-- src/_igraph/operators.h | 4 ++-- src/_igraph/platform.h | 4 ++-- src/_igraph/preamble.h | 4 ++-- src/_igraph/pyhelpers.h | 4 ++-- src/_igraph/random.h | 4 ++-- src/_igraph/vertexobject.h | 4 ++-- src/_igraph/vertexseqobject.h | 4 ++-- 20 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 cairo_layout.pickle create mode 100644 docker/emscripten/Dockerfile diff --git a/cairo_layout.pickle b/cairo_layout.pickle new file mode 100644 index 0000000000000000000000000000000000000000..c827b64ec9f4d9e5a5ff4a4352161a3ea2e42787 GIT binary patch literal 126 zcmZo*nOe*M0kKmwfXLnc!<$7%zAx}|w?88?wPfD{=~S@j^~?zE7Udjw`_GHKj!D1f z1dHx}c`oDrGMDe}_HT6R#nbQkK}28OxE?jRPS$<@)jK(7Kg?=}m~e$#Jyx{-mizt} NjH2GsvCmUe^#CNnH?sf$ literal 0 HcmV?d00001 diff --git a/docker/emscripten/Dockerfile b/docker/emscripten/Dockerfile new file mode 100644 index 000000000..b52c94838 --- /dev/null +++ b/docker/emscripten/Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.10.6-bullseye + +SHELL ["/bin/bash", "-c"] + +COPY setup.py.diff.txt /setup.py.diff + +RUN set -ex \ + && echo "Installing flex and bison" \ + && apt-get update \ + && apt-get -y install flex bison \ + && echo "Installing Emscripten" \ + && git clone https://github.com/emscripten-core/emsdk.git \ + && cd emsdk \ + && ./emsdk install latest \ + && ./emsdk activate latest \ + && source "/emsdk/emsdk_env.sh" \ + && cd .. \ + && echo "Cloning igraph repositories" \ + && git clone https://github.com/igraph/python-igraph.git \ + && cd python-igraph/vendor/source \ + && git clone https://github.com/igraph/igraph.git \ + && cd ../.. \ + && echo "Applying patch to setup.py" \ + && git apply < /setup.py.diff \ + && echo "Installing pyodide-build" \ + && pip install pyodide-build \ + && echo "Building igraph wheel" \ + && pyodide build diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index 18ab29d4c..3bfe80991 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_ARPACKOBJECT_H -#define PYTHON_ARPACKOBJECT_H +#ifndef IGRAPHMODULE_ARPACKOBJECT_H +#define IGRAPHMODULE_ARPACKOBJECT_H #include "preamble.h" diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index 60469c011..93a5dacdb 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_BFSITER_H -#define PYTHON_BFSITER_H +#ifndef IGRAPHMODULE_BFSITER_H +#define IGRAPHMODULE_BFSITER_H #include "preamble.h" diff --git a/src/_igraph/common.h b/src/_igraph/common.h index 388591035..ac950ae64 100644 --- a/src/_igraph/common.h +++ b/src/_igraph/common.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_COMMON_H -#define PYTHON_COMMON_H +#ifndef IGRAPHMODULE_COMMON_H +#define IGRAPHMODULE_COMMON_H #include diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index d318ce585..cf474a929 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -25,8 +25,8 @@ /** \defgroup python_interface_conversion Converting between Python and igraph data types * \ingroup python_interface */ -#ifndef PYTHON_CONVERT_H -#define PYTHON_CONVERT_H +#ifndef IGRAPHMODULE_CONVERT_H +#define IGRAPHMODULE_CONVERT_H #include "preamble.h" diff --git a/src/_igraph/dfsiter.h b/src/_igraph/dfsiter.h index 1b21c7139..226df7b64 100644 --- a/src/_igraph/dfsiter.h +++ b/src/_igraph/dfsiter.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_DFSITER_H -#define PYTHON_DFSITER_H +#ifndef IGRAPHMODULE_DFSITER_H +#define IGRAPHMODULE_DFSITER_H #include "preamble.h" diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index 7432d22a3..b506acce4 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_EDGEOBJECT_H -#define PYTHON_EDGEOBJECT_H +#ifndef IGRAPHMODULE_EDGEOBJECT_H +#define IGRAPHMODULE_EDGEOBJECT_H #include "preamble.h" diff --git a/src/_igraph/edgeseqobject.h b/src/_igraph/edgeseqobject.h index 982368d69..c1a7449ee 100644 --- a/src/_igraph/edgeseqobject.h +++ b/src/_igraph/edgeseqobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_EDGESEQOBJECT_H -#define PYTHON_EDGESEQOBJECT_H +#ifndef IGRAPHMODULE_EDGESEQOBJECT_H +#define IGRAPHMODULE_EDGESEQOBJECT_H #include "preamble.h" diff --git a/src/_igraph/error.h b/src/_igraph/error.h index 282136f98..9cbb4eefc 100644 --- a/src/_igraph/error.h +++ b/src/_igraph/error.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_ERROR_H -#define PYTHON_ERROR_H +#ifndef IGRAPHMODULE_ERROR_H +#define IGRAPHMODULE_ERROR_H #include "preamble.h" diff --git a/src/_igraph/filehandle.h b/src/_igraph/filehandle.h index 6f3c5acf7..2ebcddc3e 100644 --- a/src/_igraph/filehandle.h +++ b/src/_igraph/filehandle.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_FILEHANDLE_H -#define PYTHON_FILEHANDLE_H +#ifndef IGRAPHMODULE_FILEHANDLE_H +#define IGRAPHMODULE_FILEHANDLE_H #include "preamble.h" diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 29e022239..02ed0cad8 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_GRAPHOBJECT_H -#define PYTHON_GRAPHOBJECT_H +#ifndef IGRAPHMODULE_GRAPHOBJECT_H +#define IGRAPHMODULE_GRAPHOBJECT_H #include "preamble.h" diff --git a/src/_igraph/indexing.h b/src/_igraph/indexing.h index 6b34ff09c..785e7969d 100644 --- a/src/_igraph/indexing.h +++ b/src/_igraph/indexing.h @@ -21,8 +21,8 @@ */ -#ifndef PYTHON_INDEXING_H -#define PYTHON_INDEXING_H +#ifndef IGRAPHMODULE_INDEXING_H +#define IGRAPHMODULE_INDEXING_H #include "preamble.h" diff --git a/src/_igraph/operators.h b/src/_igraph/operators.h index e90dd88e1..af4c5703e 100644 --- a/src/_igraph/operators.h +++ b/src/_igraph/operators.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_OPERATORS_H -#define PYTHON_OPERATORS_H +#ifndef IGRAPHMODULE_OPERATORS_H +#define IGRAPHMODULE_OPERATORS_H #include "preamble.h" diff --git a/src/_igraph/platform.h b/src/_igraph/platform.h index c1ff8cf6a..7277e6c05 100644 --- a/src/_igraph/platform.h +++ b/src/_igraph/platform.h @@ -22,8 +22,8 @@ */ -#ifndef PYTHON_PLATFORM_H -#define PYTHON_PLATFORM_H +#ifndef IGRAPHMODULE_PLATFORM_H +#define IGRAPHMODULE_PLATFORM_H #ifdef _MSC_VER # define INLINE __forceinline diff --git a/src/_igraph/preamble.h b/src/_igraph/preamble.h index b1c9596b9..e70f91c0a 100644 --- a/src/_igraph/preamble.h +++ b/src/_igraph/preamble.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_IGRAPH_PREAMBLE_H -#define PYTHON_IGRAPH_PREAMBLE_H +#ifndef IGRAPHMODULE_IGRAPH_PREAMBLE_H +#define IGRAPHMODULE_IGRAPH_PREAMBLE_H #ifndef PY_IGRAPH_ALLOW_ENTIRE_PYTHON_API # ifndef Py_LIMITED_API diff --git a/src/_igraph/pyhelpers.h b/src/_igraph/pyhelpers.h index 563765059..c700f1c0d 100644 --- a/src/_igraph/pyhelpers.h +++ b/src/_igraph/pyhelpers.h @@ -21,8 +21,8 @@ */ -#ifndef PYTHON_HELPERS_H -#define PYTHON_HELPERS_H +#ifndef IGRAPHMODULE_HELPERS_H +#define IGRAPHMODULE_HELPERS_H #include "preamble.h" diff --git a/src/_igraph/random.h b/src/_igraph/random.h index 4902e8697..2a83999db 100644 --- a/src/_igraph/random.h +++ b/src/_igraph/random.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_RANDOM_H -#define PYTHON_RANDOM_H +#ifndef IGRAPHMODULE_RANDOM_H +#define IGRAPHMODULE_RANDOM_H #include "preamble.h" diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index e16e8c37c..85180e375 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_VERTEXOBJECT_H -#define PYTHON_VERTEXOBJECT_H +#ifndef IGRAPHMODULE_VERTEXOBJECT_H +#define IGRAPHMODULE_VERTEXOBJECT_H #include "preamble.h" diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index e27c47f08..449308ab8 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -20,8 +20,8 @@ */ -#ifndef PYTHON_VERTEXSEQOBJECT_H -#define PYTHON_VERTEXSEQOBJECT_H +#ifndef IGRAPHMODULE_VERTEXSEQOBJECT_H +#define IGRAPHMODULE_VERTEXSEQOBJECT_H #include "preamble.h" From b8b073159446d0d902634804bbcc87cf564647b8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Jul 2023 15:41:39 +0200 Subject: [PATCH 1355/1892] chore: updated copyright info in header --- src/_igraph/arpackobject.c | 2 +- src/_igraph/arpackobject.h | 2 +- src/_igraph/attributes.c | 2 +- src/_igraph/attributes.h | 2 +- src/_igraph/bfsiter.c | 2 +- src/_igraph/bfsiter.h | 2 +- src/_igraph/common.c | 2 +- src/_igraph/common.h | 2 +- src/_igraph/convert.c | 2 +- src/_igraph/convert.h | 2 +- src/_igraph/edgeobject.c | 2 +- src/_igraph/edgeobject.h | 2 +- src/_igraph/edgeseqobject.c | 2 +- src/_igraph/edgeseqobject.h | 2 +- src/_igraph/error.c | 2 +- src/_igraph/error.h | 2 +- src/_igraph/filehandle.c | 2 +- src/_igraph/filehandle.h | 2 +- src/_igraph/graphobject.c | 2 +- src/_igraph/graphobject.h | 2 +- src/_igraph/igraphmodule.c | 2 +- src/_igraph/igraphmodule_api.h | 2 +- src/_igraph/operators.c | 2 +- src/_igraph/operators.h | 2 +- src/_igraph/platform.h | 2 +- src/_igraph/random.c | 2 +- src/_igraph/random.h | 2 +- src/_igraph/vertexobject.c | 2 +- src/_igraph/vertexobject.h | 2 +- src/_igraph/vertexseqobject.c | 2 +- src/_igraph/vertexseqobject.h | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/_igraph/arpackobject.c b/src/_igraph/arpackobject.c index 047dbba01..293afce4f 100644 --- a/src/_igraph/arpackobject.c +++ b/src/_igraph/arpackobject.c @@ -1,7 +1,7 @@ /* vim:set ts=4 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2007-2012 Tamas Nepusz + Copyright (C) 2007-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/arpackobject.h b/src/_igraph/arpackobject.h index 3bfe80991..b5a487404 100644 --- a/src/_igraph/arpackobject.h +++ b/src/_igraph/arpackobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/attributes.c b/src/_igraph/attributes.c index 26bc5ee77..081d4897a 100644 --- a/src/_igraph/attributes.c +++ b/src/_igraph/attributes.c @@ -1,7 +1,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/attributes.h b/src/_igraph/attributes.h index 010ca4b63..094826d18 100644 --- a/src/_igraph/attributes.h +++ b/src/_igraph/attributes.h @@ -1,7 +1,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/bfsiter.c b/src/_igraph/bfsiter.c index f4b384bdf..f015d7a6a 100644 --- a/src/_igraph/bfsiter.c +++ b/src/_igraph/bfsiter.c @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/bfsiter.h b/src/_igraph/bfsiter.h index 93a5dacdb..d46cbcb24 100644 --- a/src/_igraph/bfsiter.h +++ b/src/_igraph/bfsiter.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/common.c b/src/_igraph/common.c index 751af257c..9a9fc5039 100644 --- a/src/_igraph/common.c +++ b/src/_igraph/common.c @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/common.h b/src/_igraph/common.h index ac950ae64..c474b7d7b 100644 --- a/src/_igraph/common.h +++ b/src/_igraph/common.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index a3a7f28e0..029c31c4f 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -1,7 +1,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index cf474a929..cb65374bf 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/edgeobject.c b/src/_igraph/edgeobject.c index 82b8ae9e4..4780d943d 100644 --- a/src/_igraph/edgeobject.c +++ b/src/_igraph/edgeobject.c @@ -3,7 +3,7 @@ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/edgeobject.h b/src/_igraph/edgeobject.h index b506acce4..7aa4d2dc7 100644 --- a/src/_igraph/edgeobject.h +++ b/src/_igraph/edgeobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/edgeseqobject.c b/src/_igraph/edgeseqobject.c index 2ea925fe5..780de0606 100644 --- a/src/_igraph/edgeseqobject.c +++ b/src/_igraph/edgeseqobject.c @@ -3,7 +3,7 @@ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/edgeseqobject.h b/src/_igraph/edgeseqobject.h index c1a7449ee..a0120348a 100644 --- a/src/_igraph/edgeseqobject.h +++ b/src/_igraph/edgeseqobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/error.c b/src/_igraph/error.c index 4502cd34e..ffe448fad 100644 --- a/src/_igraph/error.c +++ b/src/_igraph/error.c @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/error.h b/src/_igraph/error.h index 9cbb4eefc..ce94c484a 100644 --- a/src/_igraph/error.h +++ b/src/_igraph/error.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/filehandle.c b/src/_igraph/filehandle.c index 1e0a9f3b2..e25c0236a 100644 --- a/src/_igraph/filehandle.c +++ b/src/_igraph/filehandle.c @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Tamas Nepusz + Copyright (C) 2010-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/filehandle.h b/src/_igraph/filehandle.h index 2ebcddc3e..19543f4e7 100644 --- a/src/_igraph/filehandle.h +++ b/src/_igraph/filehandle.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2010-2012 Tamas Nepusz + Copyright (C) 2010-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 4509fa703..2dd4bda16 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1,7 +1,7 @@ /* vim:set ts=4 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/graphobject.h b/src/_igraph/graphobject.h index 02ed0cad8..f6c775c88 100644 --- a/src/_igraph/graphobject.h +++ b/src/_igraph/graphobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index a7edd9315..3d22f5415 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -1,7 +1,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/igraphmodule_api.h b/src/_igraph/igraphmodule_api.h index 1551ca5c8..793e1f382 100644 --- a/src/_igraph/igraphmodule_api.h +++ b/src/_igraph/igraphmodule_api.h @@ -2,7 +2,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/operators.c b/src/_igraph/operators.c index 5aaca69b5..09f5139db 100644 --- a/src/_igraph/operators.c +++ b/src/_igraph/operators.c @@ -1,7 +1,7 @@ /* vim:set ts=4 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/operators.h b/src/_igraph/operators.h index af4c5703e..0ed19d895 100644 --- a/src/_igraph/operators.h +++ b/src/_igraph/operators.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/platform.h b/src/_igraph/platform.h index 7277e6c05..a2d1d0f4b 100644 --- a/src/_igraph/platform.h +++ b/src/_igraph/platform.h @@ -3,7 +3,7 @@ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/random.c b/src/_igraph/random.c index 61b67b04e..6daa68d0f 100644 --- a/src/_igraph/random.c +++ b/src/_igraph/random.c @@ -2,7 +2,7 @@ /* vim:set ts=2 sw=2 sts=2 et: */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/random.h b/src/_igraph/random.h index 2a83999db..13c10e9e5 100644 --- a/src/_igraph/random.h +++ b/src/_igraph/random.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/vertexobject.c b/src/_igraph/vertexobject.c index f2894a36c..69e084816 100644 --- a/src/_igraph/vertexobject.c +++ b/src/_igraph/vertexobject.c @@ -3,7 +3,7 @@ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/vertexobject.h b/src/_igraph/vertexobject.h index 85180e375..f92550d17 100644 --- a/src/_igraph/vertexobject.h +++ b/src/_igraph/vertexobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/vertexseqobject.c b/src/_igraph/vertexseqobject.c index 5183510c6..d751ae76f 100644 --- a/src/_igraph/vertexseqobject.c +++ b/src/_igraph/vertexseqobject.c @@ -3,7 +3,7 @@ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/_igraph/vertexseqobject.h b/src/_igraph/vertexseqobject.h index 449308ab8..b80935311 100644 --- a/src/_igraph/vertexseqobject.h +++ b/src/_igraph/vertexseqobject.h @@ -1,7 +1,7 @@ /* -*- mode: C -*- */ /* IGraph library. - Copyright (C) 2006-2012 Tamas Nepusz + Copyright (C) 2006-2023 Tamas Nepusz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 402949392f20194b1924a5b4685a2959d99f40a1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 17 Jul 2023 16:25:09 +0200 Subject: [PATCH 1356/1892] feat: Graph.distances(), Graph.get_shortest_paths() and Graph.get_shortest_path() now allows the user to select the algorithm explicitly --- CHANGELOG.md | 4 + src/_igraph/convert.c | 16 +++- src/_igraph/convert.h | 10 ++- src/_igraph/graphobject.c | 178 ++++++++++++++++++++++++++++---------- src/_igraph/utils.c | 70 +++++++++++++++ src/_igraph/utils.h | 40 +++++++++ tests/test_structural.py | 20 +++++ 7 files changed, 291 insertions(+), 47 deletions(-) create mode 100644 src/_igraph/utils.c create mode 100644 src/_igraph/utils.h diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c3bbb62..157ffdb34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [master] +### Added + +- `Graph.distances()`, `Graph.get_shortest_path()` and `Graph.get_shortest_paths()` now allow the user to select the algorithm to be used explicitly. + ### Changed - `Graph.distances()` now uses Dijkstra's algorithm when there are zero weights but no negative weights. Earlier versions switched to Bellman-Ford or Johnson in the presence of zero weights unnecessarily. diff --git a/src/_igraph/convert.c b/src/_igraph/convert.c index 029c31c4f..b3294e067 100644 --- a/src/_igraph/convert.c +++ b/src/_igraph/convert.c @@ -20,7 +20,7 @@ */ -/************************ Miscellaneous functions *************************/ +/************************ Conversion functions *************************/ #include #include "attributes.h" @@ -715,6 +715,20 @@ int igraphmodule_PyObject_to_rewiring_t(PyObject *o, igraph_rewiring_t *result) TRANSLATE_ENUM_WITH(rewiring_tt); } +/** + * \brief Converts a Python object to an igraph \c igraphmodule_shortest_path_algorithm_t + */ +int igraphmodule_PyObject_to_shortest_path_algorithm_t(PyObject *o, igraphmodule_shortest_path_algorithm_t *result) { + static igraphmodule_enum_translation_table_entry_t shortest_path_algorithm_tt[] = { + {"auto", IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO}, + {"dijkstra", IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA}, + {"bellman_ford", IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD}, + {"johnson", IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON}, + {0,0} + }; + TRANSLATE_ENUM_WITH(shortest_path_algorithm_tt); +} + /** * \brief Converts a Python object to an igraph \c igraph_spinglass_implementation_t */ diff --git a/src/_igraph/convert.h b/src/_igraph/convert.h index cb65374bf..173366eb3 100644 --- a/src/_igraph/convert.h +++ b/src/_igraph/convert.h @@ -20,7 +20,7 @@ */ -/************************ Miscellaneous functions *************************/ +/************************ Conversion functions *************************/ /** \defgroup python_interface_conversion Converting between Python and igraph data types * \ingroup python_interface */ @@ -45,6 +45,13 @@ typedef struct { int value; } igraphmodule_enum_translation_table_entry_t; +typedef enum { + IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO = 0, + IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA = 1, + IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD = 2, + IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON = 3, +} igraphmodule_shortest_path_algorithm_t; + /* Conversion from PyObject to enum types */ int igraphmodule_PyObject_to_enum(PyObject *o, @@ -76,6 +83,7 @@ int igraphmodule_PyObject_to_random_tree_t(PyObject *o, igraph_random_tree_t *re int igraphmodule_PyObject_to_random_walk_stuck_t(PyObject *o, igraph_random_walk_stuck_t *result); int igraphmodule_PyObject_to_reciprocity_t(PyObject *o, igraph_reciprocity_t *result); int igraphmodule_PyObject_to_rewiring_t(PyObject *o, igraph_rewiring_t *result); +int igraphmodule_PyObject_to_shortest_path_algorithm_t(PyObject *o, igraphmodule_shortest_path_algorithm_t *result); int igraphmodule_PyObject_to_spinglass_implementation_t(PyObject *o, igraph_spinglass_implementation_t *result); int igraphmodule_PyObject_to_spincomm_update_t(PyObject *o, igraph_spincomm_update_t *result); int igraphmodule_PyObject_to_star_mode_t(PyObject *o, igraph_star_mode_t *result); diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 2dd4bda16..15fb67686 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -33,6 +33,7 @@ #include "indexing.h" #include "memory.h" #include "pyhelpers.h" +#include "utils.h" #include "vertexseqobject.h" #include @@ -5213,17 +5214,20 @@ PyObject *igraphmodule_Graph_feedback_arc_set( PyObject *igraphmodule_Graph_get_shortest_path( igraphmodule_GraphObject *self, PyObject *args, PyObject * kwds ) { - static char *kwlist[] = { "v", "to", "weights", "mode", "output", NULL }; + static char *kwlist[] = { "v", "to", "weights", "mode", "output", "algorithm", NULL }; igraph_vector_t *weights=0; igraph_neimode_t mode = IGRAPH_OUT; igraph_integer_t from, to; PyObject *list, *mode_o=Py_None, *weights_o=Py_None, - *output_o=Py_None, *from_o = Py_None, *to_o=Py_None; + *output_o=Py_None, *from_o = Py_None, *to_o=Py_None, + *algorithm_o=Py_None; igraph_vector_int_t vec; igraph_bool_t use_edges = false; + igraph_error_t retval; + igraphmodule_shortest_path_algorithm_t algorithm = IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO!", kwlist, &from_o, - &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO!O", kwlist, &from_o, + &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o, &algorithm_o)) return NULL; if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) @@ -5238,6 +5242,9 @@ PyObject *igraphmodule_Graph_get_shortest_path( if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_shortest_path_algorithm_t(algorithm_o, &algorithm)) + return NULL; + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; @@ -5246,9 +5253,32 @@ PyObject *igraphmodule_Graph_get_shortest_path( return NULL; } + if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) { + algorithm = igraphmodule_select_shortest_path_algorithm( + &self->g, weights, NULL, mode, /* allow_johnson = */ false + ); + } + /* Call the C function */ - if (igraph_get_shortest_path_dijkstra(&self->g, use_edges ? 0 : &vec, - use_edges ? &vec : 0, from, to, weights, mode)) { + switch (algorithm) { + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA: + retval = igraph_get_shortest_path_dijkstra( + &self->g, use_edges ? NULL : &vec, use_edges ? &vec : NULL, from, to, weights, mode + ); + break; + + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD: + retval = igraph_get_shortest_path_bellman_ford( + &self->g, use_edges ? NULL : &vec, use_edges ? &vec : NULL, from, to, weights, mode + ); + break; + + default: + retval = IGRAPH_UNIMPLEMENTED; + PyErr_SetString(PyExc_ValueError, "Algorithm not supported"); + } + + if (retval) { igraph_vector_int_destroy(&vec); if (weights) { igraph_vector_destroy(weights); free(weights); } igraphmodule_handle_igraph_error(); @@ -5387,18 +5417,21 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - static char *kwlist[] = { "v", "to", "weights", "mode", "output", NULL }; - igraph_vector_t *weights=0; + static char *kwlist[] = { "v", "to", "weights", "mode", "output", "algorithm", NULL }; + igraph_vector_t *weights = NULL; igraph_neimode_t mode = IGRAPH_OUT; + igraphmodule_shortest_path_algorithm_t algorithm = IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO; igraph_integer_t from, no_of_target_nodes; igraph_vs_t to; PyObject *list, *mode_o=Py_None, *weights_o=Py_None, - *output_o=Py_None, *from_o = Py_None, *to_o=Py_None; + *output_o=Py_None, *from_o = Py_None, *to_o=Py_None, + *algorithm_o=Py_None; igraph_vector_int_list_t veclist; igraph_bool_t use_edges = false; + igraph_error_t retval; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO!", kwlist, &from_o, - &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO!O", kwlist, &from_o, + &to_o, &weights_o, &mode_o, &PyUnicode_Type, &output_o, &algorithm_o)) return NULL; if (igraphmodule_PyObject_to_vpath_or_epath(output_o, &use_edges)) @@ -5410,6 +5443,9 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return NULL; + if (igraphmodule_PyObject_to_shortest_path_algorithm_t(algorithm_o, &algorithm)) + return NULL; + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) return NULL; @@ -5436,9 +5472,34 @@ PyObject *igraphmodule_Graph_get_shortest_paths(igraphmodule_GraphObject * return NULL; } + if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) { + algorithm = igraphmodule_select_shortest_path_algorithm( + &self->g, weights, NULL, mode, /* allow_johnson = */ false + ); + } + /* Call the C function */ - if (igraph_get_shortest_paths_dijkstra(&self->g, use_edges ? 0 : &veclist, - use_edges ? &veclist : 0, from, to, weights, mode, 0, 0)) { + switch (algorithm) { + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA: + retval = igraph_get_shortest_paths_dijkstra( + &self->g, use_edges ? NULL : &veclist, use_edges ? &veclist : NULL, + from, to, weights, mode, NULL, NULL + ); + break; + + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD: + retval = igraph_get_shortest_paths_bellman_ford( + &self->g, use_edges ? NULL : &veclist, use_edges ? &veclist : NULL, + from, to, weights, mode, NULL, NULL + ); + break; + + default: + retval = IGRAPH_UNIMPLEMENTED; + PyErr_SetString(PyExc_ValueError, "Algorithm not supported"); + } + + if (retval) { igraph_vector_int_list_destroy(&veclist); if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_vs_destroy(&to); @@ -6181,21 +6242,28 @@ PyObject *igraphmodule_Graph_distances( igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds ) { - static char *kwlist[] = { "source", "target", "weights", "mode", NULL }; + static char *kwlist[] = { "source", "target", "weights", "mode", "algorithm", NULL }; PyObject *from_o = NULL, *to_o = NULL, *mode_o = NULL, *weights_o = Py_None; + PyObject *algorithm_o = NULL; PyObject *list = NULL; igraph_matrix_t res; - igraph_vector_t *weights=0; + igraph_vector_t *weights = NULL; igraph_neimode_t mode = IGRAPH_OUT; - igraph_bool_t return_single_from = false, return_single_to = 0; - igraph_error_t e = 0; + igraphmodule_shortest_path_algorithm_t algorithm = IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO; + igraph_bool_t return_single_from = false, return_single_to = false; + igraph_error_t retval = IGRAPH_SUCCESS; igraph_vs_t from_vs, to_vs; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, - &from_o, &to_o, &weights_o, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, + &from_o, &to_o, &weights_o, &mode_o, &algorithm_o)) + return NULL; + + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + return NULL; + + if (igraphmodule_PyObject_to_shortest_path_algorithm_t(algorithm_o, &algorithm)) return NULL; - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) return 0; if (igraphmodule_PyObject_to_vs_t(from_o, &from_vs, &self->g, &return_single_from, 0)) { igraphmodule_handle_igraph_error(); return NULL; @@ -6219,30 +6287,37 @@ PyObject *igraphmodule_Graph_distances( return igraphmodule_handle_igraph_error(); } - /* Select the most suitable algorithm */ - if (weights && igraph_vector_size(weights) > 0) { - if (igraph_vector_min(weights) >= 0) { - /* Only positive weights, use Dijkstra's algorithm */ - e = igraph_distances_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode); - } else { - /* There are negative weights. For a small number of sources, use Bellman-Ford. - * Otherwise, use Johnson's algorithm */ - igraph_integer_t vs_size; - e = igraph_vs_size(&self->g, &from_vs, &vs_size); - if (!e) { - if (vs_size <= 100 || mode != IGRAPH_OUT) { - e = igraph_distances_bellman_ford(&self->g, &res, from_vs, to_vs, weights, mode); - } else { - e = igraph_distances_johnson(&self->g, &res, from_vs, to_vs, weights); - } - } - } - } else { - /* No weights or empty weight vector, use a simple BFS */ - e = igraph_distances(&self->g, &res, from_vs, to_vs, mode); + if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_AUTO) { + algorithm = igraphmodule_select_shortest_path_algorithm( + &self->g, weights, &from_vs, mode, /* allow_johnson = */ true + ); + } + + if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON && mode != IGRAPH_OUT) { + PyErr_SetString(PyExc_ValueError, "Johnson's algorithm is supported for mode=\"out\" only"); + return NULL; } - if (e) { + /* Call the C function */ + switch (algorithm) { + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA: + retval = igraph_distances_dijkstra(&self->g, &res, from_vs, to_vs, weights, mode); + break; + + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD: + retval = igraph_distances_bellman_ford(&self->g, &res, from_vs, to_vs, weights, mode); + break; + + case IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON: + retval = igraph_distances_johnson(&self->g, &res, from_vs, to_vs, weights); + break; + + default: + retval = IGRAPH_UNIMPLEMENTED; + PyErr_SetString(PyExc_ValueError, "Algorithm not supported"); + } + + if (retval) { if (weights) igraph_vector_destroy(weights); igraph_matrix_destroy(&res); igraph_vs_destroy(&from_vs); @@ -14827,7 +14902,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_get_shortest_path */ {"get_shortest_path", (PyCFunction) igraphmodule_Graph_get_shortest_path, METH_VARARGS | METH_KEYWORDS, - "get_shortest_path(v, to, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "get_shortest_path(v, to, weights=None, mode=\"out\", output=\"vpath\", algorithm=\"auto\")\n--\n\n" "Calculates the shortest path from a source vertex to a target vertex in a graph.\n\n" "@param v: the source vertex of the path\n" "@param to: the target vertex of the path\n" @@ -14842,12 +14917,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@param output: determines what should be returned. If this is\n" " C{\"vpath\"}, a list of vertex IDs will be returned. If this is\n" " C{\"epath\"}, edge IDs are returned instead of vertex IDs.\n" + "@param algorithm: the shortest path algorithm to use. C{\"auto\"} selects an\n" + " algorithm automatically based on whether the graph has negative weights\n" + " or not. C{\"dijkstra\"} uses Dijkstra's algorithm. C{\"bellman_ford\"}\n" + " uses the Bellman-Ford algorithm. Ignored for unweighted graphs.\n" "@return: see the documentation of the C{output} parameter.\n"}, /* interface to igraph_get_shortest_paths */ {"get_shortest_paths", (PyCFunction) igraphmodule_Graph_get_shortest_paths, METH_VARARGS | METH_KEYWORDS, - "get_shortest_paths(v, to=None, weights=None, mode=\"out\", output=\"vpath\")\n--\n\n" + "get_shortest_paths(v, to=None, weights=None, mode=\"out\", output=\"vpath\", algorithm=\"auto\")\n--\n\n" "Calculates the shortest paths from/to a given node in a graph.\n\n" "@param v: the source/destination for the calculated paths\n" "@param to: a vertex selector describing the destination/source for\n" @@ -14866,6 +14945,10 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " elements may be empty. Note that in case of mode=C{\"in\"}, the vertices\n" " in a path are returned in reversed order. If C{output=\"epath\"},\n" " edge IDs are returned instead of vertex IDs.\n" + "@param algorithm: the shortest path algorithm to use. C{\"auto\"} selects an\n" + " algorithm automatically based on whether the graph has negative weights\n" + " or not. C{\"dijkstra\"} uses Dijkstra's algorithm. C{\"bellman_ford\"}\n" + " uses the Bellman-Ford algorithm. Ignored for unweighted graphs.\n" "@return: see the documentation of the C{output} parameter.\n"}, /* interface to igraph_get_all_shortest_paths */ @@ -15326,7 +15409,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_distances */ {"distances", (PyCFunction) igraphmodule_Graph_distances, METH_VARARGS | METH_KEYWORDS, - "distances(source=None, target=None, weights=None, mode=\"out\")\n--\n\n" + "distances(source=None, target=None, weights=None, mode=\"out\", algorithm=\"auto\")\n--\n\n" "Calculates shortest path lengths for given vertices in a graph.\n\n" "The algorithm used for the calculations is selected automatically:\n" "a simple BFS is used for unweighted graphs, Dijkstra's algorithm is\n" @@ -15344,6 +15427,11 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " calculation in directed graphs. C{\"out\"} means only outgoing,\n" " C{\"in\"} means only incoming paths. C{\"all\"} means to consider\n" " the directed graph as an undirected one.\n" + "@param algorithm: the shortest path algorithm to use. C{\"auto\"} selects an\n" + " algorithm automatically based on whether the graph has negative weights\n" + " or not. C{\"dijkstra\"} uses Dijkstra's algorithm. C{\"bellman_ford\"}\n" + " uses the Bellman-Ford algorithm. C{\"johnson\"} uses Johnson's\n" + " algorithm. Ignored for unweighted graphs.\n" "@return: the shortest path lengths for given vertices in a matrix\n"}, /* interface to igraph_simplify */ diff --git a/src/_igraph/utils.c b/src/_igraph/utils.c new file mode 100644 index 000000000..2fd58420c --- /dev/null +++ b/src/_igraph/utils.c @@ -0,0 +1,70 @@ +/* + IGraph library. + Copyright (C) 2006-2023 Tamas Nepusz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#include "utils.h" + +/************************ Miscellaneous functions *************************/ + +/** + * Helper function that automatically selects a shortest path algorithm based on + * a graph, its weight vector and the source vertex set (if any). + */ +igraphmodule_shortest_path_algorithm_t igraphmodule_select_shortest_path_algorithm( + const igraph_t* graph, const igraph_vector_t* weights, const igraph_vs_t* from_vs, + igraph_neimode_t mode, igraph_bool_t allow_johnson +) { + igraph_error_t retval; + igraph_integer_t vs_size; + + /* Select the most suitable algorithm */ + if (weights && igraph_vector_size(weights) > 0) { + if (igraph_vector_min(weights) >= 0) { + /* Only positive weights, use Dijkstra's algorithm */ + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA; + } else if (allow_johnson) { + /* There are negative weights. For a small number of sources, use Bellman-Ford. + * Otherwise, use Johnson's algorithm */ + if (from_vs) { + retval = igraph_vs_size(graph, from_vs, &vs_size); + } else { + retval = IGRAPH_SUCCESS; + vs_size = IGRAPH_INTEGER_MAX; + } + if (retval == IGRAPH_SUCCESS) { + if (vs_size <= 100 || mode != IGRAPH_OUT) { + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD; + } else { + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON; + } + } else { + /* Error while calling igraph_vs_size(). Use Bellman-Ford. */ + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD; + } + } else { + /* Johnson's algorithm is disallowed, use Bellman-Ford */ + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_BELLMAN_FORD; + } + } else { + /* No weights or empty weight vector, use Dijstra, which should fall back to + * an unweighted algorithm */ + return IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_DIJKSTRA; + } +} diff --git a/src/_igraph/utils.h b/src/_igraph/utils.h new file mode 100644 index 000000000..bc39b84b9 --- /dev/null +++ b/src/_igraph/utils.h @@ -0,0 +1,40 @@ +/* -*- mode: C -*- */ +/* + IGraph library. + Copyright (C) 2006-2023 Tamas Nepusz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + +#ifndef IGRAPHMODULE_UTILS_H +#define IGRAPHMODULE_UTILS_H + +#include "preamble.h" + +#include +#include +#include "convert.h" +#include "graphobject.h" + +/************************ Miscellaneous functions *************************/ + +igraphmodule_shortest_path_algorithm_t igraphmodule_select_shortest_path_algorithm( + const igraph_t* graph, const igraph_vector_t* weights, const igraph_vs_t* from_vs, + igraph_neimode_t mode, igraph_bool_t allow_johnson +); + +#endif diff --git a/tests/test_structural.py b/tests/test_structural.py index afe6413da..319a6deaa 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -786,6 +786,18 @@ def testDistances(self): g.distances(weights="weight", target=[2, 3]) == [row[2:4] for row in expected] ) + self.assertTrue( + g.distances(weights="weight", target=[2, 3], algorithm="bellman_ford") + == [row[2:4] for row in expected] + ) + self.assertTrue( + g.distances(weights="weight", target=[2, 3], algorithm="johnson") + == [row[2:4] for row in expected] + ) + self.assertRaises( + ValueError, g.distances, + weights="weight", target=[2, 3], algorithm="johnson", mode="in" + ) def testGetShortestPath(self): g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) @@ -795,6 +807,14 @@ def testGetShortestPath(self): self.assertRaises(ValueError, g.get_shortest_path, 0, 3, output="x") self.assertRaises(TypeError, g.get_shortest_path, 0) + def testGetShortestPathManualAlgorithmSelection(self): + g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) + g.es["weight"] = [1] * g.ecount() + + self.assertEqual([0, 1, 3], g.get_shortest_path(0, 3, algorithm="bellman_ford")) + self.assertRaises(ValueError, g.get_shortest_path, 0, 3, algorithm="johnson") + self.assertRaises(ValueError, g.get_shortest_path, 0, 3, algorithm="johnson", mode="in") + def testGetShortestPaths(self): g = Graph(4, [(0, 1), (0, 2), (1, 3), (3, 2), (2, 1)], directed=True) sps = g.get_shortest_paths(0) From c0ae44c489c75066790e43242c056319360c608f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Wed, 19 Jul 2023 17:18:02 +0200 Subject: [PATCH 1357/1892] chore: configure 'git archive' to provide a JSON file with metadata --- .git_archival.json | 7 +++++++ .gitattributes | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .git_archival.json diff --git a/.git_archival.json b/.git_archival.json new file mode 100644 index 000000000..9869b5923 --- /dev/null +++ b/.git_archival.json @@ -0,0 +1,7 @@ +{ + "hash-full": "$Format:%H$", + "hash-short": "$Format:%h$", + "timestamp": "$Format:%cI$", + "refs": "$Format:%D$", + "describe": "$Format:%(describe:tags=true,match=[0-9]*)$" +} diff --git a/.gitattributes b/.gitattributes index c7158f857..56669188e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.c linguist-language=Python +.git_archival.json export-subst From 20892ec7ccc53d0a5916005d40df424f5f145d7b Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 31 Jul 2023 08:44:00 +1000 Subject: [PATCH 1358/1892] Fix last expected image --- .../graph_directed_curved_loops.png | Bin 23404 -> 25013 bytes tests/drawing/matplotlib/test_graph.py | 2 ++ 2 files changed, 2 insertions(+) diff --git a/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png b/tests/drawing/matplotlib/baseline_images/test_graph/graph_directed_curved_loops.png index 9108a760ce7b860295020295e347aa16ac2a5595..9062bfb103f501fc2eac20d04350d87baeb6d53c 100644 GIT binary patch literal 25013 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 YG8bk&nzV^2cuH1>=^MDU(ub4zC!*_FSpWb4 literal 23404 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%0Df| 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 HoD!M Date: Mon, 31 Jul 2023 08:49:22 +1000 Subject: [PATCH 1359/1892] Update igraph submodule and test --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 7686bc9a3..a20205be9 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 7686bc9a3bc9d751f6aca8b0445dae15097fd6d7 +Subproject commit a20205be93f523547578800f315d19367e49fe61 From a2e10ce21dab2c4239699d75768f77b908499ce7 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 31 Jul 2023 10:48:31 +0200 Subject: [PATCH 1360/1892] fix: fix memory leak in Graph.distances() when attempting to use the Johnson algorithm with mode != out --- src/_igraph/graphobject.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 15fb67686..046b47db6 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -6295,7 +6295,7 @@ PyObject *igraphmodule_Graph_distances( if (algorithm == IGRAPHMODULE_SHORTEST_PATH_ALGORITHM_JOHNSON && mode != IGRAPH_OUT) { PyErr_SetString(PyExc_ValueError, "Johnson's algorithm is supported for mode=\"out\" only"); - return NULL; + goto cleanup; } /* Call the C function */ @@ -6318,21 +6318,17 @@ PyObject *igraphmodule_Graph_distances( } if (retval) { - if (weights) igraph_vector_destroy(weights); - igraph_matrix_destroy(&res); - igraph_vs_destroy(&from_vs); - igraph_vs_destroy(&to_vs); igraphmodule_handle_igraph_error(); - return NULL; + goto cleanup; } if (weights) { - igraph_vector_destroy(weights); list = igraphmodule_matrix_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); } else { list = igraphmodule_matrix_t_to_PyList(&res, IGRAPHMODULE_TYPE_INT); } +cleanup: if (weights) { igraph_vector_destroy(weights); free(weights); } igraph_matrix_destroy(&res); From 16500f1e5892e5fd49d5297c9216b3758ffd96bf Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Mon, 31 Jul 2023 19:43:02 +1000 Subject: [PATCH 1361/1892] CHANGELOG for matplotlib revamp --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 157ffdb34..b31c046e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ ### Changed +- The `matplotlib` plotting infrastructure underwent major surgery and is now able to show consistent vertex and edge drawings at any level of zoom, including with animations, and for any aspect ratio. +- As a consequence of the restructuring at the previous point, vertex sizes are now specified in figure points and are not affected by axis limits or zoom. With the current conventions, `vertex_size=25` is a reasonable size for `igraph.plot`. +- As another consequence of the above, vertex labels now support offsets from the vertex center, in figure point units. +- As another consequence of the above, self loops are now looking better and their size can be controlled using the `edge_loop_size` argument in `igraph.plot`. +- As another consequence of the above, if using the `matplotlib` backend when plotting a graph, `igraph.plot` now does not return the `Axes` anymore. Instead, it returns a container artist called `GraphArtist`, which contains as children the elements of the graph plot: a `VertexCollection` for the vertices, and `EdgeCollection` for the edges, and so on. These objects can be used to modify the plot after the initial rendering, e.g. inside a Jupyter notebook, to fine tune the appearance of the plot. While documentation on specific graphic elements is still scant, more descriptive examples will follow in the future. - `Graph.distances()` now uses Dijkstra's algorithm when there are zero weights but no negative weights. Earlier versions switched to Bellman-Ford or Johnson in the presence of zero weights unnecessarily. ## [0.10.6] - 2023-07-13 From ada854a19625075883c7353c2ffd2b0779a60e55 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 18 Aug 2023 13:49:20 +0200 Subject: [PATCH 1362/1892] doc: extend docs of Graph.Watts_Strogatz(), closes #702 --- src/_igraph/graphobject.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 046b47db6..28abc2987 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -14288,6 +14288,18 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { {"Watts_Strogatz", (PyCFunction) igraphmodule_Graph_Watts_Strogatz, METH_VARARGS | METH_CLASS | METH_KEYWORDS, "Watts_Strogatz(dim, size, nei, p, loops=False, multiple=False)\n--\n\n" + "This function generates networks with the small-world property based on a\n" + "variant of the Watts-Strogatz model. The network is obtained by first creating\n" + "a periodic undirected lattice, then rewiring both endpoints of each edge with\n" + "probability I{p}, while avoiding the creation of multi-edges.\n\n" + "This process differs from the original model of Watts and Strogatz (see\n" + "reference) in that it rewires I{both} endpoints of edges. Thus in the limit\n" + "of C{p=1}, we obtain a G(n,m) random graph with the same number of vertices\n" + "and edges as the original lattice. In comparison, the original Watts-Strogatz\n" + "model only rewires a single endpoint of each edge, thus the network does not\n" + "become fully random even for p=1.\n\n" + "For appropriate choices of I{p}, both models exhibit the property of\n" + "simultaneously having short path lengths and high clustering.\n\n" "@param dim: the dimension of the lattice\n" "@param size: the size of the lattice along all dimensions\n" "@param nei: value giving the distance (number of steps) within which\n" From 92f0abd10fe232a133438fe79d15412223091bb1 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Sun, 20 Aug 2023 18:38:57 +0200 Subject: [PATCH 1363/1892] fix: use the same macOS deployment target version when compiling the C core as the one that was used when compiling Python --- setup.py | 5 +++++ test.sh | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ffb0a5913..1165148c5 100644 --- a/setup.py +++ b/setup.py @@ -299,6 +299,11 @@ def _compile_in( # to avoid having the architecture name in the LIBPATH (e.g. lib/x86_64-linux-gnu) args.append("-DCMAKE_INSTALL_PREFIX=" + str(install_folder)) + # On macOS, compile the C core with the same macOS deployment target as + # the one that was used to compile Python itself + if sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET"): + args.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=" + sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")) + # Compile the C core with sanitizers if needed if building_with_sanitizers(): args.append("-DUSE_SANITIZER=Address;Undefined") diff --git a/test.sh b/test.sh index 3b3f7b190..8e59d034a 100755 --- a/test.sh +++ b/test.sh @@ -53,8 +53,6 @@ if [ x$CLEAN = x1 ]; then rm -rf vendor/build vendor/install fi -export MACOSX_DEPLOYMENT_TARGET=12.0 - # pip install is called in verbose mode so we can see the compiler warnings if [ "x$USE_SANITIZERS" = x1 ]; then # Do not run plotting tests -- they tend to have lots of false positives in From 2f9b374bfed544765262a05de899ccce429c1c13 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 1 Sep 2023 22:14:39 +0200 Subject: [PATCH 1364/1892] fix: fix bug in EdgeSeq.select(_incident=...) when the graph is directed --- src/igraph/seq.py | 2 +- tests/test_edgeseq.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/igraph/seq.py b/src/igraph/seq.py index 0f0dc2168..950bc473e 100644 --- a/src/igraph/seq.py +++ b/src/igraph/seq.py @@ -601,7 +601,7 @@ def _ensure_set(value): # the vertices specified candidates = set() for v in value: - candidates.update(es.graph.incident(v)) + candidates.update(es.graph.incident(v, mode="all")) if not es.is_all(): # Find those that are in the current edge sequence diff --git a/tests/test_edgeseq.py b/tests/test_edgeseq.py index df14bd490..c3259257a 100644 --- a/tests/test_edgeseq.py +++ b/tests/test_edgeseq.py @@ -85,7 +85,10 @@ def testPhantomEdge(self): self.assertRaises(ValueError, getattr, e, "tuple") self.assertRaises(ValueError, getattr, e, "vertex_tuple") - @unittest.skipIf(is_pypy, "skipped on PyPy because we do not have access to docstrings") + @unittest.skipIf( + is_pypy, + "skipped on PyPy because we do not have access to docstrings" + ) def testProxyMethods(self): g = Graph.GRG(10, 0.5) e = g.es[0] @@ -150,6 +153,8 @@ def testIndexing(self): @unittest.skipIf(np is None, "test case depends on NumPy") def testNumPyIndexing(self): + assert np is not None + n = self.g.ecount() for i in range(n): arr = np.array([i]) @@ -334,6 +339,16 @@ def testIncidentFiltering(self): self.assertTrue(all((e.source in vs3 or e.target in vs3) for e in es_filtered)) self.assert_edges_unique_in(es_filtered) + def testIncidentFilteringDirected(self): + # Test case from https://igraph.discourse.group/t/edge-select-using-incident-on-directed-graphs/1645 + g = Graph([(0, 1), (1, 2), (2, 3)], directed=True) + + vs = (1, ) + es = g.es.select(_incident=vs) + self.assertEqual(2, len(es)) + self.assertTrue(all((e.source in vs or e.target in vs) for e in es)) + self.assert_edges_unique_in(es) + def testIncidentFilteringByNames(self): g = Graph.Lattice([10, 10], circular=False) vs = (0, 1, 10, 11) From ea1c19589f1e24360364bde3dd302ecdd9019d5c Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 15:18:26 +0200 Subject: [PATCH 1365/1892] ci: update cibuildwheel, skip tests on Python 3.12 until NumPy 1.26 is out --- .github/workflows/build.yml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6a4d5aa8..5ae731bf0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,16 +29,17 @@ jobs: python-version: '3.8' - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" - # Skip tests for Python 3.10 and 3.11 because SciPy does not have - # 32-bit wheels for Linux - CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686" + # Skip tests for Python 3.10 onwards because SciPy does not have + # 32-bit wheels for Linux. Also skip tests for Python 3.12 until + # NumPy 1.26 is out (with Python 3.12 wheels) + CIBW_TEST_SKIP: "cp310-manylinux_i686 cp311-manylinux_i686 cp312-manylinux_i686 cp312-*" - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" @@ -68,6 +69,9 @@ jobs: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" + # Skip tests for Python 3.12 until NumPy 1.26 is out (with Python + # 3.12 wheels) + CIBW_TEST_SKIP: "cp312-*" - uses: actions/upload-artifact@v3 with: @@ -94,6 +98,9 @@ jobs: CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test-musl]' && python -m pytest -v tests" + # Skip tests for Python 3.12 until NumPy 1.26 is out (with Python + # 3.12 wheels) + CIBW_TEST_SKIP: "cp312-*" - uses: actions/upload-artifact@v3 with: @@ -161,6 +168,9 @@ jobs: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_ENVIRONMENT: "LDFLAGS=-L$HOME/local/lib" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} ${{ matrix.cmake_extra_args }} -DCMAKE_PREFIX_PATH=$HOME/local + # Skip tests for Python 3.12 until NumPy 1.26 is out (with Python + # 3.12 wheels) + CIBW_TEST_SKIP: "cp312-*" - uses: actions/upload-artifact@v3 with: @@ -248,9 +258,10 @@ jobs: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" CIBW_TEST_COMMAND: "cd /d {project} && pip install --prefer-binary \".[test]\" && python -m pytest tests" - # Skip tests for Python 3.10 and 3.11 because SciPy does not have - # 32-bit wheels for Windows - CIBW_TEST_SKIP: "cp310-win32 cp311-win32" + # Skip tests for Python 3.10 onwards because SciPy does not have + # 32-bit wheels for Windows. Also skip tests for Python 3.12 until + # NumPy 1.26 is out (with Python 3.12 wheels) + CIBW_TEST_SKIP: "cp310-win32 cp311-win32 cp312-win32 cp312-*" IGRAPH_CMAKE_EXTRA_ARGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }}-windows-static-md -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -A ${{ matrix.cmake_arch }} IGRAPH_EXTRA_LIBRARY_PATH: C:/vcpkg/installed/${{ matrix.vcpkg_arch }}-windows-static-md/lib/ IGRAPH_STATIC_EXTENSION: True From 62b5541040f3d296d7fdcfd75856a99f047b3879 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:19:03 +0000 Subject: [PATCH 1366/1892] build(deps): bump pypa/cibuildwheel from 2.14.1 to 2.15.0 Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.14.1 to 2.15.0. - [Release notes](https://github.com/pypa/cibuildwheel/releases) - [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md) - [Commits](https://github.com/pypa/cibuildwheel/compare/v2.14.1...v2.15.0) --- updated-dependencies: - dependency-name: pypa/cibuildwheel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ae731bf0..a4ea62cdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (manylinux) - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -92,7 +92,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Build wheels (musllinux) - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 @@ -162,7 +162,7 @@ jobs: cmake --install . - name: Build wheels - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_ARCHS_MACOS: "${{ matrix.wheel_arch }}" CIBW_BEFORE_BUILD: "python setup.py build_c_core" @@ -253,7 +253,7 @@ jobs: shell: cmd - name: Build wheels - uses: pypa/cibuildwheel@v2.14.1 + uses: pypa/cibuildwheel@v2.15.0 env: CIBW_BEFORE_BUILD: "python setup.py build_c_core" CIBW_BUILD: "*-${{ matrix.wheel_arch }}" From dbbe6f7043f5c2ac1caac96edd200968b6920a6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:25:05 +0000 Subject: [PATCH 1367/1892] build(deps): bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ae731bf0..233cb05bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: wheel_arch: [x86_64, i686] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -54,7 +54,7 @@ jobs: runs-on: ubuntu-20.04 if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-20.04 if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -121,7 +121,7 @@ jobs: wheel_arch: arm64 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -181,7 +181,7 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -219,7 +219,7 @@ jobs: vcpkg_arch: x64 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -276,7 +276,7 @@ jobs: name: Build sdist and test extra dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 @@ -322,7 +322,7 @@ jobs: env: IGRAPH_CMAKE_EXTRA_ARGS: -DFORCE_COLORED_OUTPUT=ON steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 From f01bd6e88fbb4d2778d3b0a34dff2b4ba53cdd56 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 18:38:27 +0200 Subject: [PATCH 1368/1892] chore: updated vendored C core --- vendor/source/igraph | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/source/igraph b/vendor/source/igraph index 7686bc9a3..6559f7e92 160000 --- a/vendor/source/igraph +++ b/vendor/source/igraph @@ -1 +1 @@ -Subproject commit 7686bc9a3bc9d751f6aca8b0445dae15097fd6d7 +Subproject commit 6559f7e92f64d6f71a61063132dace9ce72cf680 From a9c7d900ee0a838e90c14967c2abd987c50e339e Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 18:42:00 +0200 Subject: [PATCH 1369/1892] chore: updated changelog --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 157ffdb34..2474f0c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,16 @@ ### Changed +- The C core of igraph was updated to version 0.10.7. + - `Graph.distances()` now uses Dijkstra's algorithm when there are zero weights but no negative weights. Earlier versions switched to Bellman-Ford or Johnson in the presence of zero weights unnecessarily. +### Fixed + +- Fixed a bug in `EdgeSeq.select(_incident=...)` for undirected graphs. + +- Fixed a memory leak in `Graph.distances()` when attempting to use Johnson's algorithm with `mode != "out"` + ## [0.10.6] - 2023-07-13 ### Changed @@ -542,7 +550,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[Unreleased]: https://github.com/igraph/python-igraph/compare/0.10.5...main +[master]: https://github.com/igraph/python-igraph/compare/0.10.6...main +[0.10.6]: https://github.com/igraph/python-igraph/compare/0.10.5...0.10.6 [0.10.5]: https://github.com/igraph/python-igraph/compare/0.10.4...0.10.5 [0.10.4]: https://github.com/igraph/python-igraph/compare/0.10.3...0.10.4 [0.10.3]: https://github.com/igraph/python-igraph/compare/0.10.2...0.10.3 From f0287f5f43c2a2991ba6eb47603dda183ccc6058 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 18:47:36 +0200 Subject: [PATCH 1370/1892] fix: fix Pandas deprecation warning in unit tests, closes #705 --- src/igraph/io/objects.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/igraph/io/objects.py b/src/igraph/io/objects.py index 6cc550a24..7c29cfd9e 100644 --- a/src/igraph/io/objects.py +++ b/src/igraph/io/objects.py @@ -418,8 +418,8 @@ def _construct_graph_from_dataframe( if use_vids: if ( - str(edges.dtypes[0]).startswith(("int", "Int")) - and str(edges.dtypes[1]).startswith(("int", "Int")) + str(edges.dtypes.iloc[0]).startswith(("int", "Int")) + and str(edges.dtypes.iloc[1]).startswith(("int", "Int")) ): # Check pandas nullable integer data type: # https://pandas.pydata.org/docs/user_guide/integer_na.html From 79fe9e60ea3aa66029a3f20fdce9176ef74bff03 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 18:51:26 +0200 Subject: [PATCH 1371/1892] refactor: use igraph_bipartite_game_gnp() or _gnm() instead of the deprecated igraph_bipartite_game() --- src/_igraph/graphobject.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 28abc2987..069aeb1df 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3153,11 +3153,11 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, igraph_t g; Py_ssize_t n1, n2, m = -1; double p = -1.0; - igraph_erdos_renyi_t t; igraph_neimode_t neimode = IGRAPH_ALL; PyObject *directed_o = Py_False, *neimode_o = NULL; igraph_vector_bool_t vertex_types; PyObject *vertex_types_o; + igraph_error_t retval; static char *kwlist[] = { "n1", "n2", "p", "m", "directed", "neimode", NULL }; @@ -3179,8 +3179,6 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, return NULL; } - t = (m == -1) ? IGRAPH_ERDOS_RENYI_GNP : IGRAPH_ERDOS_RENYI_GNM; - if (igraphmodule_PyObject_to_neimode_t(neimode_o, &neimode)) return NULL; @@ -3189,10 +3187,16 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, return NULL; } - if (igraph_bipartite_game(&g, &vertex_types, t, n1, n2, p, m, PyObject_IsTrue(directed_o), neimode)) { - igraph_vector_bool_destroy(&vertex_types); - igraphmodule_handle_igraph_error(); - return NULL; + if (m == -1) { + /* GNP model */ + retval = igraph_bipartite_game_gnp( + &g, &vertex_types, n1, n2, p, PyObject_IsTrue(directed_o), neimode + ); + } else { + /* GNM model */ + retval = igraph_bipartite_game_gnm( + &g, &vertex_types, n1, n2, m, PyObject_IsTrue(directed_o), neimode + ); } CREATE_GRAPH_FROM_TYPE(self, g, type); From d3100c8a58eedf6f4a664d782cb99967f98a3b7a Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Mon, 4 Sep 2023 18:58:53 +0200 Subject: [PATCH 1372/1892] chore: bumped version to 0.10.7 --- CHANGELOG.md | 5 +++-- src/igraph/version.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2474f0c2b..9f016d831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [master] +## [0.10.7] - 2023-09-04 ### Added @@ -550,7 +550,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[master]: https://github.com/igraph/python-igraph/compare/0.10.6...main +[master]: https://github.com/igraph/python-igraph/compare/0.10.7...main +[0.10.7]: https://github.com/igraph/python-igraph/compare/0.10.6...0.10.7 [0.10.6]: https://github.com/igraph/python-igraph/compare/0.10.5...0.10.6 [0.10.5]: https://github.com/igraph/python-igraph/compare/0.10.4...0.10.5 [0.10.4]: https://github.com/igraph/python-igraph/compare/0.10.3...0.10.4 diff --git a/src/igraph/version.py b/src/igraph/version.py index a9750c7c7..713f7483f 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 6) +__version_info__ = (0, 10, 7) __version__ = ".".join("{0}".format(x) for x in __version_info__) From cddbc558e3b76b7af47230791070fc559a28204f Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 12 Sep 2023 13:31:48 +0200 Subject: [PATCH 1373/1892] feat: exposed igraph_is_bigraphical(), closes #708 --- CHANGELOG.md | 6 +++++ src/_igraph/igraphmodule.c | 50 +++++++++++++++++++++++++++++++++----- src/igraph/__init__.py | 2 ++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f016d831..ecd0707ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # igraph Python interface changelog +## [master] + +### Added + +- Added `is_bigraphical()` to test whether a pair of integer sequences can be the degree sequence of some bipartite graph. + ## [0.10.7] - 2023-09-04 ### Added diff --git a/src/_igraph/igraphmodule.c b/src/_igraph/igraphmodule.c index 3d22f5415..554523363 100644 --- a/src/_igraph/igraphmodule.c +++ b/src/_igraph/igraphmodule.c @@ -520,19 +520,39 @@ PyObject* igraphmodule_is_graphical_degree_sequence(PyObject *self, } +static PyObject* igraphmodule_i_is_graphical_or_bigraphical( + PyObject *self, PyObject *args, PyObject *kwds, igraph_bool_t is_bigraphical +); + PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kwds) { - static char* kwlist[] = { "out_deg", "in_deg", "loops", "multiple", NULL }; + return igraphmodule_i_is_graphical_or_bigraphical(self, args, kwds, /* is_bigraphical = */ false); +} + +PyObject* igraphmodule_is_bigraphical(PyObject *self, PyObject *args, PyObject *kwds) { + return igraphmodule_i_is_graphical_or_bigraphical(self, args, kwds, /* is_bigraphical = */ true); +} + +static PyObject* igraphmodule_i_is_graphical_or_bigraphical( + PyObject *self, PyObject *args, PyObject *kwds, igraph_bool_t is_bigraphical +) { + static char* kwlist_graphical[] = { "out_deg", "in_deg", "loops", "multiple", NULL }; + static char* kwlist_bigraphical[] = { "degrees1", "degrees2", "loops", "multiple", NULL }; PyObject *out_deg_o = 0, *in_deg_o = 0; PyObject *loops = Py_False, *multiple = Py_False; igraph_vector_int_t out_deg, in_deg; igraph_bool_t is_directed, result; int allowed_edge_types; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, - &out_deg_o, &in_deg_o, &loops, &multiple)) + igraph_error_t retval; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, + is_bigraphical ? "OO|OO" : "O|OOO", + is_bigraphical ? kwlist_bigraphical : kwlist_graphical, + &out_deg_o, &in_deg_o, &loops, &multiple + )) return NULL; - is_directed = (in_deg_o != 0 && in_deg_o != Py_None); + is_directed = (in_deg_o != 0 && in_deg_o != Py_None) || is_bigraphical; if (igraphmodule_PyObject_to_vector_int_t(out_deg_o, &out_deg)) return NULL; @@ -550,7 +570,11 @@ PyObject* igraphmodule_is_graphical(PyObject *self, PyObject *args, PyObject *kw allowed_edge_types |= IGRAPH_MULTI_SW; } - if (igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, allowed_edge_types, &result)) { + retval = is_bigraphical + ? igraph_is_bigraphical(&out_deg, is_directed ? &in_deg : 0, allowed_edge_types, &result) + : igraph_is_graphical(&out_deg, is_directed ? &in_deg : 0, allowed_edge_types, &result); + + if (retval) { igraphmodule_handle_igraph_error(); igraph_vector_int_destroy(&out_deg); if (is_directed) { @@ -794,6 +818,20 @@ static PyMethodDef igraphmodule_methods[] = "@return: C{True} if there exists some graph that can realize the given degree\n" " sequence, C{False} otherwise.\n" }, + {"is_bigraphical", (PyCFunction)igraphmodule_is_bigraphical, + METH_VARARGS | METH_KEYWORDS, + "is_bigraphical(degrees1, degrees2, loops=False, multiple=False)\n--\n\n" + "Returns whether two sequences of integers can be the degree sequences of a\n" + "bipartite graph.\n\n" + "The bipartite graph may or may not have multiple and loop edges, depending\n" + "on the allowed edge types in the remaining arguments.\n\n" + "@param degrees1: the list of degrees in the first partition.\n" + "@param degrees2: the list of degrees in the second partition.\n" + "@param loops: whether loop edges are allowed.\n" + "@param multiple: whether multiple edges are allowed.\n" + "@return: C{True} if there exists some bipartite graph that can realize the\n" + " given degree sequences with the given edge types, C{False} otherwise.\n" + }, {"is_graphical", (PyCFunction)igraphmodule_is_graphical, METH_VARARGS | METH_KEYWORDS, "is_graphical(out_deg, in_deg=None, loops=False, multiple=False)\n--\n\n" diff --git a/src/igraph/__init__.py b/src/igraph/__init__.py index 674e20d51..466f7344f 100644 --- a/src/igraph/__init__.py +++ b/src/igraph/__init__.py @@ -65,6 +65,7 @@ arpack_options as default_arpack_options, community_to_membership, convex_hull, + is_bigraphical, is_degree_sequence, is_graphical, is_graphical_degree_sequence, @@ -1183,6 +1184,7 @@ def write(graph, filename, *args, **kwds): 'hsl_to_rgb', 'hsva_to_rgba', 'hsv_to_rgb', + 'is_bigraphical', 'is_degree_sequence', 'is_graphical', 'is_graphical_degree_sequence', From b7d33f229960869f80358032ca5923ac3327ac47 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 12 Sep 2023 13:48:32 +0200 Subject: [PATCH 1374/1892] fix: added missing error handling to Graph.Random_Bipartite() --- src/_igraph/graphobject.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 069aeb1df..944f6697f 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -3199,6 +3199,11 @@ PyObject *igraphmodule_Graph_Random_Bipartite(PyTypeObject * type, ); } + if (retval) { + igraphmodule_handle_igraph_error(); + return NULL; + } + CREATE_GRAPH_FROM_TYPE(self, g, type); if (self == NULL) { return NULL; From e624df96209e46581792ad38506dea4d7db3ddb6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 12 Sep 2023 13:56:40 +0200 Subject: [PATCH 1375/1892] feat: added weights=... argument to Graph.radius() and Graph.eccentricity() --- CHANGELOG.md | 2 ++ src/_igraph/graphobject.c | 66 ++++++++++++++++++++++++++++++--------- tests/test_structural.py | 21 +++++++++++++ 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecd0707ec..a87ef27db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - Added `is_bigraphical()` to test whether a pair of integer sequences can be the degree sequence of some bipartite graph. +- Added `weights=...` keyword argument to `Graph.radius()` and `Graph.eccentricity()`. + ## [0.10.7] - 2023-09-04 ### Added diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 944f6697f..321bd5685 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -1869,24 +1869,37 @@ PyObject *igraphmodule_Graph_knn(igraphmodule_GraphObject *self, PyObject *igraphmodule_Graph_radius(igraphmodule_GraphObject * self, PyObject * args, PyObject * kwds) { - PyObject *mode_o = Py_None; + PyObject *mode_o = Py_None, *weights_o = Py_None; igraph_neimode_t mode = IGRAPH_OUT; igraph_real_t radius; + igraph_vector_t *weights; - static char *kwlist[] = { "mode", NULL }; + static char *kwlist[] = { "mode", "weights", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, - &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &mode_o, &weights_o)) { return NULL; + } - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; + } - if (igraph_radius(&self->g, &radius, mode)) { + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { + return NULL; + } + + if (igraph_radius_dijkstra(&self->g, weights, &radius, mode)) { + if (weights) { + igraph_vector_destroy(weights); free(weights); + } igraphmodule_handle_igraph_error(); return NULL; } + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + return igraphmodule_real_t_to_PyObject(radius, IGRAPHMODULE_TYPE_FLOAT_IF_FRACTIONAL_ELSE_INT); } @@ -4862,18 +4875,21 @@ PyObject *igraphmodule_Graph_decompose(igraphmodule_GraphObject * self, */ PyObject *igraphmodule_Graph_eccentricity(igraphmodule_GraphObject* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = { "vertices", "mode", NULL }; - PyObject *vobj = Py_None, *list = NULL, *mode_o = Py_None; + static char *kwlist[] = { "vertices", "mode", "weights", NULL }; + PyObject *vobj = Py_None, *list = NULL, *mode_o = Py_None, *weights_o = Py_None; igraph_vector_t res; igraph_neimode_t mode = IGRAPH_OUT; igraph_bool_t return_single = false; igraph_vs_t vs; + igraph_vector_t* weights; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &vobj, &mode_o)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &vobj, &mode_o, &weights_o)) { return NULL; + } - if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) + if (igraphmodule_PyObject_to_neimode_t(mode_o, &mode)) { return NULL; + } if (igraphmodule_PyObject_to_vs_t(vobj, &vs, &self->g, &return_single, 0)) { igraphmodule_handle_igraph_error(); @@ -4885,17 +4901,31 @@ PyObject *igraphmodule_Graph_eccentricity(igraphmodule_GraphObject* self, return igraphmodule_handle_igraph_error(); } - if (igraph_eccentricity(&self->g, &res, vs, mode)) { + if (igraphmodule_attrib_to_vector_t(weights_o, self, &weights, ATTRIBUTE_TYPE_EDGE)) { + igraph_vs_destroy(&vs); + igraph_vector_destroy(&res); + return NULL; + } + + if (igraph_eccentricity_dijkstra(&self->g, weights, &res, vs, mode)) { + if (weights) { + igraph_vector_destroy(weights); free(weights); + } igraph_vs_destroy(&vs); igraph_vector_destroy(&res); igraphmodule_handle_igraph_error(); return NULL; } - if (!return_single) + if (weights) { + igraph_vector_destroy(weights); free(weights); + } + + if (!return_single) { list = igraphmodule_vector_t_to_PyList(&res, IGRAPHMODULE_TYPE_FLOAT); - else + } else { list = PyFloat_FromDouble(VECTOR(res)[0]); + } igraph_vector_destroy(&res); igraph_vs_destroy(&vs); @@ -14786,7 +14816,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interface to igraph_eccentricity */ {"eccentricity", (PyCFunction) igraphmodule_Graph_eccentricity, METH_VARARGS | METH_KEYWORDS, - "eccentricity(vertices=None, mode=\"all\")\n--\n\n" + "eccentricity(vertices=None, mode=\"all\", weights=None)\n--\n\n" "Calculates the eccentricities of given vertices in a graph.\n\n" "The eccentricity of a vertex is calculated by measuring the\n" "shortest distance from (or to) the vertex, to (or from) all other\n" @@ -14797,6 +14827,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " that edge directions are followed; C{\"out\"} means that edge directions\n" " are followed the opposite direction; C{\"all\"} means that directions are\n" " ignored. The argument has no effect for undirected graphs.\n" + "@param weights: a list containing the edge weights. It can also be\n" + " an attribute name (edge weights are retrieved from the given\n" + " attribute) or C{None} (all edges have equal weight).\n" "@return: the calculated eccentricities in a list, or a single number if\n" " a single vertex was supplied.\n"}, @@ -15358,7 +15391,7 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { /* interfaces to igraph_radius */ {"radius", (PyCFunction) igraphmodule_Graph_radius, METH_VARARGS | METH_KEYWORDS, - "radius(mode=\"out\")\n--\n\n" + "radius(mode=\"out\", weights=None)\n--\n\n" "Calculates the radius of the graph.\n\n" "The radius of a graph is defined as the minimum eccentricity of\n" "its vertices (see L{eccentricity()}).\n" @@ -15367,6 +15400,9 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { " edge directions, C{IN} considers paths that follow the opposite\n" " edge directions, C{ALL} ignores edge directions. The argument is\n" " ignored for undirected graphs.\n" + "@param weights: a list containing the edge weights. It can also be\n" + " an attribute name (edge weights are retrieved from the given\n" + " attribute) or C{None} (all edges have equal weight).\n" "@return: the radius\n" "@see: L{eccentricity()}" }, diff --git a/tests/test_structural.py b/tests/test_structural.py index 319a6deaa..2b043503d 100644 --- a/tests/test_structural.py +++ b/tests/test_structural.py @@ -56,6 +56,21 @@ def testEccentricity(self): ) self.assertEqual(Graph().eccentricity(), []) + def testWeightedEccentricity(self): + self.assertEqual( + self.gfull.eccentricity(weights=[2] * self.gfull.ecount()), + [2] * self.gfull.vcount() + ) + self.assertEqual( + self.gempty.eccentricity(weights=[]), + [0] * self.gempty.vcount() + ) + self.assertEqual( + self.g.eccentricity(weights=range(1, self.g.ecount() + 1)), + [4, 5, 6, 6] + ) + self.assertEqual(Graph().eccentricity(), []) + def testRadius(self): self.assertEqual(self.gfull.radius(), 1) self.assertEqual(self.gempty.radius(), 0) @@ -64,6 +79,12 @@ def testRadius(self): self.assertEqual(self.tree.radius(), 3) self.assertTrue(isnan(Graph().radius())) + def testWeightedRadius(self): + self.assertEqual(self.gfull.radius(weights=[2] * self.gfull.ecount()), 2) + self.assertEqual(self.gempty.radius(weights=[]), 0) + self.assertEqual(self.g.radius(weights=range(1, self.g.ecount() + 1)), 4) + self.assertTrue(isnan(Graph().radius())) + def testTransitivity(self): self.assertTrue(self.gfull.transitivity_undirected() == 1.0) self.assertTrue(self.tree.transitivity_undirected() == 0.0) From c61f7f0f501d75466a11329ee6046df439cf4197 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Tue, 12 Sep 2023 14:00:23 +0200 Subject: [PATCH 1376/1892] chore: bumped version to 0.10.8 --- CHANGELOG.md | 5 +++-- src/igraph/version.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a87ef27db..b520ec928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # igraph Python interface changelog -## [master] +## [0.10.8] - 2023-09-12 ### Added @@ -558,7 +558,8 @@ Please refer to the commit logs at https://github.com/igraph/python-igraph for a list of changes affecting versions up to 0.8.3. Notable changes after 0.8.3 are documented above. -[master]: https://github.com/igraph/python-igraph/compare/0.10.7...main +[master]: https://github.com/igraph/python-igraph/compare/0.10.8...main +[0.10.8]: https://github.com/igraph/python-igraph/compare/0.10.7...0.10.8 [0.10.7]: https://github.com/igraph/python-igraph/compare/0.10.6...0.10.7 [0.10.6]: https://github.com/igraph/python-igraph/compare/0.10.5...0.10.6 [0.10.5]: https://github.com/igraph/python-igraph/compare/0.10.4...0.10.5 diff --git a/src/igraph/version.py b/src/igraph/version.py index 713f7483f..655891d8a 100644 --- a/src/igraph/version.py +++ b/src/igraph/version.py @@ -1,2 +1,2 @@ -__version_info__ = (0, 10, 7) +__version_info__ = (0, 10, 8) __version__ = ".".join("{0}".format(x) for x in __version_info__) From 0d1fd16db47136ca596b7aa6eb3c46d09cd98299 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:18:42 +0000 Subject: [PATCH 1377/1892] build(deps): bump docker/setup-qemu-action from 2 to 3 Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18cd744c4..7ff2bd4e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,7 +61,7 @@ jobs: - name: Set up QEMU id: qemu - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Build wheels (manylinux) uses: pypa/cibuildwheel@v2.15.0 @@ -89,7 +89,7 @@ jobs: - name: Set up QEMU id: qemu - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.15.0 From 01ce84b495962d314f524c74cc68678fa080acb5 Mon Sep 17 00:00:00 2001 From: Fabio Zanini Date: Tue, 19 Sep 2023 15:07:56 +1000 Subject: [PATCH 1378/1892] Document invert y axis for trees and matplotlib --- doc/examples_sphinx-gallery/spanning_trees.py | 5 +++++ doc/source/tutorial.rst | 5 +++++ doc/source/visualisation.rst | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/doc/examples_sphinx-gallery/spanning_trees.py b/doc/examples_sphinx-gallery/spanning_trees.py index e9b083f60..82f190a8a 100644 --- a/doc/examples_sphinx-gallery/spanning_trees.py +++ b/doc/examples_sphinx-gallery/spanning_trees.py @@ -55,3 +55,8 @@ edge_width=g.es["width"] ) plt.show() + +# %% +# .. note:: +# To invert the y axis such that the root of the tree is on top of the plot, +# you can call `ax.invert_yaxis()` before `plt.show()`. diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 015e80b91..7a1567adb 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -691,6 +691,11 @@ If you prefer to use `matplotlib`_ as a plotting engine, create an axes and use :alt: The visual representation of our social network (matplotlib backend) :align: center +.. note:: + When plotting rooted trees, Cairo automatically puts the root on top of the image and + the leaves at the bottom. For `matplotlib`_, the root is usually at the bottom instead. + You can easily place the root on top by calling `ax.invert_yaxis()`. + Hmm, this is not too pretty so far. A trivial addition would be to use the names as the vertex labels and to color the vertices according to the gender. Vertex labels are taken from the ``label`` attribute by default and vertex colors are determined by the diff --git a/doc/source/visualisation.rst b/doc/source/visualisation.rst index 24b752e36..c2c73d4a3 100644 --- a/doc/source/visualisation.rst +++ b/doc/source/visualisation.rst @@ -129,6 +129,11 @@ You can then further manipulate the axes and figure however you like via the `ax called them). This variant does not use `Cairo`_ directly and might be lacking some features that are available in the `Cairo`_ backend: please open an issue on Github to request specific features. +.. note:: + When plotting rooted trees, Cairo automatically puts the root on top of the image and + the leaves at the bottom. For `matplotlib`_, the root is usually at the bottom instead. + You can easily place the root on top by calling `ax.invert_yaxis()`. + Plotting via `matplotlib`_ makes it easy to combine igraph with other plots. For instance, if you want to have a figure with two panels showing different aspects of some data set, say a graph and a bar plot, you can easily do that:: From eb916c71f69e059b45e2f8780715fabddd02f0a8 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Sep 2023 15:16:24 +0200 Subject: [PATCH 1379/1892] doc: fix a broken link to Matplotlib's user guide in the gallery --- doc/examples_sphinx-gallery/visualize_communities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/examples_sphinx-gallery/visualize_communities.py b/doc/examples_sphinx-gallery/visualize_communities.py index 7cfd90746..b7b96103f 100644 --- a/doc/examples_sphinx-gallery/visualize_communities.py +++ b/doc/examples_sphinx-gallery/visualize_communities.py @@ -33,7 +33,7 @@ # %% # Last, we plot the graph. We use a fancy technique called proxy artists to # make a legend. You can find more about that in matplotlib's -# :doc:`matplotlib:tutorials/intermediate/legend_guide`: +# :doc:`matplotlib:users/explain/axes/legend_guide`: fig, ax = plt.subplots() ig.plot( communities, From 223863cacee9c988987b460bc1dfff77a285fba6 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Fri, 22 Sep 2023 21:27:18 +0200 Subject: [PATCH 1380/1892] doc: cleanup documentation generation code, remove obsolete parts --- doc/jekyll_tools/Gemfile | 5 - doc/jekyll_tools/Gemfile.lock | 74 ---- doc/jekyll_tools/Makefile | 130 ------- doc/jekyll_tools/_config.yml | 18 - doc/jekyll_tools/_includes/defaults | 16 - doc/jekyll_tools/_layouts/default.html | 156 -------- doc/jekyll_tools/_layouts/main.html | 75 ---- doc/jekyll_tools/_layouts/pydoctor.html | 18 - doc/jekyll_tools/css/affix.css | 90 ----- doc/jekyll_tools/css/bootstrap.min.css | 1 - doc/jekyll_tools/css/other.css | 205 ----------- doc/jekyll_tools/css/pydoctor.css | 399 --------------------- doc/jekyll_tools/css/syntax.css | 61 ---- doc/jekyll_tools/favicon.ico | Bin 142910 -> 0 bytes doc/jekyll_tools/favicon.svg | 27 -- doc/jekyll_tools/fonts/fonts.css | 32 -- doc/jekyll_tools/img/igraph_logo_black.svg | 1 - doc/jekyll_tools/img/igraph_logo_white.svg | 1 - doc/jekyll_tools/js/affix.js | 10 - doc/jekyll_tools/js/html5shiv.js | 8 - doc/jekyll_tools/js/pydoctor.js | 29 -- doc/jekyll_tools/js/respond.min.js | 6 - doc/jekyll_tools/js/toggle.js | 23 -- doc/source/_templates/breadcrumb.html | 48 --- doc/source/_templates/globaltoc.html | 5 - doc/source/_templates/layout.html | 104 ------ doc/source/_templates/navbar.html | 20 -- doc/source/_templates/relations.html | 18 - doc/source/conf.py | 81 +---- doc/source/requirements.txt | 6 +- doc/source/sphinxext/postprocess_api.py | 94 ----- scripts/mkdoc.sh | 48 +-- setup.py | 6 +- 33 files changed, 22 insertions(+), 1793 deletions(-) delete mode 100644 doc/jekyll_tools/Gemfile delete mode 100644 doc/jekyll_tools/Gemfile.lock delete mode 100644 doc/jekyll_tools/Makefile delete mode 100644 doc/jekyll_tools/_config.yml delete mode 100644 doc/jekyll_tools/_includes/defaults delete mode 100644 doc/jekyll_tools/_layouts/default.html delete mode 100644 doc/jekyll_tools/_layouts/main.html delete mode 100644 doc/jekyll_tools/_layouts/pydoctor.html delete mode 100644 doc/jekyll_tools/css/affix.css delete mode 100644 doc/jekyll_tools/css/bootstrap.min.css delete mode 100644 doc/jekyll_tools/css/other.css delete mode 100644 doc/jekyll_tools/css/pydoctor.css delete mode 100644 doc/jekyll_tools/css/syntax.css delete mode 100644 doc/jekyll_tools/favicon.ico delete mode 100644 doc/jekyll_tools/favicon.svg delete mode 100644 doc/jekyll_tools/fonts/fonts.css delete mode 100644 doc/jekyll_tools/img/igraph_logo_black.svg delete mode 100644 doc/jekyll_tools/img/igraph_logo_white.svg delete mode 100644 doc/jekyll_tools/js/affix.js delete mode 100644 doc/jekyll_tools/js/html5shiv.js delete mode 100644 doc/jekyll_tools/js/pydoctor.js delete mode 100644 doc/jekyll_tools/js/respond.min.js delete mode 100644 doc/jekyll_tools/js/toggle.js delete mode 100644 doc/source/_templates/breadcrumb.html delete mode 100644 doc/source/_templates/globaltoc.html delete mode 100644 doc/source/_templates/layout.html delete mode 100644 doc/source/_templates/navbar.html delete mode 100644 doc/source/_templates/relations.html delete mode 100644 doc/source/sphinxext/postprocess_api.py diff --git a/doc/jekyll_tools/Gemfile b/doc/jekyll_tools/Gemfile deleted file mode 100644 index 3e5e9cbd3..000000000 --- a/doc/jekyll_tools/Gemfile +++ /dev/null @@ -1,5 +0,0 @@ -source 'http://rubygems.org' - -gem 'jekyll-sitemap' -gem "webrick", "~> 1.7" -gem 'jekyll-redirect-from' diff --git a/doc/jekyll_tools/Gemfile.lock b/doc/jekyll_tools/Gemfile.lock deleted file mode 100644 index 710e3df51..000000000 --- a/doc/jekyll_tools/Gemfile.lock +++ /dev/null @@ -1,74 +0,0 @@ -GEM - remote: http://rubygems.org/ - specs: - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - colorator (1.1.0) - concurrent-ruby (1.1.9) - em-websocket (0.5.3) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0) - eventmachine (1.2.7) - ffi (1.15.4) - forwardable-extended (2.6.0) - http_parser.rb (0.8.0) - i18n (1.8.11) - concurrent-ruby (~> 1.0) - jekyll (4.2.1) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (~> 1.0) - jekyll-sass-converter (~> 2.0) - jekyll-watch (~> 2.0) - kramdown (~> 2.3) - kramdown-parser-gfm (~> 1.0) - liquid (~> 4.0) - mercenary (~> 0.4.0) - pathutil (~> 0.9) - rouge (~> 3.0) - safe_yaml (~> 1.0) - terminal-table (~> 2.0) - jekyll-redirect-from (0.16.0) - jekyll (>= 3.3, < 5.0) - jekyll-sass-converter (2.1.0) - sassc (> 2.0.1, < 3.0) - jekyll-sitemap (1.4.0) - jekyll (>= 3.7, < 5.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - kramdown (2.3.1) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.3) - listen (3.7.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.4.0) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (4.0.6) - rb-fsevent (0.11.0) - rb-inotify (0.10.1) - ffi (~> 1.0) - rexml (3.2.5) - rouge (3.27.0) - safe_yaml (1.0.5) - sassc (2.4.0) - ffi (~> 1.9) - terminal-table (2.0.0) - unicode-display_width (~> 1.1, >= 1.1.1) - unicode-display_width (1.8.0) - webrick (1.7.0) - -PLATFORMS - x86_64-linux - -DEPENDENCIES - jekyll-redirect-from - jekyll-sitemap - webrick (~> 1.7) - -BUNDLED WITH - 2.2.26 diff --git a/doc/jekyll_tools/Makefile b/doc/jekyll_tools/Makefile deleted file mode 100644 index aa1a6dbf8..000000000 --- a/doc/jekyll_tools/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/igraph.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/igraph.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/igraph" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/igraph" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/jekyll_tools/_config.yml b/doc/jekyll_tools/_config.yml deleted file mode 100644 index b9a8a09d7..000000000 --- a/doc/jekyll_tools/_config.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: igraph – the network analysis package -destination: jekyll_output -future: true -include: [ _static, _images ] -exclude: [ source, Gemfile, Gemfile.lock, build_old_sources.py ] -keep_files: [ ] -markdown: kramdown -kramdown: - input: GFM -url: "https://igraph.org/python" -plugins: - - jekyll-sitemap -defaults: - - - scope: - path: "" - values: - layout: "post" diff --git a/doc/jekyll_tools/_includes/defaults b/doc/jekyll_tools/_includes/defaults deleted file mode 100644 index 42baf8c90..000000000 --- a/doc/jekyll_tools/_includes/defaults +++ /dev/null @@ -1,16 +0,0 @@ -{% assign lang = "python" %} -{%- assign bodyclass = lang %} -{% assign title = page.title %} -{% assign mainheader = page.mainheader %} -{% assign lead = page.lead %} - -{% assign langname = 'python-igraph' %} -{% assign langversions = version | split: ", " %} -{% if title == nil %}{% assign title = 'python-igraph' %}{% endif %} -{% assign extramenu = '

  • Get started
  • ' %} -{% if mainheader == nil %} - {% assign mainheader = 'Get started with python-igraph' %} -{% endif %} -{% if lead == nil %} - {% assign lead = 'Install and start using igraph from Python' %} -{% endif %} diff --git a/doc/jekyll_tools/_layouts/default.html b/doc/jekyll_tools/_layouts/default.html deleted file mode 100644 index d74c2b8b1..000000000 --- a/doc/jekyll_tools/_layouts/default.html +++ /dev/null @@ -1,156 +0,0 @@ -{% include defaults %} - - - - - - - - - - - - - - {{ title }} - - - - - - - - - - - - - - - - - - - - {{ page.extrahead | default: layout.extrahead }} - - - -
    - - - {% if page.layout != "main" %} - -
    -
    -

    {{ page.mainheader | default: layout.mainheader }}

    -

    {{ page.lead | default: layout.lead }}

    -
    - -
    - - {% endif %} - - {{content}} - - - - -
    - - - - - - - - - -{% if page.animated_header or layout.animated_header %} - - -{% endif %} - - diff --git a/doc/jekyll_tools/_layouts/main.html b/doc/jekyll_tools/_layouts/main.html deleted file mode 100644 index 42c90e4f6..000000000 --- a/doc/jekyll_tools/_layouts/main.html +++ /dev/null @@ -1,75 +0,0 @@ ---- -layout: default -bodyclass: start-page -animated_header: true ---- - -
    -
    -

    igraph – - The network analysis package -

    -

    - igraph is a collection of network analysis tools with the - emphasis on efficiency, - portability and ease of use. igraph is - open source and free. igraph can be - programmed in R, Python, - Mathematica and C/C++. -

    -
    - igraph R package - python-igraph - IGraph/M - igraph C library -
    - -
    - -
    -
    -
    - -
    - -
    -
    - - - - {% for post in site.posts limit:10 %} - -
    -

    -   - {{ post.title }} -

    -
    -
    - - {{ post.content | extract_excerpt: post.url | redir_docs | smallheaders }} - -
    - - {% endfor %} - -

    All news →

    - -
    -
    -
    - -
    diff --git a/doc/jekyll_tools/_layouts/pydoctor.html b/doc/jekyll_tools/_layouts/pydoctor.html deleted file mode 100644 index e70459159..000000000 --- a/doc/jekyll_tools/_layouts/pydoctor.html +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: default -extrahead: -vmenu: true -doctype: api/ ---- - -
    -
    -
    -
    - - {{ content }} - -
    -
    -
    -
    diff --git a/doc/jekyll_tools/css/affix.css b/doc/jekyll_tools/css/affix.css deleted file mode 100644 index 5b57395ef..000000000 --- a/doc/jekyll_tools/css/affix.css +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Side navigation - * - * Scrollspy and affixed enhanced navigation to highlight sections and secondary - * sections of docs content. - */ - -/* By default it's not affixed in mobile views, so undo that */ -.bs-sidebar.affix { - position: static; -} - -/* First level of nav */ -.bs-sidenav { - margin-top: 30px; - margin-bottom: 30px; - padding-top: 10px; - padding-bottom: 10px; - text-shadow: 0 1px 0 #fff; - background-color: #e9ecef; - border-radius: 5px; -} - -/* All levels of nav */ -.bs-sidebar .nav > li { - width: 100%; -} - -.bs-sidebar .nav > li > a { - display: block; - color: #716b7a; - padding: 5px 20px; -} -.bs-sidebar .nav > li > a:hover, -.bs-sidebar .nav > li > a:focus { - text-decoration: none; - background-color: #d3d9df; - border-right: 2px solid #a7b3bf; -} -.bs-sidebar .nav > li > a.active, -.bs-sidebar .nav > li > a.active:hover, -.bs-sidebar .nav > li > a.active:focus { - font-weight: bold; - color: #563d7c; - background-color: transparent; - border-right: 2px solid #563d7c; -} - -/* Nav: second level (shown on .active) */ -.bs-sidebar .nav .nav { - display: none; /* Hide by default, but at >768px, show it */ - margin-bottom: 8px; -} -.bs-sidebar .nav .nav > li > a { - padding-top: 3px; - padding-bottom: 3px; - padding-left: 30px; - font-size: 90%; -} - -/* Show and affix the side nav when space allows it */ -@media (min-width: 992px) { - .bs-sidebar .nav .nav-item > a.active + ul { - display: block; - } - /* Widen the fixed sidebar */ - .bs-sidebar.affix, - .bs-sidebar.affix-bottom { - width: 213px; - } - .bs-sidebar.affix { - position: sticky; /* Undo the static from mobile first approach */ - top: 80px; - } - .bs-sidebar.affix-bottom { - position: absolute; /* Undo the static from mobile first approach */ - } - .bs-sidebar.affix-bottom .bs-sidenav, - .bs-sidebar.affix .bs-sidenav { - margin-top: 0; - margin-bottom: 0; - } -} -@media (min-width: 1200px) { - /* Widen the fixed sidebar again */ - .bs-sidebar.affix-bottom, - .bs-sidebar.affix { - width: 263px; - } -} diff --git a/doc/jekyll_tools/css/bootstrap.min.css b/doc/jekyll_tools/css/bootstrap.min.css deleted file mode 100644 index ad8c117b8..000000000 --- a/doc/jekyll_tools/css/bootstrap.min.css +++ /dev/null @@ -1 +0,0 @@ -:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#dc3545;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#dc3545;text-decoration:none;background-color:transparent}a:hover{color:#a71d2a;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;flex-grow:1;max-width:100%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.33333%;max-width:8.33333%}.col-2{flex:0 0 16.66667%;max-width:16.66667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333%;max-width:33.33333%}.col-5{flex:0 0 41.66667%;max-width:41.66667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333%;max-width:58.33333%}.col-8{flex:0 0 66.66667%;max-width:66.66667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333%;max-width:83.33333%}.col-11{flex:0 0 91.66667%;max-width:91.66667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}@media (min-width:576px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}}@media (min-width:768px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}}@media (min-width:992px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}}@media (min-width:1200px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#f5c6cb}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#ed969e}.table-hover .table-primary:hover{background-color:#f1b0b7}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#f1b0b7}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#efa2a9;outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip{display:block}.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip,.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");background-repeat:no-repeat;background-position:center right calc(.375em + .1875rem);background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc((1em + .75rem) * 3 / 4 + 1.75rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip{display:block}.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip,.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:flex;flex-flow:row wrap;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:flex;align-items:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:flex;flex:0 0 auto;flex-flow:row wrap;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:flex;align-items:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-primary:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#dc3545;border-color:#dc3545}.btn-outline-primary:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#dc3545;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#dc3545;text-decoration:none}.btn-link:hover{color:#a71d2a;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#dc3545}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#dc3545;background-color:#dc3545}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#efa2a9}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#f6cdd1;border-color:#f6cdd1}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#dc3545;background-color:#dc3545}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(220,53,69,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(220,53,69,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(220,53,69,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(220,53,69,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;appearance:none}.custom-select:focus{border-color:#efa2a9;outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#efa2a9;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:calc(1rem + .4rem);padding:0;background-color:transparent;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#dc3545;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#f6cdd1}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#dc3545;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#f6cdd1}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#dc3545;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#f6cdd1}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#dc3545}.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:flex;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:flex;flex:1 0 0%;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:flex;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{column-count:3;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion>.card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion>.card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.accordion>.card .card-header{margin-bottom:-1px}.breadcrumb{display:flex;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#dc3545;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#a71d2a;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#dc3545;border-color:#dc3545}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#dc3545}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#bd2130}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-primary hr{border-top-color:#f1b0b7}.alert-primary .alert-link{color:#491217}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;flex-direction:column;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#dc3545;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.media{display:flex;align-items:flex-start}.media-body{flex:1}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#dc3545;border-color:#dc3545}.list-group-horizontal{flex-direction:row}.list-group-horizontal .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-sm .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-md .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-lg .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl .list-group-item{margin-right:-1px;margin-bottom:0}.list-group-horizontal-xl .list-group-item:first-child{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{margin-right:0;border-top-right-radius:.25rem;border-bottom-right-radius:.25rem;border-bottom-left-radius:0}}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush .list-group-item:last-child{margin-bottom:-1px}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{margin-bottom:0;border-bottom:0}.list-group-item-primary{color:#721c24;background-color:#f5c6cb}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;align-items:center;justify-content:flex-end;padding:1rem;border-top:1px solid #dee2e6;border-bottom-right-radius:.3rem;border-bottom-left-radius:.3rem}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:0s .6s opacity}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#dc3545!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#bd2130!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#dc3545!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:576px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:768px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#dc3545!important}a.text-primary:focus,a.text-primary:hover{color:#a71d2a!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} \ No newline at end of file diff --git a/doc/jekyll_tools/css/other.css b/doc/jekyll_tools/css/other.css deleted file mode 100644 index ca975001e..000000000 --- a/doc/jekyll_tools/css/other.css +++ /dev/null @@ -1,205 +0,0 @@ -/* Sticky footer, http://getbootstrap.com/examples/sticky-footer-navbar/ */ - -html { - min-height: 100%; - scroll-padding-top: 80px; -} - -html, -body { - height: 100%; - background-color: #fff; -} - -body { - position: relative; -} - -nav.fixed-top { - box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); -} - -span.type { - font-family: monospace; - font-size: 87.5%; -} - -#wrap { - min-height: 100%; - position: relative; - /* Pad top by header height, bottom by footer */ - padding: 57px 0 0 0; -} - -#footer { - width: 100%; -} - -#footer .credit { - text-align: center; -} - -/* -.navbar-brand -{ - padding-right: 5px; -} - -.navbar-brand img -{ - margin-right: 5px; -} -*/ - -.gist { - line-height: 1.2; -} - -@media(min-width:768px) { - .bs-docs-section { - font-size: 140%; - } - .bs-sidebar { - font-size: 120%; - } - .gist .gist-file .gist-data { - font-size: 80% !important; - } -} - -.bs-docs-section .navigation-header { - margin-bottom: 1.5rem; -} -.bs-docs-section h1 { - margin: 2.5rem 0; -} -.bs-docs-section h2 { - margin: 2.5rem 0 1.5rem 0; -} -.bs-docs-section h3 { - margin: 2.5rem 0 1.5rem 0; -} - -.bs-docs-section .page-header:first-child h1, -.bs-docs-section .post-header:first-child h1 -{ - margin-top: 0 !important; -} - -.post-header h1, -.post-header h2 { - margin-bottom: 0.5rem !important; -} -.post-header .post-time { - margin-bottom: 1.5rem; -} - -code { - color: #87556e; -} - -code.rfun:after { - content: "()"; -} - -/* Page headers */ -.bs-header { - padding: 20px 15px 20px; /* side padding builds on .container 15px, so 30px */ - font-size: 16px; - text-align: center; - text-shadow: 0 1px 0 rgba(0,0,0,.15); - color: white; - margin-bottom: 30px; - background: #3e648d; - background-image: -webkit-gradient( - linear, - left top, - left bottom, - color-stop(0, #3e648d), - color-stop(1, #405a6a) - ); - background-image: -o-linear-gradient(bottom, #3e648d 0%, #405a6a 100%); - background-image: -moz-linear-gradient(bottom, #3e648d 0%, #405a6a 100%); - background-image: -webkit-linear-gradient(bottom, #3e648d 0%, #405a6a 100%); - background-image: -ms-linear-gradient(bottom, #3e648d 0%, #405a6a 100%); - background-image: linear-gradient(to bottom, #3e648d 0%, #405a6a 100%); -} -.bs-header p { - font-weight: 300; - line-height: 1.5; -} -.bs-header .container { - position: relative; -} -.bs-header p, .bs-header h1 { - color: white; - text-shadow: - -1px -1px 0 #000, - 1px -1px 0 #000, - -1px 1px 0 #000, - 1px 1px 0 #000; -} - -@media (min-width: 768px) { - .bs-header { - font-size: 21px; - text-align: left; - } - .bs-header h1 { - font-size: 60px; - line-height: 1; - } -} - -@media (min-width: 992px) { - .bs-header p { - margin-right: 380px; - } -} - -.tooltip-inner { - font-size: medium; -} - -span.anchor { - margin-top: -70px; /* Size of fixed header */ - padding-bottom: 70px; - height: 0px; - display: block; -} - -.tr-first-in-group { - border-top: 2px solid; - border-color: lightgray; - padding-top: 10px; -} - -/* To hide the empty python index */ - -#indices-and-tables { - visibility: hidden; - display: none; -} - -.jumbotron { - position: relative; -} -.jumbotron canvas { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: #e9ecef; -} -.jumbotron .container { - pointer-events: none; - position: relative; - z-index: 10; -} -.jumbotron .container .btn { - margin-bottom: 0.25em; - pointer-events: auto; -} - - diff --git a/doc/jekyll_tools/css/pydoctor.css b/doc/jekyll_tools/css/pydoctor.css deleted file mode 100644 index 18c3e03b9..000000000 --- a/doc/jekyll_tools/css/pydoctor.css +++ /dev/null @@ -1,399 +0,0 @@ -.pydoctor-navbar { - margin-bottom: 0px; -} - -.page-header { - margin-top: 22px; - position: sticky; - top: 0; - display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-items: baseline; - background-color: #fff; - margin-bottom: 3px; - border-bottom: 0; - box-shadow: 0px 0px 8px 8px #fff; -} -.page-header h1 { - margin-bottom: 0; -} - -.categoryHeader { - font-size: 24px; - color: #777; - margin-bottom: 1.8em; -} - -a[name] { - position: relative; - bottom: 80px; - font-size: 0; -} - -.bs-docs-container ul { - margin-top: 10px; - padding-left: 10px; -} - -.bs-docs-container li { - padding-top: 5px; - padding-bottom: 5px; -} - -.bs-docs-container li a { - text-decoration: none; -} - -.bs-docs-container ul { - margin-left: 10px; -} - -.bs-docs-container ul ul { - border-left-color: #e1f5fe; - border-left-width: 1px; - border-left-style: solid; -} - -.bs-docs-container ul ul ul { - border-left-color: #b3e5fc; -} - -.bs-docs-container ul ul ul ul { - border-left-color: #81d4fa; -} - -.bs-docs-container ul ul ul ul ul { - border-left-color: #4fc3f7; -} - -.bs-docs-container ul ul ul ul ul ul { - border-left-color: #29b6f6; -} - -.bs-docs-container ul ul ul ul ul ul ul { - border-left-color: #03a9f4; -} - -.bs-docs-container ul ul ul ul ul ul ul ul { - border-left-color: #039be5; -} - -.pre { - white-space: pre; -} - -.undocumented { - font-style: italic; - color: #9e9e9e; -} - -.functionBody p { - margin-top: 6px; - margin-bottom: 6px; -} - -#splitTables > p { - margin-bottom: 5px; -} - -#splitTables > table, .fieldTable { - margin-bottom: 20px; - width: 100%; - border: 0; -} - -#splitTables > table { - border: 1px solid #eee; -} - -#splitTables > table tr { - border-bottom-color: #eee; - border-bottom-width: 1px; - border-bottom-style: solid; -} - -#splitTables > table tr td, .fieldTable tr td { - padding: 5px; -} - -#splitTables > table tr td { - border-left-color: #eee; - border-left-width: 1px; - border-left-style: solid; -} - -#splitTables > table tr td:nth-child(1), .fieldTable tr td:nth-child(1) { - border-left: none; - width: 150px; -} - -#splitTables > table tr td:nth-child(2), .fieldTable tr td.fieldArg { - width: 200px; -} - -tr.package { - background-color: #fff3e0; -} - -tr.module { - background-color: #fff8e1; -} - -tr.class, tr.classvariable, tr.baseclassvariable { - background-color: #fffde7; -} - -tr.instancevariable, tr.baseinstancevariable, tr.variable, tr.attribute, tr.property { - background-color: #f3e5f5; -} - -tr.interface { - background-color: #fbe9e7; -} - -tr.method, tr.function, tr.basemethod, tr.baseclassmethod, tr.classmethod { - background-color: #f1f8e9; -} - -tr.private { - background-color: #f1f1f1; -} - -.fieldTable { - margin-top: 10px; -} - -.fieldName { - font-weight: bold; -} - - -#childList > div { - margin: 10px; - padding: 10px; - padding-bottom: 5px; -} - -.functionBody { - margin-left: 15px; -} - -.functionBody > #part { - font-style: italic; -} - -.functionBody > #part > a { - text-decoration: none; -} - -.functionBody .interfaceinfo { - font-style: italic; - margin-bottom: 3px; -} - -.functionBody > .undocumented { - - margin-top: 6px; - margin-bottom: 6px; -} - -/* -- Links to class/function/etc names are nested like this: - label - This applies to inline docstring content marked up as code, - for example L{foo} in epytext or `bar` in restructuredtext, - but also to links that are present in summary tables. -- 'functionHeader' is used for lines like `def func():` and `var =` -*/ -code, .pre, #childList > div .functionHeader, -#splitTables > table tr td:nth-child(2), .fieldTable tr td.fieldArg { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code, #childList > div .functionHeader, .fieldTable tr td.fieldArg { - font-size: 90%; - color: #222222; -} -code > a { - color:#c7254e; - background-color:#f9f2f4; -} -/* top navagation bar */ -.page-header > h1 { - margin-top: 0; -} -.page-header > h1 > code { - color: #971c3a; -} - -/* -This defines the code style, it's black on light gray. -It also overwrite the default values inherited from bootstrap min -*/ -code { - padding:2px 4px; - background-color: #f4f4f4; - border-radius:4px -} - - -a.functionSourceLink { - font-weight: normal; -} - - -#childList > div { - border-left-color: #03a9f4; - border-left-width: 1px; - border-left-style: solid; - background: #fafafa; -} - -.moduleDocstring { - margin: 20px; -} - -#partOf { - margin-top: -13px; - margin-bottom: 19px; -} - -.fromInitPy { - font-style: italic; -} - -pre { - padding-left: 0px; -} - -/* Private stuff */ - -body.private-hidden #splitTables .private, -body.private-hidden #childList .private, -body.private-hidden #summaryTree .private { - /* changed because we don't want to hide members that pydoctor considers - * private; currently igraph._igraph.GraphBase is private according to - * pydoctor because of the underscore */ - /* display: none; */ -} - -#showPrivate { - padding: 10px; -} - -#current-docs-container { - font-style: italic; - padding-top: 11px; -} - -/* Deprecation stuff */ - -.deprecationNotice { - margin: 10px; -} - -/* Syntax highlighting for source code */ - -.py-string { - color: #337ab7; -} -.py-comment { - color: #309078; - font-style: italic; -} -.py-keyword { - font-weight: bold; -} -.py-defname { - color: #a947b8; - font-weight: bold; -} -.py-builtin { - color: #fc7844; - font-weight: bold; -} - -/* Doctest */ - -pre.py-doctest { - padding: .5em; -} -.py-prompt, .py-more { - color: #a8a8a8; -} -.py-output { - color: #c7254e; -} - -/* Admonitions */ - -div.rst-admonition p.rst-admonition-title:after { - content: ":"; -} - -div.rst-admonition p.rst-admonition-title { - margin: 0; - padding: 0.1em 0 0.35em 0em; - font-weight: bold; -} - -div.rst-admonition p.rst-admonition-title { - color: #333333; -} - -div.rst-admonition { - padding: 8px; - margin-bottom: 20px; - background-color: #EEE; - border: 1px solid #CCC; - border-radius: 4px; -} - -div.warning, div.attention, div.danger, div.error, div.caution { - background-color: #ffcf9cb0; - border: 1px solid #ffbbaa; -} - -div.danger p.rst-admonition-title, div.error p.rst-admonition-title, div.caution p.rst-admonition-title { - color: #b94a48; -} - -div.tip p.rst-admonition-title, div.hint p.rst-admonition-title, div.important p.rst-admonition-title{ - color: #3a87ad; -} - -div.tip, div.hint, div.important { - background-color: #d9edf7; - border-color: #bce8f1; -} - - -/* igraph-specific customizations follow from here */ - -.pydoctor-navbar { - display: none; -} - -table.fieldTable tr td { - vertical-align: baseline; -} - -.moduleDocstring { - margin: 20px 0; -} - -.page-header h1 { - font-size: 24px; -} -.categoryHeader { - font-size: 18px !important; - padding: 0 0 0 8px; -} -#showPrivate { - display: none; -} -.undocumented { - font-style: normal !important; -} - - diff --git a/doc/jekyll_tools/css/syntax.css b/doc/jekyll_tools/css/syntax.css deleted file mode 100644 index 67e6ea397..000000000 --- a/doc/jekyll_tools/css/syntax.css +++ /dev/null @@ -1,61 +0,0 @@ -.hll { background-color: #ffffcc } -.c { color: #408080; font-style: italic } /* Comment */ -.err { border: 1px solid #FF0000 } /* Error */ -.k { color: #008000; font-weight: bold } /* Keyword */ -.o { color: #666666 } /* Operator */ -.cm { color: #408080; font-style: italic } /* Comment.Multiline */ -.cp { color: #BC7A00 } /* Comment.Preproc */ -.c1 { color: #408080; font-style: italic } /* Comment.Single */ -.cs { color: #408080; font-style: italic } /* Comment.Special */ -.gd { color: #A00000 } /* Generic.Deleted */ -.ge { font-style: italic } /* Generic.Emph */ -.gr { color: #FF0000 } /* Generic.Error */ -.gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.gi { color: #00A000 } /* Generic.Inserted */ -.go { color: #888888 } /* Generic.Output */ -.gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.gs { font-weight: bold } /* Generic.Strong */ -.gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.gt { color: #0044DD } /* Generic.Traceback */ -.kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.kp { color: #008000 } /* Keyword.Pseudo */ -.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.kt { color: #B00040 } /* Keyword.Type */ -.m { color: #666666 } /* Literal.Number */ -.s { color: #BA2121 } /* Literal.String */ -.na { color: #7D9029 } /* Name.Attribute */ -.nb { color: #008000 } /* Name.Builtin */ -.nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.no { color: #880000 } /* Name.Constant */ -.nd { color: #AA22FF } /* Name.Decorator */ -.ni { color: #999999; font-weight: bold } /* Name.Entity */ -.ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -.nf { color: #0000FF } /* Name.Function */ -.nl { color: #A0A000 } /* Name.Label */ -.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.nt { color: #008000; font-weight: bold } /* Name.Tag */ -.nv { color: #19177C } /* Name.Variable */ -.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.w { color: #bbbbbb } /* Text.Whitespace */ -.mf { color: #666666 } /* Literal.Number.Float */ -.mh { color: #666666 } /* Literal.Number.Hex */ -.mi { color: #666666 } /* Literal.Number.Integer */ -.mo { color: #666666 } /* Literal.Number.Oct */ -.sb { color: #BA2121 } /* Literal.String.Backtick */ -.sc { color: #BA2121 } /* Literal.String.Char */ -.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.s2 { color: #BA2121 } /* Literal.String.Double */ -.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -.sh { color: #BA2121 } /* Literal.String.Heredoc */ -.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -.sx { color: #008000 } /* Literal.String.Other */ -.sr { color: #BB6688 } /* Literal.String.Regex */ -.s1 { color: #BA2121 } /* Literal.String.Single */ -.ss { color: #19177C } /* Literal.String.Symbol */ -.bp { color: #008000 } /* Name.Builtin.Pseudo */ -.vc { color: #19177C } /* Name.Variable.Class */ -.vg { color: #19177C } /* Name.Variable.Global */ -.vi { color: #19177C } /* Name.Variable.Instance */ -.il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/doc/jekyll_tools/favicon.ico b/doc/jekyll_tools/favicon.ico deleted file mode 100644 index df709da1aa15e00cf36f79285888a834ab0df8e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142910 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 aWz=cfH9OLW>RYJ?BYxegywt_j^zi>D?NN3B diff --git a/doc/jekyll_tools/favicon.svg b/doc/jekyll_tools/favicon.svg deleted file mode 100644 index 6b2569802..000000000 --- a/doc/jekyll_tools/favicon.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - logo-black - - - - - - - - - - - - diff --git a/doc/jekyll_tools/fonts/fonts.css b/doc/jekyll_tools/fonts/fonts.css deleted file mode 100644 index d4776e902..000000000 --- a/doc/jekyll_tools/fonts/fonts.css +++ /dev/null @@ -1,32 +0,0 @@ -@font-face { - font-family: 'rlogo'; - src:url('/fonts/rlogo.eot'); - src:url('/fonts/rlogo.eot?#iefix') format('embedded-opentype'), - url('/fonts/rlogo.ttf') format('truetype'), - url('/fonts/rlogo.woff') format('woff'), - url('/fonts/rlogo.svg#rlogo') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class*="icon-rlogo"], [class*="icon-rlogo-alt"] { - font-family: 'rlogo'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - color: auto; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.icon-rlogo:before { - content: "\e600"; -} -.icon-rlogo-alt:before { - content: "\e601"; -} diff --git a/doc/jekyll_tools/img/igraph_logo_black.svg b/doc/jekyll_tools/img/igraph_logo_black.svg deleted file mode 100644 index 410ffa84d..000000000 --- a/doc/jekyll_tools/img/igraph_logo_black.svg +++ /dev/null @@ -1 +0,0 @@ -logo-black \ No newline at end of file diff --git a/doc/jekyll_tools/img/igraph_logo_white.svg b/doc/jekyll_tools/img/igraph_logo_white.svg deleted file mode 100644 index cada6f592..000000000 --- a/doc/jekyll_tools/img/igraph_logo_white.svg +++ /dev/null @@ -1 +0,0 @@ -logo-white \ No newline at end of file diff --git a/doc/jekyll_tools/js/affix.js b/doc/jekyll_tools/js/affix.js deleted file mode 100644 index a94c76253..000000000 --- a/doc/jekyll_tools/js/affix.js +++ /dev/null @@ -1,10 +0,0 @@ - -var $window = $(window); -var $body = $(document.body); - -$body.scrollspy({ target: '.bs-sidebar' }); - -$window.on('load', function () { - $body.scrollspy('refresh'); -}); - diff --git a/doc/jekyll_tools/js/html5shiv.js b/doc/jekyll_tools/js/html5shiv.js deleted file mode 100644 index 784f221ca..000000000 --- a/doc/jekyll_tools/js/html5shiv.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed -*/ -(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); -a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; -c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| -"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); -for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d

    3&d%}xZZW+`g_A~m_IP753kl3u7nInA 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 z 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 mMB}CUMZX3{Qm%)pbLxu literal 19005 zcmZv^2|QJ8+cv(4Ol8OvB@!}5sMuu6kf98fDWM5TDP#_J$Q%hNQAiRZQY2GSh9XIb z6v;d#Q^x@j+qfqPOEMADEsOy%)b}e|XwY#@=fsarzcvo5uCsZ{GeqcJ*g$X)kk_ zjAY^R%J;?JyAPeZb!+6^yOBR{=TfWR-FZHD+5fVSN?S>z@x~}^27>VUDL}ze1dW3T zqEwrWni%EPq9^jta%?3kAOGizdd*Zs?W>vy?&!^mEZZPay0biseVXK-+^;B-Uy zHHJhsE&BF6*MY{F;jWU=_enPj3cf6#&FGWXz1`FQthw$?b2#VMefw%OY2HN((u{tR zu2}jgr{L-0KC82K-&W_vW3k@Fr6GoilfT-Za5bzo-+Glp+%DKiPgTm^_27Nw8ai*z--qUevL0lg{Zi&L zK0a<2Moa&SXREEv7G=*1lXKq!BUYweA6xw~^!ep*-^;0jRM^vM-{8QGU0jGlpO~X`t@(pfjM{P<{U=_fY zw%?45jO0D?$VqC2ZbJ9t^_MU2-4kfBrw%&7ztxuespVKzAl)GolgCyiR6;>Y3XG8Sz`5t`*@Df0T0*C-oB@O*?F_$oo!Fgv~-vG zC@Cu5nusRo)!C>`r6nZJwmm*pS67#klHyoIk&*e(+FBHPch|;s+2tz~zp1{FGiSz< z?>y@J>*-xxemCzg>YZL?QC*T3*UKL#AJ5j+c$jemc8Edi;Fksvv=5(`}Wmdhp|W8DE$0)7iLEGocXBvYxQ~e*`hDy zmly3$o!TGE!OF_Y#q}nT;kX>0c)>yb_T|OdbFfr)Yx%D?o0640b{u*TS;F$d_s`U> zv!6MZzSPuY_{@#ts!Oh}a&s4{T+`{P&YE0coNqBy-Gwj6HC6TgXm=jo>NEG%;}Yd- zwVC+ghcdR6#IyG5FW5;=&tkrn;nwVA$|Xhy2C<{ha(*&ac74q7TVA*{{7KQZ|J_NL<;A(qXGKmO1r~*N z8dsCaEqoSnV z@5&BP!vdM2&xOFlN|nvN;#++t$~^GwA$f-%TPg0?G5%-ZE_WiM=z5-IefE4q9v&Vg zkMXX8)B3k$Pk(Zp8Ej5JW@V)r;w=u(G|e`9Y-KUo$!+7ibNhB3o4zEEHL|adU|^M_dhgBy)x*arfU=w zka61Hes%sw^rk)MKMlD#zx;L8GIw@*nuG6==L5sL<2^k)o!axS9E*g35gikE6kT)1 zS*Z6Ti|A56uTC;`cYhWV@-{v1UDBS3sh!bKVNww=(8-wyQJ{5WSrHJ47|^9sbzT;xYE6$m_SAw6t`QRj8*vw8DoUS4qu(vmaLm)e-EFbI1xttU#`lA)#L7x+Cq)gqs-{NMbX zwyz@;Rq-01(ryuvt8^Xv&Wmb%=kM%Uvu4e{efut7zN{5eppFcUNBZ*amRz=JF8S@M z99u_uJA0&@no{;km_0VwzkhOemMfWdo_wRZ`jFbQ>Z9FeHkW5c@+undDBf7U8N(3H zIxCE92_HwcY;0^qiP#syymZOwxOV!*+0l-np`j;Fo=8?{FpFxmGd-(r2sxOUBy(J& zCY%#bE=FNeV|(@a%ztMxF;&%yLzxGws;aE5t<(0Ye{_)N_g}h*e1bG4MPVA{)1pth z^s_!5_8UbQ>)sH-7vi^5$j$ia>FLQyRAGNrQPKTwTnzl-AEp}2goLAg_VBBLHT@bc{bmko$G|nmX?;{aM_KV9I~(pZ{P0Y?fs~AxUy2s%*?Dg)s|N~ zedq4opX=(*AiG$7W71EfKhC%1EAzK>9hMYZ+Z$6;Q*R=9S{@pwQ>|GW+DNUW!KU$f z%lVKt$0B4J?SaPRhB&cp6pnYIa&mHrW-J>%2fJ7s1;u1tIaGPqZy{`Ka<(6d79qTj zg~j>ni=sivd?t>qeLvyQ*e`tGbVC9sA7g?$cKz3nw}vUoCDvu$xXY|@P)r087g-gt zlc-FGvs;nPFI~96%E$O>2?32Hj*RUdFMdSR{-3CH`mKovGnFoUSJTt0hmEgXx$?q& zZ1~3ytnt)VVd2xrEes3{2DG-O99x6L+L=c?YS@4)K&j<+&d)lZGwVpnKy6TxKWhC z&e-6O+^#1($6T-}AS>bnCTbtZ6rAx#2O|mpY zu8b+TkG2C$*frjl_kGfylP6E| z@$q3rt?Bf}$|$8Q>(LhE-X1i{S6Ul*{NsIH@p#8i4~?p1UV+L}CRT5F6tFONal_vA9-EBpBAgZAhpOEkju8L~RcYZ8I5TacfuG+>;?9#x z%gd@ull$aX@7}$ut*woTi9zOxXrvxdWBXDZk{RF>60%&3;(6*+UntwQ zFHg^GgV_l!hr)t_0>IF_ckYaij^>zVE4d9;;x^If&ETm!cJF=$lcW`@jf-k*dhPD1 z7JI)sgry0F1F&sUU41zy8M7<=gZqDh(C(Lt($abVN9v{$M1+qeIhX71-!BT-h|8tJ zKX6%a1{AOsowuUxA+Gb^OqN3@JVoPi55jU<{4lRcoq^Js)pL({o zwrDJYO9dz#0@8?Czy$o<5INvNW)M0TO*YGn|Eo`N3ZY}nY#B;RPe-Xkj3KFPHV*py z+Exb5fuy41pV5v&b#?V)FWj=w0S+1kaDH%*PuGqb{*YRI)VWNU!gMM`@F_E(VP~1o z+=By2hsEP9bD0?#UEJNd_!#p=@J>W%=-{`CRqXW+3R7ROU|i9EX7NhPW97boZWyZY zsQUS0wOB=@QIKqWe0&kIVPD@VQ~(r)jT>usIjapND_j)Zz1w|ZdZ_CJ1B-D`!S6x$ z`F|UPh=VlkaY&uQ_z@Di5WkDjD9FV)pU)344=^!mPxl~j5J0MC2(?qom!h*+-X?zj ziJqRV6sFhd^feL+v`a&ocMdOgl}yO|FD6K=dR)>Cu+j?A_IJVv8!Q2 zfWiHYjHu0uvZzHzvQ2T}y6_K?TRNG)VK>liL@?8Szer|Nq)L)|&s`be0< z79iLGr0?S5;_It?)N^dTmIE(sXV0GVT@PD^x;=j&5snQFiBUKLdM#dh{<l$34d5WQ#yQd=F<)6@U>pITIBOE5yPrtS;*oM&_Q`t@ccfrH5upn>L8 zA}--z<|epBu4U2M^}Iq9CdnW{$!FPSdE@O*0>>r;a_bu#wnM96`fnWq61Pi~4^4ZUlBrvhC<>E*c(lv2+pN&>s zDL!7kHn8dg$~lZsQc{97sByt&ITnR02z_8UMG7VS+M1TaIYD1fou`O8U>y7oKS-nI zj%F>0fnD4*N5Q3UKkn@9ZW)A%2!}#ra{1uFgBLEyV7VLz)0=%!Yx7=C)hkWBM5;4* zHy%FuKbTuvj|dmsyLYd$^3w9$Hx@?54au|*PDyJ$Y;`1I0G#&E)Xz2>|Gh#&_u-Oh z`>66|Zz4BMw-~+!g!;F-$Ud_PLN{|1S*gU;zRGk!CIc3*7kFuTaSkv>*gjtCVY37J_2*u{`_b-Ub7<-4e7w9!AK7x+ z&JJk9eWDxo&~)R9i;3s#0T=ZQ9Ti+o484R%I-({%Hnsp5 z8gb^r?mr^*Bt4F%}N zqNh2VK6h%f1Bpz{axG8G^U|%`_yGwgBv19_HcJEuP`oL?k^b5>0Uu%NmQ2H@#>Nzd zi)n#@frAR7v9aJGllA}tdx1FBjrF~Jc@v1B+L+(QaN0t<_g}zpRXKySm`92_D}Vcc z!TPpdZEE7yhyNRMYMDd|%5Pj}<3H1y#v|8wtoXyb)}q*h+jT##&zPzxDJfcBy6U?y ziMIVF7$;43jPQO>?mdErFn!DPQbKW_rFAh?V0FXPV*BESH}`}#H=z{e-R-)V*4 zJHjo4aOp7n29w#@v4=T1%(3@<`*bXIziih%q`X(|vhU~f-Ak{tL!_-=Dja_mgiYN$ z>kSv%e(=s2=sr$E$A}zbq)6dWM)+}3C@U3=Si4{`RHPO*s5R*9D z7tEBm+qoPi;jM}vSTLX%|L6CFbl(C6)z^z3cPC=9!D+m$sgbfM5Zbj1xk|aZFk-T= z?#9H-;PpH4trHdl*CsYa)pc}C%nn{0{*)CWEdo+TM+c_e?)Tb39<(5b#7@FI7}bO1 zSf={w%<`#aX>e+8-d;brKnrWTF)xi==G6Y@7^V^V2vlXRael!ajy8q>%nT4 zDJQ8bMaJ-a=w5&Q`qi{|?#`g3r|jt-)q|EVi@mkAn~xgB-Y?hwQSURyB_v{9dhrL6 zWUP=_e7)@HdQUI%XYW!?I%tQi6;?vP4B@(8Uq9m7wUk|FxeP;ZWZK_hTd0_P^)cJ* zDCci||LgaoA05{1F4V~|!ADC3=@ki6JbkM;?=8HaeAjUG_DK^cwTuGK3TE4?7S(XfW}bKWWUMLj45=> z(ibI(d|_s0X1ITa=dWIvNXx$J2cyI*U@Eh^_fj2mrgaVa`uY+b_EeR##l^)auBSot zp%QT<)2(@l+-uGXZ15@|uUuPtox`0SKP;#1777emn!y8Xbq&!Jgk&wtf*!l=0M(O42 z6&EXnW@ctpTxZ0a;)nnZ@XAP5N)*a9epTyK(JIqjiErf2zW^90Iq~&{N7q+rjaSG_DKD(dj@-L0{%uPn+V$rbxelsx9z zI|_liZDTJGww-s9lec3;(I8y`qEFq8Yw^e@y59f;KbD_&Gd4S>ySO}B9?85Zd?q}p zlgoY}e&q9|(e~y(F{;X|UtfBmYj=4a%7${zmRz%ivxr_;cL8v^B2n3EC|0vMIoI(v*nHV(x4z;$mWT4Gkk>&%f#9TCw9#u^n?%l^q_kz(@)@@>h~M9M?d zhC>ewNLUBv5bs^g5Z3@_fNm{H`{W~eA|T|ES>6^tzP+HMnYhC}E9~Pmv%-yHh2r&U zWU)qFv<@H>x%l`l4>a;MTR54Xi6GYxx>Y2MnwWpyX6=)U^alQ*qoV^3A%dBb+PF7h zdj9e1F!t@kZWMgV=uE_i&dwwz9jeMM+^!#_FUX6>hVqK+k=kM!gv=f~x)4m*b21iiG);>tOo~^UwF?916&+%fSNL$vsJ^+vyBK5jT`* z;n;eVfl7^og(Vt~IZ?5?GH}-)4=;WZ4``YPPLF;2!N}-n)l0*1gOZ;^1Zjw)MySy{ zPriXoK=q(rNL1Iz61LlJ?{V%1QTOnn=oa>)k~y&47(Ei-x^q^h&-p2*A~%uf=^U~$QNS_7L=7W$!lv$RsuOaQpvlOXy?r^QA8mG7V-Q2 zeh-#Q)pCbT#dEUKRwiyGn;=Ab#>cmCb3aGZiy9x+DCi*~szFCb$HKxg9>7c#Oo5T9 zsi{F@w+s-RR#8Q1Emq=G7APfl5rafv%U~vMP5bN8Fa&8iL+P^Vj|e=p853P4 z+b9tRw;s@!m6gFmVlu(b7NII5l@DC^GCWlvr!o6!O@LF`@@(gU+w!-7P)xHqleOH< z5fh~{Zi63Cm)<4r49uKYxeCLT-ZK(?bB)gj*%UA@yirhEL_$M5oe*%{v111SC7>qe zRyPJEWlt3B(m3zVOiT^@{J9Hp0lJA_;ewhQSBb4WBQaak*0u-TET}-lVdkJ@K_&cd z6yWlb%JOszHuynC2CR{CCj3J~gMNDRWGxGk&qcDjZF%3|-wIJX53q@IFrr0XX`vw` zukvV<|yQcCPP-)(`+vAiqBf9Mr0d+nu&N| zPuALqfUA6rGK{=Gim53o8+WqSx^Pxv^jOs)Ur@iR;H9vjfV%LQ#q(MHw-FwW9t6}F) zhd8`(whiqcpe;rP7z`kGw%)ldt*TT7c0$zvHmCv$OM#1S+Bv zv%dbp!Niyt0ZOQFVh%l;78h67BFo&Ya$tw>z`%Wn4}ZdZzAeWBUeIwXhn|x$7;W43 zV8V8jm6g>4gIfhi>wsRUbJn==UyDhJ$BScU0Gkm>rGt`or|Jby!Qq_VF-gCafiItF zd62B?Z|%nAy7M$!K_E5Z)TA$6#<69K3f{zA1@XWovLyqu3UfeWk)@Ops2puQKyJGRd-gmv~&BSId5Iae<9v&WL)^~5-w0|{0L)01p{9;tK7py+gaaf~?B`ygg6Ylw^ z4$Wzp;2=eRR$-FI6Y$Xzi)@=WFV#!rX=3;K`@kMb z;g;XuB)n`S$^mx#lVcHRiL}BvRwT~=6Jzmsbl_wo;_>bBc8b1kVmW<@`C4K$s}8uNE%;hrGB> z-tm*Dq@<*{_%L=kt&oHBEQB40yvK^#z?buKa>geoOHuT%Cl-_WK@lOZ)Q0v4wFSA~ zII|_Jamq<#2U+TLV?lfvEEW;Oh^$k)3{ovgvXF?V0Z|lqmq?kX4q`OSj~gwS{)WYVrA8Zt@K|U+tX}84$_E3%}E~w}kC7m)WMAtcl8#|5JE!awMBAw%8}gy^4%ncf((bsC+~= zep(S+Fz(;Nv$O{0CYX5S9gG0Z(W~vqejofmTI2kVHH4>Nu*NS8d@!u^$EVT?msrS) z8?ZMh9m-%7TwDqUC0E~CnMKtPKjkI___u7?a$~!pHI@dhQ<4%PbSs@6L&4-bcjS4a z>MD2;VQ5EBoIHt%k6|)Jm=eK*ye+Yn_-^6Y_83goAP9|Ps69>_3OTkmWziAJhp?w` z9ac_GVfPk3askJ$1O{RvheYn`>Z)}b@&`f?Bg8y_T;P%Bkr@r@#BBNwbt*!XF<66* zhbOCTgq@u|n8r2=2_VrV>ki@-8&$qMd$fT+xmlD@Q}*zfLzP7H30|h*RfrvuaZK<) ziVyPldCWIgmnZzCysVH82^V8HF*?MoLz&ja7phLsW#C2GsgL^7>%rkrC=2kZ1jV$H z9SL>s-u1bs69F4MXIjllFOAqe$(+BPK_9P|k)55rj(^`eBA?N@V%eQ+1P|Q4-|G1O zvScAg>T5R+!iWNd{(E}*&d!rpO9mnkKWf)F7;7+ZcK%kr+-hcXYeubKoGem=UR_Pi zX^aq5SLT0!_Ic;Q;mVo%{P`XzlthK&_5P>GR2qcH{NUN@GfYKf42+Cy+O$c@XLeK- z0_wnl5o?lX+}Sv}XZ4a7xBMa5JIf1`u^PVdWs z{^dOY=LUJI>CFl`N8279uNLgijM{}zx>O8KSbH{Te)v%-pIWg9d!z< zvVAZ?N3_Rdk}RPU{ic6_dwJWTsj0_Ha}`MA(o5%H_`gsjIxX)AHDMGgotD;HP#9nH zCp2B?Kz;p!@6!CMZ+4Fb!nLOR_KliW#vZb_jqLNbY^qu5hdXOB(9y zrzD3085$glf^G6obnntYQ8w~cQBi?_OmDU$>G9+8^77!9|B&82j?vJ{1vkkK`_&6> z)4zX9^sWE9!ENAUTq$3pdi`Y%#5Rt&!Lh~r_L9yvj-igX+eCR~T~;ywor%$|k@tJz z>tD_Cljt~~dgopL^4hu~my0Scy0HnO@y!=623Pz|#GIZhe+JS|oGkV6=KA%kv?G>d zxaXIJl@&&mjQ*KC5r8ccpcpb+ZcVTfs1$#Gy?u||I@ojZx5dOuFGL!`EOeZ!u|9wGn-4iyM|AD%>85xUeR^_p#M=exEKHVJzCYe_=J{m zd7=57wA8aJr(Yp>8*_B1h<1ixjpl4aetVYa_-~i@{F)v*?|oVA{P^!!A>EI=bSZtq zFPfX1^Q_DIXqfbJO72$GO6S=5fC1^^5mOHMWFsSeSNufEY@Yd7P0pqwLU8Q z^r-dPhYzqK*ND>lqe0!>-J?iZaVgCXR!D&m{AC%54!7k=>zbfN7`e8|Y{B{2Yllxc zAq3H`oNKCtp%4Tw`(qDd+6TzS?x%>TjUoAd!`t#hC=j$2=RQ5Wex~AEq*;_6fH$Ex zfN}Zp<4_y0TFQZu$HPI)ksOZ(4 zrnNS(rG_lMMd zfM8^1odxZ@oSj#GTjlZ#jno(+G2|9J88frptrNG)=qpytSwXRB#Cb4|D_|gSnhGKNTwE2C)wqW&pnoHZQ(#99k0iz?nb$ zj;7IDh~QCr=YRdk%E|(u<8*Oj;v_qlfbAb0i!isx9MQwom3>11iDCBRV_7KwYH9%w z3A>86hnjGXlwJ%Kz;IbVb+}%+EJ_0daYw zL_knGk$_%6&CaeLyp!OzZSSY!s?rKS{6*r*NYFKTWwVxmfLe4<_Op5W_#DETLcrO3 zfdIv@GmKeKcNE)T4)H-mbTt2Nr^M1yAmrFnw*=iTUIawtje0} zeDfIje84TnKflXCe%rQcS@Px|0_j*1BrP_e+#j~=9Z%7+FOegAFx#fs*jU&F#O2;* z^(}AFP}#b}EmVMCusd3GUepay+9b+byx%qg7%b;DXoO${{0czwtbB=~J~V43;QAw& zr%sXfv~z3hCKtW;%iuqZc7z;kpYyzMqtwQ_xIcK*uF{?8Q^GzAGy$xP72j z1PK}Q+3hh{zwo`1j^9^+Qd>ysj@esAW?&!k$p_w4y)}PK-*JeAaPJM__XAIaZM!`v zparEZQ5kn0xB=AC)!^VTW|PBKl4}T=40L%jsQK{zv_KBdbYno{r2*B|5>U3thnjR^ zYhgd41w&pY?j4Y?c(}N1NY2(<<{GL>I8eCGZ;JxUs%%?&L zqLAV{KM9Vd+i&q)v$|g6N3B{|p*<3l8j!%Dq4f6l_RSW5Unl8^Nb)(RKkB2`XXCqn zSh7reKS+*q#h`VuZGR_?`_GV_tmy9a=8gRPs@Mj68(JGnGAW0jL%WRJM(Pg-1w<IfRgn1TL4U1k42`PQ?0zIiLm(;&KsU0b@Df6DOeCn{35-Mi# z;%^R-AR#^gM`tBm;sO@!`Rqzm;D2SUK}iu(z@8!{EDVk&yVbE--M~hG=~AnwUvzyQ+d(_bk{XbH*uD93|S+`oUL zif^&hxy`=o5D)>GmQV{t@$N!5qDi-NTSjoS4s2Rf3`7W34ahGcN~o8`LL?N}vQQaP zk{e&Wr6o8bnjIjZ^PDJ~tG_7?YSar)#mT4z>ReV%PRiGcPr%%7w!%UaA}Y) z0gcqWeH#)SOpaHfdF_l|cftRS!l;D%Iaz*9vip&4O3BmrQ)QVjceO@3F0 zc=yz)`{-l_B@^BpL9mI5iIK^FX1JA|Pm`e1!gvUy@!!9HOZhtxl@%Ee9&7=vj~OgC zpXNF$vi6dd^^`_l+jb}xgM+=iy+J=+O-!nN5)U>ERQsi$4L6ss4VwgU7ka(yNvEzlkPeb$v9o>0yhHpVuEChPgDCfM=A+s$j^_27dGX4OfM-grwz~9pGr-V8;9UK$gCw z|H~4g+DY1>5P}840gWgvy6b$$wQ5tmiTp$ml4zr%!H)eiDBvRGfNRU{3o*oaWdb?a2Cskp`gL@kZd|u|0XdvHmj3*P zeDtqcG}Jfjq=a@cNRZqET97F1ZQ?+Z`N+5^S=H zjz3Q7s42)?f#SdU;YKH@$nPIwDd`57AW;Twpg=kPev%2BPbDWHqt0?d4>21oX=CMggggfeM93VF=<4KR3UN z^b6t=vvDmq)}sP`Q8DO?@0lY-ndO*+kU)x>pSaK|uo4*qq$-*KLgv!ohg1kk(gNG* ze`(bMq=b)S&WBVx@i$XF+viKNg8_ojQvw&E12}*FJSG;*zs?4MLH&*rYs5ifLeSp; z8`xN}D-j>i*t~x)B`0^tX&n($ft-i)A!3q}23XX#mGEuA8uvsoUs{+QJ4$LQ)SaRv z|AH^kE~t-48R3QvaJcmV$!g;`t3wX^YisvoK#U>^``}vlZUunTApb=B5)JC0yxEUE1G$csmM74XP_N z;xM7gFRj6!KcN`QXdBU@qasRb8ygSm>4ir|9u}{Ww(U^H``^ER9~!C~)28~K3ZOtH zdQ!L-*iQRPOO)(LqRBB2NC{{dKqQyN=>KgBV}*uhz<^2{gy1Q8#>$jrXo3N4*U&L@@V!0=3-Lrz=O0}gm}>ju9!@YM*O0G4yL=-lDZ6Dz z69&>hTH#lglynqQS!|+Bfv85XM$gZmHK+=+sB21~eWPGJQ4YAAv;{aS%*Qvp1PmZ#f$M5|*{m*5_mgWa0CsycnbA6*ON)u=y0Pw$&1s~^lxDW_Z^FQ_xDcn!aZu0` zl8#8sg+acfUCvg$NBQ5Z|KNbrJT-nd3 z=+cMm41F9IAI+-3O+lzXz(kYOXdn?_fj&-HM5N%N(N%mPRtOq2giQORyz&LoSxAWk zA5HWPW70D!O^-o1hMsEQ)pcxqG=>7{BuouBfc$`XU9)!GziLiTYOE5#z{v#eXr0Hx z%#1HK6iFAHo}IOeVhxCbj@lfmzS`^CIut~YV)bw!r>0lIOppzr!QD=wPtn`4=W7DV zErBSV!MGg5rKZ|iBk_2ktqpvPgx)whq}3nMsvty#DfEonis|8Jr5HGaSm2JcF*W^+ zEoJiK;N`^>G~XH>F;W;Gz#DkUK}pfb?}A8!!v$u&RykubO}W zqFH@%-IX?aRKFB=rdb@jI;yY^7hswN-h+brjtiW6r4xp_%N8r7A56{6NZFLXj8P_x z^dLmV@e`DX9}_#X1c1G3Z}X{N+>$A}T&sH_$9@FN5?xNVIub=F1(lVR*y%9lD`~M>Y!n3r z=&eF3qz*kGhcyB+EJWNp%+kQ-|LXRcz*Q$=wAl1wIWV@EvwBSBIlZEb`;uK zm?bGG31(Sa!jY<%;SDaA$?rY&R^seaKv{eKqZA~vKWPpQ0_znSdOqm8Q#roDQ2O3bqFJp zUo8(v33-b{&gfvVP3-xN>&&L6EalI4NlWG!ek)&UVhV7QvVJ)qZ)Tl!^!Z~fa%*t2 z1Ba()l(rns%0%Hnh`98GRAA~tx@zqGW3loLEx-M0!W$|UA7j>)ra@iVa!1)q7U#b} zVB!b~D`as(1@us*HvcSYv?2P zRR&P~RbJ2vZ+Gg0n(l@BAgjyDQoRPrZ9R{A^Og5~=*lv@+d1_DVMK#Td~S3!i+Yvv?C-f4VdRyiKL{be(SNA&wNHd!aJRBLWu5XU@$Q1;o;^V0nF=!u zM1MY5WCWn{OMb4L+mOs|Tz7Q0v!8yR^f;Y_u8G|COh^clws8_1#?TY~3+he8BKRCc zg{ibWhdv5(mz8UWsVsg$Iq_fVc>ND?PXVli<@58$Aj51{x8FdxS`-VDQ#g9-s?N8AAAD+b14p-_DFb_tsvEb0K*TkkB6I^ujd1E_u=Gm#sS|{=O|s^i9=; z!QYCm;q%MjRB;^Hz=$di_&m)zFFG<3A!@gEYNtWnNE^%LiL$(1x9@3uOW2`XrmS55 z?CjhzJ-xb=4-GV&YGKKWt|AnQH>!{Lk&6>d3?l;bRWHf8OXsoDN57{;`uh&Av>9HC zeQJ`LIN1N$f_E0@h1wIkL|KlWNlY39atC-7hsh)9MeMVgGc~+B+<%e$6~S#KK3BKlx^z zw$5$?UpB7V_wT==<;kOCw%Y5lLt3db(|g7{iuclZ*B=azpPOIJJYa;&h-vVgxWd?8LJ9PqTtw;R&gKOuW7C@9FN)AltvI7z&@Ne~QQ$iE99udS&`o^U~TgN@Y? z)nFnAK$z7rdS7P{7dQ%X9~fyxIEZwlf1+C zkr4?BpDhMQQz{FC=@4g(_VMz1s-jgM%gUFqnuN2n!4w zBrOW=1KB~rPlSIMh7t6t9pp(x@$e@x1qE|Au26NhFL5F4pRjq5&uV10;2K6!ii}hS zsc=$MpnHVi)6)h<|Gdh`%w*w}cfcG2C(-{sJYcPS?g}Z#MLmx=NEgb+&5d~=d2S3V z*`VbRjg`a-0b)CYTSO(kbm?#U^fC^f+9^pLp-p zL8ygC0YxF9;pU_1H4gF=7kQX}1jj@dpjYCOwzk4q;bsegEn1;z@R&|pd0w(%H?#K2 zfQMmST%sCrH0+1X^T4-2jl65;&g)TuqH1huPp7??0W6pfa^1S8(T}b~72l6xEm`0j zsY`HZ@PuK~J!l|riXGB+qqLWj$84ZYUdl)CfJcmzg616=(r1z&h%h2N*quS`0$u*;j9I4 z{*329Ti`lz=D4Y<3WdKGf7~Ja*M%$Iz(t=veRBC(zf-+N4jOVltN;`3ERw#Gj1dcG zH4S4B4|l-XJDjga$_M(K(qenXC8J)$o~-QUf+URXn)zFb$u~YLQ`Gl*P2I;7rlLZX z{jk#gmLbHitZiigNx?T#Tcpz;ZvZii=Sopf&pniR4czo#fJ{1aEGZwkcoEWU@+ea~ zo5;i2Z78egVW2zBBai<`#wdlex`#77I=4yA&HxPPzs!p*t*Ax-!=qeMijKApN}#5h zYEi~;R?n^$k%u5?=BB1LBr`X~BquN9JlMfRnN+gzDy*a!1*si}o}%%t>gwdFU(F1T zKvtfwOV+)=CHEGGH0LKV9;kH0RmMBj<15H5yrXatu?}P4wVE`vyhN33u^MkXeG z1B24hGC3fF-T3kce@&ADiBhWh>!?o>XChH)CtuztpQJmnp z_@fl8KkyLv0jmQASK_^d0PXZYlhrKgX=yl!hGc#OowbFhf;!l&Q8b}Yt2ELSg>GPH zU%z%ANT5N1e4Nx2P%vWC;g~D z_hG4EU}iv!b9B+Qs%(FV+W$4LVugal-xzDmi_`D9qrO+X(Ut;SfP;ZpA7VfAJ@_*k zwC)P(QDI>Kgy+HDY0{BL7O6H(KV@))SQE#&2Hiv^p&RpuDqcT9@=4vbkYMAWfT+SU z21oEfIyA*UYtvQg6CqxA}UDXC4Byh$g{ZjSBgrt`MJds(T>XV00|VX(wd=oY-mI8e)_MgN^gZ?}3fR3org3Y2;1 z!*RHO^p*}zQ2L-*8Fd{Hu|It&?*7~Q-?xQ?6_lhukDTo7Rl$*wPyQm`{h@=biAhRY zBu~h=UU8J?MX0>T!NV)x*3!^KZrqs$++?`;1&-O6S5A?abImb5T3ga>p*uX@(|r1S z<&f*Z?I}arMQpEV>RXYAupf88YSFACJGmE$oHZwV#WZ0_R7SZ@;iT zatBlIh~LYuoB8G{X1`oLR;riG5wls7j<5{`{9^huL?T({&GS&N47t6iaqaiLbK_7B zSDet9#J_s!%#4h95h0@hK^of=kT}mFiW&V4&z~QMNbpB*@3Z^&gSh;6{1ntp=G(m6 z`OD#tk(H|)m;6}>j%GYaq;`5{rak2Hj4Klr{>GrQp#6snWXRdYjf&~z%HRG`u_C^n z=S1&xKF;M6>}NX)em+ji?as)^II?5Peevz#g!_Cqcf^ktR;Gi{mU)u)O;0=3C~n?y zZ@SP$f1X4dEqb+$Ha6cjQI6HA`0R`I%|0S`ZcF?2aMl1BB+y2W3&kdBOEiu@q2%T#kDZLt$xQ%lZXO`9OS8da2ba8DE>(A_0qC7j> z`3#xgu8u~jI{7p~Kbv4VhJ)|}TIDrggmoQ<#>-ddzM*|Q+h~=~4bGO;sj5Ey+upgZ zHfF7bkwItO;r<>rxpTZy^oI~T^rkpMd7#uo$IIufq9PCD<$*K0jFXdt(>)=_dwRGS z>69=GVQm5`Z@aPGW0zC=yB607p=BSP8cto_pS>R&t50H|ZC<}+3Z?I?!HA4U_u#>l zoyT8w{2u6hQT#II?!@i8{tfS?TAP18sv^(${Ce^vSotfrC=bjr+6B4=f4l+65n+o7 zB`TOZWL%qZ2zubkIdbOi{#Uwlj8w9@BXkM!uMQBlZ3vWr|MlVu|K6og6_+Ei1^6RO Ogs#>>&Bq$HSN=bKBxy4M diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_directed.png index 77106eb56d46320be55f68af9f3cc345a7d8513a..83d6e37647f1b6fe90f88f080974afea8573013d 100644 GIT binary patch literal 17353 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 z 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 mMB}CUMZX3{Qm%)pbLxu literal 19005 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 Ogs#>>&Bq$HSN=bKBxy4M diff --git a/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png b/tests/drawing/cairo/baseline_images/graph_mark_groups_squares_directed.png index d3168068ef58d289d1fff76b692d9bf2b22ae6fb..c5372745cb597e2bbd728fcaa117abd639f956cb 100644 GIT binary patch literal 14924 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 literal 16548 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 xi_-X%C1OvY)-3|biJ None: @image_comparison(baseline_images=["graph_basic"]) def test_basic(self): g = Graph.Ring(5) - plot(g, target=result_image_folder / "graph_basic.png", backend="cairo") + lo = g.layout("auto") + plot(g, layout=lo, target=result_image_folder / "graph_basic.png", backend="cairo") @image_comparison(baseline_images=["graph_directed"]) def test_directed(self): g = Graph.Ring(5, directed=True) - plot(g, target=result_image_folder / "graph_directed.png", backend="cairo") + lo = g.layout("auto") + plot(g, layout=lo, target=result_image_folder / "graph_directed.png", backend="cairo") @image_comparison(baseline_images=["graph_mark_groups_directed"]) def test_mark_groups(self): g = Graph.Ring(5, directed=True) + lo = g.layout("auto") plot( g, + layout=lo, target=result_image_folder / "graph_mark_groups_directed.png", backend="cairo", mark_groups=True, @@ -51,8 +55,10 @@ def test_mark_groups(self): @image_comparison(baseline_images=["graph_mark_groups_squares_directed"]) def test_mark_groups_squares(self): g = Graph.Ring(5, directed=True) + lo = g.layout("auto") plot( g, + layout=lo, target=result_image_folder / "graph_mark_groups_squares_directed.png", backend="cairo", mark_groups=True, From 6880e25aec46306cc9ee10945dc590627ad9b5e0 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 18:24:46 +0200 Subject: [PATCH 1303/1892] test: extending test coverage in CI a bit --- .github/workflows/build.yml | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 264db9e2f..bbe9e2699 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -295,7 +295,7 @@ jobs: - name: Test run: | - pip install --prefer-binary numpy scipy pandas networkx pytest pytest-timeout + pip install --prefer-binary cairocffi numpy scipy pandas networkx pytest pytest-timeout python -m pytest -v tests - uses: actions/upload-artifact@v3 diff --git a/setup.py b/setup.py index 7257780d5..36002acd3 100644 --- a/setup.py +++ b/setup.py @@ -978,6 +978,7 @@ def get_tag(self): # pure Python or have musllinux wheels as we don't want to compile wheels # in CI "test-musl": [ + "cairocffi>=1.2.0", "networkx>=2.5", "pytest>=7.0.1", "pytest-timeout>=2.1.0", From 4cd7f8a9b05b8972bbd525675dd0c68eb45c972b Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 18:27:25 +0200 Subject: [PATCH 1304/1892] ci: install Cairo in CI environment for tests --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbe9e2699..d29e8cdd4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: - name: Build wheels (manylinux) uses: pypa/cibuildwheel@v2.13.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-manylinux_${{ matrix.wheel_arch }}" # Skip tests for Python 3.10 and 3.11 because SciPy does not have # 32-bit wheels for Linux @@ -40,7 +40,7 @@ jobs: - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.13.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_BUILD: "*-musllinux_${{ matrix.wheel_arch }}" CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test-musl]' && python -m pytest -v tests" @@ -65,7 +65,7 @@ jobs: - name: Build wheels (manylinux) uses: pypa/cibuildwheel@v2.13.1 env: - CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel && pip install -U cmake pip wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "yum install -y flex bison libxml2-devel zlib-devel cairo-devel && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-manylinux_aarch64" @@ -90,7 +90,7 @@ jobs: - name: Build wheels (musllinux) uses: pypa/cibuildwheel@v2.13.1 env: - CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev && pip install -U cmake pip wheel && python setup.py build_c_core" + CIBW_BEFORE_BUILD: "apk add flex bison libxml2-dev zlib-dev cairo-dev && pip install -U cmake pip wheel && python setup.py build_c_core" CIBW_ARCHS_LINUX: aarch64 CIBW_BUILD: "*-musllinux_aarch64" CIBW_TEST_COMMAND: "cd {project} && pip install --prefer-binary '.[test-musl]' && python -m pytest -v tests" From 3a914318e4b0a1f57dfd93c0a190c55378ec3718 Mon Sep 17 00:00:00 2001 From: Tamas Nepusz Date: Thu, 29 Jun 2023 18:28:53 +0200 Subject: [PATCH 1305/1892] test: fix another failing Cairo test in CI --- .../baseline_images/clustering_directed.png | Bin 33682 -> 31493 bytes tests/drawing/cairo/test_graph.py | 2 ++ 2 files changed, 2 insertions(+) diff --git a/tests/drawing/cairo/baseline_images/clustering_directed.png b/tests/drawing/cairo/baseline_images/clustering_directed.png index 14885e28c4e93b66b41f7ec5884d509c27601dc5..712f1b95f8fdc22b4eb1b2683143634a81146a14 100644 GIT binary patch literal 31493 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

    U7wH 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 diff --git a/doc/source/tutorials/spanning_trees/spanning_trees.rst b/doc/source/tutorials/spanning_trees/spanning_trees.rst deleted file mode 100644 index cbc704269..000000000 --- a/doc/source/tutorials/spanning_trees/spanning_trees.rst +++ /dev/null @@ -1,68 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-spanning-trees: - -============== -Spanning Trees -============== - -This example shows how to generate a spanning tree from an input graph using :meth:`igraph.Graph.spanning_tree`. For the related idea of finding a *minimum spanning tree*, see :ref:`tutorials-minimum-spanning-trees`. - -First we create a 6 by 6 lattice graph. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - import random - - g = ig.Graph.Lattice([6, 6], circular=False) - -As an optional step, we randomly rearrange some of the vertex IDs with :meth:`igraph.GraphBase.permute_vertices` in order to generate a more interesting spanning tree. - -.. code-block:: python - - # Optional: Rearrange the vertex ids to get a more interesting spanning tree - layout = g.layout("grid") - - random.seed(0) - permutation = list(range(g.vcount())) - random.shuffle(permutation) - g = g.permute_vertices(permutation) - - # Calculate the new layout coordinates based on the permutation - new_layout = g.layout("grid") - for i in range(36): - new_layout[permutation[i]] = layout[i] - layout = new_layout - -Finally, we generate the spanning tree and display it. Note that we use ``None`` as our weights value, to indicate that we any spanning tree in the graph will do. - -.. code-block:: python - - # Generate spanning tree - spanning_tree = g.spanning_tree(weights=None, return_tree=False) - - # Plot graph - g.es["color"] = "lightgray" - g.es[spanning_tree]["color"] = "midnightblue" - g.es["width"] = 0.5 - g.es[spanning_tree]["width"] = 3.0 - - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout=layout, - vertex_color="lightblue", - edge_width=g.es["width"] - ) - plt.show() - -The final plot looks like this: - -.. figure:: ./figures/spanning_trees.png - :alt: A visual representation of the spanning tree generated from a grid graph - :align: center - - Spanning tree edges are bolded. diff --git a/doc/source/tutorials/topological_sort/assets/topological_sort.py b/doc/source/tutorials/topological_sort/assets/topological_sort.py deleted file mode 100644 index 55efe2eab..000000000 --- a/doc/source/tutorials/topological_sort/assets/topological_sort.py +++ /dev/null @@ -1,35 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - - -# generate a directed acyclic graph (DAG) -g = ig.Graph( - edges=[(0, 1), (0, 2), (1, 3), (2, 4), (4, 3), (3, 5), (4, 5)], - directed=True, -) -assert g.is_dag - -# g.topological_sorting() returns a list of node IDs. -# If the given graph is not DAG, the error will occur. -results = g.topological_sorting(mode='out') -print('Topological sort of g (out):', *results) - -results = g.topological_sorting(mode='in') -print('Topological sort of g (in):', *results) - -# g.vs[i].indegree() returns the indegree of the node. -for i in range(g.vcount()): - print('degree of {}: {}'.format(i, g.vs[i].indegree())) - -# visualization -with plt.xkcd(): - fig, ax = plt.subplots(figsize=(5, 5)) - ig.plot( - g, - target=ax, - layout='kk', - vertex_size=0.3, - edge_width=4, - vertex_label=range(g.vcount()), - vertex_color="white", - ) diff --git a/doc/source/tutorials/topological_sort/figures/topological_sort.png b/doc/source/tutorials/topological_sort/figures/topological_sort.png deleted file mode 100644 index b622630d8996dadc7227a7915d5cb82ad9fbc16b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27783 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 diff --git a/doc/source/tutorials/visual_style/visual_style.rst b/doc/source/tutorials/visual_style/visual_style.rst deleted file mode 100644 index 095c043eb..000000000 --- a/doc/source/tutorials/visual_style/visual_style.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-visual-style: - -======================================= -Plotting graphs with a consistent style -======================================= - -This example shows how to use dictionary unpacking in order to easily use the same visual style across multiple graphs. This is a quick and easy way to quickly share a single visual style across multiple graphs, without having to copy and paste each of the individual attributes over and over again for each graph you plot. - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - import math - import random - - # Configure visual style - visual_style = { - "edge_width": 0.3, - "vertex_size": 1.5, - "palette": "heat", - "layout": "fruchterman_reingold" - } - - # Generate four random graphs - random.seed(1) - gs = [ig.Graph.Barabasi(n=30, m=1) for i in range(4)] - - # Calculate colors between 0-255 for all nodes - betweenness = [g.betweenness() for g in gs] - colors = [[int(i * 255 / max(btw)) for i in btw] for btw in betweenness] - - # Plot the graphs, using the same predefined visual style for both - fig, axs = plt.subplots(2, 2) - axs = axs.ravel() - for g, color, ax in zip(gs, colors, axs): - ig.plot(g, target=ax, vertex_color=color, **visual_style) - plt.show() - -The plots looks like this: - -.. figure:: ./figures/visual_style.png - :alt: Four graphs plotted using the same palette and layout algorithm - :align: center - - Four graphs using the same palette and layout algorithm. - -.. note:: - If you would like to set global defaults, for example, always using the Matplotlib plotting backend, or using a particular color palette by default, you can use |igraph|'s `configuration instance :class:`igraph.configuration.Configuration`. A quick example on how to use it can be found here: :ref:`tutorials-configuration` diff --git a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py deleted file mode 100644 index cd8cdf6c9..000000000 --- a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques.py +++ /dev/null @@ -1,21 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -g = ig.Graph.Famous('Zachary') - -# Compute cliques -cliques = g.cliques(4, 4) - -# Plot each clique highlighted in a separate axes -fig, axs = plt.subplots(3, 4) -axs = axs.ravel() -for clique, ax in zip(cliques, axs): - ig.plot( - ig.VertexCover(g, [clique]), - mark_groups=True, palette=ig.RainbowPalette(), - edge_width=0.5, - target=ax, - ) - -plt.axis('off') -plt.show() diff --git a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py b/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py deleted file mode 100644 index f677371fc..000000000 --- a/doc/source/tutorials/visualize_cliques/assets/visualize_cliques_with_edges.py +++ /dev/null @@ -1,30 +0,0 @@ -import igraph as ig -import matplotlib.pyplot as plt - -g = ig.Graph.Famous('Zachary') -cliques = g.cliques(4, 4) - -fig, axs = plt.subplots(3, 4) -axs = axs.ravel() -for clique, ax in zip(cliques, axs): - # Color vertices yellow/red based on whether they are in this clique - g.vs['color'] = 'yellow' - g.vs[clique]['color'] = 'red' - - # Color edges black/red based on whether they are in this clique - clique_edges = g.es.select(_within=clique) - g.es['color'] = 'black' - clique_edges['color'] = 'red' - # also increase thickness of clique edges - g.es['width'] = 0.3 - clique_edges['width'] = 1 - - ig.plot( - ig.VertexCover(g, [clique]), - mark_groups=True, - palette=ig.RainbowPalette(), - target=ax, - ) - -plt.axis('off') -plt.show() diff --git a/doc/source/tutorials/visualize_cliques/figures/cliques.png b/doc/source/tutorials/visualize_cliques/figures/cliques.png deleted file mode 100644 index a6e9d626f172f8347c0454974c1148cb2cbddbbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99882 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�`FG0gowi&!Jzy&$N>#c##5RQPIl^)x(* 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 diff --git a/doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png b/doc/source/tutorials/visualize_cliques/figures/cliques_with_edges.png deleted file mode 100644 index 49e4abf1ca037631a0b229576b7602f1867ff837..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106100 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 H<_G^DFGyWo diff --git a/doc/source/tutorials/visualize_cliques/figures/visualize_cliques.png b/doc/source/tutorials/visualize_cliques/figures/visualize_cliques.png deleted file mode 100644 index 3c78d8205cc42894e4c4444ae8cbf4028d1cf573..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61106 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

  • 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 F{ug#u?q~o2 diff --git a/doc/source/tutorials/isomorphism/isomorphism.rst b/doc/source/tutorials/isomorphism/isomorphism.rst deleted file mode 100644 index 1d4175623..000000000 --- a/doc/source/tutorials/isomorphism/isomorphism.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-isomorphism: - -=========== -Isomorphism -=========== - -This example shows how to check for `isomorphism `_ between small graphs using :meth:`igraph.GraphBase.isomorphic`. - -First we generate three different graphs: - -.. code-block:: python - - import igraph as ig - import matplotlib.pyplot as plt - - # Create Graphs - g1 = ig.Graph([(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]) - g2 = ig.Graph([(4, 2), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) - g3 = ig.Graph([(4, 1), (4, 3), (4, 0), (2, 3), (2, 1), (3, 1), (3, 0), (1, 0)]) - -To check if they are isomorphic, we run: - -.. code-block:: python - - # Check isomorphism - print("Are the graphs g1 and g2 isomorphic?") - print(g1.isomorphic(g2)) - print("Are the graphs g1 and g3 isomorphic?") - print(g1.isomorphic(g3)) - print("Are the graphs g2 and g3 isomorphic?") - print(g2.isomorphic(g3)) - -The final output is: - -.. code-block:: - - Are the graphs g1 and g2 isomorphic? - True - Are the graphs g1 and g3 isomorphic? - False - Are the graphs g2 and g3 isomorphic? - False - -.. note:: - `Graph isomorphism `_ is an equivalence - relationship, i.e. if `g1 ~ g2` and `g2 ~ g3`, then automatically `g1 ~ g3`. Therefore, - we could have skipped the last check in our example. - -We can plot the graphs to get an idea about the problem: - -.. code-block:: python - - # Plot graphs - visual_style = { - "vertex_color": "lightblue", - "vertex_label": [0, 1, 2, 3, 4], - "vertex_size": 0.4, - } - - fig, axs = plt.subplots(1, 3) - ig.plot( - g1, - layout=g1.layout("circle"), - target=axs[0], - **visual_style, - ) - ig.plot( - g2, - layout=g1.layout("circle"), - target=axs[1], - **visual_style, - ) - ig.plot( - g3, - layout=g1.layout("circle"), - target=axs[2], - **visual_style, - ) - fig.text(0.38, 0.5, '$\simeq$' if g1.isomorphic(g2) else '$\\neq$', fontsize=15, ha='center', va='center') - fig.text(0.65, 0.5, '$\simeq$' if g2.isomorphic(g3) else '$\\neq$', fontsize=15, ha='center', va='center') - plt.show() - -.. figure:: ./figures/isomorphism.png - :alt: A visual representation of three different graphs - :align: center - - Three graphs to be compared for isomorphism diff --git a/doc/source/tutorials/maxflow/figures/maxflow.png b/doc/source/tutorials/maxflow/figures/maxflow.png deleted file mode 100644 index 7004367c9a97aab02ddd7d71312e4dfd1d9e0511..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17642 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 O%~LujvwpsC>wf`eFWZ~| diff --git a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst b/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst deleted file mode 100644 index c24e67e3b..000000000 --- a/doc/source/tutorials/minimum_spanning_trees/minimum_spanning_trees.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-minimum-spanning-trees: - -====================== -Minimum Spanning Trees -====================== - -This example shows how to generate a `minimum spanning tree `_ from an input graph using :meth:`igraph.Graph.spanning_tree`. If you only need a regular spanning tree, check out :ref:`tutorials-spanning-trees`. - -We start by generating a grid graph with random integer weights between 1 and 20: - -.. code-block:: python - - import random - import igraph as ig - import matplotlib.pyplot as plt - - # Generate grid graph with random weights - random.seed(0) - - g = ig.Graph.Lattice([5, 5], circular=False) - g.es["weight"] = [random.randint(1, 20) for _ in g.es] - -We then call :meth:`igraph.Graph.spanning_tree`, making sure to pass in the randomly generated weights. - -.. code-block:: python - - # Generate spanning tree - spanning_tree = g.spanning_tree(weights=None, return_tree=False) - -Finally, we generate the plot the graph and visualise the spanning tree. We also print out the sum of the edges in the MST. - -.. code-block:: python - - # Plot graph - g.es["color"] = "lightgray" - g.es[spanning_tree]["color"] = "midnightblue" - g.es["width"] = 0.5 - g.es[spanning_tree]["width"] = 3.0 - - fig, ax = plt.subplots() - ig.plot( - g, - target=ax, - layout=layout, - vertex_color="lightblue", - edge_width=g.es["width"] - ) - plt.show() - - # Print out minimum edge weight sum - print("Minimum edge weight sum:", sum(g.es[mst_edges]["weight"])) - -The final plot looks like this: - -.. figure:: ./figures/minimum_spanning_trees.png - :alt: A visual representation of the spanning tree generated from a grid graph - :align: center - - Minimum spanning tree edges are bolded. - -... and the output looks like this: - -.. code-block:: - - Minimum edge weight sum: 136 - -.. note:: - - The randomised weights may vary depending on the machine that you run this code on. diff --git a/doc/source/tutorials/online_user_actions/assets/online_user_actions.py b/doc/source/tutorials/online_user_actions/assets/online_user_actions.py deleted file mode 100644 index 12dec7210..000000000 --- a/doc/source/tutorials/online_user_actions/assets/online_user_actions.py +++ /dev/null @@ -1,63 +0,0 @@ -import igraph as ig -import numpy as np -import pandas as pd -import matplotlib.pyplot as plt - -# User data (usually would come with time stamp) -action_dataframe = pd.DataFrame([ - ['dsj3239asadsa3', 'createPage', 'greatProject'], - ['2r09ej221sk2k5', 'editPage', 'greatProject'], - ['dsj3239asadsa3', 'editPage', 'greatProject'], - ['789dsadafj32jj', 'editPage', 'greatProject'], - ['oi32ncwosap399', 'editPage', 'greatProject'], - ['4r4320dkqpdokk', 'createPage', 'miniProject'], - ['320eljl3lk3239', 'editPage', 'miniProject'], - ['dsj3239asadsa3', 'editPage', 'miniProject'], - ['3203ejew332323', 'createPage', 'private'], - ['3203ejew332323', 'editPage', 'private'], - ['40m11919332msa', 'createPage', 'private2'], - ['40m11919332msa', 'editPage', 'private2'], - ['dsj3239asadsa3', 'createPage', 'anotherGreatProject'], - ['2r09ej221sk2k5', 'editPage', 'anotherGreatProject'], - ], - columns=['userid', 'action', 'project'], -) - -# Make a graph with vertices as users, and edges connecting two users who -# worked on the same project -users = action_dataframe['userid'].unique() -adjacency_matrix = pd.DataFrame( - np.zeros((len(users), len(users)), np.int32), - index=users, - columns=users, -) -for project, project_data in action_dataframe.groupby('project'): - project_users = project_data['userid'].values - for i1, user1 in enumerate(project_users): - for user2 in project_users[:i1]: - adjacency_matrix.at[user1, user2] += 1 - -g = ig.Graph.Weighted_Adjacency(adjacency_matrix, mode='plus') - -# Plot the graph -# Make a layout first -layout = g.layout('circle') - -# Make vertex size based on their closeness to other vertices -vertex_size = g.closeness() -vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] - -# Make mpl axes -fig, ax = plt.subplots() - -# Plot graph in that axes -ig.plot( - g, - target=ax, - layout=layout, - vertex_label=g.vs['name'], - vertex_color="lightblue", - vertex_size=vertex_size, - edge_width=g.es["weight"], -) -plt.show() diff --git a/doc/source/tutorials/online_user_actions/figures/online_user_actions.png b/doc/source/tutorials/online_user_actions/figures/online_user_actions.png deleted file mode 100644 index 01cc648d71cfbe61ed9a8e1ceb7c4a06b5ba18aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31455 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 diff --git a/doc/source/tutorials/online_user_actions/figures/online_users_simple.png b/doc/source/tutorials/online_user_actions/figures/online_users_simple.png deleted file mode 100644 index eee2ee4e8f237edfae277bdf6404e29d16ce0aac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47195 zcmeEucQ}{r|F^a>3u#HDjI79rP%PCw_c)&8`2F+z|GSUlKDzJH=W|`xd7kh0YrU_)E0^Uc_8i(nLPA1uQC?b=gkr@XJ|887)UO+Z&E9hPO;fE*U!7S=l;TSr{F2HofIwVQa(BeTJK# z^O(7#qn(2Y50CYKe}LQemKjf7oOA;|WVfCCH3t$BDnsJmEw3d~EJ#QSK3|l+pzazo z-tDBNKC)UfBP1Vbbo)-XQLtt3ofj1bE?I>iS~IghEOd0|ITwwl@dtDVX8dG$eZcn^ z!_eX`3A0$914VbY-73qp%(5JcF{>{$d(_82bk6VvThLuTZ*f0_{{0V7T zy*vr+Kc8s!zaR6z&*uMQ-y9ezBEd#v4@#UKsHHh7;jJVsy*((=;Kq&nB_(1qL9|R# z_sLhdRY;lUB(eMYi*AklIFWDN`Ki!hsL*a^>lWJ{miGFJAK|x5zxEBN-`PoV=t`EJ z7&*nCZxTm#jjZ z6N?V~-pG8D@=}@Wg{U+Ed&{QXDIN2l4dzURglT2^7LxvscfWt$bdrJj|!zX zd^ZyH%e_idpO=ac^1f%bDovaAelc-lr6QTB?Xk zQ1B`C=p#`V8*&N?i>~*lA1yh(@|6ocYKTusyPBTc`RT#I$Kx*({iu5xQBq$S$BMdq zDlh-_a#PG>fn0ugTY>A0(U+%O!4VO33kwTp%)j4OOSybPWYCX{{evJanqaH86w`1JCI(67yJtJWlK4RJ;@2|4lB zhYudTOf__CZmKhKH_gfKADk>N#|YnvkB_%0`Yiw8!2{lv%@ZTVB_&a!F5Fks)S1lc zV|@MnbF4cBLl`CM!%rvC>kU(=j7s)eduU(aVAMtN?;>$=ak(5X{;j*n1rMh$s5_XRhfVbrX=Y}o zRcHQ0&d??=NxpgG-LD0cyryGuPu#LMr+T-azfByJmgB24e?1gpMVwscN9o!!bywSl z9tH=$l=RypEh~F#td)x-@#V|2J{#w*rfalVh}v`s%Z48PhNZ$bS#BHJCmBFh%Vogi z8$xkd(7?dpd}qG(mVm%OCT8ZX9v&XC&iLoRp+iPCHksYdYfJVzIy$+1RLA5(jtGm2 z{{Hi)y2xcJxASFU;sIg1W9{!u@!$?AD>q1MHhOy2tG?2a(NH=flO-bYJxyKwgF09B zPe$#TUn^Iwiw+NYJ?kmkC1xqwh(B^~PAmU%@nvAp1NpfXPs;Hdx6=eO6o<_4i}$3Q`PH8}2##P6(0r_aY9S6FaA2xXulh~~#a5Tg%6DJ9EtI&J>!$SUY*m1erJY(CQ zF-h&bHB^7e&hD*qbYS4c#OYn%UtOdjvFRyJ?LO&+;=CF0W;?U*_n^SQzO1s1#G5T? z*tS$84h{|+SJSF+G+(PG1ug8KX7pLRlaZ0J(0YQ!_XE|oK9BwT_e;ykIZSj2aA;H*pi^*59UPad|?F+Xz$##CbmL@j%heqyMPnIa_u4SZ3cE~9K^-F;d1N&YrUQVVO{y1H2$+omPv_9Xa-=1el zkBw~n;}seSkKWqjDSIug1AF)GE%sX7pLhM+WOtE8OInMWkKo3}28qeH=kqz%e$@RA z1U}1MnCw>gUxp*1vujO)^YR2xBTYU(x-e9-{6ybp zJ>rDoQq2Do+$^Z#pB^6mJNWIebx}`=hr>`k!w2VyFAon3y?35Cgf2Qz z9ZXLmEzQyuKEJTAlQ`NULkD>cZZB-w_Le>jOg*S^kl%iB^u$*E6`$Nms(aT>T!on~ zY@y}S+$*Ev>dK#BtM@%U@?5c7?DdD*=9P@+qi)s<({jw#8kc$;R$3~e4idfE|B*r; z8053=``7usJ!Pj2%1IWcdK*St(k;Hf*n)MyuJoBbOT&73p#07@rMPoZN>P04V-9K8x@DBD{JFbv!DGy-~C8eTLc3fTjnQg37Ng ztQ%;txqFKB@@E4RX(gq)GVz7Yn?1#6hw5X0 zV_gClCVI=_an=2kllA@8!DTBt*q?DafHEX+z1Q8}ym_;4M@b}){?^?W#(b))s;Cbi zjy5mK$lz*8*K89P2V$b6r0h7QPXIJD($&SOF`fA$uhsm8&2M#e0n3}(FY}!jnr%Cy zR;)$;3jU(F_xwY)^~{kkZEq?ciwe1I3~%vbZAj4gy}x5f|E!yOO7f!Dn%+70XRmwA zsGNo*&*j+Ce@ae%pi{cVm_}`4q0+~8V<=Bf#_;KBenUgUz>r1T;otc>wYc-{pKJTkE71@+ywEPaPxJ@$K&lj)RpV30LgI$FV1;Jg~~SZ<~$#bf^4 zciwF~ckZn6p?23_7W*^)(P!{DIR*KW=K2h9V1&80k`lRP>zj{VT`~JkD3}-Y7Q4}) zrqBNQ>K_@Y8Gbw+mD2LFrUKJ;T;)jsu*M1f+k5CZ2x_5`rFThQo@n01t}}PB5{BrV z{C2;w1s@z1qSVyXd}mTy5yfw&Re0+JaD9r;=0=CJ>DQ-8m!btZb>2TJukNsF_;)PDk$Wte-A; z*Iy@YTOoOursSz}8M&EJ1LXtr&SxUuuK%61=It5NcvNJk!YuJVTr)vK_e}cJX}Lw` z=4tba&f7xc?Qes|-DdwTEl?OGzI63m-2ca8Q7Je4OU>MP`{PHCsDXknX6h79FD{y` zugrISa0))if5UuL4*0Tva8UNj73zDtsBYjKiqx=cy*&newVX(l9yxYM16f$qpxD^h zeb})B8`INvrd{vt6$1C2phdeqVf^VqkiWk_!QEn=7bm;bbaZti-dxM!NKQ^xz^Q+7 z@$pG^6&01hkb`^oCV&tr11JR>Sy-f^4*Wr#-t*$YQL*cR4<4uk%N2F&oKc zIOh`8f9364BP*jc)Zaw%r~;kTmiI~FTq*Z17xmEGU^_dz|H^|)N)b9c_ON@MtXI9h zuq?CXNvifD+wEH`a~9R@?bqxb9hK%*ddfl;1#P-szkmOp4NWO1EG*2((lVX+Us0FI zX1AV7e=0h_e6SpLmClG$nl}p`;x58MotdhJKC9YE2B@cdF7Gk;&|TA0yl=Q zpD2!>Idi7AGY8fFz`=tvHH<#IMpXf{>AwN#XgSma@+{kK4lx}$dyD1q$x90FY?G-a zi&+V@ld6Gs{@!)&Mg1Ah)Q?eKdTY~CNudkhJS3(J6|y?Qn%(q@U76DTNSVYH!K9h5 z1_4HTF3%QIkpG(N(T(@15Sm@<^U91lC;R711W{LWea2cd<|exjZ`-!*W?N>gk<%Nk z?7O|*s}y8pWI#rB*bksdJArumze81C3DHyzU{AQ>+jBrdui0Gj(?3gMc`%q^b`z#Pfc1yt8!&FUUYuz+OjemFiJm zKE6cxFlMEA@!0zmhu__7;aHg;lgqfCxAeC`BD4!KWRF$aF`hg85YNVfa zn`HrXZ_d!Br=p_r^zyRk$Yu9=(|LJ!ih_H_U+eP2E3H}e4JAJPk^0^rJ39~C+S=Z| zdzbBM8f{!$oO-$jg|V@5Nh`ZAbv&VSB?zJNjrW!@K9sElsUdg_eyllNlS)xh@mQaR z-TbJ4YyW2WNav#AO`Dmhm&q|B>mGJP6$fo}%0j>{9`Q!@0+U=xZ_z1nr_(*=UE73ymXHHE9n=L=cXn1?$KCk^#-<3E3n% zAS7h4Dv;)N%gs#vvdd37ui3e{q+GbSQ~%6OryKoTYTxK+P+s1=&}%L1s7u6-k}2_A-p9kk zg90vPXUB_@SKZX~7+8BPect+af4}+n7fh^|V@>MPxM(@93jPV&I6ocTw$_uscV~8^ zPN8R%Rr@=y83#IiP(~Zqu_1SVc!?w9jK*q%!hNg4Qx)c=l*jPqFK#XZ2jW-TyRD(VfBr zrNs_jiw~hYaNspV_u9(5B@oDcg`|r1_Je9_O(vN-|M#}qeSLl3x=iU67ZB%0k56t!I=nt7HZyZpv4-imy><6#nUywOaeH5xOiNhqngnq8?uWhD zv7qQvEN5T;wv>^U<^?W%%B`!As?f4zQ9(Y=Fw62ayRz5so%b2^+ILUDN@@3F{)oddfK9kSWEj9F#0iplwLS<~9v$qCF z4?Vn(`ek5i8|v@B%f`m$XGe$k<3p53gv i)IHek=RU#{BBJ1zgRAFHu!uaKBZx}GrzM&jMU0JQJCf4@pvW@fOO|7g#2_0&f(S{bIud)p-DM`h6HYU9LK zZNs>Eco=(=>q$-&wYCJ5Tjw#Hy(zsj2|m`v{~Y zQcDu@JITc?y%}#^y=x`Rr@j2nFPUAXL&-wF_#AVVe{yp2jMdNSV2!H~LkShifr?SQ zIaB{I9i2=B$JJ@v1y0{P?+LSE{_Ula%^$vC&%HDK`sKx5ba+rqW(I;sV?lA~P*bz> z@{$ZI@8dJ6MMXuuA|sPu-KQqqea`@dg{Wj8kpuOyha(hZO5Eq)zI(TloJY!}DuHkI z`~*z(9=jiRbCQ?$(dU1a8zG?-RC@K-SMC^92PFjtdgzz9`xO)j_4M>?-?2j_O`RPj zF;yeu5K8+BH_tZ(E*z#6JHR(1(?n>?-`TCxu%70uJ4#lnN~{dQGBCu(0DWuX5bEo#j6| zo-18@XJ}<4>FIfHZ=YeY_XatM0~y(u$WzMT%b>lwX`}q~jEoIQijmlFG2&i_`1$$K z(x#`UkNIq@t#D5jg*})2_ot3zGwR3?yHj#C~7$ z0X2W4T@bQ^jQ-Y4#g1`?TWYC#QhT0qN`Zew)Z40edy5& zNamLrM1K_6>Id!TN=wmv%zI%L1p+rg=(fNGeIp|mQHHYLzWuJP+ndvTU~6w1fn?4c zqKM?yWd@{c&eCTjYS+N$gn|!*8iGfsRcx}mAztjIdHbFx87k3tLz38kX&vgc3M@Ll zy>xD9V?O=dd+&%~IjUPz9dx&bYAcmX+#7Sul=;l+-}q}XOLq`0_t%dkMd;8`mTjKw z`Z<&~)*>qTvJ*aDSNkB%qr#PcR&tXrNx^H~Ug9JNN6<^T(8Nab_fBK`2_db! zI~HceXS%&&@)Jzd$C#P#0xrHpWAND&hcqgO4hz%`?O1KR7+k$SrKe=sqf;>Lz1w%M z=Bftn_Qex-^-4@ee)bA`*zsgsFSxN$?8bK@ggXA%mMgEcp-NOsCH2pZG@Ti14^0+Z zHH@iSPn=xVyYcbumL&eZ4Is^%XA<}(5ARs8Y^L3zlMwUXpu~dcS*~z?E zy5Dk-8b3YXwz@c$clbVaYSi}gVca`#jN7XHiWVpNt!54dMPxlQ8VU*tGU@rgu{6GT z1L!r^qG>QagdXJ^?hf!$jD*k8Q>RW%{4fCRtyRyHr?fb+y_EjQkvFmC1@y^V@0)W_?=ix7`>RNvbf5_RZmdaLH9{eE`V48Qa8ua_Y_;Smv7Bq`~{Kk7x==G+N_@~fxo#VReF zJy_^@90Jh^pT^DOENr*!b+6OR2tInudKr@Z9a@PLYKuTTqDjZ8p4j=rf_&~R`n24- zlhLt4+=5RJZu7V`F=wBtUnGk|Cb4=1y}|zXPIPJGnh;2%#HyfvKhf5n#4cN47Es6njBeLSaE>Pd)jjV~^2>+0^#E>JEEnU$0% zjie@>M#Gsf`R(oPJ@74>K0?6{S{#IB^|iiTcPoxZ<+{qG70hbYs5OI`Sb6 zYsi1U_!JbM^Eu2mJb%i))j82AU84$0 z(SZZ<;LIwi>gv!au5vY<2=85_-O7}ZHM;s|r*f=_Uur5lfQM1*n`?xgLdTjlS|nXR z{`bc9G8>%_j)Ca)-nreNa|cA7IkO0k;I^Gn%w2k8Z8-{d64ca{(cinnbOz$W+89}iJYvEKB6So}1E;nS~Vn_SK){~Oh}PTo|5;(u*C z$7im0v21>^*QY7%>M2O_xBdKf$OP~I)28opLRff7f?=xhr5qqO%W`k>rReaa8%*LR zuco$EEhYeoN=r)*`_k*{>swh{kMx#FT+6vpjao@}N@Kc`O2Q5b#+N7T+sYxTEUz#2 zTKs&=bX@j9`RC68@HZOasM&PA{|GIsEKN{Gq)Xe)-jG1D|k&*PU1``1(2*nyg z6S$5PB&9R^_-?xZ@|>x`%vxdn`9gpt_Jv#8Km12NP z^@xZ6xpO{q$7WWoO?(xos{&)M?57yo)P(FniEO_(3^u)IAGJocC!EcM@G{ zPE~_pFyfj0!DEp-Ng*N;9}W!4U2Dt{Bxz#8GB`L0YVZgR*#Q>i1nDfq00abFU_1q< zr=KDL9RXH;4s-FQ+?mCl$N-w9WDt4VKX5hHv`246>|=TPl@zMX zM79SLKZ3OB8?s01oM1^^3%ozFF2~yx|q# zA8N3#Y|k;I>$DM5R@c0}>EPac%Lu~O8Ov7A+K#fh{nKFC`itS{y?a9$m50fDQ5|CQu{bCB z_`+jFX>7jk*tzr8?@ts^`V(oSQC6g|JO3;+Ypyg;{DQxFa&+Gn047*%g>HY7owZ9n zm%)n+P#~~*Ae$48Jn8P;hMODfI1_qiD=*-U7@3+@!`J(3yRbC#8(QkH(n$DmIm(#W z*qPZ`1;?+hIQXE6Tc9h0G$`TOz3>Vtk&2Vv_7=~4DIxPP zKzXs}idIpH)^bqb(;IbBStNyIbRVZSbYmx?-rcBd9{;P^1=}?+DUSkl^@p>m-K|?j zkm%w)dys`-SAR{7x-)?I1Cca#w&C8Z_c8JYUv@be?42S?6^`%^KhrfYD)*%Dt}`}NBJxr~QdSvYT@_R0Nx`Q8IhkO%G?vbSkO?EtT zZY!CkJ}Xkab$yIV2owNdQtD)JCoJB`1&;)WLui6e2m4{pU?qTO5S^|!X(N~0HH@_!XI#?e{4+A%8CBErEw*nrl!`*zH{0ARB&B%IoH2o7`G7(6DS?4z9mb)w zBML$TlQ`ta+1c8#<@l94cOLKp;Q5>z-wx&5_Fe{-aassv5Zw=cQdd{^S}U6wg1~BI zmTCacaW9f;vxf&x-+lJ%z-7<3F{)TLBwg5$WNYL;ws{(OXK-P{_mL@fI>7F5N8T7~ zJPi^t_jC%)U(}Pmwt$xdCDzQzC-)$R}uz>dO?EMZE z`N|uu(@%Ny>pzDbrzzoq+FI4oA=0<}=W7%C_{Q2_WeB&6Sv`vo0`~nY!U1-Fa9&+K zb*~{#Y+HFxPaMFq{p`TS*x$RhZ?{A3ur7FrZocYmNeR@<8ZU~KNw`e=Hp58I@wy4qs1L{?7Dva)g2hYAhs1`#A;l+a6w zH^&mOYi1t#JJc}LpA>v%)q+HMYD6zpQNi4fdRKwXi}z|t4VhG)N`Hm!@aTX4(Cbqq z7?LOsFgm>+~3g&R0?c#A*WXZAwu<9H(7-+{|Moe=R&q|0~JON&G@4Nsuz!7vtVi zuQN7XT4r3|a97{+t+kP6x*#wAnKd-~)*l6I%1SU?0^}gpfm`*;^@0oqo_ri2@TJ#p z;NYac?`0nz+P;0exn+B{@h&1PcSvB5goMPn#DTS$4JirZLCyh=D*=ax_Eq#`1P}4n zJ-YKr*M}M1(OPacn%_S?1Ip1P32Kc8mmDAKK9u1S4qjrhaC>6kNL?=~IGR`86>S`+8!i zXA!+7{Is#G_u7mc5oCY>LSzzA47PvQy9%G{m03gFk#nw(pd{J@y>X+81DNC$q=tXk z%Dz$3pu4*mYKhm%T!KOb2Na=;Lxm_FZM%J@8yc#co6j^B;_Nwk+rUR1#Nl+D=!iHh zWMhZmj)?R4XT+==LkJj6!^o(N&jm(#xKM`eriP{jIs3e;)`5k>zg`RTpK5CO&88cC z{d~V$S1l>$&wJQKn*P48mTR@+rhv_IyD@9^50T?xeSO<^?DSsf9fzoD=j?n^ztr=H zu-&hmK3nt(9M%{jkAfv*?O`*{RLCwgtkeKd$mex+V|Qr}fpvHp;gv zke)WzgX#MDVVf_#f^AL%I50q34mgNQ-fR~)XACj0?EWBtN4(1bHqFKSsm=l(kA-nV zaFC9@>6@n@Q;LN4`UvmZvBS{VxDp?H8jlqkBWQrpO4wev>Qn0d{n=9ID>8ZrF;43p zxyC{3Lbs3pO4o8`mRc!pz87i~AA+uSYv5bFxhbXpUBA55EkOEpsbYsdx!B6xSUvJ2 zL*sE8#W{A(m-!24Wk2mM(1$;uWMJ^(^7$Op^T}@CQ*7SeyK8c@vm0$Zc+l`*?6Wp5 zfbxe6SZaX5oUaa|BQh)(E?nqHS0cdbec0{Wx21>ZH+4~eNhv7);30$b^1?g7DXa%w$Z=RhA<{iJt-VGHMrF1d?8E!bheos=bMa!XNDShuHO@8 zzw}|TZ>?`#T2A%~bn4NzEM=tZpjBT_%;$*MgP0uwdm|!RSVKJ!u|uvX2-*swgYxgb zy}J0A@MHjlH~I@zL1vWDp&JMb54&vjnDK%+Q_2qC5cgM!0{fW!HiRG3z6w8r zPf;?6i<|Y==Byk1w^)*Y<5bZ47(>+j7u`-%wh6a~=4E5(vBHgStgIl9jMzkjn& zs*jNA#bzRQ#pku^%^fdXk@VZY&~cpFf1^h!LzZh;)RdA$Fa7D(-9F_wLYca6HgL9x zJOC=-w%rBZTUs-9zka;8%cpFDXIX<_@}E0V5pVjhCBva|N#s&JkVrXoQE0ML#}#i#A|ZIZ;q z#C_|L zi7(h(zn7uw3=+gPywtFg(0)r~da3>r*4HU>tGI`qa?z%kF%1nzt9_CYgC>4^*RVL}pSR1-V)tx$ToUVVWE0)_*v<<qSvEGwiCrS?}Kq1DO+jRxy%$ec*Jp4-FbWfQ%N{WnW*P`Wvk< zY!$V%CzB+>P>4`^`=lj0zkk01UsxIs{Q#dyfU}3A;~BV6i7=#vm=Lx9rv@MTYx+SlC{KZ%iwEcat9$RAPOC|Dia3{J8t#I+ zf@elIIA2kG3ufaBbY_tzMbBXrunxC@9uJu2yQq#To#C(t)h6=($VHrX7_7_6ECQY* zXApUUU&2nAaqBIwJG3aO&|3S5Lq;&kZ@6<~UbWxIm`$UU`4Kg_rZPiKREZufw^|%I zqvw@Km&~t-Je?gWd3@;T?t=Tjjf`jX3byi-DIPg>vTK%-Vo&qI40CgH`JTkx1!cw? zn}XLotvE>_1vU4mcD^$uG_rx#66IXl`O~8w5lzE*-cboSoJ7}E4A_6AfGey^QLHW9X7`xlo&t? zexq0N93^{%{M8j&KeR_%#cKQyOnx;8|Rx9N61$ z3I8=-z}8{aIWB&?26W$K^M&g_b5 zFA9c$(rCIQT(`N&QC<;t&z1g&QtFqM&oN@V5X;T>=vJ7ecWGXr&t2WTN`@*Z1Feo& z8c;k&uM(_XGPXDF+z-T!&tt&~cB?d=?B@I`<*)H^C7fe65N5DOPTdbraIc6SB++c3 zXx0D@zDAk>Js+^?cG<>CFq*HIqonT4y!ZONCY(h~nV>mX*p>nO0zyCMh3M39)EEa> zJ>xnZBs}-IVdVW8`ES&fx3omyVOe$}ocjRB2YD0}=WD_c35jir5<555tKXRk=O2V1 z4iIx@xbgTQA)5!-m@vOhz}G+)?x9xMZz8eI*tR&SS5noLu%7+JL=g|eyxJiSgxzvLelfHR0sT2WC7s-77v+YSVw)dCcdePsPKD5XaMeig>_h%&qBs$1!4N7X zk;H+iXxCr0d*bi-#6&6%Shz$enn4aY0bp&w!-o`#PdT?3KvU={^NELQ5YBIQ`KXwC z6(OgPkr~&=oV|EdF(50EbY=&pFJ6N`vE!KsA&jY7qVtNM#7G<4@N40X}WVHfPXM@2flM*3vK|k= zlauq8)kg?jFM};8k!Y1z#?4`S#FH|yE3cmB=U2lfN`}=cw|n>QMhgNJRkyTUt$i+# z4u2#KeyLK_8H@0JbaW8|rwgn*li|_m0*X8WqTY<-+`(Gv0j5o`AM&WO7zJ*MIo*(_ ziEQL{F0y|#rgGM2A)82orb68RDmQe1rngL)>u}_AqM8FpswI^M`3reodpq@{RB`LE z;TFXYEu1wd{}%1DWtUDIuUeEG+(O%10)_m_I}`Sh$)AZ+s*YVHxAvCpT4d9CKTRJR zLp#!0cI~uud{{BqLM$HcAkJ>F+l*50 zAM=Txw|mGG6^URXyrK4DH;3?-Fa4IT!0d+0o``N(>^gT_HG-xgJB11jZM?TQ1hs4I zjSHu=J5oQd$Z%(sNKdT$WNdo=wmk+rSFPvft-;S2<=aA3J?;DlP_lTT*T71dsa+$Q{1LhP60~xj+VfuhI#p`%;BuU@*=YO3|w#;zLe*9;nw5ANe zz3@L#vy-(gn()>_6_OHxHQh@RnN=g3k8Jf>{zJc?Q>SWfV)gUY7vF^>Hh*^t9sE%& zes34W%6J;9w#*OX_xT9_K9P-c^|#A{jm|fe zA!6=^UP1_puGi{9LZdlSgN5~_DC}2C+?~Mwkris~w6+ctK{5qXT~}|4h(1ogqH>?- zntx%EX;3`>nl9V#qP#!zO>!~9-ZA~vW!;ftOh2~5kk&=(rK``o*|#|=aQvzDF`t=m zcIV9ZKehHF(vx5v4S6NC{+;!vEQBI@9zBfs*}(=SSi!>3e_iOOy}zj5$j7Q$lAd!K zrL_U0OgGqjpG)ta)5%U+(Kd{po?I}mNlytq>-y{V+$s(8ZsJkTBO=)~+BUQ@e>nFb zFYRJTcX)|@Hyko8UMmtRnz2qV6 zp4p*z#ac8zK6TEj#f!*@l_O6!(v?Jp@|XP1QVJ@GB=FbTn79*0eU5bG2d+oA&5lMf z0@|DcN3ZVcI_Jl+Sp!KLmqTD4wAWZKG#G;EATVKIW)|6>7tqX)5x@Q&AFnrNRFl~*O@}D0JALi%lh?(H`U5a3_-HYSOA)~}P?Q+J z&9`=a%up>Adzh7;efotcCnq&I$L+N{(kB3HKv@)g|n5D1N=?1zYaTmY^-$ zc3y!gW4j?zQBeUUiv*z(#3{zc`5__!w4&BR<3#@%@p1PH9ln z9*}Pzt$&iC7rhn2(v@PCK@E+-IGPRaC;md21f=3V(%v8tuZG41hs_xWLk{$EZd$=t z-UCx;GZNUAXB~&B$>_QIaXz>2+Og$PwYX^1yADI6n+iHsoGN?!&iSl8dNynh4ruSl zc@cU{rxf@V2zj9gemY67XMIP<0^P4!7hN z=KqY^-~B|A+>up*oC-tF&6dTyQawzfzRB9um60fFj& zQ;I~OC5WD<9{u;gX(QkIze6z3F;+3BUP5i*k4yRy1_};rLR2~EhJg$8T-Rw4yF@6+ z}P2iX4h*mDPsW)N}sjvBZD#Dwy!pG<)ABZTGU2M`H@Hn0mx^Vp56B(k!y z5Nx)A!NF%Vtuj5dP~uw-75ICZk58;M?7I|fWcM`rfM#VPTKy6lk}$?)@!dIQ4YOs8 z^jJ)U?ZD5v)y4K)_v~7v-iio%O1yVJjGzu{+>z1R(v15Xg@9%v=H4Gn%>BTM&o*l~ zie`|W(@;^d6`?iUJy>0n@|}K()uWOxkX?mX`9oX~0}WtM1E0gBLa*))b0_Bh*G?g` zc|_Ei906VU#QP?AbU&OSl6QcUt&EqYez=o92ncwAr-sC$WdZc1ATXtoYz`(>9zaGYlhFAdH&)UlO1FvB-o@@g`q83{d~KHhK6RH?u0bQ zKhfnDd_WEEuMv4quN8H(cu*2d^n66f86sNki!gO=F8^|cne7`E{!(+@l&Z^SiVBf<#!AA*sss{%|bTz z>|>4yCzfz8;;@*!h{jXgi~M~~Lv!;JM1Nl3Xz09ui=z=At|9dc#r7bk?CSGz1XUml zid|)q9{uM<0g0I0JB!|R=%MV;mpTuibs{b~KF;Ztry7-eU@J6Wi{4VPEnBv9SYz(l zN>BjGFGaa1i1ua`Z?9+TXer{-;>=PVWA#7$%cK`*U1* z0ogYiBzBlsH+rlaX^9H0AGYQT)GSEXiSz#0f+3h1$M>_M-L0^zl34I;4>>Fpf_-br z2!I+5>+dU@BhyAa&Z=}8H7#uwRt`>hKmI^u6%(zgVAR+;m;u(=2pGF~ea{`jaE7rj z(up}wNo>h^^)TvGB6KgEM!0e~P*`=0LUK25V7{{-eHoDUw2)Anl;4Op>IHo53~eDq zR1&*2fLJh3o>7zLD=$Wj4y$GWh!S(*kUk;Ax3rsCSX_i>PK@x>K9*CaOIAikbMj~Q zJ#Z0o#>0mWy~BL*wJ2Fq;&1=B4OOl!k;{0rpHBhognZnzS*U-B2~0+K9| z3kZKjT`ThzLvg^uldhv;`N}_r#{aX-M*^vO+{D=US7P=v?P?|VJVJk8Uxd*<0Zs=e z9BE09tk2(jTo!u9o0K45d4_*3J{O~-$ZYuH;=%O-TN&#gvr-{b2ux;(QMD9~GTT(K z?UeAK;bK}cMzX8jN4p%$W@eiEr}PxfKvl!r36S_X$;Kvc7LTrh+m%7_d24V%?CR3G z!Z)UA6la+J7tNs0ef=CQloiLZPjZv^{!&qd*D=+)FYh`+1Gb6lAt52eAP1J{nvd{7 zpqc}4ov`!p7KT^s+KE{D@$g3HQaYe_vBVh7luqkV&rDB$*S;h<{FvB#9}?O2l$MqfQDV&X=;*}MZy-O|k2f%Y zVqnD5J&kWd@gb8P3MGDDcJ)2TI;UQ-mTX|KBZ0k`yZ4Zjn?PtH6hw%D04YfP!(<_z z0eoq(tIzV2@~K@XyUr5IWsWtr#S_kJsyy?g3IEK6jOZa6j`-Du3=Ie5RHRpfY1!|B zcHkpG8b=Z;a!(2Pm1B)XTqf&aeB^c#hRa*S%2GEj$>D#-GL~*bdm>6lcTpsit&#DZ z{QOUV8<;aYa^%RIx?#s-g#D4%AaM9XHe_e0!R4*33(;-NzT!mX4`3l)+koT{2ogTw zQf?XEBcF8~sfgudC(;C4Vz{NBhIp&YL?wU!%@GnpdeHTO>{W*+Xf4mhWQWVfyqf;%&-(fh1Tp0w(T@aS1$>tznV6Vx>GZ$~ zO`+ubY))X7mEm7ggZ;Ro1har|IsEQM%mkouetP&4gsk_?PNq4c?MbdFLJ+|)#TIP8 z&`_$))zi;;^u>uVG;&`Ew&L68f4Go>jv_TQ+|`kVNCbqewUa~i%mPH?rq=(69O8c( zXKd0Z66iR9Z5NVM!z6sX*J+*y*s9c8R+H0)NC`m+U3>uQcEPGs6~V z?t@V`Vr~U5FF0`c@K{1cvs^qAif6LJ*1%giF0DcidXC-<0q1%D(Ek5i!yZg55;+&_ zVxm6gG$3aKBZFvMsJb8Ye6;kLz9Wu^GBIp*7~x@r!P(vQm{hkB?VOzOZky}MS4SgDC4Zp=IBEE>YrHuCyFjtgVb6bVz;+lp+m3nv zZCkfGE<`7Uc?UI*z-b*dF! zsGK6Jz~Bg3RiO4_?#_Gh>r=0<$S@y}NBx4r*R0!@?dBNd7mk^*Xt3nGMH4vj@ zFnm#d^9u^lwYLcg2_fn_uWtHf^(m7bq~eahBm;F(k3rm$#~R!FS5Ff6ubK@m3RU?Y z;;67an%m8+td!uQBQgDiO{Kp`$7e~~?>u6&-cTN5tsy>F)Yh_JYd9`_lX%|}S{HD3 zeY^yc9>mx>zMlKa3lcP5sHwY2I7a=e+TXgr<$$5CRV&oDqgGQ~N;P6tp({^y)Pvc*nEjLYgd1vC4> zt&HNH^6bwp?)2ADy{5JIze9Pf#HoaCkepK9D+EJZ0DZTl{g;j2KJ7*@TJ(S6A z8`I(*LK%NPFMRX$yAMPu1$XXYbaban*=+FA!oObw3*|UbQz?(g=Wf`c_~eaIA=RU+ zOy^xVu;&h;l=y6JdEFwK{q|k*XKf^p z1m1g~S<%(J1Pf;G9P%{FZ)lESVRLEEatYvblSofErxDse9xvUEO${Hw*+ zHfrpQ5}Bg}oj5@Dm0RxUyz(X*wd64A{|r~q>{0Qaj@n%Gwjjy{(qz0ho7u)4hLYMC zn~=u}KgzLj3t`Tj8y$>Cx;}(qnBtv%<<7!GY#aRlTyi)qJ-t6#FmNp53M?J^h%=!L zpjKSIsutm64gO zB%6$kBxF=ZR-#ZD*)t>|DvBgYsEq9Gew=;2_wRS#_i-P`{pbD1bsbk%@qWEuuk&@D z&*x)3nx*Zipg_r}uJc}|)#&)U3lLzk-) zEZ}=nfO*afok|t{cN5&718zZ~as#g>uqhP$`!8@{%fdsPlyquX38+LvfYvtDCrIGr zw(Ol3TA5w5My+dQ6`q?;s%^AgAsG~7jr%JGOLm3_{5y&MCgSs1|1(FUB53~{1C9dT z8zL_{_req>;fh}+9+&;!wp}lNzOMcBQU7^Mfz{K+hLfp1``eY2cVQ=Zhjrv|uVb!bU@b_Hn>OE{{Rnel!? zTh!t{(xSruYz|@@o+800LAj0+lw|4ZDRpd;u6{ue%ItQl9j$GSVtEB!Tb8ZPl{kso zbDW&Ok+SiP1^=CgvcW8W|pUcpUU)5;?%g?2RNq^@o_8&BW_MC40`aZ-P;kuA#_w?V< zftrcHW*5pAz4S)*LRIh3-?-^Pl^^Yc!>)<9- zcL!HPghBehsc@4eMX14v`>zwtZl&xEk~ z@g{1$H$VhUkas!=TS7h`ux5rht>Iv`o;xQvHrrnS(EcwbYgkf{ z5eE+mkYi~ag7c`w>bVQfHFBo~E*5d`qmijX~3J*Sm%lL;dkjO?+!ja{T%1%(dSC*|ezdrlzL~-0! zg`IdEQny3l=gs09{ z_mrhr=E6xJq2E=Zu#S6K=fB>vs=J#y-F3sDgl9mxvQiXrHClwMK^3GW7**cLltF}H zfAEe&n>;x;XTF*Gq~7Eljd{yYXs z7B~s8Oi=__5HwI*g$xv1gf+Jxbz~ALIJZ3U_vxX}ZMJU=K-{B^*aHPSVapqIpEL4g zh1|OJW32b2mb2~CQ4NhUs|{MF2M!uT>O3zbm%0i}(hKk(bY9DI{AKkmm2j7u9={U* zC~HvEi36aU5v-yO*9^F2JDrgLgF9kLCA{8{iO`8%UJ;{1cjX^dHXv$gEu5$laDHY*M%Qq`VXrYIS9$H_{b7@<`vy z_sHzWK0Warf{T)d6Jm0?#$rW39fM`k8Xf0vg_SEalSeFZAI@;(PXT@ymy$pkya0fK zgc#yYahir+g&s{evI|2200E6lhgOB8m8Bbki(J2TFHyEYMSao6<}{*Kbn`6KBRobx zmfVBX5WfK><}Kh=xxm$qIgO~?E}gUdIMcB*saGzWdw!`wKlLa?O?=0W9jk5T^;0Zc zp2@XA9l!m-eY+MN=g)WMG`oA_ zU&c)$xHARUFrI zpo2EC&p_jCKKL#Pp*&$YW5fAXIgVW&tV|2pHfOnbYqOyn(X=P>z5UjC4LspQ9nc1W60;JObYX+Wqa=VnLd-A~5 z-|eAElxJwJ~TCJ9mv}`D&fuMGC_SO$AY#l ztNW2-Lcp+>sd3J2%U-ggqkI&;K-FP+rdYnsjacCSc={|z|^3eP5D&?H~J@J zKx4~1Ni5+7KBX$Y%h_oooe5_b!#2CO(k4`@R1{FC?t@TCDG7za>W{)6}%`1 z!L)=G1O*3I*VOpp**X9mY~j!h{4fGJFT}Y_h%2Gny7x6$a_0Qc0LM`+5h_CW+&Oh@ zJOoMYUMZ6FR!x+osZ6?Pbop{F<5rgBZgZ0da{P;BGrr2yl*N&rr9als8lxUO4qRt! z!dx6DUgj3^?9NLq>%oloF|8TbB%o6k>n+nP*~fS6eyC&m!NLqy_PF4-0)rFsdDgc^ z??nbRI~sRvTqEj~f{iCHN6pVC^Vs#QbC0??S=e6v5-{2EIP+x5xWC1Pq;-8IFZ-bQ z3A(-I+e%!6NAWxSmSRNDl6={@hmE%&!@;Xc;&ZTl@B(VV=G*)2n=}-6E(_CH1;eN& z(HL)pPz*biMzSm|qLC**&un<-DdaUfBcCedKr=?7GgFYELEa?rhaP#|uqezT?Up&2{zk zG)iZs;Plp1ek!&Q>5u=dQEtZ0@nx((EZZiJGnF$- z6nPO+1$>h>2fUtk%TJ5b<}8c{@v4k=u;08PXCZ30{kPc}Q-lz6Zm7g6RH1OBQn;>>OJ)Iw#utx~Wxw}t4 z8X8vO^#gQM2M>qjyekqotFU0uU(t4#@RvziBBdQj!gpW}MAi_z<00^=QL2fW&nkONya0rV;0c2WN}poWo}ivvn%){<}<5U^7k{nCf(k8Z&ox@IAI{ZhRy&!wjgi)E%G3N5UY^IJ^3 zF3Vjt-H8Qv+c4Yf#;4*Pn_kE6V(k-WMjsgWPY>)ZT$-7UgQt>F$`j{zDt%{55len z*6TP^M)t!Nj9|`<0re4~c|*q{k~DyrkyV6`Oh!%>r-zrH;vN_m{F8UHNqM4p8mGK_ zdhSsC{xZn;`SB70i}~%|x~ReFSung}Es>pd>|OGVx2hy!XIXNNco`4exhZq%>bcMP zW;=eHpJ@Xon08D`b#Y+*`P=Su!Uqm~Yfp1Lmdh^gW*2s+((eS9k*)9Zf~H$(r}?(B zPgZ?;CEJyKKIGb@weF@-r#*v*xO*K3t6P0_bMKtVA`^UMjCqOSn#-z7bt%?le*Di{VXfpx^)+! zhajdZ5~uefD>v5>(b%*}MEn{wKjZNhJniR~ww&iB^~hEG9^(j!WF|TjuA?=3WGEsD=zC@Sr|^ z2i)eyFM;?^-QYzbU*f6?w9v2(OILUn>ue*MaP&$uSGq4nfjB{ohZ*`wTHaJC=4GP7 zLy!PO8{e_$nU`NVli(g~D{Y1LCN`L8aK5zgOkysUA{DKn@^a(qQRoyN!J`tZ4=h>5 z#n>b{C}e5U>O|x6EPI8U^Pq^ssvQyArFFW?Xc6*jTscYeVN7vw%_jD_mdcH+U3;}` z9)3s6-D91-bt^+AB>VU0{;~rHMb22PtR(sZEqWJF0q8)+*EcXEB<-Qe4g|`5J9ECI!p$Jl|dINdN1rS{lJ%x9zQY1$lj4|!gm1%wLPWOE#{cx>+d&}1CzSuNFHqt*)PB!ri$Xe_0Ut?fqk z5((9u>kE^z`1CBPSrVMa@XL}J__5`Z-W>7qx)M_AIkI-AyZ*9T-P?1|-oy$tOf<8% zh0)8)zy0jAx$E+^V+#?-&PV?d6Pp;{wPnvSZ1o#PzMdXz=^Kc7N8mBoOfF%Q#6$RJ z_PkI|5ADV28d_NN>jxKJx_51(LUzzWFj*DA*L@)Q21gp-(n^D@ooGK_7$u*g#4J?OAZY6qB<~@6!v^0kb{yS_Ouyw-=^9G%PQ$VePygaH}Lh?U* z{+!$Kr=O<)r{{#LEy{6x3Q<{F59qi`-I#^s2Ai(z0PD=kK}70-#)C_56BASTAls9( zS;lC_CVzblfrMhGt0(YZLj46NTS#3@#(OuvVq1D|_|GPZ0cGv%jyt@^Up}*LI@q}~ zKPMRs;lH1MSsxyoUqFD>+DFjWQD}9Buk^IDUv+@57s8*R?vj_&UB6KiLp^xsObOf` zgKQJfrX54*3JnaP8?0vN|evcDr#z~X9Wd(*lf`w z^$rfs=J37V!jtd1vP(FlrwR-u#lkBFl%l|ea&eT;z3{qScXP9T3AK-fS7HaIM3}z3 zhf|MQb?Yr6_i`^%Jw#QBc5?Ag;FG|>b%@qHd{~R0f?g#OH@-E`QgbWx zl|LM@j2oe1fC}=_v`9uqkU-920_D!=%JC!SjrYbj%-5#eG;LW@y-efQGb8Gi;+W#ReOn( z6fq+4`-dpdH+Hz3cXwx#-*Jm%#=x$LENZ5>V@|;UtDmDxtqbEs+9$W5AYHy*mZK5T z*}G>za4YK^O6C-evCe(k%!_;}E_5XT-rcV$#Q@3WE2j5?jtg6UJ@{Ja9Ad96V4u%> zss9zgtr^VI$PU#v@4==|lrYe+m=g0@S=kqGm1{P#y@vfee}V!r_yg4B;h!bf$~B5n zsTEtDzI7|~bJ-P|OHYnlO9hsm<@d1uS+=!oEi**PQ-}DCjBHLWiO_lsTps?@aN$ch z`i^(0^)0%3U1Q(>QX@^K8U+M2SNlOPuX%Ug=J@q7E+|_%J-t!bqa58s@O3dO9U)7smrs#?~GXJ%I{`lC;yDNtd zt89Pw*Jyi*V?U3x&;>5*+g|hh2t6}istPnk=QaG|+Nc6MD~p-pVR*|VSfB#qs$Xfj zOHun;B!qC8{>k(Ehq>+mcmz*#exPXdYx&0=ajS?|9>VT?pW!9%y9_PBGxX198)QtB zqH&Ztc@kM0A3u9S4uG!G5=-K{s7fjwGo>ON9Vv>uKH09G3xAcZdR82qoKEKrFKv;6 zJrFjwye`(m7T!q9!g*f}1r+F!XK>CXNO?8mCg%_1T)35PULALqs7vyy<%inR1PqTE z-MNV$p8@=K*i3_dl(r4jeRVzF{77ezEK-$0j$YR4`)Vr7oe$ z^&9!crmAlq+pt6Ky2Wn9x7UAZqcd+YqvS1II=ad2+C|x}x(}A^_e1J8GBdFRr=;+r z2UNZq2i2E4gnORzL;R3p!~#k{@j_yPIz@=|1mU1?-%X$xBa@PV_c60;LM8~kkLSvg zGZZGW=sG{4ipObX3g0;Ah7rhJ%m_(1HVJ0oAVl9KmDTg>FYym{I;#%f9$z$$8Xa0UF=Ko_1oZ{ zB9ABtA;^{tF90X<$Y_Bxf0H~lxtTz5AK48#Y-ibFKV8Xz^m(NRR41L}w;uoKP-Tw8 z&1*S)yjiGp+^xF2$=ZImmfvfJH41y#!~&hGs_teQgueakI5uCzS<;cU6O$m===l7; z(&Za`dSSP9;^u~j7Dd70MUIgs_lG|Xw8v8=oewGabG{Z1R3<`)K{MX69e8t&a z+^h@=2r7nf9yth*EmH@213xLa0gQ5svAfDII0x1N)+k>T9+uEvb&iW7=-atq~1y&@D8c@shTo2Ue zO1Q!Q<{?0@ssw}@0{%3}!&TC|G4_az5D3NGfOHRtCJ)+wm)(VjgD~cxh&?(&G-_w# zi?aWjE_Of1@rox4y6ciHjzI*_vQLCjWM$pix0efD_;4EUatVYgZ6#T`zLAEMkIKV$&Cb6r2 zUHL3_ee7Wy&VyZ`g#O(Pm|)3>jW|9QOXcJa#yO|reltt zrNs3&zf>2Q>(F)W!+5BYzn+kiS;?Q^@aNBsuUMvS-g7~H=#YK%i>aT7;`=sUD3up5 zD2^k46MO%`9=SJKYM$|Bvgu6)`YlmeqKN{-Yc^`W=)d}JXvE?!CBd3)IqFtNu4I@t z4n4FHwP;RM!mJ;qy1nPN@S1GeW!-ELZ2e^8n-_gC`8Fbk9*?hI8_HM`-*>h=`JiQ_ zyghuKqy`DWHJ|uT7o3)Ri@$gnD86M6G5+=;@{i8oUc|Sv<qw(Co$#rPL>^!B`*VSts@8)sLDZP7XST7V!F*!@@ z3ZY-cgkV^{0Iae@Zp~~7Qf~6$2m1xI)7H?iD@W!O@?!K<$sVFvVTSb2I5LqRaYlBPal*Yh_cmA313hVW#DkgudN*qVTr+v}|AE+E2#*{_XwP7;~zi(agM_L26ODY84HM8uD72+J<(er%;buR*wndKadiz z2}1V*(`rq!uleg}%{9SGIj5wYcJhsp&~=sRb1br*P`0>hf(eC82^>QmqJtpDgjx&S z5SibD0V-UG)yKZvhIB%VMavwGz;qZDjA8lu^(z`#Xo^{t?(RMT*M`OWf_+zpJyVCh zljenlwO#sW?tYyT%r$LbMyrxdWHeAmr79t+=o^kbygxGKS#(4)M~rv>d(sMeEXZJz zWc(?Fr2Q>&#rSXU#CGKlrYxsJd=3{USk8-k-A+qOBMJyVJcx`4xb&csR*o?Z;^%Hd zhSUKxrKg~<+5zkrHU*LkMpB<}epuCTR;o%Z$=X%2-nL$DH>u4~M!wz60-IFjfoA4q zzm0ekG?w&_Sh^)6d zQBfB8Z(4f*YN25us5NO2MjiYZ1xUgqaW|l%*u=)Bf=?rP&IrEXO@Wuq7z!#9yTRm@ zoo*1?DWGQmYa9EPhKF@iuWf8Gkg^`L%zTLg0rQ%}Gn?SjM6dY*aM#M@P3d*v$7<{A z!H&{^vB2mq!ihlwg#jPf@|QAA_5{n6xn|FPEv;2)GJ5;osORNWE?-~1gD{pInpfs| zA%#>KY#Eu;&~`vNQU!GwBGB5M#bg3=HZvn#?mt%&(BsX!)hN(6pfmCr{wKXKYfMvztu;3)`f$G|z{lpopYH+${>Iq5_d#DblpV@-RzNNr0GV#u=3m%Vx0 zVDj4V*?~)$9zD)XJT*1hCGcpi6Z{U6^OxaT~a7 z&;GxUTdB2`+zya>qq8%^nYd%MvD#jc8&8T#th{92#NL$W*O46bUJp_)m~bAI9-MjjW4$9ntvd?BbrMTNnz|EKd0sU7F7K|xm4rg6L+?KYWw z(}cjX#~rQ_`qrCf-k(#R>#B z1Dq#;z=#2Vgg^vhuz`#WIowl*31=|}%*oK8(0PRl2K0xRp*$}na86c1?x2Y@Lw16A z9X6gH6YB25P;NDCKV(LaBKaab6+>3CFav}p?}oc>1Js+aXcOO1cB6i(B9lkVjCxg7 z)rXuO??#>Mv56m_F;1Y(`P7A7V`)`BXNpNJl5{PUzDvx0*BajumtcbU=T+Lyp$6r9od(^<^}yMTl?I-z2@O2~ z#w>-z&*|zugHHENv_K7DkRq?CgA#RTYK3C(PA>4+KY#uQz;3AHBem?yVsHhV!Qnk+ z7_I1w>_0_K+_XACV9@E*h~ATz37izfQAO0yXP*?gP6-wi6p+3Sl1gK9^Yqd22x7k* z?95_4aiS`ZeU|l#&GGbKyWVr4i%DkkE%aIvgp17_Y3CW4iD`=ZQ0X1s1q6odH`#{A z(cz|GznL9@uvxD}$oAqzE+9L^iUCx|BWB`Fna4sjveZKX@@nSAZIW6Nj{oAXp(9l{ z_*k)EZ(LJz|9X;Vx+i-7f5nn=sy$h&hfM0|kvD_!!qys7FP*sCf{6h3f9di;wuA44 zxkh zU*N|XcnYdIICSn~+5Rfo%-t4;W0#zOz_lS7{~rV%C$NC#UMie7WU;@W$&u5zmHlUP z$W(K=`z;i7~RR~+;|31VxzIeh^}&`bDvHc9tb z&GeSBAAfl%s7ZFphm0@rXFlz7Mtj9i0e&TuNY0^VQOp-70K?k?oVB`eN)(1Y~571gwcs`f0f}#BifdFZABzgr6RxFYv)b)hGf`Rl@8X1`M8r?qO&V2EEAK*N@Rzmn7w| zUN_YRo@7&mP^08h&vp+S)j;erL<;0{z|SJlKo;;TLXY@y|L28N*M+ZvmC^D%P6Fsm z(@?1&w*6{=sw@05y3rb7MC9;*zyul1#9a(<3h$bDH z{ksC1@{jDG3EWQW{k;TJvb{lE0Eh1fPe7c3B|Et#1tBVcf|S_jFnk4IUDBn-XfmrE za3r}**<)P3(yyF(p(unm>pfU#=pK`?%__e7->ye2A_2r$6Q_TM1`Jell0qm(er!^3 z7bQwBm;hml2Pa^1`SR1z2tO`>^;p|vOZ)q`b@})dhDrhZ`S%FU;1To?<0;OPD(p&+ z4ND5JP=|B@_u(;BH8w)|aemBexZ6cn>*LDWu^GyX(GVWG#}0oIS?`KXJ&MI=Wg-zzZ_c*G;{n(y}kM^CR=r}Eo}xUPf> zk9JIqiQA17%_KOE8qC@?OAL@C6AVYXKAhii5qiYm-=v>KE*T*@FMF`m&hSg*U6BrjT(&u z`S;Jye> zaB%S0uO~S?hYxQ?*-J_er@w)Lg0)+vGwm@;l#!YF24;D1AnPhlHYQ<@zl;wYfHdS9 zkSrOEqkIDGlQcEslPY0 z1m&PjC=}YywDkKK%^jMd;V5)ffv_G7}i%Uz~ zQA#A++i+W0;9!O@C6z^4Fv=LGHOaJt%Qfxy_jeVF>gr6;dal2x5^(DlJrQ-nsB{8l z$;C^T@DG@nBo3|d)-rK%bE|k(am`s% zo=o-a6pheb;fh>QO3zVkekpU?2JvpO5ObN|4+k;4bgS`MNOwYdHwO+_1uQVY>{oH; zlegXQm3}ObqmTmx`z`oF5oM{>QJWO=8W|mb->XWI7!8>#SA=l&{>c1nT`erXfQ4jTUng%u|UO~=QMXF@fgX!wqKfeDl9Jk zReW@E74j{5AzH@I6<+_#gBx)GkR`b8^^g-53vn>DD*Np7PTlsVu~8U*fn@HBSd7I& z8_Oub;S`mWsQ)H^f@UF`qE%$;>2igZvO+QYJRGTdAo#A>Uy}Y!V)V#9BK4 zRUij_RrpT2x*o&SA!I=KK{tm-f1#t6m&etTTxlIVpGe;KasKMEmW(iPvLD>>hmf884AwbD!e#usolg!>c9!u(DM2GoZ%}%j36^+#MeUQPP6b&Regz?4SzAkE zTRz8!xvG${XZ`!3J;L}Q9LdxG!||)vc<(R5(Q$$=l6%)K8ocBdNbG=MFcb$r=6y($ z?>4W~cicPGS;Y41Ex6l^0Utw_(2DQIy=BW5qA4&vxC1c}G)OKaj{x>|2p(_$dreKq zB}OJDhN1g3L8id=qjnFoLrzj&jf-*&!)9SdusI-rbDv3Xp&uBTpdC76);Mb1RA5ks+Ej-l;J-1%n|gmgb8TrYznh z@;!x3@=dwViS=eUTQfrFfNlsl6VvOGRmmjKdt3AP$`cg?*nTdmAV}@2Re0hf3(&dW~!xIr1`P^~f z%#VSA6rAUH;mAaVj{aRduC&;?CZjPq3eWKwZY7d49A|1a2E1me?AE#q?mX2 z?sY%_eV#mdLT9%(o53j1pb`or^q~PGGu7Inc)cvwBlOhExWP{ZzPOC>*kOsWAN z+&;WOn6MKJza=cY)X~w=WVd1}bE9WrUq(C?7?=#dQWIDQb4(|T_z z>UTIASafuFcrsbm`Y=kQ;%d;LZ%5KM1jTp<#J3TIM?-@dMT}2rsW{NdlY&vnC>stO z{J!E%KCEIXh{G5obg?7sy?hg16yhcWFae&30oy4-kjXooYO>N? zaYc6j9V`|6b`bHa;5xy=2->`PGl>DlPriQpRu=A|14h+Yo2%^%&-3tT7;QTczIC*8 zVk0U8cmP&u>&eN{96WSLT|;9PjE#^{*EBbuxtX?@2oW0=7nxk6CK!c=(-)rvV3jP& zz{A*j+KA(cXfuH{*~3?tn$B4dk-wUrUS@PlQxihlhrbOB+yqQf^Y!a8=N^-D=XQ85 z&ykIh)JS+(@`;ijSh0(3t097#bTFnUPOd95xDAM~Z^hU|{Z3+7@s$ya@59t#KeNOXGW23zK6}QPQ$8<< zMF)1h2vrJ`_IhgR{~8+mxzILYF&2Kqy0!u=BUq-k~BnxsB) zR@MF1_zR88=L*(!>Fif{P+${Y=y4oz%L&CQh;Geva)E9w6z#7J76TGVU|4tg)yK>f z?um_dH5sTu2=nt{Y&WYmrKdzc|9gmibbKgs_VCYry7%vWt89^~X==*qT%h}RjNuL9 zIdWtRjxmh3SHN9`4Sr6g9~;7|?G$Ds7)D}YNDEMn_bCtWOYE|@?J4zP;Qi{Ie{V-y z+wID#s-!oI*bY7+)OGR7KTUjTdWWy6CZx#+bh~%j81Ud_B)>Bja4xC431JAM(cNuXHDDGr7 zH8p+QhCKo6WbKSj>4BqWAO;F=i{3B3*u(H3@fVxPlE?E&sYorU(FLPJ$!^zVMwx7T zaY)r-%X{3(7t?4D860K=?657H+KP@R5Sx!NIyrRCzSz}#rFeK;jb^t6Bp|_jfDDyB zZ1rIs)W&vKulgb9#`NGl!7z=CSAcUESy<>G-p16uhd42D^9$;}xH2Hnl?5k1N-8;M z7M`IR8_*kh`&I?^bl&;C+5?%|%5L3lURCvdJO>`R9rt@_75G{xOW1mn(O_{(H^1e5 z-RP0hUp<@pQc}Y2-3x-uhiu5?(fVPOFzty`r)ZZ)SC$ztf*Me>JhoQMcYS&-?)!IR z_rJB<29Xc~$=Z5QA6ScP;3D>xNqYCV3wt!4FfIOXM7UIUbZkSF;a?!XGFrZX1jPa} z2oYr)3=%=edbjEbPiTTsf-78+sL(@g6mGMTt{Ro&MjWkBf)M7TrHmfG9y$wZr2el7 zlD&c8JF6yV05OXLQY%%~Ic00`ad>7#M6EaRrr!Z5Z4%f~tlSf1lY!GqOH1oL zwW7+S$5;sb0J_IVZ7+oM3+Tz6#J@)IHa1c+ij7-wUrVGoHIy$W(P-o4xM*yA0{|%R z-o5ldWwaY(aE3sZR|(%f5X)!z`EocHAV7M*^j7( zc0dqlxoVM2f@JOOcu*#Q7|1##XA`Jn-hKNv0M8<89c^g3$j3M2pCYTQ^lu&O^_gzx z@cZ|JG1iFuB*GwC49wCrXww)6ncKE)xG$1(xF_qD6u0mJ>6S63XHHjT)IB9PzF|J# zsOwc)VI|Rd)noYiK!o%SytRGZ9n{2GiXEHxzyU^_;LzZ`!hl1P%Mbb7*5>Bs*G)~e zfIP`Qi5_9~+O^aa@LS1x?Ze&9J^o1XMy2SFI;1b=f@c*jUVGqeb2CZ`QO2!X*B}+< zHBO||)Qc$o3K7-_wb+w4CCK7N8aM~Q3HU0R5YX$>BDp}1qD?1@S7m=Qe)s_LPq5G} zE-wIFW@KcfAQa(a+1%uNReOLTP#yObMVkP|LDS&}11gk^+Lq-w4hXbkfze=k1($>J z^751>HnNJ)WAmzgU|UX$YJYLOaX*n(F3^Tblj)9=e|9h>j7&`hWT3;MwyF~9 zkiQN5iClQbP&#xG?3M{5x|qiaWkhxAJU0o+#LSe4~*=K7ca(8V<9?no28{C zQOi-d@C-TK$Ee731BiYw+7T}k?K%bqX!!@gGwQ@EpPqDJl-(~aC+Cl!Aj4yk@S}eA zEFXEl!l6(>(QB_G5$wX*1Mn%~aPs1( zzG*~llWPeMrsICKv|wy)y$2hmpGJmOe`JH{D(_jmhMaCHt|ACAVg}_-4iPe<(5efO z4!f{v>=~b!(6+qbF%?DO!YZ0FXaoR|G*3@{Dc+W>IXXHz*)wNuBiI0q6&=MG2R+Li zl%RZ+Kp={lX_&in4zDk<@oVcL{0&o`qw$X?C$CaTBXz-=4Zb?f?bu^*!aqqvyrUL{ z5uid?)<8;&^d&qsKYSprUn32JMdZj<->)ec1!(a?Y;3I7@6UX$=bo*PJ--g}I&_{q z`}Z?YNX{sl9m^l6t2rs(!2V?Bp&#ev=U>}b|0L{n=dk>$@2LzK{G`0!|4H=NI?^b#H*2reSJGuG>e`ij8rO{EhpY){Pz!uX7uUgd4 zBch@=BO@b!%~N?}q1_klxSaLj+J-%ZZ^G-JQd-JJv4cGCM}I#_8?@T@jC24*{^0MziXp+B~lbatMx%3`&-bV)mF7Xz%DR20;dRzvtN zMw!P>5AMgtR(}3`ZeOBChOCUtDjAvi%97LiiVzfn*2X4mA;ITu<#C?VV~wCD^mOQ6 zo=Es&^YJSwDbbU}h2WG-e)^OikfeH=RG8Zfynp}&*l;icRV4>!`O>uh$7!4@M(|kT zYe-A@dGMsfAKxw))o^t>w=LMMc-zd9C);h65o0Dgc9`DbZhtZGw7ox-0n; z-B*2EKJs`(m~)0+d@tSrq*qnpbIC=Zj2E9cG@Cc`<4I1r3>5w-QUbsNa)Dn(>w~V~ zv7jp85>);-086Z!lh zfl84M(x7mx45g6Ux3?k)Sa0IEm{<^g6SkY|81##QU`g{w8nHpPJ~KK=+7Io{8biPy zwbcNTJ~-L#ykF7zT+gubt6}kzUuIg3x|3{&4K5#ZO6xSNypX=kXTa)47xYRR<=Hvw zZnW200{|7a!q<|FGwaQ79qh*VPJGZ5?Ec|UR5y*9PS;6=!o$TSO-9yd4&!bxF$c*a zP7wba6K_9C;ylrg_DN_4Iph}_8j6XE1&lHlSE-~1&r3ioS62>sD06<($22KwZbxJSSIXK*7^Zz`y#zJG#N?z_e{NphX3Xng zr1MXHV|^zwlGmyudmj;*MK3>{`9XTy>$|?GPi`1 z-R)?>$X>B~bFg5^IUM96U|lbw{Y25DofdQVuEpZb6>rpaN=izUFJ32>VIRRH>opDz z4j;y80KuW?#mZ!PpMi~5I!UckR(ZYjrGV3(oJlFkcjBXh5?|WL`IoW<)6uAfe*EOH z-2BR1Glhy0dOyFCs0n|9s^Q>MO}K@f*96Lg-TU`W8DQkf}lbN8}9Sns%#=@99@zk(nD+)Z~xgZgC5FAKTze=QShUurlqQeIB4g;zI(?A@S040M?0xK1UeYoj@IvNcP1S28xY|J zpBoJ}C<|;QBp{AKa+c&GM|oy*xc@BcoUb0p=dkJ`4U^3UFCSniCZI{yty@Nt4Gm49Lq8pkc+&U!%cu|CRZ&V~CU`f#Lt5@;@nH$5vujZ--APEe zt#iRc`}cFsE46nU`*-i&Ee(Rs$l5vtv+%Yce5Iq9lc`d@a+2+cP3LCFGimHrB+|fM zqqX~vy@6$Ps}1lJtPg374My>nUeNUR?b9}7oaAXuDUaewQoL~_D>dFtOk_BI{CIxe z+KR!0#O)exVga3)D*N$<4x{95z%_1K-J zme3TC0gD7z#X(cnzDRO5aOM6m+9v@B)SEyh`sC|57GyRe#LO3P1N!h&PV72adj1g+ z%;W|`m9HM(gTz6p#W89eU!3|1t_N}D-UtiFC{#7e1cj0z&gn77v1bY~Y#4^;1KGZO zM=IXMI;qnw53oRSIFsc-s%gr|+T29X+qc1Byt( z)50~Jj2)M>Nyxgo0o?h?_}#mAzX2vA;{gZ~AX0YP)3dyNoKd3EnKI;$a7%(Q6N!2L zB#=v3+gAZo)x`*yI!}B6;c@`%e{5@PYz&W#q(&c1Q7d~;0Hg$)mc>%rv_c)0YUPq= zLb`h6r|miA?VA)dJ!Q@f_376in;Z;HzTv(zXMrV{&c8jnSYZb%D=%mn+)dwhZ+n>a zVVLfN7*AM27)6Rjd_+I$?9730Mhuc&Van7Gog`lmWT7lP z>NdR>v%y24Y&JDB`=0gktIV})BIjNDw`47d$6kB<<9t&4@SBx_*YRSGYw()C3T2(? z*#Px~Yg)Z~Y=OBnD;DPL!h%lm4OQd-Av66p5z>Bco6ehg)!4Wm{baRskH<}5PdQLhHIYzeCpUbGq7u=~Xv$3`2$4^J!P>8yFS9+ZflCJWjgYkGxfDaDB zV_81?J%nHIWr5qcH%Rczd{Tt+pNUh;|MG6a5j@N8C?&MVTzq`;CT=L)grQ7F*IR{l z1MO5jR;_jy*2!N05*cY_Z+9{Wbq-Du*j*{@MVt9_m6VNn7>B&SLAJ=LlG0Low}Q*k ziiwg|k!FdIeS$m7ygL5truG!QMdOowJ=-q0`#?I$i1WZzXd>cl9U|9J+gCq4;j4E3 z{B4lBWa`oN(XyF~R#w4;&_hzU6>lKiogd|eHfaa!^PYUmVUs~UQW5q7!8wq>C7sJ% zFcbr}EDb^n^FX|T{AL;IQV6Pw-kgXX_mL4t2Sh~)<>kGQazjE~d~7H^(aLZ~(hKKd zq~jS`o8OH1UZ3;mPGU+Ci@f>?Nzc#m^!3F;&+Ol^O{F(^{~hHrowfKeU~0X1qV?Jm z>bX02?oa@wAUaGx%5&`72~b}(=-|P?Kh0w;c~K1PjD1O+Kz5i+q5Cjusak`0T5y!-pFSZ~lr@--nJFy3MC*;du`)YR4J z8fDQ22wxxjCOGkR>G*oiFjk)))urGUZOjIXN7x?P!GjPe zVXfZw5A^mXxvtc`eM=AQk_ap?qQ)C_7hq;GoSQ_-TWvfDhn4%%R0rWY5WR65pbMEH z4KpDhM$R&zj?3>KLOYu|-?vKD-2W1MR2(tQZ|~uw4mt z-e!62f=-&|eu0P%uTY#;Ng$%Pi(KALd5HgkI!TgLwtyP?5V|6RO%#R6$Dc~*%~?Q? zafd4cc?iJ1l*wKJMBUHe&!)w3u29bH|K@(opOj{LlD5ry-s2=)uGsI+*NH7Ie&1m(R3 zg^Z|&w6Yi{N&zks2)A;{>l>K~ff}5ef-BQb+(*frgrb3}kn=9Gk=9W@oIeFdj0><5 zQJ~_nd;?5T1rO1kxHx)XS@{$Dfl0ZzxBwaB7pVuMy}A9~{ez)hKDwlh0h$P`~DKqv5zLO;=qLtGbe&LFgYHZAlRB;gpVfqwMc zw{IBhN(mk5MO#bIGF8{1{9ib(;^N~;LK*RHlCc=5XF<~^7hgkzS%vnLEO#hKxPfyJ zZo}8N#!-O!qunt!AC)7ofEvqUGA-c&kp;~RR+i_$0X68c45J3nhgfL}i_fRoyb0Q0 zv8Vxs7#&JsbdKCx_n&_%(%nefvdw6!w?Rr=4GsiFK?r!KU`X*Z$Hj}86=A`Fz?$)N z*Zf(r4Q~hUIr`}whfKhHKYi#ezx*=aF_)~HvH3<1>a>Kz^l4Lj^ljJgv9=b5%M|lU zcan#T4q`|ejW$UJ0q-Ag3Fu8$Y zVI745s4f9(>L8+r7AAe7-$Zd7&A+t$-J!Mu=0HXnydc52rL<^{k(0U;?2X)s6Fzzg zYc+49I#t*wfpB0T9a_H)uuDdH7H}9wrDV4B*1&hOpNMimsQAan#{((cg8T77&kHTL zQdp5)ugr7E(vsA6%Obj(AV=tz7$IRNO$h`>s(sg0$LS$~qC**MWNyw67R3)aI)I+G zky&kxGv8(uowDEOevQQ2K?_Fay~*&t_!l)3Q>#?a zC?(=Ne1VvFM>9V1Wm(~CjM&{$_Bm(A!;eb2K}-Vn|>L;+EsmaBe+kLjCogvLz(?66<9sJLzgDlC0=?=(LL2aupV3eD}n+$^z*6I7iRXiL9^J+!N* z2Ynp;nbkS>NtaxqQuTOR{iQ@#!kkYdvY;1uOFig?BkeL^6WVqWR?rE1gslASI-Ce& zdKEs~XQwxR$kwUoT+n&luh=C}(>Z6acJ}r2$%&RH2E2Dc!|H$*k&s>I15}{&xXVGh z^>pvD^(l)rYiiziDg1t6yTw6lx!9d)$j#ZPr9HIJZNXMCEeS;;4OZ(_HEJH7i>_wPL9z7``B9M=4`ml7s3GuTC{2i zyo=Uc8bkr19iS9~f*kB(#yCnW5Cm(W+JI`CEM`&wU{g;)bM)IDN74p>)6mr>V?-Yr zIUt{a>VO+$JO-^2G68)r6HX+YCFRfNC2g_H$YF-eexpm5h-d;W0x@U-H|x*3;^FAv zKuAw~I0hNfqRAx00JIlR?U#Rjk^0s!VuYKIasy}ndV(yrwK3zYt20mZSW{%M9GA_; zwDe&6P%%Yz(jBti4Y*$1VsAv$!hu9iJpdz5_44V6Udi5Gn56drQ@#j99ojXKwzf7# zR@M+~w1hdud7WvJP5v>aXtCOs`k;K?hHi?~`1o091hU^aW3m}e7ozF`VYp|*QIE;aJVQAJSq%wuY6TVw+~^yU1FjFmJKLd7cL!~-@@)%Wa?A~`WR{%dWSP7x z-FoDt;r83TXU`_+H``yMapI>0qQlbGv$ub4XJ^NV&$4m>eW)=HO))66I}ugjwc`2X z$B&D^HLYB*536fw`QgukEqI>)kkaNQZ!m%gi+hKRBC_ys%mBrP#4B4*(q@zr9Tmk* zj8Ckh0YO2usF2A>VQ9`W#^E&N#NyOmii0KxMI69$5VM&Csip(y3NeJ%xiAQB2}=dl zfvQ0ds2^B_fWi^7piQ$Z!E*%ciVvlis~ z)2Dkeuyr*65P&0UjhnV?@h7Y#I5I4}DyZn5U;ccM{LnuYu3mm#Gz>aKT8JlCjdJW; zf4@H}ZQ^&B#ZLSet@bJk5tgC2ixe_S(ZzgXFT#-ua$9LzrQe3XoAa40ZI%ImuTn-5P(93z^h>rLQEeI z6koZqGkF`Ypr8_kk>Upt9W+dCmz`};7okPmN+|X`goGKPMn6&kh#v=ZhvEznrT8wi z%?Lz3xqCC+$7!^~RMLdEwy6LLW|a!Q^EC4CPESps2=m9Ug>q55%lRKBn5lnQLc&mc zO-?~h@K|idDsMZxYfKc9@`WgLkmbSf9$0+n#SJ<8f0TE%K~2|j{6B|4D93{+X(7>r zAfi*tq!d_l3T((=2bm$bZkNY4OS&2&G8u`=FeDF`1t*|s!e9{+86PLSKR*m_j~w$9=@M%zZ)M^cn)UdiSMh^)@jTaE?n?H z={N(6%yxQQF;L=u{Xr)e$GWtlAU{7p7-gS4KT^2FErG$ejHAvE@)*uCVBslVE-UpN z`%&3aM?@6{TR`(Qw24I`s3nzZUsOO?63K^ImZcX)He*!npb1N30%Wq331a~cipJ(< zM@$Ogr>52_E#yAK!G=T!7MFBQG2He>7&--T9N8WZ4G%k|SXxiRPeD>2(_q&5hhDF8 zt+OOJ0a3g-ZFJG^;T9b{8t?&6!lGzPKI@=`4${Q3PBeT0W)!=9bdynSjMn%bi3?nW zh%{_Qh0ki&Lrm0kvfrfQJyh)XlX=6`YJ;aeAyo|Mocq0mUmICreej^hfB9h|>>SXYhGEQ{Zr( zPUj(Tu7=Nm!%wS8p6|I}L++(B>%9{NBe`mJfwL|vt4f{XMd}%I4xC9v<#u;L{m|6} z%+`yC_!IV-#+SxjgBDIWF;Ly3DK(7x3vJkw=tl5>w+J=U;a$Pb*%6ZL9XtF&LVVB` zUiV?TNaO$_<>t{>K;|`(V)enryszhLXqM|OQ^tVmkw_o4YsFOeZQ{gs6_0q{D3YRy< zDjQ!1+UR}FA1M#_gP zbCuMu$tl|)gC(dq?Xu>(k`j}M;@GhEolxJR;dk|XQWwd}3 zedF7v1?6=-Y?)^&#rbM8a7(w18(RKJgGh_Qs^1MlUzhv2bGV1WMwZ3_}9MGlt`^h`R{w+%Pi9L2W2|$uxmX901Xv{I8tYCZzp;I9UBkFS7G$i1Z=$OIK2N5QJ6)So%xFO; zoNsOY8ZXN_vbpDykFh5a$dAaMD~oML9z*6i^vsbR4yl`QigCl%3GKaGO?`bE^WvkJ z+ep}SEPbc3=-EGn+Yg*Fja?!U3FkA;Bg|w?ItTd^I)e_Z6^?7arAxiBQEcC~{sMXy zcZmZ-iOWbv!GwTj*fz*Bi{p$K60FcH%)C-spoRjtP*W^)y(a8gLbTuve?~5d-UP)M z7h5CioB0*stt$XF0kITtjT<{oPcP9to{5o}HCHzwc$3Z{qAh{nzQ;*~H%HcB#5mBD zKt%sLVMBai|A_`TIxIHXb&jixI?wMBjvXKMfBCm9nQP6+j#W8m@nCd0kT(S8g?8Am zA=^htBrIscD?db)f2zp`#zv$TEJ;{GoLL=B*yaLMjRwsGv)mfej%h7OP|=Zq2{cWv zXsmsxu9M2+472zvgz3U-JU>tCpc#W5F?TNjEt;EQ|`mcQQ-*`Cl z-bgdcuGw;?ySuyOu05nTBuXOjCZ!Af7(sZF^wD0I3**uYr`8=Cy6GN!agK*TY+>Nl zJ_HpPh4NWk9>u-Exc70?Y7ZPp)IUI6OE33FZiJ9$#!^ru+PWgwCM3YDS4>z82+1nG zhq90KOgr2L%J~%li#FI%UrnEj)+m={seKIy+pEU-dH=$j**Q4|cz2&d5a{|(e?Mm^ g@;qVC|LU^`C)x{20t%b6=P~$+Tp2AqCXjvkH$cX>fB*mh diff --git a/doc/source/tutorials/online_user_actions/online_user_actions.rst b/doc/source/tutorials/online_user_actions/online_user_actions.rst deleted file mode 100644 index 8561fdbe0..000000000 --- a/doc/source/tutorials/online_user_actions/online_user_actions.rst +++ /dev/null @@ -1,113 +0,0 @@ -.. include:: ../../include/global.rst - -.. _tutorials-online-user-actions: - -=================== -Online user actions -=================== - -This example reproduces a typical data science situation in an internet company. We start from a pandas DataFrame with online user actions, for instance for an online text editor: the user can create a page, edit it, or delete it. We want to construct and visualize a graph of the users highlighting collaborations on the same page/project. - -.. code-block:: python - - import igraph as ig - import numpy as np - import pandas as pd - import matplotlib.pyplot as plt - - # User data (usually would come with time stamp) - action_dataframe = pd.DataFrame([ - ['dsj3239asadsa3', 'createPage', 'greatProject'], - ['2r09ej221sk2k5', 'editPage', 'greatProject'], - ['dsj3239asadsa3', 'editPage', 'greatProject'], - ['789dsadafj32jj', 'editPage', 'greatProject'], - ['oi32ncwosap399', 'editPage', 'greatProject'], - ['4r4320dkqpdokk', 'createPage', 'miniProject'], - ['320eljl3lk3239', 'editPage', 'miniProject'], - ['dsj3239asadsa3', 'editPage', 'miniProject'], - ['3203ejew332323', 'createPage', 'private'], - ['3203ejew332323', 'editPage', 'private'], - ['40m11919332msa', 'createPage', 'private2'], - ['40m11919332msa', 'editPage', 'private2'], - ['dsj3239asadsa3', 'createPage', 'anotherGreatProject'], - ['2r09ej221sk2k5', 'editPage', 'anotherGreatProject'], - ], - columns=['userid', 'action', 'project'], - ) - -This block just introduces the toy data: a DataFrame with three columns, namely the user id, the action, and the page or project that was being actioned upon. Now we need to check when two users worked on the same page. We choose to use a weighted adjacency matrix for this, i.e. a table with rows and columns indexes by the users that has nonzero entries whenever folks collaborate. First, let's get the users and prepare an empty matrix: - -.. code-block:: python - - users = action_dataframe['userid'].unique() - adjacency_matrix = pd.DataFrame( - np.zeros((len(users), len(users)), np.int32), - index=users, - columns=users, - ) - -Then, let's iterate over all projects one by one, and add all collaborations: - -.. code-block:: python - - for project, project_data in action_dataframe.groupby('project'): - project_users = project_data['userid'].values - for i1, user1 in enumerate(project_users): - for user2 in project_users[:i1]: - adjacency_matrix.at[user1, user2] += 1 - -There are many ways to achieve the above matrix, so don't be surprised if you came up with another algorithm ;-) - -Now it's time to make the graph: - -.. code-block:: python - - g = ig.Graph.Weighted_Adjacency(adjacency_matrix, mode='plus') - -And finally, let's plot a layout of the graph, for instance a circle: - -.. code-block:: python - - # Make a layout first - layout = g.layout('circle') - - # Make vertex size based on their closeness to other vertices - vertex_size = g.closeness() - vertex_size = [0.5 * v**2 if not np.isnan(v) else 0.05 for v in vertex_size] - - # Make mpl axes - fig, ax = plt.subplots() - - # Plot graph in that axes - ig.plot( - g, - target=ax, - layout=layout, - vertex_label=g.vs['name'], - vertex_color="lightblue", - vertex_size=vertex_size, - edge_width=g.es["weight"], - ) - plt.show() - -We added a few fancy features to this plot to show off igraph's capabilities. The result is shown below. - -.. figure:: ./figures/online_user_actions.png - :alt: A visual representation of the collaboratoin graph - :align: center - - The collaboration graph: thicker edges mean multiple collaborations, and larger vertices indicate users with higher closeness to the rest of the network. - -Loops indicate "self-collaborations", which are not very meaningful. To filter out loops without losing the edge weights, we can use: - -.. code-block:: python - - g = g.simplify(combine_edges='first') - -and then repeat the plotting code verbatim. The result is shown below. - -.. figure:: ./figures/online_users_simple.png - :alt: A visual representation of the collaboratoin graph - :align: center - - Simplified graph after loops are filtered out. diff --git a/doc/source/tutorials/quickstart/figures/quickstart.png b/doc/source/tutorials/quickstart/figures/quickstart.png deleted file mode 100644 index 56ef350300530d17123e638c42557e0f1d358917..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16277 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 diff --git a/doc/source/tutorials/quickstart/figures/social_network.png b/doc/source/tutorials/quickstart/figures/social_network.png deleted file mode 100644 index f528c450abd21668dbea3e4a1e7d2eef2e1e39db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65370 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%0Ao@8SF>iJ!=AXDhWCGOBDQO)#uM=_9nE0PW_j? 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

  • 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Ě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 y#(i);?PtUjz^YK2qZ<< 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