Правила игнорируются в VehicleRouting с TimeWindows - PullRequest
0 голосов
/ 02 июля 2018

Я взял пример с Optaplanner для расчета оптимальных маршрутов для VRP с Timewindows и немного изменил код, чтобы удовлетворить наши потребности.

У нас есть специалисты, которые работают на месте клиентов. Каждый из техников - это свое собственное «депо», потому что они могут начинать в разных местах. Поэтому в каждом депо ровно один автомобиль.

Это удивительно хорошо работает с приведенным примером.

Теперь мы хотим добавить правило, согласно которому техник должен назначаться заказчику только в том случае, если он обладает необходимой квалификацией (например, только некоторым техническим специалистам разрешается бурить)

Заказчик и технический специалист имеют квалификации, которые должны соответствовать. Мы добавили правило в файл drl:

rule "qulificationcorrect"
when
    $vehicle : Vehicle($vehicleQualifications:qualifications)
    $customer : Customer(vehicle==$vehicle,$customerQualification:qualifications)
    $test : Integer(RuleHelper.qualified($vehicleQualifications,$customerQualification)<1)
then
    System.out.println(RuleHelper.qualified($depotQualifications,$customerQualification));
    scoreHolder.addHardConstraintMatch(kcontext, -100L);

где Rulehelper выглядит так:

public class RuleHelper
{
   public static int qualified(Integer[] vehicle, Integer[] customer)
   {
       if (customer == null || customer.length < 1)
       {
        System.out.println("CUSTOMER EMPTY");

        return 1;
       }
       if (vehicle == null || vehicle.length < 1)
       {
           System.out.println("VEHICLE EMPTY");

           return 0;
       }
       List<Integer> vehicleList = Arrays.asList(vehicle);
       List<Integer> customerList = Arrays.asList(customer);
       System.out.println("VehicleList=" + vehicleList + " CustomerList" + customerList + " rule = " + vehicleList.containsAll(customerList));
       return vehicleList.containsAll(customerList) ? 1 : 0;
   }
}

Но когда я смотрю на свое Решение, у него нет хардскора (0), и это вывод:

{
 "solutions" : [
   {
     "employee" : {
       "name" : "Technician 1",
       "qualifications" : [
         1,
         2,
         5,
         999
       ],
       "lat" : 49.70103,
       "lng" : 8.32404,
       "employeeId" : 31,
       "startTime" : 480,
       "endTime" : 1170,
       "maxOrderCount" : 0,
       "solutionId" : 1
     },
     "orders" : [
       {
         "qualifications" : [
           1000
         ],
         "transmittedStart" : 435,
         "transmittedEnd" : 660,
         "startTime" : 480,
         "endTime" : 540,
         "lat" : 49.96685,
         "lng" : 8.0308,
         "orderId" : 638411,
         "fixed" : false,
         "calculatedStart" : 522,
         "calculatedEnd" : 567,
         "solutionId" : 4
       },
       {
         "qualifications" : [
           999
         ],
         "transmittedStart" : 615,
         "transmittedEnd" : 840,
         "startTime" : 660,
         "endTime" : 720,
         "lat" : 49.89585,
         "lng" : 8.0809,
         "orderId" : 637001,
         "fixed" : false,
         "calculatedStart" : 583,
         "calculatedEnd" : 660,
         "solutionId" : 3
       }
     ]
   },
   {
     "employee" : {
       "name" : "Technician 2",
       "qualifications" : [
         3,
         1000
       ],
       "lat" : 49.70103,
       "lng" : 8.32404,
       "employeeId" : 264,
       "startTime" : 480,
       "endTime" : 1170,
       "maxOrderCount" : 0,
       "solutionId" : 2
     },
     "orders" : [ ]
   }
 ]
}

По сути, первый техник получает оба заказа (клиентов), хотя у него есть только квалификации 1,2,5999, а не 1000. Техник-разведчик не получает заказов вместо того, который имеет квалификацию 1000.

Я надеюсь, что этого достаточно, чтобы кто-то сказал мне, что не так ...

С уважением

РЕДАКТИРОВАТЬ: Благодаря помощи Джеффри Де Смет Я изменил правило на

rule "qualificationcorrect"
when
    $customer : Customer(hasAllQualifications() == false)
then

    scoreHolder.addHardConstraintMatch(kcontext, -100L);

конец

, а также реализованы все требования к клиенту:

    public boolean hasAllQualifications()
{
    if (qualifications.length < 1)
    {
            return true;
    }
    if (vehicle == null || vehicle.getQualifications() == null || vehicle.getQualifications().length < 1)
    { 
        return false;
    }
    List<Integer> vehicleList = Arrays.asList(vehicle.getQualifications());
    List<Integer> customerList = Arrays.asList(this.getQualifications());
    return vehicleList.containsAll(customerList);
}

Теперь решение показывает ожидаемое поведение Еще раз спасибо за быстрый ответ

1 Ответ

0 голосов
/ 02 июля 2018

Это может быть связано с тем, как работает «вычисление инкрементного балла» (которое основывается на вызове modify() для фактов слюней). Включить environmentMode FULL_ASSERT - если выдается исключение искажения оценки, это проблема.

Если это так, давайте взглянем на ваше правило

when
    $vehicle : Vehicle($vehicleQualifications:qualifications)
    // When the Customer.vehicle changes, the rule engine gets notified
    $customer : Customer(vehicle==$vehicle,$customerQualification:qualifications)
    // That should retrigger the evaluation of this line every time a customer's vehicle changes
    $test : Integer(RuleHelper.qualified($vehicleQualifications,$customerQualification)<1)

В любом случае, вы все равно можете переписать это так:

when
    $customer : Customer(hasAllQualifications() == false)

И просто Customer.hasAllQualifications() посмотрите на Customer.vehicle

...