Example #1
0
        /// <summary>
        /// Selects a new seed customer.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="solution"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        private int SelectSeed(MaxTimeProblem problem, MaxTimeCalculator calculator,
                               MaxTimeSolution solution, List <int> customers)
        {
            int    selected_customer = -1;
            double max_distance      = double.MaxValue;

            foreach (int customer_to_check in customers)
            {
                SortedDictionary <double, List <int> > neighbours = new SortedDictionary <double, List <int> >();
                for (int idx = 0; idx < customers.Count; idx++)
                {
                    int customer = customers[idx];
                    if (customer != customer_to_check)
                    {
                        double weight = problem.WeightMatrix[customer_to_check][customer] +
                                        problem.WeightMatrix[customer_to_check][customer];
                        List <int> customers_list = null;
                        if (!neighbours.TryGetValue(weight, out customers_list))
                        {
                            customers_list = new List <int>();
                            neighbours.Add(weight, customers_list);
                        }
                        customers_list.Add(customer);
                    }
                }

                double nearest_neighbour_average = 0;
                int    neighbour_count           = 20;
                int    neighbour_counted         = 0;
                foreach (KeyValuePair <double, List <int> > pair in neighbours)
                {
                    foreach (int customer in pair.Value)
                    {
                        if (neighbour_counted < neighbour_count)
                        {
                            neighbour_counted++;
                            nearest_neighbour_average = nearest_neighbour_average +
                                                        pair.Key;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (max_distance > nearest_neighbour_average)
                {
                    max_distance      = nearest_neighbour_average;
                    selected_customer = customer_to_check;
                }
            }
            return(selected_customer);
        }
Example #2
0
        /// <summary>
        /// Selects a new seed customer.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="solution"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        private int SelectSeed(MaxTimeProblem problem, MaxTimeCalculator calculator,
                               MaxTimeSolution solution, List <int> customers)
        { // select the customer farthest from the depot.
            int    selectedCustomer = -1;
            double maxDistance      = double.MinValue;

            foreach (int customerToCheck in customers)
            {
                double distance = problem.WeightMatrix[0][customerToCheck] +
                                  problem.WeightMatrix[customerToCheck][0];
                if (distance > maxDistance)
                {
                    maxDistance      = distance;
                    selectedCustomer = customerToCheck;
                }
            }
            return(selectedCustomer);
        }
        /// <summary>
        /// Executes a solver procedure.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            MaxTimeCalculator calculator = new MaxTimeCalculator(problem);

            // get the seed customers.
            ICollection<int> seeds = _seed_selector.SelectSeeds(
                problem, _k);
            double[] weights = new double[seeds.Count];

            // start the seed routes.
            List<int> selectable_customers = problem.Customers;
            MaxTimeSolution routes = new MaxTimeSolution(
                problem.Size, true);
            foreach (int seed in seeds)
            {
                routes.Add(seed);
                selectable_customers.Remove(seed);
            }

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

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

            // keep looping until all customers have been placed.
            while (selectable_customers.Count > 0)
            {
                // try and place into every route.
                CheapestInsertionResult best_result = new CheapestInsertionResult();
                best_result.Increase = float.MaxValue;
                int best_route_idx = -1;

                CheapestInsertionResult best_result_above_max = new CheapestInsertionResult();
                best_result_above_max.Increase = float.MaxValue;
                int best_route_above_max_idx = -1;

                for (int route_idx = 0; route_idx < routes.Count; route_idx++)
                {
                    IRoute current_route = routes.Route(route_idx);

                    // choose the next customer.
                    CheapestInsertionResult result =
                        CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, selectable_customers, costs);
                    if (result.Customer == result.CustomerAfter)
                    {
                        throw new Exception();
                    }
                    // get the current weight
                    double weight = weights[route_idx];
                    if (result.Increase < best_result.Increase)
                    {
                        if (weight + result.Increase + calculator.DeliveryTime < problem.Max.Value)
                        { // route will still be inside bounds.
                            best_result = result;
                            best_route_idx = route_idx;
                        }
                        else
                        { // route will become above max.
                            if (result.Increase < best_result_above_max.Increase)
                            {
                                best_result_above_max = result;
                                best_route_above_max_idx = route_idx;
                            }
                        }
                    }
                }

                // do the placement if a placement is found without max violation.
                // else do the placement in the above max route.
                CheapestInsertionResult placement_result = new CheapestInsertionResult();
                placement_result.Increase = double.MaxValue;
                int placement_result_idx = -1;
                if (best_route_idx >= 0)
                { // best placement found.
                    placement_result = best_result;
                    placement_result_idx = best_route_idx;
                }
                else
                { // best placement found but only above max.
                    placement_result = best_result_above_max;
                    placement_result_idx = best_route_above_max_idx;
                }

                // do the actual placement.
                weights[placement_result_idx] = calculator.CalculateOneRouteIncrease(
                    weights[placement_result_idx], placement_result.Increase);
                selectable_customers.Remove(placement_result.Customer);
                //routes.Route(placement_result_idx).InsertAfterAndRemove(
                //    placement_result.CustomerBefore, placement_result.Customer, placement_result.CustomerAfter);
                routes.Route(placement_result_idx).InsertAfter(
                    placement_result.CustomerBefore, placement_result.Customer);

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

            return routes;
        }
        /// <summary>
        /// Calculates a solution.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            // create the calculator.
            MaxTimeCalculator calculator = new MaxTimeCalculator(problem);

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

            double max = problem.Max.Value;

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

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

            // creates a result.
            MergeResult result = new MergeResult();
            result.Weight = double.MaxValue;

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

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

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

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

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

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

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

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

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

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

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

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

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

            return solution;
        }
        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));
        }
        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();
                //}
            }
            //    }
            //}
        }
