Пример #1
0
        /// <summary>
        /// Solves the problem.
        /// </summary>
        /// <returns></returns>
        protected override IRoute DoSolve(IProblem problem)
        {
            bool is_round;
            int  first;

            if (problem.First.HasValue)
            { // the first customer is set.
                // test if the last customer is the same.
                if (problem.Last == problem.First)
                { // the route is a round.
                    is_round = true;
                    first    = problem.First.Value;
                }
                else
                { // the route is not a round.
                    is_round = false;
                    first    = problem.First.Value;
                }
            }
            else
            { // the first and last customer can be choosen randomly.
                is_round = false;
                first    = -1;
            }

            // convert the problem to another problem with a virtual depot if needed.
            IProblem converted_problem;

            if (!is_round && first < 0)
            { // the end points can both vary.
                converted_problem = problem.AddVirtualDepot();
            }
            else
            { // the problem does not need to be converted.
                converted_problem = problem;
            }

            // do the RAI.
            IRoute route = RandomizedArbitraryInsertionSolver.DoSolve(this, converted_problem, _route);

            // convert the route again if needed.
            if (!is_round && first < 0)
            { // the end points could both vary so a virtual one was added. Remove it again here.
                List <int> route_list     = new List <int>(route);
                List <int> new_route_list = new List <int>();
                for (int idx = 0; idx < route_list.Count; idx++)
                { // remove customer zero.
                    if (route_list[idx] > 0)
                    {
                        new_route_list.Add(route_list[idx] - 1);
                    }
                }
                route = DynamicAsymmetricRoute.CreateFrom(new_route_list, false);
            }
            return(route);
        }
Пример #2
0
        /// <summary>
        /// Generates a random route.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        public static IRoute DoSolveStatic(IProblem problem)
        {
            List <int> customers = new List <int>();

            for (int customer = 0; customer < problem.Size; customer++)
            {
                customers.Add(customer);
            }
            customers.Shuffle <int>();
            return(DynamicAsymmetricRoute.CreateFrom(customers));
        }
