From 79c4c607faadb8d420f438fb0e6e2128fd49083b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Sat, 18 May 2024 15:48:49 +0000 Subject: [PATCH] feat: add is_complete() --- CHANGELOG.md | 4 ++++ src/_igraph/graphobject.c | 29 +++++++++++++++++++++++++++++ src/igraph/adjacency.py | 2 +- tests/test_bipartite.py | 6 ++++++ tests/test_generators.py | 1 + 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9036a3b2..859944b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # igraph Python interface changelog +### Added + + - Added `Graph.is_complete()` to test if there is a connection between all distinct pair of vertices. + ### Changed - Error messages issued when an attribute is not found now mention the name and type of that attribute. diff --git a/src/_igraph/graphobject.c b/src/_igraph/graphobject.c index 9045148c3..92fc7def9 100644 --- a/src/_igraph/graphobject.c +++ b/src/_igraph/graphobject.c @@ -548,6 +548,25 @@ PyObject *igraphmodule_Graph_is_simple(igraphmodule_GraphObject* self, PyObject* } +/** \ingroup python_interface_graph + * \brief Checks whether an \c igraph.Graph object is a complete graph. + * \return \c True if the graph is complete, \c False otherwise. + * \sa igraph_is_complete + */ +PyObject *igraphmodule_Graph_is_complete(igraphmodule_GraphObject* self, PyObject* Py_UNUSED(_null)) { + igraph_bool_t res; + + if (igraph_is_complete(&self->g, &res)) { + igraphmodule_handle_igraph_error(); + return NULL; + } + + if (res) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + + /** \ingroup python_interface_graph * \brief Determines whether a graph is a (directed or undirected) tree * \sa igraph_is_tree @@ -13625,6 +13644,16 @@ struct PyMethodDef igraphmodule_Graph_methods[] = { "@return: C{True} if it is simple, C{False} otherwise.\n" "@rtype: boolean"}, + /* interface to igraph_is_complete */ + {"is_complete", (PyCFunction) igraphmodule_Graph_is_complete, + METH_NOARGS, + "is_complete()\n--\n\n" + "Checks whether the graph is complete, i.e. whether there is at least one\n" + "connection between all distinct pairs of vertices. In directed graphs,\n" + "ordered pairs are considered.\n\n" + "@return: C{True} if it is complete, C{False} otherwise.\n" + "@rtype: boolean"}, + /* interface to igraph_is_tree */ {"is_tree", (PyCFunction) igraphmodule_Graph_is_tree, METH_VARARGS | METH_KEYWORDS, diff --git a/src/igraph/adjacency.py b/src/igraph/adjacency.py index d94b246a3..b38889c81 100644 --- a/src/igraph/adjacency.py +++ b/src/igraph/adjacency.py @@ -140,7 +140,7 @@ def _get_biadjacency(graph, types="type", *args, **kwds): 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 + @param types: a 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 bipartite adjacency matrix and two lists in a triplet. The diff --git a/tests/test_bipartite.py b/tests/test_bipartite.py index 45cca2fc2..f3c5cc8c7 100644 --- a/tests/test_bipartite.py +++ b/tests/test_bipartite.py @@ -172,7 +172,9 @@ def testBipartiteProjection(self): g = Graph.Full_Bipartite(10, 5) g1, g2 = g.bipartite_projection() + self.assertTrue(g1.is_complete()) self.assertTrue(g1.isomorphic(Graph.Full(10))) + self.assertTrue(g2.is_complete()) self.assertTrue(g2.isomorphic(Graph.Full(5))) self.assertTrue(g.bipartite_projection(which=0).isomorphic(g1)) self.assertTrue(g.bipartite_projection(which=1).isomorphic(g2)) @@ -183,7 +185,9 @@ def testBipartiteProjection(self): self.assertTrue(g.bipartite_projection_size() == (10, 45, 5, 10)) g1, g2 = g.bipartite_projection(probe1=10) + self.assertTrue(g1.is_complete()) self.assertTrue(g1.isomorphic(Graph.Full(5))) + self.assertTrue(g2.is_complete()) self.assertTrue(g2.isomorphic(Graph.Full(10))) self.assertTrue(g.bipartite_projection(which=0).isomorphic(g2)) self.assertTrue(g.bipartite_projection(which=1).isomorphic(g1)) @@ -191,7 +195,9 @@ def testBipartiteProjection(self): self.assertTrue(g.bipartite_projection(which=True).isomorphic(g1)) g1, g2 = g.bipartite_projection(multiplicity=False) + self.assertTrue(g1.is_complete()) self.assertTrue(g1.isomorphic(Graph.Full(10))) + self.assertTrue(g2.is_complete()) self.assertTrue(g2.isomorphic(Graph.Full(5))) self.assertTrue(g.bipartite_projection(which=0).isomorphic(g1)) self.assertTrue(g.bipartite_projection(which=1).isomorphic(g2)) diff --git a/tests/test_generators.py b/tests/test_generators.py index 17205eb95..733a31c66 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -110,6 +110,7 @@ def testFull(self): g = Graph.Full(20, directed=True) el = g.get_edgelist() el.sort() + self.assertTrue(g.is_complete()) self.assertTrue( g.get_edgelist() == [(x, y) for x in range(20) for y in range(20) if x != y] )