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

在TimeFold中实现PreviousStandstill变更:现成方法是否存在?自研代码可行吗?

TimeFold VRP: ProblemChange for Route Adjustment

Does TimeFold have built-in support for this?

TimeFold does not provide out-of-the-box ProblemChange implementations for modifying VRP routes (like moving a customer to a new position). This is because route adjustment use cases vary widely (insertions, swaps, reorders) and require customization to fit specific business rules. However, the core ProblemChange API is designed exactly for this kind of manual modification of the solution state, so your approach of implementing a custom ProblemChange is valid.

Code Review & Corrections

Your code attempts to modify a customer's previousStandstill, but it has several issues that will prevent it from working correctly in all scenarios. Here's a breakdown of the problems and how to fix them:

Key Issues in Your Current Code

  1. Ignores Vehicles as previousStandstill: Your loop only checks customers, but previousStandstill can be a Vehicle (the start of a route). This means inserting a customer at the beginning of a vehicle's route will fail.
  2. Inefficient lookup of the next customer: Instead of looping through all customers to find the one following previousStandstill, you can directly access previousStandstill.getNextCustomer() (a standard method in VRP domain models).
  3. Direct field modifications without change tracking: You're setting fields like setPreviousStandstill directly, but TimeFold requires using ProblemChangeDirector.changeProperty() to track these changes for accurate score recalculation.
  4. Unnecessary complexity in insertion logic: The current loop-based approach overcomplicates connecting the customer to its new position.

Corrected Implementation

Here's a revised version of your PreviousStandstillChange class that addresses these issues:

public class PreviousStandstillChange implements ProblemChange<VehicleRoutingSolution> {

    private final TimeWindowedCustomer customerToMove;
    private final Standstill newPreviousStandstill;

    public PreviousStandstillChange(TimeWindowedCustomer customerToMove, Standstill newPreviousStandstill) {
        this.customerToMove = customerToMove;
        this.newPreviousStandstill = newPreviousStandstill;
    }

    @Override
    public void doChange(VehicleRoutingSolution workingSolution, ProblemChangeDirector changeDirector) {
        // Get working clones of the objects (critical for TimeFold's state management)
        TimeWindowedCustomer workingCustomer = changeDirector.lookUpWorkingObjectOrFail(customerToMove);
        Standstill workingNewPrevious = changeDirector.lookUpWorkingObjectOrFail(newPreviousStandstill);

        // Step 1: Disconnect the customer from its current position
        Standstill currentPrevious = workingCustomer.getPreviousStandstill();
        TimeWindowedCustomer currentNext = workingCustomer.getNextCustomer();

        if (currentPrevious != null) {
            changeDirector.changeProperty(currentPrevious, "nextCustomer", currentNext);
        }
        if (currentNext != null) {
            changeDirector.changeProperty(currentNext, "previousStandstill", currentPrevious);
        }

        // Step 2: Connect the customer to its new position
        TimeWindowedCustomer nextAfterNewPrevious = workingNewPrevious.getNextCustomer();

        // Update the customer's previous and next
        changeDirector.changeProperty(workingCustomer, "previousStandstill", workingNewPrevious);
        changeDirector.changeProperty(workingCustomer, "nextCustomer", nextAfterNewPrevious);

        // Update the new previous standstill's next
        changeDirector.changeProperty(workingNewPrevious, "nextCustomer", workingCustomer);

        // Update the customer that was after the new previous (if exists)
        if (nextAfterNewPrevious != null) {
            changeDirector.changeProperty(nextAfterNewPrevious, "previousStandstill", workingCustomer);
        }
    }
}

Key Improvements

  • Handles both Vehicle and Customer as previousStandstill: Uses workingNewPrevious.getNextCustomer() which works for both types of Standstill.
  • Proper change tracking: Uses changeDirector.changeProperty() to notify TimeFold of every modification, ensuring accurate score recalculation.
  • Simplified logic: Breaks the operation into clear disconnect/connect steps, making the code easier to maintain and debug.
  • Null safety: Properly checks for null values when updating relationships.

Usage Notes

  • Ensure your domain model (Vehicle, TimeWindowedCustomer) implements the necessary getters/setters for previousStandstill and nextCustomer.
  • After applying this ProblemChange, you can trigger a score calculation or continue optimizing the solution with TimeFold's solver.

内容的提问来源于stack exchange,提问作者elk-tamer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:55:30