00001
00002 #ifndef _SimTK_OPTIMIZER_H
00003 #define _SimTK_OPTIMIZER_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "SimTKcommon.h"
00038 #include "SimTKmath.h"
00039 #include <limits.h>
00040
00041 namespace SimTK {
00042
00043 enum OptimizerAlgorithm {
00044 BestAvailiable = 0,
00045 InteriorPoint = 1,
00046 LBFGS = 2,
00047 LBFGSB = 3,
00048 CFSQP = 4
00049 };
00056 class SimTK_SIMMATH_EXPORT OptimizerSystem {
00057 public:
00058 OptimizerSystem() : numParameters(0),
00059 numEqualityConstraints(0),
00060 numInequalityConstraints(0),
00061 numLinearEqualityConstraints(0),
00062 numLinearInequalityConstraints(0),
00063 useLimits( false ),
00064 lowerLimits(0),
00065 upperLimits(0) {
00066 }
00067
00068 OptimizerSystem(int nParameters ) : numEqualityConstraints(0),
00069 numInequalityConstraints(0),
00070 numLinearEqualityConstraints(0),
00071 numLinearInequalityConstraints(0),
00072 useLimits( false ),
00073 lowerLimits(0),
00074 upperLimits(0) {
00075 setNumParameters(nParameters);
00076 }
00077
00078 virtual ~OptimizerSystem() {
00079 if( useLimits ) {
00080 delete lowerLimits;
00081 delete upperLimits;
00082 }
00083 }
00084
00087 virtual int objectiveFunc ( const Vector& parameters,
00088 const bool new_parameters, Real& f ) const {
00089 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "objectiveFunc" );
00090 return -1; }
00091
00094 virtual int gradientFunc ( const Vector ¶meters,
00095 const bool new_parameters, Vector &gradient ) const {
00096 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "gradientFunc" );
00097 return -1; }
00100 virtual int constraintFunc ( const Vector & parameters,
00101 const bool new_parameters, Vector & constraints ) const {
00102 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "constraintFunc" );
00103 return -1; }
00106 virtual int constraintJacobian ( const Vector& parameters,
00107 const bool new_parameters, Matrix& jac ) const {
00108 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "constraintJacobian" );
00109 return -1; }
00112 virtual int hessian ( const Vector ¶meters,
00113 const bool new_parameters, Vector &gradient) const {
00114 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "hessian" );
00115 return -1; }
00117 virtual void setNumParameters( const int nParameters ) {
00118
00119 if( nParameters < 1 ) {
00120 const char* where = " OptimizerSystem Constructor";
00121 const char* szName = "number of parameters";
00122 SimTK_THROW5(SimTK::Exception::ValueOutOfRange, szName, 1, nParameters, INT_MAX, where);
00123 }else {
00124 numParameters = nParameters;
00125 }
00126 }
00128 void setNumEqualityConstraints( const int n ) {
00129
00130 if( n < 0 ) {
00131 const char* where = " OptimizerSystem setNumEqualityConstraints";
00132 const char* szName = "number of equality constraints";
00133 SimTK_THROW3(SimTK::Exception::SizeWasNegative, szName, n, where);
00134 } else {
00135 numEqualityConstraints = n;
00136 }
00137 }
00139 void setNumInequalityConstraints( const int n ) {
00140
00141 if( n < 0 ) {
00142 const char* where = " OptimizerSystem setNumInequalityConstraints";
00143 const char* szName = "number of inequality constraints";
00144 SimTK_THROW3(SimTK::Exception::SizeWasNegative, szName, n, where);
00145 }else {
00146 numInequalityConstraints = n;
00147 }
00148 }
00150 void setNumLinearEqualityConstraints( const int n ) {
00151
00152 if( n < 0 || n > numEqualityConstraints ) {
00153 const char* where = " OptimizerSystem setNumLinearEqualityConstraints";
00154 const char* szName = "number of linear equality constraints";
00155 SimTK_THROW4(SimTK::Exception::SizeOutOfRange, szName, n, numEqualityConstraints, where);
00156 } else {
00157 numLinearEqualityConstraints = n;
00158 }
00159 }
00161 void setNumLinearInequalityConstraints( const int n ) {
00162
00163 if( n < 0 || n > numInequalityConstraints ) {
00164 const char* where = " OptimizerSystem setNumLinearInequalityConstraints";
00165 const char* szName = "number of linear inequality constraints";
00166 SimTK_THROW4(SimTK::Exception::SizeOutOfRange, szName, n, numInequalityConstraints, where);
00167 }else {
00168 numLinearInequalityConstraints = n;
00169 }
00170 }
00172 void setParameterLimits( const Vector& lower, const Vector& upper ) {
00173
00174 if( upper.size() != numParameters && upper.size() != 0) {
00175 const char* where = " OptimizerSystem setParamtersLimits";
00176 const char* szName = "upper limits length";
00177 SimTK_THROW5(Exception::IncorrectArrayLength, szName, upper.size(), "numParameters", numParameters, where);
00178 }
00179 if( lower.size() != numParameters && lower.size() != 0 ) {
00180 const char* where = " OptimizerSystem setParamtersLimits";
00181 const char* szName = "lower limits length";
00182 SimTK_THROW5(Exception::IncorrectArrayLength, szName, lower.size(), "numParameters", numParameters, where);
00183 }
00184
00185 if( useLimits ) {
00186 delete lowerLimits;
00187 delete upperLimits;
00188 }
00189
00190 if( upper.size() == 0 ) {
00191 useLimits = false;
00192 } else {
00193 lowerLimits = new Vector( lower );
00194 upperLimits = new Vector( upper );
00195 useLimits = true;
00196 }
00197
00198 return;
00199 }
00201 int getNumParameters() const {return numParameters;}
00202
00204 int getNumConstraints() const {return numEqualityConstraints+numInequalityConstraints;}
00206 int getNumEqualityConstraints() const {return numEqualityConstraints;}
00208 int getNumInequalityConstraints() const {return numInequalityConstraints;}
00210 int getNumLinearEqualityConstraints() const {return numLinearEqualityConstraints;}
00212 int getNumNonlinearEqualityConstraints() const {return numEqualityConstraints-numLinearEqualityConstraints;}
00214 int getNumLinearInequalityConstraints() const {return numLinearInequalityConstraints;}
00216 int getNumNonlinearInequalityConstraints() const {return numInequalityConstraints-numLinearInequalityConstraints;}
00217
00219 bool getHasLimits() const { return useLimits; }
00221 void getParameterLimits( double **lower, double **upper ) const {
00222 *lower = &(*lowerLimits)[0];
00223 *upper = &(*upperLimits)[0];
00224 }
00225
00226
00227 int numParameters;
00228 int numEqualityConstraints;
00229 int numInequalityConstraints;
00230 int numLinearEqualityConstraints;
00231 int numLinearInequalityConstraints;
00232 bool useLimits;
00233 Vector* lowerLimits;
00234 Vector* upperLimits;
00235
00236 };
00237
00238
00239
00240
00241
00242 static int objectiveFunc_static(const OptimizerSystem& sys,
00243 const Vector& parameters,
00244 const bool new_parameters, Real& f ) {
00245
00246 return sys.objectiveFunc(parameters, new_parameters, f);
00247 }
00248 static int gradientFunc_static(const OptimizerSystem& sys,
00249 const Vector ¶meters,
00250 const bool new_parameters, Vector &gradient ) {
00251 return sys.gradientFunc( parameters, new_parameters, gradient);
00252 }
00253 static int constraintFunc_static(const OptimizerSystem& sys,
00254 const Vector ¶meters,
00255 const bool new_parameters, Vector& constraints ) {
00256 return sys.constraintFunc( parameters, new_parameters, constraints);
00257 }
00258 static int constraintJacobian_static(const OptimizerSystem& sys,
00259 const Vector ¶meters,
00260 const bool new_parameters, Matrix& jac ) {
00261 return sys.constraintJacobian( parameters, new_parameters, jac);
00262 }
00263 static int hessian_static(const OptimizerSystem& sys,
00264 const Vector ¶meters,
00265 const bool new_parameters, Vector& gradient ) {
00266 return sys.hessian( parameters, new_parameters, gradient);
00267 }
00268
00291 class SimTK_SIMMATH_EXPORT Optimizer {
00292
00293 public:
00294
00295 Optimizer();
00296 Optimizer( const OptimizerSystem& sys);
00297 Optimizer( const OptimizerSystem& sys, OptimizerAlgorithm algorithm);
00298
00299
00300 ~Optimizer();
00301
00302 static bool isAlgorithmAvailable(OptimizerAlgorithm algorithm);
00303
00305 void setConvergenceTolerance( const Real tolerance );
00307 void setMaxIterations( const int iter );
00309 void setLimitedMemoryHistory( const int history );
00311 void setDiagnosticsLevel( const int level );
00313 void setDifferentiatorMethod( Differentiator::Method method);
00314
00315 void setOptimizerSystem( const OptimizerSystem& sys );
00316 void setOptimizerSystem( const OptimizerSystem& sys, OptimizerAlgorithm algorithm );
00317
00319 bool setAdvancedStrOption( const char *option, const char *value );
00321 bool setAdvancedRealOption( const char *option, const Real value );
00323 bool setAdvancedIntOption( const char *option, const int value );
00325 bool setAdvancedBoolOption( const char *option, const bool value );
00326
00328 void useNumericalGradient( const bool flag );
00330 void useNumericalJacobian( const bool flag );
00331
00333 double optimize(Vector&);
00334
00335 private:
00336 typedef int (*ObjectiveFunc) ( const OptimizerSystem&,
00337 const Vector& parameters, const bool new_parameters,
00338 Real& f );
00339
00340 typedef int (*GradientFunc) ( const OptimizerSystem&,
00341 const Vector ¶meters, const bool new_parameters,
00342 Vector &gradient );
00343
00344 typedef int (*ConstraintFunc) ( const OptimizerSystem&,
00345 const Vector & parameters, const bool new_parameters,
00346 Vector &constraints );
00347
00348 typedef int (*ConstraintJacobian) ( const OptimizerSystem&,
00349 const Vector& parameters, const bool new_parameters,
00350 Matrix& jac );
00351
00352 typedef int (*Hessian) ( const OptimizerSystem&,
00353 const Vector ¶meters, const bool new_parameters,
00354 Vector &gradient);
00355
00356 void registerObjectiveFunc( ObjectiveFunc );
00357 void registerGradientFunc( GradientFunc );
00358 void registerConstraintFunc( ConstraintFunc );
00359 void registerConstraintJacobian( ConstraintJacobian );
00360 void registerHessian( Hessian );
00361
00362
00363
00364 void librarySideOptimizerConstructor(const OptimizerSystem& sys, OptimizerAlgorithm algorithm);
00365
00366 void clientSideOptimizerConstructor() {
00367 registerObjectiveFunc( objectiveFunc_static );
00368 registerGradientFunc( gradientFunc_static );
00369 registerConstraintFunc( constraintFunc_static );
00370 registerConstraintJacobian( constraintJacobian_static );
00371 registerHessian( hessian_static );
00372 }
00373
00374 class OptimizerRep* rep;
00375 friend class OptimizerRep;
00376
00377 const OptimizerRep& getRep() const {assert(rep); return *rep;}
00378 OptimizerRep& updRep() {assert(rep); return *rep;}
00379
00380 Optimizer( const Optimizer& c );
00381 Optimizer& operator=(const Optimizer& rhs);
00382
00383 };
00384
00385 }
00386
00387 #endif //_SimTK_OPTIMIZER_H
00388