示例#1
0
        /// <summary>
        /// Tries all 3Opt Moves for the neighbourhood of v_1 containing v_3.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="weights"></param>
        /// <param name="route"></param>
        /// <param name="v1"></param>
        /// <param name="v_2"></param>
        /// <param name="weight_1_2"></param>
        /// <param name="v_3"></param>
        /// <returns></returns>
        public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route,
                                 int v1, int v_2, double weight_1_2,
                                 int v_3)
        {
            // get v_4.
            int    v_4 = route.GetNeigbours(v_3)[0];
            double weight_1_2_plus_3_4 = weight_1_2 + weights[v_3][v_4];
            double weight_1_4          = weights[v1][v_4];

            double[] weights_3 = weights[v_3];
            return(this.Try3OptMoves(problem, weights, route, v1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4));
        }
示例#2
0
        /// <summary>
        /// Do get neighbour tests.
        /// </summary>
        protected void DoTestGetNeighbours()
        {
            int count = 10;

            IRoute route = this.BuildRoute(true);

            if (route != null)
            { // this part needs testing.
                for (int customer = 0; customer < count; customer++)
                {
                    route.InsertAfter(customer - 1, customer);
                    //route.InsertAfterAndRemove(customer - 1, customer, -1);
                }
            }

            int[] neighbours;
            for (int customer = 0; customer < count - 1; customer++)
            {
                neighbours = route.GetNeigbours(customer);
                Assert.IsTrue(neighbours[0] == customer + 1);
            }
            neighbours = route.GetNeigbours(count - 1);
            Assert.IsTrue(neighbours[0] == 0);
        }
        /// <summary>
        /// Tries to improve the existing route using CI and return true if succesful.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="difference"></param>
        /// <returns></returns>
        public bool Improve(IProblemWeights problem, IRoute route, out double difference)
        {
            bool improvement = false;

            difference = 0;
            if (route.Count > 3)
            {
                // loop over all customers and try cheapest insertion.
                for (int customer = 0; customer < problem.Size; customer++)
                {
                    //string route_string = route.ToString();
                    //IRoute previous = route.Clone() as IRoute;
                    if (route.Contains(customer))
                    {
                        // remove customer and keep position.
                        int next = route.GetNeigbours(customer)[0];
                        route.Remove(customer);

                        // insert again.
                        ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference);

                        if (!route.IsValid())
                        {
                            throw new Exception();
                        }
                        if (route.GetNeigbours(customer)[0] != next &&
                            difference < 0)
                        { // another customer was found as the best, improvement is succesful.
                            improvement = true;
                            break;
                        }
                    }
                }
            }
            return(improvement);
        }
示例#4
0
 /// <summary>
 /// Returns the neighbours of the given customer.
 /// </summary>
 /// <param name="customer"></param>
 /// <returns></returns>
 public int[] GetNeigbours(int customer)
 {
     //int[] neighbour;
     //if (customer == 0)
     //{
     //    neighbour = new int[1];
     //    neighbour[0] = _route.First;
     //}
     //else if (_route.Last == customer)
     //{
     //    neighbour = new int[1];
     //    neighbour[0] = 0;
     //}
     return(_route.GetNeigbours(customer));
 }
        /// <summary>
        /// Returns the customer after the given customer.
        /// </summary>
        /// <param name="customer"></param>
        /// <returns></returns>
        public int Next(int customer)
        {
            int next = _next_array[customer];

            if (next < 0)
            {
                for (int idx = 0; idx < this.Count; idx++)
                {
                    IRoute route = this.Route(idx);
                    if (route.Contains(customer) &&
                        route.GetNeigbours(customer)[0] == route.First)
                    {
                        return(route.First);
                    }
                }
            }
            return(next);
        }
