Skip to content

Commit

Permalink
quantum circuits inherit user gates from add_circuit (#144)
Browse files Browse the repository at this point in the history
* quantum circuits inherit user gates from add_circuit

The `add_circuit` function in `QuantumCircuit` class used to copy the names of all gates without add the definition of user gates to the target circuit. Hence the user gates cannot be recognized by the new circuit. I made the copy of the definition automatic.
  • Loading branch information
BoxiLi committed May 16, 2022
1 parent 5662577 commit ed1ddad
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 102 deletions.
138 changes: 37 additions & 101 deletions src/qutip_qip/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
expand_operator,
gate_sequence_product,
)
from .operations.gates import _gate_label
from .operations.gates import _gate_label, _single_qubit_gates
from qutip import basis, ket2dm, qeye
from qutip import Qobj
from qutip.measurement import measurement_statistics
Expand Down Expand Up @@ -280,7 +280,7 @@ def add_measurement(
Parameters
----------
name: string
measurement: string
Measurement name. If name is an instance of `Measuremnent`,
parameters are unpacked and added.
targets: list
Expand Down Expand Up @@ -438,20 +438,7 @@ def add_1q_gate(
arg_label : string
Label for gate representation.
"""
if name not in [
"RX",
"RY",
"RZ",
"SNOT",
"SQRTNOT",
"PHASEGATE",
"X",
"Y",
"Z",
"S",
"T",
"QASMU",
]:
if name not in _single_qubit_gates:
raise ValueError("%s is not a single qubit gate" % name)

if qubits is not None:
Expand Down Expand Up @@ -482,7 +469,7 @@ def add_1q_gate(
)
self.gates.append(gate)

def add_circuit(self, qc, start=0):
def add_circuit(self, qc, start=0, overwrite_user_gates=False):
"""
Adds a block of a qubit circuit to the main circuit.
Globalphase gates are not added.
Expand All @@ -497,94 +484,43 @@ def add_circuit(self, qc, start=0):
if self.N - start < qc.N:
raise NotImplementedError("Targets exceed number of qubits.")

# Inherit the user gates
for user_gate in qc.user_gates:
if user_gate in self.user_gates and not overwrite_user_gates:
continue
self.user_gates[user_gate] = qc.user_gates[user_gate]

for circuit_op in qc.gates:

if isinstance(circuit_op, Gate):
gate = circuit_op

if gate.name in [
"RX",
"RY",
"RZ",
"SNOT",
"SQRTNOT",
"PHASEGATE",
"QASMU",
]:
self.add_gate(
gate.name,
gate.targets[0] + start,
None,
gate.arg_value,
gate.arg_label,
)
elif gate.name in ["X", "Y", "Z", "S", "T"]:
self.add_gate(
gate.name,
gate.targets[0] + start,
None,
None,
gate.arg_label,
)
elif gate.name in [
"CPHASE",
"CNOT",
"CSIGN",
"CRX",
"CRY",
"CRZ",
"CY",
"CZ",
"CS",
"CT",
]:
self.add_gate(
gate.name,
gate.targets[0] + start,
gate.controls[0] + start,
gate.arg_value,
gate.arg_label,
)
elif gate.name in [
"BERKELEY",
"SWAPalpha",
"SWAP",
"ISWAP",
"SQRTSWAP",
"SQRTISWAP",
]:
self.add_gate(
gate.name,
[gate.targets[0] + start, gate.targets[1] + start],
)
elif gate.name in ["TOFFOLI"]:
self.add_gate(
gate.name,
gate.targets[0] + start,
[gate.controls[0] + start, gate.controls[1] + start],
None,
None,
)
elif gate.name in ["FREDKIN"]:
self.add_gate(
gate.name,
[gate.targets[0] + start, gate.targets[1] + start],
gate.controls + start,
None,
None,
)
elif gate.name in self.user_gates:
self.add_gate(
gate.name,
targets=gate.targets,
arg_value=gate.arg_value,
)
else:
measurement = circuit_op

if circuit_op.targets is not None:
tar = [target + start for target in circuit_op.targets]
else:
tar = None
if circuit_op.controls is not None:
ctrl = [control + start for control in circuit_op.controls]
else:
ctrl = None

self.add_gate(
circuit_op.name,
targets=tar,
controls=ctrl,
arg_value=circuit_op.arg_value,
)
elif isinstance(circuit_op, Measurement):
self.add_measurement(
measurement.name,
targets=[measurement.targets[0] + start],
classical_store=measurement.classical_store,
circuit_op.name,
targets=[target + start for target in circuit_op.targets],
classical_store=circuit_op.classical_store,
)
else:
raise TypeError(
"The circuit to be added contains unknown \
operator {}".format(
circuit_op
)
)

def remove_gate_or_measurement(
Expand Down
2 changes: 1 addition & 1 deletion src/qutip_qip/operations/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@

class Gate:
"""
Representation of a quantum gate, with its required parametrs, and target
Representation of a quantum gate, with its required parameters, and target
and control qubits.
Parameters
Expand Down
18 changes: 18 additions & 0 deletions tests/test_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@ def test_add_circuit(self):
"""
Addition of a circuit to a `QubitCircuit`
"""

def customer_gate1(arg_values):
mat = np.zeros((4, 4), dtype=np.complex128)
mat[0, 0] = mat[1, 1] = 1.
mat[2:4, 2:4] = gates.rx(arg_values)
return Qobj(mat, dims=[[2, 2], [2, 2]])

qc = QubitCircuit(6)
qc.user_gates = {"CTRLRX": customer_gate1}

qc = QubitCircuit(6)
qc.add_gate("CNOT", targets=[1], controls=[0])
test_gate = Gate("SWAP", targets=[1, 4])
Expand All @@ -289,6 +299,7 @@ def test_add_circuit(self):
qc.add_gate(test_gate, index=[3])
qc.add_measurement("M0", targets=[0], classical_store=[1])
qc.add_1q_gate("RY", start=4, end=5, arg_value=1.570796)
qc.add_gate("CTRLRX", targets=[1, 2], arg_value=np.pi/2)

qc1 = QubitCircuit(6)

Expand All @@ -297,6 +308,9 @@ def test_add_circuit(self):
# Test if all gates and measurements are added
assert len(qc1.gates) == len(qc.gates)

# Test if the definitions of user gates are added
assert qc1.user_gates == qc.user_gates

for i in range(len(qc1.gates)):
assert (qc1.gates[i].name
== qc.gates[i].name)
Expand Down Expand Up @@ -332,6 +346,10 @@ def test_add_circuit(self):
assert (qc2.gates[i].controls[0]
== qc.gates[i].controls[0]+2)

# Test exception when the operators to be added are not gates or measurements
qc.gates[-1] = 0
pytest.raises(TypeError, qc2.add_circuit, qc)

def test_add_state(self):
"""
Addition of input and output states to a circuit.
Expand Down

0 comments on commit ed1ddad

Please sign in to comment.