Skip to content

Commit

Permalink
Merge pull request #1 from dobbse42/master
Browse files Browse the repository at this point in the history
controlled addition
  • Loading branch information
alexandrupaler authored Sep 16, 2021
2 parents 5dded6c + 00c4532 commit 46aa1d2
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
46 changes: 46 additions & 0 deletions Control_add.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import cirq

class ctrl_add:

def __init__(self, ctrl, A, B):
self.size = len(B) - 2
self.ctrl = ctrl
self.A = A
self.B = B

def construct_circuit(self):
circuit = cirq.Circuit()

# step 1
for i in range(1, self.size):
circuit.append(cirq.CNOT(self.A[i], self.B[i]))

# step 2:
circuit.append(cirq.TOFFOLI(self.ctrl, self.A[self.size - 1], self.B[self.size]))
for i in range(self.size - 2, 0, -1):
circuit.append(cirq.CNOT(self.A[i], self.A[i + 1]))

# step 3:
for i in range(0, self.size - 1):
circuit.append(cirq.TOFFOLI(self.A[i], self.B[i], self.A[i + 1]))

# step 4:
circuit.append(cirq.TOFFOLI(self.A[self.size - 1], self.B[self.size - 1], self.B[self.size+1]))
circuit.append(cirq.TOFFOLI(self.ctrl, self.B[self.size+1], self.B[self.size]))
circuit.append(cirq.TOFFOLI(self.A[self.size - 1], self.B[self.size - 1], self.B[self.size+1]))
circuit.append(cirq.TOFFOLI(self.ctrl, self.A[self.size - 1], self.B[self.size - 1]))

# step 5:
for i in range(self.size - 2, -1, -1):
circuit.append(cirq.TOFFOLI(self.A[i], self.B[i], self.A[i + 1]))
circuit.append(cirq.TOFFOLI(self.ctrl, self.A[i], self.B[i]))

# step 6:
for i in range(1, self.size - 1):
circuit.append(cirq.CNOT(self.A[i], self.A[i + 1]))

# step 7:
for i in range(1, self.size):
circuit.append(cirq.CNOT(self.A[i], self.B[i]))

return circuit
54 changes: 54 additions & 0 deletions Multiplier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import cirq
from arithmetic.Control_add import ctrl_add
# testing qubit setup
# circuit.append(cirq.H(q) for q in qubitsA)
# circuit.append(cirq.Z(q) for q in qubitsB)
# circuit.append(cirq.X(q) for q in qubitsOut)


"""
Pseudocode for full multiplier:
//step 1: toffolis
for(int i = 0; i < n; i++)
{
toffoli(qubitsSumnB(0), qubitsSumnA(i), qubitsOut(i);
}
//step 2: ctrladd
for(int i = 0; i < n+1; i++)
{
ctrladd(qubitsSumnB(1), qubitsSumnA(0:i-1), qubitsOut(0:i))
}
for(int i = 0; i < n+1; i++)
{
ctrladd(qubitsSumnB(i), qubitsSumnA, qubitsOut(i:i+n+1)) //ctrl on qubitsSumnB[i], sum mapped to qubitsOut[i:i+n-1],
//the last qubit in qubitsOut(i:i+n) is ancillary. Also it may be n+2 instead of n+1, not sure.
}
"""


# def the following as ctrl_add with ctrl as the ctrl, qubitsSumnA as the bits of one summand, and qubitsSumnB as the
# bits of the other, with the result stored in qubitsSumnB. qubitsSumnA[n] is ancillary, qubitsSumnB[n] = s[4] dot ctrl
# NOTE: The Coreas-Thapliyal paper defines the ancillary bit as A[n+1] and the final sum bit as A[n]. I define them as
# B[n], B[n+1] respectively to stay consistent with the definitions in the multiplier.

class multiplier:

def __init__(self, A, B, out):
self.size = len(A)
self.A = A
self.B = B
self.out = out

def multiply(self):
circuit = cirq.Circuit()
# step 1: toffolis
for i in range(0, self.size):
circuit.append(cirq.TOFFOLI(self.B[0], self.A[i], self.out[i]))
# step 2 (and 3):
for i in range(1, self.size):
circuit += ctrl_add(self.B[i], self.A, self.out[i:i+self.size+2]).construct_circuit()
return circuit;
113 changes: 113 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import cirq
from arithmetic.Multiplier import multiplier
from arithmetic.Control_add import ctrl_add

