grid.cpp
Go to the documentation of this file.
00001 /*
00002  *    This file is part of ACADO Toolkit.
00003  *
00004  *    ACADO Toolkit -- A Toolkit for Automatic Control and Dynamic Optimization.
00005  *    Copyright (C) 2008-2014 by Boris Houska, Hans Joachim Ferreau,
00006  *    Milan Vukov, Rien Quirynen, KU Leuven.
00007  *    Developed within the Optimization in Engineering Center (OPTEC)
00008  *    under supervision of Moritz Diehl. All rights reserved.
00009  *
00010  *    ACADO Toolkit is free software; you can redistribute it and/or
00011  *    modify it under the terms of the GNU Lesser General Public
00012  *    License as published by the Free Software Foundation; either
00013  *    version 3 of the License, or (at your option) any later version.
00014  *
00015  *    ACADO Toolkit is distributed in the hope that it will be useful,
00016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *    Lesser General Public License for more details.
00019  *
00020  *    You should have received a copy of the GNU Lesser General Public
00021  *    License along with ACADO Toolkit; if not, write to the Free Software
00022  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023  *
00024  */
00025 
00026 
00034 #include <acado/variables_grid/grid.hpp>
00035 #include <iomanip>
00036 
00037 using namespace std;
00038 
00039 BEGIN_NAMESPACE_ACADO
00040 
00041 
00042 
00043 //
00044 // PUBLIC MEMBER FUNCTIONS:
00045 //
00046 
00047 Grid::Grid( )
00048 {
00049         nPoints = 0;
00050         times   = 0;
00051 }
00052 
00053 
00054 Grid::Grid(     uint nPoints_,
00055                         double *times_
00056                         )
00057 {
00058         times = 0;
00059         init( nPoints_,times_ );
00060 }
00061 
00062 
00063 Grid::Grid(     const DVector& times_
00064                         )
00065 {
00066         times = 0;
00067         init( times_ );
00068 }
00069 
00070 
00071 Grid::Grid(     double _firstTime,
00072                         double _lastTime,
00073                         uint _nPoints
00074                         )
00075 {
00076         times = 0;
00077         init( _firstTime,_lastTime,_nPoints );
00078 }
00079 
00080 
00081 
00082 Grid::Grid( const Grid& rhs )
00083 {
00084         nPoints = rhs.nPoints;
00085 
00086         if ( rhs.times != 0 )
00087         {
00088                 times = (double*) calloc( nPoints,sizeof(double) );
00089 
00090                 for( uint i=0; i<nPoints; ++i )
00091                         times[i] = rhs.times[i];
00092         }
00093         else
00094         {
00095                 times = 0;
00096         }
00097 }
00098 
00099 
00100 Grid::~Grid( )
00101 {
00102         if ( times != 0 )
00103                 free( times );
00104 }
00105 
00106 
00107 returnValue Grid::init( uint _nPoints,
00108                                                 const double* const _times
00109                                                 )
00110 {
00111         nPoints = _nPoints;
00112 
00113         if ( times != 0 )
00114                 free( times );
00115 
00116         if ( nPoints > 0 )
00117                 times = (double*) calloc( nPoints,sizeof(double) );
00118         else
00119                 times = 0;
00120 
00121         if ( _times != 0 )
00122         {
00123                 for( uint i=0; i<nPoints; ++i )
00124                         times[i] = _times[i];
00125         }
00126         else
00127         {
00128                 for( uint i=0; i<nPoints; ++i )
00129                         times[i] = -INFTY;
00130         }
00131 
00132         return SUCCESSFUL_RETURN;
00133 }
00134 
00135 
00136 returnValue Grid::init( const DVector& times_
00137                                                 )
00138 {
00139         nPoints = times_.getDim();
00140 
00141         if ( times != 0 )
00142                 free( times );
00143 
00144         if ( nPoints > 0 )
00145                 times = (double*) calloc( nPoints,sizeof(double) );
00146         else
00147                 times = 0;
00148 
00149         for( uint i=0; i<nPoints; ++i )
00150                 times[i] = times_(i);
00151 
00152         return SUCCESSFUL_RETURN;
00153 }
00154 
00155 
00156 returnValue Grid::init( double _firstTime,
00157                                                 double _lastTime,
00158                                                 uint _nPoints
00159                                                 )
00160 {
00161         nPoints = _nPoints;
00162 
00163         if ( times != 0 )
00164                 free( times );
00165 
00166         if ( nPoints > 0 )
00167                 times = (double*) calloc( nPoints,sizeof(double) );
00168         else
00169                 times = 0;
00170 
00171         return setupEquidistant( _firstTime,_lastTime );
00172 }
00173 
00174 
00175 returnValue Grid::init( const Grid& rhs
00176                                                 )
00177 {
00178         operator=( rhs );
00179 
00180         return SUCCESSFUL_RETURN;
00181 }
00182 
00183 
00184 
00185 Grid& Grid::operator=( const Grid& rhs )
00186 {
00187     if ( this != &rhs )
00188     {
00189                 if ( times != 0 )
00190                         free( times );
00191 
00192 
00193                 nPoints = rhs.nPoints;
00194 
00195                 if ( rhs.times != 0 )
00196                 {
00197                         times = (double*) calloc( nPoints,sizeof(double) );
00198 
00199                         for( uint i=0; i<nPoints; ++i )
00200                                 times[i] = rhs.times[i];
00201                 }
00202                 else
00203                 {
00204                         times = 0;
00205                 }
00206         }
00207 
00208         return *this;
00209 }
00210 
00211 
00212 Grid& Grid::operator&( const Grid& arg )
00213 {
00214         merge( arg,MM_KEEP,BT_TRUE );
00215 
00216 //     if( times     == 0 ) return Grid::operator=( arg );
00217 //     if( arg.times == 0 ) return *this;
00218 // 
00219 //     uint max_n = nPoints + arg.nPoints;
00220 //     uint count  = 0;
00221 //     uint count1 = 0;
00222 //     uint count2 = 0;
00223 // 
00224 //     double* new_times = (double*) calloc( max_n,sizeof(double) );
00225 //     double tt = getTime(0);
00226 // 
00227 //     if( arg.getTime(0) < tt ){
00228 //         tt = arg.getTime(0);
00229 //     }
00230 // 
00231 //     double tt2 = tt;
00232 // 
00233 //     new_times[count] = tt2;
00234 //     count++;
00235 // 
00236 //     while( count < max_n ){
00237 // 
00238 //         count1 = 0;
00239 //         while( count1 < nPoints ){
00240 // 
00241 //             if( acadoIsStrictlyGreater( getTime(count1) , tt ) == BT_TRUE ){
00242 //                 tt2 = getTime(count1);
00243 //                 break;
00244 //             }
00245 //             count1++;
00246 //         }
00247 // 
00248 //         if( count1 < nPoints ){
00249 //             count2 = 0;
00250 //             while( count2 < arg.nPoints ){
00251 //                 if( acadoIsStrictlyGreater( arg.getTime(count2) , tt  ) == BT_TRUE &&
00252 //                     acadoIsStrictlySmaller( arg.getTime(count2) , tt2 ) == BT_TRUE   ){
00253 //                     tt2 = arg.getTime(count2);
00254 //                     break;
00255 //                 }
00256 //                 count2++;
00257 //             }
00258 //         }
00259 //         else{
00260 //             count2 = 0;
00261 //             while( count2 < arg.nPoints ){
00262 //                 if( acadoIsStrictlyGreater( arg.getTime(count2), tt ) == BT_TRUE ){
00263 //                     tt2 = arg.getTime(count2);
00264 //                     break;
00265 //                 }
00266 //                 count2++;
00267 //             }
00268 //         }
00269 //         if( count1 == nPoints && count2 == arg.nPoints ){
00270 //             break;
00271 //         }
00272 // 
00273 //         new_times[count] = tt2;
00274 //         tt = tt2;
00275 // 
00276 //         count++;
00277 //     }
00278 // 
00279 //     free( times );
00280 // 
00281 //     nPoints = count;
00282 //     times = (double*) calloc( count,sizeof(double) );
00283 //     for( count = 0; count < nPoints; count++ ){
00284 //         times[count] = new_times[count];
00285 //     }
00286 // 
00287 //     free( new_times );
00288 
00289     return *this;
00290 }
00291 
00292 
00293 returnValue Grid::equalizeGrids(        Grid& arg
00294                                                                         )
00295 {
00296         if ( *this == arg )
00297                 return SUCCESSFUL_RETURN;
00298 
00299         // construct common grid and assigns it to both grids
00300         *this & arg;
00301         arg = *this;
00302 
00303         return SUCCESSFUL_RETURN;
00304 }
00305 
00306 
00307 returnValue Grid::setTime(      double _time
00308                                                         )
00309 {
00310         int idx = findNextIndex( );
00311 
00312         if ( idx < 0 )
00313                 return ACADOERROR( RET_GRIDPOINT_SETUP_FAILED );
00314 
00315         if ( idx > 0 )
00316         {
00317                 if ( acadoIsStrictlyGreater( times[idx-1] , _time ) == BT_TRUE )
00318                         return ACADOERROR( RET_GRIDPOINT_HAS_INVALID_TIME );
00319         }
00320 
00321         times[idx] = _time;
00322         return SUCCESSFUL_RETURN;
00323 }
00324 
00325 
00326 returnValue Grid::setTime(      uint pointIdx,
00327                                                         double _time
00328                                                         )
00329 {
00330         if ( pointIdx >= getNumPoints( ) )
00331                 return ACADOERROR( RET_INDEX_OUT_OF_BOUNDS );
00332 
00333         times[pointIdx] = _time;
00334 
00335         return SUCCESSFUL_RETURN;
00336 }
00337 
00338 
00339 returnValue Grid::addTime(      double _time
00340                                                         )
00341 {
00342         if ( ( getNumPoints( ) > 0 ) && ( acadoIsGreater( _time,getLastTime() ) == BT_FALSE ) )
00343         {
00344                 //ASSERT( 1==0 );
00345                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00346         }
00347 
00348         ++nPoints;
00349 
00350         times = (double*) realloc( times,nPoints*sizeof(double) );
00351         times[nPoints-1] = _time;
00352 
00353         return SUCCESSFUL_RETURN;
00354 }
00355 
00356 
00357 // uses a simple O(n^2) algorithm for sorting
00358 returnValue Grid::merge(        const Grid& arg,
00359                                                         MergeMethod _mergeMethod,
00360                                                         BooleanType keepOverlap
00361                                                         )
00362 {
00363         if ( ( keepOverlap == BT_FALSE ) && ( _mergeMethod == MM_DUPLICATE ) )
00364                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00365 
00366         // nothing to do if arg or object itself is empty
00367         if ( arg.getNumPoints( ) == 0 )
00368                 return SUCCESSFUL_RETURN;
00369 
00370         if ( getNumPoints( ) == 0 )
00371         {
00372                 *this = arg;
00373                 return SUCCESSFUL_RETURN;
00374         }
00375 
00376 
00377         // construct merged grid
00378         Grid mergedGrid;
00379         uint j = 0;
00380         BooleanType overlapping = BT_FALSE;
00381 
00382         for( uint i=0; i<getNumPoints( ); ++i )
00383         {
00384                 if ( keepOverlap == BT_FALSE )
00385                         overlapping = arg.isInInterval( getTime(i) );
00386 
00387                 // add all grid points of argument grid that are smaller 
00388                 // then current one of original grid
00389                 while ( ( j < arg.getNumPoints( ) ) && 
00390                                 ( acadoIsStrictlySmaller( arg.getTime( j ),getTime( i ) ) == BT_TRUE ) )
00391                 {
00392                         if ( ( overlapping == BT_FALSE ) ||
00393                                  ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_REPLACE ) ) )
00394                         {
00395                                 mergedGrid.addTime( arg.getTime( j ) );
00396                         }
00397 
00398                         ++j;
00399                 }
00400 
00401                 // merge current grid points if they are at equal times
00402                 if ( acadoIsEqual( arg.getTime( j ),getTime( i ) ) == BT_TRUE )
00403                 {
00404                         switch ( _mergeMethod )
00405                         {
00406                                 case MM_KEEP:
00407                                         mergedGrid.addTime( getTime( i ) );
00408                                         break;
00409         
00410                                 case MM_REPLACE:
00411                                         mergedGrid.addTime( arg.getTime( j ) );
00412                                         break;
00413         
00414                                 case MM_DUPLICATE:
00415                                         mergedGrid.addTime( getTime( i ) );
00416                                         mergedGrid.addTime( arg.getTime( j ) );
00417                                         break;
00418                         }
00419                         ++j;
00420                 }
00421                 else
00422                 {
00423                         // add current grid point of original grid
00424                         if ( ( overlapping == BT_FALSE ) ||
00425                                  ( ( overlapping == BT_TRUE ) && ( _mergeMethod == MM_KEEP ) ) )
00426                         {
00427                                 mergedGrid.addTime( getTime( i ) );
00428                         }
00429                 }
00430         }
00431 
00432         // add all remaining grid points of argument grid
00433         while ( j < arg.getNumPoints( ) )
00434         {
00435                 if ( acadoIsStrictlyGreater( arg.getTime(j),getLastTime() ) == BT_TRUE )
00436                         mergedGrid.addTime( arg.getTime( j ) );
00437 
00438                 ++j;
00439         }
00440 
00441         // merged grid becomes current grid
00442         *this = mergedGrid;
00443 
00444         return SUCCESSFUL_RETURN;
00445 }
00446 
00447 
00448 
00449 Grid& Grid::shiftTimes( double timeShift
00450                                                 )
00451 {
00452         for( uint i=0; i<nPoints; ++i )
00453                 times[i] += timeShift;
00454 
00455         return *this;
00456 }
00457 
00458 
00459 
00460 returnValue Grid::scaleTimes(   double scaling
00461                                                                 )
00462 {
00463         if ( acadoIsStrictlyGreater( scaling,0.0 ) == BT_FALSE )
00464         {
00465                 ACADOWARNING( RET_INVALID_ARGUMENTS );
00466                 scaling = 1.0;
00467         }
00468 
00469         for( uint i=0; i<nPoints; ++i )
00470                 times[i] *= scaling;
00471 
00472         return SUCCESSFUL_RETURN;
00473 }
00474 
00475 
00476 
00477 returnValue Grid::refineGrid(   uint factor
00478                                                                 )
00479 {
00480         if ( factor == 0 )
00481                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00482 
00483         /* nothing to do */
00484         if ( ( factor == 1 ) || ( getNumIntervals( ) == 0 ) )
00485                 return SUCCESSFUL_RETURN;
00486 
00487         /* setup <factor>-times finer grid */
00488         double* newTimes = (double*) calloc( getNumIntervals( )*factor+1,sizeof(double) );
00489 
00490         for( uint i=0; i<getNumIntervals( ); ++i )
00491                 for( uint j=0; j<factor; ++j )
00492                         newTimes[i*factor + j] = getTime( i ) + ((double) j) / ((double) factor) * getIntervalLength( i );
00493         newTimes[ getNumIntervals( )*factor ] = getLastTime( );
00494 
00495         /* assign new time array and deallocate old one */
00496         nPoints = getNumIntervals( )*factor + 1;
00497 
00498         double* tmp = times;
00499         times = newTimes;
00500         free( tmp );
00501 
00502         return SUCCESSFUL_RETURN;
00503 }
00504 
00505 
00506 returnValue Grid::coarsenGrid(  uint factor
00507                                                                 )
00508 {
00509         if ( factor == 0 )
00510                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00511 
00512         /* nothing to do */
00513         if ( ( factor == 1 ) || ( getNumIntervals( ) == 0 ) )
00514                 return SUCCESSFUL_RETURN;
00515 
00516         return RET_NOT_YET_IMPLEMENTED;
00517 }
00518 
00519 
00520 BooleanType Grid::hasTime(      double _time
00521                                                         ) const
00522 {
00523         if ( findTime( _time ) < 0 )
00524                 return BT_FALSE;
00525         else
00526                 return BT_TRUE;
00527 }
00528 
00529 
00530 
00531 int Grid::findTime(     double _time,
00532                                         uint startIdx
00533                                         ) const
00534 {
00535         return findFirstTime( _time,startIdx );
00536 }
00537 
00538 
00539 int Grid::findFirstTime(        double _time,
00540                                                         uint startIdx
00541                                                         ) const
00542 {
00543         if ( times == 0 )
00544                 return -1;
00545 
00546         for( uint i=startIdx; i<getNumPoints( ); ++i )
00547         {
00548                 if ( acadoIsEqual( times[i] ,_time ) == BT_TRUE )
00549                         return i;
00550 
00551                 /* stop here as grid point times are ordered! */
00552                 if ( times[i] > _time )
00553                         return -1;
00554         }
00555 
00556         /* no grid point with given time found */
00557         return -1;
00558 }
00559 
00560 
00561 int Grid::findLastTime( double _time,
00562                                                 uint startIdx
00563                                                 ) const
00564 {
00565         if ( times == 0 )
00566                 return -1;
00567 
00568         for( uint i=startIdx; i<getNumPoints( ); ++i )
00569         {
00570                 if ( acadoIsEqual( times[i] ,_time ) == BT_TRUE )
00571                 {
00572                         uint j = i;
00573 
00574                         while( ( j<getNumPoints( ) ) && ( acadoIsEqual( times[j] , _time ) == BT_TRUE ) )
00575                         {
00576                                 ++j;
00577                         }
00578 
00579                         return j-1;
00580                 }
00581 
00582                 /* stop here as grid point times are ordered! */
00583                 if ( times[i] > _time )
00584                         return -1;
00585         }
00586 
00587         /* no grid point with given time found */
00588         return -1;
00589 }
00590 
00591 
00592 
00593 uint Grid::getFloorIndex(       double time_
00594                                                         ) const
00595 {
00596         uint lowerIdx = 0;
00597         uint upperIdx = getLastIndex( );
00598         uint idx = 0;
00599 
00600         /* ensure that time lies within range */
00601         if ( acadoIsGreater( getTime( lowerIdx ) , time_ ) == BT_TRUE )
00602                 return lowerIdx;
00603 
00604         if ( acadoIsSmaller( getTime( upperIdx ) , time_ ) == BT_TRUE )
00605                 return upperIdx;
00606 
00607         /* if so, perform binary search */
00608         while ( lowerIdx < upperIdx )
00609         {
00610                 idx = (uint)floor( 0.5*( (double)(upperIdx + lowerIdx) ) );
00611 
00612                 if ( isInUpperHalfOpenInterval( idx,time_ ) == BT_TRUE )
00613                         break;
00614 
00615                 if ( acadoIsStrictlyGreater( getTime( idx ) , time_ ) == BT_TRUE )
00616                         upperIdx = idx;
00617                 else
00618                         lowerIdx = idx;
00619         }
00620 
00621     return idx;
00622 }
00623 
00624 
00625 uint Grid::getCeilIndex ( double time_ ) const
00626 {
00627         uint lowerIdx = 0;
00628         uint upperIdx = getLastIndex( );
00629         uint idx = 0;
00630 
00631         /* ensure that time lies within range */
00632         if ( acadoIsGreater( getTime( lowerIdx ) , time_ ) == BT_TRUE )
00633                 return lowerIdx;
00634 
00635         if ( acadoIsSmaller( getTime( upperIdx ) , time_ ) == BT_TRUE )
00636                 return upperIdx;
00637 
00638         /* if so, perform binary search */
00639         while ( lowerIdx < upperIdx )
00640         {
00641                 idx = (uint)ceil(0.5*( (double)( upperIdx + lowerIdx) ) );
00642 
00643                 if ( isInLowerHalfOpenInterval( idx,time_ ) == BT_TRUE )
00644                         break;
00645 
00646                 if ( acadoIsGreater( getTime( idx ) ,  time_ ) == BT_TRUE )
00647                         upperIdx = idx;
00648                 else
00649                         lowerIdx = idx;
00650     }
00651     return idx;
00652 }
00653 
00654 
00655 returnValue Grid::getSubGrid(   double tStart,
00656                                                                 double tEnd,
00657                                                                 Grid& _subGrid
00658                                                                 ) const
00659 {
00660         if ( ( isInInterval( tStart ) == BT_FALSE ) ||
00661                  ( isInInterval( tEnd ) == BT_FALSE ) )
00662                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00663 
00664 
00665         // determine number of subpoints
00666         uint nSubPoints = 0;
00667 
00668         if ( hasTime( tStart ) == BT_FALSE )
00669                 ++nSubPoints;
00670 
00671         for( uint i=0; i<getNumPoints( ); ++i )
00672         {
00673                 if ( acadoIsGreater( getTime( i ) , tStart ) == BT_TRUE  &&
00674                          acadoIsSmaller( getTime( i ) , tEnd   ) == BT_TRUE     ) ++nSubPoints;
00675         }
00676 
00677         if ( hasTime( tEnd ) == BT_FALSE )
00678                 ++nSubPoints;
00679 
00680         // setup subgrid with subpoints
00681         _subGrid.init( nSubPoints );
00682 
00683         if ( hasTime( tStart ) == BT_FALSE )
00684                 _subGrid.setTime( tStart );
00685 
00686         for( uint i=0; i<getNumPoints( ); ++i )
00687         {
00688                 if ( acadoIsGreater( getTime( i ) , tStart ) == BT_TRUE &&
00689                          acadoIsSmaller( getTime( i ) , tEnd   ) == BT_TRUE     )
00690                         _subGrid.setTime( getTime( i ) );
00691         }
00692 
00693         if ( hasTime( tEnd ) == BT_FALSE )
00694                 _subGrid.setTime( tEnd );
00695 
00696         return SUCCESSFUL_RETURN;
00697 }
00698 
00699 
00700 returnValue Grid::print( ) const
00701 {
00702         for (unsigned t = 0; t < getNumPoints(); t++)
00703                 cout << setprecision( 8 ) << getTime( t ) << "  ";
00704         cout << endl;
00705         
00706         return SUCCESSFUL_RETURN;
00707 }
00708 
00709 
00710 
00711 //
00712 // PROTECTED MEMBER FUNCTIONS:
00713 //
00714 
00715 returnValue Grid::setupEquidistant(     double _firstTime,
00716                                                                         double _lastTime
00717                                                                         )
00718 {
00719         if ( getNumPoints( ) == 0 )
00720                 return SUCCESSFUL_RETURN;
00721 
00722         if ( getNumPoints( ) == 1 )
00723         {
00724                 times[0] = _firstTime;
00725                 return SUCCESSFUL_RETURN;
00726         }
00727 
00728         if ( _firstTime > _lastTime )
00729                 return ACADOERROR( RET_INVALID_ARGUMENTS );
00730 
00731 
00732         double horizon = _lastTime - _firstTime;
00733 
00734         for( uint i=0; i<nPoints; ++i )
00735                 times[i] = _firstTime + ((double) i) / ((double) getNumPoints( )-1) * horizon;
00736 
00737         return SUCCESSFUL_RETURN;
00738 }
00739 
00740 
00741 int Grid::findNextIndex( ) const
00742 {
00743         if ( times == 0 )
00744                 return -1;
00745 
00746         for( uint i=0; i<getNumPoints( ); ++i )
00747                 if ( times[i] < -INFTY+1.0 )
00748                         return i;
00749 
00750         /* no uninitialised grid point found */
00751         return -1;
00752 }
00753 
00754 
00755 
00756 CLOSE_NAMESPACE_ACADO
00757 
00758 
00759 /*
00760  *      end of file
00761  */


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 11:58:25