diff --git a/xcs/ClassifierSet.cc b/xcs/ClassifierSet.cc index d437cf16aaa0e2c45e04f488d1a06ccc2ca2c2d9..9e2231d807c3da01f3503c827b92f5a2d14b8967 100644 --- a/xcs/ClassifierSet.cc +++ b/xcs/ClassifierSet.cc @@ -103,8 +103,7 @@ void ClassifierSet::createPredictionArray() { this->fitnessSumArray.clear(); for (unsigned int i = 0; i < this->parameter.possibleActionsPtr->size(); i++) { - this->predictionArray.push_back( - std::numeric_limits<double>::quiet_NaN()); + this->predictionArray.push_back(-std::numeric_limits<float>::infinity()); this->fitnessSumArray.push_back(0); } @@ -117,7 +116,7 @@ void ClassifierSet::createPredictionArray() { j++) { if (this->matchSet[i]->getAction() == this->parameter.possibleActionsPtr->at(j)) { - if (std::isnan(this->predictionArray[j])) { + if (this->predictionArray[j] == -std::numeric_limits<float>::infinity()) { this->predictionArray[j] = this->matchSet[i]->getPrediction() * this->matchSet[i]->getFitness(); @@ -174,7 +173,7 @@ returnAction ClassifierSet::selectAction() { // Do pure exploration here double randomNumber = this->RandomNumberGenerator->getRandom(); int ActionPosition = static_cast<int>( - std::round(randomNumber * (this->differentActions.size() - 1))); + std::round(randomNumber * (this->differentActions.size() - 0.5))); return returnAction{this->differentActions[ActionPosition], 0}; } else { // Do pure exploitation here @@ -206,7 +205,7 @@ returnAction ClassifierSet::selectAction() { // get random action from the actions with highest prediction value double randomNumber = this->RandomNumberGenerator->getRandom(); int ActionPosition = static_cast<int>( - std::round(randomNumber * (bestActions.size() - 1))); + std::round(randomNumber * (bestActions.size() - 0.5))); return returnAction{bestActions[ActionPosition], 1}; } } @@ -695,49 +694,48 @@ void ClassifierSet::actionSetSubsumption() { for (unsigned int i = 0; i < this->actionSet.size(); i++) { if (this->actionSet[i]->couldSubsume(this->parameter.thetaSub, this->parameter.e0)) { - if ((clPtr->getCondition() == "\0")) { - int numberDoNotCares = 0; - int numberDoNotCaresClPtr = 0; - for (unsigned int j = 0; j < clPtr->getCondition().size(); - j++) { - if (this->actionSet[i]->getCondition()[j] == '#') { - numberDoNotCares++; - } - if (clPtr->getCondition()[j] == '#') { - numberDoNotCaresClPtr++; - } - } - if (numberDoNotCares > numberDoNotCaresClPtr || - ((numberDoNotCares == numberDoNotCaresClPtr) && - (this->RandomNumberGenerator->getRandom() < 0.5))) { + if (clPtr->getCondition().size() == 0 or this->actionSet[i]->isMoreGeneralThan(clPtr)) { clPtr = this->actionSet[i]; - delete (deletePtr); - this->numberofDeletion++; + } } } - } - if (clPtr->getCondition() != "\0") { + if (clPtr->getCondition().size() != 0) { + // the new,empty Classifier can be deleted since we found a Classifier as candidat + // to subsume other Classifier in the actionSet + delete (deletePtr); + this->numberofDeletion++; + this->numberofActionSetSubsumption++; for (unsigned int i = 0; i < this->actionSet.size(); i++) { + //find a Classifier, which can be subsumed if (clPtr->isMoreGeneralThan(this->actionSet[i])) { + clPtr->setNumerosity(clPtr->getNumerosity() + this->actionSet[i]->getNumerosity()); + + //delete the less generelized Classifier from populationSet for (unsigned int j = 0; j < this->populationSet.size(); j++) { if (this->actionSet[i] == this->populationSet[j]) { this->numberofDeletion++; - this->populationSet.erase(this->populationSet.begin() + j); + break; + } + } + for (unsigned int j = 0; j < this->matchSet.size(); j++) { + if (this->actionSet[i] == this->matchSet[j]) { + this->numberofDeletion++; + this->matchSet.erase(this->matchSet.begin() + j); + break; } } delete (this->actionSet[i]); this->actionSet.erase(this->actionSet.begin() + i); - return; } } } else { - delete (clPtr); + delete (deletePtr); } } diff --git a/xcs/Headers/config.hh b/xcs/Headers/config.hh index 1f7d4a8c96023c527e760f9cc39065c6492bc4bb..16925d37896b6099253a34af6da132c09cb3148d 100644 --- a/xcs/Headers/config.hh +++ b/xcs/Headers/config.hh @@ -1,9 +1,11 @@ #if !defined(MYLIB_CONFIG_H) #define MYLIB_CONFIG_H 1 -constexpr unsigned CYCLE = 155; + // Inputsize must be defined as a constant in case binary conditions should be used -constexpr unsigned INPUTSIZE = 16; +constexpr unsigned INPUTSIZE = 6; + +constexpr unsigned CYCLE = 2174; /// @brief struct for all user configurable parameters; possibleActions_ptr must set; all default values from scikit-XCS /// @param possibleActions_ptr Pointer to vector for all possible actions given by the user @@ -31,7 +33,7 @@ constexpr unsigned INPUTSIZE = 16; /// @param discountFactorPA Float for discount the largest prediction of the current PredictionArray in multi-step problems struct XCSParameter{ std::vector<std::string>* possibleActionsPtr; - unsigned int N = 400; + unsigned int N = 1000; float pGeneral = 0.5; float beta = 0.2; float alpha = 0.1; @@ -46,14 +48,14 @@ struct XCSParameter{ float initError = 0; float initFitness = 0.01; float pExplore = 0.5; - int thetaMatching = 8; + int thetaMatching = 2; bool doGASubsumption = true; bool doActionSetSubsumption = false; int thetaSub = 20 ; unsigned int seed = 20; bool GAInExploitation = false; - float discountFactorPA = 0.71; - bool doSpecify = true; + float discountFactorPA = 0.7; + bool doSpecify = false; int n_sp = 20; float p_sp = 0.5; }; diff --git a/xcs/main.cc b/xcs/main.cc index 83682479b70f9af0982f9649c72494d18a001895..e10d4f673e856b0a7520069dfe182bafa649d2f3 100644 --- a/xcs/main.cc +++ b/xcs/main.cc @@ -13,7 +13,7 @@ #include "Headers/XCS.hh" //include the Environment -#include "Environments/Woods1.hh" +#include "Environments/Multiplexer.hh" //include for RandomGenerator #include "Headers/Random.hh" @@ -22,9 +22,9 @@ using namespace std; int main(int argc, char* argv[]) { + cout << "XCS START!\n"; //learning measurement - MovingAvgTracker env; std::ofstream popSetFile; std::ofstream performanceFile; bool popset_in_csv = false; @@ -37,12 +37,10 @@ int main(int argc, char* argv[]) //init for XCS parameter and action XCSParameter parameter; - //init variables for action and condition returnAction b; std::string condition; - //init RandomNumberGenerator unsigned seed=13; Random* RandomNumberGeneratorPtr = new Random(seed); @@ -54,7 +52,6 @@ int main(int argc, char* argv[]) { "popsetFile", required_argument, 0, 'p'}, { "performanceFile", required_argument, 0, 'f'}, { "timeFile", required_argument, 0, 't'}, - { "popsetSize", required_argument, 0, 'n'}, 0 }; while(1){ @@ -79,7 +76,7 @@ int main(int argc, char* argv[]) //cout << dir_path+"/../"+optarg+".csv" << endl; performanceFile.open(dir_path+"/../"+optarg+".csv",ios::out); performance_in_csv = true; - performanceFile << "Iteration, Exploitation, Steps, Last120IterationsAverage, PopulationSetSize, XCSCalls_per_Iteration" << endl; + performanceFile << "Iteration, Reward, Last200IterationsAverage, PopulationSetSize" << endl; break; } case 'p': @@ -91,18 +88,11 @@ int main(int argc, char* argv[]) break; } case 't': - { std::string file_path = __FILE__; std::string dir_path = file_path.substr(0, file_path.rfind("/")); timeFile.open(dir_path+"/../"+optarg+".csv",ios::out | std::ofstream::app); time_measurement = true; break; - } - case 'n': - { - parameter.N = std::stoi(optarg); - break; - } } } @@ -112,79 +102,54 @@ int main(int argc, char* argv[]) //wall time auto wcts = std::chrono::system_clock::now(); - //init of possible Actions for multistep problem - parameter.possibleActionsPtr = new std::vector<std::string>{"0","1","2","3","4","5","6","7"}; - - //init of multistep test environment - std::string file_path = __FILE__; - std::string dir_path = file_path.substr(0, file_path.rfind("/")); - Woods1 testEnv = Woods1(dir_path+"/Environments/Woods1_test.txt",RandomNumberGeneratorPtr); - - //init reward variable - RewardWoods1 reward{0,0}; + //init possible Actions for single step problems + parameter.possibleActionsPtr = new std::vector<std::string>{"0","1"}; - XCS xcs = XCS(parameter); - - //informationparameter init - - // if the ringBuffer parameters are changed, please init this specific ringBuffer - // into the RingBuffer.cc file (some are given at the end of the file) - ringBuffer<unsigned int, 120> stepTracker; - unsigned steps=0; - unsigned int iterations = 0; + //init of single step test environment + Multiplexer testEnv = Multiplexer(2,RandomNumberGeneratorPtr); - unsigned int number_xcs_calls_per_iteration = 0; - - try{ - while(iterations<CYCLE){ - steps = 0; - number_xcs_calls_per_iteration=0; - // if(iterations % (CYCLE/10) == 0){ - // std::cout << iterations << " full iterations were made. These are " << (static_cast<float>(iterations)/CYCLE)*100 << "%" << std::endl; - // fflush(stdout); + XCS xcs = XCS(parameter); + ringBuffer<unsigned int, 200> tracker; + unsigned i = 0; + try{ + while(i < CYCLE){ + // if(i % (CYCLE/10) == 0){ + // std::cout << i << " full iterations were made. These are " << (static_cast<float>(i)/CYCLE)*100 << "%" << std::endl; + // fflush(stdout); // } - - condition = testEnv.getCondition(); - b = xcs.generateAction(condition); - number_xcs_calls_per_iteration++; - reward = testEnv.walk(std::stoi(b.action)); - steps++; - xcs.provideReward(reward.eop, reward.reward); - while(!reward.eop){ - condition = testEnv.getCondition(); - b = xcs.generateAction(condition); - number_xcs_calls_per_iteration++; - reward = testEnv.walk(std::stoi(b.action)); - steps++; - if(steps >= 30 && !reward.eop){ - xcs.stopMultiStepRun(); - reward = {0,1}; - testEnv.resetMap(); - } - else{ - xcs.provideReward(reward.eop, reward.reward); - } - } - testEnv.resetMap(); - if(b.isExploitation){ - stepTracker.add(steps); - } - if(performance_in_csv){ - performanceFile << iterations << "," << b.isExploitation << "," << steps << "," << stepTracker.average() << "," << xcs.getPopulationSetSize() << "," << number_xcs_calls_per_iteration << std::endl; - } - iterations++; + condition = testEnv.getCondition(); + b = xcs.generateAction(condition); + if(b.action == testEnv.getAction()){ + xcs.provideReward(1,1000); + if(b.isExploitation){ + i++; + if(performance_in_csv){ + tracker.add(1000); + performanceFile << i << "," << "1000" << "," << tracker.average() << "," << xcs.getPopulationSetSize() << endl; + } + } + }else{ + xcs.provideReward(1,0); + if(b.isExploitation){ + i++; + if(performance_in_csv){ + tracker.add(0); + performanceFile << i << "," << "0" << "," << tracker.average() << "," << xcs.getPopulationSetSize() << endl; + } + } + } + } + if(time_measurement){ + double cpu_duration = (std::clock() - startcputime) / (double)CLOCKS_PER_SEC; + std::chrono::duration<double> wctduration = (std::chrono::system_clock::now() - wcts); + timeFile << seed << "," << cpu_duration << "," << wctduration.count() << endl; } - }catch(std::exception& e){ - std::cout << e.what() << " happens at iteration: " << iterations << endl; + if(popset_in_csv){ + xcs.printPopulationToFile(popSetFile); + } + }catch(std::exception& e){ + std::cout << e.what() << " happens at iteration: " << i << endl; return EXIT_FAILURE; } - if(time_measurement){ - double cpu_duration = (std::clock() - startcputime) / (double)CLOCKS_PER_SEC; - std::chrono::duration<double> wctduration = (std::chrono::system_clock::now() - wcts); - timeFile << seed << "," << cpu_duration << "," << wctduration.count() << "," << endl; - } - if(popset_in_csv){ - xcs.printPopulationToFile(popSetFile); - } - return 0; -} \ No newline at end of file +} +