Xmipp  v3.23.11-Nereus
Functions | Variables
QPSolver.cpp File Reference
#include <stdio.h>
#include <memory.h>
#include "Matrix.h"
#include "tools.h"
#include "VectorChar.h"
Include dependency graph for QPSolver.cpp:

Go to the source code of this file.

Functions

void QPReconstructLambda (Vector vLambda, Vector vLambdaScale)
 
void simpleQPSolve (Matrix mH, Vector vG, Matrix mA, Vector vB, Vector vP, Vector vLambda, int *info)
 
void restartSimpleQPSolve (Vector vBO, Vector vP)
 

Variables

Matrix mQ_QP
 
MatrixTriangle mR_QP
 
VectorInt vi_QP
 
VectorInt viPermut_QP
 
Vector vLastLambda_QP
 
char bQRFailed_QP
 

Function Documentation

◆ QPReconstructLambda()

void QPReconstructLambda ( Vector  vLambda,
Vector  vLambdaScale 
)

Definition at line 84 of file QPSolver.cpp.

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 }
int sz()
Definition: VectorInt.h:63
VectorInt vi_QP
Definition: QPSolver.cpp:80
unsigned sz()
Definition: Vector.h:79
int * n

◆ restartSimpleQPSolve()

void restartSimpleQPSolve ( Vector  vBO,
Vector  vP 
)

Definition at line 363 of file QPSolver.cpp.

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 }
void permutIn(Vector vR, VectorInt viP)
Definition: Vector.cpp:501
int sz()
Definition: VectorInt.h:63
MatrixTriangle mR_QP
Definition: QPSolver.cpp:79
VectorInt vi_QP
Definition: QPSolver.cpp:80
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
Matrix mQ_QP
Definition: QPSolver.cpp:78
Definition: Vector.h:37
VectorInt viPermut_QP
Definition: QPSolver.cpp:80
Vector vLastLambda_QP
Definition: QPSolver.cpp:81
#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: Vector.cpp:112
doublereal * b
double * lambda
void solveInPlace(Vector b)
void zero(int _i=0, int _n=0)
Definition: Vector.cpp:93
char bQRFailed_QP
Definition: QPSolver.cpp:82

◆ simpleQPSolve()

void simpleQPSolve ( Matrix  mH,
Vector  vG,
Matrix  mA,
Vector  vB,
Vector  vP,
Vector  vLambda,
int *  info 
)

Definition at line 105 of file QPSolver.cpp.

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);
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 }
void permutIn(Vector vR, VectorInt viP)
Definition: Vector.cpp:501
void zero()
Definition: Matrix.cpp:553
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
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
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
#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
void setSize(int _n)
Definition: Vector.cpp:112
void solveTransposInPlace(Vector y)
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
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
#define j
Matrix clone()
Definition: Matrix.cpp:470
#define INF
Definition: svm.cpp:43
void transposeAndMultiply(Vector R, Vector a)
Definition: Matrix.cpp:669
void copyFrom(Vector r, int _n=0)
Definition: Vector.cpp:215
char bQRFailed_QP
Definition: QPSolver.cpp:82
doublereal * a

Variable Documentation

◆ bQRFailed_QP

char bQRFailed_QP

Definition at line 82 of file QPSolver.cpp.

◆ mQ_QP

Matrix mQ_QP

Definition at line 78 of file QPSolver.cpp.

◆ mR_QP

Definition at line 79 of file QPSolver.cpp.

◆ vi_QP

VectorInt vi_QP

Definition at line 80 of file QPSolver.cpp.

◆ viPermut_QP

VectorInt viPermut_QP

Definition at line 80 of file QPSolver.cpp.

◆ vLastLambda_QP

Vector vLastLambda_QP

Definition at line 81 of file QPSolver.cpp.