Engine.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. Author: Juan Rada-Vilela, Ph.D.
  3. Copyright (C) 2010-2014 FuzzyLite Limited
  4. All rights reserved
  5. This file is part of fuzzylite.
  6. fuzzylite is free software: you can redistribute it and/or modify it under
  7. the terms of the GNU Lesser General Public License as published by the Free
  8. Software Foundation, either version 3 of the License, or (at your option)
  9. any later version.
  10. fuzzylite is distributed in the hope that it will be useful, but WITHOUT
  11. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  13. for more details.
  14. You should have received a copy of the GNU Lesser General Public License
  15. along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
  16. fuzzylite™ is a trademark of FuzzyLite Limited.
  17. */
  18. #include "fl/Engine.h"
  19. #include "fl/defuzzifier/WeightedAverage.h"
  20. #include "fl/defuzzifier/WeightedSum.h"
  21. #include "fl/factory/DefuzzifierFactory.h"
  22. #include "fl/factory/FactoryManager.h"
  23. #include "fl/factory/SNormFactory.h"
  24. #include "fl/factory/TNormFactory.h"
  25. #include "fl/hedge/Hedge.h"
  26. #include "fl/imex/FllExporter.h"
  27. #include "fl/norm/t/AlgebraicProduct.h"
  28. #include "fl/rule/Consequent.h"
  29. #include "fl/rule/Expression.h"
  30. #include "fl/rule/Rule.h"
  31. #include "fl/rule/RuleBlock.h"
  32. #include "fl/term/Accumulated.h"
  33. #include "fl/term/Constant.h"
  34. #include "fl/term/Linear.h"
  35. #include "fl/term/Function.h"
  36. #include "fl/term/Ramp.h"
  37. #include "fl/term/Sigmoid.h"
  38. #include "fl/term/SShape.h"
  39. #include "fl/term/ZShape.h"
  40. #include "fl/variable/InputVariable.h"
  41. #include "fl/variable/OutputVariable.h"
  42. namespace fl {
  43. Engine::Engine(const std::string& name) : _name(name) {
  44. }
  45. Engine::Engine(const Engine& other) : _name("") {
  46. copyFrom(other);
  47. }
  48. Engine& Engine::operator=(const Engine& other) {
  49. if (this != &other) {
  50. for (std::size_t i = 0; i < _ruleblocks.size(); ++i)
  51. delete _ruleblocks.at(i);
  52. _ruleblocks.clear();
  53. for (std::size_t i = 0; i < _outputVariables.size(); ++i)
  54. delete _outputVariables.at(i);
  55. _outputVariables.clear();
  56. for (std::size_t i = 0; i < _inputVariables.size(); ++i)
  57. delete _inputVariables.at(i);
  58. _inputVariables.clear();
  59. copyFrom(other);
  60. }
  61. return *this;
  62. }
  63. void Engine::copyFrom(const Engine& other) {
  64. _name = other._name;
  65. for (std::size_t i = 0; i < other._inputVariables.size(); ++i)
  66. _inputVariables.push_back(new InputVariable(*other._inputVariables.at(i)));
  67. for (std::size_t i = 0; i < other._outputVariables.size(); ++i)
  68. _outputVariables.push_back(new OutputVariable(*other._outputVariables.at(i)));
  69. updateReferences();
  70. for (std::size_t i = 0; i < other._ruleblocks.size(); ++i) {
  71. RuleBlock* ruleBlock = new RuleBlock(*other._ruleblocks.at(i));
  72. try {
  73. ruleBlock->loadRules(this);
  74. } catch (...) {
  75. }
  76. _ruleblocks.push_back(ruleBlock);
  77. }
  78. }
  79. void Engine::updateReferences() const {
  80. std::vector<Variable*> myVariables = variables();
  81. for (std::size_t i = 0; i < myVariables.size(); ++i) {
  82. Variable* variable = myVariables.at(i);
  83. for (int t = 0; t < variable->numberOfTerms(); ++t) {
  84. Term::updateReference(variable->getTerm(t), this);
  85. }
  86. }
  87. }
  88. Engine::~Engine() {
  89. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) delete _ruleblocks.at(i);
  90. for (std::size_t i = 0; i < _outputVariables.size(); ++i) delete _outputVariables.at(i);
  91. for (std::size_t i = 0; i < _inputVariables.size(); ++i) delete _inputVariables.at(i);
  92. }
  93. void Engine::configure(const std::string& conjunctionT, const std::string& disjunctionS,
  94. const std::string& activationT, const std::string& accumulationS,
  95. const std::string& defuzzifierName, int resolution) {
  96. TNormFactory* tnormFactory = FactoryManager::instance()->tnorm();
  97. SNormFactory* snormFactory = FactoryManager::instance()->snorm();
  98. DefuzzifierFactory* defuzzFactory = FactoryManager::instance()->defuzzifier();
  99. TNorm* conjunction = tnormFactory->constructObject(conjunctionT);
  100. SNorm* disjunction = snormFactory->constructObject(disjunctionS);
  101. TNorm* activation = tnormFactory->constructObject(activationT);
  102. SNorm* accumulation = snormFactory->constructObject(accumulationS);
  103. Defuzzifier* defuzzifier = defuzzFactory->constructObject(defuzzifierName);
  104. IntegralDefuzzifier* integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (defuzzifier);
  105. if (integralDefuzzifier) integralDefuzzifier->setResolution(resolution);
  106. configure(conjunction, disjunction, activation, accumulation, defuzzifier);
  107. }
  108. void Engine::configure(TNorm* conjunction, SNorm* disjunction,
  109. TNorm* activation, SNorm* accumulation, Defuzzifier* defuzzifier) {
  110. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  111. _ruleblocks.at(i)->setConjunction(conjunction ? conjunction->clone() : fl::null);
  112. _ruleblocks.at(i)->setDisjunction(disjunction ? disjunction->clone() : fl::null);
  113. _ruleblocks.at(i)->setActivation(activation ? activation->clone() : fl::null);
  114. }
  115. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  116. _outputVariables.at(i)->setDefuzzifier(defuzzifier ? defuzzifier->clone() : fl::null);
  117. _outputVariables.at(i)->fuzzyOutput()->setAccumulation(
  118. accumulation ? accumulation->clone() : fl::null);
  119. }
  120. if (defuzzifier) delete defuzzifier;
  121. if (accumulation) delete accumulation;
  122. if (activation) delete activation;
  123. if (disjunction) delete disjunction;
  124. if (conjunction) delete conjunction;
  125. }
  126. bool Engine::isReady(std::string* status) const {
  127. std::ostringstream ss;
  128. if (_inputVariables.empty()) {
  129. ss << "- Engine <" << _name << "> has no input variables\n";
  130. }
  131. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  132. InputVariable* inputVariable = _inputVariables.at(i);
  133. if (not inputVariable) {
  134. ss << "- Engine <" << _name << "> has a fl::null input variable at index <" << i << ">\n";
  135. } else if (inputVariable->terms().empty()) {
  136. //ignore because sometimes inputs can be empty: takagi-sugeno/matlab/slcpp1.fis
  137. // ss << "- Input variable <" << _inputVariables.at(i)->getName() << ">"
  138. // << " has no terms\n";
  139. }
  140. }
  141. if (_outputVariables.empty()) {
  142. ss << "- Engine <" << _name << "> has no output variables\n";
  143. }
  144. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  145. OutputVariable* outputVariable = _outputVariables.at(i);
  146. if (not outputVariable) {
  147. ss << "- Engine <" << _name << "> has a fl::null output variable at index <" << i << ">\n";
  148. } else {
  149. if (outputVariable->terms().empty()) {
  150. ss << "- Output variable <" << outputVariable->getName() << ">"
  151. << " has no terms\n";
  152. }
  153. SNorm* accumulation = outputVariable->fuzzyOutput()->getAccumulation();
  154. if (not accumulation and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier())) {
  155. ss << "- Output variable <" << outputVariable->getName() << ">"
  156. << " has no accumulation operator\n";
  157. }
  158. Defuzzifier* defuzzifier = outputVariable->getDefuzzifier();
  159. if (not defuzzifier) {
  160. ss << "- Output variable <" << outputVariable->getName() << ">"
  161. << " has no defuzzifier\n";
  162. }
  163. }
  164. }
  165. if (_ruleblocks.empty()) {
  166. ss << "- Engine <" << _name << "> has no rule blocks\n";
  167. }
  168. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  169. RuleBlock* ruleblock = _ruleblocks.at(i);
  170. if (not ruleblock) {
  171. ss << "- Engine <" << _name << "> has a fl::null rule block at index <" << i << ">\n";
  172. } else {
  173. if (ruleblock->rules().empty()) {
  174. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no rules\n";
  175. }
  176. int requiresConjunction = 0;
  177. int requiresDisjunction = 0;
  178. int requiresActivation = 0;
  179. for (int r = 0; r < ruleblock->numberOfRules(); ++r) {
  180. Rule* rule = ruleblock->getRule(r);
  181. if (not rule) {
  182. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName()
  183. << "> has a fl::null rule at index <" << r << ">\n";
  184. } else {
  185. std::size_t thenIndex = rule->getText().find(" " + Rule::thenKeyword() + " ");
  186. std::size_t andIndex = rule->getText().find(" " + Rule::andKeyword() + " ");
  187. std::size_t orIndex = rule->getText().find(" " + Rule::orKeyword() + " ");
  188. if (andIndex != std::string::npos and andIndex < thenIndex) {
  189. ++requiresConjunction;
  190. }
  191. if (orIndex != std::string::npos and orIndex < thenIndex) {
  192. ++requiresDisjunction;
  193. }
  194. if (rule->isLoaded()) {
  195. Consequent* consequent = rule->getConsequent();
  196. for (std::size_t c = 0; c < consequent->conclusions().size(); ++c) {
  197. Proposition* proposition = consequent->conclusions().at(c);
  198. const OutputVariable* outputVariable =
  199. dynamic_cast<const OutputVariable*> (proposition->variable);
  200. if (outputVariable and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier())) {
  201. ++requiresActivation;
  202. break;
  203. }
  204. }
  205. }
  206. }
  207. }
  208. const TNorm* conjunction = ruleblock->getConjunction();
  209. if (requiresConjunction > 0 and not conjunction) {
  210. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no conjunction operator\n";
  211. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has "
  212. << requiresConjunction << " rules that require conjunction operator\n";
  213. }
  214. const SNorm* disjunction = ruleblock->getDisjunction();
  215. if (requiresDisjunction > 0 and not disjunction) {
  216. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no disjunction operator\n";
  217. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has "
  218. << requiresDisjunction << " rules that require disjunction operator\n";
  219. }
  220. const TNorm* activation = ruleblock->getActivation();
  221. if (requiresActivation > 0 and not activation) {
  222. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no activation operator\n";
  223. ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has "
  224. << requiresActivation << " rules that require activation operator\n";
  225. }
  226. }
  227. }
  228. if (status) *status = ss.str();
  229. return ss.str().empty();
  230. }
  231. void Engine::restart() {
  232. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  233. _inputVariables.at(i)->setInputValue(fl::nan);
  234. }
  235. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  236. _outputVariables.at(i)->clear();
  237. }
  238. }
  239. void Engine::process() {
  240. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  241. _outputVariables.at(i)->fuzzyOutput()->clear();
  242. }
  243. FL_DEBUG_BEGIN;
  244. FL_DBG("===============");
  245. FL_DBG("CURRENT INPUTS:");
  246. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  247. InputVariable* inputVariable = _inputVariables.at(i);
  248. scalar inputValue = inputVariable->getInputValue();
  249. if (inputVariable->isEnabled()) {
  250. FL_DBG(inputVariable->getName() << ".input = " << Op::str(inputValue));
  251. FL_DBG(inputVariable->getName() << ".fuzzy = " << inputVariable->fuzzify(inputValue));
  252. } else {
  253. FL_DBG(inputVariable->getName() << ".enabled = false");
  254. }
  255. }
  256. FL_DEBUG_END;
  257. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  258. RuleBlock* ruleBlock = _ruleblocks.at(i);
  259. if (ruleBlock->isEnabled()) {
  260. ruleBlock->activate();
  261. }
  262. }
  263. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  264. OutputVariable* outputVariable = _outputVariables.at(i);
  265. outputVariable->defuzzify();
  266. }
  267. FL_DEBUG_BEGIN;
  268. FL_DBG("===============");
  269. FL_DBG("CURRENT OUTPUTS:");
  270. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  271. OutputVariable* outputVariable = _outputVariables.at(i);
  272. if (outputVariable->isEnabled()) {
  273. FL_DBG(outputVariable->getName() << ".default = "
  274. << outputVariable->getDefaultValue());
  275. FL_DBG(outputVariable->getName() << ".lockValueInRange = "
  276. << outputVariable->isLockedOutputValueInRange());
  277. FL_DBG(outputVariable->getName() << ".lockPreviousValue= "
  278. << outputVariable->isLockedPreviousOutputValue());
  279. scalar output = outputVariable->getOutputValue();
  280. FL_DBG(outputVariable->getName() << ".output = " << output);
  281. FL_DBG(outputVariable->getName() << ".fuzzy = " <<
  282. outputVariable->fuzzify(output));
  283. FL_DBG(outputVariable->fuzzyOutput()->toString());
  284. } else {
  285. FL_DBG(outputVariable->getName() << ".enabled = false");
  286. }
  287. }
  288. FL_DBG("==============");
  289. FL_DEBUG_END;
  290. }
  291. void Engine::setName(const std::string& name) {
  292. this->_name = name;
  293. }
  294. std::string Engine::getName() const {
  295. return this->_name;
  296. }
  297. void Engine::setInputValue(const std::string& name, scalar value) {
  298. InputVariable* inputVariable = getInputVariable(name);
  299. inputVariable->setInputValue(value);
  300. }
  301. scalar Engine::getOutputValue(const std::string& name) {
  302. OutputVariable* outputVariable = getOutputVariable(name);
  303. return outputVariable->getOutputValue();
  304. }
  305. std::string Engine::toString() const {
  306. return FllExporter().toString(this);
  307. }
  308. Engine::Type Engine::type(std::string* name, std::string* reason) const {
  309. if (_outputVariables.empty()) {
  310. if (name) *name = "Unknown";
  311. if (reason) *reason = "- Engine has no output variables";
  312. return Engine::Unknown;
  313. }
  314. //Mamdani
  315. bool mamdani = true;
  316. for (std::size_t i = 0; mamdani and i < _outputVariables.size(); ++i) {
  317. OutputVariable* outputVariable = _outputVariables.at(i);
  318. //Defuzzifier must be integral
  319. mamdani = mamdani and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier());
  320. }
  321. //Larsen
  322. bool larsen = mamdani and not _ruleblocks.empty();
  323. //Larsen is Mamdani with AlgebraicProduct as Activation
  324. if (mamdani) {
  325. for (std::size_t i = 0; larsen and i < _ruleblocks.size(); ++i) {
  326. RuleBlock* ruleBlock = _ruleblocks.at(i);
  327. larsen = larsen and dynamic_cast<const AlgebraicProduct*> (ruleBlock->getActivation());
  328. }
  329. }
  330. if (larsen) {
  331. if (name) *name = "Larsen";
  332. if (reason) *reason = "- Output variables have integral defuzzifiers\n"
  333. "- Rule blocks activate using the algebraic product T-Norm";
  334. return Engine::Larsen;
  335. }
  336. if (mamdani) {
  337. if (name) *name = "Mamdani";
  338. if (reason) *reason = "-Output variables have integral defuzzifiers";
  339. return Engine::Mamdani;
  340. }
  341. //Else, keep checking
  342. //TakagiSugeno
  343. bool takagiSugeno = true;
  344. for (std::size_t i = 0; takagiSugeno and i < _outputVariables.size(); ++i) {
  345. OutputVariable* outputVariable = _outputVariables.at(i);
  346. //Defuzzifier is Weighted
  347. WeightedDefuzzifier* weightedDefuzzifier =
  348. dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
  349. takagiSugeno = takagiSugeno and weightedDefuzzifier and
  350. (weightedDefuzzifier->getType() == WeightedDefuzzifier::Automatic or
  351. weightedDefuzzifier->getType() == WeightedDefuzzifier::TakagiSugeno);
  352. if (takagiSugeno) {
  353. //Takagi-Sugeno has only Constant, Linear or Function terms
  354. for (int t = 0; takagiSugeno and t < outputVariable->numberOfTerms(); ++t) {
  355. Term* term = outputVariable->getTerm(t);
  356. takagiSugeno = takagiSugeno and
  357. weightedDefuzzifier->inferType(term) == WeightedDefuzzifier::TakagiSugeno;
  358. }
  359. }
  360. }
  361. if (takagiSugeno) {
  362. if (name) *name = "Takagi-Sugeno";
  363. if (reason) *reason = "- Output variables have weighted defuzzifiers\n"
  364. "- Output variables have constant, linear or function terms";
  365. return Engine::TakagiSugeno;
  366. }
  367. //Tsukamoto
  368. bool tsukamoto = true;
  369. for (std::size_t i = 0; tsukamoto and i < _outputVariables.size(); ++i) {
  370. OutputVariable* outputVariable = _outputVariables.at(i);
  371. //Defuzzifier is Weighted
  372. WeightedDefuzzifier* weightedDefuzzifier =
  373. dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
  374. tsukamoto = tsukamoto and weightedDefuzzifier and
  375. (weightedDefuzzifier->getType() == WeightedDefuzzifier::Automatic or
  376. weightedDefuzzifier->getType() == WeightedDefuzzifier::Tsukamoto);
  377. if (tsukamoto) {
  378. //Tsukamoto has only monotonic terms: Concave, Ramp, Sigmoid, SShape, or ZShape
  379. for (int t = 0; tsukamoto and t < outputVariable->numberOfTerms(); ++t) {
  380. Term* term = outputVariable->getTerm(t);
  381. tsukamoto = tsukamoto and weightedDefuzzifier->isMonotonic(term);
  382. }
  383. }
  384. }
  385. if (tsukamoto) {
  386. if (name) *name = "Tsukamoto";
  387. if (reason) *reason = "- Output variables have weighted defuzzifiers\n"
  388. "- Output variables only have monotonic terms";
  389. return Engine::Tsukamoto;
  390. }
  391. //Inverse Tsukamoto
  392. bool inverseTsukamoto = true;
  393. for (std::size_t i = 0; inverseTsukamoto and i < _outputVariables.size(); ++i) {
  394. OutputVariable* outputVariable = _outputVariables.at(i);
  395. //Defuzzifier cannot be integral
  396. WeightedDefuzzifier* weightedDefuzzifier =
  397. dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
  398. inverseTsukamoto = inverseTsukamoto and weightedDefuzzifier;
  399. }
  400. if (inverseTsukamoto) {
  401. if (name) *name = "Inverse Tsukamoto";
  402. if (reason) *reason = "- Output variables have weighted defuzzifiers\n"
  403. "- Output variables do not only have constant, linear or function terms\n"
  404. "- Output variables do not only have monotonic terms\n";
  405. return Engine::InverseTsukamoto;
  406. }
  407. bool hybrid = true;
  408. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  409. OutputVariable* outputVariable = _outputVariables.at(i);
  410. //Output variables have non-fl::null defuzzifiers
  411. hybrid = hybrid and outputVariable->getDefuzzifier();
  412. }
  413. if (hybrid) {
  414. if (name) *name = "Hybrid";
  415. if (reason) *reason = "- Output variables have different defuzzifiers";
  416. return Engine::Hybrid;
  417. }
  418. if (name) *name = "Unknown";
  419. if (reason) *reason = "- There are output variables without a defuzzifier";
  420. return Engine::Unknown;
  421. }
  422. Engine* Engine::clone() const {
  423. return new Engine(*this);
  424. }
  425. std::vector<Variable*> Engine::variables() const {
  426. std::vector<Variable*> result;
  427. result.reserve(_inputVariables.size() + _outputVariables.size());
  428. result.insert(result.end(), _inputVariables.begin(), _inputVariables.end());
  429. result.insert(result.end(), _outputVariables.begin(), _outputVariables.end());
  430. return result;
  431. }
  432. /**
  433. * Operations for iterable datatype _inputVariables
  434. */
  435. void Engine::addInputVariable(InputVariable* inputVariable) {
  436. this->_inputVariables.push_back(inputVariable);
  437. }
  438. InputVariable* Engine::setInputVariable(InputVariable* inputVariable, int index) {
  439. InputVariable* result = this->_inputVariables.at(index);
  440. this->_inputVariables.at(index) = inputVariable;
  441. return result;
  442. }
  443. void Engine::insertInputVariable(InputVariable* inputVariable, int index) {
  444. this->_inputVariables.insert(this->_inputVariables.begin() + index,
  445. inputVariable);
  446. }
  447. InputVariable* Engine::getInputVariable(int index) const {
  448. return this->_inputVariables.at(index);
  449. }
  450. InputVariable* Engine::getInputVariable(const std::string& name) const {
  451. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  452. if (_inputVariables.at(i)->getName() == name)
  453. return _inputVariables.at(i);
  454. }
  455. throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT);
  456. }
  457. bool Engine::hasInputVariable(const std::string& name) const {
  458. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  459. if (_inputVariables.at(i)->getName() == name)
  460. return true;
  461. }
  462. return false;
  463. }
  464. InputVariable* Engine::removeInputVariable(int index) {
  465. InputVariable* result = this->_inputVariables.at(index);
  466. this->_inputVariables.erase(this->_inputVariables.begin() + index);
  467. return result;
  468. }
  469. InputVariable* Engine::removeInputVariable(const std::string& name) {
  470. for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
  471. if (_inputVariables.at(i)->getName() == name) {
  472. InputVariable* result = this->_inputVariables.at(i);
  473. this->_inputVariables.erase(this->_inputVariables.begin() + i);
  474. return result;
  475. }
  476. }
  477. throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT);
  478. }
  479. int Engine::numberOfInputVariables() const {
  480. return this->_inputVariables.size();
  481. }
  482. const std::vector<InputVariable*>& Engine::inputVariables() const {
  483. return this->_inputVariables;
  484. }
  485. void Engine::setInputVariables(const std::vector<InputVariable*>& inputVariables) {
  486. this->_inputVariables = inputVariables;
  487. }
  488. std::vector<InputVariable*>& Engine::inputVariables() {
  489. return this->_inputVariables;
  490. }
  491. /**
  492. * Operations for iterable datatype _outputVariables
  493. */
  494. void Engine::addOutputVariable(OutputVariable* outputVariable) {
  495. this->_outputVariables.push_back(outputVariable);
  496. }
  497. OutputVariable* Engine::setOutputVariable(OutputVariable* outputVariable, int index) {
  498. OutputVariable* result = this->_outputVariables.at(index);
  499. this->_outputVariables.at(index) = outputVariable;
  500. return result;
  501. }
  502. void Engine::insertOutputVariable(OutputVariable* outputVariable, int index) {
  503. this->_outputVariables.insert(this->_outputVariables.begin() + index,
  504. outputVariable);
  505. }
  506. OutputVariable* Engine::getOutputVariable(int index) const {
  507. return this->_outputVariables.at(index);
  508. }
  509. OutputVariable* Engine::getOutputVariable(const std::string& name) const {
  510. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  511. if (_outputVariables.at(i)->getName() == name)
  512. return _outputVariables.at(i);
  513. }
  514. throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT);
  515. }
  516. bool Engine::hasOutputVariable(const std::string& name) const {
  517. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  518. if (_outputVariables.at(i)->getName() == name)
  519. return true;
  520. }
  521. return false;
  522. }
  523. OutputVariable* Engine::removeOutputVariable(int index) {
  524. OutputVariable* result = this->_outputVariables.at(index);
  525. this->_outputVariables.erase(this->_outputVariables.begin() + index);
  526. return result;
  527. }
  528. OutputVariable* Engine::removeOutputVariable(const std::string& name) {
  529. for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
  530. if (_outputVariables.at(i)->getName() == name) {
  531. OutputVariable* result = this->_outputVariables.at(i);
  532. this->_outputVariables.erase(this->_outputVariables.begin() + i);
  533. return result;
  534. }
  535. }
  536. throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT);
  537. }
  538. int Engine::numberOfOutputVariables() const {
  539. return this->_outputVariables.size();
  540. }
  541. const std::vector<OutputVariable*>& Engine::outputVariables() const {
  542. return this->_outputVariables;
  543. }
  544. void Engine::setOutputVariables(const std::vector<OutputVariable*>& outputVariables) {
  545. this->_outputVariables = outputVariables;
  546. }
  547. std::vector<OutputVariable*>& Engine::outputVariables() {
  548. return this->_outputVariables;
  549. }
  550. /**
  551. * Operations for iterable datatype _ruleblocks
  552. */
  553. void Engine::addRuleBlock(RuleBlock* ruleblock) {
  554. this->_ruleblocks.push_back(ruleblock);
  555. }
  556. RuleBlock* Engine::setRuleBlock(RuleBlock* ruleBlock, int index) {
  557. RuleBlock* result = this->_ruleblocks.at(index);
  558. this->_ruleblocks.at(index) = ruleBlock;
  559. return result;
  560. }
  561. void Engine::insertRuleBlock(RuleBlock* ruleblock, int index) {
  562. this->_ruleblocks.insert(this->_ruleblocks.begin() + index, ruleblock);
  563. }
  564. RuleBlock* Engine::getRuleBlock(int index) const {
  565. return this->_ruleblocks.at(index);
  566. }
  567. RuleBlock* Engine::getRuleBlock(const std::string& name) const {
  568. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  569. if (_ruleblocks.at(i)->getName() == name)
  570. return _ruleblocks.at(i);
  571. }
  572. throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT);
  573. }
  574. bool Engine::hasRuleBlock(const std::string& name) const {
  575. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  576. if (_ruleblocks.at(i)->getName() == name)
  577. return true;
  578. }
  579. return false;
  580. }
  581. RuleBlock* Engine::removeRuleBlock(int index) {
  582. RuleBlock* result = this->_ruleblocks.at(index);
  583. this->_ruleblocks.erase(this->_ruleblocks.begin() + index);
  584. return result;
  585. }
  586. RuleBlock* Engine::removeRuleBlock(const std::string& name) {
  587. for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
  588. if (_ruleblocks.at(i)->getName() == name) {
  589. RuleBlock* result = this->_ruleblocks.at(i);
  590. this->_ruleblocks.erase(this->_ruleblocks.begin() + i);
  591. return result;
  592. }
  593. }
  594. throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT);
  595. }
  596. int Engine::numberOfRuleBlocks() const {
  597. return this->_ruleblocks.size();
  598. }
  599. const std::vector<RuleBlock*>& Engine::ruleBlocks() const {
  600. return this->_ruleblocks;
  601. }
  602. void Engine::setRuleBlocks(const std::vector<RuleBlock*>& ruleBlocks) {
  603. this->_ruleblocks = ruleBlocks;
  604. }
  605. std::vector<RuleBlock*>& Engine::ruleBlocks() {
  606. return this->_ruleblocks;
  607. }
  608. }