/// <summary>
        /// Places a city into an idividual.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="round_idx"></param>
        /// <param name="individual"></param>
        /// <param name="city_to_place"></param>
        /// <returns></returns>
        internal static BestPlacementResult CalculateBestPlacementInIndividual(
            Problem problem,
            FitnessCalculator calculator,
            int round_idx,
            Individual <List <Genome>, Problem, Fitness> individual,
            int city_to_place)
        {
            // if the target round is empty best placement is impossible.
            Genome round = individual.Genomes[round_idx];

            // do best placement in the genome/round.
            BestPlacementResult result =
                BestPlacementHelper.CalculateBestPlacementInGenome(problem, calculator, round, city_to_place);

            // set the round index.
            result.RoundIdx = round_idx;
            if (!individual.FitnessCalculated)
            {
                individual.CalculateFitness(
                    problem, calculator);
            }
            result.Fitness = calculator.Adjust(
                problem,
                individual.Fitness,
                round_idx,
                result.Increase);

            // return the result.
            return(result);
        }
        /// <summary>
        /// Places cities into an individual.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="genomes"></param>
        /// <param name="cities_to_place"></param>
        /// <returns></returns>
        public static BestPlacementResult CalculateBestPlacementInGenomes(
            Problem problem,
            FitnessCalculator calculator,
            List <Genome> genomes,
            List <int> cities_to_place)
        {
            // initialize the best placement result.
            BestPlacementResult result = null;

            // place all the cities until there are no more left.
            // try to place every city in every round.
            for (int round_idx = 0; round_idx < genomes.Count; round_idx++)
            {
                Genome genome = genomes[round_idx];
                BestPlacementResult new_result =
                    BestPlacementHelper.CalculateBestPlacementInGenome(
                        problem,
                        calculator,
                        genome,
                        cities_to_place);
                if (result == null ||
                    new_result.Increase < result.Increase)
                {
                    result          = new_result;
                    result.RoundIdx = round_idx;
                }
            }

            // return the result.
            return(result);
        }
        /// <summary>
        /// Places cities into an individual.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="individual"></param>
        /// <param name="cities_to_place"></param>
        /// <returns></returns>
        internal static BestPlacementResult CalculateBestPlacementInIndividual(
            Problem problem,
            FitnessCalculator calculator,
            Individual <List <Genome>, Problem, Fitness> individual,
            List <int> cities_to_place)
        {
            // initialize the best placement result.
            BestPlacementResult result = null;

            // place all the cities until there are no more left.
            // try to place every city in every round.
            foreach (int city_to_place in cities_to_place)
            {
                for (int round_idx = 0; round_idx < individual.Genomes.Count; round_idx++)
                {
                    BestPlacementResult new_result =
                        BestPlacementHelper.CalculateBestPlacementInIndividual(
                            problem,
                            calculator,
                            round_idx,
                            individual,
                            city_to_place);
                    if (result == null ||
                        new_result.Fitness < result.Fitness)
                    {
                        result = new_result;
                    }
                }
            }

            // return the result.
            return(result);
        }
        /// <summary>
        /// Places the given city in the individual.
        /// </summary>
        /// <param name="problem"></param>
        /// <param name="calculator"></param>
        /// <param name="genomes"></param>
        /// <param name="city_to_place"></param>
        /// <returns></returns>
        public static BestPlacementResult CalculateBestPlacementInGenomes(
            Problem problem,
            FitnessCalculator calculator,
            List <Genome> genomes,
            int city_to_place)
        {
            List <int> cities_to_place = new List <int>();

            cities_to_place.Add(city_to_place);
            return(BestPlacementHelper.CalculateBestPlacementInGenomes(problem, calculator, genomes, cities_to_place));
        }
        public static Genome DoFast(
            Problem problem,
            FitnessCalculator calculator,
            Genome genome,
            List <int> cities_to_place)
        {
            List <Genome> genomes = new List <Genome>();

            genomes.Add(genome);
            return(BestPlacementHelper.DoFast(
                       problem,
                       calculator,
                       genomes,
                       cities_to_place)[0]);
        }
        public static List <Genome> DoFast(
            Problem problem,
            FitnessCalculator calculator,
            List <Genome> genomes,
            List <int> cities_to_place)
        {
            // initialize the best placement result.
            BestPlacementResult result = null;

            // create the new individual.
            cities_to_place = new List <int>(cities_to_place);
            while (cities_to_place.Count > 0)
            {
                int city_to_place = cities_to_place[cities_to_place.Count - 1];
                cities_to_place.RemoveAt(cities_to_place.Count - 1);

                // calculates the next best position for placement.
                result = BestPlacementHelper.CalculateBestPlacementInGenomes(
                    problem,
                    calculator,
                    genomes,
                    city_to_place);

                // calculate the new individual using the result.
                List <int> round = genomes[result.RoundIdx];
                if (round.Count == result.CityIdx)
                {
                    round.Add(result.City);
                }
                else
                {
                    round.Insert(result.CityIdx, result.City);
                }

                // remove the placed city.
                cities_to_place.Remove(result.City);
            }

            // return the result.
            return(genomes);
        }
        internal static BestPlacementResult CalculateBestPlacementInGenome(
            Problem problem,
            FitnessCalculator calculator,
            Genome genome,
            List <int> cities_to_place)
        {
            // initialize the best placement result.
            BestPlacementResult result
                = new BestPlacementResult();

            result.RoundIdx = -1;

            // try and place all cities.
            for (int city_idx = 0; city_idx < cities_to_place.Count; city_idx++)
            {
                // try to place first city.
                int city = cities_to_place[city_idx];

                // place the city and check the result.
                BestPlacementResult current_result =
                    BestPlacementHelper.CalculateBestPlacementInGenome(
                        problem,
                        calculator,
                        genome,
                        city);

                // check current result
                //if (result.Increase == null ||
                //    current_result.Increase < result.Increase)
                if (current_result.Increase < result.Increase)
                {
                    result = current_result;
                }
            }

            return(result);
        }