Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIPBackend: more changes #137

Merged
merged 9 commits into from
May 5, 2021
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,20 @@ add_prefix(MP_HEADERS include/mp/
arrayref.h basic-expr-visitor.h clock.h common.h error.h expr.h
expr-visitor.h nl.h nl-reader.h option.h os.h problem.h problem-builder.h
rstparser.h safeint.h sol.h solver.h suffix.h)

add_prefix(MP_CONVERT_HEADERS include/mp/convert/
affine_expr.h backend.h basic_constr.h basic_converters.h
constraint_keeper.h context.h converter_flat.h converter_flat_query.h
converter_query.h convert_functional.h eexpr.h interface_app.h
mip_backend.h model.h model_adapter.h preprocess.h
quad_expr.h std_constr.h std_obj.h suffix.h MIP/mp2mip.h)

set(MP_SOURCES )
add_prefix(MP_SOURCES src/
clock.cc expr.cc expr-writer.h nl-reader.cc option.cc os.cc
problem.cc rstparser.cc sol.cc solver.cc solver-c.h sp.h sp.cc)

add_mp_library(mp ${MP_HEADERS} ${MP_SOURCES} ${MP_EXPR_INFO_FILE}
add_mp_library(mp ${MP_HEADERS} ${MP_CONVERT_HEADERS} ${MP_SOURCES} ${MP_EXPR_INFO_FILE}
COMPILE_DEFINITIONS MP_DATE=${MP_DATE} MP_SYSINFO="${MP_SYSINFO}"
INCLUDE_DIRECTORIES src include OBJECT_LIBRARIES format)
set_target_properties(mp PROPERTIES
Expand Down
64 changes: 26 additions & 38 deletions include/mp/convert/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include "mp/convert/model.h"
#include "mp/convert/model_adapter.h"

#define ALLOW_STD_FEATURE( name, val ) \
constexpr bool AllowFeature__##name() { return val; }
#define IMPL_HAS_STD_FEATURE( name ) MP_DISPATCH( AllowFeature##name() )

namespace mp {

/// Basic backend wrapper.
Expand Down Expand Up @@ -109,7 +113,7 @@ class BasicBackend :
name, version ) );
}


///////////////////////////// MODEL MANIP //////////////////////////////
using Model = BasicModel<>;

using Variable = typename Model::Variable;
Expand Down Expand Up @@ -191,15 +195,9 @@ class BasicBackend :
throw MakeUnsupportedError("BasicBackend::AddLinearConstraint");
}

/// Solution values. The vectors are emptied if not available
void DualSolution(std::vector<double>& pi) { pi.clear(); }
void VarStatii(std::vector<int>& stt) { stt.clear(); }
void ConStatii(std::vector<int>& stt) { stt.clear(); }



////////////////////////////////////////////////////////////////////////////
////////////////////// PROCESS LOGIC ////////////////////////////
/////////////////////////// BASIC PROCESS LOGIC ////////////////////////////
////////////////////////////////////////////////////////////////////////////

void SolveAndReport() {
Expand All @@ -208,7 +206,7 @@ class BasicBackend :
MP_DISPATCH( WrapupSolve() );

MP_DISPATCH( ObtainSolutionStatus() );
MP_DISPATCH( CalculateDerivedResults() );
MP_DISPATCH( CalculateAndReportDerivedResults() );
MP_DISPATCH( ReportSolution() );
if (MP_DISPATCH( timing() ))
MP_DISPATCH( PrintTimingInfo() );
Expand All @@ -227,7 +225,7 @@ class BasicBackend :
solve_status = MP_DISPATCH(
ConvertSolutionStatus(*MP_DISPATCH( interrupter() ), solve_code) );
}
void CalculateDerivedResults() { }
void CalculateAndReportDerivedResults() { }

void ReportSolution() {
MP_DISPATCH( ReportSuffixes() );
Expand All @@ -239,40 +237,35 @@ class BasicBackend :
MP_DISPATCH( ReportCustomSuffixes() );
}

///////////////////////////// STANDARD SUFFIXES ////////////////////////////
const SuffixDef<int> suf_varstatus = { "sstatus", suf::VAR | suf::OUTPUT };
const SuffixDef<int> suf_constatus = { "sstatus", suf::CON | suf::OUTPUT };

void ReportStandardSuffixes() {
std::vector<int> stt;
MP_DISPATCH( VarStatii(stt) );
DeclareAndReportIntSuffix(suf_varstatus, stt);
MP_DISPATCH( ConStatii(stt) );
DeclareAndReportIntSuffix(suf_constatus, stt);
}
void ReportStandardSuffixes() { }

void ReportCustomSuffixes() { }

