Files
Upsilon/apps/solver/test/equation_store.cpp
Léa Saviot 40c5196cee [test] Use strcmpWithSystemParentheses
Now there can be two types of parentheses : '(' or
UCodePointLeftSystemParenthesis. Because we do not want to complicate
the test results, when comparing a computed serialization and a result
we do not differentiate between the two types of parentheses.
2019-06-26 14:03:08 +02:00

269 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <quiz.h>
#include <apps/shared/global_context.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <cmath>
#include "../equation_store.h"
#include "../../../poincare/test/helper.h"
using namespace Poincare;
namespace Solver {
void addEquationWithText(EquationStore * equationStore, const char * text) {
Ion::Storage::Record::ErrorStatus err = equationStore->addEmptyModel();
assert(err == Ion::Storage::Record::ErrorStatus::None);
Ion::Storage::Record record = equationStore->recordAtIndex(equationStore->numberOfModels()-1);
Shared::ExpiringPointer<Equation> model = equationStore->modelForRecord(record);
model->setContent(text);
}
void assert_equation_system_exact_solve_to(const char * equations[], EquationStore::Error error, EquationStore::Type type, const char * variables[], const char * solutions[], int numberOfSolutions) {
Shared::GlobalContext globalContext;
EquationStore equationStore;
int index = 0;
while (equations[index] != 0) {
addEquationWithText(&equationStore, equations[index++]);
}
EquationStore::Error err = equationStore.exactSolve(&globalContext);
quiz_assert(err == error);
if (err != EquationStore::Error::NoError) {
equationStore.removeAll();
return;
}
quiz_assert(equationStore.type() == type);
quiz_assert(equationStore.numberOfSolutions() == numberOfSolutions);
if (numberOfSolutions == INT_MAX) {
equationStore.removeAll();
return;
}
if (type == EquationStore::Type::LinearSystem) {
for (int i = 0; i < numberOfSolutions; i++) {
quiz_assert(strcmpWithSystemParentheses(equationStore.variableAtIndex(i),variables[i]) == 0);
}
} else {
quiz_assert(strcmpWithSystemParentheses(equationStore.variableAtIndex(0), variables[0]) == 0);
}
constexpr int bufferSize = 200;
char buffer[bufferSize];
for (int i = 0; i < numberOfSolutions; i++) {
equationStore.exactSolutionLayoutAtIndex(i, true).serializeForParsing(buffer, bufferSize);
quiz_assert(strcmpWithSystemParentheses(buffer, solutions[i]) == 0);
}
equationStore.removeAll();
}
void assert_equation_approximate_solve_to(const char * equations, double xMin, double xMax, const char * variable, double solutions[], int numberOfSolutions, bool hasMoreSolutions) {
Shared::GlobalContext globalContext;
EquationStore equationStore;
addEquationWithText(&equationStore, equations);
EquationStore::Error err = equationStore.exactSolve(&globalContext);
quiz_assert(err == EquationStore::Error::RequireApproximateSolution);
equationStore.setIntervalBound(0, xMin);
equationStore.setIntervalBound(1, xMax);
equationStore.approximateSolve(&globalContext);
quiz_assert(equationStore.numberOfSolutions() == numberOfSolutions);
quiz_assert(strcmp(equationStore.variableAtIndex(0), variable)== 0);
for (int i = 0; i < numberOfSolutions; i++) {
quiz_assert(std::fabs(equationStore.approximateSolutionAtIndex(i) - solutions[i]) < 1E-5);
}
quiz_assert(equationStore.haveMoreApproximationSolutions(&globalContext) == hasMoreSolutions);
equationStore.removeAll();
}
QUIZ_CASE(equation_solve) {
// x+y+z+a+b+c+d = 0
const char * variables1[] = {""};
const char * equations0[] = {"x+y+z+a+b+c+d=0", 0};
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::TooManyVariables, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
// x^2+y = 0
const char * equations1[] = {"x^2+y=0", 0};
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NonLinearSystem, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
// cos(x) = 0
const char * equations2[] = {"cos(x)=0", 0};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::RequireApproximateSolution, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
// 2 = 0
const char * equations3[] = {"2=0", 0};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
// 0 = 0
const char * equations4[] = {"0=0", 0};
assert_equation_system_exact_solve_to(equations4, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, INT_MAX);
// x-x+2 = 0
const char * equations5[] = {"x-x+2=0", 0};
assert_equation_system_exact_solve_to(equations5, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
// x-x= 0
const char * equations6[] = {"x-x=0", 0};
assert_equation_system_exact_solve_to(equations6, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, INT_MAX);
const char * variablesx[] = {"x", ""};
// 2x+3=4
const char * equations7[] = {"2x+3=4", 0};
const char * solutions7[] = {"(1)/(2)"};
assert_equation_system_exact_solve_to(equations7, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions7, 1);
// 3x^2-4x+4=2
const char * equations8[] = {"3×x^2-4x+4=2", 0};
const char * solutions8[] = {"(2)/(3)-(√(2))/(3)·𝐢","(2)/(3)+(√(2))/(3)·𝐢", "-8"};
assert_equation_system_exact_solve_to(equations8, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions8, 3);
// 2×x^2-4×x+4=3
const char * equations9[] = {"2×x^2-4×x+4=3", 0};
const char * solutions9[] = {"(-√(2)+2)/(2)","(√(2)+2)/(2)", "8"};
assert_equation_system_exact_solve_to(equations9, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions9, 3);
// 2×x^2-4×x+2=0
const char * equations10[] = {"2×x^2-4×x+2=0", 0};
const char * solutions10[] = {"1", "0"};
assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions10, 2);
quiz_assert(UCodePointLeftSuperscript == '\022');
quiz_assert(UCodePointLeftSuperscript == '\x12');
quiz_assert(UCodePointRightSuperscript == '\023');
quiz_assert(UCodePointRightSuperscript == '\x13');
// x^2+x+1=3×x^2+pi×x-√(5)
const char * equations11[] = {"x^2+x+1=3×x^2+π×x-√(5)", 0};
const char * solutions11[] = {"(√(π\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "(-√(π\0222\023-2·π+8·√(5)+9)-π+1)/(4)", "π\0222\023-2·π+8·√(5)+9"};
assert_equation_system_exact_solve_to(equations11, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions11, 3);
// TODO
// x^3 - 4x^2 + 6x - 24 = 0
//const char * equations10[] = {"2×x^2-4×x+4=3", 0};
//assert_equation_system_exact_solve_to(equations10, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, {"x", ""}, {"4", "𝐢×√(6)", "-𝐢×√(6)", "-11616"}, 4);
//x^3+x^2+1=0
// x^3-3x-2=0
// Linear System
const char * equations12[] = {"x+y=0", 0};
assert_equation_system_exact_solve_to(equations12, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, INT_MAX);
const char * variablesxy[] = {"x", "y", ""};
const char * equations13[] = {"x+y=0", "3x+y=-5", 0};
const char * solutions13[] = {"-(5)/(2)", "(5)/(2)"};
assert_equation_system_exact_solve_to(equations13, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesxy, solutions13, 2);
const char * variablesxyz[] = {"x", "y", "z", ""};
const char * equations14[] = {"x+y=0", "3x+y+z=-5", "4z-π=0", 0};
const char * solutions14[] = {"(-π-20)/(8)", "(π+20)/(8)", "(π)/(4)"};
assert_equation_system_exact_solve_to(equations14, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesxyz, solutions14, 3);
// Monovariable non-polynomial equation
double solutions15[] = {-90.0, 90.0};
assert_equation_approximate_solve_to("cos(x)=0", -100.0, 100.0, "x", solutions15, 2, false);
double solutions16[] = {-810.0, -630.0, -450.0, -270.0, -90.0, 90.0, 270.0, 450.0, 630.0, 810.0};
assert_equation_approximate_solve_to("cos(x)=0", -900.0, 1000.0, "x", solutions16, 10, true);
double solutions17[] = {0};
assert_equation_approximate_solve_to("√(y)=0", -900.0, 1000.0, "y", solutions17, 1, false);
// Long variable names
const char * variablesabcde[] = {"abcde", ""};
const char * equations18[] = {"2abcde+3=4", 0};
const char * solutions18[] = {"(1)/(2)"};
assert_equation_system_exact_solve_to(equations18, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesabcde, solutions18, 1);
const char * variablesBig1Big2[] = {"Big1", "Big2", ""};
const char * equations19[] = {"Big1+Big2=0", "3Big1+Big2=-5", 0};
const char * solutions19[] = {"-(5)/(2)", "(5)/(2)"};
assert_equation_system_exact_solve_to(equations19, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesBig1Big2, solutions19, 2);
// conj(x)*x+1 = 0
const char * equations20one = "conj(x)*x+1=0";
const char * equations20[] = {equations20one, 0};
assert_equation_system_exact_solve_to(equations20, EquationStore::Error::RequireApproximateSolution, EquationStore::Type::LinearSystem, (const char **)variables1, nullptr, 0);
assert_equation_approximate_solve_to(equations20one, -100.0, 100.0, "x", nullptr, 0, false);
}
QUIZ_CASE(equation_solve_complex_format) {
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real);
const char * variablesx[] = {"x", ""};
// x+I = 0 --> x = -𝐢
const char * equations0[] = {"x+𝐢=0", 0};
const char * solutions0[] = {"-𝐢"};
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x+√(-1) = 0 --> Not defined in R
const char * equations1[] = {"x+√(-1)=0", 0};
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::EquationUnreal, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0);
// x^2+x+1=0 --> No solution in R
const char * equations2[] = {"x^2+x+1=0", 0};
const char * delta2[] = {"-3"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, delta2, 1);
// x^2-√(-1)=0 --> Not defined in R
const char * equations3[] = {"x^2-√(-1)=0", 0};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::EquationUnreal, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, nullptr, 0);
// x+√(-1)×√(-1) = 0 --> Not defined in R
const char * equations4[] = {"x+√(-1)×√(-1)=0", 0};
assert_equation_system_exact_solve_to(equations4, EquationStore::Error::EquationUnreal, EquationStore::Type::LinearSystem, (const char **)variablesx, nullptr, 0);
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian);
// x+𝐢 = 0 --> x = -𝐢
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x+√(-1) = 0 --> x = -𝐢
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0, 1);
// x^2+x+1=0
const char * solutions2[] = {"-(1)/(2)-(√(3))/(2)·𝐢","-(1)/(2)+(√(3))/(2)·𝐢", "-3"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2, 3);
// x^2-√(-1)=0
const char * solutions3[] = {"-(√(2))/(2)-(√(2))/(2)·𝐢", "(√(2))/(2)+(√(2))/(2)·𝐢","𝐢"};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3, 3);
// x+√(-1)×√(-1) = 0
const char * solutions4[] = {"1"};
assert_equation_system_exact_solve_to(equations4, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions4, 1);
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar);
// x+𝐢 = 0 --> x = e^(-π/2×i)
const char * solutions0Polar[] = {"\x12-(π)/(2)·𝐢\x13"};
assert_equation_system_exact_solve_to(equations0, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1);
// x+√(-1) = 0 --> x = e^(-π/2×𝐢)
assert_equation_system_exact_solve_to(equations1, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesx, solutions0Polar, 1);
// x^2+x+1=0
const char * solutions2Polar[] = {"\x12-(2·π)/(3)·𝐢\x13","\x12(2·π)/(3)·𝐢\x13", "\x12π·𝐢\x13"};
assert_equation_system_exact_solve_to(equations2, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions2Polar, 3);
// x^2-√(-1)=0
const char * solutions3Polar[] = {"\x12-(3·π)/(4)·𝐢\x13", "\x12(π)/(4)·𝐢\x13", "\x12(π)/(2)·𝐢\x13"};
assert_equation_system_exact_solve_to(equations3, EquationStore::Error::NoError, EquationStore::Type::PolynomialMonovariable, (const char **)variablesx, solutions3Polar, 3);
}
QUIZ_CASE(equation_and_symbolic_computation) {
// x+a=0 : non linear system
const char * equation[] = {"x+a=0", 0};
assert_equation_system_exact_solve_to(equation, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, nullptr, nullptr, INT_MAX);
// -3->a
Shared::GlobalContext globalContext;
Expression::ParseAndSimplify("-3→a", globalContext, Preferences::ComplexFormat::Polar, Preferences::AngleUnit::Degree);
// x+a = 0 : x = 3
const char * variables[] = {"x", ""};
const char * solutions[] = {"3"};
assert_equation_system_exact_solve_to(equation, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variables, solutions, 1);
// Clean the storage
Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy();
}
}