Creare un modello di funzione Qiskit per la simulazione hamiltoniana
Questo modello racchiude un flusso di lavoro per simulare l'evoluzione temporale di uno stato iniziale rispetto a un hamiltoniano basato sullo spin definito dall'utente e restituisce una serie di valori attesi specificati utilizzando l'add-on AQC-Tensor Qiskit.
Questo modello è strutturato come un modello Qiskit con i seguenti passaggi:
1. Raccolta di input e mappatura del problema
Questa sezione prende in input l'hamiltoniana da simulare, uno stato iniziale sotto forma di QuantumCircuit, un insieme di osservabili per stimare i valori di aspettativa e una specifica di opzioni per l'addon AQC. Questa fase convalida la presenza di tutti i dati di input richiesti e il loro formato corretto.
Gli argomenti in ingresso vengono quindi utilizzati per costruire i circuiti quantistici e gli operatori rilevanti per il flusso di lavoro. Si crea un circuito di destinazione e si trova una rappresentazione di stato del prodotto matriciale di questo circuito utilizzando l'addon AQC. In seguito, viene generato un circuito di ansatz e ottimizzato con metodi di rete tensoriale, producendo un circuito finale che esegue il resto dell'evoluzione temporale.
2. Preparare i circuiti generati per l'esecuzione
I circuiti generati dall'addon AQC vengono poi transpilati per essere eseguiti su un backend scelto. Viene creata un'istanza EstimatorV2 viene creata con un insieme predefinito di opzioni di attenuazione degli errori per gestire l'esecuzione del circuito.
3. Esecuzione
Infine, il circuito di ansatz viene transpilato ed eseguito su una QPU e raccoglie le stime per tutti i valori di aspettativa specificati, che vengono restituiti in un formato serializzabile per l'accesso da parte dell'utente.
Scrivi il modello di funzione
In primo luogo, scrivere un modello di funzione per la simulazione hamiltoniana che utilizzi l 'add-on AQC-Tensor Qiskit per mappare la descrizione del problema su un circuito a profondità ridotta per l'esecuzione su hardware.
Se scarichi questa pagina e la visualizzi in locale in un editor di file di testo, noterai che alcune delle celle di codice contengono il comando magico %%writefile. Questo comando magico salva il codice in ./source_files/template_hamiltonian_simulation.py, ovvero il modello di funzione che puoi caricare su ed eseguire in remoto tramite Qiskit Serverless.
Raccogliere e convalidare gli input
Iniziate con l'ottenere gli input per il modello. Questo esempio ha input specifici del dominio rilevanti per la simulazione hamiltoniana (come l'hamiltoniano e l'osservabile) e opzioni specifiche della capacità (come la quantità di compressione degli strati iniziali del circuito di Trotter usando AQC-Tensor, o opzioni avanzate per la regolazione fine della soppressione e della mitigazione degli errori al di là dei valori predefiniti che fanno parte di questo esempio).
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
)Quando il modello di funzione è in esecuzione, è utile riportare le informazioni nei log utilizzando le istruzioni di stampa, in modo da poter valutare meglio l'andamento del carico di lavoro. Di seguito è riportato un semplice esempio di stampa del sito estimator_options , in modo da avere una registrazione delle opzioni dell'Estimatore effettivamente utilizzate. Ci sono molti altri esempi simili in tutto il programma per segnalare i progressi durante l'esecuzione, tra cui il valore della funzione obiettivo durante la componente iterativa di AQC-Tensor e la profondità di due qubit del circuito finale dell'instruction set architecture (ISA) destinato all'esecuzione su hardware.
print("estimator_options =", json.dumps(estimator_options, indent=4))Convalida gli input
Un aspetto importante per garantire che il modello possa essere riutilizzato per una serie di input è la convalida dell'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, restituisce un messaggio di errore informativo su come risolvere l'errore.
# 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."
)Preparare gli output della funzione
Per prima cosa, preparare un dizionario che contenga tutti gli output dei modelli di funzione. Le chiavi verranno aggiunte a questo dizionario nel corso del flusso di lavoro e verrà restituito alla fine del programma.
output = {}Mappare il problema ed eseguire la pre-elaborazione del circuito con AQC
L'ottimizzazione di AQC-Tensor avviene nel passo 1 di un modello Qiskit. In primo luogo, viene costruito uno stato di destinazione. In questo esempio, è costruito a partire da un circuito target che evolve la stessa hamiltoniana per lo stesso periodo di tempo della parte AQC. Quindi, si genera un'ansatz da un circuito equivalente, ma con meno passi di Trotter. Nella parte principale dell'algoritmo AQC, tale ansatz viene avvicinato iterativamente allo stato target. Infine, il risultato viene combinato con il resto dei passi di Trotter necessari per raggiungere il tempo di evoluzione desiderato.
Si notino gli esempi aggiuntivi di registrazione incorporati nel codice seguente.
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)Ottimizzare il circuito finale per l'esecuzione
Dopo la parte AQC del flusso di lavoro, final_circuit viene transpilato per l'hardware come di consueto.
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_depthEsci prima se utilizzi la modalità dry run
Se è stata selezionata la modalità Dry Run, il programma viene interrotto prima di essere eseguito sull'hardware. Questo può essere utile se, ad esempio, si vuole prima ispezionare la profondità a due qubit del circuito ISA prima di decidere di eseguirlo sull'hardware.
# 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)Eseguire il circuito sull'hardware
# ## 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]Salva l'output
Questo modello di funzione restituisce l'output rilevante a livello di dominio per questo flusso di lavoro di simulazione hamiltoniana (valori di aspettativa), oltre a importanti metadati generati lungo il percorso.
save_result(output)Distribuisci la funzione su IBM Quantum Platform
Nella sezione precedente è stato creato un programma da eseguire in remoto. Il codice in questa sezione carica il programma su Qiskit Serverless.
Utilizzate qiskit-ibm-catalog per autenticarvi su QiskitServerless con la vostra chiave API, che potete trovare sulla dashboard di IBM Quantum Platform, e caricate il programma.
È possibile utilizzare save_account() per salvare le credenziali (vedere la guida Configurazione dell'account IBM Cloud ). Si noti che questa operazione scrive le 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 personalizzate da pip . Aggiungerli a un array dependencies quando si costruisce 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)Output:
QiskitFunction(template_hamiltonian_simulation)
Infine, per verificare se il programma è stato caricato con successo, utilizzare serverless.list():
serverless.list()Output:
QiskitFunction(template_hamiltonian_simulation),
Esegui il modello di funzione in remoto
Il modello di funzione è stato caricato, quindi è possibile eseguirlo in remoto con Qiskit Serverless. Per prima cosa, caricare il modello per nome:
template = serverless.load("template_hamiltonian_simulation")Quindi, eseguire il modello con gli input a livello di dominio per la simulazione hamiltoniana. Questo esempio specifica un modello XXZ a 50 qubit con accoppiamenti casuali e uno stato e un'osservabile iniziali.
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
Controllare lo stato del lavoro:
job.status()Output:
'QUEUED'
Dopo l'esecuzione del lavoro, è possibile recuperare i registri creati dalle uscite di print() . Questi possono fornire informazioni utili sull'avanzamento del flusso di lavoro della simulazione hamiltoniana. Ad esempio, il valore della funzione obiettivo durante la componente iterativa del CQA, o la profondità di due qubit del circuito ISA finale destinato all'esecuzione su hardware.
print(job.logs())Output:
No logs yet.
Blocca il resto del programma finché non è disponibile un risultato. Al termine del lavoro, è possibile recuperare i risultati. Questi includono l'output a livello di dominio della simulazione hamiltoniana (valore di aspettativa) e metadati utili.
result = job.result()
del result[
"aqc_final_parameters"
] # the list is too long to conveniently display here
resultOutput:
{'target_bond_dimension': 5,
'num_aqc_parameters': 816,
'aqc_starting_fidelity': 0.9914382555614002,
'num_iterations': 72,
'aqc_fidelity': 0.9998108844412502,
'twoqubit_depth': 33}
Al termine del lavoro, sarà disponibile l'intero output di registrazione.
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.
Passi successivi
Per un'immersione più approfondita nell'addon Qiskit AQC-Tensor, consultate il tutorial Improved Trotterized Time Evolution with Approximate Quantum Compilation o il repository qiskit-addon-aqc-tensor.
Ecco l'intero sorgente di
./source_files/template_hamiltonian_simulation.pycome blocco di codice../source_files/template_hamiltonian_simulation_full.pyfrom 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)