Skip to content

Commit

Permalink
C API: write ini guesses & suffixes #30
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Nov 28, 2023
1 parent 8487264 commit 25761a8
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 71 deletions.
19 changes: 18 additions & 1 deletion nl-writer2/examples/c/nlsol_ex_c_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ CAPIExample MakeCAPIExample_Linear_01(void) {
static const SparseEntry obj_linpart[]
= { {0, 13}, {1, 1.0} };

static const double ini_x[] = {30.15, 15.11};
static const double ini_y[] = {-10, -120};

static const SparseEntry suf_val[] = {{0, 5.3}};

static int n_suf = 1;
static const Suffix suf[] = {
{"zork", 1+4, // constraints, float-valued
1, suf_val}
};

/// Solution
static double sol_dual[] = {NAN, NAN};
static double sol_primal[] = {NAN, NAN};
Expand Down Expand Up @@ -66,6 +77,12 @@ CAPIExample MakeCAPIExample_Linear_01(void) {
.n_obj_nz = 2,
.obj_name = "TotalSum",

.ini_x = ini_x,
.ini_y = ini_y,

.n_suf = n_suf,
.suf = suf,

.binary_nl = 1,

.sol_dual_ = sol_dual,
Expand Down Expand Up @@ -98,5 +115,5 @@ void PrintSolution_C(CAPIExample* pex, const char* stub) {
pex->var_name[i], pex->sol_primal_[i]);

printf("\nObjno used: %d, solve_result_num: %d\n",
pex->objno_, pex->solve_code_);
pex->objno_+1, pex->solve_code_);
}
28 changes: 25 additions & 3 deletions nl-writer2/examples/c/nlsol_ex_c_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ subj to C3:
22*x + 14536*y <= 3e5;
## Initial guess
let x := 1.5;
let y := 0.11;
let x := 30.15;
let y := 15.11;
## Dual initial guess
let C2 := -10;
let C3 := -120;
## A suffix
suffix zork;
let C2.zork := 5;
let C2.zork := 5.3;
*
*/
Expand All @@ -44,6 +48,15 @@ typedef struct SparseEntry {
} SparseEntry;


/// Suffix
typedef struct Suffix {
const char* name_;
int kind_;
int n_val_;
const SparseEntry* values_; // store double's always
} Suffix;


