Skip to content

Commit 99f72c2

Browse files
committed
chore: address comments
1 parent 4a1b322 commit 99f72c2

File tree

12 files changed

+52
-363
lines changed

12 files changed

+52
-363
lines changed

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/LocalSearchDecider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import ai.timefold.solver.core.impl.heuristic.selector.move.MoveSelector;
77
import ai.timefold.solver.core.impl.localsearch.decider.acceptor.Acceptor;
88
import ai.timefold.solver.core.impl.localsearch.decider.forager.LocalSearchForager;
9-
import ai.timefold.solver.core.impl.localsearch.decider.reconfiguration.AdaptedSolverScope;
109
import ai.timefold.solver.core.impl.localsearch.decider.reconfiguration.RestartStrategy;
1110
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchMoveScope;
1211
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchPhaseScope;
@@ -78,13 +77,14 @@ public void setAssertExpectedUndoMoveScore(boolean assertExpectedUndoMoveScore)
7877
// ************************************************************************
7978

8079
public void solvingStarted(SolverScope<Solution_> solverScope) {
81-
restartStrategy.solvingStarted(new AdaptedSolverScope<>(solverScope, this));
80+
restartStrategy.solvingStarted(solverScope);
8281
moveSelector.solvingStarted(solverScope);
8382
acceptor.solvingStarted(solverScope);
8483
forager.solvingStarted(solverScope);
8584
}
8685

