Source code for discrete_optimization.generic_tools.do_mutation

#  Copyright (c) 2022 AIRBUS and its affiliates.
#  This source code is licensed under the MIT license found in the
#  LICENSE file in the root directory of this source tree.

from abc import ABC, abstractmethod
from typing import Any

from discrete_optimization.generic_tools.do_problem import (
    Problem,
    Solution,
)
from discrete_optimization.generic_tools.encoding_register import AttributeType


[docs] class LocalMove:
[docs] @abstractmethod def apply_local_move(self, solution: Solution) -> Solution: ...
[docs] @abstractmethod def backtrack_local_move(self, solution: Solution) -> Solution: ...
[docs] class LocalMoveDefault(LocalMove): """ Not clever local move If you're lazy or don't have the choice, don't do in place modification of the previous solution, so that you can retrieve it directly. So the backward operator is then obvious. """ def __init__(self, prev_solution: Solution, new_solution: Solution): self.prev_solution = prev_solution self.new_solution = new_solution
[docs] def apply_local_move(self, solution: Solution) -> Solution: return self.new_solution
[docs] def backtrack_local_move(self, solution: Solution) -> Solution: return self.prev_solution
[docs] class Mutation(ABC):
[docs] @classmethod def build(cls, problem: Problem, **kwargs: Any) -> "Mutation": return cls(problem=problem, **kwargs)
def __init__(self, problem: Problem, **kwargs: Any): self.problem = problem
[docs] @abstractmethod def mutate(self, solution: Solution) -> tuple[Solution, LocalMove]: ...
[docs] def mutate_and_compute_obj( self, solution: Solution ) -> tuple[Solution, LocalMove, dict[str, float]]: sol, move = self.mutate(solution=solution) res = self.problem.evaluate(sol) return sol, move, res
[docs] class SingleAttributeMutation(Mutation): attribute_type_cls: type[AttributeType] def __init__(self, problem, attribute: str | None = None, **kwargs: Any): super().__init__(problem, **kwargs) register = self.problem.get_attribute_register() if attribute is None: self.attribute = register.get_first_attribute_of_type( self.attribute_type_cls ) else: self.attribute = attribute self.attribute_type = register[self.attribute] def __repr__(self): return f"{type(self).__name__}(attribute='{self.attribute}')"