问题描述
我们正在尝试创建一个简单的示例来测试OptaPlanner的功能。在下文中,我们展示了我们想出的东西。我们的例子的问题在于,当我们选择详尽的搜索算法来解决问题时,OptaPlanner会以错误的答案快速终止,即使零不是ValueRangeProvider提供的可能解决方案,也始终为零。此外,在使用本地搜索时,不会在求解期间设置PlanningVariable。
We are trying to create a simple example to test the capabilities of OptaPlanner. In the following we show what we came up with. The problem with our example is that when we are selecting an exhaustive search algorithm for solving the problem, OptaPlanner terminates quickly with the wrong answer, which is always zero, even if zero is not a possible solution available from the ValueRangeProvider. Furthermore the PlanningVariable is not set during solving, as opposed to when local search is used.
我们尝试更改OptaPlanner附带的示例中的算法(例如TSP)哪个有效。因此我们的问题是:为什么我们的代码不起作用?
We tried to change the algorithms in the examples that come with OptaPlanner (e.g. TSP), which worked. Therefore our question is: Why is our code not working?
MyPlanningEntity.java:
MyPlanningEntity.java:
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
@PlanningEntity
public class MyPlanningEntity {
@PlanningVariable(valueRangeProviderRefs = {"myListValueRangeProvider"})
private int myPlanningVariable;
public int getMyPlanningVariable() {
return myPlanningVariable;
}
public void setMyPlanningVariable(int myPlanningVariable) {
this.myPlanningVariable = myPlanningVariable;
}
}
MySolution.java:
MySolution.java:
import org.optaplanner.core.api.domain.solution.PlanningEntityProperty;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.Solution;
import org.optaplanner.core.api.domain.valuerange.CountableValueRange;
import org.optaplanner.core.api.domain.valuerange.ValueRangeFactory;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.simple.SimpleScore;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@PlanningSolution
public class MySolution implements Solution<SimpleScore> {
@PlanningEntityProperty
private MyPlanningEntity myPlanningEntity;
private SimpleScore score;
public MyPlanningEntity getMyPlanningEntity() {
return myPlanningEntity;
}
public void setMyPlanningEntity(MyPlanningEntity myPlanningEntity) {
this.myPlanningEntity = myPlanningEntity;
}
@ValueRangeProvider(id = "myListValueRangeProvider")
public List<Integer> getListValueRange(){
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
return list;
}
@Override
public SimpleScore getScore() {
return score;
}
@Override
public void setScore(SimpleScore simpleScore) {
this.score = simpleScore;
}
@Override
public Collection<?> getProblemFacts() {
return null;
}
}
MyScoreCalculator.java:
MyScoreCalculator.java:
import org.optaplanner.core.api.score.Score;
import org.optaplanner.core.api.score.buildin.simple.SimpleScore;
import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
public class MyScoreCalculator implements EasyScoreCalculator<MySolution>{
@Override
public Score calculateScore(MySolution mySolution) {
// The higher the input, the higher the output
int value = mySolution.getMyPlanningEntity().getMyPlanningVariable();
return SimpleScore.valueOf(value);
}
}
ESTest.java:
ESTest.java:
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
public class ESTest {
public static void run(){
SolverFactory solverFactory = SolverFactory.createFromXmlResource("resources/myPlanningProblem.xml");
Solver solver = solverFactory.buildSolver();
MySolution mySolution = new MySolution();
MyPlanningEntity myPlanningEntity = new MyPlanningEntity();
mySolution.setMyPlanningEntity(myPlanningEntity);
solver.solve(mySolution);
MySolution bestSolution = (MySolution) solver.getBestSolution();
System.out.println("Best solution: " + bestSolution.getMyPlanningEntity().getMyPlanningVariable());
}
public static void main(String args[]){
run();
}
}
myPlanningProblem.xml:
myPlanningProblem.xml:
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!-- Domain model configuration -->
<scanAnnotatedClasses/>
<scoreDirectorFactory>
<scoreDefinitionType>SIMPLE</scoreDefinitionType>
<easyScoreCalculatorClass>MyScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<!-- THIS DOES NOT WORK STAND ALONE -->
<!--<constructionHeuristic>-->
<!--<constructionHeuristicType>FIRST_FIT</constructionHeuristicType>-->
<!--</constructionHeuristic>-->
<!-- THIS DOES NOT WORK STAND ALONE -->
<exhaustiveSearch>
<exhaustiveSearchType>BRUTE_FORCE</exhaustiveSearchType>
<termination>
<stepCountLimit>100</stepCountLimit>
</termination>
</exhaustiveSearch>
<!-- THIS WORKS BEAUTIFULLY -->
<!--<localSearch>-->
<!--<localSearchType>HILL_CLIMBING</localSearchType>-->
<!--<termination>-->
<!--<secondsSpentLimit>10</secondsSpentLimit>-->
<!--</termination>-->
<!--</localSearch>-->
</solver>
我们正在使用OptaPlanner 6.3 Final。
We are using OptaPlanner 6.3 Final.
这是OptaPlanner启动此配置时得到的结果:
This is what we get when OptaPlanner is started with this configuration:
14:58:58.742 [main] INFO o.o.core.impl.solver.DefaultSolver - Solving started: time spent (4), best score (0), environment mode (REPRODUCIBLE), random (JDK with seed 0).
14:58:58.745 [main] INFO o.o.c.i.e.DefaultExhaustiveSearchPhase - Exhaustive Search phase (0) ended: step total (0), time spent (7), best score (0).
14:58:58.745 [main] INFO o.o.core.impl.solver.DefaultSolver - Solving ended: time spent (7), best score (0), average calculate count per second (285), environment mode (REPRODUCIBLE).
Best solution: 0
Process finished with exit code 0
推荐答案
计划变量应该是 Integer
,而不是 int
。它应该以 null
开头。 如果它以 0
开头,则OptaPlanner假设它已经初始化,并且 - 默认情况下 - 不会在CH或ES中重新初始化该变量。
A planning variable should be an Integer
, not an int
. It should start out as null
. If it starts out as 0
, OptaPlanner presumes it's already initialized and - by default - does not reinitialize that variable in CH or ES.
这篇关于OptaPlanner中的穷举搜索不适用于非常简单的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!