# Ticket #12810: trac_12810-rebased.patch

File trac_12810-rebased.patch, 45.1 KB (added by jdemeyer, 9 years ago)

Rebased to sage-5.1.beta4

• ## doc/en/reference/graphs.rst

# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1332446450 -3600
# Node ID ec7e358278e67598cfac3f4cc057168cfa000a54
# Parent  c32bd63d6b03ded645f57028ae29b682db7e4b26
Broken links in the documentation of graph/ files

diff --git a/doc/en/reference/graphs.rst b/doc/en/reference/graphs.rst
 a sage/graphs/generic_graph sage/graphs/graph sage/graphs/graph_plot sage/graphs/digraph sage/graphs/bipartite_graph sage/graphs/comparability sage/graphs/spanning_tree sage/graphs/pq_trees sage/graphs/trees sage/graphs/matchpoly sage/graphs/linearextensions sage/graphs/schnyder sage/graphs/graph_plot sage/graphs/graph_decompositions/vertex_separation sage/graphs/graph_decompositions/rankwidth sage/graphs/modular_decomposition/modular_decomposition
• ## sage/graphs/all.py

diff --git a/sage/graphs/all.py b/sage/graphs/all.py
 a import sage.graphs.isgci from sage.graphs.isgci import graph_classes import sage.graphs.distances_all_pairs import sage.graphs.trees import sage.graphs.graph_latex
• ## sage/graphs/base/c_graph.pyx

diff --git a/sage/graphs/base/c_graph.pyx b/sage/graphs/base/c_graph.pyx
 a .. SEEALSO:: - :meth:add_vertex_unsafe -- add a vertex to a graph. This method is potentially unsafe. You should instead use :meth:add_vertex. - :meth:add_vertices -- add a bunch of vertices to a graph. - add_vertex_unsafe -- add a vertex to a graph. This method is potentially unsafe.  You should instead use :meth:add_vertex. - add_vertices -- add a bunch of vertices to a graph. EXAMPLES: .. SEEALSO:: - :meth:del_vertex_unsafe -- delete a vertex from a graph. This method is potentially unsafe. Use :meth:del_vertex instead. - del_vertex_unsafe -- delete a vertex from a graph. This method is potentially unsafe. Use :meth:del_vertex instead. EXAMPLES: raise NotImplementedError() cdef int * adjacency_sequence_in(self, int n, int *vertices, int v): r""" r""" Returns the adjacency sequence corresponding to a list of vertices and a vertex. and a vertex. See the OUTPUT section for a formal definition. See the function _test_adjacency_sequence() of dense_graph.pyx and sparse_graph.pyx for unit tests. INPUT: INPUT: - n -- nonnegative integer; the maximum index in vertices up to which we want to consider. If n = 0,
• ## sage/graphs/base/static_sparse_graph.pyx

diff --git a/sage/graphs/base/static_sparse_graph.pyx b/sage/graphs/base/static_sparse_graph.pyx
 a bitset_intersection(scc, scc, scc_reversed) cdef void free_short_digraph(short_digraph g): if g.edges != NULL: sage_free(g.edges) .. NOTE:: This method has been written as an attempt to solve the slowness reported in #12235. It is not the one used by :meth:sage.graphs.digraph.strongly_connected_components as saving some time on the computation of the strongly connected components is not worth copying the whole graph, but it is a nice way to test this reported in :trac:12235. It is not the one used by :meth:sage.graphs.digraph.DiGraph.strongly_connected_components as saving some time on the computation of the strongly connected components is not worth copying the whole graph, but it is a nice way to test this module's functions. It is also tested in the doctest or :meth:sage.graphs.digraph.strongly_connected_components. :meth:sage.graphs.digraph.DiGraph.strongly_connected_components. EXAMPLE:: sage: from sage.graphs.base.static_sparse_graph import strongly_connected_components sage: g = digraphs.ButterflyGraph(2) sage: strongly_connected_components(g) [[('00', 0)], [('00', 1)], [('00', 2)], [('01', 0)], [('01', 1)], [('01', 2)], [[('00', 0)], [('00', 1)], [('00', 2)], [('01', 0)], [('01', 1)], [('01', 2)], [('10', 0)], [('10', 1)], [('10', 2)], [('11', 0)], [('11', 1)], [('11', 2)]] """ strongly_connected_component_containing_vertex(g, gr, v, scc) answer.append([vertices[i] for i in bitset_list(scc)]) bitset_union(seen, seen, scc) bitset_free(seen) bitset_free(scc) free_short_digraph(g)
