export_gauss_newton_cn2.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 
35 
36 using namespace std;
37 
39 
41  const std::string& _commonHeaderName
42  ) : ExportNLPSolver( _userInteraction,_commonHeaderName )
43 {}
44 
46 {
47  if (performFullCondensing() == true && initialStateFixed() == false)
48  return ACADOERRORTEXT( RET_INVALID_OPTION, "Impossible to perform full condensing, when the initial state is not fixed. You can use regular condensing instead." );
49  if (performFullCondensing() == false && initialStateFixed() == true)
51  if (performsSingleShooting() == true)
53 
54  LOG( LVL_DEBUG ) << "Solver: setup initialization... " << endl;
56  LOG( LVL_DEBUG ) << "done!" << endl;
57 
58  LOG( LVL_DEBUG ) << "Solver: setup variables... " << endl;
60  LOG( LVL_DEBUG ) << "done!" << endl;
61 
62  LOG( LVL_DEBUG ) << "Solver: setup multiplication routines... " << endl;
64  LOG( LVL_DEBUG ) << "done!" << endl;
65 
66  LOG( LVL_DEBUG ) << "Solver: setup model simulation... " << endl;
68  LOG( LVL_DEBUG ) << "done!" << endl;
69 
70  LOG( LVL_DEBUG ) << "Solver: setup objective evaluation... " << endl;
72  LOG( LVL_DEBUG ) << "done!" << endl;
73 
74  LOG( LVL_DEBUG ) << "Solver: setup condensing... " << endl;
76  LOG( LVL_DEBUG ) << "done!" << endl;
77 
78  LOG( LVL_DEBUG ) << "Solver: setup constraints... " << endl;
80  LOG( LVL_DEBUG ) << "done!" << endl;
81 
82  LOG( LVL_DEBUG ) << "Solver: setup evaluation... " << endl;
84  LOG( LVL_DEBUG ) << "done!" << endl;
85 
86  LOG( LVL_DEBUG ) << "Solver: setup auxiliary functions... " << endl;
88  LOG( LVL_DEBUG ) << "done!" << endl;
89 
90  return SUCCESSFUL_RETURN;
91 }
92 
94  ExportStruct dataStruct
95  ) const
96 {
97  ExportNLPSolver::getDataDeclarations(declarations, dataStruct);
98 
99  declarations.addDeclaration(sbar, dataStruct);
100  declarations.addDeclaration(x0, dataStruct);
101  declarations.addDeclaration(Dx0, dataStruct);
102 
103  declarations.addDeclaration(T1, dataStruct);
104  declarations.addDeclaration(T2, dataStruct);
105  declarations.addDeclaration(C, dataStruct);
106 
107  declarations.addDeclaration(W1, dataStruct);
108  declarations.addDeclaration(W2, dataStruct);
109  declarations.addDeclaration(E, dataStruct);
110 
111  declarations.addDeclaration(QDy, dataStruct);
112  declarations.addDeclaration(w1, dataStruct);
113  declarations.addDeclaration(w2, dataStruct);
114 
115  declarations.addDeclaration(lbValues, dataStruct);
116  declarations.addDeclaration(ubValues, dataStruct);
117  declarations.addDeclaration(lbAValues, dataStruct);
118  declarations.addDeclaration(ubAValues, dataStruct);
119 
120 // if (performFullCondensing() == true)
121 // declarations.addDeclaration(A10, dataStruct);
122 // declarations.addDeclaration(A20, dataStruct);
123 
124  declarations.addDeclaration(pacA01Dx0, dataStruct);
125  declarations.addDeclaration(pocA02Dx0, dataStruct);
126 
127  declarations.addDeclaration(H, dataStruct);
128  declarations.addDeclaration(A, dataStruct);
129  declarations.addDeclaration(g, dataStruct);
130  declarations.addDeclaration(lb, dataStruct);
131  declarations.addDeclaration(ub, dataStruct);
132  declarations.addDeclaration(lbA, dataStruct);
133  declarations.addDeclaration(ubA, dataStruct);
134  declarations.addDeclaration(xVars, dataStruct);
135  declarations.addDeclaration(yVars, dataStruct);
136 
137  // lagrange multipliers
138  declarations.addDeclaration(mu, dataStruct);
139 
140  return SUCCESSFUL_RETURN;
141 }
142 
144  ) const
145 {
146  declarations.addDeclaration( preparation );
147  declarations.addDeclaration( feedback );
148 
149  declarations.addDeclaration( initialize );
150  declarations.addDeclaration( initializeNodes );
151  declarations.addDeclaration( shiftStates );
152  declarations.addDeclaration( shiftControls );
153  declarations.addDeclaration( getKKT );
154  declarations.addDeclaration( getObjective );
155 
156  declarations.addDeclaration( evaluateStageCost );
157  declarations.addDeclaration( evaluateTerminalCost );
158 
159  return SUCCESSFUL_RETURN;
160 }
161 
163  )
164 {
166 
167  code.addLinebreak( 2 );
168  code.addStatement( "/******************************************************************************/\n" );
169  code.addStatement( "/* */\n" );
170  code.addStatement( "/* ACADO code generation */\n" );
171  code.addStatement( "/* */\n" );
172  code.addStatement( "/******************************************************************************/\n" );
173  code.addLinebreak( 2 );
174 
175  int useOMP;
176  get(CG_USE_OPENMP, useOMP);
177  if ( useOMP )
178  {
179  code.addDeclaration( state );
180  }
181 
183 
186 
188 
189  for (unsigned i = 0; i < evaluatePointConstraints.size(); ++i)
190  {
191  if (evaluatePointConstraints[ i ] == 0)
192  continue;
194  }
195 
196  code.addFunction( setObjQ1Q2 );
197  code.addFunction( setObjR1R2 );
198  code.addFunction( setObjS1 );
199  code.addFunction( setObjQN1QN2 );
201 
203 
204  code.addFunction( moveGxT );
205  code.addFunction( multGxGx );
206  code.addFunction( multGxGu );
207  code.addFunction( moveGuE );
208 
209  code.addFunction( multBTW1 );
210  code.addFunction( mac_S1T_E );
211  code.addFunction( macBTW1_R1 );
212  code.addFunction( multGxTGu );
213  code.addFunction( macQEW2 );
214 
215  code.addFunction( macATw1QDy );
216  code.addFunction( macBTw1 );
217  code.addFunction( macS1TSbar );
218  code.addFunction( macQSbarW2 );
219  code.addFunction( macASbar );
220  code.addFunction( expansionStep );
221 
222  code.addFunction( expansionStep2 );
223 
224  code.addFunction( mult_BT_T1 );
225  code.addFunction( mac_ST_C );
226  code.addFunction( multGxTGx );
227  code.addFunction( macGxTGx );
228 
229  code.addFunction( copyHTH );
230  code.addFunction( copyHTH1 );
231 
232  code.addFunction( multRDy );
233  code.addFunction( multQDy );
234 
235  code.addFunction( multQN1Gx );
236  code.addFunction( multQN1Gu );
237 
238  code.addFunction( multHxC );
239  code.addFunction( multHxE );
240  code.addFunction( macHxd );
241 
242  code.addFunction( condensePrep );
243  code.addFunction( condenseFdb );
244  code.addFunction( expand );
245 
246  code.addFunction( preparation );
247  code.addFunction( feedback );
248 
249  code.addFunction( initialize );
251  code.addFunction( shiftStates );
252  code.addFunction( shiftControls );
253  code.addFunction( getKKT );
254  code.addFunction( getObjective );
255 
256  return SUCCESSFUL_RETURN;
257 }
258 
259 
261 {
262  if (performFullCondensing() == true)
263  return (N * NU);
264 
265  return (NX + N * NU);
266 }
267 
269 {
270  return xBoundsIdx.size();
271 }
272 
273 //
274 // PROTECTED FUNCTIONS:
275 //
276 
278 {
279  evaluateObjective.setup("evaluateObjective");
280 
281  int variableObjS;
282  get(CG_USE_VARIABLE_WEIGHTING_MATRIX, variableObjS);
283 
284  //
285  // A loop the evaluates objective and corresponding gradients
286  //
287  ExportIndex runObj( "runObj" );
288  ExportForLoop loopObjective(runObj, 0, N);
289 
290  evaluateObjective.addIndex( runObj );
291 
292  loopObjective.addStatement( objValueIn.getCols(0, getNX()) == x.getRow( runObj ) );
293  loopObjective.addStatement( objValueIn.getCols(NX, NX + NU) == u.getRow( runObj ) );
294  loopObjective.addStatement( objValueIn.getCols(NX + NU, NX + NU + NOD) == od.getRow( runObj ) );
295  loopObjective.addLinebreak( );
296 
297  // Evaluate the objective function
299 
300  // Stack the measurement function value
301  loopObjective.addStatement(
302  Dy.getRows(runObj * NY, (runObj + 1) * NY) == objValueOut.getTranspose().getRows(0, getNY())
303  );
304  loopObjective.addLinebreak( );
305 
306  // Optionally compute derivatives
307 
308  ExportVariable tmpObjS, tmpFx, tmpFu;
309  ExportVariable tmpFxEnd, tmpObjSEndTerm;
310  tmpObjS.setup("tmpObjS", NY, NY, REAL, ACADO_LOCAL);
311  if (objS.isGiven() == true)
312  tmpObjS = objS;
313  tmpFx.setup("tmpFx", NY, NX, REAL, ACADO_LOCAL);
314  if (objEvFx.isGiven() == true)
315  tmpFx = objEvFx;
316  tmpFu.setup("tmpFu", NY, NU, REAL, ACADO_LOCAL);
317  if (objEvFu.isGiven() == true)
318  tmpFu = objEvFu;
319  tmpFxEnd.setup("tmpFx", NYN, NX, REAL, ACADO_LOCAL);
320  if (objEvFxEnd.isGiven() == true)
321  tmpFxEnd = objEvFxEnd;
322  tmpObjSEndTerm.setup("tmpObjSEndTerm", NYN, NYN, REAL, ACADO_LOCAL);
323  if (objSEndTerm.isGiven() == true)
324  tmpObjSEndTerm = objSEndTerm;
325 
326  unsigned indexX = getNY();
327  ExportArgument tmpFxCall = tmpFx;
328  if (tmpFx.isGiven() == false)
329  {
330  tmpFxCall = objValueOut.getAddress(0, indexX);
331  indexX += objEvFx.getDim();
332  }
333 
334  ExportArgument tmpFuCall = tmpFu;
335  if (tmpFu.isGiven() == false)
336  {
337  tmpFuCall = objValueOut.getAddress(0, indexX);
338  }
339 
340  ExportArgument objSCall = variableObjS == true ? objS.getAddress(runObj * NY, 0) : objS;
341 
342  //
343  // Optional computation of Q1, Q2
344  //
345  if (Q1.isGiven() == false)
346  {
347  ExportVariable tmpQ1, tmpQ2;
348  tmpQ1.setup("tmpQ1", NX, NX, REAL, ACADO_LOCAL);
349  tmpQ2.setup("tmpQ2", NX, NY, REAL, ACADO_LOCAL);
350 
351  setObjQ1Q2.setup("setObjQ1Q2", tmpFx, tmpObjS, tmpQ1, tmpQ2);
352  setObjQ1Q2.addStatement( tmpQ2 == (tmpFx ^ tmpObjS) );
353  setObjQ1Q2.addStatement( tmpQ1 == tmpQ2 * tmpFx );
354 
355  loopObjective.addFunctionCall(
356  setObjQ1Q2,
357  tmpFxCall, objSCall,
358  Q1.getAddress(runObj * NX, 0), Q2.getAddress(runObj * NX, 0)
359  );
360 
361  loopObjective.addLinebreak( );
362  }
363 
364  if (R1.isGiven() == false)
365  {
366  ExportVariable tmpR1, tmpR2;
367  tmpR1.setup("tmpR1", NU, NU, REAL, ACADO_LOCAL);
368  tmpR2.setup("tmpR2", NU, NY, REAL, ACADO_LOCAL);
369 
370  setObjR1R2.setup("setObjR1R2", tmpFu, tmpObjS, tmpR1, tmpR2);
371  setObjR1R2.addStatement( tmpR2 == (tmpFu ^ tmpObjS) );
372  setObjR1R2.addStatement( tmpR1 == tmpR2 * tmpFu );
373 
374  loopObjective.addFunctionCall(
375  setObjR1R2,
376  tmpFuCall, objSCall,
377  R1.getAddress(runObj * NU, 0), R2.getAddress(runObj * NU, 0)
378  );
379 
380  loopObjective.addLinebreak( );
381  }
382 
383  if (S1.isGiven() == false)
384  {
385  ExportVariable tmpS1;
386  ExportVariable tmpS2;
387 
388  tmpS1.setup("tmpS1", NX, NU, REAL, ACADO_LOCAL);
389  tmpS2.setup("tmpS2", NX, NY, REAL, ACADO_LOCAL);
390 
391  setObjS1.setup("setObjS1", tmpFx, tmpFu, tmpObjS, tmpS1);
392  setObjS1.addVariable( tmpS2 );
393  setObjS1.addStatement( tmpS2 == (tmpFx ^ tmpObjS) );
394  setObjS1.addStatement( tmpS1 == tmpS2 * tmpFu );
395 
396  loopObjective.addFunctionCall(
397  setObjS1,
398  tmpFxCall, tmpFuCall, objSCall,
399  S1.getAddress(runObj * NX, 0)
400  );
401  }
402 
403  evaluateObjective.addStatement( loopObjective );
404 
405  //
406  // Evaluate the quadratic Mayer term
407  //
410 
411  // Evaluate the objective function, last node.
414 
417 
418  if (QN1.isGiven() == false)
419  {
420  ExportVariable tmpQN1, tmpQN2;
421  tmpQN1.setup("tmpQN1", NX, NX, REAL, ACADO_LOCAL);
422  tmpQN2.setup("tmpQN2", NX, NYN, REAL, ACADO_LOCAL);
423 
424  setObjQN1QN2.setup("setObjQN1QN2", tmpFxEnd, tmpObjSEndTerm, tmpQN1, tmpQN2);
425  setObjQN1QN2.addStatement( tmpQN2 == (tmpFxEnd ^ tmpObjSEndTerm) );
426  setObjQN1QN2.addStatement( tmpQN1 == tmpQN2 * tmpFxEnd );
427 
428  indexX = getNYN();
429  ExportArgument tmpFxEndCall = tmpFxEnd.isGiven() == true ? tmpFxEnd : objValueOut.getAddress(0, indexX);
430 
432  setObjQN1QN2,
433  tmpFxEndCall, objSEndTerm,
434  QN1.getAddress(0, 0), QN2.getAddress(0, 0)
435  );
436 
438  }
439 
440  return SUCCESSFUL_RETURN;
441 }
442 
444 {
445  ExportVariable tmp("tmp", 1, 1, REAL, ACADO_LOCAL, true);
446 
447  int hardcodeConstraintValues;
448  get(CG_HARDCODE_CONSTRAINT_VALUES, hardcodeConstraintValues);
449 
450  int hessianApproximation;
451  get( HESSIAN_APPROXIMATION, hessianApproximation );
452  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
453 
455  //
456  // Setup the bounds on control variables
457  //
459 
460  unsigned numBounds = initialStateFixed( ) == true ? N * NU : NX + N * NU;
461  unsigned offsetBounds = initialStateFixed( ) == true ? 0 : NX;
462 
463  DVector lbValuesMatrix( numBounds );
464  DVector ubValuesMatrix( numBounds );
465 
466  if (initialStateFixed( ) == false)
467  for(unsigned run1 = 0; run1 < NX; ++run1)
468  {
469  lbValuesMatrix( run1 )= xBounds.getLowerBound(0, run1);
470  ubValuesMatrix( run1) = xBounds.getUpperBound(0, run1);
471  }
472 
473  for(unsigned run1 = 0; run1 < N; ++run1)
474  for(unsigned run2 = 0; run2 < NU; ++run2)
475  {
476  lbValuesMatrix(offsetBounds + run1 * getNU() + run2) = uBounds.getLowerBound(run1, run2);
477  ubValuesMatrix(offsetBounds + run1 * getNU() + run2) = uBounds.getUpperBound(run1, run2);
478  }
479 
480 
481  if (hardcodeConstraintValues == YES)
482  {
483  lbValues.setup("lbValues", lbValuesMatrix, REAL, ACADO_VARIABLES);
484  ubValues.setup("ubValues", ubValuesMatrix, REAL, ACADO_VARIABLES);
485  }
486  else
487 // else if (isFinite( lbValuesMatrix ) || isFinite( ubValuesMatrix ))
488  {
489  lbValues.setup("lbValues", numBounds, 1, REAL, ACADO_VARIABLES);
490  lbValues.setDoc( "Lower bounds values." );
491  ubValues.setup("ubValues", numBounds, 1, REAL, ACADO_VARIABLES);
492  ubValues.setDoc( "Upper bounds values." );
493 
494  initialize.addStatement(lbValues == lbValuesMatrix);
495  initialize.addStatement(ubValues == ubValuesMatrix);
496  }
497 
498  ExportFunction* boundSetFcn = hardcodeConstraintValues == YES ? &condensePrep : &condenseFdb;
499 
500  if (performFullCondensing() == true)
501  {
502  boundSetFcn->addStatement( lb.getRows(0, getNumQPvars()) == lbValues - u.makeColVector() );
503  boundSetFcn->addStatement( ub.getRows(0, getNumQPvars()) == ubValues - u.makeColVector() );
504  }
505  else
506  {
507  if ( initialStateFixed( ) == true )
508  {
509  condenseFdb.addStatement( lb.getRows(0, NX) == Dx0 );
510  condenseFdb.addStatement( ub.getRows(0, NX) == Dx0 );
511 
512  boundSetFcn->addStatement( lb.getRows(NX, getNumQPvars()) == lbValues - u.makeColVector() );
513  boundSetFcn->addStatement( ub.getRows(NX, getNumQPvars()) == ubValues - u.makeColVector() );
514  }
515  else
516  {
517  boundSetFcn->addStatement( lb.getRows(0, NX) == lbValues.getRows(0, NX) - x.getRow( 0 ).getTranspose() );
518  boundSetFcn->addStatement( lb.getRows(NX, getNumQPvars()) == lbValues.getRows(NX, getNumQPvars()) - u.makeColVector() );
519 
520  boundSetFcn->addStatement( ub.getRows(0, NX) == ubValues.getRows(0, NX) - x.getRow( 0 ).getTranspose() );
521  boundSetFcn->addStatement( ub.getRows(NX, getNumQPvars()) == ubValues.getRows(NX, getNumQPvars()) - u.makeColVector() );
522  }
523  }
526 
528  //
529  // Setup the bounds on state variables
530  //
532 
533  DVector lbTmp; DVector ubTmp;
534  unsigned numStateBounds = getNumStateBounds();
535  unsigned numPathCon = N * dimPacH;
536  unsigned numPointCon = dimPocH;
537  if( getNumStateBounds() )
538  {
539  condenseFdb.addVariable( tmp );
540 
541  lbTmp = DVector( getNumStateBounds( ));
542  ubTmp = DVector( getNumStateBounds( ) );
543  for(unsigned i = 0; i < xBoundsIdx.size(); ++i)
544  {
545  lbTmp( i ) = xBounds.getLowerBound( xBoundsIdx[ i ] / NX, xBoundsIdx[ i ] % NX );
546  ubTmp( i ) = xBounds.getUpperBound( xBoundsIdx[ i ] / NX, xBoundsIdx[ i ] % NX );
547  }
548 
549  unsigned numOps = getNumStateBounds() * N * (N + 1) / 2 * NU;
550 
551  if (numOps < 1024)
552  {
553  for(unsigned row = 0; row < getNumStateBounds( ); ++row)
554  {
555  unsigned conIdx = xBoundsIdx[ row ] - NX;
556  if( initialStateFixed( ) == false ) {
557  condensePrep.addStatement( A.getSubMatrix(row, row + 1, 0, NX ) == C.getRow( conIdx ) );
558  }
559 
560  unsigned blk = conIdx / NX + 1;
561  for (unsigned col = 0; col < blk; ++col)
562  {
563  unsigned blkRow = (col * (2 * N - col - 1) / 2 + blk - 1) * NX + conIdx % NX;
564 
566  A.getSubMatrix(row, row + 1, offsetBounds + col * NU, offsetBounds + (col + 1) * NU ) == E.getRow( blkRow ) );
567  }
568 
570  }
571  }
572  else
573  {
574 
575  DMatrix vXBoundIndices(1, numStateBounds);
576  for (unsigned i = 0; i < numStateBounds; ++i)
577  vXBoundIndices(0, i) = xBoundsIdx[ i ];
578  ExportVariable evXBounds("xBoundIndices", vXBoundIndices, STATIC_CONST_INT, ACADO_LOCAL, false);
579 
580  condensePrep.addVariable( evXBounds );
581 
582  ExportIndex row, col, conIdx, blk, blkRow;
583 
584  condensePrep.acquire( row ).acquire( col ).acquire( conIdx ).acquire( blk ).acquire( blkRow );
585 
586  ExportForLoop lRow(row, 0, numStateBounds);
587 
588  lRow << conIdx.getFullName() << " = " << evXBounds.getFullName() << "[ " << row.getFullName() << " ] - " << toString(NX) << ";\n";
589 
590  if( initialStateFixed( ) == false ) {
591  lRow.addStatement( A.getSubMatrix(row, row + 1, 0, NX ) == C.getRow( conIdx ) );
592  }
593 
594  lRow.addStatement( blk == conIdx / NX + 1 );
595 
596  ExportForLoop lCol(col, 0, blk);
597 
598  lCol.addStatement( blkRow == (col * (2 * N - col - 1) / 2 + blk - 1) * NX + conIdx % NX );
599  lCol.addStatement(
600  A.getSubMatrix(row, row + 1, offsetBounds + col * NU, offsetBounds + (col + 1) * NU ) == E.getRow( blkRow ) );
601 
602  lRow.addStatement( lCol );
603  condensePrep.addStatement( lRow );
604 
605  condensePrep.release( row ).release( col ).release( conIdx ).release( blk ).release( blkRow );
606  }
608  }
610 
611  lbTmp.append( lbPathConValues );
612  ubTmp.append( ubPathConValues );
613 
614  lbTmp.append( lbPointConValues );
615  ubTmp.append( ubPointConValues );
616 
617  if (hardcodeConstraintValues == YES)
618  {
619  lbAValues.setup("lbAValues", lbTmp, REAL, ACADO_VARIABLES);
620  ubAValues.setup("ubAValues", ubTmp, REAL, ACADO_VARIABLES);
621  }
622  else
623  {
624  lbAValues.setup("lbAValues", numStateBounds+numPathCon+numPointCon, 1, REAL, ACADO_VARIABLES);
625  lbAValues.setDoc( "Lower bounds values for affine constraints." );
626  ubAValues.setup("ubAValues", numStateBounds+numPathCon+numPointCon, 1, REAL, ACADO_VARIABLES);
627  ubAValues.setDoc( "Upper bounds values for affine constraints." );
628 
631  }
632 
633  // Shift constraint bounds by first interval
634  for(unsigned boundIndex = 0; boundIndex < getNumStateBounds( ); ++boundIndex)
635  {
636  unsigned row = xBoundsIdx[boundIndex];
637 
638  condenseFdb.addStatement( tmp == sbar.getRow( row ) + x.makeRowVector().getCol( row ) );
639  condenseFdb.addStatement( lbA.getRow( boundIndex ) == lbAValues.getRow( boundIndex ) - tmp );
640  condenseFdb.addStatement( ubA.getRow( boundIndex ) == ubAValues.getRow( boundIndex ) - tmp );
641  }
643  }
644 
645 
647  //
648  // Setup the evaluation of the path constraints
649  //
651 
652  if ( numPathCon )
653  {
654  unsigned rowOffset = numStateBounds;
655  unsigned colOffset = performFullCondensing() == true ? 0 : NX;
656 
657  //
658  // Setup evaluation
659  //
660  ExportIndex runPac;
661  if( secondOrder ) {
662  evaluateObjective.acquire( runPac );
663  }
664  else {
665  condensePrep.acquire( runPac );
666  }
667  ExportForLoop loopPac(runPac, 0, N);
668 
669  loopPac.addStatement( conValueIn.getCols(0, NX) == x.getRow( runPac ) );
670 
671  uint dimL = 0;
672  if ( secondOrder && pacEvDDH.isGiven() == false ) {
673  dimL = dimPacH;
674  loopPac.addStatement( conValueIn.getCols(NX, NX+dimPacH) == yVars.getRows(getNumQPvars()+getNumStateBounds()+runPac*dimPacH,getNumQPvars()+getNumStateBounds()+runPac*dimPacH+dimPacH).getTranspose() );
675  }
676 
677  loopPac.addStatement( conValueIn.getCols(NX+dimL, NX+dimL + NU) == u.getRow( runPac ) );
678  loopPac.addStatement( conValueIn.getCols(NX+dimL + NU, NX+dimL + NU + NOD) == od.getRow( runPac ) );
680 
681  loopPac.addStatement( pacEvH.getRows( runPac * dimPacH, (runPac + 1) * dimPacH) ==
682  conValueOut.getTranspose().getRows(0, dimPacH) );
683  loopPac.addLinebreak( );
684 
685  unsigned derOffset = dimPacH;
686 
687  // Optionally store derivatives
688  if ( pacEvHx.isGiven() == false )
689  {
690  loopPac.addStatement(
692  getCols(runPac * dimPacH * NX, (runPac + 1) * dimPacH * NX)
693  == conValueOut.getCols(derOffset, derOffset + dimPacH * NX )
694  );
695 
696  derOffset = derOffset + dimPacH * NX;
697  }
698  if (pacEvHu.isGiven() == false )
699  {
700  loopPac.addStatement(
702  getCols(runPac * dimPacH * NU, (runPac + 1) * dimPacH * NU)
703  == conValueOut.getCols(derOffset, derOffset + dimPacH * NU )
704  );
705 
706  derOffset = derOffset + dimPacH * NU;
707  }
708  if( secondOrder ) {
709  if (pacEvDDH.isGiven() == false )
710  {
711  loopPac.addStatement( pacEvDDH.makeRowVector() == conValueOut.getCols(derOffset, derOffset + (NX+NU)*(NX+NU) ) );
712  }
713  loopPac.addStatement( objS.getRows( runPac*(NX+NU), runPac*(NX+NU)+NX+NU ) += pacEvDDH );
714  }
715 
716  // Add loop to the function.
717  if( secondOrder ) {
718  evaluateObjective.addStatement( loopPac );
720  }
721  else {
722  condensePrep.addStatement( loopPac );
724  }
725 
726  // Define the multHxC multiplication routine
727  ExportVariable tmpA01, tmpHx, tmpGx;
728 
729  if (pacEvHx.isGiven() == true)
730  tmpHx = pacEvHx;
731  else
732  tmpHx.setup("Hx", dimPacH, NX, REAL, ACADO_LOCAL);
733 
734  tmpGx.setup("Gx", NX, NX, REAL, ACADO_LOCAL);
735 
736  if (performFullCondensing() == false)
737  {
738 // tmpA01.setup("A01", dimPacH, NX, REAL, ACADO_LOCAL);
739 //
740 // multHxC.setup("multHxC", tmpHx, tmpGx, tmpA01);
741 // multHxC.addStatement( tmpA01 == tmpHx * tmpGx );
742 //
743 // A10.setup("A01", numPathCon, NX, REAL, ACADO_WORKSPACE);
744 // }
745 // else
746 // {
747  tmpA01.setup("A01", dimPacH, getNumQPvars(), REAL, ACADO_LOCAL);
748  multHxC.setup("multHxC", tmpHx, tmpGx, tmpA01);
749  multHxC.addStatement( tmpA01.getSubMatrix(0, dimPacH, 0, NX) == tmpHx * tmpGx );
750 
751  A10 = A;
752  }
753 
754  unsigned offsetA01 = (performFullCondensing() == true) ? 0 : rowOffset;
755 
756  if (performFullCondensing() == false) {
757  // Define the block A_{10}(0: dimPacH, 0: NX) = H_{x}(0: dimPacH, 0: NX)
758  if (pacEvHx.isGiven() == true)
759  {
761  A10.getSubMatrix(offsetA01, offsetA01 + dimPacH, 0, NX)
762  == pacEvHx);
763  }
764  else
765  {
767  A10.getSubMatrix(offsetA01, offsetA01 + dimPacH, 0, NX)
768  == pacEvHx.getSubMatrix(0, dimPacH, 0, NX));
769  }
770  }
772 
773  if (performFullCondensing() == false) {
774  // Evaluate Hx * C
775  for (unsigned row = 0; row < N - 1; ++row)
776  {
777  if (pacEvHx.isGiven() == true)
778  {
780  multHxC,
781  pacEvHx,
782  C.getAddress(row * NX, 0),
783  A10.getAddress(offsetA01 + (row + 1) * dimPacH, 0) );
784  }
785  else
786  {
788  multHxC,
789  pacEvHx.getAddress((row + 1) * dimPacH, 0),
790  C.getAddress(row * NX, 0),
791  A10.getAddress(offsetA01 + (row + 1) * dimPacH, 0) );
792  }
793  }
794  }
796 
797  //
798  // Evaluate Hx * E
799  //
800  ExportVariable tmpE;
801  tmpE.setup("E", NX, NU, REAL, ACADO_LOCAL);
802  ExportIndex iRow( "row" ), iCol( "col" );
803 
804  multHxE.setup("multHxE", tmpHx, tmpE, iRow, iCol);
806  A.getSubMatrix( rowOffset + iRow * dimPacH,
807  rowOffset + (iRow + 1) * dimPacH,
808  colOffset + iCol * NU,
809  colOffset + (iCol + 1) * NU)
810  == tmpHx * tmpE );
811 
812  if ( N <= 20 )
813  {
814  for (unsigned row = 0; row < N - 1; ++row)
815  {
816  for (unsigned col = 0; col <= row; ++col)
817  {
818  unsigned blk = (col * (2 * N - col - 1) / 2 + row);
819  unsigned row2 = row + 1;
820 
821  if (pacEvHx.isGiven() == true)
823  multHxE,
824  pacEvHx,
825  E.getAddress(blk * NX, 0),
826  ExportIndex( row2 ),
827  ExportIndex( col )
828  );
829  else
831  multHxE,
832  pacEvHx.getAddress((row + 1) * dimPacH, 0),
833  E.getAddress(blk * NX, 0),
834  ExportIndex( row2 ),
835  ExportIndex( col )
836  );
837  }
838  }
839  }
840  else
841  {
842  ExportIndex row, col, blk, row2;
843  condensePrep.acquire( row );
844  condensePrep.acquire( col );
845  condensePrep.acquire( blk );
846  condensePrep.acquire( row2 );
847 
848  ExportForLoop eLoopI(row, 0, N - 1);
849  ExportForLoop eLoopJ(col, 0, row + 1);
850 
851  eLoopJ.addStatement( blk == (col * (2 * N - col - 1) / 2 + row) );
852  eLoopJ.addStatement( row2 == row + 1 );
853 
854  if (pacEvHx.isGiven() == true)
855  {
856  eLoopJ.addFunctionCall(
857  multHxE,
858  pacEvHx,
859  E.getAddress(blk * NX, 0),
860  row2,
861  col
862  );
863  }
864  else
865  {
866  eLoopJ.addFunctionCall(
867  multHxE,
868  pacEvHx.getAddress((row + 1) * dimPacH, 0),
869  E.getAddress(blk * NX, 0),
870  row2,
871  col
872  );
873  }
874 
875  eLoopI.addStatement( eLoopJ );
876  condensePrep.addStatement( eLoopI );
877 
878  condensePrep.release( row );
879  condensePrep.release( col );
880  condensePrep.release( blk );
881  condensePrep.release( row2 );
882  }
884 
885  if (pacEvHu.getDim() > 0)
886  {
887  for (unsigned i = 0; i < N; ++i)
888  {
889  if (pacEvHu.isGiven() == true)
891  A.getSubMatrix(
892  rowOffset + i * dimPacH,
893  rowOffset + (i + 1) * dimPacH,
894  colOffset + i * NU,
895  colOffset + (i + 1) * NU)
896  == pacEvHu
897  );
898  else
900  A.getSubMatrix(
901  rowOffset + i * dimPacH,
902  rowOffset + (i + 1) * dimPacH,
903  colOffset + i * NU,
904  colOffset + (i + 1) * NU)
906  i * dimPacH,(i + 1) * dimPacH, 0, NU)
907  );
908  }
909  }
910 
911  //
912  // Set upper and lower bounds
913  //
914  condensePrep.addStatement(lbA.getRows(rowOffset, rowOffset + numPathCon) ==
915  lbAValues.getRows(rowOffset, rowOffset + numPathCon) - pacEvH);
917  condensePrep.addStatement(ubA.getRows(rowOffset, rowOffset + numPathCon) ==
918  ubAValues.getRows(rowOffset, rowOffset + numPathCon) - pacEvH);
920 
921 // if (performFullCondensing() == true)
922 // {
923 // pacA01Dx0.setup("pacA01Dx0", numPathCon, 1, REAL, ACADO_WORKSPACE);
924 //
925 // condenseFdb.addStatement( pacA01Dx0 == A10 * Dx0 );
926 // condenseFdb.addStatement(lbA.getRows(rowOffset, rowOffset + numPathCon) -= pacA01Dx0);
927 // condenseFdb.addLinebreak();
928 // condenseFdb.addStatement(ubA.getRows(rowOffset, rowOffset + numPathCon) -= pacA01Dx0);
929 // condenseFdb.addLinebreak();
930 // }
931 
932  // Evaluate Hx * d
933  if ( performsSingleShooting() == false )
934  {
935  ExportVariable tmpd("tmpd", NX, 1, REAL, ACADO_LOCAL);
936  ExportVariable tmpLb("lbA", dimPacH, 1, REAL, ACADO_LOCAL);
937  ExportVariable tmpUb("ubA", dimPacH, 1, REAL, ACADO_LOCAL);
938 
939  macHxd.setup("macHxd", tmpHx, tmpd, tmpLb, tmpUb);
940  macHxd.addStatement( pacEvHxd == tmpHx * tmpd );
941  macHxd.addStatement( tmpLb -= pacEvHxd );
942  macHxd.addStatement( tmpUb -= pacEvHxd );
943 
944  for (unsigned i = 0; i < N; ++i)
945  {
946  if (pacEvHx.isGiven() == true)
947  {
949  macHxd,
950  pacEvHx,
951  sbar.getAddress(i * NX),
952  lbA.getAddress(rowOffset + i * dimPacH),
953  ubA.getAddress(rowOffset + i * dimPacH)
954  );
955  }
956  else
957  {
959  macHxd,
960  pacEvHx.getAddress(i * dimPacH, 0),
961  sbar.getAddress(i * NX),
962  lbA.getAddress(rowOffset + i * dimPacH),
963  ubA.getAddress(rowOffset + i * dimPacH)
964  );
965  }
966  }
968  }
969  }
970 
972  //
973  // Setup the evaluation of the point constraints
974  //
976 
977  if ( numPointCon )
978  {
979  unsigned rowOffset = getNumStateBounds() + N * dimPacH;
980  unsigned colOffset = performFullCondensing() == true ? 0 : NX;
981  unsigned dim;
982 
983  if( secondOrder ) {
985  }
986 
987 // if (performFullCondensing() == true)
988 // A20.setup("A02", dimPocH, NX, REAL, ACADO_WORKSPACE);
989 
990  //
991  // Evaluate the point constraints
992  //
993  for (unsigned i = 0, intRowOffset = 0; i < N + 1; ++i)
994  {
995  if (evaluatePointConstraints[ i ] == 0)
996  continue;
997 
998  condensePrep.addComment( string( "Evaluating constraint on node: #" ) + toString( i ) );
1000 
1002  if (i < N)
1003  {
1004  condensePrep.addStatement( conValueIn.getCols(NX, NX + NU) == u.getRow( i ) );
1005  condensePrep.addStatement( conValueIn.getCols(NX + NU, NX + NU + NOD) == od.getRow( i ) );
1006  }
1007  else
1008  condensePrep.addStatement( conValueIn.getCols(NX, NX + NOD) == od.getRow( i ) );
1009 
1012 
1013  if (i < N)
1014  dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX + NU);
1015  else
1016  dim = evaluatePointConstraints[ i ]->getFunctionDim() / (1 + NX);
1017 
1018  // Fill pocEvH, pocEvHx, pocEvHu
1020  pocEvH.getRows(intRowOffset, intRowOffset + dim)
1021  == conValueOut.getTranspose().getRows(0, dim));
1023 
1025  pocEvHx.makeRowVector().getCols(intRowOffset * NX,
1026  (intRowOffset + dim) * NX)
1027  == conValueOut.getCols(dim, dim + dim * NX));
1029 
1030  if (i < N)
1031  {
1033  pocEvHu.makeRowVector().getCols(intRowOffset * NU,
1034  (intRowOffset + dim) * NU)
1035  == conValueOut.getCols(dim + dim * NX,
1036  dim + dim * NX + dim * NU));
1038  }
1039 
1040  intRowOffset += dim;
1041  }
1042 
1043  //
1044  // Include point constraint data in the QP problem
1045  //
1046  for (unsigned row = 0, intRowOffset = 0; row < N + 1; ++row)
1047  {
1048  if (evaluatePointConstraints[ row ] == 0)
1049  continue;
1050 
1052  string( "Evaluating multiplications of constraint functions on node: #" ) + toString( row ) );
1054 
1055  if (row < N)
1056  dim = evaluatePointConstraints[ row ]->getFunctionDim() / (1 + NX + NU);
1057  else
1058  dim = evaluatePointConstraints[ row ]->getFunctionDim() / (1 + NX);
1059 
1060  if (row == 0)
1061  {
1062  if (performFullCondensing() == false) {
1063 // condensePrep.addStatement(
1064 // A20.getSubMatrix(0, dim, 0, NX)
1065 // == pocEvHx.getSubMatrix(0, dim, 0, NX));
1066 // else
1068  A.getSubMatrix(rowOffset, rowOffset + dim, 0, NX)
1069  == pocEvHx.getSubMatrix(0, dim, 0, NX));
1070  }
1072 
1074  A.getSubMatrix(rowOffset, rowOffset + dim, colOffset,
1075  colOffset + NU)
1076  == pocEvHu.getSubMatrix(0, dim, 0, NU));
1078  }
1079  else
1080  {
1081  // Hx * C
1082  if (performFullCondensing() == false) {
1083 // condensePrep.addStatement(
1084 // A20.getSubMatrix(intRowOffset, intRowOffset + dim, 0, NX) ==
1085 // pocEvHx.getSubMatrix(intRowOffset, intRowOffset + dim, 0, NX) *
1086 // C.getSubMatrix((row - 1) * NX, row * NX, 0, NX) );
1087 // else
1089  A.getSubMatrix(rowOffset + intRowOffset, rowOffset + intRowOffset + dim, 0, NX) ==
1090  pocEvHx.getSubMatrix(intRowOffset, intRowOffset + dim, 0, NX) *
1091  C.getSubMatrix((row - 1) * NX, row * NX, 0, NX) );
1092  }
1094 
1095  // Hx * E
1096  ExportIndex iCol, iBlk;
1097  condensePrep.acquire( iCol );
1098  condensePrep.acquire( iBlk );
1099  ExportForLoop eLoop(iCol, 0, row);
1100 
1101  // row - 1, col -> blk
1102  eLoop.addStatement( iBlk == (iCol * (2 * N - iCol - 1) / 2 + row-1) );
1103  eLoop.addStatement(
1104  A.getSubMatrix(rowOffset + intRowOffset, rowOffset + intRowOffset + dim,
1105  colOffset + iCol * NU, colOffset + (iCol + 1) * NU) ==
1106  pocEvHx.getSubMatrix(intRowOffset, intRowOffset + dim, 0 , NX) *
1107  E.getSubMatrix(iBlk * NX, (iBlk + 1) * NX, 0, NU)
1108  );
1109 
1110  condensePrep.addStatement( eLoop );
1111  condensePrep.release( iCol );
1112  condensePrep.release( iBlk );
1113 
1114  // Add Hu block to the A21 block
1115  if (row < N)
1116  {
1118  A.getSubMatrix(rowOffset + intRowOffset, rowOffset + intRowOffset + dim,
1119  colOffset + row * NU, colOffset + (row + 1) * NU) ==
1120  pocEvHu.getSubMatrix(intRowOffset, intRowOffset + dim, 0, NU));
1122  }
1123  }
1124 
1125  // Hx * d, MS only
1126  if (performsSingleShooting() == false)
1127  {
1129  pocEvHxd.getRows(intRowOffset, intRowOffset + dim) ==
1130  pocEvHx.getSubMatrix(intRowOffset, intRowOffset + dim, 0 , NX) *
1131  sbar.getRows(row * NX, row * NX + NX) );
1133  }
1134 
1135  intRowOffset += dim;
1136  }
1137 
1138  //
1139  // And now setup the lbA and ubA
1140  //
1141  condensePrep.addStatement( lbA.getRows(rowOffset, rowOffset + dimPocH) ==
1142  lbAValues.getRows(rowOffset, rowOffset + dimPocH) - pocEvH);
1144  condensePrep.addStatement( ubA.getRows(rowOffset, rowOffset + dimPocH) ==
1145  ubAValues.getRows(rowOffset, rowOffset + dimPocH) - pocEvH);
1147 
1148 // if (performFullCondensing() == true)
1149 // {
1150 // pocA02Dx0.setup("pacA02Dx0", dimPocH, 1, REAL, ACADO_WORKSPACE);
1151 //
1152 // condenseFdb.addStatement( pocA02Dx0 == A20 * Dx0 );
1153 // condenseFdb.addLinebreak();
1154 // condenseFdb.addStatement(lbA.getRows(rowOffset, rowOffset + dimPocH) -= pocA02Dx0);
1155 // condenseFdb.addLinebreak();
1156 // condenseFdb.addStatement(ubA.getRows(rowOffset, rowOffset + dimPocH) -= pocA02Dx0);
1157 // condenseFdb.addLinebreak();
1158 // }
1159 
1160  if (performsSingleShooting() == false)
1161  {
1162  condenseFdb.addStatement( lbA.getRows(rowOffset, rowOffset + dimPocH) -= pocEvHxd );
1164  condenseFdb.addStatement( ubA.getRows(rowOffset, rowOffset + dimPocH) -= pocEvHxd );
1166  }
1167  }
1168 
1169  return SUCCESSFUL_RETURN;
1170 }
1171 
1173 {
1174  condensePrep.setup("condensePrep");
1175  condenseFdb.setup( "condenseFdb" );
1176 
1178  //
1179  // Setup local memory for preparation phase: T1, T2, W1, W2
1180  //
1182 
1183  // TODO
1184 
1186  //
1187  // Compute Hessian block H00, H10 and C
1188  //
1190 
1191  if (performFullCondensing() == false || getNumComplexConstraints() > 0) {
1192  LOG( LVL_DEBUG ) << "Setup condensing: C" << endl;
1194  for (unsigned row = 1; row < N; ++row)
1196  multGxGx, evGx.getAddress(row * NX), C.getAddress((row - 1) * NX), C.getAddress(row * NX));
1197 
1198  }
1199 
1200  if (performFullCondensing() == false)
1201  {
1202  LOG( LVL_DEBUG ) << "Setup condensing: H00, H10" << endl;
1203 
1204  T1.setup("T1", NX, NX, REAL, ACADO_WORKSPACE);
1205  T2.setup("T2", NX, NX, REAL, ACADO_WORKSPACE);
1206 
1207  /* Algorithm for computation of H10 and H00
1208 
1209  T1 = Q_N * C_{N - 1}
1210  for i = N - 1: 1
1211  H_{i + 1, 0} = B_i^T * T1
1212  H_{i + 1, 0} += S_i^T * C_{i - 1}
1213 
1214  T2 = A_i^T * T1
1215  T1 = T2 + Q_i * C_{i - 1}
1216 
1217  H_{1, 0} = B_0^T * T1
1218  H_{1, 0} += S_0^T
1219  H_{0, 0} = Q_0 + A_0^T * T1
1220 
1221  */
1222 
1223  // H10 Block
1224  ExportFunction* QN1Call = QN1.isGiven() == true ? &multQN1Gx : &multGxGx;
1225  condensePrep.addFunctionCall(*QN1Call, QN1, C.getAddress((N - 1) * NX), T1);
1226  for (unsigned row = N - 1; row > 0; --row)
1227  {
1229 
1230  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1231  {
1232  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress(row * NX) : S1;
1233  condensePrep.addFunctionCall(mac_ST_C, S1Call, C.getAddress((row - 1) * NX), ExportIndex( row ));
1234  }
1235 
1237 
1238  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress(row * NX);
1239  condensePrep.addFunctionCall(macGxTGx, T2, Q1Call, C.getAddress((row - 1) * NX), T1);
1240  }
1241 
1243  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1244  {
1246  H.getSubMatrix(NX, NX + NU, 0, NX) += S1.getSubMatrix(0, NX, 0, NU).getTranspose()
1247  );
1248  }
1249 
1250  // H00 Block
1251  DMatrix mRegH00 = eye<double>( getNX() );
1252  mRegH00 *= levenbergMarquardt;
1254  H.getSubMatrix(0, NX, 0, NX) == Q1.getSubMatrix(0, NX, 0, NX) + (evGx.getSubMatrix(0, NX, 0, NX).getTranspose() * T1)
1255  );
1256  condensePrep.addStatement( H.getSubMatrix(0, NX, 0, NX) += mRegH00 );
1257  }
1258 
1260  //
1261  // Compute Hessian block H11
1262  //
1264 
1265  LOG( LVL_DEBUG ) << "Setup condensing: H11 and E" << endl;
1266 
1267  /*
1268 
1269  This one is only for the case where we have input constraints only
1270 
1271  // Create E and H
1272 
1273  for i = 0: N - 1
1274  {
1275  // Storage for E: (N x nx) x nu
1276 
1277  E_0 = B_i;
1278  for k = 1: N - i - 1
1279  E_k = A_{i + k} * E_{k - 1};
1280 
1281  // Two temporary matrices W1, W2 of size nx x nu
1282 
1283  W1 = Q_N^T * E_{N - i - 1};
1284 
1285  for k = N - 1: i + 1
1286  {
1287  H_{k, i} = B_k^T * W1;
1288 
1289  W2 = A_k^T * W1;
1290  W1 = Q_k^T * E_{k - i - 1} + W2;
1291  }
1292  H_{i, i} = B_i^T * W1 + R_i^T
1293  }
1294 
1295  Else, in general case:
1296 
1297  for i = 0: N - 1
1298  {
1299  // Storage for E: (N * (N + 1) / 2 x nx) x nu
1300 
1301  j = 1 / 2 * i * (2 * N - i + 1);
1302 
1303  E_j = B_i;
1304  for k = 1: N - i - 1
1305  E_{j + k} = A_{i + k} * E_{j + k - 1};
1306 
1307  // Two temporary matrices W1, W2 of size nx x nu
1308 
1309  W1 = Q_N^T * E_{j + N - i - 1};
1310 
1311  for k = N - 1: i + 1
1312  {
1313  H_{k, i} = B_k^T * W1;
1314  H_{k, i} += S_k^T * E_{j + k - i - 1};
1315 
1316  W2 = A_k^T * W1;
1317  W1 = Q_k^T * E_{j + k - i - 1} + W2;
1318  }
1319  H_{i, i} = B_i^T * W1 + R_i^T
1320  }
1321 
1322  */
1323 
1324  W1.setup("W1", NX, NU, REAL, ACADO_WORKSPACE);
1325  W2.setup("W2", NX, NU, REAL, ACADO_WORKSPACE);
1326 
1327  if (N <= 15)
1328  {
1329  for (unsigned col = 0; col < N; ++col)
1330  {
1331  int offset = col * (2 * N - col + 1) / 2;
1332 
1333  condensePrep.addComment( "Column: " + toString( col ) );
1335  moveGuE, evGu.getAddress(col * NX), E.getAddress(offset * NX)
1336  );
1337  for (unsigned row = 1; row < N - col; ++row)
1339  multGxGu,
1340  evGx.getAddress((col + row) * NX),
1341  E.getAddress((offset + row - 1) * NX), E.getAddress((offset + row) * NX)
1342  );
1344 
1345  ExportFunction* QN1Call = QN1.isGiven() == true ? &multQN1Gu : &multGxGu;
1347  *QN1Call, QN1, E.getAddress((offset + N - col - 1) * NX), W1
1348  );
1349 
1350  for (unsigned row = N - 1; col < row; --row)
1351  {
1353  multBTW1, evGu.getAddress(row * NX), W1,
1354  ExportIndex( row ), ExportIndex( col )
1355  );
1356 
1357  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1358  {
1359  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress(row * NX) : S1;
1360 
1362  mac_S1T_E,
1363  S1Call, E.getAddress((offset + row - col - 1) * NX),
1364  ExportIndex( row ), ExportIndex( col )
1365  );
1366  }
1367 
1369  multGxTGu, evGx.getAddress(row * NX), W1, W2
1370  );
1371 
1372  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress(row * NX);
1374  macQEW2, Q1Call, E.getAddress((offset + row - col - 1) * NX), W2, W1
1375  );
1376  }
1377 
1378  ExportArgument R1Call = R1.isGiven() == true ? R1 : R1.getAddress(col * NU);
1380  macBTW1_R1, R1Call, evGu.getAddress(col * NX), W1,
1381  ExportIndex( col )
1382  );
1383 
1385  }
1386  }
1387  else
1388  {
1389  // Long horizons
1390 
1391  ExportIndex row, col, offset;
1392  condensePrep.acquire( row ).acquire( col ).acquire( offset );
1393 
1394  ExportForLoop cLoop(col, 0, N);
1395  ExportForLoop fwdLoop(row, 1, N - col);
1396  ExportForLoop adjLoop(row, N - 1, col, -1);
1397 
1398  cLoop.addStatement( offset == col * (2 * N + 1 - col) / 2 );
1399  cLoop.addFunctionCall(
1400  moveGuE, evGu.getAddress(col * NX), E.getAddress(offset * NX)
1401  );
1402 
1403  fwdLoop.addFunctionCall(
1404  multGxGu,
1405  evGx.getAddress((col + row) * NX),
1406  E.getAddress((offset + row - 1) * NX), E.getAddress((offset + row) * NX)
1407  );
1408  cLoop.addStatement( fwdLoop );
1409  cLoop.addLinebreak();
1410 
1411  ExportFunction* QN1Call = QN1.isGiven() == true ? &multQN1Gu : &multGxGu;
1412  cLoop.addFunctionCall(
1413  *QN1Call, QN1, E.getAddress((offset - col + N - 1) * NX), W1
1414  );
1415 
1416  adjLoop.addFunctionCall(
1417  multBTW1, evGu.getAddress(row * NX), W1,
1418  row, col
1419  );
1420 
1421  if ((S1.isGiven() && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1422  {
1423  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress(row * NX) : S1;
1424 
1425  adjLoop.addFunctionCall(
1426  mac_S1T_E,
1427  S1Call, E.getAddress((offset + row - col - 1) * NX),
1428  row, col
1429  );
1430  }
1431 
1432  adjLoop.addFunctionCall(
1433  multGxTGu, evGx.getAddress(row * NX), W1, W2
1434  );
1435 
1436  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress(row * NX);
1437  adjLoop.addFunctionCall(
1438  macQEW2, Q1Call, E.getAddress((offset + row - col - 1) * NX), W2, W1
1439  );
1440 
1441  cLoop.addStatement( adjLoop );
1442 
1443  ExportArgument R1Call = R1.isGiven() == true ? R1 : R1.getAddress(col * NU);
1444  cLoop.addFunctionCall(
1445  macBTW1_R1, R1Call, evGu.getAddress(col * NX), W1,
1446  ExportIndex( col )
1447  );
1448 
1449  condensePrep.addStatement( cLoop );
1451 
1452  condensePrep.release( row ).release( col ).release( offset );
1453  }
1454 
1456 
1457  LOG( LVL_DEBUG ) << "---> Copy H11 lower part" << endl;
1458 
1459  // Copy to H11 upper lower part to upper triangular part
1460  if (N <= 20)
1461  {
1462  for (unsigned ii = 0; ii < N; ++ii)
1463  for(unsigned jj = 0; jj < ii; ++jj)
1465  copyHTH, ExportIndex( jj ), ExportIndex( ii ));
1466 
1467  // Copy H10 to H01
1468  if( performFullCondensing() == false) {
1469  for (unsigned ii = 0; ii < N; ++ii)
1471  }
1472  }
1473  else
1474  {
1475  ExportIndex ii, jj;
1476 
1477  condensePrep.acquire( ii );
1478  condensePrep.acquire( jj );
1479 
1480  ExportForLoop eLoopI(ii, 0, N);
1481  ExportForLoop eLoopJ(jj, 0, ii);
1482 
1483  eLoopJ.addFunctionCall(copyHTH, jj, ii);
1484  eLoopI.addStatement( eLoopJ );
1485  condensePrep.addStatement( eLoopI );
1486 
1487  // Copy H10 to H01
1488  if( performFullCondensing() == false) {
1489  ExportForLoop eLoopK(ii, 0, N);
1490  eLoopK.addFunctionCall(copyHTH1, ii);
1491  condensePrep.addStatement( eLoopK );
1492  }
1493 
1494  condensePrep.release( ii );
1495  condensePrep.release( jj );
1496  }
1498 
1500  //
1501  // Compute gradient components g0 and g1
1502  //
1504 
1505  LOG( LVL_DEBUG ) << "Setup condensing: create Dx0, Dy and DyN" << endl;
1506 
1507  unsigned offset = performFullCondensing() == true ? 0 : NX;
1508 
1509  if (initialStateFixed() == true)
1510  {
1512  }
1513  condenseFdb << (Dy -= y) << (DyN -= yN);
1515 
1516  int gradientUp;
1517  get( LIFTED_GRADIENT_UPDATE, gradientUp );
1518  bool gradientUpdate = (bool) gradientUp;
1519 
1520  int variableObjS;
1521  get(CG_USE_VARIABLE_WEIGHTING_MATRIX, variableObjS);
1522  int sensitivityProp;
1523  get( DYNAMIC_SENSITIVITY, sensitivityProp );
1524  bool adjoint = ((ExportSensitivityType) sensitivityProp == BACKWARD || ((ExportSensitivityType) sensitivityProp == INEXACT && gradientUpdate));
1525 
1526  // Compute RDy
1527  if( getNY() > 0 || getNYN() ) {
1528  for(unsigned run1 = 0; run1 < N; ++run1)
1529  {
1530  ExportArgument R2Call = R2.isGiven() == true ? R2 : R2.getAddress(run1 * NU, 0);
1531  ExportArgument SluCall =
1532  objSlu.isGiven() == true || (variableObjS == false && !adjoint) ? objSlu : objSlu.getAddress(run1 * NU, 0);
1534  multRDy, R2Call, Dy.getAddress(run1 * NY, 0), SluCall, g.getAddress(offset + run1 * NU, 0)
1535  );
1536  }
1538 
1539  // Compute QDy
1540  for(unsigned run1 = 0; run1 < N; run1++ )
1541  {
1542  ExportArgument Q2Call = Q2.isGiven() == true ? Q2 : Q2.getAddress(run1 * NX);
1543  ExportArgument SlxCall =
1544  objSlx.isGiven() == true || (variableObjS == false && !adjoint) ? objSlx : objSlx.getAddress(run1 * NX, 0);
1546  multQDy, Q2Call, Dy.getAddress(run1 * NY), SlxCall, QDy.getAddress(run1 * NX) );
1547  }
1549  ExportVariable SlxCall =
1550  objSlx.isGiven() == true || (variableObjS == false && !adjoint) ? objSlx : objSlx.getRows(N * NX, (N + 1) * NX);
1551  condenseFdb.addStatement( QDy.getRows(N * NX, (N + 1) * NX) == QN2 * DyN );
1552  condenseFdb.addStatement( QDy.getRows(N * NX, (N + 1) * NX) += SlxCall );
1554  }
1555 
1556 
1557  if (performFullCondensing() == false)
1559 
1560  /*
1561  if partial condensing:
1562  g0 = q_0
1563 
1564  for k = 0: N - 1
1565  g1_k = r_k
1566 
1567  if partial condensing:
1568  sbar_0 = 0;
1569  else:
1570  sbar_0 = Dx_0;
1571 
1572  sbar(1: N) = d;
1573 
1574  for k = 0: N - 1
1575  sbar_{k + 1} += A_k sbar_k;
1576 
1577  w1 = Q_N^T * sbar_N + q_N;
1578  for k = N - 1: 1
1579  {
1580  g1_k += B_k^T * w1;
1581  g1_k += S_k^T * sbar_k;
1582  w2 = A_k^T * w1 + q_k;
1583  w1 = Q_k^T * sbar_k + w2;
1584  }
1585 
1586  g1_0 += B_0^T * w1;
1587  if partial condensing:
1588  g_0 += A_0^T * w1
1589  else:
1590  g1_0 += S^0^T * x0;
1591 
1592  */
1593 
1594  w1.setup("w1", NX, 1, REAL, ACADO_WORKSPACE);
1595  w2.setup("w2", NX, 1, REAL, ACADO_WORKSPACE);
1596  sbar.setup("sbar", (N + 1) * NX, 1, REAL, ACADO_WORKSPACE);
1597 
1598  if( performFullCondensing() == true ) {
1600  }
1601  else {
1602  condensePrep.addStatement( sbar.getRows(0, NX) == zeros<double>(NX,1) ); // Dx0 is now a variable as well !!
1603  }
1604  condensePrep.addStatement( sbar.getRows(NX, (N + 1) * NX) == d );
1605 
1606  for (unsigned i = 0; i < N; ++i)
1608  macASbar, evGx.getAddress(i * NX), sbar.getAddress(i * NX), sbar.getAddress((i + 1) * NX)
1609  );
1611 
1613  w1 == QDy.getRows(N * NX, (N + 1) * NX) + QN1 * sbar.getRows(N * NX, (N + 1) * NX)
1614  );
1615  for (unsigned i = N - 1; 0 < i; --i)
1616  {
1618  macBTw1, evGu.getAddress(i * NX), w1, g.getAddress(offset + i * NU)
1619  );
1620 
1621  if ((S1.isGiven() == true && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1622  {
1623  ExportArgument S1Call = S1.isGiven() == false ? S1.getAddress(i * NX) : S1;
1624  condenseFdb.addFunctionCall(macS1TSbar, S1Call, sbar.getAddress(i * NX), g.getAddress(offset + i * NU));
1625  }
1626 
1628  // TODO Check indexing for QDy
1629  macATw1QDy, evGx.getAddress(i * NX), w1, QDy.getAddress(i * NX), w2
1630  );
1631 
1632  ExportArgument Q1Call = Q1.isGiven() == true ? Q1 : Q1.getAddress(i * NX);
1634  macQSbarW2, Q1Call, sbar.getAddress(i * NX), w2, w1);
1635  }
1637  macBTw1, evGu.getAddress( 0 ), w1, g.getAddress( offset + 0 )
1638  );
1639  if( performFullCondensing() == true ) {
1640  if ((S1.isGiven() == true && S1.getGivenMatrix().isZero() == false) || S1.isGiven() == false)
1641  {
1643  }
1644  }
1645  else {
1646  condenseFdb.addStatement(g.getRows(0, NX) += evGx.getRows(0, NX).getTranspose() * w1);
1647  }
1649 
1650 
1652  //
1653  // Expansion routine
1654  //
1656 
1657  /*
1658 
1659  // Step expansion, assuming that u_k is already updated
1660 
1661  Ds_0 = Dx_0;
1662  Ds_{1: N} = d;
1663 
1664  for i = 0: N - 1
1665  {
1666  Ds_{k + 1} += A_k * Ds_k; // Reuse multABarD
1667  Ds_{k + 1} += B_k * Du_k;
1668  s_{k + 1} += Ds_{k + 1};
1669  }
1670 
1671  */
1672 
1673  LOG( LVL_DEBUG ) << "Setup condensing: create expand routine" << endl;
1674 
1675  expand.setup( "expand" );
1676 
1677  if (performFullCondensing() == true)
1678  {
1680  }
1681  else
1682  {
1684  }
1685 
1686  if( performFullCondensing() == true ) {
1687  expand.addStatement( sbar.getRows(0, NX) == Dx0 );
1688  }
1689  else {
1690  expand.addStatement( sbar.getRows(0, NX) == xVars.getRows(0, NX) );
1691  }
1692  expand.addStatement( sbar.getRows(NX, (N + 1) * NX) == d );
1693 
1694  for (unsigned row = 0; row < N; ++row )
1697  xVars.getAddress(offset + row * NU), sbar.getAddress(row * NX),
1698  sbar.getAddress((row + 1) * NX)
1699  );
1700 
1702 
1703  // !! Calculation of multipliers: !!
1704  int hessianApproximation;
1705  get( HESSIAN_APPROXIMATION, hessianApproximation );
1706  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
1707  if( secondOrder || adjoint ) {
1708  // mu_N = lambda_N + q_N + Q_N^T * Ds_N --> wrong in Joel's paper !!
1709  // for i = N - 1: 1
1710  // mu_k = Q_k^T * Ds_k + A_k^T * mu_{k + 1} + S_k * Du_k + q_k
1711 
1712  for (uint j = 0; j < NX; j++ ) {
1713  uint item = N*NX+j;
1714  uint IdxF = std::find(xBoundsIdx.begin(), xBoundsIdx.end(), item) - xBoundsIdx.begin();
1715  if( IdxF != xBoundsIdx.size() ) { // INDEX FOUND
1716  expand.addStatement( mu.getSubMatrix(N-1,N,j,j+1) == -1.0*yVars.getRow(getNumQPvars()+IdxF) );
1717  }
1718  else { // INDEX NOT FOUND
1719  expand.addStatement( mu.getSubMatrix(N-1,N,j,j+1) == 0.0 );
1720  }
1721  if( getNumComplexConstraints() ) {
1722  if( dimPocH > 0 ) return ACADOERROR( RET_NOT_IMPLEMENTED_YET );
1723  // HERE: POINT CONSTRAINTS ON TERMINAL STATE??
1724  }
1725  }
1726  expand.addStatement( mu.getRow(N-1) += sbar.getRows(N*NX,(N+1)*NX).getTranspose()*QN1 );
1727  expand.addStatement( mu.getRow(N-1) += QDy.getRows(N*NX,(N+1)*NX).getTranspose() );
1728  for (int i = N - 1; i >= 1; i--) {
1729  for (uint j = 0; j < NX; j++ ) {
1730  uint item = i*NX+j;
1731  uint IdxF = std::find(xBoundsIdx.begin(), xBoundsIdx.end(), item) - xBoundsIdx.begin();
1732  if( IdxF != xBoundsIdx.size() ) { // INDEX FOUND
1733  expand.addStatement( mu.getSubMatrix(i-1,i,j,j+1) == -1.0*yVars.getRow(getNumQPvars()+IdxF) );
1734  }
1735  else { // INDEX NOT FOUND
1736  expand.addStatement( mu.getSubMatrix(i-1,i,j,j+1) == 0.0 );
1737  }
1738  if( getNumComplexConstraints() ) {
1739  if( dimPocH > 0 ) return ACADOERROR( RET_NOT_IMPLEMENTED_YET );
1740  if( pacEvHx.isGiven() == false ) {
1741  expand.addStatement( mu.getSubMatrix(i-1,i,j,j+1) -= yVars.getRows(getNumQPvars()+getNumStateBounds()+i*dimPacH,getNumQPvars()+getNumStateBounds()+i*dimPacH+dimPacH).getTranspose()*pacEvHx.getSubMatrix(i*dimPacH,i*dimPacH+dimPacH,j,j+1) );
1742  }
1743  else {
1745  }
1746  }
1747  }
1749  expansionStep2, QDy.getAddress(i*NX), Q1.getAddress(i * NX), sbar.getAddress(i*NX),
1750  S1.getAddress(i * NX), xVars.getAddress(offset + i * NU), evGx.getAddress(i * NX),
1751  mu.getAddress(i-1), mu.getAddress(i) );
1752  }
1753  }
1754 
1755  return SUCCESSFUL_RETURN;
1756 }
1757 
1759 {
1761  //
1762  // Make index vector for state constraints
1763  //
1765 
1766  bool boxConIsFinite = false;
1767  xBoundsIdx.clear();
1768 
1769  DVector lbBox, ubBox;
1770  for (unsigned i = 0; i < xBounds.getNumPoints(); ++i)
1771  {
1772  lbBox = xBounds.getLowerBounds( i );
1773  ubBox = xBounds.getUpperBounds( i );
1774 
1775  if (isFinite( lbBox ) || isFinite( ubBox ))
1776  boxConIsFinite = true;
1777 
1778  // This is maybe not necessary
1779  if (boxConIsFinite == false || i == 0)
1780  continue;
1781 
1782  for (unsigned j = 0; j < lbBox.getDim(); ++j)
1783  {
1784  if ( ( acadoIsFinite( ubBox( j ) ) == true ) || ( acadoIsFinite( lbBox( j ) ) == true ) )
1785  {
1786  xBoundsIdx.push_back(i * lbBox.getDim() + j);
1787  }
1788  }
1789  }
1790 
1791  if (initialStateFixed() == true)
1792  {
1793  x0.setup("x0", NX, 1, REAL, ACADO_VARIABLES);
1794  x0.setDoc( (std::string)"Current state feedback vector." );
1795  Dx0.setup("Dx0", NX, 1, REAL, ACADO_WORKSPACE);
1796  }
1797 
1798  if (performFullCondensing() == false || getNumComplexConstraints() > 0)
1799  {
1800  C.setup("C", N*NX, NX, REAL, ACADO_WORKSPACE);
1801  }
1802  E.setup("E", N * (N + 1) / 2 * NX, NU, REAL, ACADO_WORKSPACE);
1803 
1804  QDy.setup ("QDy", (N + 1) * NX, 1, REAL, ACADO_WORKSPACE);
1805 
1807  g.setup("g", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1809 
1810  lb.setup("lb", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1811  ub.setup("ub", getNumQPvars(), 1, REAL, ACADO_WORKSPACE);
1812 
1815 
1818 
1819  return SUCCESSFUL_RETURN;
1820 }
1821 
1823 {
1824  ExportIndex iCol( "iCol" );
1825  ExportIndex iRow( "iRow" );
1826 
1827  ExportVariable dp, dn, Gx1, Gx2, Gx3, Gx4, Gu1, Gu2, Gu3;
1828  ExportVariable R22, Dy1, RDy1, Q22, QDy1, E1, U1, U2, H101, w11, w12, w13;
1829  dp.setup("dOld", NX, 1, REAL, ACADO_LOCAL);
1830  dn.setup("dNew", NX, 1, REAL, ACADO_LOCAL);
1831  Gx1.setup("Gx1", NX, NX, REAL, ACADO_LOCAL);
1832  Gx2.setup("Gx2", NX, NX, REAL, ACADO_LOCAL);
1833  Gx3.setup("Gx3", NX, NX, REAL, ACADO_LOCAL);
1834  Gx4.setup("Gx4", NX, NX, REAL, ACADO_LOCAL);
1835  Gu1.setup("Gu1", NX, NU, REAL, ACADO_LOCAL);
1836  Gu2.setup("Gu2", NX, NU, REAL, ACADO_LOCAL);
1837  Gu3.setup("Gu3", NX, NU, REAL, ACADO_LOCAL);
1838  R22.setup("R2", NU, NY, REAL, ACADO_LOCAL);
1839  Dy1.setup("Dy1", NY, 1, REAL, ACADO_LOCAL);
1840  RDy1.setup("RDy1", NU, 1, REAL, ACADO_LOCAL);
1841  Q22.setup("Q2", NX, NY, REAL, ACADO_LOCAL);
1842  QDy1.setup("QDy1", NX, 1, REAL, ACADO_LOCAL);
1843  E1.setup("E1", NX, NU, REAL, ACADO_LOCAL);
1844  U1.setup("U1", NU, 1, REAL, ACADO_LOCAL);
1845  U2.setup("U2", NU, 1, REAL, ACADO_LOCAL);
1846  H101.setup("H101", NU, NX, REAL, ACADO_LOCAL);
1847 
1848  w11.setup("w11", NX, 1, REAL, ACADO_LOCAL);
1849  w12.setup("w12", NX, 1, REAL, ACADO_LOCAL);
1850  w13.setup("w13", NX, 1, REAL, ACADO_LOCAL);
1851 
1852  if ( Q2.isGiven() )
1853  Q22 = Q2;
1854  if ( R2.isGiven() )
1855  R22 = R2;
1856 
1857  // multGxd; // d_k += Gx_k * d_{k-1}
1858  multGxd.setup("multGxd", dp, Gx1, dn);
1859  multGxd.addStatement( dn += Gx1 * dp );
1860 
1861  if( performFullCondensing() == false || getNumComplexConstraints() > 0 ) {
1862  // moveGxT
1863  moveGxT.setup("moveGxT", Gx1, Gx2);
1864  moveGxT.addStatement( Gx2 == Gx1 );
1865  // multGxGx
1866  multGxGx.setup("multGxGx", Gx1, Gx2, Gx3);
1867  multGxGx.addStatement( Gx3 == Gx1 * Gx2 );
1868  }
1869 
1870  // multGxGu
1871  multGxGu.setup("multGxGu", Gx1, Gu1, Gu2);
1872  multGxGu.addStatement( Gu2 == Gx1 * Gu1 );
1873  // moveGuE
1874  moveGuE.setup("moveGuE", Gu1, Gu2);
1875  moveGuE.addStatement( Gu2 == Gu1 );
1876 
1877  unsigned offset = (performFullCondensing() == true) ? 0 : NX;
1878 
1879  // copyHTH
1880  copyHTH.setup("copyHTH", iRow, iCol);
1882  H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, offset + iCol * NU, offset + (iCol + 1) * NU) ==
1883  H.getSubMatrix(offset + iCol * NU, offset + (iCol + 1) * NU, offset + iRow * NU, offset + (iRow + 1) * NU).getTranspose()
1884  );
1885 
1886  if( performFullCondensing() == false ) {
1887  // copyHTH1
1888  copyHTH1.setup("copyHTH1", iCol);
1890  H.getSubMatrix(0, NX, offset + iCol * NU, offset + (iCol + 1) * NU) ==
1891  H.getSubMatrix(offset + iCol * NU, offset + (iCol + 1) * NU, 0, NX).getTranspose()
1892  );
1893  }
1894  // multRDy
1895  ExportVariable SluCall = objSlu.isGiven() == true ? objSlu : ExportVariable("Slu", NU, 1, REAL, ACADO_LOCAL);
1896  multRDy.setup("multRDy", R22, Dy1, SluCall, RDy1);
1897  multRDy.addStatement( RDy1 == R22 * Dy1 );
1898  multRDy.addStatement( RDy1 += SluCall );
1899 
1900  // mult QDy1
1901  ExportVariable SlxCall = objSlx.isGiven() == true ? objSlx : ExportVariable("Slx", NX, 1, REAL, ACADO_LOCAL);
1902  multQDy.setup("multQDy", Q22, Dy1, SlxCall, QDy1);
1903  multQDy.addStatement( QDy1 == Q22 * Dy1 );
1904  multQDy.addStatement( QDy1 += SlxCall );
1905  // multEQDy;
1906  multEQDy.setup("multEQDy", E1, QDy1, U1);
1907  multEQDy.addStatement( U1 += (E1 ^ QDy1) );
1908  // multQETGx
1909  multQETGx.setup("multQETGx", E1, Gx1, H101);
1910  multQETGx.addStatement( H101 += (E1 ^ Gx1) );
1911 
1912  if (performsSingleShooting() == false)
1913  {
1914  // multEDu
1915  multEDu.setup("multEDu", E1, U1, dn);
1916  multEDu.addStatement( dn += E1 * U1 );
1917  }
1918 
1919  if (Q1.isGiven() == true)
1920  {
1921  // multQ1Gx
1922  multQ1Gx.setup("multQ1Gx", Gx1, Gx2);
1923  multQ1Gx.addStatement( Gx2 == Q1 * Gx1 );
1924 
1925  // multQ1Gu
1926  multQ1Gu.setup("multQ1Gu", Gu1, Gu2);
1927  multQ1Gu.addStatement( Gu2 == Q1 * Gu1 );
1928 
1929  // multQ1d
1930  multQ1d.setup("multQ1d", Q1, dp, dn);
1931  multQ1d.addStatement( dn == Q1 * dp );
1932  }
1933  else
1934  {
1935  // multQ1d
1936  multQ1d.setup("multQ1d", Gx1, dp, dn);
1937  multQ1d.addStatement( dn == Gx1 * dp );
1938  }
1939 
1940  if (QN1.isGiven() == true)
1941  {
1942  // multQN1Gx
1943  multQN1Gx.setup("multQN1Gx", QN1, Gx1, Gx2);
1944  multQN1Gx.addStatement( Gx2 == QN1 * Gx1 );
1945 
1946  // multQN1Gu
1947  multQN1Gu.setup("multQN1Gu", QN1, Gu1, Gu2);
1948  multQN1Gu.addStatement( Gu2 == QN1 * Gu1 );
1949 
1950  // multQN1d
1951  multQN1d.setup("multQN1d", QN1, dp, dn);
1952  multQN1d.addStatement( dn == QN1 * dp );
1953  }
1954 
1955  //
1956  // N2 condensing related
1957  //
1958 
1959  multBTW1.setup("multBTW1", Gu1, Gu2, iRow, iCol);
1961  H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, offset + iCol * NU, offset + (iCol + 1) * NU) ==
1962  (Gu1 ^ Gu2)
1963  );
1964 
1965  multGxTGu.setup("multGxTGu", Gx1, Gu1, Gu2);
1966  multGxTGu.addStatement( Gu2 == (Gx1 ^ Gu1) );
1967 
1968  ExportVariable Q11 = Q1.isGiven() ? Q1 : ExportVariable("Q11", NX, NX, REAL, ACADO_LOCAL);
1969 
1970  macQEW2.setup("multQEW2", Q11, Gu1, Gu2, Gu3);
1971  macQEW2.addStatement( Gu3 == Gu2 + Q11 * Gu1 );
1972 
1973  macASbar.setup("macASbar", Gx1, w11, w12);
1974  macASbar.addStatement( w12 += Gx1 * w11 );
1975 
1976  macBTw1.setup("macBTw1", Gu1, w11, U1);
1977  macBTw1.addStatement( U1 += Gu1 ^ w11 );
1978 
1979  macATw1QDy.setup("macATw1QDy", Gx1, w11, w12, w13);
1980  macATw1QDy.addStatement( w13 == w12 + (Gx1 ^ w11) );
1981 
1982  macQSbarW2.setup("macQSbarW2", Q11, w11, w12, w13);
1983  macQSbarW2.addStatement( w13 == w12 + Q11 * w11 );
1984 
1985  expansionStep.setup("expansionStep", Gx1, Gu1, U1, w11, w12);
1986  expansionStep.addStatement( w12 += Gx1 * w11 );
1987  expansionStep.addStatement( w12 += Gu1 * U1 );
1988 
1989  //
1990  // Define LM regularization terms
1991  //
1992  DMatrix mRegH11 = eye<double>( getNU() );
1993  mRegH11 *= levenbergMarquardt;
1994 
1995  ExportVariable R11 = R1.isGiven() == true ? R1 : ExportVariable("R11", NU, NU, REAL, ACADO_LOCAL);
1996 
1997  macBTW1_R1.setup("multBTW1_R1", R11, Gu1, Gu2, iRow);
1999  H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, offset + iRow * NU, offset + (iRow + 1) * NU) ==
2000  R11 + (Gu1 ^ Gu2)
2001  );
2003  H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, offset + iRow * NU, offset + (iRow + 1) * NU) += mRegH11
2004  );
2005 
2006  ExportVariable S11 = zeros<double>(NX, NU);
2007  if (S1.isGiven() == true && S1.getGivenMatrix().isZero() == false)
2008  S11 = S1;
2009  else if (S1.isGiven() == false)
2010  S11 = Gu1;
2011 
2012  if ((S11.isGiven() == true && S11.getGivenMatrix().isZero() == false) || S11.isGiven() == false)
2013  {
2014  mac_S1T_E.setup("mac_S1T_E", S11, Gu2, iRow, iCol);
2016  H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, offset + iCol * NU, offset + (iCol + 1) * NU) +=
2017  (S11 ^ Gu2)
2018  );
2019 
2020  macS1TSbar.setup("macS1TSbar", S11, w11, U1);
2021  macS1TSbar.addStatement( U1 += (S11 ^ w11) );
2022  }
2023 
2024  int gradientUp;
2025  get( LIFTED_GRADIENT_UPDATE, gradientUp );
2026  bool gradientUpdate = (bool) gradientUp;
2027 
2028  int hessianApproximation;
2029  get( HESSIAN_APPROXIMATION, hessianApproximation );
2030  bool secondOrder = ((HessianApproximationMode)hessianApproximation == EXACT_HESSIAN);
2031  int sensitivityProp;
2032  get( DYNAMIC_SENSITIVITY, sensitivityProp );
2033  bool adjoint = ((ExportSensitivityType) sensitivityProp == BACKWARD || ((ExportSensitivityType) sensitivityProp == INEXACT && gradientUpdate));
2034  if( secondOrder || adjoint ) {
2035  ExportVariable mu1; mu1.setup("mu1", 1, NX, REAL, ACADO_LOCAL);
2036  ExportVariable mu2; mu2.setup("mu2", 1, NX, REAL, ACADO_LOCAL);
2037 
2038  expansionStep2.setup("expansionStep2", QDy1, Q11, w11, S11, U1, Gx1, mu1, mu2);
2039  expansionStep2.addStatement( mu1 += QDy1.getTranspose() );
2040  expansionStep2.addStatement( mu1 += w11 ^ Q11.getTranspose() );
2041  expansionStep2.addStatement( mu1 += U1 ^ S11.getTranspose() );
2042  expansionStep2.addStatement( mu1 += mu2*Gx1 );
2043  }
2044 
2045  if (performFullCondensing() == false)
2046  {
2047  // ExportFunction mult_BT_T1, mac_ST_C, multGxTGx, macGxTGx;
2048 
2049  mult_BT_T1.setup("mult_BT_T1", Gu1, Gx1, iRow);
2050  mult_BT_T1.addStatement( H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, 0, NX) == (Gu1 ^ Gx1) );
2051 
2052  if ((S11.isGiven() == true && S11.getGivenMatrix().isZero() == false) || S11.isGiven() == false)
2053  {
2054  mac_ST_C.setup("mac_ST_C", S11, Gx1, iRow);
2055  mac_ST_C.addStatement( H.getSubMatrix(offset + iRow * NU, offset + (iRow + 1) * NU, 0, NX) += (S11 ^ Gx1) );
2056  }
2057 
2058  multGxTGx.setup("multGxTGx", Gx1, Gx2, Gx3);
2059  multGxTGx.addStatement( Gx3 == (Gx1 ^ Gx2) );
2060 
2061  macGxTGx.setup("macGxTGx", Gx1, Q11, Gx3, Gx4);
2062  macGxTGx.addStatement( Gx4 == Gx1 + (Q11 * Gx3) );
2063  }
2064 
2065  return SUCCESSFUL_RETURN;
2066 }
2067 
2069 {
2070  int hessianRegularization;
2071  get( HESSIAN_REGULARIZATION, hessianRegularization );
2073  //
2074  // Preparation phase
2075  //
2077 
2078  preparation.setup( "preparationStep" );
2079  preparation.doc( "Preparation step of the RTI scheme." );
2080  ExportVariable retSim("ret", 1, 1, INT, ACADO_LOCAL, true);
2081  retSim.setDoc("Status of the integration module. =0: OK, otherwise the error code.");
2082  preparation.setReturnValue(retSim, false);
2083 
2084  preparation << retSim.getFullName() << " = " << modelSimulation.getName() << "();\n";
2085 
2087  if( regularizeHessian.isDefined() ) { // ALSO IN THE CASE OF CONDENSED REGULARIZATION, THIS IS CURRENTLY NECESSARY:
2089  }
2091  if( regularizeHessian.isDefined() && (HessianRegularizationMode)hessianRegularization == CONDENSED_REG ) {
2093  }
2094 
2096  //
2097  // Feedback phase
2098  //
2100 
2101  ExportVariable tmp("tmp", 1, 1, INT, ACADO_LOCAL, true);
2102  tmp.setDoc( "Status code of the qpOASES QP solver." );
2103 
2104  ExportFunction solve("solve");
2105  solve.setReturnValue( tmp );
2106 
2107  feedback.setup("feedbackStep");
2108  feedback.doc( "Feedback/estimation step of the RTI scheme." );
2109  feedback.setReturnValue( tmp );
2110 
2113 
2114  stringstream s;
2115  s << tmp.getName() << " = " << solve.getName() << "( );" << endl;
2116  feedback << s.str();
2118 
2120 
2122  //
2123  // Setup evaluation of the KKT tolerance
2124  //
2126 
2127  ExportVariable kkt("kkt", 1, 1, REAL, ACADO_LOCAL, true);
2128  ExportVariable prd("prd", 1, 1, REAL, ACADO_LOCAL, true);
2129  ExportIndex index( "index" );
2130 
2131  getKKT.setup( "getKKT" );
2132  getKKT.doc( "Get the KKT tolerance of the current iterate." );
2133  kkt.setDoc( "The KKT tolerance value." );
2134  getKKT.setReturnValue( kkt );
2135  getKKT.addVariable( prd );
2136  getKKT.addIndex( index );
2137 
2138  // ACC = |\nabla F^T * xVars|
2139  getKKT.addStatement( kkt == (g ^ xVars) );
2140  getKKT << kkt.getFullName() << " = fabs( " << kkt.getFullName() << " );\n";
2141 
2142  ExportForLoop bLoop(index, 0, getNumQPvars());
2143 
2144  bLoop.addStatement( prd == yVars.getRow( index ) );
2145  bLoop << "if (" << prd.getFullName() << " > " << toString(1.0 / INFTY) << ")\n";
2146  bLoop << kkt.getFullName() << " += fabs(" << lb.get(index, 0) << " * " << prd.getFullName() << ");\n";
2147  bLoop << "else if (" << prd.getFullName() << " < " << toString(-1.0 / INFTY) << ")\n";
2148  bLoop << kkt.getFullName() << " += fabs(" << ub.get(index, 0) << " * " << prd.getFullName() << ");\n";
2149  getKKT.addStatement( bLoop );
2150 
2152  {
2154 
2155  cLoop.addStatement( prd == yVars.getRow( getNumQPvars() + index ));
2156  cLoop << "if (" << prd.getFullName() << " > " << toString(1.0 / INFTY) << ")\n";
2157  cLoop << kkt.getFullName() << " += fabs(" << lbA.get(index, 0) << " * " << prd.getFullName() << ");\n";
2158  cLoop << "else if (" << prd.getFullName() << " < " << toString(-1.0 / INFTY) << ")\n";
2159  cLoop << kkt.getFullName() << " += fabs(" << ubA.get(index, 0) << " * " << prd.getFullName() << ");\n";
2160 
2161  getKKT.addStatement( cLoop );
2162  }
2163 
2164  return SUCCESSFUL_RETURN;
2165 }
2166 
2168 {
2169  string folderName;
2170  get(CG_EXPORT_FOLDER_NAME, folderName);
2171 
2172  string moduleName;
2173  get(CG_MODULE_NAME, moduleName);
2174 
2175  int qpSolver;
2176  get(QP_SOLVER, qpSolver);
2177 
2178  std::string sourceFile, headerFile, solverDefine;
2179  ExportQpOasesInterface* qpInterface = 0;
2180 
2181  switch ( (QPSolverName)qpSolver )
2182  {
2183  case QP_QPOASES:
2184  sourceFile = folderName + "/" + moduleName + "_qpoases_interface.cpp";
2185  headerFile = folderName + "/" + moduleName + "_qpoases_interface.hpp";
2186  solverDefine = "QPOASES_HEADER";
2187  qpInterface = new ExportQpOasesInterface(headerFile, sourceFile, "");
2188  break;
2189 
2190  case QP_QPOASES3:
2191  sourceFile = folderName + "/" + moduleName + "_qpoases3_interface.c";
2192  headerFile = folderName + "/" + moduleName + "_qpoases3_interface.h";
2193  solverDefine = "QPOASES3_HEADER";
2194  qpInterface = new ExportQpOases3Interface(headerFile, sourceFile, "");
2195  break;
2196 
2197  default:
2199  "For condensed solution only qpOASES and qpOASES3 QP solver are supported");
2200  }
2201 
2202  int useSinglePrecision;
2203  get(USE_SINGLE_PRECISION, useSinglePrecision);
2204 
2205  int hotstartQP;
2206  get(HOTSTART_QP, hotstartQP);
2207 
2208  int covCalc;
2209  get(CG_COMPUTE_COVARIANCE_MATRIX, covCalc);
2210 
2211  int maxNumQPiterations;
2212  get(MAX_NUM_QP_ITERATIONS, maxNumQPiterations);
2213 
2214  //
2215  // Set up export of the source file
2216  //
2217 
2218  if ( qpInterface == 0 )
2219  return RET_UNKNOWN_BUG;
2220 
2221  qpInterface->configure(
2222  "",
2223  solverDefine,
2224  getNumQPvars(),
2226  maxNumQPiterations,
2227  "PL_NONE",
2228  useSinglePrecision,
2229 
2231  "",
2232  xVars.getFullName(),
2233  yVars.getFullName(),
2234  "", // TODO
2235 // sigma.getFullName(),
2236  hotstartQP,
2237  true,
2238  H.getFullName(),
2239  string(),
2240  g.getFullName(),
2241  A.getFullName(),
2242  lb.getFullName(),
2243  ub.getFullName(),
2244  lbA.getFullName(),
2245  ubA.getFullName()
2246  );
2247 
2248  returnValue returnvalue = qpInterface->exportCode();
2249 
2250  if ( qpInterface != 0 )
2251  delete qpInterface;
2252 
2253  return returnvalue;
2254 }
2255 
2257 {
2258  int sparseQPsolution;
2259  get(SPARSE_QP_SOLUTION, sparseQPsolution);
2260 
2261  if ((SparseQPsolutionMethods)sparseQPsolution == CONDENSING || (SparseQPsolutionMethods)sparseQPsolution == CONDENSING_N2 || (SparseQPsolutionMethods)sparseQPsolution == BLOCK_CONDENSING_N2)
2262  return false;
2263 
2264  return (initialStateFixed() == true);
2265 }
2266 
virtual returnValue setupCondensing()
uint getNumPoints() const
virtual returnValue setupMultiplicationRoutines()
#define LOG(level)
Just define a handy macro for getting the logger.
#define R22
Lowest level, the debug level.
ExportVariable objEvFx
HessianApproximationMode
std::string getFullName() const
virtual bool isDefined() const
ExportVariable conValueOut
ExportVariable objS
ExportVariable objSlu
const DMatrix & getGivenMatrix() const
ExportFunction shiftStates
ExportVariable pacEvHx
SparseQPsolutionMethods
const double INFTY
virtual returnValue setupObjectiveEvaluation(void)
ExportVariable pocEvH
VariablesGrid xBounds
ExportVariable pocEvHx
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 bool isGiven() const
DVector getLowerBounds(uint pointIdx) const
bool performsSingleShooting() const
Allows to pass back messages to the calling function.
ExportVariable conValueIn
ExportVariable pacEvHu
virtual uint getDim() const
ExportVariable getRow(const ExportIndex &idx) const
returnValue addComment(const std::string &_comment)
HessianRegularizationMode
virtual returnValue configure(const std::string &_prefix, const std::string &_solverDefine, const int nvmax, const int ncmax, const int nwsrmax, const std::string &_printLevel, bool _useSinglePrecision, const std::string &_commonHeader, const std::string &_namespace, const std::string &_primalSolution, const std::string &_dualSolution, const std::string &_sigma, bool _hotstartQP, bool _externalCholesky, const std::string &_qpH, const std::string &_qpR, const std::string &_qpg, const std::string &_qpA, const std::string &_qplb, const std::string &_qpub, const std::string &_qplbA, const std::string &_qpubA)
ExportVariable objEvFxEnd
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
virtual returnValue setupConstraintsEvaluation(void)
Allows to export code of a for-loop.
string toString(T const &value)
VariablesGrid uBounds
#define R11
ExportVariable objSlx
#define CLOSE_NAMESPACE_ACADO
DVector getUpperBounds(uint pointIdx) const
ExportVariable DyN
ExportVariable state
ExportVariable evGx
Defines a scalar-valued index variable to be used for exporting code.
ExportVariable getSubMatrix(const ExportIndex &rowIdx1, const ExportIndex &rowIdx2, const ExportIndex &colIdx1, const ExportIndex &colIdx2) const
Base class for export of NLP/OCP solvers.
ExportAcadoFunction evaluateStageCost
A class for generating the glue code for interfacing qpOASES.
ExportVariable getRows(const ExportIndex &idx1, const ExportIndex &idx2) const
virtual returnValue setup()
Defines a matrix-valued variable that can be passed as argument to exported functions.
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
ExportAcadoFunction evaluateTerminalCost
bool initialStateFixed() const
ExportFunction regularization
ExportFunction & setup(const std::string &_name="defaultFunctionName", 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)
#define YES
Definition: acado_types.hpp:51
virtual returnValue setupEvaluation()
virtual returnValue setDoc(const std::string &_doc)
virtual returnValue setupInitialization()
std::string commonHeaderName
ExportStruct
ExportFunction modelSimulation
virtual ExportFunction & doc(const std::string &_doc)
ExportFunction getObjective
virtual returnValue setupQPInterface()
virtual returnValue getFunctionDeclarations(ExportStatementBlock &declarations) const
ExportVariable objValueIn
ExportFunction initializeNodes
bool isGiven(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
ExportVariable pacEvHxd
virtual returnValue exportCode()
ExportVariable getTranspose() const
ExportVariable QN2
virtual returnValue setupSimulation(void)
ExportVariable QN1
std::vector< std::shared_ptr< ExportAcadoFunction > > evaluatePointConstraints
Encapsulates all user interaction for setting options, logging data and plotting results.
Allows to export code of an arbitrary function.
ExportFunction shiftControls
returnValue addStatement(const ExportStatement &_statement)
std::string getName() const
Definition: export_data.cpp:86
returnValue addLinebreak(uint num=1)
ExportAcadoFunction evaluatePathConstraints
GenericVector & append(const GenericVector &_arg)
Definition: vector.cpp:42
ExportFunction & setReturnValue(const ExportVariable &_functionReturnValue, bool _returnAsPointer=false)
virtual ExportFunction & acquire(ExportIndex &obj)
RowXpr row(Index i)
Definition: BlockMethods.h:725
ExportFunction & addVariable(const ExportVariable &_var)
GenericVector< double > DVector
Definition: vector.hpp:329
BooleanType acadoIsFinite(double x, double TOL)
ExportVariable evGu
ExportVariable objSEndTerm
returnValue addDeclaration(const ExportVariable &_data, ExportStruct _dataStruct=ACADO_ANY)
returnValue setupAuxiliaryFunctions()
ExportArgument getAddress(const ExportIndex &_rowIdx, const ExportIndex &_colIdx=emptyConstExportIndex) const
virtual ExportFunction & release(const ExportIndex &obj)
virtual unsigned getNumStateBounds() const
unsigned getNumComplexConstraints(void)
unsigned getDim() const
Definition: vector.hpp:172
ExportGaussNewtonCN2(UserInteraction *_userInteraction=0, const std::string &_commonHeaderName="")
std::string getName() const
#define BEGIN_NAMESPACE_ACADO
BooleanType isFinite(const T &_value)
const std::string get(const ExportIndex &rowIdx, const ExportIndex &colIdx) const
returnValue addFunction(const ExportFunction &_function)
ExportVariable pocEvHxd
ColXpr col(Index i)
Definition: BlockMethods.h:708
virtual returnValue setupVariables()
A class for generating the glue code for interfacing qpOASES.
ExportVariable objEvFu
QPSolverName
std::vector< unsigned > xBoundsIdx
double getLowerBound(uint pointIdx, uint valueIdx) const
virtual returnValue getCode(ExportStatementBlock &code)
ExportVariable pacEvH
ExportVariable pocEvHu
ExportVariable pacEvDDH
uint getNX() const
ExportVariable getCols(const ExportIndex &idx1, const ExportIndex &idx2) const
ExportVariable makeRowVector() const
Allows to export code for a block of statements.
ExportFunction initialize
ExportVariable objValueOut
virtual returnValue getDataDeclarations(ExportStatementBlock &declarations, ExportStruct dataStruct=ACADO_ANY) const
ExportVariable getCol(const ExportIndex &idx) const
ExportFunction & addIndex(const ExportIndex &_index)
ExportFunction regularizeHessian
double getUpperBound(uint pointIdx, uint valueIdx) const
#define ACADOERROR(retval)
ExportVariable makeColVector() const
Defines a matrix-valued variable to be used for exporting code.
#define ACADOERRORTEXT(retval, text)
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)


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Feb 28 2022 21:31:53