/// C API example data
typedef struct CAPIExample {
const int n_var;
Expand Down Expand Up @@ -97,6 +110,15 @@ typedef struct CAPIExample {
int n_obj_nz;
const char* obj_name;

/// Primal initial guess (dense vector).
const double* ini_x;
/// Primal dual guess (dense vector).
const double* ini_y;

/// Suffixes.
int n_suf;
const Suffix* suf;

/// Some technical stuff
int binary_nl;

Expand Down
78 changes: 57 additions & 21 deletions nl-writer2/examples/c/nlsol_ex_c_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,19 +290,45 @@ void FeedColumnSizes(void* p_user_data, void* p_api_data) {


///////////////////// 12. INITIAL GUESSES /////////////////////
/** Initial primal guesses.
*

int CountNNZ(const double* parray, int len) {
int result = 0;
for (int i=0; i<len; ++i)
if (parray[i])
++result;
return result;
}
void WriteDenseAsSparse(
const double* parray, int len, void* p_api_data) {
for (int i=0; i<len; ++i)
if (parray[i])
NLW2_WriteSparseDblEntry(p_api_data, i, parray[i]);
}

/**
* Implementation:
* if (ini_guess.size()) {
* auto ig = igw.MakeVectorWriter(ini_guess.size());
* for (size_t i=0; i<ini_guess.size(); ++i)
* ig.Write(i, ini_guess[i]);
* }
* for (size_t i=0; i<n_ini_guess; ++i)
* NLW2_WriteSparseDblEntry(p_api_data, i, ini_guess[i]);
*/
// void FeedInitialGuesses(IGWriter& ) { }
int InitialGuessesNNZ(void* p_user_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
return CountNNZ(pex->ini_x, pex->n_var);
}
void FeedInitialGuesses(void* p_user_data, void* p_api_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
WriteDenseAsSparse(pex->ini_x, pex->n_var, p_api_data);
}

/** Initial dual guesses. */
// void FeedInitialDualGuesses(IDGWriter& ) { }
/// Initial dual guesses
int InitialDualGuessesNNZ(void* p_user_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
return CountNNZ(pex->ini_y, pex->n_con);
}
void FeedInitialDualGuesses(
void* p_user_data, void* p_api_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
WriteDenseAsSparse(pex->ini_y, pex->n_con, p_api_data);
}


///////////////////// 13. SUFFIXES /////////////////////
Expand All @@ -313,13 +339,25 @@ void FeedColumnSizes(void* p_user_data, void* p_api_data) {
*
* Implementation:
* while (....) {
* auto sw = swf.StartIntSuffix( // or ...DblSuffix
* suf_name, kind, n_nonzeros);
* void* p_api_2 = NLW2_StartIntSuffix( // or ...DblSuffix
* p_api_data, suf_name, kind, n_nonzeros);
* for (int i=0; i<n_nonzeros; ++i)
* sw.Write(index[i], value[i]);
* NLW2_WriteSparseIntEntry(p_api_2, // <- new API pointer
* index[i], value[i]); // or ...DblEntry
* }
*/
// void FeedSuffixes(SuffixWriterFactory& ) { }
void FeedSuffixes(void* p_user_data, void* p_api_data) {
CAPIExample* pex = (CAPIExample*)p_user_data;
for (int i_suf=0; i_suf<pex->n_suf; ++i_suf) {
const Suffix* ps = &pex->suf[i_suf];
void* p_api_2 = NLW2_StartDblSuffix(
p_api_data, ps->name_, ps->kind_, ps->n_val_);
for (int i=0; i<ps->n_val_; ++i)
NLW2_WriteSparseDblEntry(p_api_2,
ps->values_[i].index_,
ps->values_[i].value_);
}
}


//////////////////// 14. ROW/COLUMN NAMES ETC /////////////////////
Expand Down Expand Up @@ -499,11 +537,10 @@ NLW2_NLFeeder2_C MakeNLFeeder2_C(
* ig.Write(i, ini_guess[i]);
* }
*/
// void FeedInitialGuesses(IGWriter& ) { }

/** Initial dual guesses. */
// void FeedInitialDualGuesses(IDGWriter& ) { }

result.InitialGuessesNNZ = InitialGuessesNNZ;
result.InitialDualGuessesNNZ = InitialDualGuessesNNZ;
result.FeedInitialGuesses = FeedInitialGuesses;
result.FeedInitialDualGuesses = FeedInitialDualGuesses;

///////////////////// 13. SUFFIXES /////////////////////
/** Feed suffixes.
Expand All @@ -519,8 +556,7 @@ NLW2_NLFeeder2_C MakeNLFeeder2_C(
* sw.Write(index[i], value[i]);
* }
*/
// void FeedSuffixes(SuffixWriterFactory& ) { }

result.FeedSuffixes = FeedSuffixes;

//////////////////// 14. ROW/COLUMN NAMES ETC /////////////////////
/** FeedRowAndObjNames:
Expand Down
2 changes: 1 addition & 1 deletion nl-writer2/examples/cpp/nlsol_ex_sol.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void ExampleSOLHandler2::PrintSolution(
printf("%.17g\t", x);

printf("\nObjno used: %d, solve_result_num: %d\n",
Model().objno_, Model().solve_result_);
Model().objno_+1, Model().solve_result_);

printf("\n%s\n", "Suffixes:");
for (auto suf: Model().suf_out_) {
Expand Down
16 changes: 8 additions & 8 deletions nl-writer2/include/api/c/nl-feeder2-c-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@
namespace mp {

/// Implementation:
/// Wrap NLFeeder2_C into a C++ class,
/// Wrap NLW2_NLFeeder2_C into a C++ class,
/// in order to interface it for NLWriter2
class NLFeeder2_C_Impl
: public NLFeeder2<NLFeeder2_C_Impl, void*> {
class NLW2_NLFeeder2_C_Impl
: public NLFeeder2<NLW2_NLFeeder2_C_Impl, void*> {
public:
/// typedef base class
using Base = NLFeeder2<NLFeeder2_C_Impl, void*>;
using Base = NLFeeder2<NLW2_NLFeeder2_C_Impl, void*>;

/// Construct
NLFeeder2_C_Impl(NLW2_NLFeeder2_C* pnlf2)
NLW2_NLFeeder2_C_Impl(NLW2_NLFeeder2_C* pnlf2)
: nlf2_c_(*pnlf2) { }

///////////////////// 1. NL HEADER AND OPTIONS /////////////////
Expand Down Expand Up @@ -338,11 +338,11 @@ class NLFeeder2_C_Impl
* }
*/
template <class IGWriter>
void FeedInitialGuesses(IGWriter& ) { }
void FeedInitialGuesses(IGWriter& );

/** Initial dual guesses. */
template <class IDGWriter>
void FeedInitialDualGuesses(IDGWriter& ) { }
void FeedInitialDualGuesses(IDGWriter& );


///////////////////// 13. SUFFIXES /////////////////////
Expand All @@ -360,7 +360,7 @@ class NLFeeder2_C_Impl
* }
*/
template <class SuffixWriterFactory>
void FeedSuffixes(SuffixWriterFactory& ) { }
void FeedSuffixes(SuffixWriterFactory& );


//////////////////// 14. ROW/COLUMN NAMES ETC /////////////////////
Expand Down
37 changes: 24 additions & 13 deletions nl-writer2/include/api/c/nl-feeder2-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ extern "C" {

/// Declare callbacks

/// Write sparse vector entry
/// Write sparse vector(int) entry
void NLW2_WriteSparseIntEntry(
void* p_api_data_, int index, int value);
/// Write sparse vector(double) entry
void NLW2_WriteSparseDblEntry(
void* p_api_data_, int index, double value);
/// Write next variable's Lb, Ub
Expand Down Expand Up @@ -86,6 +89,13 @@ typedef struct NLW2_AlgConRange_C {
/// Callback: write next constraint's range
void NLW2_WriteAlgConRange(void* , NLW2_AlgConRange_C*);

/// Callback: start int suffix
void* NLW2_StartIntSuffix(void* p_api_1,
const char* suf_name, int kind, int nnz);
/// Callback: start dbl suffix
void* NLW2_StartDblSuffix(void* p_api_1,
const char* suf_name, int kind, int nnz);


/** Wrap mp::NLFeeder2 for C API.
Expand Down Expand Up @@ -419,16 +429,16 @@ typedef struct NLW2_NLFeeder2_C {
/** Initial primal guesses.
*
* Implementation:
* if (ini_guess.size()) {
* auto ig = igw.MakeVectorWriter(ini_guess.size());
* for (size_t i=0; i<ini_guess.size(); ++i)
* ig.Write(i, ini_guess[i]);
* }
* for (size_t i=0; i<n_ini_guess; ++i)
* NLW2_WriteSparseDblEntry(p_api_data, i, ini_guess[i]);
*/
// void FeedInitialGuesses(IGWriter& ) { }
int (*InitialGuessesNNZ)(void* p_user_data);
void (*FeedInitialGuesses)(void* p_user_data, void* p_api_data);

/** Initial dual guesses. */
// void FeedInitialDualGuesses(IDGWriter& ) { }
/// Initial dual guesses
int (*InitialDualGuessesNNZ)(void* p_user_data);
void (*FeedInitialDualGuesses)(
void* p_user_data, void* p_api_data);


///////////////////// 13. SUFFIXES /////////////////////
Expand All @@ -439,13 +449,14 @@ typedef struct NLW2_NLFeeder2_C {
*
* Implementation:
* while (....) {
* auto sw = swf.StartIntSuffix( // or ...DblSuffix
* suf_name, kind, n_nonzeros);
* void* p_api_2 = NLW2_StartIntSuffix( // or ...DblSuffix
* p_api_data, suf_name, kind, n_nonzeros);
* for (int i=0; i<n_nonzeros; ++i)
* sw.Write(index[i], value[i]);
* NLW2_WriteSparseIntEntry(p_api_2, // or ...DblEntry
* index[i], value[i]); // <- new API pointer
* }
*/
// void FeedSuffixes(SuffixWriterFactory& ) { }
void (*FeedSuffixes)(void* p_user_data, void* p_api_data);


//////////////////// 14. ROW/COLUMN NAMES ETC /////////////////////
Expand Down
6 changes: 3 additions & 3 deletions nl-writer2/include/api/c/sol-handler2-c-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ namespace mp {
template <class Value>
class VecReader;

/// Wrap SOLHandler2_C into a C++ class,
/// Wrap NLW2_SOLHandler2_C into a C++ class,
/// in order to interface it for mp::SOLReader2
class SOLHandler2_C_Impl
class NLW2_SOLHandler2_C_Impl
: public SOLHandler2 {
public:
/// Construct
SOLHandler2_C_Impl(NLW2_SOLHandler2_C* psh2)
NLW2_SOLHandler2_C_Impl(NLW2_SOLHandler2_C* psh2)
: solh2_c_(*psh2) { }

/** The NLHeader used to write the NL file. */
Expand Down
25 changes: 23 additions & 2 deletions nl-writer2/include/mp/nl-writer2.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,39 @@ class NLWriter2 :
template <class Index, class Value>
class SparseVectorWriter {
public:
/// Construct
SparseVectorWriter() { }
/// Not construct(const&)
SparseVectorWriter(const SparseVectorWriter& ) = delete;
/// Construct(&&)
SparseVectorWriter(SparseVectorWriter&& other) {
SparseVectorWriter svw;
svw = std::move(other);
}
/// Constructor
SparseVectorWriter(NLWriter2& nlw, size_t n);
/// Destructor
~SparseVectorWriter() { assert(0 == n_entries_); }
/// No operator=(const&)
SparseVectorWriter& operator=(
const SparseVectorWriter& vw) = delete;
/// operator=(&&)
SparseVectorWriter& operator=(
SparseVectorWriter&& other) {
if (this!=&other) {
std::swap(p_nlw_, other.p_nlw_);
std::swap(n_entries_, other.n_entries_);
}
return *this;
}
/// Write next entry
void Write(Index , Value );
/// Number of outstanding elements
int NLeft() const { return n_entries_; }

private:
NLWriter2& nlw_;
size_t n_entries_;
NLWriter2* p_nlw_ = nullptr;
size_t n_entries_ = 0;
};

/// Typedef SparseDblVecWriter
Expand Down
Loading

0 comments on commit 25761a8

Please sign in to comment.