Skip to content

Commit

Permalink
Fixed bugs in _gate_FREDKIN function (#1489)
Browse files Browse the repository at this point in the history
* Fixed bugs in _gate_FREDKIN function

* Added test
  • Loading branch information
BOBO1997 authored and BoxiLi committed Apr 16, 2021
1 parent 5383325 commit 4bd52c2
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 76 deletions.
198 changes: 122 additions & 76 deletions src/qutip_qip/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
x_gate, y_gate, z_gate, cy_gate,
cz_gate, s_gate, t_gate, cs_gate,
qasmu_gate, ct_gate, cphase, cnot,
csign, berkeley, swapalpha, swap, iswap,
sqrtswap, sqrtiswap, fredkin,
csign, berkeley, swapalpha, swap,
iswap, sqrtswap, sqrtiswap, fredkin,
toffoli, controlled_gate, globalphase,
expand_operator, gate_sequence_product)
from qutip import tensor, basis, identity, ket2dm
Expand Down Expand Up @@ -217,7 +217,8 @@ def _to_qasm(self, qasm_out):
qasm_gate = qasm_out.qasm_name(self.name)

if not qasm_gate:
error_str = "{} gate's qasm defn is not specified".format(self.name)
error_str =\
"{} gate's qasm defn is not specified".format(self.name)
raise NotImplementedError(error_str)

if self.classical_controls:
Expand Down Expand Up @@ -839,73 +840,118 @@ def _gate_ISWAP(self, gate, temp_resolved):
arg_label=r"\pi/2"))

def _gate_FREDKIN(self, gate, temp_resolved):
half_pi = np.pi / 2
eigth_pi = np.pi / 8
temp_resolved.append(Gate("CNOT", gate.targets[0],
gate.targets[1]))
temp_resolved.append(Gate("CNOT", gate.targets[0],
gate.controls))
temp_resolved.append(Gate("RZ", gate.controls, None,
arg_value=eigth_pi,
arg_label=r"\pi/8"))
temp_resolved.append(Gate("RZ", [gate.targets[0]], None,
arg_value=-eigth_pi,
arg_label=r"-\pi/8"))
temp_resolved.append(Gate("CNOT", gate.targets[0],
gate.controls))
temp_resolved.append(Gate("GLOBALPHASE", None, None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("RY", gate.targets[1], None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("RY", gate.targets, None,
arg_value=-half_pi,
arg_label=r"-\pi/2"))
temp_resolved.append(Gate("RZ", gate.targets, None,
arg_value=np.pi, arg_label=r"\pi"))
temp_resolved.append(Gate("RY", gate.targets, None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("RZ", gate.targets[0], None,
arg_value=eigth_pi,
arg_label=r"\pi/8"))
temp_resolved.append(Gate("RZ", gate.targets[1], None,
arg_value=eigth_pi,
arg_label=r"\pi/8"))
temp_resolved.append(Gate("CNOT", gate.targets[1],
gate.controls))
temp_resolved.append(Gate("RZ", gate.targets[1], None,
arg_value=-eigth_pi,
arg_label=r"-\pi/8"))
temp_resolved.append(Gate("CNOT", gate.targets[1],
gate.targets[0]))
temp_resolved.append(Gate("RZ", gate.targets[1], None,
arg_value=eigth_pi,
arg_label=r"\pi/8"))
temp_resolved.append(Gate("CNOT", gate.targets[1],
gate.controls))
temp_resolved.append(Gate("RZ", gate.targets[1], None,
arg_value=-eigth_pi,
arg_label=r"-\pi/8"))
temp_resolved.append(Gate("CNOT", gate.targets[1],
gate.targets[0]))
temp_resolved.append(Gate("GLOBALPHASE", None, None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("RY", gate.targets[1], None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("RY", gate.targets, None,
arg_value=-half_pi,
arg_label=r"-\pi/2"))
temp_resolved.append(Gate("RZ", gate.targets, None,
arg_value=np.pi, arg_label=r"\pi"))
temp_resolved.append(Gate("RY", gate.targets, None,
arg_value=half_pi,
arg_label=r"\pi/2"))
temp_resolved.append(Gate("CNOT", gate.targets[0],
gate.targets[1]))
pi = np.pi
temp_resolved += [
Gate("CNOT",
controls=gate.targets[1],
targets=gate.targets[0]),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=pi,
arg_label=r"\pi"),
Gate("RX",
controls=None,
targets=gate.targets[1],
arg_value=pi / 2,
arg_label=r"\pi/2"),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=- pi / 2,
arg_label=r"-\pi/2"),
Gate("RX",
controls=None,
targets=gate.targets[1],
arg_value=pi / 2,
arg_label=r"\pi/2"),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=pi,
arg_label=r"\pi"),
Gate("CNOT",
controls=gate.targets[0],
targets=gate.targets[1]),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=- pi / 4,
arg_label=r"-\pi/4"),
Gate("CNOT",
controls=gate.controls,
targets=gate.targets[1]),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=pi / 4,
arg_label=r"\pi/4"),
Gate("CNOT",
controls=gate.targets[0],
targets=gate.targets[1]),
Gate("RZ",
controls=None,
targets=gate.targets[0],
arg_value=pi / 4,
arg_label=r"\pi/4"),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=- pi / 4,
arg_label=r"-\pi/4"),
Gate("CNOT",
controls=gate.controls,
targets=gate.targets[1]),
Gate("CNOT",
controls=gate.controls,
targets=gate.targets[0]),
Gate("RZ",
controls=None,
targets=gate.controls,
arg_value=pi / 4,
arg_label=r"\pi/4"),
Gate("RZ",
controls=None,
targets=gate.targets[0],
arg_value=- pi / 4,
arg_label=r"-\pi/4"),
Gate("CNOT",
controls=gate.controls,
targets=gate.targets[0]),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=- 3 * pi / 4,
arg_label=r"-3\pi/4"),
Gate("RX",
controls=None,
targets=gate.targets[1],
arg_value=pi / 2,
arg_label=r"\pi/2"),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=- pi / 2,
arg_label=r"-\pi/2"),
Gate("RX",
controls=None,
targets=gate.targets[1],
arg_value=pi / 2,
arg_label=r"\pi/2"),
Gate("RZ",
controls=None,
targets=gate.targets[1],
arg_value=pi,
arg_label=r"\pi"),
Gate("CNOT",
controls=gate.targets[1],
targets=gate.targets[0]),
Gate("GLOBALPHASE",
controls=None,
targets=None,
arg_value=pi / 8,
arg_label=r"\pi/8")
]

