Ejemplo n.º 1
0
        /// <summary>
        /// Computes the simple backhaul count for the given route solution
        /// </summary>
        /// <param name="routeSolution">the route solution from which backhauls are counted</param>
        /// <returns>the sum of JobNodes plus DriverNodes minus 1</returns>
        public int CalculateNumberOfBackhauls(NodeRouteSolution routeSolution)
        {
            int result = 0;

            result = routeSolution.Nodes.Count - 1;
            return(result);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Computes the TruckPerformanceStatistics for a given route solution
        /// </summary>
        /// <param name="routeSolution">The route from which statistics are generated</param>
        /// <returns>The performance statistics for the truck</returns>
        public TruckPerformanceStatistics CalculateTruckPerformanceStatistics(NodeRouteSolution routeSolution)
        {
            var segmentStats = GetRouteSegmentStats(routeSolution);

            // calculate the statistics by truck state
            var statsByTructState = (from segment in segmentStats
                                     group segment by segment.TruckState into g
                                     select new
            {
                TruckState = g.Key,
                Statistics = g.Aggregate(new RouteStatistics(), (seed, segment) => seed + segment.Statistics)
            })
                                    .ToDictionary(key => key.TruckState, value => value.Statistics);

            // compute the sum of all the route statistics
            var totalRouteStatistics = segmentStats.Aggregate(new RouteStatistics(), (seed, segment) => seed + segment.Statistics);

            var performanceStatistics = CalculatePerformanceStatistics(routeSolution);

            var truckStatistics = new TruckPerformanceStatistics
            {
                RouteStatisticsByTruckState = statsByTructState,
                RouteStatistics             = totalRouteStatistics,
                PerformanceStatistics       = performanceStatistics,
                RouteSegmentStatistics      = segmentStats
            };

            return(truckStatistics);
        }
Ejemplo n.º 3
0
        ///// <summary>
        ///// Creates a route solution from a list of nodes
        ///// </summary>
        ///// <param name="nodes"></param>
        ///// <returns></returns>
        public NodeRouteSolution CreateRouteSolution(IEnumerable <INode> nodes, DriverNode driverNode)
        {
            var routeSolution = new NodeRouteSolution
            {
                DriverNode = driverNode,
                StartTime  = driverNode.Driver.EarliestStartTime,
                Nodes      = nodes.ToList()
            };

            var allNodes = routeSolution.AllNodes;

            // calculate route statistics
            for (int i = 0; i < allNodes.Count; i++)
            {
                // create node plan
                var node = allNodes[i];

                // add node trip length
                routeSolution.RouteStatistics += node.RouteStatistics;

                var previousNode = i == 0 ? null : allNodes[i - 1];
                if (previousNode != null)
                {
                    var statistics = CalculateRouteStatistics(previousNode, node);
                    routeSolution.RouteStatistics += statistics;
                }
            }

            return(routeSolution);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns true if the given route solution is feasable within time windows and exit criteria
        /// </summary>
        /// <param name="nodeRouteSolution"></param>
        /// <returns></returns>
        public bool IsFeasableRouteSolution(NodeRouteSolution nodeRouteSolution)
        {
            var driverNode                = nodeRouteSolution.DriverNode;
            var currentNodeEndTime        = driverNode.Driver.EarliestStartTime;
            var cumulativeRouteStatistics = new RouteStatistics();
            var allNodes = nodeRouteSolution.AllNodes;

            for (int i = 0; i < allNodes.Count - 1; i++)
            {
                var nodeTiming = _nodeService.GetNodeTiming(allNodes[i], allNodes[i + 1], currentNodeEndTime, cumulativeRouteStatistics);

                if (nodeTiming.IsFeasableTimeWindow)
                {
                    // is it a feasable route
                    var lastConnection       = _nodeService.GetNodeConnection(nodeTiming.Node, driverNode);
                    var finalRouteStatistics = nodeTiming.CumulativeRouteStatistics + lastConnection.RouteStatistics;

                    if (_routeExitFunction.ExeedsExitCriteria(finalRouteStatistics, driverNode.Driver))
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }

                currentNodeEndTime        = nodeTiming.EndExecutionTime;
                cumulativeRouteStatistics = nodeTiming.CumulativeRouteStatistics;
            }

            return(true);
        }
Ejemplo n.º 5
0
        public IList <RouteStop> GetRouteStopsForRouteSolution(NodeRouteSolution routeSolution)
        {
            var allNodes = routeSolution.AllNodes;

            var routeStops = new List <RouteStop>();

            routeStops.AddRange(allNodes[0].RouteStops);

            // calculate route statistics
            for (int i = 1; i < allNodes.Count; i++)
            {
                // create node plan
                var node = allNodes[i];

                var previousNode = allNodes[i - 1];
                if (previousNode != null)
                {
                    var nodeConnection = _nodeService.GetNodeConnection(previousNode, node);
                    if (nodeConnection.RouteStops != null)
                    {
                        routeStops.AddRange(nodeConnection.RouteStops);
                    }
                }

                routeStops.AddRange(node.RouteStops);
            }

            return(routeStops);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the route segment stats.
        /// </summary>
        /// <param name="routeSolution">The route solution.</param>
        /// <returns>a list of statistics for each leg of the route</returns>
        public IList <RouteSegmentStatistics> GetRouteSegmentStats(NodeRouteSolution routeSolution)
        {
            var startTime    = routeSolution.StartTime;
            var routeStops   = _routeService.GetRouteStopsForRouteSolution(routeSolution);
            var segmentStats = _routeStopService.CalculateRouteSegmentStatistics(startTime, routeStops);

            return(segmentStats);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Computes the performance statistics for a given route solution
        /// </summary>
        /// <param name="routeSolution">The solution from which the report is generated</param>
        /// <returns>the statistics generated from the route</returns>
        private PerformanceStatistics CalculatePerformanceStatistics(NodeRouteSolution routeSolution)
        {
            var result = new PerformanceStatistics()
            {
                NumberOfJobs = routeSolution.JobCount,
                DriverDutyHourUtilization = routeSolution.RouteStatistics.TotalTime.TotalHours / routeSolution.DriverNode.Driver.AvailableDutyTime.TotalHours,
                DriverDrivingUtilization  = routeSolution.RouteStatistics.TotalTravelTime.TotalHours / routeSolution.DriverNode.Driver.AvailableDrivingTime.TotalHours,
                DrivingTimePercentage     = routeSolution.RouteStatistics.TotalTravelTime.TotalHours / routeSolution.RouteStatistics.TotalTime.TotalHours,
                WaitingTimePercentage     = routeSolution.RouteStatistics.TotalIdleTime.TotalHours / routeSolution.RouteStatistics.TotalTime.TotalHours,
                NumberOfBackhauls         = CalculateNumberOfBackhauls(routeSolution),
                NumberOfLoadmatches       = CalculateNumberOfLoadMatches(routeSolution)
            };

            return(result);
        }
Ejemplo n.º 8
0
        public NodeRouteSolution GetBestSolution(NodeRouteSolution left, NodeRouteSolution right)
        {
            double prioritySumLeft       = left.AllNodes.Sum(f => f.Priority);
            double prioritySumRight      = right.AllNodes.Sum(f => f.Priority);
            int    priorityCompareResult = prioritySumLeft.CompareTo(prioritySumRight);

            if (priorityCompareResult == 0)
            {
                return(_statisticsService.CompareRouteStatistics(left.RouteStatistics, right.RouteStatistics) > 0
                           ? right
                           : left);
            }

            // return the solution with the highest priority sum
            return(priorityCompareResult > 0 ? left : right);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the best solution between a new list of <see cref="INode"/> and a current best <see cref="NodeRouteSolution"/>
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="driverNode"> </param>
        /// <param name="bestSolution"></param>
        /// <returns>the best solution</returns>
        public NodeRouteSolution GetBestFeasableSolution(IEnumerable <INode> nodes, DriverNode driverNode, NodeRouteSolution bestSolution)
        {
            // create solution
            var routeSolution = CreateRouteSolution(driverNode, nodes);

            // check feasibility
            if (IsFeasableRouteSolution(routeSolution))
            {
                if (bestSolution != null)
                {
                    routeSolution = GetBestSolution(bestSolution, routeSolution);
                }
            }
            else
            {
                routeSolution = bestSolution;
            }

            return(routeSolution);
        }
Ejemplo n.º 10
0
        public NodeRouteSolution GetBestSolution(NodeRouteSolution left, NodeRouteSolution right)
        {
            double prioritySumLeft  = left.AllNodes.Sum(f => f.Priority);
            double prioritySumRight = right.AllNodes.Sum(f => f.Priority);

            // set driver count
            var leftRs = left.RouteStatistics;

            leftRs.DriversWithAssignments = left.Nodes.Count > 0 ? 1 : 0;
            left.RouteStatistics          = leftRs;

            var rightRs = right.RouteStatistics;

            rightRs.DriversWithAssignments = right.Nodes.Count > 0 ? 1 : 0;
            right.RouteStatistics          = rightRs;

            //if (leftRs.DriversWithAssignments > 0 || rightRs.DriversWithAssignments > 0)
            //{
            //    ;
            //}
            int priorityCompareResult = prioritySumLeft.CompareTo(prioritySumRight);

            if (priorityCompareResult == 0)
            {
                return(_routeStatisticsComparer.Compare(left.RouteStatistics, right.RouteStatistics) > 0
                           ? right
                           : left);
            }

            return(_routeStatisticsComparer.Compare(left.RouteStatistics, right.RouteStatistics) > 0
           ? right
           : left);

            // return the solution with the highest priority sum
            //return priorityCompareResult > 0 ? left : right;
            var result = _routeStatisticsComparer.Min(left, right);

            return(result);
            //return _routeStatisticsComparer.Compare(left.RouteStatistics, right.RouteStatistics) > 0 ? right : left;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Computes the number of load maches for the given route solution
        /// </summary>
        /// <param name="routeSolution">the solution from which the count is retrieved</param>
        /// <returns>the count of liveloading followed by live unloading stops along the route</returns>
        public int CalculateNumberOfLoadMatches(NodeRouteSolution routeSolution)
        {
            int result = 0;

            // iterates through node collection
            foreach (var node in routeSolution.Nodes)
            {
                bool hasLiveUnloading = false;
                bool hasBoth          = false;

                foreach (var routeStop in node.RouteStops)
                {
                    if (routeStop.StopAction == StopActions.LiveUnloading)
                    {
                        hasLiveUnloading = true;
                    }
                    else
                    {
                        if (hasLiveUnloading && routeStop.StopAction == StopActions.LiveLoading)
                        {
                            hasBoth = true;
                        }
                        else if (hasLiveUnloading && routeStop.StopAction != StopActions.LiveLoading)
                        {
                            hasLiveUnloading = false;
                            hasBoth          = false;
                        }
                    }

                    if (hasBoth)
                    {
                        result++;
                        hasLiveUnloading = false;
                        hasBoth          = false;
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 12
0
        public IList <RouteStop> GetRouteStopsForRouteSolution(NodeRouteSolution routeSolution)
        {
            var allNodes = routeSolution.AllNodes;

            var routeStops = new List <RouteStop>();

            foreach (var rs in allNodes[0].RouteStops)
            {
                routeStops.Add(rs);
            }


            // calculate route statistics
            for (int i = 1; i < allNodes.Count; i++)
            {
                // create node plan
                var node = allNodes[i];
                routeStops.AddRange(node.RouteStops);
            }

            return(routeStops);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Creates our route assignments by processing all the drivers and getting their routes
        /// </summary>
        /// <returns></returns>
        public virtual Solution ProcessDrivers(IList <DriverNode> driverNodes, Driver placeholderDriver, IList <INode> jobNodes)
        {
            var solution = new Solution();

            if (jobNodes.Count == 0)
            {
                return(solution);
            }

            var availableNodes = jobNodes;

            var realDriverNodes = driverNodes.Where(f => f.Driver != placeholderDriver)
                                  .OrderBy(f => _randomNumberGenerator.Next()); // random sort order

            var placeholderDriverNodes = driverNodes.Where(f => f.Driver == placeholderDriver);

            // going through all the real drivers
            foreach (var driverNode in realDriverNodes)
            {
                // get the route solution for this particular driver
                var nodeRouteSolution = new NodeRouteSolution();
                nodeRouteSolution = GenerateIterativeRouteSolution(availableNodes, driverNode);

                // insert solution
                solution.RouteSolutions.Add(nodeRouteSolution);

                // update available nodes based on new solution
                var selectedIds = nodeRouteSolution.Nodes.Select(p => p.Id).ToList();
                availableNodes = availableNodes.Where(p => !selectedIds.Contains(p.Id)).ToList();
                if (availableNodes.Count == 0)
                {
                    break;
                }
            }

            // try using placeholder drivers
            if (availableNodes.Count > 0)
            {
                foreach (var driverNode in placeholderDriverNodes)
                {
                    // get the route solution for this particular driver
                    var nodeRouteSolution = GenerateIterativeRouteSolution(availableNodes, driverNode);

                    // don't bother if we didn't generate a solution
                    if (nodeRouteSolution.Nodes.Count == 0)
                    {
                        break;
                    }

                    // insert solution
                    solution.RouteSolutions.Add(nodeRouteSolution);

                    // update available nodes based on new solution
                    availableNodes = availableNodes.Where(n => !nodeRouteSolution.Nodes.Contains(n)).ToList();
                    if (availableNodes.Count == 0)
                    {
                        break;
                    }
                }
            }

            // Add unassigned job nodes
            solution.UnassignedJobNodes.AddRange(availableNodes);

            return(solution);
        }
Ejemplo n.º 14
0
        ///// <summary>
        ///// Creates a route solution from a list of nodes
        ///// </summary>
        ///// <param name="nodes"></param>
        ///// <returns></returns>
        public NodeRouteSolution CreateRouteSolution(DriverNode driverNode, IEnumerable <INode> nodes)
        {
            var startTime    = driverNode.Driver.EarliestStartTimeSpan;
            var firstJobNode = nodes.FirstOrDefault();

            // adjust the start time
            if (firstJobNode != null)
            {
                // there may have been waiting for the driver to leave, do not count that as idle time
                // update the currentTime to the JobNode WindowEnd, less travel time
                var connection = _nodeService.GetNodeConnection(driverNode, nodes.First());
                if (firstJobNode.WindowEnd.Subtract(connection.RouteStatistics.TotalTravelTime) > startTime)
                {
                    startTime = firstJobNode.WindowEnd.Subtract(connection.RouteStatistics.TotalTravelTime);
                }
            }


            var routeSolution = new NodeRouteSolution
            {
                DriverNode = driverNode,
                StartTime  = startTime,
                Nodes      = nodes.ToList()
            };

            var allNodes = routeSolution.AllNodes;


            var currentTime = startTime;

            // calculate route statistics
            for (int i = 0; i < allNodes.Count; i++)
            {
                // create node plan
                var node         = allNodes[i];
                var previousNode = i > 0 ? allNodes[i - 1] : null;

                // insert waiting time as per JobNode windows
                if (i >= 1 && node is JobNode && previousNode is JobNode)
                {
                    // there may have been waiting for the driver to leave, do not count that as idle time
                    // update the currentTime to the JobNode WindowEnd, less travel time
                    var connection = _nodeService.GetNodeConnection(previousNode, node);
                    if (node.WindowEnd.Subtract(connection.RouteStatistics.TotalTravelTime) > currentTime)
                    {
                        // waiting found
                        var waitingTime       = node.WindowEnd.Subtract(currentTime);
                        var currentStatistics = routeSolution.RouteStatistics;
                        currentStatistics.TotalIdleTime = currentStatistics.TotalIdleTime.Add(waitingTime);
                        routeSolution.RouteStatistics   = currentStatistics;
                        currentTime = currentTime.Add(waitingTime);
                    }
                }

                // add node trip length
                var stats = _routeStatisticsService.GetRouteStatistics(node, currentTime, previousNode);
                routeSolution.RouteStatistics += stats;

                // currentTime = startTime + routeSolution.RouteStatistics.TotalTime;

                if (previousNode != null)
                {
                    var statistics = _routeStatisticsService.GetRouteStatistics(previousNode, node, currentTime);
                    routeSolution.RouteStatistics += statistics;
                }

                currentTime = startTime + routeSolution.RouteStatistics.TotalTime;
            }

            return(routeSolution);
        }