# 2026/04/17
# Joerg Gutschank
# full adder circuit can be found in
# Feynman,R. P. (1996). Feynman Lectures on Computation. Boulder, Colorado:
# Westview Press, p. 190, fig. 6.5
# and
# Stolze, J. and D. Suter (2008). Quantum Computing, A short Course from
# Theory to Experiment (2nd edition). Weinheim: Wiley-VHC, p. 80, fig. 6.3
import getpass
from qiskit import transpile
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler

# prompt for IBM Quantum API token
token = getpass.getpass("Input IBM Quantum API Token: ")

# prompt for IBM CRN instance
instance = getpass.getpass("Input CRN instance: ")

# connect to IBM Quantum
service = QiskitRuntimeService(
    channel="ibm_cloud",
    token=token,
    instance=instance
)

# get a backend (any operational hardware backend)
backend = service.least_busy(simulator=False, operational=True)

# create quantum circuit
qubit_register = QuantumRegister(4, 'q') 
bit_register = ClassicalRegister(2, 'c') 
qcirc = QuantumCircuit(qubit_register, bit_register)

# setting the input values:
# applying Pauli-X gate to set a=1
qcirc.x(qubit_register[0])
# applying Pauli-X gate to set b=1
qcirc.x(qubit_register[1])

# applying quantum gates:
# Toffoli gate
qcirc.ccx(qubit_register[0], qubit_register[1], qubit_register[3])
# CNOT
qcirc.cx(qubit_register[0], qubit_register[1])
# Toffoli
qcirc.ccx(qubit_register[1], qubit_register[2], qubit_register[3])
# CNOT
qcirc.cx(qubit_register[1], qubit_register[2])

# measure qubits 2 and 3 and put results into classical bits 0 and 1
# to get the result as a two digit binary number
qcirc.measure(qubit_register[2], bit_register[0])
qcirc.measure(qubit_register[3], bit_register[1])

# visualize circuit on a text terminal, i.e. print
# print(qcirc)

# optimize the circuit for the backend hardware
qcirc_transpiled = transpile(qcirc, backend)

# run with Sampler (V2 API)
sampler = Sampler(mode=backend)
# the first argument is a "list of circuits", so qcirc is "[0]" later
job = sampler.run([qcirc_transpiled], shots=1024) 

# get results
result = job.result()
counts = result[0].data.c.get_counts()
# result[0] is my qcirc
# data is an instance of qiskit.primitives.containers.DataBin
# "c" is the name of the classical register

# print job id and results
print(job.job_id())

print("1 + 1 was measured 1024 times. The results are displayed as a binary number followed by the absolute frequency of the respective result.")
print(counts)

