ECF 1.5
Classifier.cpp
1#include "../ECF_base.h"
2#include "../FitnessMax.h"
3#include "../ECF_macro.h"
4
5#include "Classifier.h"
6#include "time.h"
7
8//Class that represents single classifier in XCS system
9//This implementation is designed for BitString::BitString genotypes for
10//rule, input and action definition
11//By extending it, other genotypes could also be used.
12//All used genotypes need to have the same type as corresponding in configuration file.
13
14Classifier::Classifier(XCSParamsP xcsParams, unsigned long long int time, IndividualP ind, StateP state){
15
16 this->xcsParams = xcsParams;
17 params = boost::dynamic_pointer_cast<ClassifierParams> (ind->getGenotype(3));
18
19 this->ind = ind;
20 this->ind->fitness = static_cast<FitnessP> (new FitnessMax);
21 setFitness(xcsParams->initF_);
22
23 setTimeStamp(time);
24
25 BitStringP dontCareBits = getDontCareBitString();
26 for (uint i = 0; i < dontCareBits->bits.size(); ++i){
27 double rnd = state->getRandomizer()->getRandomDouble();
28 if (rnd < xcsParams->pdc_)
29 dontCareBits->bits[i] = true;
30 else
31 dontCareBits->bits[i] = false;
32 }
33 valid = true;
34}
35
36Classifier::Classifier(ClassifierP cl){
37
38 xcsParams = cl->xcsParams;
39 ind = static_cast<IndividualP> (cl->ind->copy());
40 params = boost::dynamic_pointer_cast<ClassifierParams> (ind->getGenotype(3));
41 valid = true;
42}
43
44//Checks if current state configuration is acceptable by Classifier
45bool Classifier::checkState(const StateP state) {
46
47 // minimum 3 genotypes required
48 if(state->getGenotypes().size() < 3) {
49 ECF_LOG_ERROR(state, "Error: XCS algorithm requires min. 3 genotypes!");
50 return false;
51 }
52
53 BitStringP bitstring = static_cast<BitStringP> (new BitString::BitString);
54
55 if(state->getGenotypes()[0]->getName() != bitstring->getName()
56 || state->getGenotypes()[1]->getName() != bitstring->getName()) {
57 ECF_LOG_ERROR(state, "Error: XCS algorithm accepts only BitString::BitString genotype as input!");
58 return false;
59 }
60
61 return true;
62}
63
64//Checks if classifier matches input value
65bool Classifier::doesMatch(const GenotypeP inp) {
66
67 BitStringP input = boost::static_pointer_cast<BitString::BitString> (inp);
68
69 BitStringP ruleBits = boost::static_pointer_cast<BitString::BitString> (ind->getGenotype(0));
70 BitStringP dontCareBits = boost::static_pointer_cast<BitString::BitString> (ind->getGenotype(1));
71
72 for (uint i = 0; i < input->bits.size(); i++){
73 if (dontCareBits->bits[i] ) continue;
74 if (ruleBits->bits[i] != input->bits[i]) return false;
75 }
76 return true;
77}
78//Fits classifier rule to match the input value
79void Classifier::cover (std::set<int> actions, const GenotypeP input, StateP state){
80 ind->at(0) = static_cast<GenotypeP> (input->copy());
81 BitStringP action = boost::dynamic_pointer_cast<BitString::BitString> (getAction());
82
83 do {
84 action->initialize(state);
85 } while (actions.find(getActionId()) != actions.end());
86
87}
88
89//Prints classifier data on screen
90void Classifier::print(){
91
92 std::cout << " [" << ind->index << "] ";
93 printRuleString (getRuleBitString(),getDontCareBitString());
94 std::cout << " : ";
95
96 printBitString (boost::dynamic_pointer_cast<BitString::BitString> (getAction()) );
97
98 std::cout << " ("<< getError() << ", " << getPrediction() <<", "<< getFitness() << ")";
99 std::cout << "\t[ " << getNumerosity() << ", " << getActSetSize() << ", " << getExperience() << ", " << getTimeStamp() << " ]";
100 std::cout << std::endl;
101}
102
103void Classifier::printRuleString (const BitStringP bString, const BitStringP hashString) {
104 char sign;
105
106 for (uint i = 0; i < bString->bits.size(); i++){
107 if (hashString != NULL && hashString->bits[i]) sign = '#';
108 else sign = bString->bits[i] ? '1':'0';
109 std::cout << sign;
110
111 }
112}
113
114void Classifier::printBitString (const BitStringP bString) {
115
116 for (uint i = 0; i < bString->bits.size(); i++){
117 std::cout << bString->bits[i] ? '1':'0';
118 }
119
120}
121
122//Each action has id that is used for creating PA
123//Since action is Genotype XCS can't make a difference
124//beetwean two abstract classes
125int Classifier::getActionId(){
126
127 int ret = 0;
128 BitStringP bstring = boost::dynamic_pointer_cast<BitString::BitString> (ind->getGenotype(2));
129 /* Promjenjeno zbog mux problema
130 if (bstring->bits[0]) ret += 1;
131 if (bstring->bits[1]) ret += 10;
132 if (bstring->bits[2]) ret += 100;
133 */
134
135 int add = 1;
136 for (uint i =0; i < bstring->bits.size(); ++i){
137 if (bstring->bits[i]) ret += add;
138 add *= 10;
139 }
140
141 return ret;
142}
143
144GenotypeP Classifier::getAction(){
145 return ind->getGenotype(2);
146}
147void Classifier::setAction(GenotypeP action){
148 ind->at(2) = static_cast<GenotypeP> (action->copy());
149}
150
151
152#pragma region Parameters setters
153
154void Classifier::setError(double eps){
155 params->eps_ = eps;
156}
157
158void Classifier::setPrediction(double p){
159 params->p_ = p;
160}
161
162void Classifier::setFitness(double F){
163 ind->fitness->setValue(F);
164}
165
166void Classifier::setTimeStamp(unsigned long long int ts) {
167 params->ts_ = ts;
168}
169
170void Classifier::setNumerosity(int num) {
171 params->num_ = num;
172}
173
174void Classifier::setActSetSize(double as) {
175 params->as_ = as;
176}
177
178void Classifier::setExperience(double exp) {
179 params->exp_ = exp;
180}
181
182#pragma endregion
183
184#pragma region Parameters getters
185
186double Classifier::getError(){
187 return params->eps_;
188}
189
190double Classifier::getPrediction(){
191 return params->p_;
192}
193
194double Classifier::getFitness(){
195 return ind->fitness->getValue();
196}
197
198unsigned long long int Classifier::getTimeStamp() {
199 return params->ts_;
200}
201
202int Classifier::getNumerosity(){
203 return params->num_;
204}
205
206double Classifier::getActSetSize(){
207 return params->as_;
208}
209
210double Classifier::getExperience(){
211 return params->exp_;
212}
213
214#pragma endregion
215
216double Classifier::getDeletionVote(double avFit){
217 double vote = getActSetSize() * getNumerosity();
218 if (getExperience() > xcsParams->thresholdDel_ &&
219 getFitness() / getNumerosity() < xcsParams->delta_ * avFit){
220 vote = vote * avFit / (getFitness() / getNumerosity());
221 }
222 return vote;
223}
224bool Classifier::couldSubsume(){
225 double exp = getExperience();
226 double eps = getError();
227 if (exp > xcsParams->thresholdSub_ && eps < xcsParams->eps0_){
228 return true;
229 }
230 return false;
231}
232
233int Classifier::numOfDCBits(){
234 int num = 0;
235 BitStringP dcbstring = getDontCareBitString();
236 for (uint i = 0; i < dcbstring->bits.size(); ++i){
237 if (dcbstring->bits[i]) ++num;
238 }
239 return num;
240}
241bool Classifier::isMoreGeneral(ClassifierP cl){
242 if (numOfDCBits() <= cl->numOfDCBits()) return false;
243
244 BitStringP dcGen = getDontCareBitString();
245 BitStringP ruleGen = getRuleBitString();
246 BitStringP ruleSpec = cl->getRuleBitString();
247 int bitsSize = (int) ruleGen->bits.size();
248
249 int i = 0;
250 do {
251 if (!dcGen->bits[i] && ruleGen->bits[i] != ruleSpec->bits[i])
252 return false;
253 ++i;
254 } while(i < bitsSize);
255
256 return true;
257}
258
259bool Classifier::doesSubsume(ClassifierP cl){
260
261 if (cl->getActionId() == getActionId()){
262 if (couldSubsume()){
263 if (isMoreGeneral(cl)){
264 return true;
265 }
266 }
267 }
268 return false;
269}
270
271
272BitStringP Classifier::getRuleBitString(){
273 return boost::dynamic_pointer_cast<BitString::BitString> (ind->getGenotype(0));
274}
275
276BitStringP Classifier::getDontCareBitString(){
277 return boost::dynamic_pointer_cast<BitString::BitString> (ind->getGenotype(1));
278}
279
280void Classifier::mutateRule(GenotypeP genInput, StateP state) {
281
282 double rnd = state->getRandomizer()->getRandomDouble();
283 BitStringP input = boost::dynamic_pointer_cast<BitString::BitString> (genInput);
284
285 for (uint i= 0; i < input->bits.size(); i++){
286 if (rnd < xcsParams->pMutation_){
287 BitStringP ruleBits = getRuleBitString();
288 BitStringP dontCareBits = getDontCareBitString();
289
290 if (dontCareBits->bits[i] == true){
291 dontCareBits->bits[i] = false;
292 ruleBits->bits[i] = input->bits[i];
293 } else
294 dontCareBits->bits[i] = true;
295 }
296 }
297}
298
299void Classifier::mutateAction(StateP state) {
300 double rnd = state->getRandomizer()->getRandomDouble();
301 if (rnd < xcsParams->pMutation_){
302 BitStringP actionBits = boost::dynamic_pointer_cast<BitString::BitString> (getAction());
303 actionBits->initialize(state);
304 }
305}
BitString class - implements genotype as a series of bits.
Definition: BitString.h:24
Fitness for maximization problems.
Definition: FitnessMax.h:13