├── README.md ├── LICENSE ├── sieve.py ├── Basic_gates.py ├── Shor_version1_5bit_hardware.py ├── control_unitaries.py └── Shor_version2_5bit_simulation.py /README.md: -------------------------------------------------------------------------------- 1 | # Shor-s-Algorithm-on-IBM-Quantum-Experience 2 | 3 | Developed By: 4 | [Pinakin Padalia](https://github.com/pinpad9) & [Amitabh Yadav](https://github.com/amitabhyadav/) 5 | 6 | Running Shor's Algorithm using IBM Quantum Experience and Measuring the result by implementation on IBM's 5-Qubit Quantum Computer (Raven). 7 | - Reference: 8 | 9 | [Realization of a scalable Shor algorithm](https://arxiv.org/abs/1507.08852), 10 | 11 | [Presentation](http://amitabhyadav.github.io/files/shor_final.pdf) 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Amitabh Yadav 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sieve.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | def sieve_of_eratosthenes(n): 4 | primes = range(3, n + 1, 2) # primes above 2 must be odd so start at three and increase by 2 5 | for base in xrange(len(primes)): 6 | if primes[base] is None: 7 | continue 8 | if primes[base] >= sqrt(n): # stop at sqrt of n 9 | break 10 | for i in xrange(base + (base + 1) * primes[base], len(primes), primes[base]): 11 | primes[i] = None 12 | primes.insert(0,2) 13 | sieve=filter(None, primes) 14 | return sieve 15 | 16 | def prime_factor(sieve,n): 17 | p_f = [] 18 | for prime in sieve: 19 | while n % prime == 0: 20 | p_f.append(prime) 21 | n /= prime 22 | if n > 1: 23 | p_f.append(n) 24 | return p_f 25 | 26 | def p_fctr_exp(s,n): 27 | primes = prime_factor(s,n) 28 | exp=[] 29 | for p in primes: 30 | e=0 31 | while (n%p==0): 32 | n=n//p # since p still divides n, 33 | e+=1 # we divide n by p and increase the exponent 34 | exp.append(e) 35 | return exp 36 | 37 | def checkEqual1(iterator): 38 | iterator = iter(iterator) 39 | try: 40 | first = next(iterator) 41 | except StopIteration: 42 | return True 43 | return all(first == rest for rest in iterator) 44 | 45 | num = input("Enter a number: ") 46 | sieve = sieve_of_eratosthenes(num) 47 | pf = prime_factor(sieve,num) 48 | expo = p_fctr_exp(sieve,num) 49 | print pf 50 | print expo 51 | chk = checkEqual1(pf) 52 | print chk 53 | if chk == True: 54 | print pf[0] 55 | print expo[0] 56 | input() 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Basic_gates.py: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------------------------------------- 2 | # This module contains basic gates that can be used while developing circuits on IBM QExperience 3 | #-------------------------------------------------------------------------------------------------------------- 4 | 5 | #-------------------------------------------------------------------------------------------------------------- 6 | # Import necessary modules 7 | #-------------------------------------------------------------------------------------------------------------- 8 | from qiskit import QuantumProgram 9 | import Qconfig 10 | 11 | #-------------------------------------------------------------------------------------------------------------- 12 | # The CSWAP gate 13 | # Input : Quantum program object, the Circuit name, the quantum register name, control bit number and target 14 | # bit numbers. 15 | # Output : Quantum_program_object with the relevant connections 16 | # Circuit implemented - CSWAP 17 | #-------------------------------------------------------------------------------------------------------------- 18 | def CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,Target_bit_numbers): 19 | 20 | # Get the circuit and the quantum register by name 21 | qc = Quantum_program_object.get_circuit(Circuit_name) 22 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 23 | 24 | # Get control bit numbers and the target bit number for the addressing the qubits 25 | Control = Control_bit_number 26 | Target_1 = Target_bit_numbers[0] 27 | Target_2 = Target_bit_numbers[1] 28 | 29 | # Implement CSWAP using 3 CCNOT implementations 30 | 31 | # Implement CCNOT on Control,Target_1 and Target_2 using decomposition given by Nelson and Chuang 32 | qc.h(qr[Target_2]) 33 | qc.cx(qr[Target_1],qr[Target_2]) 34 | qc.tdg(qr[Target_2]) 35 | qc.cx(qr[Control],qr[Target_2]) 36 | qc.t(qr[Target_2]) 37 | qc.cx(qr[Target_1],qr[Target_2]) 38 | qc.tdg(qr[Target_2]) 39 | qc.cx(qr[Control],qr[Target_2]) 40 | qc.tdg(qr[Target_1]) 41 | qc.t(qr[Target_2]) 42 | qc.h(qr[Target_2]) 43 | qc.cx(qr[Control],qr[Target_1]) 44 | qc.tdg(qr[Target_1]) 45 | qc.cx(qr[Control],qr[Target_1]) 46 | qc.t(qr[Control]) 47 | qc.s(qr[Target_1]) 48 | 49 | # Implement CCNOT on Control,Target_2 and Target_1 using decomposition given by Nelson and Chuang 50 | qc.h(qr[Target_1]) 51 | qc.cx(qr[Target_2],qr[Target_1]) 52 | qc.tdg(qr[Target_1]) 53 | qc.cx(qr[Control],qr[Target_1]) 54 | qc.t(qr[Target_1]) 55 | qc.cx(qr[Target_2],qr[Target_1]) 56 | qc.tdg(qr[Target_1]) 57 | qc.cx(qr[Control],qr[Target_1]) 58 | qc.tdg(qr[Target_2]) 59 | qc.t(qr[Target_1]) 60 | qc.h(qr[Target_1]) 61 | qc.cx(qr[Control],qr[Target_2]) 62 | qc.tdg(qr[Target_2]) 63 | qc.cx(qr[Control],qr[Target_2]) 64 | qc.t(qr[Control]) 65 | qc.s(qr[Target_2]) 66 | 67 | # Implement CCNOT on Control,Target_1 and Target_2 using decomposition given by Nelson and Chuang 68 | qc.h(qr[Target_2]) 69 | qc.cx(qr[Target_1],qr[Target_2]) 70 | qc.tdg(qr[Target_2]) 71 | qc.cx(qr[Control],qr[Target_2]) 72 | qc.t(qr[Target_2]) 73 | qc.cx(qr[Target_1],qr[Target_2]) 74 | qc.tdg(qr[Target_2]) 75 | qc.cx(qr[Control],qr[Target_2]) 76 | qc.tdg(qr[Target_1]) 77 | qc.t(qr[Target_2]) 78 | qc.h(qr[Target_2]) 79 | qc.cx(qr[Control],qr[Target_1]) 80 | qc.tdg(qr[Target_1]) 81 | qc.cx(qr[Control],qr[Target_1]) 82 | qc.t(qr[Control]) 83 | qc.s(qr[Target_1]) 84 | 85 | # Return the program object 86 | return Quantum_program_object 87 | 88 | 89 | #-------------------------------------------------------------------------------------------------------------- 90 | # The CCNOT gate 91 | # Input : Quantum program object, the Circuit name, the quantum register name, control bit numbers and target 92 | # bit number. 93 | # Output : Quantum_program_object with the relevant connections 94 | # Circuit implemented - CCNOT 95 | #-------------------------------------------------------------------------------------------------------------- 96 | def CCNOT(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_numbers,Target_bit_number): 97 | 98 | # Get the circuit and the quantum register by name 99 | qc = Quantum_program_object.get_circuit(Circuit_name) 100 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 101 | 102 | # Get control bit numbers and the target bit number for the addressing the qubits 103 | Control_1 = Control_bit_numbers[0] 104 | Control_2 = Control_bit_numbers[1] 105 | Target = Target_bit_number 106 | 107 | # Implement Hadamard on target qubits 108 | qc.h(qr[Target]) 109 | 110 | # Implement CNOT between Control_2 and Target 111 | qc.cx(qr[Control_2],qr[Target]) 112 | 113 | # Implement T (dagger) on target qubits 114 | qc.tdg(qr[Target]) 115 | 116 | # Implement CNOT between Control_1 and Target 117 | qc.cx(qr[Control_1],qr[Target]) 118 | 119 | # Implement T on target qubits 120 | qc.t(qr[Target]) 121 | 122 | # Implement CNOT between Control_2 and Target 123 | qc.cx(qr[Control_2],qr[Target]) 124 | 125 | # Implement T (dagger) on target qubits 126 | qc.tdg(qr[Target]) 127 | 128 | # Implement CNOT between Control_1 and Target 129 | qc.cx(qr[Control_1],qr[Target]) 130 | 131 | # Implement T (dagger) on Control_2, T and H on Target 132 | qc.tdg(qr[Control_2]) 133 | qc.t(qr[Target]) 134 | qc.h(qr[Target]) 135 | 136 | # Implement CNOT from Control_1 to Control_2 followed by T (dagger) on Control_2 137 | qc.cx(qr[Control_1],qr[Control_2]) 138 | qc.tdg(qr[Control_2]) 139 | 140 | # Implement CNOT from Control_1 to Control_2 followed by T on Control_1 and S on Control_2 141 | qc.cx(qr[Control_1],qr[Control_2]) 142 | qc.t(qr[Control_1]) 143 | qc.s(qr[Control_2]) 144 | 145 | # Return the program object 146 | return Quantum_program_object 147 | -------------------------------------------------------------------------------- /Shor_version1_5bit_hardware.py: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------------------------------------- 2 | # Import necessary modules 3 | #-------------------------------------------------------------------------------------------------------------- 4 | import sys 5 | from qiskit import QuantumProgram 6 | import Qconfig 7 | import Basic_gates 8 | import math 9 | from random import randint 10 | import control_unitaries 11 | 12 | #-------------------------------------------------------------------------------------------------------------- 13 | # global variables 14 | #-------------------------------------------------------------------------------------------------------------- 15 | Counts = 0 16 | #-------------------------------------------------------------------------------------------------------------- 17 | # The function to compute GCD using Euclid's method 18 | # Input : Two number to X and Y for which a GCD is to be computed 19 | # Output : GCD of two given numbers 20 | #-------------------------------------------------------------------------------------------------------------- 21 | def gcd(x,y): 22 | while y != 0: 23 | (x, y) = (y, x % y) 24 | return x 25 | 26 | #-------------------------------------------------------------------------------------------------------------- 27 | # The function to compute QFT 28 | # Input : Circuit, quantum bits, and number of quantum bits 29 | # Output : None. Circuit is created and saved 30 | #-------------------------------------------------------------------------------------------------------------- 31 | def qft(Quantum_program_object,Circuit_name,Quantum_register_name,Smallest_Quantum_register_number,Size_of_QFT): 32 | # Get the circuit and the quantum register by name 33 | qc = Quantum_program_object.get_circuit(Circuit_name) 34 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 35 | s = Smallest_Quantum_register_number 36 | for j in range(Size_of_QFT): 37 | for k in range(j): 38 | qc.cu1(math.pi/float(2**(j-k)), qr[s+j], qr[s+k]) 39 | qc.h(qr[s+j]) 40 | 41 | #-------------------------------------------------------------------------------------------------------------- 42 | # The function to find period using the Quantum computer 43 | # Input : a and N for which the period is to be computed. 44 | # Output : period r of the function a^x mod N 45 | #-------------------------------------------------------------------------------------------------------------- 46 | def period(a,N): 47 | # Create the first QuantumProgram object instance. 48 | qp = QuantumProgram() 49 | qp.set_api(Qconfig.APItoken, Qconfig.config["url"]) 50 | # TO DO : generalize the number of qubits and give proper security against rogue input. 51 | # Create the first Quantum Register called "qr" with 12 qubits 52 | qr = qp.create_quantum_register('qr', 5) 53 | # Create your first Classical Register called "cr" with 12 bits 54 | cr = qp.create_classical_register('cr', 3) 55 | 56 | # Create the first Quantum Circuit called "qc" involving your Quantum Register "qr" 57 | # and the Classical Register "cr" 58 | qc = qp.create_circuit('Period_Finding', [qr], [cr]) 59 | 60 | # Get the circuit and the registers by name 61 | Shor1 = qp.get_circuit('Period_Finding') 62 | Q_reg = qp.get_quantum_register('qr') 63 | C_reg = qp.get_classical_register('cr') 64 | 65 | # Create the circuit for period finding 66 | # Initialize qr[0] to |1> and create a superposition on the top 8 qubits 67 | Shor1.x(Q_reg[0]) 68 | 69 | # Step one : apply 11**4 mod 15 70 | Shor1.h(Q_reg[2]) 71 | # Controlled Identity to remaining gates which is equivalent to doing nothing 72 | Shor1.h(Q_reg[2]) 73 | Shor1.measure(Q_reg[2],C_reg[0]) 74 | # Reinitialize to |0> 75 | Shor1.reset(Q_reg[2]) 76 | 77 | # Step two : apply 11**2 mod 15 78 | Shor1.h(Q_reg[2]) 79 | # Controlled Identity to remaining gates which is equivalent to doing nothing 80 | if C_reg[0] == 1 : 81 | Shor1.u1(pi/2.0,Q_reg[2]) 82 | Shor1.h(Q_reg[2]) 83 | Shor1.measure(Q_reg[2],C_reg[1]) 84 | # Reinitialize to |0> 85 | Shor1.reset(Q_reg[2]) 86 | 87 | # Step three : apply 11 mod 15 88 | Shor1.h(Q_reg[2]) 89 | # Controlled nots in between to remaining gates which is equivalent to doing nothing 90 | Shor1.cx(Q_reg[2],Q_reg[1]) 91 | Shor1.cx(Q_reg[2],Q_reg[4]) 92 | # Feed forward and measure 93 | if C_reg[1] == 1 : 94 | Shor1.u1(pi/2.0,Q_reg[2]) 95 | if C_reg[0] == 1 : 96 | Shor1.u1(pi/4.0,Q_reg[2]) 97 | Shor1.h(Q_reg[2]) 98 | Shor1.measure(Q_reg[2],C_reg[2]) 99 | 100 | # Run the circuit 101 | while True: 102 | global Counts 103 | Counts = Counts + 1 104 | qp.set_api(Qconfig.APItoken, Qconfig.config['url']) # set the APIToken and API url 105 | simulate = qp.execute(["Period_Finding"], backend="ibmqx4", shots=1,timeout=500) 106 | simulate.get_counts("Period_Finding") 107 | #print(simulate) 108 | data = simulate.get_counts("Period_Finding") 109 | #print(data) 110 | data = list(data.keys()) 111 | #print(data) 112 | r = int(data[0]) 113 | #print(r) 114 | l = gcd(2**3,r) 115 | #print(l) 116 | r = int((2**3)/l) 117 | #print(r) 118 | if (r%2 == 0) and (((a**(r/2))+1)%N != 0) and (r != 0) and (r != 8): 119 | break 120 | return r 121 | 122 | #-------------------------------------------------------------------------------------------------------------- 123 | # The main function to compute factors 124 | # Input : The number to be factored, N 125 | # Output : Factors of the number 126 | #-------------------------------------------------------------------------------------------------------------- 127 | def Factorize_N(N): 128 | factors = [0,0] 129 | #-------------------------------------------------------------------------------------------------------------- 130 | # Step 1 : Determine the number of bits based on N; n = [log2(N)] 131 | #-------------------------------------------------------------------------------------------------------------- 132 | n = math.ceil(math.log(N,2)) 133 | #-------------------------------------------------------------------------------------------------------------- 134 | # Step 2 : Check if N is even. In that case return 2 and the remaining number as factors 135 | #-------------------------------------------------------------------------------------------------------------- 136 | if N % 2 == 0: 137 | factors = [2,N/2] 138 | return factors 139 | #-------------------------------------------------------------------------------------------------------------- 140 | # Step 3 : Check if N is of the form P^(k), where P is some prime factor. In that case return P and k. 141 | #-------------------------------------------------------------------------------------------------------------- 142 | 143 | #-------------------------------------------------------------------------------------------------------------- 144 | # Step 4 : Choose a random number between 2...(N-1). 145 | #-------------------------------------------------------------------------------------------------------------- 146 | a = randint(2,N-1) 147 | a = 11 148 | #-------------------------------------------------------------------------------------------------------------- 149 | # Step 5 : Take GCD of a and N. t = GCD(a,N) 150 | #-------------------------------------------------------------------------------------------------------------- 151 | t = gcd(N,a) 152 | if t > 1: 153 | factors = [t,N/t] 154 | return factors 155 | #-------------------------------------------------------------------------------------------------------------- 156 | # Step 6 : t = 1. Hence, no common period. Find Period using Shor's method 157 | #-------------------------------------------------------------------------------------------------------------- 158 | r = period(a,N) 159 | factor_1 = gcd((a**(r/2))+1,N) 160 | factor_2 = N/factor_1 161 | factors = [factor_1,factor_2] 162 | return factors 163 | 164 | #-------------------------------------------------------------------------------------------------------------- 165 | # Running the Shor's algorithm version 1 166 | #-------------------------------------------------------------------------------------------------------------- 167 | 168 | #-------------------------------------------------------------------------------------------------------------- 169 | # Step 0 : Take the input N 170 | #-------------------------------------------------------------------------------------------------------------- 171 | 172 | if __name__ == '__main__': 173 | N = 15 174 | factors = Factorize_N(N) 175 | print("The Number being factorized is : 15 with a = 11") 176 | print("Factors are = ",factors) 177 | print("Number of times the circuit looped to find out the period = ",Counts) 178 | -------------------------------------------------------------------------------- /control_unitaries.py: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------------------------------------- 2 | # This module contains control unitaries that can be used while developing circuits on IBM QExperience 3 | #-------------------------------------------------------------------------------------------------------------- 4 | 5 | #-------------------------------------------------------------------------------------------------------------- 6 | # Import necessary modules 7 | #-------------------------------------------------------------------------------------------------------------- 8 | from qiskit import QuantumProgram 9 | import Qconfig 10 | import Basic_gates 11 | # TODO make it more generalized 12 | #-------------------------------------------------------------------------------------------------------------- 13 | # The control unitary for 2mod15 on 4 quantum qubits 14 | # Input : Quantum program object, the Circuit name and the quantum register name, and the 15 | # control bit number where the connections are supposed to be made 16 | # Output : Quantum_program_object with the relevant connections 17 | # Circuit implemented - CSwap(Q[3],Q[2])->CSwap(Q[2],Q[1])->CSwap(Q[1],Q[0]) 18 | #-------------------------------------------------------------------------------------------------------------- 19 | def C_2mod15(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number): 20 | 21 | # Get the circuit and the quantum register by name 22 | qc = Quantum_program_object.get_circuit(Circuit_name) 23 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 24 | 25 | Control_bit_number = Control_bit_number 26 | 27 | # Implement controlled swap on qr[3] and qr[2] 28 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[3,2]) 29 | 30 | # Implement controlled swap on qr[2] and qr[1] 31 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[2,1]) 32 | 33 | # Implement controlled swap on qr[1] and qr[0] 34 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[1,0]) 35 | 36 | # Return the program object 37 | return Quantum_program_object 38 | 39 | #-------------------------------------------------------------------------------------------------------------- 40 | # The control unitary for 7mod15 on 4 quantum qubits 41 | # Input : Quantum program object, the Circuit name and the quantum register name, and the 42 | # control bit number where the connections are supposed to be made 43 | # Output : Quantum_program_object with the relevant connections 44 | # Circuit implemented - CSwap(Q[1],Q[0])->CSwap(Q[1],Q[2])->CSwap(Q[2],Q[3])->CX on all 4 qubits 45 | #-------------------------------------------------------------------------------------------------------------- 46 | def C_7mod15(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number): 47 | 48 | # Get the circuit and the quantum register by name 49 | qc = Quantum_program_object.get_circuit(Circuit_name) 50 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 51 | 52 | Control_bit_number = Control_bit_number 53 | 54 | # Implement controlled swap on qr[1] and qr[0] 55 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[1,0]) 56 | 57 | # Implement controlled swap on qr[2] and qr[1] 58 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[2,1]) 59 | 60 | # Implement controlled swap on qr[3] and qr[2] 61 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[3,2]) 62 | 63 | # Implement CX on all four qubits 64 | qc.cx(Control_bit_number,qr[3]) 65 | qc.cx(Control_bit_number,qr[2]) 66 | qc.cx(Control_bit_number,qr[1]) 67 | qc.cx(Control_bit_number,qr[0]) 68 | 69 | # Return the program object 70 | return Quantum_program_object 71 | 72 | #-------------------------------------------------------------------------------------------------------------- 73 | # The control unitary for 8mod15 on 4 quantum qubits 74 | # Input : Quantum program object, the Circuit name and the quantum register name, and the 75 | # control bit number where the connections are supposed to be made 76 | # Output : Quantum_program_object with the relevant connections 77 | # Circuit implemented - CSwap(Q[1],Q[0])->CSwap(Q[1],Q[2])->CSwap(Q[2],Q[3]) 78 | #-------------------------------------------------------------------------------------------------------------- 79 | def C_8mod15(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number): 80 | 81 | # Get the circuit and the quantum register by name 82 | qc = Quantum_program_object.get_circuit(Circuit_name) 83 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 84 | 85 | Control_bit_number = Control_bit_number 86 | 87 | # Implement controlled swap on qr[1] and qr[0] 88 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[1,0]) 89 | 90 | # Implement controlled swap on qr[2] and qr[1] 91 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[2,1]) 92 | 93 | # Implement controlled swap on qr[3] and qr[2] 94 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[3,2]) 95 | 96 | # Return the program object 97 | return Quantum_program_object 98 | 99 | #-------------------------------------------------------------------------------------------------------------- 100 | # The control unitary for 11mod15 on 4 quantum qubits 101 | # Input : Quantum program object, the Circuit name and the quantum register name, and the 102 | # control bit number where the connections are supposed to be made 103 | # Output : Quantum_program_object with the relevant connections 104 | # Circuit implemented - CSwap(Q[2],Q[0])->CSwap(Q[3],Q[1])->CX on all 4 qubits 105 | #-------------------------------------------------------------------------------------------------------------- 106 | def C_11mod15(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number): 107 | 108 | # Get the circuit and the quantum register by name 109 | qc = Quantum_program_object.get_circuit(Circuit_name) 110 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 111 | 112 | Control_bit_number = Control_bit_number 113 | 114 | # Implement controlled swap on qr[2] and qr[0] 115 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[2,0]) 116 | 117 | # Implement controlled swap on qr[3] and qr[1] 118 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[3,1]) 119 | 120 | # Implement CX on all four qubits 121 | qc.cx(Control_bit_number,qr[3]) 122 | qc.cx(Control_bit_number,qr[2]) 123 | qc.cx(Control_bit_number,qr[1]) 124 | qc.cx(Control_bit_number,qr[0]) 125 | 126 | # Return the program object 127 | return Quantum_program_object 128 | 129 | #-------------------------------------------------------------------------------------------------------------- 130 | # The control unitary for 13mod15 on 4 quantum qubits 131 | # Input : Quantum program object, the Circuit name and the quantum register name, and the 132 | # control bit number where the connections are supposed to be made 133 | # Output : Quantum_program_object with the relevant connections 134 | # Circuit implemented - CSwap(Q[3],Q[2])->CSwap(Q[2],Q[1])->CSwap(Q[1],Q[0])->CX on all 4 qubits 135 | #-------------------------------------------------------------------------------------------------------------- 136 | def C_13mod15(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number): 137 | 138 | # Get the circuit and the quantum register by name 139 | qc = Quantum_program_object.get_circuit(Circuit_name) 140 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 141 | 142 | Control_bit_number = Control_bit_number 143 | 144 | # Implement controlled swap on qr[3] and qr[2] 145 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[3,2]) 146 | 147 | # Implement controlled swap on qr[2] and qr[1] 148 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[2,1]) 149 | 150 | # Implement controlled swap on qr[1] and qr[0] 151 | Basic_gates.CSWAP(Quantum_program_object,Circuit_name,Quantum_register_name,Control_bit_number,[1,0]) 152 | 153 | # Implement CX on all four qubits 154 | qc.cx(Control_bit_number,qr[3]) 155 | qc.cx(Control_bit_number,qr[2]) 156 | qc.cx(Control_bit_number,qr[1]) 157 | qc.cx(Control_bit_number,qr[0]) 158 | 159 | # Return the program object 160 | return Quantum_program_object 161 | -------------------------------------------------------------------------------- /Shor_version2_5bit_simulation.py: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------------------------------------- 2 | # Import necessary modules 3 | #-------------------------------------------------------------------------------------------------------------- 4 | import sys 5 | from qiskit import QuantumProgram 6 | import Qconfig 7 | import Basic_gates 8 | import math 9 | from random import randint 10 | import control_unitaries 11 | import xlsxwriter 12 | #-------------------------------------------------------------------------------------------------------------- 13 | # global variables 14 | #-------------------------------------------------------------------------------------------------------------- 15 | Counts = 0 16 | A = 0 17 | Ran_Quantum_period_finding = 0 18 | global m 19 | m = 0 20 | #-------------------------------------------------------------------------------------------------------------- 21 | # The function to compute GCD using Euclid's method 22 | # Input : Two number to X and Y for which a GCD is to be computed 23 | # Output : GCD of two given numbers 24 | #-------------------------------------------------------------------------------------------------------------- 25 | def gcd(x,y): 26 | while y != 0: 27 | (x, y) = (y, x % y) 28 | return x 29 | 30 | #-------------------------------------------------------------------------------------------------------------- 31 | # The function to construct the unitary based on a 32 | # Input : Quantum program object, the Circuit name and the quantum register name, and a 33 | # Output : None. The relevant circuit is made. 34 | #-------------------------------------------------------------------------------------------------------------- 35 | def cmod(Quantum_program_object,Circuit_name,Quantum_register_name,a): 36 | # Get the circuit and the quantum register by name 37 | qc = Quantum_program_object.get_circuit(Circuit_name) 38 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 39 | 40 | # Construct unitary based on a 41 | if a == 2: 42 | qc.cswap(qr[4],qr[3],qr[2]) 43 | qc.cswap(qr[4],qr[2],qr[1]) 44 | qc.cswap(qr[4],qr[1],qr[0]) 45 | if a == 4 or a == 11 or a == 14: 46 | qc.cswap(qr[4],qr[2],qr[0]) 47 | qc.cswap(qr[4],qr[3],qr[1]) 48 | qc.cx(qr[4],qr[3]) 49 | qc.cx(qr[4],qr[2]) 50 | qc.cx(qr[4],qr[1]) 51 | qc.cx(qr[4],qr[0]) 52 | if a == 7: 53 | qc.cswap(qr[4],qr[1],qr[0]) 54 | qc.cswap(qr[4],qr[2],qr[1]) 55 | qc.cswap(qr[4],qr[3],qr[2]) 56 | qc.cx(qr[4],qr[3]) 57 | qc.cx(qr[4],qr[2]) 58 | qc.cx(qr[4],qr[1]) 59 | qc.cx(qr[4],qr[0]) 60 | if a == 8: 61 | qc.cswap(qr[4],qr[1],qr[0]) 62 | qc.cswap(qr[4],qr[2],qr[1]) 63 | qc.cswap(qr[4],qr[3],qr[2]) 64 | if a == 13: 65 | qc.cswap(qr[4],qr[3],qr[2]) 66 | qc.cswap(qr[4],qr[2],qr[1]) 67 | qc.cswap(qr[4],qr[1],qr[0]) 68 | qc.cx(qr[4],qr[3]) 69 | qc.cx(qr[4],qr[2]) 70 | qc.cx(qr[4],qr[1]) 71 | qc.cx(qr[4],qr[0]) 72 | 73 | #-------------------------------------------------------------------------------------------------------------- 74 | # The function to compute QFT 75 | # Input : Circuit, quantum bits, and number of quantum bits 76 | # Output : None. Circuit is created and saved 77 | #-------------------------------------------------------------------------------------------------------------- 78 | def qft(Quantum_program_object,Circuit_name,Quantum_register_name,Smallest_Quantum_register_number,Size_of_QFT): 79 | # Get the circuit and the quantum register by name 80 | qc = Quantum_program_object.get_circuit(Circuit_name) 81 | qr = Quantum_program_object.get_quantum_register(Quantum_register_name) 82 | s = Smallest_Quantum_register_number 83 | for j in range(Size_of_QFT): 84 | for k in range(j): 85 | qc.cu1(math.pi/float(2**(j-k)), qr[s+j], qr[s+k]) 86 | qc.h(qr[s+j]) 87 | 88 | #-------------------------------------------------------------------------------------------------------------- 89 | # The function to find period using the Quantum computer 90 | # Input : a and N for which the period is to be computed. 91 | # Output : period r of the function a^x mod N 92 | #-------------------------------------------------------------------------------------------------------------- 93 | def period(a,N): 94 | global Ran_Quantum_period_finding 95 | Ran_Quantum_period_finding = 1 96 | # Create the first QuantumProgram object instance. 97 | qp = QuantumProgram() 98 | #qp.set_api(Qconfig.APItoken, Qconfig.config["url"]) 99 | # TO DO : generalize the number of qubits and give proper security against rogue input. 100 | # Create the first Quantum Register called "qr" with 12 qubits 101 | qr = qp.create_quantum_register('qr', 5) 102 | # Create your first Classical Register called "cr" with 12 bits 103 | cr = qp.create_classical_register('cr', 3) 104 | 105 | # Create the first Quantum Circuit called "qc" involving your Quantum Register "qr" 106 | # and the Classical Register "cr" 107 | qc = qp.create_circuit('Period_Finding', [qr], [cr]) 108 | 109 | # Get the circuit and the registers by name 110 | Shor1 = qp.get_circuit('Period_Finding') 111 | Q_reg = qp.get_quantum_register('qr') 112 | C_reg = qp.get_classical_register('cr') 113 | 114 | # Create the circuit for period finding 115 | # Initialize qr[0] to |1> 116 | Shor1.x(Q_reg[0]) 117 | 118 | # Step one : apply a**4 mod 15 119 | Shor1.h(Q_reg[4]) 120 | # Controlled Identity on the remaining 4 qubits. Which is equivalent to doing nothing 121 | Shor1.h(Q_reg[4]) 122 | Shor1.measure(Q_reg[4],C_reg[0]) 123 | # Reinitialize to |0> 124 | Shor1.reset(Q_reg[4]) 125 | 126 | # Step two : apply a**2 mod 15 127 | Shor1.h(Q_reg[4]) 128 | # Controlled unitary. Apply a mod 15 twice. 129 | for k in range(2): 130 | cmod(qp,'Period_Finding','qr',a) 131 | if C_reg[0] == 1 : 132 | Shor1.u1(pi/2.0,Q_reg[4]) 133 | Shor1.h(Q_reg[4]) 134 | Shor1.measure(Q_reg[4],C_reg[1]) 135 | # Reinitialize to |0> 136 | Shor1.reset(Q_reg[4]) 137 | 138 | # Step three : apply 11 mod 15 139 | Shor1.h(Q_reg[4]) 140 | # Controlled unitary. Apply a mod 15 141 | cmod(qp,'Period_Finding','qr',a) 142 | # Feed forward and measure 143 | if C_reg[1] == 1 : 144 | Shor1.u1(pi/2.0,Q_reg[4]) 145 | if C_reg[0] == 1 : 146 | Shor1.u1(pi/4.0,Q_reg[4]) 147 | Shor1.h(Q_reg[4]) 148 | Shor1.measure(Q_reg[4],C_reg[2]) 149 | 150 | # Run the circuit 151 | #qp.set_api(Qconfig.APItoken, Qconfig.config['url']) # set the APIToken and API url 152 | simulate = qp.execute(["Period_Finding"], backend="local_qasm_simulator", shots=1,timeout=500) 153 | simulate.get_counts("Period_Finding") 154 | #print(simulate) 155 | data = simulate.get_counts("Period_Finding") 156 | #print(data) 157 | data = list(data.keys()) 158 | #print(data) 159 | r = int(data[0]) 160 | #print(r) 161 | l = gcd(2**3,r) 162 | #print(l) 163 | r = int((2**3)/l) 164 | #print(r) 165 | return r 166 | 167 | #-------------------------------------------------------------------------------------------------------------- 168 | # The main function to compute factors 169 | # Input : The number to be factored, N 170 | # Output : Factors of the number 171 | #-------------------------------------------------------------------------------------------------------------- 172 | def Factorize_N(N): 173 | factors = [0,0] 174 | #-------------------------------------------------------------------------------------------------------------- 175 | # Step 1 : Determine the number of bits based on N; n = [log2(N)] 176 | #-------------------------------------------------------------------------------------------------------------- 177 | n = math.ceil(math.log(N,2)) 178 | #-------------------------------------------------------------------------------------------------------------- 179 | # Step 2 : Check if N is even. In that case return 2 and the remaining number as factors 180 | #-------------------------------------------------------------------------------------------------------------- 181 | if N % 2 == 0: 182 | factors = [2,N/2] 183 | return factors 184 | #-------------------------------------------------------------------------------------------------------------- 185 | # Step 3 : Check if N is of the form P^(k), where P is some prime factor. In that case return P and k. 186 | #-------------------------------------------------------------------------------------------------------------- 187 | # The step has been eliminated for simulation purposes. 188 | #-------------------------------------------------------------------------------------------------------------- 189 | # Step 4 : Choose a random number between 2...(N-1). 190 | #-------------------------------------------------------------------------------------------------------------- 191 | while True: 192 | a = randint(2,N-1) 193 | global A 194 | A = a 195 | #-------------------------------------------------------------------------------------------------------------- 196 | # Step 5 : Take GCD of a and N. t = GCD(a,N) 197 | #-------------------------------------------------------------------------------------------------------------- 198 | t = gcd(N,a) 199 | if t > 1: 200 | factors = [t,N/t] 201 | return factors 202 | #-------------------------------------------------------------------------------------------------------------- 203 | # Step 6 : t = 1. Hence, no common period. Find Period using Shor's method 204 | #-------------------------------------------------------------------------------------------------------------- 205 | r = period(a,N) 206 | if (r%2 == 0) and (((a**(r/2))+1)%N != 0) and (r != 0) and (r != 8): 207 | break 208 | global Counts 209 | Counts = Counts + 1 210 | factor_1 = gcd((a**(r/2))+1,N) 211 | factor_2 = N/factor_1 212 | factors = [factor_1,factor_2] 213 | return factors 214 | 215 | #-------------------------------------------------------------------------------------------------------------- 216 | # Running the Shor's algorithm version 1 217 | #-------------------------------------------------------------------------------------------------------------- 218 | 219 | #-------------------------------------------------------------------------------------------------------------- 220 | # Step 0 : Take the input N 221 | #-------------------------------------------------------------------------------------------------------------- 222 | factors_list = list() 223 | A_used = list() 224 | Ran_QPF = list() 225 | Total_counts = list() 226 | if __name__ == '__main__': 227 | #global m 228 | for m in range(100): 229 | N = 15 230 | factors_found = Factorize_N(N) 231 | factors_list.append(factors_found) 232 | #ws.write(row,col,A) 233 | #ws.write(row,col+1,Counts) 234 | #ws.write(row,col+2,factors[0]) 235 | #ws.write(row,col+3,factors[1]) 236 | #ws.write(row,col+4,Ran_Quantum_period_finding) 237 | #row = row + 1 238 | #print("The Number being factorized is 15") 239 | #print("Factors are = ",factors) 240 | #print("Number of times the quantum circuit did not give correct period = ",Counts) 241 | #print ("The parameter a used = ", A) 242 | print("Run ", m) 243 | A_used.append(A) 244 | Ran_QPF.append(Ran_Quantum_period_finding) 245 | Total_counts.append(Counts) 246 | Counts = 0 247 | Ran_Quantum_period_finding = 0 248 | 249 | 250 | if m == 99: 251 | wb = xlsxwriter.Workbook('log.xlsx') 252 | ws = wb.add_worksheet('Data') 253 | row = 0 254 | col = 0 255 | ws.write(row,col,'a used for factorizing') 256 | ws.write(row,col+1,'Number of times the quantum circuit did not give correct period') 257 | ws.write(row,col+2,'Factor1') 258 | ws.write(row,col+3,'Factor2') 259 | ws.write(row,col+4,'Ran_Quantum_period_finding?') 260 | row = row + 1 261 | 262 | for k in range(100): 263 | ws.write(row,col,A_used[k]) 264 | ws.write(row,col+1,Total_counts[k]) 265 | ws.write(row,col+2,factors_list[k][0]) 266 | ws.write(row,col+3,factors_list[k][1]) 267 | ws.write(row,col+4,Ran_QPF[k]) 268 | row = row + 1 269 | 270 | wb.close() --------------------------------------------------------------------------------