Beispiel #1
0
        /// <summary>
        /// Test removing adding every customer at every position.
        /// </summary>
        public void DoTestAddRemoveComplete()
        {
            // create a new empty route.
            const int count = 10;

            for (int customerToRemove = 0; customerToRemove < count; customerToRemove++)
            {
                for (int customerToPlaceAfter = 0; customerToPlaceAfter < count; customerToPlaceAfter++)
                {
                    if (customerToRemove != customerToPlaceAfter)
                    {
                        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);
                            }

                            route.Remove(customerToRemove);
                            route.InsertAfter(customerToPlaceAfter, customerToRemove);
                            //route.InsertAfterAndRemove(customer_to_place_after, customer_to_remove, -1);

                            Assert.IsTrue(route.Contains(customerToPlaceAfter, customerToRemove));
                            Assert.AreEqual(count, route.Count);
                            var customersInRoute = new HashSet <int>(route);
                            Assert.AreEqual(customersInRoute.Count, route.Count);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Tests all enumerations of a route.
        /// </summary>
        protected void DoTestEnumerateBetween()
        {
            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);
                }
            }

            for (int from = 0; from < count; from++)
            {
                for (int to = 0; to < count; to++)
                {
                    IEnumerator <int> enumerator = route.Between(from, to).GetEnumerator();
                    for (int customer = from; customer - 1 != to; customer++)
                    {
                        if (customer == count)
                        {
                            customer = 0;
                        }

                        Assert.IsTrue(enumerator.MoveNext());
                        Assert.AreEqual(customer, enumerator.Current);
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Tests enumeration all edges.
        /// </summary>
        protected void DoTestEnumeratePairs()
        {
            // create a new empty route.
            IRoute route = this.BuildRoute(0, true);

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

            Assert.AreEqual(0, edges.Count);

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

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

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

                    for (int edge_from = 0; edge_from < customer; edge_from++)
                    {
                        Assert.AreEqual(edges[edge_from].From, edge_from);
                        Assert.AreEqual(edges[edge_from].To, edge_from + 1);
                    }
                    Assert.AreEqual(edges[edges.Count - 1].From, edges.Count - 1);
                    Assert.AreEqual(edges[edges.Count - 1].To, 0);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Tests if the route containts functions work correctly.
        /// </summary>
        public void DoTestContains()
        {
            // create a new empty route.
            const int count = 100;
            IRoute    route = this.BuildRoute(true);

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

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

                    Assert.AreEqual(customer + 1, route.Count);
                    Assert.AreEqual(false, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(0, route.First);
                    Assert.AreEqual(0, route.Last);
                }

                for (int customer = 0; customer < count - 1; customer++)
                {
                    Assert.IsTrue(route.Contains(customer));
                    Assert.IsTrue(route.Contains(customer, customer + 1));
                }
                Assert.IsTrue(route.Contains(count - 1));
                Assert.IsTrue(route.Contains(count - 1, 0));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Some tests on an IRoute.
        /// </summary>
        public void DoTestAdd()
        {
            // create a new empty route.
            IRoute route = this.BuildRoute(0, true);

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

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

                    Assert.AreEqual(customer + 1, route.Count);
                    Assert.AreEqual(false, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(0, route.First);
                    Assert.AreEqual(0, route.Last);
                }
            }

            // create a new empty route.
            route = this.BuildRoute(true);
            if (route != null)
            { // this part needs testing.
                Assert.AreEqual(0, route.Count);
                Assert.AreEqual(true, route.IsEmpty);
                Assert.AreEqual(true, route.IsRound);

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

                    Assert.AreEqual(customer + 1, route.Count);
                    Assert.AreEqual(false, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(0, route.First);
                    Assert.AreEqual(0, route.Last);
                }
            }
        }
Beispiel #6
0
 /// <summary>
 /// Removes the edge from->unknown and replaces it with the edge from->to->unknown.
 /// 0->1:InsertAfter(0, 2):0->2-1
 /// </summary>
 /// <param name="from"></param>
 /// <param name="to"></param>
 public void InsertAfter(int from, int to)
 {
     if (from == 0)
     {
         _route.InsertFirst(to);
     }
     else
     {
         _route.InsertAfter(from, to);
     }
 }
Beispiel #7
0
        /// <summary>
        /// Generates individuals based on a random first customer for each route.
        /// </summary>
        /// <param name="solver"></param>
        /// <returns></returns>
        public Individual <MaxTimeSolution, MaxTimeProblem, Fitness> Generate(
            Solver <MaxTimeSolution, MaxTimeProblem, Fitness> solver)
        {
            MaxTimeProblem problem = solver.Problem;

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

            // create the problem for the genetic algorithm.
            List <int> customers = new List <int>();

            for (int customer = 0; customer < problem.Size; customer++)
            {
                customers.Add(customer);
            }
            //BestPlacementHelper helper = new BestPlacementHelper();

            // keep placing customer until none are left.
            while (customers.Count > 0)
            {
                // select a random customer.
                double weight       = 0;
                int    customer_idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers.Count);
                int    customer     = customers[customer_idx];
                customers.RemoveAt(customer_idx);

                // use best placement to generate a route.
                IRoute current_route = solution.Add(customer);
                //Console.WriteLine("Starting new route with {0}", customer);
                while (customers.Count > 0)
                {
                    // calculate the best placement.
                    int customer_to_place          = customers[OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers.Count)];
                    CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customer_to_place);

                    // calculate the new weight.
                    double potential_weight = result.Increase + weight + 20;
                    // cram as many customers into one route as possible.
                    if (potential_weight < problem.Max.Value)
                    { // ok we are done!
                        customers.Remove(result.Customer);
                        //current_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                        current_route.InsertAfter(result.CustomerBefore, result.Customer);
                        weight = potential_weight;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(new Individual <MaxTimeSolution, MaxTimeProblem, Fitness>(solution));
        }
Beispiel #8
0
        /// <summary>
        /// Tests adding customers.
        /// </summary>
        public void DoTestRemove()
        {
            IMultiRoute multiRoute = this.BuildRoute(true);

            Assert.AreEqual(0, multiRoute.Count);
            int count  = 10;
            int routes = 3;

            // test with initializing the routes empty.
            var customersPerRoute = new List <List <int> >();

            Assert.AreEqual(0, multiRoute.Count);
            for (int routeIdx = 0; routeIdx < routes; routeIdx++)
            {
                customersPerRoute.Add(new List <int>());
                int    customerStart = (routeIdx * count);
                IRoute route         = multiRoute.Add();

                for (int customer = customerStart; customer < customerStart + count; customer++)
                {
                    customersPerRoute[routeIdx].Add(customer);
                    route.InsertAfter(customer - 1, customer);
                    //route.InsertAfterAndRemove(customer - 1, customer, -1);
                }
            }

            // remove all the customers.
            while (customersPerRoute.Count > 0)
            {
                int routeIdx    = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customersPerRoute.Count);
                int customerIdx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customersPerRoute[routeIdx].Count);

                int customer = customersPerRoute[routeIdx][customerIdx];
                customersPerRoute[routeIdx].RemoveAt(customerIdx);

                IRoute route = multiRoute.Route(routeIdx);
                route.Remove(customer);

                Assert.AreEqual(customersPerRoute[routeIdx].Count, route.Count);
                Assert.AreEqual(customersPerRoute[routeIdx].Count == 0, route.IsEmpty);
                Assert.AreEqual(true, route.IsRound);
                Assert.AreEqual(route.First, route.Last);

                if (customersPerRoute[routeIdx].Count == 0)
                {
                    customersPerRoute.RemoveAt(routeIdx);
                    multiRoute.Remove(routeIdx);
                }
            }
        }
        /// <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);
        }
Beispiel #10
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);
        }
