Individual::Individual( const Context *context, char origin, int input_ch, int input_loci, double input_lamda, int input_selected_loci, std::tuple<int, int, int> ind_birthplace ) : context{context} { number_of_chromosomes = input_ch; lambda = input_lamda; selected_loci = input_selected_loci; genome[0].reserve(number_of_chromosomes); genome[1].reserve(number_of_chromosomes); if(origin == 'A' or origin == 'B'){ for(int i=0;i<number_of_chromosomes;i++){ genome[0].push_back(Chromosome(origin, input_loci)); genome[1].push_back(Chromosome(origin, input_loci)); } } else { for(int i=0;i<number_of_chromosomes;i++){ genome[0].push_back(Chromosome('A', input_loci)); genome[1].push_back(Chromosome('B', input_loci)); } } birthplace = ind_birthplace; }
std::pair<Chromosome, Breeder::BreedStats> Breeder::breed(const Chromosome& mum, const Chromosome& dad, uint32_t crossOverPerMillion) { BreedStats stats; stats.crossOvers = 0; std::random_device rd; std::uniform_int_distribution<> randomMillion(0, 999999); std::uniform_int_distribution<> mumOrDad(0, 1); bool startWithMum = mumOrDad(rd) == 0; const Gene* currentGene = startWithMum ? &mum.gene() : &dad.gene(); const Gene* otherGene = startWithMum ? &dad.gene() : &mum.gene(); Gene resultingGene; resultingGene.resize(currentGene->size()); for(uint32_t i = 0; i < resultingGene.size(); i++) { resultingGene[i] = (*currentGene)[i]; if(crossOverPerMillion > randomMillion(rd)) { std::swap(currentGene, otherGene); ++stats.crossOvers; } } return {Chromosome(mum.maxCistronIds(), mum.informationDensity(), mum.startSequence(), mum.stopSequence(), resultingGene), stats}; }
void Population::createEmpty() { for(int i = 0; i < size_; i++) { individuals_.add(Chromosome(Chromosome::Id({generation_, i}))); } }
// Select 1 parent and for every activated state the // parameters for existing combat or economy rules have // a 50% chance of being mutated. The mutation is within a // predefined boundary (between a minimum and maximum value). // For this genetic operator, we exclude build and research rules. Chromosome GeneticOperator::RuleBiasedMutation(const Chromosome& parent) { std::vector<State> childStates = parent.getStates(); for(size_t i=0;i<childStates.size();i++) { State& s = childStates.at(i); for (size_t j=0;j<s.getGenes().size(); j++){ const std::tr1::shared_ptr<Gene> g = s.getGenes().at(j); if(typeid(*g) != typeid(BuildGene) && typeid(*g) != typeid(ResearchGene)) { // Mutate gene boost::random::uniform_int_distribution<> dist(0, 1); int randomNr = dist(randomGen); if(randomNr) { if(typeid(*g) != typeid(AttackGene)) { // Mutate parameters of gene std::tr1::shared_ptr<AttackGene> gene = StarcraftRules::getValidAttackGene(s); s.replaceGeneAt(j, gene); } else if(typeid(*g) != typeid(CombatGene)) { // Mutate parameters of gene bool found; std::tr1::shared_ptr<CombatGene> gene = StarcraftRules::getValidCombatGene(s, found); if (found) s.replaceGeneAt(j, gene); } } } } } return Chromosome(childStates); }
Chromosome randomChromosome(int size) { std::ostringstream sout; for (int i = 0; i < size; i++) { sout << (char) ((rand() % 26) + 97); } return Chromosome(sout.str()); }
vector<Chromosome> Chromosome::generateRandomPopulation(int populationSize, int solutionSize, Chromosome::GenerationType genType){ vector<Chromosome> population; population.reserve(populationSize); for (int i = 0; i < populationSize; i++){ population.push_back(Chromosome(solutionSize, genType)); } return population; }
Population* Population::nextGeneration() { Population *out=new Population(this->family, this->id+1); /*elements of the new population*/ std::vector<Chromosome>& parentElems = this->getElements(); std::vector<Chromosome> selectedElems; std::vector<Chromosome>& childElems = out->getElements(); /* copying the best ancestor chromosomes from the parent population */ for(size_t i=0; i<family.getAncCount(); i++) childElems.push_back(parentElems[i]); /* selection chromosomes from previous generation, * the number of them is popSz - ancCount * input vector for crossing operator */ select(parentElems, selectedElems); /* some of selected will be crossed */ std::vector<Chromosome> cxOpIn; float pc = family.getPc(); std::uniform_real_distribution<float> urd(0,1); size_t crossedCnt=0, rewritedCnt=0; for(Chromosome &c : selectedElems) { /* for each chromosome generate randomly g * if rg < pc then this chromosome is to be crossed, * otherwise it goes to the new population directly */ float rg = urd(gen); if(rg<pc) { cxOpIn.push_back(c); crossedCnt++; } else { childElems.push_back(c); rewritedCnt++; } } /* applying crossing operator on subsequent pairs of selected chromosomes */ /* trick - number of crossed elements always even for convienience */ if(crossedCnt %2 == 1) { cxOpIn.push_back(cxOpIn[0]); childElems.pop_back(); rewritedCnt--; } const std::vector<Chromosome> cxOpOut = (family.getCrossOp())->run(cxOpIn); for(const Chromosome &c : cxOpOut) childElems.push_back(c); /* generation new chromosomes */ for(size_t i=0; i<family.getGenSz(); i++) childElems.push_back(Chromosome( family.getCitiesNb(), family.getChromSz()) ); /* mutation */ mutate(childElems); return out; }
Chromosome Chromosome::combination(Chromosome &mate){ Chromosome newChromosome = Chromosome(_genes.substr(0)); for (size_t i = 0; i < CHROMOSOME_LENGTH; i++) { if (eventHappenedWithProbability(CROSSOVER_CHANCE)){ int crossoverLength = binomialRandomAroundTarget(CROSSOVER_AVERAGE_LENGTH); newChromosome.addCrossover(mate, i, crossoverLength); } } return newChromosome; }
Population::Population(int size) { /* * DE is not working with less than minimum amount of chromosomes. */ if (size < MIN_POPULATION_SIZE) { size = MIN_POPULATION_SIZE; } list.clear(); for(int i=0; i<size; i++) { list.push_back( Chromosome() ); } searchBestFitnessIndex(); }
Chromosome Chromosome::GACrossOver(Chromosome parentA, Chromosome parentB) { int size = parentA._solution.size(); int distance = Chromosome::distance(parentA, parentB); if (distance > size / 2) { parentA.invert(); } vector<char> childSolution(size); int ones = 0, zeros = 0; for (int i = 0; i < size; ++i) { if (parentA._solution[i] == parentB._solution[i]) { childSolution[i] = parentA._solution[i]; ones += parentA._solution[i]; zeros += parentA._solution[i] ^ 1; } else { childSolution[i] = 2; // the placeholder } } random_device rd; mt19937 gen(rd()); int addOnes = (size / 2) - ones; int addZeroes = (size / 2) - zeros; for (int k = 0; k < size; ++k) { if (childSolution[k] == 2) { bernoulli_distribution d(addOnes / (addOnes + addZeroes)); char bit = d(gen); if (bit) { addOnes--; } else { addZeroes--; } childSolution[k] = bit; } } return Chromosome(childSolution); }
Population::Population(const Family &family): family(family), id(0), next(nullptr), prev(nullptr) { /* first population is created with id=0, * popSz <= chromSz! - max number of different chromosomes * CAUTION: pointer prev of first population has to be set to nullptr * in order to memory deallocation works properly */ for(size_t i=0; i<family.getPopSz(); i++) { Chromosome c; do { c = Chromosome(family.getCitiesNb(), family.getChromSz()); } while(i>0 && this->contains(c)); elements.push_back(c); } }
int testIndividual(){ Context context = createTestContext(); Individual Lili; Individual Igor(&context, 'C', 3, 40, 2.3, 4, std::tuple<int, int, int>(-1, -1, -1)); double sumCh = 0.0; for(int i = 0; i < 10000; i++){ sumCh += context.random.poisson(Igor.getLambda()); } sumCh = sumCh / 10000; if(sumCh > 2.5 or sumCh < 2.1){ std::cerr << "WARNING: unexpected behavior of generator of Chiasmas, " << std::endl; std::cerr << "Change seed for random number and rerun tests, if this message occurs again" << " something is wrong, please do not ignore it and report the issue." << std::endl; return 2; } // to test all computing functions on semi-known system, one gamete for the tested individual Stuart // will be a product of recombination and the second will be pure 'A' gamete. Therefore heterozygocity // will be equivalent to proportion of B in the sirt set std::vector<Chromosome> gamete1; std::vector<Chiasmata> chiasma1, chiasma2; Igor.makeGamete(gamete1, chiasma1); std::vector<Chromosome> gamete2; for(unsigned int i = 0; i < gamete1.size(); i++){ gamete2.push_back(Chromosome('A',gamete1[i].getResolution())); chiasma2.push_back(Chiasmata()); } Individual Stuart(&context, gamete1, chiasma1, gamete2, chiasma2, 1.6, Igor.getNumberOfSelectedLoci(), std::tuple<int, int, int>(-1, -1, -1)); if(Igor.getSelectedHybridIndex() != 0.5){ std::cerr << "f1 hybrid has selected hybrid index != 0.5!" << std::endl; return 1; } int count = 0; for(int i=0;i<Stuart.getNumberOfChromosomes();i++){ count += gamete1[i].countB(); count += gamete2[i].countB(); } if(count != Stuart.getBcount()){ std::cerr << "Discrepancy between B count of all Chromosomes and Individual \n"; return 1; } double total_number_of_loci = (Stuart.getNumberOfChromosomes() * Stuart.getNumberOfLoci(0)); if((count / (total_number_of_loci * 2)) != Stuart.getBprop()){ std::cerr << "Discrepancy between B prop of all Chromosomes and Individual \n"; return 1; } if((double)count / total_number_of_loci != Stuart.getHetProp()){ std::cerr << "Manually comuted heterozygocity: " << count << " / " << total_number_of_loci << " = " << (double)count / total_number_of_loci << " != heterozygocity from function: " << Stuart.getHetProp() << std::endl; return 1; } if( 0 != Stuart.isPureA()){ std::cerr << "Error: isPureA have not passed \n"; return 1; } if( 0 != Stuart.isPureB()){ std::cerr << "Warning: isPureB have not passed. Very very unlikely scenario, rerun test. \n"; return 1; } // number of junctions independently derived from every chromosome compared to number of juctions derived from the method of individual int number_junction = 0; for(int i=0;i<Stuart.getNumberOfChromosomes();i++){ number_junction += gamete1[i].getNumberOfJunctions(); number_junction += gamete2[i].getNumberOfJunctions(); } if(Stuart.getNumberOfJunctions(0, 0) != gamete1[0].getNumberOfJunctions()){ std::cerr << "Number of junctions of st chromosome and st haplotype does not match number of junction in first gamete." << std::endl; return 1; } if(Stuart.getNumberOfJunctions() != number_junction){ std::cerr << "Total number of junctions does not match number of junction in first gamete." << std::endl; return 1; } // neutral loci test 2 Chromosome ch1('B', 40); Chromosome ch2('A', 40); ch1.write(13,'A'); ch2.write(14,'B'); gamete1.clear(); gamete1.push_back(ch1); gamete2.clear(); gamete2.push_back(ch2); Individual Anna(&context, gamete1, chiasma1, gamete2, chiasma2, 1.6, 4, std::tuple<int, int, int>(-1, -1, -1)); if(Anna.getSelectedHybridIndex() != 0.375){ std::cerr << "Folowing individual :" << std::endl; Anna.readGenotype(); std::cerr << "has unexpected selected hybrid index: " << Anna.getSelectedHybridIndex() << std::endl; std::cerr << "4 selected loci / chromosome of total 40 loci" << std::endl; std::cerr << "means that selected loci have indices 0, 13, 26 and 39" << std::endl; std::cerr << "therefore we expected 0.375 given the genotype..." << std::endl; return 1; } return 0; }
void Individual::replace_chromozome(int set, int position, std::map <int, char> input_chrom, int size){ genome[set][position] = Chromosome(input_chrom, size); }
// Select 2 parents and check if the selected parents have at // least 3 matching activated states for crossover. We make sure that // the child chromosome inherits genetic material from both parents // to prevent a parent from being copied completely onto the child chromosome. // Between two matching states, all states and genes are copied from either parent Chromosome GeneticOperator::StateCrossover(const Chromosome& parent1, const Chromosome& parent2, bool& threeMatchesFound) { std::vector<State> childStates; bool takeFromParent1 = true; int matches = 0; int stateSize = std::min(parent1.getStates().size(),parent2.getStates().size()); // Counts the number of matches. At least three is required for(int i=0;i<stateSize;i++) { if(parent1.getStates().at(i) == parent2.getStates().at(i)) { matches++; } } if (matches < 3) { threeMatchesFound = false; return Chromosome(); } else threeMatchesFound = true; int lastMatch = 0; for(int i=0;i<stateSize;i++) { if(parent1.getStates().at(i) == parent2.getStates().at(i)) { // Alternate between copying states from parent1 and parent2 if(takeFromParent1) { for(int j=lastMatch;j<i;j++) { childStates.push_back(parent1.getStates().at(j)); } //std::copy(parent1.getStates().begin()+lastMatch, parent1.getStates().begin()+i,std::back_inserter(childStates)); takeFromParent1 = false; } else { for(int j=lastMatch;j<i;j++) { childStates.push_back(parent2.getStates().at(j)); } //std::copy(parent2.getStates().begin()+lastMatch, parent2.getStates().begin()+i,std::back_inserter(childStates)); takeFromParent1 = true; } lastMatch = i; } } // Add remaining states after last matching state if(takeFromParent1) { for(int j=lastMatch;j<parent1.getStates().size();j++) { childStates.push_back(parent1.getStates().at(j)); } //std::copy(parent1.getStates().begin()+lastMatch, parent1.getStates().end(),std::back_inserter(childStates)); } else { for(int j=lastMatch;j<parent2.getStates().size();j++) { childStates.push_back(parent2.getStates().at(j)); } //std::copy(parent2.getStates().begin()+lastMatch, parent2.getStates().end(),std::back_inserter(childStates)); } return Chromosome(childStates); }
// Select 1 parent and for every activated state all // economy, research or combat rules have a 25% chance of being replaced. // Building rules are excluded here both for replacement and as replacement, // because these could spawn a state change and could possibly corrupt the // chromosome. Genes in inactivated states are ignored as they are considered // ‘dead’ and mutation doesn’t really make sense here. Chromosome GeneticOperator::RuleReplaceMutation(const Chromosome& parent) { std::vector<State> childStates = parent.getStates(); // TODO: Only select activated states for(size_t i=0;i<childStates.size();i++) { State& s = childStates.at(i); for (size_t j=0;j<s.getGenes().size(); j++){ const std::tr1::shared_ptr<Gene> g = s.getGenes().at(j); if(typeid(*g) != typeid(BuildGene)) { boost::random::uniform_int_distribution<> dist(1, 100); int randomNr = dist(randomGen); if(randomNr <= 25) { boost::random::uniform_int_distribution<> dist2(0, 1); int replaceNr = dist2(randomGen); if(typeid(*g) == typeid(CombatGene)) { if (replaceNr == 1) { bool found; std::tr1::shared_ptr<ResearchGene> gene = StarcraftRules::getValidResearchGene( s, found); if (found == true) s.replaceGeneAt(j,gene); } else { std::tr1::shared_ptr<AttackGene> gene = StarcraftRules::getValidAttackGene(s); s.replaceGeneAt(j,gene); } } else if(typeid(*g) == typeid(ResearchGene)) { if (replaceNr == 1) { std::tr1::shared_ptr<AttackGene> gene = StarcraftRules::getValidAttackGene( s); s.replaceGeneAt(j,gene); } else { bool found; std::tr1::shared_ptr<CombatGene> gene = StarcraftRules::getValidCombatGene( s, found); if (found == true) s.replaceGeneAt(j,gene); } } else if(typeid(*g) == typeid(AttackGene)) { if (replaceNr == 1) { bool found; std::tr1::shared_ptr<ResearchGene> gene = StarcraftRules::getValidResearchGene( s, found); if (found == true) s.replaceGeneAt(j,gene); } else { bool found; std::tr1::shared_ptr<CombatGene> gene = StarcraftRules::getValidCombatGene( s, found); if (found == true) s.replaceGeneAt(j,gene); } } } } } }; return Chromosome(childStates); }