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

Implement iterating/collecting PauliSumOp coefficients #5547 #5560

Merged
merged 7 commits into from
Jan 12, 2021
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
35 changes: 35 additions & 0 deletions qiskit/opflow/primitive_ops/pauli_sum_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from qiskit.circuit import Instruction, ParameterExpression
from qiskit.quantum_info import Pauli, SparsePauliOp
from qiskit.quantum_info.operators.symplectic.pauli_table import PauliTable
from qiskit.quantum_info.operators.custom_iterator import CustomIterator
from ..exceptions import OpflowError
from ..list_ops.summed_op import SummedOp
from ..list_ops.tensored_op import TensoredOp
Expand Down Expand Up @@ -59,6 +61,39 @@ def primitive_strings(self) -> Set[str]:
def num_qubits(self) -> int:
return self.primitive.num_qubits # type: ignore

@property
def coeffs(self):
"""Return the Pauli coefficients."""
return self.coeff * self.primitive.coeffs

def matrix_iter(self, sparse=False):
"""Return a matrix representation iterator.

This is a lazy iterator that converts each term in the PauliSumOp
into a matrix as it is used. To convert to a single matrix use the
:meth:`to_matrix` method.

Args:
sparse (bool): optionally return sparse CSR matrices if True,
otherwise return Numpy array matrices
(Default: False)

Returns:
MatrixIterator: matrix iterator object for the PauliTable.
"""
class MatrixIterator(CustomIterator):
"""Matrix representation iteration and item access."""
def __repr__(self):
return "<PauliSumOp_matrix_iterator at {}>".format(hex(id(self)))

def __getitem__(self, key):
sumopcoeff = self.obj.coeff * self.obj.primitive.coeffs[key]
mat = PauliTable._to_matrix(self.obj.primitive.table.array[key],
sparse=sparse)
return sumopcoeff * mat

return MatrixIterator(self)

def add(self, other: OperatorBase) -> OperatorBase:
if not self.num_qubits == other.num_qubits:
raise ValueError(
Expand Down
26 changes: 25 additions & 1 deletion test/python/opflow/test_pauli_sum_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
Zero,
)
from qiskit.circuit import Parameter, ParameterVector
from qiskit.quantum_info import Pauli, SparsePauliOp
from qiskit.quantum_info import Pauli, SparsePauliOp, PauliTable


class TestPauliSumOp(QiskitOpflowTestCase):
Expand Down Expand Up @@ -229,6 +229,30 @@ def test_from_list(self):
)
self.assertEqual(target, expected)

def test_matrix_iter(self):
"""Test PauliSumOp dense matrix_iter method."""
labels = ['III', 'IXI', 'IYY', 'YIZ', 'XYZ', 'III']
coeffs = np.array([1, 2, 3, 4, 5, 6])
table = PauliTable.from_labels(labels)
coeff = 10
op = PauliSumOp(SparsePauliOp(table, coeffs), coeff)
for idx, i in enumerate(op.matrix_iter()):
self.assertTrue(
np.array_equal(i, coeff * coeffs[idx] *
Pauli(labels[idx]).to_matrix()))

def test_matrix_iter_sparse(self):
"""Test PauliSumOp sparse matrix_iter method."""
labels = ['III', 'IXI', 'IYY', 'YIZ', 'XYZ', 'III']
coeffs = np.array([1, 2, 3, 4, 5, 6])
coeff = 10
table = PauliTable.from_labels(labels)
op = PauliSumOp(SparsePauliOp(table, coeffs), coeff)
for idx, i in enumerate(op.matrix_iter(sparse=True)):
self.assertTrue(
np.array_equal(i.toarray(), coeff * coeffs[idx] *
Pauli(labels[idx]).to_matrix()))


if __name__ == "__main__":
unittest.main()