init: repository publish
This commit is contained in:
commit
2120e6fbf5
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
libs/
|
||||||
|
.env
|
||||||
|
__pycache__/
|
43
bench-cirq/deutsch_algorithm.py
Normal file
43
bench-cirq/deutsch_algorithm.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from cirq import LineQubit,Circuit,CNOT,X,H,measure
|
||||||
|
from cirq import Simulator
|
||||||
|
|
||||||
|
from qiskit import IBMQ
|
||||||
|
|
||||||
|
from quantum_runner import quantum_simulate,setup_IBM,cirq_qasm
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
q0,q1 = LineQubit.range(2)
|
||||||
|
|
||||||
|
ffunction = [randint(0, 1) for _ in range(2)]
|
||||||
|
|
||||||
|
# создаем вентиль для генерации функции
|
||||||
|
def make_oracle(q0,q1,ffunction):
|
||||||
|
if ffunction[0]:
|
||||||
|
# используем контролируемый вентиль отрицания и матрицу Паули по координате x, sigma_x
|
||||||
|
yield [CNOT(q0,q1), X(q1)]
|
||||||
|
if ffunction[1]:
|
||||||
|
yield CNOT(q0,q1)
|
||||||
|
|
||||||
|
print(f"f(x) = <{', '.join(str(e) for e in ffunction)}>")
|
||||||
|
|
||||||
|
circuit = Circuit()
|
||||||
|
|
||||||
|
# создаем кубиты используя вентиль Адамара и матрицу Паули
|
||||||
|
|
||||||
|
circuit.append([X(q1),H(q1),H(q0)])
|
||||||
|
|
||||||
|
# добавляем функцию
|
||||||
|
circuit.append(make_oracle(q0,q1,ffunction))
|
||||||
|
|
||||||
|
# проведем измерение
|
||||||
|
circuit.append([H(q0),measure(q0)])
|
||||||
|
|
||||||
|
print(circuit)
|
||||||
|
print(Simulator().run(circuit))
|
||||||
|
|
||||||
|
# запуск на квантовом компьютере
|
||||||
|
|
||||||
|
setup_IBM()
|
||||||
|
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
|
||||||
|
print(quantum_simulate(cirq_qasm(circuit,(q0,q1,)),provider.get_backend('ibm_lagos'),True))
|
61
bench-cirq/grover_algorithm.py
Normal file
61
bench-cirq/grover_algorithm.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# https://github.com/quantumlib/Cirq/blob/master/examples/grover.py
|
||||||
|
# https://quantum-ods.github.io/qmlcourse/book/qcalgo/ru/grovers_algorithm.html
|
||||||
|
|
||||||
|
from ctypes import wstring_at
|
||||||
|
from random import randint
|
||||||
|
from cirq import Circuit,X,H,CNOT,TOFFOLI,GridQubit,measure
|
||||||
|
from cirq import Simulator
|
||||||
|
|
||||||
|
from qiskit import IBMQ
|
||||||
|
|
||||||
|
from quantum_runner import quantum_simulate,setup_IBM,cirq_qasm
|
||||||
|
|
||||||
|
def oracle(iqs,oq,bits):
|
||||||
|
yield (X(q) for (q, bit) in zip(iqs,bits) if not bit)
|
||||||
|
yield (TOFFOLI(iqs[0],iqs[1],oq))
|
||||||
|
yield (X(q) for (q,bit) in zip(iqs,bits) if not bit)
|
||||||
|
|
||||||
|
circuit = Circuit()
|
||||||
|
|
||||||
|
qb_count = 2
|
||||||
|
|
||||||
|
iqs = [GridQubit(i,0) for i in range(qb_count)]
|
||||||
|
oq = GridQubit(qb_count,0)
|
||||||
|
bits = [randint(0, 1) for _ in range(qb_count)]
|
||||||
|
|
||||||
|
circuit.append([X(oq),H(oq),H.on_each(iqs)])
|
||||||
|
|
||||||
|
circuit.append(oracle(iqs,oq,bits))
|
||||||
|
|
||||||
|
# Строим оператор Гровера
|
||||||
|
circuit.append(H.on_each(iqs))
|
||||||
|
circuit.append(X.on_each(iqs))
|
||||||
|
circuit.append(H.on(iqs[1]))
|
||||||
|
circuit.append(CNOT.on(iqs[0],iqs[1]))
|
||||||
|
circuit.append(H.on(iqs[1]))
|
||||||
|
circuit.append(X.on_each(iqs))
|
||||||
|
circuit.append(H.on_each(iqs))
|
||||||
|
|
||||||
|
circuit.append(measure(iqs, key="result"))
|
||||||
|
|
||||||
|
print(circuit)
|
||||||
|
|
||||||
|
result = Simulator().run(circuit,repetitions=10)
|
||||||
|
|
||||||
|
def bitstring(bits):
|
||||||
|
return ''.join(str(int(b)) for b in bits)
|
||||||
|
|
||||||
|
frequencies = result.histogram(key='result',fold_func=bitstring)
|
||||||
|
|
||||||
|
print(f"результат",frequencies)
|
||||||
|
print(f"наиболее распространеная битовая строка",frequencies.most_common(1)[0][0])
|
||||||
|
|
||||||
|
setup_IBM()
|
||||||
|
|
||||||
|
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
|
||||||
|
|
||||||
|
quantum_simulate(
|
||||||
|
cirq_qasm(circuit),
|
||||||
|
provider.get_backend('ibmq_lima'),
|
||||||
|
True
|
||||||
|
)
|
143
bench-cirq/shor_algorithm.py
Normal file
143
bench-cirq/shor_algorithm.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# https://github.com/dmitrifried/Shors-Algorithm-in-Cirq/blob/master/Shor's%20Algorithm%20in%20Cirq.ipynb
|
||||||
|
|
||||||
|
from math import gcd,floor,ceil,pow,log2
|
||||||
|
from random import randint
|
||||||
|
from typing import Optional,Sequence,Union,Callable
|
||||||
|
from fractions import Fraction
|
||||||
|
|
||||||
|
from sympy import isprime
|
||||||
|
|
||||||
|
from cirq import ArithmeticGate,Circuit,X,H,qft,measure,LineQubit
|
||||||
|
from cirq import CircuitDiagramInfoArgs,CircuitDiagramInfo,Result
|
||||||
|
from cirq import Simulator
|
||||||
|
|
||||||
|
def classic_order_finder(x: int, n: int) -> Optional[int]:
|
||||||
|
"""
|
||||||
|
Поиск делителя классическим способом
|
||||||
|
"""
|
||||||
|
if x < 2 or n <= x or gcd(x, n) > 1:
|
||||||
|
raise ValueError(f'Invalid x={x} for modulus n={n}.')
|
||||||
|
r, y = 1, x
|
||||||
|
while y != 1:
|
||||||
|
y = (x * y) % n
|
||||||
|
r += 1
|
||||||
|
return r
|
||||||
|
|
||||||
|
class ModularExp(ArithmeticGate):
|
||||||
|
def __init__(self, target: Sequence[int], exponent: Union[int, Sequence[int]], base: int, modulus: int) -> None:
|
||||||
|
if len(target) < modulus.bit_length():
|
||||||
|
raise ValueError(
|
||||||
|
f'Регистр с {len(target)} кубитами маленький для {modulus}'
|
||||||
|
)
|
||||||
|
self.target = target
|
||||||
|
self.exponent = exponent
|
||||||
|
self.base = base
|
||||||
|
self.modulus = modulus
|
||||||
|
|
||||||
|
def registers(self) -> Sequence[Union[int, Sequence[int]]]:
|
||||||
|
return self.target, self.exponent, self.base, self.modulus
|
||||||
|
|
||||||
|
def with_registers(self, *new_registers: Union[int, Sequence[int]]) -> 'ModularExp':
|
||||||
|
if len(new_registers) != 4:
|
||||||
|
raise ValueError(
|
||||||
|
f'Expected 4 registers (target, exponent, base, '
|
||||||
|
f'modulus), but got {len(new_registers)}'
|
||||||
|
)
|
||||||
|
target, exponent, base, modulus = new_registers
|
||||||
|
if not isinstance(target, Sequence):
|
||||||
|
raise ValueError(f'Метка должна быть регистром кубитов {type(target)}')
|
||||||
|
if not isinstance(modulus,int):
|
||||||
|
raise ValueError(f'модуль это классическая константа {type(modulus)}')
|
||||||
|
if not isinstance(base,int):
|
||||||
|
raise ValueError(f'база у числа это классическая константа {type(base)}')
|
||||||
|
return ModularExp(target, exponent, base, modulus)
|
||||||
|
def apply(self, *register_values: int) -> int:
|
||||||
|
assert len(register_values) == 4
|
||||||
|
target, exponent, base, modulus = register_values
|
||||||
|
if target >= modulus:
|
||||||
|
return target
|
||||||
|
return (target * base**exponent) % modulus
|
||||||
|
def _circuit_diagram_info_(self, args: CircuitDiagramInfoArgs) -> CircuitDiagramInfo:
|
||||||
|
assert args.known_qubits is not None
|
||||||
|
wire_symbols = [f't{i}' for i in range(len(self.target))]
|
||||||
|
e_str = str(self.exponent)
|
||||||
|
if isinstance(self.exponent, Sequence):
|
||||||
|
e_str = 'e'
|
||||||
|
wire_symbols += [f'e{i}' for i in range(len(self.exponent))]
|
||||||
|
wire_symbols[0] = f'ModularExp(t*{self.base}**{e_str} % {self.modulus})'
|
||||||
|
return CircuitDiagramInfo(wire_symbols=tuple(wire_symbols))
|
||||||
|
|
||||||
|
def make_order_finding_circuit(x: int, n: int) -> Circuit:
|
||||||
|
L = n.bit_length()
|
||||||
|
target = LineQubit.range(L)
|
||||||
|
exponent = LineQubit.range(L, 3 * L + 3)
|
||||||
|
return Circuit(
|
||||||
|
X(target[L - 1]),
|
||||||
|
H.on_each(*exponent),
|
||||||
|
ModularExp([2] * len(target), [2] * len(exponent), x, n).on(*target + exponent),
|
||||||
|
qft(*exponent, inverse=True),
|
||||||
|
measure(*exponent, key='exponent'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def read_eigenphase(result: Result) -> float:
|
||||||
|
exponent_as_integer = result.data['exponent'][0]
|
||||||
|
exponent_num_bits = result.measurements['exponent'].shape[1]
|
||||||
|
return float(exponent_as_integer / 2**exponent_num_bits)
|
||||||
|
|
||||||
|
def quantum_order_finder(x: int, n: int) -> Optional[int]:
|
||||||
|
if x < 2 or n <= x or gcd(x, n) > 1:
|
||||||
|
raise ValueError(f'Неправильный x={x} для модуля n={n}.')
|
||||||
|
|
||||||
|
circuit = make_order_finding_circuit(x, n)
|
||||||
|
result = Simulator().run(circuit)
|
||||||
|
eigenphase = read_eigenphase(result)
|
||||||
|
f = Fraction.from_float(eigenphase).limit_denominator(n)
|
||||||
|
if f.numerator == 0:
|
||||||
|
return None
|
||||||
|
r = f.denominator
|
||||||
|
if x**r % n != 1:
|
||||||
|
return None
|
||||||
|
print(circuit)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def find_factor_of_prime_power(n: int) -> Optional[int]:
|
||||||
|
for k in range(2, floor(log2(n)) + 1):
|
||||||
|
c = pow(n, 1 / k)
|
||||||
|
c1 =floor(c)
|
||||||
|
if c1**k == n:
|
||||||
|
return c1
|
||||||
|
c2 = ceil(c)
|
||||||
|
if c2**k == n:
|
||||||
|
return c2
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_factor(
|
||||||
|
n: int, order_finder: Callable[[int, int], Optional[int]], max_attempts: int = 30
|
||||||
|
) -> Optional[int]:
|
||||||
|
if isprime(n):
|
||||||
|
return None
|
||||||
|
if n % 2 == 0:
|
||||||
|
return 2
|
||||||
|
c = find_factor_of_prime_power(n)
|
||||||
|
if c is not None:
|
||||||
|
return c
|
||||||
|
for _ in range(max_attempts):
|
||||||
|
x = randint(2, n - 1)
|
||||||
|
c = gcd(x, n)
|
||||||
|
if 1 < c < n:
|
||||||
|
return c
|
||||||
|
r = order_finder(x, n)
|
||||||
|
if r is None:
|
||||||
|
continue
|
||||||
|
if r % 2 != 0:
|
||||||
|
continue
|
||||||
|
y = x ** (r // 2) % n
|
||||||
|
assert 1 < y < n
|
||||||
|
c = gcd(y - 1, n)
|
||||||
|
if 1 < c < n:
|
||||||
|
return c
|
||||||
|
return None
|
||||||
|
|
||||||
|
n = 33
|
||||||
|
d = find_factor(n, quantum_order_finder)
|
||||||
|
|
85
bench-qiskit/deutsch_alogrithm.py
Normal file
85
bench-qiskit/deutsch_alogrithm.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# https://github.com/qiskit-community/qiskit-community-tutorials/blob/master/algorithms/deutsch_jozsa.ipynb
|
||||||
|
# https://github.com/mrtkp9993/QuantumComputingExamples
|
||||||
|
# https://github.com/DavitKhach/quantum-algorithms-tutorials/blob/master/quantum_parallelism_Deutsch_Jozsa.ipynb
|
||||||
|
# https://fullstackquantumcomputation.tech/blog/deutsch-algorithm/
|
||||||
|
# https://www.mlq.ai/quantum-programming-with-qiskit/
|
||||||
|
# https://github.com/przecze/deutschs_algorithm_in_qiskit_vs_cirq/blob/main/common.py
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
from qiskit import QuantumCircuit,QuantumRegister,ClassicalRegister
|
||||||
|
from qiskit import BasicAer,IBMQ
|
||||||
|
from qiskit.tools.monitor import job_monitor
|
||||||
|
|
||||||
|
from qiskit import transpile
|
||||||
|
|
||||||
|
from quantum_runner import quantum_simulate,setup_IBM
|
||||||
|
|
||||||
|
|
||||||
|
# количество создаваемых битов
|
||||||
|
n = 1
|
||||||
|
|
||||||
|
# создаем функции
|
||||||
|
ff = randint(0, n)
|
||||||
|
|
||||||
|
if ff !=0:
|
||||||
|
randint(1,2**n)
|
||||||
|
|
||||||
|
# создание n-кубитов в системе
|
||||||
|
|
||||||
|
qr = QuantumRegister(n+1)
|
||||||
|
|
||||||
|
# создание n классических битов, для записи измерений
|
||||||
|
|
||||||
|
cr = ClassicalRegister(n)
|
||||||
|
|
||||||
|
circuit = QuantumCircuit(qr,cr)
|
||||||
|
|
||||||
|
# создаем вспомогательные кубиты
|
||||||
|
|
||||||
|
circuit.x(qr[n])
|
||||||
|
|
||||||
|
circuit.h(qr[n])
|
||||||
|
|
||||||
|
# Барьер нужен для группировки отдельных частей цепи
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# Первая часть, это подготовка суперпозиции состояний.
|
||||||
|
# Для этого используем вентиль Адамара
|
||||||
|
|
||||||
|
circuit.h(qr[0])
|
||||||
|
circuit.h(qr[1])
|
||||||
|
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# Создаем квантовый оракул, используя контроллер
|
||||||
|
circuit.cx(qr[0],qr[1])
|
||||||
|
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# Применяем вентиль уже к оракулу
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
circuit.h(qr[i])
|
||||||
|
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# Измеряем кубит
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
circuit.measure(qr[i],cr[i])
|
||||||
|
|
||||||
|
# Запустим локально
|
||||||
|
|
||||||
|
backend = BasicAer.get_backend("qasm_simulator")
|
||||||
|
results = quantum_simulate(circuit,backend,True)
|
||||||
|
results = list(results.keys())
|
||||||
|
|
||||||
|
print(circuit)
|
||||||
|
print(f"q({ff})=",results)
|
||||||
|
|
||||||
|
#setup_IBM()
|
||||||
|
#provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
|
||||||
|
#backend = provider.get_backend('ibmq_lima')
|
||||||
|
#job_monitor(quantum_simulate(circuit,backend), interval=2)
|
||||||
|
|
||||||
|
#print(quantum_simulate(circuit,backend,True))
|
49
bench-qiskit/grover_algorithm.py
Normal file
49
bench-qiskit/grover_algorithm.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# https://www.qmunity.tech/tutorials/grovers-algorithm-using-2-qubits
|
||||||
|
from qiskit import QuantumCircuit
|
||||||
|
from qiskit import BasicAer,IBMQ
|
||||||
|
|
||||||
|
from quantum_runner import setup_IBM,quantum_simulate
|
||||||
|
|
||||||
|
qb_count = 2
|
||||||
|
|
||||||
|
circuit = QuantumCircuit(qb_count)
|
||||||
|
|
||||||
|
circuit.h(0)
|
||||||
|
circuit.h(1)
|
||||||
|
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# создаем оракул для котроллируемого вентиля по z
|
||||||
|
circuit.cz(0,1)
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
# создаем оператор гровера
|
||||||
|
for k in range(0,qb_count):
|
||||||
|
circuit.h(k)
|
||||||
|
for k in range(0,qb_count):
|
||||||
|
circuit.x(k)
|
||||||
|
|
||||||
|
circuit.h(1)
|
||||||
|
circuit.cx(0,1)
|
||||||
|
|
||||||
|
circuit.x(0)
|
||||||
|
circuit.h(1)
|
||||||
|
circuit.h(0)
|
||||||
|
circuit.x(1)
|
||||||
|
circuit.h(1)
|
||||||
|
|
||||||
|
circuit.barrier()
|
||||||
|
|
||||||
|
circuit.measure_all()
|
||||||
|
|
||||||
|
print(circuit)
|
||||||
|
|
||||||
|
backend = BasicAer.get_backend("qasm_simulator")
|
||||||
|
results = quantum_simulate(circuit,backend,True)
|
||||||
|
|
||||||
|
print(quantum_simulate(circuit,backend,True))
|
||||||
|
|
||||||
|
|
||||||
|
setup_IBM()
|
||||||
|
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
|
||||||
|
quantum_simulate(circuit,provider.get_backend('ibm_lagos'),True)
|
376
bench-qiskit/shor_algorithm.py
Normal file
376
bench-qiskit/shor_algorithm.py
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
# https://qiskit.org/documentation/tutorials/circuits/3_summary_of_quantum_operations.html
|
||||||
|
# https://github.com/olekssy/qiskit-shors/blob/master/shors.py
|
||||||
|
# https://quantumcomputinguk.org/tutorials/shors-algorithm-with-code
|
||||||
|
|
||||||
|
from math import pow,gcd,floor,isinf,ceil,log
|
||||||
|
|
||||||
|
from numpy import zeros,pi
|
||||||
|
|
||||||
|
from fractions import Fraction
|
||||||
|
from array import array
|
||||||
|
|
||||||
|
from qiskit import QuantumRegister,ClassicalRegister,QuantumCircuit
|
||||||
|
from qiskit import IBMQ
|
||||||
|
|
||||||
|
from quantum_runner import setup_IBM,quantum_simulate
|
||||||
|
|
||||||
|
def check_if_power(N):
|
||||||
|
b=2
|
||||||
|
while (2**b) <= N:
|
||||||
|
a = 1
|
||||||
|
c = N
|
||||||
|
while (c-a) >= 2:
|
||||||
|
m = int( (a+c)/2 )
|
||||||
|
|
||||||
|
if (m**b) < (N+1):
|
||||||
|
p = int( (m**b) )
|
||||||
|
else:
|
||||||
|
p = int(N+1)
|
||||||
|
|
||||||
|
if int(p) == int(N):
|
||||||
|
print('N is {0}^{1}'.format(int(m),int(b)) )
|
||||||
|
return True
|
||||||
|
|
||||||
|
if p<N:
|
||||||
|
a = int(m)
|
||||||
|
else:
|
||||||
|
c = int(m)
|
||||||
|
b=b+1
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def create_QFT(circuit,up_reg,n,with_swaps):
|
||||||
|
i=n-1
|
||||||
|
while i>=0:
|
||||||
|
circuit.h(up_reg[i])
|
||||||
|
j=i-1
|
||||||
|
while j>=0:
|
||||||
|
if (pi)/(pow(2,(i-j))) > 0:
|
||||||
|
circuit.crz( (pi)/(pow(2,(i-j))) , up_reg[i] , up_reg[j] )
|
||||||
|
j=j-1
|
||||||
|
i=i-1
|
||||||
|
|
||||||
|
if with_swaps==1:
|
||||||
|
i=0
|
||||||
|
while i < ((n-1)/2):
|
||||||
|
circuit.swap(up_reg[i], up_reg[n-1-i])
|
||||||
|
i=i+1
|
||||||
|
|
||||||
|
def create_inverse_QFT(circuit,up_reg,n,with_swaps):
|
||||||
|
if with_swaps==1:
|
||||||
|
i=0
|
||||||
|
while i < ((n-1)/2):
|
||||||
|
circuit.swap(up_reg[i], up_reg[n-1-i])
|
||||||
|
i=i+1
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<n:
|
||||||
|
circuit.h(up_reg[i])
|
||||||
|
if i != n-1:
|
||||||
|
j=i+1
|
||||||
|
y=i
|
||||||
|
while y>=0:
|
||||||
|
if (pi)/(pow(2,(j-y))) > 0:
|
||||||
|
circuit.crz( - (pi)/(pow(2,(j-y))) , up_reg[j] , up_reg[y] )
|
||||||
|
|
||||||
|
|
||||||
|
def egcd(a, b):
|
||||||
|
if a == 0:
|
||||||
|
return (b, 0, 1)
|
||||||
|
else:
|
||||||
|
g, y, x = egcd(b % a, a)
|
||||||
|
return (g, x - (b // a) * y, y)
|
||||||
|
|
||||||
|
def modinv(a, m):
|
||||||
|
g, x, y = egcd(a, m)
|
||||||
|
if g != 1:
|
||||||
|
raise Exception('modular inverse does not exist')
|
||||||
|
else:
|
||||||
|
return x % m
|
||||||
|
|
||||||
|
def get_factors(x_value,t_upper,N,a):
|
||||||
|
|
||||||
|
if x_value<=0:
|
||||||
|
print('x_value is <= 0, there are no continued fractions\n')
|
||||||
|
return False
|
||||||
|
|
||||||
|
# print('Running continued fractions for this case\n')
|
||||||
|
|
||||||
|
T = pow(2,t_upper)
|
||||||
|
|
||||||
|
x_over_T = x_value/T
|
||||||
|
|
||||||
|
i=0
|
||||||
|
b = array('i')
|
||||||
|
t = array('f')
|
||||||
|
|
||||||
|
b.append(floor(x_over_T))
|
||||||
|
t.append(x_over_T - b[i])
|
||||||
|
|
||||||
|
while i>=0:
|
||||||
|
|
||||||
|
if i>0:
|
||||||
|
b.append( floor( 1 / (t[i-1]) ) )
|
||||||
|
t.append( ( 1 / (t[i-1]) ) - b[i] )
|
||||||
|
|
||||||
|
|
||||||
|
aux = 0
|
||||||
|
j=i
|
||||||
|
while j>0:
|
||||||
|
aux = 1 / ( b[j] + aux )
|
||||||
|
j = j-1
|
||||||
|
|
||||||
|
aux = aux + b[0]
|
||||||
|
|
||||||
|
frac = Fraction(aux).limit_denominator()
|
||||||
|
den=frac.denominator
|
||||||
|
|
||||||
|
print('Approximation number {0} of continued fractions:'.format(i+1))
|
||||||
|
print("Numerator:{0} \t\t Denominator: {1}\n".format(frac.numerator,frac.denominator))
|
||||||
|
|
||||||
|
""" Increment i for next iteration """
|
||||||
|
i=i+1
|
||||||
|
|
||||||
|
if (den%2) == 1:
|
||||||
|
if i>=15:
|
||||||
|
print('Returning because have already done too much tries')
|
||||||
|
return False
|
||||||
|
print('Odd denominator, will try next iteration of continued fractions\n')
|
||||||
|
continue
|
||||||
|
|
||||||
|
""" If denominator even, try to get factors of N """
|
||||||
|
|
||||||
|
""" Get the exponential a^(r/2) """
|
||||||
|
|
||||||
|
exponential = 0
|
||||||
|
|
||||||
|
if den<1000:
|
||||||
|
exponential=pow(a , (den/2))
|
||||||
|
|
||||||
|
""" Check if the value is too big or not """
|
||||||
|
if isinf(exponential)==1 or exponential>1000000000:
|
||||||
|
print('Denominator of continued fraction is too big!\n')
|
||||||
|
aux_out = input('Input number 1 if you want to continue searching, other if you do not: ')
|
||||||
|
if aux_out != '1':
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
putting_plus = int(exponential + 1)
|
||||||
|
|
||||||
|
putting_minus = int(exponential - 1)
|
||||||
|
|
||||||
|
one_factor = gcd(putting_plus,N)
|
||||||
|
other_factor = gcd(putting_minus,N)
|
||||||
|
|
||||||
|
""" Check if the factors found are trivial factors or are the desired
|
||||||
|
factors """
|
||||||
|
|
||||||
|
if one_factor==1 or one_factor==N or other_factor==1 or other_factor==N:
|
||||||
|
print('Found just trivial factors, not good enough\n')
|
||||||
|
if t[i-1]==0:
|
||||||
|
print('The continued fractions found exactly x_final/(2^(2n)) , leaving funtion\n')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
""" Return if already too much tries and numbers are huge """
|
||||||
|
print('Returning because have already done too many tries\n')
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print('The factors of {0} are {1} and {2}\n'.format(N,one_factor,other_factor))
|
||||||
|
print('Found the desired factors!\n')
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getAngles(a,N):
|
||||||
|
s=bin(int(a))[2:].zfill(N)
|
||||||
|
angles=zeros([N])
|
||||||
|
for i in range(0, N):
|
||||||
|
for j in range(i,N):
|
||||||
|
if s[j]=='1':
|
||||||
|
angles[N-i-1]+=pow(2, -(j-i))
|
||||||
|
angles[N-i-1]*=pi
|
||||||
|
return angles
|
||||||
|
|
||||||
|
def ccphase(circuit,angle,ctl1,ctl2,tgt):
|
||||||
|
circuit.crz(angle/2,ctl1,tgt)
|
||||||
|
circuit.cx(ctl2,ctl1)
|
||||||
|
circuit.crz(-angle/2,ctl1,tgt)
|
||||||
|
circuit.cx(ctl2,ctl1)
|
||||||
|
circuit.crz(angle/2,ctl2,tgt)
|
||||||
|
|
||||||
|
def phiADD(circuit,q,a,N,inv):
|
||||||
|
angle=getAngles(a,N)
|
||||||
|
for i in range(0,N):
|
||||||
|
if inv==0:
|
||||||
|
circuit.p(angle[i],q[i])
|
||||||
|
else:
|
||||||
|
circuit.p(-angle[i],q[i])
|
||||||
|
|
||||||
|
def cphiADD(circuit,q,ctl,a,n,inv):
|
||||||
|
angle=getAngles(a,n)
|
||||||
|
for i in range(0,n):
|
||||||
|
if inv==0:
|
||||||
|
circuit.crz(angle[i],ctl,q[i])
|
||||||
|
else:
|
||||||
|
circuit.crz(-angle[i],ctl,q[i])
|
||||||
|
|
||||||
|
def ccphiADD(circuit,q,ctl1,ctl2,a,n,inv):
|
||||||
|
angle=getAngles(a,n)
|
||||||
|
for i in range(0,n):
|
||||||
|
if inv==0:
|
||||||
|
ccphase(circuit,angle[i],ctl1,ctl2,q[i])
|
||||||
|
else:
|
||||||
|
ccphase(circuit,-angle[i],ctl1,ctl2,q[i])
|
||||||
|
|
||||||
|
def ccphiADDmodN(circuit, q, ctl1, ctl2, aux, a, N, n):
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 0)
|
||||||
|
phiADD(circuit, q, N, n, 1)
|
||||||
|
create_inverse_QFT(circuit, q, n, 0)
|
||||||
|
circuit.cx(q[n-1],aux)
|
||||||
|
create_QFT(circuit,q,n,0)
|
||||||
|
cphiADD(circuit, q, aux, N, n, 0)
|
||||||
|
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 1)
|
||||||
|
create_inverse_QFT(circuit, q, n, 0)
|
||||||
|
circuit.x(q[n-1])
|
||||||
|
circuit.cx(q[n-1], aux)
|
||||||
|
circuit.x(q[n-1])
|
||||||
|
create_QFT(circuit,q,n,0)
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 0)
|
||||||
|
|
||||||
|
def ccphiADDmodN_inv(circuit, q, ctl1, ctl2, aux, a, N, n):
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 1)
|
||||||
|
create_inverse_QFT(circuit, q, n, 0)
|
||||||
|
circuit.x(q[n-1])
|
||||||
|
circuit.cx(q[n-1],aux)
|
||||||
|
circuit.x(q[n-1])
|
||||||
|
create_QFT(circuit, q, n, 0)
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 0)
|
||||||
|
cphiADD(circuit, q, aux, N, n, 1)
|
||||||
|
create_inverse_QFT(circuit, q, n, 0)
|
||||||
|
circuit.cx(q[n-1], aux)
|
||||||
|
create_QFT(circuit, q, n, 0)
|
||||||
|
phiADD(circuit, q, N, n, 0)
|
||||||
|
ccphiADD(circuit, q, ctl1, ctl2, a, n, 1)
|
||||||
|
|
||||||
|
def cMULTmodN(circuit, ctl, q, aux, a, N, n):
|
||||||
|
create_QFT(circuit,aux,n+1,0)
|
||||||
|
for i in range(0, n):
|
||||||
|
ccphiADDmodN(circuit, aux, q[i], ctl, aux[n+1], (2**i)*a % N, N, n+1)
|
||||||
|
create_inverse_QFT(circuit, aux, n+1, 0)
|
||||||
|
|
||||||
|
for i in range(0, n):
|
||||||
|
circuit.cswap(ctl,q[i],aux[i])
|
||||||
|
|
||||||
|
a_inv = modinv(a, N)
|
||||||
|
create_QFT(circuit, aux, n+1, 0)
|
||||||
|
i = n-1
|
||||||
|
while i >= 0:
|
||||||
|
ccphiADDmodN_inv(circuit, aux, q[i], ctl, aux[n+1], pow(2,i)*a_inv % N, N, n+1)
|
||||||
|
i -= 1
|
||||||
|
create_inverse_QFT(circuit, aux, n+1, 0)
|
||||||
|
|
||||||
|
def get_value_a(N):
|
||||||
|
a=2
|
||||||
|
while gcd(a,N)!=1:
|
||||||
|
a=a+1
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def factorize_number(N):
|
||||||
|
if N==1 or N==0:
|
||||||
|
print('Please put an N different from 0 and from 1')
|
||||||
|
exit()
|
||||||
|
|
||||||
|
""" Check if N is even """
|
||||||
|
|
||||||
|
if (N%2)==0:
|
||||||
|
print('N is even, so does not make sense!')
|
||||||
|
exit()
|
||||||
|
|
||||||
|
""" Check if N can be put in N=p^q, p>1, q>=2 """
|
||||||
|
|
||||||
|
""" Try all numbers for p: from 2 to sqrt(N) """
|
||||||
|
if check_if_power(N)==True:
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# print('Not an easy case, using the quantum circuit is necessary\n')
|
||||||
|
|
||||||
|
setup_IBM()
|
||||||
|
|
||||||
|
""" Get an integer a that is coprime with N """
|
||||||
|
a = get_value_a(N)
|
||||||
|
|
||||||
|
# """ If user wants to force some values, he can do that here, please make sure to update the print and that N and a are coprime"""
|
||||||
|
# print('Forcing N=15 and a=4 because its the fastest case, please read top of source file for more info')
|
||||||
|
# N=15
|
||||||
|
# a=4
|
||||||
|
|
||||||
|
print("help !!!")
|
||||||
|
""" Get n value used in Shor's algorithm, to know how many qubits are used """
|
||||||
|
n = ceil(log(N,2))
|
||||||
|
|
||||||
|
# print('Total number of qubits used: {0}\n'.format(4*n+2))
|
||||||
|
|
||||||
|
aux = QuantumRegister(n+2)
|
||||||
|
up_reg = QuantumRegister(2*n)
|
||||||
|
down_reg = QuantumRegister(n)
|
||||||
|
up_classic = ClassicalRegister(2*n)
|
||||||
|
circuit = QuantumCircuit(down_reg , up_reg , aux, up_classic)
|
||||||
|
|
||||||
|
circuit.h(up_reg)
|
||||||
|
circuit.x(down_reg[0])
|
||||||
|
|
||||||
|
""" Apply the multiplication gates as showed in the report in order to create the exponentiation """
|
||||||
|
for i in range(0, 2*n):
|
||||||
|
cMULTmodN(circuit, up_reg[i], down_reg, aux, int(pow(a, pow(2, i))), N, n)
|
||||||
|
|
||||||
|
""" Apply inverse QFT """
|
||||||
|
create_inverse_QFT(circuit, up_reg, 2*n ,1)
|
||||||
|
|
||||||
|
""" Measure the top qubits, to get x value"""
|
||||||
|
circuit.measure(up_reg,up_classic)
|
||||||
|
|
||||||
|
""" Simulate the created Quantum Circuit """
|
||||||
|
# print(transpile(circuit,BasicAer.get_backend('qasm_simulator')))
|
||||||
|
#simulation = execute(circuit, backend=BasicAer.get_backend('qasm_simulator'),shots=number_shots)
|
||||||
|
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
|
||||||
|
simulation = quantum_simulate(circuit,provider.get_backend('ibmq_lima'),True)
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i < len(simulation):
|
||||||
|
print('Result \"{0}\" happened {1} times out of {2}'.format(list(simulation.keys())[i],list(simulation.values())[i]))
|
||||||
|
i=i+1
|
||||||
|
|
||||||
|
""" An empty print just to have a good display in terminal """
|
||||||
|
print(' ')
|
||||||
|
|
||||||
|
""" Initialize this variable """
|
||||||
|
# prob_success=0
|
||||||
|
|
||||||
|
""" For each simulation result, print proper info to user and try to calculate the factors of N"""
|
||||||
|
# i=0
|
||||||
|
# while i < len(counts_result):
|
||||||
|
|
||||||
|
#""" Get the x_value from the final state qubits """
|
||||||
|
# output_desired = list(sim_result.get_counts().keys())[i]
|
||||||
|
# x_value = int(output_desired, 2)
|
||||||
|
# prob_this_result = 100 * ( int( list(sim_result.get_counts().values())[i] ) ) / (number_shots)
|
||||||
|
|
||||||
|
#print("------> Analysing result {0}. This result happened in {1:.4f} % of all cases\n".format(output_desired,prob_this_result))
|
||||||
|
|
||||||
|
#""" Print the final x_value to user """
|
||||||
|
# print('In decimal, x_final value for this result is: {0}\n'.format(x_value))
|
||||||
|
|
||||||
|
#""" Get the factors using the x value obtained """
|
||||||
|
# success=get_factors(int(x_value),int(2*n),int(N),int(a))
|
||||||
|
|
||||||
|
#if success==True:
|
||||||
|
# prob_success = prob_success + prob_this_result
|
||||||
|
|
||||||
|
#i=i+1
|
||||||
|
|
||||||
|
# print("\nUsing a={0}, found the factors of N={1} in {2:.4f} % of the cases\n".format(a,N,prob_success))
|
||||||
|
|
||||||
|
N = 33
|
||||||
|
factorize_number(N)
|
14
license
Normal file
14
license
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
BSD Zero Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Konrad Geletey
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
31
quantum_runner/__init__.py
Normal file
31
quantum_runner/__init__.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from qiskit import execute,QuantumCircuit
|
||||||
|
|
||||||
|
def quantum_simulate(circuit,backend,counts=False,shots=1024):
|
||||||
|
exe = execute(circuit,backend=backend,shots=shots)
|
||||||
|
if counts:
|
||||||
|
return exe.result().get_counts()
|
||||||
|
else:
|
||||||
|
return exe
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
#from pathlib import Path
|
||||||
|
from os import getenv
|
||||||
|
|
||||||
|
from qiskit import IBMQ
|
||||||
|
|
||||||
|
def setup_IBM():
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# сохранить аккаунт
|
||||||
|
IBMQ.save_account(getenv('API_KEY'), overwrite=True)
|
||||||
|
IBMQ.load_account()
|
||||||
|
|
||||||
|
from cirq import QasmOutput,Circuit,Qid
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
def cirq_qasm(circuit: 'Circuit'):
|
||||||
|
qasm_output = circuit.to_qasm()
|
||||||
|
return QuantumCircuit().from_qasm_str(str(qasm_output))
|
||||||
|
|
||||||
|
|
||||||
|
#print(provider.backends())
|
Reference in New Issue
Block a user