def period_find(a, N): """Finds the period of a in modulo N arithmetic This is quantum part of Shor's algorithm.It takes two registers, puts first in superposition of states with Hadamards so: |k>|0> with k being all possible choices. It then does a controlled mod and a QFT to determine the order of a. """ epsilon = .5 #picks out t's such that maintains accuracy within epsilon t = int(2 * math.ceil(log(N, 2))) # make the first half of register be 0's |000...000> start = [0 for x in range(t)] #Put second half into superposition of states so we have |1>x|0> + |2>x|0> + ... |k>x>|0> + ... + |2**n-1>x|0> factor = 1 / sqrt(2**t) qubits = 0 for i in range(2**t): qbitArray = arr(i, t) + start qubits = qubits + Qubit(*qbitArray) circuit = (factor * qubits).expand() #Controlled second half of register so that we have: # |1>x|a**1 %N> + |2>x|a**2 %N> + ... + |k>x|a**k %N >+ ... + |2**n-1=k>x|a**k % n> circuit = CMod(t, a, N) * circuit #will measure first half of register giving one of the a**k%N's circuit = apply_operators(circuit) print "controlled Mod'd" for i in range(t): circuit = measure_partial_oneshot(circuit, i) # circuit = measure(i)*circuit # circuit = apply_operators(circuit) print "measured 1" #Now apply Inverse Quantum Fourier Transform on the second half of the register circuit = apply_operators(QFT(t, t * 2).decompose() * circuit, floatingPoint=True) print "QFT'd" for i in range(t): circuit = measure_partial_oneshot(circuit, i + t) # circuit = measure(i+t)*circuit # circuit = apply_operators(circuit) print circuit if isinstance(circuit, Qubit): register = circuit elif isinstance(circuit, Mul): register = circuit.args[-1] else: register = circuit.args[-1].args[-1] print register n = 1 answer = 0 for i in range(len(register) / 2): answer += n * register[i + t] n = n << 1 if answer == 0: raise OrderFindingException( "Order finder returned 0. Happens with chance %f" % epsilon) #turn answer into r using continued fractions g = getr(answer, 2**t, N) print g return g
def period_find(a, N): """Finds the period of a in modulo N arithmetic This is quantum part of Shor's algorithm.It takes two registers, puts first in superposition of states with Hadamards so: ``|k>|0>`` with k being all possible choices. It then does a controlled mod and a QFT to determine the order of a. """ epsilon = .5 #picks out t's such that maintains accuracy within epsilon t = int(2*math.ceil(log(N, 2))) # make the first half of register be 0's |000...000> start = [0 for x in range(t)] #Put second half into superposition of states so we have |1>x|0> + |2>x|0> + ... |k>x>|0> + ... + |2**n-1>x|0> factor = 1/sqrt(2**t) qubits = 0 for i in range(2**t): qbitArray = arr(i, t) + start qubits = qubits + Qubit(*qbitArray) circuit = (factor*qubits).expand() #Controlled second half of register so that we have: # |1>x|a**1 %N> + |2>x|a**2 %N> + ... + |k>x|a**k %N >+ ... + |2**n-1=k>x|a**k % n> circuit = CMod(t, a, N)*circuit #will measure first half of register giving one of the a**k%N's circuit = qapply(circuit) print "controlled Mod'd" for i in range(t): circuit = measure_partial_oneshot(circuit, i) # circuit = measure(i)*circuit # circuit = qapply(circuit) print "measured 1" #Now apply Inverse Quantum Fourier Transform on the second half of the register circuit = qapply(QFT(t, t*2).decompose()*circuit, floatingPoint=True) print "QFT'd" for i in range(t): circuit = measure_partial_oneshot(circuit, i + t) # circuit = measure(i+t)*circuit # circuit = qapply(circuit) print circuit if isinstance(circuit, Qubit): register = circuit elif isinstance(circuit, Mul): register = circuit.args[-1] else: register = circuit.args[-1].args[-1] print register n = 1 answer = 0 for i in range(len(register)/2): answer += n*register[i + t] n = n << 1 if answer == 0: raise OrderFindingException( "Order finder returned 0. Happens with chance %f" % epsilon) #turn answer into r using continued fractions g = getr(answer, 2**t, N) print g return g
def find_r(x, N): """ Encontra o período de x em aritimética módulo N. Essa é a parte realmente quântica da solução. Põe a primeira parte do registrador em um estado de superposição |j> |0>, com j = 0 to 2 ** n - 1, usando a porta Hadamard. Depois aplica a porta Vx e IQFT para determinar a ordem de x. """ # Calcula o número de qubits necessários n = int(math.ceil(log(N, 2))) t = int(math.ceil(2 * log(N, 2))) print("n: ", n) print("t: ", t) # Cria o registrador register = Qubit(IntQubit(0, t + n)) print("register: ", register) # Põe a segunda metade do registrado em superposição |1>|0> + |2>|0> + ... |j>|0> + ... + |2 ** n - 1>|0> print("Aplicando Hadamard...") circuit = 1 for i in reversed(list(range(n, n + t))): circuit = HadamardGate(i) * circuit circuit = qapply(circuit * register) print("Circuit Hadamard:\n", circuit.simplify()) # Calcula os valores para a primeira metade do registrador |1>|x ** 1 % N> + |2>|x ** 2 % N> + ... + |k>|x ** k % N >+ ... + |2 ** n - 1 = j>|x ** j % N> print("Aplicando Vx...") circuit = qapply(Vx(n, t, x, N) * circuit) print("Circuit Vx:\n", circuit.simplify()) # Faz a medição da primeira metade do registrador obtendo um dos [x ** j % N's] print("Medindo 0->n ...") circuit = measure_partial_oneshot(circuit, range(n)) print("Circuit 0->n:\n", circuit.simplify()) # Aplica a Transformada de Fourier Quântica Inversa na segunda metade do registrador print("Aplicando a transformada inversa...") circuit = qapply(IQFT(n, n + t).decompose() * circuit) print("Circuit IQFT:\n", circuit.simplify()) # Faz a medição da segunda metade do registrador um dos valores da transformada while ( True ): # O correto seria repetir a rotina inteira, mas é suficiente repetir a medição. # Num computador quântico real o estado colapsaria e não seria possível medi-lo novamente. print("Medindo n->n+t ...") #measurement = measure_partial_oneshot(circuit, range(n, n + t)) measurement = measure_all_oneshot(circuit) print(measurement.simplify()) if isinstance(measurement, Qubit): register = measurement elif isinstance(measurement, Mul): register = measurement.args[-1] else: register = measurement.args[-1].args[-1] print("Medicao: ", register) # Converte o qubit de binário para decimal k = 1 answer = 0 for i in range(t): answer += k * register[n + i] k = k << 1 print("Medicao: ", answer) if answer != 0: break print("2^t: ", 2**t) # Lista os termos da fração continuada fraction = continued_fraction(answer, 2**t) # A soma dos termos da fração continuada é a razão entre dois # números primos entre si (p e q onde MDC(p, q) == 1) que # multiplicados resultam N (somar apenas os termos menores ou iguais a N) r = 0 for x in fraction: if (x > N): break else: print("fraction: ", x) r = r + x return r