Я взял пример с 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);
}
Теперь решение показывает ожидаемое поведение
Еще раз спасибо за быстрый ответ