Слюни правила для вместимости транспортного средства в Optaplanner - PullRequest
0 голосов
/ 08 июня 2018

Я использую Optaplanner для CVRP и внес некоторые изменения, а именно хотел использовать несколько измерений для вместимости автомобиля.Я создал новый класс

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];
        }
    }
}

и

public boolean fitsInto (Load otherContainer) {
    if (myDimension != otherContainer.myDimension) {
        throw new IllegalArgumentException("Different load dimensions (" + myDimension +" / "+ otherContainer.myDimension + ").");
    } else {
        for (int i=0; i < myDimension; i++) {
            if (capacity[i]>otherContainer.capacity[i]) return false;
        }
    }
    return true;
}

.В тот момент, когда я испытываю трудности с правилами Drools, я совершенно новичок в этом.Старое правило было:

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

end

Мне нужно изменить его так, чтобы он использовал класс 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());

end

Конечно, он не проходит, поэтому я был бы рад получить некоторые советы и подсказки.Спасибо!

Ответы [ 2 ]

0 голосов
/ 20 июня 2018

Мне не удалось решить проблему, поэтому я просто скопировал емкости в intacity1, intacity2, скопировал и изменил правила соответствующим образом.Это не элегантно и не масштабируемо, но пока делает свою работу ...

0 голосов
/ 09 июня 2018

Из того, что я понял, вы пытаетесь добавить больше измерений к demand и, следовательно, к capacity, где ограничение состоит в том, что ни одна из возможностей любого измерения не может быть превышена.Чтобы достичь этого, вы можете просто изменить Vehicle и Customers следующим образом

class Vehicle extends AbstractPersistable implements Standstill{
     protected Location location;
     protected List<Integer> capacities;
     ...
}

и

class Customer extends AbstractPersistable implements Standstill{
    protected List<Integer> demands;
    ...
}

Затем в Drools вы изменяете свое правило (абсолютно не проверенное; вв частности, вам, возможно, придется добавить .intValue() после методов get):

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);

Это позволит убедиться, что если спрос превысит емкость для любого измерения , жесткий результат будет оштрафован наразница.Просто убедитесь, что все списки имеют одинаковый размер с размером $loadType в capacities, соответствующем одному и тому же измерению в demands.

Вы также можете попробовать, просто изменив protected int capacity на protected int[] capacities в Vehicle и аналогично в Customer с demand, но я не уверен, что вы можете связывать элементы массива в 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() не нужно)

...