matrix_variables_grid.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 
37 
38 #include <iomanip>
39 
40 using namespace std;
41 
43 
44 //
45 // PUBLIC MEMBER FUNCTIONS:
46 //
47 
49 {
50  values = 0;
51 }
52 
53 
55  uint _nCols,
56  const Grid& _grid,
57  VariableType _type,
58  const char** const _names,
59  const char** const _units,
60  const DVector* const _scaling,
61  const DVector* const _lb,
62  const DVector* const _ub,
63  const BooleanType* const _autoInit
64  ) : Grid( )
65 {
66  values = 0;
67  init( _nRows,_nCols,_grid,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
68 }
69 
70 
72  uint _nCols,
73  uint _nPoints,
74  VariableType _type,
75  const char** const _names,
76  const char** const _units,
77  const DVector* const _scaling,
78  const DVector* const _lb,
79  const DVector* const _ub,
80  const BooleanType* const _autoInit
81  ) : Grid( )
82 {
83  values = 0;
84  init( _nRows,_nCols,_nPoints,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
85 }
86 
87 
89  uint _nCols,
90  double _firstTime,
91  double _lastTime,
92  uint _nPoints,
93  VariableType _type,
94  const char** const _names,
95  const char** const _units,
96  const DVector* const _scaling,
97  const DVector* const _lb,
98  const DVector* const _ub,
99  const BooleanType* const _autoInit
100  ) : Grid( )
101 {
102  values = 0;
103  init( _nRows,_nCols,_firstTime,_lastTime,_nPoints,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
104 }
105 
106 
108  const Grid& _grid,
109  VariableType _type
110  ) : Grid( )
111 {
112  values = 0;
113  init( arg,_grid,_type );
114 }
115 
117  ) : Grid( rhs )
118 {
119  if ( nPoints > 0 )
120  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
121  else
122  values = 0;
123 
124  for( uint i=0; i<nPoints; ++i )
125  values[i] = new MatrixVariable( *(rhs.values[i]) );
126 }
127 
128 
130 {
131  clearValues( );
132 }
133 
134 
135 
137  )
138 {
139  if ( this != &rhs )
140  {
141  clearValues( );
142 
143  Grid::operator=( rhs );
144 
145  if ( nPoints > 0 )
146  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
147  else
148  values = 0;
149 
150  for( uint i=0; i<nPoints; ++i )
151  values[i] = new MatrixVariable( *(rhs.values[i]) );
152  }
153 
154  return *this;
155 }
156 
157 
159  )
160 {
161  init( rhs.getNumCols()-1,1,rhs.getNumRows( ),getType() );
162 
163  for( uint i=0; i<nPoints; ++i )
164  {
165  setTime( rhs( i,0 ) );
166 
167  for( uint j=0; j<rhs.getNumCols( )-1; ++j )
168  operator()( i,j,0 ) = rhs( i,j+1 );
169  }
170 
171  return *this;
172 }
173 
174 
176 {
177  clearValues( );
178  Grid::init( );
179 
180  return SUCCESSFUL_RETURN;
181 }
182 
183 
185  uint _nCols,
186  const Grid& _grid,
187  VariableType _type,
188  const char** const _names,
189  const char** const _units,
190  const DVector* const _scaling,
191  const DVector* const _lb,
192  const DVector* const _ub,
193  const BooleanType* const _autoInit
194  )
195 {
196  clearValues( );
197  Grid::init( _grid );
198 
199  if ( nPoints > 0 )
200  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
201  else
202  values = 0;
203 
204  return initMatrixVariables( _nRows,_nCols,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
205 }
206 
207 
209  uint _nCols,
210  uint _nPoints,
211  VariableType _type,
212  const char** const _names,
213  const char** const _units,
214  const DVector* const _scaling,
215  const DVector* const _lb,
216  const DVector* const _ub,
217  const BooleanType* const _autoInit
218  )
219 {
220  clearValues( );
221  Grid::init( _nPoints );
222 
223  if ( nPoints > 0 )
224  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
225  else
226  values = 0;
227 
228  return initMatrixVariables( _nRows,_nCols,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
229 }
230 
231 
233  uint _nCols,
234  double _firstTime,
235  double _lastTime,
236  uint _nPoints,
237  VariableType _type,
238  const char** const _names,
239  const char** const _units,
240  const DVector* const _scaling,
241  const DVector* const _lb,
242  const DVector* const _ub,
243  const BooleanType* const _autoInit
244  )
245 {
246  clearValues( );
247  Grid::init( _firstTime,_lastTime,_nPoints );
248 
249  if ( nPoints > 0 )
250  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
251  else
252  values = 0;
253 
254  return initMatrixVariables( _nRows,_nCols,_type,_names,_units,_scaling,_lb,_ub,_autoInit );
255 }
256 
257 
259  const Grid& _grid,
260  VariableType _type
261  )
262 {
263  clearValues( );
264  Grid::operator=( _grid );
265 
266  if ( nPoints > 0 )
267  values = (MatrixVariable**) calloc( nPoints,sizeof(MatrixVariable*) );
268  else
269  values = 0;
270 
271  for( uint i=0; i<nPoints; ++i )
272  values[i] = new MatrixVariable( arg );
273 
274  return SUCCESSFUL_RETURN;
275 }
276 
277 
278 
280  double newTime
281  )
282 {
283  return addMatrix( MatrixVariable(newMatrix),newTime );
284 }
285 
286 
287 
289  const DMatrix& _value
290  ) const
291 {
292  ASSERT( values != 0 );
293 
294  if ( pointIdx >= getNumPoints( ) )
296 
297  *(values[pointIdx]) = _value;
298 
299  return SUCCESSFUL_RETURN;
300 }
301 
302 
304  )
305 {
306  for( uint i = 0; i < getNumPoints(); i++ )
307  ACADO_TRY( setMatrix( i,_values ) );
308 
309  return SUCCESSFUL_RETURN;
310 }
311 
312 
314  ) const
315 {
316  ASSERT( values != 0 );
317 
318  if ( pointIdx >= getNumPoints( ) )
319  return emptyMatrix;
320 
321  return values[pointIdx]->getMatrix( );
322 }
323 
324 
326 {
327  if ( getNumPoints( ) <= 0 )
328  return emptyMatrix;
329 
330  return getMatrix( 0 );
331 }
332 
333 
335 {
336  if ( getNumPoints( ) <= 0 )
337  return emptyMatrix;
338 
339  return getMatrix( getNumPoints( )-1 );
340 }
341 
342 
343 
345  MergeMethod _mergeMethod
346  )
347 {
348  if ( arg.getNumPoints( ) == 0 )
349  return SUCCESSFUL_RETURN;
350 
351  if ( acadoIsGreater( getLastTime( ),arg.getFirstTime( ) ) == BT_TRUE )
353 
354  if ( acadoIsEqual( getLastTime( ),arg.getFirstTime( ) ) == BT_FALSE )
355  {
356  // simply append
357  for( uint i=0; i<arg.getNumPoints( ); ++i )
358  addMatrix( *(arg.values[i]),arg.getTime( i ) );
359  }
360  else
361  {
362  // if last and first time point coincide, merge as specified
363  switch ( _mergeMethod )
364  {
365  case MM_KEEP:
366  break;
367 
368  case MM_REPLACE:
370  break;
371 
372  case MM_DUPLICATE:
373  addMatrix( *(arg.values[0]),arg.getTime( 0 ) );
374  break;
375  }
376 
377  // simply append all remaining points
378  for( uint i=1; i<arg.getNumPoints( ); ++i )
379  addMatrix( *(arg.values[i]),arg.getTime( i ) );
380  }
381 
382  return SUCCESSFUL_RETURN;
383 }
384 
385 
387 {
388  if ( getNumPoints( ) != arg.getNumPoints( ) )
390 
391  DVector tmp1,tmp2;
392 
393  for( uint i=0; i<getNumPoints(); ++i )
394  {
395  values[i]->appendRows( *(arg.values[i]) );
396  values[i]->appendSettings( *(arg.values[i]) );
397  }
398 
399  return SUCCESSFUL_RETURN;
400 }
401 
402 
403 // uses a simple O(n^2) algorithm for sorting
405  MergeMethod _mergeMethod,
406  BooleanType keepOverlap
407  )
408 {
409  if ( ( keepOverlap == BT_FALSE ) && ( _mergeMethod == MM_DUPLICATE ) )
411 
412  // nothing to do if arg or object itself is empty
413  if ( arg.getNumPoints( ) == 0 )
414  return SUCCESSFUL_RETURN;
415 
416  if ( getNumPoints( ) == 0 )
417  {
418  *this = arg;
419  return SUCCESSFUL_RETURN;
420  }
421 
422  // use append if grids do not overlap
423  if ( acadoIsSmaller( getLastTime( ),arg.getFirstTime( ) ) == BT_TRUE )
424  return appendTimes( arg,_mergeMethod );
425 
426 
427  // construct merged grid
428  MatrixVariablesGrid mergedGrid;
429  uint j = 0;
430  BooleanType overlapping = BT_FALSE;
431 
432  for( uint i=0; i<getNumPoints( ); ++i )
433  {
434  if ( keepOverlap == BT_FALSE )
435  overlapping = arg.isInInterval( getTime(i) );
436 
437  // add all grid points of argument grid that are smaller
438  // then current one of original grid
439  while ( ( j < arg.getNumPoints( ) ) &&
440  ( acadoIsStrictlySmaller( arg.getTime( j ),getTime( i ) ) == BT_TRUE ) )
441  {
442  if ( ( overlapping == BT_FALSE ) ||
443  ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_REPLACE ) ) )
444  {
445  mergedGrid.addMatrix( *(arg.values[j]),arg.getTime( j ) );
446  }
447 
448  ++j;
449  }
450 
451  // merge current grid points if they are at equal times
452  if ( acadoIsEqual( arg.getTime( j ),getTime( i ) ) == BT_TRUE )
453  {
454  switch ( _mergeMethod )
455  {
456  case MM_KEEP:
457  mergedGrid.addMatrix( *(values[i]),getTime( i ) );
458  break;
459 
460  case MM_REPLACE:
461  mergedGrid.addMatrix( *(arg.values[j]),arg.getTime( j ) );
462  break;
463 
464  case MM_DUPLICATE:
465  mergedGrid.addMatrix( *(values[i]),getTime( i ) );
466  mergedGrid.addMatrix( *(arg.values[j]),arg.getTime( j ) );
467  break;
468  }
469  ++j;
470  }
471  else
472  {
473  // add current grid point of original grid
474  if ( ( overlapping == BT_FALSE ) ||
475  ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_KEEP ) ) )
476  {
477  mergedGrid.addMatrix( *(values[i]),getTime( i ) );//arg.
478  }
479  }
480  }
481 
482  // add all remaining grid points of argument grid
483  while ( j < arg.getNumPoints( ) )
484  {
485  if ( acadoIsStrictlyGreater( arg.getTime(j),getLastTime() ) == BT_TRUE )
486  mergedGrid.addMatrix( *(arg.values[j]),arg.getTime( j ) );
487 
488  ++j;
489  }
490 
491  // merged grid becomes current grid
492  *this = mergedGrid;
493 
494  return SUCCESSFUL_RETURN;
495 }
496 
497 
498 
500  uint endIdx
501  ) const
502 {
503  MatrixVariablesGrid newVariablesGrid;
504 
505  if ( ( startIdx >= getNumPoints( ) ) || ( endIdx >= getNumPoints( ) ) )
506  return newVariablesGrid;
507 
508  if ( startIdx > endIdx )
509  return newVariablesGrid;
510 
511  for( uint i=startIdx; i<=endIdx; ++i )
512  newVariablesGrid.addMatrix( *(values[i]),getTime( i ) );
513 
514  return newVariablesGrid;
515 }
516 
517 
519  uint endIdx
520  ) const
521 {
522  MatrixVariablesGrid newVariablesGrid;
523 
524  if ( ( startIdx >= getNumValues( ) ) || ( endIdx >= getNumValues( ) ) )
525  return newVariablesGrid;
526 
527  if ( startIdx > endIdx )
528  return newVariablesGrid;
529 
530  for( uint i=0; i<getNumPoints( ); ++i )
531  newVariablesGrid.addMatrix( values[i]->getRows( startIdx,endIdx ),getTime( i ) );
532 
533  return newVariablesGrid;
534 }
535 
536 
537 
539  InterpolationMode mode
540  )
541 {
542  // nothing to do
543  if ( this->isEmpty( ) == BT_TRUE )
544  return SUCCESSFUL_RETURN;
545 
546  *this = getRefinedGrid( arg,mode );
547 
548  if ( this->isEmpty( ) == BT_TRUE )
550  else
551  return SUCCESSFUL_RETURN;
552 }
553 
554 
556  )
557 {
558  // nothing to do
559  if ( this->isEmpty( ) == BT_TRUE )
560  return SUCCESSFUL_RETURN;
561 
562  *this = getCoarsenedGrid( arg );
563 
564  if ( this->isEmpty( ) == BT_TRUE)
566  else
567  return SUCCESSFUL_RETURN;
568 }
569 
570 
572  InterpolationMode mode
573  ) const
574 {
576 
577  // nothing to do
578  if ( this->isEmpty( ) == BT_TRUE )
579  return tmp;
580 
581  int count = -1;
582 
583  // checks for equality and superset
584  if ( Grid::operator==( arg ) == BT_TRUE )
585  return *this;
586 
587 // if ( Grid::operator<=( arg ) == BT_FALSE )
588 // return tmp;
589 
590  if ( mode != IM_CONSTANT )
591  return tmp;
592 
593  for( uint i=0; i<arg.getNumPoints( ); ++i )
594  {
595  if ( hasTime( arg.getTime( i ) ) == BT_TRUE )
596  count = acadoMin( count+1,(int)getNumPoints()-1 );
597 
598  if ( count < 0 )
599  tmp.addMatrix( *(values[0]),arg.getTime( i ) );
600  else
601  tmp.addMatrix( *(values[count]),arg.getTime( i ) );
602  }
603 
604  return tmp;
605 }
606 
607 
609  ) const
610 {
612 
613  // nothing to do
614  if ( this->isEmpty( ) == BT_TRUE )
615  return tmp;
616 
617  // checks for equality and subset
618  if ( Grid::operator==( arg ) == BT_TRUE )
619  return *this;
620 
621  if ( Grid::operator>=( arg ) == BT_FALSE )
622  return tmp;
623 
624  for( uint i=0; i<arg.getNumPoints( ); ++i )
625  {
626  int idx = findLastTime( arg.getTime( i ) );
627 
628  if ( idx >= 0 )
629  tmp.addMatrix( *(values[idx]),arg.getTime( i ) );
630  else
631  {
632  tmp.init( );
633  return tmp;
634  }
635  }
636 
637  return tmp;
638 }
639 
640 
641 
643  )
644 {
645  Grid::shiftTimes( timeShift );
646  return *this;
647 }
648 
649 
651 {
652  if ( getNumPoints() < 2 ){
653  if( lastValue.isEmpty() == BT_FALSE )
654  *(values[getNumIntervals()]) = lastValue;
655  return *this;
656  }
657 
658  for( uint i=1; i<getNumPoints( ); ++i )
659  *(values[i-1]) = *(values[i]);
660 
661  if( lastValue.isEmpty() == BT_FALSE )
662  *(values[getNumIntervals()]) = lastValue;
663 
664  return *this;
665 }
666 
667 
668 
670 {
671  uint idx1 = getFloorIndex( time );
672  uint idx2 = getCeilIndex ( time );
673 
674  ASSERT( values != 0 );
675  ASSERT( idx1 < getNumPoints( ) );
676  ASSERT( idx2 < getNumPoints( ) );
677 
678  DVector tmp1( values[idx1]->getCol( 0 ) );
679  DVector tmp2( values[idx2]->getCol( 0 ) );
680 
681  double t1 = getTime( idx1 );
682  double t2 = getTime( idx2 );
683 
684  if( fabs( t2 - t1 ) < SQRT_EPS ) return tmp1;
685 
686  tmp1 *= (t2 - time);
687  tmp2 *= (time - t1);
688 
689  DVector tmp = tmp1 + tmp2;
690  tmp /= (t2 - t1);
691 
692  return tmp;
693 }
694 
696  const char* const name,
697  const char* const startString,
698  const char* const endString,
699  uint width,
700  uint precision,
701  const char* const colSeparator,
702  const char* const rowSeparator
703  ) const
704 {
705  if (name != NULL && strlen(name) > 0)
706  stream << name << " = ";
707  if (startString != NULL && strlen(startString) > 0)
708  stream << startString;
709 
710  if ( precision > 0 )
711  stream << setw( width ) << setprecision( precision ) << scientific;
712  else
713  stream << setw( width );
714 
715  for (unsigned k = 0; k < getNumPoints(); ++k)
716  {
717  if ( precision > 0 )
718  stream << getTime( k );
719  else
720  stream << (int)getTime( k );
721 
722  if (colSeparator != NULL && strlen(colSeparator) > 0)
723  stream << colSeparator;
724 
725  values[k]->print(stream, "", "", "", width, precision, colSeparator, colSeparator);
726 
727  if (k < (getNumPoints() - 1) && rowSeparator != NULL && strlen(rowSeparator) > 0)
728  stream << rowSeparator;
729  }
730  if (endString != NULL && strlen(endString) > 0)
731  stream << endString;
732 
733  return SUCCESSFUL_RETURN;
734 }
735 
736 returnValue MatrixVariablesGrid::print( const char* const filename,
737  const char* const name,
738  const char* const startString,
739  const char* const endString,
740  uint width,
741  uint precision,
742  const char* const colSeparator,
743  const char* const rowSeparator
744  ) const
745 {
746  ofstream stream( filename );
747  returnValue status;
748 
749  if (stream.is_open() == true)
750  status = print(stream, name, startString, endString, width, precision,
751  colSeparator, rowSeparator);
752  else
754 
755  stream.close();
756 
757  return status;
758 }
759 
760 returnValue MatrixVariablesGrid::print( const char* const filename,
761  const char* const name,
762  PrintScheme printScheme
763  ) const
764 {
765  ofstream stream(filename);
766  returnValue status;
767 
768  if (stream.is_open())
769  status = print(stream, name, printScheme);
770  else
772 
773  stream.close();
774 
775  return status;
776 }
777 
779  const char* const name,
780  PrintScheme printScheme
781  ) const
782 {
783 // MatFile* matFile = 0;
784 
785  switch (printScheme) {
786  case PS_MATLAB_BINARY:
787 
789 
790  break;
791 
792 // matFile = new MatFile;
793 //
794 // matFile->write(stream, (const VariablesGrid) *this, name);
795 //
796 // delete matFile;
797 //
798 // return SUCCESSFUL_RETURN;
799 
800  default:
801  char* startString = 0;
802  char* endString = 0;
803  uint width = 0;
804  uint precision = 0;
805  char* colSeparator = 0;
806  char* rowSeparator = 0;
807 
808  returnValue ret = getGlobalStringDefinitions(printScheme, &startString,
809  &endString, width, precision, &colSeparator, &rowSeparator);
810 
811  returnValue status;
812  if (status == SUCCESSFUL_RETURN)
813  status = print(stream, name, startString, endString, width, precision,
814  colSeparator, rowSeparator);
815 
816  if (startString != 0)
817  delete[] startString;
818  if (endString != 0)
819  delete[] endString;
820  if (colSeparator != 0)
821  delete[] colSeparator;
822  if (rowSeparator != 0)
823  delete[] rowSeparator;
824 
825  return status;
826  }
827 
828  return SUCCESSFUL_RETURN;
829 }
830 
831 returnValue MatrixVariablesGrid::read( std::istream& stream )
832 {
833  vector< vector< double > > data;
834  stream >> data;
835 
836  if (data.size() == 0)
837  return SUCCESSFUL_RETURN;
838 
839  // Sanity check
840  unsigned nc = data[ 0 ].size();
841  unsigned nr = data.size();
842  for (unsigned row = 0; row < nr; ++row)
843  if (data[ row ].size() != nc)
845 
846  // Data conversions and initialization
847  init(nc - 1, 1, nr, getType());
848 
849  for (unsigned row = 0; row < nr; ++row)
850  setTime( data[ row ][ 0 ] );
851 
852  for (unsigned row = 0; row < nr; ++row)
853  for (unsigned col = 0; col < nc - 1; ++col)
854  operator()(row, col, 0) = data[ row ][col + 1];
855 
856  return SUCCESSFUL_RETURN;
857 }
858 
859 returnValue MatrixVariablesGrid::read( const char* const filename )
860 {
861  ifstream stream( filename );
862  returnValue status;
863 
864  if (stream.is_open())
865  status = read( stream );
866  else
868 
869  stream.close();
870 
871  return status;
872 }
873 
874 std::ostream& operator<<(std::ostream& stream, const MatrixVariablesGrid& arg)
875 {
876  if (arg.print( stream ) != SUCCESSFUL_RETURN)
877  ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "Cannot write to output stream.");
878 
879  return stream;
880 }
881 
882 std::istream& operator>>(std::istream& stream, MatrixVariablesGrid& arg)
883 {
884  if (arg.read( stream ) != SUCCESSFUL_RETURN)
885  ACADOERRORTEXT(RET_INVALID_ARGUMENTS, "Cannot read from input stream.");
886 
887  return stream;
888 }
889 
890 //
891 // PROTECTED MEMBER FUNCTIONS:
892 //
893 
895 {
896  if ( values != 0 )
897  {
898  for( uint i=0; i<nPoints; ++i )
899  {
900  if ( values[i] != 0 )
901  delete values[i];
902  }
903 
904  free( values );
905  values = 0;
906  }
907 
908  return SUCCESSFUL_RETURN;
909 }
910 
911 
913  uint _nCols,
914  VariableType _type,
915  const char** const _names,
916  const char** const _units,
917  const DVector* const _scaling,
918  const DVector* const _lb,
919  const DVector* const _ub,
920  const BooleanType* const _autoInit
921  )
922 {
923  DVector currentScaling,currentLb,currentUb;
924 
925  for( uint i=0; i<nPoints; ++i )
926  {
927  if ( _scaling != 0 )
928  currentScaling = _scaling[i];
929  else
930  currentScaling.init( );
931 
932  if ( _lb != 0 )
933  currentLb = _lb[i];
934  else
935  currentLb.init( );
936 
937  if ( _ub != 0 )
938  currentUb = _ub[i];
939  else
940  currentUb.init( );
941 
942  values[i] = new MatrixVariable( _nRows,_nCols,_type,_names,_units,currentScaling,currentLb,currentUb );
943  }
944 
945  return SUCCESSFUL_RETURN;
946 }
947 
948 
950  double newTime
951  )
952 {
953  if ( ( isInfty( newTime ) == BT_TRUE ) && ( getNumPoints( ) > 0 ) )
954  newTime = getLastTime( ) + 1.0;
955 
956  if ( Grid::addTime( newTime ) != SUCCESSFUL_RETURN )
957  return RET_INVALID_ARGUMENTS;
958 
959  values = (MatrixVariable**) realloc( values,nPoints*sizeof(MatrixVariable*) );
960  values[nPoints-1] = new MatrixVariable( newMatrix );
961 
962  return SUCCESSFUL_RETURN;
963 }
964 
966  )
967 {
968  uint run1, run2, run3;
969 
970  unsigned tmpSize = getNumPoints() * (getNumRows() + 1);
971  double *tmp = new double[tmpSize];
972 
973  if( times == 0 ) return ACADOERROR(RET_MEMBER_NOT_INITIALISED);
974 
975  for( run1 = 0; run1 < getNumPoints(); run1++ ){
976  tmp[run1*(getNumValues()+1)] = getTime(run1);
977 
978  for( run2 = 0; run2 < getNumRows(); run2++ ){
979  for( run3 = 0; run3 < getNumCols(); run3++ ){
980  tmp[run1*(getNumValues()+1)+1+run2*getNumCols() + run3] = operator()( run1,run2,run3 );
981  }
982  }
983  }
984 
985  unsigned nRows = getNumPoints();
986  unsigned nCols = getNumValues() + 1;
987  for (run1 = 0; run1 < nRows; run1++) {
988  for (run2 = 0; run2 < nCols; run2++) {
989  if (tmp[nCols * run1 + run2] <= ACADO_NAN - 1.0)
990  stream << scientific << tmp[nCols * run1 + run2] << TEXT_SEPARATOR;
991  else
992  stream << NOT_A_NUMBER << TEXT_SEPARATOR;
993  }
994  stream << LINE_SEPARATOR;
995  }
996  stream << LINE_SEPARATOR;
997 
998  delete[] tmp;
999 
1000  return SUCCESSFUL_RETURN;
1001 }
1002 
1003 #ifdef WIN32
1004 #pragma warning( disable : 4390 )
1005 #endif
1006 
1007 //
1008 // PUBLIC MEMBER FUNCTIONS:
1009 //
1010 
1011 
1012 double& MatrixVariablesGrid::operator()( uint pointIdx, uint rowIdx, uint colIdx )
1013 {
1014  ASSERT( values != 0 );
1015  ASSERT( pointIdx < getNumPoints( ) );
1016 
1017  return values[pointIdx]->operator()( rowIdx,colIdx );
1018 }
1019 
1020 
1021 double MatrixVariablesGrid::operator()( uint pointIdx, uint rowIdx, uint colIdx ) const
1022 {
1023  ASSERT( values != 0 );
1024  ASSERT( pointIdx < getNumPoints( ) );
1025 
1026  return values[pointIdx]->operator()( rowIdx,colIdx );
1027 }
1028 
1029 
1030 
1032  ) const
1033 {
1034  ASSERT( values != 0 );
1035  if ( rowIdx >= getNumRows( ) )
1036  {
1038  return MatrixVariablesGrid();
1039  }
1040 
1041  Grid tmpGrid;
1042  getGrid( tmpGrid );
1043 
1044  MatrixVariablesGrid rowGrid( 1,1,tmpGrid,getType( ) );
1045 
1046  for( uint run1 = 0; run1 < getNumPoints(); run1++ )
1047  rowGrid( run1,0,0 ) = values[run1]->operator()( rowIdx,0 );
1048 
1049  return rowGrid;
1050 }
1051 
1052 
1054  ) const
1055 {
1056  ASSERT( values != 0 );
1057  if ( pointIdx >= getNumPoints( ) )
1058  {
1060  return MatrixVariablesGrid();
1061  }
1062 
1063  MatrixVariablesGrid pointGrid;
1064  pointGrid.addMatrix( *(values[pointIdx]),getTime( pointIdx ) );
1065 
1066  return pointGrid;
1067 }
1068 
1069 
1070 
1072  ) const
1073 {
1074  ASSERT( getNumPoints( ) == arg.getNumPoints( ) );
1075 
1076  MatrixVariablesGrid tmp( *this );
1077 
1078  for( uint i=0; i<getNumPoints( ); ++i )
1079  *(tmp.values[i]) += *(arg.values[i]);
1080 
1081  return tmp;
1082 }
1083 
1084 
1085 
1086 
1087 
1089  )
1090 {
1091  ASSERT( getNumPoints( ) == arg.getNumPoints( ) );
1092 
1093  for( uint i=0; i<getNumPoints( ); ++i )
1094  *(values[i]) += *(arg.values[i]);
1095 
1096  return *this;
1097 }
1098 
1099 
1100 
1102  ) const
1103 {
1104  ASSERT( getNumPoints( ) == arg.getNumPoints( ) );
1105 
1106  MatrixVariablesGrid tmp( *this );
1107 
1108  for( uint i=0; i<getNumPoints( ); ++i )
1109  *(tmp.values[i]) -= *(arg.values[i]);
1110 
1111  return tmp;
1112 }
1113 
1114 
1116  )
1117 {
1118  ASSERT( getNumPoints( ) == arg.getNumPoints( ) );
1119 
1120  for( uint i=0; i<getNumPoints( ); ++i )
1121  *(values[i]) -= *(arg.values[i]);
1122 
1123  return *this;
1124 }
1125 
1126 
1127 
1129 {
1130  uint totalDim = 0;
1131 
1132  for( uint i=0; i<getNumPoints( ); ++i )
1133  totalDim += values[i]->getDim( );
1134 
1135  return totalDim;
1136 }
1137 
1138 
1139 
1141 {
1142  if ( values == 0 )
1143  return 0;
1144 
1145  return getNumRows( 0 );
1146 }
1147 
1148 
1150 {
1151  if ( values == 0 )
1152  return 0;
1153 
1154  return getNumCols( 0 );
1155 }
1156 
1157 
1159 {
1160  if ( values == 0 )
1161  return 0;
1162 
1163  return getNumValues( 0 );
1164 }
1165 
1166 
1168  ) const
1169 {
1170  if( values == 0 )
1171  return 0;
1172 
1173  ASSERT( pointIdx < getNumPoints( ) );
1174 
1175  return values[pointIdx]->getNumRows( );
1176 }
1177 
1178 
1180  ) const
1181 {
1182  if( values == 0 )
1183  return 0;
1184 
1185  ASSERT( pointIdx < getNumPoints( ) );
1186 
1187  return values[pointIdx]->getNumCols( );
1188 }
1189 
1190 
1192  ) const
1193 {
1194  if( values == 0 )
1195  return 0;
1196 
1197  ASSERT( pointIdx < getNumPoints( ) );
1198 
1199  return values[pointIdx]->getDim( );
1200 }
1201 
1202 
1203 
1205 {
1206  if ( getNumPoints() == 0 )
1207  return VT_UNKNOWN;
1208 
1209  return getType( 0 );
1210 }
1211 
1212 
1214  )
1215 {
1216  for( uint i=0; i<getNumPoints( ); ++i )
1217  setType( i,_type );
1218 
1219  return SUCCESSFUL_RETURN;
1220 }
1221 
1222 
1224  ) const
1225 {
1226  if ( pointIdx >= getNumPoints( ) )
1227  return VT_UNKNOWN;
1228 
1229  return values[pointIdx]->getType( );
1230 }
1231 
1232 
1234  VariableType _type
1235  )
1236 {
1237  if ( pointIdx >= getNumPoints( ) )
1239 
1240  return values[pointIdx]->setType( _type );
1241 }
1242 
1243 
1244 
1246  uint idx,
1247  char* const _name
1248  ) const
1249 {
1250  if( pointIdx >= getNumPoints( ) )
1252 
1253  return values[pointIdx]->getName( idx,_name );
1254 }
1255 
1256 
1258  uint idx,
1259  const char* const _name
1260  )
1261 {
1262  if( pointIdx >= getNumPoints( ) )
1264 
1265  return values[pointIdx]->setName( idx,_name );
1266 }
1267 
1268 
1269 
1271  uint idx,
1272  char* const _unit
1273  ) const
1274 {
1275  if( pointIdx >= getNumPoints( ) )
1277 
1278  return values[pointIdx]->getUnit( idx,_unit );
1279 }
1280 
1281 
1283  uint idx,
1284  const char* const _unit
1285  )
1286 {
1287  if( pointIdx >= getNumPoints( ) )
1289 
1290  return values[pointIdx]->setUnit( idx,_unit );
1291 }
1292 
1293 
1294 
1296  ) const
1297 {
1298  if( pointIdx >= getNumPoints( ) )
1299  return emptyVector;
1300 
1301  return values[pointIdx]->getScaling( );
1302 }
1303 
1304 
1306  const DVector& _scaling
1307  )
1308 {
1309  if ( pointIdx >= getNumPoints( ) )
1311 
1312  return values[pointIdx]->setScaling( _scaling );
1313 }
1314 
1315 
1317  uint valueIdx
1318  ) const
1319 {
1320  if( pointIdx >= getNumPoints( ) )
1321  return -1.0;
1322 
1323  return values[pointIdx]->getScaling( valueIdx );
1324 }
1325 
1326 
1328  uint valueIdx,
1329  double _scaling
1330  )
1331 {
1332  if( pointIdx >= getNumPoints( ) )
1334 
1335  if( valueIdx >= values[pointIdx]->getDim( ) )
1337 
1338  values[pointIdx]->setScaling( valueIdx,_scaling );
1339  return SUCCESSFUL_RETURN;
1340 }
1341 
1342 
1343 
1345  ) const
1346 {
1347  if( pointIdx >= getNumPoints( ) )
1348  return emptyVector;
1349 
1350  return values[pointIdx]->getLowerBounds( );
1351 }
1352 
1353 
1355  const DVector& _lb
1356  )
1357 {
1358  if( pointIdx >= nPoints )
1360 
1361  return values[pointIdx]->setLowerBounds( _lb );
1362 }
1363 
1364 
1366  uint valueIdx
1367  ) const
1368 {
1369  if( pointIdx >= getNumPoints( ) )
1370  return -INFTY;
1371 
1372  return values[pointIdx]->getLowerBound( valueIdx );
1373 }
1374 
1375 
1377  uint valueIdx,
1378  double _lb
1379  )
1380 {
1381  if( pointIdx >= getNumPoints( ) )
1383 
1384  if( valueIdx >= values[pointIdx]->getDim( ) )
1386 
1387  values[pointIdx]->setLowerBound( valueIdx,_lb );
1388  return SUCCESSFUL_RETURN;
1389 }
1390 
1391 
1392 
1394  ) const
1395 {
1396  if( pointIdx >= getNumPoints( ) )
1397  return emptyVector;
1398 
1399  return values[pointIdx]->getUpperBounds( );
1400 }
1401 
1402 
1404  const DVector& _ub
1405  )
1406 {
1407  if( pointIdx >= getNumPoints( ) )
1409 
1410  return values[pointIdx]->setUpperBounds( _ub );
1411 }
1412 
1413 
1415  uint valueIdx
1416  ) const
1417 {
1418  if( pointIdx >= getNumPoints( ) )
1419  return INFTY;
1420 
1421  return values[pointIdx]->getUpperBound( valueIdx );
1422 }
1423 
1424 
1426  uint valueIdx,
1427  double _ub
1428  )
1429 {
1430  if( pointIdx >= getNumPoints( ) )
1432 
1433  if( valueIdx >= values[pointIdx]->getDim( ) )
1435 
1436  values[pointIdx]->setUpperBound( valueIdx,_ub );
1437  return SUCCESSFUL_RETURN;
1438 }
1439 
1440 
1441 
1443  ) const
1444 {
1445  if ( pointIdx >= getNumPoints( ) )
1446  {
1448  return defaultAutoInit;
1449  }
1450 
1451  return values[pointIdx]->getAutoInit( );
1452 }
1453 
1454 
1456  BooleanType _autoInit
1457  )
1458 {
1459  if ( pointIdx >= getNumPoints( ) )
1461 
1462  return values[pointIdx]->setAutoInit( _autoInit );
1463 }
1464 
1465 
1467 {
1468  for( uint i=0; i<getNumPoints( ); ++i )
1469  values[i]->setAutoInit( BT_FALSE );
1470 
1471  return SUCCESSFUL_RETURN;
1472 }
1473 
1474 
1476 {
1477  for( uint i=0; i<getNumPoints( ); ++i )
1478  values[i]->setAutoInit( BT_TRUE );
1479 
1480  return SUCCESSFUL_RETURN;
1481 }
1482 
1483 
1484 
1486 {
1487  for( uint i=0; i<getNumPoints( ); ++i )
1488  {
1489  if ( values[i]->hasNames( ) == BT_TRUE )
1490  return BT_TRUE;
1491  }
1492 
1493  return BT_FALSE;
1494 }
1495 
1496 
1498 {
1499  for( uint i=0; i<getNumPoints( ); ++i )
1500  {
1501  if ( values[i]->hasUnits( ) == BT_TRUE )
1502  return BT_TRUE;
1503  }
1504 
1505  return BT_FALSE;
1506 }
1507 
1508 
1510 {
1511  for( uint i=0; i<getNumPoints( ); ++i )
1512  {
1513  if ( values[i]->hasScaling( ) == BT_TRUE )
1514  return BT_TRUE;
1515  }
1516 
1517  return BT_FALSE;
1518 }
1519 
1520 
1522 {
1523  for( uint i=0; i<getNumPoints( ); ++i )
1524  {
1525  if ( values[i]->hasLowerBounds( ) == BT_TRUE )
1526  return BT_TRUE;
1527  }
1528 
1529  return BT_FALSE;
1530 }
1531 
1532 
1534 {
1535  for( uint i=0; i<getNumPoints( ); ++i )
1536  {
1537  if ( values[i]->hasUpperBounds( ) == BT_TRUE )
1538  return BT_TRUE;
1539  }
1540 
1541  return BT_FALSE;
1542 }
1543 
1544 
1545 
1547 {
1548  double maxValue = -INFTY;
1549 
1550  for( uint i=0; i<getNumPoints( ); ++i )
1551  {
1552  if ( values[i]->getMax( ) > maxValue )
1553  maxValue = values[i]->getMax( );
1554  }
1555 
1556  return maxValue;
1557 }
1558 
1559 
1561 {
1562  double minValue = INFTY;
1563 
1564  for( uint i=0; i<getNumPoints( ); ++i )
1565  {
1566  if ( values[i]->getMin( ) < minValue )
1567  minValue = values[i]->getMin( );
1568  }
1569 
1570  return minValue;
1571 }
1572 
1573 
1575 {
1576  double meanValue = 0.0;
1577 
1578  if ( getNumPoints( ) == 0 )
1579  return meanValue;
1580 
1581  for( uint i=0; i<getNumPoints( ); ++i )
1582  meanValue += values[i]->getMean( );
1583 
1584  return ( meanValue / (double)getNumPoints( ) );
1585 }
1586 
1587 
1588 
1590 {
1591  for( uint i=0; i<getNumPoints( ); ++i )
1592  values[i]->setZero( );
1593 
1594  return SUCCESSFUL_RETURN;
1595 }
1596 
1597 
1599  )
1600 {
1601  for( uint i = 0; i<getNumPoints( ); ++i )
1602  values[i]->setAll( _value );
1603 
1604  return SUCCESSFUL_RETURN;
1605 }
1606 
1607 
1608 
1610  ) const
1611 {
1612  return _grid.init( getNumPoints(),times );
1613 }
1614 
1615 
1617 {
1618  Grid tmp;
1619  getGrid( tmp );
1620  return tmp;
1621 }
1622 
1623 
1625 
1626 
1627 /*
1628  * end of file
1629  */
returnValue getGlobalStringDefinitions(PrintScheme _printScheme, char **_startString, char **_endString, uint &_width, uint &_precision, char **_colSeparator, char **_rowSeparator)
returnValue setAllMatrices(const DMatrix &_values)
returnValue setTime(double _time)
Definition: grid.cpp:307
returnValue setType(VariableType _type)
double getLowerBound(uint idx) const
returnValue appendSettings(const VariableSettings &rhs)
returnValue print(std::ostream &stream=std::cout, const char *const name=DEFAULT_LABEL, const char *const startString=DEFAULT_START_STRING, const char *const endString=DEFAULT_END_STRING, uint width=DEFAULT_WIDTH, uint precision=DEFAULT_PRECISION, const char *const colSeparator=DEFAULT_COL_SEPARATOR, const char *const rowSeparator=DEFAULT_ROW_SEPARATOR) const
bool isEmpty() const
Definition: matrix.hpp:193
int findLastTime(double _time, uint startIdx=0) const
Definition: grid.cpp:561
BooleanType getAutoInit(uint pointIdx) const
returnValue addMatrix(const DMatrix &newMatrix, double newTime=-INFTY)
double getTime(uint pointIdx) const
DVector getScaling(uint pointIdx) const
returnValue setUnit(uint idx, const char *const _unit)
MatrixVariablesGrid & operator+=(const MatrixVariablesGrid &arg)
double getFirstTime() const
BooleanType acadoIsEqual(double x, double y, double TOL)
Definition: acado_utils.cpp:88
const double INFTY
const double SQRT_EPS
uint getCeilIndex(double time) const
Definition: grid.cpp:625
DMatrix getFirstMatrix() const
MatrixVariablesGrid & operator-=(const MatrixVariablesGrid &arg)
returnValue getUnit(uint idx, char *_unit) const
returnValue setScaling(uint pointIdx, const DVector &_scaling)
returnValue setUpperBounds(uint pointIdx, const DVector &_ub)
void init(unsigned _dim=0)
Definition: vector.hpp:155
BooleanType hasScaling() const
returnValue setName(uint idx, const char *const _name)
double getUpperBound(uint idx) const
Allows to pass back messages to the calling function.
DVector getUpperBounds(uint pointIdx) const
double getLowerBound(uint pointIdx, uint valueIdx) const
returnValue getName(uint idx, char *_name) const
BooleanType hasLowerBounds() const
MatrixVariablesGrid operator+(const MatrixVariablesGrid &arg) const
BEGIN_NAMESPACE_ACADO typedef unsigned int uint
Definition: acado_types.hpp:42
Allows to conveniently handle (one-dimensional) grids consisting of time points.
Definition: grid.hpp:58
BooleanType isEmpty() const
returnValue setScaling(const DVector &_scaling)
GenericMatrix & appendRows(const GenericMatrix &_arg)
Definition: matrix.cpp:62
uint getLastIndex() const
BooleanType acadoIsGreater(double x, double y, double TOL)
MatrixVariablesGrid getTimeSubGrid(uint startIdx, uint endIdx) const
const char NOT_A_NUMBER[3]
returnValue setLowerBound(uint pointIdx, uint valueIdx, double _lb)
DVector getLowerBounds() const
#define CLOSE_NAMESPACE_ACADO
double getUpperBound(uint pointIdx, uint valueIdx) const
MatrixVariablesGrid getCoarsenedGrid(const Grid &arg) const
BooleanType isInInterval(double _time) const
VariableType
Definition: acado_types.hpp:95
returnValue print() const
Definition: grid.cpp:700
DVector getScaling() const
returnValue setAll(double _value)
MatrixVariablesGrid getRefinedGrid(const Grid &arg, InterpolationMode mode=IM_CONSTANT) const
BooleanType getAutoInit() const
MatrixVariablesGrid & shiftBackwards(DMatrix lastValue=emptyMatrix)
returnValue setUpperBound(uint idx, double _ub)
uint getFloorIndex(double time) const
Definition: grid.cpp:593
#define ACADOFATAL(retval)
returnValue setAutoInit(uint pointIdx, BooleanType _autoInit)
returnValue appendValues(const MatrixVariablesGrid &arg)
double * times
Definition: grid.hpp:614
#define ACADO_TRY(X)
BooleanType acadoIsStrictlySmaller(double x, double y, double TOL)
BEGIN_NAMESPACE_ACADO const char LINE_SEPARATOR
returnValue sprint(std::ostream &stream)
VariableType getType() const
static DMatrix emptyMatrix
Definition: matrix.hpp:465
returnValue merge(const MatrixVariablesGrid &arg, MergeMethod _mergeMethod=MM_DUPLICATE, BooleanType keepOverlap=BT_TRUE)
returnValue setAutoInit(BooleanType _autoInit)
VariableType getType() const
virtual returnValue print(std::ostream &_stream=std::cout, const std::string &_name=DEFAULT_LABEL, const std::string &_startString=DEFAULT_START_STRING, const std::string &_endString=DEFAULT_END_STRING, uint _width=DEFAULT_WIDTH, uint _precision=DEFAULT_PRECISION, const std::string &_colSeparator=DEFAULT_COL_SEPARATOR, const std::string &_rowSeparator=DEFAULT_ROW_SEPARATOR) const
Definition: matrix.cpp:254
BooleanType hasNames() const
uint nPoints
Definition: grid.hpp:613
BooleanType hasUnits() const
double & operator()(uint pointIdx, uint rowIdx, uint colIdx)
DVector linearInterpolation(double time) const
friend std::istream & operator>>(std::istream &stream, MatrixVariablesGrid &arg)
Provides a time grid consisting of matrix-valued optimization variables at each grid point...
Grid & operator=(const Grid &rhs)
Definition: grid.cpp:185
unsigned getDim() const
Definition: matrix.hpp:181
const BooleanType defaultAutoInit
returnValue setUpperBound(uint pointIdx, uint valueIdx, double _ub)
PrintScheme
DMatrix getMatrix() const
returnValue getGrid(Grid &_grid) const
DMatrix getLastMatrix() const
returnValue refineGrid(const Grid &arg, InterpolationMode mode=IM_CONSTANT)
returnValue setUnit(uint pointIdx, uint idx, const char *const _unit)
returnValue getUnit(uint pointIdx, uint idx, char *const _unit) const
returnValue setLowerBounds(const DVector &_lb)
friend std::ostream & operator<<(std::ostream &stream, const MatrixVariablesGrid &arg)
returnValue init(uint _nPoints=0, const double *const _times=0)
Definition: grid.cpp:107
BooleanType isInfty(const double x)
BooleanType acadoIsSmaller(double x, double y, double TOL)
MatrixVariablesGrid operator[](const uint pointIdx) const
returnValue initMatrixVariables(uint _nRows, uint _nCols, VariableType _type=VT_UNKNOWN, const char **const _names=0, const char **const _units=0, const DVector *const _scaling=0, const DVector *const _lb=0, const DVector *const _ub=0, const BooleanType *const _autoInit=0)
Provides matrix-valued optimization variables.
void rhs(const real_t *x, real_t *f)
MatrixVariablesGrid getValuesSubGrid(uint startIdx, uint endIdx) const
DVector getUpperBounds() const
returnValue getName(uint pointIdx, uint idx, char *const _name) const
DMatrix getMatrix(uint pointIdx) const
unsigned getNumRows() const
Definition: matrix.hpp:185
MatrixVariable getRows(uint startIdx, uint endIdx) const
const char TEXT_SEPARATOR
returnValue read(std::istream &stream)
int acadoMin(const int x, const int y)
Definition: acado_utils.cpp:76
#define ASSERT(x)
returnValue setLowerBound(uint idx, double _lb)
returnValue appendTimes(const MatrixVariablesGrid &arg, MergeMethod _mergeMethod=MM_DUPLICATE)
#define BT_TRUE
Definition: acado_types.hpp:47
returnValue setMatrix(uint pointIdx, const DMatrix &_value) const
RowXpr row(Index i)
Definition: BlockMethods.h:725
Grid & shiftTimes(double timeShift)
Definition: grid.cpp:449
unsigned getNumCols() const
Definition: matrix.hpp:189
uint getNumIntervals() const
returnValue addTime(double _time)
Definition: grid.cpp:339
MatrixVariablesGrid & operator=(const MatrixVariablesGrid &rhs)
returnValue coarsenGrid(const Grid &arg)
uint getNumPoints() const
returnValue setType(VariableType _type)
BooleanType hasTime(double _time) const
Definition: grid.cpp:520
double getLastTime() const
DVector getLowerBounds(uint pointIdx) const
MatrixVariablesGrid operator-(const MatrixVariablesGrid &arg) const
static DVector emptyVector
Definition: vector.hpp:335
returnValue setLowerBounds(uint pointIdx, const DVector &_lb)
BooleanType hasUpperBounds() const
#define BEGIN_NAMESPACE_ACADO
#define BT_FALSE
Definition: acado_types.hpp:49
MergeMethod
MatrixVariablesGrid & shiftTimes(double timeShift)
ColXpr col(Index i)
Definition: BlockMethods.h:708
returnValue setName(uint pointIdx, uint idx, const char *const _name)
returnValue setUpperBounds(const DVector &_ub)
BooleanType acadoIsStrictlyGreater(double x, double y, double TOL)
const double ACADO_NAN
#define ACADOERROR(retval)
InterpolationMode
#define ACADOERRORTEXT(retval, text)


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