computation/optimization/NLoptSolver.cxx

00001 // Copyright (C) 2010 INRIA
00002 // Author(s): Marc Fragu
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_COMPUTATION_OPTIMIZATION_NLOPTSOLVER_CXX
00022 #define SELDON_COMPUTATION_OPTIMIZATION_NLOPTSOLVER_CXX
00023 
00024 
00025 #include "NLoptSolver.hxx"
00026 
00027 
00028 namespace Seldon
00029 {
00030 
00031 
00033   NLoptSolver::NLoptSolver()
00034   {
00035   }
00036 
00037 
00039   NLoptSolver::~NLoptSolver()
00040   {
00041   }
00042 
00043 
00045 
00072   void NLoptSolver::Initialize(int Nparameter, string algorithm,
00073                                double parameter_tolerance,
00074                                double cost_function_tolerance,
00075                                int Niteration_max)
00076   {
00077     map<string, nlopt::algorithm> algorithm_map;
00078     map<string, nlopt::algorithm>::iterator it;
00079     algorithm_map["GN_DIRECT"] = nlopt::GN_DIRECT;
00080     algorithm_map["GN_DIRECT_L"] = nlopt::GN_DIRECT_L;
00081     algorithm_map["GN_DIRECT_L_RAND"] = nlopt::GN_DIRECT_L_RAND;
00082     algorithm_map["GN_DIRECT_NOSCAL"] = nlopt::GN_DIRECT_NOSCAL;
00083     algorithm_map["GN_DIRECT_L_NOSCAL"] = nlopt::GN_DIRECT_L_NOSCAL;
00084     algorithm_map["GN_DIRECT_L_RAND_NOSCAL"]
00085       = nlopt::GN_DIRECT_L_RAND_NOSCAL;
00086     algorithm_map["GN_ORIG_DIRECT"] = nlopt::GN_ORIG_DIRECT;
00087     algorithm_map["GN_ORIG_DIRECT_L"] = nlopt::GN_ORIG_DIRECT_L;
00088     algorithm_map["GD_STOGO"] = nlopt::GD_STOGO;
00089     algorithm_map["GD_STOGO_RAND"] = nlopt::GD_STOGO_RAND;
00090     algorithm_map["LD_LBFGS_NOCEDAL"] = nlopt::LD_LBFGS_NOCEDAL;
00091     algorithm_map["LD_LBFGS"] = nlopt::LD_LBFGS;
00092     algorithm_map["LN_PRAXIS"] = nlopt::LN_PRAXIS;
00093     algorithm_map["LD_VAR1"] = nlopt::LD_VAR1;
00094     algorithm_map["LD_VAR2"] = nlopt::LD_VAR2;
00095     algorithm_map["LD_TNEWTON"] = nlopt::LD_TNEWTON;
00096     algorithm_map["LD_TNEWTON_RESTART"] = nlopt::LD_TNEWTON_RESTART;
00097     algorithm_map["LD_TNEWTON_PRECOND"] = nlopt::LD_TNEWTON_PRECOND;
00098     algorithm_map["LD_TNEWTON_PRECOND_RESTART"]
00099       = nlopt::LD_TNEWTON_PRECOND_RESTART;
00100     algorithm_map["GN_CRS2_LM"] = nlopt::GN_CRS2_LM;
00101     algorithm_map["GN_MLSL"] = nlopt::GN_MLSL;
00102     algorithm_map["GD_MLSL"] = nlopt::GD_MLSL;
00103     algorithm_map["GN_MLSL_LDS"] = nlopt::GN_MLSL_LDS;
00104     algorithm_map["GD_MLSL_LDS"] = nlopt::GD_MLSL_LDS;
00105     algorithm_map["LD_MMA"] = nlopt::LD_MMA;
00106     algorithm_map["LN_COBYLA"] = nlopt::LN_COBYLA;
00107     algorithm_map["LN_NEWUOA"] = nlopt::LN_NEWUOA;
00108     algorithm_map["LN_NEWUOA_BOUND"] = nlopt::LN_NEWUOA_BOUND;
00109     algorithm_map["LN_NELDERMEAD"] = nlopt::LN_NELDERMEAD;
00110     algorithm_map["LN_SBPLX"] = nlopt::LN_SBPLX;
00111     algorithm_map["LN_AUGLAG"] = nlopt::LN_AUGLAG;
00112     algorithm_map["LD_AUGLAG"] = nlopt::LD_AUGLAG;
00113     algorithm_map["LN_AUGLAG_EQ"] = nlopt::LN_AUGLAG_EQ;
00114     algorithm_map["LD_AUGLAG_EQ"] = nlopt::LD_AUGLAG_EQ;
00115     algorithm_map["LN_BOBYQA"] = nlopt::LN_BOBYQA;
00116     algorithm_map["GN_ISRES"] = nlopt::GN_ISRES;
00117     algorithm_map["AUGLAG"] = nlopt::AUGLAG;
00118     algorithm_map["AUGLAG_EQ"] = nlopt::AUGLAG_EQ;
00119     algorithm_map["G_MLSL"] = nlopt::G_MLSL;
00120     algorithm_map["G_MLSL_LDS"] = nlopt::G_MLSL_LDS;
00121     algorithm_map["LD_SLSQP"] = nlopt::LD_SLSQP;
00122 
00123     it = algorithm_map.find(algorithm);
00124     if (it == algorithm_map.end())
00125       WrongArgument("void NLoptSolver::Initialize(int, string, double)",
00126                     "Unknown algorithm. Implemented algorithms are:"
00127                     " GN_DIRECT, "
00128                     "GN_DIRECT_L, GN_DIRECT_L_RAND, "
00129                     "GN_DIRECT_NOSCAL, "
00130                     "GN_DIRECT_L_NOSCAL, GN_DIRECT_L_RAND_NOSCAL,"
00131                     " GN_ORIG_DIRECT, "
00132                     "GN_ORIG_DIRECT_L, GD_STOGO, GD_STOGO_RAND, "
00133                     "LD_LBFGS_NOCEDAL, LD_LBFGS, LN_PRAXIS, "
00134                     "LD_VAR1, LD_VAR2, LD_TNEWTON, "
00135                     "LD_TNEWTON_RESTART, LD_TNEWTON_PRECOND, "
00136                     "LD_TNEWTON_PRECOND_RESTART, GN_CRS2_LM, "
00137                     "GN_MLSL,"
00138                     "GD_MLSL, GN_MLSL_LDS, GD_MLSL_LDS, "
00139                     "LD_MMA, LN_COBYLA, LN_NEWUOA, "
00140                     "LN_NEWUOA_BOUND, LN_NELDERMEAD, "
00141                     "LN_SBPLX, LN_AUGLAG, LD_AUGLAG, "
00142                     "LN_AUGLAG_EQ, LD_AUGLAG_EQ, LN_BOBYQA, "
00143                     "GN_ISRES, AUGLAG, AUGLAG_EQ,"
00144                     "G_MLSL, G_MLSL_LDS, LD_SLSQP, NUM_ALGORITHMS");
00145     else
00146       algorithm_ = it->second;
00147 
00148     opt_ = nlopt::SeldonOpt(algorithm_, Nparameter);
00149 
00150     parameter_tolerance_ = parameter_tolerance;
00151 
00152     cost_function_tolerance_ = cost_function_tolerance;
00153 
00154     Niteration_max_ = Niteration_max;
00155   }
00156 
00157 
00159 
00162   void NLoptSolver::SetLowerBound(const Vector<double>& lower_bound)
00163   {
00164     if (lower_bound.GetSize() != 0)
00165       opt_.set_lower_bounds(lower_bound);
00166   }
00167 
00168 
00170 
00173   void NLoptSolver::SetUpperBound(const Vector<double>& upper_bound)
00174   {
00175     if (upper_bound.GetSize() != 0)
00176       opt_.set_upper_bounds(upper_bound);
00177   }
00178 
00179 
00181 
00189   void NLoptSolver::SetParameterTolerance(double tolerance)
00190   {
00191     parameter_tolerance_ = tolerance;
00192   }
00193 
00194 
00196 
00204   void NLoptSolver::SetCostFunctionTolerance(double tolerance)
00205   {
00206     cost_function_tolerance_ = tolerance;
00207   }
00208 
00209 
00211 
00215   void NLoptSolver::SetNiterationMax(int Niteration_max)
00216   {
00217     Niteration_max_ = Niteration_max;
00218   }
00219 
00220 
00222 
00228   void NLoptSolver::GetParameterTolerance(double& tolerance) const
00229   {
00230     tolerance = parameter_tolerance_;
00231   }
00232 
00233 
00235 
00241   void NLoptSolver::GetCostFunctionTolerance(double& tolerance) const
00242   {
00243     tolerance = cost_function_tolerance_;
00244   }
00245 
00246 
00248 
00251   void NLoptSolver::GetNiterationMax(int& Niteration_max) const
00252   {
00253     Niteration_max = Niteration_max_;
00254   }
00255 
00256 
00258 
00261   void NLoptSolver::SetParameter(const Vector<double>& parameter)
00262   {
00263     parameter_.Reallocate(parameter.GetM());
00264     Copy(parameter, parameter_);
00265   }
00266 
00267 
00269 
00272   void NLoptSolver::GetParameter(Vector<double>& parameter) const
00273   {
00274     parameter.Reallocate(parameter_.GetM());
00275     Copy(parameter_, parameter);
00276   }
00277 
00278 
00280 
00293   void NLoptSolver::Optimize(cost_ptr cost, void* argument)
00294   {
00295     int Nparameter;
00296     if (0 == (Nparameter = parameter_.GetM()))
00297       throw WrongArgument("NLoptSolver::Optimize()",
00298                           "The vector of parameters to be optimized"
00299                           " is empty.");
00300 
00301     opt_.set_min_objective(cost, argument);
00302     opt_.set_xtol_rel(parameter_tolerance_);
00303     opt_.set_ftol_rel(cost_function_tolerance_);
00304     opt_.set_maxeval(Niteration_max_);
00305     nlopt::result result = opt_.optimize(parameter_, cost_);
00306 
00307     if (result < 0)
00308       throw Error("NLoptSolver::Optimize()", "Nlopt failed.");
00309   }
00310 
00311 
00313 
00317   double NLoptSolver::GetCost() const
00318   {
00319     return cost_;
00320   }
00321 
00322 
00323 } // namespace Seldon.
00324 
00325 
00326 #endif