mirror of https://github.com/Qiskit/qiskit.git
Removes old VarQTE algorithm code (without primitives). (#8750)
* Removed old VarQTE and tests. * Removed reno * Updated init. * Updated init. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
64a9eb1e4a
commit
8bb1c01a8b
|
@ -94,17 +94,6 @@ knowledge to do this in that application domain.
|
|||
VQD
|
||||
|
||||
|
||||
Variational Quantum Time Evolution
|
||||
----------------------------------
|
||||
|
||||
Classes used by variational quantum time evolution algorithms - VarQITE and VarQRTE.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
|
||||
evolvers.variational
|
||||
|
||||
|
||||
Evolvers
|
||||
--------
|
||||
|
||||
|
@ -124,8 +113,6 @@ used to train Quantum Boltzmann Machine Neural Networks for example.
|
|||
RealEvolver
|
||||
ImaginaryEvolver
|
||||
TrotterQRTE
|
||||
VarQITE
|
||||
VarQRTE
|
||||
PVQD
|
||||
PVQDResult
|
||||
EvolutionResult
|
||||
|
@ -322,8 +309,6 @@ from .exceptions import AlgorithmError
|
|||
from .aux_ops_evaluator import eval_observables
|
||||
from .observables_evaluator import estimate_observables
|
||||
from .evolvers.trotterization import TrotterQRTE
|
||||
from .evolvers.variational.var_qite import VarQITE
|
||||
from .evolvers.variational.var_qrte import VarQRTE
|
||||
|
||||
from .evolvers.pvqd import PVQD, PVQDResult
|
||||
|
||||
|
@ -353,8 +338,6 @@ __all__ = [
|
|||
"RealTimeEvolver",
|
||||
"ImaginaryTimeEvolver",
|
||||
"TrotterQRTE",
|
||||
"VarQITE",
|
||||
"VarQRTE",
|
||||
"EvolutionResult",
|
||||
"EvolutionProblem",
|
||||
"TimeEvolutionResult",
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""
|
||||
Variational Quantum Time Evolutions (:mod:`qiskit.algorithms.evolvers.variational`)
|
||||
===================================================================================
|
||||
|
||||
Algorithms for performing Variational Quantum Time Evolution of quantum states,
|
||||
which can be tailored to near-term devices.
|
||||
:class:`~qiskit.algorithms.evolvers.variational.VarQTE` base class exposes an interface, compliant
|
||||
with the Quantum Time Evolution Framework in Qiskit Terra, that is implemented by
|
||||
:class:`~qiskit.algorithms.VarQRTE` and :class:`~qiskit.algorithms.VarQITE` classes for real and
|
||||
imaginary time evolution respectively. The variational approach is taken according to a variational
|
||||
principle chosen by a user.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block::
|
||||
|
||||
from qiskit import BasicAer
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, I, Z, Y, X
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
from qiskit.algorithms import VarQITE
|
||||
|
||||
# define a Hamiltonian
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
).reduce()
|
||||
|
||||
# define a parametrized initial state to be evolved
|
||||
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=1)
|
||||
parameters = ansatz.parameters
|
||||
|
||||
# define values of initial parameters
|
||||
init_param_values = np.zeros(len(ansatz.parameters))
|
||||
for i in range(len(ansatz.parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
# define a variational principle
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
# optionally define a backend
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
# define evolution time
|
||||
time = 1
|
||||
|
||||
# define evolution problem
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
|
||||
# instantiate the algorithm
|
||||
var_qite = VarQITE(ansatz, var_principle, param_dict, quantum_instance=backend)
|
||||
|
||||
# run the algorithm/evolve the state
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
||||
|
||||
.. currentmodule:: qiskit.algorithms.evolvers.variational
|
||||
|
||||
Variational Principles
|
||||
----------------------
|
||||
|
||||
Variational principles can be used to simulate quantum time evolution by propagating the parameters
|
||||
of a parameterized quantum circuit.
|
||||
|
||||
They can be divided into two categories:
|
||||
|
||||
1) Variational Quantum Imaginary Time Evolution
|
||||
Given a Hamiltonian, a time and a variational ansatz, the variational principle describes a
|
||||
variational principle according to the normalized Wick-rotated Schroedinger equation.
|
||||
|
||||
2) Variational Quantum Real Time Evolution
|
||||
Given a Hamiltonian, a time and a variational ansatz, the variational principle describes a
|
||||
variational principle according to the Schroedinger equation.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
:template: autosummary/class_no_inherited_members.rst
|
||||
|
||||
VariationalPrinciple
|
||||
RealVariationalPrinciple
|
||||
ImaginaryVariationalPrinciple
|
||||
RealMcLachlanPrinciple
|
||||
ImaginaryMcLachlanPrinciple
|
||||
|
||||
ODE solvers
|
||||
-----------
|
||||
ODE solvers that implement the SciPy ODE Solver interface. The Forward Euler Solver is
|
||||
a preferred choice in the presence of noise. One might also use solvers provided by SciPy directly,
|
||||
e.g. RK45.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
:template: autosummary/class_no_inherited_members.rst
|
||||
|
||||
ForwardEulerSolver
|
||||
|
||||
"""
|
||||
from .solvers.ode.forward_euler_solver import ForwardEulerSolver
|
||||
from .var_qte import VarQTE
|
||||
from .variational_principles.variational_principle import VariationalPrinciple
|
||||
from .variational_principles import RealVariationalPrinciple, ImaginaryVariationalPrinciple
|
||||
from .variational_principles.imaginary_mc_lachlan_principle import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from .variational_principles.real_mc_lachlan_principle import (
|
||||
RealMcLachlanPrinciple,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ForwardEulerSolver",
|
||||
"VarQTE",
|
||||
"VariationalPrinciple",
|
||||
"RealVariationalPrinciple",
|
||||
"ImaginaryVariationalPrinciple",
|
||||
"RealMcLachlanPrinciple",
|
||||
"ImaginaryMcLachlanPrinciple",
|
||||
]
|
|
@ -1,44 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""
|
||||
Solvers (:mod:`qiskit.algorithms.evolvers.variational.solvers`)
|
||||
===============================================================
|
||||
|
||||
This package contains the necessary classes to solve systems of equations arising in the
|
||||
Variational Quantum Time Evolution. They include ordinary differential equations (ODE) which
|
||||
describe ansatz parameter propagation and systems of linear equations.
|
||||
|
||||
|
||||
Systems of Linear Equations Solver
|
||||
----------------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
:template: autosummary/class_no_inherited_members.rst
|
||||
|
||||
VarQTELinearSolver
|
||||
|
||||
|
||||
ODE Solver
|
||||
----------
|
||||
.. autosummary::
|
||||
:toctree: ../stubs/
|
||||
:template: autosummary/class_no_inherited_members.rst
|
||||
|
||||
VarQTEOdeSolver
|
||||
"""
|
||||
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.var_qte_ode_solver import VarQTEOdeSolver
|
||||
from qiskit.algorithms.evolvers.variational.solvers.var_qte_linear_solver import VarQTELinearSolver
|
||||
|
||||
__all__ = ["VarQTELinearSolver", "VarQTEOdeSolver"]
|
|
@ -1,13 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""ODE Solvers"""
|
|
@ -1,52 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Abstract class for generating ODE functions."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Iterable, Dict, Optional
|
||||
from qiskit.circuit import Parameter
|
||||
from ..var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
|
||||
|
||||
class AbstractOdeFunction(ABC):
|
||||
"""Abstract class for generating ODE functions."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
varqte_linear_solver: VarQTELinearSolver,
|
||||
error_calculator,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
t_param: Optional[Parameter] = None,
|
||||
) -> None:
|
||||
|
||||
self._varqte_linear_solver = varqte_linear_solver
|
||||
self._error_calculator = error_calculator
|
||||
self._param_dict = param_dict
|
||||
self._t_param = t_param
|
||||
|
||||
@abstractmethod
|
||||
def var_qte_ode_function(self, time: float, parameters_values: Iterable) -> Iterable:
|
||||
"""
|
||||
Evaluates an ODE function for a given time and parameter values. It is used by an ODE
|
||||
solver.
|
||||
|
||||
Args:
|
||||
time: Current time of evolution.
|
||||
parameters_values: Current values of parameters.
|
||||
|
||||
Returns:
|
||||
ODE gradient arising from solving a system of linear equations.
|
||||
"""
|
||||
pass
|
|
@ -1,73 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Forward Euler ODE solver."""
|
||||
|
||||
from typing import Sequence
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import OdeSolver
|
||||
from scipy.integrate._ivp.base import ConstantDenseOutput
|
||||
|
||||
|
||||
class ForwardEulerSolver(OdeSolver):
|
||||
"""Forward Euler ODE solver."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
function: callable,
|
||||
t0: float,
|
||||
y0: Sequence,
|
||||
t_bound: float,
|
||||
vectorized: bool = False,
|
||||
support_complex: bool = False,
|
||||
num_t_steps: int = 15,
|
||||
):
|
||||
"""
|
||||
Forward Euler ODE solver that implements an interface from SciPy.
|
||||
|
||||
Args:
|
||||
function: Right-hand side of the system. The calling signature is ``fun(t, y)``. Here
|
||||
``t`` is a scalar, and there are two options for the ndarray ``y``:
|
||||
It can either have shape (n,); then ``fun`` must return array_like with
|
||||
shape (n,). Alternatively it can have shape (n, k); then ``fun``
|
||||
must return an array_like with shape (n, k), i.e., each column
|
||||
corresponds to a single column in ``y``. The choice between the two
|
||||
options is determined by `vectorized` argument (see below). The
|
||||
vectorized implementation allows a faster approximation of the Jacobian
|
||||
by finite differences (required for this solver).
|
||||
t0: Initial time.
|
||||
y0: Initial state.
|
||||
t_bound: Boundary time - the integration won't continue beyond it. It also determines
|
||||
the direction of the integration.
|
||||
vectorized: Whether ``fun`` is implemented in a vectorized fashion. Default is False.
|
||||
support_complex: Whether integration in a complex domain should be supported.
|
||||
Generally determined by a derived solver class capabilities. Default is False.
|
||||
num_t_steps: Number of time steps for the forward Euler method.
|
||||
"""
|
||||
self.y_old = None
|
||||
self.step_length = (t_bound - t0) / num_t_steps
|
||||
super().__init__(function, t0, y0, t_bound, vectorized, support_complex)
|
||||
|
||||
def _step_impl(self):
|
||||
"""
|
||||
Takes an Euler step.
|
||||
"""
|
||||
try:
|
||||
self.y_old = self.y
|
||||
self.y = list(np.add(self.y, self.step_length * self.fun(self.t, self.y)))
|
||||
self.t += self.step_length
|
||||
return True, None
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
return False, f"Unknown ODE solver error: {str(ex)}."
|
||||
|
||||
def _dense_output_impl(self):
|
||||
return ConstantDenseOutput(self.t_old, self.t, self.y_old)
|
|
@ -1,43 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for generating ODE functions based on ODE gradients."""
|
||||
from typing import Iterable
|
||||
|
||||
from ..ode.abstract_ode_function import (
|
||||
AbstractOdeFunction,
|
||||
)
|
||||
|
||||
|
||||
class OdeFunction(AbstractOdeFunction):
|
||||
"""Class for generating ODE functions based on ODE gradients."""
|
||||
|
||||
def var_qte_ode_function(self, time: float, parameters_values: Iterable) -> Iterable:
|
||||
"""
|
||||
Evaluates an ODE function for a given time and parameter values. It is used by an ODE
|
||||
solver.
|
||||
|
||||
Args:
|
||||
time: Current time of evolution.
|
||||
parameters_values: Current values of parameters.
|
||||
|
||||
Returns:
|
||||
ODE gradient arising from solving a system of linear equations.
|
||||
"""
|
||||
current_param_dict = dict(zip(self._param_dict.keys(), parameters_values))
|
||||
|
||||
ode_grad_res, _, _ = self._varqte_linear_solver.solve_lse(
|
||||
current_param_dict,
|
||||
time,
|
||||
)
|
||||
|
||||
return ode_grad_res
|
|
@ -1,83 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Abstract class for generating ODE functions."""
|
||||
|
||||
from abc import ABC
|
||||
from enum import Enum
|
||||
from typing import Dict, Any, Optional, Callable
|
||||
|
||||
import numpy as np
|
||||
|
||||
from qiskit.circuit import Parameter
|
||||
from .abstract_ode_function import AbstractOdeFunction
|
||||
from .ode_function import OdeFunction
|
||||
from ..var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
|
||||
|
||||
class OdeFunctionType(Enum):
|
||||
"""Types of ODE functions for VatQTE algorithms."""
|
||||
|
||||
# more will be supported in the near future
|
||||
STANDARD_ODE = "STANDARD_ODE"
|
||||
|
||||
|
||||
class OdeFunctionFactory(ABC):
|
||||
"""Factory for building ODE functions."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ode_function_type: OdeFunctionType = OdeFunctionType.STANDARD_ODE,
|
||||
lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
ode_function_type: An Enum that defines a type of an ODE function to be built. If
|
||||
not provided, a default ``STANDARD_ODE`` is used.
|
||||
lse_solver: Linear system of equations solver callable. It accepts ``A`` and ``b`` to
|
||||
solve ``Ax=b`` and returns ``x``. If ``None``, the default ``np.linalg.lstsq``
|
||||
solver is used.
|
||||
"""
|
||||
self.ode_function_type = ode_function_type
|
||||
self.lse_solver = lse_solver
|
||||
|
||||
def _build(
|
||||
self,
|
||||
varqte_linear_solver: VarQTELinearSolver,
|
||||
error_calculator: Any,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
t_param: Optional[Parameter] = None,
|
||||
) -> AbstractOdeFunction:
|
||||
"""
|
||||
Initializes an ODE function specified in the class.
|
||||
|
||||
Args:
|
||||
varqte_linear_solver: Solver of LSE for the VarQTE algorithm.
|
||||
error_calculator: Calculator of errors for error-based ODE functions.
|
||||
param_dict: Dictionary which relates parameter values to the parameters in the ansatz.
|
||||
t_param: Time parameter in case of a time-dependent Hamiltonian.
|
||||
|
||||
Returns:
|
||||
An ODE function.
|
||||
|
||||
Raises:
|
||||
ValueError: If unsupported ODE function provided.
|
||||
|
||||
"""
|
||||
if self.ode_function_type == OdeFunctionType.STANDARD_ODE:
|
||||
return OdeFunction(varqte_linear_solver, error_calculator, param_dict, t_param)
|
||||
raise ValueError(
|
||||
f"Unsupported ODE function provided: {self.ode_function_type}."
|
||||
f" Only {[tp.value for tp in OdeFunctionType]} are supported."
|
||||
)
|
|
@ -1,83 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for solving ODEs for Quantum Time Evolution."""
|
||||
from functools import partial
|
||||
from typing import List, Union, Type, Optional
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import OdeSolver, solve_ivp
|
||||
|
||||
from .abstract_ode_function import (
|
||||
AbstractOdeFunction,
|
||||
)
|
||||
from .forward_euler_solver import ForwardEulerSolver
|
||||
|
||||
|
||||
class VarQTEOdeSolver:
|
||||
"""Class for solving ODEs for Quantum Time Evolution."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
init_params: List[complex],
|
||||
ode_function: AbstractOdeFunction,
|
||||
ode_solver: Union[Type[OdeSolver], str] = ForwardEulerSolver,
|
||||
num_timesteps: Optional[int] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Initialize ODE Solver.
|
||||
|
||||
Args:
|
||||
init_params: Set of initial parameters for time 0.
|
||||
ode_function: Generates the ODE function.
|
||||
ode_solver: ODE solver callable that implements a SciPy ``OdeSolver`` interface or a
|
||||
string indicating a valid method offered by SciPy.
|
||||
num_timesteps: The number of timesteps to take. If None, it is
|
||||
automatically selected to achieve a timestep of approximately 0.01. Only
|
||||
relevant in case of the ``ForwardEulerSolver``.
|
||||
"""
|
||||
self._init_params = init_params
|
||||
self._ode_function = ode_function.var_qte_ode_function
|
||||
self._ode_solver = ode_solver
|
||||
self._num_timesteps = num_timesteps
|
||||
|
||||
def run(self, evolution_time: float) -> List[complex]:
|
||||
"""
|
||||
Finds numerical solution with ODE Solver.
|
||||
|
||||
Args:
|
||||
evolution_time: Evolution time.
|
||||
|
||||
Returns:
|
||||
List of parameters found by an ODE solver for a given ODE function callable.
|
||||
"""
|
||||
# determine the number of timesteps and set the timestep
|
||||
num_timesteps = (
|
||||
int(np.ceil(evolution_time / 0.01))
|
||||
if self._num_timesteps is None
|
||||
else self._num_timesteps
|
||||
)
|
||||
|
||||
if self._ode_solver == ForwardEulerSolver:
|
||||
solve = partial(solve_ivp, num_t_steps=num_timesteps)
|
||||
else:
|
||||
solve = solve_ivp
|
||||
|
||||
sol = solve(
|
||||
self._ode_function,
|
||||
(0, evolution_time),
|
||||
self._init_params,
|
||||
method=self._ode_solver,
|
||||
)
|
||||
final_params_vals = [lst[-1] for lst in sol.y]
|
||||
|
||||
return final_params_vals
|
|
@ -1,160 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for solving linear equations for Quantum Time Evolution."""
|
||||
|
||||
from typing import Union, List, Dict, Optional, Callable
|
||||
|
||||
import numpy as np
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.algorithms.evolvers.variational.variational_principles.variational_principle import (
|
||||
VariationalPrinciple,
|
||||
)
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import (
|
||||
CircuitSampler,
|
||||
OperatorBase,
|
||||
ExpectationBase,
|
||||
)
|
||||
from qiskit.providers import Backend
|
||||
from qiskit.utils import QuantumInstance
|
||||
from qiskit.utils.backend_utils import is_aer_provider
|
||||
|
||||
|
||||
class VarQTELinearSolver:
|
||||
"""Class for solving linear equations for Quantum Time Evolution."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
var_principle: VariationalPrinciple,
|
||||
hamiltonian: OperatorBase,
|
||||
ansatz: QuantumCircuit,
|
||||
gradient_params: List[Parameter],
|
||||
t_param: Optional[Parameter] = None,
|
||||
lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]] = None,
|
||||
imag_part_tol: float = 1e-7,
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
var_principle: Variational Principle to be used.
|
||||
hamiltonian:
|
||||
Operator used for Variational Quantum Time Evolution.
|
||||
The operator may be given either as a composed op consisting of a Hermitian
|
||||
observable and a ``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a
|
||||
``ComboFn``.
|
||||
The latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
gradient_params: List of parameters with respect to which gradients should be computed.
|
||||
t_param: Time parameter in case of a time-dependent Hamiltonian.
|
||||
lse_solver: Linear system of equations solver callable. It accepts ``A`` and ``b`` to
|
||||
solve ``Ax=b`` and returns ``x``. If ``None``, the default ``np.linalg.lstsq``
|
||||
solver is used.
|
||||
imag_part_tol: Allowed value of an imaginary part that can be neglected if no
|
||||
imaginary part is expected.
|
||||
expectation: An instance of ``ExpectationBase`` used for calculating a metric tensor
|
||||
and an evolution gradient. If ``None`` provided, a ``PauliExpectation`` is used.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
"""
|
||||
self._var_principle = var_principle
|
||||
self._hamiltonian = hamiltonian
|
||||
self._ansatz = ansatz
|
||||
self._gradient_params = gradient_params
|
||||
self._bind_params = gradient_params + [t_param] if t_param else gradient_params
|
||||
self._time_param = t_param
|
||||
self.lse_solver = lse_solver
|
||||
self._quantum_instance = None
|
||||
self._circuit_sampler = None
|
||||
self._imag_part_tol = imag_part_tol
|
||||
self._expectation = expectation
|
||||
if quantum_instance is not None:
|
||||
self.quantum_instance = quantum_instance
|
||||
|
||||
@property
|
||||
def lse_solver(self) -> Callable[[np.ndarray, np.ndarray], np.ndarray]:
|
||||
"""Returns an LSE solver callable."""
|
||||
return self._lse_solver
|
||||
|
||||
@lse_solver.setter
|
||||
def lse_solver(
|
||||
self, lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]]
|
||||
) -> None:
|
||||
"""Sets an LSE solver. Uses a ``np.linalg.lstsq`` callable if ``None`` provided."""
|
||||
if lse_solver is None:
|
||||
lse_solver = lambda a, b: np.linalg.lstsq(a, b, rcond=1e-2)[0]
|
||||
|
||||
self._lse_solver = lse_solver
|
||||
|
||||
@property
|
||||
def quantum_instance(self) -> Optional[QuantumInstance]:
|
||||
"""Returns quantum instance."""
|
||||
return self._quantum_instance
|
||||
|
||||
@quantum_instance.setter
|
||||
def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None:
|
||||
"""Sets quantum_instance"""
|
||||
if not isinstance(quantum_instance, QuantumInstance):
|
||||
quantum_instance = QuantumInstance(quantum_instance)
|
||||
|
||||
self._quantum_instance = quantum_instance
|
||||
self._circuit_sampler = CircuitSampler(
|
||||
quantum_instance, param_qobj=is_aer_provider(quantum_instance.backend)
|
||||
)
|
||||
|
||||
def solve_lse(
|
||||
self,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
time_value: Optional[float] = None,
|
||||
) -> (Union[List, np.ndarray], Union[List, np.ndarray], np.ndarray):
|
||||
"""
|
||||
Solve the system of linear equations underlying McLachlan's variational principle for the
|
||||
calculation without error bounds.
|
||||
|
||||
Args:
|
||||
param_dict: Dictionary which relates parameter values to the parameters in the ansatz.
|
||||
time_value: Time value that will be bound to ``t_param``. It is required if ``t_param``
|
||||
is not ``None``.
|
||||
|
||||
Returns:
|
||||
Solution to the LSE, A from Ax=b, b from Ax=b.
|
||||
"""
|
||||
param_values = list(param_dict.values())
|
||||
if self._time_param is not None:
|
||||
param_values.append(time_value)
|
||||
|
||||
metric_tensor_lse_lhs = self._var_principle.metric_tensor(
|
||||
self._ansatz,
|
||||
self._bind_params,
|
||||
self._gradient_params,
|
||||
param_values,
|
||||
self._expectation,
|
||||
self._quantum_instance,
|
||||
)
|
||||
evolution_grad_lse_rhs = self._var_principle.evolution_grad(
|
||||
self._hamiltonian,
|
||||
self._ansatz,
|
||||
self._circuit_sampler,
|
||||
param_dict,
|
||||
self._bind_params,
|
||||
self._gradient_params,
|
||||
param_values,
|
||||
self._expectation,
|
||||
self._quantum_instance,
|
||||
)
|
||||
|
||||
x = self._lse_solver(metric_tensor_lse_lhs, evolution_grad_lse_rhs)
|
||||
|
||||
return np.real(x), metric_tensor_lse_lhs, evolution_grad_lse_rhs
|
|
@ -1,125 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Variational Quantum Imaginary Time Evolution algorithm."""
|
||||
from typing import Optional, Union, Type, Callable, List, Dict
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import OdeSolver
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import ExpectationBase, OperatorBase
|
||||
from qiskit.algorithms.evolvers.imaginary_evolver import ImaginaryEvolver
|
||||
from qiskit.utils import QuantumInstance
|
||||
from . import ImaginaryMcLachlanPrinciple
|
||||
from .solvers.ode.forward_euler_solver import ForwardEulerSolver
|
||||
from .variational_principles import ImaginaryVariationalPrinciple
|
||||
from .var_qte import VarQTE
|
||||
|
||||
|
||||
class VarQITE(VarQTE, ImaginaryEvolver):
|
||||
"""Variational Quantum Imaginary Time Evolution algorithm.
|
||||
|
||||
.. code-block::python
|
||||
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
from qiskit.algorithms import VarQITE
|
||||
from qiskit import BasicAer
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, I, Z, Y, X
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
import numpy as np
|
||||
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
).reduce()
|
||||
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=1)
|
||||
parameters = ansatz.parameters
|
||||
init_param_values = np.zeros(len(ansatz.parameters))
|
||||
for i in range(len(ansatz.ordered_parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
time = 1
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
var_qite = VarQITE(ansatz, var_principle, param_dict, quantum_instance=backend)
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ansatz: Union[OperatorBase, QuantumCircuit],
|
||||
variational_principle: Optional[ImaginaryVariationalPrinciple] = None,
|
||||
initial_parameters: Optional[
|
||||
Union[Dict[Parameter, complex], List[complex], np.ndarray]
|
||||
] = None,
|
||||
ode_solver: Union[Type[OdeSolver], str] = ForwardEulerSolver,
|
||||
lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]] = None,
|
||||
num_timesteps: Optional[int] = None,
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
imag_part_tol: float = 1e-7,
|
||||
num_instability_tol: float = 1e-7,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> None:
|
||||
r"""
|
||||
Args:
|
||||
ansatz: Ansatz to be used for variational time evolution.
|
||||
variational_principle: Variational Principle to be used. Defaults to
|
||||
``ImaginaryMcLachlanPrinciple``.
|
||||
initial_parameters: Initial parameter values for an ansatz. If ``None`` provided,
|
||||
they are initialized uniformly at random.
|
||||
ode_solver: ODE solver callable that implements a SciPy ``OdeSolver`` interface or a
|
||||
string indicating a valid method offered by SciPy.
|
||||
lse_solver: Linear system of equations solver callable. It accepts ``A`` and ``b`` to
|
||||
solve ``Ax=b`` and returns ``x``. If ``None``, the default ``np.linalg.lstsq``
|
||||
solver is used.
|
||||
num_timesteps: The number of timesteps to take. If None, it is
|
||||
automatically selected to achieve a timestep of approximately 0.01. Only
|
||||
relevant in case of the ``ForwardEulerSolver``.
|
||||
expectation: An instance of ``ExpectationBase`` which defines a method for calculating
|
||||
a metric tensor and an evolution gradient and, if provided, expectation values of
|
||||
``EvolutionProblem.aux_operators``.
|
||||
imag_part_tol: Allowed value of an imaginary part that can be neglected if no
|
||||
imaginary part is expected.
|
||||
num_instability_tol: The amount of negative value that is allowed to be
|
||||
rounded up to 0 for quantities that are expected to be non-negative.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on NumPy matrix multiplication
|
||||
(which might be slow for larger numbers of qubits).
|
||||
"""
|
||||
if variational_principle is None:
|
||||
variational_principle = ImaginaryMcLachlanPrinciple()
|
||||
super().__init__(
|
||||
ansatz,
|
||||
variational_principle,
|
||||
initial_parameters,
|
||||
ode_solver,
|
||||
lse_solver=lse_solver,
|
||||
num_timesteps=num_timesteps,
|
||||
expectation=expectation,
|
||||
imag_part_tol=imag_part_tol,
|
||||
num_instability_tol=num_instability_tol,
|
||||
quantum_instance=quantum_instance,
|
||||
)
|
|
@ -1,126 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Variational Quantum Real Time Evolution algorithm."""
|
||||
from typing import Optional, Union, Type, Callable, List, Dict
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import OdeSolver
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.algorithms.evolvers.real_evolver import RealEvolver
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import ExpectationBase, OperatorBase
|
||||
from qiskit.utils import QuantumInstance
|
||||
from . import RealMcLachlanPrinciple
|
||||
from .solvers.ode.forward_euler_solver import ForwardEulerSolver
|
||||
from .variational_principles import RealVariationalPrinciple
|
||||
from .var_qte import VarQTE
|
||||
|
||||
|
||||
class VarQRTE(VarQTE, RealEvolver):
|
||||
"""Variational Quantum Real Time Evolution algorithm.
|
||||
|
||||
.. code-block::python
|
||||
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
from qiskit.algorithms import VarQITE
|
||||
from qiskit import BasicAer
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, I, Z, Y, X
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
RealMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
import numpy as np
|
||||
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
).reduce()
|
||||
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=1)
|
||||
parameters = ansatz.parameters
|
||||
init_param_values = np.zeros(len(ansatz.parameters))
|
||||
for i in range(len(ansatz.parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
var_principle = RealMcLachlanPrinciple()
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
time = 1
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
var_qrte = VarQRTE(ansatz, var_principle, param_dict, quantum_instance=backend)
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ansatz: Union[OperatorBase, QuantumCircuit],
|
||||
variational_principle: Optional[RealVariationalPrinciple] = None,
|
||||
initial_parameters: Optional[
|
||||
Union[Dict[Parameter, complex], List[complex], np.ndarray]
|
||||
] = None,
|
||||
ode_solver: Union[Type[OdeSolver], str] = ForwardEulerSolver,
|
||||
lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]] = None,
|
||||
num_timesteps: Optional[int] = None,
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
imag_part_tol: float = 1e-7,
|
||||
num_instability_tol: float = 1e-7,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> None:
|
||||
r"""
|
||||
Args:
|
||||
ansatz: Ansatz to be used for variational time evolution.
|
||||
variational_principle: Variational Principle to be used. Defaults to
|
||||
``RealMcLachlanPrinciple``.
|
||||
initial_parameters: Initial parameter values for an ansatz. If ``None`` provided,
|
||||
they are initialized uniformly at random.
|
||||
ode_solver: ODE solver callable that implements a SciPy ``OdeSolver`` interface or a
|
||||
string indicating a valid method offered by SciPy.
|
||||
lse_solver: Linear system of equations solver callable. It accepts ``A`` and ``b`` to
|
||||
solve ``Ax=b`` and returns ``x``. If ``None``, the default ``np.linalg.lstsq``
|
||||
solver is used.
|
||||
num_timesteps: The number of timesteps to take. If None, it is
|
||||
automatically selected to achieve a timestep of approximately 0.01. Only
|
||||
relevant in case of the ``ForwardEulerSolver``.
|
||||
expectation: An instance of ``ExpectationBase`` which defines a method for calculating
|
||||
a metric tensor and an evolution gradient and, if provided, expectation values of
|
||||
``EvolutionProblem.aux_operators``.
|
||||
imag_part_tol: Allowed value of an imaginary part that can be neglected if no
|
||||
imaginary part is expected.
|
||||
num_instability_tol: The amount of negative value that is allowed to be
|
||||
rounded up to 0 for quantities that are expected to be
|
||||
non-negative.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
"""
|
||||
if variational_principle is None:
|
||||
variational_principle = RealMcLachlanPrinciple()
|
||||
super().__init__(
|
||||
ansatz,
|
||||
variational_principle,
|
||||
initial_parameters,
|
||||
ode_solver,
|
||||
lse_solver=lse_solver,
|
||||
num_timesteps=num_timesteps,
|
||||
expectation=expectation,
|
||||
imag_part_tol=imag_part_tol,
|
||||
num_instability_tol=num_instability_tol,
|
||||
quantum_instance=quantum_instance,
|
||||
)
|
|
@ -1,303 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""The Variational Quantum Time Evolution Interface"""
|
||||
from abc import ABC
|
||||
from typing import Optional, Union, Dict, List, Any, Type, Callable
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import OdeSolver
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.algorithms.aux_ops_evaluator import eval_observables
|
||||
from qiskit.algorithms.evolvers.evolution_problem import EvolutionProblem
|
||||
from qiskit.algorithms.evolvers.evolution_result import EvolutionResult
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.providers import Backend
|
||||
from qiskit.utils import QuantumInstance
|
||||
from qiskit.opflow import (
|
||||
CircuitSampler,
|
||||
OperatorBase,
|
||||
ExpectationBase,
|
||||
)
|
||||
from qiskit.utils.backend_utils import is_aer_provider
|
||||
from .solvers.ode.forward_euler_solver import ForwardEulerSolver
|
||||
from .solvers.ode.ode_function_factory import OdeFunctionFactory
|
||||
from .solvers.var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
from .variational_principles.variational_principle import (
|
||||
VariationalPrinciple,
|
||||
)
|
||||
from .solvers.ode.var_qte_ode_solver import (
|
||||
VarQTEOdeSolver,
|
||||
)
|
||||
|
||||
|
||||
class VarQTE(ABC):
|
||||
"""Variational Quantum Time Evolution.
|
||||
|
||||
Algorithms that use variational principles to compute a time evolution for a given
|
||||
Hermitian operator (Hamiltonian) and a quantum state prepared by a parameterized quantum circuit.
|
||||
|
||||
References:
|
||||
|
||||
[1] Benjamin, Simon C. et al. (2019).
|
||||
Theory of variational quantum simulation. `<https://doi.org/10.22331/q-2019-10-07-191>`_
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ansatz: Union[OperatorBase, QuantumCircuit],
|
||||
variational_principle: VariationalPrinciple,
|
||||
initial_parameters: Optional[
|
||||
Union[Dict[Parameter, complex], List[complex], np.ndarray]
|
||||
] = None,
|
||||
ode_solver: Union[Type[OdeSolver], str] = ForwardEulerSolver,
|
||||
lse_solver: Optional[Callable[[np.ndarray, np.ndarray], np.ndarray]] = None,
|
||||
num_timesteps: Optional[int] = None,
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
imag_part_tol: float = 1e-7,
|
||||
num_instability_tol: float = 1e-7,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> None:
|
||||
r"""
|
||||
Args:
|
||||
ansatz: Ansatz to be used for variational time evolution.
|
||||
variational_principle: Variational Principle to be used.
|
||||
initial_parameters: Initial parameter values for an ansatz. If ``None`` provided,
|
||||
they are initialized uniformly at random.
|
||||
ode_solver: ODE solver callable that implements a SciPy ``OdeSolver`` interface or a
|
||||
string indicating a valid method offered by SciPy.
|
||||
lse_solver: Linear system of equations solver callable. It accepts ``A`` and ``b`` to
|
||||
solve ``Ax=b`` and returns ``x``. If ``None``, the default ``np.linalg.lstsq``
|
||||
solver is used.
|
||||
num_timesteps: The number of timesteps to take. If None, it is
|
||||
automatically selected to achieve a timestep of approximately 0.01. Only
|
||||
relevant in case of the ``ForwardEulerSolver``.
|
||||
expectation: An instance of ``ExpectationBase`` which defines a method for calculating
|
||||
a metric tensor and an evolution gradient and, if provided, expectation values of
|
||||
``EvolutionProblem.aux_operators``.
|
||||
imag_part_tol: Allowed value of an imaginary part that can be neglected if no
|
||||
imaginary part is expected.
|
||||
num_instability_tol: The amount of negative value that is allowed to be
|
||||
rounded up to 0 for quantities that are expected to be
|
||||
non-negative.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
"""
|
||||
super().__init__()
|
||||
self.ansatz = ansatz
|
||||
self.variational_principle = variational_principle
|
||||
self.initial_parameters = initial_parameters
|
||||
self._quantum_instance = None
|
||||
if quantum_instance is not None:
|
||||
self.quantum_instance = quantum_instance
|
||||
self.expectation = expectation
|
||||
self.num_timesteps = num_timesteps
|
||||
self.lse_solver = lse_solver
|
||||
# OdeFunction abstraction kept for potential extensions - unclear at the moment;
|
||||
# currently hidden from the user
|
||||
self._ode_function_factory = OdeFunctionFactory(lse_solver=lse_solver)
|
||||
self.ode_solver = ode_solver
|
||||
self.imag_part_tol = imag_part_tol
|
||||
self.num_instability_tol = num_instability_tol
|
||||
|
||||
@property
|
||||
def quantum_instance(self) -> Optional[QuantumInstance]:
|
||||
"""Returns quantum instance."""
|
||||
return self._quantum_instance
|
||||
|
||||
@quantum_instance.setter
|
||||
def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend]) -> None:
|
||||
"""Sets quantum_instance"""
|
||||
if not isinstance(quantum_instance, QuantumInstance):
|
||||
quantum_instance = QuantumInstance(quantum_instance)
|
||||
|
||||
self._quantum_instance = quantum_instance
|
||||
self._circuit_sampler = CircuitSampler(
|
||||
quantum_instance, param_qobj=is_aer_provider(quantum_instance.backend)
|
||||
)
|
||||
|
||||
def evolve(self, evolution_problem: EvolutionProblem) -> EvolutionResult:
|
||||
"""
|
||||
Apply Variational Quantum Imaginary Time Evolution (VarQITE) w.r.t. the given
|
||||
operator.
|
||||
|
||||
Args:
|
||||
evolution_problem: Instance defining an evolution problem.
|
||||
Returns:
|
||||
Result of the evolution which includes a quantum circuit with bound parameters as an
|
||||
evolved state and, if provided, observables evaluated on the evolved state using
|
||||
a ``quantum_instance`` and ``expectation`` provided.
|
||||
|
||||
Raises:
|
||||
ValueError: If no ``initial_state`` is included in the ``evolution_problem``.
|
||||
"""
|
||||
self._validate_aux_ops(evolution_problem)
|
||||
|
||||
if evolution_problem.initial_state is not None:
|
||||
raise ValueError("initial_state provided but not applicable to VarQTE.")
|
||||
|
||||
init_state_param_dict = self._create_init_state_param_dict(
|
||||
self.initial_parameters, self.ansatz.parameters
|
||||
)
|
||||
|
||||
error_calculator = None # TODO will be supported in another PR
|
||||
|
||||
evolved_state = self._evolve(
|
||||
init_state_param_dict,
|
||||
evolution_problem.hamiltonian,
|
||||
evolution_problem.time,
|
||||
evolution_problem.t_param,
|
||||
error_calculator,
|
||||
)
|
||||
|
||||
evaluated_aux_ops = None
|
||||
if evolution_problem.aux_operators is not None:
|
||||
evaluated_aux_ops = eval_observables(
|
||||
self.quantum_instance,
|
||||
evolved_state,
|
||||
evolution_problem.aux_operators,
|
||||
self.expectation,
|
||||
)
|
||||
|
||||
return EvolutionResult(evolved_state, evaluated_aux_ops)
|
||||
|
||||
def _evolve(
|
||||
self,
|
||||
init_state_param_dict: Dict[Parameter, complex],
|
||||
hamiltonian: OperatorBase,
|
||||
time: float,
|
||||
t_param: Optional[Parameter] = None,
|
||||
error_calculator: Any = None,
|
||||
) -> OperatorBase:
|
||||
r"""
|
||||
Helper method for performing time evolution. Works both for imaginary and real case.
|
||||
|
||||
Args:
|
||||
init_state_param_dict: Parameter dictionary with initial values for a given
|
||||
parametrized state/ansatz. If no initial parameter values are provided, they are
|
||||
initialized uniformly at random.
|
||||
hamiltonian:
|
||||
Operator used for Variational Quantum Imaginary Time Evolution (VarQTE).
|
||||
The operator may be given either as a composed op consisting of a Hermitian
|
||||
observable and a ``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a
|
||||
``ComboFn``.
|
||||
The latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
time: Total time of evolution.
|
||||
t_param: Time parameter in case of a time-dependent Hamiltonian.
|
||||
error_calculator: Not yet supported. Calculator of errors for error-based ODE functions.
|
||||
|
||||
Returns:
|
||||
Result of the evolution which is a quantum circuit with bound parameters as an
|
||||
evolved state.
|
||||
"""
|
||||
|
||||
init_state_parameters = list(init_state_param_dict.keys())
|
||||
init_state_parameters_values = list(init_state_param_dict.values())
|
||||
|
||||
linear_solver = VarQTELinearSolver(
|
||||
self.variational_principle,
|
||||
hamiltonian,
|
||||
self.ansatz,
|
||||
init_state_parameters,
|
||||
t_param,
|
||||
self._ode_function_factory.lse_solver,
|
||||
self.imag_part_tol,
|
||||
self.expectation,
|
||||
self._quantum_instance,
|
||||
)
|
||||
|
||||
# Convert the operator that holds the Hamiltonian and ansatz into a NaturalGradient operator
|
||||
ode_function = self._ode_function_factory._build(
|
||||
linear_solver, error_calculator, init_state_param_dict, t_param
|
||||
)
|
||||
|
||||
ode_solver = VarQTEOdeSolver(
|
||||
init_state_parameters_values, ode_function, self.ode_solver, self.num_timesteps
|
||||
)
|
||||
parameter_values = ode_solver.run(time)
|
||||
param_dict_from_ode = dict(zip(init_state_parameters, parameter_values))
|
||||
|
||||
return self.ansatz.assign_parameters(param_dict_from_ode)
|
||||
|
||||
@staticmethod
|
||||
def _create_init_state_param_dict(
|
||||
param_values: Union[Dict[Parameter, complex], List[complex], np.ndarray],
|
||||
init_state_parameters: List[Parameter],
|
||||
) -> Dict[Parameter, complex]:
|
||||
r"""
|
||||
If ``param_values`` is a dictionary, it looks for parameters present in an initial state
|
||||
(an ansatz) in a ``param_values``. Based on that, it creates a new dictionary containing
|
||||
only parameters present in an initial state and their respective values.
|
||||
If ``param_values`` is a list of values, it creates a new dictionary containing
|
||||
parameters present in an initial state and their respective values.
|
||||
If no ``param_values`` is provided, parameter values are chosen uniformly at random.
|
||||
|
||||
Args:
|
||||
param_values: Dictionary which relates parameter values to the parameters or a list of
|
||||
values.
|
||||
init_state_parameters: Parameters present in a quantum state.
|
||||
|
||||
Returns:
|
||||
Dictionary that maps parameters of an initial state to some values.
|
||||
|
||||
Raises:
|
||||
ValueError: If the dictionary with parameter values provided does not include all
|
||||
parameters present in the initial state or if the list of values provided is not the
|
||||
same length as the list of parameters.
|
||||
TypeError: If an unsupported type of ``param_values`` provided.
|
||||
"""
|
||||
if param_values is None:
|
||||
init_state_parameter_values = np.random.random(len(init_state_parameters))
|
||||
elif isinstance(param_values, dict):
|
||||
init_state_parameter_values = []
|
||||
for param in init_state_parameters:
|
||||
if param in param_values.keys():
|
||||
init_state_parameter_values.append(param_values[param])
|
||||
else:
|
||||
raise ValueError(
|
||||
f"The dictionary with parameter values provided does not "
|
||||
f"include all parameters present in the initial state."
|
||||
f"Parameters present in the state: {init_state_parameters}, "
|
||||
f"parameters in the dictionary: "
|
||||
f"{list(param_values.keys())}."
|
||||
)
|
||||
elif isinstance(param_values, (list, np.ndarray)):
|
||||
if len(init_state_parameters) != len(param_values):
|
||||
raise ValueError(
|
||||
f"Initial state has {len(init_state_parameters)} parameters and the"
|
||||
f" list of values has {len(param_values)} elements. They should be"
|
||||
f"equal in length."
|
||||
)
|
||||
init_state_parameter_values = param_values
|
||||
else:
|
||||
raise TypeError(f"Unsupported type of param_values provided: {type(param_values)}.")
|
||||
|
||||
init_state_param_dict = dict(zip(init_state_parameters, init_state_parameter_values))
|
||||
return init_state_param_dict
|
||||
|
||||
def _validate_aux_ops(self, evolution_problem: EvolutionProblem) -> None:
|
||||
if evolution_problem.aux_operators is not None:
|
||||
if self.quantum_instance is None:
|
||||
raise ValueError(
|
||||
"aux_operators where provided for evaluations but no ``quantum_instance`` "
|
||||
"was provided."
|
||||
)
|
||||
|
||||
if self.expectation is None:
|
||||
raise ValueError(
|
||||
"aux_operators where provided for evaluations but no ``expectation`` "
|
||||
"was provided."
|
||||
)
|
|
@ -1,25 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Variational Principles"""
|
||||
|
||||
from .imaginary_mc_lachlan_principle import ImaginaryMcLachlanPrinciple
|
||||
from .imaginary_variational_principle import ImaginaryVariationalPrinciple
|
||||
from .real_mc_lachlan_principle import RealMcLachlanPrinciple
|
||||
from .real_variational_principle import RealVariationalPrinciple
|
||||
|
||||
__all__ = [
|
||||
"ImaginaryMcLachlanPrinciple",
|
||||
"ImaginaryVariationalPrinciple",
|
||||
"RealMcLachlanPrinciple",
|
||||
"RealVariationalPrinciple",
|
||||
]
|
|
@ -1,76 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for an Imaginary McLachlan's Variational Principle."""
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import numpy as np
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import StateFn, OperatorBase, CircuitSampler, ExpectationBase
|
||||
from qiskit.utils import QuantumInstance
|
||||
from .imaginary_variational_principle import (
|
||||
ImaginaryVariationalPrinciple,
|
||||
)
|
||||
|
||||
|
||||
class ImaginaryMcLachlanPrinciple(ImaginaryVariationalPrinciple):
|
||||
"""Class for an Imaginary McLachlan's Variational Principle. It aims to minimize the distance
|
||||
between both sides of the Wick-rotated Schrödinger equation with a quantum state given as a
|
||||
parametrized trial state. The principle leads to a system of linear equations handled by a
|
||||
linear solver. The imaginary variant means that we consider imaginary time dynamics.
|
||||
"""
|
||||
|
||||
def evolution_grad(
|
||||
self,
|
||||
hamiltonian: OperatorBase,
|
||||
ansatz: QuantumCircuit,
|
||||
circuit_sampler: CircuitSampler,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
bind_params: List[Parameter],
|
||||
gradient_params: List[Parameter],
|
||||
param_values: List[complex],
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Calculates an evolution gradient according to the rules of this variational principle.
|
||||
|
||||
Args:
|
||||
hamiltonian: Operator used for Variational Quantum Time Evolution. The operator may be
|
||||
given either as a composed op consisting of a Hermitian observable and a
|
||||
``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a ``ComboFn``. The
|
||||
latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
circuit_sampler: A circuit sampler.
|
||||
param_dict: Dictionary which relates parameter values to the parameters in the ansatz.
|
||||
bind_params: List of parameters that are supposed to be bound.
|
||||
gradient_params: List of parameters with respect to which gradients should be computed.
|
||||
param_values: Values of parameters to be bound.
|
||||
expectation: An instance of ``ExpectationBase`` used for calculating an evolution
|
||||
gradient. If ``None`` provided, a ``PauliExpectation`` is used.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
|
||||
Returns:
|
||||
An evolution gradient.
|
||||
"""
|
||||
if self._evolution_gradient_callable is None:
|
||||
operator = StateFn(hamiltonian, is_measurement=True) @ StateFn(ansatz)
|
||||
self._evolution_gradient_callable = self._evolution_gradient.gradient_wrapper(
|
||||
operator, bind_params, gradient_params, quantum_instance, expectation
|
||||
)
|
||||
evolution_grad_lse_rhs = -0.5 * self._evolution_gradient_callable(param_values)
|
||||
|
||||
return evolution_grad_lse_rhs
|
|
@ -1,24 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Abstract class for an Imaginary Variational Principle."""
|
||||
|
||||
from abc import ABC
|
||||
|
||||
from ..variational_principles.variational_principle import (
|
||||
VariationalPrinciple,
|
||||
)
|
||||
|
||||
|
||||
class ImaginaryVariationalPrinciple(VariationalPrinciple, ABC):
|
||||
"""Abstract class for an Imaginary Variational Principle. The imaginary variant means that we
|
||||
consider imaginary time dynamics."""
|
|
@ -1,150 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for a Real McLachlan's Variational Principle."""
|
||||
from typing import Union, Dict, List, Optional
|
||||
|
||||
import numpy as np
|
||||
from numpy import real
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import (
|
||||
StateFn,
|
||||
SummedOp,
|
||||
Y,
|
||||
I,
|
||||
PauliExpectation,
|
||||
CircuitQFI,
|
||||
CircuitSampler,
|
||||
OperatorBase,
|
||||
ExpectationBase,
|
||||
)
|
||||
from qiskit.opflow.gradients.circuit_gradients import LinComb
|
||||
from qiskit.utils import QuantumInstance
|
||||
from .real_variational_principle import (
|
||||
RealVariationalPrinciple,
|
||||
)
|
||||
|
||||
|
||||
class RealMcLachlanPrinciple(RealVariationalPrinciple):
|
||||
"""Class for a Real McLachlan's Variational Principle. It aims to minimize the distance
|
||||
between both sides of the Schrödinger equation with a quantum state given as a parametrized
|
||||
trial state. The principle leads to a system of linear equations handled by a linear solver.
|
||||
The real variant means that we consider real time dynamics.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
qfi_method: Union[str, CircuitQFI] = "lin_comb_full",
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
qfi_method: The method used to compute the QFI. Can be either
|
||||
``'lin_comb_full'`` or ``'overlap_block_diag'`` or ``'overlap_diag'`` or
|
||||
``CircuitQFI``.
|
||||
"""
|
||||
self._grad_method = LinComb(aux_meas_op=-Y)
|
||||
self._energy_param = None
|
||||
self._energy = None
|
||||
|
||||
super().__init__(qfi_method)
|
||||
|
||||
def evolution_grad(
|
||||
self,
|
||||
hamiltonian: OperatorBase,
|
||||
ansatz: QuantumCircuit,
|
||||
circuit_sampler: CircuitSampler,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
bind_params: List[Parameter],
|
||||
gradient_params: List[Parameter],
|
||||
param_values: List[complex],
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Calculates an evolution gradient according to the rules of this variational principle.
|
||||
|
||||
Args:
|
||||
hamiltonian: Operator used for Variational Quantum Time Evolution. The operator may be
|
||||
given either as a composed op consisting of a Hermitian observable and a
|
||||
``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a ``ComboFn``. The
|
||||
latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
circuit_sampler: A circuit sampler.
|
||||
param_dict: Dictionary which relates parameter values to the parameters in the ansatz.
|
||||
bind_params: List of parameters that are supposed to be bound.
|
||||
gradient_params: List of parameters with respect to which gradients should be computed.
|
||||
param_values: Values of parameters to be bound.
|
||||
expectation: An instance of ``ExpectationBase`` used for calculating an evolution
|
||||
gradient. If ``None`` provided, a ``PauliExpectation`` is used.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
|
||||
Returns:
|
||||
An evolution gradient.
|
||||
"""
|
||||
if self._evolution_gradient_callable is None:
|
||||
self._energy_param = Parameter("alpha")
|
||||
modified_hamiltonian = self._construct_expectation(
|
||||
hamiltonian, ansatz, self._energy_param
|
||||
)
|
||||
|
||||
self._evolution_gradient_callable = self._evolution_gradient.gradient_wrapper(
|
||||
modified_hamiltonian,
|
||||
bind_params + [self._energy_param],
|
||||
gradient_params,
|
||||
quantum_instance,
|
||||
expectation,
|
||||
)
|
||||
|
||||
energy = StateFn(hamiltonian, is_measurement=True) @ StateFn(ansatz)
|
||||
if expectation is None:
|
||||
expectation = PauliExpectation()
|
||||
self._energy = expectation.convert(energy)
|
||||
|
||||
if circuit_sampler is not None:
|
||||
energy = circuit_sampler.convert(self._energy, param_dict).eval()
|
||||
else:
|
||||
energy = self._energy.assign_parameters(param_dict).eval()
|
||||
|
||||
param_values.append(real(energy))
|
||||
evolution_grad = 0.5 * self._evolution_gradient_callable(param_values)
|
||||
|
||||
# quick fix due to an error on opflow; to be addressed in a separate PR
|
||||
evolution_grad = (-1) * evolution_grad
|
||||
return evolution_grad
|
||||
|
||||
@staticmethod
|
||||
def _construct_expectation(
|
||||
hamiltonian: OperatorBase, ansatz: QuantumCircuit, energy_param: Parameter
|
||||
) -> OperatorBase:
|
||||
"""
|
||||
Modifies a Hamiltonian according to the rules of this variational principle.
|
||||
|
||||
Args:
|
||||
hamiltonian: Operator used for Variational Quantum Time Evolution. The operator may be
|
||||
given either as a composed op consisting of a Hermitian observable and a
|
||||
``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a ``ComboFn``. The
|
||||
latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
energy_param: Parameter for energy correction.
|
||||
|
||||
Returns:
|
||||
An modified Hamiltonian composed with an ansatz.
|
||||
"""
|
||||
energy_term = I ^ hamiltonian.num_qubits
|
||||
energy_term *= -1
|
||||
energy_term *= energy_param
|
||||
modified_hamiltonian = SummedOp([hamiltonian, energy_term]).reduce()
|
||||
return StateFn(modified_hamiltonian, is_measurement=True) @ StateFn(ansatz)
|
|
@ -1,42 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for a Real Variational Principle."""
|
||||
|
||||
from abc import ABC
|
||||
from typing import Union
|
||||
|
||||
from qiskit.opflow import (
|
||||
CircuitQFI,
|
||||
)
|
||||
from .variational_principle import (
|
||||
VariationalPrinciple,
|
||||
)
|
||||
|
||||
|
||||
class RealVariationalPrinciple(VariationalPrinciple, ABC):
|
||||
"""Class for a Real Variational Principle. The real variant means that we consider real time
|
||||
dynamics."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
qfi_method: Union[str, CircuitQFI] = "lin_comb_full",
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
qfi_method: The method used to compute the QFI. Can be either ``'lin_comb_full'`` or
|
||||
``'overlap_block_diag'`` or ``'overlap_diag'`` or ``CircuitQFI``.
|
||||
"""
|
||||
super().__init__(
|
||||
qfi_method,
|
||||
self._grad_method,
|
||||
)
|
|
@ -1,129 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Class for a Variational Principle."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Union, List, Optional, Dict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.opflow import (
|
||||
CircuitQFI,
|
||||
CircuitGradient,
|
||||
QFI,
|
||||
Gradient,
|
||||
CircuitStateFn,
|
||||
CircuitSampler,
|
||||
OperatorBase,
|
||||
ExpectationBase,
|
||||
)
|
||||
from qiskit.utils import QuantumInstance
|
||||
|
||||
|
||||
class VariationalPrinciple(ABC):
|
||||
"""A Variational Principle class. It determines the time propagation of parameters in a
|
||||
quantum state provided as a parametrized quantum circuit (ansatz)."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
qfi_method: Union[str, CircuitQFI] = "lin_comb_full",
|
||||
grad_method: Union[str, CircuitGradient] = "lin_comb",
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
grad_method: The method used to compute the state gradient. Can be either
|
||||
``'param_shift'`` or ``'lin_comb'`` or ``'fin_diff'`` or ``CircuitGradient``.
|
||||
qfi_method: The method used to compute the QFI. Can be either
|
||||
``'lin_comb_full'`` or ``'overlap_block_diag'`` or ``'overlap_diag'`` or
|
||||
``CircuitQFI``.
|
||||
"""
|
||||
self._qfi_method = qfi_method
|
||||
self.qfi = QFI(qfi_method)
|
||||
self._grad_method = grad_method
|
||||
self._evolution_gradient = Gradient(self._grad_method)
|
||||
self._qfi_gradient_callable = None
|
||||
self._evolution_gradient_callable = None
|
||||
|
||||
def metric_tensor(
|
||||
self,
|
||||
ansatz: QuantumCircuit,
|
||||
bind_params: List[Parameter],
|
||||
gradient_params: List[Parameter],
|
||||
param_values: List[complex],
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Calculates a metric tensor according to the rules of this variational principle.
|
||||
|
||||
Args:
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
bind_params: List of parameters that are supposed to be bound.
|
||||
gradient_params: List of parameters with respect to which gradients should be computed.
|
||||
param_values: Values of parameters to be bound.
|
||||
expectation: An instance of ``ExpectationBase`` used for calculating a metric tensor.
|
||||
If ``None`` provided, a ``PauliExpectation`` is used.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
|
||||
Returns:
|
||||
Metric tensor.
|
||||
"""
|
||||
if self._qfi_gradient_callable is None:
|
||||
self._qfi_gradient_callable = self.qfi.gradient_wrapper(
|
||||
CircuitStateFn(ansatz), bind_params, gradient_params, quantum_instance, expectation
|
||||
)
|
||||
metric_tensor = 0.25 * self._qfi_gradient_callable(param_values)
|
||||
|
||||
return metric_tensor
|
||||
|
||||
@abstractmethod
|
||||
def evolution_grad(
|
||||
self,
|
||||
hamiltonian: OperatorBase,
|
||||
ansatz: QuantumCircuit,
|
||||
circuit_sampler: CircuitSampler,
|
||||
param_dict: Dict[Parameter, complex],
|
||||
bind_params: List[Parameter],
|
||||
gradient_params: List[Parameter],
|
||||
param_values: List[complex],
|
||||
expectation: Optional[ExpectationBase] = None,
|
||||
quantum_instance: Optional[QuantumInstance] = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Calculates an evolution gradient according to the rules of this variational principle.
|
||||
|
||||
Args:
|
||||
hamiltonian: Operator used for Variational Quantum Time Evolution. The operator may be
|
||||
given either as a composed op consisting of a Hermitian observable and a
|
||||
``CircuitStateFn`` or a ``ListOp`` of a ``CircuitStateFn`` with a ``ComboFn``. The
|
||||
latter case enables the evaluation of a Quantum Natural Gradient.
|
||||
ansatz: Quantum state in the form of a parametrized quantum circuit.
|
||||
circuit_sampler: A circuit sampler.
|
||||
param_dict: Dictionary which relates parameter values to the parameters in the ansatz.
|
||||
bind_params: List of parameters that are supposed to be bound.
|
||||
gradient_params: List of parameters with respect to which gradients should be computed.
|
||||
param_values: Values of parameters to be bound.
|
||||
expectation: An instance of ``ExpectationBase`` used for calculating an evolution
|
||||
gradient. If ``None`` provided, a ``PauliExpectation`` is used.
|
||||
quantum_instance: Backend used to evaluate the quantum circuit outputs. If ``None``
|
||||
provided, everything will be evaluated based on matrix multiplication (which is
|
||||
slow).
|
||||
|
||||
Returns:
|
||||
An evolution gradient.
|
||||
"""
|
||||
pass
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Add algorithms for Variational Quantum Time Evolution that implement a new interface for
|
||||
Quantum Time Evolution. The feature supports real (:class:`qiskit.algorithms.VarQRTE`.) and
|
||||
imaginary (:class:`qiskit.algorithms.VarQITE`.) quantum time evolution according to a
|
||||
variational principle passed. Each algorithm accepts a variational principle and the following
|
||||
are provided:
|
||||
:class:`qiskit.algorithms.evolvers.variational.ImaginaryMcLachlanPrinciple`,
|
||||
:class:`qiskit.algorithms.evolvers.variational.RealMcLachlanPrinciple`,
|
||||
:class:`qiskit.algorithms.evolvers.variational.RealTimeDependentPrinciple`.
|
||||
Both algorithms require solving ODE equations and linear equations which is handled by classes
|
||||
implemented in `qiskit.algorithms.evolvers.variational.solvers` module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
from qiskit.algorithms import VarQITE
|
||||
from qiskit import BasicAer
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, I, Z, Y, X
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.algorithms import EvolutionProblem
|
||||
import numpy as np
|
||||
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
).reduce()
|
||||
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=1)
|
||||
parameters = ansatz.parameters
|
||||
init_param_values = np.zeros(len(ansatz.parameters))
|
||||
for i in range(len(ansatz.parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
time = 1
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
var_qite = VarQITE(ansatz, var_principle, param_dict, quantum_instance=backend)
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,12 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
|
@ -1,182 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
||||
expected_metric_res_1 = [
|
||||
[
|
||||
2.50000000e-01 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-2.77500000e-17 + 0.0j,
|
||||
4.85000000e-17 + 0.0j,
|
||||
4.77630626e-32 + 0.0j,
|
||||
],
|
||||
[
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
],
|
||||
[
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
2.50000000e-01 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-3.85185989e-33 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-2.77500000e-17 + 0.0j,
|
||||
4.85000000e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
],
|
||||
[
|
||||
-2.77500000e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
-2.77500000e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
4.85000000e-17 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
4.85334346e-32 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
1.38006319e-17 + 0.0j,
|
||||
4.85000000e-17 + 0.0j,
|
||||
0.00000000e00 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-2.77500000e-17 + 0.0j,
|
||||
],
|
||||
[
|
||||
4.77630626e-32 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
-1.39493681e-17 + 0.0j,
|
||||
-7.00000000e-18 + 0.0j,
|
||||
4.17500000e-17 + 0.0j,
|
||||
-2.77500000e-17 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
],
|
||||
]
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,47 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test Forward Euler solver."""
|
||||
|
||||
import unittest
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
import numpy as np
|
||||
from ddt import ddt, data, unpack
|
||||
from scipy.integrate import solve_ivp
|
||||
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.forward_euler_solver import (
|
||||
ForwardEulerSolver,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class TestForwardEulerSolver(QiskitAlgorithmsTestCase):
|
||||
"""Test Forward Euler solver."""
|
||||
|
||||
@unpack
|
||||
@data((4, 16), (16, 35.52713678800501), (320, 53.261108839604795))
|
||||
def test_solve(self, timesteps, expected_result):
|
||||
"""Test Forward Euler solver for a simple ODE."""
|
||||
|
||||
y0 = [1]
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def func(time, y):
|
||||
return y
|
||||
|
||||
t_span = [0.0, 4.0]
|
||||
sol1 = solve_ivp(func, t_span, y0, method=ForwardEulerSolver, num_t_steps=timesteps)
|
||||
np.testing.assert_equal(sol1.y[-1][-1], expected_result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,165 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test ODE function generator."""
|
||||
|
||||
import unittest
|
||||
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
import numpy as np
|
||||
from qiskit.algorithms.evolvers.variational.solvers.var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.ode_function import (
|
||||
OdeFunction,
|
||||
)
|
||||
from qiskit import BasicAer
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import (
|
||||
SummedOp,
|
||||
X,
|
||||
Y,
|
||||
I,
|
||||
Z,
|
||||
)
|
||||
|
||||
|
||||
class TestOdeFunctionGenerator(QiskitAlgorithmsTestCase):
|
||||
"""Test ODE function generator."""
|
||||
|
||||
def test_var_qte_ode_function(self):
|
||||
"""Test ODE function generator."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
t_param = None
|
||||
linear_solver = None
|
||||
linear_solver = VarQTELinearSolver(
|
||||
var_principle,
|
||||
observable,
|
||||
ansatz,
|
||||
parameters,
|
||||
t_param,
|
||||
linear_solver,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
|
||||
time = 2
|
||||
ode_function_generator = OdeFunction(
|
||||
linear_solver, error_calculator=None, t_param=None, param_dict=param_dict
|
||||
)
|
||||
|
||||
qte_ode_function = ode_function_generator.var_qte_ode_function(time, param_dict.values())
|
||||
|
||||
expected_qte_ode_function = [
|
||||
0.442145,
|
||||
-0.022081,
|
||||
0.106223,
|
||||
-0.117468,
|
||||
0.251233,
|
||||
0.321256,
|
||||
-0.062728,
|
||||
-0.036209,
|
||||
-0.509219,
|
||||
-0.183459,
|
||||
-0.050739,
|
||||
-0.093163,
|
||||
]
|
||||
|
||||
np.testing.assert_array_almost_equal(expected_qte_ode_function, qte_ode_function)
|
||||
|
||||
def test_var_qte_ode_function_time_param(self):
|
||||
"""Test ODE function generator with time param."""
|
||||
t_param = Parameter("t")
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * t_param * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
time = 2
|
||||
|
||||
linear_solver = None
|
||||
linear_solver = VarQTELinearSolver(
|
||||
var_principle,
|
||||
observable,
|
||||
ansatz,
|
||||
parameters,
|
||||
t_param,
|
||||
linear_solver,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
ode_function_generator = OdeFunction(
|
||||
linear_solver, error_calculator=None, t_param=t_param, param_dict=param_dict
|
||||
)
|
||||
|
||||
qte_ode_function = ode_function_generator.var_qte_ode_function(time, param_dict.values())
|
||||
|
||||
expected_qte_ode_function = [
|
||||
0.442145,
|
||||
-0.022081,
|
||||
0.106223,
|
||||
-0.117468,
|
||||
0.251233,
|
||||
0.321256,
|
||||
-0.062728,
|
||||
-0.036209,
|
||||
-0.509219,
|
||||
-0.183459,
|
||||
-0.050739,
|
||||
-0.093163,
|
||||
]
|
||||
|
||||
np.testing.assert_array_almost_equal(expected_qte_ode_function, qte_ode_function, decimal=5)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,136 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test solver of ODEs."""
|
||||
|
||||
import unittest
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
from ddt import ddt, data, unpack
|
||||
import numpy as np
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.forward_euler_solver import (
|
||||
ForwardEulerSolver,
|
||||
)
|
||||
from qiskit.algorithms.evolvers.variational.solvers.var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.var_qte_ode_solver import (
|
||||
VarQTEOdeSolver,
|
||||
)
|
||||
from qiskit.algorithms.evolvers.variational.solvers.ode.ode_function import (
|
||||
OdeFunction,
|
||||
)
|
||||
from qiskit import BasicAer
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import (
|
||||
SummedOp,
|
||||
X,
|
||||
Y,
|
||||
I,
|
||||
Z,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class TestVarQTEOdeSolver(QiskitAlgorithmsTestCase):
|
||||
"""Test solver of ODEs."""
|
||||
|
||||
@data(
|
||||
(
|
||||
"RK45",
|
||||
[
|
||||
-0.30076755873631345,
|
||||
-0.8032811383782005,
|
||||
1.1674108371914734e-15,
|
||||
3.2293849116821145e-16,
|
||||
2.541585055586039,
|
||||
1.155475184255733,
|
||||
-2.966331417968169e-16,
|
||||
9.604292449638343e-17,
|
||||
],
|
||||
),
|
||||
(
|
||||
ForwardEulerSolver,
|
||||
[
|
||||
-3.2707e-01,
|
||||
-8.0960e-01,
|
||||
3.4323e-16,
|
||||
8.9034e-17,
|
||||
2.5290e00,
|
||||
1.1563e00,
|
||||
3.0227e-16,
|
||||
-2.2769e-16,
|
||||
],
|
||||
),
|
||||
)
|
||||
@unpack
|
||||
def test_run_no_backend(self, ode_solver, expected_result):
|
||||
"""Test ODE solver with no backend."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 1
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(ansatz.num_qubits):
|
||||
init_param_values[-(ansatz.num_qubits + i + 1)] = np.pi / 2
|
||||
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
time = 1
|
||||
|
||||
t_param = None
|
||||
|
||||
linear_solver = None
|
||||
linear_solver = VarQTELinearSolver(
|
||||
var_principle,
|
||||
observable,
|
||||
ansatz,
|
||||
parameters,
|
||||
t_param,
|
||||
linear_solver,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
ode_function_generator = OdeFunction(linear_solver, None, param_dict, t_param)
|
||||
|
||||
var_qte_ode_solver = VarQTEOdeSolver(
|
||||
list(param_dict.values()),
|
||||
ode_function_generator,
|
||||
ode_solver=ode_solver,
|
||||
num_timesteps=25,
|
||||
)
|
||||
|
||||
result = var_qte_ode_solver.run(time)
|
||||
|
||||
np.testing.assert_array_almost_equal(result, expected_result, decimal=4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,115 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test solver of linear equations."""
|
||||
|
||||
import unittest
|
||||
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
from ddt import ddt, data
|
||||
import numpy as np
|
||||
|
||||
from qiskit import BasicAer
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.algorithms.evolvers.variational.solvers.var_qte_linear_solver import (
|
||||
VarQTELinearSolver,
|
||||
)
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, X, Y, I, Z
|
||||
from .expected_results.test_varqte_linear_solver_expected_1 import (
|
||||
expected_metric_res_1,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class TestVarQTELinearSolver(QiskitAlgorithmsTestCase):
|
||||
"""Test solver of linear equations."""
|
||||
|
||||
@data(BasicAer.get_backend("statevector_simulator"), None)
|
||||
def test_solve_lse(self, backend):
|
||||
"""Test SLE solver."""
|
||||
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(ansatz.num_qubits):
|
||||
init_param_values[-(ansatz.num_qubits + i + 1)] = np.pi / 2
|
||||
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
t_param = None
|
||||
linear_solver = None
|
||||
linear_solver = VarQTELinearSolver(
|
||||
var_principle,
|
||||
observable,
|
||||
ansatz,
|
||||
parameters,
|
||||
t_param,
|
||||
linear_solver,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
|
||||
nat_grad_res, metric_res, grad_res = linear_solver.solve_lse(param_dict)
|
||||
|
||||
expected_nat_grad_res = [
|
||||
3.43500000e-01,
|
||||
-2.89800000e-01,
|
||||
2.43575264e-16,
|
||||
1.31792695e-16,
|
||||
-9.61200000e-01,
|
||||
-2.89800000e-01,
|
||||
1.27493709e-17,
|
||||
1.12587456e-16,
|
||||
3.43500000e-01,
|
||||
-2.89800000e-01,
|
||||
3.69914720e-17,
|
||||
1.95052083e-17,
|
||||
]
|
||||
|
||||
expected_grad_res = [
|
||||
(0.17174999999999926 - 0j),
|
||||
(-0.21735000000000085 + 0j),
|
||||
(4.114902862895087e-17 - 0j),
|
||||
(4.114902862895087e-17 - 0j),
|
||||
(-0.24030000000000012 + 0j),
|
||||
(-0.21735000000000085 + 0j),
|
||||
(4.114902862895087e-17 - 0j),
|
||||
(4.114902862895087e-17 - 0j),
|
||||
(0.17174999999999918 - 0j),
|
||||
(-0.21735000000000076 + 0j),
|
||||
(1.7789936190837538e-17 - 0j),
|
||||
(-8.319872568662832e-17 + 0j),
|
||||
]
|
||||
|
||||
np.testing.assert_array_almost_equal(nat_grad_res, expected_nat_grad_res, decimal=4)
|
||||
np.testing.assert_array_almost_equal(grad_res, expected_grad_res, decimal=4)
|
||||
np.testing.assert_array_almost_equal(metric_res, expected_metric_res_1, decimal=4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,287 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test Variational Quantum Imaginary Time Evolution algorithm."""
|
||||
|
||||
import unittest
|
||||
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
from ddt import data, ddt
|
||||
import numpy as np
|
||||
from qiskit.test import slow_test
|
||||
from qiskit.utils import algorithm_globals, QuantumInstance
|
||||
from qiskit import BasicAer
|
||||
from qiskit.algorithms import EvolutionProblem, VarQITE
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import (
|
||||
SummedOp,
|
||||
X,
|
||||
Y,
|
||||
I,
|
||||
Z,
|
||||
ExpectationFactory,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class TestVarQITE(QiskitAlgorithmsTestCase):
|
||||
"""Test Variational Quantum Imaginary Time Evolution algorithm."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.seed = 11
|
||||
np.random.seed(self.seed)
|
||||
backend_statevector = BasicAer.get_backend("statevector_simulator")
|
||||
backend_qasm = BasicAer.get_backend("qasm_simulator")
|
||||
self.quantum_instance = QuantumInstance(
|
||||
backend=backend_statevector,
|
||||
shots=1,
|
||||
seed_simulator=self.seed,
|
||||
seed_transpiler=self.seed,
|
||||
)
|
||||
self.quantum_instance_qasm = QuantumInstance(
|
||||
backend=backend_qasm,
|
||||
shots=4000,
|
||||
seed_simulator=self.seed,
|
||||
seed_transpiler=self.seed,
|
||||
)
|
||||
self.backends_dict = {
|
||||
"qi_sv": self.quantum_instance,
|
||||
"qi_qasm": self.quantum_instance_qasm,
|
||||
"b_sv": backend_statevector,
|
||||
}
|
||||
|
||||
self.backends_names = ["qi_qasm", "b_sv", "qi_sv"]
|
||||
|
||||
@slow_test
|
||||
def test_run_d_1_with_aux_ops(self):
|
||||
"""Test VarQITE for d = 1 and t = 1 with evaluating auxiliary operator and the Forward
|
||||
Euler solver.."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
aux_ops = [X ^ X, Y ^ Z]
|
||||
d = 1
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(len(parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
init_param_values[0] = 1
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
time = 1
|
||||
|
||||
evolution_problem = EvolutionProblem(observable, time, aux_operators=aux_ops)
|
||||
|
||||
thetas_expected_sv = [
|
||||
1.03612467538419,
|
||||
1.91891042963193,
|
||||
2.81129500883365,
|
||||
2.78938736703301,
|
||||
2.2215151699331,
|
||||
1.61953721158502,
|
||||
2.23490753161058,
|
||||
1.97145113701782,
|
||||
]
|
||||
|
||||
thetas_expected_qasm = [
|
||||
1.03612467538419,
|
||||
1.91891042963193,
|
||||
2.81129500883365,
|
||||
2.78938736703301,
|
||||
2.2215151699331,
|
||||
1.61953721158502,
|
||||
2.23490753161058,
|
||||
1.97145113701782,
|
||||
]
|
||||
|
||||
expected_aux_ops_evaluated_sv = [(-0.160899, 0.0), (0.26207, 0.0)]
|
||||
expected_aux_ops_evaluated_qasm = [
|
||||
(-0.1765, 0.015563),
|
||||
(0.2555, 0.015287),
|
||||
]
|
||||
|
||||
for backend_name in self.backends_names:
|
||||
with self.subTest(msg=f"Test {backend_name} backend."):
|
||||
algorithm_globals.random_seed = self.seed
|
||||
backend = self.backends_dict[backend_name]
|
||||
expectation = ExpectationFactory.build(
|
||||
operator=observable,
|
||||
backend=backend,
|
||||
)
|
||||
var_qite = VarQITE(
|
||||
ansatz,
|
||||
var_principle,
|
||||
param_dict,
|
||||
expectation=expectation,
|
||||
num_timesteps=25,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
||||
|
||||
evolved_state = evolution_result.evolved_state
|
||||
aux_ops = evolution_result.aux_ops_evaluated
|
||||
|
||||
parameter_values = evolved_state.data[0][0].params
|
||||
|
||||
if backend_name == "qi_qasm":
|
||||
thetas_expected = thetas_expected_qasm
|
||||
expected_aux_ops = expected_aux_ops_evaluated_qasm
|
||||
else:
|
||||
thetas_expected = thetas_expected_sv
|
||||
expected_aux_ops = expected_aux_ops_evaluated_sv
|
||||
|
||||
for i, parameter_value in enumerate(parameter_values):
|
||||
np.testing.assert_almost_equal(
|
||||
float(parameter_value), thetas_expected[i], decimal=3
|
||||
)
|
||||
|
||||
np.testing.assert_array_almost_equal(aux_ops, expected_aux_ops)
|
||||
|
||||
def test_run_d_1_t_7(self):
|
||||
"""Test VarQITE for d = 1 and t = 7 with RK45 ODE solver."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 1
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(len(parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
init_param_values[0] = 1
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
time = 7
|
||||
var_qite = VarQITE(
|
||||
ansatz,
|
||||
var_principle,
|
||||
init_param_values,
|
||||
ode_solver="RK45",
|
||||
num_timesteps=25,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
|
||||
thetas_expected = [
|
||||
0.828917365718767,
|
||||
1.88481074798033,
|
||||
3.14111335991238,
|
||||
3.14125849601269,
|
||||
2.33768562678401,
|
||||
1.78670990729437,
|
||||
2.04214275514208,
|
||||
2.04009918594422,
|
||||
]
|
||||
|
||||
self._test_helper(observable, thetas_expected, time, var_qite, 2)
|
||||
|
||||
@slow_test
|
||||
@data(
|
||||
SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
),
|
||||
0.2252 * (I ^ I)
|
||||
+ 0.5716 * (Z ^ Z)
|
||||
+ 0.3435 * (I ^ Z)
|
||||
+ -0.4347 * (Z ^ I)
|
||||
+ 0.091 * (Y ^ Y)
|
||||
+ 0.091 * (X ^ X),
|
||||
)
|
||||
def test_run_d_2(self, observable):
|
||||
"""Test VarQITE for d = 2 and t = 1 with RK45 ODE solver."""
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(len(parameters)):
|
||||
init_param_values[i] = np.pi / 4
|
||||
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
time = 1
|
||||
var_qite = VarQITE(
|
||||
ansatz,
|
||||
var_principle,
|
||||
param_dict,
|
||||
ode_solver="RK45",
|
||||
num_timesteps=25,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
|
||||
thetas_expected = [
|
||||
1.29495364023786,
|
||||
1.08970061333559,
|
||||
0.667488228710748,
|
||||
0.500122687902944,
|
||||
1.4377736672043,
|
||||
1.22881086103085,
|
||||
0.729773048146251,
|
||||
1.01698854755226,
|
||||
0.050807780587492,
|
||||
0.294828474947149,
|
||||
0.839305697704923,
|
||||
0.663689581255428,
|
||||
]
|
||||
|
||||
self._test_helper(observable, thetas_expected, time, var_qite, 4)
|
||||
|
||||
def _test_helper(self, observable, thetas_expected, time, var_qite, decimal):
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
evolution_result = var_qite.evolve(evolution_problem)
|
||||
evolved_state = evolution_result.evolved_state
|
||||
|
||||
parameter_values = evolved_state.data[0][0].params
|
||||
for i, parameter_value in enumerate(parameter_values):
|
||||
np.testing.assert_almost_equal(
|
||||
float(parameter_value), thetas_expected[i], decimal=decimal
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,234 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test Variational Quantum Real Time Evolution algorithm."""
|
||||
|
||||
import unittest
|
||||
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
from ddt import data, ddt
|
||||
import numpy as np
|
||||
from qiskit.test import slow_test
|
||||
from qiskit.utils import QuantumInstance, algorithm_globals
|
||||
from qiskit.algorithms import EvolutionProblem, VarQRTE
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
RealMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit import BasicAer
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import (
|
||||
SummedOp,
|
||||
X,
|
||||
Y,
|
||||
I,
|
||||
Z,
|
||||
ExpectationFactory,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class TestVarQRTE(QiskitAlgorithmsTestCase):
|
||||
"""Test Variational Quantum Real Time Evolution algorithm."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.seed = 11
|
||||
np.random.seed(self.seed)
|
||||
backend_statevector = BasicAer.get_backend("statevector_simulator")
|
||||
backend_qasm = BasicAer.get_backend("qasm_simulator")
|
||||
self.quantum_instance = QuantumInstance(
|
||||
backend=backend_statevector,
|
||||
shots=1,
|
||||
seed_simulator=self.seed,
|
||||
seed_transpiler=self.seed,
|
||||
)
|
||||
self.quantum_instance_qasm = QuantumInstance(
|
||||
backend=backend_qasm,
|
||||
shots=4000,
|
||||
seed_simulator=self.seed,
|
||||
seed_transpiler=self.seed,
|
||||
)
|
||||
self.backends_dict = {
|
||||
"qi_sv": self.quantum_instance,
|
||||
"qi_qasm": self.quantum_instance_qasm,
|
||||
"b_sv": backend_statevector,
|
||||
}
|
||||
|
||||
self.backends_names = ["qi_qasm", "b_sv", "qi_sv"]
|
||||
|
||||
@slow_test
|
||||
def test_run_d_1_with_aux_ops(self):
|
||||
"""Test VarQRTE for d = 1 and t = 0.1 with evaluating auxiliary operators and the Forward
|
||||
Euler solver."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
aux_ops = [X ^ X, Y ^ Z]
|
||||
d = 1
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(len(parameters)):
|
||||
init_param_values[i] = np.pi / 2
|
||||
init_param_values[0] = 1
|
||||
var_principle = RealMcLachlanPrinciple()
|
||||
|
||||
time = 0.1
|
||||
|
||||
evolution_problem = EvolutionProblem(observable, time, aux_operators=aux_ops)
|
||||
|
||||
thetas_expected_sv = [
|
||||
0.88967020378258,
|
||||
1.53740751016451,
|
||||
1.57076759018861,
|
||||
1.58893301221363,
|
||||
1.60100970594142,
|
||||
1.57008242207638,
|
||||
1.63791241090936,
|
||||
1.53741371076912,
|
||||
]
|
||||
|
||||
thetas_expected_qasm = [
|
||||
0.88967811203145,
|
||||
1.53745130248168,
|
||||
1.57206794045495,
|
||||
1.58901347342829,
|
||||
1.60101431615503,
|
||||
1.57138020823337,
|
||||
1.63796000651177,
|
||||
1.53742227084076,
|
||||
]
|
||||
|
||||
expected_aux_ops_evaluated_sv = [(0.06675, 0.0), (0.772636, 0.0)]
|
||||
|
||||
expected_aux_ops_evaluated_qasm = [
|
||||
(0.06450000000000006, 0.01577846435810532),
|
||||
(0.7895000000000001, 0.009704248425303218),
|
||||
]
|
||||
|
||||
for backend_name in self.backends_names:
|
||||
with self.subTest(msg=f"Test {backend_name} backend."):
|
||||
algorithm_globals.random_seed = self.seed
|
||||
backend = self.backends_dict[backend_name]
|
||||
expectation = ExpectationFactory.build(
|
||||
operator=observable,
|
||||
backend=backend,
|
||||
)
|
||||
var_qrte = VarQRTE(
|
||||
ansatz,
|
||||
var_principle,
|
||||
init_param_values,
|
||||
expectation=expectation,
|
||||
num_timesteps=25,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
evolution_result = var_qrte.evolve(evolution_problem)
|
||||
|
||||
evolved_state = evolution_result.evolved_state
|
||||
aux_ops = evolution_result.aux_ops_evaluated
|
||||
|
||||
parameter_values = evolved_state.data[0][0].params
|
||||
if backend_name == "qi_qasm":
|
||||
thetas_expected = thetas_expected_qasm
|
||||
expected_aux_ops = expected_aux_ops_evaluated_qasm
|
||||
else:
|
||||
thetas_expected = thetas_expected_sv
|
||||
expected_aux_ops = expected_aux_ops_evaluated_sv
|
||||
|
||||
for i, parameter_value in enumerate(parameter_values):
|
||||
np.testing.assert_almost_equal(
|
||||
float(parameter_value), thetas_expected[i], decimal=3
|
||||
)
|
||||
np.testing.assert_array_almost_equal(aux_ops, expected_aux_ops)
|
||||
|
||||
@slow_test
|
||||
@data(
|
||||
SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
),
|
||||
0.2252 * (I ^ I)
|
||||
+ 0.5716 * (Z ^ Z)
|
||||
+ 0.3435 * (I ^ Z)
|
||||
+ -0.4347 * (Z ^ I)
|
||||
+ 0.091 * (Y ^ Y)
|
||||
+ 0.091 * (X ^ X),
|
||||
)
|
||||
def test_run_d_2(self, observable):
|
||||
"""Test VarQRTE for d = 2 and t = 1 with RK45 ODE solver."""
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
parameters = list(ansatz.parameters)
|
||||
init_param_values = np.zeros(len(parameters))
|
||||
for i in range(len(parameters)):
|
||||
init_param_values[i] = np.pi / 4
|
||||
|
||||
var_principle = RealMcLachlanPrinciple()
|
||||
|
||||
param_dict = dict(zip(parameters, init_param_values))
|
||||
|
||||
backend = BasicAer.get_backend("statevector_simulator")
|
||||
|
||||
time = 1
|
||||
var_qrte = VarQRTE(
|
||||
ansatz,
|
||||
var_principle,
|
||||
param_dict,
|
||||
ode_solver="RK45",
|
||||
num_timesteps=25,
|
||||
quantum_instance=backend,
|
||||
)
|
||||
|
||||
thetas_expected = [
|
||||
0.348407744196573,
|
||||
0.919404626262464,
|
||||
1.18189219371626,
|
||||
0.771011177789998,
|
||||
0.734384256533924,
|
||||
0.965289520781899,
|
||||
1.14441687204195,
|
||||
1.17231927568571,
|
||||
1.03014771379412,
|
||||
0.867266309056347,
|
||||
0.699606368428206,
|
||||
0.610788576398685,
|
||||
]
|
||||
|
||||
self._test_helper(observable, thetas_expected, time, var_qrte)
|
||||
|
||||
def _test_helper(self, observable, thetas_expected, time, var_qrte):
|
||||
evolution_problem = EvolutionProblem(observable, time)
|
||||
evolution_result = var_qrte.evolve(evolution_problem)
|
||||
evolved_state = evolution_result.evolved_state
|
||||
|
||||
parameter_values = evolved_state.data[0][0].params
|
||||
for i, parameter_value in enumerate(parameter_values):
|
||||
np.testing.assert_almost_equal(float(parameter_value), thetas_expected[i], decimal=4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,78 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Test Variational Quantum Real Time Evolution algorithm."""
|
||||
|
||||
import unittest
|
||||
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
from numpy.testing import assert_raises
|
||||
from ddt import data, ddt
|
||||
import numpy as np
|
||||
|
||||
from qiskit.algorithms.evolvers.variational.var_qte import VarQTE
|
||||
from qiskit.circuit import Parameter
|
||||
|
||||
|
||||
@ddt
|
||||
class TestVarQTE(QiskitAlgorithmsTestCase):
|
||||
"""Test Variational Quantum Time Evolution class methods."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self._parameters1 = [Parameter("a"), Parameter("b"), Parameter("c")]
|
||||
|
||||
@data([1.4, 2, 3], np.asarray([1.4, 2, 3]))
|
||||
def test_create_init_state_param_dict(self, param_values):
|
||||
"""Tests if a correct dictionary is created."""
|
||||
expected = dict(zip(self._parameters1, param_values))
|
||||
with self.subTest("Parameters values given as a list test."):
|
||||
result = VarQTE._create_init_state_param_dict(param_values, self._parameters1)
|
||||
np.testing.assert_equal(result, expected)
|
||||
with self.subTest("Parameters values given as a dictionary test."):
|
||||
result = VarQTE._create_init_state_param_dict(
|
||||
dict(zip(self._parameters1, param_values)), self._parameters1
|
||||
)
|
||||
np.testing.assert_equal(result, expected)
|
||||
with self.subTest("Parameters values given as a superset dictionary test."):
|
||||
expected = dict(
|
||||
zip(
|
||||
[self._parameters1[0], self._parameters1[2]], [param_values[0], param_values[2]]
|
||||
)
|
||||
)
|
||||
result = VarQTE._create_init_state_param_dict(
|
||||
dict(zip(self._parameters1, param_values)),
|
||||
[self._parameters1[0], self._parameters1[2]],
|
||||
)
|
||||
np.testing.assert_equal(result, expected)
|
||||
|
||||
@data([1.4, 2], np.asarray([1.4, 3]), {}, [])
|
||||
def test_create_init_state_param_dict_errors_list(self, param_values):
|
||||
"""Tests if an error is raised."""
|
||||
with assert_raises(ValueError):
|
||||
_ = VarQTE._create_init_state_param_dict(param_values, self._parameters1)
|
||||
|
||||
@data([1.4, 2], np.asarray([1.4, 3]))
|
||||
def test_create_init_state_param_dict_errors_subset(self, param_values):
|
||||
"""Tests if an error is raised if subset of parameters provided."""
|
||||
param_values_dict = dict(zip([self._parameters1[0], self._parameters1[2]], param_values))
|
||||
with assert_raises(ValueError):
|
||||
_ = VarQTE._create_init_state_param_dict(param_values_dict, self._parameters1)
|
||||
|
||||
@data(5, "s", Parameter("x"))
|
||||
def test_create_init_state_param_dict_errors_type(self, param_values):
|
||||
"""Tests if an error is raised if wrong input type."""
|
||||
with assert_raises(TypeError):
|
||||
_ = VarQTE._create_init_state_param_dict(param_values, self._parameters1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,12 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
|
@ -1,182 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
||||
expected_bound_metric_tensor_1 = [
|
||||
[
|
||||
2.50000000e-01 + 0.0j,
|
||||
1.59600000e-33 + 0.0j,
|
||||
5.90075760e-18 + 0.0j,
|
||||
-8.49242405e-19 + 0.0j,
|
||||
8.83883476e-02 + 0.0j,
|
||||
1.33253788e-17 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.40000000e-17 + 0.0j,
|
||||
-1.41735435e-01 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
1.00222087e-01 + 0.0j,
|
||||
-3.12500000e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.59600000e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
1.34350288e-17 + 0.0j,
|
||||
6.43502884e-18 + 0.0j,
|
||||
-8.83883476e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-8.45970869e-02 + 0.0j,
|
||||
7.54441738e-02 + 0.0j,
|
||||
1.48207521e-01 + 0.0j,
|
||||
2.00444174e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
5.90075760e-18 + 0.0j,
|
||||
1.34350288e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.19638348e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
-5.14514565e-02 + 0.0j,
|
||||
6.89720869e-02 + 0.0j,
|
||||
1.04933262e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-8.49242405e-19 + 0.0j,
|
||||
6.43502884e-18 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-6.25000000e-02 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
5.14514565e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
7.81250000e-03 + 0.0j,
|
||||
1.94162607e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
8.83883476e-02 + 0.0j,
|
||||
-8.83883476e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
2.34375000e-01 + 0.0j,
|
||||
-1.10485435e-01 + 0.0j,
|
||||
-2.02014565e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
1.49547935e-02 + 0.0j,
|
||||
-2.24896848e-02 + 0.0j,
|
||||
-1.42172278e-03 + 0.0j,
|
||||
-1.23822206e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.33253788e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
-6.25000000e-02 + 0.0j,
|
||||
-1.10485435e-01 + 0.0j,
|
||||
2.18750000e-01 + 0.0j,
|
||||
-2.68082618e-03 + 0.0j,
|
||||
-1.59099026e-17 + 0.0j,
|
||||
-1.57197815e-01 + 0.0j,
|
||||
2.53331304e-02 + 0.0j,
|
||||
9.82311963e-03 + 0.0j,
|
||||
1.06138957e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
6.25000000e-02 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.19638348e-01 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
-2.02014565e-02 + 0.0j,
|
||||
-2.68082618e-03 + 0.0j,
|
||||
2.23881674e-01 + 0.0j,
|
||||
1.37944174e-01 + 0.0j,
|
||||
-3.78033966e-02 + 0.0j,
|
||||
1.58423239e-01 + 0.0j,
|
||||
1.34535646e-01 + 0.0j,
|
||||
-5.49651086e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.40000000e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-1.59099026e-17 + 0.0j,
|
||||
1.37944174e-01 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-2.10523539e-17 + 0.0j,
|
||||
1.15574269e-17 + 0.0j,
|
||||
9.75412607e-02 + 0.0j,
|
||||
5.71383476e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.41735435e-01 + 0.0j,
|
||||
-8.45970869e-02 + 0.0j,
|
||||
-5.14514565e-02 + 0.0j,
|
||||
5.14514565e-02 + 0.0j,
|
||||
1.49547935e-02 + 0.0j,
|
||||
-1.57197815e-01 + 0.0j,
|
||||
-3.78033966e-02 + 0.0j,
|
||||
-2.10523539e-17 + 0.0j,
|
||||
1.95283753e-01 + 0.0j,
|
||||
-3.82941440e-02 + 0.0j,
|
||||
-6.11392595e-02 + 0.0j,
|
||||
-4.51588288e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
3.12500000e-02 + 0.0j,
|
||||
7.54441738e-02 + 0.0j,
|
||||
6.89720869e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
-2.24896848e-02 + 0.0j,
|
||||
2.53331304e-02 + 0.0j,
|
||||
1.58423239e-01 + 0.0j,
|
||||
1.15574269e-17 + 0.0j,
|
||||
-3.82941440e-02 + 0.0j,
|
||||
2.17629701e-01 + 0.0j,
|
||||
1.32431810e-01 + 0.0j,
|
||||
-1.91961467e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.00222087e-01 + 0.0j,
|
||||
1.48207521e-01 + 0.0j,
|
||||
1.04933262e-02 + 0.0j,
|
||||
7.81250000e-03 + 0.0j,
|
||||
-1.42172278e-03 + 0.0j,
|
||||
9.82311963e-03 + 0.0j,
|
||||
1.34535646e-01 + 0.0j,
|
||||
9.75412607e-02 + 0.0j,
|
||||
-6.11392595e-02 + 0.0j,
|
||||
1.32431810e-01 + 0.0j,
|
||||
1.81683746e-01 + 0.0j,
|
||||
7.28902444e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-3.12500000e-02 + 0.0j,
|
||||
2.00444174e-01 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
1.94162607e-02 + 0.0j,
|
||||
-1.23822206e-01 + 0.0j,
|
||||
1.06138957e-01 + 0.0j,
|
||||
-5.49651086e-02 + 0.0j,
|
||||
5.71383476e-02 + 0.0j,
|
||||
-4.51588288e-02 + 0.0j,
|
||||
-1.91961467e-02 + 0.0j,
|
||||
7.28902444e-02 + 0.0j,
|
||||
2.38616353e-01 + 0.0j,
|
||||
],
|
||||
]
|
|
@ -1,182 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
||||
expected_bound_metric_tensor_2 = [
|
||||
[
|
||||
2.50000000e-01 + 0.0j,
|
||||
1.59600000e-33 + 0.0j,
|
||||
5.90075760e-18 + 0.0j,
|
||||
-8.49242405e-19 + 0.0j,
|
||||
8.83883476e-02 + 0.0j,
|
||||
1.33253788e-17 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.40000000e-17 + 0.0j,
|
||||
-1.41735435e-01 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
1.00222087e-01 + 0.0j,
|
||||
-3.12500000e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.59600000e-33 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
1.34350288e-17 + 0.0j,
|
||||
6.43502884e-18 + 0.0j,
|
||||
-8.83883476e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-8.45970869e-02 + 0.0j,
|
||||
7.54441738e-02 + 0.0j,
|
||||
1.48207521e-01 + 0.0j,
|
||||
2.00444174e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
5.90075760e-18 + 0.0j,
|
||||
1.34350288e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.19638348e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
-5.14514565e-02 + 0.0j,
|
||||
6.89720869e-02 + 0.0j,
|
||||
1.04933262e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-8.49242405e-19 + 0.0j,
|
||||
6.43502884e-18 + 0.0j,
|
||||
-1.38777878e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-6.25000000e-02 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
5.14514565e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
7.81250000e-03 + 0.0j,
|
||||
1.94162607e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
8.83883476e-02 + 0.0j,
|
||||
-8.83883476e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
2.34375000e-01 + 0.0j,
|
||||
-1.10485435e-01 + 0.0j,
|
||||
-2.02014565e-02 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
1.49547935e-02 + 0.0j,
|
||||
-2.24896848e-02 + 0.0j,
|
||||
-1.42172278e-03 + 0.0j,
|
||||
-1.23822206e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.33253788e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
-6.25000000e-02 + 0.0j,
|
||||
-1.10485435e-01 + 0.0j,
|
||||
2.18750000e-01 + 0.0j,
|
||||
-2.68082618e-03 + 0.0j,
|
||||
-1.59099026e-17 + 0.0j,
|
||||
-1.57197815e-01 + 0.0j,
|
||||
2.53331304e-02 + 0.0j,
|
||||
9.82311963e-03 + 0.0j,
|
||||
1.06138957e-01 + 0.0j,
|
||||
],
|
||||
[
|
||||
6.25000000e-02 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.19638348e-01 + 0.0j,
|
||||
3.12500000e-02 + 0.0j,
|
||||
-2.02014565e-02 + 0.0j,
|
||||
-2.68082618e-03 + 0.0j,
|
||||
2.23881674e-01 + 0.0j,
|
||||
1.37944174e-01 + 0.0j,
|
||||
-3.78033966e-02 + 0.0j,
|
||||
1.58423239e-01 + 0.0j,
|
||||
1.34535646e-01 + 0.0j,
|
||||
-5.49651086e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.40000000e-17 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
6.25000000e-02 + 0.0j,
|
||||
1.25000000e-01 + 0.0j,
|
||||
-4.41941738e-02 + 0.0j,
|
||||
-1.59099026e-17 + 0.0j,
|
||||
1.37944174e-01 + 0.0j,
|
||||
2.50000000e-01 + 0.0j,
|
||||
-2.10523539e-17 + 0.0j,
|
||||
1.15574269e-17 + 0.0j,
|
||||
9.75412607e-02 + 0.0j,
|
||||
5.71383476e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-1.41735435e-01 + 0.0j,
|
||||
-8.45970869e-02 + 0.0j,
|
||||
-5.14514565e-02 + 0.0j,
|
||||
5.14514565e-02 + 0.0j,
|
||||
1.49547935e-02 + 0.0j,
|
||||
-1.57197815e-01 + 0.0j,
|
||||
-3.78033966e-02 + 0.0j,
|
||||
-2.10523539e-17 + 0.0j,
|
||||
1.95283753e-01 + 0.0j,
|
||||
-3.82941440e-02 + 0.0j,
|
||||
-6.11392595e-02 + 0.0j,
|
||||
-4.51588288e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
3.12500000e-02 + 0.0j,
|
||||
7.54441738e-02 + 0.0j,
|
||||
6.89720869e-02 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
-2.24896848e-02 + 0.0j,
|
||||
2.53331304e-02 + 0.0j,
|
||||
1.58423239e-01 + 0.0j,
|
||||
1.15574269e-17 + 0.0j,
|
||||
-3.82941440e-02 + 0.0j,
|
||||
2.17629701e-01 + 0.0j,
|
||||
1.32431810e-01 + 0.0j,
|
||||
-1.91961467e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
1.00222087e-01 + 0.0j,
|
||||
1.48207521e-01 + 0.0j,
|
||||
1.04933262e-02 + 0.0j,
|
||||
7.81250000e-03 + 0.0j,
|
||||
-1.42172278e-03 + 0.0j,
|
||||
9.82311963e-03 + 0.0j,
|
||||
1.34535646e-01 + 0.0j,
|
||||
9.75412607e-02 + 0.0j,
|
||||
-6.11392595e-02 + 0.0j,
|
||||
1.32431810e-01 + 0.0j,
|
||||
1.81683746e-01 + 0.0j,
|
||||
7.28902444e-02 + 0.0j,
|
||||
],
|
||||
[
|
||||
-3.12500000e-02 + 0.0j,
|
||||
2.00444174e-01 + 0.0j,
|
||||
-6.89720869e-02 + 0.0j,
|
||||
1.94162607e-02 + 0.0j,
|
||||
-1.23822206e-01 + 0.0j,
|
||||
1.06138957e-01 + 0.0j,
|
||||
-5.49651086e-02 + 0.0j,
|
||||
5.71383476e-02 + 0.0j,
|
||||
-4.51588288e-02 + 0.0j,
|
||||
-1.91961467e-02 + 0.0j,
|
||||
7.28902444e-02 + 0.0j,
|
||||
2.38616353e-01 + 0.0j,
|
||||
],
|
||||
]
|
|
@ -1,182 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
"""Stores expected results that are lengthy."""
|
||||
expected_bound_metric_tensor_3 = [
|
||||
[
|
||||
-1.21000000e-34 + 0.00e00j,
|
||||
1.21000000e-34 + 2.50e-19j,
|
||||
1.76776695e-01 - 1.00e-18j,
|
||||
-1.40000000e-17 + 0.00e00j,
|
||||
-6.25000000e-02 + 0.00e00j,
|
||||
8.83883476e-02 - 1.25e-18j,
|
||||
1.69194174e-01 + 2.25e-18j,
|
||||
8.83883476e-02 - 2.50e-19j,
|
||||
-7.27633476e-02 + 0.00e00j,
|
||||
9.75412607e-02 + 7.50e-19j,
|
||||
1.48398042e-02 - 1.75e-18j,
|
||||
-9.75412607e-02 + 3.75e-18j,
|
||||
],
|
||||
[
|
||||
1.21000000e-34 + 2.50e-19j,
|
||||
-1.21000000e-34 + 0.00e00j,
|
||||
1.10000000e-34 + 2.75e-18j,
|
||||
1.76776695e-01 - 2.25e-18j,
|
||||
-6.25000000e-02 + 0.00e00j,
|
||||
-8.83883476e-02 + 4.00e-18j,
|
||||
4.41941738e-02 - 1.25e-18j,
|
||||
1.76776695e-01 - 2.50e-19j,
|
||||
7.27633476e-02 - 7.50e-19j,
|
||||
-9.75412607e-02 - 7.50e-19j,
|
||||
1.10485435e-02 - 7.50e-19j,
|
||||
2.74587393e-02 + 2.50e-19j,
|
||||
],
|
||||
[
|
||||
1.76776695e-01 - 1.00e-18j,
|
||||
1.10000000e-34 + 2.75e-18j,
|
||||
-1.25000000e-01 + 0.00e00j,
|
||||
-1.25000000e-01 + 0.00e00j,
|
||||
-1.06694174e-01 + 1.25e-18j,
|
||||
-6.25000000e-02 + 1.75e-18j,
|
||||
-1.01332521e-01 + 7.50e-19j,
|
||||
4.67500000e-17 - 7.50e-19j,
|
||||
1.75206304e-02 + 5.00e-19j,
|
||||
-8.57075215e-02 - 1.00e-18j,
|
||||
-1.63277304e-01 + 1.00e-18j,
|
||||
-1.56250000e-02 + 0.00e00j,
|
||||
],
|
||||
[
|
||||
-1.40000000e-17 + 0.00e00j,
|
||||
1.76776695e-01 - 2.25e-18j,
|
||||
-1.25000000e-01 + 0.00e00j,
|
||||
-1.25000000e-01 + 0.00e00j,
|
||||
1.83058262e-02 - 1.50e-18j,
|
||||
-1.50888348e-01 - 1.50e-18j,
|
||||
-1.01332521e-01 + 2.50e-19j,
|
||||
-8.83883476e-02 - 1.00e-18j,
|
||||
-2.28822827e-02 - 1.00e-18j,
|
||||
-1.16957521e-01 + 1.00e-18j,
|
||||
-1.97208130e-01 + 0.00e00j,
|
||||
-1.79457521e-01 + 1.25e-18j,
|
||||
],
|
||||
[
|
||||
-6.25000000e-02 + 0.00e00j,
|
||||
-6.25000000e-02 + 0.00e00j,
|
||||
-1.06694174e-01 + 1.25e-18j,
|
||||
1.83058262e-02 - 1.50e-18j,
|
||||
-1.56250000e-02 + 0.00e00j,
|
||||
-2.20970869e-02 - 2.00e-18j,
|
||||
1.48992717e-01 - 1.00e-18j,
|
||||
2.60000000e-17 - 1.50e-18j,
|
||||
-6.69614673e-02 - 5.00e-19j,
|
||||
2.00051576e-01 + 5.00e-19j,
|
||||
1.13640168e-01 + 1.25e-18j,
|
||||
-4.83780325e-02 - 1.00e-18j,
|
||||
],
|
||||
[
|
||||
8.83883476e-02 - 1.25e-18j,
|
||||
-8.83883476e-02 + 4.00e-18j,
|
||||
-6.25000000e-02 + 1.75e-18j,
|
||||
-1.50888348e-01 - 1.50e-18j,
|
||||
-2.20970869e-02 - 2.00e-18j,
|
||||
-3.12500000e-02 + 0.00e00j,
|
||||
-2.85691738e-02 + 4.25e-18j,
|
||||
1.76776695e-01 + 0.00e00j,
|
||||
5.52427173e-03 + 1.00e-18j,
|
||||
-1.29346478e-01 + 5.00e-19j,
|
||||
-4.81004238e-02 + 4.25e-18j,
|
||||
5.27918696e-02 + 2.50e-19j,
|
||||
],
|
||||
[
|
||||
1.69194174e-01 + 2.25e-18j,
|
||||
4.41941738e-02 - 1.25e-18j,
|
||||
-1.01332521e-01 + 7.50e-19j,
|
||||
-1.01332521e-01 + 2.50e-19j,
|
||||
1.48992717e-01 - 1.00e-18j,
|
||||
-2.85691738e-02 + 4.25e-18j,
|
||||
-2.61183262e-02 + 0.00e00j,
|
||||
-6.88900000e-33 + 0.00e00j,
|
||||
6.62099510e-02 - 1.00e-18j,
|
||||
-2.90767610e-02 + 1.75e-18j,
|
||||
-1.24942505e-01 + 0.00e00j,
|
||||
-1.72430217e-02 + 2.50e-19j,
|
||||
],
|
||||
[
|
||||
8.83883476e-02 - 2.50e-19j,
|
||||
1.76776695e-01 - 2.50e-19j,
|
||||
4.67500000e-17 - 7.50e-19j,
|
||||
-8.83883476e-02 - 1.00e-18j,
|
||||
2.60000000e-17 - 1.50e-18j,
|
||||
1.76776695e-01 + 0.00e00j,
|
||||
-6.88900000e-33 + 0.00e00j,
|
||||
-6.88900000e-33 + 0.00e00j,
|
||||
1.79457521e-01 - 1.75e-18j,
|
||||
-5.33470869e-02 + 2.00e-18j,
|
||||
-9.56456304e-02 + 3.00e-18j,
|
||||
-1.32582521e-01 + 2.50e-19j,
|
||||
],
|
||||
[
|
||||
-7.27633476e-02 + 0.00e00j,
|
||||
7.27633476e-02 - 7.50e-19j,
|
||||
1.75206304e-02 + 5.00e-19j,
|
||||
-2.28822827e-02 - 1.00e-18j,
|
||||
-6.69614673e-02 - 5.00e-19j,
|
||||
5.52427173e-03 + 1.00e-18j,
|
||||
6.62099510e-02 - 1.00e-18j,
|
||||
1.79457521e-01 - 1.75e-18j,
|
||||
-5.47162473e-02 + 0.00e00j,
|
||||
-4.20854047e-02 + 4.00e-18j,
|
||||
-7.75494553e-02 - 2.50e-18j,
|
||||
-2.49573723e-02 + 7.50e-19j,
|
||||
],
|
||||
[
|
||||
9.75412607e-02 + 7.50e-19j,
|
||||
-9.75412607e-02 - 7.50e-19j,
|
||||
-8.57075215e-02 - 1.00e-18j,
|
||||
-1.16957521e-01 + 1.00e-18j,
|
||||
2.00051576e-01 + 5.00e-19j,
|
||||
-1.29346478e-01 + 5.00e-19j,
|
||||
-2.90767610e-02 + 1.75e-18j,
|
||||
-5.33470869e-02 + 2.00e-18j,
|
||||
-4.20854047e-02 + 4.00e-18j,
|
||||
-3.23702991e-02 + 0.00e00j,
|
||||
-4.70257118e-02 + 0.00e00j,
|
||||
1.22539288e-01 - 2.25e-18j,
|
||||
],
|
||||
[
|
||||
1.48398042e-02 - 1.75e-18j,
|
||||
1.10485435e-02 - 7.50e-19j,
|
||||
-1.63277304e-01 + 1.00e-18j,
|
||||
-1.97208130e-01 + 0.00e00j,
|
||||
1.13640168e-01 + 1.25e-18j,
|
||||
-4.81004238e-02 + 4.25e-18j,
|
||||
-1.24942505e-01 + 0.00e00j,
|
||||
-9.56456304e-02 + 3.00e-18j,
|
||||
-7.75494553e-02 - 2.50e-18j,
|
||||
-4.70257118e-02 + 0.00e00j,
|
||||
-6.83162540e-02 + 0.00e00j,
|
||||
-2.78870598e-02 + 0.00e00j,
|
||||
],
|
||||
[
|
||||
-9.75412607e-02 + 3.75e-18j,
|
||||
2.74587393e-02 + 2.50e-19j,
|
||||
-1.56250000e-02 + 0.00e00j,
|
||||
-1.79457521e-01 + 1.25e-18j,
|
||||
-4.83780325e-02 - 1.00e-18j,
|
||||
5.27918696e-02 + 2.50e-19j,
|
||||
-1.72430217e-02 + 2.50e-19j,
|
||||
-1.32582521e-01 + 2.50e-19j,
|
||||
-2.49573723e-02 + 7.50e-19j,
|
||||
1.22539288e-01 - 2.25e-18j,
|
||||
-2.78870598e-02 + 0.00e00j,
|
||||
-1.13836467e-02 + 0.00e00j,
|
||||
],
|
||||
]
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,111 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test imaginary McLachlan's variational principle."""
|
||||
|
||||
import unittest
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
import numpy as np
|
||||
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
ImaginaryMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, X, Y, I, Z
|
||||
from ..expected_results.test_imaginary_mc_lachlan_variational_principle_expected1 import (
|
||||
expected_bound_metric_tensor_1,
|
||||
)
|
||||
|
||||
|
||||
class TestImaginaryMcLachlanPrinciple(QiskitAlgorithmsTestCase):
|
||||
"""Test imaginary McLachlan's variational principle."""
|
||||
|
||||
def test_calc_metric_tensor(self):
|
||||
"""Test calculating a metric tensor."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
bound_metric_tensor = var_principle.metric_tensor(
|
||||
ansatz, parameters, parameters, param_dict.values(), None, None
|
||||
)
|
||||
|
||||
np.testing.assert_almost_equal(bound_metric_tensor, expected_bound_metric_tensor_1)
|
||||
|
||||
def test_calc_calc_evolution_grad(self):
|
||||
"""Test calculating evolution gradient."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
var_principle = ImaginaryMcLachlanPrinciple()
|
||||
|
||||
bound_evolution_grad = var_principle.evolution_grad(
|
||||
observable,
|
||||
ansatz,
|
||||
None,
|
||||
param_dict,
|
||||
parameters,
|
||||
parameters,
|
||||
param_dict.values(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
expected_bound_evolution_grad = [
|
||||
(0.19308934095957098 - 1.4e-17j),
|
||||
(0.007027674650099142 - 0j),
|
||||
(0.03192524520091862 - 0j),
|
||||
(-0.06810314606309673 - 1e-18j),
|
||||
(0.07590371669521798 - 7e-18j),
|
||||
(0.11891968269385343 + 1.5e-18j),
|
||||
(-0.0012030273438232639 + 0j),
|
||||
(-0.049885258804562266 + 1.8500000000000002e-17j),
|
||||
(-0.20178860797540302 - 5e-19j),
|
||||
(-0.0052269232310933195 + 1e-18j),
|
||||
(0.022892905637005266 - 3e-18j),
|
||||
(-0.022892905637005294 + 3.5e-18j),
|
||||
]
|
||||
|
||||
np.testing.assert_almost_equal(bound_evolution_grad, expected_bound_evolution_grad)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -1,11 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
|
@ -1,114 +0,0 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2021, 2022.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""Test real McLachlan's variational principle."""
|
||||
|
||||
import unittest
|
||||
from test.python.algorithms import QiskitAlgorithmsTestCase
|
||||
import numpy as np
|
||||
from qiskit.algorithms.evolvers.variational import (
|
||||
RealMcLachlanPrinciple,
|
||||
)
|
||||
from qiskit.circuit.library import EfficientSU2
|
||||
from qiskit.opflow import SummedOp, X, Y, I, Z
|
||||
from ..expected_results.test_imaginary_mc_lachlan_variational_principle_expected2 import (
|
||||
expected_bound_metric_tensor_2,
|
||||
)
|
||||
|
||||
|
||||
class TestRealMcLachlanPrinciple(QiskitAlgorithmsTestCase):
|
||||
"""Test real McLachlan's variational principle."""
|
||||
|
||||
def test_calc_calc_metric_tensor(self):
|
||||
"""Test calculating a metric tensor."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
var_principle = RealMcLachlanPrinciple()
|
||||
|
||||
bound_metric_tensor = var_principle.metric_tensor(
|
||||
ansatz, parameters, parameters, list(param_dict.values()), None, None
|
||||
)
|
||||
|
||||
np.testing.assert_almost_equal(
|
||||
bound_metric_tensor, expected_bound_metric_tensor_2, decimal=5
|
||||
)
|
||||
|
||||
def test_calc_evolution_grad(self):
|
||||
"""Test calculating evolution gradient."""
|
||||
observable = SummedOp(
|
||||
[
|
||||
0.2252 * (I ^ I),
|
||||
0.5716 * (Z ^ Z),
|
||||
0.3435 * (I ^ Z),
|
||||
-0.4347 * (Z ^ I),
|
||||
0.091 * (Y ^ Y),
|
||||
0.091 * (X ^ X),
|
||||
]
|
||||
)
|
||||
|
||||
d = 2
|
||||
ansatz = EfficientSU2(observable.num_qubits, reps=d)
|
||||
|
||||
# Define a set of initial parameters
|
||||
parameters = list(ansatz.parameters)
|
||||
param_dict = {param: np.pi / 4 for param in parameters}
|
||||
var_principle = RealMcLachlanPrinciple()
|
||||
|
||||
bound_evolution_grad = var_principle.evolution_grad(
|
||||
observable,
|
||||
ansatz,
|
||||
None,
|
||||
param_dict,
|
||||
parameters,
|
||||
parameters,
|
||||
list(param_dict.values()),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
expected_bound_evolution_grad = [
|
||||
(-0.04514911474522546 + 4e-18j),
|
||||
(0.0963123928027075 - 1.5e-18j),
|
||||
(0.1365347823673539 - 7e-18j),
|
||||
(0.004969316401057883 - 4.9999999999999996e-18j),
|
||||
(-0.003843833929692342 - 4.999999999999998e-19j),
|
||||
(0.07036988622493834 - 7e-18j),
|
||||
(0.16560609099860682 - 3.5e-18j),
|
||||
(0.16674183768051887 + 1e-18j),
|
||||
(-0.03843296670360974 - 6e-18j),
|
||||
(0.08891074158680243 - 6e-18j),
|
||||
(0.06425681697616654 + 7e-18j),
|
||||
(-0.03172376682078948 - 7e-18j),
|
||||
]
|
||||
|
||||
np.testing.assert_almost_equal(
|
||||
bound_evolution_grad, expected_bound_evolution_grad, decimal=5
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue