/// <summary> /// Generates a random individual. /// </summary> /// <param name="solver"></param> /// <returns></returns> public Individual <List <int>, GeneticProblem, Fitness> Generate( Solver <List <int>, GeneticProblem, Fitness> solver) { // create new genomes list. List <int> genome = new List <int>(); // build cities to place (in a thread-safe way!) List <int> cities_to_place = new List <int>(); lock (solver) { for (int idx = 0; idx < solver.Problem.Along.Count; idx++) { cities_to_place.Add(solver.Problem.Along[idx]); } } BestPlacementHelper helper = BestPlacementHelper.Instance(); helper.DoFast( solver.Problem, solver.FitnessCalculator as FitnessCalculator, genome, cities_to_place); Individual individual = new Individual(genome); individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); return(individual); }
internal static Population <List <Genome>, Problem, Fitness> InitializePopulation( Problem problem, Second target, int population_size, int round_count) { IRandomGenerator random = new RandomGenerator(); // generate a list of cities to place. List <int> cities = new List <int>(); for (int city_to_place = 0; city_to_place < problem.Cities; city_to_place++) { cities.Add(city_to_place); } // create the population Population <List <Genome>, Problem, Fitness> population = new Population <List <Genome>, Problem, Fitness>( null, false); // create the fitness calculator. FitnessCalculator fitness_calculator = new FitnessCalculator(5); while (population.Count < population_size) { OsmSharp.Logging.Log.TraceEvent("OsmSharp.Math.VRP.MultiSalesman.Facade", System.Diagnostics.TraceEventType.Information, "Initializing population individual {0}/{1}...", population.Count + 1, population_size); // create copy of cities List <int> cities_list = new List <int>(cities); // create new individuals. Individual individual = new Individual(new List <Genome>()); // place one random city in each round. for (int round_idx = 0; round_idx < round_count; round_idx++) { // select a random city to place. int city_idx = random.Generate(cities_list.Count); int city = cities_list[city_idx]; cities_list.RemoveAt(city_idx); // create new genome. Genome genome = new Genome(); genome.Add(city); individual.Genomes.Add(genome); } individual = BestPlacementHelper.Do( problem, fitness_calculator, individual, cities_list); // add inidividual to the population. population.Add(individual); OsmSharp.Logging.Log.TraceEvent("OsmSharp.Math.VRP.MultiSalesman.Facade", System.Diagnostics.TraceEventType.Information, "Done!"); } return(population); }
/// <summary> /// Re-places all the cities again to their own best place. /// </summary> /// <param name="solver"></param> /// <param name="mutating"></param> /// <returns></returns> private Individual <List <int>, GeneticProblem, Fitness> MutateByRePlacement( Solver <List <int>, GeneticProblem, Fitness> solver, Individual <List <int>, GeneticProblem, Fitness> mutating) { List <int> nodes_to_re_place = mutating.Genomes.ToList <int>(); List <int> current_placement = mutating.Genomes.ToList <int>(); foreach (int node_to_place in nodes_to_re_place) { // take the node out. current_placement.Remove(node_to_place); // place the node back in. BestPlacementHelper helper = BestPlacementHelper.Instance(); helper.Do( solver.Problem, solver.FitnessCalculator as FitnessCalculator, current_placement, node_to_place); } Individual individual = new Individual(current_placement); individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); return(individual); }
/// <summary> /// Mutates a given individual. /// </summary> /// <param name="solver"></param> /// <param name="mutating"></param> /// <returns></returns> public Individual <List <int>, GeneticProblem, Fitness> Mutate( Solver <List <int>, GeneticProblem, Fitness> solver, Individual <List <int>, GeneticProblem, Fitness> mutating) { // take a random piece. int idx = solver.Random.Next(mutating.Genomes.Count); List <int> new_genome = new List <int>(mutating.Genomes); int customer = new_genome[idx]; new_genome.RemoveAt(idx); // apply best placement algorithm to place the selected genomes. BestPlacementHelper helper = BestPlacementHelper.Instance(); helper.Do( solver.Problem, solver.FitnessCalculator as FitnessCalculator, new_genome, customer); Individual individual = new Individual(new_genome); individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); return(individual); }
/// <summary> /// Take a piece of the genome and re-do best placement. /// </summary> /// <param name="solver"></param> /// <param name="mutating"></param> /// <returns></returns> private Individual <List <int>, GeneticProblem, Fitness> MutateByTakingPiece( Solver <List <int>, GeneticProblem, Fitness> solver, Individual <List <int>, GeneticProblem, Fitness> mutating) { // take a random piece. int idx1 = 0; int idx2 = 0; while (idx2 - idx1 == 0) { idx1 = solver.Random.Next(mutating.Genomes.Count - 1) + 1; idx2 = solver.Random.Next(mutating.Genomes.Count - 1) + 1; if (idx1 > idx2) { int temp = idx1; idx1 = idx2; idx2 = temp; } } // if the genome range is big take it from the best individual. Individual <List <int>, GeneticProblem, Fitness> source = (mutating as Individual <List <int>, GeneticProblem, Fitness>); Individual <List <int>, GeneticProblem, Fitness> target = (mutating as Individual <List <int>, GeneticProblem, Fitness>); List <int> source_piece = source.Genomes.GetRange(idx1, idx2 - idx1); List <int> new_genome = target.Genomes.GetRange(0, target.Genomes.Count); // insert the piece into the worst individual. // remove nodes in the source_piece. foreach (int source_node in source_piece) { new_genome.Remove(source_node); } // apply best placement algorithm to place the selected genomes. //List<int> genome = new List<int>(); BestPlacementHelper helper = BestPlacementHelper.Instance(); helper.DoFast( solver.Problem, solver.FitnessCalculator as FitnessCalculator, new_genome, source_piece); Individual individual = new Individual(new_genome); individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); return(individual); }
/// <summary> /// Generates one individual. /// </summary> /// <param name="solver"></param> /// <returns></returns> public Individual <List <Genome>, Problem, Fitness> Generate( Solver <List <Genome>, Problem, Fitness> solver) { IRandomGenerator random = new RandomGenerator(); // generate a list of cities to place. List <int> cities = new List <int>(); for (int city_to_place = 0; city_to_place < solver.Problem.Cities; city_to_place++) { cities.Add(city_to_place); } // create new individuals. Individual individual = new Individual(new List <Genome>()); //individual.Initialize(); // place one random city in each round. for (int round_idx = 0; round_idx < solver.Problem.InitialVehicles; round_idx++) { // select a random city to place. int city_idx = random.Generate(cities.Count); int city = cities[city_idx]; cities.RemoveAt(city_idx); // create new genome. Genome genome = new Genome(); genome.Add(city); individual.Genomes.Add(genome); } individual = BestPlacementHelper.DoFast( solver.Problem, (solver.FitnessCalculator as FitnessCalculator), individual, cities); return(individual); }
internal static List <Genome> EstimateVehicles <EdgeType, VertexType>( Problem problem, Second min, Second max) where EdgeType : class where VertexType : class, IEquatable <VertexType> { // create the fitness calculator. FitnessCalculator fitness_calculator = new FitnessCalculator(5); IRandomGenerator random = new RandomGenerator(); double average_time = (min.Value + max.Value) / 2.0; double previous_time = average_time; // generate a list of cities to place. List <int> cities = new List <int>(); for (int city_to_place = 0; city_to_place < problem.Cities; city_to_place++) { cities.Add(city_to_place); } // first optimize the number of vehicles; this means generate rounds that are as close to the max as possible. List <Genome> generated_rounds = new List <Genome>(); bool new_round = true; Genome current_round = null; while (cities.Count > 0) { OsmSharp.Logging.Log.TraceEvent("OsmSharp.Math.VRP.MultiSalesman.Facade", System.Diagnostics.TraceEventType.Information, "Placing cities {0}/{1}", cities.Count, problem.Cities); if (_registered_progress_reporter != null) { ProgressStatus status = new ProgressStatus(); status.TotalNumber = problem.Cities; status.CurrentNumber = problem.Cities - cities.Count; status.Message = "Placing cities..."; _registered_progress_reporter.Report(status); } // create a new round if needed. int city; int city_idx; if (new_round) { new_round = false; current_round = new Genome(); // select a random city to place. city_idx = random.Generate(cities.Count); city = cities[city_idx]; cities.RemoveAt(city_idx); current_round.Add(city); previous_time = average_time; } if (cities.Count > 0) { // find the best city to place next. // calculate the best position to place the next city. BestPlacementHelper.BestPlacementResult new_position_to_place = BestPlacementHelper.CalculateBestPlacementInGenome( problem, fitness_calculator, current_round, cities); city = new_position_to_place.City; // remove the node from the source list. cities.Remove(city); // place the node. current_round.Insert(new_position_to_place.CityIdx, new_position_to_place.City); // calculate the time. double time = fitness_calculator.CalculateTime( problem, current_round); if (average_time < time) { // time limit has been reached. double diff_average = time - average_time; double diff_previous = average_time - previous_time; if (diff_average > diff_previous) { // remove the last added city. current_round.Remove(city); cities.Add(city); } else { // keep the last city. } // keep the generated round. generated_rounds.Add(current_round); new_round = true; } previous_time = time; } } return(generated_rounds); }
CrossOver(Solver <List <int>, GeneticProblem, Fitness> solver, Individual <List <int>, GeneticProblem, Fitness> parent1, Individual <List <int>, GeneticProblem, Fitness> parent2) { // take a random piece. int idx1 = 0; int idx2 = 0; while (idx2 - idx1 == 0) { idx1 = solver.Random.Next(parent1.Genomes.Count - 1) + 1; idx2 = solver.Random.Next(parent2.Genomes.Count - 1) + 1; if (idx1 > idx2) { int temp = idx1; idx1 = idx2; idx2 = temp; } } // if the genome range is big take it from the best individual. Individual <List <int>, GeneticProblem, Fitness> source = (parent1 as Individual <List <int>, GeneticProblem, Fitness>); Individual <List <int>, GeneticProblem, Fitness> target = (parent2 as Individual <List <int>, GeneticProblem, Fitness>); if (idx2 - idx1 < parent1.Genomes.Count / 2) { // the range is small; take the worste genomes. if (source.Fitness.CompareTo(target.Fitness) > 0) { Individual <List <int>, GeneticProblem, Fitness> temp = source; source = target; target = temp; } else { // do nothing. } } else { // the range is big; take the good genomes. if (source.Fitness.CompareTo(target.Fitness) > 0) { // do nothing. } else { Individual <List <int>, GeneticProblem, Fitness> temp = source; source = target; target = temp; } } List <int> source_piece = source.Genomes.GetRange(idx1, idx2 - idx1); List <int> new_genome = target.Genomes.GetRange(0, target.Genomes.Count); // insert the piece into the worst individual. // remove nodes in the source_piece. foreach (int source_node in source_piece) { new_genome.Remove(source_node); } // apply best placement algorithm to place the selected genomes. //List<int> genome = new List<int>(); BestPlacementHelper helper = BestPlacementHelper.Instance(); helper.DoFast( solver.Problem, solver.FitnessCalculator as FitnessCalculator, new_genome, source_piece); // return a new individual based on the new genome list. Individual individual = new Individual(new_genome); individual.CalculateFitness(solver.Problem, solver.FitnessCalculator); return(individual); }