Skip to content

Commit

Permalink
NL Writer C API: linear example #30
Browse files Browse the repository at this point in the history
No suffixes, no names output
  • Loading branch information
glebbelov committed Nov 15, 2023
1 parent 9b96e54 commit c8c2a96
Show file tree
Hide file tree
Showing 11 changed files with 424 additions and 75 deletions.
17 changes: 12 additions & 5 deletions doc/source/components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,18 @@ The library is zero-overhead: it does not store the model,
nor does it require any intermediate objects to represent
model information.

The API is provided by classes `mp::NLSOL`, `mp::NLWriter2`,
`mp::NLFeeder2`, `mp::SOLReader2`, `mp::SOLHandler2`.
See
`example <https://github.com/ampl/mp/blob/develop/nl-writer2/examples/nlsol_ex.cc>`_
solving a small non-linear model.
- **NL Writer C++ API** is provided by classes
`mp::NLSOL`, `mp::NLFeeder2`, `mp::SOLHandler2`.
See
`example <https://github.com/ampl/mp/blob/develop/nl-writer2/examples/cpp/nlsol_ex.cc>`_
solving a small non-linear model.

- **NL Writer C API** is provided by structs
`NLSOL_C`, `NLFeeder2_C`, `SOLHandler2_C`.
*Currently only linear models are supported.*
See
`example <https://github.com/ampl/mp/blob/develop/nl-writer2/examples/c/nlsol_ex_c.c>`_
solving a small linear model.


.. _recommended-driver-logic:
Expand Down
4 changes: 2 additions & 2 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The documentation is divided in two sections:
* :ref:`howto` illustrates how to get familiar with the framework and how to quickly obtain the
boilerplate code necessary to develop a new solver driver
* :ref:`components` shows the main components of the framework,
including NL reader and writer API
including NL reader and NL writer APIs
* :ref:`howto-test` illustrates how to execute tests during development
* :ref:`cppreference` contains the reference to all the classes in the framework

Expand All @@ -73,7 +73,7 @@ Developer documentation
-----------------------

.. toctree::
:maxdepth: 2
:maxdepth: 3

Developer docs <developers>

Expand Down
2 changes: 1 addition & 1 deletion nl-writer2/examples/c/nlsol_ex_c.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ int main(int argc, const char* const* argv) {
"where <solver> is ipopt, gurobi, minos, ...;\n"
"binary/text is the NL format (default: binary.)\n"
"Examples:\n"
" <this_exe> highs \"\" text /tmp/stub\n"
" <this_exe> highs \"writeprob=/tmp/stub.lp\" text /tmp/stub\n"
" <this_exe> gurobi \"mip:return_gap=1\"");
exit(0);
}
Expand Down
29 changes: 27 additions & 2 deletions nl-writer2/examples/c/nlsol_ex_c_model.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

Expand Down Expand Up @@ -37,6 +38,10 @@ CAPIExample MakeCAPIExample_Linear_01() {
static const SparseEntry obj_linpart[]
= { {0, 13}, {1, 1.0} };

/// Solution
static double sol_dual[] = {NAN, NAN};
static double sol_primal[] = {NAN, NAN};

CAPIExample result = {
.n_var = 2,
.n_var_int = 1,
Expand All @@ -59,7 +64,14 @@ CAPIExample MakeCAPIExample_Linear_01() {
.obj_sense = 1,
.obj_linpart = obj_linpart,
.n_obj_nz = 2,
.obj_name = "TotalSum"
.obj_name = "TotalSum",

.binary_nl = 1,

.sol_dual_ = sol_dual,
.sol_primal_ = sol_primal,
.objno_ = -2,
.solve_code_ = -100
};
return result;
}
Expand All @@ -73,5 +85,18 @@ void DestroyCAPIExample_Linear_01(CAPIExample* pEx) {
}

void PrintSolution_C(CAPIExample* pex, const char* stub) {
assert(0);
printf(
"\n ********** SOLUTION (%s.sol) ***********\n",
stub);
printf("%s\n", "DUALS.");
for (int i=0; i<pex->n_con; ++i)
printf(" %10s = %.17g\n",
pex->con_name[i], pex->sol_dual_[i]);
printf("%s\n", "PRIMALS.");
for (int i=0; i<pex->n_con; ++i)
printf(" %7s = %.17g\n",
pex->var_name[i], pex->sol_primal_[i]);

printf("\nObjno used: %d, solve_result_num: %d\n",
pex->objno_, pex->solve_code_);
}
6 changes: 6 additions & 0 deletions nl-writer2/examples/c/nlsol_ex_c_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ typedef struct CAPIExample {
/// Some technical stuff
int binary_nl;

///////////////////// SOLUTION //////////////////////
double* sol_dual_;
double* sol_primal_;
int objno_;
int solve_code_;

} CAPIExample;

/// Create linear example data
Expand Down
39 changes: 38 additions & 1 deletion nl-writer2/examples/c/nlsol_ex_c_sol.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,51 @@

#include "nlsol_ex_c_sol.h"

/// Declare, implementation in nlsol_ex_c_nl.c
NLHeader_C CAPI_ex_Header(void* pex_void);

void OnDualSolution(
void* p_user_data, int nvals, void* p_api_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
for (int i=0; i<nvals; ++i)
pex->sol_dual_[i] = NLW2_ReadSolVal(p_api_data);
}

void OnPrimalSolution(
void* p_user_data, int nvals, void* p_api_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
for (int i=0; i<nvals; ++i)
pex->sol_primal_[i] = NLW2_ReadSolVal(p_api_data);
}

void OnObjno(void* p_user_data, int on) {
CAPIExample* pex = (CAPIExample*)p_user_data;
pex->objno_ = on;
}

void OnSolveCode(void* p_user_data, int sc) {
CAPIExample* pex = (CAPIExample*)p_user_data;
pex->solve_code_ = sc;
}

SOLHandler2_C MakeSOLHandler2_C(CAPIExample* pex) {
SOLHandler2_C result;
SOLHandler2_C result
= NLW2_MakeSOLHandler2_C_Default();

result.p_user_data_ = pex;

result.Header = CAPI_ex_Header;
// solve message: use default (print it)
// AMPL options: use default
result.OnDualSolution = OnDualSolution;
result.OnPrimalSolution = OnPrimalSolution;
result.OnObjno = OnObjno;
result.OnSolveCode = OnSolveCode;

return result;
}

void DestroySOLHandler2_C(SOLHandler2_C* p) {
p->p_user_data_ = NULL;
NLW2_DestroySOLHandler2_C_Default(p);
}
68 changes: 8 additions & 60 deletions nl-writer2/include/api/c/nl-feeder2-c-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,64 +200,6 @@ class NLFeeder2_C_Impl


///////////////// 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).
Expand Down Expand Up @@ -293,7 +235,7 @@ class NLFeeder2_C_Impl
bnd.U = bnd_c->U;
crw.WriteAlgConRange(bnd);
};
NLF().FeedVarBounds(NLF().p_user_data_, &crw_c);
NLF().FeedConBounds(NLF().p_user_data_, &crw_c);
}


Expand Down Expand Up @@ -376,7 +318,13 @@ class NLFeeder2_C_Impl
* csw.Write(col_size[i]);
*/
template <class ColSizeWriter>
void FeedColumnSizes(ColSizeWriter& ) { }
void FeedColumnSizes(ColSizeWriter& csw) {
assert(NLF().FeedColumnSizes);
std::function<void(int )> f = [&csw](int cs) {
csw.Write(cs);
};
NLF().FeedColumnSizes(NLF().p_user_data_, &f);
}


///////////////////// 12. INITIAL GUESSES /////////////////////
Expand Down
2 changes: 1 addition & 1 deletion nl-writer2/include/api/c/nl-feeder2-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern "C" {
void NLW2_WriteSparseDblEntry(
void* p_api_data_, int index, double value);
/// Write next variable's Lb, Ub
void NLW2_WriteVarLbUb(void* p_api_data, int lb, int ub);
void NLW2_WriteVarLbUb(void* p_api_data, double lb, double ub);
/// Write next Jacobian column size
void NLW2_WriteColSize(void* p_api_data, int sz);

Expand Down
Loading

0 comments on commit c8c2a96

Please sign in to comment.