Class Optaplanner中车辆容量的下降规则

Class Optaplanner中车辆容量的下降规则,class,drools,rules,optaplanner,Class,Drools,Rules,Optaplanner,我正在为CVRP使用Optaplanner,并做了一些更改,即希望为车辆容量使用多个尺寸。 我开设了一个新班级 public class Load { protected int[] capacity; protected int myDimension=1;} 它还有几种管理数据的方法,最重要的是 public void add (Load otherLoad) { if (myDimension != otherLoad.myDimension) { throw n

我正在为CVRP使用Optaplanner,并做了一些更改,即希望为车辆容量使用多个尺寸。 我开设了一个新班级

public class Load {
protected int[] capacity;
protected int myDimension=1;}
它还有几种管理数据的方法,最重要的是

public void add (Load otherLoad) {
    if (myDimension != otherLoad.myDimension) {
        throw new IllegalArgumentException("Different load dimensions (" + myDimension +" / "+ otherLoad.myDimension + ").");
    } else {
        for (int i=0; i < myDimension; i++) {
            capacity[i]+=otherLoad.capacity[i];
        }
    }
}
结束

我需要修改它,以便它将使用Load类而不是整数,但不确定如何使用。我读了一些Drools文档后做的蹩脚实验是这样的

rule "vehicleCapacity"
when
    $demandTotal: Load
    $vehicle : Vehicle($capacity : capacity)
    accumulate(
        Customer(
            vehicle == $vehicle,
            $demand : demand);
        $demandTotal.add($demand);
        not ($demandTotal.fitsInto($capacity))
    )
then
    scoreHolder.addHardConstraintMatch(kcontext, $capacity.sumValues() - $demandTotal.sumValues());
结束

当然不会通过,所以我很乐意得到一些提示和建议。
谢谢大家!

据我所知,您正试图为需求增加更多维度,从而增加容量,其中限制条件是任何维度的容量都不能超过。为了实现这一点,您只需修改车辆和客户,如下所示

class Vehicle extends AbstractPersistable implements Standstill{
     protected Location location;
     protected List<Integer> capacities;
     ...
}
这将确保如果需求超过任何维度的容量,硬分数将惩罚差异。只需确保所有列表的大小相同,容量中的维度$loadType对应于需求中的相同维度

您也可以尝试将车辆中的protected int capacity更改为protected int[]capacity,并根据需要在Customer中进行类似更改,但我不确定您是否可以绑定到Drools中的数组元素。也许值得一试:Drools规则再次运行,完全未经测试:

rule "vehicleCapacity"
    when
        $vehicle : Vehicle($capacity: capacities[$lt:lt])
        accumulate(
            Customer(
                vehicle == $vehicle,
                $demand : demands[lt]);
            $demandTotal : sum($demand);
            $demandTotal > $capacity
        )
    then
        scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);

那么至少.intValue是不必要的

我无法解决这个问题,所以我实际上只是将容量复制到int capacity1,int capacity2,并相应地复制和修改了规则。
它既不优雅,也不可扩展,但到目前为止,它确实做到了这一点

谢谢你的评论。我尝试了第二个int[]版本,但是,我得到了一些错误。我猜$lt附近出了点问题,但不太确定,主线程java.lang.IllegalStateException中出现了什么异常。IllegalStateException:分数中有错误DRL:错误消息:消息[id=1,kieBase=defaultKieBase,level=ERROR,path=org/optaplanner/examples/vehiclerouting/solver/vehicleRoutingScoreRules.drl,line=42,column=0 text=无法分析表达式容量[$lt:lt]:[ERROR:无法使用严格模式解析方法:org.optaplanner.examples.vehiclerouting.domain.Vehicle.$lt][Near:{……容量[$lt:lt]]我无法解决这个问题,所以我实际上只是将容量复制到int capacity1,int capacity2,并相应地复制和修改了规则。遗憾的是,您必须这样做。Drools明确提供了绑定到列表中元素的可能性,请参阅第8.8.3节。它没有说明任何关于数组的内容,但我认为它会相同。您尝试过解决方案1吗?顺便说一句,应该是需求:需求[$lt]和$。
class Vehicle extends AbstractPersistable implements Standstill{
     protected Location location;
     protected List<Integer> capacities;
     ...
}
class Customer extends AbstractPersistable implements Standstill{
    protected List<Integer> demands;
    ...
}
rule "vehicleCapacity"
when
    $vehicle : Vehicle($capacity: capacities.get($loadType:lt))
    accumulate(
        Customer(
            vehicle == $vehicle,
            $demand : demands.get($loadType));
        $demandTotal : sum($demand);
        $demandTotal > $capacity
    )
then
    scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);
rule "vehicleCapacity"
    when
        $vehicle : Vehicle($capacity: capacities[$lt:lt])
        accumulate(
            Customer(
                vehicle == $vehicle,
                $demand : demands[lt]);
            $demandTotal : sum($demand);
            $demandTotal > $capacity
        )
    then
        scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);