diff --git a/Control_add.py b/Control_add.py new file mode 100644 index 0000000..1103c05 --- /dev/null +++ b/Control_add.py @@ -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 \ No newline at end of file diff --git a/Multiplier.py b/Multiplier.py new file mode 100644 index 0000000..44b9ddb --- /dev/null +++ b/Multiplier.py @@ -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; diff --git a/main.py b/main.py new file mode 100644 index 0000000..ef28483 --- /dev/null +++ b/main.py @@ -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() \ No newline at end of file