/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.optaplanner.core.impl.solver.recaller; import org.junit.Test; import org.optaplanner.core.api.score.Score; import org.optaplanner.core.api.score.buildin.simple.SimpleScore; import org.optaplanner.core.impl.constructionheuristic.scope.ConstructionHeuristicPhaseScope; import org.optaplanner.core.impl.constructionheuristic.scope.ConstructionHeuristicStepScope; import org.optaplanner.core.impl.domain.solution.AbstractSolution; import org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor; import org.optaplanner.core.impl.score.director.InnerScoreDirector; import org.optaplanner.core.impl.solver.event.SolverEventSupport; import org.optaplanner.core.impl.solver.scope.DefaultSolverScope; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class BestSolutionRecallerTest { private static <Solution_> DefaultSolverScope<Solution_> createSolverScope() { DefaultSolverScope<Solution_> solverScope = new DefaultSolverScope<>(); InnerScoreDirector<Solution_> scoreDirector = mock(InnerScoreDirector.class); SolutionDescriptor<Solution_> solutionDescriptor = mock(SolutionDescriptor.class); when(scoreDirector.getSolutionDescriptor()).thenReturn(solutionDescriptor); solverScope.setScoreDirector(scoreDirector); return solverScope; } private static <Solution_> ConstructionHeuristicStepScope<Solution_> setupConstrunctionHeuristics( DefaultSolverScope<Solution_> solverScope) { ConstructionHeuristicPhaseScope<Solution_> phaseScope = mock(ConstructionHeuristicPhaseScope.class); when(phaseScope.getSolverScope()).thenReturn(solverScope); ConstructionHeuristicStepScope<Solution_> stepScope = mock(ConstructionHeuristicStepScope.class); when(stepScope.getPhaseScope()).thenReturn(phaseScope); return stepScope; } private static <Solution_> BestSolutionRecaller<Solution_> createBestSolutionRecaller() { BestSolutionRecaller<Solution_> recaller = new BestSolutionRecaller<>(); recaller.setSolverEventSupport(mock(SolverEventSupport.class)); return recaller; } @Test public void unimprovedUninitializedProcessWorkingSolutionDuringStep() { SimpleScore originalBestScore = SimpleScore.valueOfUninitialized(-1, -300); SimpleScore stepScore = SimpleScore.valueOfUninitialized(-2, 0); doProcessWorkingSolutionDuringStep(originalBestScore, stepScore, false); } @Test public void unimprovedInitializedProcessWorkingSolutionDuringStep() { Score originalBestScore = SimpleScore.valueOf(0); Score stepScore = SimpleScore.valueOf(-1); doProcessWorkingSolutionDuringStep(originalBestScore, stepScore, false); } @Test public void improvedUninitializedProcessWorkingSolutionDuringStep() { Score originalBestScore = SimpleScore.valueOfUninitialized(-2, 0); Score stepScore = SimpleScore.valueOfUninitialized(-1, 0); doProcessWorkingSolutionDuringStep(originalBestScore, stepScore, true); } @Test public void improvedInitializedProcessWorkingSolutionDuringStep() { Score originalBestScore = SimpleScore.valueOf(-1); Score stepScore = SimpleScore.valueOf(0); doProcessWorkingSolutionDuringStep(originalBestScore, stepScore, true); } protected void doProcessWorkingSolutionDuringStep(Score originalBestScore, Score stepScore, boolean stepImprovesBestSolution) { DefaultSolverScope<AbstractSolution> solverScope = createSolverScope(); AbstractSolution originalBestSolution = mock(AbstractSolution.class); when(solverScope.getScoreDirector().getSolutionDescriptor().getScore(originalBestSolution)).thenReturn(originalBestScore); solverScope.setBestSolution(originalBestSolution); solverScope.setBestScore(originalBestScore); ConstructionHeuristicStepScope<AbstractSolution> stepScope = setupConstrunctionHeuristics(solverScope); AbstractSolution stepSolution = mock(AbstractSolution.class); when(solverScope.getScoreDirector().getSolutionDescriptor().getScore(stepSolution)).thenReturn(stepScore); when(stepScope.getScore()).thenReturn(stepScore); when(stepScope.createOrGetClonedSolution()).thenReturn(stepSolution); BestSolutionRecaller<AbstractSolution> recaller = createBestSolutionRecaller(); recaller.processWorkingSolutionDuringStep(stepScope); if (stepImprovesBestSolution) { assertEquals(stepSolution, solverScope.getBestSolution()); assertEquals(stepScore, solverScope.getBestScore()); } else { assertEquals(originalBestSolution, solverScope.getBestSolution()); assertEquals(originalBestScore, solverScope.getBestScore()); } } @Test public void unimprovedUninitializedProcessWorkingSolutionDuringMove() { Score bestScore = SimpleScore.valueOf(-10); Score moveScore = SimpleScore.valueOfUninitialized(-1, -1); doProcessWorkingSolutionDuringMove(bestScore, moveScore, false); } @Test public void unimprovedInitializedProcessWorkingSolutionDuringMove() { Score bestScore = SimpleScore.valueOf(0); Score moveScore = SimpleScore.valueOf(-1); doProcessWorkingSolutionDuringMove(bestScore, moveScore, false); } @Test public void improvedUninitializedProcessWorkingSolutionDuringMove() { Score bestScore = SimpleScore.valueOfUninitialized(-1, 0); SimpleScore moveScore = SimpleScore.valueOf(-2); doProcessWorkingSolutionDuringMove(bestScore, moveScore, true); } @Test public void improvedInitializedProcessWorkingSolutionDuringMove() { Score bestScore = SimpleScore.valueOf(-2); Score moveScore = SimpleScore.valueOf(-1); doProcessWorkingSolutionDuringMove(bestScore, moveScore, true); } protected void doProcessWorkingSolutionDuringMove(Score originalBestScore, Score moveScore, boolean moveImprovesBestSolution) { DefaultSolverScope<AbstractSolution> solverScope = createSolverScope(); AbstractSolution originalBestSolution = mock(AbstractSolution.class); when(solverScope.getScoreDirector().getSolutionDescriptor().getScore(originalBestSolution)).thenReturn(originalBestScore); solverScope.setBestSolution(originalBestSolution); solverScope.setBestScore(originalBestScore); ConstructionHeuristicStepScope<AbstractSolution> stepScope = setupConstrunctionHeuristics(solverScope); AbstractSolution moveSolution = mock(AbstractSolution.class); when(solverScope.getScoreDirector().getSolutionDescriptor().getScore(moveSolution)) .thenReturn(moveScore); when(solverScope.getScoreDirector().cloneWorkingSolution()).thenReturn(moveSolution); BestSolutionRecaller<AbstractSolution> recaller = createBestSolutionRecaller(); recaller.processWorkingSolutionDuringMove(moveScore, stepScope); if (moveImprovesBestSolution) { assertEquals(moveSolution, solverScope.getBestSolution()); assertEquals(moveScore, solverScope.getBestScore()); } else { assertEquals(originalBestSolution, solverScope.getBestSolution()); assertEquals(originalBestScore, solverScope.getBestScore()); } } }