48 pdCurParams[i] = (pInitParams) ? pInitParams[i] : 1;
75 lout << pdDir[i] <<
" ";
76 lout <<
"... }" << endl;
80 lout << pdCurParams[i] <<
" ";
81 lout <<
"... }" << endl;
85 lout << pdCurGradient[i] <<
" ";
86 lout <<
"... }" << endl;
89 lout_Solve <<
"a=" << dStep <<
" |g_k|=" << dNorm <<
" f_k=" << dCurValue << endl;
92 for (
int i = 0; i < nExValueNum; i++)
93 lout << dExValues[i] <<
" ";
114 dStep =
LineSearch(pdDir, dCurValue, pdCurParams, pdCurGradient);
117 Update(pdCurParams, pdDir, dStep);
141 pdDir[i] = -pdGradient[i];
143 double Solve::LineSearch(
double *pdDir,
double dValue,
const double *pdCurParam,
const double *pdGradient)
151 double a0 = 0, a1 = 0, a2 = 0;
152 double phi0 = 0, phi1 = 0, phi2 = 0;
157 for (
int k = 1; a2 > 0; k++)
161 pdNextParam[n] = pdCurParam[n] + a2 * pdDir[n];
166 if (phi2 <= dValue + c * a2 * phi_t)
175 a2 = -phi_t*a1*a1 / 2 / (phi1 - dValue - phi_t * a1);
178 double v1 = phi1 - dValue - phi_t * a1;
179 double v2 = phi0 - dValue - phi_t * a0;
180 double a = a0*a0*v1 - a1*a1*v2;
181 double b = -a0*a0*a0*v1 + a1*a1*a1*v2;
182 double t = a0*a0*a1*a1*(a1 - a0);
185 a2 = (-b + sqrt(b*b - 3 * a*phi_t)) / (3 * a);
189 if (fabs(a2 - a1) < 1e-5 ||
194 lout_warning(
"[Solve] LineSearch: a2 is too small < 1e-10, break")
207 pdParam[i] += pdDir[i] * dStep;
223 for (
int i = 0; i < nSize; i++)
224 d += pdVec1[i] * pdVec2[i];
234 for (
int i = 0; i < nSize; i++)
235 d += pow(pdVec1[i] - pdVec2[i], 2);
249 m_pdAlpha =
new double[m_nLimitiedNum];
251 CirQueueBuf_Release();
258 CirQueueBuf_In(m_pd_s, m_pd_y);
260 m_pd_s[n] = pdParam[n] - m_pdPrevParam[n];
261 m_pd_y[n] = pdGradient[n] - m_pdPrevGradient[n];
274 int nBound = min(m_nLimitiedNum, k-1);
277 memcpy(pdDir, pdGradient,
sizeof(pdDir[0])*nVecLen);
282 CirQueueBuf_Prev(1, pd_s, pd_y);
288 for (
int i = 1; i <= nBound; i++)
290 CirQueueBuf_Prev(i, pd_s, pd_y);
292 double dProd =
VecProduct(pd_s, pd_y, nVecLen);
293 m_pdAlpha[i - 1] =
VecProduct(pd_s, pdDir, nVecLen) / dProd;
294 for (
int n = 0; n < nVecLen; n++)
295 pdDir[n] -= m_pdAlpha[i - 1] * pd_y[n];
302 CirQueueBuf_Prev(1, pd_s, pd_y);
307 for (
int n = 0; n < nVecLen; n++)
311 for (
int i = nBound; i >= 1; i--)
313 CirQueueBuf_Prev(i, pd_s, pd_y);
315 for (
int n = 0; n < nVecLen; n++)
316 pdDir[n] += pd_s[n] * (m_pdAlpha[i - 1] - dBeta);
322 for (
int n = 0; n < nVecLen; n++)
323 pdDir[n] = -pdDir[n];
336 m_pCirQueueBuf =
new sy[m_nLimitiedNum];
337 for (
int i = 0; i < m_nLimitiedNum; i++) {
341 m_nCirQueueBufTail = 0;
345 if (m_pCirQueueBuf) {
346 for (
int i = 0; i < m_nLimitiedNum; i++) {
352 m_nCirQueueBufTail = 0;
356 i = (m_nLimitiedNum + m_nCirQueueBufTail - i) % m_nLimitiedNum;
357 pd_s = m_pCirQueueBuf[i].s;
358 pd_y = m_pCirQueueBuf[i].y;
362 pd_s = m_pCirQueueBuf[m_nCirQueueBufTail].s;
363 pd_y = m_pCirQueueBuf[m_nCirQueueBufTail].y;
364 m_nCirQueueBufTail = (m_nCirQueueBufTail + 1) % m_nLimitiedNum;
int m_nIterMin
minium iteration number
virtual void ComputeDir(int k, const double *pdParam, const double *pdGradient, double *pdDir)
Calculate the update direction p_k.
virtual void SetParam(double *pdParams)=0
set the parameter.
static double VecDist(const double *pdVec1, const double *pdVec2, int nSize)
calculate the distance of two vectors
virtual void IterInit()
initial the iteration, for derivation.
clock - used to record the time
virtual void GetGradient(double *pdGradient)=0
calculate the gradient g(x)
clock_t Begin()
begin to record
static double ToSecond(clock_t t)
transform the clock_t to second
int m_nIterNum
current iteration number, iter form m_nIterMin to m_nIterMax
virtual double GetValue()=0
calculate the function value f(x)
virtual void IterInit()
iter init
static double VecProduct(const double *pdVec1, const double *pdVec2, int nSize)
calculate the dot of two vectors
#define SAFE_DELETE_ARRAY(p)
virtual double LineSearch(double *pdDir, double dValue, const double *pdParam, const double *pdGradient)
linear search.
int m_nIterMax
maximum iteration number
void CirQueueBuf_In(double *&pd_s, double *&pd_y)
in queue. return the pointer.
int GetParamNum() const
get the paremeter number
static double VecNorm(const double *pdVec, int nSize)
calculate the norm of a vector
virtual void ComputeDir(int k, const double *pdParam, const double *pdGradient, double *pdDir)
Calculate the update direction p_k, referring to "Numerical Optimization"锟斤拷P178锟斤拷Algorithm 7...
double * m_pdRoot
save the root of the function
virtual bool StopDecision(int k, double dValue, const double *pdGradient)
Stop decision.
double m_dGain
itera step. ==0 means using the line search .
Func * m_pfunc
pointer to the function
void CirQueueBuf_Release()
release the circular queue
double m_dStop
stop threshold
Log lout
the defination is in wb-log.cpp
define the framework of iterative algorithms, such as gradient descent or LBFGS.
static const int cn_exvalue_max_num
virtual int GetExtraValues(int k, double *pdValues)
calculate extra values which will be print at each iteration
int m_nParamNum
the parameter number
clock_t End()
record end and return the time
void CirQueueBuf_Init()
Init the circular queue.
virtual bool Run(const double *pInitParams=NULL)
Run iteration. input the init-parameters.
virtual void Update(double *pdParam, const double *pdDir, double dStep)
Update.
double m_dSpendMinute
record the iteration spend time锟斤拷minute锟斤拷
define all the code written by Bin Wang.
void CirQueueBuf_Prev(int i, double *&pd_s, double *&pd_y)
find the previoud ith datas, i<=m_nLimitiedNum