Eksaktong simulation gamit ang Qiskit SDK primitives
Mga bersyon ng package
Ang code sa pahinang ito ay ginawa gamit ang mga sumusunod na kinakailangan. Inirerekomenda naming gamitin ang mga bersyong ito o mas bago.
qiskit[all]~=2.3.0
Ang mga reference primitives sa Qiskit SDK ay nagsasagawa ng lokal na statevector simulations. Hindi sinusuportahan ng mga simulation na ito ang pag-modelo ng noise ng device, ngunit kapaki-pakinabang para sa mabilis na pag-prototype ng mga algorithm bago tumingin sa mas advanced na mga teknik sa simulation (gamit ang Qiskit Aer) o pagpapatakbo sa mga tunay na device (Qiskit Runtime primitives).
Ang Estimator primitive ay maaaring mag-compute ng mga expectation value ng mga circuit, at ang Sampler primitive ay maaaring mag-sample mula sa mga output distribution ng mga circuit.
Ipinapakita ng mga sumusunod na seksyon kung paano gamitin ang mga reference primitives para patakbuhin ang iyong workflow nang lokal.
Gamitin ang reference Estimatorβ
Ang reference implementation ng EstimatorV2 sa qiskit.primitives na tumatakbo sa lokal na statevector
simulators ay ang StatevectorEstimator class. Maaari itong tumanggap ng mga circuit, observable, at parameter bilang input at ibinabalik ang mga lokal na kinomputang expectation value.
Inihahanda ng sumusunod na code ang mga input na gagamitin sa mga halimbawang susunod. Ang inaasahang uri ng input para sa
mga observable ay qiskit.quantum_info.SparsePauliOp. Tandaan na
ang circuit sa halimbawa ay may parameter, ngunit maaari ka ring magpatakbo ng Estimator sa mga circuit na walang parameter.
Anumang circuit na ipinasa sa Estimator ay hindi dapat magsama ng anumang measurements.
# 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]]
Ang Qiskit Runtime primitives workflow ay nangangailangan ng mga circuit at observable na ma-transform para gamitin lamang ang mga instruction na sinusuportahan ng QPU (tinatawag na instruction set architecture (ISA) circuits at observables). Ang mga reference primitives ay tumatanggap pa rin ng mga abstract na instruction, dahil umaasa sila sa lokal na statevector simulations, ngunit ang pag-transpile ng circuit ay maaari pa ring maging kapaki-pakinabang sa mga tuntunin ng pag-optimize ng circuit.
# 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)
I-initialize ang Estimatorβ
Mag-instantiate ng qiskit.primitives.StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()
Patakbuhin at kunin ang mga resultaβ
Ang halimbawang ito ay gumagamit lamang ng isang circuit (ng uri QuantumCircuit) at isang
observable.
Patakbuhin ang estimation sa pamamagitan ng pagtawag sa StatevectorEstimator.run method, na nagbabalik ng instance ng PrimitiveJob object. Maaari mong makuha ang mga resulta mula sa job (bilang qiskit.primitives.PrimitiveResult object)
gamit ang qiskit.primitives.PrimitiveJob.result method.
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'>
Kunin ang expected value mula sa resultaβ
Ang output ng primitives result ay isang array ng mga PubResult object, kung saan ang bawat item ng array ay isang PubResult object na naglalaman sa data nito ng array ng mga evaluation na tumutugma sa bawat kombinasyon ng circuit-observable sa PUB.
Para makuha ang mga expectation value at metadata para sa unang (at sa kasong ito, tanging) circuit evaluation, dapat nating i-access ang evaluation data para sa 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': {}}
I-set ang mga run option ng Estimatorβ
Sa default, ang reference Estimator ay nagsasagawa ng eksaktong statevector calculation batay sa
quantum_info.Statevector class.
Gayunpaman, maaari itong baguhin para ipakilala ang epekto ng sampling overhead (kilala rin bilang "shot noise").
Tumatanggap ang Estimator ng precision argument na nagpapahayag ng mga error bar na dapat target ng
primitive implementation para sa mga estimate ng expectation value. Ito ang sampling overhead at eksklusibong tinukoy sa .run() method. Pinapayagan ka nitong i-fine-tune ang opsyon hanggang sa antas ng PUB.
# Estimate expectation values for two PUBs, both with 0.05 precision.
precise_job = estimator.run(
[(circuit, observable, parameter_values)], precision=0.05
)
Para sa isang kumpletong halimbawa, tingnan ang pahina ng Primitives examples.
Gamitin ang reference Samplerβ
Ang reference implementations ng SamplerV2 sa qiskit.primitives ay ang StatevectorSampler class. Tumatanggap ito ng mga circuit at parameter bilang input at ibinabalik ang mga resulta mula sa pag-sample ng mga output probability distribution bilang quasi-probability distribution ng mga output state.
Inihahanda ng sumusunod na code ang mga input na ginamit sa mga halimbawang susunod. Tandaan na ang mga halimbawang ito ay nagpapatakbo ng isang parametrized na circuit, ngunit maaari ka ring magpatakbo ng Sampler sa mga circuit na walang parameter.
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw("mpl", style="iqp")
Anumang quantum circuit na ipinasa sa Sampler ay dapat magsama ng measurements.
Ang Qiskit Runtime primitives workflow ay nangangailangan ng mga circuit na ma-transform para gamitin lamang ang mga instruction na sinusuportahan ng QPU (tinatawag na ISA circuits). Ang mga reference primitives ay tumatanggap pa rin ng mga abstract na instruction, dahil umaasa sila sa lokal na statevector simulations, ngunit ang pag-transpile ng circuit ay maaari pa ring maging kapaki-pakinabang sa mga tuntunin ng pag-optimize ng circuit.
# 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)
I-initialize ang SamplerV2β
Mag-instantiate ng qiskit.primitives.StatevectorSampler:
from qiskit.primitives import StatevectorSampler
sampler = StatevectorSampler()
Patakbuhin at kunin ang mga resultaβ
# 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'>
Tinatanggap ng mga Primitive ang maramihang PUB bilang input, at ang bawat PUB ay may sariling resulta. Kaya naman, maaari kang magpatakbo ng iba't ibang circuit na may iba't ibang kombinasyon ng parameter/observable, at makuha ang mga PUB result:
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'>
Kunin ang probability distribution o measurement outcomeβ
Ang mga sample ng measurement outcome ay ibinabalik bilang bitstrings o counts. Ipinapakita ng mga bitstring ang mga measurement outcome, pinapanatili ang pagkakasunud-sunod ng shot kung kailan sila sinukat. Inoorganisa ng mga Sampler result object ang data batay sa mga pangalan ng classical register ng kanilang input circuit, para sa compatibility sa mga dynamic na circuit.
Ang pangalan ng classical register ay default sa "meas". Gagamitin ang pangalang ito sa ibaba para i-access ang mga measurement bitstring.
# 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}
Baguhin ang mga run optionβ
Sa default, ang reference Sampler ay nagsasagawa ng eksaktong statevector calculation batay sa
quantum_info.Statevector class.
Gayunpaman, maaari itong baguhin para ipakilala ang epekto ng sampling overhead (kilala rin bilang "shot noise"). Para makatulong sa pamamahala ng overhead na ito, tinatanggap ng Sampler interface ang shots argument na maaaring tukuyin sa antas ng PUB.
Ipinapalagay ng halimbawang ito na tinukoy mo ang dalawang circuit.
# 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>
Para sa isang kumpletong halimbawa, tingnan ang pahina ng Primitives examples.
Mga susunod na hakbangβ
- Para sa mas mataas na performance na simulation na kayang hawakan ang mas malalaking circuit, o para isama ang mga noise model sa iyong simulation, tingnan ang Eksaktong at maingay na simulation gamit ang Qiskit Aer primitives.
- Para matutunan kung paano gamitin ang Quantum Composer para sa simulation, tingnan ang IBM Quantum Composer guide.
- Basahin ang Qiskit Estimator API reference.
- Basahin ang Qiskit Sampler API reference.
- Basahin ang Mag-migrate sa V2 primitives.