LogicalExpression.h 18 KB

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