Beispiel #11
0
        public MaxTimeSolution ChangeSizes(MaxTimeProblem problem, MaxTimeSolution solution, IEnumerable <int> sizes)
        {
            MaxTimeSolution changed_solution = new MaxTimeSolution(
                solution.Size, true);

            //int[] next_array = new int[solution.Size];
            bool[] used = new bool[solution.Size];
            //List<int> first = new List<int>();
            foreach (int size in sizes)
            {
                int current = 0;
                while (used[current])
                {
                    current++;
                }
                IRoute route = changed_solution.Add(current);
                used[current] = true;
                int current_size = size - 1;
                int previous     = current;
                while (current_size > 0)
                {
                    // choose the next customer.
                    current = solution.Next(current);
                    if (used[current])
                    {
                        double neighbour_weight = double.MaxValue;
                        foreach (int nn in problem.Get10NearestNeighbours(previous))
                        {
                            if (!used[nn])
                            {
                                double potential_weight =
                                    problem.WeightMatrix[previous][current];
                                if (potential_weight < neighbour_weight)
                                {
                                    current          = nn;
                                    neighbour_weight = potential_weight;
                                }
                                //break;
                            }
                        }
                        int used_count = 0;
                        while (used[current])
                        {
                            current++;
                            used_count++;

                            if (current == solution.Size)
                            {
                                current = 0;
                            }

                            //if (used_count == problem.Size)
                            //{
                            //    break;
                            //}
                        }
                    }

                    // set the next array.
                    //route.InsertAfterAndRemove(previous, current, route.First);
                    route.InsertAfter(previous, current);
                    used[current] = true;
                    previous      = current;
                    current_size--;
                }

                if (!changed_solution.IsValid())
                {
                    throw new Exception();
                }
            }
            return(changed_solution);
        }
