/// <summary> /// Originally described at https://github.com/stevengj/nlopt/blob/master/src/api/optimize.c#L804 /// </summary> private static void pre_max(int n, double[] x, int x_offset, double[] v, int v_offset, double[] vpre, int vpre_offset, object[] data, int data_offset) { f_max_data d = (f_max_data)data[data_offset]; d.pre(n, x, x_offset, v, v_offset, vpre, vpre_offset, d.f_data, data_offset); for (int i = 0; i < n; ++i) { vpre[i] = -vpre[i]; } }
/// <summary> /// Wrapper for maximizing: just flip the sign of f and grad. /// Originally described at https://github.com/stevengj/nlopt/blob/master/src/api/optimize.c#L792 /// </summary> private static double f_max(int n, double[] x, int x_offset, double[] grad, int grad_offset, object[] data, int data_offset) { f_max_data d = (f_max_data)data[data_offset]; double val = d.f(n, x, x_offset, grad, grad_offset, d.f_data, data_offset); if (grad != null) { for (int i = 0; i < n; ++i) { grad[i] = -grad[i]; } } return(-val); }
/// <summary> /// Originally described at https://github.com/stevengj/nlopt/blob/master/src/api/optimize.c#L813 /// </summary> internal static nlopt_result nlopt_optimize(nlopt_opt opt, double[] x, int x_offset, ref double opt_f) { nlopt_func f; object[] f_data; nlopt_precond pre; f_max_data fmd = new f_max_data(); bool maximize; nlopt_result ret; NLoptOptions.nlopt_unset_errmsg(opt); if (opt == null /*|| opt_f == null*/ || opt.f == null) { NLoptApi.RETURN_ERR(nlopt_result.NLOPT_INVALID_ARGS, opt, "NULL args to nlopt_optimize"); } f = opt.f; f_data = opt.f_data; pre = opt.pre; // for maximizing, just minimize the f_max wrapper, which flips the sign of everything if ((maximize = opt.maximize)) { fmd.f = f; fmd.f_data = f_data; fmd.pre = pre; opt.f = f_max; opt.f_data = new object[] { fmd }; opt.f_data_offset = 0; if (opt.pre != null) { opt.pre = pre_max; } opt.stopval = -opt.stopval; opt.maximize = false; } // possibly eliminate lb == ub dimensions for some algorithms { nlopt_opt elim_opt = opt; if (elimdim_wrapcheck(opt)) { elim_opt = elimdim_create(opt); if (elim_opt == null) { NLoptOptions.nlopt_set_errmsg(opt, "failure allocating elim_opt"); ret = nlopt_result.NLOPT_OUT_OF_MEMORY; goto done; } elimdim_shrink(opt.n, x, x_offset, opt.lb, opt.ub); } ret = nlopt_optimize_(elim_opt, x, x_offset, ref opt_f); if (elim_opt != opt) { elimdim_destroy(elim_opt); elimdim_expand(opt.n, x, x_offset, opt.lb, opt.ub); } } done: if (maximize) // restore original signs { opt.maximize = maximize; opt.stopval = -opt.stopval; opt.f = f; opt.f_data = f_data; opt.pre = pre; opt_f = -opt_f; } return(ret); }