首页 > 解决方案 > 寻找在 OptaPlanner 中使用“DoubleValueRange”的正确方法

问题描述

我正在学习如何通过解决线性规划来使用 OptaPlanner。我知道有很多 LP 求解器,但我认为这是我理解建模的一个很好的起点。

但是当我开始研究它时,我遇到了一个问题,它看起来实体计划变量只能是可数的。

例外情况如下:

The selector is not countable, check the ValueRanges involved.
Verify that a ValueRangeProvider does not return ValueRange when it can return CountableValueRange or Collection.

我可以知道吗:

  1. 使用“DoubleValueRange”的“合法”方式是什么?

  2. OptaPlanner 中是否有 LP 的“最佳实践”?

谢谢你。

我的解决方案:


@PlanningSolution
public class Solution {
    @PlanningEntityProperty
    private Entity entity;

    @PlanningScore
    private HardSoftScore score = HardSoftScore.ZERO;

    public Solution(Entity entity) {
        this.entity = entity;
    }

    @ValueRangeProvider(id = "x_1")
    public ValueRange<Double> getX1Range() {
        return ValueRangeFactory.createDoubleValueRange(0.0, 100.0);
    }

    @ValueRangeProvider(id = "x_2")
    public ValueRange<Double> getX2Range() {
        return ValueRangeFactory.createDoubleValueRange(0.0, 100.0);
    }
...<getters setters>...

我的实体:

@PlanningEntity
public class Entity {
    private long id;

    @PlanningVariable(valueRangeProviderRefs = "x_1")
    private Double x1;

    @PlanningVariable(valueRangeProviderRefs = "x_2")
    private Double x2;
...<getters setters>...

我的限制:

...
    private Constraint c1(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Entity.class)
                .filter(e -> !(3.0 * e.getX1() + 5.0 * e.getX2() < 5.0 ))
                .penalize("C1", HardSoftScore.ONE_HARD);
    }

    private Constraint c2(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Entity.class)
                .filter(e -> !(2.0 * e.getX1() - 6.0 * e.getX2() > 0.0 ))
                .penalize("C2", HardSoftScore.ONE_HARD);
    }

    private Constraint min(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Entity.class)
                .penalize("MIN", HardSoftScore.ONE_SOFT, e -> (int)(-e.getX1() + 6.0 * e.getX2()));
    }
...

标签: javalinear-programmingoptaplanner

解决方案


查看 ValueRangeFactory 的 createXXXValueRange() 方法集中的返回类型,我注意到除了一个之外,所有的返回类型都返回一个Countable ValueRange。该规则的一个例外是 createDoubleValueRange(),它返回一个“纯粹的”ValueRange (ValueRange)。

您的错误指向同一个方向:ValueRange 不被视为有效的可数ValueRange。这对我来说很有意义:OptaPlanner 想要从一组离散值中进行选择来进行移动。所以我认为没有任何“合法”的方式可以将它用于 OptaPlanner 的求解器 Move's。

由于一个我无法确定的原因,我自己不会将 OptaPlanner 作为解决 LP 问题的首选,因为可以计算出一组可行的解决方案。但是无论如何使用OptaPlanner(就像你的情况一样),然后我会处理离散值的倍数(10、100、1000,...)(在结果计算中将它们除以10、100、1000,...) . 并且/但与此同时,我会非常谨慎地避免分数腐败,这种危险永远不会很远。


推荐阅读