/// <summary> /// Add time window constraints for each location except depot. /// </summary> /// <param name="scope"></param> /// <see cref="!:https://developers.google.com/optimization/routing/vrptw#time_window_constraints"/> private void OnArrangeVehicleTimeWindows(TimeWindowCaseStudyScope scope) { var this_Context_DepotCoords = this.Context.DepotCoordinates.ToArray(); // Instead of assuming "0" is the Depot, here we scan "around" the known Depot coordinates. bool DepotCoordinatesDoNotContain(int _) => !this_Context_DepotCoords.Contains(_); // TODO: TBD: we may want to follow a similar tract here re: RC versus RoutingIndexManager... // TODO: TBD: however we just prefer to abstract those sorts of bits through the RC... // TODO: TBD: if there is a case for it, we will, but for now, the interface is sufficient... void OnSetCumulVarTimeWindow(int node, in (long start, long end) timeWin) => this.SetCumulVarRange( node, timeWin, (RoutingContext _, int i) => _.NodeToIndex(i) ); void OnSetCumulVarRange(int node) => OnSetCumulVarTimeWindow( node , scope.TimeWindows.ElementAt(node) ); // Add Time Window constraints for each Node except the Depot(s). Enumerable.Range(default, this.Context.NodeCount)
/// <summary> /// Constructs the dimension. /// </summary> /// <param name="context"></param> /// <param name="scope"></param> /// <see cref="!:https://developers.google.com/optimization/routing/tsp#distance_callback"/> /// <see cref="!:https://developers.google.com/optimization/routing/dimensions#slack_variables"/> /// <see cref="!:https://github.com/google/or-tools/discussions/2298">Concerning slack</see> public TimeWindowDimension(RoutingContext context, TimeWindowCaseStudyScope scope) : base(context, scope.DimensionCoefficient) { if (this.Coefficient > 0) { this.Scope = scope; var evaluatorIndex = this.RegisterTransitEvaluationCallback(this.OnEvaluateTransit); // TODO: TBD: I'm not sure we actually ever add the dimension here ... // TODO: TBD: should review the example again to make sure that we actually should/are/do... (take your pick) this.SetArcCostEvaluators(evaluatorIndex); // TODO: TBD: with parameters that could be captured in a context, etc... this.AddDimension(evaluatorIndex, scope.VehicleCap, scope.SlackMaximumOrDefault, scope.ZeroAccumulatorOrDefault); // Arrange the several constraints dealing with the vehicles, start, end, etc. this.OnArrangeVehicleTimeWindows(scope); this.OnArrangeVehicleStartTimeWindows(scope); this.OnArrangeVehicleStartEndFinalizers(scope); } }