IterationFormula.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include "IterationFormula.h"
  2. #include <sstream>
  3. #include <vector>
  4. #include <stack>
  5. #include <regex>
  6. #include <optional>
  7. using mnd::ParseError;
  8. mnd::IterationFormula::IterationFormula(std::unique_ptr<Expression> expr, const std::vector<std::string>& variables) :
  9. expr{ std::move(expr) },
  10. variables{ variables }
  11. {
  12. this->variables.push_back("i");
  13. auto maybeUnknown = findUnknownVariables(*this->expr);
  14. if (maybeUnknown.has_value()) {
  15. throw ParseError(std::string("unknown variable: ") + maybeUnknown.value());
  16. }
  17. }
  18. mnd::IterationFormula::IterationFormula(mnd::Expression expr, const std::vector<std::string>& variables) :
  19. IterationFormula{ std::make_unique<mnd::Expression>(std::move(expr)), variables }
  20. {
  21. }
  22. struct SimpleOptimizer
  23. {
  24. using Ret = std::optional<mnd::Expression>;
  25. void visitExpr(std::unique_ptr<mnd::Expression>& expr)
  26. {
  27. Ret replacement = std::visit(*this, *expr);
  28. if (replacement.has_value()) {
  29. expr = std::make_unique<mnd::Expression>(std::move(replacement.value()));
  30. }
  31. }
  32. Ret operator() (mnd::Constant& c)
  33. {
  34. return std::nullopt;
  35. }
  36. Ret operator() (mnd::Variable& v)
  37. {
  38. if (v.name == "i") {
  39. return mnd::Constant{ 0.0, 1.0 };
  40. }
  41. else {
  42. return std::nullopt;
  43. }
  44. }
  45. Ret operator() (mnd::Negation& n)
  46. {
  47. visitExpr(n.operand);
  48. auto* valConst = std::get_if<mnd::Constant>(n.operand.get());
  49. if (valConst) {
  50. return mnd::Constant {
  51. -valConst->re,
  52. -valConst->im
  53. };
  54. }
  55. return std::nullopt;
  56. }
  57. Ret operator() (mnd::Addition& a)
  58. {
  59. visitExpr(a.left);
  60. visitExpr(a.right);
  61. auto* leftConst = std::get_if<mnd::Constant>(a.left.get());
  62. auto* rightConst = std::get_if<mnd::Constant>(a.right.get());
  63. if (leftConst && rightConst) {
  64. if (a.subtraction) {
  65. return mnd::Constant {
  66. leftConst->re - rightConst->re,
  67. leftConst->im - rightConst->im
  68. };
  69. }
  70. else {
  71. return mnd::Constant{
  72. leftConst->re + rightConst->re,
  73. leftConst->im + rightConst->im
  74. };
  75. }
  76. }
  77. return std::nullopt;
  78. }
  79. Ret operator() (mnd::Multiplication& a)
  80. {
  81. visitExpr(a.left);
  82. visitExpr(a.right);
  83. auto* leftConst = std::get_if<mnd::Constant>(a.left.get());
  84. auto* rightConst = std::get_if<mnd::Constant>(a.right.get());
  85. if (leftConst && rightConst) {
  86. return mnd::Constant {
  87. leftConst->re * rightConst->re - leftConst->im * rightConst->im,
  88. (leftConst->re * rightConst->im + leftConst->im * rightConst->re) * 2
  89. };
  90. }
  91. return std::nullopt;
  92. }
  93. Ret operator() (mnd::Division& a)
  94. {
  95. visitExpr(a.left);
  96. visitExpr(a.right);
  97. auto* leftConst = std::get_if<mnd::Constant>(a.left.get());
  98. auto* rightConst = std::get_if<mnd::Constant>(a.right.get());
  99. if (leftConst && rightConst) {
  100. return mnd::Constant {
  101. (leftConst->re * rightConst->re + leftConst->im * rightConst->im) /
  102. (rightConst->re * rightConst->re + rightConst->im * rightConst->im),
  103. (leftConst->im * rightConst->re - leftConst->re * rightConst->im) /
  104. (rightConst->re * rightConst->re + rightConst->im * rightConst->im)
  105. };
  106. }
  107. return std::nullopt;
  108. }
  109. Ret operator() (mnd::Pow& a)
  110. {
  111. visitExpr(a.left);
  112. visitExpr(a.right);
  113. auto* leftConst = std::get_if<mnd::Constant>(a.left.get());
  114. auto* rightConst = std::get_if<mnd::Constant>(a.right.get());
  115. if (rightConst) {
  116. if (rightConst->im == 0) {
  117. a.realExponent = true;
  118. if (int(rightConst->re) == rightConst->re) {
  119. a.integerExponent = true;
  120. }
  121. }
  122. }
  123. return std::nullopt;
  124. }
  125. };
  126. std::optional<std::string> mnd::IterationFormula::findUnknownVariables(const Expression& expr)
  127. {
  128. std::string unknownVariable;
  129. std::function<bool(const Expression&)> isCorrect;
  130. auto corrLambda = [this, &isCorrect, &unknownVariable](const auto& x) {
  131. using T = std::decay_t<decltype(x)>;
  132. if constexpr (std::is_same<T, mnd::Variable>::value) {
  133. if (containsVariable(x.name)) {
  134. return true;
  135. }
  136. else {
  137. unknownVariable = x.name;
  138. return false;
  139. }
  140. }
  141. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  142. return isCorrect(*x.operand);
  143. }
  144. else if constexpr (std::is_same<T, mnd::Addition>::value ||
  145. std::is_same<T, mnd::Multiplication>::value ||
  146. std::is_same<T, mnd::Division>::value ||
  147. std::is_same<T, mnd::Pow>::value) {
  148. return isCorrect(*x.left) && isCorrect(*x.right);
  149. }
  150. return true;
  151. };
  152. isCorrect = [corrLambda](const mnd::Expression& x) {
  153. return std::visit(corrLambda, x);
  154. };
  155. bool allCorrect = isCorrect(expr);
  156. if (allCorrect) {
  157. return std::nullopt;
  158. }
  159. else {
  160. return unknownVariable;
  161. }
  162. }
  163. void mnd::IterationFormula::optimize(void)
  164. {
  165. SimpleOptimizer so;
  166. so.visitExpr(this->expr);
  167. }
  168. bool mnd::IterationFormula::containsVariable(const std::string& name) const
  169. {
  170. for (const auto& varname : variables) {
  171. if (varname == name)
  172. return true;
  173. }
  174. return false;
  175. }
  176. mnd::IterationFormula mnd::IterationFormula::clone(void) const
  177. {
  178. std::function<std::unique_ptr<mnd::Expression>(const mnd::Expression&)> cloner;
  179. cloner = [&cloner](const mnd::Expression& e) {
  180. return std::make_unique<mnd::Expression>(std::visit([&cloner](const auto& x) -> mnd::Expression {
  181. using T = std::decay_t<decltype(x)>;
  182. if constexpr (std::is_same<T, mnd::Constant>::value) {
  183. return x;
  184. }
  185. else if constexpr (std::is_same<T, mnd::Variable>::value) {
  186. return mnd::Variable{ x.name };
  187. }
  188. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  189. return mnd::Negation{ cloner(*x.operand) };
  190. }
  191. else if constexpr (std::is_same<T, mnd::Addition>::value) {
  192. return mnd::Addition{ cloner(*x.left), cloner(*x.right), x.subtraction };
  193. }
  194. else {
  195. return T{ cloner(*x.left), cloner(*x.right) };
  196. }
  197. }, e));
  198. };
  199. IterationFormula cl{ cloner(*expr), this->variables };
  200. return cl;
  201. }
  202. static const std::string regexIdent = "[A-Za-z][A-Za-z0-9]*";
  203. static const std::string regexNum = "[1-9][0-9]*";
  204. static const std::string regexFloat = "(\\d*\\.?\\d+|\\d+\\.?\\d*)([eE][-+]\\d+)?";
  205. class Parser
  206. {
  207. static const std::regex tokenize;
  208. static const std::regex ident;
  209. static const std::regex num;
  210. static const std::regex floatNum;
  211. std::string in;
  212. std::regex_iterator<std::string::iterator> rit;
  213. std::vector<std::string> tokens;
  214. std::stack<char> operators;
  215. std::vector<mnd::Expression> output;
  216. bool expectingBinaryOperator;
  217. public:
  218. Parser(const std::string& s) :
  219. in{ s },
  220. rit{ in.begin(), in.end(), tokenize },
  221. expectingBinaryOperator{ false }
  222. {}
  223. void parse(void)
  224. {
  225. std::string token;
  226. while (getToken(token)) {
  227. if (std::regex_match(token, num) || std::regex_match(token, floatNum)) {
  228. output.push_back(mnd::Constant{ std::atof(token.c_str()) });
  229. expectingBinaryOperator = true;
  230. }
  231. else if (std::regex_match(token, ident)) {
  232. output.push_back(mnd::Variable{ token });
  233. expectingBinaryOperator = true;
  234. }
  235. else if (token == "+" || token == "-") {
  236. if (expectingBinaryOperator) {
  237. while (!operators.empty() && getTopPrecedence() >= 1) {
  238. popOperator();
  239. }
  240. operators.push(token[0]);
  241. expectingBinaryOperator = false;
  242. }
  243. else { // unary op
  244. if (token == "-")
  245. operators.push('m');
  246. else
  247. throw ParseError("unary '+' is not allowed");
  248. }
  249. }
  250. else if (token == "*" || token == "/") {
  251. while (!operators.empty() && getTopPrecedence() >= 2) {
  252. popOperator();
  253. }
  254. operators.push(token[0]);
  255. expectingBinaryOperator = false;
  256. }
  257. else if (token == "^") {
  258. while (!operators.empty() && getTopPrecedence() > 3) {
  259. popOperator();
  260. }
  261. operators.push(token[0]);
  262. expectingBinaryOperator = false;
  263. }
  264. else if (token == "(") {
  265. operators.push(token[0]);
  266. expectingBinaryOperator = false;
  267. }
  268. else if (token == ")") {
  269. while (operators.top() != '(') {
  270. popOperator();
  271. }
  272. operators.pop();
  273. expectingBinaryOperator = true;
  274. }
  275. }
  276. while (!operators.empty())
  277. popOperator();
  278. }
  279. mnd::Expression& getExpression(void) {
  280. return output[0];
  281. }
  282. void popOperator(void) {
  283. if (operators.empty()) {
  284. throw ParseError("error parsing expression");
  285. }
  286. char top = operators.top();
  287. operators.pop();
  288. if (output.size() < 1) {
  289. throw ParseError("not enough operands");
  290. }
  291. mnd::Expression& unaryOperand = output.at(output.size() - 1);
  292. // handle unary minus separately
  293. if (top == 'm') {
  294. auto neg = mnd::Negation{ std::make_unique<mnd::Expression>(std::move(unaryOperand)) };
  295. output.pop_back();
  296. output.push_back(std::move(neg));
  297. return;
  298. }
  299. if (output.size() < 2) {
  300. throw ParseError(std::string("not enough operands for operator '") + top + "'");
  301. }
  302. mnd::Expression& left = output.at(output.size() - 2);
  303. mnd::Expression& right = output.at(output.size() - 1);
  304. mnd::Expression newExpr = mnd::Constant{ 0.0 };
  305. if (top == '+' || top == '-') {
  306. newExpr = mnd::Addition {
  307. std::make_unique<mnd::Expression>(std::move(left)),
  308. std::make_unique<mnd::Expression>(std::move(right)),
  309. top == '-'
  310. };
  311. }
  312. else if (top == '*') {
  313. newExpr = mnd::Multiplication {
  314. std::make_unique<mnd::Expression>(std::move(left)),
  315. std::make_unique<mnd::Expression>(std::move(right))
  316. };
  317. }
  318. else if (top == '/') {
  319. newExpr = mnd::Division {
  320. std::make_unique<mnd::Expression>(std::move(left)),
  321. std::make_unique<mnd::Expression>(std::move(right))
  322. };
  323. }
  324. else if (top == '^') {
  325. newExpr = mnd::Pow {
  326. std::make_unique<mnd::Expression>(std::move(left)),
  327. std::make_unique<mnd::Expression>(std::move(right))
  328. };
  329. }
  330. else {
  331. throw ParseError(std::string("not a valid operator: ") + top);
  332. }
  333. output.pop_back();
  334. output.pop_back();
  335. output.push_back(std::move(newExpr));
  336. }
  337. int getTopPrecedence(void) const {
  338. return getPrecedence(operators.top());
  339. }
  340. int getPrecedence(char op) const {
  341. char t = op;
  342. if (t == '+' || t == '-')
  343. return 1;
  344. else if (t == '*' || t == '/')
  345. return 2;
  346. else if (t == '^' || t == 'm') // 'm' == unary minus
  347. return 3;
  348. return 0;
  349. }
  350. private:
  351. bool getToken(std::string& token)
  352. {
  353. if (rit != std::regex_iterator<std::string::iterator>()) {
  354. token = rit->str();
  355. ++rit;
  356. return true;
  357. }
  358. return false;
  359. }
  360. };
  361. const std::regex Parser::tokenize = std::regex(regexIdent + "|" + regexFloat + "|[\\+\\-\\*/\\^]|[\\(\\)]");
  362. const std::regex Parser::ident = std::regex(regexIdent);
  363. const std::regex Parser::num = std::regex(regexNum);
  364. const std::regex Parser::floatNum = std::regex(regexFloat);
  365. namespace mnd
  366. {
  367. Expression parse(const std::string& formula)
  368. {
  369. Parser p(formula);
  370. p.parse();
  371. mnd::Expression& res = p.getExpression();
  372. //printf("expr: %s\n", toString(res).c_str());
  373. return std::move(res);
  374. }
  375. std::string toString(const mnd::Expression& expr)
  376. {
  377. return std::visit([] (auto&& ex) -> std::string {
  378. std::stringstream ss;
  379. using T = std::decay_t<decltype(ex)>;
  380. if constexpr (std::is_same<T, mnd::Constant>::value) {
  381. ss << "const[" << ex.re << "+" << ex.im << "i" << "]";
  382. return ss.str();
  383. }
  384. else if constexpr (std::is_same<T, mnd::Variable>::value) {
  385. return std::string("var[") + ex.name + "]";
  386. }
  387. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  388. return std::string("-(") + toString(*ex.operand) + ")";
  389. }
  390. else if constexpr (std::is_same<T, mnd::Addition>::value) {
  391. return std::string("(") + toString(*ex.left) + std::string(") + (") + toString(*ex.right) + ")";
  392. }
  393. else if constexpr (std::is_same<T, mnd::Multiplication>::value) {
  394. return std::string("(") + toString(*ex.left) + std::string(") * (") + toString(*ex.right) + ")";
  395. }
  396. else if constexpr (std::is_same<T, mnd::Division>::value) {
  397. return std::string("(") + toString(*ex.left) + std::string(") / (") + toString(*ex.right) + ")";
  398. }
  399. else if constexpr (std::is_same<T, mnd::Pow>::value) {
  400. return std::string("(") + toString(*ex.left) + std::string(") ^ (") + toString(*ex.right) + ")";
  401. }
  402. return "";
  403. }, expr);
  404. }
  405. }