Optaplanner内置硬约束持续计划

发布于 2025-02-08 23:19:11 字数 168 浏览 2 评论 0原文

目前,我正在进行持续的计划,我有两个实体,一个是机器,另一个是订单。 该机器包含一个规划列表变量,并且该顺序具有指向机器的逆阴影变量。 我想添加一个内置的硬约束来限制某些订单可以进行的机器,但是我不能使用机器实体中的valyerangeProvider来滤除订单列表,因为它不能在实体内部使用。还有另一种方法吗? 提前致谢

Currently I'm doing continuous planning, and I have two entities, one is the machine and the other one is the order.
The machine contains a planning list variable and the order has an inverse shadow variable pointing to the machine.
I want to add a built-in hard constraint to limit to what machines a certain order can go, however I cannot use the ValueRangeProvider in the machine entity to filter out the orders list because it cannot be used inside an entity. Is there another way to do this?
Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

往事随风而去 2025-02-15 23:19:11

实际上,实体依赖性价值范围不适合计划列表变量。没有计划在不久的将来支持这一点。

您仍然可以通过使用过滤移动选择

通常,您通常需要三个selectionFilter实现,每种移动类型一个。我假设您想使用构造启发式阶段,该阶段具有listAssignMove,并且您想在本地搜索阶段中同时拥有listChangeMovelistSwapMove

然后,您需要一个高级求解器配置来应用这些过滤器。

我在任务设施示例上尝试了这种方法,以替换nomissingskillstask> taskAssigningConstraintProvider中替换约束,并使用移动过滤器使其成为内置的硬约束。这就是我最终得到的:

过滤器

,如果您只需将雇员更改为机器task> task> task 订购并重命名istasklower()以更好地适合您的域。

public class TaskAssignMoveFilter implements SelectionFilter<TaskAssignment, ListAssignMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListAssignMove<TaskAssignment> move) {
        return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
    }
}
public class TaskChangeMoveFilter implements SelectionFilter<TaskAssignment, ListChangeMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListChangeMove<TaskAssignment> move) {
        return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
    }
}
public class TaskSwapMoveFilter implements SelectionFilter<TaskAssignment, ListSwapMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListSwapMove<TaskAssignment> move) {
        return ((Employee) move.getLeftEntity()).isTaskAllowed(((Task) move.getRightValue())) &&
                ((Employee) move.getRightEntity()).isTaskAllowed(((Task) move.getLeftValue()));
    }
}

新的istasklower() 雇员

这实现了硬约束。将逻辑替换为拒绝顺序 s,必须将必须分配给给定的机器

@PlanningEntity
public class Employee extends AbstractPersistable implements Labeled {

    ...

    public boolean isTaskAllowed(Task task) {
        return skillSet.containsAll(task.getTaskType().getRequiredSkillList());
    }

    ...
}

求解器

几乎将其复制。只需更改variablename属性值(我猜是“ orders”)和过滤器的类名称。

  <constructionHeuristic>
    <queuedValuePlacer>
      <valueSelector id="1" variableName="tasks"/>
      <changeMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskAssignMoveFilter</filterClass>
        <valueSelector mimicSelectorRef="1"/>
      </changeMoveSelector>
    </queuedValuePlacer>
  </constructionHeuristic>
  <localSearch>
    <unionMoveSelector>
      <changeMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskChangeMoveFilter</filterClass>
      </changeMoveSelector>
      <swapMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskSwapMoveFilter</filterClass>
      </swapMoveSelector>
    </unionMoveSelector>
  </localSearch>

Indeed, entity-dependent value ranges do not work with planning list variables. There is no plan to support that in the near future.

You can still achieve the desired built-in hard constraint by using filtered move selection.

You'll typically need three SelectionFilter implementations, one for each move type. I assume you want to use the Construction Heuristic phase, which has the ListAssignMove and you want to have both ListChangeMove and ListSwapMove in your Local Search phase.

Then, you'll need an advanced solver configuration to apply those filter.

I've tried this approach on the TaskAssignment example to replace the noMissingSkills constraint in the TaskAssigningConstraintProvider and make it a built-in hard constraint using move filtering. This is what I ended up with:

Filters

These should also work in your case if you just change Employee to Machine, Task to Order and rename the isTaskAllowed() to better fit your domain.

public class TaskAssignMoveFilter implements SelectionFilter<TaskAssignment, ListAssignMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListAssignMove<TaskAssignment> move) {
        return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
    }
}
public class TaskChangeMoveFilter implements SelectionFilter<TaskAssignment, ListChangeMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListChangeMove<TaskAssignment> move) {
        return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
    }
}
public class TaskSwapMoveFilter implements SelectionFilter<TaskAssignment, ListSwapMove<TaskAssignment>> {

    @Override
    public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListSwapMove<TaskAssignment> move) {
        return ((Employee) move.getLeftEntity()).isTaskAllowed(((Task) move.getRightValue())) &&
                ((Employee) move.getRightEntity()).isTaskAllowed(((Task) move.getLeftValue()));
    }
}

The new isTaskAllowed() method on Employee

This implements the hard constraint. Replace the logic to reject Orders that must not be assigned to the given Machine.

@PlanningEntity
public class Employee extends AbstractPersistable implements Labeled {

    ...

    public boolean isTaskAllowed(Task task) {
        return skillSet.containsAll(task.getTaskType().getRequiredSkillList());
    }

    ...
}

Solver config

Pretty much copy-paste this. Just change the variableName attribute value (I guess to "orders") and the filters' class names.

  <constructionHeuristic>
    <queuedValuePlacer>
      <valueSelector id="1" variableName="tasks"/>
      <changeMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskAssignMoveFilter</filterClass>
        <valueSelector mimicSelectorRef="1"/>
      </changeMoveSelector>
    </queuedValuePlacer>
  </constructionHeuristic>
  <localSearch>
    <unionMoveSelector>
      <changeMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskChangeMoveFilter</filterClass>
      </changeMoveSelector>
      <swapMoveSelector>
        <filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskSwapMoveFilter</filterClass>
      </swapMoveSelector>
    </unionMoveSelector>
  </localSearch>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文