Beispiel #12
0
        /// <summary>
        /// Executes a solver procedure.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            // create the solution.
            var solution = new MaxTimeSolution(problem.Size);

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

            customers.RemoveAt(0);

            double max = problem.Max.Value - (problem.Max.Value * _deltaPercentage);

            // keep a list of cheapest insertions.
            IInsertionCosts costs      = new BinaryHeapInsertionCosts();
            double          percentage = _thresholdPercentage;

            while (customers.Count > 0)
            {
                //// try and distribute the remaining customers if there are only a few left.
                //if (customers.Count < problem.Size * percentage)
                //{
                //    bool succes = true;
                //    while (succes && customers.Count > 0)
                //    {
                //        succes = false;
                //        CheapestInsertionResult best = new CheapestInsertionResult();
                //        best.Increase = float.MaxValue;
                //        int best_idx = -1;
                //        for (int route_idx = 0; route_idx < solution.Count; route_idx++)
                //        {
                //            IRoute route = solution.Route(route_idx);
                //            CheapestInsertionResult result =
                //                CheapestInsertionHelper.CalculateBestPlacement(problem, route, customers);
                //            if (best.Increase > result.Increase)
                //            {
                //                best = result;
                //                best_idx = route_idx;
                //            }
                //        }

                //        IRoute best_route = solution.Route(best_idx);
                //        double route_time = problem.Time(best_route);
                //        if (route_time + best.Increase < max)
                //        { // insert the customer.
                //            best_route.InsertAfter(best.CustomerBefore, best.Customer);
                //            customers.Remove(best.Customer);

                //            this.Improve(problem, solution, max, best_idx);

                //            succes = true;
                //        }
                //    }
                //}

                // select a customer using some heuristic.
                int customer = this.SelectSeed(problem, problem.MaxTimeCalculator, solution, customers);
                customers.Remove(customer);

                // start a route r.
                IRoute currentRoute = solution.Add(customer);
                solution[solution.Count - 1] = 0;

                while (customers.Count > 0)
                {
                    // calculate the best placement.
                    CheapestInsertionResult result;
                    if (_useSeedCost)
                    { // use the seed cost; the cost to the seed customer.
                        result = CheapestInsertionHelper.CalculateBestPlacement(problem, currentRoute, customers,
                                                                                customer, 0.7);

                        // calculate the 'real' increase.
                        result.Increase = (problem.WeightMatrix[result.CustomerBefore][result.Customer] +
                                           problem.WeightMatrix[result.Customer][result.CustomerAfter]) -
                                          problem.WeightMatrix[result.CustomerBefore][result.CustomerAfter];
                    }
                    else
                    { // just use cheapest insertion.
                        result = CheapestInsertionHelper.CalculateBestPlacement(problem, currentRoute, customers, costs);
                    }

                    // calculate the new weight.
                    solution[solution.Count - 1] = problem.Time(solution.Route(solution.Count - 1));
                    double potentialWeight = problem.MaxTimeCalculator.CalculateOneRouteIncrease(solution[solution.Count - 1],
                                                                                                 result.Increase);
                    // cram as many customers into one route as possible.
                    if (potentialWeight < max)
                    {
                        // insert the customer, it is
                        customers.Remove(result.Customer);
                        currentRoute.InsertAfter(result.CustomerBefore, result.Customer);

                        // free some memory in the costs list.
                        costs.Remove(result.CustomerBefore, result.CustomerAfter);

                        // update the cost of the route.
                        solution[solution.Count - 1] = potentialWeight;

                        // improve if needed.
                        if (((problem.Size - customers.Count) % _k) == 0)
                        { // an improvement is decided.
                            // apply the inter-route improvements.
                            var copy = (solution.Clone() as MaxTimeSolution);

                            int countBefore = solution.Route(solution.Count - 1).Count;

                            solution[solution.Count - 1] = this.ImproveIntraRoute(problem,
                                                                                  solution.Route(solution.Count - 1), solution[solution.Count - 1]);
                            if (!solution.IsValid())
                            {
                                throw new Exception();
                            }
                            int countAfter = solution.Route(solution.Count - 1).Count;
                            if (countAfter != countBefore)
                            {
                                throw new Exception();
                            }

                            // also to the inter-improvements.
                            currentRoute = this.Improve(problem, solution, max, solution.Count - 1);
                        }
                    }
                    else
                    {// ok we are done!
                        this.Improve(problem, solution, max, solution.Count - 1);

                        // break the route.
                        break;
                    }
                }
            }

            // remove empty routes.
            for (int routeIdx = solution.Count - 1; routeIdx >= 0; routeIdx--)
            {
                if (solution.Route(routeIdx).IsEmpty)
                {
                    solution.Remove(routeIdx);
                }
            }

            return(solution);
        }
        /// <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;
            //}
            //}
        }
