Skip to main content
IBM Quantum Platform

Crear una plantilla de función Qiskit para la simulación hamiltoniana

Esta plantilla encapsula un flujo de trabajo para simular la evolución temporal de un estado inicial frente a un hamiltoniano basado en espín definido por el usuario y devuelve un conjunto de valores esperados especificados utilizando el complemento AQC-Tensor Qiskit.

Esta plantilla está estructurada como un patrón Qiskit con los siguientes pasos:

1. Recopilar información y analizar el problema

Esta sección toma como entrada el Hamiltoniano a simular, un estado inicial en forma de QuantumCircuit, un conjunto de observables para estimar valores de expectativa, y una especificación de opciones para el addon AQC. Este paso valida que todos los datos de entrada requeridos están presentes y que están en el formato correcto.

A continuación, los argumentos de entrada se utilizan para construir los circuitos cuánticos y operadores pertinentes para el flujo de trabajo. Se crea un circuito de destino y se encuentra una representación de estado de producto matricial de este circuito utilizando el complemento AQC. A continuación, se genera un circuito ansatz y se optimiza utilizando métodos de redes tensoriales, produciendo un circuito final que ejecuta el resto de la evolución temporal.

2. Preparar los circuitos generados para su ejecución

Los circuitos generados a partir del addon AQC se transpilan para ejecutarse en el backend elegido. Se crea una instancia de EstimatorV2 instancia se crea con un conjunto predeterminado de opciones de mitigación de errores para gestionar la ejecución del circuito.

3. Ejecución

Por último, el circuito ansatz se transpila y ejecuta en una QPU y recopila estimaciones para todos los valores de expectativa especificados, que se devuelven en un formato serializable para que el usuario pueda acceder a ellas.


Escribir la plantilla de función

En primer lugar, escriba una plantilla de función para la simulación hamiltoniana que utilice el complemento AQC-Tensor Qiskit para asignar la descripción del problema a un circuito de profundidad reducida para su ejecución en hardware.

Si descargas esta página y la abres en un editor de código, verás que algunas de las celdas de código contienen el comando mágico %%writefile. Este comando mágico guarda el código en ./source_files/template_hamiltonian_simulation.py, que es la plantilla de función que puedes subir a y ejecutar de forma remota con Qiskit Serverless.

Recopilar y validar las entradas

Empiece por obtener las entradas para la plantilla. Este ejemplo tiene entradas específicas de dominio relevantes para la simulación hamiltoniana (como el hamiltoniano y el observable) y opciones específicas de capacidad (como cuánto desea comprimir las capas iniciales del circuito Trotter utilizando AQC-Tensor, u opciones avanzadas para ajustar con precisión la supresión y mitigación de errores más allá de los valores predeterminados que forman parte de este ejemplo).

./source_files/template_hamiltonian_simulation.py
from qiskit import QuantumCircuit
from qiskit_serverless import get_arguments, save_result


# Extract parameters from arguments
#
# Do this at the top of the program so it fails early if any required arguments
# are missing or invalid.

arguments = get_arguments()

dry_run = arguments.get("dry_run", False)
backend_name = arguments["backend_name"]

aqc_evolution_time = arguments["aqc_evolution_time"]
aqc_ansatz_num_trotter_steps = arguments["aqc_ansatz_num_trotter_steps"]
aqc_target_num_trotter_steps = arguments["aqc_target_num_trotter_steps"]

remainder_evolution_time = arguments["remainder_evolution_time"]
remainder_num_trotter_steps = arguments["remainder_num_trotter_steps"]

# Stop if this fidelity is achieved
aqc_stopping_fidelity = arguments.get("aqc_stopping_fidelity", 1.0)
# Stop after this number of iterations, even if stopping fidelity is not achieved
aqc_max_iterations = arguments.get("aqc_max_iterations", 500)

hamiltonian = arguments["hamiltonian"]
observable = arguments["observable"]
initial_state = arguments.get("initial_state",
    QuantumCircuit(hamiltonian.num_qubits))
./source_files/template_hamiltonian_simulation.py (appended)
import numpy as np
import json
from mergedeep import merge


# Configure `EstimatorOptions`, to control the parameters
# of the hardware experiment
#
# Set default options
estimator_default_options = {
    "resilience": {
        "measure_mitigation": True,
        "zne_mitigation": True,
        "zne": {
            "amplifier": "gate_folding",
            "noise_factors": [1, 2, 3],
            "extrapolated_noise_factors": list(np.linspace(0, 3, 31)),
            "extrapolator": ["exponential", "linear", "fallback"],
        },
        "measure_noise_learning": {
            "num_randomizations": 512,
            "shots_per_randomization": 512,
        },
    },
    "twirling": {
        "enable_gates": True,
        "enable_measure": True,
        "num_randomizations": 300,
        "shots_per_randomization": 100,
        "strategy": "active",
    },
}
# Merge with user-provided options
estimator_options = merge(
    arguments.get("estimator_options", {}), estimator_default_options
)

