parent
7ca9f7de84
commit
a7a28968c1
|
@ -83,7 +83,7 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
|
@ -121,7 +121,7 @@
|
|||
<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\QMReducerHelper.cpp" />
|
||||
<ClCompile Include="maths\solver\term_rewriter\QMEvalHelper.cpp" />
|
||||
<ClCompile Include="maths\solver\term_rewriter\QMRule.h" />
|
||||
<ClCompile Include="maths\solver\term_rewriter\ds\TermPool.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -129,9 +129,10 @@
|
|||
<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\QMReducerHelper.h" />
|
||||
<ClInclude Include="maths\solver\term_rewriter\QMEvalHelper.h" />
|
||||
<ClInclude Include="maths\solver\term_rewriter\QMRuleSet.h" />
|
||||
<ClInclude Include="maths\terms\Brackets.h" />
|
||||
<ClInclude Include="maths\terms\Bundle.h" />
|
||||
<ClInclude Include="maths\terms\Constant.h" />
|
||||
<ClInclude Include="maths\terms\Equal.h" />
|
||||
<ClInclude Include="maths\terms\Operator.h" />
|
||||
|
|
|
@ -24,15 +24,15 @@
|
|||
<ClCompile Include="maths\solver\term_rewriter\QMRule.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
<ClCompile Include="maths\solver\term_rewriter\QMEvalHelper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="maths\tokenizer.h">
|
||||
|
@ -77,9 +77,6 @@
|
|||
<ClInclude Include="maths\solver\term_rewriter\QMRuleSet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="maths\solver\term_rewriter\QMReducerHelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="maths\solver\term_rewriter\QMEvaluator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -89,5 +86,11 @@
|
|||
<ClInclude Include="maths\solver\term_rewriter\ds\ExprTree.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="maths\terms\Bundle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="maths\solver\term_rewriter\QMEvalHelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -8,20 +8,19 @@
|
|||
#include "maths/solver/Solver.h"
|
||||
#include "maths/Equations.h"
|
||||
|
||||
#include "maths/solver/term_rewriter/QMReducerHelper.h"
|
||||
#include "maths/solver/term_rewriter/QMEvalHelper.h"
|
||||
#include "maths/solver/term_rewriter/QMEvaluator.h"
|
||||
|
||||
#include "maths/solver/term_rewriter/ds/ExprTree.h"
|
||||
|
||||
//#define MAIN_APP
|
||||
#define APP_TEST
|
||||
#define MAIN_APP
|
||||
//#define APP_TEST
|
||||
|
||||
|
||||
#ifdef MAIN_APP
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
while (true) {
|
||||
|
@ -29,35 +28,19 @@ int main() {
|
|||
string input;
|
||||
cin >> input;
|
||||
|
||||
lexertk::generator generator;
|
||||
cout << "Solution: " << endl;
|
||||
|
||||
if (!generator.process(input)) {
|
||||
cout << "Failed to lex: " << input << endl;
|
||||
system("PAUSE");
|
||||
system("CLS");
|
||||
return true;
|
||||
}
|
||||
Solver solver;
|
||||
solver.Parse(input);
|
||||
solver.Solve();
|
||||
|
||||
//lexertk::helper::commutative_inserter ci;
|
||||
//ci.process(generator);
|
||||
|
||||
lexertk::helper::bracket_checker bc;
|
||||
bc.process(generator);
|
||||
|
||||
if (!bc.result()) {
|
||||
cout << "Failed Bracket Check!" << endl;
|
||||
system("PAUSE");
|
||||
system("CLS");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
lexertk::helper::dump(generator);
|
||||
#endif // DEBUG_MODE
|
||||
|
||||
Equation equation;
|
||||
equation.Parse(generator);
|
||||
for (auto *lwing : solver.mEquation->lwing)
|
||||
cout << lwing->to_str();
|
||||
cout << "=";
|
||||
for (auto *rwing : solver.mEquation->rwing)
|
||||
cout << rwing->to_str();
|
||||
|
||||
cout << endl;
|
||||
|
||||
system("PAUSE");
|
||||
system("CLS");
|
||||
|
@ -72,12 +55,23 @@ int main() {
|
|||
|
||||
int main() {
|
||||
lexertk::generator lexer;
|
||||
lexer.process("2/2*4^2");
|
||||
lexer.process("12341-(2x+3)");
|
||||
|
||||
auto result = tokenize(lexer);
|
||||
|
||||
auto res = evaluate(result);
|
||||
Solver solver;
|
||||
solver.Parse("4+3=4x+6");
|
||||
solver.Solve();
|
||||
|
||||
for (auto *lwing : solver.mEquation->lwing)
|
||||
cout << lwing->to_str();
|
||||
cout << "=";
|
||||
for (auto *rwing : solver.mEquation->rwing)
|
||||
cout << rwing->to_str();
|
||||
|
||||
cout << endl;
|
||||
|
||||
system("PAUSE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ struct Equation {
|
|||
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
|
||||
(left) ? lwing_str.append(expression[i].value) : rwing_str.append(expression[i].value); // append to wings
|
||||
}
|
||||
|
||||
// Tokenize wings
|
||||
|
|
|
@ -31,7 +31,7 @@ enum TermTypes {
|
|||
Op,
|
||||
Brack,
|
||||
Equ,
|
||||
Frac,
|
||||
Bund,
|
||||
};
|
||||
|
||||
// for string delimiter
|
||||
|
@ -176,4 +176,12 @@ static int gcf(int x, int y) {
|
|||
return gcd;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static bool IsInVector(vector<T> v, T elem) {
|
||||
for (auto *item : v)
|
||||
if (item == elem)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // !
|
||||
|
|
|
@ -1,35 +1,533 @@
|
|||
#include "Solver.h"
|
||||
|
||||
void Solver::Parse(string equation)
|
||||
{
|
||||
void Solver::Parse(string equation) {
|
||||
mEquation = new Equation();
|
||||
lexertk::generator lexer;
|
||||
lexer.process(equation);
|
||||
mEquation->Parse(lexer);
|
||||
}
|
||||
|
||||
Term * Solver::Solve()
|
||||
{
|
||||
return nullptr;
|
||||
Equation * Solver::Solve() {
|
||||
// Put vars on one side and consts on another
|
||||
mEquation = PutVarsInOneSide(mEquation);
|
||||
mEquation = PutConstsInOneSide(mEquation);
|
||||
|
||||
// Evaluate lwing and rwing
|
||||
mEquation->lwing = evaluate(mEquation->lwing);
|
||||
mEquation->rwing = evaluate(mEquation->rwing);
|
||||
|
||||
// Check For Diversion Calculations
|
||||
mEquation = ApplyDiversionCalcs(mEquation);
|
||||
|
||||
return mEquation;
|
||||
}
|
||||
|
||||
bool Solver::CheckValidOps(Equation * equ)
|
||||
{
|
||||
return false;
|
||||
vector<Term*> Solver::FlipTermSigns(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
|
||||
terms = RemNonEssientalOps(terms);
|
||||
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
auto term = terms[i];
|
||||
if (term->mType == TermTypes::Brack) {
|
||||
auto brack = static_cast<Bracket*>(term);
|
||||
if (brack->mConstant == nullptr) {
|
||||
brack->mConstant = new Constant(-1, 1);
|
||||
}
|
||||
else
|
||||
brack->mConstant->mValue = -brack->mConstant->mValue;
|
||||
res.push_back(brack);
|
||||
}
|
||||
else {
|
||||
term->mValue = -term->mValue;
|
||||
res.push_back(term);
|
||||
}
|
||||
}
|
||||
|
||||
res = AddNonEssientalOps(terms);
|
||||
return res;
|
||||
}
|
||||
|
||||
Equation * Solver::RemoveWeightOfWings(Equation * equ)
|
||||
{
|
||||
return nullptr;
|
||||
Equation * Solver::ApplyDiversionCalcs(Equation * equ) {
|
||||
// Situations
|
||||
// 2x = 50 -> x = 50/2, applies only if one var
|
||||
|
||||
auto lwing = RemNonEssientalOps(equ->lwing);
|
||||
auto rwing = RemNonEssientalOps(equ->rwing);
|
||||
|
||||
if (lwing.size() == 1) {
|
||||
// Check if x's coeffiecent is higher than 1 or lower
|
||||
if (lwing[0]->mValue != 1 && lwing[0]->mPower == 1) {
|
||||
// situation of "2x = 50 -> x = 50/2" is confirmed
|
||||
auto domin = lwing[0]->mValue;
|
||||
Bracket* brack = new Bracket();
|
||||
for (int i = 0; i < rwing.size(); i++)
|
||||
brack->mTerms.push_back(rwing[i]);
|
||||
auto term = QMEvalHelper::Div(brack, new Constant(domin));
|
||||
rwing.clear();
|
||||
rwing = term;
|
||||
lwing[0]->mValue = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
equ->lwing = lwing;
|
||||
equ->rwing = rwing;
|
||||
return equ;
|
||||
}
|
||||
|
||||
Equation * Solver::OrderTerms(Equation * equ)
|
||||
{
|
||||
return nullptr;
|
||||
bool Solver::CheckValidOps(Equation * equ) {
|
||||
|
||||
// Check Lwing
|
||||
for (int i = 0; i < equ->lwing.size() - 1; i++) {
|
||||
auto term = equ->lwing[i];
|
||||
if (term->mType == TermTypes::Op) {
|
||||
if (i == 0) {
|
||||
if (term->mOperator == '/' || term->mOperator == '*') {
|
||||
cout << "Can't have division or multiplication at the begining!" << endl;
|
||||
system("PUASE");
|
||||
exit(0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
auto before_Term = equ->lwing[i - 1];
|
||||
auto after_Term = equ->lwing[i + 1];
|
||||
|
||||
if (before_Term->mType == TermTypes::Op ||
|
||||
after_Term->mType == TermTypes::Op) {
|
||||
cout << "Can't have trialing operators!" << endl;
|
||||
system("PUASE");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check Rwing
|
||||
for (int i = 0; i < equ->rwing.size() - 1; i++) {
|
||||
auto term = equ->rwing[i];
|
||||
if (term->mType == TermTypes::Op) {
|
||||
if (i == 0) {
|
||||
if (term->mOperator == '/' || term->mOperator == '*') {
|
||||
cout << "Can't have division or multiplication at the begining!" << endl;
|
||||
system("PUASE");
|
||||
exit(0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
auto before_Term = equ->rwing[i - 1];
|
||||
auto after_Term = equ->rwing[i + 1];
|
||||
|
||||
if (before_Term->mType == TermTypes::Op ||
|
||||
after_Term->mType == TermTypes::Op) {
|
||||
cout << "Can't have trialing operators!" << endl;
|
||||
system("PUASE");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Equation * Solver::CheckDiversionCalcs(Equation * equ)
|
||||
{
|
||||
return nullptr;
|
||||
Equation * Solver::PutVarsInOneSide(Equation * equ) {
|
||||
Equation* res = new Equation();
|
||||
|
||||
vector<Term*> lwing = OrderTermsByValue(equ->lwing);
|
||||
vector<Term*> rwing = OrderTermsByValue(equ->rwing);
|
||||
|
||||
lwing = RemNonEssientalOps(lwing);
|
||||
rwing = RemNonEssientalOps(rwing);
|
||||
|
||||
vector<int> lwing_vars;
|
||||
vector<int> rwing_vars;
|
||||
|
||||
// Find vars and place them in lwing_vars or rwing_vars
|
||||
for (int i = 0; i < lwing.size(); i++) {
|
||||
if (lwing[i]->mType == TermTypes::Bund) {
|
||||
// check if it has a variable
|
||||
Bundle* bundle = static_cast<Bundle*>(lwing[i]);
|
||||
bool contains = false;
|
||||
for (auto *term : bundle->mTerms)
|
||||
if (term->mType == TermTypes::Var) { contains = true; continue; }
|
||||
|
||||
if (contains)
|
||||
lwing_vars.push_back(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lwing[i]->mType == TermTypes::Var)
|
||||
lwing_vars.push_back(i);
|
||||
}
|
||||
for (int i = 0; i < rwing.size(); i++) {
|
||||
if (rwing[i]->mType == TermTypes::Bund) {
|
||||
// check if it has a variable
|
||||
Bundle* bundle = static_cast<Bundle*>(rwing[i]);
|
||||
bool contains = false;
|
||||
for (auto *term : bundle->mTerms)
|
||||
if (term->mType == TermTypes::Var) { contains = true; continue; }
|
||||
|
||||
if (contains)
|
||||
rwing_vars.push_back(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rwing[i]->mType == TermTypes::Var)
|
||||
rwing_vars.push_back(i);
|
||||
}
|
||||
|
||||
// place variables
|
||||
for (auto lwing_term : lwing_vars)
|
||||
res->lwing.push_back(lwing[lwing_term]);
|
||||
|
||||
for (auto rwing_term : rwing_vars) {
|
||||
auto term = rwing[rwing_term];
|
||||
term->mValue = -term->mValue;
|
||||
res->lwing.push_back(term);
|
||||
}
|
||||
|
||||
// place other terms
|
||||
for (int i = 0; i < lwing.size(); i++) {
|
||||
if (std::find(lwing_vars.begin(), lwing_vars.end(), i) != lwing_vars.end()) {
|
||||
// variable encouterd
|
||||
continue;
|
||||
}
|
||||
|
||||
res->lwing.push_back(lwing[i]);
|
||||
}
|
||||
for (int i = 0; i < rwing.size(); i++) {
|
||||
if (std::find(rwing_vars.begin(), rwing_vars.end(), i) != rwing_vars.end()) {
|
||||
// variable encouterd
|
||||
continue;
|
||||
}
|
||||
|
||||
res->rwing.push_back(rwing[i]);
|
||||
}
|
||||
|
||||
res->lwing = AddNonEssientalOps(res->lwing);
|
||||
res->rwing = AddNonEssientalOps(res->rwing);
|
||||
|
||||
return res;
|
||||
}
|
||||
Equation * Solver::PutConstsInOneSide(Equation * equ) {
|
||||
Equation* res = new Equation();
|
||||
|
||||
vector<Term*> lwing = OrderTermsByValue(equ->lwing);
|
||||
vector<Term*> rwing = OrderTermsByValue(equ->rwing);
|
||||
|
||||
lwing = RemNonEssientalOps(lwing);
|
||||
rwing = RemNonEssientalOps(rwing);
|
||||
|
||||
vector<int> lwing_const;
|
||||
vector<int> rwing_const;
|
||||
|
||||
// Make lwing_const
|
||||
for (int i = 0; i < lwing.size(); i++) {
|
||||
if (lwing[i]->mType == TermTypes::Bund) {
|
||||
// check if it has a constant
|
||||
Bundle* bundle = static_cast<Bundle*>(lwing[i]);
|
||||
bool contains = false;
|
||||
for (auto *term : bundle->mTerms)
|
||||
if (term->mType == TermTypes::Const) { contains = true; continue; }
|
||||
|
||||
if (contains)
|
||||
lwing_const.push_back(i);
|
||||
continue;
|
||||
}
|
||||
if (lwing[i]->mType == TermTypes::Const)
|
||||
lwing_const.push_back(i);
|
||||
}
|
||||
// Make rwing_const
|
||||
for (int i = 0; i < rwing.size(); i++) {
|
||||
if (rwing[i]->mType == TermTypes::Bund) {
|
||||
// check if it has a cosnstant
|
||||
Bundle* bundle = static_cast<Bundle*>(rwing[i]);
|
||||
bool contains = false;
|
||||
for (auto *term : bundle->mTerms)
|
||||
if (term->mType == TermTypes::Const) { contains = true; continue; }
|
||||
|
||||
if (contains)
|
||||
rwing_const.push_back(i);
|
||||
continue;
|
||||
}
|
||||
if (rwing[i]->mType == TermTypes::Const)
|
||||
rwing_const.push_back(i);
|
||||
}
|
||||
|
||||
// Place lwing constants in res->rwing
|
||||
for (auto i : lwing_const) {
|
||||
auto term = lwing[i];
|
||||
term->mValue = -term->mValue;
|
||||
res->rwing.push_back(term);
|
||||
}
|
||||
// Place rwing constants in res->rwing
|
||||
for (auto i : rwing_const)
|
||||
res->rwing.push_back(rwing[i]);
|
||||
|
||||
// Place other terms of lwing to res->lwing
|
||||
for (int i = 0; i < lwing.size(); i++) {
|
||||
if (std::find(lwing_const.begin(), lwing_const.end(), i) != lwing_const.end()) {
|
||||
// constant encouterd
|
||||
continue;
|
||||
}
|
||||
res->lwing.push_back(lwing[i]);
|
||||
}
|
||||
|
||||
// Place other terms of rwing to res->rwing
|
||||
for (int i = 0; i < rwing.size(); i++) {
|
||||
if (std::find(rwing_const.begin(), rwing_const.end(), i) != rwing_const.end()) {
|
||||
// constant encouterd
|
||||
continue;
|
||||
}
|
||||
res->rwing.push_back(rwing[i]);
|
||||
}
|
||||
|
||||
res->lwing = AddNonEssientalOps(res->lwing);
|
||||
res->rwing = AddNonEssientalOps(res->rwing);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Equation * Solver::DoDiversionCalcs(Equation * equ)
|
||||
{
|
||||
return nullptr;
|
||||
vector<Term*> Solver::RemNonEssientalOps(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
auto term = terms[i];
|
||||
if (term->mType == TermTypes::Op) {
|
||||
if (term->mOperator == '+') {
|
||||
auto after_term = terms[i + 1];
|
||||
after_term->mValue = abs(after_term->mValue);
|
||||
res.push_back(after_term);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (term->mOperator == '-') {
|
||||
auto after_term = terms[i+1];
|
||||
after_term->mValue = after_term->mValue * -1;
|
||||
res.push_back(after_term);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (term->mOperator == '*') {
|
||||
auto before_term = *res.end();
|
||||
res.pop_back();
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term);
|
||||
bundle->mTerms.push_back(term);
|
||||
bundle->mTerms.push_back(after_term);
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (term->mOperator == '/') {
|
||||
auto before_term = *(--res.end());
|
||||
res.pop_back();
|
||||
auto after_term = terms[i+1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term);
|
||||
bundle->mTerms.push_back(term);
|
||||
bundle->mTerms.push_back(after_term);
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
res.push_back(term);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
vector<Term*> Solver::AddNonEssientalOps(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
auto term = terms[i];
|
||||
if (i == 0) {
|
||||
res.push_back(term);
|
||||
continue;
|
||||
}
|
||||
if (term->mType == TermTypes::Bund) {
|
||||
auto bundle = static_cast<Bundle*>(term);
|
||||
for (auto *_term : bundle->mTerms)
|
||||
res.push_back(_term);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (term->mType == TermTypes::Brack) {
|
||||
res.push_back(term);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if term was positive
|
||||
if (term->mValue > 0) {
|
||||
res.push_back(new Operator('+'));
|
||||
res.push_back(term);
|
||||
continue;
|
||||
}
|
||||
else if (term->mValue < 0) {
|
||||
term->mValue = abs(term->mValue);
|
||||
res.push_back(new Operator('-'));
|
||||
res.push_back(term);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Bundle * Solver::BuildBundle(vector<Term*> terms) {
|
||||
Bundle* bundle = new Bundle();
|
||||
for (int i = 0; i < terms.size(); i++)
|
||||
bundle->mTerms.push_back(terms[i]);
|
||||
return bundle;
|
||||
}
|
||||
vector<Term*> Solver::BreakBundle(Bundle * bundle) {
|
||||
vector<Term*> res;
|
||||
for (auto *item : bundle->mTerms)
|
||||
res.push_back(item);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<Term*> Solver::BundleTermsDuo(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
auto term = terms[i];
|
||||
if (term->mType == TermTypes::Op) {
|
||||
if (term->mOperator == '/') {
|
||||
if (i == 0) {
|
||||
// invalid cant have division at begining
|
||||
cout << "Can't have division at begining!" << endl;
|
||||
system("PAUSE");
|
||||
exit(0);
|
||||
}
|
||||
auto before_term = terms[i-1];
|
||||
auto after_term = terms[i +1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term); // t1
|
||||
bundle->mTerms.push_back(term); // op
|
||||
bundle->mTerms.push_back(after_term); // t2
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// if it was a multiplication
|
||||
if (term->mOperator == '*') {
|
||||
if (i == 0) {
|
||||
// invalid cant have multiplication at begining
|
||||
cout << "Can't have multiplication at begining!" << endl;
|
||||
system("PAUSE");
|
||||
exit(0);
|
||||
}
|
||||
auto before_term = terms[i-1];
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term); // t1
|
||||
bundle->mTerms.push_back(term); // op
|
||||
bundle->mTerms.push_back(after_term); // t2
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it was not division and not multiplication
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(term); // operator
|
||||
bundle->mTerms.push_back(after_term); // term
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
res.push_back(term);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
vector<Term*> Solver::BundleTermsTri(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
auto term = terms[i];
|
||||
if (term->mType == TermTypes::Op) {
|
||||
if (term->mOperator == '/') {
|
||||
if (i == 0) {
|
||||
// invalid cant have division at begining
|
||||
cout << "Can't have division at begining!" << endl;
|
||||
system("PUASE");
|
||||
exit(0);
|
||||
}
|
||||
auto before_term = terms[i - 1];
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term); // t1
|
||||
bundle->mTerms.push_back(term); // op
|
||||
bundle->mTerms.push_back(after_term); // t2
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// if it was a multiplication
|
||||
if (term->mOperator == '*') {
|
||||
if (i == 0) {
|
||||
// invalid cant habe multiplication at begining
|
||||
cout << "Can't have multiplication at beginign!" << endl;
|
||||
system("PAUSE");
|
||||
exit(0);
|
||||
}
|
||||
auto before_term = terms[i - 1];
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term); // t1
|
||||
bundle->mTerms.push_back(term); // op
|
||||
bundle->mTerms.push_back(after_term); // t2
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it was not division and not multiplication
|
||||
auto before_term = terms[i - 1];
|
||||
auto after_term = terms[i + 1];
|
||||
Bundle* bundle = new Bundle();
|
||||
bundle->mTerms.push_back(before_term);
|
||||
bundle->mTerms.push_back(term);
|
||||
bundle->mTerms.push_back(after_term);
|
||||
res.push_back(bundle);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
res.push_back(term);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Solver::IsEqualBundle(Bundle * b1, Bundle * b2) {
|
||||
auto b1_copy = OrderTermsByValue(b1->mTerms);
|
||||
auto b2_copy = OrderTermsByValue(b2->mTerms);
|
||||
|
||||
if (b1_copy.size() != b2_copy.size()) return false;
|
||||
|
||||
for (int i = 0; i < b1_copy.size(); i++)
|
||||
if (!QMEvalHelper::IsEquTerms(b1_copy[i], b2_copy[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<Term*> Solver::OrderTermsByValue(vector<Term*> terms) {
|
||||
vector<Term*> res;
|
||||
res = RemNonEssientalOps(terms);
|
||||
stable_sort(res.begin(), res.end(), QMEvalHelper::IsHigherSig);
|
||||
res = AddNonEssientalOps(res);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -11,25 +11,44 @@
|
|||
#include "../terms/Variable.h"
|
||||
#include "../terms/Paranthesis.h"
|
||||
#include "../tokenizer.h"
|
||||
#include "../terms/Bundle.h"
|
||||
|
||||
#include "../../vendor/lexertk.hpp"
|
||||
|
||||
#include "term_rewriter/QMEvalHelper.h"
|
||||
#include "term_rewriter/QMEvaluator.h"
|
||||
|
||||
class Solver {
|
||||
public:
|
||||
void Parse(string equation);
|
||||
Term* Solve();
|
||||
Equation* Solve();
|
||||
|
||||
public: // PRIVATE MEMBERS TODO: MARK PRIVATE IN FINAL BUILD
|
||||
Equation* equation = nullptr;
|
||||
public: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD
|
||||
Equation* mEquation = nullptr;
|
||||
|
||||
private: // Mathematics Side Class Todo: Mark Private in final build
|
||||
vector<Term*> FlipTermSigns(vector<Term*> terms);
|
||||
|
||||
Equation* ApplyDiversionCalcs(Equation* equ);
|
||||
|
||||
private: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD
|
||||
bool CheckValidOps(Equation* equ);
|
||||
|
||||
Equation* RemoveWeightOfWings(Equation* equ);
|
||||
Equation* OrderTerms(Equation* equ);
|
||||
Equation* PutVarsInOneSide(Equation* equ);
|
||||
Equation* PutConstsInOneSide(Equation* equ);
|
||||
|
||||
Equation* CheckDiversionCalcs(Equation* equ);
|
||||
Equation* DoDiversionCalcs(Equation* equ);
|
||||
vector<Term*> RemNonEssientalOps(vector<Term*> terms);
|
||||
vector<Term*> AddNonEssientalOps(vector<Term*> terms);
|
||||
|
||||
Bundle* BuildBundle(vector<Term*> term);
|
||||
vector<Term*> BreakBundle(Bundle* bundle);
|
||||
|
||||
vector<Term*> BundleTermsDuo(vector<Term*> terms);
|
||||
vector<Term*> BundleTermsTri(vector<Term*> terms);
|
||||
|
||||
bool IsEqualBundle(Bundle* b1, Bundle* b2);
|
||||
|
||||
vector<Term*> OrderTermsByValue(vector<Term*> terms);
|
||||
};
|
||||
|
||||
#endif // !1
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "QMReducerHelper.h"
|
||||
#include "QMEvalHelper.h"
|
||||
|
||||
vector<IdsWithTerms> QMEvalHelper::convertRangeToIds(vector<Term*> range) {
|
||||
vector<IdsWithTerms> result;
|
||||
|
@ -44,13 +44,13 @@ bool QMEvalHelper::IsSolvable(Term * t1, Operator * op, Term * t2) {
|
|||
vector<Term*> QMEvalHelper::BreakBracket(Bracket * brack, bool order, Identifier_t order_type) {
|
||||
vector<Term*> res;
|
||||
|
||||
if (brack->GetConstant() == nullptr) {
|
||||
if (brack->mConstant == 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]);
|
||||
auto returns = Mul(brack->mConstant, brack->mTerms[i]);
|
||||
for (int j = 0; j < returns.size(); j++)
|
||||
res.push_back(returns[j]);
|
||||
}
|
||||
|
@ -91,12 +91,13 @@ Constant * QMEvalHelper::convertToConstant(Term * t1) {
|
|||
bool QMEvalHelper::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
|
||||
if (t1->mType == TermTypes::Brack)
|
||||
return true;
|
||||
else if (t1->mType == TermTypes::Op)
|
||||
if (t1->mType == TermTypes::Op)
|
||||
return false;
|
||||
else if (t2->mType == TermTypes::Op)
|
||||
if (t2->mType == TermTypes::Op)
|
||||
return true;
|
||||
if (t1->mType == TermTypes::Var) {
|
||||
// its a var check for other term
|
||||
if (t2->mType == TermTypes::Bund) return false;
|
||||
if (t2->mType == TermTypes::Brack) return false;
|
||||
|
||||
if (t2->mType == TermTypes::Var) {
|
||||
|
@ -106,22 +107,29 @@ bool QMEvalHelper::IsHigherSig(Term * t1, Term * t2) { // x^2 > x : true
|
|||
return t1->mValue >= t2->mValue;
|
||||
}
|
||||
// if t1 has higher or equal power
|
||||
if (t1->mPower >= t2->mPower) return true;
|
||||
if (t1->mPower >= t2->mPower)
|
||||
return true;
|
||||
else return false; // t2 is higher
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (t1->mType == TermTypes::Const) {
|
||||
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;
|
||||
if (t1->mValue > t2->mValue) return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (t1->mType == TermTypes::Bund)
|
||||
return true;
|
||||
if (t2->mType == TermTypes::Bund)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -485,7 +493,7 @@ vector<Term*> QMEvalHelper::FactorizeTermsToBrack(vector<Term*> terms, vector<Te
|
|||
|
||||
// make first bracket
|
||||
Bracket* brack1 = new Bracket();
|
||||
brack1->setConstant(HCF_all);
|
||||
brack1->mConstant = HCF_all;
|
||||
for (int i = 0; i < terms.size(); i++)
|
||||
if (terms[i]->mType != TermTypes::Op)
|
||||
brack1->mTerms.push_back(Div(terms[i], HCF_all)[0]);
|
||||
|
@ -493,7 +501,7 @@ vector<Term*> QMEvalHelper::FactorizeTermsToBrack(vector<Term*> terms, vector<Te
|
|||
|
||||
// make second bracket
|
||||
Bracket* brack2 = new Bracket();
|
||||
brack2->setConstant(HCF_all);
|
||||
brack2->mConstant = HCF_all;
|
||||
for (int i = 0; i < terms2.size(); i++)
|
||||
if (terms2[i]->mType != TermTypes::Op)
|
||||
brack2->mTerms.push_back(Div(terms2[i], HCF_all)[0]);
|
||||
|
@ -510,7 +518,7 @@ vector<Term*> QMEvalHelper::FactorizeTermsToBrack(vector<Term*> allTerms) {
|
|||
|
||||
// make bracket
|
||||
Bracket* brack = new Bracket();
|
||||
brack->setConstant(HCF_all);
|
||||
brack->mConstant = HCF_all;
|
||||
for (int i = 0; i < allTerms.size(); i++)
|
||||
if (allTerms[i]->mType != TermTypes::Op)
|
||||
brack->mTerms.push_back(Div(allTerms[i], HCF_all)[0]);
|
||||
|
@ -582,16 +590,16 @@ vector<Term*> QMEvalHelper::Div(Term * t1, Term * t2, Identifier_t order) {
|
|||
if (TermsMatch(fraction_nomin->mTerms, fraction_domin->mTerms))
|
||||
// common bracket terms matched
|
||||
// TIME FOR RECURSION!
|
||||
return Div(fraction_nomin->GetConstant(), fraction_domin->GetConstant());
|
||||
return Div(fraction_nomin->mConstant, fraction_domin->mConstant);
|
||||
|
||||
// check if taking out common factors make common bracket coeffiecient
|
||||
auto fraction = FactorizeTermsToBrack(t1_brack->mTerms, t2_brack->mTerms);
|
||||
// fraction[0] is nomin
|
||||
// fraction[1] is domin
|
||||
fraction_nomin = convertToBracket(fraction[0]);
|
||||
fraction_nomin->setConstant(nullptr); // Nullptr == 1
|
||||
fraction_nomin->mConstant = nullptr; // Nullptr == 1
|
||||
fraction_domin = convertToBracket(fraction[1]);
|
||||
fraction_domin->setConstant(nullptr); // Nullptr == 1
|
||||
fraction_domin->mConstant = nullptr; // Nullptr == 1
|
||||
|
||||
vector<Term*> res;
|
||||
for (int i = 0; i < fraction_nomin->mTerms.size(); i++)
|
||||
|
@ -649,7 +657,7 @@ vector<Term*> QMEvalHelper::Div(Term * t1, Term * t2, Identifier_t order) {
|
|||
|
||||
auto fraction = FactorizeTermsToBrack({ t1 }, t2_Brack->mTerms);
|
||||
|
||||
auto comfac = convertToBracket(fraction[0])->GetConstant();
|
||||
auto comfac = convertToBracket(fraction[0])->mConstant;
|
||||
|
||||
vector<Term*> res;
|
||||
for (auto *term : convertToBracket(fraction[0])->mTerms)
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef QMREDUCER_H
|
||||
#define QMREDUCER_H
|
||||
#ifndef QMEVAL_HELPER_H
|
||||
#define QMEVAL_HELPER_H
|
||||
#pragma once
|
||||
// WARINING: Only one variable is allowed or errors will happen!
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
#include "ds/ExprTree.h"
|
||||
#include "ds/TermPool.h"
|
||||
|
||||
TermPool mPool;
|
||||
static TermPool mPool;
|
||||
static vector<Term*> solveNode(TreeNode * node) {
|
||||
if (node->_term->mType != TermTypes::Op) return { node->_term };
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "../../../tokenizer.h"
|
||||
|
||||
#include "../../../../vendor/lexertk.hpp"
|
||||
#include "../QMReducerHelper.h"
|
||||
#include "../QMEvalHelper.h"
|
||||
#include "TermPool.h"
|
||||
|
||||
struct TreeNode {
|
||||
|
|
|
@ -20,12 +20,8 @@ public:
|
|||
}
|
||||
|
||||
vector<Term*> mTerms;
|
||||
Term *mConstant = nullptr; // Nullptr == 1
|
||||
|
||||
void setConstant(Term* constant) {
|
||||
mConstant = constant;
|
||||
}
|
||||
|
||||
Term* GetConstant() const { return mConstant; }
|
||||
|
||||
string to_str() override {
|
||||
string str;
|
||||
|
@ -33,12 +29,13 @@ public:
|
|||
if (mConstant != nullptr)
|
||||
str.append(mConstant->to_str());
|
||||
|
||||
str.append("(");
|
||||
|
||||
for (int i = 0; i < mTerms.size(); i++)
|
||||
str.append(mTerms[i]->to_str());
|
||||
|
||||
str.append(")");
|
||||
return str;
|
||||
}
|
||||
|
||||
private:
|
||||
Term *mConstant = nullptr; // Nullptr == 1
|
||||
};
|
||||
#endif // !BRACKET_H
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef BUNDLE_H
|
||||
#pragma once
|
||||
#include "../defines.h"
|
||||
#include "Term.h"
|
||||
using namespace std;
|
||||
|
||||
// An Abstract term for representing bundles of terms
|
||||
// Ex: 2x/4x
|
||||
|
||||
class Bundle : public Term {
|
||||
public:
|
||||
Bundle() : Term() { mType = TermTypes::Bund; }
|
||||
Bundle(vector<Term*> terms) : Term() { mType = TermTypes::Bund; mTerms = terms; }
|
||||
|
||||
string to_str() override {
|
||||
string str;
|
||||
for (int i = 0; i < mTerms.size(); i++)
|
||||
str.append(mTerms[i]->to_str());
|
||||
return str;
|
||||
}
|
||||
|
||||
vector<Term*> mTerms;
|
||||
};
|
||||
|
||||
#endif // !BUNDLE_H
|
|
@ -14,7 +14,9 @@ public:
|
|||
mPower = pwr;
|
||||
}
|
||||
|
||||
virtual string to_str() { return "TERM_UNKNOWN"; };
|
||||
virtual string to_str() {
|
||||
return "TERM_UNKNOWN";
|
||||
};
|
||||
|
||||
NValue mValue = DEF_N;
|
||||
CValue mVariable = DEF_C;
|
||||
|
|
|
@ -114,7 +114,7 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co
|
|||
if (coefficient != "") {
|
||||
lexertk::generator lex;
|
||||
lex.process(coefficient);
|
||||
result->setConstant(tokenize(lex)[0]);
|
||||
result->mConstant = tokenize(lex)[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -136,9 +136,9 @@ static vector<Term*> combineBrackets(vector<Term*> terms) {
|
|||
// 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();
|
||||
auto constant = static_cast<Bracket*>(terms[i + 2])->mConstant;
|
||||
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
|
||||
brack->setConstant(constant);
|
||||
brack->mConstant = constant;
|
||||
result.push_back(brack);
|
||||
i += 2;
|
||||
continue;
|
||||
|
@ -149,9 +149,17 @@ static vector<Term*> combineBrackets(vector<Term*> terms) {
|
|||
// 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);
|
||||
auto constant = static_cast<Bracket*>(terms[i + 1])->mConstant;
|
||||
if (constant == nullptr) { // 1
|
||||
Constant* Const = new Constant();
|
||||
if (term->mOperator == '+')
|
||||
Const->mValue = 1;
|
||||
else Const->mValue = -1;
|
||||
}
|
||||
else {
|
||||
constant->mValue *= (term->mOperator == '+') ? +1 : -1;
|
||||
brack->mConstant = constant;
|
||||
}
|
||||
result.push_back(brack);
|
||||
i += 1;
|
||||
continue;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,19 @@
|
|||
QMReducerHelper.cpp
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\term.h(10): warning C4309: 'default argument': truncation of constant value
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\term.h(22): warning C4305: 'initializing': truncation from 'int' to 'CValue'
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\term.h(22): warning C4309: 'initializing': truncation of constant value
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\term.h(24): warning C4305: 'initializing': truncation from 'int' to 'CValue'
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\term.h(24): warning C4309: 'initializing': truncation of constant value
|
||||
r:\projects\quicmaf\quicmaf\maths\terms\variable.h(11): warning C4309: 'default argument': truncation of constant value
|
||||
r:\projects\quicmaf\quicmaf\maths\tokenizer.h(99): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
|
||||
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmruleset.h(34): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
|
||||
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(445): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
|
||||
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(453): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
|
||||
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(464): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
|
||||
r:\projects\quicmaf\quicmaf\maths\solver\term_rewriter\qmreducerhelper.cpp(472): warning C4244: 'argument': conversion from 'NValue' to 'int', possible loss of data
|
||||
Generating code
|
||||
2 of 790 functions ( 0.3%) were compiled, the rest were copied from previous compilation.
|
||||
0 functions were new in current compilation
|
||||
1 functions had inline decision re-evaluated but remain unchanged
|
||||
Finished generating code
|
||||
QuicMaf.vcxproj -> R:\Projects\QuicMaf\x64\Release\QuicMaf.exe
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
|
||||
Release|x64|R:\Projects\QuicMaf\|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue