Skip to content

Commit

Permalink
MP2NL: solve LP #237
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Sep 11, 2024
1 parent c5c247f commit 3810e9b
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 59 deletions.
4 changes: 3 additions & 1 deletion include/mp/backend-to-model-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class Backend2ModelAPIConnector :
// Retrieve the other object
CommonInfo* get_other() { assert(other_); return other_; }
/// Set the other object.
/// This is standardly called from CreateModelManagerWithModelAPI()
/// This is standardly called from CreateModelManagerWithModelAPI(),
/// thus, after construction of both
/// (Solver)Backend and (Solver)ModelAPI.
void set_other(CommonInfo* other) { other_ = other; }

/// Copy into the other object.
Expand Down
2 changes: 1 addition & 1 deletion nl-writer2/include/mp/nl-solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class NLSolver {
std::unique_ptr<NLHeader> p_nlheader_;
NLModel::PreprocessData pd_;

std::string err_msg_;
std::string err_msg_ {"Solving not attempted"}; // We don't check if empty
NLW2_WriteNLResultCode nl_result_
{NLW2_WriteNL_Unset};
NLW2_SOLReadResultCode sol_result_
Expand Down
2 changes: 1 addition & 1 deletion nl-writer2/include/mp/nl-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class File {
f_ = nullptr;
}

/// Printf
/// Printf into the file
void Printf(const char* format, ...);

/// Obtain handler
Expand Down
3 changes: 3 additions & 0 deletions nl-writer2/include/mp/sol-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ class SOLHandler {
/**
* Receive notification of the objective index
* used by the driver (solver option 'objno'-1).
*
* @note AMPL .sol file does not provide
* objective values, only in the solve message if at all.
*/
void OnObjno(int ) { }

Expand Down
48 changes: 27 additions & 21 deletions solvers/mp2nl/mp2nlbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ MP2NLBackend::MP2NLBackend() {
SetMM( std::move( data ) );
SetValuePresolver(pPre);

p_nlsi_ = get_other()->p_nlsi_; // before copying
/// Copy env/lp to ModelAPI
copy_common_info_to_other();
}
Expand All @@ -59,23 +60,19 @@ std::string MP2NLBackend::set_external_libs() {
}

ArrayRef<double> MP2NLBackend::PrimalSolution() {
int num_vars = NumVars();
std::vector<double> x(num_vars);
return x;
return GetNLSolver().GetX();
}

pre::ValueMapDbl MP2NLBackend::DualSolution() {
return {{ { CG_Linear, DualSolution_LP() } }};
return {{ { CG_Algebraic, DualSolution_LP() } }};
}

ArrayRef<double> MP2NLBackend::DualSolution_LP() {
int num_cons = NumLinCons();
std::vector<double> pi(num_cons);
return pi;
return GetNLSolver().GetY();
}

double MP2NLBackend::ObjectiveValue() const {
return 0.0;
return -DBL_MAX/1.01; // SOL does not provide one
}

double MP2NLBackend::NodeCount() const {
Expand All @@ -95,10 +92,13 @@ void MP2NLBackend::ExportModel(const std::string &file) {


void MP2NLBackend::SetInterrupter(mp::Interrupter *inter) {
// TODO
}

void MP2NLBackend::Solve() {
// TODO
GetNLSolver().Solve(
storedOptions_.solver_.c_str(),
storedOptions_.solver_options_.c_str());
WindupMP2NLSolve();
}

Expand Down Expand Up @@ -141,16 +141,12 @@ void MP2NLBackend::ReportMP2NLPool() {


void MP2NLBackend::AddMP2NLMessages() {
AddToSolverMessage(
fmt::format("{} simplex iterations\n", SimplexIterations()));
if (auto nbi = BarrierIterations())
AddToSolverMessage(
fmt::format("{} barrier iterations\n", nbi));
}

std::pair<int, std::string> MP2NLBackend::GetSolveResult() {
namespace sol = mp::sol;
return { sol::UNKNOWN, "not solved" };
return {
GetNLSolver().GetSolveResult(),
GetNLSolver().GetSolveMessage() };
}


Expand Down Expand Up @@ -182,21 +178,31 @@ void MP2NLBackend::InitCustomOptions() {
"To set these options, assign a string specifying their values to the "
"AMPL option ``mp2nl_options``. For example::\n"
"\n"
" ampl: option mp2nl_options 'mipgap=1e-6';\n");
" ampl: option mp2nl_options 'solver=baron solver_options=\"outlev=1 iisfind=1\"';\n");

AddStoredOption("tech:outlev outlev",
"0*/1: Whether to write MP2NL log lines (chatter) to stdout and to file.",
"0*/1: Verbosity for the MP2NL driver. For the underlying solver, use tech:solver_options.",
storedOptions_.outlev_);

AddStoredOption("tech:logfile logfile",
"Log file name.",
storedOptions_.logFile_);
// AddStoredOption("tech:logfile logfile",
// "Log file name.",
// storedOptions_.logFile_);

AddStoredOption("tech:solver solver",
"Underlying AMPL solver.",
storedOptions_.solver_);

AddStoredOption("tech:solver_options solver_options slv_opts",
"Underlying solver options.",
storedOptions_.solver_options_);

/// Enforce time limit?
// AddSolverOption("lim:time timelim timelimit time_limit",
// "Limit on solve time (in seconds; default: 1e+20).",
// "limits/time", 0.0, 1e+20);


/// Custom infinity value?
// AddSolverOption("num:infinity infinity",
// "Values larger than this are considered infinity (default: 1e+20)",
// "numerics/infinity", 1e+10, DBL_MAX);
Expand Down
17 changes: 8 additions & 9 deletions solvers/mp2nl/mp2nlbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class MP2NLBackend :
* MULTISOL support
* No API, see ReportIntermediateSolution()
**/
ALLOW_STD_FEATURE(MULTISOL, true)
ALLOW_STD_FEATURE(MULTISOL, false)

/**
* Get/Set AMPL var/con statii
Expand Down Expand Up @@ -84,7 +84,7 @@ class MP2NLBackend :
/**
* EXPORT PROBLEM
**/
ALLOW_STD_FEATURE(WRITE_PROBLEM, true)
ALLOW_STD_FEATURE(WRITE_PROBLEM, false)
void DoWriteProblem(const std::string& name) override;


Expand All @@ -93,15 +93,15 @@ class MP2NLBackend :
**/
// return MIP gap
// (adds option mip:return_gap)
ALLOW_STD_FEATURE(RETURN_MIP_GAP, true)
ALLOW_STD_FEATURE(RETURN_MIP_GAP, false)
double MIPGap() override;
double MIPGapAbs() override;
/**
* Get MIP dual bound
**/
// return the best dual bound value
// (adds option mip:bestbound)
ALLOW_STD_FEATURE(RETURN_BEST_DUAL_BOUND, true)
ALLOW_STD_FEATURE(RETURN_BEST_DUAL_BOUND, false)
double BestDualBound() override;

/////////////////////////// Model attributes /////////////////////////
Expand Down Expand Up @@ -162,11 +162,10 @@ class MP2NLBackend :
private:
/// These options are stored in the class
struct Options {
std::string logFile_, paramRead_;
int concurrent_ = 0;
int heuristics_ = 0;
int cuts_ = 0;
int presolvings_ = 0;
std::string solver_,
solver_options_;
std::string logFile_,
nlstub_;
int outlev_ = 0;
};
Options storedOptions_;
Expand Down
88 changes: 86 additions & 2 deletions solvers/mp2nl/mp2nlcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,96 @@
#include <vector>
#include <string>

#include "mp/arrayref.h"
#include "mp/backend-to-model-api.h"

#include "mp/format.h"


namespace mp {


/// interface for quesry callbacks
class MP2NLSolverQueryCallbacks {
public:
/// Virtual destruct
virtual ~MP2NLSolverQueryCallbacks() { }

/// ...
};


/// MP2NLSolverNLParams
struct MP2NLSolverNLParams {
/// NL format text mode?
int if_nl_text_ {};
/// In text mode, comments?
int if_nl_comments_ {};
/// Custom stub file?
const char* stub_file_ {};
};


/// Interface for NLSolver
class MP2NLSolverIntf {
public:
/// Virtual destruct
virtual ~MP2NLSolverIntf() { }

/// Provide query callback (e.g., for suffixes)
void ProvideQuaryCallbacks(MP2NLSolverQueryCallbacks& qc)
{ p_nlsq_ = &qc; }

void ProvideNLParams(MP2NLSolverNLParams prm) { prm_ = prm; }

/// Solve
virtual void Solve(const char* solver, const char* sopts) = 0;

/// AMPL solve result code
virtual int GetSolveResult() const = 0;

/// Solve result message or error message
virtual const char* GetSolveMessage() const = 0;

/// Number of backspaces to print
/// if printing the solve message right here,
/// or skip so many symbols first.
virtual int GetSolveMessageNbs() const = 0;

/// Stub file used
virtual const char* GetFileStub() const = 0;

/// Objno used.
/// @note AMPL .sol file does not provide
/// objective values, only in the solve message if at all.
virtual int GetObjnoUsed() const = 0;

/// Primal solution
virtual ArrayRef<double> GetX() const = 0;

/// Dual solution
virtual ArrayRef<double> GetY() const = 0;

/// @todo + Suffixes... Pull or push?
/// ..
protected:
MP2NLSolverQueryCallbacks* GetCallbacks()
{ assert(p_nlsq_); return p_nlsq_; }
const MP2NLSolverNLParams& GetParams() const { return prm_; }
MP2NLSolverNLParams& GetParams() { return prm_; }
private:
MP2NLSolverQueryCallbacks* p_nlsq_ {};
MP2NLSolverNLParams prm_ {};
};


/// Information shared by both
/// `ScipBackend` and `ScipModelAPI`
/// `MP2NLBackend` and `MP2NLModelAPI`
struct MP2NLCommonInfo {

/// MP2NLSolver
MP2NLSolverIntf* p_nlsi_ {};
/// Query cb
MP2NLSolverQueryCallbacks* p_qc_ {};
private:
};

Expand All @@ -30,6 +109,11 @@ class MP2NLCommon :
void OpenSolver();
void CloseSolver();

const MP2NLSolverIntf& GetNLSolver() const
{ assert(p_nlsi_); return *p_nlsi_; }
MP2NLSolverIntf& GetNLSolver()
{ assert(p_nlsi_); return *p_nlsi_; }

int NumLinCons() const;
int NumVars() const;
int NumObjs() const;
Expand Down
Loading

0 comments on commit 3810e9b

Please sign in to comment.