Simbody
3.4 (development)
|
00001 #ifndef SimTK_SIMMATH_OPTIMIZER_H_ 00002 #define SimTK_SIMMATH_OPTIMIZER_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKmath * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2006-13 Stanford University and the Authors. * 00013 * Authors: Jack Middleton * 00014 * Contributors: Michael Sherman * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 00028 #include "SimTKcommon.h" 00029 #include "simmath/internal/common.h" 00030 #include "simmath/Differentiator.h" 00031 00032 namespace SimTK { 00033 00034 enum OptimizerAlgorithm { 00035 BestAvailable = 0, // Simmath will select best Optimizer based on problem type 00036 InteriorPoint = 1, // IPOPT interior point optimizer 00037 LBFGS = 2, // LBFGS optimizer 00038 LBFGSB = 3, // LBFGS optimizer with simple bounds 00039 CFSQP = 4 // CFSQP sequential quadratic programming optimizer (requires external library) 00040 }; 00041 00047 class SimTK_SIMMATH_EXPORT OptimizerSystem { 00048 public: 00049 OptimizerSystem() : numParameters(0), 00050 numEqualityConstraints(0), 00051 numInequalityConstraints(0), 00052 numLinearEqualityConstraints(0), 00053 numLinearInequalityConstraints(0), 00054 useLimits( false ), 00055 lowerLimits(0), 00056 upperLimits(0) { 00057 } 00058 00059 explicit OptimizerSystem(int nParameters ) { 00060 new (this) OptimizerSystem(); // call the above constructor 00061 setNumParameters(nParameters); 00062 } 00063 00064 virtual ~OptimizerSystem() { 00065 if( useLimits ) { 00066 delete lowerLimits; 00067 delete upperLimits; 00068 } 00069 } 00070 00073 virtual int objectiveFunc ( const Vector& parameters, 00074 bool new_parameters, Real& f ) const { 00075 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "objectiveFunc" ); 00076 return -1; } 00077 00080 virtual int gradientFunc ( const Vector ¶meters, 00081 bool new_parameters, Vector &gradient ) const { 00082 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "gradientFunc" ); 00083 return -1; } 00086 virtual int constraintFunc ( const Vector & parameters, 00087 bool new_parameters, Vector & constraints ) const { 00088 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "constraintFunc" ); 00089 return -1; } 00092 virtual int constraintJacobian ( const Vector& parameters, 00093 bool new_parameters, Matrix& jac ) const { 00094 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "constraintJacobian" ); 00095 return -1; } 00098 virtual int hessian ( const Vector ¶meters, 00099 bool new_parameters, Vector &gradient) const { 00100 SimTK_THROW2(SimTK::Exception::UnimplementedVirtualMethod , "OptimizerSystem", "hessian" ); 00101 return -1; } 00102 00104 void setNumParameters( const int nParameters ) { 00105 if( nParameters < 1 ) { 00106 const char* where = " OptimizerSystem Constructor"; 00107 const char* szName = "number of parameters"; 00108 SimTK_THROW5(SimTK::Exception::ValueOutOfRange, szName, 1, nParameters, INT_MAX, where); 00109 } else { 00110 numParameters = nParameters; 00111 } 00112 } 00114 void setNumEqualityConstraints( const int n ) { 00115 if( n < 0 ) { 00116 const char* where = " OptimizerSystem setNumEqualityConstraints"; 00117 const char* szName = "number of equality constraints"; 00118 SimTK_THROW3(SimTK::Exception::SizeWasNegative, szName, n, where); 00119 } else { 00120 numEqualityConstraints = n; 00121 } 00122 } 00124 void setNumInequalityConstraints( const int n ) { 00125 if( n < 0 ) { 00126 const char* where = " OptimizerSystem setNumInequalityConstraints"; 00127 const char* szName = "number of inequality constraints"; 00128 SimTK_THROW3(SimTK::Exception::SizeWasNegative, szName, n, where); 00129 } else { 00130 numInequalityConstraints = n; 00131 } 00132 } 00134 void setNumLinearEqualityConstraints( const int n ) { 00135 if( n < 0 || n > numEqualityConstraints ) { 00136 const char* where = " OptimizerSystem setNumLinearEqualityConstraints"; 00137 const char* szName = "number of linear equality constraints"; 00138 SimTK_THROW4(SimTK::Exception::SizeOutOfRange, szName, n, numEqualityConstraints, where); 00139 } else { 00140 numLinearEqualityConstraints = n; 00141 } 00142 } 00144 void setNumLinearInequalityConstraints( const int n ) { 00145 if( n < 0 || n > numInequalityConstraints ) { 00146 const char* where = " OptimizerSystem setNumLinearInequalityConstraints"; 00147 const char* szName = "number of linear inequality constraints"; 00148 SimTK_THROW4(SimTK::Exception::SizeOutOfRange, szName, n, numInequalityConstraints, where); 00149 } else { 00150 numLinearInequalityConstraints = n; 00151 } 00152 } 00154 void setParameterLimits( const Vector& lower, const Vector& upper ) { 00155 if( upper.size() != numParameters && upper.size() != 0) { 00156 const char* where = " OptimizerSystem setParamtersLimits"; 00157 const char* szName = "upper limits length"; 00158 SimTK_THROW5(Exception::IncorrectArrayLength, szName, upper.size(), "numParameters", numParameters, where); 00159 } 00160 if( lower.size() != numParameters && lower.size() != 0 ) { 00161 const char* where = " OptimizerSystem setParamtersLimits"; 00162 const char* szName = "lower limits length"; 00163 SimTK_THROW5(Exception::IncorrectArrayLength, szName, lower.size(), "numParameters", numParameters, where); 00164 } 00165 00166 // set the upper and lower limits 00167 if( useLimits ) { 00168 delete lowerLimits; 00169 delete upperLimits; 00170 } 00171 00172 if( upper.size() == 0 ) { 00173 useLimits = false; 00174 } else { 00175 lowerLimits = new Vector( lower ); 00176 upperLimits = new Vector( upper ); 00177 useLimits = true; 00178 } 00179 } 00180 00183 int getNumParameters() const {return numParameters;} 00185 int getNumConstraints() const {return numEqualityConstraints+numInequalityConstraints;} 00187 int getNumEqualityConstraints() const {return numEqualityConstraints;} 00189 int getNumInequalityConstraints() const {return numInequalityConstraints;} 00191 int getNumLinearEqualityConstraints() const {return numLinearEqualityConstraints;} 00193 int getNumNonlinearEqualityConstraints() const {return numEqualityConstraints-numLinearEqualityConstraints;} 00195 int getNumLinearInequalityConstraints() const {return numLinearInequalityConstraints;} 00197 int getNumNonlinearInequalityConstraints() const {return numInequalityConstraints-numLinearInequalityConstraints;} 00198 00200 bool getHasLimits() const { return useLimits; } 00204 void getParameterLimits( Real **lower, Real **upper ) const { 00205 *lower = &(*lowerLimits)[0]; 00206 *upper = &(*upperLimits)[0]; 00207 } 00208 00209 private: 00210 int numParameters; 00211 int numEqualityConstraints; 00212 int numInequalityConstraints; 00213 int numLinearEqualityConstraints; 00214 int numLinearInequalityConstraints; 00215 bool useLimits; 00216 Vector* lowerLimits; 00217 Vector* upperLimits; 00218 00219 }; // class OptimizerSystem 00220 00241 class SimTK_SIMMATH_EXPORT Optimizer { 00242 public: 00243 Optimizer(); 00244 Optimizer( const OptimizerSystem& sys); 00245 Optimizer( const OptimizerSystem& sys, OptimizerAlgorithm algorithm); 00246 ~Optimizer(); 00247 00248 static bool isAlgorithmAvailable(OptimizerAlgorithm algorithm); 00249 00251 void setConvergenceTolerance(Real accuracy ); 00254 void setConstraintTolerance(Real tolerance); 00255 00256 00262 void setMaxIterations( int iter ); 00264 void setLimitedMemoryHistory( int history ); 00266 void setDiagnosticsLevel( int level ); 00267 00268 void setOptimizerSystem( const OptimizerSystem& sys ); 00269 void setOptimizerSystem( const OptimizerSystem& sys, OptimizerAlgorithm algorithm ); 00270 00272 bool setAdvancedStrOption( const char *option, const char *value ); 00274 bool setAdvancedRealOption( const char *option, const Real value ); 00276 bool setAdvancedIntOption( const char *option, const int value ); 00278 bool setAdvancedBoolOption( const char *option, const bool value ); 00279 00280 00290 void setDifferentiatorMethod(Differentiator::Method method); 00295 Differentiator::Method getDifferentiatorMethod() const; 00296 00308 void useNumericalGradient(bool flag, 00309 Real estimatedAccuracyOfObjective = SignificantReal); 00322 void useNumericalJacobian(bool flag, 00323 Real estimatedAccuracyOfConstraints = SignificantReal); 00324 00326 Real optimize(Vector&); 00327 00329 const OptimizerSystem& getOptimizerSystem() const; 00330 00332 bool isUsingNumericalGradient() const; 00334 bool isUsingNumericalJacobian() const; 00336 Real getEstimatedAccuracyOfObjective() const; 00338 Real getEstimatedAccuracyOfConstraints() const; 00339 00340 // This is a local class. 00341 class OptimizerRep; 00342 private: 00343 Optimizer( const Optimizer& c ); 00344 Optimizer& operator=(const Optimizer& rhs); 00345 00346 OptimizerRep* constructOptimizerRep(const OptimizerSystem&, OptimizerAlgorithm); 00347 const OptimizerRep& getRep() const {assert(rep); return *rep;} 00348 OptimizerRep& updRep() {assert(rep); return *rep;} 00349 00350 // Hidden implementation to preserve binary compatibility. 00351 OptimizerRep* rep; 00352 00353 friend class OptimizerRep; 00354 }; // class Optimizer 00355 00356 } // namespace SimTK 00357 00358 #endif //SimTK_SIMMATH_OPTIMIZER_H_ 00359