void ReportPrimalDualValues() {
double obj_value = std::numeric_limits<double>::quiet_NaN();
std::vector<double> solution, dual_solution;

fmt::MemoryWriter writer;
writer.write("{}: {}", MP_DISPATCH( long_name() ), solve_status);
if (solve_code < sol::INFEASIBLE) {
MP_DISPATCH( PrimalSolution(solution) );

solution = MP_DISPATCH( PrimalSolution() );
obj_value = MP_DISPATCH( ObjectiveValue() );
if (MP_DISPATCH( NumberOfObjectives() ) > 0) {
writer.write("; objective {}",
MP_DISPATCH( FormatObjValue(MP_DISPATCH( ObjectiveValue() )) ));
MP_DISPATCH( FormatObjValue(obj_value) ));
}
}
writer.write("\n");

MP_DISPATCH( DualSolution(dual_solution) );

dual_solution = MP_DISPATCH( DualSolution() ); // Try in any case
HandleSolution(solve_code, writer.c_str(),
solution.empty() ? 0 : solution.data(),
dual_solution.empty() ? 0 : dual_solution.data(), obj_value);
}

/// Dual solution. Returns empty if not available
std::vector<double> DualSolution() { return {}; }

void PrintTimingInfo() {
double output_time = GetTimeAndReset(stats.time);
MP_DISPATCH( Print("Setup time = {:.6f}s\n"
Expand All @@ -282,7 +275,6 @@ class BasicBackend :
}

/////////////////////////////// SERVICE STUFF ///////////////////////////////////
///
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////// SOLUTION STATUS /////////////////////////////////
Expand All @@ -296,13 +288,6 @@ class BasicBackend :
return sol::NOT_CHECKED!=solve_code;
}

int solve_code=sol::NOT_CHECKED;
std::string solve_status;

/////////////////////////////// STORING SOLUTON AND STATS ///////////////////////
double obj_value = std::numeric_limits<double>::quiet_NaN();
std::vector<double> solution, dual_solution;

struct Stats {
steady_clock::time_point time;
double setup_time;
Expand All @@ -311,6 +296,7 @@ class BasicBackend :
Stats stats;


/////////////////////////////// SOME MATHS ////////////////////////////////
static bool float_equal(double a, double b) { // ??????
return std::fabs(a-b) < 1e-8*std::max(std::fabs(a), std::fabs(b));
}
Expand All @@ -323,7 +309,6 @@ class BasicBackend :
static double MinusInfinity() { return -Infinity(); }

public:

using Solver::add_to_long_name;
using Solver::add_to_version;
using Solver::set_option_header;
Expand All @@ -346,10 +331,14 @@ class BasicBackend :
GetCQ().DeclareAndReportDblSuffix(suf, values);
}

private:
///////////////////////// STORING SOLUTON STATUS //////////////////////
int solve_code=sol::NOT_CHECKED;
std::string solve_status;

///////////////////////////// OPTIONS /////////////////////////////////
protected:

protected:
///////////////////////////// OPTIONS /////////////////////////////////
using Solver::AddOption;

template <class Value>
Expand Down Expand Up @@ -436,7 +425,6 @@ class BasicBackend :

};


} // namespace mp

