/*
* Copyright 2014 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.heuristic.move;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.optaplanner.core.impl.domain.variable.descriptor.GenuineVariableDescriptor;
import org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove;
import org.optaplanner.core.impl.heuristic.selector.move.generic.SwapMove;
import org.optaplanner.core.impl.score.director.InnerScoreDirector;
import org.optaplanner.core.impl.score.director.ScoreDirector;
import org.optaplanner.core.impl.testdata.domain.TestdataEntity;
import org.optaplanner.core.impl.testdata.domain.TestdataSolution;
import org.optaplanner.core.impl.testdata.domain.TestdataValue;
import org.optaplanner.core.impl.testdata.util.PlannerTestUtils;
import static org.mockito.Mockito.*;
import static org.optaplanner.core.impl.testdata.util.PlannerAssert.*;
import static org.optaplanner.core.impl.testdata.util.PlannerTestUtils.*;
public class CompositeMoveTest {
@Test
public void createUndoMove() {
InnerScoreDirector<TestdataSolution> scoreDirector = PlannerTestUtils.mockScoreDirector(
TestdataSolution.buildSolutionDescriptor());
DummyMove a = new DummyMove("a");
DummyMove b = new DummyMove("b");
DummyMove c = new DummyMove("c");
CompositeMove<TestdataSolution> move = new CompositeMove<>(a, b, c);
CompositeMove<TestdataSolution> undoMove = move.doMove(scoreDirector);
assertAllCodesOfArray(move.getMoves(), "a", "b", "c");
assertAllCodesOfArray(undoMove.getMoves(), "undo c", "undo b", "undo a");
}
@Test
public void doMove() {
InnerScoreDirector<TestdataSolution> scoreDirector = PlannerTestUtils.mockScoreDirector(
TestdataSolution.buildSolutionDescriptor());
DummyMove a = mock(DummyMove.class);
DummyMove b = mock(DummyMove.class);
DummyMove c = mock(DummyMove.class);
CompositeMove<TestdataSolution> move = new CompositeMove<>(a, b, c);
move.doMove(scoreDirector);
verify(a, times(1)).doMove(scoreDirector);
verify(b, times(1)).doMove(scoreDirector);
verify(c, times(1)).doMove(scoreDirector);
}
@Test
public void buildEmptyMove() {
assertInstanceOf(NoChangeMove.class, CompositeMove.buildMove(new ArrayList<>()));
assertInstanceOf(NoChangeMove.class, CompositeMove.buildMove());
}
@Test
public void buildOneElemMove() {
DummyMove tmpMove = new DummyMove();
Move<TestdataSolution> move = CompositeMove.buildMove(Collections.singletonList(tmpMove));
assertInstanceOf(DummyMove.class, move);
move = CompositeMove.buildMove(tmpMove);
assertInstanceOf(DummyMove.class, move);
}
@Test
public void buildTwoElemMove() {
DummyMove first = new DummyMove();
NoChangeMove<TestdataSolution> second = new NoChangeMove<>();
Move<TestdataSolution> move = CompositeMove.buildMove(Arrays.asList(first, second));
assertInstanceOf(CompositeMove.class, move);
assertInstanceOf(DummyMove.class, ((CompositeMove) move).getMoves()[0]);
assertInstanceOf(NoChangeMove.class, ((CompositeMove) move).getMoves()[1]);
move = CompositeMove.buildMove(first, second);
assertInstanceOf(CompositeMove.class, move);
assertInstanceOf(DummyMove.class, ((CompositeMove) move).getMoves()[0]);
assertInstanceOf(NoChangeMove.class, ((CompositeMove) move).getMoves()[1]);
}
@Test
public void isMoveDoable() {
InnerScoreDirector<TestdataSolution> scoreDirector = PlannerTestUtils.mockScoreDirector(
TestdataSolution.buildSolutionDescriptor());
DummyMove first = new DummyMove();
DummyMove second = mock(DummyMove.class);
when(second.isMoveDoable(scoreDirector)).thenReturn(false);
Move<TestdataSolution> move = CompositeMove.buildMove(first, second);
assertEquals(false, move.isMoveDoable(scoreDirector));
}
@Test
public void equals() {
DummyMove first = new DummyMove();
NoChangeMove<TestdataSolution> second = new NoChangeMove<>();
Move<TestdataSolution> move = CompositeMove.buildMove(Arrays.asList(first, second));
Move<TestdataSolution> other = CompositeMove.buildMove(first, second);
assertTrue(move.equals(other));
move = CompositeMove.buildMove(first, second);
other = CompositeMove.buildMove(second, first);
assertFalse(move.equals(other));
assertFalse(move.equals(new DummyMove()));
assertTrue(move.equals(move));
}
@Test
public void interconnectedChildMoves() {
TestdataSolution solution = new TestdataSolution("s1");
TestdataValue v1 = new TestdataValue("v1");
TestdataValue v2 = new TestdataValue("v2");
TestdataValue v3 = new TestdataValue("v3");
solution.setValueList(Arrays.asList(v1, v2, v3));
TestdataEntity e1 = new TestdataEntity("e1", v1);
TestdataEntity e2 = new TestdataEntity("e2", v2);
solution.setEntityList(Arrays.asList(e1, e2));
GenuineVariableDescriptor<TestdataSolution> variableDescriptor = TestdataEntity.buildVariableDescriptorForValue();
SwapMove<TestdataSolution> first = new SwapMove<>(Collections.singletonList(variableDescriptor), e1, e2);
ChangeMove<TestdataSolution> second = new ChangeMove<>(e1, variableDescriptor, v3);
Move<TestdataSolution> move = CompositeMove.buildMove(first, second);
assertSame(v1, e1.getValue());
assertSame(v2, e2.getValue());
ScoreDirector<TestdataSolution> scoreDirector
= mockScoreDirector(variableDescriptor.getEntityDescriptor().getSolutionDescriptor());
Move<TestdataSolution> undoMove = move.doMove(scoreDirector);
assertSame(v3, e1.getValue());
assertSame(v1, e2.getValue());
undoMove.doMove(scoreDirector);
assertSame(v1, e1.getValue());
assertSame(v2, e2.getValue());
}
}