Skip to content

Commit

Permalink
Write flat constraints & objectives #232
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Mar 18, 2024
1 parent 17ed8f4 commit 145fbae
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 27 deletions.
34 changes: 34 additions & 0 deletions include/mp/flat/constr_algebraic.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,40 @@ using QuadConGE = QuadConRhs< 1>;
using QuadConGT = QuadConRhs< 2>;


void WriteModelItem(fmt::MemoryWriter& wrt, const LinTerms& lt,
const std::vector<std::string>& vnam);

void WriteModelItem(fmt::MemoryWriter& wrt, const QuadTerms& qt,
const std::vector<std::string>& vnam);

void WriteModelItem(fmt::MemoryWriter& wrt, const QuadAndLinTerms& qlt,
const std::vector<std::string>& vnam);

/// Write RangeCon without name.
template <class Writer, class Body>
inline void WriteModelItem(Writer& wrt,
const AlgebraicConstraint<Body, AlgConRange>& algc,
const std::vector<std::string>& vnam) {
const auto& rng = algc.GetRhsOrRange();
if (rng.lb() >= -DBL_MAX && rng.lb() < rng.ub())
wrt << rng.lb() << " <= ";
WriteModelItem(wrt, algc.GetBody(), vnam);
if (rng.lb() == rng.ub())
wrt << " == " << rng.lb();
else if (rng.ub() <= DBL_MAX)
wrt << " <= " << rng.ub();
}

/// Write RhsCon without name.
template <class Writer, class Body, int kind>
inline void WriteModelItem(Writer& wrt,
const AlgebraicConstraint<Body, AlgConRhs<kind> >& algc,
const std::vector<std::string>& vnam) {
const auto& rng = algc.GetRhsOrRange();
WriteModelItem(wrt, algc.GetBody(), vnam);
wrt << ' ' << rng.GetCmpStr() << ' ' << rng.rhs();
}

/// Write an algebraic constraint
template <class Body, class RhsOrRange>
inline void WriteJSON(JSONW jw,
Expand Down
71 changes: 71 additions & 0 deletions include/mp/flat/constr_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,66 @@ class CustomFunctionalConstraint :
Violation ComputeViolation(const VarVec& x) const;
};

/// Write flat expr/obj/con variables:
/// vector/array
template <class Writer, class Vec,
typename T = std::decay_t<
decltype(*begin(std::declval<Vec>()))> >
inline void WriteModelItem(
Writer& wrt, const Vec& v,
const std::vector<std::string>& vnam) {
static_assert (
std::is_integral_v<typename Vec::value_type>, "Variable vector: need int's");
wrt << '[';
int n=-1;
for (const auto& el: v) {
if (++n)
wrt << ", ";
wrt << vnam.at(el);
}
wrt << ']';
}

/// Write flat expr/obj/con parameters:
/// vector/array
template <class Writer, class Vec,
typename T = std::decay_t<
decltype(*begin(std::declval<Vec>()))> >
void WriteModelItemParameters(
Writer& wrt, const Vec& v) {
wrt << '[';
int n=-1;
for (const auto& el: v) {
if (++n)
wrt << ", ";
wrt << el;
}
wrt << ']';
}

/// Specialize WriteModelItem() for CustomFuncCon<>
template <class Writer, class A, class P, class N, class I>
inline void WriteModelItem(
Writer& wrt,
const CustomFunctionalConstraint<A,P,N,I>& cfc,
const std::vector<std::string>& vnam) {
wrt << vnam.at(cfc.GetResultVar()) << " == ";
wrt << cfc.GetTypeName();
wrt << '(';
WriteModelItem(wrt, cfc.GetArguments(), vnam);
wrt << ", ";
WriteModelItemParameters(wrt, cfc.GetParameters());
wrt << ')';
}

/// Very general template to write any flat constraint
/// with name.
template <class Writer, class Con>
inline void WriteFlatCon(Writer& wrt, const Con& c,
const std::vector<std::string>& vnam) {
wrt << c.name() << ": ";
WriteModelItem(wrt, c, vnam);
}

/// Write a CustomFunctionalConstraint<>
template <class JW, class A, class P, class N, class I>
Expand Down Expand Up @@ -347,6 +407,17 @@ class ConditionalConstraint :
}
};

/// Write ConditionalCon without name.
template <class Writer, class Con>
inline void WriteModelItem(Writer& wrt,
const ConditionalConstraint<Con>& condc,
const std::vector<std::string>& vnam) {
wrt << vnam.at(condc.GetResultVar()) << "==1 <==> ";
wrt << '(';
WriteModelItem(wrt, condc.GetArguments(), vnam);
wrt << ')';
}

/// Write a readable variable definition
template <class Writer>
void WriteVar(Writer& pr, const char* name,
Expand Down
31 changes: 30 additions & 1 deletion include/mp/flat/constr_functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ class LinearFunctionalConstraint :
}
};

