Bertini 2 - C++ Core
Software for Numerical Algebraic Geometry
Loading...
Searching...
No Matches
newton_corrector.hpp
1//
2// newton_corrector.hpp
3// Xcode_b2
4//
5// Created by Collins, James B. on 4/27/16.
6// Copyright (c) 2016 West Texas A&M University. All rights reserved.
7//
8
9#ifndef BERTINI_NEWTON_CORRECTOR_HPP
10#define BERTINI_NEWTON_CORRECTOR_HPP
11
15
16
17namespace bertini{
18 namespace tracking{
19 namespace correct{
20
21
43
44 class NewtonCorrector
45 {
46 public:
47
48
49 NewtonCorrector(const System& S) : current_precision_(DefaultPrecision())
50 {
51 ChangeSystem(S);
52 }
53
54
55
56
57
58
59
66
67 void Settings(const NewtonConfig& newton_settings)
68 {
69 newton_config_ = newton_settings;
70 }
71
72
73
74
75
82 void ChangePrecision(unsigned new_precision)
83 {
84 Precision(std::get< Vec<mpfr_complex> >(f_temp_), new_precision);
85 Precision(std::get< Vec<mpfr_complex> >(step_temp_), new_precision);
86 Precision(std::get< Mat<mpfr_complex> >(J_temp_), new_precision);
87
88 std::get< Eigen::PartialPivLU<Mat<mpfr_complex>> >(LU_) = Eigen::PartialPivLU<Mat<mpfr_complex>>(numTotalFunctions_);
89
90 current_precision_ = new_precision;
91 }
92
93
94 unsigned precision() const
95 {
96 return current_precision_;
97 }
98
105 void ChangeSystem(const System& S)
106 {
107 numTotalFunctions_ = S.NumTotalFunctions();
108 numVariables_ = S.NumVariables();
109 std::get< Mat<dbl> >(J_temp_).resize(numTotalFunctions_, numVariables_);
110 std::get< Mat<mpfr_complex> >(J_temp_).resize(numTotalFunctions_, numVariables_);
111 std::get< Vec<dbl> >(f_temp_).resize(numTotalFunctions_);
112 std::get< Vec<mpfr_complex> >(f_temp_).resize(numTotalFunctions_);
113 std::get< Vec<dbl> >(step_temp_).resize(numTotalFunctions_);
114 std::get< Vec<mpfr_complex> >(step_temp_).resize(numTotalFunctions_);
115 }
116
117
118
119
139
140 template <typename ComplexType>
141 SuccessCode Correct(Vec<ComplexType> & next_space,
142 System const& S,
143 Vec<ComplexType> const& current_space, // pass by value to get a copy of it
144 ComplexType const& current_time,
145 NumErrorT const& tracking_tolerance,
146 unsigned min_num_newton_iterations,
147 unsigned max_num_newton_iterations)
148 {
149 #ifndef BERTINI_DISABLE_ASSERTS
150 assert(max_num_newton_iterations >= min_num_newton_iterations && "max number newton iterations must be at least the min.");
151 #endif
152
153 Vec<ComplexType>& step_ref = std::get< Vec<ComplexType> >(step_temp_);
154
155 next_space = current_space;
156 for (unsigned ii = 0; ii < max_num_newton_iterations; ++ii)
157 {
158 //Update the newton iterate by one iteration
159 auto success_code = EvalIterationStep(step_ref, S, next_space, current_time);
160 if(success_code != SuccessCode::Success)
161 return success_code;
162
163 next_space += step_ref;
164
165 if ( (step_ref.template lpNorm<Eigen::Infinity>() < tracking_tolerance) && (ii >= (min_num_newton_iterations-1)) )
166 return SuccessCode::Success;
167 }
168
169 return SuccessCode::FailedToConverge;
170
171
172
173 }
174
175
176
177
178
179
197 template <typename ComplexType>
198 SuccessCode Correct(Vec<ComplexType> & next_space,
199 System const& S,
200 Vec<ComplexType> const& current_space, // pass by value to get a copy of it
201 ComplexType const& current_time,
202 NumErrorT const& tracking_tolerance,
203 unsigned min_num_newton_iterations,
204 unsigned max_num_newton_iterations,
205 AdaptiveMultiplePrecisionConfig const& AMP_config)
206 {
207 #ifndef BERTINI_DISABLE_ASSERTS
208 assert(max_num_newton_iterations >= min_num_newton_iterations && "max number newton iterations must be at least the min.");
209 #endif
210
211 Vec<ComplexType>& step_ref = std::get< Vec<ComplexType> >(step_temp_);
212
213 next_space = current_space;
214 for (unsigned ii = 0; ii < max_num_newton_iterations; ++ii)
215 {
216 //Update the newton iterate by one iteration
217 auto success_code = EvalIterationStep(step_ref, S, next_space, current_time);
218 if(success_code != SuccessCode::Success)
219 return success_code;
220
221 next_space += step_ref;
222
223 Mat<ComplexType>& J_temp_ref = std::get< Mat<ComplexType> >(J_temp_);
224 Eigen::PartialPivLU< Mat<ComplexType> >& LU_ref = std::get< Eigen::PartialPivLU< Mat<ComplexType> > >(LU_);
225
226 if ( (step_ref.template lpNorm<Eigen::Infinity>() < tracking_tolerance) && (ii >= (min_num_newton_iterations-1)) )
227 return SuccessCode::Success;
228
229 NumErrorT norm_J_inverse(LU_ref.solve(RandomOfUnits<ComplexType>(S.NumVariables())).norm());
230
231 if (!amp::CriterionB<ComplexType>(NumErrorT(J_temp_ref.norm()), norm_J_inverse, max_num_newton_iterations - ii, tracking_tolerance, NumErrorT(step_ref.template lpNorm<Eigen::Infinity>()), AMP_config))
232 return SuccessCode::HigherPrecisionNecessary;
233
234 if (!amp::CriterionC<ComplexType>(norm_J_inverse, next_space, tracking_tolerance, AMP_config))
235 return SuccessCode::HigherPrecisionNecessary;
236 }
237
238 return SuccessCode::FailedToConverge;
239 }
240
241
242
243
244
245
268 template <typename ComplexType>
269 SuccessCode Correct(Vec<ComplexType> & next_space,
270 NumErrorT & norm_delta_z,
271 NumErrorT & norm_J,
272 NumErrorT & norm_J_inverse,
273 NumErrorT & condition_number_estimate,
274 System const& S,
275 Vec<ComplexType> const& current_space, // pass by value to get a copy of it
276 ComplexType const& current_time,
277 NumErrorT const& tracking_tolerance,
278 unsigned min_num_newton_iterations,
279 unsigned max_num_newton_iterations,
280 AdaptiveMultiplePrecisionConfig const& AMP_config)
281 {
282 #ifndef BERTINI_DISABLE_ASSERTS
283 assert(max_num_newton_iterations >= min_num_newton_iterations && "max number newton iterations must be at least the min.");
284 #endif
285
286 Vec<ComplexType>& step_ref = std::get< Vec<ComplexType> >(step_temp_);
287
288 next_space = current_space;
289 for (unsigned ii = 0; ii < max_num_newton_iterations; ++ii)
290 {
291 //Update the newton iterate by one iteration
292 auto success_code = EvalIterationStep(step_ref, S, next_space, current_time);
293 if(success_code != SuccessCode::Success)
294 return success_code;
295
296 next_space += step_ref;
297
298 Mat<ComplexType>& J_temp_ref = std::get< Mat<ComplexType> >(J_temp_);
299 Eigen::PartialPivLU< Mat<ComplexType> >& LU_ref = std::get< Eigen::PartialPivLU< Mat<ComplexType> > >(LU_);
300
301
302 norm_delta_z = NumErrorT(step_ref.template lpNorm<Eigen::Infinity>());
303 norm_J = NumErrorT(J_temp_ref.norm());
304 norm_J_inverse = NumErrorT(LU_ref.solve(RandomOfUnits<ComplexType>(S.NumVariables())).norm());
305 condition_number_estimate = NumErrorT(norm_J*norm_J_inverse);
306
307 if ( (norm_delta_z < tracking_tolerance) && (ii >= (min_num_newton_iterations-1)) )
308 return SuccessCode::Success;
309
310 if (!amp::CriterionB<ComplexType>(norm_J, norm_J_inverse, max_num_newton_iterations - ii, tracking_tolerance, norm_delta_z, AMP_config))
311 return SuccessCode::HigherPrecisionNecessary;
312
313 if (!amp::CriterionC<ComplexType>(norm_J_inverse, next_space, tracking_tolerance, AMP_config))
314 return SuccessCode::HigherPrecisionNecessary;
315 }
316
317 return SuccessCode::FailedToConverge;
318 }
319
320
321 private:
322
324 //
325 // Private Data Methods
326 //
328
329
339
340 template<typename ComplexType, typename Derived>
341 SuccessCode EvalIterationStep(Vec<ComplexType> & newton_step,
342 const System& S,
343 const Eigen::MatrixBase<Derived>& current_space, const ComplexType& current_time)
344 {
345 Vec<ComplexType>& f_temp_ref = std::get< Vec<ComplexType> >(f_temp_);
346 Mat<ComplexType>& J_temp_ref = std::get< Mat<ComplexType> >(J_temp_);
347
348 Eigen::PartialPivLU< Mat<ComplexType> >& LU_ref = std::get< Eigen::PartialPivLU< Mat<ComplexType> > >(LU_);
349
350 S.SetAndReset<ComplexType>(current_space, current_time);
351 S.EvalInPlace(f_temp_ref);
352 S.JacobianInPlace(J_temp_ref);
353 LU_ref = J_temp_ref.lu();
354
355 if (LUPartialPivotDecompositionSuccessful(LU_ref.matrixLU())!=MatrixSuccessCode::Success)
356 return SuccessCode::MatrixSolveFailure;
357
358 newton_step = LU_ref.solve(-f_temp_ref);
359
360 return SuccessCode::Success;
361
362 }
363
364
365
367 //
368 // Private Data Members
369 //
371
372 unsigned numTotalFunctions_; // Number of total functions for the current system
373 unsigned numVariables_; // Number of variables for the current system
374
375 std::tuple< Vec<dbl>, Vec<mpfr_complex> > f_temp_; // Variable to hold temporary evaluation of the system
376 std::tuple< Vec<dbl>, Vec<mpfr_complex> > step_temp_; // Variable to hold temporary evaluation of the newton step
377 std::tuple< Mat<dbl>, Mat<mpfr_complex> > J_temp_; // Variable to hold temporary evaluation of the Jacobian
378
379 std::tuple< Eigen::PartialPivLU<Mat<dbl>>, Eigen::PartialPivLU<Mat<mpfr_complex>> > LU_; // The LU factorization from the Newton iterates
380
381 unsigned current_precision_;
382
383 NewtonConfig newton_config_; // Hold the settings of the Newton iteration
384
385
386 }; //re: class NewtonCorrector
387
388 } //re: namespace correct
389 }// re: namespace tracking
390}// re: namespace bertini
391
392#endif
Provides the Adaptive Multiple Precision criteria functions.
bool CriterionC(double const &norm_J_inverse, const Eigen::MatrixBase< Derived > &z, double tracking_tolerance, AdaptiveMultiplePrecisionConfig const &AMP_config)
Check AMP Criterion C.
Definition amp_criteria.hpp:206
bool CriterionB(double const &norm_J, double const &norm_J_inverse, unsigned num_newton_iterations_remaining, double const &tracking_tolerance, double const &norm_of_latest_newton_residual, AdaptiveMultiplePrecisionConfig const &AMP_config)
Check AMP Criterion B.
Definition amp_criteria.hpp:132
The fundamental polynomial system class for Bertini2.
Definition system/system.hpp:99
void EvalInPlace(Vec< T > &function_values) const
Evaluate the system using the previously set variable (and time) values, in place.
Definition system/system.hpp:272
void JacobianInPlace(Mat< T > &J) const
Evaluate the Jacobian matrix of the system, using the previous space and time values,...
Definition system/system.hpp:470
size_t NumVariables() const
size_t NumTotalFunctions() const
void Settings(const NewtonConfig &newton_settings)
Sets the Newton configuration settings.
Definition newton_corrector.hpp:67
SuccessCode Correct(Vec< ComplexType > &next_space, System const &S, Vec< ComplexType > const &current_space, ComplexType const &current_time, NumErrorT const &tracking_tolerance, unsigned min_num_newton_iterations, unsigned max_num_newton_iterations, AdaptiveMultiplePrecisionConfig const &AMP_config)
Run Newton's method in multiple precision.
Definition newton_corrector.hpp:198
SuccessCode Correct(Vec< ComplexType > &next_space, System const &S, Vec< ComplexType > const &current_space, ComplexType const &current_time, NumErrorT const &tracking_tolerance, unsigned min_num_newton_iterations, unsigned max_num_newton_iterations)
Run Newton's method in fixed precision.
Definition newton_corrector.hpp:141
SuccessCode Correct(Vec< ComplexType > &next_space, NumErrorT &norm_delta_z, NumErrorT &norm_J, NumErrorT &norm_J_inverse, NumErrorT &condition_number_estimate, System const &S, Vec< ComplexType > const &current_space, ComplexType const &current_time, NumErrorT const &tracking_tolerance, unsigned min_num_newton_iterations, unsigned max_num_newton_iterations, AdaptiveMultiplePrecisionConfig const &AMP_config)
Run Newton's method in multiple precision.
Definition newton_corrector.hpp:269
void ChangeSystem(const System &S)
Change the system(number of total functions) that the predictor uses.
Definition newton_corrector.hpp:105
void ChangePrecision(unsigned new_precision)
Definition newton_corrector.hpp:82
Mat< NumberType > RandomOfUnits(uint rows, uint cols)
Make a random matrix of units (numbers with norm 1).
Definition eigen_extensions.hpp:502
MatrixSuccessCode LUPartialPivotDecompositionSuccessful(Eigen::MatrixBase< Derived > const &LU)
Check the diagonal elements of an LU decomposition for small values and large ratios.
Definition eigen_extensions.hpp:417
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
Definition trackers/config.hpp:154
Provides the bertini::System class.
Configs and settings for tracking.