Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00034 #include <acado/sparse_solver/sparse_solver.hpp>
00035
00036 #include <iostream>
00037
00038 BEGIN_NAMESPACE_ACADO
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 ConjugateGradientMethod::ConjugateGradientMethod( ){
00049
00050 dim = 0 ;
00051 nDense = 0 ;
00052 A = 0 ;
00053 x = 0 ;
00054 norm2 = 0 ;
00055 p = 0 ;
00056 r = 0 ;
00057 TOL = 1.e-10;
00058 printLevel = LOW;
00059 pCounter = 0 ;
00060 condScale = 0 ;
00061 }
00062
00063
00064 ConjugateGradientMethod::ConjugateGradientMethod( const ConjugateGradientMethod &arg ){
00065
00066 int run1, run2;
00067
00068 dim = arg.dim;
00069 nDense = arg.nDense;
00070
00071 if( arg.A == 0 ) A = 0;
00072 else{
00073 A = new double[nDense];
00074 for( run1 = 0; run1 < nDense; run1++ )
00075 A[run1] = arg.A[run1];
00076 }
00077
00078 if( arg.x == 0 ) x = 0;
00079 else{
00080 x = new double[dim];
00081 for( run1 = 0; run1 < dim; run1++ )
00082 x[run1] = arg.x[run1];
00083 }
00084
00085 pCounter = arg.pCounter;
00086
00087
00088 if( arg.norm2 == 0 ) norm2 = 0;
00089 else{
00090 norm2 = new double[2*dim+1];
00091 for( run1 = 0; run1 < 2*dim+1; run1++ )
00092 norm2[run1] = arg.norm2[run1];
00093 }
00094
00095
00096 if( arg.p == 0 ) p = 0;
00097 else{
00098 p = new double*[2*dim+1];
00099 for( run1 = 0; run1 < 2*dim+1; run1++ ){
00100 p[run1] = new double[dim];
00101 for( run2 = 0; run2 < dim; run2++ ){
00102 p[run1][run2] = arg.p[run1][run2];
00103 }
00104 }
00105 }
00106
00107 if( arg.r == 0 ) r = 0;
00108 else{
00109 r = new double[dim];
00110 for( run1 = 0; run1 < dim; run1++ )
00111 r[run1] = arg.r[run1];
00112 }
00113
00114 TOL = arg.TOL;
00115 printLevel = arg.printLevel;
00116
00117 if( arg.condScale == 0 ) condScale = 0;
00118 else{
00119 condScale = new double[dim];
00120 for( run1 = 0; run1 < dim; run1++ )
00121 condScale[run1] = arg.condScale[run1];
00122 }
00123 }
00124
00125
00126 ConjugateGradientMethod::~ConjugateGradientMethod( ){
00127
00128 int run1;
00129
00130 if( A != 0 ) delete[] A;
00131 if( x != 0 ) delete[] x;
00132
00133 if( norm2 != 0 ) delete[] norm2;
00134
00135 if( p != 0 ){
00136 for( run1 = 0; run1 < 2*dim+1; run1++ )
00137 delete[] p[run1];
00138 delete[] p;
00139 }
00140
00141 if( r != 0 ) delete[] r;
00142
00143 if( condScale != 0) delete[] condScale;
00144 }
00145
00146
00147
00148
00149 returnValue ConjugateGradientMethod::solve( double *b ){
00150
00151
00152
00153 if( dim <= 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
00154 if( nDense <= 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
00155 if( A == 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
00156
00157
00158 int run1, run2;
00159
00160 double *aux = new double[dim];
00161 double auxR, auxR2, norm1;
00162 double alpha, beta;
00163
00164
00165
00166
00167 for( run1 = 0; run1 < dim; run1++ )
00168 x[run1] = 0.0;
00169
00170
00171
00172
00173 if( pCounter > dim ) pCounter = dim-1;
00174
00175
00176
00177
00178
00179 applyPreconditioner( b );
00180
00181
00182
00183
00184
00185
00186 for( run1 = 0; run1 < pCounter; run1++ ){
00187 alpha = scalarProduct( p[run1], r )/norm2[run1];
00188 for( run2 = 0; run2 < dim; run2++ ){
00189 x[run2] += alpha*p[run1][run2];
00190 }
00191 }
00192
00193
00194
00195
00196 multiply( x, aux );
00197
00198 for( run1 = 0; run1 < dim; run1++ )
00199 r[run1] -= aux[run1];
00200
00201
00202 for( run1 = 0; run1 < dim; run1++ )
00203 p[pCounter][run1] = r[run1];
00204
00205
00206 while( pCounter <= 2*dim-1 ){
00207
00208 norm1 = 0.0;
00209
00210 for( run1 = 0; run1 < dim; run1++ ){
00211 if( r[run1] >= 0 && norm1 < r[run1] ) norm1 = r[run1];
00212 if( r[run1] <= 0 && norm1 < -r[run1] ) norm1 = -r[run1];
00213 }
00214
00215 if( printLevel == HIGH )
00216 std::cout << "STEP NUMBER " << pCounter << ", WEIGHTED NORM = "
00217 << std::scientific << norm1 << std::endl;
00218
00219 if( norm1 < TOL ) break;
00220
00221 auxR = scalarProduct( r,r );
00222 multiply( p[pCounter], aux );
00223 norm2[pCounter] = scalarProduct( p[pCounter], aux );
00224 alpha = auxR/norm2[pCounter];
00225
00226 for( run1 = 0; run1 < dim; run1++ ){
00227 x [run1] += alpha*p[pCounter][run1];
00228 r [run1] -= alpha*aux[run1];
00229 }
00230
00231 auxR2 = scalarProduct( r,r );
00232 beta = auxR2/auxR;
00233
00234 for( run1 = 0; run1 < dim; run1++ )
00235 p[pCounter+1][run1] = r[run1] + beta*p[pCounter][run1];
00236
00237 pCounter++;
00238 }
00239
00240 delete[] aux ;
00241
00242 if( pCounter >= 2*dim ){
00243 if( printLevel == MEDIUM || printLevel == HIGH )
00244 return ACADOWARNING( RET_LINEAR_SYSTEM_NUMERICALLY_SINGULAR );
00245 else return RET_LINEAR_SYSTEM_NUMERICALLY_SINGULAR;
00246 }
00247
00248 return SUCCESSFUL_RETURN;
00249 }
00250
00251
00252 returnValue ConjugateGradientMethod::setDimension( const int &n ){
00253
00254 int run1;
00255
00256 dim = n;
00257
00258 if( x != 0 ){
00259 delete[] x;
00260 x = 0;
00261 }
00262 x = new double[dim];
00263
00264 if( norm2 != 0 ){
00265 delete[] norm2;
00266 norm2 = 0;
00267 }
00268 norm2 = new double[2*dim+1];
00269
00270 if( p != 0 ){
00271 for( run1 = 0; run1 < 2*dim+1; run1++ )
00272 delete[] p[run1];
00273 delete[] p;
00274 }
00275 p = new double*[2*dim+1];
00276 for( run1 = 0; run1 < 2*dim+1; run1++ ){
00277 p[run1] = new double[dim];
00278 }
00279
00280
00281 if( r != 0 ){
00282 delete[] r;
00283 r = 0;
00284 }
00285 r = new double[dim];
00286
00287 if( condScale != 0 ){
00288 delete[] condScale;
00289 condScale = 0;
00290 }
00291 condScale = new double[dim];
00292
00293 pCounter = 0;
00294
00295 return SUCCESSFUL_RETURN;
00296 }
00297
00298
00299
00300 returnValue ConjugateGradientMethod::setNumberOfEntries( const int &nDense_ ){
00301
00302 if( A != 0 ){
00303 delete[] A;
00304 A = 0;
00305 }
00306
00307 nDense = nDense_;
00308
00309 return SUCCESSFUL_RETURN;
00310 }
00311
00312
00313
00314
00315 returnValue ConjugateGradientMethod::setMatrix( double *A_ ){
00316
00317 if( dim <= 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
00318 if( nDense <= 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
00319
00320 pCounter = 0;
00321
00322 A = new double[nDense];
00323 return computePreconditioner( A_ );
00324 }
00325
00326
00327
00328
00329 returnValue ConjugateGradientMethod::getX( double *x_ ){
00330
00331 return applyInversePreconditioner( x_ );
00332 }
00333
00334
00335 returnValue ConjugateGradientMethod::setTolerance( double TOL_ ){
00336
00337 TOL = TOL_;
00338 return SUCCESSFUL_RETURN;
00339 }
00340
00341
00342 returnValue ConjugateGradientMethod::setPrintLevel( PrintLevel printLevel_ ){
00343
00344 printLevel = printLevel_;
00345 return SUCCESSFUL_RETURN;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355 double ConjugateGradientMethod::scalarProduct( double *aa, double *bb ){
00356
00357 int run1;
00358 double aux = 0.0;
00359
00360 for( run1 = 0; run1 < dim; run1++ )
00361 aux += aa[run1]*bb[run1];
00362
00363 return aux;
00364 }
00365
00366
00367
00368 CLOSE_NAMESPACE_ACADO
00369
00370
00371
00372
00373