Skip to content

Commit

Permalink
Merge pull request #172 from dlyongemallo/fix_phases_output
Browse files Browse the repository at this point in the history
Fix a bug where gates with multiple phases did not output the phases …
  • Loading branch information
jvdwetering authored Oct 22, 2023
2 parents 635f829 + dcf547a commit f4f47c8
Showing 1 changed file with 29 additions and 17 deletions.
46 changes: 29 additions & 17 deletions pyzx/circuit/gates.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PyZX - Python library for quantum circuit rewriting
# PyZX - Python library for quantum circuit rewriting
# and optimization using the ZX-calculus
# Copyright (C) 2018 - Aleks Kissinger and John van de Wetering

Expand Down Expand Up @@ -93,7 +93,7 @@ def set_all_rows(self, n: int) -> None:
"""
for l in self._rows.keys():
self._rows[l] = n

def max_row(self) -> int:
"""
Returns the highest 'next row' number.
Expand Down Expand Up @@ -152,8 +152,11 @@ def __str__(self) -> str:
attribs = []
if hasattr(self, "control"): attribs.append(str(self.control))
if hasattr(self, "target"): attribs.append(str(self.target))
if hasattr(self, "phase") and self.print_phase:
attribs.append("phase={!s}".format(self.phase))
if self.print_phase:
if hasattr(self, "phase"):
attribs.append("phase={!s}".format(self.phase))
elif hasattr(self, "phases"):
attribs.append("phases={}".format(",".join(str(p) for p in self.phases)))
return "{}{}({})".format(
self.name,
("*" if (hasattr(self,"adjoint") and self.adjoint) else ""),
Expand Down Expand Up @@ -248,8 +251,11 @@ def to_qasm(self) -> str:
for a in ["ctrl1","ctrl2", "control", "target"]:
if hasattr(self, a): args.append("q[{:d}]".format(getattr(self,a)))
param = ""
if hasattr(self, "phase") and self.print_phase:
param = "({}*pi)".format(float(self.phase))
if self.print_phase:
if hasattr(self, "phase"):
param = "({}*pi)".format(float(self.phase))
elif hasattr(self, "phases"):
param = "({})".format(",".join("{}*pi".format(float(p)) for p in self.phases))
return "{}{} {};".format(n, param, ", ".join(args))

def to_qc(self) -> str:
Expand All @@ -261,15 +267,15 @@ def to_qc(self) -> str:
bg = self.split_phases()
if any(g.qc_name == 'undefined' for g in bg):
raise TypeError("Gate {} doesn't have a .qc description".format(str(self)))
else:
else:
bg = self.to_basic_gates()
if len(bg) == 1:
raise TypeError("Gate {} doesn't have a .qc description".format(str(self)))
return "\n".join(g.to_qc() for g in bg)
args = []
for a in ["ctrl1","ctrl2", "control", "target"]:
if hasattr(self, a): args.append("q{:d}".format(getattr(self,a)))

# if hasattr(self, "phase") and self.print_phase:
# args.insert(0, phase_to_s(self.phase))
return "{} {}".format(n, " ".join(args))
Expand All @@ -284,12 +290,12 @@ def to_graph(self, g: BaseGraph[VT,ET], q_mapper: TargetMapper[VT], c_mapper: Ta
"""
raise NotImplementedError("to_graph() must be implemented by each Gate subclass.")

def graph_add_node(self,
g: BaseGraph[VT,ET],
def graph_add_node(self,
g: BaseGraph[VT,ET],
mapper: TargetMapper[VT],
t: VertexType.Type,
l: int, r: int,
phase: FractionLike=0,
t: VertexType.Type,
l: int, r: int,
phase: FractionLike=0,
etype: EdgeType.Type=EdgeType.SIMPLE,
ground: bool = False) -> VT:
v = g.add_vertex(t, mapper.to_qubit(l), r, phase, ground)
Expand Down Expand Up @@ -339,7 +345,7 @@ def split_phases(self) -> List['ZPhase']:
return [S(self.target)]
else: return [S(self.target, adjoint=True)]
elif self.phase.denominator == 4:
gates: List['ZPhase'] = []
gates: List['ZPhase'] = []
n = self.phase.numerator % 8
if n == 3 or n == 5:
gates.append(Z(self.target))
Expand Down Expand Up @@ -440,6 +446,7 @@ class SX(XPhase):
name = 'SX'
qasm_name = 'sx'
qasm_name_adjoint = 'sxdg'
print_phase = False
def __init__(self, target: int, adjoint:bool=False) -> None:
super().__init__(target, Fraction(1,2)*(-1 if adjoint else 1))
self.adjoint = adjoint
Expand Down Expand Up @@ -562,7 +569,7 @@ def to_emoji(self,strings: List[List[str]]) -> None:
mi = min([c,t])
ma = max([c,t])
r = max([len(s) for s in strings[mi:ma+1]])
for s in (strings[mi:ma+1]):
for s in (strings[mi:ma+1]):
s.extend([':W_:']*(r-len(s)))
for i in range(mi+1,ma): strings[i].append(':Wud:')
if c<t:
Expand Down Expand Up @@ -829,6 +836,7 @@ def __init__(self, control:int, target:int, theta:FractionLike, phi:FractionLike
self.target = target
self.theta = theta
self.phi = phi
self.phases = [theta, phi]

def __eq__(self, other: object) -> bool:
if not isinstance(other, FSim): return False
Expand Down Expand Up @@ -886,7 +894,7 @@ def to_graph(self, g, q_mapper, _c_mapper):
# t1 = self.graph_add_node(g, q_mapper, VertexType.Z, self.target,r)
# c2 = self.graph_add_node(g, q_mapper, VertexType.Z, self.control,r+1)
# t2 = self.graph_add_node(g, q_mapper, VertexType.Z, self.target,r+1)

# pg1 = g.add_vertex(VertexType.Z,qmin-0.5,r+1)
# pg1b = g.add_vertex(VertexType.Z,qmin-1.5,r+1, phase=self.theta)
# g.add_edge((c1,pg1),EdgeType.HADAMARD)
Expand Down Expand Up @@ -921,7 +929,7 @@ def to_graph(self, g, q_mapper, _c_mapper):
#g.add_edge((t,h),EdgeType.SIMPLE)
#g.add_edge((c1,h),EdgeType.SIMPLE)
#g.add_edge((c2,h),EdgeType.SIMPLE)

#rs[self.target] = r+4
#rs[self.control] = r+4

Expand Down Expand Up @@ -1052,6 +1060,7 @@ def __init__(self, target: int, theta: FractionLike, phi: FractionLike) -> None:
self.target = target
self.theta = theta
self.phi = phi
self.phases = [theta, phi]

def to_basic_gates(self):
return [ZPhase(self.target,phase=(self.phi-Fraction(1,2))%2),
Expand All @@ -1071,6 +1080,7 @@ def __init__(self, target: int, theta: FractionLike, phi: FractionLike, rho: Fra
self.theta = theta
self.phi = phi
self.rho = rho
self.phases = [theta, phi, rho]

def to_basic_gates(self):
return [ZPhase(self.target,phase=self.rho),
Expand All @@ -1094,6 +1104,7 @@ def __init__(self, control: int, target: int, theta: FractionLike, phi: Fraction
self.theta = theta
self.phi = phi
self.rho = rho
self.phases = [theta, phi, rho]

def to_basic_gates(self):
return [ZPhase(self.control,phase=(self.rho+self.phi)/2),
Expand Down Expand Up @@ -1121,6 +1132,7 @@ def __init__(self, control: int, target: int, theta: FractionLike, phi: Fraction
self.phi = phi
self.rho = rho
self.gamma = gamma
self.phases = [theta, phi, rho, gamma]

def to_basic_gates(self):
return [ZPhase(self.control,phase=self.gamma)] + \
Expand Down

0 comments on commit f4f47c8

Please sign in to comment.