Пример #3
0
        /// <summary>
        /// Executes the solver.
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        public IRoute Solve(IProblem problem)
        {
            IProblem converted_problem = problem;

            bool first = problem.First.HasValue;
            bool last  = problem.Last.HasValue;

            // convert the problem if needed.
            if (!first && !last)
            { // add a virtual customer with distance zero to all existing customers.
                double[][] new_weights = new double[problem.WeightMatrix.Length + 1][];
                new_weights[0] = new double[problem.WeightMatrix.Length + 1];
                for (int idx = 0; idx < problem.WeightMatrix.Length + 1; idx++)
                {
                    new_weights[0][idx] = 0;
                }
                for (int idx = 0; idx < problem.WeightMatrix.Length; idx++)
                {
                    new_weights[idx + 1]    = new double[problem.WeightMatrix.Length + 1];
                    new_weights[idx + 1][0] = 0;
                    problem.WeightMatrix[idx].CopyTo(new_weights[idx + 1], 1);
                }
                converted_problem = MatrixProblem.CreateATSP(new_weights, 0);
            }
            else if (!last)
            { // set all weights to the first customer to zero.
                for (int idx = 0; idx < problem.WeightMatrix.Length; idx++)
                {
                    problem.WeightMatrix[idx][problem.First.Value] = 0;
                }
                converted_problem = MatrixProblem.CreateATSP(problem.WeightMatrix, problem.First.Value);
            }

            // execute the solver on the converted problem.
            IRoute converted_route = this.DoSolve(converted_problem);

            // convert the route back.
            if (!first && !last)
            { // when a virtual customer was added the route needs converting.
                List <int> customers_list = converted_route.ToList <int>();
                customers_list.RemoveAt(0);
                for (int idx = 0; idx < customers_list.Count; idx++)
                {
                    customers_list[idx] = customers_list[idx] - 1;
                }
                converted_route = DynamicAsymmetricRoute.CreateFrom(customers_list, false);
            }
            else if (!last)
            { // the returned route will return to customer zero; convert the route.
                converted_route = DynamicAsymmetricRoute.CreateFrom(converted_route, false);
            }
            return(converted_route);
        }
        /// <summary>
        /// Returns a solution found using best-placement.
        /// </summary>
        /// <returns></returns>
        protected override IRoute DoSolve(OsmSharp.Math.TSP.Problems.IProblem problem)
        {
            // create the settings.
            SolverSettings settings = new SolverSettings(
                -1,
                -1,
                1000000000,
                -1,
                -1,
                -1);

            Solver <List <int>, GeneticProblem, Fitness> solver =
                new Solver <List <int>, GeneticProblem, Fitness>(
                    new GeneticProblem(problem),
                    settings,
                    null,
                    null,
                    null,
                    _generation_operation,
                    new FitnessCalculator(),
                    true, false);

            Population <List <int>, GeneticProblem, Fitness> population =
                new Population <List <int>, GeneticProblem, Fitness>(true);

            while (population.Count < _population_size)
            {
                // generate new.
                Individual <List <int>, GeneticProblem, Fitness> new_individual =
                    _generation_operation.Generate(solver);

                // add to population.
                population.Add(new_individual);
            }

            // select each individual once.
            Population <List <int>, GeneticProblem, Fitness> new_population =
                new Population <List <int>, GeneticProblem, Fitness>(true);
            Individual <List <int>, GeneticProblem, Fitness> best = null;
            int stagnation = 0;

            while (stagnation < _stagnation)
            {
                while (new_population.Count < _population_size)
                {
                    // select an individual and the next one.
                    int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(population.Count);
                    Individual <List <int>, GeneticProblem, Fitness> individual1 = population[idx];
                    Individual <List <int>, GeneticProblem, Fitness> individual2 = null;
                    if (idx == population.Count - 1)
                    {
                        individual2 = population[0];
                    }
                    else
                    {
                        individual2 = population[idx + 1];
                    }
                    population.RemoveAt(idx);

                    Individual <List <int>, GeneticProblem, Fitness> new_individual = _cross_over_operation.CrossOver(solver,
                                                                                                                      individual1, individual2);

                    new_individual.CalculateFitness(solver.Problem, solver.FitnessCalculator);
                    if (new_individual.Fitness.CompareTo(
                            individual1.Fitness) < 0)
                    {
                        new_population.Add(new_individual);
                    }
                    else
                    {
                        new_population.Add(individual1);
                    }
                }

                population = new_population;
                population.Sort(solver, solver.FitnessCalculator);

                new_population = new Population <List <int>, GeneticProblem, Fitness>(true);

                if (best == null ||
                    best.Fitness.CompareTo(population[0].Fitness) > 0)
                {
                    stagnation = 0;
                    best       = population[0];
                }
                else
                {
                    stagnation++;
                }

                // report progress.
                OsmSharp.Logging.Log.TraceEvent("EdgeAssemblyCrossOverSolver", Logging.TraceEventType.Information,
                                                string.Format("Solving using EAX: Stagnation {0}.", stagnation));
            }

            var result = new List <int>(best.Genomes);

            result.Insert(0, 0);
            return(DynamicAsymmetricRoute.CreateFrom(result));
        }
