Making a term rewrite system.
This commit is contained in:
Ayham Mamoun 2019-03-10 15:43:33 +03:00
parent 99afb00916
commit 1fb27bb26c
22 changed files with 469 additions and 29 deletions

View File

@ -119,9 +119,15 @@
</ItemDefinitionGroup>
<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\QMRule.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="maths\defines.h" />
<ClInclude Include="maths\Equations.h" />
<ClInclude Include="maths\solver\term_rewriter\QMReducer.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" />
@ -131,6 +137,7 @@
<ClInclude Include="maths\terms\term_parser.h" />
<ClInclude Include="maths\terms\Variable.h" />
<ClInclude Include="maths\tokenizer.h" />
<ClInclude Include="maths\solver\Solver.h" />
<ClInclude Include="vendor\lexertk.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -18,6 +18,15 @@
<ClCompile Include="app.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\Solver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\QMRule.h">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="maths\solver\term_rewriter\QMRule.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="maths\tokenizer.h">
@ -53,5 +62,17 @@
<ClInclude Include="maths\terms\Paranthesis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\Equations.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\Solver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\term_rewriter\QMRuleSet.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="maths\solver\term_rewriter\QMReducer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -3,4 +3,7 @@
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -5,10 +5,11 @@
#include "vendor/lexertk.hpp"
#include "maths/tokenizer.h"
#include "maths/solver/Solver.h"
#include "maths/Equations.h"
#define MAIN_APP
//#define APP_TEST
//#define MAIN_APP
#define APP_TEST
#ifdef MAIN_APP
@ -44,13 +45,14 @@ int main() {
system("CLS");
return 1;
}
#ifdef DEBUG_MODE
lexertk::helper::dump(generator);
#endif // DEBUG_MODE
Equation equation;
equation.Parse(generator);
auto result = tokenize(generator);
system("PAUSE");
system("CLS");
@ -64,5 +66,14 @@ int main() {
#ifdef APP_TEST
int main() {
lexertk::generator lexer;
lexer.process("_const+_const,_eval:no_diff_Var");
//auto result = tokenize(lexer);
return 0;
}
#endif

48
QuicMaf/maths/Equations.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef EQUATIONS_H
#define EQUATIONS_H
#pragma once
#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"
struct Equation {
vector<Term*> lwing;
vector<Term*> rwing;
// TODO: Optimize this mess
void Parse(lexertk::generator expression) {
string lwing_str;
string rwing_str;
bool left = true;
for (int i = 0; i < expression.size(); i++) {
if (expression[i].value[0] == '\0') continue;
if (expression[i].value[0] == '=') {
left = !left;
continue; // dont add equal sign
}
else left = left;
(left) ? lwing_str.push_back(expression[i].value[0]) : rwing_str.push_back(expression[i].value[0]); // append to wings
}
// Tokenize wings
lexertk::generator lwing_lexer;
lwing_lexer.process(lwing_str);
lwing = tokenize(lwing_lexer);
lexertk::generator rwing_lexer;
rwing_lexer.process(rwing_str);
rwing = tokenize(rwing_lexer);
}
};
#endif // !EQUATIONS_H

View File

@ -7,8 +7,12 @@
#include <string>
#include <algorithm>
#include <math.h>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
#define DEF_C -999
@ -25,7 +29,6 @@ enum TermTypes {
Equ,
};
// for string delimiter
static vector<string> split(string s, string delimiter) {
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
@ -51,7 +54,7 @@ static void removeSubstrs(string& s, string& p) {
s.erase(i, n);
}
int getPrecedence(char c) {
static int getPrecedence(char c) {
//if (!isArithmitic(c)) return -1; // invalid
if (c == '*') return 1;
@ -64,7 +67,7 @@ int getPrecedence(char c) {
// return true if c1 is higher precedence
// return false if c2 is higher precedence
bool compPrecedence(char c1, char c2) {
static bool compPrecedence(char c1, char c2) {
return getPrecedence(c1) > getPrecedence(c2);
}
@ -149,4 +152,23 @@ static int getTermType(string str) {
else return Var;
}
// 1 is pos
// -1 is neg
// 0 is 0
static int sign(NValue x) {
return (x > 0) ? 1 : ((x < 0) ? -1 : 0);
}
// Function to calculate highest common divisor
static int gcf(int x, int y) {
int gcd;
for (int i = 1; i <= x && i <= y; i++)
if (x % i == 0 && y % i == 0)
gcd = i;
return gcd;
}
#endif // !

View File

@ -0,0 +1 @@
#include "Solver.h"

View File

@ -0,0 +1,44 @@
#ifndef SOLVER_H
#define SOLVER_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"
class Solver
{
public:
void Parse(string equation);
Term* Solve();
public: // PRIVATE MEMBERS TODO: MARK PRIVATE IN FINAL BUILD
Equation* equation = nullptr;
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 @@
#pragma once

View File

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

View File

@ -0,0 +1,73 @@
#ifndef QMRULE_H
#define QMRULE_H
#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"
enum Identifier_t {
_const = 1,
_var = 2,
_brack,
_eval,
_add,
_sub,
_mul,
_div,
_equ,
_const_aval,
_var_aval,
_pow_diff,
_no_pow_diff,
_var_diff,
_no_var_diff,
_high_order_left,
_high_order_right,
_priority1,
_priority2,
_priority3,
_priority4,
_priority5,
};
class QMRule {
public:
QMRule(vector<int> rule, vector<int> props, int prio)
: mRules(rule), mProps(props), mPrior(prio) {}
vector<int> GetRules() const { return mRules; }
vector<int> GetProps() const { return mProps; }
int GetPrior() { return mPrior; }
bool operator==(const QMRule& left) const {
if (left.mPrior != mPrior) return false;
if (left.mProps != mProps) return false;
if (left.mRules != mRules) return false;
return true;
}
bool operator>(const QMRule& left) const {
return (left.mPrior > mPrior);
}
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;
};
#endif // QMRULE_H

View File

@ -0,0 +1,35 @@
#ifndef QMRULESET_H
#define QMRULESET_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"
class QMRuleSet {
public:
void push_back(QMRule rule);
void push_front(QMRule rule);
void pop_back(QMRule rule);
void pop_front(QMRule rule);
void order();
auto GetRuleSet() { return mRuleSet; }
private:
deque<QMRule> mRuleSet;
};
#endif // !QMRULESET_H

View File

@ -13,7 +13,12 @@ public:
Bracket() {
Term();
mType = TermTypes::Brack;
mConstant = new Constant(1);
}
Bracket(vector<Term*> ts) {
Term();
mType = TermTypes::Brack;
mTerms = ts;
}
vector<Term*> mTerms;
@ -21,6 +26,8 @@ public:
void setConstant(Term* constant) {
mConstant = constant;
}
Term* GetConstant() const { return mConstant; }
private:
Term *mConstant;

View File

@ -23,8 +23,9 @@ public:
NValue mValue = DEF_N;
CValue mVariable = DEF_C;
CValue mOperator = DEF_C;
NValue mPower = 1;
CValue mOperator = DEF_C;
bool mSquareRoot = false;
int mType = -1;
};
#endif // !TERM_H

View File

@ -8,12 +8,11 @@ using namespace std;
class Variable : public Term {
public:
Variable(NValue val = 0, CValue var = DEF_C, NValue pwr = 1) {
Variable(NValue val = 1, CValue var = DEF_C, NValue pwr = 1) {
mValue = val;
mVariable = var;
mPower = pwr;
mType = TermTypes::Var;
}
};
#endif // !VARIABLE_H

View File

@ -1,3 +1,13 @@
/*
****************************************************
This Code Is Depreciated
Remade and tuned in:
tokenizer.h
****************************************************
*/
#ifndef TERM_PARSER_H
#define TERM_PARSER_H
#pragma once

View File

@ -1,3 +1,20 @@
/*
***************************************************************************
The goal of this class is to tokenize a string of equation and splits
it to mathematical term, with brackets begin a complete terms alone.
Ex:
2(5 + 9) - 56=90
If the above input was given to the main function in this class it must give an output of:
vector:
- 2(5 + 9)
- -
- 56
- =
- 90
***************************************************************************
*/
#ifndef TOKENIZER_H
#define TOKENIZER_H
#pragma once
@ -75,11 +92,11 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co
index++;
} while (!(!state && counter == 0));
bracks = retriveSubLexer(gen, Token(token->begin, index-1));
bracks = retriveSubLexer(gen, Token(token->begin, index - 1));
token->end = index - 1; // to make sure we move the token pointer to the end of bracks
// DELETE THIS BRACKET PARANTHESIS
bracks = retriveSubLexer(bracks, Token(1, bracks.size()-2));
bracks = retriveSubLexer(bracks, Token(1, bracks.size() - 2));
// Tokenize its term
// first make sure it is not empty
@ -102,6 +119,50 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co
return result;
}
static vector<Term*> combineBrackets(vector<Term*> terms) {
vector<Term*> result;
for (int i = 0; i < terms.size(); i++) {
auto term = terms[i];
if (term->mType == TermTypes::Op &&
(term->mOperator == '-' || term->mOperator == '+')) {
// if after it was a number
if (terms[i + 1]->mType == TermTypes::Const || terms[i + 1]->mType == TermTypes::Var) {
// check for safety
if (!(terms.size() <= i + 2))
// if after it was a bracket too
if (terms[i + 2]->mType == TermTypes::Brack) {
// if so combine the terms
Bracket* brack = new Bracket();
brack->mTerms = static_cast<Bracket*>(terms[i + 2])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 2])->GetConstant();
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->setConstant(constant);
result.push_back(brack);
i += 2;
continue;
}
}
else {
if (terms[i + 1]->mType == TermTypes::Brack) {
// if so combine the terms
Bracket* brack = new Bracket();
brack->mTerms = static_cast<Bracket*>(terms[i + 1])->mTerms;
auto constant = static_cast<Bracket*>(terms[i + 1])->GetConstant();
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
brack->setConstant(constant);
result.push_back(brack);
i += 1;
continue;
}
}
}
result.push_back(term);
}
return result;
}
static vector<Term*> tokenize(lexertk::generator lexed) {
vector<Term*> result;
@ -130,18 +191,38 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
/////// ENDING OF TREE
}
Variable* Var = nullptr;
Var = new Variable(atof(&lex.value[0]), after_lex.value[0], atof(&lexed[i + 3].value[0]));
result.push_back(Var);
tok.end = i + 3;
/////// ENDING OF TREE
// check for bracket
if (lexed[i + 4].value == "(") {
// bracket detected
tok.begin += 4; // consume coefficient
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value + lexed[i + 3].value));
/////// ENDING OF TREE
}
else {
// simple power variable
Variable* Var = nullptr;
Var = new Variable(atof(&lex.value[0]), after_lex.value[0], atof(&lexed[i + 3].value[0]));
result.push_back(Var);
tok.end = i + 3;
/////// ENDING OF TREE
}
}
else {
// The variable is simple!
Variable* Var = nullptr;
Var = new Variable(atof(&lex.value[0]), after_lex.value[0]);
result.push_back(Var);
tok.end = i + 1;
if (lexed[i + 2].value == "(") {
// bracket detected
tok.begin += 2;
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value));
/////// ENDING OF TREE
}
else {
// The variable is simple!
Variable* Var = nullptr;
Var = new Variable(atof(&lex.value[0]), after_lex.value[0]);
result.push_back(Var);
tok.end = i + 1;
/////// ENDING OF TREE
}
}
}
else if (isBrackets(after_lex.value[0]) && isBracketsOpening(after_lex.value[0])) {
@ -163,11 +244,18 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
/////// ENDING OF TREE
}
Constant* Const = nullptr;
Const = new Constant(atof(&lex.value[0]), atof(&lexed[i + 2].value[0]));
result.push_back(Const);
tok.end = i + 2;
/////// ENDING OF TREE
// check for brackets
if (lexed[i + 3].value == "(") {
tok.begin += 3;
result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value));
}
else {
Constant* Const = nullptr;
Const = new Constant(atof(&lex.value[0]), atof(&lexed[i + 2].value[0]));
result.push_back(Const);
tok.end = i + 2;
/////// ENDING OF TREE
}
}
else {
// The number is simple!
@ -219,6 +307,7 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
op = new Operator(lex.value[0]);
result.push_back(op);
tok.end = i;
}
else if (isEqualChar(lex.value[0])) {
// equal sign
@ -232,6 +321,8 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
i = tok.end; // no need to increment, automatically done in loop statment
}
result = combineBrackets(result);
return result;
}
#endif // !TOKENIZER_H