Beispiel #14
0
        /// <summary>
        /// Generates individuals based on a random first customer for each route.
        /// </summary>
        /// <param name="solver"></param>
        /// <returns></returns>
        public Individual <List <Genome>, Problem, Fitness> Generate(
            Solver <List <Genome>, Problem, Fitness> solver)
        {
            Problem problem = solver.Problem;

            DynamicAsymmetricMultiRoute multi_route = new DynamicAsymmetricMultiRoute(problem.Size, true);

            // create the problem for the genetic algorithm.
            List <int> customers = new List <int>();

            for (int customer = problem.Depots.Count; customer < problem.Size; customer++)
            {
                customers.Add(customer);
            }
            CheapestInsertionHelper helper = new CheapestInsertionHelper();

            List <double> weights = new List <double>();

            for (int i = 0; i < problem.Depots.Count; i++)
            {
                multi_route.Add(i);
                weights.Add(0);
            }
            int k = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(problem.Depots.Count);

            // keep placing customer until none are left.
            while (customers.Count > 0)
            {
                k = (k + 1) % problem.Depots.Count;

                // use best placement to generate a route.
                IRoute current_route = multi_route.Route(k);


                //Console.WriteLine("Starting new route with {0}", customer);
                while (customers.Count > 0)
                {
                    // calculate the best placement.
                    CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers);

                    if (result.CustomerAfter == -1 || result.CustomerBefore == -1)
                    {
                        customers.Remove(result.Customer);
                        continue;
                    }
                    // calculate the new weight.
                    customers.Remove(result.Customer);
                    //current_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                    current_route.InsertAfter(result.CustomerBefore, result.Customer);
                    weights[k] += result.Increase + 15 * 60;

                    if (weights[k] == weights.Max())
                    {
                        break;
                    }
                }
            }

            for (int i = 0; i < problem.Depots.Count; i++)
            {
                multi_route.RemoveCustomer(i);
            }


            List <Genome> genomes = new List <Genome>();

            genomes.Add(Genome.CreateFrom(multi_route));
            Individual <List <Genome>, Problem, Fitness> individual = new Individual <List <Genome>, Problem, Fitness>(genomes);

            //individual.Initialize();
            return(individual);
        }
        public Individual <MaxTimeSolution, MaxTimeProblem, Fitness> CrossOver(
            Solver <MaxTimeSolution, MaxTimeProblem, Fitness> solver,
            Individual <MaxTimeSolution, MaxTimeProblem, Fitness> parent1,
            Individual <MaxTimeSolution, MaxTimeProblem, Fitness> parent2)
        {
            MaxTimeCalculator calculator = new MaxTimeCalculator(solver.Problem);

            MaxTimeSolution route1 = parent1.Genomes;
            MaxTimeSolution route2 = parent2.Genomes;

            // get the minimum size of both routes.
            int size = route1.Count;

            if (route2.Count < size)
            {
                size = route2.Count;
            }

            // select a random number of routes.
            HashSet <int> selected_first  = new HashSet <int>();
            HashSet <int> selected_second = new HashSet <int>();
            List <IRoute> selected_routes = new List <IRoute>();
            bool          first           = true;

            while (selected_routes.Count < size)
            {
                // select route.
                int selected_route = -1;
                if (first)
                {
                    selected_route = this.ChooseNextFrom(selected_routes, route1, selected_first);

                    selected_first.Add(selected_route);
                    selected_routes.Add(route1.Route(selected_route));
                }
                else
                {
                    selected_route = this.ChooseNextFrom(selected_routes, route2, selected_second);

                    selected_second.Add(selected_route);
                    selected_routes.Add(route2.Route(selected_route));
                }

                first = !first;
            }

            // generate the new customer genome.
            MaxTimeSolution solution = new MaxTimeSolution(route1.Size, true);

            int previous = -1;

            foreach (IRoute route in selected_routes)
            {
                IRoute current_route = null;
                foreach (int customer in route)
                {
                    MaxTimeSolution copy            = (solution.Clone() as MaxTimeSolution);
                    string          solution_string = solution.ToString();
                    if (!solution.Contains(customer))
                    {
                        if (current_route == null)
                        { // add the route.
                            current_route = solution.Add(customer);

                            // safe the previous customer.
                            previous = customer;

                            if (!solution.IsValid())
                            {
                                throw new Exception();
                            }
                        }
                        else
                        { // add the customer.
                            string current_route_string = current_route.ToString();
                            //current_route.InsertAfterAndRemove(previous, customer, current_route.First);
                            current_route.InsertAfter(previous, customer);
                            //current_route.InsertAfter(customer, current_route.First);

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

                            // safe the previous customer.
                            previous = customer;
                        }
                    }
                }
            }

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

            this.FillRoutes(calculator, route1, solution, solver.Problem);

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

            return(new Individual <MaxTimeSolution, MaxTimeProblem, Fitness>(solution));
        }
Beispiel #16
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;
            //}
            //}
        }
        /// <summary>
        /// Executes a solver procedure.
        /// </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);

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

            while (customers.Count > 0)
            {
                // select a customer using some heuristic.
                int customer_idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers.Count);
                int customer     = customers[customer_idx];
                customers.Remove(customer);

                // start a route r.
                double current_route_weight = 0;
                IRoute current_route        = solution.Add(customer);
                //Console.WriteLine("Starting new route with {0}", customer);
                while (customers.Count > 0)
                {
                    // calculate the best placement.
                    CheapestInsertionResult result =
                        CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers);

                    // calculate the new weight.
                    double potential_weight = calculator.CalculateOneRouteIncrease(current_route_weight, result.Increase);
                    // cram as many customers into one route as possible.
                    if (potential_weight < problem.Max.Value)
                    {
                        // insert the customer, it is
                        customers.Remove(result.Customer);
                        //current_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                        current_route.InsertAfter(result.CustomerBefore, result.Customer);
                        current_route_weight = potential_weight;

                        //// improve if needed.
                        ////if (improvement_probalitity > OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(1))
                        //if (((problem.Size - customers.Count) % _k) == 0)
                        //{ // an improvement is descided.
                        //    current_route_weight = this.ImproveIntraRoute(problem,
                        //        current_route, current_route_weight);
                        //}
                    }
                    else
                    {// ok we are done!
                        //// apply the intra-route heuristics.
                        //for (int route_idx = 0; route_idx < solution.Count - 1; route_idx++)
                        //{ // apply the intra-route heurstic between the new and all existing routes.
                        //    this.ImproveInterRoute(problem, solution.Route(route_idx), current_route);
                        //}

                        //// apply the inter-route heuristics.
                        //for (int route_idx = 0; route_idx < solution.Count; route_idx++)
                        //{ // apply heurstic for each route.
                        //    IRoute route = solution.Route(route_idx);
                        //    this.ImproveIntraRoute(problem, current_route, current_route_weight);
                        //}

                        // break the route.
                        break;
                    }
                }
            }

            return(solution);
        }
