Made Basic QMReducer
This commit is contained in:
Ayham Mamoun 2019-03-10 21:21:34 +03:00
parent 1fb27bb26c
commit cc743f1e54
15 changed files with 552 additions and 23 deletions

View File

@ -0,0 +1,66 @@
QMReducer Functions Calling, and Callers:
General Utilities Functions:
IsSolvable:
Callings:
Callers: Add, Sub
BreakBrackets:
Callings: Mul
Callers: Add, Sub
OrderTerms:
Callings: IsHigherSig
Callers:
GetRangeTerms:
Callings:
Callers:
ConverttoBracket:
Callings:
Callers: Add, Sub
ConvertToVariable:
Callings:
Callers: Add, Sub
ConvertToConstant:
Callings:
Callers: Add, Sub
IsHigherSig:
Callings:
Calelrs: OrderTerms
IsEquTerms:
Callings:
IsEquTypes, IsEquPower, IsEquValue, IsEquVariable
Callers:
IsEquTypes:
Callings:
Callers: IsEquTerms
IsEquPower:
Callings:
Callers: IsEquTerms
IsEquValue:
Callings:
Callers: IsEquTerms
IsEquVaraible:
Callings:
Callers: IsEquTerms
IsBracket:
Callings:
Callers: Add, Sum
Power Evaluation:
ReducePower:
Callings: Mul
Callers: Add, Sub
Addition Evaluation:
Add:
Callings: IsBracket, BreakBracket, convertTo*, IsSolvable, ReducePower, OrderTerms
Callers:
Subtraction Evaluation:
Sub:
Callings: IsBracket, BreakBracket, convertTo*, IsSolvable, ReducePower, OrderTerms
Callers:
Multiplication Evaluation:
Mul:
Callings: Mul, IsBracket, BreakBracket, convertTo*, ReducePower
Callers: ReducePower, BreakBracket

View File

@ -120,7 +120,7 @@
<ItemGroup>
<ClCompile Include="app.cpp" />
<ClCompile Include="maths\solver\Solver.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMRule.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMReducer.cpp" />
<ClCompile Include="maths\solver\term_rewriter\QMRule.h" />
</ItemGroup>
<ItemGroup>

View File

