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
00027
00028
00029
00030
00031
00032
00033
00034 #include <SQPsearchDirectionMeritFunctionAndHessian.h>
00035 #include <SearchDirection.h>
00036 #include <MeritFunctionCheck.h>
00037 #include <HessianApproximation.h>
00038 #include <MatrixOperations.h>
00039 #include <Vector.h>
00040
00041
00042 SQPsearchDirectionMeritFunctionAndHessian::SQPsearchDirectionMeritFunctionAndHessian(
00043 double pc_bar,
00044 double pe_bar)
00045 :SearchDirection(), MeritFunctionCheck(), HessianApproximation()
00046 {
00047 theHessianApproximation = 0;
00048
00049
00050 alpha = 0.0;
00051 c_bar = pc_bar;
00052 e_bar = pe_bar;
00053
00054
00055
00056 B = 0;
00057 delta = 1.0;
00058 c = c_bar;
00059 lambda = 1.0;
00060
00061
00062
00063 if (c_bar < 1.0) {
00064 opserr << "ERROR: Parameter c_bar in SQP algorithm is invalid." << endln;
00065 }
00066 if (e_bar > 1.0) {
00067 opserr << "ERROR: Parameter e_bar in SQP algorithm is invalid." << endln;
00068 }
00069 }
00070
00071 SQPsearchDirectionMeritFunctionAndHessian::~SQPsearchDirectionMeritFunctionAndHessian()
00072 {
00073 if (B != 0)
00074 delete B;
00075 }
00076
00077
00078 int
00079 SQPsearchDirectionMeritFunctionAndHessian::setHessianApproximation(HessianApproximation *passedHessianApproximation)
00080 {
00081 theHessianApproximation = passedHessianApproximation;
00082 return 0;
00083 }
00084
00085
00086
00087
00088
00089 Vector
00090 SQPsearchDirectionMeritFunctionAndHessian::getSearchDirection()
00091 {
00092 return searchDirection;
00093 }
00094
00095 int
00096 SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection(
00097 int stepNumber,
00098 Vector u,
00099 double g,
00100 Vector gradG )
00101 {
00102
00103 int i,j;
00104
00105
00106
00107 int nrv = u.Size();
00108
00109
00110
00111
00112 if (stepNumber == 1) {
00113 if (theHessianApproximation != 0) {
00114 theHessianApproximation->setHessianToIdentity(nrv);
00115 }
00116 else {
00117 opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection() -- " << endln
00118 << "theHessianApproximation has not been set! " << endln;
00119 }
00120 delta = 1.0;
00121 c = c_bar;
00122 lambda = 1.0;
00123 }
00124
00125
00126
00127 Matrix Hessian;
00128 if (theHessianApproximation != 0) {
00129 Hessian = theHessianApproximation->getHessianApproximation();
00130 }
00131 else {
00132 opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::computeSearchDirection() -- " << endln
00133 << "theHessianApproximation has not been set! " << endln;
00134 }
00135
00136
00137
00138 Matrix A((nrv+1),(nrv+1));
00139 for (i=0; i<(nrv+1); i++) {
00140 for (j=0; j<(nrv+1); j++) {
00141 if (i==nrv && j==nrv) {
00142 A(i,j) = 0.0;
00143 }
00144 else {
00145 if (i<nrv && j<nrv) {
00146 A(i,j) = Hessian(i,j);
00147 }
00148 else if (i==nrv) {
00149 A(i,j) = gradG(j);
00150 }
00151 else {
00152 A(i,j) = gradG(i);
00153 }
00154 }
00155 }
00156 }
00157
00158
00159
00160 Vector b(nrv+1);
00161 for (i=0; i<nrv; i++) {
00162 b(i) = -u(i);
00163 }
00164 b(nrv) = -g;
00165
00166
00167
00168 MatrixOperations theMatrixOperations(A);
00169 theMatrixOperations.computeInverse();
00170 Matrix invA = theMatrixOperations.getInverse();
00171 Vector dAndKappa = invA ^ b;
00172
00173
00174
00175 Vector d(nrv);
00176 for (i=0; i<nrv; i++) {
00177 d(i) = dAndKappa(i);
00178 }
00179 kappa = dAndKappa(nrv);
00180 searchDirection = d;
00181
00182
00183
00184
00185
00186
00187
00188 Vector temp2 = Hessian ^ searchDirection;
00189 double dBd = temp2 ^ searchDirection;
00190 double dd = searchDirection^searchDirection;
00191
00192
00193
00194 double term1 = dBd/dd;
00195 if ( term1 < delta ) {
00196 delta = term1;
00197 }
00198
00199
00200
00201 double e;
00202 if ( fabs(kappa-lambda)<1.0e-9 ) {
00203 e = e_bar;
00204 }
00205 else {
00206 e = dd / ((kappa-lambda)*(kappa-lambda));
00207 }
00208
00209
00210
00211 double iii = -ceil(log(0.25*e*delta*(1-0.25*delta))/log(c_bar));
00212 if (iii < 0) {
00213 iii = 0;
00214 }
00215
00216
00217
00218 term1 = pow(c_bar,iii);
00219 if ( c < term1 ) {
00220 c = term1;
00221 }
00222
00223 return 0;
00224 }
00225
00226
00227 double
00228 SQPsearchDirectionMeritFunctionAndHessian::getMeritFunctionValue(Vector u, double g, Vector grad_G)
00229 {
00230 opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::getMeritFunctionValue() --" << endln
00231 << " no explicit merit function value is computed." << endln;
00232 return 0.0;
00233 }
00234
00235
00236
00237 int
00238 SQPsearchDirectionMeritFunctionAndHessian::updateMeritParameters(Vector u, double g, Vector grad_G)
00239 {
00240 opserr << "WARNING: SQPsearchDirectionMeritFunctionAndHessian::updateMeritParameters() --" << endln
00241 << " no explicit merit function value is computed." << endln;
00242
00243 return 0;
00244 }
00245
00246
00247
00248 int
00249 SQPsearchDirectionMeritFunctionAndHessian::check(Vector u_old,
00250 double g_old,
00251 Vector grad_G_old,
00252 double stepSize,
00253 Vector stepDirection,
00254 double g_new)
00255 {
00256
00257
00258
00259
00260
00261 int i;
00262
00263
00264 int nrv = u_old.Size();
00265
00266
00267
00268 Vector u_new = u_old + stepSize*stepDirection;
00269
00270
00271
00272 if (alpha == 0.0) {
00273 opserr << "ERROR: SQPsearchDirectionMeritFunctionAndHessian::check()" << endln
00274 << " the alpha factor is not set! " << endln;
00275 }
00276
00277
00278
00279 double tempNewLambda = lambda+stepSize*(kappa-lambda);
00280 double LHS = 0.5*(u_new^u_new) + tempNewLambda*g_new + 0.5*c*g_new*g_new;
00281
00282
00283
00284 double term1 = 0.5*(u_old^u_old) + lambda*g_old + 0.5*c*g_old*g_old;
00285 Vector gradient = u_old + lambda*grad_G_old + (c*g_old)*grad_G_old;
00286 Vector extendedGradient(nrv+1);
00287 for (i=0; i<nrv; i++) {
00288 extendedGradient(i) = gradient(i);
00289 }
00290 extendedGradient(nrv) = g_old;
00291 Vector extendedDirection(nrv+1);
00292 for (i=0; i<nrv; i++) {
00293 extendedDirection(i) = stepDirection(i);
00294 }
00295 extendedDirection(nrv) = (kappa-lambda);
00296
00297
00298 double RHS = term1 + alpha*stepSize*(gradient^stepDirection);
00299
00300
00301 if ( LHS <= RHS ) {
00302 return 0;
00303 }
00304 else {
00305 return -1;
00306 }
00307
00308 }
00309
00310
00311
00312
00313
00314 int
00315 SQPsearchDirectionMeritFunctionAndHessian::setAlpha(double palpha)
00316 {
00317 alpha = palpha;
00318
00319 if (alpha > 0.5) {
00320 opserr << "ERROR: Parameter alpha in SQP algorithm is invalid." << endln;
00321 }
00322
00323 return 0;
00324 }
00325
00326
00327
00328 Matrix
00329 SQPsearchDirectionMeritFunctionAndHessian::getHessianApproximation()
00330 {
00331 return (*B);
00332 }
00333
00334 int
00335 SQPsearchDirectionMeritFunctionAndHessian::updateHessianApproximation(Vector u_old,
00336 double g_old,
00337 Vector gradG_old,
00338 double stepSize,
00339 Vector searchDirection,
00340 double g_new,
00341 Vector gradG_new)
00342 {
00343 if (B == 0) {
00344 this->setHessianToIdentity(u_old.Size());
00345 }
00346
00347
00348 int i,j;
00349
00350
00351 Vector u_new = u_old + stepSize * searchDirection;
00352
00353
00354
00355 Vector gradL_old = u_old + lambda*gradG_old;
00356
00357
00358
00359 lambda = lambda + stepSize * (kappa-lambda);
00360
00361
00362
00363 Vector gradL_new = u_new + lambda*gradG_new;
00364
00365
00366
00367 Vector qPrime = gradL_new - gradL_old;
00368
00369 Vector temp2 = (*B) ^ searchDirection;
00370
00371 double dBd = temp2 ^ searchDirection ;
00372
00373 double dqPrime = searchDirection ^ qPrime;
00374
00375 double theta;
00376 if (dqPrime >= 0.2*stepSize*dBd) {
00377 theta = 1.0;
00378 }
00379 else {
00380 theta = (0.8*stepSize*dBd) / (stepSize*dBd-dqPrime);
00381 }
00382 Vector q = theta*qPrime + (1-theta)*stepSize*((*B)^searchDirection);
00383
00384
00385
00386 Vector Bd = (*B)^searchDirection;
00387 int nrv = Bd.Size();
00388 Matrix Bdd(nrv,nrv);
00389 for (i=0; i<nrv; i++) {
00390 for (j=0; j<nrv; j++) {
00391 Bdd(i,j) = Bd(i)*searchDirection(j);
00392 }
00393 }
00394 Matrix BddB = Bdd*(*B);
00395 Matrix qq(nrv,nrv);
00396 for (i=0; i<nrv; i++) {
00397 for (j=0; j<nrv; j++) {
00398 qq(i,j) = q(i)*q(j);
00399 }
00400 }
00401 Matrix newB = (*B) + 1.0/(stepSize*(q^searchDirection))*(qq) - (1.0/(dBd))*(BddB);
00402 (*B) = newB;
00403
00404
00405 return 0;
00406 }
00407
00408
00409
00410
00411 int
00412 SQPsearchDirectionMeritFunctionAndHessian::setHessianToIdentity(int size)
00413 {
00414
00415
00416 if (B == 0) {
00417 B = new Matrix(size,size);
00418 }
00419
00420
00421 for (int i=0; i<size; i++) {
00422 for (int j=0; j<size; j++) {
00423 if (i==j) {
00424 (*B)(i,j) = 1.0;
00425 }
00426 else {
00427 (*B)(i,j) = 0.0;
00428 }
00429 }
00430 }
00431
00432 return 0;
00433 }