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

Use opflow operators in dynamics #167

Closed
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
7 changes: 4 additions & 3 deletions qiskit_dynamics/models/hamiltonian_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from qiskit import QiskitError
from qiskit.quantum_info.operators import Operator
from qiskit.opflow import OperatorBase
from qiskit_dynamics.array import Array
from qiskit_dynamics.signals import Signal, SignalList
from qiskit_dynamics.type_utils import to_numeric_matrix_type, to_array
Expand Down Expand Up @@ -64,10 +65,10 @@ class HamiltonianModel(GeneratorModel):

def __init__(
self,
static_operator: Optional[Array] = None,
operators: Optional[List[Operator]] = None,
static_operator: Optional[Union[Array, Operator, OperatorBase]] = None,
operators: Optional[List[Union[Array, Operator, OperatorBase]]] = None,
signals: Optional[Union[SignalList, List[Signal]]] = None,
rotating_frame: Optional[Union[Operator, Array, RotatingFrame]] = None,
rotating_frame: Optional[Union[Operator, OperatorBase, Array, RotatingFrame]] = None,
in_frame_basis: bool = False,
evaluation_mode: str = "dense",
validate: bool = True,
Expand Down
9 changes: 6 additions & 3 deletions qiskit_dynamics/models/lindblad_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from qiskit import QiskitError
from qiskit.quantum_info.operators import Operator
from qiskit.opflow import OperatorBase
from qiskit_dynamics.array import Array
from qiskit_dynamics.type_utils import to_numeric_matrix_type
from qiskit_dynamics.signals import Signal, SignalList
Expand Down Expand Up @@ -105,13 +106,15 @@ class LindbladModel(BaseGeneratorModel):

def __init__(
self,
static_hamiltonian: Optional[Union[Array, csr_matrix]] = None,
hamiltonian_operators: Optional[Union[Array, List[csr_matrix]]] = None,
static_hamiltonian: Optional[Union[Array, Operator, OperatorBase, csr_matrix]] = None,
hamiltonian_operators: Optional[
List[Union[Array, Operator, OperatorBase, csr_matrix]]
] = None,
hamiltonian_signals: Optional[Union[List[Signal], SignalList]] = None,
static_dissipators: Optional[Union[Array, csr_matrix]] = None,
dissipator_operators: Optional[Union[Array, List[csr_matrix]]] = None,
dissipator_signals: Optional[Union[List[Signal], SignalList]] = None,
rotating_frame: Optional[Union[Operator, Array, RotatingFrame]] = None,
rotating_frame: Optional[Union[Operator, OperatorBase, Array, RotatingFrame]] = None,
in_frame_basis: bool = False,
evaluation_mode: Optional[str] = "dense",
validate: bool = True,
Expand Down
6 changes: 5 additions & 1 deletion qiskit_dynamics/models/rotating_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from qiskit import QiskitError
from qiskit.quantum_info.operators import Operator
from qiskit.opflow import OperatorBase
from qiskit.quantum_info.operators.predicates import is_hermitian_matrix
from qiskit_dynamics.array import Array
from qiskit_dynamics.type_utils import to_array, to_BCOO, to_numeric_matrix_type
Expand Down Expand Up @@ -58,7 +59,10 @@ class RotatingFrame:
"""

def __init__(
self, frame_operator: Union[Array, Operator], atol: float = 1e-10, rtol: float = 1e-10
self,
frame_operator: Union[Array, Operator, OperatorBase],
atol: float = 1e-10,
rtol: float = 1e-10,
):
"""Initialize with a frame operator.

Expand Down
27 changes: 21 additions & 6 deletions qiskit_dynamics/type_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from scipy.sparse import identity as sparse_identity

from qiskit.quantum_info.operators import Operator
from qiskit.opflow import OperatorBase
from qiskit_dynamics.array import Array
from qiskit_dynamics.dispatch import requires_backend

Expand Down Expand Up @@ -354,11 +355,11 @@ def isinstance_qutip_qobj(obj):

# pylint: disable=too-many-return-statements
def to_array(op: Union[Operator, Array, List[Operator], List[Array], spmatrix], no_iter=False):
"""Convert an operator or list of operators to an Array.
"""Convert an operator, operatorBase, or list of either to an Array.
Args:
op: Either an Operator to be converted to an array, a list of Operators
to be converted to a 3d array, or an array (which simply gets
returned)
op: Either a single `Operator` or `OperatorBase` to be converted to an array
or a list of either to be converted to a 3d array
or an array (which simply gets returned)
no_iter (Bool): Boolean determining whether to recursively unroll `Iterables`.
If recurring, this should be True to avoid making each element of the
input array into a separate Array.
Expand All @@ -383,6 +384,9 @@ def to_array(op: Union[Operator, Array, List[Operator], List[Array], spmatrix],
if type(op).__name__ == "BCOO":
return Array(op.todense())

if isinstance(op, OperatorBase):
return Array(op.to_matrix())

if isinstance(op, Iterable) and not no_iter:
op = Array([to_array(sub_op, no_iter=True) for sub_op in op])
elif isinstance(op, Iterable) and no_iter:
Expand Down Expand Up @@ -452,9 +456,18 @@ def to_BCOO(op: Union[Operator, Array, List[Operator], List[Array], spmatrix, "B


def to_numeric_matrix_type(
op: Union[Operator, Array, spmatrix, List[Operator], List[Array], List[spmatrix]]
op: Union[
Operator,
OperatorBase,
Array,
spmatrix,
List[Operator],
List[OperatorBase],
List[Array],
List[spmatrix],
]
):
"""Given an operator, array, sparse matrix, or a list of operators, arrays, or sparse matrices,
"""Given an operator, array, sparse matrix or a list of operators, arrays or sparse matrices,
attempts to leave them in their original form, only converting the operator to an array,
and converting lists as necessary. Summarized below:
- operator is converted to array
Expand Down Expand Up @@ -482,6 +495,8 @@ def to_numeric_matrix_type(
return op
elif isinstance(op, Operator):
return to_array(op)
elif isinstance(op, OperatorBase):
return to_array(op)

elif isinstance(op, Iterable) and isinstance(op[0], spmatrix):
return to_csr(op)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
features:
- |
``qiskit.opflow`` Operators can now be used to specify operators for the ``HamiltonianModel``
and the ``RotatingFrame``
Example::

from qiskit_dynamics.solvers import Solver
from qiskit.opflow import X, Y, Z

drift = Z/2
operators = [X,Y]
hamiltonian_solver = dynamics.Solver(
static_hamiltonian = drift,
hamiltonian_operators = operators,
rotating_frame = drift
)

3 changes: 3 additions & 0 deletions test/dynamics/test_type_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from scipy.sparse import csr_matrix

from qiskit.quantum_info.operators.operator import Operator
from qiskit.opflow import X, Y, Z
from qiskit_dynamics.array import Array
from qiskit_dynamics.type_utils import (
convert_state,
Expand Down Expand Up @@ -524,10 +525,12 @@ def test_to_numeric_matrix_type(self):
normal_array = Array(np.array(list_of_ops))
list_of_arrays = [Array(op) for op in list_of_ops]
op_arr = [Operator.from_label(s) for s in "XYZ"]
opflow_arr = [X, Y, Z]
sparse_matrices = [csr_matrix(op) for op in list_of_ops]
self.assertAllClose(to_numeric_matrix_type(list_of_ops), normal_array)
self.assertAllClose(to_numeric_matrix_type(list_of_arrays), normal_array)
self.assertAllClose(to_numeric_matrix_type(op_arr), list_of_arrays)
self.assertAllClose(to_numeric_matrix_type(opflow_arr), list_of_arrays)
for i in range(3):
self.assertAllCloseSparse(
to_numeric_matrix_type(sparse_matrices)[i], sparse_matrices[i]
Expand Down