Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00040 #include <plugins/prediction/DecisionTree.h>
00041
00042
00043 namespace beliefstate {
00044 DecisionTree::DecisionTree() {
00045 this->init();
00046 }
00047
00048 DecisionTree::DecisionTree(std::string strFile) {
00049 this->init("", strFile);
00050 }
00051
00052 DecisionTree::~DecisionTree() {
00053 if(m_jsnDecisionTree) {
00054 delete m_jsnDecisionTree;
00055 }
00056 }
00057
00058 void DecisionTree::init(std::string strMessagePrefix, std::string strFile) {
00059 if(strMessagePrefix == "") {
00060 strMessagePrefix = "dtree-aux";
00061 }
00062
00063 this->setMessagePrefixLabel(strMessagePrefix);
00064
00065 m_jsnDecisionTree = new JSON();
00066 }
00067
00068 bool DecisionTree::load(std::string strFile) {
00069 bool bReturn = false;
00070
00071 if(strFile != "") {
00072 std::ifstream ifFile(strFile.c_str());
00073
00074 if(ifFile.good()) {
00075 std::string strJSON((istreambuf_iterator<char>(ifFile)),
00076 (istreambuf_iterator<char>()));
00077
00078 m_jsnDecisionTree->parse(strJSON);
00079
00080 if(m_jsnDecisionTree->rootProperty()) {
00081 bReturn = true;
00082 }
00083 }
00084 }
00085
00086 return bReturn;
00087 }
00088
00089 Property* DecisionTree::evaluate(CKeyValuePair* ckvpFeatures) {
00090 Property* prReturn = NULL;
00091
00092 if(m_jsnDecisionTree) {
00093 if(m_jsnDecisionTree->rootProperty()) {
00094 prReturn = this->evaluate(m_jsnDecisionTree->rootProperty(), ckvpFeatures);
00095 }
00096 }
00097
00098 return prReturn;
00099 }
00100
00101 bool DecisionTree::relationSatisfied(Property* prRelation, CKeyValuePair* ckvpFeatures) {
00102
00103 bool bResult = false;
00104 Property* prOperator = NULL;
00105 Property* prVariable = NULL;
00106 Property* prValue = NULL;
00107
00108 std::string strOperator = prRelation->key();
00109 prVariable = prRelation->namedSubProperty("variable");
00110 prValue = prRelation->namedSubProperty("value");
00111
00112 if(strOperator != "" && prVariable && prValue) {
00113 if(ckvpFeatures->childForKey(prVariable->getString())) {
00114 if(strOperator == "=") {
00115 switch(prValue->type()) {
00116 case Property::String: {
00117 std::string strFeature = ckvpFeatures->stringValue(prVariable->getString());
00118 bResult = (strFeature == prValue->getString());
00119 } break;
00120
00121 case Property::Integer: {
00122 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00123 bResult = (nFeature == prValue->getInteger());
00124 } break;
00125
00126 case Property::Double: {
00127 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00128 bResult = (fFeature == (float)prValue->getDouble());
00129 } break;
00130
00131 case Property::Boolean: {
00132 bool bFeature = (ckvpFeatures->floatValue(prVariable->getString()) != 0.0);
00133 bResult = (bFeature == prValue->getBoolean());
00134 } break;
00135
00136 default: {
00137 this->warn("Unknown property value type, not evaluating.");
00138 } break;
00139 }
00140 } else if(strOperator == "<") {
00141 switch(prValue->type()) {
00142 case Property::Integer: {
00143 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00144 bResult = (nFeature < prValue->getInteger());
00145 } break;
00146
00147 case Property::Double: {
00148 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00149 bResult = (fFeature < (float)prValue->getDouble());
00150 } break;
00151
00152 default: {
00153 this->warn("Unknown property value type, not evaluating.");
00154 } break;
00155 }
00156 } else if(strOperator == "<=") {
00157 switch(prValue->type()) {
00158 case Property::Integer: {
00159 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00160 bResult = (nFeature <= prValue->getInteger());
00161 } break;
00162
00163 case Property::Double: {
00164 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00165 bResult = (fFeature <= (float)prValue->getDouble());
00166 } break;
00167
00168 default: {
00169 this->warn("Unknown property value type, not evaluating.");
00170 } break;
00171 }
00172 } else if(strOperator == ">") {
00173 switch(prValue->type()) {
00174 case Property::Integer: {
00175 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00176 bResult = (nFeature > prValue->getInteger());
00177 } break;
00178
00179 case Property::Double: {
00180 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00181 bResult = (fFeature > (float)prValue->getDouble());
00182 } break;
00183
00184 default: {
00185 this->warn("Unknown property value type, not evaluating.");
00186 } break;
00187 }
00188 } else if(strOperator == ">=") {
00189 switch(prValue->type()) {
00190 case Property::Integer: {
00191 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00192 bResult = (nFeature >= prValue->getInteger());
00193 } break;
00194
00195 case Property::Double: {
00196 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00197 bResult = (fFeature >= (float)prValue->getDouble());
00198 } break;
00199
00200 default: {
00201 this->warn("Unknown property value type, not evaluating.");
00202 } break;
00203 }
00204 } else if(strOperator == "!=") {
00205 switch(prValue->type()) {
00206 case Property::String: {
00207 std::string strFeature = ckvpFeatures->stringValue(prVariable->getString());
00208 bResult = (strFeature != prValue->getString());
00209 } break;
00210
00211 case Property::Integer: {
00212 int nFeature = (int)ckvpFeatures->floatValue(prVariable->getString());
00213 bResult = (nFeature != prValue->getInteger());
00214 } break;
00215
00216 case Property::Double: {
00217 float fFeature = ckvpFeatures->floatValue(prVariable->getString());
00218 bResult = (fFeature != (float)prValue->getDouble());
00219 } break;
00220
00221 case Property::Boolean: {
00222 bool bFeature = (ckvpFeatures->floatValue(prVariable->getString()) != 0.0);
00223 bResult = (bFeature != prValue->getBoolean());
00224 } break;
00225
00226 default: {
00227 this->warn("Unknown property value type, not evaluating.");
00228 } break;
00229 }
00230 } else {
00231 this->warn("Unknown operator: '" + strOperator + "'");
00232 }
00233 } else {
00234 this->missingFeature(strOperator, prVariable->getString());
00235 }
00236 } else {
00237 this->warn("Missing operator, variable, or value.");
00238 }
00239
00240 return bResult;
00241 }
00242
00243 Property* DecisionTree::evaluate(Property* prTree, CKeyValuePair* ckvpFeatures) {
00244 Property* prResult = NULL;
00245
00246 if(prTree && ckvpFeatures) {
00247 Property* prAction = prTree->namedSubProperty("relation");
00248
00249 if(prAction) {
00250 bool bResult = this->relationSatisfied(prAction->subProperties().front(), ckvpFeatures);
00251
00252 prResult = prTree->namedSubProperty((bResult ? "true" : "false"));
00253 if(prResult) {
00254 list<Property*> lstSubActions = prResult->subProperties();
00255
00256 for(Property* prSubAction : lstSubActions) {
00257 prResult = this->evaluate(prSubAction, ckvpFeatures);
00258
00259 if(prResult) {
00260 break;
00261 }
00262 }
00263 }
00264 } else if((prAction = prTree->namedSubProperty("result")) != NULL) {
00265
00266 prResult = prAction;
00267 } else if(prTree->type() == Property::Array) {
00268 for(Property* prSubAction : prTree->subProperties()) {
00269 prResult = this->evaluate(prSubAction, ckvpFeatures);
00270
00271 if(prResult) {
00272 break;
00273 }
00274 }
00275 } else {
00276
00277 this->warn("Cannot evaluate decision tree branch:");
00278 prTree->print();
00279 }
00280 }
00281
00282 return prResult;
00283 }
00284
00285 std::vector<CKeyValuePair*> DecisionTree::invert(Property* prTargetResult, CKeyValuePair* ckvpFeatures) {
00286 std::vector<CKeyValuePair*> vecSolutions;
00287
00288
00289 std::vector<Property*> vecSolutionsTemp = this->findBranchesWithResult(prTargetResult);
00290 std::vector< std::vector<Property*> > vecSolutionsStraightened = this->straightenResultBranches(vecSolutionsTemp);
00291 for(Property* prSolution : vecSolutionsTemp) {
00292 delete prSolution;
00293 }
00294
00295
00296
00297 std::vector< std::vector<Property*> > vecSols;
00298
00299 for(std::vector<Property*> vecSolution : vecSolutionsStraightened) {
00300 std::vector<Property*> vecSolutionNew;
00301
00302 for(std::vector<Property*>::iterator itSolutionStep = vecSolution.begin();
00303 itSolutionStep != vecSolution.end();
00304 ++itSolutionStep) {
00305 if(!this->relationSatisfied(*itSolutionStep, ckvpFeatures)) {
00306 vecSolutionNew.push_back(*itSolutionStep);
00307 } else {
00308 delete *itSolutionStep;
00309 }
00310 }
00311
00312 vecSols.push_back(vecSolutionNew);
00313 }
00314
00315 for(std::vector<Property*> vecSolution : vecSols) {
00316 if(vecSolution.size() > 0) {
00317 CKeyValuePair* ckvpSolution = new CKeyValuePair("solution", LIST);
00318
00319 for(Property* prSolutionStep : vecSolution) {
00320 CKeyValuePair* ckvpStep = new CKeyValuePair("step", LIST);
00321 ckvpSolution->addChild(ckvpStep);
00322
00323 ckvpStep->setValue("relation", prSolutionStep->key());
00324
00325 std::list<std::string> lstCopyFields;
00326 lstCopyFields.push_back("variable");
00327 lstCopyFields.push_back("value");
00328
00329 for(std::string strFieldName : lstCopyFields) {
00330 Property* prField = prSolutionStep->namedSubProperty(strFieldName);
00331
00332 switch(prField->type()) {
00333 case Property::String:
00334 ckvpStep->setValue(strFieldName, prField->getString());
00335 break;
00336
00337 case Property::Integer:
00338 ckvpStep->setValue(strFieldName, prField->getInteger());
00339 break;
00340
00341 case Property::Double:
00342 ckvpStep->setValue(strFieldName, prField->getDouble());
00343 break;
00344
00345 case Property::Boolean:
00346 ckvpStep->setValue(strFieldName, prField->getBoolean());
00347 break;
00348
00349 default:
00350 this->warn("Unknown property type.");
00351 break;
00352 }
00353 }
00354
00355 delete prSolutionStep;
00356 }
00357
00358 vecSolutions.push_back(ckvpSolution);
00359 }
00360 }
00361
00362 return vecSolutions;
00363 }
00364
00365 std::vector< std::vector<Property*> > DecisionTree::straightenResultBranches(std::vector<Property*> vecSolutionBranches) {
00366 std::vector< std::vector<Property*> > vecSolutionsStraightened;
00367
00368 for(Property* prSolutionBranch : vecSolutionBranches) {
00369 vecSolutionsStraightened.push_back(this->straightenResultBranch(prSolutionBranch));
00370 }
00371
00372 return vecSolutionsStraightened;
00373 }
00374
00375 std::vector<Property*> DecisionTree::straightenResultBranch(Property* prSolutionBranch) {
00376 std::vector<Property*> vecStraightened;
00377
00378
00379
00380 if(prSolutionBranch->key() == "relation") {
00381 if(prSolutionBranch->subProperties().size() == 1) {
00382 vecStraightened.push_back(new Property(prSolutionBranch->subProperties().front()));
00383 }
00384 }
00385
00386 for(Property* prSub : prSolutionBranch->subProperties()) {
00387 std::vector<Property*> vecSubStraightened = this->straightenResultBranch(prSub);
00388
00389 for(Property* prSubStraightened : vecSubStraightened) {
00390 vecStraightened.push_back(new Property(prSubStraightened));
00391 delete prSubStraightened;
00392 }
00393 }
00394
00395 return vecStraightened;
00396 }
00397
00398 std::vector<Property*> DecisionTree::findBranchesWithResult(Property* prTargetResult, Property* prStart) {
00399 std::vector<Property*> vecSolutions;
00400
00401 if(!prStart) {
00402 prStart = m_jsnDecisionTree->rootProperty();
00403 }
00404
00405 Property* prResult = prStart->namedSubProperty("result");
00406 if(prResult) {
00407
00408
00409
00410
00411
00412
00413 if(prResult->getString() == prTargetResult->getString()) {
00414
00415
00416 vecSolutions.push_back(new Property(prStart));
00417 } else {
00418
00419
00420 }
00421 } else {
00422
00423
00424
00425
00426 Property* prRelation = prStart->namedSubProperty("relation");
00427
00428
00429
00430 for(Property* prBranch : prStart->subProperties()) {
00431 if(prBranch->key() != "relation") {
00432
00433 std::vector<Property*> vecSubSolutions = this->findBranchesWithResult(prTargetResult, prBranch);
00434
00435
00436 for(Property* prSubSolution : vecSubSolutions) {
00437 Property* prSolutionBranch = new Property("", Property::Object);
00438
00439 if(prRelation) {
00440 prSolutionBranch->addSubProperty(new Property(prRelation));
00441 }
00442
00443 prSolutionBranch->addSubProperty(new Property(prSubSolution));
00444 delete prSubSolution;
00445
00446 vecSolutions.push_back(prSolutionBranch);
00447 }
00448 }
00449 }
00450 }
00451
00452 return vecSolutions;
00453 }
00454
00455 void DecisionTree::missingFeature(std::string strOperator, std::string strFeatureName) {
00456 this->warn("Decision Tree: '" + strFeatureName + "' missing from feature space while evaluating operator '" + strOperator + "'.");
00457 }
00458
00459 void DecisionTree::missingOperand(std::string strOperator) {
00460 this->warn("Decision Tree: Operand missing while evaluating operator '" + strOperator + "'.");
00461 }
00462 }