Fix `EvolvedOp.to_instruction` (#8384)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Julien Gacon 2022-07-21 10:38:55 +02:00 committed by GitHub
parent d9af1d1f7a
commit 1312624309
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 1 deletions

View File

@ -169,7 +169,7 @@ class EvolvedOp(PrimitiveOp):
# pylint: disable=arguments-differ
def to_instruction(self, massive: bool = False) -> Instruction:
mat_op = self.primitive.to_matrix_op(massive=massive)
mat_op = self.to_matrix_op(massive=massive)
if not isinstance(mat_op, MatrixOp):
raise OpflowError("to_instruction is not allowed for ListOp.")
return mat_op.to_instruction()

View File

@ -0,0 +1,18 @@
---
fixes:
- |
Fix :meth:`~.EvolvedOp.to_instruction` which previously tried to create a
:class:`~.UnitaryGate` without exponentiating the operator to evolve.
Since this operator is generally not unitary, this raised an error (and if
the operator would have been unitary by chance, it would not have been the expected result).
Now calling :meth:`~.EvolvedOp.to_instruction` correctly produces a gate
that implements the time evolution of the operator it holds::
>>> from qiskit.opflow import EvolvedOp, X
>>> op = EvolvedOp(0.5 * X)
>>> op.to_instruction()
Instruction(
name='unitary', num_qubits=1, num_clbits=0,
params=[array([[0.87758256+0.j, 0.-0.47942554j], [0.-0.47942554j, 0.87758256+0.j]])]
)

View File

@ -19,6 +19,7 @@ import scipy.linalg
import qiskit
from qiskit.circuit import Parameter, ParameterVector
from qiskit.extensions import UnitaryGate
from qiskit.opflow import (
CX,
CircuitOp,
@ -364,6 +365,19 @@ class TestEvolution(QiskitOpflowTestCase):
)
np.testing.assert_array_almost_equal(evolution.to_matrix(), matrix)
def test_evolved_op_to_instruction(self):
"""Test calling `to_instruction` on a plain EvolvedOp.
Regression test of Qiskit/qiskit-terra#8025.
"""
op = EvolvedOp(0.5 * X)
circuit = op.to_instruction()
unitary = scipy.linalg.expm(-0.5j * X.to_matrix())
expected = UnitaryGate(unitary)
self.assertEqual(circuit, expected)
if __name__ == "__main__":
unittest.main()