예제 #1
0
        /// <summary>
        /// Tests enumeration all edges.
        /// </summary>
        protected void DoTestEnumeratePairs()
        {
            // create a new empty route.
            IRoute route = this.BuildRoute(0, true);

            // do the enumerable.
            List <Edge> edges = new List <Edge>(route.Edges());

            Assert.AreEqual(0, edges.Count);

            if (route != null)
            { // this part needs testing!
                Assert.AreEqual(1, route.Count);
                Assert.AreEqual(false, route.IsEmpty);
                Assert.AreEqual(true, route.IsRound);

                for (int customer = 1; customer < 100; customer++)
                {
                    route.InsertAfter(customer - 1, customer);
                    //route.InsertAfterAndRemove(customer - 1, customer, -1);

                    edges = new List <Edge>(route.Edges());
                    Assert.AreEqual(customer + 1, edges.Count);

                    for (int edge_from = 0; edge_from < customer; edge_from++)
                    {
                        Assert.AreEqual(edges[edge_from].From, edge_from);
                        Assert.AreEqual(edges[edge_from].To, edge_from + 1);
                    }
                    Assert.AreEqual(edges[edges.Count - 1].From, edges.Count - 1);
                    Assert.AreEqual(edges[edges.Count - 1].To, 0);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Calculates the shortest route along all given points starting and ending at the given points.
        /// </summary>
        /// <param name="vehicle">The vehicle type.</param>
        /// <param name="points">The points to travel along.</param>
        /// <param name="first">The index of the point to start from.</param>
        /// <param name="isRound">Return back to the first point or not.</param>
        /// <returns></returns>
        public Route CalculateTSP(Vehicle vehicle, RouterPoint[] points, int first, bool isRound)
        {
            // calculate the weights.
            double[][] weights = this.CalculateManyToManyWeight(vehicle, points);

            // build the points array.
            var locations = new GeoCoordinate[points.Length];

            for (int idx = 0; idx < points.Length; idx++)
            {
                locations[idx] = points[idx].Location;
            }

            // calculates the TSP solution.
            IRoute tspSolution = _routerTSP.CalculateTSP(weights, locations, first, isRound);

            // calculate weight
            double weight = 0;

            foreach (Edge edge in tspSolution.Edges())
            {
                weight = weight + weights[edge.From][edge.To];
            }

            // concatenate the route(s).
            return(this.BuildRoute(vehicle, points, tspSolution, weight));
        }
예제 #3
0
        /// <summary>
        /// Calculates the time of one route.
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public double Time(IRoute route)
        {
            double time = 0;

            foreach (Edge edge in route.Edges())
            {
                time = time + this.WeightMatrix[edge.From][edge.To];
            }
            return(this.Time(time, route.Count));
        }
예제 #4
0
        /// <summary>
        /// Calculates the time of one route.
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public double Time(IRoute route)
        {
            double time = 0;

            //Edge? first = null;
            //Edge? last = null;
            foreach (Edge edge in route.Edges())
            {
                //if (!first.HasValue)
                //{
                //    first = edge;
                //    time = time + this.WeightMatrix[0][edge.From];
                //}
                time = time + this.WeightMatrix[edge.From][edge.To];
                //last = edge;
            }
            //if (last.HasValue)
            //{
            //    time = time + this.WeightMatrix[last.Value.To][0];
            //}
            return(this.Time(time, route.Count));
        }
예제 #5
0
        /// <summary>
        /// Executes a solver procedure.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            float lambda = _lambda;

            var vrpRouter =
                new CheapestInsertionSolverWithImprovements(problem.Max.Value, problem.DeliveryTime.Value, 10, 0.10f, true, _thresholdPercentage, true, 0.75f);
            MaxTimeSolution originalSolution = vrpRouter.Solve(
                problem);

            for (int roundX = 0; roundX < originalSolution.Count; roundX++)
            {             // keep looping on rounds.
                for (int roundY = 0; roundY < roundX; roundY++)
                {         // keep looping on rounds with a smaller index not equal to the current round.
                    if (roundX != roundY)
                    {     // routes are different.
                        if (this.Overlaps(problem, originalSolution.Route(roundX), originalSolution.Route(roundY)))
                        { // only check routes that overlap.
                            double tau           = double.MinValue;
                            var    penalizations = new Dictionary <Edge, int>();

                            //bool improvement = true;
                            //while (improvement)
                            //{ // keep looping until no more improvement is found.
                            //    improvement = false;

                            while (true)
                            { // keep trying to improve until the tau limit is exceeded.
                                // calculate the route sizes before.
                                double route1ActualBefore = problem.Time(originalSolution.Route(roundX));
                                double route2ActualBefore = problem.Time(originalSolution.Route(roundY));

                                // copy orignal solution.
                                var solution = (originalSolution.Clone() as MaxTimeSolution);

                                // apply penalties.
                                foreach (KeyValuePair <Edge, int> penalty in penalizations)
                                {
                                    problem.Penalize(penalty.Key, (double)penalty.Value * lambda);
                                }

                                // apply the inter-route improvements.
                                int countBefore = solution.Route(roundX).Count + solution.Route(roundY).Count;
                                int countAfter;
                                if (this.ImproveInterRoute(problem, solution, roundX, roundY, problem.Max.Value))
                                { // the improve inter route succeeded.
                                    if (!solution.IsValid())
                                    {
                                        throw new Exception();
                                    }
                                    //improvement_inter = true;

                                    countAfter = solution.Route(roundX).Count + solution.Route(roundY).Count;
                                    if (countBefore != countAfter)
                                    {
                                        throw new Exception();
                                    }

                                    // apply the intra-route improvements.
                                    solution[roundX] = this.ImproveIntraRoute(problem, solution.Route(roundX), solution[roundX]);
                                    solution[roundY] = this.ImproveIntraRoute(problem, solution.Route(roundY), solution[roundY]);

                                    // recalculate weights.
                                    solution[roundX] = problem.Time(solution.Route(roundX));
                                    solution[roundY] = problem.Time(solution.Route(roundY));
                                }

                                // check customer counts.
                                countAfter = solution.Route(roundX).Count + solution.Route(roundY).Count;
                                if (countBefore != countAfter)
                                {
                                    throw new Exception();
                                }

                                // undo the penalizations.
                                problem.ResetPenalizations();

                                // check against the orginal objective function.
                                double route1ActualAfter = problem.Time(solution.Route(roundX));
                                double route2ActualAfter = problem.Time(solution.Route(roundY));
                                if (route1ActualAfter + route2ActualAfter < route1ActualBefore + route2ActualBefore - 0.001 &&
                                    route1ActualAfter < problem.Max.Value && route2ActualAfter < problem.Max.Value)
                                { // there is improvement!
                                    originalSolution = solution;

                                    //improvement = true;

                                    OsmSharp.Logging.Log.TraceEvent("OsmSharp.Routing.VRP.NoDepot.MaxTime.VNS.GuidedVNS", TraceEventType.Information,
                                                                    "IMPROVEMENT: {0}->{1}",
                                                                    route1ActualBefore + route2ActualBefore, route1ActualAfter + route2ActualAfter);
                                }

                                // select arc to be penalized.
                                IRoute route1         = originalSolution.Route(roundX);
                                IRoute route2         = originalSolution.Route(roundY);
                                double u              = double.MinValue;
                                var    penalizingEdge = new Edge();
                                double totalP         = 0;
                                foreach (Edge edge in route1.Edges())
                                {
                                    int edgeP;
                                    if (!penalizations.TryGetValue(edge, out edgeP))
                                    {
                                        edgeP = 0;
                                    }
                                    totalP = totalP + edgeP;
                                    double edgeU = ((lambda * (double)edgeP) + problem.WeightMatrix[edge.From][edge.To]) /
                                                   ((double)edgeP + 1.0);
                                    if (u <= edgeU)
                                    {
                                        penalizingEdge = edge;
                                        u = edgeU;
                                    }
                                }
                                foreach (Edge edge in route2.Edges())
                                {
                                    int edgeP;
                                    if (!penalizations.TryGetValue(edge, out edgeP))
                                    {
                                        edgeP = 0;
                                    }
                                    totalP = totalP + edgeP;
                                    double edgeU = ((lambda * (double)edgeP) + problem.WeightMatrix[edge.From][edge.To]) /
                                                   ((double)edgeP + 1.0);
                                    if (u <= edgeU)
                                    {
                                        penalizingEdge = edge;
                                        u = edgeU;
                                    }
                                }

                                // actually penalize the edge.
                                int p;
                                if (!penalizations.TryGetValue(penalizingEdge, out p))
                                {
                                    p = 1;
                                }
                                else
                                {
                                    p++;
                                }
                                penalizations[penalizingEdge] = p;

                                // evaluate or set tau.
                                if (tau > double.MinValue)
                                {     // evaluate if penalizations should end.
                                    if (tau <= lambda * totalP)
                                    { // the penalization should end!
                                        break;
                                    }
                                }
                                else
                                { // first edge being penalized.
                                    tau = lambda * problem.WeightMatrix[penalizingEdge.From][penalizingEdge.To] / 10;
                                }
                            }
                        }
                    }
                }
            }
            return(originalSolution);
        }
예제 #6
0
        /// <summary>
        /// Applies inter-improvements by exchanging parts of the route(s).
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="solution"></param>
        /// <param name="route1_idx"></param>
        /// <param name="route2_idx"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public bool Improve(MaxTimeProblem problem, MaxTimeSolution solution,
                            int route1_idx, int route2_idx, double max)
        {
            int max_window = 40;

            IRoute route1 = solution.Route(route1_idx);
            IRoute route2 = solution.Route(route2_idx);

            int route1_customers = route1.Count;
            int route2_customers = route2.Count;

            double[] route1_cumul = problem.TimeCumul(route1);
            double[] route2_cumul = problem.TimeCumul(route2);

            // build all edge weights.
            List <Edge> route1_edges = new List <Edge>(route1.Edges());
            List <Edge> route2_edges = new List <Edge>(route2.Edges());

            double[] route1_weights = new double[route1_edges.Count];
            for (int idx = 0; idx < route1_edges.Count; idx++)
            {
                Edge edge = route1_edges[idx];
                route1_weights[idx] = problem.WeightMatrix[edge.From][edge.To];
            }
            double[] route2_weights = new double[route2_edges.Count];
            for (int idx = 0; idx < route2_edges.Count; idx++)
            {
                Edge edge = route2_edges[idx];
                route2_weights[idx] = problem.WeightMatrix[edge.From][edge.To];
            }

            List <EdgePair> route2_pairs = new List <EdgePair>();

            for (int i_idx = 0; i_idx < route2_edges.Count - 2; i_idx++)
            {
                Edge   i               = route2_edges[i_idx];
                double i_weight        = route2_weights[i_idx];
                double weight_before_i = route2_cumul[i_idx];

                int k_idx_max = route2_edges.Count;
                if (k_idx_max > i_idx + 2 + max_window)
                {
                    k_idx_max = i_idx + 2 + max_window;
                }
                for (int k_idx = i_idx + 2; k_idx < k_idx_max; k_idx++)
                {
                    Edge   k                    = route2_edges[k_idx];
                    double k_weight             = route2_weights[k_idx];
                    double weight_after_k       = route2_cumul[route2_cumul.Length - 1] - route2_cumul[k_idx + 1];
                    double weight_between_route = route2_cumul[k_idx] - route2_cumul[i_idx + 1];

                    route2_pairs.Add(new EdgePair()
                    {
                        First            = i,
                        FirstWeight      = i_weight,
                        Second           = k,
                        SecondWeight     = k_weight,
                        Between          = new List <int>(route2.Between(i.To, k.From)),
                        WeightTotal      = i_weight + k_weight,
                        WeightAfter      = weight_after_k,
                        WeightBefore     = weight_before_i,
                        WeightBetween    = weight_between_route,
                        CustomersBetween = k_idx - i_idx
                    });
                }
            }

            // build all edge pairs.
            for (int i_idx = 0; i_idx < route1_edges.Count - 2; i_idx++)
            {
                Edge   i               = route1_edges[i_idx];
                double i_weight        = route1_weights[i_idx];
                double weight_before_i = route1_cumul[i_idx];

                int k_idx_max = route1_edges.Count;
                if (k_idx_max > i_idx + 2 + max_window)
                {
                    k_idx_max = i_idx + 2 + max_window;
                }
                for (int k_idx = i_idx + 2; k_idx < k_idx_max; k_idx++)
                {
                    Edge   k                    = route1_edges[k_idx];
                    double k_weight             = route1_weights[k_idx];
                    double weight_after_k       = route1_cumul[route1_cumul.Length - 1] - route1_cumul[k_idx + 1];
                    double weight_between_route = route1_cumul[k_idx] - route1_cumul[i_idx + 1];

                    EdgePair pair1 = new EdgePair()
                    {
                        First            = i,
                        FirstWeight      = i_weight,
                        Second           = k,
                        SecondWeight     = k_weight,
                        Between          = new List <int>(route1.Between(i.To, k.From)),
                        WeightTotal      = i_weight + k_weight,
                        WeightAfter      = weight_after_k,
                        WeightBefore     = weight_before_i,
                        WeightBetween    = weight_between_route,
                        CustomersBetween = k_idx - i_idx
                    };

                    foreach (EdgePair pair2 in route2_pairs)
                    {
                        double existing_weight = pair1.WeightTotal + pair2.WeightTotal;

                        //double new_weight = 0;

                        // get first route new.
                        double new_weight = problem.WeightMatrix[pair1.First.From][pair2.First.To];
                        //new_weight = first_route1_new;
                        if (new_weight > existing_weight - 0.001)
                        {
                            continue;
                        }

                        double first_route2_new = problem.WeightMatrix[pair2.First.From][pair1.First.To];
                        new_weight = new_weight + first_route2_new;
                        if (new_weight > existing_weight - 0.001)
                        {
                            continue;
                        }

                        double second_route1_new = problem.WeightMatrix[pair1.Second.From][pair2.Second.To];
                        new_weight = new_weight + second_route1_new;
                        if (new_weight > existing_weight - 0.001)
                        {
                            continue;
                        }

                        double second_route2_new = problem.WeightMatrix[pair2.Second.From][pair1.Second.To];
                        new_weight = new_weight + second_route2_new;

                        if (new_weight < existing_weight - 0.001)
                        { // there is a decrease in total weight; check bounds.
                            double route1_weight = pair1.WeightBefore + pair2.WeightBetween + pair1.WeightAfter;
                            double route2_weight = pair2.WeightBefore + pair1.WeightBetween + pair2.WeightAfter;

                            // calculate the maximum.
                            int route1_customers_between = pair1.CustomersBetween;
                            int route2_customers_between = pair1.CustomersBetween;
                            route1_weight = problem.Time(route1_weight,
                                                         route1_customers - route1_customers_between + route2_customers_between);
                            route2_weight = problem.Time(route2_weight,
                                                         route2_customers - route2_customers_between + route1_customers_between);

                            if (route1_weight < max && route2_weight < max)
                            {
                                MaxTimeSolution solution_copy = solution.Clone() as MaxTimeSolution;

                                List <int> route1_between = pair1.Between;
                                List <int> route2_between = pair2.Between;

                                route1.ReplaceEdgeFrom(pair1.First.From, pair1.Second.To);
                                route2.ReplaceEdgeFrom(pair2.First.From, pair2.Second.To);

                                int previous = pair1.First.From;
                                for (int idx = 0; idx < route2_between.Count; idx++)
                                {
                                    route1.ReplaceEdgeFrom(previous, route2_between[idx]);
                                    previous = route2_between[idx];
                                }
                                route1.ReplaceEdgeFrom(previous, pair1.Second.To);

                                previous = pair2.First.From;
                                for (int idx = 0; idx < route1_between.Count; idx++)
                                {
                                    route2.ReplaceEdgeFrom(previous, route1_between[idx]);
                                    previous = route1_between[idx];
                                }
                                route2.ReplaceEdgeFrom(previous, pair2.Second.To);

                                if (!solution.IsValid())
                                {
                                    throw new Exception();
                                }
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
예제 #7
0
        /// <summary>
        /// Tries to relocate customers using the source the same as the CrossExchange but places customers using cheapest insertion.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="solution"></param>
        /// <param name="route1_idx"></param>
        /// <param name="route2_idx"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public bool Improve(MaxTimeProblem problem, MaxTimeSolution solution,
                            int route1_idx, int route2_idx, double max)
        {
            int max_window = 10;

            IRoute route1 = solution.Route(route1_idx);
            IRoute route2 = solution.Route(route2_idx);

            double total_before = problem.Time(solution.Route(route1_idx)) +
                                  problem.Time(solution.Route(route2_idx));

            int route1_customers = route1.Count;
            int route2_customers = route2.Count;

            double[] route1_cumul = problem.TimeCumul(route1);
            double[] route2_cumul = problem.TimeCumul(route2);

            // build all edge weights.
            List <Edge> route1_edges = new List <Edge>(route1.Edges());
            List <Edge> route2_edges = new List <Edge>(route2.Edges());

            double[] route1_weights = new double[route1_edges.Count];
            for (int idx = 0; idx < route1_edges.Count; idx++)
            {
                Edge edge = route1_edges[idx];
                route1_weights[idx] = problem.WeightMatrix[edge.From][edge.To];
            }
            double[] route2_weights = new double[route2_edges.Count];
            for (int idx = 0; idx < route2_edges.Count; idx++)
            {
                Edge edge = route2_edges[idx];
                route2_weights[idx] = problem.WeightMatrix[edge.From][edge.To];
            }

            List <EdgePair> route2_pairs = new List <EdgePair>();

            for (int i_idx = 0; i_idx < route2_edges.Count - 2; i_idx++)
            {
                Edge   i               = route2_edges[i_idx];
                double i_weight        = route2_weights[i_idx];
                double weight_before_i = route2_cumul[i_idx];

                int k_idx_max = route2_edges.Count;
                if (k_idx_max > i_idx + 2 + max_window)
                {
                    k_idx_max = i_idx + 2 + max_window;
                }
                for (int k_idx = i_idx + 2; k_idx < k_idx_max; k_idx++)
                {
                    Edge   k                    = route2_edges[k_idx];
                    double k_weight             = route2_weights[k_idx];
                    double weight_after_k       = route2_cumul[route2_cumul.Length - 1] - route2_cumul[k_idx + 1];
                    double weight_between_route = route2_cumul[k_idx] - route2_cumul[i_idx + 1];

                    route2_pairs.Add(new EdgePair()
                    {
                        First            = i,
                        FirstWeight      = i_weight,
                        Second           = k,
                        SecondWeight     = k_weight,
                        Between          = new List <int>(route2.Between(i.To, k.From)),
                        WeightTotal      = i_weight + k_weight,
                        WeightAfter      = weight_after_k,
                        WeightBefore     = weight_before_i,
                        WeightBetween    = weight_between_route,
                        CustomersBetween = k_idx - i_idx
                    });
                }
            }

            // try to relocate all and find best pair.
            double   route1_weight = route1_cumul[route1_cumul.Length - 1];
            EdgePair best          = null;
            CheapestInsertionResult best_result = new CheapestInsertionResult();
            double best_extra = double.MaxValue;

            foreach (EdgePair pair2 in route2_pairs)
            {
                // calculate cheapest insertion.
                CheapestInsertionResult result =
                    CheapestInsertionHelper.CalculateBestPlacement(problem, route1,
                                                                   pair2.First.To, pair2.Second.From);

                double extra_route2 = problem.WeightMatrix[pair2.First.From][pair2.Second.To];

                // check if the result has a net-decrease.
                if (result.Increase + extra_route2 < pair2.WeightTotal - 0.01)
                { // there is a net decrease.
                    // calculate the real increase.
                    double new_weight = problem.Time(route1_weight + result.Increase + pair2.WeightBetween, route1_customers +
                                                     pair2.CustomersBetween);

                    // check the max.
                    if (new_weight < max && new_weight < best_extra)
                    { // the route is smaller than max.
                        best_extra  = new_weight;
                        best_result = result;
                        best        = pair2;
                    }
                }
            }

            if (best != null)
            {
                if (route2.Last == best.Second.To)
                {
                    //throw new Exception();
                }
                route2.ReplaceEdgeFrom(best.First.From, best.Second.To);

                int previous = best_result.CustomerBefore;
                foreach (int customer in best.Between)
                {
                    route1.ReplaceEdgeFrom(previous, customer);

                    previous = customer;
                }
                route1.ReplaceEdgeFrom(previous, best_result.CustomerAfter);

                // check validity.
                if (!route2.IsValid())
                {
                    throw new Exception();
                }
                if (!route1.IsValid())
                {
                    throw new Exception();
                }

                if (route1.Count + route2.Count != route1_customers + route2_customers)
                {
                    throw new Exception();
                }

                double total_after = problem.Time(solution.Route(route1_idx)) +
                                     problem.Time(solution.Route(route2_idx));
                if (total_after >= total_before)
                {
                    throw new Exception("this is not an improvement!");
                }

                return(true);
            }
            return(false);
        }
예제 #8
0
 /// <summary>
 /// Calculates the time of one route.
 /// </summary>
 /// <param name="route"></param>
 /// <returns></returns>
 public double Time(IRoute route)
 {
     double time = 0;
     foreach(Edge edge in route.Edges())
     {
         time = time + this.WeightMatrix[edge.From][edge.To];
     }
     return this.Time(time, route.Count);
 }
예제 #9
0
        /// <summary>
        /// Try and merge route2 into route1.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="solution"></param>
        /// <param name="route1_idx"></param>
        /// <param name="route2_idx"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        private MergeResult TryMerge(MaxTimeProblem problem, MaxTimeSolution solution,
                                     int route1_idx, int route2_idx, double max)
        {
            // get the route weights.
            double route1_weight = solution[route1_idx];
            double route2_weight = solution[route2_idx];

            // creates a result.
            MergeResult result = new MergeResult();

            result.Weight = double.MaxValue;

            // get the two routes.
            IRoute route1 = solution.Route(route1_idx);
            IRoute route2 = solution.Route(route2_idx);

            // just first do the case where both routes are of zero length.
            if (route1.Count == 1 && route2.Count == 1)
            { // calculate the increase when joining the two points.
                foreach (int customer1 in route1)
                {
                    foreach (int customer2 in route2)
                    {
                        double difference = problem.WeightMatrix[customer1][customer2] +
                                            problem.WeightMatrix[customer2][customer1];
                        double new_route_weight = route1_weight + difference + route2_weight;
                        if (new_route_weight < max)
                        {
                            result.Weight               = difference;
                            result.RouteSourceId        = route2_idx;
                            result.RouteTargetId        = route1_idx;
                            result.CustomerSourceSource = customer2;
                            result.CustomerSourceTarget = customer2;
                            result.CustomerTargetSource = customer1;

                            return(result);
                        }
                    }
                }
            }

            foreach (Edge route1_edge in route1.Edges())
            { // loop over all route1 edges.
                // calculate weight of the current edge.
                double route1_edge_weight  = problem.WeightMatrix[route1_edge.From][route1_edge.To];
                double route1_edge_without = route1_weight - route1_edge_weight;

                if (route2.Count == 1)
                { // there is only one customer.
                    foreach (int customer2 in route2)
                    {
                        //// calculate weight of the current edge.
                        //double route2_edge_weight = problem.WeightMatrix[route2_edge.From][route2_edge.To];
                        //double route2_edge_without = route2_weight - route2_edge_weight;

                        double new_edges_weight = problem.WeightMatrix[route1_edge.From][customer2] +
                                                  problem.WeightMatrix[customer2][route1_edge.To];

                        double difference = problem.WeightDifferenceAfterMerge(solution,
                                                                               new_edges_weight - (route1_edge_weight));

                        // check if the max bound is not violated.
                        double new_route_weight = route1_edge_without + difference + route2_weight; // the customer remain the same.
                        if (new_route_weight < max)
                        {
                            // the difference is smaller than the current result.
                            if (difference < result.Weight)
                            {
                                result.Weight               = difference;
                                result.RouteSourceId        = route2_idx;
                                result.RouteTargetId        = route1_idx;
                                result.CustomerSourceSource = customer2;
                                result.CustomerSourceTarget = customer2;
                                result.CustomerTargetSource = route1_edge.From;
                            }
                        }
                    }
                }
                else
                {     // there is at least one edge.
                    foreach (Edge route2_edge in route2.Edges())
                    { // loop over all route2 edges.
                        // calculate weight of the current edge.
                        double route2_edge_weight  = problem.WeightMatrix[route2_edge.From][route2_edge.To];
                        double route2_edge_without = route2_weight - route2_edge_weight;

                        double new_edges_weight = problem.WeightMatrix[route1_edge.From][route2_edge.To] +
                                                  problem.WeightMatrix[route2_edge.From][route1_edge.To];

                        double difference = problem.WeightDifferenceAfterMerge(solution,
                                                                               new_edges_weight - (route1_edge_weight + route2_edge_weight));

                        // check if the max bound is not violated.
                        double new_route_weight = route1_edge_weight + route2_edge_without + new_edges_weight; // the customer remain the same.
                        if (new_route_weight < max)
                        {
                            // the difference is smaller than the current result.
                            if (difference < result.Weight)
                            {
                                result.Weight               = difference;
                                result.RouteSourceId        = route2_idx;
                                result.RouteTargetId        = route1_idx;
                                result.CustomerSourceSource = route2_edge.To;
                                result.CustomerSourceTarget = route2_edge.From;
                                result.CustomerTargetSource = route1_edge.From;
                            }
                        }
                    }
                }
            }
            return(result);
        }
예제 #10
0
 /// <summary>
 /// Calculates the time of one route.
 /// </summary>
 /// <param name="route"></param>
 /// <returns></returns>
 public double Time(IRoute route)
 {
     double time = 0;
     //Edge? first = null;
     //Edge? last = null;
     foreach (Edge edge in route.Edges())
     {
         //if (!first.HasValue)
         //{
         //    first = edge;
         //    time = time + this.WeightMatrix[0][edge.From];
         //}
         time = time + this.WeightMatrix[edge.From][edge.To];
         //last = edge;
     }
     //if (last.HasValue)
     //{
     //    time = time + this.WeightMatrix[last.Value.To][0];
     //}
     return this.Time(time, route.Count);
 }