Source code for discrete_optimization.generic_tools.mutations.mutation_bool

#  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 collections.abc import Iterable
from typing import Any, Optional

import numpy as np

from discrete_optimization.generic_tools.do_mutation import LocalMove, Mutation
from discrete_optimization.generic_tools.do_problem import (
    Problem,
    Solution,
    TypeAttribute,
)
from discrete_optimization.generic_tools.mutations.mutation_util import (
    get_attribute_for_type,
)


[docs] class BitFlipMove(LocalMove): def __init__(self, attribute: str, list_index_flip: Iterable[int]): self.attribute = attribute self.list_index_flip = list_index_flip
[docs] def apply_local_move(self, solution: Solution) -> Solution: l = getattr(solution, self.attribute) for index in self.list_index_flip: l[index] = 1 - l[index] return solution
[docs] def backtrack_local_move(self, solution: Solution) -> Solution: return self.apply_local_move(solution)
[docs] class MutationBitFlip(Mutation):
[docs] @staticmethod def build(problem: Problem, solution: Solution, **kwargs: Any) -> "MutationBitFlip": return MutationBitFlip(problem, **kwargs)
def __init__( self, problem: Problem, attribute: Optional[str] = None, probability_flip: float = 0.1, ): self.problem = problem self.probability_flip = probability_flip register = problem.get_attribute_register() if attribute is None: self.attribute = get_attribute_for_type( register, TypeAttribute.LIST_BOOLEAN ) else: self.attribute = attribute self.length = register.dict_attribute_to_type[self.attribute]["n"]
[docs] def mutate(self, solution: Solution) -> tuple[Solution, LocalMove]: indexes = np.where(np.random.random(self.length) <= self.probability_flip) move = BitFlipMove(self.attribute, indexes[0]) return move.apply_local_move(solution), move
[docs] def mutate_and_compute_obj( self, solution: Solution ) -> tuple[Solution, LocalMove, dict[str, float]]: s, move = self.mutate(solution) f = self.problem.evaluate(s) return s, move, f