cnot is generalized to two qubit gate
This commit is contained in:
parent
402ac81f2a
commit
4c4f6bd43b
@ -428,8 +428,8 @@ class HermitianOperator(LinearOperator, HermitianMatrix):
|
|||||||
return str(self.m)
|
return str(self.m)
|
||||||
|
|
||||||
|
|
||||||
# TODO - How to add a CNOT gate to the Quantum Processor?
|
# How to add a CNOT gate to the Quantum Processor?
|
||||||
# Imagine if I have to act on a 3-qubit computer and CNOT(q1, q3)
|
# Imagine if I have to act on a 3-qubit computer and CNOT(q1, q3)
|
||||||
#
|
#
|
||||||
# Decomposed CNOT :
|
# Decomposed CNOT :
|
||||||
# reverse engineered from
|
# reverse engineered from
|
||||||
@ -454,8 +454,8 @@ class TwoQubitPartial(object):
|
|||||||
return str("-{}-".format(self.rpr))
|
return str("-{}-".format(self.rpr))
|
||||||
|
|
||||||
|
|
||||||
C_ = TwoQubitPartial("C")
|
C_partial = TwoQubitPartial("C")
|
||||||
x_ = TwoQubitPartial("x")
|
x_partial = TwoQubitPartial("x")
|
||||||
|
|
||||||
|
|
||||||
class TwoQubitOperator(UnitaryOperator):
|
class TwoQubitOperator(UnitaryOperator):
|
||||||
@ -468,13 +468,16 @@ class TwoQubitOperator(UnitaryOperator):
|
|||||||
self.A_p = A_p
|
self.A_p = A_p
|
||||||
self.B_p = B_p
|
self.B_p = B_p
|
||||||
|
|
||||||
|
A.operator = self
|
||||||
|
B.operator = self
|
||||||
|
|
||||||
def verify_step(self, step):
|
def verify_step(self, step):
|
||||||
if not (step.count(self.A) == 1 and step.count(self.B) == 1):
|
if not (step.count(self.A) == 1 and step.count(self.B) == 1):
|
||||||
raise RuntimeError("Both CONTROL and TARGET need to be defined in the same step exactly once")
|
raise RuntimeError("Both {} and {} need to be defined in the same step exactly once".format(
|
||||||
|
self.A, self.B
|
||||||
|
))
|
||||||
|
|
||||||
def compose(self, step, state):
|
def compose(self, step, state):
|
||||||
# TODO: Hacky way to do CNOT
|
|
||||||
# Should generalize for a 2-Qubit gate
|
|
||||||
# _0.x(_0) * Matrix(I.m) + _1.x(_1) * Matrix(X.m)
|
# _0.x(_0) * Matrix(I.m) + _1.x(_1) * Matrix(X.m)
|
||||||
outer_0, outer_1 = [], []
|
outer_0, outer_1 = [], []
|
||||||
for s in step:
|
for s in step:
|
||||||
@ -555,11 +558,12 @@ Z = UnitaryOperator([[1, 0],
|
|||||||
name="Z")
|
name="Z")
|
||||||
|
|
||||||
|
|
||||||
# TODO: These are rotations that are specified commonly e.g. in
|
# These are rotations that are specified commonly e.g. in
|
||||||
# https://www.quantum-inspire.com/kbase/rotation-operators/
|
# https://www.quantum-inspire.com/kbase/rotation-operators/
|
||||||
# http://www.vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf
|
# http://www.vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf
|
||||||
# and elsewhere DO NOT equate X, Y and Z for theta=np.pi
|
# and elsewhere DO NOT equate X, Y and Z for theta=np.pi
|
||||||
# ??????????????????????????????????????????????????????
|
# However - they are correct up to a global phase which is all that matters for measurement purposes
|
||||||
|
#
|
||||||
|
|
||||||
def Rx(theta):
|
def Rx(theta):
|
||||||
return UnitaryOperator([[np.cos(theta / 2), -1j * np.sin(theta / 2)],
|
return UnitaryOperator([[np.cos(theta / 2), -1j * np.sin(theta / 2)],
|
||||||
@ -578,11 +582,6 @@ def Rz(theta):
|
|||||||
[0, np.power(np.e, 1j * theta / 2)]],
|
[0, np.power(np.e, 1j * theta / 2)]],
|
||||||
name="Rz")
|
name="Rz")
|
||||||
|
|
||||||
|
|
||||||
# def unitary(alpha, vector:Vector, theta):
|
|
||||||
# return np.exp(1j * alpha)
|
|
||||||
|
|
||||||
|
|
||||||
H = UnitaryOperator([[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
H = UnitaryOperator([[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
||||||
[1 / np.sqrt(2), -1 / np.sqrt(2)], ],
|
[1 / np.sqrt(2), -1 / np.sqrt(2)], ],
|
||||||
name="H")
|
name="H")
|
||||||
@ -591,16 +590,7 @@ CNOT = TwoQubitOperator([[1, 0, 0, 0],
|
|||||||
[0, 1, 0, 0],
|
[0, 1, 0, 0],
|
||||||
[0, 0, 0, 1],
|
[0, 0, 0, 1],
|
||||||
[0, 0, 1, 0], ],
|
[0, 0, 1, 0], ],
|
||||||
TwoQubitPartial("C"),
|
C_partial, x_partial, I, X)
|
||||||
TwoQubitPartial("x"),
|
|
||||||
I,
|
|
||||||
X)
|
|
||||||
|
|
||||||
C, x = CNOT.A, CNOT.B
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: End Hacky way to define 2-qbit gate
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
|
|
||||||
def assert_raises(exception, msg, callable, *args, **kwargs):
|
def assert_raises(exception, msg, callable, *args, **kwargs):
|
||||||
@ -664,7 +654,7 @@ class MeasurementOpeartor(HermitianOperator):
|
|||||||
|
|
||||||
def get_prob(self, state: State):
|
def get_prob(self, state: State):
|
||||||
state_ct = state.conjugate_transpose()
|
state_ct = state.conjugate_transpose()
|
||||||
return np.asscalar(state_ct.m.dot(self.m.dot(state.m)))
|
return state_ct.m.dot(self.m.dot(state.m)).item()
|
||||||
|
|
||||||
|
|
||||||
def test_measurement_ops():
|
def test_measurement_ops():
|
||||||
@ -939,24 +929,12 @@ class QuantumCircuit(object):
|
|||||||
self.add_row(row_data)
|
self.add_row(row_data)
|
||||||
|
|
||||||
def compose_quantum_state(self, step):
|
def compose_quantum_state(self, step):
|
||||||
if C in step or x in step:
|
partials = [op for op in step if isinstance(op, TwoQubitPartial)]
|
||||||
if not (step.count(C) == 1 and step.count(x) == 1):
|
# TODO: No more than 1 TwoQubitGate **OR** UnitaryOperator can be used in a step
|
||||||
raise RuntimeError("Both CONTROL and TARGET need to be defined in the same step exactly once")
|
for partial in partials:
|
||||||
# TODO: Hacky way to do CNOT
|
two_qubit_op = partial.operator
|
||||||
# Should generalize for a 2-Qubit gate
|
two_qubit_op.verify_step()
|
||||||
# _0.x(_0) * Matrix(I.m) + _1.x(_1) * Matrix(X.m)
|
return two_qubit_op.compose(step)
|
||||||
outer_0, outer_1 = [], []
|
|
||||||
for s in step:
|
|
||||||
if s == C:
|
|
||||||
outer_0.append(_0.x(_0))
|
|
||||||
outer_1.append(_1.x(_1))
|
|
||||||
elif s == x:
|
|
||||||
outer_0.append(Matrix(I.m))
|
|
||||||
outer_1.append(Matrix(X.m))
|
|
||||||
else:
|
|
||||||
outer_0.append(Matrix(s.m))
|
|
||||||
outer_1.append(Matrix(s.m))
|
|
||||||
return reduce((lambda x, y: x * y), outer_0) + reduce((lambda x, y: x * y), outer_1)
|
|
||||||
return reduce((lambda x, y: x * y), step)
|
return reduce((lambda x, y: x * y), step)
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
@ -1077,9 +1055,9 @@ class QuantumProcessor(object):
|
|||||||
def test_quantum_processor():
|
def test_quantum_processor():
|
||||||
# Produce Bell state between 0 and 2 qubit
|
# Produce Bell state between 0 and 2 qubit
|
||||||
qc = QuantumCircuit(3)
|
qc = QuantumCircuit(3)
|
||||||
qc.add_row([H, C])
|
qc.add_row([H, C_partial])
|
||||||
qc.add_row([_, _])
|
qc.add_row([_, _])
|
||||||
qc.add_row([_, x])
|
qc.add_row([_, x_partial])
|
||||||
qc.print()
|
qc.print()
|
||||||
qp = QuantumProcessor(qc)
|
qp = QuantumProcessor(qc)
|
||||||
qp.get_sample(100)
|
qp.get_sample(100)
|
||||||
|
Loading…
Reference in New Issue
Block a user