Encontrar cortes automáticamente
Paso 1: Mapear
Crear un circuito y observables
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting
import numpy as np
from qiskit.circuit.random import random_circuit
from qiskit.quantum_info import SparsePauliOp
circuit = random_circuit(7, 6, max_operands=2, seed=1242)
observable = SparsePauliOp(["ZIIIIII", "IIIZIII", "IIIIIIZ"])
circuit.draw("mpl", scale=0.8)

Paso 2: Optimizar
Encontrar las ubicaciones de los cortes, dado un máximo de 4 Qubits por subcircuito. Este circuito puede separarse en dos realizando un único corte de hilo y cortando una CRZGate
from qiskit_addon_cutting.automated_cut_finding import (
find_cuts,
OptimizationParameters,
DeviceConstraints,
)
# Specify settings for the cut-finding optimizer
optimization_settings = OptimizationParameters(seed=111)
# Specify the size of the QPUs available
device_constraints = DeviceConstraints(qubits_per_subcircuit=4)
cut_circuit, metadata = find_cuts(circuit, optimization_settings, device_constraints)
print(
f'Found solution using {len(metadata["cuts"])} cuts with a sampling '
f'overhead of {metadata["sampling_overhead"]}.\n'
f'Lowest cost solution found: {metadata["minimum_reached"]}.'
)
for cut in metadata["cuts"]:
print(f"{cut[0]} at circuit instruction index {cut[1]}")
cut_circuit.draw("mpl", scale=0.8, fold=-1)
Found solution using 2 cuts with a sampling overhead of 127.06026169907257.
Lowest cost solution found: True.
Wire Cut at circuit instruction index 19
Gate Cut at circuit instruction index 28

Agregar ancillas para los cortes de hilo y expandir los observables para tener en cuenta los Qubits ancilla
from qiskit_addon_cutting import cut_wires, expand_observables
qc_w_ancilla = cut_wires(cut_circuit)
observables_expanded = expand_observables(observable.paulis, circuit, qc_w_ancilla)
qc_w_ancilla.draw("mpl", scale=0.8, fold=-1)

Particionar el circuito y los observables en subcircuitos y subobservables. Calcular el costo de muestreo incurrido por cortar estas Gates e hilos.
from qiskit_addon_cutting import partition_problem
partitioned_problem = partition_problem(
circuit=qc_w_ancilla, observables=observables_expanded
)
subcircuits = partitioned_problem.subcircuits
subobservables = partitioned_problem.subobservables
print(
f"Sampling overhead: {np.prod([basis.overhead for basis in partitioned_problem.bases])}"
)
Sampling overhead: 127.06026169907257
subobservables
{0: PauliList(['IIII', 'IZII', 'IIIZ']),
1: PauliList(['ZIII', 'IIII', 'IIII'])}
subcircuits[0].draw("mpl", style="iqp", scale=0.8)

subcircuits[1].draw("mpl", style="iqp", scale=0.8)

Generar los experimentos para ejecutar en el backend.
from qiskit_addon_cutting import generate_cutting_experiments
subexperiments, coefficients = generate_cutting_experiments(
circuits=subcircuits, observables=subobservables, num_samples=1_000
)
print(
f"{len(subexperiments[0]) + len(subexperiments[1])} total subexperiments to run on backend."
)
96 total subexperiments to run on backend.
Los pasos 3 y 4 de un patrón de Qiskit pueden realizarse a continuación como en los tutoriales anteriores.