LogicalExpression.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /*
  2. * LogicalExpression.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. //FIXME: move some of code into .cpp to avoid this include?
  12. #include "JsonNode.h"
  13. namespace LogicalExpressionDetail
  14. {
  15. /// class that defines required types for logical expressions
  16. template<typename ContainedClass>
  17. class ExpressionBase
  18. {
  19. public:
  20. /// Possible logical operations, mostly needed to create different types for boost::variant
  21. enum EOperations
  22. {
  23. ANY_OF,
  24. ALL_OF,
  25. NONE_OF
  26. };
  27. template<EOperations tag> class Element;
  28. typedef Element<ANY_OF> OperatorAny;
  29. typedef Element<ALL_OF> OperatorAll;
  30. typedef Element<NONE_OF> OperatorNone;
  31. typedef ContainedClass Value;
  32. /// Variant that contains all possible elements from logical expression
  33. typedef boost::variant<
  34. OperatorAll,
  35. OperatorAny,
  36. OperatorNone,
  37. Value
  38. > Variant;
  39. /// Variant element, contains list of expressions to which operation "tag" should be applied
  40. template<EOperations tag>
  41. class Element
  42. {
  43. public:
  44. Element() {}
  45. Element(std::vector<Variant> expressions):
  46. expressions(expressions)
  47. {}
  48. std::vector<Variant> expressions;
  49. bool operator == (const Element & other) const
  50. {
  51. return expressions == other.expressions;
  52. }
  53. template <typename Handler>
  54. void serialize(Handler & h, const int version)
  55. {
  56. h & expressions;
  57. }
  58. };
  59. };
  60. /// Visitor to test result (true/false) of the expression
  61. template <typename ContainedClass>
  62. class TestVisitor : public boost::static_visitor<bool>
  63. {
  64. typedef ExpressionBase<ContainedClass> Base;
  65. std::function<bool(const typename Base::Value &)> classTest;
  66. size_t countPassed(const std::vector<typename Base::Variant> & element) const
  67. {
  68. return boost::range::count_if(element, [&](const typename Base::Variant & expr)
  69. {
  70. return boost::apply_visitor(*this, expr);
  71. });
  72. }
  73. public:
  74. TestVisitor(std::function<bool (const typename Base::Value &)> classTest):
  75. classTest(classTest)
  76. {}
  77. bool operator()(const typename Base::OperatorAny & element) const
  78. {
  79. return countPassed(element.expressions) != 0;
  80. }
  81. bool operator()(const typename Base::OperatorAll & element) const
  82. {
  83. return countPassed(element.expressions) == element.expressions.size();
  84. }
  85. bool operator()(const typename Base::OperatorNone & element) const
  86. {
  87. return countPassed(element.expressions) == 0;
  88. }
  89. bool operator()(const typename Base::Value & element) const
  90. {
  91. return classTest(element);
  92. }
  93. };
  94. template <typename ContainedClass>
  95. class SatisfiabilityVisitor;
  96. template <typename ContainedClass>
  97. class FalsifiabilityVisitor;
  98. template <typename ContainedClass>
  99. class PossibilityVisitor : public boost::static_visitor<bool>
  100. {
  101. typedef ExpressionBase<ContainedClass> Base;
  102. protected:
  103. std::function<bool(const typename Base::Value &)> satisfiabilityTest;
  104. std::function<bool(const typename Base::Value &)> falsifiabilityTest;
  105. SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor;
  106. FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor;
  107. size_t countSatisfiable(const std::vector<typename Base::Variant> & element) const
  108. {
  109. return boost::range::count_if(element, [&](const typename Base::Variant & expr)
  110. {
  111. return boost::apply_visitor(*satisfiabilityVisitor, expr);
  112. });
  113. }
  114. size_t countFalsifiable(const std::vector<typename Base::Variant> & element) const
  115. {
  116. return boost::range::count_if(element, [&](const typename Base::Variant & expr)
  117. {
  118. return boost::apply_visitor(*falsifiabilityVisitor, expr);
  119. });
  120. }
  121. public:
  122. PossibilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
  123. std::function<bool (const typename Base::Value &)> falsifiabilityTest):
  124. satisfiabilityTest(satisfiabilityTest),
  125. falsifiabilityTest(falsifiabilityTest),
  126. satisfiabilityVisitor(nullptr),
  127. falsifiabilityVisitor(nullptr)
  128. {}
  129. void setSatisfiabilityVisitor(SatisfiabilityVisitor<ContainedClass> *satisfiabilityVisitor)
  130. {
  131. this->satisfiabilityVisitor = satisfiabilityVisitor;
  132. }
  133. void setFalsifiabilityVisitor(FalsifiabilityVisitor<ContainedClass> *falsifiabilityVisitor)
  134. {
  135. this->falsifiabilityVisitor = falsifiabilityVisitor;
  136. }
  137. };
  138. /// Visitor to test whether expression's value can be true
  139. template <typename ContainedClass>
  140. class SatisfiabilityVisitor : public PossibilityVisitor<ContainedClass>
  141. {
  142. typedef ExpressionBase<ContainedClass> Base;
  143. public:
  144. SatisfiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
  145. std::function<bool (const typename Base::Value &)> falsifiabilityTest):
  146. PossibilityVisitor<ContainedClass>(satisfiabilityTest, falsifiabilityTest)
  147. {
  148. this->setSatisfiabilityVisitor(this);
  149. }
  150. bool operator()(const typename Base::OperatorAny & element) const
  151. {
  152. return this->countSatisfiable(element.expressions) != 0;
  153. }
  154. bool operator()(const typename Base::OperatorAll & element) const
  155. {
  156. return this->countSatisfiable(element.expressions) == element.expressions.size();
  157. }
  158. bool operator()(const typename Base::OperatorNone & element) const
  159. {
  160. return this->countFalsifiable(element.expressions) == element.expressions.size();
  161. }
  162. bool operator()(const typename Base::Value & element) const
  163. {
  164. return this->satisfiabilityTest(element);
  165. }
  166. };
  167. /// Visitor to test whether expression's value can be false
  168. template <typename ContainedClass>
  169. class FalsifiabilityVisitor : public PossibilityVisitor<ContainedClass>
  170. {
  171. typedef ExpressionBase<ContainedClass> Base;
  172. public:
  173. FalsifiabilityVisitor(std::function<bool (const typename Base::Value &)> satisfiabilityTest,
  174. std::function<bool (const typename Base::Value &)> falsifiabilityTest):
  175. PossibilityVisitor<ContainedClass>(satisfiabilityTest, falsifiabilityTest)
  176. {
  177. this->setFalsifiabilityVisitor(this);
  178. }
  179. bool operator()(const typename Base::OperatorAny & element) const
  180. {
  181. return this->countFalsifiable(element.expressions) == element.expressions.size();
  182. }
  183. bool operator()(const typename Base::OperatorAll & element) const
  184. {
  185. return this->countFalsifiable(element.expressions) != 0;
  186. }
  187. bool operator()(const typename Base::OperatorNone & element) const
  188. {
  189. return this->countSatisfiable(element.expressions) != 0;
  190. }
  191. bool operator()(const typename Base::Value & element) const
  192. {
  193. return this->falsifiabilityTest(element);
  194. }
  195. };
  196. /// visitor that is trying to generates candidates that must be fulfilled
  197. /// to complete this expression
  198. template <typename ContainedClass>
  199. class CandidatesVisitor : public boost::static_visitor<std::vector<ContainedClass> >
  200. {
  201. typedef ExpressionBase<ContainedClass> Base;
  202. typedef std::vector<typename Base::Value> TValueList;
  203. TestVisitor<ContainedClass> classTest;
  204. public:
  205. CandidatesVisitor(std::function<bool(const typename Base::Value &)> classTest):
  206. classTest(classTest)
  207. {}
  208. TValueList operator()(const typename Base::OperatorAny & element) const
  209. {
  210. TValueList ret;
  211. if (!classTest(element))
  212. {
  213. for (auto & elem : element.expressions)
  214. boost::range::copy(boost::apply_visitor(*this, elem), std::back_inserter(ret));
  215. }
  216. return ret;
  217. }
  218. TValueList operator()(const typename Base::OperatorAll & element) const
  219. {
  220. TValueList ret;
  221. if (!classTest(element))
  222. {
  223. for (auto & elem : element.expressions)
  224. boost::range::copy(boost::apply_visitor(*this, elem), std::back_inserter(ret));
  225. }
  226. return ret;
  227. }
  228. TValueList operator()(const typename Base::OperatorNone & element) const
  229. {
  230. return TValueList(); //TODO. Implementing this one is not straightforward, if ever possible
  231. }
  232. TValueList operator()(const typename Base::Value & element) const
  233. {
  234. if (classTest(element))
  235. return TValueList();
  236. else
  237. return TValueList(1, element);
  238. }
  239. };
  240. /// Simple foreach visitor
  241. template <typename ContainedClass>
  242. class ForEachVisitor : public boost::static_visitor<typename ExpressionBase<ContainedClass>::Variant>
  243. {
  244. typedef ExpressionBase<ContainedClass> Base;
  245. std::function<typename Base::Variant(const typename Base::Value &)> visitor;
  246. public:
  247. ForEachVisitor(std::function<typename Base::Variant(const typename Base::Value &)> visitor):
  248. visitor(visitor)
  249. {}
  250. typename Base::Variant operator()(const typename Base::Value & element) const
  251. {
  252. return visitor(element);
  253. }
  254. template <typename Type>
  255. typename Base::Variant operator()(Type element) const
  256. {
  257. for (auto & entry : element.expressions)
  258. entry = boost::apply_visitor(*this, entry);
  259. return element;
  260. }
  261. };
  262. /// Minimizing visitor that removes all redundant elements from variant (e.g. AllOf inside another AllOf can be merged safely)
  263. template <typename ContainedClass>
  264. class MinimizingVisitor : public boost::static_visitor<typename ExpressionBase<ContainedClass>::Variant>
  265. {
  266. typedef ExpressionBase<ContainedClass> Base;
  267. public:
  268. typename Base::Variant operator()(const typename Base::Value & element) const
  269. {
  270. return element;
  271. }
  272. template <typename Type>
  273. typename Base::Variant operator()(const Type & element) const
  274. {
  275. Type ret;
  276. for (auto & entryRO : element.expressions)
  277. {
  278. auto entry = boost::apply_visitor(*this, entryRO);
  279. try
  280. {
  281. // copy entries from child of this type
  282. auto sublist = boost::get<Type>(entry).expressions;
  283. std::move(sublist.begin(), sublist.end(), std::back_inserter(ret.expressions));
  284. }
  285. catch (boost::bad_get &)
  286. {
  287. // different type (e.g. allOf vs oneOf) just copy
  288. ret.expressions.push_back(entry);
  289. }
  290. }
  291. for ( auto it = ret.expressions.begin(); it != ret.expressions.end();)
  292. {
  293. if (std::find(ret.expressions.begin(), it, *it) != it)
  294. it = ret.expressions.erase(it); // erase duplicate
  295. else
  296. it++; // goto next
  297. }
  298. return ret;
  299. }
  300. };
  301. /// Json parser for expressions
  302. template <typename ContainedClass>
  303. class Reader
  304. {
  305. typedef ExpressionBase<ContainedClass> Base;
  306. std::function<typename Base::Value(const JsonNode &)> classParser;
  307. typename Base::Variant readExpression(const JsonNode & node)
  308. {
  309. assert(!node.Vector().empty());
  310. std::string type = node.Vector()[0].String();
  311. if (type == "anyOf")
  312. return typename Base::OperatorAny(readVector(node));
  313. if (type == "allOf")
  314. return typename Base::OperatorAll(readVector(node));
  315. if (type == "noneOf")
  316. return typename Base::OperatorNone(readVector(node));
  317. return classParser(node);
  318. }
  319. std::vector<typename Base::Variant> readVector(const JsonNode & node)
  320. {
  321. std::vector<typename Base::Variant> ret;
  322. ret.reserve(node.Vector().size()-1);
  323. for (size_t i=1; i < node.Vector().size(); i++)
  324. ret.push_back(readExpression(node.Vector()[i]));
  325. return ret;
  326. }
  327. public:
  328. Reader(std::function<typename Base::Value(const JsonNode &)> classParser):
  329. classParser(classParser)
  330. {}
  331. typename Base::Variant operator ()(const JsonNode & node)
  332. {
  333. return readExpression(node);
  334. }
  335. };
  336. /// Serializes expression in JSON format. Part of map format.
  337. template <typename ContainedClass>
  338. class Writer : public boost::static_visitor<JsonNode>
  339. {
  340. typedef ExpressionBase<ContainedClass> Base;
  341. std::function<JsonNode(const typename Base::Value &)> classPrinter;
  342. JsonNode printExpressionList(std::string name, const std::vector<typename Base::Variant> & element) const
  343. {
  344. JsonNode ret;
  345. ret.Vector().resize(1);
  346. ret.Vector().back().String() = name;
  347. for (auto & expr : element)
  348. ret.Vector().push_back(boost::apply_visitor(*this, expr));
  349. return ret;
  350. }
  351. public:
  352. Writer(std::function<JsonNode(const typename Base::Value &)> classPrinter):
  353. classPrinter(classPrinter)
  354. {}
  355. JsonNode operator()(const typename Base::OperatorAny & element) const
  356. {
  357. return printExpressionList("anyOf", element.expressions);
  358. }
  359. JsonNode operator()(const typename Base::OperatorAll & element) const
  360. {
  361. return printExpressionList("allOf", element.expressions);
  362. }
  363. JsonNode operator()(const typename Base::OperatorNone & element) const
  364. {
  365. return printExpressionList("noneOf", element.expressions);
  366. }
  367. JsonNode operator()(const typename Base::Value & element) const
  368. {
  369. return classPrinter(element);
  370. }
  371. };
  372. std::string DLL_LINKAGE getTextForOperator(std::string operation);
  373. /// Prints expression in human-readable format
  374. template <typename ContainedClass>
  375. class Printer : public boost::static_visitor<std::string>
  376. {
  377. typedef ExpressionBase<ContainedClass> Base;
  378. std::function<std::string(const typename Base::Value &)> classPrinter;
  379. std::unique_ptr<TestVisitor<ContainedClass>> statusTest;
  380. mutable std::string prefix;
  381. template<typename Operator>
  382. std::string formatString(std::string toFormat, const Operator & expr) const
  383. {
  384. // highlight not fulfilled expressions, if pretty formatting is on
  385. if (statusTest && !(*statusTest)(expr))
  386. return "{" + toFormat + "}";
  387. return toFormat;
  388. }
  389. std::string printExpressionList(const std::vector<typename Base::Variant> & element) const
  390. {
  391. std::string ret;
  392. prefix.push_back('\t');
  393. for (auto & expr : element)
  394. ret += prefix + boost::apply_visitor(*this, expr) + "\n";
  395. prefix.pop_back();
  396. return ret;
  397. }
  398. public:
  399. Printer(std::function<std::string(const typename Base::Value &)> classPrinter):
  400. classPrinter(classPrinter)
  401. {}
  402. Printer(std::function<std::string(const typename Base::Value &)> classPrinter, std::function<bool(const typename Base::Value &)> toBool):
  403. classPrinter(classPrinter),
  404. statusTest(new TestVisitor<ContainedClass>(toBool))
  405. {}
  406. std::string operator()(const typename Base::OperatorAny & element) const
  407. {
  408. return formatString(getTextForOperator("anyOf"), element) + "\n"
  409. + printExpressionList(element.expressions);
  410. }
  411. std::string operator()(const typename Base::OperatorAll & element) const
  412. {
  413. return formatString(getTextForOperator("allOf"), element) + "\n"
  414. + printExpressionList(element.expressions);
  415. }
  416. std::string operator()(const typename Base::OperatorNone & element) const
  417. {
  418. return formatString(getTextForOperator("noneOf"), element) + "\n"
  419. + printExpressionList(element.expressions);
  420. }
  421. std::string operator()(const typename Base::Value & element) const
  422. {
  423. return formatString(classPrinter(element), element);
  424. }
  425. };
  426. }
  427. ///
  428. /// Class for evaluation of logical expressions generated in runtime
  429. ///
  430. template<typename ContainedClass>
  431. class LogicalExpression
  432. {
  433. typedef LogicalExpressionDetail::ExpressionBase<ContainedClass> Base;
  434. public:
  435. /// Type of values used in expressions, same as ContainedClass
  436. typedef typename Base::Value Value;
  437. /// Operators for use in expressions, all include vectors with operands
  438. typedef typename Base::OperatorAny OperatorAny;
  439. typedef typename Base::OperatorAll OperatorAll;
  440. typedef typename Base::OperatorNone OperatorNone;
  441. /// one expression entry
  442. typedef typename Base::Variant Variant;
  443. private:
  444. Variant data;
  445. public:
  446. /// Base constructor
  447. LogicalExpression()
  448. {}
  449. /// Constructor from variant or (implicitly) from Operator* types
  450. LogicalExpression(const Variant & data):
  451. data(data)
  452. {
  453. }
  454. /// Constructor that receives JsonNode as input and function that can parse Value instances
  455. LogicalExpression(const JsonNode & input, std::function<Value(const JsonNode &)> parser)
  456. {
  457. LogicalExpressionDetail::Reader<Value> reader(parser);
  458. LogicalExpression expr(reader(input));
  459. std::swap(data, expr.data);
  460. }
  461. Variant get() const
  462. {
  463. return data;
  464. }
  465. /// Simple visitor that visits all entries in expression
  466. Variant morph(std::function<Variant(const Value &)> morpher) const
  467. {
  468. LogicalExpressionDetail::ForEachVisitor<Value> visitor(morpher);
  469. return boost::apply_visitor(visitor, data);
  470. }
  471. /// Minimizes expression, removing any redundant elements
  472. void minimize()
  473. {
  474. LogicalExpressionDetail::MinimizingVisitor<Value> visitor;
  475. data = boost::apply_visitor(visitor, data);
  476. }
  477. /// calculates if expression evaluates to "true".
  478. /// Note: empty expressions always return true
  479. bool test(std::function<bool(const Value &)> toBool) const
  480. {
  481. LogicalExpressionDetail::TestVisitor<Value> testVisitor(toBool);
  482. return boost::apply_visitor(testVisitor, data);
  483. }
  484. /// calculates if expression can evaluate to "true".
  485. bool satisfiable(std::function<bool(const Value &)> satisfiabilityTest, std::function<bool(const Value &)> falsifiabilityTest) const
  486. {
  487. LogicalExpressionDetail::SatisfiabilityVisitor<Value> satisfiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
  488. LogicalExpressionDetail::FalsifiabilityVisitor<Value> falsifiabilityVisitor(satisfiabilityTest, falsifiabilityTest);
  489. satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor);
  490. falsifiabilityVisitor.setSatisfiabilityVisitor(&satisfiabilityVisitor);
  491. return boost::apply_visitor(satisfiabilityVisitor, data);
  492. }
  493. /// calculates if expression can evaluate to "false".
  494. bool falsifiable(std::function<bool(const Value &)> satisfiabilityTest, std::function<bool(const Value &)> falsifiabilityTest) const
  495. {
  496. LogicalExpressionDetail::SatisfiabilityVisitor<Value> satisfiabilityVisitor(satisfiabilityTest);
  497. LogicalExpressionDetail::FalsifiabilityVisitor<Value> falsifiabilityVisitor(falsifiabilityTest);
  498. satisfiabilityVisitor.setFalsifiabilityVisitor(&falsifiabilityVisitor);
  499. falsifiabilityVisitor.setFalsifiabilityVisitor(&satisfiabilityVisitor);
  500. return boost::apply_visitor(falsifiabilityVisitor, data);
  501. }
  502. /// generates list of candidates that can be fulfilled by caller (like AI)
  503. std::vector<Value> getFulfillmentCandidates(std::function<bool(const Value &)> toBool) const
  504. {
  505. LogicalExpressionDetail::CandidatesVisitor<Value> candidateVisitor(toBool);
  506. return boost::apply_visitor(candidateVisitor, data);
  507. }
  508. /// Converts expression in human-readable form
  509. /// Second version will try to do some pretty printing using H3 text formatting "{}"
  510. /// to indicate fulfilled components of an expression
  511. std::string toString(std::function<std::string(const Value &)> toStr) const
  512. {
  513. LogicalExpressionDetail::Printer<Value> printVisitor(toStr);
  514. return boost::apply_visitor(printVisitor, data);
  515. }
  516. std::string toString(std::function<std::string(const Value &)> toStr, std::function<bool(const Value &)> toBool) const
  517. {
  518. LogicalExpressionDetail::Printer<Value> printVisitor(toStr, toBool);
  519. return boost::apply_visitor(printVisitor, data);
  520. }
  521. JsonNode toJson(std::function<JsonNode(const Value &)> toJson) const
  522. {
  523. LogicalExpressionDetail::Writer<Value> writeVisitor(toJson);
  524. return boost::apply_visitor(writeVisitor, data);
  525. }
  526. template <typename Handler>
  527. void serialize(Handler & h, const int version)
  528. {
  529. h & data;
  530. }
  531. };