Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
fixed_precision_tracker.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//fixed_precision_tracker.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//fixed_precision_tracker.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with fixed_precision_tracker.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
26
27#ifndef BERTINI_FIXED_PRECISION_TRACKER_HPP
28#define BERTINI_FIXED_PRECISION_TRACKER_HPP
29
31
32
33namespace bertini{
34
35 namespace tracking{
36
37 using std::max;
38 using std::min;
39 using std::pow;
40
41 using bertini::max;
42
43
44
45
46
47
48
54 template<class DerivedT>
55 class FixedPrecisionTracker : public Tracker<FixedPrecisionTracker<DerivedT>>
56 {
57 public:
58
61
63 using RealT = BaseRealT;
64
65 virtual ~FixedPrecisionTracker() = default;
66
69
70 using Config = typename Base::Config;
72 using Stepping = typename Base::Stepping;
73 using Newton = typename Base::Newton;
74
76 FixedPrecisionTracker(System const& sys) : Base(sys){}
77
83
84
86 Vec<ComplexT> CurrentPoint() const override
87 {
88 return std::get<Vec<ComplexT>>(this->current_space_);
89 }
90
91
92
93 void ResetCounters() const override
94 {
96
98 // initialize to the frequency so guaranteed to compute it the first try
99 this->num_steps_since_last_condition_number_computation_ = this->Get<Stepping>().frequency_of_CN_estimation;
100 }
101
102
109 {
110 // The budget counts EVERY step, not only the successful ones. A path that
111 // fails steps has spent the effort whether or not it advanced, and counting
112 // only successes leaves a failing path un-budgeted: it can fail forever at
113 // 0% of its allowance. See issue #410.
114 if (this->NumTotalStepsTaken() >= Get<Stepping>().max_num_steps)
116 if (this->current_stepsize_ < Get<Stepping>().min_step_size)
118
120 }
121
122
123
124
125
126
127
128
129
130
131 void PostTrackCleanup() const override
132 {
133 this->NotifyObservers(TrackingEnded<EmitterType>(*this));
134 }
135
143 void CopySolution(Vec<ComplexT> & solution_at_endtime) const override
144 {
145
146 // the current precision is the precision of the output solution point.
147
148 unsigned num_vars = static_cast<unsigned>(this->GetSystem().NumVariables());
149 solution_at_endtime.resize(num_vars);
150 for (unsigned ii=0; ii<num_vars; ii++)
151 {
152 solution_at_endtime(ii) = std::get<Vec<ComplexT> >(this->current_space_)(ii);
153 }
154
155 }
156
157
158
159
168 {
169 static_assert(std::is_same< typename Eigen::NumTraits<RealT>::Real,
170 typename Eigen::NumTraits<ComplexT>::Real>::value,
171 "underlying complex type and the type for comparisons must match");
172
173 this->NotifyObservers(NewStep<EmitterType >(*this));
174
175 Vec<ComplexT>& predicted_space = std::get<Vec<ComplexT> >(this->temporary_space_); // this will be populated in the Predict step
176 Vec<ComplexT>& current_space = std::get<Vec<ComplexT> >(this->current_space_); // the thing we ultimately wish to update
177 ComplexT current_time = ComplexT(this->current_time_);
178 ComplexT delta_t = ComplexT(this->delta_t_);
179
180 SuccessCode predictor_code = Predict(predicted_space, current_space, current_time, delta_t);
181
182 if (predictor_code!=SuccessCode::Success)
183 {
184 this->NotifyObservers(FirstStepPredictorMatrixSolveFailure<EmitterType >(*this));
185
186 this->next_stepsize_ = RealT(Get<Stepping>().step_size_fail_factor)*this->current_stepsize_;
187
189
190 return predictor_code;
191 }
192
193 this->NotifyObservers(SuccessfulPredict<EmitterType , ComplexT>(*this, predicted_space));
194
195 Vec<ComplexT>& tentative_next_space = std::get<Vec<ComplexT> >(this->tentative_space_); // this will be populated in the Correct step
196
197 ComplexT tentative_next_time = current_time + delta_t;
198
199 SuccessCode corrector_code = Correct(tentative_next_space,
200 predicted_space,
201 tentative_next_time);
202
203 if (corrector_code == SuccessCode::GoingToInfinity)
204 {
205 // there is no corrective action possible...
206 return corrector_code;
207 }
208 else if (corrector_code!=SuccessCode::Success)
209 {
210 this->NotifyObservers(CorrectorMatrixSolveFailure<EmitterType >(*this));
211
212 this->next_stepsize_ = RealT(Get<Stepping>().step_size_fail_factor)*this->current_stepsize_;
214
215 return corrector_code;
216 }
217
218
219 this->NotifyObservers(SuccessfulCorrect<EmitterType , ComplexT>(*this, tentative_next_space));
220
221 // copy the tentative vector into the current space vector;
222 current_space = tentative_next_space;
224 }
225
226
231 {
232 return Base::template CheckGoingToInfinity<ComplexT>();
233 }
234
235
236
237
238
243 {
244 this->SetStepSize(this->next_stepsize_);
246 }
247
248
249
250
251
253 //
254 // overrides for counter adjustment after a TrackerIteration()
255 //
257
261 void OnStepSuccess() const override
262 {
264 this->NotifyObservers(SuccessfulStep<EmitterType >(*this));
265 }
266
270 void OnStepFail() const override
271 {
274 this->NotifyObservers(FailedStep<EmitterType >(*this));
275 }
276
277
278
280 void OnInfiniteTruncation() const override
281 {
282 this->NotifyObservers(InfinitePathTruncation<EmitterType>(*this));
283 }
284
286 //
287 //
288
289
303 Vec<ComplexT> const& current_space,
304 ComplexT const& current_time, ComplexT const& delta_t) const
305 {
306
307 return this->predictor_.Predict(
308 predicted_space,
309 this->last_step_,
310 this->tracked_system_,
311 current_space, current_time,
312 delta_t,
314 Get<Stepping>().frequency_of_CN_estimation,
315 this->TrackingTolerance());
316 }
317
318
319
332 Vec<ComplexT> const& current_space,
333 ComplexT const& current_time) const
334 {
335 return this->corrector_.Correct(corrected_space,
336 this->last_step_,
337 this->tracked_system_,
338 current_space,
339 current_time,
340 this->TrackingTolerance(),
341 Get<Newton>().min_num_newton_iterations,
342 Get<Newton>().max_num_newton_iterations);
343 }
344
345
346
360 Vec<ComplexT> const& start_point, ComplexT const& current_time) const
361 {
362 return this->corrector_.Correct(new_space,
363 this->last_step_,
364 this->tracked_system_,
365 start_point,
366 current_time,
367 this->TrackingTolerance(),
368 Get<Newton>().min_num_newton_iterations,
369 Get<Newton>().max_num_newton_iterations);
370 }
371
372
373
374
375
376
392 Vec<ComplexT> const& start_point, ComplexT const& current_time,
393 NumErrorT const& tolerance, unsigned max_iterations) const
394 {
395 return this->corrector_.Correct(new_space,
396 this->last_step_,
397 this->tracked_system_,
398 start_point,
399 current_time,
400 tolerance,
401 1,
402 max_iterations);
403 }
404
405
412 //
413
414 // no additional state variables needed for the FixedPrecision base tracker types
415
416 };
417
418
419
420
422 class DoublePrecisionTracker : public FixedPrecisionTracker<DoublePrecisionTracker>
423 {
424 public:
426 using BaseRealT = double;
427
429
430
435 {
436 // Report the precision honestly: double tracking is always DoublePrecision() digits.
439 this->template Set<FixedPrecisionConfig>(c);
440 }
441
442
444
445 virtual ~DoublePrecisionTracker() = default;
446
447
449 unsigned CurrentPrecision() const override
450 {
451 return DoublePrecision();
452 }
453
460 {
461 if (c.precision != 0 && c.precision != DoublePrecision())
462 throw std::runtime_error("double-precision tracking is fixed at "
463 + std::to_string(DoublePrecision())
464 + " digits; cannot set precision to " + std::to_string(c.precision)
465 + " (use mptype 'multiple' or 'adaptive')");
466 }
467
468
479 BaseComplexT const& end_time,
480 Vec<BaseComplexT> const& start_point) const override
481 {
482 this->NotifyObservers(Initializing<EmitterType,BaseComplexT>(*this,start_time, end_time, start_point));
483
484 // set up the master current time and the current step size
485 this->current_time_ = start_time;
486 this->endtime_ = end_time;
487 std::get<Vec<BaseComplexT> >(this->current_space_) = start_point;
488 if (this->reinitialize_stepsize_)
489 this->SetStepSize(min(BaseRealT(Get<Stepping>().initial_step_size),abs(start_time-end_time)/Get<Stepping>().min_num_steps));
490
492
494 }
495
496
497 private:
498
499 }; // re: DoublePrecisionTracker
500
501
503 class MultiplePrecisionTracker : public FixedPrecisionTracker<MultiplePrecisionTracker>
504 {
505 public:
508
510
511
518 {
519 SyncPrecisionToConfig();
520 }
521
522
524
525 virtual ~MultiplePrecisionTracker() = default;
526
527
529 unsigned CurrentPrecision() const override
530 {
531 return precision_;
532 }
533
542 void SetPrecision(unsigned p)
543 {
544 precision_ = p;
545 SyncPrecisionToConfig();
546 }
547
553 {
554 if (c.precision != 0)
556 }
557
558
569 BaseComplexT const& end_time,
570 Vec<BaseComplexT> const& start_point) const override
571 {
572
573 // ThreadPrecision: thread-local read, correct both on the main thread
574 // (where it equals the global) and on std::thread workers.
575 if (start_point(0).precision()!=ThreadPrecision())
576 {
577 std::stringstream err_msg;
578 err_msg << "start point for fixed multiple precision tracker has differing precision from default (" << start_point(0).precision() << "!=" << ThreadPrecision() << "), tracking cannot start";
579 throw std::runtime_error(err_msg.str());
580 }
581
582 if (start_point(0).precision()!=this->CurrentPrecision())
583 {
584 std::stringstream err_msg;
585 err_msg << "start point for fixed multiple precision tracker has differing precision from tracker's precision (" << start_point(0).precision() << "!=" << this->CurrentPrecision() << "), tracking cannot start";
586 throw std::runtime_error(err_msg.str());
587 }
588
589 if (ThreadPrecision()!=this->CurrentPrecision())
590 {
591 std::stringstream err_msg;
592 err_msg << "current default precision differs from tracker's precision (" << ThreadPrecision() << "!=" << this->CurrentPrecision() << "), tracking cannot start";
593 throw std::runtime_error(err_msg.str());
594 }
595
596
597 this->NotifyObservers(Initializing<EmitterType,BaseComplexT>(*this,start_time, end_time, start_point));
598
599 // Reset precision of all persistent members before assignment so that
600 // BMP preserve_related_precision doesn't propagate stale high precision
601 // from a previous TrackPath call into the new one.
602 this->current_time_.precision(precision_);
603 this->endtime_.precision(precision_);
604 this->delta_t_.precision(precision_);
605 this->current_stepsize_.precision(precision_);
606 this->next_stepsize_.precision(precision_);
607 Precision(std::get<Vec<BaseComplexT>>(this->current_space_), precision_);
608 Precision(std::get<Vec<BaseComplexT>>(this->temporary_space_), precision_);
609 Precision(std::get<Vec<BaseComplexT>>(this->tentative_space_), precision_);
610 this->predictor_.ChangePrecision(precision_);
611 this->corrector_.ChangePrecision(precision_);
612
613 // set up the master current time and the current step size
614 this->current_time_ = start_time;
615 this->endtime_ = end_time;
616 std::get<Vec<BaseComplexT> >(this->current_space_) = start_point;
617 if (this->reinitialize_stepsize_)
618 this->SetStepSize(min(real_mp(Get<Stepping>().initial_step_size),real_mp(abs(start_time-end_time)/Get<Stepping>().min_num_steps)));
619
621
623 }
624
627 {
628 // the System is no longer checked here: it carries no precision of its own, and
629 // evaluation materializes it from the point it is handed (ADR-0057)
630 return ThreadPrecision()==precision_ &&
631 std::get<Vec<complex_mp> >(current_space_)(0).precision() == precision_ &&
632 std::get<Vec<complex_mp> >(tentative_space_)(0).precision() == precision_ &&
633 std::get<Vec<complex_mp> >(temporary_space_)(0).precision() == precision_ &&
634 Precision(this->endtime_)==precision_
635 ;
636 }
637 private:
638
639 // Keep the stored FixedPrecisionConfig.precision equal to the tracker's actual precision,
640 // so reading the config tells you the precision in effect (not the 0 sentinel).
641 void SyncPrecisionToConfig()
642 {
644 c.precision = precision_;
645 this->template Set<FixedPrecisionConfig>(c);
646 }
647
648 unsigned precision_;
649 }; // re: MultiplePrecisionTracker
650 } // namespace tracking
651} // namespace bertini
652
653
654#endif
Contains the abstract base Tracker type, from which all other Trackers inherit.
void NotifyObservers(AnyEvent const &e) const
Definition observable.hpp:185
The fundamental polynomial system class for Bertini2.
Definition system.hpp:106
size_t NumVariables() const
Get the total number of variables in this system, including homogenizing variables.
complex_dbl BaseComplexT
The complex number type.
Definition fixed_precision_tracker.hpp:425
void PrecisionSetup(FixedPrecisionConfig const &c)
Double-precision tracking is fixed at DoublePrecision() digits.
Definition fixed_precision_tracker.hpp:459
DoublePrecisionTracker(class System const &sys)
Construct a tracker, associating to it a System.
Definition fixed_precision_tracker.hpp:434
unsigned CurrentPrecision() const override
Get the current working precision (always DoublePrecision() for this tracker).
Definition fixed_precision_tracker.hpp:449
SuccessCode TrackerLoopInitialization(BaseComplexT const &start_time, BaseComplexT const &end_time, Vec< BaseComplexT > const &start_point) const override
Set up the internals of the tracker for a fresh start.
Definition fixed_precision_tracker.hpp:478
typename TrackerTraits< DoublePrecisionTracker >::EventEmitterType EmitterType
The event-emitter type for this tracker.
Definition fixed_precision_tracker.hpp:428
double BaseRealT
The real number type.
Definition fixed_precision_tracker.hpp:426
void OnInfiniteTruncation() const override
React to a path being truncated for going to infinity, by notifying observers.
Definition fixed_precision_tracker.hpp:280
BaseComplexT ComplexT
The complex number type.
Definition fixed_precision_tracker.hpp:62
SuccessCode RefineImpl(Vec< ComplexT > &new_space, Vec< ComplexT > const &start_point, ComplexT const &current_time, NumErrorT const &tolerance, unsigned max_iterations) const
Run Newton's method from a start point with a current time.
Definition fixed_precision_tracker.hpp:391
typename Base::Newton Newton
The Newton corrector configuration type.
Definition fixed_precision_tracker.hpp:73
SuccessCode TrackerIteration() const override
Run an iteration of the tracker loop.
Definition fixed_precision_tracker.hpp:167
SuccessCode Predict(Vec< ComplexT > &predicted_space, Vec< ComplexT > const &current_space, ComplexT const &current_time, ComplexT const &delta_t) const
Wrapper function for calling the correct predictor.
Definition fixed_precision_tracker.hpp:302
SuccessCode RefineImpl(Vec< ComplexT > &new_space, Vec< ComplexT > const &start_point, ComplexT const &current_time) const
Run Newton's method from a start point with a current time.
Definition fixed_precision_tracker.hpp:359
typename Base::Stepping Stepping
The stepping configuration type.
Definition fixed_precision_tracker.hpp:72
FixedPrecisionTracker(System const &sys)
Construct a fixed-precision tracker for a system.
Definition fixed_precision_tracker.hpp:76
SuccessCode UpdateStepsize() const
Commit the next stepsize, and adjust internals.
Definition fixed_precision_tracker.hpp:242
typename Base::Config Config
The configuration-holding base type.
Definition fixed_precision_tracker.hpp:70
typename TrackerTraits< DerivedT >::BaseRealT BaseRealT
The real number type.
Definition fixed_precision_tracker.hpp:60
SuccessCode Correct(Vec< ComplexT > &corrected_space, Vec< ComplexT > const &current_space, ComplexT const &current_time) const
Run Newton's method.
Definition fixed_precision_tracker.hpp:331
void PrecisionSetup(FixedPrecisionConfig const &)
An additional no-op call, provided for conformity of interface with AMP tracker in generic code.
Definition fixed_precision_tracker.hpp:81
void ResetCounters() const override
Reset counters used during tracking.
Definition fixed_precision_tracker.hpp:93
SuccessCode PreIterationCheck() const override
Ensure that number of steps, stepsize, and precision still ok.
Definition fixed_precision_tracker.hpp:108
SuccessCode CheckGoingToInfinity() const override
Check whether the path is going to infinity.
Definition fixed_precision_tracker.hpp:230
void OnStepFail() const override
Increment and reset counters after a failed TrackerIteration().
Definition fixed_precision_tracker.hpp:270
FixedPrecisionTracker< DerivedT > EmitterType
The event-emitter type for this tracker.
Definition fixed_precision_tracker.hpp:67
typename TrackerTraits< DerivedT >::BaseComplexT BaseComplexT
The complex number type.
Definition fixed_precision_tracker.hpp:59
Tracker< FixedPrecisionTracker< DerivedT > > Base
The base tracker type.
Definition fixed_precision_tracker.hpp:68
void OnStepSuccess() const override
Increment and reset counters after a successful TrackerIteration().
Definition fixed_precision_tracker.hpp:261
void CopySolution(Vec< ComplexT > &solution_at_endtime) const override
Copy from the internally stored current solution into a final solution.
Definition fixed_precision_tracker.hpp:143
Vec< ComplexT > CurrentPoint() const override
Get the current space point of the track.
Definition fixed_precision_tracker.hpp:86
void PostTrackCleanup() const override
Function to be called before exiting the tracker loop.
Definition fixed_precision_tracker.hpp:131
BaseRealT RealT
The real number type.
Definition fixed_precision_tracker.hpp:63
TrackPath is initializing the tracker.
Definition events.hpp:295
void PrecisionSetup(FixedPrecisionConfig const &c)
Adopt the precision named in a FixedPrecisionConfig (its sentinel 0 means "leave asis").
Definition fixed_precision_tracker.hpp:552
complex_mp BaseComplexT
The complex number type.
Definition fixed_precision_tracker.hpp:506
unsigned CurrentPrecision() const override
Get the current (fixed multiple) working precision of this tracker.
Definition fixed_precision_tracker.hpp:529
bool PrecisionSanityCheck() const
Check that the system, thread precision, and all tracker state are at the expected precision.
Definition fixed_precision_tracker.hpp:626
real_mp BaseRealT
The real number type.
Definition fixed_precision_tracker.hpp:507
FixedPrecisionTracker< MultiplePrecisionTracker > EmitterType
The event-emitter type for this tracker.
Definition fixed_precision_tracker.hpp:509
void SetPrecision(unsigned p)
Set the fixed precision this tracker works at.
Definition fixed_precision_tracker.hpp:542
MultiplePrecisionTracker(class System const &sys)
Construct a tracker, associating to it a System.
Definition fixed_precision_tracker.hpp:517
SuccessCode TrackerLoopInitialization(BaseComplexT const &start_time, BaseComplexT const &end_time, Vec< BaseComplexT > const &start_point) const override
Set up the internals of the tracker for a fresh start.
Definition fixed_precision_tracker.hpp:568
The correct part of a time step was successful.
Definition events.hpp:102
The predict part of tracking step was successful.
Definition events.hpp:72
predict::ExplicitRKPredictor predictor_
Definition base_tracker.hpp:815
Tracker(System const &sys)
Definition base_tracker.hpp:181
SteppingConfig Stepping
Definition base_tracker.hpp:176
const System & GetSystem() const
Definition base_tracker.hpp:507
unsigned num_successful_steps_since_stepsize_increase_
Definition base_tracker.hpp:837
correct::NewtonCorrector corrector_
Definition base_tracker.hpp:818
NewtonConfig Newton
Definition base_tracker.hpp:177
unsigned NumTotalStepsTaken() const
Definition base_tracker.hpp:517
unsigned num_steps_since_last_condition_number_computation_
Definition base_tracker.hpp:836
void IncrementBaseCountersFail() const
Definition base_tracker.hpp:761
auto TrackingTolerance() const
Definition base_tracker.hpp:614
std::reference_wrapper< const System > tracked_system_
Definition base_tracker.hpp:787
StepMetadata last_step_
Definition base_tracker.hpp:850
detail::Configured< typename TrackerTraits< FixedPrecisionTracker< DerivedT > >::NeededConfigs > Config
Definition base_tracker.hpp:175
void ResetCountersBase() const
Definition base_tracker.hpp:727
void SetStepSize(RealT const &new_stepsize) const
Definition base_tracker.hpp:595
void IncrementBaseCountersSuccess() const
Definition base_tracker.hpp:742
#define FORWARD_GET_CONFIGURED
Macro injecting a Get<T>() that forwards to the class's Config base (for Configured users).
Definition configured.hpp:125
Definition adaptive_precision_utilities.hpp:35
Definition algorithm_builder.hpp:36
constexpr unsigned DoublePrecision()
The number of digits considered "double precision" (16).
Definition num_traits.hpp:152
std::complex< double > complex_dbl
The double-precision complex number type.
Definition double_extensions.hpp:47
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
double NumErrorT
The numeric type used to hold error/tolerance magnitudes throughout Bertini2 – tracking tolerances,...
Definition num_traits.hpp:48
bmp::number< mpc_complex_backend< 0 >, bmp::et_on > complex_mp
The arbitrary-precision complex number type.
Definition mpfr_complex.hpp:58
auto DefaultPrecision()
Get the global default precision (digits) for multiprecision numbers.
Definition mpfr_complex.hpp:135
SuccessCode
Definition config.hpp:42
@ MinStepSizeReached
Definition config.hpp:60
@ Success
Definition config.hpp:51
@ MaxNumStepsTaken
Definition config.hpp:58
@ GoingToInfinity
Definition config.hpp:54
boost::multiprecision::number< boost::multiprecision::mpfr_float_backend< 0 >, boost::multiprecision::et_on > real_mp
The arbitrary-precision real number type.
Definition mpfr_extensions.hpp:53
unsigned ThreadPrecision()
Get the current thread's precision (digits).
Definition mpfr_complex.hpp:183
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
T max(T const &a, T const &b, T const &c)
Three-argument form of max.
Definition mpfr_extensions.hpp:96
void Set(T const &t)
Definition configured.hpp:101
Settings for a fixed-precision tracker (carries the single working precision in effect).
Definition config.hpp:157
unsigned precision
The number of digits to always work at.
Definition config.hpp:170
Trait lookup mapping a tracker type to its numeric types, event-emitter type, precision config,...
Definition config.hpp:387