Binary file not shown.

Binary file not shown.

Binary file not shown.

17
notes2.txt Normal file
View File

@ -0,0 +1,17 @@
Term1 Term2
--------------
Var Var
Var Bracket
Var Const
Var Op
Const Const
Const Var
Const Bracket
Const Op
Bracket Bracket
Bracket Var
Bracket Const
Bracket Op
Op Var
Op Const
Op Bracket

43
notes3.txt Normal file
View File

@ -0,0 +1,43 @@
- Break brackets:
- Mutliply each child term with coefficeint, ignore operators.
- Solve:
- Rules:
// These ruls are not complete in the application we should take in mind
// that 'const * var' might come as 'var * const' and still evaluate to the same thing
// Also it must always evaluate using the 'TermHelper' class.
- const * const, eval
- const * var, eval
- const * bracket, eval
- const / const, eval
- const / var, eval
- const / bracket, eval
- const + const, eval
- const + var, eval
- const + bracket, eval
- const - const, eval
- const - var, eval
- const - bracket, eval
- Apply Rules, until no difference.
- Move variables to the right:
- Specific Rules:
// These rules are not complete in the application we should take in mind
// that 'const * var' might come as 'var * const' THIS IS FOR ALL RULES!
// Also it should evaluate to something like this, although not always:
- const * const, const * const
- const * var, const * var
- const * bracket, const * bracket
- const / const, const / const
- const / var, const / var
- const / bracket, const / bracket
- const + const, cosnt + const
- const + var, const + var
- const + bracket, const + bracket
- const - const, const - const
- const - var, const - var
- const - bracket, const - bracket
- Keep appling rules until there is no change.
BreakBrackets()
Move_Variables_To_The_Right()
Solve()