From f0e008cc2919382563a7ab13b2aae13b26e6dbd6 Mon Sep 17 00:00:00 2001 From: Gleb Belov Date: Fri, 10 Nov 2023 21:30:22 +1100 Subject: [PATCH] NL Writer C API: NLHeader_C #30 Extract NLHeader definition into C structs --- nl-writer2/CMakeLists.txt | 1 + nl-writer2/examples/c/nlsol_ex_c_nl.c | 127 +++++ nl-writer2/include/api/c/nl-feeder2-c-impl.h | 454 +++++++++++++++++- nl-writer2/include/api/c/nl-feeder2-c.h | 432 ++++++++++++++++- .../include/api/c/nl-writer2-misc-c-impl.h | 6 +- nl-writer2/include/api/c/nlsol-c.h | 2 +- .../include/api/c/sol-handler2-c-impl.h | 5 +- nl-writer2/include/mp/nl-feeder2.h | 4 +- nl-writer2/include/mp/nl-header-c.h | 339 +++++++++++++ nl-writer2/include/mp/nl-header.h | 300 ++---------- nl-writer2/include/mp/nl-writer2.hpp | 2 +- nl-writer2/src/c_api.cc | 14 +- nl-writer2/src/nl-writer2.cc | 10 + 13 files changed, 1432 insertions(+), 264 deletions(-) create mode 100644 nl-writer2/include/mp/nl-header-c.h diff --git a/nl-writer2/CMakeLists.txt b/nl-writer2/CMakeLists.txt index 3912446ff..d180964ca 100644 --- a/nl-writer2/CMakeLists.txt +++ b/nl-writer2/CMakeLists.txt @@ -23,6 +23,7 @@ set(NLW2_LIB_FILES ${NLW2_SRC_PATH}/dtoa.c) set(NLW2_INC_FILES ${NLW2_INCLUDE_PATH}/mp/nlsol.h + ${NLW2_INCLUDE_PATH}/mp/nl-header-c.h ${NLW2_INCLUDE_PATH}/mp/nl-header.h ${NLW2_INCLUDE_PATH}/mp/nl-feeder2.h ${NLW2_INCLUDE_PATH}/mp/nl-writer2.h diff --git a/nl-writer2/examples/c/nlsol_ex_c_nl.c b/nl-writer2/examples/c/nlsol_ex_c_nl.c index 34edaae0f..6dca434c8 100644 --- a/nl-writer2/examples/c/nlsol_ex_c_nl.c +++ b/nl-writer2/examples/c/nlsol_ex_c_nl.c @@ -2,6 +2,131 @@ #include "nlsol_ex_c_nl.h" +NLHeader_C CAPI_ex_Header(void* pex_void) { + CAPIExample* pex = (CAPIExample*)pex_void; + NLHeader_C hdr; + + hdr.pi.num_vars = pex->n_var; + hdr.pi.num_algebraic_cons = pex->n_con; + hdr.pi.num_objs = pex->n_obj; + hdr.pi.num_ranges = 0; + hdr.pi.num_eqns = 0; + hdr.pi.num_logical_cons = 0; + + // Setting some other common data (more may be needed) + + /** Total number of nonlinear constraints. */ + hdr.pi.num_nl_cons = 0; + hdr.pi.num_nl_objs = 0; + hdr.pi.num_compl_conds = 0; + hdr.pi.num_nl_compl_conds = 0; + hdr.pi.num_compl_dbl_ineqs = 0; + hdr.pi.num_compl_vars_with_nz_lb = 0; + + /** Number of nonlinear network constraints. */ + hdr.pi.num_nl_net_cons = 0; + hdr.pi.num_linear_net_cons = 0; + + /** + Number of nonlinear variables in constraints including nonlinear + variables in both constraints and objectives. + */ + hdr.pi.num_nl_vars_in_cons = 0; + + /** + Number of nonlinear variables in objectives including nonlinear + variables in both constraints and objectives. + */ + hdr.pi.num_nl_vars_in_objs = 0; + + /** Number of nonlinear variables in both constraints and objectives. */ + hdr.pi.num_nl_vars_in_both = 0; + + // Miscellaneous + // ------------- + + /** Number of linear network variables (arcs). */ + hdr.pi.num_linear_net_vars = 0; + + /** Number of functions. */ + hdr.pi.num_funcs = 0; + + // Information about discrete variables + // ------------------------------------ + + /** Number of linear binary variables. */ + hdr.pi.num_linear_binary_vars = 0; + + /** Number of linear non-binary integer variables. */ + hdr.pi.num_linear_integer_vars = pex->n_var_int; + + /** + Number of integer nonlinear variables in both constraints and objectives. + */ + hdr.pi.num_nl_integer_vars_in_both = 0; + + /** Number of integer nonlinear variables just in constraints. */ + hdr.pi.num_nl_integer_vars_in_cons = 0; + + /** Number of integer nonlinear variables just in objectives. */ + hdr.pi.num_nl_integer_vars_in_objs = 0; + + // Information about nonzeros + // -------------------------- + + /** Number of nonzeros in constraints' Jacobian. */ + hdr.pi.num_con_nonzeros = pex->n_con_nz; + + /** Number of nonzeros in all objective gradients. */ + hdr.pi.num_obj_nonzeros = pex->n_obj_nz; + + // Information about names + // ----------------------- + + /** Length of longest con/obj name if names are available. */ + hdr.pi.max_con_name_len = 0; // no need to set + + /** Length of longest variable name if names are available. */ + hdr.pi.max_var_name_len = 0; // no need to set + + // Information about common expressions + // ------------------------------------ + + /** + Number of common expressions that appear both in constraints + and objectives. + */ + hdr.pi.num_common_exprs_in_both = 0; + + /** + Number of common expressions that appear in multiple constraints + and don't appear in objectives. + */ + hdr.pi.num_common_exprs_in_cons = 0; + + /** + Number of common expressions that appear in multiple objectives + and don't appear in constraints. + */ + hdr.pi.num_common_exprs_in_objs = 0; + + /** + Number of common expressions that only appear in a single constraint + and don't appear in objectives. + */ + hdr.pi.num_common_exprs_in_single_cons = 0; + + /** + Number of common expressions that only appear in a single objective + and don't appear in constraints. + */ + hdr.pi.num_common_exprs_in_single_objs = 0; + + hdr.nli.prob_name = "c_api_example_model"; + + return hdr; +} + NLFeeder2_C MakeNLFeeder2_C( CAPIExample* pex, int binary) { NLFeeder2_C result; @@ -9,6 +134,8 @@ NLFeeder2_C MakeNLFeeder2_C( result.p_user_data_ = pex; pex->binary_nl = binary; + result.Header = CAPI_ex_Header; + return result; } diff --git a/nl-writer2/include/api/c/nl-feeder2-c-impl.h b/nl-writer2/include/api/c/nl-feeder2-c-impl.h index 51f5bcc47..f98dd050a 100644 --- a/nl-writer2/include/api/c/nl-feeder2-c-impl.h +++ b/nl-writer2/include/api/c/nl-feeder2-c-impl.h @@ -19,10 +19,460 @@ class NLFeeder2_C_Impl public: /// Construct NLFeeder2_C_Impl(NLFeeder2_C* pnlf2) - : p_nlf2_c_(pnlf2) { } + : nlf2_c_(*pnlf2) { } + + ///////////////////// 1. NL HEADER AND OPTIONS ///////////////// + /** Provide NLHeader. + * + * This method is called first. + * + * NLHeader summarizes the model and provides some + * technical parameters, + * such as text/binary NL format. */ + NLHeader Header() { + auto h_c = NLF().Header(NLF().p_user_data_); + NLHeader hdr; + *(ProblemInfo_C*)(&hdr) = h_c.pi; + *(NLInfo_C*)(&hdr) = h_c.nli; + + return hdr; + } + + /// NL comments? + bool WantNLComments() const { return false; } + + /// The maximum number of significant digits written. + /// The default value requests full precision, which + /// might be the shortest representation that, when + /// converted to binary and properly rounded, will + /// give exactly the binary value stored in the computer. + int OutputPrecision() const { return 0; } + + /// Write bounds first? + /// The default is yes in AMPL, controlled by + /// (the value of option nl_permute) & 32 + /// (the bit is 0 for yes). + /// Changing this option is deprecated, see + /// https://netlib.org/ampl/changes. + bool WantBoundsFirst() const { return true; } + + /// Want Jacobian column sizes? + /// Required by some nonlinear solvers. + /// Options: 0 - none, 1 - cumulative, + /// 2 - non-cumulative. + /// This option controls how ColSizeWriter + /// writes the provided sizes (which should be + /// non-cumulative). + int WantColumnSizes() const { return 1; } + + + ///////////////////// 2. OBJECTIVES ///////////////////// + /** Description for objective function \a i + * (\a i in 0..num_objs-1). + * With WantNLComments()==true, this is + * written to text-format NL as a comment. */ + const char* ObjDescription(int i) { return ""; } + + /** Provide type of objective \a i. + * 0 - minimization; + * 1 - maximization. */ + int ObjType(int i) { return {}; } + + /** Feed gradient for objective \a i. + * Should include entries for all potentially + * nonzero elements (sparsity pattern). + * + * Implementation skeleton: + * if (obj_grad[i].size()) { + * auto sv = svw.MakeVectorWriter(obj_grad[i].size()); + * for (size_t j=0; j + void FeedObjGradient(int i, ObjGradWriterFactory& ) { } + + /** Feed nonlinear expression of objective \a i. + * + * Implementation example: + * ew.EPut(obj_root_expr[i]); + * + * Details of ObjExprWriter: see NLWriter2. */ + template + void FeedObjExpression(int i, ObjExprWriter& ) { } + + + ///////////////////// 3. DEFINED VARIABLES ///////////////////// + /** Defined variables. + * + * Classical NL writes first the defined variables + * which are used in several places (constraints and/or + * objectives). Defined variables used in a single place + * (1 constraint, or 1 objective), are written + * just before the expression tree of their usage. + * + * For most solvers, this requirement can be ignored + * and this method can return all defined variables + * in the first group (for \a i=0). + * + * The method is guaranteed to be called in the following order: + * 1. For \a i=0; + * 2. For \a i>0, increasing, before constraint \a (i-1)'s expression; + * 3. For \a i<0, decreasing, before objective \a (-i-1)'s expression. + * + * @param i: + * - For \a i=0, feed a sequence of defined variables + * used in several constraints and/or objectives. + * - For \a i>0, feed the defined variables used solely + * in constraint \a i-1. + * - For \a i<0, feed the defined variables used solely + * in objective \a -i-1. + * + * Implementation skeleton: + * // dvar_index in num_vars..num_vars+num_defvars-1. + * for (int dvar_index: dvar_indexes[i]) { + * auto dv = dvw.StartDefVar(dvar_index, lin_nnz, name_or_comment); + * /////////// Write the linear part: + * auto linw = dv.GetLinExprWriter(); + * for (int i=0; i + void FeedDefinedVariables(int i, DefVarWriterFactory& ) { } + + + ///////////////////// 4. VARIABLE BOUNDS ///////////////////// + /** Bounds for variables (except defined variables). + * Use +-inf for missing lower and/or upper bounds. + * Note that variable type is given by variable ordering, + * see NLHeader. + * + * Implementation skeleton: + * for (int i = 0; i < hdr.num_vars; i++) + * vbw.WriteLbUb(lb[i], ub[i]); + */ + template + void FeedVarBounds(VarBoundsWriter& ) { } + + + ///////////////// 5. CONSTRAINT BOUNDS & COMPLEMENTARITY /////// + /// \rst + /// Algebraic constraint bounds (for a single constraint): + /// either range (lb, ub), + /// or complementarity info (k, cvar), when k>0. + /// + /// For a complementarity constraint to hold, if cvar is at + /// its lower bound, then body >= 0; if cvar is at its upper + /// bound, then body <= 0; + /// and if cvar is strictly between its bounds, then body = 0. + /// The integer k in a complementarity constraint line indicates + /// which bounds on cvar are finite: 1 and 3 imply a finite + /// lower bound; 2 and 3 imply a finite upper bound; 0 (which + /// should not occur) would imply no finite bounds, i.e., + /// body = 0 must always hold. + /// + /// Example: + /// + /// .. code-block:: ampl + /// + /// ampl: var x; var y; var z; + /// ampl: s.t. Compl1: x+y >= 3 complements x-z <= 15; + /// ampl: s.t. Compl2: -2 <= 2*y+3*z <= 13 complements 6*z-2*x; + /// ampl: expand; + /// subject to Compl1: + /// 3 <= x + y + /// complements + /// x - z <= 15; + /// + /// subject to Compl2: + /// -2 <= 2*y + 3*z <= 13 + /// complements + /// -2*x + 6*z; + /// + /// ampl: solexpand; + /// Nonsquare complementarity system: + /// 4 complementarities including 2 equations + /// 5 variables + /// subject to Compl1.L: + /// x + y + Compl1$cvar = 0; + /// + /// subject to Compl1.R: + /// -15 + x - z <= 0 + /// complements + /// Compl1$cvar <= -3; + /// + /// subject to Compl2.L: + /// 2*y + 3*z - Compl2$cvar = 0; + /// + /// subject to Compl2.R: + /// -2*x + 6*z + /// complements + /// -2 <= Compl2$cvar <= 13; + /// + /// \endrst + struct AlgConRange { + double L{}, U{}; + int k{0}, cvar{0}; // k>0 means complementarity to cvar + }; + + /** Bounds/complementarity for all algebraic constraints + * (\a num_algebraic_cons). + * + * Implementation skeleton: + * for (int j=0; j negInfinity) + * bnd.k = 1; + * if (vub[j] < Infinity) + * bnd.k |= 2; + * assert(bnd.k); + * bnd.cvar = j; + * } else { + * bnd.L = clb[j]; + * bnd.U = cub[j]; + * } + * cbw.WriteAlgConRange(bnd); + * } + */ + template + void FeedConBounds(ConBoundsWriter& ) { } + + + ///////////////////// 6. CONSTRAINTS ///////////////////// + /** Description of constraint \a i + * (\a i in 0..num_algebraic_cons+num_logical_cons-1). + * With WantNLComments()==true, this is + * written to text-format NL as a comment. */ + const char* ConDescription(int ) { return ""; } + + /** Feed the linear part of algebraic constraint \a i. + * For smooth solvers, should contain entries for all + * potential nonzeros (Jacobian sparsity pattern). + * + * Implementation skeleton: + * if (con_grad[i].size()) { + * auto sv = svw.MakeVectorWriter(con_grad[i].size()); + * for (size_t j=0; j + void FeedLinearConExpr(int i, ConLinearExprWriterFactory& ) { } + + /** Feed nonlinear expression of constraint \a i. + * Algebraic constraints (num_algebraic_cons) + * come before logical (num_logical_cons). + * For linear constraints, the expression should be + * constant 0. + */ + template + void FeedConExpression(int i, ConExprWriter& ) { } + + + ///////////////////// 7. EXPRESSIONS ///////////////////// + /** Feed native expression. + * This method is recursively called from NLWriter, + * when Feeder uses ExprWriter::EPut(). + * Feeder should not call this method itself. + * + * Details of ExprWriter: see NLWriter2. + */ + template + void FeedExpr(Expr e, ExprWriter& ) { } + + + ///////////////////// 8. PL-SOS CONSTRAINTS //////////// + /** + * The below feature is for AMPL's internal + * linearization of piecewise-linear functions. + * For user-definable SOS constraints, use suffixes + * .sosno/.ref. + * + * The below is a feeder interface + * for .sos/.sosref suffixes. + * The feeder can provide 3 sparse vectors: + * - .sos for variables: + * Each nonzero value defines SOS group number. + * Negative means SOS Type 2, positive - SOS Type 1. + * - .sos for constraints: + * Each nonzero value denotes a constraint used in a + * linearization of an SOS. The constraint can be deleted + * by the solver driver if using solver's SOS. + * - .sosref for variables: + * SOS weights. Variables participating in an SOS having + * zero weights are involved in linearization and can be + * deleted if the solver accepts SOS natively. + * + * Implementation: + * auto sosv = plsos.StartSOSVars(nvsos); + * for (int i=0; insosref); + * .... + */ + template + void FeedPLSOS(PLSOSWriter& ) { } + + + ///////////////////// 9. FUNCTIONS ///////////////////// + /** Function definition. */ + struct FuncDef { + const char* Name() { return ""; } + int NumArgs() { return 0; } + /** Function type. + * 0 - numeric; + * 1 - symbolic. */ + int Type() { return 0; } + }; + + /** Provide definition + * of function \a i, i=0..num_funcs-1. */ + FuncDef Function(int i) { return {}; } + + + ///////////////////// 10. RANDOM VARIABLES ///////////////////// + /// Random variables. + /// Undocumented feature. SNL2006. + /// Example: + /// var z >= 0; + /// let z.stage := 1; + /// var x{0..1, 0..1} random := Uniform(0,2); + /// for {i in 0..1, j in 0..1} {let x[i,j].stage := 1;}; + /// display z.stage, x.stage; + /// c: z * sum{i in 0..1, j in 0..1} x[i,j] <= 3 + Sample(Uniform(0,2)); + /// + /// Feed random variables. + /// Indexes: num_vars+num_common_exprs + /// .. num_vars+num_common_exprs+num_rand_vars-1. + /// + /// Implementation skeleton: + /// for(j = num_vars+num_common_exprs; + /// j < num_vars+num_common_exprs+num_rand_vars; j++) { + /// auto ew = rvw.StartRandVar(j, rand_var_comment(j)); + /// ew.EPut(rand_var_root_expr(j)); + /// } + template + void FeedRandomVariables(RandVarWriterFactory& ) { } + + + ///////////////////// 11. COLUMN SIZES ///////////////////// + + /** Jacobian column sizes. + * Should feed LP column sizes + * for all but the last variable. + * + * Implementation skeleton: + * if (WantColumnSizes()) + * for (int i=0; i < num_vars+num_rand_vars-1; ++i) + * csw.Write(col_size[i]); + */ + template + void FeedColumnSizes(ColSizeWriter& ) { } + + + ///////////////////// 12. INITIAL GUESSES ///////////////////// + /** Initial primal guesses. + * + * Implementation: + * if (ini_guess.size()) { + * auto ig = igw.MakeVectorWriter(ini_guess.size()); + * for (size_t i=0; i + void FeedInitialGuesses(IGWriter& ) { } + + /** Initial dual guesses. */ + template + void FeedInitialDualGuesses(IDGWriter& ) { } + + + ///////////////////// 13. SUFFIXES ///////////////////// + /** Feed suffixes. + * + * For constraints, assume ordering: + * first algebraic, then logical. + * + * Implementation: + * while (....) { + * auto sw = swf.StartIntSuffix( // or ...DblSuffix + * suf_name, kind, n_nonzeros); + * for (int i=0; i + void FeedSuffixes(SuffixWriterFactory& ) { } + + + //////////////////// 14. ROW/COLUMN NAMES ETC ///////////////////// + /** FeedRowAndObjNames: + * Provide constraint, then objective names. + * Name information is optional. + * + * Implementation: + * if ((output_desired) && wrt) + * for (i: ....) + * wrt << name[i].c_str(); + */ + template + void FeedRowAndObjNames(RowObjNameWriter& wrt) { } + + /** Provide deleted row names.*/ + template + void FeedDelRowNames(DelRowNameWriter& ) { } + + /** Provide variable names. */ + template + void FeedColNames(ColNameWriter& ) { } + + /** Provide unused variable names. */ + template + void FeedUnusedVarNames(UnusedVarNameWriter& ) { } + + /** Provide {fixed variable, extra info} pairs. + * This includes defined eliminated variables. + * + * Implementation: + * if ((output_desired) && wrt) + * for (....) + * wrt << typename Writer::StrStrValue + * { name[i].c_str(), comment[i].c_str() }; + */ + template + void FeedFixedVarNames(FixedVarNameWriter& ) { } + + /** Provide {obj name, constant term} pairs. + * + * Implementation: + * if (wrt) + * for (....) + * wrt << typename Writer::StrDblValue + * { name[i].c_str(), (double)obj_offset[i] }; + */ + template + void FeedObjAdj(ObjOffsetWriter& ) { } + + +protected: + const NLFeeder2_C& NLF() const { return nlf2_c_; } + private: - NLFeeder2_C* p_nlf2_c_ {nullptr}; + /// Just store copy + const NLFeeder2_C nlf2_c_; }; } // namespace mp diff --git a/nl-writer2/include/api/c/nl-feeder2-c.h b/nl-writer2/include/api/c/nl-feeder2-c.h index 1f8eaa8aa..7417e3618 100644 --- a/nl-writer2/include/api/c/nl-feeder2-c.h +++ b/nl-writer2/include/api/c/nl-feeder2-c.h @@ -1,17 +1,21 @@ /** * C API: extern "C" wrappers for the NLFeeder2 interface, - * as well as NLWriter2 calls. + * as well as for NLWriter2 calls. * */ #ifndef NLFEEDER2_C_H #define NLFEEDER2_C_H +#include "mp/nl-header-c.h" + #ifdef __cplusplus // Can be used from C++ extern "C" { #endif +typedef struct NLW2_ObjGradWriter NLW2_ObjGradWriter; + /** Wrap mp::NLFeeder2 for C API. NLFeeder2_C: writes model details on request @@ -32,6 +36,432 @@ typedef struct NLFeeder2_C { /// User data void* p_user_data_; + /////////////////////////////////////////////////////////////// + /// Set the below function pointers + /////////////////////////////////////////////////////////////// + + ///////////////////// 1. NL HEADER AND OPTIONS ///////////////// + /** Provide NLHeader. + * + * This method is called first. + * + * NLHeader summarizes the model and provides some + * technical parameters, + * such as text/binary NL format. */ + NLHeader_C (*Header)(void* p_user_data); + + /// NL comments? + int want_nl_comments_; + + /// The maximum number of significant digits written. + /// The default value 0 requests full precision, which + /// might be the shortest representation that, when + /// converted to binary and properly rounded, will + /// give exactly the binary value stored in the computer. + int output_precision_; + + /// Write bounds first? + /// The default is yes in AMPL, controlled by + /// (the value of option nl_permute) & 32 + /// (the bit is 0 for yes). + /// Changing this option is deprecated, see + /// https://netlib.org/ampl/changes. + int want_bounds_first_; + + /// Want Jacobian column sizes? + /// Required by some nonlinear solvers. + /// Options: 0 - none, 1 - cumulative (default), + /// 2 - non-cumulative. + /// This option controls how ColSizeWriter + /// writes the provided sizes (which should be + /// non-cumulative). + int want_column_sizes_; + + + ///////////////////// 2. OBJECTIVES ///////////////////// + /** Description for objective function \a i + * (\a i in 0..num_objs-1). + * With WantNLComments()==true, this is + * written to text-format NL as a comment. */ + const char* (*ObjDescription)(void* p_user_data, int i); + + /** Provide type of objective \a i. + * 0 - minimization; + * 1 - maximization. */ + int (*ObjType)(void* p_user_data, int i); + + /** Number of nonzeros in the gradient for objective \a i. + * Should include entries for all potentially + * nonzero elements (sparsity pattern). */ + int (*ObjGradientNNZ)(void* p_user_data, int i); + + /** Feed gradient for objective \a i. + * Should include entries for all potentially + * nonzero elements (sparsity pattern). + * + * Implementation skeleton: + * for (size_t j=0; j +// void FeedObjExpression(int i, ObjExprWriter& ) { } + + + ///////////////////// 3. DEFINED VARIABLES ///////////////////// + /** Defined variables. + * + * Classical NL writes first the defined variables + * which are used in several places (constraints and/or + * objectives). Defined variables used in a single place + * (1 constraint, or 1 objective), are written + * just before the expression tree of their usage. + * + * For most solvers, this requirement can be ignored + * and this method can return all defined variables + * in the first group (for \a i=0). + * + * The method is guaranteed to be called in the following order: + * 1. For \a i=0; + * 2. For \a i>0, increasing, before constraint \a (i-1)'s expression; + * 3. For \a i<0, decreasing, before objective \a (-i-1)'s expression. + * + * @param i: + * - For \a i=0, feed a sequence of defined variables + * used in several constraints and/or objectives. + * - For \a i>0, feed the defined variables used solely + * in constraint \a i-1. + * - For \a i<0, feed the defined variables used solely + * in objective \a -i-1. + * + * Implementation skeleton: + * // dvar_index in num_vars..num_vars+num_defvars-1. + * for (int dvar_index: dvar_indexes[i]) { + * auto dv = dvw.StartDefVar(dvar_index, lin_nnz, name_or_comment); + * /////////// Write the linear part: + * auto linw = dv.GetLinExprWriter(); + * for (int i=0; i +// void FeedDefinedVariables(int i, DefVarWriterFactory& ) { } + + + ///////////////////// 4. VARIABLE BOUNDS ///////////////////// + /** Bounds for variables (except defined variables). + * Use +-inf for missing lower and/or upper bounds. + * Note that variable type is given by variable ordering, + * see NLHeader. + * + * Implementation skeleton: + * for (int i = 0; i < hdr.num_vars; i++) + * vbw.WriteLbUb(lb[i], ub[i]); + */ +// void FeedVarBounds(VarBoundsWriter& ) { } + + + ///////////////// 5. CONSTRAINT BOUNDS & COMPLEMENTARITY /////// + /// \rst + /// Algebraic constraint bounds (for a single constraint): + /// either range (lb, ub), + /// or complementarity info (k, cvar), when k>0. + /// + /// For a complementarity constraint to hold, if cvar is at + /// its lower bound, then body >= 0; if cvar is at its upper + /// bound, then body <= 0; + /// and if cvar is strictly between its bounds, then body = 0. + /// The integer k in a complementarity constraint line indicates + /// which bounds on cvar are finite: 1 and 3 imply a finite + /// lower bound; 2 and 3 imply a finite upper bound; 0 (which + /// should not occur) would imply no finite bounds, i.e., + /// body = 0 must always hold. + /// + /// Example: + /// + /// .. code-block:: ampl + /// + /// ampl: var x; var y; var z; + /// ampl: s.t. Compl1: x+y >= 3 complements x-z <= 15; + /// ampl: s.t. Compl2: -2 <= 2*y+3*z <= 13 complements 6*z-2*x; + /// ampl: expand; + /// subject to Compl1: + /// 3 <= x + y + /// complements + /// x - z <= 15; + /// + /// subject to Compl2: + /// -2 <= 2*y + 3*z <= 13 + /// complements + /// -2*x + 6*z; + /// + /// ampl: solexpand; + /// Nonsquare complementarity system: + /// 4 complementarities including 2 equations + /// 5 variables + /// subject to Compl1.L: + /// x + y + Compl1$cvar = 0; + /// + /// subject to Compl1.R: + /// -15 + x - z <= 0 + /// complements + /// Compl1$cvar <= -3; + /// + /// subject to Compl2.L: + /// 2*y + 3*z - Compl2$cvar = 0; + /// + /// subject to Compl2.R: + /// -2*x + 6*z + /// complements + /// -2 <= Compl2$cvar <= 13; + /// + /// \endrst + struct AlgConRange_C { + double L, U; + int k, cvar; // k>0 means complementarity to cvar + }; + + /** Bounds/complementarity for all algebraic constraints + * (\a num_algebraic_cons). + * + * Implementation skeleton: + * for (int j=0; j negInfinity) + * bnd.k = 1; + * if (vub[j] < Infinity) + * bnd.k |= 2; + * assert(bnd.k); + * bnd.cvar = j; + * } else { + * bnd.L = clb[j]; + * bnd.U = cub[j]; + * } + * cbw.WriteAlgConRange(bnd); + * } + */ +// void FeedConBounds(ConBoundsWriter& ) { } + + + ///////////////////// 6. CONSTRAINTS ///////////////////// + /** Description of constraint \a i + * (\a i in 0..num_algebraic_cons+num_logical_cons-1). + * With WantNLComments()==true, this is + * written to text-format NL as a comment. */ + const char* (*ConDescription)(void *p_user_data, int ); + + /** Feed the linear part of algebraic constraint \a i. + * For smooth solvers, should contain entries for all + * potential nonzeros (Jacobian sparsity pattern). + * + * Implementation skeleton: + * if (con_grad[i].size()) { + * auto sv = svw.MakeVectorWriter(con_grad[i].size()); + * for (size_t j=0; jnsosref); + * .... + */ +// void FeedPLSOS(PLSOSWriter& ) { } + + + ///////////////////// 9. FUNCTIONS ///////////////////// + /** Function definition. */ +// struct FuncDef { +// const char* Name() { return ""; } +// int NumArgs() { return 0; } +// /** Function type. +// * 0 - numeric; +// * 1 - symbolic. */ +// int Type() { return 0; } +// }; + + /** Provide definition + * of function \a i, i=0..num_funcs-1. */ +// FuncDef Function(int i) { return {}; } + + + ///////////////////// 10. RANDOM VARIABLES ///////////////////// + /// Random variables. + /// Undocumented feature. SNL2006. + /// Example: + /// var z >= 0; + /// let z.stage := 1; + /// var x{0..1, 0..1} random := Uniform(0,2); + /// for {i in 0..1, j in 0..1} {let x[i,j].stage := 1;}; + /// display z.stage, x.stage; + /// c: z * sum{i in 0..1, j in 0..1} x[i,j] <= 3 + Sample(Uniform(0,2)); + /// + /// Feed random variables. + /// Indexes: num_vars+num_common_exprs + /// .. num_vars+num_common_exprs+num_rand_vars-1. + /// + /// Implementation skeleton: + /// for(j = num_vars+num_common_exprs; + /// j < num_vars+num_common_exprs+num_rand_vars; j++) { + /// auto ew = rvw.StartRandVar(j, rand_var_comment(j)); + /// ew.EPut(rand_var_root_expr(j)); + /// } +// void FeedRandomVariables(RandVarWriterFactory& ) { } + + + ///////////////////// 11. COLUMN SIZES ///////////////////// + + /** Jacobian column sizes. + * Should feed LP column sizes + * for all but the last variable. + * + * Implementation skeleton: + * if (WantColumnSizes()) + * for (int i=0; i < num_vars+num_rand_vars-1; ++i) + * csw.Write(col_size[i]); + */ +// void FeedColumnSizes(ColSizeWriter& ) { } + + + ///////////////////// 12. INITIAL GUESSES ///////////////////// + /** Initial primal guesses. + * + * Implementation: + * if (ini_guess.size()) { + * auto ig = igw.MakeVectorWriter(ini_guess.size()); + * for (size_t i=0; i diff --git a/nl-writer2/include/mp/nl-header-c.h b/nl-writer2/include/mp/nl-header-c.h new file mode 100644 index 000000000..e6ea598fd --- /dev/null +++ b/nl-writer2/include/mp/nl-header-c.h @@ -0,0 +1,339 @@ +/** + * Base C structs for NL header. + * + * Used both in C and C++. + * + */ +#ifndef NLHEADERC_H +#define NLHEADERC_H + +#include + +#ifdef __cplusplus // Can be used from C++ +extern "C" { +#endif + + +/** Information about an optimization problem. + * Full documentation on the NL format: + * technical report "Writing .nl Files" + * (https://ampl.github.io/nlwrite.pdf.) + */ +typedef struct ProblemInfo_C { + /** Total number of variables. */ + int num_vars; + + /** + Number of algebraic constraints including ranges and equality constraints. + It doesn't include logical constraints. + */ + int num_algebraic_cons; + + /** Total number of objectives. */ + int num_objs; + + /** Number of ranges (constraints with -Infinity < LHS < RHS < Infinity). */ + int num_ranges; + + /** + Number of equality constraints or -1 if unknown (AMPL prior to 19970627). + */ + int num_eqns; + + /** Number of logical constraints. */ + int num_logical_cons; + + /** Number of random variables. */ + int num_rand_vars; + + /** Number of random defined variables. */ + int num_rand_common_exprs; + + /** Number of random constraints. */ + int num_rand_cons; + + /** Number of random objectives. */ + int num_rand_objs; + + /** Number of random calls. */ + int num_rand_calls; + + /** Number of stages. */ + int num_stages; + + // Nonlinear and complementarity information + // ----------------------------------------- + + /** Total number of nonlinear constraints. */ + int num_nl_cons; + + /** Total number of nonlinear objectives. */ + int num_nl_objs; + + /** Total number of complementarity conditions. */ + int num_compl_conds; + + /** Number of nonlinear complementarity conditions. */ + int num_nl_compl_conds; + + /** Number of complementarities involving double inequalities. */ + int num_compl_dbl_ineqs; + + /** Number of complemented variables with a nonzero lower bound. */ + int num_compl_vars_with_nz_lb; + + // Information about network constraints + // ------------------------------------- + + /** Number of nonlinear network constraints. */ + int num_nl_net_cons; + + /** Number of linear network constraints. */ + int num_linear_net_cons; + + // Information about nonlinear variables + // ------------------------------------- + + /** + Number of nonlinear variables in constraints including nonlinear + variables in both constraints and objectives. + */ + int num_nl_vars_in_cons; + + /** + Number of nonlinear variables in objectives including nonlinear + variables in both constraints and objectives. + */ + int num_nl_vars_in_objs; + + /** Number of nonlinear variables in both constraints and objectives. */ + int num_nl_vars_in_both; + + // Miscellaneous + // ------------- + + /** Number of linear network variables (arcs). */ + int num_linear_net_vars; + + /** Number of functions. */ + int num_funcs; + + // Information about discrete variables + // ------------------------------------ + + /** Number of linear binary variables. */ + int num_linear_binary_vars; + + /** Number of linear non-binary integer variables. */ + int num_linear_integer_vars; + + /** + Number of integer nonlinear variables in both constraints and objectives. + */ + int num_nl_integer_vars_in_both; + + /** Number of integer nonlinear variables just in constraints. */ + int num_nl_integer_vars_in_cons; + + /** Number of integer nonlinear variables just in objectives. */ + int num_nl_integer_vars_in_objs; + + // Information about nonzeros + // -------------------------- + + /** Number of nonzeros in constraints' Jacobian. */ + size_t num_con_nonzeros; + + /** Number of nonzeros in all objective gradients. */ + size_t num_obj_nonzeros; + + // Information about names. + // Does not have to be filled for NLWriter2. + // ----------------------- + + /** Length of longest constraint or objective name + * if names are available. */ + int max_con_name_len; + + /** Length of longest variable name if names are available. */ + int max_var_name_len; + + // Information about common expressions + // ------------------------------------ + + /** + Number of common expressions that appear both in constraints + and objectives. + */ + int num_common_exprs_in_both; + + /** + Number of common expressions that appear in multiple constraints + and don't appear in objectives. + */ + int num_common_exprs_in_cons; + + /** + Number of common expressions that appear in multiple objectives + and don't appear in constraints. + */ + int num_common_exprs_in_objs; + + /** + Number of common expressions that only appear in a single constraint + and don't appear in objectives. + */ + int num_common_exprs_in_single_cons; + + /** + Number of common expressions that only appear in a single objective + and don't appear in constraints. + */ + int num_common_exprs_in_single_objs; + +} ProblemInfo_C; + + +enum { + /** Maximum number of options reserved for AMPL use in NL and SOL formats. */ + MAX_AMPL_OPTIONS = 9 +}; + + +enum { + VBTOL_OPTION_INDEX = 1, + USE_VBTOL_FLAG = 3 +}; + + +/** Floating-point arithmetic kind. */ +typedef enum NLArithKind { + + /** Unknown floating-point arithmetic. */ + NL_ARITH_UNKNOWN = 0, + + /** + \rst + Standard `IEEE-754 floating point + `_ - little endian. + \endrst + */ + NL_ARITH_IEEE_LITTLE_ENDIAN = 1, + + /** Standard IEEE-754 floating point - big endian. */ + NL_ARITH_IEEE_BIG_ENDIAN = 2, + + /** + \rst + `IBM floating point + `_. + \endrst + */ + NL_ARITH_IBM = 3, + + /** VAX floating point (legacy). */ + NL_ARITH_VAX = 4, + + /** Cray floating point. */ + NL_ARITH_CRAY = 5, + + /** Last floating point. */ + NL_ARITH_LAST = NL_ARITH_CRAY +} NLArithKind; + + +/** Input/output format */ +typedef int NLFormat; + +enum { + /** + Text format. The text format is fully portable meaning that an .nl file + can be written on a machine of one architecture and then read on a + machine of a different architecture. + */ + NL_FORMAT_TEXT = 0, + + /** + Binary format. The binary format is not generally portable and should + normally be used on a single machine. + */ + NL_FORMAT_BINARY = 1 +}; + + +/** NL Flags. */ +enum { + /** Flag that specifies whether to write output suffixes to a .sol file. */ + WANT_OUTPUT_SUFFIXES = 1 +}; + + +/** + * NL technical info + */ +typedef struct NLInfo_C { + + /** Input/output format. */ + NLFormat format; + + /** The number of options reserved for AMPL use. */ + int num_ampl_options; + + /** + Values of options reserved for AMPL use. + Leave the default values if not using AMPL. + */ + long ampl_options[MAX_AMPL_OPTIONS]; + + /** + Extra info for writing a solution reserved for AMPL use. + Leave the default value if not using AMPL. + */ + double ampl_vbtol; + + /** + * Problem name. + */ + const char* prob_name; + + /** + \rst + Floating-point arithmetic kind used with binary format to check + if an .nl file is written using a compatible representation of + floating-point numbers. It is not used with the text format and normally + set to `mp::arith::UNKNOWN` there. + \endrst + */ + NLArithKind arith_kind; + + /** + \rst + Flags. Can be either 0 or `mp::NLHeader::WANT_OUTPUT_SUFFIXES`. + \endrst + */ + int flags; +} NLInfo_C; + + +/** + \rst + An NL `header `_ + which contains information about problem dimensions, such as the number of + variables and constraints, and the input format. + \endrst + */ +typedef struct NLHeader_C { + ProblemInfo_C pi; + NLInfo_C nli; +} NLHeader_C; + + +/// Default NLHeader_C +NLHeader_C MakeNLHeader_C_Default(); + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // NLHEADERC_H diff --git a/nl-writer2/include/mp/nl-header.h b/nl-writer2/include/mp/nl-header.h index bd8ac6f01..dd0e1da74 100644 --- a/nl-writer2/include/mp/nl-header.h +++ b/nl-writer2/include/mp/nl-header.h @@ -27,6 +27,9 @@ #include #include #include +#include + +#include "mp/nl-header-c.h" /// Namespace mp. namespace mp { @@ -37,47 +40,11 @@ namespace mp { * technical report "Writing .nl Files" * (https://ampl.github.io/nlwrite.pdf.) */ -struct ProblemInfo { - /** Total number of variables. */ - int num_vars {0}; - - /** - Number of algebraic constraints including ranges and equality constraints. - It doesn't include logical constraints. - */ - int num_algebraic_cons {0}; - - /** Total number of objectives. */ - int num_objs {0}; - - /** Number of ranges (constraints with -Infinity < LHS < RHS < Infinity). */ - int num_ranges {0}; - - /** - Number of equality constraints or -1 if unknown (AMPL prior to 19970627). - */ - int num_eqns {0}; - - /** Number of logical constraints. */ - int num_logical_cons {0}; - - /** Number of random variables. */ - int num_rand_vars {0}; - - /** Number of random defined variables. */ - int num_rand_common_exprs {0}; - - /** Number of random constraints. */ - int num_rand_cons {0}; - - /** Number of random objectives. */ - int num_rand_objs {0}; - - /** Number of random calls. */ - int num_rand_calls {0}; - - /** Number of stages. */ - int num_stages {0}; +struct ProblemInfo : ProblemInfo_C { + /// Construct default + ProblemInfo() { + std::memset(this, 0, sizeof(*this)); + } /** Returns the number of integer variables (includes binary variables). */ int num_integer_vars() const { @@ -89,136 +56,6 @@ struct ProblemInfo { /** Returns the number of continuous variables. */ int num_continuous_vars() const { return num_vars - num_integer_vars(); } - // Nonlinear and complementarity information - // ----------------------------------------- - - /** Total number of nonlinear constraints. */ - int num_nl_cons {0}; - - /** Total number of nonlinear objectives. */ - int num_nl_objs {0}; - - /** Total number of complementarity conditions. */ - int num_compl_conds {0}; - - /** Number of nonlinear complementarity conditions. */ - int num_nl_compl_conds {0}; - - /** Number of complementarities involving double inequalities. */ - int num_compl_dbl_ineqs {0}; - - /** Number of complemented variables with a nonzero lower bound. */ - int num_compl_vars_with_nz_lb {0}; - - // Information about network constraints - // ------------------------------------- - - /** Number of nonlinear network constraints. */ - int num_nl_net_cons {0}; - - /** Number of linear network constraints. */ - int num_linear_net_cons {0}; - - // Information about nonlinear variables - // ------------------------------------- - - /** - Number of nonlinear variables in constraints including nonlinear - variables in both constraints and objectives. - */ - int num_nl_vars_in_cons {0}; - - /** - Number of nonlinear variables in objectives including nonlinear - variables in both constraints and objectives. - */ - int num_nl_vars_in_objs {0}; - - /** Number of nonlinear variables in both constraints and objectives. */ - int num_nl_vars_in_both {0}; - - // Miscellaneous - // ------------- - - /** Number of linear network variables (arcs). */ - int num_linear_net_vars {0}; - - /** Number of functions. */ - int num_funcs {0}; - - // Information about discrete variables - // ------------------------------------ - - /** Number of linear binary variables. */ - int num_linear_binary_vars {0}; - - /** Number of linear non-binary integer variables. */ - int num_linear_integer_vars {0}; - - /** - Number of integer nonlinear variables in both constraints and objectives. - */ - int num_nl_integer_vars_in_both {0}; - - /** Number of integer nonlinear variables just in constraints. */ - int num_nl_integer_vars_in_cons {0}; - - /** Number of integer nonlinear variables just in objectives. */ - int num_nl_integer_vars_in_objs {0}; - - // Information about nonzeros - // -------------------------- - - /** Number of nonzeros in constraints' Jacobian. */ - std::size_t num_con_nonzeros {0}; - - /** Number of nonzeros in all objective gradients. */ - std::size_t num_obj_nonzeros {0}; - - // Information about names. - // Does not have to be filled for NLWriter2. - // ----------------------- - - /** Length of longest constraint or objective name - * if names are available. */ - int max_con_name_len {0}; - - /** Length of longest variable name if names are available. */ - int max_var_name_len {0}; - - // Information about common expressions - // ------------------------------------ - - /** - Number of common expressions that appear both in constraints - and objectives. - */ - int num_common_exprs_in_both {0}; - - /** - Number of common expressions that appear in multiple constraints - and don't appear in objectives. - */ - int num_common_exprs_in_cons {0}; - - /** - Number of common expressions that appear in multiple objectives - and don't appear in constraints. - */ - int num_common_exprs_in_objs {0}; - - /** - Number of common expressions that only appear in a single constraint - and don't appear in objectives. - */ - int num_common_exprs_in_single_cons {0}; - - /** - Number of common expressions that only appear in a single objective - and don't appear in constraints. - */ - int num_common_exprs_in_single_objs {0}; - /** Returns the total number of common expressions. */ int num_common_exprs() const { return num_common_exprs_in_both + num_common_exprs_in_cons + @@ -234,7 +71,9 @@ enum { }; enum { + /// internal constant VBTOL_OPTION_INDEX = 1, + /// internal constant USE_VBTOL_FLAG = 3 }; @@ -245,7 +84,7 @@ namespace arith { enum Kind { /** Unknown floating-point arithmetic. */ - UNKNOWN = 0, + UNKNOWN = NL_ARITH_UNKNOWN, /** \rst @@ -253,10 +92,10 @@ enum Kind { `_ - little endian. \endrst */ - IEEE_LITTLE_ENDIAN = 1, + IEEE_LITTLE_ENDIAN = NL_ARITH_IEEE_LITTLE_ENDIAN, /** Standard IEEE-754 floating point - big endian. */ - IEEE_BIG_ENDIAN = 2, + IEEE_BIG_ENDIAN = NL_ARITH_IEEE_BIG_ENDIAN, /** \rst @@ -264,16 +103,16 @@ enum Kind { `_. \endrst */ - IBM = 3, + IBM = NL_ARITH_IBM, /** VAX floating point (legacy). */ - VAX = 4, + VAX = NL_ARITH_VAX, /** Cray floating point. */ - CRAY = 5, + CRAY = NL_ARITH_CRAY, /** Last floating point. */ - LAST = CRAY + LAST = NL_ARITH_LAST }; /// Returns floating-point arithmetic kind used on the current system. @@ -286,6 +125,37 @@ inline bool IsIEEE(arith::Kind k) { } // namespace arith +/// NL info +struct NLInfo : NLInfo_C { + + /** Input/output format */ + using Format = NLFormat; + /** + Text format. The text format is fully portable meaning that an .nl file + can be written on a machine of one architecture and then read on a + machine of a different architecture. + */ + static const Format TEXT = NL_FORMAT_TEXT; + + /** + Binary format. The binary format is not generally portable and should + normally be used on a single machine. + */ + static const Format BINARY = NL_FORMAT_BINARY; + + /// Construct default + NLInfo() { + format = TEXT; + num_ampl_options = 3; + ampl_vbtol = 0.0; + arith_kind = NL_ARITH_IEEE_LITTLE_ENDIAN; + flags = WANT_OUTPUT_SUFFIXES; + std::fill(ampl_options, ampl_options + MAX_AMPL_OPTIONS, 0); + std::array opt_default {1, 1, 0}; + std::copy(opt_default.begin(), opt_default.end(), ampl_options); + } +}; + /** \rst An NL `header `_ @@ -295,79 +165,7 @@ inline bool IsIEEE(arith::Kind k) { Base class: `mp::ProblemInfo` \endrst */ -struct NLHeader : ProblemInfo { - /** Input/output format */ - enum Format { - /** - Text format. The text format is fully portable meaning that an .nl file - can be written on a machine of one architecture and then read on a - machine of a different architecture. - */ - TEXT = 0, - - /** - Binary format. The binary format is not generally portable and should - normally be used on a single machine. - */ - BINARY = 1 - }; - - /** Input/output format. */ - Format format {TEXT}; - - /** The number of options reserved for AMPL use. */ - int num_ampl_options {3}; - - /** - Values of options reserved for AMPL use. - Leave the default values if not using AMPL. - */ - long ampl_options[MAX_AMPL_OPTIONS] = {1, 1, 0}; - - /** - Extra info for writing a solution reserved for AMPL use. - Leave the default value if not using AMPL. - */ - double ampl_vbtol {0.0}; - - /** - * Problem name. - */ - std::string prob_name; - - /** - \rst - Floating-point arithmetic kind used with binary format to check - if an .nl file is written using a compatible representation of - floating-point numbers. It is not used with the text format and normally - set to `mp::arith::UNKNOWN` there. - \endrst - */ - arith::Kind arith_kind {arith::IEEE_LITTLE_ENDIAN}; - - /** Flags. */ - enum { - /** Flag that specifies whether to write output suffixes to a .sol file. */ - WANT_OUTPUT_SUFFIXES = 1 - }; - - /** - \rst - Flags. Can be either 0 or `mp::NLHeader::WANT_OUTPUT_SUFFIXES`. - \endrst - */ - int flags {WANT_OUTPUT_SUFFIXES}; - - NLHeader() - : ProblemInfo(), - format(TEXT), - num_ampl_options(3), ampl_vbtol(0), - arith_kind(arith::IEEE_LITTLE_ENDIAN), - flags(WANT_OUTPUT_SUFFIXES) { - std::fill(ampl_options, ampl_options + MAX_AMPL_OPTIONS, 0); - std::array opt_default {1, 1, 0}; - std::copy(opt_default.begin(), opt_default.end(), ampl_options); - } +struct NLHeader : ProblemInfo, NLInfo { }; } // namespace mp diff --git a/nl-writer2/include/mp/nl-writer2.hpp b/nl-writer2/include/mp/nl-writer2.hpp index ef2f51875..68d139350 100644 --- a/nl-writer2/include/mp/nl-writer2.hpp +++ b/nl-writer2/include/mp/nl-writer2.hpp @@ -306,7 +306,7 @@ void NLWriter2::WriteNLHeader() { nm.Printf(" %ld", Hdr().ampl_options[i]); if (Hdr().ampl_options[VBTOL_OPTION_INDEX] == USE_VBTOL_FLAG) nm.Printf(" %.g", Hdr().ampl_vbtol); - nm.Printf(gl_1a, Hdr().prob_name.c_str()); + nm.Printf(gl_1a, Hdr().prob_name); /// Num variables, constraints, obj, ... nm.Printf(gl_2a, diff --git a/nl-writer2/src/c_api.cc b/nl-writer2/src/c_api.cc index 2bf87e2a3..48f2b45a1 100644 --- a/nl-writer2/src/c_api.cc +++ b/nl-writer2/src/c_api.cc @@ -14,6 +14,7 @@ #include "api/c/nl-feeder2-c-impl.h" #include "api/c/sol-handler2-c-impl.h" #include "api/c/nl-writer2-misc-c-impl.h" +#include "mp/nlsol.h" ///////////////////////// NLUtils_C /////////////////////////// @@ -32,7 +33,9 @@ void NLW2_DestroyNLUtils_C_Default(NLUtils_C* ) { } //////////// NLSOL_C API ////////////// -/// Construct +/// Construct. +/// +/// Note that the argument objects are stored by value. NLSOL_C NLW2_MakeNLSOL_C( NLFeeder2_C* pnlf, SOLHandler2_C* psolh, NLUtils_C* putl) { NLSOL_C result; @@ -40,6 +43,13 @@ NLSOL_C NLW2_MakeNLSOL_C( result.p_nlf_ = new mp::NLFeeder2_C_Impl(pnlf); result.p_solh_ = new mp::SOLHandler2_C_Impl(psolh); result.p_utl_ = new mp::NLUtils_C_Impl(putl); + result.p_nlsol_ + = new mp::NLSOL( + *(mp::NLFeeder2_C_Impl*)result.p_nlf_, + *(mp::SOLHandler2_C_Impl*)result.p_solh_, + *(mp::NLUtils_C_Impl*)result.p_utl_); + return result; } @@ -48,6 +58,8 @@ void NLW2_DestroyNLSOL_C(NLSOL_C* pnls) { delete (mp::NLUtils_C_Impl*)pnls->p_utl_; delete (mp::SOLHandler2_C_Impl*)pnls->p_solh_; delete (mp::NLFeeder2_C_Impl*)pnls->p_nlf_; + delete (mp::NLSOL*)pnls->p_nlsol_; assert(0); } diff --git a/nl-writer2/src/nl-writer2.cc b/nl-writer2/src/nl-writer2.cc index ebe2e7b7f..3cc16473f 100644 --- a/nl-writer2/src/nl-writer2.cc +++ b/nl-writer2/src/nl-writer2.cc @@ -78,6 +78,16 @@ void gfmt(char*, size_t, double, int); //////////////////////////////////////////////////////// namespace mp { +extern "C" +NLHeader_C MakeNLHeader_C_Default() { + NLHeader nlh; + NLHeader_C nlh_c; + nlh_c.pi = *(ProblemInfo_C*)(&nlh); + nlh_c.nli = *(NLInfo_C*)(&nlh); + return nlh_c; +} + + /// \brief For printing to .nl or auxiliary files. int TextFormatter::apr(File& f, const char *fmt, ...) {