Learning Home Catalog Composer
Learning
Home Catalog Composer
Tutorials

Improved Trotterized Time Evolution with Approximate Quantum Compilation

Estimated QPU usage: 5 minutes (tested on IBM Brisbane)

Background

This tutorial demonstrates how to implement Approximate Quantum Compilation using tensor networks (AQC-Tensor) with Qiskit to enhance quantum circuit performance. We apply AQC-Tensor within the context of a Trotterized time evolution to reduce circuit depth while maintaining simulation accuracy, following Qiskit’s framework for state preparation and optimization. In this notebook, you'll learn how to create a low-depth ansatz circuit from an initial Trotter circuit, optimize it with tensor networks, and prepare it for quantum hardware execution.

The primary objective is to simulate time evolution for a model Hamiltonian with a reduced circuit depth. This is achieved using the AQC-Tensor addon, qiskit-addon-aqc-tensor, which leverages tensor networks, specifically matrix product states (MPS), to compress and optimize the initial circuit. Through iterative adjustments, the compressed ansatz circuit maintains fidelity to the original circuit while staying feasible for near-term quantum hardware. More details can be found in the corresponding docs with a simple example to get started.

Approximate Quantum Compilation is particularly advantageous in quantum simulations that exceed hardware coherence times, as it allows complex simulations to be performed more efficiently. This tutorial will guide you through the AQC-Tensor workflow setup in Qiskit, covering initialization of a Hamiltonian, generation of Trotter circuits, and transpilation of the final optimized circuit for a target device.

Requirements

Before starting this tutorial, ensure that you have the following installed:

  • Qiskit SDK 1.0 or later, with visualization support (pip install 'qiskit[visualization]')
  • Qiskit Runtime (pip install qiskit-ibm-runtime) 0.22 or later
  • AQC-Tensor Qiskit addon (pip install 'qiskit-addon-aqc-tensor[aer,quimb-jax]')
  • rustworkx 0.15 or later (pip install rustworkx)

Part I. Small scale example

The first part of this tutorial uses a small-scale example with 10 sites to illustrate the process of mapping a quantum simulation problem to an executable quantum circuit. Here, we’ll explore the dynamics of a 10-site XXZ model, allowing us to build and optimize a manageable quantum circuit before scaling to larger systems.

The XXZ model is widely studied in physics for examining spin interactions and magnetic properties. We set up the Hamiltonian to have open boundary conditions with site-dependent interactions between neighboring sites along the chain.

Model Hamiltonian and observable

The Hamiltonian for our 10-site XXZ model is defined as:

H^XXZ=i=1L1Ji,(i+1)(XiX(i+1)+YiY(i+1)+2ZiZ(i+1)),\hat{\mathcal{H}}_{XXZ} = \sum_{i=1}^{L-1} J_{i,(i+1)}\left(X_i X_{(i+1)}+Y_i Y_{(i+1)}+ 2\cdot Z_i Z_{(i+1)} \right) \, ,

where Ji,(i+1)J_{i,(i+1)} is a random coefficient corresponding to edge (i,i+1)(i, i+1) and L=10L=10 is the number of sites.

By simulating the evolution of this system with reduced circuit depth, we can gain insights into using AQC-Tensor to compress and optimize circuits.

Set up the Hamiltonian and Observable

Before, we map our problem, we will need to set up the coupling map, Hamiltonian, and observable for the 10-site XXZ model.

Copy to clipboard

Output:

Hamiltonian: SparsePauliOp(['IIIIIIIIII', 'IIIIIIIIXX', 'IIIIIIIIYY', 'IIIIIIIIZZ', 'IIIIIIXXII', 'IIIIIIYYII', 'IIIIIIZZII', 'IIIIXXIIII', 'IIIIYYIIII', 'IIIIZZIIII', 'IIXXIIIIII', 'IIYYIIIIII', 'IIZZIIIIII', 'XXIIIIIIII', 'YYIIIIIIII', 'ZZIIIIIIII', 'IIIIIIIXXI', 'IIIIIIIYYI', 'IIIIIIIZZI', 'IIIIIXXIII', 'IIIIIYYIII', 'IIIIIZZIII', 'IIIXXIIIII', 'IIIYYIIIII', 'IIIZZIIIII', 'IXXIIIIIII', 'IYYIIIIIII', 'IZZIIIIIII'],
              coeffs=[1.        +0.j, 0.52440675+0.j, 0.52440675+0.j, 1.0488135 +0.j,
 0.60759468+0.j, 0.60759468+0.j, 1.21518937+0.j, 0.55138169+0.j,
 0.55138169+0.j, 1.10276338+0.j, 0.52244159+0.j, 0.52244159+0.j,
 1.04488318+0.j, 0.4618274 +0.j, 0.4618274 +0.j, 0.9236548 +0.j,
 0.57294706+0.j, 0.57294706+0.j, 1.14589411+0.j, 0.46879361+0.j,
 0.46879361+0.j, 0.93758721+0.j, 0.6958865 +0.j, 0.6958865 +0.j,
 1.391773  +0.j, 0.73183138+0.j, 0.73183138+0.j, 1.46366276+0.j])
