4#ifndef LBFGSPP_CAUCHY_H
5#define LBFGSPP_CAUCHY_H
31template <
typename Scalar>
35 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
36 using IndexSet = std::vector<int>;
41 ArgSort(
const Vector& value_vec) :
42 values(value_vec.data())
45 inline bool operator()(
int key1,
int key2) {
return values[key1] < values[key2]; }
46 inline void sort_key(IndexSet& key_vec)
const
48 std::sort(key_vec.begin(), key_vec.end(), *
this);
52template <
typename Scalar>
56 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;
57 typedef Eigen::Matrix<int, Eigen::Dynamic, 1> IntVector;
58 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
59 typedef std::vector<int> IndexSet;
63 static int search_greater(
const Vector& brk,
const IndexSet& ord,
const Scalar& t,
int start = 0)
65 const int nord = ord.size();
67 for (i = start; i < nord; i++)
86 static void get_cauchy_point(
87 const BFGSMat<Scalar, true>& bfgs,
const Vector& x0,
const Vector& g,
const Vector& lb,
const Vector& ub,
88 Vector& xcp, Vector& vecc, IndexSet& newact_set, IndexSet& fv_set)
93 const int n = x0.size();
96 vecc.resize(2 * bfgs.num_corrections());
99 newact_set.reserve(n);
104 Vector brk(n), vecd(n);
110 const Scalar inf = std::numeric_limits<Scalar>::infinity();
111 for (
int i = 0; i < n; i++)
115 else if (g[i] < Scalar(0))
116 brk[i] = (x0[i] - ub[i]) / g[i];
117 else if (g[i] > Scalar(0))
118 brk[i] = (x0[i] - lb[i]) / g[i];
122 const bool iszero = (brk[i] == Scalar(0));
123 vecd[i] = iszero ? Scalar(0) : -g[i];
132 ArgSort<Scalar> sorting(brk);
133 sorting.sort_key(ord);
138 const int nord = ord.size();
139 const int nfree = fv_set.size();
140 if ((nfree < 1) && (nord < 1))
152 bfgs.apply_Wtv(vecd, vecp);
154 Scalar fp = -vecd.squaredNorm();
157 bfgs.apply_Mv(vecp, cache);
158 Scalar fpp = -bfgs.theta() * fp - vecp.dot(cache);
161 Scalar deltatmin = -fp / fpp;
164 Scalar il = Scalar(0);
167 Scalar iu = (nord < 1) ? inf : brk[ord[b]];
168 Scalar deltat = iu - il;
180 bool crossed_all =
false;
181 const int ncorr = bfgs.num_corrections();
182 Vector wact(2 * ncorr);
183 while (deltatmin >= deltat)
186 vecc.noalias() += deltat * vecp;
193 const int act_begin = b;
194 const int act_end = search_greater(brk, ord, iu, b) - 1;
198 if ((nfree == 0) && (act_end == nord - 1))
201 for (
int i = act_begin; i <= act_end; i++)
203 const int act = ord[i];
204 xcp[act] = (vecd[act] > Scalar(0)) ? ub[act] : lb[act];
205 newact_set.push_back(act);
219 for (
int i = act_begin; i <= act_end; i++)
221 const int act = ord[i];
222 xcp[act] = (vecd[act] > Scalar(0)) ? ub[act] : lb[act];
224 const Scalar zact = xcp[act] - x0[act];
225 const Scalar gact = g[act];
226 const Scalar ggact = gact * gact;
227 wact.noalias() = bfgs.Wb(act);
228 bfgs.apply_Mv(wact, cache);
229 fp += ggact + bfgs.theta() * gact * zact - gact * cache.dot(vecc);
230 fpp -= (bfgs.theta() * ggact + 2 * gact * cache.dot(vecp) + ggact * cache.dot(wact));
231 vecp.noalias() += gact * wact;
232 vecd[act] = Scalar(0);
233 newact_set.push_back(act);
240 deltatmin = -fp / fpp;
260 const Scalar eps = std::numeric_limits<Scalar>::epsilon();
262 deltatmin = -fp / eps;
267 deltatmin = std::max(deltatmin, Scalar(0));
268 vecc.noalias() += deltatmin * vecp;
269 const Scalar tfinal = il + deltatmin;
271 for (
int i = 0; i < nfree; i++)
273 const int coord = fv_set[i];
274 xcp[coord] = x0[coord] + tfinal * vecd[coord];
276 for (
int i = b; i < nord; i++)
278 const int coord = ord[i];
279 xcp[coord] = x0[coord] + tfinal * vecd[coord];
280 fv_set.push_back(coord);