Optaplanner:遍历drools规则文件中的列表变量 [英] Optaplanner: Iterate over list variable in drools rule file

查看:746
本文介绍了Optaplanner:遍历drools规则文件中的列表变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在解决类似于员工名册的问题.我还有其他限制.员工具有分配给他们的类型"值.每天至少要有每种"类型的至少1名员工在这里,这是一个严格的约束.我将其建模如下:

I am solving a problem similar to employee rostering. I have an additional constraint. The employees have a "type" value assigned to them. It's a hard constraint that atleast 1 employee of each "type" be there everyday. I have modelled it as follows:

rule "All employee types must be covered"
when
    $type: Constants.EmployeeType() from Constants.EmployeeType.values()       
    not Shift(employeeId != null, $employee: getEmployee(), $employee.getType() == $type.getValue())

then
    scoreHolder.addHardConstraintMatch(kcontext, -100);
end

但是,此规则不认为每天都满足约束条件.我有一个日期字符串列表.如何以与EmployeeType枚举相同的方式在drools文件中对其进行迭代?

This rule however, does not consider that the constraint be satisfied on each day. I have a list of date strings. How can I iterate over them in the drools file in the same manner that I am on the EmployeeType enum?

编辑:我想出了一种方法,但感觉像是在破解.在初始化日期字符串列表时,我还将其分配给静态变量.然后,我可以使用类似于枚举的静态变量.

I figured out a way but it feels like a hack. When initialising the list of date strings, I also assign it to a static variable. Then I am able to use the static variable similar to the enum.

rule "All employee types must be covered"
when
    $type: Constants.EmployeeType() from Constants.EmployeeType.values()
    $date: String() from Constants.dateStringList;   
    not Shift(employeeId != null, $date == getDate(), $employee: getEmployee(), $employee.getType() == $type.getValue())

then
    scoreHolder.addHardConstraintMatch(kcontext, -100);
end

但是不要以为这是正确的方法.

Don't think this is the correct approach though.

推荐答案

您的方法行得通,但是必须在类的静态属性中定义动态配置听起来并不正确(就像您指出的那样).

Your approach works, but having to define dynamic configurations in a static property of a class doesn't sound right (like you pointed out).

一种解决方案是要么在会话中使用全局变量,要么使用指定此配置的事实类.

One solution would be to either use a global in the session, or to have a fact class that specify this configuration.

使用全局

如果您决定采用这种方法,则需要在DRL中定义类型为List<String>的全局变量,然后将其与memberOf运算符结合使用在规则中:

If you decide to take this approach, then you need to define a global of type List<String> in your DRL and then use it in your rules in combination with the memberOf operator:

global List<String> dates;

rule "All employee types must be covered"
when
  $type: Constants.EmployeeType() from Constants.EmployeeType.values()  
  not Shift(
    employeeId != null, 
    date memberOf dates, 
    $employee: getEmployee(), 
    $employee.getType() == $type.getValue()
  )
then
  scoreHolder.addHardConstraintMatch(kcontext, -100);
end

建议在将任何事实Shift插入会话之前,先为global设置值:

It is recommended to set the value for global before you insert any fact Shift into you session:

List<String> dates = //get the List from somewhere
ksession.setGlobal("dates", dates);

使用实况类

除了全局变量外,还可以将配置建模为一个类.如果您想例如在规则内部修改配置,这将使事情变得容易.

Other than a global, you can model your configuration as a class. This makes things easier if you want for example to modify the configuration inside the rules themselves.

对于这种方法,您首先需要具有一个包含List<String>的类.从理论上讲,您可以插入List<String>而不将其包装在任何类中,但这会使内容难以阅读和维护.

for this approach you will need to have a class containing the List<String> first. You could in theory insert the List<String> without wrapping it in any class, but this will make things hard to read and maintain.

public class DatesConfiguration { 

    private List<String> dates;

    //... getters + setters
}

然后,您需要实例化此类的对象并将其插入到会话中:

Then, you need to instantiate an object of this class and to insert it into your session:

DatesConfiguration dc = new DatesConfiguration();
dc.setDates(...);

ksession.insert(dc);

这时,您创建的对象只是Drools的另一个事实,可以在您的规则中使用:

At this point, the object you have created is just another fact for Drools and can be used in your rules:

rule "All employee types must be covered"
when
  $type: Constants.EmployeeType() from Constants.EmployeeType.values()  
  DatesConfiguration($dates: dates)
  not Shift(
    employeeId != null, 
    date memberOf $dates, 
    $employee: getEmployee(), 
    $employee.getType() == $type.getValue()
  )
then
  scoreHolder.addHardConstraintMatch(kcontext, -100);
end

希望有帮助,

这篇关于Optaplanner:遍历drools规则文件中的列表变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