• ## sage/graphs/digraph.py

diff --git a/sage/graphs/digraph.py b/sage/graphs/digraph.py
 a set decomposition of the graph (see :meth:.level_sets). This is achieved by calling graphviz and dot2tex if available (see :meth:.layout_acyclic_graphviz), and using a random horizontal (see :meth:.layout_graphviz), and using a random horizontal placement of the vertices otherwise (see :meth:.layout_acyclic_dummy). Non acyclic graphs are partially supported by graphviz, which then
• ## sage/graphs/generic_graph.py

diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
 a Multiple starting vertices can be specified in a list:: sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) sage: list(D.breadth_first_search([0])) sage: list(D.breadth_first_search([0])) [0, 1, 2, 3, 4, 5, 6, 7] sage: list(D.breadth_first_search([0,6])) [0, 6, 1, 2, 3, 7, 4, 5] [0, 6, 1, 2, 3, 7] sage: list(D.breadth_first_search(6,ignore_direction=True,distance=2)) [6, 3, 7, 0, 5] More generally, you can specify a neighbors function.  For example, you can traverse the graph backwards by setting neighbors to be the :meth:.predecessor function of the graph:: neighbors to be the :meth:.neighbors_in function of the graph:: sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) sage: list(D.breadth_first_search(5,neighbors=D.neighbors_in, distance=2)) [5, 1, 2, 0] sage: list(D.breadth_first_search(5,neighbors=D.neighbors_out, distance=2)) sage: list(D.breadth_first_search(5,neighbors=D.neighbors_out, distance=2)) [5, 7, 0] sage: list(D.breadth_first_search(5,neighbors=D.neighbors, distance=2)) sage: list(D.breadth_first_search(5,neighbors=D.neighbors, distance=2)) [5, 1, 2, 7, 0, 4, 6] [0, 1, 2] """ # Preferably use the Cython implementation if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"breadth_first_search"): for v in self._backend.breadth_first_search(start, ignore_direction = ignore_direction): yield v else: # Preferably use the Cython implementation if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"breadth_first_search"): for v in self._backend.breadth_first_search(start, ignore_direction = ignore_direction): yield v else: if neighbors is None: if not self._directed or ignore_direction: neighbors=self.neighbor_iterator neighbors=self.neighbor_iterator else: neighbors=self.neighbor_out_iterator seen=set([]) More generally, you can specify a neighbors function.  For example, you can traverse the graph backwards by setting neighbors to be the :meth:.predecessor function of the graph:: neighbors to be the :meth:.neighbors_in function of the graph:: sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) sage: list(D.depth_first_search(5,neighbors=D.neighbors_in, distance=2)) :meth:.layout_graphviz for installation instructions. A subclass may implement another layout algorithm blah, by implementing a method :meth:.layout_blah. It may override implementing a method .layout_blah. It may override the default layout by overriding :meth:.layout_default, and similarly override the predefined layouts. INPUT: -  laplacian - if True, use the Laplacian matrix (see :meth:~sage.graphs.graph.GenericGraph.kirchhoff_matrix()) (see :meth:kirchhoff_matrix) OUTPUT: INPUT: -  laplacian - if True, use the Laplacian matrix (see :meth:~sage.graphs.graph.GenericGraph.kirchhoff_matrix()) (see :meth:kirchhoff_matrix) OUTPUT: INPUT: -  laplacian - if True, use the Laplacian matrix (see :meth:~sage.graphs.graph.GenericGraph.kirchhoff_matrix()) (see :meth:kirchhoff_matrix) OUTPUT:
• ## sage/graphs/graph.py

diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
 a for h in H: for u,v in self.edges(labels=None): p.add_constraint(r_edges[h][(u,v)] + r_edges[h][(v,u)] - edges[h][S((u,v))], min = 0) for v in self: p.add_constraint(Sum([r_edges[h][(u,v)] for u in self.neighbors(v)]), max = 1-epsilon) Returns an rank-decomposition of self achieving optiml rank-width. See the documentation of the rankwidth module :class:. :mod:rankwidth . INPUT: See the documentation of the rankwidth module for more information on the tree :class:rankwidth . .. WARNING:: obtained from H through arbitrary subdivision of its edges) as a subgraph. For more information, see the Wikipedia article on graph minor _. For more information, see the Wikipedia article on graph minor :wikipedia:Minor_(graph_theory). INPUT: The topological H-minor found is returned as a subgraph M of self, such that the vertex v of M that represents a vertex h\in H has h as a label (see :meth:get_vertex  :meth:get_vertex  and :meth:set_vertex ), :meth:set_vertex ), and such that every edge of M has as a label the edge of H it (partially) represents. are highly exponential in H, though. .. NOTE:: * This function can be expected to be *very* slow, especially where the topological minor does not exist. from sage.numerical.mip import MixedIntegerLinearProgram, Sum, MIPSolverException p = MixedIntegerLinearProgram() # This is an existence problem # This is an existence problem p.set_objective(None) #######################
• ## sage/graphs/graph_decompositions/rankwidth.pyx

diff --git a/sage/graphs/graph_decompositions/rankwidth.pyx b/sage/graphs/graph_decompositions/rankwidth.pyx
 a def rank_decomposition(G, verbose = False): r""" Computes an optiml rank-decomposition of the given graph. Computes an optimal rank-decomposition of the given graph. This function is available as a method of the :class:Graph  class. See :meth:rank_decomposition . This function is available as a method of the :class:Graph  class. See :meth:rank_decomposition . INPUT: r""" Returns the graph corresponding the the current rank-decomposition. (This function is for interna use) (This function is for internal use) EXAMPLE::
• ## sage/graphs/graph_generators.py

diff --git a/sage/graphs/graph_generators.py b/sage/graphs/graph_generators.py
 a 0: [1, 2, 3, 4], 1: [2, 3, 4], 3: [4], 5: [2, 0, 1] 5: [2, 0, 1] })) graphs.append(Graph({
• ## sage/graphs/graph_latex.py

diff --git a/sage/graphs/graph_latex.py b/sage/graphs/graph_latex.py
 a should call this once as having random output to exhaust the warnings before testing output. See also :meth:sage.misc.latex.check_file See also :meth:sage.misc.latex.Latex.check_file TESTS:: The result is cached. See also :meth:sage.misc.latex.has_file See also :meth:sage.misc.latex.Latex.has_file TESTS:: graphs(tikz, tkz-graph, tkz-berge), if available in the LaTeX installation. See also :meth:sage.misc.latex.add_package_to_preamble_if_available. See also :meth:sage.misc.latex.Latex.add_package_to_preamble_if_available. EXAMPLES:: sage: sage.graphs.graph_latex.setup_latex_preamble() Sets, modifies, clears a LaTeX option for controlling the rendering of a graph. The possible options are documented here, because ultimately it is this routine that sets the values.  However, the :meth:sage.graphs.generic_graph.Graph.set_latex_options method is the easiest way to set options, and allows several to be set at once. The possible options are documented here, because ultimately it is this routine that sets the values.  However, the :meth:sage.graphs.generic_graph.GenericGraph.set_latex_options method is the easiest way to set options, and allows several to be set at once. INPUTS: - option_name - a string for a latex option contained in the list :data:__graphlatex_options. A ValueError is raised if the option is not allowed. - option_name - a string for a latex option contained in the list sage.graphs.graph_latex.GraphLatex.__graphlatex_options. A ValueError is raised if the option is not allowed. - option_value - a value for the option.  If omitted, or set to None, the option will use the default value. ... ValueError: bad_name is not a LaTeX option for a graph. See :meth:Graph.layout_graphviz for installation instructions for graphviz and dot2tex. Further more, pgf >= 2.00 should be available inside LaTeX's tree for LaTeX compilation (e.g. when using view). In case your LaTeX distribution does not provide it, here are short instructions: See :meth:sage.graphs.generic_graph.GenericGraph.layout_graphviz for installation instructions for graphviz and dot2tex. Further more, pgf >= 2.00 should be available inside LaTeX's tree for LaTeX compilation (e.g. when using view). In case your LaTeX distribution does not provide it, here are short instructions: - download pgf from http://sourceforge.net/projects/pgf/ - unpack it in /usr/share/texmf/tex/generic (depends on your system) OUTPUT: If the name is not present in :data:sage.graphs.graph_latex.__graphlatex_options it is an __graphlatex_options it is an error to ask for it.  If an option has not been set then the default value is returned. Otherwise, the value of the option is returned. Returns a string in LaTeX representing a graph. This is the command that is invoked by :meth:~sage.graphs.graph.GenericGraph._latex_ for a graph, so it returns a string of LaTeX commands that can be incorporated into a LaTeX document unmodified.  The exact contents of this string are influenced by the options set via the methods :meth:sage.graphs.graph.GenericGraph.set_latex_options, sage.graphs.generic_graph.GenericGraph._latex_ for a graph, so it returns a string of LaTeX commands that can be incorporated into a LaTeX document unmodified.  The exact contents of this string are influenced by the options set via the methods :meth:sage.graphs.generic_graph.GenericGraph.set_latex_options, :meth:set_option, and :meth:set_options. By setting the format option different packages can be used to create the latex version of a graph.  Supported packages are By setting the format option different packages can be used to create the latex version of a graph.  Supported packages are tkz-graph and dot2tex. EXAMPLES::
• ## sage/graphs/graph_plot.py

diff --git a/sage/graphs/graph_plot.py b/sage/graphs/graph_plot.py
 a Make sure that vertex locations are floats.  Not being floats isn't a bug in itself but makes it too easy to accidentally introduce a bug elsewhere, such as in set_edges (trac #10124), introduce a bug elsewhere, such as in set_edges (:trac:10124), via silent truncating division of integers:: sage: g = graphs.FruchtGraph() sage: G.show(edge_colors={'red':[(3,6),(2,5)]}) Verify that default edge labels are pretty close to being between the vertices in some cases where they weren't due to truncating division (trac #10124):: in some cases where they weren't due to truncating division (:trac:10124):: sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph() sage: tol = 0.001 TESTS: Make sure that Python ints are acceptable arguments (trac #10124):: Make sure that Python ints are acceptable arguments (:trac:10124):: sage: GP = DiGraph().graphplot() sage: GP._polar_hack_for_multidigraph((0, 1), (2, 2), .1)
• ## sage/graphs/linearextensions.py

diff --git a/sage/graphs/linearextensions.py b/sage/graphs/linearextensions.py
 a A linear extension of a directed acyclic graph is a total (linear) ordering on the vertices that is compatible with the graph in the following sense: if there is a path from x to y in the graph, the x appears before y in the if there is a path from x to y in the graph, the x appears before y in the linear extension. The algorithm implemented in this module is from "Generating Linear Extensions Fast" by Preusse and Ruskey, which can be found at Fast" by Preusse and Ruskey, which can be found at http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.52.3057 .  The algorithm generates the extensions in constant amortized time (CAT) -- a constant amount of time per extension generated, or linear in the number of extensions of time per extension generated, or linear in the number of extensions generated. EXAMPLES: Here we generate the 5 linear extensions of the following directed acyclic graph. acyclic graph:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: D.is_directed_acyclic() induced from the graph. We can also get at the linear extensions directly from the graph.  From the graph, the linear extensions are known as topological sorts. the graph, the linear extensions are known as topological sorts :: sage: D.topological_sort_generator() [[0, 1, 2, 3, 4], [0, 1, 2, 4, 3], This is an in-place algorithm and the list self.le keeps track of the current linear extensions.  The boolean variable self.is_plus keeps track of the "sign". keeps track of the "sign". EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D) sage: l == loads(dumps(l)) True """ ################ #Precomputation# self.is_plus = True self.linear_extensions = None self._name = "Linear extensions of %s"%dag def switch(self, i): """ This implements the Switch procedure described on page 7 of "Generating Linear Extensions Fast" by Pruesse and Ruskey. If i == -1, then the sign is changed.  If i > 0, then self.a[i] If i == -1, then the sign is changed.  If i > 0, then self.a[i] and self.b[i] are transposed. Note that this meant to be called by the generate_linear_extensions method and is not meant to be used directly. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D) of "Generating Linear Extensions Fast" by Pruesse and Ruskey. If direction is "left", then this transposes element with the element on its left.  If the direction is "right", then this element on its left.  If the direction is "right", then this transposes element with the element on its right. Note that this is meant to be called by the generate_linear_extensions method and is not meant to be used directly. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D) """ If letter =="b", then this returns True if and only if self.b[i] is incomparable with the elements to its right in self.le.  If letter == "a", then it returns True if in self.le.  If letter == "a", then it returns True if and only if self.a[i] is incomparable with the element to its right in self.le and the element to the right is not self.b[i] This is the Right function described on page 8 of This is the Right function described on page 8 of "Generating Linear Extensions Fast" by Pruesse and Ruskey. Note that this is meant to be called by the generate_linear_extensions method and is not meant to be used directly. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D) Note that this is meant to be called by the list method and is not meant to be used directly. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D) """ Returns a list of the linear extensions of the directed acyclic graph. Note that once they are computed, the linear extensions are Note that once they are computed, the linear extensions are cached in this object. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: LinearExtensions(D).list() """ if self.linear_extensions is not None: return self.linear_extensions[:] self.linear_extensions = [] self.linear_extensions.append(self.le[:]) self.generate_linear_extensions(self.max_pair) self.linear_extensions.sort() return self.linear_extensions[:] def incomparable(self, x, y): """ Returns True if vertices x and y are incomparable in the directed acyclic graph when thought of as a poset. EXAMPLES: EXAMPLES:: sage: from sage.graphs.linearextensions import LinearExtensions sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) sage: l = LinearExtensions(D)
