Source code for QHyper.optimizers
# This work was supported by the EuroHPC PL infrastructure funded at the
# Smart Growth Operational Programme (2014-2020), Measure 4.2
# under the grant agreement no. POIR.04.02.00-00-D014/20-00
"""
This module contains implementations of different optimizers.
Some of the optimizers are written from scratch based on popular algorithms,
while others are just a wrapper for existing solutions.
No optimizer is imported by deafult to reduce number of dependencies.
To use any optimizer you can import it directly like
.. code-block:: python
from QHyper.optimizers.random import Random
or use function :py:func:`Optimizers.get` with the name of the optimizer.
Any optimizer that is in directory 'QHyper/custom' or 'custom' will be
also available in this function.
.. rubric:: Optimization result dataclass
.. autosummary::
:toctree: generated
OptimizationResult
OptimizationParameter
.. rubric:: Interface
.. autosummary::
:toctree: generated
Optimizer
.. rubric:: Available optimizers
.. autosummary::
:toctree: generated
scipy_minimizer.ScipyOptimizer -- Wrapper for the scipy.optimize.minimize function.
qml_gradient_descent.QmlGradientDescent -- Wrapper for the PennyLane gradient descent optimizers.
cem.CEM -- Cross-entropy method optimizer.
random.Random -- Random search optimizer.
grid_search.GridSearch -- Grid search optimizer.
dummy.Dummy -- Dummy optimizer.
.. rubric:: Additional functions
.. autoclass:: Optimizers
:members:
"""
import copy
from typing import Type, Any
from QHyper.util import search_for
from QHyper.optimizers.base import ( # noqa: F401
Optimizer, OptimizationResult, OptimizerError, OptimizationParameter) # noqa: F401
from .dummy import Dummy
[docs]
class Optimizers:
custom_optimizers: None | dict[str, type] = None
[docs]
@staticmethod
def get(name: str) -> Type[Optimizer]:
"""
Get Optimizer class by name.
The optimizer will be available by the 'name' attribute if defined or
by the class name. Letters case doesn't matter.
"""
if Optimizers.custom_optimizers is None:
Optimizers.custom_optimizers = (
search_for(Optimizer, 'QHyper/custom')
| search_for(Optimizer, 'custom'))
name_ = name.lower()
if name_ in Optimizers.custom_optimizers:
return Optimizers.custom_optimizers[name_]
elif name_ in ["scipy", "scipyminimizer"]:
from .scipy_minimizer import ScipyOptimizer
return ScipyOptimizer
elif name_ in ["random", "randomsearch"]:
from .random import Random
return Random
elif name_ in ["qml", "qmlgradientdescent"]:
from .qml_gradient_descent import QmlGradientDescent
return QmlGradientDescent
elif name_ in ["cem", "crossentropymethod"]:
from .cem import CEM
return CEM
elif name_ in ["grid", "gridsearch"]:
from .grid_search import GridSearch
return GridSearch
elif name_ in ["dummy"]:
return Dummy
else:
raise OptimizerError(f"Optimizer {name} not found")
def create_optimizer(config: dict[str, Any]) -> Optimizer:
config_ = copy.deepcopy(config)
opt_type = config_.pop('type')
optimizer_class = Optimizers.get(opt_type)
return optimizer_class(**config_)