# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

classifier.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "nel/ai/nimat/classifier.h"
00027 #include "nel/misc/debug.h"
00028 
00029 namespace NLAINIMAT
00030 {
00031 
00033 // CClassifierSystem
00035 
00036 CClassifierSystem::CClassifierSystem()
00037 {
00038 }
00039 
00040 CClassifierSystem::~CClassifierSystem()
00041 {
00042         std::list<CClassifier*>::iterator itClassifiers = _classifiers.begin();
00043         while (itClassifiers != _classifiers.end())
00044         {
00045                 delete (*itClassifiers);
00046                 itClassifiers++;
00047         }
00048 }
00049 
00050 void CClassifierSystem::addClassifier(const TSensorMap &conditionsMap, sint16 priority, const char* behavior)
00051 {
00052         // We build a new classifier.
00053         CClassifier* classifier = new CClassifier();
00054         classifier->Behavior = behavior;
00055         classifier->Priority = priority;
00056 
00057         CClassifierConditionCell* condCell;
00058         std::map<std::string, char>::const_iterator itCondition;
00059         for (itCondition = conditionsMap.begin(); itCondition != conditionsMap.end(); itCondition++)
00060         {
00061                 // We add the new sensor in the sensor map and init it with a joker value '#'
00062                 _sensors[(*itCondition).first] = '#';
00063 
00064                 // A new condition cell is added to the classifier condition.
00065                 condCell = new CClassifierConditionCell(_sensors.find((*itCondition).first), (*itCondition).second);
00066                 classifier->Condition.push_back(condCell);
00067         }
00068 
00069         // The new classifier is added to the classifier list.
00070         _classifiers.push_back(classifier);
00071 }
00072 
00074 void CClassifierSystem::addClassifierSystem(const CClassifierSystem &cs)
00075 {
00076         std::list<CClassifier*>::const_iterator itCSClassifiers;
00077         for (itCSClassifiers = cs._classifiers.begin(); itCSClassifiers != cs._classifiers.end(); itCSClassifiers++)
00078         {
00079                 TSensorMap conditionsMap;
00080 
00081                 std::list<CClassifierConditionCell*>::const_iterator itCondCell;
00082                 for (itCondCell = (*itCSClassifiers)->Condition.begin(); itCondCell !=(*itCSClassifiers)->Condition.end(); itCondCell++)
00083                 {
00084                         CClassifierConditionCell* pCondCell = (*itCondCell);
00085                         conditionsMap[pCondCell->getSensorName()] = pCondCell->getValue();
00086                 }
00087                 addClassifier(conditionsMap, (*itCSClassifiers)->Priority, (*itCSClassifiers)->Behavior.c_str());
00088         }
00089 }
00090 
00091 std::string CClassifierSystem::selectBehavior( const TSensorMap &sensorMap)
00092 {
00093         // We update the internal sensor values.
00094         std::map<std::string, char>::const_iterator itConditionsmap;
00095         for (itConditionsmap = sensorMap.begin(); itConditionsmap != sensorMap.end(); itConditionsmap++)
00096         {
00097                 char c =  (*itConditionsmap).second;
00098                 std::string sensName = (*itConditionsmap).first;
00099                 _sensors[sensName ] = c;
00100                 int size = _sensors.size();
00101         }
00102 
00103         // We select the activables classifiers
00104         std::list<CClassifier*> activableList;
00105         std::list<CClassifier*>::iterator itClassifiers = _classifiers.begin();
00106         std::list<CClassifierConditionCell*>::iterator itConditions;
00107         bool activable;
00108         int totalPriority = 0;
00109 
00110         while (itClassifiers != _classifiers.end())
00111         {
00112                 activable = true;
00113                 itConditions = (*itClassifiers)->Condition.begin();
00114                 while (itConditions != (*itClassifiers)->Condition.end())
00115                 {
00116                         if (! (*itConditions)->isActivable() )
00117                         {
00118                                 activable = false;
00119                                 break;
00120                         }
00121                         itConditions++;
00122                 }
00123                 if (activable)
00124                 {
00125                         activableList.push_back(*itClassifiers);
00126                         totalPriority += (*itClassifiers)->Priority;
00127                 }
00128                 itClassifiers++;
00129         }
00130 
00131         // We set the sensors back to the default value.
00132         for (itConditionsmap = sensorMap.begin(); itConditionsmap != sensorMap.end(); itConditionsmap++)
00133         {
00134                 char c =  (*itConditionsmap).second;
00135                 std::string sensName = (*itConditionsmap).first;
00136                 _sensors[sensName ] = '#';
00137                 int size = _sensors.size();
00138         }
00139 
00140         // We select a classifier in the active classifier with a roullette wheel random.
00141         int r = rand() * totalPriority;
00142         r /= RAND_MAX;
00143         itClassifiers = activableList.begin();
00144         while (itClassifiers != activableList.end())
00145         {
00146                 r -= (*itClassifiers)->Priority;
00147                 if (r<=0)
00148                 {
00149                         return (*itClassifiers)->Behavior;
00150                 }
00151                 itClassifiers++;
00152         }
00153 
00154         // If no classifier is activable, we send a default joker value '#'
00155         return "#";
00156 }
00157 
00158 void CClassifierSystem::getDebugString(std::string &t) const
00159 {
00160         std::string dbg = "\n";
00161 
00162         std::list<CClassifier*>::const_iterator itClassifiers;
00163         for (itClassifiers = _classifiers.begin(); itClassifiers != _classifiers.end(); itClassifiers++)
00164         {
00165                 std::list<CClassifierConditionCell*>::const_iterator itConditions;
00166                 for (itConditions = (*itClassifiers)->Condition.begin(); itConditions != (*itClassifiers)->Condition.end(); itConditions++)
00167                 {
00168                         CClassifierConditionCell* condCell = (*itConditions);
00169                         dbg += " (" + condCell->getSensorName() + "=" + condCell->getValue() + ") +";
00170                 }
00171                 std::string actionName = (*itClassifiers)->Behavior;
00172                 sint16          prio = (*itClassifiers)->Priority;
00173                 dbg += "> " + actionName + " [" + NLMISC::toString(prio) + "]\n";
00174         }
00175         t += dbg;
00176 }
00177 
00179 // CClassifier
00181 
00182 CClassifierSystem::CClassifier::CClassifier()
00183 {
00184 }
00185 
00186 CClassifierSystem::CClassifier::~CClassifier()
00187 {
00188         std::list<CClassifierConditionCell*>::iterator itConditions = Condition.begin();
00189         while (itConditions != Condition.end())
00190         {
00191                 delete (*itConditions );
00192                 itConditions++;
00193         }
00194 }
00195 
00197 // CClassifierConditionCell
00199 
00200 CClassifierSystem::CClassifierConditionCell::CClassifierConditionCell(TSensorMap::const_iterator itSensor, char value)
00201 {
00202         _itSensor = itSensor;
00203         _value = value;
00204 }
00205 
00206 bool CClassifierSystem::CClassifierConditionCell::isActivable() const
00207 {
00208         if ((*_itSensor).second == _value)
00209                 return true;
00210         else
00211                 return false;
00212 }
00213 
00214 std::string CClassifierSystem::CClassifierConditionCell::getSensorName() const
00215 {
00216         return (*_itSensor).first;
00217 }
00218 
00219 char CClassifierSystem::CClassifierConditionCell::getValue()
00220 {
00221         return _value;
00222 }
00223 
00225 // CActionCS
00227 CActionCS::CActionCS(std::string name)
00228 {
00229         _Name = name;
00230 }
00231 
00232 CActionCS::~CActionCS()
00233 {
00234 }
00235 
00237 std::string CActionCS::getName() const
00238 {
00239         return _Name;
00240 }
00241 
00243 void CActionCS::addMotivationRule (std::string motivationName, const TSensorMap &conditionsMap, sint16 priority)
00244 {
00245         CClassifierSystem* pCS;
00246 
00247         pCS = &(_ClassifiersByMotivation[motivationName]);
00248         pCS->addClassifier(conditionsMap, priority, _Name.c_str());
00249 }
00250 
00251 const std::map<std::string, CClassifierSystem> *CActionCS::getClassifiersMap () const
00252 {
00253         return &_ClassifiersByMotivation;
00254 }
00255 
00256 
00258 void CActionCS::getDebugString(std::string &t) const
00259 {
00260         std::string ret = "\nACTION :\t" + _Name + "\n";
00261         std::map<std::string, CClassifierSystem>::const_iterator ItClassifiersByMotivation;
00262         for (ItClassifiersByMotivation = _ClassifiersByMotivation.begin(); ItClassifiersByMotivation != _ClassifiersByMotivation.end(); ItClassifiersByMotivation++)
00263         {
00264                 ret += "\nMotivation : " + (*ItClassifiersByMotivation).first + "\n";
00265                 (*ItClassifiersByMotivation).second.getDebugString(ret);
00266         }
00267         t+=ret;
00268 }
00269 
00270 
00272 // CMotivationEnergy
00274 CMotivationEnergy::CMotivationEnergy()
00275 {
00276         _SumValue = 0;
00277 }
00278 
00279 CMotivationEnergy::~CMotivationEnergy()
00280 {
00281 }
00282 
00283 sint16 CMotivationEnergy::getSumValue() const
00284 {
00285         return _SumValue;
00286 }
00287 
00288 void    CMotivationEnergy::removeProvider(std::string providerName)
00289 {
00290         _MotivationProviders.erase(providerName);
00291         computeMotivationValue();
00292 }
00293 
00294 void    CMotivationEnergy::addProvider(std::string providerName, const CMotivationEnergy& providerMotivation)
00295 {
00296         _MotivationProviders[providerName] = providerMotivation._EnergyByMotivation ;
00297         computeMotivationValue();
00298 }
00299 
00300 void    CMotivationEnergy::computeMotivationValue()
00301 {
00302         _EnergyByMotivation.clear();
00303         std::map<std::string, TEnergyByMotivation>::iterator itMotivationProviders;
00304 
00305         for (itMotivationProviders = _MotivationProviders.begin(); itMotivationProviders != _MotivationProviders.end(); itMotivationProviders++)
00306         {
00307                 TEnergyByMotivation &motivation = (*itMotivationProviders).second;
00308                 TEnergyByMotivation::iterator itMotivation, itMyMotivation;
00309                 for (itMotivation = motivation.begin(); itMotivation != motivation.end(); itMotivation++)
00310                 {
00311                         std::string motivSource = (*itMotivation).first;
00312                         sint16 motiveValue = (*itMotivation).second.Value;
00313                         sint16 motivePP = (*itMotivation).second.PP;
00314                         itMyMotivation = _EnergyByMotivation.find(motivSource);
00315                         if (itMyMotivation != _EnergyByMotivation.end())
00316                         {
00317                                 sint16 myMotiveValue = (*itMyMotivation).second.Value;
00318                                 if (motiveValue > myMotiveValue)
00319                                 {
00320                                         _EnergyByMotivation[motivSource].Value = motiveValue;
00321                                         _EnergyByMotivation[motivSource].PP = motivePP;
00322                                 }
00323                         }
00324                         else
00325                         {
00326                                 _EnergyByMotivation[motivSource].Value = motiveValue;
00327                                 _EnergyByMotivation[motivSource].PP = motivePP;
00328                         }
00329                 }
00330         }
00331 
00332         TEnergyByMotivation::const_iterator itEnergyByMotivation;
00333         sint16 sum = 0;
00334         for (itEnergyByMotivation = _EnergyByMotivation.begin(); itEnergyByMotivation != _EnergyByMotivation.end(); itEnergyByMotivation++)
00335         {
00336                 sum += (*itEnergyByMotivation).second.Value * (*itEnergyByMotivation).second.PP;
00337         }
00338         _SumValue = sum;
00339 }
00340 
00342 void CMotivationEnergy::setMotivationPP(std::string motivationName, sint16 PP)
00343 {
00344         _SumValue -= _EnergyByMotivation[motivationName].Value * _EnergyByMotivation[motivationName].PP;
00345         _SumValue += _EnergyByMotivation[motivationName].Value * PP;
00346         _EnergyByMotivation[motivationName].PP = PP;
00347 }
00348 
00350 void CMotivationEnergy::setMotivationValue(std::string motivationName, sint16 value)
00351 {
00352         _SumValue -= _EnergyByMotivation[motivationName].Value * _EnergyByMotivation[motivationName].PP;
00353         _SumValue += value * _EnergyByMotivation[motivationName].PP;
00354         _EnergyByMotivation[motivationName].Value = value;
00355 }
00356 
00358 void CMotivationEnergy::getDebugString(std::string &t) const
00359 {
00360         std::string ret;
00361         TEnergyByMotivation::const_iterator itEnergyByMotivation;
00362         
00363         for (itEnergyByMotivation = _EnergyByMotivation.begin(); itEnergyByMotivation!= _EnergyByMotivation.end(); itEnergyByMotivation++)
00364         {
00365                 ret += " Motivation source : " + (*itEnergyByMotivation).first + " (" + NLMISC::toString((*itEnergyByMotivation).second.Value * (*itEnergyByMotivation).second.PP) + ")\n";
00366         }
00367         t+=ret;
00368 }
00369 
00371 // CNetCS
00373 
00374 CNetCS::CNetCS()
00375 {
00376 }
00377 
00378 CNetCS::~CNetCS()
00379 {
00380 }
00381 
00382 void CNetCS::addVirtualActionCS(const CActionCS &action)
00383 {
00384         const std::map<std::string, CClassifierSystem> *mapAction = action.getClassifiersMap();
00385         std::map<std::string, CClassifierSystem>::const_iterator ItMapAction;
00386         for (ItMapAction = mapAction->begin(); ItMapAction != mapAction->end(); ItMapAction++)
00387         {
00388                 CClassifierSystem* pCS;
00389                 std::string motivationName = (*ItMapAction).first;
00390                 const CClassifierSystem* pOtherCS = &((*ItMapAction).second);
00391 
00392                 pCS = &(_ClassifiersAndMotivationIntensity[motivationName].CS);
00393                 pCS->addClassifierSystem(*pOtherCS);
00394         }
00395 }
00396 
00397 void CNetCS::addActionCS(const CActionCS& action)
00398 {
00399         addVirtualActionCS(action);
00400         CMotivationEnergy motivalue;
00401         _ActionsExecutionIntensity[action.getName()] = motivalue;
00402 }
00403 
00404 
00406 void CNetCS::getDebugString(std::string &t) const
00407 {
00408         std::string ret = "\n---------------------------";
00409         std::map<std::string, CMotivateCS>::const_iterator itClassifiers;
00410         for (itClassifiers = _ClassifiersAndMotivationIntensity.begin(); itClassifiers!= _ClassifiersAndMotivationIntensity.end(); itClassifiers++)
00411         {
00412                 ret += "\nMotivation : " + (*itClassifiers).first;
00413                 (*itClassifiers).second.CS.getDebugString(ret);
00414                 (*itClassifiers).second.MotivationIntensity.getDebugString(ret);
00415         }
00416         ret += "\nACTIONS :\n";
00417         std::map<std::string, CMotivationEnergy>::const_iterator itActionsExecutionIntensity;
00418         for (itActionsExecutionIntensity = _ActionsExecutionIntensity.begin(); itActionsExecutionIntensity != _ActionsExecutionIntensity.end(); itActionsExecutionIntensity++)
00419         {
00420                 ret += (* itActionsExecutionIntensity).first + " :\n";
00421                 (*itActionsExecutionIntensity).second.getDebugString(ret);
00422         }
00423         t+=ret;
00424 }
00425 
00427 void CNetCS::setMotivationPP(std::string motivationName, sint16 PP)
00428 {
00429         _ClassifiersAndMotivationIntensity[motivationName].MotivationIntensity.setMotivationPP(motivationName, PP);
00430 }
00431 
00433 void CNetCS::setMotivationValue(std::string motivationName, sint16 value)
00434 {
00435         _ClassifiersAndMotivationIntensity[motivationName].MotivationIntensity.setMotivationValue(motivationName, value);
00436 }
00437 
00438 void CNetCS::run()
00439 {
00440         /*
00441         Je sélectionne par roulette weel le classeur que je vais gérer
00442         Je met à jour l'énergie du vainqueur
00443         */
00444         sint16 somme = 0;
00445         typedef std::map<std::string, CMotivateCS>::iterator TitNameAndMotivation;
00446         std::map<sint16, TitNameAndMotivation > mapCSweel;
00447         std::map<std::string, CMotivateCS>::iterator itClassifiers;
00448         // On calcule la somme
00449         for (itClassifiers = _ClassifiersAndMotivationIntensity.begin(); itClassifiers != _ClassifiersAndMotivationIntensity.end(); itClassifiers++)
00450         {
00451                 CMotivateCS* pCMotivateCS = &((*itClassifiers).second);
00452                 sint16 energy = pCMotivateCS->MotivationIntensity.getSumValue();
00453                 if (energy > 0)
00454                 {
00455                         somme += energy;
00456                         mapCSweel[somme] = itClassifiers;
00457                 }
00458         }
00459         if (somme>0)
00460         {
00461                 // on selectionne le classeur;
00462                 sint16 randomeNumber = rand()%(somme);
00463                 std::map<sint16, TitNameAndMotivation>::iterator itMapCSweel = mapCSweel.upper_bound(randomeNumber);
00464                 CMotivateCS* pCSselection = &((*((*itMapCSweel).second)).second);
00465                 std::string selectionName = (*((*itMapCSweel).second)).first;
00466 
00467                 // On fait calculer le CS
00468                 std::string behav = pCSselection->CS.selectBehavior(_SensorsValues);
00469 
00470                 // On récupère le pointeur sur le modul auquel on va transmettre la motivation
00471                 CMotivationEnergy* pEnergy2Evolve;
00472                 CMotivationEnergy& refMyEnergy = pCSselection->MotivationIntensity;
00473                 std::map<std::string, CMotivationEnergy>::iterator itActionsExecutionIntensity;
00474                 itActionsExecutionIntensity = _ActionsExecutionIntensity.find(behav);
00475                 if (itActionsExecutionIntensity != _ActionsExecutionIntensity.end())
00476                 {
00477                         pEnergy2Evolve = &((*itActionsExecutionIntensity).second);
00478                 }
00479                 else
00480                 {
00481                         std::map<std::string, CMotivateCS>::iterator itClassifiersAndMotivationIntensity;
00482                         itClassifiersAndMotivationIntensity = _ClassifiersAndMotivationIntensity.find(behav);
00483                         nlassert (itClassifiersAndMotivationIntensity != _ClassifiersAndMotivationIntensity.end()); // Sinon c'est que j'ai une action qui ne correspond ni à une vrai action ni à un autre classeur.
00484                         pEnergy2Evolve = &((*itClassifiersAndMotivationIntensity).second.MotivationIntensity);
00485                 }
00486                 nlassert(pEnergy2Evolve);
00487 
00488                 // On change la valeur de motivation de la cible.
00489                 // 1) on retire son énergie au précédent truc
00490                 _ClassifiersAndMotivationIntensity[pCSselection->LastMotivedAction].MotivationIntensity.removeProvider(selectionName);
00491 
00492                 // 2) on rajoute notre énergie au nouveau.
00493                 pEnergy2Evolve->addProvider(selectionName, refMyEnergy);
00494                 
00495         }
00496 }
00497 
00498 void CNetCS::setSensors(const TSensorMap &sensorMap)
00499 {
00500         _SensorsValues = sensorMap;
00501 }
00502 
00503 
00504 std::string CNetCS::selectBehavior()
00505 {
00506         // On prend le max
00507         std::string ret = "";
00508         sint16 executionIntensity = 0;
00509         std::map<std::string, CMotivationEnergy>::iterator itActionsExecutionIntensity;
00510         for (itActionsExecutionIntensity = _ActionsExecutionIntensity.begin(); itActionsExecutionIntensity != _ActionsExecutionIntensity.end(); itActionsExecutionIntensity++)
00511         {
00512                 sint16 value = (*itActionsExecutionIntensity).second.getSumValue();
00513                 if (value > executionIntensity)
00514                 {
00515                         ret = (*itActionsExecutionIntensity).first;
00516                 }
00517         }
00518         return ret;
00519 }
00520 
00521 
00522 } // NLAINIMAT