• ## sage/graphs/matchpoly.pyx

diff --git a/sage/graphs/matchpoly.pyx b/sage/graphs/matchpoly.pyx
 a AUTHORS: - Robert Miller, Tom Boothby - original implementation - Robert Miller, Tom Boothby - original implementation REFERENCE: Chris Godsil, Algebraic Combinatorics. Chris Godsil, Algebraic Combinatorics. Methods -------
• ## sage/graphs/schnyder.py

diff --git a/sage/graphs/schnyder.py b/sage/graphs/schnyder.py
 a """ Schnyder's Algorithm for straight-line planar embeddings. """ A module for computing the (x,y) coordinates for a straight-line planar embedding of any connected planar graph with at least three vertices.  Uses embedding of any connected planar graph with at least three vertices.  Uses Walter Schnyder's Algorithm. AUTHORS: """ Helper function to schnyder method for computing coordinates in the plane to plot a planar graph with no edge crossings. Given a connected graph g with at least 3 vertices and a planar combinatorial embedding comb_emb of g, modify g in place to form a graph whose faces are all triangles, and return the set of newly created edges. The simple way to triangulate a face is to just pick a vertex and draw an edge from that vertex to every other vertex in the face. Think that this might ultimately result in graphs that don't look very nice when we draw them a repeat, we keep the first edge of the face and retry the process at the next edge in the face list.  (By removing the special cases we guarantee that this method will work on one of these attempts.) INPUT: g -- the graph to triangulate comb_emb -- a planar combinatorial embedding of g RETURNS: A list of edges that are added to the graph (in place) EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import _triangulate sage: g = Graph(graphs.CycleGraph(4)) sage: g.is_planar(set_embedding=True) raise NotImplementedError("_triangulate() only knows how to handle connected graphs.") if g.order() == 3 and len(g.edges()) == 2:             # if g is o--o--o vertex_list = g.vertices() vertex_list = g.vertices() if len(g.neighbors(vertex_list[0])) == 2:          # figure out which of the vertices already has two neighbors new_edge = (vertex_list[1], vertex_list[2])    # and connect the other two together. elif len(g.neighbors(vertex_list[1])) == 2: new_edge = (vertex_list[0], vertex_list[2]) else: new_edge = (vertex_list[0], vertex_list[1]) g.add_edge(new_edge) return [new_edge] # that it is not the graph o--o--o. This is where the real work starts. faces = g.trace_faces(comb_emb)        # We start by finding all of the faces of this embedding. edges_added = []                        # The list of edges that we add to the graph. # This will be returned at the end. for face in faces: new_face = [] if len(face) < 3: new_face = (face[2][1], face[1][0]) g.add_edge(new_face) edges_added.append(new_face) else: else: N = len(face) i = 0 while i < N-1: """ Helper function to schnyder method for computing coordinates in the plane to plot a planar graph with no edge crossings. Constructs a normal labelling of a triangular graph g, given the planar combinatorial embedding of g and a designated external face.  Returns labels dictionary.  The normal label is constructed by first contracting the graph dictionary.  The normal label is constructed by first contracting the graph down to its external face, then expanding the graph back to the original while simultaneously adding angle labels. INPUT: g -- the graph to find the normal labeling of (g must be triangulated) comb_emb -- a planar combinatorial embedding of g external_face -- the list of three edges in the external face of g RETURNS: x -- tuple with entries x[0] = dict of dicts of normal labeling for each vertex of g and each adjacent neighbors u,v (u < v) of vertex: adjacent neighbors u,v (u < v) of vertex: { vertex : { (u,v): angel_label } } x[1] = (v1,v2,v3) tuple of the three vertices of the external face. EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer sage: g = Graph(graphs.CycleGraph(7)) sage: g.is_planar(set_embedding=True) sage: _realizer(g, tn) ({0: []}, (0, 1, 2)) """ contracted = [] contractible = [] labels = {} external_vertices = [external_face[0][0], external_face[1][0], external_face[2][0]] external_vertices.sort() v1,v2,v3 = external_vertices neighbor_count[v] = 0 for v in g.neighbors(v1): neighbor_count[v] = len(v1_neighbors.intersection( Set(g.neighbors(v)))) for v in v1_neighbors: if v in [v1,v2,v3]: continue if neighbor_count[v] == 2: contractible.append(v) # contraction phase: while g.order() > 3: for w in g.neighbors(v1): if(len(v1_neighbors.intersection( Set(g.neighbors(w))))) == 2 and w not in [v1, v2, v3]: contractible.append(w) # expansion phase: v1, v2, v3 = g.vertices() #always in sorted order if len(neighbors_to_delete) == 0: # we are adding v into the face new_neighbors w1, w2, w3 = sorted(new_neighbors) labels[v] = {(w1, w2): labels[w3].pop((w1,w2)), (w2,w3) : labels[w1].pop((w2,w3)), (w1,w3) : labels[w2].pop((w1,w3))} labels[w1][tuple(sorted((w2,v)))] = labels[v][(w2,w3)] labels[w1][tuple(sorted((w3,v)))] = labels[v][(w2,w3)] else: vertices_in_order.append(angle[0]) angles_out_of_v1.remove(angle) w = vertices_in_order # is w[0] a 2 or a 3? labels[w[i]][ tuple(sorted( (w[i+1], v) )) ] = top_label labels[w[i+1]][ tuple(sorted( (w[i], v) )) ] = bottom_label i = i + 1 labels[v][tuple(sorted( (v1, w[0])))] = bottom_label labels[v][tuple(sorted( (v1, w[-1])))] = top_label labels[w[-1]][tuple(sorted((v1,v)))] = bottom_label labels[v1][tuple(sorted( (w[0],v) ))] = 1 labels[v1][tuple(sorted( (w[-1],v) ))] = 1 #delete all the extra labels for angle in angle_set: labels[w[0]].pop( tuple (sorted( (v1, w[1]) ) )) labels[w[-1]].pop( tuple (sorted( (v1, w[-2]) ) )) i = 1 while i < len(w) - 1: labels[w[i]].pop(tuple(sorted( (v1, w[i+1])))) labels[w[i]].pop(tuple(sorted( (v1, w[i-1])))) labels[w[i]].pop(tuple(sorted( (v1, w[i+1])))) labels[w[i]].pop(tuple(sorted( (v1, w[i-1])))) i = i + 1 for w in new_neighbors: realizer and returns a dictionary of three trees determined by the realizer, each spanning all interior vertices and rooted at one of the three external vertices. A realizer is a directed graph with edge labels that span all interior vertices from each external vertex.  It is determined by giving direction to the edges that have the same angle label on both sides at a vertex. (Thus the direction actually points to the parent in the tree.)  The edge label is set as whatever the matching angle label is.  Then from any interior vertex, following the directed edges by label will any interior vertex, following the directed edges by label will give a path to each of the three external vertices. INPUT: g -- the graph to compute the realizer of x -- tuple with entries x[0] = dict of dicts representing a normal labeling of g.  For each vertex of g and each adjacent neighbors u,v (u < v) of x[0] = dict of dicts representing a normal labeling of g.  For each vertex of g and each adjacent neighbors u,v (u < v) of vertex:  { vertex : { (u,v): angle_label } } x[1] = (v1, v2, v3) tuple of the three external vertices (also the roots of each tree) RETURNS: x -- tuple with entries x[0] = dict of lists of TreeNodes: { root_vertex : [ list of all TreeNodes under root_vertex ] } x[0] = (v1,v2,v3) tuple of the three external vertices (also the roots of each tree) EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer sage: g = Graph(graphs.CycleGraph(7)) sage: g.is_planar(set_embedding=True) sage: _realizer(g, tn) ({0: []}, (0, 1, 2)) """ normal_labeling, (v1, v2, v3) = x realizer = DiGraph() tree_nodes = {} for v in g: tree_nodes[v] = [TreeNode(label = v, children = []), TreeNode(label = v, children = []), TreeNode(label = v, children = [])] for v in g: ones = [] ones.sort() twos.sort() threes.sort() i = 0 while i < len(ones) - 1: if ones[i] == ones[i+1]: i = i + 1 _compute_coordinates(realizer, (tree_nodes, (v1, v2, v3))) if example: realizer.show(talk=True, edge_labels=True) def _compute_coordinates(g, x): """ Given a triangulated graph g with a dict of trees given by the realizer and tuple of the external vertices, we compute the realizer and tuple of the external vertices, we compute the coordinates of a planar geometric embedding in the grid. The coordinates will be set to the _pos attribute of g. INPUT: g -- the graph to compute the coordinates of x -- tuple with entries x[0] = dict of tree nodes for the three trees with each external x[0] = dict of tree nodes for the three trees with each external vertex as root { root_vertex : [ list of all TreeNodes under root_vertex ] } x[1] = (v1, v2, v3) tuple of the three external vertices (also the roots of each tree) EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer, _compute_coordinates sage: g = Graph(graphs.CycleGraph(7)) sage: g.is_planar(set_embedding=True) sage: g.get_pos() {0: [5, 1], 1: [0, 5], 2: [1, 0], 3: [1, 4], 4: [2, 1], 5: [2, 3], 6: [3, 2]} """ tree_nodes, (v1, v2, v3) = x # find the roots of each tree: t1, t2, t3 = tree_nodes[v1][0], tree_nodes[v2][1], tree_nodes[v3][2] if v not in [t1.label,t2.label,t3.label]: # Computing coordinates for v r = list((0,0,0)) for i in [0,1,2]: # Computing size of region i: # Tracing up tree (i + 1) % 3 p = tree_nodes[v][(i + 1) % 3] while p is not None: r[i] += q p = p.parent # Tracing up tree (i - 1) % 3 # Tracing up tree (i - 1) % 3 p = tree_nodes[v][(i - 1) % 3] while p is not None: q = tree_nodes[p.label][i].number_of_descendants # labels on path up tree (i - 1) % 3 r[i] += q p = p.parent q = tree_nodes[v][i].number_of_descendants # Subtracting # Subtracting r[i] -= q # Subtracting # Subtracting q = tree_nodes[v][(i-1)%3].depth r[i] -= q A class to represent each node in the trees used by _realizer() and _compute_coordinates() when finding a planar geometric embedding in the grid. Each tree node is doubly linked to its parent and children. INPUT: parent -- the parent TreeNode of self children -- a list of TreeNode children of self label -- the associated realizer vertex label EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import TreeNode sage: tn = TreeNode(label=5) sage: tn2 = TreeNode(label=2,parent=tn) parent -- the parent TreeNode of self children -- a list of TreeNode children of self label -- the associated realizer vertex label EXAMPLE: EXAMPLE:: sage: from sage.graphs.schnyder import TreeNode sage: tn = TreeNode(label=5) sage: tn2 = TreeNode(label=2,parent=tn) def compute_number_of_descendants(self): """ Computes the number of descendants of self and all descendants. Computes the number of descendants of self and all descendants. For each TreeNode, sets result as attribute self.number_of_descendants EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import TreeNode sage: tn = TreeNode(label=5) sage: tn2 = TreeNode(label=2,parent=tn) n += child.compute_number_of_descendants() self.number_of_descendants = n return n def compute_depth_of_self_and_children(self): """ Computes the depth of self and all descendants. For each TreeNode, sets result as attribute self.depth EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import TreeNode sage: tn = TreeNode(label=5) sage: tn2 = TreeNode(label=2,parent=tn) self.depth = self.parent.depth + 1 for child in self.children: child.compute_depth_of_self_and_children() def append_child(self, child): """ Add a child to list of children. EXAMPLES: EXAMPLES:: sage: from sage.graphs.schnyder import TreeNode sage: tn = TreeNode(label=5) sage: tn2 = TreeNode(label=2,parent=tn)
