# Ticket #13599: trac_13599.patch

File trac_13599.patch, 10.1 KB (added by ncohen, 8 years ago)
• ## sage/graphs/graph.py

# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1350219732 -7200
# Node ID 8054fcd6b8975b707a2424f2ea43c613758b7963
# Parent  f58cebb10eeeb8e1fcaed9f36f953f475c338f95
Bug in Graph.is_cartesian_product

diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
 a return D[0] == "Prime" and len(D[1]) == self.order() def is_cartesian_product(self, certificate = False): r""" Tests whether self is a cartesian product of graphs. INPUT: - certificate (boolean) -- if certificate = False (default) the method only returns True or False answers. If certificate = True, the True answers are replaced by the list of the factors of the graph. .. SEEALSO:: - :meth:~sage.graphs.generic_graph.GenericGraph.cartesian_product - :mod:~sage.graphs.graph_decompositions.graph_products -- a module on graph products. EXAMPLE: The Petersen graph is prime:: sage: g = graphs.PetersenGraph() sage: g.is_cartesian_product() False A 2d grid is the product of paths:: sage: g = graphs.Grid2dGraph(5,5) sage: p1, p2 = g.is_cartesian_product(certificate = True) sage: p1.is_isomorphic(graphs.PathGraph(5)) True sage: p2.is_isomorphic(graphs.PathGraph(5)) True And of course, we find the factors back when we build a graph from a product:: sage: g = graphs.PetersenGraph().cartesian_product(graphs.CycleGraph(3)) sage: g1, g2 = g.is_cartesian_product(certificate = True) sage: any( x.is_isomorphic(graphs.PetersenGraph()) for x in [g1,g2]) True sage: any( x.is_isomorphic(graphs.CycleGraph(3)) for x in [g1,g2]) True """ from sage.graphs.graph_decompositions.graph_products import is_cartesian_product return is_cartesian_product(self, certificate = certificate) def _gomory_hu_tree(self, vertices=None, method="FF"): r""" Returns a Gomory-Hu tree associated to self. return classes_b # Aliases to functions defined in Cython modules import types import sage.graphs.cliquer Graph.cliques_maximum = types.MethodType(sage.graphs.cliquer.all_max_clique, None, Graph) import sage.graphs.graph_decompositions.graph_products Graph.is_cartesian_product = types.MethodType(sage.graphs.graph_decompositions.graph_products.is_cartesian_product, None, Graph) def compare_edges(x, y): """ This function has been deprecated.
• ## sage/graphs/graph_decompositions/graph_products.pyx

