For my vehicle routing problem, each node has a time by which we'd like to have visited it (time window constraints).
All of my time windows begin at 0 seconds (equivalent of 11am for me). Many of the nodes have a end time window of 11pm, but some of them need to be visited earlier.
My current solution is able to enforce these constraints using the following (here's just a snippet, lmk if more context is necessary):
def add_time_window_constraints(
routing: pywrapcp.RoutingModel, data: dict, time_callback
):
"""
Add time window constraints.
"""
time = "Time"
horizon = 60 * 60 * 20
routing.AddDimension(
evaluator=time_callback,
slack_max=0,
capacity=horizon, # maximum time per vehicle
# Don't force start cumul to zero. This doesn't have any effect in this example,
# since the depot has a start window of (0, 0).
fix_start_cumul_to_zero=False,
name=time,
)
time_dimension = routing.GetDimensionOrDie(time)
for loc_node, (open_time, close_time) in enumerate(data["time_windows"]):
index = routing.NodeToIndex(loc_node)
time_dimension.CumulVar(index).SetRange(open_time, close_time)
# encourages equal distribution of work across teams
time_dimension.SetGlobalSpanCostCoefficient(100)
Getting to my question:
I would like to reward the solver for visiting certain nodes earlier in the day. A node might, for example, have a hard deadline of being visited by 3 pm, but I would be happier if it were visited earlier in the day.
Some nodes have this "the earlier the visit, the better" quality, while some do not.
Does anyone out there have a recommendation of the best way to do that?
Please let me know if my explanation needs clarification.
This probably needs the following labels:
Help NeededSolver: RoutingSolverLang: PythonOS: MacOne point, you can't visit a node outside of hard limit (i.e. domain range), this why they are soft, for time windows you can see limits sorted like this:
0 -> Hard lower bound -> Soft lower bound -> Soft upper bound -> Hard upper bound -> horizon
When the Node is not visited, will the 'soft' cost be 0?
Thank you! I believe that a soft upper bound is what I need.
How should I think about the way the coefficient that I use on the soft upper bound interacts with the coefficient that I'm using with time_dimension.SetGlobalSpanCostCoefficient(100)?
Most helpful comment
This probably needs the following labels:
Help NeededSolver: RoutingSolverLang: PythonOS: Mac