"""Demo 1: Bell state. Entangle two qubits and measure them.

usage: python bell.py            -> ideal simulator, then a simulated noisy machine
       python bell.py --hardware -> real IBM machine (needs a saved free Open Plan account)
"""
import sys
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator

qc = QuantumCircuit(2, 2)
qc.h(0)          # qubit 0 into superposition (0 and 1 at once)
qc.cx(0, 1)      # qubit 1 follows qubit 0: entangled
qc.measure([0, 1], [0, 1])
print(qc.draw("text"))

SHOTS = 4096

def show(title, counts):
    print(f"\n{title}")
    for k in sorted(counts):
        print(f"  {k}: {counts[k]:5d}  ({100 * counts[k] / SHOTS:5.1f}%)")

if "--hardware" in sys.argv:
    from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
    service = QiskitRuntimeService()  # uses the account saved once with save_account()
    backend = service.least_busy(operational=True, simulator=False)
    print("running on", backend.name)
    isa = transpile(qc, backend=backend, optimization_level=1)
    job = Sampler(mode=backend).run([isa], shots=SHOTS)
    print("job id", job.job_id())
    counts = job.result()[0].data.c.get_counts()
    show(f"REAL machine: {backend.name}", counts)
else:
    ideal = AerSimulator()
    counts = ideal.run(transpile(qc, ideal), shots=SHOTS).result().get_counts()
    show("Ideal simulator (perfect qubits)", counts)