Example #7
0
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            MaxTimeCalculator calculator = new MaxTimeCalculator(
                problem);

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

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

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

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

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

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

            previous = start;

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

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

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

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

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

            StringBuilder builder = new StringBuilder();

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

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

            return(solution);
        }
        /// <summary>
        /// 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);
        }
        /// <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.Tools.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.Tools.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;
        }
        /// <summary>
        /// Selects a new seed customer.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="solution"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        private int SelectSeed(MaxTimeProblem problem, MaxTimeCalculator calculator, 
            MaxTimeSolution solution, List<int> customers)
        {
            int selected_customer = -1;
            double max_distance = double.MaxValue;
            foreach (int customer_to_check in customers)
            {
                SortedDictionary<double, List<int>> neighbours = new SortedDictionary<double, List<int>>();
                for (int idx = 0; idx < customers.Count; idx++)
                {
                    int customer = customers[idx];
                    if (customer != customer_to_check)
                    {
                        double weight = problem.WeightMatrix[customer_to_check][customer] +
                            problem.WeightMatrix[customer_to_check][customer];
                        List<int> customers_list = null;
                        if (!neighbours.TryGetValue(weight, out customers_list))
                        {
                            customers_list = new List<int>();
                            neighbours.Add(weight, customers_list);
                        }
                        customers_list.Add(customer);
                    }
                }

                double nearest_neighbour_average = 0;
                int neighbour_count = 20;
                int neighbour_counted = 0;
                foreach (KeyValuePair<double, List<int>> pair in neighbours)
                {
                    foreach (int customer in pair.Value)
                    {
                        if (neighbour_counted < neighbour_count)
                        {
                            neighbour_counted++;
                            nearest_neighbour_average = nearest_neighbour_average +
                                pair.Key;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (max_distance > nearest_neighbour_average)
                {
                    max_distance = nearest_neighbour_average;
                    selected_customer = customer_to_check;
                }
            }
            return selected_customer;
        }
Example #11
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));
            OsmSharp.Logging.Log.TraceEvent("TSPPlacementSolver", TraceEventType.Information, builder.ToString());

            return solution;
        }
