刚开始使用 Optaplanner 7.36.0。一个简单的项目开始。在我的解决方案类中有 1 个 @PlanningEntity 集合。每个@PlanningEntity 实例都有 2 个 @PlanningVariable 实例成员,两者都通过 valueRangeProviderRefs= 指定我的解决方案类中的 2 个 List
使用 optaplanner-examples 中的 Conferencescheduling 来指导我,但我显然遗漏了一些细节,对我来说不明显的是哪个可能负责未分配的 PlanningVariables。我没有在我的 @PlanningVariable 注释使用中使用 nullable = true 设置。但是其他原因会导致类似的行为吗?
我移交给solver.solve() 方法的解决方案实例如上所述具有未初始化的PlanningVariables,以及我的@PlanningSolution 类中的未初始化@PlanningScore 属性。我也没有在我的解决方案类中提供/覆盖 cloneSolution 方法,因为我没有任何从 PlanningEntity 实例返回到解决方案的引用。根据我的理解,将 PlanningVariables 统一化是预期状态,也许我遗漏/混淆了重要方面?
这是我正在使用的solverConfig.xml:
<?xml version="1.0" encoding="UTF-8"?>
<solver xmlns="https://www.optaplanner.org/xsd/solver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.optaplanner.org/xsd/solver https://www.optaplanner.org/xsd/solver/solver.xsd">
<environmentMode>FULL_ASSERT</environmentMode><!-- To slowly prove there are no bugs in this code -->
<!-- Domain model configuration -->
<solutionClass>org.shespelt.uslnj.domain.Season</solutionClass>
<entityClass>org.shespelt.uslnj.domain.Fixture</entityClass>
<!-- Score configuration -->
<scoreDirectorFactory>
<easyScoreCalculatorClass>org.shespelt.uslnj.score.SeasonEasyScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<secondsSpentLimit>300</secondsSpentLimit>
</termination>
<!-- Tabu Search performs much better than Late Acceptance (default algo) on this use case -->
<constructionHeuristic/>
<exhaustiveSearch>
<exhaustiveSearchType>BRUTE_FORCE</exhaustiveSearchType>
</exhaustiveSearch>
</solver>
@PlanningEntity 类
package org.shespelt.uslnj.domain;
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
/**
* see section 18.4.1 regarding making a PlanningEntity immovable (ie. a match must be defined by the current
* home & away teams for the given PlanningEntity (Fixture.class). Might be useful? along with the PlanningPin
*/
@PlanningEntity
public class Fixture extends AbstractPersistable {
private Integer matchDay = null;
@PlanningVariable( valueRangeProviderRefs = {"homeTeamRange"})
private Team homeTeam=null;
@PlanningVariable( valueRangeProviderRefs = {"awayTeamRange"})
private Team awayTeam=null;
public Fixture( long id, int matchDay, Team homeTeam, Team awayTeam ) {
super.setId(id);
this.matchDay = matchDay;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
System.out.println("Fixture() -> just created via non-empty CTOR. ID: " + this.getId().toString());
}
// the no-arg Ctor only needed by Optaplanner framework - when cloning so it ought to handle, through
// reflection, the setting of all of the properties.
public Fixture() {
super();
System.out.println("Fixture() - no-arg CTOR invoked. ID: " +
( this.getId() != null ? this.getId().toString():"NULL") );
}
//@PlanningVariable( valueRangeProviderRefs = { "matchDayRange"})
public Integer getMatchDay() {
return matchDay;
}
public void setMatchDay(Integer theMatchDay) {
this.matchDay = theMatchDay;
}
public Team getHomeTeam() {
return homeTeam;
}
public void setHomeTeam(Team homeTeam) {
this.homeTeam = homeTeam;
}
public Team getAwayTeam() {
return awayTeam;
}
public void setAwayTeam(Team awayTeam) {
this.awayTeam = awayTeam;
}
@Override
public String toString() {
return "Fixture: " + this.getId() + ", matchDay: " + this.getMatchDay() +
", homeTeam: " + this.getHomeTeam() + ", awayTeam: " + this.getAwayTeam();
}
}
这是我的 main() - 简单的开始...
// build the solver
SolverFactory<Season> solverFactory = SolverFactory.createFromXmlResource(
"org/shespelt/uslnj/seasonSolverConfig.xml");
Solver<Season> solver = solverFactory.buildSolver();
// instantiate the uninitialized Season - with our Fixtures, Teams, Divisions,
Season unsolvedSeason = loadData();
// solve it
Season scheduledSeason = solver.solve( unsolvedSeason );
scheduledSeason.showSchedule();
更新观察:最终解决方案的得分很差(硬:-2000,软:-409,600),但这比最差的(硬:-214749364,软:-214748364)要好 并且我收到了许多 caculateScore() 调用返回这种更糟糕的情况(所有 Fixture PlanningEntity 的 PlanningVariables 都未设置(特定团队实例)。总共计算了 337 个分数,其中 261 个是最坏的情况 - 两个 PlanningVariables 的调用calculateScore() 时未设置PlanningEntity。
最好的情况仍然很糟糕,因为只有 1 支球队被设置为主队,也被设置为客队 - 本赛季所有赛程的配对都是相同的。因此,-2000 分数 - 逻辑返回 -1000 难于计算 Score() 情况,其中 2 个团队是相同的。
如果我认为我必须实现某种 MoveSelector ,我会不会走在“正确”的轨道上?因为我相当“担心”每个解决方案只考虑来自 homeTeamList 和 awayTeamList List 实例的每个团队的 1 个团队。因为我看到 1 个团队被用于两个声明的 PlanningEntity 集合的所有 Fixture 实例(所有 PlanningEntity 实例)。每个 PlanningVariable 都有一个提供的 valueRangeProviderRefs,它是我的 PlanningSolution 中的一个不同列表。够了吗?它只运行 1 秒。
也许我的问题是我没有正确建模我的域。与示例旅行锦标赛的建模方式进行比较,但两者必须不同。在我的领域中,整套装置的日期已设置(计划事实),但我需要解决的是什么装置匹配满足所有约束 - 硬和软 - 在“最佳”案例解决方案中,对于所有'Season' 中的灯具(由 PlanningEntity(灯具类实例)列表组成的规划解决方案)。 谢谢,