using System; using System.Runtime.InteropServices; namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression { public static class NLOpt { public delegate double nlopt_func(uint n, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] x, // double* [In][Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] gradient, /* double* NULL if not needed */ IntPtr func_data); public delegate IntPtr nlopt_mfunc(uint m, [Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] result, uint n, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] double[] x, ref double[] gradient, /* NULL if not needed */ // TODO: we need manual marshalling here (array is of length n*m) is stored in ∂c_i/∂x_j = grad[i*n + j] IntPtr func_data); /* A preconditioner, which preconditions v at x to return vpre. (The meaning of "preconditioning" is algorithm-dependent.) */ public delegate void nlopt_precond(uint n, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] x, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] v, [In][Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] vpre, IntPtr data); public enum nlopt_algorithm { /* Naming conventions: NLOPT_{G/L}{D/N}_* = global/local derivative/no-derivative optimization, respectively *_RAND algorithms involve some randomization. *_NOSCAL algorithms are *not* scaled to a unit hypercube (i.e. they are sensitive to the units of x) */ NLOPT_GN_DIRECT = 0, NLOPT_GN_DIRECT_L, NLOPT_GN_DIRECT_L_RAND, NLOPT_GN_DIRECT_NOSCAL, NLOPT_GN_DIRECT_L_NOSCAL, NLOPT_GN_DIRECT_L_RAND_NOSCAL, NLOPT_GN_ORIG_DIRECT, NLOPT_GN_ORIG_DIRECT_L, NLOPT_GD_STOGO, NLOPT_GD_STOGO_RAND, NLOPT_LD_LBFGS_NOCEDAL, NLOPT_LD_LBFGS, NLOPT_LN_PRAXIS, NLOPT_LD_VAR1, NLOPT_LD_VAR2, NLOPT_LD_TNEWTON, NLOPT_LD_TNEWTON_RESTART, NLOPT_LD_TNEWTON_PRECOND, NLOPT_LD_TNEWTON_PRECOND_RESTART, NLOPT_GN_CRS2_LM, NLOPT_GN_MLSL, NLOPT_GD_MLSL, NLOPT_GN_MLSL_LDS, NLOPT_GD_MLSL_LDS, NLOPT_LD_MMA, NLOPT_LN_COBYLA, NLOPT_LN_NEWUOA, NLOPT_LN_NEWUOA_BOUND, NLOPT_LN_NELDERMEAD, NLOPT_LN_SBPLX, NLOPT_LN_AUGLAG, NLOPT_LD_AUGLAG, NLOPT_LN_AUGLAG_EQ, NLOPT_LD_AUGLAG_EQ, NLOPT_LN_BOBYQA, NLOPT_GN_ISRES, /* new variants that require local_optimizer to be set, not with older constants for backwards compatibility */ NLOPT_AUGLAG, NLOPT_AUGLAG_EQ, NLOPT_G_MLSL, NLOPT_G_MLSL_LDS, NLOPT_LD_SLSQP, NLOPT_LD_CCSAQ, NLOPT_GN_ESCH, NLOPT_GN_AGS, NLOPT_NUM_ALGORITHMS /* not an algorithm, just the number of them */ }; public enum nlopt_result { NLOPT_FAILURE = -1, /* generic failure code */ NLOPT_INVALID_ARGS = -2, NLOPT_OUT_OF_MEMORY = -3, NLOPT_ROUNDOFF_LIMITED = -4, NLOPT_FORCED_STOP = -5, NLOPT_SUCCESS = 1, /* generic success code */ NLOPT_STOPVAL_REACHED = 2, NLOPT_FTOL_REACHED = 3, NLOPT_XTOL_REACHED = 4, NLOPT_MAXEVAL_REACHED = 5, NLOPT_MAXTIME_REACHED = 6 }; #region x86 [DllImport("nlopt_x86.dll", EntryPoint = "nlopt_version", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr nlopt_version_x86(ref int major, ref int minor, ref int bugfix); #endregion #region x64 [DllImport("nlopt_x64.dll", EntryPoint = "nlopt_version", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr nlopt_version_x64(ref int major, ref int minor, ref int bugfix); /*************************** OBJECT-ORIENTED API **************************/ /* The style here is that we create an nlopt_opt "object" (an opaque pointer), then set various optimization parameters, and then execute the algorithm. In this way, we can add more and more optimization parameters (including algorithm-specific ones) without breaking backwards compatibility, having functions with zillions of parameters, or relying non-reentrantly on global variables.*/ /* the only immutable parameters of an optimization are the algorithm and the dimension n of the problem, since changing either of these could have side-effects on lots of other parameters */ [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr nlopt_create(nlopt_algorithm algorithm, uint n); // returns nlopt_opt [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr nlopt_destroy(IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr /*nlopt_opt*/ nlopt_copy([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_optimize(IntPtr nlopt_opt, [In][Out] double[] x, ref double opt_f); // opt_f is optimal value [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_min_objective(IntPtr nlopt_opt, [MarshalAs(UnmanagedType.FunctionPtr)] nlopt_func f, IntPtr f_data); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_max_objective(IntPtr nlopt_opt, nlopt_func f, IntPtr f_data); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_precond_min_objective(IntPtr nlopt_opt, nlopt_func f, nlopt_precond pre, IntPtr f_data); // only used by CCSAQ optimizer in NLOpt version 2.6.1 [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_precond_max_objective(IntPtr nlopt_opt, nlopt_func f, nlopt_precond pre, IntPtr f_data); // only used by CCSAQ optimizer in NLOpt version 2.6.1 [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_algorithm nlopt_get_algorithm([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern uint nlopt_get_dimension([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern string nlopt_get_errmsg(IntPtr nlopt_opt); /* constraints: */ [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_lower_bounds(IntPtr nlopt_opt, [In] double[] lb); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_lower_bounds1(IntPtr nlopt_opt, double lb); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_lower_bound(IntPtr nlopt_opt, int i, double lb); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_get_lower_bounds([In] IntPtr nlopt_opt, IntPtr lb); // actually: double* TODO: manual marshalling [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_upper_bounds(IntPtr nlopt_opt, [In] double[] ub); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_upper_bounds1(IntPtr nlopt_opt, double ub); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_upper_bound(IntPtr nlopt_opt, int i, double ub); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_get_upper_bounds([In] IntPtr nlopt_opt, IntPtr ub); // actually: double* TODO: manual marshalling [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_remove_inequality_constraints(IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_inequality_constraint(IntPtr nlopt_opt, nlopt_func fc, IntPtr fc_data, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_precond_inequality_constraint(IntPtr nlopt_opt, nlopt_func fc, nlopt_precond pre, IntPtr fc_data, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_inequality_mconstraint(IntPtr nlopt_opt, uint m, nlopt_mfunc fc, IntPtr fc_data, ref double[] tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_remove_equality_constraints(IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_equality_constraint(IntPtr nlopt_opt, nlopt_func h, IntPtr h_data, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_precond_equality_constraint(IntPtr nlopt_opt, nlopt_func h, nlopt_precond pre, IntPtr h_data, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_add_equality_mconstraint(IntPtr nlopt_opt, uint m, nlopt_mfunc h, IntPtr h_data, ref double[] tol); /* stopping criteria: */ [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_stopval(IntPtr nlopt_opt, double stopval); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double nlopt_get_stopval([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_ftol_rel(IntPtr nlopt_opt, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double nlopt_get_ftol_rel([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_ftol_abs(IntPtr nlopt_opt, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double nlopt_get_ftol_abs([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_xtol_rel(IntPtr nlopt_opt, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double nlopt_get_xtol_rel([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_xtol_abs1(IntPtr nlopt_opt, double tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_xtol_abs(IntPtr nlopt_opt, [In] double[] tol); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_get_xtol_abs([In] IntPtr nlopt_opt, IntPtr tol); // actually: double* TODO: manual marshalling [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_maxeval(IntPtr nlopt_opt, int maxeval); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int nlopt_get_maxeval([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int nlopt_get_numevals([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_maxtime(IntPtr nlopt_opt, double maxtime); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double nlopt_get_maxtime([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_force_stop(IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_force_stop(IntPtr nlopt_opt, int val); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int nlopt_get_force_stop([In] IntPtr nlopt_opt); /* more algorithm-specific parameters */ [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_local_optimizer(IntPtr nlopt_opt, [In] IntPtr local_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_population(IntPtr nlopt_opt, uint pop); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern uint nlopt_get_population([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_vector_storage(IntPtr nlopt_opt, uint dim); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern uint nlopt_get_vector_storage([In] IntPtr nlopt_opt); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_default_initial_step(IntPtr nlopt_opt, [In] double[] x); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_initial_step(IntPtr nlopt_opt, [In] double[] dx); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_set_initial_step1(IntPtr nlopt_opt, double dx); [DllImport("nlopt_x64.dll", CallingConvention = CallingConvention.Cdecl)] public static extern nlopt_result nlopt_get_initial_step([In] IntPtr nlopt_opt, IntPtr x, // actually: double* TODO: manual marshalling IntPtr dx // actually: double* TODO: manual marshalling ); #endregion #region dispatch x86/x64 public static void nlopt_version(out int major, out int minor, out int bugfix) { major = 0; minor = 0; bugfix = 0; if (Environment.Is64BitProcess) { nlopt_version_x64(ref major, ref minor, ref bugfix); } else { nlopt_version_x86(ref major, ref minor, ref bugfix); } } #endregion } }