8786
public void phaseStarted(LocalSearchPhaseScope<Solution_> phaseScope) {
87+
phaseScope.setDecider(this);
8888
restartStrategy.phaseStarted(phaseScope);
8989
moveSelector.phaseStarted(phaseScope);
9090
acceptor.phaseStarted(phaseScope);

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/acceptor/RestartableAcceptor.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,52 @@
1212
*/
1313
public abstract class RestartableAcceptor<Solution_> extends AbstractAcceptor<Solution_> {
1414

15-
private final StuckCriterion<Solution_> stuckCriterionDetection;
15+
private final StuckCriterion<Solution_> stuckCriterion;
1616
protected boolean restartTriggered;
1717

18-
protected RestartableAcceptor(StuckCriterion<Solution_> stuckCriterionDetection) {
19-
this.stuckCriterionDetection = stuckCriterionDetection;
18+
protected RestartableAcceptor(StuckCriterion<Solution_> stuckCriterion) {
19+
this.stuckCriterion = stuckCriterion;
2020
}
2121

2222
@Override
2323
public void solvingStarted(SolverScope<Solution_> solverScope) {
2424
super.solvingStarted(solverScope);
25-
stuckCriterionDetection.solvingStarted(solverScope);
25+
stuckCriterion.solvingStarted(solverScope);
2626
}
2727

2828
@Override
2929
public void phaseStarted(LocalSearchPhaseScope<Solution_> phaseScope) {
3030
super.phaseStarted(phaseScope);
31-
stuckCriterionDetection.phaseStarted(phaseScope);
31+
stuckCriterion.phaseStarted(phaseScope);
3232
}
3333

3434
@Override
3535
public void phaseEnded(LocalSearchPhaseScope<Solution_> phaseScope) {
3636
super.phaseEnded(phaseScope);
37-
stuckCriterionDetection.phaseEnded(phaseScope);
37+
stuckCriterion.phaseEnded(phaseScope);
3838
}
3939

4040
@Override
4141
public void stepStarted(LocalSearchStepScope<Solution_> stepScope) {
4242
super.stepStarted(stepScope);
43-
stuckCriterionDetection.stepStarted(stepScope);
43+
stuckCriterion.stepStarted(stepScope);
4444
}
4545

4646
@Override
4747
public void stepEnded(LocalSearchStepScope<Solution_> stepScope) {
4848
super.stepEnded(stepScope);
49-
stuckCriterionDetection.stepEnded(stepScope);
49+
stuckCriterion.stepEnded(stepScope);
5050
}
5151

5252
@Override
5353
public boolean isAccepted(LocalSearchMoveScope<Solution_> moveScope) {
54-
if (stuckCriterionDetection.isSolverStuck(moveScope)) {
55-
moveScope.getStepScope().getPhaseScope().triggerSolverStuck();
54+
if (stuckCriterion.isSolverStuck(moveScope)) {
55+
moveScope.getStepScope().getPhaseScope().setSolverStuck(true);
5656
restartTriggered = true;
5757
return true;
5858
}
59-
return applyAcceptanceCriteria(moveScope);
59+
return accept(moveScope);
6060
}
6161

62-
protected abstract boolean applyAcceptanceCriteria(LocalSearchMoveScope<Solution_> moveScope);
62+
protected abstract boolean accept(LocalSearchMoveScope<Solution_> moveScope);
6363
}

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/acceptor/lateacceptance/DiversifiedLateAcceptanceAcceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private void validate() {
5353

5454
@Override
5555
@SuppressWarnings({ "rawtypes", "unchecked" })
56-
protected boolean applyAcceptanceCriteria(LocalSearchMoveScope<Solution_> moveScope) {
56+
protected boolean accept(LocalSearchMoveScope<Solution_> moveScope) {
5757
// The acceptance and replacement strategies are based on the work:
5858
// Diversified Late Acceptance Search by M. Namazi, C. Sanderson, M. A. H. Newton, M. M. A. Polash, and A. Sattar
5959
var moveScore = moveScope.getScore();

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/acceptor/lateacceptance/LateAcceptanceAcceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private void validate() {
5252

5353
@Override
5454
@SuppressWarnings("unchecked")
55-
public boolean applyAcceptanceCriteria(LocalSearchMoveScope<Solution_> moveScope) {
55+
public boolean accept(LocalSearchMoveScope<Solution_> moveScope) {
5656
var moveScore = moveScope.getScore();
5757
var lateScore = previousScores[lateScoreIndex];
5858
if (moveScore.compareTo(lateScore) >= 0) {

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/acceptor/restart/AbstractGeometricStuckCriterion.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ai.timefold.solver.core.impl.localsearch.decider.acceptor.restart;
22

33
import java.time.Clock;
4+
import java.time.Instant;
45

56
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchMoveScope;
67
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchPhaseScope;
@@ -21,12 +22,12 @@
2122
public abstract class AbstractGeometricStuckCriterion<Solution_> implements StuckCriterion<Solution_> {
2223
protected static final Logger logger = LoggerFactory.getLogger(AbstractGeometricStuckCriterion.class);
2324
private static final double GEOMETRIC_FACTOR = 1.4; // Value extracted from the cited paper
24-
private static final long GRACE_PERIOD_MILLIS = 30_000; // Same value as DiminishedReturnsTermination
25+
private static final long GRACE_PERIOD_MILLIS = 30_000; // 30s by default
2526

2627
private final double scalingFactor;
2728
private final Clock clock;
2829
private boolean gracePeriodFinished;
29-
private long gracePeriodMillis;
30+
private Instant gracePeriodEnd;
3031
protected long nextRestart;
3132
private double currentGeometricGrowFactor;
3233

@@ -37,9 +38,9 @@ protected AbstractGeometricStuckCriterion(Clock clock, double scalingFactor) {
3738

3839
@Override
3940
public void phaseStarted(LocalSearchPhaseScope<Solution_> phaseScope) {
40-
if (gracePeriodMillis == 0) {
41+
if (gracePeriodEnd == null) {
4142
// 30 seconds of grace period
42-
gracePeriodMillis = clock.instant().toEpochMilli() + GRACE_PERIOD_MILLIS;
43+
gracePeriodEnd = clock.instant().plusMillis(GRACE_PERIOD_MILLIS);
4344
}
4445
}
4546

@@ -51,7 +52,7 @@ public void phaseEnded(LocalSearchPhaseScope<Solution_> phaseScope) {
5152
@Override
5253
public void solvingStarted(SolverScope<Solution_> solverScope) {
5354
currentGeometricGrowFactor = 1;
54-
gracePeriodMillis = 0;
55+
gracePeriodEnd = null;
5556
gracePeriodFinished = false;
5657
nextRestart = calculateNextRestart();
5758
}
@@ -83,7 +84,7 @@ protected boolean isGracePeriodFinished() {
8384
if (gracePeriodFinished) {
8485
return true;
8586
}
86-
gracePeriodFinished = clock.instant().toEpochMilli() >= gracePeriodMillis;
87+
gracePeriodFinished = clock.millis() >= gracePeriodEnd.toEpochMilli();
8788
return gracePeriodFinished;
8889
}
8990

core/src/main/java/ai/timefold/solver/core/impl/localsearch/decider/acceptor/restart/StuckCriterion.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
package ai.timefold.solver.core.impl.localsearch.decider.acceptor.restart;
22

3+
import ai.timefold.solver.core.api.solver.Solver;
34
import ai.timefold.solver.core.impl.localsearch.event.LocalSearchPhaseLifecycleListener;
45
import ai.timefold.solver.core.impl.localsearch.scope.LocalSearchMoveScope;
56

67
/**
7-
* Base contract
8-
* for defining strategies that identify when the {@link ai.timefold.solver.core.api.solver.Solver solver} is stuck.
8+
* Allow defining strategies that identify when the {@link Solver solver} is stuck.
99
*
10-
* @param <Solution_>
10+
* @param <Solution_> the solution type
1111
*/
1212
public interface StuckCriterion<Solution_> extends LocalSearchPhaseLifecycleListener<Solution_> {
1313

1414
/**
15-
* Main logic that applies a specific metric to determine if a solver is stuck and cannot find better solutions
16-
* in the current solving flow.
15+
* Main logic that applies a specific metric to determine if a solver is stuck in a local optimum.
1716
*
1817
* @param moveScope cannot be null
1918
* @return

0 commit comments

Comments
 (0)