/// <summary> /// Krzyżuje dwa chromosomy podane na wejściu i zwracam całkowicie nowe chromosomy /// </summary> public virtual ChromosomeClass[] crossoverOfTwoChromosomesByWeekends(ChromosomeClass chromosome1, ChromosomeClass chromosome2, int fromWhichWeekStartCrossover) //tu pracuje na orginałach chromosomów dlatego nic nie zwracam { int whichWeekChange = fromWhichWeekStartCrossover; NurseClass[][][] tempTableOnWeek; //to jakby wskaźnik na tablice 3 wymiarową ChromosomeClass[] newChromosomes = new ChromosomeClass[2] { new ChromosomeClass(), new ChromosomeClass() }; // miejsce na 2 nowe chromosomy //krzyżuje 2 chromosomy wymieniając między nimi tygodnie //najpierw przypisuje do nowych chromosomów stare chromosomy ( bo jak bd puste to co bd Krzyżować ? xd) //przypisujemy do tych nowych chromosomów kopie tablic chrosomome vector - musi to byc kopia wartościowa a nie kopia referencyjna newChromosomes[0].chromosomeVector = new List <NurseClass[][][]>(chromosome1.chromosomeVector).ToArray(); //tworze liste i pozniej tworze z niej tablice - po wartosciach wszystko kopiuje (czyli mamy całkowicie nowe tablice z tymi samymi wartosciami) newChromosomes[1].chromosomeVector = new List <NurseClass[][][]>(chromosome2.chromosomeVector).ToArray(); while (whichWeekChange < 5)//jak wyjedziemy na 6 tydzien chromosomu to koniec krzyżowania { tempTableOnWeek = newChromosomes[0].chromosomeVector[whichWeekChange]; newChromosomes[0].chromosomeVector[whichWeekChange] = newChromosomes[1].chromosomeVector[whichWeekChange]; //wymieniam cały tydzien miedzy dwoma chromosomami newChromosomes[1].chromosomeVector[whichWeekChange] = tempTableOnWeek; //tu też wymiana whichWeekChange += 2; //bedziemy krzyżować co 2 week - bo krzyżowanie co jeden nie ma sensu bo uzyskalibyśmy 2 identyczne chromosomy takie jak na wejsciu } //return new ChromosomeClass[2] { chromosome1, chromosome2 }; //zwracam 2 przekrzyżowane juz chromosomy return(newChromosomes); }
static void Main(string[] args) { //Console.SetBufferSize(200, 100); ChromosomeClass obChromosomeClass = new ChromosomeClass(); obChromosomeClass.writeNursesFromChromosomeFromEachShift(); GeneticAlgorithmClass obGeneticAlgorithmClass = new GeneticAlgorithmClass(6, 0, 2000, 1000, 1000, 4); obChromosomeClass = obGeneticAlgorithmClass.runAlgorithm(); obChromosomeClass.writeNursesFromChromosomeFromEachShift(); //wypisz ten chromosom ktory jest wynikiem Console.ReadLine(); Console.ReadLine(); }
/// <summary> /// Funkcja do krzyżowania chromosomów ze sobą , ale tylko z tymczasowej listy bestChromosomesSelectedToCrossover /// </summary> public virtual void CrossoverOfBestChromosomes(List <ChromosomeClass> bestChromosomesSelectedToCrossover) { //krzyżowanie musimy przeprowadzać dopóki nie uzyskamy howMuchChromosomeCreate nowych chromosomów int howMuchNewChromosomesWasCreated = 0; int indexOfFirstChromosome = -1; int indexOfSecondChromosome = 0; Random rnd = new Random(); ChromosomeClass[] newChromosomesAfterCrossover = new ChromosomeClass[2]; while (howMuchNewChromosomesWasCreated < howMuchChromosomesCreate) { if (howMuchNewChromosomesWasCreated >= howMuchChromosomesSelectToCrossover - 1) //jezeli już skrzyżowaliśmy ze sobą chromosomy parzyście czyli 1 z 2 , 3 z 4 itd { //to tutaj wybieramy losowo chromosomy aby stworzyć z nich pozostałe osobniki do populacji - bo paru nam brakuje do howMUchNewChromosomesWasCreated do { indexOfFirstChromosome = rnd.Next(0, bestChromosomesSelectedToCrossover.Count); indexOfSecondChromosome = rnd.Next(0, bestChromosomesSelectedToCrossover.Count); } while (indexOfFirstChromosome == indexOfSecondChromosome); //jesli bedą sie powtarzac te indeksy to żeby nie krzyżowało jednego chromosomu ze sobą //no i krzyżuje te dwa losowo wybrane chromosomy i dodaje je do listy newChromosomesAfterCrossover = crossoverOfTwoChromosomesByWeekends(bestChromosomesSelectedToCrossover[indexOfFirstChromosome], bestChromosomesSelectedToCrossover[indexOfSecondChromosome], howMuchNewChromosomesWasCreated % 2); //dodaje do listy nowych bestChromosomesSelectedToCrossover.Add(newChromosomesAfterCrossover[0]); //dodaje bestChromosomesSelectedToCrossover.Add(newChromosomesAfterCrossover[1]); } else { indexOfFirstChromosome++; indexOfSecondChromosome++; //krzyżuje parzyście - czyli pierwszy z drugim , trzeci z czwartym itd i przypisuje je odpowidnio do miejsc w liscie (zastepuje 2 inne chromosomy w liscie tymczasowej) // ↓↓↓ tu na dole w argumencie raz zaczynamy krzyżowanie od 0 week a raz od 1 week - tak żeby było różnorodnie newChromosomesAfterCrossover = crossoverOfTwoChromosomesByWeekends(bestChromosomesSelectedToCrossover[indexOfFirstChromosome], bestChromosomesSelectedToCrossover[indexOfSecondChromosome], howMuchNewChromosomesWasCreated % 2); bestChromosomesSelectedToCrossover[indexOfFirstChromosome] = newChromosomesAfterCrossover[0]; //przypisuje pierwszy nowy chromosom bestChromosomesSelectedToCrossover[indexOfSecondChromosome] = newChromosomesAfterCrossover[1]; //no i drugi nowy chromosom } howMuchNewChromosomesWasCreated += 2; //co iteracje mam 2 nowe chromosomy bo krzyżuje 2 i z nich powstaja 2 nowe } }