|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
QDrift Class
|
|
|
|
"""
|
|
|
|
from typing import List, Union, cast
|
|
|
|
import numpy as np
|
|
|
|
from qiskit.opflow.evolutions.trotterizations.trotterization_base import TrotterizationBase
|
|
from qiskit.opflow.list_ops.composed_op import ComposedOp
|
|
from qiskit.opflow.list_ops.summed_op import SummedOp
|
|
from qiskit.opflow.operator_base import OperatorBase
|
|
from qiskit.opflow.primitive_ops.pauli_sum_op import PauliSumOp
|
|
from qiskit.opflow.primitive_ops.primitive_op import PrimitiveOp
|
|
from qiskit.utils import algorithm_globals
|
|
from qiskit.utils.deprecation import deprecate_func
|
|
|
|
|
|
|
|
|
|
class QDrift(TrotterizationBase):
|
|
"""Deprecated: The QDrift Trotterization method, which selects each each term in the
|
|
Trotterization randomly, with a probability proportional to its weight. Based on the work
|
|
of Earl Campbell in https://arxiv.org/abs/1811.08017.
|
|
"""
|
|
|
|
@deprecate_func(
|
|
since="0.24.0",
|
|
additional_msg="For code migration guidelines, visit https://qisk.it/opflow_migration.",
|
|
)
|
|
def __init__(self, reps: int = 1) -> None:
|
|
r"""
|
|
Args:
|
|
reps: The number of times to repeat the Trotterization circuit.
|
|
"""
|
|
super().__init__(reps=reps)
|
|
|
|
def convert(self, operator: OperatorBase) -> OperatorBase:
|
|
if not isinstance(operator, (SummedOp, PauliSumOp)):
|
|
raise TypeError("Trotterization converters can only convert SummedOp or PauliSumOp.")
|
|
|
|
if not isinstance(operator.coeff, (float, int)):
|
|
raise TypeError(
|
|
"Trotterization converters can only convert operators with real coefficients."
|
|
)
|
|
|
|
operator_iter: Union[PauliSumOp, List[PrimitiveOp]]
|
|
|
|
if isinstance(operator, PauliSumOp):
|
|
operator_iter = operator
|
|
coeffs = operator.primitive.coeffs
|
|
coeff = operator.coeff
|
|
else:
|
|
operator_iter = cast(List[PrimitiveOp], operator.oplist)
|
|
coeffs = [op.coeff for op in operator_iter]
|
|
coeff = operator.coeff
|
|
|
|
|
|
weights = np.abs(coeffs)
|
|
lambd = np.sum(weights)
|
|
|
|
N = 2 * (lambd**2) * (coeff**2)
|
|
factor = lambd * coeff / (N * self.reps)
|
|
|
|
|
|
scaled_ops = [(op * (factor / op.coeff)).exp_i() for op in operator_iter]
|
|
sampled_ops = algorithm_globals.random.choice(
|
|
scaled_ops, size=(int(N * self.reps),), p=weights / lambd
|
|
)
|
|
|
|
return ComposedOp(sampled_ops).reduce()
|
|
|