Spaces:
Configuration error
Configuration error
Create goldbahc_core.py
Browse files- goldbahc_core.py +84 -0
goldbahc_core.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sympy, math, itertools, time
|
| 2 |
+
from qiskit import QuantumCircuit, Aer, execute
|
| 3 |
+
from qiskit.circuit.library import QFT
|
| 4 |
+
|
| 5 |
+
def generate_qsieve_mask(max_val):
|
| 6 |
+
return [1 if sympy.isprime(i) else 0 for i in range(max_val + 1)]
|
| 7 |
+
|
| 8 |
+
def build_grover_circuit(N):
|
| 9 |
+
"""Возвращает схему + результат измерения."""
|
| 10 |
+
n = math.ceil(math.log2(N // 2 + 1))
|
| 11 |
+
qa = list(range(n))
|
| 12 |
+
qb = list(range(n, 2 * n))
|
| 13 |
+
anc = list(range(2 * n, 2 * n + 4))
|
| 14 |
+
qc = QuantumCircuit(2 * n + 4, 2 * n)
|
| 15 |
+
|
| 16 |
+
# суперпозиция
|
| 17 |
+
qc.h(qa + qb)
|
| 18 |
+
|
| 19 |
+
# решето
|
| 20 |
+
mask = generate_qsieve_mask(N // 2)
|
| 21 |
+
def apply_mask(qr, flag):
|
| 22 |
+
for val, is_prime in enumerate(mask):
|
| 23 |
+
if is_prime:
|
| 24 |
+
ctrl = [qr[i] for i in range(n) if not (val >> i) & 1]
|
| 25 |
+
if ctrl:
|
| 26 |
+
qc.x(ctrl)
|
| 27 |
+
qc.mcx(qr, flag)
|
| 28 |
+
if ctrl:
|
| 29 |
+
qc.x(ctrl)
|
| 30 |
+
apply_mask(qa, anc[0])
|
| 31 |
+
apply_mask(qb, anc[1])
|
| 32 |
+
|
| 33 |
+
# сложение p+q=N
|
| 34 |
+
def adder(a, b, carry):
|
| 35 |
+
for i in range(n):
|
| 36 |
+
qc.cx(a[i], b[i])
|
| 37 |
+
tgt = [b[i] for i in range(n)]
|
| 38 |
+
bits = [(N >> i) & 1 for i in range(n)]
|
| 39 |
+
for i, bit in enumerate(bits):
|
| 40 |
+
if not bit:
|
| 41 |
+
qc.x(tgt[i])
|
| 42 |
+
qc.mcx(tgt, carry)
|
| 43 |
+
for i, bit in enumerate(bits):
|
| 44 |
+
if not bit:
|
| 45 |
+
qc.x(tgt[i])
|
| 46 |
+
for i in reversed(range(n)):
|
| 47 |
+
qc.cx(a[i], b[i])
|
| 48 |
+
adder(qa, qb, anc[2])
|
| 49 |
+
|
| 50 |
+
# oracle
|
| 51 |
+
qc.mcx([anc[0], anc[1], anc[2]], anc[3])
|
| 52 |
+
qc.z(anc[3])
|
| 53 |
+
qc.mcx([anc[0], anc[1], anc[2]], anc[3])
|
| 54 |
+
|
| 55 |
+
# uncompute
|
| 56 |
+
adder(qa, qb, anc[2])
|
| 57 |
+
apply_mask(qa, anc[0])
|
| 58 |
+
apply_mask(qb, anc[1])
|
| 59 |
+
|
| 60 |
+
# diffusion
|
| 61 |
+
qc.h(qa + qb)
|
| 62 |
+
qc.x(qa + qb)
|
| 63 |
+
qc.h(qa[-1])
|
| 64 |
+
qc.mcx(qa[:-1], qa[-1])
|
| 65 |
+
qc.h(qa[-1])
|
| 66 |
+
qc.x(qa + qb)
|
| 67 |
+
qc.h(qa + qb)
|
| 68 |
+
|
| 69 |
+
qc.measure(qa + qb, list(range(2 * n)))
|
| 70 |
+
return qc
|
| 71 |
+
|
| 72 |
+
def run_quantum(N, shots=1024):
|
| 73 |
+
"""Запускает схему и возвращает найденную пару."""
|
| 74 |
+
qc = build_grover_circuit(N)
|
| 75 |
+
backend = Aer.get_backend('qasm_simulator')
|
| 76 |
+
counts = execute(qc, backend, shots=shots).result().get_counts()
|
| 77 |
+
valid = {k: v for k, v in counts.items()
|
| 78 |
+
if int(k[:len(k)//2], 2) + int(k[len(k)//2:], 2) == N}
|
| 79 |
+
if not valid:
|
| 80 |
+
return None
|
| 81 |
+
best = max(valid, key=valid.get)
|
| 82 |
+
p = int(best[:len(best)//2], 2)
|
| 83 |
+
q = int(best[len(best)//2:], 2)
|
| 84 |
+
return p, q
|