/*! * \brief Interpret the GP individual. * \param outResult Datum containing the result of the interpretation. * \param ioContext GP evolutionary context. * \throw Beagle::ObjectException When individual or tree are empty. * \throw Beagle::AssertException When context is not correctly set. * \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed. * \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed. */ void GP::Individual::run(GP::Datum& outResult, GP::Context& ioContext) { Beagle_StackTraceBeginM(); if(&ioContext.getIndividual() != this) { std::ostringstream lOSS; lOSS << "In GP::Individual::run(): For the given context, "; lOSS << "getIndividual() did not return the same individual as was passed to this (run) "; lOSS << "method. Consider setting the context's individual to be the same by using the "; lOSS << "method Context::setIndividualHandle()."; throw Beagle_RunTimeExceptionM(lOSS.str()); } if(empty()) throw Beagle_ObjectExceptionM("Could not interpret, individual has no trees!"); if((*this)[0]->empty()) throw Beagle_ObjectExceptionM("Could not interpret, 1st tree is empty!"); Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle(); unsigned int lOldTreeIndex = ioContext.getGenotypeIndex(); ioContext.setGenotypeIndex(0); ioContext.setGenotypeHandle((*this)[0]); Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Running the ")+uint2ordinal(ioContext.getIndividualIndex()+1)+ std::string(" individual") ); Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("The individual is: ") ); Beagle_LogDebugM( ioContext.getSystem().getLogger(), (*this) ); Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("Executing the first tree root node '")+ (*(*this)[0])[0].mPrimitive->getName()+"'" ); ioContext.setNodesExecutionCount(0); ioContext.incrementNodesExecuted(); ioContext.getExecutionTimer().reset(); ioContext.pushCallStack(0); (*(*this)[0])[0].mPrimitive->execute(outResult, ioContext); ioContext.popCallStack(); ioContext.checkExecutionTime(); Beagle_LogDebugM( ioContext.getSystem().getLogger(), std::string("Result of executing the ")+uint2ordinal(ioContext.getIndividualIndex()+1)+ std::string(" individual: ")+outResult.serialize() ); ioContext.setGenotypeIndex(lOldTreeIndex); ioContext.setGenotypeHandle(lOldTreeHandle); Beagle_StackTraceEndM(); }
/*! * \brief Validate the GP individual. * \param ioContext Evolutionary context. * \return True if the GP individual is valid, false if not. */ bool GP::Individual::validate(GP::Context& ioContext) { Beagle_StackTraceBeginM(); bool lResult = true; Beagle_LogDetailedM( ioContext.getSystem().getLogger(), std::string("Validating ")+uint2ordinal(ioContext.getIndividualIndex()+1)+ std::string(" individual") ); // Store original values. GP::Tree::Handle lOldTreeHandle = ioContext.getGenotypeHandle(); unsigned int lOldTreeIndex = ioContext.getGenotypeIndex(); // Loop through each of the trees in the individual for (unsigned int i=0; i<size(); i++) { GP::Tree::Handle lTree = (*this)[i]; if (lTree == NULL) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Skipping ")+uint2ordinal(i+1)+std::string(" tree because it's NULL-valued") ); continue; } Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Validating ")+uint2ordinal(i+1)+std::string(" tree") ); // Store the new values ioContext.setGenotypeHandle(lTree); ioContext.setGenotypeIndex(i); lTree->setContextToNode(0, ioContext); if(!lTree->validateSubTree(0, ioContext)) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Validation of ")+uint2ordinal(i+1)+std::string(" tree failed.") ); lResult = false; break; } } if(lResult) { Beagle_LogVerboseM( ioContext.getSystem().getLogger(), std::string("Individual passed validation testing.") ); } // Restore the original values. ioContext.setGenotypeHandle(lOldTreeHandle); ioContext.setGenotypeIndex(lOldTreeIndex); return lResult; Beagle_StackTraceEndM(); }
/*! * \brief Evaluate the individual fitness. * \param inIndividual Individual to evaluate. * \param ioContext Evolutionary context. * \return Handle to the fitness measure. */ Fitness::Handle SharedLibEvalOp::evaluate(GP::Individual& inIndividual, GP::Context& ioContext) { Beagle_StackTraceBeginM(); std::ostringstream lOSS; lOSS << "Evaluating individual " << ioContext.getIndividualIndex() << ", deme "; lOSS << ioContext.getDemeIndex() << ", generation " << ioContext.getGeneration(); Beagle_LogDebugM(ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SpamebaseEvalOp", lOSS.str()); GP::PrimitiveSuperSet::Handle lPrimitiveSuperSet= castHandleT<GP::PrimitiveSuperSet>(ioContext.getSystem().getComponent("GP-PrimitiveSuperSet")); GP::PrimitiveSet::Handle lPrimitiveSet= (*lPrimitiveSuperSet)[0]; // Get a handle on the shared library used for evaluation. // TODO: Open shared lib only once per generation! this->mTimer.reset(); if (this->mSharedLibHandle) { dlclose(this->mSharedLibHandle); Beagle_LogDebugM( ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SpamebaseEvalOp", "Closed previously opened shared lib."); } if (!ioContext.getSystem().getRegister().isRegistered("icu.compiler.lib-path")) { throw Beagle_RunTimeExceptionM("Parameter icu.compiler.lib-path not found in registry; make sure to apply SharedLibCompilerOp before applying SharedLibEvalOp."); } std::string lLibName= castHandleT<String>(ioContext.getSystem().getRegister()["icu.compiler.lib-path"])->getWrappedValue(); this->mSharedLibHandle= dlopen((const char*)lLibName.c_str(), RTLD_LAZY); if (!this->mSharedLibHandle) { throw Beagle_RunTimeExceptionM("Cannot open shared library "+ lLibName+ ": "+ dlerror()+ "."); } dlerror(); // Draw a sample from the data set to construct the training set. this->mTimer.reset(); // Get a handle on D, S, and L. DataSetBinaryClassification::Handle lDataSet= castHandleT<DataSetBinaryClassification>(ioContext.getSystem().getComponent("DataSet")); std::vector<unsigned int>* lIndexesPositives= lDataSet->getIndexesPositives(); std::vector<unsigned int>* lIndexesNegatives= lDataSet->getIndexesNegatives(); int lNrSamplesPositive= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.trainingset.size-pos"])->getWrappedValue(); int lNrSamplesNegative= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.trainingset.size-neg"])->getWrappedValue(); // Shuffle both negative and positive indexes. std::random_shuffle(lIndexesPositives->begin(), lIndexesPositives->end(), ioContext.getSystem().getRandomizer()); std::random_shuffle(lIndexesNegatives->begin(), lIndexesNegatives->end(), ioContext.getSystem().getRandomizer()); // Nr of columns in each row in the dataset. int lNrColumns= castHandleT<Int>(ioContext.getSystem().getRegister()["icu.dataset.columns"])->getWrappedValue(); double lTimeInit= this->mTimer.getValue(); this->mTimer.reset(); // Evaluate sampled test cases unsigned int lTruePositives = 0; unsigned int lTrueNegatives = 0; unsigned int lFalsePositives= 0; unsigned int lFalseNegatives= 0; int (*apply_individual)(float[])= 0; float lValues[lNrColumns]; std::vector<unsigned int>::iterator lLastIndex= lIndexesPositives->begin()+ lNrSamplesPositive; // Positives. for(std::vector<unsigned int>::const_iterator lIndex=lIndexesPositives->begin(); lIndex!=lLastIndex; ++lIndex) { const Beagle::Vector& lData = (*lDataSet)[*lIndex].second; std::ostringstream lFunctionName; lFunctionName << "apply_individual_"; lFunctionName << ioContext.getGeneration() << "_" << ioContext.getDemeIndex() << "_" << ioContext.getIndividualIndex(); apply_individual= (int(*)(float*))dlsym(this->mSharedLibHandle, lFunctionName.str().c_str()); char* lError= 0; if ((lError = dlerror()) != NULL) { throw Beagle_RunTimeExceptionM("Error loading function "+ lFunctionName.str()+ ": "+ lError+ "."); } for(unsigned int j=0; j<lData.size(); ++j) { lValues[j]= Float(lData[j]); } bool lResult= apply_individual(lValues); (lResult == 1) ? lTruePositives++ : lFalseNegatives++; } // Negatives. lLastIndex= lIndexesNegatives->begin()+ lNrSamplesNegative; for(std::vector<unsigned int>::const_iterator lIndex=lIndexesNegatives->begin(); lIndex!=lLastIndex; ++lIndex) { const Beagle::Vector& lData = (*lDataSet)[*lIndex].second; std::ostringstream lFunctionName; lFunctionName << "apply_individual_"; lFunctionName << ioContext.getGeneration() << "_" << ioContext.getDemeIndex() << "_" << ioContext.getIndividualIndex(); apply_individual= (int(*)(float*))dlsym(this->mSharedLibHandle, lFunctionName.str().c_str()); char* lError= 0; if ((lError = dlerror()) != NULL) { throw Beagle_RunTimeExceptionM("Error loading function "+ lFunctionName.str()+ ": "+ lError+ "."); } for(unsigned int j=0; j<lData.size(); ++j) { lValues[j]= Float(lData[j]); } bool lResult= apply_individual(lValues); (lResult == 0) ? lTrueNegatives++ : lFalsePositives++; } double lTimeEvaluate= this->mTimer.getValue(); { using namespace std; ostringstream lOSS; lOSS << "g" << ioContext.getGeneration(); lOSS << " d" << ioContext.getDemeIndex(); lOSS << " i" << ioContext.getIndividualIndex() << ", "; lOSS << "TP|FP|FN|TN = "; lOSS.width(7); lOSS << right << lTruePositives << "|"; lOSS.width(7); lOSS << right << lFalsePositives << "|"; lOSS.width(7); lOSS << right << lFalseNegatives << "|"; lOSS.width(7); lOSS << right << lTrueNegatives; Beagle_LogDetailedM(ioContext.getSystem().getLogger(), "evaluate", "Beagle::GP::SharedLibEvalOp", lOSS.str()); } GP::FitnessMCC* fitness= new GP::FitnessMCC(lTruePositives, lFalsePositives, lTrueNegatives, lFalseNegatives); return fitness; Beagle_StackTraceEndM("SharedLibEvalOp::evaluate(GP::Individual& inIndividual, GP::Context& ioContext)"); }