Xmipp  v3.23.11-Nereus
QPSolver.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 
27 #include <stdio.h>
28 #include <memory.h>
29 
30 //#include <crtdbg.h>
31 
32 #include "Matrix.h"
33 #include "tools.h"
34 #include "VectorChar.h"
35 
36 
37 // #define POWELLQP
38 #ifdef POWELLQP
39 
40 int ql0001_(int *m,int *me,int *mmax,int *n,int *nmax,int *mnn,
41  double *c,double *d,double *a,double *b,double *xl,
42  double *xu,double *x,double *u,int *iout,int *ifail,
43  int *iprint,double *war,int *lwar,int *iwar,int *liwar,
44  double *eps1);
45 
46 void simpleQPSolve(Matrix G, Vector vd, Matrix Astar, Vector vBstar, // in
47  Vector vXtmp, Vector vLambda) // out
48 {
49  Astar.setNLine(Astar.nLine()+1);
50  Matrix thisG, At=Astar.transpose();
51  Astar.setNLine(Astar.nLine()-1);
52  Vector minusvd=vd.clone();
53  minusvd.multiply(-1.0); vBstar.multiply(-1.0);
54  int m=Astar.nLine(), me=0, mmax=Astar.nLine()+1, n=vd.sz(), nmax=n,
55  mnn=m+n+n, iout=0, ifail, iprint=0, lwar=3*nmax*nmax/2 + 10*nmax+ 2*mmax+1,
56  liwar=n;
57  if (G==Matrix::emptyMatrix) {
58  thisG.setSize(n,n); thisG.diagonal(1.0); }
59  else thisG=G;
60  double *c=*((double**)thisG), *d=minusvd, *a=*((double**)At), *b=vBstar;
61  Vector vxl(n),vxu(n), temp(lwar);
62  VectorInt itemp(liwar);
63  vLambda.setSize(mnn);
64  double *xl=vxl, *xu=vxu, *x=vXtmp, *u=vLambda, *war=temp, eps1=1e-20;
65  int *iwar=itemp;
66 
67  int dim=n; while (dim--) { xl[dim]=-INF; xu[dim]=INF; }
68  iwar[0]=0;
69 
70  ql0001_(&m,&me,&mmax,&n,&nmax,&mnn,c,d,a,b,xl,xu,x,u,&iout,&ifail,
71  &iprint,war,&lwar,iwar,&liwar,&eps1);
72 
73  vLambda.setSize(m);
74 }
75 
76 #else
77 
83 
84 void QPReconstructLambda(Vector vLambda, Vector vLambdaScale)
85 {
86  int n=vi_QP.sz()-1, nc=vLambda.sz();
87  int *ii=vi_QP;
88  double *l=vLambda, *s=vLambdaScale;
89 
90  if (n>=0)
91  while (nc--)
92  {
93  if (ii[n]==nc)
94  {
95 // l[nc]=mmax(0.0,l[n]/s[n]);
96  l[nc]=l[n]/s[n];
97  n--;
98  if (n<0) break;
99  }
100  else l[nc]=0.0;
101  }
102  if (nc) memset(l,0,nc*sizeof(double));
103 }
104 
105 void simpleQPSolve(Matrix mH, Vector vG, Matrix mA, Vector vB, // in
106  Vector vP, Vector vLambda, int *info) // out
107 {
108  const double tolRelFeasibility=1e-6;
109 // int *info=NULL;
110  int dim=mA.nColumn(), nc=mA.nLine(), ncr, i,j,k, lastJ=-2, *ii;
111  MatrixTriangle M(dim);
112  Matrix mAR, mZ(dim,dim-1), mHZ(dim,dim-1), mZHZ(dim-1,dim-1);
113  Vector vTmp(mmax(nc,dim)), vYB(dim), vD(dim), vTmp2(dim), vTmp3(nc), vLast(dim),
114  vBR_QP, vLambdaScale(nc);
115  VectorChar vLB(nc);
116  double *lambda=vLambda, *br, *b=vB, violationMax, violationMax2,
117  *rlambda,ax,al,dviolation, **a=mA, **ar=mAR, mymin, mymax, maxb, *llambda,
118  **r,t, *scaleLambda=vLambdaScale;
119  char finished=0, feasible=0, *lb=vLB;
120 
121  if (info) *info=0;
122 
123  // remove lines which are null
124  k=0; vi_QP.setSize(nc); maxb=0.0;
125  for (i=0; i<nc; i++)
126  {
127  mymin=INF; mymax=-INF;
128  for (j=0; j<dim; j++)
129  {
130  mymin=mmin(mymin,a[i][j]);
131  mymax=mmax(mymax,a[i][j]);
132  if ((mymin!=mymax)||(mymin!=0.0)||(mymax!=0.0)) break;
133  }
134  if ((mymin!=mymax)||(mymin!=0.0)||(mymax!=0.0))
135  {
136  lambda[k]=lambda[i];
137  maxb=mmax(maxb,condorAbs(b[i]));
138  scaleLambda[k]=mA.euclidianNorm(i);
139  vi_QP[k]=i;
140  k++;
141  }
142  }
143  nc=k; vi_QP.setSize(nc); ii=vi_QP; maxb=(1.0+maxb)*tolRelFeasibility;
144  vLast.zero();
145 
146  for (i=0; i<nc; i++) if (lambda[i]!=0.0) lb[i]=2; else lb[i]=1;
147 
148  while (!finished)
149  {
150  finished=1;
151  mAR.setSize(dim,dim); mAR.zero(); ar=mAR;
152  vBR_QP.setSize(mmin(nc,dim)); br=vBR_QP;
153  ncr=0;
154  for (i=0; i<nc; i++)
155  if (lambda[i]!=0.0)
156  {
157 // mAR.setLines(ncr,mA,ii[i],1);
158  k=ii[i];
159  t=scaleLambda[ncr];
160  for (j=0; j<dim; j++) ar[ncr][j]=a[k][j]*t;
161  br[ncr]=b[ii[i]]*t;
162  ncr++;
163  }
164  mAR.setSize(ncr,dim);
165  vBR_QP.setSize(ncr);
166  vLastLambda_QP.copyFrom(vLambda); llambda=vLastLambda_QP;
167 
168  if (ncr==0)
169  {
170  // compute step
171  vYB.copyFrom(vG);
172  vYB.multiply(-1.0);
173  if (mH.cholesky(M))
174  {
175  M.solveInPlace(vYB);
176  M.solveTransposInPlace(vYB);
177  } else
178  {
179  printf("warning: cholesky factorisation failed.\n");
180  if (info) *info=2;
181  }
182  vLambda.zero();
183  } else
184  {
185  Matrix mAR2=mAR.clone(), mQ2;
186  MatrixTriangle mR2;
187  mAR2.QR(mQ2,mR2);
188 
189  mAR.QR(mQ_QP,mR_QP, viPermut_QP); // content of mAR is destroyed here !
190  bQRFailed_QP=0;
191 
192  r=mR_QP;
193  for (i=0; i<ncr; i++)
194  if (r[i][i]==0.0)
195  {
196  // one constraint has been wrongly added.
197  bQRFailed_QP=1;
198  QPReconstructLambda(vLambda,vLambdaScale); vP.copyFrom(vLast); return;
199  }
200 
201  for (i=0; i<ncr; i++)
202  if (viPermut_QP[i]!=i)
203  {
204  // printf("whoups.\n");
205  }
206  if (ncr<dim)
207  {
208  mQ_QP.getSubMatrix(mZ,0,ncr);
209 
210  // Z^t H Z
211  mH.multiply(mHZ,mZ);
212  mZ.transposeAndMultiply(mZHZ,mHZ);
213  mQ_QP.setSize(dim,ncr);
214  }
215 
216  // form Yb
217  vBR_QP.permutIn(vTmp,viPermut_QP);
218  mR_QP.solveInPlace(vTmp);
219  mQ_QP.multiply(vYB,vTmp);
220 
221  if (ncr<dim)
222  {
223 
224  // ( vG + H vYB )^t Z : result in vD
225 
226  mH.multiply(vTmp,vYB);
227  vTmp+=vG;
228  vTmp.transposeAndMultiply(vD,mZ);
229 
230  // calculate current delta (result in vD)
231  vD.multiply(-1.0);
232  if (mZHZ.cholesky(M))
233  {
234  M.solveInPlace(vD);
235  M.solveTransposInPlace(vD);
236  }
237  else
238  {
239  printf("warning: cholesky factorisation failed.\n");
240  if (info) *info=2;
241  };
242 
243  // evaluate vX* (result in vYB):
244  mZ.multiply(vTmp, vD);
245  vYB+=vTmp;
246  }
247 
248  // evaluate vG* (result in vTmp2)
249  mH.multiply(vTmp2,vYB);
250  vTmp2+=vG;
251 
252  // evaluate lambda star (result in vTmp):
253  mQ2.transposeAndMultiply(vTmp,vTmp2);
254  mR2.solveTransposInPlace(vTmp);
255 
256  // evaluate lambda star (result in vTmp):
257  mQ_QP.transposeAndMultiply(vTmp3,vTmp2);
258  mR_QP.solveTransposInPlace(vTmp3);
259  vTmp3.permutOut(vTmp,viPermut_QP);
260  rlambda=vTmp;
261 
262  ncr=0;
263  for (i=0; i<nc; i++)
264  if (lambda[i]!=0.0)
265  {
266  lambda[i]=rlambda[ncr];
267  ncr++;
268  }
269  } // end of test on ncr==0
270 
271  // find the most violated constraint j among non-active Linear constraints:
272  j=-1;
273  if (nc>0)
274  {
275  k=-1; violationMax=-INF; violationMax2=-INF;
276  for (i=0; i<nc; i++)
277  {
278  if (lambda[i]<=0.0) // test to see if this constraint is not active
279  {
280  ax=mA.scalarProduct(ii[i],vYB);
281  dviolation=b[ii[i]]-ax;
282  if (llambda[i]==0.0)
283  {
284  // the constraint was not active this round
285  // thus, it can enter the competition for the next
286  // active constraint
287 
288  if (dviolation>maxb)
289  {
290  // the constraint should be activated
291  if (dviolation>violationMax2)
292  { k=i; violationMax2=dviolation; }
293  al=mA.scalarProduct(ii[i],vLast)-ax;
294  if (al>0.0) // test to see if we are going closer
295  {
296  dviolation/=al;
297  if (dviolation>violationMax )
298  { j=i; violationMax =dviolation; }
299  }
300  }
301  } else
302  {
303  lb[i]--;
304  if (feasible)
305  {
306  if (lb[i]==0)
307  {
308  vLambda.copyFrom(vLastLambda_QP);
309  if (lastJ>=0) lambda[lastJ]=0.0;
310  QPReconstructLambda(vLambda,vLambdaScale);
311  vP.copyFrom(vYB);
312  return;
313  }
314  } else
315  {
316  if (lb[i]==0)
317  {
318  if (info) *info=1;
319  QPReconstructLambda(vLambda,vLambdaScale);
320  vP.zero();
321  return;
322  }
323  }
324  finished=0; // this constraint was wrongly activated.
325  lambda[i]=0.0;
326  }
327  }
328  }
329 
330  // !!! the order the tests is important here !!!
331  if ((j==-1)&&(!feasible))
332  {
333  feasible=1;
334  for (i=0; i<nc; i++) if (llambda[i]!=0.0) lb[i]=2; else lb[i]=1;
335  }
336  if (j==-1) { j=k; violationMax=violationMax2; } // change j to k after feasible is set
337  if (ncr==mmin(dim,nc)) {
338  if (feasible) { // feasible must have been checked before
339  QPReconstructLambda(vLambda,vLambdaScale); vP.copyFrom(vYB); return;
340  } else
341  {
342  if (info) *info=1;
343  QPReconstructLambda(vLambda,vLambdaScale); vP.zero(); return;
344  }
345  }
346  // activation of constraint only if ncr<mmin(dim,nc)
347  if (j>=0) { lambda[j]=1e-5; finished=0; } // we need to activate a new constraint
348 // else if (ncr==dim){
349 // QPReconstructLambda(vLambda); vP.copyFrom(vYB); return; }
350  }
351 
352  // to prevent rounding error
353  if (j==lastJ) {
354 // if (0) {
355  QPReconstructLambda(vLambda,vLambdaScale); vP.copyFrom(vYB); return; }
356  lastJ=j;
357 
358  vLast.copyFrom(vYB);
359  }
360  QPReconstructLambda(vLambda,vLambdaScale); vP.copyFrom(vYB); return;
361 }
362 
364  Vector vP) // out
365 {
366  if (bQRFailed_QP) { vP.zero(); return; }
367  int i,k=0, *ii=vi_QP, nc2=vi_QP.sz();
368  double *lambda=vLastLambda_QP, *b=vBO;
369  Vector vTmp(nc2);
370  for (i=0; i<nc2; i++)
371  {
372  if (lambda[i]!=0.0)
373  {
374  b[k]=b[ii[i]];
375  k++;
376  }
377  }
378  vBO.setSize(k);
379  vBO.permutIn(vTmp,viPermut_QP);
380  mR_QP.solveInPlace(vTmp);
381  mQ_QP.multiply(vP,vTmp);
382 }
383 
384 #endif
void permutIn(Vector vR, VectorInt viP)
Definition: Vector.cpp:501
int ql0001_(m, me, mmax, n, nmax, mnn, c, d, a, b, xl, xu, x, u, iout, ifail, iprint, war, lwar, iwar, liwar, eps1) integer *m
int sz()
Definition: VectorInt.h:63
int * nmax
void zero()
Definition: Matrix.cpp:553
void simpleQPSolve(Matrix mH, Vector vG, Matrix mA, Vector vB, Vector vP, Vector vLambda, int *info)
Definition: QPSolver.cpp:105
doublereal * war
MatrixTriangle mR_QP
Definition: QPSolver.cpp:79
int * mmax
double scalarProduct(int nl, Vector v)
Definition: Matrix.cpp:695
VectorInt vi_QP
Definition: QPSolver.cpp:80
void QPReconstructLambda(Vector vLambda, Vector vLambdaScale)
Definition: QPSolver.cpp:84
doublereal * c
doublereal * xl
void QR(Matrix Q=Matrix::emptyMatrix, MatrixTriangle R=MatrixTriangle::emptyMatrixTriangle, VectorInt permutation=VectorInt::emptyVectorInt)
Definition: Matrix.cpp:820
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
Matrix mQ_QP
Definition: QPSolver.cpp:78
Definition: Vector.h:37
double mmin(const double t1, const double t2)
Definition: tools.h:69
doublereal * xu
void setSize(int _nLine, int _nColumn)
Definition: Matrix.cpp:205
VectorInt viPermut_QP
Definition: QPSolver.cpp:80
Vector vLastLambda_QP
Definition: QPSolver.cpp:81
int nColumn()
Definition: Matrix.h:84
integer * liwar
Vector clone()
Definition: Vector.cpp:207
integer * iprint
void restartSimpleQPSolve(Vector vBO, Vector vP)
Definition: QPSolver.cpp:363
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void setSize(int _n)
Definition: VectorInt.cpp:126
doublereal * d
void setSize(int _n)
Definition: Vector.cpp:112
void solveTransposInPlace(Vector y)
unsigned sz()
Definition: Vector.h:79
int nLine()
Definition: Matrix.h:83
doublereal * b
void getSubMatrix(Matrix R, int startL, int StartC, int nl=0, int nc=0)
Definition: Matrix.cpp:1145
bool cholesky(MatrixTriangle matL, double lambda=0, double *lambdaCorrection=NULL)
Definition: Matrix.cpp:763
double * lambda
void solveInPlace(Vector b)
void zero(int _i=0, int _n=0)
Definition: Vector.cpp:93
integer * iwar
double euclidianNorm(int i)
Definition: Matrix.cpp:1140
double condorAbs(const double t1)
Definition: tools.h:47
Definition: Matrix.h:38
void transposeAndMultiply(Vector vR, Matrix M)
Definition: Vector.cpp:297
void multiply(double a)
Definition: Vector.cpp:281
int * me
#define j
int m
doublereal * eps1
integer * iout
int * mnn
Matrix transpose()
Definition: Matrix.cpp:539
doublereal * u
Matrix clone()
Definition: Matrix.cpp:470
#define INF
Definition: svm.cpp:43
integer * ifail
void transposeAndMultiply(Vector R, Vector a)
Definition: Matrix.cpp:669
void setNLine(int _nLine)
Definition: Matrix.cpp:187
static Matrix emptyMatrix
Definition: Matrix.h:134
integer * lwar
void copyFrom(Vector r, int _n=0)
Definition: Vector.cpp:215
char bQRFailed_QP
Definition: QPSolver.cpp:82
int * n
doublereal * a
void diagonal(double d)
Definition: Matrix.cpp:65