Example #12
0
        /// <summary>
        /// Executes a solver procedure.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            MaxTimeCalculator calculator = new MaxTimeCalculator(problem);

            // get the seed customers.
            ICollection <int> seeds = _seed_selector.SelectSeeds(
                problem, _k);

            double[] weights = new double[seeds.Count];

            // start the seed routes.
            List <int>      selectable_customers = problem.Customers;
            MaxTimeSolution routes = new MaxTimeSolution(
                problem.Size, true);

            foreach (int seed in seeds)
            {
                routes.Add(seed);
                selectable_customers.Remove(seed);
            }

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

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

            // keep looping until all customers have been placed.
            while (selectable_customers.Count > 0)
            {
                // try and place into every route.
                CheapestInsertionResult best_result = new CheapestInsertionResult();
                best_result.Increase = float.MaxValue;
                int best_route_idx = -1;

                CheapestInsertionResult best_result_above_max = new CheapestInsertionResult();
                best_result_above_max.Increase = float.MaxValue;
                int best_route_above_max_idx = -1;

                for (int route_idx = 0; route_idx < routes.Count; route_idx++)
                {
                    IRoute current_route = routes.Route(route_idx);

                    // choose the next customer.
                    CheapestInsertionResult result =
                        CheapestInsertionHelper.CalculateBestPlacement(problem, current_route, selectable_customers, costs);
                    if (result.Customer == result.CustomerAfter)
                    {
                        throw new Exception();
                    }
                    // get the current weight
                    double weight = weights[route_idx];
                    if (result.Increase < best_result.Increase)
                    {
                        if (weight + result.Increase + calculator.DeliveryTime < problem.Max.Value)
                        { // route will still be inside bounds.
                            best_result    = result;
                            best_route_idx = route_idx;
                        }
                        else
                        { // route will become above max.
                            if (result.Increase < best_result_above_max.Increase)
                            {
                                best_result_above_max    = result;
                                best_route_above_max_idx = route_idx;
                            }
                        }
                    }
                }

                // do the placement if a placement is found without max violation.
                // else do the placement in the above max route.
                CheapestInsertionResult placement_result = new CheapestInsertionResult();
                placement_result.Increase = double.MaxValue;
                int placement_result_idx = -1;
                if (best_route_idx >= 0)
                { // best placement found.
                    placement_result     = best_result;
                    placement_result_idx = best_route_idx;
                }
                else
                { // best placement found but only above max.
                    placement_result     = best_result_above_max;
                    placement_result_idx = best_route_above_max_idx;
                }

                // do the actual placement.
                weights[placement_result_idx] = calculator.CalculateOneRouteIncrease(
                    weights[placement_result_idx], placement_result.Increase);
                selectable_customers.Remove(placement_result.Customer);
                //routes.Route(placement_result_idx).InsertAfterAndRemove(
                //    placement_result.CustomerBefore, placement_result.Customer, placement_result.CustomerAfter);
                routes.Route(placement_result_idx).InsertAfter(
                    placement_result.CustomerBefore, placement_result.Customer);

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

            return(routes);
        }
Example #13
0
        /// <summary>
        /// Calculates a solution.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        internal override MaxTimeSolution Solve(MaxTimeProblem problem)
        {
            // create the calculator.
            MaxTimeCalculator calculator = new MaxTimeCalculator(problem);

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

            double max = problem.Max.Value;

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

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

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

            result.Weight = double.MaxValue;

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

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

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

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

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

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

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

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

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

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

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

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

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

            return(solution);
        }
 /// <summary>
 /// Selects a new seed customer.
 /// </summary>
 /// <param name="problem"></param>
 /// <param name="calculator"></param>
 /// <param name="solution"></param>
 /// <param name="customers"></param>
 /// <returns></returns>
 private int SelectSeed(MaxTimeProblem problem, MaxTimeCalculator calculator,
     MaxTimeSolution solution, List<int> customers)
 {
     // select the customer farthest from the depot.
     int selectedCustomer = -1;
     double maxDistance = double.MinValue;
     foreach (int customerToCheck in customers)
     {
         double distance = problem.WeightMatrix[0][customerToCheck] +
             problem.WeightMatrix[customerToCheck][0];
         if (distance > maxDistance)
         {
             maxDistance = distance;
             selectedCustomer = customerToCheck;
         }
     }
     return selectedCustomer;
 }