"""Offline 'real machine' demo: run the circuits on a noise model copied from a real IBM chip (ibm_kingston).
No account, no internet. The noise numbers are IBM's published calibration snapshot baked into the fake backend,
so this is a SIMULATION of that machine, not the machine itself. Say so on screen."""
import math
from fractions import Fraction
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import QFTGate
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime.fake_provider import FakeKingston

fake = FakeKingston()
noisy = AerSimulator.from_backend(fake)

def run(qc, shots):
    isa = transpile(qc, backend=fake, optimization_level=3, seed_transpiler=7)
    ops = isa.count_ops()
    twoq = sum(v for k, v in ops.items() if k in ("cz", "ecr", "cx"))
    print(f"  fitted to {fake.name}: depth {isa.depth()}, two-qubit gates {twoq}")
    return noisy.run(isa, shots=shots, seed_simulator=11).result().get_counts()

# Bell
bell = QuantumCircuit(2, 2); bell.h(0); bell.cx(0, 1); bell.measure([0, 1], [0, 1])
S = 4096
print("Bell state on the noisy copy of", fake.name)
c = run(bell, S)
for k in sorted(c): print(f"  {k}: {c[k]:5d} ({100*c[k]/S:5.1f}%)")
print(f"  'wrong' answers (01 or 10): {100*(c.get('01',0)+c.get('10',0))/S:.1f}%")

# Shor 15
N, A, T = 15, 2, 4
qc = QuantumCircuit(T + 4, T); qc.x(T); qc.h(range(T))
def cmul2(cq):
    qc.cswap(cq, T+2, T+3); qc.cswap(cq, T+1, T+2); qc.cswap(cq, T, T+1)
cmul2(0); cmul2(1); cmul2(1)
qc.append(QFTGate(T).inverse(), range(T)); qc.measure(range(T), range(T))
print("\nShor N=15, a=2 on the noisy copy of", fake.name)
c = run(qc, S)
good = {0, 4, 8, 12}
ok = sum(v for k, v in c.items() if int(k, 2) in good)
print(f"  shots landing on the correct peaks (0,4,8,12): {100*ok/S:.1f}%  (ideal 100%, random guessing 25%)")
for k, v in sorted(c.items(), key=lambda kv: -kv[1])[:8]:
    print(f"  {int(k,2):2d}/16: {100*v/S:5.1f}% {'(peak)' if int(k,2) in good else ''}")
best = max((k for k in c if int(k,2) != 0), key=lambda k: c[k])
r = Fraction(int(best,2), 16).limit_denominator(N).denominator
print(f"  strongest non-zero value {int(best,2)}/16 -> period {r}", "(correct, 4)" if r == 4 else "(WRONG: noise broke it)")
