# 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
|
b
|
|
10 | 10 | |
11 | 11 | sage/graphs/generic_graph |
12 | 12 | sage/graphs/graph |
13 | | sage/graphs/graph_plot |
14 | 13 | sage/graphs/digraph |
15 | 14 | sage/graphs/bipartite_graph |
16 | 15 | |
… |
… |
|
51 | 50 | sage/graphs/comparability |
52 | 51 | sage/graphs/spanning_tree |
53 | 52 | sage/graphs/pq_trees |
| 53 | sage/graphs/trees |
54 | 54 | sage/graphs/matchpoly |
| 55 | sage/graphs/linearextensions |
| 56 | sage/graphs/schnyder |
| 57 | sage/graphs/graph_plot |
55 | 58 | sage/graphs/graph_decompositions/vertex_separation |
56 | 59 | sage/graphs/graph_decompositions/rankwidth |
57 | 60 | sage/graphs/modular_decomposition/modular_decomposition |
diff --git a/sage/graphs/all.py b/sage/graphs/all.py
a
|
b
|
|
22 | 22 | import sage.graphs.isgci |
23 | 23 | from sage.graphs.isgci import graph_classes |
24 | 24 | import sage.graphs.distances_all_pairs |
| 25 | import sage.graphs.trees |
| 26 | import sage.graphs.graph_latex |
diff --git a/sage/graphs/base/c_graph.pyx b/sage/graphs/base/c_graph.pyx
a
|
b
|
|
226 | 226 | |
227 | 227 | .. SEEALSO:: |
228 | 228 | |
229 | | - :meth:`add_vertex_unsafe` |
230 | | -- add a vertex to a graph. This method is potentially unsafe. |
231 | | You should instead use :meth:`add_vertex`. |
232 | | |
233 | | - :meth:`add_vertices` |
234 | | -- add a bunch of vertices to a graph. |
| 229 | - ``add_vertex_unsafe`` -- add a vertex to a graph. This |
| 230 | method is potentially unsafe. You should instead use |
| 231 | :meth:`add_vertex`. |
| 232 | |
| 233 | - ``add_vertices`` -- add a bunch of vertices to a graph. |
235 | 234 | |
236 | 235 | EXAMPLES: |
237 | 236 | |
… |
… |
|
439 | 438 | |
440 | 439 | .. SEEALSO:: |
441 | 440 | |
442 | | - :meth:`del_vertex_unsafe` |
443 | | -- delete a vertex from a graph. This method is potentially |
444 | | unsafe. Use :meth:`del_vertex` instead. |
| 441 | - ``del_vertex_unsafe`` -- delete a vertex from a graph. This method |
| 442 | is potentially unsafe. Use :meth:`del_vertex` instead. |
445 | 443 | |
446 | 444 | EXAMPLES: |
447 | 445 | |
… |
… |
|
853 | 851 | raise NotImplementedError() |
854 | 852 | |
855 | 853 | cdef int * adjacency_sequence_in(self, int n, int *vertices, int v): |
856 | | r""" |
| 854 | r""" |
857 | 855 | Returns the adjacency sequence corresponding to a list of vertices |
858 | | and a vertex. |
| 856 | and a vertex. |
859 | 857 | |
860 | 858 | See the OUTPUT section for a formal definition. |
861 | 859 | |
862 | 860 | See the function ``_test_adjacency_sequence()`` of |
863 | 861 | ``dense_graph.pyx`` and ``sparse_graph.pyx`` for unit tests. |
864 | | |
865 | | INPUT: |
| 862 | |
| 863 | INPUT: |
866 | 864 | |
867 | 865 | - ``n`` -- nonnegative integer; the maximum index in |
868 | 866 | ``vertices`` up to which we want to consider. If ``n = 0``, |
diff --git a/sage/graphs/base/static_sparse_graph.pyx b/sage/graphs/base/static_sparse_graph.pyx
a
|
b
|
|
401 | 401 | bitset_intersection(scc, scc, scc_reversed) |
402 | 402 | |
403 | 403 | cdef void free_short_digraph(short_digraph g): |
404 | | |
| 404 | |
405 | 405 | if g.edges != NULL: |
406 | 406 | sage_free(g.edges) |
407 | 407 | |
… |
… |
|
419 | 419 | .. NOTE:: |
420 | 420 | |
421 | 421 | This method has been written as an attempt to solve the slowness |
422 | | reported in #12235. It is not the one used by |
423 | | :meth:`sage.graphs.digraph.strongly_connected_components` as saving some |
424 | | time on the computation of the strongly connected components is not |
425 | | worth copying the whole graph, but it is a nice way to test this |
| 422 | reported in :trac:`12235`. It is not the one used by |
| 423 | :meth:`sage.graphs.digraph.DiGraph.strongly_connected_components` as |
| 424 | saving some time on the computation of the strongly connected components |
| 425 | is not worth copying the whole graph, but it is a nice way to test this |
426 | 426 | module's functions. It is also tested in the doctest or |
427 | | :meth:`sage.graphs.digraph.strongly_connected_components`. |
| 427 | :meth:`sage.graphs.digraph.DiGraph.strongly_connected_components`. |
428 | 428 | |
429 | 429 | EXAMPLE:: |
430 | 430 | |
431 | 431 | sage: from sage.graphs.base.static_sparse_graph import strongly_connected_components |
432 | 432 | sage: g = digraphs.ButterflyGraph(2) |
433 | 433 | sage: strongly_connected_components(g) |
434 | | [[('00', 0)], [('00', 1)], [('00', 2)], [('01', 0)], [('01', 1)], [('01', 2)], |
| 434 | [[('00', 0)], [('00', 1)], [('00', 2)], [('01', 0)], [('01', 1)], [('01', 2)], |
435 | 435 | [('10', 0)], [('10', 1)], [('10', 2)], [('11', 0)], [('11', 1)], [('11', 2)]] |
436 | 436 | """ |
437 | 437 | |
… |
… |
|
467 | 467 | strongly_connected_component_containing_vertex(g, gr, v, scc) |
468 | 468 | answer.append([vertices[i] for i in bitset_list(scc)]) |
469 | 469 | bitset_union(seen, seen, scc) |
470 | | |
| 470 | |
471 | 471 | bitset_free(seen) |
472 | 472 | bitset_free(scc) |
473 | 473 | free_short_digraph(g) |
diff --git a/sage/graphs/digraph.py b/sage/graphs/digraph.py
a
|
b
|
|
2724 | 2724 | set decomposition of the graph (see :meth:`.level_sets`). |
2725 | 2725 | |
2726 | 2726 | This is achieved by calling ``graphviz`` and ``dot2tex`` if available |
2727 | | (see :meth:`.layout_acyclic_graphviz`), and using a random horizontal |
| 2727 | (see :meth:`.layout_graphviz`), and using a random horizontal |
2728 | 2728 | placement of the vertices otherwise (see :meth:`.layout_acyclic_dummy`). |
2729 | 2729 | |
2730 | 2730 | Non acyclic graphs are partially supported by ``graphviz``, which then |
diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
a
|
b
|
|
12468 | 12468 | Multiple starting vertices can be specified in a list:: |
12469 | 12469 | |
12470 | 12470 | sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) |
12471 | | sage: list(D.breadth_first_search([0])) |
| 12471 | sage: list(D.breadth_first_search([0])) |
12472 | 12472 | [0, 1, 2, 3, 4, 5, 6, 7] |
12473 | 12473 | sage: list(D.breadth_first_search([0,6])) |
12474 | 12474 | [0, 6, 1, 2, 3, 7, 4, 5] |
… |
… |
|
12478 | 12478 | [0, 6, 1, 2, 3, 7] |
12479 | 12479 | sage: list(D.breadth_first_search(6,ignore_direction=True,distance=2)) |
12480 | 12480 | [6, 3, 7, 0, 5] |
12481 | | |
| 12481 | |
12482 | 12482 | More generally, you can specify a ``neighbors`` function. For |
12483 | 12483 | example, you can traverse the graph backwards by setting |
12484 | | ``neighbors`` to be the :meth:`.predecessor` function of the graph:: |
12485 | | |
| 12484 | ``neighbors`` to be the :meth:`.neighbors_in` function of the graph:: |
| 12485 | |
12486 | 12486 | sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) |
12487 | 12487 | sage: list(D.breadth_first_search(5,neighbors=D.neighbors_in, distance=2)) |
12488 | 12488 | [5, 1, 2, 0] |
12489 | | sage: list(D.breadth_first_search(5,neighbors=D.neighbors_out, distance=2)) |
| 12489 | sage: list(D.breadth_first_search(5,neighbors=D.neighbors_out, distance=2)) |
12490 | 12490 | [5, 7, 0] |
12491 | | sage: list(D.breadth_first_search(5,neighbors=D.neighbors, distance=2)) |
| 12491 | sage: list(D.breadth_first_search(5,neighbors=D.neighbors, distance=2)) |
12492 | 12492 | [5, 1, 2, 7, 0, 4, 6] |
12493 | 12493 | |
12494 | 12494 | |
… |
… |
|
12501 | 12501 | [0, 1, 2] |
12502 | 12502 | |
12503 | 12503 | """ |
12504 | | # Preferably use the Cython implementation |
12505 | | if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"breadth_first_search"): |
12506 | | for v in self._backend.breadth_first_search(start, ignore_direction = ignore_direction): |
12507 | | yield v |
12508 | | else: |
| 12504 | # Preferably use the Cython implementation |
| 12505 | if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"breadth_first_search"): |
| 12506 | for v in self._backend.breadth_first_search(start, ignore_direction = ignore_direction): |
| 12507 | yield v |
| 12508 | else: |
12509 | 12509 | if neighbors is None: |
12510 | 12510 | if not self._directed or ignore_direction: |
12511 | | neighbors=self.neighbor_iterator |
| 12511 | neighbors=self.neighbor_iterator |
12512 | 12512 | else: |
12513 | 12513 | neighbors=self.neighbor_out_iterator |
12514 | 12514 | seen=set([]) |
… |
… |
|
12607 | 12607 | |
12608 | 12608 | More generally, you can specify a ``neighbors`` function. For |
12609 | 12609 | example, you can traverse the graph backwards by setting |
12610 | | ``neighbors`` to be the :meth:`.predecessor` function of the graph:: |
| 12610 | ``neighbors`` to be the :meth:`.neighbors_in` function of the graph:: |
12611 | 12611 | |
12612 | 12612 | sage: D = DiGraph( { 0: [1,2,3], 1: [4,5], 2: [5], 3: [6], 5: [7], 6: [7], 7: [0]}) |
12613 | 12613 | sage: list(D.depth_first_search(5,neighbors=D.neighbors_in, distance=2)) |
… |
… |
|
13787 | 13787 | :meth:`.layout_graphviz` for installation instructions. |
13788 | 13788 | |
13789 | 13789 | A subclass may implement another layout algorithm `blah`, by |
13790 | | implementing a method :meth:`.layout_blah`. It may override |
| 13790 | implementing a method ``.layout_blah``. It may override |
13791 | 13791 | the default layout by overriding :meth:`.layout_default`, and |
13792 | 13792 | similarly override the predefined layouts. |
13793 | 13793 | |
… |
… |
|
15207 | 15207 | INPUT: |
15208 | 15208 | |
15209 | 15209 | - ``laplacian`` - if ``True``, use the Laplacian matrix |
15210 | | (see :meth:`~sage.graphs.graph.GenericGraph.kirchhoff_matrix()`) |
| 15210 | (see :meth:`kirchhoff_matrix`) |
15211 | 15211 | |
15212 | 15212 | OUTPUT: |
15213 | 15213 | |
… |
… |
|
15315 | 15315 | INPUT: |
15316 | 15316 | |
15317 | 15317 | - ``laplacian`` - if True, use the Laplacian matrix |
15318 | | (see :meth:`~sage.graphs.graph.GenericGraph.kirchhoff_matrix()`) |
| 15318 | (see :meth:`kirchhoff_matrix`) |
15319 | 15319 | |
15320 | 15320 | OUTPUT: |
15321 | 15321 | |
… |
… |
|
15406 | 15406 | INPUT: |
15407 | 15407 | |
15408 | 15408 | - ``laplacian`` - if True, use the Laplacian matrix |
15409 | | (see :meth:`~sage.graphs.graph.GenericGraph.kirchhoff_matrix()`) |
| 15409 | (see :meth:`kirchhoff_matrix`) |
15410 | 15410 | |
15411 | 15411 | OUTPUT: |
15412 | 15412 | |
diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
a
|
b
|
|
3065 | 3065 | for h in H: |
3066 | 3066 | for u,v in self.edges(labels=None): |
3067 | 3067 | p.add_constraint(r_edges[h][(u,v)] + r_edges[h][(v,u)] - edges[h][S((u,v))], min = 0) |
3068 | | |
| 3068 | |
3069 | 3069 | for v in self: |
3070 | 3070 | p.add_constraint(Sum([r_edges[h][(u,v)] for u in self.neighbors(v)]), max = 1-epsilon) |
3071 | 3071 | |
… |
… |
|
3109 | 3109 | Returns an rank-decomposition of ``self`` achieving optiml rank-width. |
3110 | 3110 | |
3111 | 3111 | See the documentation of the ``rankwidth`` module |
3112 | | :class:`<rankwidth sage.graphs.graph_decompositions.rankwidth>`. |
| 3112 | :mod:`rankwidth <sage.graphs.graph_decompositions.rankwidth>`. |
3113 | 3113 | |
3114 | 3114 | INPUT: |
3115 | 3115 | |
… |
… |
|
3124 | 3124 | |
3125 | 3125 | See the documentation of the ``rankwidth`` module for more information |
3126 | 3126 | on the tree |
3127 | | :class:`rankwidth <sage.graphs.graph_decompositions.rankwidth.`. |
| 3127 | :mod:`rankwidth <sage.graphs.graph_decompositions.rankwidth>`. |
3128 | 3128 | |
3129 | 3129 | .. WARNING:: |
3130 | 3130 | |
… |
… |
|
3470 | 3470 | obtained from `H` through arbitrary subdivision of its edges) |
3471 | 3471 | as a subgraph. |
3472 | 3472 | |
3473 | | For more information, see the `Wikipedia article on graph |
3474 | | minor |
3475 | | <http://en.wikipedia.org/wiki/Minor_%28graph_theory%29>`_. |
| 3473 | For more information, see the `Wikipedia article on graph minor |
| 3474 | :wikipedia:`Minor_(graph_theory)`. |
3476 | 3475 | |
3477 | 3476 | INPUT: |
3478 | 3477 | |
… |
… |
|
3494 | 3493 | The topological `H`-minor found is returned as a subgraph `M` |
3495 | 3494 | of ``self``, such that the vertex `v` of `M` that represents a |
3496 | 3495 | vertex `h\in H` has ``h`` as a label (see |
3497 | | :meth:`get_vertex <sage.graphs.generic_graph.get_vertex>` |
| 3496 | :meth:`get_vertex <sage.graphs.generic_graph.GenericGraph.get_vertex>` |
3498 | 3497 | and |
3499 | | :meth:`set_vertex <sage.graphs.generic_graph.set_vertex>`), |
| 3498 | :meth:`set_vertex <sage.graphs.generic_graph.GenericGraph.set_vertex>`), |
3500 | 3499 | and such that every edge of `M` has as a label the edge of `H` |
3501 | 3500 | it (partially) represents. |
3502 | 3501 | |
… |
… |
|
3514 | 3513 | are highly exponential in `H`, though. |
3515 | 3514 | |
3516 | 3515 | .. NOTE:: |
3517 | | |
| 3516 | |
3518 | 3517 | * This function can be expected to be *very* slow, especially |
3519 | 3518 | where the topological minor does not exist. |
3520 | 3519 | |
… |
… |
|
3548 | 3547 | from sage.numerical.mip import MixedIntegerLinearProgram, Sum, MIPSolverException |
3549 | 3548 | p = MixedIntegerLinearProgram() |
3550 | 3549 | |
3551 | | # This is an existence problem |
| 3550 | # This is an existence problem |
3552 | 3551 | p.set_objective(None) |
3553 | 3552 | |
3554 | 3553 | ####################### |
diff --git a/sage/graphs/graph_decompositions/rankwidth.pyx b/sage/graphs/graph_decompositions/rankwidth.pyx
a
|
b
|
|
132 | 132 | |
133 | 133 | def rank_decomposition(G, verbose = False): |
134 | 134 | r""" |
135 | | Computes an optiml rank-decomposition of the given graph. |
| 135 | Computes an optimal rank-decomposition of the given graph. |
136 | 136 | |
137 | | This function is available as a method of the |
138 | | :class:`Graph <sage.graphs.graph>` class. See |
139 | | :meth:`rank_decomposition <sage.graphs.graph.rank_decomposition>`. |
| 137 | This function is available as a method of the :class:`Graph |
| 138 | <sage.graphs.graph>` class. See :meth:`rank_decomposition |
| 139 | <sage.graphs.graph.Graph.rank_decomposition>`. |
140 | 140 | |
141 | 141 | INPUT: |
142 | 142 | |
… |
… |
|
304 | 304 | r""" |
305 | 305 | Returns the graph corresponding the the current rank-decomposition. |
306 | 306 | |
307 | | (This function is for interna use) |
| 307 | (This function is for internal use) |
308 | 308 | |
309 | 309 | EXAMPLE:: |
310 | 310 | |
diff --git a/sage/graphs/graph_generators.py b/sage/graphs/graph_generators.py
a
|
b
|
|
7608 | 7608 | 0: [1, 2, 3, 4], |
7609 | 7609 | 1: [2, 3, 4], |
7610 | 7610 | 3: [4], |
7611 | | 5: [2, 0, 1] |
| 7611 | 5: [2, 0, 1] |
7612 | 7612 | })) |
7613 | 7613 | |
7614 | 7614 | graphs.append(Graph({ |
diff --git a/sage/graphs/graph_latex.py b/sage/graphs/graph_latex.py
a
|
b
|
|
392 | 392 | should call this once as having random output to exhaust the |
393 | 393 | warnings before testing output. |
394 | 394 | |
395 | | See also :meth:`sage.misc.latex.check_file` |
| 395 | See also :meth:`sage.misc.latex.Latex.check_file` |
396 | 396 | |
397 | 397 | TESTS:: |
398 | 398 | |
… |
… |
|
418 | 418 | |
419 | 419 | The result is cached. |
420 | 420 | |
421 | | See also :meth:`sage.misc.latex.has_file` |
| 421 | See also :meth:`sage.misc.latex.Latex.has_file` |
422 | 422 | |
423 | 423 | TESTS:: |
424 | 424 | |
… |
… |
|
437 | 437 | graphs(``tikz``, ``tkz-graph``, ``tkz-berge``), if available |
438 | 438 | in the ``LaTeX`` installation. |
439 | 439 | |
440 | | See also :meth:`sage.misc.latex.add_package_to_preamble_if_available`. |
441 | | |
| 440 | See also :meth:`sage.misc.latex.Latex.add_package_to_preamble_if_available`. |
| 441 | |
442 | 442 | EXAMPLES:: |
443 | 443 | |
444 | 444 | sage: sage.graphs.graph_latex.setup_latex_preamble() |
… |
… |
|
597 | 597 | Sets, modifies, clears a LaTeX |
598 | 598 | option for controlling the rendering of a graph. |
599 | 599 | |
600 | | The possible options are documented here, because ultimately |
601 | | it is this routine that sets the values. However, the |
602 | | :meth:`sage.graphs.generic_graph.Graph.set_latex_options` method |
603 | | is the easiest way to set options, and allows several to |
604 | | be set at once. |
| 600 | The possible options are documented here, because ultimately it is this |
| 601 | routine that sets the values. However, the |
| 602 | :meth:`sage.graphs.generic_graph.GenericGraph.set_latex_options` method |
| 603 | is the easiest way to set options, and allows several to be set at once. |
605 | 604 | |
606 | 605 | INPUTS: |
607 | 606 | |
608 | | - ``option_name`` - a string for a latex option contained in |
609 | | the list :data:`__graphlatex_options`. A ``ValueError`` is |
610 | | raised if the option is not allowed. |
| 607 | - ``option_name`` - a string for a latex option contained in the list |
| 608 | ``sage.graphs.graph_latex.GraphLatex.__graphlatex_options``. A |
| 609 | ``ValueError`` is raised if the option is not allowed. |
611 | 610 | |
612 | 611 | - ``option_value`` - a value for the option. If omitted, or |
613 | 612 | set to ``None``, the option will use the default value. |
… |
… |
|
888 | 887 | ... |
889 | 888 | ValueError: bad_name is not a LaTeX option for a graph. |
890 | 889 | |
891 | | See :meth:`Graph.layout_graphviz` for installation |
892 | | instructions for ``graphviz`` and ``dot2tex``. Further more, |
893 | | pgf >= 2.00 should be available inside LaTeX's tree for LaTeX |
894 | | compilation (e.g. when using ``view``). In case your LaTeX |
895 | | distribution does not provide it, here are short instructions: |
| 890 | See :meth:`sage.graphs.generic_graph.GenericGraph.layout_graphviz` for |
| 891 | installation instructions for ``graphviz`` and ``dot2tex``. Further |
| 892 | more, pgf >= 2.00 should be available inside LaTeX's tree for LaTeX |
| 893 | compilation (e.g. when using ``view``). In case your LaTeX distribution |
| 894 | does not provide it, here are short instructions: |
896 | 895 | |
897 | 896 | - download pgf from http://sourceforge.net/projects/pgf/ |
898 | 897 | - unpack it in ``/usr/share/texmf/tex/generic`` (depends on your system) |
… |
… |
|
1236 | 1235 | OUTPUT: |
1237 | 1236 | |
1238 | 1237 | If the name is not present in |
1239 | | :data:`sage.graphs.graph_latex.__graphlatex_options` it is an |
| 1238 | ``__graphlatex_options`` it is an |
1240 | 1239 | error to ask for it. If an option has not been set then the |
1241 | 1240 | default value is returned. Otherwise, the value of the |
1242 | 1241 | option is returned. |
… |
… |
|
1269 | 1268 | Returns a string in LaTeX representing a graph. |
1270 | 1269 | |
1271 | 1270 | This is the command that is invoked by |
1272 | | :meth:`~sage.graphs.graph.GenericGraph._latex_` for |
1273 | | a graph, so it returns a string of |
1274 | | LaTeX commands that can be incorporated |
1275 | | into a LaTeX document unmodified. The exact contents |
1276 | | of this string are influenced by the options set via the methods |
1277 | | :meth:`sage.graphs.graph.GenericGraph.set_latex_options`, |
| 1271 | ``sage.graphs.generic_graph.GenericGraph._latex_`` for a graph, so |
| 1272 | it returns a string of LaTeX commands that can be incorporated into a |
| 1273 | LaTeX document unmodified. The exact contents of this string are |
| 1274 | influenced by the options set via the methods |
| 1275 | :meth:`sage.graphs.generic_graph.GenericGraph.set_latex_options`, |
1278 | 1276 | :meth:`set_option`, and :meth:`set_options`. |
1279 | 1277 | |
1280 | | By setting the ``format`` option different packages can be used |
1281 | | to create the latex version of a graph. Supported packages are |
| 1278 | By setting the ``format`` option different packages can be used to |
| 1279 | create the latex version of a graph. Supported packages are |
1282 | 1280 | ``tkz-graph`` and ``dot2tex``. |
1283 | 1281 | |
1284 | 1282 | EXAMPLES:: |
diff --git a/sage/graphs/graph_plot.py b/sage/graphs/graph_plot.py
a
|
b
|
|
151 | 151 | |
152 | 152 | Make sure that vertex locations are floats. Not being floats |
153 | 153 | isn't a bug in itself but makes it too easy to accidentally |
154 | | introduce a bug elsewhere, such as in set_edges (trac #10124), |
| 154 | introduce a bug elsewhere, such as in set_edges (:trac:`10124`), |
155 | 155 | via silent truncating division of integers:: |
156 | 156 | |
157 | 157 | sage: g = graphs.FruchtGraph() |
… |
… |
|
313 | 313 | sage: G.show(edge_colors={'red':[(3,6),(2,5)]}) |
314 | 314 | |
315 | 315 | Verify that default edge labels are pretty close to being between the vertices |
316 | | in some cases where they weren't due to truncating division (trac #10124):: |
| 316 | in some cases where they weren't due to truncating division (:trac:`10124`):: |
317 | 317 | |
318 | 318 | sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph() |
319 | 319 | sage: tol = 0.001 |
… |
… |
|
514 | 514 | |
515 | 515 | TESTS: |
516 | 516 | |
517 | | Make sure that Python ints are acceptable arguments (trac #10124):: |
| 517 | Make sure that Python ints are acceptable arguments (:trac:`10124`):: |
518 | 518 | |
519 | 519 | sage: GP = DiGraph().graphplot() |
520 | 520 | sage: GP._polar_hack_for_multidigraph((0, 1), (2, 2), .1) |
diff --git a/sage/graphs/linearextensions.py b/sage/graphs/linearextensions.py
a
|
b
|
|
3 | 3 | |
4 | 4 | A linear extension of a directed acyclic graph is a total (linear) ordering on |
5 | 5 | the vertices that is compatible with the graph in the following sense: |
6 | | if there is a path from x to y in the graph, the x appears before y in the |
| 6 | if there is a path from x to y in the graph, the x appears before y in the |
7 | 7 | linear extension. |
8 | 8 | |
9 | 9 | The algorithm implemented in this module is from "Generating Linear Extensions |
10 | | Fast" by Preusse and Ruskey, which can be found at |
| 10 | Fast" by Preusse and Ruskey, which can be found at |
11 | 11 | http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.52.3057 . The algorithm |
12 | 12 | generates the extensions in constant amortized time (CAT) -- a constant amount |
13 | | of time per extension generated, or linear in the number of extensions |
| 13 | of time per extension generated, or linear in the number of extensions |
14 | 14 | generated. |
15 | 15 | |
16 | 16 | EXAMPLES: |
| 17 | |
17 | 18 | Here we generate the 5 linear extensions of the following directed |
18 | | acyclic graph. |
| 19 | acyclic graph:: |
| 20 | |
19 | 21 | sage: from sage.graphs.linearextensions import LinearExtensions |
20 | 22 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
21 | 23 | sage: D.is_directed_acyclic() |
… |
… |
|
31 | 33 | induced from the graph. |
32 | 34 | |
33 | 35 | We can also get at the linear extensions directly from the graph. From |
34 | | the graph, the linear extensions are known as topological sorts. |
| 36 | the graph, the linear extensions are known as topological sorts :: |
| 37 | |
35 | 38 | sage: D.topological_sort_generator() |
36 | 39 | [[0, 1, 2, 3, 4], |
37 | 40 | [0, 1, 2, 4, 3], |
… |
… |
|
62 | 65 | |
63 | 66 | This is an in-place algorithm and the list self.le keeps track |
64 | 67 | of the current linear extensions. The boolean variable self.is_plus |
65 | | keeps track of the "sign". |
| 68 | keeps track of the "sign". |
66 | 69 | |
67 | | EXAMPLES: |
| 70 | EXAMPLES:: |
| 71 | |
68 | 72 | sage: from sage.graphs.linearextensions import LinearExtensions |
69 | 73 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
70 | 74 | sage: l = LinearExtensions(D) |
71 | 75 | sage: l == loads(dumps(l)) |
72 | 76 | True |
73 | | |
| 77 | |
74 | 78 | """ |
75 | 79 | ################ |
76 | 80 | #Precomputation# |
… |
… |
|
113 | 117 | self.is_plus = True |
114 | 118 | self.linear_extensions = None |
115 | 119 | self._name = "Linear extensions of %s"%dag |
116 | | |
| 120 | |
117 | 121 | |
118 | 122 | def switch(self, i): |
119 | 123 | """ |
120 | 124 | This implements the Switch procedure described on page 7 |
121 | 125 | of "Generating Linear Extensions Fast" by Pruesse and Ruskey. |
122 | 126 | |
123 | | If i == -1, then the sign is changed. If i > 0, then self.a[i] |
| 127 | If i == -1, then the sign is changed. If i > 0, then self.a[i] |
124 | 128 | and self.b[i] are transposed. |
125 | 129 | |
126 | 130 | Note that this meant to be called by the generate_linear_extensions |
127 | 131 | method and is not meant to be used directly. |
128 | | |
129 | | EXAMPLES: |
| 132 | |
| 133 | EXAMPLES:: |
| 134 | |
130 | 135 | sage: from sage.graphs.linearextensions import LinearExtensions |
131 | 136 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
132 | 137 | sage: l = LinearExtensions(D) |
… |
… |
|
171 | 176 | of "Generating Linear Extensions Fast" by Pruesse and Ruskey. |
172 | 177 | |
173 | 178 | If direction is "left", then this transposes element with the |
174 | | element on its left. If the direction is "right", then this |
| 179 | element on its left. If the direction is "right", then this |
175 | 180 | transposes element with the element on its right. |
176 | | |
| 181 | |
177 | 182 | Note that this is meant to be called by the generate_linear_extensions |
178 | 183 | method and is not meant to be used directly. |
179 | 184 | |
180 | | EXAMPLES: |
| 185 | EXAMPLES:: |
| 186 | |
181 | 187 | sage: from sage.graphs.linearextensions import LinearExtensions |
182 | 188 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
183 | 189 | sage: l = LinearExtensions(D) |
… |
… |
|
209 | 215 | """ |
210 | 216 | If letter =="b", then this returns True if and only if |
211 | 217 | self.b[i] is incomparable with the elements to its right |
212 | | in self.le. If letter == "a", then it returns True if |
| 218 | in self.le. If letter == "a", then it returns True if |
213 | 219 | and only if self.a[i] is incomparable with the element to its |
214 | 220 | right in self.le and the element to the right is not |
215 | 221 | self.b[i] |
216 | | |
217 | | This is the Right function described on page 8 of |
| 222 | |
| 223 | This is the Right function described on page 8 of |
218 | 224 | "Generating Linear Extensions Fast" by Pruesse and Ruskey. |
219 | 225 | |
220 | 226 | Note that this is meant to be called by the generate_linear_extensions |
221 | 227 | method and is not meant to be used directly. |
222 | 228 | |
223 | | EXAMPLES: |
| 229 | EXAMPLES:: |
| 230 | |
224 | 231 | sage: from sage.graphs.linearextensions import LinearExtensions |
225 | 232 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
226 | 233 | sage: l = LinearExtensions(D) |
… |
… |
|
270 | 277 | Note that this is meant to be called by the list |
271 | 278 | method and is not meant to be used directly. |
272 | 279 | |
273 | | EXAMPLES: |
| 280 | EXAMPLES:: |
| 281 | |
274 | 282 | sage: from sage.graphs.linearextensions import LinearExtensions |
275 | 283 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
276 | 284 | sage: l = LinearExtensions(D) |
… |
… |
|
322 | 330 | """ |
323 | 331 | Returns a list of the linear extensions of the directed acyclic graph. |
324 | 332 | |
325 | | Note that once they are computed, the linear extensions are |
| 333 | Note that once they are computed, the linear extensions are |
326 | 334 | cached in this object. |
327 | 335 | |
328 | | EXAMPLES: |
| 336 | EXAMPLES:: |
| 337 | |
329 | 338 | sage: from sage.graphs.linearextensions import LinearExtensions |
330 | 339 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
331 | 340 | sage: LinearExtensions(D).list() |
… |
… |
|
337 | 346 | """ |
338 | 347 | if self.linear_extensions is not None: |
339 | 348 | return self.linear_extensions[:] |
340 | | |
| 349 | |
341 | 350 | self.linear_extensions = [] |
342 | 351 | self.linear_extensions.append(self.le[:]) |
343 | 352 | self.generate_linear_extensions(self.max_pair) |
… |
… |
|
346 | 355 | self.linear_extensions.sort() |
347 | 356 | return self.linear_extensions[:] |
348 | 357 | |
349 | | |
| 358 | |
350 | 359 | def incomparable(self, x, y): |
351 | 360 | """ |
352 | 361 | Returns True if vertices x and y are incomparable in the directed |
353 | 362 | acyclic graph when thought of as a poset. |
354 | 363 | |
355 | | EXAMPLES: |
| 364 | EXAMPLES:: |
| 365 | |
356 | 366 | sage: from sage.graphs.linearextensions import LinearExtensions |
357 | 367 | sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] }) |
358 | 368 | sage: l = LinearExtensions(D) |
diff --git a/sage/graphs/matchpoly.pyx b/sage/graphs/matchpoly.pyx
a
|
b
|
|
13 | 13 | |
14 | 14 | AUTHORS: |
15 | 15 | |
16 | | - Robert Miller, Tom Boothby - original implementation |
| 16 | - Robert Miller, Tom Boothby - original implementation |
17 | 17 | |
18 | 18 | REFERENCE: |
19 | | Chris Godsil, Algebraic Combinatorics. |
| 19 | Chris Godsil, Algebraic Combinatorics. |
20 | 20 | |
21 | 21 | Methods |
22 | 22 | ------- |
diff --git a/sage/graphs/schnyder.py b/sage/graphs/schnyder.py
a
|
b
|
|
| 1 | """ |
| 2 | Schnyder's Algorithm for straight-line planar embeddings. |
1 | 3 | |
2 | | """ |
3 | 4 | A module for computing the (x,y) coordinates for a straight-line planar |
4 | | embedding of any connected planar graph with at least three vertices. Uses |
| 5 | embedding of any connected planar graph with at least three vertices. Uses |
5 | 6 | Walter Schnyder's Algorithm. |
6 | 7 | |
7 | 8 | AUTHORS: |
… |
… |
|
26 | 27 | """ |
27 | 28 | Helper function to schnyder method for computing coordinates in the plane to |
28 | 29 | plot a planar graph with no edge crossings. |
29 | | |
| 30 | |
30 | 31 | Given a connected graph g with at least 3 vertices and a planar combinatorial |
31 | 32 | embedding comb_emb of g, modify g in place to form a graph whose faces are |
32 | 33 | all triangles, and return the set of newly created edges. |
33 | | |
| 34 | |
34 | 35 | The simple way to triangulate a face is to just pick a vertex and draw |
35 | 36 | an edge from that vertex to every other vertex in the face. Think that this |
36 | 37 | might ultimately result in graphs that don't look very nice when we draw them |
… |
… |
|
39 | 40 | a repeat, we keep the first edge of the face and retry the process at the next |
40 | 41 | edge in the face list. (By removing the special cases we guarantee that this |
41 | 42 | method will work on one of these attempts.) |
42 | | |
| 43 | |
43 | 44 | INPUT: |
44 | 45 | g -- the graph to triangulate |
45 | 46 | comb_emb -- a planar combinatorial embedding of g |
46 | | |
| 47 | |
47 | 48 | RETURNS: |
48 | 49 | A list of edges that are added to the graph (in place) |
49 | | |
50 | | EXAMPLES: |
| 50 | |
| 51 | EXAMPLES:: |
| 52 | |
51 | 53 | sage: from sage.graphs.schnyder import _triangulate |
52 | 54 | sage: g = Graph(graphs.CycleGraph(4)) |
53 | 55 | sage: g.is_planar(set_embedding=True) |
… |
… |
|
68 | 70 | raise NotImplementedError("_triangulate() only knows how to handle connected graphs.") |
69 | 71 | |
70 | 72 | if g.order() == 3 and len(g.edges()) == 2: # if g is o--o--o |
71 | | vertex_list = g.vertices() |
| 73 | vertex_list = g.vertices() |
72 | 74 | if len(g.neighbors(vertex_list[0])) == 2: # figure out which of the vertices already has two neighbors |
73 | 75 | new_edge = (vertex_list[1], vertex_list[2]) # and connect the other two together. |
74 | 76 | elif len(g.neighbors(vertex_list[1])) == 2: |
75 | 77 | new_edge = (vertex_list[0], vertex_list[2]) |
76 | 78 | else: |
77 | 79 | new_edge = (vertex_list[0], vertex_list[1]) |
78 | | |
| 80 | |
79 | 81 | g.add_edge(new_edge) |
80 | 82 | return [new_edge] |
81 | 83 | |
… |
… |
|
83 | 85 | # that it is not the graph o--o--o. This is where the real work starts. |
84 | 86 | |
85 | 87 | faces = g.trace_faces(comb_emb) # We start by finding all of the faces of this embedding. |
86 | | |
| 88 | |
87 | 89 | edges_added = [] # The list of edges that we add to the graph. |
88 | 90 | # This will be returned at the end. |
89 | | |
90 | | |
| 91 | |
| 92 | |
91 | 93 | for face in faces: |
92 | 94 | new_face = [] |
93 | 95 | if len(face) < 3: |
… |
… |
|
100 | 102 | new_face = (face[2][1], face[1][0]) |
101 | 103 | g.add_edge(new_face) |
102 | 104 | edges_added.append(new_face) |
103 | | else: |
| 105 | else: |
104 | 106 | N = len(face) |
105 | 107 | i = 0 |
106 | 108 | while i < N-1: |
… |
… |
|
126 | 128 | """ |
127 | 129 | Helper function to schnyder method for computing coordinates in the plane to |
128 | 130 | plot a planar graph with no edge crossings. |
129 | | |
| 131 | |
130 | 132 | Constructs a normal labelling of a triangular graph g, given the planar |
131 | 133 | combinatorial embedding of g and a designated external face. Returns labels |
132 | | dictionary. The normal label is constructed by first contracting the graph |
| 134 | dictionary. The normal label is constructed by first contracting the graph |
133 | 135 | down to its external face, then expanding the graph back to the original while |
134 | 136 | simultaneously adding angle labels. |
135 | | |
| 137 | |
136 | 138 | INPUT: |
137 | 139 | g -- the graph to find the normal labeling of (g must be triangulated) |
138 | 140 | comb_emb -- a planar combinatorial embedding of g |
139 | 141 | external_face -- the list of three edges in the external face of g |
140 | | |
| 142 | |
141 | 143 | RETURNS: |
142 | 144 | x -- tuple with entries |
143 | 145 | x[0] = dict of dicts of normal labeling for each vertex of g and each |
144 | | adjacent neighbors u,v (u < v) of vertex: |
| 146 | adjacent neighbors u,v (u < v) of vertex: |
145 | 147 | { vertex : { (u,v): angel_label } } |
146 | 148 | x[1] = (v1,v2,v3) tuple of the three vertices of the external face. |
147 | | |
148 | | EXAMPLES: |
| 149 | |
| 150 | EXAMPLES:: |
| 151 | |
149 | 152 | sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer |
150 | 153 | sage: g = Graph(graphs.CycleGraph(7)) |
151 | 154 | sage: g.is_planar(set_embedding=True) |
… |
… |
|
157 | 160 | sage: _realizer(g, tn) |
158 | 161 | ({0: [<sage.graphs.schnyder.TreeNode instance at ...>]}, |
159 | 162 | (0, 1, 2)) |
160 | | |
| 163 | |
161 | 164 | """ |
162 | 165 | contracted = [] |
163 | 166 | contractible = [] |
164 | 167 | |
165 | 168 | labels = {} |
166 | | |
| 169 | |
167 | 170 | external_vertices = [external_face[0][0], external_face[1][0], external_face[2][0]] |
168 | 171 | external_vertices.sort() |
169 | 172 | v1,v2,v3 = external_vertices |
… |
… |
|
174 | 177 | neighbor_count[v] = 0 |
175 | 178 | for v in g.neighbors(v1): |
176 | 179 | neighbor_count[v] = len(v1_neighbors.intersection( Set(g.neighbors(v)))) |
177 | | |
| 180 | |
178 | 181 | |
179 | 182 | for v in v1_neighbors: |
180 | 183 | if v in [v1,v2,v3]: |
181 | 184 | continue |
182 | 185 | if neighbor_count[v] == 2: |
183 | 186 | contractible.append(v) |
184 | | |
| 187 | |
185 | 188 | # contraction phase: |
186 | 189 | |
187 | 190 | while g.order() > 3: |
… |
… |
|
206 | 209 | for w in g.neighbors(v1): |
207 | 210 | if(len(v1_neighbors.intersection( Set(g.neighbors(w))))) == 2 and w not in [v1, v2, v3]: |
208 | 211 | contractible.append(w) |
209 | | |
210 | | |
| 212 | |
| 213 | |
211 | 214 | # expansion phase: |
212 | 215 | |
213 | 216 | v1, v2, v3 = g.vertices() #always in sorted order |
… |
… |
|
227 | 230 | if len(neighbors_to_delete) == 0: |
228 | 231 | # we are adding v into the face new_neighbors |
229 | 232 | w1, w2, w3 = sorted(new_neighbors) |
230 | | |
| 233 | |
231 | 234 | labels[v] = {(w1, w2): labels[w3].pop((w1,w2)), (w2,w3) : labels[w1].pop((w2,w3)), (w1,w3) : labels[w2].pop((w1,w3))} |
232 | 235 | labels[w1][tuple(sorted((w2,v)))] = labels[v][(w2,w3)] |
233 | 236 | labels[w1][tuple(sorted((w3,v)))] = labels[v][(w2,w3)] |
… |
… |
|
267 | 270 | else: |
268 | 271 | vertices_in_order.append(angle[0]) |
269 | 272 | angles_out_of_v1.remove(angle) |
270 | | |
| 273 | |
271 | 274 | w = vertices_in_order |
272 | 275 | |
273 | 276 | # is w[0] a 2 or a 3? |
… |
… |
|
282 | 285 | labels[w[i]][ tuple(sorted( (w[i+1], v) )) ] = top_label |
283 | 286 | labels[w[i+1]][ tuple(sorted( (w[i], v) )) ] = bottom_label |
284 | 287 | i = i + 1 |
285 | | |
| 288 | |
286 | 289 | labels[v][tuple(sorted( (v1, w[0])))] = bottom_label |
287 | 290 | labels[v][tuple(sorted( (v1, w[-1])))] = top_label |
288 | 291 | |
… |
… |
|
291 | 294 | labels[w[-1]][tuple(sorted((v1,v)))] = bottom_label |
292 | 295 | labels[v1][tuple(sorted( (w[0],v) ))] = 1 |
293 | 296 | labels[v1][tuple(sorted( (w[-1],v) ))] = 1 |
294 | | |
| 297 | |
295 | 298 | #delete all the extra labels |
296 | 299 | |
297 | 300 | for angle in angle_set: |
… |
… |
|
299 | 302 | |
300 | 303 | labels[w[0]].pop( tuple (sorted( (v1, w[1]) ) )) |
301 | 304 | labels[w[-1]].pop( tuple (sorted( (v1, w[-2]) ) )) |
302 | | |
| 305 | |
303 | 306 | i = 1 |
304 | 307 | while i < len(w) - 1: |
305 | | labels[w[i]].pop(tuple(sorted( (v1, w[i+1])))) |
306 | | labels[w[i]].pop(tuple(sorted( (v1, w[i-1])))) |
| 308 | labels[w[i]].pop(tuple(sorted( (v1, w[i+1])))) |
| 309 | labels[w[i]].pop(tuple(sorted( (v1, w[i-1])))) |
307 | 310 | i = i + 1 |
308 | 311 | |
309 | 312 | for w in new_neighbors: |
… |
… |
|
317 | 320 | realizer and returns a dictionary of three trees determined by the |
318 | 321 | realizer, each spanning all interior vertices and rooted at one of |
319 | 322 | the three external vertices. |
320 | | |
| 323 | |
321 | 324 | A realizer is a directed graph with edge labels that span all interior |
322 | 325 | vertices from each external vertex. It is determined by giving direction |
323 | 326 | to the edges that have the same angle label on both sides at a vertex. |
324 | 327 | (Thus the direction actually points to the parent in the tree.) The |
325 | 328 | edge label is set as whatever the matching angle label is. Then from |
326 | | any interior vertex, following the directed edges by label will |
| 329 | any interior vertex, following the directed edges by label will |
327 | 330 | give a path to each of the three external vertices. |
328 | | |
| 331 | |
329 | 332 | INPUT: |
330 | 333 | g -- the graph to compute the realizer of |
331 | 334 | x -- tuple with entries |
332 | | x[0] = dict of dicts representing a normal labeling of g. For |
333 | | each vertex of g and each adjacent neighbors u,v (u < v) of |
| 335 | x[0] = dict of dicts representing a normal labeling of g. For |
| 336 | each vertex of g and each adjacent neighbors u,v (u < v) of |
334 | 337 | vertex: { vertex : { (u,v): angle_label } } |
335 | 338 | x[1] = (v1, v2, v3) tuple of the three external vertices (also |
336 | 339 | the roots of each tree) |
337 | | |
| 340 | |
338 | 341 | RETURNS: |
339 | 342 | x -- tuple with entries |
340 | 343 | x[0] = dict of lists of TreeNodes: |
341 | 344 | { root_vertex : [ list of all TreeNodes under root_vertex ] } |
342 | 345 | x[0] = (v1,v2,v3) tuple of the three external vertices (also the |
343 | 346 | roots of each tree) |
344 | | |
345 | | EXAMPLES: |
| 347 | |
| 348 | EXAMPLES:: |
| 349 | |
346 | 350 | sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer |
347 | 351 | sage: g = Graph(graphs.CycleGraph(7)) |
348 | 352 | sage: g.is_planar(set_embedding=True) |
… |
… |
|
354 | 358 | sage: _realizer(g, tn) |
355 | 359 | ({0: [<sage.graphs.schnyder.TreeNode instance at ...>]}, |
356 | 360 | (0, 1, 2)) |
357 | | |
| 361 | |
358 | 362 | """ |
359 | 363 | normal_labeling, (v1, v2, v3) = x |
360 | 364 | realizer = DiGraph() |
… |
… |
|
362 | 366 | tree_nodes = {} |
363 | 367 | for v in g: |
364 | 368 | tree_nodes[v] = [TreeNode(label = v, children = []), TreeNode(label = v, children = []), TreeNode(label = v, children = [])] |
365 | | |
| 369 | |
366 | 370 | |
367 | 371 | for v in g: |
368 | 372 | ones = [] |
… |
… |
|
375 | 379 | ones.sort() |
376 | 380 | twos.sort() |
377 | 381 | threes.sort() |
378 | | |
| 382 | |
379 | 383 | i = 0 |
380 | 384 | while i < len(ones) - 1: |
381 | 385 | if ones[i] == ones[i+1]: |
… |
… |
|
399 | 403 | i = i + 1 |
400 | 404 | |
401 | 405 | _compute_coordinates(realizer, (tree_nodes, (v1, v2, v3))) |
402 | | |
| 406 | |
403 | 407 | if example: |
404 | 408 | realizer.show(talk=True, edge_labels=True) |
405 | 409 | |
… |
… |
|
408 | 412 | def _compute_coordinates(g, x): |
409 | 413 | """ |
410 | 414 | Given a triangulated graph g with a dict of trees given by the |
411 | | realizer and tuple of the external vertices, we compute the |
| 415 | realizer and tuple of the external vertices, we compute the |
412 | 416 | coordinates of a planar geometric embedding in the grid. |
413 | | |
| 417 | |
414 | 418 | The coordinates will be set to the _pos attribute of g. |
415 | | |
| 419 | |
416 | 420 | INPUT: |
417 | 421 | g -- the graph to compute the coordinates of |
418 | 422 | x -- tuple with entries |
419 | | x[0] = dict of tree nodes for the three trees with each external |
| 423 | x[0] = dict of tree nodes for the three trees with each external |
420 | 424 | vertex as root |
421 | 425 | { root_vertex : [ list of all TreeNodes under root_vertex ] } |
422 | | |
| 426 | |
423 | 427 | x[1] = (v1, v2, v3) tuple of the three external vertices (also |
424 | 428 | the roots of each tree) |
425 | | EXAMPLES: |
| 429 | EXAMPLES:: |
| 430 | |
426 | 431 | sage: from sage.graphs.schnyder import _triangulate, _normal_label, _realizer, _compute_coordinates |
427 | 432 | sage: g = Graph(graphs.CycleGraph(7)) |
428 | 433 | sage: g.is_planar(set_embedding=True) |
… |
… |
|
436 | 441 | sage: g.get_pos() |
437 | 442 | {0: [5, 1], 1: [0, 5], 2: [1, 0], 3: [1, 4], 4: [2, 1], 5: [2, 3], 6: [3, 2]} |
438 | 443 | """ |
439 | | |
| 444 | |
440 | 445 | tree_nodes, (v1, v2, v3) = x |
441 | 446 | # find the roots of each tree: |
442 | 447 | t1, t2, t3 = tree_nodes[v1][0], tree_nodes[v2][1], tree_nodes[v3][2] |
… |
… |
|
462 | 467 | if v not in [t1.label,t2.label,t3.label]: |
463 | 468 | # Computing coordinates for v |
464 | 469 | r = list((0,0,0)) |
465 | | |
| 470 | |
466 | 471 | for i in [0,1,2]: |
467 | 472 | # Computing size of region i: |
468 | | |
| 473 | |
469 | 474 | # Tracing up tree (i + 1) % 3 |
470 | 475 | p = tree_nodes[v][(i + 1) % 3] |
471 | 476 | while p is not None: |
… |
… |
|
475 | 480 | r[i] += q |
476 | 481 | p = p.parent |
477 | 482 | |
478 | | # Tracing up tree (i - 1) % 3 |
| 483 | # Tracing up tree (i - 1) % 3 |
479 | 484 | p = tree_nodes[v][(i - 1) % 3] |
480 | 485 | while p is not None: |
481 | 486 | q = tree_nodes[p.label][i].number_of_descendants |
… |
… |
|
483 | 488 | # labels on path up tree (i - 1) % 3 |
484 | 489 | r[i] += q |
485 | 490 | p = p.parent |
486 | | |
| 491 | |
487 | 492 | q = tree_nodes[v][i].number_of_descendants |
488 | | # Subtracting |
| 493 | # Subtracting |
489 | 494 | r[i] -= q |
490 | | |
491 | | # Subtracting |
| 495 | |
| 496 | # Subtracting |
492 | 497 | q = tree_nodes[v][(i-1)%3].depth |
493 | 498 | r[i] -= q |
494 | 499 | |
… |
… |
|
504 | 509 | A class to represent each node in the trees used by _realizer() and |
505 | 510 | _compute_coordinates() when finding a planar geometric embedding in |
506 | 511 | the grid. |
507 | | |
| 512 | |
508 | 513 | Each tree node is doubly linked to its parent and children. |
509 | | |
| 514 | |
510 | 515 | INPUT: |
511 | 516 | parent -- the parent TreeNode of self |
512 | 517 | children -- a list of TreeNode children of self |
513 | 518 | label -- the associated realizer vertex label |
514 | | |
515 | | EXAMPLES: |
| 519 | |
| 520 | EXAMPLES:: |
| 521 | |
516 | 522 | sage: from sage.graphs.schnyder import TreeNode |
517 | 523 | sage: tn = TreeNode(label=5) |
518 | 524 | sage: tn2 = TreeNode(label=2,parent=tn) |
… |
… |
|
535 | 541 | parent -- the parent TreeNode of self |
536 | 542 | children -- a list of TreeNode children of self |
537 | 543 | label -- the associated realizer vertex label |
538 | | |
539 | | EXAMPLE: |
| 544 | |
| 545 | EXAMPLE:: |
| 546 | |
540 | 547 | sage: from sage.graphs.schnyder import TreeNode |
541 | 548 | sage: tn = TreeNode(label=5) |
542 | 549 | sage: tn2 = TreeNode(label=2,parent=tn) |
… |
… |
|
563 | 570 | |
564 | 571 | def compute_number_of_descendants(self): |
565 | 572 | """ |
566 | | Computes the number of descendants of self and all descendants. |
| 573 | Computes the number of descendants of self and all descendants. |
567 | 574 | For each TreeNode, sets result as attribute self.number_of_descendants |
568 | | |
569 | | EXAMPLES: |
| 575 | |
| 576 | EXAMPLES:: |
| 577 | |
570 | 578 | sage: from sage.graphs.schnyder import TreeNode |
571 | 579 | sage: tn = TreeNode(label=5) |
572 | 580 | sage: tn2 = TreeNode(label=2,parent=tn) |
… |
… |
|
588 | 596 | n += child.compute_number_of_descendants() |
589 | 597 | self.number_of_descendants = n |
590 | 598 | return n |
591 | | |
| 599 | |
592 | 600 | def compute_depth_of_self_and_children(self): |
593 | 601 | """ |
594 | 602 | Computes the depth of self and all descendants. |
595 | 603 | For each TreeNode, sets result as attribute self.depth |
596 | | |
597 | | EXAMPLES: |
| 604 | |
| 605 | EXAMPLES:: |
| 606 | |
598 | 607 | sage: from sage.graphs.schnyder import TreeNode |
599 | 608 | sage: tn = TreeNode(label=5) |
600 | 609 | sage: tn2 = TreeNode(label=2,parent=tn) |
… |
… |
|
617 | 626 | self.depth = self.parent.depth + 1 |
618 | 627 | for child in self.children: |
619 | 628 | child.compute_depth_of_self_and_children() |
620 | | |
| 629 | |
621 | 630 | def append_child(self, child): |
622 | 631 | """ |
623 | 632 | Add a child to list of children. |
624 | | |
625 | | EXAMPLES: |
| 633 | |
| 634 | EXAMPLES:: |
| 635 | |
626 | 636 | sage: from sage.graphs.schnyder import TreeNode |
627 | 637 | sage: tn = TreeNode(label=5) |
628 | 638 | sage: tn2 = TreeNode(label=2,parent=tn) |
diff --git a/sage/graphs/trees.pyx b/sage/graphs/trees.pyx
a
|
b
|
|
1 | 1 | r""" |
2 | | This is an implementation of the algorithm for generating trees with n vertices |
| 2 | Generation of trees |
| 3 | |
| 4 | This is an implementation of the algorithm for generating trees with `n` vertices |
3 | 5 | (up to isomorphism) in constant time per tree described in [WRIGHT-ETAL]_. |
4 | 6 | |
5 | 7 | AUTHORS: |
… |
… |
|
27 | 29 | r""" |
28 | 30 | This class iterates over all trees with n vertices (up to isomorphism). |
29 | 31 | |
30 | | EXAMPLES: |
| 32 | EXAMPLES:: |
31 | 33 | |
32 | 34 | sage: from sage.graphs.trees import TreeIterator |
33 | 35 | sage: def check_trees(n): |
… |
… |
|
47 | 49 | sage: print check_trees(10) |
48 | 50 | True |
49 | 51 | |
| 52 | :: |
| 53 | |
50 | 54 | sage: from sage.graphs.trees import TreeIterator |
51 | 55 | sage: count = 0 |
52 | 56 | sage: for t in TreeIterator(15): |
… |
… |
|
57 | 61 | |
58 | 62 | def __init__(self, int vertices): |
59 | 63 | r""" |
60 | | Initializes an iterator over all trees with n vertices. |
| 64 | Initializes an iterator over all trees with `n` vertices. |
61 | 65 | |
62 | 66 | EXAMPLES:: |
63 | 67 | |
… |
… |
|
73 | 77 | |
74 | 78 | def __dealloc__(self): |
75 | 79 | r""" |
76 | | EXAMPLES: |
| 80 | EXAMPLES:: |
| 81 | |
77 | 82 | sage: from sage.graphs.trees import TreeIterator |
78 | 83 | sage: t = TreeIterator(100) |
79 | 84 | sage: t = None # indirect doctest |
… |
… |
|
85 | 90 | |
86 | 91 | def __str__(self): |
87 | 92 | r""" |
88 | | EXAMPLES: |
| 93 | EXAMPLES:: |
| 94 | |
89 | 95 | sage: from sage.graphs.trees import TreeIterator |
90 | 96 | sage: t = TreeIterator(100) |
91 | 97 | sage: print t # indirect doctest |
… |
… |
|
95 | 101 | |
96 | 102 | def __iter__(self): |
97 | 103 | r""" |
98 | | Returns an iterator over all the trees with n vertices. |
| 104 | Returns an iterator over all the trees with `n` vertices. |
99 | 105 | |
100 | | EXAMPLES: |
| 106 | EXAMPLES:: |
| 107 | |
101 | 108 | sage: from sage.graphs.trees import TreeIterator |
102 | 109 | sage: t = TreeIterator(4) |
103 | 110 | sage: list(iter(t)) |
… |
… |
|
107 | 114 | |
108 | 115 | def __next__(self): |
109 | 116 | r""" |
110 | | Returns the next tree with n vertices |
| 117 | Returns the next tree with `n` vertices |
111 | 118 | |
112 | | EXAMPLES: |
| 119 | EXAMPLES:: |
| 120 | |
113 | 121 | sage: from sage.graphs.trees import TreeIterator |
114 | 122 | sage: T = TreeIterator(5) |
115 | 123 | sage: [t for t in T] # indirect doctest |
… |
… |
|
164 | 172 | |
165 | 173 | cdef int generate_first_level_sequence(self): |
166 | 174 | r""" |
167 | | Generates the level sequence representing the first tree with n vertices |
| 175 | Generates the level sequence representing the first tree with `n` vertices |
168 | 176 | """ |
169 | 177 | cdef int i |
170 | 178 | cdef int k |
… |
… |
|
200 | 208 | |
201 | 209 | cdef int generate_next_level_sequence(self): |
202 | 210 | r""" |
203 | | Generates the level sequence representing the next tree with n vertices |
| 211 | Generates the level sequence representing the next tree with `n` vertices |
204 | 212 | """ |
205 | 213 | cdef int i |
206 | 214 | cdef int fixit = 0 |
… |
… |
|
311 | 319 | self.l = l |
312 | 320 | self.current_level_sequence = w |
313 | 321 | |
314 | | return 0 |
315 | | No newline at end of file |
| 322 | return 0 |