Cuando la plantilla de funciones se está ejecutando, es útil devolver información en los registros mediante sentencias print, para poder evaluar mejor el progreso de la carga de trabajo. A continuación se muestra un sencillo ejemplo de impresión de estimator_options para que quede constancia de las opciones reales del Estimador utilizadas. Hay muchos más ejemplos similares a lo largo del programa para informar del progreso durante la ejecución, incluyendo el valor de la función objetivo durante el componente iterativo de AQC-Tensor, y la profundidad de dos qubits del circuito final de arquitectura de conjunto de instrucciones (ISA) destinado a la ejecución en hardware.

./source_files/template_hamiltonian_simulation.py (appended)
print("estimator_options =", json.dumps(estimator_options, indent=4))

Validar las entradas

Un aspecto importante para garantizar que la plantilla pueda reutilizarse en toda una serie de entradas es la validación de las mismas. El siguiente código es un ejemplo de verificación de que la fidelidad de parada durante AQC-Tensor se ha especificado correctamente y, si no es así, devuelve un mensaje de error informativo sobre cómo solucionar el error.

./source_files/template_hamiltonian_simulation.py (appended)
# Perform parameter validation

if not 0.0 < aqc_stopping_fidelity <= 1.0:
    raise ValueError(
        f"Invalid stopping fidelity: {aqc_stopping_fidelity}.  "
        f"It must be a positive float no greater than 1."
    )

Prepare las salidas de la función

En primer lugar, prepare un diccionario que contenga todas las salidas de las plantillas de funciones. Las claves se irán añadiendo a este diccionario a lo largo del flujo de trabajo, y se devuelve al final del programa.

./source_files/template_hamiltonian_simulation.py (appended)
output = {}

Mapea el problema y preprocesa el circuito con AQC

La optimización AQC-Tensor se produce en el paso 1 de un patrón Qiskit. En primer lugar, se construye un estado objetivo. En este ejemplo, se construye a partir de un circuito objetivo que evoluciona el mismo Hamiltoniano durante el mismo periodo de tiempo que la parte AQC. A continuación, se genera un ansatz a partir de un circuito equivalente pero con menos pasos de Trotter. En la parte principal del algoritmo AQC, ese ansatz se acerca iterativamente al estado objetivo. Por último, el resultado se combina con el resto de pasos Trotter necesarios para alcanzar el tiempo de evolución deseado.

Observe los ejemplos adicionales de registro incorporados en el siguiente código.

./source_files/template_hamiltonian_simulation.py (appended)
import os
os.environ["NUMBA_CACHE_DIR"] = "/data"

import datetime
import quimb.tensor
from scipy.optimize import OptimizeResult, minimize
from qiskit.synthesis import SuzukiTrotter
from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit
from qiskit_addon_aqc_tensor.ansatz_generation import (
    generate_ansatz_from_circuit,
    AnsatzBlock,
)
from qiskit_addon_aqc_tensor.simulation import (
    tensornetwork_from_circuit,
    compute_overlap,
)
from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator
from qiskit_addon_aqc_tensor.objective import OneMinusFidelity

print("Hamiltonian:", hamiltonian)
print("Observable:", observable)
simulator_settings = QuimbSimulator(quimb.tensor.CircuitMPS, autodiff_backend="jax")

# Construct the AQC target circuit
aqc_target_circuit = initial_state.copy()
if aqc_evolution_time:
    aqc_target_circuit.compose(
        generate_time_evolution_circuit(
            hamiltonian,
            synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),
            time=aqc_evolution_time,
        ),
        inplace=True,
    )

# Construct matrix-product state representation of the AQC target state
aqc_target_mps = tensornetwork_from_circuit(aqc_target_circuit, simulator_settings)
print("Target MPS maximum bond dimension:", aqc_target_mps.psi.max_bond())
output["target_bond_dimension"] = aqc_target_mps.psi.max_bond()

# Generate an ansatz and initial parameters from a Trotter circuit with fewer steps
aqc_good_circuit = initial_state.copy()
if aqc_evolution_time:
    aqc_good_circuit.compose(
        generate_time_evolution_circuit(
            hamiltonian,
            synthesis=SuzukiTrotter(reps=aqc_ansatz_num_trotter_steps),
            time=aqc_evolution_time,
        ),
        inplace=True,
    )
aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(aqc_good_circuit)
print("Number of AQC parameters:", len(aqc_initial_parameters))
output["num_aqc_parameters"] = len(aqc_initial_parameters)

# Calculate the fidelity of ansatz circuit vs. the target state, before optimization
good_mps = tensornetwork_from_circuit(aqc_good_circuit, simulator_settings)
starting_fidelity = abs(compute_overlap(good_mps, aqc_target_mps)) ** 2
print("Starting fidelity of AQC portion:", starting_fidelity)
output["aqc_starting_fidelity"] = starting_fidelity

# Optimize the ansatz parameters by using MPS calculations
def callback(intermediate_result: OptimizeResult):
    fidelity = 1 - intermediate_result.fun
    print(f"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}")
    if intermediate_result.fun < stopping_point:
        raise StopIteration


objective = OneMinusFidelity(aqc_target_mps, aqc_ansatz, simulator_settings)
stopping_point = 1.0 - aqc_stopping_fidelity

