36 m_Gradient(num_variables), m_PreConditioner(num_variables),
94 real_t gnorm_start = gnorm;
97 if(!std::isfinite(f) || !std::isfinite(gnorm) || !std::isfinite(gnorm0)) {
98 spdlog::error(
"Invalid newton optimization: initial value: {}, gradient norm: {}, gnorm_0: {}", f, gnorm, gnorm0);
103 m_Logger->info(
"initial: f={:<5.3} |g|={:<5.3} |g_0|={:<5.3} eps={:<5.3}", f, gnorm, gnorm0,
m_Epsilon);
109 for(
int iter = 1; iter <=
m_MaxIter; ++iter) {
128 if (ls_result.StepSize == 0)
130 spdlog::warn(
"line search failed in iteration {} of newton optimization. Current objective value: {:.3}, "
131 "gradient norm: {:.3} (target: {:.3}), squared search dir: {:.3}",
132 iter, f, gnorm,
m_Epsilon * gnorm0, cg_solution.squaredNorm());
139 real_t absolute_improvement = fold - f;
155 spdlog::warn(
"Objective appears to be unbounded (got value {:.2})", f);
158 if (abs(absolute_improvement) <= 1.0e-12 * abs(f))
160 spdlog::warn(
"relative improvement too low");
181 m_Logger->info(
"iter {:3}: f={:<10.8} |g|={:<8.4} CG={:<3} line-search={:<4.2}",
188 spdlog::error(
"Non-positive epsilon {} specified for newton minimization", eps);
189 throw std::invalid_argument(
"Epsilon must be larger than zero.");
196 spdlog::error(
"Non-positive iteration limit {} specified for newton minimization", max_iter);
197 throw std::invalid_argument(
"maximum iterations must be larger than zero.");
203 if(alpha <= 0 || alpha >= 1) {
204 spdlog::error(
"The `alpha_pcg` parameter needs to be between 0 and 1, got {} ", alpha);
205 throw std::invalid_argument(
"alpha_pcg not in (0, 1)");
211 #include <Eigen/Dense>
220 CHECK(nwls.get_epsilon() == 0.1);
222 nwls.set_maximum_iterations(500);
223 CHECK(nwls.get_maximum_iterations() == 500);
225 nwls.set_alpha_preconditioner(0.4);
226 CHECK(nwls.get_alpha_preconditioner() == 0.4);
229 CHECK_THROWS(nwls.set_epsilon(-0.4));
230 CHECK_THROWS(nwls.set_maximum_iterations(0));
231 CHECK_THROWS(nwls.set_alpha_preconditioner(-0.1));
232 CHECK_THROWS(nwls.set_alpha_preconditioner(1.1));
235 nwls.set_hyper_parameter(
"epsilon", 0.25);
236 CHECK( std::get<double>(nwls.get_hyper_parameter(
"epsilon")) == 0.25);
237 nwls.set_hyper_parameter(
"max-steps", 50l);
238 CHECK( std::get<long>(nwls.get_hyper_parameter(
"max-steps")) == 50);
239 nwls.set_hyper_parameter(
"alpha-pcg", 0.3);
240 CHECK( std::get<double>(nwls.get_hyper_parameter(
"alpha-pcg")) == 0.3);
245 QuadraticObjective(types::DenseColMajor<real_t> m,
DenseRealVector s) : A(std::move(m)), b(std::move(s)),
246 m_LocCache(A.row(0)){}
248 [[nodiscard]]
long num_variables()
const noexcept
override {
253 return location->dot(A * location) + location->dot(b);
255 void gradient_unchecked(
const HashVector& location, Eigen::Ref<DenseRealVector> target)
override {
256 target= 2 * A * location + b;
259 Eigen::Ref<DenseRealVector> target)
override
261 target = 2 * A * direction;
265 m_DirCache = direction;
266 m_LocCache = location;
269 return value(
HashVector{m_LocCache + m_DirCache * position});
272 types::DenseColMajor<real_t> A;
278 types::DenseColMajor<real_t> mat(4, 4);
279 mat << 1.0, 1.0, 0.0, 0.0,
284 mat = (mat.transpose() * mat).eval();
287 vec << 1.0, 2.0, 0.0, -2.0;
297 for(
int i = 0; i < w.size(); ++i) {
298 CHECK(w.coeff(i) == doctest::Approx(direct.coeff(i)));
An Eigen vector with versioning information, to implement simple caching of results.
const DenseRealVector & get() const
Gets a constant reference to the data of this vector.
void declare_hyper_parameter(std::string name, U S::*pointer)
void declare_sub_object(const std::string &name, T S::*object)
Declares a sub-object that also contains hyper-parameters.
Class that models an optimization objective.
An integer-like type that represents categorical values.
sLineSearchResult search(const std::function< double(double)> &projected_objective, double gTs, double f_init) const
const DenseRealVector & get_solution() const
returns the solution vector found by the last minimize call
long minimize(const MatrixVectorProductFn &A, const DenseRealVector &b, const DenseRealVector &M)
Solves Ax+b=0. returns the number of iterations.
MinimizationResult minimize(objective::Objective &objective, Eigen::Ref< DenseRealVector > init)
std::shared_ptr< spdlog::logger > m_Logger
DenseRealVector m_PreConditioner
double get_epsilon() const
BacktrackingLineSearch m_LineSearcher
long get_maximum_iterations() const
void record_iteration(int iter, int cg_iter, real_t gnorm, real_t objective, const sLineSearchResult &step, real_t gnorm0)
void set_maximum_iterations(long max_iter)
double get_alpha_preconditioner() const
MinimizationResult run(objective::Objective &objective, Eigen::Ref< DenseRealVector > init) override
NewtonWithLineSearch(long num_variables)
DenseRealVector m_Gradient
void set_epsilon(double eps)
void set_alpha_preconditioner(double alpha)
void declare_tag(tag_id_t index, std::string name)
Declares a new tag. This function just forwards all its arguments to the internal StatisticsCollectio...
void record(stat_id_t stat, T &&value)
Record statistics. This function just forwards all its arguments to the internal StatisticsCollection...
auto make_timer(stat_id_t id, Args... args)
Creates a new ScopeTimer using stats::record_scope_time.
void declare_stat(stat_id_t index, StatisticMetaData meta)
Declares a new statistics. This function just forwards all its arguments to the internal StatisticsCo...
void set_tag(tag_id_t tag, long value)
Set value of tag. This function just forwards all its arguments to the internal StatisticsCollection.
constexpr const stat_id_t STAT_PROGRESS
constexpr const stat_id_t STAT_WEIGHT_VECTOR
constexpr const stat_id_t STAT_ABSOLUTE_STEP
constexpr const stat_id_t STAT_GRADIENT
constexpr const stat_id_t STAT_PRECONDITIONER
constexpr const stat_id_t STAT_ITER_TIME
constexpr const stat_id_t STAT_OBJECTIVE_VALUE
constexpr const stat_id_t STAT_GRADIENT_NORM
constexpr const stat_id_t STAT_CG_ITERS
constexpr const stat_id_t STAT_GRADIENT_NORM_0
constexpr const dismec::stats::tag_id_t TAG_ITERATION
constexpr const stat_id_t STAT_LINESEARCH_STEPSIZE
constexpr const stat_id_t STAT_LS_STEPS
constexpr const stat_id_t STAT_LS_FAIL
@ FAILED
Some internal operation failed.
@ DIVERGED
The optimization objective appears to be unbounded.
@ SUCCESS
The returned result is a minimum according to the stopping criterion of the algorithm.
@ TIMED_OUT
The maximum number of iterations has been reached but no minimum has been found.
opaque_int_type< detail::stat_id_tag > stat_id_t
An opaque int-like type that is used to identify a statistic in a StatisticsCollection.
Main namespace in which all types, classes, and functions are defined.
types::DenseVector< real_t > DenseRealVector
Any dense, real values vector.
float real_t
The default type for floating point values.
TEST_CASE("newton with line search hyperparameters")
Result of a Line Search operation.
double StepSize
The step size used to reach that position.