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/optimization_algorithm/multi_objective_algorithm.hpp>
00035 #include <acado/ocp/ocp.hpp>
00036
00037 BEGIN_NAMESPACE_ACADO
00038
00039
00040
00041
00042
00043
00044
00045 MultiObjectiveAlgorithm::MultiObjectiveAlgorithm()
00046 :OptimizationAlgorithm(){
00047
00048 m = 0;
00049 N = 0;
00050 count = 0;
00051 totalNumberOfSQPiterations = 0;
00052 totalCPUtime = 0;
00053
00054 xResults = 0;
00055 xaResults = 0;
00056 pResults = 0;
00057 uResults = 0;
00058 wResults = 0;
00059
00060 setupOptions( );
00061 }
00062
00063
00064 MultiObjectiveAlgorithm::MultiObjectiveAlgorithm( const OCP& ocp_ )
00065 :OptimizationAlgorithm( ocp_ ){
00066
00067 m = ocp->getNumberOfMayerTerms();
00068 N = 0;
00069 count = 0;
00070 totalNumberOfSQPiterations = 0;
00071 totalCPUtime = 0;
00072
00073 xResults = 0;
00074 xaResults = 0;
00075 pResults = 0;
00076 uResults = 0;
00077 wResults = 0;
00078
00079 setupOptions( );
00080 }
00081
00082
00083 MultiObjectiveAlgorithm::MultiObjectiveAlgorithm( const MultiObjectiveAlgorithm& arg )
00084 :OptimizationAlgorithm( arg )
00085 {
00086
00087 m = arg.m;
00088 N = arg.N;
00089
00090 vertices = arg.vertices;
00091 result = arg.result ;
00092
00093 count = arg.count;
00094
00095 totalNumberOfSQPiterations = arg.totalNumberOfSQPiterations;
00096 totalCPUtime = arg.totalCPUtime ;
00097
00098 xResults = 0;
00099 xaResults = 0;
00100 pResults = 0;
00101 uResults = 0;
00102 wResults = 0;
00103 }
00104
00105
00106 MultiObjectiveAlgorithm::~MultiObjectiveAlgorithm( ){
00107
00108 if( xResults != 0 ) delete[] xResults ;
00109 if( xaResults != 0 ) delete[] xaResults;
00110 if( pResults != 0 ) delete[] pResults ;
00111 if( uResults != 0 ) delete[] uResults ;
00112 if( wResults != 0 ) delete[] wResults ;
00113 }
00114
00115
00116 MultiObjectiveAlgorithm& MultiObjectiveAlgorithm::operator=( const MultiObjectiveAlgorithm& arg ){
00117
00118 if( this != &arg ){
00119
00120 OptimizationAlgorithm ::operator=(arg);
00121
00122 m = arg.m;
00123 N = arg.N;
00124
00125 vertices = arg.vertices;
00126 result = arg.result ;
00127 count = arg.count;
00128
00129 totalNumberOfSQPiterations = arg.totalNumberOfSQPiterations;
00130 totalCPUtime = arg.totalCPUtime ;
00131
00132 xResults = 0;
00133 xaResults = 0;
00134 pResults = 0;
00135 uResults = 0;
00136 wResults = 0;
00137 }
00138 return *this;
00139 }
00140
00141
00142 returnValue MultiObjectiveAlgorithm::solveSingleObjective( const int &number_ ){
00143
00144
00145 int run1 ;
00146 returnValue returnvalue;
00147
00148 ASSERT( ocp != 0 );
00149 ASSERT( number_ < m );
00150 if( N == 0 ) get( PARETO_FRONT_DISCRETIZATION, N );
00151
00152 int N_pow_m_minus_1 = 1;
00153 int i;
00154 for(i=0; i<m-1; i++)
00155 N_pow_m_minus_1 *= N;
00156
00157 Expression **arg = 0;
00158 arg = new Expression*[m];
00159 for( run1 = 0; run1 < m; run1++ )
00160 ocp->getObjective( run1, &arg[run1] );
00161
00162 Grid tmp_grid;
00163 ocp->getGrid( tmp_grid );
00164 Objective tmp(tmp_grid);
00165 tmp.addMayerTerm(*arg[number_]);
00166 ocp->setObjective( tmp );
00167
00168 setStatus( BS_NOT_INITIALIZED );
00169
00170 printf("\n\n Optimization of individual objective %d out of %d \n\n",number_ +1, m );
00171 totalCPUtime = -acadoGetTime();
00172 returnvalue = OptimizationAlgorithm::solve();
00173 totalCPUtime += acadoGetTime();
00174
00175 int index=0;
00176 DMatrix Weights = getWeights();
00177
00178 for( run1 = 0; run1 < (int) Weights.getNumCols(); run1++ ){
00179 if( fabs( Weights( number_, run1 ) - 1.0 ) < 1000.0*EPS )
00180 index = run1;
00181 }
00182
00183 if( xResults == 0 ) xResults = new VariablesGrid[Weights.getNumCols()];
00184 if( xaResults == 0 ) xaResults = new VariablesGrid[Weights.getNumCols()];
00185 if( pResults == 0 ) pResults = new VariablesGrid[Weights.getNumCols()];
00186 if( uResults == 0 ) uResults = new VariablesGrid[Weights.getNumCols()];
00187 if( wResults == 0 ) wResults = new VariablesGrid[Weights.getNumCols()];
00188
00189 getDifferentialStates( xResults[index] );
00190 getAlgebraicStates ( xaResults[index] );
00191 getParameters ( pResults[index] );
00192 getControls ( uResults[index] );
00193 getDisturbances ( wResults[index] );
00194
00195
00196 if( returnvalue != SUCCESSFUL_RETURN )
00197 return ACADOERROR(returnvalue);
00198
00199 if( nlpSolver != 0 )
00200 totalNumberOfSQPiterations = nlpSolver->getNumberOfSteps();
00201
00202 int hotstart;
00203 get( PARETO_FRONT_HOTSTART, hotstart );
00204
00205 int *indices = new int[m];
00206 for( run1 = 0; run1 < m; run1++ )
00207 indices[run1] = number_;
00208
00209 VariablesGrid xd_tmp, xa_tmp, p_tmp, u_tmp, w_tmp;
00210
00211 if( hotstart == BT_TRUE ){
00212 getDifferentialStates( *userInit.x );
00213 getAlgebraicStates ( *userInit.xa );
00214 getParameters ( *userInit.p );
00215 getControls ( *userInit.u );
00216 getDisturbances ( *userInit.w );
00217 xd_tmp = *userInit.x;
00218 xa_tmp = *userInit.xa;
00219 p_tmp = *userInit.p;
00220 u_tmp = *userInit.u;
00221 w_tmp = *userInit.w;
00222 }
00223 else{
00224 getDifferentialStates( xd_tmp );
00225 getAlgebraicStates ( xa_tmp );
00226 getParameters ( p_tmp );
00227 getControls ( u_tmp );
00228 getDisturbances ( w_tmp );
00229 }
00230
00231 VariablesGrid *_xd = 0;
00232 VariablesGrid *_xa = 0;
00233 VariablesGrid *_p = 0;
00234 VariablesGrid *_u = 0;
00235 VariablesGrid *_w = 0;
00236
00237 if( xd_tmp.isEmpty() == BT_FALSE ) _xd = new VariablesGrid(xd_tmp);
00238 if( xa_tmp.isEmpty() == BT_FALSE ) _xa = new VariablesGrid(xa_tmp);
00239 if( p_tmp.isEmpty() == BT_FALSE ) _p = new VariablesGrid(p_tmp );
00240 if( u_tmp.isEmpty() == BT_FALSE ) _u = new VariablesGrid(u_tmp );
00241 if( w_tmp.isEmpty() == BT_FALSE ) _w = new VariablesGrid(w_tmp );
00242
00243 if( vertices.getDim() == 0 ){
00244 vertices.init(m,m);
00245 vertices.setAll(-INFTY);
00246 }
00247
00248 Objective **obj = new Objective*[m];
00249 for( run1 = 0; run1 < m; run1++ ){
00250 obj[run1] = new Objective( tmp_grid );
00251 obj[run1]->addMayerTerm(*arg[run1]);
00252 OCPiterate xx( _xd, _xa, _p, _u, _w );
00253 obj[run1]->evaluate( xx );
00254 obj[run1]->getObjectiveValue( vertices(number_,run1) );
00255 }
00256
00257 if( _xd != 0 ) delete _xd;
00258 if( _xa != 0 ) delete _xa;
00259 if( _p != 0 ) delete _p ;
00260 if( _u != 0 ) delete _u ;
00261 if( _w != 0 ) delete _w ;
00262
00263
00264 delete[] indices;
00265
00266 for( run1 = 0; run1 < m; run1++ )
00267 delete arg[run1];
00268 delete[] arg;
00269
00270 for( run1 = 0; run1 < m; run1++ )
00271 delete obj[run1];
00272 delete[] obj;
00273
00274 return SUCCESSFUL_RETURN;
00275 }
00276
00277
00278 returnValue MultiObjectiveAlgorithm::solve( ){
00279
00280 int run1,run2;
00281 returnValue returnvalue;
00282
00283 ASSERT( ocp != 0 );
00284 ASSERT( m >= 2 );
00285 if( N == 0 ) get( PARETO_FRONT_DISCRETIZATION, N );
00286
00287 int paretoGeneration;
00288 get( PARETO_FRONT_GENERATION, paretoGeneration );
00289
00290 int hotstart;
00291 get( PARETO_FRONT_HOTSTART, hotstart );
00292
00293 Expression **arg = 0;
00294 arg = new Expression*[m];
00295
00296 for( run1 = 0; run1 < m; run1++ )
00297 ocp->getObjective( run1, &arg[run1] );
00298
00299 Constraint tmp_con;
00300
00301 double *idx = new double[m];
00302
00303 WeightGeneration generator;
00304 DMatrix Weights;
00305 DVector formers;
00306 DVector lb(m);
00307 DVector ub(m);
00308 lb.setZero();
00309 ub.setAll(1.0);
00310
00311 generator.getWeights( m, N, lb, ub, Weights, formers );
00312
00313 result.init( Weights.getNumCols(), m );
00314 count = 0;
00315
00316 if( xResults == 0 ) xResults = new VariablesGrid[Weights.getNumCols()];
00317 if( xaResults == 0 ) xaResults = new VariablesGrid[Weights.getNumCols()];
00318 if( pResults == 0 ) pResults = new VariablesGrid[Weights.getNumCols()];
00319 if( uResults == 0 ) uResults = new VariablesGrid[Weights.getNumCols()];
00320 if( wResults == 0 ) wResults = new VariablesGrid[Weights.getNumCols()];
00321
00322 totalNumberOfSQPiterations = 0;
00323 totalCPUtime = -acadoGetTime();
00324
00325 run1 = 0;
00326 while( run1 < (int) Weights.getNumCols() ){
00327
00328
00329
00330
00331 printf("\n\n Multi-objective point: %d out of %d \n\n",run1+1, (int) Weights.getNumCols() );
00332
00333
00334 ocp->getConstraint( tmp_con );
00335
00336 for( run2 = 0; run2 < (int) Weights.getNumRows(); run2++ )
00337 idx[run2] = Weights( run2, run1 );
00338
00339
00340
00341
00342 int vertex = -1;
00343 for( run2 = 0; run2 < m; run2++ ){
00344 if( fabs( idx[run2]-1.0 ) < 100.0*EPS )
00345 vertex = run2;
00346 }
00347
00348
00349
00350 if( vertex == -1 || paretoGeneration == PFG_WEIGHTED_SUM ){
00351
00352 formulateOCP( idx, ocp, arg );
00353 setStatus( BS_NOT_INITIALIZED );
00354 returnvalue = OptimizationAlgorithm::solve();
00355
00356 if( nlpSolver != 0 )
00357 totalNumberOfSQPiterations += nlpSolver->getNumberOfSteps();
00358
00359 ocp->setConstraint( tmp_con );
00360 set( PRINT_COPYRIGHT, BT_FALSE );
00361
00362 if( returnvalue != SUCCESSFUL_RETURN ){
00363 ACADOERROR(returnvalue);
00364 }
00365 else{
00366
00367 getDifferentialStates( xResults[run1] );
00368 getAlgebraicStates ( xaResults[run1] );
00369 getParameters ( pResults[run1] );
00370 getControls ( uResults[run1] );
00371 getDisturbances ( wResults[run1] );
00372
00373 if( hotstart == BT_TRUE ){
00374 getDifferentialStates( *userInit.x );
00375 getAlgebraicStates ( *userInit.xa );
00376 getParameters ( *userInit.p );
00377 getControls ( *userInit.u );
00378 getDisturbances ( *userInit.w );
00379 evaluateObjectives( *userInit.x, *userInit.xa, *userInit.p, *userInit.u, *userInit.w, arg );
00380 }
00381 else{
00382 VariablesGrid xd_tmp, xa_tmp, p_tmp, u_tmp, w_tmp;
00383 getDifferentialStates( xd_tmp );
00384 getAlgebraicStates ( xa_tmp );
00385 getParameters ( p_tmp );
00386 getControls ( u_tmp );
00387 getDisturbances ( w_tmp );
00388 evaluateObjectives( xd_tmp, xa_tmp, p_tmp, u_tmp, w_tmp, arg );
00389 }
00390 }
00391 }
00392 else{
00393 printf(" Result from single objective optimization is adopted. \n\n" );
00394 for( run2 = 0; run2 < m; run2++ ){
00395 result(count,run2) = vertices(vertex,run2);
00396 }
00397 count++;
00398 }
00399 run1++;
00400 }
00401 totalCPUtime += acadoGetTime();
00402
00403 for( run1 = 0; run1 < m; run1++ )
00404 delete arg[run1];
00405 delete[] arg;
00406
00407 delete[] idx;
00408
00409 return SUCCESSFUL_RETURN;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418 returnValue MultiObjectiveAlgorithm::setupOptions( )
00419 {
00420 addOption( PARETO_FRONT_DISCRETIZATION , defaultParetoFrontDiscretization );
00421 addOption( PARETO_FRONT_GENERATION , defaultParetoFrontGeneration );
00422 addOption( PARETO_FRONT_HOTSTART , defaultParetoFrontHotstart );
00423
00424
00425
00426
00427 return SUCCESSFUL_RETURN;
00428 }
00429
00430
00431 returnValue MultiObjectiveAlgorithm::initializeNlpSolver( const OCPiterate& _userInit )
00432 {
00433 return OptimizationAlgorithm::initializeNlpSolver( _userInit );
00434 }
00435
00436
00437 returnValue MultiObjectiveAlgorithm::initializeObjective( Objective* F
00438 )
00439 {
00440 return SUCCESSFUL_RETURN;
00441 }
00442
00443
00444
00445
00446 returnValue MultiObjectiveAlgorithm::formulateOCP( double *idx, OCP *ocp_, Expression **arg ){
00447
00448 int run1, run2;
00449 int paretoGeneration;
00450 double factor;
00451
00452 get( PARETO_FRONT_GENERATION, paretoGeneration );
00453 if( paretoGeneration == PFG_UNKNOWN ) paretoGeneration = PFG_WEIGHTED_SUM;
00454
00455 Grid tmp_grid;
00456 ocp_->getGrid( tmp_grid );
00457 Objective tmp(tmp_grid);
00458
00459
00460
00461
00462
00463 if( paretoGeneration == PFG_WEIGHTED_SUM ){
00464
00465 Expression sum(1);
00466
00467 for( run1 = 0; run1 < m; run1++ ){
00468 factor = idx[run1];
00469 sum = sum + arg[run1][0]*factor;
00470 }
00471 tmp.addMayerTerm(sum);
00472 ocp_->setObjective(tmp);
00473 return SUCCESSFUL_RETURN;
00474 }
00475
00476
00477
00478
00479
00480 if( paretoGeneration == PFG_NORMALIZED_NORMAL_CONSTRAINT ){
00481
00482
00483
00484
00485
00486 DMatrix P = getNormalizedPayOffMatrix();
00487 DMatrix NK = getUtopiaPlaneVectors ();
00488
00489 DVector W(m);
00490 for( run1 = 0; run1 < m; run1++ )
00491 W(run1) = idx[run1];
00492
00493 DVector PW = P*W;
00494
00495 DVector U = getUtopiaVector();
00496 DVector L = getNormalizationVector();
00497
00498 Expression *Fnorm;
00499 Fnorm = new Expression[m];
00500
00501 for( run2 = 0; run2 < m; run2++ ){
00502
00503 Fnorm[run2] = ( *arg[run2] - U(run2) ) / L(run2);
00504 }
00505
00506 tmp.addMayerTerm( Fnorm[m-1] );
00507 ocp_->setObjective( tmp );
00508
00509 for( run1 = 0; run1 < m-1; run1++ ){
00510 Expression sum(1);
00511 for( run2 = 0; run2 < m; run2++ ){
00512
00513 sum = sum + NK(run2,run1)*( Fnorm[run2] - PW(run2) );
00514 }
00515 ocp_->subjectTo( AT_END, sum <= 0.0 );
00516 }
00517 delete[] Fnorm;
00518
00519 return SUCCESSFUL_RETURN;
00520 }
00521
00522
00523
00524
00525
00526 if( paretoGeneration == PFG_ENHANCED_NORMALIZED_NORMAL_CONSTRAINT ){
00527
00528
00529 DMatrix P = getPayOffMatrix();
00530 DMatrix PHI_N(m,m);
00531
00532 int run3, run4;
00533 for( run3 = 0; run3 < m; run3++ ){
00534 for( run4 = 0; run4 < m; run4++ ){
00535 PHI_N(run3,run4) = 1.0;
00536 }
00537 }
00538 for( run3 = 0; run3 < m; run3++ )
00539 PHI_N(run3,run3) = 0.0;
00540
00541 DMatrix T;
00542 T = PHI_N * P.inverse();
00543
00544 DMatrix NK(m,m-1);
00545 NK.setZero();
00546
00547 for( run3 = 0; run3 < m-1; run3++ )
00548 NK(run3,run3) = 1.0;
00549
00550 for( run3 = 0; run3 < m-1; run3++ )
00551 NK(m-1,run3) = -1.0;
00552
00553
00554 DVector W(m);
00555 for( run1 = 0; run1 < m; run1++ )
00556 W(run1) = idx[run1];
00557
00558 DVector PW = PHI_N*W;
00559
00560 DVector U = getUtopiaVector();
00561
00562 Expression *Fnorm;
00563 Fnorm = new Expression[m];
00564
00565 for( run2 = 0; run2 < m; run2++ ){
00566 Expression tmp3(1);
00567 for( run3 = 0; run3 < m; run3++ ){
00568 tmp3 = tmp3 + T(run2,run3)*( *arg[run3]- U(run3) );
00569 }
00570 Fnorm[run2] = tmp3;
00571 }
00572
00573 tmp.addMayerTerm( Fnorm[m-1] );
00574 ocp_->setObjective( tmp );
00575
00576 for( run1 = 0; run1 < m-1; run1++ ){
00577
00578 Expression sum(1);
00579
00580 for( run2 = 0; run2 < m; run2++ ){
00581
00582 sum = sum + NK(run2,run1)*( Fnorm[run2] - PW(run2) );
00583 }
00584 ocp_->subjectTo( AT_END, sum <= 0.0 );
00585 }
00586 delete[] Fnorm;
00587
00588 return SUCCESSFUL_RETURN;
00589 }
00590
00591
00592
00593
00594
00595 if( paretoGeneration == PFG_NORMAL_BOUNDARY_INTERSECTION ){
00596
00597 DVector W(m);
00598 for( run1 = 0; run1 < m; run1++ )
00599 W(run1) = idx[run1];
00600
00601 DMatrix P = getPayOffMatrix();
00602 DVector U = getUtopiaVector();
00603 DVector V = P*W + U;
00604 W.setAll( 1.0 );
00605 DVector X = P*W;
00606
00607 Expression lambda;
00608
00609 lambda = ( *arg[m-1] - V(m-1) )/ X(m-1);
00610
00611 tmp.addMayerTerm( *arg[m-1] );
00612 ocp_->setObjective( tmp );
00613
00614 for( run1 = 0; run1 < m-1; run1++ )
00615 ocp->subjectTo( AT_END, *arg[run1] - lambda*X(run1) == V(run1) );
00616
00617 return SUCCESSFUL_RETURN;
00618 }
00619 return SUCCESSFUL_RETURN;
00620 }
00621
00622
00623 returnValue MultiObjectiveAlgorithm::evaluateObjectives( VariablesGrid &xd_ ,
00624 VariablesGrid &xa_ ,
00625 VariablesGrid &p_ ,
00626 VariablesGrid &u_ ,
00627 VariablesGrid &w_ ,
00628 Expression **arg ){
00629
00630 int run1;
00631 Grid tmp_grid;
00632 ocp->getGrid( tmp_grid );
00633
00634 VariablesGrid *_xd = 0;
00635 VariablesGrid *_xa = 0;
00636 VariablesGrid *_p = 0;
00637 VariablesGrid *_u = 0;
00638 VariablesGrid *_w = 0;
00639
00640 if( xd_.isEmpty() == BT_FALSE ) _xd = new VariablesGrid(xd_);
00641 if( xa_.isEmpty() == BT_FALSE ) _xa = new VariablesGrid(xa_);
00642 if( p_.isEmpty() == BT_FALSE ) _p = new VariablesGrid(p_ );
00643 if( u_.isEmpty() == BT_FALSE ) _u = new VariablesGrid(u_ );
00644 if( w_.isEmpty() == BT_FALSE ) _w = new VariablesGrid(w_ );
00645
00646 Objective *obj;
00647 for( run1 = 0; run1 < m; run1++ ){
00648 obj = new Objective( tmp_grid );
00649 obj->addMayerTerm(*arg[run1]);
00650 OCPiterate xx( _xd, _xa, _p, _u, _w );
00651 obj->evaluate( xx );
00652 obj->getObjectiveValue( result(count,run1) );
00653 delete obj;
00654 }
00655 count++;
00656
00657 if( _xd != 0 ) delete _xd;
00658 if( _xa != 0 ) delete _xa;
00659 if( _p != 0 ) delete _p ;
00660 if( _u != 0 ) delete _u ;
00661 if( _w != 0 ) delete _w ;
00662
00663 return SUCCESSFUL_RETURN;
00664 }
00665
00666
00667
00668 CLOSE_NAMESPACE_ACADO
00669
00670