Skip to content

Commit

Permalink
Solution check warnings -> solve_msg #200
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Aug 22, 2023
1 parent 576cf27 commit a53f9e4
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 27 deletions.
9 changes: 8 additions & 1 deletion include/mp/backend-std.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ class StdBackend :
virtual void Report() {
ReportResults();
// if (verbose_mode())
PrintWarnings();
// if (!ampl_flag()) // otherwise to solve_message
// PrintWarnings();
if ( timing() )
PrintTimingInfo();
}
Expand Down Expand Up @@ -380,6 +381,9 @@ class StdBackend :
objIntermSol_.second = obj_value;
}
writer.write("\n");
auto wrn = GetWarnings();
if (wrn.size())
writer.write("\n{}", wrn);
if (round() && MP_DISPATCH(IsMIP()))
RoundSolution(sol.primal, writer);
HandleFeasibleSolution(SolveCode(), writer.c_str(),
Expand Down Expand Up @@ -448,6 +452,9 @@ class StdBackend :
solution_stub(), solution_stub(),
kIntermSol_);
}
auto wrn = GetWarnings();
if (wrn.size())
writer.write("\n{}", wrn);
/// Even without a feasible solution, we can have duals/suffixes
HandleSolution(SolveCode(), writer.c_str(),
sol.primal.empty() ? 0 : sol.primal.data(),
Expand Down
32 changes: 20 additions & 12 deletions include/mp/flat/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,9 @@ class FlatConverter :
MP_RAISE_WITH_CODE(520, // numeric error
chk.GetReport());
else
AddWarning("SolutionCheck", chk.GetReport());
AddWarning(
"SolutionCheck", chk.GetReport(),
true); // replace for multiple solutions
}
return !chk.HasAnyViols();
}
Expand Down Expand Up @@ -665,13 +667,17 @@ class FlatConverter :
"(sol:chk:feastol={}, sol:chk:inttol={}):\n",
options_.solfeastol_, options_.solinttol_);
Gen1Viol(chk.VarViolBnds().at(0), wrt,
" - {} original variable(s) violate bounds, max by {}");
" - {} original variable(s) violate bounds,\n"
" max by {}");
Gen1Viol(chk.VarViolBnds().at(1), wrt,
" - {} auxiliary variable(s) violate bounds, max by {}");
" - {} auxiliary variable(s) violate bounds,\n"
" max by {}");
Gen1Viol(chk.VarViolIntty().at(0), wrt,
" - {} original variable(s) violate integrality, max by {}");
" - {} original variable(s) violate integrality,\n"
" max by {}");
Gen1Viol(chk.VarViolIntty().at(1), wrt,
" - {} auxiliary variable(s) violate integrality, max by {}");
" - {} auxiliary variable(s) violate integrality,\n"
" max by {}");
}
GenConViol(chk.ConViolAlg(), wrt, "Algebraic");
GenConViol(chk.ConViolLog(), wrt, "Logical");
Expand All @@ -680,7 +686,7 @@ class FlatConverter :
"(sol:chk:feastol={})\n",
options_.solfeastol_);
Gen1Viol(chk.ObjViols(), wrt,
" - {} objective value(s) violated, max by {}");
" - {} objective value(s) violated,\n max by {}");
}
chk.SetReport( wrt.str() );
}
Expand All @@ -705,15 +711,15 @@ class FlatConverter :
Gen1Viol(cva.second.at(0), wrt,
" - {} original constraint(s) of type '"
+ std::string(cva.first)
+ "' violate bounds, max by {}");
+ "' violate bounds,\n max by {}");
Gen1Viol(cva.second.at(1), wrt,
" - {} reformulated constraint(s) of type '"
+ std::string(cva.first)
+ "' violate bounds, max by {}");
+ "' violate bounds,\n max by {}");
Gen1Viol(cva.second.at(2), wrt,
" - {} auxiliary constraint(s) of type '"
" - {} final constraint(s) of type '"
+ std::string(cva.first)
+ "' violate bounds, max by {}");
+ "' violate bounds,\n max by {}");
}
}
}
Expand Down Expand Up @@ -1157,8 +1163,10 @@ class FlatConverter :
/// AddWarning.
/// @param key: warning category
/// @param msg: detailed message
void AddWarning(std::string key, std::string msg) {
GetEnv().AddWarning(std::move(key), std::move(msg));
void AddWarning(
std::string key, std::string msg, bool replace=false) {
GetEnv().AddWarning(
std::move(key), std::move(msg), replace);
}


Expand Down
9 changes: 7 additions & 2 deletions include/mp/solver-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,11 @@ class BasicSolver : private ErrorHandler,
/// Add a warning.
/// @param key: warning category
/// @param msg: detailed message
void AddWarning(std::string key, std::string msg);
void AddWarning(
std::string key, std::string msg, bool replace=false);

/// Get warnings as string
std::string GetWarnings() const;

/// Print warnings
void PrintWarnings();
Expand Down Expand Up @@ -397,7 +401,8 @@ class BasicSolver : private ErrorHandler,
std::pair<int, std::string> >; // total number, description of the 1st

/// Get warnings map
WarningsMap& GetWarnings() { return warnings_; }
const WarningsMap& GetWarningsMap() const { return warnings_; }
WarningsMap& GetWarningsMap() { return warnings_; }

/// Stringify a WarningsMap entry
static std::string ToString(const WarningsMap::value_type& wrn);
Expand Down
2 changes: 1 addition & 1 deletion src/sol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void mp::internal::WriteMessage(fmt::BufferedFile &file, const char *message) {
++line_end;
// Replace an empty line with a line containing a single space
// because an empty line indicates the end of message.
if (line_end == line_start + 1)
if (line_end == line_start)
std::fputc(' ', file.get());
else
std::fwrite(line_start, 1, line_end - line_start, file.get());
Expand Down
30 changes: 19 additions & 11 deletions src/solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -688,24 +688,32 @@ SolverOptionManager::~SolverOptionManager() {
std::for_each(options_.begin(), options_.end(), Deleter());
}

void BasicSolver::AddWarning(std::string key, std::string msg) {
auto& v = GetWarnings()[ std::move(key) ];
if (!v.first++) // only remember the 1st detailed message
void BasicSolver::AddWarning(
std::string key, std::string msg, bool replace) {
auto& v = GetWarningsMap()[ std::move(key) ];
if (!v.first++ // only remember the 1st detailed message
|| replace) // unless asked to replace
v.second = std::move(msg);
}

void BasicSolver::PrintWarnings() {
if (GetWarnings().size()) {
Print("\n------------ WARNINGS ------------\n");
for (const auto& e: GetWarnings())
Print(ToString(e));
std::string BasicSolver::GetWarnings() const {
if (GetWarningsMap().size()) {
std::string wrn = "------------ WARNINGS ------------\n";
for (const auto& e: GetWarningsMap())
wrn += ToString(e) + '\n';
return wrn;
}
return "";
}

void BasicSolver::PrintWarnings() {
Print('\n' + GetWarnings());
}

std::string BasicSolver::ToString(
const WarningsMap::value_type& wrn) {
return fmt::format(
"WARNING. {} case(s) of \"{}\". The first of them:\n {}\n",
"WARNING. {} case(s) of \"{}\". One of them:\n {}",
wrn.second.first, wrn.first, wrn.second.second);
}

Expand Down Expand Up @@ -1168,8 +1176,8 @@ const char* const * AMPLSGetMessages(AMPLS_MP_Solver* slv) {
pchar_vec.clear();

/// Add Backend warnings
for (const auto& wrn: be->GetWarnings())
msg_wrn.push_back(mp::BasicSolver::ToString(wrn));
for (const auto& wrn: be->GetWarningsMap())
msg_wrn.push_back(mp::BasicSolver::ToString(wrn) + '\n');

/// Add Backend warnings
for (const auto& wrn: msg_wrn)
Expand Down

0 comments on commit a53f9e4

Please sign in to comment.