Skip to content

Commit

Permalink
More SCIP expressions #237
Browse files Browse the repository at this point in the history
  • Loading branch information
glebbelov committed Aug 20, 2024
1 parent 7edb0fa commit 78bed78
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 25 deletions.
3 changes: 3 additions & 0 deletions include/mp/flat/constr_keeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ class ConstraintKeeper final
void AddUnbridgedToBackend(
BasicFlatModelAPI& be,
const std::vector<std::string>* pvnam) override {
if (ExpressionAcceptanceLevel::NotAccepted
== GetChosenAcceptanceLevelEXPR()
|| !GetConverter().IfWantNLOutput())
try {
AddAllUnbridged(be, pvnam);
} catch (const std::exception& exc) {
Expand Down
68 changes: 67 additions & 1 deletion include/mp/flat/nl_expr/model_api_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,75 @@ class BasicExprModelAPI
return GetInitExpression(nll.GetResultVar());
}

/// Get the expression term of an \a NLReification.
template <int sense>
ExprType GetExpression(const NLReification<sense>& nll) {
assert( nll.GetResultVar()>=0 );
return GetInitExpression(nll.GetResultVar());
}

/// Get the variable of an \a NLReification.
template <int sense>
int GetVariable(const NLReification<sense>& nll) {
assert( nll.GetResultVar()>=0 );
return nll.GetResultVar();
}

/// GetLinSize(le)
int GetLinSize(const LinExpression& le) const
{ return le.GetFlatConstraint().GetAffineExpr().size(); }
/// GetLinCoef(le, i)
double GetLinCoef(const LinExpression& le, int i) const
{ return le.GetFlatConstraint().GetAffineExpr().coef(i); }
/// GetLinTerm(le, i)
Expr GetLinTerm(const LinExpression& le, int i)
{ return GetInitExpression(le.GetFlatConstraint().GetAffineExpr().var(i)); }
/// GetConstTerm(le)
double GetConstTerm(const LinExpression& le) const
{ return le.GetFlatConstraint().GetAffineExpr().constant_term(); }

/// GetLinSize(qe)
int GetLinSize(const QuadExpression& qe) const
{ return qe.GetFlatConstraint().GetQuadExpr().GetBody().GetLinTerms().size(); }
/// GetLinCoef(qe, i)
double GetLinCoef(const QuadExpression& qe, int i) const
{ return qe.GetFlatConstraint().GetQuadExpr().GetBody().GetLinTerms().coef(i); }
/// GetLinTerm(qe, i)
Expr GetLinTerm(const QuadExpression& qe, int i)
{ return GetInitExpression(qe.GetFlatConstraint().GetQuadExpr().GetBody().GetLinTerms().var(i)); }

/// GetQuadSize(qe)
int GetQuadSize(const QuadExpression& qe) const
{ return qe.GetFlatConstraint().GetQuadExpr().GetBody().GetQPTerms().size(); }
/// GetQuadCoef(qe, i)
double GetQuadCoef(const QuadExpression& qe, int i) const
{ return qe.GetFlatConstraint().GetQuadExpr().GetBody().GetQPTerms().coef(i); }
/// GetQuadTerm1(qe, i)
Expr GetQuadTerm1(const QuadExpression& qe, int i)
{ return GetInitExpression(qe.GetFlatConstraint().GetQuadExpr().GetBody().GetQPTerms().var1(i)); }
/// GetQuadTerm2(qe, i)
Expr GetQuadTerm2(const QuadExpression& qe, int i)
{ return GetInitExpression(qe.GetFlatConstraint().GetQuadExpr().GetBody().GetQPTerms().var2(i)); }

/// GetConstTerm(qe)
double GetConstTerm(const QuadExpression& qe) const
{ return qe.GetFlatConstraint().GetQuadExpr().constant_term(); }

/// Get argument expression [\a i]
template <class FlatExpression>
Expr GetArgExpression(const FlatExpression& fe, int i)
{ return GetInitExpression(fe.GetFlatConstraint().GetArguments().at(i)); }

/// Get expression parameter [\a i]
template <class FlatExpression>
double GetParameter(const FlatExpression& fe, int i)
{ return fe.GetFlatConstraint().GetParameters().at(i); }

////////////////////// INTERNAL ////////////////////////

/// Get InitExpression()
/// Get InitExpression().
/// Solver expression for the given implicit variable,
/// or for the given independent variable.
Expr GetInitExpression(int i_expr) {
assert(i_expr < is_expr_stored_.size());
assert(i_expr < expr_stored_.size());
Expand Down
119 changes: 113 additions & 6 deletions solvers/scipmp/scipmpmodelapi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ void ScipModelAPI::AddConstraint(const LinConGE& lc) {
}


SCIP_EXPR* ScipModelAPI::AddExpression(const AbsExpression &abse) {
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprAbs(getSCIP(), &result_expr,
GetArgExpression(abse, 0), NULL, NULL) );
return result_expr;
}


void ScipModelAPI::AddConstraint(const AbsConstraint &absc) {
SCIP_VAR* x = getPROBDATA()->vars[absc.GetArguments()[0]];
SCIP_VAR* res = getPROBDATA()->vars[absc.GetResultVar()];
Expand Down Expand Up @@ -306,16 +314,82 @@ void ScipModelAPI::AddConstraint( const NLLogical& nll ) {
SCIP_CCALL( SCIPaddCons(getSCIP(), getPROBDATA()->nlconss.back()) );
}

void ScipModelAPI::AddConstraint( const NLEquivalence& nll ) { }
void ScipModelAPI::AddConstraint( const NLImpl& nll ) { }
void ScipModelAPI::AddConstraint( const NLRimpl& nll ) { }
void ScipModelAPI::AddConstraint( const NLEquivalence& nll ) {
getPROBDATA()->nlconss.push_back(nullptr);

SCIP_CCALL( SCIPcreateConsBasicNonlinear(
getSCIP(), &getPROBDATA()->nlconss.back(), nll.GetName(),
GetExpression(nll), 0.0, 0.0) );
SCIP_CCALL( SCIPaddCons(getSCIP(), getPROBDATA()->nlconss.back()) );
SCIP_CCALL( SCIPaddLinearVarNonlinear(
getSCIP(), getPROBDATA()->nlconss.back(),
getPROBDATA()->vars[ GetVariable(nll) ], -1.0) );
}
void ScipModelAPI::AddConstraint( const NLImpl& nll ) {
getPROBDATA()->nlconss.push_back(nullptr);

SCIP_CCALL( SCIPcreateConsBasicNonlinear(
getSCIP(), &getPROBDATA()->nlconss.back(), nll.GetName(),
GetExpression(nll), 0.0, Infinity()) );
SCIP_CCALL( SCIPaddCons(getSCIP(), getPROBDATA()->nlconss.back()) );
SCIP_CCALL( SCIPaddLinearVarNonlinear(
getSCIP(), getPROBDATA()->nlconss.back(),
getPROBDATA()->vars[ GetVariable(nll) ], -1.0) );
}
void ScipModelAPI::AddConstraint( const NLRimpl& nll ) {
getPROBDATA()->nlconss.push_back(nullptr);

SCIP_CCALL( SCIPcreateConsBasicNonlinear(
getSCIP(), &getPROBDATA()->nlconss.back(), nll.GetName(),
GetExpression(nll), MinusInfinity(), 0.0) );
SCIP_CCALL( SCIPaddCons(getSCIP(), getPROBDATA()->nlconss.back()) );
SCIP_CCALL( SCIPaddLinearVarNonlinear(
getSCIP(), getPROBDATA()->nlconss.back(),
getPROBDATA()->vars[ GetVariable(nll) ], -1.0) );
}

SCIP_EXPR* ScipModelAPI::AddExpression(const LinExpression &le) {
return {};
std::vector<SCIP_EXPR*> terms(GetLinSize(le));
std::vector<double> coefs(GetLinSize(le));

for (size_t i=0; i<terms.size(); ++i) {
terms[i] = GetLinTerm(le, i);
coefs[i] = GetLinCoef(le, i);
}
SCIP_EXPR* sumexpr;

SCIP_CCALL( SCIPcreateExprSum(getSCIP(), &sumexpr,
terms.size(), terms.data(), coefs.data(),
GetConstTerm(le), NULL, NULL) );
return sumexpr;
}

SCIP_EXPR* ScipModelAPI::AddExpression(const QuadExpression &qe) {
return {};
std::vector<SCIP_EXPR*> terms(GetLinSize(qe) + GetQuadSize(qe));
std::vector<double> coefs(GetLinSize(qe) + GetQuadSize(qe));

for (int i=0; i<GetLinSize(qe); ++i) {
terms[i] = GetLinTerm(qe, i);
coefs[i] = GetLinCoef(qe, i);
}
for (int i=0; i<GetQuadSize(qe); ++i) {
int i_quad = i + GetLinSize(qe);
SCIP_EXPR* mul_terms[] =
{ GetQuadTerm1(qe, i), GetQuadTerm2(qe, i) };
SCIP_CCALL( SCIPcreateExprProduct(getSCIP(), &terms[i_quad],
2, mul_terms, GetQuadCoef(qe, i), NULL, NULL) );
coefs[i_quad] = 1.0;
}
SCIP_EXPR* sumexpr;

SCIP_CCALL( SCIPcreateExprSum(getSCIP(), &sumexpr,
terms.size(), terms.data(), coefs.data(),
GetConstTerm(qe), NULL, NULL) );
for (int i=0; i<GetQuadSize(qe); ++i) {
int i_quad = i + GetLinSize(qe);
SCIP_CCALL( SCIPreleaseExpr(getSCIP(), &terms[i_quad]) );
}
return sumexpr;
}


Expand Down Expand Up @@ -383,7 +457,10 @@ void ScipModelAPI::AddConstraint(const SOS2Constraint& sos) {
}

SCIP_EXPR* ScipModelAPI::AddExpression(const ExpExpression &ee) {
return {};
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprExp(getSCIP(), &result_expr,
GetArgExpression(ee, 0), NULL, NULL) );
return result_expr;
}

void ScipModelAPI::AddConstraint(const ExpConstraint &cc) {
Expand Down Expand Up @@ -414,6 +491,13 @@ void ScipModelAPI::AddConstraint(const ExpConstraint &cc) {
SCIP_CCALL( SCIPreleaseExpr(getSCIP(), &xexpr) );
}

SCIP_EXPR* ScipModelAPI::AddExpression(const LogExpression &ee) {
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprLog(getSCIP(), &result_expr,
GetArgExpression(ee, 0), NULL, NULL) );
return result_expr;
}

void ScipModelAPI::AddConstraint(const LogConstraint &cc) {
SCIP_VAR* x = getPROBDATA()->vars[cc.GetArguments()[0]];
SCIP_VAR* res = getPROBDATA()->vars[cc.GetResultVar()];
Expand Down Expand Up @@ -442,6 +526,15 @@ void ScipModelAPI::AddConstraint(const LogConstraint &cc) {
SCIP_CCALL( SCIPreleaseExpr(getSCIP(), &xexpr) );
}

SCIP_EXPR* ScipModelAPI::AddExpression(const PowExpression &ee) {
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprPow(getSCIP(), &result_expr,
GetArgExpression(ee, 0),
GetParameter(ee, 0),
NULL, NULL) );
return result_expr;
}

void ScipModelAPI::AddConstraint(const PowConstraint &cc) {
SCIP_VAR* x = getPROBDATA()->vars[cc.GetArguments()[0]];
SCIP_VAR* res = getPROBDATA()->vars[cc.GetResultVar()];
Expand Down Expand Up @@ -470,6 +563,13 @@ void ScipModelAPI::AddConstraint(const PowConstraint &cc) {
SCIP_CCALL( SCIPreleaseExpr(getSCIP(), &xexpr) );
}

SCIP_EXPR* ScipModelAPI::AddExpression(const SinExpression &ee) {
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprSin(getSCIP(), &result_expr,
GetArgExpression(ee, 0), NULL, NULL) );
return result_expr;
}

void ScipModelAPI::AddConstraint(const SinConstraint &cc) {
SCIP_VAR* x = getPROBDATA()->vars[cc.GetArguments()[0]];
SCIP_VAR* res = getPROBDATA()->vars[cc.GetResultVar()];
Expand Down Expand Up @@ -498,6 +598,13 @@ void ScipModelAPI::AddConstraint(const SinConstraint &cc) {
SCIP_CCALL( SCIPreleaseExpr(getSCIP(), &xexpr) );
}

SCIP_EXPR* ScipModelAPI::AddExpression(const CosExpression &ee) {
SCIP_EXPR* result_expr;
SCIP_CCALL( SCIPcreateExprCos(getSCIP(), &result_expr,
GetArgExpression(ee, 0), NULL, NULL) );
return result_expr;
}

void ScipModelAPI::AddConstraint(const CosConstraint &cc) {
SCIP_VAR* x = getPROBDATA()->vars[cc.GetArguments()[0]];
SCIP_VAR* res = getPROBDATA()->vars[cc.GetResultVar()];
Expand Down
67 changes: 49 additions & 18 deletions solvers/scipmp/scipmpmodelapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,42 @@ class ScipModelAPI :
ACCEPT_EXPRESSION(QuadExpression, Recommended);
SCIP_EXPR* AddExpression(const QuadExpression& le);

/// Linear indicator constraints can be used as
/// auxiliary constraints for logical conditions.
/// If not handled, the compared expressions need
/// deducible finite bounds for a big-M redefinition.
/// Each expression can be accpeted as a proper expression,
/// or a flat constraint var == expr (with var arguments).
///
/// For each expression,
/// say ACCEPT_EXPRESSION(Recommended)
/// and/or ACCEPT_EXPRESSION(AcceptedButNotRecommended).
/// This can be user-configured via options 'acc:exp' etc.
///
/// Use accessor: GetArgExpression(ee, 0)
/// - don't ExpExpression's methods.
///
/// Similar for other expression types.
ACCEPT_EXPRESSION(AbsExpression, Recommended)
SCIP_EXPR* AddExpression(const AbsExpression& absc);

/// For each flat constraint type,
/// say ACCEPT_CONSTRAINT(Recommended)
/// and/or ACCEPT_CONSTRAINT(AcceptedButNotRecommended).
/// This can be user-configured via options 'acc:exp' etc.
ACCEPT_CONSTRAINT(AbsConstraint, Recommended, CG_General)
void AddConstraint(const AbsConstraint& absc);

// SCIP 9 has AND/OR as constraints only:
// ACCEPT_EXPRESSION(AndExpression, AcceptedButNotRecommended)
// void AddExpression(const AndExpression& cc);
// ACCEPT_EXPRESSION(OrExpression, Recommended)
// void AddExpression(const OrExpression& dc);
ACCEPT_CONSTRAINT(AndConstraint, AcceptedButNotRecommended, CG_General)
void AddConstraint(const AndConstraint& cc);
ACCEPT_CONSTRAINT(OrConstraint, Recommended, CG_General)
void AddConstraint(const OrConstraint& dc);

/// Linear indicator constraints can be used as
/// auxiliary constraints for logical conditions.
/// If not handled, the compared expressions need
/// deducible finite bounds for a big-M redefinition.
ACCEPT_CONSTRAINT(IndicatorConstraintLinLE, AcceptedButNotRecommended, CG_General)
void AddConstraint(const IndicatorConstraintLinLE& mc);
ACCEPT_CONSTRAINT(IndicatorConstraintLinEQ, AcceptedButNotRecommended, CG_General)
Expand All @@ -213,32 +239,37 @@ class ScipModelAPI :
ACCEPT_CONSTRAINT(SOS2Constraint, AcceptedButNotRecommended, CG_SOS)
void AddConstraint(const SOS2Constraint& cc);

/// SCIP nonlinear generals.

/// Each expression can be accpeted as a proper expression,
/// or a flat constraint var == expr (with var arguments).
/// SCIP nonlinear general constraints and expressions.

/// For each expression,
/// say ACCEPT_EXPRESSION(Recommended)
/// and/or ACCEPT_EXPRESSION(AcceptedButNotRecommended).
/// This can be user-configured via options 'acc:exp' etc.
ACCEPT_EXPRESSION(ExpExpression, Recommended)
SCIP_EXPR* AddExpression(const ExpExpression& );

/// For each flat constraint type,
/// say ACCEPT_CONSTRAINT(Recommended)
/// and/or ACCEPT_CONSTRAINT(AcceptedButNotRecommended).
/// This can be user-configured via options 'acc:exp' etc.
ACCEPT_CONSTRAINT(ExpConstraint, Recommended, CG_General)
void AddConstraint(const ExpConstraint& cc);

ACCEPT_EXPRESSION(LogExpression, Recommended)
SCIP_EXPR* AddExpression(const LogExpression& );
ACCEPT_CONSTRAINT(LogConstraint, Recommended, CG_General)
void AddConstraint(const LogConstraint& cc);

/// Use accessor: GetParameter(pe, 0)
/// - don't use PowExpression's methods.
ACCEPT_EXPRESSION(PowExpression, Recommended)
SCIP_EXPR* AddExpression(const PowExpression& );
ACCEPT_CONSTRAINT(PowConstraint, Recommended, CG_General)
void AddConstraint(const PowConstraint& cc);

ACCEPT_EXPRESSION(SinExpression, Recommended)
SCIP_EXPR* AddExpression(const SinExpression& );
ACCEPT_CONSTRAINT(SinConstraint, Recommended, CG_General)
void AddConstraint(const SinConstraint& cc);
ACCEPT_CONSTRAINT(CosConstraint, AcceptedButNotRecommended, CG_General) //pretty slow

ACCEPT_EXPRESSION(CosExpression, Recommended)
SCIP_EXPR* AddExpression(const CosExpression& );
ACCEPT_CONSTRAINT(CosConstraint, Recommended, CG_General) //pretty slow in SCIP 8
void AddConstraint(const CosConstraint& cc);

// TODO Div; PowVarExponent;
// CondLin... - not really, reader_nl.cpp only handles bool args
};

} // namespace mp
Expand Down

0 comments on commit 78bed78

Please sign in to comment.