1081 lines
26 KiB
C++
1081 lines
26 KiB
C++
//This file is part of Bertini 2.
|
|
//
|
|
//system_test.cpp is free software: you can redistribute it and/or modify
|
|
//it under the terms of the GNU General Public License as published by
|
|
//the Free Software Foundation, either version 3 of the License, or
|
|
//(at your option) any later version.
|
|
//
|
|
//system_test.cpp is distributed in the hope that it will be useful,
|
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
//GNU General Public License for more details.
|
|
//
|
|
//You should have received a copy of the GNU General Public License
|
|
//along with system_test.cpp. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
|
//
|
|
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
|
// as well as COPYING. Bertini2 is provided with permitted
|
|
// additional terms in the b2/licenses/ directory.
|
|
|
|
// individual authors of this file include:
|
|
// silviana amethyst, university of wisconsin eau claire
|
|
|
|
// system_test.cpp
|
|
//
|
|
// Created by Collins, James B. on 4/30/15.
|
|
// Copyright (c) 2015 West Texas A&M University. All rights reserved.
|
|
|
|
/**
|
|
\file system_test.cpp Unit testing for the bertini::System class.
|
|
*/
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
|
|
|
#include "bertini2/system/system.hpp"
|
|
#include "bertini2/system/precon.hpp"
|
|
#include "bertini2/io/parsing/system_parsers.hpp"
|
|
|
|
#include "externs.hpp"
|
|
|
|
using Variable = bertini::node::Variable;
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE(system_class)
|
|
|
|
using Var = std::shared_ptr<bertini::node::Variable>;
|
|
|
|
using mpfr = bertini::mpfr_complex;
|
|
|
|
using namespace bertini;
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_make_a_system_at_all Confirms that can default construct a System.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_make_a_system_at_all)
|
|
{
|
|
System S;
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_create_parser Confirms that can parse a system defined by a Bertini Classic style string.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_create_parser)
|
|
{
|
|
System sys;
|
|
std::string str = "variable_group x, y, z; \nfunction f1, f2;\n f1 = x*y*z;\n f2 = x+y+z;\n";
|
|
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
|
|
BOOST_CHECK(s);
|
|
BOOST_CHECK(!sys.IsHomogeneous());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_parse_xyz_f1f2_t_pq Confirms that can parse a system defined by a Bertini Classic style string, containing two functions, powers, parameters, a path variable, and three variables.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_parse_xyz_f1f2_t_pq)
|
|
{
|
|
|
|
std::string str = "variable_group x, y, z;\n function f1, f2;\n pathvariable t;\n parameter p, q;\n p = t;\n q = 1-t;\n f1 = x*y*z;\n\nf2 = p*q*x - 2^(-5);\n";
|
|
|
|
|
|
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
BOOST_CHECK(s);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_parse_with_subfunctions Confirms that can parse a system with a subfunction.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_parse_with_subfunctions)
|
|
{
|
|
|
|
std::string str = "function f; variable_group x1, x2; y = x1*x2; f = y*y;";
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
BOOST_CHECK(s);
|
|
|
|
BOOST_CHECK(!sys.IsHomogeneous());
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_parse_around_the_unit_circle Tests parsing a system with cosine, sine, \f$\pi\f$, \f$i\f$, and subfunctions.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_parse_around_the_unit_circle)
|
|
{
|
|
std::string str =
|
|
"variable z;\nfunction H;\nparameter q1,q2;\npathvariable t;\nq1 = cos(2*Pi*(1-t));\nq2 = sin(2*Pi*(1-t));\ns = q1 + I*q2;\nH = z^2 - s;\n";
|
|
|
|
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
BOOST_CHECK(s);
|
|
|
|
BOOST_CHECK(!sys.IsHomogeneous());
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_parse_around_the_unit_circle_alt Tests parsing an exponential function with time in it as a parameter.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_parse_around_the_unit_circle_alt)
|
|
{
|
|
std::string str = " variable z; function H; parameter s; pathvariable t; s = exp(2*Pi*I*(1-t)); H = z^2 - s; ";
|
|
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
BOOST_CHECK(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: uncomment this test once error handling has been done for the parsers.
|
|
// BOOST_AUTO_TEST_CASE(system_parse_x_y_not_xy)
|
|
// {
|
|
// std::string str = " variable x, y; function f; f = xy;";
|
|
|
|
|
|
// bertini::System sys;
|
|
// std::string::const_iterator iter = str.begin();
|
|
// std::string::const_iterator end = str.end();
|
|
// bertini::SystemParser<std::string::const_iterator> S;
|
|
// bool s = phrase_parse(iter, end, S, boost::spirit::ascii::space, sys);
|
|
// BOOST_CHECK(!s && iter!=end);
|
|
|
|
// }
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_differentiate_x Create a system with two functions, and check that can compute and evaluate its Jacobian.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_differentiate_x)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
auto f1 = pow(x,2);
|
|
auto f2 = x-1;
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
Vec<dbl> v(1);
|
|
v << 1.0;
|
|
|
|
auto J = S.Jacobian(v);
|
|
|
|
BOOST_CHECK_EQUAL(J(0),2.0);
|
|
BOOST_CHECK_EQUAL(J(1),1.0);
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_differentiate_x_and_y Create a system with two functions and two variables, and check that can compute and evaluate its Jacobian.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_differentiate_x_and_y)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
Var y = Variable::Make("y");
|
|
auto f1 = pow(x,2)*y/2;
|
|
auto f2 = x-y;
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddUngroupedVariable(y);
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
Vec<dbl> v(2);
|
|
v << 1.0 , 2.0;
|
|
|
|
auto J = S.Jacobian(v);
|
|
|
|
BOOST_CHECK_THROW(S.Jacobian(v,dbl(0.5)), std::runtime_error);
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_differentiate_x_and_t Create a system with two functions, one variable, one time variable, and check that can compute and evaluate its Jacobian.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_differentiate_x_and_t)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
Var t = Variable::Make("t");
|
|
auto f1 = (1-t)*x + t*(1-x);
|
|
auto f2 = x-t;
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddPathVariable(t);
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
Vec<dbl> v(1);
|
|
v << 1.0;
|
|
dbl time(0.5,0.2);
|
|
bertini::Mat<dbl> J = S.Jacobian(v,time);
|
|
|
|
BOOST_CHECK_THROW(S.Jacobian(v), std::runtime_error);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_homogenize_multiple_variable_groups Homogenize a system with multiple variable groups.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_homogenize_multiple_variable_groups)
|
|
{
|
|
Var x1 = Variable::Make("x1");
|
|
Var x2 = Variable::Make("x2");
|
|
|
|
Var y1 = Variable::Make("y1");
|
|
Var y2 = Variable::Make("y2");
|
|
|
|
|
|
bertini::VariableGroup v1{x1, x2};
|
|
bertini::VariableGroup v2{y1, y2};
|
|
|
|
auto f1 = x1*y1 + x1;
|
|
auto f2 = x2*x1 + y1*y2 + x1 + y2 - 1;
|
|
|
|
|
|
bertini::System S;
|
|
S.AddVariableGroup(v1);
|
|
S.AddVariableGroup(v2);
|
|
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
BOOST_CHECK(!S.IsHomogeneous());
|
|
|
|
BOOST_CHECK_EQUAL(S.NumHomVariables(),0);
|
|
|
|
S.Homogenize();
|
|
|
|
BOOST_CHECK(S.IsHomogeneous());
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_reorder_by_degree_decreasing For a system with four functions, re-order the functions so they are in decreasing degree.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_reorder_by_degree_decreasing)
|
|
{
|
|
Var x1 = Variable::Make("x1");
|
|
Var x2 = Variable::Make("x2");
|
|
|
|
Var y1 = Variable::Make("y1");
|
|
Var y2 = Variable::Make("y2");
|
|
|
|
|
|
bertini::VariableGroup v1{x1, x2};
|
|
bertini::VariableGroup v2{y1, y2};
|
|
|
|
auto f1 = x1*y1 + x1;
|
|
auto f2 = x2*pow(x1,2) + y1*y2 + x1 + y2 - 1;
|
|
|
|
bertini::System S;
|
|
S.AddVariableGroup(v1);
|
|
S.AddVariableGroup(v2);
|
|
|
|
S.AddFunction(f1); // deg 2
|
|
S.AddFunction(f2); // deg 3
|
|
S.AddFunction(pow(x1,4) + pow(y2,5)); // deg 5
|
|
S.AddFunction(x1 + x2 + y1 + y2); // deg 1
|
|
|
|
|
|
BOOST_CHECK(!S.IsHomogeneous());
|
|
S.ReorderFunctionsByDegreeDecreasing();
|
|
|
|
auto degs = S.Degrees();
|
|
|
|
for (auto d = degs.begin(); d != degs.end()-1; d++)
|
|
{
|
|
BOOST_CHECK(*d >= *(d+1));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_reorder_by_degree_increasing For a system with four functions, re-order the functions so they are in increasing degree.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_reorder_by_degree_increasing)
|
|
{
|
|
Var x1 = Variable::Make("x1");
|
|
Var x2 = Variable::Make("x2");
|
|
|
|
Var y1 = Variable::Make("y1");
|
|
Var y2 = Variable::Make("y2");
|
|
|
|
|
|
bertini::VariableGroup v1{x1, x2};
|
|
bertini::VariableGroup v2{y1, y2};
|
|
|
|
auto f1 = x1*y1 + x1;
|
|
auto f2 = x2*pow(x1,2) + y1*y2 + x1 + y2 - 1;
|
|
|
|
|
|
bertini::System S;
|
|
S.AddVariableGroup(v1);
|
|
S.AddVariableGroup(v2);
|
|
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
BOOST_CHECK(!S.IsHomogeneous());
|
|
S.ReorderFunctionsByDegreeIncreasing();
|
|
|
|
auto degs = S.Degrees();
|
|
|
|
for (auto d = degs.begin(); d != degs.end()-1; d++)
|
|
{
|
|
BOOST_CHECK(*d <= *(d+1));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_evaluate_double Evaluate a system in double precision.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_evaluate_double)
|
|
{
|
|
|
|
std::string str = "function f; variable_group x1, x2; y = x1*x2; f = y*y;";
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
|
|
Vec<dbl> values(2);
|
|
|
|
values(0) = dbl(2.0);
|
|
values(1) = dbl(3.0);
|
|
|
|
Vec<dbl> v = sys.Eval(values);
|
|
|
|
BOOST_CHECK_EQUAL(v(0), 36.0);
|
|
|
|
|
|
auto J = sys.Jacobian(values);
|
|
|
|
double x1 = 2;
|
|
double x2 = 3;
|
|
|
|
BOOST_CHECK_EQUAL(J(0,0), 2*x1*x2*x2);
|
|
BOOST_CHECK_EQUAL(J(0,1), x1*x1*2*x2);
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_evaluate_mpfr Evaluate a system in multiple precision.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_evaluate_mpfr)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
std::string str = "function f; variable_group x1, x2; y = x1*x2; f = y*y;";
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
|
|
Vec<mpfr> values(2);
|
|
|
|
values(0) = mpfr(2);
|
|
values(1) = mpfr(3);
|
|
|
|
Vec<mpfr> v = sys.Eval(values);
|
|
|
|
BOOST_CHECK_EQUAL(v(0), mpfr(36));
|
|
|
|
|
|
auto J = sys.Jacobian(values);
|
|
|
|
mpfr x1(2);
|
|
mpfr x2(3);
|
|
|
|
BOOST_CHECK_EQUAL(J(0,0), mpfr(2.0)*x1*x2*x2);
|
|
BOOST_CHECK_EQUAL(J(0,1), x1*x1*mpfr(2.0)*x2);
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(system_jacobian)
|
|
{
|
|
auto x = Variable::Make("x");
|
|
auto y = Variable::Make("y");
|
|
auto z = Variable::Make("z");
|
|
|
|
System sys;
|
|
|
|
sys.AddVariableGroup(VariableGroup{x, y, z});
|
|
|
|
sys.AddFunction(pow(x,2)*pow(y,3)*pow(z,4) + 1);
|
|
sys.AddFunction(pow(x,3)*pow(y,4)*pow(z,5) + 4);
|
|
|
|
auto a = x->Eval<dbl>();
|
|
auto b = y->Eval<dbl>();
|
|
auto c = z->Eval<dbl>();
|
|
|
|
Vec<dbl> v(3);
|
|
v << a, b, c;
|
|
|
|
auto J = sys.Jacobian(v);
|
|
|
|
|
|
BOOST_CHECK_SMALL(J(0,0).real() - (2.*a*pow(b,3)*pow(c,4)).real(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(0,1).real() - (3.*pow(a,2)*pow(b,2)*pow(c,4)).real(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(0,2).real() - (4.*pow(a,2)*pow(b,3)*pow(c,3)).real(), 1e-15);
|
|
|
|
BOOST_CHECK_SMALL(J(1,0).real() - (3.*pow(a,2)*pow(b,4)*pow(c,5)).real(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(1,1).real() - (4.*pow(a,3)*pow(b,3)*pow(c,5)).real(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(1,2).real() - (5.*pow(a,3)*pow(b,4)*pow(c,4)).real(), 1e-15);
|
|
|
|
BOOST_CHECK_SMALL(J(0,0).imag() - (2.*a*pow(b,3)*pow(c,4)).imag(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(0,1).imag() - (3.*pow(a,2)*pow(b,2)*pow(c,4)).imag(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(0,2).imag() - (4.*pow(a,2)*pow(b,3)*pow(c,3)).imag(), 1e-15);
|
|
|
|
BOOST_CHECK_SMALL(J(1,0).imag() - (3.*pow(a,2)*pow(b,4)*pow(c,5)).imag(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(1,1).imag() - (4.*pow(a,3)*pow(b,3)*pow(c,5)).imag(), 1e-15);
|
|
BOOST_CHECK_SMALL(J(1,2).imag() - (5.*pow(a,3)*pow(b,4)*pow(c,4)).imag(), 1e-15);
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b add_two_systems Test the arithmetic sum of two Systems.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(add_two_systems)
|
|
{
|
|
bertini::System sys1, sys2;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
|
|
VariableGroup vars;
|
|
vars.push_back(x); vars.push_back(y);
|
|
|
|
sys1.AddVariableGroup(vars);
|
|
sys1.AddFunction(y+1);
|
|
sys1.AddFunction(x*y);
|
|
|
|
sys2.AddVariableGroup(vars);
|
|
sys2.AddFunction(-y-1);
|
|
sys2.AddFunction(-x*y);
|
|
|
|
sys1+=sys2;
|
|
|
|
|
|
Vec<dbl> values(2);
|
|
|
|
values << dbl(2.0), dbl(3.0);
|
|
|
|
auto v = sys1.Eval(values);
|
|
|
|
BOOST_CHECK_EQUAL(v(0), 0.0);
|
|
BOOST_CHECK_EQUAL(v(1), 0.0);
|
|
|
|
auto deg = sys1.Degrees();
|
|
|
|
BOOST_CHECK_EQUAL(deg.size(),2);
|
|
if (deg.size()==2)
|
|
{
|
|
BOOST_CHECK_EQUAL(deg[0],1);
|
|
BOOST_CHECK_EQUAL(deg[1],2);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_differentiate_wrt_time_linear Test the arithmetic sum of two Systems.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_differentiate_wrt_time_linear)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
Var t = Variable::Make("t");
|
|
auto f1 = (1-t)*x + t*(1-x);
|
|
auto f2 = x-t;
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddPathVariable(t);
|
|
S.AddFunction(f1);
|
|
S.AddFunction(f2);
|
|
|
|
Vec<dbl> v(1);
|
|
v << 1.0;
|
|
dbl time(0.5,0.2);
|
|
auto dS_dt = S.TimeDerivative(v,time);
|
|
|
|
BOOST_CHECK_CLOSE( dS_dt(0).real(), dbl(-1).real(), threshold_clearance_d);
|
|
BOOST_CHECK_CLOSE( dS_dt(1).imag(), dbl(-1).imag(), threshold_clearance_d);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_one_aff_group Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_one_aff_group)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
VariableGroup vars{x, y};
|
|
sys.AddVariableGroup(vars);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(3);
|
|
v << dbl(2,3), dbl(3,4), dbl(4,5);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),2);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(1)/v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(2)/v(0)) < threshold_clearance_d);
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_two_aff_groups Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_two_aff_groups)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
Var z = Variable::Make("z"), w = Variable::Make("w");
|
|
VariableGroup vars{x, y};
|
|
VariableGroup vars2{z, w};
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddVariableGroup(vars2);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(6);
|
|
v << dbl(2,3), dbl(3,4), dbl(4,5),
|
|
dbl(5,6), dbl(6,7), dbl(7,8);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),4);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(1)/v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(2)/v(0)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(2) - v(4)/v(3)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(3) - v(5)/v(3)) < threshold_clearance_d);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_two_aff_groups_one_hom_group Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_two_aff_groups_one_hom_group)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
Var z = Variable::Make("z"), w = Variable::Make("w");
|
|
Var h1 = Variable::Make("h1"), h2 = Variable::Make("h2");
|
|
VariableGroup vars{x, y};
|
|
VariableGroup vars2{h1,h2};
|
|
VariableGroup vars3{z, w};
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddHomVariableGroup(vars2);
|
|
sys.AddVariableGroup(vars3);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(8);
|
|
v << dbl(2,3), dbl(3,4), dbl(4,5),
|
|
dbl(10,11), dbl(11,12),
|
|
dbl(5,6), dbl(6,7), dbl(7,8);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),6);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(1)/v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(2)/v(0)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(2) - v(3)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(3) - v(4)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(4) - v(6)/v(5)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(5) - v(7)/v(5)) < threshold_clearance_d);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_one_hom_group Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_one_hom_group)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
VariableGroup vars{x, y};
|
|
sys.AddHomVariableGroup(vars);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(2);
|
|
v << dbl(2,3), dbl(3,4);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),2);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(1)) < threshold_clearance_d);
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_one_hom_group_two_ungrouped_vars Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_one_hom_group_two_ungrouped_vars)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
Var z = Variable::Make("z"), w = Variable::Make("w");
|
|
VariableGroup vars{x, y};
|
|
|
|
sys.AddHomVariableGroup(vars);
|
|
sys.AddUngroupedVariable(z);
|
|
sys.AddUngroupedVariable(w);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(4);
|
|
v << dbl(2,3), dbl(3,4), dbl(4,5), dbl(5,6);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),4);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(1)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(2) - v(2)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(3) - v(3)) < threshold_clearance_d);
|
|
}
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_dehomogenize_FIFO_one_aff_group_two_ungrouped_vars_another_aff_grp_hom_grp Test the dehomogenization of a point using the first-in-first-out variable ordering which is standard in Bertini 1.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_dehomogenize_FIFO_one_aff_group_two_ungrouped_vars_another_aff_grp_hom_grp)
|
|
{
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y");
|
|
Var z = Variable::Make("z"), w = Variable::Make("w");
|
|
Var h1 = Variable::Make("h1"), h2 = Variable::Make("h2");
|
|
Var u1 = Variable::Make("u1"), u2 = Variable::Make("u2");
|
|
|
|
VariableGroup vars{x,y};
|
|
VariableGroup vars2{z,w};
|
|
|
|
VariableGroup vars3{h1,h2};
|
|
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddUngroupedVariable(u1);
|
|
sys.AddUngroupedVariable(u2);
|
|
sys.AddVariableGroup(vars2);
|
|
sys.AddHomVariableGroup(vars3);
|
|
|
|
sys.Homogenize();
|
|
|
|
Vec<dbl> v(10);
|
|
v << dbl(2,3), dbl(3,4), dbl(4,5),
|
|
dbl(10,11), dbl(11,12),
|
|
dbl(5,6), dbl(6,7), dbl(7,8),
|
|
dbl(12,13), dbl(13,14);
|
|
|
|
auto d = sys.DehomogenizePoint(v);
|
|
|
|
BOOST_CHECK_EQUAL(d.size(),8);
|
|
|
|
BOOST_CHECK(abs(d(0) - v(1)/v(0)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(1) - v(2)/v(0)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(2) - v(3)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(3) - v(4)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(4) - v(6)/v(5)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(5) - v(7)/v(5)) < threshold_clearance_d);
|
|
|
|
BOOST_CHECK(abs(d(6) - v(8)) < threshold_clearance_d);
|
|
BOOST_CHECK(abs(d(7) - v(9)) < threshold_clearance_d);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_estimate_coeff_bound_linear Test the estimation of the largest coefficient in a system, including its derivatives.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_estimate_coeff_bound_linear)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
Var x = Variable::Make("x");
|
|
Var t = Variable::Make("t");
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddPathVariable(t);
|
|
S.AddFunction((1-t)*x + t*(1-x));
|
|
S.AddFunction(x-t);
|
|
|
|
mpfr_float coefficient_bound = S.CoefficientBound<mpfr>();
|
|
BOOST_CHECK(coefficient_bound < mpfr_float("10"));
|
|
BOOST_CHECK(coefficient_bound > mpfr_float("0.5"));
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_estimate_coeff_bound_quartic Test the estimation of the largest coefficient in a system, including its derivatives.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_estimate_coeff_bound_quartic)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y"), z = Variable::Make("z");
|
|
|
|
VariableGroup vars{x,y,z};
|
|
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddFunction(y+x*y + mpfr_float("0.5"));
|
|
sys.AddFunction(pow(x,3)+x*y+bertini::node::E());
|
|
sys.AddFunction(pow(x,2)*pow(y,2)+x*y*z*z - 1);
|
|
|
|
mpfr_float coefficient_bound = sys.CoefficientBound<mpfr>();
|
|
BOOST_CHECK(coefficient_bound < mpfr_float("5"));
|
|
BOOST_CHECK(coefficient_bound > mpfr_float("2"));
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_estimate_coeff_bound_quartic Test the estimation of the largest coefficient in a system, including its derivatives.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_estimate_coeff_bound_homogenized_quartic)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y"), z = Variable::Make("z");
|
|
|
|
VariableGroup vars{x,y,z};
|
|
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddFunction(y+x*y + mpfr_float("0.5"));
|
|
sys.AddFunction(pow(x,3)+x*y+bertini::node::E());
|
|
sys.AddFunction(pow(x,2)*pow(y,2)+x*y*z*z - 1);
|
|
|
|
sys.Homogenize();
|
|
sys.AutoPatch();
|
|
|
|
mpfr_float coefficient_bound = sys.CoefficientBound<mpfr>();
|
|
BOOST_CHECK(coefficient_bound < mpfr_float("10"));
|
|
BOOST_CHECK(coefficient_bound > mpfr_float("2"));
|
|
}
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_estimate_degree_bound_linear Test the estimation of the degree in a system, including its derivatives.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_estimate_degree_bound_linear)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
Var x = Variable::Make("x");
|
|
Var t = Variable::Make("t");
|
|
|
|
bertini::System S;
|
|
S.AddUngroupedVariable(x);
|
|
S.AddPathVariable(t);
|
|
S.AddFunction((1-t)*x + t*(1-x));
|
|
S.AddFunction(x-t);
|
|
|
|
mpfr_float degree_bound = S.DegreeBound();
|
|
BOOST_CHECK(degree_bound == mpfr_float("1"));
|
|
}
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_estimate_degree_bound_quartic Test the estimation of the degree in a system, including its derivatives.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_estimate_degree_bound_quartic)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
bertini::System sys;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y"), z = Variable::Make("z");
|
|
|
|
VariableGroup vars{x,y,z};
|
|
|
|
sys.AddVariableGroup(vars);
|
|
sys.AddFunction(y+x*y + mpfr_float("0.5"));
|
|
sys.AddFunction(pow(x,3)+x*y+bertini::node::E());
|
|
sys.AddFunction(pow(x,2)*pow(y,2)+x*y*z*z - 1);
|
|
|
|
mpfr_float degree_bound = sys.DegreeBound();
|
|
BOOST_CHECK(degree_bound == mpfr_float("4"));
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b system_multiply_by_node Ensure that multiplication of a system by a node doesn't affect other copies of a system
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(system_multiply_by_node)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
bertini::System sys1, sys2;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y"), z = Variable::Make("z");
|
|
|
|
VariableGroup vars{x,y,z};
|
|
|
|
sys1.AddVariableGroup(vars);
|
|
sys1.AddFunction(x);
|
|
sys1.AddFunction(y);
|
|
sys1.AddFunction(z);
|
|
|
|
sys2.AddVariableGroup(vars);
|
|
sys2.AddFunction(y+x*y + mpfr_float("0.5"));
|
|
sys2.AddFunction(pow(x,3)+x*y+bertini::node::E());
|
|
sys2.AddFunction(pow(x,2)*pow(y,2)+x*y*z*z - 1);
|
|
|
|
Var t = Variable::Make("t");
|
|
|
|
auto sys_copy1 = t*sys1;
|
|
auto sys_copy2 = (1-t)*sys2;
|
|
|
|
auto sys_copy3 = sys_copy1 + sys_copy2; // this line couples the two systems... this coupling is total garbage!!! this 'homotopy' should never be used.
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b concatenate_two_systems Test that contactenation of two systems works correctly
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(concatenate_two_systems)
|
|
{
|
|
bertini::System sys1, sys2;
|
|
Var x = Variable::Make("x"), y = Variable::Make("y"), z = Variable::Make("z");
|
|
|
|
VariableGroup vars{x,y,z};
|
|
|
|
sys1.AddVariableGroup(vars);
|
|
sys1.AddFunction(x);
|
|
sys1.AddFunction(y);
|
|
sys1.AddFunction(z);
|
|
|
|
sys2.AddVariableGroup(vars);
|
|
sys2.AddFunction(y+x*y + mpfr_float("0.5"));
|
|
sys2.AddFunction(pow(x,3)+x*y+bertini::node::E());
|
|
sys2.AddFunction(pow(x,2)*pow(y,2)+x*y*z*z - 1);
|
|
|
|
|
|
auto sys3 = Concatenate(sys1, sys2);
|
|
|
|
BOOST_CHECK_EQUAL(sys3.NumNaturalFunctions(),6);
|
|
}
|
|
|
|
/**
|
|
\class bertini::System
|
|
\test \b parsed_system_evaluates_correctly
|
|
*/
|
|
BOOST_AUTO_TEST_CASE(parsed_system_evaluates_correctly)
|
|
{
|
|
|
|
std::string str = "function f; variable_group x1, x2; y = x1*x2; f = y*y;";
|
|
|
|
bertini::System sys;
|
|
bool s = bertini::parsing::classic::parse(str.begin(), str.end(), sys);
|
|
|
|
Vec<dbl> values(2);
|
|
|
|
values(0) = dbl(2.0);
|
|
values(1) = dbl(3.0);
|
|
|
|
Vec<dbl> v(sys.NumNaturalFunctions());
|
|
sys.EvalInPlace(v, values);
|
|
|
|
BOOST_CHECK_EQUAL(v(0), 36.0);
|
|
|
|
|
|
auto J = sys.Jacobian(values);
|
|
|
|
double x1 = 2;
|
|
double x2 = 3;
|
|
|
|
BOOST_CHECK_EQUAL(J(0,0), 2*x1*x2*x2);
|
|
BOOST_CHECK_EQUAL(J(0,1), x1*x1*2*x2);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(variable_group_sizes_and_degrees_homvargrp)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
Var y = Variable::Make("y");
|
|
|
|
System sys;
|
|
|
|
VariableGroup v1{x};
|
|
VariableGroup v2{y};
|
|
|
|
sys.AddHomVariableGroup(v1);
|
|
sys.AddHomVariableGroup(v2);
|
|
|
|
sys.AddFunction(x*y - 1);
|
|
sys.AddFunction(pow(x,2) - 1);
|
|
|
|
auto size_of_each_var_gp = sys.VariableGroupSizes();
|
|
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[0], 1);
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[1], 1);
|
|
|
|
BOOST_CHECK(!sys.IsHomogeneous());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(variable_group_sizes_and_degrees_affvargrp)
|
|
{
|
|
Var x = Variable::Make("x");
|
|
Var y = Variable::Make("y");
|
|
|
|
System sys;
|
|
|
|
VariableGroup v1{x};
|
|
VariableGroup v2{y};
|
|
|
|
sys.AddVariableGroup(v1);
|
|
sys.AddVariableGroup(v2);
|
|
|
|
sys.AddFunction(x*y - 1);
|
|
sys.AddFunction(pow(x,2) - 1);
|
|
|
|
auto size_of_each_var_gp = sys.VariableGroupSizes();
|
|
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[0], 1);
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[1], 1);
|
|
|
|
|
|
sys.Homogenize();
|
|
|
|
size_of_each_var_gp = sys.VariableGroupSizes();
|
|
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[0], 2);
|
|
BOOST_CHECK_EQUAL(size_of_each_var_gp[1], 2);
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(clone_system_new_variables_evaluation)
|
|
{
|
|
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
auto sys = bertini::system::Precon::GriewankOsborn();
|
|
Vec<mpfr> x1(2), x2(2);
|
|
x1(0) = bertini::multiprecision::RandomUnit(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
x1(1) = bertini::multiprecision::RandomUnit(CLASS_TEST_MPFR_DEFAULT_DIGITS);
|
|
|
|
auto f = sys.Eval(x1);
|
|
|
|
auto sys_clone = bertini::Clone(sys);
|
|
|
|
x2(0) = mpfr{2};
|
|
x2(1) = mpfr{3};
|
|
|
|
auto f_clone = sys_clone.Eval(x2);
|
|
|
|
BOOST_CHECK_EQUAL(mpfr(2.5), f_clone(0));
|
|
BOOST_CHECK_EQUAL(mpfr(-1), f_clone(1));
|
|
|
|
auto f_clone2 = sys_clone.Eval(x1);
|
|
auto f2 = sys.Eval<mpfr>();
|
|
|
|
BOOST_CHECK_EQUAL(f,f2);
|
|
BOOST_CHECK_EQUAL(f_clone2,f2);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
|
|
|
|
|