|
12 | 12 | import java.util.List; |
13 | 13 | import java.util.Objects; |
14 | 14 |
|
| 15 | +import ai.timefold.solver.core.api.score.HardSoftScore; |
15 | 16 | import ai.timefold.solver.core.api.score.SimpleScore; |
16 | 17 | import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; |
| 18 | +import ai.timefold.solver.core.api.score.stream.Constraint; |
| 19 | +import ai.timefold.solver.core.api.score.stream.ConstraintFactory; |
| 20 | +import ai.timefold.solver.core.api.score.stream.ConstraintProvider; |
17 | 21 | import ai.timefold.solver.core.api.solver.SolutionManager; |
18 | 22 | import ai.timefold.solver.core.config.constructionheuristic.ConstructionHeuristicPhaseConfig; |
19 | 23 | import ai.timefold.solver.core.config.constructionheuristic.ConstructionHeuristicType; |
|
31 | 35 | import ai.timefold.solver.core.config.heuristic.selector.move.generic.list.ListChangeMoveSelectorConfig; |
32 | 36 | import ai.timefold.solver.core.config.heuristic.selector.value.ValueSelectorConfig; |
33 | 37 | import ai.timefold.solver.core.config.heuristic.selector.value.ValueSorterManner; |
| 38 | +import ai.timefold.solver.core.config.solver.SolverConfig; |
| 39 | +import ai.timefold.solver.core.config.solver.termination.TerminationConfig; |
34 | 40 | import ai.timefold.solver.core.testdomain.TestdataEntity; |
35 | 41 | import ai.timefold.solver.core.testdomain.TestdataSolution; |
36 | 42 | import ai.timefold.solver.core.testdomain.TestdataValue; |
|
55 | 61 | import ai.timefold.solver.core.testdomain.list.unassignedvar.TestdataAllowsUnassignedValuesListEntity; |
56 | 62 | import ai.timefold.solver.core.testdomain.list.unassignedvar.TestdataAllowsUnassignedValuesListSolution; |
57 | 63 | import ai.timefold.solver.core.testdomain.list.unassignedvar.TestdataAllowsUnassignedValuesListValue; |
| 64 | +import ai.timefold.solver.core.testdomain.list.unassignedvar.sort.TestdataAllowsUnassignedListSortableEntity; |
| 65 | +import ai.timefold.solver.core.testdomain.list.unassignedvar.sort.TestdataAllowsUnassignedListSortableSolution; |
58 | 66 | import ai.timefold.solver.core.testdomain.list.valuerange.TestdataListEntityProvidingEntity; |
59 | 67 | import ai.timefold.solver.core.testdomain.list.valuerange.TestdataListEntityProvidingScoreCalculator; |
60 | 68 | import ai.timefold.solver.core.testdomain.list.valuerange.TestdataListEntityProvidingSolution; |
|
82 | 90 | import ai.timefold.solver.core.testdomain.unassignedvar.TestdataAllowsUnassignedEasyScoreCalculator; |
83 | 91 | import ai.timefold.solver.core.testdomain.unassignedvar.TestdataAllowsUnassignedEntity; |
84 | 92 | import ai.timefold.solver.core.testdomain.unassignedvar.TestdataAllowsUnassignedSolution; |
| 93 | +import ai.timefold.solver.core.testdomain.unassignedvar.sort.TestdataAllowsUnassignedSortableEntity; |
| 94 | +import ai.timefold.solver.core.testdomain.unassignedvar.sort.TestdataAllowsUnassignedSortableSolution; |
85 | 95 | import ai.timefold.solver.core.testdomain.valuerange.entityproviding.unassignedvar.TestdataAllowsUnassignedEntityProvidingEntity; |
86 | 96 | import ai.timefold.solver.core.testdomain.valuerange.entityproviding.unassignedvar.TestdataAllowsUnassignedEntityProvidingScoreCalculator; |
87 | 97 | import ai.timefold.solver.core.testdomain.valuerange.entityproviding.unassignedvar.TestdataAllowsUnassignedEntityProvidingSolution; |
@@ -1328,6 +1338,32 @@ void solveValueFactorySorting(ConstructionHeuristicTestConfig phaseConfig) { |
1328 | 1338 | } |
1329 | 1339 | } |
1330 | 1340 |
|
| 1341 | + @Test |
| 1342 | + void penalizeBasicVariable() { |
| 1343 | + var solverConfig = new SolverConfig() |
| 1344 | + .withSolutionClass(TestdataAllowsUnassignedSortableSolution.class) |
| 1345 | + .withEntityClasses(TestdataAllowsUnassignedSortableEntity.class) |
| 1346 | + .withConstraintProviderClass(PenalizeAssignedConstraintProvider.class) |
| 1347 | + .withPhases(new ConstructionHeuristicPhaseConfig() |
| 1348 | + .withTerminationConfig(new TerminationConfig().withStepCountLimit(3))); |
| 1349 | + var problem = TestdataAllowsUnassignedSortableSolution.generateSolution(1, 1, false); |
| 1350 | + var solution = PlannerTestUtils.solve(solverConfig, problem); |
| 1351 | + assertThat(solution.getEntityList().getFirst().getValue()).isNull(); |
| 1352 | + } |
| 1353 | + |
| 1354 | + @Test |
| 1355 | + void penalizeListVariable() { |
| 1356 | + var solverConfig = new SolverConfig() |
| 1357 | + .withSolutionClass(TestdataAllowsUnassignedListSortableSolution.class) |
| 1358 | + .withEntityClasses(TestdataAllowsUnassignedListSortableEntity.class) |
| 1359 | + .withConstraintProviderClass(ListPenalizeAssignedConstraintProvider.class) |
| 1360 | + .withPhases(new ConstructionHeuristicPhaseConfig() |
| 1361 | + .withTerminationConfig(new TerminationConfig().withStepCountLimit(3))); |
| 1362 | + var problem = TestdataAllowsUnassignedListSortableSolution.generateSolution(1, 1, false); |
| 1363 | + var solution = PlannerTestUtils.solve(solverConfig, problem); |
| 1364 | + assertThat(solution.getEntityList().getFirst().getValueList()).isEmpty(); |
| 1365 | + } |
| 1366 | + |
1331 | 1367 | @Test |
1332 | 1368 | void failConstructionHeuristicEntityRange() { |
1333 | 1369 | var solverConfig = |
@@ -1496,4 +1532,33 @@ private record ConstructionHeuristicTestConfig(ConstructionHeuristicPhaseConfig |
1496 | 1532 | boolean shuffle) { |
1497 | 1533 |
|
1498 | 1534 | } |
| 1535 | + |
| 1536 | + public static class PenalizeAssignedConstraintProvider implements ConstraintProvider { |
| 1537 | + |
| 1538 | + @Override |
| 1539 | + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { |
| 1540 | + return new Constraint[] { penalizeAssigned(constraintFactory) }; |
| 1541 | + } |
| 1542 | + |
| 1543 | + Constraint penalizeAssigned(ConstraintFactory constraintFactory) { |
| 1544 | + return constraintFactory.forEach(TestdataAllowsUnassignedSortableEntity.class) |
| 1545 | + .penalize(HardSoftScore.ONE_HARD) |
| 1546 | + .asConstraint("penalize assigned"); |
| 1547 | + } |
| 1548 | + } |
| 1549 | + |
| 1550 | + public static class ListPenalizeAssignedConstraintProvider implements ConstraintProvider { |
| 1551 | + |
| 1552 | + @Override |
| 1553 | + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { |
| 1554 | + return new Constraint[] { penalizeAssigned(constraintFactory) }; |
| 1555 | + } |
| 1556 | + |
| 1557 | + Constraint penalizeAssigned(ConstraintFactory constraintFactory) { |
| 1558 | + return constraintFactory.forEach(TestdataAllowsUnassignedListSortableEntity.class) |
| 1559 | + .filter(entity -> !entity.getValueList().isEmpty()) |
| 1560 | + .penalize(HardSoftScore.ONE_HARD) |
| 1561 | + .asConstraint("penalize assigned"); |
| 1562 | + } |
| 1563 | + } |
1499 | 1564 | } |
0 commit comments