/// <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);
        }