Skip to content

Commit

Permalink
SolCheck (Idealistic) #200
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Aug 30, 2023
1 parent 0a0e96f commit 9892040
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 84 deletions.
23 changes: 13 additions & 10 deletions include/mp/flat/constr_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,20 @@ double ComputeViolation(
const CustomFunctionalConstraint<Args, Params, NumOrLogic, Id>& c,
const VarVec& x) {
auto resvar = c.GetResultVar();
auto viol = x[resvar] - ComputeValue(c, x);
switch (c.GetContext().GetValue()) {
case Context::CTX_MIX:
return std::fabs(viol);
case Context::CTX_POS:
return viol;
case Context::CTX_NEG:
return -viol;
default:
return INFINITY;
if (!x.recomp_vals()) { // solver's var values: normal check
auto viol = x[resvar] - ComputeValue(c, x);
switch (c.GetContext().GetValue()) {
case Context::CTX_MIX:
return std::fabs(viol);
case Context::CTX_POS:
return viol;
case Context::CTX_NEG:
return -viol;
default:
return INFINITY;
}
}
return x.bounds_viol(resvar); // recomputed vars: bounds viol
}


Expand Down
7 changes: 6 additions & 1 deletion include/mp/flat/constr_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@

/**
* Evaluations and violations
* of (mainly functional) constraints
* of (mainly functional) constraints.
*
* For most evaluators, it's enough to supply
* a simple vector x.
* For some, it needs to be an object with
* extra API.
*/

#include <cmath>
Expand Down
85 changes: 58 additions & 27 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ template <class VarVec>
class VarInfoImpl {
public:
/// Constructor
VarInfoImpl(double ft,
VarInfoImpl(double ft, bool recomp_vals,
VarVec x,
ArrayRef<var::Type> type,
ArrayRef<double> lb, ArrayRef<double> ub,
const char* sol_rnd, const char* sol_prec)
: feastol_(ft), x_(std::move(x)),
type_(type), lb_(lb), ub_(ub) {
: feastol_(ft), recomp_vals_(recomp_vals),
x_(std::move(x)), type_(type), lb_(lb), ub_(ub) {
assert((int)x_.size()>=(int)type_.size()); // feasrelax can add more
assert(type_.size()==lb_.size());
assert(type_.size()==ub_.size());
Expand Down Expand Up @@ -157,8 +157,16 @@ class VarInfoImpl {
bool is_at_ub(int i) const
{ return -((*this)[i] - ub_[i]) <= feastol(); }

/// Bounds violation
double bounds_viol(int i) const {
assert(i>=0 && i<(int)type_.size());
return std::max(lb_[i] - x_[i], x_[i] - ub_[i]);
}

/// Feasibility tolerance
double feastol() const { return feastol_; }
/// Using recomputed auxiliary vars?
bool recomp_vals() const { return recomp_vals_; }
/// sol_rnd as string
std::string solution_round() const
{ return sol_rnd_ < 100 ? std::to_string(sol_rnd_) : ""; }
Expand Down Expand Up @@ -189,6 +197,7 @@ class VarInfoImpl {

private:
double feastol_;
bool recomp_vals_; // variables are recomputed

VarVec x_; // can be rounded, recomputed, etc.
const ArrayRef<var::Type> type_;
Expand All @@ -215,19 +224,22 @@ using VarInfoStatic = VarInfoImpl<VarVecStatic>;

/// Solution check data
struct SolCheck {
/// Construct
/// Construct.
/// @param chkmode: can be subset of 1+2+4+8+16
SolCheck(ArrayRef<double> x,
const pre::ValueMapDbl& duals,
ArrayRef<double> obj,
ArrayRef<var::Type> vtype,
ArrayRef<double> lb, ArrayRef<double> ub,
double feastol, double inttol,
const char* sol_rnd, const char* sol_prec,
bool reportBridged)
: x_(feastol, x, vtype, lb, ub, sol_rnd, sol_prec),
bool recomp_vals, int chk_mode)
: x_(feastol, recomp_vals,
x, vtype, lb, ub, sol_rnd, sol_prec),
y_(duals), obj_(obj),
feastol_(feastol), inttol_(inttol),
reportBridgedCons_(reportBridged) { }
fRecomputedVals_(recomp_vals),
check_mode_(chk_mode) { }
/// Any violations?
bool HasAnyViols() const
{ return HasAnyConViols() || HasAnyObjViols(); }
Expand All @@ -251,8 +263,11 @@ struct SolCheck {
double x(int i) const { return x_[i]; }
/// Feasibility tolerance
double GetFeasTol() const { return feastol_; }
/// Report reformulated constraints?
bool RepRefCons() const { return reportBridgedCons_; }

/// Using recomputed aux vars?
bool if_recomputed() const { return fRecomputedVals_; }
/// Check mode
int check_mode() const { return check_mode_; }

/// Var bnd violations
ViolSummArray<2>& VarViolBnds() { return viol_var_bnds_; }
Expand Down Expand Up @@ -282,7 +297,8 @@ struct SolCheck {
ArrayRef<double> obj_;
double feastol_;
double inttol_;
bool reportBridgedCons_ = false;
bool fRecomputedVals_;
int check_mode_;

std::string report_;

Expand Down Expand Up @@ -617,9 +633,9 @@ class ConstraintKeeper final
/// Add a pre-constructed constraint (or just arguments)
/// @return index of the new constraint
template <class... Args>
int AddConstraint(Args&&... args)
int AddConstraint(int d, Args&&... args)
{
cons_.emplace_back( std::move(args)... );
cons_.emplace_back( d, std::move(args)... );
return cons_.size()-1;
}

Expand Down Expand Up @@ -725,7 +741,11 @@ class ConstraintKeeper final

/// Container for a single constraint
struct Container {
Container(Constraint&& c) noexcept : con_(std::move(c)) { }
Container(int d, Constraint&& c) noexcept
: con_(std::move(c)), depth_(d) { }

/// Depth in redef tree
int GetDepth() const { return depth_; }

/// Bridged (reformulated or just unused.)
/// If only reformulated, can still be checked
Expand All @@ -743,6 +763,7 @@ class ConstraintKeeper final
}

Constraint con_;
int depth_ = 0;
bool is_bridged_ = false;
bool is_unused_ = false;
};
Expand Down Expand Up @@ -787,7 +808,7 @@ class ConstraintKeeper final
/// @param i constraint index, needed for bridging
void ConvertConstraint(Container& cnt, int i) {
assert(!cnt.IsBridged());
GetConverter().RunConversion(cnt.con_, i);
GetConverter().RunConversion(cnt.con_, i, cnt.GetDepth());
MarkAsBridged(cnt, i);
}

Expand Down Expand Up @@ -859,19 +880,29 @@ class ConstraintKeeper final
const auto& x = chk.x_ext();
ViolSummArray<3>* conviolarray {nullptr};
for (int i=(int)cons_.size(); i--; ) {
if (!cons_[i].IsUnused()
&& (chk.RepRefCons() || !cons_[i].IsBridged())) {
auto viol = cons_[i].con_.ComputeViolation(x);
if (viol > chk.GetFeasTol()) {
if (!conviolarray)
conviolarray =
&conviolmap[GetShortTypeName()];
/// index==2 <==> solver-side constraint.
/// TODO also original NL constraints (index 0)
int index = cons_[i].IsBridged() ? 1 : 2;
assert(index < (int)conviolarray->size());
(*conviolarray)[index].CountViol(
viol, cons_[i].con_.name());
if (!cons_[i].IsUnused()) {
int c_class = 0; // class of this constraint
if (!cons_[i].IsBridged())
c_class |= 8; // solver-side constraint
if (!cons_[i].GetDepth())
c_class |= 2; // top-level
if (!c_class)
c_class = 4; // intermediate
if (c_class & chk.check_mode()) {
auto viol = cons_[i].con_.ComputeViolation(x);
if (viol > chk.GetFeasTol()) {
if (!conviolarray)
conviolarray = // lazy map access
&conviolmap[GetShortTypeName()];
/// index==0,1,2: original, interm, solver-side
/// If both orig and solver, report as orig
int index = (c_class & 2) ? 0
: (c_class & 8)
? 2 : 1;
assert(index < (int)conviolarray->size());
(*conviolarray)[index].CountViol(
viol, cons_[i].con_.name());
}
}
}
}
Expand Down
Loading

0 comments on commit 9892040

Please sign in to comment.