示例#6
0
        /// <summary>
        /// Tries all 3Opt Moves for the neighbourhood of v_1.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="weights"></param>
        /// <param name="route"></param>
        /// <param name="v1"></param>
        /// <returns></returns>
        public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route, int v1)
        {
            // get v_2.
            int v_2 = route.GetNeigbours(v1)[0];

            if (v_2 < 0)
            {
                return(false);
            }
            IEnumerable <int> between_v_2_v_1 = route.Between(v_2, v1);
            double            weight_1_2      = weights[v1][v_2];
            int v_3 = -1;
            NearestNeighbours10 neighbours = null;

            if (_nearest_neighbours)
            {
                neighbours = problem.Get10NearestNeighbours(v1);
            }

            foreach (int v_4 in between_v_2_v_1)
            {
                if (v_3 >= 0 && v_3 != v1)
                {
                    //if (!_nearest_neighbours ||
                    //    neighbours.Max <= weight_1_4)
                    if (!_nearest_neighbours ||
                        neighbours.Contains(v_4))
                    {
                        double   weight_1_4          = weights[v1][v_4];
                        double   weight_1_2_plus_3_4 = weight_1_2 + weights[v_3][v_4];
                        double[] weights_3           = weights[v_3];
                        if (this.Try3OptMoves(problem, weights, route, v1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4))
                        {
                            return(true);
                        }
                    }
                }
                v_3 = v_4;
            }
            return(false);
        }
        /// <summary>
        /// Applies inter-improvements by exchanging customers.
        /// </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)
        {
            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));

            double route1_size = solution[route1_idx];
            double route2_size = solution[route2_idx];

            // this heuristic removes a customer1 from route1 and a customer2 from route2 and inserts the customers again
            // but swappes them; customer1 in route2 and customer2 in route1.
            int previous_customer1 = -1;

            //if (route1.IsRound)
            //{
            //    previous_customer1= route1.Last; // set the previous customer.
            //}
            foreach (int customer1 in route1)
            {     // loop over all customers in route1.
                if (previous_customer1 >= 0)
                { // the previous customer is set.
                    int next_customer1 = route1.GetNeigbours(customer1)[0];
                    if (next_customer1 < 0)
                    {
                        continue;
                    }

                    int previous_customer2 = -1;
                    //if (route2.IsRound)
                    //{
                    //    previous_customer2 = route2.Last; // set the previous customer.
                    //}

                    foreach (int customer2 in route2)
                    { // loop over all customers in route2.
                        int next_customer2 = route2.GetNeigbours(customer2)[0];
                        if (previous_customer2 >= 0 && next_customer2 >= 0)
                        { // the previous customer is set.
                            float weight1 = (float)problem.WeightMatrix[previous_customer1][customer1] +
                                            (float)problem.WeightMatrix[customer1][next_customer1];
                            float weight2 = (float)problem.WeightMatrix[previous_customer2][customer2] +
                                            (float)problem.WeightMatrix[customer2][next_customer2];

                            float weight1_after = (float)problem.WeightMatrix[previous_customer1][customer2] +
                                                  (float)problem.WeightMatrix[customer2][next_customer1];
                            float weight2_after = (float)problem.WeightMatrix[previous_customer2][customer1] +
                                                  (float)problem.WeightMatrix[customer1][next_customer2];
                            double difference = (weight1_after + weight2_after) - (weight1 + weight2);

                            if (difference < -0.01)
                            { // the old weights are bigger!
                                // check if the new routes are bigger than max.
                                if (route1_size + (weight1_after - weight1) <= max &&
                                    route2_size + (weight2_after - weight1) <= max)
                                { // the exchange can happen, both routes stay within bound!
                                    // exchange customer.
                                    int count_before = route1.Count + route2.Count;

                                    //route1.Remove(customer1);
                                    //route2.Remove(customer2);
                                    if (previous_customer1 == next_customer2)
                                    {
                                        throw new Exception();
                                    }

                                    //route1.InsertAfter(previous_customer1, customer2);
                                    //route2.InsertAfter(previous_customer2, customer1);
                                    route1.ReplaceEdgeFrom(previous_customer1, customer2);
                                    route1.ReplaceEdgeFrom(customer2, next_customer1);
                                    route2.ReplaceEdgeFrom(previous_customer2, customer1);
                                    route2.ReplaceEdgeFrom(customer1, next_customer2);

                                    int count_after = route1.Count + route2.Count;
                                    if (count_before != count_after)
                                    {
                                        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);
                                }
                            }
                        }

                        previous_customer2 = customer2; // set the previous customer.
                    }
                }
                previous_customer1 = customer1; // set the previous customer.
            }
            return(false);
        }
