Skip to content

Commit

Permalink
Compact sol check output #200 #227
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Jan 9, 2024
1 parent 9495e1d commit 8b2c27c
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 45 deletions.
2 changes: 1 addition & 1 deletion include/mp/flat/redef/MIP/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

/**
* Redefinition for MIP of
* <cond> ==> <constr1> [ else <constr2> ]
* (cond) ==> (constr1) [ else (constr2) ]
*/

#include "mp/flat/redef/redef_base.h"
Expand Down
73 changes: 32 additions & 41 deletions include/mp/flat/sol_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class SolutionChecker {

/// Check single unpostsolved solution.
/// @param x_back: solution vector from realistic mode.
/// It can be changed by AMPL solution_... options.
/// It can be changed by the :round and :prec options.
/// Its auxiliary vars are compared
/// with recomputed expression values.
bool DoCheckSol(
Expand Down Expand Up @@ -194,35 +194,28 @@ class SolutionChecker {
void GenerateViolationsReport(
SolCheck& chk, bool f_idealistic) {
fmt::MemoryWriter wrt;
if (chk.HasAnyViols())
wrt.write(
" [ sol:chk:feastol={}, :feastolrel={}, :inttol={},\n"
" :round='{}', :prec='{}' ]\n",
MPCD( sol_feas_tol() ), MPCD( sol_feas_tol_rel() ),
MPCD( sol_int_tol() ),
chk.x_ext().solution_round(),
chk.x_ext().solution_precision());
if (chk.HasAnyViols()) {
wrt.write("Type MaxAbs [Name] MaxRel [Name]\n");
}
if (chk.HasAnyConViols()) {
Gen1Viol(chk.VarViolBnds().at(0), wrt, true,
" - {} variable(s) violate bounds");
"variable bounds");
Gen1Viol(chk.VarViolBnds().at(1), wrt, true,
" - {} auxiliary variable(s) violate bounds");
"aux var bounds");
Gen1Viol(chk.VarViolIntty().at(0), wrt, true,
" - {} variable(s) violate integrality");
"variable integrality");
Gen1Viol(chk.VarViolIntty().at(1), wrt, true,
" - {} auxiliary variable(s) violate integrality");
"aux var integrality");
}
GenConViol(chk.ConViolAlg(), wrt, 0);
GenConViol(chk.ConViolLog(), wrt, 1);
if (chk.HasAnyObjViols()) {
wrt.write("Objective value violations:\n");
Gen1Viol(chk.ObjViols(), wrt, true,
" - {} objective value(s) violated");
"objective(s)");
}
if (f_idealistic && chk.HasAnyViols())
wrt.write(
"AMPL may evaluate constraints/objectives differently\n"
"than the solver, see mp.ampl.com/modeling-tools.html.");
"Documentation: mp.ampl.com/modeling-tools.html.");
chk.SetReport( wrt.str() );
}

Expand All @@ -231,58 +224,56 @@ class SolutionChecker {
/// the maximal violations.
void Gen1Viol(
const ViolSummary& vs, fmt::MemoryWriter& wrt,
bool f_max, const std::string& format) {
bool f_max, const std::string& type) {
if (vs.N_) {
wrt.write(format, vs.N_);
auto vmaxabs = Gen1ViolMax(
f_max, vs.epsAbsMax_, vs.nameAbs_, false);
// wrt.write(" {:16} {:<7}", type, vs.N_);
wrt.write(" {:17}", type);
auto vmaxabs = Gen1ViolMax( // true: 1 for logical
f_max, vs.epsAbsMax_, vs.nameAbs_);
auto vmaxrel = Gen1ViolMax(
f_max, vs.epsRelMax_, vs.nameRel_, true);
if (vmaxabs.size() || vmaxrel.size())
wrt.write(",\n {}", vmaxabs);
if (vmaxabs.size() && vmaxrel.size())
wrt.write(", ");
wrt.write("{}", vmaxrel);
f_max, vs.epsRelMax_, vs.nameRel_);
wrt.write(" {:14}", vmaxabs);
wrt.write(" {:14}", vmaxrel);
wrt.write("\n");
}
}

/// Stringify 1 maximal violation
std::string Gen1ViolMax(
bool f_max, double viol, const char* nm, bool relVsAbs) {
bool f_max, double viol, const char* nm) {
fmt::MemoryWriter wrt;
if (viol>0.0) {
if (f_max)
wrt.write("up to {:.0E} ({}",
viol, relVsAbs ? "rel" : "abs");
wrt.write("{:.0E}", viol);
if (nm && *nm != '\0') {
wrt.write(f_max ? ", " : "(");
wrt.write("item '{}')", nm);
} else if (f_max)
wrt.write(")");
wrt.write(f_max ? " [" : "[");
wrt.write("{}]", nm);
}
}
if (0 == wrt.size())
wrt.write("-");
return wrt.str();
}

/// std::string classnm = alg_log ? "Logical" : "Algebraic";
/// wrt.write(classnm + " expression violations:\n");
void GenConViol(
const std::map< std::string, ViolSummArray<3> >& cvmap,
fmt::MemoryWriter& wrt, int alg_log) {
std::string classnm = alg_log ? "Logical" : "Algebraic";
if (cvmap.size()) {
wrt.write(classnm + " expression violations:\n");
for (const auto& cva: cvmap) {
Gen1Viol(cva.second.at(0), wrt, !alg_log,
0==cva.first.compare(0, 4, ":lin")
? " - {} linear constraint(s)"
? "algebraic con(s)"
: 0==cva.first.compare(0, 5, ":quad")
? " - {} quadratic constraint(s)"
: " - {} constraint(s) of type '"
? "quadratic con(s)"
: "expr '"
+ std::string(cva.first) + "'");
Gen1Viol(cva.second.at(1), wrt, !alg_log,
" - {} intermediate auxiliary constraint(s) of type '"
"interm expr '"
+ std::string(cva.first) + "'");
Gen1Viol(cva.second.at(2), wrt, !alg_log,
" - {} final auxiliary constraint(s) of type '"
"final expr '"
+ std::string(cva.first) + "'");
}
}
Expand Down
2 changes: 1 addition & 1 deletion solvers/mosek/mosekbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ std::pair<int, std::string> MosekBackend::ConvertMOSEKStatus() {
case MSK_PRO_STA_PRIM_INFEAS:
return { sol::INFEASIBLE, "primal infeasible" + term_info };
case MSK_PRO_STA_DUAL_INFEAS:
return { sol::INF_OR_UNB, "dual infeasible" + term_info };
return { sol::LIMIT_INF_UNB, "dual infeasible" + term_info };
case MSK_PRO_STA_PRIM_AND_DUAL_INFEAS:
return
{ sol::INFEASIBLE, "primal and dual infeasible" + term_info };
Expand Down
4 changes: 2 additions & 2 deletions src/solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -748,8 +748,8 @@ SolverOptionManager::~SolverOptionManager() {
const char*
BasicSolver::GetSolCheckWarningKey(bool f_recomp) const {
return f_recomp
? "Solution Check (Idealistic)"
: "Solution Check";
? "Tolerance violations"
: "Tolerance violations (solver model)";
}

void BasicSolver::AddWarning(
Expand Down

0 comments on commit 8b2c27c

Please sign in to comment.