Skip to content

Commit

Permalink
Merge a208b0b into 6cc9539
Browse files Browse the repository at this point in the history
  • Loading branch information
hodgestar committed Jun 23, 2021
2 parents 6cc9539 + a208b0b commit 51110b8
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 102 deletions.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ where = src
graphics = matplotlib>=1.3.0
tests =
pytest>=5.2
pytest-repeat
full =
%(graphics)s
%(tests)s
213 changes: 111 additions & 102 deletions src/qutip_qip/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,21 @@
from itertools import product
import numbers

import warnings
import inspect

import numpy as np
from copy import deepcopy

from . import circuit_latex as _latex
from .operations import (Gate, rx, ry, rz, sqrtnot, snot, phasegate,
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,
toffoli, controlled_gate, globalphase,
expand_operator, gate_sequence_product)
from qutip import tensor, basis, identity, ket2dm, qeye
from .operations import (
Gate, rx, ry, rz, sqrtnot, snot, phasegate,
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, toffoli, controlled_gate, globalphase,
expand_operator, gate_sequence_product
)
from .operations.gates import _gate_label
from qutip import basis, ket2dm, qeye
from qutip.qobj import Qobj
from qutip.measurement import measurement_statistics

Expand All @@ -68,6 +67,7 @@ def DisplaySVG(data, *args, **kwargs):
__all__ = ['QubitCircuit', 'Measurement',
'CircuitResult', 'CircuitSimulator']


class Measurement:
"""
Representation of a quantum measurement, with its required parameters,
Expand Down Expand Up @@ -202,7 +202,6 @@ def __init__(self, N, input_states=None, output_states=None,
self.N = N
self.reverse_states = reverse_states
self.gates = []
self.U_list = []
self.dims = dims
self.num_cbits = num_cbits

Expand Down Expand Up @@ -344,8 +343,6 @@ def add_gate(self, gate, targets=None, controls=None, arg_value=None,

else:
for position in index:
num_mes = (sum(isinstance(op, Measurement) for op
in self.gates[:position]))
gate = Gate(name, targets=targets, controls=controls,
arg_value=arg_value, arg_label=arg_label,
classical_controls=classical_controls,
Expand Down Expand Up @@ -569,7 +566,7 @@ def _gate_PHASEGATE(self, gate, temp_resolved):
def _gate_NOTIMPLEMENTED(self, gate, temp_resolved):
raise NotImplementedError("Cannot be resolved in this basis")

_gate_PHASEGATE = _gate_BERKELEY = _gate_SWAPalpha = _gate_NOTIMPLEMENTED
_gate_BERKELEY = _gate_SWAPalpha = _gate_NOTIMPLEMENTED
_gate_SQRTSWAP = _gate_SQRTISWAP = _gate_NOTIMPLEMENTED

def _gate_CSIGN(self, gate, temp_resolved):
Expand Down Expand Up @@ -1238,8 +1235,20 @@ def adjacent_gates(self):

def propagators(self, expand=True):
"""
Propagator matrix calculator for N qubits returning the individual
Propagator matrix calculator returning the individual
steps as unitary matrices operating from left to right.
Parameters
----------
expand : bool, optional
Whether to expand the unitary matrices for the individual
steps to the full Hilbert space for N qubits.
Defaults to ``True``.
If ``False``, the unitary matrices will not be expanded and the
list of unitaries will need to be combined with the list of
gates in order to determine which qubits the unitaries should
act on.
Returns
-------
U_list : list
Expand All @@ -1249,99 +1258,99 @@ def propagators(self, expand=True):
if not expand:
return self.propagators_no_expand()

self.U_list = []
U_list = []

gates = filter(lambda x: isinstance(x, Gate), self.gates)

