Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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