diff --git a/sage/graphs/graph_decompositions/graph_products.pyx b/sage/graphs/graph_decompositions/graph_products.pyx
 a Products of graphs This module gathers everything related to graph products. At the moment it contains different implementations of recognition algorithms for graphs that can be written as a cartesian product of smaller ones. contains an implementation of a recognition algorithm for graphs that can be written as a cartesian product of smaller ones. References: if and only if : - g=g' and hh'\in H; or - h=h' and gg'\in H - h=h' and gg'\in G Two remarks follow : unique. What is explained below can be found in the book *Handbook of Product Graphs* [HIK11]_. Everything is actually based on a simple observation. Given a graph G, finding Everything is actually based on simple observations. Given a graph G, finding out whether G can be written as the product of several graphs can be attempted by trying to color its edges according to some rules. Indeed, if we are to color the edges of G in such a way that each color class represents a factor of G, \put(-55,0){\makebox(0,0)[r]{$u_2=(g',h)$}} \end{picture} As a corollary, we also know that: **1st criterion** : As a corollary, we know that: #. If two vertices u,v have a *unique* common neighbor x, then ux and uv have the same color. xv have the same color. #. If two vertices u, v have more that two common neighbors x_1, ..., x_k then all edges between the x_i and the vertices of u,v have the same color. This is also a consequence of the first remark. **2nd criterion** : if two edges uv and u'v' of the product graph G\square H are such that d(u,u')+d(v,v')\neq d(u,v') + d(v,u') then the two edges uv and u'v' necessarily have the same color. This is a consequence of the fact that for any two vertices u,v of G\square H (where u=(u_G,u_H) and v=(v_G,v_H)), we have d(u,v) = d_G(u_G,v_G)+d_H(u_H,v_H). Indeed, a shortest path from u to v in G\square H contains the information of a shortest path from u_G to v_G in G, and a shortest path from u_H to v_H in H. The algorithm ^^^^^^^^^^^^^ Then again, please refer to [HIK11]_ for any technical question. To Do ^^^^^ This implementation is made at Python level, and some parts of the algorithm could be rewritten in Cython to save time. Especially when enumerating all pairs of edges and computing their distances. This can easily be done in C with the functions from the :mod:sage.graphs.distances_all_pairs module. Methods ------- """ #                         http://www.gnu.org/licenses/                        * #****************************************************************************** def is_cartesian_product(g, certificate = False): def is_cartesian_product(g, certificate = False, relabeling = False): r""" Tests whether the graph can be factorized. Tests whether the graph is a cartesian product. INPUT: True, the True answers are replaced by the list of the factors of the graph. - relabeling (boolean) -- if relabeling = True (implies certificate = True), the method also returns a dictionary associating to each vertex its natural coordinates as a vertex of a product graph. If g is not a cartesian product, None is returned instead. This is set to False by default. .. SEEALSO:: - :meth:~sage.graphs.generic_graph.GenericGraph.cartesian_product - :meth:sage.graphs.generic_graph.GenericGraph.cartesian_product - :mod:~sage.graphs.graph_decompositions.graph_products -- a module on graph products. .. NOTE:: This algorithm may run faster whenever the graph's vertices are integers (see :meth:~sage.graphs.generic_graph.GenericGraph.relabel). Give it a try if it is too slow ! EXAMPLE: sage: p2.is_isomorphic(graphs.PathGraph(5)) True Forgetting the graph's labels, then finding them back:: sage: g.relabel() sage: g.is_cartesian_product(g, relabeling = True) (True, {0: (0, 0), 1: (0, 1), 2: (0, 2), 3: (0, 3), 4: (0, 4), 5: (5, 0), 6: (5, 1), 7: (5, 2), 8: (5, 3), 9: (5, 4), 10: (10, 0), 11: (10, 1), 12: (10, 2), 13: (10, 3), 14: (10, 4), 15: (15, 0), 16: (15, 1), 17: (15, 2), 18: (15, 3), 19: (15, 4), 20: (20, 0), 21: (20, 1), 22: (20, 2), 23: (20, 3), 24: (20, 4)}) And of course, we find the factors back when we build a graph from a product:: True sage: any( x.is_isomorphic(graphs.CycleGraph(3)) for x in [g1,g2]) True TESTS: Wagner's Graph (:trac:13599):: sage: g = graphs.WagnerGraph() sage: g.is_cartesian_product() False """ if relabeling: certificate = True from sage.rings.integer import Integer H = g # Of course the number of vertices of g can not be prime ! if Integer(g.order()).is_prime(): return False return (False, None) if relabeling else False if not g.is_connected(): raise ValueError("The graph must be connected !") else: h.add_path([r(u,x) for x in intersect] + [r(v,x) for x in intersect]) # Edges uv and u'v' such that d(u,u')+d(v,v') != d(u,v')+d(v,u') are also # equivalent edges = g.edges(labels = False) d = g.distance_all_pairs() for i,(u,v) in enumerate(edges): du = d[u] dv = d[v] for j in range(i+1,len(edges)): uu,vv = edges[j] if du[uu]+dv[vv] != du[vv] + dv[uu]: h.add_edge(r(u,v),r(uu,vv)) # Gathering the connected components, relabeling the vertices on-the-fly edges = map(lambda x:map(lambda y : (t[y[0]],t[y[1]]),x),h.connected_components()) #Print the graph, distinguishing the edges according to their color classes # #from sage.plot.colors import rainbow #g.show(edge_colors = dict(zip(rainbow(len(edges)),edges))) # Only one connected component ? if len(edges) == 1: return False return (False, None) if relabeling else False # Building the list of factors factors = [] answer = answer.cartesian_product(factors[i]) # Checking that the resulting graph is indeed isomorphic to what we have. if not answer.is_isomorphic(g): isiso, dictt = g.is_isomorphic(answer, certify = True) if not isiso: raise ValueError("Something weird happened during the algorithm... "+ "Please report the bug and give us the graph instance"+ " that made it fail !!!") if relabeling: return isiso, dictt if certificate: return factors else: