Warning: this documentation for the development version is under construction.

/home/vivien/public_html/.src_seldon/computation/optimization/NLopt.hxx

00001 // Copyright (c) 2007-2010 Massachusetts Institute of Technology
00002 // Modifications by Marc Fragu, copyright (C) 2011 INRIA
00003 //
00004 // Permission is hereby granted, free of charge, to any person obtaining a
00005 // copy of this software and associated documentation files (the "Software"),
00006 // to deal in the Software without restriction, including without limitation
00007 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 // and/or sell copies of the Software, and to permit persons to whom the
00009 // Software is furnished to do so, subject to the following conditions:
00010 //
00011 // The above copyright notice and this permission notice shall be included in
00012 // all copies or substantial portions of the Software.
00013 //
00014 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020 // DEALINGS IN THE SOFTWARE.
00021 
00022 
00023 #ifndef SELDON_COMPUTATION_OPTIMIZATION_NLOPT_HXX
00024 #define SELDON_COMPUTATION_OPTIMIZATION_NLOPT_HXX
00025 
00026 
00027 #include <nlopt.hpp>
00028 
00029 
00030 namespace nlopt
00031 {
00032 
00033 
00034   typedef double (*svfunc)(const Seldon::Vector<double> &x,
00035                            Seldon::Vector<double> &grad, void *data);
00036 
00037   class SeldonOpt
00038   {
00039 
00040   private:
00041 
00042     nlopt_opt o;
00043 
00044     void mythrow(nlopt_result ret) const
00045     {
00046       switch (ret)
00047         {
00048         case NLOPT_FAILURE:
00049           throw Seldon::Error("SeldonOpt", "Nlopt failure.");
00050         case NLOPT_OUT_OF_MEMORY:
00051           throw Seldon::NoMemory("SeldonOpt",
00052                                  "Nlopt failed to allocate the"
00053                                  " requested storage space.");
00054         case NLOPT_INVALID_ARGS:
00055           throw Seldon::WrongArgument("SeldonOpt", "Nlopt invalid argument.");
00056         case NLOPT_ROUNDOFF_LIMITED:
00057           throw Seldon::Error("SeldonOpt", "Nlopt roundoff-limited.");
00058         case NLOPT_FORCED_STOP:
00059           throw Seldon::Error("SeldonOpt", "Nlopt forced stop.");
00060         default:
00061           break;
00062         }
00063     }
00064 
00065 
00066     typedef struct
00067     {
00068       SeldonOpt* o;
00069       mfunc mf;
00070       func f;
00071       void* f_data;
00072       svfunc vf;
00073       nlopt_munge munge_destroy, munge_copy;
00074     } myfunc_data;
00075 
00076 
00077     static void *free_myfunc_data(void *p)
00078     {
00079       myfunc_data *d = (myfunc_data *) p;
00080       if (d)
00081         {
00082           if (d->f_data && d->munge_destroy)
00083             d->munge_destroy(d->f_data);
00084           delete d;
00085         }
00086       return NULL;
00087     }
00088 
00089 
00090     static void *dup_myfunc_data(void *p)
00091     {
00092       myfunc_data *d = (myfunc_data *) p;
00093       if (d)
00094         {
00095           void *f_data;
00096           if (d->f_data && d->munge_copy) {
00097             f_data = d->munge_copy(d->f_data);
00098             if (!f_data)
00099               return NULL;
00100           }
00101           else
00102             f_data = d->f_data;
00103           myfunc_data *dnew = new myfunc_data;
00104           if (dnew)
00105             {
00106               *dnew = *d;
00107               dnew->f_data = f_data;
00108             }
00109           return (void*) dnew;
00110         }
00111       else
00112         return NULL;
00113     }
00114 
00115 
00116     static double myfunc(unsigned n, const double *x, double *grad,
00117                          void *d_)
00118     {
00119       myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
00120       return d->f(n, x, grad, d->f_data);
00121     }
00122 
00123 
00124     static void mymfunc(unsigned m, double *result,
00125                         unsigned n, const double *x,
00126                         double *grad, void *d_)
00127     {
00128       myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
00129       d->mf(m, result, n, x, grad, d->f_data);
00130       return;
00131     }
00132 
00133 
00134     Seldon::Vector<double> xtmp, gradtmp, gradtmp0;
00135 
00136 
00137     static double myvfunc(unsigned n, const double *x, double *grad,
00138                           void *d_)
00139     {
00140       myfunc_data *d = reinterpret_cast<myfunc_data*>(d_);
00141       Seldon::Vector<double> &xv = d->o->xtmp;
00142       if (n)
00143         memcpy(xv.GetData(), x, n * sizeof(double));
00144 
00145       double val=d->vf(xv, grad ? d->o->gradtmp : d->o->gradtmp0,
00146                        d->f_data);
00147       if (grad && n)
00148         {
00149           Seldon::Vector<double> &gradv = d->o->gradtmp;
00150           memcpy(grad, gradv.GetData(), n * sizeof(double));
00151         }
00152       return val;
00153     }
00154 
00155 
00156     void alloc_tmp()
00157     {
00158       if (xtmp.GetSize() != int(nlopt_get_dimension(o)))
00159         {
00160           xtmp = Seldon::Vector<double>(nlopt_get_dimension(o));
00161           gradtmp = Seldon::Vector<double>(nlopt_get_dimension(o));
00162         }
00163     }
00164 
00165 
00166     result last_result;
00167     double last_optf;
00168     nlopt_result forced_stop_reason;
00169 
00170 
00171   public:
00172 
00173     SeldonOpt() : o(NULL), xtmp(0), gradtmp(0), gradtmp0(0),
00174                   last_result(nlopt::FAILURE), last_optf(HUGE_VAL),
00175                   forced_stop_reason(NLOPT_FORCED_STOP)
00176     {
00177     }
00178 
00179 
00180     ~SeldonOpt()
00181     {
00182       nlopt_destroy(o);
00183     }
00184 
00185 
00186     SeldonOpt(algorithm a, unsigned n) :
00187       o(nlopt_create(nlopt_algorithm(a), n)),
00188       xtmp(0), gradtmp(0), gradtmp0(0),
00189       last_result(nlopt::FAILURE), last_optf(HUGE_VAL),
00190       forced_stop_reason(NLOPT_FORCED_STOP)
00191     {
00192       if (!o)
00193         throw Seldon::NoMemory("SeldonOpt(algorithm a, unsigned n)",
00194                                "Nlopt failed to allocate the"
00195                                " requested storage space.");
00196       nlopt_set_munge(o, free_myfunc_data, dup_myfunc_data);
00197     }
00198 
00199 
00200     SeldonOpt(const SeldonOpt& f) :
00201       o(nlopt_copy(f.o)),
00202       xtmp(f.xtmp), gradtmp(f.gradtmp),
00203       gradtmp0(0),
00204       last_result(f.last_result),
00205       last_optf(f.last_optf),
00206       forced_stop_reason(f.forced_stop_reason)
00207     {
00208       if (f.o && !o)
00209         throw Seldon::NoMemory("SeldonOpt(const SeldonOpt& f)",
00210                                "Nlopt failed to allocate the"
00211                                " requested storage space.");
00212     }
00213 
00214 
00215     SeldonOpt& operator=(SeldonOpt const& f)
00216     {
00217       if (this == &f)
00218         return *this;
00219       nlopt_destroy(o);
00220       o = nlopt_copy(f.o);
00221       if (f.o && !o)
00222         throw Seldon::NoMemory("SeldonOpt::operator=(const SeldonOpt& f)",
00223                                "Nlopt failed to allocate the"
00224                                " requested storage space.");
00225       xtmp = f.xtmp;
00226       gradtmp = f.gradtmp;
00227       last_result = f.last_result;
00228       last_optf = f.last_optf;
00229       forced_stop_reason = f.forced_stop_reason;
00230       return *this;
00231     }
00232 
00233 
00234     result optimize(Seldon::Vector<double>& x, double& opt_f)
00235     {
00236       if (o && int(nlopt_get_dimension(o)) != x.GetSize())
00237         throw Seldon::WrongArgument("SeldonOpt::optimize("
00238                                     "Seldon::Vector<double>& x,"
00239                                     " double& opt_f)", "Dimension mismatch.");
00240       forced_stop_reason = NLOPT_FORCED_STOP;
00241       nlopt_result ret =
00242         nlopt_optimize(o, x.GetSize() == 0 ? NULL : x.GetData(),
00243                        &opt_f);
00244       last_result = result(ret);
00245       last_optf = opt_f;
00246       if (ret == NLOPT_FORCED_STOP)
00247         mythrow(forced_stop_reason);
00248       mythrow(ret);
00249       return last_result;
00250     }
00251 
00252 
00253     Seldon::Vector<double> optimize(const Seldon::Vector<double> &x0)
00254     {
00255       Seldon::Vector<double> x(x0);
00256       last_result = optimize(x, last_optf);
00257       return x;
00258     }
00259 
00260 
00261     result last_optimize_result() const
00262     {
00263       return last_result;
00264     }
00265 
00266 
00267     double last_optimum_value() const
00268     {
00269       return last_optf;
00270     }
00271 
00272 
00273     algorithm get_algorithm() const
00274     {
00275       if (!o)
00276         throw Seldon::Error("SeldonOpt::get_algorithm() const",
00277                             "Uninitialized nlopt::SeldonOpt.");
00278       return algorithm(nlopt_get_algorithm(o));
00279     }
00280 
00281 
00282     const char *get_algorithm_name() const
00283     {
00284       if (!o)
00285         Seldon::Error("SeldonOpt::get_algorithm() const",
00286                       "Uninitialized nlopt::SeldonOpt.");
00287       return nlopt_algorithm_name(nlopt_get_algorithm(o));
00288     }
00289 
00290 
00291     unsigned get_dimension() const
00292     {
00293       if (!o)
00294         Seldon::Error("SeldonOpt::get_algorithm() const",
00295                       "Uninitialized nlopt::SeldonOpt.");
00296       return nlopt_get_dimension(o);
00297     }
00298 
00299 
00300     void set_min_objective(func f, void *f_data)
00301     {
00302       myfunc_data *d = new myfunc_data;
00303       if (!d)
00304         throw Seldon::NoMemory("SeldonOpt::set_min_objective(func f, "
00305                                "void *f_data)", "Nlopt failed to allocate the"
00306                                " requested storage space.");
00307       d->o = this;
00308       d->f = f;
00309       d->f_data = f_data;
00310       d->mf = NULL;
00311       d->vf = NULL;
00312       d->munge_destroy = d->munge_copy = NULL;
00313       mythrow(nlopt_set_min_objective(o, myfunc, d));
00314     }
00315 
00316 
00317     void set_min_objective(svfunc vf, void *f_data) {
00318       myfunc_data *d = new myfunc_data;
00319       if (!d)
00320         throw Seldon::NoMemory("SeldonOpt::set_min_objective(func f, "
00321                                "void *f_data)", "Nlopt failed to allocate the"
00322                                " requested storage space.");
00323       d->o = this;
00324       d->f = NULL;
00325       d->f_data = f_data;
00326       d->mf = NULL;
00327       d->vf = vf;
00328       d->munge_destroy = d->munge_copy = NULL;
00329       mythrow(nlopt_set_min_objective(o, myvfunc, d));
00330       alloc_tmp();
00331     }
00332 
00333 
00334     void set_max_objective(func f, void *f_data) {
00335       myfunc_data *d = new myfunc_data;
00336       if (!d)
00337         throw Seldon::NoMemory("SeldonOpt::set_min_objective(func f, "
00338                                "void *f_data)", "Nlopt failed to allocate the"
00339                                " requested storage space.");
00340       d->o = this;
00341       d->f = f;
00342       d->f_data = f_data;
00343       d->mf = NULL;
00344       d->vf = NULL;
00345       d->munge_destroy = d->munge_copy = NULL;
00346       mythrow(nlopt_set_max_objective(o, myfunc, d));
00347     }
00348 
00349 
00350     void set_max_objective(svfunc vf, void *f_data)
00351     {
00352       myfunc_data *d = new myfunc_data;
00353       if (!d)
00354         throw Seldon::NoMemory("SeldonOpt::set_max_objective(func f, "
00355                                "void *f_data)", "Nlopt failed to allocate the"
00356                                " requested storage space.");
00357       d->o = this;
00358       d->f = NULL;
00359       d->f_data = f_data;
00360       d->mf = NULL;
00361       d->vf = vf;
00362       d->munge_destroy = d->munge_copy = NULL;
00363       mythrow(nlopt_set_max_objective(o, myvfunc, d));
00364       alloc_tmp();
00365     }
00366 
00367 
00368     void set_min_objective(func f, void *f_data,
00369                            nlopt_munge md, nlopt_munge mc)
00370     {
00371       myfunc_data *d = new myfunc_data;
00372       if (!d)
00373         throw Seldon::NoMemory("SeldonOpt::set_min_objective(func f, "
00374                                "void *f_data)", "Nlopt failed to allocate the"
00375                                " requested storage space.");
00376       d->o = this;
00377       d->f = f;
00378       d->f_data = f_data;
00379       d->mf = NULL;
00380       d->vf = NULL;
00381       d->munge_destroy = md;
00382       d->munge_copy = mc;
00383       mythrow(nlopt_set_min_objective(o, myfunc, d));
00384     }
00385 
00386 
00387     void set_max_objective(func f, void *f_data,
00388                            nlopt_munge md, nlopt_munge mc)
00389     {
00390       myfunc_data *d = new myfunc_data;
00391       if (!d)
00392         throw Seldon::NoMemory("SeldonOpt::set_max_objective(func f, "
00393                                "void *f_data)", "Nlopt failed to allocate the"
00394                                " requested storage space.");
00395       d->o = this;
00396       d->f = f;
00397       d->f_data = f_data;
00398       d->mf = NULL;
00399       d->vf = NULL;
00400       d->munge_destroy = md;
00401       d->munge_copy = mc;
00402       mythrow(nlopt_set_max_objective(o, myfunc, d));
00403     }
00404 
00405 
00406     void remove_inequality_constraints()
00407     {
00408       nlopt_result ret = nlopt_remove_inequality_constraints(o);
00409       mythrow(ret);
00410     }
00411 
00412 
00413     void add_inequality_constraint(func f, void *f_data, double tol = 0)
00414     {
00415       myfunc_data *d = new myfunc_data;
00416       if (!d)
00417         throw Seldon::NoMemory("SeldonOpt::add_inequality_constraint(func f, "
00418                                "void *f_data, double tol = 0)",
00419                                "Nlopt failed to allocate the"
00420                                " requested storage space.");
00421       d->o = this;
00422       d->f = f;
00423       d->f_data = f_data;
00424       d->mf = NULL;
00425       d->vf = NULL;
00426       d->munge_destroy = d->munge_copy = NULL;
00427       mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol));
00428     }
00429 
00430 
00431     void add_inequality_constraint(svfunc vf, void *f_data,
00432                                    double tol = 0)
00433     {
00434       myfunc_data *d = new myfunc_data;
00435       if (!d)
00436         throw Seldon::NoMemory("SeldonOpt::add_inequality_constraint(func f, "
00437                                "void *f_data, double tol = 0)",
00438                                "Nlopt failed to allocate the"
00439                                " requested storage space.");
00440       d->o = this;
00441       d->f = NULL;
00442       d->f_data = f_data;
00443       d->mf = NULL;
00444       d->vf = vf;
00445       d->munge_destroy = d->munge_copy = NULL;
00446       mythrow(nlopt_add_inequality_constraint(o, myvfunc, d, tol));
00447       alloc_tmp();
00448     }
00449 
00450 
00451     void add_inequality_mconstraint(mfunc mf, void *f_data,
00452                                     const Seldon::Vector<double> &tol)
00453     {
00454       myfunc_data *d = new myfunc_data;
00455       if (!d)
00456         throw Seldon::NoMemory("SeldonOpt::add_inequality_mconstraint(func f,"
00457                                " void *f_data, double tol = 0)",
00458                                "Nlopt failed to allocate the"
00459                                " requested storage space.");
00460       d->o = this;
00461       d->mf = mf;
00462       d->f_data = f_data;
00463       d->f = NULL;
00464       d->vf = NULL;
00465       d->munge_destroy = d->munge_copy = NULL;
00466       mythrow(nlopt_add_inequality_mconstraint(o, tol.GetSize(),
00467                                                mymfunc, d,
00468                                                tol.GetSize() == 0
00469                                                ? NULL : tol.GetData()));
00470     }
00471 
00472 
00473     void remove_equality_constraints()
00474     {
00475       nlopt_result ret = nlopt_remove_equality_constraints(o);
00476       mythrow(ret);
00477     }
00478 
00479 
00480     void add_equality_constraint(func f, void *f_data, double tol = 0)
00481     {
00482       myfunc_data *d = new myfunc_data;
00483       if (!d)
00484         throw Seldon::NoMemory("SeldonOpt::add_equality_constraint(func f, "
00485                                "void *f_data, double tol = 0)",
00486                                "Nlopt failed to allocate the"
00487                                " requested storage space.");
00488       d->o = this;
00489       d->f = f;
00490       d->f_data = f_data;
00491       d->mf = NULL;
00492       d->vf = NULL;
00493       d->munge_destroy = d->munge_copy = NULL;
00494       nlopt_add_equality_constraint(o, myfunc, d, tol);
00495       mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol));
00496     }
00497 
00498 
00499     void add_equality_constraint(svfunc vf, void *f_data, double tol = 0)
00500     {
00501       myfunc_data *d = new myfunc_data;
00502       if (!d)
00503         throw Seldon::NoMemory("SeldonOpt::add_equality_constraint(func f, "
00504                                "void *f_data, double tol = 0)",
00505                                "Nlopt failed to allocate the"
00506                                " requested storage space.");
00507       d->o = this;
00508       d->f = NULL;
00509       d->f_data = f_data;
00510       d->mf = NULL;
00511       d->vf = vf;
00512       d->munge_destroy = d->munge_copy = NULL;
00513       mythrow(nlopt_add_equality_constraint(o, myvfunc, d, tol));
00514       alloc_tmp();
00515     }
00516 
00517 
00518     void add_equality_mconstraint(mfunc mf, void *f_data,
00519                                   const Seldon::Vector<double> &tol)
00520     {
00521       myfunc_data *d = new myfunc_data;
00522       if (!d)
00523         throw Seldon::NoMemory("SeldonOpt::add_equality_mconstraint(func f, "
00524                                "void *f_data, double tol = 0)",
00525                                "Nlopt failed to allocate the"
00526                                " requested storage space.");
00527       d->o = this;
00528       d->mf = mf;
00529       d->f_data = f_data;
00530       d->f = NULL;
00531       d->vf = NULL;
00532       d->munge_destroy = d->munge_copy = NULL;
00533       mythrow(nlopt_add_equality_mconstraint(o, tol.GetSize(),
00534                                              mymfunc, d,
00535                                              tol.GetSize() == 0 ?
00536                                              NULL : tol.GetData()));
00537     }
00538 
00539 
00540     // For internal use in SWIG wrappers (see also above)
00541     void add_inequality_constraint(func f, void *f_data,
00542                                    nlopt_munge md, nlopt_munge mc,
00543                                    double tol=0)
00544     {
00545       myfunc_data *d = new myfunc_data;
00546       if (!d)
00547         throw Seldon::NoMemory("SeldonOpt::add_inequality_constraint(func f, "
00548                                "void *f_data, double tol = 0)",
00549                                "Nlopt failed to allocate the"
00550                                " requested storage space.");
00551       d->o = this;
00552       d->f = f;
00553       d->f_data = f_data;
00554       d->mf = NULL;
00555       d->vf = NULL;
00556       d->munge_destroy = md;
00557       d->munge_copy = mc;
00558       mythrow(nlopt_add_inequality_constraint(o, myfunc, d, tol));
00559     }
00560 
00561 
00562     void add_equality_constraint(func f, void *f_data,
00563                                  nlopt_munge md, nlopt_munge mc,
00564                                  double tol=0)
00565     {
00566       myfunc_data *d = new myfunc_data;
00567       if (!d)
00568         throw Seldon::NoMemory("SeldonOpt::add_inequality_constraint(func f, "
00569                                "void *f_data, double tol = 0)",
00570                                "Nlopt failed to allocate the"
00571                                " requested storage space.");
00572       d->o = this;
00573       d->f = f;
00574       d->f_data = f_data;
00575       d->mf = NULL;
00576       d->vf = NULL;
00577       d->munge_destroy = md;
00578       d->munge_copy = mc;
00579       mythrow(nlopt_add_equality_constraint(o, myfunc, d, tol));
00580     }
00581 
00582 
00583     void add_inequality_mconstraint(mfunc mf, void *f_data,
00584                                     nlopt_munge md, nlopt_munge mc,
00585                                     const Seldon::Vector<double> &tol)
00586     {
00587       myfunc_data *d = new myfunc_data;
00588       if (!d)
00589         throw Seldon::NoMemory("SeldonOpt::add_inequality_mconstraint(func f,"
00590                                " void *f_data, double tol = 0)",
00591                                "Nlopt failed to allocate the"
00592                                " requested storage space.");
00593       d->o = this;
00594       d->mf = mf;
00595       d->f_data = f_data;
00596       d->f = NULL;
00597       d->vf = NULL;
00598       d->munge_destroy = md; d->munge_copy = mc;
00599       mythrow(nlopt_add_inequality_mconstraint(o, tol.GetSize(),
00600                                                mymfunc, d,
00601                                                tol.GetSize() == 0
00602                                                ? NULL : tol.GetData()));
00603     }
00604 
00605 
00606     void add_equality_mconstraint(mfunc mf, void *f_data,
00607                                   nlopt_munge md, nlopt_munge mc,
00608                                   const Seldon::Vector<double> &tol)
00609     {
00610       myfunc_data *d = new myfunc_data;
00611       if (!d)
00612         throw Seldon::NoMemory("SeldonOpt::add_equality_mconstraint(mfunc mf,"
00613                                " void *f_data,"
00614                                "nlopt_munge md, nlopt_munge mc,"
00615                                "const Seldon::Vector<double> &tol)",
00616                                "Nlopt failed to allocate the"
00617                                " requested storage space.");
00618       d->o = this;
00619       d->mf = mf;
00620       d->f_data = f_data;
00621       d->f = NULL;
00622       d->vf = NULL;
00623       d->munge_destroy = md;
00624       d->munge_copy = mc;
00625       mythrow(nlopt_add_equality_mconstraint(o, tol.GetSize(), mymfunc,
00626                                              d, tol.GetSize() == 0
00627                                              ? NULL :
00628                                              tol.GetData()));
00629     }
00630 
00631 
00632 #define SELDON_NLOPT_GETSET_VEC(name)                                   \
00633     void set_##name(double val) {                                       \
00634       mythrow(nlopt_set_##name##1(o, val));                             \
00635     }                                                                   \
00636     void get_##name(Seldon::Vector<double> &v) const {                  \
00637       if (o && int(nlopt_get_dimension(o)) != v.GetSize())              \
00638         throw Seldon::WrongArgument("SeldonOpt::get_" #name "(Vector&)" \
00639                                     " const",                           \
00640                                     "Nlopt invalid argument.");         \
00641       mythrow(nlopt_get_##name(o, v.GetSize() == 0 ? NULL :             \
00642                                v.GetData()));                           \
00643     }                                                                   \
00644     Seldon::Vector<double> get_##name() const {                         \
00645       if (!o) throw                                                     \
00646                 Seldon::Error("SeldonOpt::get_" #name "() const",       \
00647                               "Uninitialized nlopt::SeldonOpt.");       \
00648       Seldon::Vector<double> v(nlopt_get_dimension(o));                 \
00649       get_##name(v);                                                    \
00650       return v;                                                         \
00651     }                                                                   \
00652     void set_##name(const Seldon::Vector<double> &v) {                  \
00653       if (o && int(nlopt_get_dimension(o)) != v.GetSize())              \
00654         throw Seldon::WrongArgument("SeldonOpt::get_" #name "(Vector&)" \
00655                                     " const",                           \
00656                                     "Nlopt invalid argument.");         \
00657       mythrow(nlopt_set_##name(o, v.GetSize() == 0 ?                    \
00658                                NULL : v.GetData()));                    \
00659     }
00660 
00661     SELDON_NLOPT_GETSET_VEC(lower_bounds)
00662     SELDON_NLOPT_GETSET_VEC(upper_bounds)
00663 
00664 
00665 #define SELDON_NLOPT_GETSET(T, name)                                    \
00666       T get_##name() const {                                            \
00667         if (!o) throw                                                   \
00668                   Seldon::Error("SeldonOpt::get_" #name "() const",     \
00669                                 "Uninitialized nlopt::SeldonOpt.");     \
00670         return nlopt_get_##name(o);                                     \
00671       }                                                                 \
00672       void set_##name(T name) {                                         \
00673         mythrow(nlopt_set_##name(o, name));                             \
00674       }
00675 
00676 
00677     SELDON_NLOPT_GETSET(double, stopval)
00678     SELDON_NLOPT_GETSET(double, ftol_rel)
00679     SELDON_NLOPT_GETSET(double, ftol_abs)
00680     SELDON_NLOPT_GETSET(double, xtol_rel)
00681     SELDON_NLOPT_GETSET_VEC(xtol_abs)
00682     SELDON_NLOPT_GETSET(int, maxeval)
00683     SELDON_NLOPT_GETSET(double, maxtime)
00684 
00685     SELDON_NLOPT_GETSET(int, force_stop)
00686 
00687 
00688     void force_stop()
00689     {
00690       set_force_stop(1);
00691     }
00692 
00693 
00694     void set_local_optimizer(const SeldonOpt &lo)
00695     {
00696       nlopt_result ret = nlopt_set_local_optimizer(o, lo.o);
00697       mythrow(ret);
00698     }
00699 
00700 
00701     SELDON_NLOPT_GETSET(unsigned, population)
00702     SELDON_NLOPT_GETSET_VEC(initial_step)
00703 
00704 
00705     void set_default_initial_step(const Seldon::Vector<double>& x)
00706     {
00707       nlopt_result ret
00708         = nlopt_set_default_initial_step(o, x.GetSize() == 0 ?
00709                                          NULL : x.GetData());
00710       mythrow(ret);
00711     }
00712 
00713 
00714     void get_initial_step(const Seldon::Vector<double> &x,
00715                           Seldon::Vector<double> &dx) const
00716     {
00717       if (o && (int(nlopt_get_dimension(o)) != x.GetSize()
00718                 || int(nlopt_get_dimension(o)) != dx.GetSize()))
00719         throw Seldon::WrongArgument("SeldonOpt::get_initial_step("
00720                                     "Vector<double>& x, double& dx)",
00721                                     "Dimension mismatch.");
00722       nlopt_result ret = nlopt_get_initial_step(o, x.GetSize() == 0 ?
00723                                                 NULL : x.GetData(),
00724                                                 dx.GetSize() == 0 ?
00725                                                 NULL : dx.GetData());
00726       mythrow(ret);
00727     }
00728 
00729 
00730     Seldon::Vector<double> get_initial_step_(const Seldon::Vector<double>& x)
00731     const
00732     {
00733       if (!o)
00734         throw Seldon::Error("SeldonOpt::get_initial_step_"
00735                             "(const Seldon::Vector<double>& x)",
00736                             "Uninitialized nlopt::SeldonOpt.");
00737       Seldon::Vector<double> v(nlopt_get_dimension(o));
00738       get_initial_step(x, v);
00739       return v;
00740     }
00741   };
00742 
00743 
00744 #undef SELDON_NLOPT_GETSET
00745 #undef SELDON_NLOPT_GETSET_VEC
00746 
00747 
00748 }
00749 
00750 #endif