Skip to content

Commit

Permalink
Rename acceptance criteria (#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonlan committed Sep 1, 2023
1 parent db88880 commit 04991b6
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 185 deletions.
4 changes: 2 additions & 2 deletions alns/accept/RandomWalk.py → alns/accept/AlwaysAccept.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class RandomWalk:
class AlwaysAccept:
"""
The random walk criterion always accepts the candidate solution.
This criterion always accepts the candidate solution.
"""

def __call__(self, rnd, best, current, candidate):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from typing import Deque, List


class AdaptiveThreshold:
class MovingAverageThreshold:
"""
The Adaptive Threshold (AT) criterion of [1]. This criterion accepts a
candidate solution if it is better than an adaptive threshold value. The
adaptive threshold is computed as:
The Moving Average Threshold (MAT) criterion of [1]. This criterion accepts
a candidate solution if it is better than a threshold value that is based
on the moving average of the objective values of recently observed
candidate solutions. The threshold is computed as:
.. math::
Expand Down
8 changes: 4 additions & 4 deletions alns/accept/WorseAccept.py → alns/accept/RandomAccept.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from alns.accept.update import update


class WorseAccept:
class RandomAccept:
"""
The Worse Accept criterion accepts a candidate solution if it improves over
the current one, or with a given probability :math:`P` regardless of the
cost. :math:`P` is updated in each iteration as:
The Random Accept criterion accepts a candidate solution if it improves
over the current one, or with a given probability :math:`P` regardless of
the cost. :math:`P` is updated in each iteration as:
.. math::
Expand Down
6 changes: 3 additions & 3 deletions alns/accept/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from .AcceptanceCriterion import AcceptanceCriterion
from .AdaptiveThreshold import AdaptiveThreshold
from .AlwaysAccept import AlwaysAccept
from .GreatDeluge import GreatDeluge
from .HillClimbing import HillClimbing
from .LateAcceptanceHillClimbing import LateAcceptanceHillClimbing
from .MovingAverageThreshold import MovingAverageThreshold
from .NonLinearGreatDeluge import NonLinearGreatDeluge
from .RandomWalk import RandomWalk
from .RandomAccept import RandomAccept
from .RecordToRecordTravel import RecordToRecordTravel
from .SimulatedAnnealing import SimulatedAnnealing
from .WorseAccept import WorseAccept
124 changes: 0 additions & 124 deletions alns/accept/tests/test_adaptive_threshold.py

This file was deleted.

124 changes: 124 additions & 0 deletions alns/accept/tests/test_moving_average_threshold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import numpy.random as rnd
from numpy.testing import assert_, assert_equal, assert_raises
from pytest import mark

from alns.accept import MovingAverageThreshold
from alns.tests.states import One, Two, VarObj, Zero


@mark.parametrize(
"eta, gamma",
[
(-1, 3), # eta cannot be < 0
(2, 3), # eta cannot be > 1
(0.5, -2), # gamma cannot be < 0
(0.5, 0), # gamma cannot be 0
],
)
def test_raise_invalid_parameters(eta, gamma):
with assert_raises(ValueError):
MovingAverageThreshold(eta=eta, gamma=gamma)


@mark.parametrize("eta, gamma", [(1, 3), (0.4, 4)])
def test_no_raise_valid_parameters(eta, gamma):
MovingAverageThreshold(eta=eta, gamma=gamma)


@mark.parametrize("eta", [0, 0.01, 0.5, 0.99, 1])
def test_eta(eta):
moving_average = MovingAverageThreshold(eta, 3)
assert_equal(moving_average.eta, eta)


@mark.parametrize("gamma", range(1, 10))
def test_gamma(gamma):
moving_average = MovingAverageThreshold(0.5, gamma)
assert_equal(moving_average.gamma, gamma)


def test_accepts_below_threshold():
moving_average = MovingAverageThreshold(eta=0.5, gamma=4)
moving_average(rnd.RandomState(), One(), One(), One())
moving_average(rnd.RandomState(), One(), One(), Zero())

# The threshold is set at 0 + 0.5 * (0.5 - 0) = 0.25
assert_(moving_average(rnd.RandomState(), One(), One(), Zero()))


def test_rejects_above_threshold():
moving_average = MovingAverageThreshold(eta=0.5, gamma=4)
moving_average(rnd.RandomState(), One(), One(), Two())
moving_average(rnd.RandomState(), One(), One(), Zero())

# The threshold is set at 0 + 0.5 * (1 - 0) = 0.5
assert_(not moving_average(rnd.RandomState(), One(), One(), One()))


def test_accepts_equal_threshold():
moving_average = MovingAverageThreshold(eta=0.5, gamma=4)
moving_average(rnd.RandomState(), One(), One(), VarObj(7100))
moving_average(rnd.RandomState(), One(), One(), VarObj(7200))

# The threshold is set at 7100 + 0.5 * (7140 - 7100) = 7120
assert_(moving_average(rnd.RandomState(), One(), One(), VarObj(7120)))


def test_accepts_over_gamma_candidates():
moving_average = MovingAverageThreshold(eta=0.2, gamma=3)
moving_average(rnd.RandomState(), One(), One(), VarObj(7100))
moving_average(rnd.RandomState(), One(), One(), VarObj(7200))
moving_average(rnd.RandomState(), One(), One(), VarObj(7200))

# The threshold is set at 7000 + 0.2 * (7133.33 - 7000) = 7013.33
assert_(moving_average(rnd.RandomState(), One(), One(), VarObj(7000)))


def test_rejects_over_gamma_candidates():
moving_average = MovingAverageThreshold(eta=0.2, gamma=3)

for value in [7100, 7200, 7200, 7000]:
moving_average(rnd.RandomState(), One(), One(), VarObj(value))

# The threshold is set at 7000 + 0.2 * (7100 - 7000) = 7020
result = moving_average(rnd.RandomState(), One(), One(), VarObj(7100))
assert_(not result)


def test_evaluate_consecutive_solutions():
"""
Test if MAT correctly accepts and rejects consecutive solutions.
"""
moving_average = MovingAverageThreshold(eta=0.5, gamma=4)

# The threshold is set at 7100, hence the solution is accepted.
assert_(moving_average(rnd.RandomState(), One(), One(), VarObj(7100)))

# The threshold is set at 7125, hence the solution is accepted.
result = moving_average(rnd.RandomState(), One(), One(), VarObj(7200))
assert_(not result)

# The threshold is set at 7120, hence the solution is accepted.
assert_(moving_average(rnd.RandomState(), One(), One(), VarObj(7120)))


def test_history():
"""
Test if MAT correctly stores the history of the thresholds correctly.
"""
moving_average = MovingAverageThreshold(eta=0.5, gamma=4)

moving_average(rnd.RandomState(), One(), One(), VarObj(7100))
assert_equal(moving_average.history, [7100])

moving_average(rnd.RandomState(), One(), One(), VarObj(7200))
assert_equal(moving_average.history, [7100, 7200])

moving_average(rnd.RandomState(), One(), One(), VarObj(7120))
assert_equal(moving_average.history, [7100, 7200, 7120])

moving_average(rnd.RandomState(), One(), One(), VarObj(7100))
assert_equal(moving_average.history, [7100, 7200, 7120, 7100])

moving_average(rnd.RandomState(), One(), One(), VarObj(7200))
assert_equal(moving_average.history, [7200, 7120, 7100, 7200])

0 comments on commit 04991b6

Please sign in to comment.