示例#1
0
        /// <summary>
        /// Calculates the weight of the route given the weights.
        /// </summary>
        /// <param name="route"></param>
        /// <param name="is_round"></param>
        /// <param name="weights"></param>
        public static double CalculateWeight(this int[] route, bool is_round, IProblemWeights weights)
        {
            double weight   = 0;
            int    previous = -1;

            foreach (int customer in route)
            {
                if (previous >= 0)
                { // calculate the weight.
                    weight = weight +
                             weights.WeightMatrix[previous][customer];
                }

                // set the previous and current.
                previous = customer;
            }

            // if the route is round add the last-first weight.
            if (is_round)
            {
                weight = weight +
                         weights.WeightMatrix[previous][route[0]];
            }
            return(weight);
        }
示例#2
0
 private void Set(IProblemWeights problem, int customer, bool value)
 {
     if (_dont_look)
     {
         _dont_look_bits[customer] = value;
     }
 }
示例#3
0
        /// <summary>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static TwoOptResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route)
        {
            //int previous1 = -1;
            //foreach (int customer1 in route)
            //{
            //    if (previous1 >= 0)
            //    {
            //        int previous2 = -1;
            //        foreach (int customer2 in route)
            //        {
            //            if (previous1 != previous2)
            //            {
            //                // test the two opt move.

            //            }

            //            previous2 = customer2;
            //        }
            //    }

            //    previous1 = customer1;
            //}
            throw new NotImplementedException();
        }
示例#4
0
        /// <summary>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static TwoOptResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route)
        {
            //int previous1 = -1;
            //foreach (int customer1 in route)
            //{
            //    if (previous1 >= 0)
            //    {
            //        int previous2 = -1;
            //        foreach (int customer2 in route)
            //        {
            //            if (previous1 != previous2)
            //            {
            //                // test the two opt move.

            //            }

            //            previous2 = customer2;
            //        }
            //    }

            //    previous1 = customer1;
            //}
            throw new NotImplementedException();
        }
示例#5
0
        public Problem(ICollection<int> depots,ICollection<int> customers, IProblemWeights weights)
        {
            this.Depots = depots;
            this.Customers = customers;

            _weights = weights;
        }
示例#6
0
        /// <summary>
        /// Improves an existing solution.
        /// </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)
        {
            if (!route.IsValid())
            {
                throw new Exception();
            }

            _dont_look_bits = new bool[problem.Size];
            double[][] weights = problem.WeightMatrix;

            // loop over all customers.
            bool any_improvement = false;
            bool improvement     = true;

            difference = -1;
            while (improvement)
            {
                improvement = false;
                foreach (int v_1 in route)
                {
                    if (!this.Check(problem, v_1))
                    {
                        if (this.Try3OptMoves(problem, weights, route, v_1))
                        {
                            any_improvement = true;
                            improvement     = true;
                            break;
                        }
                        this.Set(problem, v_1, true);
                    }
                }
            }
            return(any_improvement);
        }
示例#7
0
        public Problem(ICollection <int> depots, ICollection <int> customers, IProblemWeights weights)
        {
            this.Depots    = depots;
            this.Customers = customers;

            _weights = weights;
        }
示例#8
0
        /// <summary>
        /// Considers one customer for relocation.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="previous"></param>
        /// <param name="current"></param>
        /// <param name="next"></param>
        /// <param name="route_weight"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        private bool ConsiderCustomer(IProblemWeights problem, IRoute route, int previous, int current, int next, double route_weight, double max)
        {
            // calculate the removal gain of the customer.
            double removal_gain = problem.WeightMatrix[previous][current] + problem.WeightMatrix[current][next]
                                  - problem.WeightMatrix[previous][next];

            if (removal_gain > 0.0001)
            {
                // try and place the customer in the next route.
                CheapestInsertionResult result =
                    CheapestInsertionHelper.CalculateBestPlacement(problem, route, current);
                if (result.Increase < removal_gain - 0.001 && route_weight + result.Increase < max)
                { // there is a gain in relocating this customer.
                    int count_before = route.Count;
//                    string route_string = route.ToString();

                    // and the route is still within bounds!
                    route.ReplaceEdgeFrom(result.CustomerBefore, result.Customer);
                    route.ReplaceEdgeFrom(result.Customer, result.CustomerAfter);

                    int count_after = route.Count;
                    if (count_before + 1 != count_after)
                    {
                        throw new Exception();
                    }
                    return(true);
                }
            }
            return(false);
        }
示例#9
0
        /// <summary>
        /// Cuts out a part of the route and returns the customers contained.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="start"></param>
        /// <param name="weight"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public CutResult CutAndRemove(IProblemWeights weights, double weight, int start, int length)
        {
            double weight_difference = 0;

            int[]      next_array       = _next_array.Clone() as int[];
            List <int> cut_part         = new List <int>();
            int        position         = 0;
            int        current_customer = this.First;

            // keep moving next until the start.
            while (position < start - 1)
            {
                position++; // increase the position.
                current_customer = next_array[current_customer];
            }

            // cut the actual part.
            int start_customer    = current_customer;
            int previous_customer = current_customer;

            while (position < start + length - 1)
            {
                // move next.
                position++; // increase the position.
                current_customer = next_array[current_customer];

                // set the current customer.
                cut_part.Add(current_customer);

                // add the weigth difference.
                weight_difference = weight_difference -
                                    weights.WeightMatrix[previous_customer][current_customer];
                previous_customer = current_customer;
            }

            // move to the next customer.
            current_customer  = next_array[current_customer];
            weight_difference = weight_difference -
                                weights.WeightMatrix[previous_customer][current_customer];

            // set the next customer.
            next_array[start_customer] = current_customer;
            weight_difference          = weight_difference +
                                         weights.WeightMatrix[start_customer][current_customer];

            // create cut result.
            CutResult result = new CutResult();

            result.Weight  = weight + weight_difference;
            result.Route   = new DynamicAsymmetricRoute(this.First, next_array, true);
            result.CutPart = cut_part;
            if (!result.Route.IsValid())
            {
                throw new Exception();
            }


            return(result);
        }