result = minimize(
    objective,
    aqc_initial_parameters,
    method="L-BFGS-B",
    jac=True,
    options={"maxiter": aqc_max_iterations},
    callback=callback,
)
if result.status not in (
    0,
    1,
    99,
):  # 0 => success; 1 => max iterations reached;
    # 99 => early termination via StopIteration
    raise RuntimeError(
        f"Optimization failed: {result.message} (status={result.status})"
    )
print(f"Done after {result.nit} iterations.")
output["num_iterations"] = result.nit
aqc_final_parameters = result.x
output["aqc_final_parameters"] = list(aqc_final_parameters)

# Construct an optimized circuit for initial portion of time evolution
aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)

# Calculate fidelity after optimization
aqc_final_mps = tensornetwork_from_circuit(aqc_final_circuit, simulator_settings)
aqc_fidelity = abs(compute_overlap(aqc_final_mps, aqc_target_mps)) ** 2
print("Fidelity of AQC portion:", aqc_fidelity)
output["aqc_fidelity"] = aqc_fidelity

# Construct final circuit, with remainder of time evolution
final_circuit = aqc_final_circuit.copy()
if remainder_evolution_time:
    remainder_circuit = generate_time_evolution_circuit(
        hamiltonian,
        synthesis=SuzukiTrotter(reps=remainder_num_trotter_steps),
        time=remainder_evolution_time,
    )
    final_circuit.compose(remainder_circuit, inplace=True)

Optimizar el circuito final para la ejecución

Después de la parte AQC del flujo de trabajo, el final_circuit se transpila para el hardware como de costumbre.

./source_files/template_hamiltonian_simulation.py (appended)
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.backend(backend_name)

# Transpile PUBs (circuits and observables) to match ISA
pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=3)
isa_circuit = pass_manager.run(final_circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)

isa_2qubit_depth = isa_circuit.depth(lambda x: x.operation.num_qubits == 2)
print("ISA circuit two-qubit depth:", isa_2qubit_depth)
output["twoqubit_depth"] = isa_2qubit_depth

Salga antes de tiempo si utiliza el modo de simulación

Si se ha seleccionado el modo de funcionamiento en seco, el programa se detiene antes de ejecutarse en el hardware. Esto puede ser útil si, por ejemplo, desea inspeccionar primero la profundidad de dos qubits del circuito ISA antes de decidir ejecutarlo en hardware.

./source_files/template_hamiltonian_simulation.py (appended)
# Exit now if dry run; don't execute on hardware
if dry_run:
    import sys

    print("Exiting before hardware execution since `dry_run` is True.")
    save_result(output)
    sys.exit(0)

Ejecutar el circuito en hardware

./source_files/template_hamiltonian_simulation.py (appended)
# ## Step 3: Execute quantum experiments on backend
from qiskit_ibm_runtime import EstimatorV2 as Estimator


estimator = Estimator(backend, options=estimator_options)

# Submit the underlying Estimator job. Note that this is not the
# actual function job.
job = estimator.run([(isa_circuit, isa_observable)])
print("Job ID:", job.job_id())
output["job_id"] = job.job_id()

# Wait until job is complete
hw_results = job.result()
hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]

# Save hardware results to serverless output dictionary
output["hw_results"] = hw_results_dicts

# Reorganize expectation values
hw_expvals = [pub_result_data["evs"].tolist()
    for pub_result_data in hw_results_dicts]

# Save expectation values to Qiskit Serverless
print("Hardware expectation values", hw_expvals)
output["hw_expvals"] = hw_expvals[0]

Guardar la salida

Esta plantilla de función devuelve la salida relevante a nivel de dominio para este flujo de trabajo de simulación Hamiltoniana (valores de expectativa) además de metadatos importantes generados a lo largo del camino.

./source_files/template_hamiltonian_simulation.py (appended)
save_result(output)

Implementa la función en IBM Quantum Platform

En el apartado anterior se ha creado un programa que se ejecutará de forma remota. El código de esta sección sube ese programa a Qiskit Serverless.

Utilice qiskit-ibm-catalog para autenticarse en QiskitServerless con su clave API, que encontrará en el panel de control de la plataforma Quantum IBM, y cargue el programa.

Opcionalmente, puede utilizar save_account() para guardar sus credenciales (consulte la guía Configurar su cuenta de IBM Cloud ). Tenga en cuenta que esto escribe sus credenciales en el mismo archivo que QiskitRuntimeService.save_account().

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

# Authenticate to the remote cluster and submit the pattern
# for remote execution
serverless = QiskitServerless()

Este programa tiene dependencias personalizadas de pip . Añádalos a una matriz dependencies cuando construya la instancia QiskitFunction :

template = QiskitFunction(
    title="template_hamiltonian_simulation",
    entrypoint="template_hamiltonian_simulation.py",
    working_dir="./source_files/",
    dependencies=[
        "qiskit-addon-utils~=0.1.0",
        "qiskit-addon-aqc-tensor[quimb-jax]~=0.1.2",
        "mergedeep==1.3.4",
    ],
)
serverless.upload(template)

Output:

QiskitFunction(template_hamiltonian_simulation)