Observable: SparsePauliOp(['IIIIZZIIII'],
              coeffs=[1.+0.j])

With the Hamiltonian defined, we can proceed to construct the initial state.

Copy to clipboard

No output produced

Step 1. Map classical inputs to a quantum problem

Now that we have constructed the Hamiltonian, defining the spin-spin interactions and external magnetic fields that characterize the system, we follow three main steps in the AQC-Tensor workflow:

  1. Generate the optimized AQC circuit: Using Trotterization, we approximate the initial evolution, which is then compressed to reduce circuit depth.
  2. Create the remaining time evolution circuit: Capture the evolution for the remaining time beyond the initial segment.
  3. Combine the circuits: Merge the optimized AQC circuit with the remaining evolution circuit into a complete time-evolution circuit ready for execution.

This approach creates a low-depth ansatz for the target evolution, supporting efficient simulation within near-term quantum hardware constraints.

Determine the Portion of Time Evolution to Simulate Classically

Our goal is to simulate the time evolution of the model Hamiltonian defined earlier using Trotter evolution. To make this process efficient for quantum hardware, we split the evolution into two segments:

  • Initial Segment: This initial portion of the evolution, from ti=0.0t_i = 0.0 to tf=0.2t_f = 0.2, is simulable with MPS and can be efficiently “compiled” using AQC-Tensor. By using the AQC-Tensor addon, we generate a compressed circuit for this segment, referred to as the aqc_target_circuit. Because this segment will be simulated on a tensor-network simulator, we can afford to use a higher number of Trotter layers without impacting hardware resources significantly. We set aqc_target_num_trotter_steps = 32 for this segment.

  • Subsequent Segment: This remaining portion of the evolution, from t=0.2t = 0.2 to t=0.4t = 0.4, will be executed on quantum hardware, referred to as the subsequent_circuit. Given hardware limitations, we aim to use as few Trotter layers as possible to maintain a manageable circuit depth. For this segment, we use subsequent_num_trotter_steps = 3.

Choosing the split time

We choose t=0.2t = 0.2 as the split time to balance classical simulability with hardware feasibility. Early in the evolution, entanglement in the XXZ model remains low enough for classical methods like MPS to approximate accurately.

When choosing a split time, a good guideline is to select a point where entanglement is still manageable classically but captures enough of the evolution to simplify the hardware-executed portion. Trial and error may be needed to find the best balance for different Hamiltonians.

Copy to clipboard

No output produced

Copy to clipboard

Output:

To enable a meaningful comparison, we will generate two additional circuits:

  • AQC Comparison Circuit: This circuit evolves up to aqc_evolution_time but uses the same Trotter step duration as the subsequent_circuit. It serves as a comparison to the aqc_target_circuit, showing the evolution we would observe without using an increased number of Trotter steps. We will refer to this circuit as the aqc_comparison_circuit.

  • Reference Circuit: This circuit is used as a baseline to obtain the exact result. It simulates the full evolution using tensor networks to calculate the exact outcome, providing a reference for evaluating the effectiveness of AQC-Tensor. We will refer to this circuit as the reference_circuit.

Copy to clipboard

Output:

Number of Trotter steps for comparison: 3

Copy to clipboard

No output produced

Generate an ansatz and initial parameteres from a Trotter circuit with fewer steps

Now that we have constructed our four circuits, let's proceed with the AQC-Tensor workflow. First, we construct a “good” circuit that has the same evolution time as the target circuit, but with fewer Trotter steps (and thus fewer layers).

Then we pass this “good” circuit to AQC-Tensor’s generate_ansatz_from_circuit function. This function analyzes the two-qubit connectivity of the circuit and returns two things:

  1. A general, parametrized ansatz circuit with the same two-qubit connectivity as the input circuit.
  2. Parameters that, when plugged into the ansatz, yield the input (good) circuit.

