文档学习列表:
plannerConfiguration https://docs.optaplanner.org/7.45.0.Final/optaplanner-docs/html_single/index.html#plannerConfiguration
01. 快速回顾OptaPlanner的使用步骤
- 问题建模,使用@PlanningSolution和@PlanningEntity来确定输入输出域等
- 配置Slover
- 加载输入数据
- 调用Slover.solve(problem) ,求解返回结果
02. Opta的几个基础概念或者注解
2.1 Problem fact
用于描述问题的最小不可变的子状态的POJO类,如N皇后问题里的行或者列
public class Column implements Serializable {
private int index;
// ... getters
}
public class Row implements Serializable {
private int index;
// ... getters
}
2.2 Planning entity
算法搜索过程中可以计算得出的其中一个状态集合的POJO类,在运算中会一直变化,如N皇后问题中的一个棋子的行+列
@PlanningEntity
public class Queen {
private Column column;
// Planning variables: changes during planning, between score calculations.
private Row row;
// ... getters and setters
}
2.3 Planning entity difficulty 预排序一下候选的状态集,加速(如Bin装箱问题)
应用场景: 如果一些优化算法能够估计出哪些规划实体更难规划,那么它们的工作效率会更高。例如:在箱子里包装更大的物品更难安排,在课程中安排更多学生的讲座更难安排,而在n皇后区,中间皇后区更难安排在棋盘上。
难度应该按升序执行:容易的实体越低,难的实体就越高。例如,箱式包装:小件物品<中型物品<大物品。
虽然大多数算法首先从较难的实体开始,但它们只是颠倒顺序。
实例如下:
@PlanningEntity(difficultyComparatorClass = CloudProcessDifficultyComparator.class)
public class CloudProcess {
// ...
}
在云调度的实例中, getRequiredMultiplicand()获得被需要的调度值(预排序)
public class CloudProcessDifficultyComparator implements Comparator<CloudProcess> {
public int compare(CloudProcess a, CloudProcess b) {
return new CompareToBuilder()
.append(a.getRequiredMultiplicand(), b.getRequiredMultiplicand())
.append(a.getId(), b.getId())
.toComparison();
}
}
2.4 Planning variable annotation
也支持加在方法上作为输入源
@PlanningEntity
public class Queen {
...
private Row row;
@PlanningVariable(valueRangeProviderRefs = {"rowRange"})
public Row getRow() {
return row;
}
2.5 支持Nullable planning variable
@PlanningVariable(..., nullable = true)
public Worker getWorker() {
return worker;
}
2.6 Planning value strength (优势排序)
基本同planning entity difficulty,单比planning entity difficulty声明地要低
不能用Planning value strength或者planning entity difficulty 来实现弱约束,它们在尝试建立不会改变评分函数;如果计算时间足够充沛,则返回的解决方案时会保持一致的
要允许一些启发式算法利用特定于域的信息,可以将strengthComparatorClass设置为@PlanningVariable注释:
@PlanningVariable(..., strengthComparatorClass = CloudComputerStrengthComparator.class)
public CloudComputer getComputer() {
return computer;
}
public class CloudComputerStrengthComparator implements Comparator<CloudComputer> {
public int compare(CloudComputer a, CloudComputer b) {
return new CompareToBuilder()
.append(a.getMultiplicand(), b.getMultiplicand())
.append(b.getCost(), a.getCost()) //逆序 (但这是有争议的)
.append(a.getId(), b.getId())
.toComparison();
}
}
See sorted selection for more information.
2.7 Chained planning variable (TSP, VRP, …)
链式约束的计划变量(旅行商问题、车辆路径优化问题等),这意味着规划实体相互指向并形成一个链。通过将问题建模为一组链(而不是一组树/环),搜索空间大大减少。
一个计划变量,它被链接为:
- 直接指向问题事实(或计划实体),称为锚点(anchor)。
- 指向具有相同计划变量的另一个计划实体,该实体递归地指向锚点。
- 没有组成环或者树结构,当且仅有唯一的锚点连接的一条线
2.8 planning Solution class
一个@PlanningSolution的实体类,包含了所有的可以枚举的结果集(problem facts)、planning entitty(枚举中的一个组合状态)、评分(score);如N皇后问题的示例:
@PlanningSolution
public class NQueens {
// Problem facts 可以使用 @ProblemFactCollectionProperty来替代
private int n;
private List<Column> columnList;
private List<Row> rowList;
// Planning entities
private List<Queen> queenList;
private SimpleScore score;
...
}
2.9 Cached problem fact
提前拿problem fact来组合problem fact,多此一举,直接初始化成新的problem fact就完了
2.10 Auto discover solution properties
省去几个注解,自动检测属性
不建议
2.11 Cloning a solution (复制保存多个解决方案)
TODO
深拷贝,我尝试使用简单的方式来实现,结果都会莫名其妙地导致运行异常了~
原文地址: https://docs.optaplanner.org/7.45.0.Final/optaplanner-docs/html_single/index.html#customCloning
文档原话: plementing a planning clone method is hard, therefore you do not need to implement it. 就离谱,给的代码示例和我的版本不一致,暂时搁着~~
3. Solver & SolverManager
@Resource
private SolverManager<ChessBoard, UUID> nQueensPuzzleSolverManager;
---
CloudBalance problem1 = ...;
UUID problemId = UUID.randomUUID();
// Returns immediately
SolverJob<CloudBalance, UUID> solverJob = solverManager.solve(problemId, problem1);
...
CloudBalance solution1;
try {
// Returns only after solving terminates
solution1 = solverJob.getFinalBestSolution();
} catch (InterruptedException | ExecutionException e) {
throw ...;
}