Parametrized circuits¶
This tutorial shows you can submit parametrized quantum circuits to the POVMSampler
.
[1]:
%load_ext autoreload
%autoreload 2
Parametrized Circuit¶
Let us look at a 2-qubit quantum circuit with 5 parameters.
[2]:
from qiskit.circuit.library import RealAmplitudes
# Prepare inputs.
num_qubits = 2
qc = RealAmplitudes(num_qubits=num_qubits, reps=2)
qc.draw()
[2]:
┌────────────────────────────────────────────────┐ q_0: ┤0 ├ │ RealAmplitudes(θ[0],θ[1],θ[2],θ[3],θ[4],θ[5]) │ q_1: ┤1 ├ └────────────────────────────────────────────────┘
[3]:
import numpy as np
# Assume you want to run the circuit with two different sets of parameter values
theta = np.array(
[
[0, 1, 1, 2, 3, 5], # first set of parameter values
[0, 1, 1, 2, 2, 5], # second set of parameter values
]
)
# Shape of the resulting `BindingsArray` is (2,) with `num_param` equal to 6
Measurement¶
We now look at the implementation of Classical Shadows measurement
[4]:
from povm_toolbox.library import ClassicalShadows
# By default, the Classical Shadows (CS) measurement uses X,Y,Z measurements with equal probability.
cs_implementation = ClassicalShadows(num_qubits=num_qubits, seed=342)
# Define the default shot budget.
shots = 4096
[5]:
pub = (qc, theta, shots, cs_implementation)
[6]:
from povm_toolbox.sampler import POVMSampler
from qiskit.primitives import StatevectorSampler as Sampler
# Internal `BaseSampler`
sampler = Sampler(seed=432)
# Actual `POVMSampler` instance
povm_sampler = POVMSampler(sampler=sampler)
# Submit the job by specifying the list of PUBs to run, here we have a single PUB.
job = povm_sampler.run([pub])
Results¶
We submitted a single PUB, hence the PrimitiveResult
will contain only one POVMPubResult
.
[7]:
pub_result = job.result()[0]
print(pub_result)
# Note that the pub result will contain a `BitArray` that has the same shape
# as the submitted `BindingsArray`, which is (2,) in this example.
print(pub_result.get_counts().shape)
POVMPubResult(data=DataBin<2>(povm_measurement_creg=BitArray(<shape=(2,), num_shots=4096, num_bits=2>)), metadata=RPMMetadata(povm_implementation=ClassicalShadows(num_qubits=2), composed_circuit=<qiskit.circuit.library.n_local.real_amplitudes.RealAmplitudes object at 0x177cbbd40>, pvm_keys=np.ndarray<2,4096,2>))
(2,)
We now define our POVM post-processor, which will use the result object to estimate expectation values of some observables.
[8]:
from povm_toolbox.post_processor.povm_post_processor import POVMPostProcessor
post_processor = POVMPostProcessor(pub_result)
Since the POVM implementation that we used is informationally complete, we can define our observables of interest after the sampling process.
[9]:
from qiskit.quantum_info import SparsePauliOp
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("II", 1), ("XX", 1), ("YY", -1), ("ZZ", 1)])
The post-processor will return two expectation values corresponding to the two different sets of parameter values that were submitted.
[10]:
exp_value, std = post_processor.get_expectation_value(H1)
print(exp_value)
[1.98364258 4.71411133]
If we are interested to evaluate an observable only for one set of parameter values, this set can be specified through the loc
argument.
[11]:
exp_value, std = post_processor.get_expectation_value(H2, loc=1)
print(exp_value)
0.05297851562500033
Further example¶
Let us look at a BindingsArray
instance with a more complex shape.
[12]:
bindings_array_shape = (3, 4)
num_param = 6
theta = np.arange(72).reshape((*bindings_array_shape, num_param))
[13]:
job = povm_sampler.run([(qc, theta, shots, cs_implementation)])
pub_result = job.result()[0]
print(pub_result.get_counts().shape)
(3, 4)
[14]:
post_processor = POVMPostProcessor(pub_result)
exp_values, std = post_processor.get_expectation_value(H1)
print(exp_values)
print(std)
[[-2.65698242 -1.44775391 4.69360352 3.39575195]
[-4.09399414 -2.57861328 -1.41918945 5.98339844]
[ 4.74121094 5.98266602 -0.06347656 -0.11474609]]
[[0.09684276 0.07191009 0.05729555 0.07203544]
[0.0796096 0.09563027 0.10687004 0.07980559]
[0.0973881 0.07996116 0.08056718 0.07930243]]