Add get_embedding_from_pos to derive combinatorial embedding from vertex positions
Replaces is_planar(set_embedding=True) calls in pluck and squish so the embedding stays consistent with inherited positions across reduction steps. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -155,6 +155,15 @@ def tutte_embedding(g: Graph, outer: list[Any]) -> dict[Any, tuple[float, float]
|
|||||||
|
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
|
def get_embedding_from_pos(g: Graph) -> dict[Any, list[Any]]:
|
||||||
|
"""Compute a combinatorial planar embedding by sorting each vertex's neighbors by angle."""
|
||||||
|
import math
|
||||||
|
pos = g.get_pos()
|
||||||
|
return {
|
||||||
|
v: sorted(g.neighbors(v), key=lambda w: math.atan2(pos[w][1] - pos[v][1], pos[w][0] - pos[v][0]))
|
||||||
|
for v in g.vertices()
|
||||||
|
}
|
||||||
|
|
||||||
def _neighbors_form_cycle(g: Graph, v: Any) -> bool:
|
def _neighbors_form_cycle(g: Graph, v: Any) -> bool:
|
||||||
"""Return True if the neighbors of v induce a cycle in g."""
|
"""Return True if the neighbors of v induce a cycle in g."""
|
||||||
return bool(cast(Graph, g.subgraph(g.neighbors(v))).is_cycle())
|
return bool(cast(Graph, g.subgraph(g.neighbors(v))).is_cycle())
|
||||||
@@ -174,7 +183,7 @@ def pluck(g: Graph, coloring: VertexColoring, v0: Any) -> tuple[Graph, VertexCol
|
|||||||
g_prime.delete_vertex(v0)
|
g_prime.delete_vertex(v0)
|
||||||
if (pos := g.get_pos()) is not None:
|
if (pos := g.get_pos()) is not None:
|
||||||
g_prime.set_pos({v: p for v, p in pos.items() if v != v0})
|
g_prime.set_pos({v: p for v, p in pos.items() if v != v0})
|
||||||
g_prime.is_planar(set_embedding=True)
|
g_prime.set_embedding(get_embedding_from_pos(g_prime))
|
||||||
coloring_prime = coloring.copy()
|
coloring_prime = coloring.copy()
|
||||||
del coloring_prime[v0]
|
del coloring_prime[v0]
|
||||||
return g_prime, coloring_prime
|
return g_prime, coloring_prime
|
||||||
@@ -211,7 +220,7 @@ def squish(g: Graph, coloring: VertexColoring, v0: Any) -> tuple[Graph, VertexCo
|
|||||||
g_prime.merge_vertices([v0, v1, v2])
|
g_prime.merge_vertices([v0, v1, v2])
|
||||||
if (pos := g.get_pos()) is not None:
|
if (pos := g.get_pos()) is not None:
|
||||||
g_prime.set_pos({v: p for v, p in pos.items() if v not in (v1, v2)})
|
g_prime.set_pos({v: p for v, p in pos.items() if v not in (v1, v2)})
|
||||||
g_prime.is_planar(set_embedding=True)
|
g_prime.set_embedding(get_embedding_from_pos(g_prime))
|
||||||
coloring_prime = {v: c for v, c in coloring.items() if v not in (v1, v2)}
|
coloring_prime = {v: c for v, c in coloring.items() if v not in (v1, v2)}
|
||||||
coloring_prime[v0] = coloring[v1]
|
coloring_prime[v0] = coloring[v1]
|
||||||
return g_prime, coloring_prime, v1, v2
|
return g_prime, coloring_prime, v1, v2
|
||||||
|
|||||||
Reference in New Issue
Block a user