optapy 中的影子变量未按预期更新

Shadow variable in optapy is not updated as expected

对我来说很有意义,但如果我尝试将推理应用于下面的代码(基于 optapy 中可用的员工调度示例),我会期望 set_timeslot_listset_task 被调用时被调用,但它看起来不像是。

优化运行正常并找到一组合适的任务分配给我可用的时间段列表,但每个 task.timeslot_list 仍然是空的,看起来 set_timeslot_list 方法是从来没有打电话。

我想我遗漏了一些东西..你能帮我理解我在下面的代码中修改示例的方式有什么问题吗?或者我正在解释影子变量的工作原理? 我可以提供更长的片段,或者 @planning_solution class 如果这还不够。

@planning_entity(pinning_filter=timeslot_pinning_filter)
class Timeslot:
    def __init__(self, start: datetime.datetime = None, end: datetime.datetime = None,
             location: str = None, required_skill: str = None, task: object = None):
        self.start = start
        self.end = end
        self.location = location
        self.required_skill = required_skill
        self.task = task

        @planning_id
        def get_id(self):
            return self.id

        # The type of the planning variable is Task, but we cannot use it because task refers to Timeslot below.
        @planning_variable(object, value_range_provider_refs=['task_range'], nullable=False)
        def get_task(self):
            return self.task

        def set_task(self, task):
            self.task = task
    

@planning_entity
class Task:
    def __init__(self, name: str = None, duration: int = None, skill_set: list = None):
        self.name = name
        self.duration = duration
        self.skill_set = skill_set
        self.timeslot_list = [] #The shadow property, which is a list, can never be None. If no genuine variable references that shadow entity, then it is an empty list

    @inverse_relation_shadow_variable(Timeslot, source_variable_name = "task")
    def get_timeslot_list(self):
        return self.timeslot_list

    def set_timeslot_list(self, ts):
        self.timeslot_list = ts

Inverse Relation Shadow 变量的工作方式与其他变量不同:特别是,它们直接修改 get_timeslot_list 返回的列表,因此永远不会调用 set_timeslot_list。您的代码看起来正确,这让我相信您正在检查原始规划实体而不是解决方案规划实体。在 OptaPy(和 OptaPlanner)中,每当我们找到新的最佳解决方案时,就会克隆有效的 solution/planning 解决方案。结果,原始问题(和原始规划实体)从未被触及。因此,如果您的代码看起来类似于:

solver = optapy.solver_factory_create(...).buildSolver()
timeslot_list = [...]
task_1 = Task(...)
task_2 = Task(...)
task_list = [task_1, task_2]
problem = EmployeeSchedulingProblem(timeslot_list, task_list, ...)
solution = solver.solve(problem)
# this is incorrect; it prints the timeslot_list of the original problem
print(task_1.timeslot_list)

应该改为:

solver = optapy.solver_factory_create(...).buildSolver()
timeslot_list = [...]
task_1 = Task(...)
task_2 = Task(...)
task_list = [task_1, task_2]
problem = EmployeeSchedulingProblem(timeslot_list, task_list, ...)
solution = solver.solve(problem)
# this is correct; it prints the timeslot_list of the solution
print(solution.task_list[0].timeslot_list)