public static void Main() { // define cost matrix Double INF = Double.PositiveInfinity; /* Double[,] costMatrix = new Double[,] { { INF, 2.0, 4.0, 22.0, 2.0, INF}, { 2.0, INF, 8.0, 15.0, 13.0, 10.0}, { 4.0, 8.0, INF, 5.0, 2.0, INF}, {22.0, 15.0, 5.0, INF, 11.0, 12.0}, { 2.0, 13.0, 2.0, 11.0, INF, 14.0}, { INF, 10.0, INF, 12.0, 14.0, INF}, }; */ Double[,] costMatrix = new Double[,] { { INF, 2.0, INF, INF, 7.0}, { 2.0, INF, 1.0, 3.0, INF}, { INF, 1.0, INF, 1.0, 5.0}, { INF, 3.0, 1.0, INF, INF}, { 7.0, INF, 5.0, INF, INF}, }; costMatrix = new Double[,] { { INF, 20.0, INF, 70.0}, { 20.0, INF, 40.0, INF}, { INF, 40.0, INF,50.0}, { 70.0, INF, 50.0,INF}, }; // create prototype chromosome PermutationChromosome prototype = new PermutationChromosome(0, costMatrix.GetLength(0) - 1); // set prototype's parameters prototype.CrossOverStrategy = new PermutationChromosome.CycleCrossOverStrategy(); prototype.RandomGenerator = new ThreadSafeRandomGenerator(); prototype.MutationStrategy = new PermutationChromosome.InsertMutationStrategy(); prototype.Fitness = new TSPFitness(costMatrix); // stop condition, keep reference for selecting the leader NoChangeStopCondion stopCondition = new NoChangeStopCondion(10); // create population DefaultPopulation population = new DefaultPopulation(prototype, 40); // set population's parameters population.SelectionStrategy = new StochasticUniversalSamplingStrategy(new FixedSizeStrategy(40), new ThreadSafeRandomGenerator()); population.RandomGenerator = new ThreadSafeRandomGenerator(); population.StopCondition = stopCondition; // perform util the stop condition returns false while (population.NextGeneration()) ; // print the result System.Console.WriteLine("Best fitness: " + (1.0 / stopCondition.Leader.Evaluate())); System.Console.WriteLine(stopCondition.Leader.ToString()); System.Console.ReadKey(); }
/// <summary> /// Realizuje algorytm mutacji na zadanym chromosomie. /// </summary> /// <param name="chromosome">Chromosom, który zostanie poddany mutacji.</param> public void Mutate(PermutationChromosome chromosome) { Int32 mutationPoint1 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); Int32 mutationPoint2 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); if (mutationPoint1 != mutationPoint2) { Int32 mpLower = Math.Min(mutationPoint1, mutationPoint2); Int32 mpUpper = Math.Max(mutationPoint1, mutationPoint2); Array.Reverse(chromosome.Data, mpLower, mpUpper - mpLower); } }
/// <summary> /// Dokonuje oceny dopasowania. /// </summary> /// <param name="chromosome">Oceniany chromosom.</param> /// <returns>Ocena dopasowania.</returns> public double Evaluate(PermutationChromosome chromosome) { Int32[] permutation = chromosome.Data; #if DEBUG Debug.Assert(costMatrix.GetLength(0) == costMatrix.GetLength(1)); Debug.Assert(costMatrix.GetLength(0) == permutation.Length); Debug.Assert(permutation.Min() == 0); Debug.Assert(permutation.Max() == permutation.Length - 1); #endif Double cost = 0.0; for (Int32 i = 1; i < permutation.Length; ++i) { cost += costMatrix[permutation[i - 1], permutation[i]]; } cost += costMatrix[permutation[permutation.Length - 1], permutation[0]]; return Double.IsInfinity(cost) ? 0.0 : 1.0 / cost; }
/// <summary> /// Realizuje algorytm mutacji na zadanym chromosomie. /// </summary> /// <param name="chromosome">Chromosom, który zostanie poddany mutacji.</param> public void Mutate(PermutationChromosome chromosome) { Int32 mutationPoint1 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); Int32 mutationPoint2 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); if (mutationPoint1 != mutationPoint2) { Int32 mpLower = Math.Min(mutationPoint1, mutationPoint2); Int32 mpUpper = Math.Max(mutationPoint1, mutationPoint2); for (Int32 i = mpLower; i < mpUpper; ++i) { Int32 value = chromosome.Data[i]; Int32 point = chromosome.RandomGenerator.Next(i, mpUpper); chromosome.Data[i] = chromosome.Data[point]; chromosome.Data[point] = value; } } }
/// <summary> /// Krzyżuje dwa osobniki modyfikując je. /// </summary> /// <param name="ch1">Osobnik pierwszy.</param> /// <param name="ch2">Osobnik drugi.</param> public void CrossOver(PermutationChromosome ch1, PermutationChromosome ch2) { #if DEBUG Debug.Assert(ch1.RandomGenerator.GetType() == ch2.RandomGenerator.GetType()); Debug.Assert(ch1.CrossOverStrategy.GetType() == ch2.CrossOverStrategy.GetType()); Debug.Assert(ch1.HasSameData(ch2)); #endif Int32[] child1 = new Int32[ch1.Data.Length]; Int32[] child2 = new Int32[ch2.Data.Length]; Boolean[] visited = new Boolean[ch2.Data.Length]; Int32 pos = 0; do { // odd circle pos = Array.IndexOf(visited, false); while (pos >= 0 && false == visited[pos]) { visited[pos] = true; child1[pos] = ch1.Data[pos]; child2[pos] = ch2.Data[pos]; pos = Array.IndexOf(ch1.Data, ch2.Data[pos]); } // even circle pos = Array.IndexOf(visited, false); while (pos >= 0 && false == visited[pos]) { visited[pos] = true; child1[pos] = ch2.Data[pos]; child2[pos] = ch1.Data[pos]; pos = Array.IndexOf(ch2.Data, ch1.Data[pos]); } } while (Array.IndexOf(visited, false) >= 0); ch1.Data = child1; ch2.Data = child2; }
/// <summary> /// Krzyżuje dwa osobniki modyfikując je. /// </summary> /// <param name="ch1">Osobnik pierwszy.</param> /// <param name="ch2">Osobnik drugi.</param> public void CrossOver(PermutationChromosome ch1, PermutationChromosome ch2) { #if DEBUG Debug.Assert(ch1.RandomGenerator.GetType() == ch2.RandomGenerator.GetType()); Debug.Assert(ch1.CrossOverStrategy.GetType() == ch2.CrossOverStrategy.GetType()); Debug.Assert(ch1.HasSameData(ch2)); #endif Int32 crossOverPoint1 = ch1.RandomGenerator.Next(0, ch1.Data.Length); Int32 crossOverPoint2 = ch1.RandomGenerator.Next(0, ch1.Data.Length); if (crossOverPoint1 != crossOverPoint2) { Int32 copLower = Math.Min(crossOverPoint1, crossOverPoint2); Int32 copUpper = Math.Max(crossOverPoint1, crossOverPoint2); Int32[] data1 = PartiallyMappedCrossOver(ch1.Data, ch2.Data, copLower, copUpper); Int32[] data2 = PartiallyMappedCrossOver(ch2.Data, ch1.Data, copLower, copUpper); ch1.Data = data1; ch2.Data = data2; } }
/// <summary> /// Realizuje algorytm mutacji na zadanym chromosomie. /// </summary> /// <param name="chromosome">Chromosom, który zostanie poddany mutacji.</param> public void Mutate(PermutationChromosome chromosome) { Int32 mutationPoint1 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); Int32 mutationPoint2 = chromosome.RandomGenerator.Next(0, chromosome.Data.Length); if (mutationPoint1 != mutationPoint2) { Int32 mpLower = Math.Min(mutationPoint1, mutationPoint2); Int32 mpUpper = Math.Max(mutationPoint1, mutationPoint2); Int32 mutationValueLower = chromosome.Data[mpLower]; Int32 mutationValueUpper = chromosome.Data[mpUpper]; Int32 position = mpUpper; while ((--position) > mpLower) { chromosome.Data[position + 1] = chromosome.Data[position]; } chromosome.Data[mpLower + 0] = mutationValueLower; chromosome.Data[mpLower + 1] = mutationValueUpper; } }
/// <summary> /// Porównuje allele dwóch chromosomów. /// </summary> /// <param name="chromosome">Chromosom, z którym jest realizowane porównywanie.</param> /// <returns>True, jeżeli oba chromosomy mają takie same allele na odpowiadających sobie pozycjach.</returns> private bool HasSameData(PermutationChromosome chromosome) { foreach (Int32 value in chromosome.Data) { if (false == Data.Contains(value)) { return false; } } return true; }
/// <summary> /// Kopiuje instancję obiektu chromosomu. /// </summary> /// <returns></returns> public IChromosome Clone() { PermutationChromosome chromosome = new PermutationChromosome(Data); chromosome.RandomGenerator = RandomGenerator; chromosome.MutationStrategy = MutationStrategy; chromosome.CrossOverStrategy = CrossOverStrategy; chromosome.Fitness = Fitness; return chromosome; }
private void startProcessingButton_Click(object sender, EventArgs e) { if (worker.IsBusy) { worker.CancelAsync(); return; } if (costMatrix == null) { MessageBox.Show("Macierz jest pusta. Uzupełnij graf."); return; } /* * Prototyp chromosomu. */ PermutationChromosome chromosomePrototype = new PermutationChromosome(0, costMatrix.GetLength(0) - 1); chromosomePrototype.MutationStrategy = (PermutationChromosome.IMutationStrategy)mutationAlgorithmComboBox.SelectedItem; chromosomePrototype.CrossOverStrategy = (PermutationChromosome.ICrossOverStrategy)crossoverAlgorithmComboBox.SelectedItem; chromosomePrototype.RandomGenerator = new ThreadSafeRandomGenerator(); chromosomePrototype.Fitness = new TSPFitness(costMatrix); /* * Populacja */ population = new DefaultPopulation(chromosomePrototype, (UInt32)populationSpinner.Value); population.RandomGenerator = new ThreadSafeRandomGenerator(); population.StopCondition = stopCondition; /* * Selekcja */ ISelectionSizeStrategy selectionSizeStrategy = selectionSizeCheckBox.Checked ? (ISelectionSizeStrategy)new ProportionalSizeStrategy((Double)selectionSizeSpinner.Value) : (ISelectionSizeStrategy)new FixedSizeStrategy((UInt32)selectionSizeSpinner.Value); switch ((SelectionStrategies)selectionAlgorithmComboBox.SelectedValue) { case SelectionStrategies.NoSelectionStrategy: population.SelectionStrategy = new NoSelectionStrategy(); break; case SelectionStrategies.RouletteWheelSelectionStrategy: population.SelectionStrategy = new RouletteWheelSelectionStrategy(selectionSizeStrategy, new ThreadSafeRandomGenerator()); break; case SelectionStrategies.StochasticUniversalSamplingStrategy: population.SelectionStrategy = new StochasticUniversalSamplingStrategy(selectionSizeStrategy, new ThreadSafeRandomGenerator()); break; case SelectionStrategies.TournamentSelectionStrategy: ISelectionSizeStrategy tournamentGroupSizeStrategy = tournamentGroupSizeCheckBox.Checked ? (ISelectionSizeStrategy)new ProportionalSizeStrategy((Double)tournamentGroupSizeSpinner.Value) : (ISelectionSizeStrategy)new FixedSizeStrategy((UInt32)tournamentGroupSizeSpinner.Value); population.SelectionStrategy = new TournamentSelectionStrategy(selectionSizeStrategy, tournamentGroupSizeStrategy, new ThreadSafeRandomGenerator()); break; default: return; } ISelectionSizeStrategy eliteSizeStrategy = eliteSizeCheckBox.Checked ? (ISelectionSizeStrategy)new ProportionalSizeStrategy((Double)eliteSizeSpinner.Value) : (ISelectionSizeStrategy)new FixedSizeStrategy((UInt32)eliteSizeSpinner.Value); ISelectionSizeStrategy survivorSizeStrategy = eliteSizeCheckBox.Checked ? (ISelectionSizeStrategy)new ProportionalSizeStrategy((Double)survivorSizeSpinner.Value) : (ISelectionSizeStrategy)new FixedSizeStrategy((UInt32)survivorSizeSpinner.Value); switch ((ModifierCombination)selecitonModifierComboBox.SelectedValue) { case ModifierCombination.None: break; case ModifierCombination.Elite: population.SelectionStrategy = new EliteSelectionStrategyAdapter(population.SelectionStrategy, eliteSizeStrategy); break; case ModifierCombination.Survivor: population.SelectionStrategy = new SurvivorSelectionStrategyAdapter(population.SelectionStrategy, survivorSizeStrategy); break; case ModifierCombination.EliteSurvivor: population.SelectionStrategy = new EliteSelectionStrategyAdapter(population.SelectionStrategy, eliteSizeStrategy); population.SelectionStrategy = new SurvivorSelectionStrategyAdapter(population.SelectionStrategy, survivorSizeStrategy); break; case ModifierCombination.SurvivorElite: population.SelectionStrategy = new SurvivorSelectionStrategyAdapter(population.SelectionStrategy, survivorSizeStrategy); population.SelectionStrategy = new EliteSelectionStrategyAdapter(population.SelectionStrategy, eliteSizeStrategy); break; } /* * Warunek stopu. Zachować referencję dla wskazania lidera. */ stopCondition = new NoChangeStopCondion((UInt32)stopSpinner.Value); population.StopCondition = stopCondition; /* * Rozpocznij przetwarzanie. */ startProcessingButton.Text = "Stop"; TimeStart = DateTime.Now; worker.RunWorkerAsync(stopCondition); }