123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 |
- #ifndef LBFGS_HPP
- #define LBFGS_HPP
- #include <Eigen/Eigen>
- #include <cmath>
- #include <algorithm>
- #include <time.h>
- #include <chrono>
- namespace lbfgs
- {
- // ----------------------- Data Type Part -----------------------
- /**
- * L-BFGS optimization parameters.
- */
- struct lbfgs_parameter_t
- {
- /**
- * The number of corrections to approximate the inverse hessian matrix.
- * The L-BFGS routine stores the computation results of previous m
- * iterations to approximate the inverse hessian matrix of the current
- * iteration. This parameter controls the size of the limited memories
- * (corrections). The default value is 8. Values less than 3 are
- * not recommended. Large values will result in excessive computing time.
- */
- int mem_size = 8;
- /**
- * Epsilon for grad convergence test. DO NOT USE IT in nonsmooth cases!
- * Set it to 0.0 and use past-delta-based test for nonsmooth functions.
- * This parameter determines the accuracy with which the solution is to
- * be found. A minimization terminates when
- * ||g(x)||_inf / max(1, ||x||_inf) < g_epsilon,
- * where ||.||_inf is the infinity norm. The default value is 0.0.
- * This should be greater than 1.0e-6 in practice because L-BFGS does
- * not directly reduce first-order residual. It still needs the function
- * value which can be corrupted by machine_prec when ||g|| is small.
- */
- double g_epsilon = 0.0;
- /**
- * Distance for delta-based convergence test.
- * This parameter determines the distance, in iterations, to compute
- * the rate of decrease of the cost function. If the value of this
- * parameter is zero, the library does not perform the delta-based
- * convergence test. The default value is 3.
- */
- int past = 3;
- /**
- * Delta for convergence test.
- * This parameter determines the minimum rate of decrease of the
- * cost function. The library stops iterations when the following
- * condition is met:
- * |f' - f| / max(1, |f|) < delta,
- * where f' is the cost value of past iterations ago, and f is
- * the cost value of the current iteration.
- * The default value is 1.0e-6.
- */
- double delta = 1.0e-6;
- /**
- * The maximum number of iterations.
- * The lbfgs_optimize() function terminates an minimization process with
- * ::LBFGSERR_MAXIMUMITERATION status code when the iteration count
- * exceedes this parameter. Setting this parameter to zero continues an
- * minimization process until a convergence or error. The default value
- * is 0.
- */
- int max_iterations = 0;
- /**
- * The maximum number of trials for the line search.
- * This parameter controls the number of function and gradients evaluations
- * per iteration for the line search routine. The default value is 64.
- */
- int max_linesearch = 64;
- /**
- * The minimum step of the line search routine.
- * The default value is 1.0e-20. This value need not be modified unless
- * the exponents are too large for the machine being used, or unless the
- * problem is extremely badly scaled (in which case the exponents should
- * be increased).
- */
- double min_step = 1.0e-20;
- /**
- * The maximum step of the line search.
- * The default value is 1.0e+20. This value need not be modified unless
- * the exponents are too large for the machine being used, or unless the
- * problem is extremely badly scaled (in which case the exponents should
- * be increased).
- */
- double max_step = 1.0e+20;
- /**
- * A parameter to control the accuracy of the line search routine.
- * The default value is 1.0e-4. This parameter should be greater
- * than zero and smaller than 1.0.
- */
- double f_dec_coeff = 1.0e-4;
- /**
- * A parameter to control the accuracy of the line search routine.
- * The default value is 0.9. If the function and gradient
- * evaluations are inexpensive with respect to the cost of the
- * iteration (which is sometimes the case when solving very large
- * problems) it may be advantageous to set this parameter to a small
- * value. A typical small value is 0.1. This parameter should be
- * greater than the f_dec_coeff parameter and smaller than 1.0.
- */
- double s_curv_coeff = 0.9;
- /**
- * A parameter to ensure the global convergence for nonconvex functions.
- * The default value is 1.0e-6. The parameter performs the so called
- * cautious update for L-BFGS, especially when the convergence is
- * not sufficient. The parameter must be positive but might as well
- * be less than 1.0e-3 in practice.
- */
- double cautious_factor = 1.0e-6;
- /**
- * The machine precision for floating-point values. The default is 1.0e-16.
- * This parameter must be a positive value set by a client program to
- * estimate the machine precision.
- */
- double machine_prec = 1.0e-16;
- };
- /**
- * Return values of lbfgs_optimize().
- * Roughly speaking, a negative value indicates an error.
- */
- enum
- {
- /** L-BFGS reaches convergence. */
- LBFGS_CONVERGENCE = 0,
- /** L-BFGS satisfies stopping criteria. */
- LBFGS_STOP,
- /** The iteration has been canceled by the monitor callback. */
- LBFGS_CANCELED,
- /** Unknown error. */
- LBFGSERR_UNKNOWNERROR = -1024,
- /** Invalid number of variables specified. */
- LBFGSERR_INVALID_N,
- /** Invalid parameter lbfgs_parameter_t::mem_size specified. */
- LBFGSERR_INVALID_MEMSIZE,
- /** Invalid parameter lbfgs_parameter_t::g_epsilon specified. */
- LBFGSERR_INVALID_GEPSILON,
- /** Invalid parameter lbfgs_parameter_t::past specified. */
- LBFGSERR_INVALID_TESTPERIOD,
- /** Invalid parameter lbfgs_parameter_t::delta specified. */
- LBFGSERR_INVALID_DELTA,
- /** Invalid parameter lbfgs_parameter_t::min_step specified. */
- LBFGSERR_INVALID_MINSTEP,
- /** Invalid parameter lbfgs_parameter_t::max_step specified. */
- LBFGSERR_INVALID_MAXSTEP,
- /** Invalid parameter lbfgs_parameter_t::f_dec_coeff specified. */
- LBFGSERR_INVALID_FDECCOEFF,
- /** Invalid parameter lbfgs_parameter_t::s_curv_coeff specified. */
- LBFGSERR_INVALID_SCURVCOEFF,
- /** Invalid parameter lbfgs_parameter_t::machine_prec specified. */
- LBFGSERR_INVALID_MACHINEPREC,
- /** Invalid parameter lbfgs_parameter_t::max_linesearch specified. */
- LBFGSERR_INVALID_MAXLINESEARCH,
- /** The function value became NaN or Inf. */
- LBFGSERR_INVALID_FUNCVAL,
- /** The line-search step became smaller than lbfgs_parameter_t::min_step. */
- LBFGSERR_MINIMUMSTEP,
- /** The line-search step became larger than lbfgs_parameter_t::max_step. */
- LBFGSERR_MAXIMUMSTEP,
- /** Line search reaches the maximum, assumptions not satisfied or precision not achievable.*/
- /* 线搜索达到最大值,不满足假设或无法达到精度。 */
- LBFGSERR_MAXIMUMLINESEARCH,
- /** The algorithm routine reaches the maximum number of iterations. */
- LBFGSERR_MAXIMUMITERATION,
- /** Relative search interval width is at least lbfgs_parameter_t::machine_prec. */
- LBFGSERR_WIDTHTOOSMALL,
- /** A logic error (negative line-search step) occurred. */
- LBFGSERR_INVALIDPARAMETERS,
- /** The current search direction increases the cost function value. */
- LBFGSERR_INCREASEGRADIENT,
- };
- /**
- * Callback interface to provide cost function and gradient evaluations.
- *
- * The lbfgs_optimize() function call this function to obtain the values of cost
- * function and its gradients when needed. A client program must implement
- * this function to evaluate the values of the cost function and its
- * gradients, given current values of variables.
- *
- * @param instance The user data sent for lbfgs_optimize() function by the client.
- * @param x The current values of variables.
- * @param g The gradient vector. The callback function must compute
- * the gradient values for the current variables.
- * @retval double The value of the cost function for the current variables.
- */
- typedef double (*lbfgs_evaluate_t)(void *instance,
- const Eigen::VectorXd &x,
- Eigen::VectorXd &g);
- /**
- * Callback interface to monitor the progress of the minimization process.
- *
- * The lbfgs_optimize() function call this function for each iteration. Implementing
- * this function, a client program can store or display the current progress
- * of the minimization process. If it is not used, just set it nullptr.
- *
- * @param instance The user data sent for lbfgs_optimize() function by the client.
- * @param x The current values of variables.
- * @param g The current gradient values of variables.
- * @param fx The current value of the cost function.
- * @param step The line-search step used for this iteration.
- * @param k The iteration count.
- * @param ls The number of evaluations called for this iteration.
- * @retval int Zero to continue the minimization process. Returning a
- * non-zero value will cancel the minimization process.
- */
- typedef int (*lbfgs_progress_t)(void *instance,
- const Eigen::VectorXd &x,
- const Eigen::VectorXd &g,
- const double fx,
- const double step,
- const int k,
- const int ls);
- /**
- * Callback data struct
- */
- struct callback_data_t
- {
- void *instance = nullptr;
- lbfgs_evaluate_t proc_evaluate = nullptr;
- lbfgs_progress_t proc_progress = nullptr;
- };
- // ----------------------- L-BFGS Part -----------------------
- /**
- * Line search method for smooth or nonsmooth functions.
- * This function performs line search to find a point that satisfy
- * both the Armijo condition and the weak Wolfe condition. It is
- * as robust as the backtracking line search but further applies
- * to continuous and piecewise smooth functions where the strong
- * Wolfe condition usually does not hold.
- *
- * @see
- * Adrian S. Lewis and Michael L. Overton. Nonsmooth optimization
- * via quasi-Newton methods. Mathematical Programming, Vol 141,
- * No 1, pp. 135-163, 2013.
- */
- inline int line_search_lewisoverton(Eigen::VectorXd &x,
- double &f,
- Eigen::VectorXd &g,
- double &stp,
- const Eigen::VectorXd &s,
- const Eigen::VectorXd &xp,
- const Eigen::VectorXd &gp,
- const double stpmin,
- const double stpmax,
- const callback_data_t &cd,
- const lbfgs_parameter_t ¶m)
- {
- // x is the decision variable vector
- // f is function value at x
- // g is the gradient value at x
- // stp is the initial stepsize for line search
- // s is the search direction vector
- // xp is the decision variable vector at the current iteration
- // gp is the gradient vector at the current iteration
- // stpmin is the minimum allowable stepsize
- // stpmax is the maximum allowable stepsize
- // the struct param contains all necessary parameters
- // the cd contains all necessary callback function
- // x 是决策变量向量
- // f 是 x 处的函数值
- // g 是 x 处的梯度值
- // stp 是线搜索的初始步长
- // s 是搜索方向向量
- // xp 是当前迭代的决策变量向量
- // gp 是当前迭代的梯度向量
- // stpmin 是允许的最小步长
- // stpmax 是最大允许步长
- // struct param 包含所有必需的参数
- // cd 包含所有必需的回调函数
- // eg. x = xp; f = cd.proc_evaluate(cd.instance, x, g);
- // the above line assigns x with xp and computes the function and grad at x
- // 上面的行将 x 指定为 xp 并计算 x 处的函数和梯度
- // note the output x, f and g which satisfy the weak wolfe condition when the function returns
- // 注意函数返回时满足弱沃尔夫条件的输出 x、f 和 g
- //////////////////////////// HOMEWORK 1 START ////////////////////////////
- // PUT YOUR CODE FOR Lewis-Overton line search here
- int linesearch_cnt = 0; // 线搜索计次
- double step_l = 0.0; // l
- double step_u = stpmax; // u
- const double fp = cd.proc_evaluate(cd.instance, xp, g); // 当前 x 处的代价值
- const double d_delta = gp.dot(s); // 点积
- while (linesearch_cnt < param.max_linesearch)
- {
- ++linesearch_cnt;
- // std::cout << "xp = " << std::endl
- // << xp << std::endl;
- // std::cout << "stp = " << stp << std::endl;
- // std::cout << "s = " << std::endl
- // << s << std::endl;
- x = xp + stp * s; // 按照方向 x 和 步长 step 搜索得到的下一组决策变量
- // std::cout << "x = " << std::endl
- // << x << std::endl;
- if (x.minCoeff() < 0)
- {
- // std::cout << "x < 0 =======" << std::endl;
- x = xp;
- // continue;
- }
- f = cd.proc_evaluate(cd.instance, x, g); // 下一组决策变量的代价值
- if (f > fp + param.f_dec_coeff * stp * d_delta)
- stp = stp / 2;
- else
- return linesearch_cnt;
- if (stp < 0.6)
- return linesearch_cnt; // 返回线搜索次数
- }
- return LBFGSERR_MAXIMUMLINESEARCH; // -1009 是这里return的
- //////////////////////////// HOMEWORK 1 END ////////////////////////////
- }
- /**
- * Start a L-BFGS optimization.
- * Assumptions: 1. f(x) is either C2 or C0 but piecewise C2;
- * 2. f(x) is lower bounded;
- * 3. f(x) has bounded level sets;
- * 4. g(x) is either the gradient or subgradient;
- * 5. The gradient exists at the initial guess x0.
- * A user must implement a function compatible with ::lbfgs_evaluate_t (evaluation
- * callback) and pass the pointer to the callback function to lbfgs_optimize()
- * arguments. Similarly, a user can implement a function compatible with
- * ::lbfgs_progress_t (progress callback) to obtain the current progress
- * (e.g., variables, function, and gradient, etc) and to cancel the iteration
- * process if necessary. Implementation of the stepbound and the progress callback
- * is optional: a user can pass nullptr if progress notification is not necessary.
- *
- *
- * @param x The vector of decision variables.
- * THE INITIAL GUESS x0 SHOULD BE SET BEFORE THE CALL!
- * A client program can receive decision variables
- * through this vector, at which the cost and its
- * gradient are queried during minimization.
- * @param f The ref to the variable that receives the final
- * value of the cost function for the variables.
- * @param proc_evaluate The callback function to provide function f(x) and
- * gradient g(x) evaluations given a current values of
- * variables x. A client program must implement a
- * callback function compatible with lbfgs_evaluate_t
- * and pass the pointer to the callback function.
- * @param proc_stepbound The callback function to provide values of the
- * upperbound of the stepsize to search in, provided
- * with the beginning values of variables before the
- * line search, and the current step vector (can be
- * negative gradient). A client program can implement
- * this function for more efficient linesearch. If it is
- * not used, just set it nullptr.
- * @param proc_progress The callback function to receive the progress
- * (the number of iterations, the current value of
- * the cost function) of the minimization
- * process. This argument can be set to nullptr if
- * a progress report is unnecessary.
- * @param instance A user data pointer for client programs. The callback
- * functions will receive the value of this argument.
- * @param param The parameters for L-BFGS optimization.
- * @retval int The status code. This function returns a nonnegative
- * integer if the minimization process terminates without
- * an error. A negative integer indicates an error.
- */
- inline int lbfgs_optimize(Eigen::VectorXd &x, // 决策变量
- double &f, // 最小代价值
- lbfgs_evaluate_t proc_evaluate, // 代价函数
- lbfgs_progress_t proc_progress, // 空
- void *instance, // this
- const lbfgs_parameter_t ¶m) // 参数
- {
- int ret, i, j, k, ls, end, bound;
- double step, step_min, step_max, fx, ys, yy;
- double gnorm_inf, xnorm_inf, beta, rate, cau;
- const int n = x.size();
- const int m = param.mem_size;
- /* Check the input parameters for errors. */
- if (n <= 0)
- {
- return LBFGSERR_INVALID_N;
- }
- if (m <= 0)
- {
- return LBFGSERR_INVALID_MEMSIZE;
- }
- if (param.g_epsilon < 0.0)
- {
- return LBFGSERR_INVALID_GEPSILON;
- }
- if (param.past < 0)
- {
- return LBFGSERR_INVALID_TESTPERIOD;
- }
- if (param.delta < 0.0)
- {
- return LBFGSERR_INVALID_DELTA;
- }
- if (param.min_step < 0.0)
- {
- return LBFGSERR_INVALID_MINSTEP;
- }
- if (param.max_step < param.min_step)
- {
- return LBFGSERR_INVALID_MAXSTEP;
- }
- if (!(param.f_dec_coeff > 0.0 &&
- param.f_dec_coeff < 1.0))
- {
- return LBFGSERR_INVALID_FDECCOEFF;
- }
- if (!(param.s_curv_coeff < 1.0 &&
- param.s_curv_coeff > param.f_dec_coeff))
- {
- return LBFGSERR_INVALID_SCURVCOEFF;
- }
- if (!(param.machine_prec > 0.0))
- {
- return LBFGSERR_INVALID_MACHINEPREC;
- }
- if (param.max_linesearch <= 0)
- {
- return LBFGSERR_INVALID_MAXLINESEARCH;
- }
- /* Prepare intermediate variables. */
- Eigen::VectorXd xp(n);
- Eigen::VectorXd g(n);
- Eigen::VectorXd gp(n);
- Eigen::VectorXd d(n);
- Eigen::VectorXd pf(std::max(1, param.past));
- /* Initialize the limited memory. */
- Eigen::VectorXd lm_alpha = Eigen::VectorXd::Zero(m);
- Eigen::MatrixXd lm_s = Eigen::MatrixXd::Zero(n, m);
- Eigen::MatrixXd lm_y = Eigen::MatrixXd::Zero(n, m);
- Eigen::VectorXd lm_ys = Eigen::VectorXd::Zero(m);
- /* Construct a callback data. */
- callback_data_t cd;
- cd.instance = instance;
- cd.proc_evaluate = proc_evaluate;
- cd.proc_progress = proc_progress;
- /* Evaluate the function value and its gradient. */
- fx = cd.proc_evaluate(cd.instance, x, g);
- /* Store the initial value of the cost function. */
- pf(0) = fx;
- /*
- Compute the direction;
- we assume the initial hessian matrix H_0 as the identity matrix.
- */
- d = -g;
- /*
- Make sure that the initial variables are not a stationary point.
- */
- gnorm_inf = g.cwiseAbs().maxCoeff();
- xnorm_inf = x.cwiseAbs().maxCoeff();
- if (gnorm_inf / std::max(1.0, xnorm_inf) < param.g_epsilon)
- {
- /* The initial guess is already a stationary point. */
- ret = LBFGS_CONVERGENCE;
- }
- else
- {
- /*
- Compute the initial step:
- */
- step = 1.0 / d.norm();
- k = 1;
- end = 0;
- bound = 0;
- auto LBFGS_start = std::chrono::high_resolution_clock::now();
- auto LBFGS_NOW = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> LBFGS_duration;
- while (true)
- {
- LBFGS_NOW = std::chrono::high_resolution_clock::now();
- LBFGS_duration = LBFGS_NOW - LBFGS_start;
- if(LBFGS_duration.count() > 30){ // 自己加的 效果好像ok喔,小论文这个就不写了,大论文感觉可以提一下
- ret = 95432;
- break; // 直接暴力解决了有时候求解时间特别长的问题!
- }
- /* Store the current position and gradient vectors. */
- xp = x;
- gp = g;
- /* If the step bound can be provied dynamically, then apply it. */
- step_min = param.min_step;
- step_max = param.max_step;
- /* Search for an optimal step. */
- // ls = line_search_lewisoverton(x, fx, g, step, d, xp, gp, step_min, step_max, cd, param);
- // auto start_time = std::chrono::high_resolution_clock::now();
- ls = line_search_lewisoverton(x, fx, g, step, d, xp, gp, step_min, step_max, cd, param);
- // auto end_time = std::chrono::high_resolution_clock::now();
- // auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
- // std::cout << ls << " ";
- // if (ls != 1)
- // ROS_INFO("Slept for %lld microseconds, line_search_times = %d", duration.count(), ls);
- if (ls < 0)
- {
- /* Revert to the previous point. */
- x = xp;
- g = gp;
- ret = ls;
- break;
- }
- /* Report the progress. */
- if (cd.proc_progress)
- {
- if (cd.proc_progress(cd.instance, x, g, fx, step, k, ls))
- {
- ret = LBFGS_CANCELED;
- break;
- }
- }
- /*
- Convergence test.
- The criterion is given by the following formula:
- ||g(x)||_inf / max(1, ||x||_inf) < g_epsilon
- */
- gnorm_inf = g.cwiseAbs().maxCoeff();
- xnorm_inf = x.cwiseAbs().maxCoeff();
- if (gnorm_inf / std::max(1.0, xnorm_inf) < param.g_epsilon)
- {
- /* Convergence. */
- ret = LBFGS_CONVERGENCE;
- break;
- }
- /*
- Test for stopping criterion.
- The criterion is given by the following formula:
- |f(past_x) - f(x)| / max(1, |f(x)|) < \delta.
- */
- if (0 < param.past)
- {
- /* We don't test the stopping criterion while k < past. */
- if (param.past <= k)
- {
- /* The stopping criterion. */
- rate = std::fabs(pf(k % param.past) - fx) / std::max(1.0, std::fabs(fx));
- if (rate < param.delta)
- {
- ret = LBFGS_STOP;
- break;
- }
- }
- /* Store the current value of the cost function. */
- pf(k % param.past) = fx;
- }
- if (param.max_iterations != 0 && param.max_iterations <= k)
- {
- /* Maximum number of iterations. */
- ret = LBFGSERR_MAXIMUMITERATION;
- break;
- }
- /* Count the iteration number. */
- ++k;
- // std::cout << "k = " << k << std::endl;
- /*
- Update vectors s and y:
- s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}.
- y_{k+1} = g_{k+1} - g_{k}.
- */
- lm_s.col(end) = x - xp;
- lm_y.col(end) = g - gp;
- /*
- Compute scalars ys and yy:
- ys = y^t \cdot s = 1 / \rho.
- yy = y^t \cdot y.
- Notice that yy is used for scaling the hessian matrix H_0 (Cholesky factor).
- */
- ys = lm_y.col(end).dot(lm_s.col(end));
- yy = lm_y.col(end).squaredNorm();
- lm_ys(end) = ys;
- /* Compute the negative of gradients. */
- d = -g;
- /*
- Only cautious update is performed here as long as
- (y^t \cdot s) / ||s_{k+1}||^2 > \epsilon * ||g_{k}||^\alpha,
- where \epsilon is the cautious factor and a proposed value
- for \alpha is 1.
- This is not for enforcing the PD of the approxomated Hessian
- since ys > 0 is already ensured by the weak Wolfe condition.
- This is to ensure the global convergence as described in:
- Dong-Hui Li and Masao Fukushima. On the global convergence of
- the BFGS method for nonconvex unconstrained optimization problems.
- SIAM Journal on Optimization, Vol 11, No 4, pp. 1054-1064, 2011.
- */
- cau = lm_s.col(end).squaredNorm() * gp.norm() * param.cautious_factor;
- if (ys > cau)
- {
- /*
- Recursive formula to compute dir = -(H \cdot g).
- This is described in page 779 of:
- Jorge Nocedal.
- Updating Quasi-Newton Matrices with Limited Storage.
- Mathematics of Computation, Vol. 35, No. 151,
- pp. 773--782, 1980.
- */
- ++bound;
- bound = m < bound ? m : bound;
- end = (end + 1) % m;
- j = end;
- for (i = 0; i < bound; ++i)
- {
- j = (j + m - 1) % m; /* if (--j == -1) j = m-1; */
- /* \alpha_{j} = \rho_{j} s^{t}_{j} \cdot q_{k+1}. */
- lm_alpha(j) = lm_s.col(j).dot(d) / lm_ys(j);
- /* q_{i} = q_{i+1} - \alpha_{i} y_{i}. */
- d += (-lm_alpha(j)) * lm_y.col(j);
- }
- d *= ys / yy;
- for (i = 0; i < bound; ++i)
- {
- /* \beta_{j} = \rho_{j} y^t_{j} \cdot \gamm_{i}. */
- beta = lm_y.col(j).dot(d) / lm_ys(j);
- /* \gamm_{i+1} = \gamm_{i} + (\alpha_{j} - \beta_{j}) s_{j}. */
- d += (lm_alpha(j) - beta) * lm_s.col(j);
- j = (j + 1) % m; /* if (++j == m) j = 0; */
- }
- }
- /* The search direction d is ready. We try step = 1 first. */
- step = 1.0;
- }
- int asdfd = 0;
- }
- /* Return the final value of the cost function. */
- f = fx;
- return ret;
- }
- /**
- * Get string description of an lbfgs_optimize() return code.
- *
- * @param err A value returned by lbfgs_optimize().
- */
- inline const char *lbfgs_strerror(const int err)
- {
- switch (err)
- {
- case LBFGS_CONVERGENCE:
- return "Success: reached convergence (g_epsilon).";
- case LBFGS_STOP:
- return "Success: met stopping criteria (past f decrease less than delta).";
- case LBFGS_CANCELED:
- return "The iteration has been canceled by the monitor callback.";
- case LBFGSERR_UNKNOWNERROR:
- return "Unknown error.";
- case LBFGSERR_INVALID_N:
- return "Invalid number of variables specified.";
- case LBFGSERR_INVALID_MEMSIZE:
- return "Invalid parameter lbfgs_parameter_t::mem_size specified.";
- case LBFGSERR_INVALID_GEPSILON:
- return "Invalid parameter lbfgs_parameter_t::g_epsilon specified.";
- case LBFGSERR_INVALID_TESTPERIOD:
- return "Invalid parameter lbfgs_parameter_t::past specified.";
- case LBFGSERR_INVALID_DELTA:
- return "Invalid parameter lbfgs_parameter_t::delta specified.";
- case LBFGSERR_INVALID_MINSTEP:
- return "Invalid parameter lbfgs_parameter_t::min_step specified.";
- case LBFGSERR_INVALID_MAXSTEP:
- return "Invalid parameter lbfgs_parameter_t::max_step specified.";
- case LBFGSERR_INVALID_FDECCOEFF:
- return "Invalid parameter lbfgs_parameter_t::f_dec_coeff specified.";
- case LBFGSERR_INVALID_SCURVCOEFF:
- return "Invalid parameter lbfgs_parameter_t::s_curv_coeff specified.";
- case LBFGSERR_INVALID_MACHINEPREC:
- return "Invalid parameter lbfgs_parameter_t::machine_prec specified.";
- case LBFGSERR_INVALID_MAXLINESEARCH:
- return "Invalid parameter lbfgs_parameter_t::max_linesearch specified.";
- case LBFGSERR_INVALID_FUNCVAL:
- return "The function value became NaN or Inf.";
- case LBFGSERR_MINIMUMSTEP:
- return "The line-search step became smaller than lbfgs_parameter_t::min_step.";
- case LBFGSERR_MAXIMUMSTEP:
- return "The line-search step became larger than lbfgs_parameter_t::max_step.";
- case LBFGSERR_MAXIMUMLINESEARCH:
- return "Line search reaches the maximum try number, assumptions not satisfied or precision not achievable.";
- case LBFGSERR_MAXIMUMITERATION:
- return "The algorithm routine reaches the maximum number of iterations.";
- case LBFGSERR_WIDTHTOOSMALL:
- return "Relative search interval width is at least lbfgs_parameter_t::machine_prec.";
- case LBFGSERR_INVALIDPARAMETERS:
- return "A logic error (negative line-search step) occurred.";
- case LBFGSERR_INCREASEGRADIENT:
- return "The current search direction increases the cost function value.";
- default:
- return "(unknown)";
- }
- }
- } // namespace lbfgs
- #endif
|