10.2. 分数计算类型
计算解决方案分数的方法有几种:
- 简单 Java 分数计算 :以 Java 或其他 JVM 语言通过单一方法实施所有限制。这个方法无法扩展。
- 约束 流分数计算 :将每个约束实施为 Java 或其他 JVM 语言的独立约束流。这个方法快速且可扩展的。
- 增量 Java 分数计算 (不推荐):使用 Java 或其他 JVM 语言实施多种低级别方法。这个方法快速、可扩展,但很难实施和维护。
- Drools 分数计算(已弃用): 将每个约束作为 DRL 中的单独分数规则实施。这个方法可扩展。
每个分数计算类型都可以用于任何分数定义,如 HardSoftScore
或 HardMediumSoftScore
。所有分数计算类型都面向对象,并可重复利用现有的 Java 代码。
分数计算必须为只读。它不得以任何方式更改计划实体或问题事实。例如,分数计算不得对分数计算中的规划实体调用 setter 方法。
如果可以预测,在启用了 environmentMode
断言时,OptaPlanner 不会重新计算解决方案分数。例如,在完成获奖步骤后,无需计算分数,因为之前已完成并撤消。因此,无法保证在分数计算过程中应用的更改实际发生。
要在规划变量更改时更新计划实体,请使用 shadow 变量。
10.2.1. Implenting the Easy Java 分数计算类型 复制链接链接已复制到粘贴板!
Easy Java 分数计算类型提供了一种在 Java 中实施分数计算的简单方法。您可以使用单一方法以 Java 或其他 JVM 语言实施所有限制。
优点:
- 使用普通旧 Java,因此没有学习曲线
- 提供一个将分数计算委托给现有代码库或旧系统的机会
缺点:
- 最慢的计算类型
- 不扩展,因为没有增量分数计算
流程
实现
EasyScoreCalculator
接口:public interface EasyScoreCalculator<Solution_, Score_ extends Score<Score_>> { Score_ calculateScore(Solution_ solution); }
public interface EasyScoreCalculator<Solution_, Score_ extends Score<Score_>> { Score_ calculateScore(Solution_ solution); }
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 以下示例在 N Queens 问题中实施这个接口:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在 solver 配置中配置
EasyScoreCalculator
类。以下示例演示了如何在 N Queens 问题中实施这个接口:<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.nqueens.optional.score.NQueensEasyScoreCalculator</easyScoreCalculatorClass> </scoreDirectorFactory>
<scoreDirectorFactory> <easyScoreCalculatorClass>org.optaplanner.examples.nqueens.optional.score.NQueensEasyScoreCalculator</easyScoreCalculatorClass> </scoreDirectorFactory>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 要在 solver 配置中动态配置
EasyScoreCalculator
方法的值,以便基准器可以调整这些参数,添加easyScoreCalculatorCustomProperties
元素并使用自定义属性:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
10.2.2. 实施增量 Java 分数计算类型 复制链接链接已复制到粘贴板!
Incremental Java 分数计算类型提供了一种方式,可以在 Java 中逐步实施分数计算。
不建议使用这个类型。
优点:
- 非常快速且可扩展的。如果正确实施,这是目前最快的类型。
缺点:
很难写入。
- 一个可扩展的实现,它大量使用映射、索引等。
- 您必须自行了解、设计、编写并改进所有这些性能优化。
- 读取困难。常规分数约束更改可能会导致高维护成本。
流程
实现
IncrementalScoreCalculator
接口的所有方法:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 以下示例在 N Queens 问题中实施这个接口:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在 solver 配置中配置
incrementalScoreCalculatorClass
类。以下示例演示了如何在 N Queens 问题中实施这个接口:<scoreDirectorFactory> <incrementalScoreCalculatorClass>org.optaplanner.examples.nqueens.optional.score.NQueensAdvancedIncrementalScoreCalculator</incrementalScoreCalculatorClass> </scoreDirectorFactory>
<scoreDirectorFactory> <incrementalScoreCalculatorClass>org.optaplanner.examples.nqueens.optional.score.NQueensAdvancedIncrementalScoreCalculator</incrementalScoreCalculatorClass> </scoreDirectorFactory>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要编写和审核增量分数计算器代码可能比较困难。通过使用
EasyScoreCalculator
来满足environmentMode
触发的断言,以保证其正确性。要在 solver 配置中动态配置
IncrementalScoreCalculator
的值,以便基准器可以调整这些参数,添加incrementalScoreCalculProperties
元素并使用自定义属性:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 可选:实现
ConstraintMatchAwareIncrementalScoreCalculator
接口,以促进以下目标:-
使用
ScoreExplanation.getConstraintMatchTotalMap ()
对每个分数约束进行分割,以说明分数。 -
通过
ScoreExplanation.getIndictmentMap ()
中断来视觉化或排序规划实体。 如果在
FAST_ASSERT
或FULL_ASSERT
environmentMode
中损坏IncrementalScoreCalculator
,您会收到详细的分析。Copy to Clipboard Copied! Toggle word wrap Toggle overflow 例如,在机器重新分配中,为每个约束类型创建一个
ConstraintMatchTotal
,并为每个约束匹配调用addConstraintMatch ()
:Copy to Clipboard Copied! Toggle word wrap Toggle overflow getConstraintMatchTotals ()
代码通常会复制 normalIncrementalScoreCalculator
方法的一些逻辑。约束流和 Drools Score Calculation 没有这种缺点,因为它们在不需要任何额外的域代码时会自动匹配。
-
使用