40namespace bertini{
namespace endgame{
169template<
typename PrecT>
171 public virtual EndgameBase<CauchyEndgame<PrecT>, PrecT>
174 using BaseEGT = EndgameBase<CauchyEndgame<PrecT>, PrecT>;
175 using FinalEGT = CauchyEndgame<PrecT>;
176 using TrackerType =
typename PrecT::TrackerType;
178 using BaseComplexType =
typename tracking::TrackerTraits<TrackerType>::BaseComplexType;
179 using BaseRealType =
typename tracking::TrackerTraits<TrackerType>::BaseRealType;
181 using EmitterType = CauchyEndgame<PrecT>;
190 using TupleOfTimes =
typename BaseEGT::TupleOfTimes;
191 using TupleOfSamps =
typename BaseEGT::TupleOfSamps;
193 using BCT = BaseComplexType;
194 using BRT = BaseRealType;
196 using Configs =
typename AlgoTraits<FinalEGT>::NeededConfigs;
197 using ConfigsAsTuple =
typename Configs::ToTuple;
229 template<
typename CT>
239 template<
typename CT>
241 { std::get<TimeCont<CT> >(
pseg_times_) = pseg_times_to_set;}
246 template<
typename CT>
248 template<
typename CT>
254 template<
typename CT>
262 template<
typename CT>
264 template<
typename CT>
269 template<
typename CT>
280 template<
typename CT>
285 template<
typename CT>
292 template<
typename CT>
295 std::get<TimeCont<CT> >(
cauchy_times_) = cauchy_times_to_set;
301 template<
typename CT>
306 template<
typename CT>
313 const BCT& LatestTimeImpl()
const
324 this->
template Set(new_cauchy_settings);
332 return this->
template Get<CauchyConfig>();
337 const ConfigsAsTuple& settings )
341 template<
typename... Ts >
342 CauchyEndgame(TrackerType
const& tr,
const Ts&... ts ) : CauchyEndgame(tr, Configs::Unpermute( ts... ) )
346 virtual ~CauchyEndgame() =
default;
348 void ValidateConfigs()
350 if (this->EndgameSettings().num_sample_points < 3)
352 std::stringstream err_msg;
353 err_msg <<
"ERROR: The number of sample points " << this->EndgameSettings().num_sample_points <<
" for circle tracking must be >= 3";
354 throw std::runtime_error(err_msg.str());
375 template<
typename CT>
379 using RT =
typename Eigen::NumTraits<CT>::Real;
387 CT starting_time = circle_times.back();
391 const auto num_vars = this->GetSystem().NumVariables();
393 for (
unsigned ii = 0; ii < this->EndgameSettings().num_sample_points; ++ii)
395 const Vec<CT>& current_sample = circle_samples.back();
396 const CT& current_time = circle_times.back();
398#ifndef BERTINI_DISABLE_PRECISION_CHECKS
400 std::stringstream err_msg;
401 err_msg <<
"current time and sample for circle track must be of same precision. respective precisions: " <<
Precision(current_time) <<
" " <<
Precision(current_sample) << std::endl;
402 throw std::runtime_error(err_msg.str());
409#ifndef USE_BMP_COMPLEX
410 using bertini::polar;
415 RT radius = abs(starting_time - target_time), angle = arg(starting_time - target_time);
417 auto next_sample = Vec<CT>(num_vars);
418 CT next_time = (ii==this->EndgameSettings().num_sample_points-1)
422 polar(radius, (ii+1)*2*acos(
static_cast<RT
>(-1)) / (this->EndgameSettings().num_sample_points) + angle) + target_time;
427 auto tracking_success = this->GetTracker().TrackPath(next_sample, current_time, next_time, current_sample);
428 if (tracking_success != SuccessCode::Success)
430 return tracking_success;
449 AddToCauchyData(next_time, next_sample);
454 return SuccessCode::Success;
458 template<
typename CT>
459 void AddToCauchyData(CT
const& time, Vec<CT>
const& sample)
465 template<
typename CT>
466 void AddToPSData(CT
const& time, Vec<CT>
const& sample)
468 std::get<TimeCont<CT>>(
pseg_times_).push_back(time);
489 template<
typename CT>
492 using RT =
typename Eigen::NumTraits<CT>::Real;
496 const auto& pseg_samples = std::get<SampCont<CT> >(
pseg_samples_);
498 assert(pseg_samples.size()>=3);
499 const Vec<CT> & sample0 = pseg_samples[0];
500 const Vec<CT> & sample1 = pseg_samples[1];
501 const Vec<CT> & sample2 = pseg_samples[2];
503 Vec<CT> rand_vector = Vec<CT>::Random(sample0.size());
508 RT estimate = abs(log(abs((((sample2 - sample1).transpose()*rand_vector).
template lpNorm<Eigen::Infinity>())/(((sample1 - sample0).transpose()*rand_vector).
template lpNorm<Eigen::Infinity>()))));
509 estimate = abs(log(RT(this->EndgameSettings().sample_factor)))/estimate;
532 template<
typename CT>
535 using RT =
typename Eigen::NumTraits<CT>::Real;
539 for(
unsigned ii = 1; ii <
GetCauchySettings().num_needed_for_stabilization ; ++ii)
541 RT a = abs(c_over_k_array[ii-1]);
542 RT b = abs(c_over_k_array[ii]);
544 typename Eigen::NumTraits<CT>::Real divide = a;
623 template<
typename CT>
626 using RT =
typename Eigen::NumTraits<CT>::Real;
630 if((samples.front() - samples.back()).template lpNorm<Eigen::Infinity>() < this->GetTracker().TrackingTolerance())
635 if (tracking::TrackerTraits<TrackerType>::IsAdaptivePrec)
638 auto new_precision = this->EnsureAtUniformPrecision(times, samples);
639 this->GetSystem().precision(new_precision);
642 this->GetTracker().Refine(samples.front(),samples.front(),times.front(),this->FinalTolerance(),this->EndgameSettings().max_num_newton_iterations);
643 this->GetTracker().Refine(samples.back(),samples.back(),times.back(),this->FinalTolerance(),this->EndgameSettings().max_num_newton_iterations);
645 if((samples.front() - samples.back()).template lpNorm<Eigen::Infinity>() < this->GetTracker().TrackingTolerance())
674 template<
typename CT>
677 using RT =
typename Eigen::NumTraits<CT>::Real;
689 for(
unsigned int ii=0; ii < this->EndgameSettings().num_sample_points; ++ii)
691 norm = samples[ii].template lpNorm<Eigen::Infinity>();
702 if(min > this->FinalTolerance() &&
max > this->FinalTolerance())
740 template<
typename CT>
745 auto fail_safe_max_cycle_number =
GetCauchySettings().fail_safe_maximum_cycle_number;
747 auto initial_cauchy_loop_success = SuccessCode::Success;
749 bool loop_hasnt_closed =
true;
750 while (loop_hasnt_closed)
752 this->CycleNumber(0);
753 ClearAndSeedCauchyData<CT>();
757 this->IncrementCycleNumber(1);
758 if (tracking_success != SuccessCode::Success)
759 return tracking_success;
769 initial_cauchy_loop_success = SuccessCode::Success;
770 loop_hasnt_closed =
false;
773 else if(this->CycleNumber() > fail_safe_max_cycle_number)
775 initial_cauchy_loop_success = SuccessCode::CycleNumTooHigh;
776 loop_hasnt_closed =
false;
782 this->IncrementCycleNumber(1);
783 if(tracking_success != SuccessCode::Success)
784 return tracking_success;
790 if (advance_success!=SuccessCode::Success)
791 return advance_success;
795 return initial_cauchy_loop_success;
800 template <
typename CT>
801 void RotateOntoPS(CT
const& next_time, Vec<CT>
const& next_sample)
803 auto& ps_times = std::get<TimeCont<CT> >(
pseg_times_);
806 ps_times.pop_front();
807 ps_samples.pop_front();
809 ps_times.push_back(next_time);
810 ps_samples.push_back(next_sample);
813 template <
typename CT>
814 void ClearAndSeedCauchyData()
818 auto& ps_times = std::get<TimeCont<CT> >(
pseg_times_);
823 cau_samples.push_back(ps_samples.back());
824 cau_times.push_back(ps_times.back());
851 template<
typename CT>
853 CT
const& target_time, Vec<CT> & approximation)
855 auto init_success = GetIntoEGZone(start_time, start_point, target_time);
856 if (init_success!= SuccessCode::Success)
860 if (cauchy_loop_success != SuccessCode::Success)
861 return cauchy_loop_success;
869 template<
typename CT>
870 SuccessCode GetIntoEGZone(CT
const& start_time, Vec<CT>
const& start_point, CT
const& target_time)
872 using RT =
typename Eigen::NumTraits<CT>::Real;
875 std::deque<RT> c_over_k;
877 auto& ps_times = std::get<TimeCont<CT> >(
pseg_times_);
881 auto initial_sample_success = this->ComputeInitialSamples(start_time, target_time, start_point, ps_times, ps_samples);
882 if (initial_sample_success!=SuccessCode::Success)
883 return initial_sample_success;
889 for (
unsigned ii = 0; ii <
GetCauchySettings().num_needed_for_stabilization; ++ii)
892 if (advance_success!=SuccessCode::Success)
893 return advance_success;
902 if (advance_success!=SuccessCode::Success)
903 return advance_success;
905 c_over_k.pop_front();
912 return SuccessCode::Success;
930 template<
typename CT>
933 using RT =
typename Eigen::NumTraits<CT>::Real;
937 if (cau_samples.size() != this->CycleNumber() * this->EndgameSettings().num_sample_points+1)
939 std::stringstream err_msg;
940 err_msg <<
"to compute cauchy approximation, cau_samples must be of size " << this->CycleNumber() * this->EndgameSettings().num_sample_points+1 <<
" but is of size " << cau_samples.size() <<
'\n';
941 throw std::runtime_error(err_msg.str());
946 if (tracking::TrackerTraits<TrackerType>::IsAdaptivePrec)
948 auto new_precision = this->EnsureAtUniformPrecision(cau_times, cau_samples);
949 this->GetSystem().precision(new_precision);
953 auto total_num_pts = this->CycleNumber() * this->EndgameSettings().num_sample_points;
954 this->
template RefineAllSamples(cau_samples, cau_times);
958 result = Vec<CT>::Zero(this->GetSystem().NumVariables());
959 for(
unsigned int ii = 0; ii < total_num_pts; ++ii)
960 result += cau_samples[ii];
961 result /= this->CycleNumber() * this->EndgameSettings().num_sample_points;
963 return SuccessCode::Success;
985 template<
typename CT>
990 ClearAndSeedCauchyData<CT>();
991 this->CycleNumber(0);
994 while( this->CycleNumber() <
GetCauchySettings().fail_safe_maximum_cycle_number )
998 this->IncrementCycleNumber(1);
1000 if(tracking_success != SuccessCode::Success)
1002 return tracking_success;
1006 return SuccessCode::Success;
1010 return SuccessCode::CycleNumTooHigh;
1021 template<
typename CT>
1024 using RT =
typename Eigen::NumTraits<CT>::Real;
1026 auto& ps_times = std::get<TimeCont<CT> >(
pseg_times_);
1029 auto& current_time = ps_times.back();
1030 auto& current_sample = ps_samples.back();
1033 CT next_time = (target_time-current_time) *
static_cast<RT
>(this->EndgameSettings().sample_factor)+current_time;
1035 if (abs(next_time - target_time) < this->EndgameSettings().min_track_time)
1036 return SuccessCode::MinTrackTimeReached;
1039 Vec<CT> next_sample;
1040 auto time_advance_success = this->GetTracker().TrackPath(next_sample,current_time, next_time, current_sample);
1041 if (time_advance_success != SuccessCode::Success)
1044 return time_advance_success;
1047 this->EnsureAtPrecision(next_time,
Precision(next_sample));
1048 RotateOntoPS(next_time, next_sample);
1051 return SuccessCode::Success;
1075 template<
typename CT>
1076 SuccessCode
RunImpl(CT
const& start_time, Vec<CT>
const& start_point, CT
const& target_time)
1078 if (start_point.size()!=this->GetSystem().NumVariables())
1080 std::stringstream err_msg;
1081 err_msg <<
"number of variables in start point for CauchyEG, " << start_point.size() <<
", must match the number of variables in the system, " << this->GetSystem().NumVariables();
1082 throw std::runtime_error(err_msg.str());
1087 std::stringstream ss;
1088 ss <<
"CauchyEG Run time and point must be of matching precision. (" <<
Precision(start_time) <<
"!=" <<
Precision(start_point) <<
")";
1089 throw std::runtime_error(ss.str());
1092 using RT =
typename Eigen::NumTraits<CT>::Real;
1094 Vec<CT>& latest_approx = this->final_approximation_;
1095 Vec<CT>& prev_approx = this->previous_approximation_;
1096 NumErrorT& approx_error = this->approximate_error_;
1100 this->CycleNumber(0);
1101 prev_approx = start_point;
1103 auto init_success = GetIntoEGZone(start_time, start_point, target_time);
1104 if (init_success!= SuccessCode::Success)
1105 return init_success;
1108 if (cauchy_loop_success != SuccessCode::Success)
1109 return cauchy_loop_success;
1112 RT norm_of_dehom_prev, norm_of_dehom_latest;
1114 if(this->SecuritySettings().level <= 0)
1115 norm_of_dehom_prev = this->GetSystem().DehomogenizePoint(prev_approx).template lpNorm<Eigen::Infinity>();
1122 if (extrapolation_success!=SuccessCode::Success)
1123 return extrapolation_success;
1125 approx_error =
static_cast<NumErrorT
>((latest_approx - prev_approx).template lpNorm<Eigen::Infinity>());
1128 if (approx_error < this->FinalTolerance())
1131 return SuccessCode::Success;
1134 if (this->SecuritySettings().level)
1136 norm_of_dehom_latest = this->GetSystem().DehomogenizePoint(latest_approx).template lpNorm<Eigen::Infinity>();
1138 if (norm_of_dehom_prev > this->SecuritySettings().max_norm &&
1139 norm_of_dehom_latest > this->SecuritySettings().max_norm )
1142 return SuccessCode::SecurityMaxNormReached;
1146 prev_approx = latest_approx;
1147 norm_of_dehom_prev = norm_of_dehom_latest;
1150 if (advance_success != SuccessCode::Success)
1151 return advance_success;
1155 if (cauchy_samples_success != SuccessCode::Success)
1156 return cauchy_samples_success;
1160 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
Class used to finish tracking paths during Homotopy Continuation.
Definition cauchy.hpp:172
TupleOfSamps pseg_samples_
Definition cauchy.hpp:206
bool RatioEGOperatingZoneTest(CT const &target_time) const
After we have used CircleTrack and have successfully closed the loop using CheckClosedLoop we need to...
Definition cauchy.hpp:675
void SetPSEGSamples(SampCont< CT > const &pseg_samples_to_set)
Setter for the space values for the power series approximation of the Cauchy endgame.
Definition cauchy.hpp:255
TimeCont< CT > & GetCauchyTimes()
Getter for the time values for the Cauchy endgame.
Definition cauchy.hpp:302
auto ComputeCOverK() const -> typename Eigen::NumTraits< CT >::Real
A function that uses the assumption of being in the endgame operating zone to compute an approximatio...
Definition cauchy.hpp:490
TimeCont< CT > & GetPSEGTimes()
Getter for the time values for the power series approximation of the Cauchy endgame.
Definition cauchy.hpp:247
bool CheckClosedLoop()
Function that determines if we have closed a loop after calling CircleTrack().
Definition cauchy.hpp:624
SuccessCode InitialApproximation(CT const &start_time, Vec< CT > const &start_point, CT const &target_time, Vec< CT > &approximation)
Definition cauchy.hpp:852
SuccessCode RunImpl(CT const &start_time, Vec< CT > const &start_point, CT const &target_time)
Primary function that runs the Cauchy endgame. To begin, this function will compute a first approxima...
Definition cauchy.hpp:1076
void SetCauchyTimes(TimeCont< CT > const &cauchy_times_to_set)
Setter for the time values for the Cauchy endgame.
Definition cauchy.hpp:293
TupleOfTimes pseg_times_
Definition cauchy.hpp:202
SampCont< CT > & GetPSEGSamples()
Getter for the space values for the power series approximation of the Cauchy endgame.
Definition cauchy.hpp:263
SuccessCode ComputeCauchyApproximationOfXAtT0(Vec< CT > &result)
Function that computes the mean of the samples that were collected while tracking around the origin....
Definition cauchy.hpp:931
SampCont< CT > & GetCauchySamples()
Getter for the space values for the Cauchy endgame.
Definition cauchy.hpp:281
void ClearTimesAndSamples()
Function that clears all samples and times from data members for the Cauchy endgame.
Definition cauchy.hpp:230
void SetCauchySettings(CauchyConfig const &new_cauchy_settings)
Setter for the specific settings in tracking_conifg.hpp under Cauchy.
Definition cauchy.hpp:322
SuccessCode AdvanceTime(CT const &target_time)
Advances time, marching toward the target time.
Definition cauchy.hpp:1022
SuccessCode ComputeCauchySamples(CT const &target_time)
Collects samples while tracking around the target time, until we close the loop, or exceed the limit ...
Definition cauchy.hpp:986
SuccessCode InitialCauchyLoops(CT const &target_time)
Definition cauchy.hpp:741
const auto & GetCauchySettings() const
Getter for the specific settings in tracking_conifg.hpp under Cauchy.
Definition cauchy.hpp:330
void SetPSEGTimes(TimeCont< CT > pseg_times_to_set)
Setter for the time values for the power series approximation of the Cauchy endgame.
Definition cauchy.hpp:240
bool CheckForCOverKStabilization(TimeCont< CT > const &c_over_k_array) const
Function to determine if ratios of c/k estimates are withing a user defined threshold.
Definition cauchy.hpp:533
TupleOfSamps cauchy_samples_
Definition cauchy.hpp:214
void SetCauchySamples(SampCont< CT > const &cauchy_samples_to_set)
Setter for the space values for the Cauchy endgame.
Definition cauchy.hpp:270
SuccessCode CircleTrack(CT const &target_time)
Function to track around the origin.
Definition cauchy.hpp:376
TupleOfTimes cauchy_times_
Definition cauchy.hpp:210
Advanced around the circle around target time.
Definition endgames/events.hpp:93
A common base type for various precision types, fixed and adaptive. The purpose of this is to maintai...
Definition prec_base.hpp:46
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
T max(T const &a, T const &b, T const &c)
Three-argument form of max.
Definition mpfr_extensions.hpp:98