/// Write LFC without name.
template <class Writer>
inline void WriteModelItem(Writer& wrt,
const LinearFunctionalConstraint& lfc,
const std::vector<std::string>& vnam) {
wrt << vnam.at(lfc.GetResultVar()) << " == ";
WriteModelItem(wrt, lfc.GetArguments(), vnam);
}

/// Write a LinFuncCon
inline void WriteJSON(JSONW jw,
Expand Down Expand Up @@ -275,6 +283,14 @@ class QuadraticFunctionalConstraint :
}
};

/// Write LFC without name.
template <class Writer>
inline void WriteModelItem(Writer& wrt,
const QuadraticFunctionalConstraint& qfc,
const std::vector<std::string>& vnam) {
wrt << vnam.at(qfc.GetResultVar()) << " == ";
WriteModelItem(wrt, qfc.GetArguments(), vnam);
}

/// Write a QuadrFuncCon
inline void WriteJSON(JSONW jw,
Expand Down Expand Up @@ -392,6 +408,20 @@ class PLConParams {
DEF_NUMERIC_FUNC_CONSTR_WITH_PRM( PLConstraint,
VarArray1, PLConParams, "r = piecewise_linear(x)");

/// Write flat expr/obj/con parameters:
/// PLConParams
template <class Writer>
void WriteModelItemParameters(
Writer& wrt, const PLConParams& plp) {
wrt << "plpoints[";
const auto& p = plp.GetPLPoints();
for (size_t i=0; i<p.x_.size(); ++i) {
if (i)
wrt << ", ";
wrt << '(' << p.x_[i] << ", " << p.y_[i] << ')';
}
wrt << ']';
}

/// Write PLConParams
inline void WriteJSON(JSONW jw,
Expand All @@ -401,7 +431,6 @@ inline void WriteJSON(JSONW jw,
jw["pl_y"] = p.y_;
}


} // namespace mp

#endif // CONSTRAINTS_FUNCTIONAL_H
38 changes: 36 additions & 2 deletions include/mp/flat/constr_general.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,18 @@ using IndicatorConstraintQuadEQ = IndicatorConstraint<QuadConEQ>;
/// Typedef indicator<QuadConGE>
using IndicatorConstraintQuadGE = IndicatorConstraint<QuadConGE>;

/// Write indicator without name.
template <class Writer, class Con>
inline void WriteModelItem(Writer& wrt, const IndicatorConstraint<Con>& ic,
const std::vector<std::string>& vnam) {
wrt << vnam.at(ic.get_binary_var())
<< "==" << ic.get_binary_value()
<< " ==> (";
WriteModelItem(wrt, ic.get_constraint(), vnam);
wrt << ')';
}

/// Write an indicator constraint
/// Export indicator constraint
template <class Con>
inline void WriteJSON(JSONW jw,
const IndicatorConstraint<Con>& ic) {
Expand Down Expand Up @@ -231,7 +241,22 @@ using SOS1Constraint = SOS_1or2_Constraint<1>;
using SOS2Constraint = SOS_1or2_Constraint<2>;


/// Write a SOS1, SOS2 constraint
/// Write SOS without name.
template <class Writer, int type>
inline void WriteModelItem(Writer& wrt, const SOS_1or2_Constraint<type>& sos,
const std::vector<std::string>& vnam) {
// Type 1/2 should be in the name.
wrt << sos.GetTypeName();
wrt << '(';
WriteModelItem(wrt, sos.get_vars(), vnam);
wrt << ", ";
WriteModelItemParameters(wrt, sos.get_weights());
auto bnds = sos.get_sum_of_vars_range();
wrt << "; [" << bnds.lb_ << ", " << bnds.ub_ << "]";
wrt << ')';
}

/// Export a SOS1, SOS2 constraint
template <int type>
inline void WriteJSON(JSONW jw, const SOS_1or2_Constraint<type>& sos) {
jw["SOS_type"] = sos.get_sos_type();
Expand Down Expand Up @@ -296,6 +321,15 @@ using ComplementarityLinear = ComplementarityConstraint<AffineExpr>;
/// Typedef ComplementarityQuadRange
using ComplementarityQuadratic = ComplementarityConstraint<QuadraticExpr>;

/// Write ComplCon without name.
template <class Writer, class Expr>
inline void WriteModelItem(Writer& wrt,
const ComplementarityConstraint<Expr>& cc,
const std::vector<std::string>& vnam) {
wrt << vnam.at(cc.GetVariable());
wrt << " complements ";
WriteModelItem(wrt, cc.GetExpression(), vnam);
}

/// Write a ComplementarityCon
template <class Expr>
Expand Down
37 changes: 26 additions & 11 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ class BasicConstraintKeeper {
virtual int GetNumberOfAddable() const = 0;

/// This adds all unbridged items to the backend (without conversion)
virtual void AddUnbridgedToBackend(BasicFlatModelAPI& be) = 0;
virtual void AddUnbridgedToBackend(
BasicFlatModelAPI& be, const std::vector<std::string>* vnames) = 0;

/// This logs the constraint group
virtual void LogConstraintGroup(BasicFlatModelAPI& be) = 0;
Expand Down Expand Up @@ -782,9 +783,11 @@ class ConstraintKeeper final
}

/// Add remaining constraints to Backend
void AddUnbridgedToBackend(BasicFlatModelAPI& be) override {
void AddUnbridgedToBackend(
BasicFlatModelAPI& be,
const std::vector<std::string>* pvnam) override {
try {
AddAllUnbridged(be);
AddAllUnbridged(be, pvnam);
} catch (const std::exception& exc) {
MP_RAISE(std::string("Adding constraint of type '") +
Constraint::GetTypeName() + "' to " +
Expand Down Expand Up @@ -923,16 +926,25 @@ class ConstraintKeeper final
GetLogger()->Append(wrt);
}
}
/// Export constraint status
void ExportConStatus(int i_con, const Container& cnt) {
/// Export constraint status.
/// This is called in the end,
/// so printing the readbale form.
void ExportConStatus(int i_con, const Container& cnt,
const std::vector<std::string>* pvnam) {
if (GetLogger()) {
fmt::MemoryWriter wrt;
{
MiniJSONWriter jw(wrt);
jw["CON_TYPE"] = GetShortTypeName();
jw["index"] = i_con;
if (*cnt.con_.name())
if (*cnt.con_.name()) {
jw["name"] = cnt.con_.name();
if (pvnam && pvnam->size()) {
fmt::MemoryWriter pr;
WriteFlatCon(pr, cnt.con_, *pvnam);
jw["printed"] = pr.c_str();
}
}
jw["depth"] = cnt.GetDepth();
jw["unused"] = (int)cnt.IsUnused();
jw["bridged"] = (int)cnt.IsBridged();
Expand Down Expand Up @@ -1030,8 +1042,10 @@ class ConstraintKeeper final


protected:
/// Add all non-converted items to ModelAPI
void AddAllUnbridged(BasicFlatModelAPI& be) {
/// Add all non-converted items to ModelAPI.
/// Export all constraints if desired.
void AddAllUnbridged(BasicFlatModelAPI& be,
const std::vector<std::string>* pvnam) {
int con_index=0;
auto con_group = GetConstraintGroup(be);
for (const auto& cont: cons_) {
Expand All @@ -1044,7 +1058,7 @@ class ConstraintKeeper final
GetConValues()(con_group).Add()
});
}
ExportConStatus(con_index, cont);
ExportConStatus(con_index, cont, pvnam);
++con_index; // increment index
}
}
Expand Down Expand Up @@ -1248,9 +1262,10 @@ class ConstraintManager {

/// Add all unbridged constraints to Backend
void AddUnbridgedConstraintsToBackend(
BasicFlatModelAPI& be) const {
BasicFlatModelAPI& be,
const std::vector<std::string>* pvnam=nullptr) const {
for (const auto& ck: con_keepers_)
ck.second.AddUnbridgedToBackend(be);
ck.second.AddUnbridgedToBackend(be, pvnam);
}

/// Log constraint groups
Expand Down
3 changes: 2 additions & 1 deletion include/mp/flat/converter_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ class FlatModel

template <class Backend>
void PushCustomConstraintsTo(Backend& backend) const {
this->AddUnbridgedConstraintsToBackend(backend);
this->AddUnbridgedConstraintsToBackend(
backend, &var_names_storage_);
this->LogConstraintGroups(backend);
}

Expand Down
15 changes: 11 additions & 4 deletions include/mp/flat/expr_algebraic.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,17 @@ class AlgebraicExpression : public Body {
double constant_term_ = 0.0;
};

/// Very general template to write any flat con/obj
template <class Writer, class Item>
void WriteModelItem(Writer& wrt, const Item& i,
const std::vector<std::string>& vnam);

/// Write algebraic expr.
template <class Writer, class Terms>
inline void WriteModelItem(Writer& wrt,
const AlgebraicExpression<Terms>& ale,
const std::vector<std::string>& vnam) {
WriteModelItem(wrt, ale.GetBody(), vnam);
wrt << (ale.constant_term()>=0 ? " + " : " - ")
<< std::fabs(ale.constant_term());
}


/// Very general template to write
/// a JSON-like representation of anything
Expand Down
4 changes: 4 additions & 0 deletions include/mp/flat/obj_std.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class QuadraticObjective : public LinearObjective {
}
};

/// Write objective
void WriteModelItem(fmt::MemoryWriter& wrt, const QuadraticObjective& obj,
const std::vector<std::string>& vnam);

/// Compute value of an objective.
template <class VarVec>
double ComputeValue(
Expand Down
Loading

0 comments on commit 145fbae

Please sign in to comment.