java - 未更新 ProblemFact 中具有 InverseRelationShadowVariable 的 PlanningEntity 字段 - Optaplanner
问题描述
我有一个引用影子计划实体的ProblemFact (没有PlanningVariable,只有一个引用PlanningEntity的InverseRelationShadowVariable)AgentAvailability
Agent
Agent
Shift
这是我的类定义:
Shift.class
@PlanningEntity
public class Shift extends AbstractPersistable implements Comparable<Shift> {
@PlanningVariable(valueRangeProviderRefs = { "agentRange" }, nullable = true)
private Agent agent;
private Spot spot;
private LocalDateTime startDateTime;
private LocalDateTime endDateTime;
//Constructor, getters, setters and JPA annotations removed for clarity
Agent.class
@PlanningEntity
public class Agent implements Comparable<Agent> {
@PlanningId
private long registrationNumber;
private String username;
private boolean pro;
private SortedSet<Skill> skillSet = new TreeSet<>();
@InverseRelationShadowVariable(sourceVariableName = "agent")
private SortedSet<Shift> shiftSet = new TreeSet<>();
//Constructor, getters, setters and JPA annotations removed for clarity
AgentAvailability.class
public class AgentAvailability extends AbstractPersistable implements Comparable<AgentAvailability> {
private Agent agent;
private LocalDateTime startDateTime;
private LocalDateTime endDateTime;
//Constructor, getters, setters and JPA annotations removed for clarity
这是我的解决方案定义:
Schedule.class
@PlanningSolution
public class Schedule extends AbstractPersistable {
// ...
@ProblemFactCollectionProperty
@ValueRangeProvider(id = "agentRange")
private List<Agent> agentList = new ArrayList<>();
@ProblemFactCollectionProperty
private List<AgentAvailability> agentAvailabilities = new ArrayList<>();
@PlanningEntityCollectionProperty
private List<Shift> shifts = new ArrayList<>();
// ...
//Constructor, getters, setters and JPA annotations removed for clarity
inverseShadowVariable正在按预期工作:当将 an分配Agent
给 a时Shift
,分配的shiftSet
the 将Agent
使用此班次进行更新。
问题出agent
在AgentAvailability
.
据我了解,当 Optaplanner 根据文档克隆解决方案时,它会重用 ProblemFacts 的实例,并使用克隆来规划实体。
因为AgentAvailability
这是一个事实,我假设它被重用(在调试器视图中,情况就是这样,初始问题和找到的最佳解决方案之间的实例是相同的)
Agent
fromSchedule
也被正确地克隆shiftSet
到解决方案中。
但问题是agent
字段 inAgentAvailability
仍然是Agent
原始问题的实例。
因此,实例中的字段仍然shiftSet
为空。agent
AgentAvailability
它是在最后找到的 bestSolution 中出现的情况,而且在计算过程中也是如此。
因此,我不能使用这样的约束:
return constraintFactory.from(AgentAvailability.class)
.groupBy(AgentAvailability::getAgent, count())
.filter((agent, availabilities) -> availabilities - agent.getShiftSet().size() > 0)
.penalizeConfigurableLong(ShiftSchedulingConstraintConfiguration.PRO_HAS_SHIFT, (agent, availabilities) -> availabilities - agent.getShiftSet().size());
因为agent.getShiftSet().size()
即使代理已分配到班次,也始终返回 0。
一种可能的解决方法是使用 from(Agent.class) 子句,并加入 AgentAvailabilities 和 Shift 以从Agent
实体“重建”shiftSet。但是有什么方法可以从Agent
实体中“克隆”shiftSet Agent
,以便我可以使用更新后的AgentAvailability
代理字段?AgentAvailability
shiftSet
解决方案
这是您的模型的问题。你不能期望AgentAvailability
两者都被克隆。如果AgentAvailability
是问题事实,则不会克隆,因此agent
不会更改 的值。
(旁注:也许我们应该检测一个实体是否从计划事实中引用,并快速失败?我不明白这种情况如何导致除了麻烦之外的任何事情。)
这个问题有几种解决方案。我建议您制作Agent
一个问题事实并创建一个新实体AgentAssignment
,将 1 对 1 映射到Agent
. 在此模型中,您可以自由引用Agent
其他事实中的事实实例。
然后约束变得相对容易编写。
from(AgentAssignment.class)
.join(AgentAvailability.class,
Joiners.equal(
AgentAssignment::getAgent,
AgentAvailability::getAgent))
.groupBy(
(agentAssignment, agentAvailability) -> agentAssignment,
countBi())
.filter((agentAssignment, availabilities) -> availabilities - agentAssignment.getShiftSet().size() > 0)
...
推荐阅读
- excel - 运行时错误 1004 vba 方法范围对象 _global 失败
- javascript - 为什么在 ECMAScript 规范中将语句称为子句?
- reactjs - skipWaiting() 没有安装卡在等待阶段的新服务工作者
- php - html表单不发送数据
- django - 为什么我的代码不能与环境变量一起正常工作?
- python - 如何减少执行时间(Python)
- arrays - 具有可变内容类型和长度的元组数组?
- html - 如果我使用 github 页面托管我的网站,如何缩短我的网址?
- javascript - 用于附加属性子项计数的递归对象数组
- reactjs - 使用 react.js 创建产品后如何正确显示产品预览页面