示例#10
0
 private bool Check(IProblemWeights problem, int customer)
 {
     if (_dont_look)
     {
         return(_dont_look_bits[customer]);
     }
     return(false);
 }
        /// <summary>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            ICollection<int> customers)
        {
            IInsertionCosts costs = new BinaryHeapInsertionCosts();

            return CheapestInsertionHelper.CalculateBestPlacement(problem, route, customers, costs);
        }
        /// <summary>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            ICollection <int> customers)
        {
            IInsertionCosts costs = new BinaryHeapInsertionCosts();

            return(CheapestInsertionHelper.CalculateBestPlacement(problem, route, customers, costs));
        }
示例#13
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));
        }
示例#14
0
        /// <summary>
        /// Creates a new max time problem.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="max"></param>
        /// <param name="delivery_time"></param>
        /// <param name="cost_per_second"></param>
        /// <param name="cost_per_vehicle"></param>
        public MaxTimeProblem(IProblemWeights weights, Second max, Second delivery_time,
                              double cost_per_second, double cost_per_vehicle)
        {
            this.Max          = max;
            this.DeliveryTime = delivery_time;
            _cost_per_second  = cost_per_second;
            _cost_per_vehicle = cost_per_vehicle;

            _weights = weights;

            _calculator         = new MaxTimeCalculator(this);
            _customer_positions = new List <GeoCoordinate>();
        }
示例#15
0
        /// <summary>
        /// Creates a new max time problem.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="max"></param>
        /// <param name="delivery_time"></param>
        /// <param name="cost_per_second"></param>
        /// <param name="cost_per_vehicle"></param>
        public MaxTimeProblem(IProblemWeights weights, Second max, Second delivery_time, 
            double cost_per_second, double cost_per_vehicle)
        {
            this.Max = max;
            this.DeliveryTime = delivery_time;
            _cost_per_second = cost_per_second;
            _cost_per_vehicle = cost_per_vehicle;

            _weights = weights;

            _calculator = new MaxTimeCalculator(this);
            _customer_positions = new List<GeoCoordinate>();
        }
示例#16
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>
        /// Re-inserts a customer in the route.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="route"></param>
        /// <param name="customer"></param>
        /// <param name="difference"></param>
        /// <returns></returns>
        public static bool InsertOne(IProblemWeights weights, IRoute route, int customer,
                                     out double difference)
        {
            // calculate placement.
            CheapestInsertionResult result =
                CheapestInsertionHelper.CalculateBestPlacement(weights, route, customer);

            // place the customer.
            if (result.CustomerAfter >= 0 && result.CustomerBefore >= 0)
            {
                //route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                route.InsertAfter(result.CustomerBefore, result.Customer);
                difference =
                    -(weights.WeightMatrix[result.CustomerBefore][result.CustomerAfter]) +
                    (weights.WeightMatrix[result.CustomerBefore][result.Customer]) +
                    (weights.WeightMatrix[result.Customer][result.CustomerAfter]);
                return(true);
            }
            difference = 0;
            return(false);
        }
示例#18
0
        /// <summary>
        /// Apply some improvements within one route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="currentWeight"></param>
        private double ImproveIntraRoute(IProblemWeights problem, IRoute route, double currentWeight)
        {
            bool   improvement = true;
            double newWeight   = currentWeight;

            while (improvement)
            { // keep trying while there are still improvements.
                improvement = false;

                // loop over all improvement operations.
                foreach (IImprovement improvementOperation in _intra_improvements)
                { // try the current improvement operations.
                    double difference;
                    if (improvementOperation.Improve(problem, route, out difference))
                    { // there was an improvement.
                        OsmSharp.Logging.Log.TraceEvent("OsmSharp.Routing.VRP.NoDepot.MaxTime.VNS.GuidedVNS", TraceEventType.Information,
                                                        "Intra-improvement found {0} {1}->{2}",
                                                        improvementOperation.Name, newWeight, newWeight + difference);

                        // check if the route is valid.
                        if (!route.IsValid())
                        {
                            throw new Exception();
                        }

                        // update the weight.
                        newWeight = newWeight + difference;

                        improvement = true;

                        break;
                    }
                }
            }
            return(newWeight);
        }
        /// <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);
        }
