Quick start

This guide demonstrates a minimal working example of the qiskit-addon-aqc-tensor package. We use AQC-Tensor to compress a deep Trotter circuit into a shallower parametrized ansatz that approximates the same time-evolved state. To see examples of how to build realistic workflows with this tool and execute on quantum hardware, check out the tutorials on the IBM Quantum Platform (Tutorial 1).

Prepare inputs for AQC-Tensor

AQC-Tensor takes as input a deep target circuit (simulated as a tensor network) and a shallower circuit from which to derive the ansatz structure.

We define a 10-site Ising Hamiltonian and generate both circuits from it.

[1]:
from qiskit.synthesis import SuzukiTrotter
from qiskit.transpiler import CouplingMap
from qiskit_addon_utils.problem_generators import (
    generate_time_evolution_circuit,
    generate_xyz_hamiltonian,
)

coupling_map = CouplingMap.from_heavy_hex(3, bidirectional=False)
reduced_coupling_map = coupling_map.reduce([0, 13, 1, 14, 10, 16, 4, 15, 3, 9])

hamiltonian = generate_xyz_hamiltonian(
    reduced_coupling_map,
    coupling_constants=(0.0, 0.0, 1.0),
    ext_magnetic_field=(0.4, 0.0, 0.0),
)

evolution_time = 4.0

# Deep target circuit (many Trotter steps)
target_circuit = generate_time_evolution_circuit(
    hamiltonian,
    synthesis=SuzukiTrotter(reps=45),
    time=evolution_time,
)

# Shallow circuit (fewer Trotter steps) to define ansatz structure
good_circuit = generate_time_evolution_circuit(
    hamiltonian,
    synthesis=SuzukiTrotter(reps=5),
    time=evolution_time,
)
/tmp/ipykernel_3406/963505141.py:1: DeprecationWarning: Using Qiskit with Python 3.9 is deprecated as of the 2.1.0 release. Support for running Qiskit with Python 3.9 will be removed in the 2.3.0 release, which coincides with when Python 3.9 goes end of life.
  from qiskit.synthesis import SuzukiTrotter

Compress with AQC-Tensor

We simulate the target circuit as a matrix-product state (MPS), generate a parametrized ansatz from the shallow circuit, and optimize its parameters to maximize fidelity with the target state.

[2]:
from functools import partial

import quimb.tensor
from scipy.optimize import minimize

from qiskit_addon_aqc_tensor import generate_ansatz_from_circuit
from qiskit_addon_aqc_tensor.objective import MaximizeStateFidelity
from qiskit_addon_aqc_tensor.simulation import tensornetwork_from_circuit
from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator

# Configure the MPS simulator
simulator_settings = QuimbSimulator(
    partial(quimb.tensor.CircuitMPS, max_bond=100, cutoff=1e-8),
    autodiff_backend="jax",
)

# Simulate target circuit as MPS
target_mps = tensornetwork_from_circuit(target_circuit, simulator_settings)

# Generate ansatz and initial parameters from the shallow circuit
ansatz, initial_parameters = generate_ansatz_from_circuit(good_circuit, qubits_initially_zero=True)
print(f"Target circuit depth: {target_circuit.depth()}")
print(f"Ansatz circuit depth: {ansatz.depth()}, with {len(initial_parameters)} parameters")

# Optimize ansatz parameters against the target MPS
objective = MaximizeStateFidelity(target_mps, ansatz, simulator_settings)

result = minimize(
    objective.loss_function,
    initial_parameters,
    method="L-BFGS-B",
    jac=True,
    options={"maxiter": 100},
)

print(f"\nFinal fidelity: {1 - result.fun:.8f}")
print(f"Compressed circuit depth: {ansatz.assign_parameters(result.x).depth()}")
Target circuit depth: 270
Ansatz circuit depth: 23, with 515 parameters

Final fidelity: 0.99987901
Compressed circuit depth: 23
Target circuit depth: 270
Ansatz circuit depth: 23, with 515 parameters

Final fidelity: 0.99971010
Compressed circuit depth: 23

Next steps

Check out the tutorials on the IBM Quantum Platform to see how to build realistic workflows with AQC-Tensor (Tutorial 1).