示例#8
0
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            MaxTimeCalculator calculator = new MaxTimeCalculator(
                problem);

            // generate a ATSP solution.
            IRoute tsp_solution = _tsp_solution;

            if (tsp_solution == null)
            {
                tsp_solution = _tsp_solver.Solve(new TSPProblem(problem));
            }

            // generate subtours from this solution.
            MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true);

            // select a random start point.
            int start = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(problem.Size);

            // start the first tour.
            int placed   = 0;
            int previous = -1;

            // place the first customer.
            double weight       = 0;
            double total_weight = 0;
            IRoute route        = solution.Add(start);

            previous = start;

            while (placed < problem.Size)
            {
                // get the next customer from the tsp solution.
                int next = tsp_solution.GetNeigbours(previous)[0];

                // get the weight to the current start.
                double weight_to_next  = problem.WeightMatrix[previous][next];
                double weight_to_start = problem.WeightMatrix[next][start];
                total_weight = calculator.CalculateOneRouteIncrease(
                    weight, weight_to_next + weight_to_start);
                weight = calculator.CalculateOneRouteIncrease(
                    weight, weight_to_next);

                if (total_weight > problem.Max.Value)
                { // start a new route.
                    route  = solution.Add(next);
                    weight = 0;
                }
                else
                { // just insert the next customer.
                    route.InsertAfter(previous, next);
                    //route.InsertAfterAndRemove(previous, next, -1);
                }

                // set the previous.
                previous = next;
                placed++;
            }

            if (!solution.IsValid())
            {
                throw new Exception();
            }

            StringBuilder builder = new StringBuilder();

            builder.Append("[");
            total_weight = 0;
            for (int idx = 0; idx < solution.Count; idx++)
            {
                //IRoute route = routes.Route(idx);
                route  = solution.Route(idx);
                weight = calculator.CalculateOneRoute(route);
                builder.Append(" ");
                builder.Append(weight);
                builder.Append(" ");

                total_weight = total_weight + weight;
            }
            builder.Append("]");
            builder.Append(total_weight);
            builder.Append(": ");
            builder.Append(calculator.Calculate(solution));
            Console.WriteLine(builder.ToString());

            return(solution);
        }
        /// <summary>
        /// Tries to improve the existing route using CI and return true if succesful.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="difference"></param>
        /// <returns></returns>
        public bool Improve(IProblemWeights problem, IRoute route, out double difference)
        {
            bool improvement = false;

            difference = 0;
            if (route.Count > 3)
            {
                // loop over all customers and try cheapest insertion.
                for (int customer = 0; customer < problem.Size; customer++)
                {
                    //string route_string = route.ToString();
                    //IRoute previous = route.Clone() as IRoute;
                    if (route.Contains(customer))
                    {
                        // remove customer and keep position.
                        int next = route.GetNeigbours(customer)[0];
                        route.Remove(customer);

                        // insert again.
                        ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference);

                        if (!route.IsValid())
                        {
                            throw new Exception();
                        }
                        if (route.GetNeigbours(customer)[0] != next
                            && difference < 0)
                        { // another customer was found as the best, improvement is succesful.
                            improvement = true;
                            break;
                        }
                    }
                }
            }
            return improvement;
        }
示例#10
0
 /// <summary>
 /// Tries all 3Opt Moves for the neighbourhood of v_1 containing v_3.
 /// </summary>
 /// <param name="problem"></param>
 /// <param name="weights"></param>
 /// <param name="route"></param>
 /// <param name="v1"></param>
 /// <param name="v_2"></param>
 /// <param name="weight_1_2"></param>
 /// <param name="v_3"></param>
 /// <returns></returns>
 public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route,
     int v1, int v_2, double weight_1_2,
     int v_3)
 {
     // get v_4.
     int v_4 = route.GetNeigbours(v_3)[0];
     double weight_1_2_plus_3_4 = weight_1_2 + weights[v_3][v_4];
     double weight_1_4 = weights[v1][v_4];
     double[] weights_3 = weights[v_3];
     return this.Try3OptMoves(problem, weights, route, v1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4);
 }
