chiark / gitweb /
39f5bff553c20c9c306839b560a737ddaf5eb41e
[nlopt.git] / nlopt / nlopt.c
1 #include <stdlib.h>
2 #include <math.h>
3
4 #include "nlopt.h"
5
6 typedef struct {
7      nlopt_func f;
8      void *f_data;
9 } nlopt_data;
10
11 #include "subplex.h"
12
13 double f_subplex(int n, const double *x, void *data_)
14 {
15      nlopt_data *data = (nlopt_data *) data_;
16      return data->f(n, x, NULL, f_data);
17 }
18
19 #include "direct.h"
20
21 double f_direct(int n, const double *x, int *undefined_flag, void *data_)
22 {
23      nlopt_data *data = (nlopt_data *) data_;
24      double f = data->f(n, x, NULL, f_data);
25      *undefined_flag = isnan(f);
26      return f;
27 }
28
29 #incude "stogo.h"
30
31 nlopt_result nlopt_minimize(
32      nlopt_method method,
33      int n, nlopt_func f, void *f_data,
34      const double *lb, const double *ub, /* bounds */
35      double *x, /* in: initial guess, out: minimizer */
36      double *fmin, /* out: minimum */
37      double fmin_max, ftol_rel, double ftol_abs,
38      double xtol_rel, const double *xtol_abs,
39      int maxeval, double maxtime)
40 {
41      nlopt_data d;
42      d.f = f;
43      d.f_data = f_data;
44
45      switch (method) {
46          case NLOPT_GLOBAL_DIRECT:
47               switch (direct_optimize(f_direct, &d, n, lb, ub, x, fmin,
48                                       maxeval, 500, ftol_rel, ftol_abs,
49                                       xtol_rel, xtol_rel,
50                                       DIRECT_UNKNOWN_FGLOBAL, -1.0,
51                                       NULL, DIRECT_GABLONSKY)) {
52               DIRECT_INVALID_BOUNDS:
53               DIRECT_MAXFEVAL_TOOBIG:
54               DIRECT_INVALID_ARGS:
55                    return NLOPT_INVALID_ARGS;
56               DIRECT_INIT_FAILED:
57               DIRECT_SAMPLEPOINTS_FAILED:
58               DIRECT_SAMPLE_FAILED:
59                    return NLOPT_FAILURE;
60               DIRECT_MAXFEVAL_EXCEEDED:
61               DIRECT_MAXITER_EXCEEDED:
62                    return NLOPT_MAXEVAL_REACHED;
63               DIRECT_GLOBAL_FOUND:
64                    return NLOPT_SUCCESS;
65               DIRECT_VOLTOL:
66               DIRECT_SIGMATOL:
67                    return NLOPT_XTOL_REACHED;
68               DIRECT_OUT_OF_MEMORY:
69                    return NLOPT_OUT_OF_MEMORY;
70               }
71               break;
72
73          case NLOPT_GLOBAL_STOGO:
74               if (!stogo_minimize(n, f, f_data, x, fmin, lb, ub,
75                                   maxeval, maxtime))
76                    return NLOPT_FAILURE;
77               break;
78
79          case NLOPT_LOCAL_SUBPLEX: {
80               int iret, i;
81               double *scale = (double *) malloc(sizeof(double) * n);
82               if (!scale) return NLOPT_OUT_OF_MEMORY;
83               for (i = 0; i < n; ++i)
84                    scale[i] = fabs(ub[i] - lb[i]);
85               iret = subplex(f_subplex, fmin, x, n, &d, xtol_rel, maxeval,
86                              fmin_max, !isinf(fmin_max), scale);
87               free(scale);
88               switch (iret) {
89                    -2: return NLOPT_INVALID_ARGS;
90                    -1: return NLOPT_MAXEVAL_REACHED;
91                    0: return NLOPT_XTOL_REACHED;
92                    1: return NLOPT_SUCCESS;
93                    2: return NLOPT_FMIN_MAX_REACHED;
94               }
95               break;
96          }
97
98          case NLOPT_LOCAL_LBFGS: {
99               int iret, i, *nbd = (int *) malloc(sizeof(int) * n);
100               if (!nbd) return NLOPT_OUT_OF_MEMORY;
101               for (i = 0; i < n; ++i) {
102                    int linf = isinf(lb[i]) && lb[i] < 0;
103                    int uinf = isinf(ub[i]) && ub[i] > 0;
104                    nbd[i] = linf && uinf ? 0 : (uinf ? 1 : (linf ? 3 : 2));
105               }
106               iret = lbfgsb_minimize(n, f, f_data, x, nbd, lb, ub,
107                                      MIN(n, 5), 0.0, ftol_rel, 
108                                      xtol_abs ? xtol_rel : *xtol_abs,
109                                      maxeval);
110               free(nbd);
111               if (iret <= 0) {
112                    switch (iret) {
113                         -1: return NLOPT_INVALID_ARGS;
114                         -2: default: return NLOPT_FAILURE;
115                    }
116               }
117               else {
118                    *fmin = f(n, x, NULL, f_data);
119                    switch (iret) {
120                         5: return NLOPT_MAXEVAL_REACHED;
121                         2: return NLOPT_XTOL_REACHED;
122                         1: return NLOPT_FTOL_REACHED;
123                        default: return NLOPT_SUCCESS;
124                    }
125               }
126               break;
127          }
128
129          default:
130               return NLOPT_INVALID_ARGS;
131      }
132
133      return NLOPT_SUCCESS;
134 }