def main():
circuit = cirq.Circuit()
choice = int(input("1. Add two numbers\n2. Multiply two numbers\n3. Multiply the first n numbers together"))
if(choice == 1):
testAdd(circuit)
if(choice == 2):
testMultiply(circuit)
if(choice == 3):
exampleMultiply()

# simulator = cirq.Simulator()
# result = simulator.run(circuit)

# print(circuit)
# print(result)

def testAdd(circuit): # does not work for two ints using diff number of bits e.g. 7+8 does not work
num1 = int(input("Enter the first summand"))
num2 = int(input("Enter the second summand"))
size = (len(bin(max(num1, num2))))
size -= 2
qubitsTestA = [cirq.GridQubit(0, i) for i in range(size)]
qubitsTestB = [cirq.GridQubit(1, i) for i in range(size + 2)]
ctrl = cirq.GridQubit(2,0)
circuit.append(cirq.X.on(ctrl))
i = size-1
for bit in (bin(num1)[2:]):
if bit == '1':
circuit.append(cirq.X.on(qubitsTestA[i]))
i -= 1
i = size-1
for bit in (bin(num2)[2:]):
print("bit " + str(i) + " = " + bit)
if bit == '1':
circuit.append(cirq.X.on(qubitsTestB[i]))
i -= 1
circuit += ctrl_add(ctrl, qubitsTestA, qubitsTestB).construct_circuit()
circuit.append(cirq.measure(qubitsTestB[i]) for i in range(size+2))
return;

def testMultiply(circuit):
num1 = int(input("Enter the first number to be multiplied"))
num2 = int(input("Enter the second number to be multiplied"))
size = (len(bin(max(num1, num2))))
size -= 2

qubitsTestA = [cirq.GridQubit(0, i) for i in range(size)]
qubitsTestB = [cirq.GridQubit(1, i) for i in range(size)]

i = 0

for bit in reversed((bin(num1)[2:])):
# print("num1 bit " + str(i) + " = " + bit)
if bit == '1':
circuit.append(cirq.X.on(qubitsTestA[i]))
i += 1
i = 0
for bit in reversed((bin(num2)[2:])):
# print("num2 bit " + str(i) + " = " + bit)
if bit == '1':
circuit.append(cirq.X.on(qubitsTestB[i]))
i += 1
qubitsTestOut = [cirq.GridQubit(2, i) for i in range(2*size + 1)]
circuit += multiplier(qubitsTestA, qubitsTestB, qubitsTestOut).multiply()
circuit.append(cirq.measure(qubitsTestOut[i]) for i in range(2*size + 1))
return;

def testMultiply(circuit, num1, num2): #overloaded for the purposes of exampleMultiply
size = (len(bin(max(num1, num2))))
size -= 2

qubitsTestA = [cirq.GridQubit(0, i) for i in range(size)]
qubitsTestB = [cirq.GridQubit(1, i) for i in range(size)]

i = 0

for bit in reversed((bin(num1)[2:])):
# print("num1 bit " + str(i) + " = " + bit)
if bit == '1':
circuit.append(cirq.X.on(qubitsTestA[i]))
i += 1
i = 0
for bit in reversed((bin(num2)[2:])):
# print("num2 bit " + str(i) + " = " + bit)
if bit == '1':
circuit.append(cirq.X.on(qubitsTestB[i]))
i += 1
qubitsTestOut = [cirq.GridQubit(2, i) for i in range(2*size + 1)]
circuit += multiplier(qubitsTestA, qubitsTestB, qubitsTestOut).multiply()
circuit.append(cirq.measure(qubitsTestOut[i]) for i in range(2*size + 1))
return;

def exampleMultiply():
num = int(input("The program will multiply every number between 1 and the number you enter inclusive. Enter the range: "))
for i in range(1,num+1):
for j in range(1, num+1):
circuit = cirq.Circuit()
testMultiply(circuit, i, j)
simulator = cirq.Simulator()
result = simulator.run(circuit)

# print(circuit)
print(i, "*", j, "=")
print(result)
return;


if __name__ == '__main__':
main()

0 comments on commit 46aa1d2

Please sign in to comment.