Source code for gemseo_benchmark.algorithms.algorithm_configuration

# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
# Contributors:
#    INITIAL AUTHORS - initial API and implementation and/or initial
#                           documentation
#        :author: Benoit Pauwels
#    OTHER AUTHORS   - MACROSCOPIC CHANGES
"""Configuration of an algorithm defined by the values of its options.

An algorithm depends on the values of its options. A value set defines a configuration
of the algorithm.
"""

from __future__ import annotations

from collections.abc import MutableMapping
from types import MappingProxyType
from typing import Any
from typing import Callable
from typing import Final

from gemseo.utils.string_tools import pretty_repr

InstanceAlgorithmOptions = MutableMapping[str, Callable[[int], Any]]


[docs] class AlgorithmConfiguration: """The configuration of an algorithm.""" __ALGORITHM_NAME: Final[str] = "algorithm_name" __ALGORITHM_OPTIONS: Final[str] = "algorithm_options" __CONFIGURATION_NAME: Final[str] = "configuration_name" __INSTANCE_ALGORITHM_OPTIONS: Final[str] = "instance_algorithm_options" def __init__( self, algorithm_name: str, configuration_name: str | None = None, instance_algorithm_options: InstanceAlgorithmOptions = MappingProxyType({}), **algorithm_options: Any, ) -> None: """ Args: algorithm_name: The name of the algorithm. configuration_name: The name of the configuration of the algorithm. If ``None``, a name will be generated based on the algorithm name and its options, based on the pattern ``"algorithm_name[option_name=option_value, ...]"``. instance_algorithm_options: The options of the algorithm specific to instances of a problem. They shall be passed as a mapping that links the name of an algorithm option to a callable that takes the 0-based index of the instance as argument and returns the value of the option. **algorithm_options: The options of the algorithm. """ # noqa: D205, D212, D415 self.__algorithm_name = algorithm_name self.__algorithm_options = algorithm_options self.__configuration_name = configuration_name or self.__get_configuration_name( algorithm_name, **algorithm_options ) self.__instance_algorithm_options = instance_algorithm_options @staticmethod def __get_configuration_name(algorithm_name: str, **algorithm_options: Any) -> str: """Define a name for the configuration based on the algorithm name and options. Args: algorithm_name: The name of the algorithm. **algorithm_options: The options of the algorithm. Returns: The name of the algorithm configuration. """ if not algorithm_options: return algorithm_name return f"{algorithm_name}_{pretty_repr(algorithm_options)}" @property def name(self) -> str: """The name of the algorithm configuration.""" return self.__configuration_name @property def algorithm_name(self) -> str: """The name of the algorithm.""" return self.__algorithm_name @property def algorithm_options(self) -> dict[str, Any]: """The options of the algorithm.""" return self.__algorithm_options @property def instance_algorithm_options(self) -> InstanceAlgorithmOptions: """The instance-specific options of the algorithm.""" return self.__instance_algorithm_options
[docs] def to_dict( self, skip_instance_algorithm_options: bool = False ) -> dict[str, str | dict[str, Any]]: """Return the algorithm configuration as a dictionary. Args: skip_instance_algorithm_options: Whether to skip the algorithm options specific to problem instances. Returns: The algorithm configuration as a dictionary. """ dictionary = { self.__CONFIGURATION_NAME: self.__configuration_name, self.__ALGORITHM_NAME: self.__algorithm_name, self.__ALGORITHM_OPTIONS: self.__algorithm_options, } if not skip_instance_algorithm_options: dictionary[self.__INSTANCE_ALGORITHM_OPTIONS] = ( self.__instance_algorithm_options ) return dictionary
[docs] @classmethod def from_dict( cls, algorithm_configuration: dict[str, str | dict[str, Any]] ) -> AlgorithmConfiguration: """Load an algorithm configuration from a dictionary. Args: algorithm_configuration: The algorithm configuration. Returns: The algorithm configuration. """ return AlgorithmConfiguration( algorithm_configuration[cls.__ALGORITHM_NAME], algorithm_configuration[cls.__CONFIGURATION_NAME], algorithm_configuration.get(cls.__INSTANCE_ALGORITHM_OPTIONS, {}), **algorithm_configuration[cls.__ALGORITHM_OPTIONS], )
[docs] def copy(self) -> AlgorithmConfiguration: """Return a copy of the algorithm configuration. Returns: A copy of the algorithm configuration. """ return AlgorithmConfiguration( self.algorithm_name, self.name, self.instance_algorithm_options, **self.algorithm_options, )