/// <summary> /// Generates node sequence iteration /// </summary> /// <param name="nodes"></param> /// <param name="driverNode"> </param> /// <returns></returns> public virtual NodeRouteSolution GenerateRouteSolution(IList <INode> nodes, DriverNode driverNode) { IList <INode> processedNodes = new List <INode>(); INode currentNode = driverNode; var startTime = driverNode.Driver.EarliestStartTime; var currentNodeEndTime = startTime; var cumulativeRouteStatistics = new RouteStatistics(); int exitCounter = 0; while (exitCounter++ < 1000) { // getting avaiable nodes that have not been processed var feasibleNodeTimings = GetFeasibleNodes(nodes, driverNode, processedNodes, currentNodeEndTime, cumulativeRouteStatistics); if (!feasibleNodeTimings.Any()) { break; } var feasibleNodeTimingsByNode = feasibleNodeTimings.ToDictionary(f => f.Node); // build probability matrix for the available nodes var probabilityData = _probabilityMatrix.BuildProbabilityDataMatrix(currentNode, feasibleNodeTimings); // find a suitable node based on the cumulative probability var selectedNode = (INode)_probabilityMatrix.GetNominatedElement(probabilityData); processedNodes.Add(selectedNode); currentNode = selectedNode; // now we update the current node's end time var selectedNodeTiming = feasibleNodeTimingsByNode[selectedNode]; if (processedNodes.Count == 1 && selectedNodeTiming.DepartureTime != currentNodeEndTime) { startTime = selectedNodeTiming.DepartureTime; } currentNodeEndTime = selectedNodeTiming.EndExecutionTime; cumulativeRouteStatistics = selectedNodeTiming.CumulativeRouteStatistics; } // create solution object var result = _routeService.CreateRouteSolution(processedNodes, driverNode); result.StartTime = startTime; return(result); }
/// <summary> /// Generates node sequence iteration /// </summary> /// <param name="nodes"></param> /// <param name="driverNode"> </param> /// <returns></returns> public virtual NodeRouteSolution GenerateRouteSolution(IList <INode> nodes, DriverNode driverNode) { IList <INode> processedNodes = new List <INode>(); INode currentNode = driverNode; var startTime = driverNode.Driver.EarliestStartTimeSpan; var currentNodeEndTime = startTime; var cumulativeRouteStatistics = new RouteStatistics(); int exitCounter = 0; while (exitCounter++ < 1000) { // getting avaiable nodes that have not been processed var feasibleNodeTimings = GetFeasibleNodes(nodes, driverNode, processedNodes, currentNodeEndTime, cumulativeRouteStatistics); if (!feasibleNodeTimings.Any()) { break; } var feasibleNodeTimingsByNode = feasibleNodeTimings.ToDictionary(f => f.Node); // build probability matrix for the available nodes var probabilityData = _probabilityMatrix.BuildProbabilityDataMatrix(currentNode, feasibleNodeTimings); // find a suitable node based on the cumulative probability var selectedNode = (INode)_probabilityMatrix.GetNominatedElement(probabilityData); selectedNode.DepartureTime = feasibleNodeTimingsByNode[selectedNode].DepartureTime; // set the Departure Time // break if we nominated the driver node if (selectedNode == driverNode) { break; } processedNodes.Add(selectedNode); currentNode = selectedNode; // now we update the current node's end time var selectedNodeTiming = feasibleNodeTimingsByNode[selectedNode]; if (processedNodes.Count == 1 && selectedNodeTiming.DepartureTime != currentNodeEndTime.Ticks) { startTime = new TimeSpan(selectedNodeTiming.DepartureTime); } currentNodeEndTime = selectedNodeTiming.EndExecutionTime; cumulativeRouteStatistics = selectedNodeTiming.CumulativeRouteStatistics; var processedRouteStops = processedNodes.SelectMany(x => x.RouteStops); var provisionalRouteStops = new Queue <RouteStop>(); foreach (var processedRouteStop in processedRouteStops) { provisionalRouteStops.Enqueue(processedRouteStop); } foreach (var routeStop in selectedNode.RouteStops) { provisionalRouteStops.Enqueue(routeStop); } var tempJob = new Job { RouteStops = provisionalRouteStops.Select(x => x).ToList() }; var tempJobNode = _jobNodeService.CreateJobNode(tempJob, driverNode.Driver.EarliestStartTimeSpan, false); if (!tempJobNode.IsInvalid) { var serviceTimeIndex = _jobNodeService.GetMatrixIndex("ServiceTime"); var waitTimeIndex = _jobNodeService.GetMatrixIndex("WaitTime"); var travelTimeIndex = _jobNodeService.GetMatrixIndex("TravelTime"); var entryCount = tempJobNode.RouteStatisticsMatrix.GetLength(1); var travelTime = TimeSpan.Zero; var serviceTime = TimeSpan.Zero; var waitTime = TimeSpan.Zero; for (var i = 0; i < entryCount; i++) { travelTime += TimeSpan.FromSeconds(tempJobNode.RouteStatisticsMatrix[travelTimeIndex, i]); serviceTime += TimeSpan.FromSeconds(tempJobNode.RouteStatisticsMatrix[serviceTimeIndex, i]); waitTime += TimeSpan.FromSeconds(tempJobNode.RouteStatisticsMatrix[waitTimeIndex, i]); } var statistics = new RouteStatistics { TotalExecutionTime = serviceTime, TotalIdleTime = waitTime, TotalTravelTime = travelTime, TotalQueueTime = TimeSpan.Zero }; if (!_routeExitFunction.ExeedsExitCriteria(statistics, driverNode.Driver)) { processedNodes.Add(selectedNode); driverNode.Driver.EarliestStartTime = tempJobNode.WindowStart.Ticks; } } } // create solution object, adjust start time var result = _routeService.CreateRouteSolution(driverNode, processedNodes); var driverStartTicks = Math.Max(driverNode.Driver.EarliestStartTime, startTime.Ticks); result.StartTime = TimeSpan.FromTicks(driverStartTicks); var s = string.Join("\t", result.Nodes.Select(f => "[" + f.Id + "]").ToArray()); Console.WriteLine(s); Console.WriteLine(result.RouteStatistics.ToString()); return(result); }