【问题标题】:optaplanner custom implementation of ScoreHolderscoreHolder 的 optaplanner 自定义实现
【发布时间】:2014-12-13 22:38:22
【问题描述】:

我的主要问题是,我是否可以在 OptaPlanner 中使用 ScoreHolder 的自定义实现来计算流口水分数?如果是的话,我该怎么做,因为 scoreHolder 对象被隐式注入到全局变量中?您可以在下面找到详细信息,为什么我要使用 ScoreHolder 的自定义实现。

我在开发需要优化某些产品价值的应用程序时发现了一个问题。我有设备,并根据预测计算每个设备的产量。 我使用 OptaPlanner,我有如下规则:

when
    $device : Device($deviceId : id)
    $forecast : Forecast(deviceId == $deviceId)
then
    int deviceProduction = $device.calculateProduction($forecast);
    scoreHolder.addSoftConstraintMatch(kcontext, deviceProduction);
end

因此,在此之后,软分数将包含总产量(overallProduction)。我想要的,是将整体生产的价值保持在软分数中。问题是,生产价值不仅仅是整体生产乘以价格。生产是有限制的,超出限制的所有东西都有负价格。所以我们给出了限价和两个价格:正数(positive_price) 和负数(negative_price)。值计算的架构如下:

if( overallProduction <= limit)
    value = positive_price * overallProduction;
else
    value = positive_price * limit + negative_price * (overallProduction - limit);

所以我认为,我不能将这个值的计算包含在单个设备的规则计算产量中,因为只有在收集所有设备的产量之后,我才能计算整体产量的这个值。

我唯一的想法是如何处理它,就是让 scoreHolder 的自定义实现扩展 HardSoftScoreHolder。这个定制的 ScoreHolder 将在内部保持整体生产。它将按照开头给出的规则计算。然后,在从 extractScore 方法返回结果之前,将通过自定义 ScoreHolder 计算出正确的值。

问题是,我是否可以在 drools 分数计算中使用我的自定义 ScoreHolder?由于全局 scoreHolder 对象被隐式注入..

或者如果有其他方法可以将整体生产的价值放入 score 对象中?

感谢您的帮助和问候,

【问题讨论】:

  • 全局变量不能参与规则条件的求值;然而,事实可以。这建议您在规则中计算整体生产并将该值存储在一个事实中,不断更新它,避免循环(无循环!)。然后,添加一些规则来计算值(类似于 if 语句)并在分数中使用值。 (我不是 optaplanner 方面的专家,所以我不会将此作为答案。)

标签: optimization drools optaplanner


【解决方案1】:

我没有破解 ScoreHolder,而是按照 Geoffrey De Smet 的建议进行了操作,谢谢!

rule "SingleProduction"
    when
        $device : Device($deviceId : id)
        $forecast : Forecast(deviceId == $deviceId)
    then
        int deviceProduction = $device.calculateProduction($forecast);
        insertLogical(new SingleProduction(deviceProduction));
end

rule "ValueOfTotalProduction"
    when
        ProductionLimit( $limit : value )
        PositivePrice( $positivePrice : value )
        NegativePrice( $negativePrice : value )
        Number( $totalProduction : intValue() )
                 from accumulate( SingleProduction( $value : value ),
                              sum( $value ) )
    then
        int productionValue;
        if($totalProduction <= $limit)
            productionValue = $totalProduction * $positivePrice;
        else
            productionValue = $limit * $positivePrice +
                              ($totalProduction - $limit) * $negativePrice;

        scoreHolder.addSoftConstraintMatch(kcontext, productionValue);
end

【讨论】:

    【解决方案2】:

    破解ScoreHolder 不是这样做的方法(尽管通过创建自定义ScoreDefinition 你可以这样做)。

    相反,您的规则可以使用insertLogical() 将中间结果作为新事实插入,而不是直接修改ScoreHolder。然后另一个规则匹配该中间结果(可能具有较低的salience)并相应地修改ScoreHolder。有关示例,请参见护士排班示例。

    Laune 的方法也行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多