如何在Optaplanner中实现不确定的分数规则?

时间:2018-03-15 07:16:42

标签: drools optaplanner

我使用Optaplanner开发系统,它与示例类似 - MeetingScheduling。将某些任务分配给某些机器并确定开始时间。我创建了一个类 - TaskAssignment作为计划实体,字段 - "机器"和" startTimeGrain"作为计划变量。

但在我的用例中,MeetingScheduling中不存在约束,我不知道如何实现。在某些情况下,可能在任务的前面有准备时间。这意味着,TaskA和TaskB是同一台机器上的连续任务,TaskB不会启动,直到TaskA完成(TaskA是TaskB的上一个任务),并且可能在这些任务之间有准备时间,这意味着在TaskA完成之后,TaskA必须等待一段时间才能启动,但等待多长时间并不固定,这取决于它以前的任务。

var currentInventory = [
  {
    name: 'Brunello Cucinelli',
    shoes: [
      {name: 'tasselled black low-top lace-up', price: 1000},
      {name: 'tasselled green low-top lace-up', price: 1100},
      {name: 'plain beige suede moccasin', price: 950},
      {name: 'plain olive suede moccasin', price: 1050}
    ]
  },
  {
    name: 'Gucci',
    shoes: [
      {name: 'red leather laced sneakers', price: 800},
      {name: 'black leather laced sneakers', price: 900}
    ]
  }
];

function renderInventory(inventoryList) {
  var summaryList = [];

  for (var i = 0; i < inventoryList.length; i++) {
    var currentElement = inventoryList[i];
    var designerName = currentElement.name;
    var shoes = currentElement.shoes;

    for (var j = 0; j < shoes.length; j++) {
      var shoe = shoes[j].name;
      var price = shoes[j].price;

      summaryList.push(designerName + ', ' + shoe + ', ' + price);
    }
  }
  var summaryString = turnListToString(summaryList);

  return summaryString;
}

function turnListToString(list) {
  var outputString = '';

  for (var i = 0; i < list.length; i++) {
    outputString += list[i] + '\n';
  }

因此。我根据上一个任务得到任务库的准备时间(从列表中读取)并计算两个任务之间的间隔。如果间隔小于准备时间,间隔减去准备时间作为惩罚分数。 当我运行计划时,规则通过Score Corruption例外。我发现原因是间隔和准备时间都不确定。

对于间隔,它取决于前一个任务的结束时间和它自己的任务的开始时间,开始时间是计划变量,所以它是不确定的。

对于准备时间,每个任务都有一个准备时间表,准备时间可用,取决于前一个任务,由于计划期间开始时间不断变化,准备时间也在不断变化。所以准备时间也不确定。 在这种情况下,有什么办法可以实现? 非常感谢

这是我的规则,但会出现分数损坏例外。

Possibly like following:
TaskA -> TaskB: TaskB's preparation time is 5 mins.
TaskC -> TaskB: TaskB's preparation time is 15 mins.
TaskC -> TaskA: TaskA's preparation time is 0 min.

异常消息:

rule "Make sure interval large than preparation time"
salience 1
    when
        $currentTA : TaskAssignment(
            $machine: machine != null, 
            startingTimeGrain != null,
            $lack : getIntervalLack() < 0L // in getIntervalLack(), interval minus preparation time
            ) 
    then
            scoreHolder.addHardConstraintMatch(kcontext,  $lack);
end

2 个答案:

答案 0 :(得分:0)

如果这是一个严格的约束,我会让它内置并用阴影变量来做:

我可能预先计算了任务依赖性,因此taskB引用了它potentioalPrecedingTasks(示例中的taskA和taskC)。然后我将使用“链接时间”模式(请参阅文档)来确定任务执行的顺序。根据该顺序,开始时间是影子变量,即actualPrecedingTask.endingTime + lookUpPreperationTime(precedingTask, thisTask)。请参阅VRP中的arrivalTime监听器,原理相同。

如果它是一个软约束,我仍然有相同的阴影变量,但称之为desiredStartingTime并添加一个软约束来检查实际的startingTime是否等于或高于desiredStartingTime。

答案 1 :(得分:0)

背景摘要:一些订单被发送到生产车间,订单被流程路由按顺序拆分为多个任务。订单的任务必须按顺序执行。每个任务只能在特定计算机上执行。在开始任务之前可能有准备时间,准备时间是否存在,是长还是短,取决于同一台机器前面的任务。 以下是难以实施的主要限制因素:

Hard constraints:
1. A task must be executed by the particular machine.
2. Tasks in an order must be executed by a particular sequence (tasks of an order, come from the processes of the order, usually they need to be executed by different machine).
3. The first task of an order has the earliest start time. It means when the order arrived the production workshop.
4. Some tasks in an order maybe have a request start time, means if the previous task finish, the next task has to start in a period. For example, TaskA is the previous task of TaskB in the same order, TaskB has to start in 16 hours after TaskA finish.
5. A task probably has a preparation time, depends on its previous task of in the same machine(usually, the same process from different order were assigned to the same machine). If there is the preparation time on the task, the task has to start after the preparation time. In other words, there is an interval between these tasks.
Soft constraints:
1. All task should be executed as soon as possible.
2. Minimize the preparation time, due to the different location of the tasks lead to the different relationship of the tasks, then the preparation times are different. 

因此,在规划期间,解决方案中有两个“链”。 Optaplanner为同一台机器中的任务生成了一个链。另一个“链”来自订单,在这个“链”中,任务将被分配给不同的机器。两条链” 他们在一起。

我将机器中的链(由Optaplanner生成)命名为“机器链”,并将“链”命名为“订单链”。

现在,你可以看到,由于两个“链”挂在一起,一个任务作为机器链和订单链中的节点。

我曾尝试过“链接时间”模式,出现了undoMove损坏。我认为原因是当我更新机器链中的任务时,同一机器链中的以下任务也将更新,这些任务是订单链的节点,连锁反应爆发。

我认为我的案例就像示例 - 项目作业调度。但不同的是,本例中的两个“链”永远不会挂在一起。

所以,我尝试了简单的模式,但我无法逃脱Score Corruption例外。