QCut Basic Usage#
# Needs QCut[iqm] install otherwise use
# from qiskit_aer import AerSimulator
# as backend.
from iqm.qiskit_iqm import IQMFakeAdonis
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import CXGate
from qiskit.primitives import (
BackendEstimatorV2 as BackendEstimator,
)
from qiskit.primitives import (
StatevectorEstimator,
)
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer import AerSimulator
import QCut as ck
from QCut import cut, cutGate
/home/nivalajo/work/QCut/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
# define initial circuit
circuit = QuantumCircuit(5)
for qubit in range(5):
circuit.ry(0.4 + 0.3 * qubit, qubit)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.cx(2, 3)
circuit.cx(3, 4)
circuit.draw("mpl")
# insert cuts
marked_circuit = QuantumCircuit(5)
for qubit in range(5):
marked_circuit.ry(0.4 + 0.3 * qubit, qubit)
marked_circuit.cx(0, 1)
marked_circuit.append(**cutGate(CXGate(), 1, 2))
marked_circuit.cx(2, 3)
marked_circuit.append(cut(), [3])
marked_circuit.cx(3, 4)
marked_circuit.decompose(["CutGate"]).draw("mpl")
# extract cut locations and separate into subcircuits
cut_circuit = ck.get_locations_and_subcircuits(marked_circuit)
cut_circuit.subcircuits[0].draw("mpl")
cut_circuit.subcircuits[1].draw("mpl")
cut_circuit.subcircuits[2].draw("mpl")
# define backends
fake = IQMFakeAdonis()
sim = AerSimulator()
# transpile subcircuits for backend
transpiled = ck.transpile_subcircuits(cut_circuit, fake, optimization_level=3)
# generate experiment circuits
observables = SparsePauliOp(["IIIIZ", "IIIZI", "IIZII", "IIIZZ"])
cut_experiment = ck.get_experiment_circuits(transpiled, observables)
# run experiment circuits
# run_experiments() also post processes the results
results = ck.run_experiments(cut_experiment, backend=fake)
# get the approximated expectation values
expectation_values = ck.estimate_expectation_values(results)
obs = [ob.to_label() for ob in observables.paulis]
estimator = StatevectorEstimator()
exact_expvals = [
e.data.evs
for e in estimator.run([(x) for x in zip([circuit] * len(obs), obs)]).result()
]
tr = transpile(circuit, backend=fake)
tr_obs = observables.apply_layout(tr.layout)
tr_obs_separate = [SparsePauliOp(pauli.to_label()) for pauli in tr_obs.paulis]
fake_estimator = BackendEstimator(backend=fake)
exps = [
e.data.evs
for e in fake_estimator.run(
[(x) for x in zip([tr] * len(tr_obs_separate), tr_obs_separate)]
).result()
]
import numpy as np
np.set_printoptions(formatter={"float": lambda x: f"{x:0.6f}"})
print(f"QCut expectation values:{np.array(expectation_values)}")
print(f"Noisy expectation values with fake backend:{np.array(exps)}")
print(f"Exact expectation values with ideal simulator :{np.array(exact_expvals)}")
QCut expectation values:[0.808219 0.649909 0.285554 0.621305]
Noisy expectation values with fake backend:[0.865723 0.568848 0.307617 0.609375]
Exact expectation values with ideal simulator :[0.921061 0.704466 0.380625 0.764842]