erk_fob_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  ) : AdjointERKExport( _userInteraction,_commonHeaderName )
48 {
49 }
50 
51 
53  ) : AdjointERKExport( arg )
54 {
55 }
56 
57 
59 {
60  clear( );
61 }
62 
63 
64 
66 {
67  int sensGen;
68  get( DYNAMIC_SENSITIVITY,sensGen );
69 
70  OnlineData dummy0;
71  Control dummy1;
72  DifferentialState dummy2;
73  AlgebraicState dummy3;
75  dummy0.clearStaticCounters();
76  dummy1.clearStaticCounters();
77  dummy2.clearStaticCounters();
78  dummy3.clearStaticCounters();
79  dummy4.clearStaticCounters();
80 
81  x = DifferentialState("", NX, 1);
83  z = AlgebraicState("", NXA, 1);
84  u = Control("", NU, 1);
85  od = OnlineData("", NOD, 1);
86 
87  if( NDX > 0 && NDX != NX ) {
89  }
90  if( rhs_.getNumRows() != (NX+NXA) ) {
92  }
93 
94  uint numX = NX*(NX+1)/2.0;
95  uint numU = NU*(NU+1)/2.0;
96  if ( (ExportSensitivityType)sensGen == FORWARD_OVER_BACKWARD ) {
97  numX = NX*NX;
98  numU = NU*NU;
99  }
100 
101  DifferentialEquation f, g, f_ODE;
102  // add usual ODE
103  f_ODE << rhs_;
104  if( f_ODE.getNDX() > 0 ) {
105  return ACADOERROR( RET_INVALID_OPTION );
106  }
107 
109  DifferentialState Gx("", NX,NX), Gu("", NX,NU);
110  // no free parameters yet!
111  // DifferentialState Gp(NX,NP);
112 
113  f << rhs_;
114  /* if ( f.getDim() != f.getNX() )
115  return ACADOERROR( RET_ILLFORMED_ODE );*/
116 
117  Expression arg;
118  arg << x;
119  arg << u;
120  Expression S_tmp = Gx;
121  S_tmp.appendCols( Gu );
122  S_tmp.appendRows(zeros<double>(NU,NX).appendCols(eye<double>(NU)));
123  Expression dfS = multipleForwardDerivative( rhs_, arg, S_tmp );
124  // add VDE for differential states
125  f << dfS.getCols(0,NX);
126 // f << multipleForwardDerivative( rhs_, x, Gx );
127  /* if ( f.getDim() != f.getNX() )
128  return ACADOERROR( RET_ILLFORMED_ODE );*/
129 
130  // add VDE for control inputs
131  f << dfS.getCols(NX,NX+NU);
132 // f << multipleForwardDerivative( rhs_, x, Gu ) + forwardDerivative( rhs_, u );
133  // if ( f.getDim() != f.getNX() )
134  // return ACADOERROR( RET_ILLFORMED_ODE );
135 
136  // no free parameters yet!
137  // f << forwardDerivative( rhs_, x ) * Gp + forwardDerivative( rhs_, p );
138 
139 
140  DifferentialState lx("", NX,1);
141 
142  if( (ExportSensitivityType)sensGen == FORWARD_OVER_BACKWARD ) {
143  Expression tmp = backwardDerivative( rhs_, arg, lx );
144 
145  g << tmp.getRows(0,NX);
146 
147  Expression tmp2 = multipleForwardDerivative( tmp, arg, S_tmp );
148 
149  DifferentialState Sxx("", NX,NX), Sux("", NU,NX), Suu("", NU,NU);
150  Expression SS_tmp = Sxx;
151  SS_tmp.appendCols( Sux.transpose() );
152  Expression tmp3 = multipleBackwardDerivative( rhs_, arg, SS_tmp );
153 
154  g << tmp2.getSubMatrix(0,NX,0,NX) + tmp3.getSubMatrix(0,NX,0,NX);
155  g << tmp2.getSubMatrix(0,NX,NX,NX+NU).transpose() + tmp3.getSubMatrix(0,NX,NX,NX+NU).transpose();
156  g << tmp2.getSubMatrix(NX,NX+NU,NX,NX+NU) + tmp3.getSubMatrix(NX,NX+NU,NX,NX+NU);
157  }
158  else {
159  // SYMMETRIC DERIVATIVES
160  Expression dfS2, dfL;
161  Expression h_tmp = symmetricDerivative( rhs_, arg, S_tmp, lx, &dfS2, &dfL );
162  g << dfL.getRows(0,NX);
163  g << returnLowerTriangular( h_tmp );
164  }
165 
166 // g << multipleForwardDerivative(tmp, x, Gx) + multipleBackwardDerivative(rhs_, x, Sxx);
167 // g << multipleBackwardDerivative(tmp, x, Gu).transpose() + forwardDerivative(tmp, u).transpose() + multipleBackwardDerivative(rhs_, x, Sux.transpose()).transpose();
168 // g << forwardDerivative(backwardDerivative(rhs_, u, lx), u) + multipleBackwardDerivative(tmp, u, Gu) + multipleBackwardDerivative(rhs_, u, Sux.transpose());
169  }
170  else {
171  return ACADOERROR( RET_INVALID_OPTION );
172  }
173  if( f.getNT() > 0 ) timeDependant = true;
174 
175  return rhs.init(f, "acado_forward", NX*(NX+NU+1), 0, NU, NP, NDX, NOD)
176  & diffs_rhs.init(g, "acado_backward", NX*(NX+NU+1) + NX + numX + NX*NU + numU, 0, NU, NP, NDX, NOD);
177 }
178 
179 
181 {
182  int sensGen;
183  get( DYNAMIC_SENSITIVITY,sensGen );
185 
186  // NOT SUPPORTED: since the forward sweep needs to be saved
188 
189  // NOT SUPPORTED: since the adjoint derivatives could be 'arbitrarily bad'
191 
192  LOG( LVL_DEBUG ) << "Preparing to export ForwardOverBackwardERKExport... " << endl;
193 
194  // export RK scheme
195  uint numX = NX*(NX+1)/2.0;
196  uint numU = NU*(NU+1)/2.0;
197  if ( (ExportSensitivityType)sensGen == FORWARD_OVER_BACKWARD ) {
198  numX = NX*NX;
199  numU = NU*NU;
200  }
201  uint rhsDim = NX*(NX+NU+1) + NX + numX + NX*NU + numU;
202  inputDim = rhsDim + NU + NOD;
203  const uint rkOrder = getNumStages();
204 
205  double h = (grid.getLastTime() - grid.getFirstTime())/grid.getNumIntervals();
206 
207  ExportVariable Ah ( "A*h", DMatrix( AA )*=h );
208  ExportVariable b4h( "b4*h", DMatrix( bb )*=h );
209 
210  rk_index = ExportVariable( "rk_index", 1, 1, INT, ACADO_LOCAL, true );
211  rk_eta = ExportVariable( "rk_eta", 1, inputDim );
212 // seed_backward.setup( "seed", 1, NX );
213 
214  int useOMP;
215  get(CG_USE_OPENMP, useOMP);
216  ExportStruct structWspace;
217  structWspace = useOMP ? ACADO_LOCAL : ACADO_WORKSPACE;
218 
219  rk_ttt.setup( "rk_ttt", 1, 1, REAL, structWspace, true );
220  uint timeDep = 0;
221  if( timeDependant ) timeDep = 1;
222 
223  rk_xxx.setup("rk_xxx", 1, inputDim+timeDep, REAL, structWspace);
224  rk_kkk.setup("rk_kkk", rkOrder, NX+numX+NX*NU+numU, REAL, structWspace);
225  if(NX*(NX+NU) > numX+NX*NU+numU) rk_kkk.setup("rk_kkk", rkOrder, NX+NX*(NX+NU), REAL, structWspace);
226  rk_forward_sweep.setup("rk_sweep1", 1, grid.getNumIntervals()*rkOrder*NX*(NX+NU+1), REAL, structWspace);
227 
228  if ( useOMP )
229  {
230  ExportVariable auxVar;
231 
232  auxVar = getAuxVariable();
233  auxVar.setName( "odeAuxVar" );
234  auxVar.setDataStruct( ACADO_LOCAL );
235  rhs.setGlobalExportVariable( auxVar );
237  }
238 
239  ExportIndex run( "run1" );
240 
241  // setup INTEGRATE function
242  integrate = ExportFunction( "integrate", rk_eta, reset_int );
244  rk_eta.setDoc( "Working array to pass the input values and return the results." );
245  reset_int.setDoc( "The internal memory of the integrator can be reset." );
246  rk_index.setDoc( "Number of the shooting interval." );
247  error_code.setDoc( "Status code of the integrator." );
248  integrate.doc( "Performs the integration and sensitivity propagation for one shooting interval." );
249  integrate.addIndex( run );
250 
252 
253 
254  // initialize sensitivities:
255  DMatrix idX = eye<double>( NX );
256  DMatrix zeroXU = zeros<double>( NX,NU );
257  integrate.addStatement( rk_eta.getCols( 2*NX,NX*(2+NX) ) == idX.makeVector().transpose() );
258  integrate.addStatement( rk_eta.getCols( NX*(2+NX),NX*(2+NX+NU) ) == zeroXU.makeVector().transpose() );
259 
260 // integrate.addStatement( rk_eta.getCols( NX*(1+NX+NU),NX*(2+NX+NU) ) == seed_backward );
261  integrate.addStatement( rk_eta.getCols( NX*(2+NX+NU),rhsDim ) == zeros<double>( 1,numX+NX*NU+numU ) );
262  if( inputDim > rhsDim ) {
263  // FORWARD SWEEP FIRST
264  integrate.addStatement( rk_xxx.getCols( NX*(1+NX+NU),NX*(1+NX+NU)+NU+NOD ) == rk_eta.getCols( rhsDim,inputDim ) );
265  }
267 
268  // integrator loop: FORWARD SWEEP
269  ExportForLoop loop = ExportForLoop( run, 0, grid.getNumIntervals() );
270  for( uint run1 = 0; run1 < rkOrder; run1++ )
271  {
272  loop.addStatement( rk_xxx.getCols( 0,NX ) == rk_eta.getCols( 0,NX ) + Ah.getRow(run1)*rk_kkk.getCols( 0,NX ) );
273  loop.addStatement( rk_xxx.getCols( NX,NX*(1+NX+NU) ) == rk_eta.getCols( 2*NX,NX*(2+NX+NU) ) + Ah.getRow(run1)*rk_kkk.getCols( NX,NX*(1+NX+NU) ) );
274  // save forward trajectory
275  loop.addStatement( rk_forward_sweep.getCols( run*rkOrder*NX*(1+NX+NU)+run1*NX*(1+NX+NU),run*rkOrder*NX*(1+NX+NU)+(run1+1)*NX*(1+NX+NU) ) == rk_xxx.getCols( 0,NX*(1+NX+NU) ) );
276  if( timeDependant ) loop.addStatement( rk_xxx.getCol( NX*(NX+NU+1)+NU+NOD ) == rk_ttt + ((double)cc(run1))/grid.getNumIntervals() );
278  }
279  loop.addStatement( rk_eta.getCols( 0,NX ) += b4h^rk_kkk.getCols( 0,NX ) );
280  loop.addStatement( rk_eta.getCols( NX*2,NX*(2+NX+NU) ) += b4h^rk_kkk.getCols( NX,NX*(1+NX+NU) ) );
281  loop.addStatement( rk_ttt += DMatrix(1.0/grid.getNumIntervals()) );
282  // end of integrator loop: FORWARD SWEEP
283  integrate.addStatement( loop );
284 
285  if( inputDim > rhsDim ) {
286  // BACKWARD SWEEP NEXT
287  integrate.addStatement( rk_xxx.getCols( rhsDim,inputDim ) == rk_eta.getCols( rhsDim,inputDim ) );
288  }
289  // integrator loop: BACKWARD SWEEP
290  ExportForLoop loop2 = ExportForLoop( run, 0, grid.getNumIntervals() );
291  for( uint run1 = 0; run1 < rkOrder; run1++ )
292  {
293  // load forward trajectory
294  loop2.addStatement( rk_xxx.getCols( 0,NX*(1+NX+NU) ) == rk_forward_sweep.getCols( (grid.getNumIntervals()-run)*rkOrder*NX*(1+NX+NU)-(run1+1)*NX*(1+NX+NU),(grid.getNumIntervals()-run)*rkOrder*NX*(1+NX+NU)-run1*NX*(1+NX+NU) ) );
295  loop2.addStatement( rk_xxx.getCols( NX*(1+NX+NU),NX*(2+NX+NU) ) == rk_eta.getCols( NX,NX*2 ) + Ah.getRow(run1)*rk_kkk.getCols(0,NX) );
296  loop2.addStatement( rk_xxx.getCols( NX*(2+NX+NU),rhsDim ) == rk_eta.getCols( NX*(2+NX+NU),rhsDim ) + Ah.getRow(run1)*rk_kkk.getCols(NX,NX+numX+NX*NU+numU) );
297  if( timeDependant ) loop2.addStatement( rk_xxx.getCol( inputDim ) == rk_ttt - ((double)cc(run1))/grid.getNumIntervals() );
299  }
300  loop2.addStatement( rk_eta.getCols( NX,2*NX ) += b4h^rk_kkk.getCols(0,NX) );
301  loop2.addStatement( rk_eta.getCols( NX*(2+NX+NU),rhsDim ) += b4h^rk_kkk.getCols(NX,NX+numX+NX*NU+numU) );
302  loop2.addStatement( rk_ttt -= DMatrix(1.0/grid.getNumIntervals()) );
303  // end of integrator loop: BACKWARD SWEEP
304  integrate.addStatement( loop2 );
305 
307 
308  LOG( LVL_DEBUG ) << "done" << endl;
309 
310  return SUCCESSFUL_RETURN;
311 }
312 
313 
315 // std::cout << "returnLowerTriangular with " << expr.getNumRows() << " rows and " << expr.getNumCols() << " columns\n";
316  ASSERT( expr.getNumRows() == expr.getNumCols() );
317 
318  Expression new_expr;
319  for( uint i = 0; i < expr.getNumRows(); i++ ) {
320  for( uint j = 0; j <= i; j++ ) {
321  new_expr << expr(i,j);
322  }
323  }
324  return new_expr;
325 }
326 
327 
328 // PROTECTED:
329 
330 
331 
333 
334 // end of file.
#define LOG(level)
Just define a handy macro for getting the logger.
Lowest level, the debug level.
Expression symmetricDerivative(const Expression &arg1, const Expression &arg2, const Expression &forward_seed, const Expression &backward_seed, Expression *forward_result, Expression *backward_result)
virtual returnValue setDifferentialEquation(const Expression &rhs)
ExportVariable getRow(const ExportIndex &idx) const
Expression backwardDerivative(const Expression &arg1, const Expression &arg2)
double getFirstTime() const
ExportVariable & setup(const std::string &_name, uint _nRows=1, uint _nCols=1, ExportType _type=REAL, ExportStruct _dataStruct=ACADO_LOCAL, bool _callItByValue=false, const std::string &_prefix=std::string())
virtual returnValue setup()
ExportAcadoFunction diffs_rhs
int getNDX() const
Definition: function.cpp:217
ExportVariable rk_index
virtual ExportVariable getAuxVariable() const
Definition: erk_export.cpp:386
Allows to pass back messages to the calling function.
ExportVariable rk_kkk
Definition: rk_export.hpp:189
ForwardOverBackwardERKExport(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
GenericMatrix & makeVector()
Definition: matrix.cpp:124
DifferentialState x
uint getNumCols() const
uint getNumRows() const
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
Allows to export code of a for-loop.
Expression getCols(const uint &colIdx1, const uint &colIdx2) const
Definition: expression.cpp:582
returnValue setName(const std::string &_name)
Definition: export_data.cpp:61
#define CLOSE_NAMESPACE_ACADO
GenericMatrix< double > DMatrix
Definition: matrix.hpp:457
const std::string getNameDiffsRHS() const
Defines a scalar-valued index variable to be used for exporting code.
Base class for all variables within the symbolic expressions family.
Definition: expression.hpp:56
virtual returnValue setDoc(const std::string &_doc)
ExportVariable rk_eta
ExportStruct
Expression returnLowerTriangular(const Expression &expr)
virtual ExportFunction & doc(const std::string &_doc)
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
Expression multipleForwardDerivative(const Expression &arg1, const Expression &arg2, const Expression &seed)
const std::string getNameRHS() const
ExportVariable reset_int
ExportVariable rk_forward_sweep
Expression & appendRows(const Expression &arg)
Definition: expression.cpp:141
Encapsulates all user interaction for setting options, logging data and plotting results.
Allows to export code of an arbitrary function.
returnValue setDataStruct(ExportStruct _dataStruct)
Definition: export_data.cpp:80
returnValue addStatement(const ExportStatement &_statement)
int getNT() const
Definition: function.cpp:251
ExportFunction integrate
Expression transpose() const
Definition: expression.cpp:811
returnValue addLinebreak(uint num=1)
#define ASSERT(x)
ExportFunction & setReturnValue(const ExportVariable &_functionReturnValue, bool _returnAsPointer=false)
uint getNumIntervals() const
returnValue setGlobalExportVariable(const ExportVariable &var)
ExportVariable rk_xxx
DifferentialStateDerivative dx
double getLastTime() const
ExportVariable rk_ttt
Expression getSubMatrix(const uint &rowIdx1, const uint &rowIdx2, const uint &colIdx1, const uint &colIdx2) const
Definition: expression.cpp:601
#define BEGIN_NAMESPACE_ACADO
ExportVariable error_code
returnValue clearStaticCounters()
Definition: expression.hpp:398
Allows to export a tailored explicit Runge-Kutta integrator with forward-over-backward second order s...
Expression & appendCols(const Expression &arg)
Definition: expression.cpp:162
virtual returnValue clear()
Expression multipleBackwardDerivative(const Expression &arg1, const Expression &arg2, const Expression &seed)
Expression getRows(const uint &rowIdx1, const uint &rowIdx2) const
Definition: expression.cpp:548
Allows to export a tailored explicit Runge-Kutta integrator with adjoint first order sensitivity prop...
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
Defines a matrix-valued variable to be used for exporting code.
ExportAcadoFunction rhs
returnValue addFunctionCall(const std::string &_fName, const ExportArgument &_argument1=emptyConstExportArgument, const ExportArgument &_argument2=emptyConstExportArgument, const ExportArgument &_argument3=emptyConstExportArgument, const ExportArgument &_argument4=emptyConstExportArgument, const ExportArgument &_argument5=emptyConstExportArgument, const ExportArgument &_argument6=emptyConstExportArgument, const ExportArgument &_argument7=emptyConstExportArgument, const ExportArgument &_argument8=emptyConstExportArgument, const ExportArgument &_argument9=emptyConstExportArgument)
Allows to setup and evaluate differential equations (ODEs and DAEs) based on SymbolicExpressions.
BooleanType is_symmetric
Definition: rk_export.hpp:194


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