Something went wrong
Get started with primitives for Qiskit Runtime
Quantum primitives are foundational building blocks for designing and optimizing quantum workloads. They provide options to customize the iteration and execution of programs to maximize the solution quality from IBM quantum processing units (QPUs).
How they workEstimator
Calculate expectation values
Efficiently calculate and interpret expectation values of the quantum operators required for many algorithms with Estimator. Explore uses in molecular modeling, machine learning, and complex optimization problems.
View API ReferenceTry out Estimator
Run a single experiment
Use Estimator to determine the expectation value of a single circuit-observable pair
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit.quantum_info import SparsePauliOp, random_hermitian5from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator6 7n_qubits = 1278 9service = QiskitRuntimeService()10backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)11 12mat = np.real(random_hermitian(n_qubits, seed=1234))13circuit = IQP(mat)14observable = SparsePauliOp("Z" * n_qubits)15 16pm = generate_preset_pass_manager(backend=backend, optimization_level=1)17isa_circuit = pm.run(circuit)18isa_observable = observable.apply_layout(isa_circuit.layout)19 20estimator = Estimator(backend)21job = estimator.run([(isa_circuit, isa_observable)])22result = job.result()23 24print(f" > Expectation value: {result[0].data.evs}")25print(f" > Metadata: {result[0].metadata}")26
Run multiple experiments in a single job
Use Estimator to determine the expectation values of multiple circuit-observable pairs
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit.quantum_info import SparsePauliOp, random_hermitian5from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator6 7n_qubits = 1278 9service = QiskitRuntimeService()10backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)11 12rng = np.random.default_rng()13mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]14 15pubs = []16circuits = [IQP(mat) for mat in mats]17observables = [18 SparsePauliOp("X" * n_qubits),19 SparsePauliOp("Y" * n_qubits),20 SparsePauliOp("Z" * n_qubits),21]22 23# Get ISA circuits24pm = generate_preset_pass_manager(optimization_level=1, backend=backend)25 26for qc, obs in zip(circuits, observables):27 isa_circuit = pm.run(qc)28 isa_obs = obs.apply_layout(isa_circuit.layout)29 pubs.append((isa_circuit, isa_obs))30 31estimator = Estimator(backend)32job = estimator.run(pubs)33job_result = job.result()34 35for idx in range(len(pubs)):36 pub_result = job_result[idx]37 print(f">>> Expectation values for PUB {idx}: {pub_result.data.evs}")38 print(f">>> Standard errors for PUB {idx}: {pub_result.data.stds}")39
Run parametrized circuits
Run 3 experiments in a single job, leveraging parameter values to increase circuit reusability
1import numpy as np2 3from qiskit.circuit import QuantumCircuit, Parameter4from qiskit.quantum_info import SparsePauliOp5from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager6from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator7 8service = QiskitRuntimeService()9backend = service.least_busy(operational=True, simulator=False)10 11# Step 1: Map classical inputs to a quantum problem12theta = Parameter("θ")13 14chsh_circuit = QuantumCircuit(2)15chsh_circuit.h(0)16chsh_circuit.cx(0, 1)17chsh_circuit.ry(theta, 0)18 19number_of_phases = 2120phases = np.linspace(0, 2 * np.pi, number_of_phases)21individual_phases = [[ph] for ph in phases]22 23ZZ = SparsePauliOp.from_list([("ZZ", 1)])24ZX = SparsePauliOp.from_list([("ZX", 1)])25XZ = SparsePauliOp.from_list([("XZ", 1)])26XX = SparsePauliOp.from_list([("XX", 1)])27ops = [ZZ, ZX, XZ, XX]28 29# Step 2: Optimize problem for quantum execution.30 31pm = generate_preset_pass_manager(backend=backend, optimization_level=1)32chsh_isa_circuit = pm.run(chsh_circuit)33isa_observables = [operator.apply_layout(chsh_isa_circuit.layout) for operator in ops]34 35# Step 3: Execute using Qiskit primitives.36 37# Reshape observable array for broadcasting38reshaped_ops = np.fromiter(isa_observables, dtype=object)39reshaped_ops = reshaped_ops.reshape((4, 1))40 41estimator = Estimator(backend, options={"default_shots": int(1e4)})42job = estimator.run([(chsh_isa_circuit, reshaped_ops, individual_phases)])43# Get results for the first (and only) PUB44pub_result = job.result()[0]45print(f">>> Expectation values: {pub_result.data.evs}")46print(f">>> Standard errors: {pub_result.data.stds}")47print(f">>> Metadta: {pub_result.metadata}")48
Leverage sessions and advanced options
Explore session and advanced options to optimize circuit performance on QPUs
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit.quantum_info import SparsePauliOp, random_hermitian5from qiskit_ibm_runtime import QiskitRuntimeService, Session, EstimatorV2 as Estimator6 7n_qubits = 1278 9service = QiskitRuntimeService()10backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)11 12rng = np.random.default_rng(1234)13mat = np.real(random_hermitian(n_qubits, seed=rng))14circuit = IQP(mat)15mat = np.real(random_hermitian(n_qubits, seed=rng))16another_circuit = IQP(mat)17observable = SparsePauliOp("X" * n_qubits)18another_observable = SparsePauliOp("Y" * n_qubits)19 20pm = generate_preset_pass_manager(optimization_level=1, backend=backend)21isa_circuit = pm.run(circuit)22another_isa_circuit = pm.run(another_circuit)23isa_observable = observable.apply_layout(isa_circuit.layout)24another_isa_observable = another_observable.apply_layout(another_isa_circuit.layout)25 26with Session(service=service, backend=backend) as session:27 estimator = Estimator(mode=session)28 29 estimator.options.optimization_level = 130 estimator.options.resilience_level = 131 32 job = estimator.run([(isa_circuit, isa_observable)])33 another_job = estimator.run([(another_isa_circuit, another_isa_observable)])34 result = job.result()35 another_result = another_job.result()36 37 # first job38 print(f" > Expectation value: {result[0].data.evs}")39 print(f" > Metadata: {result[0].metadata}")40 41 # second job42 print(f" > Another Expectation value: {another_result[0].data.evs}")43 print(f" > More Metadata: {another_result[0].metadata}")44
Sampler
Generate quasi-probabilities
Generate entire error-mitigated quasi-probability distributions sampled from quantum circuit outputs. Leverage Sampler's capabilities for search and classification algorithms like Grover's and QSVM.
View API ReferenceTry out Sampler
Run a single experiment
Use Sampler to determine the quasi-probability distribution of a single circuit
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit.quantum_info import random_hermitian5from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler6 7n_qubits = 1278 9service = QiskitRuntimeService()10backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)11 12mat = np.real(random_hermitian(n_qubits, seed=1234))13circuit = IQP(mat)14circuit.measure_all()15 16pm = generate_preset_pass_manager(backend=backend, optimization_level=1)17isa_circuit = pm.run(circuit)18 19sampler = Sampler(backend)20job = sampler.run([isa_circuit])21result = job.result()22 23# Get results for the first (and only) PUB24pub_result = result[0]25 26print(f" > Counts: {pub_result.data.meas.get_counts()}")27
Run multiple experiments in a single job
Use Sampler to determine the quasi-probability distributions of multiple circuits in one job
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit.quantum_info import random_hermitian5from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler6 7n_qubits = 1278 9service = QiskitRuntimeService()10backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)11 12rng = np.random.default_rng()13mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]14circuits = [IQP(mat) for mat in mats]15for circuit in circuits:16 circuit.measure_all()17 18pm = generate_preset_pass_manager(backend=backend, optimization_level=1)19isa_circuits = pm.run(circuits)20 21sampler = Sampler(backend)22job = sampler.run(isa_circuits)23result = job.result()24 25for idx, pub_result in enumerate(result):26 print(f" > Counts for pub {idx}: {pub_result.data.meas.get_counts()}")27
Run parametrized circuits
Run 3 experiments in a single job, leveraging parameter values to increase circuit reusability
1import numpy as np2from qiskit.circuit.library import RealAmplitudes3from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager4from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler5 6n_qubits = 1277 8service = QiskitRuntimeService()9backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)10 11# Step 1: Map classical inputs to a quantum problem12circuit = RealAmplitudes(num_qubits=n_qubits, reps=2)13circuit.measure_all()14 15# Define three sets of parameters for the circuit16rng = np.random.default_rng(1234)17parameter_values = [18 rng.uniform(-np.pi, np.pi, size=circuit.num_parameters) for _ in range(3)19]20 21# Step 2: Optimize problem for quantum execution.22 23pm = generate_preset_pass_manager(backend=backend, optimization_level=1)24isa_circuit = pm.run(circuit)25 26# Step 3: Execute using Qiskit primitives.27sampler = Sampler(backend)28job = sampler.run([(isa_circuit, parameter_values)])29result = job.result()30# Get results for the first (and only) PUB31pub_result = result[0]32# Get counts from the classical register "meas".33print(f" >> Counts for the meas output register: {pub_result.data.meas.get_counts()}")34
Leverage sessions and advanced options
Explore session and advanced options to optimize circuit performance on QPUs
1import numpy as np2from qiskit.circuit.library import IQP3from qiskit.quantum_info import random_hermitian4from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager5from qiskit_ibm_runtime import Session, SamplerV2 as Sampler6from qiskit_ibm_runtime import QiskitRuntimeService7 8n_qubits = 1279 10service = QiskitRuntimeService()11backend = service.least_busy(operational=True, simulator=False, min_num_qubits=n_qubits)12 13rng = np.random.default_rng(1234)14mat = np.real(random_hermitian(n_qubits, seed=rng))15circuit = IQP(mat)16circuit.measure_all()17mat = np.real(random_hermitian(n_qubits, seed=rng))18another_circuit = IQP(mat)19another_circuit.measure_all()20 21pm = generate_preset_pass_manager(backend=backend, optimization_level=1)22isa_circuit = pm.run(circuit)23another_isa_circuit = pm.run(another_circuit)24 25with Session(backend=backend) as session:26 sampler = Sampler(mode=session)27 job = sampler.run([isa_circuit])28 another_job = sampler.run([another_isa_circuit])29 result = job.result()30 another_result = another_job.result()31 32# first job33print(f" > Counts for job 1: {result[0].data.meas.get_counts()}")34