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:
dlasecki 2022-09-16 00:39:30 +02:00 committed by GitHub
parent 64a9eb1e4a
commit 8bb1c01a8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 0 additions and 3862 deletions

View File

@ -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",

View File

@ -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",
]

View File

@ -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"]

View File

@ -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"""

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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."
)

View File

@ -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

View File

@ -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

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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."
)

View File

@ -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",
]

View File

@ -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

View File

@ -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."""

View File

@ -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)

View File

@ -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,
)

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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."""

View File

@ -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,
],
]

View File

@ -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.

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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.

View File

@ -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."""

View File

@ -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,
],
]

View File

@ -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,
],
]

View File

@ -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,
],
]

View File

@ -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.

View File

@ -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()

View File

@ -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.

View File

@ -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()