2.6 分数概念
这是我参与更文挑战的第9天,活动详情查看: 更文挑战
内容概要
分数计算是一大章节,后续篇章会连更来学习分数的在OptaPlanner使用。分数在OptaPlanner非常的重要,约束规则的编写跟其是密不可分的。
什么是分数
每个@PlanningSolution类都有一个分数。分数是比较两种解决方案的客观方式。分数越高的解越好。求解器的目前是找到所有可能的解中得分最高的解。最优解决方案是规划求解在求解过程中遇到的得分最高的解决方案,这可能是最佳解决方案。
OptaPlanner不能自动知道哪种解决方案最适合我们的业务,因此需要告诉它如何根据我们的业务需求计算给定@PlanningSolution实例的分数。如果您忘记或无法实现一个重要的业务约束,解决方案可能是无用的。
确定业务约束
业务约束需要将其转换为分数约束。在OptaPlanner中通过以下评分技术定义约束,而且非常灵活。
- **分数符号(正或负):**最大化或最小化一个约束类型
- **分数权重:**给一个约束类型加上成本/利润
- **分数水平(硬,软,中):**对一组约束类型进行优先排序
需要花点时间熟悉一下这三种技术。一旦理解了它们,大多数业务约束的编写就变得简单明了。
分数约束符号(正或负)
所有的评分技术都是基于约束条件的。一个约束条件可以是一个简单的模式(如最大化解决方案中的苹果收获)或更复杂的模式。一个正的约束是我们想最大化的约束。负的约束是指我们想要最小化的约束。
上面的图片说明,无论约束条件是正还是负,最优方案总是具有最高分。
大多数规划问题只有负的约束,因此有一个负的分数。负约束和正约束可以结合在一起,甚至在同一个分数等级中。
当一个约束在某个PlanningEntity规划实体上匹配到(因为负约束被打破或正约束被满足)时,它被称为约束匹配。
约束权重(分值)
不是所有的约束都是同等重要的。如果破坏一个约束条件和破坏另一个约束条件n次同样坏,那么这两个约束条件就有不同的权重(但它们处于同一分数水平)。例如,在车辆路线选择中,你可以让一个心情糟糕的司机约束条件匹配和消耗两个油箱的约束条件匹配一样多。
在这种情况下,积极的约束条件使收入最大化,消极的约束条件使费用最小化,因此它们共同使利润最大化。
约束匹配的权重可以取决于所涉及的PlanningEntity规划实体。例如,在CloudBalance中,Computer计算机的软约束匹配的权重是该计算机的维护成本(每台计算机不同)。
分数等级
有时候,一个分数约束会超过另一个分数约束,无论后者被打破多少次。在这种情况下,这些分数约束就处于不同的层次。例如,一个护士不能同时上两个班次,所以这超过了所有护士的期望约束。
大多数用例只有两个分数级别,Hard硬的和Soft软的。两个分数的级别是按词法比较的。第一个分数级别首先被比较。如果这些不同,其余的分数级别就会被忽略。例如,一个打破0个硬约束和1000000个软约束的分数比一个打破1个硬约束和0个软约束的分数要好。
如果有两个(或更多)分数级别,例如
HardSoftScore,那么如果没有打破硬约束,那么一个分数是可行的。
对于每个约束,需要选择一个分数级别,一个分数权重和一个分数符号。例如:-1soft,它的得分级别为Soft,权重为1,符号为负数。
大多数用例都使用有两个或三个权重的分数,如HardSoftScore和HardMediumSoftScore。
Score类型
分数由Score接口表示,它自然地扩展了Comparable。
public interface Score<...> extends Comparable<...> {
...
}
要使用的得分实现取决于我们的业务情况。OptaPlanner有几个内置的Score实现,但你也可以实现一个自定义Score。大多数用例倾向于使用内置的HardSoftScore。
所有的Score实现也有一个initScore(是一个int)。它主要是为了在OptaPlanner内部使用:它是未初始化的规划变量的负数。从用户的角度来看,它是0,除非构造启发式在初始化所有规划变量之前就被终止了(在这种情况下,Score.isSolutionInitialized()返回false)。
@PlanningSolution
public class CloudBalance {
...
@PlanningScore
private HardSoftScore score;
}
避免使用浮点数
在分数计算中避免使用float或double。使用BigDecimal或Long来代替。
浮点数(float和double)不能正确表示一个小数。例如:一个双数不能正确地保持0.05的数值。相反,它持有最接近的可表示的值。用浮点数进行算术(包括加法和减法),特别是对于计划问题,会导致不正确的决定。
此外,浮点数的加法不是关联性的。
System.out.println( ((0.01 + 0.02) + 0.03) == (0.01 + (0.02 + 0.03)) ); // returns false
这导致了分数的损坏。十进制数字(BigDecimal)则没有这些问题。
总结
这一篇章主要学习分数Score在OptaPlanner内的概念,以及分数的级别、类型等。
结束语
下一篇章,我们将来学习分值如何匹配到约束条件,以及如何的计算。
创作不易,禁止未授权的转载。如果我的文章对您有帮助,就请点赞/收藏/关注鼓励支持一下吧。💕💕💕💕💕💕