Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Use Operator rather than unitary simulator to convert circuit to unitary matrix #1224

Merged
merged 7 commits into from
Sep 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions qiskit/aqua/operators/primitive_ops/circuit_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import logging
import numpy as np

from qiskit import QuantumCircuit, BasicAer, execute
import qiskit
from qiskit import QuantumCircuit
from qiskit.circuit.library import IGate
from qiskit.circuit import Instruction, ParameterExpression

Expand Down Expand Up @@ -139,14 +140,7 @@ def to_matrix(self, massive: bool = False) -> np.ndarray:
' in this case {0}x{0} elements.'
' Set massive=True if you want to proceed.'.format(2 ** self.num_qubits))

# NOTE: not reversing qubits!! We generally reverse endianness when converting between
# circuit or Pauli representation and matrix representation, but we don't need to here
# because the Unitary simulator already presents the endianness of the circuit unitary in
# forward endianness.
unitary_backend = BasicAer.get_backend('unitary_simulator')
unitary = execute(self.to_circuit(),
unitary_backend,
optimization_level=0).result().get_unitary()
unitary = qiskit.quantum_info.Operator(self.to_circuit()).data
# pylint: disable=cyclic-import
from ..operator_globals import EVAL_SIG_DIGITS
return np.round(unitary * self.coeff, decimals=EVAL_SIG_DIGITS)
Expand Down
6 changes: 3 additions & 3 deletions qiskit/aqua/operators/primitive_ops/pauli_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@ def exp_i(self) -> OperatorBase:
else self.coeff
# Y rotation
if corrected_x[sig_qubit_index] and corrected_z[sig_qubit_index]:
rot_op = PrimitiveOp(RYGate(coeff))
rot_op = PrimitiveOp(RYGate(2 * coeff))
# Z rotation
elif corrected_z[sig_qubit_index]:
rot_op = PrimitiveOp(RZGate(coeff))
rot_op = PrimitiveOp(RZGate(2 * coeff))
# X rotation
elif corrected_x[sig_qubit_index]:
rot_op = PrimitiveOp(RXGate(coeff))
rot_op = PrimitiveOp(RXGate(2 * coeff))

from ..operator_globals import I
left_pad = I.tensorpower(sig_qubit_index)
Expand Down
9 changes: 9 additions & 0 deletions releasenotes/notes/pauli-expi-c0c97395190622c0.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
fixes:
- |
Make PauliOp.exp_i() generate the correct matrix with the following changes.
1) There was previously an error in the phase of a factor of 2.
2) The global phase was ignored when converting the circuit
to a matrix. We now use qiskit.quantum_info.Operator, which is
generally useful for converting a circuit to a unitary matrix,
when possible.
8 changes: 8 additions & 0 deletions test/aqua/operators/test_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import numpy as np
import scipy.linalg

import qiskit
from qiskit.circuit import ParameterVector, Parameter

from qiskit.aqua.operators import (X, Y, Z, I, CX, H, ListOp, CircuitOp, Zero, EvolutionFactory,
Expand All @@ -29,6 +30,13 @@
class TestEvolution(QiskitAquaTestCase):
"""Evolution tests."""

def test_exp_i(self):
""" exponential of Pauli test """
op = Z.exp_i()
gate = op.to_circuit().data[0][0]
self.assertIsInstance(gate, qiskit.circuit.library.RZGate)
self.assertEqual(gate.params[0], 2)

def test_pauli_evolution(self):
""" pauli evolution test """
op = (-1.052373245772859 * I ^ I) + \
Expand Down
9 changes: 9 additions & 0 deletions test/aqua/operators/test_op_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from test.aqua import QiskitAquaTestCase
import itertools
import scipy
from scipy.stats import unitary_group
import numpy as np
from ddt import ddt, data
Expand Down Expand Up @@ -201,6 +202,14 @@ def test_to_matrix(self):
np.testing.assert_array_almost_equal(
op6.to_matrix(), op5.to_matrix() + Operator.from_label('+r').data)

def test_circuit_op_to_matrix(self):
""" test CircuitOp.to_matrix """
qc = QuantumCircuit(1)
qc.rz(1.0, 0)
qcop = CircuitOp(qc)
np.testing.assert_array_almost_equal(
qcop.to_matrix(), scipy.linalg.expm(-0.5j * Z.to_matrix()))

def test_matrix_to_instruction(self):
"""Test MatrixOp.to_instruction yields an Instruction object."""
matop = (H ^ 3).to_matrix_op()
Expand Down