32namespace bertini{
namespace endgame{
169template<
typename PrecT>
170class PowerSeriesEndgame :
171 public virtual EndgameBase<PowerSeriesEndgame<PrecT>, PrecT>
174 using BaseEGT = EndgameBase<PowerSeriesEndgame<PrecT>, PrecT>;
175 using FinalEGT = PowerSeriesEndgame<PrecT>;
176 using TrackerType =
typename BaseEGT::TrackerType;
178 using BaseComplexType =
typename BaseEGT::BaseComplexType;
179 using BaseRealType =
typename BaseEGT::BaseRealType;
181 using EmitterType = PowerSeriesEndgame<PrecT>;
187 using TupleOfTimes =
typename BaseEGT::TupleOfTimes;
188 using TupleOfSamps =
typename BaseEGT::TupleOfSamps;
190 using BCT = BaseComplexType;
191 using BRT = BaseRealType;
193 using Configs =
typename AlgoTraits<FinalEGT>::NeededConfigs;
194 using ConfigsAsTuple =
typename Configs::ToTuple;
221 template<
typename CT>
222 void AssertSizesTimeSpace()
const
224 const auto num_sample_points = this->EndgameSettings().num_sample_points;
225 assert(std::get<SampCont<CT> >(
samples_).size()==std::get<TimeCont<CT> >(
times_).size() &&
"must have same number of samples in times and spaces");
226 assert(std::get<SampCont<CT> >(
samples_).size()>=num_sample_points &&
"must have sufficient number of samples");
229 template<
typename CT>
230 void AssertSizesTimeSpaceDeriv()
const
232 const auto num_sample_points = this->EndgameSettings().num_sample_points;
233 assert(std::get<SampCont<CT> >(
samples_).size()==std::get<TimeCont<CT> >(
times_).size() &&
"must have same number of samples in times and spaces");
234 assert(std::get<SampCont<CT> >(
samples_).size()==std::get<SampCont<CT> >(
derivatives_).size() &&
"must have same number of samples in derivatives and spaces");
235 assert(std::get<SampCont<CT> >(
samples_).size()>=num_sample_points &&
"must have sufficient number of samples");
246 template<
typename CT>
249 std::get<TimeCont<CT> >(
times_).clear();
250 std::get<SampCont<CT> >(
samples_).clear();
256 template<
typename CT>
257 void SetTimes(TimeCont<CT>
const& times_to_set) { std::get<TimeCont<CT> >(
times_) = times_to_set;}
262 template<
typename CT>
266 const BCT& LatestTimeImpl()
const
274 template<
typename CT>
275 void SetSamples(SampCont<CT>
const& samples_to_set) { std::get<SampCont<CT> >(
samples_) = samples_to_set;}
280 template<
typename CT>
286 template<
typename CT>
294 const ConfigsAsTuple& settings )
298 template<
typename... Ts >
300 PowerSeriesEndgame(TrackerType
const& tr,
const Ts&... ts ) : PowerSeriesEndgame(tr, Configs::Unpermute( ts... ) )
317 template<
typename CT>
320 using RT =
typename Eigen::NumTraits<CT>::Real;
321 using std::log;
using std::abs;
323 const auto& samples = std::get<SampCont<CT> >(
samples_);
325 AssertSizesTimeSpace<CT>();
327 auto num_samples = samples.size();
328 const Vec<CT> & sample0 = samples[num_samples-3];
329 const Vec<CT> & sample1 = samples[num_samples-2];
330 const Vec<CT> & sample2 = samples[num_samples-1];
334 CT rand_sum1 = ((sample1 - sample0).transpose()*
rand_vector_).sum();
335 CT rand_sum2 = ((sample2 - sample1).transpose()*
rand_vector_).sum();
337 if ( abs(rand_sum1)==0 || abs(rand_sum2)==0)
343 RT estimate = log(
static_cast<RT
>(this->EndgameSettings().sample_factor))/log(abs(rand_sum2/rand_sum1));
350 auto upper_bound = unsigned(round(estimate)*this->
template Get<PowerSeriesConfig>().cycle_number_amplification);
375 template<
typename CT>
378 using RT =
typename Eigen::NumTraits<CT>::Real;
380 const auto& samples = std::get<SampCont<CT> >(
samples_);
381 const auto& times = std::get<TimeCont<CT> >(
times_);
382 const auto& derivatives = std::get<SampCont<CT> >(
derivatives_);
384 AssertSizesTimeSpaceDeriv<CT>();
386 const Vec<CT> &most_recent_sample = samples.back();
387 const CT& most_recent_time = times.back();
394 if (samples.size() > this->EndgameSettings().num_sample_points)
395 num_pts = this->EndgameSettings().num_sample_points;
397 num_pts = this->EndgameSettings().num_sample_points-1;
400 auto min_found_difference = Eigen::NumTraits<RT>::highest();
402 TimeCont<CT> s_times(num_pts);
403 SampCont<CT> s_derivatives(num_pts);
405 auto offset = samples.size() - num_pts - 1;
410 std::tie(s_times, s_derivatives) =
TransformToSPlane(candidate, t0, num_pts, ContStart::Front);
411 RT cand_power{1/
static_cast<RT
>(candidate)};
413 pow((most_recent_time-t0)/(times[0]-t0),cand_power),
414 num_pts,s_times,samples,s_derivatives, ContStart::Front)
416 most_recent_sample).
template lpNorm<Eigen::Infinity>();
418 if (curr_diff < min_found_difference)
420 min_found_difference = curr_diff;
421 this->cycle_number_ = candidate;
426 return this->cycle_number_;
443 template<
typename CT>
446 auto& samples = std::get<SampCont<CT> >(
samples_);
447 auto& times = std::get<TimeCont<CT> >(
times_);
448 auto& derivatives = std::get<SampCont<CT> >(
derivatives_);
450 assert((samples.size() == times.size()) &&
"must have same number of times and samples");
452 if (tracking::TrackerTraits<TrackerType>::IsAdaptivePrec)
454 auto max_precision = this->EnsureAtUniformPrecision(times, samples);
455 this->GetSystem().precision(max_precision);
459 derivatives.clear(); derivatives.resize(samples.size());
460 for(
unsigned ii = 0; ii < samples.size(); ++ii)
462 derivatives[ii] = -this->GetSystem().Jacobian(samples[ii],times[ii]).lu().solve(this->GetSystem().TimeDerivative(samples[ii],times[ii]));
474 template <
typename CT>
475 std::tuple<TimeCont<CT>, SampCont<CT>>
TransformToSPlane(
int cycle_num, CT
const& t0,
unsigned num_pts, ContStart shift_from)
478 throw std::runtime_error(
"cannot transform to s plane with cycle number 0");
479 AssertSizesTimeSpaceDeriv<CT>();
482 using RT =
typename Eigen::NumTraits<CT>::Real;
484 const auto& times = std::get<TimeCont<CT> >(
times_);
485 const auto& derivatives = std::get<SampCont<CT> >(
derivatives_);
487 RT c =
static_cast<RT
>(cycle_num);
490 unsigned offset_t, offset_d;
491 if (shift_from == ContStart::Back)
493 offset_t = times.size()-num_pts;
494 offset_d = derivatives.size()-num_pts;
497 offset_t = offset_d = 0;
500 TimeCont<CT> s_times(num_pts);
501 SampCont<CT> s_derivatives(num_pts);
503 CT time_shift = times[offset_t] - t0;
505 for(
unsigned ii = 0; ii < num_pts; ++ii){
506 s_times[ii] =
pow((times[ii+offset_t]-t0)/time_shift, one_over_c);
507 s_derivatives[ii] = derivatives[ii+offset_d]*( c*
pow(s_times[ii],cycle_num-1))*time_shift;
510 return std::make_tuple(s_times, s_derivatives);
531 template<
typename CT>
536 auto num_pts = this->EndgameSettings().num_sample_points;
538 TimeCont<CT> s_times;
539 SampCont<CT> s_derivatives;
541 std::tie(s_times, s_derivatives) =
TransformToSPlane(c, t0, num_pts, ContStart::Back);
546 return SuccessCode::Success;
566 template<
typename CT>
569 using RT =
typename Eigen::NumTraits<CT>::Real;
571 auto& samples = std::get<SampCont<CT> >(
samples_);
572 auto& times = std::get<TimeCont<CT> >(
times_);
573 auto& derivatives = std::get<SampCont<CT> >(
derivatives_);
575 AssertSizesTimeSpaceDeriv<CT>();
578 CT next_time = (times.back() + target_time) *
static_cast<RT
>(this->EndgameSettings().sample_factor);
580 if (abs(next_time - target_time) < this->EndgameSettings().min_track_time)
583 return SuccessCode::MinTrackTimeReached;
586 SuccessCode tracking_success = this->GetTracker().TrackPath(next_sample,times.back(),next_time,samples.back());
587 if (tracking_success != SuccessCode::Success)
588 return tracking_success;
592 this->EnsureAtPrecision(next_time,
Precision(next_sample));
595 times.push_back(next_time);
596 samples.push_back(next_sample);
601 auto refine_success = this->RefineSample(samples.back(), next_sample, times.back(),
602 this->FinalTolerance() * this->EndgameSettings().sample_point_refinement_factor,
603 this->EndgameSettings().max_num_newton_iterations);
604 if (refine_success != SuccessCode::Success)
607 return refine_success;
610 this->EnsureAtPrecision(times.back(),
Precision(samples.back()));
615 if (times.size() > this->EndgameSettings().num_sample_points+1)
621 return SuccessCode::Success;
641 template<
typename CT>
642 SuccessCode
RunImpl(
const CT & start_time,
const Vec<CT> & start_point, CT
const& target_time)
644 if (start_point.size()!=this->GetSystem().NumVariables())
646 std::stringstream err_msg;
647 err_msg <<
"number of variables in start point for PSEG, " << start_point.size() <<
", must match the number of variables in the system, " << this->GetSystem().NumVariables();
648 throw std::runtime_error(err_msg.str());
651 DefaultPrecision(
Precision(start_point));
653 using RT =
typename Eigen::NumTraits<CT>::Real;
659 auto& samples = std::get<SampCont<CT> >(
samples_);
660 auto& times = std::get<TimeCont<CT> >(
times_);
661 auto& derivatives = std::get<SampCont<CT> >(
derivatives_);
662 Vec<CT>& latest_approx = this->final_approximation_;
663 Vec<CT>& prev_approx = this->previous_approximation_;
669 auto initial_sample_success = this->ComputeInitialSamples(start_time, target_time, start_point, times, samples);
671 if (initial_sample_success!=SuccessCode::Success)
674 return initial_sample_success;
677 this->
template RefineAllSamples<CT>(samples, times);
683 latest_approx = prev_approx;
685 if (extrapolation_code != SuccessCode::Success)
686 return extrapolation_code;
688 RT norm_of_dehom_of_latest_approx;
689 RT norm_of_dehom_of_prev_approx;
690 if (this->SecuritySettings().level <= 0)
691 norm_of_dehom_of_prev_approx = this->GetSystem().DehomogenizePoint(prev_approx).template lpNorm<Eigen::Infinity>();
694 NumErrorT& approx_error = this->approximate_error_;
697 while (approx_error > this->FinalTolerance())
700 if (advance_code!=SuccessCode::Success)
707 this->
template RefineAllSamples<CT>(samples, times);
711 if (extrapolation_code!=SuccessCode::Success)
714 return extrapolation_code;
717 approx_error =
static_cast<NumErrorT
>((latest_approx - prev_approx).template lpNorm<Eigen::Infinity>());
721 if(this->SecuritySettings().level <= 0)
723 norm_of_dehom_of_latest_approx = this->GetSystem().DehomogenizePoint(latest_approx).template lpNorm<Eigen::Infinity>();
724 if(norm_of_dehom_of_latest_approx > this->SecuritySettings().max_norm && norm_of_dehom_of_prev_approx > this->SecuritySettings().max_norm)
727 return SuccessCode::SecurityMaxNormReached;
729 norm_of_dehom_of_prev_approx = norm_of_dehom_of_latest_approx;
736 prev_approx = latest_approx;
740 return SuccessCode::Success;
Contains parent class, Endgame, the parent class for all endgames.
void NotifyObservers(AnyEvent const &e) const
Sends an Event (more particularly, AnyEvent) to all watching observers of this object.
Definition observable.hpp:90
A common base type for various precision types, fixed and adaptive. The purpose of this is to maintai...
Definition prec_base.hpp:46
class used to finish tracking paths during Homotopy Continuation
Definition powerseries.hpp:172
const auto & GetSamples() const
Function to get the space values used for the Power Series endgame.
Definition powerseries.hpp:281
TupleOfSamps derivatives_
Definition powerseries.hpp:214
std::tuple< TimeCont< CT >, SampCont< CT > > TransformToSPlane(int cycle_num, CT const &t0, unsigned num_pts, ContStart shift_from)
Definition powerseries.hpp:475
TupleOfTimes times_
Definition powerseries.hpp:204
Vec< BCT > rand_vector_
Definition powerseries.hpp:219
SuccessCode RunImpl(const CT &start_time, const Vec< CT > &start_point, CT const &target_time)
Primary function running the Power Series endgame.
Definition powerseries.hpp:642
unsigned ComputeBoundOnCycleNumber()
Computes an upper bound on the cycle number. Consult page 53 of bertinibook.
Definition powerseries.hpp:318
const auto & GetTimes() const
Function to get the times used for the Power Series endgame.
Definition powerseries.hpp:263
unsigned ComputeCycleNumber(CT const &t0)
This function computes the cycle number using an exhaustive search up the upper bound computed by the...
Definition powerseries.hpp:376
TupleOfSamps samples_
Definition powerseries.hpp:209
void ClearTimesAndSamples()
Function that clears all samples and times from data members for the Power Series endgame.
Definition powerseries.hpp:247
SuccessCode ComputeApproximationOfXAtT0(Vec< CT > &result, const CT &t0)
This function computes an approximation of the space value at the time time_t0.
Definition powerseries.hpp:532
void SetTimes(TimeCont< CT > const ×_to_set)
Function to set the times used for the Power Series endgame.
Definition powerseries.hpp:257
void ComputeAllDerivatives()
Compute a set of derivatives using internal data to the endgame.
Definition powerseries.hpp:444
unsigned upper_bound_on_cycle_number_
Definition powerseries.hpp:199
void SetSamples(SampCont< CT > const &samples_to_set)
Function to set the space values used for the Power Series endgame.
Definition powerseries.hpp:275
void SetRandVec(int size)
Function to set the times used for the Power Series endgame.
Definition powerseries.hpp:287
SuccessCode AdvanceTime(const CT &target_time)
The samples used in the power series endgame are collected by advancing time to t = 0,...
Definition powerseries.hpp:567
dbl pow(const dbl &z, int power)
Definition double_extensions.hpp:88
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object. If the object is empty, it's the precision of a default-constru...
Definition eigen_extensions.hpp:292
Vec< CT > HermiteInterpolateAndSolve(CT const &target_time, const unsigned int num_sample_points, const TimeCont< CT > ×, const SampCont< CT > &samples, const SampCont< CT > &derivatives, ContStart shift_from=ContStart::Back)
Estimates the root to interpolating polynomial.
Definition interpolation.hpp:63
T max(T const &a, T const &b, T const &c)
Three-argument form of max.
Definition mpfr_extensions.hpp:98