cnot is generalized to two qubit gate

This commit is contained in:
Daniel Tsvetkov 2020-02-03 16:15:00 +01:00
parent 402ac81f2a
commit 4c4f6bd43b
1 changed files with 23 additions and 45 deletions

View File

@ -428,8 +428,8 @@ class HermitianOperator(LinearOperator, HermitianMatrix):
return str(self.m)
# TODO - 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)
# 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)
#
# Decomposed CNOT :
# reverse engineered from
@ -454,8 +454,8 @@ class TwoQubitPartial(object):
return str("-{}-".format(self.rpr))
C_ = TwoQubitPartial("C")
x_ = TwoQubitPartial("x")
C_partial = TwoQubitPartial("C")
x_partial = TwoQubitPartial("x")
class TwoQubitOperator(UnitaryOperator):
@ -468,13 +468,16 @@ class TwoQubitOperator(UnitaryOperator):
self.A_p = A_p
self.B_p = B_p
A.operator = self
B.operator = self
def verify_step(self, step):
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):
# 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)
outer_0, outer_1 = [], []
for s in step:
@ -555,11 +558,12 @@ Z = UnitaryOperator([[1, 0],
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/
# 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
# ??????????????????????????????????????????????????????
# However - they are correct up to a global phase which is all that matters for measurement purposes
#
def Rx(theta):
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)]],
name="Rz")
# def unitary(alpha, vector:Vector, theta):
# return np.exp(1j * alpha)
H = UnitaryOperator([[1 / np.sqrt(2), 1 / np.sqrt(2)],
[1 / np.sqrt(2), -1 / np.sqrt(2)], ],
name="H")
@ -591,16 +590,7 @@ CNOT = TwoQubitOperator([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0], ],
TwoQubitPartial("C"),
TwoQubitPartial("x"),
I,
X)
C, x = CNOT.A, CNOT.B
# TODO: End Hacky way to define 2-qbit gate
###########################################################
C_partial, x_partial, I, X)
def assert_raises(exception, msg, callable, *args, **kwargs):
@ -664,7 +654,7 @@ class MeasurementOpeartor(HermitianOperator):
def get_prob(self, state: State):
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():
@ -939,24 +929,12 @@ class QuantumCircuit(object):
self.add_row(row_data)
def compose_quantum_state(self, step):
if C in step or x in step:
if not (step.count(C) == 1 and step.count(x) == 1):
raise RuntimeError("Both CONTROL and TARGET need to be defined in the same step exactly once")
# 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)
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)
partials = [op for op in step if isinstance(op, TwoQubitPartial)]
# TODO: No more than 1 TwoQubitGate **OR** UnitaryOperator can be used in a step
for partial in partials:
two_qubit_op = partial.operator
two_qubit_op.verify_step()
return two_qubit_op.compose(step)
return reduce((lambda x, y: x * y), step)
def step(self):
@ -1077,9 +1055,9 @@ class QuantumProcessor(object):
def test_quantum_processor():
# Produce Bell state between 0 and 2 qubit
qc = QuantumCircuit(3)
qc.add_row([H, C])
qc.add_row([H, C_partial])
qc.add_row([_, _])
qc.add_row([_, x])
qc.add_row([_, x_partial])
qc.print()
qp = QuantumProcessor(qc)
qp.get_sample(100)