C# 如何在Google或Tools中限制路由持续时间?

C# 如何在Google或Tools中限制路由持续时间?,c#,mathematical-optimization,or-tools,C#,Mathematical Optimization,Or Tools,我正在研究路由优化问题,我发现自己陷入了僵局。 我使用或工具作为.Net核心的解算器 问题如下:当我处理时间窗口约束时,可能需要等待一些时间来适应某个位置时间窗口。这很好。解算器倾向于使用时间窗口约束位置作为第一个节点。这也很好。但这样的话,我们可能想把车辆的出发日期推迟一些。 因此,当我将路线持续时间限制设置为8小时时,我们在开始时有2小时的等待时间,结果是6小时的工作时间,这不是最优的。 我不知道如何通知解算器第一个节点的等待时间正在增加总持续时间 这里是文档链接: //这是我的时间维度

我正在研究路由优化问题,我发现自己陷入了僵局。 我使用或工具作为.Net核心的解算器

问题如下:当我处理时间窗口约束时,可能需要等待一些时间来适应某个位置时间窗口。这很好。解算器倾向于使用时间窗口约束位置作为第一个节点。这也很好。但这样的话,我们可能想把车辆的出发日期推迟一些。 因此,当我将路线持续时间限制设置为8小时时,我们在开始时有2小时的等待时间,结果是6小时的工作时间,这不是最优的。 我不知道如何通知解算器第一个节点的等待时间正在增加总持续时间

这里是文档链接:

//这是我的时间维度

        _routingModel.AddDimension(
            evaluator_index: _absoluteTimeCallbackIndex,
            slack_max: (long)TimeSpan.FromDays(1).TotalSeconds,
            capacity: (long)TimeSpan.FromDays(1).TotalSeconds,
            fix_start_cumul_to_zero: true,
            name: PlannerConstants.TIME_DIMENSION_NAME);
//这段代码正在设置时间窗口和持续时间约束

        var timeDimension = _routingModel.GetDimensionOrDie(PlannerConstants.TIME_DIMENSION_NAME);

        for (int locationNodeIndex = 0; locationNodeIndex < _targets.Count; locationNodeIndex++)
        {
            var location = _targets[locationNodeIndex].Location;
            var index = _manager.NodeToIndex(locationNodeIndex);

            var timeWindowMatch = new TimeWindowMatcher(_departureDate, location.TimeSlots.ToList())
                .GetTimeWindowsWithGaps();

            var start = (long)timeWindowMatch.WideTimeRange.From.TotalSeconds;
            var end = (long)timeWindowMatch.WideTimeRange.To.TotalSeconds;

            timeDimension
                .CumulVar(index)
                .SetRange(start, end);

            timeWindowMatch.TimeGaps.ForEach(gap =>
            {
                timeDimension
                    .CumulVar(index)
                    .RemoveInterval((long)gap.From.TotalSeconds, (long)gap.To.TotalSeconds);
            });
        }


        for (int vehicleNodeIndex = 0; vehicleNodeIndex < _vehicles.Count; vehicleNodeIndex++)
        {
            _routingModel
                .solver()
                .Add(RelativeDuration.DoesNotExeedLimit(_settings.MaximumRouteDuration, _routingModel, vehicleNodeIndex, _vehicles[vehicleNodeIndex]));
        }
var timeDimension=\u routingModel.getdimensionOrde(PlannerConstants.TIME\u DIMENSION\u NAME);
对于(int locationNodeIndex=0;locationNodeIndex<\u targets.Count;locationNodeIndex++)
{
变量位置=_目标[locationNodeIndex]。位置;
var指数=_manager.NodeToIndex(locationNodeIndex);
var timeWindowMatch=new TimeWindowMatcher(_departureDate,location.TimeSlots.ToList())
.GetTimeWindowWithGaps();
var start=(长)timeWindowMatch.WideTimeRange.From.TotalSeconds;
var end=(长)timeWindowMatch.WideTimeRange.To.TotalSeconds;
时间维度
.CumulVar(指数)
.设置范围(开始、结束);
timeWindowMatch.TimeGaps.ForEach(间隙=>
{
时间维度
.CumulVar(指数)
.RemoveInterval((长)间隙从.TotalSeconds,(长)间隙到.TotalSeconds);
});
}
对于(int vehicleNodeIndex=0;vehicleNodeIndex<\u vehicles.Count;vehicleNodeIndex++)
{
_路由模型
.solver()
.Add(RelativeDuration.doesnotexeedslimit(_settings.MaximumRouteDuration,_routingModel,vehicleNodeIndex,_vehicles[vehicleNodeIndex]));
}
公共类相关教育
{
公共静态约束不超过限制(时间跨度限制、路线模型路线、int车辆索引、路线车辆)
{
var timeDimension=routing.getdimensionOrde(PlannerConstants.TIME\u DIMENSION\u NAME);
var startSerconds=timeDimension.CumulVar(routing.Start(vehicleIndex));
var endSeconds=timeDimension.CumulVar(routing.End(vehicleIndex));
如果(vehicle.Type==VehicleType.Virual)
返回endSeconds<(长)PlannerConstants.infinition_WORKDAY_SECONDS;

return endSeconds好的!经过一周的搜索,终于找到了发布在这里的解决方案:

谢谢@ihadanny

我所需要的只是在时间维度上使用SetSpanUpperBoundForVehicle方法,将StartCumulZero设置为false

public class RelativeDuration
    {
        public static Constraint DoesNotExeedLimit(TimeSpan limit, RoutingModel routing, int vehicleIndex, RoutingVehicle vehicle)
        {
            var timeDimension = routing.GetDimensionOrDie(PlannerConstants.TIME_DIMENSION_NAME);

            var startSerconds = timeDimension.CumulVar(routing.Start(vehicleIndex));
            var endSeconds = timeDimension.CumulVar(routing.End(vehicleIndex));

            if (vehicle.Type == VehicleType.Virual)
                return endSeconds < (long) PlannerConstants.INFINITIVE_WORKDAY_SECONDS;

            return endSeconds <= (long) limit.TotalSeconds + startSerconds;
        }
    }