@ -24,7 +24,7 @@
<ClCompile Include="maths\solver\term_rewriter\QMRule.h">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\QMRule.cpp">
<ClCompile Include="maths\solver\term_rewriter\QMReducer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -8,6 +8,8 @@
#include "maths/solver/Solver.h"
#include "maths/Equations.h"
#include "maths/solver/term_rewriter/QMReducer.h"
//#define MAIN_APP
#define APP_TEST
@ -68,10 +70,13 @@ int main() {
int main() {
lexertk::generator lexer;
lexer.process("_const+_const,_eval:no_diff_Var");
lexer.process("2(x + 2x) + 2x");
//auto result = tokenize(lexer);
auto result = tokenize(lexer);
QMReducer reducer;
reducer.setPool(result);
auto res = reducer.Sub(result[0], result[2]);
return 0;
}

View File

@ -13,6 +13,8 @@
#include <sstream>
#include <iomanip>
#include <functional>
using namespace std;
#define DEF_C -999

View File

@ -0,0 +1,393 @@
#include "QMReducer.h"
vector<Term*> QMReducer::Reduce() {
return vector<Term*>();
}
bool QMReducer::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 &&
op->mOperator == '*') return true;
// Variables check
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var &&
IsEquPower(t1, t2)) return true;
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var &&
!IsEquPower(t1, t2)) return false;
// Brackets checks
// Avoid calling is solvable on bracket since they will break
// in evaluation process
if (t1->mType == TermTypes::Brack && t2->mType == TermTypes::Brack &&
op->mOperator == '*') return true;
if (t1->mType == TermTypes::Brack && t2->mType != TermTypes::Brack &&
op->mOperator == '*') return true;
if (t2->mType == TermTypes::Brack && t1->mType != TermTypes::Brack &&
op->mOperator == '*') return true;
if (t1->mType == TermTypes::Brack && t2->mType != TermTypes::Brack &&
op->mOperator != '*') return true;
if (t2->mType == TermTypes::Brack && t1->mType != TermTypes::Brack &&
op->mOperator != '*') return true;
return false; // End situation
}
vector<Term*> QMReducer::BreakBracket(Bracket * brack, bool order, Identifier_t order_type) {
vector<Term*> res;
if (brack->GetConstant() == nullptr) {
for (int i = 0; i < brack->mTerms.size(); i++)
res.push_back(brack->mTerms[i]);
}
for (int i = 0; i < brack->mTerms.size(); i++) {
auto returns = Mul(brack->GetConstant(), brack->mTerms[i]);
for (int j = 0; j < returns.size(); j++)
res.push_back(returns[j]);
}
return res;
}
vector<Term*> QMReducer::OrderTerms(vector<Term*> terms, Identifier_t order) {
stable_sort(terms.begin(), terms.end(), [this](Term* t1, Term* t2) {return IsHigherSig(t1, t2); });
return terms;
}
vector<Term*> QMReducer::getRangeOfTerms(vector<Term*> terms, int begin, int end) {
vector<Term*> res;
for (int i = begin; i < end; i++) res.push_back(terms[i]);
return res;
return res;
}
Bracket * QMReducer::convertToBracket(Term * t1) {
if (t1->mType != TermTypes::Brack) return false;
return static_cast<Bracket*>(t1);
}
Variable * QMReducer::converToVariable(Term * t1) {
if (t1->mType != TermTypes::Var) return false;
return static_cast<Variable*>(t1);
}
Constant * QMReducer::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
if (t1->mType == TermTypes::Brack)
return true;
else if (t1->mType == TermTypes::Op)
return false;
else if (t2->mType == TermTypes::Op)
return true;
if (t1->mType == TermTypes::Var) {
// its a var check for other term
if (t2->mType == TermTypes::Brack) return false;
if (t2->mType == TermTypes::Var) {
// if power is equal
if (IsEquPower(t1, t2)) {
// check for value
return t1->mValue >= t2->mValue;
}
// if t1 has higher or equal power
if (t1->mPower >= t2->mPower) return true;
else return false; // t2 is higher
}
return true;
}
else if (t1->mType == TermTypes::Const) {
// its a const check for other term
if (t2->mType == TermTypes::Brack) return false;
if (t2->mType == TermTypes::Var) return false;
if (t2->mType == TermTypes::Const) {
// if same type
// check for power
return t1->mPower >= t2->mPower;
}
}
return false;
}
bool QMReducer::IsEquTerms(Term * t1, Term * t2) {
if (!IsEquTypes(t1, t2)) return false;
if (!IsEquPower(t1, t2)) return false;
if (!IsEquValue(t1, t2)) return false;
if (!IsEquVariable(t1, t2)) return false;
return true;
}
bool QMReducer::IsEquTypes(Term * t1, Term * t2) {
return t1->mType == t2->mType;
}
bool QMReducer::IsEquPower(Term * t1, Term * t2) {
return t1->mPower == t2->mPower;
}
bool QMReducer::IsEquValue(Term * t1, Term * t2) {
return t1->mValue == t2->mValue;
}
bool QMReducer::IsEquVariable(Term * t1, Term * t2) {
return t1->mVariable == t2->mVariable;
}
bool QMReducer::IsBracket(Term * t1) {
return t1->mType == TermTypes::Brack;
}
vector<Term*> QMReducer::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);
return { t1 };
}
vector<Term*> QMReducer::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
if (IsBracket(t1) && !IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1));
auto brokenbrack2 = BreakBracket(convertToBracket(t2));
for (int i = 0; i < brokenbrack2.size(); i++)
brokenbrack.push_back(brokenbrack[i]);
// TODO: evaluation system
return brokenbrack;
}
if (IsBracket(t1) && !IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1));
brokenbrack.push_back(t2);
// TODO: evaluation system
return brokenbrack;
}
else if (!IsBracket(t1) && IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t2));
brokenbrack.push_back(t1);
// TODO: evaluation system
return brokenbrack;
}
}
else {
// Check if it was solvable
if (IsSolvable(t1, new Operator('+'), t2)) {
// only two cases that it is solvable
// const + const
// var + var : no var difference
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
auto t1_const = convertToConstant(t1);
auto t2_const = convertToConstant(t2);
t1_const = convertToConstant(ReducePower(t1_const)[0]);
t2_const = convertToConstant(ReducePower(t2_const)[0]);
Constant* Const = nullptr;
Const = new Constant();
Const->mValue = t1_const->mValue + t2->mValue;
return { Const };
}
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
auto t1_var = converToVariable(t1);
auto t2_var = converToVariable(t2);
Variable* var = nullptr;
var = new Variable();
var->mPower = t1_var->mPower;
var->mValue = t1_var->mValue + t2_var->mValue;
if (var->mValue == 0) {
Constant* Const = nullptr;
Const->mPower = t1_var->mPower;
Const->mValue = t1_var->mValue + t2_var->mValue;
return { Const };
}
var->mVariable = t1_var->mVariable;
return { var };
}
}
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);
return res;
}
}
return res;
}
vector<Term*> QMReducer::Sub(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
if (IsBracket(t1) && IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1));
auto brokenbrack2 = BreakBracket(convertToBracket(t2));
for (int i = 0; i < brokenbrack2.size(); i++)
brokenbrack.push_back(brokenbrack[i]);
// TODO: evaluation system
return brokenbrack;
}
if (IsBracket(t1) && !IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1));
brokenbrack.push_back(t2);
// TODO: evaluation system
return brokenbrack;
}
else if (!IsBracket(t1) && IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t2));
brokenbrack.push_back(t1);
// TODO: evaluation system
return brokenbrack;
}
}
else {
// Check if it was solvable
if (IsSolvable(t1, new Operator('-'), t2)) {
// only two cases that it is solvable
// const + const
// var + var : no var difference
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
auto t1_const = convertToConstant(t1);
auto t2_const = convertToConstant(t2);
t1_const = convertToConstant(ReducePower(t1_const)[0]);
t2_const = convertToConstant(ReducePower(t2_const)[0]);
Constant* Const = nullptr;
Const = new Constant();
Const->mValue = t1_const->mValue - t2->mValue;
return { Const };
}
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
auto t1_var = converToVariable(t1);
auto t2_var = converToVariable(t2);
Variable* var = nullptr;
var = new Variable();
var->mPower = t1_var->mPower;
var->mValue = t1_var->mValue - t2_var->mValue;
if (var->mValue == 0) {
Constant* Const = new Constant();
Const->mPower = t1_var->mPower;
Const->mValue = t1_var->mValue - t2_var->mValue;
return { Const };
}
var->mVariable = t1_var->mVariable;
return { var };
}
}
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);
return res;
}
}
return res;
}
vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
vector<Term*> res;
// check if one of the terms are brackets
if (IsBracket(t1) || IsBracket(t2)) {
// only 3 situations
// brack, brack : use foil
// brack, var
// brack, const
if (IsBracket(t1) || IsBracket(t2)) {
auto t1_brokenbrack = BreakBracket(convertToBracket(t1), true, order);
auto t2_brokenbrack = BreakBracket(convertToBracket(t2), true, order);
for (int i = 0; i < t1_brokenbrack.size(); i++) {
for (int j = 0; j < t2_brokenbrack.size(); j++) {
auto returns = Mul(t1_brokenbrack[i], t2_brokenbrack[j], order); // recurse
for (int m = 0; m < returns.size(); m++) res.push_back(returns[m]);
}
}
// TODO: Make evaluation system
return res;
}
// if only one bracket is there
if (IsBracket(t1) && !IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t1), true, order);
// if t2 was a variable or a constant same method
for (int i = 0; i < brokenbrack.size(); i++) {
auto returns = Mul(brokenbrack[i], t2);
for (int j = 0; j < returns.size(); j++) res.push_back(returns[j]);
}
return res;
}
if (!IsBracket(t1) && IsBracket(t2)) {
auto brokenbrack = BreakBracket(convertToBracket(t2), true, order);
// if t2 was a variable or a constant same method
for (int i = 0; i < brokenbrack.size(); i++) {
auto returns = Mul(brokenbrack[i], t1);
for (int j = 0; j < returns.size(); j++) res.push_back(returns[j]);
}
return res;
}
}
// niether are brackets
else {
// no need to check solvability
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
auto t1_var = converToVariable(t1);
auto t2_var = converToVariable(t2);
Variable* var = nullptr;
var = new Variable();
var->mValue = t1_var->mValue * t2_var->mValue;
var->mVariable = t1_var->mVariable;
var->mPower = t1_var->mPower + t2_var->mPower;
return { var };
}
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Const) {
auto t1_var = converToVariable(t1);
auto t2_const = convertToConstant(ReducePower(t2)[0]);
Variable* var = nullptr;
var = new Variable();
var->mValue = t1_var->mValue * t2_const->mValue;
var->mVariable = t1_var->mVariable;
var->mPower = t1_var->mPower;
return { var };
}
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Var) {
auto t1_const = convertToConstant(t1);
auto t2_var = converToVariable(ReducePower(t2)[0]);
Variable* var = nullptr;
var = new Variable();
var->mValue = t2_var->mValue * t1_const->mValue;
var->mVariable = t2_var->mVariable;
var->mPower = t2_var->mPower;
return { var };
}
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
Constant* t1_const = new Constant(), *t2_const = new Constant();
t1_const = convertToConstant(ReducePower(t1)[0]);
t2_const = convertToConstant(ReducePower(t2)[0]);
Constant* Const = nullptr;
Const = new Constant();
Const->mValue = t1_const->mValue * t2_const->mValue;
return { Const };
}
}
return res;
}

