├── img ├── Bell.png ├── Shor.png ├── gate.png ├── Thumbs.db ├── period.png ├── Bellblock.png ├── hadamar.png ├── modular.png ├── Complexity.jpg ├── complexity.png ├── controlled.png ├── modulation.png ├── qiskit-logo.gif └── qiskit-heading.gif ├── src ├── Shor_simplified │ ├── __pycache__ │ │ └── Quantum.cpython-36.pyc │ ├── Shor.py │ └── Quantum.py └── Bell_state.py └── README.md /img/Bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/Bell.png -------------------------------------------------------------------------------- /img/Shor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/Shor.png -------------------------------------------------------------------------------- /img/gate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/gate.png -------------------------------------------------------------------------------- /img/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/Thumbs.db -------------------------------------------------------------------------------- /img/period.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/period.png -------------------------------------------------------------------------------- /img/Bellblock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/Bellblock.png -------------------------------------------------------------------------------- /img/hadamar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/hadamar.png -------------------------------------------------------------------------------- /img/modular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/modular.png -------------------------------------------------------------------------------- /img/Complexity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/Complexity.jpg -------------------------------------------------------------------------------- /img/complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/complexity.png -------------------------------------------------------------------------------- /img/controlled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/controlled.png -------------------------------------------------------------------------------- /img/modulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/modulation.png -------------------------------------------------------------------------------- /img/qiskit-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/qiskit-logo.gif -------------------------------------------------------------------------------- /img/qiskit-heading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/img/qiskit-heading.gif -------------------------------------------------------------------------------- /src/Shor_simplified/__pycache__/Quantum.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aurelien-Pelissier/IBMQ-Quantum-Programming/HEAD/src/Shor_simplified/__pycache__/Quantum.cpython-36.pyc -------------------------------------------------------------------------------- /src/Bell_state.py: -------------------------------------------------------------------------------- 1 | """ 2 | this code create a Bell's state (|00> + |11>) 3 | and measure it 1000 times 4 | """ 5 | 6 | from qiskit import QuantumProgram 7 | qp = QuantumProgram() 8 | qr = qp.create_quantum_register('qr',2) #Initialize 2 qubits to perform operations 9 | cr = qp.create_classical_register('qc',2) #Initialize 2 classical bits to store the measurements 10 | qc = qp.create_circuit('Bell',[qr],[cr]) 11 | qc.h(qr[0]) #Apply Hadamar gate 12 | qc.cx(qr[0], qr[1]) #Apply CNOT gate 13 | qc.measure(qr[0], cr[0]) #Measure qubit 0 and store the result in bit 0 14 | qc.measure(qr[1], cr[1]) #Measure qubit 1 and store the result in bit 1 15 | 16 | result = qp.execute('Bell', shots=1000) #Compile and run the Quantum Program 1000 times 17 | print(result.get_counts('Bell')) 18 | 19 | 20 | #https://www.softynews.com/optional-tutorial-qiskit-quantum-computing-platform/ -------------------------------------------------------------------------------- /src/Shor_simplified/Shor.py: -------------------------------------------------------------------------------- 1 | from math import log 2 | from Quantum import quantum_period 3 | 4 | 5 | """ 6 | This code is a simplified implementation of the Shor's Algorithm for N=15 7 | The code is written to run on a 5Qbit IBMQ quantum processor 8 | """ 9 | 10 | 11 | def main(): 12 | 13 | 14 | print ("\n") 15 | print ("===========================================") 16 | print (" SHOR'S ALGPRITHM") 17 | print ("===========================================") 18 | print ("\n") 19 | 20 | 21 | #N is the prime factor to be factorized, 22 | # (Currently, the IBMQ processor has 5qbits, 23 | # So the number to be factorized should be less 2^5 = 32) 24 | 25 | N = 15 26 | 27 | if Check(N): 28 | p1, p2 = Shor(N) 29 | 30 | 31 | 32 | 33 | def Check(N): 34 | 35 | if N % 2 == 0: 36 | print ("2 is a trivial factor") 37 | return False 38 | 39 | for k in range(2,int(log(N,2))): #log2(N) 40 | if pow(N,(1/k)).is_integer(): 41 | print ("N =", pow(N,(1/k)), '^', k) 42 | return False 43 | 44 | return True 45 | 46 | 47 | def gcd(a, b): #Compute the GCD with Euclide algorithm 48 | while b: 49 | a, b = b, a%b 50 | return a 51 | 52 | 53 | 54 | def Shor(N): 55 | 56 | while True: 57 | 58 | #1) pick a random number a= 2**n_bit: 26 | print (" Error: the number N =", N, "is too big, should be smaller than 2^" + str(n_bit),"=", 2**n_bit) 27 | print("\n\n") 28 | sys.exit(0) 29 | 30 | 31 | 32 | 33 | #---------------------------------------------------------------------------# 34 | #------------------------------ Quantum part -------------------------------# 35 | #---------------------------------------------------------------------------# 36 | 37 | print(" Searching the period for N =", N, "and a =", a) 38 | 39 | qp = QuantumProgram() 40 | qr = qp.create_quantum_register('qr',n_bit) #working register 41 | cr = qp.create_classical_register('cr',n_bit) #register to store our measurement 42 | qc = qp.create_circuit('Period',[qr],[cr]) 43 | 44 | 45 | 46 | 47 | s0 = randint(1, N-1) 48 | sbin = to_binary(s0,n_bit) # Decompose s0 in binary unit for our quantum algorithm 49 | print("\n Statrting at \n s =", s0, "=", sbin) 50 | 51 | #initialize the input with s 52 | for i in range(0,n_bit): 53 | if sbin[n_bit-i-1]: 54 | qc.x(qr[i]) 55 | 56 | s = s0 57 | r=-1 58 | 59 | # Apply the modular multiplication transformation until we come back to the same initial number s 60 | while np.logical_or(s != s0, r <= 0): 61 | 62 | r+=1 63 | qc.measure(qr, cr) 64 | modular_multiplication(qc,qr,cr,a,N) 65 | result = qp.execute('Period', shots=10) 66 | P = result.get_counts('Period') 67 | 68 | results = [[],[]] 69 | for k,v in P.items(): #the result should be deterministic but there might be some quantum calculation error so we take the most reccurent output 70 | results[0].append(k) 71 | results[1].append(int(v)) 72 | 73 | index = np.argmax(np.array(results[1])) 74 | s_str = str(results[0][index]) 75 | 76 | s = int(s_str, 2) 77 | print(" ",s_str[::-1]) 78 | 79 | #sbin = 80 | 81 | 82 | 83 | 84 | print("\n Found period r =", r) 85 | return r 86 | 87 | 88 | 89 | 90 | def modular_multiplication(qc,qr,cr,a,N): 91 | """ 92 | apply the unitary operator that implements the modular multiplication function x -> a*x(modN) 93 | Only work for the particular case x -> 7*x(mod15) 94 | """ 95 | 96 | for i in range(0,3): 97 | qc.x(qr[i]) 98 | 99 | qc.cx(qr[2],qr[1]); 100 | qc.cx(qr[1],qr[2]); 101 | qc.cx(qr[2],qr[1]); 102 | 103 | qc.cx(qr[1],qr[0]); 104 | qc.cx(qr[0],qr[1]); 105 | qc.cx(qr[1],qr[0]); 106 | 107 | qc.cx(qr[3],qr[0]); 108 | qc.cx(qr[0],qr[1]); 109 | qc.cx(qr[1],qr[0]); 110 | 111 | 112 | 113 | 114 | 115 | 116 | if __name__ == '__main__': 117 | 118 | a = 7 119 | N = 15 120 | r = quantum_period(a,N) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Disclaimer: 2 | 3 | ### The Qiskit code in this repository is now depreciated. For an up-to-date implementation of the Shor's algorithm, check out [This repository](https://github.com/Aurelien-Pelissier/Medium/blob/main/Quantum%20Programming) 4 | 5 | 6 | 7 |   8 | 9 | 10 | 11 | 12 | 13 | # Quantum Computing 14 | 15 | 16 | During the past decade, considerable progress has been achieved regarding the development of quantum computers, and a breakthrough in this field will have massive application particularily in research, cryptography and logistic. Google and IBM recently claimed the creation of a 72 and 50 qubit quantum chips respectively, making the possibility for a potential imminent quantum supremacy even more likely. [1] 17 | 18 | 19 |   20 | 21 | In May 2016, IBM launched Quantum Experience (QX), which enables anyone to easily connect to its 5qubit quantum processors via the IBM Cloud. (https://www.research.ibm.com/ibm-q/). Along with it's platform, IBM also developped `QISKit`, a Python library for the Quantum Experience API, where users can more easily apply quantum gates to run complex quantum algorithms and experiments. 22 | 23 | 24 | This repository is an introdution to quantum computing and contains the source code to run simples quantum algorithms. They are implemented with the python library `QISKit`, that can be easily installed with the command `$ pip install qiskit` (`Python 3.5` is required). More information is available at https://qiskit.org/. 25 | 26 | 27 |   28 | 29 | ## Quantum Gates 30 | 31 | 32 | In analogy with the classical gates NOT, AND, OR, ... that are the building blocks for classical circuits, there are quantum gates that perform basic operations on qubits. The most common quantum gates are summarized here --> https://en.wikipedia.org/wiki/Quantum_logic_gate. 33 | 34 | For example, the Hadamard gate, H, performs the following operartion: 35 | 36 | 37 | 38 | 39 |   40 | 41 |   42 | 43 | 44 | ### Creating and measuring a Bell state 45 | The following code, available in the `src` folder, create a Bell state and measure it 1000 times. 46 | 47 | 48 | 49 | ```python 50 | from qiskit import QuantumProgram 51 | 52 | qp = QuantumProgram() 53 | qr = qp.create_quantum_register('qr',2) #Initialize 2 qubits to perform operations 54 | cr = qp.create_classical_register('qc',2) #Initialize 2 classical bits to store the measurements 55 | qc = qp.create_circuit('Bell',[qr],[cr]) 56 | qc.h(qr[0]) #Apply Hadamar gate 57 | qc.cx(qr[0], qr[1]) #Apply CNOT gate 58 | qc.measure(qr[0], cr[0]) #Measure qubit 0 and store the result in bit 0 59 | qc.measure(qr[1], cr[1]) #Measure qubit 1 and store the result in bit 1 60 | 61 | result = qp.execute('Bell', shots=1000) #Compile and run the Quantum Program 1000 times 62 | print(result.get_counts('Bell')) 63 | ``` 64 | A possible result that we get is 65 | ```python 66 | {'11': 494, '00': 506} 67 | ``` 68 | 69 | 70 | 71 | 72 |   73 | 74 | 75 | ## Shor's Algorithm 76 | 77 | The [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm), proposed by Peter Shor in 1995 [2], is today one of the most famous quantum algorithm; it is considerably significant because, while the security of our online transactions rests on the assumption that factoring integers with a thousand or more digits is practically impossible, the algorithm enables to find 2 factors of a number in polynomial time with its number of digits. Shor's algorithm was first experimentally demonstrated in 2001 by a group at IBM, which factored 15 into 3 and 5, using a quantum computer of 7 qubits [3]. 78 | 79 | 80 |   81 | 82 | ### Complexity of factoring 83 | 84 | 85 | Let N be the number to be factorized, and d~log2(N) its number of digit. The most efficient classical factoring algorithm currently known is the [General number field sieve](https://en.wikipedia.org/wiki/General_number_field_sieve), which has an exponential asymptotic runtime to the number of digits : O(exp(d^1/3)). On the other hand, Shor’s factoring algorithm has an asymptotic runtime polynomial in d : O(d^3). 86 | 87 | This remarquable difference between polynomial and exponential runtime scaling currently places the Factoring problem into the [BQP\P](https://en.wikipedia.org/wiki/BQP) decision class (cf. figure in introduction). 88 | 89 | 90 |   91 | 92 | ### The Algorithm 93 | 94 | We want to find two factors *p1* and *p2* that divide *N*. Before diving into the algorithm, we have to make sure that: 95 | * N is odd (if it's even, then 2 is a trivial factor) 96 | * N is not the power of a prime 97 | 98 | ```python 99 | from math import log 100 | 101 | def Check(N): 102 | 103 | if N % 2 == 0: 104 | print ("2 is a trivial factor") 105 | return False 106 | 107 | for k in range(2,int(log(N,2))): #log2(N) 108 | if (pow(N,(1/k)).is_integer(): 109 | print ("N =", pow(N,(1/k)), "^", k) 110 | return False 111 | 112 | return True 113 | ``` 114 | 115 | 116 |   117 | 118 | #### Classical part 119 | 120 | With some Arithmetic, Group theory, Euler's Theorem and Bézout's identity, it is possible to reduce the factorization problem into a period finding problem of the modular exponential function (see [this page](https://en.wikipedia.org/wiki/Shor%27s_algorithm) for more details). The classical part of the algorithm is implemented as follow: 121 | 122 | ```python 123 | from random import randint 124 | 125 | def Shor(N): 126 | 127 | while True: 128 | 129 | #1) pick a random number a, which is the smallest positive integer for which . Given the numbers *N* and *a*, the period finding subroutine of the modular exponentiation function proposed by Shor proceed as follow: 156 | 157 | * Initialize *n0* qubit and store *N* in the input register (*n0* ~ log2(*N*) ) 158 | * Initialize *n* qubit for the output register (where 2^*n* ~ *N*^2 => *n* ~ 2*n0*) 159 | * Apply Hadamard Gate to all of the qubit in the output register 160 | * Apply the controled modular exponentiation gates *Ua*, *Ua*^2, *Ua*^4, *Ua*^8, .., *Ua*^(2^(2*n*-1)) to the input register 161 | * Apply the inverse QFT (Quantum Fourier Transform) to the output register 162 | * Measure the output *y* 163 | * Calculate the irreducible form of *y*/*N* and extract the denominator *r* 164 | * Check if *r* is a period, if not, check multiples of *r* 165 | * If period not found, try again from the beginning 166 | 167 | 168 | 169 | The quantum gate *Ua* refers to the unitary operator that perform the modular exponentiation function *x → a^x (modN)*. 170 | The implementation of controlled *Ua* as well as the inverse QFT gate are relatively complex [4,5], and the "right" gate set to use is currently still an open question (plus it also depends the architecture used for the quantum computer). 171 | Details about how and why this algorithm works can be found in the [IBM User Guide](https://qiskit.org/textbook/ch-algorithms/shor.html). 172 | 173 | 174 |   175 | 176 | #### Simplified implementation 177 | 178 | Because the implementation of controlled modular exponentiation and inverse QFT are too difficult in the general case, only a particular case is implemented as a proof of concept, and the period finding subroutne is coded for *N=15* and *a* = 7. The non controlled gate *U7* can be implemented as follow [4]: 179 | 180 | 181 | 182 | The simplified subroutine is then carried on by successively applying modular exponentiation until the period is found: 183 | 184 | * Pick a ransom number *s* between 1 and N-1 185 | * Decompose *s* into binary units and store *s* in the input register 186 | * Apply the modular exponentiation gate successively until the output match with *s* 187 | * The period *r* is the number of time *Ua* has been applied 188 | 189 | ``` python 190 | Statrting at 191 | s = 3 = [True True False False False] 192 | "11000" 193 | "01000" 194 | "10000" 195 | "01100" 196 | "11000" 197 | 198 | Found period r = 4 199 | ``` 200 | 201 | Although this implementation does not use the properties of quantum computers to find *r* in polynomial time, it is a proof of concept of the modular exponentiation quantum implementation. The code can be found in `src/Shor_simplified`. 202 | 203 | 204 | 205 | 206 |   207 | 208 | ## References 209 | 210 | [1]: Kelly, J. (2018). Engineering superconducting qubit arrays for Quantum Supremacy. Bulletin of the American Physical Society. [http://meetings.aps.org/Meeting/MAR18/Session/A33.1] 211 | 212 | 213 | [2]: Shor, P. W. (1999). Polynomial-time algorithms for prime factorization and discrete logarithms on a quantum computer. SIAM review, 41(2), 303-332. [https://arxiv.org/abs/quant-ph/9508027] 214 | 215 | 216 | [3]: Vandersypen, L. M., Steffen, M., Breyta, G., Yannoni, C. S., Sherwood, M. H., & Chuang, I. L. (2001). Experimental realization of Shor's quantum factoring algorithm using nuclear magnetic resonance. Nature, 414(6866), 883. [https://www.nature.com/articles/414883a] 217 | 218 | 219 | [4]: Markov, I. L., & Saeedi, M. (2012). Constant-optimized quantum circuits for modular multiplication and exponentiation. arXiv preprint arXiv:1202.6614. [https://arxiv.org/abs/1202.6614] 220 | 221 | 222 | [5]: Draper, T. G. (2000). Addition on a quantum computer. arXiv preprint quant-ph/0008033. [https://arxiv.org/abs/quant-ph/0008033} 223 | --------------------------------------------------------------------------------