def run_inv(a=11, b=1, param="simulation"): # build compilation engine list resource_counter = ResourceCounter() rule_set = DecompositionRuleSet(modules=[projectq.libs.math, projectq.setups.decompositions]) compilerengines = [AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), resource_counter] # create a main compiler engine a1 = a b1 = b if a == 0: a1 = 1 if b == 0: b1 = 1 n = max(int(math.log(a1, 2)), int(math.log(b1, 2))) + 1 if param == "latex": drawing_engine = CircuitDrawer() eng2 = MainEngine(drawing_engine) xa = initialisation_n(eng2, a, n + 1) xb = initialisation_n(eng2, b, n + 1) # b --> phi(b) QFT | xb phi_adder(eng2, xa, xb) with Dagger(eng2): QFT | xb All(Measure) | xa All(Measure) | xb eng2.flush() print(drawing_engine.get_latex()) else: eng = MainEngine(Simulator(), compilerengines) xa = initialisation_n(eng, a, n + 1) xb = initialisation_n(eng, b, n + 1) # b --> phi(b) QFT | xb with Dagger(eng): phi_adder(eng, xa, xb) with Dagger(eng): QFT | xb All(Measure) | xa All(Measure) | xb eng.flush() n = n+1 measurements_a = [0] * n measurements_b = [0] * n for k in range(n): measurements_a[k] = int(xa[k]) measurements_b[k] = int(xb[k]) return [measurements_a, meas2int(measurements_b), measurements_b]
def run_shor(eng, N, a, verbose=False): """ Runs the quantum subroutine of Shor's algorithm for factoring. with 2n control qubits Args: eng (MainEngine): Main compiler engine to use. N (int): Number to factor. a (int): Relative prime to use as a base for a^x mod N. verbose (bool): If True, display intermediate measurement results. Returns: r (float): Potential period of a. """ n = int(math.ceil(math.log(N, 2))) x = eng.allocate_qureg(n) xN = initialisation_n(eng, N, n) xb = initialisation_n(eng, 0, n) aux = initialisation_n(eng, 0, 1) X | x[0] # set x to 1 measurements = [0] * (2 * n) # will hold the 2n measurement results ctrl_qubit = eng.allocate_qureg(2 * n) for k in range(2 * n): current_a = pow(a, 1 << k, N) # one iteration of 1-qubit QPE H | ctrl_qubit[k] gateUa(eng, current_a, mod_inv(current_a, N), x, xb, xN, aux, ctrl_qubit[k], N) with Dagger(eng): QFT | ctrl_qubit # and measure All(Measure) | ctrl_qubit eng.flush() for k in range(2 * n): measurements[k] = int(ctrl_qubit[k]) All(Measure) | x # turn the measured values into a number in [0,1) y = sum([(measurements[i] * 1. / (1 << (i + 1))) for i in range(2 * n)]) # continued fraction expansion to get denominator (the period?) r = Fraction(y).limit_denominator(N - 1).denominator # return the (potential) period return r
def inv_cMultModN_non_Dagger(eng, a, xb, xx, xN, aux, xc, N): """ |b> --> |b+(ax) mod N> if xc=1; else |b> -> |b> :param eng: :param a: :param xc: control bit :param aux: auxiliary :param xx: multiplier :param xb: modified qubit :param xN: Mod :return: """ # b-->phi(b) QFT | xb n = len(xx) - 1 for i in range(n - 1, -1, -1): xa = initialisation_n(eng, ((2**i) * a) % N, n + 1) # both input of modularAdder must be <N # TODO define xa in a iterative way just by adding a new qubit 0 as LSB with Dagger(eng): modularAdder(eng, xa, xb, xN, xx[i], xc, aux) with Dagger(eng): QFT | xb
def run_shor(eng, N, a, verbose=True): """ Runs the quantum subroutine of Shor's algorithm for factoring. The 1 controling qubits version [2, 3, 4, 5, 6, 7, 8] [1002,2926,6822,13802, 25257, 42548, 67868] Args: eng (MainEngine): Main compiler engine to use. N (int): Number to factor. a (int): Relative prime to use as a base for a^x mod N. verbose (bool): If True, display intermediate measurement results. Returns: r (float): Potential period of a. """ n = int(math.ceil(math.log(N, 2))) x = eng.allocate_qureg(n) xN = initialisation_n(eng, N, n) xb = initialisation_n(eng, 0, n) aux = initialisation_n(eng, 0, 1) X | x[0] measurements = [0] * (2 * n) # will hold the 2n measurement results ctrl_qubit = eng.allocate_qubit() # each iteration -> 454*log2(N) + c -> 2*n(454*log2(N) +c ) -> 908 * log2(N)^2 -> O(n^2) # c = 3 ou 4 # last interation measurment -> 3*n # donc 908*(n**2) + 3*n for k in range(2 * n): current_a = pow(a, 1 << (2 * n - 1 - k), N) # one iteration of 1-qubit QPE H | ctrl_qubit """ with Control(eng, ctrl_qubit): MultiplyByConstantModN(current_a, N) | x """ gateUa(eng, current_a, mod_inv(current_a, N), x, xb, xN, aux, ctrl_qubit, N) # nb of gate linear in log2(N) approx ~ 454*log2(N) # perform inverse QFT --> Rotations conditioned on previous outcomes """ for i in range(k): if measurements[i]: R(-math.pi/(1 << (k - i))) | ctrl_qubit """ H | ctrl_qubit # and measure Measure | ctrl_qubit eng.flush() measurements[k] = int(ctrl_qubit) if measurements[k]: X | ctrl_qubit if verbose: print("\033[95m{}\033[0m".format(measurements[k]), end="") sys.stdout.flush() Measure | aux All(Measure) | xN All(Measure) | xb All(Measure) | x # turn the measured values into a number in [0,1) y = sum([(measurements[2 * n - 1 - i] * 1. / (1 << (i + 1))) for i in range(2 * n)]) # continued fraction expansion to get denominator (the period?) r = Fraction(y).limit_denominator(N - 1).denominator # return the (potential) period return r
def run(a=4, b=6, N=7, x=2, param="count"): """ Last update 19/02 : nb of gate linear in log(N) Be careful this algo is a bit long to execute |b> --> |b+(ax) mod N> works for :param a: :param b: :param N: :param x: :param param: :return: """ # build compilation engine list resource_counter = ResourceCounter() rule_set = DecompositionRuleSet( modules=[projectq.libs.math, projectq.setups.decompositions]) compilerengines = [ AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), resource_counter ] # create a main compiler engine n = int(math.log(N, 2)) + 1 if param == "latex": drawing_engine = CircuitDrawer() eng2 = MainEngine(drawing_engine) xN = initialisation_n(eng2, N, n + 1) xx = initialisation_n(eng2, x, n + 1) xb = initialisation_n(eng2, b, n + 1) [xc, aux] = initialisation(eng2, [1, 0]) cMultModN_non_Dagger(eng2, a, xb, xx, xN, aux, xc) eng2.flush() Measure | aux Measure | xc All(Measure) | xx All(Measure) | xb All(Measure) | xN eng2.flush() print(drawing_engine.get_latex()) else: if param == "count": eng = MainEngine(resource_counter) else: eng = MainEngine(Simulator(), compilerengines) xN = initialisation_n(eng, N, n + 1) xx = initialisation_n(eng, x, n + 1) xb = initialisation_n(eng, b, n + 1) [aux, xc] = initialisation(eng, [0, 1]) cMultModN_non_Dagger(eng, a, xb, xx, xN, aux, xc, N) Measure | aux Measure | xc All(Measure) | xx All(Measure) | xb All(Measure) | xN eng.flush() if param == "count": return resource_counter measurements_b = [0] * n measurements_x = [0] * n measurements_N = [0] * n for k in range(n): measurements_b[k] = int(xb[k]) measurements_N[k] = int(xN[k]) measurements_x[k] = int(xx[k]) mes_aux = int(aux[0]) mes_c = int(aux[0]) return [ measurements_b, meas2int(measurements_b), (b + a * x) % N, measurements_N, measurements_x, mes_aux, mes_c, meas2int(measurements_b), meas2int(measurements_N), meas2int(measurements_x) ]
def arcsinQ(eng, x, N): """ with 4 qubits takes ~1800s to run with a C engine :param eng: :param x: int that represent a reel in [0,1] by taking its binary decomposition :param N: int (2^n) :return: arcsin(x [N]) """ n = int(log(N, 2)) + 1 start = time() output = initialisation_n(eng, 1, n + 1) xN = initialisation_n(eng, N, n + 1) xb = initialisation_n(eng, 1, n + 1) x_3 = initialisation_n(eng, 3, n + 1) aux = initialisation_n(eng, 0, 1) t1 = time() print("initialisation : ", t1 - start) expoModN(eng, x, output, xb, xN, aux, x_3, N) t2 = time() print("expoModN : ", t2 - t1) All(Measure) | x_3 inv_6 = 4 # 1/6 ~ 1/2^3 + 1/2^5 soit [0,0,1,0,1] en réduisant à 4 qubits [0,0,1,0]=4 c1 = initialisation_n(eng, 1, 1) cMultModN_non_Dagger(eng, inv_6, xb, output, xN, aux, c1, N) t3 = time() print("inv : ", t3 - t2) xX = initialisation_n(eng, x, n + 1) QFT | xX c2 = initialisation_n(eng, 1, 1) modularAdder(eng, output, xX, xN, c1, c2, aux) t4 = time() print("Modular Adder : ", t4 - t3) with Dagger(eng): QFT | xX t5 = time() print("QFT : ", t5 - t4) Measure | aux Measure | c1 Measure | c2 All(Measure) | output All(Measure) | xX All(Measure) | xb All(Measure) | xN eng.flush() t6 = time() print("eng.flush : ", t6 - t5) print("Temps total : ", t6 - start) measurements_x = [0] * n measurements_N = [0] * n for k in range(n): measurements_N[k] = int(xN[k]) measurements_x[k] = int(xX[k]) return [measurements_x, meas2int(measurements_x), measurements_N]
def run(a=4, N=7, x=2, param="count"): """ |b> --> |b+(ax) mod N> nb of gate ~454*log2(N) :param a: a<N and must be invertible mod[N] :param N: :param x: :param param: :return: """ # build compilation engine list resource_counter = ResourceCounter() rule_set = DecompositionRuleSet( modules=[projectq.libs.math, projectq.setups.decompositions]) compilerengines = [ AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), resource_counter ] # create a main compiler engine a = a % N inv_a = mod_inv(a, N) b = 0 n = int(math.log(N, 2)) + 1 if param == "latex": drawing_engine = CircuitDrawer() eng2 = MainEngine(drawing_engine) xN = initialisation_n(eng2, N, n + 1) xx = initialisation_n(eng2, x, n + 1) xb = initialisation_n(eng2, b, n + 1) [xc, aux] = initialisation(eng2, [1, 0]) gateUa(eng2, a, inv_a, xx, xb, xN, aux, xc, N) eng2.flush() Measure | aux Measure | xc All(Measure) | xx All(Measure) | xb All(Measure) | xN eng2.flush() print(drawing_engine.get_latex()) else: if param == "count": eng = MainEngine(resource_counter) else: eng = MainEngine(Simulator(), compilerengines) xN = initialisation_n(eng, N, n + 1) xx = initialisation_n(eng, x, n + 1) xb = initialisation_n(eng, b, n + 1) [xc, aux] = initialisation(eng, [1, 0]) gateUa(eng, a, inv_a, xx, xb, xN, aux, xc, N) Measure | aux Measure | xc All(Measure) | xx All(Measure) | xb All(Measure) | xN eng.flush() if param == "count": return resource_counter measurements_b = [0] * n measurements_x = [0] * n measurements_N = [0] * n for k in range(n): measurements_b[k] = int(xb[k]) measurements_N[k] = int(xN[k]) measurements_x[k] = int(xx[k]) mes_aux = int(aux[0]) mes_c = int(aux[0]) assert int(xb[n]) == 0 assert int(xN[n]) == 0 assert int(xx[n]) == 0 assert meas2int(measurements_b) == 0 assert meas2int(measurements_N) == N assert mes_aux == 0 return [(a * x) % N, meas2int(measurements_x), measurements_x, mes_c]
def run(a=4, N=7, x=2, param="run"): """ :param a: a<N and must be invertible mod[N] :param N: :param x: :param param: :return: |1> --> |(a**x) mod N> """ # build compilation engine list resource_counter = ResourceCounter() rule_set = DecompositionRuleSet( modules=[projectq.libs.math, projectq.setups.decompositions]) compilerengines = [ AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), resource_counter ] # create a main compiler engine a = a % N b = 0 n = int(math.log(N, 2)) + 1 if param == "latex": drawing_engine = CircuitDrawer() eng = MainEngine(drawing_engine) if param == "count": eng = MainEngine(resource_counter) else: eng = MainEngine(Simulator(), compilerengines) output = initialisation_n(eng, 1, n + 1) xN = initialisation_n(eng, N, n + 1) xx = initialisation_n(eng, x, n + 1) xb = initialisation_n(eng, b, n + 1) aux = initialisation_n(eng, 0, 1) expoModN(eng, a, output, xb, xN, aux, xx, N) Measure | aux All(Measure) | output All(Measure) | xx All(Measure) | xb All(Measure) | xN eng.flush() if param == "count": return resource_counter if param == "latex": print(drawing_engine.get_latex()) measurements_b = [0] * n measurements_x = [0] * n measurements_N = [0] * n for k in range(n): measurements_b[k] = int(xb[k]) measurements_N[k] = int(xN[k]) measurements_x[k] = int(output[k]) mes_aux = int(aux[0]) assert int(xb[n]) == 0 assert int(xN[n]) == 0 assert int(xx[n]) == 0 assert meas2int(measurements_b) == 0 assert meas2int(measurements_N) == N assert mes_aux == 0 return [(a**x) % N, meas2int(measurements_x), measurements_x]
def run(a=11, b=1, N=12, param="simulation"): # build compilation engine list resource_counter = ResourceCounter() rule_set = DecompositionRuleSet( modules=[projectq.libs.math, projectq.setups.decompositions]) compilerengines = [ AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), AutoReplacer(rule_set), TagRemover(), LocalOptimizer(3), resource_counter ] # create a main compiler engine n = int(math.log(N, 2)) + 1 if param == "latex": drawing_engine = CircuitDrawer() eng2 = MainEngine(drawing_engine) xN = initialisation_n(eng2, N, n + 1) xa = initialisation_n(eng2, a, n + 1) xb = initialisation_n(eng2, b, n + 1) c1 = initialisation_n(eng2, 1) c2 = initialisation_n(eng2, 1) aux = initialisation_n(eng2, 0) # b --> phi(b) QFT | xb modularAdder(eng2, xa, xb, xN, c1, c2, aux) with Dagger(eng2): QFT | xb Measure | c1 Measure | c2 Measure | aux All(Measure) | xa All(Measure) | xb All(Measure) | xN eng2.flush() print(drawing_engine.get_latex()) else: eng = MainEngine(Simulator(), compilerengines) xN = initialisation_n(eng, N, n + 1) xa = initialisation_n(eng, a, n + 1) xb = initialisation_n(eng, b, n + 1) [c1, c2, aux] = initialisation(eng, [1, 1, 0]) # b --> phi(b) QFT | xb modularAdder(eng, xa, xb, xN, c1, c2, aux) with Dagger(eng): QFT | xb Measure | c1 Measure | c2 Measure | aux All(Measure) | xa All(Measure) | xb All(Measure) | xN eng.flush() measurements_a = [0] * n measurements_b = [0] * n measurements_N = [0] * n for k in range(n): measurements_a[k] = int(xa[k]) measurements_b[k] = int(xb[k]) measurements_N[k] = int(xN[k]) return [ measurements_a, measurements_b, int(xb[n]), measurements_N, int(aux[0]), int(c1[0]), int(c2[0]), meas2int(measurements_b), (a + b) % N ]