1
0

IterationFormula.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. // TODO implement
  98. return std::nullopt;
  99. }
  100. Ret operator() (mnd::Pow& a)
  101. {
  102. visitExpr(a.left);
  103. visitExpr(a.right);
  104. auto* leftConst = std::get_if<mnd::Constant>(a.left.get());
  105. auto* rightConst = std::get_if<mnd::Constant>(a.right.get());
  106. if (rightConst) {
  107. if (rightConst->im == 0) {
  108. a.realExponent = true;
  109. if (int(rightConst->re) == rightConst->re) {
  110. a.integerExponent = true;
  111. }
  112. }
  113. }
  114. return std::nullopt;
  115. }
  116. };
  117. std::optional<std::string> mnd::IterationFormula::findUnknownVariables(const Expression& expr)
  118. {
  119. std::string unknownVariable;
  120. std::function<bool(const Expression&)> isCorrect;
  121. auto corrLambda = [this, &isCorrect, &unknownVariable](const auto& x) {
  122. using T = std::decay_t<decltype(x)>;
  123. if constexpr (std::is_same<T, mnd::Variable>::value) {
  124. if (containsVariable(x.name)) {
  125. return true;
  126. }
  127. else {
  128. unknownVariable = x.name;
  129. return false;
  130. }
  131. }
  132. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  133. return isCorrect(*x.operand);
  134. }
  135. else if constexpr (std::is_same<T, mnd::Addition>::value ||
  136. std::is_same<T, mnd::Multiplication>::value ||
  137. std::is_same<T, mnd::Division>::value ||
  138. std::is_same<T, mnd::Pow>::value) {
  139. return isCorrect(*x.left) && isCorrect(*x.right);
  140. }
  141. return true;
  142. };
  143. isCorrect = [corrLambda](const mnd::Expression& x) {
  144. return std::visit(corrLambda, x);
  145. };
  146. bool allCorrect = isCorrect(expr);
  147. if (allCorrect) {
  148. return std::nullopt;
  149. }
  150. else {
  151. return unknownVariable;
  152. }
  153. }
  154. void mnd::IterationFormula::optimize(void)
  155. {
  156. SimpleOptimizer so;
  157. so.visitExpr(this->expr);
  158. }
  159. bool mnd::IterationFormula::containsVariable(const std::string& name) const
  160. {
  161. for (const auto& varname : variables) {
  162. if (varname == name)
  163. return true;
  164. }
  165. return false;
  166. }
  167. mnd::IterationFormula mnd::IterationFormula::clone(void) const
  168. {
  169. std::function<std::unique_ptr<mnd::Expression>(const mnd::Expression&)> cloner;
  170. cloner = [&cloner](const mnd::Expression& e) {
  171. return std::make_unique<mnd::Expression>(std::visit([&cloner](const auto& x) -> mnd::Expression {
  172. using T = std::decay_t<decltype(x)>;
  173. if constexpr (std::is_same<T, mnd::Constant>::value) {
  174. return x;
  175. }
  176. else if constexpr (std::is_same<T, mnd::Variable>::value) {
  177. return mnd::Variable{ x.name };
  178. }
  179. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  180. return mnd::Negation{ cloner(*x.operand) };
  181. }
  182. else {
  183. return T{ cloner(*x.left), cloner(*x.right) };
  184. }
  185. }, e));
  186. };
  187. IterationFormula cl{ cloner(*expr), this->variables };
  188. return cl;
  189. }
  190. static const std::string regexIdent = "[A-Za-z][A-Za-z0-9]*";
  191. static const std::string regexNum = "[1-9][0-9]*";
  192. static const std::string regexFloat = "(\\d*\\.?\\d+|\\d+\\.?\\d*)([eE][-+]\\d+)?";
  193. class Parser
  194. {
  195. static const std::regex tokenize;
  196. static const std::regex ident;
  197. static const std::regex num;
  198. static const std::regex floatNum;
  199. std::string in;
  200. std::regex_iterator<std::string::iterator> rit;
  201. std::vector<std::string> tokens;
  202. std::stack<char> operators;
  203. std::vector<mnd::Expression> output;
  204. public:
  205. Parser(const std::string& s) :
  206. in{ s },
  207. rit{ in.begin(), in.end(), tokenize }
  208. {}
  209. void parse(void)
  210. {
  211. std::string token;
  212. bool unary = true;
  213. while (getToken(token)) {
  214. if (std::regex_match(token, num)) {
  215. output.push_back(mnd::Constant{ std::atof(token.c_str()) });
  216. }
  217. else if (std::regex_match(token, floatNum)) {
  218. output.push_back(mnd::Constant{ std::atof(token.c_str()) });
  219. }
  220. else if (std::regex_match(token, ident)) {
  221. output.push_back(mnd::Variable{ token });
  222. }
  223. else if (token == "+" || token == "-") {
  224. while (!operators.empty() && getTopPrecedence() >= 1) {
  225. popOperator();
  226. }
  227. operators.push(token[0]);
  228. }
  229. else if (token == "*" || token == "/") {
  230. while (!operators.empty() && getTopPrecedence() >= 2) {
  231. popOperator();
  232. }
  233. operators.push(token[0]);
  234. }
  235. else if (token == "^") {
  236. while (!operators.empty() && getTopPrecedence() > 3) {
  237. popOperator();
  238. }
  239. operators.push(token[0]);
  240. }
  241. else if (token == "(") {
  242. operators.push(token[0]);
  243. }
  244. else if (token == ")") {
  245. while (operators.top() != '(') {
  246. popOperator();
  247. }
  248. operators.pop();
  249. }
  250. }
  251. while (!operators.empty())
  252. popOperator();
  253. }
  254. mnd::Expression& getExpression(void) {
  255. return output[0];
  256. }
  257. void popOperator(void) {
  258. if (operators.empty()) {
  259. throw ParseError("error parsing expression");
  260. }
  261. char top = operators.top();
  262. if (output.size() < 2) {
  263. throw ParseError(std::string("not enough operands for operator '") + top + "'");
  264. }
  265. operators.pop();
  266. mnd::Expression& left = output.at(output.size() - 2);
  267. mnd::Expression& right = output.at(output.size() - 1);
  268. mnd::Expression newExpr = mnd::Constant{ 0.0 };
  269. if (top == '+' || top == '-') {
  270. newExpr = mnd::Addition {
  271. std::make_unique<mnd::Expression>(std::move(left)),
  272. std::make_unique<mnd::Expression>(std::move(right)),
  273. top == '-'
  274. };
  275. }
  276. else if (top == '*') {
  277. newExpr = mnd::Multiplication {
  278. std::make_unique<mnd::Expression>(std::move(left)),
  279. std::make_unique<mnd::Expression>(std::move(right))
  280. };
  281. }
  282. else if (top == '/') {
  283. newExpr = mnd::Division {
  284. std::make_unique<mnd::Expression>(std::move(left)),
  285. std::make_unique<mnd::Expression>(std::move(right))
  286. };
  287. }
  288. else if (top == '^') {
  289. newExpr = mnd::Pow {
  290. std::make_unique<mnd::Expression>(std::move(left)),
  291. std::make_unique<mnd::Expression>(std::move(right))
  292. };
  293. }
  294. else {
  295. throw ParseError(std::string("not a valid operator: ") + top);
  296. }
  297. output.pop_back();
  298. output.pop_back();
  299. output.push_back(std::move(newExpr));
  300. }
  301. int getTopPrecedence(void) const {
  302. return getPrecedence(operators.top());
  303. }
  304. int getPrecedence(char op) const {
  305. char t = op;
  306. if (t == '+' || t == '-')
  307. return 1;
  308. else if (t == '*' || t == '/')
  309. return 2;
  310. else if (t == '^')
  311. return 3;
  312. return 0;
  313. }
  314. private:
  315. bool getToken(std::string& token)
  316. {
  317. if (rit != std::regex_iterator<std::string::iterator>()) {
  318. token = rit->str();
  319. ++rit;
  320. return true;
  321. }
  322. return false;
  323. }
  324. };
  325. const std::regex Parser::tokenize = std::regex(regexIdent + "|" + regexFloat + "|[\\+\\-\\*/\\^]|[\\(\\)]");
  326. const std::regex Parser::ident = std::regex(regexIdent);
  327. const std::regex Parser::num = std::regex(regexNum);
  328. const std::regex Parser::floatNum = std::regex(regexFloat);
  329. namespace mnd
  330. {
  331. Expression parse(const std::string& formula)
  332. {
  333. Parser p(formula);
  334. p.parse();
  335. mnd::Expression& res = p.getExpression();
  336. //printf("expr: %s\n", toString(res).c_str());
  337. return std::move(res);
  338. }
  339. std::string toString(const mnd::Expression& expr)
  340. {
  341. return std::visit([] (auto&& ex) -> std::string {
  342. std::stringstream ss;
  343. using T = std::decay_t<decltype(ex)>;
  344. if constexpr (std::is_same<T, mnd::Constant>::value) {
  345. ss << "const[" << ex.re << "+" << ex.im << "i" << "]";
  346. return ss.str();
  347. }
  348. else if constexpr (std::is_same<T, mnd::Variable>::value) {
  349. return std::string("var[") + ex.name + "]";
  350. }
  351. else if constexpr (std::is_same<T, mnd::Negation>::value) {
  352. return std::string("-(") + toString(*ex.operand) + ")";
  353. }
  354. else if constexpr (std::is_same<T, mnd::Addition>::value) {
  355. return std::string("(") + toString(*ex.left) + std::string(") + (") + toString(*ex.right) + ")";
  356. }
  357. else if constexpr (std::is_same<T, mnd::Multiplication>::value) {
  358. return std::string("(") + toString(*ex.left) + std::string(") * (") + toString(*ex.right) + ")";
  359. }
  360. else if constexpr (std::is_same<T, mnd::Division>::value) {
  361. return std::string("(") + toString(*ex.left) + std::string(") / (") + toString(*ex.right) + ")";
  362. }
  363. else if constexpr (std::is_same<T, mnd::Pow>::value) {
  364. return std::string("(") + toString(*ex.left) + std::string(") ^ (") + toString(*ex.right) + ")";
  365. }
  366. return "";
  367. }, expr);
  368. }
  369. }