From 5bdf6c27b1fad08605ec0a538bc5f287a80ce446 Mon Sep 17 00:00:00 2001 From: Boldi Date: Sat, 22 Jun 2024 12:04:25 +0100 Subject: [PATCH 1/2] Fix multigraph color change --- pyzx/editor_actions.py | 3 +-- pyzx/graph/base.py | 6 ++++++ pyzx/graph/graph_ig.py | 3 +++ pyzx/graph/graph_s.py | 6 +++++- pyzx/graph/multigraph.py | 5 +++++ pyzx/utils.py | 6 +++++- 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pyzx/editor_actions.py b/pyzx/editor_actions.py index 67481b2c..857d61e8 100644 --- a/pyzx/editor_actions.py +++ b/pyzx/editor_actions.py @@ -53,8 +53,7 @@ def color_change(g: BaseGraph[VT,ET], matches: List[VT]) -> rules.RewriteOutputT for v in matches: g.set_type(v, toggle_vertex(g.type(v))) for e in g.incident_edges(v): - et = g.edge_type(e) - g.set_edge_type(e, toggle_edge(et)) + g.toggle_edge_type(e) return ({}, [],[],False) diff --git a/pyzx/graph/base.py b/pyzx/graph/base.py index 8f6cfec4..0d205c0c 100644 --- a/pyzx/graph/base.py +++ b/pyzx/graph/base.py @@ -872,6 +872,12 @@ def set_edge_type(self, e: ET, t: EdgeType.Type) -> None: """Sets the type of the given edge.""" raise NotImplementedError("Not implemented on backend " + type(self).backend) + def toggle_edge_type(self, e: ET) -> None: + """Toggles the type of the edge between ``EdgeType.SIMPLE`` and ``EdgeType.HADAMARD``. + Does nothing if the edge is empty. + """ + raise NotImplementedError("Not implemented on backend " + type(self).backend) + def type(self, vertex: VT) -> VertexType.Type: """Returns the type of the given vertex: VertexType.BOUNDARY if it is a boundary, VertexType.Z if it is a Z node, diff --git a/pyzx/graph/graph_ig.py b/pyzx/graph/graph_ig.py index ab81d899..47cb671d 100644 --- a/pyzx/graph/graph_ig.py +++ b/pyzx/graph/graph_ig.py @@ -21,6 +21,7 @@ ig = None from .base import BaseGraph, VertexType, EdgeType +from ..utils import toggle_edge class GraphIG(BaseGraph): """Implementation of :class:`~graph.base.BaseGraph` using ``python-igraph`` @@ -115,6 +116,8 @@ def edge_type(self, e): def set_edge_type(self, e, t): self.graph.es[e]['_t'] = t + def toggle_edge_type(self, e): + self.set_edge_type(e, toggle_edge(self.graph.es[e]['_t'])) def type(self, v): t = self.graph.vs[v]['_t'] diff --git a/pyzx/graph/graph_s.py b/pyzx/graph/graph_s.py index a4e47214..89fc131e 100644 --- a/pyzx/graph/graph_s.py +++ b/pyzx/graph/graph_s.py @@ -19,7 +19,7 @@ from .base import BaseGraph -from ..utils import VertexType, EdgeType, FractionLike, FloatInt, vertex_is_zx_like, vertex_is_z_like, set_z_box_label, get_z_box_label +from ..utils import VertexType, EdgeType, FractionLike, FloatInt, vertex_is_zx_like, vertex_is_z_like, set_z_box_label, get_z_box_label, toggle_edge class GraphS(BaseGraph[int,Tuple[int,int]]): """Purely Pythonic implementation of :class:`~graph.base.BaseGraph`.""" @@ -275,6 +275,10 @@ def set_edge_type(self, e, t): self.graph[v1][v2] = t self.graph[v2][v1] = t + def toggle_edge_type(self, e): + if edge_type := self.edge_type(e): + self.set_edge_type(e, toggle_edge(edge_type)) + def type(self, vertex): return self.ty[vertex] def types(self): diff --git a/pyzx/graph/multigraph.py b/pyzx/graph/multigraph.py index 7a2541ce..2a3d0b83 100644 --- a/pyzx/graph/multigraph.py +++ b/pyzx/graph/multigraph.py @@ -348,6 +348,11 @@ def set_edge_type(self, edge, t): elif t == EdgeType.HADAMARD: e.add(h=1) else: e.add(w_io=1) + def toggle_edge_type(self, edge): + v1,v2 = edge + e = self.graph[v1][v2] + e.h, e.s = e.s, e.h + def type(self, vertex): return self.ty[vertex] def types(self): diff --git a/pyzx/utils.py b/pyzx/utils.py index 46464c73..a7588af2 100644 --- a/pyzx/utils.py +++ b/pyzx/utils.py @@ -82,7 +82,11 @@ class EdgeType: def toggle_edge(ty: EdgeType.Type) -> EdgeType.Type: """Swap the regular and Hadamard edge types.""" - return EdgeType.HADAMARD if ty == EdgeType.SIMPLE else EdgeType.SIMPLE + if ty == EdgeType.SIMPLE: + return EdgeType.HADAMARD + if ty == EdgeType.HADAMARD: + return EdgeType.SIMPLE + return ty def phase_to_s(a: FractionLike, t:VertexType.Type=VertexType.Z) -> str: if isinstance(a, Fraction) or isinstance(a, int): From aa4f9ee4f96e5ac878f4c1ca81dcc5ebeb4e068f Mon Sep 17 00:00:00 2001 From: Boldi Date: Tue, 25 Jun 2024 21:31:08 +0100 Subject: [PATCH 2/2] raise ValueError if toggle_edge is called with an invalid argument --- pyzx/graph/multigraph.py | 12 ++++++++++-- pyzx/utils.py | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pyzx/graph/multigraph.py b/pyzx/graph/multigraph.py index 2a3d0b83..9d1e313d 100644 --- a/pyzx/graph/multigraph.py +++ b/pyzx/graph/multigraph.py @@ -34,6 +34,12 @@ def __init__(self, s: int=0, h: int=0, w_io: int=0): self.h = h self.w_io = w_io + def __repr__(self): + s = f"s={self.s}" if self.s else "" + h = f"h={self.h}" if self.h else "" + w_io = f"w_io={self.w_io}" if self.w_io else "" + return f"Edge({', '.join([s, h, w_io])})" + def add(self, s: int=0, h: int=0, w_io: int=0): self.s += s self.h += h @@ -348,9 +354,11 @@ def set_edge_type(self, edge, t): elif t == EdgeType.HADAMARD: e.add(h=1) else: e.add(w_io=1) - def toggle_edge_type(self, edge): - v1,v2 = edge + def toggle_edge_type(self, edge: Edge) -> None: + v1, v2 = edge e = self.graph[v1][v2] + if e.w_io: + raise ValueError(f'Cannot toggle {repr(e)}') e.h, e.s = e.s, e.h def type(self, vertex): diff --git a/pyzx/utils.py b/pyzx/utils.py index a7588af2..312cc32c 100644 --- a/pyzx/utils.py +++ b/pyzx/utils.py @@ -86,7 +86,7 @@ def toggle_edge(ty: EdgeType.Type) -> EdgeType.Type: return EdgeType.HADAMARD if ty == EdgeType.HADAMARD: return EdgeType.SIMPLE - return ty + raise ValueError(f'Cannot toggle {repr(ty)}') def phase_to_s(a: FractionLike, t:VertexType.Type=VertexType.Z) -> str: if isinstance(a, Fraction) or isinstance(a, int):