View File

@ -1 +1,67 @@
#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 "../../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* converToVariable(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: PUBLIC AFTER TESTING
vector<Term*> Add(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Subtraction Evaluation // TODO: PUBLIC AFTER TESTING
vector<Term*> Sub(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
public: // Multiplication Evaluation // TODO: PUBLIC AFTER TESTING
vector<Term*> Mul(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
private:
QMRuleSet mRuleSet;
vector<Term*> mPool;
};
#endif // !QMREDUCER_H

View File

@ -1,6 +0,0 @@
#include "QMRule.h"
vector<Term*> QMRule::Reduce()
{
return vector<Term*>();
}

View File

@ -60,12 +60,7 @@ public:
bool operator<(const QMRule& left) const {
return (left.mPrior < mPrior);
}
vector<Term*> Reduce(vector<Term*> terms); // applies self rule on terms vector, only once
private:
vector<Term*> Evaluate(); // evaluation method
vector<int> mRules;
vector<int> mProps;
int mPrior;

View File

@ -18,16 +18,24 @@
class QMRuleSet {
public:
void push_back(QMRule rule);
void push_front(QMRule rule);
void push_back(QMRule rule) { mRuleSet.push_back(rule); }
void push_front(QMRule rule) { mRuleSet.push_front(rule); }
void pop_back(QMRule rule);
void pop_front(QMRule rule);
void pop_back() { mRuleSet.pop_back(); };
void pop_front() { mRuleSet.pop_front(); }
void order();
QMRule back() { return mRuleSet[mRuleSet.size() - 1]; }
QMRule front() { return mRuleSet[0]; }
void order() {
stable_sort(mRuleSet.begin(), mRuleSet.end());
}
auto GetRuleSet() { return mRuleSet; }
inline QMRule& operator[](int index) {
return mRuleSet[index];
}
private:
deque<QMRule> mRuleSet;
};

View File

@ -30,6 +30,6 @@ public:
Term* GetConstant() const { return mConstant; }
private:
Term *mConstant;
Term *mConstant = nullptr; // Nullptr == 1
};
#endif // !BRACKET_H

View File

@ -19,8 +19,8 @@ class Paranthesis : Term {
bool isOpening() { return __isopening; }
int getType() { return __type; }
void setOpening(bool is) { __isopening == is; }
void setType(char type) { __type == type; }
void setOpening(bool is) { __isopening = is; }
void setType(char type) { __type = type; }
private:
bool __isopening = true;

Binary file not shown.

Binary file not shown.

Binary file not shown.