#endif // BACKEND_H_
145 changes: 95 additions & 50 deletions include/mp/convert/mip_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,51 @@ class MIPBackend :
{
using BaseBackend = BasicBackend<Impl>;

struct Options {
int exportIIS_;
int returnMipGap_;
};
Options mipStoredOptions_;

public:
/////////////////// STD FEATURE FLAGS //////////////////////
//////// Disable optional std features by default //////////
////////////////////////////////////////////////////////////
ALLOW_STD_FEATURE( IIS, false )

////////////////////////////////////////////////////////////
//// Override in the Impl for standard MIP calculations ////
////////////////////////////////////////////////////////////
/**
* Get AMPL var statii
**/
std::vector<int> VarStatii() { return {}; }
std::vector<int> ConStatii() { return {}; }
/**
* Compute the IIS and relevant values
**/
void ComputeIIS();
/**
* Get IIS values for constraints / vars
**/
std::vector<int> ConsIIS() { return {}; }
std::vector<int> VarsIIS() { return {}; }
/**
* Get MIP Gap
**/
double MIPGap() { throw std::runtime_error("Not implemented"); }


////////////////////////////////////////////////////////////
/////////////////// MIP Backend options ////////////////////
////////////////////////////////////////////////////////////
void InitOptions() {
BaseBackend::InitOptions();
MP_DISPATCH( InitMIPOptions() );
}

using BaseBackend::AddStoredOption;
void InitMIPOptions() {
this->AddStoredOption("iisfind",
"Whether to find and export the IIS. "
"Default = 0 (don't export).",
mipStoredOptions_.exportIIS_);
this->AddStoredOption("return_mipgap",
if (IMPL_HAS_STD_FEATURE( IIS ))
AddStoredOption("iisfind",
"Whether to find and export the IIS. "
"Default = 0 (don't export).",
mipStoredOptions_.exportIIS_);
AddStoredOption("return_mipgap",
"Whether to return mipgap suffixes or include mipgap values\n\
(|objectve - best_bound|) in the solve_message: sum of\n\
1 = return relmipgap suffix (relative to |obj|);\n\
Expand All @@ -68,60 +94,79 @@ class MIPBackend :
mipStoredOptions_.returnMipGap_);
}

void CalculateDerivedResults() {
BasicBackend<Impl>::CalculateDerivedResults();

////////////////////////////////////////////////////////////////////////////
/////////////////////// MIP specific derived calculations //////////////////
////////////////////////////////////////////////////////////////////////////
void CalculateAndReportDerivedResults() {
BaseBackend::CalculateAndReportDerivedResults();
CalculateAndReportDerivedResults_MIP();
}

void CalculateAndReportDerivedResults_MIP() {
CalculateAndReportIIS();
CalculateAndReportMIPGap();
}

using BaseBackend::DeclareAndReportIntSuffix;
using BaseBackend::DeclareAndReportDblSuffix;

void CalculateAndReportIIS() {
if (MP_DISPATCH( IsProblemInfOrUnb() ) &&
mipStoredOptions_.exportIIS_)
mipStoredOptions_.exportIIS_) {
MP_DISPATCH( ComputeIIS() );
if (mipStoredOptions_.returnMipGap_)
MP_DISPATCH( ComputeMipGap() );

DeclareAndReportIntSuffix(sufIISCon, MP_DISPATCH(ConsIIS()));
DeclareAndReportIntSuffix(sufIISVar, MP_DISPATCH(VarsIIS()));
}
}

// Override for standard MIP calculations
/**
* Compute the IIS and relevant values
**/
void ComputeIIS();
/**
* Get IIS values for constraints
**/
void ConsIIS(std::vector<int>& stt) { stt.clear(); }
/**
* Get IIS values for variables
**/
void VarsIIS(std::vector<int>& stt) { stt.clear(); }
void CalculateAndReportMIPGap() {
if (mipStoredOptions_.returnMipGap_) {
MP_DISPATCH( ComputeMipGap() );

std::vector<double> dbl(1, MP_DISPATCH( MIPGap() ));
DeclareAndReportDblSuffix(sufRelMipGapObj, dbl);
DeclareAndReportDblSuffix(sufRelMipGapProb, dbl);
}
}

void ComputeMipGap() {}
double MIPGap() { throw std::runtime_error("Not implemented"); }

void ReportStandardSuffixes() {
BasicBackend<Impl>::ReportStandardSuffixes();
ReportStadardMIPSuffixes();
}

void ReportStadardMIPSuffixes() {
DeclareAndReportIntSuffix(suf_varstatus,
MP_DISPATCH( VarStatii() ));
DeclareAndReportIntSuffix(suf_constatus,
MP_DISPATCH( ConStatii() ));
}

private:
struct Options {
int exportIIS_;
int returnMipGap_;
};
Options mipStoredOptions_;


//////////////////////////////////////////////////////////////////////////////
//////////////////////////// STANDARD SUFFIXES ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////
const SuffixDef<int> suf_varstatus = { "sstatus", suf::VAR | suf::OUTPUT };
const SuffixDef<int> suf_constatus = { "sstatus", suf::CON | suf::OUTPUT };

const SuffixDef<int> sufIISCon = { "iis", suf::CON | suf::OUTPUT };
const SuffixDef<int> sufIISVar = { "iis", suf::VAR | suf::OUTPUT };

const SuffixDef<double> sufRelMipGapObj = { "relmipgap", suf::OBJ | suf::OUTPUT };
const SuffixDef<double> sufRelMipGapProb = { "relmipgap", suf::PROBLEM | suf::OUTPUT };

void ReportStandardSuffixes() {
BasicBackend<Impl>::ReportStandardSuffixes();
std::vector<int> stt;
std::vector<double> dbl;
if (mipStoredOptions_.exportIIS_)
{
MP_DISPATCH(ConsIIS(stt));
this->DeclareAndReportIntSuffix(sufIISCon, stt);
MP_DISPATCH(VarsIIS(stt));
this->DeclareAndReportIntSuffix(sufIISVar, stt);
}
if (mipStoredOptions_.returnMipGap_)
{
dbl.clear();
dbl.push_back(MP_DISPATCH( MIPGap() ));
this->DeclareAndReportDblSuffix(sufRelMipGapObj, dbl);
this->DeclareAndReportDblSuffix(sufRelMipGapProb, dbl);
}
}

};

} // namespace mp

#endif // MIPBACKEND_H_
Loading