Beispiel #18
0
        /// <summary>
        /// Executes a solver procedure.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            // create the solution.
            MaxTimeSolution solution = new MaxTimeSolution(problem.Size, true);

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

            double max = problem.Max.Value - (problem.Max.Value * _delta_percentage);

            // keep a list of cheapest insertions.
            IInsertionCosts costs      = new BinaryHeapInsertionCosts();
            double          percentage = _threshold_percentage;

            while (customers.Count > 0)
            {
                // try and distribute the remaining customers if there are only a few left.
                if (customers.Count < problem.Size * percentage)
                {
                    bool succes = true;
                    while (succes && customers.Count > 0)
                    {
                        succes = false;
                        CheapestInsertionResult best = new CheapestInsertionResult();
                        best.Increase = float.MaxValue;
                        int best_idx = -1;
                        for (int route_idx = 0; route_idx < solution.Count; route_idx++)
                        {
                            IRoute route = solution.Route(route_idx);
                            CheapestInsertionResult result =
                                CheapestInsertionHelper.CalculateBestPlacement(problem, route, customers);
                            if (best.Increase > result.Increase)
                            {
                                best     = result;
                                best_idx = route_idx;
                            }
                        }

                        IRoute best_route = solution.Route(best_idx);
                        double route_time = problem.Time(best_route);
                        if (route_time + best.Increase < max)
                        { // insert the customer.
                            best_route.InsertAfter(best.CustomerBefore, best.Customer);
                            customers.Remove(best.Customer);

                            this.Improve(problem, solution, max, best_idx);

                            succes = true;
                        }
                    }
                }

                // select a customer using some heuristic.
                if (customers.Count > 0)
                {
                    // select a customer using some heuristic.
                    int customer = -1;
                    if (_use_seed)
                    { // use a seeding heuristic.
                        customer = this.SelectSeed(problem, problem.MaxTimeCalculator, solution, customers);
                    }
                    else
                    { // just select a random customer.
                        customer = customers[Math.Random.StaticRandomGenerator.Get().Generate(customers.Count)];
                    }
                    customers.Remove(customer);

                    // start a route r.
                    IRoute current_route = solution.Add(customer);
                    solution[solution.Count - 1] = 0;

                    while (customers.Count > 0)
                    {
                        //OsmSharp.IO.Output.OutputStreamHost.WriteLine("{0}/{1} placed!",
                        //    customers.Count, problem.Size);

                        // calculate the best placement.
                        CheapestInsertionResult result;
                        if (_use_seed_cost)
                        { // use the seed cost; the cost to the seed customer.
                            result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers,
                                                                                    customer, _lambda);

                            // calculate the 'real' increase.
                            result.Increase = (problem.WeightMatrix[result.CustomerBefore][result.Customer] +
                                               problem.WeightMatrix[result.Customer][result.CustomerAfter]) -
                                              problem.WeightMatrix[result.CustomerBefore][result.CustomerAfter];
                        }
                        else
                        { // just use cheapest insertion.
                            result = CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, customers, costs);
                        }

                        // calculate the new weight.
                        solution[solution.Count - 1] = problem.Time(solution.Route(solution.Count - 1));
                        double potential_weight = problem.MaxTimeCalculator.CalculateOneRouteIncrease(solution[solution.Count - 1],
                                                                                                      result.Increase);
                        // cram as many customers into one route as possible.
                        if (potential_weight < max)
                        {
                            // insert the customer, it is
                            customers.Remove(result.Customer);
                            current_route.InsertAfter(result.CustomerBefore, result.Customer);

                            // free some memory in the costs list.
                            costs.Remove(result.CustomerBefore, result.CustomerAfter);

                            // update the cost of the route.
                            solution[solution.Count - 1] = potential_weight;

                            // improve if needed.
                            if (((problem.Size - customers.Count) % _k) == 0)
                            { // an improvement is descided.
                                // apply the inter-route improvements.
                                int count_before = solution.Route(solution.Count - 1).Count;

                                solution[solution.Count - 1] = this.ImproveIntraRoute(problem,
                                                                                      current_route, solution[solution.Count - 1]);
                                if (!solution.IsValid())
                                {
                                    throw new Exception();
                                }
                                int count_after = solution.Route(solution.Count - 1).Count;

                                // also to the inter-improvements.
                                current_route = this.Improve(problem, solution, max, solution.Count - 1);
                            }
                        }
                        else
                        {// ok we are done!
                            this.Improve(problem, solution, max, solution.Count - 1);

                            // break the route.
                            break;
                        }
                    }
                    //else
                    //{// ok we are done!
                    //    solution[solution.Count - 1] = this.ImproveIntraRoute(problem,
                    //        current_route, solution[solution.Count - 1]);

                    //    if (!solution.IsValid())
                    //    {
                    //        throw new Exception();
                    //    }
                    //    int count_after = solution.Route(solution.Count - 1).Count;

                    //    this.Improve(problem, solution, max, solution.Count - 1);

                    //    // break the route.
                    //    break;
                    //}
                }
            }

            // remove empty routes.
            for (int route_idx = solution.Count - 1; route_idx >= 0; route_idx--)
            {
                if (solution.Route(route_idx).IsEmpty)
                {
                    solution.Remove(route_idx);
                }
            }

            return(solution);
        }
