Simulare exactă cu primitivele Qiskit SDK
Versiuni de pachete
Codul de pe această pagină a fost dezvoltat folosind următoarele cerințe. Recomandăm utilizarea acestor versiuni sau a unora mai noi.
qiskit[all]~=2.3.0
Primitivele de referință din Qiskit SDK realizează simulări locale cu vector de stare. Aceste simulări nu suportă modelarea zgomotului dispozitivului, dar sunt utile pentru prototiparea rapidă a algoritmilor înainte de a explora tehnici de simulare mai avansate (folosind Qiskit Aer) sau înainte de a rula pe dispozitive reale (primitivele Qiskit Runtime).
Primitiva Estimator poate calcula valorile așteptate ale circuitelor, iar primitiva Sampler poate eșantiona din distribuțiile de ieșire ale circuitelor.
Secțiunile următoare arată cum să folosești primitivele de referință pentru a rula fluxul de lucru local.
Folosește Estimator-ul de referință
Implementarea de referință a EstimatorV2 din qiskit.primitives care rulează pe simulatoare locale cu vector de stare
este clasa StatevectorEstimator. Aceasta poate primi circuite, observabile și parametri ca intrări și returnează valorile așteptate calculate local.
Următorul cod pregătește intrările care vor fi folosite în exemplele de mai jos. Tipul de intrare așteptat pentru
observabile este qiskit.quantum_info.SparsePauliOp. Observă că
circuitul din exemplu este parametrizat, dar poți rula Estimator-ul și pe circuite neparametrizate.
Orice Circuit transmis unui Estimator nu trebuie să includă măsurători.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# circuit for which you want to obtain the expected value
circuit = QuantumCircuit(2)
circuit.ry(Parameter("theta"), 0)
circuit.h(0)
circuit.cx(0, 1)
circuit.draw("mpl", style="iqp")
from qiskit.quantum_info import SparsePauliOp
import numpy as np
# observable(s) whose expected values you want to compute
observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1])
# value(s) for the circuit parameter(s)
parameter_values = [[0], [np.pi / 6], [np.pi / 2]]
Fluxul de lucru al primitivelor Qiskit Runtime necesită ca circuitele și observabilele să fie transformate pentru a folosi doar instrucțiunile suportate de QPU (denumite circuite și observabile cu arhitectură set de instrucțiuni (ISA)). Primitivele de referință acceptă în continuare instrucțiuni abstracte, deoarece se bazează pe simulări locale cu vector de stare, dar transpilarea circuitului poate fi totuși benefică în ceea ce privește optimizarea circuitului.
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
Inițializează Estimator-ul
Instanțiază un qiskit.primitives.StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()
Rulează și obține rezultate
Acest exemplu folosește un singur Circuit (de tip QuantumCircuit) și un singur
observabil.
Rulează estimarea apelând metoda StatevectorEstimator.run, care returnează o instanță a unui obiect PrimitiveJob. Poți obține rezultatele din job (ca obiect qiskit.primitives.PrimitiveResult)
cu metoda qiskit.primitives.PrimitiveJob.result.
job = estimator.run([(circuit, observable, parameter_values)])
result = job.result()
print(f" > Result class: {type(result)}")
> Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>
Obține valoarea așteptată din rezultat
Rezultatul primitivelor returnează un array de obiecte PubResult, unde fiecare element al array-ului este un obiect PubResult care conține în datele sale array-ul de evaluări corespunzătoare fiecărei combinații circuit-observabil din PUB.
Pentru a recupera valorile așteptate și metadatele pentru prima evaluare de Circuit (și singura, în acest caz), trebuie să accesăm data de evaluare pentru PUB 0:
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")
> Expectation value: [4. 3.73205081 2. ]
> Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}
Setează opțiunile de rulare ale Estimator-ului
În mod implicit, Estimator-ul de referință efectuează un calcul exact cu vector de stare bazat pe
clasa quantum_info.Statevector.
Totuși, aceasta poate fi modificată pentru a introduce efectul suprasarcinii de eșantionare (cunoscută și ca „zgomot de shot").
Estimator-ul acceptă un argument precision care exprimă barele de eroare pe care
implementarea primitivei ar trebui să le atingă pentru estimările valorilor așteptate. Aceasta este suprasarcina de eșantionare și este definită exclusiv în metoda .run(). Aceasta îți permite să reglezi fin opțiunea până la nivelul PUB.
# Estimate expectation values for two PUBs, both with 0.05 precision.
precise_job = estimator.run(
[(circuit, observable, parameter_values)], precision=0.05
)
Pentru un exemplu complet, consultă pagina Exemple pentru primitive.
Folosește Sampler-ul de referință
Implementarea de referință a SamplerV2 din qiskit.primitives este clasa StatevectorSampler. Aceasta primește circuite și parametri ca intrări și returnează rezultatele din eșantionarea distribuțiilor de probabilitate de ieșire sub forma unei distribuții cvasiprobaliliste a stărilor de ieșire.
Următorul cod pregătește intrările folosite în exemplele de mai jos. Observă că aceste exemple rulează un singur Circuit parametrizat, dar poți rula Sampler-ul și pe circuite neparametrizate.
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw("mpl", style="iqp")
Orice Circuit cuantic transmis unui Sampler trebuie să includă măsurători.
Fluxul de lucru al primitivelor Qiskit Runtime necesită ca circuitele să fie transformate pentru a folosi doar instrucțiunile suportate de QPU (denumite circuite ISA). Primitivele de referință acceptă în continuare instrucțiuni abstracte, deoarece se bazează pe simulări locale cu vector de stare, dar transpilarea circuitului poate fi totuși benefică în ceea ce privește optimizarea circuitului.
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(qc)
Inițializează SamplerV2
Instanțiază qiskit.primitives.StatevectorSampler:
from qiskit.primitives import StatevectorSampler
sampler = StatevectorSampler()
Rulează și obține rezultate
# execute 1 circuit with Sampler
job = sampler.run([circuit])
pub_result = job.result()[0]
print(f" > Result class: {type(pub_result)}")
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
Primitivele acceptă mai multe PUB-uri ca intrări, iar fiecare PUB primește propriul rezultat. Prin urmare, poți rula circuite diferite cu diverse combinații de parametri/observabile și poți recupera rezultatele PUB:
from qiskit.transpiler import generate_preset_pass_manager
# create two circuits
circuit1 = circuit.copy()
circuit2 = circuit.copy()
# transpile circuits
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit1 = pm.run(circuit1)
isa_circuit2 = pm.run(circuit2)
# execute 2 circuits using Sampler
job = sampler.run([(isa_circuit1), (isa_circuit2)])
pub_result_1 = job.result()[0]
pub_result_2 = job.result()[1]
print(f" > Result class: {type(pub_result)}")
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
Obține distribuția de probabilitate sau rezultatul măsurătorii
Eșantioanele rezultatelor măsurătorilor sunt returnate ca șiruri de biți sau numărări. Șirurile de biți arată rezultatele măsurătorilor, păstrând ordinea shot-urilor în care au fost măsurate. Obiectele rezultat ale Sampler-ului organizează datele în funcție de numele registrelor clasice ale circuitelor de intrare, pentru compatibilitate cu circuitele dinamice.
Numele registrului clasic este implicit "meas". Acest nume va fi folosit mai târziu pentru a accesa șirurile de biți ale măsurătorilor.
# Define quantum circuit with 2 qubits
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw()
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■───░─┤M├───
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/══════════════╩══╩═
0 1
# Transpile circuit
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
# Run using sampler
result = sampler.run([circuit]).result()
# Access result data for PUB 0
data_pub = result[0].data
# Access bitstring for the classical register "meas"
bitstrings = data_pub.meas.get_bitstrings()
print(f"The number of bitstrings is: {len(bitstrings)}")
# Get counts for the classical register "meas"
counts = data_pub.meas.get_counts()
print(f"The counts are: {counts}")
The number of bitstrings is: 1024
The counts are: {'11': 515, '00': 509}
Modifică opțiunile de rulare
În mod implicit, Sampler-ul de referință efectuează un calcul exact cu vector de stare bazat pe
clasa quantum_info.Statevector.
Totuși, aceasta poate fi modificată pentru a introduce efectul suprasarcinii de eșantionare (cunoscută și ca „zgomot de shot"). Pentru a gestiona această suprasarcină, interfața Sampler acceptă un argument shots care poate fi definit la nivelul PUB.
Acest exemplu presupune că ai definit două circuite.
# Sample two circuits at 128 shots each.
sampler.run([isa_circuit1, isa_circuit2], shots=128)
# Sample two circuits at different amounts of shots. The "None"s are necessary
# as placeholders
# for the lack of parameter values in this example.
sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])
<qiskit.primitives.primitive_job.PrimitiveJob at 0x7fa430e39dd0>
Pentru un exemplu complet, consultă pagina Exemple pentru primitive.
Pașii următori
- Pentru o simulare cu performanță mai ridicată care poate gestiona circuite mai mari sau pentru a incorpora modele de zgomot în simularea ta, consultă Simulare exactă și cu zgomot folosind primitivele Qiskit Aer.
- Pentru a afla cum să folosești Quantum Composer pentru simulare, consultă ghidul IBM Quantum Composer.
- Citește referința Qiskit Estimator API.
- Citește referința Qiskit Sampler API.
- Citește Migrează la primitivele V2.