/// <summary> /// Returns the <see cref="NodeTiming"/> for the next node /// </summary> /// <returns></returns> public NodeTiming GetNodeTiming(INode currentNode, INode nextNode, DateTime currentNodeEndTime, RouteStatistics currentRouteStatistics) { var connection = GetNodeConnection(currentNode, nextNode); DateTime nextNodeArrivalTime = currentNodeEndTime + connection.LocalRouteStatistics.TotalTime; bool isFirstStop = currentNode is DriverNode; // determine if time arrived within time window and calculate wait time bool early = nextNodeArrivalTime < nextNode.WindowStart; bool late = nextNodeArrivalTime > nextNode.WindowEnd; bool isFeasableTimeWindow = false; TimeSpan waitTime = TimeSpan.Zero; if (early) { waitTime = nextNode.WindowStart.Subtract(nextNodeArrivalTime); TimeSpan maxWaitTime = isFirstStop ? _configuration.MaximumWaitTimeBeforeStart : _configuration.MaximumWaitTimeAtStop; isFeasableTimeWindow = waitTime < maxWaitTime; } else if (late) { // we started past the time window isFeasableTimeWindow = false; } else { isFeasableTimeWindow = true; } DateTime nextNodeStartTime = nextNodeArrivalTime + waitTime; DateTime nextNodeEndTime = nextNodeStartTime + nextNode.LocalRouteStatistics.TotalTime; RouteStatistics cumulativeRouteStatistics = currentRouteStatistics + connection.LocalRouteStatistics + nextNode.LocalRouteStatistics; var result = new NodeTiming() { Node = nextNode, ArrivalTime = nextNodeArrivalTime, StartTime = nextNodeStartTime, EndTime = nextNodeEndTime, IsFeasableTimeWindow = isFeasableTimeWindow, CumulativeRouteStatistics = cumulativeRouteStatistics }; //var st = (result.ArrivalTime - DateTime.Now.Date).TotalMinutes; //var et = (result.EndTime - DateTime.Now.Date).TotalMinutes; //Console.WriteLine("{0},{1},{2}", nextNode, st, et); return(result); }
/// <summary> /// Calculates the probability of selecting a given node /// </summary> public virtual double CalculateProbability(INode currentNode, NodeTiming nodeTiming) { if (currentNode == null) { throw new ArgumentNullException("currentNode"); } if (nodeTiming == null) { throw new ArgumentNullException("nodeTiming"); } var node = nodeTiming.Node; var pheromone = PheromoneMatrix.GetValue(currentNode, node); double topProbability = 1.0; if (pheromone > 0) { if (Alpha > 0) { topProbability *= Math.Pow(pheromone, Alpha); } var routeStatistics = _routeStatisticsService.GetRouteStatistics(currentNode, node, nodeTiming.EndExecutionTime); var performanceMeasure = _objectiveFunction.GetObjectiveMeasure(routeStatistics); if (Beta > 0 && performanceMeasure > 0) { topProbability *= Math.Pow(1 / performanceMeasure, Beta); } } var priority = Math.Max(node.Priority, 1); if (Zeta > 0) { topProbability *= 1 + Math.Pow(Zeta, priority); } return(topProbability); }
/// <summary> /// Calculates the probability of selecting a given node /// </summary> public virtual double CalculateProbability(INode currentNode, NodeTiming nodeTiming) { var node = nodeTiming.Node as NodeBase; var pheromone = PheromoneMatrix.GetValue(currentNode, node); double topProbability = 1.0; if (pheromone > 0) { if (Alpha > 0) { topProbability *= Math.Pow(pheromone, Alpha); } } var routeStatistics = _routeService.CalculateRouteStatistics(currentNode, node); var performanceMeasure = _objectiveFunction.GetObjectiveMeasure(routeStatistics); if (Beta > 0 && performanceMeasure > 0) { topProbability *= Math.Pow(1 / performanceMeasure, Beta); } if (node.Priority > 1) { ; } var priority = Math.Max(node.Priority, 1); if (Zeta > 0) { topProbability *= 1 + Math.Pow(Zeta, priority); } return(topProbability); }
/// <summary> /// Returns the <see cref="NodeTiming"/> for the next node /// </summary> /// <returns></returns> public virtual NodeTiming GetNodeTiming(INode startNode, INode endNode, TimeSpan startNodeEndTime, RouteStatistics currentRouteStatistics) { bool isFirstStop = startNode is DriverNode; var connectionRouteStatistics = GetRouteStatistics(startNode, endNode, startNodeEndTime); var originalStartNodeEndTime = startNodeEndTime.Ticks; if (isFirstStop) { var travelTime = connectionRouteStatistics.TotalTravelTime.Ticks; var driverStartTime = originalStartNodeEndTime; var jobNodeEnd = endNode.WindowEnd.Ticks; var jobNodeStart = endNode.WindowStart.Ticks; startNodeEndTime = TimeSpan.FromTicks(Math.Max(jobNodeEnd - travelTime, driverStartTime)); startNodeEndTime = TimeSpan.FromTicks(Math.Max(jobNodeStart - travelTime, driverStartTime)); } TimeSpan endNodeArrivalTime = startNodeEndTime + connectionRouteStatistics.TotalTravelTime; // cbs 16 Sep 14 Scheduling Night Shift starts with day orders if (endNodeArrivalTime.Days > 0) { endNodeArrivalTime = endNodeArrivalTime.Add(TimeSpan.FromDays(endNodeArrivalTime.Days * -1)); } // determine if time arrived within time window and calculate wait time var firstStopWaitMinutes = isFirstStop ? endNodeArrivalTime.Subtract(TimeSpan.FromTicks(originalStartNodeEndTime)).TotalMinutes : 0; var isDriverAlreadyLate = startNodeEndTime > endNode.WindowEnd; var isFirstStopWithinDelayPeriod = isFirstStop && !isDriverAlreadyLate && firstStopWaitMinutes <= _configuration.MaximumIdleTimeBeforeStart.TotalMinutes; bool early = endNodeArrivalTime <= endNode.WindowStart; bool late = (endNodeArrivalTime > endNode.WindowEnd) || (isFirstStop && !isFirstStopWithinDelayPeriod); bool isFeasableTimeWindow = false; TimeSpan idleTime = TimeSpan.Zero; if (early) { // if we are early to make it to the first stop, there's no need to wait, we will // adjust the nextNodeArrivalTime to reflect the windowStartTime of the first // location to goto. if (!isFirstStop) { idleTime = endNode.WindowStart.Subtract(endNodeArrivalTime); } else { startNodeEndTime = endNode.WindowStart - connectionRouteStatistics.TotalTime; startNodeEndTime = endNode.WindowStart - connectionRouteStatistics.TotalNonIdleTime; endNodeArrivalTime = startNodeEndTime + connectionRouteStatistics.TotalTravelTime; idleTime = endNode.WindowStart.Subtract(endNodeArrivalTime); } var maxIdleTime = isFirstStop ? _configuration.MaximumIdleTimeBeforeStart : _configuration.MaximumIdleTimeAtStop; isFeasableTimeWindow = idleTime < maxIdleTime; } else if (late) { // we started past the time window isFeasableTimeWindow = false; } else { isFeasableTimeWindow = true; } var endNodeRouteStatistics = GetRouteStatistics(endNode, endNodeArrivalTime); TimeSpan queueTime = endNodeRouteStatistics.TotalQueueTime; TimeSpan nextNodeStartTime = endNodeArrivalTime + idleTime; TimeSpan nextNodeEndTime = nextNodeStartTime + endNodeRouteStatistics.TotalTime; // wait? RouteStatistics localRouteStatistics = new RouteStatistics() { TotalIdleTime = idleTime }; RouteStatistics cumulativeRouteStatistics = currentRouteStatistics + connectionRouteStatistics + endNodeRouteStatistics + localRouteStatistics; var result = new NodeTiming() { Node = endNode, DepartureTime = startNodeEndTime.Ticks, ArrivalTime = endNodeArrivalTime, StartExecutionTime = nextNodeStartTime, IdleTime = isFirstStop ? TimeSpan.Zero : idleTime, QueueTime = queueTime, EndExecutionTime = nextNodeEndTime, IsFeasableTimeWindow = isFeasableTimeWindow, CumulativeRouteStatistics = cumulativeRouteStatistics }; return(result); }
/// <summary> /// Returns the <see cref="NodeTiming"/> for the next node /// </summary> /// <returns></returns> public virtual NodeTiming GetNodeTiming(INode startNode, INode endNode, TimeSpan currentNodeEndTime, RouteStatistics currentRouteStatistics) { var connection = GetNodeConnection(startNode, endNode); TimeSpan nextNodeArrivalTime = currentNodeEndTime + connection.RouteStatistics.TotalTime; TimeSpan nextNodeCompletionTime = endNode.RouteStops != null ? nextNodeArrivalTime.Add( endNode.RouteStops.FirstOrDefault().StopDelay.Value) : nextNodeArrivalTime; bool isFirstStop = startNode is DriverNode; bool early = nextNodeArrivalTime < endNode.WindowStart; bool late = nextNodeArrivalTime > endNode.WindowEnd; bool isFeasableTimeWindow = false; TimeSpan waitTime = TimeSpan.Zero; if (early) { waitTime = endNode.WindowStart.Subtract(nextNodeArrivalTime); TimeSpan maxWaitTime = isFirstStop ? _configuration.MaximumWaitTimeBeforeStart : _configuration.MaximumWaitTimeAtStop; isFeasableTimeWindow = waitTime < maxWaitTime; if (isFirstStop && isFeasableTimeWindow) { waitTime = TimeSpan.Zero; currentNodeEndTime = endNode.WindowStart - connection.RouteStatistics.TotalTime; nextNodeArrivalTime = currentNodeEndTime + connection.RouteStatistics.TotalTime; } } else if (late) { // we started past the time window isFeasableTimeWindow = false; } else { isFeasableTimeWindow = true; } var cumulatingCompletionTime = new TimeSpan(nextNodeCompletionTime.Ticks); if (isFeasableTimeWindow) { // make sure that the following subsequent route stops would not be violated if (endNode is JobNode) { var jn = endNode as JobNode; for (int i=1; i<jn.RouteStops.Count; i++) { var rs = jn.RouteStops[i]; var rsConnection = GetNodeConnection( new JobNode() { RouteStops = new List<RouteStop>() { jn.RouteStops[i - 1] }, }, new JobNode() { RouteStops = new List<RouteStop>() { rs } }); var nextStopArrivalTime = cumulatingCompletionTime.Add(rsConnection.RouteStatistics.TotalTravelTime); bool isWaitRequired = nextStopArrivalTime <= rs.WindowStart; cumulatingCompletionTime = isWaitRequired ? rs.WindowStart.Add(rs.StopDelay.Value) : nextStopArrivalTime.Add(rs.StopDelay.Value); for (int q=i; q < jn.RouteStops.Count; q++) { var nextStop = jn.RouteStops[q]; bool nextStopEarly = cumulatingCompletionTime < nextStop.WindowStart; bool nextStopLate = cumulatingCompletionTime > nextStop.WindowEnd; if (nextStopLate) { isFeasableTimeWindow = false; } else if (nextStopEarly) { // todo - check to see waiting time, driver limits } } } } } TimeSpan nextNodeStartTime = nextNodeArrivalTime + waitTime; TimeSpan nextNodeEndTime = nextNodeStartTime + endNode.RouteStatistics.TotalTime; RouteStatistics localRouteStatistics = new RouteStatistics() {TotalWaitTime = waitTime}; RouteStatistics cumulativeRouteStatistics = currentRouteStatistics + connection.RouteStatistics + endNode.RouteStatistics + localRouteStatistics; var result = new NodeTiming() { Node = endNode, DepartureTime = currentNodeEndTime, ArrivalTime = nextNodeArrivalTime, StartExecutionTime = nextNodeStartTime, EndExecutionTime = cumulatingCompletionTime, IsFeasableTimeWindow = isFeasableTimeWindow, CumulativeRouteStatistics = cumulativeRouteStatistics }; return result; }