示例#11
0
        /// <summary>
        /// Tries all 3Opt Moves for the neighbourhood of v_1.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="weights"></param>
        /// <param name="route"></param>
        /// <param name="v1"></param>
        /// <returns></returns>
        public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route, int v1)
        {
            // get v_2.
            int v_2 = route.GetNeigbours(v1)[0];
            if (v_2 < 0)
            {
                return false;
            }
            IEnumerable<int> between_v_2_v_1 = route.Between(v_2, v1);
            double weight_1_2 = weights[v1][v_2];
            int v_3 = -1;
            NearestNeighbours10 neighbours = null;
            if (_nearest_neighbours)
            {
                neighbours = problem.Get10NearestNeighbours(v1);
            }

            foreach (int v_4 in between_v_2_v_1)
            {
                if (v_3 >= 0 && v_3 != v1)
                {
                    //if (!_nearest_neighbours ||
                    //    neighbours.Max <= weight_1_4)
                    if (!_nearest_neighbours ||
                        neighbours.Contains(v_4))
                    {
                        double weight_1_4 = weights[v1][v_4];
                        double weight_1_2_plus_3_4 = weight_1_2 + weights[v_3][v_4];
                        double[] weights_3 = weights[v_3];
                        if (this.Try3OptMoves(problem, weights, route, v1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4))
                        {
                            return true;
                        }
                    }
                }
                v_3 = v_4;
            }
            return false;
        }
示例#12
0
        /// <summary>
        /// Calculates a solution.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            // create the calculator.
            MaxTimeCalculator calculator = new MaxTimeCalculator(problem);

            // create the solution.
            MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true);

            double max = problem.Max.Value;

            // keep placing customer until none are left.
            List <int> customers = new List <int>(problem.Customers);

            // create n routes.
            for (int customer = 0; customer < customers.Count; customer++)
            {
                solution.Add(customer);
                solution[solution.Count - 1] = calculator.CalculateOneRouteIncrease(
                    0, 0);
            }

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

            result.Weight = double.MaxValue;

            // loop over all route pairs and merge the smallest merge.
            while (result != null)
            { // keep looping until there is no result anymore.
                result        = new MergeResult();
                result.Weight = double.MaxValue;

                for (int route1_idx = 1; route1_idx < solution.Count; route1_idx++)
                {         // keep looping over all routes.
                    for (int route2_idx = 0; route2_idx < solution.Count; route2_idx++)
                    {     // keep looping over all routes.
                        if (route1_idx == route2_idx)
                        { // only consider different routes.
                            break;
                        }

                        // calculate the merge result.
                        MergeResult current_result = this.TryMerge(problem, solution,
                                                                   route1_idx, route2_idx, problem.Max.Value);

                        // evaluate the current result.
                        if (current_result != null && current_result.Weight < result.Weight)
                        { // current result is best.
                            result = current_result;
                        }
                    }
                }

                // evaluate the result.
                if (result.Weight < double.MaxValue)
                { // there is a result; apply it!
                    IRoute source = solution.Route(result.RouteSourceId);
                    IRoute target = solution.Route(result.RouteTargetId);

                    //string source_string = source.ToString();
                    //string target_string = target.ToString();

                    if (target.Count > 1 && target.First == target.GetNeigbours(result.CustomerTargetSource)[0])
                    {
                        //throw new Exception();
                    }

                    // create an enumeration of all customers of source in the correct order.
                    IEnumerable <int> source_between = new List <int>(
                        source.Between(result.CustomerSourceSource, result.CustomerSourceTarget));

                    // insert after the complete source.
                    int previous = result.CustomerTargetSource;
                    int next     = target.GetNeigbours(result.CustomerTargetSource)[0];
                    foreach (int source_customer in source_between)
                    {
                        // insert.
                        target.ReplaceEdgeFrom(previous, source_customer);

                        previous = source_customer; // update previous.
                    }
                    target.ReplaceEdgeFrom(previous, next);

                    // remove the source route.
                    solution.Remove(result.RouteSourceId);
                    solution.RemoveWeight(result.RouteTargetId);

                    // calculate the weight of the new route.
                    solution[result.RouteTargetId] = solution[result.RouteTargetId] + result.Weight +
                                                     solution[result.RouteSourceId];

                    if (!solution.IsValid())
                    {
                        throw new Exception();
                    }
                }
                else
                { // set the result null.
                    result = null;
                }
            }

            return(solution);
        }