Refactor canonize_colored_graph to return new objects instead of mutating inputs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 01:43:52 -04:00
parent 54b33a7003
commit a4d51a6cfc
+12 -15
View File
@@ -41,8 +41,8 @@ def operation_sequence_id(ops: list[Operation]) -> str:
joined = "\n".join(op_to_transform_id(op) for op in ops)
return hashlib.sha256(joined.encode()).hexdigest()
def canonize_colored_graph(g: Graph, coloring: VertexColoring) -> ColoredGraphId:
"""Mutate g and coloring to canonical labels and return a canonical ColoredGraphId"""
def canonize_colored_graph(g: Graph, coloring: VertexColoring) -> tuple[Graph, VertexColoring, ColoredGraphId]:
"""Return a new canonical graph, new canonical coloring, and a ColoredGraphId without mutating inputs"""
canonical, cert = cast(
tuple[Graph, dict[Any, int]],
g.canonical_label(certificate=True),
@@ -55,34 +55,31 @@ def canonize_colored_graph(g: Graph, coloring: VertexColoring) -> ColoredGraphId
for orig_v, canon_idx in cert.items():
color_seq[canon_idx] = coloring[orig_v]
coloring.clear()
for canon_idx, color in enumerate(color_seq):
coloring[canon_idx] = color
canonical_coloring = {canon_idx: color for canon_idx, color in enumerate(color_seq)}
coloring_id = base64.urlsafe_b64encode(bytes(color_seq)).decode()
g.relabel(cert)
return ColoredGraphId(graph_id=graph_id, coloring_id=coloring_id)
return canonical, canonical_coloring, ColoredGraphId(graph_id=graph_id, coloring_id=coloring_id)
def save_colored_graph(g: Graph, coloring: VertexColoring) -> tuple[Graph, VertexColoring, ColoredGraphId]:
"""
Relabel g and coloring into canonical form, save to disk, and return both.
Canonize g and coloring, save to disk, and return the canonical forms with id.
If already saved, load and return the cached graph.
"""
cid = canonize_colored_graph(g, coloring)
g_canon, canonical_coloring, cid = canonize_colored_graph(g, coloring)
out_dir = DIR / "data" / "graphs" / cid['graph_id'] / cid['coloring_id']
if (out_dir / "graph.sobj").exists():
g_canon = cast(Graph, load(str(out_dir / 'graph')))
return g_canon, coloring, cid
g.is_planar(set_embedding=True, set_pos=True)
return g_canon, canonical_coloring, cid
g_canon.is_planar(set_embedding=True, set_pos=True)
vertex_colors: defaultdict[str, list[Any]] = defaultdict(list)
for v, c in coloring.items():
for v, c in canonical_coloring.items():
vertex_colors[PALETTE[c]].append(v)
out_dir.mkdir(parents=True, exist_ok=True)
g.plot(
g_canon.plot(
vertex_colors=dict(vertex_colors),
title=f"graph: {cid['graph_id']} coloring: {cid['coloring_id']}",
).save(out_dir / 'graph.png')
save(g, str(out_dir / 'graph'))
return g, coloring, cid
save(g_canon, str(out_dir / 'graph'))
return g_canon, canonical_coloring, cid
def _neighbors_form_cycle(g: Graph, v: Any) -> bool:
"""Return True if the neighbors of v induce a cycle in g."""