QCut Subsequent Wires

QCut Subsequent Wires#

import QCut as ck
from QCut import cut_wire
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import Estimator
#define initial circuit

circuit = QuantumCircuit(4)
circuit.h(0)
circuit.cx(0,1)
circuit.cx(0,2)
circuit.cx(1,3)
circuit.cx(2,3)

circuit.measure_all()

circuit.draw("mpl")
c:\Users\nivalajo\AppData\Local\miniconda3\envs\testenv\lib\site-packages\qiskit\visualization\circuit\matplotlib.py:266: FutureWarning: The default matplotlib drawer scheme will be changed to "iqp" in a following release. To silence this warning, specify the current default explicitly as style="clifford", or the new default as style="iqp".
  self._style, def_font_ratio = load_style(self._style)
../_images/25b90d64f50305c41ed5c438a174707eb6b14b9830092fe2ee2c2b6ef8e4ec67.png
#insert cuts

cut_circuit = QuantumCircuit(6)
cut_circuit.h(0)
cut_circuit.cx(0,1)
cut_circuit.cx(0,2)
cut_circuit.append(cut_wire, [1,3])
cut_circuit.append(cut_wire, [2,4])
cut_circuit.cx(3,5)
cut_circuit.cx(4,5)

cut_circuit.draw("mpl")
../_images/94c8ee98b0689e78cb10cedcf3ab764a92cb4fdbab7bb5dbba6df7ec3ec8eec9.png
#find cut locations and separate into subcircuits

cut_locations, subcircuits = ck.get_locations_and_subcircuits(cut_circuit)
subcircuits[0].draw("mpl")
../_images/d8d758273c8a0007d42abb7d3e5e0b2a8301c97d9a9f5a3b39f0336c588829bd.png
subcircuits[1].draw("mpl")
../_images/99af98f997c031b2727b96b54907ab1aaccb2595bea926761ca0d84a9d30f557.png
#insert qpd operations to get the 8^n experiment circuits, where n is the number of cuts made
#also returns coefficients used for reconstructing the expectation values
#and locations of identity basis measurements that get added with post processing

experiment_circuits, coefficients, id_meas = ck.get_experiment_circuits(subcircuits, cut_locations)
#define backend

backend = AerSimulator()
#run experiment circuits
#run_experiments() also post processes the results

results = ck.run_experiments(experiment_circuits, cut_locations, id_meas, backend=backend, mitigate=False)
#define observables to calculate expectation values for
observables = [0,1,2,3, [0,2], [0,1,3]]

#get the exact expectation values with ideal simulator
expectation_values = ck.estimate_expectation_values(results, coefficients, cut_locations, observables)
#transform observables into a PauliList for the Qiskit Estimator
paulilist_observables = ck.get_pauli_list(observables, circuit.num_qubits)

#get the exact expectation values with ideal simulator
estimator = Estimator(run_options={"shots": None}, approximation=True)
exact_expvals = (
    estimator.run([circuit] * len(paulilist_observables),  # noqa: PD011
                  list(paulilist_observables)).result().values
)
import numpy as np

#set numpy print options
np.set_printoptions(formatter={"float": lambda x: f"{x:0.6f}"})
expectation_values = np.array(expectation_values).astype(float)

#compare QCut to Estimator
print(f"QCut circuit knitting expectation values:{np.array(expectation_values)}")
print(f"Exact expectation values with ideal simulator :{np.array(exact_expvals)}")
QCut circuit knitting expectation values:[1.002256 0.003686 -0.000859 -0.014038 0.003686 1.008985]
Exact expectation values with ideal simulator :[1.000000 0.000000 0.000000 0.000000 0.000000 1.000000]