Skip to content

Commit c825343

Browse files
committed
Cleaned coding style and added a default external face if none is provided for Tutte embedding.
1 parent 983f836 commit c825343

File tree

1 file changed

+27
-26
lines changed

1 file changed

+27
-26
lines changed

src/sage/graphs/generic_graph.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21639,15 +21639,16 @@ def layout_graphviz(self, dim=2, prog='dot', **options):
2163921639

2164021640
return {key_to_vertex[key]: pos for key, pos in positions.items()}
2164121641

21642-
def layout_tutte(self, external_face, external_face_pos=None, **options):
21642+
def layout_tutte(self, external_face=None, external_face_pos=None, **options):
2164321643
r"""
2164421644
Compute graph layout based on a Tutte embedding.
2164521645

2164621646
The graph must be 3-connected and planar.
2164721647

2164821648
INPUT:
2164921649

21650-
- ``external_face`` -- list; the external face to be made a polygon
21650+
- ``external_face`` -- list (default: ``None``); the external face to
21651+
be made a polygon
2165121652

2165221653
- ``external_face_pos`` -- dictionary (default: ``None``); the positions
2165321654
of the vertices of the external face. If ``None``, will automatically
@@ -21680,42 +21681,42 @@ def layout_tutte(self, external_face, external_face_pos=None, **options):
2168021681
from sage.matrix.constructor import zero_matrix
2168121682
from sage.rings.real_mpfr import RR
2168221683

21683-
if len(external_face) < 3:
21684-
raise ValueError("External face must have at least 3 vertices")
21684+
if (external_face is not None) and (len(external_face) < 3):
21685+
raise ValueError("external face must have at least 3 vertices")
2168521686

21686-
if (not self.is_planar()):
21687-
raise ValueError("Graph must be planar")
21687+
if not self.is_planar():
21688+
raise ValueError("graph must be planar")
2168821689

21689-
C = self.subgraph(vertices=external_face)
21690-
if (not C.is_cycle(directed_cycle=False)):
21691-
raise ValueError("External face must be a cycle")
21692-
external_face_ordered = C.depth_first_search(start=external_face[0], ignore_direction=False)
21690+
if not self.vertex_connectivity(k=3):
21691+
raise ValueError("graph must be 3-connected")
2169321692

21694-
from sage.graphs.connectivity import vertex_connectivity
21695-
if (not vertex_connectivity(self, k=3)):
21696-
raise ValueError("Graph must be 3-connected")
21693+
if external_face is None:
21694+
from sage.graphs.graph import Graph
21695+
H = Graph(self) # take a (undirected) copy H of the graph
21696+
u, v = next(H.edge_iterator(labels=False)) # take any edge (u, v) of H
21697+
H.delete_edge(u, v) # remove edge (u, v) from H
21698+
external_face = H.shortest_path(v, u)
21699+
# Compute a shortest path from v to u in H minus (u, v)H = G.
21700+
# Cycle existence is guaranteed since G is 3-connected.
21701+
else:
21702+
C = self.subgraph(vertices=external_face)
21703+
if (not C.is_cycle(directed_cycle=False)):
21704+
raise ValueError("external face must be a cycle")
21705+
external_face = C.depth_first_search(start=external_face[0], ignore_direction=False)
2169721706

21698-
from math import sin, cos, pi
2169921707
pos = dict()
21700-
2170121708
if external_face_pos is None:
21702-
external_face_length = len(external_face)
21703-
a0 = pi/external_face_length + pi/2
21704-
for i, vertex in enumerate(external_face_ordered):
21705-
ai = a0 + pi*2*i/external_face_length
21706-
pos[vertex] = (cos(ai), sin(ai))
21709+
pos = self._circle_embedding(external_face, return_dict=True)
2170721710
else:
2170821711
for v, p in external_face_pos.items():
2170921712
pos[v] = p
2171021713

21711-
V = self.vertices()
21712-
n = len(V)
21714+
n = self.order()
2171321715
M = zero_matrix(RR, n, n)
2171421716
b = zero_matrix(RR, n, 2)
2171521717

21716-
vertices_to_indices = {v:I for I, v in enumerate(V)}
21717-
for i in range(n):
21718-
v = V[i]
21718+
vertices_to_indices = {v: i for i, v in enumerate(self)}
21719+
for i, v in enumerate(self):
2171921720
if v in pos:
2172021721
M[i, i] = 1
2172121722
b[i, 0] = pos[v][0]
@@ -21728,7 +21729,7 @@ def layout_tutte(self, external_face, external_face_pos=None, **options):
2172821729
M[i, i] = len(nv)
2172921730

2173021731
sol = M.pseudoinverse()*b
21731-
return {V[i]:sol[i] for i in range(n)}
21732+
return dict(zip(self, sol))
2173221733

2173321734
def _layout_bounding_box(self, pos):
2173421735
"""

0 commit comments

Comments
 (0)