b2/core/test/endgames/generic_interpolation.hpp
2025-01-14 01:15:53 +01:00

230 lines
8.2 KiB
C++
Raw Permalink 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.

//This file is part of Bertini 2.
//
//b2/test/endgames/interpolation.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.
//
//b2/test/endgames/interpolation.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 b2/test/endgames/interpolation.cpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 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
// Tim Hodges, Colorado State University
// this file in intended to be included into other test files, with blanks filled in above.
using namespace bertini;
using namespace bertini::endgame;
using bertini::DefaultPrecision;
template<typename NumType> using Vec = Eigen::Matrix<NumType, Eigen::Dynamic, 1>;
template<typename NumType> using Mat = Eigen::Matrix<NumType, Eigen::Dynamic, Eigen::Dynamic>;
using BCT = BaseComplexType;
using BRT = Eigen::NumTraits<BCT>::Real;
template<typename ...T>
BCT ComplexFromString(T... s)
{return bertini::NumTraits<BCT>::FromString(s...);}
template<typename ...T>
BRT RealFromString(T... s)
{return bertini::NumTraits<BRT>::FromString(s...);}
BOOST_AUTO_TEST_CASE( constant_four_variate )
{
int num_samples = 3;
DefaultPrecision(ambient_precision);
TimeCont<BCT> times;
SampCont<BCT> samples, derivatives;
times.emplace_back(ComplexFromString("1.890235648907826359017283461724"));
times.emplace_back(ComplexFromString("2.6751239470926520645293652"));
times.emplace_back(ComplexFromString("3.566754186725389412876498127534875"));
Vec<BCT> sample(4);
sample << ComplexFromString("6.4789162736409137056734534678679"), ComplexFromString("-1.5877816237549123614917624"), ComplexFromString("5.947461892534781890236417801"),ComplexFromString("-3.87746985236816238746178293");
for (int ii=0; ii<3; ++ii)
samples.push_back(sample);
Vec<BCT> derivative(4);
derivative << ComplexFromString("0"), ComplexFromString("0"), ComplexFromString("0"),ComplexFromString("0");
for (int ii=0; ii<3; ++ii)
derivatives.push_back(derivative);
BCT target_time = ComplexFromString("0.9471925368945182312341234123");
auto result = HermiteInterpolateAndSolve(target_time,num_samples,times,samples,derivatives);
BOOST_CHECK( (result - sample).norm() < pow(RealFromString("10"),ambient_precision-2));
}
/**
This test case illustrates the convergent nature of the HemiteInterpolateAndSolve function.
The test case will construct 3 samples with derivative,time, and space values for the function x^8 + 1.
After the three samples have been constructed there will be a hermite interpolation.
We check this against the tracking tolerance for the endgame.
*/
BOOST_AUTO_TEST_CASE( eight_degree_univariate )
{
DefaultPrecision(ambient_precision);
BCT target_time(0,0); //our target time is the origin.
unsigned int num_samples = 3;
TimeCont<BCT> times;
SampCont<BCT> samples, derivatives;
BCT time;
Vec<BCT> sample(1), derivative(1);
time = ComplexFromString(".1"); // x = .1
times.push_back(time);
sample << ComplexFromString("1.00000001"); // f(.1) = 1.00000001
samples.push_back(sample);
derivative << ComplexFromString("8e-7"); //f'(.1) = 8e-7
derivatives.push_back(derivative);
time = ComplexFromString(".05"); // x = .1/2 = .05
times.push_back(time);
sample << ComplexFromString("1.0000000000390625"); //f(.05) = 1.0000000000390625
samples.push_back(sample);
derivative << ComplexFromString("6.25e-9"); //f'(.05) = 6.25e-9
derivatives.push_back(derivative);
time = ComplexFromString(".025"); // x = .05/2 = .025
times.push_back(time);
sample << ComplexFromString("1.000000000000152587890625"); // f(.025) = 1.000000000000152587890625
samples.push_back(sample);
derivative << ComplexFromString("4.8828125e-11"); //f'(.025) = 4.8828125e-11
derivatives.push_back(derivative);
Vec< BCT > first_approx = HermiteInterpolateAndSolve(target_time,num_samples,times,samples,derivatives);
BOOST_CHECK( norm(first_approx(0) - ComplexFromString("0.9999999767578209232082898114211261253459","0")) < 1e-7);
// answer was found using matlab for a check. difference is diff is 2.32422e-08
}//end basic hermite test case mp against matlab
/**
This test case illustrates the convergent nature of the HemiteInterpolateAndSolve function.
The test case will construct 3 samples with derivative,time, and space values for the function x^8 + 1.
After the three samples have been constructed there will be a hermite interpolation.
Next, a new sample is constructed and the earliest sample is discarded. Leaving us three samples that are "nearer"
to the target at the origin.
A new approximation is made, with the a new sample and approximation done afterwards.
We then check to make sure our approximations are getting better by checking the distance from the correct answer and the
various approximations made.
*/
BOOST_AUTO_TEST_CASE(eight_degree_univariate_advanced_gets_better)
{
DefaultPrecision(ambient_precision);
BCT target_time(0,0);
unsigned int num_samples = 3;
TimeCont<BCT> times;
SampCont<BCT> samples, derivatives;
BCT time;
Vec<BCT> sample(1), derivative(1);
time = ComplexFromString(".1"); // x = .1
times.push_back(time);
sample << ComplexFromString("1.00000001"); // f(.1) = 1.00000001
samples.push_back(sample);
derivative << ComplexFromString("8e-7"); //f'(.1) = 8e-7
derivatives.push_back(derivative);
time = ComplexFromString(".05"); // x = .1/2 = .05
times.push_back(time);
sample << ComplexFromString("1.0000000000390625"); //f(.05) = 1.0000000000390625
samples.push_back(sample);
derivative << ComplexFromString("6.25e-9"); //f'(.05) = 6.25e-9
derivatives.push_back(derivative);
time = ComplexFromString(".025"); // x = .05/2 = .025
times.push_back(time);
sample << ComplexFromString("1.000000000000152587890625"); // f(.025) = 1.000000000000152587890625
samples.push_back(sample);
derivative << ComplexFromString("4.8828125e-11"); //f'(.025) = 4.8828125e-11
derivatives.push_back(derivative);
Vec< BCT > first_approx = HermiteInterpolateAndSolve(target_time,num_samples,times,samples,derivatives);
Vec< BCT > correct(1);
correct << ComplexFromString("1");
//Setting up a new sample for approximation.
time = ComplexFromString(".0125"); //.025/2 = .0125
times.push_back(time);
sample << ComplexFromString("1.00000000000000059604644775390625"); // f(.0125) = 1.00000000000000059604644775390625
samples.push_back(sample);
derivative << ComplexFromString("3.814697265625e-13"); //f'(.0125) = 3.814697265625e-13
derivatives.push_back(derivative);
//Get rid of earliest sample.
times.pop_front();
samples.pop_front();
derivatives.pop_front();
//Compute the second approximation.
Vec< BCT > second_approx = HermiteInterpolateAndSolve(target_time,num_samples,times,samples,derivatives);
// //Check to make sure we are doing better.
BOOST_CHECK(abs(second_approx(0)-correct(0)) < abs(first_approx(0)-correct(0)));
//Setting up new sample for use in approximation.
time = ComplexFromString("0.00625"); //.0125/2 = 0.00625
times.push_back(time);
sample << ComplexFromString("1.0000000000000000023283064365386962890625"); // f(.00625) = 1.0000000000000000023283064365386962890625
samples.push_back(sample);
derivative << ComplexFromString("2.98023223876953125000000000000000e-15"); //f'(.00625) = 2.98023223876953125000000000000000×e-15
derivatives.push_back(derivative);
times.pop_front();
samples.pop_front();
derivatives.pop_front();
Vec< BCT > third_approx = HermiteInterpolateAndSolve(target_time,num_samples,times,samples,derivatives);
BOOST_CHECK((first_approx - correct).norm() < 1e-10);
BOOST_CHECK((second_approx - correct).norm() < 1e-10);
BOOST_CHECK((third_approx - correct).norm() < 1e-10);
}//end hermite test case