• ## sage/graphs/trees.pyx

diff --git a/sage/graphs/trees.pyx b/sage/graphs/trees.pyx
 a r""" This is an implementation of the algorithm for generating trees with n vertices Generation of trees This is an implementation of the algorithm for generating trees with n vertices (up to isomorphism) in constant time per tree described in [WRIGHT-ETAL]_. AUTHORS: r""" This class iterates over all trees with n vertices (up to isomorphism). EXAMPLES: EXAMPLES:: sage: from sage.graphs.trees import TreeIterator sage: def check_trees(n): sage: print check_trees(10) True :: sage: from sage.graphs.trees import TreeIterator sage: count = 0 sage: for t in TreeIterator(15): def __init__(self, int vertices): r""" Initializes an iterator over all trees with n vertices. Initializes an iterator over all trees with n vertices. EXAMPLES:: def __dealloc__(self): r""" EXAMPLES: EXAMPLES:: sage: from sage.graphs.trees import TreeIterator sage: t = TreeIterator(100) sage: t = None # indirect doctest def __str__(self): r""" EXAMPLES: EXAMPLES:: sage: from sage.graphs.trees import TreeIterator sage: t = TreeIterator(100) sage: print t # indirect doctest def __iter__(self): r""" Returns an iterator over all the trees with n vertices. Returns an iterator over all the trees with n vertices. EXAMPLES: EXAMPLES:: sage: from sage.graphs.trees import TreeIterator sage: t = TreeIterator(4) sage: list(iter(t)) def __next__(self): r""" Returns the next tree with n vertices Returns the next tree with n vertices EXAMPLES: EXAMPLES:: sage: from sage.graphs.trees import TreeIterator sage: T = TreeIterator(5) sage: [t for t in T] # indirect doctest cdef int generate_first_level_sequence(self): r""" Generates the level sequence representing the first tree with n vertices Generates the level sequence representing the first tree with n vertices """ cdef int i cdef int k cdef int generate_next_level_sequence(self): r""" Generates the level sequence representing the next tree with n vertices Generates the level sequence representing the next tree with n` vertices """ cdef int i cdef int fixit = 0 self.l = l self.current_level_sequence = w return 0 No newline at end of file return 0