irk_lifted_adjoint_export.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ACADO Toolkit.
3  *
4  * ACADO Toolkit -- A Toolkit for Automatic Control and Dynamic Optimization.
5  * Copyright (C) 2008-2014 by Boris Houska, Hans Joachim Ferreau,
6  * Milan Vukov, Rien Quirynen, KU Leuven.
7  * Developed within the Optimization in Engineering Center (OPTEC)
8  * under supervision of Moritz Diehl. All rights reserved.
9  *
10  * ACADO Toolkit is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * ACADO Toolkit is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with ACADO Toolkit; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 
27 
36 
37 using namespace std;
38 
40 
41 //
42 // PUBLIC MEMBER FUNCTIONS:
43 //
44 
46  const std::string& _commonHeaderName
47  ) : ForwardLiftedIRKExport( _userInteraction,_commonHeaderName )
48 {
49 }
50 
52 {
53 }
54 
55 
57 {
58  if ( solver )
59  delete solver;
60  solver = 0;
61 
62  clear( );
63 }
64 
65 
67 
68  if( this != &arg ){
69 
71  copy( arg );
72  }
73  return *this;
74 }
75 
76 
78 {
79  ExportVariable max;
80  if( NX1 > 0 ) {
82  }
83  if( NX2 > 0 || NXA > 0 ) {
84  if( rhs.getGlobalExportVariable().getDim() >= max.getDim() ) {
86  }
87  if( diffs_rhs.getGlobalExportVariable().getDim() >= max.getDim() ) {
89  }
92  }
93 // if( forward_sweep.getGlobalExportVariable().getDim() >= max.getDim() ) {
94 // max = forward_sweep.getGlobalExportVariable();
95 // }
98  }
99  }
100  if( NX3 > 0 ) {
101  if( rhs3.getGlobalExportVariable().getDim() >= max.getDim() ) {
103  }
104  if( diffs_rhs3.getGlobalExportVariable().getDim() >= max.getDim() ) {
106  }
107  }
108  uint i;
109  for( i = 0; i < outputs.size(); i++ ) {
110  if( outputs[i].getGlobalExportVariable().getDim() >= max.getDim() ) {
111  max = outputs[i].getGlobalExportVariable();
112  }
113  if( diffs_outputs[i].getGlobalExportVariable().getDim() >= max.getDim() ) {
114  max = diffs_outputs[i].getGlobalExportVariable();
115  }
116  }
117  return max;
118 }
119 
120 
122  ExportStruct dataStruct
123  ) const
124 {
125  ForwardLiftedIRKExport::getDataDeclarations( declarations, dataStruct );
126 
127 // declarations.addDeclaration( rk_A_traj,dataStruct );
128 // declarations.addDeclaration( rk_aux_traj,dataStruct );
129 
130  declarations.addDeclaration( rk_S_traj,dataStruct );
131 
132 // declarations.addDeclaration( rk_diffsTemp2_full,dataStruct );
133 
134  return SUCCESSFUL_RETURN;
135 }
136 
137 
139  ) const
140 {
142 
143  return SUCCESSFUL_RETURN;
144 }
145 
146 
148 {
149  int sensGen;
150  get( DYNAMIC_SENSITIVITY,sensGen );
151  if( rhs_.getDim() > 0 ) {
152  OnlineData dummy0;
153  Control dummy1;
154  DifferentialState dummy2;
155  AlgebraicState dummy3;
157  dummy0.clearStaticCounters();
158  dummy1.clearStaticCounters();
159  dummy2.clearStaticCounters();
160  dummy3.clearStaticCounters();
161  dummy4.clearStaticCounters();
162 
163  NX2 = rhs_.getDim() - NXA;
164  x = DifferentialState("", NX1+NX2, 1);
165  z = AlgebraicState("", NXA, 1);
166  u = Control("", NU, 1);
167  od = OnlineData("", NOD, 1);
168 
170  f << rhs_;
171 
172  NDX2 = f.getNDX();
173  if( NDX2 > 0 && (NDX2 < NX2 || NDX2 > (NX1+NX2)) ) {
174  return ACADOERROR( RET_INVALID_OPTION );
175  }
176  else if( NDX2 > 0 ) NDX2 = NX1+NX2;
178 
180  for( uint i = 0; i < rhs_.getDim(); i++ ) {
181  g << forwardDerivative( rhs_(i), x );
182  g << forwardDerivative( rhs_(i), z );
183  g << forwardDerivative( rhs_(i), u );
184  g << forwardDerivative( rhs_(i), dx );
185  }
186 
187 // // FORWARD SWEEP:
188 // DifferentialState sX("", NX,NX+NU);
189 // Expression Gx = sX.getCols(0,NX);
190 // Expression Gu = sX.getCols(NX,NX+NU);
191 // DifferentialEquation forward;
192 // for( uint i = 0; i < rhs_.getDim(); i++ ) {
193 // // NOT YET IMPLEMENTED FOR DAES OR IMPLICIT ODES
194 // if( NDX2 > 0 || NXA > 0 ) return ACADOERROR(RET_NOT_YET_IMPLEMENTED);
195 // forward << multipleForwardDerivative( rhs_(i), x, Gx );
196 // forward << multipleForwardDerivative( rhs_(i), x, Gu ) + forwardDerivative( rhs_(i), u );
197 // }
198 
199  // FIRST ORDER ADJOINT SWEEP:
200  DifferentialState lambda("", NX,1);
201  DifferentialEquation backward, adj_update;
202 // backward << backwardDerivative( rhs_, x, lambda );
203 // adj_update << backwardDerivative( rhs_, x, lambda );
204 
205  if( NDX2 > 0 || NXA > 0 ) return ACADOERROR(RET_NOT_YET_IMPLEMENTED);
206  Expression arg;
207  arg << x;
208  arg << u;
209 
210  DifferentialState sX("", NX,NX+NU);
211  Expression S_tmp = sX;
212  S_tmp.appendRows(zeros<double>(NU,NX).appendCols(eye<double>(NU)));
213 // backward << backwardDerivative( rhs_, arg, lambda );
214 
215  int hessianApproximation;
216  get( HESSIAN_APPROXIMATION, hessianApproximation );
217  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
218 
219  Expression dfS, dfL;
220  Expression symmetric = symmetricDerivative( rhs_, arg, S_tmp, lambda, &dfS, &dfL );
221  backward << dfL.getRows(0,NX+NU);
222  if( secondOrder ) {
223  backward << returnLowerTriangular( symmetric );
224  }
225 
226  int linSolver;
227  get( LINEAR_ALGEBRA_SOLVER, linSolver );
228  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
229  adj_update << backwardDerivative( rhs_, x, lambda );
230  }
231 
232  Expression tmp = zeros<double>(NX,1);
233  tmp.appendRows(backwardDerivative( rhs_, u, lambda ));
234  backward << lambda.transpose()*multipleForwardDerivative( rhs_, x, sX ) + tmp.transpose();
235 
236  if( f.getNT() > 0 ) timeDependant = true;
237 
238  return (rhs.init( f,"acado_rhs",NX,NXA,NU,NP,NDX,NOD ) &
239  diffs_rhs.init( g,"acado_diffs",NX,NXA,NU,NP,NDX,NOD ) &
240  adjoint_sweep.init( backward,"acado_backward",NX*(2+NX+NU),NXA,NU,NP,NDX,NOD ) &
241  diffs_sweep.init( adj_update,"acado_adjoint_update",NX*(2+NX+NU),NXA,NU,NP,NDX,NOD ));
242 // forward_sweep.init( h,"acado_forward",NX*(2+NX+NU),NXA,NU,NP,NDX,NOD ) &
243  }
244  return SUCCESSFUL_RETURN;
245 }
246 
247 
249 // std::cout << "returnLowerTriangular with " << expr.getNumRows() << " rows and " << expr.getNumCols() << " columns\n";
250  ASSERT( expr.getNumRows() == expr.getNumCols() );
251 
252  Expression new_expr;
253  for( uint i = 0; i < expr.getNumRows(); i++ ) {
254  for( uint j = 0; j <= i; j++ ) {
255  new_expr << expr(i,j);
256  }
257  }
258  return new_expr;
259 }
260 
261 
263 {
264  int sensGen;
265  get( DYNAMIC_SENSITIVITY, sensGen );
266  int mode;
267  get( IMPLICIT_INTEGRATOR_MODE, mode );
268 // int liftMode;
269 // get( LIFTED_INTEGRATOR_MODE, liftMode );
272 // if( liftMode != 4 ) ACADOERROR( RET_NOT_IMPLEMENTED_YET );
274 
275  int gradientUp;
276  get( LIFTED_GRADIENT_UPDATE, gradientUp );
277  bool gradientUpdate = (bool) gradientUp;
278  if( !gradientUpdate ) return ACADOERROR( RET_INVALID_OPTION );
279 
280  int hessianApproximation;
281  get( HESSIAN_APPROXIMATION, hessianApproximation );
282  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
283 
284  uint numX = NX*(NX+1)/2.0;
285  uint numU = NU*(NU+1)/2.0;
286  uint symH = 0;
287  if( secondOrder ) symH = numX + numU + NX*NU;
288 
289  // NOTE: liftMode == 4 --> inexact Newton based implementation
290 
292 
293  int useOMP;
294  get(CG_USE_OPENMP, useOMP);
295  if ( useOMP ) ACADOERROR( RET_NOT_IMPLEMENTED_YET );
296 
298 
299  int linSolver;
300  get( LINEAR_ALGEBRA_SOLVER, linSolver );
301  if( exportRhs ) {
302  if( NX2 > 0 || NXA > 0 ) {
303  code.addFunction( rhs );
304  code.addStatement( "\n\n" );
305  code.addFunction( diffs_rhs );
306  code.addStatement( "\n\n" );
307 // if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
308  code.addFunction( diffs_sweep );
309  code.addStatement( "\n\n" );
310 // }
311 // if( liftMode == 4 ) { // ONLY for the inexact Newton based schemes
312  code.addFunction( forward_sweep );
313  code.addStatement( "\n\n" );
314 // }
315  code.addFunction( adjoint_sweep );
316  code.addStatement( "\n\n" );
317  }
318 
320 
322  }
323  if( NX2 > 0 || NXA > 0 ) solver->getCode( code );
324  code.addLinebreak(2);
325 
326  int measGrid;
327  get( MEASUREMENT_GRID, measGrid );
328 
329  // export RK scheme
330  uint run5, run6;
331  std::string tempString;
332 
335 
336  double h = (grid.getLastTime() - grid.getFirstTime())/grid.getNumIntervals();
337  DMatrix tmp = AA;
338  ExportVariable Ah( "Ah_mat", tmp*=h, STATIC_CONST_REAL );
339  code.addDeclaration( Ah );
340  code.addLinebreak( 2 );
341  // TODO: Ask Milan why this does NOT work properly !!
343 
344  DVector BB( bb );
345  ExportVariable Bh( "Bh_mat", DMatrix( BB*=h ) );
346 
347  DVector CC( cc );
348  ExportVariable C;
349  if( timeDependant ) {
350  C = ExportVariable( "C_mat", DMatrix( CC*=(1.0/grid.getNumIntervals()) ), STATIC_CONST_REAL );
351  code.addDeclaration( C );
352  code.addLinebreak( 2 );
354  }
355 
356  code.addComment(std::string("Fixed step size:") + toString(h));
357 
358  ExportVariable determinant( "det", 1, 1, REAL, ACADO_LOCAL, true );
359  integrate.addDeclaration( determinant );
360 
361  ExportIndex i( "i" );
362  ExportIndex j( "j" );
363  ExportIndex k( "k" );
364  ExportIndex run( "run" );
365  ExportIndex run1( "run1" );
366  ExportIndex tmp_index1("tmp_index1");
367  ExportIndex tmp_index2("tmp_index2");
368  ExportIndex tmp_index3("tmp_index3");
369  ExportIndex tmp_index4("tmp_index4");
370  ExportIndex k_index("k_index");
371  ExportIndex shooting_index("shoot_index");
372  ExportVariable tmp_meas("tmp_meas", 1, outputGrids.size(), INT, ACADO_LOCAL);
373 
374  ExportVariable numInt( "numInts", 1, 1, INT );
375  if( !equidistantControlGrid() ) {
376  ExportVariable numStepsV( "numSteps", numSteps, STATIC_CONST_INT );
377  code.addDeclaration( numStepsV );
378  code.addLinebreak( 2 );
379  integrate.addStatement( std::string( "int " ) + numInt.getName() + " = " + numStepsV.getName() + "[" + rk_index.getName() + "];\n" );
380  }
381 
382  prepareOutputEvaluation( code );
383 
384  integrate.addIndex( i );
385  integrate.addIndex( j );
386  integrate.addIndex( k );
387  integrate.addIndex( run );
388  integrate.addIndex( run1 );
389  integrate.addIndex( tmp_index1 );
390  integrate.addIndex( tmp_index2 );
391  integrate.addIndex( tmp_index3 );
392  integrate.addIndex( shooting_index );
393  integrate.addIndex( k_index );
394  if( rk_outputs.size() > 0 && (grid.getNumIntervals() > 1 || !equidistantControlGrid()) ) {
395  integrate.addIndex( tmp_index4 );
396  }
397  integrate << shooting_index.getFullName() << " = " << rk_index.getFullName() << ";\n";
399  if( (inputDim-diffsDim) > NX+NXA ) {
402  }
405 
406  // integrator FORWARD loop:
407  integrate.addComment("------------ Forward loop ------------:");
408  ExportForLoop tmpLoop( run, 0, grid.getNumIntervals() );
409  ExportStatementBlock *loop;
410  if( equidistantControlGrid() ) {
411  loop = &tmpLoop;
412  }
413  else {
414  loop = &integrate;
415  loop->addStatement( std::string("for(") + run.getName() + " = 0; " + run.getName() + " < " + numInt.getName() + "; " + run.getName() + "++ ) {\n" );
416  }
417 
418 // if( grid.getNumIntervals() > 1 || !equidistantControlGrid() ) {
419  // Set rk_diffsPrev:
420  loop->addStatement( std::string("if( run > 0 ) {\n") );
421  if( NX2 > 0 ) {
422  ExportForLoop loopTemp2( i,0,NX2 );
423  loopTemp2.addStatement( rk_diffsPrev2.getSubMatrix( i,i+1,0,NX1+NX2 ) == rk_eta.getCols( i*NX+2*NX+NXA+NX1*NX,i*NX+2*NX+NXA+NX1*NX+NX1+NX2 ) );
424  if( NU > 0 ) loopTemp2.addStatement( rk_diffsPrev2.getSubMatrix( i,i+1,NX1+NX2,NX1+NX2+NU ) == rk_eta.getCols( i*NU+(NX+NXA)*(NX+1)+NX1*NU+NX,i*NU+(NX+NXA)*(NX+1)+NX1*NU+NU+NX ) );
425  loop->addStatement( loopTemp2 );
426  }
427  loop->addStatement( std::string("}\nelse{\n") );
428  DMatrix eyeM = eye<double>(NX);
429  eyeM.appendCols(zeros<double>(NX,NU));
430  loop->addStatement( rk_diffsPrev2 == eyeM );
431  loop->addStatement( std::string("}\n") );
432 // }
433 
434 // if( secondOrder ) {
435  // SAVE rk_diffsPrev2 in the rk_S_traj variable:
436  loop->addStatement( rk_S_traj.getRows(run*NX,(run+1)*NX) == rk_diffsPrev2 );
437 // }
438 
439  loop->addStatement( k_index == (shooting_index*grid.getNumIntervals()+run)*(NX+NXA) );
440 
441  // Evaluate all stage values for reuse:
442  evaluateAllStatesImplicitSystem( loop, k_index, Ah, C, run1, j, tmp_index1 );
443 
444  // SAVE rk_stageValues in the rk_xxx_traj variable:
445  loop->addStatement( rk_xxx_traj.getCols(run*numStages*(NX2+NXA),(run+1)*numStages*(NX2+NXA)) == rk_stageValues );
446 
447  solveImplicitSystem( loop, i, run1, j, tmp_index1, k_index, Ah, C, determinant, true );
448 
449  // SAVE rk_A in the rk_A_traj variable:
450  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
451  // YOU DO NOT NEED TO SAVE THE TRAJECTORY FOR THE INEXACT NEWTON SCHEME !
452 // loop->addStatement( rk_A_traj.getRows(run*(NX2+NXA),(run+1)*(NX2+NXA)) == rk_A );
453 // loop->addStatement( rk_aux_traj.getRow(run) == rk_auxSolver.makeRowVector() );
454  }
455  else {
457 // loop->addStatement( rk_A_traj.getRows(run*numStages*(NX2+NXA),(run+1)*numStages*(NX2+NXA)) == rk_A );
458 // loop->addStatement( rk_aux_traj.getRow(run) == rk_auxSolver.makeRowVector() );
459  }
460 
461 // if( liftMode == 4 ) {
462 // // NEW: more accurate approximation of the derivatives in the right-hand side
463 // for( run5 = 0; run5 < numStages; run5++ ) {
464 // evaluateStatesImplicitSystem( loop, k_index, Ah, C, run5, i, tmp_index1 );
465 // loop->addFunctionCall( getNameDiffsRHS(), rk_xxx, rk_diffsTemp2_full.getAddress(run5,0) );
466 // }
467  evaluateRhsSensitivities( loop, run1, i, j, tmp_index1, tmp_index2 );
468 // if( secondOrder ) {
469  allSensitivitiesImplicitSystem( loop, run1, i, j, tmp_index1, tmp_index2, tmp_index3, ExportIndex(run*(NX+NXA)), Bh, false );
470 // }
471 // else {
472 // allSensitivitiesImplicitSystem( loop, run1, i, j, tmp_index1, tmp_index2, tmp_index3, ExportIndex(0), Bh, false );
473 // }
474 // }
475 // else return ACADOERROR( RET_NOT_IMPLEMENTED_YET );
476 
477  // update rk_kkk:
478  ExportForLoop loopTemp( j,0,numStages );
479  for( run5 = 0; run5 < NX2; run5++ ) {
480  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
481  loopTemp.addStatement( rk_kkk.getElement( k_index+NX1+run5,j ) += rk_b.getElement( j*(NX2+NXA)+run5,0 ) ); // differential states
482  }
483  else {
484  loopTemp.addStatement( rk_kkk.getElement( k_index+NX1+run5,j ) += rk_b.getElement( j*NX2+run5,0 ) ); // differential states
485  }
486  }
487  for( run5 = 0; run5 < NXA; run5++ ) {
488  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
489  loopTemp.addStatement( rk_kkk.getElement( k_index+NX+run5,j ) += rk_b.getElement( j*(NX2+NXA)+NX2+run5,0 ) ); // algebraic states
490  }
491  else {
492  loopTemp.addStatement( rk_kkk.getElement( k_index+NX+run5,j ) += rk_b.getElement( numStages*NX2+j*NXA+run5,0 ) ); // algebraic states
493  }
494  }
495  loop->addStatement( loopTemp );
496 
497  // update rk_eta:
498  for( run5 = 0; run5 < NX; run5++ ) {
499  loop->addStatement( rk_eta.getCol( run5 ) += rk_kkk.getRow( k_index+run5 )*Bh );
500  }
501  if( NXA > 0) {
502  DMatrix tempCoefs( evaluateDerivedPolynomial( 0.0 ) );
503  if( !equidistantControlGrid() || grid.getNumIntervals() > 1 ) {
504  loop->addStatement( std::string("if( run == 0 ) {\n") );
505  }
506  for( run5 = 0; run5 < NXA; run5++ ) {
507  loop->addStatement( rk_eta.getCol( NX+run5 ) == rk_kkk.getRow( k_index+NX+run5 )*tempCoefs );
508  }
509  if( !equidistantControlGrid() || grid.getNumIntervals() > 1 ) {
510  loop->addStatement( std::string("}\n") );
511  }
512  }
513 // if( liftMode != 1 ) { // INEXACT LIFTING
514  // !!! update rk_xxx_lin (YOU NEED TO UPDATE THE LINEARIZATION POINT AFTER YOU UPDATE RK_KKK): !!!
515  loop->addStatement( rk_xxx_lin == rk_eta.getCols(0,NX) );
516 // }
517 
518  // Computation of the sensitivities using the CHAIN RULE:
519  updateImplicitSystem(loop, i, j, tmp_index2);
520 
521 // loop->addStatement( std::string( reset_int.get(0,0) ) + " = 0;\n" );
522 
523  loop->addStatement( rk_ttt += DMatrix(1.0/grid.getNumIntervals()) );
524 
525  // end of the forward integrator loop.
526  if( !equidistantControlGrid() ) {
527  loop->addStatement( "}\n" );
528  }
529  else {
530  integrate.addStatement( *loop );
531  }
532 
533  // COMPUTE THE INEXACT ADJOINT BASED ON LAMBDA AND THE INEXACT SENSITIVITIES:
534  DMatrix zeroL = zeros<double>(1,NX+NU+symH);
535  integrate.addStatement( rk_eta.getCols(NX*(2+NX+NU),NX+diffsDim) == zeroL );
536 // for( run5 = 0; run5 < NX; run5 ++ ) {
537 // integrate.addStatement( rk_eta.getCols(NX*(2+NX+NU)+symH,NX+diffsDim) += rk_eta.getCol(NX+run5)*rk_diffsNew2.getRow(run5) );
538 // }
539 // integrate.addStatement( rk_eta.getCols(NX*(2+NX+NU)+symH,NX+diffsDim-NU) -= rk_eta.getCols(NX,2*NX) );
540 
541  // integrator BACKWARD loop:
542  integrate.addComment("------------ BACKWARD loop ------------:");
543  ExportForLoop tmpLoop2( run, grid.getNumIntervals()-1, -1, -1 );
544  ExportStatementBlock *loop2;
545  if( equidistantControlGrid() ) {
546  loop2 = &tmpLoop2;
547  }
548  else {
550  }
551 
552  loop2->addStatement( k_index == run*(NX+NXA)*(NX+NU) );
553 
554 
555  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) { // INEXACT
556  // Compute \hat{lambda}:
557  // vec(j*NX+1:j*NX+NX) = -Bh_vec(j+1)*dir_tmp;
558  for( run5 = 0; run5 < numStages; run5++ ) {
559  DMatrix zeroV = zeros<double>(1,NX);
560  loop2->addStatement( rk_b_trans.getCols(run5*NX,(run5+1)*NX) == zeroV );
561  loop2->addStatement( rk_b_trans.getCols(run5*NX,(run5+1)*NX) -= Bh.getRow(run5)*rk_eta.getCols(NX,2*NX) );
562  }
563  loop2->addStatement( tmp_index1 == shooting_index*grid.getNumIntervals()+run );
564  for( run5 = 0; run5 < numStages; run5++ ) {
565  loop2->addStatement( rk_seed.getCols(0,NX) == rk_xxx_traj.getCols((run*numStages+run5)*(NX2+NXA),(run*numStages+run5+1)*(NX2+NXA)) );
566  loop2->addStatement( rk_seed.getCols(NX,2*NX) == rk_adj_traj.getSubMatrix(tmp_index1,tmp_index1+1,run5*(NX+NXA),(run5+1)*(NX+NXA)) );
567  loop2->addFunctionCall( diffs_sweep.getName(), rk_seed, rk_adj_diffs_tmp );
568  for( run6 = 0; run6 < numStages; run6++ ) {
569  loop2->addStatement( rk_b_trans.getCols(run6*NX,(run6+1)*NX) -= Ah.getElement(run5,run6)*rk_adj_diffs_tmp.getCols(0,NX) );
570  }
571  loop2->addStatement( rk_b_trans.getCols(run5*NX,(run5+1)*NX) += rk_adj_traj.getSubMatrix(tmp_index1,tmp_index1+1,run5*(NX+NXA),(run5+1)*(NX+NXA)) ); // BECAUSE EXPLICIT ODE
572  }
574  loop2->addStatement( rk_adj_traj.getRow(tmp_index1) += rk_b_trans );
575 // loop2->addStatement( rk_b_trans == rk_adj_traj.getRow(tmp_index1) );
576  }
577  else return ACADOERROR( RET_NOT_IMPLEMENTED_YET );
578 
579  for( run5 = 0; run5 < numStages; run5++ ) {
580  loop2->addStatement( rk_seed.getCols(0,NX) == rk_xxx_traj.getCols((run*numStages+run5)*(NX2+NXA),(run*numStages+run5+1)*(NX2+NXA)) );
581  loop2->addStatement( rk_seed.getCols(NX,2*NX) == rk_adj_traj.getSubMatrix(tmp_index1,tmp_index1+1,run5*NX,(run5+1)*NX) );
582 // if( secondOrder ) {
583  loop2->addStatement( rk_diffsPrev2 == rk_S_traj.getRows(run*NX,(run+1)*NX) );
584 
585  ExportForLoop diffLoop1( i, 0, NX );
586  diffLoop1.addStatement( tmp_index2 == k_index+i*(NX+NU) );
587  ExportForLoop diffLoop2( j, 0, NX+NU );
588  diffLoop2.addStatement( tmp_index3 == tmp_index2+j );
589  for( run6 = 0; run6 < numStages; run6++ ) {
590  diffLoop2.addStatement( rk_diffsPrev2.getElement(i,j) += Ah.getElement(run5,run6)*rk_diffK.getElement( tmp_index3,run6 ) );
591  }
592 
593  // >>>>>>>>>>>> GRADIENT CORRECTION
594  diffLoop2.addStatement( rk_eta.getCol(NX*(2+NX+NU)+symH+j) += rk_adj_traj.getElement(tmp_index1,run5*NX+i)*rk_diffK.getElement( tmp_index3,run5 ) );
595  // GRADIENT CORRECTION <<<<<<<<<<
596 
597  diffLoop1.addStatement( diffLoop2 );
598  loop2->addStatement( diffLoop1 );
599 
600  loop2->addStatement( rk_seed.getCols(2*NX,NX*(2+NX+NU)) == rk_diffsPrev2.makeRowVector() );
601 // }
602  loop2->addFunctionCall( adjoint_sweep.getName(), rk_seed, rk_adj_diffs_tmp.getAddress(0,0) );
603  loop2->addStatement( rk_eta.getCols(NX,2*NX) += rk_adj_diffs_tmp.getCols(0,NX) );
604 // loop2->addStatement( rk_eta.getCols(NX*(2+NX+NU)+symH,NX+diffsDim) -= rk_adj_diffs_tmp.getCols(0,NX+NU) );
605  if( secondOrder ) {
606  loop2->addStatement( rk_eta.getCols(NX*(2+NX+NU),NX*(2+NX+NU)+symH) += rk_adj_diffs_tmp.getCols(NX+NU,NX+NU+symH) );
607  }
608 
609  // >>>>>>>>>>>> GRADIENT CORRECTION
610 // loop2->addFunctionCall( forward_sweep.getName(), rk_seed, rk_adj_diffs_tmp.getAddress(0,0) );
611  loop2->addStatement( rk_eta.getCols(NX*(2+NX+NU)+symH,NX+diffsDim) -= rk_adj_diffs_tmp.getCols(NX+NU+symH,NX+NU+symH+NX+NU) );
612  // GRADIENT CORRECTION <<<<<<<<<<
613  }
614 
615  loop2->addStatement( rk_ttt -= DMatrix(1.0/grid.getNumIntervals()) );
616  // end of the backward integrator loop.
617  if( !equidistantControlGrid() ) {
619  }
620  else {
621  integrate.addStatement( *loop2 );
622  }
623 
624 // integrate.addStatement( std::string( "if( " ) + determinant.getFullName() + " < 1e-12 ) {\n" );
625 // integrate.addStatement( error_code == 2 );
626 // integrate.addStatement( std::string( "} else if( " ) + determinant.getFullName() + " < 1e-6 ) {\n" );
627 // integrate.addStatement( error_code == 1 );
628 // integrate.addStatement( std::string( "} else {\n" ) );
630 // integrate.addStatement( std::string( "}\n" ) );
631 
632  code.addFunction( integrate );
633  code.addLinebreak( 2 );
634 
635  return SUCCESSFUL_RETURN;
636 }
637 
638 
639 returnValue AdjointLiftedIRKExport::evaluateRhsSensitivities( ExportStatementBlock* block, const ExportIndex& index1, const ExportIndex& index2, const ExportIndex& index3, const ExportIndex& tmp_index1, const ExportIndex& tmp_index2 )
640 {
641  if( NX2 > 0 ) {
642  ExportForLoop loop1( index2,0,numStages );
643  ExportForLoop loop2( index3,0,NX2+NXA );
644  loop2.addStatement( tmp_index1 == index2*(NX2+NXA)+index3 );
645  ExportForLoop loop3( index1,0,NX2 );
646  loop3.addStatement( rk_b.getElement( tmp_index1,1+index1 ) == 0.0 - rk_diffsTemp2.getElement( index3,index1 ) );
647  loop2.addStatement( loop3 );
648 
649  ExportForLoop loop4( index1,0,NU );
650  loop4.addStatement( rk_b.getElement( tmp_index1,1+NX+index1 ) == 0.0 - rk_diffsTemp2.getElement( index3,NX1+NX2+NXA+index1 ) );
651  loop2.addStatement( loop4 );
652  loop1.addStatement( loop2 );
653  block->addStatement( loop1 );
654 
655 // // TODO: THIS IS AN ALTERNATIVE IMPLEMENTATION WITH MORE ACCURATE DERIVATIVE EVALUATIONS:
656 // ExportForLoop loop1( index2,0,numStages );
657 // ExportForLoop loop2( index3,0,NX2+NXA );
658 // loop2.addStatement( tmp_index1 == index2*(NX2+NXA)+index3 );
659 // ExportForLoop loop3( index1,0,NX2 );
660 // loop3.addStatement( tmp_index2 == index1+index3*(NVARS2) );
661 // loop3.addStatement( rk_b.getElement( tmp_index1,1+index1 ) == 0.0 - rk_diffsTemp2_full.getElement( index2,tmp_index2 ) );
662 // loop2.addStatement( loop3 );
663 //
664 // ExportForLoop loop4( index1,0,NU );
665 // loop4.addStatement( tmp_index2 == index1+index3*(NVARS2)+NX1+NX2+NXA );
666 // loop4.addStatement( rk_b.getElement( tmp_index1,1+NX+index1 ) == 0.0 - rk_diffsTemp2_full.getElement( index2,tmp_index2 ) );
667 // loop2.addStatement( loop4 );
668 // loop1.addStatement( loop2 );
669 // block->addStatement( loop1 );
670  }
671 
672  return SUCCESSFUL_RETURN;
673 }
674 
675 
677 {
678  if( NX2 > 0 ) {
679  ExportForLoop loop01( index1,NX1,NX1+NX2 );
680  ExportForLoop loop02( index2,0,NX1+NX2 );
681  loop02.addStatement( tmp_index == index2+index1*NX );
682  loop02.addStatement( rk_eta.getCol( tmp_index+2*NX+NXA ) == rk_diffsNew2.getSubMatrix( index1-NX1,index1-NX1+1,index2,index2+1 ) );
683  loop01.addStatement( loop02 );
684 
685  if( NU > 0 ) {
686  ExportForLoop loop03( index2,0,NU );
687  loop03.addStatement( tmp_index == index2+index1*NU );
688  loop03.addStatement( rk_eta.getCol( tmp_index+(NX+NXA)*(1+NX)+NX ) == rk_diffsNew2.getSubMatrix( index1-NX1,index1-NX1+1,NX1+NX2+index2,NX1+NX2+index2+1 ) );
689  loop01.addStatement( loop03 );
690  }
691  block->addStatement( loop01 );
692  }
693  // ALGEBRAIC STATES
694  if( NXA > 0 ) {
696  }
697 
698  return SUCCESSFUL_RETURN;
699 }
700 
701 
703 {
705 
706  uint numX = NX*(NX+1)/2.0;
707  uint numU = NU*(NU+1)/2.0;
708 
709  int hessianApproximation;
710  get( HESSIAN_APPROXIMATION, hessianApproximation );
711  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
712 
713  uint symH = 0;
714  if( secondOrder ) symH = numX + numU + NX*NU;
715  diffsDim = NX + NX*(NX+NU) + NX+NU + symH;
716  inputDim = NX + diffsDim + NU + NOD;
717 
718  int useOMP;
719  get(CG_USE_OPENMP, useOMP);
720  ExportStruct structWspace;
721  structWspace = useOMP ? ACADO_LOCAL : ACADO_WORKSPACE;
722 
723  uint timeDep = 0;
724  if( timeDependant ) timeDep = 1;
725 
726  rk_eta = ExportVariable( "rk_eta", 1, inputDim, REAL );
727 
728  rk_b_trans = ExportVariable( "rk_b_trans", 1, numStages*(NX+NXA), REAL, structWspace );
729 
730  rk_adj_diffs_tmp = ExportVariable( "rk_adjoint", 1, NX+NU+symH+NX+NU, REAL, structWspace );
731 
732 // if( secondOrder ) {
733  rk_S_traj = ExportVariable( "rk_S_traj", grid.getNumIntervals()*NX, NX+NU, REAL, structWspace );
734 // }
735 
736 // int liftMode;
737 // get( LIFTED_INTEGRATOR_MODE, liftMode );
738 
739  rk_seed = ExportVariable( "rk_seed", 1, NX*(2+NX+NU)+NU+NOD+timeDep, REAL, structWspace );
740 // rk_A_traj = ExportVariable( "rk_A_traj", grid.getNumIntervals()*numStages*(NX2+NXA), numStages*(NX2+NXA), REAL, structWspace );
741 // rk_aux_traj = ExportVariable( "rk_aux_traj", grid.getNumIntervals(), numStages*(NX2+NXA), INT, structWspace );
742  rk_xxx_traj = ExportVariable( "rk_stageV_traj", 1, grid.getNumIntervals()*numStages*(NX+NXA), REAL, structWspace );
743 
744  // THIS IS CRUCIAL FOR THE ADJOINT SCHEME WHICH DOES NOT SAVE THE SENSITIVITIES OF THE K VARIABLES!!!
745 // rk_diffK = ExportVariable( "rk_diffK", (NX+NXA)*(NX+NU), numStages, REAL, structWspace );
746 // if( secondOrder ) {
747  rk_diffK = ExportVariable( "rk_diffK_traj", grid.getNumIntervals()*(NX+NXA)*(NX+NU), numStages, REAL, structWspace );
748 // }
749  rk_diffK_local = ExportVariable( "rk_diffKtraj_aux", (NX+NXA)*(NX+NU), numStages, REAL, structWspace );
750 
751  int linSolver;
752  get( LINEAR_ALGEBRA_SOLVER, linSolver );
753  if( (LinearAlgebraSolver) linSolver == SIMPLIFIED_IRK_NEWTON || (LinearAlgebraSolver) linSolver == SINGLE_IRK_NEWTON ) {
754 // rk_A = ExportVariable( "rk_J", NX2+NXA, NX2+NXA, REAL, structWspace );
755 // if(NDX2 > 0) rk_I = ExportVariable( "rk_I", NX2+NXA, NX2+NXA, REAL, structWspace );
756 // rk_A_traj = ExportVariable( "rk_J_traj", grid.getNumIntervals()*(NX2+NXA), NX2+NXA, REAL, structWspace );
757 // rk_aux_traj = ExportVariable( "rk_aux_traj", grid.getNumIntervals(), rk_auxSolver.getNumRows()*rk_auxSolver.getNumCols(), INT, structWspace );
758  rk_diffsTemp2 = ExportVariable( "rk_diffsTemp2", NX2+NXA, NVARS2, REAL, structWspace );
759  }
760  else {
761  return ACADOERROR( RET_INVALID_OPTION );
762  }
763 // rk_diffsTemp2_full = ExportVariable( "rk_diffsTemp2_full", numStages, (NX2+NXA)*(NVARS2), REAL, structWspace );
765 
766  return SUCCESSFUL_RETURN;
767 }
768 
769 
770 
771 // PROTECTED:
772 
773 
775 
776 // end of file.
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
HessianApproximationMode
Expression symmetricDerivative(const Expression &arg1, const Expression &arg2, const Expression &forward_seed, const Expression &backward_seed, Expression *forward_result, Expression *backward_result)
Allows to export a tailored lifted implicit Runge-Kutta integrator with forward sensitivity generatio...
virtual returnValue allSensitivitiesImplicitSystem(ExportStatementBlock *block, const ExportIndex &index1, const ExportIndex &index2, const ExportIndex &index3, const ExportIndex &tmp_index1, const ExportIndex &tmp_index2, const ExportIndex &tmp_index3, const ExportIndex &k_index, const ExportVariable &Bh, bool update)
ExportVariable getRow(const ExportIndex &idx) const
ExportVariable rk_diffK
Definition: irk_export.hpp:571
Expression backwardDerivative(const Expression &arg1, const Expression &arg2)
const std::string getNameSolveTransposeReuseFunction()
returnValue initializeDDMatrix()
Definition: irk_export.cpp:864
ExportVariable getGlobalExportVariable() const
virtual returnValue setDifferentialEquation(const Expression &rhs)
double getFirstTime() const
AdjointLiftedIRKExport & operator=(const AdjointLiftedIRKExport &arg)
LinearAlgebraSolver
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) const
GenericMatrix & appendCols(const GenericMatrix &_arg)
Definition: matrix.cpp:83
std::vector< Grid > outputGrids
ExportAcadoFunction diffs_rhs
int getNDX() const
Definition: function.cpp:217
virtual returnValue solveImplicitSystem(ExportStatementBlock *block, const ExportIndex &index1, const ExportIndex &index2, const ExportIndex &index3, const ExportIndex &tmp_index, const ExportIndex &k_index, const ExportVariable &Ah, const ExportVariable &C, const ExportVariable &det, bool DERIVATIVES=false)
ExportVariable rk_index
virtual returnValue evaluateRhsSensitivities(ExportStatementBlock *block, const ExportIndex &index1, const ExportIndex &index2, const ExportIndex &index3, const ExportIndex &tmp_index1, const ExportIndex &tmp_index2)
std::vector< ExportAcadoFunction > outputs
Allows to pass back messages to the calling function.
ExportVariable rk_kkk
Definition: rk_export.hpp:189
DifferentialState x
returnValue initializeCoefficients()
Definition: irk_export.cpp:883
Expression forwardDerivative(const Expression &arg1, const Expression &arg2)
ExportLinearSolver * solver
Definition: irk_export.hpp:530
uint getNumCols() const
uint getNumRows() const
returnValue addComment(const std::string &_comment)
Block< Derived > block(Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition: BlockMethods.h:56
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
std::vector< ExportAcadoFunction > diffs_outputs
ExportVariable rk_diffsPrev2
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
Allows to export code of a for-loop.
string toString(T const &value)
ImplicitIntegratorMode
ExportVariable getElement(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
ExportVariable rk_diffsTemp2
#define CLOSE_NAMESPACE_ACADO
ExportVariable getSubMatrix(const ExportIndex &rowIdx1, const ExportIndex &rowIdx2, const ExportIndex &colIdx1, const ExportIndex &colIdx2) const
GenericMatrix< double > DMatrix
Definition: matrix.hpp:457
Defines a scalar-valued index variable to be used for exporting code.
Expression returnLowerTriangular(const Expression &expr)
ExportAcadoFunction rhs3
virtual returnValue copy(const ImplicitRungeKuttaExport &arg)
Base class for all variables within the symbolic expressions family.
Definition: expression.hpp:56
virtual returnValue getCode(ExportStatementBlock &code)
ExportVariable rk_eta
ExportAcadoFunction diffs_rhs3
ExportStruct
DVector evaluateDerivedPolynomial(double time)
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
Expression multipleForwardDerivative(const Expression &arg1, const Expression &arg2, const Expression &seed)
ExportVariable rk_auxSolver
Definition: irk_export.hpp:563
ExportVariable getAuxVariable() const
ExportVariable makeRowVector() const
AdjointLiftedIRKExport(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
Expression & appendRows(const Expression &arg)
Definition: expression.cpp:141
Encapsulates all user interaction for setting options, logging data and plotting results.
virtual uint getDim() const
returnValue addStatement(const ExportStatement &_statement)
int getNT() const
Definition: function.cpp:251
ExportFunction integrate
std::string getFullName() const
Expression transpose() const
Definition: expression.cpp:811
returnValue addLinebreak(uint num=1)
virtual returnValue evaluateAllStatesImplicitSystem(ExportStatementBlock *block, const ExportIndex &k_index, const ExportVariable &Ah, const ExportVariable &C, const ExportIndex &stage, const ExportIndex &i, const ExportIndex &tmp_index)
#define ASSERT(x)
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) const
ExportVariable rk_diffsNew2
uint getNumIntervals() const
returnValue prepareOutputEvaluation(ExportStatementBlock &code)
ExportVariable rk_xxx
DifferentialStateDerivative dx
std::string getName() const
ExportVariable getRows(const ExportIndex &idx1, const ExportIndex &idx2) const
returnValue addDeclaration(const ExportVariable &_data, ExportStruct _dataStruct=ACADO_ANY)
ExportAcadoFunction lin_input
double getLastTime() const
ExportVariable rk_ttt
std::vector< ExportVariable > rk_outputs
Definition: irk_export.hpp:552
#define BEGIN_NAMESPACE_ACADO
ExportVariable error_code
returnValue clearStaticCounters()
Definition: expression.hpp:398
returnValue addFunction(const ExportFunction &_function)
virtual returnValue clear()
virtual returnValue getCode(ExportStatementBlock &code)=0
virtual returnValue updateImplicitSystem(ExportStatementBlock *block, const ExportIndex &index1, const ExportIndex &index2, const ExportIndex &tmp_index)
Allows to export code for a block of statements.
Expression getRows(const uint &rowIdx1, const uint &rowIdx2) const
Definition: expression.cpp:548
ExportArgument getAddress(const ExportIndex &_rowIdx, const ExportIndex &_colIdx=emptyConstExportIndex) const
ExportVariable getCol(const ExportIndex &idx) const
returnValue init(const Function &_f, const std::string &_name="acadoFcn", const uint _numX=0, const uint _numXA=0, const uint _numU=0, const uint _numP=0, const uint _numDX=0, const uint _numOD=0)
ExportFunction & addIndex(const ExportIndex &_index)
#define ACADOERROR(retval)
virtual bool equidistantControlGrid() const
ForwardLiftedIRKExport & operator=(const ForwardLiftedIRKExport &arg)
Defines a matrix-valued variable to be used for exporting code.
ExportAcadoFunction rhs
Allows to export a tailored lifted implicit Runge-Kutta integrator with adjoint sensitivity generatio...
Allows to setup and evaluate differential equations (ODEs and DAEs) based on SymbolicExpressions.
std::string getName() const
Definition: export_data.cpp:86
uint getDim() const


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:34:43