Por último, compruebe si el programa se ha cargado correctamente, utilice serverless.list():

serverless.list()

Output:

 QiskitFunction(template_hamiltonian_simulation),


Ejecutar la plantilla de función de forma remota

La plantilla de la función se ha cargado, por lo que se puede ejecutar de forma remota con Qiskit Serverless. En primer lugar, cargue la plantilla por su nombre:

template = serverless.load("template_hamiltonian_simulation")

A continuación, ejecute la plantilla con las entradas a nivel de dominio para la simulación hamiltoniana. Este ejemplo especifica un modelo XXZ de 50 qubits con acoplamientos aleatorios, y un estado inicial y observable.

from itertools import chain
import numpy as np
from qiskit.quantum_info import SparsePauliOp

L = 50

# Generate the edge list for this spin-chain
edges = [(i, i + 1) for i in range(L - 1)]
# Generate an edge-coloring so we can make hw-efficient circuits
edges = edges[::2] + edges[1::2]

# Generate random coefficients for our XXZ Hamiltonian
np.random.seed(0)
Js = np.random.rand(L - 1) + 0.5 * np.ones(L - 1)

hamiltonian = SparsePauliOp.from_sparse_list(
    chain.from_iterable(
        [
            [
                ("XX", (i, j), Js[i] / 2),
                ("YY", (i, j), Js[i] / 2),
                ("ZZ", (i, j), Js[i]),
            ]
            for i, j in edges
        ]
    ),
    num_qubits=L,
)
observable = SparsePauliOp.from_sparse_list(
    [("ZZ", (L // 2 - 1, L // 2), 1.0)], num_qubits=L
)
from qiskit import QuantumCircuit

initial_state = QuantumCircuit(L)
for i in range(L):
    if i % 2:
        initial_state.x(i)
job = template.run(
    dry_run=True,
    initial_state=initial_state,
    hamiltonian=hamiltonian,
    observable=observable,
    backend_name="ibm_fez",
    estimator_options={},
    aqc_evolution_time=0.2,
    aqc_ansatz_num_trotter_steps=1,
    aqc_target_num_trotter_steps=32,
    remainder_evolution_time=0.2,
    remainder_num_trotter_steps=4,
    aqc_max_iterations=300,
)
print(job.job_id)

Output:

853b0edb-d63f-4629-be71-398b6dcf33cb

Comprueba el estado del trabajo:

job.status()

Output:

'QUEUED'

Una vez ejecutada la tarea, puede recuperar los registros creados a partir de las salidas de print() . Éstas pueden proporcionar información procesable sobre el progreso del flujo de trabajo de la simulación hamiltoniana. Por ejemplo, el valor de la función objetivo durante el componente iterativo de AQC, o la profundidad de dos qubits del circuito ISA final destinado a la ejecución en hardware.

print(job.logs())

Output:

No logs yet.

Bloquea el resto del programa hasta que el resultado esté disponible. Una vez realizado el trabajo, puedes recuperar los resultados. Entre ellos se incluye el resultado a nivel de dominio de la simulación hamiltoniana (valor de expectativa) y metadatos útiles.

result = job.result()

del result[
    "aqc_final_parameters"
]  # the list is too long to conveniently display here
result

Output:

{'target_bond_dimension': 5,
 'num_aqc_parameters': 816,
 'aqc_starting_fidelity': 0.9914382555614002,
 'num_iterations': 72,
 'aqc_fidelity': 0.9998108844412502,
 'twoqubit_depth': 33}

Una vez finalizada la tarea, estará disponible toda la salida de registro.

print(job.logs())

Output:

2024-12-17 14:50:15,580	INFO job_manager.py:531 -- Runtime env is setting up.
estimator_options = {
    "resilience": {
        "measure_mitigation": true,
        "zne_mitigation": true,
        "zne": {
            "amplifier": "gate_folding",
            "noise_factors": [
                1,
                2,
                3
            ],
            "extrapolated_noise_factors": [
                0.0,
                0.1,
                0.2,
                0.30000000000000004,
                0.4,
                0.5,
                0.6000000000000001,
                0.7000000000000001,
                0.8,
                0.9,
                1.0,
                1.1,
                1.2000000000000002,
                1.3,
                1.4000000000000001,
                1.5,
                1.6,
                1.7000000000000002,
                1.8,
                1.9000000000000001,
                2.0,
                2.1,
                2.2,
                2.3000000000000003,
                2.4000000000000004,
                2.5,
                2.6,
                2.7,
                2.8000000000000003,
                2.9000000000000004,
                3.0
            ],
            "extrapolator": [
                "exponential",
                "linear",
                "fallback"
            ]
        },
        "measure_noise_learning": {
            "num_randomizations": 512,
            "shots_per_randomization": 512
        }
    },
    "twirling": {
        "enable_gates": true,
        "enable_measure": true,
        "num_randomizations": 300,
        "shots_per_randomization": 100,
        "strategy": "active"
    }
}
Hamiltonian: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYY', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'XXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'YYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'ZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IXXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IYYIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
              coeffs=[0.52440675+0.j, 0.52440675+0.j, 1.0488135 +0.j, 0.55138169+0.j,
 0.55138169+0.j, 1.10276338+0.j, 0.4618274 +0.j, 0.4618274 +0.j,
 0.9236548 +0.j, 0.46879361+0.j, 0.46879361+0.j, 0.93758721+0.j,
 0.73183138+0.j, 0.73183138+0.j, 1.46366276+0.j, 0.64586252+0.j,
 0.64586252+0.j, 1.29172504+0.j, 0.53402228+0.j, 0.53402228+0.j,
 1.06804456+0.j, 0.28551803+0.j, 0.28551803+0.j, 0.57103606+0.j,
 0.2601092 +0.j, 0.2601092 +0.j, 0.5202184 +0.j, 0.63907838+0.j,
 0.63907838+0.j, 1.27815675+0.j, 0.73930917+0.j, 0.73930917+0.j,
 1.47861834+0.j, 0.48073968+0.j, 0.48073968+0.j, 0.96147936+0.j,
 0.30913721+0.j, 0.30913721+0.j, 0.61827443+0.j, 0.32167664+0.j,
 0.32167664+0.j, 0.64335329+0.j, 0.51092416+0.j, 0.51092416+0.j,
 1.02184832+0.j, 0.38227781+0.j, 0.38227781+0.j, 0.76455561+0.j,
 0.47807517+0.j, 0.47807517+0.j, 0.95615033+0.j, 0.2593949 +0.j,
 0.2593949 +0.j, 0.5187898 +0.j, 0.55604786+0.j, 0.55604786+0.j,
 1.11209572+0.j, 0.72187404+0.j, 0.72187404+0.j, 1.44374808+0.j,
 0.42975395+0.j, 0.42975395+0.j, 0.8595079 +0.j, 0.5988156 +0.j,
 0.5988156 +0.j, 1.1976312 +0.j, 0.58338336+0.j, 0.58338336+0.j,
 1.16676672+0.j, 0.35519128+0.j, 0.35519128+0.j, 0.71038256+0.j,
 0.40771418+0.j, 0.40771418+0.j, 0.81542835+0.j, 0.60759468+0.j,
 0.60759468+0.j, 1.21518937+0.j, 0.52244159+0.j, 0.52244159+0.j,
 1.04488318+0.j, 0.57294706+0.j, 0.57294706+0.j, 1.14589411+0.j,
 0.6958865 +0.j, 0.6958865 +0.j, 1.391773  +0.j, 0.44172076+0.j,
 0.44172076+0.j, 0.88344152+0.j, 0.51444746+0.j, 0.51444746+0.j,
 1.02889492+0.j, 0.71279832+0.j, 0.71279832+0.j, 1.42559664+0.j,
 0.29356465+0.j, 0.29356465+0.j, 0.5871293 +0.j, 0.66630992+0.j,
 0.66630992+0.j, 1.33261985+0.j, 0.68500607+0.j, 0.68500607+0.j,
 1.37001215+0.j, 0.64957928+0.j, 0.64957928+0.j, 1.29915856+0.j,
 0.64026459+0.j, 0.64026459+0.j, 1.28052918+0.j, 0.56996051+0.j,
 0.56996051+0.j, 1.13992102+0.j, 0.72233446+0.j, 0.72233446+0.j,
 1.44466892+0.j, 0.45733097+0.j, 0.45733097+0.j, 0.91466194+0.j,
 0.63711684+0.j, 0.63711684+0.j, 1.27423369+0.j, 0.53421697+0.j,
 0.53421697+0.j, 1.06843395+0.j, 0.55881775+0.j, 0.55881775+0.j,
 1.1176355 +0.j, 0.558467  +0.j, 0.558467  +0.j, 1.116934  +0.j,
 0.59091015+0.j, 0.59091015+0.j, 1.1818203 +0.j, 0.46851598+0.j,
 0.46851598+0.j, 0.93703195+0.j, 0.28011274+0.j, 0.28011274+0.j,
 0.56022547+0.j, 0.58531893+0.j, 0.58531893+0.j, 1.17063787+0.j,
 0.31446315+0.j, 0.31446315+0.j, 0.6289263 +0.j])
Observable: SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIII'],
              coeffs=[1.+0.j])
Target MPS maximum bond dimension: 5
Number of AQC parameters: 816
Starting fidelity of AQC portion: 0.9914382555614002
2024-12-17 14:52:23.400028 Intermediate result: Fidelity 0.99764093
2024-12-17 14:52:23.429669 Intermediate result: Fidelity 0.99788003
2024-12-17 14:52:23.459674 Intermediate result: Fidelity 0.99795970
2024-12-17 14:52:23.489666 Intermediate result: Fidelity 0.99799067
2024-12-17 14:52:23.518545 Intermediate result: Fidelity 0.99803401
2024-12-17 14:52:23.546952 Intermediate result: Fidelity 0.99809821
2024-12-17 14:52:23.575271 Intermediate result: Fidelity 0.99824660
2024-12-17 14:52:23.604049 Intermediate result: Fidelity 0.99845326
2024-12-17 14:52:23.632709 Intermediate result: Fidelity 0.99870497
2024-12-17 14:52:23.660527 Intermediate result: Fidelity 0.99891442
2024-12-17 14:52:23.688273 Intermediate result: Fidelity 0.99904488
2024-12-17 14:52:23.716105 Intermediate result: Fidelity 0.99914438
2024-12-17 14:52:23.744336 Intermediate result: Fidelity 0.99922827
2024-12-17 14:52:23.773399 Intermediate result: Fidelity 0.99929071
2024-12-17 14:52:23.801482 Intermediate result: Fidelity 0.99932432
2024-12-17 14:52:23.830466 Intermediate result: Fidelity 0.99936460
2024-12-17 14:52:23.860738 Intermediate result: Fidelity 0.99938891
2024-12-17 14:52:23.889958 Intermediate result: Fidelity 0.99940607
2024-12-17 14:52:23.918703 Intermediate result: Fidelity 0.99941965
2024-12-17 14:52:23.949744 Intermediate result: Fidelity 0.99944337
2024-12-17 14:52:23.980871 Intermediate result: Fidelity 0.99946875
2024-12-17 14:52:24.012124 Intermediate result: Fidelity 0.99949009
2024-12-17 14:52:24.044359 Intermediate result: Fidelity 0.99952191
2024-12-17 14:52:24.075840 Intermediate result: Fidelity 0.99953669
2024-12-17 14:52:24.106303 Intermediate result: Fidelity 0.99955242
2024-12-17 14:52:24.139329 Intermediate result: Fidelity 0.99958412
2024-12-17 14:52:24.169725 Intermediate result: Fidelity 0.99960176
2024-12-17 14:52:24.198749 Intermediate result: Fidelity 0.99961606
2024-12-17 14:52:24.227874 Intermediate result: Fidelity 0.99963811
2024-12-17 14:52:24.256818 Intermediate result: Fidelity 0.99964383
2024-12-17 14:52:24.285889 Intermediate result: Fidelity 0.99964717
2024-12-17 14:52:24.315228 Intermediate result: Fidelity 0.99966064
2024-12-17 14:52:24.345322 Intermediate result: Fidelity 0.99966517
2024-12-17 14:52:24.374921 Intermediate result: Fidelity 0.99967089
2024-12-17 14:52:24.404309 Intermediate result: Fidelity 0.99968305
2024-12-17 14:52:24.432664 Intermediate result: Fidelity 0.99968889
2024-12-17 14:52:24.461639 Intermediate result: Fidelity 0.99969997
2024-12-17 14:52:24.491244 Intermediate result: Fidelity 0.99971666
2024-12-17 14:52:24.520354 Intermediate result: Fidelity 0.99972441
2024-12-17 14:52:24.549965 Intermediate result: Fidelity 0.99973561
2024-12-17 14:52:24.583464 Intermediate result: Fidelity 0.99973811
2024-12-17 14:52:24.617537 Intermediate result: Fidelity 0.99974074
2024-12-17 14:52:24.652247 Intermediate result: Fidelity 0.99974467
2024-12-17 14:52:24.686831 Intermediate result: Fidelity 0.99974991
2024-12-17 14:52:24.725476 Intermediate result: Fidelity 0.99975230
2024-12-17 14:52:24.764637 Intermediate result: Fidelity 0.99975373
2024-12-17 14:52:24.802499 Intermediate result: Fidelity 0.99975552
2024-12-17 14:52:24.839960 Intermediate result: Fidelity 0.99975885
2024-12-17 14:52:24.877472 Intermediate result: Fidelity 0.99976469
2024-12-17 14:52:24.916233 Intermediate result: Fidelity 0.99976517
2024-12-17 14:52:24.993750 Intermediate result: Fidelity 0.99976875
2024-12-17 14:52:25.034953 Intermediate result: Fidelity 0.99976887
2024-12-17 14:52:25.076197 Intermediate result: Fidelity 0.99977244
2024-12-17 14:52:25.112340 Intermediate result: Fidelity 0.99977638
2024-12-17 14:52:25.149947 Intermediate result: Fidelity 0.99977828
2024-12-17 14:52:25.190049 Intermediate result: Fidelity 0.99978174
2024-12-17 14:52:25.310903 Intermediate result: Fidelity 0.99978222
2024-12-17 14:52:25.347512 Intermediate result: Fidelity 0.99978508
2024-12-17 14:52:25.385201 Intermediate result: Fidelity 0.99978543
2024-12-17 14:52:25.457436 Intermediate result: Fidelity 0.99978770
2024-12-17 14:52:25.497133 Intermediate result: Fidelity 0.99978818
2024-12-17 14:52:25.541179 Intermediate result: Fidelity 0.99978913
2024-12-17 14:52:25.584791 Intermediate result: Fidelity 0.99978937
2024-12-17 14:52:25.621484 Intermediate result: Fidelity 0.99979068
2024-12-17 14:52:25.655847 Intermediate result: Fidelity 0.99979211
2024-12-17 14:52:25.691710 Intermediate result: Fidelity 0.99979700
2024-12-17 14:52:25.767711 Intermediate result: Fidelity 0.99979759
2024-12-17 14:52:25.804517 Intermediate result: Fidelity 0.99979807
2024-12-17 14:52:25.839394 Intermediate result: Fidelity 0.99980236
2024-12-17 14:52:25.874438 Intermediate result: Fidelity 0.99980296
2024-12-17 14:52:25.909900 Intermediate result: Fidelity 0.99980320
2024-12-17 14:52:26.713044 Intermediate result: Fidelity 0.99980320
Done after 72 iterations.
Fidelity of AQC portion: 0.9998108844412502
ISA circuit two-qubit depth: 33
Exiting before hardware execution since `dry_run` is True.


Próximos pasos

Recomendaciones

Para una inmersión más profunda en el addon Qiskit AQC-Tensor, echa un vistazo al tutorial Improved Trotterized Time Evolution with Approximate Quantum Compilation o al repositorio qiskit-addon-aqc-tensor.

  • Aquí está toda la fuente de ./source_files/template_hamiltonian_simulation.py como un bloque de código.

    ./source_files/template_hamiltonian_simulation_full.py
    from qiskit import QuantumCircuit
    from qiskit_serverless import get_arguments, save_result
    
    
    # Extract parameters from arguments
    #
    # Do this at the top of the program so it fails early
    # if any required arguments are missing or invalid.
    
    arguments = get_arguments()
    
    dry_run = arguments.get("dry_run", False)
    backend_name = arguments["backend_name"]
    
    aqc_evolution_time = arguments["aqc_evolution_time"]
    aqc_ansatz_num_trotter_steps = arguments["aqc_ansatz_num_trotter_steps"]
    aqc_target_num_trotter_steps = arguments["aqc_target_num_trotter_steps"]
    
    remainder_evolution_time = arguments["remainder_evolution_time"]
    remainder_num_trotter_steps = arguments["remainder_num_trotter_steps"]
    
    # Stop if this fidelity is achieved
    aqc_stopping_fidelity = arguments.get("aqc_stopping_fidelity", 1.0)
    # Stop after this number of iterations, even if stopping fidelity is not achieved
    aqc_max_iterations = arguments.get("aqc_max_iterations", 500)
    
    hamiltonian = arguments["hamiltonian"]
    observable = arguments["observable"]
    initial_state = arguments.get("initial_state", QuantumCircuit(hamiltonian.num_qubits))
    
    import numpy as np
    import json
    from mergedeep import merge
    
    
    # Configure `EstimatorOptions` to control the hardware experiment's parameters
    #
    # Set default options
    estimator_default_options = {
        "resilience": {
            "measure_mitigation": True,
            "zne_mitigation": True,
            "zne": {
                "amplifier": "gate_folding",
                "noise_factors": [1, 2, 3],
                "extrapolated_noise_factors": list(np.linspace(0, 3, 31)),
                "extrapolator": ["exponential", "linear", "fallback"],
            },
            "measure_noise_learning": {
                "num_randomizations": 512,
                "shots_per_randomization": 512,
            },
        },
        "twirling": {
            "enable_gates": True,
            "enable_measure": True,
            "num_randomizations": 300,
            "shots_per_randomization": 100,
            "strategy": "active",
        },
    }
    # Merge with user-provided options
    estimator_options = merge(
        arguments.get("estimator_options", {}), estimator_default_options
    )
    
    print("estimator_options =", json.dumps(estimator_options, indent=4))
    
    # Perform parameter validation
    
    if not 0.0 < aqc_stopping_fidelity <= 1.0:
        raise ValueError(
            f"Invalid stopping fidelity: {aqc_stopping_fidelity}.  "
            It must be a positive float no greater than 1."
        )
    
    output = {}
    
    import os
    os.environ["NUMBA_CACHE_DIR"] = "/data"
    
    import datetime
    import quimb.tensor
    from scipy.optimize import OptimizeResult, minimize
    from qiskit.synthesis import SuzukiTrotter
    from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit
    from qiskit_addon_aqc_tensor.ansatz_generation import (
        generate_ansatz_from_circuit,
        AnsatzBlock,
    )
    from qiskit_addon_aqc_tensor.simulation import (
        tensornetwork_from_circuit,
        compute_overlap,
    )
    from qiskit_addon_aqc_tensor.simulation.quimb import QuimbSimulator
    from qiskit_addon_aqc_tensor.objective import OneMinusFidelity
    
    print("Hamiltonian:", hamiltonian)
    print("Observable:", observable)
    simulator_settings = QuimbSimulator(quimb.tensor.CircuitMPS, autodiff_backend="jax")
    
    # Construct the AQC target circuit
    aqc_target_circuit = initial_state.copy()
    if aqc_evolution_time:
        aqc_target_circuit.compose(
            generate_time_evolution_circuit(
                hamiltonian,
                synthesis=SuzukiTrotter(reps=aqc_target_num_trotter_steps),
                time=aqc_evolution_time,
            ),
            inplace=True,
        )
    
    # Construct matrix-product state representation of the AQC target state
    aqc_target_mps = tensornetwork_from_circuit(aqc_target_circuit, simulator_settings)
    print("Target MPS maximum bond dimension:", aqc_target_mps.psi.max_bond())
    output["target_bond_dimension"] = aqc_target_mps.psi.max_bond()
    
    # Generate an ansatz and initial parameters from a Trotter circuit with fewer steps
    aqc_good_circuit = initial_state.copy()
    if aqc_evolution_time:
        aqc_good_circuit.compose(
            generate_time_evolution_circuit(
                hamiltonian,
                synthesis=SuzukiTrotter(reps=aqc_ansatz_num_trotter_steps),
                time=aqc_evolution_time,
            ),
            inplace=True,
        )
    aqc_ansatz, aqc_initial_parameters = generate_ansatz_from_circuit(aqc_good_circuit)
    print("Number of AQC parameters:", len(aqc_initial_parameters))
    output["num_aqc_parameters"] = len(aqc_initial_parameters)
    
    # Calculate the fidelity of ansatz circuit vs. the target state, before optimization
    good_mps = tensornetwork_from_circuit(aqc_good_circuit, simulator_settings)
    starting_fidelity = abs(compute_overlap(good_mps, aqc_target_mps)) ** 2
    print("Starting fidelity of AQC portion:", starting_fidelity)
    output["aqc_starting_fidelity"] = starting_fidelity
    
    # Optimize the ansatz parameters by using MPS calculations
    def callback(intermediate_result: OptimizeResult):
        fidelity = 1 - intermediate_result.fun
        print(f"{datetime.datetime.now()} Intermediate result: Fidelity {fidelity:.8f}")
        if intermediate_result.fun < stopping_point:
            raise StopIteration
    
    
    objective = OneMinusFidelity(aqc_target_mps, aqc_ansatz, simulator_settings)
    stopping_point = 1.0 - aqc_stopping_fidelity
    
    result = minimize(
        objective,
        aqc_initial_parameters,
        method="L-BFGS-B",
        jac=True,
        options={"maxiter": aqc_max_iterations},
        callback=callback,
    )
    if result.status not in (
        0,
        1,
        99,
    ):  # 0 => success; 1 => max iterations reached; 99 => early termination via StopIteration
        raise RuntimeError(
            f"Optimization failed: {result.message} (status={result.status})"
        )
    print(f"Done after {result.nit} iterations.")
    output["num_iterations"] = result.nit
    aqc_final_parameters = result.x
    output["aqc_final_parameters"] = list(aqc_final_parameters)
    
    # Construct an optimized circuit for initial portion of time evolution
    aqc_final_circuit = aqc_ansatz.assign_parameters(aqc_final_parameters)
    
    # Calculate fidelity after optimization
    aqc_final_mps = tensornetwork_from_circuit(aqc_final_circuit, simulator_settings)
    aqc_fidelity = abs(compute_overlap(aqc_final_mps, aqc_target_mps)) ** 2
    print("Fidelity of AQC portion:", aqc_fidelity)
    output["aqc_fidelity"] = aqc_fidelity
    
    # Construct final circuit, with remainder of time evolution
    final_circuit = aqc_final_circuit.copy()
    if remainder_evolution_time:
        remainder_circuit = generate_time_evolution_circuit(
            hamiltonian,
            synthesis=SuzukiTrotter(reps=remainder_num_trotter_steps),
            time=remainder_evolution_time,
        )
        final_circuit.compose(remainder_circuit, inplace=True)
    
    from qiskit.transpiler import generate_preset_pass_manager
    from qiskit_ibm_catalog import QiskitFunctionsCatalog
    
    service = QiskitRuntimeService()
    backend = service.backend(backend_name)
    
    # Transpile PUBs (circuits and observables) to match ISA
    pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=3)
    isa_circuit = pass_manager.run(final_circuit)
    isa_observable = observable.apply_layout(isa_circuit.layout)
    
    isa_2qubit_depth = isa_circuit.depth(lambda x: x.operation.num_qubits == 2)
    print("ISA circuit two-qubit depth:", isa_2qubit_depth)
    output["twoqubit_depth"] = isa_2qubit_depth
    
    # Exit now if dry run; don't execute on hardware
    if dry_run:
        import sys
    
        print("Exiting before hardware execution since `dry_run` is True.")
        save_result(output)
        sys.exit(0)
    
    # ## Step 3: Execute quantum experiments on backend
    from qiskit_ibm_runtime import EstimatorV2 as Estimator
    
    
    estimator = Estimator(backend, options=estimator_options)
    
    # Submit the underlying Estimator job. Note that this is not the
    # actual function job.
    job = estimator.run([(isa_circuit, isa_observable)])
    print("Job ID:", job.job_id())
    output["job_id"] = job.job_id()
    
    # Wait until job is complete
    hw_results = job.result()
    hw_results_dicts = [pub_result.data.__dict__ for pub_result in hw_results]
    
    # Save hardware results to serverless output dictionary
    output["hw_results"] = hw_results_dicts
    
    # Reorganize expectation values
    hw_expvals = [pub_result_data["evs"].tolist()
        for pub_result_data in hw_results_dicts]
    
    # Save expectation values to Qiskit Serverless
    output["hw_expvals"] = hw_expvals[0]
    
    save_result(output)
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.