Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiplication of SparsePauliOp and ParameterExpression #10264

Merged
merged 7 commits into from
Jun 26, 2023
4 changes: 2 additions & 2 deletions qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ def _add(self, other, qargs=None):
return SparsePauliOp(paulis, coeffs, ignore_pauli_phase=True, copy=False)

def _multiply(self, other):
if not isinstance(other, Number):
raise QiskitError("other is not a number")
if not isinstance(other, (Number, ParameterExpression)):
raise QiskitError("other is neither a Number nor a Parameter/ParameterExpression")
if other == 0:
# Check edge case that we deleted all Paulis
# In this case we return an identity Pauli with a zero coefficient
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
features:
- |
Adds support for multiplication of :class:`.SparsePauliOp` objects
with :class:`.Parameter` objects by using the * operator, for example::

from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp

param = Parameter("a")
op = SparsePauliOp("X")
param * op

fixes:
- |
Fixes issue `#10185 <https://github.com/Qiskit/qiskit-terra/issues/10185>`.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from ddt import ddt

from qiskit import QiskitError
from qiskit.circuit import Parameter, ParameterVector
from qiskit.circuit import ParameterExpression, Parameter, ParameterVector
from qiskit.circuit.parametertable import ParameterView
from qiskit.quantum_info.operators import Operator, Pauli, PauliList, PauliTable, SparsePauliOp
from qiskit.test import QiskitTestCase
Expand Down Expand Up @@ -588,14 +588,28 @@ def test_sub_qargs(self, num_qubits):
self.assertEqual(value, target)
np.testing.assert_array_equal(op.paulis.phase, np.zeros(op.size))

@combine(num_qubits=[1, 2, 3], value=[0, 1, 1j, -3 + 4.4j, np.int64(2)], param=[None, "a"])
@combine(
num_qubits=[1, 2, 3],
value=[
0,
1,
1j,
-3 + 4.4j,
np.int64(2),
Parameter("x"),
0 * Parameter("x"),
(-2 + 1.7j) * Parameter("x"),
],
param=[None, "a"],
)
def test_mul(self, num_qubits, value, param):
"""Test * method for {num_qubits} qubits and value {value}."""
spp_op = self.random_spp_op(num_qubits, 2**num_qubits, param)
target = value * spp_op.to_matrix()
op = value * spp_op
value_mat = op.to_matrix()
if value != 0 and param is not None:
has_parameters = isinstance(value, ParameterExpression) or param is not None
if value != 0 and has_parameters:
value_mat = bind_parameters_to_one(value_mat)
target = bind_parameters_to_one(target)
if value == 0:
Expand All @@ -606,7 +620,7 @@ def test_mul(self, num_qubits, value, param):
target = spp_op.to_matrix() * value
op = spp_op * value
value_mat = op.to_matrix()
if value != 0 and param is not None:
if value != 0 and has_parameters:
value_mat = bind_parameters_to_one(value_mat)
target = bind_parameters_to_one(target)
if value == 0:
Expand Down