diff --git a/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb b/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb
index 9ea79755449..eec2b0c03e4 100644
--- a/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb
+++ b/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb
@@ -2,52 +2,100 @@
"cells": [
{
"cell_type": "markdown",
- "id": "2c991cef-110a-455a-8741-52d5e20d3196",
+ "id": "dd701ecc",
"metadata": {},
"source": [
"---\n",
"title: Approximate quantum compilation for time evolution circuits\n",
- "description: This tutorial demonstrates how to implement AQC-Tensor with Qiskit to enhance quantum circuit performance\n",
+ "description: Learn how to use AQC-Tensor to compress Trotterized time-evolution circuits for efficient execution on quantum hardware.\n",
"---\n",
"\n",
- "\n",
- "{/* cspell:ignore circo */}\n",
+ "{/* cspell:ignore circo Néel */}\n",
"\n",
"# Approximate quantum compilation for time evolution circuits\n",
- "*Usage estimate: Five minutes on an Eagle processor (NOTE: This is an estimate only. Your runtime might vary.)*"
+ "\n",
+ "*Usage estimate: 15 seconds on a Heron processor (NOTE: This is an estimate only. Your runtime might vary.)*"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12608301",
+ "metadata": {},
+ "source": [
+ "## Learning outcomes\n",
+ "After completing this tutorial, you can expect to understand the following information:\n",
+ "- How to use the AQC-Tensor Qiskit addon to compress deep Trotter circuits into shallow ansatz circuits\n",
+ "- How to generate a parametrized ansatz from a Trotter circuit and optimize its parameters using tensor network (MPS) methods\n",
+ "- How to evaluate the fidelity of a compressed circuit against the target evolution and run it on quantum hardware"
]
},
{
"cell_type": "markdown",
- "id": "93895788-7d38-4cc7-a7e9-ba97c34966af",
+ "id": "c3c5992a",
+ "metadata": {},
+ "source": [
+ "## Prerequisites\n",
+ "It is recommended that you familiarize yourself with these topics:\n",
+ "- [Basics of quantum circuits](/learning/courses/basics-of-quantum-information)\n",
+ "- [Hamiltonian simulation and Trotterization](/learning/courses/utility-scale-quantum-computing/quantum-simulation)\n",
+ "- [Introduction to primitives](/docs/guides/primitives)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "714adc39",
"metadata": {},
"source": [
"## Background\n",
"\n",
- "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 the Qiskit framework for state preparation and optimization. You will 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.\n",
+ "This tutorial demonstrates how to implement **Approximate Quantum Compilation** using tensor networks (AQC-Tensor) with Qiskit to enhance quantum circuit performance. AQC-Tensor compresses deep Trotter circuits into shallower, more hardware-friendly circuits while preserving simulation accuracy.\n",
+ "\n",
+ "### How AQC-Tensor works\n",
+ "\n",
+ "Consider simulating a Hamiltonian $H$ for total time $t$ using $k$ Trotter steps. The full Trotter circuit is:\n",
"\n",
- "The primary objective is to simulate time evolution for a model Hamiltonian with a reduced circuit depth. This is achieved using the **AQC-Tensor** Qiskit addon, [qiskit-addon-aqc-tensor](https://github.com/Qiskit/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. See the [documentation](https://qiskit.github.io/qiskit-addon-aqc-tensor/) for more information.\n",
+ "$$\n",
+ "U_{\\text{full}} = \\left[U_{\\text{Trotter}}(t/k)\\right]^k\n",
+ "$$\n",
+ "\n",
+ "A naive approach uses few Trotter steps to keep circuit depth manageable, but this introduces significant Trotter error. AQC-Tensor resolves this tension by separating accuracy from depth:\n",
+ "\n",
+ "1. **Target circuit (high accuracy, deep):** Construct a Trotter circuit with many steps—say, $10k$—for the same evolution time. This circuit has far less Trotter error, but is too deep for hardware. Because it is only simulated classically as a matrix product state (MPS), depth is not a concern.\n",
+ "\n",
+ "2. **Ansatz circuit (low depth, parametrized):** Define a parametrized circuit $V(\\theta)$ with the same structure as a single-step Trotter circuit. Initialize it so that $V(\\theta_{\\text{init}}) = U_{\\text{Trotter}}(t/k)$, then iteratively optimize $\\theta$ so that $V(\\theta)$ reproduces the high-accuracy target state as closely as possible.\n",
+ "\n",
+ "The result is a circuit that retains the depth of a single Trotter step but achieves the accuracy of many, making it feasible for near-term quantum hardware.\n",
+ "\n",
+ "### When to use AQC-Tensor\n",
+ "\n",
+ "AQC-Tensor is most effective when:\n",
"\n",
- "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 guides 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."
+ "- **Circuit depth exceeds hardware coherence times.** If a Trotter simulation requires more Trotter steps than the device can support, AQC-Tensor can compress the evolution into a shallower circuit.\n",
+ "- **Entanglement remains classically tractable.** The total entanglement in a time-evolved state depends primarily on the evolution time $t$, not the number of Trotter steps $k$. This means a target circuit with $10k$ steps is typically no harder to represent as an MPS than one with $k$ steps, as long as $t$ is short enough for bond dimensions to stay manageable.\n",
+ "- **A natural ansatz exists.** Because the ansatz mirrors the structure of a Trotter circuit, it provides a physically motivated starting point with well-defined initial parameters, avoiding the convergence issues that can plague arbitrary variational ansatze.\n",
+ "\n",
+ "This approach contrasts with generic circuit compression: rather than trying to approximate an arbitrary unitary with fewer gates, AQC-Tensor keeps the same gate structure and optimizes its parameters to reduce Trotter error. See the [AQC-Tensor documentation](https://qiskit.github.io/qiskit-addon-aqc-tensor/) for more information.\n",
+ "\n",
+ "This tutorial guides you through the full state-preparation AQC-Tensor workflow: defining a Hamiltonian, generating Trotter circuits, compressing them via tensor-network optimization, and executing the result on IBM Quantum® hardware."
]
},
{
"cell_type": "markdown",
- "id": "b1b8f238-0dab-42c5-b658-779f3ff178a0",
+ "id": "f8a05291",
"metadata": {},
"source": [
"## Requirements\n",
"\n",
"Before starting this tutorial, ensure that you have the following installed:\n",
"\n",
- "* Qiskit SDK v1.0 or later, with [visualization](/docs/api/qiskit/visualization) support\n",
+ "* Qiskit SDK v2.0 or later, with [visualization](https://quantum.cloud.ibm.com/docs/en/api/qiskit/visualization) support\n",
"* Qiskit Runtime v0.22 or later (`pip install qiskit-ibm-runtime`)\n",
"* AQC-Tensor Qiskit addon (`pip install 'qiskit-addon-aqc-tensor[aer,quimb-jax]'`)"
]
},
{
"cell_type": "markdown",
- "id": "f0723f2d-e0ba-4fe9-a742-1891b7b45459",
+ "id": "f9410d21",
"metadata": {},
"source": [
"## Setup"
@@ -55,8 +103,8 @@
},
{
"cell_type": "code",
- "execution_count": 28,
- "id": "ccdcdca2-4e77-4696-b0ff-45d13dbc6ac3",
+ "execution_count": 1,
+ "id": "ecdb92e0",
"metadata": {},
"outputs": [],
"source": [
@@ -65,6 +113,7 @@
"import datetime\n",
"import matplotlib.pyplot as plt\n",
"\n",
+ "from scipy.linalg import expm\n",
"from scipy.optimize import OptimizeResult, minimize\n",
"\n",
"from qiskit.quantum_info import SparsePauliOp, Pauli\n",
@@ -86,47 +135,54 @@
"\n",
"from qiskit_ibm_runtime import QiskitRuntimeService\n",
"from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
+ "from qiskit_ibm_runtime.fake_provider import FakeKyiv\n",
"\n",
"from rustworkx.visualization import graphviz_draw"
]
},
{
"cell_type": "markdown",
- "id": "39bc4470-f7f8-4550-83a7-a22167024000",
+ "id": "6473f943",
"metadata": {},
"source": [
- "## Part I. Small-scale example\n",
+ "## Small-scale simulator example\n",
"\n",
- "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.\n",
+ "This section uses a 10-site system to illustrate the AQC-Tensor workflow step by step. We simulate the dynamics of a 10-site XXZ spin chain, a widely studied model for examining spin interactions and magnetic properties.\n",
"\n",
- "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.\n",
+ "The Hamiltonian is as follows:\n",
"\n",
- "### Model Hamiltonian and observable\n",
- "\n",
- "The Hamiltonian for our 10-site XXZ model is defined as:\n",
"$$\n",
"\\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) \\, ,\n",
"$$\n",
"\n",
- "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$, and $L=10$ is the number of sites.\n",
- "\n",
- "By simulating the evolution of this system with reduced circuit depth, we can gain insights into using AQC-Tensor to compress and optimize circuits."
+ "where $J_{i,(i+1)}$ is a random coefficient for edge $(i, i+1)$ and $L=10$."
]
},
{
"cell_type": "markdown",
- "id": "89f22428-d4d8-49e7-a1c5-39197dc58330",
+ "id": "6520161e",
"metadata": {},
"source": [
- "#### Set up the Hamiltonian and observable\n",
+ "### Step 1: Map classical inputs to a quantum problem\n",
"\n",
- "Before we map our problem, we need to set up the coupling map, Hamiltonian, and observable for the 10-site XXZ model."
+ "In this step, we:\n",
+ "1. Define the Hamiltonian, observable, and initial state.\n",
+ "2. Compute the exact expectation value classically for later comparison.\n",
+ "3. Generate a high-accuracy Trotter circuit (the AQC target) and compress it into a low-depth ansatz using AQC-Tensor."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bbeb5729",
+ "metadata": {},
+ "source": [
+ "#### Set up the Hamiltonian, observable, and initial state"
]
},
{
"cell_type": "code",
"execution_count": 2,
- "id": "1ea0e102-23d5-4e6e-8ef8-e82843452b19",
+ "id": "527dbada",
"metadata": {},
"outputs": [
{
@@ -148,7 +204,7 @@
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 2,
@@ -157,12 +213,11 @@
}
],
"source": [
- "# L is the number of sites, also the length of the 1D spin chain\n",
+ "# L is the number of sites in the 1D spin chain\n",
"L = 10\n",
"\n",
"# Generate the coupling map\n",
"edge_list = [(i - 1, i) for i in range(1, L)]\n",
- "# Generate an edge-coloring so we can make hw-efficient circuits\n",
"even_edges = edge_list[::2]\n",
"odd_edges = edge_list[1::2]\n",
"coupling_map = CouplingMap(edge_list)\n",
@@ -186,6 +241,12 @@
" [(\"ZZ\", (L // 2 - 1, L // 2), 1.0)], num_qubits=L\n",
")\n",
"\n",
+ "# Generate an initial Néel state |1010101010⟩\n",
+ "initial_state_circuit = QuantumCircuit(L)\n",
+ "for i in range(L):\n",
+ " if i % 2:\n",
+ " initial_state_circuit.x(i)\n",
+ "\n",
"print(\"Hamiltonian:\", hamiltonian)\n",
"print(\"Observable:\", observable)\n",
"graphviz_draw(coupling_map.graph, method=\"circo\")"
@@ -193,74 +254,79 @@
},
{
"cell_type": "markdown",
- "id": "e6cd54e3-6a9c-4cdc-8493-d612e930dcee",
+ "id": "54ad6963",
"metadata": {},
"source": [
- "With the Hamiltonian defined, we can proceed to construct the initial state."
+ "#### Compute the exact expectation value\n",
+ "\n",
+ "For a system of this size, we can compute the exact time-evolved expectation value directly using matrix exponentiation. This serves as our ground truth for evaluating the AQC circuit's accuracy."
]
},
{
"cell_type": "code",
"execution_count": 3,
- "id": "71252a74-e7bf-4003-a1fd-8f7659195f9a",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Generate an initial state\n",
- "initial_state = QuantumCircuit(L)\n",
- "for i in range(L):\n",
- " if i % 2:\n",
- " initial_state.x(i)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5fb34a14-d197-4ac4-a224-5be2cec06a2e",
+ "id": "20c70651",
"metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "AQC evolution time: 0.2\n",
+ "Subsequent evolution time: 0.066667\n",
+ "Total evolution time: 0.266667\n",
+ "Exact expectation value: -0.700899\n"
+ ]
+ }
+ ],
"source": [
- "### Step 1: Map classical inputs to a quantum problem\n",
+ "aqc_evolution_time = 0.2\n",
+ "\n",
+ "# Each baseline Trotter step covers dt = aqc_evolution_time / 3\n",
+ "# The subsequent (uncompressed) step covers 1 additional dt\n",
+ "subsequent_evolution_time = aqc_evolution_time / 3\n",
+ "total_evolution_time = aqc_evolution_time + subsequent_evolution_time\n",
+ "\n",
+ "# Compute exact expectation value via matrix exponentiation\n",
+ "H_matrix = hamiltonian.to_matrix()\n",
+ "U_exact = expm(-1j * H_matrix * total_evolution_time)\n",
"\n",
- "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:\n",
+ "# Build the initial state vector (Néel state)\n",
+ "initial_state_vec = np.zeros(2**L)\n",
+ "state_idx = sum(2**i for i in range(L) if i % 2)\n",
+ "initial_state_vec[state_idx] = 1.0\n",
"\n",
- "1. **Generate the optimized AQC circuit**: Using Trotterization, we approximate the initial evolution, which is then compressed to reduce circuit depth.\n",
- "2. **Create the remaining time evolution circuit**: Capture the evolution for the remaining time beyond the initial segment.\n",
- "3. **Combine the circuits**: Merge the optimized AQC circuit with the remaining evolution circuit into a complete time-evolution circuit ready for execution.\n",
+ "# Evolve and compute expectation value\n",
+ "evolved_state = U_exact @ initial_state_vec\n",
+ "obs_matrix = observable.to_matrix()\n",
+ "exact_expval = (evolved_state.conj() @ obs_matrix @ evolved_state).real\n",
"\n",
- "This approach creates a low-depth ansatz for the target evolution, supporting efficient simulation within near-term quantum hardware constraints."
+ "print(f\"AQC evolution time: {aqc_evolution_time}\")\n",
+ "print(f\"Subsequent evolution time: {subsequent_evolution_time:.6f}\")\n",
+ "print(f\"Total evolution time: {total_evolution_time:.6f}\")\n",
+ "print(f\"Exact expectation value: {exact_expval:.6f}\")"
]
},
{
"cell_type": "markdown",
- "id": "7c5f2a2e-179c-4e62-a32f-5bc202f89701",
+ "id": "a93c047c",
"metadata": {},
"source": [
- "#### Determine the portion of time evolution to simulate classically\n",
- "\n",
- "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:\n",
- "\n",
- "- **Initial Segment**: This initial portion of the evolution, from $ t_i = 0.0 $ to $ t_f = 0.2 $, is simulable with MPS and can be efficiently “compiled” using AQC-Tensor. By using the [AQC-Tensor Qiskit addon](https://github.com/Qiskit/qiskit-addon-aqc-tensor), 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.\n",
- "\n",
- "- **Subsequent Segment**: This remaining portion of the evolution, from $ t = 0.2 $ to $ t = 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`.\n",
- "\n",
+ "#### Generate the AQC target circuit\n",
"\n",
- "#### Choose the split time\n",
- "We choose $t = 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.\n",
- "\n",
- "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."
+ "We now construct the Trotter circuit that will serve as the AQC target. This circuit uses many Trotter steps (32) for high accuracy. Because it will only be simulated classically as an MPS—not executed on hardware—the large depth is not a concern."
]
},
{
"cell_type": "code",
"execution_count": 4,
- "id": "199d4e7e-02b2-4da8-b567-8195fb9de536",
+ "id": "db66bf00",
"metadata": {},
"outputs": [],
"source": [
- "# Generate the AQC target circuit (initial segment)\n",
- "aqc_evolution_time = 0.2\n",
"aqc_target_num_trotter_steps = 32\n",
"\n",
- "aqc_target_circuit = initial_state.copy()\n",
+ "aqc_target_circuit = initial_state_circuit.copy()\n",
"aqc_target_circuit.compose(\n",
" generate_time_evolution_circuit(\n",
" hamiltonian,\n",
@@ -271,133 +337,46 @@
")"
]
},
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "83039f82-97cb-4613-86c9-a8faf0839a02",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Generate the subsequent circuit\n",
- "subsequent_num_trotter_steps = 3\n",
- "subsequent_evolution_time = 0.2\n",
- "\n",
- "subsequent_circuit = generate_time_evolution_circuit(\n",
- " hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=subsequent_num_trotter_steps),\n",
- " time=subsequent_evolution_time,\n",
- ")\n",
- "subsequent_circuit.draw(\"mpl\", fold=-1)"
- ]
- },
{
"cell_type": "markdown",
- "id": "064a17af-4af8-4ff5-899c-750147d269df",
+ "id": "bce1ef52",
"metadata": {},
"source": [
- "To enable a meaningful comparison, we will generate two additional circuits:\n",
+ "#### Generate an ansatz, initial parameters, subsequent circuit, and a baseline circuit\n",
"\n",
- "- **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`.\n",
+ "Next, we construct a \"good\" circuit with the same evolution time as the AQC target but far fewer Trotter steps (only one). We pass this circuit to `generate_ansatz_from_circuit`, which returns:\n",
"\n",
- "- **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`."
+ "1. A general, parametrized **ansatz** circuit with the same two-qubit connectivity.\n",
+ "2. **Initial parameters** that reproduce the input circuit when plugged into the ansatz.\n",
+ "\n",
+ "We also construct:\n",
+ "- A **subsequent circuit** with one Trotter step that will be appended (uncompressed) after the AQC-optimized portion, following the approach in the [AQC-Tensor initial state tutorial](https://qiskit.github.io/qiskit-addon-aqc-tensor/tutorials/01_initial_state_aqc.html).\n",
+ "- A **baseline Trotter circuit** using four Trotter steps over the full evolution time (`aqc_evolution_time + subsequent_evolution_time`). This serves as the comparison: it represents what you would run on hardware without AQC. The AQC ansatz (3 compressed steps + 1 uncompressed step) achieves better accuracy at lower depth."
]
},
{
"cell_type": "code",
- "execution_count": 6,
- "id": "33b2ad93-7ae4-4250-bf38-9adc3bc2970d",
+ "execution_count": 5,
+ "id": "78f2665e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Number of Trotter steps for comparison: 3\n"
+ "Target circuit: depth 384\n",
+ "Baseline circuit: depth 48 (4 Trotter steps, time=0.2667)\n",
+ "Subsequent circuit: depth 12 (1 Trotter step, time=0.0667)\n",
+ "Ansatz circuit: depth 3, with 156 parameters\n"
]
- }
- ],
- "source": [
- "# Generate the AQC comparison circuit\n",
- "aqc_comparison_num_trotter_steps = int(\n",
- " subsequent_num_trotter_steps\n",
- " / subsequent_evolution_time\n",
- " * aqc_evolution_time\n",
- ")\n",
- "print(\n",
- " \"Number of Trotter steps for comparison:\",\n",
- " aqc_comparison_num_trotter_steps,\n",
- ")\n",
- "\n",
- "aqc_comparison_circuit = generate_time_evolution_circuit(\n",
- " hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=aqc_comparison_num_trotter_steps),\n",
- " time=aqc_evolution_time,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "1bfa67a2-ac51-4158-b539-2c33f4c5ecf3",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Generate the reference circuit\n",
- "evolution_time = 0.4\n",
- "reps = 200\n",
- "\n",
- "reference_circuit = initial_state.copy()\n",
- "reference_circuit.compose(\n",
- " generate_time_evolution_circuit(\n",
- " hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=reps),\n",
- " time=evolution_time,\n",
- " ),\n",
- " inplace=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2051f622-5b71-4be5-aab9-e9eb5d315a6f",
- "metadata": {},
- "source": [
- "#### Generate an ansatz and initial parameters from a Trotter circuit with fewer steps\n",
- "\n",
- "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).\n",
- "\n",
- "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:\n",
- "\n",
- "1. A general, parametrized ansatz circuit with the same two-qubit connectivity as the input circuit.\n",
- "2. Parameters that, when plugged into the ansatz, yield the input (good) circuit.\n",
- "\n",
- "Soon we will take these parameters and iteratively adjust them to bring the ansatz circuit as close as possible to the target MPS."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "id": "b9e81c51-dc6f-4237-9aca-e1384f1897bc",
- "metadata": {},
- "outputs": [
+ },
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 8,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -405,7 +384,7 @@
"source": [
"aqc_ansatz_num_trotter_steps = 1\n",
"\n",
- "aqc_good_circuit = initial_state.copy()\n",
+ "aqc_good_circuit = initial_state_circuit.copy()\n",
"aqc_good_circuit.compose(\n",
" generate_time_evolution_circuit(\n",
" hamiltonian,\n",
@@ -418,67 +397,56 @@
"aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(\n",
" aqc_good_circuit\n",
")\n",
- "aqc_ansatz.draw(\"mpl\", fold=-1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "id": "bd9e9bf2-9ee5-445d-aa4a-c7f412c488f8",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "AQC Comparison circuit: depth 36\n",
- "Target circuit: depth 385\n",
- "Ansatz circuit: depth 7, with 156 parameters\n"
- ]
- }
- ],
- "source": [
- "print(f\"AQC Comparison circuit: depth {aqc_comparison_circuit.depth()}\")\n",
- "print(f\"Target circuit: depth {aqc_target_circuit.depth()}\")\n",
+ "\n",
+ "# Subsequent circuit: 1 non-compressed Trotter step appended after AQC\n",
+ "subsequent_num_trotter_steps = 1\n",
+ "subsequent_circuit = generate_time_evolution_circuit(\n",
+ " hamiltonian,\n",
+ " synthesis=SuzukiTrotter(reps=subsequent_num_trotter_steps),\n",
+ " time=subsequent_evolution_time,\n",
+ ")\n",
+ "\n",
+ "# Baseline Trotter circuit: 4 Trotter steps over total evolution time, no AQC\n",
+ "baseline_num_trotter_steps = 4\n",
+ "baseline_circuit = initial_state_circuit.copy()\n",
+ "baseline_circuit.compose(\n",
+ " generate_time_evolution_circuit(\n",
+ " hamiltonian,\n",
+ " synthesis=SuzukiTrotter(reps=baseline_num_trotter_steps),\n",
+ " time=total_evolution_time,\n",
+ " ),\n",
+ " inplace=True,\n",
+ ")\n",
+ "\n",
"print(\n",
- " f\"Ansatz circuit: depth {aqc_ansatz.depth()}, with {len(aqc_initial_parameters)} parameters\"\n",
- ")"
+ " f\"Target circuit: depth {aqc_target_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Baseline circuit: depth {baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({baseline_num_trotter_steps} Trotter steps, time={total_evolution_time:.4f})\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Subsequent circuit: depth {subsequent_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({subsequent_num_trotter_steps} Trotter step, time={subsequent_evolution_time:.4f})\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Ansatz circuit: depth {aqc_ansatz.depth(lambda x: x.operation.num_qubits == 2)}, with {len(aqc_initial_parameters)} parameters\"\n",
+ ")\n",
+ "aqc_ansatz.draw(\"mpl\", fold=-1)"
]
},
{
"cell_type": "markdown",
- "id": "3c8663b9-d513-4a2a-9911-03f3500ad486",
+ "id": "be1b4049",
"metadata": {},
"source": [
- "#### Choose settings for tensor network simulation\n",
+ "#### Set up tensor network simulation and build the target MPS\n",
"\n",
- "Here, we use Quimb's matrix-product state circuit simulator, along with jax to provide the gradient."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "id": "e5b9471f-fc7a-45c9-ab11-295cfff620bf",
- "metadata": {},
- "outputs": [],
- "source": [
- "simulator_settings = QuimbSimulator(\n",
- " quimb.tensor.CircuitMPS, autodiff_backend=\"jax\"\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5030d11d-54e3-4f29-acb2-6f7dd3ff05cb",
- "metadata": {},
- "source": [
- "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."
+ "We use the [quimb](https://github.com/jcmgray/quimb) matrix-product state (MPS) circuit simulator, with JAX providing automatic differentiation for the gradient-based optimization. We then build an MPS representation of the target state and evaluate the starting fidelity between the initial ansatz and the target. As the problem instance is a relatively small example, the starting fidelity starts off quite high."
]
},
{
"cell_type": "code",
- "execution_count": 11,
- "id": "1f050059-a281-41f1-a277-d7450e8b3ee3",
+ "execution_count": 6,
+ "id": "666fcf42",
"metadata": {},
"outputs": [
{
@@ -486,129 +454,77 @@
"output_type": "stream",
"text": [
"Target MPS maximum bond dimension: 5\n",
- "Reference MPS maximum bond dimension: 7\n"
+ "Starting fidelity: 0.998246\n"
]
}
],
"source": [
+ "simulator_settings = QuimbSimulator(\n",
+ " quimb.tensor.CircuitMPS, autodiff_backend=\"jax\"\n",
+ ")\n",
+ "\n",
"aqc_target_mps = tensornetwork_from_circuit(\n",
" aqc_target_circuit, simulator_settings\n",
")\n",
"print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
"\n",
- "# Obtains the reference MPS, where we can obtain the exact expectation value by examining the `local_expectation``\n",
- "reference_mps = tensornetwork_from_circuit(\n",
- " reference_circuit, simulator_settings\n",
- ")\n",
- "reference_expval = reference_mps.local_expectation(\n",
- " quimb.pauli(\"Z\") & quimb.pauli(\"Z\"), (L // 2 - 1, L // 2)\n",
- ").real.item()\n",
- "print(\"Reference MPS maximum bond dimension:\", reference_mps.psi.max_bond())"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5ffbdd20-c9bf-4265-8a8d-8135abb2b8f7",
- "metadata": {},
- "source": [
- "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 ($ |\\langle \\psi_1 | \\psi_2 \\rangle|^2 $) between the state prepared by the initial circuit and the target state to quantify this difference."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "id": "51d7d623-3e7c-44e7-80f1-94fd555a2c9e",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Starting fidelity: 0.9982464959067222\n"
- ]
- }
- ],
- "source": [
"good_mps = tensornetwork_from_circuit(aqc_good_circuit, simulator_settings)\n",
"starting_fidelity = abs(compute_overlap(good_mps, aqc_target_mps)) ** 2\n",
- "print(\"Starting fidelity:\", starting_fidelity)"
+ "print(f\"Starting fidelity: {starting_fidelity:.6f}\")"
]
},
{
"cell_type": "markdown",
- "id": "01234b5b-f4db-4e22-993a-c8673621ab7f",
+ "id": "1f14eb3f",
"metadata": {},
"source": [
- "#### Optimize the parameters of the ansatz using MPS calculations\n",
- "In this step, we optimize the ansatz parameters by minimizing a simple cost function, `MaximizeStateFidelity`, 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. By using additional CPU time, further optimization can continue to increase fidelity."
+ "#### Optimize the ansatz parameters\n",
+ "\n",
+ "We minimize the `MaximizeStateFidelity` cost function using the L-BFGS-B optimizer. The optimizer iteratively adjusts the ansatz parameters to maximize the fidelity between the ansatz circuit and the target MPS."
]
},
{
"cell_type": "code",
- "execution_count": 29,
- "id": "ad2265cb-19a6-4402-8b0d-24239c930c90",
+ "execution_count": 7,
+ "id": "6ad144d6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "2025-04-14 11:46:52.174235 Intermediate result: Fidelity 0.99795851\n",
- "2025-04-14 11:46:52.218249 Intermediate result: Fidelity 0.99822826\n",
- "2025-04-14 11:46:52.280924 Intermediate result: Fidelity 0.99829675\n",
- "2025-04-14 11:46:52.356214 Intermediate result: Fidelity 0.99832474\n",
- "2025-04-14 11:46:52.411609 Intermediate result: Fidelity 0.99836131\n",
- "2025-04-14 11:46:52.453747 Intermediate result: Fidelity 0.99839954\n",
- "2025-04-14 11:46:52.496184 Intermediate result: Fidelity 0.99846517\n",
- "2025-04-14 11:46:52.542046 Intermediate result: Fidelity 0.99865029\n",
- "2025-04-14 11:46:52.583679 Intermediate result: Fidelity 0.99872332\n",
- "2025-04-14 11:46:52.628732 Intermediate result: Fidelity 0.99892359\n",
- "2025-04-14 11:46:52.690386 Intermediate result: Fidelity 0.99900640\n",
- "2025-04-14 11:46:52.759398 Intermediate result: Fidelity 0.99907169\n",
- "2025-04-14 11:46:52.819496 Intermediate result: Fidelity 0.99911423\n",
- "2025-04-14 11:46:52.884505 Intermediate result: Fidelity 0.99918716\n",
- "2025-04-14 11:46:52.947919 Intermediate result: Fidelity 0.99921278\n",
- "2025-04-14 11:46:53.012808 Intermediate result: Fidelity 0.99924853\n",
- "2025-04-14 11:46:53.083626 Intermediate result: Fidelity 0.99928797\n",
- "2025-04-14 11:46:53.153235 Intermediate result: Fidelity 0.99933028\n",
- "2025-04-14 11:46:53.221371 Intermediate result: Fidelity 0.99935757\n",
- "2025-04-14 11:46:53.286211 Intermediate result: Fidelity 0.99938140\n",
- "2025-04-14 11:46:53.352391 Intermediate result: Fidelity 0.99940964\n",
- "2025-04-14 11:46:53.420472 Intermediate result: Fidelity 0.99944051\n",
- "2025-04-14 11:46:53.486279 Intermediate result: Fidelity 0.99946828\n",
- "2025-04-14 11:46:53.552338 Intermediate result: Fidelity 0.99948723\n",
- "2025-04-14 11:46:53.618688 Intermediate result: Fidelity 0.99951011\n",
- "2025-04-14 11:46:53.690878 Intermediate result: Fidelity 0.99954718\n",
- "2025-04-14 11:46:53.762725 Intermediate result: Fidelity 0.99956267\n",
- "2025-04-14 11:46:53.829784 Intermediate result: Fidelity 0.99958949\n",
- "2025-04-14 11:46:53.897477 Intermediate result: Fidelity 0.99960498\n",
- "2025-04-14 11:46:53.954633 Intermediate result: Fidelity 0.99961308\n",
- "2025-04-14 11:46:54.010125 Intermediate result: Fidelity 0.99962894\n",
- "2025-04-14 11:46:54.064717 Intermediate result: Fidelity 0.99964121\n",
- "2025-04-14 11:46:54.118892 Intermediate result: Fidelity 0.99964348\n",
- "2025-04-14 11:46:54.183236 Intermediate result: Fidelity 0.99964860\n",
- "2025-04-14 11:46:54.245521 Intermediate result: Fidelity 0.99965695\n",
- "2025-04-14 11:46:54.305792 Intermediate result: Fidelity 0.99966398\n",
- "2025-04-14 11:46:54.355819 Intermediate result: Fidelity 0.99967816\n",
- "2025-04-14 11:46:54.409580 Intermediate result: Fidelity 0.99968293\n",
- "2025-04-14 11:46:54.457979 Intermediate result: Fidelity 0.99968936\n",
- "2025-04-14 11:46:54.505891 Intermediate result: Fidelity 0.99969223\n",
- "2025-04-14 11:46:54.551084 Intermediate result: Fidelity 0.99970009\n",
- "2025-04-14 11:46:54.601817 Intermediate result: Fidelity 0.99970724\n",
- "2025-04-14 11:46:54.650097 Intermediate result: Fidelity 0.99970987\n",
- "2025-04-14 11:46:54.714727 Intermediate result: Fidelity 0.99971237\n",
- "2025-04-14 11:46:54.780052 Intermediate result: Fidelity 0.99971916\n",
- "2025-04-14 11:46:54.871994 Intermediate result: Fidelity 0.99971940\n",
- "2025-04-14 11:46:54.958244 Intermediate result: Fidelity 0.99972465\n",
- "2025-04-14 11:46:55.011057 Intermediate result: Fidelity 0.99972763\n",
- "2025-04-14 11:46:55.175339 Intermediate result: Fidelity 0.99972894\n",
- "2025-04-14 11:46:56.688912 Intermediate result: Fidelity 0.99972894\n",
- "Done after 50 iterations.\n"
+ "2026-05-18 13:14:49.731596 Intermediate result: Fidelity 0.99952882\n",
+ "2026-05-18 13:14:49.734425 Intermediate result: Fidelity 0.99958531\n",
+ "2026-05-18 13:14:49.737101 Intermediate result: Fidelity 0.99960093\n",
+ "2026-05-18 13:14:49.739813 Intermediate result: Fidelity 0.99961046\n",
+ "2026-05-18 13:14:49.742969 Intermediate result: Fidelity 0.99962560\n",
+ "2026-05-18 13:14:49.745916 Intermediate result: Fidelity 0.99964395\n",
+ "2026-05-18 13:14:49.748615 Intermediate result: Fidelity 0.99968150\n",
+ "2026-05-18 13:14:49.753684 Intermediate result: Fidelity 0.99970569\n",
+ "2026-05-18 13:14:49.756208 Intermediate result: Fidelity 0.99973788\n",
+ "2026-05-18 13:14:49.759067 Intermediate result: Fidelity 0.99975385\n",
+ "2026-05-18 13:14:49.762321 Intermediate result: Fidelity 0.99976458\n",
+ "2026-05-18 13:14:49.765526 Intermediate result: Fidelity 0.99977661\n",
+ "2026-05-18 13:14:49.768496 Intermediate result: Fidelity 0.99978663\n",
+ "2026-05-18 13:14:49.771278 Intermediate result: Fidelity 0.99980236\n",
+ "2026-05-18 13:14:49.773735 Intermediate result: Fidelity 0.99981607\n",
+ "2026-05-18 13:14:49.776339 Intermediate result: Fidelity 0.99982811\n",
+ "2026-05-18 13:14:49.779177 Intermediate result: Fidelity 0.99985827\n",
+ "2026-05-18 13:14:49.782243 Intermediate result: Fidelity 0.99988354\n",
+ "2026-05-18 13:14:49.784904 Intermediate result: Fidelity 0.99991608\n",
+ "2026-05-18 13:14:49.787737 Intermediate result: Fidelity 0.99993336\n",
+ "2026-05-18 13:14:49.790414 Intermediate result: Fidelity 0.99993956\n",
+ "2026-05-18 13:14:49.793029 Intermediate result: Fidelity 0.99994421\n",
+ "2026-05-18 13:14:49.795585 Intermediate result: Fidelity 0.99994743\n",
+ "2026-05-18 13:14:49.835045 Intermediate result: Fidelity 0.99994791\n",
+ "2026-05-18 13:14:49.839786 Intermediate result: Fidelity 0.99994803\n",
+ "2026-05-18 13:14:49.842403 Intermediate result: Fidelity 0.99994898\n",
+ "2026-05-18 13:14:49.873779 Intermediate result: Fidelity 0.99994898\n",
+ "Done after 27 iterations.\n"
]
}
],
"source": [
- "# Setting values for the optimization\n",
"aqc_stopping_fidelity = 1\n",
"aqc_max_iterations = 500\n",
"\n",
@@ -624,7 +540,6 @@
" f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\"\n",
" )\n",
" if intermediate_result.fun < stopping_point:\n",
- " # Good enough for now\n",
" raise StopIteration\n",
"\n",
"\n",
@@ -636,14 +551,7 @@
" options={\"maxiter\": aqc_max_iterations},\n",
" callback=callback,\n",
")\n",
- "if (\n",
- " result.status\n",
- " not in (\n",
- " 0,\n",
- " 1,\n",
- " 99,\n",
- " )\n",
- "): # 0 => success; 1 => max iterations reached; 99 => early termination via StopIteration\n",
+ "if result.status not in (0, 1, 99):\n",
" raise RuntimeError(\n",
" f\"Optimization failed: {result.message} (status={result.status})\"\n",
" )\n",
@@ -652,46 +560,29 @@
"aqc_final_parameters = result.x"
]
},
- {
- "cell_type": "code",
- "execution_count": 14,
- "id": "c95ccea0-be99-4db9-838d-2327851e6761",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Final parameters: [-7.853983035039254, 1.5707966468427772, 1.5707962768868613, -1.570798010835122, 1.570794480409574, 1.5707972214146968, -1.570796593027083, 1.5707968206822998, -1.5707959018046258, -1.5707991700969144, 1.5707965852600927, 4.712386891737442, -7.853980840717957, 1.5707967508132654, 1.5707943162503217, -1.5707955382023582, 1.5707958007156742, 1.570796096113293, -1.5707928509846847, 1.5707971042943747, -1.570797909276557, -1.5707941020637393, 1.5707980179540793, 4.712389823219363, -1.5707928752386107, 1.5707996426312891, -1.5707975640471001, -1.570794132802984, 1.5707944361599957, 4.712390747060803, 0.1048818190315936, 0.06686710468840577, -0.0668645844756557, -3.1415923537135466, 1.2374931269696063, 6.323169390432535e-07, 3.53229204771738e-08, 2.1091105688681484, 6.283186439944202, 0.12152258846156239, 0.07961752617254866, -0.07961775088604585, -1.6564278051174865e-06, 2.0771163596472384, 3.141592651630471, -6.283185775192653, 1.7691609006726954, 3.1415922910116216, 0.19837572065074083, 0.11114901449078964, -0.11115124544944892, -3.141591983034976, 0.8570788408766729, 4.201601390404146e-07, -3.141593736550978, 0.34652010942396333, 6.283186232785291, 0.13606356527241956, 0.03891676349289617, -0.03891524189533726, -1.5707965732853424, 1.5707968967088564, -0.3086133992238162, 1.5707957152428194, 1.5707968398959653, -0.32062737993080026, 0.11027416939993417, 0.0726167290795046, -0.07262020423334464, -2.3729431959735024e-06, 1.8204437429254703, 9.299060301196612e-07, -3.141592899563451, 2.103269568939461, 3.1415937539734626, 0.11536891854817125, 0.09099022308254198, -0.09098864958606581, -3.1415913307373127, 2.078429034357281, -1.509777998069368e-06, -3.1415922600663255, 1.5189162645358172, -3.1415878461323583, 0.09999070991480716, 0.04352011445148391, -0.04351849541849812, -1.570797642506462, 1.570795238023824, 0.8903442644396505, 1.5707962698006606, 1.5707946765132268, 0.9098791754570567, 0.10448284343424026, 0.07317037684936827, -0.07316718173961152, -3.141592682240966, 2.1665363080039612, -7.450882112394189e-07, -5.771181304929921e-07, 2.615334999517103, -3.1415914971653898, 0.1890887078648001, 0.13578163074571992, -0.13578078143610256, 7.156734195912883e-07, 1.7915385305413096, -5.188866034727312e-07, 1.2827742939197711e-06, 1.2348316581417487, 6.28318357406372, 0.08061187643781703, 0.03820789039271876, -0.03820731868804904, 1.5707964027727628, 1.570798734462218, 4.387336153720882, -1.570795722044763, 1.570798457375325, 4.450361734163248, 0.092360147257953, 0.06047700345049011, -0.06048592856713045, -3.141591214829027, 2.6593289993286047, -2.366937342261038e-07, 8.112162974032695e-08, 1.8907014631413432, 8.355881261853104e-07, 0.23303641819370874, 0.14331998953606456, -0.1433194488304741, -3.141591621822901, 0.7455776479558791, 3.1415914520163586, -3.1415933560496105, 0.7603938554148255, -1.6230983177616282e-06, 0.07186349688535713, 0.03197144517771341, -0.031971177878588546, -4.712389048748508, 1.5707948403165752, 1.2773619319829186, -1.5707990802172127, 1.5707957676951863, 1.289083769394045, 0.13644999397718796, 0.032761460443590046, -0.032762060585195645, -1.5707977610073176, 1.5707964181578042, -3.4826435600366983, -4.712389691708343, 1.570794277502252, 2.799088046133275]\n"
- ]
- }
- ],
- "source": [
- "parameters = [float(param) for param in aqc_final_parameters]\n",
- "print(\"Final parameters:\", parameters)"
- ]
- },
{
"cell_type": "markdown",
- "id": "ca32c1ef-f7d5-4489-83b3-17972bf94700",
+ "id": "ea5b484a",
"metadata": {},
"source": [
- "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."
+ "#### Assemble the final AQC circuit\n",
+ "\n",
+ "With the optimized parameters in hand, we bind them to the ansatz and then append the subsequent (uncompressed) Trotter step. The resulting circuit has the depth of a single compressed Trotter step plus one uncompressed step, but the compressed portion approximates the accuracy of 32 Trotter steps."
]
},
{
"cell_type": "code",
- "execution_count": 15,
- "id": "813c9ced-6a2e-4345-bffc-7dae938e2015",
+ "execution_count": 8,
+ "id": "e09e40de",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 15,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -704,303 +595,128 @@
},
{
"cell_type": "markdown",
- "id": "46a93127-5443-40b7-a81a-dfd70df42ba2",
+ "id": "047511db",
"metadata": {},
"source": [
- "We also need to merge our `aqc_comparison_circuit` with the remaining evolution circuit. This circuit will be used to compare the performance of the AQC-Tensor-optimized circuit with the original circuit."
+ "### Step 2: Optimize problem for quantum hardware execution\n",
+ "\n",
+ "For this small-scale example, we use a fake backend (`FakeKyiv`) to simulate hardware execution locally. We transpile both the AQC-optimized circuit (`aqc_final_circuit`) and the baseline Trotter circuit (`baseline_circuit`, four Trotter steps over the full evolution time, no AQC) to the backend's instruction set architecture (ISA), with `optimization_level=3` to further reduce circuit depth."
]
},
{
"cell_type": "code",
- "execution_count": 16,
- "id": "86ba26ff-0bfa-47d0-b5ee-8944a8ddf274",
+ "execution_count": 9,
+ "id": "9e7556dd",
"metadata": {},
"outputs": [
{
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "aqc_comparison_circuit.compose(subsequent_circuit, inplace=True)\n",
- "aqc_comparison_circuit.draw(\"mpl\", fold=-1)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "982c5067-9a74-42a0-bd31-aaff72cf79df",
- "metadata": {},
- "source": [
- "### Step 2: Optimize problem for quantum hardware execution"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2121c40c-a9a7-4c36-a20a-04ee9f6637db",
- "metadata": {},
- "source": [
- "Select the hardware. Here we will use any of the IBM Quantum® devices available that have at least 127 qubits."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "88715b59-4516-4b75-b041-c978944dd14a",
- "metadata": {},
- "outputs": [],
- "source": [
- "service = QiskitRuntimeService()\n",
- "backend = service.least_busy(min_num_qubits=127)\n",
- "print(backend)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3f477394-5eac-4c12-b36b-e94c800fa889",
- "metadata": {},
- "source": [
- "We transpile PUBs (circuit and observables) to match the backend ISA (Instruction Set Architecture). By setting `optimization_level=3`, the transpiler optimizes the circuit to fit a one-dimensional chain of qubits, reducing the noise that impacts circuit fidelity. Once the circuits are transformed into a format compatible with the backend, we apply a corresponding transformation to the observables to ensure they align with the modified qubit layout."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "id": "087fff8d-98b9-4f9a-8004-01a3b0166e12",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Observable info: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ'],\n",
- " coeffs=[1.+0.j])\n",
- "Circuit depth: 111\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "AQC circuit depth: 15\n",
+ "Baseline Trotter circuit depth: 27\n"
+ ]
}
],
"source": [
+ "backend = FakeKyiv()\n",
+ "\n",
"pass_manager = generate_preset_pass_manager(\n",
" backend=backend, optimization_level=3\n",
")\n",
+ "\n",
+ "# Transpile the AQC-optimized circuit (compressed + subsequent step)\n",
"isa_circuit = pass_manager.run(aqc_final_circuit)\n",
"isa_observable = observable.apply_layout(isa_circuit.layout)\n",
- "print(\"Observable info:\", isa_observable)\n",
- "print(\"Circuit depth:\", isa_circuit.depth())\n",
- "isa_circuit.draw(\"mpl\", fold=-1, idle_wires=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "58e8e840-94a8-4414-81f7-01bbf1b73810",
- "metadata": {},
- "source": [
- "Perform transpilation for the comparison circuit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "id": "7c2e5fe7-21ce-461d-adaa-776f8d882163",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Observable info: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ'],\n",
- " coeffs=[1.+0.j])\n",
- "Circuit depth: 158\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 19,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isa_comparison_circuit = pass_manager.run(aqc_comparison_circuit)\n",
- "isa_comparison_observable = observable.apply_layout(\n",
- " isa_comparison_circuit.layout\n",
+ "print(\n",
+ " \"AQC circuit depth:\",\n",
+ " isa_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
")\n",
- "print(\"Observable info:\", isa_comparison_observable)\n",
- "print(\"Circuit depth:\", isa_comparison_circuit.depth())\n",
- "isa_comparison_circuit.draw(\"mpl\", fold=-1, idle_wires=False)"
+ "\n",
+ "# Transpile the baseline Trotter circuit (no AQC optimization)\n",
+ "isa_baseline_circuit = pass_manager.run(baseline_circuit)\n",
+ "isa_baseline_observable = observable.apply_layout(isa_baseline_circuit.layout)\n",
+ "print(\n",
+ " \"Baseline Trotter circuit depth:\",\n",
+ " isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
+ ")"
]
},
{
"cell_type": "markdown",
- "id": "1f832aaa-c2a9-42b7-95b6-bd920cdc17b0",
+ "id": "60aec566",
"metadata": {},
"source": [
"### Step 3: Execute using Qiskit primitives\n",
"\n",
- "In this step, we execute the transpiled circuit on quantum hardware (or a simulated backend). Using the `EstimatorV2` class from `qiskit_ibm_runtime`, we set up an estimator to run the circuit and measure the specified observable. The job result provides the expected outcome for the observable, giving us insights into the circuit’s performance on the target hardware."
+ "We use the [`EstimatorV2`](/docs/api/qiskit-ibm-runtime/estimator-v2) primitive with the fake backend to run both the AQC-optimized circuit and the baseline Trotter circuit, measuring the ZZ observable for each."
]
},
{
"cell_type": "code",
- "execution_count": 20,
- "id": "3aabf36b-4587-43b7-be99-9376fc7f47c1",
+ "execution_count": 10,
+ "id": "241e24f2",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Job ID: czyhqdxd8drg008hx0yg\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(), stds=np.ndarray(), ensemble_standard_error=np.ndarray()), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"estimator = Estimator(backend)\n",
- "job = estimator.run([(isa_circuit, isa_observable)])\n",
- "print(\"Job ID:\", job.job_id())\n",
- "job.result()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4ec6669b-2b76-41df-9634-3c073998b1d7",
- "metadata": {},
- "source": [
- "Perform the execution for the comparison circuit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "id": "91f16fff-da28-42b4-a32a-fa2f0945f8fd",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Job Comparison ID: czyhqdxd8drg008hx0yg\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(), stds=np.ndarray(), ensemble_standard_error=np.ndarray()), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})"
- ]
- },
- "execution_count": 21,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "job_comparison = estimator.run([(isa_comparison_circuit, isa_observable)])\n",
- "print(\"Job Comparison ID:\", job.job_id())\n",
- "job_comparison.result()"
+ "\n",
+ "# Run both circuits\n",
+ "aqc_result = estimator.run([(isa_circuit, isa_observable)]).result()\n",
+ "baseline_result = estimator.run(\n",
+ " [(isa_baseline_circuit, isa_baseline_observable)]\n",
+ ").result()"
]
},
{
"cell_type": "markdown",
- "id": "3c6d16d4-3118-49b6-9594-3d7ddb02701c",
+ "id": "0b980055",
"metadata": {},
"source": [
"### Step 4: Post-process and return result in desired classical format\n",
"\n",
- "In this case, reconstruction is unnecessary. We can directly examine the result by accessing the expectation value from the execution output."
+ "We extract the expectation values from both runs and compare them to the exact result. The baseline Trotter circuit shows what we would get without AQC at the same circuit depth, while the AQC circuit demonstrates the improvement from tensor-network optimization."
]
},
{
"cell_type": "code",
- "execution_count": 22,
- "id": "7247e56f-0ab8-4aa9-834c-ba95965a0b3f",
+ "execution_count": 11,
+ "id": "af07a1d9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Exact: \t-0.5252\n",
- "AQC: \t-0.4903, |∆| = 0.0349\n",
- "AQC Comparison:\t0.5424, |∆| = 1.0676\n"
+ "Exact: -0.7009\n",
+ "Baseline Trotter: -0.5400, |Δ| = 0.1609 (depth 27, 4 steps)\n",
+ "AQC (3+1): -0.5728, |Δ| = 0.1281 (depth 15, compressed+subsequent)\n"
]
}
],
"source": [
- "# AQC results\n",
- "hw_results = job.result()\n",
- "hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]\n",
- "hw_expvals = [\n",
- " pub_result_data[\"evs\"].tolist() for pub_result_data in hw_results_dicts\n",
- "]\n",
- "aqc_expval = hw_expvals[0]\n",
- "\n",
- "# AQC comparison results\n",
- "hw_comparison_results = job_comparison.result()\n",
- "hw_comparison_results_dicts = [\n",
- " pub_result.data.__dict__ for pub_result in hw_comparison_results\n",
- "]\n",
- "hw_comparison_expvals = [\n",
- " pub_result_data[\"evs\"].tolist()\n",
- " for pub_result_data in hw_comparison_results_dicts\n",
- "]\n",
- "aqc_compare_expval = hw_comparison_expvals[0]\n",
+ "aqc_expval = aqc_result[0].data.evs.tolist()\n",
+ "baseline_expval = baseline_result[0].data.evs.tolist()\n",
"\n",
- "print(f\"Exact: \\t{reference_expval:.4f}\")\n",
+ "print(f\"Exact: {exact_expval:.4f}\")\n",
"print(\n",
- " f\"AQC: \\t{aqc_expval:.4f}, |∆| = {np.abs(reference_expval- aqc_expval):.4f}\"\n",
+ " f\"Baseline Trotter: {baseline_expval:.4f}, |\\u0394| = {np.abs(exact_expval - baseline_expval):.4f} (depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)}, {baseline_num_trotter_steps} steps)\"\n",
")\n",
"print(\n",
- " f\"AQC Comparison:\\t{aqc_compare_expval:.4f}, |∆| = {np.abs(reference_expval- aqc_compare_expval):.4f}\"\n",
+ " f\"AQC (3+1): {aqc_expval:.4f}, |\\u0394| = {np.abs(exact_expval - aqc_expval):.4f} (depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)}, compressed+subsequent)\"\n",
")"
]
},
- {
- "cell_type": "markdown",
- "id": "1c8b65e6-df72-45b3-8f31-a6aed44cb867",
- "metadata": {},
- "source": [
- "Bar plot to compare the results of the AQC, comparison, and exact circuits."
- ]
- },
{
"cell_type": "code",
- "execution_count": 23,
- "id": "5f7b36a6-3666-4223-9c5d-d92bca741ad2",
+ "execution_count": 12,
+ "id": "77c39ba8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
@@ -1010,77 +726,141 @@
"source": [
"plt.style.use(\"seaborn-v0_8\")\n",
"\n",
- "labels = [\"AQC Result\", \"AQC Comparison Result\"]\n",
- "values = [abs(aqc_expval), abs(aqc_compare_expval)]\n",
+ "labels = [\n",
+ " f\"Baseline Trotter\\n({baseline_num_trotter_steps} steps, depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
+ " f\"AQC (3+1)\\n(depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
+ "]\n",
+ "values = [baseline_expval, aqc_expval]\n",
+ "colors = [\"tab:orange\", \"tab:blue\"]\n",
"\n",
- "plt.figure(figsize=(10, 6))\n",
- "bars = plt.bar(labels, values, color=[\"tab:blue\", \"tab:purple\"])\n",
+ "plt.figure(figsize=(8, 5))\n",
+ "bars = plt.bar(labels, values, color=colors, width=0.5)\n",
"plt.axhline(\n",
- " y=abs(reference_expval), color=\"red\", linestyle=\"--\", label=\"Exact Result\"\n",
+ " y=exact_expval,\n",
+ " color=\"tab:green\",\n",
+ " linestyle=\"--\",\n",
+ " linewidth=2,\n",
+ " label=f\"Exact ({exact_expval:.4f})\",\n",
+ ")\n",
+ "plt.ylabel(\"Expected Value\")\n",
+ "plt.title(\n",
+ " \"AQC-Tensor (3 compressed + 1 uncompressed) vs Baseline Trotter (10-site XXZ)\"\n",
")\n",
- "plt.xlabel(\"Results\")\n",
- "plt.ylabel(\"Absolute Expected Value\")\n",
- "plt.title(\"AQC Result vs AQC Comparison Result (Absolute Values)\")\n",
"plt.legend()\n",
"for bar in bars:\n",
" y_val = bar.get_height()\n",
" plt.text(\n",
" bar.get_x() + bar.get_width() / 2.0,\n",
" y_val,\n",
- " round(y_val, 2),\n",
- " va=\"bottom\",\n",
+ " f\"{y_val:.4f}\",\n",
+ " ha=\"center\",\n",
+ " va=\"bottom\" if y_val >= 0 else \"top\",\n",
" )\n",
+ "plt.axhline(y=0, color=\"black\", linewidth=0.3)\n",
+ "plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "ff81fb19-d175-42b0-8ef3-025712a7630d",
+ "id": "37062efa",
"metadata": {},
"source": [
- "## Part II: scale it up\n",
- "\n",
+ "## Large-scale hardware example\n",
"\n",
- "The second part of this tutorial builds on the previous example by scaling up to a larger system with 50 sites, illustrating how to map more complex quantum simulation problems to executable quantum circuits. Here, we explore the dynamics of a 50-site XXZ model, allowing us to build and optimize a substantial quantum circuit that reflects more realistic system sizes.\n",
+ "We now scale up to a 50-site XXZ model to demonstrate AQC-Tensor on a more realistic problem size. The workflow is the same as the small-scale example: we compress three Trotter steps via AQC and append one uncompressed step.\n",
"\n",
- "The Hamiltonian for our 50-site XXZ model is defined as:\n",
- "$$\n",
- "\\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) \\, ,\n",
- "$$\n",
+ "For a system of this size, matrix exponentiation is infeasible ($2^{50}$ dimensions), so we compute the reference expectation value directly from a high-accuracy MPS evolved for the full time.\n",
"\n",
- "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$, and $L=50$ is the number of sites."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f6d11e17-b4be-44fa-bc09-465e5e66a6af",
- "metadata": {},
- "source": [
- "Define the coupling map and edges for the Hamiltonian."
+ "### Steps 1–4 combined"
]
},
{
"cell_type": "code",
- "execution_count": 30,
- "id": "d0dec1ee-85fe-4c40-9595-b7764e9cfcca",
+ "execution_count": 13,
+ "id": "b6c0f26a",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Target circuit: depth 385\n",
+ "Ansatz circuit: depth 7, with 816 parameters\n",
+ "Subsequent circuit: depth 12\n",
+ "Baseline circuit: depth 49 (4 steps, time=0.2667)\n",
+ "Target MPS maximum bond dimension: 5\n",
+ "Reference expectation value (from MPS): -0.738669\n",
+ "2026-05-18 13:02:11.219150 Intermediate result: Fidelity 0.99795732\n",
+ "2026-05-18 13:02:11.232256 Intermediate result: Fidelity 0.99822481\n",
+ "2026-05-18 13:02:11.245160 Intermediate result: Fidelity 0.99829520\n",
+ "2026-05-18 13:02:11.257765 Intermediate result: Fidelity 0.99832379\n",
+ "2026-05-18 13:02:11.270280 Intermediate result: Fidelity 0.99836416\n",
+ "2026-05-18 13:02:11.284116 Intermediate result: Fidelity 0.99840073\n",
+ "2026-05-18 13:02:11.296856 Intermediate result: Fidelity 0.99846863\n",
+ "2026-05-18 13:02:11.309602 Intermediate result: Fidelity 0.99865244\n",
+ "2026-05-18 13:02:11.322012 Intermediate result: Fidelity 0.99872665\n",
+ "2026-05-18 13:02:11.334195 Intermediate result: Fidelity 0.99892335\n",
+ "2026-05-18 13:02:11.346570 Intermediate result: Fidelity 0.99901045\n",
+ "2026-05-18 13:02:11.359202 Intermediate result: Fidelity 0.99907181\n",
+ "2026-05-18 13:02:11.371511 Intermediate result: Fidelity 0.99911125\n",
+ "2026-05-18 13:02:11.383870 Intermediate result: Fidelity 0.99918585\n",
+ "2026-05-18 13:02:11.396184 Intermediate result: Fidelity 0.99921504\n",
+ "2026-05-18 13:02:11.408543 Intermediate result: Fidelity 0.99924936\n",
+ "2026-05-18 13:02:11.422557 Intermediate result: Fidelity 0.99929226\n",
+ "2026-05-18 13:02:11.436275 Intermediate result: Fidelity 0.99933099\n",
+ "2026-05-18 13:02:11.449511 Intermediate result: Fidelity 0.99935792\n",
+ "2026-05-18 13:02:11.462093 Intermediate result: Fidelity 0.99937925\n",
+ "2026-05-18 13:02:11.475783 Intermediate result: Fidelity 0.99940690\n",
+ "2026-05-18 13:02:11.490254 Intermediate result: Fidelity 0.99944409\n",
+ "2026-05-18 13:02:11.503292 Intermediate result: Fidelity 0.99946840\n",
+ "2026-05-18 13:02:11.516064 Intermediate result: Fidelity 0.99949378\n",
+ "2026-05-18 13:02:11.532861 Intermediate result: Fidelity 0.99951380\n",
+ "2026-05-18 13:02:11.546182 Intermediate result: Fidelity 0.99955313\n",
+ "2026-05-18 13:02:11.559168 Intermediate result: Fidelity 0.99955707\n",
+ "2026-05-18 13:02:11.571753 Intermediate result: Fidelity 0.99959306\n",
+ "2026-05-18 13:02:11.584257 Intermediate result: Fidelity 0.99960486\n",
+ "2026-05-18 13:02:11.597610 Intermediate result: Fidelity 0.99961714\n",
+ "2026-05-18 13:02:11.610106 Intermediate result: Fidelity 0.99962953\n",
+ "2026-05-18 13:02:11.622515 Intermediate result: Fidelity 0.99963525\n",
+ "2026-05-18 13:02:11.635543 Intermediate result: Fidelity 0.99964658\n",
+ "2026-05-18 13:02:11.649044 Intermediate result: Fidelity 0.99965027\n",
+ "2026-05-18 13:02:11.664148 Intermediate result: Fidelity 0.99965802\n",
+ "2026-05-18 13:02:11.678033 Intermediate result: Fidelity 0.99966731\n",
+ "2026-05-18 13:02:11.692714 Intermediate result: Fidelity 0.99967780\n",
+ "2026-05-18 13:02:11.706753 Intermediate result: Fidelity 0.99968567\n",
+ "2026-05-18 13:02:11.720780 Intermediate result: Fidelity 0.99969139\n",
+ "2026-05-18 13:02:11.733471 Intermediate result: Fidelity 0.99969628\n",
+ "2026-05-18 13:02:11.745998 Intermediate result: Fidelity 0.99970331\n",
+ "2026-05-18 13:02:11.758424 Intermediate result: Fidelity 0.99970796\n",
+ "2026-05-18 13:02:11.771986 Intermediate result: Fidelity 0.99971165\n",
+ "2026-05-18 13:02:11.785841 Intermediate result: Fidelity 0.99971892\n",
+ "2026-05-18 13:02:11.799105 Intermediate result: Fidelity 0.99972226\n",
+ "2026-05-18 13:02:11.811623 Intermediate result: Fidelity 0.99972441\n",
+ "2026-05-18 13:02:11.824114 Intermediate result: Fidelity 0.99972679\n",
+ "2026-05-18 13:02:11.837179 Intermediate result: Fidelity 0.99972965\n",
+ "2026-05-18 13:02:12.345479 Intermediate result: Fidelity 0.99972965\n",
+ "Done after 49 iterations.\n",
+ "\n",
+ "AQC circuit depth: 71\n",
+ "Baseline Trotter circuit depth: 111\n",
+ "Job ID: d85kc6o0bvlc73d5nhn0\n"
+ ]
+ }
+ ],
"source": [
- "L = 50 # L = length of our 1D spin chain\n",
+ "# -------------------------Step 1-------------------------\n",
"\n",
- "# Generate the edge list for this spin-chain\n",
+ "# Define the 50-site spin chain\n",
+ "L = 50\n",
"edge_list = [(i - 1, i) for i in range(1, L)]\n",
- "# Generate an edge-coloring so we can make hw-efficient circuits\n",
"even_edges = edge_list[::2]\n",
"odd_edges = edge_list[1::2]\n",
- "\n",
- "# Instantiate a CouplingMap object\n",
"coupling_map = CouplingMap(edge_list)\n",
"\n",
- "# Generate random coefficients for our XXZ Hamiltonian\n",
+ "# Random XXZ Hamiltonian\n",
"np.random.seed(0)\n",
"Js = np.random.rand(L - 1) + 0.5 * np.ones(L - 1)\n",
- "\n",
"hamiltonian = SparsePauliOp(Pauli(\"I\" * L))\n",
"for i, edge in enumerate(even_edges + odd_edges):\n",
" hamiltonian += SparsePauliOp.from_sparse_list(\n",
@@ -1096,47 +876,21 @@
" [(\"ZZ\", (L // 2 - 1, L // 2), 1.0)], num_qubits=L\n",
")\n",
"\n",
- "# Generate an initial state\n",
- "L = hamiltonian.num_qubits\n",
- "initial_state = QuantumCircuit(L)\n",
+ "# Initial Néel state\n",
+ "initial_state_circuit = QuantumCircuit(L)\n",
"for i in range(L):\n",
" if i % 2:\n",
- " initial_state.x(i)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "65009d89-4752-40ac-b3ab-8e88425851b2",
- "metadata": {},
- "source": [
- "### Step 1: Map classical inputs to a quantum problem\n",
- "\n",
- "For this larger problem, we start by constructing the Hamiltonian for the 50-site XXZ model, defining spin-spin interactions and external magnetic fields across all sites. After this, we follow three main steps:\n",
+ " initial_state_circuit.x(i)\n",
"\n",
- "1. **Generate the optimized AQC circuit**: Use Trotterization to approximate the initial evolution, then compress this segment to reduce circuit depth.\n",
- "2. **Create the remaining time evolution circuit**: Capture the remaining time evolution beyond the initial segment.\n",
- "3. **Combine the circuits**: Merge the optimized AQC circuit with the remaining evolution circuit to create a complete time-evolution circuit ready for execution."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "41f5186a-e54e-4913-8a52-1c90611991c7",
- "metadata": {},
- "source": [
- "Generate the AQC target circuit (the initial segment)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "id": "86735d08-49b3-47e4-abcd-631a77f50a02",
- "metadata": {},
- "outputs": [],
- "source": [
+ "# Time parameters\n",
"aqc_evolution_time = 0.2\n",
+ "subsequent_evolution_time = aqc_evolution_time / 3\n",
+ "total_evolution_time = aqc_evolution_time + subsequent_evolution_time\n",
+ "\n",
+ "# AQC target circuit (high-accuracy, 32 Trotter steps for AQC portion)\n",
"aqc_target_num_trotter_steps = 32\n",
"\n",
- "aqc_target_circuit = initial_state.copy()\n",
+ "aqc_target_circuit = initial_state_circuit.copy()\n",
"aqc_target_circuit.compose(\n",
" generate_time_evolution_circuit(\n",
" hamiltonian,\n",
@@ -1144,286 +898,83 @@
" time=aqc_evolution_time,\n",
" ),\n",
" inplace=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c5e79369-19ae-4b17-a9fc-9502a8a1254c",
- "metadata": {},
- "source": [
- "Generate the subsequent circuit (the remaining segment)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "id": "35c6469c-3be7-4e89-a065-0e4957305b59",
- "metadata": {},
- "outputs": [],
- "source": [
- "subsequent_num_trotter_steps = 3\n",
- "subsequent_evolution_time = 0.2\n",
+ ")\n",
"\n",
- "subsequent_circuit = generate_time_evolution_circuit(\n",
- " hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=subsequent_num_trotter_steps),\n",
- " time=subsequent_evolution_time,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0e13fbc5-0c00-4f21-9925-8d1230854dc5",
- "metadata": {},
- "source": [
- "Generate the AQC comparison circuit (the initial segment, but with the same number of Trotter steps as the subsequent circuit)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "id": "922fb467-81b0-40d7-b21b-ef781ad043a1",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Number of Trotter steps for comparison: 3\n"
- ]
- }
- ],
- "source": [
- "# Generate the AQC comparison circuit\n",
- "aqc_comparison_num_trotter_steps = int(\n",
- " subsequent_num_trotter_steps\n",
- " / subsequent_evolution_time\n",
- " * aqc_evolution_time\n",
+ "# Generate ansatz from 1-step Trotter circuit\n",
+ "aqc_good_circuit = initial_state_circuit.copy()\n",
+ "aqc_good_circuit.compose(\n",
+ " generate_time_evolution_circuit(\n",
+ " hamiltonian,\n",
+ " synthesis=SuzukiTrotter(reps=1),\n",
+ " time=aqc_evolution_time,\n",
+ " ),\n",
+ " inplace=True,\n",
")\n",
- "print(\n",
- " \"Number of Trotter steps for comparison:\",\n",
- " aqc_comparison_num_trotter_steps,\n",
+ "\n",
+ "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(\n",
+ " aqc_good_circuit\n",
")\n",
"\n",
- "aqc_comparison_circuit = generate_time_evolution_circuit(\n",
+ "# Subsequent circuit: 1 non-compressed Trotter step\n",
+ "subsequent_circuit = generate_time_evolution_circuit(\n",
" hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=aqc_comparison_num_trotter_steps),\n",
- " time=aqc_evolution_time,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "21228ca8-3fa6-4efe-9e53-8d3f824b7729",
- "metadata": {},
- "source": [
- "Generate the reference circuit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "id": "3525fe02-25cf-4254-b2c4-717f27bc29d8",
- "metadata": {},
- "outputs": [],
- "source": [
- "evolution_time = 0.4\n",
- "reps = 200\n",
+ " synthesis=SuzukiTrotter(reps=1),\n",
+ " time=subsequent_evolution_time,\n",
+ ")\n",
"\n",
- "reference_circuit = initial_state.copy()\n",
- "reference_circuit.compose(\n",
+ "# Baseline Trotter circuit: 4 Trotter steps over total evolution time, no AQC\n",
+ "baseline_num_trotter_steps = 4\n",
+ "baseline_circuit = initial_state_circuit.copy()\n",
+ "baseline_circuit.compose(\n",
" generate_time_evolution_circuit(\n",
" hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=reps),\n",
- " time=evolution_time,\n",
- " ),\n",
- " inplace=True,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a15b40ac-0259-4229-b76b-502ff7068499",
- "metadata": {},
- "source": [
- "Generate an ansatz and initial parameters from a Trotter circuit with fewer steps."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "id": "ddbc3549-3171-4a29-b046-2a52b5e7065a",
- "metadata": {},
- "outputs": [],
- "source": [
- "aqc_ansatz_num_trotter_steps = 1\n",
- "\n",
- "aqc_good_circuit = initial_state.copy()\n",
- "aqc_good_circuit.compose(\n",
- " generate_time_evolution_circuit(\n",
- " hamiltonian,\n",
- " synthesis=SuzukiTrotter(reps=aqc_ansatz_num_trotter_steps),\n",
- " time=aqc_evolution_time,\n",
+ " synthesis=SuzukiTrotter(reps=baseline_num_trotter_steps),\n",
+ " time=total_evolution_time,\n",
" ),\n",
" inplace=True,\n",
")\n",
- "\n",
- "aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(\n",
- " aqc_good_circuit\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "id": "8e596d77-5954-4756-b765-48855cd38659",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "AQC Comparison circuit: depth 36\n",
- "Target circuit: depth 385\n",
- "Ansatz circuit: depth 7, with 816 parameters\n"
- ]
- }
- ],
- "source": [
- "print(f\"AQC Comparison circuit: depth {aqc_comparison_circuit.depth()}\")\n",
- "print(f\"Target circuit: depth {aqc_target_circuit.depth()}\")\n",
"print(\n",
- " f\"Ansatz circuit: depth {aqc_ansatz.depth()}, with {len(aqc_initial_parameters)} parameters\"\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4d07d63a-8572-4116-9fd5-c070f62043a7",
- "metadata": {},
- "source": [
- "Set settings for tensor network simulation and then construct a matrix product state representation of the target state for optimization. Then, evaluate the fidelity between the initial circuit and the target state to quantify the difference in Trotter error."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "id": "6030706e-1451-47d9-9e47-bcccf4cb5d9c",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Target MPS maximum bond dimension: 5\n",
- "Starting fidelity: 0.9926466919924161\n"
- ]
- }
- ],
- "source": [
+ " f\"Target circuit: depth {aqc_target_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Ansatz circuit: depth {aqc_ansatz.depth(lambda x: x.operation.num_qubits == 2)}, with {len(aqc_initial_parameters)} parameters\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Subsequent circuit: depth {subsequent_circuit.depth(lambda x: x.operation.num_qubits == 2)}\"\n",
+ ")\n",
+ "print(\n",
+ " f\"Baseline circuit: depth {baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)} ({baseline_num_trotter_steps} steps, time={total_evolution_time:.4f})\"\n",
+ ")\n",
+ "\n",
+ "# Build target MPS and compute reference expectation value\n",
"simulator_settings = QuimbSimulator(\n",
" quimb.tensor.CircuitMPS, autodiff_backend=\"jax\"\n",
")\n",
- "\n",
- "# Build the matrix-product representation of the state to be approximated by AQC\n",
"aqc_target_mps = tensornetwork_from_circuit(\n",
" aqc_target_circuit, simulator_settings\n",
")\n",
"print(\"Target MPS maximum bond dimension:\", aqc_target_mps.psi.max_bond())\n",
"\n",
- "# Obtains the reference MPS, where we can obtain the exact expectation value by examining the `local_expectation``\n",
- "reference_mps = tensornetwork_from_circuit(\n",
- " reference_circuit, simulator_settings\n",
+ "# For the reference expectation value, we need the full evolution (AQC + subsequent)\n",
+ "# Build a high-accuracy full circuit for MPS reference\n",
+ "full_target_circuit = initial_state_circuit.copy()\n",
+ "full_target_circuit.compose(\n",
+ " generate_time_evolution_circuit(\n",
+ " hamiltonian,\n",
+ " synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),\n",
+ " time=total_evolution_time,\n",
+ " ),\n",
+ " inplace=True,\n",
")\n",
- "reference_expval = reference_mps.local_expectation(\n",
+ "full_target_mps = tensornetwork_from_circuit(\n",
+ " full_target_circuit, simulator_settings\n",
+ ")\n",
+ "exact_expval = full_target_mps.local_expectation(\n",
" quimb.pauli(\"Z\") & quimb.pauli(\"Z\"), (L // 2 - 1, L // 2)\n",
").real.item()\n",
+ "print(f\"Reference expectation value (from MPS): {exact_expval:.6f}\")\n",
"\n",
- "# Compute the starting fidelity\n",
- "good_mps = tensornetwork_from_circuit(aqc_good_circuit, simulator_settings)\n",
- "starting_fidelity = abs(compute_overlap(good_mps, aqc_target_mps)) ** 2\n",
- "print(\"Starting fidelity:\", starting_fidelity)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "56dfc4e4-6b28-4ed1-81da-8b0f4bc99425",
- "metadata": {},
- "source": [
- "To optimize the ansatz parameters, we minimize the `MaximizeStateFidelity` cost function using the L-BFGS optimizer from SciPy, with a stopping criterion set to surpass the fidelity of the initial circuit without AQC-Tensor. This ensures that the compressed circuit has both lower Trotter error and reduced depth."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "id": "af10ef7f-e57d-49a3-abb0-3d51e856c4b0",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2025-04-14 11:48:28.705807 Intermediate result: Fidelity 0.99795851\n",
- "2025-04-14 11:48:28.743265 Intermediate result: Fidelity 0.99822826\n",
- "2025-04-14 11:48:28.776629 Intermediate result: Fidelity 0.99829675\n",
- "2025-04-14 11:48:28.816153 Intermediate result: Fidelity 0.99832474\n",
- "2025-04-14 11:48:28.856437 Intermediate result: Fidelity 0.99836131\n",
- "2025-04-14 11:48:28.896432 Intermediate result: Fidelity 0.99839954\n",
- "2025-04-14 11:48:28.936670 Intermediate result: Fidelity 0.99846517\n",
- "2025-04-14 11:48:28.982069 Intermediate result: Fidelity 0.99865029\n",
- "2025-04-14 11:48:29.026130 Intermediate result: Fidelity 0.99872332\n",
- "2025-04-14 11:48:29.067426 Intermediate result: Fidelity 0.99892359\n",
- "2025-04-14 11:48:29.110742 Intermediate result: Fidelity 0.99900640\n",
- "2025-04-14 11:48:29.161362 Intermediate result: Fidelity 0.99907169\n",
- "2025-04-14 11:48:29.207933 Intermediate result: Fidelity 0.99911423\n",
- "2025-04-14 11:48:29.266772 Intermediate result: Fidelity 0.99918716\n",
- "2025-04-14 11:48:29.331727 Intermediate result: Fidelity 0.99921278\n",
- "2025-04-14 11:48:29.401694 Intermediate result: Fidelity 0.99924853\n",
- "2025-04-14 11:48:29.467980 Intermediate result: Fidelity 0.99928797\n",
- "2025-04-14 11:48:29.533281 Intermediate result: Fidelity 0.99933028\n",
- "2025-04-14 11:48:29.600833 Intermediate result: Fidelity 0.99935757\n",
- "2025-04-14 11:48:29.670816 Intermediate result: Fidelity 0.99938140\n",
- "2025-04-14 11:48:29.736928 Intermediate result: Fidelity 0.99940964\n",
- "2025-04-14 11:48:29.802931 Intermediate result: Fidelity 0.99944051\n",
- "2025-04-14 11:48:29.869177 Intermediate result: Fidelity 0.99946828\n",
- "2025-04-14 11:48:29.940156 Intermediate result: Fidelity 0.99948723\n",
- "2025-04-14 11:48:30.005751 Intermediate result: Fidelity 0.99951011\n",
- "2025-04-14 11:48:30.070853 Intermediate result: Fidelity 0.99954718\n",
- "2025-04-14 11:48:30.139171 Intermediate result: Fidelity 0.99956267\n",
- "2025-04-14 11:48:30.210506 Intermediate result: Fidelity 0.99958949\n",
- "2025-04-14 11:48:30.279647 Intermediate result: Fidelity 0.99960498\n",
- "2025-04-14 11:48:30.348016 Intermediate result: Fidelity 0.99961308\n",
- "2025-04-14 11:48:30.414311 Intermediate result: Fidelity 0.99962894\n",
- "2025-04-14 11:48:30.488910 Intermediate result: Fidelity 0.99964121\n",
- "2025-04-14 11:48:30.561298 Intermediate result: Fidelity 0.99964348\n",
- "2025-04-14 11:48:30.632214 Intermediate result: Fidelity 0.99964860\n",
- "2025-04-14 11:48:30.705703 Intermediate result: Fidelity 0.99965695\n",
- "2025-04-14 11:48:30.775679 Intermediate result: Fidelity 0.99966398\n",
- "2025-04-14 11:48:30.842629 Intermediate result: Fidelity 0.99967816\n",
- "2025-04-14 11:48:30.912357 Intermediate result: Fidelity 0.99968293\n",
- "2025-04-14 11:48:30.979420 Intermediate result: Fidelity 0.99968936\n",
- "2025-04-14 11:48:31.049196 Intermediate result: Fidelity 0.99969223\n",
- "2025-04-14 11:48:31.125391 Intermediate result: Fidelity 0.99970009\n",
- "2025-04-14 11:48:31.201256 Intermediate result: Fidelity 0.99970724\n",
- "2025-04-14 11:48:31.272424 Intermediate result: Fidelity 0.99970987\n",
- "2025-04-14 11:48:31.338907 Intermediate result: Fidelity 0.99971237\n",
- "2025-04-14 11:48:31.404800 Intermediate result: Fidelity 0.99971916\n",
- "2025-04-14 11:48:31.475226 Intermediate result: Fidelity 0.99971940\n",
- "2025-04-14 11:48:31.547746 Intermediate result: Fidelity 0.99972465\n",
- "2025-04-14 11:48:31.622827 Intermediate result: Fidelity 0.99972763\n",
- "2025-04-14 11:48:31.819516 Intermediate result: Fidelity 0.99972894\n",
- "2025-04-14 11:48:33.444538 Intermediate result: Fidelity 0.99972894\n",
- "Done after 50 iterations.\n"
- ]
- }
- ],
- "source": [
- "# Setting values for the optimization\n",
- "aqc_stopping_fidelity = 1\n",
- "aqc_max_iterations = 500\n",
- "\n",
- "stopping_point = 1.0 - aqc_stopping_fidelity\n",
+ "# Optimize ansatz parameters\n",
"objective = MaximizeStateFidelity(\n",
" aqc_target_mps, aqc_ansatz, simulator_settings\n",
")\n",
@@ -1434,9 +985,6 @@
" print(\n",
" f\"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}\"\n",
" )\n",
- " if intermediate_result.fun < stopping_point:\n",
- " # Good enough for now\n",
- " raise StopIteration\n",
"\n",
"\n",
"result = minimize(\n",
@@ -1444,424 +992,151 @@
" aqc_initial_parameters,\n",
" method=\"L-BFGS-B\",\n",
" jac=True,\n",
- " options={\"maxiter\": aqc_max_iterations},\n",
+ " options={\"maxiter\": 500},\n",
" callback=callback,\n",
")\n",
- "if (\n",
- " result.status\n",
- " not in (\n",
- " 0,\n",
- " 1,\n",
- " 99,\n",
- " )\n",
- "): # 0 => success; 1 => max iterations reached; 99 => early termination via StopIteration\n",
+ "if result.status not in (0, 1, 99):\n",
" raise RuntimeError(\n",
" f\"Optimization failed: {result.message} (status={result.status})\"\n",
" )\n",
- "\n",
"print(f\"Done after {result.nit} iterations.\")\n",
- "aqc_final_parameters = result.x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "id": "0e711fcc-7767-411e-bb73-fd9c8408a22b",
- "metadata": {},
- "outputs": [],
- "source": [
- "parameters = [float(param) for param in aqc_final_parameters]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "b1838b8e-81d4-4897-8cbd-dd7daa8bb220",
- "metadata": {},
- "source": [
- "Construct the final circuit for transpilation by assembling the optimized ansatz with the remaining time evolution circuit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "id": "f96b1ab0-f0ed-485f-a763-4ab57d36f410",
- "metadata": {},
- "outputs": [],
- "source": [
- "aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)\n",
- "aqc_final_circuit.compose(subsequent_circuit, inplace=True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 41,
- "id": "579cbef1-a3a8-4916-b840-ab3fcc5c4b33",
- "metadata": {},
- "outputs": [],
- "source": [
- "aqc_comparison_circuit.compose(subsequent_circuit, inplace=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "bb111fb1-07e4-4f0c-ad71-933b04492a23",
- "metadata": {},
- "source": [
- "### Step 2: Optimize problem for quantum hardware execution"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "627dd426-730d-4554-b631-1e9949f46c26",
- "metadata": {},
- "source": [
- "Select the backend."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "771a44a6-b5ba-4b9d-8c64-9a79f6d4ed77",
- "metadata": {},
- "outputs": [],
- "source": [
+ "\n",
+ "# Assemble the final AQC circuit: optimized ansatz + subsequent Trotter step\n",
+ "aqc_final_circuit = aqc_ansatz.assign_parameters(result.x)\n",
+ "aqc_final_circuit.compose(subsequent_circuit, inplace=True)\n",
+ "\n",
+ "# -------------------------Step 2-------------------------\n",
+ "\n",
"service = QiskitRuntimeService()\n",
"backend = service.least_busy(min_num_qubits=127)\n",
- "print(backend)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "cbc5d688-9acf-4fe2-8d58-fea74edb09e8",
- "metadata": {},
- "source": [
- "Transpile the completed circuit on the target hardware, preparing it for execution. The resulting ISA circuit can then be sent for execution on the backend."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "id": "85b4acc0-7121-416d-9bf5-b6d3135ae805",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Observable info: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
- " coeffs=[1.+0.j])\n",
- "Circuit depth: 122\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
+ "print(backend)\n",
+ "\n",
"pass_manager = generate_preset_pass_manager(\n",
" backend=backend, optimization_level=3\n",
")\n",
"isa_circuit = pass_manager.run(aqc_final_circuit)\n",
"isa_observable = observable.apply_layout(isa_circuit.layout)\n",
- "print(\"Observable info:\", isa_observable)\n",
- "print(\"Circuit depth:\", isa_circuit.depth())\n",
- "isa_circuit.draw(\"mpl\", fold=-1, idle_wires=False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "id": "b0d295c7-c816-4683-bb2a-0ce9898e5d88",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Observable info: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
- " coeffs=[1.+0.j])\n",
- "Circuit depth: 158\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 44,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "isa_comparison_circuit = pass_manager.run(aqc_comparison_circuit)\n",
- "isa_comparison_observable = observable.apply_layout(\n",
- " isa_comparison_circuit.layout\n",
+ "print(\n",
+ " \"AQC circuit depth:\",\n",
+ " isa_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
")\n",
- "print(\"Observable info:\", isa_comparison_observable)\n",
- "print(\"Circuit depth:\", isa_comparison_circuit.depth())\n",
- "isa_comparison_circuit.draw(\"mpl\", fold=-1, idle_wires=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f9431bec-66d1-44e3-a77d-01ca9e03e523",
- "metadata": {},
- "source": [
- "### Step 3: Execute using Qiskit primitives\n",
"\n",
- "In this step, we run the transpiled circuit on quantum hardware (or a simulated backend) using `EstimatorV2` from `qiskit_ibm_runtime` to measure the specified observable. The job result will provide valuable insights into the circuit’s performance on the target hardware.\n",
+ "# Also transpile the baseline Trotter circuit (4 Trotter steps, no AQC)\n",
+ "isa_baseline_circuit = pass_manager.run(baseline_circuit)\n",
+ "isa_baseline_observable = observable.apply_layout(isa_baseline_circuit.layout)\n",
+ "print(\n",
+ " \"Baseline Trotter circuit depth:\",\n",
+ " isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2),\n",
+ ")\n",
"\n",
- "For this larger-scale example, we will explore how to utilize `EstimatorOptions` to better manage and control the parameters of our hardware experiment. While these settings are optional, they are useful for tracking experiment parameters and refining execution options for optimal results.\n",
+ "# -------------------------Step 3-------------------------\n",
"\n",
- "For a complete list of available execution options, refer to the [qiskit-ibm-runtime documentation](/docs/api/qiskit-ibm-runtime/options-estimator-options)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "id": "cf449353-f392-4248-b6ad-5af9107c1fff",
- "metadata": {},
- "outputs": [],
- "source": [
- "twirling_options = {\n",
- " \"enable_gates\": True,\n",
- " \"enable_measure\": True,\n",
- " \"num_randomizations\": 300,\n",
- " \"shots_per_randomization\": 100,\n",
- " \"strategy\": \"active\",\n",
- "}\n",
- "\n",
- "zne_options = {\n",
- " \"amplifier\": \"gate_folding\",\n",
- " \"noise_factors\": [1, 2, 3],\n",
- " \"extrapolated_noise_factors\": list(np.linspace(0, 3, 31)),\n",
- " \"extrapolator\": [\"exponential\", \"linear\", \"fallback\"],\n",
- "}\n",
- "\n",
- "meas_learning_options = {\n",
- " \"num_randomizations\": 512,\n",
- " \"shots_per_randomization\": 512,\n",
- "}\n",
- "\n",
- "resilience_options = {\n",
- " \"measure_mitigation\": True,\n",
- " \"zne_mitigation\": True,\n",
- " \"zne\": zne_options,\n",
- " \"measure_noise_learning\": meas_learning_options,\n",
- "}\n",
- "\n",
- "estimator_options = {\n",
- " \"resilience\": resilience_options,\n",
- " \"twirling\": twirling_options,\n",
- "}\n",
- "\n",
- "estimator = Estimator(backend, options=estimator_options)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "id": "ea2a1425-a49b-4b31-b019-abbee4fdf690",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Job ID: czyjx6crxz8g008f63r0\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(), stds=np.ndarray(), evs_noise_factors=np.ndarray(), stds_noise_factors=np.ndarray(), ensemble_stds_noise_factors=np.ndarray(), evs_extrapolated=np.ndarray(), stds_extrapolated=np.ndarray()), metadata={'shots': 30000, 'target_precision': 0.005773502691896258, 'circuit_metadata': {}, 'resilience': {'zne': {'extrapolator': 'exponential'}}, 'num_randomizations': 300})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': True, 'enable_measure': True, 'num_randomizations': 300, 'shots_per_randomization': 100, 'interleave_randomizations': True, 'strategy': 'active'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': True, 'pec_mitigation': False, 'zne': {'noise_factors': [1, 2, 3], 'extrapolator': ['exponential', 'linear', 'fallback'], 'extrapolated_noise_factors': [0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9, 1, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001, 1.5, 1.6, 1.7000000000000002, 1.8, 1.9000000000000001, 2, 2.1, 2.2, 2.3000000000000003, 2.4000000000000004, 2.5, 2.6, 2.7, 2.8000000000000003, 2.9000000000000004, 3]}}, 'version': 2})"
- ]
- },
- "execution_count": 46,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "job = estimator.run([(isa_circuit, isa_observable)])\n",
- "print(\"Job ID:\", job.job_id())\n",
- "job.result()"
+ "# Submit both circuits in a single job\n",
+ "estimator = Estimator(backend)\n",
+ "estimator.options.environment.job_tags = [\"TUT_AQCTE\"]\n",
+ "\n",
+ "job = estimator.run(\n",
+ " [\n",
+ " (isa_circuit, isa_observable),\n",
+ " (isa_baseline_circuit, isa_baseline_observable),\n",
+ " ]\n",
+ ")\n",
+ "print(\"Job ID:\", job.job_id())"
]
},
{
"cell_type": "code",
- "execution_count": 47,
- "id": "4f7d9e7d-9da1-4cc3-ae09-0e3613c5479a",
+ "execution_count": 15,
+ "id": "a4dc23fd-494e-46cb-a8f5-d1cd444b96f4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Job Comparison ID: czyjx6crxz8g008f63r0\n"
+ "Exact (MPS): -0.7387\n",
+ "Baseline Trotter: -0.5955, |Δ| = 0.1432\n",
+ "AQC (3+1): -0.6734, |Δ| = 0.0653\n"
]
},
{
"data": {
"text/plain": [
- "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(), stds=np.ndarray(), evs_noise_factors=np.ndarray(), stds_noise_factors=np.ndarray(), ensemble_stds_noise_factors=np.ndarray(), evs_extrapolated=np.ndarray(), stds_extrapolated=np.ndarray()), metadata={'shots': 30000, 'target_precision': 0.005773502691896258, 'circuit_metadata': {}, 'resilience': {'zne': {'extrapolator': 'exponential'}}, 'num_randomizations': 300})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': True, 'enable_measure': True, 'num_randomizations': 300, 'shots_per_randomization': 100, 'interleave_randomizations': True, 'strategy': 'active'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': True, 'pec_mitigation': False, 'zne': {'noise_factors': [1, 2, 3], 'extrapolator': ['exponential', 'linear', 'fallback'], 'extrapolated_noise_factors': [0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9, 1, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001, 1.5, 1.6, 1.7000000000000002, 1.8, 1.9000000000000001, 2, 2.1, 2.2, 2.3000000000000003, 2.4000000000000004, 2.5, 2.6, 2.7, 2.8000000000000003, 2.9000000000000004, 3]}}, 'version': 2})"
+ ""
]
},
- "execution_count": 47,
"metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "job_comparison = estimator.run([(isa_comparison_circuit, isa_observable)])\n",
- "print(\"Job Comparison ID:\", job.job_id())\n",
- "job_comparison.result()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "17ced13b-a3d3-4ded-92a6-b978508dd27a",
- "metadata": {},
- "source": [
- "### Step 4: Post-process and return result in desired classical format\n",
- "Here, no reconstruction is needed, like before; we can directly access the expectation value from the execution output to examine the result."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "id": "5b2e2d3e-bebb-44a4-bbdb-881ffc2749e5",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Exact: \t-0.5888\n",
- "AQC: \t-0.4809, |∆| = 0.1078\n",
- "AQC Comparison:\t1.1764, |∆| = 1.7652\n"
- ]
+ "output_type": "display_data"
}
],
"source": [
- "# AQC results\n",
- "hw_results = job.result()\n",
- "hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]\n",
- "hw_expvals = [\n",
- " pub_result_data[\"evs\"].tolist() for pub_result_data in hw_results_dicts\n",
- "]\n",
- "aqc_expval = hw_expvals[0]\n",
+ "# -------------------------Step 4-------------------------\n",
"\n",
- "# AQC comparison results\n",
- "hw_comparison_results = job_comparison.result()\n",
- "hw_comparison_results_dicts = [\n",
- " pub_result.data.__dict__ for pub_result in hw_comparison_results\n",
- "]\n",
- "hw_comparison_expvals = [\n",
- " pub_result_data[\"evs\"].tolist()\n",
- " for pub_result_data in hw_comparison_results_dicts\n",
- "]\n",
- "aqc_compare_expval = hw_comparison_expvals[0]\n",
+ "hw_results = job.result()\n",
+ "aqc_expval = hw_results[0].data.evs.tolist()\n",
+ "baseline_expval = hw_results[1].data.evs.tolist()\n",
"\n",
- "print(f\"Exact: \\t{reference_expval:.4f}\")\n",
+ "print(f\"Exact (MPS): {exact_expval:.4f}\")\n",
"print(\n",
- " f\"AQC: \\t{aqc_expval:.4f}, |∆| = {np.abs(reference_expval- aqc_expval):.4f}\"\n",
+ " f\"Baseline Trotter: {baseline_expval:.4f}, |\\u0394| = {np.abs(exact_expval - baseline_expval):.4f}\"\n",
")\n",
"print(\n",
- " f\"AQC Comparison:\\t{aqc_compare_expval:.4f}, |∆| = {np.abs(reference_expval- aqc_compare_expval):.4f}\"\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f5ba5634-1689-457a-b7c7-adf3ca8e1d41",
- "metadata": {},
- "source": [
- "Plot the results of the AQC, comparison, and exact circuits for the 50-site XXZ model."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "id": "01889c4d-16a4-458a-9211-08be8bcae1e4",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "labels = [\"AQC Result\", \"AQC Comparison Result\"]\n",
- "values = [abs(aqc_expval), abs(aqc_compare_expval)]\n",
+ " f\"AQC (3+1): {aqc_expval:.4f}, |\\u0394| = {np.abs(exact_expval - aqc_expval):.4f}\"\n",
+ ")\n",
+ "\n",
+ "labels = [\n",
+ " f\"Baseline Trotter\\n({baseline_num_trotter_steps} steps, depth {isa_baseline_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
+ " f\"AQC (3+1)\\n(depth {isa_circuit.depth(lambda x: x.operation.num_qubits == 2)})\",\n",
+ "]\n",
+ "values = [baseline_expval, aqc_expval]\n",
+ "colors = [\"tab:orange\", \"tab:blue\"]\n",
"\n",
- "plt.figure(figsize=(10, 6))\n",
- "bars = plt.bar(labels, values, color=[\"tab:blue\", \"tab:purple\"])\n",
+ "plt.figure(figsize=(8, 5))\n",
+ "bars = plt.bar(labels, values, color=colors, width=0.5)\n",
"plt.axhline(\n",
- " y=abs(reference_expval), color=\"red\", linestyle=\"--\", label=\"Exact Result\"\n",
+ " y=exact_expval,\n",
+ " color=\"tab:green\",\n",
+ " linestyle=\"--\",\n",
+ " linewidth=2,\n",
+ " label=f\"Exact ({exact_expval:.4f})\",\n",
+ ")\n",
+ "plt.ylabel(\"Expected Value\")\n",
+ "plt.title(\n",
+ " \"AQC-Tensor (3 compressed + 1 uncompressed) vs Baseline Trotter (50-site XXZ)\"\n",
")\n",
- "plt.xlabel(\"Results\")\n",
- "plt.ylabel(\"Absolute Expected Value\")\n",
- "plt.title(\"AQC Result vs AQC Comparison Result (Absolute Values)\")\n",
"plt.legend()\n",
"for bar in bars:\n",
" y_val = bar.get_height()\n",
" plt.text(\n",
" bar.get_x() + bar.get_width() / 2.0,\n",
" y_val,\n",
- " round(y_val, 2),\n",
- " va=\"bottom\",\n",
+ " f\"{y_val:.4f}\",\n",
+ " ha=\"center\",\n",
+ " va=\"bottom\" if y_val >= 0 else \"top\",\n",
" )\n",
- "\n",
+ "plt.axhline(y=0, color=\"black\", linewidth=0.3)\n",
+ "plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
- "id": "45f512f7-9233-4f1f-8f24-cb3524567135",
- "metadata": {},
- "source": [
- "## Conclusion\n",
- "\n",
- "This tutorial demonstrated how to use Approximate Quantum Compilation with tensor networks (AQC-Tensor) to compress and optimize circuits for simulating quantum dynamics at scale. Utilizing both small and large Heisenberg models, we applied AQC-Tensor to reduce the circuit depth required for Trotterized time evolution. By generating a parametrized ansatz from a simplified Trotter circuit and optimizing it with matrix product state (MPS) techniques, we achieved a low-depth approximation of the target evolution that is both accurate and efficient.\n",
- "\n",
- "The workflow here highlights the key advantages of AQC-Tensor for scaling quantum simulations:\n",
- "\n",
- "- **Significant circuit compression**: AQC-Tensor reduced the circuit depth needed for complex time evolution, enhancing its feasibility on current devices.\n",
- "- **Efficient optimization**: The MPS approach provided a robust framework for parameter optimization, balancing fidelity with computational efficiency.\n",
- "- **Hardware-ready execution**: Transpiling the final optimized circuit ensured it met the constraints of the target quantum hardware.\n",
- "\n",
- "As larger quantum devices and more advanced algorithms emerge, techniques like AQC-Tensor will become essential for running complex quantum simulations on near-term hardware, demonstrating promising progress in managing depth and fidelity for scalable quantum applications."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3cc40a5a-4b55-45e8-a4f1-df45b9e37abd",
+ "id": "278bc002",
"metadata": {},
"source": [
- "## Tutorial survey\n",
- "\n",
- "Please take this short survey to provide feedback on this tutorial. Your insights will help us improve our content offerings and user experience.\n",
+ "## Next steps\n",
"\n",
- "[Link to survey](https://your.feedback.ibm.com/jfe/form/SV_eF01c2sfeSt6cqq)"
+ "\n",
+ "If you found this work interesting, you might be interested in the following material:\n",
+ "- [AQC-Tensor addon documentation](https://qiskit.github.io/qiskit-addon-aqc-tensor/) — includes the related **unitary AQC** technique, which optimizes parametrized circuits to approximate a target unitary operator rather than a prepared state\n",
+ "- [Error mitigation and suppression techniques](/docs/guides/error-mitigation-and-suppression-techniques)\n",
+ "- [Combine error mitigation techniques](/docs/tutorials/combine-error-mitigation-techniques)\n",
+ ""
]
}
],
"metadata": {
+ "description": "Learn how to use AQC-Tensor to compress Trotterized time-evolution circuits for efficient execution on quantum hardware.",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
@@ -1878,8 +1153,9 @@
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3"
- }
+ },
+ "title": "Approximate quantum compilation for time evolution circuits"
},
"nbformat": 4,
- "nbformat_minor": 4
+ "nbformat_minor": 5
}
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/01889c4d-16a4-458a-9211-08be8bcae1e4-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/01889c4d-16a4-458a-9211-08be8bcae1e4-0.avif
deleted file mode 100644
index 10c9c06980a..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/01889c4d-16a4-458a-9211-08be8bcae1e4-0.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/087fff8d-98b9-4f9a-8004-01a3b0166e12-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/087fff8d-98b9-4f9a-8004-01a3b0166e12-1.avif
deleted file mode 100644
index 997b32560a3..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/087fff8d-98b9-4f9a-8004-01a3b0166e12-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/1ea0e102-23d5-4e6e-8ef8-e82843452b19-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/1ea0e102-23d5-4e6e-8ef8-e82843452b19-1.avif
deleted file mode 100644
index a5a7647d55e..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/1ea0e102-23d5-4e6e-8ef8-e82843452b19-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/527dbada-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/527dbada-1.avif
new file mode 100644
index 00000000000..7447885d25e
Binary files /dev/null and b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/527dbada-1.avif differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/5f7b36a6-3666-4223-9c5d-d92bca741ad2-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/5f7b36a6-3666-4223-9c5d-d92bca741ad2-0.avif
deleted file mode 100644
index 5fcf6474022..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/5f7b36a6-3666-4223-9c5d-d92bca741ad2-0.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/77c39ba8-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/77c39ba8-0.avif
new file mode 100644
index 00000000000..d188122c3d4
Binary files /dev/null and b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/77c39ba8-0.avif differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b9e81c51-dc6f-4237-9aca-e1384f1897bc-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/78f2665e-1.avif
similarity index 96%
rename from public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b9e81c51-dc6f-4237-9aca-e1384f1897bc-0.avif
rename to public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/78f2665e-1.avif
index 48dcdda793a..02f8f3ef8d4 100644
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b9e81c51-dc6f-4237-9aca-e1384f1897bc-0.avif and b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/78f2665e-1.avif differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/7c2e5fe7-21ce-461d-adaa-776f8d882163-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/7c2e5fe7-21ce-461d-adaa-776f8d882163-1.avif
deleted file mode 100644
index f07c65109d4..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/7c2e5fe7-21ce-461d-adaa-776f8d882163-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/813c9ced-6a2e-4345-bffc-7dae938e2015-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/813c9ced-6a2e-4345-bffc-7dae938e2015-0.avif
deleted file mode 100644
index 00423797a62..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/813c9ced-6a2e-4345-bffc-7dae938e2015-0.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/83039f82-97cb-4613-86c9-a8faf0839a02-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/83039f82-97cb-4613-86c9-a8faf0839a02-0.avif
deleted file mode 100644
index a47b78269dd..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/83039f82-97cb-4613-86c9-a8faf0839a02-0.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/85b4acc0-7121-416d-9bf5-b6d3135ae805-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/85b4acc0-7121-416d-9bf5-b6d3135ae805-1.avif
deleted file mode 100644
index 5879f9ba26f..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/85b4acc0-7121-416d-9bf5-b6d3135ae805-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/86ba26ff-0bfa-47d0-b5ee-8944a8ddf274-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/86ba26ff-0bfa-47d0-b5ee-8944a8ddf274-0.avif
deleted file mode 100644
index 184e705c4a0..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/86ba26ff-0bfa-47d0-b5ee-8944a8ddf274-0.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/a4dc23fd-494e-46cb-a8f5-d1cd444b96f4-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/a4dc23fd-494e-46cb-a8f5-d1cd444b96f4-1.avif
new file mode 100644
index 00000000000..7adf2ca996f
Binary files /dev/null and b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/a4dc23fd-494e-46cb-a8f5-d1cd444b96f4-1.avif differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b0d295c7-c816-4683-bb2a-0ce9898e5d88-1.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b0d295c7-c816-4683-bb2a-0ce9898e5d88-1.avif
deleted file mode 100644
index 1cf27fc2d76..00000000000
Binary files a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/b0d295c7-c816-4683-bb2a-0ce9898e5d88-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/e09e40de-0.avif b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/e09e40de-0.avif
new file mode 100644
index 00000000000..95480631fe8
Binary files /dev/null and b/public/docs/images/tutorials/approximate-quantum-compilation-for-time-evolution/extracted-outputs/e09e40de-0.avif differ