Soon we will take these parameters and iteratively adjust them to bring the ansatz circuit as close as possible to the target MPS.

Copy to clipboard

Output:

Copy to clipboard

Output:

AQC Comparison circuit: depth 36
Target circuit:         depth 385
Ansatz circuit:         depth 7, with 156 parameters

Choose Settings for Tensor Network Simulation

Here, we use Quimb's matrix-product state circuit simulator, along with jax for providing the gradient.

Copy to clipboard

Output:

/Users/henryzou/.venvs/learning-aqc-1/lib/python3.11/site-packages/cotengra/hyperoptimizers/hyper.py:33: UserWarning: Couldn't import `kahypar` - skipping from default hyper optimizer and using basic `labels` method instead.
  warnings.warn(

Next, we build a MPS representation of the target state that will be approximated using AQC-Tensor. This representation enables efficient handling of entanglement, providing a compact description of the quantum state for further optimization.

Copy to clipboard

Output:

Target MPS maximum bond dimension: 5
Reference MPS maximum bond dimension: 7

Note that, by choosing a larger number of Trotter steps for the target state, we have effectively reduced its Trotter error compared to the initial circuit. We can evaluate the fidelity (ψ1ψ22|\langle \psi_1 | \psi_2 \rangle|^2) between the state prepared by the initial circuit and the target state to quantify this difference.

Copy to clipboard

Output:

Starting fidelity: 0.9982464959067983

Optimize the parameters of the Ansatz using MPS calculations

In this step, we optimize the ansatz parameters by minimizing a simple cost function, OneMinusFidelity, using the L-BFGS optimizer from SciPy. We select a stopping criterion for the fidelity that ensures it surpasses the fidelity of the initial circuit without AQC-Tensor. Once this threshold is reached, the compressed circuit will exhibit both lower Trotter error and reduced depth compared to the original circuit. With additional CPU time, further optimization can continue to increase fidelity.

Copy to clipboard

Output:

2024-11-12 12:25:24.948924 Intermediate result: Fidelity 0.99952846
2024-11-12 12:25:24.950982 Intermediate result: Fidelity 0.99958508
2024-11-12 12:25:24.952984 Intermediate result: Fidelity 0.99959974
2024-11-12 12:25:24.954757 Intermediate result: Fidelity 0.99960963
2024-11-12 12:25:24.956520 Intermediate result: Fidelity 0.99962441
2024-11-12 12:25:24.958425 Intermediate result: Fidelity 0.99964395
2024-11-12 12:25:24.960344 Intermediate result: Fidelity 0.99968078
2024-11-12 12:25:24.964133 Intermediate result: Fidelity 0.99970510
2024-11-12 12:25:24.966034 Intermediate result: Fidelity 0.99973847
2024-11-12 12:25:24.967835 Intermediate result: Fidelity 0.99975444
2024-11-12 12:25:24.970126 Intermediate result: Fidelity 0.99976553
2024-11-12 12:25:24.972458 Intermediate result: Fidelity 0.99977638
2024-11-12 12:25:24.974268 Intermediate result: Fidelity 0.99978698
2024-11-12 12:25:24.976094 Intermediate result: Fidelity 0.99980260
2024-11-12 12:25:24.978092 Intermediate result: Fidelity 0.99981571
2024-11-12 12:25:24.979911 Intermediate result: Fidelity 0.99982835
2024-11-12 12:25:24.981648 Intermediate result: Fidelity 0.99985815
2024-11-12 12:25:24.983526 Intermediate result: Fidelity 0.99988461
2024-11-12 12:25:24.985374 Intermediate result: Fidelity 0.99991644
2024-11-12 12:25:24.987610 Intermediate result: Fidelity 0.99993205
2024-11-12 12:25:24.989500 Intermediate result: Fidelity 0.99993885
2024-11-12 12:25:24.991338 Intermediate result: Fidelity 0.99994314
2024-11-12 12:25:24.993187 Intermediate result: Fidelity 0.99994719
2024-11-12 12:25:24.995118 Intermediate result: Fidelity 0.99994767
2024-11-12 12:25:24.996856 Intermediate result: Fidelity 0.99994946
2024-11-12 12:25:24.998605 Intermediate result: Fidelity 0.99994969
2024-11-12 12:25:25.018112 Intermediate result: Fidelity 0.99995077
2024-11-12 12:25:25.054920 Intermediate result: Fidelity 0.99995077
Done after 28 iterations.

Copy to clipboard

Output:

Final parameters: [-7.853981112055085, 1.570797507204238, 1.5707979087614174, -1.5707952787358048, 1.5707970310387784, 1.57079522775084, -1.5707961623743325, 1.5707967336614768, -1.570796611087232, -1.5707962145893895, 1.570796271703914, 4.712387929822417, -7.853982402563732, 1.5707989095671329, 1.5707977385737681, -1.5707940741962412, 1.570797314941096, 1.5707976541580273, -1.5707933229425972, 1.5707961058359217, -1.5707958413362826, -1.570795089655074, 1.5707976787480016, 4.712387191305782, -1.5707946890053843, 1.5707953450204197, -1.5707992793567143, -1.570796265954742, 1.5707947949425147, 4.712390321753913, 0.10487779951457206, 0.0669304855960779, -0.06692189478829999, -3.1415924255843914, 2.609868292582522, -1.1234832406759191e-07, -3.141591645153891, 0.9422894740075248, -2.1314672866019113e-07, 0.12151543373326927, 0.07942604019639618, -0.07943027847071561, -3.1415916298284436, 0.9741837915058525, 3.141591718418538, -1.1550376470679338e-06, 1.7897358800047758, 2.1195414839490685e-07, 0.19827255014703224, 0.11111512228210345, -0.11111514517077194, -2.2302169473256597e-07, 2.7173788427136363, 9.561920752269582e-07, -6.283185129165788, 0.40877973580905574, 3.1415917546673535, 0.13629495288004723, 0.038867089321180257, -0.03886603318167364, -1.5707942733242137, 1.5707946638701127, 1.0630998538585854, 1.5707947146148329, 1.5707954588319601, 1.0520260677238398, 0.11027729934543476, 0.07268290174271413, -0.07268639372562713, -9.664819288558604e-07, 1.841292046519761, 3.1415919636313694, 4.2430441661855765e-07, 1.9345295648598817, 3.1415928191472395, 0.11557365468488236, 0.09096496524200588, -0.09096419366930858, -3.141592980011209, 1.2363050992375593, 3.1804242299148496e-06, -9.095246762983908e-07, 3.166671973546177, -3.141591750951704, 0.09954182546440704, 0.04367412734331154, -0.043673428501682245, -4.712388740372665, 1.570795748520369, 4.184733645513607, -1.5707981574509364, 1.5707979112780923, -2.078714830215991, 0.1044938990848301, 0.07318796479117047, -0.07319479949587492, 2.7415965255446625e-07, 1.8712578780657543, 1.2891480920146033e-06, -3.141593686429897, 0.9452718216181584, -3.1415925948983734, 0.18919849026531882, 0.13574198824511408, -0.13574272697294087, -5.265035390574029e-07, 0.6191958289065201, 3.1415920974753946, -3.141591514332686, 0.6767539511486921, -3.536324242889494e-08, 0.08067562127055841, 0.038033682484482356, -0.038033494483792896, 1.570797747804326, 1.5707963109987413, -0.26947560538814497, -1.570797362098685, 1.5707973946644989, 6.076755706319791, 0.09236809147314735, 0.06037868942412851, -0.06037906723998776, -1.8445071708025625e-06, 0.9015846574042147, -8.578882863484991e-08, -2.313335233538696e-06, 2.1762585921566036, 3.141592702395848, 0.2332832689190369, 0.1432842460545737, -0.1432825969738356, -3.1415926982857867, 0.28940741311327817, 6.88725251354497e-07, -3.1415928946540994, 3.0855410552918903, 6.283185618988811, 0.0712161092952286, 0.031960083799565005, -0.03196042051056538, -4.712390577979708, 1.5707957554800462, -0.4100513572034228, -1.5707961302317412, 1.5707937528370368, -0.3982258985444103, 0.13634584836392488, 0.03291045667886095, -0.03291130310925488, 1.5707971288952578, 1.5708007360135277, 2.5149302025734674, -1.5707968374863968, 1.5707953797097216, 2.514010630246316]

At this point, it is only necessary to find the final parameters to the ansatz circuit. We can then merge the optimized AQC circuit with the remaining evolution circuit to create a complete time-evolution circuit for execution on quantum hardware.

Copy to clipboard

Output: