我以Optaplanner为例,使用Timewindows计算了VRP的最佳路线,并对代码进行了一些调整以满足我们的需求。
我们有在客户现场工作的技术人员。 每个技术人员都是其自己的“仓库”,因为他们可以在不同的位置开始。 因此,每个仓库只能有一辆车。
在给定的示例中,这非常好用。
现在,我们要添加一条规则,即只有在具有所需资格的情况下(例如,仅允许某些技术人员进行钻研),才应将技术人员仅委托给客户。
客户和技术人员都具有需要匹配的资格。 我们在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、5,999个资格,而没有1000个资格。侦查员没有任何订单,而是有1000个资格。
我希望有足够的信息让别人告诉我哪里错了...
国王问候
编辑:感谢Geoffrey De Smet的帮助 我将规则更改为
rule "qualificationcorrect"
when
$customer : Customer(hasAllQualifications() == false)
then
scoreHolder.addHardConstraintMatch(kcontext, -100L);
结束
,并在客户中实现了hasAllQualifications:
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);
}
现在解决方案显示了预期的行为 再次感谢您的快速解答
答案 0 :(得分:1)
这可能与“增量分数计算”的工作方式有关(这取决于对流口水事实的称呼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