Files
Upsilon/apps/solver/test/equation_store.cpp
Arthur Camouseigt 913c81a0d3 [solver] Modified the way to solve some equations
The solutions of equations that need numerical approximations to be
solved are now computed base on the undeveloped equation (instead of
fully the expended one used to identify polynomials)

This allow (x-10)^7=0 to yield x=10 as result (9.95 before)
Change-Id: Ia8acbe57a9cfebf0b5016e9c896d21c8ddac7a64
2020-11-04 15:32:59 +01:00

189 lines
5.8 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 "helpers.h"
QUIZ_CASE(equation_solve) {
assert_solves_to_error("x+y+z+a+b+c+d=0", TooManyVariables);
assert_solves_to_error("x^2+y=0", NonLinearSystem);
assert_solves_to_error("cos(x)=0", RequireApproximateSolution);
assert_solves_to_no_solution("2=0");
assert_solves_to_no_solution("x-x+2=0");
assert_solves_to_infinite_solutions("0=0");
assert_solves_to_infinite_solutions("x-x=0");
assert_solves_to("2x+3=4", "x=1/2");
assert_solves_to("3×x^2-4x+4=2", {"x=2/3-(√(2)/3)𝐢", "x=2/3+(√(2)/3)𝐢", "delta=-8"});
assert_solves_to("2×x^2-4×x+4=3", {"x=(-√(2)+2)/2", "x=(√(2)+2)/2", "delta=8"});
assert_solves_to("2×x^2-4×x+2=0", {"x=1", "delta=0"});
assert_solves_to(
"x^2+x+1=3×x^2+π×x-√(5)",
{
"x=(√(π^2-2π+8√(5)+9)-π+1)/4",
"x=(-√(π^2-2π+8×√(5)+9)-π+1)/4",
"delta=π^2-2π+8√(5)+9"
}
);
assert_solves_to("(x-3)^2=0", {"x=3", "delta=0"});
/* TODO: Cubic
* x^3-4x^2+6x-24=0
* x^3+x^2+1=0
* x^3-3x-2=0 */
// Linear System
assert_solves_to_infinite_solutions("x+y=0");
assert_solves_to({"x+y=0", "3x+y=-5"}, {"x=-5/2", "y=5/2"});
assert_solves_to(
{
"x+y=0",
"3x+y+z=-5",
"4z-π=0"
},
{
"x=(-π-20)/8",
"y=(π+20)/8",
"z=π/4"
}
);
assert_solves_to(
{
"x+y=0",
"3x+y+z=-5",
"4z-π=0",
"a+b+c=0",
"a=3",
"c=a+2"
},
{
"x=(-π-20)/8",
"y=(π+20)/8",
"z=π/4",
"a=3",
"b=-8",
"c=5"
}
);
/* This test case needs the user defined variable. Indeed, in the equation
* store, m_variables is just before m_userVariables, so bad fetching in
* m_variables might fetch into m_userVariables and create problems. */
set("x", "0");
assert_solves_to_infinite_solutions({
"b=0",
"D=0",
"e=0",
"x+y+z+t=0"
});
unset("x");
// Monovariable non-polynomial equation
assert_solves_numerically_to("cos(x)=0", -100, 100, {-90.0, 90.0});
assert_solves_numerically_to("cos(x)=0", -900, 1000, {-810.0, -630.0, -450.0, -270.0, -90.0, 90.0, 270.0, 450.0, 630.0, 810.0});
assert_solves_numerically_to("√(y)=0", -900, 1000, {0}, "y");
// Long variable names
assert_solves_to("2abcde+3=4", "abcde=1/2");
assert_solves_to({"Big1+Big2=0", "3Big1+Big2=-5"}, {"Big1=-5/2", "Big2=5/2"});
// conj(x)*x+1 = 0
assert_solves_to_error("conj(x)*x+1=0", RequireApproximateSolution);
assert_solves_numerically_to("conj(x)*x+1=0", -100, 100, {});
assert_solves_to_error("(x-10)^7=0", RequireApproximateSolution);
assert_solves_numerically_to("(x-10)^7=0", -100, 100, {10});
}
QUIZ_CASE(equation_solve_complex_real) {
set_complex_format(Real);
assert_solves_to("x+𝐢=0", "x=-𝐢"); // We still want complex solutions if the input has some complex value
assert_solves_to_error("x+√(-1)=0", EquationUnreal);
assert_solves_to("x^2+x+1=0", {"delta=-3"});
assert_solves_to_error("x^2-√(-1)=0", EquationUnreal);
assert_solves_to_error("x+√(-1)×√(-1)=0", EquationUnreal);
assert_solves_to("root(-8,3)*x+3=0", "x=3/2");
reset_complex_format();
}
QUIZ_CASE(equation_solve_complex_cartesian) {
set_complex_format(Cartesian);
assert_solves_to("x+𝐢=0", "x=-𝐢");
assert_solves_to("x+√(-1)=0", "x=-𝐢");
assert_solves_to({"x^2+x+1=0"}, {"x=-1/2-((√(3))/2)𝐢", "x=-1/2+((√(3))/2)𝐢", "delta=-3"});
assert_solves_to("x^2-√(-1)=0", {"x=-√(2)/2-(√(2)/2)𝐢", "x=√(2)/2+(√(2)/2)𝐢", "delta=4𝐢"});
assert_solves_to("x+√(-1)×√(-1)=0", "x=1");
assert_solves_to("root(-8,3)*x+3=0", "x=-3/4+(3√(3)/4)*𝐢");
reset_complex_format();
}
QUIZ_CASE(equation_solve_complex_polar) {
set_complex_format(Polar);
assert_solves_to("x+𝐢=0", "x=^(-(π/2)𝐢)");
assert_solves_to("x+√(-1)=0", "x=^(-(π/2)𝐢)");
assert_solves_to("x^2+x+1=0", {"x=^(-(2π/3)𝐢)", "x=^((2π/3)𝐢)", "delta=3^(π𝐢)"});
assert_solves_to("x^2-√(-1)=0", {"x=^(-(3π/4)𝐢)", "x=^((π/4)𝐢)", "delta=4^((π/2)𝐢)"});
assert_solves_to("root(-8,3)*x+3=0", "x=3/2×^((2π/3)𝐢)");
reset_complex_format();
}
QUIZ_CASE(equation_and_symbolic_computation) {
assert_solves_to_infinite_solutions("x+a=0");
set("a", "-3");
assert_solves_to("x+a=0", "x=3");
assert_solves_to("a=0", "a=0");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = 0. */
set("b", "-4");
assert_solves_to_infinite_solutions("a+b=0");
/* The equation has no solution since the user defined a = -3 and b = -4.
* So neither a nor b are replaced with their context values. Therefore the
* solution is an infinity of solutions. */
assert_solves_to("a+b+c=0", "c=7");
assert_solves_to({"a+c=0", "a=3"}, {"a=3", "c=-3"});
/* The system has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = 3 and c = -3. */
set("f(x)", "x+1");
assert_solves_to("f(x)=0", "x=-1");
assert_solves_to("f(a)=0", "a=-1");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the solution is a = -1. */
set("g(x)", "a+x+2");
assert_solves_to("g(x)=0", "x=1");
assert_solves_to("g(a)=0", "a=-1");
/* The equation has no solution since the user defined a = -3. So a is not
* replaced with its context value, and the equation becomes a + a + 2 = 0.
* The solution is therefore a = -1. */
set("d", "5");
set("c", "d");
set("h(x)", "c+d+3");
assert_solves_to({"h(x)=0", "c=-3"}, {"c=-3", "d=0"});
// c and d context values should not be used
assert_solves_to({"c+d=5", "c-d=1"}, {"c=3", "d=2"});
set("e", "8_g");
assert_solves_to({"e+1=0"}, {"e=-1"});
unset("a");
unset("b");
unset("c");
unset("d");
unset("e");
unset("f");
unset("g");
unset("h");
}