初学OptaPlanner-04- 配置、注解

文档学习列表:

plannerConfiguration https://docs.optaplanner.org/7.45.0.Final/optaplanner-docs/html_single/index.html#plannerConfiguration

01. 快速回顾OptaPlanner的使用步骤

问题建模,使用@PlanningSolution和@PlanningEntity来确定输入输出域等
配置Slover
加载输入数据
调用Slover.solve(problem) ,求解返回结果
初学OptaPlanner-04- 配置、注解

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)。
指向具有相同计划变量的另一个计划实体,该实体递归地指向锚点。
没有组成环或者树结构,当且仅有唯一的锚点连接的一条线
初学OptaPlanner-04- 配置、注解

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 ...;
}

(0)
陈玉龙的头像陈玉龙
上一篇 2022年9月20日 12:43:17
下一篇 2022年9月20日

相关推荐