示例#20
0
        /// <summary>
        /// Calculates the weight of the route given the weights.
        /// </summary>
        /// <param name="route"></param>
        /// <param name="is_round"></param>
        /// <param name="weights"></param>
        public static double CalculateWeight(this int[] route, bool is_round, IProblemWeights weights)
        {
            double weight = 0;
            int previous = -1;
            foreach (int customer in route)
            {
                if (previous >= 0)
                { // calculate the weight.
                    weight = weight +
                        weights.WeightMatrix[previous][customer];
                }

                // set the previous and current.
                previous = customer;
            }

            // if the route is round add the last-first weight.
            if (is_round)
            {
                weight = weight +
                    weights.WeightMatrix[previous][route[0]];
            }
            return weight;
        }
        /// <summary>
        /// Searches for the best place to insert the given two customers abstracting the distance between them.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            int from,
            int to)
        {
            // initialize the best placement result.
            CheapestInsertionResult result
                = new CheapestInsertionResult();
            result.Customer = -1; // this property is useless here!
            result.CustomerAfter = -1;
            result.CustomerBefore = -1;
            result.Increase = double.MaxValue;

            if (!route.IsEmpty)
            {
                double new_weight = double.MaxValue;
                double old_weight = 0;

                int previous = -1;
                int first = -1;
                foreach (int current in route)
                {
                    if (previous >= 0)
                    { // only if the previous is known.
                        // calculate the new weights.
                        new_weight = problem.Weight(previous, from)
                                + (problem.Weight(to, current));

                        // calculate the old weights.
                        old_weight = problem.Weight(previous, current);

                        // calculate the difference.
                        double difference = new_weight - old_weight;
                        if (result.Increase > difference)
                        {
                            result.CustomerAfter = current;
                            result.CustomerBefore = previous;
                            result.Increase = difference;
                        }
                    }
                    else
                    { // store the first city for later.
                        first = current;
                    }

                    // go to the next loop.
                    previous = current;
                }

                // test last-to-first if the route is a round.
                if (route.IsRound)
                {
                    // calculate the new weights.
                    new_weight = problem.Weight(previous, from)
                            + (problem.Weight(to, first));

                    // calculate the old weights.
                    old_weight = problem.Weight(previous, first);

                    // calculate the difference.
                    double difference = new_weight - old_weight;
                    if (result.Increase > difference)
                    {
                        result.CustomerBefore = previous;
                        result.CustomerAfter = first;
                        result.Increase = difference;
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least one customer!");
            }

            // return result.
            return result;
        }
示例#22
0
        /// <summary>
        /// Applies a local search strategy.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static void CalculateRePlaceOptHelper(
            IProblemWeights problem, IRoute route)
        {
            //bool improvement = true;
            //while (improvement)
            //{
            //// reset improvement flag.
            //improvement = false;

            // try re-placement of one customer.
            int before = -1;
            int after = -1;
            int found_customer = -1;

            // loop over all customers and try to place it better.
            HashSet<int> customers_to_place = new HashSet<int>(route);
            foreach (int customer_to_place in customers_to_place)
            {
                // find the best place.
                double current_cost = -1;
                double other_cost = double.MaxValue;
                int previous_before = -1;
                int previous = -1;
                foreach (int customer in route)
                {
                    if (previous >= 0 && previous_before >= 0)
                    {
                        if (previous == customer_to_place)
                        {
                            current_cost = problem.Weight(previous_before, previous) +
                                problem.Weight(previous, customer);
                        }
                        else if (previous_before != customer_to_place &&
                            customer != customer_to_place)
                        { // calculate the cost.
                            double cost = problem.Weight(previous_before, customer_to_place) +
                                problem.Weight(customer_to_place, previous);
                            if (cost < other_cost)
                            {
                                other_cost = cost;

                                before = previous_before;
                                after = previous;
                                found_customer = customer;
                            }
                        }
                    }

                    previous_before = previous;
                    previous = customer;
                }

                // determine if the cost is better.
                if (current_cost > other_cost)
                { // the current cost is better.
                    route.Remove(found_customer);
                    //route.InsertAfterAndRemove(before, found_customer, after);
                    route.InsertAfter(before, found_customer);
                    break;
                }
                else
                { // current cost is not better.
                    before = -1;
                    after = -1;
                    found_customer = -1;
                }
            }

            //if (found_customer >= 0)
            //{ // a found customer.
            //    improvement = true;
            //}
            //}
        }
示例#23
0
        /// <summary>
        /// Selects seed customers.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public ICollection<int> SelectSeeds(IProblemWeights weights, int k)
        {
            List<int> seeds = new List<int>();

            // randomly select k seeds.
            while (seeds.Count < k)
            {
                int new_seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                while (seeds.Contains(new_seed))
                {
                    new_seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                }
                seeds.Add(new_seed);
            }

            // find shortest distance.
            double minimal = double.MaxValue;
            int selected_idx = -1;
            for (int x = 0; x < k; x++)
            {
                for (int y = 0; y < x; y++)
                {
                    double weight = weights.Weight(seeds[x], seeds[y]);
                    if (weight < minimal)
                    {
                        selected_idx = x;
                        minimal = weight;
                    }
                }
            }

            // select any new seed and see if replacing the selected would yield better results.
            int max_tries = 2000;
            int tries = 0;
            while (tries < max_tries)
            {
                int seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                while (seeds.Contains(seed))
                {
                    seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                }

                // check the new minimal.
                double new_minimal = double.MaxValue;
                for (int x = 0; x < k; x++)
                {
                    if (x != selected_idx)
                    {
                        double weight = weights.Weight(seeds[x], seed);
                        if (weight < new_minimal)
                        {
                            new_minimal = weight;
                        }
                    }
                }

                // see if the new one has a higher minimal.
                if (new_minimal > minimal)
                { // ok there is an improvement!
                    OsmSharp.Logging.Log.TraceEvent("SimpleSeeds", System.Diagnostics.TraceEventType.Information, "Seed new minimal: {0}->{1}",
                        minimal, new_minimal);

                    tries = 0;
                    minimal = new_minimal;

                    seeds[selected_idx] = seed;
                }

                tries++; // increase the number of tries.
            }
            OsmSharp.Logging.Log.TraceEvent("SimpleSeeds", System.Diagnostics.TraceEventType.Information, "Seed distance: {0}",
                minimal);
            return seeds;
        }
示例#24
0
        /// <summary>
        /// Apply some improvements within one route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="current_weight"></param>
        private double ImproveIntraRoute(IProblemWeights problem, IRoute route, double current_weight)
        {
            bool improvement = true;
            double new_weight = current_weight;
            while (improvement)
            { // keep trying while there are still improvements.
                improvement = false;

                // loop over all improvement operations.
                foreach (IImprovement improvement_operation in _intra_improvements)
                { // try the current improvement operations.
                    double difference;
                    if (improvement_operation.Improve(problem, route, out difference))
                    { // there was an improvement.
                        OsmSharp.Tools.Output.OutputStreamHost.WriteLine("Intra-improvement found {0} {1}->{2}",
                            improvement_operation.Name, new_weight, new_weight + difference);

                        // check if the route is valid.
                        if (!route.IsValid())
                        {
                            throw new Exception();
                        }

                        // update the weight.
                        new_weight = new_weight + difference;

                        improvement = true;

                        break;
                    }
                }
            }
            return new_weight;
        }
        /// <summary>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customers"></param>
        /// <param name="costs"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            ICollection<int> customers,
            IInsertionCosts costs)
        {
            // initialize the best placement result.
            CheapestInsertionResult best = new CheapestInsertionResult();
            best.Increase = float.MaxValue;

            // loop over all customers in the route.
            if (route.Count > 0)
            { // there have to be at least two customers.
                IEnumerator<int> route_enumerator = route.GetEnumerator();
                if (!route_enumerator.MoveNext())
                { // this route is empty
                    throw new ArgumentException("Route needs to be initialized with at least two customers!");
                }
                int customer_before = route_enumerator.Current;
                int customer_after = -1;
                while (route_enumerator.MoveNext())
                { // keep moving!
                    customer_after = route_enumerator.Current;
                    InsertionCost cost = costs.PopCheapest(customer_before, customer_after);
                    bool found = false;
                    while(!found)
                    { // test if the costs are empty.
                        if (cost == null)
                        { // re-initialize the costs with all customers under consideration.
                            foreach (int customer in customers)
                            {
                                costs.Add(customer_before, customer_after, customer,
                                    (float)problem.WeightMatrix[customer_before][customer] +
                                    (float)problem.WeightMatrix[customer][customer_after] -
                                    (float)problem.WeightMatrix[customer_before][customer_after]);
                            }

                            // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                        else if (customers.Contains(cost.Customer))
                        { // the customer is found!
                            found = true;
                        }
                        else
                        { // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                    }

                    if (cost.Cost < best.Increase)
                    { // the costs is better than the current cost!
                        best = new CheapestInsertionResult()
                            {
                                Customer = cost.Customer,
                                CustomerAfter = customer_after,
                                CustomerBefore = customer_before,
                                Increase = cost.Cost
                            };
                        if (best.Increase == 0)
                        { // immidiately return if smaller than epsilon.
                            return best;
                        }
                    }

                    // set the after to the before.
                    customer_before = route_enumerator.Current;
                }

                // if the round is a round try first-last.
                if (route.IsRound)
                { // the route is a round!
                    customer_after = route.First;
                    InsertionCost cost = costs.PopCheapest(customer_before, customer_after);
                    bool found = false;
                    while (!found)
                    { // test if the costs are empty.
                        if (cost == null)
                        { // re-initialize the costs with all customers under consideration.
                            foreach (int customer in customers)
                            {
                                costs.Add(customer_before, customer_after, customer,
                                    (float)problem.WeightMatrix[customer_before][customer] +
                                    (float)problem.WeightMatrix[customer][customer_after] -
                                    (float)problem.WeightMatrix[customer_before][customer_after]);
                            }

                            // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                        else if (customers.Contains(cost.Customer))
                        { // the customer is found!
                            found = true;
                        }
                        else
                        { // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                    }

                    if (cost.Cost < best.Increase)
                    { // the costs is better than the current cost!
                        best = new CheapestInsertionResult()
                        {
                            Customer = cost.Customer,
                            CustomerAfter = customer_after,
                            CustomerBefore = customer_before,
                            Increase = cost.Cost
                        };
                        if (best.Increase == 0)
                        { // immidiately return if smaller than epsilon.
                            return best;
                        }
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least two customers!");
            }

            // return result.
            return best;
        }
        /// <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;
        }
        /// <summary>
        /// Re-inserts a customer in the route.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="route"></param>
        /// <param name="customer"></param>
        /// <param name="difference"></param>
        /// <returns></returns>
        public static bool InsertOne(IProblemWeights weights, IRoute route, int customer,
            out double difference)
        {
            // calculate placement.
            CheapestInsertionResult result =
                CheapestInsertionHelper.CalculateBestPlacement(weights, route, customer);

            // place the customer.
            if (result.CustomerAfter >= 0 && result.CustomerBefore >= 0)
            {
                //route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                route.InsertAfter(result.CustomerBefore, result.Customer);
                difference =
                    -(weights.WeightMatrix[result.CustomerBefore][result.CustomerAfter]) +
                     (weights.WeightMatrix[result.CustomerBefore][result.Customer]) +
                     (weights.WeightMatrix[result.Customer][result.CustomerAfter]);
                return true;
            }
            difference = 0;
            return false;
        }
示例#28
0
        /// <summary>
        /// Improves an existing solution.
        /// </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)
        {
            if (!route.IsValid())
            {
                throw new Exception();
            }

            _dont_look_bits = new bool[problem.Size];
            double[][] weights = problem.WeightMatrix;

            // loop over all customers.
            bool any_improvement = false;
            bool improvement = true;
            difference = -1;
            while (improvement)
            {
                improvement = false;
                foreach (int v_1 in route)
                {
                    if (!this.Check(problem, v_1))
                    {
                        if (this.Try3OptMoves(problem, weights, route, v_1))
                        {
                            any_improvement = true;
                            improvement = true;
                            break;
                        }
                        this.Set(problem, v_1, true);
                    }
                }
            }
            return any_improvement;
        }
示例#29
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="v_3"></param>
        /// <param name="weights_3"></param>
        /// <param name="v_4"></param>
        /// <param name="weight_1_2_plus_3_4"></param>
        /// <param name="weight_1_4"></param>
        /// <returns></returns>
        public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route,
                                 int v1, int v_2, int v_3, double[] weights_3, int v_4, double weight_1_2_plus_3_4, double weight_1_4)
        {
            //IEnumerable<int> between_v_4_v_1 = route.Between(v_4, v_1);
            //foreach (int v_5 in between_v_4_v_1)
            //{
            //    if (v_5 != v_1)
            //    {
            //        if (this.Try3OptMove(problem, weights, route, v_1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4, v_5))
            //        {
            //            return true;
            //        }
            //    }
            //}
            //return false;

            IEnumerator <int> between_v_4_v_1_enumerator = route.Between(v_4, v1).GetEnumerator();

            if (between_v_4_v_1_enumerator.MoveNext())
            {
                int v_5 = between_v_4_v_1_enumerator.Current;
                if (v_5 != v1)
                {
                    while (between_v_4_v_1_enumerator.MoveNext())
                    {
                        int v_6 = between_v_4_v_1_enumerator.Current;
                        //Console.WriteLine(v_6);
                        //if (this.Try3OptMove(problem, weights,
                        //    route, v_1, v_2, v_3, weights_3, v_4,
                        //    weight_1_2_plus_3_4, weight_1_4, v_5, v_6))
                        //{
                        // calculate the total weight of the 'new' arcs.
                        double weight_new = weight_1_4 +
                                            weights_3[v_6] +
                                            weights[v_5][v_2];

                        // calculate the total weights.
                        double weight = weight_1_2_plus_3_4 + weights[v_5][v_6];

                        if (weight - weight_new > _epsilon)
                        { // actually do replace the vertices.
                            int count_before = route.Count;
                            //string route_string = route.ToString();

                            route.ReplaceEdgeFrom(v1, v_4);
                            route.ReplaceEdgeFrom(v_3, v_6);
                            route.ReplaceEdgeFrom(v_5, v_2);

                            int count_after = route.Count;

                            if (count_before != count_after)
                            {
                                throw new Exception();
                            }
                            // set bits.
                            //this.Set(problem, v_1, false);
                            this.Set(problem, v_3, false);
                            this.Set(problem, v_5, false);

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

                            return(true); // move succeeded.
                        }
                        //}
                        v_5 = v_6;
                    }
                }
            }
            return(false);
        }
示例#30
0
        /// <summary>
        /// Apply some improvements within one route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="currentWeight"></param>
        private double ImproveIntraRoute(IProblemWeights problem, IRoute route, double currentWeight)
        {
            bool improvement = true;
            double newWeight = currentWeight;
            while (improvement)
            { // keep trying while there are still improvements.
                improvement = false;

                // loop over all improvement operations.
                foreach (IImprovement improvementOperation in _intra_improvements)
                { // try the current improvement operations.
                    double difference;
                    if (improvementOperation.Improve(problem, route, out difference))
                    { // there was an improvement.
                        OsmSharp.Logging.Log.TraceEvent("OsmSharp.Routing.VRP.NoDepot.MaxTime.VNS.GuidedVNS", TraceEventType.Information,
                            "Intra-improvement found {0} {1}->{2}",
                            improvementOperation.Name, newWeight, newWeight + difference);

                        // check if the route is valid.
                        if (!route.IsValid())
                        {
                            throw new Exception();
                        }

                        // update the weight.
                        newWeight = newWeight + difference;

                        improvement = true;

                        break;
                    }
                }
            }
            return newWeight;
        }
        /// <summary>
        /// Searches for the best place to insert the given customer.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customer"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            int customer)
        {  // initialize the best placement result.
            double[][] weights = problem.WeightMatrix;

            CheapestInsertionResult result
                = new CheapestInsertionResult();

            result.Customer       = customer;
            result.CustomerAfter  = -1;
            result.CustomerBefore = -1;
            result.Increase       = double.MaxValue;

            double difference = double.MaxValue;

            if (!route.IsEmpty)
            {
                double new_weight = double.MaxValue;
                double old_weight = 0;

                int previous = -1;
                int first    = -1;
                foreach (int current in route)
                {
                    if (previous >= 0)
                    { // the previous customer exists.
                      // only if the previous is known.

                        // calculate the old weights.
                        //old_weight = problem.Weight(previous, current);
                        old_weight = weights[previous][current];

                        // calculate the new weights.
                        //new_weight = problem.Weight(previous, customer);
                        new_weight = weights[previous][customer];

                        //new_weight = new_weight +
                        //    problem.Weight(customer, current);
                        new_weight = new_weight +
                                     weights[customer][current];

                        // calculate the difference.
                        difference = new_weight - old_weight;
                        if (result.Increase > difference)
                        {
                            result.CustomerAfter  = current;
                            result.CustomerBefore = previous;
                            result.Increase       = difference;

                            // if the difference is equal to or smaller than epsilon we have search enough.
                            if (difference == 0)
                            {
                                // result is the best we will be able to get.
                                return(result);
                            }
                        }
                    }
                    else
                    { // store the first city for later.
                        first = current;
                    }

                    // go to the next loop.
                    previous = current;
                }

                // set the pervious to the last.
                //previous = route.Last;

                // test last-to-first if the route is a round.
                if (route.IsRound)
                {
                    // calculate the new weights.
                    //new_weight = problem.Weight(previous, customer)
                    //        + (problem.Weight(customer, first));
                    new_weight = weights[previous][customer]
                                 + weights[customer][first];

                    // calculate the old weights.
                    //old_weight = problem.Weight(previous, first);
                    old_weight = weights[previous][first];

                    // calculate the difference.
                    difference = new_weight - old_weight;
                    if (result.Increase > difference)
                    {
                        result.CustomerAfter  = first;
                        result.CustomerBefore = previous;
                        result.Increase       = difference;
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least one customer!");
            }

            // return result.
            return(result);
        }
        /// <summary>
        /// Searches for the best place to insert the given two customers abstracting the distance between them.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            int from,
            int to)
        {  // initialize the best placement result.
            CheapestInsertionResult result
                = new CheapestInsertionResult();

            result.Customer       = -1; // this property is useless here!
            result.CustomerAfter  = -1;
            result.CustomerBefore = -1;
            result.Increase       = double.MaxValue;

            if (!route.IsEmpty)
            {
                double new_weight = double.MaxValue;
                double old_weight = 0;

                int previous = -1;
                int first    = -1;
                foreach (int current in route)
                {
                    if (previous >= 0)
                    { // only if the previous is known.
                        // calculate the new weights.
                        new_weight = problem.Weight(previous, from)
                                     + (problem.Weight(to, current));

                        // calculate the old weights.
                        old_weight = problem.Weight(previous, current);

                        // calculate the difference.
                        double difference = new_weight - old_weight;
                        if (result.Increase > difference)
                        {
                            result.CustomerAfter  = current;
                            result.CustomerBefore = previous;
                            result.Increase       = difference;
                        }
                    }
                    else
                    { // store the first city for later.
                        first = current;
                    }

                    // go to the next loop.
                    previous = current;
                }

                // test last-to-first if the route is a round.
                if (route.IsRound)
                {
                    // calculate the new weights.
                    new_weight = problem.Weight(previous, from)
                                 + (problem.Weight(to, first));

                    // calculate the old weights.
                    old_weight = problem.Weight(previous, first);

                    // calculate the difference.
                    double difference = new_weight - old_weight;
                    if (result.Increase > difference)
                    {
                        result.CustomerBefore = previous;
                        result.CustomerAfter  = first;
                        result.Increase       = difference;
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least one customer!");
            }

            // return result.
            return(result);
        }
示例#33
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>
        /// Returns the customer that least increases the length of the given route.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customers"></param>
        /// <param name="costs"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            ICollection <int> customers,
            IInsertionCosts costs)
        {
            // initialize the best placement result.
            CheapestInsertionResult best = new CheapestInsertionResult();

            best.Increase = float.MaxValue;

            // loop over all customers in the route.
            if (route.Count > 0)
            { // there have to be at least two customers.
                IEnumerator <int> route_enumerator = route.GetEnumerator();
                if (!route_enumerator.MoveNext())
                { // this route is empty
                    throw new ArgumentException("Route needs to be initialized with at least two customers!");
                }
                int customer_before = route_enumerator.Current;
                int customer_after  = -1;
                while (route_enumerator.MoveNext())
                { // keep moving!
                    customer_after = route_enumerator.Current;
                    InsertionCost cost  = costs.PopCheapest(customer_before, customer_after);
                    bool          found = false;
                    while (!found)
                    {     // test if the costs are empty.
                        if (cost == null)
                        { // re-initialize the costs with all customers under consideration.
                            foreach (int customer in customers)
                            {
                                costs.Add(customer_before, customer_after, customer,
                                          (float)problem.WeightMatrix[customer_before][customer] +
                                          (float)problem.WeightMatrix[customer][customer_after] -
                                          (float)problem.WeightMatrix[customer_before][customer_after]);
                            }

                            // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                        else if (customers.Contains(cost.Customer))
                        { // the customer is found!
                            found = true;
                        }
                        else
                        { // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                    }

                    if (cost.Cost < best.Increase)
                    { // the costs is better than the current cost!
                        best = new CheapestInsertionResult()
                        {
                            Customer       = cost.Customer,
                            CustomerAfter  = customer_after,
                            CustomerBefore = customer_before,
                            Increase       = cost.Cost
                        };
                        if (best.Increase == 0)
                        { // immidiately return if smaller than epsilon.
                            return(best);
                        }
                    }

                    // set the after to the before.
                    customer_before = route_enumerator.Current;
                }

                // if the round is a round try first-last.
                if (route.IsRound)
                { // the route is a round!
                    customer_after = route.First;
                    InsertionCost cost  = costs.PopCheapest(customer_before, customer_after);
                    bool          found = false;
                    while (!found)
                    {     // test if the costs are empty.
                        if (cost == null)
                        { // re-initialize the costs with all customers under consideration.
                            foreach (int customer in customers)
                            {
                                costs.Add(customer_before, customer_after, customer,
                                          (float)problem.WeightMatrix[customer_before][customer] +
                                          (float)problem.WeightMatrix[customer][customer_after] -
                                          (float)problem.WeightMatrix[customer_before][customer_after]);
                            }

                            // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                        else if (customers.Contains(cost.Customer))
                        { // the customer is found!
                            found = true;
                        }
                        else
                        { // pop the cheapest again!
                            cost = costs.PopCheapest(customer_before, customer_after);
                        }
                    }

                    if (cost.Cost < best.Increase)
                    { // the costs is better than the current cost!
                        best = new CheapestInsertionResult()
                        {
                            Customer       = cost.Customer,
                            CustomerAfter  = customer_after,
                            CustomerBefore = customer_before,
                            Increase       = cost.Cost
                        };
                        if (best.Increase == 0)
                        { // immidiately return if smaller than epsilon.
                            return(best);
                        }
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least two customers!");
            }

            // return result.
            return(best);
        }
示例#35
0
        /// <summary>
        /// Applies a local search strategy.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public static void CalculateRePlaceOptHelper(
            IProblemWeights problem, IRoute route)
        {
            //bool improvement = true;
            //while (improvement)
            //{
            //// reset improvement flag.
            //improvement = false;

            // try re-placement of one customer.
            int before = -1;
            //int after = -1;
            int found_customer = -1;

            // loop over all customers and try to place it better.
            HashSet <int> customers_to_place = new HashSet <int>(route);

            foreach (int customer_to_place in customers_to_place)
            {
                // find the best place.
                double current_cost    = -1;
                double other_cost      = double.MaxValue;
                int    previous_before = -1;
                int    previous        = -1;
                foreach (int customer in route)
                {
                    if (previous >= 0 && previous_before >= 0)
                    {
                        if (previous == customer_to_place)
                        {
                            current_cost = problem.Weight(previous_before, previous) +
                                           problem.Weight(previous, customer);
                        }
                        else if (previous_before != customer_to_place &&
                                 customer != customer_to_place)
                        { // calculate the cost.
                            double cost = problem.Weight(previous_before, customer_to_place) +
                                          problem.Weight(customer_to_place, previous);
                            if (cost < other_cost)
                            {
                                other_cost = cost;

                                before = previous_before;
                                //after = previous;
                                found_customer = customer;
                            }
                        }
                    }

                    previous_before = previous;
                    previous        = customer;
                }

                // determine if the cost is better.
                if (current_cost > other_cost)
                { // the current cost is better.
                    route.Remove(found_customer);
                    //route.InsertAfterAndRemove(before, found_customer, after);
                    route.InsertAfter(before, found_customer);
                    break;
                }
                else
                { // current cost is not better.
                    before = -1;
                    //after = -1;
                    found_customer = -1;
                }
            }

            //if (found_customer >= 0)
            //{ // a found customer.
            //    improvement = true;
            //}
            //}
        }
示例#36
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);
 }
示例#37
0
 /// <summary>
 /// Applies a local search strategy.
 /// </summary>
 /// <param name="problem"></param>
 /// <param name="route"></param>
 /// <returns></returns>
 public static void CalculateRePlaceOptHelper(
     IProblemWeights problem, IRoute route)
 {
     throw new NotImplementedException();
 }
示例#38
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="v_3"></param>
        /// <param name="weights_3"></param>
        /// <param name="v_4"></param>
        /// <param name="weight_1_2_plus_3_4"></param>
        /// <param name="weight_1_4"></param>
        /// <returns></returns>
        public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route,
            int v1, int v_2, int v_3, double[] weights_3, int v_4, double weight_1_2_plus_3_4, double weight_1_4)
        {
            //IEnumerable<int> between_v_4_v_1 = route.Between(v_4, v_1);
            //foreach (int v_5 in between_v_4_v_1)
            //{
            //    if (v_5 != v_1)
            //    {
            //        if (this.Try3OptMove(problem, weights, route, v_1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4, v_5))
            //        {
            //            return true;
            //        }
            //    }
            //}
            //return false;

            IEnumerator<int> between_v_4_v_1_enumerator = route.Between(v_4, v1).GetEnumerator();
            if (between_v_4_v_1_enumerator.MoveNext())
            {
                int v_5 = between_v_4_v_1_enumerator.Current;
                if (v_5 != v1)
                {
                    while (between_v_4_v_1_enumerator.MoveNext())
                    {
                        int v_6 = between_v_4_v_1_enumerator.Current;
                        //Console.WriteLine(v_6);
                        //if (this.Try3OptMove(problem, weights,
                        //    route, v_1, v_2, v_3, weights_3, v_4,
                        //    weight_1_2_plus_3_4, weight_1_4, v_5, v_6))
                        //{
                        // calculate the total weight of the 'new' arcs.
                        double weight_new = weight_1_4 +
                            weights_3[v_6] +
                            weights[v_5][v_2];

                        // calculate the total weights.
                        double weight = weight_1_2_plus_3_4 + weights[v_5][v_6];

                        if (weight - weight_new > _epsilon)
                        { // actually do replace the vertices.
                            int count_before = route.Count;
                            //string route_string = route.ToString();

                            route.ReplaceEdgeFrom(v1, v_4);
                            route.ReplaceEdgeFrom(v_3, v_6);
                            route.ReplaceEdgeFrom(v_5, v_2);

                            int count_after = route.Count;

                            if (count_before != count_after)
                            {
                                throw new Exception();
                            }
                            // set bits.
                            //this.Set(problem, v_1, false);
                            this.Set(problem, v_3, false);
                            this.Set(problem, v_5, false);

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

                            return true; // move succeeded.
                        }
                        //}
                        v_5 = v_6;
                    }
                }
            }
            return false;
        }
示例#39
0
 private bool Check(IProblemWeights problem, int customer)
 {
     if (_dont_look)
     {
         return _dont_look_bits[customer];
     }
     return false;
 }
示例#40
0
 private void Set(IProblemWeights problem, int customer, bool value)
 {
     if (_dont_look)
     {
         _dont_look_bits[customer] = value;
     }
 }
示例#41
0
        /// <summary>
        /// Selects seed customers.
        /// </summary>
        /// <param name="weights"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public ICollection <int> SelectSeeds(IProblemWeights weights, int k)
        {
            List <int> seeds = new List <int>();

            // randomly select k seeds.
            while (seeds.Count < k)
            {
                int new_seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                while (seeds.Contains(new_seed))
                {
                    new_seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                }
                seeds.Add(new_seed);
            }

            // find shortest distance.
            double minimal      = double.MaxValue;
            int    selected_idx = -1;

            for (int x = 0; x < k; x++)
            {
                for (int y = 0; y < x; y++)
                {
                    double weight = weights.Weight(seeds[x], seeds[y]);
                    if (weight < minimal)
                    {
                        selected_idx = x;
                        minimal      = weight;
                    }
                }
            }

            // select any new seed and see if replacing the selected would yield better results.
            int max_tries = 2000;
            int tries     = 0;

            while (tries < max_tries)
            {
                int seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                while (seeds.Contains(seed))
                {
                    seed = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(weights.Size);
                }

                // check the new minimal.
                double new_minimal = double.MaxValue;
                for (int x = 0; x < k; x++)
                {
                    if (x != selected_idx)
                    {
                        double weight = weights.Weight(seeds[x], seed);
                        if (weight < new_minimal)
                        {
                            new_minimal = weight;
                        }
                    }
                }

                // see if the new one has a higher minimal.
                if (new_minimal > minimal)
                { // ok there is an improvement!
                    OsmSharp.Logging.Log.TraceEvent("SimpleSeeds", System.Diagnostics.TraceEventType.Information, "Seed new minimal: {0}->{1}",
                                                    minimal, new_minimal);

                    tries   = 0;
                    minimal = new_minimal;


                    seeds[selected_idx] = seed;
                }

                tries++; // increase the number of tries.
            }
            OsmSharp.Logging.Log.TraceEvent("SimpleSeeds", System.Diagnostics.TraceEventType.Information, "Seed distance: {0}",
                                            minimal);
            return(seeds);
        }
示例#42
0
 /// <summary>
 /// Applies a local search strategy.
 /// </summary>
 /// <param name="problem"></param>
 /// <param name="route"></param>
 /// <returns></returns>
 public static void CalculateRePlaceOptHelper(
     IProblemWeights problem, IRoute route)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Considers one customer for relocation.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="previous"></param>
        /// <param name="current"></param>
        /// <param name="next"></param>
        /// <param name="route_weight"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        private bool ConsiderCustomer(IProblemWeights problem, IRoute route, int previous, int current, int next, double route_weight, double max)
        {
            // calculate the removal gain of the customer.
            double removal_gain = problem.WeightMatrix[previous][current] + problem.WeightMatrix[current][next]
                - problem.WeightMatrix[previous][next];
            if (removal_gain > 0.0001)
            {
                // try and place the customer in the next route.
                CheapestInsertionResult result =
                    CheapestInsertionHelper.CalculateBestPlacement(problem, route, current);
                if (result.Increase < removal_gain - 0.001 && route_weight + result.Increase < max)
                { // there is a gain in relocating this customer.
                    int count_before = route.Count;
            //                    string route_string = route.ToString();

                    // and the route is still within bounds!
                    route.ReplaceEdgeFrom(result.CustomerBefore, result.Customer);
                    route.ReplaceEdgeFrom(result.Customer, result.CustomerAfter);

                    int count_after = route.Count;
                    if (count_before + 1 != count_after)
                    {
                        throw new Exception();
                    }
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Searches for the best place to insert the given customer.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="route"></param>
        /// <param name="customer"></param>
        /// <returns></returns>
        public static CheapestInsertionResult CalculateBestPlacement(
            IProblemWeights problem,
            IRoute route,
            int customer)
        {
            // initialize the best placement result.
            double[][] weights = problem.WeightMatrix;

            CheapestInsertionResult result
                = new CheapestInsertionResult();
            result.Customer = customer;
            result.CustomerAfter = -1;
            result.CustomerBefore = -1;
            result.Increase = double.MaxValue;

            double difference = double.MaxValue;
            if (!route.IsEmpty)
            {
                double new_weight = double.MaxValue;
                double old_weight = 0;

                int previous = -1;
                int first = -1;
                foreach (int current in route)
                {
                    if (previous >= 0)
                    { // the previous customer exists.
                        // only if the previous is known.

                        // calculate the old weights.
                        //old_weight = problem.Weight(previous, current);
                        old_weight = weights[previous][current];

                        // calculate the new weights.
                        //new_weight = problem.Weight(previous, customer);
                        new_weight = weights[previous][customer];

                        //new_weight = new_weight +
                        //    problem.Weight(customer, current);
                        new_weight = new_weight +
                            weights[customer][current];

                        // calculate the difference.
                        difference = new_weight - old_weight;
                        if (result.Increase > difference)
                        {
                            result.CustomerAfter = current;
                            result.CustomerBefore = previous;
                            result.Increase = difference;

                            // if the difference is equal to or smaller than epsilon we have search enough.
                            if (difference == 0)
                            {
                                // result is the best we will be able to get.
                                return result;
                            }
                        }
                    }
                    else
                    { // store the first city for later.
                        first = current;
                    }

                    // go to the next loop.
                    previous = current;
                }

                // set the pervious to the last.
                //previous = route.Last;

                // test last-to-first if the route is a round.
                if (route.IsRound)
                {
                    // calculate the new weights.
                    //new_weight = problem.Weight(previous, customer)
                    //        + (problem.Weight(customer, first));
                    new_weight = weights[previous][customer]
                        + weights[customer][first];

                    // calculate the old weights.
                    //old_weight = problem.Weight(previous, first);
                    old_weight = weights[previous][first];

                    // calculate the difference.
                    difference = new_weight - old_weight;
                    if (result.Increase > difference)
                    {
                        result.CustomerAfter = first;
                        result.CustomerBefore = previous;
                        result.Increase = difference;
                    }
                }
            }
            else
            { // route needs to be initialized.
                throw new ArgumentException("Route needs to be initialized with at least one customer!");
            }

            // return result.
            return result;
        }