bool TreeMutShrink::mutate(GenotypeP gene) { Tree* tree = (Tree*) (gene.get()); // try to select random node in tree which is not a terminal // (it is silly to shrink just a terminal :)) uint chosenNode; uint chosenNodeSubtreeSize; uint tries = 0; do { chosenNode = state_->getRandomizer()->getRandomInteger((int) tree->size()); chosenNodeSubtreeSize = tree->at(chosenNode)->size_; tries++; } while(chosenNodeSubtreeSize == 1 && tries < 4); if(chosenNodeSubtreeSize == 1) { ECF_LOG(state_, 5, "TreeMutShrink not successful."); return false; } // first of all, make a copy and clear the original Tree* copyTree = tree->copy(); tree->clear(); std::stringstream log; log << "TreeMutShrink successful ("; uint i = 0; // copy all nodes before chosen subtree to original for( ; i < chosenNode; i++) { NodeP node = static_cast<NodeP> (new Node(copyTree->at(i)->primitive_)); tree->addNode(node); } log << "shrinkedSubtree = "; for( ; i < chosenNode + chosenNodeSubtreeSize; i++) { // these nodes are skipped because they are elements of the chosen subtree log << copyTree->at(i)->primitive_->getName() << " "; } // chosen subtree is shrinked to a random terminal Node* node = new Node; node->setPrimitive(copyTree->primitiveSet_->getRandomTerminal()); tree->addNode(node); log << ", shrinkedTo = " << node->primitive_->getName() << ")"; // copy all nodes after chosen subtree to original for( ; i < copyTree->size(); i++) { NodeP node = static_cast<NodeP> (new Node(copyTree->at(i)->primitive_)); tree->addNode(node); } tree->update(); delete copyTree; ECF_LOG(state_, 5, log.str()); return true; }
bool initialize(StateP state) { voidP lBound = state->getGenotypes()[0]->getParameterValue(state, "lbound"); lbound = *((double*) lBound.get()); voidP uBound = state->getGenotypes()[0]->getParameterValue(state, "ubound"); ubound = *((double*) uBound.get()); voidP dimension_ = state->getGenotypes()[0]->getParameterValue(state, "dimension"); dimension = *((uint*) dimension_.get()); voidP dup_ = getParameterValue(state, "dup"); dup = *((uint*) dup_.get()); if( *((int*) dup_.get()) <= 0 ) { ECF_LOG(state, 1, "Error: opt-IA requires parameter 'dup' to be an integer greater than 0"); throw "";} voidP c_ = getParameterValue(state, "c"); c = *((double*) c_.get()); if( c <= 0 ) { ECF_LOG(state, 1, "Error: opt-IA requires parameter 'c' to be a double greater than 0"); throw "";} voidP tauB_ = getParameterValue(state, "tauB"); tauB = *((double*) tauB_.get()); if( tauB < 0 ) { ECF_LOG(state, 1, "Error: opt-IA requires parameter 'tauB' to be a nonnegative double value"); throw "";} voidP elitism_ = getParameterValue(state, "elitism"); elitism = *((string*) elitism_.get()); if( elitism != "true" && elitism != "false" ) { ECF_LOG(state, 1, "Error: opt-IA requires parameter 'elitism' to be either 'true' or 'false'"); throw "";} // algorithm accepts a single FloatingPoint Genotype FloatingPointP flp (new FloatingPoint::FloatingPoint); if(state->getGenotypes()[0]->getName() != flp->getName()) { ECF_LOG_ERROR(state, "Error: opt-IA algorithm accepts only a FloatingPoint genotype!"); throw ("");} // algorithm adds another FloatingPoint genotype (age) FloatingPointP flpoint[2]; for(uint iGen = 1; iGen < 2; iGen++) { flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint; state->setGenotype(flpoint[iGen]); flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1)); // initial value of age parameter should be (or as close as possible to) 0 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0)); flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(0.01)); } ECF_LOG(state, 1, "opt-IA algorithm: added 1 FloatingPoint genotype (antibody age)"); return true; }
bool TreeMutGauss::mutate(GenotypeP gene) { Tree* tree = (Tree*) (gene.get()); // try to select ERC node of type double uint iNode; uint tries = 0; std::string name; do { iNode = state_->getRandomizer()->getRandomInteger((int) tree->size()); tries++; } while((name = tree->at(iNode)->primitive_->getName()).substr(0, 2) != DBL_PREFIX && tries < 4); if(name.substr(0, 2) != DBL_PREFIX) { ECF_LOG(state_, 5, "TreeMutGauss not successful."); return false; } double oldValue; PrimitiveP oldPrim = tree->at(iNode)->primitive_; tree->at(iNode)->primitive_->getValue(&oldValue); std::string oldName = tree->at(iNode)->primitive_->getName(); // generate Gauss noise offset and add it // TODO: parametrize distribution! boost::normal_distribution<double> N(0, 1); // e.g. http://www.codepedia.com/1/CppBoostRandom // TODO: preserve state //boost::lagged_fibonacci607 engine(state_->getRandomizer()->getRandomInteger(100000) + 1); double offset = N.operator () <boost::lagged_fibonacci607>(engine_); double newValue = oldValue + offset; // change double ERC value and name std::stringstream ss; ss << newValue; std::string newName; ss >> newName; newName = DBL_PREFIX + newName; oldPrim->setName(newName); oldPrim->setValue(&newValue); // new ERCs aren't stored in the PrimitiveSet std::stringstream log; log << "TreeMutGauss successful (oldNode = " << oldName << ", newNode = " << newName << ")"; ECF_LOG(state_, 5, log.str()); return true; }
/** * \brief Mutate an individual. * * May mutate one or more genotypes in given individual. * Determines which MutationOp to use on each genotype. */ bool Mutation::mutate(IndividualP ind) { ind->fitness->setInvalid(); // set mutation context state_->getContext()->mutatedIndividual = ind; ECF_LOG(state_, 5, "Mutating individual: " + ind->toString()); currentInd = ind; // if mutating a random genotype if(mutateGenotypes_ == RANDOM_GENOTYPE) { uint iGenotype = state_->getRandomizer()->getRandomInteger((int)ind->size()); if(protectedGenotypes_[iGenotype]) return false; // choose operator uint iOperator; if(opProb[iGenotype][0] < 0) iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size()); else { double random = state_->getRandomizer()->getRandomDouble(); iOperator = 0; while(opProb[iGenotype][iOperator] < random) iOperator++; } operators[iGenotype][iOperator]->mutate(ind->at(iGenotype)); } // if mutating all genotypes in the individual else if(mutateGenotypes_ == ALL_GENOTYPES) { for(uint iGenotype = 0; iGenotype < ind->size(); iGenotype++) { if(protectedGenotypes_[iGenotype]) continue; // choose operator uint iOperator; if(opProb[iGenotype][0] < 0) iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size()); else { double random = state_->getRandomizer()->getRandomDouble(); iOperator = 0; while(opProb[iGenotype][iOperator] < random) iOperator++; } operators[iGenotype][0]->mutate(ind->at(iGenotype)); } } ECF_LOG(state_, 5, "Mutated individual: " + ind->toString()); return true; }
// ispis tijeka min fitnesa - za potrebe mjerenja void StatCalc::output(uint step) { std::stringstream log; for(uint i = 0; i < min_.size(); i += step) log << i << "\t" << min_[i] << std::endl; ECF_LOG(state_, 2, log.str()); }
/** * Log statistics. */ void StatCalc::log(int generation) { if(generation == -1) generation = statNo; ECF_LOG(state_, 3, "Evaluations: " + uint2str(evaluations_[generation]) + "\nStats: fitness\n\tmax: " + dbl2str(max_[generation]) + "\n\tmin: " + dbl2str(min_[generation]) + "\n\tavg: " + dbl2str(average_[generation]) + "\n\tstdev: " + dbl2str(stdDev_[generation]) + "\n"); }
bool TermStagnationOp::operate(StateP state) { uint currentGen = state->getGenerationNo(); if(currentGen - state->getPopulation()->getHof()->getLastChange() > termStagnation_) { state->setTerminateCond(); ECF_LOG(state, 1, "Termination: maximum number of generations without improvement (" + uint2str(termStagnation_) + ") reached"); } return true; }
bool ArtificialBeeColony::initialize(StateP state) { // initialize all operators selFitOp->initialize(state); selFitOp->setSelPressure(2); selBestOp->initialize(state); selWorstOp->initialize(state); selRandomOp->initialize(state); voidP sptr = state->getRegistry()->getEntry("population.size"); uint size = *((uint*) sptr.get()); probability_.resize(size); // this algorithm accepts a single FloatingPoint Genotype FloatingPointP flp (new FloatingPoint::FloatingPoint); if(state->getGenotypes()[0]->getName() != flp->getName()) { ECF_LOG_ERROR(state, "Error: ABC algorithm accepts only a single FloatingPoint genotype!"); throw (""); } voidP limitp = getParameterValue(state, "limit"); limit_ = *((uint*) limitp.get()); voidP lBound = state->getGenotypes()[0]->getParameterValue(state, "lbound"); lbound_ = *((double*) lBound.get()); voidP uBound = state->getGenotypes()[0]->getParameterValue(state, "ubound"); ubound_ = *((double*) uBound.get()); // batch run check if(isTrialAdded_) return true; FloatingPointP flpoint[2]; for(uint iGen = 1; iGen < 2; iGen++) { flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint; state->setGenotype(flpoint[iGen]); flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1)); // initial value of trial parameter should be (as close as possible to) 0 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0)); flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(0.01)); } ECF_LOG(state, 1, "ABC algorithm: added 1 FloatingPoint genotype (trial)"); // mark adding of trial genotype isTrialAdded_ = true; return true; }
bool initialize(StateP state) { // initialize all operators selFitOp->initialize(state); selBestOp->initialize(state); selRandomOp->initialize(state); voidP limit_ = getParameterValue(state, "limit"); limit = *((uint*) limit_.get()); voidP lBound = state->getGenotypes()[0]->getParameterValue(state, "lbound"); lbound = *((double*) lBound.get()); voidP uBound = state->getGenotypes()[0]->getParameterValue(state, "ubound"); ubound = *((double*) uBound.get()); // algorithm accepts a single FloatingPoint Genotype FloatingPointP flp (new FloatingPoint::FloatingPoint); if(state->getGenotypes()[0]->getName() != flp->getName()) { ECF_LOG_ERROR(state, "Error: ABC algorithm accepts only a FloatingPoint genotype!"); throw (""); } FloatingPointP flpoint[2]; for(uint iGen = 1; iGen < 2; iGen++) { flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint; state->setGenotype(flpoint[iGen]); flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1)); // initial value of trial parameter should be (as close as possible to) 0 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0)); flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(0.01)); } ECF_LOG(state, 1, "ABC algorithm: added 1 FloatingPoint genotype (trial)"); return true; }
bool TreeCrxProbabilistic::mate(GenotypeP gen1, GenotypeP gen2, GenotypeP ch) { Tree* male = (Tree*)(gen1.get()); Tree* female = (Tree*)(gen2.get()); Tree* child = (Tree*)(ch.get()); uint mIndex, fIndex; uint mRange, fRange; uint mNodeDepth, fNodeDepth, fNodeDepthSize; mRange = (uint)male->size(); fRange = (uint)female->size(); // LD: femaleSizeIndexes[i] je vektor indeksa cvorova cija je velicina podstabla = i std::vector < std::vector<uint> > femaleSizeIndexes; femaleSizeIndexes.resize(fRange + 1); for (uint i = 0; i < fRange; i++) femaleSizeIndexes[female->at(i)->size_].push_back(i); uint nTries = 0; while (1) { //probabilisticDistancesIndices[i] contains a female index whose distance //is stored in probabilisticDistancesValues[i] std::vector<int> probabilisticDistancesIndices; //probabilisticDistancesValues[i] contains probabilistic distance of //probabilisticDistancesValues[i]-th node from chosen male node std::vector<double> probabilisticDistancesValues; // choose random crx point in male parent mIndex = state_->getRandomizer()->getRandomInteger(0, mRange - 1); // chose female crx point with expected size less or equal to the male's subtree uint subtreeSize = calculateSize(male->at(mIndex)->size_); double maleMax = male->at(mIndex)->primitive_->maxComputedValue; double maleMin = male->at(mIndex)->primitive_->minComputedValue; double sumOfAllDistances = 0; //j iterates over sizes for (uint j = 1; j < (1 + 2 * subtreeSize) && j < femaleSizeIndexes.size(); j++) { //index iterates over subtrees of j size for (uint index = 0; index < femaleSizeIndexes[j].size(); index++) { double femaleMax = female->at(femaleSizeIndexes[j].at(index))->primitive_->maxComputedValue; double femaleMin = female->at(femaleSizeIndexes[j].at(index))->primitive_->minComputedValue; double distance = 0.5 * (abs(maleMax - femaleMax) + abs(maleMin - femaleMin)); probabilisticDistancesIndices.push_back(femaleSizeIndexes[j].at(index)); probabilisticDistancesValues.push_back(distance); sumOfAllDistances += distance; } } if (sumOfAllDistances == 0) { nTries++; if (nTries > 4) { ECF_LOG(state_, 5, "TreeCrxProbabilistic not successful."); return false; } continue; } //calculate d' for (int i = 0; i < probabilisticDistancesIndices.size(); i++) { double value = probabilisticDistancesValues[i] / sumOfAllDistances; if (value < 0.000000000001) value = 0; probabilisticDistancesValues[i] = value; } //calculate p double sumOfAllInvertedDistances = 0; for (int i = 0; i < probabilisticDistancesIndices.size(); i++) { sumOfAllInvertedDistances += 1 - probabilisticDistancesValues[i]; } for (int i = 0; i < probabilisticDistancesIndices.size(); i++) { double value = (1 - probabilisticDistancesValues[i]) / sumOfAllInvertedDistances; probabilisticDistancesValues[i] = value; } srand((unsigned)time(NULL)); double p = ((double)rand() / (double)RAND_MAX); double minDiff = 1; fIndex = 0; for (int i = 0; i < probabilisticDistancesIndices.size(); i++) { double tempDiff = abs(probabilisticDistancesValues[i] - p); if (tempDiff < minDiff) { minDiff = tempDiff; fIndex = probabilisticDistancesIndices[i]; } } mNodeDepth = male->at(mIndex)->depth_; fNodeDepth = female->at(fIndex)->depth_; // find max depth int maxDepth = fNodeDepth, depth; for (uint i = 0; i < female->at(fIndex)->size_; i++) { depth = female->at(fIndex + i)->depth_; maxDepth = depth > maxDepth ? depth : maxDepth; } fNodeDepthSize = maxDepth - fNodeDepth; nTries++; if (nTries > 4 || mNodeDepth + fNodeDepthSize <= male->maxDepth_) break; } if (nTries > 4 && mNodeDepth + fNodeDepthSize > male->maxDepth_) { ECF_LOG(state_, 5, "TreeCrxProbabilistic not successful."); return false; } child->clear(); child->maxDepth_ = male->maxDepth_; child->minDepth_ = male->minDepth_; child->startDepth_ = male->startDepth_; // copy from male parent for (uint i = 0; i < mIndex; i++) { NodeP node = static_cast<NodeP> (new Node(male->at(i)->primitive_)); child->push_back(node); child->at(i)->depth_ = male->at(i)->depth_; } // copy from female parent for (uint i = 0; i < female->at(fIndex)->size_; i++) { NodeP node = static_cast<NodeP> (new Node(female->at(fIndex + i)->primitive_)); child->push_back(node); } // copy rest from male parent for (uint i = mIndex + male->at(mIndex)->size_; i < mRange; i++) { NodeP node = static_cast<NodeP> (new Node(male->at(i)->primitive_)); child->push_back(node); } // update node depths and subtree sizes child->update(); return true; }
bool TreeCrxOnePoint::mate(GenotypeP gen1, GenotypeP gen2, GenotypeP ch) { Tree* male = (Tree*) (gen1.get()); Tree* female = (Tree*) (gen2.get()); Tree* child = (Tree*) (ch.get()); uint mIndex, fIndex; uint mRange, fRange; uint mNodeDepth, fNodeDepth, fNodeDepthSize; mRange = (uint) male->size(); fRange = (uint) female->size(); // for common region nodes std::vector <uint> maleCommonRegionIndexes; std::vector <uint> femaleCommonRegionIndexes; for( uint iMale = 0, iFemale = 0; iMale < mRange && iFemale < fRange; iMale++, iFemale++ ) { // add common region nodes maleCommonRegionIndexes.push_back( iMale ); femaleCommonRegionIndexes.push_back( iFemale ); // skip nodes with different no. of arguments if( male->at( iMale )->primitive_->getNumberOfArguments() != female->at( iFemale )->primitive_->getNumberOfArguments() ) { iMale += male->at( iMale )->size_; iFemale += female->at( iFemale )->size_; } } uint nTries = 0; while(1) { // choose random node from common region uint randomNode = state_->getRandomizer()->getRandomInteger(0 , (uint) maleCommonRegionIndexes.size()-1 ); mIndex = maleCommonRegionIndexes[ randomNode ]; fIndex = femaleCommonRegionIndexes[ randomNode ]; // LD: provjera dubine je redundantna u slucaju da sve jedinke imaju jednaki maxDepth_ // ili kada otac ima veci ili jednak maxDepth_ mNodeDepth = male->at( mIndex )->depth_; fNodeDepth = female->at( fIndex )->depth_; // find max depth int maxDepth = fNodeDepth, depth; for(uint i = 0; i < female->at( fIndex )->size_; i++) { depth = female->at( fIndex + i )->depth_; maxDepth = depth > maxDepth ? depth : maxDepth; } fNodeDepthSize = maxDepth - fNodeDepth; nTries++; if(nTries > 4 || mNodeDepth + fNodeDepthSize <= male->maxDepth_ ) break; } if(nTries > 4 && mNodeDepth + fNodeDepthSize > male->maxDepth_) { ECF_LOG(state_, 5, "TreeCrxOnePoint not successful."); return false; } child->clear(); child->maxDepth_ = male->maxDepth_; child->minDepth_ = male->minDepth_; child->startDepth_ = male->startDepth_; // copy from male parent for(uint i = 0; i < mIndex; i++) { NodeP node = static_cast<NodeP> (new Node( male->at(i)->primitive_)); child->push_back( node ); child->at( i )->depth_ = male->at( i )->depth_; } // copy from female parent for(uint i = 0; i < female->at( fIndex )->size_; i++) { NodeP node = static_cast<NodeP> (new Node( female->at( fIndex + i)->primitive_)); child->push_back( node ); } // copy rest from male parent for(uint i = mIndex + male->at( mIndex )->size_; i < mRange; i++) { NodeP node = static_cast<NodeP> (new Node( male->at( i )->primitive_)); child->push_back( node ); } // update node depths and subtree sizes child->update(); return true; }
bool PSOInheritance::initialize(StateP state) { // initialize all operators selBestOp->initialize(state); voidP weightType = getParameterValue(state, "weightType"); m_weightType = *((InertiaWeightType*) weightType.get()); voidP weight = getParameterValue(state, "weight"); m_weight = *((double*) weight.get()); voidP maxV = getParameterValue(state, "maxVelocity"); m_maxV = *((double*) maxV.get()); // test if inertia weight type is time variant and if so, check if max iterations specified if(m_weightType == TIME_VARIANT) { if(state->getRegistry()->isModified("term.maxgen")) { // read maxgen parameter m_maxIter = *(boost::static_pointer_cast<int>( state->getRegistry()->getEntry("term.maxgen") )); } else { ECF_LOG_ERROR(state, "Error: term.maxgen has to be specified in order to use time variant inertia eight in PSO algorithm"); throw(""); } } // algorithm accepts a single FloatingPoint Genotype FloatingPointP flp (new FloatingPoint::FloatingPoint); if(state->getGenotypes()[0]->getName() != flp->getName()) { ECF_LOG_ERROR(state, "Error: PSO algorithm accepts only a single FloatingPoint genotype!"); throw (""); } voidP sptr = state->getGenotypes()[0]->getParameterValue(state, "dimension"); uint numDimension = *((uint*) sptr.get()); voidP bounded = getParameterValue(state, "bounded"); bounded_ = *((bool*) bounded.get()); sptr = state->getGenotypes()[0]->getParameterValue(state, "lbound"); lbound_ = *((double*) sptr.get()); sptr = state->getGenotypes()[0]->getParameterValue(state, "ubound"); ubound_ = *((double*) sptr.get()); // batch run check if(areGenotypesAdded_) return true; FloatingPointP flpoint[4]; for(uint iGen = 1; iGen < 4; iGen++) { flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint; state->setGenotype(flpoint[iGen]); if(iGen == 3) flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1)); else flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(numDimension)); // other parameters are proprietary (ignored by the algorithm) flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0)); flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(1)); } ECF_LOG(state, 1, "PSO algorithm: added 3 FloatingPoint genotypes (particle velocity, best-so-far postition, best-so-far fitness value)"); // mark adding of genotypes areGenotypesAdded_ = true; return true; }
bool TreeCrxSizeFair::mate(GenotypeP gen1, GenotypeP gen2, GenotypeP ch) { Tree* male = (Tree*) (gen1.get()); Tree* female = (Tree*) (gen2.get()); Tree* child = (Tree*) (ch.get()); uint mIndex, fIndex; uint mRange, fRange; uint mNodeDepth, fNodeDepth, fNodeDepthSize; mRange = (uint) male->size(); fRange = (uint) female->size(); // LD: femaleSizeIndexes[i] je vektor indeksa cvorova cija je velicina podstabla = i std::vector < std::vector<uint> > femaleSizeIndexes; femaleSizeIndexes.resize( fRange + 1 ); for(uint i = 0; i < fRange; i++) femaleSizeIndexes[ female->at( i )->size_ ].push_back( i ); uint nTries = 0; while(1) { // choose random crx point in male parent mIndex = state_->getRandomizer()->getRandomInteger(0 , mRange -1 ); // chose female crx point with expected size less or equal to the male's subtree uint subtreeSize = calculateSize (male->at( mIndex )->size_); while(1) { //LD: ako ne postoji podstablo trazene velicine, trazimo za jedan manje if( subtreeSize <= fRange && femaleSizeIndexes[ subtreeSize ].size()) break; subtreeSize --; } uint tmpRnd = state_->getRandomizer()->getRandomInteger(0 , (uint) femaleSizeIndexes[ subtreeSize ].size() - 1 ); fIndex = femaleSizeIndexes[ subtreeSize ][ tmpRnd ]; mNodeDepth = male->at( mIndex )->depth_; fNodeDepth = female->at( fIndex )->depth_; // find max depth int maxDepth = fNodeDepth, depth; for(uint i = 0; i < female->at( fIndex )->size_; i++) { depth = female->at( fIndex + i )->depth_; maxDepth = depth > maxDepth ? depth : maxDepth; } fNodeDepthSize = maxDepth - fNodeDepth; nTries++; if(nTries > 4 || mNodeDepth + fNodeDepthSize <= male->maxDepth_ ) break; } if(nTries > 4 && mNodeDepth + fNodeDepthSize > male->maxDepth_) { ECF_LOG(state_, 5, "TreeCrxSizeFair not successful."); return false; } child->clear(); child->maxDepth_ = male->maxDepth_; child->minDepth_ = male->minDepth_; child->startDepth_ = male->startDepth_; // copy from male parent for(uint i = 0; i < mIndex; i++) { NodeP node = static_cast<NodeP> (new Node( male->at(i)->primitive_)); child->push_back( node ); child->at( i )->depth_ = male->at( i )->depth_; } // copy from female parent for(uint i = 0; i < female->at( fIndex )->size_; i++) { NodeP node = static_cast<NodeP> (new Node( female->at( fIndex + i)->primitive_)); child->push_back( node ); } // copy rest from male parent for(uint i = mIndex + male->at( mIndex )->size_; i < mRange; i++) { NodeP node = static_cast<NodeP> (new Node( male->at( i )->primitive_)); child->push_back( node ); } // update node depths and subtree sizes child->update(); return true; }