Beispiel #19
0
        /// <summary>
        /// Tests adding customers.
        /// </summary>
        public void DoTestAdd()
        {
            IMultiRoute multiRoute = this.BuildRoute(true);

            Assert.AreEqual(0, multiRoute.Count);
            int count  = 10;
            int routes = 3;

            for (int routeIdx = 0; routeIdx < routes; routeIdx++)
            {
                int    customerStart = (routeIdx * count);
                IRoute route         = multiRoute.Add(customerStart);
                Assert.AreEqual(1, route.Count);
                Assert.AreEqual(false, route.IsEmpty);
                Assert.AreEqual(true, route.IsRound);
                for (int customer = customerStart + 1; customer < customerStart + count; customer++)
                {
                    route.InsertAfter(customer - 1, customer);

                    Assert.AreEqual(customer - customerStart + 1, route.Count);
                    Assert.AreEqual(false, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(customerStart, route.First);
                    Assert.AreEqual(customerStart, route.Last);
                }

                for (int customer = customerStart + 1; customer < customerStart + count - 1; customer++)
                {
                    Assert.IsTrue(route.Contains(customer));
                    Assert.IsTrue(route.Contains(customer, customer + 1));
                }
                Assert.IsTrue(route.Contains(customerStart + count - 1));
                Assert.IsTrue(route.Contains(customerStart + count - 1, customerStart));

                Assert.AreEqual(routeIdx + 1, multiRoute.Count);
                Assert.AreEqual(count * (routeIdx + 1), multiRoute.Size);
            }

            // test with initializing the routes empty.
            multiRoute = this.BuildRoute(true);

            Assert.AreEqual(0, multiRoute.Count);
            for (int routeIdx = 0; routeIdx < routes; routeIdx++)
            {
                int    customerStart = (routeIdx * count);
                IRoute route         = multiRoute.Add();
                Assert.AreEqual(0, route.Count);
                Assert.AreEqual(true, route.IsEmpty);
                Assert.AreEqual(true, route.IsRound);
                for (int customer = customerStart; customer < customerStart + count; customer++)
                {
                    route.InsertAfter(customer - 1, customer);

                    Assert.AreEqual(customer - customerStart + 1, route.Count);
                    Assert.AreEqual(false, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(customerStart, route.First);
                    Assert.AreEqual(customerStart, route.Last);
                }

                for (int customer = customerStart; customer < customerStart + count - 1; customer++)
                {
                    Assert.IsTrue(route.Contains(customer));
                    Assert.IsTrue(route.Contains(customer, customer + 1));
                }
                Assert.IsTrue(route.Contains(customerStart + count - 1));
                Assert.IsTrue(route.Contains(customerStart + count - 1, customerStart));

                Assert.AreEqual(routeIdx + 1, multiRoute.Count);
                Assert.AreEqual(count * (routeIdx + 1), multiRoute.Size);
            }
        }
        /// <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;
        }
        /// <summary>
        /// Does the mutation.
        /// </summary>
        /// <param name="solver"></param>
        /// <param name="mutating"></param>
        /// <returns></returns>
        public Individual <MaxTimeSolution, MaxTimeProblem, Fitness> Mutate(
            Solver <MaxTimeSolution, MaxTimeProblem, Fitness> solver,
            Individual <MaxTimeSolution, MaxTimeProblem, Fitness> mutating)
        {
            // get the route information.
            MaxTimeSolution multi_route = mutating.Genomes.Clone() as MaxTimeSolution;

            if (multi_route.Count > 1)
            { // TODO: Maybe add some extra code for the the route-count is very low and chances of collisions are big.
                // TODO: investigate what is more expensive, and extra random generation or creating a list and remove items.
                // http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
                // select a route.
                int source_route_idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(multi_route.Count);
                int target_route_idx = -1;
                do
                {
                    target_route_idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(multi_route.Count);
                } while (source_route_idx == target_route_idx);
                int source_count = multi_route.Sizes[source_route_idx];
                int target_count = multi_route.Sizes[target_route_idx];
                if (target_count > 0 && source_count > 3)
                {
                    // take a part out of the orginal.
                    int size            = (int)OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(source_count);
                    int source_location = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(source_count);

                    int first = source_location - (size / 2);
                    if (first < 0)
                    {
                        first = 0;
                    }
                    //first = multi_route.StartOf(source_route_idx) + first;
                    int last = source_location + (size / 2);
                    if (last > source_count - 1)
                    {
                        last = source_count - 1;
                    }
                    //last = multi_route.StartOf(source_route_idx) + last;
                    int        idx             = -1;
                    IRoute     source          = multi_route.Route(source_route_idx);
                    List <int> part_of_orginal = new List <int>();
                    foreach (int customer in source)
                    {
                        idx++;
                        if (idx >= first && idx <= last)
                        {
                            part_of_orginal.Add(customer);
                        }
                    }

                    // remove from the source.
                    foreach (int customer in part_of_orginal)
                    {
                        multi_route.RemoveCustomer(customer);
                    }

                    // place it somewhere in the target.
                    if (part_of_orginal.Count > 0)
                    {
                        IRoute target = multi_route.Route(target_route_idx);

                        CheapestInsertionResult route_placement = CheapestInsertionHelper.CalculateBestPlacement(
                            solver.Problem, target, part_of_orginal[0], part_of_orginal[part_of_orginal.Count - 1]);

                        int from = route_placement.CustomerBefore;
                        foreach (int customer in part_of_orginal)
                        {
                            target.InsertAfter(from, customer);
                            //target.InsertAfterAndRemove(from, customer, -1);
                            from = customer;
                        }
                    }
                }
            }

            return(new Individual <MaxTimeSolution, MaxTimeProblem, Fitness>(multi_route));
        }
Beispiel #22
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);
        }
        private void FillRoutes(MaxTimeCalculator calculator, MaxTimeSolution route1, MaxTimeSolution solution,
                                MaxTimeProblem problem)
        {
            double[] weights = new double[solution.Count];

            // insert all non-placed customers in the order of the first route.
            HashSet <int> unplaced = new HashSet <int>();

            for (int route_idx = 0; route_idx < route1.Count; route_idx++)
            {
                IRoute route1_route = route1.Route(route_idx);
                foreach (int customer in route1_route)
                {
                    if (!solution.Contains(customer))
                    {
                        unplaced.Add(customer);
                    }
                }
            }

            for (int idx = 0; idx < solution.Count; idx++)
            {
                IRoute route = solution.Route(idx);
                weights[idx] = calculator.CalculateOneRoute(route);
            }

            // insert all non-placed customers in the order of the first route.
            //for (int route_idx = 0; route_idx < route1.Count; route_idx++)
            //{
            //    IRoute route1_route = route1.Route(route_idx);
            //    foreach (int customer in route1_route)
            //    {
            //        if (!solution.Contains(customer))
            //        {
            while (unplaced.Count > 0)
            {
                int customer = unplaced.First <int>();

                // try reinsertion.
                CheapestInsertionResult result = new CheapestInsertionResult();
                result.Increase = double.MaxValue;
                int target_idx = -1;

                CheapestInsertionResult unlimited_result = new CheapestInsertionResult();
                unlimited_result.Increase = double.MaxValue;
                int unlimited_target_idx = -1;
                for (int idx = 0; idx < solution.Count; idx++)
                {
                    IRoute route = solution.Route(idx);

                    CheapestInsertionResult current_result =
                        CheapestInsertionHelper.CalculateBestPlacement(problem.Weights, route, customer);
                    if (current_result.Increase < result.Increase)
                    {
                        if (weights[idx] + current_result.Increase < problem.Max.Value)
                        {
                            target_idx = idx;
                            result     = current_result;

                            if (result.Increase <= 0)
                            {
                                break;
                            }
                        }
                    }
                    if (current_result.Increase < unlimited_result.Increase)
                    {
                        unlimited_target_idx = idx;
                        unlimited_result     = current_result;
                    }
                }

                if (target_idx < 0)
                {
                    result     = unlimited_result;
                    target_idx = unlimited_target_idx;
                }

                // get the target route and insert.
                IRoute target_route = solution.Route(target_idx);
                weights[target_idx] = weights[target_idx] + result.Increase;
                //target_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                target_route.InsertAfter(result.CustomerBefore, result.Customer);
                unplaced.Remove(result.Customer);

                ////solution.ToString();
                //if (!solution.IsValid())
                //{
                //    throw new Exception();
                //}
            }
            //    }
            //}
        }
