Xmipp  v3.23.11-Nereus
UTRSSolver.cpp
Go to the documentation of this file.
1 /*
2 
3 CONDOR 1.06 - COnstrained, Non-linear, Direct, parallel Optimization
4  using trust Region method for high-computing load,
5  noisy functions
6 Copyright (C) 2004 Frank Vanden Berghen
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation version 2
11 of the License.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 
22 If you want to include this tools in any commercial product,
23 you can contact the author at fvandenb@iridia.ulb.ac.be
24 
25 */
26 // trust region step solver
27 
28 #include <stdio.h>
29 #include <memory.h>
30 
31 #include "Matrix.h"
32 #include "tools.h"
33 #include "Poly.h"
34 
35 double findAlpha(Vector s,Vector u, double delta, Polynomial &q, Vector pointXk,Vector &output, Vector minusG, Matrix H)
36 // find root (apha*) of equation L2norm(s+alpha u)=delta
37 // which makes q(s)=<g,s>+.5*<s,Hs> smallest
38 // output is (s+alpha* u)
39 {
40  static Vector v1, v2, tmp;
41  double a=0,b=0,c=-sqr(delta), *sp=s, *up=u;
42  int n=s.sz();
43  while (n--)
44  {
45  a+=sqr(*up); b+=*up * *sp; c+=sqr(*sp);
46  sp++; up++;
47  }
48  double tmp1=-b/a, tmp2= sqrt(b*b-a*c)/a, q1, q2;
49 
50  n=s.sz();
51  v1.setSize(n); v2.setSize(n); tmp.setSize(n);
53  {
54  v1.copyFrom(u);
55  v1.multiply(tmp1+tmp2);
56  v1+=s;
57  tmp.copyFrom(v1);
58  tmp+=pointXk;
59  q1=q(tmp);
60 
61  // !!! don't do this:
62  // output=v1;
63  // return tmp1+tmp2;
64 
65  v2.copyFrom(u);
66  v2.multiply(tmp1-tmp2);
67  v2+=s;
68  tmp.copyFrom(v2);
69  tmp+=pointXk;
70  q2=q(tmp);
71 
72  } else
73  {
74  v1.copyFrom(u);
75  v1.multiply(tmp1+tmp2);
76  v1+=s;
77  H.multiply(tmp,v1);
78  q1=-minusG.scalarProduct(v1)+0.5*v1.scalarProduct(tmp);
79 
80  v2.copyFrom(u);
81  v2.multiply(tmp1-tmp2);
82  v2+=s;
83  H.multiply(tmp,v2);
84  q2=-minusG.scalarProduct(v2)+0.5*v2.scalarProduct(tmp);
85  }
86  if (q1>q2) { output=v1; return tmp1+tmp2; }
87  output=v2; return tmp1-tmp2;
88 }
89 
90 double initLambdaL(double normG,double delta, Matrix H)
91 {
92  int n=H.nLine(),i,j;
93  double **h=H, sum,l,a=INF;
94 
95  for (i=0; i<n; i++) a=mmin(a,h[i][i]);
96  l=mmax(0.0,-a);
97 
98  a=0;
99  for (i=0; i<n; i++)
100  {
101  sum=h[i][i];
102  for (j=0; j<n; j++) if (j!=i) sum+=condorAbs(h[i][j]);
103  a=mmax(a,sum);
104  }
105  a=mmin(a,H.frobeniusNorm());
106  a=mmin(a,H.LnftyNorm());
107 
108  l=mmax(l,normG/delta-a);
109  return l;
110 }
111 
112 double initLambdaU(double normG,double delta, Matrix H)
113 {
114  int n=H.nLine(),i,j;
115  double **h=H, sum,l,a=-INF;
116 
117  for (i=0; i<n; i++)
118  {
119  sum=-h[i][i];
120  for (j=0; j<n; j++) if (j!=i) sum+=condorAbs(h[i][j]);
121  a=mmax(a,sum);
122  }
123  a=mmin(a,H.frobeniusNorm());
124  a=mmin(a,H.LnftyNorm());
125 
126  l=mmax(0.0,normG/delta+a);
127  return l;
128 }
129 
131 {
132  int n=H.nLine(),i,j;
133  double **h=H, sum,a=-INF;
134 
135  for (i=0; i<n; i++)
136  {
137  sum=h[i][i];
138  for (j=0; j<n; j++) if (j!=i) sum+=condorAbs(h[i][j]);
139  a=mmax(a,sum);
140  }
141  a=mmin(a,H.frobeniusNorm());
142  return mmin(a,H.LnftyNorm());
143 }
144 
145 // #define POWEL_TERMINATION 1
146 
148  int *infoOut, int maxIter, double *lambda1, Vector minusG, Matrix H)
149 {
150 // lambda1>0.0 if interior convergence
151 
152  const double theta=0.01;
153 // const double kappaEasy=0.1, kappaHard=0.2;
154  const double kappaEasy=0.01, kappaHard=0.02;
155 
156  double normG,lambda,lambdaCorrection, lambdaPlus, lambdaL, lambdaU,
157  uHu, alpha, normS;
158  int info=0, n=minusG.sz();
159  Matrix HLambda(n,n);
160  MatrixTriangle L(n);
161  Vector s(n), omega(n), u(n), sFinal;
162  bool gIsNull, choleskyFactorAlreadyComputed=false;
163 
164 // printf("\nG= "); minusG.print();
165 // printf("\nH=\n"); H.print();
166 
167  gIsNull=minusG.isNull();
168  normG=minusG.euclidianNorm();
169  lambda=normG/delta;
170  minusG.multiply(-1.0);
171 
172  lambdaL=initLambdaL(normG,delta,H);
173  lambdaU=initLambdaU(normG,delta,H);
174 
175  // Special case: parl = paru.
176  lambdaU= mmax(lambdaU,(1+kappaEasy)*lambdaL);
177 
178  lambda=mmax(lambda, lambdaL);
179  lambda=mmin(lambda, lambdaU);
180 
181  while (maxIter--)
182  {
183  if (!choleskyFactorAlreadyComputed)
184  {
185  if (!H.cholesky(L, lambda, &lambdaCorrection))
186  {
187  // lambdaL=mmax(mmax(lambdaL,lambda),lambdaCorrection);
188  lambdaL=mmax(lambdaL,lambda+lambdaCorrection);
189  lambda=mmax(sqrt(lambdaL*lambdaU), lambdaL+theta*(lambdaU-lambdaL));
190  continue;
191  }
192  } else choleskyFactorAlreadyComputed=false;
193 
194 
195  // cholesky factorization successful : solve Hlambda * s = -G
196  s.copyFrom(minusG);
197  L.solveInPlace(s);
199  normS=s.euclidianNorm();
200 
201  // check for termination
202 #ifndef POWEL_TERMINATION
203  if (condorAbs(normS-delta)<kappaEasy*delta)
204  {
205  s.multiply(delta/normS);
206  info=1;
207  break;
208  }
209 #else
210 // powell check !!!
211  HLambda.copyFrom(H);
212  HLambda.addUnityInPlace(lambda);
213  double sHs=s.scalarProduct(HLambda.multiply(s));
214  if (sqr(delta/normS-1)<kappaEasy*(1+lambda*delta*delta/sHs))
215  {
216  s.multiply(delta/normS);
217  info=1;
218  break;
219  }
220 #endif
221 
222  if (normS<delta)
223  {
224  // check for termination
225  // interior convergence; maybe break;
226  if (lambda==0) { info=1; break; }
227  lambdaU=mmin(lambdaU,lambda);
228  } else lambdaL=mmax(lambdaL,lambda);
229 
230 // if (lambdaU-lambdaL<kappaEasy*(2-kappaEasy)*lambdaL) { info=3; break; };
231 
232  omega.copyFrom(s);
233  L.solveInPlace(omega);
234  lambdaPlus=lambda+(normS-delta)/delta*sqr(normS)/sqr(omega.euclidianNorm());
235  lambdaPlus=mmax(lambdaPlus, lambdaL);
236  lambdaPlus=mmin(lambdaPlus, lambdaU);
237 
238  if (normS<delta)
239  {
240  L.LINPACK(u);
241 #ifndef POWEL_TERMINATION
242  HLambda.copyFrom(H);
243  HLambda.addUnityInPlace(lambda);
244 #endif
245  uHu=u.scalarProduct(HLambda.multiply(u));
246  lambdaL=mmax(lambdaL,lambda-uHu);
247 
248  alpha=findAlpha(s,u,delta,q,pointXk,sFinal,minusG,H);
249  // check for termination
250 #ifndef POWEL_TERMINATION
251  if (sqr(alpha)*uHu<
252  kappaHard*(s.scalarProduct(HLambda.multiply(s)) ))// +lambda*sqr(delta)))
253 #else
254  if (sqr(alpha)*uHu+sHs<
255  kappaHard*(sHs+lambda*sqr(delta)))
256 #endif
257  {
258  s=sFinal; info=2; break;
259  }
260  }
261  if ((normS>delta)&&(!gIsNull)) { lambda=lambdaPlus; continue; };
262 
263  if (H.cholesky(L, lambdaPlus, &lambdaCorrection))
264  {
265  lambda=lambdaPlus;
266  choleskyFactorAlreadyComputed=true;
267  continue;
268  }
269 
270  lambdaL=mmax(lambdaL,lambdaPlus);
271  // check lambdaL for interior convergence
272 // if (lambdaL==0) return s;
273  lambda=mmax(sqrt(lambdaL*lambdaU), lambdaL+theta*(lambdaU-lambdaL));
274  }
275 
276  if (infoOut) *infoOut=info;
277  if (lambda1)
278  {
279  if (lambda==0.0)
280  {
281  // calculate the value of the lowest eigenvalue of H
282  // to check
283  lambdaL=0; lambdaU=initLambdaU2(H);
284  while (lambdaL<0.99*lambdaU)
285  {
286  lambda=0.5*(lambdaL+lambdaU);
287  if (H.cholesky(L,-lambda)) lambdaL=lambda;
288 // if (H.cholesky(L,-lambda,&lambdaCorrection)) lambdaL=lambda+lambdaCorrection;
289  else lambdaU=lambda;
290  }
291  *lambda1=lambdaL;
292  } else *lambda1=0.0;
293  }
294  return s;
295 }
296 
298  int *infoOut, int maxIter, double *lambda1)
299 {
300  int n=q.dim();
301  Matrix H(n,n);
302  Vector vG(n);
303  q.gradientHessian(pointXk,vG,H);
304  return L2NormMinimizer(q,pointXk,delta,infoOut,maxIter,lambda1,vG,H);
305 }
306 
308  int *infoOut, int maxIter, double *lambda1)
309 {
310  return L2NormMinimizer(q, Vector::emptyVector, delta, infoOut, maxIter, lambda1);
311 }
double initLambdaL(double normG, double delta, Matrix H)
Definition: UTRSSolver.cpp:90
double LnftyNorm()
Definition: Matrix.cpp:1058
int * mmax
doublereal * c
Vector L2NormMinimizer(Polynomial q, Vector pointXk, double delta, int *infoOut, int maxIter, double *lambda1, Vector minusG, Matrix H)
Definition: UTRSSolver.cpp:147
double initLambdaU2(Matrix H)
Definition: UTRSSolver.cpp:130
void sqrt(Image< double > &op)
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
Definition: Vector.h:37
unsigned dim()
Definition: Poly.h:62
double euclidianNorm()
Definition: Vector.cpp:222
double mmin(const double t1, const double t2)
Definition: tools.h:69
void copyFrom(Matrix a)
Definition: Matrix.cpp:478
#define q1
double initLambdaU(double normG, double delta, Matrix H)
Definition: UTRSSolver.cpp:112
#define i
double theta
void setSize(int _n)
Definition: Vector.cpp:112
void solveTransposInPlace(Vector y)
unsigned sz()
Definition: Vector.h:79
int nLine()
Definition: Matrix.h:83
double sqr(const double &t)
Definition: tools.h:99
doublereal * b
bool cholesky(MatrixTriangle matL, double lambda=0, double *lambdaCorrection=NULL)
Definition: Matrix.cpp:763
double v1
double * lambda
void solveInPlace(Vector b)
double frobeniusNorm()
Definition: Matrix.cpp:1045
void gradientHessian(Vector P, Vector G, Matrix H)
Definition: Poly.cpp:515
double condorAbs(const double t1)
Definition: tools.h:47
Definition: Matrix.h:38
void multiply(double a)
Definition: Vector.cpp:281
#define q2
bool isNull()
Definition: Vector.cpp:358
#define j
void LINPACK(Vector &u)
double scalarProduct(Vector v)
Definition: Vector.cpp:332
static Vector emptyVector
Definition: Vector.h:119
void addUnityInPlace(double d)
Definition: Matrix.cpp:1038
doublereal * u
double findAlpha(Vector s, Vector u, double delta, Polynomial &q, Vector pointXk, Vector &output, Vector minusG, Matrix H)
Definition: UTRSSolver.cpp:35
#define INF
Definition: svm.cpp:43
void copyFrom(Vector r, int _n=0)
Definition: Vector.cpp:215
static Polynomial emptyPolynomial
Definition: Poly.h:126
int * n
doublereal * a
double * delta