mirror of https://github.com/Qiskit/qiskit.git
348 lines
14 KiB
Python
348 lines
14 KiB
Python
# This code is part of Qiskit.
|
|
#
|
|
# (C) Copyright IBM 2024.
|
|
#
|
|
# This code is licensed under the Apache License, Version 2.0. You may
|
|
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
#
|
|
# Any modifications or derivative works of this code must retain this
|
|
# copyright notice, and modified files need to carry a notice indicating
|
|
# that they have been altered from the originals.
|
|
|
|
"""Test SamplerPub class"""
|
|
|
|
import ddt
|
|
import numpy as np
|
|
|
|
from qiskit.circuit import QuantumCircuit, Parameter
|
|
from qiskit.primitives.containers.sampler_pub import SamplerPub
|
|
from qiskit.primitives.containers.bindings_array import BindingsArray
|
|
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
|
|
|
|
|
@ddt.ddt
|
|
class SamplerPubTestCase(QiskitTestCase):
|
|
"""Test the SamplerPub class."""
|
|
|
|
def test_properties(self):
|
|
"""Test SamplerPub properties."""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
parameter_values = BindingsArray(data={params: np.ones((10, 2))})
|
|
shots = 1000
|
|
|
|
pub = SamplerPub(
|
|
circuit=circuit,
|
|
parameter_values=parameter_values,
|
|
shots=shots,
|
|
)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(
|
|
pub.parameter_values,
|
|
parameter_values,
|
|
msg="incorrect value for `parameter_values` property",
|
|
)
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
|
|
def test_invalidate_circuit(self):
|
|
"""Test validation of circuit argument"""
|
|
# Invalid circuit, it is an instruction
|
|
circuit = QuantumCircuit(3).to_instruction()
|
|
with self.assertRaises(TypeError):
|
|
SamplerPub(circuit)
|
|
|
|
@ddt.data(100.0, True, False, 100j, 1e5)
|
|
def test_invalidate_shots_type(self, shots):
|
|
"""Test validation of shots argument type"""
|
|
with self.assertRaises(TypeError, msg=f"shots type {type(shots)} should raise TypeError"):
|
|
SamplerPub(QuantumCircuit(), shots=shots)
|
|
|
|
@ddt.data(-1, 0)
|
|
def test_invalidate_shots_value(self, shots):
|
|
"""Test invalid shots argument value"""
|
|
with self.assertRaises(ValueError, msg="non-positive shots should raise ValueError"):
|
|
SamplerPub(QuantumCircuit(), shots=shots)
|
|
|
|
@ddt.idata(range(5))
|
|
def test_validate_no_parameters(self, num_params):
|
|
"""Test unparameterized circuit raises for parameter values"""
|
|
circuit = QuantumCircuit(2)
|
|
parameter_values = BindingsArray(
|
|
{(f"a{idx}" for idx in range(num_params)): np.zeros((2, num_params))}, shape=2
|
|
)
|
|
if num_params == 0:
|
|
SamplerPub(circuit, parameter_values=parameter_values)
|
|
return
|
|
|
|
with self.assertRaises(ValueError):
|
|
SamplerPub(circuit, parameter_values=parameter_values)
|
|
|
|
@ddt.idata(range(5))
|
|
def test_validate_num_parameters(self, num_params):
|
|
"""Test unparameterized circuit raises for parameter values"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
parameter_values = BindingsArray(
|
|
{(f"a{idx}" for idx in range(num_params)): np.zeros((2, num_params))}, shape=2
|
|
)
|
|
if num_params == len(params):
|
|
SamplerPub(circuit, parameter_values=parameter_values)
|
|
return
|
|
|
|
with self.assertRaises(ValueError):
|
|
SamplerPub(circuit, parameter_values=parameter_values)
|
|
|
|
@ddt.data((), (3,), (2, 3))
|
|
def test_shaped_zero_parameter_values(self, shape):
|
|
"""Test Passing in a shaped array with no parameters works"""
|
|
circuit = QuantumCircuit(2)
|
|
parameter_values = BindingsArray({(): np.zeros((*shape, 0))}, shape=shape)
|
|
pub = SamplerPub(circuit, parameter_values=parameter_values)
|
|
self.assertEqual(pub.shape, shape)
|
|
|
|
def test_coerce_circuit(self):
|
|
"""Test coercing an unparameterized circuit"""
|
|
circuit = QuantumCircuit(10)
|
|
circuit.measure_all()
|
|
|
|
pub = SamplerPub.coerce(circuit)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, None, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape, (), msg="incorrect shape for `parameter_values` property"
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
0,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
def test_invalid_coerce_circuit(self):
|
|
"""Test coercing parameterized circuit raises"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(10)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
with self.assertRaises(ValueError):
|
|
SamplerPub.coerce(circuit)
|
|
|
|
@ddt.data(1, 10, 100, 1000)
|
|
def test_coerce_pub_with_shots(self, shots):
|
|
"""Test coercing a SamplerPub"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
pub1 = SamplerPub(
|
|
circuit=circuit,
|
|
parameter_values=BindingsArray(data={params: np.ones((10, 2))}),
|
|
shots=1000,
|
|
)
|
|
pub2 = SamplerPub.coerce(pub1, shots=shots)
|
|
self.assertEqual(pub1, pub2)
|
|
|
|
@ddt.data(1, 10, 100, 1000)
|
|
def test_coerce_pub_without_shots(self, shots):
|
|
"""Test coercing a SamplerPub"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
pub1 = SamplerPub(
|
|
circuit=circuit,
|
|
parameter_values=BindingsArray(data={params: np.ones((10, 2))}),
|
|
shots=None,
|
|
)
|
|
pub2 = SamplerPub.coerce(pub1, shots=shots)
|
|
self.assertEqual(pub1.circuit, pub2.circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(
|
|
pub1.parameter_values,
|
|
pub2.parameter_values,
|
|
msg="incorrect value for `parameter_values` property",
|
|
)
|
|
self.assertEqual(pub2.shots, shots, msg="incorrect value for `shots` property")
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_1(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
circuit = QuantumCircuit(2)
|
|
circuit.measure_all()
|
|
pub = SamplerPub.coerce((circuit,), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape, (), msg="incorrect shape for `parameter_values` property"
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
0,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_2(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
parameter_values = np.zeros((4, 3, 2))
|
|
pub = SamplerPub.coerce((circuit, parameter_values), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape,
|
|
(4, 3),
|
|
msg="incorrect shape for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
2,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_2_trivial_params(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
circuit = QuantumCircuit(2)
|
|
circuit.measure_all()
|
|
pub = SamplerPub.coerce((circuit, None), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape, (), msg="incorrect shape for `parameter_values` property"
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
0,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_3(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
parameter_values = np.zeros((4, 3, 2))
|
|
pub = SamplerPub.coerce((circuit, parameter_values, 1000), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, 1000, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape,
|
|
(4, 3),
|
|
msg="incorrect shape for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
2,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_3_trivial_shots(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
circuit.measure_all()
|
|
parameter_values = np.zeros((4, 3, 2))
|
|
pub = SamplerPub.coerce((circuit, parameter_values, None), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape,
|
|
(4, 3),
|
|
msg="incorrect shape for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
2,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
@ddt.data(None, 1, 100)
|
|
def test_coerce_tuple_3_trivial_params_shots(self, shots):
|
|
"""Test coercing circuit and parameter values"""
|
|
circuit = QuantumCircuit(2)
|
|
circuit.measure_all()
|
|
pub = SamplerPub.coerce((circuit, None, None), shots=shots)
|
|
self.assertEqual(pub.circuit, circuit, msg="incorrect value for `circuit` property")
|
|
self.assertEqual(pub.shots, shots, msg="incorrect value for `shots` property")
|
|
# Check bindings array, this is more cumbersome since the class doesn't have an eq method
|
|
self.assertIsInstance(
|
|
pub.parameter_values,
|
|
BindingsArray,
|
|
msg="incorrect type for `parameter_values` property",
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.shape, (), msg="incorrect shape for `parameter_values` property"
|
|
)
|
|
self.assertEqual(
|
|
pub.parameter_values.num_parameters,
|
|
0,
|
|
msg="incorrect num parameters for `parameter_values` property",
|
|
)
|
|
|
|
def test_coerce_pub_with_exact_types(self):
|
|
"""Test coercing a SamplerPub with exact types."""
|
|
params = (Parameter("a"), Parameter("b"))
|
|
circuit = QuantumCircuit(2)
|
|
circuit.rx(params[0], 0)
|
|
circuit.ry(params[1], 1)
|
|
|
|
params = BindingsArray(data={params: np.ones((10, 2))})
|
|
pub = SamplerPub.coerce((circuit, params))
|
|
self.assertIs(pub.circuit, circuit)
|
|
self.assertIs(pub.parameter_values, params)
|