Source code for moptipy.algorithms.mo.morls
"""
A multi-objective version of the Randomized Local Search algorithm.
The original randomized local search (RLS) always remembers the best-so-far
solution and, in each step, generates a new one by applying the unary search
operator. If the new solution is not worse than the best-so-far one (according
to the single objective function), it becomes the new best-so-far solution.
In this multi-objective version, we accept the new solution if it is not
dominated by the best-so-far solution.
"""
from typing import Callable, Final
from numpy.random import Generator
from moptipy.api.algorithm import Algorithm1
from moptipy.api.mo_algorithm import MOAlgorithm
from moptipy.api.mo_process import MOProcess
from moptipy.api.operators import Op0, Op1
[docs]
class MORLS(Algorithm1, MOAlgorithm):
"""The MO-RLS is a local search accepting all non-worsening moves."""
[docs]
def solve_mo(self, process: MOProcess) -> None:
"""
Apply the MO-RLS to an optimization problem.
:param process: the black-box process object
"""
# Create records for old and new point in the search space.
best_x = process.create() # record for best-so-far solution
best_f = process.f_create() # the objective values
new_x = process.create() # record for new solution
new_f = process.f_create() # the objective values
# Obtain the random number generator.
random: Final[Generator] = process.get_random()
# Put function references in variables to save time.
evaluate: Final[Callable] = process.f_evaluate # the objective
op1: Final[Callable] = self.op1.op1 # the unary operator
should_terminate: Final[Callable] = process.should_terminate
domination: Final[Callable] = process.f_dominates
# Start at a random point in the search space and evaluate it.
self.op0.op0(random, best_x) # Create 1 solution randomly and
evaluate(best_x, best_f) # evaluate it.
while not should_terminate(): # Until we need to quit...
op1(random, new_x, best_x) # new_x = neighbor of best_x
evaluate(new_x, new_f)
if domination(new_f, best_f) <= 0: # new is not worse than best?
best_f, new_f = new_f, best_f # swap objective values.
best_x, new_x = new_x, best_x # swap best and new.
process.check_in(best_x, best_f) # check-in final result
def __init__(self, op0: Op0, op1: Op1) -> None:
"""
Create the randomized local search (rls).
:param op0: the nullary search operator
:param op1: the unary search operator
"""
Algorithm1.__init__(self, "morls", op0, op1)
[docs]
def initialize(self) -> None:
"""Initialize the algorithm."""
Algorithm1.initialize(self)