1515public class LateAcceptanceAcceptor <Solution_ > extends RestartableAcceptor <Solution_ > {
1616
1717 protected static final double MIN_DIVERSITY_RATIO = 0.05 ;
18- // The goal is to increase from hundreds to thousands in the first restart event and then increment it linearly
19- protected static final int SCALING_FACTOR = 10 ;
18+ protected static final int SCALE_FACTOR = 3 ;
19+ private static final int MAX_REJECTED_EVENTS = 3 ;
2020
2121 protected int lateAcceptanceSize = -1 ;
2222 protected boolean hillClimbingEnabled = true ;
2323
2424 protected Score <?>[] previousScores ;
2525 protected int lateScoreIndex = -1 ;
2626
27- private int maxBestScoreSize ;
2827 private Score <?> bestStepScore ;
2928 private Score <?> currentBestScore ;
3029 // Keep track of the best scores accumulated so far. This list will be used to reseed the later elements list.
3130 protected Deque <Score <?>> bestScoreQueue ;
32- private int defaultLateAcceptanceSize ;
31+ protected int defaultLateAcceptanceSize ;
32+ protected int maxBestScoreSize ;
3333 protected int coefficient ;
34- private int countRestartWithoutImprovement ;
34+ private boolean allowDecrease ;
35+ private int countRejected ;
3536
36- public LateAcceptanceAcceptor (StuckCriterion <Solution_ > stuckCriterionDetection ) {
37- super (stuckCriterionDetection );
37+ public LateAcceptanceAcceptor (boolean enableRestart , StuckCriterion <Solution_ > stuckCriterionDetection ) {
38+ super (enableRestart , stuckCriterionDetection );
3839 }
3940
4041 public void setLateAcceptanceSize (int lateAcceptanceSize ) {
@@ -64,13 +65,13 @@ public void phaseStarted(LocalSearchPhaseScope<Solution_> phaseScope) {
6465 var initialScore = phaseScope .getBestScore ();
6566 Arrays .fill (previousScores , initialScore );
6667 lateScoreIndex = 0 ;
67- coefficient = 0 ;
68- countRestartWithoutImprovement = 0 ;
69- defaultLateAcceptanceSize = lateAcceptanceSize ;
70- // The maximum size is three times the size of the initial element list
71- maxBestScoreSize = defaultLateAcceptanceSize * 3 * SCALING_FACTOR ;
68+ coefficient = 1 ;
69+ allowDecrease = false ;
70+ countRejected = 0 ;
71+ maxBestScoreSize = lateAcceptanceSize * 3 ;
7272 bestScoreQueue = new ArrayDeque <>(maxBestScoreSize );
7373 bestScoreQueue .addLast (initialScore );
74+ defaultLateAcceptanceSize = lateAcceptanceSize ;
7475 }
7576
7677 private void validate () {
@@ -106,14 +107,14 @@ public void stepEnded(LocalSearchStepScope<Solution_> stepScope) {
106107 previousScores [lateScoreIndex ] = stepScope .getScore ();
107108 lateScoreIndex = (lateScoreIndex + 1 ) % lateAcceptanceSize ;
108109 if (((Score ) currentBestScore ).compareTo (stepScope .getScore ()) < 0 ) {
109- if (countRestartWithoutImprovement > 0 && coefficient > 0 ) {
110+ if (allowDecrease ) {
110111 // We decrease the coefficient
111112 // if there is an improvement
112113 // to avoid altering the late element size in the next restart event.
113114 // This action is performed only once after a restart event
114- coefficient --;
115+ coefficient /= SCALE_FACTOR ;
116+ allowDecrease = false ;
115117 }
116- countRestartWithoutImprovement = 0 ;
117118 if (bestScoreQueue .size () < maxBestScoreSize ) {
118119 bestScoreQueue .addLast (stepScope .getScore ());
119120 } else {
@@ -137,18 +138,26 @@ public boolean rejectRestartEvent() {
137138 // and the proposed approach requires some diversity to reseed the scores.
138139 var reject = diversity > MIN_DIVERSITY_RATIO || bestScoreQueue .size () == 1 ;
139140 if (reject ) {
141+ countRejected ++;
142+ if (countRejected > MAX_REJECTED_EVENTS && bestScoreQueue .size () > 1 ) {
143+ logger .info (
144+ "Restart event not rejected. Diversity ({}), Count best scores ({}), Distinct Elements ({}), Rejection Count ({})" ,
145+ diversity , bestScoreQueue .size (), distinctElements , countRejected );
146+ return false ;
147+ }
140148 logger .info (
141- "Restart event delayed. Diversity ({}), Count best scores ({}), Distinct Elements ({}), Restart without Improvement ({})" ,
142- diversity , bestScoreQueue .size (), distinctElements , countRestartWithoutImprovement );
149+ "Restart event delayed. Diversity ({}), Count best scores ({}), Distinct Elements ({}), Rejection Count ({})" ,
150+ diversity , bestScoreQueue .size (), distinctElements , countRejected );
143151 }
144152 return reject ;
145153 }
146154
147155 @ Override
148156 public void restart (LocalSearchStepScope <Solution_ > stepScope ) {
149- countRestartWithoutImprovement ++;
150- coefficient ++;
151- var newLateAcceptanceSize = defaultLateAcceptanceSize * coefficient * SCALING_FACTOR ;
157+ coefficient *= SCALE_FACTOR ;
158+ allowDecrease = true ;
159+ countRejected = 0 ;
160+ var newLateAcceptanceSize = defaultLateAcceptanceSize * coefficient ;
152161 if (logger .isInfoEnabled ()) {
153162 if (lateAcceptanceSize == newLateAcceptanceSize ) {
154163 logger .info ("Keeping the lateAcceptanceSize as {}." , lateAcceptanceSize );
@@ -171,15 +180,15 @@ public void restart(LocalSearchStepScope<Solution_> stepScope) {
171180 */
172181 private void rebuildLateElementsList (int newLateAcceptanceSize ) {
173182 var newPreviousScores = new Score [newLateAcceptanceSize ];
174- var countPerScore = newLateAcceptanceSize / bestScoreQueue .size () + 1 ;
175- var count = new MutableInt (newLateAcceptanceSize - 1 );
176- var iterator = bestScoreQueue .descendingIterator ();
177- while (count .intValue () >= 0 && iterator .hasNext ()) {
183+ var countPerScore = Math . min ( newLateAcceptanceSize / 2 , ( newLateAcceptanceSize / bestScoreQueue .size ()) * 2 ) ;
184+ var count = new MutableInt (0 );
185+ var iterator = bestScoreQueue .iterator ();
186+ while (count .intValue () < newLateAcceptanceSize && iterator .hasNext ()) {
178187 var score = iterator .next ();
179188 for (var i = 0 ; i < countPerScore ; i ++) {
180189 newPreviousScores [count .intValue ()] = score ;
181- count .decrement ();
182- if (count .intValue () < 0 ) {
190+ count .increment ();
191+ if (count .intValue () == newLateAcceptanceSize ) {
183192 break ;
184193 }
185194 }
0 commit comments