From 2366b2195313a633eb5173f5f48216d56239204e Mon Sep 17 00:00:00 2001
From: Mathis Brede <mbrede@mail.uni-paderborn.de>
Date: Thu, 13 Apr 2023 10:23:30 +0200
Subject: [PATCH] bug fixes

---
 xcs/ClassifierSet.cc  |  52 ++++++++---------
 xcs/Headers/config.hh |  14 +++--
 xcs/main.cc           | 131 ++++++++++++++++--------------------------
 3 files changed, 81 insertions(+), 116 deletions(-)

diff --git a/xcs/ClassifierSet.cc b/xcs/ClassifierSet.cc
index d437cf1..9e2231d 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 1f7d4a8..16925d3 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 8368247..e10d4f6 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
+}
+
-- 
GitLab