Beispiel #24
0
        /// <summary>
        /// Test removing customers.
        /// </summary>
        public void DoTestRemove()
        {
            // create a new empty route.
            const int count     = 100;
            IRoute    route     = this.BuildRoute(0, true);
            var       customers = new List <int>();

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

                // remove customers.
                while (customers.Count > 0)
                {
                    int customerIdx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(
                        customers.Count);
                    int customer = customers[customerIdx];
                    customers.RemoveAt(customerIdx);

                    route.Remove(customer);

                    Assert.AreEqual(customers.Count, route.Count);
                    Assert.AreEqual(customers.Count == 0, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(route.Last, route.First);
                }
            }

            route     = this.BuildRoute(true);
            customers = new List <int>();
            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);
                    customers.Add(customer);
                }

                // remove customers.
                while (customers.Count > 0)
                {
                    int customerIdx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(
                        customers.Count);
                    int customer = customers[customerIdx];
                    customers.RemoveAt(customerIdx);

                    route.Remove(customer);

                    Assert.AreEqual(customers.Count, route.Count);
                    Assert.AreEqual(customers.Count == 0, route.IsEmpty);
                    Assert.AreEqual(true, route.IsRound);
                    Assert.AreEqual(route.Last, route.First);
                }
            }
        }
Beispiel #25
0
        public void TestDepotDynamicAsymmetricMultiRouteExchanges()
        {
            // create two routes.
            // 0->11->12->13->14->15->0
            // 0->21->22->23->24->25->0
            var    multiRoute = new MaxTimeSolution(0);
            IRoute route1     = multiRoute.Add();
            var    customers  = new List <int>(route1);

            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route1.InsertAfter(0, 11);
            Assert.AreEqual("0->11", route1.ToString());
            route1.InsertAfter(11, 12);
            route1.InsertAfter(12, 13);
            route1.InsertAfter(13, 14);
            route1.InsertAfter(14, 15);
            IRoute route2 = multiRoute.Add();

            customers = new List <int>(route2);
            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route2.InsertAfter(0, 21);
            Assert.AreEqual("0->21", route2.ToString());
            route2.InsertAfter(21, 22);
            route2.InsertAfter(22, 23);
            route2.InsertAfter(23, 24);
            route2.InsertAfter(24, 25);

            customers = new List <int>(route1);
            Assert.AreEqual(6, customers.Count);
            Assert.AreEqual(0, customers[0]);
            Assert.AreEqual(11, customers[1]);
            Assert.AreEqual(12, customers[2]);
            Assert.AreEqual(13, customers[3]);
            Assert.AreEqual(14, customers[4]);
            Assert.AreEqual(15, customers[5]);


            customers = new List <int>(route2);
            Assert.AreEqual(6, customers.Count);
            Assert.AreEqual(0, customers[0]);
            Assert.AreEqual(21, customers[1]);
            Assert.AreEqual(22, customers[2]);
            Assert.AreEqual(23, customers[3]);
            Assert.AreEqual(24, customers[4]);
            Assert.AreEqual(25, customers[5]);

            // replace the entire first route.
            route1.ReplaceEdgeFrom(0, 0);

            route2.ReplaceEdgeFrom(25, 11);
            route2.ReplaceEdgeFrom(11, 12);
            route2.ReplaceEdgeFrom(12, 13);
            route2.ReplaceEdgeFrom(13, 14);
            route2.ReplaceEdgeFrom(14, 15);

            Assert.IsTrue(multiRoute.IsValid());

            // create two routes.
            // 0->11->12->13->14->15->0
            // 0->21->22->23->24->25->0
            multiRoute = new MaxTimeSolution(0);
            route1     = multiRoute.Add();
            customers  = new List <int>(route1);
            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route1.InsertAfter(0, 11);
            Assert.AreEqual("0->11", route1.ToString());
            route1.InsertAfter(11, 12);
            route1.InsertAfter(12, 13);
            route1.InsertAfter(13, 14);
            route1.InsertAfter(14, 15);
            route2    = multiRoute.Add();
            customers = new List <int>(route2);
            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route2.InsertAfter(0, 21);
            Assert.AreEqual("0->21", route2.ToString());
            route2.InsertAfter(21, 22);
            route2.InsertAfter(22, 23);
            route2.InsertAfter(23, 24);
            route2.InsertAfter(24, 25);

            // exchange parts.
            var part1 = new List <int>(route1.Between(11, 13));
            var part2 = new List <int>(route2.Between(23, 25));

            route1.ReplaceEdgeFrom(0, 14);
            route2.ReplaceEdgeFrom(22, 0);

            int previous = 0;

            for (int idx = 0; idx < part2.Count; idx++)
            {
                route1.ReplaceEdgeFrom(previous, part2[idx]);
                previous = part2[idx];
            }
            route1.ReplaceEdgeFrom(previous, 14);

            previous = 22;
            for (int idx = 0; idx < part1.Count; idx++)
            {
                route2.ReplaceEdgeFrom(previous, part1[idx]);
                previous = part1[idx];
            }
            route2.ReplaceEdgeFrom(previous, 0);

            Assert.IsTrue(multiRoute.IsValid());

            customers = new List <int>(route1);
            Assert.AreEqual(6, customers.Count);
            Assert.AreEqual(0, customers[0]);
            Assert.AreEqual(23, customers[1]);
            Assert.AreEqual(24, customers[2]);
            Assert.AreEqual(25, customers[3]);
            Assert.AreEqual(14, customers[4]);
            Assert.AreEqual(15, customers[5]);

            customers = new List <int>(route2);
            Assert.AreEqual(6, customers.Count);
            Assert.AreEqual(0, customers[0]);
            Assert.AreEqual(21, customers[1]);
            Assert.AreEqual(22, customers[2]);
            Assert.AreEqual(11, customers[3]);
            Assert.AreEqual(12, customers[4]);
            Assert.AreEqual(13, customers[5]);

            // create two routes.
            // 0->11->12->13->14->15->0
            // 0->21->22->23->24->25->0
            multiRoute = new MaxTimeSolution(0);
            route1     = multiRoute.Add();
            customers  = new List <int>(route1);
            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route1.InsertAfter(0, 11);
            Assert.AreEqual("0->11", route1.ToString());
            route1.InsertAfter(11, 12);
            route1.InsertAfter(12, 13);
            route1.InsertAfter(13, 14);
            route1.InsertAfter(14, 15);
            route2    = multiRoute.Add();
            customers = new List <int>(route2);
            Assert.AreEqual(1, customers.Count);
            Assert.AreEqual(0, customers[0]);
            route2.InsertAfter(0, 21);
            Assert.AreEqual("0->21", route2.ToString());
            route2.InsertAfter(21, 22);
            route2.InsertAfter(22, 23);
            route2.InsertAfter(23, 24);
            route2.InsertAfter(24, 25);

            route1.ReplaceEdgeFrom(12, 15);
            route1.ReplaceEdgeFrom(14, 11);
            route1.ReplaceEdgeFrom(0, 13);

            customers = new List <int>(route1);
            Assert.AreEqual(6, customers.Count);
            Assert.AreEqual(0, customers[0]);
            Assert.AreEqual(13, customers[1]);
            Assert.AreEqual(14, customers[2]);
            Assert.AreEqual(11, customers[3]);
            Assert.AreEqual(12, customers[4]);
            Assert.AreEqual(15, customers[5]);

            route1.ToString();
        }