You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Timefold Python中ArrivalTimeUpdatingVariableListener未运行问题求助

解决ArrivalTimeUpdatingVariableListener未运行的问题

以下是针对Timefold Python中ArrivalTimeUpdatingVariableListener未触发问题的排查与修复步骤:

  • 确认Shadow Variable的注解配置
    检查你的Customer规划实体中,arrival_time字段的@shadow_variable注解是否正确关联了Listener类和源变量:

    @planning_entity
    class Customer:
        # 其他规划变量/字段
        _arrival_time: Optional[float] = None
    
        @shadow_variable(
            variable_listener_class=ArrivalTimeUpdatingVariableListener,
            source_variable_name="previous_customer"  # 必须指向触发更新的源变量(如前序客户)
        )
        def arrival_time(self) -> Optional[float]:
            return self._arrival_time
    
        @arrival_time.setter
        def arrival_time(self, value: Optional[float]) -> None:
            self._arrival_time = value
    

    注意source_variable_name必须是实体中存在的规划变量(如previous_customer),只有当该变量的值发生变化时,Listener才会被触发。

  • 验证Listener类的实现规范
    确保你的Listener正确继承自VariableListener,并实现了必要的方法。至少要在after_variable_changed方法中处理源变量变化后的更新逻辑,示例模板:

    from timefold_solver.core.api.score.stream.variable import VariableListener
    
    class ArrivalTimeUpdatingVariableListener(VariableListener[Customer]):
        def before_entity_added(self, score_director, customer):
            # 可选实现,按需添加调试print
            pass
    
        def after_entity_added(self, score_director, customer):
            # 可选实现,按需添加调试print
            pass
    
        def before_variable_changed(self, score_director, customer):
            # 可选实现,按需添加调试print
            pass
    
        def after_variable_changed(self, score_director, customer):
            # 这里是核心逻辑,当source变量变化时触发
            print("Listener triggered for customer:", customer.id)
            # 编写更新arrival_time及后续节点时间的逻辑
            self.update_arrival_time(score_director, customer)
    
        def update_arrival_time(self, score_director, customer):
            # 自定义更新逻辑:根据previous_customer的到达时间+服务时间计算当前客户到达时间
            current_customer = customer
            while current_customer is not None:
                previous_customer = current_customer.previous_customer
                if previous_customer is None:
                    # 车辆起点,到达时间为0或车辆出发时间
                    new_arrival_time = 0.0
                else:
                    new_arrival_time = previous_customer.arrival_time + previous_customer.service_time + \
                        self.calculate_travel_time(previous_customer, current_customer)
                if current_customer.arrival_time != new_arrival_time:
                    score_director.before_variable_changed(current_customer, "arrival_time")
                    current_customer.arrival_time = new_arrival_time
                    score_director.after_variable_changed(current_customer, "arrival_time")
                current_customer = current_customer.next_customer
    

    注意:必须调用score_director.before_variable_changed和after_variable_changed来更新shadow变量,否则求解器无法识别变量变化。

  • 检查Listener的触发条件
    VariableListener仅在关联的源变量(如previous_customer)发生变化时运行。如果你的求解场景中,初始解或求解过程中该源变量未被修改,Listener自然不会触发。可以手动构造一个包含链式previous_customer的测试用例,或者在求解器启动前手动修改某个客户的previous_customer值,验证Listener是否输出调试信息。

  • 确认求解器的实体扫描范围
    确保Customer实体类和ArrivalTimeUpdatingVariableListener类都在求解器配置的扫描路径内。如果使用代码配置求解器,可通过SolverFactory.create_from_xml_file或SolverConfig的entity_package_list、domain_package_list指定扫描包,避免类被遗漏。

  • 调试Listener的注册状态
    可以在求解器启动后,通过以下代码检查Listener是否被正确注册:

    solver = solver_factory.build_solver()
    variable_listener_manager = solver.get_score_director().get_variable_listener_manager()
    # 遍历已注册的Listener,确认你的类在其中
    for ref in variable_listener_manager.get_variable_listener_refs():
        print("Registered listener:", ref.variable_listener_class)
    

内容的提问来源于stack exchange,提问作者Siddharth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:46:09