forked from alexandrupaler/standardcells
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from dobbse42/master
controlled addition
- Loading branch information
Showing
3 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |