Costruire un template di funzione per la simulazione hamiltoniana
Questo template racchiude un workflow per simulare l'evoluzione temporale di uno stato iniziale rispetto a un'Hamiltoniana spin-based definita dall'utente, e restituisce un insieme di valori di aspettazione specificati usando il componente aggiuntivo AQC.
Il template è strutturato come un pattern Qiskit con i seguenti passaggi:
1. Raccolta degli input e mappatura del problema​
Questa sezione prende come input l'Hamiltoniana da simulare, uno stato iniziale nella forma di un QuantumCircuit, un insieme di osservabili per stimare i valori di aspettazione, e una specifica delle opzioni per il componente aggiuntivo AQC. Questo passaggio verifica che tutti i dati di input richiesti siano presenti e nel formato corretto.
Gli argomenti di input vengono poi usati per costruire i circuiti quantistici e gli operatori rilevanti per il workflow. Viene creato un circuito target e tramite il componente aggiuntivo AQC se ne trova una rappresentazione matrix product state. Successivamente, un circuito ansatz viene generato e ottimizzato usando metodi di reti tensoriali, producendo un circuito finale che esegue il resto dell'evoluzione temporale.
2. Preparare i circuiti generati per l'esecuzione​
I circuiti generati dal componente aggiuntivo AQC vengono poi transpilati per essere eseguiti su un backend scelto. Viene creata un'istanza di EstimatorV2 con un insieme predefinito di opzioni di mitigazione degli errori per gestire l'esecuzione del circuito.
3. Esecuzione​
Infine, il circuito ansatz viene transpilato ed eseguito su un QPU e raccoglie le stime per tutti i valori di aspettazione specificati, che vengono restituiti in un formato serializzabile per l'accesso da parte dell'utente.
Scrivere il template di funzione​
Prima di tutto, scrivi un template di funzione per la simulazione hamiltoniana che usa il componente aggiuntivo AQC-Tensor di Qiskit per mappare la descrizione del problema su un circuito a profondità ridotta per l'esecuzione su hardware.
Nel corso del processo, il codice viene salvato in ./source_files/template_hamiltonian_simulation.py. Questo file è il template di funzione che puoi caricare ed eseguire da remoto con Qiskit Serverless.
# Added by doQumentation — required packages for this notebook
!pip install -q mergedeep numpy qiskit qiskit-addon-aqc-tensor qiskit-addon-utils qiskit-ibm-catalog qiskit-ibm-runtime qiskit-serverless quimb scipy
# This cell is hidden from users, it just creates a new folder
from pathlib import Path
Path("./source_files").mkdir(exist_ok=True)
Raccogliere e validare gli input​
Inizia ottenendo gli input per il template. Questo esempio ha input specifici del dominio rilevanti per la simulazione hamiltoniana (come l'Hamiltoniana e l'osservabile) e opzioni specifiche delle capacità (come quanto vuoi comprimere i layer iniziali del circuito di Trotter usando AQC-Tensor, o opzioni avanzate per la messa a punto della soppressione e mitigazione degli errori al di là delle impostazioni predefinite che fanno parte di questo esempio).
%%writefile ./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))
Writing ./source_files/template_hamiltonian_simulation.py
%%writefile --append ./source_files/template_hamiltonian_simulation.py
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
)
Appending to ./source_files/template_hamiltonian_simulation.py
Quando il template di funzione è in esecuzione, è utile restituire informazioni nei log tramite istruzioni print, in modo da poter valutare meglio il progresso del workload. Di seguito è riportato un semplice esempio di stampa delle estimator_options in modo da avere un registro delle opzioni Estimator effettivamente utilizzate. Nel programma ci sono molti altri esempi simili per segnalare il progresso durante l'esecuzione, tra cui il valore della funzione obiettivo durante il componente iterativo di AQC-Tensor, e la profondità a due qubit del circuito ISA (instruction set architecture) finale destinato all'esecuzione su hardware.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
print("estimator_options =", json.dumps(estimator_options, indent=4))
Appending to ./source_files/template_hamiltonian_simulation.py
Validare gli input​
Un aspetto importante per garantire che il template possa essere riutilizzato su un'ampia gamma di input è la validazione degli input. Il codice seguente è un esempio di verifica che la fedeltà di arresto durante AQC-Tensor sia stata specificata in modo appropriato e, in caso contrario, di restituzione di un messaggio di errore informativo su come correggere l'errore.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
# 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."
)
Appending to ./source_files/template_hamiltonian_simulation.py
Preparare gli output della funzione​
Prima di tutto, prepara un dizionario per contenere tutti gli output del template di funzione. Le chiavi verranno aggiunte a questo dizionario durante tutto il workflow e viene restituito alla fine del programma.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
output = {}
Appending to ./source_files/template_hamiltonian_simulation.py
Mappare il problema e pre-elaborare il circuito con AQC​
L'ottimizzazione AQC-Tensor avviene nel passaggio 1 di un pattern Qiskit. Prima viene costruito uno stato target. In questo esempio, viene costruito da un circuito target che evolve la stessa Hamiltoniana per lo stesso periodo di tempo della porzione AQC. Poi, viene generato un ansatz da un circuito equivalente ma con meno passi di Trotter. Nella parte principale dell'algoritmo AQC, quell'ansatz viene avvicinato iterativamente allo stato target. Infine, il risultato viene combinato con i restanti passi di Trotter necessari per raggiungere il tempo di evoluzione desiderato.
Nota i numerosi esempi aggiuntivi di logging incorporati nel codice seguente.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
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)
Appending to ./source_files/template_hamiltonian_simulation.py
Ottimizzare il circuito finale per l'esecuzione​
Dopo la porzione AQC del workflow, il final_circuit viene transpilato per l'hardware come di consueto.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
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
Appending to ./source_files/template_hamiltonian_simulation.py
Uscire prima se si usa la modalità dry run​
Se è stata selezionata la modalità dry run, il programma si interrompe prima di eseguire sull'hardware. Questo può essere utile se, ad esempio, vuoi prima ispezionare la profondità a due qubit del circuito ISA prima di decidere di eseguire sull'hardware.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
# 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)
Appending to ./source_files/template_hamiltonian_simulation.py
Eseguire il circuito sull'hardware​
%%writefile --append ./source_files/template_hamiltonian_simulation.py
# ## 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]
Appending to ./source_files/template_hamiltonian_simulation.py
Salvare l'output​
Questo template di funzione restituisce l'output di livello di dominio rilevante per questo workflow di simulazione hamiltoniana (valori di aspettazione), oltre a importanti metadati generati lungo il percorso.
%%writefile --append ./source_files/template_hamiltonian_simulation.py
save_result(output)
Appending to ./source_files/template_hamiltonian_simulation.py
Distribuire la funzione su IBM Quantum Platform​
La sezione precedente ha creato un programma da eseguire da remoto. Il codice in questa sezione carica quel programma su Qiskit Serverless.
Usa qiskit-ibm-catalog per autenticarti a QiskitServerless con la tua chiave API, che puoi trovare nella dashboard di IBM Quantum Platform, e carica il programma.
Puoi facoltativamente usare save_account() per salvare le tue credenziali (vedi la guida Configurare il tuo account IBM Cloud). Nota che questo scrive le tue credenziali nello stesso file di QiskitRuntimeService.save_account().
from qiskit_ibm_catalog import QiskitServerless, QiskitFunction
# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()
Questo programma ha dipendenze pip personalizzate. Aggiungile a un array dependencies quando costruisci l'istanza 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)
QiskitFunction(template_hamiltonian_simulation)
Infine, per verificare che il programma sia stato caricato correttamente, usa serverless.list():
serverless.list()
QiskitFunction(template_hamiltonian_simulation),
Eseguire il template di funzione da remoto​
Il template di funzione è stato caricato, quindi puoi eseguirlo da remoto con Qiskit Serverless. Prima, carica il template per nome:
template = serverless.load("template_hamiltonian_simulation")
Successivamente, esegui il template con gli input di livello di dominio per la simulazione hamiltoniana. Questo esempio specifica un modello XXZ a 50 qubit con accoppiamenti casuali, uno stato iniziale e un osservabile.
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)
853b0edb-d63f-4629-be71-398b6dcf33cb
Controlla lo stato del job:
job.status()
'QUEUED'
Dopo che il job è in esecuzione, puoi recuperare i log creati dagli output print(). Questi possono fornire informazioni utili sul progresso del workflow di simulazione hamiltoniana. Ad esempio, il valore della funzione obiettivo durante il componente iterativo di AQC, o la profondità a due qubit del circuito ISA finale destinato all'esecuzione su hardware.
print(job.logs())
No logs yet.
Blocca il resto del programma fino a quando non è disponibile un risultato. Dopo che il job è terminato, puoi recuperare i risultati. Questi includono l'output di livello di dominio della simulazione hamiltoniana (valore di aspettazione) e metadati utili.
result = job.result()
del result[
"aqc_final_parameters"
] # the list is too long to conveniently display here
result
{'target_bond_dimension': 5,
'num_aqc_parameters': 816,
'aqc_starting_fidelity': 0.9914382555614002,
'num_iterations': 72,
'aqc_fidelity': 0.9998108844412502,
'twoqubit_depth': 33}
Dopo il completamento del job, sarà disponibile l'intero output di logging.
print(job.logs())
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.
Passi successivi​
Per un approfondimento sul componente aggiuntivo AQC-Tensor di Qiskit, consulta il tutorial Improved Trotterized Time Evolution with Approximate Quantum Compilation o il repository qiskit-addon-aqc-tensor.
%%writefile ./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 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
)
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_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
# 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)
Overwriting ./source_files/template_hamiltonian_simulation_full.py
Codice sorgente completo del programma
Ecco l'intero sorgente di ./source_files/template_hamiltonian_simulation.py come un unico blocco di codice.
# This cell is hidden from users. It verifies both source listings are identical then deletes the working folder we created
import shutil
with open("./source_files/template_hamiltonian_simulation.py") as f1:
with open("./source_files/template_hamiltonian_simulation_full.py") as f2:
assert f1.read() == f2.read()
shutil.rmtree("./source_files/")