Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyzx/drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ def draw_matplotlib(
ecol = '#0099ff'
elif et == 3:
ecol = 'gray'
elif et == 4:
ecol = '#8B0000' # Dark red for FAULT_EDGE
else:
ecol = 'black'

Expand Down
6 changes: 6 additions & 0 deletions pyzx/graph/jsonparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ def json_to_graph_old(js: Union[str,Dict[str,Any]], backend:Optional[str]=None)
if 'type' in edge and edge['type'] == 'w_io':
g.add_edge((names[n1],names[n2]), EdgeType.W_IO)
continue
if 'type' in edge and edge['type'] == 'fault_edge':
g.add_edge((names[n1],names[n2]), EdgeType.FAULT_EDGE)
continue

amount = edges.get((names[n1],names[n2]),[0,0])
amount[0] += 1
Expand Down Expand Up @@ -321,6 +324,9 @@ def graph_to_dict_old(g: BaseGraph[VT,ET], include_scalar: bool=True) -> Dict[st
elif et == EdgeType.W_IO:
edges["e"+str(i)] = {"src": names[src],"tgt": names[tgt], "type": "w_io"}
i += 1
elif et == EdgeType.FAULT_EDGE:
edges["e"+str(i)] = {"src": names[src],"tgt": names[tgt], "type": "fault_edge"}
i += 1
else:
raise TypeError("Edge of type 0")

Expand Down
34 changes: 25 additions & 9 deletions pyzx/graph/multigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,38 @@ class Edge:
s: int
h: int
w_io: int
fault_edge: int

def __init__(self, s: int=0, h: int=0, w_io: int=0):
def __init__(self, s: int=0, h: int=0, w_io: int=0, fault_edge: int=0):
self.s = s
self.h = h
self.w_io = w_io
self.fault_edge = fault_edge

def add(self, s: int=0, h: int=0, w_io: int=0):
def add(self, s: int=0, h: int=0, w_io: int=0, fault_edge: int=0):
self.s += s
self.h += h
self.w_io += w_io
self.fault_edge += fault_edge
if self.s < 0 or self.h < 0:
raise ValueError('Cannot have negative edges')
if self.w_io not in (0,1):
raise ValueError('Invalid number of W-IO edges')
if self.w_io == 1 and self.s + self.h > 0:
if self.w_io == 1 and self.s + self.h + self.fault_edge > 0:
raise ValueError('Cannot have W-IO edge and other edges')

def remove(self, s: int=0, h: int=0, w_io: int=0):
self.add(s=-s, h=-h, w_io=-w_io)
def remove(self, s: int=0, h: int=0, w_io: int=0, fault_edge: int=0):
self.add(s=-s, h=-h, w_io=-w_io, fault_edge=-fault_edge)

def is_empty(self) -> bool:
return self.s == 0 and self.h == 0 and self.w_io == 0
return self.s == 0 and self.h == 0 and self.w_io == 0 and self.fault_edge == 0

def get_edge_count(self, ty: EdgeType) -> int:
if ty == EdgeType.SIMPLE: return self.s
elif ty == EdgeType.HADAMARD: return self.h
else: return self.w_io
elif ty == EdgeType.W_IO: return self.w_io
elif ty == EdgeType.FAULT_EDGE: return self.fault_edge
else: return 0

class Multigraph(BaseGraph[int,Tuple[int,int,EdgeType]]):
"""Purely Pythonic multigraph implementation of :class:`~graph.base.BaseGraph`."""
Expand Down Expand Up @@ -177,7 +182,9 @@ def add_edge(self, edge_pair, edgetype=EdgeType.SIMPLE):

if edgetype == EdgeType.SIMPLE: e.add(s=1)
elif edgetype == EdgeType.HADAMARD: e.add(h=1)
else: e.add(w_io=1)
elif edgetype == EdgeType.W_IO: e.add(w_io=1)
elif edgetype == EdgeType.FAULT_EDGE: e.add(fault_edge=1)
else: raise ValueError(f"Unknown edge type: {edgetype}")

if self._auto_simplify: # This currently can keep a parallel regular and Hadamard edge
t1 = self.ty[s]
Expand All @@ -198,6 +205,9 @@ def add_edge(self, edge_pair, edgetype=EdgeType.SIMPLE):
if e.s > 0:
self.nedges = self.nedges - e.s + 1
e.s = 1
if e.fault_edge > 0:
self.nedges = self.nedges - e.fault_edge + 1
e.fault_edge = 1
if e.h > 0:
self.nedges = self.nedges - (e.h - e.h % 2)
self.scalar.add_power(-2 * (e.h - (e.h % 2)))
Expand Down Expand Up @@ -260,7 +270,9 @@ def remove_edge(self, edge):
e = self.graph[s][t]
if ty == EdgeType.SIMPLE: e.remove(s=1)
elif ty == EdgeType.HADAMARD: e.remove(h=1)
else: e.remove(w_io=1)
elif ty == EdgeType.W_IO: e.remove(w_io=1)
elif ty == EdgeType.FAULT_EDGE: e.remove(fault_edge=1)
else: raise ValueError(f"Unknown edge type: {ty}")

if e.is_empty():
del self.graph[s][t]
Expand All @@ -284,6 +296,8 @@ def num_edges(self, s=None, t=None, et=None):
return self.graph[s][t].h
elif et == EdgeType.W_IO:
return self.graph[s][t].w_io
elif et == EdgeType.FAULT_EDGE:
return self.graph[s][t].fault_edge
else:
raise ValueError("Unkown EdgeType: %s" % repr(et))
else:
Expand All @@ -308,6 +322,7 @@ def edges(self, s=None, t=None):
for _ in range(e.s): yield (v0, v1, EdgeType.SIMPLE)
for _ in range(e.h): yield (v0, v1, EdgeType.HADAMARD)
for _ in range(e.w_io): yield (v0, v1, EdgeType.W_IO)
for _ in range(e.fault_edge): yield (v0, v1, EdgeType.FAULT_EDGE)
elif t != None:
s, t = (s, t) if s < t else (t, s)
if t not in self.graph[s]:
Expand All @@ -316,6 +331,7 @@ def edges(self, s=None, t=None):
for _ in range(e.s): yield (s, t, EdgeType.SIMPLE)
for _ in range(e.h): yield (s, t, EdgeType.HADAMARD)
for _ in range(e.w_io): yield (s, t, EdgeType.W_IO)
for _ in range(e.fault_edge): yield (s, t, EdgeType.FAULT_EDGE)

# def edges_in_range(self, start, end, safe=False):
# """like self.edges, but only returns edges that belong to vertices
Expand Down
1 change: 1 addition & 0 deletions pyzx/js/zx_viewer.inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function edgeColor(t) {
if (t == 1) return _settings_colors['edge']; //"black";
else if (t == 2) return _settings_colors['Hedge']; // "#08f";
else if (t == 3) return _settings_colors['Xedge']; // "gray";
else if (t == 4) return _settings_colors['FaultEdge']; // "dark red";
}

function webColor(t) {
Expand Down
1 change: 1 addition & 0 deletions pyzx/js/zx_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function edgeColor(t) {
if (t == 1) return _settings_colors['edge']; //"black";
else if (t == 2) return _settings_colors['Hedge']; // "#08f";
else if (t == 3) return _settings_colors['Xedge']; // "gray";
else if (t == 4) return _settings_colors['FaultEdge']; // "dark red";
}

function webColor(t) {
Expand Down
6 changes: 6 additions & 0 deletions pyzx/tikz.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ def _to_tikz(g: BaseGraph[VT,ET], draw_scalar:bool = False,
elif et == EdgeType.W_IO:
style = settings.tikz_classes['W-io-edge']
if style: s += "[style={:s}] ".format(style)
elif et == EdgeType.FAULT_EDGE:
style = settings.tikz_classes['Fault-edge']
if style: s += "[style={:s}] ".format(style)
else:
style = settings.tikz_classes['edge']
if style: s += "[style={:s}] ".format(style)
Expand Down Expand Up @@ -206,6 +209,7 @@ def tikzit(g: Union[BaseGraph[VT,ET],Circuit,str], draw_scalar:bool=False) -> No
synonyms_edge = ['empty', 'simple', 'none']
synonyms_hedge = ['hadamard edge']
synonyms_wedge = ['w edge', 'w io edge']
synonyms_fault_edge = ['fault edge']

tikz_error_message = "Not a valid tikz picture. Please use Tikzit to generate correct output."
def tikz_to_graph(
Expand Down Expand Up @@ -396,6 +400,8 @@ def tikz_to_graph(
etab[e] = [0,1]
elif style.lower() in synonyms_wedge:
g.add_edge(e, EdgeType.W_IO)
elif style.lower() in synonyms_fault_edge:
g.add_edge(e, EdgeType.FAULT_EDGE)
else:
if ignore_nonzx:
if e in etab:
Expand Down
6 changes: 5 additions & 1 deletion pyzx/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class EdgeType(IntEnum):
SIMPLE = 1
HADAMARD = 2
W_IO = 3
FAULT_EDGE = 4

def toggle_edge(ty: EdgeType) -> EdgeType:
"""Swap the regular and Hadamard edge types."""
Expand Down Expand Up @@ -138,13 +139,15 @@ def phase_is_pauli(phase: FractionLike):
'dummy': 'text',
'edge': '',
'H-edge': 'hadamard edge',
'W-io-edge': 'W io edge'
'W-io-edge': 'W io edge',
'Fault-edge': 'fault edge'
}

original_colors = {
'edge': '#000000',
'Hedge': '#0088ff',
'Xedge': '#999999',
'FaultEdge': '#8B0000',
'boundary': '#000000',
'X': '#ff8888',
'Y': '#aabbff',
Expand All @@ -169,6 +172,7 @@ def phase_is_pauli(phase: FractionLike):
'edge': '#000000',
'Hedge': '#888888',
'Xedge': '#dddddd',
'FaultEdge': '#8B0000',
'boundary': '#000000',
'X': '#666666',
'Y': '#9999dd',
Expand Down