def _gate_TOFFOLI(self, gate, temp_resolved):
half_pi = np.pi / 2
Expand Down Expand Up @@ -1123,8 +1169,8 @@ def run(self, state, cbits=None, U_list=None,
chosen at random.
precompute_unitary: Boolean, optional
Specify if computation is done by pre-computing and aggregating
gate unitaries. Possibly a faster method in the case of large number
of repeat runs with different state inputs.
gate unitaries. Possibly a faster method in the case of
large number of repeat runs with different state inputs.
Returns
-------
Expand Down Expand Up @@ -1165,8 +1211,8 @@ def run_statistics(self, state, U_list=None,
chosen at random.
precompute_unitary: Boolean, optional
Specify if computation is done by pre-computing and aggregating
gate unitaries. Possibly a faster method in the case of large number
of repeat runs with different state inputs.
gate unitaries. Possibly a faster method in the case of
large number of repeat runs with different state inputs.
Returns
-------
Expand Down Expand Up @@ -1938,8 +1984,8 @@ def __init__(self, qc, state=None, cbits=None,
precompute_unitary: Boolean, optional
Specify if computation is done by pre-computing and aggregating
gate unitaries. Possibly a faster method in the case of large number
of repeat runs with different state inputs.
gate unitaries. Possibly a faster method in the case of
large number of repeat runs with different state inputs.
"""

self.qc = qc
Expand Down
13 changes: 13 additions & 0 deletions tests/test_qubitcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ def testSNOTdecompose(self):
U2 = gates.gate_sequence_product(qc2.propagators())
assert _op_dist(U1, U2) < 1e-12

def testFREDKINdecompose(self):
"""
FREDKIN to rotation and CNOT: compare unitary matrix for FREDKIN and product of
resolved matrices in terms of rotation gates and CNOT.
"""
qc1 = QubitCircuit(3)
qc1.add_gate("FREDKIN", targets=[0, 1], controls=[2])
U1 = gates.gate_sequence_product(qc1.propagators())
qc2 = qc1.resolve_gates()
U2 = gates.gate_sequence_product(qc2.propagators())
assert _op_dist(U1, U2) < 1e-12


def testadjacentgates(self):
"""
Adjacent Gates: compare unitary matrix for ISWAP and product of
Expand Down

0 comments on commit 4bd52c2

Please sign in to comment.