Skip to content

Commit

Permalink
Fix a bug in the classical controlled gate
Browse files Browse the repository at this point in the history
The classical controlled values were not correctly passed to the simulator.
  • Loading branch information
BoxiLi committed Aug 14, 2022
1 parent 98562f1 commit 647a93b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 7 deletions.
15 changes: 14 additions & 1 deletion src/qutip_qip/circuit/circuitsimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,13 +554,26 @@ def step(self):
state after one evolution step.
"""

def _decimal_to_binary(decimal, length):
binary = [int(s) for s in "{0:#b}".format(decimal)[2:]]
return [0] * (length - len(binary)) + binary

op = self.ops[self.op_index]
if isinstance(op, Measurement):
self._apply_measurement(op)
elif isinstance(op, tuple):
operation, U = op
apply_gate = all(
[self.cbits[i] for i in operation.classical_controls]
[
self.cbits[cbit_index] == control_value
for cbit_index, control_value in zip(
operation.classical_controls,
_decimal_to_binary(
operation.classical_control_value,
len(operation.classical_controls),
),
)
]
)
if apply_gate:
if self.precompute_unitary:
Expand Down
22 changes: 16 additions & 6 deletions src/qutip_qip/operations/gateclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,17 @@ class Gate:
the unitary operator on the target qubits.
E.g. if the gate should be executed when the zero-th bit is 1,
``controll_value=1``;
If the gate should be executed when the first two bits are 0 and 1,
``controll_value=3``.
classical_control_values : int, optional
If the gate should be executed when the two bits are 1 and 0,
``controll_value=2``.
classical_control_value : int, optional
The decimal value of controlling classical bits for executing
the unitary operator on the target qubits.
E.g. if the gate should be executed when the zero-th bit is 1,
``controll_value=1``;
If the gate should be executed when the first two bits are 0 and 1,
``controll_value=3``.
If the gate should be executed when the two bits are 1 and 0,
``controll_value=2``.
The default is ``2**len(classical_controls)-1``
(i.e. all classical controls are 1).
arg_label : string
Label for the argument, it will be shown in the circuit plot,
representing the argument value provided to the gate, e.g,
Expand Down Expand Up @@ -177,8 +179,16 @@ def __init__(
else:
self.classical_controls = classical_controls

if (
self.classical_controls is not None
and classical_control_value is None
):
self.classical_control_value = (
2 ** len(self.classical_controls) - 1
)
else:
self.classical_control_value = classical_control_value
self.control_value = control_value
self.classical_control_value = classical_control_value
self.arg_value = arg_value
self.arg_label = arg_label
self.latex_str = r"U"
Expand Down
23 changes: 23 additions & 0 deletions tests/test_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,29 @@ def test_run_teleportation(self):
_, final_probabilities = final_measurement.measurement_comp_basis(state_final)

np.testing.assert_allclose(initial_probabilities, final_probabilities)

def test_classical_control(self):
qc = QubitCircuit(1, num_cbits=2)
qc.add_gate(
"X",
targets=[0],
classical_controls=[0, 1],
classical_control_value=1,
)
result = qc.run(basis(2, 0), cbits=[1, 0])
fid = qp.fidelity(result, basis(2, 0))
assert pytest.approx(fid, 1.0e-6) == 1

qc = QubitCircuit(1, num_cbits=2)
qc.add_gate(
"X",
targets=[0],
classical_controls=[0, 1],
classical_control_value=2,
)
result = qc.run(basis(2, 0), cbits=[1, 0])
fid = qp.fidelity(result, basis(2, 1))
assert pytest.approx(fid, 1.0e-6) == 1

def test_runstatistics_teleportation(self):
"""
Expand Down

0 comments on commit 647a93b

Please sign in to comment.