for gate in gates:
if gate.name == "RX":
self.U_list.append(rx(
U_list.append(rx(
gate.arg_value, self.N, gate.targets[0]))
elif gate.name == "RY":
self.U_list.append(ry(
U_list.append(ry(
gate.arg_value, self.N, gate.targets[0]))
elif gate.name == "RZ":
self.U_list.append(rz(
U_list.append(rz(
gate.arg_value, self.N, gate.targets[0]))
elif gate.name == "X":
self.U_list.append(x_gate(self.N, gate.targets[0]))
U_list.append(x_gate(self.N, gate.targets[0]))
elif gate.name == "Y":
self.U_list.append(y_gate(self.N, gate.targets[0]))
U_list.append(y_gate(self.N, gate.targets[0]))
elif gate.name == "CY":
self.U_list.append(cy_gate(
U_list.append(cy_gate(
self.N, gate.controls[0], gate.targets[0]))
elif gate.name == "Z":
self.U_list.append(z_gate(self.N, gate.targets[0]))
U_list.append(z_gate(self.N, gate.targets[0]))
elif gate.name == "CZ":
self.U_list.append(cz_gate(
U_list.append(cz_gate(
self.N, gate.controls[0], gate.targets[0]))
elif gate.name == "T":
self.U_list.append(t_gate(self.N, gate.targets[0]))
U_list.append(t_gate(self.N, gate.targets[0]))
elif gate.name == "CT":
self.U_list.append(ct_gate(
U_list.append(ct_gate(
self.N, gate.controls[0], gate.targets[0]))
elif gate.name == "S":
self.U_list.append(s_gate(self.N, gate.targets[0]))
U_list.append(s_gate(self.N, gate.targets[0]))
elif gate.name == "CS":
self.U_list.append(cs_gate(
U_list.append(cs_gate(
self.N, gate.controls[0], gate.targets[0]))
elif gate.name == "SQRTNOT":
self.U_list.append(sqrtnot(self.N, gate.targets[0]))
U_list.append(sqrtnot(self.N, gate.targets[0]))
elif gate.name == "SNOT":
self.U_list.append(snot(self.N, gate.targets[0]))
U_list.append(snot(self.N, gate.targets[0]))
elif gate.name == "PHASEGATE":
self.U_list.append(phasegate(gate.arg_value, self.N,
gate.targets[0]))
U_list.append(phasegate(gate.arg_value, self.N,
gate.targets[0]))
elif gate.name == "QASMU":
self.U_list.append(qasmu_gate(gate.arg_value, self.N,
gate.targets[0]))
U_list.append(qasmu_gate(gate.arg_value, self.N,
gate.targets[0]))
elif gate.name == "CRX":
self.U_list.append(controlled_gate(rx(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
U_list.append(controlled_gate(rx(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
elif gate.name == "CRY":
self.U_list.append(controlled_gate(ry(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
U_list.append(controlled_gate(ry(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
elif gate.name == "CRZ":
self.U_list.append(controlled_gate(rz(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
U_list.append(controlled_gate(rz(gate.arg_value),
N=self.N,
control=gate.controls[0],
target=gate.targets[0]))
elif gate.name == "CPHASE":
self.U_list.append(cphase(gate.arg_value, self.N,
gate.controls[0], gate.targets[0]))
U_list.append(cphase(gate.arg_value, self.N,
gate.controls[0], gate.targets[0]))
elif gate.name == "CNOT":
self.U_list.append(cnot(self.N,
gate.controls[0], gate.targets[0]))
U_list.append(cnot(self.N,
gate.controls[0], gate.targets[0]))
elif gate.name == "CSIGN":
self.U_list.append(csign(self.N,
gate.controls[0], gate.targets[0]))
U_list.append(csign(self.N,
gate.controls[0], gate.targets[0]))
elif gate.name == "BERKELEY":
self.U_list.append(berkeley(self.N, gate.targets))
U_list.append(berkeley(self.N, gate.targets))
elif gate.name == "SWAPalpha":
self.U_list.append(swapalpha(gate.arg_value, self.N,
gate.targets))
U_list.append(swapalpha(gate.arg_value, self.N,
gate.targets))
elif gate.name == "SWAP":
self.U_list.append(swap(self.N, gate.targets))
U_list.append(swap(self.N, gate.targets))
elif gate.name == "ISWAP":
self.U_list.append(iswap(self.N, gate.targets))
U_list.append(iswap(self.N, gate.targets))
elif gate.name == "SQRTSWAP":
self.U_list.append(sqrtswap(self.N, gate.targets))
U_list.append(sqrtswap(self.N, gate.targets))
elif gate.name == "SQRTISWAP":
self.U_list.append(sqrtiswap(self.N, gate.targets))
U_list.append(sqrtiswap(self.N, gate.targets))
elif gate.name == "FREDKIN":
self.U_list.append(fredkin(self.N, gate.controls[0],
gate.targets))
U_list.append(fredkin(self.N, gate.controls[0],
gate.targets))
elif gate.name == "TOFFOLI":
self.U_list.append(toffoli(self.N, gate.controls,
gate.targets[0]))
U_list.append(toffoli(self.N, gate.controls,
gate.targets[0]))
elif gate.name == "GLOBALPHASE":
self.U_list.append(globalphase(gate.arg_value, self.N))
U_list.append(globalphase(gate.arg_value, self.N))
elif gate.name == "IDLE":
self.U_list.append(qeye(self.N * [2]))
U_list.append(qeye(self.N * [2]))
elif gate.name in self.user_gates:
if gate.controls is not None:
raise ValueError("A user defined gate {} takes only "
Expand All @@ -1361,13 +1370,13 @@ def propagators(self, expand=True):
oper = func_or_oper
else:
raise ValueError("gate is neither function nor operator")
self.U_list.append(expand_operator(
U_list.append(expand_operator(
oper, N=self.N, targets=gate.targets, dims=self.dims))
else:
raise NotImplementedError(
"{} gate is an unknown gate.".format(gate.name))

return self.U_list
return U_list

def propagators_no_expand(self):
"""
Expand All @@ -1380,75 +1389,75 @@ def propagators_no_expand(self):
Return list of unitary matrices for the qubit circuit.
"""
self.U_list = []
U_list = []

gates = filter(lambda x: isinstance(x, Gate), self.gates)

for gate in gates:
if gate.name == "RX":
self.U_list.append(rx(gate.arg_value))
U_list.append(rx(gate.arg_value))
elif gate.name == "RY":
self.U_list.append(ry(gate.arg_value))
U_list.append(ry(gate.arg_value))
elif gate.name == "RZ":
self.U_list.append(rz(gate.arg_value))
U_list.append(rz(gate.arg_value))
elif gate.name == "X":
self.U_list.append(x_gate())
U_list.append(x_gate())
elif gate.name == "Y":
self.U_list.append(y_gate())
U_list.append(y_gate())
elif gate.name == "CY":
self.U_list.append(cy_gate())
U_list.append(cy_gate())
elif gate.name == "Z":
self.U_list.append(z_gate())
U_list.append(z_gate())
elif gate.name == "CZ":
self.U_list.append(cz_gate())
U_list.append(cz_gate())
elif gate.name == "T":
self.U_list.append(t_gate())
U_list.append(t_gate())
elif gate.name == "CT":
self.U_list.append(ct_gate())
U_list.append(ct_gate())
elif gate.name == "S":
self.U_list.append(s_gate())
U_list.append(s_gate())
elif gate.name == "CS":
self.U_list.append(cs_gate())
U_list.append(cs_gate())
elif gate.name == "SQRTNOT":
self.U_list.append(sqrtnot())
U_list.append(sqrtnot())
elif gate.name == "SNOT":
self.U_list.append(snot())
U_list.append(snot())
elif gate.name == "PHASEGATE":
self.U_list.append(phasegate(gate.arg_value))
U_list.append(phasegate(gate.arg_value))
elif gate.name == "QASMU":
self.U_list.append(qasmu_gate(gate.arg_value))
U_list.append(qasmu_gate(gate.arg_value))
elif gate.name == "CRX":
self.U_list.append(controlled_gate(rx(gate.arg_value)))
U_list.append(controlled_gate(rx(gate.arg_value)))
elif gate.name == "CRY":
self.U_list.append(controlled_gate(ry(gate.arg_value)))
U_list.append(controlled_gate(ry(gate.arg_value)))
elif gate.name == "CRZ":
self.U_list.append(controlled_gate(rz(gate.arg_value)))
U_list.append(controlled_gate(rz(gate.arg_value)))
elif gate.name == "CPHASE":
self.U_list.append(cphase(gate.arg_value))
U_list.append(cphase(gate.arg_value))
elif gate.name == "CNOT":
self.U_list.append(cnot())
U_list.append(cnot())
elif gate.name == "CSIGN":
self.U_list.append(csign())
U_list.append(csign())
elif gate.name == "BERKELEY":
self.U_list.append(berkeley())
U_list.append(berkeley())
elif gate.name == "SWAPalpha":
self.U_list.append(swapalpha(gate.arg_value))
U_list.append(swapalpha(gate.arg_value))
elif gate.name == "SWAP":
self.U_list.append(swap())
U_list.append(swap())
elif gate.name == "ISWAP":
self.U_list.append(iswap())
U_list.append(iswap())
elif gate.name == "SQRTSWAP":
self.U_list.append(sqrtswap())
U_list.append(sqrtswap())
elif gate.name == "SQRTISWAP":
self.U_list.append(sqrtiswap())
U_list.append(sqrtiswap())
elif gate.name == "FREDKIN":
self.U_list.append(fredkin())
U_list.append(fredkin())
elif gate.name == "TOFFOLI":
self.U_list.append(toffoli())
U_list.append(toffoli())
elif gate.name == "GLOBALPHASE":
self.U_list.append(globalphase(gate.arg_value, n))
U_list.append(globalphase(gate.arg_value, self.N))
elif gate.name == "IDLE":
self.U_list.append(qeye(2))
U_list.append(qeye(2))
elif gate.name in self.user_gates:
if gate.controls is not None:
raise ValueError("A user defined gate {} takes only "
Expand All @@ -1468,12 +1477,12 @@ def propagators_no_expand(self):
oper = func_or_oper
else:
raise ValueError("gate is neither function nor operator")
self.U_list.append(oper)
U_list.append(oper)
else:
raise NotImplementedError(
"{} gate is an unknown gate.".format(gate.name))

return self.U_list
return U_list

def latex_code(self):
rows = []
Expand Down

0 comments on commit 51110b8

Please sign in to comment.