qqz.discrete_log
1from typing import Optional 2import math 3 4import numpy as np 5import matplotlib.pyplot as plt 6from sympy import gcdex 7from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, Aer, transpile, assemble 8from qiskit.visualization import plot_histogram 9from sympy import Rational, gcdex 10from sympy.ntheory.continued_fraction import continued_fraction, continued_fraction_convergents 11 12from qft import qft 13from elementary import ax_modM 14from order_finding import order_finding 15from classical_utils import decode_bin 16 17def discrete_log(a: int, b: int, p: int, show_hist: Optional[bool] = False) -> int: 18 """Shor's discrete log algorithm: given $a,b,p\in\mathbb{Z}$, it finds $s$ such that $a^s\equiv b\pmod p$. 19 20 Args: 21 a (int): $a$ 22 b (int): $b$ 23 p (int): $p$ 24 """ 25 26 r = order_finding(x=a, N=p, show_hist=False) 27 t = int(np.ceil(np.log2(p))) 28 29 first_register = QuantumRegister(t) 30 second_register = QuantumRegister(t) 31 third_register = QuantumRegister(2 * t) 32 auxiliary_register_mid = QuantumRegister(t) 33 auxiliary_register_end = QuantumRegister(6 * t - 2) 34 classical_register = ClassicalRegister(2 * t) 35 36 qc = QuantumCircuit( 37 first_register, 38 second_register, 39 third_register, 40 auxiliary_register_mid, 41 auxiliary_register_end, 42 classical_register, 43 ) 44 45 qc.h(first_register) 46 qc.h(second_register) 47 48 qc.append(ax_modM(a=b, M=p, N_len=t), list(first_register) + list(auxiliary_register_mid) + list(third_register) + list(auxiliary_register_end)) 49 qc.append(ax_modM(a=a, M=p, N_len=t, x_0_at_first=False), list(second_register) + list(auxiliary_register_mid) + list(third_register) + list(auxiliary_register_end)) 50 51 qc.append(qft(n=t).inverse(), first_register) 52 qc.append(qft(n=t).inverse(), second_register) 53 54 qc.measure(list(first_register) + list(second_register), classical_register) 55 #qc.measure(third_register, classical_register) 56 57 backend = Aer.get_backend('aer_simulator_matrix_product_state')#('aer_simulator') 58 qc = transpile(qc, backend) 59 job = backend.run(qc, shots=10000) 60 hist = job.result().get_counts() 61 62 if show_hist: 63 figsize_x = max(7 * (len(hist) // 8), 7) 64 plot_histogram(hist, figsize=(figsize_x, 5)) 65 plt.savefig(f'img/discrete_log_a{a}_b{b}_p{p}_r{r}.png', bbox_inches='tight') 66 67 for measured_key, _ in sorted(hist.items(), key=lambda x: x[1], reverse=True): 68 tilde_l_per_r = Rational(decode_bin(measured_key[:t]), 2 ** t) # decoded from second register: $\widetilde{l/r}$ 69 if tilde_l_per_r == 0: 70 continue 71 72 l = None 73 for fraction in continued_fraction_convergents(continued_fraction(tilde_l_per_r)): 74 if fraction.denominator == r: 75 l = fraction.numerator # get correct $l$ 76 break 77 78 if l is None: 79 continue 80 81 tilde_beta_per_r = Rational(decode_bin(measured_key[-t:]), 2 ** t) # decoded from first register: $\widetilde{\beta/r}$ 82 if tilde_beta_per_r == 0: 83 continue 84 85 beta = None 86 for fraction in continued_fraction_convergents(continued_fraction(tilde_beta_per_r)): 87 if fraction.denominator == r: 88 beta = fraction.numerator # get correct $\beta$ 89 break 90 91 if beta is None: 92 continue 93 94 s, alpha, _ = gcdex(l, -r) 95 s = int(s * beta) 96 if pow(a, s, p) == b: 97 return s 98 99 raise Exception('s is NOT found!') 100 101 102if __name__ == '__main__': 103 print(discrete_log(a=2, b=4, p=7, show_hist=True))
def
discrete_log(a: int, b: int, p: int, show_hist: Union[bool, NoneType] = False) -> int:
18def discrete_log(a: int, b: int, p: int, show_hist: Optional[bool] = False) -> int: 19 """Shor's discrete log algorithm: given $a,b,p\in\mathbb{Z}$, it finds $s$ such that $a^s\equiv b\pmod p$. 20 21 Args: 22 a (int): $a$ 23 b (int): $b$ 24 p (int): $p$ 25 """ 26 27 r = order_finding(x=a, N=p, show_hist=False) 28 t = int(np.ceil(np.log2(p))) 29 30 first_register = QuantumRegister(t) 31 second_register = QuantumRegister(t) 32 third_register = QuantumRegister(2 * t) 33 auxiliary_register_mid = QuantumRegister(t) 34 auxiliary_register_end = QuantumRegister(6 * t - 2) 35 classical_register = ClassicalRegister(2 * t) 36 37 qc = QuantumCircuit( 38 first_register, 39 second_register, 40 third_register, 41 auxiliary_register_mid, 42 auxiliary_register_end, 43 classical_register, 44 ) 45 46 qc.h(first_register) 47 qc.h(second_register) 48 49 qc.append(ax_modM(a=b, M=p, N_len=t), list(first_register) + list(auxiliary_register_mid) + list(third_register) + list(auxiliary_register_end)) 50 qc.append(ax_modM(a=a, M=p, N_len=t, x_0_at_first=False), list(second_register) + list(auxiliary_register_mid) + list(third_register) + list(auxiliary_register_end)) 51 52 qc.append(qft(n=t).inverse(), first_register) 53 qc.append(qft(n=t).inverse(), second_register) 54 55 qc.measure(list(first_register) + list(second_register), classical_register) 56 #qc.measure(third_register, classical_register) 57 58 backend = Aer.get_backend('aer_simulator_matrix_product_state')#('aer_simulator') 59 qc = transpile(qc, backend) 60 job = backend.run(qc, shots=10000) 61 hist = job.result().get_counts() 62 63 if show_hist: 64 figsize_x = max(7 * (len(hist) // 8), 7) 65 plot_histogram(hist, figsize=(figsize_x, 5)) 66 plt.savefig(f'img/discrete_log_a{a}_b{b}_p{p}_r{r}.png', bbox_inches='tight') 67 68 for measured_key, _ in sorted(hist.items(), key=lambda x: x[1], reverse=True): 69 tilde_l_per_r = Rational(decode_bin(measured_key[:t]), 2 ** t) # decoded from second register: $\widetilde{l/r}$ 70 if tilde_l_per_r == 0: 71 continue 72 73 l = None 74 for fraction in continued_fraction_convergents(continued_fraction(tilde_l_per_r)): 75 if fraction.denominator == r: 76 l = fraction.numerator # get correct $l$ 77 break 78 79 if l is None: 80 continue 81 82 tilde_beta_per_r = Rational(decode_bin(measured_key[-t:]), 2 ** t) # decoded from first register: $\widetilde{\beta/r}$ 83 if tilde_beta_per_r == 0: 84 continue 85 86 beta = None 87 for fraction in continued_fraction_convergents(continued_fraction(tilde_beta_per_r)): 88 if fraction.denominator == r: 89 beta = fraction.numerator # get correct $\beta$ 90 break 91 92 if beta is None: 93 continue 94 95 s, alpha, _ = gcdex(l, -r) 96 s = int(s * beta) 97 if pow(a, s, p) == b: 98 return s 99 100 raise Exception('s is NOT found!')
Shor's discrete log algorithm: given $a,b,p\in\mathbb{Z}$, it finds $s$ such that $a^s\equiv b\pmod p$.
Arguments:
- a (int): $a$
- b (int): $b$
- p (int): $p$