Finished Evaluator System!

This commit is contained in:
Ayham Mamoun 2019-03-15 07:12:33 +03:00
parent dacfa22a4b
commit 7ca9f7de84
27 changed files with 690 additions and 226 deletions

View File

@ -119,19 +119,21 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="app.cpp" />
<ClCompile Include="maths\solver\term_rewriter\ds\ExprTree.cpp" />
<ClCompile Include="maths\solver\Solver.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMReducer.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMReducerHelper.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMRule.h" />
<ClCompile Include="maths\solver\term_rewriter\ds\TermPool.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="maths\solver\term_rewriter\ds\ExprTree.h" />
<ClInclude Include="maths\defines.h" />
<ClInclude Include="maths\Equations.h" />
<ClInclude Include="maths\solver\term_rewriter\QMReducer.h" />
<ClInclude Include="maths\solver\term_rewriter\QMReducerHelper.h" />
<ClInclude Include="maths\solver\term_rewriter\QMRuleSet.h" />
<ClInclude Include="maths\terms\Brackets.h" />
<ClInclude Include="maths\terms\Constant.h" />
<ClInclude Include="maths\terms\Equal.h" />
<ClInclude Include="maths\terms\Fraction.h" />
<ClInclude Include="maths\terms\Operator.h" />
<ClInclude Include="maths\terms\Paranthesis.h" />
<ClInclude Include="maths\terms\Term.h" />
@ -139,6 +141,8 @@
<ClInclude Include="maths\terms\Variable.h" />
<ClInclude Include="maths\tokenizer.h" />
<ClInclude Include="maths\solver\Solver.h" />
<ClInclude Include="maths\solver\term_rewriter\QMEvaluator.h" />
<ClInclude Include="maths\solver\term_rewriter\ds\TermPool.h" />
<ClInclude Include="vendor\lexertk.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -24,7 +24,13 @@
<ClCompile Include="maths\solver\term_rewriter\QMRule.h">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\QMReducer.cpp">
<ClCompile Include="maths\solver\term_rewriter\QMReducerHelper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\ds\TermPool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\ds\ExprTree.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@ -71,10 +77,16 @@
<ClInclude Include="maths\solver\term_rewriter\QMRuleSet.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\term_rewriter\QMReducer.h">
<ClInclude Include="maths\solver\term_rewriter\QMReducerHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\terms\Fraction.h">
<ClInclude Include="maths\solver\term_rewriter\QMEvaluator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\term_rewriter\ds\TermPool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\term_rewriter\ds\ExprTree.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

View File