Пример #5
0
        /// <summary>
        /// Returns a solution found using best-placement.
        /// </summary>
        /// <returns></returns>
        protected override IRoute DoSolve(IProblem problem)
        {
            // build the customer list to place.
            List<int> customers = null;
            if (_customers != null)
            { // copy the list of the given customers and keep this order.
                customers = new List<int>(_customers);
            }
            else
            { // generate some random route.
                customers = new List<int>();
                List<int> customers_to_place = new List<int>();
                for (int customer = 0; customer < problem.Size; customer++)
                {
                    customers_to_place.Add(customer);
                }
                while (customers_to_place.Count > 0)
                {
                    int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers_to_place.Count);
                    customers.Add(customers_to_place[idx]);
                    customers_to_place.RemoveAt(idx);
                }
            }

            // initialize the route based on the problem definition.
            IRoute route = null;
            double weight = double.MaxValue;
            if (problem.Symmetric)
            { // create a symmetric route that is dynamic and can accept new customers.
                if (problem.First.HasValue && problem.Last.HasValue && problem.First == problem.Last)
                { // route is a round.
                    route = new DynamicSymmetricRoute(problem.First.Value);
                }
                else
                { // not a round.
                    throw new NotImplementedException("No symmetric routes implemented that are not rounds!");
                }
            }
            else
            { // create a asymmetric route that is dynamic and can accept new customers.
                if (problem.First.HasValue)
                { // the first customer is set.
                    // test if the last customer is the same.
                    if (!problem.Last.HasValue ||
                        problem.Last == problem.First)
                    { // the route is a round.
                        route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, true);

                        // remove the first customer.
                        customers.Remove(problem.First.Value);

                        // find the customer that is farthest away and add it.
                        int to = -1;
                        weight = double.MinValue;
                        for (int x = 0; x < customers.Count; x++)
                        {
                            if (x != problem.First.Value)
                            { // only different customers.
                                double current_weight = problem.WeightMatrix[x][problem.First.Value] +
                                    problem.WeightMatrix[problem.First.Value][x];
                                if (current_weight > weight)
                                { // the current weight is better.
                                    to = x;
                                    weight = current_weight;
                                }
                            }
                        }
                        route.InsertAfter(problem.First.Value, to);
                        customers.Remove(to);
                    }
                    else
                    { // the route is not a round.
                        route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, false);
                        route.InsertAfter(problem.First.Value, problem.Last.Value);

                        // remove the first customer.
                        customers.Remove(problem.First.Value);
                        customers.Remove(problem.Last.Value);
                    }
                }
                else
                { // the first and last customer can be choosen randomly.
                    // find two customers close together.
                    int from = -1;
                    int to = -1;
                    for (int x = 0; x < customers.Count; x++)
                    {
                        for (int y = 0; y < customers.Count; y++)
                        {
                            if (x != y)
                            { // only different customers.
                                double current_weight = problem.WeightMatrix[x][y];
                                if (current_weight < weight)
                                { // the current weight is better.
                                    from = x;
                                    to = y;
                                    weight = current_weight;

                                    if (weight == 0)
                                    { // no edge with less weight is going to be found.
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    route = new DynamicAsymmetricRoute(customers.Count, from, false);
                    route.InsertAfter(from, to);

                    // remove the first customer.
                    customers.Remove(from);
                    customers.Remove(to);
                }
            }

            // insert the rest of the customers.
            while (customers.Count > 0 && !_stopped)
            { // keep placing customer 0 until all customers are placed.
                int customer = customers[0];
                customers.RemoveAt(0);

                // insert the customer at the best place.
                double difference;
                ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference);
            }

            return route;
        }
        /// <summary>
        /// Returns a solution found using best-placement.
        /// </summary>
        /// <returns></returns>
        protected override IRoute DoSolve(IProblem problem)
        {
            // build the customer list to place.
            List <int> customers = null;

            if (_customers != null)
            { // copy the list of the given customers and keep this order.
                customers = new List <int>(_customers);
            }
            else
            { // generate some random route.
                customers = new List <int>();
                List <int> customers_to_place = new List <int>();
                for (int customer = 0; customer < problem.Size; customer++)
                {
                    customers_to_place.Add(customer);
                }
                while (customers_to_place.Count > 0)
                {
                    int idx = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(customers_to_place.Count);
                    customers.Add(customers_to_place[idx]);
                    customers_to_place.RemoveAt(idx);
                }
            }

            // initialize the route based on the problem definition.
            IRoute route  = null;
            double weight = double.MaxValue;

            if (problem.Symmetric)
            {     // create a symmetric route that is dynamic and can accept new customers.
                if (problem.First.HasValue && problem.Last.HasValue && problem.First == problem.Last)
                { // route is a round.
                    route = new DynamicSymmetricRoute(problem.First.Value);
                }
                else
                { // not a round.
                    throw new NotImplementedException("No symmetric routes implemented that are not rounds!");
                }
            }
            else
            {     // create a asymmetric route that is dynamic and can accept new customers.
                if (problem.First.HasValue)
                { // the first customer is set.
                    // test if the last customer is the same.
                    if (!problem.Last.HasValue ||
                        problem.Last == problem.First)
                    { // the route is a round.
                        route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, true);

                        // remove the first customer.
                        customers.Remove(problem.First.Value);

                        // find the customer that is farthest away and add it.
                        int to = -1;
                        weight = double.MinValue;
                        for (int x = 0; x < customers.Count; x++)
                        {
                            if (x != problem.First.Value)
                            { // only different customers.
                                double current_weight = problem.WeightMatrix[x][problem.First.Value] +
                                                        problem.WeightMatrix[problem.First.Value][x];
                                if (current_weight > weight)
                                { // the current weight is better.
                                    to     = x;
                                    weight = current_weight;
                                }
                            }
                        }
                        route.InsertAfter(problem.First.Value, to);
                        customers.Remove(to);
                    }
                    else
                    { // the route is not a round.
                        route = new DynamicAsymmetricRoute(customers.Count, problem.First.Value, false);
                        route.InsertAfter(problem.First.Value, problem.Last.Value);

                        // remove the first customer.
                        customers.Remove(problem.First.Value);
                        customers.Remove(problem.Last.Value);
                    }
                }
                else
                { // the first and last customer can be choosen randomly.
                    // find two customers close together.
                    int from = -1;
                    int to   = -1;
                    for (int x = 0; x < customers.Count; x++)
                    {
                        for (int y = 0; y < customers.Count; y++)
                        {
                            if (x != y)
                            { // only different customers.
                                double current_weight = problem.WeightMatrix[x][y];
                                if (current_weight < weight)
                                { // the current weight is better.
                                    from   = x;
                                    to     = y;
                                    weight = current_weight;

                                    if (weight == 0)
                                    { // no edge with less weight is going to be found.
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    route = new DynamicAsymmetricRoute(customers.Count, from, false);
                    route.InsertAfter(from, to);

                    // remove the first customer.
                    customers.Remove(from);
                    customers.Remove(to);
                }
            }

            // insert the rest of the customers.
            while (customers.Count > 0 && !_stopped)
            { // keep placing customer 0 until all customers are placed.
                int customer = customers[0];
                customers.RemoveAt(0);

                // insert the customer at the best place.
                double difference;
                ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference);
            }

            return(route);
        }
Пример #7
0
        /// <summary>
        /// Executes the RAI.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="solver"></param>
        /// <param name="initial_route"></param>
        /// <returns></returns>
        private static IRoute DoSolve(RandomizedArbitraryInsertionSolver solver, IProblem problem, IRoute initial_route)
        {
            // initialize a route using best-placement.
            DynamicAsymmetricRoute route = null;

            if (initial_route == null)
            {
                OsmSharp.Math.TSP.ArbitraryInsertion.ArbitraryInsertionSolver ai_solver =
                    new OsmSharp.Math.TSP.ArbitraryInsertion.ArbitraryInsertionSolver();
                initial_route = ai_solver.Solve(problem);
            }

            // get/create the dynamic route.
            if (initial_route is DynamicAsymmetricRoute)
            { // initial route is already the correct type.
                route = initial_route as DynamicAsymmetricRoute;
            }
            else
            { // convert the initial route to a route of the correct type.
                route = DynamicAsymmetricRoute.CreateFrom(initial_route);
            }

            // do the Arbitrary Insertion.
            double weight = route.CalculateWeight(problem);

            int try_count = 0;

            while (try_count < (route.Count * route.Count))
            { // keep trying for a given number of times.
                int factor = 2;

                // cut out a part.
                int i = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1;
                int j = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1;

                while (i == j)
                {
                    j = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate((route.Count / factor) - 1) + 1;
                }

                if (i > j)
                {
                    int k = j;
                    j = i;
                    i = k;
                }

                // cut out the i->j part.
                int length = j - i;
                if (length > 0)
                {
                    // cut and remove.
                    DynamicAsymmetricRoute.CutResult cut_result = route.CutAndRemove(
                        problem, weight, i, length);

                    // calculate the weight that was removed.
                    double                 new_weight = cut_result.Weight;
                    List <int>             cut_part   = cut_result.CutPart;
                    DynamicAsymmetricRoute cut_route  = cut_result.Route;

                    // use best placement to re-insert.
                    int c = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(cut_part.Count);
                    while (cut_part.Count > 0)
                    { // loop until it's empty.
                        int customer = cut_part[c];
                        cut_part.RemoveAt(c);

                        // calculate the best placement.
                        CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(
                            problem, cut_route, customer);
                        //cut_route.InsertAfterAndRemove(result.CustomerBefore, result.Customer, result.CustomerAfter);
                        cut_route.InsertAfter(result.CustomerBefore, result.Customer);
                        new_weight = new_weight + result.Increase;

                        // choose next random customer.
                        c = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(cut_part.Count);
                    }

                    // descide to keep new route or not.
                    if (weight > new_weight)
                    {
                        route  = cut_route;
                        weight = new_weight;

                        //if (this.CanRaiseIntermidiateResult())
                        //{
                        //    this.RaiseIntermidiateResult(route.ToArray<int>(), weight);
                        //}
                    }
                }

                // increase the try count.
                try_count++;
            }

            if (solver != null && solver.CanRaiseIntermidiateResult())
            {
                solver.RaiseIntermidiateResult(route.ToArray <int>());
            }

            return(route);
        }