@ -8,7 +8,10 @@
#include "maths/solver/Solver.h"
#include "maths/Equations.h"
#include "maths/solver/term_rewriter/QMReducer.h"
#include "maths/solver/term_rewriter/QMReducerHelper.h"
#include "maths/solver/term_rewriter/QMEvaluator.h"
#include "maths/solver/term_rewriter/ds/ExprTree.h"
//#define MAIN_APP
#define APP_TEST
@ -67,18 +70,13 @@ int main() {
#ifdef APP_TEST
int main() {
lexertk::generator lexer;
lexer.process("4x/(2+2x)");
lexer.process("2/2*4^2");
auto result = tokenize(lexer);
QMReducer reducer;
reducer.setPool(result);
auto frac = static_cast<Fraction*>(result[0]);
auto res = reducer.Div(frac->mNomin[0], frac->mDomin[0]);
auto res = evaluate(result);
return 0;
}

View File

@ -4,6 +4,8 @@
#include <vector>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <string>
#include <algorithm>

View File

@ -1 +1,35 @@
#include "Solver.h"
void Solver::Parse(string equation)
{
}
Term * Solver::Solve()
{
return nullptr;
}
bool Solver::CheckValidOps(Equation * equ)
{
return false;
}
Equation * Solver::RemoveWeightOfWings(Equation * equ)
{
return nullptr;
}
Equation * Solver::OrderTerms(Equation * equ)
{
return nullptr;
}
Equation * Solver::CheckDiversionCalcs(Equation * equ)
{
return nullptr;
}
Equation * Solver::DoDiversionCalcs(Equation * equ)
{
return nullptr;
}

View File

@ -14,8 +14,7 @@
#include "../../vendor/lexertk.hpp"
class Solver
{
class Solver {
public:
void Parse(string equation);
Term* Solve();
@ -25,20 +24,12 @@ public: // PRIVATE MEMBERS TODO: MARK PRIVATE IN FINAL BUILD
public: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD
bool CheckValidOps(Equation* equ);
Equation* RemNonEssentialOp(Equation* equ);
bool CheckOpRemovalValidity(Operator* op);
bool CheckOpT2RemovalNeed(Operator* op);
Equation* BreakUselessBracks(Equation* equ);
Equation* RemoveWeightOfWings(Equation* equ);
Equation* OrderTerms(Equation* equ);
Equation* CheckDiversionCalcs(Equation* equ);
Equation* DoDiversionCalcs(Equation* equ);
Term* MergeOpTerm(Operator* op, Term* t1, Term* t2);
public: // Math Side Calcs TODO: MARK PRIVATE IN FINAL BUIlD
Equation* Evaluate(Equation* equ);
};
#endif // !1

View File

@ -0,0 +1,100 @@
#ifndef QMEVALUATOR_H
#define QMEVALUATOR_H
#pragma once
#include "../../Equations.h"
#include "../../defines.h"
#include "../../terms/Brackets.h"
#include "../../terms/Constant.h"
#include "../../terms/Equal.h"
#include "../../terms/Operator.h"
#include "../../terms/Term.h"
#include "../../terms/Variable.h"
#include "../../terms/Paranthesis.h"
#include "../../tokenizer.h"
#include "../../../vendor/lexertk.hpp"
#include "QMRule.h"
#include "QMRuleSet.h"
#include "ds/ExprTree.h"
#include "ds/TermPool.h"
TermPool mPool;
static vector<Term*> solveNode(TreeNode * node) {
if (node->_term->mType != TermTypes::Op) return { node->_term };
vector<Term*> res;
auto op = node->_term;
auto t1 = solveNode(node->_left);
auto t2 = solveNode(node->_right);
Term* t1_final = nullptr;
Term* t2_final = nullptr;
if (t1.size() > 1) {
// convert it to bracket
Bracket* brack = new Bracket();
for (auto *term : t1) brack->mTerms.push_back(term);
t1_final = brack;
}
else t1_final = t1[0];
if (t2.size() > 1) {
// convert it to bracket
Bracket* brack = new Bracket();
for (auto *term : t2) brack->mTerms.push_back(term);
t2_final = brack;
}
else t2_final = t2[0];
if (op->mOperator == '*')
res = QMEvalHelper::Mul(t1_final, t2_final);
if (op->mOperator == '/')
res = QMEvalHelper::Div(t1_final, t2_final);
if (op->mOperator == '+')
res = QMEvalHelper::Add(t1_final, t2_final);
if (op->mOperator == '-')
res = QMEvalHelper::Sub(t1_final, t2_final);
return res;
}
static void evaluate() {
// Step 1:
// Reduce Powers except for variables
for (int i = 0; i < mPool.size(); i++)
if (mPool[i]->mType == TermTypes::Const)
*mPool[i] = *QMEvalHelper::ReducePower(mPool[i])[0];
// Step 2:
// Remove begining sign, if any
if (mPool[0]->mType == TermTypes::Op) {
auto op = mPool.pop_back(); // remove op
auto res = *mPool.begin();
res->mValue = res->mValue * (op->mOperator == '+') ? 1 : -1; // multiply
mPool.pop_front(); // remove term going to be modified
mPool.push_front(res);
}
// Step 3:
// Generate ExpressionTree
ExprTree tree;
tree.setPool(mPool.vec());
tree.GenerateTree();
// Step 4: Evaluate!!!
mPool.set(solveNode(tree.getHead()));
}
static vector<Term*> getPool() {
vector<Term*> res;
for (int i = 0; i < mPool.size(); i++)
res.push_back(mPool[i]);
return res;
}
static vector<Term*> evaluate(vector<Term*> term) {
mPool.set(term);
evaluate();
return getPool();
}
#endif // !QMEVALUATOR_H

View File

@ -1,79 +0,0 @@
#ifndef QMREDUCER_H
#define QMREDUCER_H
#pragma once
#include "../../Equations.h"
#include "../../defines.h"
#include "../../terms/Brackets.h"
#include "../../terms/Constant.h"
#include "../../terms/Equal.h"
#include "../../terms/Operator.h"
#include "../../terms/Term.h"
#include "../../terms/Variable.h"
#include "../../terms/Paranthesis.h"
#include "../../terms/Fraction.h"
#include "../../tokenizer.h"
#include "../../../vendor/lexertk.hpp"
#include "QMRule.h"
#include "QMRuleSet.h"
// WARINING: Only one variable is allowed or errors will happen!
class QMReducer {
public:
void setRuleSet(QMRuleSet set) { mRuleSet = set; };
void setPool(vector<Term*> terms) { mPool = terms; };
vector<Term*> Reduce();
private: // General Utilites
bool IsSolvable(Term* t1, Operator* op, Term* t2);
vector<Term*> BreakBracket(Bracket* brack, bool order = false, Identifier_t order_type = Identifier_t::_high_order_left);
vector<Term*> OrderTerms(vector<Term*> terms, Identifier_t order);
vector<Term*> getRangeOfTerms(vector<Term*> terms, int begin, int end);
Bracket* convertToBracket(Term* t1);
Variable* convertToVariable(Term* t1);
Constant* convertToConstant(Term* t1);
bool IsHigherSig(Term* t1, Term* t2);
bool IsEquTerms(Term* t1, Term* t2);
bool IsEquTypes(Term* t1, Term* t2);
bool IsEquPower(Term* t1, Term* t2);
bool IsEquValue(Term* t1, Term* t2);
bool IsEquVariable(Term* t1, Term* t2);
bool IsBracket(Term* t1);
private: // Power Evaluation
vector<Term*> ReducePower(Term* t1);
public: // Addition Evaluation // TODO: PRIVATE AFTER TESTING
vector<Term*> Add(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Subtraction Evaluation // TODO: PRIVATE AFTER TESTING
vector<Term*> Sub(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Multiplication Evaluation // TODO: PRIVATE AFTER TESTING
vector<Term*> Mul(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Division Evaluation // TODO: PRIVATE AFTER TESTING
bool IsDivSolvable(Term* t1, Term* t2);
bool IsDivSpecialCase(Term* t1, Term* t2);
vector<Term*> gcdofTerms(Term* t1, Term* t2);
vector<Term*> FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2);
vector<Term*> FactorizeTermsToBrack(vector<Term*> terms);
bool TermsMatch(vector<Term*> terms1, vector<Term*> terms2);
vector<Term*> Div(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
private:
QMRuleSet mRuleSet;
vector<Term*> mPool;
};
#endif // !QMREDUCER_H

View File

@ -1,10 +1,19 @@
#include "QMReducer.h"
#include "QMReducerHelper.h"
vector<Term*> QMReducer::Reduce() {
return vector<Term*>();
vector<IdsWithTerms> QMEvalHelper::convertRangeToIds(vector<Term*> range) {
vector<IdsWithTerms> result;
for (int i = 0; i < range.size(); i++) {
IdsWithTerms resultant;
resultant._id = getIdenByTerm(range[i]);
resultant._term = range[i];
result.push_back(resultant);
}
return result;
}
bool QMReducer::IsSolvable(Term * t1, Operator * op, Term * t2) {
bool QMEvalHelper::IsSolvable(Term * t1, Operator * op, Term * t2) {
// Constants check
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) return true;
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var &&
@ -32,7 +41,7 @@ bool QMReducer::IsSolvable(Term * t1, Operator * op, Term * t2) {
return false; // End situation
}
vector<Term*> QMReducer::BreakBracket(Bracket * brack, bool order, Identifier_t order_type) {
vector<Term*> QMEvalHelper::BreakBracket(Bracket * brack, bool order, Identifier_t order_type) {
vector<Term*> res;
if (brack->GetConstant() == nullptr) {
@ -48,34 +57,38 @@ vector<Term*> QMReducer::BreakBracket(Bracket * brack, bool order, Identifier_t
return res;
}
vector<Term*> QMReducer::OrderTerms(vector<Term*> terms, Identifier_t order) {
vector<Term*> QMEvalHelper::OrderTerms(vector<Term*> terms, Identifier_t order) {
if (order == Identifier_t::_high_order_left)
stable_sort(terms.begin(), terms.end(), [this](Term* t1, Term* t2) {return IsHigherSig(t1, t2); });
else stable_sort(terms.begin(), terms.end(), [this](Term* t1, Term* t2) {return IsHigherSig(t2, t1); });;
stable_sort(terms.begin(), terms.end(), [](Term* t1, Term* t2) {return IsHigherSig(t1, t2); });
else stable_sort(terms.begin(), terms.end(), [](Term* t1, Term* t2) {return IsHigherSig(t2, t1); });;
return terms;
}
vector<Term*> QMReducer::getRangeOfTerms(vector<Term*> terms, int begin, int end) {
vector<Term*> QMEvalHelper::getRangeOfTerms(vector<Term*> terms, int begin, int end) {
vector<Term*> res;
for (int i = begin; i < end; i++) res.push_back(terms[i]);
for (int i = begin; i <= end; i++) res.push_back(terms[i]);
return res;
}
vector<Identifier_t*> QMEvalHelper::getRangeOfIden(vector<Identifier_t*> terms, int begin, int end) {
vector<Identifier_t*> res;
for (int i = begin; i <= end; i++) res.push_back(terms[i]);
return res;
}
Bracket * QMReducer::convertToBracket(Term * t1) {
Bracket * QMEvalHelper::convertToBracket(Term * t1) {
if (t1->mType != TermTypes::Brack) return false;
return static_cast<Bracket*>(t1);
}
Variable * QMReducer::convertToVariable(Term * t1) {
Variable * QMEvalHelper::convertToVariable(Term * t1) {
if (t1->mType != TermTypes::Var) return false;
return static_cast<Variable*>(t1);
}
Constant * QMReducer::convertToConstant(Term * t1) {
Constant * QMEvalHelper::convertToConstant(Term * t1) {
if (t1->mType != TermTypes::Const) return false;
return static_cast<Constant*>(t1);
}
bool QMReducer::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
bool QMEvalHelper::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
if (t1->mType == TermTypes::Brack)
return true;
else if (t1->mType == TermTypes::Op)
@ -113,7 +126,7 @@ bool QMReducer::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
return false;
}
bool QMReducer::IsEquTerms(Term * t1, Term * t2) {
bool QMEvalHelper::IsEquTerms(Term * t1, Term * t2) {
if (!IsEquTypes(t1, t2)) return false;
if (!IsEquPower(t1, t2)) return false;
if (!IsEquValue(t1, t2)) return false;
@ -121,36 +134,35 @@ bool QMReducer::IsEquTerms(Term * t1, Term * t2) {
return true;
}
bool QMReducer::IsEquTypes(Term * t1, Term * t2) {
bool QMEvalHelper::IsEquTypes(Term * t1, Term * t2) {
return t1->mType == t2->mType;
}
bool QMReducer::IsEquPower(Term * t1, Term * t2) {
bool QMEvalHelper::IsEquPower(Term * t1, Term * t2) {
return t1->mPower == t2->mPower;
}
bool QMReducer::IsEquValue(Term * t1, Term * t2) {
bool QMEvalHelper::IsEquValue(Term * t1, Term * t2) {
return t1->mValue == t2->mValue;
}
bool QMReducer::IsEquVariable(Term * t1, Term * t2) {
bool QMEvalHelper::IsEquVariable(Term * t1, Term * t2) {
return t1->mVariable == t2->mVariable;
}
bool QMReducer::IsBracket(Term * t1) {
bool QMEvalHelper::IsBracket(Term * t1) {
return t1->mType == TermTypes::Brack;
}
vector<Term*> QMReducer::ReducePower(Term * t1) {
vector<Term*> QMEvalHelper::ReducePower(Term * t1) {
if (IsBracket(t1)) return {}; // Brackets powers aren't allowed
if (t1->mType == TermTypes::Var) return { t1 };
else
t1->mValue = pow(t1->mValue, t1->mPower);
t1->mValue = pow(t1->mValue, t1->mPower);
t1->mPower = 1;
return { t1 };
}
vector<Term*> QMReducer::Add(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> QMEvalHelper::Add(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> res;
// check if one of the terms were brackets
if (IsBracket(t1) || IsBracket(t2)) {
// check which term is bracket
@ -213,16 +225,14 @@ vector<Term*> QMReducer::Add(Term * t1, Term * t2, Identifier_t order) {
else { // if it wasn't solvable
// only 3 situations it is not solvable
// these situations are treated the same
// order them depending on arg 'order'
res = { t1, t2 };
res = OrderTerms(res, order);
res = { t1, new Operator('+') , t2 };
return res;
}
}
return res;
}
vector<Term*> QMReducer::Sub(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> QMEvalHelper::Sub(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> res;
@ -297,7 +307,7 @@ vector<Term*> QMReducer::Sub(Term * t1, Term * t2, Identifier_t order) {
return res;
}
vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> QMEvalHelper::Mul(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> res;
// check if one of the terms are brackets
@ -342,8 +352,6 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
}
return res;
}
}
// niether are brackets
else {
@ -395,13 +403,13 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
return res;
}
bool QMReducer::IsDivSolvable(Term * t1, Term * t2) {
bool QMEvalHelper::IsDivSolvable(Term * t1, Term * t2) {
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) return true;
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) return true;
return false;
}
bool QMReducer::IsDivSpecialCase(Term * t1, Term * t2) {
bool QMEvalHelper::IsDivSpecialCase(Term * t1, Term * t2) {
if (t1->mType == TermTypes::Brack &&
t2->mType != TermTypes::Brack) return true;
@ -419,7 +427,7 @@ bool QMReducer::IsDivSpecialCase(Term * t1, Term * t2) {
return false;
}
vector<Term*> QMReducer::gcdofTerms(Term * t1, Term * t2) {
vector<Term*> QMEvalHelper::gcdofTerms(Term * t1, Term * t2) {
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
auto t1_const = convertToConstant(ReducePower(t1)[0]);
@ -459,7 +467,7 @@ vector<Term*> QMReducer::gcdofTerms(Term * t1, Term * t2) {
return {};
}
vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2) {
vector<Term*> QMEvalHelper::FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2) {
vector<Term*> allTerms;
for (int i = 0; i < terms.size(); i++)
@ -493,7 +501,7 @@ vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> terms, vector<Term*
return { brack1, brack2 };
}
vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> allTerms) {
vector<Term*> QMEvalHelper::FactorizeTermsToBrack(vector<Term*> allTerms) {
Term* HCF_all = new Term();
*HCF_all = *allTerms[0];
for (int i = 0; i < allTerms.size(); i++)
@ -510,7 +518,7 @@ vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> allTerms) {
return { brack };
}
bool QMReducer::TermsMatch(vector<Term*> terms1, vector<Term*> terms2) {
bool QMEvalHelper::TermsMatch(vector<Term*> terms1, vector<Term*> terms2) {
terms1 = OrderTerms(terms1, Identifier_t::_high_order_left);
terms2 = OrderTerms(terms2, Identifier_t::_high_order_left);
@ -522,7 +530,7 @@ bool QMReducer::TermsMatch(vector<Term*> terms1, vector<Term*> terms2) {
return true;
}
// WARNING: Make sure that t1 and t2 are in the simplest form.
vector<Term*> QMReducer::Div(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> QMEvalHelper::Div(Term * t1, Term * t2, Identifier_t order) {
// Check if division is solvable
@ -585,11 +593,14 @@ vector<Term*> QMReducer::Div(Term * t1, Term * t2, Identifier_t order) {
fraction_domin = convertToBracket(fraction[1]);
fraction_domin->setConstant(nullptr); // Nullptr == 1
Fraction* frac = new Fraction();
vector<Term*> res;
for (int i = 0; i < fraction_nomin->mTerms.size(); i++)
res.push_back(fraction_nomin->mTerms[i]);
res.push_back(new Operator('/'));
for (int i = 0; i < fraction_domin->mTerms.size(); i++)
res.push_back(fraction_domin->mTerms[i]);
frac->mNomin = fraction_nomin->mTerms;
frac->mDomin = fraction_domin->mTerms;
return { frac };
return res;
}
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Var) {
// const / var
@ -639,10 +650,15 @@ vector<Term*> QMReducer::Div(Term * t1, Term * t2, Identifier_t order) {
auto fraction = FactorizeTermsToBrack({ t1 }, t2_Brack->mTerms);
auto comfac = convertToBracket(fraction[0])->GetConstant();
Fraction* frac = new Fraction();
frac->mNomin = convertToBracket(fraction[0])->mTerms;
frac->mDomin = convertToBracket(fraction[1])->mTerms;
return { frac };
vector<Term*> res;
for (auto *term : convertToBracket(fraction[0])->mTerms)
res.push_back(term);
res.push_back(new Operator('/'));
for (auto *term : convertToBracket(fraction[1])->mTerms)
res.push_back(term);
return res;
}
}

View File

@ -0,0 +1,85 @@
#ifndef QMREDUCER_H
#define QMREDUCER_H
#pragma once
// WARINING: Only one variable is allowed or errors will happen!
#include "../../Equations.h"
#include "../../defines.h"
#include "../../terms/Brackets.h"
#include "../../terms/Constant.h"
#include "../../terms/Equal.h"
#include "../../terms/Operator.h"
#include "../../terms/Term.h"
#include "../../terms/Variable.h"
#include "../../terms/Paranthesis.h"
#include "../../tokenizer.h"
#include "../../../vendor/lexertk.hpp"
#include "QMRule.h"
#include "QMRuleSet.h"
struct IdsWithTerms {
Identifier_t _id;
Term* _term;
};
class QMEvalHelper {
public: // General Utilites
static Identifier_t getIdenByTerm(Term* term) {
if (term->mType == TermTypes::Const) return Identifier_t::_const;
if (term->mType == TermTypes::Var) return Identifier_t::_var;
if (term->mType == TermTypes::Brack) return Identifier_t::_brack;
if (term->mType == TermTypes::Op) {
if (term->mOperator == '+') return Identifier_t::_add;
if (term->mOperator == '-') return Identifier_t::_sub;
if (term->mOperator == '*') return Identifier_t::_mul;
if (term->mOperator == '/') return Identifier_t::_div;
}
}
static vector<IdsWithTerms> convertRangeToIds(vector<Term*> range);
static bool IsSolvable(Term* t1, Operator* op, Term* t2);
static vector<Term*> BreakBracket(Bracket* brack, bool order = false, Identifier_t order_type = Identifier_t::_high_order_left);
static vector<Term*> OrderTerms(vector<Term*> terms, Identifier_t order);
static vector<Term*> getRangeOfTerms(vector<Term*> terms, int begin, int end);
static vector<Identifier_t*> getRangeOfIden(vector<Identifier_t*> terms, int begin, int end);
static Bracket* convertToBracket(Term* t1);
static Variable* convertToVariable(Term* t1);
static Constant* convertToConstant(Term* t1);
static bool IsHigherSig(Term* t1, Term* t2);
static bool IsEquTerms(Term* t1, Term* t2);
static bool IsEquTypes(Term* t1, Term* t2);
static bool IsEquPower(Term* t1, Term* t2);
static bool IsEquValue(Term* t1, Term* t2);
static bool IsEquVariable(Term* t1, Term* t2);
static bool IsBracket(Term* t1);
public: // Power Evaluation
static vector<Term*> ReducePower(Term* t1);
public: // Addition Evaluation
static vector<Term*> Add(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Subtraction Evaluation
static vector<Term*> Sub(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Multiplication Evaluation
static vector<Term*> Mul(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Division Evaluation
static bool IsDivSolvable(Term* t1, Term* t2);
static bool IsDivSpecialCase(Term* t1, Term* t2);
static vector<Term*> gcdofTerms(Term* t1, Term* t2);
static vector<Term*> FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2);
static vector<Term*> FactorizeTermsToBrack(vector<Term*> terms);
static bool TermsMatch(vector<Term*> terms1, vector<Term*> terms2);
static vector<Term*> Div(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
};
#endif // !QMREDUCER_H

View File

@ -17,6 +17,7 @@ enum Identifier_t {
_const = 1,
_var = 2,
_brack,
_frac,
_eval,
_add,
_sub,
@ -40,10 +41,11 @@ enum Identifier_t {
class QMRule {
public:
QMRule(vector<int> rule, vector<int> props, int prio)
: mRules(rule), mProps(props), mPrior(prio) {}
QMRule(vector<int> rule, vector<int> result, vector<int> props, int prio)
: mRules(rule), mResult(result), mProps(props), mPrior(prio) {}
vector<int> GetRules() const { return mRules; }
vector<int> GetResult() const { return mResult; }
vector<int> GetProps() const { return mProps; }
int GetPrior() { return mPrior; }
@ -62,6 +64,7 @@ public:
}
private:
vector<int> mRules;
vector<int> mResult;
vector<int> mProps;
int mPrior;
};

View File

@ -31,6 +31,8 @@ public:
stable_sort(mRuleSet.begin(), mRuleSet.end());
}
int size() { return mRuleSet.size(); }
auto GetRuleSet() { return mRuleSet; }
inline QMRule& operator[](int index) {

View File

@ -0,0 +1,103 @@
#include "ExprTree.h"
void ExprTree::setPool(vector<Term*> pool) {
mPool.set(pool);
mHead = new TreeNode();
}
void ExprTree::GenerateTree() {
mHead = _genTree(mPool);
}
void ExprTree::print() {
_print("", mHead, false);
}
TreeNode* ExprTree::_genTree(TermPool pool) {
if (pool.size() == 0) return nullptr;
if (pool.size() == 1) {
TreeNode* node = new TreeNode();
node->_term = pool[0];
node->_left = nullptr;
node->_right = nullptr;
return node;
}
// Number operations
std::vector<pair<int, int>> operators;
int counter = 0;
// DIV, MUL first
for (int i = 0; i < pool.size(); i++) {
if (pool[i]->mType == TermTypes::Op) {
if (pool[i]->mOperator == '/') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
if (pool[i]->mOperator == '*') {
pair <int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
}
}
// ADD, SUB Second
for (int i = 0; i < pool.size(); i++) {
if (pool[i]->mType == TermTypes::Op) {
if (pool[i]->mOperator == '+') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
else if (pool[i]->mOperator == '-') {
pair<int, int> resultant;
resultant.first = i;
resultant.second = counter++;
operators.push_back(resultant);
}
}
}
stable_sort(operators.begin(), operators.end(),
[this](pair<int, int> arg1, pair<int, int> arg2) {
return arg1.second < arg2.second;
});
// Split upon op, recurse
TermPool left, right;
// dont get the op to left
auto ptr1 = operators[operators.size() - 1].first;
left.set(
pool.getRange(0, ptr1-1)
);
// dont get the op to right
right.set(
pool.getRange(ptr1 + 1, pool.size()-1)
);
// get the op here
Term* op = pool[left.size()];
TreeNode* node = new TreeNode();
node->_term = op;
node->_left = _genTree(left);
node->_right = _genTree(right);
return node;
}
void ExprTree::_print(const std::string prefix, const TreeNode* node, bool isLeft) {
if (node != nullptr) {
cout << prefix;
cout << (isLeft ? "|--" : "^--");
// print the value of the node
cout << node->_term->to_str() << endl;
_print(prefix + (isLeft ? "| " : " "), node->_left, true);
_print(prefix + (isLeft ? "| " : " "), node->_right, false);
}
}

View File

@ -0,0 +1,43 @@
#ifndef EXPR_TREE_H
#define EXPR_TREE_H
#pragma once
#include "../../../Equations.h"
#include "../../../defines.h"
#include "../../../terms/Brackets.h"
#include "../../../terms/Constant.h"
#include "../../../terms/Equal.h"
#include "../../../terms/Operator.h"
#include "../../../terms/Term.h"
#include "../../../terms/Variable.h"
#include "../../../terms/Paranthesis.h"
#include "../../../tokenizer.h"
#include "../../../../vendor/lexertk.hpp"
#include "../QMReducerHelper.h"
#include "TermPool.h"
struct TreeNode {
Term* _term;
TreeNode* _left = nullptr;
TreeNode* _right = nullptr;
};
class ExprTree {
public:
void setPool(vector<Term*> pool);
void GenerateTree();
void print();
TreeNode* getHead() { return mHead; }
private:
TreeNode* _genTree(TermPool pool);
void _print(const std::string prefix, const TreeNode* node, bool isLeft);
TreeNode* mHead = nullptr;
TermPool mPool;
};
#endif // !EXPR_TREE_H

View File

@ -0,0 +1,74 @@
#include "TermPool.h"
void TermPool::set(vector<Term*> terms) {
this->clear();
for (auto* term : terms)
mList.push_back(term);
}
void TermPool::insert(Term * term, int pos) {
auto begining = std::begin(mList);
while (pos--) begining++;
mList.insert(begining, term);
}
void TermPool::insertRange(vector<Term*> terms, int pos) {
auto begining = std::begin(mList);
while (pos--) begining++;
for (auto *term : terms) mList.insert(begining++, term);
}
void TermPool::deleteItem(int pos) {
auto begining = std::begin(mList);
while (pos--) begining++;
mList.remove(*begining);
}
void TermPool::deleteItemRange(int begin, int end) {
for (int i = begin; i < end; i++)
this->deleteItem(i);
}
vector<Term*> TermPool::getRange(int begin, int end) {
vector<Term*> res;
for (int i = begin; i <= end; i++)
res.push_back(this->operator[](i));
return res;
}
void TermPool::push_back(Term * term) {
mList.push_back(term);
}
void TermPool::push_front(Term * term) {
mList.push_front(term);
}
Term * TermPool::pop_back() {
auto res = *mList.end();
mList.pop_back();
return res;
}
Term * TermPool::pop_front() {
auto res = *mList.begin();
mList.pop_front();
return res;
}
void TermPool::clear() {
mList.clear();
}
Term * TermPool::operator[](int index) const {
auto it = mList.begin();
std::advance(it, index);
// 'it' points to the element at index 'N'
auto res = *it;
return res;
}
int TermPool::size() const {
return mList.size();
}

View File

@ -0,0 +1,60 @@
#ifndef TERMPOOL_H
#define TERMPOOL_H
#pragma once
#include <list>
#include "../../../Equations.h"
#include "../../../defines.h"
#include "../../../terms/Brackets.h"
#include "../../../terms/Constant.h"
#include "../../../terms/Equal.h"
#include "../../../terms/Operator.h"
#include "../../../terms/Term.h"
#include "../../../terms/Variable.h"
#include "../../../terms/Paranthesis.h"
#include "../../../tokenizer.h"
#include "../../../../vendor/lexertk.hpp"
class TermPool {
public:
void set(vector<Term*> terms);
void insert(Term* term, int pos = -1);
void insertRange(vector<Term*> terms, int pos = -1);
void deleteItem(int pos);
void deleteItemRange(int begin, int end);
vector<Term*> getRange(int begin, int end);
void push_back(Term* term);
void push_front(Term* term);
Term* pop_back();
Term* pop_front();
auto begin() { return mList.begin(); }
auto end() { return mList.end(); }
void clear();
Term* operator[](int index) const;
auto getIterator(int index) {
auto beginining = std::begin(mList);
std::advance(beginining, index);
return beginining;
}
int size() const;
void order() {
mList.sort();
}
vector<Term*> vec() {
vector<Term*> res;
for (auto *item : mList)
res.push_back(item);
return res;
}
private:
list<Term*> mList;
};
#endif // !TERMPOOL_H

View File

@ -10,13 +10,11 @@ using namespace std;
class Bracket : public Term {
public:
Bracket() {
Term();
Bracket() : Term() {
mType = TermTypes::Brack;
}
Bracket(vector<Term*> ts) {
Term();
Bracket(vector<Term*> ts) : Term() {
mType = TermTypes::Brack;
mTerms = ts;
}
@ -29,6 +27,17 @@ public:
Term* GetConstant() const { return mConstant; }
string to_str() override {
string str;
if (mConstant != nullptr)
str.append(mConstant->to_str());
for (int i = 0; i < mTerms.size(); i++)
str.append(mTerms[i]->to_str());
return str;
}
private:
Term *mConstant = nullptr; // Nullptr == 1
};

View File

@ -7,11 +7,21 @@ using namespace std;
class Constant : public Term {
public:
Constant(NValue val = 0, NValue pwr = 1) {
Term();
Constant(NValue val = 0, NValue pwr = 1) : Term() {
mValue = val;
mPower = pwr;
mType = TermTypes::Const;
}
string to_str() override {
stringstream str;
str << setprecision(0) << mValue;
if (mPower > 1) {
str << "^";
str << setprecision(0) << mPower;
}
return str.str();
}
};
#endif // !CONSTANT_H

View File

@ -8,9 +8,13 @@ using namespace std;
class Equal : public Term {
public:
Equal() {
Equal() : Term() {
mType = TermTypes::Equ;
}
string to_str() override {
return "=";
}
};
#endif // !EQUAL_H

View File

@ -1,21 +0,0 @@
#ifndef FRACTION_H
#define FRACTION_H
#pragma once
#include "../defines.h"
#include "Term.h"
using namespace std;
class Fraction: public Term {
public:
Fraction(vector<Term*> nomin = {}, vector<Term*> domin = {}) {
Term();
mNomin = nomin;
mDomin = domin;
mType = TermTypes::Frac;
}
public: // TODO: try to change to private
vector<Term*> mNomin;
vector<Term*> mDomin;
};
#endif // !CONSTANT_H

View File

@ -12,5 +12,12 @@ public:
mOperator = oper;
mType = TermTypes::Op;
}
string to_str() override {
stringstream str;
str << mOperator;
return str.str();
}
};
#endif // !OPERATOR_

View File

@ -6,13 +6,6 @@
using namespace std;
class Term {
public:
virtual NValue GetValue() { return mValue; }
virtual CValue GetVariable() { return mVariable; }
virtual CValue GetOperator() { return mOperator; }
virtual NValue GetPower() { return mPower; }
virtual int GetType() { return mType; };
public:
Term(NValue val = DEF_N, CValue var = DEF_C, CValue oper = DEF_C, NValue pwr = 1) {
mValue = val;
@ -21,6 +14,8 @@ public:
mPower = pwr;
}
virtual string to_str() { return "TERM_UNKNOWN"; };
NValue mValue = DEF_N;
CValue mVariable = DEF_C;
NValue mPower = 1;

View File

@ -8,11 +8,24 @@ using namespace std;
class Variable : public Term {
public:
Variable(NValue val = 1, CValue var = DEF_C, NValue pwr = 1) {
Variable(NValue val = 1, CValue var = DEF_C, NValue pwr = 1) : Term() {
mValue = val;
mVariable = var;
mPower = pwr;
mType = TermTypes::Var;
}
string to_str() override {
stringstream str;
if (mValue != 1)
str << setprecision(0) << mValue;
str << (char)mVariable;
if (mPower > 1) {
str << "^";
str << setprecision(0) << mPower;
}
return str.str();
}
};
#endif // !VARIABLE_H

View File

@ -26,7 +26,6 @@
#include "terms/Term.h"
#include "terms/Variable.h"
#include "terms/Paranthesis.h"
#include "terms/Fraction.h"
#include "../vendor/lexertk.hpp"
@ -164,42 +163,42 @@ static vector<Term*> combineBrackets(vector<Term*> terms) {
return result;
}
static vector<Term*> combineOpWithTerms(vector<Term*> terms) {
vector<Term*> result;
for (int i = 0; i < terms.size(); i++) {
if (terms[i]->mType == TermTypes::Op) {
// operator detected
auto op = static_cast<Operator*>(terms[i]);
if (op->mOperator == '/') {
// division found
// check if it was the first
if (i == 0) {
// invalid
cout << "Can't divide with a Nill nominator!" << endl;
system("PAUSE");
exit(0);
}
Fraction* frac = new Fraction();
frac->mDomin.push_back(terms[i + 1]);
frac->mNomin.push_back(terms[i - 1]);
result.pop_back(); // pop the nominator, before push
result.push_back(frac);
// consume the dominator
i += 1;
continue;
}
}
result.push_back(terms[i]);
continue;
}
return result;
}
//static vector<Term*> combineOpWithTerms(vector<Term*> terms) {
// vector<Term*> result;
//
// for (int i = 0; i < terms.size(); i++) {
// if (terms[i]->mType == TermTypes::Op) {
// // operator detected
// auto op = static_cast<Operator*>(terms[i]);
// if (op->mOperator == '/') {
// // division found
//
// // check if it was the first
// if (i == 0) {
// // invalid
// cout << "Can't divide with a Nill nominator!" << endl;
// system("PAUSE");
// exit(0);
// }
//
//
// Fraction* frac = new Fraction();
// frac->mDomin.push_back(terms[i + 1]);
// frac->mNomin.push_back(terms[i - 1]);
// result.pop_back(); // pop the nominator, before push
// result.push_back(frac);
//
// // consume the dominator
// i += 1;
// continue;
// }
// }
// result.push_back(terms[i]);
// continue;
// }
//
// return result;
//}
static vector<Term*> tokenize(lexertk::generator lexed) {
vector<Term*> result;
@ -361,7 +360,7 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
// post-fix fixes
result = combineBrackets(result);
result = combineOpWithTerms(result);
//result = combineOpWithTerms(result);
return result;
}
#endif // !TOKENIZER_H

Binary file not shown.

Binary file not shown.

Binary file not shown.